SNMP Module
===========

- General Description
- Functional description and code structure
  (how to add new tables is described here)

What is this?
=============

A module which adds support for SNMPv1,2c,3 to the SIP Express Router,
implementing the current draft of the SIP MIB
(http://www.iptel.org/info/players/ietf/configuration/draft-ietf-sip-mib-04.txt)
Actually 3 MIBs are defined in here:
SIP-COMMON
SIP-SERVER
SIP-UA
Currently we implement the first 2. It also has a minimal implementation of 
the NETWORK SERVICES MIB, required by the SIP MIB.

It supports the AgentX protocol, allowing it to act as a subagent of any
SNMP agent supporting this protocol (One such agent can be found in
http://www.net-snmp.org, but it's definitely not the only one). 
It can also operate as a standalone agent. It's written using the net-snmp
library, version 5.0.x. For help installing and configuring look at 
SNMP-HOWTO in this directory, and http://www.net-snmp.org 
(some config parameters to alter the behavior of the agent are discussed
there)

The module per-se doesn't know about the specific instances of the SNMP
objects defined in the SIP MIB. Instead, it provides a framework for different
parts of ser to manage those objects specific to them. For example, the
statistics collecting code in ser's core, knows (among other things)
about the objects in the sipSummaryStatsTable Table. Upon start up,
this part of code registers with the snmp module to handle these specific
objects. When an SNMP request comes in, the SNMP module passes that request
down to the registered handler. However, this registered handler doesn't need
to deal with any SNMP-specific details. All that this handler sees is
a request to GET or SET a value. If you're interested in writing a handler,
look at the HOWTO document in this directory.

How it works and what's all that code?
======================================
(Ascii art time!!!!)

On the most common configuration:

	 ---------               --------                --------
     |       |   loadmodule  |      |    AgentX      | SNMP |<====== SNMP
     | S E R | ------------->|      |<-------------->| agent|        Msgs
     |       |               | SNMP |                --------
     ---------               |Module|                    ^
         |------------------>|      |                    |
              snmp_start()   |      |                    | AgentX
                             --------                    |
						         | fork()                |
                                 v                       |
                             |----------|                |
                             |   SNMP   |<---------------|
                             | subagent |
                             ------------

The subagent is a different process since its control loop is different from
ser's. Upon module load, it contacts the master agent using the configured
agentx socket path (see agentxsocket in SNMP-HOWTO). If it finds a master
agent, it registers the SIP MIB and returns control ser. Later on, when
all handlers have been registered, snmp_start() is called which forks
the actual agent. After this point, handler registrations are no longer 
possible. The reason for having a separate snmp_start() function is just to
simplify the management of the internal tables maintained by the agent, but
since snmp_start() is called very late in the initialization process
(currently just before forking each ser child), we argue that there's 
little chance of anyone wanting to registere handlers after this point.

One important thing to note is that snmp should be the first module 
loaded in the configuration file.

If you want to stop the agent, use the exported function snmp_stop. However,
be careful using this function, since ser currently doesn't distinguish 
between the agent and a normal child and may either die or complicate
its life trying to figure out why one of its children died :)

Registration is done using one of the 3 exported functions:
snmp_register_handler, snmp_register_row and snmp_register_table. 

The code in the module is divided between the agent and handling code, and
the MIB tables' code. 

The tables' code is separated among files, each one
corresponding to the different conceptual separations made along the MIB.
Most of this code is identical, and has been actually autogenerated. The
script, add_table.sh may be used to generate code for new tables, or 
regenerate the code for one of the existing tables. The template is found
in the file mib2c.sipdataset.conf, which is a modified version of
mib2c.create-dataset.conf distributed with net-snmp. It generates both
the .c and .h files. Look at add_table.sh's output for what needs to be
done in order to merge the new code into the module.
Inside doc/ there's a file, not-autogenerated, which lists those files 
which were either not autogenerated, or changes were done after. Please
look at this file before changing any of the module's files.

The agent and handling code is in agent.c and snmp_handler.c. agent.c
is in charge of initializing the SNMP agent/subagent, registering the
SIP tree and filling in those parts of the tree managed by the SNMP
module. snmp_handler.c contains all the code for handler registration
(look at HOWTO for details on writing a handler).
This code works by having an internal table of registration functions,
one function per table implemented in the MIB. When a new registration
comes in, the table to which the object belongs is figured out from
the OID of the object, and the corresponding registration function called.
The idea with this is to allow each table to handle registration
independently. For example, one table may not support one or more of the
registration functions (e.g. applTable), or it may need to do some additional 
work that other tables may not need to do. Cooool, huh?
