components/net-snmp/patches/035.15997718-17208688.interface.patch
author pkidd <patrick.kidd@oracle.com>
Tue, 21 Feb 2017 09:42:20 -0800
branchs11u3-sru
changeset 7677 9b4f5d1632d7
parent 3004 856505663cc3
permissions -rw-r--r--
Added tag 0.175.3.18.0.2.0, S11.3SRU18.2 for changeset 89cc78d134da

This is a combined patch taken from the community merging 2 patches
for issues related to incorrect reporting of interface details when 
interfaces are changed dynamically. 

The following are the community bug/patch details.
snmpd: BUG: 1400101: remove deleted interfaces from ifTable
http://sourceforge.net/p/net-snmp/patches/640/

snmpd: PATCH: 1849903: from jsafranek: do not spam log with asserts when XEN is used
http://sourceforge.net/p/net-snmp/patches/872/

--- net-snmp-5.4.1.old/agent/mibgroup/if-mib/data_access/interface.c	2007-01-22 08:18:29.000000000 -0800
+++ net-snmp-5.4.1/agent/mibgroup/if-mib/data_access/interface.c	2013-07-11 13:27:55.792579500 -0700
@@ -465,8 +465,13 @@
         DEBUGMSGTL(("access:interface:ifIndex", "saved ifIndex %d for %s\n",
                     index, name));
     }
-    else
-        netsnmp_assert(index == tmp);
+    else {
+       if(index != tmp) {
+         se_remove_value_from_slist("interfaces", name);
+         se_add_pair_to_slist("interfaces", strdup(name), index);
+         DEBUGMSGTL(("access:interface:ifIndex", "ifname %s, old index %d, already existing, replaced with %d\n", name, tmp, index));
+       }      
+    }
 }
 
 /**
--- net-snmp-5.4.1.old/agent/mibgroup/if-mib/ifTable/ifTable_data_access.c	2007-02-05 07:10:28.000000000 -0800
+++ net-snmp-5.4.1/agent/mibgroup/if-mib/ifTable/ifTable_data_access.c	2013-07-11 14:39:08.458138600 -0700
@@ -23,6 +23,12 @@
 #   include "mibgroup/ip-mib/ipv4InterfaceTable/ipv4InterfaceTable.h"
 #endif
 
+typedef struct cd_container_s {
+    netsnmp_container *current;
+    netsnmp_container *deleted;
+} cd_container;
+
+
 /*
  * flag so we know not to set row/table last change times
  * during startup.
@@ -158,9 +164,11 @@
  */
 static void
 _check_interface_entry_for_updates(ifTable_rowreq_ctx * rowreq_ctx,
-                                   netsnmp_container *ifcontainer)
+                                   cd_container *cdc)
 {
     char            oper_changed = 0;
+    u_long lastchange = rowreq_ctx->data.ifLastChange;
+    netsnmp_container *ifcontainer = cdc->current;
 
     /*
      * check for matching entry. We can do this directly, since
@@ -192,17 +200,32 @@
          * deleted (and thus need to update ifTableLastChanged)?
          */
         if (!rowreq_ctx->known_missing) {
-            DEBUGMSGTL(("ifTable:access", "updating missing entry\n"));
             rowreq_ctx->known_missing = 1;
+            DEBUGMSGTL(("ifTable:access", "updating missing entry %s\n",rowreq_ctx->data.ifName));
             rowreq_ctx->data.ifAdminStatus = IFADMINSTATUS_DOWN;
-            if ((!(rowreq_ctx->data.ifentry->ns_flags & NETSNMP_INTERFACE_FLAGS_HAS_LASTCHANGE))
-                && (rowreq_ctx->data.ifOperStatus != IFOPERSTATUS_DOWN))
-                oper_changed = 1;
             rowreq_ctx->data.ifOperStatus = IFOPERSTATUS_DOWN;
+            rowreq_ctx->data.ifOperStatus = IFOPERSTATUS_DOWN;
+            oper_changed = 1;
+        } else {
+            time_t now = netsnmp_get_agent_uptime();
+            u_long diff = (now - rowreq_ctx->data.ifLastChange) / 100;
+            DEBUGMSGTL(("verbose:ifTable:access", "missing entry for %ld seconds\n", diff));
+            if (diff > IFTABLE_REMOVE_MISSING_AFTER) {
+                DEBUGMSGTL(("ifTable:access", "marking missing entry %s for "
+                            "removal after %d seconds\n", rowreq_ctx->data.ifName,
+                            IFTABLE_REMOVE_MISSING_AFTER));
+                if (NULL == cdc->deleted)
+                   cdc->deleted = netsnmp_container_find("ifTable_deleted:linked_list");
+                if (NULL == cdc->deleted)
+                   snmp_log(LOG_ERR, "couldn't create container for deleted interface\n");
+                else {
+                   CONTAINER_INSERT(cdc->deleted, rowreq_ctx);
+                }
+            }
         }
     } else {
-        DEBUGMSGTL(("ifTable:access", "updating existing entry\n"));
-
+        DEBUGMSGTL(("ifTable:access", "updating existing entry %s\n",
+                    rowreq_ctx->data.ifName));
 #ifdef USING_IF_MIB_IFXTABLE_IFXTABLE_MODULE
         {
             int rc = strcmp(rowreq_ctx->data.ifName,
@@ -245,6 +268,8 @@
      */
     if (oper_changed)
         rowreq_ctx->data.ifLastChange = netsnmp_get_agent_uptime();
+    else
+        rowreq_ctx->data.ifLastChange = lastchange;
 
 }
 
@@ -255,8 +280,21 @@
 _add_new_interface(netsnmp_interface_entry *ifentry,
                    netsnmp_container *container)
 {
-    ifTable_rowreq_ctx *rowreq_ctx;
-
+    ifTable_rowreq_ctx *rowreq_ctx, *container_entry;
+    netsnmp_iterator *ctxit;
+    ctxit = CONTAINER_ITERATOR(container);
+    container_entry = ITERATOR_FIRST(ctxit);
+
+    for(; container_entry; container_entry = ITERATOR_NEXT(ctxit)) {
+	if(!strcmp(ifentry->name, container_entry->data.ifName) && \
+	    ifentry->index != container_entry->data.ifentry->index) {
+		DEBUGMSGTL(("ifTable:access", "removing old entry %s (index %d != %d)\n",
+		    container_entry->data.ifName, container_entry->data.ifentry->index, ifentry->index));
+		    se_remove_value_from_slist("interfaces", container_entry->data.ifName);
+		CONTAINER_REMOVE(container, container_entry);
+		ifTable_release_rowreq_ctx(container_entry);
+		}
+    }
     DEBUGMSGTL(("ifTable:access", "creating new entry\n"));
 
     /*
@@ -300,6 +338,21 @@
         }
     }
 }
+ 
+/**
+ * delete removed entry
+ */
+static void
+_delete_missing_interface(ifTable_rowreq_ctx *rowreq_ctx,
+                          netsnmp_container *container)
+{
+    DEBUGMSGTL(("ifTable:access", "removing missing entry %s\n",
+                rowreq_ctx->data.ifName));
+
+    CONTAINER_REMOVE(container, rowreq_ctx);
+
+    ifTable_release_rowreq_ctx(rowreq_ctx);
+}
 
 /**
  * container shutdown
@@ -365,8 +418,7 @@
 int
 ifTable_container_load(netsnmp_container *container)
 {
-    netsnmp_container *ifcontainer;
-
+    cd_container cdc;	
     DEBUGMSGTL(("verbose:ifTable:ifTable_container_load", "called\n"));
 
     /*
@@ -378,31 +430,42 @@
     /*
      * ifTable gets its data from the netsnmp_interface API.
      */
-    ifcontainer =
+    cdc.current =
         netsnmp_access_interface_container_load(NULL,
                                                 NETSNMP_ACCESS_INTERFACE_INIT_NOFLAGS);
-    if (NULL == ifcontainer)
+    if (NULL == cdc.current)
         return MFD_RESOURCE_UNAVAILABLE;        /* msg already logged */
 
+    cdc.deleted = NULL; /* created as needed */
+
     /*
      * we just got a fresh copy of interface data. compare it to
      * what we've already got, and make any adjustements...
      */
     CONTAINER_FOR_EACH(container, (netsnmp_container_obj_func *)
-                       _check_interface_entry_for_updates, ifcontainer);
+                       _check_interface_entry_for_updates, &cdc);
 
     /*
      * now add any new interfaces
      */
-    CONTAINER_FOR_EACH(ifcontainer,
+    CONTAINER_FOR_EACH(cdc.current,
                        (netsnmp_container_obj_func *) _add_new_interface,
                        container);
 
+
+     /*
+     * now remove any missing interfaces
+     */
+    if (NULL != cdc.deleted)
+       CONTAINER_FOR_EACH(cdc.deleted,
+                          (netsnmp_container_obj_func *) _delete_missing_interface,
+                          container);
+
     /*
      * free the container. we've either claimed each ifentry, or released it,
      * so the dal function doesn't need to clear the container.
      */
-    netsnmp_access_interface_container_free(ifcontainer,
+    netsnmp_access_interface_container_free(cdc.current,
                                             NETSNMP_ACCESS_INTERFACE_FREE_DONT_CLEAR);
 
     DEBUGMSGT(("verbose:ifTable:ifTable_cache_load",
--- net-snmp-5.4.1.old/agent/mibgroup/if-mib/ifTable/ifTable_data_access.h	2006-04-09 21:59:10.000000000 -0700
+++ net-snmp-5.4.1/agent/mibgroup/if-mib/ifTable/ifTable_data_access.h	2013-07-11 13:58:33.862743400 -0700
@@ -48,6 +48,8 @@
      */
 #define IFTABLE_CACHE_TIMEOUT   15
 
+#define IFTABLE_REMOVE_MISSING_AFTER     (5 * 60) /* seconds */
+
     void            ifTable_container_init(netsnmp_container
                                            **container_ptr_ptr,
                                            netsnmp_cache * cache);
--- net-snmp-5.4.1.old/snmplib/snmp_enum.c	2005-02-09 11:46:35.000000000 -0800
+++ net-snmp-5.4.1/snmplib/snmp_enum.c	2013-07-10 04:08:50.542006500 -0700
@@ -213,6 +213,28 @@
     return SE_DNE;              /* XXX: um, no good solution here */
 }
 
+int se_remove_value_from_list(struct snmp_enum_list **list, const char *label)
+{
+   struct snmp_enum_list *lastlist;
+   if(!list)
+     return SE_DNE;
+
+   lastlist = NULL;
+   while(*list) {
+      if(strcmp((*list)->label, label) == 0) {
+	 free((*list)->label);
+	 if(lastlist)
+	   lastlist->next = (*list)->next;
+	 free(*list);
+	 *list = NULL;
+	 return 0;
+      }
+      lastlist = *list;
+      (*list) = (*list)->next;
+   }
+   
+}
+
 int
 se_find_free_value_in_list(struct snmp_enum_list *list)
 {
@@ -337,6 +359,19 @@
     return (se_find_free_value_in_list(se_find_slist(listname)));
 }
 
+void se_remove_value_from_slist(const char *listname, const char *label)
+{
+   struct snmp_enum_list_str *sptr, *lastp = NULL;
+   struct snmp_enum_list *list;
+   if (!listname)
+     return;
+
+   for (sptr = sliststorage;
+	sptr != NULL; lastp = sptr, sptr = sptr->next)
+     if (sptr->name && strcmp(sptr->name, listname) == 0)
+       se_remove_value_from_list(&sptr->list, label);
+}
+
 int
 se_add_pair_to_slist(const char *listname, char *label, int value)
 {