int init_master_agent(int dest_port, int (*pre_parse) (struct snmp_session *, snmp_ipaddr), int (*post_parse) (struct snmp_session *, struct snmp_pdu *,int)) { struct snmp_session sess, *session; if ( ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_ROLE) != MASTER_AGENT ) return 0; /* no error if ! MASTER_AGENT */ DEBUGMSGTL(("snmpd","installing master agent on port %d\n", dest_port)); snmp_sess_init( &sess ); sess.version = SNMP_DEFAULT_VERSION; sess.peername = SNMP_DEFAULT_PEERNAME; sess.community_len = SNMP_DEFAULT_COMMUNITY_LEN; sess.local_port = dest_port; sess.callback = handle_snmp_packet; sess.authenticator = NULL; sess.flags = ds_get_int(DS_APPLICATION_ID, DS_AGENT_FLAGS); session = snmp_open_ex( &sess, pre_parse, 0, post_parse, 0, 0 ); if ( session == NULL ) { /* diagnose snmp_open errors with the input struct snmp_session pointer */ snmp_sess_perror("init_master_agent", &sess); return 1; } main_session = session; return 0; }
void version_conf(const char *word, char *cptr) { if (strcmp(cptr,"1") == 0) { ds_set_int(DS_LIBRARY_ID, DS_LIB_SNMPVERSION, SNMP_VERSION_1); } else if (strcasecmp(cptr,"2c") == 0) { ds_set_int(DS_LIBRARY_ID, DS_LIB_SNMPVERSION, SNMP_VERSION_2c); } else if (strcmp(cptr,"3") == 0) { ds_set_int(DS_LIBRARY_ID, DS_LIB_SNMPVERSION, SNMP_VERSION_3); } else { config_perror("Unknown version specification"); return; } DEBUGMSGTL(("snmpv3","set default version to %d\n", ds_get_int(DS_LIBRARY_ID, DS_LIB_SNMPVERSION))); }
/*******************************************************************-o-****** * snmpv3_secLevel_conf * * Parameters: * *word * *cptr * * Line syntax: * defSecurityLevel "noAuthNoPriv" | "authNoPriv" | "authPriv" */ void snmpv3_secLevel_conf(const char *word, char *cptr) { char buf[1024]; if (strcasecmp(cptr,"noAuthNoPriv") == 0 || strcmp(cptr, "1") == 0 || strcasecmp(cptr, "nanp") == 0) ds_set_int(DS_LIBRARY_ID, DS_LIB_SECLEVEL, SNMP_SEC_LEVEL_NOAUTH); else if (strcasecmp(cptr,"authNoPriv") == 0 || strcmp(cptr, "2") == 0 || strcasecmp(cptr, "anp") == 0) ds_set_int(DS_LIBRARY_ID, DS_LIB_SECLEVEL, SNMP_SEC_LEVEL_AUTHNOPRIV); else if (strcasecmp(cptr,"authPriv") == 0 || strcmp(cptr, "3") == 0 || strcasecmp(cptr, "ap") == 0) ds_set_int(DS_LIBRARY_ID, DS_LIB_SECLEVEL, SNMP_SEC_LEVEL_AUTHPRIV); else { sprintf(buf,"Unknown security level: %s", cptr); config_perror(buf); } DEBUGMSGTL(("snmpv3","default secLevel set to: %s = %d\n", cptr, ds_get_int(DS_LIBRARY_ID, DS_LIB_SECLEVEL))); }
int main(int argc, char *argv[]) { int arg, i; int ret; u_short dest_port = SNMP_PORT; int dont_fork = 0; char logfile[SNMP_MAXBUF_SMALL]; char *cptr, **argvptr; char *pid_file = NULL; #if HAVE_GETPID FILE *PID; #endif int dont_zero_log = 0; int stderr_log=0, syslog_log=0; int uid=0, gid=0; logfile[0] = 0; #ifdef LOGFILE strcpy(logfile, LOGFILE); #endif /* * usage: snmpd */ for (arg = 1; arg < argc; arg++) { if (argv[arg][0] == '-') { switch (argv[arg][1]) { case 'c': if (++arg == argc) usage(argv[0]); ds_set_string(DS_LIBRARY_ID, DS_LIB_OPTIONALCONFIG, argv[arg]); break; case 'C': ds_set_boolean(DS_LIBRARY_ID, DS_LIB_DONT_READ_CONFIGS, 1); break; case 'd': snmp_set_dump_packet(++snmp_dump_packet); ds_set_boolean(DS_APPLICATION_ID, DS_AGENT_VERBOSE, 1); break; case 'q': snmp_set_quick_print(1); break; case 'T': if (argv[arg][2] != '\0') cptr = &argv[arg][2]; else if (++arg>argc) { fprintf(stderr,"Need UDP or TCP after -T flag.\n"); usage(argv[0]); exit(1); } else { cptr = argv[arg]; } if (strcasecmp(cptr,"TCP") == 0) { ds_set_int(DS_APPLICATION_ID, DS_AGENT_FLAGS, ds_get_int(DS_APPLICATION_ID, DS_AGENT_FLAGS) | SNMP_FLAGS_STREAM_SOCKET); } else if (strcasecmp(cptr,"UDP") == 0) { /* default, do nothing */ } else { fprintf(stderr, "Unknown transport \"%s\" after -T flag.\n", cptr); usage(argv[0]); exit(1); } break; case 'D': debug_register_tokens(&argv[arg][2]); snmp_set_do_debugging(1); break; case 'p': if (++arg == argc) usage(argv[0]); dest_port = atoi(argv[arg]); if (dest_port <= 0) usage(argv[0]); break; case 'x': if (++arg == argc) usage(argv[0]); ds_set_string(DS_APPLICATION_ID, DS_AGENT_X_SOCKET, argv[arg]); break; case 'r': ds_set_boolean(DS_APPLICATION_ID, DS_AGENT_NO_ROOT_ACCESS, 1); break; case 'P': if (++arg == argc) usage(argv[0]); pid_file = argv[arg]; case 'a': log_addresses++; break; case 'V': ds_set_boolean(DS_APPLICATION_ID, DS_AGENT_VERBOSE, 1); break; case 'f': dont_fork = 1; break; case 'l': if (++arg == argc) usage(argv[0]); strcpy(logfile, argv[arg]); break; case 'L': stderr_log=1; break; case 's': syslog_log=1; break; case 'A': dont_zero_log = 1; break; #if HAVE_UNISTD_H case 'u': if (++arg == argc) usage(argv[0]); uid = atoi(argv[arg]); break; case 'g': if (++arg == argc) usage(argv[0]); gid = atoi(argv[arg]); break; #endif case 'h': usage(argv[0]); break; case 'H': init_agent("snmpd"); /* register our .conf handlers */ init_mib_modules(); init_snmp("snmpd"); fprintf(stderr, "Configuration directives understood:\n"); read_config_print_usage(" "); exit(0); case 'v': printf("\nUCD-snmp version: %s\n",VersionInfo); printf("Author: Wes Hardaker\n"); printf("Email: [email protected]\n\n"); exit (0); case '-': switch(argv[arg][2]) { case 'v': printf("\nUCD-snmp version: %s\n",VersionInfo); printf("Author: Wes Hardaker\n"); printf("Email: [email protected]\n\n"); exit (0); case 'h': usage(argv[0]); exit(0); } default: printf("invalid option: %s\n", argv[arg]); usage(argv[0]); break; } continue; } } /* end-for */ /* * Initialize a argv set to the current for restarting the agent. */ argvrestartp = (char **) malloc((argc + 2) * sizeof(char *)); argvptr = argvrestartp; for (i = 0, ret = 1; i < argc; i++) { ret += strlen(argv[i]) + 1; } argvrestart = (char *) malloc(ret); argvrestartname = (char *) malloc(strlen(argv[0]) + 1); strcpy(argvrestartname, argv[0]); if ( strstr(argvrestartname, "agentxd") != NULL) ds_set_boolean(DS_APPLICATION_ID, DS_AGENT_ROLE, SUB_AGENT); else ds_set_boolean(DS_APPLICATION_ID, DS_AGENT_ROLE, MASTER_AGENT); for (cptr = argvrestart, i = 0; i < argc; i++) { strcpy(cptr, argv[i]); *(argvptr++) = cptr; cptr += strlen(argv[i]) + 1; } *cptr = 0; *argvptr = NULL; /* * Open the logfile if necessary. */ /* Should open logfile and/or syslog based on arguments */ if (logfile[0]) snmp_enable_filelog(logfile, dont_zero_log); if (syslog_log) snmp_enable_syslog(); #ifdef BUFSIZ setvbuf(stdout, NULL, _IOLBF, BUFSIZ); #endif /* * Initialize the world. Detach from the shell. * Create initial user. */ #if HAVE_FORK if (!dont_fork && fork() != 0) { exit(0); } #endif #if HAVE_GETPID if (pid_file != NULL) { if ((PID = fopen(pid_file, "w")) == NULL) { snmp_log_perror("fopen"); if (!ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_NO_ROOT_ACCESS)) exit(1); } else { fprintf(PID, "%d\n", (int)getpid()); fclose(PID); } } #endif #else /* __ECOS environment: */ void snmpd( void *initfunc( void ) ) { int ret; u_short dest_port = SNMP_PORT; #define stderr_log 1 #endif // --------- // En-bloc reinitialization of statics. running = 1; // --------- SOCK_STARTUP; init_agent("snmpd"); /* do what we need to do first. */ init_mib_modules(); /* start library */ init_snmp("snmpd"); ret = init_master_agent( dest_port, snmp_check_packet, snmp_check_parse ); if( ret != 0 ) Exit(1); /* Exit logs exit val for us */ #ifdef SIGTERM signal(SIGTERM, SnmpdShutDown); #endif #ifdef SIGINT signal(SIGINT, SnmpdShutDown); #endif #ifdef SIGHUP signal(SIGHUP, SnmpdReconfig); #endif #ifdef SIGUSR1 signal(SIGUSR1, SnmpdDump); #endif /* send coldstart trap via snmptrap(1) if possible */ send_easy_trap (0, 0); #if HAVE_UNISTD_H if (gid) { DEBUGMSGTL(("snmpd", "Changing gid to %d.\n", gid)); if (setgid(gid)==-1) { snmp_log_perror("setgid failed"); if (!ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_NO_ROOT_ACCESS)) exit(1); } } if (uid) { DEBUGMSGTL(("snmpd", "Changing uid to %d.\n", uid)); if(setuid(uid)==-1) { snmp_log_perror("setuid failed"); if (!ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_NO_ROOT_ACCESS)) exit(1); } } #endif /* honor selection of standard error output */ if (!stderr_log) snmp_disable_stderrlog(); /* we're up, log our version number */ snmp_log(LOG_INFO, "UCD-SNMP version %s\n", VersionInfo); memset(addrCache, 0, sizeof(addrCache)); /* * Call initialization function if necessary */ DEBUGMSGTL(("snmpd", "Calling initfunc().\n")); if ( initfunc ) (initfunc)(); /* * Forever monitor the dest_port for incoming PDUs. */ DEBUGMSGTL(("snmpd", "We're up. Starting to process data.\n")); receive(); #include "mib_module_shutdown.h" DEBUGMSGTL(("snmpd", "sending shutdown trap\n")); SnmpTrapNodeDown(); DEBUGMSGTL(("snmpd", "Bye...\n")); snmp_shutdown("snmpd"); } /* End main() -- snmpd */
int snmp_parse_args(int argc, char *const *argv, netsnmp_session * session, const char *localOpts, void (*proc) (int, char *const *, int)) { int arg; char *cp; char *Apsz = NULL; char *Xpsz = NULL; char *Cpsz = NULL; char Opts[BUF_SIZE]; /* * 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:"); if (localOpts) strcat(Opts, localOpts); /* * get the options */ DEBUGMSGTL(("snmp_parse_args", "starting: %d/%d\n", optind, argc)); for (arg = 0; arg < argc; arg++) { DEBUGMSGTL(("snmp_parse_args", " arg %d = %s\n", arg, argv[arg])); } optind = 1; while ((arg = getopt(argc, argv, Opts)) != EOF) { DEBUGMSGTL(("snmp_parse_args", "handling (#%d): %c\n", optind, arg)); switch (arg) { case '-': if (strcasecmp(optarg, "help") == 0) { return (-1); } if (strcasecmp(optarg, "version") == 0) { fprintf(stderr, "NET-SNMP version: %s\n", netsnmp_get_version()); return (-2); } handle_long_opt(optarg); break; case 'V': fprintf(stderr, "NET-SNMP version: %s\n", 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; case 'm': setenv("MIBS", optarg, 1); break; case 'M': setenv("MIBDIRS", optarg, 1); break; 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_toggle_options(optarg); if (cp != NULL) { fprintf(stderr, "Unknown input option passed to -I: %c.\n", *cp); return (-1); } break; 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; case 'D': debug_register_tokens(optarg); snmp_set_do_debugging(1); break; case 'd': ds_set_boolean(DS_LIBRARY_ID, DS_LIB_DUMP_PACKET, 1); break; case 'v': if (!strcmp(optarg, "1")) { session->version = SNMP_VERSION_1; } else if (!strcasecmp(optarg, "2c")) { session->version = SNMP_VERSION_2c; } else if (!strcasecmp(optarg, "3")) { session->version = SNMP_VERSION_3; } else { fprintf(stderr, "Invalid version specified after -v flag: %s\n", optarg); return (-1); } break; case 'p': fprintf(stderr, "Warning: -p option is no longer used - "); fprintf(stderr, "specify the remote host as HOST:PORT\n"); return (-1); break; case 'T': fprintf(stderr, "Warning: -T option is no longer used - "); fprintf(stderr, "specify the remote host as TRANSPORT:HOST\n"); 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': Cpsz = optarg; break; case '3': if (snmpv3_options(optarg, session, &Apsz, &Xpsz, argc, argv) < 0) { return (-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': session->securityName = optarg; session->securityNameLen = strlen(optarg); break; case 'l': if (!strcasecmp(optarg, "noAuthNoPriv") || !strcmp(optarg, "1") || !strcasecmp(optarg, "nanp")) { session->securityLevel = SNMP_SEC_LEVEL_NOAUTH; } else if (!strcasecmp(optarg, "authNoPriv") || !strcmp(optarg, "2") || !strcasecmp(optarg, "anp")) { session->securityLevel = SNMP_SEC_LEVEL_AUTHNOPRIV; } else if (!strcasecmp(optarg, "authPriv") || !strcmp(optarg, "3") || !strcasecmp(optarg, "ap")) { session->securityLevel = SNMP_SEC_LEVEL_AUTHPRIV; } else { fprintf(stderr, "Invalid security level specified after -l flag: %s\n", optarg); return (-1); } break; case 'a': if (!strcasecmp(optarg, "MD5")) { session->securityAuthProto = usmHMACMD5AuthProtocol; session->securityAuthProtoLen = USM_AUTH_PROTO_MD5_LEN; } else if (!strcasecmp(optarg, "SHA")) { session->securityAuthProto = usmHMACSHA1AuthProtocol; session->securityAuthProtoLen = USM_AUTH_PROTO_SHA_LEN; } else { fprintf(stderr, "Invalid authentication protocol specified after -a flag: %s\n", optarg); return (-1); } break; case 'x': if (!strcasecmp(optarg, "DES")) { session->securityPrivProto = usmDESPrivProtocol; session->securityPrivProtoLen = USM_PRIV_PROTO_DES_LEN; } else { fprintf(stderr, "Invalid privacy protocol specified after -x flag: %s\n", optarg); return (-1); } break; case 'A': Apsz = optarg; break; case 'X': Xpsz = optarg; break; #endif /* SNMPV3_CMD_OPTIONS */ case '?': return (-1); break; default: proc(argc, argv, arg); break; } } DEBUGMSGTL(("snmp_parse_args", "finished: %d/%d\n", optind, argc)); /* * 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 = ds_get_int(DS_LIBRARY_ID, DS_LIB_SNMPVERSION); /* * compile time default version */ if (!session->version) { switch (SNMP_DEFAULT_VERSION) { case 1: session->version = SNMP_VERSION_1; break; case 2: session->version = SNMP_VERSION_2c; break; case 3: session->version = SNMP_VERSION_3; break; } } else { if (session->version == DS_SNMP_VERSION_1) /* bogus value. version 1 actually = 0 */ session->version = SNMP_VERSION_1; } } /* * 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) { /* * assume MD5 */ session->securityAuthProto = snmp_duplicate_objid(usmHMACMD5AuthProtocol, USM_AUTH_PROTO_MD5_LEN); session->securityAuthProtoLen = USM_AUTH_PROTO_MD5_LEN; } 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 */ session->securityPrivProto = snmp_duplicate_objid(usmDESPrivProtocol, USM_PRIV_PROTO_DES_LEN); session->securityPrivProtoLen = USM_PRIV_PROTO_DES_LEN; } 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 v1 or v2c, check community has been set, either by a -c option above, * or via a default token somewhere. */ if (session->version == SNMP_VERSION_1 || session->version == SNMP_VERSION_2c) { if (Cpsz == NULL) { Cpsz = ds_get_string(DS_LIBRARY_ID, DS_LIB_COMMUNITY); } if (Cpsz == NULL) { fprintf(stderr, "No community name specified.\n"); return (-1); } session->community = (unsigned char *) Cpsz; session->community_len = strlen(Cpsz); } return optind; }