]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
wrap potentially non-threadsafe snmp operations in mutex; support snmpwalk in subagent
authorDaniel Swarbrick <daniel@seventhsignal.de>
Tue, 25 Jan 2011 18:19:17 +0000 (19:19 +0100)
committerDaniel Swarbrick <daniel@seventhsignal.de>
Tue, 25 Jan 2011 18:19:31 +0000 (19:19 +0100)
src/mod/event_handlers/mod_snmp/mod_snmp.c
src/mod/event_handlers/mod_snmp/subagent.c

index 36a133c80504472486389e921b70a3781a2b6e8f..79ccd165c187e787bb1b7e5f9d8e4cd3647f3cd5 100644 (file)
@@ -38,6 +38,7 @@
 
 static struct {
        switch_memory_pool_t *pool;
+       switch_mutex_t *mutex;
        int shutdown;
 } globals;
 
@@ -55,27 +56,13 @@ static int snmp_callback_log(int major, int minor, void *serverarg, void *client
 }
 
 
-static switch_state_handler_table_t state_handlers = {
-       /*.on_init */ NULL,
-       /*.on_routing */ NULL,
-       /*.on_execute */ NULL,
-       /*.on_hangup */ NULL,
-       /*.on_exchange_media */ NULL,
-       /*.on_soft_execute */ NULL,
-       /*.on_consume_media */ NULL,
-       /*.on_hibernate */ NULL,
-       /*.on_reset */ NULL,
-       /*.on_park */ NULL,
-       /*.on_reporting */ NULL
-};
-
-
 static switch_status_t load_config(switch_memory_pool_t *pool)
 {
        switch_status_t status = SWITCH_STATUS_SUCCESS;
 
        memset(&globals, 0, sizeof(globals));
        globals.pool = pool;
+       switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, globals.pool);
 
        return status;
 }
@@ -87,7 +74,6 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_snmp_load)
 
        load_config(pool);
 
-       switch_core_add_state_handler(&state_handlers);
        *module_interface = switch_loadable_module_create_module_interface(pool, modname);
 
        /* Register callback function so we get Net-SNMP logging handled by FreeSWITCH */
@@ -114,9 +100,11 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_snmp_load)
 
 SWITCH_MODULE_RUNTIME_FUNCTION(mod_snmp_runtime)
 {
-       while (!globals.shutdown) {
+       if (!globals.shutdown) {
                /* Block on select() */
+               switch_mutex_lock(globals.mutex);
                agent_check_and_process(1);
+               switch_mutex_unlock(globals.mutex);
        }
 
        return SWITCH_STATUS_SUCCESS;
@@ -126,9 +114,12 @@ SWITCH_MODULE_RUNTIME_FUNCTION(mod_snmp_runtime)
 SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_snmp_shutdown)
 {
        globals.shutdown = 1;
-       switch_core_remove_state_handler(&state_handlers);
 
+       switch_mutex_lock(globals.mutex);
        snmp_shutdown("mod_snmp");
+       switch_mutex_unlock(globals.mutex);
+
+       switch_mutex_destroy(globals.mutex);
 
        return SWITCH_STATUS_SUCCESS;
 }
index 8a9f2dac21d17cae438ca527b51ed363c2ac14be..ad36624772fc161b0b6817fbd4cffdf0868b7b56 100644 (file)
@@ -63,8 +63,8 @@ void init_subagent(void)
 {
        DEBUGMSGTL(("init_nstAgentSubagentObject", "Initializing\n"));
 
-       netsnmp_register_handler(netsnmp_create_handler_registration("identity", handle_identity, identity_oid, OID_LENGTH(identity_oid), HANDLER_CAN_RONLY));
-       netsnmp_register_handler(netsnmp_create_handler_registration("systemStats", handle_systemStats, systemStats_oid, OID_LENGTH(systemStats_oid), HANDLER_CAN_RONLY));
+       netsnmp_register_scalar_group(netsnmp_create_handler_registration("identity", handle_identity, identity_oid, OID_LENGTH(identity_oid), HANDLER_CAN_RONLY), 1, 2);
+       netsnmp_register_scalar_group(netsnmp_create_handler_registration("systemStats", handle_systemStats, systemStats_oid, OID_LENGTH(systemStats_oid), HANDLER_CAN_RONLY), 1, 7);
 }
 
 
@@ -76,33 +76,29 @@ int handle_identity(netsnmp_mib_handler *handler, netsnmp_handler_registration *
        oid subid;
 
        switch(reqinfo->mode) {
-               case MODE_GET:
-                       for (request = requests; request; request = request->next) {
-                               subid = request->requestvb->name[OID_LENGTH(systemStats_oid)];
-
-                               switch (subid) {
-                                       case versionString_oid:
-                                               snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR, (u_char *) &version, strlen(version));
-                                               break;
-                                       case uuid_oid:
-                                               strncpy(uuid, switch_core_get_uuid(), sizeof(uuid));
-                                               snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR, (u_char *) &uuid, strlen(uuid));
-                                               break;
-                                       default:
-                                               snmp_log(LOG_WARNING, "Unregistered OID-suffix requested (%d)\n", (int) subid);
-                                               netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHOBJECT);
-                               }
+       case MODE_GET:
+               for (request = requests; request; request = request->next) {
+                       subid = request->requestvb->name[reginfo->rootoid_len - 2];
+
+                       switch (subid) {
+                               case versionString_oid:
+                                       snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR, (u_char *) &version, strlen(version));
+                                       break;
+                               case uuid_oid:
+                                       strncpy(uuid, switch_core_get_uuid(), sizeof(uuid));
+                                       snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR, (u_char *) &uuid, strlen(uuid));
+                                       break;
+                               default:
+                                       snmp_log(LOG_WARNING, "Unregistered OID-suffix requested (%d)\n", (int) subid);
+                                       netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHOBJECT);
                        }
-                       break;
+               }
+               break;
 
-               case MODE_GETNEXT:
-                       snmp_log(LOG_ERR, "MODE_GETNEXT not supported (yet)\n");
-                       break;
-
-               default:
-                       /* we should never get here, so this is a really bad error */
-                       snmp_log(LOG_ERR, "Unknown mode (%d) in handle_versionString\n", reqinfo->mode );
-                       return SNMP_ERR_GENERR;
+       default:
+               /* we should never get here, so this is a really bad error */
+               snmp_log(LOG_ERR, "Unknown mode (%d) in handle_identity\n", reqinfo->mode );
+               return SNMP_ERR_GENERR;
        }
 
        return SNMP_ERR_NOERROR;
@@ -117,59 +113,55 @@ int handle_systemStats(netsnmp_mib_handler *handler, netsnmp_handler_registratio
        uint32_t int_val;
 
        switch(reqinfo->mode) {
-               case MODE_GET:
-                       for (request = requests; request; request = request->next) {
-                               subid = request->requestvb->name[OID_LENGTH(systemStats_oid)];
-
-                               switch (subid) {
-                                       case uptime_oid:
-                                               uptime = switch_core_uptime() / 10000;
-                                               snmp_set_var_typed_value(requests->requestvb, ASN_TIMETICKS, (u_char *) &uptime, sizeof(uptime));
-                                               break;
-                                       case sessionsSinceStartup_oid:
-                                               int_val = switch_core_session_id() - 1;
-                                               snmp_set_var_typed_value(requests->requestvb, ASN_COUNTER, (u_char *) &int_val, sizeof(int_val));
-                                               break;
-                                       case currentSessions_oid:
-                                               int_val = switch_core_session_count();
-                                               snmp_set_var_typed_value(requests->requestvb, ASN_GAUGE, (u_char *) &int_val, sizeof(int_val));
-                                               break;
-                                       case maxSessions_oid:
-                                               switch_core_session_ctl(SCSC_MAX_SESSIONS, &int_val);;
-                                               snmp_set_var_typed_value(requests->requestvb, ASN_GAUGE, (u_char *) &int_val, sizeof(int_val));
-                                               break;
-                                       case currentCalls_oid:
-                                               /*
-                                                * This is zero for now, since there is no convenient way to get total call
-                                                * count (not to be confused with session count), without touching the
-                                                * database.
-                                                */
-                                               int_val = 0;
-                                               snmp_set_var_typed_value(requests->requestvb, ASN_GAUGE, (u_char *) &int_val, sizeof(int_val));
-                                               break;
-                                       case sessionsPerSecond_oid:
-                                               switch_core_session_ctl(SCSC_LAST_SPS, &int_val);
-                                               snmp_set_var_typed_value(requests->requestvb, ASN_GAUGE, (u_char *) &int_val, sizeof(int_val));
-                                               break;
-                                       case maxSessionsPerSecond_oid:
-                                               switch_core_session_ctl(SCSC_SPS, &int_val);
-                                               snmp_set_var_typed_value(requests->requestvb, ASN_GAUGE, (u_char *) &int_val, sizeof(int_val));
-                                               break;
-                                       default:
-                                               snmp_log(LOG_WARNING, "Unregistered OID-suffix requested (%d)\n", (int) subid);
-                                               netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHOBJECT);
-                               }
+       case MODE_GET:
+               for (request = requests; request; request = request->next) {
+                       subid = request->requestvb->name[reginfo->rootoid_len - 2];
+
+                       switch (subid) {
+                               case uptime_oid:
+                                       uptime = switch_core_uptime() / 10000;
+                                       snmp_set_var_typed_value(requests->requestvb, ASN_TIMETICKS, (u_char *) &uptime, sizeof(uptime));
+                                       break;
+                               case sessionsSinceStartup_oid:
+                                       int_val = switch_core_session_id() - 1;
+                                       snmp_set_var_typed_value(requests->requestvb, ASN_COUNTER, (u_char *) &int_val, sizeof(int_val));
+                                       break;
+                               case currentSessions_oid:
+                                       int_val = switch_core_session_count();
+                                       snmp_set_var_typed_value(requests->requestvb, ASN_GAUGE, (u_char *) &int_val, sizeof(int_val));
+                                       break;
+                               case maxSessions_oid:
+                                       switch_core_session_ctl(SCSC_MAX_SESSIONS, &int_val);;
+                                       snmp_set_var_typed_value(requests->requestvb, ASN_GAUGE, (u_char *) &int_val, sizeof(int_val));
+                                       break;
+                               case currentCalls_oid:
+                                       /*
+                                        * This is zero for now, since there is no convenient way to get total call
+                                        * count (not to be confused with session count), without touching the
+                                        * database.
+                                        */
+                                       int_val = 0;
+                                       snmp_set_var_typed_value(requests->requestvb, ASN_GAUGE, (u_char *) &int_val, sizeof(int_val));
+                                       break;
+                               case sessionsPerSecond_oid:
+                                       switch_core_session_ctl(SCSC_LAST_SPS, &int_val);
+                                       snmp_set_var_typed_value(requests->requestvb, ASN_GAUGE, (u_char *) &int_val, sizeof(int_val));
+                                       break;
+                               case maxSessionsPerSecond_oid:
+                                       switch_core_session_ctl(SCSC_SPS, &int_val);
+                                       snmp_set_var_typed_value(requests->requestvb, ASN_GAUGE, (u_char *) &int_val, sizeof(int_val));
+                                       break;
+                               default:
+                                       snmp_log(LOG_WARNING, "Unregistered OID-suffix requested (%d)\n", (int) subid);
+                                       netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHOBJECT);
                        }
-                       break;
-
-               case MODE_GETNEXT:
-                       snmp_log(LOG_ERR, "MODE_GETNEXT not supported (yet)\n");
-                       break;
+               }
+               break;
 
-               default:
-                       /* we should never get here, so this is a really bad error */
-                       snmp_log(LOG_ERR, "Unknown mode (%d) in handle_systemStats\n", reqinfo->mode);
-                       return SNMP_ERR_GENERR;
+       default:
+               /* we should never get here, so this is a really bad error */
+               snmp_log(LOG_ERR, "Unknown mode (%d) in handle_systemStats\n", reqinfo->mode);
+               return SNMP_ERR_GENERR;
        }
 
        return SNMP_ERR_NOERROR;