Sat Apr 26 2014 22:01:25

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