home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / netds / winsock / nwlink / ping / dos / dosping.c
Encoding:
C/C++ Source or Header  |  1993-06-30  |  15.2 KB  |  601 lines

  1. /*=====================================================================
  2. P I N G . C
  3.  
  4. This is the DOS side ping program.  It uses Novell's IPX/SPX APIs,
  5. requiring their SDK. It will send/receive 1-n IPX packets.
  6. ======================================================================*/
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <conio.h>
  11. #include <nxtdos.h>
  12.  
  13. #define TIMER (unsigned long far *) 0x0000046cL
  14.  
  15. char *progname;
  16. IPXHeader *ipx;
  17. int send_socket=0;
  18. int recv_socket;
  19. int datasize = 1;
  20. ECB send_ecb; 
  21. ECB recv_ecb[10];
  22. char mynodeaddr[6];
  23. char sendb[2048];
  24. char recvb[2048];
  25.  
  26. int ptype = 4;
  27. int niters = 1;
  28.  
  29. /**
  30.     This is the address we try to send to.  When
  31.     we find a server, this address is replaced by the address
  32.     of the exact server.  The address is made up of:
  33.     bytes 1-4    = network number
  34.     bytes 5-10   = node number
  35.     bytes 11-12  = socket address
  36.  
  37. **/
  38.  
  39. char destaddr[12] = {
  40.     0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x30, 0x00
  41. };
  42.  
  43. /** Function Prototypes **/
  44.  
  45. void   hang_recvs(void);
  46. void   cancel_recvs(void);
  47. void   do_recv(int);
  48. int    get_recv(void);
  49. void   find_a_server(void);
  50. void   print_address(char *);
  51. void   print_network(char *);
  52. void   print_nodeaddr(char *);
  53. void   parse_cmd_line(int, char **);
  54. void   swap_dwf(char *);
  55. char * get_node_number(char * cmd);
  56. char * get_network_number(char * cmd);
  57. /********************************************************************
  58. m a i n
  59. *********************************************************************/
  60. int main(int argc, char **argv)
  61. {
  62.     char *p;
  63.     unsigned long start = *TIMER;
  64.     unsigned long end;
  65.     int cnt = 0;
  66.     long sendpkt = 0L;
  67.     long recvpkt = 0L;
  68.     int ttime;
  69.     float total = 0;
  70.  
  71.     progname = *argv;
  72.     for (p = progname; *p; p++) {
  73.     if (*p == '\\')
  74.     progname = p + 1;
  75.     }
  76.  
  77.     /** Make sure IPX is loaded **/
  78.  
  79.     if (IPXInitialize()) {
  80.     printf("%s: IPX IS NOT LOADED\n", progname);
  81.     exit(1);
  82.     }
  83.     recv_socket = *(short *)(destaddr + 10);
  84.     parse_cmd_line(argc, argv);
  85.     print_network(destaddr);
  86.     print_nodeaddr(destaddr + 4);
  87.     printf("packet type:    %d\n",ptype);
  88.     printf("datasize:       %d\n", datasize);
  89.     printf("n iterations:   %d\n", niters);    
  90.     
  91.  
  92.  
  93.     if (IPXOpenSocket(&send_socket, 0)) {
  94.     printf("%s: ERROR: unable to open socket\n", progname);
  95.     exit(1);
  96.     }
  97.     recv_socket = send_socket;
  98.     if (IPXGetLocalTarget(destaddr, send_ecb.immediateAddress, &ttime)) {
  99.     printf("%s: ERROR: unable to get local target\n", progname);
  100.     exit(1);
  101.     }
  102.  
  103.     memcpy(mynodeaddr, send_ecb.immediateAddress, 6);
  104.  
  105.     /** Go find a server **/
  106.  
  107.     find_a_server(); 
  108.     hang_recvs();
  109.  
  110.  
  111.     /** Do # iterations (default = 1) **/
  112.     while (cnt < niters) {
  113.         int rcv;
  114.     /** send a packet **/
  115.     *(sendb + 5) = ptype;
  116.         memcpy(sendb + 6, destaddr, 12);
  117.         memcpy(send_ecb.immediateAddress, mynodeaddr, 6);
  118.         send_ecb.socketNumber = send_socket;
  119.         send_ecb.fragmentCount = 1;
  120.         send_ecb.fragmentDescriptor[0].address = sendb;
  121.         send_ecb.fragmentDescriptor[0].size = 30 + datasize;
  122.  
  123.     IPXSendPacket(&send_ecb);
  124.  
  125.     while (send_ecb.inUseFlag) /* wait for it to finish */
  126.         ;
  127.  
  128.     if (send_ecb.completionCode) {
  129.         cancel_recvs();
  130.             IPXCloseSocket(send_socket);
  131.             printf("%s: Error sending packet: %d\n", progname, send_ecb.completionCode);
  132.             exit(1);
  133.         }
  134.  
  135.         sendpkt++;
  136.         total += 30 + datasize;     /* Count the bytes */
  137.         printf("\rSend packet Number %d ", sendpkt);
  138.  
  139.         if ((rcv = get_recv()) == -1)
  140.             goto EXIT;
  141.  
  142.         do_recv(rcv);
  143.         total += 30 + datasize;     /* Count the bytes */
  144.  
  145.         cnt++;
  146.         recvpkt++;
  147.         printf(": Recv packet Number %d ", recvpkt);
  148.     }
  149.  
  150.     /** We did 1000 packets - print KB per second **/
  151. EXIT:
  152.     end = *TIMER;
  153.     end = (end - start) / 18.2; /* Num seconds it took */
  154.  
  155.     total = (float)((total / 1024.0) / end);
  156.  
  157.     /** All done - cancel recvs and exit **/
  158.     cancel_recvs();
  159.     IPXCloseSocket(send_socket);
  160.     printf("\n%ld packets \n", recvpkt);
  161.     if (recvpkt)
  162.     printf("Average time per iteration: %5.3f\n",total/recvpkt);
  163.     exit(0);
  164. }
  165.  
  166. /*page**************************************************************
  167.     h a n g _ r e c v s
  168.  
  169.     Arguments - None
  170.  
  171.     Returns - nothing
  172. *******************************************************************/
  173. void hang_recvs(void)
  174. {
  175.     int i;
  176.  
  177.     for (i = 0; i < 10; i++) {
  178.  
  179.     /** Don't hang recv on one that is already hung **/
  180.  
  181.     if (recv_ecb[i].inUseFlag)
  182.         continue;
  183.  
  184.     /** Hang a recv **/
  185.  
  186.     memset(&recv_ecb[i], 0, sizeof(ECB));
  187.     recv_ecb[i].socketNumber = recv_socket;
  188.     recv_ecb[i].fragmentCount = 1;
  189.     recv_ecb[i].fragmentDescriptor[0].address = recvb;
  190.     recv_ecb[i].fragmentDescriptor[0].size = 2048;
  191.     IPXListenForPacket(&recv_ecb[i]);
  192.     }
  193.  
  194.     /** All done **/
  195.  
  196.     return;
  197. }
  198.  
  199. /*page**************************************************************
  200.     c a n c e l _ r e c v s
  201.  
  202.     Arguments - None
  203.  
  204.     Returns - nothing
  205. *******************************************************************/
  206. void cancel_recvs(void)
  207. {
  208.     int i;
  209.  
  210.     for (i = 0; i < 10; i++) {
  211.  
  212.     /** If recv not in use - skip it **/
  213.  
  214.     if (!recv_ecb[i].inUseFlag)
  215.         continue;
  216.  
  217.     /** Cancel the recv **/
  218.  
  219.     IPXCancelEvent(&recv_ecb[i]);
  220.     }
  221.  
  222.     /** All done **/
  223.  
  224.     return;
  225. }
  226.  
  227. /*page**************************************************************
  228.     d o _ r e c v
  229.  
  230.     Arguments - i = recv index to hang
  231.  
  232.     Returns - nothing
  233. *******************************************************************/
  234. void do_recv(int i)
  235. {
  236.     memset(&recv_ecb[i], 0, sizeof(ECB));
  237.     recv_ecb[i].socketNumber = recv_socket;
  238.     recv_ecb[i].fragmentCount = 1;
  239.     recv_ecb[i].fragmentDescriptor[0].address = recvb;
  240.     recv_ecb[i].fragmentDescriptor[0].size = 2048;
  241.     IPXListenForPacket(&recv_ecb[i]);
  242.     return;
  243. }
  244.  
  245. /*page**************************************************************
  246.     g e t _ r e c v
  247.  
  248.     Arguments - none
  249.  
  250.     Returns - -1 = User hit a key
  251.           else = recv index that was hit
  252. *******************************************************************/
  253. int get_recv(void)
  254. {
  255.     int i;
  256.  
  257.     /** **/
  258.  
  259.     while (!kbhit()) {
  260.     for (i = 0; i < 10; i++) {
  261.         if (!recv_ecb[i].inUseFlag)
  262.         return i;
  263.         }                        
  264. //      try resending the bugger...maybe we be out of synch?..bug,bug,bug???    
  265.     IPXSendPacket(&send_ecb);           
  266.     }
  267.  
  268.     /** Return that user hit a key **/
  269.  
  270.     return -1;
  271. }
  272.  
  273. /*******************************************************************
  274. function name:      f i n d _ a _ s e r v e r
  275.     Description:    make sure can find the machine we want to send to
  276.     Arguments:      none
  277.     Returns:        none
  278. *********************************************************************/
  279. void find_a_server(void)
  280. {
  281.     long start;
  282.     long end;
  283.     ECB send_ecb;
  284.     ECB recv_ecb;
  285.  
  286.     /** Setup the recv ecb and listen for a packet **/
  287.  
  288.     memset(&recv_ecb, 0, sizeof(ECB));
  289.     recv_ecb.socketNumber = recv_socket;
  290.     recv_ecb.fragmentCount = 1;
  291.     recv_ecb.fragmentDescriptor[0].address = recvb;
  292.     recv_ecb.fragmentDescriptor[0].size = 31;
  293.     IPXListenForPacket(&recv_ecb);
  294.  
  295.     memset(&send_ecb, 0, sizeof(ECB));
  296.     memcpy(sendb + 6, destaddr, 12);
  297.     send_ecb.socketNumber = send_socket;
  298.     memcpy(send_ecb.immediateAddress, mynodeaddr, 6);
  299.     send_ecb.fragmentCount = 1;
  300.     send_ecb.fragmentDescriptor[0].address = sendb;
  301.     send_ecb.fragmentDescriptor[0].size = 31;
  302.  
  303.     IPXSendPacket(&send_ecb);
  304.  
  305.     while (send_ecb.inUseFlag && !kbhit())
  306.     ;
  307.  
  308.     if (send_ecb.completionCode) {
  309.     printf("%s: ERROR: send completion code 0x%02x\n", progname, send_ecb.completionCode);
  310.     exit(1);
  311.     }
  312.  
  313.     /** Wait awhile for the recv to pay off **/
  314.  
  315.     start = *TIMER;
  316.  
  317.     while (recv_ecb.inUseFlag && !kbhit() && (*TIMER - start) < 180L)
  318.     ;
  319.     end = *TIMER;
  320.  
  321.     /** If we timed out - then we couldn't find a server **/
  322.  
  323.     if (end - start >= 180L) {
  324.     IPXCancelEvent(&recv_ecb);
  325.     IPXCloseSocket(send_socket);
  326.     printf("%s: Unable to find a server\n", progname);
  327.     exit(1);
  328.     }
  329.  
  330.     /** If recv still in use - error **/
  331.  
  332.     if (recv_ecb.inUseFlag) {
  333.     IPXCancelEvent(&recv_ecb);
  334.     IPXCloseSocket(send_socket);
  335.     printf("%s: Program terminated by a keystroke\n", progname);
  336.     exit(1);
  337.     }
  338.  
  339.     /** If recv error - clean up and exit **/
  340.  
  341.     if (recv_ecb.completionCode) {
  342.     IPXCancelEvent(&recv_ecb);
  343.     IPXCloseSocket(send_socket);
  344.     printf("%s: Error receiving packet: %d\n", progname, recv_ecb.completionCode);
  345.     exit(1);
  346.     }
  347.  
  348.     /** Get the server address and print it out **/
  349.  
  350.     memcpy(destaddr, recvb + 18, 12);   /* Set the address to send to */
  351.     memcpy(mynodeaddr, recv_ecb.immediateAddress, 6);
  352.     printf("Found server: ");
  353.     print_address(destaddr);
  354.  
  355.     /** All done **/
  356.  
  357.     return;
  358. }
  359.  
  360. /********************************************************************
  361.     p r i n t _ a d d r e s s
  362.  
  363.     Arguments - netaddr = ptr to 14 bytes address to print
  364.  
  365.     Returns - nothing
  366. *********************************************************************/
  367. void print_address(char *netaddr)
  368. {
  369.     int i;
  370.  
  371.     for (i = 0; i < 12; i++) {
  372.     if ((i == 4) || (i == 10))
  373.         printf(" ");
  374.     printf("%02X", (unsigned char) *(netaddr + i));
  375.     }
  376.     printf("\n");
  377.     return;
  378. }
  379.  
  380. void print_network(char *p)
  381. {
  382.     int i;
  383.     printf("Network Number: ");
  384.     for (i = 0; i < 4; i++)
  385.     printf("%02X", (unsigned char) *p++);
  386.     printf("\n");
  387.     return;
  388. }
  389.  
  390. void print_nodeaddr(char *p)
  391. {
  392.     int i;
  393.  
  394.     printf("Node Address:   ");
  395.     for (i = 0; i < 6; i++)
  396.     printf("%02X", (unsigned char) *p++);
  397.     printf("\n");
  398.     return;
  399. }
  400.  
  401. /*-----------------------------------------------------------------
  402. function name: parse_cmd_line
  403. Description:
  404.     Parse the command line for the parameters and host name.
  405. Arguments:     
  406.        -i <number of iterations>
  407.        -p <packet type>
  408.        -d <data size>
  409.       NOTE: must be < frame size - 14 (MAC length) - 30 (IPX header)
  410.        -n <network number>
  411.       NOTE: you can ignore this if on the same subnet.  Must be 4 hex
  412.         bytes
  413.        -a <destination address>
  414.       NOTE: must be 6 hex bytes representing the physical NIC address of
  415.         the remote machine.
  416.        -s <socket>
  417.       Two byte socket number
  418. Returns:        Nothing
  419. ----------------------------------------------------------------------*/
  420. void parse_cmd_line(int argc, char **argv)
  421. {
  422.     short socket;
  423.  
  424.     argv++;                      /* skip to first arg */
  425.     while (--argc) {             /* do all args */
  426.     if (**argv == '-') {
  427.         ++(*argv);
  428.         switch(tolower(**argv)) {
  429.         case 'i':
  430.             niters = atoi(++(*argv));
  431.             if (niters < 0) 
  432.                niters = 1;
  433.             break;   
  434.         case 'p':
  435.             ptype = atoi(++(*argv));
  436.             if (ptype < 0 || ptype > 255) {
  437.             ptype = 4;
  438.             printf("%s: Invalid packet type.  Setting to default = %d\n",
  439.             progname,ptype);
  440.             }
  441.             break;
  442.         case 'd':  /*amount of data to send in a frame */
  443.             datasize = atoi(++(*argv));
  444.             if (!datasize) {
  445.             datasize = 1;
  446.             printf("%s: Datasize cannot be zero. Setting to default = 1\n", progname);
  447.             }
  448.             break;
  449.         case 's':  /* socket number, default = 0x3000 */
  450.             socket = (short)strtol(++(*argv), NULL, 16);
  451.             printf("New socket = 0x%x\n", socket);
  452.             *(short *)(destaddr + 10) = socket;
  453.             swap_dwf(destaddr + 10);
  454.             break;
  455.         case 'n':  /* network number, default = local net (= 0) */
  456.             ++(*argv);
  457.             memcpy(destaddr, get_network_number(*argv),4);
  458.             if (destaddr[0] == 'X') {
  459.             printf("\n****!\n%s is an incorrect net number.\n****!\n", *argv);
  460.             printf("%s E.G.: -nAABBCCDD (I.E.: 8 hex digits)\n");
  461.             exit(1);
  462.             }
  463.             break;
  464.         case 'a': /* remote address, have to know this */
  465.             ++(*argv);
  466.             memcpy(destaddr+4, get_node_number(*argv), 6);
  467.             if (*(destaddr+4) == 'X') {
  468.                printf("\n****!\n%s is an incorrect Node address.\n****!\n", *argv);
  469.                printf("\n E.G.: -a 023C8DAADDCC (12 hex digits)\n");
  470.                exit(1);
  471.             }
  472.             break;
  473.         default:
  474.             printf("%s [-p] [-d] [-nxxxxxxxx] [-axxxxxxxxxxxx] [-sx]\n", progname);
  475.             printf("     -p - packet type\n");
  476.             printf("     -d - data size\n");
  477.             printf("     -n - network number (in hex)\n");
  478.             printf("     -a - address (in hex)\n");
  479.             printf("     -s - socket number (in hex)\n");
  480.             exit(0);
  481.         }
  482.         argv++;
  483.     }
  484.     }
  485.     return;
  486. }
  487. /**********************************************************************
  488.     g e t _ h e x _ b y t e
  489.  
  490.     Converts the character passed in to a hexadecimal nibble.
  491.  
  492.     Arguments:    char    character to convert
  493.  
  494.     Returns:      UCHAR   hex nibble
  495. **************************************************************************/
  496. char get_hex_byte(char ch)
  497. {
  498.     if (ch >= '0' && ch <= '9')
  499.     return (ch - '0');
  500.  
  501.     if (ch >= 'A' && ch <= 'F')
  502.     return ((ch - 'A') + 0x0A);
  503.  
  504.     return -1;
  505. }
  506. /**********************************************************************
  507.     g e t _ h e x _ s t r i n g
  508.  
  509.     Reads in a character string containing hex digits and converts
  510.     it to a hexadecimal number.
  511.  
  512.     Arguments:    src   => source string to convert
  513.           dest  => destination for hex number
  514.           num   => number of chars to convert
  515.  
  516.     Returns:      nothing
  517. **************************************************************************/
  518. char get_hex_string(char * src, char * dest, int num)
  519. {
  520.     char *   q = src;
  521.     char     hexbyte1,hexbyte2;
  522.  
  523.     strupr(q);
  524.     while (num--)
  525.       {hexbyte1 = get_hex_byte(*q++);
  526.        hexbyte2 = get_hex_byte(*q++);
  527.        if ( (hexbyte1 < 0) || (hexbyte2 < 0) )
  528.       return -1;
  529.        *dest++ = (hexbyte1 << 4) + hexbyte2;
  530.       }
  531.  
  532.     return(0);
  533. }
  534. /*************************************************************************
  535.     g e t _ n o d e _ n u m b e r
  536.  
  537.     Reads a node number from the given string.
  538.  
  539.     Arguments:    cmd  => string to read from
  540.  
  541.     Returns:      hex node number
  542. **************************************************************************/
  543. char * get_node_number(char * cmd)
  544. {
  545.     static char hex_num[6];
  546.  
  547.     memset(hex_num, 0, 6);
  548.  
  549.     if (strlen(cmd) != 12){
  550.     hex_num[0] = 'X';
  551.     return hex_num;
  552.        }
  553.  
  554.     if (get_hex_string(cmd, hex_num, 6) < 0)
  555.     hex_num[0] = 'X';
  556.     return hex_num;
  557. }
  558. /**************************************************************************
  559.     g e t _ n e t w o k _ n u m b e r
  560.  
  561.     Reads a network number from the given string.
  562.  
  563.     Arguments:    cmd   string to read from
  564.  
  565.     Returns:      hex network number
  566. **************************************************************************/
  567. char * get_network_number(char * cmd)
  568. {
  569.     static char hex_num[4];
  570.  
  571.     memset(hex_num, 0, 4);
  572.  
  573.     if (strlen(cmd) != 8) {
  574.     hex_num[0] = 'X';
  575.     return(hex_num);
  576.     }
  577.  
  578.     if (get_hex_string(cmd, hex_num, 4) < 0)
  579.     hex_num[0] = 'X';
  580.  
  581.     return hex_num;
  582. }
  583. /*******************************************************************
  584.     s w a p _ d w f
  585.  
  586.     Swap the bytes pointed to by p.
  587.  
  588.     Arguments - p = ptr to word to swap
  589.  
  590.     Returns - nothing
  591. ********************************************************************/
  592. void swap_dwf(char *p)
  593. {
  594.     char tmp;
  595.  
  596.     tmp = *p;
  597.     *p = *(p + 1);
  598.     *(p + 1) = tmp;
  599.     return;
  600. }
  601.