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: 430819 $")
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(ast_channel_name(chan))) {
00276          ast_copy_string(string_ret, ast_channel_name(chan), sizeof(string_ret));
00277          *var_len = strlen(string_ret);
00278          ret = (u_char *)string_ret;
00279       }
00280       break;
00281    case ASTCHANLANGUAGE:
00282       if (!ast_strlen_zero(ast_channel_language(chan))) {
00283          ast_copy_string(string_ret, ast_channel_language(chan), sizeof(string_ret));
00284          *var_len = strlen(string_ret);
00285          ret = (u_char *)string_ret;
00286       }
00287       break;
00288    case ASTCHANTYPE:
00289       ast_copy_string(string_ret, ast_channel_tech(chan)->type, sizeof(string_ret));
00290       *var_len = strlen(string_ret);
00291       ret = (u_char *)string_ret;
00292       break;
00293    case ASTCHANMUSICCLASS:
00294       if (!ast_strlen_zero(ast_channel_musicclass(chan))) {
00295          ast_copy_string(string_ret, ast_channel_musicclass(chan), sizeof(string_ret));
00296          *var_len = strlen(string_ret);
00297          ret = (u_char *)string_ret;
00298       }
00299       break;
00300    case ASTCHANBRIDGE:
00301       ast_channel_unlock(chan);
00302       bridge = ast_channel_bridge_peer(chan);
00303       if (bridge) {
00304          ast_channel_lock(bridge);
00305          ast_copy_string(string_ret, ast_channel_name(bridge), sizeof(string_ret));
00306          ast_channel_unlock(bridge);
00307          ast_channel_unref(bridge);
00308 
00309          *var_len = strlen(string_ret);
00310          ret = (u_char *)string_ret;
00311       }
00312       ast_channel_lock(chan);
00313       break;
00314    case ASTCHANMASQ:
00315       if (ast_channel_masq(chan) && !ast_strlen_zero(ast_channel_name(ast_channel_masq(chan)))) {
00316          ast_copy_string(string_ret, ast_channel_name(ast_channel_masq(chan)), sizeof(string_ret));
00317          *var_len = strlen(string_ret);
00318          ret = (u_char *)string_ret;
00319       }
00320       break;
00321    case ASTCHANMASQR:
00322       if (ast_channel_masqr(chan) && !ast_strlen_zero(ast_channel_name(ast_channel_masqr(chan)))) {
00323          ast_copy_string(string_ret, ast_channel_name(ast_channel_masqr(chan)), sizeof(string_ret));
00324          *var_len = strlen(string_ret);
00325          ret = (u_char *)string_ret;
00326       }
00327       break;
00328    case ASTCHANWHENHANGUP:
00329       if (!ast_tvzero(*ast_channel_whentohangup(chan))) {
00330          gettimeofday(&tval, NULL);
00331          long_ret = difftime(ast_channel_whentohangup(chan)->tv_sec, tval.tv_sec) * 100 - tval.tv_usec / 10000;
00332          ret= (u_char *)&long_ret;
00333       }
00334       break;
00335    case ASTCHANAPP:
00336       if (ast_channel_appl(chan)) {
00337          ast_copy_string(string_ret, ast_channel_appl(chan), sizeof(string_ret));
00338          *var_len = strlen(string_ret);
00339          ret = (u_char *)string_ret;
00340       }
00341       break;
00342    case ASTCHANDATA:
00343       if (ast_channel_data(chan)) {
00344          ast_copy_string(string_ret, ast_channel_data(chan), sizeof(string_ret));
00345          *var_len = strlen(string_ret);
00346          ret = (u_char *)string_ret;
00347       }
00348       break;
00349    case ASTCHANCONTEXT:
00350       ast_copy_string(string_ret, ast_channel_context(chan), sizeof(string_ret));
00351       *var_len = strlen(string_ret);
00352       ret = (u_char *)string_ret;
00353       break;
00354    case ASTCHANMACROCONTEXT:
00355       ast_copy_string(string_ret, ast_channel_macrocontext(chan), sizeof(string_ret));
00356       *var_len = strlen(string_ret);
00357       ret = (u_char *)string_ret;
00358       break;
00359    case ASTCHANMACROEXTEN:
00360       ast_copy_string(string_ret, ast_channel_macroexten(chan), sizeof(string_ret));
00361       *var_len = strlen(string_ret);
00362       ret = (u_char *)string_ret;
00363       break;
00364    case ASTCHANMACROPRI:
00365       long_ret = ast_channel_macropriority(chan);
00366       ret = (u_char *)&long_ret;
00367       break;
00368    case ASTCHANEXTEN:
00369       ast_copy_string(string_ret, ast_channel_exten(chan), sizeof(string_ret));
00370       *var_len = strlen(string_ret);
00371       ret = (u_char *)string_ret;
00372       break;
00373    case ASTCHANPRI:
00374       long_ret = ast_channel_priority(chan);
00375       ret = (u_char *)&long_ret;
00376       break;
00377    case ASTCHANACCOUNTCODE:
00378       if (!ast_strlen_zero(ast_channel_accountcode(chan))) {
00379          ast_copy_string(string_ret, ast_channel_accountcode(chan), sizeof(string_ret));
00380          *var_len = strlen(string_ret);
00381          ret = (u_char *)string_ret;
00382       }
00383       break;
00384    case ASTCHANFORWARDTO:
00385       if (!ast_strlen_zero(ast_channel_call_forward(chan))) {
00386          ast_copy_string(string_ret, ast_channel_call_forward(chan), sizeof(string_ret));
00387          *var_len = strlen(string_ret);
00388          ret = (u_char *)string_ret;
00389       }
00390       break;
00391    case ASTCHANUNIQUEID:
00392       ast_copy_string(string_ret, ast_channel_uniqueid(chan), sizeof(string_ret));
00393       *var_len = strlen(string_ret);
00394       ret = (u_char *)string_ret;
00395       break;
00396    case ASTCHANCALLGROUP:
00397       long_ret = ast_channel_callgroup(chan);
00398       ret = (u_char *)&long_ret;
00399       break;
00400    case ASTCHANPICKUPGROUP:
00401       long_ret = ast_channel_pickupgroup(chan);
00402       ret = (u_char *)&long_ret;
00403       break;
00404    case ASTCHANSTATE:
00405       long_ret = ast_channel_state(chan) & 0xffff;
00406       ret = (u_char *)&long_ret;
00407       break;
00408    case ASTCHANMUTED:
00409       long_ret = ast_channel_state(chan) & AST_STATE_MUTE ? 1 : 2;
00410       ret = (u_char *)&long_ret;
00411       break;
00412    case ASTCHANRINGS:
00413       long_ret = ast_channel_rings(chan);
00414       ret = (u_char *)&long_ret;
00415       break;
00416    case ASTCHANCIDDNID:
00417       if (ast_channel_dialed(chan)->number.str) {
00418          ast_copy_string(string_ret, ast_channel_dialed(chan)->number.str, sizeof(string_ret));
00419          *var_len = strlen(string_ret);
00420          ret = (u_char *)string_ret;
00421       }
00422       break;
00423    case ASTCHANCIDNUM:
00424       if (ast_channel_caller(chan)->id.number.valid && ast_channel_caller(chan)->id.number.str) {
00425          ast_copy_string(string_ret, ast_channel_caller(chan)->id.number.str, sizeof(string_ret));
00426          *var_len = strlen(string_ret);
00427          ret = (u_char *)string_ret;
00428       }
00429       break;
00430    case ASTCHANCIDNAME:
00431       if (ast_channel_caller(chan)->id.name.valid && ast_channel_caller(chan)->id.name.str) {
00432          ast_copy_string(string_ret, ast_channel_caller(chan)->id.name.str, sizeof(string_ret));
00433          *var_len = strlen(string_ret);
00434          ret = (u_char *)string_ret;
00435       }
00436       break;
00437    case ASTCHANCIDANI:
00438       if (ast_channel_caller(chan)->ani.number.valid && ast_channel_caller(chan)->ani.number.str) {
00439          ast_copy_string(string_ret, ast_channel_caller(chan)->ani.number.str, sizeof(string_ret));
00440          *var_len = strlen(string_ret);
00441          ret = (u_char *)string_ret;
00442       }
00443       break;
00444    case ASTCHANCIDRDNIS:
00445       if (ast_channel_redirecting(chan)->from.number.valid && ast_channel_redirecting(chan)->from.number.str) {
00446          ast_copy_string(string_ret, ast_channel_redirecting(chan)->from.number.str, sizeof(string_ret));
00447          *var_len = strlen(string_ret);
00448          ret = (u_char *)string_ret;
00449       }
00450       break;
00451    case ASTCHANCIDPRES:
00452       long_ret = ast_party_id_presentation(&ast_channel_caller(chan)->id);
00453       ret = (u_char *)&long_ret;
00454       break;
00455    case ASTCHANCIDANI2:
00456       long_ret = ast_channel_caller(chan)->ani2;
00457       ret = (u_char *)&long_ret;
00458       break;
00459    case ASTCHANCIDTON:
00460       long_ret = ast_channel_caller(chan)->id.number.plan;
00461       ret = (u_char *)&long_ret;
00462       break;
00463    case ASTCHANCIDTNS:
00464       long_ret = ast_channel_dialed(chan)->transit_network_select;
00465       ret = (u_char *)&long_ret;
00466       break;
00467    case ASTCHANAMAFLAGS:
00468       long_ret = ast_channel_amaflags(chan);
00469       ret = (u_char *)&long_ret;
00470       break;
00471    case ASTCHANADSI:
00472       long_ret = ast_channel_adsicpe(chan);
00473       ret = (u_char *)&long_ret;
00474       break;
00475    case ASTCHANTONEZONE:
00476       if (ast_channel_zone(chan)) {
00477          ast_copy_string(string_ret, ast_channel_zone(chan)->country, sizeof(string_ret));
00478          *var_len = strlen(string_ret);
00479          ret = (u_char *)string_ret;
00480       }
00481       break;
00482    case ASTCHANHANGUPCAUSE:
00483       long_ret = ast_channel_hangupcause(chan);
00484       ret = (u_char *)&long_ret;
00485       break;
00486    case ASTCHANVARIABLES:
00487       if (pbx_builtin_serialize_variables(chan, &out)) {
00488          *var_len = ast_str_strlen(out);
00489          ret = (u_char *)ast_str_buffer(out);
00490       }
00491       break;
00492    case ASTCHANFLAGS:
00493       bits_ret[0] = 0;
00494       for (bit = 0; bit < 8; bit++)
00495          bits_ret[0] |= ((ast_channel_flags(chan)->flags & (1 << bit)) >> bit) << (7 - bit);
00496       bits_ret[1] = 0;
00497       for (bit = 0; bit < 8; bit++)
00498          bits_ret[1] |= (((ast_channel_flags(chan)->flags >> 8) & (1 << bit)) >> bit) << (7 - bit);
00499       *var_len = 2;
00500       ret = bits_ret;
00501       break;
00502    case ASTCHANTRANSFERCAP:
00503       long_ret = ast_channel_transfercapability(chan);
00504       ret = (u_char *)&long_ret;
00505    default:
00506       break;
00507    }
00508 
00509    ast_channel_unlock(chan);
00510    chan = ast_channel_unref(chan);
00511 
00512    return ret;
00513 }
00514 
00515 static u_char *ast_var_channel_types(struct variable *vp, oid *name, size_t *length,
00516                            int exact, size_t *var_len, WriteMethod **write_method)
00517 {
00518    static unsigned long long_ret;
00519    struct ast_variable *channel_types, *next;
00520 
00521    if (header_generic(vp, name, length, exact, var_len, write_method))
00522       return NULL;
00523 
00524    if (vp->magic != ASTCHANTYPECOUNT)
00525       return NULL;
00526 
00527    for (long_ret = 0, channel_types = next = ast_channeltype_list(); next; next = next->next)
00528       long_ret++;
00529    ast_variables_destroy(channel_types);
00530 
00531    return (u_char *)&long_ret;
00532 }
00533 
00534 static u_char *ast_var_channel_types_table(struct variable *vp, oid *name, size_t *length,
00535                               int exact, size_t *var_len, WriteMethod **write_method)
00536 {
00537    const struct ast_channel_tech *tech = NULL;
00538    struct ast_variable *channel_types, *next;
00539    static unsigned long long_ret;
00540    struct ast_channel *chan;
00541    u_long i;
00542 
00543    if (header_simple_table(vp, name, length, exact, var_len, write_method, -1))
00544       return NULL;
00545 
00546    channel_types = ast_channeltype_list();
00547    for (i = 1, next = channel_types; next && i != name[*length - 1]; next = next->next, i++)
00548       ;
00549    if (next != NULL)
00550       tech = ast_get_channel_tech(next->name);
00551    ast_variables_destroy(channel_types);
00552    if (next == NULL || tech == NULL)
00553       return NULL;
00554    
00555    switch (vp->magic) {
00556    case ASTCHANTYPEINDEX:
00557       long_ret = name[*length - 1];
00558       return (u_char *)&long_ret;
00559    case ASTCHANTYPENAME:
00560       *var_len = strlen(tech->type);
00561       return (u_char *)tech->type;
00562    case ASTCHANTYPEDESC:
00563       *var_len = strlen(tech->description);
00564       return (u_char *)tech->description;
00565    case ASTCHANTYPEDEVSTATE:
00566       long_ret = tech->devicestate ? 1 : 2;
00567       return (u_char *)&long_ret;
00568    case ASTCHANTYPEINDICATIONS:
00569       long_ret = tech->indicate ? 1 : 2;
00570       return (u_char *)&long_ret;
00571    case ASTCHANTYPETRANSFER:
00572       long_ret = tech->transfer ? 1 : 2;
00573       return (u_char *)&long_ret;
00574    case ASTCHANTYPECHANNELS:
00575    {
00576       struct ast_channel_iterator *iter;
00577 
00578       long_ret = 0;
00579 
00580       if (!(iter = ast_channel_iterator_all_new())) {
00581          return NULL;
00582       }
00583 
00584       while ((chan = ast_channel_iterator_next(iter))) {
00585          if (ast_channel_tech(chan) == tech) {
00586             long_ret++;
00587          }
00588          chan = ast_channel_unref(chan);
00589       }
00590 
00591       ast_channel_iterator_destroy(iter);
00592 
00593       return (u_char *)&long_ret;
00594    }
00595    default:
00596       break;
00597    }
00598    return NULL;
00599 }
00600 
00601 static u_char *ast_var_channel_bridge(struct variable *vp, oid *name, size_t *length,
00602    int exact, size_t *var_len, WriteMethod **write_method)
00603 {
00604    static unsigned long long_ret;
00605    struct ast_channel *chan = NULL;
00606    struct ast_channel_iterator *iter;
00607 
00608    long_ret = 0;
00609 
00610    if (header_generic(vp, name, length, exact, var_len, write_method)) {
00611       return NULL;
00612    }
00613 
00614    if (!(iter = ast_channel_iterator_all_new())) {
00615       return NULL;
00616    }
00617 
00618    while ((chan = ast_channel_iterator_next(iter))) {
00619       ast_channel_lock(chan);
00620       if (ast_channel_is_bridged(chan)) {
00621          long_ret++;
00622       }
00623       ast_channel_unlock(chan);
00624       chan = ast_channel_unref(chan);
00625    }
00626 
00627    ast_channel_iterator_destroy(iter);
00628 
00629    *var_len = sizeof(long_ret);
00630 
00631    return (vp->magic == ASTCHANBRIDGECOUNT) ? (u_char *) &long_ret : NULL;
00632 }
00633 
00634 static u_char *ast_var_Config(struct variable *vp, oid *name, size_t *length,
00635                       int exact, size_t *var_len, WriteMethod **write_method)
00636 {
00637    static unsigned long long_ret;
00638    struct timeval tval;
00639 
00640    if (header_generic(vp, name, length, exact, var_len, write_method))
00641       return NULL;
00642 
00643    switch (vp->magic) {
00644    case ASTCONFUPTIME:
00645       gettimeofday(&tval, NULL);
00646       long_ret = difftime(tval.tv_sec, ast_startuptime.tv_sec) * 100 + tval.tv_usec / 10000 - ast_startuptime.tv_usec / 10000;
00647       return (u_char *)&long_ret;
00648    case ASTCONFRELOADTIME:
00649       gettimeofday(&tval, NULL);
00650       if (ast_lastreloadtime.tv_sec)
00651          long_ret = difftime(tval.tv_sec, ast_lastreloadtime.tv_sec) * 100 + tval.tv_usec / 10000 - ast_lastreloadtime.tv_usec / 10000;
00652       else
00653          long_ret = difftime(tval.tv_sec, ast_startuptime.tv_sec) * 100 + tval.tv_usec / 10000 - ast_startuptime.tv_usec / 10000;
00654       return (u_char *)&long_ret;
00655    case ASTCONFPID:
00656       long_ret = getpid();
00657       return (u_char *)&long_ret;
00658    case ASTCONFSOCKET:
00659       *var_len = strlen(ast_config_AST_SOCKET);
00660       return (u_char *)ast_config_AST_SOCKET;
00661    case ASTCONFACTIVECALLS:
00662       long_ret = ast_active_calls();
00663       return (u_char *)&long_ret;
00664    case ASTCONFPROCESSEDCALLS:
00665       long_ret = ast_processed_calls();
00666       return (u_char *)&long_ret;
00667    default:
00668       break;
00669    }
00670    return NULL;
00671 }
00672 
00673 static u_char *ast_var_indications(struct variable *vp, oid *name, size_t *length,
00674                           int exact, size_t *var_len, WriteMethod **write_method)
00675 {
00676    static unsigned long long_ret;
00677    static char ret_buf[128];
00678    struct ast_tone_zone *tz = NULL;
00679 
00680    if (header_generic(vp, name, length, exact, var_len, write_method))
00681       return NULL;
00682 
00683    switch (vp->magic) {
00684    case ASTINDCOUNT:
00685    {
00686       struct ao2_iterator i;
00687 
00688       long_ret = 0;
00689 
00690       i = ast_tone_zone_iterator_init();
00691       while ((tz = ao2_iterator_next(&i))) {
00692          tz = ast_tone_zone_unref(tz);
00693          long_ret++;
00694       }
00695       ao2_iterator_destroy(&i);
00696 
00697       return (u_char *) &long_ret;
00698    }
00699    case ASTINDCURRENT:
00700       tz = ast_get_indication_zone(NULL);
00701       if (tz) {
00702          ast_copy_string(ret_buf, tz->country, sizeof(ret_buf));
00703          *var_len = strlen(ret_buf);
00704          tz = ast_tone_zone_unref(tz);
00705          return (u_char *) ret_buf;
00706       }
00707       *var_len = 0;
00708       return NULL;
00709    default:
00710       break;
00711    }
00712    return NULL;
00713 }
00714 
00715 static u_char *ast_var_indications_table(struct variable *vp, oid *name, size_t *length,
00716                               int exact, size_t *var_len, WriteMethod **write_method)
00717 {
00718    static unsigned long long_ret;
00719    static char ret_buf[256];
00720    struct ast_tone_zone *tz = NULL;
00721    int i;
00722    struct ao2_iterator iter;
00723 
00724    if (header_simple_table(vp, name, length, exact, var_len, write_method, -1)) {
00725       return NULL;
00726    }
00727 
00728    i = name[*length - 1] - 1;
00729 
00730    iter = ast_tone_zone_iterator_init();
00731 
00732    while ((tz = ao2_iterator_next(&iter)) && i) {
00733       tz = ast_tone_zone_unref(tz);
00734       i--;
00735    }
00736    ao2_iterator_destroy(&iter);
00737 
00738    if (tz == NULL) {
00739       return NULL;
00740    }
00741 
00742    switch (vp->magic) {
00743    case ASTINDINDEX:
00744       ast_tone_zone_unref(tz);
00745       long_ret = name[*length - 1];
00746       return (u_char *)&long_ret;
00747    case ASTINDCOUNTRY:
00748       ast_copy_string(ret_buf, tz->country, sizeof(ret_buf));
00749       ast_tone_zone_unref(tz);
00750       *var_len = strlen(ret_buf);
00751       return (u_char *) ret_buf;
00752    case ASTINDALIAS:
00753       /* No longer exists */
00754       ast_tone_zone_unref(tz);
00755       return NULL;
00756    case ASTINDDESCRIPTION:
00757       ast_tone_zone_lock(tz);
00758       ast_copy_string(ret_buf, tz->description, sizeof(ret_buf));
00759       ast_tone_zone_unlock(tz);
00760       ast_tone_zone_unref(tz);
00761       *var_len = strlen(ret_buf);
00762       return (u_char *) ret_buf;
00763    default:
00764       ast_tone_zone_unref(tz);
00765       break;
00766    }
00767    return NULL;
00768 }
00769 
00770 static int countmodule(const char *mod, const char *desc, int use, const char *status,
00771       const char *like, enum ast_module_support_level support_level)
00772 {
00773    return 1;
00774 }
00775 
00776 static u_char *ast_var_Modules(struct variable *vp, oid *name, size_t *length,
00777                        int exact, size_t *var_len, WriteMethod **write_method)
00778 {
00779    static unsigned long long_ret;
00780 
00781    if (header_generic(vp, name, length, exact, var_len, write_method))
00782       return NULL;
00783 
00784    if (vp->magic != ASTMODCOUNT)
00785       return NULL;
00786 
00787    long_ret = ast_update_module_list(countmodule, NULL);
00788 
00789    return (u_char *)&long_ret;
00790 }
00791 
00792 static u_char *ast_var_Version(struct variable *vp, oid *name, size_t *length,
00793                        int exact, size_t *var_len, WriteMethod **write_method)
00794 {
00795    static unsigned long long_ret;
00796 
00797    if (header_generic(vp, name, length, exact, var_len, write_method))
00798       return NULL;
00799 
00800    switch (vp->magic) {
00801    case ASTVERSTRING:
00802    {
00803       const char *version = ast_get_version();
00804       *var_len = strlen(version);
00805       return (u_char *)version;
00806    }
00807    case ASTVERTAG:
00808       sscanf(ast_get_version_num(), "%30lu", &long_ret);
00809       return (u_char *)&long_ret;
00810    default:
00811       break;
00812    }
00813    return NULL;
00814 }
00815 
00816 static int term_asterisk_mib(int majorID, int minorID, void *serverarg, void *clientarg)
00817 {
00818    unregister_sysORTable(asterisk_oid, OID_LENGTH(asterisk_oid));
00819    return 0;
00820 }
00821 
00822 static void init_asterisk_mib(void)
00823 {
00824    static struct variable4 asterisk_vars[] = {
00825       {ASTVERSTRING,           ASN_OCTET_STR, RONLY, ast_var_Version,             2, {ASTVERSION, ASTVERSTRING}},
00826       {ASTVERTAG,              ASN_UNSIGNED,  RONLY, ast_var_Version,             2, {ASTVERSION, ASTVERTAG}},
00827       {ASTCONFUPTIME,          ASN_TIMETICKS, RONLY, ast_var_Config,              2, {ASTCONFIGURATION, ASTCONFUPTIME}},
00828       {ASTCONFRELOADTIME,      ASN_TIMETICKS, RONLY, ast_var_Config,              2, {ASTCONFIGURATION, ASTCONFRELOADTIME}},
00829       {ASTCONFPID,             ASN_INTEGER,   RONLY, ast_var_Config,              2, {ASTCONFIGURATION, ASTCONFPID}},
00830       {ASTCONFSOCKET,          ASN_OCTET_STR, RONLY, ast_var_Config,              2, {ASTCONFIGURATION, ASTCONFSOCKET}},
00831       {ASTCONFACTIVECALLS,     ASN_GAUGE,    RONLY, ast_var_Config,              2, {ASTCONFIGURATION, ASTCONFACTIVECALLS}},
00832       {ASTCONFPROCESSEDCALLS,  ASN_COUNTER,   RONLY, ast_var_Config,              2, {ASTCONFIGURATION, ASTCONFPROCESSEDCALLS}},
00833       {ASTMODCOUNT,            ASN_INTEGER,   RONLY, ast_var_Modules ,            2, {ASTMODULES, ASTMODCOUNT}},
00834       {ASTINDCOUNT,            ASN_INTEGER,   RONLY, ast_var_indications,         2, {ASTINDICATIONS, ASTINDCOUNT}},
00835       {ASTINDCURRENT,          ASN_OCTET_STR, RONLY, ast_var_indications,         2, {ASTINDICATIONS, ASTINDCURRENT}},
00836       {ASTINDINDEX,            ASN_INTEGER,   RONLY, ast_var_indications_table,   4, {ASTINDICATIONS, ASTINDTABLE, 1, ASTINDINDEX}},
00837       {ASTINDCOUNTRY,          ASN_OCTET_STR, RONLY, ast_var_indications_table,   4, {ASTINDICATIONS, ASTINDTABLE, 1, ASTINDCOUNTRY}},
00838       {ASTINDALIAS,            ASN_OCTET_STR, RONLY, ast_var_indications_table,   4, {ASTINDICATIONS, ASTINDTABLE, 1, ASTINDALIAS}},
00839       {ASTINDDESCRIPTION,      ASN_OCTET_STR, RONLY, ast_var_indications_table,   4, {ASTINDICATIONS, ASTINDTABLE, 1, ASTINDDESCRIPTION}},
00840       {ASTCHANCOUNT,           ASN_GAUGE,     RONLY, ast_var_channels,            2, {ASTCHANNELS, ASTCHANCOUNT}},
00841       {ASTCHANINDEX,           ASN_INTEGER,   RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANINDEX}},
00842       {ASTCHANNAME,            ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANNAME}},
00843       {ASTCHANLANGUAGE,        ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANLANGUAGE}},
00844       {ASTCHANTYPE,            ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANTYPE}},
00845       {ASTCHANMUSICCLASS,      ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANMUSICCLASS}},
00846       {ASTCHANBRIDGE,          ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANBRIDGE}},
00847       {ASTCHANMASQ,            ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANMASQ}},
00848       {ASTCHANMASQR,           ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANMASQR}},
00849       {ASTCHANWHENHANGUP,      ASN_TIMETICKS, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANWHENHANGUP}},
00850       {ASTCHANAPP,             ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANAPP}},
00851       {ASTCHANDATA,            ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANDATA}},
00852       {ASTCHANCONTEXT,         ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCONTEXT}},
00853       {ASTCHANMACROCONTEXT,    ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANMACROCONTEXT}},
00854       {ASTCHANMACROEXTEN,      ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANMACROEXTEN}},
00855       {ASTCHANMACROPRI,        ASN_INTEGER,   RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANMACROPRI}},
00856       {ASTCHANEXTEN,           ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANEXTEN}},
00857       {ASTCHANPRI,             ASN_INTEGER,   RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANPRI}},
00858       {ASTCHANACCOUNTCODE,     ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANACCOUNTCODE}},
00859       {ASTCHANFORWARDTO,       ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANFORWARDTO}},
00860       {ASTCHANUNIQUEID,        ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANUNIQUEID}},
00861       {ASTCHANCALLGROUP,       ASN_UNSIGNED,  RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCALLGROUP}},
00862       {ASTCHANPICKUPGROUP,     ASN_UNSIGNED,  RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANPICKUPGROUP}},
00863       {ASTCHANSTATE,           ASN_INTEGER,   RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANSTATE}},
00864       {ASTCHANMUTED,           ASN_INTEGER,   RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANMUTED}},
00865       {ASTCHANRINGS,           ASN_INTEGER,   RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANRINGS}},
00866       {ASTCHANCIDDNID,         ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDDNID}},
00867       {ASTCHANCIDNUM,          ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDNUM}},
00868       {ASTCHANCIDNAME,         ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDNAME}},
00869       {ASTCHANCIDANI,          ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDANI}},
00870       {ASTCHANCIDRDNIS,        ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDRDNIS}},
00871       {ASTCHANCIDPRES,         ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDPRES}},
00872       {ASTCHANCIDANI2,         ASN_INTEGER,   RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDANI2}},
00873       {ASTCHANCIDTON,          ASN_INTEGER,   RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDTON}},
00874       {ASTCHANCIDTNS,          ASN_INTEGER,   RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDTNS}},
00875       {ASTCHANAMAFLAGS,        ASN_INTEGER,   RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANAMAFLAGS}},
00876       {ASTCHANADSI,            ASN_INTEGER,   RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANADSI}},
00877       {ASTCHANTONEZONE,        ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANTONEZONE}},
00878       {ASTCHANHANGUPCAUSE,     ASN_INTEGER,   RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANHANGUPCAUSE}},
00879       {ASTCHANVARIABLES,       ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANVARIABLES}},
00880       {ASTCHANFLAGS,           ASN_OCTET_STR, RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANFLAGS}},
00881       {ASTCHANTRANSFERCAP,     ASN_INTEGER,   RONLY, ast_var_channels_table,      4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANTRANSFERCAP}},
00882       {ASTCHANTYPECOUNT,       ASN_INTEGER,   RONLY, ast_var_channel_types,       2, {ASTCHANNELS, ASTCHANTYPECOUNT}},
00883       {ASTCHANTYPEINDEX,       ASN_INTEGER,   RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPEINDEX}},
00884       {ASTCHANTYPENAME,        ASN_OCTET_STR, RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPENAME}},
00885       {ASTCHANTYPEDESC,        ASN_OCTET_STR, RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPEDESC}},
00886       {ASTCHANTYPEDEVSTATE,    ASN_INTEGER,   RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPEDEVSTATE}},
00887       {ASTCHANTYPEINDICATIONS, ASN_INTEGER,   RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPEINDICATIONS}},
00888       {ASTCHANTYPETRANSFER,    ASN_INTEGER,   RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPETRANSFER}},
00889       {ASTCHANTYPECHANNELS,    ASN_GAUGE,     RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPECHANNELS}},
00890       {ASTCHANBRIDGECOUNT,     ASN_GAUGE,     RONLY, ast_var_channel_bridge,      3, {ASTCHANNELS, ASTCHANSCALARS, ASTCHANBRIDGECOUNT}},
00891    };
00892 
00893    register_sysORTable(asterisk_oid, OID_LENGTH(asterisk_oid),
00894          "ASTERISK-MIB implementation for Asterisk.");
00895 
00896    REGISTER_MIB("res_snmp", asterisk_vars, variable4, asterisk_oid);
00897 
00898    snmp_register_callback(SNMP_CALLBACK_LIBRARY,
00899             SNMP_CALLBACK_SHUTDOWN,
00900             term_asterisk_mib, NULL);
00901 }
00902 
00903 /*
00904  * Local Variables:
00905  * c-basic-offset: 4
00906  * c-file-offsets: ((case-label . 0))
00907  * tab-width: 4
00908  * indent-tabs-mode: t
00909  * End:
00910  */

Generated on Thu Apr 16 06:27:06 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6