182 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			182 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| 
								 | 
							
								SNMPv1 agent for lwIP
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Author: Christiaan Simons
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								This is a brief introduction how to use and configure the SNMP agent.
							 | 
						||
| 
								 | 
							
								Note the agent uses the raw-API UDP interface so you may also want to
							 | 
						||
| 
								 | 
							
								read rawapi.txt to gain a better understanding of the SNMP message handling.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								0 Agent Capabilities
							 | 
						||
| 
								 | 
							
								====================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								SNMPv1 per RFC1157
							 | 
						||
| 
								 | 
							
								  This is an old(er) standard but is still widely supported.
							 | 
						||
| 
								 | 
							
								  For SNMPv2c and v3 have a greater complexity and need many
							 | 
						||
| 
								 | 
							
								  more lines of code. IMHO this breaks the idea of "lightweight IP".
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Note the S in SNMP stands for "Simple". Note that "Simple" is
							 | 
						||
| 
								 | 
							
								  relative. SNMP is simple compared to the complex ISO network
							 | 
						||
| 
								 | 
							
								  management protocols CMIP (Common Management Information Protocol)
							 | 
						||
| 
								 | 
							
								  and CMOT (CMip Over Tcp).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								MIB II per RFC1213
							 | 
						||
| 
								 | 
							
								  The standard lwIP stack management information base.
							 | 
						||
| 
								 | 
							
								  This is a required MIB, so this is always enabled.
							 | 
						||
| 
								 | 
							
								  When builing lwIP without TCP, the mib-2.tcp group is omitted.
							 | 
						||
| 
								 | 
							
								  The groups EGP, CMOT and transmission are disabled by default.
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								  Most mib-2 objects are not writable except:
							 | 
						||
| 
								 | 
							
								  sysName, sysLocation, sysContact, snmpEnableAuthenTraps.
							 | 
						||
| 
								 | 
							
								  Writing to or changing the ARP and IP address and route
							 | 
						||
| 
								 | 
							
								  tables is not possible.
							 | 
						||
| 
								 | 
							
								 
							 | 
						||
| 
								 | 
							
								  Note lwIP has a very limited notion of IP routing. It currently
							 | 
						||
| 
								 | 
							
								  doen't have a route table and doesn't have a notion of the U,G,H flags.
							 | 
						||
| 
								 | 
							
								  Instead lwIP uses the interface list with only one default interface
							 | 
						||
| 
								 | 
							
								  acting as a single gateway interface (G) for the default route.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  The agent returns a "virtual table" with the default route 0.0.0.0
							 | 
						||
| 
								 | 
							
								  for the default interface and network routes (no H) for each
							 | 
						||
| 
								 | 
							
								  network interface in the netif_list.
							 | 
						||
| 
								 | 
							
								  All routes are considered to be up (U).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Loading additional MIBs
							 | 
						||
| 
								 | 
							
								  MIBs can only be added in compile-time, not in run-time.
							 | 
						||
| 
								 | 
							
								  There is no MIB compiler thus additional MIBs must be hand coded.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Large SNMP message support
							 | 
						||
| 
								 | 
							
								  The packet decoding and encoding routines are designed
							 | 
						||
| 
								 | 
							
								  to use pbuf-chains. Larger payloads than the minimum
							 | 
						||
| 
								 | 
							
								  SNMP requirement of 484 octets are supported if the 
							 | 
						||
| 
								 | 
							
								  PBUF_POOL_SIZE and IP_REASS_BUFSIZE are set to match your
							 | 
						||
| 
								 | 
							
								  local requirement.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								1 Building the Agent
							 | 
						||
| 
								 | 
							
								====================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								First of all you'll need to add the following define
							 | 
						||
| 
								 | 
							
								to your local lwipopts.h:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define LWIP_SNMP               1
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								and add the source files in lwip/src/core/snmp
							 | 
						||
| 
								 | 
							
								and some snmp headers in lwip/src/include/lwip to your makefile.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Note you'll might need to adapt you network driver to update
							 | 
						||
| 
								 | 
							
								the mib2 variables for your interface.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								2 Running the Agent
							 | 
						||
| 
								 | 
							
								===================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The following function calls must be made in your program to
							 | 
						||
| 
								 | 
							
								actually get the SNMP agent running.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Before starting the agent you should supply pointers
							 | 
						||
| 
								 | 
							
								to non-volatile memory for sysContact, sysLocation,
							 | 
						||
| 
								 | 
							
								and snmpEnableAuthenTraps. You can do this by calling
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								snmp_set_syscontact()
							 | 
						||
| 
								 | 
							
								snmp_set_syslocation()
							 | 
						||
| 
								 | 
							
								snmp_set_snmpenableauthentraps()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Additionally you may want to set
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								snmp_set_sysdescr()
							 | 
						||
| 
								 | 
							
								snmp_set_sysobjid() (if you have a private MIB)
							 | 
						||
| 
								 | 
							
								snmp_set_sysname()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Also before starting the agent you need to setup
							 | 
						||
| 
								 | 
							
								one or more trap destinations using these calls:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								snmp_trap_dst_enable();
							 | 
						||
| 
								 | 
							
								snmp_trap_dst_ip_set();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								In the lwIP initialisation sequence call snmp_init() just after
							 | 
						||
| 
								 | 
							
								the call to udp_init().
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Exactly every 10 msec the SNMP uptime timestamp must be updated with
							 | 
						||
| 
								 | 
							
								snmp_inc_sysuptime(). You should call this from a timer interrupt
							 | 
						||
| 
								 | 
							
								or a timer signal handler depending on your runtime environment.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								An alternative way to update the SNMP uptime timestamp is to do a call like
							 | 
						||
| 
								 | 
							
								snmp_add_sysuptime(100) each 1000ms (which is bigger "step", but call to
							 | 
						||
| 
								 | 
							
								a lower frequency). Another one is to not call snmp_inc_sysuptime() or
							 | 
						||
| 
								 | 
							
								snmp_add_sysuptime(), and to define the SNMP_GET_SYSUPTIME(sysuptime) macro.
							 | 
						||
| 
								 | 
							
								This one is undefined by default in mib2.c. SNMP_GET_SYSUPTIME is called inside
							 | 
						||
| 
								 | 
							
								snmp_get_sysuptime(u32_t *value), and enable to change "sysuptime" value only
							 | 
						||
| 
								 | 
							
								when it's queried (any function which need "sysuptime" have to call
							 | 
						||
| 
								 | 
							
								snmp_get_sysuptime).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								3 Private MIBs
							 | 
						||
| 
								 | 
							
								==============
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								If want to extend the agent with your own private MIB you'll need to
							 | 
						||
| 
								 | 
							
								add the following define to your local lwipopts.h:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define SNMP_PRIVATE_MIB        1
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								You must provide the private_mib.h and associated files yourself.
							 | 
						||
| 
								 | 
							
								Note we don't have a "MIB compiler" that generates C source from a MIB,
							 | 
						||
| 
								 | 
							
								so you're required to do some serious coding if you enable this!
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Note the lwIP enterprise ID (26381) is assigned to the lwIP project,
							 | 
						||
| 
								 | 
							
								ALL OBJECT IDENTIFIERS LIVING UNDER THIS ID ARE ASSIGNED BY THE lwIP
							 | 
						||
| 
								 | 
							
								MAINTAINERS!
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								If you need to create your own private MIB you'll need
							 | 
						||
| 
								 | 
							
								to apply for your own enterprise ID with IANA: http://www.iana.org/numbers.html 
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								You can set it by passing a struct snmp_obj_id to the agent
							 | 
						||
| 
								 | 
							
								using snmp_set_sysobjid(&my_object_id), just before snmp_init().
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Note the object identifiers for thes MIB-2 and your private MIB
							 | 
						||
| 
								 | 
							
								tree must be kept in sorted ascending (lexicographical) order.
							 | 
						||
| 
								 | 
							
								This to ensure correct getnext operation.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								An example for a private MIB is part of the "minimal Unix" project:
							 | 
						||
| 
								 | 
							
								contrib/ports/unix/proj/minimal/lwip_prvmib.c
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The next chapter gives a more detailed description of the
							 | 
						||
| 
								 | 
							
								MIB-2 tree and the optional private MIB.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								4 The Gory Details
							 | 
						||
| 
								 | 
							
								==================
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								4.0 Object identifiers and the MIB tree.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								We have three distinct parts for all object identifiers:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The prefix
							 | 
						||
| 
								 | 
							
								  .iso.org.dod.internet
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								the middle part 
							 | 
						||
| 
								 | 
							
								  .mgmt.mib-2.ip.ipNetToMediaTable.ipNetToMediaEntry.ipNetToMediaPhysAddress
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								and the index part
							 | 
						||
| 
								 | 
							
								  .1.192.168.0.1
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Objects located above the .internet hierarchy aren't supported.
							 | 
						||
| 
								 | 
							
								Currently only the .mgmt sub-tree is available and
							 | 
						||
| 
								 | 
							
								when the SNMP_PRIVATE_MIB is enabled the .private tree
							 | 
						||
| 
								 | 
							
								becomes available too.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Object identifiers from incoming requests are checked
							 | 
						||
| 
								 | 
							
								for a matching prefix, middle part and index part
							 | 
						||
| 
								 | 
							
								or are expanded(*) for GetNext requests with short
							 | 
						||
| 
								 | 
							
								or inexisting names in the request.
							 | 
						||
| 
								 | 
							
								(* we call this "expansion" but this also
							 | 
						||
| 
								 | 
							
								resembles the "auto-completion" operation)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The middle part is usually located in ROM (const)
							 | 
						||
| 
								 | 
							
								to preserve precious RAM on small microcontrollers.
							 | 
						||
| 
								 | 
							
								However RAM location is possible for a dynamically
							 | 
						||
| 
								 | 
							
								changing private tree.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The index part is handled by functions which in
							 | 
						||
| 
								 | 
							
								turn use dynamically allocated index trees from RAM.
							 | 
						||
| 
								 | 
							
								These trees are updated by e.g. the etharp code
							 | 
						||
| 
								 | 
							
								when new entries are made or removed form the ARP cache.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/** @todo more gory details */
							 |