windows-nt/Source/XPSP1/NT/net/nwlink/ipxroute/ipxroute.c
2020-09-26 16:20:57 +08:00

2004 lines
53 KiB
C

/****************************************************************************
* (c) Copyright 1990, 1993 Micro Computer Systems, Inc. All rights reserved.
*****************************************************************************
*
* Title: IPX/SPX Compatible Source Routing Daemon for Windows NT
*
* Module: ipx/route/ipxroute.c
*
* Version: 1.00.00
*
* Date: 04-08-93
*
* Author: Brian Walker
*
*****************************************************************************
*
* Change Log:
*
* Date DevSFC Comment
* -------- ------ -------------------------------------------------------
* 02-14-95 RamC Added command line options to support displaying
* Router Table, Router Statistics and SAP information.
* Basically a merge of ipxroute and Stefan's rttest.
* 03-12-98 Pmay Added translation of if name to version int the
connections folder.
*****************************************************************************
*
* Functional Description:
*
*
****************************************************************************/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windef.h>
#include <winbase.h>
#include <winnls.h>
#include <winuser.h>
#include <stdio.h>
#include <stdlib.h>
#include <ntstapi.h>
#include <nwsap.h>
#include <stropts.h>
#include <mprapi.h>
#include "errno.h"
#include "tdi.h"
#include "isnkrnl.h"
#include "ipxrtmsg.h"
#include "driver.h"
#include "utils.h"
typedef struct _IPX_ROUTE_ENTRY {
UCHAR Network[4];
USHORT NicId;
UCHAR NextRouter[6];
PVOID NdisBindingContext;
USHORT Flags;
USHORT Timer;
UINT Segment;
USHORT TickCount;
USHORT HopCount;
PVOID AlternateRoute[2];
PVOID NicLinkage[2];
struct {
PVOID Linkage[2];
ULONG Reserved[1];
} PRIVATE;
} IPX_ROUTE_ENTRY, * PIPX_ROUTE_ENTRY;
IPX_ROUTE_ENTRY rte;
/** Global Variables **/
int sr_def = 0;
int sr_bcast = 0;
int sr_multi = 0;
int boardnum = 0;
int clear = 0;
int config = 0;
int showtable = 0;
int showservers = 0;
int showstats = 0;
int clearstats = 0;
int ripout = 0;
int resolveguid = 0;
int resolvename = 0;
int servertype;
unsigned long netnum;
char nodeaddr[6]; /* Node address to remove */
HANDLE nwlinkfd;
HANDLE isnipxfd;
HANDLE isnripfd;
char ebuffer[128];
char nwlinkname[] = "\\Device\\Streams\\NWLinkIpx";
wchar_t isnipxname[] = L"\\Device\\NwlnkIpx";
wchar_t isnripname[] = L"\\Device\\Ipxroute";
char pgmname[] = "IPXROUTE";
#define SHOW_ALL_SERVERS 0XFFFF
/** **/
#define INVALID_HANDLE (HANDLE)(-1)
/** Structure to send REMOVE with **/
typedef struct rterem {
int rterem_bnum; /* Board number */
char rterem_node[6]; /* Node to remove */
} rterem;
typedef int (__cdecl * PQSORT_COMPARE)(const void * p0, const void * p1);
/** Internal Function Prototypes **/
extern void print_table(int);
extern void usage(void);
extern void print_version(void);
extern char *print_type(int);
extern int my_strncmp(char *, char *, int);
extern int get_board_num(char *, int *);
extern int get_node_num(char *, char *);
extern int get_server_type(char *, int *);
extern unsigned char get_hex_byte(char *);
extern int get_driver_parms(void);
extern int set_driver_parms(void);
extern int do_strioctl(HANDLE, int, char *, int, int);
extern void remove_address(char *);
extern void clear_table(void);
extern void print_config(void);
extern unsigned long get_emsg(int);
int do_isnipxioctl(HANDLE fd, int cmd, char *datap, int dlen);
unsigned long put_msg(BOOLEAN error, unsigned long MsgNum, ... );
char *load_msg( unsigned long MsgNum, ... );
extern void show_router_table(PHANDLE, PIO_STATUS_BLOCK);
extern void show_stats(HANDLE, PIO_STATUS_BLOCK);
extern void clear_stats(HANDLE, PIO_STATUS_BLOCK);
extern void show_servers(int);
extern void show_ripout(unsigned long);
extern void resolve_guid(char *);
extern void resolve_name(char *);
extern int __cdecl CompareServerNames( void * p0, void * p1);
extern int __cdecl CompareNetNumber( void * p0, void * p1);
/*page*************************************************************
m a i n
This is the main routine that gets executed when a NET START
happens.
Arguments - None
Returns - Nothing
********************************************************************/
void __cdecl main(int argc, char **argv)
{
char *p;
int todo;
int remove_flag;
UNICODE_STRING FileString;
OBJECT_ATTRIBUTES ObjectAttributes, RouterObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock, RouterIoStatusBlock;
NTSTATUS Status;
/** **/
print_version();
/** Open the nwlink driver **/
nwlinkfd = s_open(nwlinkname, 0, 0);
/** Open the isnipx driver **/
RtlInitUnicodeString (&FileString, isnipxname);
InitializeObjectAttributes(
&ObjectAttributes,
&FileString,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = NtOpenFile(
&isnipxfd,
SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
&ObjectAttributes,
&IoStatusBlock,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_SYNCHRONOUS_IO_ALERT);
if (!NT_SUCCESS(Status)) {
isnipxfd = INVALID_HANDLE;
put_msg (TRUE, MSG_OPEN_FAILED, "\\Device\\NwlnkIpx");
}
/** Open the isnrip driver **/
RtlInitUnicodeString (&FileString, isnripname);
InitializeObjectAttributes(
&RouterObjectAttributes,
&FileString,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = NtOpenFile(
&isnripfd,
SYNCHRONIZE | GENERIC_READ,
&RouterObjectAttributes,
&RouterIoStatusBlock,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_SYNCHRONOUS_IO_NONALERT);
if (!NT_SUCCESS(Status)) {
isnripfd = INVALID_HANDLE;
// don't display any error message, but display the
// message that the IPX router is not started when
// the user actually tries to look at the router.
}
if ((nwlinkfd == INVALID_HANDLE) &&
(isnipxfd == INVALID_HANDLE) &&
(isnripfd == INVALID_HANDLE))
{
exit(1);
}
/** Go thru the command line and set it up **/
argc--;
argv++;
/** Parse the command line **/
todo = 0;
remove_flag = 0;
while (argc--) {
/** Uppercase the arg **/
p = *argv;
_strupr(p);
/** Parse the argument **/
//if (!strcmp(p, "CLEAR")) {
// todo = 1;
// clear = 1;
// }
/*else*/ if (!strcmp(p, "DEF")) {
todo = 1;
sr_def = 1;
}
else if (!strcmp(p, "GBR")) {
todo = 1;
sr_bcast = 1;
}
else if (!strcmp(p, "MBR")) {
todo = 1;
sr_multi = 1;
}
else if (!strcmp(p, "CONFIG")) {
todo = 1;
config = 1;
}
else if (!my_strncmp(p, "BOARD=", 6))
get_board_num(p + 6, &boardnum);
else if (!my_strncmp(p, "REMOVE=", 7)) {
remove_flag = 1;
get_node_num(p + 7, nodeaddr);
}
//else if (!strcmp(p, "TABLE")) {
// todo = 1;
// showtable = 1;
// }
else if (!strcmp(p, "SERVERS")) {
todo = 1;
showservers = 1;
/** default is to show all server types **/
servertype = SHOW_ALL_SERVERS;
argv++;
if(argc--) {
p = *argv;
_strupr(p);
if (!my_strncmp(p, "/TYPE=", 6)) {
get_server_type(p + 6, &servertype);
}
else
usage();
}
/** no more arguments - break out of while lop **/
else
break;
}
else if (!strcmp(p, "RIPOUT")) {
todo = 1;
ripout = 1;
/** default look for local network **/
netnum = 0L;
argv++;
if(argc--) {
p = *argv;
netnum = strtoul (p, NULL, 16);
if (netnum == 0)
usage();
}
/** no more arguments - break out of while lop **/
else
break;
}
else if (!strcmp(p, "RESOLVE")) {
argv++;
if(argc--) {
p = *argv;
if (!strcmp(p, "guid")) {
todo = 1;
resolveguid = 1;
argc--;
argv++;
p = *argv;
}
else if (!strcmp(p, "name")) {
todo = 1;
resolvename = 1;
argc--;
argv++;
p = *argv;
}
else
usage();
}
/** no more arguments - break out of while lop **/
else
break;
}
//else if (!strcmp(p, "STATS")) {
// todo = 1;
// /** default is to show the router statistics **/
// showstats = 1;
// argv++;
// if(argc--) {
// p = *argv;
// _strupr(p);
// if (!strcmp(p, "/CLEAR")) {
// clearstats = 1;
// showstats = 0;
// }
// else if (!strcmp(p, "/SHOW")) {
// showstats = 1;
// }
// else
// usage;
// }
// /** no more arguments - break out of while lop **/
// else
// break;
// }
else
usage();
/** Goto the next entry **/
argv++;
}
/** Go update the driver **/
#if 0
printf("todo = %d\n", todo);
printf("remove_flag= %d\n", remove_flag);
printf("Clear flag = %d\n", clear);
printf("Config flag = %d\n", config);
printf("SR_DEF = %d\n", sr_def);
printf("SR_BCAST = %d\n", sr_bcast);
printf("SR_MULTI = %d\n", sr_multi);
printf("Board = %d\n", boardnum);
printf("Node = %02x:%02x:%02x:%02x:%02x:%02x\n",
(unsigned char)nodeaddr[0],
(unsigned char)nodeaddr[1],
(unsigned char)nodeaddr[2],
(unsigned char)nodeaddr[3],
(unsigned char)nodeaddr[4],
(unsigned char)nodeaddr[5]);
#endif
/** If we have a remove - go remove it and leave **/
if (remove_flag)
remove_address(nodeaddr); /* Does not return */
/** If clear - go clear the source routing table **/
if (clear)
clear_table(); /* Does not return */
/** If config - print out config **/
if (config)
print_config(); /* Does not return */
/** If showtable - print out routing table **/
if (showtable)
show_router_table(&isnripfd, &RouterIoStatusBlock); /* Does not return */
/** If showservers - print out selected servers list **/
if (showservers)
show_servers(servertype); /* Does not return */
/** If ripout - rip out and print results **/
if (ripout)
show_ripout(netnum); /* Does not return */
/** If resolveguid - resolve a guid name **/
if (resolveguid)
resolve_guid(p); /* Does not return */
/** If resolvename - resolve a friendly name **/
if (resolvename)
resolve_name(p); /* Does not return */
/** If showstats - print out statistics **/
if (showstats)
show_stats(&isnripfd, &RouterIoStatusBlock); /* Does not return */
/** If clearstats - go clear statistics **/
if (clearstats)
clear_stats(&isnripfd, &RouterIoStatusBlock); /* Does not return */
/** If there is nothing to do - just print out everything **/
if (!todo) {
/** Get the driver parms **/
if (get_driver_parms()) {
if (isnipxfd != INVALID_HANDLE) NtClose(isnipxfd);
if (nwlinkfd != INVALID_HANDLE) NtClose(nwlinkfd);
if (isnripfd != INVALID_HANDLE) NtClose(isnripfd);
exit(1);
}
/** Print out the table (Never comes back) **/
print_table(1);
}
/** Go set the parameters **/
set_driver_parms();
/** Print the table out **/
print_table(0);
/** All Done **/
if (isnipxfd != INVALID_HANDLE) NtClose(isnipxfd);
if (nwlinkfd != INVALID_HANDLE) NtClose(nwlinkfd);
if (isnripfd != INVALID_HANDLE) NtClose(isnripfd);
exit(0);
}
/*page*************************************************************
p r i n t _ t a b l e
Print out the status of the source routing.
Arguments - flag = 0 - Do NOT print the table
1 - Do print the table (Never returns)
Returns - Nothing
********************************************************************/
void print_table(int flag)
{
/** Print the information **/
char * ptype;
printf("\n");
ptype = print_type(sr_def);
put_msg (FALSE, MSG_DEFAULT_NODE, ptype);
LocalFree (ptype);
printf("\n");
ptype = print_type(sr_bcast);
put_msg (FALSE, MSG_BROADCAST, ptype);
LocalFree (ptype);
printf("\n");
ptype = print_type(sr_multi);
put_msg (FALSE, MSG_MULTICAST, ptype);
LocalFree (ptype);
printf("\n");
if (!flag)
return;
#if 0
printf("\n");
printf(" Node Address Source Route\n");
printf("\n");
#endif
/** All Done **/
if (isnipxfd != INVALID_HANDLE) NtClose(isnipxfd);
if (nwlinkfd != INVALID_HANDLE) NtClose(nwlinkfd);
if (isnripfd != INVALID_HANDLE) NtClose(isnripfd);
exit(0);
}
/*page*************************************************************
u s a g e
Print the usage message.
Arguments - None
Returns - Nothing
********************************************************************/
void usage(void)
{
put_msg( FALSE, MSG_USAGE, pgmname );
/** All Done **/
if (isnipxfd != INVALID_HANDLE) NtClose(isnipxfd);
if (nwlinkfd != INVALID_HANDLE) NtClose(nwlinkfd);
if (isnripfd != INVALID_HANDLE) NtClose(isnripfd);
exit(0);
}
/*page*************************************************************
p r i n t _ v e r s i o n
Print the version number
Arguments - None
Returns - Nothing
********************************************************************/
void print_version(void)
{
printf("\n");
put_msg (FALSE, MSG_VERSION);
return;
}
/*page*************************************************************
p r i n t _ t y p e
Returns the broadcast type given in a string, the caller
must free the string.
Arguments - 0 = SINGLE ROUTE
Else = ALL ROUTES
Returns - Nothing
********************************************************************/
char *print_type(int flag)
{
if (flag)
return load_msg (MSG_ALL_ROUTE);
else
return load_msg (MSG_SINGLE_ROUTE);
}
/*page*************************************************************
m y _ s t r n c m p
Given a string (p), see if the first len chars are the same
as those of the 2nd string (s).
Arguments - p = Ptr to first string
s = Ptr to 2nd string
len = Length to check
Returns - 0 = Matched
Else = Not matched
********************************************************************/
int my_strncmp(char *p, char *s, int len)
{
/** **/
while (len--) {
if (*p++ != *s++)
return 1;
}
/** They matched **/
return 0;
}
/*page*************************************************************
g e t _ b o a r d _ n u m
Get the decimal number from the command line
Arguments - p = Ptr to the ASCII number
nump = Store the number here
Returns - 0 = Got the number OK
Else = Bad number
********************************************************************/
int get_board_num(char *p, int *nump)
{
*nump = atoi(p);
return 0;
}
/*page*************************************************************
g e t _ n o d e _ n u m
Get a node address from the command line
Arguments - p = Ptr to the ASCII number
nodep = Store the node number here
Returns - 0 = Got the number OK
Else = Bad number
********************************************************************/
int get_node_num(char *p, char *nodep)
{
int i;
unsigned char c1;
unsigned char c2;
/** **/
if (strlen(p) != 12) {
put_msg (TRUE, MSG_INVALID_REMOVE);
exit(1);
}
/** Get the number **/
for (i = 0 ; i < 6 ; i++) {
/** Get the next 2 digits **/
c1 = get_hex_byte(p++);
c2 = get_hex_byte(p++);
/** If we got a bad number - return error **/
if ((c1 == 0xFF) || (c2 == 0xFF)) {
put_msg (TRUE, MSG_INVALID_REMOVE);
exit(1);
}
/** Set the next byte **/
*nodep++ = (c1 << 4) + c2;
}
/** Return OK **/
return 0;
}
/*page*************************************************************
g e t _ s e r v e r _ t y p e
Get the decimal number from the command line
Arguments - p = Ptr to the ASCII number
nump = Store the number here
Returns - 0 = Got the number OK
Else = Bad number
********************************************************************/
int get_server_type(char *p, int *nump)
{
*nump = atoi(p);
return 0;
}
/*page*************************************************************
g e t _ h e x _ b y t e
Take 1 ascii hex chars and convert to a hex byte
Arguments - p = Ptr to the ASCII number
Returns - The number
(0xFF = Error)
********************************************************************/
unsigned char get_hex_byte(char *p)
{
unsigned char c;
/** Get the char **/
c = *(unsigned char *)p;
/** If 0-9 handle it **/
if ((c >= '0') && (c <= '9')) {
c -= '0';
return c;
}
/** If A-F handle it **/
if ((c >= 'A') && (c <= 'F')) {
c -= ('A' - 10);
return c;
}
/** This is a bad number **/
return 0xFF;
}
/*page***************************************************************
g e t _ d r i v e r _ p a r m s
Get the parameters from the driver
Arguments - None
Returns - 0 = OK
else = Error
********************************************************************/
int get_driver_parms()
{
int rc;
int buffer[4];
/** Set the board number **/
buffer[0] = boardnum;
sr_def = 0;
sr_bcast = 0;
sr_multi = 0;
/** Get the parms **/
if (nwlinkfd != INVALID_HANDLE) {
rc = do_strioctl(nwlinkfd, MIPX_SRGETPARMS, (char *)buffer, 4*sizeof(int), 0);
if (rc) {
/** Get the error code **/
rc = GetLastError();
put_msg (TRUE, MSG_BAD_PARAMETERS, "nwlink");
put_msg (TRUE, get_emsg(rc));
/** Return the error **/
return rc;
}
}
if (isnipxfd != INVALID_HANDLE) {
rc = do_isnipxioctl(isnipxfd, MIPX_SRGETPARMS, (char *)buffer, 4*sizeof(int));
if (rc) {
put_msg (TRUE, MSG_BAD_PARAMETERS, "nwlnkipx");
put_msg (TRUE, get_emsg(rc));
/** Return the error **/
return rc;
}
}
/** Get the variables **/
sr_def = buffer[1];
sr_bcast = buffer[2];
sr_multi = buffer[3];
/** Return OK **/
return 0;
}
/*page***************************************************************
s e t _ d r i v e r _ p a r m s
Set the parameters for the driver
Arguments - None
Returns - 0 = OK
else = Error
********************************************************************/
int set_driver_parms()
{
int rc;
int buffer[2];
/** Set the DEFAULT parm **/
buffer[0] = boardnum;
buffer[1] = sr_def;
if (nwlinkfd != INVALID_HANDLE) {
rc = do_strioctl(nwlinkfd, MIPX_SRDEF, (char *)buffer, 2 * sizeof(int), 0);
if (rc) {
rc = GetLastError();
put_msg (TRUE, MSG_SET_DEFAULT_ERROR, "nwlink");
put_msg (TRUE, get_emsg(rc));
return rc;
}
}
if (isnipxfd != INVALID_HANDLE) {
rc = do_isnipxioctl(isnipxfd, MIPX_SRDEF, (char *)buffer, 2 * sizeof(int));
if (rc) {
put_msg (TRUE, MSG_SET_DEFAULT_ERROR, "nwlnkipx");
put_msg (TRUE, get_emsg(rc));
return rc;
}
}
/** Set the BROADCAST parm **/
buffer[0] = boardnum;
buffer[1] = sr_bcast;
if (nwlinkfd != INVALID_HANDLE) {
rc = do_strioctl(nwlinkfd, MIPX_SRBCAST, (char *)buffer, 2 * sizeof(int), 0);
if (rc) {
rc = GetLastError();
put_msg (TRUE, MSG_SET_BROADCAST_ERROR, "nwlink");
put_msg (TRUE, get_emsg(rc));
return rc;
}
}
if (isnipxfd != INVALID_HANDLE) {
rc = do_isnipxioctl(isnipxfd, MIPX_SRBCAST, (char *)buffer, 2 * sizeof(int));
if (rc) {
put_msg (TRUE, MSG_SET_BROADCAST_ERROR, "nwlnkipx");
put_msg (TRUE, get_emsg(rc));
return rc;
}
}
/** Set the MULTICAST parm **/
buffer[0] = boardnum;
buffer[1] = sr_multi;
if (nwlinkfd != INVALID_HANDLE) {
rc = do_strioctl(nwlinkfd, MIPX_SRMULTI, (char *)buffer, 2 * sizeof(int), 0);
if (rc) {
rc = GetLastError();
put_msg (TRUE, MSG_SET_MULTICAST_ERROR, "nwlink");
put_msg (TRUE, get_emsg(rc));
return rc;
}
}
if (isnipxfd != INVALID_HANDLE) {
rc = do_isnipxioctl(isnipxfd, MIPX_SRMULTI, (char *)buffer, 2 * sizeof(int));
if (rc) {
put_msg (TRUE, MSG_SET_MULTICAST_ERROR, "nwlnkipx");
put_msg (TRUE, get_emsg(rc));
return rc;
}
}
/** Return OK **/
return 0;
}
/*page***************************************************************
d o _ s t r i o c t l
Do a stream ioctl
Arguments - fd = Handle to put on
cmd = Command to send
datap = Ptr to ctrl buffer
dlen = Ptr to len of data buffer
timout = Timeout value
Returns - 0 = OK
else = Error
********************************************************************/
int do_strioctl(HANDLE fd, int cmd, char *datap, int dlen, int timout)
{
int rc;
struct strioctl io;
/** Fill out the structure **/
io.ic_cmd = cmd;
io.ic_dp = datap;
io.ic_len = dlen;
io.ic_timout = timout;
/** Issue the ioctl **/
rc = s_ioctl(fd, I_STR, &io);
/** All Done **/
return rc;
}
/*page***************************************************************
r e m o v e _ a d d r e s s
Remove an address from the source routing table.
Arguments - nodep = Ptr to node address to remove
Returns - Does not return
********************************************************************/
void remove_address(char *nodep)
{
int rc;
int len;
rterem buf;
/** Build the area to send down to the driver **/
buf.rterem_bnum = boardnum;
memcpy(buf.rterem_node, nodep, 6);
len = sizeof(int) + 6;
/** Send the ioctl to remove the address **/
if (nwlinkfd != INVALID_HANDLE) {
rc = do_strioctl(nwlinkfd, MIPX_SRREMOVE, (char *)&buf, len, 0);
if (rc) {
rc = GetLastError();
put_msg (TRUE, MSG_REMOVE_ADDRESS_ERROR, "nwlink");
put_msg (TRUE, get_emsg(rc));
}
}
if (isnipxfd != INVALID_HANDLE) {
rc = do_isnipxioctl(isnipxfd, MIPX_SRREMOVE, (char *)&buf, len);
if (rc) {
put_msg (TRUE, MSG_REMOVE_ADDRESS_ERROR, "nwlnkipx");
if (rc == EINVAL) {
put_msg (TRUE, MSG_ADDRESS_NOT_FOUND);
} else {
put_msg (TRUE, get_emsg(rc));
}
}
}
/** Close up and exit **/
if (isnipxfd != INVALID_HANDLE) NtClose(isnipxfd);
if (nwlinkfd != INVALID_HANDLE) NtClose(nwlinkfd);
if (isnripfd != INVALID_HANDLE) NtClose(isnripfd);
exit(0);
}
/*page***************************************************************
c l e a r _ t a b l e
Clear out the routing table
Arguments - None
Returns - Does not return
********************************************************************/
void clear_table(void)
{
int rc;
/** Send the ioctl to clear the table **/
if (nwlinkfd != INVALID_HANDLE) {
rc = do_strioctl(nwlinkfd, MIPX_SRCLEAR, (char *)&boardnum, sizeof(int), 0);
if (rc) {
rc= GetLastError();
put_msg (TRUE, MSG_CLEAR_TABLE_ERROR, "nwlink");
put_msg (TRUE, get_emsg(rc));
}
}
if (isnipxfd != INVALID_HANDLE) {
rc = do_isnipxioctl(isnipxfd, MIPX_SRCLEAR, (char *)&boardnum, sizeof(int));
if (rc) {
put_msg (TRUE, MSG_CLEAR_TABLE_ERROR, "nwlnkipx");
put_msg (TRUE, get_emsg(rc));
}
}
/** Close up and exit **/
if (isnipxfd != INVALID_HANDLE) NtClose(isnipxfd);
if (nwlinkfd != INVALID_HANDLE) NtClose(nwlinkfd);
if (isnripfd != INVALID_HANDLE) NtClose(isnripfd);
exit(0);
}
/*
typedef struct _ISN_ACTION_GET_DETAILS {
USHORT NicId; // passed by caller
BOOLEAN BindingSet; // returns TRUE if in set
UCHAR Type; // 1 = lan, 2 = up wan, 3 = down wan
ULONG FrameType; // returns 0 through 3
ULONG NetworkNumber; // returns virtual net if NicId is 0
UCHAR Node[6]; // adapter's MAC address.
WCHAR AdapterName[64]; // terminated with Unicode NULL
} ISN_ACTION_GET_DETAILS, *PISN_ACTION_GET_DETAILS;
*/
#define REORDER_ULONG(_Ulong) \
((((_Ulong) & 0xff000000) >> 24) | \
(((_Ulong) & 0x00ff0000) >> 8) | \
(((_Ulong) & 0x0000ff00) << 8) | \
(((_Ulong) & 0x000000ff) << 24))
void show_ripout(unsigned long netnum) {
int rc;
ISN_ACTION_GET_LOCAL_TARGET Target;
if (isnipxfd != INVALID_HANDLE) {
ZeroMemory (&Target, sizeof (Target));
Target.IpxAddress.NetworkAddress = REORDER_ULONG(netnum);
rc = do_isnipxioctl(isnipxfd, MIPX_LOCALTARGET, (char *)&Target, sizeof(Target));
if (rc)
put_msg (TRUE, MSG_RIPOUT_NOTFOUND);
else
put_msg (TRUE, MSG_RIPOUT_FOUND);
}
exit(0);
}
#define mbtowc(wname, aname) MultiByteToWideChar(CP_ACP,0,aname,-1,wname,1024)
void resolve_guid(char * guidname) {
WCHAR pszName[512], pszGuidName[128];
char * psz;
HANDLE hMpr;
DWORD dwErr;
if (MprConfigServerConnect(NULL, &hMpr) != NO_ERROR)
return;
mbtowc(pszGuidName, guidname);
dwErr = MprConfigGetFriendlyName(hMpr, pszGuidName, pszName, sizeof(pszName));
if (dwErr == NO_ERROR)
put_msg (TRUE, MSG_RESOLVEGUID_OK, pszName);
else
put_msg (TRUE, MSG_RESOLVEGUID_NO, guidname);
MprConfigServerDisconnect(hMpr);
exit(0);
}
void resolve_name(char * name) {
WCHAR pszName[1024], pszGuidName[1024];
char * pszGuid;
DWORD dwErr;
HANDLE hMpr;
if (MprConfigServerConnect(NULL, &hMpr) != NO_ERROR)
return;
// Convert to wc and look up the name
mbtowc (pszName, name);
dwErr = MprConfigGetGuidName(hMpr, pszName, pszGuidName, sizeof(pszGuidName));
if (dwErr == NO_ERROR)
put_msg (TRUE, MSG_RESOLVENAME_OK, pszGuidName);
else
put_msg (TRUE, MSG_RESOLVENAME_NO);
// Cleanup interface map
MprConfigServerDisconnect(hMpr);
exit(0);
}
/*page***************************************************************
p r i n t _ c o n f i g
Prints out the current config
Arguments - None
Returns - Does not return
********************************************************************/
void print_config(void)
{
int rc;
int nicidcount;
USHORT nicid;
int showlegend = 0;
char nicidbuf[6];
char network[9];
char * frametype;
char node[13];
char special[2];
char adaptername[64];
ISN_ACTION_GET_DETAILS getdetails;
HANDLE hMpr;
DWORD dwErr;
// Initialize the map from guid to interface name
MprConfigServerConnect(NULL, &hMpr);
if (isnipxfd != INVALID_HANDLE) {
/** First query nicid 0 **/
getdetails.NicId = 0;
rc = do_isnipxioctl(isnipxfd, MIPX_CONFIG, (char *)&getdetails, sizeof(getdetails));
if (rc) {
put_msg (TRUE, MSG_QUERY_CONFIG_ERROR, "nwlnkipx");
put_msg (TRUE, get_emsg(rc));
goto errorexit;
}
printf("\n");
put_msg (FALSE, MSG_NET_NUMBER_HDR);
if (getdetails.NetworkNumber != 0) {
sprintf (network, "%.8x", REORDER_ULONG(getdetails.NetworkNumber));
put_msg (FALSE, MSG_SHOW_NET_NUMBER,
"0.",
network,
"None ",
"Internal",
"000000000001",
"");
//put_msg (FALSE, MSG_SHOW_INTERNAL_NET, network);
}
//
// The NicId 0 query returns the total number.
//
nicidcount = getdetails.NicId;
for (nicid = 1; nicid <= nicidcount; nicid++) {
getdetails.NicId = nicid;
rc = do_isnipxioctl(isnipxfd, MIPX_CONFIG, (char *)&getdetails, sizeof(getdetails));
if (rc) {
continue;
}
sprintf (nicidbuf, "%d.", nicid);
sprintf (network, "%.8x", REORDER_ULONG(getdetails.NetworkNumber));
switch (getdetails.FrameType) {
case 0: frametype = load_msg (MSG_ETHERNET_II); break;
case 1: frametype = load_msg (MSG_802_3); break;
case 2: frametype = load_msg (MSG_802_2); break;
case 3: frametype = load_msg (MSG_SNAP); break;
case 4: frametype = load_msg (MSG_ARCNET); break;
default: frametype = load_msg (MSG_UNKNOWN); break;
}
// Translate the adapter name
if (getdetails.Type == 1) { // lan
WCHAR pszName[512];
PWCHAR pszGuid = &(getdetails.AdapterName[0]);
dwErr = MprConfigGetFriendlyName(hMpr, pszGuid, pszName, sizeof(pszName));
if (dwErr == NO_ERROR)
sprintf (adaptername, "%ws", pszName);
else
sprintf (adaptername, "%ws", getdetails.AdapterName);
}
else
sprintf (adaptername, "%ws", getdetails.AdapterName);
sprintf (node, "%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x",
getdetails.Node[0],
getdetails.Node[1],
getdetails.Node[2],
getdetails.Node[3],
getdetails.Node[4],
getdetails.Node[5]);
special[1] = '\0';
if (getdetails.BindingSet) {
special[0] = '*';
showlegend |= 1;
} else if (getdetails.Type == 2) {
special[0] = '+';
showlegend |= 2;
} else if (getdetails.Type == 3) {
special[0] = '-';
showlegend |= 4;
} else {
special[0] = '\0';
}
put_msg (FALSE, MSG_SHOW_NET_NUMBER,
nicidbuf,
network,
frametype,
adaptername,
node,
special);
LocalFree (frametype);
}
if (showlegend) {
put_msg (FALSE, MSG_NET_NUMBER_LEGEND_HDR);
if (showlegend & 1) {
put_msg (FALSE, MSG_LEGEND_BINDING_SET);
}
if (showlegend & 2) {
put_msg (FALSE, MSG_LEGEND_ACTIVE_WAN);
}
if (showlegend & 4) {
put_msg (FALSE, MSG_LEGEND_DOWN_WAN);
}
printf("\n");
}
}
errorexit:
/** Close up and exit **/
// Cleanup interface map
MprConfigServerDisconnect(hMpr);
if (isnipxfd != INVALID_HANDLE) NtClose(isnipxfd);
if (nwlinkfd != INVALID_HANDLE) NtClose(nwlinkfd);
if (isnripfd != INVALID_HANDLE) NtClose(isnripfd);
exit(0);
}
/*page***************************************************************
g e t _ e m s g
Get an error message for an error
Arguments - None
Returns - Does not return
********************************************************************/
unsigned long get_emsg(int rc)
{
/**
We have 3 defined error codes that can come back.
1 - EINVAL means that we sent down parameters wrong
(SHOULD NEVER HAPPEN)
2 - ERANGE means that the board number is invalid
(CAN HAPPEN IF USER ENTERS BAD BOARD)
3 - ENOENT means that on remove - the address given
is not in the source routing table.
**/
switch (rc) {
case EINVAL:
return MSG_INTERNAL_ERROR;
case ERANGE:
return MSG_INVALID_BOARD;
case ENOENT:
return MSG_ADDRESS_NOT_FOUND;
default:
return MSG_UNKNOWN_ERROR;
}
}
/*page***************************************************************
d o _ i s n i p x i o c t l
Do the equivalent of a stream ioctl to isnipx
Arguments - fd = Handle to put on
cmd = Command to send
datap = Ptr to ctrl buffer
dlen = Ptr to len of data buffer
Returns - 0 = OK
else = Error
********************************************************************/
int do_isnipxioctl(HANDLE fd, int cmd, char *datap, int dlen)
{
NTSTATUS Status;
UCHAR buffer[sizeof(NWLINK_ACTION) + sizeof(ISN_ACTION_GET_DETAILS) - 1];
PNWLINK_ACTION action;
IO_STATUS_BLOCK IoStatusBlock;
int rc;
/** Fill out the structure **/
action = (PNWLINK_ACTION)buffer;
action->Header.TransportId = ISN_ACTION_TRANSPORT_ID;
action->OptionType = NWLINK_OPTION_CONTROL;
action->BufferLength = sizeof(ULONG) + dlen;
action->Option = cmd;
RtlMoveMemory(action->Data, datap, dlen);
/** Issue the ioctl **/
Status = NtDeviceIoControlFile(
fd,
NULL,
NULL,
NULL,
&IoStatusBlock,
IOCTL_TDI_ACTION,
NULL,
0,
action,
FIELD_OFFSET(NWLINK_ACTION,Data) + dlen);
if (Status != STATUS_SUCCESS) {
if (Status == STATUS_INVALID_PARAMETER) {
rc = ERANGE;
} else {
rc = EINVAL;
}
} else {
if (dlen > 0) {
RtlMoveMemory (datap, action->Data, dlen);
}
rc = 0;
}
return rc;
}
//*****************************************************************************
//
// Name: put_msg
//
// Description: Reads a message resource, formats it in the current language
// and displays the message.
//
// NOTE: This routine was stolen from net\sockets\tcpcmd\common2\util.c.
//
// Parameters: error - TRUE if this is an error message.
// unsigned long MsgNum: ID of the message resource.
//
// Returns: unsigned long: number of characters displayed.
//
// History:
// 01/05/93 JayPh Created.
//
//*****************************************************************************
unsigned long put_msg(BOOLEAN error, unsigned long MsgNum, ... )
{
unsigned long msglen;
char *vp;
char *oemp;
va_list arglist;
va_start( arglist, MsgNum );
msglen = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_HMODULE,
NULL,
MsgNum,
0L, // Default country ID.
(LPTSTR)&vp,
0,
&arglist );
if ( (msglen == 0) || (vp == NULL))
{
return ( 0 );
}
oemp = (char *) malloc(msglen*sizeof(char) + 1);
if (oemp != NULL) {
CharToOem(vp, oemp);
fprintf( error ? stderr : stdout, "%s", oemp );
free(oemp);
} else {
printf("Failed to allocate memory of %d bytes\n",msglen*sizeof(char));
}
LocalFree( vp );
return ( msglen );
}
//*****************************************************************************
//
// Name: load_msg
//
// Description: Reads and formats a message resource and returns a pointer
// to the buffer containing the formatted message. It is the
// responsibility of the caller to free the buffer.
//
// NOTE: This routine was stolen from net\sockets\tcpcmd\common2\util.c.
//
// Parameters: unsigned long MsgNum: ID of the message resource.
//
// Returns: char *: pointer to the message buffer, NULL if error.
//
// History:
// 01/05/93 JayPh Created.
//
//*****************************************************************************
char *load_msg( unsigned long MsgNum, ... )
{
unsigned long msglen;
char *vp;
va_list arglist;
va_start( arglist, MsgNum );
msglen = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_HMODULE,
NULL,
MsgNum,
0L, // Default country ID.
(LPTSTR)&vp,
0,
&arglist );
if ( msglen == 0 )
{
return(0);
}
return ( vp );
}
#define MAX_NETWORK_INTERFACES 255
typedef struct router_info
{
ULONG NetNumber;
USHORT TickCount;
USHORT HopCount;
USHORT NicId;
UCHAR InterfaceNumber[10];
} ROUTER_INFO, *PROUTER_INFO;
/*page***************************************************************
s h o w _ r o u t e r _ t a b l e
Display the IPX routing table
Arguments - FileHandle = Router File Handle
IoStatusBlock = Device IO Status Block
Returns - Does not return
********************************************************************/
VOID
show_router_table(
PHANDLE FileHandle,
PIO_STATUS_BLOCK IoStatusBlock
)
{
SHOW_NIC_INFO nis[MAX_NETWORK_INTERFACES];
ULONG NetNumber;
char InterfaceNumber[10];
NTSTATUS Status;
USHORT index, i, NumEntries, count;
char router_entry[128];
char buffer[32];
PROUTER_INFO RouterInfo = NULL;
if (*FileHandle == INVALID_HANDLE) {
put_msg(TRUE, MSG_IPXROUTER_NOT_STARTED );
goto exit_show_table;
}
/** First get the Network numbers for all interfaces **/
index = 0;
while(TRUE) {
Status = NtDeviceIoControlFile(
*FileHandle, // HANDLE to File
NULL, // HANDLE to Event
NULL, // ApcRoutine
NULL, // ApcContext
IoStatusBlock, // IO_STATUS_BLOCK
IOCTL_IPXROUTER_SHOWNICINFO, // IoControlCode
&index, // Input Buffer
sizeof(USHORT), // Input Buffer Length
&nis[index], // Output Buffer
sizeof(SHOW_NIC_INFO)); // Output Buffer Length
if(IoStatusBlock->Status == STATUS_NO_MORE_ENTRIES) {
break;
}
index ++;
if(Status != STATUS_SUCCESS) {
sprintf(buffer, "%x", Status);
put_msg(TRUE, MSG_SHOWSTATS_FAILED, buffer);
goto exit_show_table;
}
if (index >= MAX_NETWORK_INTERFACES) {
// break out of this loop if there are more than 255 network
// interfaces because we only have storage for 255.
break;
}
}
Status = NtDeviceIoControlFile(
*FileHandle, // HANDLE to File
NULL, // HANDLE to Event
NULL, // ApcRoutine
NULL, // ApcContext
IoStatusBlock, // IO_STATUS_BLOCK
IOCTL_IPXROUTER_SNAPROUTES, // IoControlCode
NULL, // Input Buffer
0, // Input Buffer Length
NULL, // Output Buffer
0); // Output Buffer Length
if (IoStatusBlock->Status != STATUS_SUCCESS) {
sprintf(buffer, "%x", Status);
put_msg(TRUE, MSG_SNAPROUTES_FAILED, buffer);
goto exit_show_table;
}
// first determine the number of router table entries to
// allocate sufficient storage
NumEntries = 0;
while(TRUE) {
Status = NtDeviceIoControlFile(
*FileHandle, // HANDLE to File
NULL, // HANDLE to Event
NULL, // ApcRoutine
NULL, // ApcContext
IoStatusBlock, // IO_STATUS_BLOCK
IOCTL_IPXROUTER_GETNEXTROUTE, // IoControlCode
NULL, // Input Buffer
0, // Input Buffer Length
&rte, // Output Buffer
sizeof(IPX_ROUTE_ENTRY)); // Output Buffer Length
if(IoStatusBlock->Status == STATUS_NO_MORE_ENTRIES) {
break;
}
if(Status != STATUS_SUCCESS) {
sprintf(buffer,"%x",Status);
put_msg(TRUE, MSG_GETNEXTROUTE_FAILED, buffer);
goto exit_show_table;
}
NumEntries ++;
}
RouterInfo = (PROUTER_INFO) LocalAlloc(LPTR, sizeof(ROUTER_INFO) * NumEntries);
if(!RouterInfo) {
put_msg(FALSE, MSG_INSUFFICIENT_MEMORY);
goto exit_show_table;
}
Status = NtDeviceIoControlFile(
*FileHandle, // HANDLE to File
NULL, // HANDLE to Event
NULL, // ApcRoutine
NULL, // ApcContext
IoStatusBlock, // IO_STATUS_BLOCK
IOCTL_IPXROUTER_SNAPROUTES, // IoControlCode
NULL, // Input Buffer
0, // Input Buffer Length
NULL, // Output Buffer
0); // Output Buffer Length
if (IoStatusBlock->Status != STATUS_SUCCESS) {
sprintf(buffer, "%x", Status);
put_msg(TRUE, MSG_SNAPROUTES_FAILED, buffer);
goto exit_show_table;
}
index = 0;
while(TRUE) {
Status = NtDeviceIoControlFile(
*FileHandle, // HANDLE to File
NULL, // HANDLE to Event
NULL, // ApcRoutine
NULL, // ApcContext
IoStatusBlock, // IO_STATUS_BLOCK
IOCTL_IPXROUTER_GETNEXTROUTE, // IoControlCode
NULL, // Input Buffer
0, // Input Buffer Length
&rte, // Output Buffer
sizeof(IPX_ROUTE_ENTRY)); // Output Buffer Length
if(IoStatusBlock->Status == STATUS_NO_MORE_ENTRIES) {
break;
}
if(Status != STATUS_SUCCESS) {
sprintf(buffer,"%x",Status);
put_msg(TRUE, MSG_GETNEXTROUTE_FAILED, buffer);
goto exit_show_table;
}
// make sure we don't exceed the number of entries
if (index > NumEntries) {
break;
}
// get net nr in "on the wire" order
GETLONG2ULONG(&(RouterInfo[index].NetNumber), rte.Network);
// find out the matching Network number based on NIC ID
for(i=0; i < MAX_NETWORK_INTERFACES; i++) {
if(rte.NicId == nis[i].NicId) {
sprintf(RouterInfo[index].InterfaceNumber, "%.2x%.2x%.2x%.2x",
nis[i].Network[0],
nis[i].Network[1],
nis[i].Network[2],
nis[i].Network[3]);
break;
}
}
RouterInfo[index].TickCount = rte.TickCount;
RouterInfo[index].HopCount = rte.HopCount;
RouterInfo[index].NicId = rte.NicId;
index++;
}
// Now sort the entries by net number
qsort( (void*) RouterInfo,
NumEntries,
sizeof(ROUTER_INFO),
(PQSORT_COMPARE)CompareNetNumber );
put_msg(FALSE, MSG_ROUTER_TABLE_HEADER);
for(index =0, count = 0; index < NumEntries; index++, count++)
{
if (count > 50) {
count = 0;
// display router table header every 25 entries
// to make reading the table easier.
put_msg(FALSE, MSG_ROUTER_TABLE_HEADER);
}
printf("%.8x %6d %2d %-16s %d\n",
RouterInfo[index].NetNumber,
RouterInfo[index].TickCount,
RouterInfo[index].HopCount,
RouterInfo[index].InterfaceNumber,
RouterInfo[index].NicId );
}
/** Close up and exit **/
exit_show_table:
if (RouterInfo) LocalFree(RouterInfo);
if (isnipxfd != INVALID_HANDLE) NtClose(isnipxfd);
if (nwlinkfd != INVALID_HANDLE) NtClose(nwlinkfd);
if (isnripfd != INVALID_HANDLE) NtClose(isnripfd);
exit(0);
}
int __cdecl CompareNetNumber( void * p0, void * p1)
{
PROUTER_INFO pLeft = (PROUTER_INFO) p0;
PROUTER_INFO pRight = (PROUTER_INFO) p1;
if(pLeft->NetNumber == pRight->NetNumber)
return(0);
if(pLeft->NetNumber > pRight->NetNumber)
return(1);
else
return(-1);
}
PUCHAR DeviceType[2] = { "LAN", "WAN" };
PUCHAR NicState[4] = { "CLOSED", "CLOSING", "ACTIVE", "PENDING_OPEN" };
/*page***************************************************************
s h o w _ s t a t s
Displays IPX internal routing statistics
Arguments - FileHandle = Router File Handle
IoStatusBlock = Device IO Status Block
Returns - Does not return
********************************************************************/
VOID
show_stats(
PHANDLE FileHandle,
PIO_STATUS_BLOCK IoStatusBlock
)
{
SHOW_NIC_INFO nis;
USHORT index, i;
char NicId[4];
char NetworkNumber[10];
char RipRcvd[32], RipSent[32];
char RoutedRcvd[32], RoutedSent[32];
char Type20Rcvd[32], Type20Sent[32];
char BadRcvd[32];
char buffer[32];
NTSTATUS Status;
if (*FileHandle == INVALID_HANDLE) {
put_msg(TRUE, MSG_IPXROUTER_NOT_STARTED );
goto end_stats;
}
index = 0;
while(TRUE) {
Status = NtDeviceIoControlFile(
*FileHandle, // HANDLE to File
NULL, // HANDLE to Event
NULL, // ApcRoutine
NULL, // ApcContext
IoStatusBlock, // IO_STATUS_BLOCK
IOCTL_IPXROUTER_SHOWNICINFO, // IoControlCode
&index, // Input Buffer
sizeof(USHORT), // Input Buffer Length
&nis, // Output Buffer
sizeof(nis)); // Output Buffer Length
if(IoStatusBlock->Status == STATUS_NO_MORE_ENTRIES) {
goto end_stats;
}
index ++;
if(Status != STATUS_SUCCESS) {
sprintf(buffer, "%x", Status);
put_msg(TRUE, MSG_SHOWSTATS_FAILED, buffer);
goto end_stats;
}
sprintf(NicId, "%d", nis.NicId);
sprintf(NetworkNumber,
"%.2x%.2x%.2x%.2x",
nis.Network[0],
nis.Network[1],
nis.Network[2],
nis.Network[3]);
sprintf(RipRcvd, "%-8d", nis.StatRipReceived);
sprintf(RipSent, "%-8d", nis.StatRipSent);
sprintf(RoutedRcvd, "%-8d", nis.StatRoutedReceived);
sprintf(RoutedSent, "%-8d", nis.StatRoutedSent);
sprintf(Type20Rcvd, "%-8d", nis.StatType20Received);
sprintf(Type20Sent, "%-8d", nis.StatType20Sent);
sprintf(BadRcvd, "%-8d", nis.StatBadReceived);
put_msg(FALSE,
MSG_SHOW_STATISTICS,
NicId,
NetworkNumber,
RipRcvd,
RipSent,
Type20Rcvd,
Type20Sent,
RoutedRcvd,
RoutedSent,
BadRcvd);
}
/** Close up and exit **/
end_stats:
if (isnipxfd != INVALID_HANDLE) NtClose(isnipxfd);
if (nwlinkfd != INVALID_HANDLE) NtClose(nwlinkfd);
if (isnripfd != INVALID_HANDLE) NtClose(isnripfd);
exit(0);
}
/*page***************************************************************
c l e a r _ s t a t s
Clears the IPX internal routing statistics
Arguments - FileHandle = Router File Handle
IoStatusBlock = Device IO Status Block
Returns - Does not return
********************************************************************/
VOID
clear_stats(
PHANDLE FileHandle,
PIO_STATUS_BLOCK IoStatusBlock
)
{
NTSTATUS Status;
char buffer[32];
if (*FileHandle == INVALID_HANDLE) {
put_msg(TRUE, MSG_IPXROUTER_NOT_STARTED );
goto end_clearstats;
}
Status = NtDeviceIoControlFile(
*FileHandle, // HANDLE to File
NULL, // HANDLE to Event
NULL, // ApcRoutine
NULL, // ApcContext
IoStatusBlock, // IO_STATUS_BLOCK
IOCTL_IPXROUTER_ZERONICSTATISTICS, // IoControlCode
NULL, // Input Buffer
0, // Input Buffer Length
NULL, // Output Buffer
0); // Output Buffer Length
if(Status != STATUS_SUCCESS) {
sprintf(buffer, "%x", Status);
put_msg(TRUE, MSG_CLEAR_STATS_FAILED, buffer);
}
/** Close up and exit **/
end_clearstats:
if (isnipxfd != INVALID_HANDLE) NtClose(isnipxfd);
if (nwlinkfd != INVALID_HANDLE) NtClose(nwlinkfd);
if (isnripfd != INVALID_HANDLE) NtClose(isnripfd);
exit(0);
}
typedef struct server_info
{
USHORT ObjectType;
UCHAR ObjectName[100];
UCHAR IpxAddress[12];
} SERVER_INFO, *PSERVER_INFO;
/*page***************************************************************
s h o w _ s e r v e r s
Display the servers from the SAP table
Arguments - servertype = Type of servers to display
Defaults to show all server types
Returns - Does not return
********************************************************************/
VOID
show_servers(int servertype)
{
INT rc;
ULONG ObjectID = 0xFFFFFFFF;
UCHAR ObjectName[100];
USHORT ObjectType;
USHORT ScanType = (USHORT) servertype;
UCHAR IpxAddress[12];
USHORT i;
USHORT index, count, NumServers;
PSERVER_INFO ServerInfo = NULL;
if(rc = SapLibInit() != SAPRETURN_SUCCESS) {
put_msg(TRUE, MSG_SAP_NOT_STARTED);
goto show_servers_end;
}
memset(&ObjectName, 0, 100);
// find out how many servers are there so that we can allocate
// sufficient storage
NumServers = 0;
while((rc = SapScanObject(&ObjectID,
ObjectName,
&ObjectType,
ScanType)) == SAPRETURN_SUCCESS)
{
NumServers++;
}
ServerInfo = (PSERVER_INFO) LocalAlloc(LPTR, sizeof(SERVER_INFO) * NumServers);
if(!ServerInfo)
{
put_msg(FALSE, MSG_INSUFFICIENT_MEMORY);
goto show_servers_end;
}
index = 0;
ObjectID = 0xFFFFFFFF;
while((rc = SapScanObject(&ObjectID,
ObjectName,
&ObjectType,
ScanType)) == SAPRETURN_SUCCESS)
{
if (index >= NumServers) {
break;
}
// get object address
SapGetObjectName(ObjectID,
ObjectName,
&ObjectType,
IpxAddress);
ServerInfo[index].ObjectType = ObjectType;
strcpy(ServerInfo[index].ObjectName, ObjectName);
CopyMemory(ServerInfo[index].IpxAddress, IpxAddress, 12);
index++;
}
// Now sort the entries by server name
qsort( (void*) ServerInfo,
NumServers,
sizeof(SERVER_INFO),
(PQSORT_COMPARE)CompareServerNames );
if(servertype == SHOW_ALL_SERVERS)
put_msg(FALSE, MSG_SHOW_ALL_SERVERS_HEADER);
else
put_msg(FALSE, MSG_SHOW_SPECIFIC_SERVER_HEADER);
for(index = 0, count = 0; index < NumServers; index++, count++)
{
if (count > 50) {
// write the table header for every 50 entries
// to make this more readable.
count = 0;
if(servertype == SHOW_ALL_SERVERS)
put_msg(FALSE, MSG_SHOW_ALL_SERVERS_HEADER);
else
put_msg(FALSE, MSG_SHOW_SPECIFIC_SERVER_HEADER);
}
for(i=0; i<4; i++) {
printf("%.2x", ServerInfo[index].IpxAddress[i]);
}
printf(".");
for(i=4; i<10; i++) {
printf("%.2x", ServerInfo[index].IpxAddress[i]);
}
if(servertype == SHOW_ALL_SERVERS) {
printf(" %-6d", ServerInfo[index].ObjectType);
}
printf(" %s\n", ServerInfo[index].ObjectName);
}
/** Close up and exit **/
show_servers_end:
if (ServerInfo) LocalFree(ServerInfo);
if (isnipxfd != INVALID_HANDLE) NtClose(isnipxfd);
if (nwlinkfd != INVALID_HANDLE) NtClose(nwlinkfd);
if (isnripfd != INVALID_HANDLE) NtClose(isnripfd);
exit(0);
}
int __cdecl CompareServerNames( void * p0, void * p1)
{
PSERVER_INFO pLeft = (PSERVER_INFO) p0;
PSERVER_INFO pRight = (PSERVER_INFO) p1;
return(strcmp(pLeft->ObjectName, pRight->ObjectName));
}