net-snmp 5.7
snmp_parse_args.c
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 }