From 5a7ec0d53e257d24e98a2cb2fd0d9a5abdfee5d7 Mon Sep 17 00:00:00 2001
From: Stephane Lesage <stephane.lesage@ateis.com>
Date: Wed, 15 Feb 2012 21:33:14 +0100
Subject: [PATCH] Fix SNMP response for error too big

---
 src/core/snmp/msg_in.c  |   27 +++++++++++++++++++--------
 src/core/snmp/msg_out.c |    7 -------
 2 files changed, 19 insertions(+), 15 deletions(-)

diff --git a/src/core/snmp/msg_in.c b/src/core/snmp/msg_in.c
index 2dfb55b..5d98f5d 100644
--- a/src/core/snmp/msg_in.c
+++ b/src/core/snmp/msg_in.c
@@ -105,13 +105,29 @@ snmp_init(void)
 static void
 snmp_error_response(struct snmp_msg_pstat *msg_ps, u8_t error)
 {
+  /* move names back from outvb to invb */
+  int v;
+  struct snmp_varbind *vbi = msg_ps->invb.head;
+  struct snmp_varbind *vbo = msg_ps->outvb.head;
+  for (v=0; v<msg_ps->vb_idx; v++)
+  {
+    vbi->ident_len = vbo->ident_len;
+    vbo->ident_len = 0;
+    vbi->ident = vbo->ident;
+    vbo->ident = NULL;
+    vbi = vbi->next;
+    vbo = vbo->next;
+  }
+  /* free outvb */
   snmp_varbind_list_free(&msg_ps->outvb);
+  /* we send invb back */
   msg_ps->outvb = msg_ps->invb;
   msg_ps->invb.head = NULL;
   msg_ps->invb.tail = NULL;
   msg_ps->invb.count = 0;
   msg_ps->error_status = error;
-  msg_ps->error_index = 1 + msg_ps->vb_idx;
+  /* error index must be 0 for error too big */
+  msg_ps->error_index = error != SNMP_ES_TOOBIG ? (1 + msg_ps->vb_idx) : 0;
   snmp_send_response(msg_ps);
   snmp_varbind_list_free(&msg_ps->outvb);
   msg_ps->state = SNMP_MSG_EMPTY;
@@ -182,7 +198,6 @@ snmp_msg_get_event(u8_t request_id, struct snmp_msg_pstat *msg_ps)
 
     /* allocate output varbind */
     vb = (struct snmp_varbind *)memp_malloc(MEMP_SNMP_VARBIND);
-    LWIP_ASSERT("vb != NULL",vb != NULL);
     if (vb != NULL)
     {
       vb->next = NULL;
@@ -202,7 +217,6 @@ snmp_msg_get_event(u8_t request_id, struct snmp_msg_pstat *msg_ps)
       {
         LWIP_ASSERT("SNMP_MAX_OCTET_STRING_LEN is configured too low", vb->value_len <= SNMP_MAX_VALUE_SIZE);
         vb->value = memp_malloc(MEMP_SNMP_VALUE);
-        LWIP_ASSERT("vb->value != NULL",vb->value != NULL);
         if (vb->value != NULL)
         {
           en->get_value_a(request_id, &msg_ps->ext_object_def, vb->value_len, vb->value);
@@ -297,7 +311,6 @@ snmp_msg_get_event(u8_t request_id, struct snmp_msg_pstat *msg_ps)
             msg_ps->state = SNMP_MSG_INTERNAL_GET_VALUE;
             /* allocate output varbind */
             vb = (struct snmp_varbind *)memp_malloc(MEMP_SNMP_VARBIND);
-            LWIP_ASSERT("vb != NULL",vb != NULL);
             if (vb != NULL)
             {
               vb->next = NULL;
@@ -318,7 +331,6 @@ snmp_msg_get_event(u8_t request_id, struct snmp_msg_pstat *msg_ps)
                 LWIP_ASSERT("SNMP_MAX_OCTET_STRING_LEN is configured too low",
                   vb->value_len <= SNMP_MAX_VALUE_SIZE);
                 vb->value = memp_malloc(MEMP_SNMP_VALUE);
-                LWIP_ASSERT("vb->value != NULL",vb->value != NULL);
                 if (vb->value != NULL)
                 {
                   mn->get_value(&object_def, vb->value_len, vb->value);
@@ -331,6 +343,8 @@ snmp_msg_get_event(u8_t request_id, struct snmp_msg_pstat *msg_ps)
                   LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_event: couldn't allocate variable space\n"));
                   msg_ps->vb_ptr->ident = vb->ident;
                   msg_ps->vb_ptr->ident_len = vb->ident_len;
+                  vb->ident = NULL;
+                  vb->ident_len = NULL;
                   memp_free(MEMP_SNMP_VARBIND, vb);
                   snmp_error_response(msg_ps,SNMP_ES_TOOBIG);
                 }
@@ -1305,7 +1319,6 @@ snmp_varbind_alloc(struct snmp_obj_id *oid, u8_t type, u8_t len)
   struct snmp_varbind *vb;
 
   vb = (struct snmp_varbind *)memp_malloc(MEMP_SNMP_VARBIND);
-  LWIP_ASSERT("vb != NULL",vb != NULL);
   if (vb != NULL)
   {
     u8_t i;
@@ -1319,7 +1332,6 @@ snmp_varbind_alloc(struct snmp_obj_id *oid, u8_t type, u8_t len)
       LWIP_ASSERT("SNMP_MAX_TREE_DEPTH is configured too low", i <= SNMP_MAX_TREE_DEPTH);
       /* allocate array of s32_t for our object identifier */
       vb->ident = (s32_t*)memp_malloc(MEMP_SNMP_VALUE);
-      LWIP_ASSERT("vb->ident != NULL",vb->ident != NULL);
       if (vb->ident == NULL)
       {
         memp_free(MEMP_SNMP_VARBIND, vb);
@@ -1343,7 +1355,6 @@ snmp_varbind_alloc(struct snmp_obj_id *oid, u8_t type, u8_t len)
       LWIP_ASSERT("SNMP_MAX_OCTET_STRING_LEN is configured too low", vb->value_len <= SNMP_MAX_VALUE_SIZE);
       /* allocate raw bytes for our object value */
       vb->value = memp_malloc(MEMP_SNMP_VALUE);
-      LWIP_ASSERT("vb->value != NULL",vb->value != NULL);
       if (vb->value == NULL)
       {
         if (vb->ident != NULL)
diff --git a/src/core/snmp/msg_out.c b/src/core/snmp/msg_out.c
index 4778bee..df21ddf 100644
--- a/src/core/snmp/msg_out.c
+++ b/src/core/snmp/msg_out.c
@@ -145,14 +145,7 @@ snmp_send_response(struct snmp_msg_pstat *m_stat)
 
     /* 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)
     {
-- 
1.7.4.msysgit.0

