diff options
Diffstat (limited to 'trunk/res/snmp/agent.c')
-rw-r--r-- | trunk/res/snmp/agent.c | 842 |
1 files changed, 842 insertions, 0 deletions
diff --git a/trunk/res/snmp/agent.c b/trunk/res/snmp/agent.c new file mode 100644 index 000000000..207acb8a1 --- /dev/null +++ b/trunk/res/snmp/agent.c @@ -0,0 +1,842 @@ +/* + * Copyright (C) 2006 Voop as + * Thorsten Lockert <tholo@voop.as> + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! \file + * + * \brief SNMP Agent / SubAgent support for Asterisk + * + * \author Thorsten Lockert <tholo@voop.as> + */ + +#include "asterisk.h" + +ASTERISK_FILE_VERSION(__FILE__, "$Revision$") + +/* + * There is some collision collision between netsmp and asterisk names, + * causing build under AST_DEVMODE to fail. + * + * The following PACKAGE_* macros are one place. + * Also netsnmp has an improper check for HAVE_DMALLOC_H, using + * #if HAVE_DMALLOC_H instead of #ifdef HAVE_DMALLOC_H + * As a countermeasure we define it to 0, however this will fail + * when the proper check is implemented. + */ +#ifdef PACKAGE_NAME +#undef PACKAGE_NAME +#endif +#ifdef PACKAGE_BUGREPORT +#undef PACKAGE_BUGREPORT +#endif +#ifdef PACKAGE_STRING +#undef PACKAGE_STRING +#endif +#ifdef PACKAGE_TARNAME +#undef PACKAGE_TARNAME +#endif +#ifdef PACKAGE_VERSION +#undef PACKAGE_VERSION +#endif +#ifndef HAVE_DMALLOC_H +#define HAVE_DMALLOC_H 0 /* XXX we shouldn't do this */ +#endif + +#include <net-snmp/net-snmp-config.h> +#include <net-snmp/net-snmp-includes.h> +#include <net-snmp/agent/net-snmp-agent-includes.h> + +#include "asterisk/paths.h" /* need ast_config_AST_SOCKET */ +#include "asterisk/channel.h" +#include "asterisk/logger.h" +#include "asterisk/options.h" +#include "asterisk/indications.h" +#include "asterisk/version.h" +#include "asterisk/pbx.h" + +/* Colission between Net-SNMP and Asterisk */ +#define unload_module ast_unload_module +#include "asterisk/module.h" +#undef unload_module + +#include "agent.h" + +/* Helper functions in Net-SNMP, header file not installed by default */ +int header_generic(struct variable *, oid *, size_t *, int, size_t *, WriteMethod **); +int header_simple_table(struct variable *, oid *, size_t *, int, size_t *, WriteMethod **, int); +int register_sysORTable(oid *, size_t, const char *); +int unregister_sysORTable(oid *, size_t); + +/* Forward declaration */ +static void init_asterisk_mib(void); + +/* + * Anchor for all the Asterisk MIB values + */ +static oid asterisk_oid[] = { 1, 3, 6, 1, 4, 1, 22736, 1 }; + +/* + * MIB values -- these correspond to values in the Asterisk MIB, + * and MUST be kept in sync with the MIB for things to work as + * expected. + */ +#define ASTVERSION 1 +#define ASTVERSTRING 1 +#define ASTVERTAG 2 + +#define ASTCONFIGURATION 2 +#define ASTCONFUPTIME 1 +#define ASTCONFRELOADTIME 2 +#define ASTCONFPID 3 +#define ASTCONFSOCKET 4 +#define ASTCONFACTIVECALLS 5 +#define ASTCONFPROCESSEDCALLS 6 + +#define ASTMODULES 3 +#define ASTMODCOUNT 1 + +#define ASTINDICATIONS 4 +#define ASTINDCOUNT 1 +#define ASTINDCURRENT 2 + +#define ASTINDTABLE 3 +#define ASTINDINDEX 1 +#define ASTINDCOUNTRY 2 +#define ASTINDALIAS 3 +#define ASTINDDESCRIPTION 4 + +#define ASTCHANNELS 5 +#define ASTCHANCOUNT 1 + +#define ASTCHANTABLE 2 +#define ASTCHANINDEX 1 +#define ASTCHANNAME 2 +#define ASTCHANLANGUAGE 3 +#define ASTCHANTYPE 4 +#define ASTCHANMUSICCLASS 5 +#define ASTCHANBRIDGE 6 +#define ASTCHANMASQ 7 +#define ASTCHANMASQR 8 +#define ASTCHANWHENHANGUP 9 +#define ASTCHANAPP 10 +#define ASTCHANDATA 11 +#define ASTCHANCONTEXT 12 +#define ASTCHANMACROCONTEXT 13 +#define ASTCHANMACROEXTEN 14 +#define ASTCHANMACROPRI 15 +#define ASTCHANEXTEN 16 +#define ASTCHANPRI 17 +#define ASTCHANACCOUNTCODE 18 +#define ASTCHANFORWARDTO 19 +#define ASTCHANUNIQUEID 20 +#define ASTCHANCALLGROUP 21 +#define ASTCHANPICKUPGROUP 22 +#define ASTCHANSTATE 23 +#define ASTCHANMUTED 24 +#define ASTCHANRINGS 25 +#define ASTCHANCIDDNID 26 +#define ASTCHANCIDNUM 27 +#define ASTCHANCIDNAME 28 +#define ASTCHANCIDANI 29 +#define ASTCHANCIDRDNIS 30 +#define ASTCHANCIDPRES 31 +#define ASTCHANCIDANI2 32 +#define ASTCHANCIDTON 33 +#define ASTCHANCIDTNS 34 +#define ASTCHANAMAFLAGS 35 +#define ASTCHANADSI 36 +#define ASTCHANTONEZONE 37 +#define ASTCHANHANGUPCAUSE 38 +#define ASTCHANVARIABLES 39 +#define ASTCHANFLAGS 40 +#define ASTCHANTRANSFERCAP 41 + +#define ASTCHANTYPECOUNT 3 + +#define ASTCHANTYPETABLE 4 +#define ASTCHANTYPEINDEX 1 +#define ASTCHANTYPENAME 2 +#define ASTCHANTYPEDESC 3 +#define ASTCHANTYPEDEVSTATE 4 +#define ASTCHANTYPEINDICATIONS 5 +#define ASTCHANTYPETRANSFER 6 +#define ASTCHANTYPECHANNELS 7 + +#define ASTCHANSCALARS 5 +#define ASTCHANBRIDGECOUNT 1 + +void *agent_thread(void *arg) +{ + ast_verb(2, "Starting %sAgent\n", res_snmp_agentx_subagent ? "Sub" : ""); + + snmp_enable_stderrlog(); + + if (res_snmp_agentx_subagent) + netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, + NETSNMP_DS_AGENT_ROLE, + 1); + + init_agent("asterisk"); + + init_asterisk_mib(); + + init_snmp("asterisk"); + + if (!res_snmp_agentx_subagent) + init_master_agent(); + + while (res_snmp_dont_stop) + agent_check_and_process(1); + + snmp_shutdown("asterisk"); + + ast_verb(2, "Terminating %sAgent\n", res_snmp_agentx_subagent ? "Sub" : ""); + + return NULL; +} + +static u_char * +ast_var_channels(struct variable *vp, oid *name, size_t *length, + int exact, size_t *var_len, WriteMethod **write_method) +{ + static unsigned long long_ret; + + if (header_generic(vp, name, length, exact, var_len, write_method)) + return NULL; + + if (vp->magic != ASTCHANCOUNT) + return NULL; + + long_ret = ast_active_channels(); + + return (u_char *)&long_ret; +} + +static u_char *ast_var_channels_table(struct variable *vp, oid *name, size_t *length, + int exact, size_t *var_len, WriteMethod **write_method) +{ + static unsigned long long_ret; + static u_char bits_ret[2]; + static char string_ret[256]; + struct ast_channel *chan, *bridge; + struct timeval tval; + u_char *ret = NULL; + int i, bit; + struct ast_str *out = ast_str_alloca(2048); + + if (header_simple_table(vp, name, length, exact, var_len, write_method, ast_active_channels())) + return NULL; + + i = name[*length - 1] - 1; + for (chan = ast_channel_walk_locked(NULL); + chan && i; + chan = ast_channel_walk_locked(chan), i--) + ast_channel_unlock(chan); + if (chan == NULL) + return NULL; + *var_len = sizeof(long_ret); + + switch (vp->magic) { + case ASTCHANINDEX: + long_ret = name[*length - 1]; + ret = (u_char *)&long_ret; + break; + case ASTCHANNAME: + if (!ast_strlen_zero(chan->name)) { + strncpy(string_ret, chan->name, sizeof(string_ret)); + string_ret[sizeof(string_ret) - 1] = '\0'; + *var_len = strlen(string_ret); + ret = (u_char *)string_ret; + } + break; + case ASTCHANLANGUAGE: + if (!ast_strlen_zero(chan->language)) { + strncpy(string_ret, chan->language, sizeof(string_ret)); + string_ret[sizeof(string_ret) - 1] = '\0'; + *var_len = strlen(string_ret); + ret = (u_char *)string_ret; + } + break; + case ASTCHANTYPE: + strncpy(string_ret, chan->tech->type, sizeof(string_ret)); + string_ret[sizeof(string_ret) - 1] = '\0'; + *var_len = strlen(string_ret); + ret = (u_char *)string_ret; + break; + case ASTCHANMUSICCLASS: + if (!ast_strlen_zero(chan->musicclass)) { + strncpy(string_ret, chan->musicclass, sizeof(string_ret)); + string_ret[sizeof(string_ret) - 1] = '\0'; + *var_len = strlen(string_ret); + ret = (u_char *)string_ret; + } + break; + case ASTCHANBRIDGE: + if ((bridge = ast_bridged_channel(chan)) != NULL) { + strncpy(string_ret, bridge->name, sizeof(string_ret)); + string_ret[sizeof(string_ret) - 1] = '\0'; + *var_len = strlen(string_ret); + ret = (u_char *)string_ret; + } + break; + case ASTCHANMASQ: + if (chan->masq && !ast_strlen_zero(chan->masq->name)) { + strncpy(string_ret, chan->masq->name, sizeof(string_ret)); + string_ret[sizeof(string_ret) - 1] = '\0'; + *var_len = strlen(string_ret); + ret = (u_char *)string_ret; + } + break; + case ASTCHANMASQR: + if (chan->masqr && !ast_strlen_zero(chan->masqr->name)) { + strncpy(string_ret, chan->masqr->name, sizeof(string_ret)); + string_ret[sizeof(string_ret) - 1] = '\0'; + *var_len = strlen(string_ret); + ret = (u_char *)string_ret; + } + break; + case ASTCHANWHENHANGUP: + if (chan->whentohangup) { + gettimeofday(&tval, NULL); + long_ret = difftime(chan->whentohangup, tval.tv_sec) * 100 - tval.tv_usec / 10000; + ret= (u_char *)&long_ret; + } + break; + case ASTCHANAPP: + if (chan->appl) { + strncpy(string_ret, chan->appl, sizeof(string_ret)); + string_ret[sizeof(string_ret) - 1] = '\0'; + *var_len = strlen(string_ret); + ret = (u_char *)string_ret; + } + break; + case ASTCHANDATA: + if (chan->data) { + strncpy(string_ret, chan->data, sizeof(string_ret)); + string_ret[sizeof(string_ret) - 1] = '\0'; + *var_len = strlen(string_ret); + ret = (u_char *)string_ret; + } + break; + case ASTCHANCONTEXT: + strncpy(string_ret, chan->context, sizeof(string_ret)); + string_ret[sizeof(string_ret) - 1] = '\0'; + *var_len = strlen(string_ret); + ret = (u_char *)string_ret; + break; + case ASTCHANMACROCONTEXT: + strncpy(string_ret, chan->macrocontext, sizeof(string_ret)); + string_ret[sizeof(string_ret) - 1] = '\0'; + *var_len = strlen(string_ret); + ret = (u_char *)string_ret; + break; + case ASTCHANMACROEXTEN: + strncpy(string_ret, chan->macroexten, sizeof(string_ret)); + string_ret[sizeof(string_ret) - 1] = '\0'; + *var_len = strlen(string_ret); + ret = (u_char *)string_ret; + break; + case ASTCHANMACROPRI: + long_ret = chan->macropriority; + ret = (u_char *)&long_ret; + break; + case ASTCHANEXTEN: + strncpy(string_ret, chan->exten, sizeof(string_ret)); + string_ret[sizeof(string_ret) - 1] = '\0'; + *var_len = strlen(string_ret); + ret = (u_char *)string_ret; + break; + case ASTCHANPRI: + long_ret = chan->priority; + ret = (u_char *)&long_ret; + break; + case ASTCHANACCOUNTCODE: + if (!ast_strlen_zero(chan->accountcode)) { + strncpy(string_ret, chan->accountcode, sizeof(string_ret)); + string_ret[sizeof(string_ret) - 1] = '\0'; + *var_len = strlen(string_ret); + ret = (u_char *)string_ret; + } + break; + case ASTCHANFORWARDTO: + if (!ast_strlen_zero(chan->call_forward)) { + strncpy(string_ret, chan->call_forward, sizeof(string_ret)); + string_ret[sizeof(string_ret) - 1] = '\0'; + *var_len = strlen(string_ret); + ret = (u_char *)string_ret; + } + break; + case ASTCHANUNIQUEID: + strncpy(string_ret, chan->uniqueid, sizeof(string_ret)); + string_ret[sizeof(string_ret) - 1] = '\0'; + *var_len = strlen(string_ret); + ret = (u_char *)string_ret; + break; + case ASTCHANCALLGROUP: + long_ret = chan->callgroup; + ret = (u_char *)&long_ret; + break; + case ASTCHANPICKUPGROUP: + long_ret = chan->pickupgroup; + ret = (u_char *)&long_ret; + break; + case ASTCHANSTATE: + long_ret = chan->_state & 0xffff; + ret = (u_char *)&long_ret; + break; + case ASTCHANMUTED: + long_ret = chan->_state & AST_STATE_MUTE ? 1 : 2; + ret = (u_char *)&long_ret; + break; + case ASTCHANRINGS: + long_ret = chan->rings; + ret = (u_char *)&long_ret; + break; + case ASTCHANCIDDNID: + if (chan->cid.cid_dnid) { + strncpy(string_ret, chan->cid.cid_dnid, sizeof(string_ret)); + string_ret[sizeof(string_ret) - 1] = '\0'; + *var_len = strlen(string_ret); + ret = (u_char *)string_ret; + } + break; + case ASTCHANCIDNUM: + if (chan->cid.cid_num) { + strncpy(string_ret, chan->cid.cid_num, sizeof(string_ret)); + string_ret[sizeof(string_ret) - 1] = '\0'; + *var_len = strlen(string_ret); + ret = (u_char *)string_ret; + } + break; + case ASTCHANCIDNAME: + if (chan->cid.cid_name) { + strncpy(string_ret, chan->cid.cid_name, sizeof(string_ret)); + string_ret[sizeof(string_ret) - 1] = '\0'; + *var_len = strlen(string_ret); + ret = (u_char *)string_ret; + } + break; + case ASTCHANCIDANI: + if (chan->cid.cid_ani) { + strncpy(string_ret, chan->cid.cid_ani, sizeof(string_ret)); + string_ret[sizeof(string_ret) - 1] = '\0'; + *var_len = strlen(string_ret); + ret = (u_char *)string_ret; + } + break; + case ASTCHANCIDRDNIS: + if (chan->cid.cid_rdnis) { + strncpy(string_ret, chan->cid.cid_rdnis, sizeof(string_ret)); + string_ret[sizeof(string_ret) - 1] = '\0'; + *var_len = strlen(string_ret); + ret = (u_char *)string_ret; + } + break; + case ASTCHANCIDPRES: + long_ret = chan->cid.cid_pres; + ret = (u_char *)&long_ret; + break; + case ASTCHANCIDANI2: + long_ret = chan->cid.cid_ani2; + ret = (u_char *)&long_ret; + break; + case ASTCHANCIDTON: + long_ret = chan->cid.cid_ton; + ret = (u_char *)&long_ret; + break; + case ASTCHANCIDTNS: + long_ret = chan->cid.cid_tns; + ret = (u_char *)&long_ret; + break; + case ASTCHANAMAFLAGS: + long_ret = chan->amaflags; + ret = (u_char *)&long_ret; + break; + case ASTCHANADSI: + long_ret = chan->adsicpe; + ret = (u_char *)&long_ret; + break; + case ASTCHANTONEZONE: + if (chan->zone) { + strncpy(string_ret, chan->zone->country, sizeof(string_ret)); + string_ret[sizeof(string_ret) - 1] = '\0'; + *var_len = strlen(string_ret); + ret = (u_char *)string_ret; + } + break; + case ASTCHANHANGUPCAUSE: + long_ret = chan->hangupcause; + ret = (u_char *)&long_ret; + break; + case ASTCHANVARIABLES: + if (pbx_builtin_serialize_variables(chan, &out)) { + *var_len = strlen(out->str); + ret = (u_char *)out->str; + } + break; + case ASTCHANFLAGS: + bits_ret[0] = 0; + for (bit = 0; bit < 8; bit++) + bits_ret[0] |= ((chan->flags & (1 << bit)) >> bit) << (7 - bit); + bits_ret[1] = 0; + for (bit = 0; bit < 8; bit++) + bits_ret[1] |= (((chan->flags >> 8) & (1 << bit)) >> bit) << (7 - bit); + *var_len = 2; + ret = bits_ret; + break; + case ASTCHANTRANSFERCAP: + long_ret = chan->transfercapability; + ret = (u_char *)&long_ret; + default: + break; + } + ast_channel_unlock(chan); + return ret; +} + +static u_char *ast_var_channel_types(struct variable *vp, oid *name, size_t *length, + int exact, size_t *var_len, WriteMethod **write_method) +{ + static unsigned long long_ret; + struct ast_variable *channel_types, *next; + + if (header_generic(vp, name, length, exact, var_len, write_method)) + return NULL; + + if (vp->magic != ASTCHANTYPECOUNT) + return NULL; + + for (long_ret = 0, channel_types = next = ast_channeltype_list(); next; next = next->next) + long_ret++; + ast_variables_destroy(channel_types); + + return (u_char *)&long_ret; +} + +static u_char *ast_var_channel_types_table(struct variable *vp, oid *name, size_t *length, + int exact, size_t *var_len, WriteMethod **write_method) +{ + const struct ast_channel_tech *tech = NULL; + struct ast_variable *channel_types, *next; + static unsigned long long_ret; + struct ast_channel *chan; + u_long i; + + if (header_simple_table(vp, name, length, exact, var_len, write_method, -1)) + return NULL; + + channel_types = ast_channeltype_list(); + for (i = 1, next = channel_types; next && i != name[*length - 1]; next = next->next, i++) + ; + if (next != NULL) + tech = ast_get_channel_tech(next->name); + ast_variables_destroy(channel_types); + if (next == NULL || tech == NULL) + return NULL; + + switch (vp->magic) { + case ASTCHANTYPEINDEX: + long_ret = name[*length - 1]; + return (u_char *)&long_ret; + case ASTCHANTYPENAME: + *var_len = strlen(tech->type); + return (u_char *)tech->type; + case ASTCHANTYPEDESC: + *var_len = strlen(tech->description); + return (u_char *)tech->description; + case ASTCHANTYPEDEVSTATE: + long_ret = tech->devicestate ? 1 : 2; + return (u_char *)&long_ret; + case ASTCHANTYPEINDICATIONS: + long_ret = tech->indicate ? 1 : 2; + return (u_char *)&long_ret; + case ASTCHANTYPETRANSFER: + long_ret = tech->transfer ? 1 : 2; + return (u_char *)&long_ret; + case ASTCHANTYPECHANNELS: + long_ret = 0; + for (chan = ast_channel_walk_locked(NULL); chan; chan = ast_channel_walk_locked(chan)) { + ast_channel_unlock(chan); + if (chan->tech == tech) + long_ret++; + } + return (u_char *)&long_ret; + default: + break; + } + return NULL; +} + +static u_char *ast_var_channel_bridge(struct variable *vp, oid *name, size_t *length, + int exact, size_t *var_len, WriteMethod **write_method) +{ + static unsigned long long_ret; + struct ast_channel *chan = NULL; + + long_ret = 0; + if (header_generic(vp, name, length, exact, var_len, write_method)) + return NULL; + + while ((chan = ast_channel_walk_locked(chan))) { + if (ast_bridged_channel(chan)) + long_ret++; + ast_channel_unlock(chan); + } + + *var_len = sizeof(long_ret); + + return (vp->magic == ASTCHANBRIDGECOUNT) ? (u_char *) &long_ret : NULL; +} + +static u_char *ast_var_Config(struct variable *vp, oid *name, size_t *length, + int exact, size_t *var_len, WriteMethod **write_method) +{ + static unsigned long long_ret; + struct timeval tval; + + if (header_generic(vp, name, length, exact, var_len, write_method)) + return NULL; + + switch (vp->magic) { + case ASTCONFUPTIME: + gettimeofday(&tval, NULL); + long_ret = difftime(tval.tv_sec, ast_startuptime.tv_sec) * 100 + tval.tv_usec / 10000 - ast_startuptime.tv_usec / 10000; + return (u_char *)&long_ret; + case ASTCONFRELOADTIME: + gettimeofday(&tval, NULL); + if (ast_lastreloadtime.tv_sec) + long_ret = difftime(tval.tv_sec, ast_lastreloadtime.tv_sec) * 100 + tval.tv_usec / 10000 - ast_lastreloadtime.tv_usec / 10000; + else + long_ret = difftime(tval.tv_sec, ast_startuptime.tv_sec) * 100 + tval.tv_usec / 10000 - ast_startuptime.tv_usec / 10000; + return (u_char *)&long_ret; + case ASTCONFPID: + long_ret = getpid(); + return (u_char *)&long_ret; + case ASTCONFSOCKET: + *var_len = strlen(ast_config_AST_SOCKET); + return (u_char *)ast_config_AST_SOCKET; + case ASTCONFACTIVECALLS: + long_ret = ast_active_calls(); + return (u_char *)&long_ret; + case ASTCONFPROCESSEDCALLS: + long_ret = ast_processed_calls(); + return (u_char *)&long_ret; + default: + break; + } + return NULL; +} + +static u_char *ast_var_indications(struct variable *vp, oid *name, size_t *length, + int exact, size_t *var_len, WriteMethod **write_method) +{ + static unsigned long long_ret; + struct ind_tone_zone *tz = NULL; + + if (header_generic(vp, name, length, exact, var_len, write_method)) + return NULL; + + switch (vp->magic) { + case ASTINDCOUNT: + long_ret = 0; + while ( (tz = ast_walk_indications(tz)) ) + long_ret++; + + return (u_char *)&long_ret; + case ASTINDCURRENT: + tz = ast_get_indication_zone(NULL); + if (tz) { + *var_len = strlen(tz->country); + return (u_char *)tz->country; + } + *var_len = 0; + return NULL; + default: + break; + } + return NULL; +} + +static u_char *ast_var_indications_table(struct variable *vp, oid *name, size_t *length, + int exact, size_t *var_len, WriteMethod **write_method) +{ + static unsigned long long_ret; + struct ind_tone_zone *tz = NULL; + int i; + + if (header_simple_table(vp, name, length, exact, var_len, write_method, -1)) + return NULL; + + i = name[*length - 1] - 1; + while ( (tz = ast_walk_indications(tz)) && i ) + i--; + if (tz == NULL) + return NULL; + + switch (vp->magic) { + case ASTINDINDEX: + long_ret = name[*length - 1]; + return (u_char *)&long_ret; + case ASTINDCOUNTRY: + *var_len = strlen(tz->country); + return (u_char *)tz->country; + case ASTINDALIAS: + if (tz->alias) { + *var_len = strlen(tz->alias); + return (u_char *)tz->alias; + } + return NULL; + case ASTINDDESCRIPTION: + *var_len = strlen(tz->description); + return (u_char *)tz->description; + default: + break; + } + return NULL; +} + +static int countmodule(const char *mod, const char *desc, int use, const char *like) +{ + return 1; +} + +static u_char *ast_var_Modules(struct variable *vp, oid *name, size_t *length, + int exact, size_t *var_len, WriteMethod **write_method) +{ + static unsigned long long_ret; + + if (header_generic(vp, name, length, exact, var_len, write_method)) + return NULL; + + if (vp->magic != ASTMODCOUNT) + return NULL; + + long_ret = ast_update_module_list(countmodule, NULL); + + return (u_char *)&long_ret; +} + +static u_char *ast_var_Version(struct variable *vp, oid *name, size_t *length, + int exact, size_t *var_len, WriteMethod **write_method) +{ + static unsigned long long_ret; + + if (header_generic(vp, name, length, exact, var_len, write_method)) + return NULL; + + switch (vp->magic) { + case ASTVERSTRING: + { + const char *version = ast_get_version(); + *var_len = strlen(version); + return (u_char *)version; + } + case ASTVERTAG: + sscanf(ast_get_version_num(), "%lu", &long_ret); + return (u_char *)&long_ret; + default: + break; + } + return NULL; +} + +static int term_asterisk_mib(int majorID, int minorID, void *serverarg, void *clientarg) +{ + unregister_sysORTable(asterisk_oid, OID_LENGTH(asterisk_oid)); + return 0; +} + +static void init_asterisk_mib(void) +{ + static struct variable4 asterisk_vars[] = { + {ASTVERSTRING, ASN_OCTET_STR, RONLY, ast_var_Version, 2, {ASTVERSION, ASTVERSTRING}}, + {ASTVERTAG, ASN_UNSIGNED, RONLY, ast_var_Version, 2, {ASTVERSION, ASTVERTAG}}, + {ASTCONFUPTIME, ASN_TIMETICKS, RONLY, ast_var_Config, 2, {ASTCONFIGURATION, ASTCONFUPTIME}}, + {ASTCONFRELOADTIME, ASN_TIMETICKS, RONLY, ast_var_Config, 2, {ASTCONFIGURATION, ASTCONFRELOADTIME}}, + {ASTCONFPID, ASN_INTEGER, RONLY, ast_var_Config, 2, {ASTCONFIGURATION, ASTCONFPID}}, + {ASTCONFSOCKET, ASN_OCTET_STR, RONLY, ast_var_Config, 2, {ASTCONFIGURATION, ASTCONFSOCKET}}, + {ASTCONFACTIVECALLS, ASN_GAUGE, RONLY, ast_var_Config, 2, {ASTCONFIGURATION, ASTCONFACTIVECALLS}}, + {ASTCONFPROCESSEDCALLS, ASN_INTEGER, RONLY, ast_var_Config, 2, {ASTCONFIGURATION, ASTCONFPROCESSEDCALLS}}, + {ASTMODCOUNT, ASN_INTEGER, RONLY, ast_var_Modules , 2, {ASTMODULES, ASTMODCOUNT}}, + {ASTINDCOUNT, ASN_INTEGER, RONLY, ast_var_indications, 2, {ASTINDICATIONS, ASTINDCOUNT}}, + {ASTINDCURRENT, ASN_OCTET_STR, RONLY, ast_var_indications, 2, {ASTINDICATIONS, ASTINDCURRENT}}, + {ASTINDINDEX, ASN_INTEGER, RONLY, ast_var_indications_table, 4, {ASTINDICATIONS, ASTINDTABLE, 1, ASTINDINDEX}}, + {ASTINDCOUNTRY, ASN_OCTET_STR, RONLY, ast_var_indications_table, 4, {ASTINDICATIONS, ASTINDTABLE, 1, ASTINDCOUNTRY}}, + {ASTINDALIAS, ASN_OCTET_STR, RONLY, ast_var_indications_table, 4, {ASTINDICATIONS, ASTINDTABLE, 1, ASTINDALIAS}}, + {ASTINDDESCRIPTION, ASN_OCTET_STR, RONLY, ast_var_indications_table, 4, {ASTINDICATIONS, ASTINDTABLE, 1, ASTINDDESCRIPTION}}, + {ASTCHANCOUNT, ASN_INTEGER, RONLY, ast_var_channels, 2, {ASTCHANNELS, ASTCHANCOUNT}}, + {ASTCHANINDEX, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANINDEX}}, + {ASTCHANNAME, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANNAME}}, + {ASTCHANLANGUAGE, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANLANGUAGE}}, + {ASTCHANTYPE, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANTYPE}}, + {ASTCHANMUSICCLASS, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANMUSICCLASS}}, + {ASTCHANBRIDGE, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANBRIDGE}}, + {ASTCHANMASQ, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANMASQ}}, + {ASTCHANMASQR, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANMASQR}}, + {ASTCHANWHENHANGUP, ASN_TIMETICKS, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANWHENHANGUP}}, + {ASTCHANAPP, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANAPP}}, + {ASTCHANDATA, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANDATA}}, + {ASTCHANCONTEXT, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCONTEXT}}, + {ASTCHANMACROCONTEXT, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANMACROCONTEXT}}, + {ASTCHANMACROEXTEN, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANMACROEXTEN}}, + {ASTCHANMACROPRI, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANMACROPRI}}, + {ASTCHANEXTEN, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANEXTEN}}, + {ASTCHANPRI, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANPRI}}, + {ASTCHANACCOUNTCODE, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANACCOUNTCODE}}, + {ASTCHANFORWARDTO, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANFORWARDTO}}, + {ASTCHANUNIQUEID, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANUNIQUEID}}, + {ASTCHANCALLGROUP, ASN_UNSIGNED, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCALLGROUP}}, + {ASTCHANPICKUPGROUP, ASN_UNSIGNED, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANPICKUPGROUP}}, + {ASTCHANSTATE, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANSTATE}}, + {ASTCHANMUTED, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANMUTED}}, + {ASTCHANRINGS, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANRINGS}}, + {ASTCHANCIDDNID, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDDNID}}, + {ASTCHANCIDNUM, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDNUM}}, + {ASTCHANCIDNAME, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDNAME}}, + {ASTCHANCIDANI, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDANI}}, + {ASTCHANCIDRDNIS, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDRDNIS}}, + {ASTCHANCIDPRES, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDPRES}}, + {ASTCHANCIDANI2, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDANI2}}, + {ASTCHANCIDTON, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDTON}}, + {ASTCHANCIDTNS, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDTNS}}, + {ASTCHANAMAFLAGS, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANAMAFLAGS}}, + {ASTCHANADSI, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANADSI}}, + {ASTCHANTONEZONE, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANTONEZONE}}, + {ASTCHANHANGUPCAUSE, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANHANGUPCAUSE}}, + {ASTCHANVARIABLES, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANVARIABLES}}, + {ASTCHANFLAGS, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANFLAGS}}, + {ASTCHANTRANSFERCAP, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANTRANSFERCAP}}, + {ASTCHANTYPECOUNT, ASN_INTEGER, RONLY, ast_var_channel_types, 2, {ASTCHANNELS, ASTCHANTYPECOUNT}}, + {ASTCHANTYPEINDEX, ASN_INTEGER, RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPEINDEX}}, + {ASTCHANTYPENAME, ASN_OCTET_STR, RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPENAME}}, + {ASTCHANTYPEDESC, ASN_OCTET_STR, RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPEDESC}}, + {ASTCHANTYPEDEVSTATE, ASN_INTEGER, RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPEDEVSTATE}}, + {ASTCHANTYPEINDICATIONS, ASN_INTEGER, RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPEINDICATIONS}}, + {ASTCHANTYPETRANSFER, ASN_INTEGER, RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPETRANSFER}}, + {ASTCHANTYPECHANNELS, ASN_GAUGE, RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPECHANNELS}}, + {ASTCHANBRIDGECOUNT, ASN_GAUGE, RONLY, ast_var_channel_bridge, 3, {ASTCHANNELS, ASTCHANSCALARS, ASTCHANBRIDGECOUNT}}, + }; + + register_sysORTable(asterisk_oid, OID_LENGTH(asterisk_oid), + "ASTERISK-MIB implementation for Asterisk."); + + REGISTER_MIB("res_snmp", asterisk_vars, variable4, asterisk_oid); + + snmp_register_callback(SNMP_CALLBACK_LIBRARY, + SNMP_CALLBACK_SHUTDOWN, + term_asterisk_mib, NULL); +} + +/* + * Local Variables: + * c-basic-offset: 4 + * c-file-offsets: ((case-label . 0)) + * tab-width: 4 + * indent-tabs-mode: t + * End: + */ |