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

  1. Newsgroups: comp.sources.misc
  2. From: vikas@jvnc.net (Vikas Aggarwal)
  3. Subject: v40i145:  nocol - Network Monitoring System, Part15/26
  4. Message-ID: <1993Nov23.212654.21720@sparky.sterling.com>
  5. X-Md4-Signature: 52be94b85a4409631922e458871ec8ad
  6. Sender: kent@sparky.sterling.com (Kent Landfield)
  7. Organization: Sterling Software
  8. Date: Tue, 23 Nov 1993 21:26:54 GMT
  9. Approved: kent@sparky.sterling.com
  10.  
  11. Submitted-by: vikas@jvnc.net (Vikas Aggarwal)
  12. Posting-number: Volume 40, Issue 145
  13. Archive-name: nocol/part15
  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/apps/snmp_agent.c
  21. #   nocol-3.0/src/cmu-snmp/include/mib.c
  22. #   nocol-3.0/src/cmu-snmp/snmplib/asn1.c.cmu
  23. #   nocol-3.0/src/support/mping/m.dat nocol-3.0/src/trapmon/trapmon.c
  24. # Wrapped by kent@sparky on Tue Nov  9 22:22:20 1993
  25. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin:$PATH ; export PATH
  26. echo If this archive is complete, you will see the following message:
  27. echo '          "shar: End of archive 15 (of 26)."'
  28. if test -f 'nocol-3.0/src/cmu-snmp/apps/snmp_agent.c' -a "${1}" != "-c" ; then 
  29.   echo shar: Will not clobber existing file \"'nocol-3.0/src/cmu-snmp/apps/snmp_agent.c'\"
  30. else
  31.   echo shar: Extracting \"'nocol-3.0/src/cmu-snmp/apps/snmp_agent.c'\" \(17980 characters\)
  32.   sed "s/^X//" >'nocol-3.0/src/cmu-snmp/apps/snmp_agent.c' <<'END_OF_FILE'
  33. X/*
  34. X * Simple Network Management Protocol (RFC 1067).
  35. X *
  36. X */
  37. X/***********************************************************
  38. X    Copyright 1988, 1989 by Carnegie Mellon University
  39. X
  40. X                      All Rights Reserved
  41. X
  42. XPermission to use, copy, modify, and distribute this software and its 
  43. Xdocumentation for any purpose and without fee is hereby granted, 
  44. Xprovided that the above copyright notice appear in all copies and that
  45. Xboth that copyright notice and this permission notice appear in 
  46. Xsupporting documentation, and that the name of CMU not be
  47. Xused in advertising or publicity pertaining to distribution of the
  48. Xsoftware without specific, written prior permission.  
  49. X
  50. XCMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  51. XALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  52. XCMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  53. XANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  54. XWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  55. XARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  56. XSOFTWARE.
  57. X******************************************************************/
  58. X
  59. X#ifdef KINETICS
  60. X#include "gw.h"
  61. X#include "ab.h"
  62. X#include "inet.h"
  63. X#include "fp4/cmdmacro.h"
  64. X#include "fp4/pbuf.h"
  65. X#include "glob.h"
  66. X#endif
  67. X
  68. X#if (defined(unix) && !defined(KINETICS))
  69. X#include <sys/types.h>
  70. X#include <netinet/in.h>
  71. X#ifndef NULL
  72. X#define NULL 0
  73. X#endif
  74. X#endif
  75. X
  76. X#include "snmp.h"
  77. X#include "snmp_impl.h"
  78. X#include "asn1.h"
  79. X
  80. X#include "mib.h"
  81. X
  82. Xvoid    snmp_input();
  83. Xvoid    snmp_trap();
  84. Xint    create_identical();
  85. Xint    parse_var_op_list();
  86. Xint    snmp_access();
  87. X
  88. X#if kinetics
  89. Xchar    version_descr[];
  90. Xoid    version_id[];
  91. Xint    version_id_len;
  92. X#endif
  93. X
  94. Xstruct pbuf *definitelyGetBuf();
  95. X
  96. X#define NUM_COMMUNITIES    5
  97. Xchar    *communities[NUM_COMMUNITIES] = {
  98. X    "public", 
  99. X    "proxy",
  100. X    "private",
  101. X    "regional",
  102. X    "core"
  103. X};
  104. X
  105. X/* these can't be global in a multi-process router */
  106. X    u_char    sid[SID_MAX_LEN + 1];
  107. X    int        sidlen;
  108. X    u_char    *packet_end;
  109. X    int        community;
  110. X
  111. X
  112. X#ifdef KINETICS
  113. Xvoid
  114. Xsnmp_input(p)
  115. X    struct pbuf *p;
  116. X{
  117. X    struct ip        *ip = (struct ip *)p->p_off;
  118. X    int            hlen = (int)ip->ip_hl << 2;
  119. X    register struct udp        *udp;
  120. X    register u_char *data;  /* pointer to the rest of the unread data */
  121. X    int            length; /* bytes of data left in msg after the "data" pointer */
  122. X    struct pbuf        *out_packet;
  123. X    register u_char *out_data;
  124. X    int            out_length;
  125. X    u_short        udp_src;
  126. X    extern struct mib_udp   mib_udp;
  127. X
  128. X    
  129. X    udp = (struct udp *)(p->p_off + hlen);
  130. X    if (ntohs(ip->ip_len) - hlen < sizeof(struct udp) ||    /* IP length < minimum UDP packet */
  131. X        ntohs(udp->length) > ntohs(ip->ip_len) - hlen){ /* UDP length > IP data */
  132. X    ERROR("dropped packet with bad length");    /* delete me */
  133. X    return; /* drop packet */
  134. X    }
  135. X    data = (u_char *)udp + sizeof(struct udp);
  136. X    length = ntohs(udp->length) - sizeof(struct udp);
  137. X
  138. X    out_packet = definitelyGetBuf(); /* drop packets off input queue if necessary */
  139. X    out_data = (u_char *)(out_packet->p_off + sizeof (struct ip) + sizeof (struct udp));
  140. X    out_length = MAXDATA - sizeof(struct ip) - sizeof (struct udp);
  141. X
  142. XK_LEDON();
  143. X    if (!snmp_agent_parse(data, length, out_data, &out_length, (u_long)ip->ip_src)){
  144. X    K_PFREE(out_packet);
  145. XK_LEDOFF();
  146. X    return;
  147. X    }
  148. XK_LEDOFF();
  149. X    out_packet->p_len = packet_end - (u_char *)out_packet->p_off;
  150. X    setiphdr(out_packet, ip->ip_src);    /* address to source of request packet (ntohl ??? ) */
  151. X    udp_src = ntohs(udp->src);
  152. X    udp = (struct udp *)(out_packet->p_off + sizeof (struct ip));
  153. X    udp->src = htons(SNMP_PORT);
  154. X    udp->dst = htons(udp_src);
  155. X    udp->length = out_packet->p_len - sizeof(struct ip);
  156. X    udp->checksum = 0;    /* this should be computed */
  157. X
  158. X    mib_udp.udpOutDatagrams++;
  159. X    routeip(out_packet, 0, 0);
  160. X}
  161. X
  162. X
  163. Xvoid
  164. Xsnmp_trap(destAddr, trapType, specificType)
  165. X    u_long  destAddr;
  166. X    int        trapType;
  167. X    int        specificType;
  168. X{
  169. X    struct pbuf        *out_packet;
  170. X    register u_char *out_data;
  171. X    register struct udp        *udp;
  172. X    int            out_length;
  173. X    static oid        sysDescrOid[] = {1, 3, 6, 1, 2, 1, 1, 1, 0};
  174. X    
  175. X    out_packet = definitelyGetBuf(); /* drop packets off input queue if necessary */
  176. X    out_data = (u_char *)(out_packet->p_off + sizeof (struct ip) + sizeof (struct udp));
  177. X    out_length = MAXDATA - sizeof(struct ip) - sizeof (struct udp);
  178. X
  179. XK_LEDON();
  180. X    out_packet->p_len = snmp_build_trap(out_data, out_length, version_id, version_id_len,
  181. X    conf.ipaddr, trapType, specificType, TICKS2MS(tickclock)/10, sysDescrOid, sizeof(sysDescrOid)/sizeof(oid),
  182. X    ASN_OCTET_STR, strlen(version_descr), (u_char *)version_descr);
  183. X    if (out_packet->p_len == 0){
  184. X    K_PFREE(out_packet);
  185. XK_LEDOFF();
  186. X    return;
  187. X    }
  188. XK_LEDOFF();
  189. X    out_packet->p_len += sizeof(struct ip) + sizeof(struct udp);
  190. X    setiphdr(out_packet, destAddr);    /* address to source of request packet (ntohl ??? ) */
  191. X    udp = (struct udp *)(out_packet->p_off + sizeof (struct ip));
  192. X    udp->src = htons(SNMP_PORT);
  193. X    udp->dst = htons(SNMP_TRAP_PORT);
  194. X    udp->length = out_packet->p_len - sizeof(struct ip);
  195. X    udp->checksum = 0;    /* this should be computed */
  196. X
  197. X    mib_udp.udpOutDatagrams++;
  198. X    routeip(out_packet, 0, 0);
  199. X}
  200. X#endif
  201. X
  202. Xint
  203. Xsnmp_agent_parse(data, length, out_data, out_length, sourceip)
  204. X    register u_char    *data;
  205. X    int            length;
  206. X    register u_char    *out_data;
  207. X    int            *out_length;
  208. X    u_long        sourceip;    /* possibly for authentication */
  209. X{
  210. X    u_char        msg_type, type;
  211. X    long        zero = 0;
  212. X    long        reqid, errstat, errindex;
  213. X    register u_char *out_auth, *out_header, *out_reqid;
  214. X    u_char        *startData = data;
  215. X    int            startLength = length;
  216. X    long        version;
  217. X    int            header_shift, auth_shift;
  218. X
  219. X    sidlen = SID_MAX_LEN;
  220. X    data = snmp_auth_parse(data, &length, sid, &sidlen, &version); /* authenticates message and returns length if valid */
  221. X    if (data == NULL){
  222. X    ERROR("bad authentication");
  223. X    /* send auth fail trap */
  224. X    return 0;
  225. X    }
  226. X    if (version != SNMP_VERSION_1){
  227. X    ERROR("wrong version");
  228. X    return NULL;
  229. X    }
  230. X    community = get_community(sid);
  231. X    if (community == -1)
  232. X    return NULL;
  233. X    data = asn_parse_header(data, &length, &msg_type);
  234. X    if (data == NULL){
  235. X    ERROR("bad header");
  236. X    return 0;
  237. X    }
  238. X    if (msg_type != GET_REQ_MSG && msg_type != GETNEXT_REQ_MSG && msg_type != SET_REQ_MSG){
  239. X    return 0;
  240. X    }
  241. X    data = asn_parse_int(data, &length, &type, &reqid, sizeof(reqid));
  242. X    if (data == NULL){
  243. X    ERROR("bad parse of reqid");
  244. X    return 0;
  245. X    }
  246. X    data = asn_parse_int(data, &length, &type, &errstat, sizeof(errstat));
  247. X    if (data == NULL){
  248. X    ERROR("bad parse of errstat");
  249. X    return 0;
  250. X    }
  251. X    data = asn_parse_int(data, &length, &type, &errindex, sizeof(errindex));
  252. X    if (data == NULL){
  253. X    ERROR("bad parse of errindex");
  254. X    return 0;
  255. X    }
  256. X    /*
  257. X     * Now start cobbling together what is known about the output packet.
  258. X     * The final lengths are not known now, so they will have to be recomputed
  259. X     * later.
  260. X     */
  261. X    out_auth = out_data;
  262. X    out_header = snmp_auth_build(out_auth, out_length, sid, &sidlen, &zero, 0);
  263. X    if (out_header == NULL){
  264. X    ERROR("snmp_auth_build failed");
  265. X    return 0;
  266. X    }
  267. X    out_reqid = asn_build_header(out_header, out_length, (u_char)GET_RSP_MSG, 0);
  268. X    if (out_reqid == NULL){
  269. X    ERROR("");
  270. X    return 0;
  271. X    }
  272. X
  273. X    type = (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER);
  274. X    /* return identical request id */
  275. X    out_data = asn_build_int(out_reqid, out_length, type, &reqid, sizeof(reqid));
  276. X    if (out_data == NULL){
  277. X    ERROR("build reqid failed");
  278. X    return 0;
  279. X    }
  280. X
  281. X    /* assume that error status will be zero */
  282. X    out_data = asn_build_int(out_data, out_length, type, &zero, sizeof(zero));
  283. X    if (out_data == NULL){
  284. X    ERROR("build errstat failed");
  285. X    return 0;
  286. X    }
  287. X
  288. X    /* assume that error index will be zero */
  289. X    out_data = asn_build_int(out_data, out_length, type, &zero, sizeof(zero));
  290. X    if (out_data == NULL){
  291. X    ERROR("build errindex failed");
  292. X    return 0;
  293. X    }
  294. X
  295. X    errstat = parse_var_op_list(data, length, out_data, *out_length, msg_type, &errindex, 0);
  296. X    if (msg_type == SET_REQ_MSG && errstat == SNMP_ERR_NOERROR){
  297. X    /*
  298. X     * SETS require 2 passes through the var_op_list.  The first pass verifies that
  299. X     * all types, lengths, and values are valid, and the second does the set.  Then
  300. X     * the identical GET RESPONSE packet is returned.
  301. X     */
  302. X    errstat = parse_var_op_list(data, length, out_data, *out_length, msg_type, &errindex, 1);
  303. X    if (create_identical(startData, out_auth, startLength, 0L, 0L))
  304. X        return 1;
  305. X    return 0;
  306. X    }
  307. X    switch((short)errstat){
  308. X    case SNMP_ERR_NOERROR:
  309. X        /*
  310. X         * Because of the assumption above that header lengths would be encoded
  311. X         * in one byte, things need to be fixed, now that the actual lengths are known.
  312. X         */
  313. X        header_shift = 0;
  314. X        *out_length = packet_end - out_reqid;
  315. X        if (*out_length >= 0x80){
  316. X        header_shift++;
  317. X        if (*out_length > 0xFF)
  318. X            header_shift++;
  319. X        }
  320. X        auth_shift = 0;
  321. X        *out_length = (packet_end - out_auth) - 2 + header_shift;
  322. X        if (*out_length >= 0x80){
  323. X        auth_shift++;
  324. X        if (*out_length > 0xFF)
  325. X            auth_shift++;
  326. X        }
  327. X        if (auth_shift + header_shift){
  328. X        /*
  329. X         * Shift packet (from request id to end of packet) by the sum of the
  330. X         * necessary shift counts.
  331. X         */
  332. X        shift_array(out_reqid, packet_end - out_reqid, auth_shift + header_shift);
  333. X        /* Now adjust pointers into the packet */
  334. X        packet_end += auth_shift + header_shift;
  335. X        out_reqid += auth_shift + header_shift;
  336. X        out_header += auth_shift;
  337. X        }
  338. X        
  339. X        /* re-encode the headers with the real lengths */
  340. X        out_data = out_header;
  341. X        *out_length = packet_end - out_reqid;
  342. X        out_data = asn_build_header(out_data, out_length, GET_RSP_MSG, *out_length);
  343. X        if (out_data != out_reqid){
  344. X        ERROR("internal error: header");
  345. X        return 0;
  346. X        }
  347. X
  348. X        out_data = out_auth;
  349. X        *out_length = packet_end - out_auth;
  350. X        out_data = snmp_auth_build(out_data, out_length, sid, &sidlen, &zero, packet_end - out_header);
  351. X        if (out_data != out_header){
  352. X        ERROR("internal error");
  353. X        return 0;
  354. X        }
  355. X        break;
  356. X    case SNMP_ERR_NOSUCHNAME:
  357. X    case SNMP_ERR_TOOBIG:
  358. X    case SNMP_ERR_BADVALUE:
  359. X    case SNMP_ERR_READONLY:
  360. X    case SNMP_ERR_GENERR:
  361. X        if (create_identical(startData, out_auth, startLength, errstat, errindex))
  362. X        break;
  363. X        return 0;
  364. X    default:
  365. X        return 0;
  366. X    }
  367. X    *out_length = packet_end - out_auth;
  368. X    return 1;
  369. X}
  370. X
  371. X/*
  372. X * Parse_var_op_list goes through the list of variables and retrieves each one,
  373. X * placing it's value in the output packet.  If doSet is non-zero, the variable is set
  374. X * with the value in the packet.  If any error occurs, an error code is returned.
  375. X */
  376. Xint
  377. Xparse_var_op_list(data, length, out_data, out_length, msgtype, index, doSet)
  378. X    register u_char    *data;
  379. X    int            length;
  380. X    register u_char    *out_data;
  381. X    int            out_length;
  382. X    u_char        msgtype;
  383. X    register long    *index;
  384. X    int            doSet;
  385. X{
  386. X    u_char  type;
  387. X    oid        var_name[MAX_NAME_LEN];
  388. X    int        var_name_len, var_val_len;
  389. X    u_char  var_val_type, *var_val, statType;
  390. X    register u_char *statP;
  391. X    int        statLen;
  392. X    u_short acl;
  393. X    int        rw, exact;
  394. X    int        (*write_method)();
  395. X    u_char  *headerP, *var_list_start;
  396. X    int        dummyLen;
  397. X    int        header_shift;
  398. X    u_char  *getStatPtr();
  399. X
  400. X    if (msgtype == SET_REQ_MSG)
  401. X    rw = WRITE;
  402. X    else
  403. X    rw = READ;
  404. X    if (msgtype == GETNEXT_REQ_MSG)
  405. X    exact = FALSE;
  406. X    else
  407. X    exact = TRUE;
  408. X    data = asn_parse_header(data, &length, &type);
  409. X    if (data == NULL){
  410. X    ERROR("not enough space for varlist");
  411. X    return PARSE_ERROR;
  412. X    }
  413. X    if (type != (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR)){
  414. X    ERROR("wrong type");
  415. X    return PARSE_ERROR;
  416. X    }
  417. X    headerP = out_data;
  418. X    out_data = asn_build_header(out_data, &out_length, (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), 0);
  419. X    if (out_data == NULL){
  420. X        ERROR("not enough space in output packet");
  421. X    return BUILD_ERROR;
  422. X    }
  423. X    var_list_start = out_data;
  424. X
  425. X    *index = 1;
  426. X    while((int)length > 0){
  427. X    /* parse the name, value pair */
  428. X    var_name_len = MAX_NAME_LEN;
  429. X    data = snmp_parse_var_op(data, var_name, &var_name_len, &var_val_type, &var_val_len, &var_val, (int *)&length);
  430. X    if (data == NULL)
  431. X        return PARSE_ERROR;
  432. X    /* now attempt to retrieve the variable on the local entity */
  433. X    statP = getStatPtr(var_name, &var_name_len, &statType, &statLen, &acl, exact, &write_method);
  434. X    if (statP == NULL)
  435. X        return SNMP_ERR_NOSUCHNAME;
  436. X    /* Check if this user has access rights to this variable */
  437. X    if (!snmp_access(acl, community, rw))
  438. X        return SNMP_ERR_NOSUCHNAME;    /* bogus */
  439. X    if (msgtype == SET_REQ_MSG){
  440. X        if (write_method == 0){
  441. X        /* see if the type and value is consistent with this entities variable */
  442. X        if (!goodValue(var_val_type, var_val_len, statType, statLen)){
  443. X            return SNMP_ERR_BADVALUE;
  444. X        }
  445. X        /* actually do the set if necessary */
  446. X        if (doSet)
  447. X            setVariable(var_val, var_val_type, var_val_len, statP, statLen);
  448. X        } else {
  449. X        if (!(*write_method)(doSet, var_val, var_val_type, var_val_len, statP))
  450. X            return SNMP_ERR_BADVALUE;
  451. X        }
  452. X    }
  453. X    /* retrieve the value of the variable and place it into the outgoing packet */
  454. X    out_data = snmp_build_var_op(out_data, var_name, &var_name_len, statType, statLen, statP, &out_length);
  455. X    if (out_data == NULL){
  456. X        return SNMP_ERR_TOOBIG;
  457. X    }
  458. X
  459. X    (*index)++;
  460. X    }
  461. X    packet_end = out_data;  /* save a pointer to the end of the packet */
  462. X
  463. X    /*
  464. X     * Because of the assumption above that header lengths would be encoded
  465. X     * in one byte, things need to be fixed, now that the actual lengths are known.
  466. X     */
  467. X    header_shift = 0;
  468. X    out_length = packet_end - var_list_start;
  469. X    if (out_length >= 0x80){
  470. X    header_shift++;
  471. X    if (out_length > 0xFF)
  472. X        header_shift++;
  473. X    }
  474. X    if (header_shift){
  475. X    shift_array(var_list_start, packet_end - var_list_start, header_shift);
  476. X    packet_end += header_shift;
  477. X    var_list_start += header_shift;
  478. X    }
  479. X
  480. X    /* Now rebuild header with the actual lengths */
  481. X    dummyLen = packet_end - var_list_start;
  482. X    if (asn_build_header(headerP, &dummyLen, (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), dummyLen) == NULL){
  483. X    return SNMP_ERR_TOOBIG;    /* bogus error ???? */
  484. X    }
  485. X    *index = 0;
  486. X    return SNMP_ERR_NOERROR;
  487. X}
  488. X
  489. X/*
  490. X * create a packet identical to the input packet, except for the error status
  491. X * and the error index which are set according to the input variables.
  492. X * Returns 1 upon success and 0 upon failure.
  493. X */
  494. Xint
  495. Xcreate_identical(snmp_in, snmp_out, snmp_length, errstat, errindex)
  496. X    u_char        *snmp_in;
  497. X    u_char        *snmp_out;
  498. X    int            snmp_length;
  499. X    long        errstat, errindex;
  500. X{
  501. X    register u_char *data;
  502. X    u_char        type;
  503. X    u_long        dummy;
  504. X    int            length, headerLength;
  505. X    register u_char *headerPtr, *reqidPtr, *errstatPtr, *errindexPtr, *varListPtr;
  506. X
  507. X    bcopy((char *)snmp_in, (char *)snmp_out, snmp_length);
  508. X    length = snmp_length;
  509. X    headerPtr = snmp_auth_parse(snmp_out, &length, sid, &sidlen, (long *)&dummy);
  510. X    if (headerPtr == NULL)
  511. X    return 0;
  512. X    reqidPtr = asn_parse_header(headerPtr, &length, (u_char *)&dummy);
  513. X    if (reqidPtr == NULL)
  514. X    return 0;
  515. X    headerLength = length;
  516. X    errstatPtr = asn_parse_int(reqidPtr, &length, &type, (long *)&dummy, sizeof dummy);    /* request id */
  517. X    if (errstatPtr == NULL)
  518. X    return 0;
  519. X    errindexPtr = asn_parse_int(errstatPtr, &length, &type, (long *)&dummy, sizeof dummy);    /* error status */
  520. X    if (errindexPtr == NULL)
  521. X    return 0;
  522. X    varListPtr = asn_parse_int(errindexPtr, &length, &type, (long *)&dummy, sizeof dummy);    /* error index */
  523. X    if (varListPtr == NULL)
  524. X    return 0;
  525. X
  526. X    data = asn_build_header(headerPtr, &headerLength, GET_RSP_MSG, headerLength);
  527. X    if (data != reqidPtr)
  528. X    return 0;
  529. X    length = snmp_length;
  530. X    type = (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER);
  531. X    data = asn_build_int(errstatPtr, &length, type, &errstat, sizeof errstat);
  532. X    if (data != errindexPtr)
  533. X    return 0;
  534. X    data = asn_build_int(errindexPtr, &length, type, &errindex, sizeof errindex);
  535. X    if (data != varListPtr)
  536. X    return 0;
  537. X    packet_end = snmp_out + snmp_length;
  538. X    return 1;
  539. X}
  540. X
  541. X#ifdef KINETICS
  542. Xstruct pbuf *
  543. XdefinitelyGetBuf(){
  544. X    register struct pbuf *p;
  545. X
  546. X    K_PGET(PT_DATA, p);
  547. X    while(p == 0){
  548. X#ifdef notdef
  549. X    if (pq->pq_head != NULL){
  550. X        K_PDEQ(SPLIMP, pq, p);
  551. X        if (p) K_PFREE(p);
  552. X    } else if (sendq->pq_head != NULL){
  553. X        K_PDEQ(SPLIMP, sendq, p);
  554. X        if (p) K_PFREE(p);
  555. X    }
  556. X#endif
  557. X    K_PGET(PT_DATA, p);
  558. X    }
  559. X    return p;
  560. X}
  561. X#endif
  562. X
  563. Xint
  564. Xsnmp_access(acl, community, rw)
  565. X    u_short     acl;
  566. X    int        community;
  567. X    int        rw;
  568. X{
  569. X    /*
  570. X     * Each group has 2 bits, the more significant one is for read access,
  571. X     * the less significant one is for write access.
  572. X     */
  573. X
  574. X    community <<= 1;    /* multiply by two two shift two bits at a time */
  575. X    if (rw == READ){
  576. X    return (acl & (2 << community));    /* return the correct bit */
  577. X    } else {
  578. X    return (acl & (1 << community));
  579. X    }
  580. X}
  581. X
  582. Xint
  583. Xget_community(sessionid)
  584. X    u_char    *sessionid;
  585. X{
  586. X    int    count;
  587. X
  588. X    for(count = 0; count < NUM_COMMUNITIES; count++){
  589. X    if (!strcmp(communities[count], (char *)sessionid))
  590. X        break;
  591. X    }
  592. X    if (count == NUM_COMMUNITIES)
  593. X    return -1;
  594. X    return count;
  595. X}
  596. X
  597. Xint
  598. XgoodValue(inType, inLen, actualType, actualLen)
  599. X    u_char    inType, actualType;
  600. X    int        inLen, actualLen;
  601. X{
  602. X    if (inLen > actualLen)
  603. X    return FALSE;
  604. X    return (inType == actualType);
  605. X}
  606. X
  607. XsetVariable(var_val, var_val_type, var_val_len, statP, statLen)
  608. X    u_char  *var_val;
  609. X    u_char  var_val_type;
  610. X    int        var_val_len;
  611. X    u_char  *statP;
  612. X    int        statLen;
  613. X{
  614. X    int        buffersize = 1000;
  615. X
  616. X    switch(var_val_type){
  617. X    case ASN_INTEGER:
  618. X    case COUNTER:
  619. X    case GAUGE:
  620. X    case TIMETICKS:
  621. X        asn_parse_int(var_val, &buffersize, &var_val_type, (long *)statP, statLen);
  622. X        break;
  623. X    case ASN_OCTET_STR:
  624. X    case IPADDRESS:
  625. X    case OPAQUE:
  626. X        asn_parse_string(var_val, &buffersize, &var_val_type, statP, &statLen);
  627. X        break;
  628. X    case ASN_OBJECT_ID:
  629. X        asn_parse_objid(var_val, &buffersize, &var_val_type, (oid *)statP, &statLen);
  630. X        break;
  631. X    }
  632. X}
  633. X
  634. X
  635. END_OF_FILE
  636.   if test 17980 -ne `wc -c <'nocol-3.0/src/cmu-snmp/apps/snmp_agent.c'`; then
  637.     echo shar: \"'nocol-3.0/src/cmu-snmp/apps/snmp_agent.c'\" unpacked with wrong size!
  638.   fi
  639.   # end of 'nocol-3.0/src/cmu-snmp/apps/snmp_agent.c'
  640. fi
  641. if test -f 'nocol-3.0/src/cmu-snmp/include/mib.c' -a "${1}" != "-c" ; then 
  642.   echo shar: Will not clobber existing file \"'nocol-3.0/src/cmu-snmp/include/mib.c'\"
  643. else
  644.   echo shar: Extracting \"'nocol-3.0/src/cmu-snmp/include/mib.c'\" \(17909 characters\)
  645.   sed "s/^X//" >'nocol-3.0/src/cmu-snmp/include/mib.c' <<'END_OF_FILE'
  646. X/***********************************************************
  647. X    Copyright 1988, 1989 by Carnegie Mellon University
  648. X
  649. X                      All Rights Reserved
  650. X
  651. XPermission to use, copy, modify, and distribute this software and its 
  652. Xdocumentation for any purpose and without fee is hereby granted, 
  653. Xprovided that the above copyright notice appear in all copies and that
  654. Xboth that copyright notice and this permission notice appear in 
  655. Xsupporting documentation, and that the name of CMU not be
  656. Xused in advertising or publicity pertaining to distribution of the
  657. Xsoftware without specific, written prior permission.  
  658. X
  659. XCMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  660. XALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  661. XCMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  662. XANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  663. XWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  664. XARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  665. XSOFTWARE.
  666. X******************************************************************/
  667. X#include <stdio.h>
  668. X#include <ctype.h>
  669. X#include <sys/types.h>
  670. X#include <netinet/in.h>
  671. X#include <sys/time.h>
  672. X#include "asn1.h"
  673. X#include "snmp_impl.h"
  674. X#include "snmp_api.h"
  675. X#include "parse.h"
  676. X
  677. Xstatic void sprint_by_type();
  678. X
  679. Xstatic char *
  680. XuptimeString(timeticks, buf)
  681. X    register long timeticks;
  682. X    char *buf;
  683. X{
  684. X    int    seconds, minutes, hours, days;
  685. X
  686. X    timeticks /= 100;
  687. X    days = timeticks / (60 * 60 * 24);
  688. X    timeticks %= (60 * 60 * 24);
  689. X
  690. X    hours = timeticks / (60 * 60);
  691. X    timeticks %= (60 * 60);
  692. X
  693. X    minutes = timeticks / 60;
  694. X    seconds = timeticks % 60;
  695. X
  696. X    if (days == 0){
  697. X    sprintf(buf, "%d:%02d:%02d", hours, minutes, seconds);
  698. X    } else if (days == 1) {
  699. X    sprintf(buf, "%d day, %d:%02d:%02d", days, hours, minutes, seconds);
  700. X    } else {
  701. X    sprintf(buf, "%d days, %d:%02d:%02d", days, hours, minutes, seconds);
  702. X    }
  703. X    return buf;
  704. X}
  705. X
  706. Xstatic sprint_hexstring(buf, cp, len)
  707. X    char *buf;
  708. X    u_char  *cp;
  709. X    int        len;
  710. X{
  711. X
  712. X    for(; len >= 16; len -= 16){
  713. X    sprintf(buf, "%02X %02X %02X %02X %02X %02X %02X %02X ", cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
  714. X    buf += strlen(buf);
  715. X    cp += 8;
  716. X    sprintf(buf, "%02X %02X %02X %02X %02X %02X %02X %02X\n", cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
  717. X    buf += strlen(buf);
  718. X    cp += 8;
  719. X    }
  720. X    for(; len > 0; len--){
  721. X    sprintf(buf, "%02X ", *cp++);
  722. X    buf += strlen(buf);
  723. X    }
  724. X    *buf = '\0';
  725. X}
  726. X
  727. Xstatic sprint_asciistring(buf, cp, len)
  728. X    char *buf;
  729. X    u_char  *cp;
  730. X    int        len;
  731. X{
  732. X    int    x;
  733. X
  734. X    for(x = 0; x < len; x++){
  735. X    if (isprint(*cp)){
  736. X        *buf++ = *cp++;
  737. X    } else {
  738. X        *buf++ = '.';
  739. X        cp++;
  740. X    }
  741. X    if ((x % 48) == 47)
  742. X        *buf++ = '\n';
  743. X    }
  744. X    *buf = '\0';
  745. X}
  746. X
  747. X#ifdef UNUSED
  748. Xint
  749. Xread_rawobjid(input, output, out_len)
  750. X    char *input;
  751. X    oid *output;
  752. X    int    *out_len;
  753. X{
  754. X    char    buf[12], *cp;
  755. X    oid        *op = output;
  756. X    u_long  subid;
  757. X
  758. X    while(*input != '\0'){
  759. X    if (!isdigit(*input))
  760. X        break;
  761. X    cp = buf;
  762. X    while(isdigit(*input))
  763. X        *cp++ = *input++;
  764. X    *cp = '\0';
  765. X    subid = atoi(buf);
  766. X    if(subid > MAX_SUBID){
  767. X        fprintf(stderr, "sub-identifier too large: %s\n", buf);
  768. X        return 0;
  769. X    }
  770. X    if((*out_len)-- <= 0){
  771. X        fprintf(stderr, "object identifier too long\n");
  772. X        return 0;
  773. X    }
  774. X    *op++ = subid;
  775. X    if(*input++ != '.')
  776. X        break;
  777. X    }
  778. X    *out_len = op - output;
  779. X    if (*out_len == 0)
  780. X    return 0;
  781. X    return 1;
  782. X}
  783. X
  784. X#endif /* UNUSED */
  785. X
  786. Xstatic void
  787. Xsprint_octet_string(buf, var)
  788. X    char *buf;
  789. X    struct variable_list *var;
  790. X{
  791. X    int hex, x;
  792. X    u_char *cp;
  793. X
  794. X    if (var->type != ASN_OCTET_STR){
  795. X    sprintf(buf, "Wrong Type (should be OCTET STRING): ");
  796. X    buf += strlen(buf);
  797. X    sprint_by_type(buf, var, (struct enum_list *)NULL);
  798. X    return;
  799. X    }
  800. X    hex = 0;
  801. X    for(cp = var->val.string, x = 0; x < var->val_len; x++, cp++){
  802. X    if (!(isprint(*cp) || isspace(*cp)))
  803. X        hex = 1;
  804. X    }
  805. X    if (var->val_len <= 4)
  806. X    hex = 1;    /* not likely to be ascii */
  807. X    if (hex){
  808. X    sprintf(buf, "OCTET STRING-   (hex):\t");
  809. X    buf += strlen(buf);
  810. X    sprint_hexstring(buf, var->val.string, var->val_len);
  811. X    } else {
  812. X    sprintf(buf, "OCTET STRING- (ascii):\t");
  813. X    buf += strlen(buf);
  814. X    sprint_asciistring(buf, var->val.string, var->val_len);
  815. X    }
  816. X}
  817. X
  818. Xstatic void
  819. Xsprint_opaque(buf, var)
  820. X    char *buf;
  821. X    struct variable_list *var;
  822. X{
  823. X
  824. X    if (var->type != OPAQUE){
  825. X    sprintf(buf, "Wrong Type (should be Opaque): ");
  826. X    buf += strlen(buf);
  827. X    sprint_by_type(buf, var, (struct enum_list *)NULL);
  828. X    return;
  829. X    }
  830. X    sprintf(buf, "OPAQUE -   (hex):\t");
  831. X    buf += strlen(buf);
  832. X    sprint_hexstring(buf, var->val.string, var->val_len);
  833. X}
  834. X
  835. Xstatic void
  836. Xsprint_object_identifier(buf, var)
  837. X    char *buf;
  838. X    struct variable_list *var;
  839. X{
  840. X    if (var->type != ASN_OBJECT_ID){
  841. X    sprintf(buf, "Wrong Type (should be OBJECT IDENTIFIER): ");
  842. X    buf += strlen(buf);
  843. X    sprint_by_type(buf, var, (struct enum_list *)NULL);
  844. X    return;
  845. X    }
  846. X    sprintf(buf, "OBJECT IDENTIFIER:\t");
  847. X    buf += strlen(buf);
  848. X    sprint_objid(buf, (oid *)(var->val.objid), var->val_len / sizeof(oid));
  849. X}
  850. X
  851. Xstatic void
  852. Xsprint_timeticks(buf, var)
  853. X    char *buf;
  854. X    struct variable_list *var;
  855. X{
  856. X    char timebuf[32];
  857. X
  858. X    if (var->type != TIMETICKS){
  859. X    sprintf(buf, "Wrong Type (should be Timeticks): ");
  860. X    buf += strlen(buf);
  861. X    sprint_by_type(buf, var, (struct enum_list *)NULL);
  862. X    return;
  863. X    }
  864. X    sprintf(buf, "Timeticks: (%d) %s", *(var->val.integer), uptimeString(*(var->val.integer), timebuf));
  865. X}
  866. X
  867. Xstatic void
  868. Xsprint_integer(buf, var, enums)
  869. X    char *buf;
  870. X    struct variable_list *var;
  871. X    struct enum_list        *enums;
  872. X{
  873. X    char    *enum_string = NULL;
  874. X
  875. X    if (var->type != ASN_INTEGER){
  876. X    sprintf(buf, "Wrong Type (should be INTEGER): ");
  877. X    buf += strlen(buf);
  878. X    sprint_by_type(buf, var, (struct enum_list *)NULL);
  879. X    return;
  880. X    }
  881. X    for (; enums; enums = enums->next)
  882. X    if (enums->value == *var->val.integer){
  883. X        enum_string = enums->label;
  884. X        break;
  885. X    }
  886. X    if (enum_string == NULL)
  887. X    sprintf(buf, "INTEGER: %d", *var->val.integer);
  888. X    else
  889. X    sprintf(buf, "INTEGER: %s(%d)", enum_string, *var->val.integer);
  890. X}
  891. X
  892. Xstatic void
  893. Xsprint_gauge(buf, var)
  894. X    char *buf;
  895. X    struct variable_list *var;
  896. X{
  897. X    if (var->type != GAUGE){
  898. X    sprintf(buf, "Wrong Type (should be Gauge): ");
  899. X    buf += strlen(buf);
  900. X    sprint_by_type(buf, var, (struct enum_list *)NULL);
  901. X    return;
  902. X    }
  903. X    sprintf(buf, "Gauge: %lu", *var->val.integer);
  904. X}
  905. X
  906. Xstatic void
  907. Xsprint_counter(buf, var)
  908. X    char *buf;
  909. X    struct variable_list *var;
  910. X{
  911. X    if (var->type != COUNTER){
  912. X    sprintf(buf, "Wrong Type (should be Counter): ");
  913. X    buf += strlen(buf);
  914. X    sprint_by_type(buf, var, (struct enum_list *)NULL);
  915. X    return;
  916. X    }
  917. X    sprintf(buf, "Counter: %lu", *var->val.integer);
  918. X}
  919. X
  920. Xstatic void
  921. Xsprint_networkaddress(buf, var)
  922. X    char *buf;
  923. X    struct variable_list *var;
  924. X{
  925. X    int x, len;
  926. X    u_char *cp;
  927. X
  928. X    sprintf(buf, "Network Address:\t");
  929. X    buf += strlen(buf);
  930. X    cp = var->val.string;    
  931. X    len = var->val_len;
  932. X    for(x = 0; x < len; x++){
  933. X    sprintf(buf, "%02X", *cp++);
  934. X    buf += strlen(buf);
  935. X    if (x < (len - 1))
  936. X        *buf++ = ':';
  937. X    }
  938. X}
  939. X
  940. Xstatic void
  941. Xsprint_ipaddress(buf, var)
  942. X    char *buf;
  943. X    struct variable_list *var;
  944. X{
  945. X    u_char *ip;
  946. X
  947. X    if (var->type != IPADDRESS){
  948. X    sprintf(buf, "Wrong Type (should be Ipaddress): ");
  949. X    buf += strlen(buf);
  950. X    sprint_by_type(buf, var, (struct enum_list *)NULL);
  951. X    return;
  952. X    }
  953. X    ip = var->val.string;
  954. X    sprintf(buf, "IpAddress:\t%d.%d.%d.%d",ip[0], ip[1], ip[2], ip[3]);
  955. X}
  956. X
  957. Xstatic void
  958. Xsprint_unsigned_short(buf, var)
  959. X    char *buf;
  960. X    struct variable_list *var;
  961. X{
  962. X    if (var->type != ASN_INTEGER){
  963. X    sprintf(buf, "Wrong Type (should be INTEGER): ");
  964. X    buf += strlen(buf);
  965. X    sprint_by_type(buf, var, (struct enum_list *)NULL);
  966. X    return;
  967. X    }
  968. X    sprintf(buf, "INTEGER (0..65535): %lu", *var->val.integer);
  969. X}
  970. X
  971. Xstatic void
  972. Xsprint_null(buf, var)
  973. X    char *buf;
  974. X    struct variable_list *var;
  975. X{
  976. X    if (var->type != ASN_NULL){
  977. X    sprintf(buf, "Wrong Type (should be NULL): ");
  978. X    buf += strlen(buf);
  979. X    sprint_by_type(buf, var, (struct enum_list *)NULL);
  980. X    return;
  981. X    }
  982. X    sprintf(buf, "NULL");
  983. X}
  984. X
  985. Xstatic void
  986. Xsprint_unknowntype(buf, var)
  987. X    char *buf;
  988. X    struct variable_list *var;
  989. X{
  990. X/*    sprintf(buf, "Variable has bad type"); */
  991. X    sprint_by_type(buf, var, NULL);
  992. X}
  993. X
  994. Xstatic void
  995. Xsprint_badtype(buf)
  996. X    char *buf;
  997. X{
  998. X    sprintf(buf, "Variable has bad type");
  999. X}
  1000. X
  1001. Xstatic void
  1002. Xsprint_by_type(buf, var, enums)
  1003. X    char *buf;
  1004. X    struct variable_list *var;
  1005. X    struct enum_list        *enums;
  1006. X{
  1007. X    switch (var->type){
  1008. X    case ASN_INTEGER:
  1009. X        sprint_integer(buf, var, enums);
  1010. X        break;
  1011. X    case ASN_OCTET_STR:
  1012. X        sprint_octet_string(buf, var);
  1013. X        break;
  1014. X    case OPAQUE:
  1015. X        sprint_opaque(buf, var);
  1016. X        break;
  1017. X    case ASN_OBJECT_ID:
  1018. X        sprint_object_identifier(buf, var);
  1019. X        break;
  1020. X    case TIMETICKS:
  1021. X        sprint_timeticks(buf, var);
  1022. X        break;
  1023. X    case GAUGE:
  1024. X        sprint_gauge(buf, var);
  1025. X        break;
  1026. X    case COUNTER:
  1027. X        sprint_counter(buf, var);
  1028. X        break;
  1029. X    case IPADDRESS:
  1030. X        sprint_ipaddress(buf, var);
  1031. X        break;
  1032. X    case ASN_NULL:
  1033. X        sprint_null(buf, var);
  1034. X        break;
  1035. X    default:
  1036. X        sprint_badtype(buf);
  1037. X        break;
  1038. X    }
  1039. X}
  1040. X
  1041. Xstruct tree *get_symbol();
  1042. X
  1043. Xoid RFC1066_MIB[] = { 1, 3, 6, 1, 2, 1 };
  1044. Xunsigned char RFC1066_MIB_text[] = ".iso.org.dod.internet.mgmt.mib";
  1045. Xstruct tree *Mib;
  1046. X
  1047. Xinit_mib()
  1048. X{
  1049. X    char *file, *getenv();
  1050. X
  1051. X    Mib = 0;
  1052. X    file = getenv("MIBFILE");
  1053. X    if (file)
  1054. X    Mib = read_mib(file);
  1055. X    if (!Mib)
  1056. X    Mib = read_mib("mib.txt");
  1057. X    if (!Mib)
  1058. X    Mib = read_mib("/etc/mib.txt");
  1059. X    if (!Mib){
  1060. X    fprintf(stderr, "Couldn't find mib file\n");
  1061. X    exit(2);
  1062. X    }
  1063. X    set_functions(Mib);
  1064. X}
  1065. X
  1066. Xstatic
  1067. Xset_functions(subtree)
  1068. X    struct tree *subtree;
  1069. X{
  1070. X    for(; subtree; subtree = subtree->next_peer){
  1071. X    switch(subtree->type){
  1072. X        case TYPE_OBJID:
  1073. X        subtree->printer = sprint_object_identifier;
  1074. X        break;
  1075. X        case TYPE_OCTETSTR:
  1076. X        subtree->printer = sprint_octet_string;
  1077. X        break;
  1078. X        case TYPE_INTEGER:
  1079. X        subtree->printer = sprint_integer;
  1080. X        break;
  1081. X        case TYPE_NETADDR:
  1082. X        subtree->printer = sprint_networkaddress;
  1083. X        break;
  1084. X        case TYPE_IPADDR:
  1085. X        subtree->printer = sprint_ipaddress;
  1086. X        break;
  1087. X        case TYPE_COUNTER:
  1088. X        subtree->printer = sprint_counter;
  1089. X        break;
  1090. X        case TYPE_GAUGE:
  1091. X        subtree->printer = sprint_gauge;
  1092. X        break;
  1093. X        case TYPE_TIMETICKS:
  1094. X        subtree->printer = sprint_timeticks;
  1095. X        break;
  1096. X        case TYPE_OPAQUE:
  1097. X        subtree->printer = sprint_opaque;
  1098. X        break;
  1099. X        case TYPE_NULL:
  1100. X        subtree->printer = sprint_null;
  1101. X        break;
  1102. X        case TYPE_OTHER:
  1103. X        default:
  1104. X        subtree->printer = sprint_unknowntype;
  1105. X        break;
  1106. X    }
  1107. X    set_functions(subtree->child_list);
  1108. X    }
  1109. X}
  1110. X
  1111. X#ifdef testing
  1112. Xint snmp_dump_packet = 0;
  1113. X
  1114. Xmain(argc, argv)
  1115. X     int argc;
  1116. X     char *argv[];
  1117. X{
  1118. X    oid objid[64];
  1119. X    int objidlen = sizeof (objid);
  1120. X    int count;
  1121. X    struct variable variable;
  1122. X
  1123. X    init_mib(&Mib);
  1124. X    if (argc < 2)
  1125. X    print_subtree(Mib, 0);
  1126. X    variable.type = ASN_INTEGER;
  1127. X    variable.val.integer = 3;
  1128. X    variable.val_len = 4;
  1129. X    for (argc--; argc; argc--, argv++) {
  1130. X    objidlen = sizeof (objid);
  1131. X    printf("read_objid(%s) = %d\n",
  1132. X           argv[1], read_objid(argv[1], objid, &objidlen));
  1133. X    for(count = 0; count < objidlen; count++)
  1134. X        printf("%d.", objid[count]);
  1135. X    printf("\n");
  1136. X    print_variable(objid, objidlen, &variable);
  1137. X    }
  1138. X}
  1139. X
  1140. X#endif testing
  1141. X
  1142. X
  1143. Xstatic struct tree *
  1144. Xfind_rfc1066_mib(root)
  1145. X    struct tree *root;
  1146. X{
  1147. X    oid *op = RFC1066_MIB;
  1148. X    struct tree *tp;
  1149. X    int len;
  1150. X
  1151. X    for(len = sizeof(RFC1066_MIB)/sizeof(oid); len; len--, op++){
  1152. X    for(tp = root; tp; tp = tp->next_peer){
  1153. X        if (tp->subid == *op){
  1154. X        root = tp->child_list;
  1155. X        break;
  1156. X        }
  1157. X    }
  1158. X    if (tp == NULL)
  1159. X        return NULL;
  1160. X    }
  1161. X    return root;
  1162. X}
  1163. X
  1164. Xint read_objid(input, output, out_len)
  1165. X    char *input;
  1166. X    oid *output;
  1167. X    int    *out_len;   /* number of subid's in "output" */
  1168. X{
  1169. X    struct tree *root = Mib;
  1170. X    oid *op = output;
  1171. X    int i;
  1172. X
  1173. X    if (*input == '.')
  1174. X    input++;
  1175. X    else {
  1176. X    root = find_rfc1066_mib(root);
  1177. X    for (i = 0; i < sizeof (RFC1066_MIB)/sizeof(oid); i++) {
  1178. X        if ((*out_len)-- > 0)
  1179. X        *output++ = RFC1066_MIB[i];
  1180. X        else {
  1181. X        fprintf(stderr, "object identifier too long\n");
  1182. X        return (0);
  1183. X        }
  1184. X    }
  1185. X    }
  1186. X
  1187. X    if (root == NULL){
  1188. X    fprintf(stderr, "Mib not initialized.  Exiting.\n");
  1189. X    exit(1);
  1190. X    }
  1191. X    if ((*out_len =
  1192. X     parse_subtree(root, input, output, out_len)) == 0)
  1193. X    return (0);
  1194. X    *out_len += output - op;
  1195. X
  1196. X    return (1);
  1197. X}
  1198. X
  1199. Xstatic
  1200. Xparse_subtree(subtree, input, output, out_len)
  1201. X    struct tree *subtree;
  1202. X    char *input;
  1203. X    oid    *output;
  1204. X    int    *out_len;   /* number of subid's */
  1205. X{
  1206. X    char buf[128], *to = buf;
  1207. X    u_long subid = 0;
  1208. X    struct tree *tp;
  1209. X
  1210. X    /*
  1211. X     * No empty strings.  Can happen if there is a trailing '.' or two '.'s
  1212. X     * in a row, i.e. "..".
  1213. X     */
  1214. X    if ((*input == '\0') ||
  1215. X    (*input == '.'))
  1216. X    return (0);
  1217. X
  1218. X    if (isdigit(*input)) {
  1219. X    /*
  1220. X     * Read the number, then try to find it in the subtree.
  1221. X     */
  1222. X    while (isdigit(*input)) {
  1223. X        subid *= 10;
  1224. X        subid += *input++ - '0';
  1225. X    }
  1226. X    for (tp = subtree; tp; tp = tp->next_peer) {
  1227. X        if (tp->subid == subid)
  1228. X        goto found;
  1229. X    }
  1230. X    tp = NULL;
  1231. X    }
  1232. X    else {
  1233. X    /*
  1234. X     * Read the name into a buffer.
  1235. X     */
  1236. X    while ((*input != '\0') &&
  1237. X           (*input != '.')) {
  1238. X        *to++ = *input++;
  1239. X    }
  1240. X    *to = '\0';
  1241. X
  1242. X    /*
  1243. X     * Find the name in the subtree;
  1244. X     */
  1245. X    for (tp = subtree; tp; tp = tp->next_peer) {
  1246. X        if (lc_cmp(tp->label, buf) == 0) {
  1247. X        subid = tp->subid;
  1248. X        goto found;
  1249. X        }
  1250. X    }
  1251. X
  1252. X    /*
  1253. X     * If we didn't find the entry, punt...
  1254. X     */
  1255. X    if (tp == NULL) {
  1256. X        fprintf(stderr, "sub-identifier not found: %s\n", buf);
  1257. X        return (0);
  1258. X    }
  1259. X    }
  1260. X
  1261. Xfound:
  1262. X    if(subid > (u_long)MAX_SUBID){
  1263. X    fprintf(stderr, "sub-identifier too large: %s\n", buf);
  1264. X    return (0);
  1265. X    }
  1266. X
  1267. X    if ((*out_len)-- <= 0){
  1268. X    fprintf(stderr, "object identifier too long\n");
  1269. X    return (0);
  1270. X    }
  1271. X    *output++ = subid;
  1272. X
  1273. X    if (*input != '.')
  1274. X    return (1);
  1275. X    if ((*out_len =
  1276. X     parse_subtree(tp ? tp->child_list : NULL, ++input, output, out_len)) == 0)
  1277. X    return (0);
  1278. X    return (++*out_len);
  1279. X}
  1280. X
  1281. Xprint_objid(objid, objidlen)
  1282. X    oid        *objid;
  1283. X    int        objidlen;    /* number of subidentifiers */
  1284. X{
  1285. X    char    buf[256];
  1286. X    struct tree    *subtree = Mib;
  1287. X
  1288. X    *buf = '.';    /* this is a fully qualified name */
  1289. X    get_symbol(objid, objidlen, subtree, buf + 1);
  1290. X    printf("%s\n", buf);
  1291. X        
  1292. X}
  1293. X
  1294. Xsprint_objid(buf, objid, objidlen)
  1295. X    char *buf;
  1296. X    oid        *objid;
  1297. X    int        objidlen;    /* number of subidentifiers */
  1298. X{
  1299. X    struct tree    *subtree = Mib;
  1300. X
  1301. X    *buf = '.';    /* this is a fully qualified name */
  1302. X    get_symbol(objid, objidlen, subtree, buf + 1);
  1303. X}
  1304. X
  1305. X
  1306. Xprint_variable(objid, objidlen, variable)
  1307. X    oid     *objid;
  1308. X    int        objidlen;
  1309. X    struct  variable_list *variable;
  1310. X{
  1311. X    char    buf[512], *cp;
  1312. X    struct tree    *subtree = Mib;
  1313. X
  1314. X    *buf = '.';    /* this is a fully qualified name */
  1315. X    subtree = get_symbol(objid, objidlen, subtree, buf + 1);
  1316. X    cp = buf;
  1317. X    if ((strlen(buf) >= strlen((char *)RFC1066_MIB_text)) && !bcmp(buf, (char *)RFC1066_MIB_text,
  1318. X    strlen((char *)RFC1066_MIB_text))){
  1319. X        cp += sizeof(RFC1066_MIB_text);
  1320. X    }
  1321. X    printf("Name: %s\n", cp);
  1322. X    *buf = '\0';
  1323. X    if (subtree->printer)
  1324. X    (*subtree->printer)(buf, variable, subtree->enums);
  1325. X    else {
  1326. X    sprint_by_type(buf, variable, subtree->enums);
  1327. X    }
  1328. X    printf("%s\n", buf);
  1329. X}
  1330. X
  1331. Xsprint_variable(buf, objid, objidlen, variable)
  1332. X    char *buf;
  1333. X    oid     *objid;
  1334. X    int        objidlen;
  1335. X    struct  variable_list *variable;
  1336. X{
  1337. X    char    tempbuf[512], *cp;
  1338. X    struct tree    *subtree = Mib;
  1339. X
  1340. X    *tempbuf = '.';    /* this is a fully qualified name */
  1341. X    subtree = get_symbol(objid, objidlen, subtree, tempbuf + 1);
  1342. X    cp = tempbuf;
  1343. X    if ((strlen(buf) >= strlen((char *)RFC1066_MIB_text)) && !bcmp(buf, (char *)RFC1066_MIB_text,
  1344. X    strlen((char *)RFC1066_MIB_text))){
  1345. X        cp += sizeof(RFC1066_MIB_text);
  1346. X    }
  1347. X    sprintf(buf, "Name: %s\n", cp);
  1348. X    buf += strlen(buf);
  1349. X    if (subtree->printer)
  1350. X    (*subtree->printer)(buf, variable, subtree->enums);
  1351. X    else {
  1352. X    sprint_by_type(buf, variable, subtree->enums);
  1353. X    }
  1354. X    strcat(buf, "\n");
  1355. X}
  1356. X
  1357. Xsprint_value(buf, objid, objidlen, variable)
  1358. X    char *buf;
  1359. X    oid     *objid;
  1360. X    int        objidlen;
  1361. X    struct  variable_list *variable;
  1362. X{
  1363. X    char    tempbuf[512];
  1364. X    struct tree    *subtree = Mib;
  1365. X
  1366. X    subtree = get_symbol(objid, objidlen, subtree, tempbuf);
  1367. X    if (subtree->printer)
  1368. X    (*subtree->printer)(buf, variable, subtree->enums);
  1369. X    else {
  1370. X    sprint_by_type(buf, variable, subtree->enums);
  1371. X    }
  1372. X}
  1373. X
  1374. Xprint_value(objid, objidlen, variable)
  1375. X    oid     *objid;
  1376. X    int        objidlen;
  1377. X    struct  variable_list *variable;
  1378. X{
  1379. X    char    tempbuf[512];
  1380. X    struct tree    *subtree = Mib;
  1381. X
  1382. X    subtree = get_symbol(objid, objidlen, subtree, tempbuf);
  1383. X    if (subtree->printer)
  1384. X    (*subtree->printer)(tempbuf, variable, subtree->enums);
  1385. X    else {
  1386. X    sprint_by_type(tempbuf, variable, subtree->enums);
  1387. X    }
  1388. X    printf("%s\n", tempbuf);
  1389. X}
  1390. X
  1391. Xstruct tree *
  1392. Xget_symbol(objid, objidlen, subtree, buf)
  1393. X    oid        *objid;
  1394. X    int        objidlen;
  1395. X    struct tree    *subtree;
  1396. X    char    *buf;
  1397. X{
  1398. X    struct tree    *return_tree = NULL;
  1399. X
  1400. X    for(; subtree; subtree = subtree->next_peer){
  1401. X    if (*objid == subtree->subid){
  1402. X        strcpy(buf, subtree->label);
  1403. X        goto found;
  1404. X    }
  1405. X    }
  1406. X
  1407. X    /* subtree not found */
  1408. X    while(objidlen--){    /* output rest of name, uninterpreted */
  1409. X    sprintf(buf, "%u.", *objid++);
  1410. X    while(*buf)
  1411. X        buf++;
  1412. X    }
  1413. X    *(buf - 1) = '\0'; /* remove trailing dot */
  1414. X    return NULL;
  1415. X
  1416. Xfound:
  1417. X    if (objidlen > 1){
  1418. X    while(*buf)
  1419. X        buf++;
  1420. X    *buf++ = '.';
  1421. X    *buf = '\0';
  1422. X    return_tree = get_symbol(objid + 1, objidlen - 1, subtree->child_list, buf);
  1423. X    } 
  1424. X    if (return_tree != NULL)
  1425. X    return return_tree;
  1426. X    else
  1427. X    return subtree;
  1428. X}
  1429. X
  1430. X
  1431. Xstatic int
  1432. Xlc_cmp(s1, s2)
  1433. X    char *s1, *s2;
  1434. X{
  1435. X    char c1, c2;
  1436. X
  1437. X    while(*s1 && *s2){
  1438. X    if (isupper(*s1))
  1439. X        c1 = tolower(*s1);
  1440. X    else
  1441. X        c1 = *s1;
  1442. X    if (isupper(*s2))
  1443. X        c2 = tolower(*s2);
  1444. X    else
  1445. X        c2 = *s2;
  1446. X    if (c1 != c2)
  1447. X        return ((c1 - c2) > 0 ? 1 : -1);
  1448. X    s1++;
  1449. X    s2++;
  1450. X    }
  1451. X
  1452. X    if (*s1)
  1453. X    return -1;
  1454. X    if (*s2)
  1455. X    return 1;
  1456. X    return 0;
  1457. X}
  1458. X
  1459. END_OF_FILE
  1460.   if test 17909 -ne `wc -c <'nocol-3.0/src/cmu-snmp/include/mib.c'`; then
  1461.     echo shar: \"'nocol-3.0/src/cmu-snmp/include/mib.c'\" unpacked with wrong size!
  1462.   fi
  1463.   # end of 'nocol-3.0/src/cmu-snmp/include/mib.c'
  1464. fi
  1465. if test -f 'nocol-3.0/src/cmu-snmp/snmplib/asn1.c.cmu' -a "${1}" != "-c" ; then 
  1466.   echo shar: Will not clobber existing file \"'nocol-3.0/src/cmu-snmp/snmplib/asn1.c.cmu'\"
  1467. else
  1468.   echo shar: Extracting \"'nocol-3.0/src/cmu-snmp/snmplib/asn1.c.cmu'\" \(18366 characters\)
  1469.   sed "s/^X//" >'nocol-3.0/src/cmu-snmp/snmplib/asn1.c.cmu' <<'END_OF_FILE'
  1470. X/*
  1471. X * Abstract Syntax Notation One, ASN.1
  1472. X * As defined in ISO/IS 8824 and ISO/IS 8825
  1473. X * This implements a subset of the above International Standards that
  1474. X * is sufficient to implement SNMP.
  1475. X *
  1476. X * Encodes abstract data types into a machine independent stream of bytes.
  1477. X *
  1478. X */
  1479. X/***********************************************************
  1480. X    Copyright 1988, 1989 by Carnegie Mellon University
  1481. X
  1482. X                      All Rights Reserved
  1483. X
  1484. XPermission to use, copy, modify, and distribute this software and its 
  1485. Xdocumentation for any purpose and without fee is hereby granted, 
  1486. Xprovided that the above copyright notice appear in all copies and that
  1487. Xboth that copyright notice and this permission notice appear in 
  1488. Xsupporting documentation, and that the name of CMU not be
  1489. Xused in advertising or publicity pertaining to distribution of the
  1490. Xsoftware without specific, written prior permission.  
  1491. X
  1492. XCMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  1493. XALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  1494. XCMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  1495. XANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  1496. XWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  1497. XARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  1498. XSOFTWARE.
  1499. X******************************************************************/
  1500. X#ifdef KINETICS
  1501. X#include "gw.h"
  1502. X#endif
  1503. X
  1504. X#if (defined(unix) && !defined(KINETICS))
  1505. X#include <sys/types.h>
  1506. X#include <netinet/in.h>
  1507. X#endif
  1508. X
  1509. X#include "asn1.h"
  1510. X
  1511. X#ifndef NULL
  1512. X#define NULL    0
  1513. X#endif
  1514. X#define    ERROR(x)
  1515. X
  1516. X/*
  1517. X * asn_parse_int - pulls a long out of an ASN int type.
  1518. X *  On entry, datalength is input as the number of valid bytes following
  1519. X *   "data".  On exit, it is returned as the number of valid bytes
  1520. X *   following the end of this object.
  1521. X *
  1522. X *  Returns a pointer to the first byte past the end
  1523. X *   of this object (i.e. the start of the next object).
  1524. X *  Returns NULL on any error.
  1525. X */
  1526. Xu_char *
  1527. Xasn_parse_int(data, datalength, type, intp, intsize)
  1528. X    register u_char        *data;    /* IN - pointer to start of object */
  1529. X    register int        *datalength;/* IN/OUT - number of valid bytes left in buffer */
  1530. X    u_char            *type;    /* OUT - asn type of object */
  1531. X    long            *intp;    /* IN/OUT - pointer to start of output buffer */
  1532. X    int                intsize;    /* IN - size of output buffer */
  1533. X{
  1534. X/*
  1535. X * ASN.1 integer ::= 0x02 asnlength byte {byte}*
  1536. X */
  1537. X    register u_char *bufp = data;
  1538. X    u_long        asn_length;
  1539. X    register long   value = 0;
  1540. X
  1541. X    if (intsize != sizeof (long)){
  1542. X    ERROR("not long");
  1543. X    return NULL;
  1544. X    }
  1545. X    *type = *bufp++;
  1546. X    bufp = asn_parse_length(bufp, &asn_length);
  1547. X    if (bufp == NULL){
  1548. X    ERROR("bad length");
  1549. X    return NULL;
  1550. X    }
  1551. X    if (asn_length + (bufp - data) > *datalength){
  1552. X    ERROR("overflow of message");
  1553. X    return NULL;
  1554. X    }
  1555. X    if (asn_length > intsize){
  1556. X    ERROR("I don't support such large integers");
  1557. X    return NULL;
  1558. X    }
  1559. X    *datalength -= (int)asn_length + (bufp - data);
  1560. X    if (*bufp & 0x80)
  1561. X    value = -1; /* integer is negative */
  1562. X    while(asn_length--)
  1563. X    value = (value << 8) | *bufp++;
  1564. X    *intp = value;
  1565. X    return bufp;
  1566. X}
  1567. X
  1568. X
  1569. X/*
  1570. X * asn_build_int - builds an ASN object containing an integer.
  1571. X *  On entry, datalength is input as the number of valid bytes following
  1572. X *   "data".  On exit, it is returned as the number of valid bytes
  1573. X *   following the end of this object.
  1574. X *
  1575. X *  Returns a pointer to the first byte past the end
  1576. X *   of this object (i.e. the start of the next object).
  1577. X *  Returns NULL on any error.
  1578. X */
  1579. Xu_char *
  1580. Xasn_build_int(data, datalength, type, intp, intsize)
  1581. X    register u_char *data;    /* IN - pointer to start of output buffer */
  1582. X    register int    *datalength;/* IN/OUT - number of valid bytes left in buffer */
  1583. X    u_char        type;    /* IN - asn type of object */
  1584. X    register long   *intp;    /* IN - pointer to start of long integer */
  1585. X    register int    intsize;    /* IN - size of *intp */
  1586. X{
  1587. X/*
  1588. X * ASN.1 integer ::= 0x02 asnlength byte {byte}*
  1589. X */
  1590. X
  1591. X    register long integer;
  1592. X    register u_long mask;
  1593. X
  1594. X    if (intsize != sizeof (long))
  1595. X    return NULL;
  1596. X    integer = *intp;
  1597. X    /*
  1598. X     * Truncate "unnecessary" bytes off of the most significant end of this 2's complement integer.
  1599. X     * There should be no sequence of 9 consecutive 1's or 0's at the most significant end of the
  1600. X     * integer.
  1601. X     */
  1602. X    mask = 0x1FF << ((8 * (sizeof(long) - 1)) - 1);
  1603. X    /* mask is 0xFF800000 on a big-endian machine */
  1604. X    while((((integer & mask) == 0) || ((integer & mask) == mask)) && intsize > 1){
  1605. X    intsize--;
  1606. X    integer <<= 8;
  1607. X    }
  1608. X    data = asn_build_header(data, datalength, type, intsize);
  1609. X    if (data == NULL)
  1610. X    return NULL;
  1611. X    if (*datalength < intsize)
  1612. X    return NULL;
  1613. X    *datalength -= intsize;
  1614. X    mask = 0xFF << (8 * (sizeof(long) - 1));
  1615. X    /* mask is 0xFF000000 on a big-endian machine */
  1616. X    while(intsize--){
  1617. X    *data++ = (u_char)((integer & mask) >> (8 * (sizeof(long) - 1)));
  1618. X    integer <<= 8;
  1619. X    }
  1620. X    return data;
  1621. X}
  1622. X
  1623. X
  1624. X/*
  1625. X * asn_parse_string - pulls an octet string out of an ASN octet string type.
  1626. X *  On entry, datalength is input as the number of valid bytes following
  1627. X *   "data".  On exit, it is returned as the number of valid bytes
  1628. X *   following the beginning of the next object.
  1629. X *
  1630. X *  "string" is filled with the octet string.
  1631. X *
  1632. X *  Returns a pointer to the first byte past the end
  1633. X *   of this object (i.e. the start of the next object).
  1634. X *  Returns NULL on any error.
  1635. X */
  1636. Xu_char *
  1637. Xasn_parse_string(data, datalength, type, string, strlength)
  1638. X    u_char        *data;        /* IN - pointer to start of object */
  1639. X    register int    *datalength;    /* IN/OUT - number of valid bytes left in buffer */
  1640. X    u_char        *type;        /* OUT - asn type of object */
  1641. X    u_char        *string;        /* IN/OUT - pointer to start of output buffer */
  1642. X    register int    *strlength;     /* IN/OUT - size of output buffer */
  1643. X{
  1644. X/*
  1645. X * ASN.1 octet string ::= primstring | cmpdstring
  1646. X * primstring ::= 0x04 asnlength byte {byte}*
  1647. X * cmpdstring ::= 0x24 asnlength string {string}*
  1648. X * This doesn't yet support the compound string.
  1649. X */
  1650. X    register u_char *bufp = data;
  1651. X    u_long        asn_length;
  1652. X
  1653. X    *type = *bufp++;
  1654. X    bufp = asn_parse_length(bufp, &asn_length);
  1655. X    if (bufp == NULL)
  1656. X    return NULL;
  1657. X    if (asn_length + (bufp - data) > *datalength){
  1658. X    ERROR("overflow of message");
  1659. X    return NULL;
  1660. X    }
  1661. X    if (asn_length > *strlength){
  1662. X    ERROR("I don't support such long strings");
  1663. X    return NULL;
  1664. X    }
  1665. X    bcopy((char *)bufp, (char *)string, (int)asn_length);
  1666. X    *strlength = (int)asn_length;
  1667. X    *datalength -= (int)asn_length + (bufp - data);
  1668. X    return bufp + asn_length;
  1669. X}
  1670. X
  1671. X
  1672. X/*
  1673. X * asn_build_string - Builds an ASN octet string object containing the input string.
  1674. X *  On entry, datalength is input as the number of valid bytes following
  1675. X *   "data".  On exit, it is returned as the number of valid bytes
  1676. X *   following the beginning of the next object.
  1677. X *
  1678. X *  Returns a pointer to the first byte past the end
  1679. X *   of this object (i.e. the start of the next object).
  1680. X *  Returns NULL on any error.
  1681. X */
  1682. Xu_char *
  1683. Xasn_build_string(data, datalength, type, string, strlength)
  1684. X    u_char        *data;        /* IN - pointer to start of object */
  1685. X    register int    *datalength;    /* IN/OUT - number of valid bytes left in buffer */
  1686. X    u_char        type;        /* IN - ASN type of string */
  1687. X    u_char        *string;        /* IN - pointer to start of input buffer */
  1688. X    register int    strlength;        /* IN - size of input buffer */
  1689. X{
  1690. X/*
  1691. X * ASN.1 octet string ::= primstring | cmpdstring
  1692. X * primstring ::= 0x04 asnlength byte {byte}*
  1693. X * cmpdstring ::= 0x24 asnlength string {string}*
  1694. X * This code will never send a compound string.
  1695. X */
  1696. X    data = asn_build_header(data, datalength, type, strlength);
  1697. X    if (data == NULL)
  1698. X    return NULL;
  1699. X    if (*datalength < strlength)
  1700. X    return NULL;
  1701. X    bcopy((char *)string, (char *)data, strlength);
  1702. X    *datalength -= strlength;
  1703. X    return data + strlength;
  1704. X}
  1705. X
  1706. X
  1707. X/*
  1708. X * asn_parse_header - interprets the ID and length of the current object.
  1709. X *  On entry, datalength is input as the number of valid bytes following
  1710. X *   "data".  On exit, it is returned as the number of valid bytes
  1711. X *   in this object following the id and length.
  1712. X *
  1713. X *  Returns a pointer to the first byte of the contents of this object.
  1714. X *  Returns NULL on any error.
  1715. X */
  1716. Xu_char *
  1717. Xasn_parse_header(data, datalength, type)
  1718. X    u_char        *data;    /* IN - pointer to start of object */
  1719. X    int            *datalength;/* IN/OUT - number of valid bytes left in buffer */
  1720. X    u_char        *type;    /* OUT - ASN type of object */
  1721. X{
  1722. X    register u_char *bufp = data;
  1723. X    register        header_len;
  1724. X    u_long        asn_length;
  1725. X
  1726. X    /* this only works on data types < 30, i.e. no extension octets */
  1727. X    if (IS_EXTENSION_ID(*bufp)){
  1728. X    ERROR("can't process ID >= 30");
  1729. X    return NULL;
  1730. X    }
  1731. X    *type = *bufp;
  1732. X    bufp = asn_parse_length(bufp + 1, &asn_length);
  1733. X    if (bufp == NULL)
  1734. X    return NULL;
  1735. X    header_len = bufp - data;
  1736. X    if (header_len + asn_length > *datalength){
  1737. X    ERROR("asn length too long");
  1738. X    return NULL;
  1739. X    }
  1740. X    *datalength = (int)asn_length;
  1741. X    return bufp;
  1742. X}
  1743. X
  1744. X/*
  1745. X * asn_build_header - builds an ASN header for an object with the ID and
  1746. X * length specified.
  1747. X *  On entry, datalength is input as the number of valid bytes following
  1748. X *   "data".  On exit, it is returned as the number of valid bytes
  1749. X *   in this object following the id and length.
  1750. X *
  1751. X *  This only works on data types < 30, i.e. no extension octets.
  1752. X *  The maximum length is 0xFFFF;
  1753. X *
  1754. X *  Returns a pointer to the first byte of the contents of this object.
  1755. X *  Returns NULL on any error.
  1756. X */
  1757. Xu_char *
  1758. Xasn_build_header(data, datalength, type, length)
  1759. X    register u_char *data;    /* IN - pointer to start of object */
  1760. X    int            *datalength;/* IN/OUT - number of valid bytes left in buffer */
  1761. X    u_char        type;    /* IN - ASN type of object */
  1762. X    int            length;    /* IN - length of object */
  1763. X{
  1764. X    if (*datalength < 1)
  1765. X    return NULL;
  1766. X    *data++ = type;
  1767. X    (*datalength)--;
  1768. X    return asn_build_length(data, datalength, length);
  1769. X    
  1770. X}
  1771. X
  1772. X/*
  1773. X * asn_parse_length - interprets the length of the current object.
  1774. X *  On exit, length contains the value of this length field.
  1775. X *
  1776. X *  Returns a pointer to the first byte after this length
  1777. X *  field (aka: the start of the data field).
  1778. X *  Returns NULL on any error.
  1779. X */
  1780. Xu_char *
  1781. Xasn_parse_length(data, length)
  1782. X    u_char  *data;    /* IN - pointer to start of length field */
  1783. X    u_long  *length;    /* OUT - value of length field */
  1784. X{
  1785. X    register u_char lengthbyte = *data;
  1786. X
  1787. X    if (lengthbyte & ASN_LONG_LEN){
  1788. X    lengthbyte &= ~ASN_LONG_LEN;    /* turn MSb off */
  1789. X    if (lengthbyte == 0){
  1790. X        ERROR("We don't support indefinite lengths");
  1791. X        return NULL;
  1792. X    }
  1793. X    if (lengthbyte > sizeof(long)){
  1794. X        ERROR("we can't support data lengths that long");
  1795. X        return NULL;
  1796. X    }
  1797. X    bcopy((char *)data + 1, (char *)length, (int)lengthbyte);
  1798. X    *length = ntohl(*length);
  1799. X    *length >>= (8 * ((sizeof *length) - lengthbyte));
  1800. X    return data + lengthbyte + 1;
  1801. X    } else { /* short asnlength */
  1802. X    *length = (long)lengthbyte;
  1803. X    return data + 1;
  1804. X    }
  1805. X}
  1806. X
  1807. Xu_char *
  1808. Xasn_build_length(data, datalength, length)
  1809. X    register u_char *data;    /* IN - pointer to start of object */
  1810. X    int            *datalength;/* IN/OUT - number of valid bytes left in buffer */
  1811. X    register int    length;    /* IN - length of object */
  1812. X{
  1813. X    u_char    *start_data = data;
  1814. X
  1815. X    /* no indefinite lengths sent */
  1816. X    if (length < 0x80){
  1817. X    *data++ = (u_char)length;
  1818. X    } else if (length <= 0xFF){
  1819. X    *data++ = (u_char)(0x01 | ASN_LONG_LEN);
  1820. X    *data++ = (u_char)length;
  1821. X    } else { /* 0xFF < length <= 0xFFFF */
  1822. X    *data++ = (u_char)(0x02 | ASN_LONG_LEN);
  1823. X    *data++ = (u_char)((length >> 8) & 0xFF);
  1824. X    *data++ = (u_char)(length & 0xFF);
  1825. X    }
  1826. X    if (*datalength < (data - start_data)){
  1827. X    ERROR("build_length");
  1828. X    return NULL;
  1829. X    }
  1830. X    *datalength -= (data - start_data);
  1831. X    return data;
  1832. X
  1833. X}
  1834. X
  1835. X/*
  1836. X * asn_parse_objid - pulls an object indentifier out of an ASN object identifier type.
  1837. X *  On entry, datalength is input as the number of valid bytes following
  1838. X *   "data".  On exit, it is returned as the number of valid bytes
  1839. X *   following the beginning of the next object.
  1840. X *
  1841. X *  "objid" is filled with the object identifier.
  1842. X *
  1843. X *  Returns a pointer to the first byte past the end
  1844. X *   of this object (i.e. the start of the next object).
  1845. X *  Returns NULL on any error.
  1846. X */
  1847. Xu_char *
  1848. Xasn_parse_objid(data, datalength, type, objid, objidlength)
  1849. X    u_char        *data;        /* IN - pointer to start of object */
  1850. X    int            *datalength;    /* IN/OUT - number of valid bytes left in buffer */
  1851. X    u_char        *type;        /* OUT - ASN type of object */
  1852. X    oid            *objid;        /* IN/OUT - pointer to start of output buffer */
  1853. X    int            *objidlength;     /* IN/OUT - number of sub-id's in objid */
  1854. X{
  1855. X/*
  1856. X * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}*
  1857. X * subidentifier ::= {leadingbyte}* lastbyte
  1858. X * leadingbyte ::= 1 7bitvalue
  1859. X * lastbyte ::= 0 7bitvalue
  1860. X */
  1861. X    register u_char *bufp = data;
  1862. X    register oid *oidp = objid + 1;
  1863. X    register u_long subidentifier;
  1864. X    register long   length;
  1865. X    u_long        asn_length;
  1866. X
  1867. X    *type = *bufp++;
  1868. X    bufp = asn_parse_length(bufp, &asn_length);
  1869. X    if (bufp == NULL)
  1870. X    return NULL;
  1871. X    if (asn_length + (bufp - data) > *datalength){
  1872. X    ERROR("overflow of message");
  1873. X    return NULL;
  1874. X    }
  1875. X    *datalength -= (int)asn_length + (bufp - data);
  1876. X
  1877. X    length = asn_length;
  1878. X    (*objidlength)--;    /* account for expansion of first byte */
  1879. X    while (length > 0 && (*objidlength)-- > 0){
  1880. X    subidentifier = 0;
  1881. X    do {    /* shift and add in low order 7 bits */
  1882. X        subidentifier = (subidentifier << 7) + (*(u_char *)bufp & ~ASN_BIT8);
  1883. X        length--;
  1884. X    } while (*(u_char *)bufp++ & ASN_BIT8);    /* last byte has high bit clear */
  1885. X    if (subidentifier > (u_long)MAX_SUBID){
  1886. X        ERROR("subidentifier too long");
  1887. X        return NULL;
  1888. X    }
  1889. X    *oidp++ = (oid)subidentifier;
  1890. X    }
  1891. X
  1892. X    /*
  1893. X     * The first two subidentifiers are encoded into the first component
  1894. X     * with the value (X * 40) + Y, where:
  1895. X     *    X is the value of the first subidentifier.
  1896. X     *  Y is the value of the second subidentifier.
  1897. X     */
  1898. X    subidentifier = (u_long)objid[1];
  1899. X    objid[1] = (u_char)(subidentifier % 40);
  1900. X    objid[0] = (u_char)((subidentifier - objid[1]) / 40);
  1901. X
  1902. X    *objidlength = (int)(oidp - objid);
  1903. X    return bufp;
  1904. X}
  1905. X
  1906. X/*
  1907. X * asn_build_objid - Builds an ASN object identifier object containing the input string.
  1908. X *  On entry, datalength is input as the number of valid bytes following
  1909. X *   "data".  On exit, it is returned as the number of valid bytes
  1910. X *   following the beginning of the next object.
  1911. X *
  1912. X *  Returns a pointer to the first byte past the end
  1913. X *   of this object (i.e. the start of the next object).
  1914. X *  Returns NULL on any error.
  1915. X */
  1916. Xu_char *
  1917. Xasn_build_objid(data, datalength, type, objid, objidlength)
  1918. X    register u_char *data;        /* IN - pointer to start of object */
  1919. X    int            *datalength;    /* IN/OUT - number of valid bytes left in buffer */
  1920. X    u_char        type;        /* IN - ASN type of object */
  1921. X    oid            *objid;        /* IN - pointer to start of input buffer */
  1922. X    int            objidlength;    /* IN - number of sub-id's in objid */
  1923. X{
  1924. X/*
  1925. X * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}*
  1926. X * subidentifier ::= {leadingbyte}* lastbyte
  1927. X * leadingbyte ::= 1 7bitvalue
  1928. X * lastbyte ::= 0 7bitvalue
  1929. X */
  1930. X    u_char buf[MAX_OID_LEN];
  1931. X    u_char *bp = buf;
  1932. X    oid    objbuf[MAX_OID_LEN];
  1933. X    oid *op = objbuf;
  1934. X    register int    asnlength;
  1935. X    register u_long subid, mask, testmask;
  1936. X    register int bits, testbits;
  1937. X
  1938. X    bcopy((char *)objid, (char *)objbuf, objidlength * sizeof(oid));
  1939. X    /* transform size in bytes to size in subid's */
  1940. X    /* encode the first two components into the first subidentifier */
  1941. X    op[1] = op[1] + (op[0] * 40);
  1942. X    op++;
  1943. X    objidlength--;
  1944. X
  1945. X    while(objidlength-- > 0){
  1946. X    subid = *op++;
  1947. X    mask = 0x7F; /* handle subid == 0 case */
  1948. X    bits = 0;
  1949. X    /* testmask *MUST* !!!! be of an unsigned type */
  1950. X    for(testmask = 0x7F, testbits = 0; testmask != 0; testmask <<= 7, testbits += 7){
  1951. X        if (subid & testmask){    /* if any bits set */
  1952. X        mask = testmask;
  1953. X        bits = testbits;
  1954. X        }
  1955. X    }
  1956. X    /* mask can't be zero here */
  1957. X    for(;mask != 0x7F; mask >>= 7, bits -= 7){
  1958. X        if (mask == 0x1E00000)  /* fix a mask that got truncated above */
  1959. X        mask = 0xFE00000;
  1960. X        *bp++ = (u_char)(((subid & mask) >> bits) | ASN_BIT8);
  1961. X    }
  1962. X    *bp++ = (u_char)(subid & mask);
  1963. X    }
  1964. X    asnlength = bp - buf;
  1965. X    data = asn_build_header(data, datalength, type, asnlength);
  1966. X    if (data == NULL)
  1967. X    return NULL;
  1968. X    if (*datalength < asnlength)
  1969. X    return NULL;
  1970. X    bcopy((char *)buf, (char *)data, asnlength);
  1971. X    *datalength -= asnlength;
  1972. X    return data + asnlength;
  1973. X}
  1974. X
  1975. X/*
  1976. X * asn_parse_null - Interprets an ASN null type.
  1977. X *  On entry, datalength is input as the number of valid bytes following
  1978. X *   "data".  On exit, it is returned as the number of valid bytes
  1979. X *   following the beginning of the next object.
  1980. X *
  1981. X *  Returns a pointer to the first byte past the end
  1982. X *   of this object (i.e. the start of the next object).
  1983. X *  Returns NULL on any error.
  1984. X */
  1985. Xu_char *
  1986. Xasn_parse_null(data, datalength, type)
  1987. X    u_char        *data;        /* IN - pointer to start of object */
  1988. X    int            *datalength;    /* IN/OUT - number of valid bytes left in buffer */
  1989. X    u_char        *type;        /* OUT - ASN type of object */
  1990. X{
  1991. X/*
  1992. X * ASN.1 null ::= 0x05 0x00
  1993. X */
  1994. X    register u_char   *bufp = data;
  1995. X    u_long        asn_length;
  1996. X
  1997. X    *type = *bufp++;
  1998. X    bufp = asn_parse_length(bufp, &asn_length);
  1999. X    if (bufp == NULL)
  2000. X    return NULL;
  2001. X    if (asn_length != 0){
  2002. X    ERROR("Malformed NULL");
  2003. X    return NULL;
  2004. X    }
  2005. X    *datalength -= (bufp - data);
  2006. X    return bufp + asn_length;
  2007. X}
  2008. X
  2009. X
  2010. X/*
  2011. X * asn_build_null - Builds an ASN null object.
  2012. X *  On entry, datalength is input as the number of valid bytes following
  2013. X *   "data".  On exit, it is returned as the number of valid bytes
  2014. X *   following the beginning of the next object.
  2015. X *
  2016. X *  Returns a pointer to the first byte past the end
  2017. X *   of this object (i.e. the start of the next object).
  2018. X *  Returns NULL on any error.
  2019. X */
  2020. Xu_char *
  2021. Xasn_build_null(data, datalength, type)
  2022. X    u_char        *data;        /* IN - pointer to start of object */
  2023. X    int            *datalength;    /* IN/OUT - number of valid bytes left in buffer */
  2024. X    u_char        type;        /* IN - ASN type of object */
  2025. X{
  2026. X/*
  2027. X * ASN.1 null ::= 0x05 0x00
  2028. X */
  2029. X    return asn_build_header(data, datalength, type, 0);
  2030. X}
  2031. X
  2032. END_OF_FILE
  2033.   if test 18366 -ne `wc -c <'nocol-3.0/src/cmu-snmp/snmplib/asn1.c.cmu'`; then
  2034.     echo shar: \"'nocol-3.0/src/cmu-snmp/snmplib/asn1.c.cmu'\" unpacked with wrong size!
  2035.   fi
  2036.   # end of 'nocol-3.0/src/cmu-snmp/snmplib/asn1.c.cmu'
  2037. fi
  2038. if test -f 'nocol-3.0/src/support/mping/m.dat' -a "${1}" != "-c" ; then 
  2039.   echo shar: Will not clobber existing file \"'nocol-3.0/src/support/mping/m.dat'\"
  2040. else
  2041.   echo shar: Extracting \"'nocol-3.0/src/support/mping/m.dat'\" \(1541 characters\)
  2042.   sed "s/^X//" >'nocol-3.0/src/support/mping/m.dat' <<'END_OF_FILE'
  2043. X#
  2044. X# Format:
  2045. X#
  2046. X# name    address    size[56],pattern[0],numToGet[1],retry[5],timeout[1000 m-sec]
  2047. X#
  2048. X#
  2049. X#  size [default: 56]:        Decimal number giving the size of the ICMP
  2050. X#                data portion of the packet.  The actual IP
  2051. X#                packet will be at least 8 octets larger.
  2052. X#
  2053. X# pattern [default: 0x0]:    A hex number specifying a byte value to
  2054. X#                initialize the ICMP data portion of the
  2055. X#                packet.
  2056. X#
  2057. X# numToGet [default: 1]:    Number of return packets to require.
  2058. X#
  2059. X# retry [default: 5]:        Number of retries to make before declaring
  2060. X#                a packet lost.  Note that if <numToGet> is
  2061. X#                greater than 1, the retry limit applies to
  2062. X#                each attempt.  That is if the first attempt
  2063. X#                requires 4 tries before a successful return,
  2064. X#                then next attempt will still make up to 5
  2065. X#                tries.
  2066. X#
  2067. X# timeout [default: 1000]    Number of milliseconds to wait before
  2068. X#                assuming packet lost and retrying.  The
  2069. X#                default timeout is fine within an all
  2070. X#                ethernet environment, but you need a longer
  2071. X#                one for WAN links.
  2072. X
  2073. X#
  2074. X# systems upstairs and on the 21 subnet
  2075. X# (no router, no bridge)
  2076. X#
  2077. Xcupid        130.132.21.192    128,0,2
  2078. X
  2079. Xyalevm        130.132.1.4    128,0,2
  2080. Xvenus        130.132.1.5    128,0,2
  2081. X
  2082. Xenvy        130.132.1.19    128,0,2
  2083. Xcommons1-gw    130.132.1.29    128,0,2
  2084. Xcommons2-gw    130.132.1.49    128,0,2
  2085. Xcommons3-gw    130.132.1.53    128,0,2
  2086. Xcommons4-gw    130.132.1.50    128,0,2
  2087. Xcommons5-gw    130.132.1.51    128,0,2
  2088. Xcommons6-gw    130.132.1.52    128,0,2
  2089. Xcommons7-gw    130.132.1.75    128,0,2
  2090. Xcommons8-gw    130.132.1.76    128,0,2
  2091. Xcommons9-gw    130.132.1.77    128,0,2
  2092. Xcommons10-gw    130.132.1.78    128,0,2
  2093. X
  2094. Xfoo.bar        130.132.1.199    128,0,2
  2095. END_OF_FILE
  2096.   if test 1541 -ne `wc -c <'nocol-3.0/src/support/mping/m.dat'`; then
  2097.     echo shar: \"'nocol-3.0/src/support/mping/m.dat'\" unpacked with wrong size!
  2098.   fi
  2099.   # end of 'nocol-3.0/src/support/mping/m.dat'
  2100. fi
  2101. if test -f 'nocol-3.0/src/trapmon/trapmon.c' -a "${1}" != "-c" ; then 
  2102.   echo shar: Will not clobber existing file \"'nocol-3.0/src/trapmon/trapmon.c'\"
  2103. else
  2104.   echo shar: Extracting \"'nocol-3.0/src/trapmon/trapmon.c'\" \(15708 characters\)
  2105.   sed "s/^X//" >'nocol-3.0/src/trapmon/trapmon.c' <<'END_OF_FILE'
  2106. X/* $Header: /home/aggarwal/lsrc/nocol/src/trapmon/RCS/trapmon.c,v 2.3 1993/11/04 07:39:22 aggarwal Exp $ */
  2107. X
  2108. X/*
  2109. X** DESCRIPTION
  2110. X**    Listens for SNMP traps asynchronously and outputs information about
  2111. X**    received traps in several possible formats.
  2112. X**
  2113. X**    For output to netmon, maintains a datafile with one EVENT per trap.
  2114. X**    Appends new EVENTs to the end of the file.  Deletes EVENTs that are
  2115. X**    more than 30 minutes old (by having two pointers running through the
  2116. X**    file).
  2117. X**
  2118. X** Also see the DISCLAIMER file for important information.
  2119. X*/
  2120. X
  2121. X/*
  2122. X** AUTHOR
  2123. X**    David Wagner, wagner@jvnc.net, June 9 1992
  2124. X**    I changed the snmptrapd program from Carnegie Mellon University
  2125. X**    See their disclaimer attached below
  2126. X*/
  2127. X
  2128. X/*
  2129. X *
  2130. X * $Log: trapmon.c,v $
  2131. X * Revision 2.3  1993/11/04  07:39:22  aggarwal
  2132. X * Now shows type only for enterprise specific and also dumps
  2133. X * out the contents of the trap packets.
  2134. X *
  2135. X * Revision 2.2  1993/10/30  03:31:13  aggarwal
  2136. X * Tried to add the pdu->specific_type to the trapname.
  2137. X *
  2138. X * Revision 2.1  1993/09/21  19:50:27  aggarwal
  2139. X * Added NOCOL logging.
  2140. X *
  2141. X * Revision 2.0  1992/06/18  21:24:17  aggarwal
  2142. X * Had to send a pointer to the EVENT structure
  2143. X *
  2144. X * Revision 1.9  1992/06/12  00:51:12  aggarwal
  2145. X * Added enterprise specific trap identifier in the trap description.
  2146. X *
  2147. X * Revision 1.8  1992/06/11  07:21:14  aggarwal
  2148. X * Added 'usage' function.
  2149. X *
  2150. X * Revision 1.7  1992/06/11  06:44:51  aggarwal
  2151. X * Modified for the new t_desc structure.
  2152. X *
  2153. X * Revision 1.6  1992/06/10  21:27:47  wagner
  2154. X * Fixed the address and name fields of the event structure so that they
  2155. X * behave as expected now.
  2156. X *
  2157. X * Revision 1.1  1992/06/10  14:23:16  wagner
  2158. X * Initial revision
  2159. X *
  2160. X */
  2161. X
  2162. X/*
  2163. X * snmptrapd.c - receive and log snmp traps
  2164. X *
  2165. X */
  2166. X/***********************************************************
  2167. X    Copyright 1989 by Carnegie Mellon University
  2168. X
  2169. X                      All Rights Reserved
  2170. X
  2171. XPermission to use, copy, modify, and distribute this software and its 
  2172. Xdocumentation for any purpose and without fee is hereby granted, 
  2173. Xprovided that the above copyright notice appear in all copies and that
  2174. Xboth that copyright notice and this permission notice appear in 
  2175. Xsupporting documentation, and that the name of CMU not be
  2176. Xused in advertising or publicity pertaining to distribution of the
  2177. Xsoftware without specific, written prior permission.  
  2178. X
  2179. XCMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  2180. XALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  2181. XCMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  2182. XANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  2183. XWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  2184. XARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  2185. XSOFTWARE.
  2186. X******************************************************************/
  2187. X
  2188. X/*   */
  2189. X
  2190. X#ifndef lint
  2191. X static char rcsid[] = "$RCSfile: trapmon.c,v $ $Revision: 2.3 $ $Date: 1993/11/04 07:39:22 $" ;
  2192. X#endif
  2193. X
  2194. X#include "trapmon.h"
  2195. X
  2196. Xchar *
  2197. Xuptime_string(timeticks, buf)
  2198. X    register u_long timeticks;
  2199. X    char *buf;
  2200. X{
  2201. X    int    seconds, minutes, hours, days;
  2202. X
  2203. X    timeticks /= 100;
  2204. X    days = timeticks / (60 * 60 * 24);
  2205. X    timeticks %= (60 * 60 * 24);
  2206. X
  2207. X    hours = timeticks / (60 * 60);
  2208. X    timeticks %= (60 * 60);
  2209. X
  2210. X    minutes = timeticks / 60;
  2211. X    seconds = timeticks % 60;
  2212. X
  2213. X    if (days == 0)
  2214. X    sprintf(buf, "%d:%02d:%02d", hours, minutes, seconds);
  2215. X    else if (days == 1)
  2216. X    sprintf(buf, "%d day, %d:%02d:%02d", days, hours, minutes, seconds);
  2217. X    else
  2218. X    sprintf(buf, "%d days, %d:%02d:%02d", days, hours, minutes, seconds);
  2219. X
  2220. X    return buf;
  2221. X}
  2222. X
  2223. X/*
  2224. X * Appends a new event to the end of the datafile. For an enterprise specific
  2225. X * trap, it adds the 'specific_type' of the trap for identification.
  2226. X */
  2227. Xadd_event(addr, name, pdu)
  2228. X    char *addr;                    /* Address of trap sender */
  2229. X    char *name;                    /* Name of trap sender */
  2230. X    struct snmp_pdu *pdu;            /* trap PDU */
  2231. X{
  2232. X    int fd;
  2233. X    int trap = pdu->trap_type;            /* Trap number */
  2234. X    struct tm *tm;
  2235. X    time_t clock;
  2236. X    EVENT v;
  2237. X
  2238. X    bzero((char *)&v, sizeof(v));
  2239. X
  2240. X    /*
  2241. X     * In the following 'strncpy's, the null character at the end is
  2242. X     * auto appended since to the bzero of the event struct and also
  2243. X     * because we are doing a copy for 1 less than the size of the storage
  2244. X     */
  2245. X    strncpy(v.sender, progname, sizeof(v.sender) - 1);    /* Set sender */
  2246. X    strncpy(v.site.addr, addr, sizeof(v.site.addr) -1);    /* From address */
  2247. X    strncpy(v.site.name, name, sizeof(v.site.name) -1);
  2248. X
  2249. X    strncpy(v.var.name, trap_desc[trap].tname, sizeof(v.var.name) -1);
  2250. X    if (trap == SNMP_TRAP_ENTERPRISESPECIFIC)    /* specific type */
  2251. X    { 
  2252. X    static char spdutype[16] ;        /* convert int to string */
  2253. X    sprintf (spdutype, "/%d\0", pdu->specific_type) ;
  2254. X    if ( (sizeof(v.var.name) - strlen(v.var.name)) > 5)
  2255. X      strncpy (v.var.name + strlen(v.var.name), spdutype, 4) ;
  2256. X    else
  2257. X      strncpy (v.var.name + sizeof(v.var.name) - 5, spdutype, 4) ;
  2258. X    }
  2259. X
  2260. X    v.var.value = 0;                /* No value field */
  2261. X    v.var.threshold = 0;            /* No threshold field */
  2262. X    v.var.units[0] = '\0';            /* No units field */
  2263. X
  2264. X    v.severity = trap_desc[trap].tseverity;    /* Set the severity level */
  2265. X    v.nocop = SETF_UPDOUN (v.nocop, trap_desc[trap].nocop);
  2266. X    v.loglevel = trap_desc[trap].loglevel ;    /* logging level */
  2267. X
  2268. X    clock = time(NULL);                /* Get the time of day... */
  2269. X    tm = localtime(&clock);
  2270. X    v.mon = tm->tm_mon + 1;            /* Don't forget to add 1! */
  2271. X    v.day = tm->tm_mday;            /* Straightforward... */
  2272. X    v.hour = tm->tm_hour;
  2273. X    v.min = tm->tm_min;
  2274. X
  2275. X    eventlog(&v);                /* Log the event */
  2276. X
  2277. X    fd = open(datafname, O_WRONLY | O_APPEND);    /* Add the new EVENT */
  2278. X    if (write(fd, &v, sizeof(v)) != sizeof(v)) {
  2279. X    fprintf(stderr, "write() failed on %s\n", datafname);
  2280. X    perror("addevent()");
  2281. X
  2282. X    closeeventlog();
  2283. X    exit(1);
  2284. X    }
  2285. X    close(fd);
  2286. X
  2287. X    /* Store the time after which the trap event is to be deleted */
  2288. X    die_at[numtraps++] = clock + TIME_TO_LIVE;    /* When to be reaped... */
  2289. X
  2290. X    if (options & O_DEBUG)
  2291. X    printf("Added: sendr=%s sitenm=%s siteaddr=%s varnm=%s severity=%d mon=%d day=%d hr=%d min=%d die_at=%d\n",
  2292. X        v.sender, name, addr, v.var.name, v.severity, v.mon, v.day,
  2293. X        v.hour, v.min, die_at[numtraps - 1]);
  2294. X}
  2295. X
  2296. X
  2297. Xint process_trap(op, session, reqid, pdu, magic)
  2298. X    int op;
  2299. X    struct snmp_session *session;
  2300. X    int reqid;
  2301. X    struct snmp_pdu *pdu;
  2302. X    void *magic;
  2303. X{
  2304. X    char varbuf[512] ;                /* For variable_list */
  2305. X    char buf[64];                /* For uptime_string() */
  2306. X    struct hostent *he;                /* For gethostbyaddr() */
  2307. X    char *dotted;                /* For inet_ntoa() */
  2308. X    char *nameptr;                /* Name of trap sender */
  2309. X
  2310. X    varbuf[0] = '\0';
  2311. X    if (options & O_DEBUG)
  2312. X    printf("Entered process_trap...\n");
  2313. X
  2314. X    if (op == RECEIVED_MESSAGE && pdu->command == TRP_REQ_MSG){
  2315. X    he = gethostbyaddr(&(pdu->agent_addr.sin_addr),
  2316. X        sizeof(unsigned long), AF_INET);
  2317. X    if (he == NULL)
  2318. X        nameptr = "Unknown";        /* Error getting host name */
  2319. X    else
  2320. X        nameptr = he->h_name;        /* Name of trap sender */
  2321. X    dotted = inet_ntoa(pdu->agent_addr.sin_addr);/* Addr of sender */
  2322. X
  2323. X    if (options & O_PRINT)            /* Log to stderr */
  2324. X        fprintf(stderr, "%s [%s]: %s Trap (%d) Uptime: %s %s\n",
  2325. X        dotted,
  2326. X        nameptr,
  2327. X        trap_desc[pdu->trap_type].tname,
  2328. X        pdu->specific_type,
  2329. X        uptime_string(pdu->time, buf),
  2330. X        trap_desc[pdu->trap_type].tseverity_str);
  2331. X
  2332. X    if (options & O_DEBUG)
  2333. X    {
  2334. X        struct variable_list *vars;
  2335. X        char * pc = varbuf ;
  2336. X
  2337. X            for(vars = pdu->variables; vars ; vars = vars->next_variable)
  2338. X          switch (vars->type)
  2339. X          {
  2340. X          int c ;
  2341. X           case ASN_INTEGER:
  2342. X          sprintf (pc, "%d \0", *(vars->val.integer)) ;
  2343. X          pc += strlen(pc) ;
  2344. X          break ;
  2345. X               case ASN_OCTET_STR:
  2346. X          for (c = 0 ; c < vars->val_len ; ++c)
  2347. X            *pc++ = *(vars->val.string + c) ;
  2348. X          *pc++ = ' ';
  2349. X          break ;
  2350. X           default:
  2351. X          sprintf (pc, "(Unprintable type %d) \0", vars->type) ;
  2352. X          pc += strlen(pc) ;
  2353. X          break ;
  2354. X          }
  2355. X        sprintf (pc, "\n\0") ;
  2356. X        printf ("%s", varbuf);
  2357. X    }
  2358. X
  2359. X    if (options & O_LOG)            /* Log to syslog() */
  2360. X        syslog(LOG_WARNING, "%s [%s]: %s Trap (%d) Uptime: %s %s (%s)\n",
  2361. X        dotted,
  2362. X        nameptr,
  2363. X        trap_desc[pdu->trap_type].tname,
  2364. X        pdu->specific_type,
  2365. X        uptime_string(pdu->time, buf),
  2366. X        trap_desc[pdu->trap_type].tseverity_str,
  2367. X            varbuf);
  2368. X
  2369. X    if (options & O_NETMON)            /* Log EVENTs */
  2370. X        add_event(dotted,
  2371. X        nameptr,
  2372. X        pdu);
  2373. X    } else if (op == TIMED_OUT) {        /* Not a trap! */
  2374. X    fprintf(stderr, "Timeout: This shouldn't happen!\n");
  2375. X    if (options & O_LOG)
  2376. X        syslog(LOG_WARNING, "Timeout: This shouldn't happen!\n");
  2377. X    } /* end of if */
  2378. X
  2379. X    if (options & O_DEBUG) {
  2380. X    printf("Done with process_trap.\n");
  2381. X    fflush(stdout);
  2382. X    }
  2383. X}
  2384. X
  2385. X
  2386. X/*+
  2387. X** Strategy: I open the datafile twice, once read-only, and once write-only.
  2388. X** Now I have two (independent) seek pointers for the single file.
  2389. X** They then roam down the file, with the read pointer ahead of the
  2390. X** write pointer.  Normally, the cycle is this:
  2391. X**    (1) Read an EVENT with the read-only pointer, and advance it
  2392. X**    (2) Write that EVENT with the write-only pointer, and advance it
  2393. X** If, when reading an EVENT, we discover it needs to be reaped, then step (2)
  2394. X** is not performed, i.e. only the read-pointer advances (and the write-pointer
  2395. X** remains at the same location).
  2396. X** There is one more detail, though.  After the whole file has been read and
  2397. X** all the timed-out EVENTs have been reaped, the file must be truncated:
  2398. X** it must be shortened by an amount proportional to the number of EVENTs
  2399. X** reaped.
  2400. X**
  2401. X** The general loop, then, is this:
  2402. X**    (1) Read an EVENT and advance the read-pointer.
  2403. X**    (2) If this EVENT must be reaped, go to step 4.
  2404. X**    (3) Otherwise, write the EVENT and advance the write-pointer.
  2405. X**    (4) If end-of-file not reached yet, go back to 1.
  2406. X**    (5) Truncate the file.
  2407. X*/
  2408. Xint reap_events(fname)
  2409. X    char *fname;                /* Name of EVENT file */
  2410. X{
  2411. X    int rd;                    /* Read-only pointer */
  2412. X    int wr;                    /* Write-only pointer */
  2413. X    int i;                    /* Read index into die_at[] */
  2414. X    int j;                    /* Write index into die_at[] */
  2415. X    EVENT v;                    /* EVENT buffer */
  2416. X    time_t death_date;                /* die_at[] buffer */
  2417. X    time_t clock;                /* Current time */
  2418. X
  2419. X    i = j = 0;
  2420. X    clock = time(NULL);                /* Get the current time */
  2421. X    if ((rd = open(fname, O_RDONLY)) < 0)    /* Init read pointer */
  2422. X    {
  2423. X    fprintf(stderr, "%s (reap_events): %s ", progname, fname) ;
  2424. X    perror ("read open");
  2425. X    if (options & O_LOG)
  2426. X      syslog(LOG_WARNING, "(reap_events) Couldn't ropen datafile %s\n",
  2427. X         fname);
  2428. X
  2429. X    closeeventlog();
  2430. X    return (-1);
  2431. X    }
  2432. X    /* Init write pointer */
  2433. X    if ((wr = open(fname, O_WRONLY, DATAFILE_MODE)) < 0)
  2434. X    {
  2435. X    fprintf(stderr, "%s (reap_events): %s ", progname, fname) ;
  2436. X    perror ("write open");
  2437. X    if (options & O_LOG)
  2438. X      syslog(LOG_WARNING, "(reap_events) Couldn't wopen datafile %s\n",
  2439. X         fname);
  2440. X
  2441. X    closeeventlog();
  2442. X    return (-1);
  2443. X    }    
  2444. X
  2445. X    if (options & O_DEBUG)
  2446. X    printf("Entered reap_events() numtraps=%d clock=%d... ",
  2447. X        numtraps, clock);
  2448. X
  2449. X    while (read(rd, &v, sizeof(v)) == sizeof(v))/* Read EVENTs one by one */
  2450. X    if ((death_date = die_at[i++]) > clock) {    /* Reap this EVENT? */
  2451. X        write(wr, &v, sizeof(v));        /* No - keep this EVENT */
  2452. X        die_at[j++] = death_date;
  2453. X        if (options & O_DEBUG)
  2454. X        printf("kept, ");
  2455. X    }
  2456. X    else if (options & O_DEBUG)        /* Yes - reap this EVENT */
  2457. X        printf("reaped, ");
  2458. X
  2459. X    numtraps = j;
  2460. X    ftruncate(wr, (off_t) j * sizeof(EVENT));    /* Shorten the file */
  2461. X
  2462. X    if (options & O_DEBUG)
  2463. X    printf("truncated, ");
  2464. X
  2465. X    close(rd);                    /* Done with read pointer */
  2466. X    close(wr);                    /* Done with write pointer */
  2467. X
  2468. X    if (options & O_DEBUG) {
  2469. X    printf("Done.\n");
  2470. X    fflush(stdout);
  2471. X    }
  2472. X}
  2473. X
  2474. Xusage()
  2475. X{
  2476. X    fprintf(stderr,
  2477. X        "Usage: %s [-v (verbose)] [-p (errors on stderr)] ",
  2478. X        progname);
  2479. X    fprintf(stderr, "[-l (syslog output)] [-n (nocol output)]\n");
  2480. X}
  2481. X
  2482. X
  2483. Xmain(argc, argv)
  2484. X    int        argc;
  2485. X    char    *argv[];
  2486. X{
  2487. X    struct snmp_session session, *ss;
  2488. X    int    arg;
  2489. X    int ch;
  2490. X    int count, numfds, block;
  2491. X    fd_set fdset;
  2492. X    struct timeval timeout;
  2493. X
  2494. X    options = 0;                /* Default: no logging */
  2495. X    if ((progname = strrchr(argv[0], '/')) == NULL) /* Get the basename.. */
  2496. X    progname = argv[0];            /* ..not the full path */
  2497. X    else
  2498. X    progname++;
  2499. X
  2500. X    /* Make filename for EVENT file */
  2501. X    strcpy(datafname, DATADIR);
  2502. X    strcat(datafname, "/");
  2503. X    strcat(datafname, progname);
  2504. X    strcat(datafname, OUTPUT_EXTENSION);
  2505. X
  2506. X    while ((ch = getopt(argc, argv, "plnv")) != EOF)
  2507. X    switch(ch) {
  2508. X        case 'p':                /* Print to stderr */
  2509. X        options |= O_PRINT; break;
  2510. X        case 'l':                /* Log to syslog() */
  2511. X        options |= O_LOG; break;
  2512. X        case 'n':                /* Create EVENTs for netmon */
  2513. X        options |= O_NETMON; break;
  2514. X        case 'd':                /* Print debugging output */
  2515. X        case 'v':                /* Print debugging output */
  2516. X        options |= O_DEBUG; break;
  2517. X        case '?':                /* Unrecognized switch */
  2518. X        default:
  2519. X        usage() ;
  2520. X        exit (1);
  2521. X    } /* end of switch and while */
  2522. X
  2523. X    if ((options & ~O_DEBUG) == 0) {        /* Gotta do something! */
  2524. X    fprintf (stderr, "Reporting type not specified.\n");
  2525. X    usage() ;
  2526. X    exit (1);
  2527. X    }
  2528. X
  2529. X    if (options & O_LOG)            /* Start up syslog() */
  2530. X    init_syslog();
  2531. X
  2532. X    if (options & O_NETMON) {            /* Make an empty EVENT file */
  2533. X    int fd;
  2534. X
  2535. X    if (options & O_DEBUG) 
  2536. X    {
  2537. X        fprintf(stderr, 
  2538. X            "progname set to %s, datafname to %s.\n", 
  2539. X            progname, datafname);
  2540. X        fflush(stderr);
  2541. X    }
  2542. X
  2543. X    unlink(datafname);
  2544. X    fd = open(datafname, O_WRONLY | O_CREAT, DATAFILE_MODE);
  2545. X    if (fd < 0) {
  2546. X        closeeventlog();
  2547. X
  2548. X        fprintf(stderr, "open() failed on %s\n", datafname);
  2549. X        perror(progname);
  2550. X        exit(1);
  2551. X    }
  2552. X    close(fd);
  2553. X    openeventlog();            /* Logging daemon */
  2554. X    }    /* if nocol logging */
  2555. X
  2556. X    if (options & O_DEBUG)
  2557. X    printf("options set to %d.\n", options);
  2558. X
  2559. X    bzero((char *)&session, sizeof(struct snmp_session));
  2560. X    session.peername = NULL;
  2561. X    session.community = NULL;
  2562. X    session.community_len = 0;
  2563. X    session.retries = SNMP_DEFAULT_RETRIES;
  2564. X    session.timeout = SNMP_DEFAULT_TIMEOUT;
  2565. X    session.authenticator = NULL;
  2566. X    session.callback = process_trap;        /* Defined above... */
  2567. X    session.callback_magic = NULL;
  2568. X    session.local_port = SNMP_TRAP_PORT;
  2569. X    ss = snmp_open(&session);
  2570. X    if (ss == NULL) {                /* Couldn't do snmp_open() */
  2571. X    fprintf(stderr, "Couldn't open snmp session.\n");
  2572. X    if (options & O_LOG)            /* Tell syslog() */
  2573. X      syslog(LOG_WARNING, "Couldn't open snmp session.\n");
  2574. X
  2575. X    if (options & O_NETMON)
  2576. X      closeeventlog();
  2577. X    exit (1);
  2578. X    }
  2579. X
  2580. X    if (options & O_DEBUG)
  2581. X    printf("SNMP session opened successfully.\n");
  2582. X
  2583. X    while (1) {                    /* Main event-driven loop */
  2584. X    if (options & O_NETMON)
  2585. X        reap_events(datafname);        /* Delete timed-out EVENTs */
  2586. X    numfds = 0;                /* Reset the list of file.. */
  2587. X    FD_ZERO(&fdset);            /* ..descriptors */
  2588. X    block = 0;                /* Don't block */
  2589. X    timeout.tv_sec = (long) SELECT_TIMEOUT;    /* Only select() for a while */
  2590. X    timeout.tv_usec = (long) 0;
  2591. X    snmp_select_info(&numfds, &fdset, &timeout, &block);
  2592. X
  2593. X    if (options & O_DEBUG)
  2594. X        fprintf(stderr, "snmp_select_info()... ");
  2595. X
  2596. X    count = select(numfds, &fdset, 0, 0, &timeout);
  2597. X
  2598. X    if (options & O_DEBUG)
  2599. X        fprintf(stderr, "select() == %d... ", count);
  2600. X
  2601. X    if (count > 0)
  2602. X        snmp_read(&fdset);
  2603. X    else if (count == 0)
  2604. X        snmp_timeout();
  2605. X    else if (errno != EINTR) {
  2606. X        perror("select");
  2607. X        if (options & O_LOG)
  2608. X        syslog(LOG_WARNING, "fatal select() error\n");
  2609. X
  2610. X        closeeventlog();
  2611. X        exit (1);
  2612. X    } /* end of if */
  2613. X
  2614. X    if (options & O_DEBUG) {
  2615. X        fprintf(stderr, "Ok.\n");
  2616. X        fflush(stdout);
  2617. X    }
  2618. X    } /* end of while */
  2619. X
  2620. X  /* NOTREACHED */
  2621. X}
  2622. X
  2623. X/*
  2624. X * All messages will be logged to the local0 facility and will be sent to
  2625. X * the console if syslog doesn't work.
  2626. X */
  2627. Xinit_syslog()
  2628. X{
  2629. X    openlog("trapmon", LOG_CONS, LOG_LOCAL0);
  2630. X    syslog(LOG_INFO, "Starting trapmon\n");
  2631. X}
  2632. END_OF_FILE
  2633.   if test 15708 -ne `wc -c <'nocol-3.0/src/trapmon/trapmon.c'`; then
  2634.     echo shar: \"'nocol-3.0/src/trapmon/trapmon.c'\" unpacked with wrong size!
  2635.   fi
  2636.   # end of 'nocol-3.0/src/trapmon/trapmon.c'
  2637. fi
  2638. echo shar: End of archive 15 \(of 26\).
  2639. cp /dev/null ark15isdone
  2640. MISSING=""
  2641. 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
  2642.     if test ! -f ark${I}isdone ; then
  2643.     MISSING="${MISSING} ${I}"
  2644.     fi
  2645. done
  2646. if test "${MISSING}" = "" ; then
  2647.     echo You have unpacked all 26 archives.
  2648.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2649. else
  2650.     echo You still must unpack the following archives:
  2651.     echo "        " ${MISSING}
  2652. fi
  2653. exit 0
  2654. exit 0 # Just in case...
  2655.