tools.c
上传用户:cxs890
上传日期:2021-05-22
资源大小:347k
文件大小:12k
源码类别:

SNMP编程

开发平台:

C/C++

  1. /*
  2.  * tools.c
  3.  */
  4. #include <config.h>
  5. #include <ctype.h>
  6. #include <stdio.h>
  7. #include <sys/types.h>
  8. #if TIME_WITH_SYS_TIME
  9. # ifdef WIN32
  10. #  include <sys/timeb.h>
  11. # else
  12. #  include <time.h>
  13. # endif
  14. # include <time.h>
  15. #else
  16. # if HAVE_SYS_TIME_H
  17. #  include <sys/time.h> 
  18. # else
  19. #  include <time.h>
  20. # endif
  21. #endif
  22. #ifdef HAVE_SYS_SOCKET_H
  23. #include <sys/socket.h>
  24. #endif
  25. #if HAVE_WINSOCK_H
  26. #include <ip/socket.h>
  27. #endif
  28. #ifdef HAVE_STDLIB_H
  29. #include <stdlib.h>
  30. #endif
  31. #if HAVE_STRING_H
  32. #include <string.h>
  33. #else
  34. #include <strings.h>
  35. #endif
  36. #ifdef HAVE_NETINET_IN_H
  37. #include <netinet/in.h>
  38. #endif
  39. #ifdef HAVE_ARPA_INET_H
  40. #include <arpa/inet.h>
  41. #endif
  42. #if HAVE_DMALLOC_H
  43. #include <dmalloc.h>
  44. #endif
  45. #include "asn1.h" 
  46. #include "system.h"
  47. #include "snmp_api.h"
  48. #include "tools.h"
  49. #include "snmp_debug.h"
  50. #include "mib.h"
  51. #include "scapi.h" 
  52. #define timercmp(tvp, uvp, cmp) 
  53.         ((tvp)->tv_sec cmp (uvp)->tv_sec || 
  54.         ( (tvp)->tv_sec == (uvp)->tv_sec && (tvp)->tv_usec cmp (uvp)->tv_usec))
  55. /*******************************************************************-o-******
  56.  * free_zero
  57.  *
  58.  * Parameters:
  59.  * *buf Pointer at bytes to free.
  60.  * size Number of bytes in buf.
  61.  */
  62. void
  63. free_zero(void *buf, size_t size)
  64. {
  65. if (buf) {
  66. memset(buf, 0, size);
  67. free(buf);
  68. }
  69. }  /* end free_zero() */
  70. /*******************************************************************-o-******
  71.  * malloc_random
  72.  *
  73.  * Parameters:
  74.  * size Number of bytes to malloc() and fill with random bytes.
  75.  *      
  76.  * Returns pointer to allocaed & set buffer on success, size contains
  77.  * number of random bytes filled.
  78.  *
  79.  * buf is NULL and *size set to KMT error value upon failure.
  80.  *
  81.  */
  82. u_char *
  83. malloc_random(size_t *size)
  84. {
  85. int  rval = SNMPERR_SUCCESS;
  86. u_char *buf = (u_char *)calloc (1, *size);
  87. if (buf) {
  88. rval = sc_random(buf, size);
  89. if (rval < 0) {
  90. free_zero(buf, *size);
  91. buf = NULL;
  92. } else {
  93. *size = rval;
  94. }
  95. }
  96. return buf;
  97. }  /* end malloc_random() */
  98. #if 0
  99. /*******************************************************************-o-******
  100.  * memdup
  101.  *
  102.  * Parameters:
  103.  * to       Pointer to allocate and copy memory to.
  104.  *      from     Pointer to copy memory from.
  105.  *      size     Size of the data to be copied.
  106.  *      
  107.  * Returns
  108.  * SNMPERR_SUCCESS On success.
  109.  *      SNMPERR_GENERR On failure.
  110.  */
  111. extern int
  112. memdup(u_char **to, const u_char *from, size_t size);
  113. #endif
  114. /*fanghao(C): 2003-02-13, we implement this function 'memdup()' by ourselves
  115. from now on, previously, it was provided by PPP.
  116.  */
  117.  extern void *mymalloc (size_t size);
  118. int snmp_memdup(u_char **to, const u_char *from, size_t size)
  119. {
  120. *to = (u_char *)mymalloc(size + 1);
  121. if( NULL == *to )
  122. return SNMPERR_GENERR;
  123. memcpy( *to, from, size );
  124. (*to)[size] = '';
  125. return SNMPERR_SUCCESS;
  126. }
  127. /*******************************************************************-o-******
  128.  * binary_to_hex
  129.  *
  130.  * Parameters:
  131.  * *input Binary data.
  132.  * len Length of binary data.
  133.  * **output NULL terminated string equivalent in hex.
  134.  *      
  135.  * Returns:
  136.  * olen Length of output string not including NULL terminator.
  137.  *
  138.  * FIX Is there already one of these in the UCD SNMP codebase?
  139.  * The old one should be used, or this one should be moved to
  140.  * snmplib/snmp_api.c.
  141.  */
  142. u_int
  143. binary_to_hex(const u_char *input, size_t len, char **output)
  144. {
  145. u_int olen = (len * 2) + 1;
  146. char *s = (char *) calloc(1,olen),
  147. *op = s;
  148. const u_char *ip = input;
  149. while (ip-input < (int)len) {
  150. *op++ = (u_char)(VAL2HEX( (*ip >> 4) & 0xf ));
  151. *op++ = (u_char)VAL2HEX( *ip & 0xf );
  152. ip++;
  153. }
  154. *op = '';
  155. *output = s;
  156. return olen;
  157. }  /* end binary_to_hex() */
  158. /*******************************************************************-o-******
  159.  * hex_to_binary2
  160.  *
  161.  * Parameters:
  162.  * *input Printable data in base16.
  163.  * len Length in bytes of data.
  164.  * **output Binary data equivalent to input.
  165.  *      
  166.  * Returns:
  167.  * SNMPERR_GENERR Failure.
  168.  * <len> Otherwise, Length of allocated string.
  169.  *
  170.  *
  171.  * Input of an odd length is right aligned.
  172.  *
  173.  * FIX Another version of "hex-to-binary" which takes odd length input
  174.  * strings.  It also allocates the memory to hold the binary data.
  175.  * Should be integrated with the official hex_to_binary() function.
  176.  */
  177. int
  178. hex_to_binary2(const u_char *input, size_t len, char **output)
  179. {
  180. u_int olen = (len/2) + (len%2);
  181. char *s = (char *)calloc (1,olen),
  182. *op = s;
  183. const u_char *ip = input;
  184. *output = NULL;
  185. *op = 0;
  186. if (len%2) {
  187. if(!isxdigit(*ip)) goto hex_to_binary2_quit;
  188. *op++ = (u_char)HEX2VAL( *ip ); ip++;
  189. }
  190. while (ip-input < (int)len) {
  191. if(!isxdigit(*ip)) goto hex_to_binary2_quit;
  192. *op = (u_char)(HEX2VAL( *ip ) << 4); ip++;
  193. if(!isxdigit(*ip)) goto hex_to_binary2_quit;
  194. *op++ += HEX2VAL( *ip ); ip++;
  195. }
  196. *output = s;
  197. return olen;
  198. hex_to_binary2_quit:
  199. free_zero(s, olen);
  200. return -1;
  201. }  /* end hex_to_binary2() */
  202. /*******************************************************************-o-******
  203.  * dump_chunk
  204.  *
  205.  * Parameters:
  206.  * *title (May be NULL.)
  207.  * *buf
  208.  *  size
  209.  */
  210. void
  211. dump_chunk(const char *debugtoken, const char *title, const u_char *buf, int size)
  212. {
  213. u_int printunit = 64; /* XXX  Make global. */
  214. char chunk[SNMP_MAXBUF],
  215. *s, *sp;
  216. if ( title && (*title != '') ) {
  217.           DEBUGMSGTL((debugtoken, "%sn", title));
  218. }
  219. memset(chunk, 0, SNMP_MAXBUF);
  220. size = binary_to_hex(buf, size, &s);
  221. sp   = s;
  222. while (size > 0)
  223. {
  224. if (size > (int)printunit) {
  225. strncpy(chunk, sp, printunit);
  226. chunk[printunit] = '';
  227. DEBUGMSGTL((debugtoken, "t%sn", chunk));
  228. } else {
  229. DEBUGMSGTL((debugtoken, "t%sn", sp));
  230. }
  231. sp += printunit;
  232. size -= printunit;
  233. }
  234. SNMP_FREE(s);
  235. }  /* end dump_chunk() */
  236. /*******************************************************************-o-******
  237.  * dump_snmpEngineID
  238.  *
  239.  * Parameters:
  240.  * *estring
  241.  * *estring_len
  242.  *      
  243.  * Returns:
  244.  * Allocated memory pointing to a string of buflen char representing
  245.  * a printf'able form of the snmpEngineID.
  246.  *
  247.  * -OR- NULL on error.
  248.  *
  249.  *
  250.  * Translates the snmpEngineID TC into a printable string.  From RFC 2271,
  251.  * Section 5 (pp. 36-37):
  252.  *
  253.  * First bit: 0 Bit string structured by means non-SNMPv3.
  254.  *   1 Structure described by SNMPv3 SnmpEngineID TC.
  255.  *  
  256.  * Bytes 1-4: Enterprise ID.  (High bit of first byte is ignored.)
  257.  *  
  258.  * Byte 5: 0 (RESERVED by IANA.)
  259.  *   1 IPv4 address. (   4 octets)
  260.  *   2 IPv6 address. (  16 octets)
  261.  *   3 MAC address. (   6 octets)
  262.  *   4 Locally defined text. (0-27 octets)
  263.  *   5 Locally defined octets. (0-27 octets)
  264.  *   6-127 (RESERVED for enterprise.)
  265.  *  
  266.  * Bytes 6-32: (Determined by byte 5.)
  267.  *  
  268.  *
  269.  * Non-printable characters are given in hex.  Text is given in quotes.
  270.  * IP and MAC addresses are given in standard (UN*X) conventions.  Sections
  271.  * are comma separated.
  272.  *
  273.  * esp, remaining_len and s trace the state of the constructed buffer.
  274.  * s will be defined if there is something to return, and it will point
  275.  * to the end of the constructed buffer.
  276.  *
  277.  *
  278.  * ASSUME  "Text" means printable characters.
  279.  *
  280.  * XXX Must the snmpEngineID always have a minimum length of 12?
  281.  * (Cf. part 2 of the TC definition.)
  282.  * XXX Does not enforce upper-bound of 32 bytes.
  283.  * XXX Need a switch to decide whether to use DNS name instead of a simple
  284.  * IP address.
  285.  *
  286.  * FIX Use something other than sprint_hexstring which doesn't add 
  287.  * trailing spaces and (sometimes embedded) newlines...
  288.  */
  289. #ifdef SNMP_TESTING_CODE
  290. char *
  291. dump_snmpEngineID(const u_char *estring, size_t *estring_len)
  292. {
  293. #define eb(b) ( *(esp+b) & 0xff )
  294. int  rval = SNMPERR_SUCCESS,
  295.                          gotviolation = 0,
  296.                          slen           = 0;
  297. u_int    remaining_len;
  298. char    buf[SNMP_MAXBUF],
  299. *s = NULL,
  300. *t;
  301.         const u_char    *esp = estring;
  302. struct in_addr  iaddr;
  303. /*
  304.  * Sanity check.
  305.  */
  306. if ( !estring || (*estring_len <= 0) ) {
  307. QUITFUN(SNMPERR_GENERR, dump_snmpEngineID_quit);
  308. }
  309. remaining_len = *estring_len;
  310. memset(buf, 0, SNMP_MAXBUF);
  311. /*
  312.  * Test first bit.  Return immediately with a hex string, or
  313.  * begin by formatting the enterprise ID.
  314.  */
  315. if ( !(*esp & 0x80) ) {
  316. sprint_hexstring(buf, esp, remaining_len);
  317. s  = strchr(buf, '');
  318. s -= 1;
  319. goto dump_snmpEngineID_quit;
  320. }
  321. s = buf;
  322. s += sprintf(s, "enterprise %d, ", ((*(esp+0)&0x7f) << 24) |
  323. ((*(esp+1)&0xff) << 16) |
  324. ((*(esp+2)&0xff) <<  8) |
  325. ((*(esp+3)&0xff)) );
  326. /* XXX  Ick. */
  327. if (remaining_len < 5) { /* XXX Violating string. */
  328. goto dump_snmpEngineID_quit;
  329. }
  330. esp += 4; /* Incremented one more in the switch below. */
  331. remaining_len -= 5;
  332. /*
  333.  * Act on the fifth byte.
  334.  */
  335. switch ((int) *esp++) {
  336. case 1: /* IPv4 address. */
  337. if (remaining_len < 4) goto dump_snmpEngineID_violation;
  338. memcpy(&iaddr.s_addr, esp, 4);
  339. if ( !(t = inet_ntoa(iaddr)) ) goto dump_snmpEngineID_violation;
  340. s += sprintf(s, "%s", t);
  341. esp += 4;
  342. remaining_len -= 4;
  343. break;
  344. case 2: /* IPv6 address. */
  345. if (remaining_len < 16) goto dump_snmpEngineID_violation;
  346. s += sprintf( s,
  347. "%02X%02X %02X%02X %02X%02X %02X%02X::"
  348. "%02X%02X %02X%02X %02X%02X %02X%02X",
  349. eb(0),  eb(1),  eb(2),  eb(3),
  350. eb(4),  eb(5),  eb(6),  eb(7),
  351. eb(8),  eb(9),  eb(10), eb(11),
  352. eb(12), eb(13), eb(14), eb(15) );
  353. esp += 16;
  354. remaining_len -= 16;
  355. break;
  356. case 3: /* MAC address. */
  357. if (remaining_len < 6) goto dump_snmpEngineID_violation;
  358. s += sprintf( s, "%02X:%02X:%02X:%02X:%02X:%02X",
  359. eb(0), eb(1), eb(2), eb(3), eb(4), eb(5) );
  360. esp += 6;
  361. remaining_len -= 6;
  362. break;
  363. case 4: /* Text. */
  364.                 /* Doesn't exist on all (many) architectures */
  365.                 /* s += snprintf(s, remaining_len+3, ""%s"", esp); */
  366. s += sprintf(s, ""%s"", esp);
  367. goto dump_snmpEngineID_quit;
  368. break; /*NOTREACHED*/
  369. case 5: /* Octets. */
  370. sprint_hexstring(s, esp, remaining_len);
  371. s  = strchr(buf, '');
  372. s -= 1;
  373. goto dump_snmpEngineID_quit;
  374. break; /*NOTREACHED*/
  375. dump_snmpEngineID_violation:
  376. case 0: /* Violation of RESERVED, 
  377.  *   -OR- of expected length.
  378.  */
  379. gotviolation = 1;
  380. s += sprintf(s, "!!! ");
  381. default: /* Unknown encoding. */
  382. if ( !gotviolation ) {
  383. s += sprintf(s, "??? ");
  384. }
  385. sprint_hexstring(s, esp, remaining_len);
  386. s  = strchr(buf, '');
  387. s -= 1;
  388. goto dump_snmpEngineID_quit;
  389. }  /* endswitch */
  390. /*
  391.  * Cases 1-3 (IP and MAC addresses) should not have trailing
  392.  * octets, but perhaps they do.  Throw them in too.  XXX
  393.  */
  394. if (remaining_len > 0) {
  395. s += sprintf(s, " (??? ");
  396. sprint_hexstring(s, esp, remaining_len);
  397. s  = strchr(buf, '');
  398. s -= 1;
  399. s += sprintf(s, ")");
  400. }
  401. dump_snmpEngineID_quit:
  402. if (s) {
  403.                 slen = s-buf+1;
  404. s = calloc(1,slen);
  405. memcpy(s, buf, (slen)-1);
  406. }
  407. memset(buf, 0, SNMP_MAXBUF); /* XXX -- Overkill? XXX: Yes! */
  408. return s;
  409. #undef eb
  410. }  /* end dump_snmpEngineID() */
  411. #endif /* SNMP_TESTING_CODE */
  412. /*
  413.  * create a new time marker.
  414.  * NOTE: Caller must free time marker when no longer needed.
  415.  */
  416. marker_t atime_newMarker(void)
  417. {
  418.   marker_t pm = (marker_t)calloc(1,sizeof(struct timeval));
  419.   gettimeofday((struct timeval *)pm, 0);
  420.   return pm;
  421. }
  422. /*
  423.  * set a time marker.
  424.  */
  425. void atime_setMarker(marker_t pm)
  426. {
  427.   if (! pm) return;
  428.   gettimeofday((struct timeval *)pm, 0);
  429. }
  430. /*
  431.  * Test: Has (marked time plus delta) exceeded current time ?
  432.  * Returns 0 if test fails or cannot be tested (no marker).
  433.  */
  434. int atime_ready( marker_t pm, int deltaT)
  435. {
  436.   struct timeval txdelta, txnow;
  437.   if (! pm) return 0;
  438.   memcpy((void *)&txdelta, pm, sizeof(txdelta));
  439.   while (deltaT > 1000) {
  440.      txdelta.tv_sec ++;
  441.      deltaT -= 1000;
  442.   }
  443.   txdelta.tv_usec = (deltaT * 1000) + txdelta.tv_usec;
  444.   gettimeofday(&txnow, 0);
  445.   if (timercmp(&txnow, &txdelta, <))
  446.         return 0;
  447.   return 1;
  448. }