Thu Apr 28 2011 16:56:39

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