--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/net-snmp/patches/035.15997718-17208688.interface.patch Mon Mar 24 15:04:05 2014 -0700
@@ -0,0 +1,271 @@
+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)
+ {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/net-snmp/patches/036.16356248.mteTrigger.patch Mon Mar 24 15:04:05 2014 -0700
@@ -0,0 +1,65 @@
+This patch fixes the issue related to delayed response
+of the snmpd agent when monitors are used.
+
+This patch is taken from the community for the following bug.
+snmpd: PATCH: 1918383: Fix DisMan monitoring of AgentX subagents
+http://sourceforge.net/p/net-snmp/patches/897/
+--- net-snmp-5.4.1.old/agent/mibgroup/utilities/iquery.c 2006-10-12 15:21:28.000000000 -0700
++++ net-snmp-5.4.1/agent/mibgroup/utilities/iquery.c 2013-07-09 14:39:34.856060200 -0700
+@@ -159,6 +159,8 @@
+ memdup( &(ss->community), secName, strlen(secName));
+ ss->community_len = strlen(secName);
+ }
++ ss->myvoid = netsnmp_check_outstanding_agent_requests;
++ ss->flags |= SNMP_FLAGS_RESP_CALLBACK | SNMP_FLAGS_DONT_PROBE;
+ }
+ #endif
+
+--- net-snmp-5.4.1.old/include/net-snmp/library/snmp_api.h 2007-03-23 02:44:49.000000000 -0700
++++ net-snmp-5.4.1/include/net-snmp/library/snmp_api.h 2013-05-08 02:17:51.242309300 -0700
+@@ -300,7 +300,10 @@
+ void *securityInfo;
+
+ /**
+- * use as you want data
++ * use as you want data
++ *
++ * used by 'SNMP_FLAGS_RESP_CALLBACK' handling in the agent
++ * XXX: or should we add a new field into this structure?
+ */
+ void *myvoid;
+ };
+@@ -394,6 +397,7 @@
+
+ #define SNMP_DETAIL_SIZE 512
+
++#define SNMP_FLAGS_RESP_CALLBACK 0x400 /* Additional callback on response */
+ #define SNMP_FLAGS_USER_CREATED 0x200 /* USM user has been created */
+ #define SNMP_FLAGS_DONT_PROBE 0x100 /* don't probe for an engineID */
+ #define SNMP_FLAGS_STREAM_SOCKET 0x80
+--- net-snmp-5.4.1.old/snmplib/snmp_client.c 2007-07-03 15:36:42.000000000 -0700
++++ net-snmp-5.4.1/snmplib/snmp_client.c 2013-07-09 14:48:09.041945100 -0700
+@@ -1014,7 +1014,7 @@
+ count = select(numfds, &fdset, 0, 0, tvp);
+ if (count > 0) {
+ snmp_read(&fdset);
+- } else
++ } else {
+ switch (count) {
+ case 0:
+ snmp_timeout();
+@@ -1040,6 +1040,14 @@
+ state->status = STAT_ERROR;
+ state->waiting = 0;
+ }
++ }
++
++ if ( ss->flags & SNMP_FLAGS_RESP_CALLBACK ) {
++ void (*cb)(void);
++ cb = ss->myvoid;
++ cb(); /* Used to invoke 'netsnmp_check_outstanding_agent_requests();'
++ on internal AgentX queries. */
++ }
+ }
+ *response = state->pdu;
+ ss->callback = cbsav;