snmp_parse_args.c
上传用户:wxp200602
上传日期:2007-10-30
资源大小:4028k
文件大小:24k
- /*
- * snmp_parse_args.c
- */
- /* Portions of this file are subject to the following copyright(s). See
- * the Net-SNMP's COPYING file for more details and other copyrights
- * that may apply:
- */
- /*
- * Portions of this file are copyrighted by:
- * Copyright @ 2003 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms specified in the COPYING file
- * distributed with the Net-SNMP package.
- */
- #include <net-snmp/net-snmp-config.h>
- #if HAVE_STDLIB_H
- #include <stdlib.h>
- #endif
- #if HAVE_UNISTD_H
- #include <unistd.h>
- #endif
- #if HAVE_STRING_H
- #include <string.h>
- #else
- #include <strings.h>
- #endif
- #include <sys/types.h>
- #include <stdio.h>
- #if HAVE_UNISTD_H
- #include <unistd.h>
- #endif
- #include <ctype.h>
- #if HAVE_NETINET_IN_H
- #include <netinet/in.h>
- #endif
- #if TIME_WITH_SYS_TIME
- # ifdef WIN32
- # include <sys/timeb.h>
- # else
- # include <sys/time.h>
- # endif
- # include <time.h>
- #else
- # if HAVE_SYS_TIME_H
- # include <sys/time.h>
- # else
- # include <time.h>
- # endif
- #endif
- #if HAVE_SYS_SELECT_H
- #include <sys/select.h>
- #endif
- #if HAVE_WINSOCK_H
- #include <winsock.h>
- #endif
- #if HAVE_NETDB_H
- #include <netdb.h>
- #endif
- #if HAVE_ARPA_INET_H
- #include <arpa/inet.h>
- #endif
- #include <net-snmp/types.h>
- #include <net-snmp/output_api.h>
- #include <net-snmp/config_api.h>
- #include <net-snmp/library/snmp_parse_args.h> /* for "internal" definitions */
- #include <net-snmp/utilities.h>
- #include <net-snmp/library/snmp_api.h>
- #include <net-snmp/library/snmp_client.h>
- #include <net-snmp/library/mib.h>
- #include <net-snmp/library/scapi.h>
- #include <net-snmp/library/keytools.h>
- #include <net-snmp/version.h>
- #include <net-snmp/library/parse.h>
- #include <net-snmp/library/snmpv3.h>
- #include <net-snmp/library/transform_oids.h>
- int random_access = 0;
- void
- snmp_parse_args_usage(FILE * outf)
- {
- fprintf(outf, "[OPTIONS] AGENT");
- }
- void
- snmp_parse_args_descriptions(FILE * outf)
- {
- fprintf(outf, " Version: %sn", netsnmp_get_version());
- fprintf(outf, " Web: http://www.net-snmp.org/n");
- fprintf(outf,
- " Email: net-snmp-coders@lists.sourceforge.netnnOPTIONS:n");
- fprintf(outf, " -h, --helpttdisplay this help messagen");
- fprintf(outf,
- " -Htttdisplay configuration file directives understoodn");
- fprintf(outf, " -v 1|2c|3ttspecifies SNMP version to usen");
- fprintf(outf, " -V, --versionttdisplay package version numbern");
- #if !defined(DISABLE_SNMPV1) || !defined(DISABLE_SNMPV2C)
- fprintf(outf, "SNMP Version 1 or 2c specificn");
- fprintf(outf, " -c COMMUNITYttset the community stringn");
- #endif /* support for community based SNMP */
- fprintf(outf, "SNMP Version 3 specificn");
- fprintf(outf,
- " -a PROTOCOLttset authentication protocol (MD5|SHA)n");
- fprintf(outf,
- " -A PASSPHRASEttset authentication protocol pass phrasen");
- fprintf(outf,
- " -e ENGINE-IDttset security engine ID (e.g. 800000020109840301)n");
- fprintf(outf,
- " -E ENGINE-IDttset context engine ID (e.g. 800000020109840301)n");
- fprintf(outf,
- " -l LEVELttset security level (noAuthNoPriv|authNoPriv|authPriv)n");
- fprintf(outf, " -n CONTEXTttset context name (e.g. bridge1)n");
- fprintf(outf, " -u USER-NAMEttset security name (e.g. bert)n");
- #ifdef HAVE_AES
- fprintf(outf, " -x PROTOCOLttset privacy protocol (DES|AES)n");
- #else
- fprintf(outf, " -x PROTOCOLttset privacy protocol (DES)n");
- #endif
- fprintf(outf, " -X PASSPHRASEttset privacy protocol pass phrasen");
- fprintf(outf,
- " -Z BOOTS,TIMEttset destination engine boots/timen");
- fprintf(outf, "General communication optionsn");
- fprintf(outf, " -r RETRIESttset the number of retriesn");
- fprintf(outf,
- " -t TIMEOUTttset the request timeout (in seconds)n");
- fprintf(outf, "Debuggingn");
- fprintf(outf, " -dtttdump input/output packets in hexadecimaln");
- fprintf(outf,
- " -D TOKEN[,...]tturn on debugging output for the specified TOKENsnttt (ALL gives extremely verbose debugging output)n");
- fprintf(outf, "General optionsn");
- fprintf(outf,
- " -m MIB[:...]ttload given list of MIBs (ALL loads everything)n");
- fprintf(outf,
- " -M DIR[:...]ttlook in given list of directories for MIBsn");
- #ifndef DISABLE_MIB_LOADING
- fprintf(outf,
- " -P MIBOPTSttToggle various defaults controlling MIB parsing:n");
- snmp_mib_toggle_options_usage("ttt ", outf);
- #endif
- fprintf(outf,
- " -O OUTOPTSttToggle various defaults controlling output display:n");
- snmp_out_toggle_options_usage("ttt ", outf);
- fprintf(outf,
- " -I INOPTSttToggle various defaults controlling input parsing:n");
- snmp_in_toggle_options_usage("ttt ", outf);
- fprintf(outf,
- " -L LOGOPTSttToggle various defaults controlling logging:n");
- snmp_log_options_usage("ttt ", outf);
- fflush(outf);
- }
- #define BUF_SIZE 512
- void
- handle_long_opt(const char *myoptarg)
- {
- char *cp, *cp2;
- /*
- * else it's a long option, so process it like name=value
- */
- cp = malloc(strlen(myoptarg) + 3);
- if (!cp)
- return;
- strcpy(cp, myoptarg);
- cp2 = strchr(cp, '=');
- if (!cp2 && !strchr(cp, ' ')) {
- /*
- * well, they didn't specify an argument as far as we
- * can tell. Give them a '1' as the argument (which
- * works for boolean tokens and a few others) and let
- * them suffer from there if it's not what they
- * wanted
- */
- strcat(cp, " 1");
- } else {
- /*
- * replace the '=' with a ' '
- */
- if (cp2)
- *cp2 = ' ';
- }
- netsnmp_config(cp);
- free(cp);
- }
- extern int snmpv3_options(char *optarg, netsnmp_session * session,
- char **Apsz, char **Xpsz, int argc,
- char *const *argv);
- /*
- * This method does the real work for snmp_parse_args. It takes an
- * extra argument, proxy, and uses this to decide how to handle the lack of
- * of a community string.
- */
- int
- snmp_parse_args(int argc,
- char **argv,
- netsnmp_session * session, const char *localOpts,
- void (*proc) (int, char *const *, int))
- {
- static char *sensitive[4] = { NULL, NULL, NULL, NULL };
- int arg, sp = 0, zero_sensitive = 1, testcase = 0;
- char *cp;
- char *Apsz = NULL;
- char *Xpsz = NULL;
- char *Cpsz = NULL;
- char Opts[BUF_SIZE];
- int logopt = 0;
- /*
- * initialize session to default values
- */
- snmp_sess_init(session);
- 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:");
- if (localOpts)
- strcat(Opts, localOpts);
- if (strcmp(argv[0], "snmpd-trapsess") == 0 ||
- strcmp(argv[0], "snmpd-proxy") == 0) {
- /* Don't worry about zeroing sensitive parameters as they are not
- on the command line anyway (called from internal config-line
- handler). */
- zero_sensitive = 0;
- }
- /*
- * get the options
- */
- DEBUGMSGTL(("snmp_parse_args", "starting: %d/%dn", optind, argc));
- for (arg = 0; arg < argc; arg++) {
- DEBUGMSGTL(("snmp_parse_args", " arg %d = %sn", arg, argv[arg]));
- }
- optind = 1;
- while ((arg = getopt(argc, argv, Opts)) != EOF) {
- DEBUGMSGTL(("snmp_parse_args", "handling (#%d): %cn", optind, arg));
- switch (arg) {
- case '-':
- if (strcasecmp(optarg, "help") == 0) {
- return (-1);
- }
- if (strcasecmp(optarg, "version") == 0) {
- fprintf(stderr,"NET-SNMP version: %sn",netsnmp_get_version());
- return (-2);
- }
- handle_long_opt(optarg);
- break;
- case 'V':
- fprintf(stderr, "NET-SNMP version: %sn", netsnmp_get_version());
- return (-2);
- case 'h':
- return (-1);
- break;
- case 'H':
- init_snmp("snmpapp");
- fprintf(stderr, "Configuration directives understood:n");
- read_config_print_usage(" ");
- return (-2);
- case 'Y':
- netsnmp_config_remember(optarg);
- break;
- #ifndef DISABLE_MIB_LOADING
- case 'm':
- setenv("MIBS", optarg, 1);
- break;
- case 'M':
- netsnmp_set_mib_directory(optarg);
- break;
- #endif /* DISABLE_MIB_LOADING */
- case 'O':
- cp = snmp_out_toggle_options(optarg);
- if (cp != NULL) {
- fprintf(stderr, "Unknown output option passed to -O: %c.n",
- *cp);
- return (-1);
- }
- break;
- case 'I':
- cp = snmp_in_options(optarg, argc, argv);
- if (cp != NULL) {
- fprintf(stderr, "Unknown input option passed to -I: %c.n",
- *cp);
- return (-1);
- }
- break;
- #ifndef DISABLE_MIB_LOADING
- case 'P':
- cp = snmp_mib_toggle_options(optarg);
- if (cp != NULL) {
- fprintf(stderr,
- "Unknown parsing option passed to -P: %c.n", *cp);
- return (-1);
- }
- break;
- #endif /* DISABLE_MIB_LOADING */
- case 'D':
- debug_register_tokens(optarg);
- snmp_set_do_debugging(1);
- break;
- case 'd':
- netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID,
- NETSNMP_DS_LIB_DUMP_PACKET, 1);
- break;
- case 'v':
- session->version = -1;
- #ifndef DISABLE_SNMPV1
- if (!strcmp(optarg, "1")) {
- session->version = SNMP_VERSION_1;
- }
- #endif
- #ifndef DISABLE_SNMPV2C
- if (!strcasecmp(optarg, "2c")) {
- session->version = SNMP_VERSION_2c;
- }
- #endif
- if (!strcasecmp(optarg, "3")) {
- session->version = SNMP_VERSION_3;
- }
- if (session->version == -1) {
- fprintf(stderr,
- "Invalid version specified after -v flag: %sn",
- optarg);
- return (-1);
- }
- break;
- case 'p':
- fprintf(stderr, "Warning: -p option is no longer used - ");
- fprintf(stderr, "specify the remote host as HOST:PORTn");
- return (-1);
- break;
- case 'T':
- fprintf(stderr, "Warning: -T option is no longer used - ");
- fprintf(stderr, "specify the remote host as TRANSPORT:HOSTn");
- return (-1);
- break;
- case 't':
- session->timeout = atoi(optarg) * 1000000L;
- if (session->timeout < 0 || !isdigit(optarg[0])) {
- fprintf(stderr, "Invalid timeout in seconds after -t flag.n");
- return (-1);
- }
- break;
- case 'r':
- session->retries = atoi(optarg);
- if (session->retries < 0 || !isdigit(optarg[0])) {
- fprintf(stderr, "Invalid number of retries after -r flag.n");
- return (-1);
- }
- break;
- case 'c':
- if (zero_sensitive) {
- if ((sensitive[sp] = strdup(optarg)) != NULL) {
- Cpsz = sensitive[sp];
- memset(optarg, ' ', strlen(optarg));
- sp++;
- } else {
- fprintf(stderr, "malloc failure processing -c flag.n");
- return -1;
- }
- } else {
- Cpsz = optarg;
- }
- break;
- case '3':
- /* TODO: This needs to zero things too. */
- if (snmpv3_options(optarg, session, &Apsz, &Xpsz, argc, argv) < 0){
- return (-1);
- }
- break;
- case 'L':
- if (snmp_log_options(optarg, argc, argv) < 0) {
- return (-1);
- }
- logopt = 1;
- break;
- #define SNMPV3_CMD_OPTIONS
- #ifdef SNMPV3_CMD_OPTIONS
- case 'Z':
- session->engineBoots = strtoul(optarg, NULL, 10);
- if (session->engineBoots == 0 || !isdigit(optarg[0])) {
- fprintf(stderr, "Need engine boots value after -Z flag.n");
- return (-1);
- }
- cp = strchr(optarg, ',');
- if (cp && *(++cp) && isdigit(*cp))
- session->engineTime = strtoul(cp, NULL, 10);
- /*
- * Handle previous '-Z boot time' syntax
- */
- else if ((optind < argc) && isdigit(argv[optind][0]))
- session->engineTime = strtoul(argv[optind], NULL, 10);
- else {
- fprintf(stderr, "Need engine time value after -Z flag.n");
- return (-1);
- }
- break;
- case 'e':{
- size_t ebuf_len = 32, eout_len = 0;
- u_char *ebuf = (u_char *)malloc(ebuf_len);
- if (ebuf == NULL) {
- fprintf(stderr, "malloc failure processing -e flag.n");
- return (-1);
- }
- if (!snmp_hex_to_binary
- (&ebuf, &ebuf_len, &eout_len, 1, optarg)) {
- fprintf(stderr, "Bad engine ID value after -e flag.n");
- free(ebuf);
- return (-1);
- }
- session->securityEngineID = ebuf;
- session->securityEngineIDLen = eout_len;
- break;
- }
- case 'E':{
- size_t ebuf_len = 32, eout_len = 0;
- u_char *ebuf = (u_char *)malloc(ebuf_len);
- if (ebuf == NULL) {
- fprintf(stderr, "malloc failure processing -E flag.n");
- return (-1);
- }
- if (!snmp_hex_to_binary(&ebuf, &ebuf_len,
- &eout_len, 1, optarg)) {
- fprintf(stderr, "Bad engine ID value after -E flag.n");
- free(ebuf);
- return (-1);
- }
- session->contextEngineID = ebuf;
- session->contextEngineIDLen = eout_len;
- break;
- }
- case 'n':
- session->contextName = optarg;
- session->contextNameLen = strlen(optarg);
- break;
- case 'u':
- if (zero_sensitive) {
- if ((sensitive[sp] = strdup(optarg)) != NULL) {
- session->securityName = sensitive[sp];
- session->securityNameLen = strlen(sensitive[sp]);
- memset(optarg, ' ', strlen(optarg));
- sp++;
- } else {
- fprintf(stderr, "malloc failure processing -u flag.n");
- return -1;
- }
- } else {
- session->securityName = optarg;
- session->securityNameLen = strlen(optarg);
- }
- break;
- case 'l':
- if (!strcasecmp(optarg, "noAuthNoPriv") || !strcmp(optarg, "1")
- || !strcasecmp(optarg, "noauth")
- || !strcasecmp(optarg, "nanp")) {
- session->securityLevel = SNMP_SEC_LEVEL_NOAUTH;
- } else if (!strcasecmp(optarg, "authNoPriv")
- || !strcmp(optarg, "2")
- || !strcasecmp(optarg, "auth")
- || !strcasecmp(optarg, "anp")) {
- session->securityLevel = SNMP_SEC_LEVEL_AUTHNOPRIV;
- } else if (!strcasecmp(optarg, "authPriv")
- || !strcmp(optarg, "3")
- || !strcasecmp(optarg, "priv")
- || !strcasecmp(optarg, "ap")) {
- session->securityLevel = SNMP_SEC_LEVEL_AUTHPRIV;
- } else {
- fprintf(stderr,
- "Invalid security level specified after -l flag: %sn",
- optarg);
- return (-1);
- }
- break;
- case 'a':
- #ifndef DISABLE_MD5
- if (!strcasecmp(optarg, "MD5")) {
- session->securityAuthProto = usmHMACMD5AuthProtocol;
- session->securityAuthProtoLen = USM_AUTH_PROTO_MD5_LEN;
- } else
- #endif
- if (!strcasecmp(optarg, "SHA")) {
- session->securityAuthProto = usmHMACSHA1AuthProtocol;
- session->securityAuthProtoLen = USM_AUTH_PROTO_SHA_LEN;
- } else {
- fprintf(stderr,
- "Invalid authentication protocol specified after -a flag: %sn",
- optarg);
- return (-1);
- }
- break;
- case 'x':
- testcase = 0;
- #ifndef DISABLE_DES
- if (!strcasecmp(optarg, "DES")) {
- testcase = 1;
- session->securityPrivProto = usmDESPrivProtocol;
- session->securityPrivProtoLen = USM_PRIV_PROTO_DES_LEN;
- }
- #endif
- #ifdef HAVE_AES
- if (!strcasecmp(optarg, "AES128") ||
- !strcasecmp(optarg, "AES")) {
- testcase = 1;
- session->securityPrivProto = usmAESPrivProtocol;
- session->securityPrivProtoLen = USM_PRIV_PROTO_AES_LEN;
- }
- #endif
- if (testcase == 0) {
- fprintf(stderr,
- "Invalid privacy protocol specified after -x flag: %sn",
- optarg);
- return (-1);
- }
- break;
- case 'A':
- if (zero_sensitive) {
- if ((sensitive[sp] = strdup(optarg)) != NULL) {
- Apsz = sensitive[sp];
- memset(optarg, ' ', strlen(optarg));
- sp++;
- } else {
- fprintf(stderr, "malloc failure processing -A flag.n");
- return -1;
- }
- } else {
- Apsz = optarg;
- }
- break;
- case 'X':
- if (zero_sensitive) {
- if ((sensitive[sp] = strdup(optarg)) != NULL) {
- Xpsz = sensitive[sp];
- memset(optarg, ' ', strlen(optarg));
- sp++;
- } else {
- fprintf(stderr, "malloc failure processing -X flag.n");
- return -1;
- }
- } else {
- Xpsz = optarg;
- }
- break;
- #endif /* SNMPV3_CMD_OPTIONS */
- case '?':
- return (-1);
- break;
- default:
- proc(argc, argv, arg);
- break;
- }
- }
- DEBUGMSGTL(("snmp_parse_args", "finished: %d/%dn", optind, argc));
-
- if (!logopt)
- snmp_enable_stderrlog();
- /*
- * read in MIB database and initialize the snmp library
- */
- init_snmp("snmpapp");
- /*
- * session default version
- */
- if (session->version == SNMP_DEFAULT_VERSION) {
- /*
- * run time default version
- */
- session->version = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID,
- NETSNMP_DS_LIB_SNMPVERSION);
- /*
- * compile time default version
- */
- if (!session->version) {
- switch (DEFAULT_SNMP_VERSION) {
- #ifndef DISABLE_SNMPV1
- case 1:
- session->version = SNMP_VERSION_1;
- break;
- #endif
- #ifndef DISABLE_SNMPV2C
- case 2:
- session->version = SNMP_VERSION_2c;
- break;
- #endif
- case 3:
- session->version = SNMP_VERSION_3;
- break;
- default:
- snmp_log(LOG_ERR, "Can't determine a valid SNMP version for the sessionn");
- return(-2);
- }
- } else {
- #ifndef DISABLE_SNMPV1
- if (session->version == NETSNMP_DS_SNMP_VERSION_1) /* bogus value. version 1 actually = 0 */
- session->version = SNMP_VERSION_1;
- #endif
- }
- }
- /*
- * make master key from pass phrases
- */
- if (Apsz) {
- session->securityAuthKeyLen = USM_AUTH_KU_LEN;
- if (session->securityAuthProto == NULL) {
- /*
- * get .conf set default
- */
- const oid *def =
- get_default_authtype(&session->securityAuthProtoLen);
- session->securityAuthProto =
- snmp_duplicate_objid(def, session->securityAuthProtoLen);
- }
- if (session->securityAuthProto == NULL) {
- #ifndef DISABLE_MD5
- /*
- * assume MD5
- */
- session->securityAuthProto =
- snmp_duplicate_objid(usmHMACMD5AuthProtocol,
- USM_AUTH_PROTO_MD5_LEN);
- session->securityAuthProtoLen = USM_AUTH_PROTO_MD5_LEN;
- #else
- session->securityAuthProto =
- snmp_duplicate_objid(usmHMACSHA1AuthProtocol,
- USM_AUTH_PROTO_SHA_LEN);
- session->securityAuthProtoLen = USM_AUTH_PROTO_SHA_LEN;
- #endif
- }
- if (generate_Ku(session->securityAuthProto,
- session->securityAuthProtoLen,
- (u_char *) Apsz, strlen(Apsz),
- session->securityAuthKey,
- &session->securityAuthKeyLen) != SNMPERR_SUCCESS) {
- snmp_perror(argv[0]);
- fprintf(stderr,
- "Error generating a key (Ku) from the supplied authentication pass phrase. n");
- return (-2);
- }
- }
- if (Xpsz) {
- session->securityPrivKeyLen = USM_PRIV_KU_LEN;
- if (session->securityPrivProto == NULL) {
- /*
- * get .conf set default
- */
- const oid *def =
- get_default_privtype(&session->securityPrivProtoLen);
- session->securityPrivProto =
- snmp_duplicate_objid(def, session->securityPrivProtoLen);
- }
- if (session->securityPrivProto == NULL) {
- /*
- * assume DES
- */
- #ifndef DISABLE_DES
- session->securityPrivProto =
- snmp_duplicate_objid(usmDESPrivProtocol,
- USM_PRIV_PROTO_DES_LEN);
- session->securityPrivProtoLen = USM_PRIV_PROTO_DES_LEN;
- #else
- session->securityPrivProto =
- snmp_duplicate_objid(usmAESPrivProtocol,
- USM_PRIV_PROTO_AES_LEN);
- session->securityPrivProtoLen = USM_PRIV_PROTO_AES_LEN;
- #endif
- }
- if (generate_Ku(session->securityAuthProto,
- session->securityAuthProtoLen,
- (u_char *) Xpsz, strlen(Xpsz),
- session->securityPrivKey,
- &session->securityPrivKeyLen) != SNMPERR_SUCCESS) {
- snmp_perror(argv[0]);
- fprintf(stderr,
- "Error generating a key (Ku) from the supplied privacy pass phrase. n");
- return (-2);
- }
- }
- /*
- * get the hostname
- */
- if (optind == argc) {
- fprintf(stderr, "No hostname specified.n");
- return (-1);
- }
- session->peername = argv[optind++]; /* hostname */
- #if !defined(DISABLE_SNMPV1) || !defined(DISABLE_SNMPV2C)
- /*
- * If v1 or v2c, check community has been set, either by a -c option above,
- * or via a default token somewhere.
- * If neither, it will be taken from the incoming request PDU.
- */
- if (session->version == SNMP_VERSION_1 ||
- session->version == SNMP_VERSION_2c) {
- if (Cpsz == NULL) {
- Cpsz = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
- NETSNMP_DS_LIB_COMMUNITY);
- if (Cpsz == NULL) {
- if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
- NETSNMP_DS_LIB_IGNORE_NO_COMMUNITY)){
- DEBUGMSGTL(("snmp_parse_args",
- "ignoring that the community string is not presentn"));
- session->community = NULL;
- session->community_len = 0;
- } else {
- fprintf(stderr, "No community name specified.n");
- return (-1);
- }
- }
- } else {
- session->community = (unsigned char *)Cpsz;
- session->community_len = strlen(Cpsz);
- }
- }
- #endif /* support for community based SNMP */
- return optind;
- }