agent.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905
  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(ast_channel_name(chan))) {
  227. ast_copy_string(string_ret, ast_channel_name(chan), sizeof(string_ret));
  228. *var_len = strlen(string_ret);
  229. ret = (u_char *)string_ret;
  230. }
  231. break;
  232. case ASTCHANLANGUAGE:
  233. if (!ast_strlen_zero(ast_channel_language(chan))) {
  234. ast_copy_string(string_ret, ast_channel_language(chan), sizeof(string_ret));
  235. *var_len = strlen(string_ret);
  236. ret = (u_char *)string_ret;
  237. }
  238. break;
  239. case ASTCHANTYPE:
  240. ast_copy_string(string_ret, ast_channel_tech(chan)->type, sizeof(string_ret));
  241. *var_len = strlen(string_ret);
  242. ret = (u_char *)string_ret;
  243. break;
  244. case ASTCHANMUSICCLASS:
  245. if (!ast_strlen_zero(ast_channel_musicclass(chan))) {
  246. ast_copy_string(string_ret, ast_channel_musicclass(chan), sizeof(string_ret));
  247. *var_len = strlen(string_ret);
  248. ret = (u_char *)string_ret;
  249. }
  250. break;
  251. case ASTCHANBRIDGE:
  252. if ((bridge = ast_channel_bridge_peer(chan)) != NULL) {
  253. ast_copy_string(string_ret, ast_channel_name(bridge), sizeof(string_ret));
  254. *var_len = strlen(string_ret);
  255. ret = (u_char *)string_ret;
  256. ast_channel_unref(bridge);
  257. }
  258. break;
  259. case ASTCHANMASQ:
  260. if (ast_channel_masq(chan) && !ast_strlen_zero(ast_channel_name(ast_channel_masq(chan)))) {
  261. ast_copy_string(string_ret, ast_channel_name(ast_channel_masq(chan)), sizeof(string_ret));
  262. *var_len = strlen(string_ret);
  263. ret = (u_char *)string_ret;
  264. }
  265. break;
  266. case ASTCHANMASQR:
  267. if (ast_channel_masqr(chan) && !ast_strlen_zero(ast_channel_name(ast_channel_masqr(chan)))) {
  268. ast_copy_string(string_ret, ast_channel_name(ast_channel_masqr(chan)), sizeof(string_ret));
  269. *var_len = strlen(string_ret);
  270. ret = (u_char *)string_ret;
  271. }
  272. break;
  273. case ASTCHANWHENHANGUP:
  274. if (!ast_tvzero(*ast_channel_whentohangup(chan))) {
  275. gettimeofday(&tval, NULL);
  276. long_ret = difftime(ast_channel_whentohangup(chan)->tv_sec, tval.tv_sec) * 100 - tval.tv_usec / 10000;
  277. ret= (u_char *)&long_ret;
  278. }
  279. break;
  280. case ASTCHANAPP:
  281. if (ast_channel_appl(chan)) {
  282. ast_copy_string(string_ret, ast_channel_appl(chan), sizeof(string_ret));
  283. *var_len = strlen(string_ret);
  284. ret = (u_char *)string_ret;
  285. }
  286. break;
  287. case ASTCHANDATA:
  288. if (ast_channel_data(chan)) {
  289. ast_copy_string(string_ret, ast_channel_data(chan), sizeof(string_ret));
  290. *var_len = strlen(string_ret);
  291. ret = (u_char *)string_ret;
  292. }
  293. break;
  294. case ASTCHANCONTEXT:
  295. ast_copy_string(string_ret, ast_channel_context(chan), sizeof(string_ret));
  296. *var_len = strlen(string_ret);
  297. ret = (u_char *)string_ret;
  298. break;
  299. case ASTCHANMACROCONTEXT:
  300. ast_copy_string(string_ret, ast_channel_macrocontext(chan), sizeof(string_ret));
  301. *var_len = strlen(string_ret);
  302. ret = (u_char *)string_ret;
  303. break;
  304. case ASTCHANMACROEXTEN:
  305. ast_copy_string(string_ret, ast_channel_macroexten(chan), sizeof(string_ret));
  306. *var_len = strlen(string_ret);
  307. ret = (u_char *)string_ret;
  308. break;
  309. case ASTCHANMACROPRI:
  310. long_ret = ast_channel_macropriority(chan);
  311. ret = (u_char *)&long_ret;
  312. break;
  313. case ASTCHANEXTEN:
  314. ast_copy_string(string_ret, ast_channel_exten(chan), sizeof(string_ret));
  315. *var_len = strlen(string_ret);
  316. ret = (u_char *)string_ret;
  317. break;
  318. case ASTCHANPRI:
  319. long_ret = ast_channel_priority(chan);
  320. ret = (u_char *)&long_ret;
  321. break;
  322. case ASTCHANACCOUNTCODE:
  323. if (!ast_strlen_zero(ast_channel_accountcode(chan))) {
  324. ast_copy_string(string_ret, ast_channel_accountcode(chan), sizeof(string_ret));
  325. *var_len = strlen(string_ret);
  326. ret = (u_char *)string_ret;
  327. }
  328. break;
  329. case ASTCHANFORWARDTO:
  330. if (!ast_strlen_zero(ast_channel_call_forward(chan))) {
  331. ast_copy_string(string_ret, ast_channel_call_forward(chan), sizeof(string_ret));
  332. *var_len = strlen(string_ret);
  333. ret = (u_char *)string_ret;
  334. }
  335. break;
  336. case ASTCHANUNIQUEID:
  337. ast_copy_string(string_ret, ast_channel_uniqueid(chan), sizeof(string_ret));
  338. *var_len = strlen(string_ret);
  339. ret = (u_char *)string_ret;
  340. break;
  341. case ASTCHANCALLGROUP:
  342. long_ret = ast_channel_callgroup(chan);
  343. ret = (u_char *)&long_ret;
  344. break;
  345. case ASTCHANPICKUPGROUP:
  346. long_ret = ast_channel_pickupgroup(chan);
  347. ret = (u_char *)&long_ret;
  348. break;
  349. case ASTCHANSTATE:
  350. long_ret = ast_channel_state(chan) & 0xffff;
  351. ret = (u_char *)&long_ret;
  352. break;
  353. case ASTCHANMUTED:
  354. long_ret = ast_channel_state(chan) & AST_STATE_MUTE ? 1 : 2;
  355. ret = (u_char *)&long_ret;
  356. break;
  357. case ASTCHANRINGS:
  358. long_ret = ast_channel_rings(chan);
  359. ret = (u_char *)&long_ret;
  360. break;
  361. case ASTCHANCIDDNID:
  362. if (ast_channel_dialed(chan)->number.str) {
  363. ast_copy_string(string_ret, ast_channel_dialed(chan)->number.str, sizeof(string_ret));
  364. *var_len = strlen(string_ret);
  365. ret = (u_char *)string_ret;
  366. }
  367. break;
  368. case ASTCHANCIDNUM:
  369. if (ast_channel_caller(chan)->id.number.valid && ast_channel_caller(chan)->id.number.str) {
  370. ast_copy_string(string_ret, ast_channel_caller(chan)->id.number.str, sizeof(string_ret));
  371. *var_len = strlen(string_ret);
  372. ret = (u_char *)string_ret;
  373. }
  374. break;
  375. case ASTCHANCIDNAME:
  376. if (ast_channel_caller(chan)->id.name.valid && ast_channel_caller(chan)->id.name.str) {
  377. ast_copy_string(string_ret, ast_channel_caller(chan)->id.name.str, sizeof(string_ret));
  378. *var_len = strlen(string_ret);
  379. ret = (u_char *)string_ret;
  380. }
  381. break;
  382. case ASTCHANCIDANI:
  383. if (ast_channel_caller(chan)->ani.number.valid && ast_channel_caller(chan)->ani.number.str) {
  384. ast_copy_string(string_ret, ast_channel_caller(chan)->ani.number.str, sizeof(string_ret));
  385. *var_len = strlen(string_ret);
  386. ret = (u_char *)string_ret;
  387. }
  388. break;
  389. case ASTCHANCIDRDNIS:
  390. if (ast_channel_redirecting(chan)->from.number.valid && ast_channel_redirecting(chan)->from.number.str) {
  391. ast_copy_string(string_ret, ast_channel_redirecting(chan)->from.number.str, sizeof(string_ret));
  392. *var_len = strlen(string_ret);
  393. ret = (u_char *)string_ret;
  394. }
  395. break;
  396. case ASTCHANCIDPRES:
  397. long_ret = ast_party_id_presentation(&ast_channel_caller(chan)->id);
  398. ret = (u_char *)&long_ret;
  399. break;
  400. case ASTCHANCIDANI2:
  401. long_ret = ast_channel_caller(chan)->ani2;
  402. ret = (u_char *)&long_ret;
  403. break;
  404. case ASTCHANCIDTON:
  405. long_ret = ast_channel_caller(chan)->id.number.plan;
  406. ret = (u_char *)&long_ret;
  407. break;
  408. case ASTCHANCIDTNS:
  409. long_ret = ast_channel_dialed(chan)->transit_network_select;
  410. ret = (u_char *)&long_ret;
  411. break;
  412. case ASTCHANAMAFLAGS:
  413. long_ret = ast_channel_amaflags(chan);
  414. ret = (u_char *)&long_ret;
  415. break;
  416. case ASTCHANADSI:
  417. long_ret = ast_channel_adsicpe(chan);
  418. ret = (u_char *)&long_ret;
  419. break;
  420. case ASTCHANTONEZONE:
  421. if (ast_channel_zone(chan)) {
  422. ast_copy_string(string_ret, ast_channel_zone(chan)->country, sizeof(string_ret));
  423. *var_len = strlen(string_ret);
  424. ret = (u_char *)string_ret;
  425. }
  426. break;
  427. case ASTCHANHANGUPCAUSE:
  428. long_ret = ast_channel_hangupcause(chan);
  429. ret = (u_char *)&long_ret;
  430. break;
  431. case ASTCHANVARIABLES:
  432. if (pbx_builtin_serialize_variables(chan, &out)) {
  433. *var_len = ast_str_strlen(out);
  434. ret = (u_char *)ast_str_buffer(out);
  435. }
  436. break;
  437. case ASTCHANFLAGS:
  438. bits_ret[0] = 0;
  439. for (bit = 0; bit < 8; bit++)
  440. bits_ret[0] |= ((ast_channel_flags(chan)->flags & (1 << bit)) >> bit) << (7 - bit);
  441. bits_ret[1] = 0;
  442. for (bit = 0; bit < 8; bit++)
  443. bits_ret[1] |= (((ast_channel_flags(chan)->flags >> 8) & (1 << bit)) >> bit) << (7 - bit);
  444. *var_len = 2;
  445. ret = bits_ret;
  446. break;
  447. case ASTCHANTRANSFERCAP:
  448. long_ret = ast_channel_transfercapability(chan);
  449. ret = (u_char *)&long_ret;
  450. default:
  451. break;
  452. }
  453. ast_channel_unlock(chan);
  454. chan = ast_channel_unref(chan);
  455. return ret;
  456. }
  457. static u_char *ast_var_channel_types(struct variable *vp, oid *name, size_t *length,
  458. int exact, size_t *var_len, WriteMethod **write_method)
  459. {
  460. static unsigned long long_ret;
  461. struct ast_variable *channel_types, *next;
  462. if (header_generic(vp, name, length, exact, var_len, write_method))
  463. return NULL;
  464. if (vp->magic != ASTCHANTYPECOUNT)
  465. return NULL;
  466. for (long_ret = 0, channel_types = next = ast_channeltype_list(); next; next = next->next)
  467. long_ret++;
  468. ast_variables_destroy(channel_types);
  469. return (u_char *)&long_ret;
  470. }
  471. static u_char *ast_var_channel_types_table(struct variable *vp, oid *name, size_t *length,
  472. int exact, size_t *var_len, WriteMethod **write_method)
  473. {
  474. const struct ast_channel_tech *tech = NULL;
  475. struct ast_variable *channel_types, *next;
  476. static unsigned long long_ret;
  477. struct ast_channel *chan;
  478. u_long i;
  479. if (header_simple_table(vp, name, length, exact, var_len, write_method, -1))
  480. return NULL;
  481. channel_types = ast_channeltype_list();
  482. for (i = 1, next = channel_types; next && i != name[*length - 1]; next = next->next, i++)
  483. ;
  484. if (next != NULL)
  485. tech = ast_get_channel_tech(next->name);
  486. ast_variables_destroy(channel_types);
  487. if (next == NULL || tech == NULL)
  488. return NULL;
  489. switch (vp->magic) {
  490. case ASTCHANTYPEINDEX:
  491. long_ret = name[*length - 1];
  492. return (u_char *)&long_ret;
  493. case ASTCHANTYPENAME:
  494. *var_len = strlen(tech->type);
  495. return (u_char *)tech->type;
  496. case ASTCHANTYPEDESC:
  497. *var_len = strlen(tech->description);
  498. return (u_char *)tech->description;
  499. case ASTCHANTYPEDEVSTATE:
  500. long_ret = tech->devicestate ? 1 : 2;
  501. return (u_char *)&long_ret;
  502. case ASTCHANTYPEINDICATIONS:
  503. long_ret = tech->indicate ? 1 : 2;
  504. return (u_char *)&long_ret;
  505. case ASTCHANTYPETRANSFER:
  506. long_ret = tech->transfer ? 1 : 2;
  507. return (u_char *)&long_ret;
  508. case ASTCHANTYPECHANNELS:
  509. {
  510. struct ast_channel_iterator *iter;
  511. long_ret = 0;
  512. if (!(iter = ast_channel_iterator_all_new())) {
  513. return NULL;
  514. }
  515. while ((chan = ast_channel_iterator_next(iter))) {
  516. if (ast_channel_tech(chan) == tech) {
  517. long_ret++;
  518. }
  519. chan = ast_channel_unref(chan);
  520. }
  521. ast_channel_iterator_destroy(iter);
  522. return (u_char *)&long_ret;
  523. }
  524. default:
  525. break;
  526. }
  527. return NULL;
  528. }
  529. static u_char *ast_var_channel_bridge(struct variable *vp, oid *name, size_t *length,
  530. int exact, size_t *var_len, WriteMethod **write_method)
  531. {
  532. static unsigned long long_ret;
  533. struct ast_channel *chan = NULL;
  534. struct ast_channel_iterator *iter;
  535. long_ret = 0;
  536. if (header_generic(vp, name, length, exact, var_len, write_method)) {
  537. return NULL;
  538. }
  539. if (!(iter = ast_channel_iterator_all_new())) {
  540. return NULL;
  541. }
  542. while ((chan = ast_channel_iterator_next(iter))) {
  543. ast_channel_lock(chan);
  544. if (ast_channel_is_bridged(chan)) {
  545. long_ret++;
  546. }
  547. ast_channel_unlock(chan);
  548. chan = ast_channel_unref(chan);
  549. }
  550. ast_channel_iterator_destroy(iter);
  551. *var_len = sizeof(long_ret);
  552. return (vp->magic == ASTCHANBRIDGECOUNT) ? (u_char *) &long_ret : NULL;
  553. }
  554. static u_char *ast_var_Config(struct variable *vp, oid *name, size_t *length,
  555. int exact, size_t *var_len, WriteMethod **write_method)
  556. {
  557. static unsigned long long_ret;
  558. struct timeval tval;
  559. if (header_generic(vp, name, length, exact, var_len, write_method))
  560. return NULL;
  561. switch (vp->magic) {
  562. case ASTCONFUPTIME:
  563. gettimeofday(&tval, NULL);
  564. long_ret = difftime(tval.tv_sec, ast_startuptime.tv_sec) * 100 + tval.tv_usec / 10000 - ast_startuptime.tv_usec / 10000;
  565. return (u_char *)&long_ret;
  566. case ASTCONFRELOADTIME:
  567. gettimeofday(&tval, NULL);
  568. if (ast_lastreloadtime.tv_sec)
  569. long_ret = difftime(tval.tv_sec, ast_lastreloadtime.tv_sec) * 100 + tval.tv_usec / 10000 - ast_lastreloadtime.tv_usec / 10000;
  570. else
  571. long_ret = difftime(tval.tv_sec, ast_startuptime.tv_sec) * 100 + tval.tv_usec / 10000 - ast_startuptime.tv_usec / 10000;
  572. return (u_char *)&long_ret;
  573. case ASTCONFPID:
  574. long_ret = getpid();
  575. return (u_char *)&long_ret;
  576. case ASTCONFSOCKET:
  577. *var_len = strlen(ast_config_AST_SOCKET);
  578. return (u_char *)ast_config_AST_SOCKET;
  579. case ASTCONFACTIVECALLS:
  580. long_ret = ast_active_calls();
  581. return (u_char *)&long_ret;
  582. case ASTCONFPROCESSEDCALLS:
  583. long_ret = ast_processed_calls();
  584. return (u_char *)&long_ret;
  585. default:
  586. break;
  587. }
  588. return NULL;
  589. }
  590. static u_char *ast_var_indications(struct variable *vp, oid *name, size_t *length,
  591. int exact, size_t *var_len, WriteMethod **write_method)
  592. {
  593. static unsigned long long_ret;
  594. static char ret_buf[128];
  595. struct ast_tone_zone *tz = NULL;
  596. if (header_generic(vp, name, length, exact, var_len, write_method))
  597. return NULL;
  598. switch (vp->magic) {
  599. case ASTINDCOUNT:
  600. {
  601. struct ao2_iterator i;
  602. long_ret = 0;
  603. i = ast_tone_zone_iterator_init();
  604. while ((tz = ao2_iterator_next(&i))) {
  605. tz = ast_tone_zone_unref(tz);
  606. long_ret++;
  607. }
  608. ao2_iterator_destroy(&i);
  609. return (u_char *) &long_ret;
  610. }
  611. case ASTINDCURRENT:
  612. tz = ast_get_indication_zone(NULL);
  613. if (tz) {
  614. ast_copy_string(ret_buf, tz->country, sizeof(ret_buf));
  615. *var_len = strlen(ret_buf);
  616. tz = ast_tone_zone_unref(tz);
  617. return (u_char *) ret_buf;
  618. }
  619. *var_len = 0;
  620. return NULL;
  621. default:
  622. break;
  623. }
  624. return NULL;
  625. }
  626. static u_char *ast_var_indications_table(struct variable *vp, oid *name, size_t *length,
  627. int exact, size_t *var_len, WriteMethod **write_method)
  628. {
  629. static unsigned long long_ret;
  630. static char ret_buf[256];
  631. struct ast_tone_zone *tz = NULL;
  632. int i;
  633. struct ao2_iterator iter;
  634. if (header_simple_table(vp, name, length, exact, var_len, write_method, -1)) {
  635. return NULL;
  636. }
  637. i = name[*length - 1] - 1;
  638. iter = ast_tone_zone_iterator_init();
  639. while ((tz = ao2_iterator_next(&iter)) && i) {
  640. tz = ast_tone_zone_unref(tz);
  641. i--;
  642. }
  643. ao2_iterator_destroy(&iter);
  644. if (tz == NULL) {
  645. return NULL;
  646. }
  647. switch (vp->magic) {
  648. case ASTINDINDEX:
  649. ast_tone_zone_unref(tz);
  650. long_ret = name[*length - 1];
  651. return (u_char *)&long_ret;
  652. case ASTINDCOUNTRY:
  653. ast_copy_string(ret_buf, tz->country, sizeof(ret_buf));
  654. ast_tone_zone_unref(tz);
  655. *var_len = strlen(ret_buf);
  656. return (u_char *) ret_buf;
  657. case ASTINDALIAS:
  658. /* No longer exists */
  659. ast_tone_zone_unref(tz);
  660. return NULL;
  661. case ASTINDDESCRIPTION:
  662. ast_tone_zone_lock(tz);
  663. ast_copy_string(ret_buf, tz->description, sizeof(ret_buf));
  664. ast_tone_zone_unlock(tz);
  665. ast_tone_zone_unref(tz);
  666. *var_len = strlen(ret_buf);
  667. return (u_char *) ret_buf;
  668. default:
  669. ast_tone_zone_unref(tz);
  670. break;
  671. }
  672. return NULL;
  673. }
  674. static int countmodule(const char *mod, const char *desc, int use, const char *status,
  675. const char *like, enum ast_module_support_level support_level)
  676. {
  677. return 1;
  678. }
  679. static u_char *ast_var_Modules(struct variable *vp, oid *name, size_t *length,
  680. int exact, size_t *var_len, WriteMethod **write_method)
  681. {
  682. static unsigned long long_ret;
  683. if (header_generic(vp, name, length, exact, var_len, write_method))
  684. return NULL;
  685. if (vp->magic != ASTMODCOUNT)
  686. return NULL;
  687. long_ret = ast_update_module_list(countmodule, NULL);
  688. return (u_char *)&long_ret;
  689. }
  690. static u_char *ast_var_Version(struct variable *vp, oid *name, size_t *length,
  691. int exact, size_t *var_len, WriteMethod **write_method)
  692. {
  693. static unsigned long long_ret;
  694. if (header_generic(vp, name, length, exact, var_len, write_method))
  695. return NULL;
  696. switch (vp->magic) {
  697. case ASTVERSTRING:
  698. {
  699. const char *version = ast_get_version();
  700. *var_len = strlen(version);
  701. return (u_char *)version;
  702. }
  703. case ASTVERTAG:
  704. sscanf(ast_get_version_num(), "%30lu", &long_ret);
  705. return (u_char *)&long_ret;
  706. default:
  707. break;
  708. }
  709. return NULL;
  710. }
  711. static int term_asterisk_mib(int majorID, int minorID, void *serverarg, void *clientarg)
  712. {
  713. unregister_sysORTable(asterisk_oid, OID_LENGTH(asterisk_oid));
  714. return 0;
  715. }
  716. static void init_asterisk_mib(void)
  717. {
  718. static struct variable4 asterisk_vars[] = {
  719. {ASTVERSTRING, ASN_OCTET_STR, RONLY, ast_var_Version, 2, {ASTVERSION, ASTVERSTRING}},
  720. {ASTVERTAG, ASN_UNSIGNED, RONLY, ast_var_Version, 2, {ASTVERSION, ASTVERTAG}},
  721. {ASTCONFUPTIME, ASN_TIMETICKS, RONLY, ast_var_Config, 2, {ASTCONFIGURATION, ASTCONFUPTIME}},
  722. {ASTCONFRELOADTIME, ASN_TIMETICKS, RONLY, ast_var_Config, 2, {ASTCONFIGURATION, ASTCONFRELOADTIME}},
  723. {ASTCONFPID, ASN_INTEGER, RONLY, ast_var_Config, 2, {ASTCONFIGURATION, ASTCONFPID}},
  724. {ASTCONFSOCKET, ASN_OCTET_STR, RONLY, ast_var_Config, 2, {ASTCONFIGURATION, ASTCONFSOCKET}},
  725. {ASTCONFACTIVECALLS, ASN_GAUGE, RONLY, ast_var_Config, 2, {ASTCONFIGURATION, ASTCONFACTIVECALLS}},
  726. {ASTCONFPROCESSEDCALLS, ASN_COUNTER, RONLY, ast_var_Config, 2, {ASTCONFIGURATION, ASTCONFPROCESSEDCALLS}},
  727. {ASTMODCOUNT, ASN_INTEGER, RONLY, ast_var_Modules , 2, {ASTMODULES, ASTMODCOUNT}},
  728. {ASTINDCOUNT, ASN_INTEGER, RONLY, ast_var_indications, 2, {ASTINDICATIONS, ASTINDCOUNT}},
  729. {ASTINDCURRENT, ASN_OCTET_STR, RONLY, ast_var_indications, 2, {ASTINDICATIONS, ASTINDCURRENT}},
  730. {ASTINDINDEX, ASN_INTEGER, RONLY, ast_var_indications_table, 4, {ASTINDICATIONS, ASTINDTABLE, 1, ASTINDINDEX}},
  731. {ASTINDCOUNTRY, ASN_OCTET_STR, RONLY, ast_var_indications_table, 4, {ASTINDICATIONS, ASTINDTABLE, 1, ASTINDCOUNTRY}},
  732. {ASTINDALIAS, ASN_OCTET_STR, RONLY, ast_var_indications_table, 4, {ASTINDICATIONS, ASTINDTABLE, 1, ASTINDALIAS}},
  733. {ASTINDDESCRIPTION, ASN_OCTET_STR, RONLY, ast_var_indications_table, 4, {ASTINDICATIONS, ASTINDTABLE, 1, ASTINDDESCRIPTION}},
  734. {ASTCHANCOUNT, ASN_GAUGE, RONLY, ast_var_channels, 2, {ASTCHANNELS, ASTCHANCOUNT}},
  735. {ASTCHANINDEX, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANINDEX}},
  736. {ASTCHANNAME, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANNAME}},
  737. {ASTCHANLANGUAGE, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANLANGUAGE}},
  738. {ASTCHANTYPE, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANTYPE}},
  739. {ASTCHANMUSICCLASS, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANMUSICCLASS}},
  740. {ASTCHANBRIDGE, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANBRIDGE}},
  741. {ASTCHANMASQ, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANMASQ}},
  742. {ASTCHANMASQR, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANMASQR}},
  743. {ASTCHANWHENHANGUP, ASN_TIMETICKS, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANWHENHANGUP}},
  744. {ASTCHANAPP, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANAPP}},
  745. {ASTCHANDATA, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANDATA}},
  746. {ASTCHANCONTEXT, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCONTEXT}},
  747. {ASTCHANMACROCONTEXT, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANMACROCONTEXT}},
  748. {ASTCHANMACROEXTEN, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANMACROEXTEN}},
  749. {ASTCHANMACROPRI, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANMACROPRI}},
  750. {ASTCHANEXTEN, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANEXTEN}},
  751. {ASTCHANPRI, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANPRI}},
  752. {ASTCHANACCOUNTCODE, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANACCOUNTCODE}},
  753. {ASTCHANFORWARDTO, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANFORWARDTO}},
  754. {ASTCHANUNIQUEID, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANUNIQUEID}},
  755. {ASTCHANCALLGROUP, ASN_UNSIGNED, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCALLGROUP}},
  756. {ASTCHANPICKUPGROUP, ASN_UNSIGNED, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANPICKUPGROUP}},
  757. {ASTCHANSTATE, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANSTATE}},
  758. {ASTCHANMUTED, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANMUTED}},
  759. {ASTCHANRINGS, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANRINGS}},
  760. {ASTCHANCIDDNID, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDDNID}},
  761. {ASTCHANCIDNUM, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDNUM}},
  762. {ASTCHANCIDNAME, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDNAME}},
  763. {ASTCHANCIDANI, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDANI}},
  764. {ASTCHANCIDRDNIS, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDRDNIS}},
  765. {ASTCHANCIDPRES, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDPRES}},
  766. {ASTCHANCIDANI2, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDANI2}},
  767. {ASTCHANCIDTON, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDTON}},
  768. {ASTCHANCIDTNS, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDTNS}},
  769. {ASTCHANAMAFLAGS, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANAMAFLAGS}},
  770. {ASTCHANADSI, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANADSI}},
  771. {ASTCHANTONEZONE, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANTONEZONE}},
  772. {ASTCHANHANGUPCAUSE, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANHANGUPCAUSE}},
  773. {ASTCHANVARIABLES, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANVARIABLES}},
  774. {ASTCHANFLAGS, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANFLAGS}},
  775. {ASTCHANTRANSFERCAP, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANTRANSFERCAP}},
  776. {ASTCHANTYPECOUNT, ASN_INTEGER, RONLY, ast_var_channel_types, 2, {ASTCHANNELS, ASTCHANTYPECOUNT}},
  777. {ASTCHANTYPEINDEX, ASN_INTEGER, RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPEINDEX}},
  778. {ASTCHANTYPENAME, ASN_OCTET_STR, RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPENAME}},
  779. {ASTCHANTYPEDESC, ASN_OCTET_STR, RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPEDESC}},
  780. {ASTCHANTYPEDEVSTATE, ASN_INTEGER, RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPEDEVSTATE}},
  781. {ASTCHANTYPEINDICATIONS, ASN_INTEGER, RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPEINDICATIONS}},
  782. {ASTCHANTYPETRANSFER, ASN_INTEGER, RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPETRANSFER}},
  783. {ASTCHANTYPECHANNELS, ASN_GAUGE, RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPECHANNELS}},
  784. {ASTCHANBRIDGECOUNT, ASN_GAUGE, RONLY, ast_var_channel_bridge, 3, {ASTCHANNELS, ASTCHANSCALARS, ASTCHANBRIDGECOUNT}},
  785. };
  786. register_sysORTable(asterisk_oid, OID_LENGTH(asterisk_oid),
  787. "ASTERISK-MIB implementation for Asterisk.");
  788. REGISTER_MIB("res_snmp", asterisk_vars, variable4, asterisk_oid);
  789. snmp_register_callback(SNMP_CALLBACK_LIBRARY,
  790. SNMP_CALLBACK_SHUTDOWN,
  791. term_asterisk_mib, NULL);
  792. }
  793. /*
  794. * Local Variables:
  795. * c-basic-offset: 4
  796. * c-file-offsets: ((case-label . 0))
  797. * tab-width: 4
  798. * indent-tabs-mode: t
  799. * End:
  800. */