Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2003 lines
53 KiB

  1. /****************************************************************************
  2. * (c) Copyright 1990, 1993 Micro Computer Systems, Inc. All rights reserved.
  3. *****************************************************************************
  4. *
  5. * Title: IPX/SPX Compatible Source Routing Daemon for Windows NT
  6. *
  7. * Module: ipx/route/ipxroute.c
  8. *
  9. * Version: 1.00.00
  10. *
  11. * Date: 04-08-93
  12. *
  13. * Author: Brian Walker
  14. *
  15. *****************************************************************************
  16. *
  17. * Change Log:
  18. *
  19. * Date DevSFC Comment
  20. * -------- ------ -------------------------------------------------------
  21. * 02-14-95 RamC Added command line options to support displaying
  22. * Router Table, Router Statistics and SAP information.
  23. * Basically a merge of ipxroute and Stefan's rttest.
  24. * 03-12-98 Pmay Added translation of if name to version int the
  25. connections folder.
  26. *****************************************************************************
  27. *
  28. * Functional Description:
  29. *
  30. *
  31. ****************************************************************************/
  32. #include <nt.h>
  33. #include <ntrtl.h>
  34. #include <nturtl.h>
  35. #include <windef.h>
  36. #include <winbase.h>
  37. #include <winnls.h>
  38. #include <winuser.h>
  39. #include <stdio.h>
  40. #include <stdlib.h>
  41. #include <ntstapi.h>
  42. #include <nwsap.h>
  43. #include <stropts.h>
  44. #include <mprapi.h>
  45. #include "errno.h"
  46. #include "tdi.h"
  47. #include "isnkrnl.h"
  48. #include "ipxrtmsg.h"
  49. #include "driver.h"
  50. #include "utils.h"
  51. typedef struct _IPX_ROUTE_ENTRY {
  52. UCHAR Network[4];
  53. USHORT NicId;
  54. UCHAR NextRouter[6];
  55. PVOID NdisBindingContext;
  56. USHORT Flags;
  57. USHORT Timer;
  58. UINT Segment;
  59. USHORT TickCount;
  60. USHORT HopCount;
  61. PVOID AlternateRoute[2];
  62. PVOID NicLinkage[2];
  63. struct {
  64. PVOID Linkage[2];
  65. ULONG Reserved[1];
  66. } PRIVATE;
  67. } IPX_ROUTE_ENTRY, * PIPX_ROUTE_ENTRY;
  68. IPX_ROUTE_ENTRY rte;
  69. /** Global Variables **/
  70. int sr_def = 0;
  71. int sr_bcast = 0;
  72. int sr_multi = 0;
  73. int boardnum = 0;
  74. int clear = 0;
  75. int config = 0;
  76. int showtable = 0;
  77. int showservers = 0;
  78. int showstats = 0;
  79. int clearstats = 0;
  80. int ripout = 0;
  81. int resolveguid = 0;
  82. int resolvename = 0;
  83. int servertype;
  84. unsigned long netnum;
  85. char nodeaddr[6]; /* Node address to remove */
  86. HANDLE nwlinkfd;
  87. HANDLE isnipxfd;
  88. HANDLE isnripfd;
  89. char ebuffer[128];
  90. char nwlinkname[] = "\\Device\\Streams\\NWLinkIpx";
  91. wchar_t isnipxname[] = L"\\Device\\NwlnkIpx";
  92. wchar_t isnripname[] = L"\\Device\\Ipxroute";
  93. char pgmname[] = "IPXROUTE";
  94. #define SHOW_ALL_SERVERS 0XFFFF
  95. /** **/
  96. #define INVALID_HANDLE (HANDLE)(-1)
  97. /** Structure to send REMOVE with **/
  98. typedef struct rterem {
  99. int rterem_bnum; /* Board number */
  100. char rterem_node[6]; /* Node to remove */
  101. } rterem;
  102. typedef int (__cdecl * PQSORT_COMPARE)(const void * p0, const void * p1);
  103. /** Internal Function Prototypes **/
  104. extern void print_table(int);
  105. extern void usage(void);
  106. extern void print_version(void);
  107. extern char *print_type(int);
  108. extern int my_strncmp(char *, char *, int);
  109. extern int get_board_num(char *, int *);
  110. extern int get_node_num(char *, char *);
  111. extern int get_server_type(char *, int *);
  112. extern unsigned char get_hex_byte(char *);
  113. extern int get_driver_parms(void);
  114. extern int set_driver_parms(void);
  115. extern int do_strioctl(HANDLE, int, char *, int, int);
  116. extern void remove_address(char *);
  117. extern void clear_table(void);
  118. extern void print_config(void);
  119. extern unsigned long get_emsg(int);
  120. int do_isnipxioctl(HANDLE fd, int cmd, char *datap, int dlen);
  121. unsigned long put_msg(BOOLEAN error, unsigned long MsgNum, ... );
  122. char *load_msg( unsigned long MsgNum, ... );
  123. extern void show_router_table(PHANDLE, PIO_STATUS_BLOCK);
  124. extern void show_stats(HANDLE, PIO_STATUS_BLOCK);
  125. extern void clear_stats(HANDLE, PIO_STATUS_BLOCK);
  126. extern void show_servers(int);
  127. extern void show_ripout(unsigned long);
  128. extern void resolve_guid(char *);
  129. extern void resolve_name(char *);
  130. extern int __cdecl CompareServerNames( void * p0, void * p1);
  131. extern int __cdecl CompareNetNumber( void * p0, void * p1);
  132. /*page*************************************************************
  133. m a i n
  134. This is the main routine that gets executed when a NET START
  135. happens.
  136. Arguments - None
  137. Returns - Nothing
  138. ********************************************************************/
  139. void __cdecl main(int argc, char **argv)
  140. {
  141. char *p;
  142. int todo;
  143. int remove_flag;
  144. UNICODE_STRING FileString;
  145. OBJECT_ATTRIBUTES ObjectAttributes, RouterObjectAttributes;
  146. IO_STATUS_BLOCK IoStatusBlock, RouterIoStatusBlock;
  147. NTSTATUS Status;
  148. /** **/
  149. print_version();
  150. /** Open the nwlink driver **/
  151. nwlinkfd = s_open(nwlinkname, 0, 0);
  152. /** Open the isnipx driver **/
  153. RtlInitUnicodeString (&FileString, isnipxname);
  154. InitializeObjectAttributes(
  155. &ObjectAttributes,
  156. &FileString,
  157. OBJ_CASE_INSENSITIVE,
  158. NULL,
  159. NULL);
  160. Status = NtOpenFile(
  161. &isnipxfd,
  162. SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
  163. &ObjectAttributes,
  164. &IoStatusBlock,
  165. FILE_SHARE_READ | FILE_SHARE_WRITE,
  166. FILE_SYNCHRONOUS_IO_ALERT);
  167. if (!NT_SUCCESS(Status)) {
  168. isnipxfd = INVALID_HANDLE;
  169. put_msg (TRUE, MSG_OPEN_FAILED, "\\Device\\NwlnkIpx");
  170. }
  171. /** Open the isnrip driver **/
  172. RtlInitUnicodeString (&FileString, isnripname);
  173. InitializeObjectAttributes(
  174. &RouterObjectAttributes,
  175. &FileString,
  176. OBJ_CASE_INSENSITIVE,
  177. NULL,
  178. NULL);
  179. Status = NtOpenFile(
  180. &isnripfd,
  181. SYNCHRONIZE | GENERIC_READ,
  182. &RouterObjectAttributes,
  183. &RouterIoStatusBlock,
  184. FILE_SHARE_READ | FILE_SHARE_WRITE,
  185. FILE_SYNCHRONOUS_IO_NONALERT);
  186. if (!NT_SUCCESS(Status)) {
  187. isnripfd = INVALID_HANDLE;
  188. // don't display any error message, but display the
  189. // message that the IPX router is not started when
  190. // the user actually tries to look at the router.
  191. }
  192. if ((nwlinkfd == INVALID_HANDLE) &&
  193. (isnipxfd == INVALID_HANDLE) &&
  194. (isnripfd == INVALID_HANDLE))
  195. {
  196. exit(1);
  197. }
  198. /** Go thru the command line and set it up **/
  199. argc--;
  200. argv++;
  201. /** Parse the command line **/
  202. todo = 0;
  203. remove_flag = 0;
  204. while (argc--) {
  205. /** Uppercase the arg **/
  206. p = *argv;
  207. _strupr(p);
  208. /** Parse the argument **/
  209. //if (!strcmp(p, "CLEAR")) {
  210. // todo = 1;
  211. // clear = 1;
  212. // }
  213. /*else*/ if (!strcmp(p, "DEF")) {
  214. todo = 1;
  215. sr_def = 1;
  216. }
  217. else if (!strcmp(p, "GBR")) {
  218. todo = 1;
  219. sr_bcast = 1;
  220. }
  221. else if (!strcmp(p, "MBR")) {
  222. todo = 1;
  223. sr_multi = 1;
  224. }
  225. else if (!strcmp(p, "CONFIG")) {
  226. todo = 1;
  227. config = 1;
  228. }
  229. else if (!my_strncmp(p, "BOARD=", 6))
  230. get_board_num(p + 6, &boardnum);
  231. else if (!my_strncmp(p, "REMOVE=", 7)) {
  232. remove_flag = 1;
  233. get_node_num(p + 7, nodeaddr);
  234. }
  235. //else if (!strcmp(p, "TABLE")) {
  236. // todo = 1;
  237. // showtable = 1;
  238. // }
  239. else if (!strcmp(p, "SERVERS")) {
  240. todo = 1;
  241. showservers = 1;
  242. /** default is to show all server types **/
  243. servertype = SHOW_ALL_SERVERS;
  244. argv++;
  245. if(argc--) {
  246. p = *argv;
  247. _strupr(p);
  248. if (!my_strncmp(p, "/TYPE=", 6)) {
  249. get_server_type(p + 6, &servertype);
  250. }
  251. else
  252. usage();
  253. }
  254. /** no more arguments - break out of while lop **/
  255. else
  256. break;
  257. }
  258. else if (!strcmp(p, "RIPOUT")) {
  259. todo = 1;
  260. ripout = 1;
  261. /** default look for local network **/
  262. netnum = 0L;
  263. argv++;
  264. if(argc--) {
  265. p = *argv;
  266. netnum = strtoul (p, NULL, 16);
  267. if (netnum == 0)
  268. usage();
  269. }
  270. /** no more arguments - break out of while lop **/
  271. else
  272. break;
  273. }
  274. else if (!strcmp(p, "RESOLVE")) {
  275. argv++;
  276. if(argc--) {
  277. p = *argv;
  278. if (!strcmp(p, "guid")) {
  279. todo = 1;
  280. resolveguid = 1;
  281. argc--;
  282. argv++;
  283. p = *argv;
  284. }
  285. else if (!strcmp(p, "name")) {
  286. todo = 1;
  287. resolvename = 1;
  288. argc--;
  289. argv++;
  290. p = *argv;
  291. }
  292. else
  293. usage();
  294. }
  295. /** no more arguments - break out of while lop **/
  296. else
  297. break;
  298. }
  299. //else if (!strcmp(p, "STATS")) {
  300. // todo = 1;
  301. // /** default is to show the router statistics **/
  302. // showstats = 1;
  303. // argv++;
  304. // if(argc--) {
  305. // p = *argv;
  306. // _strupr(p);
  307. // if (!strcmp(p, "/CLEAR")) {
  308. // clearstats = 1;
  309. // showstats = 0;
  310. // }
  311. // else if (!strcmp(p, "/SHOW")) {
  312. // showstats = 1;
  313. // }
  314. // else
  315. // usage;
  316. // }
  317. // /** no more arguments - break out of while lop **/
  318. // else
  319. // break;
  320. // }
  321. else
  322. usage();
  323. /** Goto the next entry **/
  324. argv++;
  325. }
  326. /** Go update the driver **/
  327. #if 0
  328. printf("todo = %d\n", todo);
  329. printf("remove_flag= %d\n", remove_flag);
  330. printf("Clear flag = %d\n", clear);
  331. printf("Config flag = %d\n", config);
  332. printf("SR_DEF = %d\n", sr_def);
  333. printf("SR_BCAST = %d\n", sr_bcast);
  334. printf("SR_MULTI = %d\n", sr_multi);
  335. printf("Board = %d\n", boardnum);
  336. printf("Node = %02x:%02x:%02x:%02x:%02x:%02x\n",
  337. (unsigned char)nodeaddr[0],
  338. (unsigned char)nodeaddr[1],
  339. (unsigned char)nodeaddr[2],
  340. (unsigned char)nodeaddr[3],
  341. (unsigned char)nodeaddr[4],
  342. (unsigned char)nodeaddr[5]);
  343. #endif
  344. /** If we have a remove - go remove it and leave **/
  345. if (remove_flag)
  346. remove_address(nodeaddr); /* Does not return */
  347. /** If clear - go clear the source routing table **/
  348. if (clear)
  349. clear_table(); /* Does not return */
  350. /** If config - print out config **/
  351. if (config)
  352. print_config(); /* Does not return */
  353. /** If showtable - print out routing table **/
  354. if (showtable)
  355. show_router_table(&isnripfd, &RouterIoStatusBlock); /* Does not return */
  356. /** If showservers - print out selected servers list **/
  357. if (showservers)
  358. show_servers(servertype); /* Does not return */
  359. /** If ripout - rip out and print results **/
  360. if (ripout)
  361. show_ripout(netnum); /* Does not return */
  362. /** If resolveguid - resolve a guid name **/
  363. if (resolveguid)
  364. resolve_guid(p); /* Does not return */
  365. /** If resolvename - resolve a friendly name **/
  366. if (resolvename)
  367. resolve_name(p); /* Does not return */
  368. /** If showstats - print out statistics **/
  369. if (showstats)
  370. show_stats(&isnripfd, &RouterIoStatusBlock); /* Does not return */
  371. /** If clearstats - go clear statistics **/
  372. if (clearstats)
  373. clear_stats(&isnripfd, &RouterIoStatusBlock); /* Does not return */
  374. /** If there is nothing to do - just print out everything **/
  375. if (!todo) {
  376. /** Get the driver parms **/
  377. if (get_driver_parms()) {
  378. if (isnipxfd != INVALID_HANDLE) NtClose(isnipxfd);
  379. if (nwlinkfd != INVALID_HANDLE) NtClose(nwlinkfd);
  380. if (isnripfd != INVALID_HANDLE) NtClose(isnripfd);
  381. exit(1);
  382. }
  383. /** Print out the table (Never comes back) **/
  384. print_table(1);
  385. }
  386. /** Go set the parameters **/
  387. set_driver_parms();
  388. /** Print the table out **/
  389. print_table(0);
  390. /** All Done **/
  391. if (isnipxfd != INVALID_HANDLE) NtClose(isnipxfd);
  392. if (nwlinkfd != INVALID_HANDLE) NtClose(nwlinkfd);
  393. if (isnripfd != INVALID_HANDLE) NtClose(isnripfd);
  394. exit(0);
  395. }
  396. /*page*************************************************************
  397. p r i n t _ t a b l e
  398. Print out the status of the source routing.
  399. Arguments - flag = 0 - Do NOT print the table
  400. 1 - Do print the table (Never returns)
  401. Returns - Nothing
  402. ********************************************************************/
  403. void print_table(int flag)
  404. {
  405. /** Print the information **/
  406. char * ptype;
  407. printf("\n");
  408. ptype = print_type(sr_def);
  409. put_msg (FALSE, MSG_DEFAULT_NODE, ptype);
  410. LocalFree (ptype);
  411. printf("\n");
  412. ptype = print_type(sr_bcast);
  413. put_msg (FALSE, MSG_BROADCAST, ptype);
  414. LocalFree (ptype);
  415. printf("\n");
  416. ptype = print_type(sr_multi);
  417. put_msg (FALSE, MSG_MULTICAST, ptype);
  418. LocalFree (ptype);
  419. printf("\n");
  420. if (!flag)
  421. return;
  422. #if 0
  423. printf("\n");
  424. printf(" Node Address Source Route\n");
  425. printf("\n");
  426. #endif
  427. /** All Done **/
  428. if (isnipxfd != INVALID_HANDLE) NtClose(isnipxfd);
  429. if (nwlinkfd != INVALID_HANDLE) NtClose(nwlinkfd);
  430. if (isnripfd != INVALID_HANDLE) NtClose(isnripfd);
  431. exit(0);
  432. }
  433. /*page*************************************************************
  434. u s a g e
  435. Print the usage message.
  436. Arguments - None
  437. Returns - Nothing
  438. ********************************************************************/
  439. void usage(void)
  440. {
  441. put_msg( FALSE, MSG_USAGE, pgmname );
  442. /** All Done **/
  443. if (isnipxfd != INVALID_HANDLE) NtClose(isnipxfd);
  444. if (nwlinkfd != INVALID_HANDLE) NtClose(nwlinkfd);
  445. if (isnripfd != INVALID_HANDLE) NtClose(isnripfd);
  446. exit(0);
  447. }
  448. /*page*************************************************************
  449. p r i n t _ v e r s i o n
  450. Print the version number
  451. Arguments - None
  452. Returns - Nothing
  453. ********************************************************************/
  454. void print_version(void)
  455. {
  456. printf("\n");
  457. put_msg (FALSE, MSG_VERSION);
  458. return;
  459. }
  460. /*page*************************************************************
  461. p r i n t _ t y p e
  462. Returns the broadcast type given in a string, the caller
  463. must free the string.
  464. Arguments - 0 = SINGLE ROUTE
  465. Else = ALL ROUTES
  466. Returns - Nothing
  467. ********************************************************************/
  468. char *print_type(int flag)
  469. {
  470. if (flag)
  471. return load_msg (MSG_ALL_ROUTE);
  472. else
  473. return load_msg (MSG_SINGLE_ROUTE);
  474. }
  475. /*page*************************************************************
  476. m y _ s t r n c m p
  477. Given a string (p), see if the first len chars are the same
  478. as those of the 2nd string (s).
  479. Arguments - p = Ptr to first string
  480. s = Ptr to 2nd string
  481. len = Length to check
  482. Returns - 0 = Matched
  483. Else = Not matched
  484. ********************************************************************/
  485. int my_strncmp(char *p, char *s, int len)
  486. {
  487. /** **/
  488. while (len--) {
  489. if (*p++ != *s++)
  490. return 1;
  491. }
  492. /** They matched **/
  493. return 0;
  494. }
  495. /*page*************************************************************
  496. g e t _ b o a r d _ n u m
  497. Get the decimal number from the command line
  498. Arguments - p = Ptr to the ASCII number
  499. nump = Store the number here
  500. Returns - 0 = Got the number OK
  501. Else = Bad number
  502. ********************************************************************/
  503. int get_board_num(char *p, int *nump)
  504. {
  505. *nump = atoi(p);
  506. return 0;
  507. }
  508. /*page*************************************************************
  509. g e t _ n o d e _ n u m
  510. Get a node address from the command line
  511. Arguments - p = Ptr to the ASCII number
  512. nodep = Store the node number here
  513. Returns - 0 = Got the number OK
  514. Else = Bad number
  515. ********************************************************************/
  516. int get_node_num(char *p, char *nodep)
  517. {
  518. int i;
  519. unsigned char c1;
  520. unsigned char c2;
  521. /** **/
  522. if (strlen(p) != 12) {
  523. put_msg (TRUE, MSG_INVALID_REMOVE);
  524. exit(1);
  525. }
  526. /** Get the number **/
  527. for (i = 0 ; i < 6 ; i++) {
  528. /** Get the next 2 digits **/
  529. c1 = get_hex_byte(p++);
  530. c2 = get_hex_byte(p++);
  531. /** If we got a bad number - return error **/
  532. if ((c1 == 0xFF) || (c2 == 0xFF)) {
  533. put_msg (TRUE, MSG_INVALID_REMOVE);
  534. exit(1);
  535. }
  536. /** Set the next byte **/
  537. *nodep++ = (c1 << 4) + c2;
  538. }
  539. /** Return OK **/
  540. return 0;
  541. }
  542. /*page*************************************************************
  543. g e t _ s e r v e r _ t y p e
  544. Get the decimal number from the command line
  545. Arguments - p = Ptr to the ASCII number
  546. nump = Store the number here
  547. Returns - 0 = Got the number OK
  548. Else = Bad number
  549. ********************************************************************/
  550. int get_server_type(char *p, int *nump)
  551. {
  552. *nump = atoi(p);
  553. return 0;
  554. }
  555. /*page*************************************************************
  556. g e t _ h e x _ b y t e
  557. Take 1 ascii hex chars and convert to a hex byte
  558. Arguments - p = Ptr to the ASCII number
  559. Returns - The number
  560. (0xFF = Error)
  561. ********************************************************************/
  562. unsigned char get_hex_byte(char *p)
  563. {
  564. unsigned char c;
  565. /** Get the char **/
  566. c = *(unsigned char *)p;
  567. /** If 0-9 handle it **/
  568. if ((c >= '0') && (c <= '9')) {
  569. c -= '0';
  570. return c;
  571. }
  572. /** If A-F handle it **/
  573. if ((c >= 'A') && (c <= 'F')) {
  574. c -= ('A' - 10);
  575. return c;
  576. }
  577. /** This is a bad number **/
  578. return 0xFF;
  579. }
  580. /*page***************************************************************
  581. g e t _ d r i v e r _ p a r m s
  582. Get the parameters from the driver
  583. Arguments - None
  584. Returns - 0 = OK
  585. else = Error
  586. ********************************************************************/
  587. int get_driver_parms()
  588. {
  589. int rc;
  590. int buffer[4];
  591. /** Set the board number **/
  592. buffer[0] = boardnum;
  593. sr_def = 0;
  594. sr_bcast = 0;
  595. sr_multi = 0;
  596. /** Get the parms **/
  597. if (nwlinkfd != INVALID_HANDLE) {
  598. rc = do_strioctl(nwlinkfd, MIPX_SRGETPARMS, (char *)buffer, 4*sizeof(int), 0);
  599. if (rc) {
  600. /** Get the error code **/
  601. rc = GetLastError();
  602. put_msg (TRUE, MSG_BAD_PARAMETERS, "nwlink");
  603. put_msg (TRUE, get_emsg(rc));
  604. /** Return the error **/
  605. return rc;
  606. }
  607. }
  608. if (isnipxfd != INVALID_HANDLE) {
  609. rc = do_isnipxioctl(isnipxfd, MIPX_SRGETPARMS, (char *)buffer, 4*sizeof(int));
  610. if (rc) {
  611. put_msg (TRUE, MSG_BAD_PARAMETERS, "nwlnkipx");
  612. put_msg (TRUE, get_emsg(rc));
  613. /** Return the error **/
  614. return rc;
  615. }
  616. }
  617. /** Get the variables **/
  618. sr_def = buffer[1];
  619. sr_bcast = buffer[2];
  620. sr_multi = buffer[3];
  621. /** Return OK **/
  622. return 0;
  623. }
  624. /*page***************************************************************
  625. s e t _ d r i v e r _ p a r m s
  626. Set the parameters for the driver
  627. Arguments - None
  628. Returns - 0 = OK
  629. else = Error
  630. ********************************************************************/
  631. int set_driver_parms()
  632. {
  633. int rc;
  634. int buffer[2];
  635. /** Set the DEFAULT parm **/
  636. buffer[0] = boardnum;
  637. buffer[1] = sr_def;
  638. if (nwlinkfd != INVALID_HANDLE) {
  639. rc = do_strioctl(nwlinkfd, MIPX_SRDEF, (char *)buffer, 2 * sizeof(int), 0);
  640. if (rc) {
  641. rc = GetLastError();
  642. put_msg (TRUE, MSG_SET_DEFAULT_ERROR, "nwlink");
  643. put_msg (TRUE, get_emsg(rc));
  644. return rc;
  645. }
  646. }
  647. if (isnipxfd != INVALID_HANDLE) {
  648. rc = do_isnipxioctl(isnipxfd, MIPX_SRDEF, (char *)buffer, 2 * sizeof(int));
  649. if (rc) {
  650. put_msg (TRUE, MSG_SET_DEFAULT_ERROR, "nwlnkipx");
  651. put_msg (TRUE, get_emsg(rc));
  652. return rc;
  653. }
  654. }
  655. /** Set the BROADCAST parm **/
  656. buffer[0] = boardnum;
  657. buffer[1] = sr_bcast;
  658. if (nwlinkfd != INVALID_HANDLE) {
  659. rc = do_strioctl(nwlinkfd, MIPX_SRBCAST, (char *)buffer, 2 * sizeof(int), 0);
  660. if (rc) {
  661. rc = GetLastError();
  662. put_msg (TRUE, MSG_SET_BROADCAST_ERROR, "nwlink");
  663. put_msg (TRUE, get_emsg(rc));
  664. return rc;
  665. }
  666. }
  667. if (isnipxfd != INVALID_HANDLE) {
  668. rc = do_isnipxioctl(isnipxfd, MIPX_SRBCAST, (char *)buffer, 2 * sizeof(int));
  669. if (rc) {
  670. put_msg (TRUE, MSG_SET_BROADCAST_ERROR, "nwlnkipx");
  671. put_msg (TRUE, get_emsg(rc));
  672. return rc;
  673. }
  674. }
  675. /** Set the MULTICAST parm **/
  676. buffer[0] = boardnum;
  677. buffer[1] = sr_multi;
  678. if (nwlinkfd != INVALID_HANDLE) {
  679. rc = do_strioctl(nwlinkfd, MIPX_SRMULTI, (char *)buffer, 2 * sizeof(int), 0);
  680. if (rc) {
  681. rc = GetLastError();
  682. put_msg (TRUE, MSG_SET_MULTICAST_ERROR, "nwlink");
  683. put_msg (TRUE, get_emsg(rc));
  684. return rc;
  685. }
  686. }
  687. if (isnipxfd != INVALID_HANDLE) {
  688. rc = do_isnipxioctl(isnipxfd, MIPX_SRMULTI, (char *)buffer, 2 * sizeof(int));
  689. if (rc) {
  690. put_msg (TRUE, MSG_SET_MULTICAST_ERROR, "nwlnkipx");
  691. put_msg (TRUE, get_emsg(rc));
  692. return rc;
  693. }
  694. }
  695. /** Return OK **/
  696. return 0;
  697. }
  698. /*page***************************************************************
  699. d o _ s t r i o c t l
  700. Do a stream ioctl
  701. Arguments - fd = Handle to put on
  702. cmd = Command to send
  703. datap = Ptr to ctrl buffer
  704. dlen = Ptr to len of data buffer
  705. timout = Timeout value
  706. Returns - 0 = OK
  707. else = Error
  708. ********************************************************************/
  709. int do_strioctl(HANDLE fd, int cmd, char *datap, int dlen, int timout)
  710. {
  711. int rc;
  712. struct strioctl io;
  713. /** Fill out the structure **/
  714. io.ic_cmd = cmd;
  715. io.ic_dp = datap;
  716. io.ic_len = dlen;
  717. io.ic_timout = timout;
  718. /** Issue the ioctl **/
  719. rc = s_ioctl(fd, I_STR, &io);
  720. /** All Done **/
  721. return rc;
  722. }
  723. /*page***************************************************************
  724. r e m o v e _ a d d r e s s
  725. Remove an address from the source routing table.
  726. Arguments - nodep = Ptr to node address to remove
  727. Returns - Does not return
  728. ********************************************************************/
  729. void remove_address(char *nodep)
  730. {
  731. int rc;
  732. int len;
  733. rterem buf;
  734. /** Build the area to send down to the driver **/
  735. buf.rterem_bnum = boardnum;
  736. memcpy(buf.rterem_node, nodep, 6);
  737. len = sizeof(int) + 6;
  738. /** Send the ioctl to remove the address **/
  739. if (nwlinkfd != INVALID_HANDLE) {
  740. rc = do_strioctl(nwlinkfd, MIPX_SRREMOVE, (char *)&buf, len, 0);
  741. if (rc) {
  742. rc = GetLastError();
  743. put_msg (TRUE, MSG_REMOVE_ADDRESS_ERROR, "nwlink");
  744. put_msg (TRUE, get_emsg(rc));
  745. }
  746. }
  747. if (isnipxfd != INVALID_HANDLE) {
  748. rc = do_isnipxioctl(isnipxfd, MIPX_SRREMOVE, (char *)&buf, len);
  749. if (rc) {
  750. put_msg (TRUE, MSG_REMOVE_ADDRESS_ERROR, "nwlnkipx");
  751. if (rc == EINVAL) {
  752. put_msg (TRUE, MSG_ADDRESS_NOT_FOUND);
  753. } else {
  754. put_msg (TRUE, get_emsg(rc));
  755. }
  756. }
  757. }
  758. /** Close up and exit **/
  759. if (isnipxfd != INVALID_HANDLE) NtClose(isnipxfd);
  760. if (nwlinkfd != INVALID_HANDLE) NtClose(nwlinkfd);
  761. if (isnripfd != INVALID_HANDLE) NtClose(isnripfd);
  762. exit(0);
  763. }
  764. /*page***************************************************************
  765. c l e a r _ t a b l e
  766. Clear out the routing table
  767. Arguments - None
  768. Returns - Does not return
  769. ********************************************************************/
  770. void clear_table(void)
  771. {
  772. int rc;
  773. /** Send the ioctl to clear the table **/
  774. if (nwlinkfd != INVALID_HANDLE) {
  775. rc = do_strioctl(nwlinkfd, MIPX_SRCLEAR, (char *)&boardnum, sizeof(int), 0);
  776. if (rc) {
  777. rc= GetLastError();
  778. put_msg (TRUE, MSG_CLEAR_TABLE_ERROR, "nwlink");
  779. put_msg (TRUE, get_emsg(rc));
  780. }
  781. }
  782. if (isnipxfd != INVALID_HANDLE) {
  783. rc = do_isnipxioctl(isnipxfd, MIPX_SRCLEAR, (char *)&boardnum, sizeof(int));
  784. if (rc) {
  785. put_msg (TRUE, MSG_CLEAR_TABLE_ERROR, "nwlnkipx");
  786. put_msg (TRUE, get_emsg(rc));
  787. }
  788. }
  789. /** Close up and exit **/
  790. if (isnipxfd != INVALID_HANDLE) NtClose(isnipxfd);
  791. if (nwlinkfd != INVALID_HANDLE) NtClose(nwlinkfd);
  792. if (isnripfd != INVALID_HANDLE) NtClose(isnripfd);
  793. exit(0);
  794. }
  795. /*
  796. typedef struct _ISN_ACTION_GET_DETAILS {
  797. USHORT NicId; // passed by caller
  798. BOOLEAN BindingSet; // returns TRUE if in set
  799. UCHAR Type; // 1 = lan, 2 = up wan, 3 = down wan
  800. ULONG FrameType; // returns 0 through 3
  801. ULONG NetworkNumber; // returns virtual net if NicId is 0
  802. UCHAR Node[6]; // adapter's MAC address.
  803. WCHAR AdapterName[64]; // terminated with Unicode NULL
  804. } ISN_ACTION_GET_DETAILS, *PISN_ACTION_GET_DETAILS;
  805. */
  806. #define REORDER_ULONG(_Ulong) \
  807. ((((_Ulong) & 0xff000000) >> 24) | \
  808. (((_Ulong) & 0x00ff0000) >> 8) | \
  809. (((_Ulong) & 0x0000ff00) << 8) | \
  810. (((_Ulong) & 0x000000ff) << 24))
  811. void show_ripout(unsigned long netnum) {
  812. int rc;
  813. ISN_ACTION_GET_LOCAL_TARGET Target;
  814. if (isnipxfd != INVALID_HANDLE) {
  815. ZeroMemory (&Target, sizeof (Target));
  816. Target.IpxAddress.NetworkAddress = REORDER_ULONG(netnum);
  817. rc = do_isnipxioctl(isnipxfd, MIPX_LOCALTARGET, (char *)&Target, sizeof(Target));
  818. if (rc)
  819. put_msg (TRUE, MSG_RIPOUT_NOTFOUND);
  820. else
  821. put_msg (TRUE, MSG_RIPOUT_FOUND);
  822. }
  823. exit(0);
  824. }
  825. #define mbtowc(wname, aname) MultiByteToWideChar(CP_ACP,0,aname,-1,wname,1024)
  826. void resolve_guid(char * guidname) {
  827. WCHAR pszName[512], pszGuidName[128];
  828. char * psz;
  829. HANDLE hMpr;
  830. DWORD dwErr;
  831. if (MprConfigServerConnect(NULL, &hMpr) != NO_ERROR)
  832. return;
  833. mbtowc(pszGuidName, guidname);
  834. dwErr = MprConfigGetFriendlyName(hMpr, pszGuidName, pszName, sizeof(pszName));
  835. if (dwErr == NO_ERROR)
  836. put_msg (TRUE, MSG_RESOLVEGUID_OK, pszName);
  837. else
  838. put_msg (TRUE, MSG_RESOLVEGUID_NO, guidname);
  839. MprConfigServerDisconnect(hMpr);
  840. exit(0);
  841. }
  842. void resolve_name(char * name) {
  843. WCHAR pszName[1024], pszGuidName[1024];
  844. char * pszGuid;
  845. DWORD dwErr;
  846. HANDLE hMpr;
  847. if (MprConfigServerConnect(NULL, &hMpr) != NO_ERROR)
  848. return;
  849. // Convert to wc and look up the name
  850. mbtowc (pszName, name);
  851. dwErr = MprConfigGetGuidName(hMpr, pszName, pszGuidName, sizeof(pszGuidName));
  852. if (dwErr == NO_ERROR)
  853. put_msg (TRUE, MSG_RESOLVENAME_OK, pszGuidName);
  854. else
  855. put_msg (TRUE, MSG_RESOLVENAME_NO);
  856. // Cleanup interface map
  857. MprConfigServerDisconnect(hMpr);
  858. exit(0);
  859. }
  860. /*page***************************************************************
  861. p r i n t _ c o n f i g
  862. Prints out the current config
  863. Arguments - None
  864. Returns - Does not return
  865. ********************************************************************/
  866. void print_config(void)
  867. {
  868. int rc;
  869. int nicidcount;
  870. USHORT nicid;
  871. int showlegend = 0;
  872. char nicidbuf[6];
  873. char network[9];
  874. char * frametype;
  875. char node[13];
  876. char special[2];
  877. char adaptername[64];
  878. ISN_ACTION_GET_DETAILS getdetails;
  879. HANDLE hMpr;
  880. DWORD dwErr;
  881. // Initialize the map from guid to interface name
  882. MprConfigServerConnect(NULL, &hMpr);
  883. if (isnipxfd != INVALID_HANDLE) {
  884. /** First query nicid 0 **/
  885. getdetails.NicId = 0;
  886. rc = do_isnipxioctl(isnipxfd, MIPX_CONFIG, (char *)&getdetails, sizeof(getdetails));
  887. if (rc) {
  888. put_msg (TRUE, MSG_QUERY_CONFIG_ERROR, "nwlnkipx");
  889. put_msg (TRUE, get_emsg(rc));
  890. goto errorexit;
  891. }
  892. printf("\n");
  893. put_msg (FALSE, MSG_NET_NUMBER_HDR);
  894. if (getdetails.NetworkNumber != 0) {
  895. sprintf (network, "%.8x", REORDER_ULONG(getdetails.NetworkNumber));
  896. put_msg (FALSE, MSG_SHOW_NET_NUMBER,
  897. "0.",
  898. network,
  899. "None ",
  900. "Internal",
  901. "000000000001",
  902. "");
  903. //put_msg (FALSE, MSG_SHOW_INTERNAL_NET, network);
  904. }
  905. //
  906. // The NicId 0 query returns the total number.
  907. //
  908. nicidcount = getdetails.NicId;
  909. for (nicid = 1; nicid <= nicidcount; nicid++) {
  910. getdetails.NicId = nicid;
  911. rc = do_isnipxioctl(isnipxfd, MIPX_CONFIG, (char *)&getdetails, sizeof(getdetails));
  912. if (rc) {
  913. continue;
  914. }
  915. sprintf (nicidbuf, "%d.", nicid);
  916. sprintf (network, "%.8x", REORDER_ULONG(getdetails.NetworkNumber));
  917. switch (getdetails.FrameType) {
  918. case 0: frametype = load_msg (MSG_ETHERNET_II); break;
  919. case 1: frametype = load_msg (MSG_802_3); break;
  920. case 2: frametype = load_msg (MSG_802_2); break;
  921. case 3: frametype = load_msg (MSG_SNAP); break;
  922. case 4: frametype = load_msg (MSG_ARCNET); break;
  923. default: frametype = load_msg (MSG_UNKNOWN); break;
  924. }
  925. // Translate the adapter name
  926. if (getdetails.Type == 1) { // lan
  927. WCHAR pszName[512];
  928. PWCHAR pszGuid = &(getdetails.AdapterName[0]);
  929. dwErr = MprConfigGetFriendlyName(hMpr, pszGuid, pszName, sizeof(pszName));
  930. if (dwErr == NO_ERROR)
  931. sprintf (adaptername, "%ws", pszName);
  932. else
  933. sprintf (adaptername, "%ws", getdetails.AdapterName);
  934. }
  935. else
  936. sprintf (adaptername, "%ws", getdetails.AdapterName);
  937. sprintf (node, "%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x",
  938. getdetails.Node[0],
  939. getdetails.Node[1],
  940. getdetails.Node[2],
  941. getdetails.Node[3],
  942. getdetails.Node[4],
  943. getdetails.Node[5]);
  944. special[1] = '\0';
  945. if (getdetails.BindingSet) {
  946. special[0] = '*';
  947. showlegend |= 1;
  948. } else if (getdetails.Type == 2) {
  949. special[0] = '+';
  950. showlegend |= 2;
  951. } else if (getdetails.Type == 3) {
  952. special[0] = '-';
  953. showlegend |= 4;
  954. } else {
  955. special[0] = '\0';
  956. }
  957. put_msg (FALSE, MSG_SHOW_NET_NUMBER,
  958. nicidbuf,
  959. network,
  960. frametype,
  961. adaptername,
  962. node,
  963. special);
  964. LocalFree (frametype);
  965. }
  966. if (showlegend) {
  967. put_msg (FALSE, MSG_NET_NUMBER_LEGEND_HDR);
  968. if (showlegend & 1) {
  969. put_msg (FALSE, MSG_LEGEND_BINDING_SET);
  970. }
  971. if (showlegend & 2) {
  972. put_msg (FALSE, MSG_LEGEND_ACTIVE_WAN);
  973. }
  974. if (showlegend & 4) {
  975. put_msg (FALSE, MSG_LEGEND_DOWN_WAN);
  976. }
  977. printf("\n");
  978. }
  979. }
  980. errorexit:
  981. /** Close up and exit **/
  982. // Cleanup interface map
  983. MprConfigServerDisconnect(hMpr);
  984. if (isnipxfd != INVALID_HANDLE) NtClose(isnipxfd);
  985. if (nwlinkfd != INVALID_HANDLE) NtClose(nwlinkfd);
  986. if (isnripfd != INVALID_HANDLE) NtClose(isnripfd);
  987. exit(0);
  988. }
  989. /*page***************************************************************
  990. g e t _ e m s g
  991. Get an error message for an error
  992. Arguments - None
  993. Returns - Does not return
  994. ********************************************************************/
  995. unsigned long get_emsg(int rc)
  996. {
  997. /**
  998. We have 3 defined error codes that can come back.
  999. 1 - EINVAL means that we sent down parameters wrong
  1000. (SHOULD NEVER HAPPEN)
  1001. 2 - ERANGE means that the board number is invalid
  1002. (CAN HAPPEN IF USER ENTERS BAD BOARD)
  1003. 3 - ENOENT means that on remove - the address given
  1004. is not in the source routing table.
  1005. **/
  1006. switch (rc) {
  1007. case EINVAL:
  1008. return MSG_INTERNAL_ERROR;
  1009. case ERANGE:
  1010. return MSG_INVALID_BOARD;
  1011. case ENOENT:
  1012. return MSG_ADDRESS_NOT_FOUND;
  1013. default:
  1014. return MSG_UNKNOWN_ERROR;
  1015. }
  1016. }
  1017. /*page***************************************************************
  1018. d o _ i s n i p x i o c t l
  1019. Do the equivalent of a stream ioctl to isnipx
  1020. Arguments - fd = Handle to put on
  1021. cmd = Command to send
  1022. datap = Ptr to ctrl buffer
  1023. dlen = Ptr to len of data buffer
  1024. Returns - 0 = OK
  1025. else = Error
  1026. ********************************************************************/
  1027. int do_isnipxioctl(HANDLE fd, int cmd, char *datap, int dlen)
  1028. {
  1029. NTSTATUS Status;
  1030. UCHAR buffer[sizeof(NWLINK_ACTION) + sizeof(ISN_ACTION_GET_DETAILS) - 1];
  1031. PNWLINK_ACTION action;
  1032. IO_STATUS_BLOCK IoStatusBlock;
  1033. int rc;
  1034. /** Fill out the structure **/
  1035. action = (PNWLINK_ACTION)buffer;
  1036. action->Header.TransportId = ISN_ACTION_TRANSPORT_ID;
  1037. action->OptionType = NWLINK_OPTION_CONTROL;
  1038. action->BufferLength = sizeof(ULONG) + dlen;
  1039. action->Option = cmd;
  1040. RtlMoveMemory(action->Data, datap, dlen);
  1041. /** Issue the ioctl **/
  1042. Status = NtDeviceIoControlFile(
  1043. fd,
  1044. NULL,
  1045. NULL,
  1046. NULL,
  1047. &IoStatusBlock,
  1048. IOCTL_TDI_ACTION,
  1049. NULL,
  1050. 0,
  1051. action,
  1052. FIELD_OFFSET(NWLINK_ACTION,Data) + dlen);
  1053. if (Status != STATUS_SUCCESS) {
  1054. if (Status == STATUS_INVALID_PARAMETER) {
  1055. rc = ERANGE;
  1056. } else {
  1057. rc = EINVAL;
  1058. }
  1059. } else {
  1060. if (dlen > 0) {
  1061. RtlMoveMemory (datap, action->Data, dlen);
  1062. }
  1063. rc = 0;
  1064. }
  1065. return rc;
  1066. }
  1067. //*****************************************************************************
  1068. //
  1069. // Name: put_msg
  1070. //
  1071. // Description: Reads a message resource, formats it in the current language
  1072. // and displays the message.
  1073. //
  1074. // NOTE: This routine was stolen from net\sockets\tcpcmd\common2\util.c.
  1075. //
  1076. // Parameters: error - TRUE if this is an error message.
  1077. // unsigned long MsgNum: ID of the message resource.
  1078. //
  1079. // Returns: unsigned long: number of characters displayed.
  1080. //
  1081. // History:
  1082. // 01/05/93 JayPh Created.
  1083. //
  1084. //*****************************************************************************
  1085. unsigned long put_msg(BOOLEAN error, unsigned long MsgNum, ... )
  1086. {
  1087. unsigned long msglen;
  1088. char *vp;
  1089. char *oemp;
  1090. va_list arglist;
  1091. va_start( arglist, MsgNum );
  1092. msglen = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
  1093. FORMAT_MESSAGE_FROM_HMODULE,
  1094. NULL,
  1095. MsgNum,
  1096. 0L, // Default country ID.
  1097. (LPTSTR)&vp,
  1098. 0,
  1099. &arglist );
  1100. if ( (msglen == 0) || (vp == NULL))
  1101. {
  1102. return ( 0 );
  1103. }
  1104. oemp = (char *) malloc(msglen*sizeof(char) + 1);
  1105. if (oemp != NULL) {
  1106. CharToOem(vp, oemp);
  1107. fprintf( error ? stderr : stdout, "%s", oemp );
  1108. free(oemp);
  1109. } else {
  1110. printf("Failed to allocate memory of %d bytes\n",msglen*sizeof(char));
  1111. }
  1112. LocalFree( vp );
  1113. return ( msglen );
  1114. }
  1115. //*****************************************************************************
  1116. //
  1117. // Name: load_msg
  1118. //
  1119. // Description: Reads and formats a message resource and returns a pointer
  1120. // to the buffer containing the formatted message. It is the
  1121. // responsibility of the caller to free the buffer.
  1122. //
  1123. // NOTE: This routine was stolen from net\sockets\tcpcmd\common2\util.c.
  1124. //
  1125. // Parameters: unsigned long MsgNum: ID of the message resource.
  1126. //
  1127. // Returns: char *: pointer to the message buffer, NULL if error.
  1128. //
  1129. // History:
  1130. // 01/05/93 JayPh Created.
  1131. //
  1132. //*****************************************************************************
  1133. char *load_msg( unsigned long MsgNum, ... )
  1134. {
  1135. unsigned long msglen;
  1136. char *vp;
  1137. va_list arglist;
  1138. va_start( arglist, MsgNum );
  1139. msglen = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
  1140. FORMAT_MESSAGE_FROM_HMODULE,
  1141. NULL,
  1142. MsgNum,
  1143. 0L, // Default country ID.
  1144. (LPTSTR)&vp,
  1145. 0,
  1146. &arglist );
  1147. if ( msglen == 0 )
  1148. {
  1149. return(0);
  1150. }
  1151. return ( vp );
  1152. }
  1153. #define MAX_NETWORK_INTERFACES 255
  1154. typedef struct router_info
  1155. {
  1156. ULONG NetNumber;
  1157. USHORT TickCount;
  1158. USHORT HopCount;
  1159. USHORT NicId;
  1160. UCHAR InterfaceNumber[10];
  1161. } ROUTER_INFO, *PROUTER_INFO;
  1162. /*page***************************************************************
  1163. s h o w _ r o u t e r _ t a b l e
  1164. Display the IPX routing table
  1165. Arguments - FileHandle = Router File Handle
  1166. IoStatusBlock = Device IO Status Block
  1167. Returns - Does not return
  1168. ********************************************************************/
  1169. VOID
  1170. show_router_table(
  1171. PHANDLE FileHandle,
  1172. PIO_STATUS_BLOCK IoStatusBlock
  1173. )
  1174. {
  1175. SHOW_NIC_INFO nis[MAX_NETWORK_INTERFACES];
  1176. ULONG NetNumber;
  1177. char InterfaceNumber[10];
  1178. NTSTATUS Status;
  1179. USHORT index, i, NumEntries, count;
  1180. char router_entry[128];
  1181. char buffer[32];
  1182. PROUTER_INFO RouterInfo = NULL;
  1183. if (*FileHandle == INVALID_HANDLE) {
  1184. put_msg(TRUE, MSG_IPXROUTER_NOT_STARTED );
  1185. goto exit_show_table;
  1186. }
  1187. /** First get the Network numbers for all interfaces **/
  1188. index = 0;
  1189. while(TRUE) {
  1190. Status = NtDeviceIoControlFile(
  1191. *FileHandle, // HANDLE to File
  1192. NULL, // HANDLE to Event
  1193. NULL, // ApcRoutine
  1194. NULL, // ApcContext
  1195. IoStatusBlock, // IO_STATUS_BLOCK
  1196. IOCTL_IPXROUTER_SHOWNICINFO, // IoControlCode
  1197. &index, // Input Buffer
  1198. sizeof(USHORT), // Input Buffer Length
  1199. &nis[index], // Output Buffer
  1200. sizeof(SHOW_NIC_INFO)); // Output Buffer Length
  1201. if(IoStatusBlock->Status == STATUS_NO_MORE_ENTRIES) {
  1202. break;
  1203. }
  1204. index ++;
  1205. if(Status != STATUS_SUCCESS) {
  1206. sprintf(buffer, "%x", Status);
  1207. put_msg(TRUE, MSG_SHOWSTATS_FAILED, buffer);
  1208. goto exit_show_table;
  1209. }
  1210. if (index >= MAX_NETWORK_INTERFACES) {
  1211. // break out of this loop if there are more than 255 network
  1212. // interfaces because we only have storage for 255.
  1213. break;
  1214. }
  1215. }
  1216. Status = NtDeviceIoControlFile(
  1217. *FileHandle, // HANDLE to File
  1218. NULL, // HANDLE to Event
  1219. NULL, // ApcRoutine
  1220. NULL, // ApcContext
  1221. IoStatusBlock, // IO_STATUS_BLOCK
  1222. IOCTL_IPXROUTER_SNAPROUTES, // IoControlCode
  1223. NULL, // Input Buffer
  1224. 0, // Input Buffer Length
  1225. NULL, // Output Buffer
  1226. 0); // Output Buffer Length
  1227. if (IoStatusBlock->Status != STATUS_SUCCESS) {
  1228. sprintf(buffer, "%x", Status);
  1229. put_msg(TRUE, MSG_SNAPROUTES_FAILED, buffer);
  1230. goto exit_show_table;
  1231. }
  1232. // first determine the number of router table entries to
  1233. // allocate sufficient storage
  1234. NumEntries = 0;
  1235. while(TRUE) {
  1236. Status = NtDeviceIoControlFile(
  1237. *FileHandle, // HANDLE to File
  1238. NULL, // HANDLE to Event
  1239. NULL, // ApcRoutine
  1240. NULL, // ApcContext
  1241. IoStatusBlock, // IO_STATUS_BLOCK
  1242. IOCTL_IPXROUTER_GETNEXTROUTE, // IoControlCode
  1243. NULL, // Input Buffer
  1244. 0, // Input Buffer Length
  1245. &rte, // Output Buffer
  1246. sizeof(IPX_ROUTE_ENTRY)); // Output Buffer Length
  1247. if(IoStatusBlock->Status == STATUS_NO_MORE_ENTRIES) {
  1248. break;
  1249. }
  1250. if(Status != STATUS_SUCCESS) {
  1251. sprintf(buffer,"%x",Status);
  1252. put_msg(TRUE, MSG_GETNEXTROUTE_FAILED, buffer);
  1253. goto exit_show_table;
  1254. }
  1255. NumEntries ++;
  1256. }
  1257. RouterInfo = (PROUTER_INFO) LocalAlloc(LPTR, sizeof(ROUTER_INFO) * NumEntries);
  1258. if(!RouterInfo) {
  1259. put_msg(FALSE, MSG_INSUFFICIENT_MEMORY);
  1260. goto exit_show_table;
  1261. }
  1262. Status = NtDeviceIoControlFile(
  1263. *FileHandle, // HANDLE to File
  1264. NULL, // HANDLE to Event
  1265. NULL, // ApcRoutine
  1266. NULL, // ApcContext
  1267. IoStatusBlock, // IO_STATUS_BLOCK
  1268. IOCTL_IPXROUTER_SNAPROUTES, // IoControlCode
  1269. NULL, // Input Buffer
  1270. 0, // Input Buffer Length
  1271. NULL, // Output Buffer
  1272. 0); // Output Buffer Length
  1273. if (IoStatusBlock->Status != STATUS_SUCCESS) {
  1274. sprintf(buffer, "%x", Status);
  1275. put_msg(TRUE, MSG_SNAPROUTES_FAILED, buffer);
  1276. goto exit_show_table;
  1277. }
  1278. index = 0;
  1279. while(TRUE) {
  1280. Status = NtDeviceIoControlFile(
  1281. *FileHandle, // HANDLE to File
  1282. NULL, // HANDLE to Event
  1283. NULL, // ApcRoutine
  1284. NULL, // ApcContext
  1285. IoStatusBlock, // IO_STATUS_BLOCK
  1286. IOCTL_IPXROUTER_GETNEXTROUTE, // IoControlCode
  1287. NULL, // Input Buffer
  1288. 0, // Input Buffer Length
  1289. &rte, // Output Buffer
  1290. sizeof(IPX_ROUTE_ENTRY)); // Output Buffer Length
  1291. if(IoStatusBlock->Status == STATUS_NO_MORE_ENTRIES) {
  1292. break;
  1293. }
  1294. if(Status != STATUS_SUCCESS) {
  1295. sprintf(buffer,"%x",Status);
  1296. put_msg(TRUE, MSG_GETNEXTROUTE_FAILED, buffer);
  1297. goto exit_show_table;
  1298. }
  1299. // make sure we don't exceed the number of entries
  1300. if (index > NumEntries) {
  1301. break;
  1302. }
  1303. // get net nr in "on the wire" order
  1304. GETLONG2ULONG(&(RouterInfo[index].NetNumber), rte.Network);
  1305. // find out the matching Network number based on NIC ID
  1306. for(i=0; i < MAX_NETWORK_INTERFACES; i++) {
  1307. if(rte.NicId == nis[i].NicId) {
  1308. sprintf(RouterInfo[index].InterfaceNumber, "%.2x%.2x%.2x%.2x",
  1309. nis[i].Network[0],
  1310. nis[i].Network[1],
  1311. nis[i].Network[2],
  1312. nis[i].Network[3]);
  1313. break;
  1314. }
  1315. }
  1316. RouterInfo[index].TickCount = rte.TickCount;
  1317. RouterInfo[index].HopCount = rte.HopCount;
  1318. RouterInfo[index].NicId = rte.NicId;
  1319. index++;
  1320. }
  1321. // Now sort the entries by net number
  1322. qsort( (void*) RouterInfo,
  1323. NumEntries,
  1324. sizeof(ROUTER_INFO),
  1325. (PQSORT_COMPARE)CompareNetNumber );
  1326. put_msg(FALSE, MSG_ROUTER_TABLE_HEADER);
  1327. for(index =0, count = 0; index < NumEntries; index++, count++)
  1328. {
  1329. if (count > 50) {
  1330. count = 0;
  1331. // display router table header every 25 entries
  1332. // to make reading the table easier.
  1333. put_msg(FALSE, MSG_ROUTER_TABLE_HEADER);
  1334. }
  1335. printf("%.8x %6d %2d %-16s %d\n",
  1336. RouterInfo[index].NetNumber,
  1337. RouterInfo[index].TickCount,
  1338. RouterInfo[index].HopCount,
  1339. RouterInfo[index].InterfaceNumber,
  1340. RouterInfo[index].NicId );
  1341. }
  1342. /** Close up and exit **/
  1343. exit_show_table:
  1344. if (RouterInfo) LocalFree(RouterInfo);
  1345. if (isnipxfd != INVALID_HANDLE) NtClose(isnipxfd);
  1346. if (nwlinkfd != INVALID_HANDLE) NtClose(nwlinkfd);
  1347. if (isnripfd != INVALID_HANDLE) NtClose(isnripfd);
  1348. exit(0);
  1349. }
  1350. int __cdecl CompareNetNumber( void * p0, void * p1)
  1351. {
  1352. PROUTER_INFO pLeft = (PROUTER_INFO) p0;
  1353. PROUTER_INFO pRight = (PROUTER_INFO) p1;
  1354. if(pLeft->NetNumber == pRight->NetNumber)
  1355. return(0);
  1356. if(pLeft->NetNumber > pRight->NetNumber)
  1357. return(1);
  1358. else
  1359. return(-1);
  1360. }
  1361. PUCHAR DeviceType[2] = { "LAN", "WAN" };
  1362. PUCHAR NicState[4] = { "CLOSED", "CLOSING", "ACTIVE", "PENDING_OPEN" };
  1363. /*page***************************************************************
  1364. s h o w _ s t a t s
  1365. Displays IPX internal routing statistics
  1366. Arguments - FileHandle = Router File Handle
  1367. IoStatusBlock = Device IO Status Block
  1368. Returns - Does not return
  1369. ********************************************************************/
  1370. VOID
  1371. show_stats(
  1372. PHANDLE FileHandle,
  1373. PIO_STATUS_BLOCK IoStatusBlock
  1374. )
  1375. {
  1376. SHOW_NIC_INFO nis;
  1377. USHORT index, i;
  1378. char NicId[4];
  1379. char NetworkNumber[10];
  1380. char RipRcvd[32], RipSent[32];
  1381. char RoutedRcvd[32], RoutedSent[32];
  1382. char Type20Rcvd[32], Type20Sent[32];
  1383. char BadRcvd[32];
  1384. char buffer[32];
  1385. NTSTATUS Status;
  1386. if (*FileHandle == INVALID_HANDLE) {
  1387. put_msg(TRUE, MSG_IPXROUTER_NOT_STARTED );
  1388. goto end_stats;
  1389. }
  1390. index = 0;
  1391. while(TRUE) {
  1392. Status = NtDeviceIoControlFile(
  1393. *FileHandle, // HANDLE to File
  1394. NULL, // HANDLE to Event
  1395. NULL, // ApcRoutine
  1396. NULL, // ApcContext
  1397. IoStatusBlock, // IO_STATUS_BLOCK
  1398. IOCTL_IPXROUTER_SHOWNICINFO, // IoControlCode
  1399. &index, // Input Buffer
  1400. sizeof(USHORT), // Input Buffer Length
  1401. &nis, // Output Buffer
  1402. sizeof(nis)); // Output Buffer Length
  1403. if(IoStatusBlock->Status == STATUS_NO_MORE_ENTRIES) {
  1404. goto end_stats;
  1405. }
  1406. index ++;
  1407. if(Status != STATUS_SUCCESS) {
  1408. sprintf(buffer, "%x", Status);
  1409. put_msg(TRUE, MSG_SHOWSTATS_FAILED, buffer);
  1410. goto end_stats;
  1411. }
  1412. sprintf(NicId, "%d", nis.NicId);
  1413. sprintf(NetworkNumber,
  1414. "%.2x%.2x%.2x%.2x",
  1415. nis.Network[0],
  1416. nis.Network[1],
  1417. nis.Network[2],
  1418. nis.Network[3]);
  1419. sprintf(RipRcvd, "%-8d", nis.StatRipReceived);
  1420. sprintf(RipSent, "%-8d", nis.StatRipSent);
  1421. sprintf(RoutedRcvd, "%-8d", nis.StatRoutedReceived);
  1422. sprintf(RoutedSent, "%-8d", nis.StatRoutedSent);
  1423. sprintf(Type20Rcvd, "%-8d", nis.StatType20Received);
  1424. sprintf(Type20Sent, "%-8d", nis.StatType20Sent);
  1425. sprintf(BadRcvd, "%-8d", nis.StatBadReceived);
  1426. put_msg(FALSE,
  1427. MSG_SHOW_STATISTICS,
  1428. NicId,
  1429. NetworkNumber,
  1430. RipRcvd,
  1431. RipSent,
  1432. Type20Rcvd,
  1433. Type20Sent,
  1434. RoutedRcvd,
  1435. RoutedSent,
  1436. BadRcvd);
  1437. }
  1438. /** Close up and exit **/
  1439. end_stats:
  1440. if (isnipxfd != INVALID_HANDLE) NtClose(isnipxfd);
  1441. if (nwlinkfd != INVALID_HANDLE) NtClose(nwlinkfd);
  1442. if (isnripfd != INVALID_HANDLE) NtClose(isnripfd);
  1443. exit(0);
  1444. }
  1445. /*page***************************************************************
  1446. c l e a r _ s t a t s
  1447. Clears the IPX internal routing statistics
  1448. Arguments - FileHandle = Router File Handle
  1449. IoStatusBlock = Device IO Status Block
  1450. Returns - Does not return
  1451. ********************************************************************/
  1452. VOID
  1453. clear_stats(
  1454. PHANDLE FileHandle,
  1455. PIO_STATUS_BLOCK IoStatusBlock
  1456. )
  1457. {
  1458. NTSTATUS Status;
  1459. char buffer[32];
  1460. if (*FileHandle == INVALID_HANDLE) {
  1461. put_msg(TRUE, MSG_IPXROUTER_NOT_STARTED );
  1462. goto end_clearstats;
  1463. }
  1464. Status = NtDeviceIoControlFile(
  1465. *FileHandle, // HANDLE to File
  1466. NULL, // HANDLE to Event
  1467. NULL, // ApcRoutine
  1468. NULL, // ApcContext
  1469. IoStatusBlock, // IO_STATUS_BLOCK
  1470. IOCTL_IPXROUTER_ZERONICSTATISTICS, // IoControlCode
  1471. NULL, // Input Buffer
  1472. 0, // Input Buffer Length
  1473. NULL, // Output Buffer
  1474. 0); // Output Buffer Length
  1475. if(Status != STATUS_SUCCESS) {
  1476. sprintf(buffer, "%x", Status);
  1477. put_msg(TRUE, MSG_CLEAR_STATS_FAILED, buffer);
  1478. }
  1479. /** Close up and exit **/
  1480. end_clearstats:
  1481. if (isnipxfd != INVALID_HANDLE) NtClose(isnipxfd);
  1482. if (nwlinkfd != INVALID_HANDLE) NtClose(nwlinkfd);
  1483. if (isnripfd != INVALID_HANDLE) NtClose(isnripfd);
  1484. exit(0);
  1485. }
  1486. typedef struct server_info
  1487. {
  1488. USHORT ObjectType;
  1489. UCHAR ObjectName[100];
  1490. UCHAR IpxAddress[12];
  1491. } SERVER_INFO, *PSERVER_INFO;
  1492. /*page***************************************************************
  1493. s h o w _ s e r v e r s
  1494. Display the servers from the SAP table
  1495. Arguments - servertype = Type of servers to display
  1496. Defaults to show all server types
  1497. Returns - Does not return
  1498. ********************************************************************/
  1499. VOID
  1500. show_servers(int servertype)
  1501. {
  1502. INT rc;
  1503. ULONG ObjectID = 0xFFFFFFFF;
  1504. UCHAR ObjectName[100];
  1505. USHORT ObjectType;
  1506. USHORT ScanType = (USHORT) servertype;
  1507. UCHAR IpxAddress[12];
  1508. USHORT i;
  1509. USHORT index, count, NumServers;
  1510. PSERVER_INFO ServerInfo = NULL;
  1511. if(rc = SapLibInit() != SAPRETURN_SUCCESS) {
  1512. put_msg(TRUE, MSG_SAP_NOT_STARTED);
  1513. goto show_servers_end;
  1514. }
  1515. memset(&ObjectName, 0, 100);
  1516. // find out how many servers are there so that we can allocate
  1517. // sufficient storage
  1518. NumServers = 0;
  1519. while((rc = SapScanObject(&ObjectID,
  1520. ObjectName,
  1521. &ObjectType,
  1522. ScanType)) == SAPRETURN_SUCCESS)
  1523. {
  1524. NumServers++;
  1525. }
  1526. ServerInfo = (PSERVER_INFO) LocalAlloc(LPTR, sizeof(SERVER_INFO) * NumServers);
  1527. if(!ServerInfo)
  1528. {
  1529. put_msg(FALSE, MSG_INSUFFICIENT_MEMORY);
  1530. goto show_servers_end;
  1531. }
  1532. index = 0;
  1533. ObjectID = 0xFFFFFFFF;
  1534. while((rc = SapScanObject(&ObjectID,
  1535. ObjectName,
  1536. &ObjectType,
  1537. ScanType)) == SAPRETURN_SUCCESS)
  1538. {
  1539. if (index >= NumServers) {
  1540. break;
  1541. }
  1542. // get object address
  1543. SapGetObjectName(ObjectID,
  1544. ObjectName,
  1545. &ObjectType,
  1546. IpxAddress);
  1547. ServerInfo[index].ObjectType = ObjectType;
  1548. strcpy(ServerInfo[index].ObjectName, ObjectName);
  1549. CopyMemory(ServerInfo[index].IpxAddress, IpxAddress, 12);
  1550. index++;
  1551. }
  1552. // Now sort the entries by server name
  1553. qsort( (void*) ServerInfo,
  1554. NumServers,
  1555. sizeof(SERVER_INFO),
  1556. (PQSORT_COMPARE)CompareServerNames );
  1557. if(servertype == SHOW_ALL_SERVERS)
  1558. put_msg(FALSE, MSG_SHOW_ALL_SERVERS_HEADER);
  1559. else
  1560. put_msg(FALSE, MSG_SHOW_SPECIFIC_SERVER_HEADER);
  1561. for(index = 0, count = 0; index < NumServers; index++, count++)
  1562. {
  1563. if (count > 50) {
  1564. // write the table header for every 50 entries
  1565. // to make this more readable.
  1566. count = 0;
  1567. if(servertype == SHOW_ALL_SERVERS)
  1568. put_msg(FALSE, MSG_SHOW_ALL_SERVERS_HEADER);
  1569. else
  1570. put_msg(FALSE, MSG_SHOW_SPECIFIC_SERVER_HEADER);
  1571. }
  1572. for(i=0; i<4; i++) {
  1573. printf("%.2x", ServerInfo[index].IpxAddress[i]);
  1574. }
  1575. printf(".");
  1576. for(i=4; i<10; i++) {
  1577. printf("%.2x", ServerInfo[index].IpxAddress[i]);
  1578. }
  1579. if(servertype == SHOW_ALL_SERVERS) {
  1580. printf(" %-6d", ServerInfo[index].ObjectType);
  1581. }
  1582. printf(" %s\n", ServerInfo[index].ObjectName);
  1583. }
  1584. /** Close up and exit **/
  1585. show_servers_end:
  1586. if (ServerInfo) LocalFree(ServerInfo);
  1587. if (isnipxfd != INVALID_HANDLE) NtClose(isnipxfd);
  1588. if (nwlinkfd != INVALID_HANDLE) NtClose(nwlinkfd);
  1589. if (isnripfd != INVALID_HANDLE) NtClose(isnripfd);
  1590. exit(0);
  1591. }
  1592. int __cdecl CompareServerNames( void * p0, void * p1)
  1593. {
  1594. PSERVER_INFO pLeft = (PSERVER_INFO) p0;
  1595. PSERVER_INFO pRight = (PSERVER_INFO) p1;
  1596. return(strcmp(pLeft->ObjectName, pRight->ObjectName));
  1597. }