Chapter 3. Understanding the sub-agent

3.1. The minimum

There are two ways of explaining the details of the generated sub-agent code. The first is to explain in detail every piece of the code and let the reader make the connection. The other (which we will use) is to comb through the code explaining what it does and provide working examples and explanation.

To have just a working, compilable code, you need two extra files that are not generated by mib2c. They are the makefile and the sub-agent startup code.

3.1.1. Makefile

Makefile. A good template is available from NET-SNMP Tutorial. I have modified the template to compile the generated C code.

OBJS2=example-demon.o netSnmpIETFWGTable.o
TARGETS=example-demon

CFLAGS=-I. `net-snmp-config --cflags`
BUILDLIBS=`net-snmp-config --libs`
BUILDAGENTLIBS=`net-snmp-config --agent-libs`

# shared library flags (assumes gcc)
DLFLAGS=-fPIC -shared

all: $(TARGETS)

example-demon: $(OBJS2)
        $(CC) -o example-demon $(OBJS2)  $(BUILDAGENTLIBS)
netSnmpIETFWGTable.o: netSnmpIETFWGTable.c Makefile
        $(CC) $(CFLAGS) $(DLFLAGS) -c -o netSnmpIETFWGTable.o \
                netSnmpIETFWGTable.c
        $(CC) $(CFLAGS) $(DLFLAGS) -o netSnmpIETFWGTable.so \
                netSnmpIETFWGTable.o
              

3.1.2. Sub-agent daemon code

The daemon will use the generated sub-agent code. This example daemon code has been taken from NET-SNMP Tutorial

#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>

#include <signal.h>

#include <netSnmpIETFWGTable.h>
        
static int keep_running;

RETSIGTYPE
stop_server(int a) {
    keep_running = 0;
}

int
main (int argc, char **argv) {
  int agentx_subagent=1; /* change this if you want to 
        be a SNMP master agent */

  /* print log errors to stderr */
  snmp_enable_stderrlog();
  //snmp_set_do_debugging(1);
  /* we're an agentx subagent? */
  if (agentx_subagent) {
    /* make us a agentx client. */
    netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, 
                NETSNMP_DS_AGENT_ROLE, 1);
  }

        DEBUGMSG(("Before agent library init","\n"));
  /* initialize the agent library */
  init_agent("example-demon");

  /* initialize mib code here */

  /* mib code: nit_netSnmpIETFWGTable from init_netSnmpIETFWGTable.c */
        init_netSnmpIETFWGTable();

  /* example-demon will be used to read example-demon.conf files. */
  init_snmp("example-demon");

  /* If we're going to be a snmp master agent, initial the ports */
  if (!agentx_subagent)
    init_master_agent();  /* open the port to listen on 
        (defaults to udp:161) */

  /* In case we recevie a request to stop (kill -TERM or kill -INT) */
  keep_running = 1;
  signal(SIGTERM, stop_server);
  signal(SIGINT, stop_server);

  /* you're main loop here... */
  while(keep_running) {
    /* if you use select(), see snmp_select_info() in snmp_api(3) */
    /*     --- OR ---  */
    agent_check_and_process(1); /* 0 == don't block */
  }

  /* at shutdown time */
  snmp_shutdown("example-demon");
        return 1;
}
              
Note

The only change from the original source file code was replacing init_nstAgentSubagentObject(); with init_netSnmpIETFWGTable();.

For right now we will skip explanation of these two files and concentrate on the sub-agent generated code.