Wed, 10 Feb 2010 21:25:01 +0100
Extend uac_auth() of the UAC module to workaround CSEQ problems.
This logic is meant to complement that of changeset 17, which
added rich authentication credentials to the gw table and its
associated logic in the LCR module.
1 /*
2 * $Id: enum.c 5901 2009-07-21 07:45:05Z bogdan_iancu $
3 *
4 * Enum and E164 related functions
5 *
6 * Copyright (C) 2002-2008 Juha Heinanen
7 *
8 * This file is part of opensips, a free SIP server.
9 *
10 * opensips is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version
14 *
15 * opensips is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 */
26 #include <stdlib.h>
28 #include "enum.h"
29 #include "../../parser/parse_uri.h"
30 #include "../../parser/parse_from.h"
31 #include "../../ut.h"
32 #include "../../resolve.h"
33 #include "../../mem/mem.h"
34 #include "../../dset.h"
35 #include "../../qvalue.h"
36 #include "enum_mod.h"
37 #include "../../regexp.h"
38 #include "../../pvar.h"
40 /*
41 * Input: E.164 number w/o leading +
42 *
43 * Output: number of digits in the country code
44 * 0 on invalid number
45 *
46 * convention:
47 * 3 digits is the default length of a country code.
48 * country codes 1 and 7 are a single digit.
49 * the following country codes are two digits: 20, 27, 30-34, 36, 39,
50 * 40, 41, 43-49, 51-58, 60-66, 81, 82, 84, 86, 90-95, 98.
51 */
52 static int cclen(const char *number)
53 {
54 char d1,d2;
56 if (!number || (strlen(number) < 3))
57 return(0);
59 d1 = number[0];
60 d2 = number[1];
62 if (!isdigit((int)d2))
63 return(0);
65 switch(d1) {
66 case '1':
67 case '7':
68 return(1);
69 case '2':
70 if ((d2 == '0') || (d1 == '7'))
71 return(2);
72 break;
73 case '3':
74 if ((d2 >= '0') && (d1 <= '4'))
75 return(2);
76 if ((d2 == '6') || (d1 == '9'))
77 return(2);
78 break;
79 case '4':
80 if (d2 != '2')
81 return(2);
82 break;
83 case '5':
84 if ((d2 >= '1') && (d1 <= '8'))
85 return(2);
86 break;
87 case '6':
88 if (d1 <= '6')
89 return(2);
90 break;
91 case '8':
92 if ((d2 == '1') || (d1 == '2') || (d1 == '4') || (d1 == '6'))
93 return(2);
94 break;
95 case '9':
96 if (d1 <= '5')
97 return(2);
98 if (d2 == '8')
99 return(2);
100 break;
101 default:
102 return(0);
103 }
105 return(3);
106 }
110 /* return the length of the string until c, if not found returns n */
111 static inline int findchr(char* p, int c, unsigned int size)
112 {
113 int len=0;
115 for(;len<size;p++){
116 if (*p==(unsigned char)c) {
117 return len;
118 }
119 len++;
120 }
121 return len;
122 }
125 /* Parse NAPTR regexp field of the form !pattern!replacement! and return its
126 * components in pattern and replacement parameters. Regexp field starts at
127 * address first and is len characters long.
128 */
129 static inline int parse_naptr_regexp(char* first, int len, str* pattern,
130 str* replacement)
131 {
132 char *second, *third;
134 if (len > 0) {
135 if (*first == '!') {
136 second = (char *)memchr((void *)(first + 1), '!', len - 1);
137 if (second) {
138 len = len - (second - first + 1);
139 if (len > 0) {
140 third = memchr(second + 1, '!', len);
141 if (third) {
142 pattern->len = second - first - 1;
143 pattern->s = first + 1;
144 replacement->len = third - second - 1;
145 replacement->s = second + 1;
146 return 1;
147 } else {
148 LM_ERR("Third ! missing from regexp\n");
149 return -1;
150 }
151 } else {
152 LM_ERR("Third ! missing from regexp\n");
153 return -2;
154 }
155 } else {
156 LM_ERR("Second ! missing from regexp\n");
157 return -3;
158 }
159 } else {
160 LM_ERR("First ! missing from regexp\n");
161 return -4;
162 }
163 } else {
164 LM_ERR("Regexp missing\n");
165 return -5;
166 }
167 }
168 /* Checks if NAPTR record has flag u and its services field
169 * e2u+[service:]sip or
170 * e2u+service[+service[+service[+...]]]
171 */
172 static inline int sip_match( struct naptr_rdata* naptr, str* service)
173 {
174 if (service->len == 0) {
175 return (naptr->flags_len == 1) &&
176 ((naptr->flags[0] == 'u') || (naptr->flags[0] == 'U')) &&
177 (naptr->services_len == 7) &&
178 ((strncasecmp(naptr->services, "e2u+sip", 7) == 0) ||
179 (strncasecmp(naptr->services, "sip+e2u", 7) == 0));
180 } else if (service->s[0] != '+') {
181 return (naptr->flags_len == 1) &&
182 ((naptr->flags[0] == 'u') || (naptr->flags[0] == 'U')) &&
183 (naptr->services_len == service->len + 8) &&
184 (strncasecmp(naptr->services, "e2u+", 4) == 0) &&
185 (strncasecmp(naptr->services + 4, service->s, service->len) == 0) &&
186 (strncasecmp(naptr->services + 4 + service->len, ":sip", 4) == 0);
187 } else { /* handle compound NAPTRs and multiple services */
188 str bakservice, baknaptr; /* we bakup the str */
189 int naptrlen, len; /* length of the extracted service */
191 /* RFC 3761, NAPTR service field must start with E2U+ */
192 if (strncasecmp(naptr->services, "e2u+", 4) != 0) {
193 return 0;
194 }
195 baknaptr.s = naptr->services + 4; /* leading 'e2u+' */
196 baknaptr.len = naptr->services_len - 4;
197 for (;;) { /* iterate over services in NAPTR */
198 bakservice.s = service->s + 1; /* leading '+' */
199 bakservice.len = service->len - 1;
200 naptrlen = findchr(baknaptr.s,'+',baknaptr.len);
202 for (;;) { /* iterate over services in enum_query */
203 len = findchr(bakservice.s,'+',bakservice.len);
204 if ((naptrlen == len ) && !strncasecmp(baknaptr.s, bakservice.s, len)){
205 return 1;
206 }
207 if ( (bakservice.len -= len+1) > 0) {
208 bakservice.s += len+1;
209 continue;
210 }
211 break;
212 }
213 if ( (baknaptr.len -= naptrlen+1) > 0) {
214 baknaptr.s += naptrlen+1;
215 continue;
216 }
217 break;
218 }
219 /* no matching service found */
220 return 0;
221 }
222 }
225 /*
226 * Checks if argument is an e164 number starting with +
227 */
228 static inline int is_e164(str* _user)
229 {
230 int i;
231 char c;
233 if ((_user->len > 2) && (_user->len < 17) && ((_user->s)[0] == '+')) {
234 for (i = 1; i < _user->len; i++) {
235 c = (_user->s)[i];
236 if ((c < '0') || (c > '9')) return -1;
237 }
238 return 1;
239 } else {
240 return -1;
241 }
242 }
245 /*
246 * Call is_from_user_enum_2 with module parameter suffix and default service.
247 */
248 int is_from_user_enum_0(struct sip_msg* _msg, char* _str1, char* _str2)
249 {
250 return is_from_user_enum_2(_msg, (char *)(&suffix), (char *)(&service));
251 }
253 /*
254 * Call is_from_user_enum_2 with given suffix and default service.
255 */
256 int is_from_user_enum_1(struct sip_msg* _msg, char* _suffix, char* _str2)
257 {
258 return is_from_user_enum_2(_msg, _suffix, (char *)(&service));
259 }
261 /*
262 * Check if from user is a valid enum based user, and check to make sure
263 * that the src_ip == an srv record that maps to the enum from user.
264 */
265 int is_from_user_enum_2(struct sip_msg* _msg, char* _suffix, char* _service)
266 {
267 struct ip_addr addr;
268 struct hostent* he;
269 unsigned short zp;
270 unsigned short proto;
271 char *user_s;
272 int user_len, i, j;
273 char name[MAX_DOMAIN_SIZE];
274 char uri[MAX_URI_SIZE];
275 struct sip_uri *furi;
276 struct sip_uri luri;
277 struct rdata* head;
279 str* suffix;
280 str* service;
282 struct rdata* l;
283 struct naptr_rdata* naptr;
285 str pattern, replacement, result;
286 char string[17];
288 if (parse_from_header(_msg) < 0) {
289 LM_ERR("Failed to parse From header\n");
290 return -1;
291 }
293 if(_msg->from==NULL || get_from(_msg)==NULL) {
294 LM_DBG("No From header\n");
295 return -1;
296 }
298 if ((furi = parse_from_uri(_msg)) == NULL) {
299 LM_ERR("Failed to parse From URI\n");
300 return -1;
301 }
303 suffix = (str*)_suffix;
304 service = (str*)_service;
306 if (is_e164(&(furi->user)) == -1) {
307 LM_ERR("From URI user is not an E164 number\n");
308 return -1;
309 }
311 /* assert: the from user is a valid formatted e164 string */
313 user_s = furi->user.s;
314 user_len = furi->user.len;
316 j = 0;
317 for (i = user_len - 1; i > 0; i--) {
318 name[j] = user_s[i];
319 name[j + 1] = '.';
320 j = j + 2;
321 }
323 memcpy(name + j, suffix->s, suffix->len + 1);
325 head = get_record(name, T_NAPTR);
327 if (head == 0) {
328 LM_DBG("No NAPTR record found for %s.\n", name);
329 return -3;
330 }
332 /* we have the naptr records, loop and find an srv record with */
333 /* same ip address as source ip address, if we do then true is returned */
335 for (l = head; l; l = l->next) {
337 if (l->type != T_NAPTR) continue; /*should never happen*/
338 naptr = (struct naptr_rdata*)l->rdata;
339 if (naptr == 0) {
340 LM_ERR("Null rdata in DNS response\n");
341 free_rdata_list(head);
342 return -4;
343 }
345 LM_DBG("ENUM query on %s: order %u, pref %u, flen %u, flags "
346 "'%.*s', slen %u, services '%.*s', rlen %u, "
347 "regexp '%.*s'\n",
348 name, naptr->order, naptr->pref,
349 naptr->flags_len, (int)(naptr->flags_len), ZSW(naptr->flags), naptr->services_len,
350 (int)(naptr->services_len), ZSW(naptr->services), naptr->regexp_len,
351 (int)(naptr->regexp_len), ZSW(naptr->regexp));
353 if (sip_match(naptr, service) != 0) {
354 if (parse_naptr_regexp(&(naptr->regexp[0]), naptr->regexp_len,
355 &pattern, &replacement) < 0) {
356 free_rdata_list(head); /*clean up*/
357 LM_ERR("Parsing of NAPTR regexp failed\n");
358 return -5;
359 }
360 #ifdef LATER
361 if ((pattern.len == 4) && (strncmp(pattern.s, "^.*$", 4) == 0)) {
362 LM_DBG("Resulted in replacement: '%.*s'\n",
363 replacement.len, ZSW(replacement.s));
364 retval = set_uri(_msg, replacement.s, replacement.len);
365 free_rdata_list(head); /*clean up*/
366 return retval;
367 }
368 #endif
369 result.s = &(uri[0]);
370 result.len = MAX_URI_SIZE;
371 /* Avoid making copies of pattern and replacement */
372 pattern.s[pattern.len] = (char)0;
373 replacement.s[replacement.len] = (char)0;
374 /* We have already checked the size of
375 _msg->parsed_uri.user.s */
376 memcpy(&(string[0]), user_s, user_len);
377 string[user_len] = (char)0;
378 if (reg_replace(pattern.s, replacement.s, &(string[0]),
379 &result) < 0) {
380 pattern.s[pattern.len] = '!';
381 replacement.s[replacement.len] = '!';
382 LM_ERR("Regexp replace failed\n");
383 free_rdata_list(head); /*clean up*/
384 return -6;
385 }
386 LM_DBG("Resulted in replacement: '%.*s'\n",
387 result.len, ZSW(result.s));
389 if(parse_uri(result.s, result.len, &luri) < 0)
390 {
391 LM_ERR("Parsing of URI <%.*s> failed\n",
392 result.len, result.s);
393 free_rdata_list(head); /*clean up*/
394 return -7;
395 }
397 pattern.s[pattern.len] = '!';
398 replacement.s[replacement.len] = '!';
400 zp = 0;
401 proto = PROTO_NONE;
402 he = sip_resolvehost(&luri.host, &zp, &proto,
403 (luri.type==SIPS_URI_T)?1:0 , 0);
405 hostent2ip_addr(&addr, he, 0);
407 if(ip_addr_cmp(&addr, &_msg->rcv.src_ip))
408 {
409 free_rdata_list(head);
410 return(1);
411 }
412 }
413 }
414 free_rdata_list(head); /*clean up*/
415 LM_DBG("FAIL\n");
417 /* must not have found the record */
418 return(-8);
419 }
423 /*
424 * Add parameter to URI.
425 */
426 int add_uri_param(str *uri, str *param, str *new_uri)
427 {
428 struct sip_uri puri;
429 char *at;
431 if (parse_uri(uri->s, uri->len, &puri) < 0) {
432 return 0;
433 }
435 /* if current uri has no headers, pad param to the end of uri */
436 if (puri.headers.len == 0) {
437 memcpy(uri->s + uri->len, param->s, param->len);
438 uri->len = uri->len + param->len;
439 new_uri->len = 0;
440 return 1;
441 }
443 /* otherwise take the long path and create new_uri */
444 at = new_uri->s;
445 switch (puri.type) {
446 case SIP_URI_T:
447 memcpy(at, "sip:", 4);
448 at = at + 4;
449 break;
450 case SIPS_URI_T:
451 memcpy(at, "sips:", 5);
452 at = at + 5;
453 break;
454 case TEL_URI_T:
455 memcpy(at, "tel:", 4);
456 at = at + 4;
457 break;
458 case TELS_URI_T:
459 memcpy(at, "tels:", 5);
460 at = at + 5;
461 break;
462 default:
463 LM_ERR("Unknown URI scheme <%d>\n", puri.type);
464 return 0;
465 }
466 if (puri.user.len) {
467 memcpy(at, puri.user.s, puri.user.len);
468 at = at + puri.user.len;
469 if (puri.passwd.len) {
470 *at = ':';
471 at = at + 1;
472 memcpy(at, puri.passwd.s, puri.passwd.len);
473 at = at + puri.passwd.len;
474 };
475 *at = '@';
476 at = at + 1;
477 }
478 memcpy(at, puri.host.s, puri.host.len);
479 at = at + puri.host.len;
480 if (puri.port.len) {
481 *at = ':';
482 at = at + 1;
483 memcpy(at, puri.port.s, puri.port.len);
484 at = at + puri.port.len;
485 }
486 if (puri.params.len) {
487 *at = ';';
488 at = at + 1;
489 memcpy(at, puri.params.s, puri.params.len);
490 at = at + puri.params.len;
491 }
492 memcpy(at, param->s, param->len);
493 at = at + param->len;
494 *at = '?';
495 at = at + 1;
496 memcpy(at, puri.headers.s, puri.headers.len);
497 at = at + puri.headers.len;
498 new_uri->len = at - new_uri->s;
499 return 1;
500 }
502 /*
503 * Tests if one result record is "greater" that the other. Non-NAPTR records
504 * greater that NAPTR record. An invalid NAPTR record is greater than a
505 * valid one. Valid NAPTR records are compared based on their
506 * (order,preference).
507 */
508 static inline int naptr_greater(struct rdata* a, struct rdata* b)
509 {
510 struct naptr_rdata *na, *nb;
512 if (a->type != T_NAPTR) return 1;
513 if (b->type != T_NAPTR) return 0;
515 na = (struct naptr_rdata*)a->rdata;
516 if (na == 0) return 1;
518 nb = (struct naptr_rdata*)b->rdata;
519 if (nb == 0) return 0;
521 return (((na->order) << 16) + na->pref) >
522 (((nb->order) << 16) + nb->pref);
523 }
526 /*
527 * Bubble sorts result record list according to naptr (order,preference).
528 */
529 static inline void naptr_sort(struct rdata** head)
530 {
531 struct rdata *p, *q, *r, *s, *temp, *start;
533 /* r precedes p and s points to the node up to which comparisons
534 are to be made */
536 s = NULL;
537 start = *head;
538 while ( s != start -> next ) {
539 r = p = start ;
540 q = p -> next ;
541 while ( p != s ) {
542 if ( naptr_greater(p, q) ) {
543 if ( p == start ) {
544 temp = q -> next ;
545 q -> next = p ;
546 p -> next = temp ;
547 start = q ;
548 r = q ;
549 } else {
550 temp = q -> next ;
551 q -> next = p ;
552 p -> next = temp ;
553 r -> next = q ;
554 r = q ;
555 }
556 } else {
557 r = p ;
558 p = p -> next ;
559 }
560 q = p -> next ;
561 if ( q == s ) s = p ;
562 }
563 }
564 *head = start;
565 }
568 /*
569 * Makes enum query on name. On success, rewrites user part and
570 * replaces Request-URI.
571 */
572 int do_query(struct sip_msg* _msg, char *user, char *name, str *service) {
574 char uri[MAX_URI_SIZE];
575 char new_uri[MAX_URI_SIZE];
576 unsigned int priority, curr_prio, first;
577 qvalue_t q;
578 struct rdata* head;
579 struct rdata* l;
580 struct naptr_rdata* naptr;
581 str pattern, replacement, result, new_result;
583 head = get_record(name, T_NAPTR);
585 if (head == 0) {
586 LM_DBG("No NAPTR record found for %s.\n", name);
587 return -1;
588 }
590 naptr_sort(&head);
592 q = MAX_Q - 10;
593 curr_prio = 0;
594 first = 1;
596 for (l = head; l; l = l->next) {
598 if (l->type != T_NAPTR) continue; /*should never happen*/
599 naptr = (struct naptr_rdata*)l->rdata;
600 if (naptr == 0) {
601 LM_ERR("Null rdata in DNS response\n");
602 continue;
603 }
605 LM_DBG("ENUM query on %s: order %u, pref %u, flen %u, flags '%.*s', "
606 "slen %u, services '%.*s', rlen %u, regexp '%.*s'\n",
607 name, naptr->order, naptr->pref,
608 naptr->flags_len, (int)(naptr->flags_len), ZSW(naptr->flags),
609 naptr->services_len,
610 (int)(naptr->services_len), ZSW(naptr->services), naptr->regexp_len,
611 (int)(naptr->regexp_len), ZSW(naptr->regexp));
613 if (sip_match(naptr, service) == 0) continue;
615 if (parse_naptr_regexp(&(naptr->regexp[0]), naptr->regexp_len,
616 &pattern, &replacement) < 0) {
617 LM_ERR("Parsing of NAPTR regexp failed\n");
618 continue;
619 }
620 result.s = &(uri[0]);
621 result.len = MAX_URI_SIZE;
622 /* Avoid making copies of pattern and replacement */
623 pattern.s[pattern.len] = (char)0;
624 replacement.s[replacement.len] = (char)0;
625 if (reg_replace(pattern.s, replacement.s, user, &result) < 0) {
626 pattern.s[pattern.len] = '!';
627 replacement.s[replacement.len] = '!';
628 LM_ERR("Regexp replace failed\n");
629 continue;
630 }
631 LM_DBG("Resulted in replacement: '%.*s'\n", result.len, ZSW(result.s));
632 pattern.s[pattern.len] = '!';
633 replacement.s[replacement.len] = '!';
635 if (param.len > 0) {
636 if (result.len + param.len > MAX_URI_SIZE - 1) {
637 LM_ERR("URI is too long\n");
638 continue;
639 }
640 new_result.s = &(new_uri[0]);
641 new_result.len = MAX_URI_SIZE;
642 if (add_uri_param(&result, ¶m, &new_result) == 0) {
643 LM_ERR("Parsing of URI <%.*s> failed\n",
644 result.len, result.s);
645 continue;
646 }
647 if (new_result.len > 0) {
648 result = new_result;
649 }
650 }
652 if (first) {
653 if (set_ruri(_msg, &result) == -1) {
654 goto done;
655 }
656 set_ruri_q(q);
657 first = 0;
658 curr_prio = ((naptr->order) << 16) + naptr->pref;
659 } else {
660 priority = ((naptr->order) << 16) + naptr->pref;
661 if (priority > curr_prio) {
662 q = q - 10;
663 curr_prio = priority;
664 }
665 if (append_branch(_msg, &result, 0, 0, q, 0, 0) == -1) {
666 goto done;
667 }
668 }
669 }
671 done:
672 free_rdata_list(head);
673 return first ? -1 : 1;
674 }
677 /*
678 * Call enum_query_2 with module parameter suffix and default service.
679 */
680 int enum_query_0(struct sip_msg* _msg, char* _str1, char* _str2)
681 {
682 return enum_query_2(_msg, (char *)(&suffix), (char *)(&service));
683 }
686 /*
687 * Call enum_query_2 with given suffix and default service.
688 */
689 int enum_query_1(struct sip_msg* _msg, char* _suffix, char* _str2)
690 {
691 return enum_query_2(_msg, _suffix, (char *)(&service));
692 }
695 /*
696 * See documentation in README file.
697 */
698 int enum_query_2(struct sip_msg* _msg, char* _suffix, char* _service)
699 {
700 char *user_s;
701 int user_len, i, j;
702 char name[MAX_DOMAIN_SIZE];
703 char string[17];
705 str *suffix, *service;
707 suffix = (str*)_suffix;
708 service = (str*)_service;
710 if (parse_sip_msg_uri(_msg) < 0) {
711 LM_ERR("Parsing of R-URI failed\n");
712 return -1;
713 }
715 if (is_e164(&(_msg->parsed_uri.user)) == -1) {
716 LM_ERR("R-URI user is not an E164 number\n");
717 return -1;
718 }
720 user_s = _msg->parsed_uri.user.s;
721 user_len = _msg->parsed_uri.user.len;
723 memcpy(&(string[0]), user_s, user_len);
724 string[user_len] = (char)0;
726 j = 0;
727 for (i = user_len - 1; i > 0; i--) {
728 name[j] = user_s[i];
729 name[j + 1] = '.';
730 j = j + 2;
731 }
733 memcpy(name + j, suffix->s, suffix->len + 1);
735 return do_query(_msg, string, name, service);
736 }
739 /*
740 * Call isn_query_2 with module parameter suffix and default service.
741 */
742 int isn_query_0(struct sip_msg* _msg, char* _str1, char* _str2)
743 {
744 return isn_query_2(_msg, (char *)(&isnsuffix), (char *)(&service));
745 }
748 /*
749 * Call isn_query_2 with given suffix and default service.
750 */
751 int isn_query_1(struct sip_msg* _msg, char* _suffix, char* _str2)
752 {
753 return isn_query_2(_msg, _suffix, (char *)(&service));
754 }
757 /*
758 * See documentation in README file.
759 */
760 int isn_query_2(struct sip_msg* _msg, char* _suffix, char* _service)
761 {
762 char *user_s = NULL;
763 int user_len, i, j;
764 char name[MAX_DOMAIN_SIZE] = {0};
765 char string[17] = {0};
766 char szItad[17] = {0};
767 size_t nItlen = 0;
769 str *suffix, *service;
771 suffix = (str*)_suffix;
772 service = (str*)_service;
774 if (parse_sip_msg_uri(_msg) < 0) {
775 LM_ERR("Parsing of R-URI failed\n");
776 return -1;
777 }
779 user_s = _msg->parsed_uri.user.s;
780 user_len = _msg->parsed_uri.user.len;
782 memcpy(&(string[0]), user_s, user_len);
783 string[user_len] = (char)0;
785 /* Do primitive test for correct ISN format, */
786 /* and set szItad to the ISN ITAD (RFC 3872/2871). */
787 /* Correct ISN format guessed from freenum.org and IANA */
788 /* doc http://www.iana.org/assignments/trip-parameters/ */
789 {
790 char *pAster = strchr(string, '*');
791 if (pAster && (nItlen = strspn(pAster + sizeof(char), "0123456789")))
792 strncpy(szItad, pAster + sizeof(char), nItlen);
793 else {
794 LM_ERR("R-URI user does not contain a valid ISN\n");
795 return -1;
796 }
797 }
799 /* Ammend the original ENUM E.164 string logic to process */
800 /* ISN numbers instead, which include a nonreversed ITAD. */
801 i = user_len - nItlen - sizeof(char); /* Ex: *1212 */
802 j = 0;
803 while (i--) {
804 name[j] = user_s[i];
805 name[j + 1] = '.';
806 j = j + 2;
807 }
809 strcat(name + j, szItad); /* Copy the unreversed ITAD, */
810 name[j + nItlen] = '.'; /* and append a trailing dot. */
811 memcpy(name + j + nItlen + sizeof(char), suffix->s, suffix->len + 1);
813 return do_query(_msg, string, name, service);
814 }
817 /*********** INFRASTRUCTURE ENUM ***************/
819 /*
820 * Call enum_query_2 with default suffix and service.
821 */
822 int i_enum_query_0(struct sip_msg* _msg, char* _suffix, char* _service)
823 {
824 return i_enum_query_2(_msg, (char *)(&i_suffix), (char *)(&service));
825 }
827 /*
828 * Call enum_query_2 with given suffix and default service.
829 */
830 int i_enum_query_1(struct sip_msg* _msg, char* _suffix, char* _service)
831 {
832 return i_enum_query_2(_msg, _suffix, (char *)(&service));
833 }
836 int i_enum_query_2(struct sip_msg* _msg, char* _suffix, char* _service)
837 {
838 char *user_s;
839 int user_len, i, j;
840 char name[MAX_DOMAIN_SIZE];
841 char apex[MAX_COMPONENT_SIZE + 1];
842 char separator[MAX_COMPONENT_SIZE + 1];
843 int sdl = 0; /* subdomain location: infrastructure enum offset */
844 int cc_len;
845 struct rdata* head;
847 char string[17];
849 str *suffix, *service;
851 suffix = (str*)_suffix;
852 service = (str*)_service;
854 if (parse_sip_msg_uri(_msg) < 0) {
855 LM_ERR("Parsing of R-URI failed\n");
856 return -1;
857 }
859 if (is_e164(&(_msg->parsed_uri.user)) == -1) {
860 LM_ERR("R-URI user is not an E164 number\n");
861 return -1;
862 }
864 user_s = _msg->parsed_uri.user.s;
865 user_len = _msg->parsed_uri.user.len;
867 /* make sure we don't run out of space in strings */
868 if (( 2*user_len + MAX_COMPONENT_SIZE + MAX_COMPONENT_SIZE + 4) > MAX_DOMAIN_SIZE) {
869 LM_ERR("Strings too long\n");
870 return -1;
871 }
872 if ( i_branchlabel.len > MAX_COMPONENT_SIZE ) {
873 LM_ERR("i_branchlabel too long\n");
874 return -1;
875 }
876 if ( suffix->len > MAX_COMPONENT_SIZE ) {
877 LM_ERR("Suffix too long\n");
878 return -1;
879 }
882 memcpy(&(string[0]), user_s, user_len);
883 string[user_len] = (char)0;
885 /* Set up parameters as for user-enum */
886 memcpy(apex, suffix->s , suffix->len);
887 apex[suffix->len] = (char)0;
888 sdl = 0; /* where to insert i-enum separator */
889 separator[0] = 0; /* don't insert anything */
891 cc_len = cclen(string + 1);
893 if (!strncasecmp(i_bl_alg.s,"ebl",i_bl_alg.len)) {
894 sdl = cc_len; /* default */
896 j = 0;
897 memcpy(name, i_branchlabel.s, i_branchlabel.len);
898 j += i_branchlabel.len;
899 name[j++] = '.';
901 for (i = cc_len ; i > 0; i--) {
902 name[j++] = user_s[i];
903 name[j++] = '.';
904 }
905 memcpy(name + j, suffix->s, suffix->len + 1);
907 LM_DBG("Looking for EBL record for %s.\n", name);
908 head = get_record(name, T_EBL);
909 if (head == 0) {
910 LM_DBG("No EBL found for %s. Defaulting to user ENUM.\n",name);
911 } else {
912 struct ebl_rdata* ebl;
913 ebl = (struct ebl_rdata *) head->rdata;
915 LM_DBG("EBL record for %s is %d / %.*s / %.*s.\n",
916 name, ebl->position, (int)ebl->separator_len,
917 ebl->separator,(int)ebl->apex_len, ebl->apex);
919 if ((ebl->apex_len > MAX_COMPONENT_SIZE) || (ebl->separator_len > MAX_COMPONENT_SIZE)) {
920 LM_ERR("EBL strings too long\n");
921 return -1;
922 }
924 if (ebl->position > 15) {
925 LM_ERR("EBL position too large (%d)\n",
926 ebl->position);
927 return -1;
928 }
930 sdl = ebl->position;
932 memcpy(separator, ebl->separator, ebl->separator_len);
933 separator[ebl->separator_len] = 0;
935 memcpy(apex, ebl->apex, ebl->apex_len);
936 apex[ebl->apex_len] = 0;
937 free_rdata_list(head);
938 }
939 } else if (!strncasecmp(i_bl_alg.s,"txt",i_bl_alg.len)) {
940 sdl = cc_len; /* default */
941 memcpy(separator, i_branchlabel.s, i_branchlabel.len);
942 separator[i_branchlabel.len] = 0;
943 /* no change to apex */
945 j = 0;
946 memcpy(name, i_branchlabel.s, i_branchlabel.len);
947 j += i_branchlabel.len;
948 name[j++] = '.';
950 for (i = cc_len ; i > 0; i--) {
951 name[j++] = user_s[i];
952 name[j++] = '.';
953 }
954 memcpy(name + j, suffix->s, suffix->len + 1);
956 head = get_record(name, T_TXT);
957 if (head == 0) {
958 LM_DBG("TXT found for %s. Defaulting to %d\n",
959 name, cc_len);
960 } else {
961 sdl = atoi(((struct txt_rdata*)head->rdata)->txt);
962 LM_DBG("TXT record for %s is %d.\n", name, sdl);
964 if ((sdl < 0) || (sdl > 10)) {
965 LM_ERR("Sdl %d out of bounds. Set back to cc_len.\n", sdl);
966 sdl = cc_len;
967 }
968 free_rdata_list(head);
969 }
970 } else { /* defaults to CC */
971 sdl = cc_len;
972 memcpy(separator, i_branchlabel.s, i_branchlabel.len);
973 separator[i_branchlabel.len] = 0;
974 /* no change to apex */
975 }
977 j = 0;
978 sdl++; /* to avoid comparing i to (sdl+1) */
979 for (i = user_len - 1; i > 0; i--) {
980 name[j] = user_s[i];
981 name[j + 1] = '.';
982 j = j + 2;
983 if (separator[0] && (i == sdl)) { /* insert the I-ENUM separator here? */
984 strcpy(name + j, separator); /* we've checked string sizes. */
985 j += strlen(separator);
986 name[j++] = '.';
987 }
988 }
990 memcpy(name + j, apex, strlen(apex)+1);
992 return do_query(_msg, string, name, service);
993 }
997 /******************* FQUERY *******************/
1000 /*
1001 * Call enum_pv_query_3 with pv arg, module parameter suffix,
1002 * and default service.
1003 */
1004 int enum_pv_query_1(struct sip_msg* _msg, char* _sp)
1005 {
1006 return enum_pv_query_3(_msg, _sp, (char *)(&suffix), (char *)(&service));
1007 }
1009 /*
1010 * Call enum_pv_query_3 with pv and suffix args and default service.
1011 */
1012 int enum_pv_query_2(struct sip_msg* _msg, char* _sp, char* _suffix)
1013 {
1014 return enum_pv_query_3(_msg, _sp, _suffix, (char *)(&service));
1015 }
1017 /*
1018 * See documentation in README file.
1019 */
1021 int enum_pv_query_3(struct sip_msg* _msg, char* _sp, char* _suffix,
1022 char* _service)
1023 {
1024 char *user_s;
1025 int user_len, i, j, first;
1026 char name[MAX_DOMAIN_SIZE];
1027 char uri[MAX_URI_SIZE];
1028 char new_uri[MAX_URI_SIZE];
1029 unsigned int priority, curr_prio;
1030 qvalue_t q;
1031 char tostring[17];
1032 struct rdata* head;
1033 struct rdata* l;
1034 struct naptr_rdata* naptr;
1035 str pattern, replacement, result, new_result;
1036 str *suffix, *service;
1037 char string[17];
1038 pv_spec_t *sp;
1039 pv_value_t pv_val;
1041 sp = (pv_spec_t *)_sp;
1042 suffix = (str*)_suffix;
1043 service = (str*)_service;
1045 /*
1046 * Get R-URI user to tostring
1047 */
1048 if (parse_sip_msg_uri(_msg) < 0) {
1049 LM_ERR("R-URI parsing failed\n");
1050 return -1;
1051 }
1053 if (is_e164(&(_msg->parsed_uri.user)) == -1) {
1054 LM_ERR("R-URI user is not an E164 number\n");
1055 return -1;
1056 }
1058 user_s = _msg->parsed_uri.user.s;
1059 user_len = _msg->parsed_uri.user.len;
1061 memcpy(&(tostring[0]), user_s, user_len);
1062 tostring[user_len] = (char)0;
1064 /*
1065 * Get E.164 number from pseudo variable
1066 */
1067 if (sp && (pv_get_spec_value(_msg, sp, &pv_val) == 0)) {
1068 if (pv_val.flags & PV_VAL_STR) {
1069 if (pv_val.rs.len == 0 || pv_val.rs.s == NULL) {
1070 LM_DBG("Missing E.164 number\n");
1071 return -1;
1072 }
1073 } else {
1074 LM_DBG("Pseudo variable value is not string\n");
1075 return -1;
1076 }
1077 } else {
1078 LM_DBG("Cannot get pseudo variable value\n");
1079 return -1;
1080 }
1081 if (is_e164(&(pv_val.rs)) == -1) {
1082 LM_ERR("pseudo variable does not contain an E164 number\n");
1083 return -1;
1084 }
1086 user_s = pv_val.rs.s;
1087 user_len = pv_val.rs.len;
1089 memcpy(&(string[0]), user_s, user_len);
1090 string[user_len] = (char)0;
1092 j = 0;
1093 for (i = user_len - 1; i > 0; i--) {
1094 name[j] = user_s[i];
1095 name[j + 1] = '.';
1096 j = j + 2;
1097 }
1099 memcpy(name + j, suffix->s, suffix->len + 1);
1101 head = get_record(name, T_NAPTR);
1103 if (head == 0) {
1104 LM_DBG("No NAPTR record found for %s.\n", name);
1105 return -1;
1106 }
1108 naptr_sort(&head);
1110 q = MAX_Q - 10;
1111 curr_prio = 0;
1112 first = 1;
1114 for (l = head; l; l = l->next) {
1116 if (l->type != T_NAPTR) continue; /*should never happen*/
1117 naptr = (struct naptr_rdata*)l->rdata;
1118 if (naptr == 0) {
1119 LM_ERR("Null rdata in DNS response\n");
1120 continue;
1121 }
1123 LM_DBG("ENUM query on %s: order %u, pref %u, flen %u, flags "
1124 "'%.*s', slen %u, services '%.*s', rlen %u, "
1125 "regexp '%.*s'\n",
1126 name, naptr->order, naptr->pref,
1127 naptr->flags_len, (int)(naptr->flags_len), ZSW(naptr->flags),
1128 naptr->services_len,
1129 (int)(naptr->services_len), ZSW(naptr->services), naptr->regexp_len,
1130 (int)(naptr->regexp_len), ZSW(naptr->regexp));
1132 if (sip_match(naptr, service) == 0) continue;
1134 if (parse_naptr_regexp(&(naptr->regexp[0]), naptr->regexp_len,
1135 &pattern, &replacement) < 0) {
1136 LM_ERR("Parsing of NAPTR regexp failed\n");
1137 continue;
1138 }
1139 result.s = &(uri[0]);
1140 result.len = MAX_URI_SIZE;
1141 /* Avoid making copies of pattern and replacement */
1142 pattern.s[pattern.len] = (char)0;
1143 replacement.s[replacement.len] = (char)0;
1144 if (reg_replace(pattern.s, replacement.s, &(tostring[0]),
1145 &result) < 0) {
1146 pattern.s[pattern.len] = '!';
1147 replacement.s[replacement.len] = '!';
1148 LM_ERR("Regexp replace failed\n");
1149 continue;
1150 }
1151 LM_DBG("Resulted in replacement: '%.*s'\n",
1152 result.len, ZSW(result.s));
1153 pattern.s[pattern.len] = '!';
1154 replacement.s[replacement.len] = '!';
1156 if (param.len > 0) {
1157 if (result.len + param.len > MAX_URI_SIZE - 1) {
1158 LM_ERR("URI is too long\n");
1159 continue;
1160 }
1161 new_result.s = &(new_uri[0]);
1162 new_result.len = MAX_URI_SIZE;
1163 if (add_uri_param(&result, ¶m, &new_result) == 0) {
1164 LM_ERR("Parsing of URI <%.*s> failed\n",
1165 result.len, result.s);
1166 continue;
1167 }
1168 if (new_result.len > 0) {
1169 result = new_result;
1170 }
1171 }
1173 if (first) {
1174 if (set_ruri(_msg, &result) == -1) {
1175 goto done;
1176 }
1177 set_ruri_q(q);
1178 first = 0;
1179 curr_prio = ((naptr->order) << 16) + naptr->pref;
1180 } else {
1181 priority = ((naptr->order) << 16) + naptr->pref;
1182 if (priority > curr_prio) {
1183 q = q - 10;
1184 curr_prio = priority;
1185 }
1186 if (append_branch(_msg, &result, 0, 0, q, 0, 0) == -1) {
1187 goto done;
1188 }
1189 }
1190 }
1192 done:
1193 free_rdata_list(head);
1194 return first ? -1 : 1;
1195 }