home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1993 #3 / NN_1993_3.iso / spool / comp / os / vxworks / 1237 < prev    next >
Encoding:
Text File  |  1993-01-22  |  20.3 KB  |  754 lines

  1. Path: sparky!uunet!spool.mu.edu!agate!dog.ee.lbl.gov!lbl.gov!vxwexplo
  2. From: Mandler <rcm@ssd.ray.com>
  3. Newsgroups: comp.os.vxworks
  4. Subject: re:  ping command available?
  5. Date: Fri, 22 Jan 1993 11:03:48 -0500
  6. Organization: Lawrence Berkeley Laboratory, Berkeley CA
  7. Lines: 741
  8. Sender: vxwexplo@lbl.gov
  9. Message-ID: <199301221603.AA21789@piranha.ssd.ray.com>
  10. NNTP-Posting-Host: 128.3.112.16
  11. Originator: daemon@vxw.ee.lbl.gov
  12.  
  13. To thoff and other interested parties,
  14. Here is a "quick and dirty" version of the ping program that we ported to
  15. VxWorks.
  16.     ______________________________________________________________
  17.    |  Roland C Mandler,  Raytheon Submarine Signal Division       |
  18.    |  1847 West Main Road,  Mail Stop 188                         |
  19.    |  Portsmouth, RI  02871-1087  (401) 847-8000 (X4228)          |
  20.    |                                                              |
  21.    |      {uiucdcs,uunet}!rayssd!sgfb.ssd.ray.com!rcm             |
  22.    |______________________________________________________________|
  23.  
  24.  
  25.  /* Includes, defines and global variables used between functions.
  26.  */
  27. #include "vxWorks.h"
  28. #include "mbuf.h"
  29. #include "ctype.h"
  30. #include "socket.h"
  31. #include "if.h"
  32. #include "ioLib.h"
  33. #include "ioctl.h"
  34. #include "iosLib.h"
  35. #include "stdioLib.h"
  36. #include "selectLib.h"
  37. #include "sockLib.h"
  38. #include "in_systm.h"
  39. #include "in.h"
  40. #include "ip.h"
  41. #include "ip_icmp.h"
  42. #include "taskLib.h"
  43. #include "hostLib.h" 
  44. #include "wdLib.h"
  45. #include "errno.h"
  46.  
  47. extern int    errno;
  48.  
  49. /* defines */
  50. /*
  51.  * Beware that the outgoing packet starts with the ICMP header and
  52.  * does not include the IP header (the kernel prepends that for us).
  53.  * But, the received packet includes the IP header.
  54.  */
  55. #define    DEF_DATALEN      56    /* default data area after ICMP header */
  56. #ifndef    INADDR_NONE
  57. #define    INADDR_NONE    0xffffffff    /* should be in <in.h> */
  58. #endif
  59. #ifndef    MAXHOSTNAMELEN
  60. #define MAXHOSTNAMELEN      64    /* should be defined in <param.h> */
  61. #endif
  62. #define MAXMSG             1    /* number of messages pipe will hold */
  63. #define MAXPIPE            1    /* number of bytes in pipe message */
  64. #define    MAXPACKET    4096    /* max packet size */
  65. #define    MAXWAIT          10    /* max time to wait for response, sec. */
  66.                 /* used only for final receive */
  67. #define    NROUTES        9    /* number of record route slots */
  68. #define PF_ICMP         1       /* ICMP protocol */
  69. #define QUIET        2    /* quiet flag */
  70. #define    RROUTE        8    /* record route flag */
  71. #define    SIZE_ICMP_HDR       8    /* 8-byte ICMP header */
  72. #define    SIZE_TIME_DATA       8    /* then the BSD timeval struct (ICMP "data") */
  73.  
  74. /* variables */
  75. int        datalen;    /* size of data after the ICMP header */
  76.                    /* may be 0 */
  77.                    /* if >= SIZE_TIME_DATA, timing is done */
  78. char        *destdotaddr;
  79. char        *hostname;
  80. short        ident;        /* masked process ID, to identify returns */
  81. int        mytask;         /* full process ID */
  82. int        npackets;    /* max # of packets to send; 0 if no limit */
  83. int        nreceived;    /* # of packets we got back */
  84. int        ntransmitted;    /* sequence # for outbound packets = #sent */
  85. int             pingflags;
  86. int        packsize;    /* size of ICMP packets to send */
  87.                    /* this includes the 8-byte ICMP header */
  88. char            pipecode;
  89. int             pipefd; /* pipe file descriptor */
  90. int             pipestat;
  91. u_char        recvpack[MAXPACKET];    /* the received packet */
  92. char rspace[3+4*NROUTES+1];    /* record route space */
  93. long            sbytes;
  94. u_char        sendpack[MAXPACKET];    /* the packet we send */
  95. int        sockfd;    /* socket file descriptor */
  96. int             time_start;
  97. int             time_ret;
  98. int        timing;        /* true if time-stamp in each packet */
  99. int        tmin;        /* min round-trip time */
  100. int        tmax;        /* max round-trip time */
  101. long        tsum;        /* sum of all round-trip times, for average */
  102.             /* above 3 times are in milliseconds */
  103. int        verbose;    /* enables additional error messages */
  104.  
  105. /* structures */
  106. struct fd_set   fdset; /*file descriptor bit mapping for select */
  107. struct fd_set  *fdst;
  108. struct sockaddr_in    dest;    /* who to ping */
  109. WDOG_ID wdtmr;
  110.  
  111.  
  112. /* routines */
  113. char        *inet_ntoa();    /* BSD library routine */
  114. VOID             ping_task();
  115. VOID             finish();    /* our function to finish up and exit */
  116. VOID             stp();
  117. VOID             timeout_hndl();
  118. VOID             parseOptions();
  119.  
  120. /*
  121.  * Copyright (c) 1987 Regents of the University of California.
  122.  * All rights reserved.
  123.  *
  124.  * Redistribution and use in source and binary forms are permitted
  125.  * provided that the above copyright notice and this paragraph are
  126.  * duplicated in all such forms and that any documentation,
  127.  * advertising materials, and other materials related to such
  128.  * distribution and use acknowledge that the software was developed
  129.  * by the University of California, Berkeley.  The name of the
  130.  * University may not be used to endorse or promote products derived
  131.  * from this software without specific prior written permission.
  132.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  133.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  134.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  135.  */
  136.  
  137. #ifndef lint
  138. char copyright[] =
  139. "@(#) Copyright (c) 1987 Regents of the University of California.\n\
  140.  All rights reserved.\n";
  141. #endif /* not lint */
  142.  
  143. #ifndef lint
  144. static char sccsid[] = "@(#)ping.c    4.10 (Berkeley) 10/10/88";
  145. #endif /* not lint */
  146.  
  147.  
  148. /*
  149.  *            P I N G . C
  150.  *
  151.  * Using the InterNet Control Message Protocol (ICMP) "ECHO" facility,
  152.  * measure round-trip-delays and packet loss across network paths.
  153.  *
  154.  * Author -
  155.  *    Mike Muuss
  156.  *    U. S. Army Ballistic Research Laboratory
  157.  *    December, 1983
  158.  * Modified at Uc Berkeley
  159.  *
  160.  * This version was modified to run under vxWorks by:
  161.  *      Roland Mandler
  162.  *      Raytheon Submarine Signal Division
  163.  *      June, 1991
  164.  *
  165.  * Status -
  166.  *    Public Domain.  Distribution Unlimited.
  167.  *
  168.  * Bugs -
  169.  *    More statistics could always be gathered.
  170.  *    This program has to run SUID to ROOT to access the ICMP socket.
  171.  */
  172.  
  173. char usage[] =
  174. "\nUsage: \
  175. ping [-dnqrvRs] host [datasize [count]] \n\
  176. \n\
  177.     STANDARD OPTIONS: \n\
  178.       -s = continuous    -d = debug    -q = quiet    -v = verbose \n\
  179.       -R = record route  -r = route to interface \n\
  180. \n\
  181. ";
  182. char    hnamebuf[MAXHOSTNAMELEN];
  183. char    *pname;
  184.  
  185. ping(strng)
  186. char strng[];
  187. {
  188.         /* spawn off ping task - makes it easier to kill */
  189.         taskSpawn(NULL, 1, VX_STDIO | VX_DEALLOC_STACK,20000,&ping_task,
  190.                     strng,0,0,0,0,0,0,0,0,0);
  191. }
  192.  
  193. VOID ping_task(strng)
  194. char strng[];
  195. {
  196.     int sockoptions,on;
  197.         int host;
  198.         int pargc;
  199.     int i, i1, i2, i3, i4;
  200.     unsigned char ttl, loop;
  201.     struct in_addr ifaddr;
  202.         char *argvpar[11];
  203.         char **pargv = argvpar;
  204.  
  205.         /* parse input string into argc, argv format */
  206.         parseOptions(&pargc,pargv,strng);
  207.  
  208.     on = 1;
  209.     pname = pargv[0];
  210.     pargc--;
  211.     pargv++;
  212.  
  213.         fdst = (struct fd_set *)&fdset;
  214.     sockoptions = 0;
  215.         pingflags = 0;
  216.         ntransmitted = 0;
  217.         nreceived = 0;
  218.         verbose = 0;
  219.         timing = 0;
  220.         tmin = 0;
  221.         tmax = 0;
  222.         npackets = 1; /* default is send one ping */
  223.         tmin = 0;
  224.         tmax = 0;
  225.         tsum = 0;
  226.         wdtmr = wdCreate();
  227.     while (pargc > 0 && *pargv[0] == '-') {
  228.         while (*++pargv[0]) switch (*pargv[0]) {
  229.             case 'd': /* debug on */
  230.                 sockoptions |= SO_DEBUG;
  231.                 break;
  232.             case 'r': /* route to intfc */
  233.                 sockoptions |= SO_DONTROUTE;
  234.                 break;
  235.             case 'v': /* verbose input error printout */
  236.                 verbose++;
  237.                 break;
  238.                         case 's': /* continuous pinging at 1 Hz */
  239.                                 npackets = 0; /* 1 Hz continuous pinging */
  240.                                 printf("\n\nTYPE 'stp' TO ABORT \n\n");
  241.                                 break;
  242.             case 'q': /* disables ping send/recv messages */
  243.                 pingflags |= QUIET;
  244.                 break;
  245.             case 'R': /* record route */
  246.                 pingflags |= RROUTE;
  247.                 break;
  248.             default:
  249.                 goto print_usage;
  250.         }
  251.         pargc--, pargv++;
  252.     }
  253.         if (pargc < 1) {
  254. print_usage:    printf(usage);
  255.         return;
  256.     }
  257.  
  258.     /*
  259.      * Assume the host is specified by numbers (Internet dotted-decimal)
  260.      * and call inet_addr() to convert it.  If that doesn't work, then
  261.      * assume its a name and call hostGetByName() to look it up.
  262.      */
  263.  
  264.     bzero((char *) &dest, sizeof(dest));
  265.     dest.sin_family = AF_INET;
  266.  
  267.     if ( (dest.sin_addr.s_addr = htons(inet_addr(pargv[0]))) != INADDR_NONE) {
  268.         strcpy(hnamebuf, pargv[0]);
  269.         hostname = hnamebuf;
  270.         destdotaddr = NULL;
  271.     } else {
  272.         if ( (host = htons(hostGetByName(pargv[0]))) == NULL) {
  273.             printf("host name error: %s ", pargv[0]);
  274.         }
  275.         dest.sin_family = AF_INET;
  276.         dest.sin_addr.s_addr = host;
  277.                 strcpy(hnamebuf,pargv[0]);
  278.         hostname = hnamebuf;
  279.         destdotaddr = inet_ntoa(dest.sin_addr.s_addr);
  280.                 /* convert to dotted-decimal notation */
  281.     }
  282.  
  283.     /*
  284.      * If the user specifies a size, that is the size of the data area
  285.      * following the ICMP header that is transmitted.      */
  286.  
  287.     if (pargc >= 2)
  288.                 sscanf(pargv[1],"%d",&datalen);
  289.     else
  290.         datalen = DEF_DATALEN;
  291.  
  292.     packsize = datalen + SIZE_ICMP_HDR;
  293.     if (packsize > MAXPACKET)
  294.         printf("packet size too large");
  295.     if (datalen >= SIZE_TIME_DATA)
  296.         timing = 1; 
  297.  
  298.     /*
  299.      * The user can specify the maximum number of packets to receive.
  300.      */
  301.  
  302.     if (pargc > 2) {
  303.                 sscanf(pargv[2],"%d",&npackets);
  304.                 printf("\n\nTYPE 'stp' TO ABORT \n\n");
  305.         }
  306.  
  307.     /*
  308.      * Fetch our process ID.  We use that as the "ident" field
  309.      * in the ICMP header, to identify this process' packets.
  310.      * This allows multiple copies of ping to be running on a host
  311.      * at the same time.  This identifier is needed to separate
  312.      * the received ICMP packets (since all readers of an ICMP
  313.      * socket get all the received packets).
  314.      */
  315.  
  316.         mytask = taskIdSelf();
  317.     ident = mytask & 0x7fff;
  318.  
  319.     /*
  320.      * Create the socket.
  321.      */
  322.  
  323.     if ( (sockfd = socket(AF_INET, SOCK_RAW, PF_ICMP)) < 0) 
  324.         printf("can't create raw socket");
  325.     if (sockoptions & SO_DEBUG)
  326.         if (setsockopt(sockfd, SOL_SOCKET, SO_DEBUG, &on,
  327.                                 sizeof(on)) < 0)
  328.             printf("setsockopt SO_DEBUG error");
  329.     if (sockoptions & SO_DONTROUTE)
  330.         if (setsockopt(sockfd, SOL_SOCKET, SO_DONTROUTE, &on,
  331.                                 sizeof(on)) < 0)
  332.             printf("setsockopt SO_DONTROUTE error");
  333.     /* Record Route option */
  334.     if( pingflags & RROUTE ) {
  335. #ifdef IP_OPTIONS
  336.         rspace[IPOPT_OPTVAL] = IPOPT_RR;
  337.         rspace[IPOPT_OLEN] = sizeof(rspace)-1;
  338.         rspace[IPOPT_OFFSET] = IPOPT_MINOFF;
  339.         if( setsockopt(sockfd, IPPROTO_IP, IP_OPTIONS, rspace, sizeof(rspace)) < 0 ) {
  340.             printf( "Record route" );
  341.             return;
  342.         }
  343. #else
  344.         printf( "ping: record route not available on this machine.\n" );
  345.         return;
  346. #endif IP_OPTIONS
  347.     }
  348.  
  349.  
  350.         /* create a communication pipe */
  351.         pipeDevCreate("ping_pipe",MAXMSG,MAXPIPE); 
  352.  
  353.         if ((pipefd = open("ping_pipe", O_RDWR, (int) NULL)) == ERROR)
  354.         {
  355.         printf("error: can't open pipe.\n");
  356.             return;
  357.         }
  358.  
  359.         /* set up bit map to select on pipe or socket i/o */
  360.         FD_SET(sockfd, fdst);
  361.         FD_SET(pipefd, fdst);
  362.  
  363.     do_ping();    /* start the output going */
  364.         return;
  365. }
  366.  
  367. /* This routine is the watchdog timer handler. It writes a timeout indication
  368.  * to the pipe, which is in turn handled within 'do_ping' */
  369.  
  370. VOID timeout_hndl()
  371. {
  372.     write(pipefd, "t", 1);
  373. }
  374.  
  375.  
  376. /* This routine controls ping origination and reception */
  377.  
  378. do_ping()
  379. {
  380.     int    finflag;
  381.     register int        n;
  382.     int            fromlen;
  383.     struct sockaddr_in    from;
  384.         int                     cont;
  385.  
  386.         for ( ; ; ) {
  387.  
  388.                send_ping();        /* first send a packet */
  389.  
  390.         if (npackets != 0) 
  391.         /*
  392.          * We've sent the specified number of packets.
  393.          * But, we can't just terminate, as there is at least one
  394.          * packet still to be received (the one we sent at the
  395.          * beginning of this function).
  396.          * Just wait 10 seconds.
  397.          */
  398.                  wdStart (wdtmr, MAXWAIT * sysClkRateGet(), timeout_hndl);
  399.  
  400.             /* wait for either socket or pipe data availability */
  401.  
  402.             if ( select (32,&fdset,NULL,NULL,NULL) > 0 ) {
  403.                 if (FD_ISSET(pipefd,fdst)) {
  404.                     pipestat = read (pipefd,&pipecode, MAXPIPE);
  405.                     finish();
  406.                     break; /* escape the loop and exit the program */
  407.                 }  /* pipe data pending */
  408.  
  409.                 if (FD_ISSET(sockfd,fdst)) {
  410.  
  411.             fromlen = sizeof(from);
  412.             if ( (n = recvfrom(sockfd, recvpack, sizeof(recvpack), 0,
  413.                 (struct sockaddr *) &from, &fromlen)) < 0) {
  414.                 if (errno == EINTR)
  415.                 continue;    /* normal */
  416.                 printf("recvfrom error");
  417.                             break;
  418.                     }
  419.                     /* cancel 10 second timeout */
  420.                     wdCancel(wdtmr);
  421.  
  422.                     /* check the receive packet */
  423.             pr_pack(recvpack, n, &from);
  424.  
  425.             /*
  426.              * If we're only supposed to receive a certain number of
  427.              * packets, and we've reached the limit, stop.
  428.              */
  429.  
  430.             if (npackets && (nreceived >= npackets)) {
  431.             finish();
  432.                         break;
  433.                     }
  434.                     /* wait 1 second before pinging again */
  435.                     taskDelay(sysClkRateGet()); 
  436.  
  437.                 } /* socket data pending */
  438.             } /* select data available */
  439.     } /* loop */
  440.         return;
  441. }
  442. /*
  443.  * Compose and transmit an ICMP ECHO REQUEST packet.  The IP header
  444.  * will be prepended by the kernel.  The ID field is our process ID,
  445.  * and the sequence number is an ascending integer.  The first 8 bytes
  446.  * of the data portion are used to hold a BSD "timeval" struct in host
  447.  * byte-order, to compute the round-trip time of each packet.
  448.  */
  449.  
  450.  
  451. send_ping()
  452. {
  453.     register int        i;
  454.     register struct icmp    *icp;        /* ICMP header */
  455.     register u_char        *uptr;        /* start of user data */
  456.  
  457.     /*
  458.      * Fill in the ICMP header.
  459.      */
  460.  
  461.     icp = (struct icmp *) sendpack;    /* pointer to ICMP header */
  462.     icp->icmp_type  = ICMP_ECHO;
  463.     icp->icmp_code  = 0;
  464.     icp->icmp_cksum = 0;         /* init to 0, then call in_cksum() below */
  465.     icp->icmp_id    = ident;     /* our pid, to identify on return */
  466.     icp->icmp_seq   = ntransmitted++;    /* sequence number */
  467.  
  468.     /*
  469.      * And fill in the remainder of the packet with the user data.
  470.      * We just set each byte of udata[i] to i (although this is
  471.      * not verified when the echoed packet is received back).
  472.      */
  473.  
  474.     uptr = &sendpack[SIZE_ICMP_HDR + SIZE_TIME_DATA];
  475.     for (i = SIZE_TIME_DATA; i < datalen; i++)
  476.         *uptr++ = i;
  477.  
  478.     /*
  479.      * Compute and store the ICMP checksum (now that we've filled
  480.      * in the entire ICMP packet).  The checksum includes the ICMP
  481.      * header, the time stamp, and our user data.
  482.      */
  483.  
  484.     icp->icmp_cksum = icmp_cksum(icp, packsize);
  485.  
  486.     /*
  487.      * Add the time stamp of when we sent it.
  488.      */
  489.  
  490.     if (timing)
  491.                 time_start = tickGet();
  492.  
  493.     /*
  494.      * Now send the datagram.
  495.      */
  496.  
  497.     i = sendto(sockfd, sendpack, packsize, 0,
  498.             (struct sockaddr *) &dest, sizeof(dest));
  499.  
  500.        /* tell the user it went out */
  501.         if ((pingflags & QUIET) == 0)
  502.         {
  503.         printf("PING %s", hostname);
  504.         if (destdotaddr)
  505.         printf(" (%s)", destdotaddr);
  506.         printf(": %d data bytes\n", datalen);
  507.         setlinebuf(stdout);        /* one line at a time */
  508.         }
  509.  
  510.     if (i < 0 || i != packsize)  {
  511.         if (i < 0)
  512.             printf("sendto error");
  513.         else
  514.             printf("wrote %s %d bytes, return=%d",
  515.                         hostname, packsize, i);
  516.     }
  517. }
  518. /*
  519.  *            I C M P _ C K S U M
  520.  *
  521.  * Checksum routine for Internet Protocol family headers (C Version)
  522.  *
  523.  */
  524. icmp_cksum(addr, len)
  525. u_short *addr;
  526. int len;
  527. {
  528.     register int nleft = len;
  529.     register u_short *w = addr;
  530.     register int sum = 0;
  531.     u_short answer = 0;
  532.  
  533.     /*
  534.      *  Our algorithm is simple, using a 32 bit accumulator (sum),
  535.      *  we add sequential 16 bit words to it, and at the end, fold
  536.      *  back all the carry bits from the top 16 bits into the lower
  537.      *  16 bits.
  538.      */
  539.     while( nleft > 1 )  {
  540.         sum += *w++;
  541.         nleft -= 2;
  542.     }
  543.  
  544.     /* mop up an odd byte, if necessary */
  545.     if( nleft == 1 ) {
  546.         *(u_char *)(&answer) = *(u_char *)w ;
  547.         sum += answer;
  548.     }
  549.  
  550.     /*
  551.      * add back carry outs from top 16 bits to low 16 bits
  552.      */
  553.     sum = (sum >> 16) + (sum & 0xffff);    /* add hi 16 to low 16 */
  554.     sum += (sum >> 16);            /* add carry */
  555.     answer = ~sum;                /* truncate to 16 bits */
  556.     return (answer);
  557. }
  558.  
  559.  
  560. /*
  561.  * Print out the packet, if it came from us.  This logic is necessary
  562.  * because ALL readers of the ICMP socket get a copy of ALL ICMP packets
  563.  * which arrive ('tis only fair).  This permits multiple copies of this
  564.  * program to be run without having intermingled output (or statistics!).
  565.  */
  566.  
  567.  
  568. pr_pack(buf, cc, from)
  569. char            *buf;    /* ptr to start of IP header */
  570. int            cc;    /* total size of received packet */
  571. struct sockaddr_in    *from;    /* address of sender */
  572. {
  573.     int            i, iphdrlen, triptime;
  574.     struct ip        *ip;        /* ptr to IP header */
  575.     register struct icmp    *icp;        /* ptr to ICMP header */
  576.     long            *lp;
  577.     struct timeval        tv;
  578.     char            *pr_type();
  579.  
  580.     from->sin_addr.s_addr = ntohl(from->sin_addr.s_addr);
  581.  
  582.     if (timing)
  583.                 time_ret = tickGet();
  584.  
  585.     /*
  586.      * We have to look at the IP header, to get its length.
  587.      * We also verify that what follows the IP header contains at
  588.      * least an ICMP header (8 bytes minimum).
  589.      */
  590.  
  591.     ip = (struct ip *) buf;
  592.     iphdrlen = ip->ip_hl << 2;    /* convert # 16-bit words to #bytes */
  593.     if (cc < iphdrlen + ICMP_MINLEN) {
  594.         if (verbose)
  595.             printf("packet too short (%d bytes) from %s\n", cc,
  596.                 inet_ntoa(ntohl(from->sin_addr.s_addr)));
  597.         return;
  598.     }
  599.     cc -= iphdrlen;
  600.  
  601.     icp = (struct icmp *)(buf + iphdrlen);
  602.     if (icp->icmp_type != ICMP_ECHOREPLY) {
  603.         /*
  604.          * The received ICMP packet is not an echo reply.
  605.          * If the verbose flag was set, we print the first 48 bytes
  606.          * of the received packet as 12 longs.
  607.          */
  608.  
  609.         if (verbose) {
  610.             lp = (long *) buf;    /* to print 12 longs */
  611.             printf("%d bytes from %s: ", cc,
  612.                 inet_ntoa(ntohl(from->sin_addr.s_addr)));
  613.             printf("icmp_type=%d (%s)\n",
  614.                 icp->icmp_type, pr_type(icp->icmp_type));
  615.             for (i = 0; i < 12; i++)
  616.                 printf("x%2.2x: x%8.8x\n", i*sizeof(long), *lp++);
  617.             printf("icmp_code=%d\n", icp->icmp_code);
  618.         }
  619.         return;
  620.     }
  621.  
  622.     /*
  623.      * See if we sent the packet, and if not, just ignore it.
  624.      */
  625.  
  626.     if (icp->icmp_id != ident)
  627.         return;
  628.  
  629.         if ((pingflags & QUIET) == 0)
  630.         {
  631.         printf("%d bytes from %s: ", cc,
  632.                      inet_ntoa(ntohl(from->sin_addr.s_addr)));
  633.         printf("ping # = %d. \n ", icp->icmp_seq);
  634.         }
  635.     if (timing) {
  636.         /* Calculate the round-trip time, and update the min/avg/max */        
  637.                 triptime =(time_ret - time_start) * (1000 /sysClkRateGet());
  638.         tsum += triptime;
  639.         if (triptime < tmin)
  640.             tmin = triptime;
  641.         if (triptime > tmax)
  642.             tmax = triptime;
  643.     } 
  644.  
  645.     nreceived++;    /* only count echo reply packets that we sent */
  646. }
  647.  
  648. /*
  649.  * Convert an ICMP "type" field to a printable string.
  650.  * This is called for ICMP packets that are received that are not
  651.  * ICMP_ECHOREPLY packets.
  652.  */
  653.  
  654. char *
  655. pr_type(t)
  656. register int t;
  657. {
  658.     static char    *ttab[] = {
  659.         "Echo Reply",
  660.         "ICMP 1",
  661.         "ICMP 2",
  662.         "Dest Unreachable",
  663.         "Source Quence",
  664.         "Redirect",
  665.         "ICMP 6",
  666.         "ICMP 7",
  667.         "Echo",
  668.         "ICMP 9",
  669.         "ICMP 10",
  670.         "Time Exceeded",
  671.         "Parameter Problem",
  672.         "Timestamp",
  673.         "Timestamp Reply",
  674.         "Info Request",
  675.         "Info Reply"
  676.     };
  677.  
  678.     if (t < 0 || t > 16)
  679.         return("OUT-OF-RANGE");
  680.  
  681.     return(ttab[t]);
  682. }
  683.  
  684. /*
  685.  *    parseOptions.c
  686.  *     Generate Unix style (argc, argv) parameters from an incoming
  687.  *    VxWorks command string.  Chops up the original string with
  688.  *    nulls to make short strings and fills the argv array with pointers
  689.  *    to the new strings.
  690.  *
  691.  *    maximum of 10 parameters should be defined. (argv[11] in caller).
  692.  *    parameters should be seperated by blanks or tabs.
  693.  */
  694. VOID
  695. parseOptions(argc, argv, inpStr)
  696.     int    *argc;            /* argument count */
  697.     char    *argv[];        /* argument pointers */
  698.     char    *inpStr;        /* original input line */
  699. {
  700.     char    *cch;            /* current character */
  701.  
  702.     cch = inpStr;
  703.     *argc = 1;            /* always at least 1 */
  704.     
  705.     while (*cch != '\0')
  706.     {
  707.         while (((*cch == ' ') || (*cch == '    ')) && (*cch != '\0'))
  708.             cch++;
  709.  
  710.               
  711.                 if (*cch != '\0')
  712.                 {
  713.             argv[*argc] = cch;
  714.             *argc += 1;
  715.  
  716.             while ((*cch != ' ') && (*cch != '    ') && 
  717.                            (*cch != '\0'))
  718.                 cch++;
  719.                     if (*cch != '\0')
  720.                 *cch++ = '\0';
  721.                 }
  722.     }
  723. }
  724.  
  725. /*
  726.  * Print out statistics, and stop.
  727.  */
  728.  
  729.  
  730. VOID finish()
  731. {
  732.     printf("\n----%s PING Statistics----\n", hostname );
  733.     printf("%d packets transmitted, ", ntransmitted );
  734.     printf("%d packets received, ", nreceived );
  735.     if (ntransmitted)
  736.         printf("%d%% packet loss",
  737.             (int) (((ntransmitted-nreceived)*100) / ntransmitted) );
  738.     printf("\n");
  739.     if (nreceived && timing)
  740.         printf("round-trip (ms)  min/avg/max = %d/%d/%d\n",
  741.                 tmin, tsum / nreceived, tmax );
  742.         wdCancel(wdtmr);
  743.         close(pipefd);
  744.         close(sockfd);
  745.         printf("PING done. Hit <return>.\n");
  746.         taskDelete(mytask);
  747. }
  748. /* termination of continuous pinging */
  749.  
  750. VOID stp()
  751. {
  752.     finish();
  753. }
  754.