From c8f5c66c3520ecda8f8dbc07dc01f1d4035058e4 Mon Sep 17 00:00:00 2001 From: Daniel Swarbrick Date: Mon, 31 Jan 2011 15:41:58 +0100 Subject: [PATCH] mostly complete implementation of channel list via SNMP --- .../event_handlers/mod_snmp/FREESWITCH-MIB | 175 +++++++++++++++--- src/mod/event_handlers/mod_snmp/subagent.c | 105 +++++++++-- src/mod/event_handlers/mod_snmp/subagent.h | 51 ++++- 3 files changed, 289 insertions(+), 42 deletions(-) diff --git a/src/mod/event_handlers/mod_snmp/FREESWITCH-MIB b/src/mod/event_handlers/mod_snmp/FREESWITCH-MIB index 11c3999c6f..84485269f9 100644 --- a/src/mod/event_handlers/mod_snmp/FREESWITCH-MIB +++ b/src/mod/event_handlers/mod_snmp/FREESWITCH-MIB @@ -3,11 +3,14 @@ FREESWITCH-MIB DEFINITIONS ::= BEGIN IMPORTS OBJECT-TYPE, MODULE-IDENTITY, Integer32, Gauge32, Counter32, Counter64, TimeTicks, - enterprises, + enterprises FROM SNMPv2-SMI - DisplayString + DisplayString, DateAndTime FROM SNMPv2-TC + + InetAddressType, InetAddress + FROM INET-ADDRESS-MIB ; @@ -109,13 +112,27 @@ maxSessionsPerSecond OBJECT-TYPE ChannelEntry ::= SEQUENCE { - chanUUID DisplayString, - chanDirection DisplayString, - chanCreated DisplayString, - chanName DisplayString, - chanState DisplayString, - chanCIDName DisplayString, - chanCIDNum DisplayString + chanIndex Integer32, + chanUUID DisplayString, + chanDirection DisplayString, + chanCreated DateAndTime, + chanName DisplayString, + chanState DisplayString, + chanCIDName DisplayString, + chanCIDNum DisplayString, + chanInetAddressType InetAddressType, + chanInetAddress InetAddress, + chanDest DisplayString, + chanApplication DisplayString, + chanAppData DisplayString, + chanDialplan DisplayString, + chanContext DisplayString, + chanReadCodec DisplayString, + chanReadRate Gauge32, + chanReadBitRate Gauge32, + chanWriteCodec DisplayString, + chanWriteRate Gauge32, + chanWriteBitRate Gauge32 } channelList OBJECT-TYPE @@ -135,60 +152,172 @@ channelEntry OBJECT-TYPE INDEX { chanIndex } ::= { channelList 1 } +chanIndex OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Channel SNMP index." + ::= { channelEntry 1 } + chanUUID OBJECT-TYPE SYNTAX DisplayString MAX-ACCESS read-only STATUS current DESCRIPTION - "The channel UUID." - ::= { channelEntry 1 } + "Channel UUID." + ::= { channelEntry 2 } chanDirection OBJECT-TYPE SYNTAX DisplayString MAX-ACCESS read-only STATUS current DESCRIPTION - "The channel direction." - ::= { channelEntry 2 } + "Channel direction." + ::= { channelEntry 3 } chanCreated OBJECT-TYPE - SYNTAX DisplayString + SYNTAX DateAndTime MAX-ACCESS read-only STATUS current DESCRIPTION "Channel creation timestamp." - ::= { channelEntry 3 } + ::= { channelEntry 4 } chanName OBJECT-TYPE SYNTAX DisplayString MAX-ACCESS read-only STATUS current DESCRIPTION - "The channel name." - ::= { channelEntry 4 } + "Channel name." + ::= { channelEntry 5 } chanState OBJECT-TYPE SYNTAX DisplayString MAX-ACCESS read-only STATUS current DESCRIPTION - "The channel state." - ::= { channelEntry 5 } + "Channel state." + ::= { channelEntry 6 } chanCIDName OBJECT-TYPE SYNTAX DisplayString MAX-ACCESS read-only STATUS current DESCRIPTION - "The channel caller ID name." - ::= { channelEntry 6 } + "Channel caller ID name." + ::= { channelEntry 7 } chanCIDNum OBJECT-TYPE SYNTAX DisplayString MAX-ACCESS read-only STATUS current DESCRIPTION - "The channel caller ID number." - ::= { channelEntry 7 } + "Channel caller ID number." + ::= { channelEntry 8 } + +chanInetAddressType OBJECT-TYPE + SYNTAX InetAddressType + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Channel originator's IP address type (IPv4 or IPv6)." + ::= { channelEntry 9 } + +chanInetAddress OBJECT-TYPE + SYNTAX InetAddress + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Channel originator's IP address." + ::= { channelEntry 10 } + +chanDest OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Channel destination." + ::= { channelEntry 11 } + +chanApplication OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Channel application." + ::= { channelEntry 12 } + +chanAppData OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Channel application data." + ::= { channelEntry 13 } + +chanDialplan OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Channel dialplan." + ::= { channelEntry 14 } + +chanContext OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Channel dialplan context." + ::= { channelEntry 15 } + +chanReadCodec OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Channel read codec." + ::= { channelEntry 16 } + +chanReadRate OBJECT-TYPE + SYNTAX Gauge32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Channel read samples per second." + ::= { channelEntry 17 } + +chanReadBitRate OBJECT-TYPE + SYNTAX Gauge32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Channel read bits per second." + ::= { channelEntry 18 } + +chanWriteCodec OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Channel write codec." + ::= { channelEntry 19 } + +chanWriteRate OBJECT-TYPE + SYNTAX Gauge32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Channel write samples per second." + ::= { channelEntry 20 } + +chanWriteBitRate OBJECT-TYPE + SYNTAX Gauge32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Channel write bits per second." + ::= { channelEntry 21 } END diff --git a/src/mod/event_handlers/mod_snmp/subagent.c b/src/mod/event_handlers/mod_snmp/subagent.c index 7b9faa752b..43975ee4e0 100644 --- a/src/mod/event_handlers/mod_snmp/subagent.c +++ b/src/mod/event_handlers/mod_snmp/subagent.c @@ -42,6 +42,17 @@ netsnmp_handler_registration *ch_reginfo; uint32_t idx; +static void time_t_to_datetime(time_t epoch, char *buf, switch_size_t buflen) +{ + struct tm *dt; + uint16_t year; + + dt = gmtime(&epoch); + year = dt->tm_year + 1900; + switch_snprintf(buf, buflen, "%c%c%c%c%c%c%c%c+%c%c", year >> 8, year & 0xff, dt->tm_mon + 1, dt->tm_mday, dt->tm_hour, dt->tm_min, dt->tm_sec, 0, 0, 0); +} + + static int sql_count_callback(void *pArg, int argc, char **argv, char **columnNames) { uint32_t *count = (uint32_t *) pArg; @@ -69,11 +80,31 @@ static int channelList_callback(void *pArg, int argc, char **argv, char **column entry->idx = idx++; strncpy(entry->uuid, argv[0], sizeof(entry->uuid)); strncpy(entry->direction, argv[1], sizeof(entry->direction)); - strncpy(entry->created, argv[2], sizeof(entry->created)); + entry->created_epoch = atoi(argv[3]); strncpy(entry->name, argv[4], sizeof(entry->name)); strncpy(entry->state, argv[5], sizeof(entry->state)); strncpy(entry->cid_name, argv[6], sizeof(entry->cid_name)); strncpy(entry->cid_num, argv[7], sizeof(entry->cid_num)); + strncpy(entry->dest, argv[9], sizeof(entry->dest)); + strncpy(entry->application, argv[10], sizeof(entry->application)); + strncpy(entry->application_data, argv[11], sizeof(entry->application_data)); + strncpy(entry->dialplan, argv[12], sizeof(entry->dialplan)); + strncpy(entry->context, argv[13], sizeof(entry->context)); + strncpy(entry->read_codec, argv[14], sizeof(entry->read_codec)); + entry->read_rate = atoi(argv[15]); + entry->read_bitrate = atoi(argv[16]); + strncpy(entry->write_codec, argv[17], sizeof(entry->write_codec)); + entry->write_rate = atoi(argv[18]); + entry->write_bitrate = atoi(argv[19]); + + memset(&entry->ip_addr, 0, sizeof(entry->ip_addr)); + if (strchr(argv[8], ':')) { + switch_inet_pton(AF_INET6, argv[8], &entry->ip_addr); + entry->addr_family = AF_INET6; + } else { + switch_inet_pton(AF_INET, argv[8], &entry->ip_addr); + entry->addr_family = AF_INET; + } netsnmp_tdata_row_add_index(row, ASN_INTEGER, &entry->idx, sizeof(entry->idx)); netsnmp_tdata_add_row(ch_table, row); @@ -128,9 +159,9 @@ void init_subagent(switch_memory_pool_t *pool) netsnmp_register_scalar_group(netsnmp_create_handler_registration("systemStats", handle_systemStats, systemStats_oid, OID_LENGTH(systemStats_oid), HANDLER_CAN_RONLY), 1, 7); ch_table_info = switch_core_alloc(pool, sizeof(netsnmp_table_registration_info)); - netsnmp_table_helper_add_index(ch_table_info, ASN_INTEGER); - ch_table_info->min_column = 1; - ch_table_info->max_column = 7; + netsnmp_table_helper_add_indexes(ch_table_info, ASN_INTEGER, 0); + ch_table_info->min_column = CH_INDEX; + ch_table_info->max_column = CH_WRITE_BITRATE; ch_table = netsnmp_tdata_create_table("channelList", 0); ch_reginfo = netsnmp_create_handler_registration("channelList", handle_channelList, channelList_oid, OID_LENGTH(channelList_oid), HANDLER_CAN_RONLY); netsnmp_tdata_register(ch_reginfo, ch_table, ch_table_info); @@ -191,15 +222,15 @@ int handle_systemStats(netsnmp_mib_handler *handler, netsnmp_handler_registratio break; case SS_SESSIONS_SINCE_STARTUP: int_val = switch_core_session_id() - 1; - snmp_set_var_typed_value(requests->requestvb, ASN_COUNTER, (u_char *) &int_val, sizeof(int_val)); + snmp_set_var_typed_integer(requests->requestvb, ASN_COUNTER, int_val); break; case SS_CURRENT_SESSIONS: int_val = switch_core_session_count(); - snmp_set_var_typed_value(requests->requestvb, ASN_GAUGE, (u_char *) &int_val, sizeof(int_val)); + snmp_set_var_typed_integer(requests->requestvb, ASN_GAUGE, int_val); break; case SS_MAX_SESSIONS: 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)); + snmp_set_var_typed_integer(requests->requestvb, ASN_GAUGE, int_val); break; case SS_CURRENT_CALLS: { @@ -213,17 +244,17 @@ int handle_systemStats(netsnmp_mib_handler *handler, netsnmp_handler_registratio gethostname(hostname, sizeof(hostname)); sprintf(sql, "SELECT COUNT(*) FROM calls WHERE hostname='%s'", hostname); switch_cache_db_execute_sql_callback(dbh, sql, sql_count_callback, &int_val, NULL); - snmp_set_var_typed_value(requests->requestvb, ASN_GAUGE, (u_char *) &int_val, sizeof(int_val)); + snmp_set_var_typed_integer(requests->requestvb, ASN_GAUGE, int_val); switch_cache_db_release_db_handle(&dbh); } break; case SS_SESSIONS_PER_SECOND: 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)); + snmp_set_var_typed_integer(requests->requestvb, ASN_GAUGE, int_val); break; case SS_MAX_SESSIONS_PER_SECOND: switch_core_session_ctl(SCSC_SPS, &int_val); - snmp_set_var_typed_value(requests->requestvb, ASN_GAUGE, (u_char *) &int_val, sizeof(int_val)); + snmp_set_var_typed_integer(requests->requestvb, ASN_GAUGE, int_val); break; default: snmp_log(LOG_WARNING, "Unregistered OID-suffix requested (%d)\n", (int) subid); @@ -246,6 +277,7 @@ int handle_channelList(netsnmp_mib_handler *handler, netsnmp_handler_registratio netsnmp_request_info *request; netsnmp_table_request_info *table_info; chan_entry_t *entry; + char dt_str[12]; switch (reqinfo->mode) { case MODE_GET: @@ -254,6 +286,9 @@ int handle_channelList(netsnmp_mib_handler *handler, netsnmp_handler_registratio entry = (chan_entry_t *) netsnmp_tdata_extract_entry(request); switch (table_info->colnum) { + case CH_INDEX: + snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER, entry->idx); + break; case CH_UUID: snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR, (u_char *) entry->uuid, strlen(entry->uuid)); break; @@ -261,7 +296,8 @@ int handle_channelList(netsnmp_mib_handler *handler, netsnmp_handler_registratio snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR, (u_char *) entry->direction, strlen(entry->direction)); break; case CH_CREATED: - snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR, (u_char *) entry->created, strlen(entry->created)); + time_t_to_datetime(entry->created_epoch, (char *) &dt_str, sizeof(dt_str)); + snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR, (u_char *) &dt_str, sizeof(dt_str)); break; case CH_NAME: snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR, (u_char *) entry->name, strlen(entry->name)); @@ -275,6 +311,53 @@ int handle_channelList(netsnmp_mib_handler *handler, netsnmp_handler_registratio case CH_CID_NUM: snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR, (u_char *) entry->cid_num, strlen(entry->cid_num)); break; + case CH_IP_ADDR_TYPE: + if (entry->addr_family == AF_INET6) { + snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER, INETADDRESSTYPE_IPV6); + } else { + snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER, INETADDRESSTYPE_IPV4); + } + break; + case CH_IP_ADDR: + if (entry->addr_family == AF_INET6) { + snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR, (u_char *) &entry->ip_addr.v6, sizeof(entry->ip_addr.v6)); + } else { + snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR, (u_char *) &entry->ip_addr.v4, sizeof(entry->ip_addr.v4)); + } + break; + case CH_DEST: + snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR, (u_char *) entry->dest, strlen(entry->dest)); + break; + case CH_APPLICATION: + snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR, (u_char *) entry->application, strlen(entry->application)); + break; + case CH_APPLICATION_DATA: + snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR, (u_char *) entry->application_data, strlen(entry->application_data)); + break; + case CH_DIALPLAN: + snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR, (u_char *) entry->dialplan, strlen(entry->dialplan)); + break; + case CH_CONTEXT: + snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR, (u_char *) entry->context, strlen(entry->context)); + break; + case CH_READ_CODEC: + snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR, (u_char *) entry->read_codec, strlen(entry->read_codec)); + break; + case CH_READ_RATE: + snmp_set_var_typed_value(request->requestvb, ASN_GAUGE, (u_char *) &entry->read_rate, sizeof(entry->read_rate)); + break; + case CH_READ_BITRATE: + snmp_set_var_typed_value(request->requestvb, ASN_GAUGE, (u_char *) &entry->read_bitrate, sizeof(entry->read_bitrate)); + break; + case CH_WRITE_CODEC: + snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR, (u_char *) entry->write_codec, strlen(entry->write_codec)); + break; + case CH_WRITE_RATE: + snmp_set_var_typed_value(request->requestvb, ASN_GAUGE, (u_char *) &entry->write_rate, sizeof(entry->write_rate)); + break; + case CH_WRITE_BITRATE: + snmp_set_var_typed_value(request->requestvb, ASN_GAUGE, (u_char *) &entry->write_bitrate, sizeof(entry->write_bitrate)); + break; default: snmp_log(LOG_WARNING, "Unregistered OID-suffix requested (%d)\n", table_info->colnum); netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHOBJECT); diff --git a/src/mod/event_handlers/mod_snmp/subagent.h b/src/mod/event_handlers/mod_snmp/subagent.h index 0070b2c3af..5da87a6c4e 100644 --- a/src/mod/event_handlers/mod_snmp/subagent.h +++ b/src/mod/event_handlers/mod_snmp/subagent.h @@ -15,23 +15,58 @@ #define SS_MAX_SESSIONS_PER_SECOND 7 /* .1.3.6.1.4.1.27880.1.9 */ -#define CH_UUID 1 -#define CH_DIRECTION 2 -#define CH_CREATED 3 -#define CH_NAME 4 -#define CH_STATE 5 -#define CH_CID_NAME 6 -#define CH_CID_NUM 7 +#define CH_INDEX 1 +#define CH_UUID 2 +#define CH_DIRECTION 3 +#define CH_CREATED 4 +#define CH_NAME 5 +#define CH_STATE 6 +#define CH_CID_NAME 7 +#define CH_CID_NUM 8 +#define CH_IP_ADDR_TYPE 9 +#define CH_IP_ADDR 10 +#define CH_DEST 11 +#define CH_APPLICATION 12 +#define CH_APPLICATION_DATA 13 +#define CH_DIALPLAN 14 +#define CH_CONTEXT 15 +#define CH_READ_CODEC 16 +#define CH_READ_RATE 17 +#define CH_READ_BITRATE 18 +#define CH_WRITE_CODEC 19 +#define CH_WRITE_RATE 20 +#define CH_WRITE_BITRATE 21 + +/* Why aren't these in net-snmp-includes.h ? */ +#define INETADDRESSTYPE_UNKNOWN 0 +#define INETADDRESSTYPE_IPV4 1 +#define INETADDRESSTYPE_IPV6 2 +#define INETADDRESSTYPE_IPV4Z 3 +#define INETADDRESSTYPE_IPV6Z 4 +#define INETADDRESSTYPE_DNS 16 typedef struct { uint32_t idx; char uuid[38]; char direction[32]; - char created[128]; + time_t created_epoch; char name[1024]; char state[64]; char cid_name[1024]; char cid_num[256]; + ip_t ip_addr; + uint8_t addr_family; + char dest[1024]; + char application[128]; + char application_data[4096]; + char dialplan[128]; + char context[128]; + char read_codec[128]; + uint32_t read_rate; + uint32_t read_bitrate; + char write_codec[128]; + uint32_t write_rate; + uint32_t write_bitrate; } chan_entry_t; void init_subagent(switch_memory_pool_t *pool);