⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 msg_out.c

📁 《嵌入式网络系统设计-基于Atmel ARM7 系列》这个本书的光盘资料
💻 C
📖 第 1 页 / 共 2 页
字号:
/** * @file * SNMP output message processing (RFC1157). * * Output responses and traps are build in two passes: * * Pass 0: iterate over the output message backwards to determine encoding lengths * Pass 1: the actual forward encoding of internal form into ASN1 * * The single-pass encoding method described by Comer & Stevens * requires extra buffer space and copying for reversal of the packet. * The buffer requirement can be prohibitively large for big payloads * (>= 484) therefore we use the two encoding passes. *//* * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, *    this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, *    this list of conditions and the following disclaimer in the documentation *    and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products *    derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. * * Author: Christiaan Simons <christiaan.simons@axon.tv> */#include "lwip/opt.h"#if LWIP_SNMP#include "arch/cc.h"#include "lwip/udp.h"#include "lwip/netif.h"#include "lwip/snmp.h"#include "lwip/snmp_asn1.h"#include "lwip/snmp_msg.h"struct snmp_trap_dst{  /* destination IP address in network order */  struct ip_addr dip;  /* set to 0 when disabled, >0 when enabled */  u8_t enable;};#if (SNMP_TRAP_DESTINATIONS == 0)#error "need at least one trap destination"#endifstruct snmp_trap_dst trap_dst[SNMP_TRAP_DESTINATIONS];/** TRAP message structure */struct snmp_msg_trap trap_msg;static u16_t snmp_resp_header_sum(struct snmp_msg_pstat *m_stat, u16_t vb_len);static u16_t snmp_trap_header_sum(struct snmp_msg_trap *m_trap, u16_t vb_len);static u16_t snmp_varbind_list_sum(struct snmp_varbind_root *root);static u16_t snmp_resp_header_enc(struct snmp_msg_pstat *m_stat, struct pbuf *p);static u16_t snmp_trap_header_enc(struct snmp_msg_trap *m_trap, struct pbuf *p);static u16_t snmp_varbind_list_enc(struct snmp_varbind_root *root, struct pbuf *p, u16_t ofs);/** * Sets enable switch for this trap destination. * @param dst_idx index in 0 .. SNMP_TRAP_DESTINATIONS-1 * @param enable switch if 0 destination is disabled >0 enabled. */voidsnmp_trap_dst_enable(u8_t dst_idx, u8_t enable){  if (dst_idx < SNMP_TRAP_DESTINATIONS)  {    trap_dst[dst_idx].enable = enable;  }}/** * Sets IPv4 address for this trap destination. * @param dst_idx index in 0 .. SNMP_TRAP_DESTINATIONS-1 * @param dst IPv4 address in host order. */voidsnmp_trap_dst_ip_set(u8_t dst_idx, struct ip_addr *dst){  if (dst_idx < SNMP_TRAP_DESTINATIONS)  {    trap_dst[dst_idx].dip.addr = htonl(dst->addr);  }}/** * Sends a 'getresponse' message to the request originator. * * @param m_stat points to the current message request state source * @return ERR_OK when success, ERR_MEM if we're out of memory * * @note the caller is responsible for filling in outvb in the m_stat * and provide error-status and index (except for tooBig errors) ... */err_tsnmp_send_response(struct snmp_msg_pstat *m_stat){  struct snmp_varbind_root emptyvb = {NULL, NULL, 0, 0, 0};  struct pbuf *p;  u16_t tot_len;  err_t err;  /* pass 0, calculate length fields */  tot_len = snmp_varbind_list_sum(&m_stat->outvb);  tot_len = snmp_resp_header_sum(m_stat, tot_len);  /* try allocating pbuf(s) for complete response */  p = pbuf_alloc(PBUF_TRANSPORT, tot_len, PBUF_POOL);  if (p == NULL)  {    LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_snd_response() tooBig\n"));    /* can't construct reply, return error-status tooBig */    m_stat->error_status = SNMP_ES_TOOBIG;    m_stat->error_index = 0;    /* pass 0, recalculate lengths, for empty varbind-list */    tot_len = snmp_varbind_list_sum(&emptyvb);    tot_len = snmp_resp_header_sum(m_stat, tot_len);    /* retry allocation once for header and empty varbind-list */    p = pbuf_alloc(PBUF_TRANSPORT, tot_len, PBUF_POOL);  }  if (p != NULL)  {    /* first pbuf alloc try or retry alloc success */    u16_t ofs;    LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_snd_response() p != NULL\n"));    /* pass 1, size error, encode packet ino the pbuf(s) */    ofs = snmp_resp_header_enc(m_stat, p);    if (m_stat->error_status == SNMP_ES_TOOBIG)    {      snmp_varbind_list_enc(&emptyvb, p, ofs);    }    else    {      snmp_varbind_list_enc(&m_stat->outvb, p, ofs);    }    switch (m_stat->error_status)    {      case SNMP_ES_TOOBIG:        snmp_inc_snmpouttoobigs();        break;      case SNMP_ES_NOSUCHNAME:        snmp_inc_snmpoutnosuchnames();        break;      case SNMP_ES_BADVALUE:        snmp_inc_snmpoutbadvalues();        break;      case SNMP_ES_GENERROR:        snmp_inc_snmpoutgenerrs();        break;    }    snmp_inc_snmpoutgetresponses();    snmp_inc_snmpoutpkts();    /** @todo do we need separate rx and tx pcbs for threaded case? */    /** connect to the originating source */    udp_connect(m_stat->pcb, &m_stat->sip, m_stat->sp);    err = udp_send(m_stat->pcb, p);    if (err == ERR_MEM)    {      /** @todo release some memory, retry and return tooBig? tooMuchHassle? */      err = ERR_MEM;    }    else    {      err = ERR_OK;    }    /** disassociate remote address and port with this pcb */    udp_disconnect(m_stat->pcb);    pbuf_free(p);    LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_snd_response() done\n"));    return err;  }  else  {    /* first pbuf alloc try or retry alloc failed       very low on memory, couldn't return tooBig */    return ERR_MEM;  }}/** * Sends an generic or enterprise specific trap message. * * @param generic_trap is the trap code * @param eoid points to enterprise object identifier * @param specific_trap used for enterprise traps when generic_trap == 6 * @return ERR_OK when success, ERR_MEM if we're out of memory * * @note the caller is responsible for filling in outvb in the trap_msg * @note the use of the enterpise identifier field * is per RFC1215. * Use .iso.org.dod.internet.mgmt.mib-2.snmp for generic traps * and .iso.org.dod.internet.private.enterprises.yourenterprise * (sysObjectID) for specific traps. */err_tsnmp_send_trap(s8_t generic_trap, struct snmp_obj_id *eoid, s32_t specific_trap){  struct snmp_trap_dst *td;  struct netif *dst_if;  struct ip_addr dst_ip;  struct pbuf *p;  u16_t i,tot_len;  for (i=0, td = &trap_dst[0]; i<SNMP_TRAP_DESTINATIONS; i++, td++)  {    if ((td->enable != 0) && (td->dip.addr != 0))    {      /* network order trap destination */      trap_msg.dip.addr = td->dip.addr;      /* lookup current source address for this dst */      dst_if = ip_route(&td->dip);      dst_ip.addr = ntohl(dst_if->ip_addr.addr);      trap_msg.sip_raw[0] = dst_ip.addr >> 24;      trap_msg.sip_raw[1] = dst_ip.addr >> 16;      trap_msg.sip_raw[2] = dst_ip.addr >> 8;      trap_msg.sip_raw[3] = dst_ip.addr;      trap_msg.gen_trap = generic_trap;      trap_msg.spc_trap = specific_trap;      if (generic_trap == SNMP_GENTRAP_ENTERPRISESPC)      {        /* enterprise-Specific trap */        trap_msg.enterprise = eoid;      }      else      {        /* generic (MIB-II) trap */        snmp_get_snmpgrpid_ptr(&trap_msg.enterprise);      }      snmp_get_sysuptime(&trap_msg.ts);      /* pass 0, calculate length fields */      tot_len = snmp_varbind_list_sum(&trap_msg.outvb);      tot_len = snmp_trap_header_sum(&trap_msg, tot_len);      /* allocate pbuf(s) */      p = pbuf_alloc(PBUF_TRANSPORT, tot_len, PBUF_POOL);      if (p != NULL)      {        u16_t ofs;        /* pass 1, encode packet ino the pbuf(s) */        ofs = snmp_trap_header_enc(&trap_msg, p);        snmp_varbind_list_enc(&trap_msg.outvb, p, ofs);        snmp_inc_snmpouttraps();        snmp_inc_snmpoutpkts();        /** connect to the TRAP destination */        udp_connect(trap_msg.pcb, &trap_msg.dip, SNMP_TRAP_PORT);        udp_send(trap_msg.pcb, p);        /** disassociate remote address and port with this pcb */        udp_disconnect(trap_msg.pcb);        pbuf_free(p);      }      else      {        return ERR_MEM;      }    }  }  return ERR_OK;}voidsnmp_coldstart_trap(void){  trap_msg.outvb.head = NULL;  trap_msg.outvb.tail = NULL;  trap_msg.outvb.count = 0;  snmp_send_trap(SNMP_GENTRAP_COLDSTART, NULL, 0);}voidsnmp_authfail_trap(void){  u8_t enable;  snmp_get_snmpenableauthentraps(&enable);  if (enable == 1)  {    trap_msg.outvb.head = NULL;    trap_msg.outvb.tail = NULL;    trap_msg.outvb.count = 0;    snmp_send_trap(SNMP_GENTRAP_AUTHFAIL, NULL, 0);  }}/** * Sums response header field lengths from tail to head and * returns resp_header_lengths for second encoding pass. * * @param vb_len varbind-list length * @param rhl points to returned header lengths * @return the required lenght for encoding the response header */static u16_tsnmp_resp_header_sum(struct snmp_msg_pstat *m_stat, u16_t vb_len){  u16_t tot_len;  struct snmp_resp_header_lengths *rhl;  rhl = &m_stat->rhl;  tot_len = vb_len;  snmp_asn1_enc_s32t_cnt(m_stat->error_index, &rhl->erridxlen);  snmp_asn1_enc_length_cnt(rhl->erridxlen, &rhl->erridxlenlen);  tot_len += 1 + rhl->erridxlenlen + rhl->erridxlen;  snmp_asn1_enc_s32t_cnt(m_stat->error_status, &rhl->errstatlen);  snmp_asn1_enc_length_cnt(rhl->errstatlen, &rhl->errstatlenlen);  tot_len += 1 + rhl->errstatlenlen + rhl->errstatlen;  snmp_asn1_enc_s32t_cnt(m_stat->rid, &rhl->ridlen);  snmp_asn1_enc_length_cnt(rhl->ridlen, &rhl->ridlenlen);  tot_len += 1 + rhl->ridlenlen + rhl->ridlen;  rhl->pdulen = tot_len;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -