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

Generated on Sat Mar 10 01:53:55 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7