2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2006
6 * Mark Spencer <markster@digium.com>
7 * Oleksiy Krivoshey <oleksiyk@gmail.com>
8 * Russell Bryant <russelb@clemson.edu>
9 * Brett Bryant <bbryant@digium.com>
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.
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.
24 * \brief ENUM Functions
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>
31 * \arg See also AstENUM
37 <support_level>core</support_level>
42 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
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"
54 <function name="ENUMQUERY" language="en_US">
56 Initiate an ENUM query.
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>
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>
70 <para>This will do a ENUM lookup of the given phone number.</para>
73 <function name="ENUMRESULT" language="en_US">
75 Retrieve results from a ENUMQUERY.
78 <parameter name="id" required="true">
79 <para>The identifier returned by the ENUMQUERY function.</para>
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 or -1 on error.</para>
89 <para>This function will retrieve results from a previous use
90 of the ENUMQUERY function.</para>
93 <function name="ENUMLOOKUP" language="en_US">
95 General or specific querying of NAPTR records for ENUM or ENUM-like DNS pointers.
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>
103 <parameter name="options">
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 or -1 on error.</para>
111 <para>Returns the full URI and does not strip off the URI-scheme.</para>
114 <para>Triggers ISN specific rewriting.</para>
117 <para>Looks for branches into an Infrastructure ENUM tree.</para>
120 <para>for a direct DNS lookup without any flipping of digits.</para>
124 <parameter name="record#">
125 <para>If no <replaceable>record#</replaceable> is given,
126 defaults to <literal>1</literal>.</para>
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>
134 <para>For more information see <filename>doc/AST.pdf</filename>.</para>
137 <function name="TXTCIDNAME" language="en_US">
139 TXTCIDNAME looks up a caller name via DNS.
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>
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>
156 static char *synopsis = "Syntax: ENUMLOOKUP(number[,Method-type[,options[,record#[,zone-suffix]]]])\n";
158 static int function_enum(struct ast_channel *chan, const char *cmd, char *data,
159 char *buf, size_t len)
161 AST_DECLARE_APP_ARGS(args,
164 AST_APP_ARG(options);
169 char dest[256] = "", tmp[2] = "", num[AST_MAX_EXTENSION] = "";
171 unsigned int record = 1;
175 if (ast_strlen_zero(data)) {
176 ast_log(LOG_WARNING, "%s", synopsis);
180 AST_STANDARD_APP_ARGS(args, data);
183 ast_log(LOG_WARNING, "%s", synopsis);
187 if (args.tech && !ast_strlen_zero(args.tech)) {
188 ast_copy_string(tech,args.tech, sizeof(tech));
190 ast_copy_string(tech,"sip",sizeof(tech));
194 args.zone = "e164.arpa";
200 record = atoi(args.record) ? atoi(args.record) : record;
203 /* strip any '-' signs from number */
204 for (s = p = args.number; *s; s++) {
206 snprintf(tmp, sizeof(tmp), "%c", *s);
207 strncat(num, tmp, sizeof(num) - strlen(num) - 1);
211 ast_get_enum(chan, num, dest, sizeof(dest), tech, sizeof(tech), args.zone, args.options, record, NULL);
213 p = strchr(dest, ':');
214 if (p && strcasecmp(tech, "ALL") && !strchr(args.options, 'u')) {
215 ast_copy_string(buf, p + 1, len);
217 ast_copy_string(buf, dest, len);
222 static unsigned int enum_datastore_id;
224 struct enum_result_datastore {
225 struct enum_context *context;
229 static void erds_destroy(struct enum_result_datastore *data)
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);
238 ast_free(data->context->naptr_rrs);
239 ast_free(data->context);
243 static void erds_destroy_cb(void *data)
245 struct enum_result_datastore *erds = data;
249 static const struct ast_datastore_info enum_result_datastore_info = {
251 .destroy = erds_destroy_cb,
254 static int enum_query_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
256 struct enum_result_datastore *erds;
257 struct ast_datastore *datastore;
258 char *parse, tech[128], dest[128];
261 AST_DECLARE_APP_ARGS(args,
267 if (ast_strlen_zero(data)) {
268 ast_log(LOG_WARNING, "ENUMQUERY requires at least a number as an argument...\n");
272 parse = ast_strdupa(data);
274 AST_STANDARD_APP_ARGS(args, parse);
277 ast_log(LOG_ERROR, "ENUMQUERY cannot be used without a channel!\n");
282 args.zone = "e164.zone";
284 ast_copy_string(tech, args.tech ? args.tech : "sip", sizeof(tech));
286 if (!(erds = ast_calloc(1, sizeof(*erds))))
289 if (!(erds->context = ast_calloc(1, sizeof(*erds->context)))) {
294 erds->id = ast_atomic_fetchadd_int((int *) &enum_datastore_id, 1);
296 snprintf(buf, len, "%u", erds->id);
298 if (!(datastore = ast_datastore_alloc(&enum_result_datastore_info, buf))) {
299 ast_free(erds->context);
304 ast_get_enum(chan, args.number, dest, sizeof(dest), tech, sizeof(tech), args.zone, "", 1, &erds->context);
306 datastore->data = erds;
308 ast_channel_lock(chan);
309 ast_channel_datastore_add(chan, datastore);
310 ast_channel_unlock(chan);
319 static int enum_result_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
321 struct enum_result_datastore *erds;
322 struct ast_datastore *datastore;
326 AST_DECLARE_APP_ARGS(args,
328 AST_APP_ARG(resultnum);
331 if (ast_strlen_zero(data)) {
332 ast_log(LOG_WARNING, "ENUMRESULT requires two arguments (id and resultnum)\n");
337 ast_log(LOG_ERROR, "ENUMRESULT can not be used without a channel!\n");
341 parse = ast_strdupa(data);
343 AST_STANDARD_APP_ARGS(args, parse);
345 if (ast_strlen_zero(args.id)) {
346 ast_log(LOG_ERROR, "A result ID must be provided to ENUMRESULT\n");
350 if (ast_strlen_zero(args.resultnum)) {
351 ast_log(LOG_ERROR, "A result number must be given to ENUMRESULT!\n");
355 ast_channel_lock(chan);
356 datastore = ast_channel_datastore_find(chan, &enum_result_datastore_info, args.id);
357 ast_channel_unlock(chan);
359 ast_log(LOG_WARNING, "No ENUM results found for query id!\n");
363 erds = datastore->data;
365 if (!strcasecmp(args.resultnum, "getnum")) {
366 snprintf(buf, len, "%d", erds->context->naptr_rrs_count);
371 if (sscanf(args.resultnum, "%30u", &num) != 1) {
372 ast_log(LOG_ERROR, "Invalid value '%s' for resultnum to ENUMRESULT!\n", args.resultnum);
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);
381 for (k = 0; k < erds->context->naptr_rrs_count; k++) {
382 if (num - 1 != erds->context->naptr_rrs[k].sort_pos)
385 p = strchr(erds->context->naptr_rrs[k].result, ':');
387 if (p && strcasecmp(erds->context->naptr_rrs[k].tech, "ALL"))
388 ast_copy_string(buf, p + 1, len);
390 ast_copy_string(buf, erds->context->naptr_rrs[k].result, len);
402 static struct ast_custom_function enum_query_function = {
404 .read = enum_query_read,
407 static struct ast_custom_function enum_result_function = {
408 .name = "ENUMRESULT",
409 .read = enum_result_read,
412 static struct ast_custom_function enum_function = {
413 .name = "ENUMLOOKUP",
414 .read = function_enum,
417 static int function_txtcidname(struct ast_channel *chan, const char *cmd,
418 char *data, char *buf, size_t len)
420 AST_DECLARE_APP_ARGS(args,
427 if (ast_strlen_zero(data)) {
428 ast_log(LOG_WARNING, "Syntax: TXTCIDNAME(number[,zone-suffix])\n");
432 AST_STANDARD_APP_ARGS(args, data);
435 ast_log(LOG_WARNING, "Syntax: TXTCIDNAME(number[,zone-suffix])\n");
440 args.zone = "e164.arpa";
443 ast_get_txt(chan, args.number, buf, len, args.zone);
448 static struct ast_custom_function txtcidname_function = {
449 .name = "TXTCIDNAME",
450 .read = function_txtcidname,
453 static int unload_module(void)
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);
465 static int load_module(void)
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);
477 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "ENUM related dialplan functions");