commit 057f43d3fc70077f8cb1c5b05edea29172501e8e
Author: Dave Shield <dts12@users.sourceforge.net>
Date:   Wed Jun 3 10:12:48 2009 +0000

    CHANGES: PATCH: 2797251: Support multiple initialisation and shutdown, fix memory leaks
    Patch supplied by Ivosh
    
    
    git-svn-id: file:///home/hardaker/lib/sf-bkups/net-snmp-convert-svnrepo/branches/V5-4-patches@17646 06827809-a52a-0410-b366-d66718629ded

Index: agent/agent_handler.c
===================================================================
--- agent/agent_handler.c.orig
+++ agent/agent_handler.c
@@ -579,6 +579,10 @@ netsnmp_handler_free(netsnmp_mib_handler
          *  defined. About 30 functions down the stack, starting
          *  in clear_context() -> clear_subtree()
          */
+        if ((handler->myvoid != NULL) && (handler->data_free != NULL))
+        {
+            handler->data_free(handler->myvoid);
+        }
         SNMP_FREE(handler->handler_name);
         SNMP_FREE(handler);
     }
@@ -600,6 +604,7 @@ netsnmp_handler_dup(netsnmp_mib_handler
 
     if (h != NULL) {
         h->myvoid = handler->myvoid;
+        h->data_free = handler->data_free;
 
         if (handler->next != NULL) {
             h->next = netsnmp_handler_dup(handler->next);
Index: agent/helpers/stash_cache.c
===================================================================
--- agent/helpers/stash_cache.c.orig
+++ agent/helpers/stash_cache.c
@@ -66,6 +66,7 @@ netsnmp_get_timed_bare_stash_cache_handl
     }
 
     handler->myvoid = cinfo;
+    handler->data_free = free;
 
     return handler;
 }
Index: agent/mibgroup/agentx/subagent.c
===================================================================
--- agent/mibgroup/agentx/subagent.c.orig
+++ agent/mibgroup/agentx/subagent.c
@@ -111,6 +111,7 @@ subagent_startup(int majorID, int minorI
     return 0;
 }
 
+static int subagent_init_init = 0;
 /**
  * init subagent callback (local) session and connect to master agent
  *
@@ -119,12 +120,11 @@ subagent_startup(int majorID, int minorI
 int
 subagent_init(void)
 {
-    static int init = 0;
     int rc = 0;
 
     DEBUGMSGTL(("agentx/subagent", "initializing....\n"));
 
-    if (++init != 1)
+    if (++subagent_init_init != 1)
         return 0;
 
     netsnmp_assert(netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
@@ -679,8 +679,13 @@ subagent_shutdown(int majorID, int minor
     }
     agentx_close_session(thesession, AGENTX_CLOSE_SHUTDOWN);
     snmp_close(thesession);
-    main_session = NULL;
+    if (main_session != NULL) {
+        remove_trap_session(main_session);
+        main_session = NULL;
+    }
     DEBUGMSGTL(("agentx/subagent", "shut down finished.\n"));
+
+    subagent_init_init = 0;
     return 1;
 }
 
Index: agent/snmp_agent.c
===================================================================
--- agent/snmp_agent.c.orig
+++ agent/snmp_agent.c
@@ -644,6 +644,18 @@ netsnmp_addrcache_initialise(void)
     }
 }
 
+void netsnmp_addrcache_destroy(void)
+{
+    int             i = 0;
+
+    for (i = 0; i < SNMP_ADDRCACHE_SIZE; i++) {
+        if (addrCache[i].status == SNMP_ADDRCACHE_USED) {
+            free(addrCache[i].addr);
+            addrCache[i].status = SNMP_ADDRCACHE_UNUSED;
+        }
+    }
+}
+
 /*
  * Adds a new entry to the cache of addresses that
  * have recently made connections to the agent.
Index: agent/snmp_vars.c
===================================================================
--- agent/snmp_vars.c.orig
+++ agent/snmp_vars.c
@@ -366,6 +366,7 @@ shutdown_agent(void) {
     clear_snmp_enum();
     clear_callback();
     clear_user_list();
+    netsnmp_addrcache_destroy();
 
     done_init_agent = 0;
 }
Index: include/net-snmp/agent/agent_handler.h
===================================================================
--- include/net-snmp/agent/agent_handler.h.orig
+++ include/net-snmp/agent/agent_handler.h
@@ -61,6 +61,7 @@ typedef struct netsnmp_mib_handler_s {
                                           struct
                                           netsnmp_agent_request_info_s *,
                                           struct netsnmp_request_info_s *);
+        void (*data_free)(void *myvoid); /**< data free hook for myvoid */
 
         struct netsnmp_mib_handler_s *next;
         struct netsnmp_mib_handler_s *prev;
Index: include/net-snmp/agent/snmp_agent.h
===================================================================
--- include/net-snmp/agent/snmp_agent.h.orig
+++ include/net-snmp/agent/snmp_agent.h
@@ -204,6 +204,7 @@ extern          "C" {
      */
 
     void            netsnmp_addrcache_initialise(void);
+    void            netsnmp_addrcache_destroy(void);
     void            netsnmp_addrcache_age(void);
 
 
Index: snmplib/snmpUDPDomain.c
===================================================================
--- snmplib/snmpUDPDomain.c.orig
+++ snmplib/snmpUDPDomain.c
@@ -171,6 +171,7 @@ static int netsnmp_udp_sendto(int fd, st
     } cmsg;
     struct msghdr m;
 
+    memset(&cmsg, 0, sizeof(cmsg));
     cmsg.cm.cmsg_len = sizeof(struct cmsghdr) + sizeof(struct in_pktinfo);
     cmsg.cm.cmsg_level = SOL_IP;
     cmsg.cm.cmsg_type = IP_PKTINFO;
@@ -675,7 +676,6 @@ netsnmp_udp_transport(struct sockaddr_in
             struct sockaddr_in client_addr;
             netsnmp_sockaddr_in2(&client_addr, client_socket, NULL);
             addr_pair.local_addr = client_addr.sin_addr;
-            client_addr.sin_port = 0;
             rc = bind(t->sock, (struct sockaddr *)&client_addr,
                   sizeof(struct sockaddr));
             if ( rc != 0 ) {
Index: snmplib/snmp_api.c
===================================================================
--- snmplib/snmp_api.c.orig
+++ snmplib/snmp_api.c
@@ -634,17 +634,17 @@ snmp_sess_perror(const char *prog_string
  *
  * Warning: no debug messages here.
  */
+static char _init_snmp_init_done = 0;
 static void
 _init_snmp(void)
 {
-    static char     have_done_init = 0;
 
     struct timeval  tv;
     long            tmpReqid, tmpMsgid;
 
-    if (have_done_init)
+    if (_init_snmp_init_done)
         return;
-    have_done_init = 1;
+    _init_snmp_init_done = 1;
     Reqid = 1;
 
     snmp_res_init();            /* initialize the mt locking structures */
@@ -772,6 +772,7 @@ register_default_handlers(void)
     netsnmp_register_service_handlers();
 }
 
+static int init_snmp_init_done = 0; /* To prevent double init's. */
 /**
  * Calls the functions to do config file loading and  mib module parsing
  * in the correct order.
@@ -785,13 +786,11 @@ register_default_handlers(void)
 void
 init_snmp(const char *type)
 {
-    static int      done_init = 0;      /* To prevent double init's. */
-
-    if (done_init) {
+    if (init_snmp_init_done) {
         return;
     }
 
-    done_init = 1;
+    init_snmp_init_done = 1;
 
     /*
      * make the type available everywhere else 
@@ -872,6 +871,9 @@ snmp_shutdown(const char *type)
     netsnmp_clear_default_target();
     netsnmp_clear_default_domain();
     free_etimelist();
+
+    init_snmp_init_done  = 0;
+    _init_snmp_init_done = 0;
 }
 
 
Index: snmplib/snmpv3.c
===================================================================
--- snmplib/snmpv3.c.orig
+++ snmplib/snmpv3.c
@@ -747,6 +747,7 @@ free_engineID(int majorid, int minorid,
     SNMP_FREE(engineID);
     SNMP_FREE(engineIDNic);
     SNMP_FREE(oldEngineID);
+    engineIDIsSet = 0;
     return 0;
 }
 
