Coverage Report

Created: 2025-05-08 06:18

/src/net-snmp/snmplib/snmp_parse_args.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * snmp_parse_args.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
 * Portions of this file are copyrighted by:
10
 * Copyright @ 2003 Sun Microsystems, Inc. All rights reserved.
11
 * Use is subject to license terms specified in the COPYING file
12
 * distributed with the Net-SNMP package.
13
 *
14
 * Portions of this file are copyrighted by:
15
 * Copyright (c) 2016 VMware, Inc. All rights reserved.
16
 * Use is subject to license terms specified in the COPYING file
17
 * distributed with the Net-SNMP package.
18
 */
19
20
#include <net-snmp/net-snmp-config.h>
21
#include <errno.h>
22
23
#ifdef HAVE_STDLIB_H
24
#include <stdlib.h>
25
#endif
26
#ifdef HAVE_UNISTD_H
27
#include <unistd.h>
28
#endif
29
#ifdef HAVE_STRING_H
30
#include <string.h>
31
#else
32
#include <strings.h>
33
#endif
34
#include <sys/types.h>
35
#include <stdio.h>
36
#ifdef HAVE_UNISTD_H
37
#include <unistd.h>
38
#endif
39
#include <ctype.h>
40
#ifdef HAVE_NETINET_IN_H
41
#include <netinet/in.h>
42
#endif
43
#ifdef TIME_WITH_SYS_TIME
44
# include <sys/time.h>
45
# include <time.h>
46
#else
47
# ifdef HAVE_SYS_TIME_H
48
#  include <sys/time.h>
49
# else
50
#  include <time.h>
51
# endif
52
#endif
53
#ifdef HAVE_SYS_SELECT_H
54
#include <sys/select.h>
55
#endif
56
#ifdef HAVE_NETDB_H
57
#include <netdb.h>
58
#endif
59
#ifdef HAVE_ARPA_INET_H
60
#include <arpa/inet.h>
61
#endif
62
63
#include <net-snmp/net-snmp-includes.h>
64
#include <net-snmp/types.h>
65
#include <net-snmp/output_api.h>
66
#include <net-snmp/config_api.h>
67
#include <net-snmp/library/snmpv3.h>
68
#include <net-snmp/library/snmp_parse_args.h>   /* for "internal" definitions */
69
#include <net-snmp/utilities.h>
70
71
#include <net-snmp/library/snmp_api.h>
72
#include <net-snmp/library/snmp_client.h>
73
#include <net-snmp/library/mib.h>
74
#include <net-snmp/library/scapi.h>
75
#include <net-snmp/library/keytools.h>
76
77
#include <net-snmp/version.h>
78
#include <net-snmp/library/parse.h>
79
#include <net-snmp/library/snmpv3.h>
80
#include <net-snmp/library/transform_oids.h>
81
82
void
83
snmp_parse_args_usage(FILE * outf)
84
0
{
85
0
    fprintf(outf, "[OPTIONS] AGENT");
86
0
}
87
88
void
89
snmp_parse_args_descriptions(FILE * outf)
90
0
{
91
0
    fprintf(outf, "  Version:  %s\n", netsnmp_get_version());
92
0
    fprintf(outf, "  Web:      http://www.net-snmp.org/\n");
93
0
    fprintf(outf,
94
0
            "  Email:    net-snmp-coders@lists.sourceforge.net\n\nOPTIONS:\n");
95
0
    fprintf(outf, "  -h, --help\t\tdisplay this help message\n");
96
0
    fprintf(outf,
97
0
            "  -H\t\t\tdisplay configuration file directives understood\n");
98
0
    fprintf(outf, "  -v 1|2c|3\t\tspecifies SNMP version to use\n");
99
0
    fprintf(outf, "  -V, --version\t\tdisplay package version number\n");
100
0
#if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)
101
0
    fprintf(outf, "SNMP Version 1 or 2c specific\n");
102
0
    fprintf(outf, "  -c COMMUNITY\t\tset the community string\n");
103
0
#endif /* support for community based SNMP */
104
0
    fprintf(outf, "SNMP Version 3 specific\n");
105
0
    fprintf(outf,
106
0
            "  -a PROTOCOL\t\tset authentication protocol (MD5|SHA|SHA-224|SHA-256|SHA-384|SHA-512)\n");
107
0
    fprintf(outf,
108
0
            "  -A PASSPHRASE\t\tset authentication protocol pass phrase\n");
109
0
    fprintf(outf,
110
0
            "  -e ENGINE-ID\t\tset security engine ID (e.g. 800000020109840301)\n");
111
0
    fprintf(outf,
112
0
            "  -E ENGINE-ID\t\tset context engine ID (e.g. 800000020109840301)\n");
113
0
    fprintf(outf,
114
0
            "  -l LEVEL\t\tset security level (noAuthNoPriv|authNoPriv|authPriv)\n");
115
0
    fprintf(outf, "  -n CONTEXT\t\tset context name (e.g. bridge1)\n");
116
0
    fprintf(outf, "  -u USER-NAME\t\tset security name (e.g. bert)\n");
117
0
#ifdef HAVE_AES
118
0
    fprintf(outf, "  -x PROTOCOL\t\tset privacy protocol (DES|AES"
119
0
#ifdef NETSNMP_DRAFT_BLUMENTHAL_AES_04
120
0
            "|AES-192|AES-256"
121
0
#endif
122
0
            ")\n");
123
#else
124
    fprintf(outf, "  -x PROTOCOL\t\tset privacy protocol (DES)\n");
125
#endif
126
0
    fprintf(outf, "  -X PASSPHRASE\t\tset privacy protocol pass phrase\n");
127
0
    fprintf(outf,
128
0
            "  -Z BOOTS,TIME\t\tset destination engine boots/time\n");
129
0
    fprintf(outf, "General communication options\n");
130
0
    fprintf(outf, "  -r RETRIES\t\tset the number of retries\n");
131
0
    fprintf(outf,
132
0
            "  -t TIMEOUT\t\tset the request timeout (in seconds)\n");
133
0
    fprintf(outf, "Debugging\n");
134
0
    fprintf(outf, "  -d\t\t\tdump input/output packets in hexadecimal\n");
135
0
#ifndef NETSNMP_DISABLE_DEBUGGING
136
0
    fprintf(outf,
137
0
            "  -D[TOKEN[,...]]\tturn on debugging output for the specified TOKENs\n\t\t\t   (ALL gives extremely verbose debugging output)\n");
138
0
#endif
139
0
    fprintf(outf, "General options\n");
140
0
    fprintf(outf,
141
0
            "  -m MIB[" ENV_SEPARATOR "...]\t\tload given list of MIBs (ALL loads everything)\n");
142
0
    fprintf(outf,
143
0
            "  -M DIR[" ENV_SEPARATOR "...]\t\tlook in given list of directories for MIBs\n");
144
0
#ifndef NETSNMP_DISABLE_MIB_LOADING
145
0
    fprintf(outf,
146
0
            "    (default: %s)\n", netsnmp_get_mib_directory());
147
0
    fprintf(outf,
148
0
            "  -P MIBOPTS\t\tToggle various defaults controlling MIB parsing:\n");
149
0
    snmp_mib_toggle_options_usage("\t\t\t  ", outf);
150
0
#endif
151
0
    fprintf(outf,
152
0
            "  -O OUTOPTS\t\tToggle various defaults controlling output display:\n");
153
0
    snmp_out_toggle_options_usage("\t\t\t  ", outf);
154
0
    fprintf(outf,
155
0
            "  -I INOPTS\t\tToggle various defaults controlling input parsing:\n");
156
0
    snmp_in_toggle_options_usage("\t\t\t  ", outf);
157
0
    fprintf(outf,
158
0
            "  -L LOGOPTS\t\tToggle various defaults controlling logging:\n");
159
0
    snmp_log_options_usage("\t\t\t  ", outf);
160
0
    fflush(outf);
161
0
}
162
163
#define BUF_SIZE 512
164
165
void
166
handle_long_opt(const char *myoptarg)
167
7.77k
{
168
7.77k
    char           *cp, *cp2;
169
    /*
170
     * else it's a long option, so process it like name=value 
171
     */
172
7.77k
    cp = (char *)malloc(strlen(myoptarg) + 3);
173
7.77k
    if (!cp)
174
0
        return;
175
7.77k
    strcpy(cp, myoptarg);
176
7.77k
    cp2 = strchr(cp, '=');
177
7.77k
    if (!cp2 && !strchr(cp, ' ')) {
178
        /*
179
         * well, they didn't specify an argument as far as we
180
         * can tell.  Give them a '1' as the argument (which
181
         * works for boolean tokens and a few others) and let
182
         * them suffer from there if it's not what they
183
         * wanted 
184
         */
185
3.87k
        strcat(cp, " 1");
186
3.89k
    } else {
187
        /*
188
         * replace the '=' with a ' ' 
189
         */
190
3.89k
        if (cp2)
191
964
            *cp2 = ' ';
192
3.89k
    }
193
7.77k
    netsnmp_config(cp);
194
7.77k
    free(cp);
195
7.77k
}
196
197
int
198
netsnmp_parse_args(int argc,
199
                   char **argv,
200
                   netsnmp_session * session, const char *localOpts,
201
                   void (*proc) (int, char *const *, int),
202
                   int flags)
203
6.39k
{
204
6.39k
    int             arg, ret, sp = 0;
205
6.39k
    const char     *cp;
206
6.39k
    char           *Apsz = NULL;
207
6.39k
    char           *Xpsz = NULL;
208
6.39k
    char           *Cpsz = NULL;
209
6.39k
    char            Opts[BUF_SIZE];
210
6.39k
    int             zero_sensitive = !( flags & NETSNMP_PARSE_ARGS_NOZERO );
211
6.39k
    char           *backup_NETSNMP_DS_LIB_OUTPUT_PRECISION = NULL;
212
213
    /*
214
     * initialize session to default values 
215
     */
216
6.39k
    snmp_sess_init(session);
217
6.39k
    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:L:s:");
218
6.39k
    if (localOpts) {
219
6.39k
        if (strlen(localOpts) + strlen(Opts) >= sizeof(Opts)) {
220
0
            snmp_log(LOG_ERR, "Too many localOpts in snmp_parse_args()\n");
221
0
            return -1;
222
0
        }
223
6.39k
        strcat(Opts, localOpts);
224
6.39k
    }
225
226
    /*
227
     * get the options 
228
     */
229
6.39k
    DEBUGMSGTL(("snmp_parse_args", "starting: %d/%d\n", optind, argc));
230
40.9k
    for (arg = 0; arg < argc; arg++) {
231
34.5k
        DEBUGMSGTL(("snmp_parse_args", " arg %d = %s\n", arg, argv[arg]));
232
34.5k
    }
233
234
6.39k
#ifdef __linux__
235
    /*
236
     * glibc only resets the internal getopt() state if optind is set to zero.
237
     */
238
6.39k
    optind = 0;
239
#else
240
    optind = 1;
241
#endif
242
21.3k
    while (optind < argc && (arg = getopt(argc, argv, Opts)) != EOF) {
243
15.7k
        DEBUGMSGTL(("snmp_parse_args", "handling (#%d): %c (optarg %s) (sp %d)\n",
244
15.7k
                    optind, arg, optarg, sp));
245
15.7k
        switch (arg) {
246
7.77k
        case '-':
247
7.77k
            if (strcasecmp(optarg, "help") == 0) {
248
1
                ret = NETSNMP_PARSE_ARGS_ERROR_USAGE;
249
1
                goto out;
250
1
            }
251
7.77k
            if (strcasecmp(optarg, "version") == 0) {
252
1
                fprintf(stderr,"NET-SNMP version: %s\n",netsnmp_get_version());
253
1
                ret = NETSNMP_PARSE_ARGS_SUCCESS_EXIT;
254
1
                goto out;
255
1
            }
256
257
7.77k
            handle_long_opt(optarg);
258
7.77k
            break;
259
260
1
        case 'V':
261
1
            fprintf(stderr, "NET-SNMP version: %s\n", netsnmp_get_version());
262
1
            ret = NETSNMP_PARSE_ARGS_SUCCESS_EXIT;
263
1
            goto out;
264
265
2
        case 'h':
266
2
            ret = NETSNMP_PARSE_ARGS_ERROR_USAGE;
267
2
            goto out;
268
269
13
        case 'H':
270
13
            init_snmp(NETSNMP_APPLICATION_CONFIG_TYPE);
271
13
            fprintf(stderr, "Configuration directives understood:\n");
272
13
            read_config_print_usage("  ");
273
13
            ret = NETSNMP_PARSE_ARGS_SUCCESS_EXIT;
274
13
            goto out;
275
276
23
        case 'Y':
277
23
            netsnmp_config_remember(optarg);
278
23
            break;
279
280
0
#ifndef NETSNMP_DISABLE_MIB_LOADING
281
70
        case 'm':
282
70
            setenv("MIBS", optarg, 1);
283
70
            break;
284
285
64
        case 'M':
286
64
            netsnmp_get_mib_directory(); /* prepare the default directories */
287
64
            netsnmp_set_mib_directory(optarg);
288
64
            break;
289
0
#endif /* NETSNMP_DISABLE_MIB_LOADING */
290
291
163
        case 'O':
292
163
            cp = snmp_out_options(optarg, argc, argv);
293
163
            if (cp != NULL) {
294
67
                fprintf(stderr, "Unknown output option passed to -O: %c.\n", 
295
67
      *cp);
296
67
                ret = NETSNMP_PARSE_ARGS_ERROR_USAGE;
297
67
                goto out;
298
67
            }
299
96
            break;
300
301
99
        case 'I':
302
99
            cp = snmp_in_options(optarg, argc, argv);
303
99
            if (cp != NULL) {
304
26
                fprintf(stderr, "Unknown input option passed to -I: %c.\n",
305
26
      *cp);
306
26
                ret = NETSNMP_PARSE_ARGS_ERROR_USAGE;
307
26
                goto out;
308
26
            }
309
73
            break;
310
311
73
#ifndef NETSNMP_DISABLE_MIB_LOADING
312
73
        case 'P':
313
64
            cp = snmp_mib_toggle_options(optarg);
314
64
            if (cp != NULL) {
315
31
                fprintf(stderr,
316
31
                        "Unknown parsing option passed to -P: %c.\n", *cp);
317
31
                ret = NETSNMP_PARSE_ARGS_ERROR_USAGE;
318
31
                goto out;
319
31
            }
320
33
            break;
321
33
#endif /* NETSNMP_DISABLE_MIB_LOADING */
322
323
1.96k
        case 'D':
324
#ifdef NETSNMP_NO_DEBUGGING
325
            fprintf(stderr, "Debug not configured in\n");
326
            ret = NETSNMP_PARSE_ARGS_ERROR_USAGE;
327
            goto out;
328
#else
329
1.96k
            debug_register_tokens(optarg);
330
1.96k
            snmp_set_do_debugging(1);
331
1.96k
#endif
332
1.96k
            break;
333
334
2.16k
        case 'd':
335
2.16k
            netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, 
336
2.16k
           NETSNMP_DS_LIB_DUMP_PACKET, 1);
337
2.16k
            break;
338
339
77
        case 's':
340
77
            free(session->localname);
341
77
            session->localname = strdup(optarg);
342
77
            break;
343
344
68
        case 'v':
345
68
            session->version = -1;
346
68
#ifndef NETSNMP_DISABLE_SNMPV1
347
68
            if (!strcmp(optarg, "1")) {
348
11
                session->version = SNMP_VERSION_1;
349
11
            }
350
68
#endif
351
68
#ifndef NETSNMP_DISABLE_SNMPV2C
352
68
            if (!strcasecmp(optarg, "2c")) {
353
12
                session->version = SNMP_VERSION_2c;
354
12
            }
355
68
#endif
356
68
            if (!strcasecmp(optarg, "3")) {
357
19
                session->version = SNMP_VERSION_3;
358
19
            }
359
68
            if (session->version == -1) {
360
26
                fprintf(stderr,
361
26
                        "Invalid version specified after -v flag: %s\n",
362
26
                        optarg);
363
26
                ret = NETSNMP_PARSE_ARGS_ERROR_USAGE;
364
26
                goto out;
365
26
            }
366
42
            break;
367
368
42
        case 'p':
369
2
            fprintf(stderr, "Warning: -p option is no longer used - ");
370
2
            fprintf(stderr, "specify the remote host as HOST:PORT\n");
371
2
            ret = NETSNMP_PARSE_ARGS_ERROR_USAGE;
372
2
            goto out;
373
374
19
        case 'T':
375
19
        {
376
19
            char leftside[SNMP_MAXBUF_MEDIUM], rightside[SNMP_MAXBUF_MEDIUM];
377
19
            char *tmpcp, *tmpopt;
378
            
379
            /* ensure we have a proper argument */
380
19
            tmpopt = strdup(optarg);
381
19
            tmpcp = strchr(tmpopt, '=');
382
19
            if (!tmpcp) {
383
1
                fprintf(stderr, "-T expects a NAME=VALUE pair.\n");
384
1
                free(tmpopt);
385
1
                ret = NETSNMP_PARSE_ARGS_ERROR_USAGE;
386
1
                goto out;
387
1
            }
388
18
            *tmpcp++ = '\0';
389
390
            /* create the transport config container if this is the first */
391
18
            if (!session->transport_configuration) {
392
8
                netsnmp_container_init_list();
393
8
                session->transport_configuration =
394
8
                    netsnmp_container_find("transport_configuration:fifo");
395
8
                if (!session->transport_configuration) {
396
0
                    fprintf(stderr, "failed to initialize the transport configuration container\n");
397
0
                    free(tmpopt);
398
0
                    ret = NETSNMP_PARSE_ARGS_ERROR;
399
0
                    goto out;
400
0
                }
401
402
8
                session->transport_configuration->compare =
403
8
                    netsnmp_transport_config_compare;
404
8
            }
405
406
            /* set the config */
407
18
            strlcpy(leftside, tmpopt, sizeof(leftside));
408
18
            strlcpy(rightside, tmpcp, sizeof(rightside));
409
410
18
            CONTAINER_INSERT(session->transport_configuration,
411
18
                             netsnmp_transport_create_config(leftside,
412
18
                                                             rightside));
413
18
            free(tmpopt);
414
18
        }
415
0
        break;
416
            
417
94
        case 't':
418
94
            session->timeout = (long)(atof(optarg) * 1000000L);
419
94
            if (session->timeout <= 0) {
420
65
                fprintf(stderr, "Invalid timeout in seconds after -t flag.\n");
421
65
                ret = NETSNMP_PARSE_ARGS_ERROR_USAGE;
422
65
                goto out;
423
65
            }
424
29
            break;
425
426
52
        case 'r':
427
52
            session->retries = atoi(optarg);
428
52
            if (session->retries < 0 || !isdigit((unsigned char)(optarg[0]))) {
429
33
                fprintf(stderr, "Invalid number of retries after -r flag.\n");
430
33
                ret = NETSNMP_PARSE_ARGS_ERROR_USAGE;
431
33
                goto out;
432
33
            }
433
19
            break;
434
435
57
        case 'c':
436
57
      if (zero_sensitive) {
437
57
                SNMP_FREE(Cpsz); /* free any previous value */
438
57
    if ((Cpsz = strdup(optarg)) != NULL) {
439
57
        memset(optarg, '\0', strlen(optarg));
440
57
    } else {
441
0
        fprintf(stderr, "malloc failure processing -c flag.\n");
442
0
        ret = NETSNMP_PARSE_ARGS_ERROR;
443
0
                    goto out;
444
0
    }
445
57
      } else {
446
0
    Cpsz = strdup(optarg);
447
0
      }
448
57
            break;
449
450
62
        case '3':
451
62
            if (snmpv3_parse_args(optarg, session, &Apsz, &Xpsz, argc, argv,
452
62
                                  flags) < 0){
453
21
                ret = NETSNMP_PARSE_ARGS_ERROR_USAGE;
454
21
                goto out;
455
21
            }
456
41
            break;
457
458
1.97k
        case 'L':
459
1.97k
            if (snmp_log_options(optarg, argc, argv) < 0) {
460
67
                ret = NETSNMP_PARSE_ARGS_ERROR_USAGE;
461
67
                goto out;
462
67
            }
463
1.90k
            break;
464
465
1.90k
#define SNMPV3_CMD_OPTIONS
466
1.90k
#ifdef  SNMPV3_CMD_OPTIONS
467
1.90k
        case 'Z':
468
118
        case 'e':
469
137
        case 'E':
470
170
        case 'n':
471
568
        case 'l':
472
658
        case 'u':
473
658
#ifdef NETSNMP_SECMOD_USM
474
742
        case 'a':
475
811
        case 'x':
476
858
        case 'A':
477
909
        case 'X':
478
909
#endif             /* NETSNMP_SECMOD_USM */
479
909
            if (snmpv3_parse_arg(arg, optarg, session, &Apsz, &Xpsz, argc,
480
909
                                 argv, flags) < 0){
481
434
                ret = NETSNMP_PARSE_ARGS_ERROR_USAGE;
482
434
                goto out;
483
434
            }
484
475
            break;
485
475
#endif                          /* SNMPV3_CMD_OPTIONS */
486
487
475
        case '?':
488
77
        case ':':
489
77
            ret = NETSNMP_PARSE_ARGS_ERROR_USAGE;
490
77
            goto out;
491
492
0
        default:
493
0
            proc(argc, argv, arg);
494
0
            break;
495
15.7k
        }
496
15.7k
    }
497
5.52k
    DEBUGMSGTL(("snmp_parse_args", "finished: %d/%d\n", optind, argc));
498
    
499
    /*
500
     * save command line parameters which should have precedence above config file settings
501
     *    (There ought to be a more scalable approach than this....)
502
     */
503
5.52k
    if (netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OUTPUT_PRECISION)) {
504
2.82k
        backup_NETSNMP_DS_LIB_OUTPUT_PRECISION = 
505
2.82k
            strdup(netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OUTPUT_PRECISION));
506
2.82k
    }
507
508
    /*
509
     * read in MIB database and initialize the snmp library, read the config file
510
     */
511
5.52k
    init_snmp(NETSNMP_APPLICATION_CONFIG_TYPE);
512
513
    /*
514
     * restore command line parameters which should have precedence above config file settings
515
     */
516
5.52k
    if(backup_NETSNMP_DS_LIB_OUTPUT_PRECISION) {
517
2.82k
        netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OUTPUT_PRECISION, backup_NETSNMP_DS_LIB_OUTPUT_PRECISION);
518
2.82k
        free(backup_NETSNMP_DS_LIB_OUTPUT_PRECISION);
519
2.82k
    }
520
521
    /*
522
     * session default version 
523
     */
524
5.52k
    if (session->version == SNMP_DEFAULT_VERSION) {
525
        /*
526
         * run time default version 
527
         */
528
5.51k
        session->version = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, 
529
5.51k
                NETSNMP_DS_LIB_SNMPVERSION);
530
531
        /*
532
         * compile time default version 
533
         */
534
5.51k
        if (!session->version) {
535
1.97k
            switch (NETSNMP_DEFAULT_SNMP_VERSION) {
536
0
#ifndef NETSNMP_DISABLE_SNMPV1
537
0
            case 1:
538
0
                session->version = SNMP_VERSION_1;
539
0
                break;
540
0
#endif
541
542
0
#ifndef NETSNMP_DISABLE_SNMPV2C
543
1.97k
            case 2:
544
1.97k
                session->version = SNMP_VERSION_2c;
545
1.97k
                break;
546
0
#endif
547
548
0
            case 3:
549
0
                session->version = SNMP_VERSION_3;
550
0
                break;
551
552
0
            default:
553
0
                snmp_log(LOG_ERR, "Can't determine a valid SNMP version for the session\n");
554
0
                return(NETSNMP_PARSE_ARGS_ERROR);
555
1.97k
            }
556
3.53k
        } else {
557
3.53k
#ifndef NETSNMP_DISABLE_SNMPV1
558
3.53k
            if (session->version == NETSNMP_DS_SNMP_VERSION_1)  /* bogus value.  version 1 actually = 0 */
559
2.37k
                session->version = SNMP_VERSION_1;
560
3.53k
#endif
561
3.53k
        }
562
5.51k
    }
563
564
5.52k
#ifdef NETSNMP_SECMOD_USM
565
    /* XXX: this should ideally be moved to snmpusm.c somehow */
566
567
    /*
568
     * make master key from pass phrases 
569
     */
570
5.52k
    if (Apsz) {
571
25
        session->securityAuthKeyLen = USM_AUTH_KU_LEN;
572
25
        if (session->securityAuthProto == NULL) {
573
            /*
574
             * get .conf set default 
575
             */
576
16
            const oid      *def =
577
16
                get_default_authtype(&session->securityAuthProtoLen);
578
16
            session->securityAuthProto =
579
16
                snmp_duplicate_objid(def, session->securityAuthProtoLen);
580
16
        }
581
25
        if (session->securityAuthProto == NULL) {
582
0
            session->securityAuthProto =
583
0
                snmp_duplicate_objid(SNMP_DEFAULT_AUTH_PROTO,
584
0
                                     SNMP_DEFAULT_AUTH_PROTOLEN);
585
0
            session->securityAuthProtoLen = SNMP_DEFAULT_AUTH_PROTOLEN;
586
0
        }
587
25
        if (generate_Ku(session->securityAuthProto,
588
25
                        session->securityAuthProtoLen,
589
25
                        (u_char *) Apsz, strlen(Apsz),
590
25
                        session->securityAuthKey,
591
25
                        &session->securityAuthKeyLen) != SNMPERR_SUCCESS) {
592
14
            snmp_perror(argv[0]);
593
14
            fprintf(stderr,
594
14
                    "Error generating a key (Ku) from the supplied authentication pass phrase. \n");
595
14
            ret = NETSNMP_PARSE_ARGS_ERROR;
596
14
            goto out;
597
14
        }
598
11
        free(Apsz);
599
11
        Apsz = NULL;
600
11
    }
601
5.51k
    if (Xpsz) {
602
29
        session->securityPrivKeyLen = USM_PRIV_KU_LEN;
603
29
        if (session->securityPrivProto == NULL) {
604
            /*
605
             * get .conf set default 
606
             */
607
28
            const oid      *def =
608
28
                get_default_privtype(&session->securityPrivProtoLen);
609
28
            session->securityPrivProto =
610
28
                snmp_duplicate_objid(def, session->securityPrivProtoLen);
611
28
        }
612
29
        if (session->securityPrivProto == NULL) {
613
0
            session->securityPrivProto =
614
0
                snmp_duplicate_objid(SNMP_DEFAULT_PRIV_PROTO,
615
0
                                     SNMP_DEFAULT_PRIV_PROTOLEN);
616
0
            session->securityPrivProtoLen = SNMP_DEFAULT_PRIV_PROTOLEN;
617
0
        }
618
29
        if (generate_Ku(session->securityAuthProto,
619
29
                        session->securityAuthProtoLen,
620
29
                        (u_char *) Xpsz, strlen(Xpsz),
621
29
                        session->securityPrivKey,
622
29
                        &session->securityPrivKeyLen) != SNMPERR_SUCCESS) {
623
20
            snmp_perror(argv[0]);
624
20
            fprintf(stderr,
625
20
                    "Error generating a key (Ku) from the supplied privacy pass phrase. \n");
626
20
            ret = NETSNMP_PARSE_ARGS_ERROR;
627
20
            goto out;
628
20
        }
629
9
        free(Xpsz);
630
9
        Xpsz = NULL;
631
9
    }
632
5.49k
#endif /* NETSNMP_SECMOD_USM */
633
634
    /*
635
     * get the hostname 
636
     */
637
5.49k
    if (optind >= argc) {
638
2.98k
        fprintf(stderr, "No hostname specified.\n");
639
2.98k
        ret = NETSNMP_PARSE_ARGS_ERROR_USAGE;
640
2.98k
        goto out;
641
2.98k
    }
642
2.51k
    session->peername = strdup(argv[optind++]); /* hostname */
643
644
2.51k
#if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)
645
    /*
646
     * If v1 or v2c, check community has been set, either by a -c option above,
647
     * or via a default token somewhere.  
648
     * If neither, it will be taken from the incoming request PDU.
649
     */
650
651
#if defined(NETSNMP_DISABLE_SNMPV1)
652
    if (session->version == SNMP_VERSION_2c)
653
#else 
654
#if defined(NETSNMP_DISABLE_SNMPV2C)
655
    if (session->version == SNMP_VERSION_1)
656
#else
657
2.51k
    if (session->version == SNMP_VERSION_1 ||
658
2.51k
  session->version == SNMP_VERSION_2c)
659
2.50k
#endif
660
2.50k
#endif
661
2.50k
    {
662
2.50k
        if (Cpsz == NULL) {
663
2.50k
            Cpsz = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, 
664
2.50k
           NETSNMP_DS_LIB_COMMUNITY);
665
2.50k
      if (Cpsz == NULL) {
666
2.42k
                if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
667
2.42k
                                           NETSNMP_DS_LIB_IGNORE_NO_COMMUNITY)){
668
0
                    DEBUGMSGTL(("snmp_parse_args",
669
0
                                "ignoring that the community string is not present\n"));
670
0
                    session->community = NULL;
671
0
                    session->community_len = 0;
672
2.42k
                } else {
673
2.42k
                    fprintf(stderr, "No community name specified.\n");
674
2.42k
                    ret = NETSNMP_PARSE_ARGS_ERROR_USAGE;
675
2.42k
                    goto out;
676
2.42k
                }
677
2.42k
      } else {
678
80
                Cpsz = NULL;
679
80
            }
680
2.50k
  } else {
681
7
            session->community = (unsigned char *)Cpsz;
682
7
            session->community_len = strlen(Cpsz);
683
7
            Cpsz = NULL;
684
7
        }
685
2.50k
    }
686
88
#endif /* support for community based SNMP */
687
688
88
    ret = optind;
689
690
6.39k
out:
691
6.39k
    free(Apsz);
692
6.39k
    free(Xpsz);
693
6.39k
    free(Cpsz);
694
6.39k
    return ret;
695
88
}
696
697
int
698
snmp_parse_args(int argc,
699
                char **argv,
700
                netsnmp_session * session, const char *localOpts,
701
                void (*proc) (int, char *const *, int))
702
6.39k
{
703
6.39k
    return netsnmp_parse_args(argc, argv, session, localOpts, proc, 0);
704
6.39k
}