# BRCM_VERSION=3
[bcm963xx.git] / userapps / opensource / net-snmp / snmplib / snmp_parse_args.c
1 #ifdef BRCM_SNMP_CONFIG_SUPPORT
2
3 /*
4  * snmp_parse_args.c
5  */
6
7 #include <net-snmp/net-snmp-config.h>
8
9 #if HAVE_STDLIB_H
10 #include <stdlib.h>
11 #endif
12 #if HAVE_UNISTD_H
13 #include <unistd.h>
14 #endif
15 #if HAVE_STRING_H
16 #include <string.h>
17 #else
18 #include <strings.h>
19 #endif
20 #include <sys/types.h>
21 #include <stdio.h>
22 #if HAVE_UNISTD_H
23 #include <unistd.h>
24 #endif
25 #include <ctype.h>
26 #if HAVE_NETINET_IN_H
27 #include <netinet/in.h>
28 #endif
29 #if TIME_WITH_SYS_TIME
30 # ifdef WIN32
31 #  include <sys/timeb.h>
32 # else
33 #  include <sys/time.h>
34 # endif
35 # include <time.h>
36 #else
37 # if HAVE_SYS_TIME_H
38 #  include <sys/time.h>
39 # else
40 #  include <time.h>
41 # endif
42 #endif
43 #if HAVE_SYS_SELECT_H
44 #include <sys/select.h>
45 #endif
46 #if HAVE_WINSOCK_H
47 #include <winsock.h>
48 #endif
49 #if HAVE_NETDB_H
50 #include <netdb.h>
51 #endif
52 #if HAVE_ARPA_INET_H
53 #include <arpa/inet.h>
54 #endif
55
56 #include <net-snmp/types.h>
57 #include <net-snmp/output_api.h>
58 #include <net-snmp/config_api.h>
59 #include <net-snmp/library/snmp_parse_args.h>   /* for "internal" definitions */
60 #include <net-snmp/utilities.h>
61
62 #include <net-snmp/library/snmp_api.h>
63 #include <net-snmp/library/snmp_client.h>
64 #include <net-snmp/library/mib.h>
65 #include <net-snmp/library/scapi.h>
66 #include <net-snmp/library/keytools.h>
67
68 #include <net-snmp/version.h>
69 #include <net-snmp/library/parse.h>
70 #include <net-snmp/library/snmpv3.h>
71 #include <net-snmp/library/transform_oids.h>
72
73 int             random_access = 0;
74 void
75 snmp_parse_args_usage(FILE * outf)
76 {
77     fprintf(outf, "[OPTIONS] AGENT");
78 }
79
80 void
81 snmp_parse_args_descriptions(FILE * outf)
82 {
83     fprintf(outf, "  Version:  %s\n", netsnmp_get_version());
84     fprintf(outf, "  Web:      http://www.net-snmp.org/\n");
85     fprintf(outf,
86             "  Email:    net-snmp-coders@lists.sourceforge.net\n\nOPTIONS:\n");
87     fprintf(outf, "  -h, --help\t\tdisplay this help message\n");
88     fprintf(outf,
89             "  -H\t\t\tdisplay configuration file directives understood\n");
90     fprintf(outf, "  -v 1|2c|3\t\tspecifies SNMP version to use\n");
91     fprintf(outf, "  -V, --version\t\tdisplay package version number\n");
92     fprintf(outf, "SNMP Version 1 or 2c specific\n");
93     fprintf(outf, "  -c COMMUNITY\t\tset the community string\n");
94     fprintf(outf, "SNMP Version 3 specific\n");
95     fprintf(outf,
96             "  -a PROTOCOL\t\tset authentication protocol (MD5|SHA)\n");
97     fprintf(outf,
98             "  -A PASSPHRASE\t\tset authentication protocol pass phrase\n");
99     fprintf(outf,
100             "  -e ENGINE-ID\t\tset security engine ID (e.g. 800000020109840301)\n");
101     fprintf(outf,
102             "  -E ENGINE-ID\t\tset context engine ID (e.g. 800000020109840301)\n");
103     fprintf(outf,
104             "  -l LEVEL\t\tset security level (noAuthNoPriv|authNoPriv|authPriv)\n");
105     fprintf(outf, "  -n CONTEXT\t\tset context name (e.g. bridge1)\n");
106     fprintf(outf, "  -u USER-NAME\t\tset security name (e.g. bert)\n");
107 #ifdef HAVE_AES
108     fprintf(outf, "  -x PROTOCOL\t\tset privacy protocol (DES|AES)\n");
109 #else
110     fprintf(outf, "  -x PROTOCOL\t\tset privacy protocol (DES)\n");
111 #endif
112     fprintf(outf, "  -X PASSPHRASE\t\tset privacy protocol pass phrase\n");
113     fprintf(outf,
114             "  -Z BOOTS,TIME\t\tset destination engine boots/time\n");
115     fprintf(outf, "General communication options\n");
116     fprintf(outf, "  -r RETRIES\t\tset the number of retries\n");
117     fprintf(outf,
118             "  -t TIMEOUT\t\tset the request timeout (in seconds)\n");
119     fprintf(outf, "Debugging\n");
120     fprintf(outf, "  -d\t\t\tdump input/output packets in hexadecimal\n");
121     fprintf(outf,
122             "  -D TOKEN[,...]\tturn on debugging output for the specified TOKENs\n\t\t\t   (ALL gives extremely verbose debugging output)\n");
123     fprintf(outf, "General options\n");
124     fprintf(outf,
125             "  -m MIB[:...]\t\tload given list of MIBs (ALL loads everything)\n");
126     fprintf(outf,
127             "  -M DIR[:...]\t\tlook in given list of directories for MIBs\n");
128     fprintf(outf,
129             "  -P MIBOPTS\t\tToggle various defaults controlling MIB parsing:\n");
130     snmp_mib_toggle_options_usage("\t\t\t  ", outf);
131     fprintf(outf,
132             "  -O OUTOPTS\t\tToggle various defaults controlling output display:\n");
133     snmp_out_toggle_options_usage("\t\t\t  ", outf);
134     fprintf(outf,
135             "  -I INOPTS\t\tToggle various defaults controlling input parsing:\n");
136     snmp_in_toggle_options_usage("\t\t\t  ", outf);
137     fflush(outf);
138 }
139
140 #define BUF_SIZE 512
141 #endif /* BRCM_SNMP_CONFIG_SUPPORT */
142 void
143 handle_long_opt(const char *myoptarg)
144 {
145     char           *cp, *cp2;
146     /*
147      * else it's a long option, so process it like name=value 
148      */
149     cp = malloc(strlen(myoptarg) + 3);
150     strcpy(cp, myoptarg);
151     cp2 = strchr(cp, '=');
152     if (!cp2 && !strchr(cp, ' ')) {
153         /*
154          * well, they didn't specify an argument as far as we
155          * can tell.  Give them a '1' as the argument (which
156          * works for boolean tokens and a few others) and let
157          * them suffer from there if it's not what they
158          * wanted 
159          */
160         strcat(cp, " 1");
161     } else {
162         /*
163          * replace the '=' with a ' ' 
164          */
165         if (cp2)
166             *cp2 = ' ';
167     }
168     netsnmp_config(cp);
169     free(cp);
170 }
171 #ifdef BRCM_SNMP_CONFIG_SUPPORT
172 extern int      snmpv3_options(char *optarg, netsnmp_session * session,
173                                char **Apsz, char **Xpsz, int argc,
174                                char *const *argv);
175 int
176 snmp_parse_args(int argc,
177                 char *const *argv,
178                 netsnmp_session * session, const char *localOpts,
179                 void (*proc) (int, char *const *, int))
180 {
181     int             arg;
182     char           *cp;
183     char           *Apsz = NULL;
184     char           *Xpsz = NULL;
185     char           *Cpsz = NULL;
186     char            Opts[BUF_SIZE];
187
188     /*
189      * initialize session to default values 
190      */
191     snmp_sess_init(session);
192     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:");
193     if (localOpts)
194         strcat(Opts, localOpts);
195
196     /*
197      * get the options 
198      */
199     DEBUGMSGTL(("snmp_parse_args", "starting: %d/%d\n", optind, argc));
200     for (arg = 0; arg < argc; arg++) {
201         DEBUGMSGTL(("snmp_parse_args", " arg %d = %s\n", arg, argv[arg]));
202     }
203
204     optind = 1;
205     while ((arg = getopt(argc, argv, Opts)) != EOF) {
206         DEBUGMSGTL(("snmp_parse_args", "handling (#%d): %c\n", optind,
207                     arg));
208         switch (arg) {
209         case '-':
210             if (strcasecmp(optarg, "help") == 0) {
211                 return (-1);
212             }
213             if (strcasecmp(optarg, "version") == 0) {
214                 fprintf(stderr, "NET-SNMP version: %s\n",
215                         netsnmp_get_version());
216                 return (-2);
217             }
218
219             handle_long_opt(optarg);
220             break;
221
222         case 'V':
223             fprintf(stderr, "NET-SNMP version: %s\n",
224                     netsnmp_get_version());
225             return (-2);
226
227         case 'h':
228             return (-1);
229             break;
230
231         case 'H':
232             init_snmp("snmpapp");
233             fprintf(stderr, "Configuration directives understood:\n");
234             read_config_print_usage("  ");
235             return (-2);
236
237         case 'Y':
238             netsnmp_config_remember(optarg);
239             break;
240
241         case 'm':
242             setenv("MIBS", optarg, 1);
243             break;
244
245         case 'M':
246             netsnmp_set_mib_directory(optarg);
247             break;
248
249         case 'O':
250             cp = snmp_out_toggle_options(optarg);
251             if (cp != NULL) {
252                 fprintf(stderr,
253                         "Unknown output option passed to -O: %c.\n", *cp);
254                 return (-1);
255             }
256             break;
257
258         case 'I':
259             cp = snmp_in_toggle_options(optarg);
260             if (cp != NULL) {
261                 fprintf(stderr, "Unknown input option passed to -I: %c.\n",
262                         *cp);
263                 return (-1);
264             }
265             break;
266
267         case 'P':
268             cp = snmp_mib_toggle_options(optarg);
269             if (cp != NULL) {
270                 fprintf(stderr,
271                         "Unknown parsing option passed to -P: %c.\n", *cp);
272                 return (-1);
273             }
274             break;
275
276         case 'D':
277             debug_register_tokens(optarg);
278             snmp_set_do_debugging(1);
279             break;
280
281         case 'd':
282             netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, 
283                                    NETSNMP_DS_LIB_DUMP_PACKET, 1);
284             break;
285
286         case 'v':
287             if (!strcmp(optarg, "1")) {
288                 session->version = SNMP_VERSION_1;
289             } else if (!strcasecmp(optarg, "2c")) {
290                 session->version = SNMP_VERSION_2c;
291             } else if (!strcasecmp(optarg, "3")) {
292                 session->version = SNMP_VERSION_3;
293             } else {
294                 fprintf(stderr,
295                         "Invalid version specified after -v flag: %s\n",
296                         optarg);
297                 return (-1);
298             }
299             break;
300
301         case 'p':
302             fprintf(stderr, "Warning: -p option is no longer used - ");
303             fprintf(stderr, "specify the remote host as HOST:PORT\n");
304             return (-1);
305             break;
306
307         case 'T':
308             fprintf(stderr, "Warning: -T option is no longer used - ");
309             fprintf(stderr, "specify the remote host as TRANSPORT:HOST\n");
310             return (-1);
311             break;
312
313         case 't':
314             session->timeout = atoi(optarg) * 1000000L;
315             if (session->timeout < 0 || !isdigit(optarg[0])) {
316                 fprintf(stderr,
317                         "Invalid timeout in seconds after -t flag.\n");
318                 return (-1);
319             }
320             break;
321
322         case 'r':
323             session->retries = atoi(optarg);
324             if (session->retries < 0 || !isdigit(optarg[0])) {
325                 fprintf(stderr,
326                         "Invalid number of retries after -r flag.\n");
327                 return (-1);
328             }
329             break;
330
331         case 'c':
332             Cpsz = optarg;
333             break;
334
335         case '3':
336             if (snmpv3_options(optarg, session, &Apsz, &Xpsz, argc, argv) <
337                 0) {
338                 return (-1);
339             }
340             break;
341
342 #define SNMPV3_CMD_OPTIONS
343 #ifdef  SNMPV3_CMD_OPTIONS
344         case 'Z':
345             session->engineBoots = strtoul(optarg, NULL, 10);
346             if (session->engineBoots == 0 || !isdigit(optarg[0])) {
347                 fprintf(stderr,
348                         "Need engine boots value after -Z flag.\n");
349                 return (-1);
350             }
351             cp = strchr(optarg, ',');
352             if (cp && *(++cp) && isdigit(*cp))
353                 session->engineTime = strtoul(cp, NULL, 10);
354             /*
355              * Handle previous '-Z boot time' syntax 
356              */
357             else if ((optind < argc) && isdigit(argv[optind][0]))
358                 session->engineTime = strtoul(argv[optind], NULL, 10);
359             else {
360                 fprintf(stderr, "Need engine time value after -Z flag.\n");
361                 return (-1);
362             }
363             break;
364
365         case 'e':{
366                 size_t          ebuf_len = 32, eout_len = 0;
367                 u_char         *ebuf = (u_char *) malloc(ebuf_len);
368
369                 if (ebuf == NULL) {
370                     fprintf(stderr,
371                             "malloc failure processing -e flag.\n");
372                     return (-1);
373                 }
374                 if (!snmp_hex_to_binary
375                     (&ebuf, &ebuf_len, &eout_len, 1, optarg)) {
376                     fprintf(stderr,
377                             "Bad engine ID value after -e flag.\n");
378                     free(ebuf);
379                     return (-1);
380                 }
381                 session->securityEngineID = ebuf;
382                 session->securityEngineIDLen = eout_len;
383                 break;
384             }
385
386         case 'E':{
387                 size_t          ebuf_len = 32, eout_len = 0;
388                 u_char         *ebuf = (u_char *) malloc(ebuf_len);
389
390                 if (ebuf == NULL) {
391                     fprintf(stderr,
392                             "malloc failure processing -E flag.\n");
393                     return (-1);
394                 }
395                 if (!snmp_hex_to_binary
396                     (&ebuf, &ebuf_len, &eout_len, 1, optarg)) {
397                     fprintf(stderr,
398                             "Bad engine ID value after -E flag.\n");
399                     free(ebuf);
400                     return (-1);
401                 }
402                 session->contextEngineID = ebuf;
403                 session->contextEngineIDLen = eout_len;
404                 break;
405             }
406
407         case 'n':
408             session->contextName = optarg;
409             session->contextNameLen = strlen(optarg);
410             break;
411
412         case 'u':
413             session->securityName = optarg;
414             session->securityNameLen = strlen(optarg);
415             break;
416
417         case 'l':
418             if (!strcasecmp(optarg, "noAuthNoPriv") || !strcmp(optarg, "1")
419                 || !strcasecmp(optarg, "nanp")) {
420                 session->securityLevel = SNMP_SEC_LEVEL_NOAUTH;
421             } else if (!strcasecmp(optarg, "authNoPriv")
422                        || !strcmp(optarg, "2")
423                        || !strcasecmp(optarg, "anp")) {
424                 session->securityLevel = SNMP_SEC_LEVEL_AUTHNOPRIV;
425             } else if (!strcasecmp(optarg, "authPriv")
426                        || !strcmp(optarg, "3")
427                        || !strcasecmp(optarg, "ap")) {
428                 session->securityLevel = SNMP_SEC_LEVEL_AUTHPRIV;
429             } else {
430                 fprintf(stderr,
431                         "Invalid security level specified after -l flag: %s\n",
432                         optarg);
433                 return (-1);
434             }
435
436             break;
437
438         case 'a':
439             if (!strcasecmp(optarg, "MD5")) {
440                 session->securityAuthProto = usmHMACMD5AuthProtocol;
441                 session->securityAuthProtoLen = USM_AUTH_PROTO_MD5_LEN;
442             } else if (!strcasecmp(optarg, "SHA")) {
443                 session->securityAuthProto = usmHMACSHA1AuthProtocol;
444                 session->securityAuthProtoLen = USM_AUTH_PROTO_SHA_LEN;
445             } else {
446                 fprintf(stderr,
447                         "Invalid authentication protocol specified after -a flag: %s\n",
448                         optarg);
449                 return (-1);
450             }
451             break;
452
453         case 'x':
454             if (!strcasecmp(optarg, "DES")) {
455                 session->securityPrivProto = usmDESPrivProtocol;
456                 session->securityPrivProtoLen = USM_PRIV_PROTO_DES_LEN;
457 #ifdef HAVE_AES
458             } else if (!strcasecmp(optarg, "AES128")) {
459                 session->securityPrivProto = usmAES128PrivProtocol;
460                 session->securityPrivProtoLen = USM_PRIV_PROTO_AES128_LEN;
461             } else if (!strcasecmp(optarg, "AES192")) {
462                 session->securityPrivProto = usmAES192PrivProtocol;
463                 session->securityPrivProtoLen = USM_PRIV_PROTO_AES192_LEN;
464             } else if (!strcasecmp(optarg, "AES256")) {
465                 session->securityPrivProto = usmAES256PrivProtocol;
466                 session->securityPrivProtoLen = USM_PRIV_PROTO_AES256_LEN;
467 #endif
468             } else {
469                 fprintf(stderr,
470                         "Invalid privacy protocol specified after -x flag: %s\n",
471                         optarg);
472                 return (-1);
473             }
474             break;
475
476         case 'A':
477             Apsz = optarg;
478             break;
479
480         case 'X':
481             Xpsz = optarg;
482             break;
483 #endif                          /* SNMPV3_CMD_OPTIONS */
484
485         case '?':
486             return (-1);
487             break;
488
489         default:
490             proc(argc, argv, arg);
491             break;
492         }
493     }
494     DEBUGMSGTL(("snmp_parse_args", "finished: %d/%d\n", optind, argc));
495
496     /*
497      * read in MIB database and initialize the snmp library
498      */
499     init_snmp("snmpapp");
500
501     /*
502      * session default version 
503      */
504     if (session->version == SNMP_DEFAULT_VERSION) {
505         /*
506          * run time default version 
507          */
508         session->version = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, 
509                                               NETSNMP_DS_LIB_SNMPVERSION);
510
511         /*
512          * compile time default version 
513          */
514         if (!session->version) {
515             switch (DEFAULT_SNMP_VERSION) {
516             case 1:
517                 session->version = SNMP_VERSION_1;
518                 break;
519
520             case 2:
521                 session->version = SNMP_VERSION_2c;
522                 break;
523
524             case 3:
525                 session->version = SNMP_VERSION_3;
526                 break;
527             }
528         } else {
529             if (session->version == NETSNMP_DS_SNMP_VERSION_1)  /* bogus value.  version 1 actually = 0 */
530                 session->version = SNMP_VERSION_1;
531         }
532     }
533
534     /*
535      * make master key from pass phrases 
536      */
537     if (Apsz) {
538         session->securityAuthKeyLen = USM_AUTH_KU_LEN;
539         if (session->securityAuthProto == NULL) {
540             /*
541              * get .conf set default 
542              */
543             const oid      *def =
544                 get_default_authtype(&session->securityAuthProtoLen);
545             session->securityAuthProto =
546                 snmp_duplicate_objid(def, session->securityAuthProtoLen);
547         }
548         if (session->securityAuthProto == NULL) {
549             /*
550              * assume MD5 
551              */
552             session->securityAuthProto =
553                 snmp_duplicate_objid(usmHMACMD5AuthProtocol,
554                                      USM_AUTH_PROTO_MD5_LEN);
555             session->securityAuthProtoLen = USM_AUTH_PROTO_MD5_LEN;
556         }
557         if (generate_Ku(session->securityAuthProto,
558                         session->securityAuthProtoLen,
559                         (u_char *) Apsz, strlen(Apsz),
560                         session->securityAuthKey,
561                         &session->securityAuthKeyLen) != SNMPERR_SUCCESS) {
562             snmp_perror(argv[0]);
563             fprintf(stderr,
564                     "Error generating a key (Ku) from the supplied authentication pass phrase. \n");
565             return (-2);
566         }
567     }
568     if (Xpsz) {
569         session->securityPrivKeyLen = USM_PRIV_KU_LEN;
570         if (session->securityPrivProto == NULL) {
571             /*
572              * get .conf set default 
573              */
574             const oid      *def =
575                 get_default_privtype(&session->securityPrivProtoLen);
576             session->securityPrivProto =
577                 snmp_duplicate_objid(def, session->securityPrivProtoLen);
578         }
579         if (session->securityPrivProto == NULL) {
580             /*
581              * assume DES 
582              */
583             session->securityPrivProto =
584                 snmp_duplicate_objid(usmDESPrivProtocol,
585                                      USM_PRIV_PROTO_DES_LEN);
586             session->securityPrivProtoLen = USM_PRIV_PROTO_DES_LEN;
587         }
588         if (generate_Ku(session->securityAuthProto,
589                         session->securityAuthProtoLen,
590                         (u_char *) Xpsz, strlen(Xpsz),
591                         session->securityPrivKey,
592                         &session->securityPrivKeyLen) != SNMPERR_SUCCESS) {
593             snmp_perror(argv[0]);
594             fprintf(stderr,
595                     "Error generating a key (Ku) from the supplied privacy pass phrase. \n");
596             return (-2);
597         }
598     }
599     /*
600      * get the hostname 
601      */
602     if (optind == argc) {
603         fprintf(stderr, "No hostname specified.\n");
604         return (-1);
605     }
606     session->peername = argv[optind++]; /* hostname */
607
608     /*
609      * If v1 or v2c, check community has been set, either by a -c option above,
610      * or via a default token somewhere.  
611      */
612
613     if (session->version == SNMP_VERSION_1 ||
614         session->version == SNMP_VERSION_2c) {
615         if (Cpsz == NULL) {
616             Cpsz = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, 
617                                          NETSNMP_DS_LIB_COMMUNITY);
618         }
619         if (Cpsz == NULL) {
620             fprintf(stderr, "No community name specified.\n");
621             return (-1);
622         }
623         session->community = (unsigned char *) Cpsz;
624         session->community_len = strlen(Cpsz);
625     }
626     return optind;
627 }
628
629 #endif /* BRCM_SNMP_CONFIG_SUPPORT */