opensips/modules/enum/enum.c

Wed, 10 Feb 2010 21:25:01 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 10 Feb 2010 21:25:01 +0100
changeset 18
8ec65b8f6e2c
parent 12
a3ac912f2857
permissions
-rw-r--r--

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, &param, &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)
  1006     return enum_pv_query_3(_msg, _sp, (char *)(&suffix), (char *)(&service));
  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)
  1014     return enum_pv_query_3(_msg, _sp, _suffix, (char *)(&service));
  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)
  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;
  1053 	if (is_e164(&(_msg->parsed_uri.user)) == -1) {
  1054 		LM_ERR("R-URI user is not an E164 number\n");
  1055 		return -1;
  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;
  1073 	    } else {
  1074 		LM_DBG("Pseudo variable value is not string\n");
  1075 		return -1;
  1077 	} else {
  1078 	    LM_DBG("Cannot get pseudo variable value\n");
  1079 	    return -1;
  1081 	if (is_e164(&(pv_val.rs)) == -1) {
  1082 	    LM_ERR("pseudo variable does not contain an E164 number\n");
  1083 	    return -1;
  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;
  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;
  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;
  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;
  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;
  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;
  1161 			new_result.s = &(new_uri[0]);
  1162 			new_result.len = MAX_URI_SIZE;
  1163 			if (add_uri_param(&result, &param, &new_result) == 0) {
  1164 				LM_ERR("Parsing of URI <%.*s> failed\n",
  1165 				       result.len, result.s);
  1166 				continue;
  1168 			if (new_result.len > 0) {
  1169 				result = new_result;
  1173 		if (first) {
  1174 			if (set_ruri(_msg, &result) == -1) {
  1175 				goto done;
  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;
  1186 			if (append_branch(_msg, &result, 0, 0, q, 0, 0) == -1) {
  1187 				goto done;
  1192 done:
  1193 	free_rdata_list(head);
  1194 	return first ? -1 : 1;

mercurial