Asterisk - The Open Source Telephony Project  18.5.0
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 <[email protected]>
7  * Oleksiy Krivoshey <[email protected]>
8  * Russell Bryant <[email protected]>
9  * Brett Bryant <[email protected]>
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 <[email protected]>
27  * \author Oleksiy Krivoshey <[email protected]>
28  * \author Russell Bryant <[email protected]>
29  * \author Brett Bryant <[email protected]>
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 #include "asterisk/module.h"
43 #include "asterisk/channel.h"
44 #include "asterisk/pbx.h"
45 #include "asterisk/utils.h"
46 #include "asterisk/lock.h"
47 #include "asterisk/file.h"
48 #include "asterisk/enum.h"
49 #include "asterisk/app.h"
50 
51 /*** DOCUMENTATION
52  <function name="ENUMQUERY" language="en_US">
53  <synopsis>
54  Initiate an ENUM query.
55  </synopsis>
56  <syntax>
57  <parameter name="number" required="true" />
58  <parameter name="method-type">
59  <para>If no <replaceable>method-type</replaceable> is given, the default will be
60  <literal>sip</literal>.</para>
61  </parameter>
62  <parameter name="zone-suffix">
63  <para>If no <replaceable>zone-suffix</replaceable> is given, the default will be
64  <literal>e164.arpa</literal></para>
65  </parameter>
66  </syntax>
67  <description>
68  <para>This will do a ENUM lookup of the given phone number.</para>
69  </description>
70  </function>
71  <function name="ENUMRESULT" language="en_US">
72  <synopsis>
73  Retrieve results from a ENUMQUERY.
74  </synopsis>
75  <syntax>
76  <parameter name="id" required="true">
77  <para>The identifier returned by the ENUMQUERY function.</para>
78  </parameter>
79  <parameter name="resultnum" required="true">
80  <para>The number of the result that you want to retrieve.</para>
81  <para>Results start at <literal>1</literal>. If this argument is specified
82  as <literal>getnum</literal>, then it will return the total number of results
83  that are available or -1 on error.</para>
84  </parameter>
85  </syntax>
86  <description>
87  <para>This function will retrieve results from a previous use
88  of the ENUMQUERY function.</para>
89  </description>
90  </function>
91  <function name="ENUMLOOKUP" language="en_US">
92  <synopsis>
93  General or specific querying of NAPTR records for ENUM or ENUM-like DNS pointers.
94  </synopsis>
95  <syntax>
96  <parameter name="number" required="true" />
97  <parameter name="method-type">
98  <para>If no <replaceable>method-type</replaceable> is given, the default will be
99  <literal>sip</literal>.</para>
100  </parameter>
101  <parameter name="options">
102  <optionlist>
103  <option name="c">
104  <para>Returns an integer count of the number of NAPTRs of a certain RR type.</para>
105  <para>Combination of <literal>c</literal> and Method-type of <literal>ALL</literal> will
106  return a count of all NAPTRs for the record or -1 on error.</para>
107  </option>
108  <option name="u">
109  <para>Returns the full URI and does not strip off the URI-scheme.</para>
110  </option>
111  <option name="s">
112  <para>Triggers ISN specific rewriting.</para>
113  </option>
114  <option name="i">
115  <para>Looks for branches into an Infrastructure ENUM tree.</para>
116  </option>
117  <option name="d">
118  <para>for a direct DNS lookup without any flipping of digits.</para>
119  </option>
120  </optionlist>
121  </parameter>
122  <parameter name="record#">
123  <para>If no <replaceable>record#</replaceable> is given,
124  defaults to <literal>1</literal>.</para>
125  </parameter>
126  <parameter name="zone-suffix">
127  <para>If no <replaceable>zone-suffix</replaceable> is given, the default will be
128  <literal>e164.arpa</literal></para>
129  </parameter>
130  </syntax>
131  <description>
132  <para>For more information see <filename>doc/AST.pdf</filename>.</para>
133  </description>
134  </function>
135  <function name="TXTCIDNAME" language="en_US">
136  <synopsis>
137  TXTCIDNAME looks up a caller name via DNS.
138  </synopsis>
139  <syntax>
140  <parameter name="number" required="true" />
141  <parameter name="zone-suffix">
142  <para>If no <replaceable>zone-suffix</replaceable> is given, the default will be
143  <literal>e164.arpa</literal></para>
144  </parameter>
145  </syntax>
146  <description>
147  <para>This function looks up the given phone number in DNS to retrieve
148  the caller id name. The result will either be blank or be the value
149  found in the TXT record in DNS.</para>
150  </description>
151  </function>
152  ***/
153 
154 static char *synopsis = "Syntax: ENUMLOOKUP(number[,Method-type[,options[,record#[,zone-suffix]]]])\n";
155 
156 static int function_enum(struct ast_channel *chan, const char *cmd, char *data,
157  char *buf, size_t len)
158 {
161  AST_APP_ARG(tech);
163  AST_APP_ARG(record);
164  AST_APP_ARG(zone);
165  );
166  char tech[80];
167  char dest[256] = "", tmp[2] = "", num[AST_MAX_EXTENSION] = "";
168  char *s, *p;
169  unsigned int record = 1;
170 
171  buf[0] = '\0';
172 
173  if (ast_strlen_zero(data)) {
174  ast_log(LOG_WARNING, "%s", synopsis);
175  return -1;
176  }
177 
179 
180  if (args.argc < 1) {
181  ast_log(LOG_WARNING, "%s", synopsis);
182  return -1;
183  }
184 
185  if (args.tech && !ast_strlen_zero(args.tech)) {
186  ast_copy_string(tech,args.tech, sizeof(tech));
187  } else {
188  ast_copy_string(tech,"sip",sizeof(tech));
189  }
190 
191  if (!args.zone) {
192  args.zone = "e164.arpa";
193  }
194  if (!args.options) {
195  args.options = "";
196  }
197  if (args.record) {
198  record = atoi(args.record) ? atoi(args.record) : record;
199  }
200 
201  /* strip any '-' signs from number */
202  for (s = p = args.number; *s; s++) {
203  if (*s != '-') {
204  snprintf(tmp, sizeof(tmp), "%c", *s);
205  strncat(num, tmp, sizeof(num) - strlen(num) - 1);
206  }
207 
208  }
209  ast_get_enum(chan, num, dest, sizeof(dest), tech, sizeof(tech), args.zone, args.options, record, NULL);
210 
211  p = strchr(dest, ':');
212  if (p && strcasecmp(tech, "ALL") && !strchr(args.options, 'u')) {
213  ast_copy_string(buf, p + 1, len);
214  } else {
215  ast_copy_string(buf, dest, len);
216  }
217  return 0;
218 }
219 
220 static unsigned int enum_datastore_id;
221 
224  unsigned int id;
225 };
226 
227 static void erds_destroy(struct enum_result_datastore *data)
228 {
229  int k;
230 
231  for (k = 0; k < data->context->naptr_rrs_count; k++) {
232  ast_free(data->context->naptr_rrs[k].result);
233  ast_free(data->context->naptr_rrs[k].tech);
234  }
235 
236  ast_free(data->context->naptr_rrs);
237  ast_free(data->context);
238  ast_free(data);
239 }
240 
241 static void erds_destroy_cb(void *data)
242 {
243  struct enum_result_datastore *erds = data;
244  erds_destroy(erds);
245 }
246 
248  .type = "ENUMQUERY",
249  .destroy = erds_destroy_cb,
250 };
251 
252 static int enum_query_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
253 {
254  struct enum_result_datastore *erds;
255  struct ast_datastore *datastore;
256  char *parse, tech[128], dest[128];
257  int res = -1;
258 
261  AST_APP_ARG(tech);
262  AST_APP_ARG(zone);
263  );
264 
265  if (ast_strlen_zero(data)) {
266  ast_log(LOG_WARNING, "ENUMQUERY requires at least a number as an argument...\n");
267  goto finish;
268  }
269 
270  parse = ast_strdupa(data);
271 
272  AST_STANDARD_APP_ARGS(args, parse);
273 
274  if (!chan) {
275  ast_log(LOG_ERROR, "ENUMQUERY cannot be used without a channel!\n");
276  goto finish;
277  }
278 
279  if (!args.zone)
280  args.zone = "e164.zone";
281 
282  ast_copy_string(tech, args.tech ? args.tech : "sip", sizeof(tech));
283 
284  if (!(erds = ast_calloc(1, sizeof(*erds))))
285  goto finish;
286 
287  if (!(erds->context = ast_calloc(1, sizeof(*erds->context)))) {
288  ast_free(erds);
289  goto finish;
290  }
291 
292  erds->id = ast_atomic_fetchadd_int((int *) &enum_datastore_id, 1);
293 
294  snprintf(buf, len, "%u", erds->id);
295 
296  if (!(datastore = ast_datastore_alloc(&enum_result_datastore_info, buf))) {
297  ast_free(erds->context);
298  ast_free(erds);
299  goto finish;
300  }
301 
302  ast_get_enum(chan, args.number, dest, sizeof(dest), tech, sizeof(tech), args.zone, "", 1, &erds->context);
303 
304  datastore->data = erds;
305 
306  ast_channel_lock(chan);
307  ast_channel_datastore_add(chan, datastore);
308  ast_channel_unlock(chan);
309 
310  res = 0;
311 
312 finish:
313 
314  return res;
315 }
316 
317 static int enum_result_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
318 {
319  struct enum_result_datastore *erds;
320  struct ast_datastore *datastore;
321  char *parse, *p;
322  unsigned int num;
323  int res = -1, k;
325  AST_APP_ARG(id);
326  AST_APP_ARG(resultnum);
327  );
328 
329  if (ast_strlen_zero(data)) {
330  ast_log(LOG_WARNING, "ENUMRESULT requires two arguments (id and resultnum)\n");
331  goto finish;
332  }
333 
334  if (!chan) {
335  ast_log(LOG_ERROR, "ENUMRESULT can not be used without a channel!\n");
336  goto finish;
337  }
338 
339  parse = ast_strdupa(data);
340 
341  AST_STANDARD_APP_ARGS(args, parse);
342 
343  if (ast_strlen_zero(args.id)) {
344  ast_log(LOG_ERROR, "A result ID must be provided to ENUMRESULT\n");
345  goto finish;
346  }
347 
348  if (ast_strlen_zero(args.resultnum)) {
349  ast_log(LOG_ERROR, "A result number must be given to ENUMRESULT!\n");
350  goto finish;
351  }
352 
353  ast_channel_lock(chan);
354  datastore = ast_channel_datastore_find(chan, &enum_result_datastore_info, args.id);
355  ast_channel_unlock(chan);
356  if (!datastore) {
357  ast_log(LOG_WARNING, "No ENUM results found for query id!\n");
358  goto finish;
359  }
360 
361  erds = datastore->data;
362 
363  if (!strcasecmp(args.resultnum, "getnum")) {
364  snprintf(buf, len, "%d", erds->context->naptr_rrs_count);
365  res = 0;
366  goto finish;
367  }
368 
369  if (sscanf(args.resultnum, "%30u", &num) != 1) {
370  ast_log(LOG_ERROR, "Invalid value '%s' for resultnum to ENUMRESULT!\n", args.resultnum);
371  goto finish;
372  }
373 
374  if (!num || num > erds->context->naptr_rrs_count) {
375  ast_log(LOG_WARNING, "Result number %u is not valid for ENUM query results for ID %s!\n", num, args.id);
376  goto finish;
377  }
378 
379  for (k = 0; k < erds->context->naptr_rrs_count; k++) {
380  if (num - 1 != erds->context->naptr_rrs[k].sort_pos)
381  continue;
382 
383  p = strchr(erds->context->naptr_rrs[k].result, ':');
384 
385  if (p && strcasecmp(erds->context->naptr_rrs[k].tech, "ALL"))
386  ast_copy_string(buf, p + 1, len);
387  else
388  ast_copy_string(buf, erds->context->naptr_rrs[k].result, len);
389 
390  break;
391  }
392 
393  res = 0;
394 
395 finish:
396 
397  return res;
398 }
399 
401  .name = "ENUMQUERY",
402  .read = enum_query_read,
403 };
404 
406  .name = "ENUMRESULT",
407  .read = enum_result_read,
408 };
409 
411  .name = "ENUMLOOKUP",
412  .read = function_enum,
413 };
414 
415 static int function_txtcidname(struct ast_channel *chan, const char *cmd,
416  char *data, char *buf, size_t len)
417 {
420  AST_APP_ARG(zone);
421  );
422 
423  buf[0] = '\0';
424 
425  if (ast_strlen_zero(data)) {
426  ast_log(LOG_WARNING, "Syntax: TXTCIDNAME(number[,zone-suffix])\n");
427  return -1;
428  }
429 
431 
432  if (args.argc < 1) {
433  ast_log(LOG_WARNING, "Syntax: TXTCIDNAME(number[,zone-suffix])\n");
434  return -1;
435  }
436 
437  if (!args.zone) {
438  args.zone = "e164.arpa";
439  }
440 
441  ast_get_txt(chan, args.number, buf, len, args.zone);
442 
443  return 0;
444 }
445 
447  .name = "TXTCIDNAME",
448  .read = function_txtcidname,
449 };
450 
451 static int unload_module(void)
452 {
453  int res = 0;
454 
455  res |= ast_custom_function_unregister(&enum_result_function);
456  res |= ast_custom_function_unregister(&enum_query_function);
457  res |= ast_custom_function_unregister(&enum_function);
458  res |= ast_custom_function_unregister(&txtcidname_function);
459 
460  return res;
461 }
462 
463 static int load_module(void)
464 {
465  int res = 0;
466 
467  res |= ast_custom_function_register(&enum_result_function);
468  res |= ast_custom_function_register(&enum_query_function);
469  res |= ast_custom_function_register(&enum_function);
470  res |= ast_custom_function_register(&txtcidname_function);
471 
472  return res;
473 }
474 
475 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "ENUM related dialplan functions",
476  .support_level = AST_MODULE_SUPPORT_CORE,
477  .load = load_module,
478  .unload = unload_module,
479  .requires = "enum",
480 );
const char * name
Definition: pbx.h:119
const char * type
Definition: datastore.h:32
#define ast_channel_lock(chan)
Definition: channel.h:2945
Main Channel structure associated with a channel.
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:241
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
struct enum_naptr_rr * naptr_rrs
Definition: enum.h:51
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
#define LOG_WARNING
Definition: logger.h:274
static int tmp()
Definition: bt_open.c:389
Structure for a data store type.
Definition: datastore.h:31
static int unload_module(void)
Definition: func_enum.c:451
static const struct ast_datastore_info enum_result_datastore_info
Definition: func_enum.c:247
static struct ast_custom_function enum_query_function
Definition: func_enum.c:400
static int function_enum(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: func_enum.c:156
Structure for a data store object.
Definition: datastore.h:68
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:2404
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
const char * args
#define NULL
Definition: resample.c:96
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:755
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
static int function_txtcidname(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: func_enum.c:415
Utility functions.
#define ast_strlen_zero(foo)
Definition: strings.h:52
Number structure.
Definition: app_followme.c:154
static struct ast_custom_function enum_function
Definition: func_enum.c:410
#define ast_log
Definition: astobj2.c:42
General Asterisk PBX channel definitions.
DNS and ENUM functions.
Data structure associated with a custom dialplan function.
Definition: pbx.h:118
#define AST_MAX_EXTENSION
Definition: channel.h:135
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
struct enum_context * context
Definition: func_enum.c:223
char * tech
Definition: enum.h:36
Core PBX routines and definitions.
static unsigned int enum_datastore_id
Definition: func_enum.c:220
#define LOG_ERROR
Definition: logger.h:285
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
static char * synopsis
Definition: func_enum.c:154
#define ast_channel_unlock(chan)
Definition: channel.h:2946
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
static int load_module(void)
Definition: func_enum.c:463
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:995
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS|AST_MODFLAG_LOAD_ORDER, "HTTP Phone Provisioning",.support_level=AST_MODULE_SUPPORT_EXTENDED,.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CHANNEL_DEPEND,.requires="http",)
void * data
Definition: datastore.h:70
static struct ast_custom_function txtcidname_function
Definition: func_enum.c:446
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:649
char * result
Definition: enum.h:35
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static int enum_result_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: func_enum.c:317
static int enum_query_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: func_enum.c:252
unsigned int id
Definition: func_enum.c:224
int naptr_rrs_count
Definition: enum.h:52
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:89
static struct test_options options
static void erds_destroy(struct enum_result_datastore *data)
Definition: func_enum.c:227
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
int sort_pos
Definition: enum.h:37
Asterisk module definitions.
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2390
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1508
static struct ast_custom_function enum_result_function
Definition: func_enum.c:405
#define AST_APP_ARG(name)
Define an application argument.