/* * History: * -------- * 2006-11-23 initial version (jmagder) * * This file defines all functions required to establish a relationship with a * master agent. */ #include #include #include #include #include "sub_agent.h" /* Bring in the NetSNMP headers */ #include #include #include /* Bring in the initialization functions for all scalars */ #include "openserSIPCommonObjects.h" #include "openserSIPServerObjects.h" #include "openserObjects.h" /* Bring in the initialization functions for all tables */ #include "openserSIPPortTable.h" #include "openserSIPMethodSupportedTable.h" #include "openserSIPStatusCodesTable.h" #include "openserSIPRegUserTable.h" #include "openserSIPContactTable.h" #include "openserSIPRegUserLookupTable.h" #include "openserMIBNotifications.h" #include "../../dprint.h" static int keep_running; /* The function handles Handles shutting down of the sub_agent process. */ static void sigterm_handler(int signal) { /* Just exit. The master agent will clean everything up for us */ exit(0); } /* This function: * * 1) Registers itself with the Master Agent * * 2) Initializes all of the SNMPStats modules scalars and tables, while * simultaneously registering their respective SNMP OID's and handlers * with the master agent. * * 3) Repeatedly checks for new SNMP messages to process * * Note: This function never returns, so it should always be called from a * sub-process. * */ static int initialize_agentx(void) { /* We register with a master agent */ register_with_master_agent(AGENT_PROCESS_NAME); /* Initialize all scalars, and let the master agent know we want to * handle all OID's pertaining to these scalars. */ init_openserSIPCommonObjects(); init_openserSIPServerObjects(); init_openserObjects(); /* Initialiaze all the tables, and let the master agent know we want to * handle all the OID's pertaining to these tables */ init_openserSIPPortTable(); init_openserSIPMethodSupportedTable(); init_openserSIPStatusCodesTable(); init_openserSIPRegUserTable(); init_openserSIPContactTable(); init_openserSIPRegUserLookupTable(); /* In case we recevie a request to stop (kill -TERM or kill -INT) */ keep_running = 1; while(keep_running) { agent_check_and_process(1); /* 0 == don't block */ } snmp_shutdown(AGENT_PROCESS_NAME); SOCK_CLEANUP; exit (0); return 0; } /* Creates a child that will become the AgentX sub-agent. The child will * insulate itself from the rest of OpenSER by overriding most of signal * handlers. */ int spawn_agentx_child() { pid_t pid = fork(); /* If we are the child of the fork, then lets set up our sub-agent */ if (pid == 0) { struct sigaction new_sigterm_handler; struct sigaction default_handlers; struct sigaction sigpipe_handler; /* Setup a SIGTERM handler */ sigfillset(&new_sigterm_handler.sa_mask); new_sigterm_handler.sa_flags = 0; new_sigterm_handler.sa_handler = sigterm_handler; sigaction(SIGTERM, &new_sigterm_handler, NULL); /* We don't want OpenSER's normal handlers doing anything when * we die. As far as OpenSER knows this process never existed. * So override all signal handlers to the OS default. */ sigemptyset(&default_handlers.sa_mask); default_handlers.sa_flags = 0; default_handlers.sa_handler = SIG_DFL; sigaction(SIGCHLD, &default_handlers, NULL); sigaction(SIGINT, &default_handlers, NULL); sigaction(SIGHUP, &default_handlers, NULL); sigaction(SIGUSR1, &default_handlers, NULL); sigaction(SIGUSR2, &default_handlers, NULL); /* It is possible that the master agent will unregister us if we * take too long to respond to an SNMP request. This would * happen if a large number of users/contacts have been * registered between snmp requests to the user/contact tables. * In this situation we may try to write to a closed socket when * we are done processing, resulting in a SIGPIPE. This doesn't * need to be fatal however, because we can re-establish our * connection. Therefore we set ourselves up to ignore the * SIGPIPE. */ sigpipe_handler.sa_flags = SA_RESTART; sigpipe_handler.sa_handler = SIG_IGN; sigaction(SIGPIPE, &sigpipe_handler, NULL); initialize_agentx(); } else if (pid < 0) { return -1; } else { LOG(L_INFO, "INFO: SNMPStats: The AgentX Sub-Agent is running " "under PID %d\n", pid); } return 0; } /* This function opens up a connection with the master agent specified in * the snmpstats modules configuration file */ void register_with_master_agent(char *name_to_register_under) { /* Set ourselves up as an AgentX Client. */ netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_ROLE, 1); /* Initialize TCP if necessary. (Its here for WIN32) compatibility. */ SOCK_STARTUP; /* Read in our configuration file to determine master agent ping times * what port communication is to take place over, etc. */ init_agent("snmpstats"); /* Use a name we can register our agent under. */ init_snmp(name_to_register_under); }