net-snmp 5.7
|
00001 /* 00002 * tools.c 00003 */ 00004 00005 #define NETSNMP_TOOLS_C 1 /* dont re-define malloc wrappers here */ 00006 00007 #ifdef HAVE_CRTDBG_H 00008 /* 00009 * Define _CRTDBG_MAP_ALLOC such that in debug builds (when _DEBUG has been 00010 * defined) e.g. malloc() is rerouted to _malloc_dbg(). 00011 */ 00012 #define _CRTDBG_MAP_ALLOC 1 00013 #include <crtdbg.h> 00014 #endif 00015 00016 #include <net-snmp/net-snmp-config.h> 00017 #include <net-snmp/net-snmp-features.h> 00018 00019 #include <ctype.h> 00020 #include <stdio.h> 00021 #include <sys/types.h> 00022 #if TIME_WITH_SYS_TIME 00023 # include <sys/time.h> 00024 # include <time.h> 00025 #else 00026 # if HAVE_SYS_TIME_H 00027 # include <sys/time.h> 00028 # else 00029 # include <time.h> 00030 # endif 00031 #endif 00032 #ifdef HAVE_SYS_SOCKET_H 00033 #include <sys/socket.h> 00034 #endif 00035 #ifdef HAVE_SYS_TIME_H 00036 #include <sys/time.h> 00037 #endif 00038 #ifdef HAVE_STDLIB_H 00039 #include <stdlib.h> 00040 #endif 00041 #if HAVE_STRING_H 00042 #include <string.h> 00043 #else 00044 #include <strings.h> 00045 #endif 00046 #ifdef HAVE_NETINET_IN_H 00047 #include <netinet/in.h> 00048 #endif 00049 #ifdef HAVE_ARPA_INET_H 00050 #include <arpa/inet.h> 00051 #endif 00052 #ifdef HAVE_VALGRIND_MEMCHECK_H 00053 #include <valgrind/memcheck.h> 00054 #endif 00055 #ifdef cygwin 00056 #include <windows.h> 00057 #endif 00058 00059 #if HAVE_UNISTD_H 00060 #include <unistd.h> 00061 #endif 00062 #if HAVE_DMALLOC_H 00063 #include <dmalloc.h> 00064 #endif 00065 00066 #include <net-snmp/types.h> 00067 #include <net-snmp/output_api.h> 00068 #include <net-snmp/utilities.h> 00069 #include <net-snmp/library/tools.h> /* for "internal" definitions */ 00070 00071 #include <net-snmp/library/snmp_api.h> 00072 #include <net-snmp/library/mib.h> 00073 #include <net-snmp/library/scapi.h> 00074 00075 netsnmp_feature_child_of(tools_all, libnetsnmp) 00076 00077 netsnmp_feature_child_of(memory_wrappers, tools_all) 00078 netsnmp_feature_child_of(valgrind, tools_all) 00079 netsnmp_feature_child_of(string_time_to_secs, tools_all) 00080 netsnmp_feature_child_of(netsnmp_check_definedness, valgrind) 00081 00082 netsnmp_feature_child_of(uatime_ready, netsnmp_unused) 00083 netsnmp_feature_child_of(timeval_tticks, netsnmp_unused) 00084 00085 netsnmp_feature_child_of(memory_strdup, memory_wrappers) 00086 netsnmp_feature_child_of(memory_calloc, memory_wrappers) 00087 netsnmp_feature_child_of(memory_malloc, memory_wrappers) 00088 netsnmp_feature_child_of(memory_realloc, memory_wrappers) 00089 netsnmp_feature_child_of(memory_free, memory_wrappers) 00090 00091 #ifndef NETSNMP_FEATURE_REMOVE_MEMORY_WRAPPERS 00092 00098 char * netsnmp_strdup( const char * ptr) 00099 { 00100 return strdup(ptr); 00101 } 00102 #endif /* NETSNMP_FEATURE_REMOVE_MEMORY_STRDUP */ 00103 #ifndef NETSNMP_FEATURE_REMOVE_MEMORY_CALLOC 00104 00107 void * netsnmp_calloc(size_t nmemb, size_t size) 00108 { 00109 return calloc(nmemb, size); 00110 } 00111 #endif /* NETSNMP_FEATURE_REMOVE_MEMORY_CALLOC */ 00112 #ifndef NETSNMP_FEATURE_REMOVE_MEMORY_MALLOC 00113 00116 void * netsnmp_malloc(size_t size) 00117 { 00118 return malloc(size); 00119 } 00120 #endif /* NETSNMP_FEATURE_REMOVE_MEMORY_MALLOC */ 00121 #ifndef NETSNMP_FEATURE_REMOVE_MEMORY_REALLOC 00122 00125 void * netsnmp_realloc( void * ptr, size_t size) 00126 { 00127 return realloc(ptr, size); 00128 } 00129 #endif /* NETSNMP_FEATURE_REMOVE_MEMORY_REALLOC */ 00130 #ifndef NETSNMP_FEATURE_REMOVE_MEMORY_FREE 00131 00135 void netsnmp_free( void * ptr) 00136 { 00137 if (ptr) 00138 free(ptr); 00139 } 00140 #endif /* NETSNMP_FEATURE_REMOVE_MEMORY_FREE */ 00141 00156 int 00157 snmp_realloc(u_char ** buf, size_t * buf_len) 00158 { 00159 u_char *new_buf = NULL; 00160 size_t new_buf_len = 0; 00161 00162 if (buf == NULL) { 00163 return 0; 00164 } 00165 00166 if (*buf_len <= 255) { 00167 new_buf_len = *buf_len + 256; 00168 } else if (*buf_len > 255 && *buf_len <= 8191) { 00169 new_buf_len = *buf_len * 2; 00170 } else if (*buf_len > 8191) { 00171 new_buf_len = *buf_len + 8192; 00172 } 00173 00174 if (*buf == NULL) { 00175 new_buf = (u_char *) malloc(new_buf_len); 00176 } else { 00177 new_buf = (u_char *) realloc(*buf, new_buf_len); 00178 } 00179 00180 if (new_buf != NULL) { 00181 *buf = new_buf; 00182 *buf_len = new_buf_len; 00183 return 1; 00184 } else { 00185 return 0; 00186 } 00187 } 00188 00189 int 00190 snmp_strcat(u_char ** buf, size_t * buf_len, size_t * out_len, 00191 int allow_realloc, const u_char * s) 00192 { 00193 if (buf == NULL || buf_len == NULL || out_len == NULL) { 00194 return 0; 00195 } 00196 00197 if (s == NULL) { 00198 /* 00199 * Appending a NULL string always succeeds since it is a NOP. 00200 */ 00201 return 1; 00202 } 00203 00204 while ((*out_len + strlen((const char *) s) + 1) >= *buf_len) { 00205 if (!(allow_realloc && snmp_realloc(buf, buf_len))) { 00206 return 0; 00207 } 00208 } 00209 00210 strcpy((char *) (*buf + *out_len), (const char *) s); 00211 *out_len += strlen((char *) (*buf + *out_len)); 00212 return 1; 00213 } 00214 00220 void 00221 free_zero(void *buf, size_t size) 00222 { 00223 if (buf) { 00224 memset(buf, 0, size); 00225 free(buf); 00226 } 00227 00228 } /* end free_zero() */ 00229 00230 #ifndef NETSNMP_FEATURE_REMOVE_USM_SCAPI 00231 00241 u_char * 00242 malloc_random(size_t * size) 00243 { 00244 int rval = SNMPERR_SUCCESS; 00245 u_char *buf = (u_char *) calloc(1, *size); 00246 00247 if (buf) { 00248 rval = sc_random(buf, size); 00249 00250 if (rval < 0) { 00251 free_zero(buf, *size); 00252 buf = NULL; 00253 } else { 00254 *size = rval; 00255 } 00256 } 00257 00258 return buf; 00259 00260 } /* end malloc_random() */ 00261 #endif /* NETSNMP_FEATURE_REMOVE_USM_SCAPI */ 00262 00273 int 00274 memdup(u_char ** to, const void * from, size_t size) 00275 { 00276 if (to == NULL) 00277 return SNMPERR_GENERR; 00278 if (from == NULL) { 00279 *to = NULL; 00280 return SNMPERR_SUCCESS; 00281 } 00282 if ((*to = (u_char *) malloc(size)) == NULL) 00283 return SNMPERR_GENERR; 00284 memcpy(*to, from, size); 00285 return SNMPERR_SUCCESS; 00286 00287 } /* end memdup() */ 00288 00289 #ifndef NETSNMP_FEATURE_REMOVE_NETSNMP_CHECK_DEFINEDNESS 00290 00299 void 00300 netsnmp_check_definedness(const void *packet, size_t length) 00301 { 00302 #if defined(__VALGRIND_MAJOR__) && defined(__VALGRIND_MINOR__) \ 00303 && (__VALGRIND_MAJOR__ > 3 \ 00304 || (__VALGRIND_MAJOR__ == 3 && __VALGRIND_MINOR__ >= 6)) 00305 00306 if (RUNNING_ON_VALGRIND) { 00307 int i; 00308 char vbits; 00309 00310 for (i = 0; i < length; ++i) { 00311 if (VALGRIND_GET_VBITS((const char *)packet + i, &vbits, 1) == 1 00312 && vbits) 00313 VALGRIND_PRINTF_BACKTRACE("Undefined: byte %d/%d", i, 00314 (int)length); 00315 } 00316 } 00317 00318 #endif 00319 } 00320 #endif /* NETSNMP_FEATURE_REMOVE_NETSNMP_CHECK_DEFINEDNESS */ 00321 00325 char * 00326 netsnmp_strdup_and_null(const u_char * from, size_t from_len) 00327 { 00328 char *ret; 00329 00330 if (from_len == 0 || from[from_len - 1] != '\0') { 00331 ret = (char *)malloc(from_len + 1); 00332 if (!ret) 00333 return NULL; 00334 ret[from_len] = '\0'; 00335 } else { 00336 ret = (char *)malloc(from_len); 00337 if (!ret) 00338 return NULL; 00339 ret[from_len - 1] = '\0'; 00340 } 00341 memcpy(ret, from, from_len); 00342 return ret; 00343 } 00344 00355 u_int 00356 netsnmp_binary_to_hex(u_char ** dest, size_t *dest_len, int allow_realloc, 00357 const u_char * input, size_t len) 00358 { 00359 u_int olen = (len * 2) + 1; 00360 u_char *s, *op; 00361 const u_char *ip = input; 00362 00363 if (dest == NULL || dest_len == NULL || input == NULL) 00364 return 0; 00365 00366 if (NULL == *dest) { 00367 s = (unsigned char *) calloc(1, olen); 00368 *dest_len = olen; 00369 } 00370 else 00371 s = *dest; 00372 00373 if (*dest_len < olen) { 00374 if (!allow_realloc) 00375 return 0; 00376 *dest_len = olen; 00377 if (snmp_realloc(dest, dest_len)) 00378 return 0; 00379 } 00380 00381 op = s; 00382 while (ip - input < (int) len) { 00383 *op++ = VAL2HEX((*ip >> 4) & 0xf); 00384 *op++ = VAL2HEX(*ip & 0xf); 00385 ip++; 00386 } 00387 *op = '\0'; 00388 00389 if (s != *dest) 00390 *dest = s; 00391 *dest_len = olen; 00392 00393 return olen; 00394 00395 } /* end netsnmp_binary_to_hex() */ 00396 00409 u_int 00410 binary_to_hex(const u_char * input, size_t len, char **output) 00411 { 00412 size_t out_len = 0; 00413 00414 *output = NULL; /* will alloc new buffer */ 00415 00416 return netsnmp_binary_to_hex((u_char**)output, &out_len, 1, input, len); 00417 } /* end binary_to_hex() */ 00418 00419 00420 00421 00436 int 00437 hex_to_binary2(const u_char * input, size_t len, char **output) 00438 { 00439 u_int olen = (len / 2) + (len % 2); 00440 char *s = (char *) calloc(1, (olen) ? olen : 1), *op = s; 00441 const u_char *ip = input; 00442 00443 00444 *output = NULL; 00445 *op = 0; 00446 if (len % 2) { 00447 if (!isxdigit(*ip)) 00448 goto hex_to_binary2_quit; 00449 *op++ = HEX2VAL(*ip); 00450 ip++; 00451 } 00452 00453 while (ip - input < (int) len) { 00454 if (!isxdigit(*ip)) 00455 goto hex_to_binary2_quit; 00456 *op = HEX2VAL(*ip) << 4; 00457 ip++; 00458 00459 if (!isxdigit(*ip)) 00460 goto hex_to_binary2_quit; 00461 *op++ += HEX2VAL(*ip); 00462 ip++; 00463 } 00464 00465 *output = s; 00466 return olen; 00467 00468 hex_to_binary2_quit: 00469 free_zero(s, olen); 00470 return -1; 00471 00472 } /* end hex_to_binary2() */ 00473 00474 int 00475 snmp_decimal_to_binary(u_char ** buf, size_t * buf_len, size_t * out_len, 00476 int allow_realloc, const char *decimal) 00477 { 00478 int subid = 0; 00479 const char *cp = decimal; 00480 00481 if (buf == NULL || buf_len == NULL || out_len == NULL 00482 || decimal == NULL) { 00483 return 0; 00484 } 00485 00486 while (*cp != '\0') { 00487 if (isspace((int) *cp) || *cp == '.') { 00488 cp++; 00489 continue; 00490 } 00491 if (!isdigit((int) *cp)) { 00492 return 0; 00493 } 00494 if ((subid = atoi(cp)) > 255) { 00495 return 0; 00496 } 00497 if ((*out_len >= *buf_len) && 00498 !(allow_realloc && snmp_realloc(buf, buf_len))) { 00499 return 0; 00500 } 00501 *(*buf + *out_len) = (u_char) subid; 00502 (*out_len)++; 00503 while (isdigit((int) *cp)) { 00504 cp++; 00505 } 00506 } 00507 return 1; 00508 } 00509 00537 int 00538 netsnmp_hex_to_binary(u_char ** buf, size_t * buf_len, size_t * offset, 00539 int allow_realloc, const char *hex, const char *delim) 00540 { 00541 unsigned int subid = 0; 00542 const char *cp = hex; 00543 00544 if (buf == NULL || buf_len == NULL || offset == NULL || hex == NULL) { 00545 return 0; 00546 } 00547 00548 if ((*cp == '0') && ((*(cp + 1) == 'x') || (*(cp + 1) == 'X'))) { 00549 cp += 2; 00550 } 00551 00552 while (*cp != '\0') { 00553 if (!isxdigit((int) *cp) || 00554 !isxdigit((int) *(cp+1))) { 00555 if ((NULL != delim) && (NULL != strchr(delim, *cp))) { 00556 cp++; 00557 continue; 00558 } 00559 return 0; 00560 } 00561 if (sscanf(cp, "%2x", &subid) == 0) { 00562 return 0; 00563 } 00564 /* 00565 * if we dont' have enough space, realloc. 00566 * (snmp_realloc will adjust buf_len to new size) 00567 */ 00568 if ((*offset >= *buf_len) && 00569 !(allow_realloc && snmp_realloc(buf, buf_len))) { 00570 return 0; 00571 } 00572 *(*buf + *offset) = (u_char) subid; 00573 (*offset)++; 00574 if (*++cp == '\0') { 00575 /* 00576 * Odd number of hex digits is an error. 00577 */ 00578 return 0; 00579 } else { 00580 cp++; 00581 } 00582 } 00583 return 1; 00584 } 00585 00597 int 00598 snmp_hex_to_binary(u_char ** buf, size_t * buf_len, size_t * offset, 00599 int allow_realloc, const char *hex) 00600 { 00601 return netsnmp_hex_to_binary(buf, buf_len, offset, allow_realloc, hex, " "); 00602 } 00603 00604 /*******************************************************************-o-****** 00605 * dump_chunk 00606 * 00607 * Parameters: 00608 * *title (May be NULL.) 00609 * *buf 00610 * size 00611 */ 00612 void 00613 dump_chunk(const char *debugtoken, const char *title, const u_char * buf, 00614 int size) 00615 { 00616 u_int printunit = 64; /* XXX Make global. */ 00617 char chunk[SNMP_MAXBUF], *s, *sp; 00618 00619 if (title && (*title != '\0')) { 00620 DEBUGMSGTL((debugtoken, "%s\n", title)); 00621 } 00622 00623 00624 memset(chunk, 0, SNMP_MAXBUF); 00625 size = binary_to_hex(buf, size, &s); 00626 sp = s; 00627 00628 while (size > 0) { 00629 if (size > (int) printunit) { 00630 strncpy(chunk, sp, printunit); 00631 chunk[printunit] = '\0'; 00632 DEBUGMSGTL((debugtoken, "\t%s\n", chunk)); 00633 } else { 00634 DEBUGMSGTL((debugtoken, "\t%s\n", sp)); 00635 } 00636 00637 sp += printunit; 00638 size -= printunit; 00639 } 00640 00641 00642 SNMP_FREE(s); 00643 00644 } /* end dump_chunk() */ 00645 00646 00647 00648 00649 /*******************************************************************-o-****** 00650 * dump_snmpEngineID 00651 * 00652 * Parameters: 00653 * *estring 00654 * *estring_len 00655 * 00656 * Returns: 00657 * Allocated memory pointing to a string of buflen char representing 00658 * a printf'able form of the snmpEngineID. 00659 * 00660 * -OR- NULL on error. 00661 * 00662 * 00663 * Translates the snmpEngineID TC into a printable string. From RFC 2271, 00664 * Section 5 (pp. 36-37): 00665 * 00666 * First bit: 0 Bit string structured by means non-SNMPv3. 00667 * 1 Structure described by SNMPv3 SnmpEngineID TC. 00668 * 00669 * Bytes 1-4: Enterprise ID. (High bit of first byte is ignored.) 00670 * 00671 * Byte 5: 0 (RESERVED by IANA.) 00672 * 1 IPv4 address. ( 4 octets) 00673 * 2 IPv6 address. ( 16 octets) 00674 * 3 MAC address. ( 6 octets) 00675 * 4 Locally defined text. (0-27 octets) 00676 * 5 Locally defined octets. (0-27 octets) 00677 * 6-127 (RESERVED for enterprise.) 00678 * 00679 * Bytes 6-32: (Determined by byte 5.) 00680 * 00681 * 00682 * Non-printable characters are given in hex. Text is given in quotes. 00683 * IP and MAC addresses are given in standard (UN*X) conventions. Sections 00684 * are comma separated. 00685 * 00686 * esp, remaining_len and s trace the state of the constructed buffer. 00687 * s will be defined if there is something to return, and it will point 00688 * to the end of the constructed buffer. 00689 * 00690 * 00691 * ASSUME "Text" means printable characters. 00692 * 00693 * XXX Must the snmpEngineID always have a minimum length of 12? 00694 * (Cf. part 2 of the TC definition.) 00695 * XXX Does not enforce upper-bound of 32 bytes. 00696 * XXX Need a switch to decide whether to use DNS name instead of a simple 00697 * IP address. 00698 * 00699 * FIX Use something other than snprint_hexstring which doesn't add 00700 * trailing spaces and (sometimes embedded) newlines... 00701 */ 00702 #ifdef NETSNMP_ENABLE_TESTING_CODE 00703 char * 00704 dump_snmpEngineID(const u_char * estring, size_t * estring_len) 00705 { 00706 #define eb(b) ( *(esp+b) & 0xff ) 00707 00708 int rval = SNMPERR_SUCCESS, gotviolation = 0, slen = 0; 00709 u_int remaining_len; 00710 00711 char buf[SNMP_MAXBUF], *s = NULL, *t; 00712 const u_char *esp = estring; 00713 00714 struct in_addr iaddr; 00715 00716 00717 00718 /* 00719 * Sanity check. 00720 */ 00721 if (!estring || (*estring_len <= 0)) { 00722 QUITFUN(SNMPERR_GENERR, dump_snmpEngineID_quit); 00723 } 00724 remaining_len = *estring_len; 00725 memset(buf, 0, SNMP_MAXBUF); 00726 00727 00728 00729 /* 00730 * Test first bit. Return immediately with a hex string, or 00731 * begin by formatting the enterprise ID. 00732 */ 00733 if (!(*esp & 0x80)) { 00734 snprint_hexstring(buf, SNMP_MAXBUF, esp, remaining_len); 00735 s = strchr(buf, '\0'); 00736 s -= 1; 00737 goto dump_snmpEngineID_quit; 00738 } 00739 00740 s = buf; 00741 s += sprintf(s, "enterprise %d, ", ((*(esp + 0) & 0x7f) << 24) | 00742 ((*(esp + 1) & 0xff) << 16) | 00743 ((*(esp + 2) & 0xff) << 8) | ((*(esp + 3) & 0xff))); 00744 /* 00745 * XXX Ick. 00746 */ 00747 00748 if (remaining_len < 5) { /* XXX Violating string. */ 00749 goto dump_snmpEngineID_quit; 00750 } 00751 00752 esp += 4; /* Incremented one more in the switch below. */ 00753 remaining_len -= 5; 00754 00755 00756 00757 /* 00758 * Act on the fifth byte. 00759 */ 00760 switch ((int) *esp++) { 00761 case 1: /* IPv4 address. */ 00762 00763 if (remaining_len < 4) 00764 goto dump_snmpEngineID_violation; 00765 memcpy(&iaddr.s_addr, esp, 4); 00766 00767 if (!(t = inet_ntoa(iaddr))) 00768 goto dump_snmpEngineID_violation; 00769 s += sprintf(s, "%s", t); 00770 00771 esp += 4; 00772 remaining_len -= 4; 00773 break; 00774 00775 case 2: /* IPv6 address. */ 00776 00777 if (remaining_len < 16) 00778 goto dump_snmpEngineID_violation; 00779 00780 s += sprintf(s, 00781 "%02X%02X %02X%02X %02X%02X %02X%02X::" 00782 "%02X%02X %02X%02X %02X%02X %02X%02X", 00783 eb(0), eb(1), eb(2), eb(3), 00784 eb(4), eb(5), eb(6), eb(7), 00785 eb(8), eb(9), eb(10), eb(11), 00786 eb(12), eb(13), eb(14), eb(15)); 00787 00788 esp += 16; 00789 remaining_len -= 16; 00790 break; 00791 00792 case 3: /* MAC address. */ 00793 00794 if (remaining_len < 6) 00795 goto dump_snmpEngineID_violation; 00796 00797 s += sprintf(s, "%02X:%02X:%02X:%02X:%02X:%02X", 00798 eb(0), eb(1), eb(2), eb(3), eb(4), eb(5)); 00799 00800 esp += 6; 00801 remaining_len -= 6; 00802 break; 00803 00804 case 4: /* Text. */ 00805 00806 /* 00807 * Doesn't exist on all (many) architectures 00808 */ 00809 /* 00810 * s += snprintf(s, remaining_len+3, "\"%s\"", esp); 00811 */ 00812 s += sprintf(s, "\"%.*s\"", sizeof(buf)-strlen(buf)-3, esp); 00813 goto dump_snmpEngineID_quit; 00814 break; 00815 /*NOTREACHED*/ case 5: /* Octets. */ 00816 00817 snprint_hexstring(s, (SNMP_MAXBUF - (s-buf)), 00818 esp, remaining_len); 00819 s = strchr(buf, '\0'); 00820 s -= 1; 00821 goto dump_snmpEngineID_quit; 00822 break; 00823 /*NOTREACHED*/ dump_snmpEngineID_violation: 00824 case 0: /* Violation of RESERVED, 00825 * * -OR- of expected length. 00826 */ 00827 gotviolation = 1; 00828 s += sprintf(s, "!!! "); 00829 00830 default: /* Unknown encoding. */ 00831 00832 if (!gotviolation) { 00833 s += sprintf(s, "??? "); 00834 } 00835 snprint_hexstring(s, (SNMP_MAXBUF - (s-buf)), 00836 esp, remaining_len); 00837 s = strchr(buf, '\0'); 00838 s -= 1; 00839 00840 goto dump_snmpEngineID_quit; 00841 00842 } /* endswitch */ 00843 00844 00845 00846 /* 00847 * Cases 1-3 (IP and MAC addresses) should not have trailing 00848 * octets, but perhaps they do. Throw them in too. XXX 00849 */ 00850 if (remaining_len > 0) { 00851 s += sprintf(s, " (??? "); 00852 00853 snprint_hexstring(s, (SNMP_MAXBUF - (s-buf)), 00854 esp, remaining_len); 00855 s = strchr(buf, '\0'); 00856 s -= 1; 00857 00858 s += sprintf(s, ")"); 00859 } 00860 00861 00862 00863 dump_snmpEngineID_quit: 00864 if (s) { 00865 slen = s - buf + 1; 00866 s = calloc(1, slen); 00867 memcpy(s, buf, (slen) - 1); 00868 } 00869 00870 memset(buf, 0, SNMP_MAXBUF); /* XXX -- Overkill? XXX: Yes! */ 00871 00872 return s; 00873 00874 #undef eb 00875 } /* end dump_snmpEngineID() */ 00876 #endif /* NETSNMP_ENABLE_TESTING_CODE */ 00877 00878 00883 marker_t 00884 atime_newMarker(void) 00885 { 00886 marker_t pm = (marker_t) calloc(1, sizeof(struct timeval)); 00887 gettimeofday((struct timeval *) pm, NULL); 00888 return pm; 00889 } 00890 00894 void 00895 atime_setMarker(marker_t pm) 00896 { 00897 if (!pm) 00898 return; 00899 00900 gettimeofday((struct timeval *) pm, NULL); 00901 } 00902 00903 00907 long 00908 atime_diff(const_marker_t first, const_marker_t second) 00909 { 00910 struct timeval diff; 00911 00912 NETSNMP_TIMERSUB((const struct timeval *) second, (const struct timeval *) first, &diff); 00913 00914 return (long)(diff.tv_sec * 1000 + diff.tv_usec / 1000); 00915 } 00916 00920 u_long 00921 uatime_diff(const_marker_t first, const_marker_t second) 00922 { 00923 struct timeval diff; 00924 00925 NETSNMP_TIMERSUB((const struct timeval *) second, (const struct timeval *) first, &diff); 00926 00927 return (((u_long) diff.tv_sec) * 1000 + diff.tv_usec / 1000); 00928 } 00929 00934 u_long 00935 uatime_hdiff(const_marker_t first, const_marker_t second) 00936 { 00937 struct timeval diff; 00938 00939 NETSNMP_TIMERSUB((const struct timeval *) second, (const struct timeval *) first, &diff); 00940 return ((u_long) diff.tv_sec) * 100 + diff.tv_usec / 10000; 00941 } 00942 00947 int 00948 atime_ready(const_marker_t pm, int deltaT) 00949 { 00950 marker_t now; 00951 long diff; 00952 if (!pm) 00953 return 0; 00954 00955 now = atime_newMarker(); 00956 00957 diff = atime_diff(pm, now); 00958 free(now); 00959 if (diff < deltaT) 00960 return 0; 00961 00962 return 1; 00963 } 00964 00969 #ifndef NETSNMP_FEATURE_REMOVE_UATIME_READY 00970 int 00971 uatime_ready(const_marker_t pm, unsigned int deltaT) 00972 { 00973 marker_t now; 00974 u_long diff; 00975 if (!pm) 00976 return 0; 00977 00978 now = atime_newMarker(); 00979 00980 diff = uatime_diff(pm, now); 00981 free(now); 00982 if (diff < deltaT) 00983 return 0; 00984 00985 return 1; 00986 } 00987 #endif /* NETSNMP_FEATURE_REMOVE_UATIME_READY */ 00988 00989 00990 /* 00991 * Time-related utility functions 00992 */ 00993 00997 int 00998 marker_tticks(const_marker_t pm) 00999 { 01000 int res; 01001 marker_t now = atime_newMarker(); 01002 01003 res = atime_diff(pm, now); 01004 free(now); 01005 return res / 10; /* atime_diff works in msec, not csec */ 01006 } 01007 01008 #ifndef NETSNMP_FEATURE_REMOVE_TIMEVAL_TTICKS 01009 int 01010 timeval_tticks(const struct timeval *tv) 01011 { 01012 return marker_tticks((const_marker_t) tv); 01013 } 01014 #endif /* NETSNMP_FEATURE_REMOVE_TIMEVAL_TTICKS */ 01015 01028 char *netsnmp_getenv(const char *name) 01029 { 01030 #if !defined (WIN32) && !defined (cygwin) 01031 return (getenv(name)); 01032 #else 01033 char *temp = NULL; 01034 HKEY hKey; 01035 unsigned char * key_value = NULL; 01036 DWORD key_value_size = 0; 01037 DWORD key_value_type = 0; 01038 DWORD getenv_worked = 0; 01039 01040 DEBUGMSGTL(("read_config", "netsnmp_getenv called with name: %s\n",name)); 01041 01042 if (!(name)) 01043 return NULL; 01044 01045 /* Try environment variable first */ 01046 temp = getenv(name); 01047 if (temp) { 01048 getenv_worked = 1; 01049 DEBUGMSGTL(("read_config", "netsnmp_getenv will return from ENV: %s\n",temp)); 01050 } 01051 01052 /* Next try HKCU */ 01053 if (temp == NULL) 01054 { 01055 if (getenv("SNMP_IGNORE_WINDOWS_REGISTRY")) 01056 return NULL; 01057 01058 if (RegOpenKeyExA( 01059 HKEY_CURRENT_USER, 01060 "SOFTWARE\\Net-SNMP", 01061 0, 01062 KEY_QUERY_VALUE, 01063 &hKey) == ERROR_SUCCESS) { 01064 01065 if (RegQueryValueExA( 01066 hKey, 01067 name, 01068 NULL, 01069 &key_value_type, 01070 NULL, /* Just get the size */ 01071 &key_value_size) == ERROR_SUCCESS) { 01072 01073 SNMP_FREE(key_value); 01074 01075 /* Allocate memory needed +1 to allow RegQueryValueExA to NULL terminate the 01076 * string data in registry is missing one (which is unlikely). 01077 */ 01078 key_value = malloc((sizeof(char) * key_value_size)+sizeof(char)); 01079 01080 if (RegQueryValueExA( 01081 hKey, 01082 name, 01083 NULL, 01084 &key_value_type, 01085 key_value, 01086 &key_value_size) == ERROR_SUCCESS) { 01087 } 01088 temp = (char *) key_value; 01089 } 01090 RegCloseKey(hKey); 01091 if (temp) 01092 DEBUGMSGTL(("read_config", "netsnmp_getenv will return from HKCU: %s\n",temp)); 01093 } 01094 } 01095 01096 /* Next try HKLM */ 01097 if (temp == NULL) 01098 { 01099 if (RegOpenKeyExA( 01100 HKEY_LOCAL_MACHINE, 01101 "SOFTWARE\\Net-SNMP", 01102 0, 01103 KEY_QUERY_VALUE, 01104 &hKey) == ERROR_SUCCESS) { 01105 01106 if (RegQueryValueExA( 01107 hKey, 01108 name, 01109 NULL, 01110 &key_value_type, 01111 NULL, /* Just get the size */ 01112 &key_value_size) == ERROR_SUCCESS) { 01113 01114 SNMP_FREE(key_value); 01115 01116 /* Allocate memory needed +1 to allow RegQueryValueExA to NULL terminate the 01117 * string data in registry is missing one (which is unlikely). 01118 */ 01119 key_value = malloc((sizeof(char) * key_value_size)+sizeof(char)); 01120 01121 if (RegQueryValueExA( 01122 hKey, 01123 name, 01124 NULL, 01125 &key_value_type, 01126 key_value, 01127 &key_value_size) == ERROR_SUCCESS) { 01128 } 01129 temp = (char *) key_value; 01130 01131 } 01132 RegCloseKey(hKey); 01133 if (temp) 01134 DEBUGMSGTL(("read_config", "netsnmp_getenv will return from HKLM: %s\n",temp)); 01135 } 01136 } 01137 01138 if (temp && !getenv_worked) { 01139 setenv(name, temp, 1); 01140 SNMP_FREE(temp); 01141 } 01142 01143 DEBUGMSGTL(("read_config", "netsnmp_getenv returning: %s\n",getenv(name))); 01144 01145 return(getenv(name)); 01146 #endif 01147 } 01148 01149 /* 01150 * swap the order of an inet addr string 01151 */ 01152 int 01153 netsnmp_addrstr_hton(char *ptr, size_t len) 01154 { 01155 #ifndef WORDS_BIGENDIAN 01156 char tmp[8]; 01157 01158 if (8 == len) { 01159 tmp[0] = ptr[6]; 01160 tmp[1] = ptr[7]; 01161 tmp[2] = ptr[4]; 01162 tmp[3] = ptr[5]; 01163 tmp[4] = ptr[2]; 01164 tmp[5] = ptr[3]; 01165 tmp[6] = ptr[0]; 01166 tmp[7] = ptr[1]; 01167 memcpy (ptr, &tmp, 8); 01168 } 01169 else if (32 == len) { 01170 netsnmp_addrstr_hton(ptr , 8); 01171 netsnmp_addrstr_hton(ptr+8 , 8); 01172 netsnmp_addrstr_hton(ptr+16, 8); 01173 netsnmp_addrstr_hton(ptr+24, 8); 01174 } 01175 else 01176 return -1; 01177 #endif 01178 01179 return 0; 01180 } 01181 01182 #ifndef NETSNMP_FEATURE_REMOVE_STRING_TIME_TO_SECS 01183 01195 int 01196 netsnmp_string_time_to_secs(const char *time_string) { 01197 int secs = -1; 01198 if (!time_string || !time_string[0]) 01199 return secs; 01200 01201 secs = atoi(time_string); 01202 01203 if (isdigit((unsigned char)time_string[strlen(time_string)-1])) 01204 return secs; /* no letter specified, it's already in seconds */ 01205 01206 switch (time_string[strlen(time_string)-1]) { 01207 case 's': 01208 case 'S': 01209 /* already in seconds */ 01210 break; 01211 01212 case 'm': 01213 case 'M': 01214 secs = secs * 60; 01215 break; 01216 01217 case 'h': 01218 case 'H': 01219 secs = secs * 60 * 60; 01220 break; 01221 01222 case 'd': 01223 case 'D': 01224 secs = secs * 60 * 60 * 24; 01225 break; 01226 01227 case 'w': 01228 case 'W': 01229 secs = secs * 60 * 60 * 24 * 7; 01230 break; 01231 01232 default: 01233 snmp_log(LOG_ERR, "time string %s contains an invalid suffix letter\n", 01234 time_string); 01235 return -1; 01236 } 01237 01238 DEBUGMSGTL(("string_time_to_secs", "Converted time string %s to %d\n", 01239 time_string, secs)); 01240 return secs; 01241 } 01242 #endif /* NETSNMP_FEATURE_REMOVE_STRING_TIME_TO_SECS */