00001
00002
00003
00004
00005 #define NETSNMP_TOOLS_C 1
00006
00007 #include <net-snmp/net-snmp-config.h>
00008
00009 #include <ctype.h>
00010 #include <stdio.h>
00011 #include <sys/types.h>
00012 #if TIME_WITH_SYS_TIME
00013 # ifdef WIN32
00014 # include <sys/timeb.h>
00015 # else
00016 # include <sys/time.h>
00017 # endif
00018 # include <time.h>
00019 #else
00020 # if HAVE_SYS_TIME_H
00021 # include <sys/time.h>
00022 # else
00023 # include <time.h>
00024 # endif
00025 #endif
00026 #ifdef HAVE_SYS_SOCKET_H
00027 #include <sys/socket.h>
00028 #endif
00029 #if HAVE_WINSOCK_H
00030 #include <winsock.h>
00031 #endif
00032 #ifdef HAVE_STDLIB_H
00033 #include <stdlib.h>
00034 #endif
00035 #if HAVE_STRING_H
00036 #include <string.h>
00037 #else
00038 #include <strings.h>
00039 #endif
00040 #ifdef HAVE_NETINET_IN_H
00041 #include <netinet/in.h>
00042 #endif
00043 #ifdef HAVE_ARPA_INET_H
00044 #include <arpa/inet.h>
00045 #endif
00046 #ifdef cygwin
00047 #include <windows.h>
00048 #endif
00049
00050 #if HAVE_DMALLOC_H
00051 #include <dmalloc.h>
00052 #endif
00053
00054 #include <net-snmp/types.h>
00055 #include <net-snmp/output_api.h>
00056 #include <net-snmp/utilities.h>
00057 #include <net-snmp/library/tools.h>
00058
00059 #include <net-snmp/library/snmp_api.h>
00060 #include <net-snmp/library/mib.h>
00061 #include <net-snmp/library/scapi.h>
00062
00063 #ifdef WIN32
00064
00067 char * netsnmp_strdup( const char * ptr)
00068 {
00069 return strdup(ptr);
00070 }
00074 void * netsnmp_calloc(size_t nmemb, size_t size)
00075 {
00076 return calloc(nmemb, size);
00077 }
00078
00082 void * netsnmp_malloc(size_t size)
00083 {
00084 return malloc(size);
00085 }
00086
00090 void * netsnmp_realloc( void * ptr, size_t size)
00091 {
00092 return realloc(ptr, size);
00093 }
00094
00099 void netsnmp_free( void * ptr)
00100 {
00101 if (ptr)
00102 free(ptr);
00103 }
00104 #endif
00105
00120 int
00121 snmp_realloc(u_char ** buf, size_t * buf_len)
00122 {
00123 u_char *new_buf = NULL;
00124 size_t new_buf_len = 0;
00125
00126 if (buf == NULL) {
00127 return 0;
00128 }
00129
00130 if (*buf_len <= 255) {
00131 new_buf_len = *buf_len + 256;
00132 } else if (*buf_len > 255 && *buf_len <= 8191) {
00133 new_buf_len = *buf_len * 2;
00134 } else if (*buf_len > 8191) {
00135 new_buf_len = *buf_len + 8192;
00136 }
00137
00138 if (*buf == NULL) {
00139 new_buf = (u_char *) malloc(new_buf_len);
00140 } else {
00141 new_buf = (u_char *) realloc(*buf, new_buf_len);
00142 }
00143
00144 if (new_buf != NULL) {
00145 *buf = new_buf;
00146 *buf_len = new_buf_len;
00147 return 1;
00148 } else {
00149 return 0;
00150 }
00151 }
00152
00153 int
00154 snmp_strcat(u_char ** buf, size_t * buf_len, size_t * out_len,
00155 int allow_realloc, const u_char * s)
00156 {
00157 if (buf == NULL || buf_len == NULL || out_len == NULL) {
00158 return 0;
00159 }
00160
00161 if (s == NULL) {
00162
00163
00164
00165 return 1;
00166 }
00167
00168 while ((*out_len + strlen((const char *) s) + 1) >= *buf_len) {
00169 if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
00170 return 0;
00171 }
00172 }
00173
00174 strcpy((char *) (*buf + *out_len), (const char *) s);
00175 *out_len += strlen((char *) (*buf + *out_len));
00176 return 1;
00177 }
00178
00184 void
00185 free_zero(void *buf, size_t size)
00186 {
00187 if (buf) {
00188 memset(buf, 0, size);
00189 free(buf);
00190 }
00191
00192 }
00193
00204 u_char *
00205 malloc_random(size_t * size)
00206 {
00207 int rval = SNMPERR_SUCCESS;
00208 u_char *buf = (u_char *) calloc(1, *size);
00209
00210 if (buf) {
00211 rval = sc_random(buf, size);
00212
00213 if (rval < 0) {
00214 free_zero(buf, *size);
00215 buf = NULL;
00216 } else {
00217 *size = rval;
00218 }
00219 }
00220
00221 return buf;
00222
00223 }
00224
00235 int
00236 memdup(u_char ** to, const u_char * from, size_t size)
00237 {
00238 if (to == NULL)
00239 return SNMPERR_GENERR;
00240 if (from == NULL) {
00241 *to = NULL;
00242 return SNMPERR_SUCCESS;
00243 }
00244 if ((*to = (u_char *) malloc(size)) == NULL)
00245 return SNMPERR_GENERR;
00246 memcpy(*to, from, size);
00247 return SNMPERR_SUCCESS;
00248
00249 }
00250
00254 char *
00255 netsnmp_strdup_and_null(const u_char * from, size_t from_len)
00256 {
00257 char *ret;
00258
00259 if (from_len == 0 || from[from_len - 1] != '\0') {
00260 ret = malloc(from_len + 1);
00261 if (!ret)
00262 return NULL;
00263 ret[from_len] = '\0';
00264 } else {
00265 ret = malloc(from_len);
00266 if (!ret)
00267 return NULL;
00268 ret[from_len - 1] = '\0';
00269 }
00270 memcpy(ret, from, from_len);
00271 return ret;
00272 }
00273
00286 u_int
00287 binary_to_hex(const u_char * input, size_t len, char **output)
00288 {
00289 u_int olen = (len * 2) + 1;
00290 char *s = (char *) calloc(1, olen), *op = s;
00291 const u_char *ip = input;
00292
00293
00294 while (ip - input < (int) len) {
00295 *op++ = VAL2HEX((*ip >> 4) & 0xf);
00296 *op++ = VAL2HEX(*ip & 0xf);
00297 ip++;
00298 }
00299 *op = '\0';
00300
00301 *output = s;
00302 return olen;
00303
00304 }
00305
00306
00307
00308
00323 int
00324 hex_to_binary2(const u_char * input, size_t len, char **output)
00325 {
00326 u_int olen = (len / 2) + (len % 2);
00327 char *s = (char *) calloc(1, (olen) ? olen : 1), *op = s;
00328 const u_char *ip = input;
00329
00330
00331 *output = NULL;
00332 *op = 0;
00333 if (len % 2) {
00334 if (!isxdigit(*ip))
00335 goto hex_to_binary2_quit;
00336 *op++ = HEX2VAL(*ip);
00337 ip++;
00338 }
00339
00340 while (ip - input < (int) len) {
00341 if (!isxdigit(*ip))
00342 goto hex_to_binary2_quit;
00343 *op = HEX2VAL(*ip) << 4;
00344 ip++;
00345
00346 if (!isxdigit(*ip))
00347 goto hex_to_binary2_quit;
00348 *op++ += HEX2VAL(*ip);
00349 ip++;
00350 }
00351
00352 *output = s;
00353 return olen;
00354
00355 hex_to_binary2_quit:
00356 free_zero(s, olen);
00357 return -1;
00358
00359 }
00360
00361 int
00362 snmp_decimal_to_binary(u_char ** buf, size_t * buf_len, size_t * out_len,
00363 int allow_realloc, const char *decimal)
00364 {
00365 int subid = 0;
00366 const char *cp = decimal;
00367
00368 if (buf == NULL || buf_len == NULL || out_len == NULL
00369 || decimal == NULL) {
00370 return 0;
00371 }
00372
00373 while (*cp != '\0') {
00374 if (isspace((int) *cp) || *cp == '.') {
00375 cp++;
00376 continue;
00377 }
00378 if (!isdigit((int) *cp)) {
00379 return 0;
00380 }
00381 if ((subid = atoi(cp)) > 255) {
00382 return 0;
00383 }
00384 if ((*out_len >= *buf_len) &&
00385 !(allow_realloc && snmp_realloc(buf, buf_len))) {
00386 return 0;
00387 }
00388 *(*buf + *out_len) = (u_char) subid;
00389 (*out_len)++;
00390 while (isdigit((int) *cp)) {
00391 cp++;
00392 }
00393 }
00394 return 1;
00395 }
00396
00424 int
00425 netsnmp_hex_to_binary(u_char ** buf, size_t * buf_len, size_t * offset,
00426 int allow_realloc, const char *hex, const char *delim)
00427 {
00428 int subid = 0;
00429 const char *cp = hex;
00430
00431 if (buf == NULL || buf_len == NULL || offset == NULL || hex == NULL) {
00432 return 0;
00433 }
00434
00435 if ((*cp == '0') && ((*(cp + 1) == 'x') || (*(cp + 1) == 'X'))) {
00436 cp += 2;
00437 }
00438
00439 while (*cp != '\0') {
00440 if (!isxdigit((int) *cp) ||
00441 !isxdigit((int) *(cp+1))) {
00442 if ((NULL != delim) && (NULL != strchr(delim, *cp))) {
00443 cp++;
00444 continue;
00445 }
00446 return 0;
00447 }
00448 if (sscanf(cp, "%2x", &subid) == 0) {
00449 return 0;
00450 }
00451
00452
00453
00454
00455 if ((*offset >= *buf_len) &&
00456 !(allow_realloc && snmp_realloc(buf, buf_len))) {
00457 return 0;
00458 }
00459 *(*buf + *offset) = (u_char) subid;
00460 (*offset)++;
00461 if (*++cp == '\0') {
00462
00463
00464
00465 return 0;
00466 } else {
00467 cp++;
00468 }
00469 }
00470 return 1;
00471 }
00472
00484 int
00485 snmp_hex_to_binary(u_char ** buf, size_t * buf_len, size_t * offset,
00486 int allow_realloc, const char *hex)
00487 {
00488 return netsnmp_hex_to_binary(buf, buf_len, offset, allow_realloc, hex, " ");
00489 }
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499 void
00500 dump_chunk(const char *debugtoken, const char *title, const u_char * buf,
00501 int size)
00502 {
00503 u_int printunit = 64;
00504 char chunk[SNMP_MAXBUF], *s, *sp;
00505
00506 if (title && (*title != '\0')) {
00507 DEBUGMSGTL((debugtoken, "%s\n", title));
00508 }
00509
00510
00511 memset(chunk, 0, SNMP_MAXBUF);
00512 size = binary_to_hex(buf, size, &s);
00513 sp = s;
00514
00515 while (size > 0) {
00516 if (size > (int) printunit) {
00517 strncpy(chunk, sp, printunit);
00518 chunk[printunit] = '\0';
00519 DEBUGMSGTL((debugtoken, "\t%s\n", chunk));
00520 } else {
00521 DEBUGMSGTL((debugtoken, "\t%s\n", sp));
00522 }
00523
00524 sp += printunit;
00525 size -= printunit;
00526 }
00527
00528
00529 SNMP_FREE(s);
00530
00531 }
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589 #ifdef SNMP_TESTING_CODE
00590 char *
00591 dump_snmpEngineID(const u_char * estring, size_t * estring_len)
00592 {
00593 #define eb(b) ( *(esp+b) & 0xff )
00594
00595 int rval = SNMPERR_SUCCESS, gotviolation = 0, slen = 0;
00596 u_int remaining_len;
00597
00598 char buf[SNMP_MAXBUF], *s = NULL, *t;
00599 const u_char *esp = estring;
00600
00601 struct in_addr iaddr;
00602
00603
00604
00605
00606
00607
00608 if (!estring || (*estring_len <= 0)) {
00609 QUITFUN(SNMPERR_GENERR, dump_snmpEngineID_quit);
00610 }
00611 remaining_len = *estring_len;
00612 memset(buf, 0, SNMP_MAXBUF);
00613
00614
00615
00616
00617
00618
00619
00620 if (!(*esp & 0x80)) {
00621 snprint_hexstring(buf, SNMP_MAXBUF, esp, remaining_len);
00622 s = strchr(buf, '\0');
00623 s -= 1;
00624 goto dump_snmpEngineID_quit;
00625 }
00626
00627 s = buf;
00628 s += sprintf(s, "enterprise %d, ", ((*(esp + 0) & 0x7f) << 24) |
00629 ((*(esp + 1) & 0xff) << 16) |
00630 ((*(esp + 2) & 0xff) << 8) | ((*(esp + 3) & 0xff)));
00631
00632
00633
00634
00635 if (remaining_len < 5) {
00636 goto dump_snmpEngineID_quit;
00637 }
00638
00639 esp += 4;
00640 remaining_len -= 5;
00641
00642
00643
00644
00645
00646
00647 switch ((int) *esp++) {
00648 case 1:
00649
00650 if (remaining_len < 4)
00651 goto dump_snmpEngineID_violation;
00652 memcpy(&iaddr.s_addr, esp, 4);
00653
00654 if (!(t = inet_ntoa(iaddr)))
00655 goto dump_snmpEngineID_violation;
00656 s += sprintf(s, "%s", t);
00657
00658 esp += 4;
00659 remaining_len -= 4;
00660 break;
00661
00662 case 2:
00663
00664 if (remaining_len < 16)
00665 goto dump_snmpEngineID_violation;
00666
00667 s += sprintf(s,
00668 "%02X%02X %02X%02X %02X%02X %02X%02X::"
00669 "%02X%02X %02X%02X %02X%02X %02X%02X",
00670 eb(0), eb(1), eb(2), eb(3),
00671 eb(4), eb(5), eb(6), eb(7),
00672 eb(8), eb(9), eb(10), eb(11),
00673 eb(12), eb(13), eb(14), eb(15));
00674
00675 esp += 16;
00676 remaining_len -= 16;
00677 break;
00678
00679 case 3:
00680
00681 if (remaining_len < 6)
00682 goto dump_snmpEngineID_violation;
00683
00684 s += sprintf(s, "%02X:%02X:%02X:%02X:%02X:%02X",
00685 eb(0), eb(1), eb(2), eb(3), eb(4), eb(5));
00686
00687 esp += 6;
00688 remaining_len -= 6;
00689 break;
00690
00691 case 4:
00692
00693
00694
00695
00696
00697
00698
00699 s += sprintf(s, "\"%s\"", esp);
00700 goto dump_snmpEngineID_quit;
00701 break;
00702 case 5:
00703
00704 snprint_hexstring(s, (SNMP_MAXBUF - (s-buf)),
00705 esp, remaining_len);
00706 s = strchr(buf, '\0');
00707 s -= 1;
00708 goto dump_snmpEngineID_quit;
00709 break;
00710 dump_snmpEngineID_violation:
00711 case 0:
00712
00713
00714 gotviolation = 1;
00715 s += sprintf(s, "!!! ");
00716
00717 default:
00718
00719 if (!gotviolation) {
00720 s += sprintf(s, "??? ");
00721 }
00722 snprint_hexstring(s, (SNMP_MAXBUF - (s-buf)),
00723 esp, remaining_len);
00724 s = strchr(buf, '\0');
00725 s -= 1;
00726
00727 goto dump_snmpEngineID_quit;
00728
00729 }
00730
00731
00732
00733
00734
00735
00736
00737 if (remaining_len > 0) {
00738 s += sprintf(s, " (??? ");
00739
00740 snprint_hexstring(s, (SNMP_MAXBUF - (s-buf)),
00741 esp, remaining_len);
00742 s = strchr(buf, '\0');
00743 s -= 1;
00744
00745 s += sprintf(s, ")");
00746 }
00747
00748
00749
00750 dump_snmpEngineID_quit:
00751 if (s) {
00752 slen = s - buf + 1;
00753 s = calloc(1, slen);
00754 memcpy(s, buf, (slen) - 1);
00755 }
00756
00757 memset(buf, 0, SNMP_MAXBUF);
00758
00759 return s;
00760
00761 #undef eb
00762 }
00763 #endif
00764
00765
00770 marker_t
00771 atime_newMarker(void)
00772 {
00773 marker_t pm = (marker_t) calloc(1, sizeof(struct timeval));
00774 gettimeofday((struct timeval *) pm, 0);
00775 return pm;
00776 }
00777
00781 void
00782 atime_setMarker(marker_t pm)
00783 {
00784 if (!pm)
00785 return;
00786
00787 gettimeofday((struct timeval *) pm, 0);
00788 }
00789
00790
00794 long
00795 atime_diff(marker_t first, marker_t second)
00796 {
00797 struct timeval *tv1, *tv2, diff;
00798
00799 tv1 = (struct timeval *) first;
00800 tv2 = (struct timeval *) second;
00801
00802 diff.tv_sec = tv2->tv_sec - tv1->tv_sec - 1;
00803 diff.tv_usec = tv2->tv_usec - tv1->tv_usec + 1000000;
00804
00805 return (diff.tv_sec * 1000 + diff.tv_usec / 1000);
00806 }
00807
00811 u_long
00812 uatime_diff(marker_t first, marker_t second)
00813 {
00814 struct timeval *tv1, *tv2, diff;
00815
00816 tv1 = (struct timeval *) first;
00817 tv2 = (struct timeval *) second;
00818
00819 diff.tv_sec = tv2->tv_sec - tv1->tv_sec - 1;
00820 diff.tv_usec = tv2->tv_usec - tv1->tv_usec + 1000000;
00821
00822 return (((u_long) diff.tv_sec) * 1000 + diff.tv_usec / 1000);
00823 }
00824
00829 u_long
00830 uatime_hdiff(marker_t first, marker_t second)
00831 {
00832 struct timeval *tv1, *tv2, diff;
00833 u_long res;
00834
00835 tv1 = (struct timeval *) first;
00836 tv2 = (struct timeval *) second;
00837
00838 diff.tv_sec = tv2->tv_sec - tv1->tv_sec - 1;
00839 diff.tv_usec = tv2->tv_usec - tv1->tv_usec + 1000000;
00840
00841 res = ((u_long) diff.tv_sec) * 100 + diff.tv_usec / 10000;
00842 return res;
00843 }
00844
00849 int
00850 atime_ready(marker_t pm, int deltaT)
00851 {
00852 marker_t now;
00853 long diff;
00854 if (!pm)
00855 return 0;
00856
00857 now = atime_newMarker();
00858
00859 diff = atime_diff(pm, now);
00860 free(now);
00861 if (diff < deltaT)
00862 return 0;
00863
00864 return 1;
00865 }
00866
00871 int
00872 uatime_ready(marker_t pm, unsigned int deltaT)
00873 {
00874 marker_t now;
00875 u_long diff;
00876 if (!pm)
00877 return 0;
00878
00879 now = atime_newMarker();
00880
00881 diff = uatime_diff(pm, now);
00882 free(now);
00883 if (diff < deltaT)
00884 return 0;
00885
00886 return 1;
00887 }
00888
00889
00890
00891
00892
00893
00897 int
00898 marker_tticks(marker_t pm)
00899 {
00900 int res;
00901 marker_t now = atime_newMarker();
00902
00903 res = atime_diff(pm, now);
00904 free(now);
00905 return res / 10;
00906 }
00907
00908 int
00909 timeval_tticks(struct timeval *tv)
00910 {
00911 return marker_tticks((marker_t) tv);
00912 }
00913
00926 char *netsnmp_getenv(const char *name)
00927 {
00928 #if !defined (WIN32) && !defined (cygwin)
00929 return (getenv(name));
00930 #else
00931 char *temp = NULL;
00932 HKEY hKey;
00933 unsigned char * key_value = NULL;
00934 DWORD key_value_size = 0;
00935 DWORD key_value_type = 0;
00936 DWORD getenv_worked = 0;
00937
00938 DEBUGMSGTL(("read_config", "netsnmp_getenv called with name: %s\n",name));
00939
00940 if (!(name))
00941 return NULL;
00942
00943
00944 temp = getenv(name);
00945 if (temp) {
00946 getenv_worked = 1;
00947 DEBUGMSGTL(("read_config", "netsnmp_getenv will return from ENV: %s\n",temp));
00948 }
00949
00950
00951 if (temp == NULL)
00952 {
00953 if (RegOpenKeyExA(
00954 HKEY_CURRENT_USER,
00955 "SOFTWARE\\Net-SNMP",
00956 0,
00957 KEY_QUERY_VALUE,
00958 &hKey) == ERROR_SUCCESS) {
00959
00960 if (RegQueryValueExA(
00961 hKey,
00962 name,
00963 NULL,
00964 &key_value_type,
00965 NULL,
00966 &key_value_size) == ERROR_SUCCESS) {
00967
00968 if (key_value)
00969 SNMP_FREE(key_value);
00970
00971
00972
00973
00974 key_value = (char *) malloc((sizeof(char) * key_value_size)+sizeof(char));
00975
00976 if (RegQueryValueExA(
00977 hKey,
00978 name,
00979 NULL,
00980 &key_value_type,
00981 key_value,
00982 &key_value_size) == ERROR_SUCCESS) {
00983 }
00984 temp = key_value;
00985 }
00986 RegCloseKey(hKey);
00987 if (temp)
00988 DEBUGMSGTL(("read_config", "netsnmp_getenv will return from HKCU: %s\n",temp));
00989 }
00990 }
00991
00992
00993 if (temp == NULL)
00994 {
00995 if (RegOpenKeyExA(
00996 HKEY_LOCAL_MACHINE,
00997 "SOFTWARE\\Net-SNMP",
00998 0,
00999 KEY_QUERY_VALUE,
01000 &hKey) == ERROR_SUCCESS) {
01001
01002 if (RegQueryValueExA(
01003 hKey,
01004 name,
01005 NULL,
01006 &key_value_type,
01007 NULL,
01008 &key_value_size) == ERROR_SUCCESS) {
01009
01010 if (key_value)
01011 SNMP_FREE(key_value);
01012
01013
01014
01015
01016 key_value = (char *) malloc((sizeof(char) * key_value_size)+sizeof(char));
01017
01018 if (RegQueryValueExA(
01019 hKey,
01020 name,
01021 NULL,
01022 &key_value_type,
01023 key_value,
01024 &key_value_size) == ERROR_SUCCESS) {
01025 }
01026 temp = key_value;
01027
01028 }
01029 RegCloseKey(hKey);
01030 if (temp)
01031 DEBUGMSGTL(("read_config", "netsnmp_getenv will return from HKLM: %s\n",temp));
01032 }
01033 }
01034
01035 if (temp && !getenv_worked) {
01036 setenv(name, temp, 1);
01037 SNMP_FREE(temp);
01038 }
01039
01040 DEBUGMSGTL(("read_config", "netsnmp_getenv returning: %s\n",getenv(name)));
01041
01042 return(getenv(name));
01043 #endif
01044 }
01045
01046
01047
01048
01049 int
01050 netsnmp_addrstr_hton(char *ptr, size_t len)
01051 {
01052 #ifndef WORDS_BIGENDIAN
01053 char tmp[8];
01054
01055 if (8 == len) {
01056 tmp[0] = ptr[6];
01057 tmp[1] = ptr[7];
01058 tmp[2] = ptr[4];
01059 tmp[3] = ptr[5];
01060 tmp[4] = ptr[2];
01061 tmp[5] = ptr[3];
01062 tmp[6] = ptr[0];
01063 tmp[7] = ptr[1];
01064 memcpy (ptr, &tmp, 8);
01065 }
01066 else if (32 == len) {
01067 netsnmp_addrstr_hton(ptr , 8);
01068 netsnmp_addrstr_hton(ptr+8 , 8);
01069 netsnmp_addrstr_hton(ptr+16, 8);
01070 netsnmp_addrstr_hton(ptr+24, 8);
01071 }
01072 else
01073 return -1;
01074 #endif
01075
01076 return 0;
01077 }