Wed Jan 8 2020 09:49:47

Asterisk developer's documentation


func_enum.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2006
5  *
6  * Mark Spencer <markster@digium.com>
7  * Oleksiy Krivoshey <oleksiyk@gmail.com>
8  * Russell Bryant <russelb@clemson.edu>
9  * Brett Bryant <bbryant@digium.com>
10  *
11  * See http://www.asterisk.org for more information about
12  * the Asterisk project. Please do not directly contact
13  * any of the maintainers of this project for assistance;
14  * the project provides a web site, mailing lists and IRC
15  * channels for your use.
16  *
17  * This program is free software, distributed under the terms of
18  * the GNU General Public License Version 2. See the LICENSE file
19  * at the top of the source tree.
20  */
21 
22 /*! \file
23  *
24  * \brief ENUM Functions
25  *
26  * \author Mark Spencer <markster@digium.com>
27  * \author Oleksiy Krivoshey <oleksiyk@gmail.com>
28  * \author Russell Bryant <russelb@clemson.edu>
29  * \author Brett Bryant <bbryant@digium.com>
30  *
31  * \arg See also AstENUM
32  *
33  * \ingroup functions
34  */
35 
36 /*** MODULEINFO
37  <support_level>core</support_level>
38  ***/
39 
40 #include "asterisk.h"
41 
42 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 413586 $")
43 
44 #include "asterisk/module.h"
45 #include "asterisk/channel.h"
46 #include "asterisk/pbx.h"
47 #include "asterisk/utils.h"
48 #include "asterisk/lock.h"
49 #include "asterisk/file.h"
50 #include "asterisk/enum.h"
51 #include "asterisk/app.h"
52 
53 /*** DOCUMENTATION
54  <function name="ENUMQUERY" language="en_US">
55  <synopsis>
56  Initiate an ENUM query.
57  </synopsis>
58  <syntax>
59  <parameter name="number" required="true" />
60  <parameter name="method-type">
61  <para>If no <replaceable>method-type</replaceable> is given, the default will be
62  <literal>sip</literal>.</para>
63  </parameter>
64  <parameter name="zone-suffix">
65  <para>If no <replaceable>zone-suffix</replaceable> is given, the default will be
66  <literal>e164.arpa</literal></para>
67  </parameter>
68  </syntax>
69  <description>
70  <para>This will do a ENUM lookup of the given phone number.</para>
71  </description>
72  </function>
73  <function name="ENUMRESULT" language="en_US">
74  <synopsis>
75  Retrieve results from a ENUMQUERY.
76  </synopsis>
77  <syntax>
78  <parameter name="id" required="true">
79  <para>The identifier returned by the ENUMQUERY function.</para>
80  </parameter>
81  <parameter name="resultnum" required="true">
82  <para>The number of the result that you want to retrieve.</para>
83  <para>Results start at <literal>1</literal>. If this argument is specified
84  as <literal>getnum</literal>, then it will return the total number of results
85  that are available.</para>
86  </parameter>
87  </syntax>
88  <description>
89  <para>This function will retrieve results from a previous use
90  of the ENUMQUERY function.</para>
91  </description>
92  </function>
93  <function name="ENUMLOOKUP" language="en_US">
94  <synopsis>
95  General or specific querying of NAPTR records for ENUM or ENUM-like DNS pointers.
96  </synopsis>
97  <syntax>
98  <parameter name="number" required="true" />
99  <parameter name="method-type">
100  <para>If no <replaceable>method-type</replaceable> is given, the default will be
101  <literal>sip</literal>.</para>
102  </parameter>
103  <parameter name="options">
104  <optionlist>
105  <option name="c">
106  <para>Returns an integer count of the number of NAPTRs of a certain RR type.</para>
107  <para>Combination of <literal>c</literal> and Method-type of <literal>ALL</literal> will
108  return a count of all NAPTRs for the record.</para>
109  </option>
110  <option name="u">
111  <para>Returns the full URI and does not strip off the URI-scheme.</para>
112  </option>
113  <option name="s">
114  <para>Triggers ISN specific rewriting.</para>
115  </option>
116  <option name="i">
117  <para>Looks for branches into an Infrastructure ENUM tree.</para>
118  </option>
119  <option name="d">
120  <para>for a direct DNS lookup without any flipping of digits.</para>
121  </option>
122  </optionlist>
123  </parameter>
124  <parameter name="record#">
125  <para>If no <replaceable>record#</replaceable> is given,
126  defaults to <literal>1</literal>.</para>
127  </parameter>
128  <parameter name="zone-suffix">
129  <para>If no <replaceable>zone-suffix</replaceable> is given, the default will be
130  <literal>e164.arpa</literal></para>
131  </parameter>
132  </syntax>
133  <description>
134  <para>For more information see <filename>doc/AST.pdf</filename>.</para>
135  </description>
136  </function>
137  <function name="TXTCIDNAME" language="en_US">
138  <synopsis>
139  TXTCIDNAME looks up a caller name via DNS.
140  </synopsis>
141  <syntax>
142  <parameter name="number" required="true" />
143  <parameter name="zone-suffix">
144  <para>If no <replaceable>zone-suffix</replaceable> is given, the default will be
145  <literal>e164.arpa</literal></para>
146  </parameter>
147  </syntax>
148  <description>
149  <para>This function looks up the given phone number in DNS to retrieve
150  the caller id name. The result will either be blank or be the value
151  found in the TXT record in DNS.</para>
152  </description>
153  </function>
154  ***/
155 
156 static char *synopsis = "Syntax: ENUMLOOKUP(number[,Method-type[,options[,record#[,zone-suffix]]]])\n";
157 
158 static int function_enum(struct ast_channel *chan, const char *cmd, char *data,
159  char *buf, size_t len)
160 {
163  AST_APP_ARG(tech);
164  AST_APP_ARG(options);
165  AST_APP_ARG(record);
166  AST_APP_ARG(zone);
167  );
168  char tech[80];
169  char dest[256] = "", tmp[2] = "", num[AST_MAX_EXTENSION] = "";
170  char *s, *p;
171  unsigned int record = 1;
172 
173  buf[0] = '\0';
174 
175  if (ast_strlen_zero(data)) {
176  ast_log(LOG_WARNING, "%s", synopsis);
177  return -1;
178  }
179 
181 
182  if (args.argc < 1) {
183  ast_log(LOG_WARNING, "%s", synopsis);
184  return -1;
185  }
186 
187  if (args.tech && !ast_strlen_zero(args.tech)) {
188  ast_copy_string(tech,args.tech, sizeof(tech));
189  } else {
190  ast_copy_string(tech,"sip",sizeof(tech));
191  }
192 
193  if (!args.zone) {
194  args.zone = "e164.arpa";
195  }
196  if (!args.options) {
197  args.options = "";
198  }
199  if (args.record) {
200  record = atoi(args.record) ? atoi(args.record) : record;
201  }
202 
203  /* strip any '-' signs from number */
204  for (s = p = args.number; *s; s++) {
205  if (*s != '-') {
206  snprintf(tmp, sizeof(tmp), "%c", *s);
207  strncat(num, tmp, sizeof(num) - strlen(num) - 1);
208  }
209 
210  }
211  ast_get_enum(chan, num, dest, sizeof(dest), tech, sizeof(tech), args.zone, args.options, record, NULL);
212 
213  p = strchr(dest, ':');
214  if (p && strcasecmp(tech, "ALL") && !strchr(args.options, 'u')) {
215  ast_copy_string(buf, p + 1, len);
216  } else {
217  ast_copy_string(buf, dest, len);
218  }
219  return 0;
220 }
221 
222 static unsigned int enum_datastore_id;
223 
226  unsigned int id;
227 };
228 
229 static void erds_destroy(struct enum_result_datastore *data)
230 {
231  int k;
232 
233  for (k = 0; k < data->context->naptr_rrs_count; k++) {
234  ast_free(data->context->naptr_rrs[k].result);
235  ast_free(data->context->naptr_rrs[k].tech);
236  }
237 
238  ast_free(data->context->naptr_rrs);
239  ast_free(data->context);
240  ast_free(data);
241 }
242 
243 static void erds_destroy_cb(void *data)
244 {
245  struct enum_result_datastore *erds = data;
246  erds_destroy(erds);
247 }
248 
250  .type = "ENUMQUERY",
251  .destroy = erds_destroy_cb,
252 };
253 
254 static int enum_query_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
255 {
256  struct enum_result_datastore *erds;
257  struct ast_datastore *datastore;
258  char *parse, tech[128], dest[128];
259  int res = -1;
260 
263  AST_APP_ARG(tech);
264  AST_APP_ARG(zone);
265  );
266 
267  if (ast_strlen_zero(data)) {
268  ast_log(LOG_WARNING, "ENUMQUERY requires at least a number as an argument...\n");
269  goto finish;
270  }
271 
272  parse = ast_strdupa(data);
273 
274  AST_STANDARD_APP_ARGS(args, parse);
275 
276  if (!chan) {
277  ast_log(LOG_ERROR, "ENUMQUERY cannot be used without a channel!\n");
278  goto finish;
279  }
280 
281  if (!args.zone)
282  args.zone = "e164.zone";
283 
284  ast_copy_string(tech, args.tech ? args.tech : "sip", sizeof(tech));
285 
286  if (!(erds = ast_calloc(1, sizeof(*erds))))
287  goto finish;
288 
289  if (!(erds->context = ast_calloc(1, sizeof(*erds->context)))) {
290  ast_free(erds);
291  goto finish;
292  }
293 
294  erds->id = ast_atomic_fetchadd_int((int *) &enum_datastore_id, 1);
295 
296  snprintf(buf, len, "%u", erds->id);
297 
298  if (!(datastore = ast_datastore_alloc(&enum_result_datastore_info, buf))) {
299  ast_free(erds->context);
300  ast_free(erds);
301  goto finish;
302  }
303 
304  ast_get_enum(chan, args.number, dest, sizeof(dest), tech, sizeof(tech), args.zone, "", 1, &erds->context);
305 
306  datastore->data = erds;
307 
308  ast_channel_lock(chan);
309  ast_channel_datastore_add(chan, datastore);
310  ast_channel_unlock(chan);
311 
312  res = 0;
313 
314 finish:
315 
316  return res;
317 }
318 
319 static int enum_result_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
320 {
321  struct enum_result_datastore *erds;
322  struct ast_datastore *datastore;
323  char *parse, *p;
324  unsigned int num;
325  int res = -1, k;
327  AST_APP_ARG(id);
328  AST_APP_ARG(resultnum);
329  );
330 
331  if (ast_strlen_zero(data)) {
332  ast_log(LOG_WARNING, "ENUMRESULT requires two arguments (id and resultnum)\n");
333  goto finish;
334  }
335 
336  if (!chan) {
337  ast_log(LOG_ERROR, "ENUMRESULT can not be used without a channel!\n");
338  goto finish;
339  }
340 
341  parse = ast_strdupa(data);
342 
343  AST_STANDARD_APP_ARGS(args, parse);
344 
345  if (ast_strlen_zero(args.id)) {
346  ast_log(LOG_ERROR, "A result ID must be provided to ENUMRESULT\n");
347  goto finish;
348  }
349 
350  if (ast_strlen_zero(args.resultnum)) {
351  ast_log(LOG_ERROR, "A result number must be given to ENUMRESULT!\n");
352  goto finish;
353  }
354 
355  ast_channel_lock(chan);
356  datastore = ast_channel_datastore_find(chan, &enum_result_datastore_info, args.id);
357  ast_channel_unlock(chan);
358  if (!datastore) {
359  ast_log(LOG_WARNING, "No ENUM results found for query id!\n");
360  goto finish;
361  }
362 
363  erds = datastore->data;
364 
365  if (!strcasecmp(args.resultnum, "getnum")) {
366  snprintf(buf, len, "%d", erds->context->naptr_rrs_count);
367  res = 0;
368  goto finish;
369  }
370 
371  if (sscanf(args.resultnum, "%30u", &num) != 1) {
372  ast_log(LOG_ERROR, "Invalid value '%s' for resultnum to ENUMRESULT!\n", args.resultnum);
373  goto finish;
374  }
375 
376  if (!num || num > erds->context->naptr_rrs_count) {
377  ast_log(LOG_WARNING, "Result number %u is not valid for ENUM query results for ID %s!\n", num, args.id);
378  goto finish;
379  }
380 
381  for (k = 0; k < erds->context->naptr_rrs_count; k++) {
382  if (num - 1 != erds->context->naptr_rrs[k].sort_pos)
383  continue;
384 
385  p = strchr(erds->context->naptr_rrs[k].result, ':');
386 
387  if (p && strcasecmp(erds->context->naptr_rrs[k].tech, "ALL"))
388  ast_copy_string(buf, p + 1, len);
389  else
390  ast_copy_string(buf, erds->context->naptr_rrs[k].result, len);
391 
392  break;
393  }
394 
395  res = 0;
396 
397 finish:
398 
399  return res;
400 }
401 
403  .name = "ENUMQUERY",
404  .read = enum_query_read,
405 };
406 
408  .name = "ENUMRESULT",
409  .read = enum_result_read,
410 };
411 
413  .name = "ENUMLOOKUP",
414  .read = function_enum,
415 };
416 
417 static int function_txtcidname(struct ast_channel *chan, const char *cmd,
418  char *data, char *buf, size_t len)
419 {
422  AST_APP_ARG(zone);
423  );
424 
425  buf[0] = '\0';
426 
427  if (ast_strlen_zero(data)) {
428  ast_log(LOG_WARNING, "Syntax: TXTCIDNAME(number[,zone-suffix])\n");
429  return -1;
430  }
431 
433 
434  if (args.argc < 1) {
435  ast_log(LOG_WARNING, "Syntax: TXTCIDNAME(number[,zone-suffix])\n");
436  return -1;
437  }
438 
439  if (!args.zone) {
440  args.zone = "e164.arpa";
441  }
442 
443  ast_get_txt(chan, args.number, buf, len, args.zone);
444 
445  return 0;
446 }
447 
449  .name = "TXTCIDNAME",
450  .read = function_txtcidname,
451 };
452 
453 static int unload_module(void)
454 {
455  int res = 0;
456 
457  res |= ast_custom_function_unregister(&enum_result_function);
458  res |= ast_custom_function_unregister(&enum_query_function);
459  res |= ast_custom_function_unregister(&enum_function);
460  res |= ast_custom_function_unregister(&txtcidname_function);
461 
462  return res;
463 }
464 
465 static int load_module(void)
466 {
467  int res = 0;
468 
469  res |= ast_custom_function_register(&enum_result_function);
470  res |= ast_custom_function_register(&enum_query_function);
471  res |= ast_custom_function_register(&enum_function);
472  res |= ast_custom_function_register(&txtcidname_function);
473 
474  return res;
475 }
476 
477 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "ENUM related dialplan functions");
const char * type
Definition: datastore.h:32
#define ast_channel_lock(chan)
Definition: channel.h:2466
Main Channel structure associated with a channel.
Definition: channel.h:742
static struct ast_datastore_info enum_result_datastore_info
Definition: func_enum.c:249
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:396
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
static void erds_destroy_cb(void *data)
Definition: func_enum.c:243
struct enum_naptr_rr * naptr_rrs
Definition: enum.h:51
#define LOG_WARNING
Definition: logger.h:144
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
Structure for a data store type.
Definition: datastore.h:31
static int unload_module(void)
Definition: func_enum.c:453
static struct ast_custom_function enum_query_function
Definition: func_enum.c:402
static int function_enum(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: func_enum.c:158
Structure for a data store object.
Definition: datastore.h:54
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2604
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return * the previous value of *p. This can be used to handle reference co...
Definition: lock.h:603
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
Definition: pbx.c:3814
static int function_txtcidname(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: func_enum.c:417
Utility functions.
Number structure.
Definition: app_followme.c:109
static struct ast_custom_function enum_function
Definition: func_enum.c:412
General Asterisk PBX channel definitions.
DNS and ENUM functions.
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
Data structure associated with a custom dialplan function.
Definition: pbx.h:95
#define AST_MAX_EXTENSION
Definition: channel.h:135
struct enum_context * context
Definition: func_enum.c:225
char * tech
Definition: enum.h:36
Core PBX routines and definitions.
static unsigned int enum_datastore_id
Definition: func_enum.c:222
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
#define LOG_ERROR
Definition: logger.h:155
static struct @350 args
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
struct ast_datastore * ast_datastore_alloc(const struct ast_datastore_info *info, const char *uid)
Definition: datastore.c:98
static char * synopsis
Definition: func_enum.c:156
#define ast_channel_unlock(chan)
Definition: channel.h:2467
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1858
#define ast_free(a)
Definition: astmm.h:97
static int load_module(void)
Definition: func_enum.c:465
int ast_get_txt(struct ast_channel *chan, const char *number, char *txt, int maxtxt, char *suffix)
Lookup DNS TXT record (used by app TXTCIDnum)
Definition: enum.c:927
void * data
Definition: datastore.h:56
static struct ast_custom_function txtcidname_function
Definition: func_enum.c:448
int ast_get_enum(struct ast_channel *chan, const char *number, char *location, int maxloc, char *technology, int maxtech, char *suffix, char *options, unsigned int record, struct enum_context **argcontext)
Lookup entry in ENUM.
Definition: enum.c:632
char * result
Definition: enum.h:35
#define ast_calloc(a, b)
Definition: astmm.h:82
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
static int enum_result_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: func_enum.c:319
static int enum_query_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: func_enum.c:254
unsigned int id
Definition: func_enum.c:226
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
int naptr_rrs_count
Definition: enum.h:52
const char * name
Definition: pbx.h:96
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
static void erds_destroy(struct enum_result_datastore *data)
Definition: func_enum.c:229
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:38
int sort_pos
Definition: enum.h:37
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2590
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1164
static struct ast_custom_function enum_result_function
Definition: func_enum.c:407
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
Definition: asterisk.h:180