/src/net-snmp/snmplib/system.c
| Line | Count | Source (jump to first uncovered line) | 
| 1 |  | /* | 
| 2 |  |  * system.c | 
| 3 |  |  */ | 
| 4 |  | /* Portions of this file are subject to the following copyright(s).  See | 
| 5 |  |  * the Net-SNMP's COPYING file for more details and other copyrights | 
| 6 |  |  * that may apply: | 
| 7 |  |  */ | 
| 8 |  | /*********************************************************** | 
| 9 |  |         Copyright 1992 by Carnegie Mellon University | 
| 10 |  |  | 
| 11 |  |                       All Rights Reserved | 
| 12 |  |  | 
| 13 |  | Permission to use, copy, modify, and distribute this software and its | 
| 14 |  | documentation for any purpose and without fee is hereby granted, | 
| 15 |  | provided that the above copyright notice appear in all copies and that | 
| 16 |  | both that copyright notice and this permission notice appear in | 
| 17 |  | supporting documentation, and that the name of CMU not be | 
| 18 |  | used in advertising or publicity pertaining to distribution of the | 
| 19 |  | software without specific, written prior permission. | 
| 20 |  |  | 
| 21 |  | CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING | 
| 22 |  | ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL | 
| 23 |  | CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR | 
| 24 |  | ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, | 
| 25 |  | WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, | 
| 26 |  | ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS | 
| 27 |  | SOFTWARE. | 
| 28 |  | ******************************************************************/ | 
| 29 |  | /* | 
| 30 |  |  * Portions of this file are copyrighted by: | 
| 31 |  |  * Copyright © 2003 Sun Microsystems, Inc. All rights reserved. | 
| 32 |  |  * Use is subject to license terms specified in the COPYING file | 
| 33 |  |  * distributed with the Net-SNMP package. | 
| 34 |  |  */ | 
| 35 |  | /* | 
| 36 |  |  * Portions of this file are copyrighted by: | 
| 37 |  |  * Copyright (C) 2007 Apple, Inc. All rights reserved. | 
| 38 |  |  * Use is subject to license terms specified in the COPYING file | 
| 39 |  |  * distributed with the Net-SNMP package. | 
| 40 |  |  * | 
| 41 |  |  * Portions of this file are copyrighted by: | 
| 42 |  |  * Copyright (c) 2016 VMware, Inc. All rights reserved. | 
| 43 |  |  * Use is subject to license terms specified in the COPYING file | 
| 44 |  |  * distributed with the Net-SNMP package. | 
| 45 |  |  */ | 
| 46 |  | /* | 
| 47 |  |  * System dependent routines go here | 
| 48 |  |  */ | 
| 49 |  | #include <net-snmp/net-snmp-config.h> | 
| 50 |  | #include <net-snmp/net-snmp-features.h> | 
| 51 |  | #include <stdio.h> | 
| 52 |  | #include <ctype.h> | 
| 53 |  | #include <errno.h> | 
| 54 |  |  | 
| 55 |  | #ifdef HAVE_INTTYPES_H | 
| 56 |  | #include <inttypes.h> | 
| 57 |  | #endif | 
| 58 |  | #ifdef HAVE_IO_H | 
| 59 |  | #include <io.h> | 
| 60 |  | #endif | 
| 61 |  | #ifdef HAVE_DIRECT_H | 
| 62 |  | #include <direct.h> | 
| 63 |  | #endif | 
| 64 |  | #ifdef HAVE_UNISTD_H | 
| 65 |  | #include <unistd.h> | 
| 66 |  | #endif | 
| 67 |  | #ifdef HAVE_STDLIB_H | 
| 68 |  | #include <stdlib.h> | 
| 69 |  | #endif | 
| 70 |  |  | 
| 71 |  | #ifdef TIME_WITH_SYS_TIME | 
| 72 |  | # include <sys/time.h> | 
| 73 |  | # include <time.h> | 
| 74 |  | #else | 
| 75 |  | # ifdef HAVE_SYS_TIME_H | 
| 76 |  | #  include <sys/time.h> | 
| 77 |  | # else | 
| 78 |  | #  include <time.h> | 
| 79 |  | # endif | 
| 80 |  | #endif | 
| 81 |  |  | 
| 82 |  | #include <sys/types.h> | 
| 83 |  |  | 
| 84 |  | #ifdef HAVE_NETINET_IN_H | 
| 85 |  | #include <netinet/in.h> | 
| 86 |  | #endif | 
| 87 |  |  | 
| 88 |  | #ifdef HAVE_SYS_SOCKET_H | 
| 89 |  | #include <sys/socket.h> | 
| 90 |  | #endif | 
| 91 |  | #ifdef HAVE_NET_IF_H | 
| 92 |  | #include <net/if.h> | 
| 93 |  | #endif | 
| 94 |  | #ifdef HAVE_NETDB_H | 
| 95 |  | #include <netdb.h> | 
| 96 |  | #endif | 
| 97 |  |  | 
| 98 |  |  | 
| 99 |  | #ifdef HAVE_SYS_SOCKIO_H | 
| 100 |  | #include <sys/sockio.h> | 
| 101 |  | #endif | 
| 102 |  |  | 
| 103 |  | #ifdef HAVE_SYS_IOCTL_H | 
| 104 |  | #include <sys/ioctl.h> | 
| 105 |  | #endif | 
| 106 |  |  | 
| 107 |  | #ifdef HAVE_NLIST_H | 
| 108 |  | #include <nlist.h> | 
| 109 |  | #endif | 
| 110 |  |  | 
| 111 |  | #ifdef HAVE_SYS_FILE_H | 
| 112 |  | #include <sys/file.h> | 
| 113 |  | #endif | 
| 114 |  |  | 
| 115 |  | #ifdef HAVE_KSTAT_H | 
| 116 |  | #include <kstat.h> | 
| 117 |  | #endif | 
| 118 |  |  | 
| 119 |  | #ifdef HAVE_SYS_PARAM_H | 
| 120 |  | #include <sys/param.h> | 
| 121 |  | #endif | 
| 122 |  | #ifdef HAVE_SYS_SYSCTL_H | 
| 123 |  | #include <sys/sysctl.h> | 
| 124 |  | #endif | 
| 125 |  |  | 
| 126 |  | #ifdef HAVE_STRING_H | 
| 127 |  | #include <string.h> | 
| 128 |  | #else | 
| 129 |  | #include <strings.h> | 
| 130 |  | #endif | 
| 131 |  |  | 
| 132 |  | #ifdef WIN32 | 
| 133 |  | #include <wchar.h>   /* wcsncmp() */ | 
| 134 |  | #include <winperf.h> /* PERF_DATA_BLOCK */ | 
| 135 |  | #endif | 
| 136 |  |  | 
| 137 |  | #ifdef HAVE_SYS_STAT_H | 
| 138 |  | #include <sys/stat.h> | 
| 139 |  | #endif | 
| 140 |  | #ifdef HAVE_FCNTL_H | 
| 141 |  | #include <fcntl.h> | 
| 142 |  | #endif | 
| 143 |  |  | 
| 144 |  | #if defined(hpux10) || defined(hpux11) | 
| 145 |  | #include <sys/pstat.h> | 
| 146 |  | #endif | 
| 147 |  |  | 
| 148 |  | #ifdef HAVE_SYS_UTSNAME_H | 
| 149 |  | #include <sys/utsname.h> | 
| 150 |  | #endif | 
| 151 |  |  | 
| 152 |  | #ifdef HAVE_SYS_SYSTEMCFG_H | 
| 153 |  | #include <sys/systemcfg.h> | 
| 154 |  | #endif | 
| 155 |  |  | 
| 156 |  | #ifdef HAVE_SYS_SYSTEMINFO_H | 
| 157 |  | #include <sys/systeminfo.h> | 
| 158 |  | #endif | 
| 159 |  |  | 
| 160 |  | #ifdef HAVE_CRT_EXTERNS_H | 
| 161 |  | #include <crt_externs.h>        /* for _NSGetArgv() */ | 
| 162 |  | #endif | 
| 163 |  |  | 
| 164 |  | #ifdef HAVE_MACH_O_DYLD_H | 
| 165 |  | #include <mach-o/dyld.h> | 
| 166 |  | #endif | 
| 167 |  |  | 
| 168 |  | #ifdef HAVE_PWD_H | 
| 169 |  | #include <pwd.h> | 
| 170 |  | #endif | 
| 171 |  | #ifdef HAVE_GRP_H | 
| 172 |  | #include <grp.h> | 
| 173 |  | #endif | 
| 174 |  |  | 
| 175 |  | #ifdef HAVE_LIMITS_H | 
| 176 |  | #include <limits.h> | 
| 177 |  | #endif | 
| 178 |  |  | 
| 179 |  | #ifdef HAVE_ARPA_INET_H | 
| 180 |  | #include <arpa/inet.h> | 
| 181 |  | #endif | 
| 182 |  |  | 
| 183 |  | #ifdef DNSSEC_LOCAL_VALIDATION | 
| 184 |  | #if 1 /*HAVE_ARPA_NAMESER_H*/ | 
| 185 |  | #include <arpa/nameser.h> | 
| 186 |  | #endif | 
| 187 |  | #include <validator/validator.h> | 
| 188 |  | /* NetSNMP and DNSSEC-Tools both define FREE. We'll not use either here. */ | 
| 189 |  | #undef FREE | 
| 190 |  | #endif | 
| 191 |  |  | 
| 192 |  | #include <net-snmp/types.h> | 
| 193 |  | #include <net-snmp/output_api.h> | 
| 194 |  | #include <net-snmp/utilities.h> | 
| 195 |  | #include <net-snmp/library/system.h>    /* for "internal" definitions */ | 
| 196 |  |  | 
| 197 |  | #include <net-snmp/library/snmp_api.h> | 
| 198 |  | #include <net-snmp/library/read_config.h> /* for get_temp_file_pattern() */ | 
| 199 |  |  | 
| 200 |  | #include "inet_ntop.h" | 
| 201 |  |  | 
| 202 |  | /* NetSNMP and DNSSEC-Tools both define FREE. We'll not use either here. */ | 
| 203 |  | #undef FREE | 
| 204 |  |  | 
| 205 |  | netsnmp_feature_child_of(system_all, libnetsnmp); | 
| 206 |  |  | 
| 207 |  | netsnmp_feature_child_of(user_information, system_all); | 
| 208 |  | netsnmp_feature_child_of(calculate_sectime_diff, system_all); | 
| 209 |  |  | 
| 210 |  | #ifndef IFF_LOOPBACK | 
| 211 |  | # define IFF_LOOPBACK 0 | 
| 212 |  | #endif | 
| 213 |  |  | 
| 214 |  | #ifdef  INADDR_LOOPBACK | 
| 215 | 0 | # define LOOPBACK    INADDR_LOOPBACK | 
| 216 |  | #else | 
| 217 |  | # define LOOPBACK    0x7f000001 | 
| 218 |  | #endif | 
| 219 |  |  | 
| 220 |  | #ifndef EAI_FAIL | 
| 221 |  | # define EAI_FAIL    -4    /* Non-recoverable failure in name res.  */ | 
| 222 |  | #endif | 
| 223 |  |  | 
| 224 |  | #if defined(HAVE_FORK) | 
| 225 |  | static void | 
| 226 |  | _daemon_prep(int stderr_log) | 
| 227 | 0 | { | 
| 228 | 0 |     int fd; | 
| 229 |  |  | 
| 230 |  |     /* Avoid keeping any directory in use. */ | 
| 231 | 0 |     NETSNMP_IGNORE_RESULT(chdir("/")); | 
| 232 |  | 
 | 
| 233 | 0 |     if (stderr_log) | 
| 234 | 0 |         return; | 
| 235 |  |  | 
| 236 | 0 |     fd = open("/dev/null", O_RDWR); | 
| 237 |  |      | 
| 238 |  |     /* | 
| 239 |  |      * Close inherited file descriptors to avoid | 
| 240 |  |      * keeping unnecessary references. | 
| 241 |  |      */ | 
| 242 | 0 |     close(STDIN_FILENO); | 
| 243 | 0 |     close(STDOUT_FILENO); | 
| 244 | 0 |     close(STDERR_FILENO); | 
| 245 |  |  | 
| 246 |  |     /* | 
| 247 |  |      * Redirect std{in,out,err} to /dev/null, just in case. | 
| 248 |  |      */ | 
| 249 | 0 |     if (fd >= 0) { | 
| 250 | 0 |         dup2(fd, STDIN_FILENO); | 
| 251 | 0 |         dup2(fd, STDOUT_FILENO); | 
| 252 | 0 |         dup2(fd, STDERR_FILENO); | 
| 253 | 0 |         close(fd); | 
| 254 | 0 |     } | 
| 255 | 0 | } | 
| 256 |  | #endif | 
| 257 |  |  | 
| 258 |  | /** | 
| 259 |  |  * fork current process into the background. | 
| 260 |  |  * | 
| 261 |  |  * This function forks a process into the background, in order to | 
| 262 |  |  * become a daemon process. It does a few things along the way: | 
| 263 |  |  * | 
| 264 |  |  * - becoming a process/session group leader, and  forking a second time so | 
| 265 |  |  *   that process/session group leader can exit. | 
| 266 |  |  * | 
| 267 |  |  * - changing the working directory to / | 
| 268 |  |  * | 
| 269 |  |  * - closing stdin, stdout and stderr (unless stderr_log is set) and | 
| 270 |  |  *   redirecting them to /dev/null | 
| 271 |  |  * | 
| 272 |  |  * @param quit_immediately : indicates if the parent process should | 
| 273 |  |  *                           exit after a successful fork. | 
| 274 |  |  * @param stderr_log       : indicates if stderr is being used for | 
| 275 |  |  *                           logging and shouldn't be closed | 
| 276 |  |  * @returns -1 : fork error | 
| 277 |  |  *           0 : child process returning | 
| 278 |  |  *          >0 : parent process returning. returned value is the child PID. | 
| 279 |  |  */ | 
| 280 |  | int | 
| 281 |  | netsnmp_daemonize(int quit_immediately, int stderr_log) | 
| 282 | 0 | { | 
| 283 | 0 |     int i = 0; | 
| 284 | 0 |     DEBUGMSGT(("daemonize","deamonizing...\n")); | 
| 285 | 0 | #ifdef HAVE_FORK | 
| 286 |  | #ifdef HAVE__NSGETEXECUTABLEPATH | 
| 287 |  |      char            path [PATH_MAX] = ""; | 
| 288 |  |      uint32_t        size = sizeof (path); | 
| 289 |  |  | 
| 290 |  |      /* | 
| 291 |  |       * if we are already launched in a "daemonized state", just | 
| 292 |  |       * close & redirect the file descriptors | 
| 293 |  |       */ | 
| 294 |  |      if(getppid() <= 2) { | 
| 295 |  |          _daemon_prep(stderr_log); | 
| 296 |  |          return 0; | 
| 297 |  |      } | 
| 298 |  |  | 
| 299 |  |      if (_NSGetExecutablePath (path, &size)) | 
| 300 |  |          return -1; | 
| 301 |  | #endif | 
| 302 |  |     /* | 
| 303 |  |      * Fork to return control to the invoking process and to | 
| 304 |  |      * guarantee that we aren't a process group leader. | 
| 305 |  |      */ | 
| 306 |  | #ifdef HAVE_FORKALL | 
| 307 |  |     i = forkall(); | 
| 308 |  | #else | 
| 309 | 0 |     i = fork(); | 
| 310 | 0 | #endif | 
| 311 | 0 |     if (i != 0) { | 
| 312 |  |         /* Parent. */ | 
| 313 | 0 |         DEBUGMSGT(("daemonize","first fork returned %d.\n", i)); | 
| 314 | 0 |         if(i == -1) { | 
| 315 | 0 |             snmp_log(LOG_ERR,"first fork failed (errno %d) in " | 
| 316 | 0 |                      "netsnmp_daemonize()\n", errno); | 
| 317 | 0 |             return -1; | 
| 318 | 0 |         } | 
| 319 | 0 |         if (quit_immediately) { | 
| 320 | 0 |             DEBUGMSGT(("daemonize","parent exiting\n")); | 
| 321 | 0 |             exit(0); | 
| 322 | 0 |         } | 
| 323 | 0 |     } else { | 
| 324 |  |         /* Child. */ | 
| 325 | 0 | #ifdef HAVE_SETSID | 
| 326 |  |         /* Become a process/session group leader. */ | 
| 327 | 0 |         setsid(); | 
| 328 | 0 | #endif | 
| 329 |  |         /* | 
| 330 |  |          * Fork to let the process/session group leader exit. | 
| 331 |  |          */ | 
| 332 |  | #ifdef HAVE_FORKALL | 
| 333 |  |   i = forkall(); | 
| 334 |  | #else | 
| 335 | 0 |   i = fork(); | 
| 336 | 0 | #endif | 
| 337 | 0 |         if (i != 0) { | 
| 338 | 0 |             DEBUGMSGT(("daemonize","second fork returned %d.\n", i)); | 
| 339 | 0 |             if(i == -1) { | 
| 340 | 0 |                 snmp_log(LOG_ERR,"second fork failed (errno %d) in " | 
| 341 | 0 |                          "netsnmp_daemonize()\n", errno); | 
| 342 | 0 |             } | 
| 343 |  |             /* Parent. */ | 
| 344 | 0 |             exit(0); | 
| 345 | 0 |         } | 
| 346 | 0 | #ifndef WIN32 | 
| 347 | 0 |         else { | 
| 348 |  |             /* Child. */ | 
| 349 |  |              | 
| 350 | 0 |             DEBUGMSGT(("daemonize","child continuing\n")); | 
| 351 |  | 
 | 
| 352 | 0 | #if !defined(HAVE__NSGETARGV) | 
| 353 | 0 |             _daemon_prep(stderr_log); | 
| 354 |  | #else | 
| 355 |  |              /* | 
| 356 |  |               * Some darwin calls (using mach ports) don't work after | 
| 357 |  |               * a fork. So, now that we've forked, we re-exec ourself | 
| 358 |  |               * to ensure that the child's mach ports are all set up correctly, | 
| 359 |  |               * the getppid call above will prevent the exec child from | 
| 360 |  |               * forking... | 
| 361 |  |               */ | 
| 362 |  |              char * const *argv = *_NSGetArgv (); | 
| 363 |  |              DEBUGMSGT(("daemonize","re-execing forked child\n")); | 
| 364 |  |              execv (path, argv); | 
| 365 |  |              snmp_log(LOG_ERR,"Forked child unable to re-exec - %s.\n", strerror (errno)); | 
| 366 |  |              exit (0); | 
| 367 |  | #endif | 
| 368 | 0 |         } | 
| 369 | 0 | #endif /* !WIN32 */ | 
| 370 | 0 |     } | 
| 371 | 0 | #endif /* HAVE_FORK */ | 
| 372 | 0 |     return i; | 
| 373 | 0 | } | 
| 374 |  |  | 
| 375 |  | /* | 
| 376 |  |  * *********************************************  | 
| 377 |  |  */ | 
| 378 |  | #ifdef              WIN32 | 
| 379 |  | in_addr_t | 
| 380 |  | get_myaddr(void) | 
| 381 |  | { | 
| 382 |  |     char            local_host[130]; | 
| 383 |  |     int             result; | 
| 384 |  |     LPHOSTENT       lpstHostent; | 
| 385 |  |     SOCKADDR_IN     in_addr, remote_in_addr; | 
| 386 |  |     SOCKET          hSock; | 
| 387 |  |     int             nAddrSize = sizeof(SOCKADDR); | 
| 388 |  |  | 
| 389 |  |     in_addr.sin_addr.s_addr = INADDR_ANY; | 
| 390 |  |  | 
| 391 |  |     result = gethostname(local_host, sizeof(local_host)); | 
| 392 |  |     if (result == 0) { | 
| 393 |  |         lpstHostent = gethostbyname((LPSTR) local_host); | 
| 394 |  |         if (lpstHostent) { | 
| 395 |  |             in_addr.sin_addr.s_addr = | 
| 396 |  |                 *((u_long FAR *) (lpstHostent->h_addr)); | 
| 397 |  |             return ((in_addr_t) in_addr.sin_addr.s_addr); | 
| 398 |  |         } | 
| 399 |  |     } | 
| 400 |  |  | 
| 401 |  |     /* | 
| 402 |  |      * if we are here, than we don't have host addr  | 
| 403 |  |      */ | 
| 404 |  |     hSock = socket(AF_INET, SOCK_DGRAM, 0); | 
| 405 |  |     if (hSock != INVALID_SOCKET) { | 
| 406 |  |         /* | 
| 407 |  |          * connect to any port and address  | 
| 408 |  |          */ | 
| 409 |  |         remote_in_addr.sin_family = AF_INET; | 
| 410 |  |         remote_in_addr.sin_port = htons(IPPORT_ECHO); | 
| 411 |  |         remote_in_addr.sin_addr.s_addr = inet_addr("0.0.0.0"); | 
| 412 |  |         result = | 
| 413 |  |             connect(hSock, (LPSOCKADDR) & remote_in_addr, | 
| 414 |  |                     sizeof(SOCKADDR)); | 
| 415 |  |         if (result != SOCKET_ERROR) { | 
| 416 |  |             /* | 
| 417 |  |              * get local ip address  | 
| 418 |  |              */ | 
| 419 |  |             getsockname(hSock, (LPSOCKADDR) & in_addr, | 
| 420 |  |                         (int FAR *) &nAddrSize); | 
| 421 |  |         } | 
| 422 |  |         closesocket(hSock); | 
| 423 |  |     } | 
| 424 |  |     return ((in_addr_t) in_addr.sin_addr.s_addr); | 
| 425 |  | } | 
| 426 |  |  | 
| 427 |  | long | 
| 428 |  | get_uptime(void) | 
| 429 |  | { | 
| 430 |  |     long            return_value = 0; | 
| 431 |  |     DWORD           buffersize = (sizeof(PERF_DATA_BLOCK) + | 
| 432 |  |                                   sizeof(PERF_OBJECT_TYPE)), | 
| 433 |  |         type = REG_EXPAND_SZ; | 
| 434 |  |     PPERF_DATA_BLOCK perfdata = NULL; | 
| 435 |  |  | 
| 436 |  |     /* | 
| 437 |  |      * min requirement is one PERF_DATA_BLOCK plus one PERF_OBJECT_TYPE  | 
| 438 |  |      */ | 
| 439 |  |     perfdata = (PPERF_DATA_BLOCK) malloc(buffersize); | 
| 440 |  |     if (!perfdata) | 
| 441 |  |         return 0; | 
| 442 |  |  | 
| 443 |  |     memset(perfdata, 0, buffersize); | 
| 444 |  |  | 
| 445 |  |     RegQueryValueEx(HKEY_PERFORMANCE_DATA, | 
| 446 |  |                     "Global", NULL, &type, (LPBYTE) perfdata, &buffersize); | 
| 447 |  |  | 
| 448 |  |     /* | 
| 449 |  |      * we can not rely on the return value since there is always more so | 
| 450 |  |      * we check the signature  | 
| 451 |  |      */ | 
| 452 |  |  | 
| 453 |  |     if (wcsncmp(perfdata->Signature, L"PERF", 4) == 0) { | 
| 454 |  |         /* | 
| 455 |  |          * signature ok, and all we need is in the in the PERF_DATA_BLOCK  | 
| 456 |  |          */ | 
| 457 |  |         return_value = (long) ((perfdata->PerfTime100nSec.QuadPart / | 
| 458 |  |                                 (LONGLONG) 100000)); | 
| 459 |  |     } else | 
| 460 |  |         return_value = GetTickCount() / 10; | 
| 461 |  |  | 
| 462 |  |     RegCloseKey(HKEY_PERFORMANCE_DATA); | 
| 463 |  |     free(perfdata); | 
| 464 |  |  | 
| 465 |  |     return return_value; | 
| 466 |  | } | 
| 467 |  |  | 
| 468 |  | char           * | 
| 469 |  | winsock_startup(void) | 
| 470 |  | { | 
| 471 |  |     WORD            VersionRequested; | 
| 472 |  |     WSADATA         stWSAData; | 
| 473 |  |     int             i; | 
| 474 |  |     static char     errmsg[100]; | 
| 475 |  |  | 
| 476 |  |   /* winsock 1: use MAKEWORD(1,1) */ | 
| 477 |  |   /* winsock 2: use MAKEWORD(2,2) */ | 
| 478 |  |  | 
| 479 |  |     VersionRequested = MAKEWORD(2,2); | 
| 480 |  |     i = WSAStartup(VersionRequested, &stWSAData); | 
| 481 |  |     if (i != 0) { | 
| 482 |  |         if (i == WSAVERNOTSUPPORTED) | 
| 483 |  |             sprintf(errmsg, | 
| 484 |  |                     "Unable to init. socket lib, does not support 1.1"); | 
| 485 |  |         else { | 
| 486 |  |             sprintf(errmsg, "Socket Startup error %d", i); | 
| 487 |  |         } | 
| 488 |  |         return (errmsg); | 
| 489 |  |     } | 
| 490 |  |     return (NULL); | 
| 491 |  | } | 
| 492 |  |  | 
| 493 |  | void | 
| 494 |  | winsock_cleanup(void) | 
| 495 |  | { | 
| 496 |  |     WSACleanup(); | 
| 497 |  | } | 
| 498 |  |  | 
| 499 |  | #else                           /* ! WIN32 */ | 
| 500 |  | /*******************************************************************/ | 
| 501 |  |  | 
| 502 |  | /* | 
| 503 |  |  * XXX  What if we have multiple addresses?  Or no addresses for that matter? | 
| 504 |  |  * XXX  Could it be computed once then cached?  Probably not worth it (not | 
| 505 |  |  *                                                           used very often). | 
| 506 |  |  */ | 
| 507 |  | in_addr_t | 
| 508 |  | get_myaddr(void) | 
| 509 | 0 | { | 
| 510 | 0 |     int             sd, i, lastlen = 0; | 
| 511 | 0 |     struct ifconf   ifc; | 
| 512 | 0 |     struct ifreq   *ifrp = NULL; | 
| 513 | 0 |     in_addr_t       addr; | 
| 514 | 0 |     char           *buf = NULL; | 
| 515 |  | 
 | 
| 516 | 0 |     if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { | 
| 517 | 0 |         return 0; | 
| 518 | 0 |     } | 
| 519 |  |  | 
| 520 |  |     /* | 
| 521 |  |      * Cope with lots of interfaces and brokenness of ioctl SIOCGIFCONF on | 
| 522 |  |      * some platforms; see W. R. Stevens, ``Unix Network Programming Volume | 
| 523 |  |      * I'', p.435.   | 
| 524 |  |      */ | 
| 525 |  |  | 
| 526 | 0 |     for (i = 8;; i += 8) { | 
| 527 | 0 |         buf = calloc(i, sizeof(struct ifreq)); | 
| 528 | 0 |         if (buf == NULL) { | 
| 529 | 0 |             close(sd); | 
| 530 | 0 |             return 0; | 
| 531 | 0 |         } | 
| 532 | 0 |         ifc.ifc_len = i * sizeof(struct ifreq); | 
| 533 | 0 |         ifc.ifc_buf = (caddr_t) buf; | 
| 534 |  | 
 | 
| 535 | 0 |         if (ioctl(sd, SIOCGIFCONF, (char *) &ifc) < 0) { | 
| 536 | 0 |             if (errno != EINVAL || lastlen != 0) { | 
| 537 |  |                 /* | 
| 538 |  |                  * Something has gone genuinely wrong.   | 
| 539 |  |                  */ | 
| 540 | 0 |                 free(buf); | 
| 541 | 0 |                 close(sd); | 
| 542 | 0 |                 return 0; | 
| 543 | 0 |             } | 
| 544 |  |             /* | 
| 545 |  |              * Otherwise, it could just be that the buffer is too small.   | 
| 546 |  |              */ | 
| 547 | 0 |         } else { | 
| 548 | 0 |             if (ifc.ifc_len == lastlen) { | 
| 549 |  |                 /* | 
| 550 |  |                  * The length is the same as the last time; we're done.   | 
| 551 |  |                  */ | 
| 552 | 0 |                 break; | 
| 553 | 0 |             } | 
| 554 | 0 |             lastlen = ifc.ifc_len; | 
| 555 | 0 |         } | 
| 556 | 0 |         free(buf); | 
| 557 | 0 |     } | 
| 558 |  |  | 
| 559 | 0 |     for (ifrp = ifc.ifc_req; | 
| 560 | 0 |         (char *)ifrp < (char *)ifc.ifc_req + ifc.ifc_len; | 
| 561 |  | #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN | 
| 562 |  |         ifrp = (struct ifreq *)(((char *) ifrp) + | 
| 563 |  |                                 sizeof(ifrp->ifr_name) + | 
| 564 |  |                                 ifrp->ifr_addr.sa_len) | 
| 565 |  | #else | 
| 566 | 0 |         ifrp++ | 
| 567 | 0 | #endif | 
| 568 | 0 |         ) { | 
| 569 | 0 |         if (ifrp->ifr_addr.sa_family != AF_INET) { | 
| 570 | 0 |             continue; | 
| 571 | 0 |         } | 
| 572 | 0 |         addr = ((struct sockaddr_in *) &(ifrp->ifr_addr))->sin_addr.s_addr; | 
| 573 |  | 
 | 
| 574 | 0 |         if (ioctl(sd, SIOCGIFFLAGS, (char *) ifrp) < 0) { | 
| 575 | 0 |             continue; | 
| 576 | 0 |         } | 
| 577 | 0 |         if ((ifrp->ifr_flags & IFF_UP) | 
| 578 | 0 | #ifdef IFF_RUNNING | 
| 579 | 0 |             && (ifrp->ifr_flags & IFF_RUNNING) | 
| 580 | 0 | #endif                          /* IFF_RUNNING */ | 
| 581 | 0 |             && !(ifrp->ifr_flags & IFF_LOOPBACK) | 
| 582 | 0 |             && addr != LOOPBACK) { | 
| 583 |  |             /* | 
| 584 |  |              * I *really* don't understand why this is necessary.  Perhaps for | 
| 585 |  |              * some broken platform?  Leave it for now.  JBPN   | 
| 586 |  |              */ | 
| 587 | 0 | #ifdef SYS_IOCTL_H_HAS_SIOCGIFADDR | 
| 588 | 0 |             if (ioctl(sd, SIOCGIFADDR, (char *) ifrp) < 0) { | 
| 589 | 0 |                 continue; | 
| 590 | 0 |             } | 
| 591 | 0 |             addr = | 
| 592 | 0 |                 ((struct sockaddr_in *) &(ifrp->ifr_addr))->sin_addr. | 
| 593 | 0 |                 s_addr; | 
| 594 | 0 | #endif | 
| 595 | 0 |             free(buf); | 
| 596 | 0 |             close(sd); | 
| 597 | 0 |             return addr; | 
| 598 | 0 |         } | 
| 599 | 0 |     } | 
| 600 | 0 |     free(buf); | 
| 601 | 0 |     close(sd); | 
| 602 | 0 |     return 0; | 
| 603 | 0 | } | 
| 604 |  |  | 
| 605 |  |  | 
| 606 |  | #if !defined(solaris2) && !defined(linux) && !defined(cygwin) | 
| 607 |  | /* | 
| 608 |  |  * Returns boottime in centiseconds(!). | 
| 609 |  |  *      Caches this for future use. | 
| 610 |  |  */ | 
| 611 |  | long | 
| 612 |  | get_boottime(void) | 
| 613 |  | { | 
| 614 |  |     static long     boottime_csecs = 0; | 
| 615 |  | #if defined(hpux10) || defined(hpux11) | 
| 616 |  |     struct pst_static pst_buf; | 
| 617 |  | #else | 
| 618 |  |     struct timeval  boottime; | 
| 619 |  | #ifdef  NETSNMP_CAN_USE_SYSCTL | 
| 620 |  |     int             mib[2]; | 
| 621 |  |     size_t          len; | 
| 622 |  | #elif defined(NETSNMP_CAN_USE_NLIST) | 
| 623 |  |     int             kmem; | 
| 624 |  | #if !defined(hpux) | 
| 625 |  |     static char boottime_name[] = "_boottime"; | 
| 626 |  | #else | 
| 627 |  |     static char boottime_name[] = "boottime"; | 
| 628 |  | #endif | 
| 629 |  |     static char empty_name[] = ""; | 
| 630 |  |     struct nlist nl[2]; | 
| 631 |  |  | 
| 632 |  |     memset(nl, 0, sizeof(nl)); | 
| 633 |  |     nl[0].n_name = boottime_name; | 
| 634 |  |     nl[1].n_name = empty_name; | 
| 635 |  | #endif                          /* NETSNMP_CAN_USE_SYSCTL */ | 
| 636 |  | #endif                          /* hpux10 || hpux 11 */ | 
| 637 |  |  | 
| 638 |  |  | 
| 639 |  |     if (boottime_csecs != 0) | 
| 640 |  |         return (boottime_csecs); | 
| 641 |  |  | 
| 642 |  | #if defined(hpux10) || defined(hpux11) | 
| 643 |  |     pstat_getstatic(&pst_buf, sizeof(struct pst_static), 1, 0); | 
| 644 |  |     boottime_csecs = pst_buf.boot_time * 100; | 
| 645 |  | #elif defined(NETSNMP_CAN_USE_SYSCTL) | 
| 646 |  |     mib[0] = CTL_KERN; | 
| 647 |  |     mib[1] = KERN_BOOTTIME; | 
| 648 |  |  | 
| 649 |  |     len = sizeof(boottime); | 
| 650 |  |  | 
| 651 |  |     sysctl(mib, 2, &boottime, &len, NULL, 0); | 
| 652 |  |     boottime_csecs = (boottime.tv_sec * 100) + (boottime.tv_usec / 10000); | 
| 653 |  | #elif defined(NETSNMP_CAN_USE_NLIST) | 
| 654 |  |     if ((kmem = open("/dev/kmem", 0)) < 0) | 
| 655 |  |         return 0; | 
| 656 |  |     nlist(KERNEL_LOC, nl); | 
| 657 |  |     if (nl[0].n_type == 0) { | 
| 658 |  |         close(kmem); | 
| 659 |  |         return 0; | 
| 660 |  |     } | 
| 661 |  |  | 
| 662 |  |     lseek(kmem, (long) nl[0].n_value, L_SET); | 
| 663 |  |     read(kmem, &boottime, sizeof(boottime)); | 
| 664 |  |     close(kmem); | 
| 665 |  |     boottime_csecs = (boottime.tv_sec * 100) + (boottime.tv_usec / 10000); | 
| 666 |  | #else | 
| 667 |  |     return 0; | 
| 668 |  | #endif                          /* hpux10 || hpux 11 */ | 
| 669 |  |  | 
| 670 |  |     return (boottime_csecs); | 
| 671 |  | } | 
| 672 |  | #endif | 
| 673 |  |  | 
| 674 |  | /** | 
| 675 |  |  * Returns the system uptime in centiseconds. | 
| 676 |  |  * | 
| 677 |  |  * @note The value returned by this function is not identical to sysUpTime | 
| 678 |  |  *   defined in RFC 1213. get_uptime() returns the system uptime while | 
| 679 |  |  *   sysUpTime represents the time that has elapsed since the most recent | 
| 680 |  |  *   restart of the network manager (snmpd). | 
| 681 |  |  * | 
| 682 |  |  * @see See also netsnmp_get_agent_uptime(). | 
| 683 |  |  */ | 
| 684 |  | long | 
| 685 |  | get_uptime(void) | 
| 686 | 0 | { | 
| 687 |  | #if defined(aix4) || defined(aix5) || defined(aix6) || defined(aix7) | 
| 688 |  |     static char lbolt_name[] = "lbolt"; | 
| 689 |  |     struct nlist nl; | 
| 690 |  |     int kmem; | 
| 691 |  |     time_t lbolt; | 
| 692 |  |     nl.n_name = lbolt_name; | 
| 693 |  |     if(knlist(&nl, 1, sizeof(struct nlist)) != 0) return(0); | 
| 694 |  |     if(nl.n_type == 0 || nl.n_value == 0) return(0); | 
| 695 |  |     if((kmem = open("/dev/mem", 0)) < 0) return 0; | 
| 696 |  |     lseek(kmem, (long) nl.n_value, L_SET); | 
| 697 |  |     read(kmem, &lbolt, sizeof(lbolt)); | 
| 698 |  |     close(kmem); | 
| 699 |  |     return(lbolt); | 
| 700 |  | #elif defined(solaris2) | 
| 701 |  |     kstat_ctl_t    *ksc = kstat_open(); | 
| 702 |  |     kstat_t        *ks; | 
| 703 |  |     kid_t           kid; | 
| 704 |  |     kstat_named_t  *named; | 
| 705 |  |     u_long          lbolt = 0; | 
| 706 |  |  | 
| 707 |  |     if (ksc) { | 
| 708 |  |         ks = kstat_lookup(ksc, NETSNMP_REMOVE_CONST(char *, "unix"), -1, | 
| 709 |  |                           NETSNMP_REMOVE_CONST(char *, "system_misc")); | 
| 710 |  |         if (ks) { | 
| 711 |  |             kid = kstat_read(ksc, ks, NULL); | 
| 712 |  |             if (kid != -1) { | 
| 713 |  |                 named = kstat_data_lookup(ks, NETSNMP_REMOVE_CONST(char *, "lbolt")); | 
| 714 |  |                 if (named) { | 
| 715 |  | #ifdef KSTAT_DATA_UINT32 | 
| 716 |  |                     lbolt = named->value.ui32; | 
| 717 |  | #else | 
| 718 |  |                     lbolt = named->value.ul; | 
| 719 |  | #endif | 
| 720 |  |                 } | 
| 721 |  |             } | 
| 722 |  |         } | 
| 723 |  |         kstat_close(ksc); | 
| 724 |  |     } | 
| 725 |  |     return lbolt; | 
| 726 |  | #elif defined(linux) || defined(cygwin) | 
| 727 | 0 |     FILE           *in = fopen("/proc/uptime", "r"); | 
| 728 | 0 |     long            uptim = 0, a, b; | 
| 729 | 0 |     if (in) { | 
| 730 | 0 |         if (2 == fscanf(in, "%ld.%ld", &a, &b)) | 
| 731 | 0 |             uptim = a * 100 + b; | 
| 732 | 0 |         fclose(in); | 
| 733 | 0 |     } | 
| 734 | 0 |     return uptim; | 
| 735 |  | #else | 
| 736 |  |     struct timeval  now; | 
| 737 |  |     long            boottime_csecs, nowtime_csecs; | 
| 738 |  |  | 
| 739 |  |     boottime_csecs = get_boottime(); | 
| 740 |  |     if (boottime_csecs == 0) | 
| 741 |  |         return 0; | 
| 742 |  |     gettimeofday(&now, (struct timezone *) 0); | 
| 743 |  |     nowtime_csecs = (now.tv_sec * 100) + (now.tv_usec / 10000); | 
| 744 |  |  | 
| 745 |  |     return (nowtime_csecs - boottime_csecs); | 
| 746 |  | #endif | 
| 747 | 0 | } | 
| 748 |  |  | 
| 749 |  | #endif                          /* ! WIN32 */ | 
| 750 |  | /*******************************************************************/ | 
| 751 |  |  | 
| 752 |  | #ifdef DNSSEC_LOCAL_VALIDATION | 
| 753 |  | static val_context_t *_val_context = NULL; | 
| 754 |  |  | 
| 755 |  | static val_context_t * | 
| 756 |  | netsnmp_validator_context(void) | 
| 757 |  | { | 
| 758 |  |     if (NULL == _val_context) { | 
| 759 |  |         int rc; | 
| 760 |  |         char *apptype = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,  | 
| 761 |  |                                               NETSNMP_DS_LIB_APPTYPE); | 
| 762 |  |         DEBUGMSGTL(("dns:sec:context", "creating dnssec context for %s\n", | 
| 763 |  |                     apptype)); | 
| 764 |  |         rc = val_create_context(apptype, &_val_context); | 
| 765 |  |     } | 
| 766 |  |  | 
| 767 |  |     return _val_context; | 
| 768 |  | } | 
| 769 |  | #endif /* DNSSEC_LOCAL_VALIDATION */ | 
| 770 |  |  | 
| 771 |  | int | 
| 772 |  | netsnmp_gethostbyname_v4(const char* name, in_addr_t *addr_out) | 
| 773 | 0 | { | 
| 774 | 0 | #ifdef HAVE_GETADDRINFO | 
| 775 | 0 |     struct addrinfo *addrs = NULL; | 
| 776 | 0 |     struct addrinfo hint; | 
| 777 | 0 |     int             err; | 
| 778 |  | 
 | 
| 779 | 0 |     memset(&hint, 0, sizeof hint); | 
| 780 | 0 |     hint.ai_flags = 0; | 
| 781 | 0 |     hint.ai_family = PF_INET; | 
| 782 | 0 |     hint.ai_socktype = SOCK_DGRAM; | 
| 783 | 0 |     hint.ai_protocol = 0; | 
| 784 |  | 
 | 
| 785 | 0 |     err = netsnmp_getaddrinfo(name, NULL, &hint, &addrs); | 
| 786 | 0 |     if (err != 0) { | 
| 787 | 0 |         return -1; | 
| 788 | 0 |     } | 
| 789 |  |  | 
| 790 | 0 |     if (addrs != NULL) { | 
| 791 | 0 |         memcpy(addr_out, | 
| 792 | 0 |                &((struct sockaddr_in *) addrs->ai_addr)->sin_addr, | 
| 793 | 0 |                sizeof(in_addr_t)); | 
| 794 | 0 |         freeaddrinfo(addrs); | 
| 795 | 0 |     } else { | 
| 796 | 0 |         DEBUGMSGTL(("get_thisaddr", | 
| 797 | 0 |                     "Failed to resolve IPv4 hostname\n")); | 
| 798 | 0 |     } | 
| 799 | 0 |     return 0; | 
| 800 |  | 
 | 
| 801 |  | #elif defined(HAVE_GETHOSTBYNAME) | 
| 802 |  |     struct hostent *hp = NULL; | 
| 803 |  |  | 
| 804 |  |     hp = netsnmp_gethostbyname(name); | 
| 805 |  |     if (hp == NULL) { | 
| 806 |  |         DEBUGMSGTL(("get_thisaddr", | 
| 807 |  |                     "hostname (couldn't resolve)\n")); | 
| 808 |  |         return -1; | 
| 809 |  |     } else if (hp->h_addrtype != AF_INET) { | 
| 810 |  |         DEBUGMSGTL(("get_thisaddr", | 
| 811 |  |                     "hostname (not AF_INET!)\n")); | 
| 812 |  |         return -1; | 
| 813 |  |     } else { | 
| 814 |  |         DEBUGMSGTL(("get_thisaddr", | 
| 815 |  |                     "hostname (resolved okay)\n")); | 
| 816 |  |         memcpy(addr_out, hp->h_addr, sizeof(in_addr_t)); | 
| 817 |  |     } | 
| 818 |  |     return 0; | 
| 819 |  |  | 
| 820 |  | #elif defined(HAVE_GETIPNODEBYNAME) | 
| 821 |  |     struct hostent *hp = NULL; | 
| 822 |  |     int             err; | 
| 823 |  |  | 
| 824 |  |     hp = getipnodebyname(peername, AF_INET, 0, &err); | 
| 825 |  |     if (hp == NULL) { | 
| 826 |  |         DEBUGMSGTL(("get_thisaddr", | 
| 827 |  |                     "hostname (couldn't resolve = %d)\n", err)); | 
| 828 |  |         return -1; | 
| 829 |  |     } | 
| 830 |  |     DEBUGMSGTL(("get_thisaddr", | 
| 831 |  |                 "hostname (resolved okay)\n")); | 
| 832 |  |     memcpy(addr_out, hp->h_addr, sizeof(in_addr_t)); | 
| 833 |  |     return 0; | 
| 834 |  |  | 
| 835 |  | #else /* HAVE_GETIPNODEBYNAME */ | 
| 836 |  |     return -1; | 
| 837 |  | #endif | 
| 838 | 0 | } | 
| 839 |  |  | 
| 840 |  | int | 
| 841 |  | netsnmp_getaddrinfo(const char *name, const char *service, | 
| 842 |  |                     const struct addrinfo *hints, struct addrinfo **res) | 
| 843 | 0 | { | 
| 844 | 0 | #ifdef HAVE_GETADDRINFO | 
| 845 | 0 |     struct addrinfo *addrs = NULL; | 
| 846 | 0 |     struct addrinfo hint; | 
| 847 | 0 |     int             err; | 
| 848 |  | #ifdef DNSSEC_LOCAL_VALIDATION | 
| 849 |  |     val_status_t    val_status; | 
| 850 |  | #endif | 
| 851 |  | 
 | 
| 852 | 0 |     DEBUGMSGTL(("dns:getaddrinfo", "looking up ")); | 
| 853 | 0 |     if (name) | 
| 854 | 0 |         DEBUGMSG(("dns:getaddrinfo", "\"%s\"", name)); | 
| 855 | 0 |     else | 
| 856 | 0 |         DEBUGMSG(("dns:getaddrinfo", "<NULL>")); | 
| 857 |  | 
 | 
| 858 | 0 |     if (service) | 
| 859 | 0 |   DEBUGMSG(("dns:getaddrinfo", ":\"%s\"", service)); | 
| 860 |  | 
 | 
| 861 | 0 |     if (hints) | 
| 862 | 0 |   DEBUGMSG(("dns:getaddrinfo", | 
| 863 | 0 |                   " with hints ({.ai_flags = %#x, .ai_family = %s})", | 
| 864 | 0 |                   hints->ai_flags, hints->ai_family == 0 ? "0" : | 
| 865 | 0 |                   hints->ai_family == AF_INET ? "AF_INET" : | 
| 866 | 0 |                   hints->ai_family == AF_INET6 ? "AF_INET6" : "?")); | 
| 867 | 0 |     else | 
| 868 | 0 |   DEBUGMSG(("dns:getaddrinfo", " with no hint")); | 
| 869 |  | 
 | 
| 870 | 0 |     DEBUGMSG(("dns:getaddrinfo", "\n")); | 
| 871 |  | 
 | 
| 872 | 0 |     if (NULL == hints) { | 
| 873 | 0 |         memset(&hint, 0, sizeof hint); | 
| 874 | 0 |         hint.ai_flags = 0; | 
| 875 | 0 |         hint.ai_family = PF_INET; | 
| 876 | 0 |         hint.ai_socktype = SOCK_DGRAM; | 
| 877 | 0 |         hint.ai_protocol = 0; | 
| 878 | 0 |         hints = &hint; | 
| 879 | 0 |     } else { | 
| 880 | 0 |         memcpy(&hint, hints, sizeof hint); | 
| 881 | 0 |     } | 
| 882 |  | 
 | 
| 883 | 0 | #ifndef DNSSEC_LOCAL_VALIDATION | 
| 884 | 0 |     err = getaddrinfo(name, NULL, &hint, &addrs); | 
| 885 |  | #else /* DNSSEC_LOCAL_VALIDATION */ | 
| 886 |  |     err = val_getaddrinfo(netsnmp_validator_context(), name, NULL, &hint, | 
| 887 |  |                           &addrs, &val_status); | 
| 888 |  |     DEBUGMSGTL(("dns:sec:val", "err %d, val_status %d / %s; trusted: %d\n", | 
| 889 |  |                 err, val_status, p_val_status(val_status), | 
| 890 |  |                 val_istrusted(val_status))); | 
| 891 |  |     if (! val_istrusted(val_status)) { | 
| 892 |  |         int rc; | 
| 893 |  |         if ((err != 0) && VAL_GETADDRINFO_HAS_STATUS(err)) { | 
| 894 |  |             snmp_log(LOG_WARNING, | 
| 895 |  |                      "WARNING: UNTRUSTED error in DNS resolution for %s!\n", | 
| 896 |  |                      name); | 
| 897 |  |             rc = EAI_FAIL; | 
| 898 |  |         } else { | 
| 899 |  |             snmp_log(LOG_WARNING, | 
| 900 |  |                      "The authenticity of DNS response is not trusted (%s)\n", | 
| 901 |  |                      p_val_status(val_status)); | 
| 902 |  |             rc = EAI_NONAME; | 
| 903 |  |         } | 
| 904 |  |         /** continue anyways if DNSSEC_WARN_ONLY is set */ | 
| 905 |  |         if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,  | 
| 906 |  |                                     NETSNMP_DS_LIB_DNSSEC_WARN_ONLY)) | 
| 907 |  |             return rc; | 
| 908 |  |     } | 
| 909 |  |  | 
| 910 |  |  | 
| 911 |  | #endif /* DNSSEC_LOCAL_VALIDATION */ | 
| 912 | 0 |     *res = addrs; | 
| 913 | 0 |     DEBUGIF("dns:getaddrinfo") { | 
| 914 | 0 |         if (err == 0 && addrs && addrs->ai_addr) { | 
| 915 | 0 |             const char *fam = "?"; | 
| 916 | 0 |             char dst[64] = "?"; | 
| 917 | 0 |             uint16_t port = 0; | 
| 918 |  | 
 | 
| 919 | 0 |             switch (addrs->ai_addr->sa_family) { | 
| 920 | 0 |             case AF_INET: { | 
| 921 | 0 |                 struct sockaddr_in *sin = (struct sockaddr_in *)addrs->ai_addr; | 
| 922 |  | 
 | 
| 923 | 0 |                 fam = "AF_INET"; | 
| 924 | 0 |                 inet_ntop(AF_INET, &sin->sin_addr, dst, sizeof(dst)); | 
| 925 | 0 |                 port = ntohs(sin->sin_port); | 
| 926 | 0 |                 break; | 
| 927 | 0 |             } | 
| 928 | 0 |             case AF_INET6: { | 
| 929 | 0 |                 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) | 
| 930 | 0 |                     addrs->ai_addr; | 
| 931 |  | 
 | 
| 932 | 0 |                 fam = "AF_INET6"; | 
| 933 | 0 |                 inet_ntop(AF_INET6, &sin6->sin6_addr, dst, sizeof(dst)); | 
| 934 | 0 |                 port = ntohs(sin6->sin6_port); | 
| 935 | 0 |                 break; | 
| 936 | 0 |             } | 
| 937 | 0 |             } | 
| 938 | 0 |             DEBUGMSGTL(("dns:getaddrinfo", "answer { %s, %s:%hu }\n", fam, dst, | 
| 939 | 0 |                         port)); | 
| 940 | 0 |         } | 
| 941 | 0 |     } | 
| 942 | 0 |     return err; | 
| 943 |  | #else | 
| 944 |  |     NETSNMP_LOGONCE((LOG_ERR, "getaddrinfo not available")); | 
| 945 |  |     return EAI_FAIL; | 
| 946 |  | #endif /* getaddrinfo */ | 
| 947 | 0 | } | 
| 948 |  |  | 
| 949 |  | struct hostent * | 
| 950 |  | netsnmp_gethostbyname(const char *name) | 
| 951 | 0 | { | 
| 952 | 0 | #ifdef HAVE_GETHOSTBYNAME | 
| 953 |  | #ifdef DNSSEC_LOCAL_VALIDATION | 
| 954 |  |     val_status_t val_status; | 
| 955 |  | #endif | 
| 956 | 0 |     struct hostent *hp = NULL; | 
| 957 |  | 
 | 
| 958 | 0 |     if (NULL == name) | 
| 959 | 0 |         return NULL; | 
| 960 |  |  | 
| 961 | 0 |     DEBUGMSGTL(("dns:gethostbyname", "looking up %s\n", name)); | 
| 962 |  | 
 | 
| 963 |  | #ifdef DNSSEC_LOCAL_VALIDATION | 
| 964 |  |     hp  = val_gethostbyname(netsnmp_validator_context(), name, &val_status); | 
| 965 |  |     DEBUGMSGTL(("dns:sec:val", "val_status %d / %s; trusted: %d\n", | 
| 966 |  |                 val_status, p_val_status(val_status), | 
| 967 |  |                 val_istrusted(val_status))); | 
| 968 |  |     if (!val_istrusted(val_status)) { | 
| 969 |  |         snmp_log(LOG_WARNING, | 
| 970 |  |                  "The authenticity of DNS response is not trusted (%s)\n", | 
| 971 |  |                  p_val_status(val_status)); | 
| 972 |  |         /** continue anyways if DNSSEC_WARN_ONLY is set */ | 
| 973 |  |         if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,  | 
| 974 |  |                                     NETSNMP_DS_LIB_DNSSEC_WARN_ONLY)) | 
| 975 |  |             hp = NULL; | 
| 976 |  |     } | 
| 977 |  |     else if (val_does_not_exist(val_status) && hp) | 
| 978 |  |         hp = NULL; | 
| 979 |  | #else | 
| 980 | 0 |     hp = gethostbyname(name); | 
| 981 | 0 | #endif | 
| 982 | 0 |     if (hp == NULL) { | 
| 983 | 0 |         DEBUGMSGTL(("dns:gethostbyname", | 
| 984 | 0 |                     "couldn't resolve %s\n", name)); | 
| 985 | 0 |     } else if (hp->h_addrtype != AF_INET | 
| 986 | 0 | #ifdef AF_INET6 | 
| 987 | 0 |                && hp->h_addrtype != AF_INET6 | 
| 988 | 0 | #endif | 
| 989 | 0 |         ) { | 
| 990 | 0 | #ifdef AF_INET6 | 
| 991 | 0 |         DEBUGMSGTL(("dns:gethostbyname", | 
| 992 | 0 |                     "warning: response for %s not AF_INET/AF_INET6!\n", name)); | 
| 993 |  | #else | 
| 994 |  |         DEBUGMSGTL(("dns:gethostbyname", | 
| 995 |  |                     "warning: response for %s not AF_INET!\n", name)); | 
| 996 |  | #endif | 
| 997 | 0 |     } else { | 
| 998 | 0 |         DEBUGMSGTL(("dns:gethostbyname", | 
| 999 | 0 |                     "%s resolved okay\n", name)); | 
| 1000 | 0 |     } | 
| 1001 | 0 |     return hp; | 
| 1002 |  | #else | 
| 1003 |  |     NETSNMP_LOGONCE((LOG_ERR, "gethostbyname not available")); | 
| 1004 |  |     return NULL; | 
| 1005 |  | #endif /* HAVE_GETHOSTBYNAME */ | 
| 1006 | 0 | } | 
| 1007 |  |  | 
| 1008 |  | /** | 
| 1009 |  |  * Look up the host name via DNS. | 
| 1010 |  |  * | 
| 1011 |  |  * @param[in] addr Pointer to the address to resolve. This argument points e.g. | 
| 1012 |  |  *   to a struct in_addr for AF_INET or to a struct in6_addr for AF_INET6. | 
| 1013 |  |  * @param[in] len  Length in bytes of *addr. | 
| 1014 |  |  * @param[in] type Address family, e.g. AF_INET or AF_INET6. | 
| 1015 |  |  * | 
| 1016 |  |  * @return Pointer to a hostent structure if address lookup succeeded or NULL | 
| 1017 |  |  *   if the lookup failed. | 
| 1018 |  |  * | 
| 1019 |  |  * @see See also the gethostbyaddr() man page. | 
| 1020 |  |  */ | 
| 1021 |  | struct hostent * | 
| 1022 |  | netsnmp_gethostbyaddr(const void *addr, socklen_t len, int type) | 
| 1023 | 0 | { | 
| 1024 | 0 | #ifdef HAVE_GETHOSTBYADDR | 
| 1025 | 0 |     struct hostent *hp = NULL; | 
| 1026 | 0 |     char buf[64]; | 
| 1027 |  | 
 | 
| 1028 | 0 |     DEBUGMSGTL(("dns:gethostbyaddr", "resolving %s\n", | 
| 1029 | 0 |                 inet_ntop(type, addr, buf, sizeof(buf)))); | 
| 1030 |  | 
 | 
| 1031 |  | #ifdef DNSSEC_LOCAL_VALIDATION | 
| 1032 |  |     val_status_t val_status; | 
| 1033 |  |     hp = val_gethostbyaddr(netsnmp_validator_context(), addr, len, type, | 
| 1034 |  |                            &val_status); | 
| 1035 |  |     DEBUGMSGTL(("dns:sec:val", "val_status %d / %s; trusted: %d\n", | 
| 1036 |  |                 val_status, p_val_status(val_status), | 
| 1037 |  |                 val_istrusted(val_status))); | 
| 1038 |  |     if (!val_istrusted(val_status)) { | 
| 1039 |  |         snmp_log(LOG_WARNING, | 
| 1040 |  |                  "The authenticity of DNS response is not trusted (%s)\n", | 
| 1041 |  |                  p_val_status(val_status)); | 
| 1042 |  |         /** continue anyways if DNSSEC_WARN_ONLY is set */ | 
| 1043 |  |         if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,  | 
| 1044 |  |                                     NETSNMP_DS_LIB_DNSSEC_WARN_ONLY)) | 
| 1045 |  |             hp = NULL; | 
| 1046 |  |     } | 
| 1047 |  |     else if (val_does_not_exist(val_status) && hp) | 
| 1048 |  |         hp = NULL; | 
| 1049 |  | #else | 
| 1050 | 0 |     hp = gethostbyaddr(addr, len, type); | 
| 1051 | 0 | #endif | 
| 1052 | 0 |     if (hp == NULL) { | 
| 1053 | 0 |         DEBUGMSGTL(("dns:gethostbyaddr", "couldn't resolve addr\n")); | 
| 1054 | 0 |     } else if (hp->h_addrtype != AF_INET) { | 
| 1055 | 0 |         DEBUGMSGTL(("dns:gethostbyaddr", | 
| 1056 | 0 |                     "warning: response for addr not AF_INET!\n")); | 
| 1057 | 0 |     } else { | 
| 1058 | 0 |         DEBUGMSGTL(("dns:gethostbyaddr", "addr resolved okay\n")); | 
| 1059 | 0 |     } | 
| 1060 | 0 |     return hp; | 
| 1061 |  | #else | 
| 1062 |  |     NETSNMP_LOGONCE((LOG_ERR, "gethostbyaddr not available")); | 
| 1063 |  |     return NULL; | 
| 1064 |  | #endif | 
| 1065 | 0 | } | 
| 1066 |  |  | 
| 1067 |  | /*******************************************************************/ | 
| 1068 |  |  | 
| 1069 |  | #if !defined(HAVE_STRNCASECMP) && !defined(strncasecmp) | 
| 1070 |  |  | 
| 1071 |  | /* | 
| 1072 |  |  * test for NULL pointers before and NULL characters after | 
| 1073 |  |  * * comparing possibly non-NULL strings. | 
| 1074 |  |  * * WARNING: This function does NOT check for array overflow. | 
| 1075 |  |  */ | 
| 1076 |  | int | 
| 1077 |  | strncasecmp(const char *s1, const char *s2, size_t nch) | 
| 1078 |  | { | 
| 1079 |  |     size_t          ii; | 
| 1080 |  |     int             res = -1; | 
| 1081 |  |  | 
| 1082 |  |     if (!s1) { | 
| 1083 |  |         if (!s2) | 
| 1084 |  |             return 0; | 
| 1085 |  |         return (-1); | 
| 1086 |  |     } | 
| 1087 |  |     if (!s2) | 
| 1088 |  |         return (1); | 
| 1089 |  |  | 
| 1090 |  |     for (ii = 0; (ii < nch) && *s1 && *s2; ii++, s1++, s2++) { | 
| 1091 |  |         res = (int) (tolower(*s1) - tolower(*s2)); | 
| 1092 |  |         if (res != 0) | 
| 1093 |  |             break; | 
| 1094 |  |     } | 
| 1095 |  |  | 
| 1096 |  |     if (ii == nch) { | 
| 1097 |  |         s1--; | 
| 1098 |  |         s2--; | 
| 1099 |  |     } | 
| 1100 |  |  | 
| 1101 |  |     if (!*s1) { | 
| 1102 |  |         if (!*s2) | 
| 1103 |  |             return 0; | 
| 1104 |  |         return (-1); | 
| 1105 |  |     } | 
| 1106 |  |     if (!*s2) | 
| 1107 |  |         return (1); | 
| 1108 |  |  | 
| 1109 |  |     return (res); | 
| 1110 |  | } | 
| 1111 |  |  | 
| 1112 |  | int | 
| 1113 |  | strcasecmp(const char *s1, const char *s2) | 
| 1114 |  | { | 
| 1115 |  |     return strncasecmp(s1, s2, 1000000); | 
| 1116 |  | } | 
| 1117 |  |  | 
| 1118 |  | #endif                /* !defined(HAVE_STRNCASECMP) && !defined(strncasecmp) */ | 
| 1119 |  |  | 
| 1120 |  |  | 
| 1121 |  | #ifndef HAVE_STRDUP | 
| 1122 |  | char           * | 
| 1123 |  | strdup(const char *src) | 
| 1124 |  | { | 
| 1125 |  |     int             len; | 
| 1126 |  |     char           *dst; | 
| 1127 |  |  | 
| 1128 |  |     len = strlen(src) + 1; | 
| 1129 |  |     if ((dst = (char *) malloc(len)) == NULL) | 
| 1130 |  |         return (NULL); | 
| 1131 |  |     strcpy(dst, src); | 
| 1132 |  |     return (dst); | 
| 1133 |  | } | 
| 1134 |  | #endif                          /* HAVE_STRDUP */ | 
| 1135 |  |  | 
| 1136 |  | #ifndef HAVE_SETENV | 
| 1137 |  | int | 
| 1138 |  | setenv(const char *name, const char *value, int overwrite) | 
| 1139 |  | { | 
| 1140 |  |     char           *cp; | 
| 1141 |  |     int             ret; | 
| 1142 |  |  | 
| 1143 |  |     if (overwrite == 0) { | 
| 1144 |  |         if (getenv(name)) | 
| 1145 |  |             return 0; | 
| 1146 |  |     } | 
| 1147 |  |     if (asprintf(&cp, "%s=%s", name, value) < 0) | 
| 1148 |  |         return -1; | 
| 1149 |  |     ret = putenv(cp); | 
| 1150 |  | #ifdef WIN32 | 
| 1151 |  |     free(cp); | 
| 1152 |  | #endif | 
| 1153 |  |     return ret; | 
| 1154 |  | } | 
| 1155 |  | #endif                          /* HAVE_SETENV */ | 
| 1156 |  |  | 
| 1157 |  | netsnmp_feature_child_of(calculate_time_diff, netsnmp_unused); | 
| 1158 |  | #ifndef NETSNMP_FEATURE_REMOVE_CALCULATE_TIME_DIFF | 
| 1159 |  | /** | 
| 1160 |  |  * Compute (*now - *then) in centiseconds. | 
| 1161 |  |  */ | 
| 1162 |  | int | 
| 1163 |  | calculate_time_diff(const struct timeval *now, const struct timeval *then) | 
| 1164 | 0 | { | 
| 1165 | 0 |     struct timeval  diff; | 
| 1166 |  | 
 | 
| 1167 | 0 |     NETSNMP_TIMERSUB(now, then, &diff); | 
| 1168 | 0 |     return (int)(diff.tv_sec * 100 + diff.tv_usec / 10000); | 
| 1169 | 0 | } | 
| 1170 |  | #endif /* NETSNMP_FEATURE_REMOVE_CALCULATE_TIME_DIFF */ | 
| 1171 |  |  | 
| 1172 |  | #ifndef NETSNMP_FEATURE_REMOVE_CALCULATE_SECTIME_DIFF | 
| 1173 |  | /** Compute rounded (*now - *then) in seconds. */ | 
| 1174 |  | u_int | 
| 1175 |  | calculate_sectime_diff(const struct timeval *now, const struct timeval *then) | 
| 1176 | 0 | { | 
| 1177 | 0 |     struct timeval  diff; | 
| 1178 |  | 
 | 
| 1179 | 0 |     NETSNMP_TIMERSUB(now, then, &diff); | 
| 1180 | 0 |     return (u_int)(diff.tv_sec + (diff.tv_usec >= 500000L)); | 
| 1181 | 0 | } | 
| 1182 |  | #endif /* NETSNMP_FEATURE_REMOVE_CALCULATE_SECTIME_DIFF */ | 
| 1183 |  |  | 
| 1184 |  | #ifndef HAVE_STRCASESTR | 
| 1185 |  | /* | 
| 1186 |  |  * only glibc2 has this. | 
| 1187 |  |  */ | 
| 1188 |  | char           * | 
| 1189 |  | strcasestr(const char *haystack, const char *needle) | 
| 1190 |  | { | 
| 1191 |  |     const char     *cp1 = haystack, *cp2 = needle; | 
| 1192 |  |     const char     *cx; | 
| 1193 |  |     int             tstch1, tstch2; | 
| 1194 |  |  | 
| 1195 |  |     /* | 
| 1196 |  |      * printf("looking for '%s' in '%s'\n", needle, haystack);  | 
| 1197 |  |      */ | 
| 1198 |  |     if (cp1 && cp2 && *cp1 && *cp2) | 
| 1199 |  |         for (cp1 = haystack, cp2 = needle; *cp1;) { | 
| 1200 |  |             cx = cp1; | 
| 1201 |  |             cp2 = needle; | 
| 1202 |  |             do { | 
| 1203 |  |                 /* | 
| 1204 |  |                  * printf("T'%c' ", *cp1);  | 
| 1205 |  |                  */ | 
| 1206 |  |                 if (!*cp2) {    /* found the needle */ | 
| 1207 |  |                     /* | 
| 1208 |  |                      * printf("\nfound '%s' in '%s'\n", needle, cx);  | 
| 1209 |  |                      */ | 
| 1210 |  |                     return NETSNMP_REMOVE_CONST(char *, cx); | 
| 1211 |  |                 } | 
| 1212 |  |                 if (!*cp1) | 
| 1213 |  |                     break; | 
| 1214 |  |  | 
| 1215 |  |                 tstch1 = toupper(*cp1); | 
| 1216 |  |                 tstch2 = toupper(*cp2); | 
| 1217 |  |                 if (tstch1 != tstch2) | 
| 1218 |  |                     break; | 
| 1219 |  |                 /* | 
| 1220 |  |                  * printf("M'%c' ", *cp1);  | 
| 1221 |  |                  */ | 
| 1222 |  |                 cp1++; | 
| 1223 |  |                 cp2++; | 
| 1224 |  |             } | 
| 1225 |  |             while (1); | 
| 1226 |  |             if (*cp1) | 
| 1227 |  |                 cp1++; | 
| 1228 |  |         } | 
| 1229 |  |     /* | 
| 1230 |  |      * printf("\n");  | 
| 1231 |  |      */ | 
| 1232 |  |     if (cp1 && *cp1) | 
| 1233 |  |         return NETSNMP_REMOVE_CONST(char *, cp1); | 
| 1234 |  |  | 
| 1235 |  |     return NULL; | 
| 1236 |  | } | 
| 1237 |  | #endif | 
| 1238 |  |  | 
| 1239 |  | int | 
| 1240 |  | mkdirhier(const char *pathname, mode_t mode, int skiplast) | 
| 1241 | 0 | { | 
| 1242 | 0 |     struct stat     sbuf; | 
| 1243 | 0 |     char           *ourcopy = strdup(pathname); | 
| 1244 | 0 |     char           *entry; | 
| 1245 | 0 |     char           *buf = NULL; | 
| 1246 | 0 |     char           *st = NULL; | 
| 1247 | 0 |     int             res; | 
| 1248 |  | 
 | 
| 1249 | 0 |     res = SNMPERR_GENERR; | 
| 1250 | 0 |     if (!ourcopy) | 
| 1251 | 0 |         goto out; | 
| 1252 |  |  | 
| 1253 | 0 |     buf = malloc(strlen(pathname) + 2); | 
| 1254 | 0 |     if (!buf) | 
| 1255 | 0 |         goto out; | 
| 1256 |  |  | 
| 1257 |  | #if defined (WIN32) || defined (cygwin) | 
| 1258 |  |     /* convert backslash to forward slash */ | 
| 1259 |  |     for (entry = ourcopy; *entry; entry++) | 
| 1260 |  |         if (*entry == '\\') | 
| 1261 |  |             *entry = '/'; | 
| 1262 |  | #endif | 
| 1263 |  |  | 
| 1264 | 0 |     entry = strtok_r(ourcopy, "/", &st); | 
| 1265 |  | 
 | 
| 1266 | 0 |     buf[0] = '\0'; | 
| 1267 |  | 
 | 
| 1268 |  | #if defined (WIN32) || defined (cygwin) | 
| 1269 |  |     /* | 
| 1270 |  |      * Check if first entry contains a drive-letter | 
| 1271 |  |      *   e.g  "c:/path" | 
| 1272 |  |      */ | 
| 1273 |  |     if ((entry) && (':' == entry[1]) && | 
| 1274 |  |         (('\0' == entry[2]) || ('/' == entry[2]))) { | 
| 1275 |  |         strcat(buf, entry); | 
| 1276 |  |         entry = strtok_r(NULL, "/", &st); | 
| 1277 |  |     } | 
| 1278 |  | #endif | 
| 1279 |  |  | 
| 1280 |  |     /* | 
| 1281 |  |      * check to see if filename is a directory  | 
| 1282 |  |      */ | 
| 1283 | 0 |     while (entry) { | 
| 1284 | 0 |         strcat(buf, "/"); | 
| 1285 | 0 |         strcat(buf, entry); | 
| 1286 | 0 |         entry = strtok_r(NULL, "/", &st); | 
| 1287 | 0 |         if (entry == NULL && skiplast) | 
| 1288 | 0 |             break; | 
| 1289 | 0 |         if (stat(buf, &sbuf) < 0) { | 
| 1290 |  |             /* | 
| 1291 |  |              * DNE, make it  | 
| 1292 |  |              */ | 
| 1293 |  | #ifdef WIN32 | 
| 1294 |  |             if (CreateDirectory(buf, NULL) == 0) | 
| 1295 |  | #else | 
| 1296 | 0 |             if (mkdir(buf, mode) == -1) | 
| 1297 | 0 | #endif | 
| 1298 | 0 |                 goto out; | 
| 1299 | 0 |             else | 
| 1300 | 0 |                 snmp_log(LOG_INFO, "Created directory: %s\n", buf); | 
| 1301 | 0 |         } else { | 
| 1302 |  |             /* | 
| 1303 |  |              * exists, is it a file?  | 
| 1304 |  |              */ | 
| 1305 | 0 |             if ((sbuf.st_mode & S_IFDIR) == 0) { | 
| 1306 |  |                 /* | 
| 1307 |  |                  * ack! can't make a directory on top of a file  | 
| 1308 |  |                  */ | 
| 1309 | 0 |                 goto out; | 
| 1310 | 0 |             } | 
| 1311 | 0 |         } | 
| 1312 | 0 |     } | 
| 1313 | 0 |     res = SNMPERR_SUCCESS; | 
| 1314 | 0 | out: | 
| 1315 | 0 |     free(buf); | 
| 1316 | 0 |     free(ourcopy); | 
| 1317 | 0 |     return res; | 
| 1318 | 0 | } | 
| 1319 |  |  | 
| 1320 |  | /** | 
| 1321 |  |  * netsnmp_mktemp creates a temporary file based on the | 
| 1322 |  |  *                 configured tempFilePattern | 
| 1323 |  |  * | 
| 1324 |  |  * @return file descriptor | 
| 1325 |  |  */ | 
| 1326 |  | const char     * | 
| 1327 |  | netsnmp_mktemp(void) | 
| 1328 | 0 | { | 
| 1329 | 0 | #ifdef PATH_MAX | 
| 1330 | 0 |     static char     name[PATH_MAX]; | 
| 1331 |  | #else | 
| 1332 |  |     static char     name[256]; | 
| 1333 |  | #endif | 
| 1334 | 0 |     int             fd = -1; | 
| 1335 |  | 
 | 
| 1336 | 0 |     strlcpy(name, get_temp_file_pattern(), sizeof(name)); | 
| 1337 | 0 | #ifdef HAVE_MKSTEMP | 
| 1338 | 0 |     { | 
| 1339 | 0 |         mode_t oldmask = umask(~(S_IRUSR | S_IWUSR)); | 
| 1340 | 0 |         netsnmp_assert(oldmask != (mode_t)(-1)); | 
| 1341 | 0 |         fd = mkstemp(name); | 
| 1342 | 0 |         umask(oldmask); | 
| 1343 | 0 |     } | 
| 1344 |  | #else | 
| 1345 |  |     if (mktemp(name)) { | 
| 1346 |  | # ifndef WIN32 | 
| 1347 |  |         fd = open(name, O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWUSR); | 
| 1348 |  | # else | 
| 1349 |  |         /* | 
| 1350 |  |          * Win32 needs _S_IREAD | _S_IWRITE to set permissions on file | 
| 1351 |  |          * after closing | 
| 1352 |  |          */ | 
| 1353 |  |         fd = _open(name, _O_CREAT | _O_EXCL | _O_WRONLY, _S_IREAD | _S_IWRITE); | 
| 1354 |  | # endif | 
| 1355 |  |     } | 
| 1356 |  | #endif | 
| 1357 | 0 |     if (fd >= 0) { | 
| 1358 | 0 |         close(fd); | 
| 1359 | 0 |         DEBUGMSGTL(("netsnmp_mktemp", "temp file created: %s\n", | 
| 1360 | 0 |                     name)); | 
| 1361 | 0 |         return name; | 
| 1362 | 0 |     } | 
| 1363 | 0 |     snmp_log(LOG_ERR, "netsnmp_mktemp: error creating file %s\n", | 
| 1364 | 0 |              name); | 
| 1365 | 0 |     return NULL; | 
| 1366 | 0 | } | 
| 1367 |  |  | 
| 1368 |  | /* | 
| 1369 |  |  * This function was created to differentiate actions | 
| 1370 |  |  * that are appropriate for Linux 2.4 kernels, but not later kernels. | 
| 1371 |  |  * | 
| 1372 |  |  * This function can be used to test kernels on any platform that supports uname(). | 
| 1373 |  |  * | 
| 1374 |  |  * If not running a platform that supports uname(), return -1. | 
| 1375 |  |  * | 
| 1376 |  |  * If ospname matches, and the release matches up through the prefix, | 
| 1377 |  |  *  return 0. | 
| 1378 |  |  * If the release is ordered higher, return 1. | 
| 1379 |  |  * Be aware that "ordered higher" is not a guarantee of correctness. | 
| 1380 |  |  */ | 
| 1381 |  | int | 
| 1382 |  | netsnmp_os_prematch(const char *ospmname, | 
| 1383 |  |                     const char *ospmrelprefix) | 
| 1384 | 0 | { | 
| 1385 | 0 | #ifdef HAVE_SYS_UTSNAME_H | 
| 1386 | 0 |   static int printOSonce = 1; | 
| 1387 | 0 |   struct utsname utsbuf; | 
| 1388 | 0 |   if ( 0 > uname(&utsbuf)) | 
| 1389 | 0 |     return -1; | 
| 1390 |  |  | 
| 1391 | 0 |   if (printOSonce) { | 
| 1392 | 0 |     printOSonce = 0; | 
| 1393 |  |     /* show the four elements that the kernel can be sure of */ | 
| 1394 | 0 |   DEBUGMSGT(("daemonize","sysname '%s',\nrelease '%s',\nversion '%s',\nmachine '%s'\n", | 
| 1395 | 0 |       utsbuf.sysname, utsbuf.release, utsbuf.version, utsbuf.machine)); | 
| 1396 | 0 |   } | 
| 1397 | 0 |   if (0 != strcasecmp(utsbuf.sysname, ospmname)) return -1; | 
| 1398 |  |  | 
| 1399 |  |   /* Required to match only the leading characters */ | 
| 1400 | 0 |   return strncasecmp(utsbuf.release, ospmrelprefix, strlen(ospmrelprefix)); | 
| 1401 |  | 
 | 
| 1402 |  | #else | 
| 1403 |  |  | 
| 1404 |  |   return -1; | 
| 1405 |  |  | 
| 1406 |  | #endif /* HAVE_SYS_UTSNAME_H */ | 
| 1407 | 0 | } | 
| 1408 |  |  | 
| 1409 |  | /** | 
| 1410 |  |  * netsnmp_os_kernel_width determines kernel width at runtime | 
| 1411 |  |  * Currently implemented for IRIX, AIX and Tru64 Unix | 
| 1412 |  |  * | 
| 1413 |  |  * @return kernel width (usually 32 or 64) on success, -1 on error | 
| 1414 |  |  */ | 
| 1415 |  | int | 
| 1416 |  | netsnmp_os_kernel_width(void) | 
| 1417 | 0 | { | 
| 1418 |  | #ifdef irix6 | 
| 1419 |  |   char buf[8]; | 
| 1420 |  |   sysinfo(_MIPS_SI_OS_NAME, buf, 7); | 
| 1421 |  |   if (strncmp("IRIX64", buf, 6) == 0) { | 
| 1422 |  |     return 64; | 
| 1423 |  |   } else if (strncmp("IRIX", buf, 4) == 0) { | 
| 1424 |  |     return 32; | 
| 1425 |  |   } else { | 
| 1426 |  |     return -1; | 
| 1427 |  |   } | 
| 1428 |  | #elif defined(aix4) || defined(aix5) || defined(aix6) || defined(aix7) | 
| 1429 |  |   return (__KERNEL_32() ? 32 : (__KERNEL_64() ? 64 : -1)); | 
| 1430 |  | #elif defined(osf4) || defined(osf5) || defined(__alpha) | 
| 1431 |  |   return 64; /* Alpha is always 64bit */ | 
| 1432 |  | #else | 
| 1433 |  |   /* kernel width detection not implemented */ | 
| 1434 | 0 |   return -1; | 
| 1435 | 0 | #endif | 
| 1436 | 0 | } | 
| 1437 |  |  | 
| 1438 |  | netsnmp_feature_child_of(str_to_uid, user_information); | 
| 1439 |  | #ifndef NETSNMP_FEATURE_REMOVE_STR_TO_UID | 
| 1440 |  | /** | 
| 1441 |  |  * Convert a user name or number into numeric form. | 
| 1442 |  |  * | 
| 1443 |  |  * @param[in] useroruid Either a Unix user name or the ASCII representation | 
| 1444 |  |  *   of a user number. | 
| 1445 |  |  * | 
| 1446 |  |  * @return Either a user number > 0 or 0 if useroruid is not a valid user | 
| 1447 |  |  *   name, not a valid user number or the name of the root user. | 
| 1448 |  |  */ | 
| 1449 | 0 | int netsnmp_str_to_uid(const char *useroruid) { | 
| 1450 | 0 |     int uid; | 
| 1451 | 0 | #if defined(HAVE_GETPWNAM) && defined(HAVE_PWD_H) | 
| 1452 | 0 |     struct passwd *pwd; | 
| 1453 | 0 | #endif | 
| 1454 |  | 
 | 
| 1455 | 0 |     uid = atoi(useroruid); | 
| 1456 |  | 
 | 
| 1457 | 0 |     if (uid == 0) { | 
| 1458 | 0 | #if defined(HAVE_GETPWNAM) && defined(HAVE_PWD_H) | 
| 1459 | 0 |         pwd = getpwnam(useroruid); | 
| 1460 | 0 |         uid = pwd ? pwd->pw_uid : 0; | 
| 1461 | 0 |         endpwent(); | 
| 1462 | 0 | #endif | 
| 1463 | 0 |         if (uid == 0) | 
| 1464 | 0 |             snmp_log(LOG_WARNING, "Can't identify user (%s).\n", useroruid); | 
| 1465 | 0 |     } | 
| 1466 | 0 |     return uid; | 
| 1467 |  |      | 
| 1468 | 0 | } | 
| 1469 |  | #endif /* NETSNMP_FEATURE_REMOVE_STR_TO_UID */ | 
| 1470 |  |  | 
| 1471 |  | netsnmp_feature_child_of(str_to_gid, user_information); | 
| 1472 |  | #ifndef NETSNMP_FEATURE_REMOVE_STR_TO_GID | 
| 1473 |  | /** | 
| 1474 |  |  * Convert a group name or number into numeric form. | 
| 1475 |  |  * | 
| 1476 |  |  * @param[in] grouporgid Either a Unix group name or the ASCII representation | 
| 1477 |  |  *   of a group number. | 
| 1478 |  |  * | 
| 1479 |  |  * @return Either a group number > 0 or 0 if grouporgid is not a valid group | 
| 1480 |  |  *   name, not a valid group number or the root group. | 
| 1481 |  |  */ | 
| 1482 |  | int netsnmp_str_to_gid(const char *grouporgid) | 
| 1483 | 0 | { | 
| 1484 | 0 |     int gid; | 
| 1485 |  | 
 | 
| 1486 | 0 |     gid = atoi(grouporgid); | 
| 1487 |  | 
 | 
| 1488 | 0 |     if (gid == 0) { | 
| 1489 | 0 | #if defined(HAVE_GETGRNAM) && defined(HAVE_GRP_H) | 
| 1490 | 0 |         struct group  *grp; | 
| 1491 |  | 
 | 
| 1492 | 0 |         grp = getgrnam(grouporgid); | 
| 1493 | 0 |         gid = grp ? grp->gr_gid : 0; | 
| 1494 | 0 |         endgrent(); | 
| 1495 | 0 | #endif | 
| 1496 | 0 |         if (gid == 0) | 
| 1497 | 0 |             snmp_log(LOG_WARNING, "Can't identify group (%s).\n", grouporgid); | 
| 1498 | 0 |     } | 
| 1499 |  | 
 | 
| 1500 | 0 |     return gid; | 
| 1501 | 0 | } | 
| 1502 |  | #endif /* NETSNMP_FEATURE_REMOVE_STR_TO_GID */ |