net-snmp 5.7
|
00001 /* 00002 * snmp_parse_args.c 00003 */ 00004 /* Portions of this file are subject to the following copyright(s). See 00005 * the Net-SNMP's COPYING file for more details and other copyrights 00006 * that may apply: 00007 */ 00008 /* 00009 * Portions of this file are copyrighted by: 00010 * Copyright @ 2003 Sun Microsystems, Inc. All rights reserved. 00011 * Use is subject to license terms specified in the COPYING file 00012 * distributed with the Net-SNMP package. 00013 */ 00014 00015 #include <net-snmp/net-snmp-config.h> 00016 #include <errno.h> 00017 00018 #if HAVE_STDLIB_H 00019 #include <stdlib.h> 00020 #endif 00021 #if HAVE_UNISTD_H 00022 #include <unistd.h> 00023 #endif 00024 #if HAVE_STRING_H 00025 #include <string.h> 00026 #else 00027 #include <strings.h> 00028 #endif 00029 #include <sys/types.h> 00030 #include <stdio.h> 00031 #if HAVE_UNISTD_H 00032 #include <unistd.h> 00033 #endif 00034 #include <ctype.h> 00035 #if HAVE_NETINET_IN_H 00036 #include <netinet/in.h> 00037 #endif 00038 #if TIME_WITH_SYS_TIME 00039 # include <sys/time.h> 00040 # include <time.h> 00041 #else 00042 # if HAVE_SYS_TIME_H 00043 # include <sys/time.h> 00044 # else 00045 # include <time.h> 00046 # endif 00047 #endif 00048 #if HAVE_SYS_SELECT_H 00049 #include <sys/select.h> 00050 #endif 00051 #if HAVE_NETDB_H 00052 #include <netdb.h> 00053 #endif 00054 #if HAVE_ARPA_INET_H 00055 #include <arpa/inet.h> 00056 #endif 00057 00058 #include <net-snmp/net-snmp-includes.h> 00059 #include <net-snmp/types.h> 00060 #include <net-snmp/output_api.h> 00061 #include <net-snmp/config_api.h> 00062 #include <net-snmp/library/snmp_parse_args.h> /* for "internal" definitions */ 00063 #include <net-snmp/utilities.h> 00064 00065 #include <net-snmp/library/snmp_api.h> 00066 #include <net-snmp/library/snmp_client.h> 00067 #include <net-snmp/library/mib.h> 00068 #include <net-snmp/library/scapi.h> 00069 #include <net-snmp/library/keytools.h> 00070 00071 #include <net-snmp/version.h> 00072 #include <net-snmp/library/parse.h> 00073 #include <net-snmp/library/snmpv3.h> 00074 #include <net-snmp/library/transform_oids.h> 00075 00076 int random_access = 0; 00077 00078 void 00079 snmp_parse_args_usage(FILE * outf) 00080 { 00081 fprintf(outf, "[OPTIONS] AGENT"); 00082 } 00083 00084 void 00085 snmp_parse_args_descriptions(FILE * outf) 00086 { 00087 fprintf(outf, " Version: %s\n", netsnmp_get_version()); 00088 fprintf(outf, " Web: http://www.net-snmp.org/\n"); 00089 fprintf(outf, 00090 " Email: net-snmp-coders@lists.sourceforge.net\n\nOPTIONS:\n"); 00091 fprintf(outf, " -h, --help\t\tdisplay this help message\n"); 00092 fprintf(outf, 00093 " -H\t\t\tdisplay configuration file directives understood\n"); 00094 fprintf(outf, " -v 1|2c|3\t\tspecifies SNMP version to use\n"); 00095 fprintf(outf, " -V, --version\t\tdisplay package version number\n"); 00096 #if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C) 00097 fprintf(outf, "SNMP Version 1 or 2c specific\n"); 00098 fprintf(outf, " -c COMMUNITY\t\tset the community string\n"); 00099 #endif /* support for community based SNMP */ 00100 fprintf(outf, "SNMP Version 3 specific\n"); 00101 fprintf(outf, 00102 " -a PROTOCOL\t\tset authentication protocol (MD5|SHA)\n"); 00103 fprintf(outf, 00104 " -A PASSPHRASE\t\tset authentication protocol pass phrase\n"); 00105 fprintf(outf, 00106 " -e ENGINE-ID\t\tset security engine ID (e.g. 800000020109840301)\n"); 00107 fprintf(outf, 00108 " -E ENGINE-ID\t\tset context engine ID (e.g. 800000020109840301)\n"); 00109 fprintf(outf, 00110 " -l LEVEL\t\tset security level (noAuthNoPriv|authNoPriv|authPriv)\n"); 00111 fprintf(outf, " -n CONTEXT\t\tset context name (e.g. bridge1)\n"); 00112 fprintf(outf, " -u USER-NAME\t\tset security name (e.g. bert)\n"); 00113 #ifdef HAVE_AES 00114 fprintf(outf, " -x PROTOCOL\t\tset privacy protocol (DES|AES)\n"); 00115 #else 00116 fprintf(outf, " -x PROTOCOL\t\tset privacy protocol (DES)\n"); 00117 #endif 00118 fprintf(outf, " -X PASSPHRASE\t\tset privacy protocol pass phrase\n"); 00119 fprintf(outf, 00120 " -Z BOOTS,TIME\t\tset destination engine boots/time\n"); 00121 fprintf(outf, "General communication options\n"); 00122 fprintf(outf, " -r RETRIES\t\tset the number of retries\n"); 00123 fprintf(outf, 00124 " -t TIMEOUT\t\tset the request timeout (in seconds)\n"); 00125 fprintf(outf, "Debugging\n"); 00126 fprintf(outf, " -d\t\t\tdump input/output packets in hexadecimal\n"); 00127 fprintf(outf, 00128 " -D[TOKEN[,...]]\tturn on debugging output for the specified TOKENs\n\t\t\t (ALL gives extremely verbose debugging output)\n"); 00129 fprintf(outf, "General options\n"); 00130 fprintf(outf, 00131 " -m MIB[:...]\t\tload given list of MIBs (ALL loads everything)\n"); 00132 fprintf(outf, 00133 " -M DIR[:...]\t\tlook in given list of directories for MIBs\n"); 00134 #ifndef NETSNMP_DISABLE_MIB_LOADING 00135 fprintf(outf, 00136 " (default: %s)\n", netsnmp_get_mib_directory()); 00137 fprintf(outf, 00138 " -P MIBOPTS\t\tToggle various defaults controlling MIB parsing:\n"); 00139 snmp_mib_toggle_options_usage("\t\t\t ", outf); 00140 #endif 00141 fprintf(outf, 00142 " -O OUTOPTS\t\tToggle various defaults controlling output display:\n"); 00143 snmp_out_toggle_options_usage("\t\t\t ", outf); 00144 fprintf(outf, 00145 " -I INOPTS\t\tToggle various defaults controlling input parsing:\n"); 00146 snmp_in_toggle_options_usage("\t\t\t ", outf); 00147 fprintf(outf, 00148 " -L LOGOPTS\t\tToggle various defaults controlling logging:\n"); 00149 snmp_log_options_usage("\t\t\t ", outf); 00150 fflush(outf); 00151 } 00152 00153 #define BUF_SIZE 512 00154 00155 void 00156 handle_long_opt(const char *myoptarg) 00157 { 00158 char *cp, *cp2; 00159 /* 00160 * else it's a long option, so process it like name=value 00161 */ 00162 cp = (char *)malloc(strlen(myoptarg) + 3); 00163 if (!cp) 00164 return; 00165 strcpy(cp, myoptarg); 00166 cp2 = strchr(cp, '='); 00167 if (!cp2 && !strchr(cp, ' ')) { 00168 /* 00169 * well, they didn't specify an argument as far as we 00170 * can tell. Give them a '1' as the argument (which 00171 * works for boolean tokens and a few others) and let 00172 * them suffer from there if it's not what they 00173 * wanted 00174 */ 00175 strcat(cp, " 1"); 00176 } else { 00177 /* 00178 * replace the '=' with a ' ' 00179 */ 00180 if (cp2) 00181 *cp2 = ' '; 00182 } 00183 netsnmp_config(cp); 00184 free(cp); 00185 } 00186 00187 extern int snmpv3_options(char *optarg, netsnmp_session * session, 00188 char **Apsz, char **Xpsz, int argc, 00189 char *const *argv); 00190 00191 int 00192 netsnmp_parse_args(int argc, 00193 char **argv, 00194 netsnmp_session * session, const char *localOpts, 00195 void (*proc) (int, char *const *, int), 00196 int flags) 00197 { 00198 static char *sensitive[4] = { NULL, NULL, NULL, NULL }; 00199 int arg, sp = 0, testcase = 0; 00200 char *cp; 00201 char *Apsz = NULL; 00202 char *Xpsz = NULL; 00203 char *Cpsz = NULL; 00204 char Opts[BUF_SIZE]; 00205 int zero_sensitive = !( flags & NETSNMP_PARSE_ARGS_NOZERO ); 00206 00207 /* 00208 * initialize session to default values 00209 */ 00210 snmp_sess_init(session); 00211 strcpy(Opts, "Y:VhHm:M:O:I:P:D:dv:r:t:c:Z:e:E:n:u:l:x:X:a:A:p:T:-:3:s:S:L:"); 00212 if (localOpts) 00213 strcat(Opts, localOpts); 00214 00215 /* 00216 * get the options 00217 */ 00218 DEBUGMSGTL(("snmp_parse_args", "starting: %d/%d\n", optind, argc)); 00219 for (arg = 0; arg < argc; arg++) { 00220 DEBUGMSGTL(("snmp_parse_args", " arg %d = %s\n", arg, argv[arg])); 00221 } 00222 00223 optind = 1; 00224 while ((arg = getopt(argc, argv, Opts)) != EOF) { 00225 DEBUGMSGTL(("snmp_parse_args", "handling (#%d): %c\n", optind, arg)); 00226 switch (arg) { 00227 case '-': 00228 if (strcasecmp(optarg, "help") == 0) { 00229 return (NETSNMP_PARSE_ARGS_ERROR_USAGE); 00230 } 00231 if (strcasecmp(optarg, "version") == 0) { 00232 fprintf(stderr,"NET-SNMP version: %s\n",netsnmp_get_version()); 00233 return (NETSNMP_PARSE_ARGS_SUCCESS_EXIT); 00234 } 00235 00236 handle_long_opt(optarg); 00237 break; 00238 00239 case 'V': 00240 fprintf(stderr, "NET-SNMP version: %s\n", netsnmp_get_version()); 00241 return (NETSNMP_PARSE_ARGS_SUCCESS_EXIT); 00242 00243 case 'h': 00244 return (NETSNMP_PARSE_ARGS_ERROR_USAGE); 00245 break; 00246 00247 case 'H': 00248 init_snmp("snmpapp"); 00249 fprintf(stderr, "Configuration directives understood:\n"); 00250 read_config_print_usage(" "); 00251 return (NETSNMP_PARSE_ARGS_SUCCESS_EXIT); 00252 00253 case 'Y': 00254 netsnmp_config_remember(optarg); 00255 break; 00256 00257 #ifndef NETSNMP_DISABLE_MIB_LOADING 00258 case 'm': 00259 setenv("MIBS", optarg, 1); 00260 break; 00261 00262 case 'M': 00263 netsnmp_get_mib_directory(); /* prepare the default directories */ 00264 netsnmp_set_mib_directory(optarg); 00265 break; 00266 #endif /* NETSNMP_DISABLE_MIB_LOADING */ 00267 00268 case 'O': 00269 cp = snmp_out_toggle_options(optarg); 00270 if (cp != NULL) { 00271 fprintf(stderr, "Unknown output option passed to -O: %c.\n", 00272 *cp); 00273 return (NETSNMP_PARSE_ARGS_ERROR_USAGE); 00274 } 00275 break; 00276 00277 case 'I': 00278 cp = snmp_in_options(optarg, argc, argv); 00279 if (cp != NULL) { 00280 fprintf(stderr, "Unknown input option passed to -I: %c.\n", 00281 *cp); 00282 return (NETSNMP_PARSE_ARGS_ERROR_USAGE); 00283 } 00284 break; 00285 00286 #ifndef NETSNMP_DISABLE_MIB_LOADING 00287 case 'P': 00288 cp = snmp_mib_toggle_options(optarg); 00289 if (cp != NULL) { 00290 fprintf(stderr, 00291 "Unknown parsing option passed to -P: %c.\n", *cp); 00292 return (NETSNMP_PARSE_ARGS_ERROR_USAGE); 00293 } 00294 break; 00295 #endif /* NETSNMP_DISABLE_MIB_LOADING */ 00296 00297 case 'D': 00298 debug_register_tokens(optarg); 00299 snmp_set_do_debugging(1); 00300 break; 00301 00302 case 'd': 00303 netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, 00304 NETSNMP_DS_LIB_DUMP_PACKET, 1); 00305 break; 00306 00307 case 'v': 00308 session->version = -1; 00309 #ifndef NETSNMP_DISABLE_SNMPV1 00310 if (!strcmp(optarg, "1")) { 00311 session->version = SNMP_VERSION_1; 00312 } 00313 #endif 00314 #ifndef NETSNMP_DISABLE_SNMPV2C 00315 if (!strcasecmp(optarg, "2c")) { 00316 session->version = SNMP_VERSION_2c; 00317 } 00318 #endif 00319 if (!strcasecmp(optarg, "3")) { 00320 session->version = SNMP_VERSION_3; 00321 } 00322 if (session->version == -1) { 00323 fprintf(stderr, 00324 "Invalid version specified after -v flag: %s\n", 00325 optarg); 00326 return (NETSNMP_PARSE_ARGS_ERROR_USAGE); 00327 } 00328 break; 00329 00330 case 'p': 00331 fprintf(stderr, "Warning: -p option is no longer used - "); 00332 fprintf(stderr, "specify the remote host as HOST:PORT\n"); 00333 return (NETSNMP_PARSE_ARGS_ERROR_USAGE); 00334 break; 00335 00336 case 'T': 00337 { 00338 char leftside[SNMP_MAXBUF_MEDIUM], rightside[SNMP_MAXBUF_MEDIUM]; 00339 char *tmpcp, *tmpopt; 00340 00341 /* ensure we have a proper argument */ 00342 tmpopt = strdup(optarg); 00343 tmpcp = strchr(tmpopt, '='); 00344 if (!tmpcp) { 00345 fprintf(stderr, "-T expects a NAME=VALUE pair.\n"); 00346 return (NETSNMP_PARSE_ARGS_ERROR_USAGE); 00347 } 00348 *tmpcp++ = '\0'; 00349 00350 /* create the transport config container if this is the first */ 00351 if (!session->transport_configuration) { 00352 netsnmp_container_init_list(); 00353 session->transport_configuration = 00354 netsnmp_container_find("transport_configuration:fifo"); 00355 if (!session->transport_configuration) { 00356 fprintf(stderr, "failed to initialize the transport configuration container\n"); 00357 free(tmpopt); 00358 return (NETSNMP_PARSE_ARGS_ERROR); 00359 } 00360 00361 session->transport_configuration->compare = 00362 (netsnmp_container_compare*) 00363 netsnmp_transport_config_compare; 00364 } 00365 00366 /* set the config */ 00367 strncpy(leftside, tmpopt, sizeof(leftside)); 00368 leftside[sizeof(leftside)-1] = '0'; 00369 strncpy(rightside, tmpcp, sizeof(rightside)); 00370 rightside[sizeof(rightside)-1] = '0'; 00371 00372 CONTAINER_INSERT(session->transport_configuration, 00373 netsnmp_transport_create_config(leftside, 00374 rightside)); 00375 free(tmpopt); 00376 } 00377 break; 00378 00379 case 't': 00380 session->timeout = (long)(atof(optarg) * 1000000L); 00381 if (session->timeout <= 0) { 00382 fprintf(stderr, "Invalid timeout in seconds after -t flag.\n"); 00383 return (NETSNMP_PARSE_ARGS_ERROR_USAGE); 00384 } 00385 break; 00386 00387 case 'r': 00388 session->retries = atoi(optarg); 00389 if (session->retries < 0 || !isdigit((unsigned char)(optarg[0]))) { 00390 fprintf(stderr, "Invalid number of retries after -r flag.\n"); 00391 return (NETSNMP_PARSE_ARGS_ERROR_USAGE); 00392 } 00393 break; 00394 00395 case 'c': 00396 if (zero_sensitive) { 00397 if ((sensitive[sp] = strdup(optarg)) != NULL) { 00398 Cpsz = sensitive[sp]; 00399 memset(optarg, '\0', strlen(optarg)); 00400 sp++; 00401 } else { 00402 fprintf(stderr, "malloc failure processing -c flag.\n"); 00403 return NETSNMP_PARSE_ARGS_ERROR; 00404 } 00405 } else { 00406 Cpsz = optarg; 00407 } 00408 break; 00409 00410 case '3': 00411 /* TODO: This needs to zero things too. */ 00412 if (snmpv3_options(optarg, session, &Apsz, &Xpsz, argc, argv) < 0){ 00413 return (NETSNMP_PARSE_ARGS_ERROR_USAGE); 00414 } 00415 break; 00416 00417 case 'L': 00418 if (snmp_log_options(optarg, argc, argv) < 0) { 00419 return (NETSNMP_PARSE_ARGS_ERROR_USAGE); 00420 } 00421 break; 00422 00423 #define SNMPV3_CMD_OPTIONS 00424 #ifdef SNMPV3_CMD_OPTIONS 00425 case 'Z': 00426 errno = 0; 00427 session->engineBoots = strtoul(optarg, &cp, 10); 00428 if (errno || cp == optarg) { 00429 fprintf(stderr, "Need engine boots value after -Z flag.\n"); 00430 return (NETSNMP_PARSE_ARGS_ERROR_USAGE); 00431 } 00432 if (*cp == ',') { 00433 char *endptr; 00434 cp++; 00435 session->engineTime = strtoul(cp, &endptr, 10); 00436 if (errno || cp == endptr) { 00437 fprintf(stderr, "Need engine time after \"-Z engineBoot,\".\n"); 00438 return (NETSNMP_PARSE_ARGS_ERROR_USAGE); 00439 } 00440 } 00441 /* 00442 * Handle previous '-Z boot time' syntax 00443 */ 00444 else if (optind < argc) { 00445 session->engineTime = strtoul(argv[optind], &cp, 10); 00446 if (errno || cp == argv[optind]) { 00447 fprintf(stderr, "Need engine time after \"-Z engineBoot\".\n"); 00448 return (NETSNMP_PARSE_ARGS_ERROR_USAGE); 00449 } 00450 } else { 00451 fprintf(stderr, "Need engine time after \"-Z engineBoot\".\n"); 00452 return (NETSNMP_PARSE_ARGS_ERROR_USAGE); 00453 } 00454 break; 00455 00456 case 'e':{ 00457 size_t ebuf_len = 32, eout_len = 0; 00458 u_char *ebuf = (u_char *)malloc(ebuf_len); 00459 00460 if (ebuf == NULL) { 00461 fprintf(stderr, "malloc failure processing -e flag.\n"); 00462 return (NETSNMP_PARSE_ARGS_ERROR); 00463 } 00464 if (!snmp_hex_to_binary 00465 (&ebuf, &ebuf_len, &eout_len, 1, optarg)) { 00466 fprintf(stderr, "Bad engine ID value after -e flag.\n"); 00467 free(ebuf); 00468 return (NETSNMP_PARSE_ARGS_ERROR_USAGE); 00469 } 00470 if ((eout_len < 5) || (eout_len > 32)) { 00471 fprintf(stderr, "Invalid engine ID value after -e flag.\n"); 00472 free(ebuf); 00473 return (NETSNMP_PARSE_ARGS_ERROR_USAGE); 00474 } 00475 session->securityEngineID = ebuf; 00476 session->securityEngineIDLen = eout_len; 00477 break; 00478 } 00479 00480 case 'E':{ 00481 size_t ebuf_len = 32, eout_len = 0; 00482 u_char *ebuf = (u_char *)malloc(ebuf_len); 00483 00484 if (ebuf == NULL) { 00485 fprintf(stderr, "malloc failure processing -E flag.\n"); 00486 return (NETSNMP_PARSE_ARGS_ERROR); 00487 } 00488 if (!snmp_hex_to_binary(&ebuf, &ebuf_len, 00489 &eout_len, 1, optarg)) { 00490 fprintf(stderr, "Bad engine ID value after -E flag.\n"); 00491 free(ebuf); 00492 return (NETSNMP_PARSE_ARGS_ERROR_USAGE); 00493 } 00494 if ((eout_len < 5) || (eout_len > 32)) { 00495 fprintf(stderr, "Invalid engine ID value after -E flag.\n"); 00496 free(ebuf); 00497 return (NETSNMP_PARSE_ARGS_ERROR_USAGE); 00498 } 00499 session->contextEngineID = ebuf; 00500 session->contextEngineIDLen = eout_len; 00501 break; 00502 } 00503 00504 case 'n': 00505 session->contextName = optarg; 00506 session->contextNameLen = strlen(optarg); 00507 break; 00508 00509 case 'u': 00510 if (zero_sensitive) { 00511 if ((sensitive[sp] = strdup(optarg)) != NULL) { 00512 session->securityName = sensitive[sp]; 00513 session->securityNameLen = strlen(sensitive[sp]); 00514 memset(optarg, '\0', strlen(optarg)); 00515 sp++; 00516 } else { 00517 fprintf(stderr, "malloc failure processing -u flag.\n"); 00518 return NETSNMP_PARSE_ARGS_ERROR; 00519 } 00520 } else { 00521 session->securityName = optarg; 00522 session->securityNameLen = strlen(optarg); 00523 } 00524 break; 00525 00526 case 'l': 00527 if (!strcasecmp(optarg, "noAuthNoPriv") || !strcmp(optarg, "1") 00528 || !strcasecmp(optarg, "noauth") 00529 || !strcasecmp(optarg, "nanp")) { 00530 session->securityLevel = SNMP_SEC_LEVEL_NOAUTH; 00531 } else if (!strcasecmp(optarg, "authNoPriv") 00532 || !strcmp(optarg, "2") 00533 || !strcasecmp(optarg, "auth") 00534 || !strcasecmp(optarg, "anp")) { 00535 session->securityLevel = SNMP_SEC_LEVEL_AUTHNOPRIV; 00536 } else if (!strcasecmp(optarg, "authPriv") 00537 || !strcmp(optarg, "3") 00538 || !strcasecmp(optarg, "priv") 00539 || !strcasecmp(optarg, "ap")) { 00540 session->securityLevel = SNMP_SEC_LEVEL_AUTHPRIV; 00541 } else { 00542 fprintf(stderr, 00543 "Invalid security level specified after -l flag: %s\n", 00544 optarg); 00545 return (NETSNMP_PARSE_ARGS_ERROR_USAGE); 00546 } 00547 00548 break; 00549 00550 #ifdef NETSNMP_SECMOD_USM 00551 case 'a': 00552 #ifndef NETSNMP_DISABLE_MD5 00553 if (!strcasecmp(optarg, "MD5")) { 00554 session->securityAuthProto = usmHMACMD5AuthProtocol; 00555 session->securityAuthProtoLen = USM_AUTH_PROTO_MD5_LEN; 00556 } else 00557 #endif 00558 if (!strcasecmp(optarg, "SHA")) { 00559 session->securityAuthProto = usmHMACSHA1AuthProtocol; 00560 session->securityAuthProtoLen = USM_AUTH_PROTO_SHA_LEN; 00561 } else { 00562 fprintf(stderr, 00563 "Invalid authentication protocol specified after -a flag: %s\n", 00564 optarg); 00565 return (NETSNMP_PARSE_ARGS_ERROR_USAGE); 00566 } 00567 break; 00568 00569 case 'x': 00570 testcase = 0; 00571 #ifndef NETSNMP_DISABLE_DES 00572 if (!strcasecmp(optarg, "DES")) { 00573 testcase = 1; 00574 session->securityPrivProto = usmDESPrivProtocol; 00575 session->securityPrivProtoLen = USM_PRIV_PROTO_DES_LEN; 00576 } 00577 #endif 00578 #ifdef HAVE_AES 00579 if (!strcasecmp(optarg, "AES128") || 00580 !strcasecmp(optarg, "AES")) { 00581 testcase = 1; 00582 session->securityPrivProto = usmAESPrivProtocol; 00583 session->securityPrivProtoLen = USM_PRIV_PROTO_AES_LEN; 00584 } 00585 #endif 00586 if (testcase == 0) { 00587 fprintf(stderr, 00588 "Invalid privacy protocol specified after -x flag: %s\n", 00589 optarg); 00590 return (NETSNMP_PARSE_ARGS_ERROR_USAGE); 00591 } 00592 break; 00593 00594 case 'A': 00595 if (zero_sensitive) { 00596 if ((sensitive[sp] = strdup(optarg)) != NULL) { 00597 Apsz = sensitive[sp]; 00598 memset(optarg, '\0', strlen(optarg)); 00599 sp++; 00600 } else { 00601 fprintf(stderr, "malloc failure processing -A flag.\n"); 00602 return NETSNMP_PARSE_ARGS_ERROR; 00603 } 00604 } else { 00605 Apsz = optarg; 00606 } 00607 break; 00608 00609 case 'X': 00610 if (zero_sensitive) { 00611 if ((sensitive[sp] = strdup(optarg)) != NULL) { 00612 Xpsz = sensitive[sp]; 00613 memset(optarg, '\0', strlen(optarg)); 00614 sp++; 00615 } else { 00616 fprintf(stderr, "malloc failure processing -X flag.\n"); 00617 return NETSNMP_PARSE_ARGS_ERROR; 00618 } 00619 } else { 00620 Xpsz = optarg; 00621 } 00622 break; 00623 #endif /* SNMPV3_CMD_OPTIONS */ 00624 #endif /* NETSNMP_SECMOD_USM */ 00625 00626 case '?': 00627 return (NETSNMP_PARSE_ARGS_ERROR_USAGE); 00628 break; 00629 00630 default: 00631 proc(argc, argv, arg); 00632 break; 00633 } 00634 } 00635 DEBUGMSGTL(("snmp_parse_args", "finished: %d/%d\n", optind, argc)); 00636 00637 /* 00638 * read in MIB database and initialize the snmp library 00639 */ 00640 init_snmp("snmpapp"); 00641 00642 /* 00643 * session default version 00644 */ 00645 if (session->version == SNMP_DEFAULT_VERSION) { 00646 /* 00647 * run time default version 00648 */ 00649 session->version = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, 00650 NETSNMP_DS_LIB_SNMPVERSION); 00651 00652 /* 00653 * compile time default version 00654 */ 00655 if (!session->version) { 00656 switch (NETSNMP_DEFAULT_SNMP_VERSION) { 00657 #ifndef NETSNMP_DISABLE_SNMPV1 00658 case 1: 00659 session->version = SNMP_VERSION_1; 00660 break; 00661 #endif 00662 00663 #ifndef NETSNMP_DISABLE_SNMPV2C 00664 case 2: 00665 session->version = SNMP_VERSION_2c; 00666 break; 00667 #endif 00668 00669 case 3: 00670 session->version = SNMP_VERSION_3; 00671 break; 00672 00673 default: 00674 snmp_log(LOG_ERR, "Can't determine a valid SNMP version for the session\n"); 00675 return(NETSNMP_PARSE_ARGS_ERROR); 00676 } 00677 } else { 00678 #ifndef NETSNMP_DISABLE_SNMPV1 00679 if (session->version == NETSNMP_DS_SNMP_VERSION_1) /* bogus value. version 1 actually = 0 */ 00680 session->version = SNMP_VERSION_1; 00681 #endif 00682 } 00683 } 00684 00685 #ifdef NETSNMP_SECMOD_USM 00686 /* XXX: this should ideally be moved to snmpusm.c somehow */ 00687 00688 /* 00689 * make master key from pass phrases 00690 */ 00691 if (Apsz) { 00692 session->securityAuthKeyLen = USM_AUTH_KU_LEN; 00693 if (session->securityAuthProto == NULL) { 00694 /* 00695 * get .conf set default 00696 */ 00697 const oid *def = 00698 get_default_authtype(&session->securityAuthProtoLen); 00699 session->securityAuthProto = 00700 snmp_duplicate_objid(def, session->securityAuthProtoLen); 00701 } 00702 if (session->securityAuthProto == NULL) { 00703 #ifndef NETSNMP_DISABLE_MD5 00704 /* 00705 * assume MD5 00706 */ 00707 session->securityAuthProto = 00708 snmp_duplicate_objid(usmHMACMD5AuthProtocol, 00709 USM_AUTH_PROTO_MD5_LEN); 00710 session->securityAuthProtoLen = USM_AUTH_PROTO_MD5_LEN; 00711 #else 00712 session->securityAuthProto = 00713 snmp_duplicate_objid(usmHMACSHA1AuthProtocol, 00714 USM_AUTH_PROTO_SHA_LEN); 00715 session->securityAuthProtoLen = USM_AUTH_PROTO_SHA_LEN; 00716 #endif 00717 } 00718 if (generate_Ku(session->securityAuthProto, 00719 session->securityAuthProtoLen, 00720 (u_char *) Apsz, strlen(Apsz), 00721 session->securityAuthKey, 00722 &session->securityAuthKeyLen) != SNMPERR_SUCCESS) { 00723 snmp_perror(argv[0]); 00724 fprintf(stderr, 00725 "Error generating a key (Ku) from the supplied authentication pass phrase. \n"); 00726 return (NETSNMP_PARSE_ARGS_ERROR); 00727 } 00728 } 00729 if (Xpsz) { 00730 session->securityPrivKeyLen = USM_PRIV_KU_LEN; 00731 if (session->securityPrivProto == NULL) { 00732 /* 00733 * get .conf set default 00734 */ 00735 const oid *def = 00736 get_default_privtype(&session->securityPrivProtoLen); 00737 session->securityPrivProto = 00738 snmp_duplicate_objid(def, session->securityPrivProtoLen); 00739 } 00740 if (session->securityPrivProto == NULL) { 00741 /* 00742 * assume DES 00743 */ 00744 #ifndef NETSNMP_DISABLE_DES 00745 session->securityPrivProto = 00746 snmp_duplicate_objid(usmDESPrivProtocol, 00747 USM_PRIV_PROTO_DES_LEN); 00748 session->securityPrivProtoLen = USM_PRIV_PROTO_DES_LEN; 00749 #else 00750 session->securityPrivProto = 00751 snmp_duplicate_objid(usmAESPrivProtocol, 00752 USM_PRIV_PROTO_AES_LEN); 00753 session->securityPrivProtoLen = USM_PRIV_PROTO_AES_LEN; 00754 #endif 00755 00756 } 00757 if (generate_Ku(session->securityAuthProto, 00758 session->securityAuthProtoLen, 00759 (u_char *) Xpsz, strlen(Xpsz), 00760 session->securityPrivKey, 00761 &session->securityPrivKeyLen) != SNMPERR_SUCCESS) { 00762 snmp_perror(argv[0]); 00763 fprintf(stderr, 00764 "Error generating a key (Ku) from the supplied privacy pass phrase. \n"); 00765 return (NETSNMP_PARSE_ARGS_ERROR); 00766 } 00767 } 00768 #endif /* NETSNMP_SECMOD_USM */ 00769 00770 /* 00771 * get the hostname 00772 */ 00773 if (optind == argc) { 00774 fprintf(stderr, "No hostname specified.\n"); 00775 return (NETSNMP_PARSE_ARGS_ERROR_USAGE); 00776 } 00777 session->peername = argv[optind++]; /* hostname */ 00778 00779 #if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C) 00780 /* 00781 * If v1 or v2c, check community has been set, either by a -c option above, 00782 * or via a default token somewhere. 00783 * If neither, it will be taken from the incoming request PDU. 00784 */ 00785 00786 #if defined(NETSNMP_DISABLE_SNMPV1) 00787 if (session->version == SNMP_VERSION_2c) 00788 #else 00789 #if defined(NETSNMP_DISABLE_SNMPV2C) 00790 if (session->version == SNMP_VERSION_1) 00791 #else 00792 if (session->version == SNMP_VERSION_1 || 00793 session->version == SNMP_VERSION_2c) 00794 #endif 00795 #endif 00796 { 00797 if (Cpsz == NULL) { 00798 Cpsz = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, 00799 NETSNMP_DS_LIB_COMMUNITY); 00800 if (Cpsz == NULL) { 00801 if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 00802 NETSNMP_DS_LIB_IGNORE_NO_COMMUNITY)){ 00803 DEBUGMSGTL(("snmp_parse_args", 00804 "ignoring that the community string is not present\n")); 00805 session->community = NULL; 00806 session->community_len = 0; 00807 } else { 00808 fprintf(stderr, "No community name specified.\n"); 00809 return (NETSNMP_PARSE_ARGS_ERROR_USAGE); 00810 } 00811 } 00812 } else { 00813 session->community = (unsigned char *)Cpsz; 00814 session->community_len = strlen(Cpsz); 00815 } 00816 } 00817 #endif /* support for community based SNMP */ 00818 00819 return optind; 00820 } 00821 00822 int 00823 snmp_parse_args(int argc, 00824 char **argv, 00825 netsnmp_session * session, const char *localOpts, 00826 void (*proc) (int, char *const *, int)) 00827 { 00828 return netsnmp_parse_args(argc, argv, session, localOpts, proc, 0); 00829 }