Mon Oct 8 12:38:55 2012

Asterisk developer's documentation


agent.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2006 Voop as
00003  * Thorsten Lockert <tholo@voop.as>
00004  *
00005  * This program is free software, distributed under the terms of
00006  * the GNU General Public License Version 2. See the LICENSE file
00007  * at the top of the source tree.
00008  */
00009 
00010 /*! \file
00011  *
00012  * \brief SNMP Agent / SubAgent support for Asterisk
00013  *
00014  * \author Thorsten Lockert <tholo@voop.as>
00015  */
00016 
00017 /*** MODULEINFO
00018    <support_level>extended</support_level>
00019  ***/
00020 
00021 #include "asterisk.h"
00022 
00023 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 369001 $")
00024 
00025 /*
00026  * There is some collision collision between netsmp and asterisk names,
00027  * causing build under AST_DEVMODE to fail.
00028  *
00029  * The following PACKAGE_* macros are one place.
00030  * Also netsnmp has an improper check for HAVE_DMALLOC_H, using
00031  *    #if HAVE_DMALLOC_H   instead of #ifdef HAVE_DMALLOC_H
00032  * As a countermeasure we define it to 0, however this will fail
00033  * when the proper check is implemented.
00034  */
00035 #ifdef PACKAGE_NAME
00036 #undef PACKAGE_NAME
00037 #endif
00038 #ifdef PACKAGE_BUGREPORT
00039 #undef PACKAGE_BUGREPORT
00040 #endif
00041 #ifdef PACKAGE_STRING
00042 #undef PACKAGE_STRING
00043 #endif
00044 #ifdef PACKAGE_TARNAME
00045 #undef PACKAGE_TARNAME
00046 #endif
00047 #ifdef PACKAGE_VERSION
00048 #undef PACKAGE_VERSION
00049 #endif
00050 #ifndef HAVE_DMALLOC_H
00051 #define HAVE_DMALLOC_H 0   /* XXX we shouldn't do this */
00052 #endif
00053 
00054 #if defined(__OpenBSD__)
00055 /*
00056  * OpenBSD uses old "legacy" cc which has a rather pedantic builtin preprocessor.
00057  * Using a macro which is not #defined throws an error.
00058  */
00059 #define __NetBSD_Version__ 0
00060 #endif
00061 
00062 #include <net-snmp/net-snmp-config.h>
00063 #include <net-snmp/net-snmp-includes.h>
00064 #include <net-snmp/agent/net-snmp-agent-includes.h>
00065 
00066 #include "asterisk/paths.h"   /* need ast_config_AST_SOCKET */
00067 #include "asterisk/channel.h"
00068 #include "asterisk/logger.h"
00069 #include "asterisk/options.h"
00070 #include "asterisk/indications.h"
00071 #include "asterisk/ast_version.h"
00072 #include "asterisk/pbx.h"
00073 
00074 /* Colission between Net-SNMP and Asterisk */
00075 #define unload_module ast_unload_module
00076 #include "asterisk/module.h"
00077 #undef unload_module
00078 
00079 #include "agent.h"
00080 
00081 /* Helper functions in Net-SNMP, header file not installed by default */
00082 int header_generic(struct variable *, oid *, size_t *, int, size_t *, WriteMethod **);
00083 int header_simple_table(struct variable *, oid *, size_t *, int, size_t *, WriteMethod **, int);
00084 int register_sysORTable(oid *, size_t, const char *);
00085 int unregister_sysORTable(oid *, size_t);
00086 
00087 /* Forward declaration */
00088 static void init_asterisk_mib(void);
00089 
00090 /*
00091  * Anchor for all the Asterisk MIB values
00092  */
00093 static oid asterisk_oid[] = { 1, 3, 6, 1, 4, 1, 22736, 1 };
00094 
00095 /*
00096  * MIB values -- these correspond to values in the Asterisk MIB,
00097  * and MUST be kept in sync with the MIB for things to work as
00098  * expected.
00099  */
00100 #define ASTVERSION            1
00101 #define     ASTVERSTRING         1
00102 #define     ASTVERTAG            2
00103 
00104 #define  ASTCONFIGURATION     2
00105 #define     ASTCONFUPTIME        1
00106 #define     ASTCONFRELOADTIME    2
00107 #define     ASTCONFPID           3
00108 #define     ASTCONFSOCKET        4
00109 #define     ASTCONFACTIVECALLS   5
00110 #define     ASTCONFPROCESSEDCALLS   6
00111 
00112 #define  ASTMODULES           3
00113 #define     ASTMODCOUNT          1
00114 
00115 #define  ASTINDICATIONS       4
00116 #define     ASTINDCOUNT          1
00117 #define     ASTINDCURRENT        2
00118 
00119 #define     ASTINDTABLE          3
00120 #define        ASTINDINDEX          1
00121 #define        ASTINDCOUNTRY        2
00122 #define        ASTINDALIAS          3
00123 #define        ASTINDDESCRIPTION    4
00124 
00125 #define  ASTCHANNELS          5
00126 #define     ASTCHANCOUNT         1
00127 
00128 #define     ASTCHANTABLE         2
00129 #define        ASTCHANINDEX         1
00130 #define        ASTCHANNAME          2
00131 #define        ASTCHANLANGUAGE         3
00132 #define        ASTCHANTYPE          4
00133 #define        ASTCHANMUSICCLASS    5
00134 #define        ASTCHANBRIDGE        6
00135 #define        ASTCHANMASQ          7
00136 #define        ASTCHANMASQR         8
00137 #define        ASTCHANWHENHANGUP    9
00138 #define        ASTCHANAPP           10
00139 #define        ASTCHANDATA          11
00140 #define        ASTCHANCONTEXT       12
00141 #define        ASTCHANMACROCONTEXT     13
00142 #define        ASTCHANMACROEXTEN    14
00143 #define        ASTCHANMACROPRI         15
00144 #define        ASTCHANEXTEN         16
00145 #define        ASTCHANPRI           17
00146 #define        ASTCHANACCOUNTCODE      18
00147 #define        ASTCHANFORWARDTO     19
00148 #define        ASTCHANUNIQUEID         20
00149 #define        ASTCHANCALLGROUP     21
00150 #define        ASTCHANPICKUPGROUP      22
00151 #define        ASTCHANSTATE         23
00152 #define        ASTCHANMUTED         24
00153 #define        ASTCHANRINGS         25
00154 #define        ASTCHANCIDDNID       26
00155 #define        ASTCHANCIDNUM        27
00156 #define        ASTCHANCIDNAME       28
00157 #define        ASTCHANCIDANI        29
00158 #define        ASTCHANCIDRDNIS         30
00159 #define        ASTCHANCIDPRES       31
00160 #define        ASTCHANCIDANI2       32
00161 #define        ASTCHANCIDTON        33
00162 #define        ASTCHANCIDTNS        34
00163 #define        ASTCHANAMAFLAGS         35
00164 #define        ASTCHANADSI          36
00165 #define        ASTCHANTONEZONE         37
00166 #define        ASTCHANHANGUPCAUSE      38
00167 #define        ASTCHANVARIABLES     39
00168 #define        ASTCHANFLAGS         40
00169 #define        ASTCHANTRANSFERCAP      41
00170 
00171 #define     ASTCHANTYPECOUNT     3
00172 
00173 #define     ASTCHANTYPETABLE     4
00174 #define        ASTCHANTYPEINDEX     1
00175 #define        ASTCHANTYPENAME         2
00176 #define        ASTCHANTYPEDESC         3
00177 #define        ASTCHANTYPEDEVSTATE     4
00178 #define        ASTCHANTYPEINDICATIONS  5
00179 #define        ASTCHANTYPETRANSFER     6
00180 #define        ASTCHANTYPECHANNELS     7
00181 
00182 #define     ASTCHANSCALARS       5
00183 #define        ASTCHANBRIDGECOUNT      1
00184 
00185 void *agent_thread(void *arg)
00186 {
00187    ast_verb(2, "Starting %sAgent\n", res_snmp_agentx_subagent ? "Sub" : "");
00188 
00189    snmp_enable_stderrlog();
00190 
00191    if (res_snmp_agentx_subagent)
00192       netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID,
00193                         NETSNMP_DS_AGENT_ROLE,
00194                         1);
00195 
00196    init_agent("asterisk");
00197 
00198    init_asterisk_mib();
00199 
00200    init_snmp("asterisk");
00201 
00202    if (!res_snmp_agentx_subagent)
00203       init_master_agent();
00204 
00205    while (res_snmp_dont_stop)
00206       agent_check_and_process(1);
00207 
00208    snmp_shutdown("asterisk");
00209 
00210    ast_verb(2, "Terminating %sAgent\n", res_snmp_agentx_subagent ? "Sub" : "");
00211 
00212    return NULL;
00213 }
00214 
00215 static u_char *
00216 ast_var_channels(struct variable *vp, oid *name, size_t *length,
00217              int exact, size_t *var_len, WriteMethod **write_method)
00218 {
00219    static unsigned long long_ret;
00220 
00221    if (header_generic(vp, name, length, exact, var_len, write_method))
00222       return NULL;
00223 
00224    if (vp->magic != ASTCHANCOUNT)
00225       return NULL;
00226 
00227    long_ret = ast_active_channels();
00228 
00229    return (u_char *)&long_ret;
00230 }
00231 
00232 static u_char *ast_var_channels_table(struct variable *vp, oid *name, size_t *length,
00233                            int exact, size_t *var_len, WriteMethod **write_method)
00234 {
00235    static unsigned long long_ret;
00236    static u_char bits_ret[2];
00237    static char string_ret[256];
00238    struct ast_channel *chan, *bridge;
00239    struct timeval tval;
00240    u_char *ret = NULL;
00241    int i, bit;
00242    struct ast_str *out = ast_str_alloca(2048);
00243    struct ast_channel_iterator *iter;
00244 
00245    if (header_simple_table(vp, name, length, exact, var_len, write_method, ast_active_channels()))
00246       return NULL;
00247 
00248    i = name[*length - 1] - 1;
00249 
00250    if (!(iter = ast_channel_iterator_all_new())) {
00251       return NULL;
00252    }
00253 
00254    while ((chan = ast_channel_iterator_next(iter)) && i) {
00255       ast_channel_unref(chan);
00256       i--;
00257    }
00258 
00259    iter = ast_channel_iterator_destroy(iter);
00260 
00261    if (chan == NULL) {
00262       return NULL;
00263    }
00264 
00265    *var_len = sizeof(long_ret);
00266 
00267    ast_channel_lock(chan);
00268 
00269    switch (vp->magic) {
00270    case ASTCHANINDEX:
00271       long_ret = name[*length - 1];
00272       ret = (u_char *)&long_ret;
00273       break;
00274    case ASTCHANNAME:
00275       if (!ast_strlen_zero(chan->name)) {
00276          strncpy(string_ret, chan->name, sizeof(string_ret));
00277          string_ret[sizeof(string_ret) - 1] = '\0';
00278          *var_len = strlen(string_ret);
00279          ret = (u_char *)string_ret;
00280       }
00281       break;
00282    case ASTCHANLANGUAGE:
00283       if (!ast_strlen_zero(chan->language)) {
00284          strncpy(string_ret, chan->language, sizeof(string_ret));
00285          string_ret[sizeof(string_ret) - 1] = '\0';
00286          *var_len = strlen(string_ret);
00287          ret = (u_char *)string_ret;
00288       }
00289       break;
00290    case ASTCHANTYPE:
00291       strncpy(string_ret, chan->tech->type, sizeof(string_ret));
00292       string_ret[sizeof(string_ret) - 1] = '\0';
00293       *var_len = strlen(string_ret);
00294       ret = (u_char *)string_ret;
00295       break;
00296    case ASTCHANMUSICCLASS:
00297       if (!ast_strlen_zero(chan->musicclass)) {
00298          strncpy(string_ret, chan->musicclass, sizeof(string_ret));
00299          string_ret[sizeof(string_ret) - 1] = '\0';
00300          *var_len = strlen(string_ret);
00301          ret = (u_char *)string_ret;
00302       }
00303       break;
00304    case ASTCHANBRIDGE:
00305       if ((bridge = ast_bridged_channel(chan)) != NULL) {
00306          strncpy(string_ret, bridge->name, sizeof(string_ret));
00307          string_ret[sizeof(string_ret) - 1] = '\0';
00308          *var_len = strlen(string_ret);
00309          ret = (u_char *)string_ret;
00310       }
00311       break;
00312    case ASTCHANMASQ:
00313       if (chan->masq && !ast_strlen_zero(chan->masq->name)) {
00314          strncpy(string_ret, chan->masq->name, sizeof(string_ret));
00315          string_ret[sizeof(string_ret) - 1] = '\0';
00316          *var_len = strlen(string_ret);
00317          ret = (u_char *)string_ret;
00318       }
00319       break;
00320    case ASTCHANMASQR:
00321       if (chan->masqr && !ast_strlen_zero(chan->masqr->name)) {
00322          strncpy(string_ret, chan->masqr->name, sizeof(string_ret));
00323          string_ret[sizeof(string_ret) - 1] = '\0';
00324          *var_len = strlen(string_ret);
00325          ret = (u_char *)string_ret;
00326       }
00327       break;
00328    case ASTCHANWHENHANGUP:
00329       if (!ast_tvzero(chan->whentohangup)) {
00330          gettimeofday(&tval, NULL);
00331          long_ret = difftime(chan->whentohangup.tv_sec, tval.tv_sec) * 100 - tval.tv_usec / 10000;
00332          ret= (u_char *)&long_ret;
00333       }
00334       break;
00335    case ASTCHANAPP:
00336       if (chan->appl) {
00337          strncpy(string_ret, chan->appl, sizeof(string_ret));
00338          string_ret[sizeof(string_ret) - 1] = '\0';
00339          *var_len = strlen(string_ret);
00340          ret = (u_char *)string_ret;
00341       }
00342       break;
00343    case ASTCHANDATA:
00344       if (chan->data) {
00345          strncpy(string_ret, chan->data, sizeof(string_ret));
00346          string_ret[sizeof(string_ret) - 1] = '\0';
00347          *var_len = strlen(string_ret);
00348          ret = (u_char *)string_ret;
00349       }
00350       break;
00351    case ASTCHANCONTEXT:
00352       strncpy(string_ret, chan->context, sizeof(string_ret));
00353       string_ret[sizeof(string_ret) - 1] = '\0';
00354       *var_len = strlen(string_ret);
00355       ret = (u_char *)string_ret;
00356       break;
00357    case ASTCHANMACROCONTEXT:
00358       strncpy(string_ret, chan->macrocontext, sizeof(string_ret));
00359       string_ret[sizeof(string_ret) - 1] = '\0';
00360       *var_len = strlen(string_ret);
00361       ret = (u_char *)string_ret;
00362       break;
00363    case ASTCHANMACROEXTEN:
00364       strncpy(string_ret, chan->macroexten, sizeof(string_ret));
00365       string_ret[sizeof(string_ret) - 1] = '\0';
00366       *var_len = strlen(string_ret);
00367       ret = (u_char *)string_ret;
00368       break;
00369    case ASTCHANMACROPRI:
00370       long_ret = chan->macropriority;
00371       ret = (u_char *)&long_ret;
00372       break;
00373    case ASTCHANEXTEN:
00374       strncpy(string_ret, chan->exten, sizeof(string_ret));
00375       string_ret[sizeof(string_ret) - 1] = '\0';
00376       *var_len = strlen(string_ret);
00377       ret = (u_char *)string_ret;
00378       break;
00379    case ASTCHANPRI:
00380       long_ret = chan->priority;
00381       ret = (u_char *)&long_ret;
00382       break;
00383    case ASTCHANACCOUNTCODE:
00384       if (!ast_strlen_zero(chan->accountcode)) {
00385          strncpy(string_ret, chan->accountcode, sizeof(string_ret));
00386          string_ret[sizeof(string_ret) - 1] = '\0';
00387          *var_len = strlen(string_ret);
00388          ret = (u_char *)string_ret;
00389       }
00390       break;
00391    case ASTCHANFORWARDTO:
00392       if (!ast_strlen_zero(chan->call_forward)) {
00393          strncpy(string_ret, chan->call_forward, sizeof(string_ret));
00394          string_ret[sizeof(string_ret) - 1] = '\0';
00395          *var_len = strlen(string_ret);
00396          ret = (u_char *)string_ret;
00397       }
00398       break;
00399    case ASTCHANUNIQUEID:
00400       strncpy(string_ret, chan->uniqueid, sizeof(string_ret));
00401       string_ret[sizeof(string_ret) - 1] = '\0';
00402       *var_len = strlen(string_ret);
00403       ret = (u_char *)string_ret;
00404       break;
00405    case ASTCHANCALLGROUP:
00406       long_ret = chan->callgroup;
00407       ret = (u_char *)&long_ret;
00408       break;
00409    case ASTCHANPICKUPGROUP:
00410       long_ret = chan->pickupgroup;
00411       ret = (u_char *)&long_ret;
00412       break;
00413    case ASTCHANSTATE:
00414       long_ret = chan->_state & 0xffff;
00415       ret = (u_char *)&long_ret;
00416       break;
00417    case ASTCHANMUTED:
00418       long_ret = chan->_state & AST_STATE_MUTE ? 1 : 2;
00419       ret = (u_char *)&long_ret;
00420       break;
00421    case ASTCHANRINGS:
00422       long_ret = chan->rings;
00423       ret = (u_char *)&long_ret;
00424       break;
00425    case ASTCHANCIDDNID:
00426       if (chan->dialed.number.str) {
00427          strncpy(string_ret, chan->dialed.number.str, sizeof(string_ret));
00428          string_ret[sizeof(string_ret) - 1] = '\0';
00429          *var_len = strlen(string_ret);
00430          ret = (u_char *)string_ret;
00431       }
00432       break;
00433    case ASTCHANCIDNUM:
00434       if (chan->caller.id.number.valid && chan->caller.id.number.str) {
00435          strncpy(string_ret, chan->caller.id.number.str, sizeof(string_ret));
00436          string_ret[sizeof(string_ret) - 1] = '\0';
00437          *var_len = strlen(string_ret);
00438          ret = (u_char *)string_ret;
00439       }
00440       break;
00441    case ASTCHANCIDNAME:
00442       if (chan->caller.id.name.valid && chan->caller.id.name.str) {
00443          strncpy(string_ret, chan->caller.id.name.str, sizeof(string_ret));
00444          string_ret[sizeof(string_ret) - 1] = '\0';
00445          *var_len = strlen(string_ret);
00446          ret = (u_char *)string_ret;
00447       }
00448       break;
00449    case ASTCHANCIDANI:
00450       if (chan->caller.ani.number.valid && chan->caller.ani.number.str) {
00451          strncpy(string_ret, chan->caller.ani.number.str, sizeof(string_ret));
00452          string_ret[sizeof(string_ret) - 1] = '\0';
00453          *var_len = strlen(string_ret);
00454          ret = (u_char *)string_ret;
00455       }
00456       break;
00457    case ASTCHANCIDRDNIS:
00458       if (chan->redirecting.from.number.valid && chan->redirecting.from.number.str) {
00459          strncpy(string_ret, chan->redirecting.from.number.str, sizeof(string_ret));
00460          string_ret[sizeof(string_ret) - 1] = '\0';
00461          *var_len = strlen(string_ret);
00462          ret = (u_char *)string_ret;
00463       }
00464       break;
00465    case ASTCHANCIDPRES:
00466       long_ret = ast_party_id_presentation(&chan->caller.id);
00467       ret = (u_char *)&long_ret;
00468       break;
00469    case ASTCHANCIDANI2:
00470       long_ret = chan->caller.ani2;
00471       ret = (u_char *)&long_ret;
00472       break;
00473    case ASTCHANCIDTON:
00474       long_ret = chan->caller.id.number.plan;
00475       ret = (u_char *)&long_ret;
00476       break;
00477    case ASTCHANCIDTNS:
00478       long_ret = chan->dialed.transit_network_select;
00479       ret = (u_char *)&long_ret;
00480       break;
00481    case ASTCHANAMAFLAGS:
00482       long_ret = chan->amaflags;
00483       ret = (u_char *)&long_ret;
00484       break;
00485    case ASTCHANADSI:
00486       long_ret = chan->adsicpe;
00487       ret = (u_char *)&long_ret;
00488       break;
00489    case ASTCHANTONEZONE:
00490       if (chan->zone) {
00491          strncpy(string_ret, chan->zone->country, sizeof(string_ret));
00492          string_ret[sizeof(string_ret) - 1] = '\0';
00493          *var_len = strlen(string_ret);
00494          ret = (u_char *)string_ret;
00495       }
00496       break;
00497    case ASTCHANHANGUPCAUSE:
00498       long_ret = chan->hangupcause;
00499       ret = (u_char *)&long_ret;
00500       break;
00501    case ASTCHANVARIABLES:
00502       if (pbx_builtin_serialize_variables(chan, &out)) {
00503          *var_len = ast_str_strlen(out);
00504          ret = (u_char *)ast_str_buffer(out);
00505       }
00506       break;
00507    case ASTCHANFLAGS:
00508       bits_ret[0] = 0;
00509       for (bit = 0; bit < 8; bit++)
00510          bits_ret[0] |= ((chan->flags & (1 << bit)) >> bit) << (7 - bit);
00511       bits_ret[1] = 0;
00512       for (bit = 0; bit < 8; bit++)
00513          bits_ret[1] |= (((chan->flags >> 8) & (1 << bit)) >> bit) << (7 - bit);
00514       *var_len = 2;
00515       ret = bits_ret;
00516       break;
00517    case ASTCHANTRANSFERCAP:
00518       long_ret = chan->transfercapability;
00519       ret = (u_char *)&long_ret;
00520    default:
00521       break;
00522    }
00523 
00524    ast_channel_unlock(chan);
00525    chan = ast_channel_unref(chan);
00526 
00527    return ret;
00528 }
00529 
00530 static u_char *ast_var_channel_types(struct variable *vp, oid *name, size_t *length,
00531                            int exact, size_t *var_len, WriteMethod **write_method)
00532 {
00533    static unsigned long long_ret;
00534    struct ast_variable *channel_types, *next;
00535 
00536    if (header_generic(vp, name, length, exact, var_len, write_method))
00537       return NULL;
00538 
00539    if (vp->magic != ASTCHANTYPECOUNT)
00540       return NULL;
00541 
00542    for (long_ret = 0, channel_types = next = ast_channeltype_list(); next; next = next->next)
00543       long_ret++;
00544    ast_variables_destroy(channel_types);
00545 
00546    return (u_char *)&long_ret;
00547 }
00548 
00549 static u_char *ast_var_channel_types_table(struct variable *vp, oid *name, size_t *length,
00550                               int exact, size_t *var_len, WriteMethod **write_method)
00551 {
00552    const struct ast_channel_tech *tech = NULL;
00553    struct ast_variable *channel_types, *next;
00554    static unsigned long long_ret;
00555    struct ast_channel *chan;
00556    u_long i;
00557 
00558    if (header_simple_table(vp, name, length, exact, var_len, write_method, -1))
00559       return NULL;
00560 
00561    channel_types = ast_channeltype_list();
00562    for (i = 1, next = channel_types; next && i != name[*length - 1]; next = next->next, i++)
00563       ;
00564    if (next != NULL)
00565       tech = ast_get_channel_tech(next->name);
00566    ast_variables_destroy(channel_types);
00567    if (next == NULL || tech == NULL)
00568       return NULL;
00569    
00570    switch (vp->magic) {
00571    case ASTCHANTYPEINDEX:
00572       long_ret = name[*length - 1];
00573       return (u_char *)&long_ret;
00574    case ASTCHANTYPENAME:
00575       *var_len = strlen(tech->type);
00576       return (u_char *)tech->type;
00577    case ASTCHANTYPEDESC:
00578       *var_len = strlen(tech->description);
00579       return (u_char *)tech->description;
00580    case ASTCHANTYPEDEVSTATE:
00581       long_ret = tech->devicestate ? 1 : 2;
00582       return (u_char *)&long_ret;
00583    case ASTCHANTYPEINDICATIONS:
00584       long_ret = tech->indicate ? 1 : 2;
00585       return (u_char *)&long_ret;
00586    case ASTCHANTYPETRANSFER:
00587       long_ret = tech->transfer ? 1 : 2;
00588       return (u_char *)&long_ret;
00589    case ASTCHANTYPECHANNELS:
00590    {
00591       struct ast_channel_iterator *iter;
00592 
00593       long_ret = 0;
00594 
00595       if (!(iter = ast_channel_iterator_all_new())) {
00596          return NULL;
00597       }
00598 
00599       while ((chan = ast_channel_iterator_next(iter))) {
00600          if (chan->tech == tech) {
00601             long_ret++;
00602          }
00603          chan = ast_channel_unref(chan);
00604       }
00605 
00606       ast_channel_iterator_destroy(iter);
00607 
00608       return (u_char *)&long_ret;
00609    }
00610    default:
00611       break;
00612    }
00613    return NULL;
00614 }
00615 
00616 static u_char *ast_var_channel_bridge(struct variable *vp, oid *name, size_t *length,
00617    int exact, size_t *var_len, WriteMethod **write_method)
00618 {
00619    static unsigned long long_ret;
00620    struct ast_channel *chan = NULL;
00621    struct ast_channel_iterator *iter;
00622 
00623    long_ret = 0;
00624 
00625    if (header_generic(vp, name, length, exact, var_len, write_method)) {
00626       return NULL;
00627    }
00628 
00629    if (!(iter = ast_channel_iterator_all_new())) {
00630       return NULL;
00631    }
00632 
00633    while ((chan = ast_channel_iterator_next(iter))) {
00634       ast_channel_lock(chan);
00635       if (ast_bridged_channel(chan)) {
00636          long_ret++;
00637       }
00638       ast_channel_unlock(chan);
00639       chan = ast_channel_unref(chan);
00640    }
00641 
00642    ast_channel_iterator_destroy(iter);
00643 
00644    *var_len = sizeof(long_ret);
00645 
00646    return (vp->magic == ASTCHANBRIDGECOUNT) ? (u_char *) &long_ret : NULL;
00647 }
00648 
00649 static u_char *ast_var_Config(struct variable *vp, oid *name, size_t *length,
00650                       int exact, size_t *var_len, WriteMethod **write_method)
00651 {
00652    static unsigned long long_ret;
00653    struct timeval tval;
00654 
00655    if (header_generic(vp, name, length, exact, var_len, write_method))
00656       return NULL;
00657 
00658    switch (vp->magic) {
00659    case ASTCONFUPTIME:
00660       gettimeofday(&tval, NULL);
00661       long_ret = difftime(tval.tv_sec, ast_startuptime.tv_sec) * 100 + tval.tv_usec / 10000 - ast_startuptime.tv_usec / 10000;
00662       return (u_char *)&long_ret;
00663    case ASTCONFRELOADTIME:
00664       gettimeofday(&tval, NULL);
00665       if (ast_lastreloadtime.tv_sec)
00666          long_ret = difftime(tval.tv_sec, ast_lastreloadtime.tv_sec) * 100 + tval.tv_usec / 10000 - ast_lastreloadtime.tv_usec / 10000;
00667       else
00668          long_ret = difftime(tval.tv_sec, ast_startuptime.tv_sec) * 100 + tval.tv_usec / 10000 - ast_startuptime.tv_usec / 10000;
00669       return (u_char *)&long_ret;
00670    case ASTCONFPID:
00671       long_ret = getpid();
00672       return (u_char *)&long_ret;
00673    case ASTCONFSOCKET:
00674       *var_len = strlen(ast_config_AST_SOCKET);
00675       return (u_char *)ast_config_AST_SOCKET;
00676    case ASTCONFACTIVECALLS:
00677       long_ret = ast_active_calls();
00678       return (u_char *)&long_ret;
00679    case ASTCONFPROCESSEDCALLS:
00680       long_ret = ast_processed_calls();
00681       return (u_char *)&long_ret;
00682    default:
00683       break;
00684    }
00685    return NULL;
00686 }
00687 
00688 static u_char *ast_var_indications(struct variable *vp, oid *name, size_t *length,
00689                           int exact, size_t *var_len, WriteMethod **write_method)
00690 {
00691    static unsigned long long_ret;
00692    static char ret_buf[128];
00693    struct ast_tone_zone *tz = NULL;
00694 
00695    if (header_generic(vp, name, length, exact, var_len, write_method))
00696       return NULL;
00697 
00698    switch (vp->magic) {
00699    case ASTINDCOUNT:
00700    {
00701       struct ao2_iterator i;
00702 
00703       long_ret = 0;
00704 
00705       i = ast_tone_zone_iterator_init();
00706       while ((tz = ao2_iterator_next(&i))) {
00707          tz = ast_tone_zone_unref(tz);
00708          long_ret++;
00709       }
00710       ao2_iterator_destroy(&i);
00711 
00712       return (u_char *) &long_ret;
00713    }
00714    case ASTINDCURRENT:
00715       tz = ast_get_indication_zone(NULL);
00716       if (tz) {
00717          ast_copy_string(ret_buf, tz->country, sizeof(ret_buf));
00718          *var_len = strlen(ret_buf);
00719          tz = ast_tone_zone_unref(tz);
00720          return (u_char *) ret_buf;
00721       }
00722       *var_len = 0;
00723       return NULL;
00724    default:
00725       break;
00726    }
00727    return NULL;
00728 }
00729 
00730 static u_char *ast_var_indications_table(struct variable *vp, oid *name, size_t *length,
00731                               int exact, size_t *var_len, WriteMethod **write_method)
00732 {
00733    static unsigned long long_ret;
00734    static char ret_buf[256];
00735    struct ast_tone_zone *tz = NULL;
00736    int i;
00737    struct ao2_iterator iter;
00738 
00739    if (header_simple_table(vp, name, length, exact, var_len, write_method, -1)) {
00740       return NULL;
00741    }
00742 
00743    i = name[*length - 1] - 1;
00744 
00745    iter = ast_tone_zone_iterator_init();
00746 
00747    while ((tz = ao2_iterator_next(&iter)) && i) {
00748       tz = ast_tone_zone_unref(tz);
00749       i--;
00750    }
00751    ao2_iterator_destroy(&iter);
00752 
00753    if (tz == NULL) {
00754       return NULL;
00755    }
00756 
00757    switch (vp->magic) {
00758    case ASTINDINDEX:
00759       ast_tone_zone_unref(tz);
00760       long_ret = name[*length - 1];
00761       return (u_char *)&long_ret;
00762    case ASTINDCOUNTRY:
00763       ast_copy_string(ret_buf, tz->country, sizeof(ret_buf));
00764       ast_tone_zone_unref(tz);
00765       *var_len = strlen(ret_buf);
00766       return (u_char *) ret_buf;
00767    case ASTINDALIAS:
00768       /* No longer exists */
00769       ast_tone_zone_unref(tz);
00770       return NULL;
00771    case ASTINDDESCRIPTION:
00772       ast_tone_zone_lock(tz);
00773       ast_copy_string(ret_buf, tz->description, sizeof(ret_buf));
00774       ast_tone_zone_unlock(tz);
00775       ast_tone_zone_unref(tz);
00776       *var_len = strlen(ret_buf);
00777       return (u_char *) ret_buf;
00778    default:
00779       ast_tone_zone_unref(tz);
00780       break;
00781    }
00782    return NULL;
00783 }
00784 
00785 static int countmodule(const char *mod, const char *desc, int use, const char *like)
00786 {
00787    return 1;
00788 }
00789 
00790 static u_char *ast_var_Modules(struct variable *vp, oid *name, size_t *length,
00791                        int exact, size_t *var_len, WriteMethod **write_method)
00792 {
00793    static unsigned long long_ret;
00794 
00795    if (header_generic(vp, name, length, exact, var_len, write_method))
00796       return NULL;
00797 
00798    if (vp->magic != ASTMODCOUNT)
00799       return NULL;
00800 
00801    long_ret = ast_update_module_list(countmodule, NULL);
00802 
00803    return (u_char *)&long_ret;
00804 }
00805 
00806 static u_char *ast_var_Version(struct variable *vp, oid *name, size_t *length,
00807                        int exact, size_t *var_len, WriteMethod **write_method)
00808 {
00809    static unsigned long long_ret;
00810 
00811    if (header_generic(vp, name, length, exact, var_len, write_method))
00812       return NULL;
00813 
00814    switch (vp->magic) {
00815    case ASTVERSTRING:
00816    {
00817       const char *version = ast_get_version();
00818       *var_len = strlen(version);
00819       return (u_char *)version;
00820    }
00821    case ASTVERTAG:
00822       sscanf(ast_get_version_num(), "%30lu", &long_ret);
00823       return (u_char *)&long_ret;
00824    default:
00825       break;
00826    }
00827    return NULL;
00828 }
00829 
00830 static int term_asterisk_mib(int majorID, int minorID, void *serverarg, void *clientarg)
00831 {
00832    unregister_sysORTable(asterisk_oid, OID_LENGTH(asterisk_oid));
00833    return 0;
00834 }
00835 
00836 static void init_asterisk_mib(void)
00837 {
00838    static struct variable4 asterisk_vars[] = {
00839       {ASTVERSTRING,           ASN_OCTET_STR, RONLY, ast_var_Version,             2, {ASTVERSION, ASTVERSTRING}},
00840       {ASTVERTAG,              ASN_UNSIGNED,  RONLY, ast_var_Version,             2, {ASTVERSION, ASTVERTAG}},
00841       {ASTCONFUPTIME,          ASN_TIMETICKS, RONLY, ast_var_Config,              2, {ASTCONFIGURATION, ASTCONFUPTIME}},
00842       {ASTCONFRELOADTIME,      ASN_TIMETICKS, RONLY, ast_var_Config,              2, {ASTCONFIGURATION, ASTCONFRELOADTIME}},
00843       {ASTCONFPID,             ASN_INTEGER,   RONLY, ast_var_Config,              2, {ASTCONFIGURATION, ASTCONFPID}},
00844       {ASTCONFSOCKET,          ASN_OCTET_STR, RONLY, ast_var_Config,              2, {ASTCONFIGURATION, ASTCONFSOCKET}},
00845       {ASTCONFACTIVECALLS,     ASN_GAUGE,    RONLY, ast_var_Config,              2, {ASTCONFIGURATION, ASTCONFACTIVECALLS}},
00846       {ASTCONFPROCESSEDCALLS,  ASN_COUNTER,   RONLY, ast_var_Config,              2, {ASTCONFIGURATION, ASTCONFPROCESSEDCALLS}},
00847       {ASTMODCOUNT,            ASN_INTEGER,   RONLY, ast_var_Modules ,            2, {ASTMODULES, ASTMODCOUNT}},
00848       {ASTINDCOUNT,            ASN_INTEGER,   RONLY, ast_var_indications,         2, {ASTINDICATIONS, ASTINDCOUNT}},
00849       {ASTINDCURRENT,          ASN_OCTET_STR, RONLY, ast_var_indications,         2, {ASTINDICATIONS, ASTINDCURRENT}},
00850       {ASTINDINDEX,            ASN_INTEGER,   RONLY, ast_var_indications_table,   4, {ASTINDICATIONS, ASTINDTABLE, 1, ASTINDINDEX}},
00851       {ASTINDCOUNTRY,          ASN_OCTET_STR, RONLY, ast_var_indications_table,   4, {ASTINDICATIONS, ASTINDTABLE, 1, ASTINDCOUNTRY}},
00852       {ASTINDALIAS,            ASN_OCTET_STR, RONLY, ast_var_indications_table,   4, {ASTINDICATIONS, ASTINDTABLE, 1, ASTINDALIAS}},
00853       {ASTINDDESCRIPTION,      ASN_OCTET_STR, RONLY, ast_var_indications_table,   4, {ASTINDICATIONS, ASTINDTABLE, 1, ASTINDDESCRIPTION}},
00854       {ASTCHANCOUNT,           ASN_GAUGE,     RONLY, ast_var_channels,            2, {ASTCHANNELS, ASTCHANCOUNT}},
00855       {ASTCHANINDEX,           ASN_INTEGER,   RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANINDEX}},
00856       {ASTCHANNAME,            ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANNAME}},
00857       {ASTCHANLANGUAGE,        ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANLANGUAGE}},
00858       {ASTCHANTYPE,            ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANTYPE}},
00859       {ASTCHANMUSICCLASS,      ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANMUSICCLASS}},
00860       {ASTCHANBRIDGE,          ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANBRIDGE}},
00861       {ASTCHANMASQ,            ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANMASQ}},
00862       {ASTCHANMASQR,           ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANMASQR}},
00863       {ASTCHANWHENHANGUP,      ASN_TIMETICKS, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANWHENHANGUP}},
00864       {ASTCHANAPP,             ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANAPP}},
00865       {ASTCHANDATA,            ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANDATA}},
00866       {ASTCHANCONTEXT,         ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCONTEXT}},
00867       {ASTCHANMACROCONTEXT,    ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANMACROCONTEXT}},
00868       {ASTCHANMACROEXTEN,      ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANMACROEXTEN}},
00869       {ASTCHANMACROPRI,        ASN_INTEGER,   RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANMACROPRI}},
00870       {ASTCHANEXTEN,           ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANEXTEN}},
00871       {ASTCHANPRI,             ASN_INTEGER,   RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANPRI}},
00872       {ASTCHANACCOUNTCODE,     ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANACCOUNTCODE}},
00873       {ASTCHANFORWARDTO,       ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANFORWARDTO}},
00874       {ASTCHANUNIQUEID,        ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANUNIQUEID}},
00875       {ASTCHANCALLGROUP,       ASN_UNSIGNED,  RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCALLGROUP}},
00876       {ASTCHANPICKUPGROUP,     ASN_UNSIGNED,  RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANPICKUPGROUP}},
00877       {ASTCHANSTATE,           ASN_INTEGER,   RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANSTATE}},
00878       {ASTCHANMUTED,           ASN_INTEGER,   RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANMUTED}},
00879       {ASTCHANRINGS,           ASN_INTEGER,   RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANRINGS}},
00880       {ASTCHANCIDDNID,         ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDDNID}},
00881       {ASTCHANCIDNUM,          ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDNUM}},
00882       {ASTCHANCIDNAME,         ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDNAME}},
00883       {ASTCHANCIDANI,          ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDANI}},
00884       {ASTCHANCIDRDNIS,        ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDRDNIS}},
00885       {ASTCHANCIDPRES,         ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDPRES}},
00886       {ASTCHANCIDANI2,         ASN_INTEGER,   RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDANI2}},
00887       {ASTCHANCIDTON,          ASN_INTEGER,   RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDTON}},
00888       {ASTCHANCIDTNS,          ASN_INTEGER,   RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDTNS}},
00889       {ASTCHANAMAFLAGS,        ASN_INTEGER,   RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANAMAFLAGS}},
00890       {ASTCHANADSI,            ASN_INTEGER,   RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANADSI}},
00891       {ASTCHANTONEZONE,        ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANTONEZONE}},
00892       {ASTCHANHANGUPCAUSE,     ASN_INTEGER,   RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANHANGUPCAUSE}},
00893       {ASTCHANVARIABLES,       ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANVARIABLES}},
00894       {ASTCHANFLAGS,           ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANFLAGS}},
00895       {ASTCHANTRANSFERCAP,     ASN_INTEGER,   RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANTRANSFERCAP}},
00896       {ASTCHANTYPECOUNT,       ASN_INTEGER,   RONLY, ast_var_channel_types,       2, {ASTCHANNELS, ASTCHANTYPECOUNT}},
00897       {ASTCHANTYPEINDEX,       ASN_INTEGER,   RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPEINDEX}},
00898       {ASTCHANTYPENAME,        ASN_OCTET_STR, RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPENAME}},
00899       {ASTCHANTYPEDESC,        ASN_OCTET_STR, RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPEDESC}},
00900       {ASTCHANTYPEDEVSTATE,    ASN_INTEGER,   RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPEDEVSTATE}},
00901       {ASTCHANTYPEINDICATIONS, ASN_INTEGER,   RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPEINDICATIONS}},
00902       {ASTCHANTYPETRANSFER,    ASN_INTEGER,   RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPETRANSFER}},
00903       {ASTCHANTYPECHANNELS,    ASN_GAUGE,     RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPECHANNELS}},
00904       {ASTCHANBRIDGECOUNT,     ASN_GAUGE,     RONLY, ast_var_channel_bridge,      3, {ASTCHANNELS, ASTCHANSCALARS, ASTCHANBRIDGECOUNT}},
00905    };
00906 
00907    register_sysORTable(asterisk_oid, OID_LENGTH(asterisk_oid),
00908          "ASTERISK-MIB implementation for Asterisk.");
00909 
00910    REGISTER_MIB("res_snmp", asterisk_vars, variable4, asterisk_oid);
00911 
00912    snmp_register_callback(SNMP_CALLBACK_LIBRARY,
00913             SNMP_CALLBACK_SHUTDOWN,
00914             term_asterisk_mib, NULL);
00915 }
00916 
00917 /*
00918  * Local Variables:
00919  * c-basic-offset: 4
00920  * c-file-offsets: ((case-label . 0))
00921  * tab-width: 4
00922  * indent-tabs-mode: t
00923  * End:
00924  */

Generated on Mon Oct 8 12:38:55 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7