SRV and ENUM fixes (bug #'s 350 and 351)
[asterisk/asterisk.git] / apps / app_enumlookup.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * Time of day - Report the time of day
5  * 
6  * Copyright (C) 1999, Mark Spencer
7  *
8  * Mark Spencer <markster@linux-support.net>
9  *
10  * This program is free software, distributed under the terms of
11  * the GNU General Public License
12  */
13
14 #include <asterisk/lock.h>
15 #include <asterisk/file.h>
16 #include <asterisk/logger.h>
17 #include <asterisk/channel.h>
18 #include <asterisk/pbx.h>
19 #include <asterisk/options.h>
20 #include <asterisk/config.h>
21 #include <asterisk/module.h>
22 #include <asterisk/enum.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include <ctype.h>
28
29 #include <pthread.h>
30
31
32 static char *tdesc = "ENUM Lookup";
33
34 static char *app = "EnumLookup";
35
36 static char *synopsis = "Lookup number in ENUM";
37
38 static char *descrip = 
39 "  EnumLookup(exten):  Looks up an extension via ENUM and sets\n"
40 "the variable 'ENUM'. For VoIP URIs this variable will \n"
41 "look like 'TECHNOLOGY/URI' with the appropriate technology.\n"
42 "Returns -1 on hangup, or 0 on completion regardless of whether the \n"
43 "lookup was successful. \n"
44 "Currently, the enumservices SIP, H323, IAX, IAX2 and TEL are recognized. \n"
45 "A good SIP, H323, IAX or IAX2 entry will result in normal priority handling, \n"
46 "whereas a good TEL entry will increase the priority by 51 (if existing).\n"
47 "If the lookup was *not* successful and there exists a priority n + 101,\n"
48 "then that priority will be taken next.\n" ;
49
50 #define ENUM_CONFIG "enum.conf"
51
52 static char h323driver[80];
53 #define H323DRIVERDEFAULT "H323"
54
55 STANDARD_LOCAL_USER;
56
57 LOCAL_USER_DECL;
58
59 static int enumlookup_exec(struct ast_channel *chan, void *data)
60 {
61         int res=0;
62         char tech[80];
63         char dest[80];
64         char tmp[256];
65         char *c,*t;
66         struct localuser *u;
67         if (!data || !strlen(data)) {
68                 ast_log(LOG_WARNING, "EnumLookup requires an argument (extension)\n");
69                 res = 1;
70         }
71         LOCAL_USER_ADD(u);
72         if (!res) {
73                 res = ast_get_enum(chan, data, dest, sizeof(dest), tech, sizeof(tech));
74                 printf("ENUM got '%d'\n", res);
75         }
76         LOCAL_USER_REMOVE(u);
77         /* Parse it out */
78         if (res > 0) {
79                 if (!strcasecmp(tech, "SIP")) {
80                         c = dest;
81                         if (!strncmp(c, "sip:", 4))
82                                 c += 4;
83                         snprintf(tmp, sizeof(tmp), "SIP/%s", c);
84                         pbx_builtin_setvar_helper(chan, "ENUM", tmp);
85                 } else if (!strcasecmp(tech, "h323")) {
86                         c = dest;
87                         if (!strncmp(c, "h323:", 5))
88                                 c += 5;
89                         snprintf(tmp, sizeof(tmp), "%s/%s", h323driver, c);
90 /* do a s!;.*!! on the H323 URI */
91                         t = strchr(c,';');
92                         if (t) 
93                                 *t = 0;
94                         pbx_builtin_setvar_helper(chan, "ENUM", tmp);
95                 } else if (!strcasecmp(tech, "iax")) {
96                         c = dest;
97                         if (!strncmp(c, "iax:", 4))
98                                 c += 4;
99                         snprintf(tmp, sizeof(tmp), "IAX/%s", c);
100                         pbx_builtin_setvar_helper(chan, "ENUM", tmp);
101                 } else if (!strcasecmp(tech, "iax2")) {
102                         c = dest;
103                         if (!strncmp(c, "iax2:", 5))
104                                 c += 5;
105                         snprintf(tmp, sizeof(tmp), "IAX2/%s", c);
106                         pbx_builtin_setvar_helper(chan, "ENUM", tmp);
107                 } else if (!strcasecmp(tech, "tel")) {
108                         c = dest;
109                         if (!strncmp(c, "tel:", 4))
110                                 c += 4;
111
112                         if (c[0] != '+') {
113                                 ast_log(LOG_NOTICE, "tel: uri must start with a \"+\" (got '%s')\n", c);
114                                 res = 0;
115                         } else {
116 /* now copy over the number, skipping all non-digits and stop at ; or NULL */
117                                 t = tmp;        
118                                 while( *c && (*c != ';') && (t - tmp < (sizeof(tmp) - 1))) {
119                                         if (isdigit(*c))
120                                                 *t++ = *c;
121                                         c++;
122                                 }
123                                 *t = 0;
124                                 pbx_builtin_setvar_helper(chan, "ENUM", tmp);
125                                 ast_log(LOG_NOTICE, "tel: ENUM set to \"%s\"\n", tmp);
126                                 if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 51, chan->callerid))
127                                         chan->priority += 50;
128                                 else
129                                         res = 0;
130                         }
131                 } else if (strlen(tech)) {
132                         ast_log(LOG_NOTICE, "Don't know how to handle technology '%s'\n", tech);
133                         res = 0;
134                 }
135         }
136         if (!res) {
137                 /* Look for a "busy" place */
138                 if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
139                         chan->priority += 100;
140         } else if (res > 0)
141                 res = 0;
142         return res;
143 }
144
145 static int load_config(void)
146 {
147         struct ast_config *cfg;
148         char *s;
149
150         ast_log(LOG_WARNING, "reading enum config\n");
151
152         cfg = ast_load(ENUM_CONFIG);
153         if (cfg) {
154                 if (!(s=ast_variable_retrieve(cfg, "general", "h323driver"))) {
155                         strcpy(h323driver, H323DRIVERDEFAULT);
156                 } else {
157                         strcpy(h323driver, s);
158                 }
159                 ast_destroy(cfg);
160                 return 0;
161         }
162         ast_log(LOG_WARNING, "Error reading enum config\n");
163         return -1;
164 }
165
166
167 int unload_module(void)
168 {
169         STANDARD_HANGUP_LOCALUSERS;
170         return ast_unregister_application(app);
171 }
172
173 int load_module(void)
174 {
175         int res;
176         res = ast_register_application(app, enumlookup_exec, synopsis, descrip);
177         if (res)
178                 return(res);
179         if ((res=load_config())) {
180                 return(res);
181         }
182         return(0);
183 }
184
185 int reload(void)
186 {
187         return(load_config());
188 }
189
190
191 char *description(void)
192 {
193         return tdesc;
194 }
195
196 int usecount(void)
197 {
198         int res;
199         STANDARD_USECOUNT(res);
200         return res;
201 }
202
203 char *key()
204 {
205         return ASTERISK_GPL_KEY;
206 }
207