/*
* History:
* --------
* 2006-11-23 initial version (jmagder)
*
* This file defines all functions required to establish a relationship with a
* master agent.
*/
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include "sub_agent.h"
/* Bring in the NetSNMP headers */
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
/* 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);
}
syntax highlighted by Code2HTML, v. 0.9.1