agent.c 31 KB

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