[C] lwip-1.3.1 →→→→→进入此内容的聊天室

来自 , 2021-01-07, 写在 C, 查看 125 次.
URL http://www.code666.cn/view/3f998e71
  1. /**
  2.  * @file
  3.  * SNMP input message processing (RFC1157).
  4.  */
  5.  
  6. /*
  7.  * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands.
  8.  * All rights reserved.
  9.  *
  10.  * Redistribution and use in source and binary forms, with or without modification,
  11.  * are permitted provided that the following conditions are met:
  12.  *
  13.  * 1. Redistributions of source code must retain the above copyright notice,
  14.  *    this list of conditions and the following disclaimer.
  15.  * 2. Redistributions in binary form must reproduce the above copyright notice,
  16.  *    this list of conditions and the following disclaimer in the documentation
  17.  *    and/or other materials provided with the distribution.
  18.  * 3. The name of the author may not be used to endorse or promote products
  19.  *    derived from this software without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
  22.  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  23.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
  24.  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  25.  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
  26.  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  27.  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  28.  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  29.  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  30.  * OF SUCH DAMAGE.
  31.  *
  32.  * Author: Christiaan Simons <christiaan.simons@axon.tv>
  33.  */
  34.  
  35. #include "lwip/opt.h"
  36.  
  37. #if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */
  38.  
  39. #include "lwip/ip_addr.h"
  40. #include "lwip/mem.h"
  41. #include "lwip/udp.h"
  42. #include "lwip/stats.h"
  43. #include "lwip/snmp.h"
  44. #include "lwip/snmp_asn1.h"
  45. #include "lwip/snmp_msg.h"
  46. #include "lwip/snmp_structs.h"
  47.  
  48. #include <string.h>
  49.  
  50. /* public (non-static) constants */
  51. /** SNMP v1 == 0 */
  52. const s32_t snmp_version = 0;
  53. /** default SNMP community string */
  54. const char snmp_publiccommunity[7] = "public1";
  55.  
  56. /* statically allocated buffers for SNMP_CONCURRENT_REQUESTS */
  57. struct snmp_msg_pstat msg_input_list[SNMP_CONCURRENT_REQUESTS];
  58. /* UDP Protocol Control Block */
  59. struct udp_pcb *snmp1_pcb;
  60.  
  61. static void snmp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port);
  62. 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);
  63. static err_t snmp_pdu_dec_varbindlist(struct pbuf *p, u16_t ofs, u16_t *ofs_ret, struct snmp_msg_pstat *m_stat);
  64.  
  65.  
  66. /**
  67.  * Starts SNMP Agent.
  68.  * Allocates UDP pcb and binds it to IP_ADDR_ANY port 161.
  69.  */
  70. void
  71. snmp_init(void)
  72. {
  73.   struct snmp_msg_pstat *msg_ps;
  74.   u8_t i;
  75.  
  76.   snmp1_pcb = udp_new();
  77.   if (snmp1_pcb != NULL)
  78.   {
  79.     udp_recv(snmp1_pcb, snmp_recv, (void *)SNMP_IN_PORT);
  80.     udp_bind(snmp1_pcb, IP_ADDR_ANY, SNMP_IN_PORT);
  81.   }
  82.   msg_ps = &msg_input_list[0];
  83.   for (i=0; i<SNMP_CONCURRENT_REQUESTS; i++)
  84.   {
  85.     msg_ps->state = SNMP_MSG_EMPTY;
  86.     msg_ps->error_index = 0;
  87.     msg_ps->error_status = SNMP_ES_NOERROR;
  88.     msg_ps++;
  89.   }
  90.   trap_msg.pcb = snmp1_pcb;
  91.   /* The coldstart trap will only be output
  92.      if our outgoing interface is up & configured  */
  93.   snmp_coldstart_trap();
  94. }
  95.  
  96. static void
  97. snmp_error_response(struct snmp_msg_pstat *msg_ps, u8_t error)
  98. {
  99.   snmp_varbind_list_free(&msg_ps->outvb);
  100.   msg_ps->outvb = msg_ps->invb;
  101.   msg_ps->invb.head = NULL;
  102.   msg_ps->invb.tail = NULL;
  103.   msg_ps->invb.count = 0;
  104.   msg_ps->error_status = error;
  105.   msg_ps->error_index = 1 + msg_ps->vb_idx;
  106.   snmp_send_response(msg_ps);
  107.   snmp_varbind_list_free(&msg_ps->outvb);
  108.   msg_ps->state = SNMP_MSG_EMPTY;
  109. }
  110.  
  111. static void
  112. snmp_ok_response(struct snmp_msg_pstat *msg_ps)
  113. {
  114.   err_t err_ret;
  115.  
  116.   err_ret = snmp_send_response(msg_ps);
  117.   if (err_ret == ERR_MEM)
  118.   {
  119.     /* serious memory problem, can't return tooBig */
  120.   }
  121.   else
  122.   {
  123.     LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_event = %"S32_F"\n",msg_ps->error_status));
  124.   }
  125.   /* free varbinds (if available) */
  126.   snmp_varbind_list_free(&msg_ps->invb);
  127.   snmp_varbind_list_free(&msg_ps->outvb);
  128.   msg_ps->state = SNMP_MSG_EMPTY;
  129. }
  130.  
  131. /**
  132.  * Service an internal or external event for SNMP GET.
  133.  *
  134.  * @param request_id identifies requests from 0 to (SNMP_CONCURRENT_REQUESTS-1)
  135.  * @param msg_ps points to the assosicated message process state
  136.  */
  137. static void
  138. snmp_msg_get_event(u8_t request_id, struct snmp_msg_pstat *msg_ps)
  139. {
  140.   LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_get_event: msg_ps->state==%"U16_F"\n",(u16_t)msg_ps->state));
  141.  
  142.   if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_OBJDEF)
  143.   {
  144.     struct mib_external_node *en;
  145.     struct snmp_name_ptr np;
  146.  
  147.     /* get_object_def() answer*/
  148.     en = msg_ps->ext_mib_node;
  149.     np = msg_ps->ext_name_ptr;
  150.  
  151.     /* translate answer into a known lifeform */
  152.     en->get_object_def_a(request_id, np.ident_len, np.ident, &msg_ps->ext_object_def);
  153.     if (msg_ps->ext_object_def.instance != MIB_OBJECT_NONE)
  154.     {
  155.       msg_ps->state = SNMP_MSG_EXTERNAL_GET_VALUE;
  156.       en->get_value_q(request_id, &msg_ps->ext_object_def);
  157.     }
  158.     else
  159.     {
  160.       en->get_object_def_pc(request_id, np.ident_len, np.ident);
  161.       /* search failed, object id points to unknown object (nosuchname) */
  162.       snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME);
  163.     }
  164.   }
  165.   else if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_VALUE)
  166.   {
  167.     struct mib_external_node *en;
  168.     struct snmp_varbind *vb;
  169.  
  170.     /* get_value() answer */
  171.     en = msg_ps->ext_mib_node;
  172.  
  173.     /* allocate output varbind */
  174.     vb = (struct snmp_varbind *)mem_malloc(sizeof(struct snmp_varbind));
  175.     LWIP_ASSERT("vb != NULL",vb != NULL);
  176.     if (vb != NULL)
  177.     {
  178.       vb->next = NULL;
  179.       vb->prev = NULL;
  180.  
  181.       /* move name from invb to outvb */
  182.       vb->ident = msg_ps->vb_ptr->ident;
  183.       vb->ident_len = msg_ps->vb_ptr->ident_len;
  184.       /* ensure this memory is refereced once only */
  185.       msg_ps->vb_ptr->ident = NULL;
  186.       msg_ps->vb_ptr->ident_len = 0;
  187.  
  188.       vb->value_type = msg_ps->ext_object_def.asn_type;
  189.       vb->value_len =  msg_ps->ext_object_def.v_len;
  190.       if (vb->value_len > 0)
  191.       {
  192.         vb->value = mem_malloc(vb->value_len);
  193.         LWIP_ASSERT("vb->value != NULL",vb->value != NULL);
  194.         if (vb->value != NULL)
  195.         {
  196.           en->get_value_a(request_id, &msg_ps->ext_object_def, vb->value_len, vb->value);
  197.           snmp_varbind_tail_add(&msg_ps->outvb, vb);
  198.           /* search again (if vb_idx < msg_ps->invb.count) */
  199.           msg_ps->state = SNMP_MSG_SEARCH_OBJ;
  200.           msg_ps->vb_idx += 1;
  201.         }
  202.         else
  203.         {
  204.           en->get_value_pc(request_id, &msg_ps->ext_object_def);
  205.           LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_event: no variable space\n"));
  206.           msg_ps->vb_ptr->ident = vb->ident;
  207.           msg_ps->vb_ptr->ident_len = vb->ident_len;
  208.           mem_free(vb);
  209.           snmp_error_response(msg_ps,SNMP_ES_TOOBIG);
  210.         }
  211.       }
  212.       else
  213.       {
  214.         /* vb->value_len == 0, empty value (e.g. empty string) */
  215.         en->get_value_a(request_id, &msg_ps->ext_object_def, 0, NULL);
  216.         vb->value = NULL;
  217.         snmp_varbind_tail_add(&msg_ps->outvb, vb);
  218.         /* search again (if vb_idx < msg_ps->invb.count) */
  219.         msg_ps->state = SNMP_MSG_SEARCH_OBJ;
  220.         msg_ps->vb_idx += 1;
  221.       }
  222.     }
  223.     else
  224.     {
  225.       en->get_value_pc(request_id, &msg_ps->ext_object_def);
  226.       LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_event: no outvb space\n"));
  227.       snmp_error_response(msg_ps,SNMP_ES_TOOBIG);
  228.     }
  229.   }
  230.  
  231.   while ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) &&
  232.          (msg_ps->vb_idx < msg_ps->invb.count))
  233.   {
  234.     struct mib_node *mn;
  235.     struct snmp_name_ptr np;
  236.  
  237.     if (msg_ps->vb_idx == 0)
  238.     {
  239.       msg_ps->vb_ptr = msg_ps->invb.head;
  240.     }
  241.     else
  242.     {
  243.       msg_ps->vb_ptr = msg_ps->vb_ptr->next;
  244.     }
  245.     /** test object identifier for .iso.org.dod.internet prefix */
  246.     if (snmp_iso_prefix_tst(msg_ps->vb_ptr->ident_len,  msg_ps->vb_ptr->ident))
  247.     {
  248.       mn = snmp_search_tree((struct mib_node*)&internet, msg_ps->vb_ptr->ident_len - 4,
  249.                              msg_ps->vb_ptr->ident + 4, &np);
  250.       if (mn != NULL)
  251.       {
  252.         if (mn->node_type == MIB_NODE_EX)
  253.         {
  254.           /* external object */
  255.           struct mib_external_node *en = (struct mib_external_node*)mn;
  256.  
  257.           msg_ps->state = SNMP_MSG_EXTERNAL_GET_OBJDEF;
  258.           /* save en && args in msg_ps!! */
  259.           msg_ps->ext_mib_node = en;
  260.           msg_ps->ext_name_ptr = np;
  261.  
  262.           en->get_object_def_q(en->addr_inf, request_id, np.ident_len, np.ident);
  263.         }
  264.         else
  265.         {
  266.           /* internal object */
  267.           struct obj_def object_def;
  268.  
  269.           msg_ps->state = SNMP_MSG_INTERNAL_GET_OBJDEF;
  270.           mn->get_object_def(np.ident_len, np.ident, &object_def);
  271.           if (object_def.instance != MIB_OBJECT_NONE)
  272.           {
  273.             mn = mn;
  274.           }
  275.           else
  276.           {
  277.             /* search failed, object id points to unknown object (nosuchname) */
  278.             mn =  NULL;
  279.           }
  280.           if (mn != NULL)
  281.           {
  282.             struct snmp_varbind *vb;
  283.  
  284.             msg_ps->state = SNMP_MSG_INTERNAL_GET_VALUE;
  285.             /* allocate output varbind */
  286.             vb = (struct snmp_varbind *)mem_malloc(sizeof(struct snmp_varbind));
  287.             LWIP_ASSERT("vb != NULL",vb != NULL);
  288.             if (vb != NULL)
  289.             {
  290.               vb->next = NULL;
  291.               vb->prev = NULL;
  292.  
  293.               /* move name from invb to outvb */
  294.               vb->ident = msg_ps->vb_ptr->ident;
  295.               vb->ident_len = msg_ps->vb_ptr->ident_len;
  296.               /* ensure this memory is refereced once only */
  297.               msg_ps->vb_ptr->ident = NULL;
  298.               msg_ps->vb_ptr->ident_len = 0;
  299.  
  300.               vb->value_type = object_def.asn_type;
  301.               vb->value_len = object_def.v_len;
  302.               if (vb->value_len > 0)
  303.               {
  304.                 vb->value = mem_malloc(vb->value_len);
  305.                 LWIP_ASSERT("vb->value != NULL",vb->value != NULL);
  306.                 if (vb->value != NULL)
  307.                 {
  308.                   mn->get_value(&object_def, vb->value_len, vb->value);
  309.                   snmp_varbind_tail_add(&msg_ps->outvb, vb);
  310.                   msg_ps->state = SNMP_MSG_SEARCH_OBJ;
  311.                   msg_ps->vb_idx += 1;
  312.                 }
  313.                 else
  314.                 {
  315.                   LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_event: couldn't allocate variable space\n"));
  316.                   msg_ps->vb_ptr->ident = vb->ident;
  317.                   msg_ps->vb_ptr->ident_len = vb->ident_len;
  318.                   mem_free(vb);
  319.                   snmp_error_response(msg_ps,SNMP_ES_TOOBIG);
  320.                 }
  321.               }
  322.               else
  323.               {
  324.                 /* vb->value_len == 0, empty value (e.g. empty string) */
  325.                 vb->value = NULL;
  326.                 snmp_varbind_tail_add(&msg_ps->outvb, vb);
  327.                 msg_ps->state = SNMP_MSG_SEARCH_OBJ;
  328.                 msg_ps->vb_idx += 1;
  329.               }
  330.             }
  331.             else
  332.             {
  333.               LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_event: couldn't allocate outvb space\n"));
  334.               snmp_error_response(msg_ps,SNMP_ES_TOOBIG);
  335.             }
  336.           }
  337.         }
  338.       }
  339.     }
  340.     else
  341.     {
  342.       mn = NULL;
  343.     }
  344.     if (mn == NULL)
  345.     {
  346.       /* mn == NULL, noSuchName */
  347.       snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME);
  348.     }
  349.   }
  350.   if ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) &&
  351.       (msg_ps->vb_idx == msg_ps->invb.count))
  352.   {
  353.     snmp_ok_response(msg_ps);
  354.   }
  355. }
  356.  
  357. /**
  358.  * Service an internal or external event for SNMP GETNEXT.
  359.  *
  360.  * @param request_id identifies requests from 0 to (SNMP_CONCURRENT_REQUESTS-1)
  361.  * @param msg_ps points to the assosicated message process state
  362.  */
  363. static void
  364. snmp_msg_getnext_event(u8_t request_id, struct snmp_msg_pstat *msg_ps)
  365. {
  366.   LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_getnext_event: msg_ps->state==%"U16_F"\n",(u16_t)msg_ps->state));
  367.  
  368.   if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_OBJDEF)
  369.   {
  370.     struct mib_external_node *en;
  371.  
  372.     /* get_object_def() answer*/
  373.     en = msg_ps->ext_mib_node;
  374.  
  375.     /* translate answer into a known lifeform */
  376.     en->get_object_def_a(request_id, 1, &msg_ps->ext_oid.id[msg_ps->ext_oid.len - 1], &msg_ps->ext_object_def);
  377.     if (msg_ps->ext_object_def.instance != MIB_OBJECT_NONE)
  378.     {
  379.       msg_ps->state = SNMP_MSG_EXTERNAL_GET_VALUE;
  380.       en->get_value_q(request_id, &msg_ps->ext_object_def);
  381.     }
  382.     else
  383.     {
  384.       en->get_object_def_pc(request_id, 1, &msg_ps->ext_oid.id[msg_ps->ext_oid.len - 1]);
  385.       /* search failed, object id points to unknown object (nosuchname) */
  386.       snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME);
  387.     }
  388.   }
  389.   else if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_VALUE)
  390.   {
  391.     struct mib_external_node *en;
  392.     struct snmp_varbind *vb;
  393.  
  394.     /* get_value() answer */
  395.     en = msg_ps->ext_mib_node;
  396.  
  397.     vb = snmp_varbind_alloc(&msg_ps->ext_oid,
  398.                             msg_ps->ext_object_def.asn_type,
  399.                             msg_ps->ext_object_def.v_len);
  400.     if (vb != NULL)
  401.     {
  402.       en->get_value_a(request_id, &msg_ps->ext_object_def, vb->value_len, vb->value);
  403.       snmp_varbind_tail_add(&msg_ps->outvb, vb);
  404.       msg_ps->state = SNMP_MSG_SEARCH_OBJ;
  405.       msg_ps->vb_idx += 1;
  406.     }
  407.     else
  408.     {
  409.       en->get_value_pc(request_id, &msg_ps->ext_object_def);
  410.       LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_getnext_event: couldn't allocate outvb space\n"));
  411.       snmp_error_response(msg_ps,SNMP_ES_TOOBIG);
  412.     }
  413.   }
  414.  
  415.   while ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) &&
  416.          (msg_ps->vb_idx < msg_ps->invb.count))
  417.   {
  418.     struct mib_node *mn;
  419.     struct snmp_obj_id oid;
  420.  
  421.     if (msg_ps->vb_idx == 0)
  422.     {
  423.       msg_ps->vb_ptr = msg_ps->invb.head;
  424.     }
  425.     else
  426.     {
  427.       msg_ps->vb_ptr = msg_ps->vb_ptr->next;
  428.     }
  429.     if (snmp_iso_prefix_expand(msg_ps->vb_ptr->ident_len, msg_ps->vb_ptr->ident, &oid))
  430.     {
  431.       if (msg_ps->vb_ptr->ident_len > 3)
  432.       {
  433.         /* can offset ident_len and ident */
  434.         mn = snmp_expand_tree((struct mib_node*)&internet,
  435.                               msg_ps->vb_ptr->ident_len - 4,
  436.                               msg_ps->vb_ptr->ident + 4, &oid);
  437.       }
  438.       else
  439.       {
  440.         /* can't offset ident_len -4, ident + 4 */
  441.         mn = snmp_expand_tree((struct mib_node*)&internet, 0, NULL, &oid);
  442.       }
  443.     }
  444.     else
  445.     {
  446.       mn = NULL;
  447.     }
  448.     if (mn != NULL)
  449.     {
  450.       if (mn->node_type == MIB_NODE_EX)
  451.       {
  452.         /* external object */
  453.         struct mib_external_node *en = (struct mib_external_node*)mn;
  454.  
  455.         msg_ps->state = SNMP_MSG_EXTERNAL_GET_OBJDEF;
  456.         /* save en && args in msg_ps!! */
  457.         msg_ps->ext_mib_node = en;
  458.         msg_ps->ext_oid = oid;
  459.  
  460.         en->get_object_def_q(en->addr_inf, request_id, 1, &oid.id[oid.len - 1]);
  461.       }
  462.       else
  463.       {
  464.         /* internal object */
  465.         struct obj_def object_def;
  466.         struct snmp_varbind *vb;
  467.  
  468.         msg_ps->state = SNMP_MSG_INTERNAL_GET_OBJDEF;
  469.         mn->get_object_def(1, &oid.id[oid.len - 1], &object_def);
  470.  
  471.         vb = snmp_varbind_alloc(&oid, object_def.asn_type, object_def.v_len);
  472.         if (vb != NULL)
  473.         {
  474.           msg_ps->state = SNMP_MSG_INTERNAL_GET_VALUE;
  475.           mn->get_value(&object_def, object_def.v_len, vb->value);
  476.           snmp_varbind_tail_add(&msg_ps->outvb, vb);
  477.           msg_ps->state = SNMP_MSG_SEARCH_OBJ;
  478.           msg_ps->vb_idx += 1;
  479.         }
  480.         else
  481.         {
  482.           LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_recv couldn't allocate outvb space\n"));
  483.           snmp_error_response(msg_ps,SNMP_ES_TOOBIG);
  484.         }
  485.       }
  486.     }
  487.     if (mn == NULL)
  488.     {
  489.       /* mn == NULL, noSuchName */
  490.       snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME);
  491.     }
  492.   }
  493.   if ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) &&
  494.       (msg_ps->vb_idx == msg_ps->invb.count))
  495.   {
  496.     snmp_ok_response(msg_ps);
  497.   }
  498. }
  499.  
  500. /**
  501.  * Service an internal or external event for SNMP SET.
  502.  *
  503.  * @param request_id identifies requests from 0 to (SNMP_CONCURRENT_REQUESTS-1)
  504.  * @param msg_ps points to the assosicated message process state
  505.  */
  506. static void
  507. snmp_msg_set_event(u8_t request_id, struct snmp_msg_pstat *msg_ps)
  508. {
  509.   LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_set_event: msg_ps->state==%"U16_F"\n",(u16_t)msg_ps->state));
  510.  
  511.   if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_OBJDEF)
  512.   {
  513.     struct mib_external_node *en;
  514.     struct snmp_name_ptr np;
  515.  
  516.     /* get_object_def() answer*/
  517.     en = msg_ps->ext_mib_node;
  518.     np = msg_ps->ext_name_ptr;
  519.  
  520.     /* translate answer into a known lifeform */
  521.     en->get_object_def_a(request_id, np.ident_len, np.ident, &msg_ps->ext_object_def);
  522.     if (msg_ps->ext_object_def.instance != MIB_OBJECT_NONE)
  523.     {
  524.       msg_ps->state = SNMP_MSG_EXTERNAL_SET_TEST;
  525.       en->set_test_q(request_id, &msg_ps->ext_object_def);
  526.     }
  527.     else
  528.     {
  529.       en->get_object_def_pc(request_id, np.ident_len, np.ident);
  530.       /* search failed, object id points to unknown object (nosuchname) */
  531.       snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME);
  532.     }
  533.   }
  534.   else if (msg_ps->state == SNMP_MSG_EXTERNAL_SET_TEST)
  535.   {
  536.     struct mib_external_node *en;
  537.  
  538.     /* set_test() answer*/
  539.     en = msg_ps->ext_mib_node;
  540.  
  541.     if (msg_ps->ext_object_def.access == MIB_OBJECT_READ_WRITE)
  542.     {
  543.        if ((msg_ps->ext_object_def.asn_type == msg_ps->vb_ptr->value_type) &&
  544.            (en->set_test_a(request_id,&msg_ps->ext_object_def,
  545.                            msg_ps->vb_ptr->value_len,msg_ps->vb_ptr->value) != 0))
  546.       {
  547.         msg_ps->state = SNMP_MSG_SEARCH_OBJ;
  548.         msg_ps->vb_idx += 1;
  549.       }
  550.       else
  551.       {
  552.         en->set_test_pc(request_id,&msg_ps->ext_object_def);
  553.         /* bad value */
  554.         snmp_error_response(msg_ps,SNMP_ES_BADVALUE);
  555.       }
  556.     }
  557.     else
  558.     {
  559.       en->set_test_pc(request_id,&msg_ps->ext_object_def);
  560.       /* object not available for set */
  561.       snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME);
  562.     }
  563.   }
  564.   else if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_OBJDEF_S)
  565.   {
  566.     struct mib_external_node *en;
  567.     struct snmp_name_ptr np;
  568.  
  569.     /* get_object_def() answer*/
  570.     en = msg_ps->ext_mib_node;
  571.     np = msg_ps->ext_name_ptr;
  572.  
  573.     /* translate answer into a known lifeform */
  574.     en->get_object_def_a(request_id, np.ident_len, np.ident, &msg_ps->ext_object_def);
  575.     if (msg_ps->ext_object_def.instance != MIB_OBJECT_NONE)
  576.     {
  577.       msg_ps->state = SNMP_MSG_EXTERNAL_SET_VALUE;
  578.       en->set_value_q(request_id, &msg_ps->ext_object_def,
  579.                       msg_ps->vb_ptr->value_len,msg_ps->vb_ptr->value);
  580.     }
  581.     else
  582.     {
  583.       en->get_object_def_pc(request_id, np.ident_len, np.ident);
  584.       /* set_value failed, object has disappeared for some odd reason?? */
  585.       snmp_error_response(msg_ps,SNMP_ES_GENERROR);
  586.     }
  587.   }
  588.   else if (msg_ps->state == SNMP_MSG_EXTERNAL_SET_VALUE)
  589.   {
  590.     struct mib_external_node *en;
  591.  
  592.     /** set_value_a() */
  593.     en = msg_ps->ext_mib_node;
  594.     en->set_value_a(request_id, &msg_ps->ext_object_def,
  595.       msg_ps->vb_ptr->value_len, msg_ps->vb_ptr->value);
  596.  
  597.     /** @todo use set_value_pc() if toobig */
  598.     msg_ps->state = SNMP_MSG_INTERNAL_SET_VALUE;
  599.     msg_ps->vb_idx += 1;
  600.   }
  601.  
  602.   /* test all values before setting */
  603.   while ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) &&
  604.          (msg_ps->vb_idx < msg_ps->invb.count))
  605.   {
  606.     struct mib_node *mn;
  607.     struct snmp_name_ptr np;
  608.  
  609.     if (msg_ps->vb_idx == 0)
  610.     {
  611.       msg_ps->vb_ptr = msg_ps->invb.head;
  612.     }
  613.     else
  614.     {
  615.       msg_ps->vb_ptr = msg_ps->vb_ptr->next;
  616.     }
  617.     /** test object identifier for .iso.org.dod.internet prefix */
  618.     if (snmp_iso_prefix_tst(msg_ps->vb_ptr->ident_len,  msg_ps->vb_ptr->ident))
  619.     {
  620.       mn = snmp_search_tree((struct mib_node*)&internet, msg_ps->vb_ptr->ident_len - 4,
  621.                              msg_ps->vb_ptr->ident + 4, &np);
  622.       if (mn != NULL)
  623.       {
  624.         if (mn->node_type == MIB_NODE_EX)
  625.         {
  626.           /* external object */
  627.           struct mib_external_node *en = (struct mib_external_node*)mn;
  628.  
  629.           msg_ps->state = SNMP_MSG_EXTERNAL_GET_OBJDEF;
  630.           /* save en && args in msg_ps!! */
  631.           msg_ps->ext_mib_node = en;
  632.           msg_ps->ext_name_ptr = np;
  633.  
  634.           en->get_object_def_q(en->addr_inf, request_id, np.ident_len, np.ident);
  635.         }
  636.         else
  637.         {
  638.           /* internal object */
  639.           struct obj_def object_def;
  640.  
  641.           msg_ps->state = SNMP_MSG_INTERNAL_GET_OBJDEF;
  642.           mn->get_object_def(np.ident_len, np.ident, &object_def);
  643.           if (object_def.instance != MIB_OBJECT_NONE)
  644.           {
  645.             mn = mn;
  646.           }
  647.           else
  648.           {
  649.             /* search failed, object id points to unknown object (nosuchname) */
  650.             mn = NULL;
  651.           }
  652.           if (mn != NULL)
  653.           {
  654.             msg_ps->state = SNMP_MSG_INTERNAL_SET_TEST;
  655.  
  656.             if (object_def.access == MIB_OBJECT_READ_WRITE)
  657.             {
  658.               if ((object_def.asn_type == msg_ps->vb_ptr->value_type) &&
  659.                   (mn->set_test(&object_def,msg_ps->vb_ptr->value_len,msg_ps->vb_ptr->value) != 0))
  660.               {
  661.                 msg_ps->state = SNMP_MSG_SEARCH_OBJ;
  662.                 msg_ps->vb_idx += 1;
  663.               }
  664.               else
  665.               {
  666.                 /* bad value */
  667.                 snmp_error_response(msg_ps,SNMP_ES_BADVALUE);
  668.               }
  669.             }
  670.             else
  671.             {
  672.               /* object not available for set */
  673.               snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME);
  674.             }
  675.           }
  676.         }
  677.       }
  678.     }
  679.     else
  680.     {
  681.       mn = NULL;
  682.     }
  683.     if (mn == NULL)
  684.     {
  685.       /* mn == NULL, noSuchName */
  686.       snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME);
  687.     }
  688.   }
  689.  
  690.   if ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) &&
  691.       (msg_ps->vb_idx == msg_ps->invb.count))
  692.   {
  693.     msg_ps->vb_idx = 0;
  694.     msg_ps->state = SNMP_MSG_INTERNAL_SET_VALUE;
  695.   }
  696.  
  697.   /* set all values "atomically" (be as "atomic" as possible) */
  698.   while ((msg_ps->state == SNMP_MSG_INTERNAL_SET_VALUE) &&
  699.          (msg_ps->vb_idx < msg_ps->invb.count))
  700.   {
  701.     struct mib_node *mn;
  702.     struct snmp_name_ptr np;
  703.  
  704.     if (msg_ps->vb_idx == 0)
  705.     {
  706.       msg_ps->vb_ptr = msg_ps->invb.head;
  707.     }
  708.     else
  709.     {
  710.       msg_ps->vb_ptr = msg_ps->vb_ptr->next;
  711.     }
  712.     /* skip iso prefix test, was done previously while settesting() */
  713.     mn = snmp_search_tree((struct mib_node*)&internet, msg_ps->vb_ptr->ident_len - 4,
  714.                            msg_ps->vb_ptr->ident + 4, &np);
  715.     /* check if object is still available
  716.        (e.g. external hot-plug thingy present?) */
  717.     if (mn != NULL)
  718.     {
  719.       if (mn->node_type == MIB_NODE_EX)
  720.       {
  721.         /* external object */
  722.         struct mib_external_node *en = (struct mib_external_node*)mn;
  723.  
  724.         msg_ps->state = SNMP_MSG_EXTERNAL_GET_OBJDEF_S;
  725.         /* save en && args in msg_ps!! */
  726.         msg_ps->ext_mib_node = en;
  727.         msg_ps->ext_name_ptr = np;
  728.  
  729.         en->get_object_def_q(en->addr_inf, request_id, np.ident_len, np.ident);
  730.       }
  731.       else
  732.       {
  733.         /* internal object */
  734.         struct obj_def object_def;
  735.  
  736.         msg_ps->state = SNMP_MSG_INTERNAL_GET_OBJDEF_S;
  737.         mn->get_object_def(np.ident_len, np.ident, &object_def);
  738.         msg_ps->state = SNMP_MSG_INTERNAL_SET_VALUE;
  739.         mn->set_value(&object_def,msg_ps->vb_ptr->value_len,msg_ps->vb_ptr->value);
  740.         msg_ps->vb_idx += 1;
  741.       }
  742.     }
  743.   }
  744.   if ((msg_ps->state == SNMP_MSG_INTERNAL_SET_VALUE) &&
  745.       (msg_ps->vb_idx == msg_ps->invb.count))
  746.   {
  747.     /* simply echo the input if we can set it
  748.        @todo do we need to return the actual value?
  749.        e.g. if value is silently modified or behaves sticky? */
  750.     msg_ps->outvb = msg_ps->invb;
  751.     msg_ps->invb.head = NULL;
  752.     msg_ps->invb.tail = NULL;
  753.     msg_ps->invb.count = 0;
  754.     snmp_ok_response(msg_ps);
  755.   }
  756. }
  757.  
  758.  
  759. /**
  760.  * Handle one internal or external event.
  761.  * Called for one async event. (recv external/private answer)
  762.  *
  763.  * @param request_id identifies requests from 0 to (SNMP_CONCURRENT_REQUESTS-1)
  764.  */
  765. void
  766. snmp_msg_event(u8_t request_id)
  767. {
  768.   struct snmp_msg_pstat *msg_ps;
  769.  
  770.   if (request_id < SNMP_CONCURRENT_REQUESTS)
  771.   {
  772.     msg_ps = &msg_input_list[request_id];
  773.     if (msg_ps->rt == SNMP_ASN1_PDU_GET_NEXT_REQ)
  774.     {
  775.       snmp_msg_getnext_event(request_id, msg_ps);
  776.     }
  777.     else if (msg_ps->rt == SNMP_ASN1_PDU_GET_REQ)
  778.     {
  779.       snmp_msg_get_event(request_id, msg_ps);
  780.     }
  781.     else if(msg_ps->rt == SNMP_ASN1_PDU_SET_REQ)
  782.     {
  783.       snmp_msg_set_event(request_id, msg_ps);
  784.     }
  785.   }
  786. }
  787.  
  788.  
  789. /* lwIP UDP receive callback function */
  790. static void
  791. snmp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port)
  792. {
  793.   struct udp_hdr *udphdr;
  794.  
  795.   /* suppress unused argument warning */
  796.   LWIP_UNUSED_ARG(arg);
  797.   /* peek in the UDP header (goto IP payload) */
  798.   if(pbuf_header(p, UDP_HLEN)){
  799.     LWIP_ASSERT("Can't move to UDP header", 0);
  800.     pbuf_free(p);
  801.     return;
  802.   }
  803.   udphdr = p->payload;
  804.  
  805.   /* check if datagram is really directed at us (including broadcast requests) */
  806.   if ((pcb == snmp1_pcb) && (ntohs(udphdr->dest) == SNMP_IN_PORT))
  807.   {
  808.     struct snmp_msg_pstat *msg_ps;
  809.     u8_t req_idx;
  810.  
  811.     /* traverse input message process list, look for SNMP_MSG_EMPTY */
  812.     msg_ps = &msg_input_list[0];
  813.     req_idx = 0;
  814.     while ((req_idx<SNMP_CONCURRENT_REQUESTS) && (msg_ps->state != SNMP_MSG_EMPTY))
  815.     {
  816.       req_idx++;
  817.       msg_ps++;
  818.     }
  819.     if (req_idx != SNMP_CONCURRENT_REQUESTS)
  820.     {
  821.       err_t err_ret;
  822.       u16_t payload_len;
  823.       u16_t payload_ofs;
  824.       u16_t varbind_ofs = 0;
  825.  
  826.       /* accepting request */
  827.       snmp_inc_snmpinpkts();
  828.       /* record used 'protocol control block' */
  829.       msg_ps->pcb = pcb;
  830.       /* source address (network order) */
  831.       msg_ps->sip = *addr;
  832.       /* source port (host order (lwIP oddity)) */
  833.       msg_ps->sp = port;
  834.       /* read UDP payload length from UDP header */
  835.       payload_len = ntohs(udphdr->len) - UDP_HLEN;
  836.  
  837.       /* adjust to UDP payload */
  838.       payload_ofs = UDP_HLEN;
  839.  
  840.       /* check total length, version, community, pdu type */
  841.       err_ret = snmp_pdu_header_check(p, payload_ofs, payload_len, &varbind_ofs, msg_ps);
  842.       if (((msg_ps->rt == SNMP_ASN1_PDU_GET_REQ) ||
  843.            (msg_ps->rt == SNMP_ASN1_PDU_GET_NEXT_REQ) ||
  844.            (msg_ps->rt == SNMP_ASN1_PDU_SET_REQ)) &&
  845.           ((msg_ps->error_status == SNMP_ES_NOERROR) &&
  846.            (msg_ps->error_index == 0)) )
  847.       {
  848.         /* Only accept requests and requests without error (be robust) */
  849.         err_ret = err_ret;
  850.       }
  851.       else
  852.       {
  853.         /* Reject response and trap headers or error requests as input! */
  854.         err_ret = ERR_ARG;
  855.       }
  856.       if (err_ret == ERR_OK)
  857.       {
  858.         LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_recv ok, community %s\n", msg_ps->community));
  859.  
  860.         /* Builds a list of variable bindings. Copy the varbinds from the pbuf
  861.           chain to glue them when these are divided over two or more pbuf's. */
  862.         err_ret = snmp_pdu_dec_varbindlist(p, varbind_ofs, &varbind_ofs, msg_ps);
  863.         if ((err_ret == ERR_OK) && (msg_ps->invb.count > 0))
  864.         {
  865.           /* we've decoded the incoming message, release input msg now */
  866.           pbuf_free(p);
  867.  
  868.           msg_ps->error_status = SNMP_ES_NOERROR;
  869.           msg_ps->error_index = 0;
  870.           /* find object for each variable binding */
  871.           msg_ps->state = SNMP_MSG_SEARCH_OBJ;
  872.           /* first variable binding from list to inspect */
  873.           msg_ps->vb_idx = 0;
  874.  
  875.           LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_recv varbind cnt=%"U16_F"\n",(u16_t)msg_ps->invb.count));
  876.  
  877.           /* handle input event and as much objects as possible in one go */
  878.           snmp_msg_event(req_idx);
  879.         }
  880.         else
  881.         {
  882.           /* varbind-list decode failed, or varbind list empty.
  883.              drop request silently, do not return error!
  884.              (errors are only returned for a specific varbind failure) */
  885.           pbuf_free(p);
  886.           LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_pdu_dec_varbindlist() failed\n"));
  887.         }
  888.       }
  889.       else
  890.       {
  891.         /* header check failed
  892.            drop request silently, do not return error! */
  893.         pbuf_free(p);
  894.         LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_pdu_header_check() failed\n"));
  895.       }
  896.     }
  897.     else
  898.     {
  899.       /* exceeding number of concurrent requests */
  900.       pbuf_free(p);
  901.     }
  902.   }
  903.   else
  904.   {
  905.     /* datagram not for us */
  906.     pbuf_free(p);
  907.   }
  908. }
  909.  
  910. /**
  911.  * Checks and decodes incoming SNMP message header, logs header errors.
  912.  *
  913.  * @param p points to pbuf chain of SNMP message (UDP payload)
  914.  * @param ofs points to first octet of SNMP message
  915.  * @param pdu_len the length of the UDP payload
  916.  * @param ofs_ret returns the ofset of the variable bindings
  917.  * @param m_stat points to the current message request state return
  918.  * @return
  919.  * - ERR_OK SNMP header is sane and accepted
  920.  * - ERR_ARG SNMP header is either malformed or rejected
  921.  */
  922. static err_t
  923. snmp_pdu_header_check(struct pbuf *p, u16_t ofs, u16_t pdu_len, u16_t *ofs_ret, struct snmp_msg_pstat *m_stat)
  924. {
  925.   err_t derr;
  926.   u16_t len, ofs_base;
  927.   u8_t  len_octets;
  928.   u8_t  type;
  929.   s32_t version;
  930.  
  931.   ofs_base = ofs;
  932.   snmp_asn1_dec_type(p, ofs, &type);
  933.   derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len);
  934.   if ((derr != ERR_OK) ||
  935.       (pdu_len != (1 + len_octets + len)) ||
  936.       (type != (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)))
  937.   {
  938.     snmp_inc_snmpinasnparseerrs();
  939.     return ERR_ARG;
  940.   }
  941.   ofs += (1 + len_octets);
  942.   snmp_asn1_dec_type(p, ofs, &type);
  943.   derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len);
  944.   if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)))
  945.   {
  946.     /* can't decode or no integer (version) */
  947.     snmp_inc_snmpinasnparseerrs();
  948.     return ERR_ARG;
  949.   }
  950.   derr = snmp_asn1_dec_s32t(p, ofs + 1 + len_octets, len, &version);
  951.   if (derr != ERR_OK)
  952.   {
  953.     /* can't decode */
  954.     snmp_inc_snmpinasnparseerrs();
  955.     return ERR_ARG;
  956.   }
  957.   if (version != 0)
  958.   {
  959.     /* not version 1 */
  960.     snmp_inc_snmpinbadversions();
  961.     return ERR_ARG;
  962.   }
  963.   ofs += (1 + len_octets + len);
  964.   snmp_asn1_dec_type(p, ofs, &type);
  965.   derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len);
  966.   if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR)))
  967.   {
  968.     /* can't decode or no octet string (community) */
  969.     snmp_inc_snmpinasnparseerrs();
  970.     return ERR_ARG;
  971.   }
  972.   derr = snmp_asn1_dec_raw(p, ofs + 1 + len_octets, len, SNMP_COMMUNITY_STR_LEN, m_stat->community);
  973.   if (derr != ERR_OK)
  974.   {
  975.     snmp_inc_snmpinasnparseerrs();
  976.     return ERR_ARG;
  977.   }
  978.   /* add zero terminator */
  979.   len = ((len < (SNMP_COMMUNITY_STR_LEN))?(len):(SNMP_COMMUNITY_STR_LEN));
  980.   m_stat->community[len] = 0;
  981.   m_stat->com_strlen = len;
  982.   if (strncmp(snmp_publiccommunity, (const char*)m_stat->community, SNMP_COMMUNITY_STR_LEN) != 0)
  983.   {
  984.     /** @todo: move this if we need to check more names */
  985.     snmp_inc_snmpinbadcommunitynames();
  986.     snmp_authfail_trap();
  987.     return ERR_ARG;
  988.   }
  989.   ofs += (1 + len_octets + len);
  990.   snmp_asn1_dec_type(p, ofs, &type);
  991.   derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len);
  992.   if (derr != ERR_OK)
  993.   {
  994.     snmp_inc_snmpinasnparseerrs();
  995.     return ERR_ARG;
  996.   }
  997.   switch(type)
  998.   {
  999.     case (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_GET_REQ):
  1000.       /* GetRequest PDU */
  1001.       snmp_inc_snmpingetrequests();
  1002.       derr = ERR_OK;
  1003.       break;
  1004.     case (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_GET_NEXT_REQ):
  1005.       /* GetNextRequest PDU */
  1006.       snmp_inc_snmpingetnexts();
  1007.       derr = ERR_OK;
  1008.       break;
  1009.     case (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_GET_RESP):
  1010.       /* GetResponse PDU */
  1011.       snmp_inc_snmpingetresponses();
  1012.       derr = ERR_ARG;
  1013.       break;
  1014.     case (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_SET_REQ):
  1015.       /* SetRequest PDU */
  1016.       snmp_inc_snmpinsetrequests();
  1017.       derr = ERR_OK;
  1018.       break;
  1019.     case (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_TRAP):
  1020.       /* Trap PDU */
  1021.       snmp_inc_snmpintraps();
  1022.       derr = ERR_ARG;
  1023.       break;
  1024.     default:
  1025.       snmp_inc_snmpinasnparseerrs();
  1026.       derr = ERR_ARG;
  1027.       break;
  1028.   }
  1029.   if (derr != ERR_OK)
  1030.   {
  1031.     /* unsupported input PDU for this agent (no parse error) */
  1032.     return ERR_ARG;
  1033.   }
  1034.   m_stat->rt = type & 0x1F;
  1035.   ofs += (1 + len_octets);
  1036.   if (len != (pdu_len - (ofs - ofs_base)))
  1037.   {
  1038.     /* decoded PDU length does not equal actual payload length */
  1039.     snmp_inc_snmpinasnparseerrs();
  1040.     return ERR_ARG;
  1041.   }
  1042.   snmp_asn1_dec_type(p, ofs, &type);
  1043.   derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len);
  1044.   if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)))
  1045.   {
  1046.     /* can't decode or no integer (request ID) */
  1047.     snmp_inc_snmpinasnparseerrs();
  1048.     return ERR_ARG;
  1049.   }
  1050.   derr = snmp_asn1_dec_s32t(p, ofs + 1 + len_octets, len, &m_stat->rid);
  1051.   if (derr != ERR_OK)
  1052.   {
  1053.     /* can't decode */
  1054.     snmp_inc_snmpinasnparseerrs();
  1055.     return ERR_ARG;
  1056.   }
  1057.   ofs += (1 + len_octets + len);
  1058.   snmp_asn1_dec_type(p, ofs, &type);
  1059.   derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len);
  1060.   if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)))
  1061.   {
  1062.     /* can't decode or no integer (error-status) */
  1063.     snmp_inc_snmpinasnparseerrs();
  1064.     return ERR_ARG;
  1065.   }
  1066.   /* must be noError (0) for incoming requests.
  1067.      log errors for mib-2 completeness and for debug purposes */
  1068.   derr = snmp_asn1_dec_s32t(p, ofs + 1 + len_octets, len, &m_stat->error_status);
  1069.   if (derr != ERR_OK)
  1070.   {
  1071.     /* can't decode */
  1072.     snmp_inc_snmpinasnparseerrs();
  1073.     return ERR_ARG;
  1074.   }
  1075.   switch (m_stat->error_status)
  1076.   {
  1077.     case SNMP_ES_TOOBIG:
  1078.       snmp_inc_snmpintoobigs();
  1079.       break;
  1080.     case SNMP_ES_NOSUCHNAME:
  1081.       snmp_inc_snmpinnosuchnames();
  1082.       break;
  1083.     case SNMP_ES_BADVALUE:
  1084.       snmp_inc_snmpinbadvalues();
  1085.       break;
  1086.     case SNMP_ES_READONLY:
  1087.       snmp_inc_snmpinreadonlys();
  1088.       break;
  1089.     case SNMP_ES_GENERROR:
  1090.       snmp_inc_snmpingenerrs();
  1091.       break;
  1092.   }
  1093.   ofs += (1 + len_octets + len);
  1094.   snmp_asn1_dec_type(p, ofs, &type);
  1095.   derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len);
  1096.   if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)))
  1097.   {
  1098.     /* can't decode or no integer (error-index) */
  1099.     snmp_inc_snmpinasnparseerrs();
  1100.     return ERR_ARG;
  1101.   }
  1102.   /* must be 0 for incoming requests.
  1103.      decode anyway to catch bad integers (and dirty tricks) */
  1104.   derr = snmp_asn1_dec_s32t(p, ofs + 1 + len_octets, len, &m_stat->error_index);
  1105.   if (derr != ERR_OK)
  1106.   {
  1107.     /* can't decode */
  1108.     snmp_inc_snmpinasnparseerrs();
  1109.     return ERR_ARG;
  1110.   }
  1111.   ofs += (1 + len_octets + len);
  1112.   *ofs_ret = ofs;
  1113.   return ERR_OK;
  1114. }
  1115.  
  1116. static err_t
  1117. snmp_pdu_dec_varbindlist(struct pbuf *p, u16_t ofs, u16_t *ofs_ret, struct snmp_msg_pstat *m_stat)
  1118. {
  1119.   err_t derr;
  1120.   u16_t len, vb_len;
  1121.   u8_t  len_octets;
  1122.   u8_t type;
  1123.  
  1124.   /* variable binding list */
  1125.   snmp_asn1_dec_type(p, ofs, &type);
  1126.   derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &vb_len);
  1127.   if ((derr != ERR_OK) ||
  1128.       (type != (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)))
  1129.   {
  1130.     snmp_inc_snmpinasnparseerrs();
  1131.     return ERR_ARG;
  1132.   }
  1133.   ofs += (1 + len_octets);
  1134.  
  1135.   /* start with empty list */
  1136.   m_stat->invb.count = 0;
  1137.   m_stat->invb.head = NULL;
  1138.   m_stat->invb.tail = NULL;
  1139.  
  1140.   while (vb_len > 0)
  1141.   {
  1142.     struct snmp_obj_id oid, oid_value;
  1143.     struct snmp_varbind *vb;
  1144.  
  1145.     snmp_asn1_dec_type(p, ofs, &type);
  1146.     derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len);
  1147.     if ((derr != ERR_OK) ||
  1148.         (type != (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)) ||
  1149.         (len == 0) || (len > vb_len))
  1150.     {
  1151.       snmp_inc_snmpinasnparseerrs();
  1152.       /* free varbinds (if available) */
  1153.       snmp_varbind_list_free(&m_stat->invb);
  1154.       return ERR_ARG;
  1155.     }
  1156.     ofs += (1 + len_octets);
  1157.     vb_len -= (1 + len_octets);
  1158.  
  1159.     snmp_asn1_dec_type(p, ofs, &type);
  1160.     derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len);
  1161.     if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID)))
  1162.     {
  1163.       /* can't decode object name length */
  1164.       snmp_inc_snmpinasnparseerrs();
  1165.       /* free varbinds (if available) */
  1166.       snmp_varbind_list_free(&m_stat->invb);
  1167.       return ERR_ARG;
  1168.     }
  1169.     derr = snmp_asn1_dec_oid(p, ofs + 1 + len_octets, len, &oid);
  1170.     if (derr != ERR_OK)
  1171.     {
  1172.       /* can't decode object name */
  1173.       snmp_inc_snmpinasnparseerrs();
  1174.       /* free varbinds (if available) */
  1175.       snmp_varbind_list_free(&m_stat->invb);
  1176.       return ERR_ARG;
  1177.     }
  1178.     ofs += (1 + len_octets + len);
  1179.     vb_len -= (1 + len_octets + len);
  1180.  
  1181.     snmp_asn1_dec_type(p, ofs, &type);
  1182.     derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len);
  1183.     if (derr != ERR_OK)
  1184.     {
  1185.       /* can't decode object value length */
  1186.       snmp_inc_snmpinasnparseerrs();
  1187.       /* free varbinds (if available) */
  1188.       snmp_varbind_list_free(&m_stat->invb);
  1189.       return ERR_ARG;
  1190.     }
  1191.  
  1192.     switch (type)
  1193.     {
  1194.       case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG):
  1195.         vb = snmp_varbind_alloc(&oid, type, sizeof(s32_t));
  1196.         if (vb != NULL)
  1197.         {
  1198.           s32_t *vptr = vb->value;
  1199.  
  1200.           derr = snmp_asn1_dec_s32t(p, ofs + 1 + len_octets, len, vptr);
  1201.           snmp_varbind_tail_add(&m_stat->invb, vb);
  1202.         }
  1203.         else
  1204.         {
  1205.           derr = ERR_ARG;
  1206.         }
  1207.         break;
  1208.       case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER):
  1209.       case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE):
  1210.       case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS):
  1211.         vb = snmp_varbind_alloc(&oid, type, sizeof(u32_t));
  1212.         if (vb != NULL)
  1213.         {
  1214.           u32_t *vptr = vb->value;
  1215.  
  1216.           derr = snmp_asn1_dec_u32t(p, ofs + 1 + len_octets, len, vptr);
  1217.           snmp_varbind_tail_add(&m_stat->invb, vb);
  1218.         }
  1219.         else
  1220.         {
  1221.           derr = ERR_ARG;
  1222.         }
  1223.         break;
  1224.       case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR):
  1225.       case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_OPAQUE):
  1226.         vb = snmp_varbind_alloc(&oid, type, len);
  1227.         if (vb != NULL)
  1228.         {
  1229.           derr = snmp_asn1_dec_raw(p, ofs + 1 + len_octets, len, vb->value_len, vb->value);
  1230.           snmp_varbind_tail_add(&m_stat->invb, vb);
  1231.         }
  1232.         else
  1233.         {
  1234.           derr = ERR_ARG;
  1235.         }
  1236.         break;
  1237.       case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_NUL):
  1238.         vb = snmp_varbind_alloc(&oid, type, 0);
  1239.         if (vb != NULL)
  1240.         {
  1241.           snmp_varbind_tail_add(&m_stat->invb, vb);
  1242.           derr = ERR_OK;
  1243.         }
  1244.         else
  1245.         {
  1246.           derr = ERR_ARG;
  1247.         }
  1248.         break;
  1249.       case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID):
  1250.         derr = snmp_asn1_dec_oid(p, ofs + 1 + len_octets, len, &oid_value);
  1251.         if (derr == ERR_OK)
  1252.         {
  1253.           vb = snmp_varbind_alloc(&oid, type, oid_value.len * sizeof(s32_t));
  1254.           if (vb != NULL)
  1255.           {
  1256.             u8_t i = oid_value.len;
  1257.             s32_t *vptr = vb->value;
  1258.  
  1259.             while(i > 0)
  1260.             {
  1261.               i--;
  1262.               vptr[i] = oid_value.id[i];
  1263.             }
  1264.             snmp_varbind_tail_add(&m_stat->invb, vb);
  1265.             derr = ERR_OK;
  1266.           }
  1267.           else
  1268.           {
  1269.             derr = ERR_ARG;
  1270.           }
  1271.         }
  1272.         break;
  1273.       case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR):
  1274.         if (len == 4)
  1275.         {
  1276.           /* must be exactly 4 octets! */
  1277.           vb = snmp_varbind_alloc(&oid, type, 4);
  1278.           if (vb != NULL)
  1279.           {
  1280.             derr = snmp_asn1_dec_raw(p, ofs + 1 + len_octets, len, vb->value_len, vb->value);
  1281.             snmp_varbind_tail_add(&m_stat->invb, vb);
  1282.           }
  1283.           else
  1284.           {
  1285.             derr = ERR_ARG;
  1286.           }
  1287.         }
  1288.         else
  1289.         {
  1290.           derr = ERR_ARG;
  1291.         }
  1292.         break;
  1293.       default:
  1294.         derr = ERR_ARG;
  1295.         break;
  1296.     }
  1297.     if (derr != ERR_OK)
  1298.     {
  1299.       snmp_inc_snmpinasnparseerrs();
  1300.       /* free varbinds (if available) */
  1301.       snmp_varbind_list_free(&m_stat->invb);
  1302.       return ERR_ARG;
  1303.     }
  1304.     ofs += (1 + len_octets + len);
  1305.     vb_len -= (1 + len_octets + len);
  1306.   }
  1307.  
  1308.   if (m_stat->rt == SNMP_ASN1_PDU_SET_REQ)
  1309.   {
  1310.     snmp_add_snmpintotalsetvars(m_stat->invb.count);
  1311.   }
  1312.   else
  1313.   {
  1314.     snmp_add_snmpintotalreqvars(m_stat->invb.count);
  1315.   }
  1316.  
  1317.   *ofs_ret = ofs;
  1318.   return ERR_OK;
  1319. }
  1320.  
  1321. struct snmp_varbind*
  1322. snmp_varbind_alloc(struct snmp_obj_id *oid, u8_t type, u8_t len)
  1323. {
  1324.   struct snmp_varbind *vb;
  1325.  
  1326.   vb = (struct snmp_varbind *)mem_malloc(sizeof(struct snmp_varbind));
  1327.   LWIP_ASSERT("vb != NULL",vb != NULL);
  1328.   if (vb != NULL)
  1329.   {
  1330.     u8_t i;
  1331.  
  1332.     vb->next = NULL;
  1333.     vb->prev = NULL;
  1334.     i = oid->len;
  1335.     vb->ident_len = i;
  1336.     if (i > 0)
  1337.     {
  1338.       /* allocate array of s32_t for our object identifier */
  1339.       vb->ident = (s32_t*)mem_malloc(sizeof(s32_t) * i);
  1340.       LWIP_ASSERT("vb->ident != NULL",vb->ident != NULL);
  1341.       if (vb->ident == NULL)
  1342.       {
  1343.         mem_free(vb);
  1344.         return NULL;
  1345.       }
  1346.       while(i > 0)
  1347.       {
  1348.         i--;
  1349.         vb->ident[i] = oid->id[i];
  1350.       }
  1351.     }
  1352.     else
  1353.     {
  1354.       /* i == 0, pass zero length object identifier */
  1355.       vb->ident = NULL;
  1356.     }
  1357.     vb->value_type = type;
  1358.     vb->value_len = len;
  1359.     if (len > 0)
  1360.     {
  1361.       /* allocate raw bytes for our object value */
  1362.       vb->value = mem_malloc(len);
  1363.       LWIP_ASSERT("vb->value != NULL",vb->value != NULL);
  1364.       if (vb->value == NULL)
  1365.       {
  1366.         if (vb->ident != NULL)
  1367.         {
  1368.           mem_free(vb->ident);
  1369.         }
  1370.         mem_free(vb);
  1371.         return NULL;
  1372.       }
  1373.     }
  1374.     else
  1375.     {
  1376.       /* ASN1_NUL type, or zero length ASN1_OC_STR */
  1377.       vb->value = NULL;
  1378.     }
  1379.   }
  1380.   return vb;
  1381. }
  1382.  
  1383. void
  1384. snmp_varbind_free(struct snmp_varbind *vb)
  1385. {
  1386.   if (vb->value != NULL )
  1387.   {
  1388.     mem_free(vb->value);
  1389.   }
  1390.   if (vb->ident != NULL )
  1391.   {
  1392.     mem_free(vb->ident);
  1393.   }
  1394.   mem_free(vb);
  1395. }
  1396.  
  1397. void
  1398. snmp_varbind_list_free(struct snmp_varbind_root *root)
  1399. {
  1400.   struct snmp_varbind *vb, *prev;
  1401.  
  1402.   vb = root->tail;
  1403.   while ( vb != NULL )
  1404.   {
  1405.     prev = vb->prev;
  1406.     snmp_varbind_free(vb);
  1407.     vb = prev;
  1408.   }
  1409.   root->count = 0;
  1410.   root->head = NULL;
  1411.   root->tail = NULL;
  1412. }
  1413.  
  1414. void
  1415. snmp_varbind_tail_add(struct snmp_varbind_root *root, struct snmp_varbind *vb)
  1416. {
  1417.   if (root->count == 0)
  1418.   {
  1419.     /* add first varbind to list */
  1420.     root->head = vb;
  1421.     root->tail = vb;
  1422.   }
  1423.   else
  1424.   {
  1425.     /* add nth varbind to list tail */
  1426.     root->tail->next = vb;
  1427.     vb->prev = root->tail;
  1428.     root->tail = vb;
  1429.   }
  1430.   root->count += 1;
  1431. }
  1432.  
  1433. struct snmp_varbind*
  1434. snmp_varbind_tail_remove(struct snmp_varbind_root *root)
  1435. {
  1436.   struct snmp_varbind* vb;
  1437.  
  1438.   if (root->count > 0)
  1439.   {
  1440.     /* remove tail varbind */
  1441.     vb = root->tail;
  1442.     root->tail = vb->prev;
  1443.     vb->prev->next = NULL;
  1444.     root->count -= 1;
  1445.   }
  1446.   else
  1447.   {
  1448.     /* nothing to remove */
  1449.     vb = NULL;
  1450.   }
  1451.   return vb;
  1452. }
  1453.  
  1454. #endif /* LWIP_SNMP */
  1455.  

回复 "lwip-1.3.1"

这儿你可以回复上面这条便签

captcha