agent.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925
  1. /*
  2. * Copyright (C) 2006 Voop as
  3. * Thorsten Lockert <tholo@voop.as>
  4. *
  5. * This program is free software, distributed under the terms of
  6. * the GNU General Public License Version 2. See the LICENSE file
  7. * at the top of the source tree.
  8. */
  9. /*! \file
  10. *
  11. * \brief SNMP Agent / SubAgent support for Asterisk
  12. *
  13. * \author Thorsten Lockert <tholo@voop.as>
  14. */
  15. /*** MODULEINFO
  16. <support_level>extended</support_level>
  17. ***/
  18. #include "asterisk.h"
  19. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  20. /*
  21. * There is some collision collision between netsmp and asterisk names,
  22. * causing build under AST_DEVMODE to fail.
  23. *
  24. * The following PACKAGE_* macros are one place.
  25. * Also netsnmp has an improper check for HAVE_DMALLOC_H, using
  26. * #if HAVE_DMALLOC_H instead of #ifdef HAVE_DMALLOC_H
  27. * As a countermeasure we define it to 0, however this will fail
  28. * when the proper check is implemented.
  29. */
  30. #ifdef PACKAGE_NAME
  31. #undef PACKAGE_NAME
  32. #endif
  33. #ifdef PACKAGE_BUGREPORT
  34. #undef PACKAGE_BUGREPORT
  35. #endif
  36. #ifdef PACKAGE_STRING
  37. #undef PACKAGE_STRING
  38. #endif
  39. #ifdef PACKAGE_TARNAME
  40. #undef PACKAGE_TARNAME
  41. #endif
  42. #ifdef PACKAGE_VERSION
  43. #undef PACKAGE_VERSION
  44. #endif
  45. #ifndef HAVE_DMALLOC_H
  46. #define HAVE_DMALLOC_H 0 /* XXX we shouldn't do this */
  47. #endif
  48. #if defined(__OpenBSD__)
  49. /*
  50. * OpenBSD uses old "legacy" cc which has a rather pedantic builtin preprocessor.
  51. * Using a macro which is not #defined throws an error.
  52. */
  53. #define __NetBSD_Version__ 0
  54. #endif
  55. #include <net-snmp/net-snmp-config.h>
  56. #include <net-snmp/net-snmp-includes.h>
  57. #include <net-snmp/agent/net-snmp-agent-includes.h>
  58. #include "asterisk/paths.h" /* need ast_config_AST_SOCKET */
  59. #include "asterisk/channel.h"
  60. #include "asterisk/logger.h"
  61. #include "asterisk/options.h"
  62. #include "asterisk/indications.h"
  63. #include "asterisk/ast_version.h"
  64. #include "asterisk/pbx.h"
  65. /* Colission between Net-SNMP and Asterisk */
  66. #define unload_module ast_unload_module
  67. #include "asterisk/module.h"
  68. #undef unload_module
  69. #include "agent.h"
  70. /* Helper functions in Net-SNMP, header file not installed by default */
  71. int header_generic(struct variable *, oid *, size_t *, int, size_t *, WriteMethod **);
  72. int header_simple_table(struct variable *, oid *, size_t *, int, size_t *, WriteMethod **, int);
  73. int register_sysORTable(oid *, size_t, const char *);
  74. int unregister_sysORTable(oid *, size_t);
  75. /* Forward declaration */
  76. static void init_asterisk_mib(void);
  77. /*
  78. * Anchor for all the Asterisk MIB values
  79. */
  80. static oid asterisk_oid[] = { 1, 3, 6, 1, 4, 1, 22736, 1 };
  81. /*
  82. * MIB values -- these correspond to values in the Asterisk MIB,
  83. * and MUST be kept in sync with the MIB for things to work as
  84. * expected.
  85. */
  86. #define ASTVERSION 1
  87. #define ASTVERSTRING 1
  88. #define ASTVERTAG 2
  89. #define ASTCONFIGURATION 2
  90. #define ASTCONFUPTIME 1
  91. #define ASTCONFRELOADTIME 2
  92. #define ASTCONFPID 3
  93. #define ASTCONFSOCKET 4
  94. #define ASTCONFACTIVECALLS 5
  95. #define ASTCONFPROCESSEDCALLS 6
  96. #define ASTMODULES 3
  97. #define ASTMODCOUNT 1
  98. #define ASTINDICATIONS 4
  99. #define ASTINDCOUNT 1
  100. #define ASTINDCURRENT 2
  101. #define ASTINDTABLE 3
  102. #define ASTINDINDEX 1
  103. #define ASTINDCOUNTRY 2
  104. #define ASTINDALIAS 3
  105. #define ASTINDDESCRIPTION 4
  106. #define ASTCHANNELS 5
  107. #define ASTCHANCOUNT 1
  108. #define ASTCHANTABLE 2
  109. #define ASTCHANINDEX 1
  110. #define ASTCHANNAME 2
  111. #define ASTCHANLANGUAGE 3
  112. #define ASTCHANTYPE 4
  113. #define ASTCHANMUSICCLASS 5
  114. #define ASTCHANBRIDGE 6
  115. #define ASTCHANMASQ 7
  116. #define ASTCHANMASQR 8
  117. #define ASTCHANWHENHANGUP 9
  118. #define ASTCHANAPP 10
  119. #define ASTCHANDATA 11
  120. #define ASTCHANCONTEXT 12
  121. #define ASTCHANMACROCONTEXT 13
  122. #define ASTCHANMACROEXTEN 14
  123. #define ASTCHANMACROPRI 15
  124. #define ASTCHANEXTEN 16
  125. #define ASTCHANPRI 17
  126. #define ASTCHANACCOUNTCODE 18
  127. #define ASTCHANFORWARDTO 19
  128. #define ASTCHANUNIQUEID 20
  129. #define ASTCHANCALLGROUP 21
  130. #define ASTCHANPICKUPGROUP 22
  131. #define ASTCHANSTATE 23
  132. #define ASTCHANMUTED 24
  133. #define ASTCHANRINGS 25
  134. #define ASTCHANCIDDNID 26
  135. #define ASTCHANCIDNUM 27
  136. #define ASTCHANCIDNAME 28
  137. #define ASTCHANCIDANI 29
  138. #define ASTCHANCIDRDNIS 30
  139. #define ASTCHANCIDPRES 31
  140. #define ASTCHANCIDANI2 32
  141. #define ASTCHANCIDTON 33
  142. #define ASTCHANCIDTNS 34
  143. #define ASTCHANAMAFLAGS 35
  144. #define ASTCHANADSI 36
  145. #define ASTCHANTONEZONE 37
  146. #define ASTCHANHANGUPCAUSE 38
  147. #define ASTCHANVARIABLES 39
  148. #define ASTCHANFLAGS 40
  149. #define ASTCHANTRANSFERCAP 41
  150. #define ASTCHANTYPECOUNT 3
  151. #define ASTCHANTYPETABLE 4
  152. #define ASTCHANTYPEINDEX 1
  153. #define ASTCHANTYPENAME 2
  154. #define ASTCHANTYPEDESC 3
  155. #define ASTCHANTYPEDEVSTATE 4
  156. #define ASTCHANTYPEINDICATIONS 5
  157. #define ASTCHANTYPETRANSFER 6
  158. #define ASTCHANTYPECHANNELS 7
  159. #define ASTCHANSCALARS 5
  160. #define ASTCHANBRIDGECOUNT 1
  161. void *agent_thread(void *arg)
  162. {
  163. ast_verb(2, "Starting %sAgent\n", res_snmp_agentx_subagent ? "Sub" : "");
  164. snmp_enable_stderrlog();
  165. if (res_snmp_agentx_subagent)
  166. netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID,
  167. NETSNMP_DS_AGENT_ROLE,
  168. 1);
  169. init_agent("asterisk");
  170. init_asterisk_mib();
  171. init_snmp("asterisk");
  172. if (!res_snmp_agentx_subagent)
  173. init_master_agent();
  174. while (res_snmp_dont_stop)
  175. agent_check_and_process(1);
  176. snmp_shutdown("asterisk");
  177. ast_verb(2, "Terminating %sAgent\n", res_snmp_agentx_subagent ? "Sub" : "");
  178. return NULL;
  179. }
  180. static u_char *
  181. ast_var_channels(struct variable *vp, oid *name, size_t *length,
  182. int exact, size_t *var_len, WriteMethod **write_method)
  183. {
  184. static unsigned long long_ret;
  185. if (header_generic(vp, name, length, exact, var_len, write_method))
  186. return NULL;
  187. if (vp->magic != ASTCHANCOUNT)
  188. return NULL;
  189. long_ret = ast_active_channels();
  190. return (u_char *)&long_ret;
  191. }
  192. static u_char *ast_var_channels_table(struct variable *vp, oid *name, size_t *length,
  193. int exact, size_t *var_len, WriteMethod **write_method)
  194. {
  195. static unsigned long long_ret;
  196. static u_char bits_ret[2];
  197. static char string_ret[256];
  198. struct ast_channel *chan, *bridge;
  199. struct timeval tval;
  200. u_char *ret = NULL;
  201. int i, bit;
  202. struct ast_str *out = ast_str_alloca(2048);
  203. struct ast_channel_iterator *iter;
  204. if (header_simple_table(vp, name, length, exact, var_len, write_method, ast_active_channels()))
  205. return NULL;
  206. i = name[*length - 1] - 1;
  207. if (!(iter = ast_channel_iterator_all_new())) {
  208. return NULL;
  209. }
  210. while ((chan = ast_channel_iterator_next(iter)) && i) {
  211. ast_channel_unref(chan);
  212. i--;
  213. }
  214. iter = ast_channel_iterator_destroy(iter);
  215. if (chan == NULL) {
  216. return NULL;
  217. }
  218. *var_len = sizeof(long_ret);
  219. ast_channel_lock(chan);
  220. switch (vp->magic) {
  221. case ASTCHANINDEX:
  222. long_ret = name[*length - 1];
  223. ret = (u_char *)&long_ret;
  224. break;
  225. case ASTCHANNAME:
  226. if (!ast_strlen_zero(chan->name)) {
  227. strncpy(string_ret, chan->name, sizeof(string_ret));
  228. string_ret[sizeof(string_ret) - 1] = '\0';
  229. *var_len = strlen(string_ret);
  230. ret = (u_char *)string_ret;
  231. }
  232. break;
  233. case ASTCHANLANGUAGE:
  234. if (!ast_strlen_zero(chan->language)) {
  235. strncpy(string_ret, chan->language, sizeof(string_ret));
  236. string_ret[sizeof(string_ret) - 1] = '\0';
  237. *var_len = strlen(string_ret);
  238. ret = (u_char *)string_ret;
  239. }
  240. break;
  241. case ASTCHANTYPE:
  242. strncpy(string_ret, chan->tech->type, sizeof(string_ret));
  243. string_ret[sizeof(string_ret) - 1] = '\0';
  244. *var_len = strlen(string_ret);
  245. ret = (u_char *)string_ret;
  246. break;
  247. case ASTCHANMUSICCLASS:
  248. if (!ast_strlen_zero(chan->musicclass)) {
  249. strncpy(string_ret, chan->musicclass, sizeof(string_ret));
  250. string_ret[sizeof(string_ret) - 1] = '\0';
  251. *var_len = strlen(string_ret);
  252. ret = (u_char *)string_ret;
  253. }
  254. break;
  255. case ASTCHANBRIDGE:
  256. if ((bridge = ast_bridged_channel(chan)) != NULL) {
  257. strncpy(string_ret, bridge->name, sizeof(string_ret));
  258. string_ret[sizeof(string_ret) - 1] = '\0';
  259. *var_len = strlen(string_ret);
  260. ret = (u_char *)string_ret;
  261. }
  262. break;
  263. case ASTCHANMASQ:
  264. if (chan->masq && !ast_strlen_zero(chan->masq->name)) {
  265. strncpy(string_ret, chan->masq->name, sizeof(string_ret));
  266. string_ret[sizeof(string_ret) - 1] = '\0';
  267. *var_len = strlen(string_ret);
  268. ret = (u_char *)string_ret;
  269. }
  270. break;
  271. case ASTCHANMASQR:
  272. if (chan->masqr && !ast_strlen_zero(chan->masqr->name)) {
  273. strncpy(string_ret, chan->masqr->name, sizeof(string_ret));
  274. string_ret[sizeof(string_ret) - 1] = '\0';
  275. *var_len = strlen(string_ret);
  276. ret = (u_char *)string_ret;
  277. }
  278. break;
  279. case ASTCHANWHENHANGUP:
  280. if (!ast_tvzero(chan->whentohangup)) {
  281. gettimeofday(&tval, NULL);
  282. long_ret = difftime(chan->whentohangup.tv_sec, tval.tv_sec) * 100 - tval.tv_usec / 10000;
  283. ret= (u_char *)&long_ret;
  284. }
  285. break;
  286. case ASTCHANAPP:
  287. if (chan->appl) {
  288. strncpy(string_ret, chan->appl, sizeof(string_ret));
  289. string_ret[sizeof(string_ret) - 1] = '\0';
  290. *var_len = strlen(string_ret);
  291. ret = (u_char *)string_ret;
  292. }
  293. break;
  294. case ASTCHANDATA:
  295. if (chan->data) {
  296. strncpy(string_ret, chan->data, sizeof(string_ret));
  297. string_ret[sizeof(string_ret) - 1] = '\0';
  298. *var_len = strlen(string_ret);
  299. ret = (u_char *)string_ret;
  300. }
  301. break;
  302. case ASTCHANCONTEXT:
  303. strncpy(string_ret, chan->context, sizeof(string_ret));
  304. string_ret[sizeof(string_ret) - 1] = '\0';
  305. *var_len = strlen(string_ret);
  306. ret = (u_char *)string_ret;
  307. break;
  308. case ASTCHANMACROCONTEXT:
  309. strncpy(string_ret, chan->macrocontext, sizeof(string_ret));
  310. string_ret[sizeof(string_ret) - 1] = '\0';
  311. *var_len = strlen(string_ret);
  312. ret = (u_char *)string_ret;
  313. break;
  314. case ASTCHANMACROEXTEN:
  315. strncpy(string_ret, chan->macroexten, sizeof(string_ret));
  316. string_ret[sizeof(string_ret) - 1] = '\0';
  317. *var_len = strlen(string_ret);
  318. ret = (u_char *)string_ret;
  319. break;
  320. case ASTCHANMACROPRI:
  321. long_ret = chan->macropriority;
  322. ret = (u_char *)&long_ret;
  323. break;
  324. case ASTCHANEXTEN:
  325. strncpy(string_ret, chan->exten, sizeof(string_ret));
  326. string_ret[sizeof(string_ret) - 1] = '\0';
  327. *var_len = strlen(string_ret);
  328. ret = (u_char *)string_ret;
  329. break;
  330. case ASTCHANPRI:
  331. long_ret = chan->priority;
  332. ret = (u_char *)&long_ret;
  333. break;
  334. case ASTCHANACCOUNTCODE:
  335. if (!ast_strlen_zero(chan->accountcode)) {
  336. strncpy(string_ret, chan->accountcode, sizeof(string_ret));
  337. string_ret[sizeof(string_ret) - 1] = '\0';
  338. *var_len = strlen(string_ret);
  339. ret = (u_char *)string_ret;
  340. }
  341. break;
  342. case ASTCHANFORWARDTO:
  343. if (!ast_strlen_zero(chan->call_forward)) {
  344. strncpy(string_ret, chan->call_forward, sizeof(string_ret));
  345. string_ret[sizeof(string_ret) - 1] = '\0';
  346. *var_len = strlen(string_ret);
  347. ret = (u_char *)string_ret;
  348. }
  349. break;
  350. case ASTCHANUNIQUEID:
  351. strncpy(string_ret, chan->uniqueid, sizeof(string_ret));
  352. string_ret[sizeof(string_ret) - 1] = '\0';
  353. *var_len = strlen(string_ret);
  354. ret = (u_char *)string_ret;
  355. break;
  356. case ASTCHANCALLGROUP:
  357. long_ret = chan->callgroup;
  358. ret = (u_char *)&long_ret;
  359. break;
  360. case ASTCHANPICKUPGROUP:
  361. long_ret = chan->pickupgroup;
  362. ret = (u_char *)&long_ret;
  363. break;
  364. case ASTCHANSTATE:
  365. long_ret = chan->_state & 0xffff;
  366. ret = (u_char *)&long_ret;
  367. break;
  368. case ASTCHANMUTED:
  369. long_ret = chan->_state & AST_STATE_MUTE ? 1 : 2;
  370. ret = (u_char *)&long_ret;
  371. break;
  372. case ASTCHANRINGS:
  373. long_ret = chan->rings;
  374. ret = (u_char *)&long_ret;
  375. break;
  376. case ASTCHANCIDDNID:
  377. if (chan->dialed.number.str) {
  378. strncpy(string_ret, chan->dialed.number.str, sizeof(string_ret));
  379. string_ret[sizeof(string_ret) - 1] = '\0';
  380. *var_len = strlen(string_ret);
  381. ret = (u_char *)string_ret;
  382. }
  383. break;
  384. case ASTCHANCIDNUM:
  385. if (chan->caller.id.number.valid && chan->caller.id.number.str) {
  386. strncpy(string_ret, chan->caller.id.number.str, sizeof(string_ret));
  387. string_ret[sizeof(string_ret) - 1] = '\0';
  388. *var_len = strlen(string_ret);
  389. ret = (u_char *)string_ret;
  390. }
  391. break;
  392. case ASTCHANCIDNAME:
  393. if (chan->caller.id.name.valid && chan->caller.id.name.str) {
  394. strncpy(string_ret, chan->caller.id.name.str, sizeof(string_ret));
  395. string_ret[sizeof(string_ret) - 1] = '\0';
  396. *var_len = strlen(string_ret);
  397. ret = (u_char *)string_ret;
  398. }
  399. break;
  400. case ASTCHANCIDANI:
  401. if (chan->caller.ani.number.valid && chan->caller.ani.number.str) {
  402. strncpy(string_ret, chan->caller.ani.number.str, sizeof(string_ret));
  403. string_ret[sizeof(string_ret) - 1] = '\0';
  404. *var_len = strlen(string_ret);
  405. ret = (u_char *)string_ret;
  406. }
  407. break;
  408. case ASTCHANCIDRDNIS:
  409. if (chan->redirecting.from.number.valid && chan->redirecting.from.number.str) {
  410. strncpy(string_ret, chan->redirecting.from.number.str, sizeof(string_ret));
  411. string_ret[sizeof(string_ret) - 1] = '\0';
  412. *var_len = strlen(string_ret);
  413. ret = (u_char *)string_ret;
  414. }
  415. break;
  416. case ASTCHANCIDPRES:
  417. long_ret = ast_party_id_presentation(&chan->caller.id);
  418. ret = (u_char *)&long_ret;
  419. break;
  420. case ASTCHANCIDANI2:
  421. long_ret = chan->caller.ani2;
  422. ret = (u_char *)&long_ret;
  423. break;
  424. case ASTCHANCIDTON:
  425. long_ret = chan->caller.id.number.plan;
  426. ret = (u_char *)&long_ret;
  427. break;
  428. case ASTCHANCIDTNS:
  429. long_ret = chan->dialed.transit_network_select;
  430. ret = (u_char *)&long_ret;
  431. break;
  432. case ASTCHANAMAFLAGS:
  433. long_ret = chan->amaflags;
  434. ret = (u_char *)&long_ret;
  435. break;
  436. case ASTCHANADSI:
  437. long_ret = chan->adsicpe;
  438. ret = (u_char *)&long_ret;
  439. break;
  440. case ASTCHANTONEZONE:
  441. if (chan->zone) {
  442. strncpy(string_ret, chan->zone->country, sizeof(string_ret));
  443. string_ret[sizeof(string_ret) - 1] = '\0';
  444. *var_len = strlen(string_ret);
  445. ret = (u_char *)string_ret;
  446. }
  447. break;
  448. case ASTCHANHANGUPCAUSE:
  449. long_ret = chan->hangupcause;
  450. ret = (u_char *)&long_ret;
  451. break;
  452. case ASTCHANVARIABLES:
  453. if (pbx_builtin_serialize_variables(chan, &out)) {
  454. *var_len = ast_str_strlen(out);
  455. ret = (u_char *)ast_str_buffer(out);
  456. }
  457. break;
  458. case ASTCHANFLAGS:
  459. bits_ret[0] = 0;
  460. for (bit = 0; bit < 8; bit++)
  461. bits_ret[0] |= ((chan->flags & (1 << bit)) >> bit) << (7 - bit);
  462. bits_ret[1] = 0;
  463. for (bit = 0; bit < 8; bit++)
  464. bits_ret[1] |= (((chan->flags >> 8) & (1 << bit)) >> bit) << (7 - bit);
  465. *var_len = 2;
  466. ret = bits_ret;
  467. break;
  468. case ASTCHANTRANSFERCAP:
  469. long_ret = chan->transfercapability;
  470. ret = (u_char *)&long_ret;
  471. default:
  472. break;
  473. }
  474. ast_channel_unlock(chan);
  475. chan = ast_channel_unref(chan);
  476. return ret;
  477. }
  478. static u_char *ast_var_channel_types(struct variable *vp, oid *name, size_t *length,
  479. int exact, size_t *var_len, WriteMethod **write_method)
  480. {
  481. static unsigned long long_ret;
  482. struct ast_variable *channel_types, *next;
  483. if (header_generic(vp, name, length, exact, var_len, write_method))
  484. return NULL;
  485. if (vp->magic != ASTCHANTYPECOUNT)
  486. return NULL;
  487. for (long_ret = 0, channel_types = next = ast_channeltype_list(); next; next = next->next)
  488. long_ret++;
  489. ast_variables_destroy(channel_types);
  490. return (u_char *)&long_ret;
  491. }
  492. static u_char *ast_var_channel_types_table(struct variable *vp, oid *name, size_t *length,
  493. int exact, size_t *var_len, WriteMethod **write_method)
  494. {
  495. const struct ast_channel_tech *tech = NULL;
  496. struct ast_variable *channel_types, *next;
  497. static unsigned long long_ret;
  498. struct ast_channel *chan;
  499. u_long i;
  500. if (header_simple_table(vp, name, length, exact, var_len, write_method, -1))
  501. return NULL;
  502. channel_types = ast_channeltype_list();
  503. for (i = 1, next = channel_types; next && i != name[*length - 1]; next = next->next, i++)
  504. ;
  505. if (next != NULL)
  506. tech = ast_get_channel_tech(next->name);
  507. ast_variables_destroy(channel_types);
  508. if (next == NULL || tech == NULL)
  509. return NULL;
  510. switch (vp->magic) {
  511. case ASTCHANTYPEINDEX:
  512. long_ret = name[*length - 1];
  513. return (u_char *)&long_ret;
  514. case ASTCHANTYPENAME:
  515. *var_len = strlen(tech->type);
  516. return (u_char *)tech->type;
  517. case ASTCHANTYPEDESC:
  518. *var_len = strlen(tech->description);
  519. return (u_char *)tech->description;
  520. case ASTCHANTYPEDEVSTATE:
  521. long_ret = tech->devicestate ? 1 : 2;
  522. return (u_char *)&long_ret;
  523. case ASTCHANTYPEINDICATIONS:
  524. long_ret = tech->indicate ? 1 : 2;
  525. return (u_char *)&long_ret;
  526. case ASTCHANTYPETRANSFER:
  527. long_ret = tech->transfer ? 1 : 2;
  528. return (u_char *)&long_ret;
  529. case ASTCHANTYPECHANNELS:
  530. {
  531. struct ast_channel_iterator *iter;
  532. long_ret = 0;
  533. if (!(iter = ast_channel_iterator_all_new())) {
  534. return NULL;
  535. }
  536. while ((chan = ast_channel_iterator_next(iter))) {
  537. if (chan->tech == tech) {
  538. long_ret++;
  539. }
  540. chan = ast_channel_unref(chan);
  541. }
  542. ast_channel_iterator_destroy(iter);
  543. return (u_char *)&long_ret;
  544. }
  545. default:
  546. break;
  547. }
  548. return NULL;
  549. }
  550. static u_char *ast_var_channel_bridge(struct variable *vp, oid *name, size_t *length,
  551. int exact, size_t *var_len, WriteMethod **write_method)
  552. {
  553. static unsigned long long_ret;
  554. struct ast_channel *chan = NULL;
  555. struct ast_channel_iterator *iter;
  556. long_ret = 0;
  557. if (header_generic(vp, name, length, exact, var_len, write_method)) {
  558. return NULL;
  559. }
  560. if (!(iter = ast_channel_iterator_all_new())) {
  561. return NULL;
  562. }
  563. while ((chan = ast_channel_iterator_next(iter))) {
  564. ast_channel_lock(chan);
  565. if (ast_bridged_channel(chan)) {
  566. long_ret++;
  567. }
  568. ast_channel_unlock(chan);
  569. chan = ast_channel_unref(chan);
  570. }
  571. ast_channel_iterator_destroy(iter);
  572. *var_len = sizeof(long_ret);
  573. return (vp->magic == ASTCHANBRIDGECOUNT) ? (u_char *) &long_ret : NULL;
  574. }
  575. static u_char *ast_var_Config(struct variable *vp, oid *name, size_t *length,
  576. int exact, size_t *var_len, WriteMethod **write_method)
  577. {
  578. static unsigned long long_ret;
  579. struct timeval tval;
  580. if (header_generic(vp, name, length, exact, var_len, write_method))
  581. return NULL;
  582. switch (vp->magic) {
  583. case ASTCONFUPTIME:
  584. gettimeofday(&tval, NULL);
  585. long_ret = difftime(tval.tv_sec, ast_startuptime.tv_sec) * 100 + tval.tv_usec / 10000 - ast_startuptime.tv_usec / 10000;
  586. return (u_char *)&long_ret;
  587. case ASTCONFRELOADTIME:
  588. gettimeofday(&tval, NULL);
  589. if (ast_lastreloadtime.tv_sec)
  590. long_ret = difftime(tval.tv_sec, ast_lastreloadtime.tv_sec) * 100 + tval.tv_usec / 10000 - ast_lastreloadtime.tv_usec / 10000;
  591. else
  592. long_ret = difftime(tval.tv_sec, ast_startuptime.tv_sec) * 100 + tval.tv_usec / 10000 - ast_startuptime.tv_usec / 10000;
  593. return (u_char *)&long_ret;
  594. case ASTCONFPID:
  595. long_ret = getpid();
  596. return (u_char *)&long_ret;
  597. case ASTCONFSOCKET:
  598. *var_len = strlen(ast_config_AST_SOCKET);
  599. return (u_char *)ast_config_AST_SOCKET;
  600. case ASTCONFACTIVECALLS:
  601. long_ret = ast_active_calls();
  602. return (u_char *)&long_ret;
  603. case ASTCONFPROCESSEDCALLS:
  604. long_ret = ast_processed_calls();
  605. return (u_char *)&long_ret;
  606. default:
  607. break;
  608. }
  609. return NULL;
  610. }
  611. static u_char *ast_var_indications(struct variable *vp, oid *name, size_t *length,
  612. int exact, size_t *var_len, WriteMethod **write_method)
  613. {
  614. static unsigned long long_ret;
  615. static char ret_buf[128];
  616. struct ast_tone_zone *tz = NULL;
  617. if (header_generic(vp, name, length, exact, var_len, write_method))
  618. return NULL;
  619. switch (vp->magic) {
  620. case ASTINDCOUNT:
  621. {
  622. struct ao2_iterator i;
  623. long_ret = 0;
  624. i = ast_tone_zone_iterator_init();
  625. while ((tz = ao2_iterator_next(&i))) {
  626. tz = ast_tone_zone_unref(tz);
  627. long_ret++;
  628. }
  629. ao2_iterator_destroy(&i);
  630. return (u_char *) &long_ret;
  631. }
  632. case ASTINDCURRENT:
  633. tz = ast_get_indication_zone(NULL);
  634. if (tz) {
  635. ast_copy_string(ret_buf, tz->country, sizeof(ret_buf));
  636. *var_len = strlen(ret_buf);
  637. tz = ast_tone_zone_unref(tz);
  638. return (u_char *) ret_buf;
  639. }
  640. *var_len = 0;
  641. return NULL;
  642. default:
  643. break;
  644. }
  645. return NULL;
  646. }
  647. static u_char *ast_var_indications_table(struct variable *vp, oid *name, size_t *length,
  648. int exact, size_t *var_len, WriteMethod **write_method)
  649. {
  650. static unsigned long long_ret;
  651. static char ret_buf[256];
  652. struct ast_tone_zone *tz = NULL;
  653. int i;
  654. struct ao2_iterator iter;
  655. if (header_simple_table(vp, name, length, exact, var_len, write_method, -1)) {
  656. return NULL;
  657. }
  658. i = name[*length - 1] - 1;
  659. iter = ast_tone_zone_iterator_init();
  660. while ((tz = ao2_iterator_next(&iter)) && i) {
  661. tz = ast_tone_zone_unref(tz);
  662. i--;
  663. }
  664. ao2_iterator_destroy(&iter);
  665. if (tz == NULL) {
  666. return NULL;
  667. }
  668. switch (vp->magic) {
  669. case ASTINDINDEX:
  670. ast_tone_zone_unref(tz);
  671. long_ret = name[*length - 1];
  672. return (u_char *)&long_ret;
  673. case ASTINDCOUNTRY:
  674. ast_copy_string(ret_buf, tz->country, sizeof(ret_buf));
  675. ast_tone_zone_unref(tz);
  676. *var_len = strlen(ret_buf);
  677. return (u_char *) ret_buf;
  678. case ASTINDALIAS:
  679. /* No longer exists */
  680. ast_tone_zone_unref(tz);
  681. return NULL;
  682. case ASTINDDESCRIPTION:
  683. ast_tone_zone_lock(tz);
  684. ast_copy_string(ret_buf, tz->description, sizeof(ret_buf));
  685. ast_tone_zone_unlock(tz);
  686. ast_tone_zone_unref(tz);
  687. *var_len = strlen(ret_buf);
  688. return (u_char *) ret_buf;
  689. default:
  690. ast_tone_zone_unref(tz);
  691. break;
  692. }
  693. return NULL;
  694. }
  695. static int countmodule(const char *mod, const char *desc, int use, const char *like)
  696. {
  697. return 1;
  698. }
  699. static u_char *ast_var_Modules(struct variable *vp, oid *name, size_t *length,
  700. int exact, size_t *var_len, WriteMethod **write_method)
  701. {
  702. static unsigned long long_ret;
  703. if (header_generic(vp, name, length, exact, var_len, write_method))
  704. return NULL;
  705. if (vp->magic != ASTMODCOUNT)
  706. return NULL;
  707. long_ret = ast_update_module_list(countmodule, NULL);
  708. return (u_char *)&long_ret;
  709. }
  710. static u_char *ast_var_Version(struct variable *vp, oid *name, size_t *length,
  711. int exact, size_t *var_len, WriteMethod **write_method)
  712. {
  713. static unsigned long long_ret;
  714. if (header_generic(vp, name, length, exact, var_len, write_method))
  715. return NULL;
  716. switch (vp->magic) {
  717. case ASTVERSTRING:
  718. {
  719. const char *version = ast_get_version();
  720. *var_len = strlen(version);
  721. return (u_char *)version;
  722. }
  723. case ASTVERTAG:
  724. sscanf(ast_get_version_num(), "%30lu", &long_ret);
  725. return (u_char *)&long_ret;
  726. default:
  727. break;
  728. }
  729. return NULL;
  730. }
  731. static int term_asterisk_mib(int majorID, int minorID, void *serverarg, void *clientarg)
  732. {
  733. unregister_sysORTable(asterisk_oid, OID_LENGTH(asterisk_oid));
  734. return 0;
  735. }
  736. static void init_asterisk_mib(void)
  737. {
  738. static struct variable4 asterisk_vars[] = {
  739. {ASTVERSTRING, ASN_OCTET_STR, RONLY, ast_var_Version, 2, {ASTVERSION, ASTVERSTRING}},
  740. {ASTVERTAG, ASN_UNSIGNED, RONLY, ast_var_Version, 2, {ASTVERSION, ASTVERTAG}},
  741. {ASTCONFUPTIME, ASN_TIMETICKS, RONLY, ast_var_Config, 2, {ASTCONFIGURATION, ASTCONFUPTIME}},
  742. {ASTCONFRELOADTIME, ASN_TIMETICKS, RONLY, ast_var_Config, 2, {ASTCONFIGURATION, ASTCONFRELOADTIME}},
  743. {ASTCONFPID, ASN_INTEGER, RONLY, ast_var_Config, 2, {ASTCONFIGURATION, ASTCONFPID}},
  744. {ASTCONFSOCKET, ASN_OCTET_STR, RONLY, ast_var_Config, 2, {ASTCONFIGURATION, ASTCONFSOCKET}},
  745. {ASTCONFACTIVECALLS, ASN_GAUGE, RONLY, ast_var_Config, 2, {ASTCONFIGURATION, ASTCONFACTIVECALLS}},
  746. {ASTCONFPROCESSEDCALLS, ASN_COUNTER, RONLY, ast_var_Config, 2, {ASTCONFIGURATION, ASTCONFPROCESSEDCALLS}},
  747. {ASTMODCOUNT, ASN_INTEGER, RONLY, ast_var_Modules , 2, {ASTMODULES, ASTMODCOUNT}},
  748. {ASTINDCOUNT, ASN_INTEGER, RONLY, ast_var_indications, 2, {ASTINDICATIONS, ASTINDCOUNT}},
  749. {ASTINDCURRENT, ASN_OCTET_STR, RONLY, ast_var_indications, 2, {ASTINDICATIONS, ASTINDCURRENT}},
  750. {ASTINDINDEX, ASN_INTEGER, RONLY, ast_var_indications_table, 4, {ASTINDICATIONS, ASTINDTABLE, 1, ASTINDINDEX}},
  751. {ASTINDCOUNTRY, ASN_OCTET_STR, RONLY, ast_var_indications_table, 4, {ASTINDICATIONS, ASTINDTABLE, 1, ASTINDCOUNTRY}},
  752. {ASTINDALIAS, ASN_OCTET_STR, RONLY, ast_var_indications_table, 4, {ASTINDICATIONS, ASTINDTABLE, 1, ASTINDALIAS}},
  753. {ASTINDDESCRIPTION, ASN_OCTET_STR, RONLY, ast_var_indications_table, 4, {ASTINDICATIONS, ASTINDTABLE, 1, ASTINDDESCRIPTION}},
  754. {ASTCHANCOUNT, ASN_GAUGE, RONLY, ast_var_channels, 2, {ASTCHANNELS, ASTCHANCOUNT}},
  755. {ASTCHANINDEX, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANINDEX}},
  756. {ASTCHANNAME, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANNAME}},
  757. {ASTCHANLANGUAGE, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANLANGUAGE}},
  758. {ASTCHANTYPE, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANTYPE}},
  759. {ASTCHANMUSICCLASS, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANMUSICCLASS}},
  760. {ASTCHANBRIDGE, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANBRIDGE}},
  761. {ASTCHANMASQ, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANMASQ}},
  762. {ASTCHANMASQR, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANMASQR}},
  763. {ASTCHANWHENHANGUP, ASN_TIMETICKS, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANWHENHANGUP}},
  764. {ASTCHANAPP, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANAPP}},
  765. {ASTCHANDATA, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANDATA}},
  766. {ASTCHANCONTEXT, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCONTEXT}},
  767. {ASTCHANMACROCONTEXT, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANMACROCONTEXT}},
  768. {ASTCHANMACROEXTEN, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANMACROEXTEN}},
  769. {ASTCHANMACROPRI, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANMACROPRI}},
  770. {ASTCHANEXTEN, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANEXTEN}},
  771. {ASTCHANPRI, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANPRI}},
  772. {ASTCHANACCOUNTCODE, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANACCOUNTCODE}},
  773. {ASTCHANFORWARDTO, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANFORWARDTO}},
  774. {ASTCHANUNIQUEID, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANUNIQUEID}},
  775. {ASTCHANCALLGROUP, ASN_UNSIGNED, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCALLGROUP}},
  776. {ASTCHANPICKUPGROUP, ASN_UNSIGNED, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANPICKUPGROUP}},
  777. {ASTCHANSTATE, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANSTATE}},
  778. {ASTCHANMUTED, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANMUTED}},
  779. {ASTCHANRINGS, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANRINGS}},
  780. {ASTCHANCIDDNID, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDDNID}},
  781. {ASTCHANCIDNUM, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDNUM}},
  782. {ASTCHANCIDNAME, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDNAME}},
  783. {ASTCHANCIDANI, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDANI}},
  784. {ASTCHANCIDRDNIS, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDRDNIS}},
  785. {ASTCHANCIDPRES, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDPRES}},
  786. {ASTCHANCIDANI2, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDANI2}},
  787. {ASTCHANCIDTON, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDTON}},
  788. {ASTCHANCIDTNS, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDTNS}},
  789. {ASTCHANAMAFLAGS, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANAMAFLAGS}},
  790. {ASTCHANADSI, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANADSI}},
  791. {ASTCHANTONEZONE, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANTONEZONE}},
  792. {ASTCHANHANGUPCAUSE, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANHANGUPCAUSE}},
  793. {ASTCHANVARIABLES, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANVARIABLES}},
  794. {ASTCHANFLAGS, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANFLAGS}},
  795. {ASTCHANTRANSFERCAP, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANTRANSFERCAP}},
  796. {ASTCHANTYPECOUNT, ASN_INTEGER, RONLY, ast_var_channel_types, 2, {ASTCHANNELS, ASTCHANTYPECOUNT}},
  797. {ASTCHANTYPEINDEX, ASN_INTEGER, RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPEINDEX}},
  798. {ASTCHANTYPENAME, ASN_OCTET_STR, RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPENAME}},
  799. {ASTCHANTYPEDESC, ASN_OCTET_STR, RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPEDESC}},
  800. {ASTCHANTYPEDEVSTATE, ASN_INTEGER, RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPEDEVSTATE}},
  801. {ASTCHANTYPEINDICATIONS, ASN_INTEGER, RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPEINDICATIONS}},
  802. {ASTCHANTYPETRANSFER, ASN_INTEGER, RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPETRANSFER}},
  803. {ASTCHANTYPECHANNELS, ASN_GAUGE, RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPECHANNELS}},
  804. {ASTCHANBRIDGECOUNT, ASN_GAUGE, RONLY, ast_var_channel_bridge, 3, {ASTCHANNELS, ASTCHANSCALARS, ASTCHANBRIDGECOUNT}},
  805. };
  806. register_sysORTable(asterisk_oid, OID_LENGTH(asterisk_oid),
  807. "ASTERISK-MIB implementation for Asterisk.");
  808. REGISTER_MIB("res_snmp", asterisk_vars, variable4, asterisk_oid);
  809. snmp_register_callback(SNMP_CALLBACK_LIBRARY,
  810. SNMP_CALLBACK_SHUTDOWN,
  811. term_asterisk_mib, NULL);
  812. }
  813. /*
  814. * Local Variables:
  815. * c-basic-offset: 4
  816. * c-file-offsets: ((case-label . 0))
  817. * tab-width: 4
  818. * indent-tabs-mode: t
  819. * End:
  820. */