home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume40 / nocol / part12 < prev    next >
Encoding:
Text File  |  1993-11-23  |  75.7 KB  |  2,271 lines

  1. Newsgroups: comp.sources.misc
  2. From: vikas@jvnc.net (Vikas Aggarwal)
  3. Subject: v40i142:  nocol - Network Monitoring System, Part12/26
  4. Message-ID: <1993Nov23.212524.21488@sparky.sterling.com>
  5. X-Md4-Signature: fdf3877a9d2f7c45110a4051ffbf6725
  6. Sender: kent@sparky.sterling.com (Kent Landfield)
  7. Organization: Sterling Software
  8. Date: Tue, 23 Nov 1993 21:25:24 GMT
  9. Approved: kent@sparky.sterling.com
  10.  
  11. Submitted-by: vikas@jvnc.net (Vikas Aggarwal)
  12. Posting-number: Volume 40, Issue 142
  13. Archive-name: nocol/part12
  14. Environment: INET, UNIX
  15.  
  16. #! /bin/sh
  17. # This is a shell archive.  Remove anything before this line, then feed it
  18. # into a shell via "sh file" or similar.  To overwrite existing files,
  19. # type "sh file -c".
  20. # Contents:  nocol-3.0/src/cmu-snmp/include/snmp_api.h
  21. #   nocol-3.0/src/cmu-snmp/include/snmp_vars.c.kip
  22. #   nocol-3.0/src/support/multiping/multiping.c
  23. # Wrapped by kent@sparky on Tue Nov  9 22:22:18 1993
  24. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin:$PATH ; export PATH
  25. echo If this archive is complete, you will see the following message:
  26. echo '          "shar: End of archive 12 (of 26)."'
  27. if test -f 'nocol-3.0/src/cmu-snmp/include/snmp_api.h' -a "${1}" != "-c" ; then 
  28.   echo shar: Will not clobber existing file \"'nocol-3.0/src/cmu-snmp/include/snmp_api.h'\"
  29. else
  30.   echo shar: Extracting \"'nocol-3.0/src/cmu-snmp/include/snmp_api.h'\" \(8565 characters\)
  31.   sed "s/^X//" >'nocol-3.0/src/cmu-snmp/include/snmp_api.h' <<'END_OF_FILE'
  32. X/***********************************************************
  33. X    Copyright 1989 by Carnegie Mellon University
  34. X
  35. X                      All Rights Reserved
  36. X
  37. XPermission to use, copy, modify, and distribute this software and its 
  38. Xdocumentation for any purpose and without fee is hereby granted, 
  39. Xprovided that the above copyright notice appear in all copies and that
  40. Xboth that copyright notice and this permission notice appear in 
  41. Xsupporting documentation, and that the name of CMU not be
  42. Xused in advertising or publicity pertaining to distribution of the
  43. Xsoftware without specific, written prior permission.  
  44. X
  45. XCMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  46. XALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  47. XCMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  48. XANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  49. XWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  50. XARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  51. XSOFTWARE.
  52. X******************************************************************/
  53. X/*
  54. X * snmp_api.h - API for access to snmp.
  55. X */
  56. X
  57. X
  58. Xtypedef struct sockaddr_in  ipaddr;
  59. X
  60. Xstruct snmp_session {
  61. X    u_char  *community;    /* community for outgoing requests. */
  62. X    int        community_len;  /* Length of community name. */
  63. X    int        retries;    /* Number of retries before timeout. */
  64. X    long    timeout;    /* Number of uS until first timeout, then exponential backoff */
  65. X    char    *peername;    /* Domain name or dotted IP address of default peer */
  66. X    u_short remote_port;/* UDP port number of peer. */
  67. X    u_short local_port; /* My UDP port number, 0 for default, picked randomly */
  68. X    /* Authentication function or NULL if null authentication is used */
  69. X    u_char    *(*authenticator)();
  70. X    int        (*callback)();  /* Function to interpret incoming data */
  71. X    /* Pointer to data that the callback function may consider important */
  72. X    void    *callback_magic;
  73. X};
  74. X
  75. X/*
  76. X * Set fields in session and pdu to the following to get a default or unconfigured value.
  77. X */
  78. X#define SNMP_DEFAULT_COMMUNITY_LEN  0    /* to get a default community name */
  79. X#define SNMP_DEFAULT_RETRIES        -1
  80. X#define SNMP_DEFAULT_TIMEOUT        -1
  81. X#define SNMP_DEFAULT_REMPORT        0
  82. X#define SNMP_DEFAULT_REQID        0
  83. X#define SNMP_DEFAULT_ERRSTAT        -1
  84. X#define SNMP_DEFAULT_ERRINDEX        -1
  85. X#define SNMP_DEFAULT_ADDRESS        0
  86. X#define SNMP_DEFAULT_PEERNAME        NULL
  87. X#define SNMP_DEFAULT_ENTERPRISE_LENGTH    0
  88. X#define SNMP_DEFAULT_TIME        0
  89. X
  90. Xextern int snmp_errno;
  91. X/* Error return values */
  92. X#define SNMPERR_GENERR        -1
  93. X#define SNMPERR_BAD_LOCPORT    -2  /* local port was already in use */
  94. X#define SNMPERR_BAD_ADDRESS    -3
  95. X#define SNMPERR_BAD_SESSION    -4
  96. X#define SNMPERR_TOO_LONG    -5
  97. X
  98. X
  99. Xstruct snmp_pdu {
  100. X    ipaddr  address;    /* Address of peer */
  101. X
  102. X    int        command;    /* Type of this PDU */
  103. X
  104. X    u_long  reqid;    /* Request id */
  105. X    u_long  errstat;    /* Error status */
  106. X    u_long  errindex;    /* Error index */
  107. X
  108. X    /* Trap information */
  109. X    oid        *enterprise;/* System OID */
  110. X    int        enterprise_length;
  111. X    ipaddr  agent_addr;    /* address of object generating trap */
  112. X    int        trap_type;    /* trap type */
  113. X    int        specific_type;  /* specific type */
  114. X    u_long  time;    /* Uptime */
  115. X
  116. X    struct variable_list *variables;
  117. X};
  118. X
  119. X
  120. Xstruct variable_list {
  121. X    struct variable_list *next_variable;    /* NULL for last variable */
  122. X    oid        *name;  /* Object identifier of variable */
  123. X    int        name_length;    /* number of subid's in name */
  124. X    u_char  type;   /* ASN type of variable */
  125. X    union { /* value of variable */
  126. X    long    *integer;
  127. X    u_char    *string;
  128. X    oid    *objid;
  129. X    } val;
  130. X    int        val_len;
  131. X};
  132. X
  133. X/*
  134. X * struct snmp_session *snmp_open(session)
  135. X *    struct snmp_session *session;
  136. X * 
  137. X * Sets up the session with the snmp_session information provided
  138. X * by the user.  Then opens and binds the necessary UDP port.
  139. X * A handle to the created session is returned (this is different than
  140. X * the pointer passed to snmp_open()).  On any error, NULL is returned
  141. X * and snmp_errno is set to the appropriate error code.
  142. X */
  143. Xstruct snmp_session *snmp_open();
  144. X
  145. X/*
  146. X * int snmp_close(session)
  147. X *     struct snmp_session *session;
  148. X * 
  149. X * Close the input session.  Frees all data allocated for the session,
  150. X * dequeues any pending requests, and closes any sockets allocated for
  151. X * the session.  Returns 0 on error, 1 otherwise.
  152. X */
  153. Xint snmp_close();
  154. X
  155. X
  156. X/*
  157. X * int snmp_send(session, pdu)
  158. X *     struct snmp_session *session;
  159. X *     struct snmp_pdu    *pdu;
  160. X * 
  161. X * Sends the input pdu on the session after calling snmp_build to create
  162. X * a serialized packet.  If necessary, set some of the pdu data from the
  163. X * session defaults.  Add a request corresponding to this pdu to the list
  164. X * of outstanding requests on this session, then send the pdu.
  165. X * Returns the request id of the generated packet if applicable, otherwise 1.
  166. X * On any error, 0 is returned.
  167. X * The pdu is freed by snmp_send() unless a failure occured.
  168. X */
  169. Xint snmp_send();
  170. X
  171. X
  172. X/*
  173. X * void snmp_read(fdset)
  174. X *     fd_set  *fdset;
  175. X * 
  176. X * Checks to see if any of the fd's set in the fdset belong to
  177. X * snmp.  Each socket with it's fd set has a packet read from it
  178. X * and snmp_parse is called on the packet received.  The resulting pdu
  179. X * is passed to the callback routine for that session.  If the callback
  180. X * routine returns successfully, the pdu and it's request are deleted.
  181. X */
  182. Xvoid snmp_read();
  183. X
  184. X
  185. X/*
  186. X * void
  187. X * snmp_free_pdu(pdu)
  188. X *     struct snmp_pdu *pdu;
  189. X * 
  190. X * Frees the pdu and any malloc'd data associated with it.
  191. X */
  192. Xvoid snmp_free_pdu();
  193. X
  194. X/*
  195. X * int snmp_select_info(numfds, fdset, timeout, block)
  196. X * int *numfds;
  197. X * fd_set   *fdset;
  198. X * struct timeval *timeout;
  199. X * int *block;
  200. X *
  201. X * Returns info about what snmp requires from a select statement.
  202. X * numfds is the number of fds in the list that are significant.
  203. X * All file descriptors opened for SNMP are OR'd into the fdset.
  204. X * If activity occurs on any of these file descriptors, snmp_read
  205. X * should be called with that file descriptor set.
  206. X *
  207. X * The timeout is the latest time that SNMP can wait for a timeout.  The
  208. X * select should be done with the minimum time between timeout and any other
  209. X * timeouts necessary.  This should be checked upon each invocation of select.
  210. X * If a timeout is received, snmp_timeout should be called to check if the
  211. X * timeout was for SNMP.  (snmp_timeout is idempotent)
  212. X *
  213. X * Block is 1 if the select is requested to block indefinitely, rather than time out.
  214. X * If block is input as 1, the timeout value will be treated as undefined, but it must
  215. X * be available for setting in snmp_select_info.  On return, if block is true, the value
  216. X * of timeout will be undefined.
  217. X *
  218. X * snmp_select_info returns the number of open sockets.  (i.e. The number of sessions open)
  219. X */
  220. Xint snmp_select_info();
  221. X
  222. X/*
  223. X * void snmp_timeout();
  224. X * 
  225. X * snmp_timeout should be called whenever the timeout from snmp_select_info expires,
  226. X * but it is idempotent, so snmp_timeout can be polled (probably a cpu expensive
  227. X * proposition).  snmp_timeout checks to see if any of the sessions have an
  228. X * outstanding request that has timed out.  If it finds one (or more), and that
  229. X * pdu has more retries available, a new packet is formed from the pdu and is
  230. X * resent.  If there are no more retries available, the callback for the session
  231. X * is used to alert the user of the timeout.
  232. X */
  233. Xvoid snmp_timeout();
  234. X
  235. X
  236. X/*
  237. X * This routine must be supplied by the application:
  238. X *
  239. X * u_char *authenticator(pdu, length, community, community_len)
  240. X * u_char *pdu;        The rest of the PDU to be authenticated
  241. X * int *length;        The length of the PDU (updated by the authenticator)
  242. X * u_char *community;    The community name to authenticate under.
  243. X * int    community_len    The length of the community name.
  244. X *
  245. X * Returns the authenticated pdu, or NULL if authentication failed.
  246. X * If null authentication is used, the authenticator in snmp_session can be
  247. X * set to NULL(0).
  248. X */
  249. X
  250. X/*
  251. X * This routine must be supplied by the application:
  252. X *
  253. X * int callback(operation, session, reqid, pdu, magic)
  254. X * int operation;
  255. X * struct snmp_session *session;    The session authenticated under.
  256. X * int reqid;                The request id of this pdu (0 for TRAP)
  257. X * struct snmp_pdu *pdu;        The pdu information.
  258. X * void *magic                A link to the data for this routine.
  259. X *
  260. X * Returns 1 if request was successful, 0 if it should be kept pending.
  261. X * Any data in the pdu must be copied because it will be freed elsewhere.
  262. X * Operations are defined below:
  263. X */
  264. X#define RECEIVED_MESSAGE   1
  265. X#define TIMED_OUT       2
  266. X
  267. X
  268. Xextern int snmp_dump_packet;
  269. END_OF_FILE
  270.   if test 8565 -ne `wc -c <'nocol-3.0/src/cmu-snmp/include/snmp_api.h'`; then
  271.     echo shar: \"'nocol-3.0/src/cmu-snmp/include/snmp_api.h'\" unpacked with wrong size!
  272.   fi
  273.   # end of 'nocol-3.0/src/cmu-snmp/include/snmp_api.h'
  274. fi
  275. if test -f 'nocol-3.0/src/cmu-snmp/include/snmp_vars.c.kip' -a "${1}" != "-c" ; then 
  276.   echo shar: Will not clobber existing file \"'nocol-3.0/src/cmu-snmp/include/snmp_vars.c.kip'\"
  277. else
  278.   echo shar: Extracting \"'nocol-3.0/src/cmu-snmp/include/snmp_vars.c.kip'\" \(33903 characters\)
  279.   sed "s/^X//" >'nocol-3.0/src/cmu-snmp/include/snmp_vars.c.kip' <<'END_OF_FILE'
  280. X/*
  281. X * snmp_vars.c - return a pointer to the named variable.
  282. X *
  283. X *
  284. X */
  285. X/***********************************************************
  286. X    Copyright 1988, 1989 by Carnegie Mellon University
  287. X
  288. X                      All Rights Reserved
  289. X
  290. XPermission to use, copy, modify, and distribute this software and its 
  291. Xdocumentation for any purpose and without fee is hereby granted, 
  292. Xprovided that the above copyright notice appear in all copies and that
  293. Xboth that copyright notice and this permission notice appear in 
  294. Xsupporting documentation, and that the name of CMU not be
  295. Xused in advertising or publicity pertaining to distribution of the
  296. Xsoftware without specific, written prior permission.  
  297. X
  298. XCMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  299. XALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  300. XCMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  301. XANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  302. XWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  303. XARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  304. XSOFTWARE.
  305. X******************************************************************/
  306. X#ifdef KINETICS
  307. X#include "gw.h"
  308. X#include "fp4/pbuf.h"
  309. X#include "fp4/cmdmacro.h"
  310. X#include "ab.h"
  311. X#include "glob.h"
  312. X#endif
  313. X
  314. X#if (defined(unix) && !defined(KINETICS))
  315. X#include <sys/types.h>
  316. X#include <netinet/in.h>
  317. X#ifndef NULL
  318. X#define NULL 0
  319. X#endif
  320. X#endif
  321. X
  322. X
  323. X#include "asn1.h"
  324. X#include "snmp.h"
  325. X#include "snmp_impl.h"
  326. X#include "mib.h"
  327. X#include "inet.h"
  328. X#include "snmp_vars.h"
  329. X/*
  330. X *    Each variable name is placed in the variable table, without the terminating
  331. X * substring that determines the instance of the variable.  When a string is found that
  332. X * is lexicographicly preceded by the input string, the function for that entry is
  333. X * called to find the method of access of the instance of the named variable.  If
  334. X * that variable is not found, NULL is returned, and the search through the table
  335. X * continues (it should stop at the next entry).  If it is found, the function returns
  336. X * a character pointer and a length or a function pointer.  The former is the address
  337. X * of the operand, the latter is an access routine for the variable.
  338. X *
  339. X * u_char *
  340. X * findVar(name, length, exact, var_len, access_method)
  341. X * oid        *name;        IN/OUT - input name requested, output name found
  342. X * int        length;        IN/OUT - number of sub-ids in the in and out oid's
  343. X * int        exact;        IN - TRUE if an exact match was requested.
  344. X * int        len;        OUT - length of variable or 0 if function returned.
  345. X * int        access_method; OUT - 1 if function, 0 if char pointer.
  346. X *
  347. X * accessVar(rw, var, varLen)
  348. X * int        rw;        IN - request to READ or WRITE the variable
  349. X * u_char   *var;   IN/OUT - input or output buffer space
  350. X * int        *varLen;IN/OUT - input and output buffer len
  351. X */
  352. X
  353. Xstruct variable {
  354. X    oid            name[16];        /* object identifier of variable */
  355. X    u_char        namelen;        /* length of above */
  356. X    char        type;        /* type of variable, INTEGER or (octet) STRING */
  357. X    u_char        magic;        /* passed to function as a hint */
  358. X    u_short        acl;        /* access control list for variable */
  359. X    u_char        *(*findVar)();  /* function that finds variable */
  360. X};
  361. X
  362. Xchar        version_descr[30] = "Kinetics FastPath4";
  363. Xoid        version_id[] = {1, 3, 6, 1, 4, 1, 3, 1, 1};
  364. Xint        version_id_len = sizeof(version_id);
  365. Xu_long        uptime;
  366. Xlong        cfg_nnets = MAX_INTERFACES;
  367. Xlong        long_return;
  368. Xu_char        return_buf[64];
  369. X
  370. X
  371. Xstruct mib_ifEntry  mib_ifEntry_proto[MAX_INTERFACES] = {
  372. X    {1, "Kinetics KFPS2 Ethernet", MIB_IFTYPE_ETHERNETCSMACD, 
  373. X        1500, 10000000L, "", 
  374. X    6, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 
  375. X    {2, "Kinetics KFPS2 Appletalk", MIB_IFTYPE_OTHER,
  376. X        1500, 230000L, "", 
  377. X    3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
  378. X};
  379. Xstruct mib_ifEntry mib_ifEntry[MAX_INTERFACES];
  380. X
  381. Xstruct mib_ip mib_ip_proto = {
  382. X    1, IPFRAGTTL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  383. X};
  384. Xstruct mib_ip mib_ip;
  385. X
  386. X#define ROUTE_DEFAULT    0
  387. X#define ROUTE_LOCAL    1
  388. Xstruct mib_ipRouteEntry mib_ipRouteEntry_proto[2] = {
  389. X    {0, 1, 1, -1, -1, -1, 0, MIB_IPROUTETYPE_REMOTE, MIB_IPROUTEPROTO_LOCAL, 0},    /* default route */
  390. X    {0, 1, 0, -1, -1, -1, 0, MIB_IPROUTETYPE_DIRECT, MIB_IPROUTEPROTO_LOCAL, 0}        /* local route */
  391. X};
  392. Xstruct mib_ipRouteEntry mib_ipRouteEntry[2];
  393. X
  394. Xstruct mib_udp mib_udp_proto = {
  395. X    0, 0, 0, 0
  396. X};
  397. Xstruct mib_udp mib_udp;
  398. X
  399. Xlong    mib_icmpInMsgs;
  400. Xlong    mib_icmpOutMsgs;
  401. Xlong    mib_icmpInErrors;    /* not checked in KIP */
  402. Xlong    mib_icmpOutErrors;    /* not checked in KIP */
  403. Xlong    mib_icmpInCount[ICMP_MAXTYPE + 1];
  404. Xlong    mib_icmpOutCount[ICMP_MAXTYPE + 1];
  405. X
  406. X
  407. Xinit_snmp(){
  408. X    bcopy((char *)mib_ifEntry_proto, (char *)mib_ifEntry, sizeof(mib_ifEntry));
  409. X    bcopy((char *)&mib_ip_proto, (char *)&mib_ip, sizeof(mib_ip));
  410. X    bcopy((char *)mib_ipRouteEntry_proto, (char *)mib_ipRouteEntry, sizeof(mib_ipRouteEntry));
  411. X    bcopy((char *)&mib_udp_proto, (char *)&mib_udp, sizeof(mib_udp));
  412. X}
  413. X
  414. X/*
  415. X * These are byte offsets into their structures.
  416. X * This really should be computed by the compiler, but the
  417. X * compiler I'm using doesn't want to do this.
  418. X */
  419. X#define VERSION_DESCR    0
  420. X#define VERSION_ID    32
  421. X#define CFG_NNETS    48
  422. X#define UPTIME        52
  423. X
  424. X#define IFINDEX        0
  425. X#define IFDESCR        4
  426. X#define IFTYPE        36
  427. X#define IFMTU        40
  428. X#define IFSPEED        44
  429. X#define IFPHYSADDRESS    48
  430. X#define IFADMINSTATUS    60
  431. X#define IFOPERSTATUS    64
  432. X#define IFLASTCHANGE    68
  433. X#define IFINOCTETS    72
  434. X#define IFINUCASTPKTS    76
  435. X#define    IFINNUCASTPKTS    80
  436. X#define    IFINDISCARDS    84
  437. X#define    IFINERRORS    88
  438. X#define    IFINUNKNOWNPROTOS   92
  439. X#define    IFOUTOCTETS    96
  440. X#define    IFOUTUCASTPKTS    100
  441. X#define    IFOUTNUCASTPKTS    104
  442. X#define    IFOUTDISCARDS    108
  443. X#define    IFOUTERRORS    112
  444. X#define    IFOUTQLEN    116
  445. X
  446. X#define ATIFINDEX    0
  447. X#define ATPHYSADDRESS    4
  448. X#define ATNETADDRESS    16
  449. X
  450. X#define IPFORWARDING    0
  451. X#define IPDEFAULTTTL    4
  452. X#define IPINRECEIVES    8
  453. X#define IPINHDRERRORS    12
  454. X#define IPINADDRERRORS    16
  455. X#define IPFORWDATAGRAMS    20
  456. X#define IPINUNKNOWNPROTOS   24
  457. X#define IPINDISCARDS    28
  458. X#define IPINDELIVERS    32
  459. X#define IPOUTREQUESTS    36
  460. X#define IPOUTDISCARDS    40
  461. X#define IPOUTNOROUTES    44
  462. X#define IPREASMTIMEOUT    48
  463. X#define IPREASMREQDS    52
  464. X#define IPREASMOKS    56
  465. X#define IPREASMFAILS    60
  466. X#define IPFRAGOKS    64
  467. X#define IPFRAGFAILS    68
  468. X#define IPFRAGCREATES    72
  469. X
  470. X#define IPADADDR    0
  471. X#define IPADIFINDEX    4
  472. X#define IPADNETMASK    8
  473. X#define IPADBCASTADDR    12
  474. X
  475. X#define IPROUTEDEST    0
  476. X#define IPROUTEIFINDEX    4
  477. X#define IPROUTEMETRIC1    8
  478. X#define IPROUTEMETRIC2    12
  479. X#define IPROUTEMETRIC3    16
  480. X#define IPROUTEMETRIC4    20
  481. X#define IPROUTENEXTHOP    24
  482. X#define IPROUTETYPE    28
  483. X#define IPROUTEPROTO    32
  484. X#define IPROUTEAGE    36
  485. X
  486. X#define    ICMPINMSGS        0
  487. X#define    ICMPINERRORS        4
  488. X#define    ICMPINDESTUNREACHS  8
  489. X#define    ICMPINTIMEEXCDS        12
  490. X#define    ICMPINPARMPROBS        16
  491. X#define    ICMPINSRCQUENCHS    20
  492. X#define    ICMPINREDIRECTS        24
  493. X#define    ICMPINECHOS        28
  494. X#define    ICMPINECHOREPS        32
  495. X#define    ICMPINTIMESTAMPS    36
  496. X#define    ICMPINTIMESTAMPREPS 40
  497. X#define    ICMPINADDRMASKS        44
  498. X#define    ICMPINADDRMASKREPS  48
  499. X#define    ICMPOUTMSGS        52
  500. X#define    ICMPOUTERRORS        56
  501. X#define    ICMPOUTDESTUNREACHS 60
  502. X#define    ICMPOUTTIMEEXCDS    64
  503. X#define    ICMPOUTPARMPROBS    68
  504. X#define    ICMPOUTSRCQUENCHS   72
  505. X#define    ICMPOUTREDIRECTS    76
  506. X#define    ICMPOUTECHOS        80
  507. X#define    ICMPOUTECHOREPS        84
  508. X#define    ICMPOUTTIMESTAMPS   88
  509. X#define    ICMPOUTTIMESTAMPREPS    92
  510. X#define    ICMPOUTADDRMASKS    96
  511. X#define    ICMPOUTADDRMASKREPS 100
  512. X
  513. X#define UDPINDATAGRAMS        0
  514. X#define UDPNOPORTS        4
  515. X#define    UDPINERRORS        8
  516. X#define UDPOUTDATAGRAMS        12
  517. X
  518. Xstruct variable        variables[] = {
  519. X    /* these must be lexicographly ordered by the name field */
  520. X    {{MIB, 1, 1, 0},        9, STRING,  VERSION_DESCR, RONLY, var_system },
  521. X    {{MIB, 1, 2, 0},        9, OBJID,   VERSION_ID, RONLY, var_system },
  522. X    {{MIB, 1, 3, 0},        9, TIMETICKS, UPTIME, RONLY, var_system },
  523. X    {{MIB, 2, 1, 0},        9, INTEGER, CFG_NNETS, RONLY, var_system },
  524. X    {{MIB, 2, 2, 1, 1, 0xFF},  11, INTEGER, IFINDEX, RONLY, var_ifEntry },
  525. X    {{MIB, 2, 2, 1, 2, 0xFF},  11, STRING,  IFDESCR, RONLY, var_ifEntry },
  526. X    {{MIB, 2, 2, 1, 3, 0xFF},  11, INTEGER, IFTYPE, RONLY, var_ifEntry },
  527. X    {{MIB, 2, 2, 1, 4, 0xFF},  11, INTEGER, IFMTU, RONLY, var_ifEntry },
  528. X    {{MIB, 2, 2, 1, 5, 0xFF},  11, GAUGE,   IFSPEED, RONLY, var_ifEntry },
  529. X    {{MIB, 2, 2, 1, 6, 0xFF},  11, STRING,  IFPHYSADDRESS, RONLY, var_ifEntry },
  530. X    {{MIB, 2, 2, 1, 7, 0xFF},  11, INTEGER, IFADMINSTATUS, RWRITE, var_ifEntry },
  531. X    {{MIB, 2, 2, 1, 8, 0xFF},  11, INTEGER, IFOPERSTATUS, RONLY, var_ifEntry },
  532. X    {{MIB, 2, 2, 1, 9, 0xFF},  11, TIMETICKS, IFLASTCHANGE, RONLY, var_ifEntry },
  533. X    {{MIB, 2, 2, 1, 10, 0xFF}, 11, COUNTER, IFINOCTETS, RONLY, var_ifEntry },
  534. X    {{MIB, 2, 2, 1, 11, 0xFF}, 11, COUNTER, IFINUCASTPKTS, RONLY, var_ifEntry },
  535. X    {{MIB, 2, 2, 1, 12, 0xFF}, 11, COUNTER, IFINNUCASTPKTS, RONLY, var_ifEntry },
  536. X    {{MIB, 2, 2, 1, 13, 0xFF}, 11, COUNTER, IFINDISCARDS, RONLY, var_ifEntry },
  537. X    {{MIB, 2, 2, 1, 14, 0xFF}, 11, COUNTER, IFINERRORS, RONLY, var_ifEntry },
  538. X    {{MIB, 2, 2, 1, 15, 0xFF}, 11, COUNTER, IFINUNKNOWNPROTOS, RONLY, var_ifEntry },
  539. X    {{MIB, 2, 2, 1, 16, 0xFF}, 11, COUNTER, IFOUTOCTETS, RONLY, var_ifEntry },
  540. X    {{MIB, 2, 2, 1, 17, 0xFF}, 11, COUNTER, IFOUTUCASTPKTS, RONLY, var_ifEntry },
  541. X    {{MIB, 2, 2, 1, 18, 0xFF}, 11, COUNTER, IFOUTNUCASTPKTS, RONLY, var_ifEntry },
  542. X    {{MIB, 2, 2, 1, 19, 0xFF}, 11, COUNTER, IFOUTDISCARDS, RONLY, var_ifEntry },
  543. X    {{MIB, 2, 2, 1, 20, 0xFF}, 11, COUNTER, IFOUTERRORS, RONLY, var_ifEntry },
  544. X    {{MIB, 2, 2, 1, 21, 0xFF}, 11, GAUGE,   IFOUTQLEN, RONLY, var_ifEntry },
  545. X    {{MIB, 3, 1, 1, 1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, 16, INTEGER,    ATIFINDEX, RWRITE, var_atEntry }, 
  546. X    {{MIB, 3, 1, 1, 2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, 16, STRING,        ATPHYSADDRESS, RWRITE, var_atEntry }, 
  547. X    {{MIB, 3, 1, 1, 3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, 16, IPADDRESS,  ATNETADDRESS, RWRITE, var_atEntry },
  548. X    {{MIB, 4, 1, 0},        9, INTEGER, IPFORWARDING, RONLY, var_ip },
  549. X    {{MIB, 4, 2, 0},        9, INTEGER, IPDEFAULTTTL, RWRITE, var_ip },
  550. X    {{MIB, 4, 3, 0},        9, COUNTER, IPINRECEIVES, RONLY, var_ip },
  551. X    {{MIB, 4, 4, 0},        9, COUNTER, IPINHDRERRORS, RONLY, var_ip },
  552. X    {{MIB, 4, 5, 0},        9, COUNTER, IPINADDRERRORS, RONLY, var_ip },
  553. X    {{MIB, 4, 6, 0},        9, COUNTER, IPFORWDATAGRAMS, RONLY, var_ip },
  554. X    {{MIB, 4, 7, 0},        9, COUNTER, IPINUNKNOWNPROTOS, RONLY, var_ip },
  555. X    {{MIB, 4, 8, 0},        9, COUNTER, IPINDISCARDS, RONLY, var_ip },
  556. X    {{MIB, 4, 9, 0},        9, COUNTER, IPINDELIVERS, RONLY, var_ip },
  557. X    {{MIB, 4, 10, 0},        9, COUNTER, IPOUTREQUESTS, RONLY, var_ip },
  558. X    {{MIB, 4, 11, 0},        9, COUNTER, IPOUTDISCARDS, RONLY, var_ip },
  559. X    {{MIB, 4, 12, 0},        9, COUNTER, IPOUTNOROUTES, RONLY, var_ip },
  560. X    {{MIB, 4, 13, 0},        9, INTEGER, IPREASMTIMEOUT, RONLY, var_ip },
  561. X    {{MIB, 4, 14, 0},        9, COUNTER, IPREASMREQDS, RONLY, var_ip },
  562. X    {{MIB, 4, 15, 0},        9, COUNTER, IPREASMOKS, RONLY, var_ip },
  563. X    {{MIB, 4, 16, 0},        9, COUNTER, IPREASMFAILS, RONLY, var_ip },
  564. X    {{MIB, 4, 17, 0},        9, COUNTER, IPFRAGOKS, RONLY, var_ip },
  565. X    {{MIB, 4, 18, 0},        9, COUNTER, IPFRAGFAILS, RONLY, var_ip },
  566. X    {{MIB, 4, 19, 0},        9, COUNTER, IPFRAGCREATES, RONLY, var_ip },
  567. X    {{MIB, 4, 20, 1, 1, 0xFF, 0xFF, 0xFF, 0xFF}, 14, IPADDRESS, IPADADDR, RONLY, var_ipAddrEntry },
  568. X    {{MIB, 4, 20, 1, 2, 0xFF, 0xFF, 0xFF, 0xFF}, 14, INTEGER,    IPADIFINDEX, RONLY, var_ipAddrEntry },
  569. X    {{MIB, 4, 20, 1, 3, 0xFF, 0xFF, 0xFF, 0xFF}, 14, IPADDRESS, IPADNETMASK, RONLY, var_ipAddrEntry },
  570. X    {{MIB, 4, 20, 1, 4, 0xFF, 0xFF, 0xFF, 0xFF}, 14, INTEGER,    IPADBCASTADDR, RONLY, var_ipAddrEntry },
  571. X    {{MIB, 4, 21, 1, 1, 0xFF, 0xFF, 0xFF, 0xFF}, 14, IPADDRESS, IPROUTEDEST, RWRITE, var_ipRouteEntry },
  572. X    {{MIB, 4, 21, 1, 2, 0xFF, 0xFF, 0xFF, 0xFF}, 14, INTEGER,    IPROUTEIFINDEX, RWRITE, var_ipRouteEntry },
  573. X    {{MIB, 4, 21, 1, 3, 0xFF, 0xFF, 0xFF, 0xFF}, 14, INTEGER,    IPROUTEMETRIC1, RWRITE, var_ipRouteEntry },
  574. X    {{MIB, 4, 21, 1, 4, 0xFF, 0xFF, 0xFF, 0xFF}, 14, INTEGER,    IPROUTEMETRIC2, RWRITE, var_ipRouteEntry },
  575. X    {{MIB, 4, 21, 1, 5, 0xFF, 0xFF, 0xFF, 0xFF}, 14, INTEGER,    IPROUTEMETRIC3, RWRITE, var_ipRouteEntry },
  576. X    {{MIB, 4, 21, 1, 6, 0xFF, 0xFF, 0xFF, 0xFF}, 14, INTEGER,    IPROUTEMETRIC4, RWRITE, var_ipRouteEntry },
  577. X    {{MIB, 4, 21, 1, 7, 0xFF, 0xFF, 0xFF, 0xFF}, 14, IPADDRESS, IPROUTENEXTHOP, RWRITE, var_ipRouteEntry },
  578. X    {{MIB, 4, 21, 1, 8, 0xFF, 0xFF, 0xFF, 0xFF}, 14, INTEGER,    IPROUTETYPE, RWRITE, var_ipRouteEntry },
  579. X    {{MIB, 4, 21, 1, 9, 0xFF, 0xFF, 0xFF, 0xFF}, 14, INTEGER,    IPROUTEPROTO, RONLY, var_ipRouteEntry },
  580. X    {{MIB, 4, 21, 1, 10, 0xFF, 0xFF, 0xFF, 0xFF}, 14, INTEGER,    IPROUTEAGE, RWRITE, var_ipRouteEntry },
  581. X    {{MIB, 5, 1, 0},        9, COUNTER, ICMPINMSGS, RONLY, var_icmp },
  582. X    {{MIB, 5, 2, 0},        9, COUNTER, ICMPINERRORS, RONLY, var_icmp },
  583. X    {{MIB, 5, 3, 0},        9, COUNTER, ICMPINDESTUNREACHS, RONLY, var_icmp },
  584. X    {{MIB, 5, 4, 0},        9, COUNTER, ICMPINTIMEEXCDS, RONLY, var_icmp },
  585. X    {{MIB, 5, 5, 0},        9, COUNTER, ICMPINPARMPROBS, RONLY, var_icmp },
  586. X    {{MIB, 5, 6, 0},        9, COUNTER, ICMPINSRCQUENCHS, RONLY, var_icmp },
  587. X    {{MIB, 5, 7, 0},        9, COUNTER, ICMPINREDIRECTS, RONLY, var_icmp },
  588. X    {{MIB, 5, 8, 0},        9, COUNTER, ICMPINECHOS, RONLY, var_icmp },
  589. X    {{MIB, 5, 9, 0},        9, COUNTER, ICMPINECHOREPS, RONLY, var_icmp },
  590. X    {{MIB, 5, 10, 0},        9, COUNTER, ICMPINTIMESTAMPS, RONLY, var_icmp },
  591. X    {{MIB, 5, 11, 0},        9, COUNTER, ICMPINTIMESTAMPREPS, RONLY, var_icmp },
  592. X    {{MIB, 5, 12, 0},        9, COUNTER, ICMPINADDRMASKS, RONLY, var_icmp },
  593. X    {{MIB, 5, 13, 0},        9, COUNTER, ICMPINADDRMASKREPS, RONLY, var_icmp },
  594. X    {{MIB, 5, 14, 0},        9, COUNTER, ICMPOUTMSGS, RONLY, var_icmp },
  595. X    {{MIB, 5, 15, 0},        9, COUNTER, ICMPOUTERRORS, RONLY, var_icmp },
  596. X    {{MIB, 5, 16, 0},        9, COUNTER, ICMPOUTDESTUNREACHS, RONLY, var_icmp },
  597. X    {{MIB, 5, 17, 0},        9, COUNTER, ICMPOUTTIMEEXCDS, RONLY, var_icmp },
  598. X    {{MIB, 5, 18, 0},        9, COUNTER, ICMPOUTPARMPROBS, RONLY, var_icmp },
  599. X    {{MIB, 5, 19, 0},        9, COUNTER, ICMPOUTSRCQUENCHS, RONLY, var_icmp },
  600. X    {{MIB, 5, 20, 0},        9, COUNTER, ICMPOUTREDIRECTS, RONLY, var_icmp },
  601. X    {{MIB, 5, 21, 0},        9, COUNTER, ICMPOUTECHOS, RONLY, var_icmp },
  602. X    {{MIB, 5, 22, 0},        9, COUNTER, ICMPOUTECHOREPS, RONLY, var_icmp },
  603. X    {{MIB, 5, 23, 0},        9, COUNTER, ICMPOUTTIMESTAMPS, RONLY, var_icmp },
  604. X    {{MIB, 5, 24, 0},        9, COUNTER, ICMPOUTTIMESTAMPREPS, RONLY, var_icmp },
  605. X    {{MIB, 5, 25, 0},        9, COUNTER, ICMPOUTADDRMASKS, RONLY, var_icmp },
  606. X    {{MIB, 5, 26, 0},        9, COUNTER, ICMPOUTADDRMASKREPS, RONLY, var_icmp },
  607. X    {{MIB, 7, 1, 0},        9, COUNTER, UDPINDATAGRAMS, RONLY, var_udp }, 
  608. X    {{MIB, 7, 2, 0},        9, COUNTER, UDPNOPORTS, RONLY, var_udp },
  609. X    {{MIB, 7, 3, 0},        9, COUNTER, UDPINERRORS, RONLY, var_udp }, 
  610. X    {{MIB, 7, 4, 0},        9, COUNTER, UDPOUTDATAGRAMS, RONLY, var_udp }
  611. X};
  612. X
  613. X
  614. X
  615. X
  616. X/*
  617. X * getStatPtr - return a pointer to the named variable, as well as it's
  618. X * type, length, and access control list.
  619. X *
  620. X * If an exact match for the variable name exists, it is returned.  If not,
  621. X * and exact is false, the next variable lexicographically after the
  622. X * requested one is returned.
  623. X *
  624. X * If no appropriate variable can be found, NULL is returned.
  625. X */
  626. Xu_char  *
  627. XgetStatPtr(name, namelen, type, len, acl, exact, access_method)
  628. X    oid        *name;        /* IN - name of var, OUT - name matched */
  629. X    int        *namelen;   /* IN -number of sub-ids in name, OUT - subid-is in matched name */
  630. X    u_char    *type;        /* OUT - type of matched variable */
  631. X    int        *len;        /* OUT - length of matched variable */
  632. X    u_short    *acl;        /* OUT - access control list */
  633. X    int        exact;        /* IN - TRUE if exact match wanted */
  634. X    int        *access_method; /* OUT - 1 if function, 0 if char * */
  635. X{
  636. X
  637. X    register struct variable    *vp;
  638. X
  639. X    register int    x;
  640. X    register u_char    *access;
  641. X    int            result;
  642. X
  643. X    for(x = 0, vp = variables; x < sizeof(variables)/sizeof(struct variable); vp++, x++){
  644. X    /*
  645. X     * compare should be expanded inline.
  646. X     */
  647. X    result = compare(name, *namelen, vp->name, (int)vp->namelen);
  648. X    if ((result < 0) || (exact && (result == 0))){
  649. X        access = (*(vp->findVar))(vp, name, namelen, exact, len, access_method);
  650. X        if (access != NULL)
  651. X        break;
  652. X    }
  653. X    }
  654. X    if (x == sizeof(variables)/sizeof(struct variable))
  655. X    return NULL;
  656. X
  657. X    /* vp now points to the approprate struct */
  658. X    *type = vp->type;
  659. X    *acl = vp->acl;
  660. X    return access;
  661. X}
  662. X
  663. X
  664. X
  665. Xint
  666. Xcompare(name1, len1, name2, len2)
  667. X    register oid        *name1, *name2;
  668. X    register int        len1, len2;
  669. X{
  670. X    register int    len;
  671. X
  672. X    /* len = minimum of len1 and len2 */
  673. X    if (len1 < len2)
  674. X    len = len1;
  675. X    else
  676. X    len = len2;
  677. X    /* find first non-matching byte */
  678. X    while(len-- > 0){
  679. X    if (*name1 < *name2)
  680. X        return -1;
  681. X    if (*name2++ < *name1++)
  682. X        return 1;
  683. X    }
  684. X    /* bytes match up to length of shorter string */
  685. X    if (len1 < len2)
  686. X    return -1;  /* name1 shorter, so it is "less" */
  687. X    if (len2 < len1)
  688. X    return 1;
  689. X    return 0;    /* both strings are equal */
  690. X}
  691. X
  692. X
  693. Xu_char *
  694. Xvar_system(vp, name, length, exact, var_len, access_method)
  695. X    register struct variable *vp;   /* IN - pointer to variable entry that points here */
  696. X    register oid    *name;        /* IN/OUT - input name requested, output name found */
  697. X    register int    *length;    /* IN/OUT - length of input and output oid's */
  698. X    int            exact;        /* IN - TRUE if an exact match was requested. */
  699. X    int            *var_len;   /* OUT - length of variable or 0 if function returned. */
  700. X    int            *access_method;    /* OUT - 1 if function, 0 if char pointer. */
  701. X{
  702. X    if (exact && (compare(name, *length, vp->name, (int)vp->namelen) != 0))
  703. X    return NULL;
  704. X    bcopy((char *)vp->name, (char *)name, (int)vp->namelen * sizeof(oid));
  705. X    *length = vp->namelen;
  706. X    *access_method = 0;
  707. X    *var_len = sizeof(long);    /* default length */
  708. X    switch (vp->magic){
  709. X    case VERSION_DESCR:
  710. X        *var_len = strlen(version_descr);
  711. X        return (u_char *)version_descr;
  712. X    case VERSION_ID:
  713. X        *var_len = sizeof(version_id);
  714. X        return (u_char *)version_id;
  715. X    case CFG_NNETS:
  716. X        return (u_char *)&cfg_nnets;
  717. X    case UPTIME:
  718. X        return (u_char *)&uptime;
  719. X    default:
  720. X        ERROR("");
  721. X    }
  722. X    return NULL;
  723. X}
  724. X
  725. X
  726. Xu_char *
  727. Xvar_ifEntry(vp, name, length, exact, var_len, access_method)
  728. X    register struct variable *vp;   /* IN - pointer to variable entry that points here */
  729. X    register oid    *name;        /* IN/OUT - input name requested, output name found */
  730. X    register int    *length;    /* IN/OUT - length of input and output oid's */
  731. X    int            exact;        /* IN - TRUE if an exact match was requested. */
  732. X    int            *var_len;   /* OUT - length of variable or 0 if function returned. */
  733. X    int            *access_method; /* OUT - 1 if function, 0 if char pointer. */
  734. X{
  735. X    oid            newname[MAX_NAME_LEN];
  736. X    register int    interface;
  737. X    register struct mib_ifEntry    *ifp;
  738. X    extern struct conf    conf;
  739. X    int            result;
  740. X
  741. X    bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid));
  742. X    /* find "next" interface */
  743. X    for(interface = 1; interface <= MAX_INTERFACES; interface++){
  744. X    newname[10] = (oid)interface;
  745. X    result = compare(name, *length, newname, (int)vp->namelen);
  746. X    if ((exact && (result == 0)) || (!exact && (result < 0)))
  747. X        break;
  748. X    }
  749. X    if (interface > MAX_INTERFACES)
  750. X    return NULL;
  751. X    interface--; /* translate into internal index of interfaces */
  752. X    bcopy((char *)newname, (char *)name, (int)vp->namelen * sizeof(oid));
  753. X    *length = vp->namelen;
  754. X    *access_method = 0;
  755. X    *var_len = sizeof(long);
  756. X
  757. X    ifp = &mib_ifEntry[interface];
  758. X    switch (vp->magic){
  759. X        case IFDESCR:
  760. X        *var_len = strlen(ifp->ifDescr);
  761. X        return (u_char *)ifp->ifDescr;
  762. X    case IFPHYSADDRESS:
  763. X        *var_len = ifp->PhysAddrLen;
  764. X        if (interface == 0)
  765. X            return (u_char *)ifie.if_haddr;
  766. X        else {
  767. X        /*
  768. X         * As far as IP is concerned, the "physical" address includes the Appletalk
  769. X         * network address as well as node number.
  770. X         */
  771. X        return_buf[0] = ((u_char *)&conf.atneta)[0];
  772. X        return_buf[1] = ((u_char *)&conf.atneta)[1];
  773. X        return_buf[2] = ifab.if_dnode;
  774. X            return (u_char *)return_buf;
  775. X        }
  776. X    case IFOUTQLEN:
  777. X#ifdef notdef
  778. X        if (interface == 0)
  779. X        long_return = sendq->pq_len;
  780. X        else
  781. X        long_return = 0;    /* There is no appletalk transmit queue */
  782. X#else
  783. X        long_return = 0;
  784. X#endif
  785. X        return (u_char *)&long_return;
  786. X    default:
  787. X        return (u_char *)(((char *)ifp) + vp->magic);
  788. X    }
  789. X}
  790. X
  791. X/* 
  792. X * from arp.c:
  793. X * There is no arp.h, so this must be recreated here.
  794. X */
  795. X#define    ARPHLNMAX    6    /* largest arp_hln value needed */
  796. X#define    ARPPLN        4    /* length of protocol address (IP) */
  797. Xstruct    arptab {
  798. X    iaddr_t at_iaddr;        /* internet address */
  799. X    u_char    at_haddr[ARPHLNMAX];    /* hardware address */
  800. X    u_char    at_timer;        /* minutes since last reference */
  801. X    u_char    at_flags;        /* flags */
  802. X    struct    pbuf *at_hold;        /* last packet until resolved/timeout */
  803. X};
  804. X/* at_flags field values */
  805. X#define    ATF_INUSE    1        /* entry in use */
  806. X#define ATF_COM        2        /* completed entry (haddr valid) */
  807. X
  808. X#define    ARPTAB_BSIZ    5        /* bucket size */
  809. X#define    ARPTAB_NB    11        /* number of buckets */
  810. X#define    ARPTAB_SIZE    (ARPTAB_BSIZ * ARPTAB_NB)
  811. X
  812. X
  813. Xu_char *
  814. Xvar_atEntry(vp, name, length, exact, var_len, access_method)
  815. X    register struct variable *vp;    /* IN - pointer to variable entry that points here */
  816. X    register oid        *name;    /* IN/OUT - input name requested, output name found */
  817. X    register int        *length;    /* IN/OUT - length of input and output oid's */
  818. X    int                exact;    /* IN - TRUE if an exact match was requested. */
  819. X    int                *var_len;    /* OUT - length of variable or 0 if function returned. */
  820. X    int                *access_method; /* OUT - 1 if function, 0 if char pointer. */
  821. X{
  822. X    /*
  823. X     * object identifier is of form:
  824. X     * 1.3.6.1.2.1.3.1.1.1.interface.1.A.B.C.D,  where A.B.C.D is IP address.
  825. X     * Interface is at offset 10,
  826. X     * IPADDR starts at offset 12.
  827. X     */
  828. X    oid                lowest[16];
  829. X    oid                current[16];
  830. X    register struct arptab  *arp;
  831. X    struct arptab        *lowarp = 0;
  832. X    extern struct arptab    arptab[];
  833. X    register struct ipdad   *ipdp;
  834. X    struct ipdad        *lowipdp = 0;
  835. X    extern struct ipdad        ipdad[];
  836. X    long            ipaddr;
  837. X    int                addrlen;
  838. X    extern struct conf        conf;
  839. X    register u_char        *cp;
  840. X    register oid        *op;
  841. X    register int        count;
  842. X
  843. X    /* fill in object part of name for current (less sizeof instance part) */
  844. X    bcopy((char *)vp->name, (char *)current, (int)(vp->namelen - 6) * sizeof(oid));
  845. X    for(arp = arptab; arp < arptab + ARPTAB_SIZE; arp++){
  846. X    if (!(arp->at_flags & ATF_COM))    /* if this entry isn't valid */
  847. X        continue;
  848. X    /* create new object id */
  849. X    current[10] = 1;    /* ifIndex == 1 (ethernet) */
  850. X    current[11] = 1;
  851. X    cp = (u_char *)&(arp->at_iaddr);
  852. X    op = current + 12;
  853. X    for(count = 4; count > 0; count--)
  854. X        *op++ = *cp++;
  855. X    if (exact){
  856. X        if (compare(current, 16, name, *length) == 0){
  857. X        bcopy((char *)current, (char *)lowest, 16 * sizeof(oid));
  858. X        lowarp = arp;
  859. X        break;    /* no need to search further */
  860. X        }
  861. X    } else {
  862. X        if ((compare(current, 16, name, *length) > 0) && (!lowarp || (compare(current, 16, lowest, 16) < 0))){
  863. X        /*
  864. X         * if new one is greater than input and closer to input than
  865. X         * previous lowest, save this one as the "next" one.
  866. X         */
  867. X        bcopy((char *)current, (char *)lowest, 16 * sizeof(oid));
  868. X        lowarp = arp;
  869. X        }
  870. X    }
  871. X    }
  872. X    ipaddr = conf.ipaddr + conf.ipstatic + 1;
  873. X    for(ipdp = ipdad; ipdp < ipdad + NIPDAD; ipdp++, ipaddr++){
  874. X    if (ipdp->timer == 0)    /* if this entry is unused, continue */
  875. X        continue;
  876. X    /* create new object id */
  877. X    current[10] = 2;    /* ifIndex == 2 (appletalk) */
  878. X    current[11] = 1;
  879. X    cp = (u_char *)&ipaddr;
  880. X    op = current + 12;
  881. X    for(count = 4; count > 0; count--)
  882. X        *op++ = *cp++;
  883. X    if (exact){
  884. X        if (compare(current, 16, name, *length) == 0){
  885. X        bcopy((char *)current, (char *)lowest, 16 * sizeof(oid));
  886. X        lowipdp = ipdp;
  887. X        lowarp = 0;
  888. X        break;    /* no need to search further */
  889. X        }
  890. X    } else {
  891. X        if ((compare(current, 16, name, *length) > 0) && ((!lowarp && !lowipdp) || (compare(current, 16, lowest, 16) < 0))){
  892. X        /*
  893. X         * if new one is greater than input and closer to input than
  894. X         * previous lowest, save this one as the "next" one.
  895. X         */
  896. X        bcopy((char *)current, (char *)lowest, 16 * sizeof(oid));
  897. X        lowipdp = ipdp;
  898. X        /* ipdad entry is lower, so invalidate arp entry */
  899. X        lowarp = 0;
  900. X        }
  901. X    }
  902. X    }
  903. X    if (lowarp != 0){    /* arp entry was lowest */
  904. X    addrlen = 6;
  905. X    bcopy((char *)lowarp->at_haddr, (char *)return_buf, 6);
  906. X    } else if (lowipdp != 0) {
  907. X    addrlen = 3;
  908. X    /*
  909. X     * As far as IP is concerned, the "physical" address includes the Appletalk
  910. X     * network address as well as node number.
  911. X     */
  912. X    return_buf[0] = ((u_char *)&lowipdp->net)[0];
  913. X    return_buf[1] = ((u_char *)&lowipdp->net)[1];
  914. X    return_buf[2] = lowipdp->node;
  915. X    } else
  916. X    return NULL;    /* no match */
  917. X    bcopy((char *)lowest, (char *)name, 16 * sizeof(oid));
  918. X    *length = 16;
  919. X    *access_method = 0;
  920. X    switch(vp->magic){
  921. X    case ATIFINDEX:
  922. X        *var_len = sizeof long_return;
  923. X        long_return = lowest[10];
  924. X        return (u_char *)&long_return;
  925. X    case ATPHYSADDRESS:
  926. X        *var_len = addrlen;
  927. X        return (u_char *)return_buf;
  928. X    case ATNETADDRESS:
  929. X        *var_len = sizeof long_return;
  930. X        cp = (u_char *)&long_return;
  931. X        op = lowest + 12;
  932. X        for(count = 4; count > 0; count--)
  933. X        *cp++ = *op++;
  934. X        return (u_char *)&long_return;
  935. X    default:
  936. X        ERROR("");
  937. X   }
  938. X   return NULL;
  939. X}
  940. X
  941. Xu_char *
  942. Xvar_ip(vp, name, length, exact, var_len, access_method)
  943. X    register struct variable *vp;   /* IN - pointer to variable entry that points here */
  944. X    oid        *name;        /* IN/OUT - input name requested, output name found */
  945. X    int        *length;        /* IN/OUT - length of input and output oid's */
  946. X    int        exact;        /* IN - TRUE if an exact match was requested. */
  947. X    int        *var_len;        /* OUT - length of variable or 0 if function returned. */
  948. X    int        *access_method; /* OUT - 1 if function, 0 if char pointer. */
  949. X{
  950. X    if (exact && (compare(name, *length, vp->name, (int)vp->namelen) != 0))
  951. X    return NULL;
  952. X    bcopy((char *)vp->name, (char *)name, (int)vp->namelen * sizeof(oid));
  953. X    *length = vp->namelen;
  954. X    *access_method = 0;
  955. X    *var_len = sizeof(long);
  956. X    return ((u_char *)&mib_ip) + vp->magic;
  957. X}
  958. X
  959. Xu_char *
  960. Xvar_ipRouteEntry(vp, name, length, exact, var_len, access_method)
  961. X    register struct variable *vp;   /* IN - pointer to variable entry that points here */
  962. X    register oid        *name;        /* IN/OUT - input name requested, output name found */
  963. X    register int    *length;    /* IN/OUT - length of input and output strings */
  964. X    int            exact;        /* IN - TRUE if an exact match was requested. */
  965. X    int            *var_len;   /* OUT - length of variable or 0 if function returned. */
  966. X    int            *access_method; /* OUT - 1 if function, 0 if char pointer. */
  967. X{
  968. X    oid                newname[MAX_NAME_LEN];
  969. X    register int        entry;
  970. X    register struct mib_ipRouteEntry    *routep;
  971. X    int                result;
  972. X    register int        count;
  973. X    register u_char        *cp;
  974. X    register oid        *op;
  975. X    extern struct conf        conf;
  976. X
  977. X    /* set up a routing table to search. All other values are set at startup. */
  978. X    routep = mib_ipRouteEntry;
  979. X    routep[ROUTE_DEFAULT].ipRouteDest = 0;
  980. X    routep[ROUTE_DEFAULT].ipRouteNextHop = conf.iproutedef;
  981. X    routep[ROUTE_LOCAL].ipRouteDest = ipnetpart(conf.ipaddr);
  982. X    routep[ROUTE_LOCAL].ipRouteNextHop = conf.ipaddr;
  983. X
  984. X    bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid));
  985. X    /* find "next" route */
  986. X    for(entry = 0; entry < ROUTE_ENTRIES; entry++){
  987. X    cp = (u_char *)&routep->ipRouteDest;
  988. X    op = newname + 10;
  989. X    for(count = 4; count > 0; count--)
  990. X        *op++ = *cp++;
  991. X    result = compare(name, *length, newname, (int)vp->namelen);
  992. X    if ((exact && (result == 0)) || (!exact && (result < 0)))
  993. X        break;
  994. X    routep++;
  995. X    }
  996. X    if (entry >= ROUTE_ENTRIES)
  997. X    return NULL;
  998. X    bcopy((char *)newname, (char *)name, (int)vp->namelen * sizeof(oid));
  999. X    *length = vp->namelen;
  1000. X    *access_method = 0;
  1001. X    *var_len = sizeof(long);
  1002. X
  1003. X    routep = &mib_ipRouteEntry[entry];
  1004. X    switch (vp->magic){
  1005. X    case IPROUTENEXTHOP:
  1006. X        if (entry == ROUTE_DEFAULT)
  1007. X        return (u_char *)&conf.iproutedef;
  1008. X        else
  1009. X        return (u_char *)&conf.ipaddr;
  1010. X    default:
  1011. X        return (u_char *)(((u_char *)routep) + vp->magic);
  1012. X    }
  1013. X}
  1014. X
  1015. Xu_char *
  1016. Xvar_ipAddrEntry(vp, name, length, exact, var_len, access_method)
  1017. X    register struct variable *vp;    /* IN - pointer to variable entry that points here */
  1018. X    register oid    *name;        /* IN/OUT - input name requested, output name found */
  1019. X    register int    *length;    /* IN/OUT - length of input and output oid's */
  1020. X    int            exact;        /* IN - TRUE if an exact match was requested. */
  1021. X    int            *var_len;   /* OUT - length of variable or 0 if function returned. */
  1022. X    int            *access_method; /* OUT - 1 if function, 0 if char pointer. */
  1023. X{
  1024. X    oid            newname[14];
  1025. X    int            result;
  1026. X    extern struct conf    conf;
  1027. X    register int    count;
  1028. X    register u_char *cp;
  1029. X    register oid    *op;
  1030. X
  1031. X    bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid));
  1032. X    /* now find "next" ipaddr */
  1033. X    /*
  1034. X     * foreach ipaddress entry, cobble up newname with its IP address,
  1035. X     * by copying the ipaddress into the 10 - 13't subid's
  1036. X     * then compare with name.  If greater than name and less than lowest,
  1037. X     * save as new lowest.
  1038. X     * Having said all that, I'm now going to cheat because I only have one
  1039. X     * IP address (on both interfaces).
  1040. X     */
  1041. X    cp = (u_char *)&conf.ipaddr;
  1042. X    op = newname + 10;
  1043. X    for(count = sizeof(conf.ipaddr); count > 0; count--)
  1044. X    *op++ = *cp++;
  1045. X    result = compare(name, *length, newname, (int)vp->namelen);
  1046. X    if ((exact && (result != 0)) || (!exact && (result >= 0)))
  1047. X    return NULL;    /* no match */
  1048. X    bcopy((char *)newname, (char *)name, (int)vp->namelen * sizeof(oid));
  1049. X    *length = vp->namelen;
  1050. X    *access_method = 0;
  1051. X    *var_len = sizeof(long);
  1052. X
  1053. X    switch (vp->magic){
  1054. X        case IPADADDR:
  1055. X        return (u_char *)&conf.ipaddr;
  1056. X        case IPADIFINDEX:
  1057. X        /*
  1058. X         * Always return ethernet interface. SNMP
  1059. X         * has no access method to access instances
  1060. X         * on different interfaces with same IP address.
  1061. X         */
  1062. X        long_return = 1;
  1063. X        return (u_char *)&long_return;
  1064. X    case IPADNETMASK:
  1065. X        long_return = (IN_CLASSA(conf.ipaddr) ? IN_CLASSA_NET :
  1066. X            (IN_CLASSB(conf.ipaddr) ? IN_CLASSB_NET : IN_CLASSC_NET));
  1067. X        return (u_char *)&long_return;
  1068. X    case IPADBCASTADDR:
  1069. X        long_return = conf.ipbroad & 1;
  1070. X        return (u_char *)&long_return;
  1071. X    default:
  1072. X        ERROR("");
  1073. X    }
  1074. X    return NULL;
  1075. X}
  1076. X
  1077. X
  1078. Xu_char *
  1079. Xvar_icmp(vp, name, length, exact, var_len, access_method)
  1080. X    register struct variable *vp;    /* IN - pointer to variable entry that points here */
  1081. X    oid        *name;        /* IN/OUT - input name requested, output name found */
  1082. X    int        *length;        /* IN/OUT - length of input and output oid's */
  1083. X    int        exact;        /* IN - TRUE if an exact match was requested. */
  1084. X    int        *var_len;        /* OUT - length of variable or 0 if function returned. */
  1085. X    int        *access_method; /* OUT - 1 if function, 0 if char pointer. */
  1086. X{
  1087. X    if (exact && (compare(name, *length, vp->name, (int)vp->namelen) != 0))
  1088. X    return NULL;
  1089. X    bcopy((char *)vp->name, (char *)name, (int)vp->namelen * sizeof(oid));
  1090. X    *length = vp->namelen;
  1091. X    *access_method = 0;
  1092. X    *var_len = sizeof(long); /* all following variables are sizeof long */
  1093. X    switch (vp->magic){
  1094. X    case ICMPINMSGS:
  1095. X        return (u_char *)&mib_icmpInMsgs;
  1096. X    case ICMPINERRORS:
  1097. X        return (u_char *)&mib_icmpInErrors;
  1098. X    case ICMPINDESTUNREACHS:
  1099. X        return (u_char *)&mib_icmpInCount[3];
  1100. X    case ICMPINTIMEEXCDS:
  1101. X        return (u_char *)&mib_icmpInCount[11];
  1102. X    case ICMPINPARMPROBS:
  1103. X        return (u_char *)&mib_icmpInCount[12];
  1104. X    case ICMPINSRCQUENCHS:
  1105. X        return (u_char *)&mib_icmpInCount[4];
  1106. X    case ICMPINREDIRECTS:
  1107. X        return (u_char *)&mib_icmpInCount[5];
  1108. X    case ICMPINECHOS:
  1109. X        return (u_char *)&mib_icmpInCount[8];
  1110. X    case ICMPINECHOREPS:
  1111. X        return (u_char *)&mib_icmpInCount[0];
  1112. X    case ICMPINTIMESTAMPS:
  1113. X        return (u_char *)&mib_icmpInCount[13];
  1114. X    case ICMPINTIMESTAMPREPS:
  1115. X        return (u_char *)&mib_icmpInCount[14];
  1116. X    case ICMPINADDRMASKS:
  1117. X        return (u_char *)&mib_icmpInCount[17];
  1118. X    case ICMPINADDRMASKREPS:
  1119. X        return (u_char *)&mib_icmpInCount[18];
  1120. X    case ICMPOUTMSGS:
  1121. X        return (u_char *)&mib_icmpOutMsgs;
  1122. X    case ICMPOUTERRORS:
  1123. X        return (u_char *)&mib_icmpOutErrors;
  1124. X    case ICMPOUTDESTUNREACHS:
  1125. X        return (u_char *)&mib_icmpOutCount[3];
  1126. X    case ICMPOUTTIMEEXCDS:
  1127. X        return (u_char *)&mib_icmpOutCount[11];
  1128. X    case ICMPOUTPARMPROBS:
  1129. X        return (u_char *)&mib_icmpOutCount[12];
  1130. X    case ICMPOUTSRCQUENCHS:
  1131. X        return (u_char *)&mib_icmpOutCount[4];
  1132. X    case ICMPOUTREDIRECTS:
  1133. X        return (u_char *)&mib_icmpOutCount[5];
  1134. X    case ICMPOUTECHOS:
  1135. X        return (u_char *)&mib_icmpOutCount[8];
  1136. X    case ICMPOUTECHOREPS:
  1137. X        return (u_char *)&mib_icmpOutCount[0];
  1138. X    case ICMPOUTTIMESTAMPS:
  1139. X        return (u_char *)&mib_icmpOutCount[13];
  1140. X    case ICMPOUTTIMESTAMPREPS:
  1141. X        return (u_char *)&mib_icmpOutCount[14];
  1142. X    case ICMPOUTADDRMASKS:
  1143. X        return (u_char *)&mib_icmpOutCount[17];
  1144. X    case ICMPOUTADDRMASKREPS:
  1145. X        return (u_char *)&mib_icmpOutCount[18];
  1146. X    default:
  1147. X        ERROR("");
  1148. X    }
  1149. X    return NULL;
  1150. X}
  1151. X
  1152. X
  1153. Xu_char *
  1154. Xvar_udp(vp, name, length, exact, var_len, access_method)
  1155. X    register struct variable *vp;    /* IN - pointer to variable entry that points here */
  1156. X    oid        *name;        /* IN/OUT - input name requested, output name found */
  1157. X    int        *length;        /* IN/OUT - length of input and output oid's */
  1158. X    int        exact;        /* IN - TRUE if an exact match was requested. */
  1159. X    int        *var_len;        /* OUT - length of variable or 0 if function returned. */
  1160. X    int        *access_method; /* OUT - 1 if function, 0 if char pointer. */
  1161. X{
  1162. X    if (exact && (compare(name, *length, vp->name, (int)vp->namelen) != 0))
  1163. X    return NULL;
  1164. X    bcopy((char *)vp->name, (char *)name, (int)vp->namelen * sizeof(oid));
  1165. X    *length = vp->namelen;
  1166. X    *access_method = 0;
  1167. X    *var_len = sizeof(long);
  1168. X    return ((u_char *)&mib_udp) + vp->magic;
  1169. X}
  1170. END_OF_FILE
  1171.   if test 33903 -ne `wc -c <'nocol-3.0/src/cmu-snmp/include/snmp_vars.c.kip'`; then
  1172.     echo shar: \"'nocol-3.0/src/cmu-snmp/include/snmp_vars.c.kip'\" unpacked with wrong size!
  1173.   fi
  1174.   # end of 'nocol-3.0/src/cmu-snmp/include/snmp_vars.c.kip'
  1175. fi
  1176. if test -f 'nocol-3.0/src/support/multiping/multiping.c' -a "${1}" != "-c" ; then 
  1177.   echo shar: Will not clobber existing file \"'nocol-3.0/src/support/multiping/multiping.c'\"
  1178. else
  1179.   echo shar: Extracting \"'nocol-3.0/src/support/multiping/multiping.c'\" \(29414 characters\)
  1180.   sed "s/^X//" >'nocol-3.0/src/support/multiping/multiping.c' <<'END_OF_FILE'
  1181. X#ifndef lint
  1182. Xchar            copyright[] =
  1183. X"@(#) Copyright (c) 1989 The Regents of the University of California.\n\
  1184. X All rights reserved.\n";
  1185. X#endif                /* not lint */
  1186. X
  1187. X#ifndef lint
  1188. Xstatic char     sccsid[] = "@(#)ping.c    5.9 (Berkeley) 5/12/91";
  1189. X#endif                /* not lint */
  1190. X
  1191. X#ifndef lint
  1192. Xstatic char rcsid[] = "$Header: /home/aggarwal/lsrc/nocol/src/support/multiping/RCS/multiping.c,v 1.5 1993/10/31 05:25:12 aggarwal Exp $" ;
  1193. X#endif
  1194. X
  1195. X/*
  1196. X * (Multi) P I N G . C
  1197. X * 
  1198. X * Using the InterNet Control Message Protocol (ICMP) "ECHO" facility, measure
  1199. X * round-trip-delays and packet loss across network paths.
  1200. X * 
  1201. X * Author -
  1202. X *      Mike Muuss
  1203. X *      U. S. Army Ballistic Research Laboratory
  1204. X *      December, 1983
  1205. X * Modified at Uc Berkeley
  1206. X * Record Route and verbose headers - Phil Dykstra, BRL, March 1988.
  1207. X * ttl, duplicate detection - Cliff Frost, UCB, April 1989
  1208. X * Pad pattern - Cliff Frost (from Tom Ferrin, UCSF), April 1989
  1209. X * Wait for dribbles, option decoding, pkt compare - vjs@sgi.com, May 1989
  1210. X * Ping multiple sites simultaneously - Spencer Sun, Princeton/JvNC, June 1992
  1211. X * 
  1212. X * Status - Public Domain.  Distribution Unlimited. Bugs - More statistics
  1213. X * could always be gathered. This program has to run SUID to ROOT to access
  1214. X * the ICMP socket.
  1215. X *
  1216. X * $Log: multiping.c,v $
  1217. X * Revision 1.5  1993/10/31  05:25:12  aggarwal
  1218. X * Had an extra '*' in sendto (for 'to'). Reported by Rick Beebe @Yale
  1219. X *
  1220. X * Revision 1.4  1993/10/31  05:23:05  conklin
  1221. X * Added loop/delay to prevent the return packets from overflowing the
  1222. X * kernel.
  1223. X *
  1224. X * Revision 1.3  1992/06/10  15:04:00  spencer
  1225. X * Realized that since recvfrom() tells where the packet came from, I don't
  1226. X * need to use the upper four bits to keep track of it (as long as the
  1227. X * same IP# doesn't show up more than once on the command line).  So I
  1228. X * stopped using the upper four bits as a tag, freeing up the full 16 bits
  1229. X * for the sequence number.  Made a separate usage() function and an
  1230. X * output_new_style() function for clarity.
  1231. X *
  1232. X * Revision 1.2  1992/06/10  14:58:39  spencer
  1233. X * First completed version of multiping.  Uses upper four bits of the ICMP
  1234. X * sequence number field in the ICMP header to keep track of which remote
  1235. X * site the echo is going to or coming from.
  1236. X *
  1237. X * This version was reconstructed backwards, after-the-fact, so it probably
  1238. X * has some bugs and quirks in it.  Things to check are the bit manipulation
  1239. X * for the sequence ID numbers, and whether or not prefinish() screws things
  1240. X * up.  The only other changes to be made are to make a separate usage()
  1241. X * function and a output_new_style() function for clarity.
  1242. X *
  1243. X * Revision 1.1  1992/06/10  14:57:07  spencer
  1244. X * Initial revision
  1245. X *
  1246. X */
  1247. X#include <stdio.h>
  1248. X#include <netdb.h>
  1249. X#include <unistd.h>
  1250. X#include <ctype.h>
  1251. X#include <errno.h>
  1252. X#include <string.h>
  1253. X#include <values.h>
  1254. X
  1255. X#include <sys/param.h>
  1256. X#include <sys/socket.h>
  1257. X#include <sys/file.h>
  1258. X#include <sys/time.h>
  1259. X#include <sys/signal.h>
  1260. X
  1261. X#include <netinet/in_systm.h>
  1262. X#include <netinet/in.h>
  1263. X#include <netinet/ip.h>
  1264. X#include <netinet/ip_icmp.h>
  1265. X#include <netinet/ip_var.h>
  1266. X
  1267. X#include "multiping.h"        /* all sorts of nasty #defines */
  1268. X#define GLOBALS
  1269. X#include "vars.h"
  1270. X#undef GLOBALS
  1271. X
  1272. Xint options;            /* F_* options */
  1273. Xint             max_dup_chk = MAX_DUP_CHK;
  1274. Xint             s;        /* socket file descriptor */
  1275. Xu_char          outpack[MAXPACKET];
  1276. Xchar            BSPACE = '\b';    /* characters written for flood */
  1277. Xchar            DOT = '.';
  1278. Xunsigned short  ident;        /* process id to identify our packets */
  1279. X
  1280. X/* counters */
  1281. Xlong            npackets;    /* max packets to transmit */
  1282. Xlong            ntransmitted;    /* number xmitted */
  1283. Xlong            nreceived;      /* number received */
  1284. Xint             interval = 1;    /* interval between packets */
  1285. X
  1286. X/* timing */
  1287. Xint             timing;        /* flag to do timing */
  1288. Xlong            tmin = MAXLONG;    /* minimum round trip time */
  1289. Xlong            tmax;        /* maximum round trip time */
  1290. Xu_long          tsum;        /* sum of all times, for doing average */
  1291. X
  1292. Xchar         *prognm ;
  1293. Xchar        *pr_addr();
  1294. Xvoid            catcher(), prefinish(), finish();
  1295. X
  1296. Xmain(argc, argv)
  1297. X  int             argc;
  1298. X  char          **argv;
  1299. X{
  1300. X  extern int      errno, optind;
  1301. X  extern char    *optarg;
  1302. X  struct timeval  timeout;
  1303. X  struct hostent *hp;
  1304. X  struct sockaddr_in *to;
  1305. X  struct protoent *proto;
  1306. X  register int    i;
  1307. X  int             ch, fdmask, hold, packlen, preload;
  1308. X  u_char         *datap, *packet;
  1309. X  char           *target, hnamebuf[MAXHOSTNAMELEN], *malloc();
  1310. X#ifdef IP_OPTIONS
  1311. X  char            rspace[3 + 4 * NROUTES + 1];    /* record route space */
  1312. X#endif
  1313. X
  1314. X  prognm = argv[0] ;
  1315. X  startup();
  1316. X  preload = 0;
  1317. X  datap = &outpack[8 + sizeof(struct timeval)];
  1318. X  while ((ch = getopt(argc, argv, "tRc:dfh:i:l:np:qrs:v")) != EOF) {
  1319. X    switch (ch) {
  1320. X      case 't':
  1321. X        options |= F_TABULAR_OUTPUT;
  1322. X        break;
  1323. X      case 'c':
  1324. X        npackets = atoi(optarg);
  1325. X        if (npackets <= 0) {
  1326. X      fprintf(stderr, "%s: bad number of packets to transmit.\n", prognm);
  1327. X      exit(1);
  1328. X        }
  1329. X        break;
  1330. X      case 'd':
  1331. X        options |= F_SO_DEBUG;
  1332. X        break;
  1333. X      case 'f':
  1334. X        if (getuid()) {  /* only root can use flood option */
  1335. X      fprintf(stderr, "%s: flood: Permission denied.\n", prognm); 
  1336. X      exit(1);
  1337. X        }
  1338. X        options |= F_FLOOD;
  1339. X        setbuf(stdout, (char *) NULL);
  1340. X        break;
  1341. X      case 'i':            /* wait between sending packets */
  1342. X        interval = atoi(optarg);
  1343. X        if (interval <= 0) {
  1344. X      fprintf(stderr, "%s: bad timing interval.\n", prognm);
  1345. X      exit(1);
  1346. X        }
  1347. X        options |= F_INTERVAL;
  1348. X        break;
  1349. X      case 'l':
  1350. X        preload = atoi(optarg);
  1351. X        if (preload < 0) {
  1352. X      fprintf(stderr, "%s: bad preload value.\n", prognm);
  1353. X      exit(1);
  1354. X        }
  1355. X        break;
  1356. X      case 'n':                 /* for pr_addr() */
  1357. X        options |= F_NUMERIC;
  1358. X        break;
  1359. X      case 'p':            /* fill buffer with user pattern */
  1360. X        options |= F_PINGFILLED;
  1361. X        fill((char *) datap, optarg);
  1362. X        break;
  1363. X      case 'q':
  1364. X        options |= F_QUIET;
  1365. X        break;
  1366. X      case 'R':                 /* record route */
  1367. X        options |= F_RROUTE;
  1368. X        break;
  1369. X      case 'r':
  1370. X        options |= F_SO_DONTROUTE;
  1371. X        break;
  1372. X      case 's':            /* size of packet to send */
  1373. X        datalen = atoi(optarg);
  1374. X        if (datalen > MAXPACKET) {
  1375. X      fprintf(stderr, "%s: packet size too large.\n", prognm);
  1376. X      exit(1);
  1377. X        }
  1378. X        if (datalen <= 0) {
  1379. X      fprintf(stderr, "%s: illegal packet size.\n", prognm);
  1380. X      exit(1);
  1381. X        }
  1382. X        break;
  1383. X      case 'v':
  1384. X        options |= F_VERBOSE;
  1385. X        break;
  1386. X      default:
  1387. X        usage();
  1388. X    }
  1389. X  }
  1390. X  argc -= optind;
  1391. X  argv += optind;
  1392. X
  1393. X  if (argc < 1)
  1394. X    usage();
  1395. X  while (argc--)
  1396. X    setup_sockaddr(*argv++);
  1397. X
  1398. X  if (options & F_FLOOD && options & F_INTERVAL) {
  1399. X    fprintf(stderr, "%s: -f and -i are incompatible options.\n", prognm);
  1400. X    exit(1);
  1401. X  }
  1402. X  if (datalen >= sizeof(struct timeval))    /* can we time transfer */
  1403. X    timing = 1;
  1404. X  packlen = datalen + MAXIPLEN + MAXICMPLEN;
  1405. X  if (!(packet = (u_char *) malloc((u_int) packlen))) {
  1406. X    fprintf(stderr, "%s: out of memory.\n", prognm);
  1407. X    exit(1);
  1408. X  }
  1409. X  if (!(options & F_PINGFILLED))
  1410. X    for (i = 8; i < datalen; ++i)
  1411. X      *datap++ = i;
  1412. X
  1413. X  ident = (unsigned short)(getpid() & 0xFFFF);
  1414. X
  1415. X  if (!(proto = getprotobyname("icmp"))) {
  1416. X    fprintf(stderr, "%s: unknown protocol icmp.\n", prognm);
  1417. X    exit(1);
  1418. X  }
  1419. X  if ((s = socket(AF_INET, SOCK_RAW, proto->p_proto)) < 0) {
  1420. X    perror("ping: socket");
  1421. X    exit(1);
  1422. X  }
  1423. X  hold = 1;
  1424. X  if (options & F_SO_DEBUG)
  1425. X    setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *) &hold, sizeof(hold));
  1426. X  if (options & F_SO_DONTROUTE)
  1427. X    setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *) &hold, sizeof(hold));
  1428. X
  1429. X  /* record route option */
  1430. X  if (options & F_RROUTE) {
  1431. X#ifdef IP_OPTIONS
  1432. X    rspace[IPOPT_OPTVAL] = IPOPT_RR;
  1433. X    rspace[IPOPT_OLEN] = sizeof(rspace) - 1;
  1434. X    rspace[IPOPT_OFFSET] = IPOPT_MINOFF;
  1435. X    if (setsockopt(s, IPPROTO_IP, IP_OPTIONS, rspace, sizeof(rspace)) < 0) {
  1436. X      perror("ping: record route");
  1437. X      exit(1);
  1438. X    }
  1439. X#else
  1440. X    fprintf(stderr,
  1441. X      "%s: record route not available in this implementation.\n", prognm);
  1442. X    exit(1);
  1443. X#endif                /* IP_OPTIONS */
  1444. X  }
  1445. X  /*
  1446. X   * When pinging the broadcast address, you can get a lot of answers. Doing
  1447. X   * something so evil is useful if you are trying to stress the ethernet, or
  1448. X   * just want to fill the arp cache to get some stuff for /etc/ethers.
  1449. X   */
  1450. X  hold = 48 * 1024;
  1451. X  setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *) &hold, sizeof(hold));
  1452. X
  1453. X  signal(SIGINT, prefinish);
  1454. X  signal(SIGALRM, catcher);
  1455. X
  1456. X  while (preload--)        /* fire off them quickies */
  1457. X    pinger();
  1458. X
  1459. X  if ((options & F_FLOOD) == 0)
  1460. X    catcher();            /* start things going */
  1461. X
  1462. X  for (;;) {
  1463. X    struct sockaddr_in from;
  1464. X    register int    cc;
  1465. X    int             fromlen;
  1466. X
  1467. X    /*
  1468. X     * If not flooding, we only send another packet after receiving
  1469. X     * the previous one, or after 'interval' seconds expire (see -i
  1470. X     * option).  If flooding, we send anyway (and read response only
  1471. X     * if select() says something is waiting)
  1472. X     */
  1473. X    if (options & F_FLOOD) {
  1474. X      pinger();
  1475. X      timeout.tv_sec = 0;
  1476. X      timeout.tv_usec = 10000;
  1477. X      fdmask = 1 << s;
  1478. X      if (select(s + 1, (fd_set *) & fdmask, (fd_set *) NULL, (fd_set *) NULL,
  1479. X            &timeout) < 1)
  1480. X    continue;
  1481. X    }
  1482. X    fromlen = sizeof(from);
  1483. X    if ((cc = recvfrom(s, (char *) packet, packlen, 0,
  1484. X                (struct sockaddr *) &from, &fromlen)) < 0) {
  1485. X      if (errno == EINTR)
  1486. X    continue;
  1487. X      perror("ping: recvfrom");
  1488. X      continue;
  1489. X    }
  1490. X    pr_pack((char *) packet, cc, &from);
  1491. X    if (npackets && (nreceived >= npackets)) break;
  1492. X  }
  1493. X  finish();
  1494. X  /* NOT REACHED */
  1495. X}
  1496. X
  1497. X/*
  1498. X * catcher -- This routine causes another PING to be transmitted, and then
  1499. X * schedules another SIGALRM for 1 second from now.
  1500. X * 
  1501. X * bug -- Our sense of time will slowly skew (i.e., packets will not be
  1502. X * launched exactly at 1-second intervals).  This does not affect the
  1503. X * quality of the delay and loss statistics.
  1504. X */
  1505. Xvoid
  1506. Xcatcher()
  1507. X{
  1508. X  int             waittime;
  1509. X  int             i;
  1510. X
  1511. X  pinger();
  1512. X  signal(SIGALRM, catcher);
  1513. X  nreceived = 0;
  1514. X  for (i = 0; i < numsites; i++)
  1515. X    if (dest[i]->nreceived > nreceived)
  1516. X      nreceived = dest[i]->nreceived;
  1517. X
  1518. X  if (!npackets || ntransmitted < npackets)
  1519. X    alarm((u_int) interval);
  1520. X  else {
  1521. X    if (nreceived) {
  1522. X      waittime = 2 * tmax / 1000;
  1523. X      if (!waittime) {
  1524. X    waittime = 1;
  1525. X    }
  1526. X    } else
  1527. X      waittime = MAXWAIT + 1; 
  1528. X    signal(SIGALRM, finish);
  1529. X    alarm((u_int) waittime);
  1530. X  }
  1531. X}
  1532. X
  1533. X/*
  1534. X * real_pinger -- was 'pinger' in the original but pinger() is now a front
  1535. X * end to this one.
  1536. X * 
  1537. X * Compose and transmit an ICMP ECHO REQUEST packet.  The IP packet will be
  1538. X * added on by the kernel.  The ID field is our UNIX process ID, and the
  1539. X * sequence number is an ascending integer.  The first 8 bytes of the data
  1540. X * portion are used to hold a UNIX "timeval" struct in VAX byte-order, to
  1541. X * compute the round-trip time.
  1542. X */
  1543. Xreal_pinger(which)
  1544. X  int             which;       /* index into dest[] array, tells which */
  1545. X                               /* site is being pinged */
  1546. X{
  1547. X  register struct icmp *icp;
  1548. X  register int    cc;
  1549. X  int             i;
  1550. X  struct sockaddr_in *to;
  1551. X
  1552. X  /* fill in the icmp headr */
  1553. X  icp = (struct icmp *) outpack;
  1554. X  icp->icmp_type = ICMP_ECHO;                   /* this is an echo request */
  1555. X  icp->icmp_code = 0; 
  1556. X  icp->icmp_cksum = 0;
  1557. X  icp->icmp_seq = dest[which]->ntransmitted++;  /* sequence # */
  1558. X  icp->icmp_id = ident;                        /* ID # == our pid */
  1559. X
  1560. X  CLR(which, icp->icmp_seq % max_dup_chk);
  1561. X
  1562. X  /* record time at which we sent the packet out */
  1563. X  if (timing)
  1564. X    gettimeofday((struct timeval *) & outpack[8], (struct timezone *) NULL);
  1565. X
  1566. X  cc = datalen + 8;        /* skips ICMP portion */
  1567. X
  1568. X  /* compute ICMP checksum here */
  1569. X  icp->icmp_cksum = in_cksum((u_short *) icp, cc);
  1570. X
  1571. X  to = &dest[which]->sockad;
  1572. X  i = sendto(s, (char *) outpack, cc, 0, (struct sockaddr *)to,
  1573. X             sizeof(struct sockaddr));
  1574. X
  1575. X  if (i < 0 || i != cc) {
  1576. X    if (i < 0)
  1577. X      perror("ping: sendto");
  1578. X    printf("%s: wrote %d chars to %s, ret=%d\n", prognm, cc,
  1579. X           inet_ntoa(to->sin_addr.s_addr), i);
  1580. X  }
  1581. X  if (!(options & F_QUIET) && options & F_FLOOD)
  1582. X    write(STDOUT_FILENO, &DOT, 1);
  1583. X}
  1584. X
  1585. X/*
  1586. X * pinger -- front end to real_pinger() so that all sites get pinged with
  1587. X * each invocation of pinger().
  1588. X * Need to add a small delay to prevent the kernel overflow from packets.
  1589. X * Can't use sleep() since that might trigger the wrong ALARM signal
  1590. X * handler.
  1591. X */
  1592. X
  1593. Xpinger()
  1594. X{
  1595. X  int             i;
  1596. X  register int loop;
  1597. X
  1598. X  for (i = 0; i < numsites; i++) {
  1599. X    real_pinger(i);
  1600. X    for (loop = 0; loop < 200000; loop++)    /* delay loop */
  1601. X    ; /* */
  1602. X    }
  1603. X    
  1604. X  ++ntransmitted;
  1605. X}
  1606. X
  1607. X/*
  1608. X * pr_pack -- Print out the packet, if it came from us.  This logic is
  1609. X * necessary because ALL readers of the ICMP socket get a copy of ALL ICMP
  1610. X * packets which arrive ('tis only fair).  This permits multiple copies of
  1611. X * this program to be run without having intermingled output (or
  1612. X * statistics!).
  1613. X */
  1614. Xpr_pack(buf, cc, from)
  1615. X  char           *buf;
  1616. X  int             cc;
  1617. X  struct sockaddr_in *from;
  1618. X{
  1619. X  register struct icmp *icp;
  1620. X  register u_long l;
  1621. X  register int    i, j;
  1622. X  register u_char *cp, *dp;
  1623. X  static int      old_rrlen;
  1624. X  static char     old_rr[MAX_IPOPTLEN];
  1625. X  struct ip      *ip;
  1626. X  struct timeval  tv, *tp;
  1627. X  long            triptime;
  1628. X  int             hlen, dupflag;
  1629. X
  1630. X  /* record time when we received the echo reply */
  1631. X  gettimeofday(&tv, (struct timezone *) NULL);
  1632. X
  1633. X  /* Check the IP header */
  1634. X  ip = (struct ip *) buf;
  1635. X  hlen = ip->ip_hl << 2;
  1636. X  if (cc < hlen + ICMP_MINLEN) {
  1637. X    if (options & F_VERBOSE)
  1638. X      fprintf(stderr, "%s: packet too short (%d bytes) from %s\n", prognm, cc,
  1639. X    inet_ntoa(*(struct in_addr *) & from->sin_addr.s_addr));
  1640. X    return;
  1641. X  }
  1642. X  /* Now the ICMP part */
  1643. X  cc -= hlen;
  1644. X  icp = (struct icmp *) (buf + hlen);
  1645. X  if (icp->icmp_type == ICMP_ECHOREPLY) {
  1646. X    int             wherefrom;
  1647. X    destrec        *dst;
  1648. X
  1649. X    /* first see if this reply is addressed to our process */
  1650. X    if (icp->icmp_id != ident)
  1651. X      return;            /* 'Twas not our ECHO */
  1652. X
  1653. X    /* if so, figure out which site it is in the dest[] array */
  1654. X    for (wherefrom = 0; wherefrom < numsites; wherefrom++)
  1655. X      if (!memcmp((char *) & (dest[wherefrom]->sockad), from,
  1656. X                  sizeof(struct sockaddr_in)))
  1657. X        break;
  1658. X    if (wherefrom >= numsites) {
  1659. X      fprintf(stderr,
  1660. X          "%s: received ICMP_ECHOREPLY from someone we didn't send to!?\n",
  1661. X          prognm);
  1662. X      return;
  1663. X    }
  1664. X    dst = dest[wherefrom];
  1665. X    icp->icmp_seq;
  1666. X    ++dst->nreceived;
  1667. X
  1668. X    /* figure out round trip time, check min/max */
  1669. X    if (timing) {
  1670. X#ifndef icmp_data
  1671. X      tp = (struct timeval *) & icp->icmp_ip;
  1672. X#else
  1673. X      tp = (struct timeval *) icp->icmp_data;
  1674. X#endif
  1675. X      tvsub(&tv, tp);
  1676. X      triptime = tv.tv_sec * 1000 + (tv.tv_usec / 1000);
  1677. X      dst->tsum += triptime;
  1678. X      if (triptime < dst->tmin)
  1679. X    dst->tmin = triptime;
  1680. X      if (triptime > dst->tmax)
  1681. X    dst->tmax = triptime;
  1682. X      if (triptime > tmax)
  1683. X        tmax = triptime;
  1684. X    }
  1685. X
  1686. X    /* check for duplicate echoes */
  1687. X    if (TST(wherefrom, icp->icmp_seq % max_dup_chk)) {
  1688. X      ++dst->nrepeats;
  1689. X      --dst->nreceived;
  1690. X      dupflag = 1;
  1691. X    } else {
  1692. X      SET(wherefrom, icp->icmp_seq % max_dup_chk);
  1693. X      dupflag = 0;
  1694. X    }
  1695. X
  1696. X    if (options & F_QUIET)
  1697. X      return;
  1698. X
  1699. X    if (options & F_FLOOD)
  1700. X      write(STDOUT_FILENO, &BSPACE, 1);
  1701. X    else {
  1702. X      printf("%d bytes from %s: icmp_seq=%u", cc,
  1703. X        inet_ntoa(*(struct in_addr *) &from->sin_addr.s_addr),
  1704. X        icp->icmp_seq);
  1705. X      printf(" ttl=%d", ip->ip_ttl);
  1706. X      if (timing)
  1707. X    printf(" time=%ld ms", triptime);
  1708. X      if (dupflag)
  1709. X    printf(" (DUP!)");
  1710. X      /* check the data */
  1711. X      cp = (u_char *) & icp->icmp_data[8];
  1712. X      dp = &outpack[8 + sizeof(struct timeval)];
  1713. X      for (i = 8; i < datalen; ++i, ++cp, ++dp) {
  1714. X    if (*cp != *dp) {
  1715. X      printf("\nwrong data byte #%d should be 0x%x but was 0x%x",
  1716. X        i, *dp, *cp);
  1717. X      cp = (u_char *) & icp->icmp_data[0];
  1718. X      for (i = 8; i < datalen; ++i, ++cp) {
  1719. X        if ((i % 32) == 8)
  1720. X          printf("\n\t");
  1721. X        printf("%x ", *cp);
  1722. X      }
  1723. X      break;
  1724. X    }
  1725. X      }
  1726. X    }
  1727. X  } else {
  1728. X    /* We've got something other than an ECHOREPLY */
  1729. X    if (!(options & F_VERBOSE))
  1730. X      return;
  1731. X    printf("%d bytes from %s: ", cc, pr_addr(from->sin_addr.s_addr));
  1732. X    pr_icmph(icp);
  1733. X  }
  1734. X
  1735. X  /* Display any IP options */
  1736. X  cp = (u_char *) buf + sizeof(struct ip);
  1737. X
  1738. X  for (; hlen > (int) sizeof(struct ip); --hlen, ++cp)
  1739. X    switch (*cp) {
  1740. X    case IPOPT_EOL:
  1741. X      hlen = 0;
  1742. X      break;
  1743. X    case IPOPT_LSRR:
  1744. X      printf("\nLSRR: ");
  1745. X      hlen -= 2;
  1746. X      j = *++cp;
  1747. X      ++cp;
  1748. X      if (j > IPOPT_MINOFF)
  1749. X    for (;;) {
  1750. X      l = *++cp;
  1751. X      l = (l << 8) + *++cp;
  1752. X      l = (l << 8) + *++cp;
  1753. X      l = (l << 8) + *++cp;
  1754. X      if (l == 0)
  1755. X        printf("\t0.0.0.0");
  1756. X      else
  1757. X        printf("\t%s", pr_addr(ntohl(l)));
  1758. X      hlen -= 4;
  1759. X      j -= 4;
  1760. X      if (j <= IPOPT_MINOFF)
  1761. X        break;
  1762. X      putchar('\n');
  1763. X    }
  1764. X      break;
  1765. X    case IPOPT_RR:
  1766. X      j = *++cp;        /* get length */
  1767. X      i = *++cp;        /* and pointer */
  1768. X      hlen -= 2;
  1769. X      if (i > j)
  1770. X    i = j;
  1771. X      i -= IPOPT_MINOFF;
  1772. X      if (i <= 0)
  1773. X    continue;
  1774. X      if (i == old_rrlen
  1775. X      && cp == (u_char *) buf + sizeof(struct ip) + 2
  1776. X      && !bcmp((char *) cp, old_rr, i)
  1777. X      && !(options & F_FLOOD)) {
  1778. X    printf("\t(same route)");
  1779. X    i = ((i + 3) / 4) * 4;
  1780. X    hlen -= i;
  1781. X    cp += i;
  1782. X    break;
  1783. X      }
  1784. X      old_rrlen = i;
  1785. X      bcopy((char *) cp, old_rr, i);
  1786. X      printf("\nRR: ");
  1787. X      for (;;) {
  1788. X    l = *++cp;
  1789. X    l = (l << 8) + *++cp;
  1790. X    l = (l << 8) + *++cp;
  1791. X    l = (l << 8) + *++cp;
  1792. X    if (l == 0)
  1793. X      printf("\t0.0.0.0");
  1794. X    else
  1795. X      printf("\t%s", pr_addr(ntohl(l)));
  1796. X    hlen -= 4;
  1797. X    i -= 4;
  1798. X    if (i <= 0)
  1799. X      break;
  1800. X    putchar('\n');
  1801. X      }
  1802. X      break;
  1803. X    case IPOPT_NOP:
  1804. X      printf("\nNOP");
  1805. X      break;
  1806. X    default:
  1807. X      printf("\nunknown option %x", *cp);
  1808. X      break;
  1809. X    }
  1810. X  if (!(options & F_FLOOD)) {
  1811. X    putchar('\n');
  1812. X    fflush(stdout);
  1813. X  }
  1814. X}
  1815. X
  1816. X/*
  1817. X * in_cksum -- Checksum routine for Internet Protocol family headers (C
  1818. X * Version)
  1819. X */
  1820. Xin_cksum(addr, len)
  1821. X  u_short        *addr;
  1822. X  int             len;
  1823. X{
  1824. X  register int    nleft = len;
  1825. X  register u_short *w = addr;
  1826. X  register int    sum = 0;
  1827. X  u_short         answer = 0;
  1828. X
  1829. X  /*
  1830. X   * Our algorithm is simple, using a 32 bit accumulator (sum), we add
  1831. X   * sequential 16 bit words to it, and at the end, fold back all the carry
  1832. X   * bits from the top 16 bits into the lower 16 bits.
  1833. X   */
  1834. X  while (nleft > 1) {
  1835. X    sum += *w++;
  1836. X    nleft -= 2;
  1837. X  }
  1838. X
  1839. X  /* mop up an odd byte, if necessary */
  1840. X  if (nleft == 1) {
  1841. X    *(u_char *) (&answer) = *(u_char *) w;
  1842. X    sum += answer;
  1843. X  }
  1844. X  /* add back carry outs from top 16 bits to low 16 bits */
  1845. X  sum = (sum >> 16) + (sum & 0xffff);    /* add hi 16 to low 16 */
  1846. X  sum += (sum >> 16);        /* add carry */
  1847. X  answer = ~sum;        /* truncate to 16 bits */
  1848. X  return (answer);
  1849. X}
  1850. X
  1851. X/*
  1852. X * tvsub -- Subtract 2 timeval structs:  out = out - in.  Out is assumed to
  1853. X * be >= in.
  1854. X */
  1855. Xtvsub(out, in)
  1856. X  register struct timeval *out, *in;
  1857. X{
  1858. X  if ((out->tv_usec -= in->tv_usec) < 0) {
  1859. X    --out->tv_sec;
  1860. X    out->tv_usec += 1000000;
  1861. X  }
  1862. X  out->tv_sec -= in->tv_sec;
  1863. X}
  1864. X
  1865. X/*
  1866. X * In case anyone's using a program that depends on the output being
  1867. X * in the non-tabular format
  1868. X */
  1869. Xvoid
  1870. Xoutput_old_style()
  1871. X{
  1872. X  int             i;
  1873. X  destrec        *dp;
  1874. X
  1875. X  for (i = 0; i < numsites; i++) {
  1876. X    dp = dest[i];
  1877. X    printf("--- %s ping statistics ---\n", pr_addr(dp->sockad.sin_addr.s_addr));
  1878. X    printf("%ld packets transmitted, ", dp->ntransmitted);
  1879. X    printf("%ld packets received, ", dp->nreceived);
  1880. X    if (dp->nrepeats)
  1881. X      printf("+%ld duplicates, ", dp->nrepeats);
  1882. X    if (dp->ntransmitted)
  1883. X      if (dp->nreceived > dp->ntransmitted)
  1884. X    printf("-- somebody's printing up packets!");
  1885. X      else
  1886. X    printf("%d%% packet loss",
  1887. X              (int) (((dp->ntransmitted - dp->nreceived) * 100) /
  1888. X                 dp->ntransmitted));
  1889. X    putchar('\n');
  1890. X    if (dp->nreceived && timing)
  1891. X      printf("round-trip min/avg/max = %ld/%lu/%ld ms\n",
  1892. X            dp->tmin, dp->tsum / (dp->nreceived + dp->nrepeats),
  1893. X            dp->tmax);
  1894. X  }
  1895. X}
  1896. X
  1897. Xvoid
  1898. Xoutput_new_style()
  1899. X{
  1900. X  int             i;
  1901. X  destrec        *dp;
  1902. X  long            sent, rcvd, rpts, tmin, tsum, tmax;
  1903. X
  1904. X  printf("-=-=- PING statistics -=-=-\n");
  1905. X  printf("                                      Number of Packets");
  1906. X  if (timing)
  1907. X    printf("         Round Trip Time\n");
  1908. X  printf("Remote Site                     Sent    Rcvd    Rptd   Lost ");
  1909. X  if (timing)
  1910. X    printf("    Min   Avg   Max");
  1911. X  printf("\n-----------------------------  ------  ------  ------  ----");
  1912. X  if (timing)
  1913. X    printf("    ----  ----  ----");
  1914. X  sent = rcvd = rpts = tmax = tsum = 0;
  1915. X  tmin = MAXLONG;
  1916. X  for (i = 0; i < numsites; i++) {
  1917. X    dp = dest[i];
  1918. X    printf("\n%-29.29s  %6ld  %6ld  %6ld%c %3ld%%",
  1919. X      pr_addr(dp->sockad.sin_addr.s_addr),
  1920. X      dp->ntransmitted, dp->nreceived, dp->nrepeats,
  1921. X      (dp->nreceived > dp->ntransmitted) ? '!' : ' ',
  1922. X      (int) (((dp->ntransmitted - dp->nreceived) * 100) / dp->ntransmitted));
  1923. X    sent += dp->ntransmitted;
  1924. X    rcvd += dp->nreceived;
  1925. X    rpts += dp->nrepeats;
  1926. X    if (timing)
  1927. X      if (dp->nreceived) {
  1928. X        printf("    %4ld  %4ld  %4ld", dp->tmin,
  1929. X          dp->tsum / dp->nreceived, dp->tmax);
  1930. X        if (dp->tmin < tmin)
  1931. X          tmin = dp->tmin;
  1932. X        if (dp->tmax > tmax)
  1933. X          tmax = dp->tmax;
  1934. X        tsum += dp->tsum;
  1935. X      } else        
  1936. X        printf("       0     0     0");
  1937. X  }
  1938. X  printf("\n-----------------------------  ------  ------  ------  ----");
  1939. X  if (timing)
  1940. X    printf("    ----  ----  ----");
  1941. X  if (numsites > 1) {
  1942. X    printf("\nTOTALS                         %6ld  %6ld  %6ld  %3ld%%",
  1943. X      sent, rcvd, rpts, (int) (((sent - rcvd) * 100) / sent));
  1944. X    if (timing)
  1945. X      printf("    %4ld  %4ld  %4ld", tmin, tsum / rcvd, tmax);
  1946. X  }
  1947. X  putchar('\n');
  1948. X  exit(0);
  1949. X}
  1950. X
  1951. X/*
  1952. X * prefinish -- On first SIGINT, allow any outstanding packets to dribble in
  1953. X */
  1954. Xvoid
  1955. Xprefinish()
  1956. X{
  1957. X  if (nreceived >= ntransmitted   /* quit now if caught up */
  1958. X      || nreceived == 0)          /* or if remote is dead */
  1959. X    finish();
  1960. X  signal(SIGINT, finish);         /* do this only the 1st time */
  1961. X  npackets = ntransmitted+1;      /* let the normal limit work */
  1962. X}
  1963. X
  1964. X/*
  1965. X * finish -- Print out statistics, and give up.
  1966. X */
  1967. Xvoid
  1968. Xfinish()
  1969. X{
  1970. X  signal(SIGINT, SIG_IGN);
  1971. X  putchar('\n');
  1972. X  if (!(options & F_TABULAR_OUTPUT))
  1973. X    output_old_style();
  1974. X  else
  1975. X    output_new_style();
  1976. X  exit(0);
  1977. X}
  1978. X
  1979. X#ifdef notdef
  1980. Xstatic char    *ttab[] = {
  1981. X  "Echo Reply",            /* ip + seq + udata */
  1982. X  "Dest Unreachable",        /* net, host, proto, port, frag, sr + IP */
  1983. X  "Source Quench",        /* IP */
  1984. X  "Redirect",            /* redirect type, gateway, + IP  */
  1985. X  "Echo",
  1986. X  "Time Exceeded",        /* transit, frag reassem + IP */
  1987. X  "Parameter Problem",        /* pointer + IP */
  1988. X  "Timestamp",            /* id + seq + three timestamps */
  1989. X  "Timestamp Reply",        /* " */
  1990. X  "Info Request",        /* id + sq */
  1991. X  "Info Reply"            /* " */
  1992. X};
  1993. X#endif
  1994. X
  1995. X/*
  1996. X * pr_icmph -- Print a descriptive string about an ICMP header.
  1997. X */
  1998. Xpr_icmph(icp)
  1999. X  struct icmp    *icp;
  2000. X{
  2001. X  switch (icp->icmp_type) {
  2002. X  case ICMP_ECHOREPLY:
  2003. X    printf("Echo Reply\n");
  2004. X    /* XXX ID + Seq + Data */
  2005. X    break;
  2006. X  case ICMP_UNREACH:
  2007. X    switch (icp->icmp_code) {
  2008. X    case ICMP_UNREACH_NET:
  2009. X      printf("Destination Net Unreachable\n");
  2010. X      break;
  2011. X    case ICMP_UNREACH_HOST:
  2012. X      printf("Destination Host Unreachable\n");
  2013. X      break;
  2014. X    case ICMP_UNREACH_PROTOCOL:
  2015. X      printf("Destination Protocol Unreachable\n");
  2016. X      break;
  2017. X    case ICMP_UNREACH_PORT:
  2018. X      printf("Destination Port Unreachable\n");
  2019. X      break;
  2020. X    case ICMP_UNREACH_NEEDFRAG:
  2021. X      printf("frag needed and DF set\n");
  2022. X      break;
  2023. X    case ICMP_UNREACH_SRCFAIL:
  2024. X      printf("Source Route Failed\n");
  2025. X      break;
  2026. X    default:
  2027. X      printf("Dest Unreachable, Bad Code: %d\n",
  2028. X            icp->icmp_code);
  2029. X      break;
  2030. X    }
  2031. X    /* Print returned IP header information */
  2032. X#ifndef icmp_data
  2033. X    pr_retip(&icp->icmp_ip);
  2034. X#else
  2035. X    pr_retip((struct ip *) icp->icmp_data);
  2036. X#endif
  2037. X    break;
  2038. X  case ICMP_SOURCEQUENCH:
  2039. X    printf("Source Quench\n");
  2040. X#ifndef icmp_data
  2041. X    pr_retip(&icp->icmp_ip);
  2042. X#else
  2043. X    pr_retip((struct ip *) icp->icmp_data);
  2044. X#endif
  2045. X    break;
  2046. X  case ICMP_REDIRECT:
  2047. X    switch (icp->icmp_code) {
  2048. X    case ICMP_REDIRECT_NET:
  2049. X      printf("Redirect Network");
  2050. X      break;
  2051. X    case ICMP_REDIRECT_HOST:
  2052. X      printf("Redirect Host");
  2053. X      break;
  2054. X    case ICMP_REDIRECT_TOSNET:
  2055. X      printf("Redirect Type of Service and Network");
  2056. X      break;
  2057. X    case ICMP_REDIRECT_TOSHOST:
  2058. X      printf("Redirect Type of Service and Host");
  2059. X      break;
  2060. X    default:
  2061. X      printf("Redirect, Bad Code: %d", icp->icmp_code);
  2062. X      break;
  2063. X    }
  2064. X    printf("(New addr: 0x%08lx)\n", icp->icmp_gwaddr.s_addr);
  2065. X#ifndef icmp_data
  2066. X    pr_retip(&icp->icmp_ip);
  2067. X#else
  2068. X    pr_retip((struct ip *) icp->icmp_data);
  2069. X#endif
  2070. X    break;
  2071. X  case ICMP_ECHO:
  2072. X    printf("Echo Request\n");
  2073. X    /* XXX ID + Seq + Data */
  2074. X    break;
  2075. X  case ICMP_TIMXCEED:
  2076. X    switch (icp->icmp_code) {
  2077. X    case ICMP_TIMXCEED_INTRANS:
  2078. X      printf("Time to live exceeded\n");
  2079. X      break;
  2080. X    case ICMP_TIMXCEED_REASS:
  2081. X      printf("Frag reassembly time exceeded\n");
  2082. X      break;
  2083. X    default:
  2084. X      printf("Time exceeded, Bad Code: %d\n",
  2085. X            icp->icmp_code);
  2086. X      break;
  2087. X    }
  2088. X#ifndef icmp_data
  2089. X    pr_retip(&icp->icmp_ip);
  2090. X#else
  2091. X    pr_retip((struct ip *) icp->icmp_data);
  2092. X#endif
  2093. X    break;
  2094. X  case ICMP_PARAMPROB:
  2095. X    printf("Parameter problem: pointer = 0x%02x\n",
  2096. X          icp->icmp_hun.ih_pptr);
  2097. X#ifndef icmp_data
  2098. X    pr_retip(&icp->icmp_ip);
  2099. X#else
  2100. X    pr_retip((struct ip *) icp->icmp_data);
  2101. X#endif
  2102. X    break;
  2103. X  case ICMP_TSTAMP:
  2104. X    printf("Timestamp\n");
  2105. X    /* XXX ID + Seq + 3 timestamps */
  2106. X    break;
  2107. X  case ICMP_TSTAMPREPLY:
  2108. X    printf("Timestamp Reply\n");
  2109. X    /* XXX ID + Seq + 3 timestamps */
  2110. X    break;
  2111. X  case ICMP_IREQ:
  2112. X    printf("Information Request\n");
  2113. X    /* XXX ID + Seq */
  2114. X    break;
  2115. X  case ICMP_IREQREPLY:
  2116. X    printf("Information Reply\n");
  2117. X    /* XXX ID + Seq */
  2118. X    break;
  2119. X#ifdef ICMP_MASKREQ
  2120. X  case ICMP_MASKREQ:
  2121. X    printf("Address Mask Request\n");
  2122. X    break;
  2123. X#endif
  2124. X#ifdef ICMP_MASKREPLY
  2125. X  case ICMP_MASKREPLY:
  2126. X    printf("Address Mask Reply\n");
  2127. X    break;
  2128. X#endif
  2129. X  default:
  2130. X    printf("Bad ICMP type: %d\n", icp->icmp_type);
  2131. X  }
  2132. X}
  2133. X
  2134. X/*
  2135. X * pr_iph -- Print an IP header with options.
  2136. X */
  2137. Xpr_iph(ip)
  2138. X  struct ip      *ip;
  2139. X{
  2140. X  int             hlen;
  2141. X  u_char         *cp;
  2142. X
  2143. X  hlen = ip->ip_hl << 2;
  2144. X  cp = (u_char *) ip + 20;    /* point to options */
  2145. X
  2146. X  printf("Vr HL TOS  Len   ID Flg  off TTL Pro  cks      Src      Dst Data\n");
  2147. X  printf(" %1x  %1x  %02x %04x %04x",
  2148. X        ip->ip_v, ip->ip_hl, ip->ip_tos, ip->ip_len, ip->ip_id);
  2149. X  printf("   %1x %04x", ((ip->ip_off) & 0xe000) >> 13,
  2150. X        (ip->ip_off) & 0x1fff);
  2151. X  printf("  %02x  %02x %04x", ip->ip_ttl, ip->ip_p, ip->ip_sum);
  2152. X  printf(" %s ", inet_ntoa(*(struct in_addr *) & ip->ip_src.s_addr));
  2153. X  printf(" %s ", inet_ntoa(*(struct in_addr *) & ip->ip_dst.s_addr));
  2154. X  /* dump and option bytes */
  2155. X  while (hlen-- > 20) {
  2156. X    printf("%02x", *cp++);
  2157. X  }
  2158. X  putchar('\n');
  2159. X}
  2160. X
  2161. X/*
  2162. X * pr_addr -- Return an ascii host address as a dotted quad and optionally
  2163. X * with a hostname.
  2164. X */
  2165. Xchar           *
  2166. Xpr_addr(l)
  2167. X  u_long          l;
  2168. X{
  2169. X  struct hostent *hp;
  2170. X  static char     buf[80];
  2171. X
  2172. X  if ((options & F_NUMERIC) ||
  2173. X      !(hp = gethostbyaddr((char *) &l, 4, AF_INET)))
  2174. X    sprintf(buf, "%s", inet_ntoa(*(struct in_addr *) & l));
  2175. X  else
  2176. X    sprintf(buf, "%s (%s)", hp->h_name,
  2177. X           inet_ntoa(*(struct in_addr *) & l));
  2178. X  return (buf);
  2179. X}
  2180. X
  2181. X/*
  2182. X * pr_retip -- Dump some info on a returned (via ICMP) IP packet.
  2183. X */
  2184. Xpr_retip(ip)
  2185. X  struct ip      *ip;
  2186. X{
  2187. X  int             hlen;
  2188. X  u_char         *cp;
  2189. X
  2190. X  pr_iph(ip);
  2191. X  hlen = ip->ip_hl << 2;
  2192. X  cp = (u_char *) ip + hlen;
  2193. X
  2194. X  if (ip->ip_p == 6)
  2195. X    printf("TCP: from port %u, to port %u (decimal)\n",
  2196. X          (*cp * 256 + *(cp + 1)), (*(cp + 2) * 256 + *(cp + 3)));
  2197. X  else if (ip->ip_p == 17)
  2198. X    printf("UDP: from port %u, to port %u (decimal)\n",
  2199. X          (*cp * 256 + *(cp + 1)), (*(cp + 2) * 256 + *(cp + 3)));
  2200. X}
  2201. X
  2202. Xfill(bp, patp)
  2203. X  char           *bp, *patp;
  2204. X{
  2205. X  register int    ii, jj, kk;
  2206. X  int             pat[16];
  2207. X  char           *cp;
  2208. X
  2209. X  for (cp = patp; *cp; cp++)
  2210. X    if (!isxdigit(*cp)) {
  2211. X      fprintf(stderr,
  2212. X             "%s: patterns must be specified as hex digits.\n",prognm);
  2213. X      exit(1);
  2214. X    }
  2215. X  ii = sscanf(patp,
  2216. X          "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
  2217. X          &pat[0], &pat[1], &pat[2], &pat[3], &pat[4], &pat[5], &pat[6],
  2218. X          &pat[7], &pat[8], &pat[9], &pat[10], &pat[11], &pat[12],
  2219. X          &pat[13], &pat[14], &pat[15]);
  2220. X
  2221. X  if (ii > 0)
  2222. X    for (kk = 0; kk <= MAXPACKET - (8 + ii); kk += ii)
  2223. X      for (jj = 0; jj < ii; ++jj)
  2224. X    bp[jj + kk] = pat[jj];
  2225. X  if (!(options & F_QUIET)) {
  2226. X    printf("PATTERN: 0x");
  2227. X    for (jj = 0; jj < ii; ++jj)
  2228. X      printf("%02x", bp[jj] & 0xFF);
  2229. X    printf("\n");
  2230. X  }
  2231. X}
  2232. X
  2233. Xusage()
  2234. X{
  2235. X  fprintf(stderr, "usage: %s [-Rdfnqrtv] [-c count] [-i wait] [-l preload]\n",
  2236. X      prognm);
  2237. X  fprintf(stderr, "            [-p pattern] [-s packetsize] host\n\n");
  2238. X  fprintf(stderr, "       Options:\n");
  2239. X  fprintf(stderr, "       R: ICMP record route\n");
  2240. X  fprintf(stderr, "       d: set SO_DEBUG socket option\n");
  2241. X  fprintf(stderr, "       f: 'flood' mode\n");
  2242. X  fprintf(stderr, "       n: force addresses to be displayed in numeric format\n");
  2243. X  fprintf(stderr, "       r: set SO_DONTROUTE socket option\n");
  2244. X  fprintf(stderr, "       t: show results in tabular form\n");
  2245. X  fprintf(stderr, "       v: verbose mode for ICMP stuff\n");
  2246. X  exit(1);
  2247. X}
  2248. END_OF_FILE
  2249.   if test 29414 -ne `wc -c <'nocol-3.0/src/support/multiping/multiping.c'`; then
  2250.     echo shar: \"'nocol-3.0/src/support/multiping/multiping.c'\" unpacked with wrong size!
  2251.   fi
  2252.   # end of 'nocol-3.0/src/support/multiping/multiping.c'
  2253. fi
  2254. echo shar: End of archive 12 \(of 26\).
  2255. cp /dev/null ark12isdone
  2256. MISSING=""
  2257. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 ; do
  2258.     if test ! -f ark${I}isdone ; then
  2259.     MISSING="${MISSING} ${I}"
  2260.     fi
  2261. done
  2262. if test "${MISSING}" = "" ; then
  2263.     echo You have unpacked all 26 archives.
  2264.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2265. else
  2266.     echo You still must unpack the following archives:
  2267.     echo "        " ${MISSING}
  2268. fi
  2269. exit 0
  2270. exit 0 # Just in case...
  2271.