LwIP的SNMP学习笔记

关于这方面的资料网上很是少,作一下笔记。html

在LwIP中,在\lwip-1.4.1\src\core\snmp目录下有SNMP相关的c文件,
在lwip-1.4.1\src\include\lwip目录下有SNMP相关的h文件,
在\lwip-1.4.1\doc目录下有一个snmp代理的说明,这是LwIP最直接的说明文档:api

 snmp_init(void)中会设置UDP接收的回调函数,这样,全部发往本机161端口的udp包都会由snmp_recv处理app

/**
 * Starts SNMP Agent.
 * Allocates UDP pcb and binds it to IP_ADDR_ANY port 161.
 */
void
snmp_init(void)
{
  struct snmp_msg_pstat *msg_ps;
  u8_t i;

  snmp1_pcb = udp_new();
  if (snmp1_pcb != NULL)
  {
    udp_recv(snmp1_pcb, snmp_recv, (void *)SNMP_IN_PORT);
    udp_bind(snmp1_pcb, IP_ADDR_ANY, SNMP_IN_PORT);
  }

snmp_recv函数中会调用snmp_pdu_header_check函数,检查SNMP PDU的头部是否正确tcp

/* lwIP UDP receive callback function */
static void
snmp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port)
  /* check total length, version, community, pdu type */
  err_ret = snmp_pdu_header_check(p, payload_ofs, payload_len, &varbind_ofs, msg_ps);
在snmp_pdu_header_check函数中,先检测type,什么type?PDU类型?但后面判断type有效性里面又不是,为何?
/**
 * Checks and decodes incoming SNMP message header, logs header errors.
 *
 * @param p points to pbuf chain of SNMP message (UDP payload)
 * @param ofs points to first octet of SNMP message
 * @param pdu_len the length of the UDP payload
 * @param ofs_ret returns the ofset of the variable bindings
 * @param m_stat points to the current message request state return
 * @return
 * - ERR_OK SNMP header is sane and accepted
 * - ERR_ARG SNMP header is either malformed or rejected
 */
static err_t
snmp_pdu_header_check(struct pbuf *p, u16_t ofs, u16_t pdu_len, u16_t *ofs_ret, struct snmp_msg_pstat *m_stat)
{
  ofs_base = ofs;
  snmp_asn1_dec_type(p, ofs, &type);
  derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len);
  if ((derr != ERR_OK) ||
      (pdu_len != (1 + len_octets + len)) ||
      (type != (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)))
  {
    snmp_inc_snmpinasnparseerrs();
    return ERR_ARG;
  }

 



SNMPv1 agent for lwIP
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". v1简单,v2和v3虽然更多功能,但须要更多代码,违背了轻量级的初衷 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). SNMP的S本意为简单,但这是相对的(与OSI的相比),其实并不简单 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.  MIB II,RFC1213是必须的MIB 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.  不能写IP地址和路由表??? 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. MIB只能经过代码实现,不能经过命令行添加 Large SNMP message support The packet decoding and encoding routines are designed to use pbuf-chains. Larger payloads then 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 mib2.c文件中 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: msg_out.c文件中 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 an 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 */

 

转载于:https://www.cnblogs.com/yanhc/p/7481571.htmlide