Asterisk - The Open Source Telephony Project  21.4.1
agent.c
Go to the documentation of this file.
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 
10 /*! \file
11  *
12  * \brief SNMP Agent / SubAgent support for Asterisk
13  *
14  * \author Thorsten Lockert <tholo@voop.as>
15  */
16 
17 /*** MODULEINFO
18  <support_level>extended</support_level>
19  ***/
20 
21 /* Needed for net-snmp headers */
22 #define ASTMM_LIBC ASTMM_IGNORE
23 #include "asterisk.h"
24 
25 /*
26  * There is some collision collision between netsmp and asterisk names,
27  * causing build under AST_DEVMODE to fail.
28  *
29  * The following PACKAGE_* macros are one place.
30  * Also netsnmp has an improper check for HAVE_DMALLOC_H, using
31  * #if HAVE_DMALLOC_H instead of #ifdef HAVE_DMALLOC_H
32  * As a countermeasure we define it to 0, however this will fail
33  * when the proper check is implemented.
34  */
35 #ifdef PACKAGE_NAME
36 #undef PACKAGE_NAME
37 #endif
38 #ifdef PACKAGE_BUGREPORT
39 #undef PACKAGE_BUGREPORT
40 #endif
41 #ifdef PACKAGE_STRING
42 #undef PACKAGE_STRING
43 #endif
44 #ifdef PACKAGE_TARNAME
45 #undef PACKAGE_TARNAME
46 #endif
47 #ifdef PACKAGE_VERSION
48 #undef PACKAGE_VERSION
49 #endif
50 #ifndef HAVE_DMALLOC_H
51 #define HAVE_DMALLOC_H 0 /* XXX we shouldn't do this */
52 #endif
53 
54 #if defined(__OpenBSD__)
55 /*
56  * OpenBSD uses old "legacy" cc which has a rather pedantic builtin preprocessor.
57  * Using a macro which is not #defined throws an error.
58  */
59 #define __NetBSD_Version__ 0
60 #endif
61 
62 #include <net-snmp/net-snmp-config.h>
63 #include <net-snmp/net-snmp-includes.h>
64 #include <net-snmp/agent/net-snmp-agent-includes.h>
65 
66 #if !defined(RONLY) && defined(NETSNMP_OLDAPI_RONLY)
67 #define RONLY NETSNMP_OLDAPI_RONLY
68 #endif
69 
70 #include "asterisk/paths.h" /* need ast_config_AST_SOCKET */
71 #include "asterisk/channel.h"
72 #include "asterisk/logger.h"
73 #include "asterisk/options.h"
74 #include "asterisk/indications.h"
75 #include "asterisk/ast_version.h"
76 #include "asterisk/pbx.h"
77 
78 /* Collision between Net-SNMP and Asterisk */
79 #define unload_module ast_unload_module
80 #include "asterisk/module.h"
81 #undef unload_module
82 
83 #include "agent.h"
84 
85 /* Helper functions in Net-SNMP, header file not installed by default */
86 int header_generic(struct variable *, oid *, size_t *, int, size_t *, WriteMethod **);
87 int header_simple_table(struct variable *, oid *, size_t *, int, size_t *, WriteMethod **, int);
88 int register_sysORTable(oid *, size_t, const char *);
89 int unregister_sysORTable(oid *, size_t);
90 
91 /* Forward declaration */
92 static void init_asterisk_mib(void);
93 
94 /*
95  * Anchor for all the Asterisk MIB values
96  */
97 static oid asterisk_oid[] = { 1, 3, 6, 1, 4, 1, 22736, 1 };
98 
99 /*
100  * MIB values -- these correspond to values in the Asterisk MIB,
101  * and MUST be kept in sync with the MIB for things to work as
102  * expected.
103  */
104 #define ASTVERSION 1
105 #define ASTVERSTRING 1
106 #define ASTVERTAG 2
107 
108 #define ASTCONFIGURATION 2
109 #define ASTCONFUPTIME 1
110 #define ASTCONFRELOADTIME 2
111 #define ASTCONFPID 3
112 #define ASTCONFSOCKET 4
113 #define ASTCONFACTIVECALLS 5
114 #define ASTCONFPROCESSEDCALLS 6
115 
116 #define ASTMODULES 3
117 #define ASTMODCOUNT 1
118 
119 #define ASTINDICATIONS 4
120 #define ASTINDCOUNT 1
121 #define ASTINDCURRENT 2
122 
123 #define ASTINDTABLE 3
124 #define ASTINDINDEX 1
125 #define ASTINDCOUNTRY 2
126 #define ASTINDALIAS 3
127 #define ASTINDDESCRIPTION 4
128 
129 #define ASTCHANNELS 5
130 #define ASTCHANCOUNT 1
131 
132 #define ASTCHANTABLE 2
133 #define ASTCHANINDEX 1
134 #define ASTCHANNAME 2
135 #define ASTCHANLANGUAGE 3
136 #define ASTCHANTYPE 4
137 #define ASTCHANMUSICCLASS 5
138 #define ASTCHANBRIDGE 6
139 #define ASTCHANMASQ 7
140 #define ASTCHANMASQR 8
141 #define ASTCHANWHENHANGUP 9
142 #define ASTCHANAPP 10
143 #define ASTCHANDATA 11
144 #define ASTCHANCONTEXT 12
145 #define ASTCHANEXTEN 16
146 #define ASTCHANPRI 17
147 #define ASTCHANACCOUNTCODE 18
148 #define ASTCHANFORWARDTO 19
149 #define ASTCHANUNIQUEID 20
150 #define ASTCHANCALLGROUP 21
151 #define ASTCHANPICKUPGROUP 22
152 #define ASTCHANSTATE 23
153 #define ASTCHANMUTED 24
154 #define ASTCHANRINGS 25
155 #define ASTCHANCIDDNID 26
156 #define ASTCHANCIDNUM 27
157 #define ASTCHANCIDNAME 28
158 #define ASTCHANCIDANI 29
159 #define ASTCHANCIDRDNIS 30
160 #define ASTCHANCIDPRES 31
161 #define ASTCHANCIDANI2 32
162 #define ASTCHANCIDTON 33
163 #define ASTCHANCIDTNS 34
164 #define ASTCHANAMAFLAGS 35
165 #define ASTCHANADSI 36
166 #define ASTCHANTONEZONE 37
167 #define ASTCHANHANGUPCAUSE 38
168 #define ASTCHANVARIABLES 39
169 #define ASTCHANFLAGS 40
170 #define ASTCHANTRANSFERCAP 41
171 
172 #define ASTCHANTYPECOUNT 3
173 
174 #define ASTCHANTYPETABLE 4
175 #define ASTCHANTYPEINDEX 1
176 #define ASTCHANTYPENAME 2
177 #define ASTCHANTYPEDESC 3
178 #define ASTCHANTYPEDEVSTATE 4
179 #define ASTCHANTYPEINDICATIONS 5
180 #define ASTCHANTYPETRANSFER 6
181 #define ASTCHANTYPECHANNELS 7
182 
183 #define ASTCHANSCALARS 5
184 #define ASTCHANBRIDGECOUNT 1
185 
186 void *agent_thread(void *arg)
187 {
188  ast_verb(2, "Starting %sAgent\n", res_snmp_agentx_subagent ? "Sub" : "");
189 
190  snmp_enable_stderrlog();
191 
192  if (res_snmp_agentx_subagent)
193  netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID,
194  NETSNMP_DS_AGENT_ROLE,
195  1);
196 
197  init_agent("asterisk");
198 
199  init_asterisk_mib();
200 
201  init_snmp("asterisk");
202 
203  if (!res_snmp_agentx_subagent)
204  init_master_agent();
205 
206  while (res_snmp_dont_stop)
207  agent_check_and_process(1);
208 
209  snmp_shutdown("asterisk");
210 
211  ast_verb(2, "Terminating %sAgent\n", res_snmp_agentx_subagent ? "Sub" : "");
212 
213  return NULL;
214 }
215 
216 static u_char *
217 ast_var_channels(struct variable *vp, oid *name, size_t *length,
218  int exact, size_t *var_len, WriteMethod **write_method)
219 {
220  static unsigned long long_ret;
221 
222  if (header_generic(vp, name, length, exact, var_len, write_method))
223  return NULL;
224 
225  if (vp->magic != ASTCHANCOUNT)
226  return NULL;
227 
228  long_ret = ast_active_channels();
229 
230  return (u_char *)&long_ret;
231 }
232 
233 static u_char *ast_var_channels_table(struct variable *vp, oid *name, size_t *length,
234  int exact, size_t *var_len, WriteMethod **write_method)
235 {
236  static unsigned long long_ret;
237  static u_char bits_ret[2];
238  static char string_ret[256];
239  struct ast_channel *chan, *bridge;
240  struct timeval tval;
241  u_char *ret = NULL;
242  int i, bit;
243  struct ast_str *out = ast_str_alloca(2048);
244  struct ast_channel_iterator *iter;
245 
246  if (header_simple_table(vp, name, length, exact, var_len, write_method, ast_active_channels()))
247  return NULL;
248 
249  i = name[*length - 1] - 1;
250 
251  if (!(iter = ast_channel_iterator_all_new())) {
252  return NULL;
253  }
254 
255  while ((chan = ast_channel_iterator_next(iter)) && i) {
256  ast_channel_unref(chan);
257  i--;
258  }
259 
260  iter = ast_channel_iterator_destroy(iter);
261 
262  if (chan == NULL) {
263  return NULL;
264  }
265 
266  *var_len = sizeof(long_ret);
267 
268  ast_channel_lock(chan);
269 
270  switch (vp->magic) {
271  case ASTCHANINDEX:
272  long_ret = name[*length - 1];
273  ret = (u_char *)&long_ret;
274  break;
275  case ASTCHANNAME:
276  if (!ast_strlen_zero(ast_channel_name(chan))) {
277  ast_copy_string(string_ret, ast_channel_name(chan), sizeof(string_ret));
278  *var_len = strlen(string_ret);
279  ret = (u_char *)string_ret;
280  }
281  break;
282  case ASTCHANLANGUAGE:
283  if (!ast_strlen_zero(ast_channel_language(chan))) {
284  ast_copy_string(string_ret, ast_channel_language(chan), sizeof(string_ret));
285  *var_len = strlen(string_ret);
286  ret = (u_char *)string_ret;
287  }
288  break;
289  case ASTCHANTYPE:
290  ast_copy_string(string_ret, ast_channel_tech(chan)->type, sizeof(string_ret));
291  *var_len = strlen(string_ret);
292  ret = (u_char *)string_ret;
293  break;
294  case ASTCHANMUSICCLASS:
295  if (!ast_strlen_zero(ast_channel_musicclass(chan))) {
296  ast_copy_string(string_ret, ast_channel_musicclass(chan), sizeof(string_ret));
297  *var_len = strlen(string_ret);
298  ret = (u_char *)string_ret;
299  }
300  break;
301  case ASTCHANBRIDGE:
302  ast_channel_unlock(chan);
303  bridge = ast_channel_bridge_peer(chan);
304  if (bridge) {
305  ast_channel_lock(bridge);
306  ast_copy_string(string_ret, ast_channel_name(bridge), sizeof(string_ret));
307  ast_channel_unlock(bridge);
308  ast_channel_unref(bridge);
309 
310  *var_len = strlen(string_ret);
311  ret = (u_char *)string_ret;
312  }
313  ast_channel_lock(chan);
314  break;
315  case ASTCHANMASQ:
316  if (ast_channel_masq(chan) && !ast_strlen_zero(ast_channel_name(ast_channel_masq(chan)))) {
317  ast_copy_string(string_ret, ast_channel_name(ast_channel_masq(chan)), sizeof(string_ret));
318  *var_len = strlen(string_ret);
319  ret = (u_char *)string_ret;
320  }
321  break;
322  case ASTCHANMASQR:
323  if (ast_channel_masqr(chan) && !ast_strlen_zero(ast_channel_name(ast_channel_masqr(chan)))) {
324  ast_copy_string(string_ret, ast_channel_name(ast_channel_masqr(chan)), sizeof(string_ret));
325  *var_len = strlen(string_ret);
326  ret = (u_char *)string_ret;
327  }
328  break;
329  case ASTCHANWHENHANGUP:
330  if (!ast_tvzero(*ast_channel_whentohangup(chan))) {
331  gettimeofday(&tval, NULL);
332  long_ret = difftime(ast_channel_whentohangup(chan)->tv_sec, tval.tv_sec) * 100 - tval.tv_usec / 10000;
333  ret= (u_char *)&long_ret;
334  }
335  break;
336  case ASTCHANAPP:
337  if (ast_channel_appl(chan)) {
338  ast_copy_string(string_ret, ast_channel_appl(chan), sizeof(string_ret));
339  *var_len = strlen(string_ret);
340  ret = (u_char *)string_ret;
341  }
342  break;
343  case ASTCHANDATA:
344  if (ast_channel_data(chan)) {
345  ast_copy_string(string_ret, ast_channel_data(chan), sizeof(string_ret));
346  *var_len = strlen(string_ret);
347  ret = (u_char *)string_ret;
348  }
349  break;
350  case ASTCHANCONTEXT:
351  ast_copy_string(string_ret, ast_channel_context(chan), sizeof(string_ret));
352  *var_len = strlen(string_ret);
353  ret = (u_char *)string_ret;
354  break;
355  case ASTCHANEXTEN:
356  ast_copy_string(string_ret, ast_channel_exten(chan), sizeof(string_ret));
357  *var_len = strlen(string_ret);
358  ret = (u_char *)string_ret;
359  break;
360  case ASTCHANPRI:
361  long_ret = ast_channel_priority(chan);
362  ret = (u_char *)&long_ret;
363  break;
364  case ASTCHANACCOUNTCODE:
365  if (!ast_strlen_zero(ast_channel_accountcode(chan))) {
366  ast_copy_string(string_ret, ast_channel_accountcode(chan), sizeof(string_ret));
367  *var_len = strlen(string_ret);
368  ret = (u_char *)string_ret;
369  }
370  break;
371  case ASTCHANFORWARDTO:
372  if (!ast_strlen_zero(ast_channel_call_forward(chan))) {
373  ast_copy_string(string_ret, ast_channel_call_forward(chan), sizeof(string_ret));
374  *var_len = strlen(string_ret);
375  ret = (u_char *)string_ret;
376  }
377  break;
378  case ASTCHANUNIQUEID:
379  ast_copy_string(string_ret, ast_channel_uniqueid(chan), sizeof(string_ret));
380  *var_len = strlen(string_ret);
381  ret = (u_char *)string_ret;
382  break;
383  case ASTCHANCALLGROUP:
384  long_ret = ast_channel_callgroup(chan);
385  ret = (u_char *)&long_ret;
386  break;
387  case ASTCHANPICKUPGROUP:
388  long_ret = ast_channel_pickupgroup(chan);
389  ret = (u_char *)&long_ret;
390  break;
391  case ASTCHANSTATE:
392  long_ret = ast_channel_state(chan) & 0xffff;
393  ret = (u_char *)&long_ret;
394  break;
395  case ASTCHANMUTED:
396  long_ret = ast_channel_state(chan) & AST_STATE_MUTE ? 1 : 2;
397  ret = (u_char *)&long_ret;
398  break;
399  case ASTCHANRINGS:
400  long_ret = ast_channel_rings(chan);
401  ret = (u_char *)&long_ret;
402  break;
403  case ASTCHANCIDDNID:
404  if (ast_channel_dialed(chan)->number.str) {
405  ast_copy_string(string_ret, ast_channel_dialed(chan)->number.str, sizeof(string_ret));
406  *var_len = strlen(string_ret);
407  ret = (u_char *)string_ret;
408  }
409  break;
410  case ASTCHANCIDNUM:
411  if (ast_channel_caller(chan)->id.number.valid && ast_channel_caller(chan)->id.number.str) {
412  ast_copy_string(string_ret, ast_channel_caller(chan)->id.number.str, sizeof(string_ret));
413  *var_len = strlen(string_ret);
414  ret = (u_char *)string_ret;
415  }
416  break;
417  case ASTCHANCIDNAME:
418  if (ast_channel_caller(chan)->id.name.valid && ast_channel_caller(chan)->id.name.str) {
419  ast_copy_string(string_ret, ast_channel_caller(chan)->id.name.str, sizeof(string_ret));
420  *var_len = strlen(string_ret);
421  ret = (u_char *)string_ret;
422  }
423  break;
424  case ASTCHANCIDANI:
425  if (ast_channel_caller(chan)->ani.number.valid && ast_channel_caller(chan)->ani.number.str) {
426  ast_copy_string(string_ret, ast_channel_caller(chan)->ani.number.str, sizeof(string_ret));
427  *var_len = strlen(string_ret);
428  ret = (u_char *)string_ret;
429  }
430  break;
431  case ASTCHANCIDRDNIS:
432  if (ast_channel_redirecting(chan)->from.number.valid && ast_channel_redirecting(chan)->from.number.str) {
433  ast_copy_string(string_ret, ast_channel_redirecting(chan)->from.number.str, sizeof(string_ret));
434  *var_len = strlen(string_ret);
435  ret = (u_char *)string_ret;
436  }
437  break;
438  case ASTCHANCIDPRES:
439  long_ret = ast_party_id_presentation(&ast_channel_caller(chan)->id);
440  ret = (u_char *)&long_ret;
441  break;
442  case ASTCHANCIDANI2:
443  long_ret = ast_channel_caller(chan)->ani2;
444  ret = (u_char *)&long_ret;
445  break;
446  case ASTCHANCIDTON:
447  long_ret = ast_channel_caller(chan)->id.number.plan;
448  ret = (u_char *)&long_ret;
449  break;
450  case ASTCHANCIDTNS:
451  long_ret = ast_channel_dialed(chan)->transit_network_select;
452  ret = (u_char *)&long_ret;
453  break;
454  case ASTCHANAMAFLAGS:
455  long_ret = ast_channel_amaflags(chan);
456  ret = (u_char *)&long_ret;
457  break;
458  case ASTCHANADSI:
459  long_ret = ast_channel_adsicpe(chan);
460  ret = (u_char *)&long_ret;
461  break;
462  case ASTCHANTONEZONE:
463  if (ast_channel_zone(chan)) {
464  ast_copy_string(string_ret, ast_channel_zone(chan)->country, sizeof(string_ret));
465  *var_len = strlen(string_ret);
466  ret = (u_char *)string_ret;
467  }
468  break;
469  case ASTCHANHANGUPCAUSE:
470  long_ret = ast_channel_hangupcause(chan);
471  ret = (u_char *)&long_ret;
472  break;
473  case ASTCHANVARIABLES:
474  if (pbx_builtin_serialize_variables(chan, &out)) {
475  *var_len = ast_str_strlen(out);
476  ret = (u_char *)ast_str_buffer(out);
477  }
478  break;
479  case ASTCHANFLAGS:
480  bits_ret[0] = 0;
481  for (bit = 0; bit < 8; bit++)
482  bits_ret[0] |= ((ast_channel_flags(chan)->flags & (1 << bit)) >> bit) << (7 - bit);
483  bits_ret[1] = 0;
484  for (bit = 0; bit < 8; bit++)
485  bits_ret[1] |= (((ast_channel_flags(chan)->flags >> 8) & (1 << bit)) >> bit) << (7 - bit);
486  *var_len = 2;
487  ret = bits_ret;
488  break;
489  case ASTCHANTRANSFERCAP:
490  long_ret = ast_channel_transfercapability(chan);
491  ret = (u_char *)&long_ret;
492  default:
493  break;
494  }
495 
496  ast_channel_unlock(chan);
497  chan = ast_channel_unref(chan);
498 
499  return ret;
500 }
501 
502 static u_char *ast_var_channel_types(struct variable *vp, oid *name, size_t *length,
503  int exact, size_t *var_len, WriteMethod **write_method)
504 {
505  static unsigned long long_ret;
506  struct ast_variable *channel_types, *next;
507 
508  if (header_generic(vp, name, length, exact, var_len, write_method))
509  return NULL;
510 
511  if (vp->magic != ASTCHANTYPECOUNT)
512  return NULL;
513 
514  for (long_ret = 0, channel_types = next = ast_channeltype_list(); next; next = next->next)
515  long_ret++;
516  ast_variables_destroy(channel_types);
517 
518  return (u_char *)&long_ret;
519 }
520 
521 static u_char *ast_var_channel_types_table(struct variable *vp, oid *name, size_t *length,
522  int exact, size_t *var_len, WriteMethod **write_method)
523 {
524  const struct ast_channel_tech *tech = NULL;
525  struct ast_variable *channel_types, *next;
526  static unsigned long long_ret;
527  struct ast_channel *chan;
528  u_long i;
529 
530  if (header_simple_table(vp, name, length, exact, var_len, write_method, -1))
531  return NULL;
532 
533  channel_types = ast_channeltype_list();
534  for (i = 1, next = channel_types; next && i != name[*length - 1]; next = next->next, i++)
535  ;
536  if (next != NULL)
537  tech = ast_get_channel_tech(next->name);
538  ast_variables_destroy(channel_types);
539  if (next == NULL || tech == NULL)
540  return NULL;
541 
542  switch (vp->magic) {
543  case ASTCHANTYPEINDEX:
544  long_ret = name[*length - 1];
545  return (u_char *)&long_ret;
546  case ASTCHANTYPENAME:
547  *var_len = strlen(tech->type);
548  return (u_char *)tech->type;
549  case ASTCHANTYPEDESC:
550  *var_len = strlen(tech->description);
551  return (u_char *)tech->description;
552  case ASTCHANTYPEDEVSTATE:
553  long_ret = tech->devicestate ? 1 : 2;
554  return (u_char *)&long_ret;
555  case ASTCHANTYPEINDICATIONS:
556  long_ret = tech->indicate ? 1 : 2;
557  return (u_char *)&long_ret;
558  case ASTCHANTYPETRANSFER:
559  long_ret = tech->transfer ? 1 : 2;
560  return (u_char *)&long_ret;
561  case ASTCHANTYPECHANNELS:
562  {
563  struct ast_channel_iterator *iter;
564 
565  long_ret = 0;
566 
567  if (!(iter = ast_channel_iterator_all_new())) {
568  return NULL;
569  }
570 
571  while ((chan = ast_channel_iterator_next(iter))) {
572  if (ast_channel_tech(chan) == tech) {
573  long_ret++;
574  }
575  chan = ast_channel_unref(chan);
576  }
577 
579 
580  return (u_char *)&long_ret;
581  }
582  default:
583  break;
584  }
585  return NULL;
586 }
587 
588 static u_char *ast_var_channel_bridge(struct variable *vp, oid *name, size_t *length,
589  int exact, size_t *var_len, WriteMethod **write_method)
590 {
591  static unsigned long long_ret;
592  struct ast_channel *chan = NULL;
593  struct ast_channel_iterator *iter;
594 
595  long_ret = 0;
596 
597  if (header_generic(vp, name, length, exact, var_len, write_method)) {
598  return NULL;
599  }
600 
601  if (!(iter = ast_channel_iterator_all_new())) {
602  return NULL;
603  }
604 
605  while ((chan = ast_channel_iterator_next(iter))) {
606  ast_channel_lock(chan);
607  if (ast_channel_is_bridged(chan)) {
608  long_ret++;
609  }
610  ast_channel_unlock(chan);
611  chan = ast_channel_unref(chan);
612  }
613 
615 
616  *var_len = sizeof(long_ret);
617 
618  return (vp->magic == ASTCHANBRIDGECOUNT) ? (u_char *) &long_ret : NULL;
619 }
620 
621 static u_char *ast_var_Config(struct variable *vp, oid *name, size_t *length,
622  int exact, size_t *var_len, WriteMethod **write_method)
623 {
624  static unsigned long long_ret;
625  struct timeval tval;
626 
627  if (header_generic(vp, name, length, exact, var_len, write_method))
628  return NULL;
629 
630  switch (vp->magic) {
631  case ASTCONFUPTIME:
632  gettimeofday(&tval, NULL);
633  long_ret = difftime(tval.tv_sec, ast_startuptime.tv_sec) * 100 + tval.tv_usec / 10000 - ast_startuptime.tv_usec / 10000;
634  return (u_char *)&long_ret;
635  case ASTCONFRELOADTIME:
636  gettimeofday(&tval, NULL);
637  if (ast_lastreloadtime.tv_sec)
638  long_ret = difftime(tval.tv_sec, ast_lastreloadtime.tv_sec) * 100 + tval.tv_usec / 10000 - ast_lastreloadtime.tv_usec / 10000;
639  else
640  long_ret = difftime(tval.tv_sec, ast_startuptime.tv_sec) * 100 + tval.tv_usec / 10000 - ast_startuptime.tv_usec / 10000;
641  return (u_char *)&long_ret;
642  case ASTCONFPID:
643  long_ret = getpid();
644  return (u_char *)&long_ret;
645  case ASTCONFSOCKET:
646  *var_len = strlen(ast_config_AST_SOCKET);
647  return (u_char *)ast_config_AST_SOCKET;
648  case ASTCONFACTIVECALLS:
649  long_ret = ast_active_calls();
650  return (u_char *)&long_ret;
651  case ASTCONFPROCESSEDCALLS:
652  long_ret = ast_processed_calls();
653  return (u_char *)&long_ret;
654  default:
655  break;
656  }
657  return NULL;
658 }
659 
660 static u_char *ast_var_indications(struct variable *vp, oid *name, size_t *length,
661  int exact, size_t *var_len, WriteMethod **write_method)
662 {
663  static unsigned long long_ret;
664  static char ret_buf[128];
665  struct ast_tone_zone *tz = NULL;
666 
667  if (header_generic(vp, name, length, exact, var_len, write_method))
668  return NULL;
669 
670  switch (vp->magic) {
671  case ASTINDCOUNT:
672  {
673  struct ao2_iterator i;
674 
675  long_ret = 0;
676 
678  while ((tz = ao2_iterator_next(&i))) {
679  tz = ast_tone_zone_unref(tz);
680  long_ret++;
681  }
683 
684  return (u_char *) &long_ret;
685  }
686  case ASTINDCURRENT:
687  tz = ast_get_indication_zone(NULL);
688  if (tz) {
689  ast_copy_string(ret_buf, tz->country, sizeof(ret_buf));
690  *var_len = strlen(ret_buf);
691  tz = ast_tone_zone_unref(tz);
692  return (u_char *) ret_buf;
693  }
694  *var_len = 0;
695  return NULL;
696  default:
697  break;
698  }
699  return NULL;
700 }
701 
702 static u_char *ast_var_indications_table(struct variable *vp, oid *name, size_t *length,
703  int exact, size_t *var_len, WriteMethod **write_method)
704 {
705  static unsigned long long_ret;
706  static char ret_buf[256];
707  struct ast_tone_zone *tz = NULL;
708  int i;
709  struct ao2_iterator iter;
710 
711  if (header_simple_table(vp, name, length, exact, var_len, write_method, -1)) {
712  return NULL;
713  }
714 
715  i = name[*length - 1] - 1;
716 
718 
719  while ((tz = ao2_iterator_next(&iter)) && i) {
720  tz = ast_tone_zone_unref(tz);
721  i--;
722  }
723  ao2_iterator_destroy(&iter);
724 
725  if (tz == NULL) {
726  return NULL;
727  }
728 
729  switch (vp->magic) {
730  case ASTINDINDEX:
732  long_ret = name[*length - 1];
733  return (u_char *)&long_ret;
734  case ASTINDCOUNTRY:
735  ast_copy_string(ret_buf, tz->country, sizeof(ret_buf));
737  *var_len = strlen(ret_buf);
738  return (u_char *) ret_buf;
739  case ASTINDALIAS:
740  /* No longer exists */
742  return NULL;
743  case ASTINDDESCRIPTION:
744  ast_tone_zone_lock(tz);
745  ast_copy_string(ret_buf, tz->description, sizeof(ret_buf));
748  *var_len = strlen(ret_buf);
749  return (u_char *) ret_buf;
750  default:
752  break;
753  }
754  return NULL;
755 }
756 
757 static int countmodule(const char *mod, const char *desc, int use, const char *status,
758  const char *like, enum ast_module_support_level support_level)
759 {
760  return 1;
761 }
762 
763 static u_char *ast_var_Modules(struct variable *vp, oid *name, size_t *length,
764  int exact, size_t *var_len, WriteMethod **write_method)
765 {
766  static unsigned long long_ret;
767 
768  if (header_generic(vp, name, length, exact, var_len, write_method))
769  return NULL;
770 
771  if (vp->magic != ASTMODCOUNT)
772  return NULL;
773 
774  long_ret = ast_update_module_list(countmodule, NULL);
775 
776  return (u_char *)&long_ret;
777 }
778 
779 static u_char *ast_var_Version(struct variable *vp, oid *name, size_t *length,
780  int exact, size_t *var_len, WriteMethod **write_method)
781 {
782  static unsigned long long_ret;
783 
784  if (header_generic(vp, name, length, exact, var_len, write_method))
785  return NULL;
786 
787  switch (vp->magic) {
788  case ASTVERSTRING:
789  {
790  const char *version = ast_get_version();
791  *var_len = strlen(version);
792  return (u_char *)version;
793  }
794  case ASTVERTAG:
795  sscanf(ast_get_version_num(), "%30lu", &long_ret);
796  return (u_char *)&long_ret;
797  default:
798  break;
799  }
800  return NULL;
801 }
802 
803 static int term_asterisk_mib(int majorID, int minorID, void *serverarg, void *clientarg)
804 {
805  unregister_sysORTable(asterisk_oid, OID_LENGTH(asterisk_oid));
806  return 0;
807 }
808 
809 static void init_asterisk_mib(void)
810 {
811  static struct variable4 asterisk_vars[] = {
812  {ASTVERSTRING, ASN_OCTET_STR, RONLY, ast_var_Version, 2, {ASTVERSION, ASTVERSTRING}},
813  {ASTVERTAG, ASN_UNSIGNED, RONLY, ast_var_Version, 2, {ASTVERSION, ASTVERTAG}},
814  {ASTCONFUPTIME, ASN_TIMETICKS, RONLY, ast_var_Config, 2, {ASTCONFIGURATION, ASTCONFUPTIME}},
815  {ASTCONFRELOADTIME, ASN_TIMETICKS, RONLY, ast_var_Config, 2, {ASTCONFIGURATION, ASTCONFRELOADTIME}},
816  {ASTCONFPID, ASN_INTEGER, RONLY, ast_var_Config, 2, {ASTCONFIGURATION, ASTCONFPID}},
817  {ASTCONFSOCKET, ASN_OCTET_STR, RONLY, ast_var_Config, 2, {ASTCONFIGURATION, ASTCONFSOCKET}},
818  {ASTCONFACTIVECALLS, ASN_GAUGE, RONLY, ast_var_Config, 2, {ASTCONFIGURATION, ASTCONFACTIVECALLS}},
819  {ASTCONFPROCESSEDCALLS, ASN_COUNTER, RONLY, ast_var_Config, 2, {ASTCONFIGURATION, ASTCONFPROCESSEDCALLS}},
820  {ASTMODCOUNT, ASN_INTEGER, RONLY, ast_var_Modules , 2, {ASTMODULES, ASTMODCOUNT}},
821  {ASTINDCOUNT, ASN_INTEGER, RONLY, ast_var_indications, 2, {ASTINDICATIONS, ASTINDCOUNT}},
822  {ASTINDCURRENT, ASN_OCTET_STR, RONLY, ast_var_indications, 2, {ASTINDICATIONS, ASTINDCURRENT}},
823  {ASTINDINDEX, ASN_INTEGER, RONLY, ast_var_indications_table, 4, {ASTINDICATIONS, ASTINDTABLE, 1, ASTINDINDEX}},
824  {ASTINDCOUNTRY, ASN_OCTET_STR, RONLY, ast_var_indications_table, 4, {ASTINDICATIONS, ASTINDTABLE, 1, ASTINDCOUNTRY}},
825  {ASTINDALIAS, ASN_OCTET_STR, RONLY, ast_var_indications_table, 4, {ASTINDICATIONS, ASTINDTABLE, 1, ASTINDALIAS}},
826  {ASTINDDESCRIPTION, ASN_OCTET_STR, RONLY, ast_var_indications_table, 4, {ASTINDICATIONS, ASTINDTABLE, 1, ASTINDDESCRIPTION}},
827  {ASTCHANCOUNT, ASN_GAUGE, RONLY, ast_var_channels, 2, {ASTCHANNELS, ASTCHANCOUNT}},
828  {ASTCHANINDEX, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANINDEX}},
829  {ASTCHANNAME, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANNAME}},
830  {ASTCHANLANGUAGE, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANLANGUAGE}},
831  {ASTCHANTYPE, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANTYPE}},
832  {ASTCHANMUSICCLASS, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANMUSICCLASS}},
833  {ASTCHANBRIDGE, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANBRIDGE}},
834  {ASTCHANMASQ, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANMASQ}},
835  {ASTCHANMASQR, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANMASQR}},
836  {ASTCHANWHENHANGUP, ASN_TIMETICKS, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANWHENHANGUP}},
837  {ASTCHANAPP, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANAPP}},
838  {ASTCHANDATA, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANDATA}},
839  {ASTCHANCONTEXT, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCONTEXT}},
840  {ASTCHANEXTEN, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANEXTEN}},
841  {ASTCHANPRI, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANPRI}},
842  {ASTCHANACCOUNTCODE, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANACCOUNTCODE}},
843  {ASTCHANFORWARDTO, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANFORWARDTO}},
844  {ASTCHANUNIQUEID, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANUNIQUEID}},
845  {ASTCHANCALLGROUP, ASN_UNSIGNED, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCALLGROUP}},
846  {ASTCHANPICKUPGROUP, ASN_UNSIGNED, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANPICKUPGROUP}},
847  {ASTCHANSTATE, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANSTATE}},
848  {ASTCHANMUTED, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANMUTED}},
849  {ASTCHANRINGS, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANRINGS}},
850  {ASTCHANCIDDNID, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDDNID}},
851  {ASTCHANCIDNUM, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDNUM}},
852  {ASTCHANCIDNAME, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDNAME}},
853  {ASTCHANCIDANI, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDANI}},
854  {ASTCHANCIDRDNIS, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDRDNIS}},
855  {ASTCHANCIDPRES, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDPRES}},
856  {ASTCHANCIDANI2, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDANI2}},
857  {ASTCHANCIDTON, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDTON}},
858  {ASTCHANCIDTNS, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANCIDTNS}},
859  {ASTCHANAMAFLAGS, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANAMAFLAGS}},
860  {ASTCHANADSI, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANADSI}},
861  {ASTCHANTONEZONE, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANTONEZONE}},
862  {ASTCHANHANGUPCAUSE, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANHANGUPCAUSE}},
863  {ASTCHANVARIABLES, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANVARIABLES}},
864  {ASTCHANFLAGS, ASN_OCTET_STR, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANFLAGS}},
865  {ASTCHANTRANSFERCAP, ASN_INTEGER, RONLY, ast_var_channels_table, 4, {ASTCHANNELS, ASTCHANTABLE, 1, ASTCHANTRANSFERCAP}},
866  {ASTCHANTYPECOUNT, ASN_INTEGER, RONLY, ast_var_channel_types, 2, {ASTCHANNELS, ASTCHANTYPECOUNT}},
867  {ASTCHANTYPEINDEX, ASN_INTEGER, RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPEINDEX}},
868  {ASTCHANTYPENAME, ASN_OCTET_STR, RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPENAME}},
869  {ASTCHANTYPEDESC, ASN_OCTET_STR, RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPEDESC}},
870  {ASTCHANTYPEDEVSTATE, ASN_INTEGER, RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPEDEVSTATE}},
871  {ASTCHANTYPEINDICATIONS, ASN_INTEGER, RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPEINDICATIONS}},
872  {ASTCHANTYPETRANSFER, ASN_INTEGER, RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPETRANSFER}},
873  {ASTCHANTYPECHANNELS, ASN_GAUGE, RONLY, ast_var_channel_types_table, 4, {ASTCHANNELS, ASTCHANTYPETABLE, 1, ASTCHANTYPECHANNELS}},
874  {ASTCHANBRIDGECOUNT, ASN_GAUGE, RONLY, ast_var_channel_bridge, 3, {ASTCHANNELS, ASTCHANSCALARS, ASTCHANBRIDGECOUNT}},
875  };
876 
877  register_sysORTable(asterisk_oid, OID_LENGTH(asterisk_oid),
878  "ASTERISK-MIB implementation for Asterisk.");
879 
880  REGISTER_MIB("res_snmp", asterisk_vars, variable4, asterisk_oid);
881 
882  snmp_register_callback(SNMP_CALLBACK_LIBRARY,
883  SNMP_CALLBACK_SHUTDOWN,
884  term_asterisk_mib, NULL);
885 }
886 
887 /*
888  * Local Variables:
889  * c-basic-offset: 4
890  * c-file-offsets: ((case-label . 0))
891  * tab-width: 4
892  * indent-tabs-mode: t
893  * End:
894  */
struct ast_variable * next
Tone Indication Support.
Main Channel structure associated with a channel.
char * str
Subscriber phone number (Malloced)
Definition: channel.h:291
int(*const transfer)(struct ast_channel *chan, const char *newdest)
Blind transfer other side (see app_transfer.c and ast_transfer()
Definition: channel.h:783
struct ast_channel * ast_channel_iterator_next(struct ast_channel_iterator *i)
Get the next channel for a channel iterator.
Definition: channel.c:1422
Asterisk main include file. File version handling, generic pbx functions.
char description[40]
Text description of the given country.
Definition: indications.h:82
char * str
Subscriber phone number (Malloced)
Definition: channel.h:386
int ast_active_calls(void)
Retrieve the number of active calls.
Definition: pbx.c:4760
static struct ast_tone_zone * ast_tone_zone_unref(struct ast_tone_zone *tz)
Release a reference to an ast_tone_zone.
Definition: indications.h:205
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1262
Asterisk version information.
const struct ast_channel_tech * ast_get_channel_tech(const char *name)
Get a channel technology structure by name.
Definition: channel.c:592
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2958
char country[MAX_TONEZONE_COUNTRY]
Country code that this set of tones is for.
Definition: indications.h:76
struct ast_party_name name
Subscriber name.
Definition: channel.h:340
struct ast_party_id from
Who is redirecting the call (Sent to the party the call is redirected toward)
Definition: channel.h:527
const char * ast_get_version(void)
Retrieve the Asterisk version string.
Definition: version.c:18
struct ast_variable * ast_channeltype_list(void)
return an ast_variable list of channeltypes
Definition: channel.c:188
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#define ast_tone_zone_unlock(tz)
Unlock an ast_tone_zone.
Definition: indications.h:193
int ast_party_id_presentation(const struct ast_party_id *id)
Determine the overall presentation value for the given party.
Definition: channel.c:1821
Structure for variables, used for configurations and for channel variables.
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:117
ast_channel_state
ast_channel states
Definition: channelstate.h:35
char * str
Subscriber name (Malloced)
Definition: channel.h:264
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
Number structure.
Definition: app_followme.c:154
struct ast_party_id id
Caller party ID.
Definition: channel.h:420
int ast_update_module_list(int(*modentry)(const char *module, const char *description, int usecnt, const char *status, const char *like, enum ast_module_support_level support_level), const char *like)
Ask for a list of modules, descriptions, use counts and status.
struct ast_party_id ani
Automatic Number Identification (ANI)
Definition: channel.h:427
General Asterisk PBX channel definitions.
Asterisk file paths, configured in asterisk.conf.
A set of tones for a given locale.
Definition: indications.h:74
Structure to describe a channel "technology", ie a channel driver See for examples: ...
Definition: channel.h:628
Core PBX routines and definitions.
int ast_processed_calls(void)
Retrieve the total number of calls processed through the PBX since last restart.
Definition: pbx.c:4765
Support for dynamic strings.
Definition: strings.h:623
int plan
Q.931 Type-Of-Number and Numbering-Plan encoded fields.
Definition: channel.h:293
struct ast_tone_zone * ast_get_indication_zone(const char *country)
locate ast_tone_zone
Definition: indications.c:439
int ani2
Automatic Number Identification 2 (Info Digits)
Definition: channel.h:433
int ast_channel_is_bridged(const struct ast_channel *chan)
Determine if a channel is in a bridge.
Definition: channel.c:10545
struct ast_bridge * bridge
Support for logging to various files, console and syslog Configuration in file logger.conf.
const char * ast_get_version_num(void)
Retrieve the numeric Asterisk version.
Definition: version.c:23
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:730
int transit_network_select
Transit Network Select.
Definition: channel.h:397
SNMP Agent / SubAgent support for Asterisk.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
struct ast_channel * ast_channel_bridge_peer(struct ast_channel *chan)
Get the channel's bridge peer only if the bridge is two-party.
Definition: channel.c:10564
struct ao2_iterator ast_tone_zone_iterator_init(void)
Get an iterator for the available tone zones.
Definition: indications.c:403
struct ast_channel_iterator * ast_channel_iterator_destroy(struct ast_channel_iterator *i)
Destroy a channel iterator.
Definition: channel.c:1360
struct ast_party_dialed::@206 number
Dialed/Called number.
int(*const devicestate)(const char *device_number)
Definition: channel.h:675
Options provided by main asterisk program.
#define ast_tone_zone_lock(tz)
Lock an ast_tone_zone.
Definition: indications.h:188
unsigned char valid
TRUE if the name information is valid/present.
Definition: channel.h:279
struct ast_channel_iterator * ast_channel_iterator_all_new(void)
Create a new channel iterator.
Definition: channel.c:1408
Asterisk module definitions.
int ast_active_channels(void)
returns number of active/allocated channels
Definition: channel.c:499
int(*const indicate)(struct ast_channel *c, int condition, const void *data, size_t datalen)
Indicate a particular condition (e.g. AST_CONTROL_BUSY or AST_CONTROL_RINGING or AST_CONTROL_CONGESTI...
Definition: channel.h:771
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:297
int pbx_builtin_serialize_variables(struct ast_channel *chan, struct ast_str **buf)
Create a human-readable string, specifying all variables and their corresponding values.
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:342