1 /*
2  * Hash functions for cached trusted and address tables
3  *
4  * Copyright (C) 2003-2012 Juha Heinanen
5  *
6  * This file is part of Kamailio, a free SIP server.
7  *
8  * Kamailio is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version
12  *
13  * Kamailio is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21  */
22 
23 #include <sys/types.h>
24 #include <regex.h>
25 #include "parse_config.h"
26 #include "../../core/mem/shm_mem.h"
27 #include "../../core/parser/parse_from.h"
28 #include "../../core/ut.h"
29 #include "../../core/hashes.h"
30 #include "../../core/usr_avp.h"
31 #include "../../core/ip_addr.h"
32 #include "../../core/pvar.h"
33 #include "hash.h"
34 #include "trusted.h"
35 #include "address.h"
36 
37 #define perm_hash(_s)  core_hash( &(_s), 0, PERM_HASH_SIZE)
38 
39 
40 /* tag AVP specs */
41 static int     tag_avp_type;
42 static int_str tag_avp;
43 
44 extern int perm_peer_tag_mode;
45 
46 
47 extern int _perm_max_subnets;
48 
49 #define PERM_MAX_SUBNETS _perm_max_subnets
50 
51 /*
52  * Parse and set tag AVP specs
53  */
init_tag_avp(str * tag_avp_param)54 int init_tag_avp(str *tag_avp_param)
55 {
56 	pv_spec_t avp_spec;
57 	unsigned short avp_flags;
58 
59 	if (tag_avp_param->s && tag_avp_param->len > 0) {
60 		if (pv_parse_spec(tag_avp_param, &avp_spec)==0
61 				|| avp_spec.type != PVT_AVP) {
62 			LM_ERR("malformed or non "
63 					"AVP %.*s peer_tag_avp definition\n", tag_avp_param->len, tag_avp_param->s);
64 			return -1;
65 		}
66 		if(pv_get_avp_name(0, &avp_spec.pvp, &tag_avp, &avp_flags)!=0) {
67 			LM_ERR("[%.*s]- invalid "
68 					"peer_tag_avp AVP definition\n", tag_avp_param->len, tag_avp_param->s);
69 			return -1;
70 		}
71 		tag_avp_type = avp_flags;
72 	} else {
73 		tag_avp.n = 0;
74 	}
75 	return 0;
76 }
77 
78 
79 /*
80  * Gets tag avp specs
81  */
get_tag_avp(int_str * tag_avp_p,int * tag_avp_type_p)82 void get_tag_avp(int_str *tag_avp_p, int *tag_avp_type_p)
83 {
84 	*tag_avp_p = tag_avp;
85 	*tag_avp_type_p = tag_avp_type;
86 }
87 
88 
89 /*
90  * Create and initialize a hash table
91  */
new_hash_table(void)92 struct trusted_list** new_hash_table(void)
93 {
94 	struct trusted_list** ptr;
95 
96 	/* Initializing hash tables and hash table variable */
97 	ptr = (struct trusted_list **)shm_malloc
98 		(sizeof(struct trusted_list*) * PERM_HASH_SIZE);
99 	if (!ptr) {
100 		LM_ERR("no shm memory for hash table\n");
101 		return 0;
102 	}
103 
104 	memset(ptr, 0, sizeof(struct trusted_list*) * PERM_HASH_SIZE);
105 	return ptr;
106 }
107 
108 
109 /*
110  * Release all memory allocated for a hash table
111  */
free_hash_table(struct trusted_list ** table)112 void free_hash_table(struct trusted_list** table)
113 {
114 	if (!table)
115 		return;
116 
117 	empty_hash_table(table);
118 	shm_free(table);
119 }
120 
121 
122 /*
123  * Add <src_ip, proto, pattern, ruri_pattern, tag, priority> into hash table, where proto is integer
124  * representation of string argument proto.
125  */
hash_table_insert(struct trusted_list ** table,char * src_ip,char * proto,char * pattern,char * ruri_pattern,char * tag,int priority)126 int hash_table_insert(struct trusted_list** table, char* src_ip,
127 		char* proto, char* pattern, char* ruri_pattern, char* tag, int priority)
128 {
129 	struct trusted_list *np;
130 	struct trusted_list *np0 = NULL;
131 	struct trusted_list *np1 = NULL;
132 	unsigned int hash_val;
133 
134 	np = (struct trusted_list *) shm_malloc(sizeof(*np));
135 	if (np == NULL) {
136 		LM_ERR("cannot allocate shm memory for table entry\n");
137 		return -1;
138 	}
139 
140 	if (strcasecmp(proto, "any") == 0) {
141 		np->proto = PROTO_NONE;
142 	} else if (strcasecmp(proto, "udp") == 0) {
143 		np->proto = PROTO_UDP;
144 	} else if (strcasecmp(proto, "tcp") == 0) {
145 		np->proto = PROTO_TCP;
146 	} else if (strcasecmp(proto, "tls") == 0) {
147 		np->proto = PROTO_TLS;
148 	} else if (strcasecmp(proto, "sctp") == 0) {
149 		np->proto = PROTO_SCTP;
150 	} else if (strcasecmp(proto, "ws") == 0) {
151 		np->proto = PROTO_WS;
152 	} else if (strcasecmp(proto, "wss") == 0) {
153 		np->proto = PROTO_WSS;
154 	} else if (strcasecmp(proto, "none") == 0) {
155 		shm_free(np);
156 		return 1;
157 	} else {
158 		LM_CRIT("unknown protocol\n");
159 		shm_free(np);
160 		return -1;
161 	}
162 
163 	np->src_ip.len = strlen(src_ip);
164 	np->src_ip.s = (char *) shm_malloc(np->src_ip.len+1);
165 
166 	if (np->src_ip.s == NULL) {
167 		LM_CRIT("cannot allocate shm memory for src_ip string\n");
168 		shm_free(np);
169 		return -1;
170 	}
171 
172 	(void) strncpy(np->src_ip.s, src_ip, np->src_ip.len);
173 	np->src_ip.s[np->src_ip.len] = 0;
174 
175 	if (pattern) {
176 		np->pattern = (char *) shm_malloc(strlen(pattern)+1);
177 		if (np->pattern == NULL) {
178 			LM_CRIT("cannot allocate shm memory for pattern string\n");
179 			shm_free(np->src_ip.s);
180 			shm_free(np);
181 			return -1;
182 		}
183 		(void) strcpy(np->pattern, pattern);
184 	} else {
185 		np->pattern = 0;
186 	}
187 
188 	if (ruri_pattern) {
189 		np->ruri_pattern = (char *) shm_malloc(strlen(ruri_pattern)+1);
190 		if (np->ruri_pattern == NULL) {
191 			LM_CRIT("cannot allocate shm memory for ruri_pattern string\n");
192 			shm_free(np->src_ip.s);
193 			shm_free(np);
194 			return -1;
195 		}
196 		(void) strcpy(np->ruri_pattern, ruri_pattern);
197 	} else {
198 		np->ruri_pattern = 0;
199 	}
200 
201 	if (tag) {
202 		np->tag.len = strlen(tag);
203 		np->tag.s = (char *) shm_malloc((np->tag.len) + 1);
204 		if (np->tag.s == NULL) {
205 			LM_CRIT("cannot allocate shm memory for pattern or ruri_pattern string\n");
206 			shm_free(np->src_ip.s);
207 			shm_free(np->pattern);
208 			shm_free(np->ruri_pattern);
209 			shm_free(np);
210 			return -1;
211 		}
212 		(void) strcpy(np->tag.s, tag);
213 	} else {
214 		np->tag.len = 0;
215 		np->tag.s = 0;
216 	}
217 
218 	np->priority = priority;
219 
220 	hash_val = perm_hash(np->src_ip);
221 	if(table[hash_val]==NULL) {
222 		np->next = NULL;
223 		table[hash_val] = np;
224 	} else {
225 		np1 = NULL;
226 		np0 = table[hash_val];
227 		while(np0) {
228 			if(np0->priority < np->priority)
229 				break;
230 			np1 = np0;
231 			np0 = np0->next;
232 		}
233 		if(np1==NULL) {
234 			np->next = table[hash_val];
235 			table[hash_val] = np;
236 		} else {
237 			np->next = np1->next;
238 			np1->next = np;
239 		}
240 	}
241 
242 	return 1;
243 }
244 
245 
246 /*
247  * Check if an entry exists in hash table that has given src_ip and protocol
248  * value and pattern that matches to From URI.  If an entry exists and tag_avp
249  * has been defined, tag of the entry is added as a value to tag_avp.
250  * Returns number of matches or -1 if none matched.
251  */
match_hash_table(struct trusted_list ** table,struct sip_msg * msg,char * src_ip_c_str,int proto,char * from_uri)252 int match_hash_table(struct trusted_list** table, struct sip_msg* msg,
253 		char *src_ip_c_str, int proto, char *from_uri)
254 {
255 	LM_DBG("match_hash_table src_ip: %s, proto: %d, uri: %s\n", src_ip_c_str,
256 			proto, from_uri);
257 	str ruri;
258 	char ruri_string[MAX_URI_SIZE + 1];
259 	regex_t preg;
260 	struct trusted_list *np;
261 	str src_ip;
262 	int_str val;
263 	int count = 0;
264 
265 	src_ip.s = src_ip_c_str;
266 	src_ip.len = strlen(src_ip.s);
267 
268 	if (IS_SIP(msg))
269 	{
270 		ruri = msg->first_line.u.request.uri;
271 		if (ruri.len > MAX_URI_SIZE) {
272 			LM_ERR("message has Request URI too large\n");
273 			return -1;
274 		}
275 		memcpy(ruri_string, ruri.s, ruri.len);
276 		ruri_string[ruri.len] = (char)0;
277 	}
278 
279 	for (np = table[perm_hash(src_ip)]; np != NULL; np = np->next) {
280 		if ((np->src_ip.len == src_ip.len) &&
281 				(strncmp(np->src_ip.s, src_ip.s, src_ip.len) == 0) &&
282 				((np->proto == PROTO_NONE) || (proto == PROTO_NONE) ||
283 				(np->proto == proto))) {
284 
285 			LM_DBG("match_hash_table: %d, %s, %s, %s\n", np->proto,
286 					(np->pattern ? np->pattern : "null"),
287 					(np->ruri_pattern ? np->ruri_pattern : "null"),
288 					(np->tag.s ? np->tag.s : "null"));
289 
290 			if (IS_SIP(msg)) {
291 				if (np->pattern) {
292 					if (regcomp(&preg, np->pattern, REG_NOSUB)) {
293 						LM_ERR("invalid regular expression\n");
294 						if (!np->pattern) {
295 							continue;
296 						}
297 					}
298 					if (regexec(&preg, from_uri, 0, (regmatch_t *)0, 0)) {
299 						regfree(&preg);
300 						continue;
301 					}
302 					regfree(&preg);
303 				}
304 				if (np->ruri_pattern) {
305 					if (regcomp(&preg, np->ruri_pattern, REG_NOSUB)) {
306 						LM_ERR("invalid regular expression\n");
307 						continue;
308 					}
309 					if (regexec(&preg, ruri_string, 0, (regmatch_t *)0, 0)) {
310 						regfree(&preg);
311 						continue;
312 					}
313 					regfree(&preg);
314 				}
315 			}
316 			/* Found a match */
317 			if (tag_avp.n && np->tag.s) {
318 				val.s = np->tag;
319 				if (add_avp(tag_avp_type|AVP_VAL_STR, tag_avp, val) != 0) {
320 					LM_ERR("setting of tag_avp failed\n");
321 					return -1;
322 				}
323 			}
324 			if (!perm_peer_tag_mode)
325 				return 1;
326 			count++;
327 		}
328 	}
329 
330 	if (!count)
331 		return -1;
332 	else
333 		return count;
334 }
335 
336 
337 /*! \brief
338  * RPC interface :: Print trusted entries stored in hash table
339  */
hash_table_rpc_print(struct trusted_list ** hash_table,rpc_t * rpc,void * c)340 int hash_table_rpc_print(struct trusted_list** hash_table, rpc_t* rpc, void* c)
341 {
342 	int i;
343 	struct trusted_list *np;
344 	void* th;
345 	void* ih;
346 
347 	if (rpc->add(c, "{", &th) < 0)
348 	{
349 		rpc->fault(c, 500, "Internal error creating rpc");
350 		return -1;
351 	}
352 
353 	for (i = 0; i < PERM_HASH_SIZE; i++) {
354 		np = hash_table[i];
355 		while (np) {
356 			if(rpc->struct_add(th, "d{",
357 						"table", i,
358 						"item", &ih) < 0)
359 			{
360 				rpc->fault(c, 500, "Internal error creating rpc ih");
361 				return -1;
362 			}
363 
364 			if(rpc->struct_add(ih, "s", "ip", np->src_ip.s) < 0)
365 			{
366 				rpc->fault(c, 500, "Internal error creating rpc data (ip)");
367 				return -1;
368 			}
369 			if(rpc->struct_add(ih, "dsssd", "proto",  np->proto,
370 						"pattern",  np->pattern ? np->pattern : "NULL",
371 						"ruri_pattern",  np->ruri_pattern ? np->ruri_pattern : "NULL",
372 						"tag",  np->tag.len ? np->tag.s : "NULL",
373 						"priority", np->priority) < 0)
374 			{
375 				rpc->fault(c, 500, "Internal error creating rpc data");
376 				return -1;
377 			}
378 			np = np->next;
379 		}
380 	}
381 	return 0;
382 }
383 
384 /*
385  * Free contents of hash table, it doesn't destroy the
386  * hash table itself
387  */
empty_hash_table(struct trusted_list ** table)388 void empty_hash_table(struct trusted_list **table)
389 {
390 	int i;
391 	struct trusted_list *np, *next;
392 
393 	for (i = 0; i < PERM_HASH_SIZE; i++) {
394 		np = table[i];
395 		while (np) {
396 			if (np->src_ip.s) shm_free(np->src_ip.s);
397 			if (np->pattern) shm_free(np->pattern);
398 			if (np->ruri_pattern) shm_free(np->ruri_pattern);
399 			if (np->tag.s) shm_free(np->tag.s);
400 			next = np->next;
401 			shm_free(np);
402 			np = next;
403 		}
404 		table[i] = 0;
405 	}
406 }
407 
408 
409 /*
410  * Create and initialize an address hash table
411  */
new_addr_hash_table(void)412 struct addr_list** new_addr_hash_table(void)
413 {
414 	struct addr_list** ptr;
415 
416 	/* Initializing hash tables and hash table variable */
417 	ptr = (struct addr_list **)shm_malloc
418 		(sizeof(struct addr_list*) * PERM_HASH_SIZE);
419 	if (!ptr) {
420 		LM_ERR("no shm memory for hash table\n");
421 		return 0;
422 	}
423 
424 	memset(ptr, 0, sizeof(struct addr_list*) * PERM_HASH_SIZE);
425 	return ptr;
426 }
427 
428 
429 /*
430  * Release all memory allocated for a hash table
431  */
free_addr_hash_table(struct addr_list ** table)432 void free_addr_hash_table(struct addr_list** table)
433 {
434 	if (!table)
435 		return;
436 
437 	empty_addr_hash_table(table);
438 	shm_free(table);
439 }
440 
441 
442 /*
443  * Add <grp, ip_addr, port> into hash table
444  */
addr_hash_table_insert(struct addr_list ** table,unsigned int grp,ip_addr_t * addr,unsigned int port,str * tagv)445 int addr_hash_table_insert(struct addr_list** table, unsigned int grp,
446 		ip_addr_t *addr, unsigned int port, str *tagv)
447 {
448 	struct addr_list *np;
449 	unsigned int hash_val;
450 	str addr_str;
451 	int len;
452 
453 	len = sizeof(struct addr_list);
454 	if(tagv!=NULL && tagv->s!=NULL) {
455 		len += tagv->len + 1;
456 	}
457 
458 	np = (struct addr_list *) shm_malloc(len);
459 	if (np == NULL) {
460 		LM_ERR("no shm memory for table entry\n");
461 		return -1;
462 	}
463 
464 	memset(np, 0, len);
465 
466 	np->grp = grp;
467 	memcpy(&np->addr, addr, sizeof(ip_addr_t));
468 	np->port = port;
469 	if(tagv!=NULL && tagv->s!=NULL)
470 	{
471 		np->tag.s = (char*)np + sizeof(struct addr_list);
472 		np->tag.len = tagv->len;
473 		memcpy(np->tag.s, tagv->s, tagv->len);
474 		np->tag.s[np->tag.len] = '\0';
475 	}
476 
477 	addr_str.s = (char*)addr->u.addr;
478 	addr_str.len = 4;
479 	hash_val = perm_hash(addr_str);
480 	np->next = table[hash_val];
481 	table[hash_val] = np;
482 
483 	return 1;
484 }
485 
486 
487 /*
488  * Check if an entry exists in hash table that has given group, ip_addr, and
489  * port.  Port 0 in hash table matches any port.
490  */
match_addr_hash_table(struct addr_list ** table,unsigned int group,ip_addr_t * addr,unsigned int port)491 int match_addr_hash_table(struct addr_list** table, unsigned int group,
492 		ip_addr_t *addr, unsigned int port)
493 {
494 	struct addr_list *np;
495 	str addr_str;
496 	avp_value_t val;
497 
498 	addr_str.s = (char*)addr->u.addr;
499 	addr_str.len = 4;
500 
501 	for (np = table[perm_hash(addr_str)]; np != NULL; np = np->next) {
502 		if ( (np->grp == group)
503 				&& ((np->port == 0) || (np->port == port))
504 				&& ip_addr_cmp(&np->addr, addr)) {
505 
506 			if (tag_avp.n && np->tag.s) {
507 				val.s = np->tag;
508 				if (add_avp(tag_avp_type|AVP_VAL_STR, tag_avp, val) != 0) {
509 					LM_ERR("setting of tag_avp failed\n");
510 					return -1;
511 				}
512 			}
513 
514 			return 1;
515 		}
516 	}
517 
518 	return -1;
519 }
520 
521 
522 /*
523  * Check if an ip_addr/port entry exists in hash table in any group.
524  * Returns first group in which ip_addr/port is found.
525  * Port 0 in hash table matches any port.
526  */
find_group_in_addr_hash_table(struct addr_list ** table,ip_addr_t * addr,unsigned int port)527 int find_group_in_addr_hash_table(struct addr_list** table,
528 		ip_addr_t *addr, unsigned int port)
529 {
530 	struct addr_list *np;
531 	str addr_str;
532 	avp_value_t val;
533 
534 	addr_str.s = (char*)addr->u.addr;
535 	addr_str.len = 4;
536 
537 	for (np = table[perm_hash(addr_str)]; np != NULL; np = np->next) {
538 		if (((np->port == 0) || (np->port == port))
539 				&& ip_addr_cmp(&np->addr, addr)) {
540 
541 			if (tag_avp.n && np->tag.s) {
542 				val.s = np->tag;
543 				if (add_avp(tag_avp_type|AVP_VAL_STR, tag_avp, val) != 0) {
544 					LM_ERR("setting of tag_avp failed\n");
545 					return -1;
546 				}
547 			}
548 
549 			return np->grp;
550 		}
551 	}
552 
553 	return -1;
554 }
555 
556 
557 /*! \brief
558  * RPC: Print addresses stored in hash table
559  */
addr_hash_table_rpc_print(struct addr_list ** table,rpc_t * rpc,void * c)560 int addr_hash_table_rpc_print(struct addr_list** table, rpc_t* rpc, void* c)
561 {
562 	int i;
563 	void* th;
564 	void* ih;
565 	struct addr_list *np;
566 
567 
568 	for (i = 0; i < PERM_HASH_SIZE; i++) {
569 		np = table[i];
570 		while (np) {
571 			if (rpc->add(c, "{", &th) < 0)
572 			{
573 				rpc->fault(c, 500, "Internal error creating rpc");
574 				return -1;
575 			}
576 
577 			if(rpc->struct_add(th, "dd{",
578 						"table", i,
579 						"group", np->grp,
580 						"item", &ih) < 0)
581 			{
582 				rpc->fault(c, 500, "Internal error creating rpc ih");
583 				return -1;
584 			}
585 
586 			if(rpc->struct_add(ih, "s", "ip", ip_addr2a(&np->addr)) < 0)
587 			{
588 				rpc->fault(c, 500, "Internal error creating rpc data (ip)");
589 				return -1;
590 			}
591 			if(rpc->struct_add(ih, "ds", "port",  np->port,
592 						"tag",  np->tag.len ? np->tag.s : "NULL") < 0)
593 			{
594 				rpc->fault(c, 500, "Internal error creating rpc data");
595 				return -1;
596 			}
597 			np = np->next;
598 		}
599 	}
600 	return 0;
601 }
602 
603 
604 /*
605  * Free contents of hash table, it doesn't destroy the
606  * hash table itself
607  */
empty_addr_hash_table(struct addr_list ** table)608 void empty_addr_hash_table(struct addr_list **table)
609 {
610 	int i;
611 	struct addr_list *np, *next;
612 
613 	for (i = 0; i < PERM_HASH_SIZE; i++) {
614 		np = table[i];
615 		while (np) {
616 			next = np->next;
617 			shm_free(np);
618 			np = next;
619 		}
620 		table[i] = 0;
621 	}
622 }
623 
624 
625 /*
626  * Create and initialize a subnet table
627  */
new_subnet_table(void)628 struct subnet* new_subnet_table(void)
629 {
630 	struct subnet* ptr;
631 
632 	/* subnet record [PERM_MAX_SUBNETS] contains in its grp field
633 	 * the number of subnet records in the subnet table */
634 	ptr = (struct subnet *)shm_malloc
635 		(sizeof(struct subnet) * (PERM_MAX_SUBNETS + 1));
636 	if (!ptr) {
637 		LM_ERR("no shm memory for subnet table\n");
638 		return 0;
639 	}
640 	memset(ptr, 0, sizeof(struct subnet) * (PERM_MAX_SUBNETS + 1));
641 	return ptr;
642 }
643 
644 
645 /*
646  * Add <grp, subnet, mask, port, tag> into subnet table so that table is
647  * kept in increasing ordered according to grp.
648  */
subnet_table_insert(struct subnet * table,unsigned int grp,ip_addr_t * subnet,unsigned int mask,unsigned int port,str * tagv)649 int subnet_table_insert(struct subnet* table, unsigned int grp,
650 		ip_addr_t *subnet, unsigned int mask,
651 		unsigned int port, str *tagv)
652 {
653 	int i;
654 	unsigned int count;
655 	str tags;
656 
657 	count = table[PERM_MAX_SUBNETS].grp;
658 
659 	if (count == PERM_MAX_SUBNETS) {
660 		LM_CRIT("subnet table is full\n");
661 		return 0;
662 	}
663 
664 	if(tagv==NULL || tagv->s==NULL)
665 	{
666 		tags.s = NULL;
667 		tags.len = 0;
668 	} else {
669 		tags.len = tagv->len;
670 		tags.s = (char*)shm_malloc(tags.len+1);
671 		if(tags.s==NULL)
672 		{
673 			LM_ERR("No more shared memory\n");
674 			return 0;
675 		}
676 		memcpy(tags.s, tagv->s, tags.len);
677 		tags.s[tags.len] = '\0';
678 	}
679 
680 	i = count - 1;
681 
682 	while ((i >= 0) && (table[i].grp > grp)) {
683 		table[i + 1] = table[i];
684 		i--;
685 	}
686 
687 	table[i + 1].grp = grp;
688 	memcpy(&table[i + 1].subnet, subnet, sizeof(ip_addr_t));
689 	table[i + 1].port = port;
690 	table[i + 1].mask = mask;
691 	table[i + 1].tag = tags;
692 
693 	table[PERM_MAX_SUBNETS].grp = count + 1;
694 
695 	return 1;
696 }
697 
698 
699 /*
700  * Check if an entry exists in subnet table that matches given group, ip_addr,
701  * and port.  Port 0 in subnet table matches any port.
702  */
match_subnet_table(struct subnet * table,unsigned int grp,ip_addr_t * addr,unsigned int port)703 int match_subnet_table(struct subnet* table, unsigned int grp,
704 		ip_addr_t *addr, unsigned int port)
705 {
706 	unsigned int count, i;
707 	avp_value_t val;
708 
709 	count = table[PERM_MAX_SUBNETS].grp;
710 
711 	i = 0;
712 	while ((i < count) && (table[i].grp < grp))
713 		i++;
714 
715 	if (i == count) return -1;
716 
717 	while ((i < count) && (table[i].grp == grp)) {
718 		if (((table[i].port == port) || (table[i].port == 0))
719 				&& (ip_addr_match_net(addr, &table[i].subnet, table[i].mask)==0))
720 		{
721 			if (tag_avp.n && table[i].tag.s) {
722 				val.s = table[i].tag;
723 				if (add_avp(tag_avp_type|AVP_VAL_STR, tag_avp, val) != 0) {
724 					LM_ERR("setting of tag_avp failed\n");
725 					return -1;
726 				}
727 			}
728 			return 1;
729 		}
730 		i++;
731 	}
732 
733 	return -1;
734 }
735 
736 
737 /*
738  * Check if an entry exists in subnet table that matches given ip_addr,
739  * and port.  Port 0 in subnet table matches any port.  Return group of
740  * first match or -1 if no match is found.
741  */
find_group_in_subnet_table(struct subnet * table,ip_addr_t * addr,unsigned int port)742 int find_group_in_subnet_table(struct subnet* table,
743 		ip_addr_t *addr, unsigned int port)
744 {
745 	unsigned int count, i;
746 	avp_value_t val;
747 
748 	count = table[PERM_MAX_SUBNETS].grp;
749 
750 	i = 0;
751 	while (i < count) {
752 		if ( ((table[i].port == port) || (table[i].port == 0))
753 				&& (ip_addr_match_net(addr, &table[i].subnet, table[i].mask)==0))
754 		{
755 			if (tag_avp.n && table[i].tag.s) {
756 				val.s = table[i].tag;
757 				if (add_avp(tag_avp_type|AVP_VAL_STR, tag_avp, val) != 0) {
758 					LM_ERR("setting of tag_avp failed\n");
759 					return -1;
760 				}
761 			}
762 			return table[i].grp;
763 		}
764 		i++;
765 	}
766 
767 	return -1;
768 }
769 
770 
771 /*! \brief
772  * RPC interface :: Print subnet entries stored in hash table
773  */
subnet_table_rpc_print(struct subnet * table,rpc_t * rpc,void * c)774 int subnet_table_rpc_print(struct subnet* table, rpc_t* rpc, void* c)
775 {
776 	int i;
777 	int count;
778 	void* th;
779 	void* ih;
780 
781 	count = table[PERM_MAX_SUBNETS].grp;
782 
783 	for (i = 0; i < count; i++) {
784 		if (rpc->add(c, "{", &th) < 0)
785 		{
786 			rpc->fault(c, 500, "Internal error creating rpc");
787 			return -1;
788 		}
789 
790 		if(rpc->struct_add(th, "dd{",
791 					"id", i,
792 					"group", table[i].grp,
793 					"item", &ih) < 0)
794 		{
795 			rpc->fault(c, 500, "Internal error creating rpc ih");
796 			return -1;
797 		}
798 
799 		if(rpc->struct_add(ih, "s", "ip", ip_addr2a(&table[i].subnet)) < 0)
800 		{
801 			rpc->fault(c, 500, "Internal error creating rpc data (subnet)");
802 			return -1;
803 		}
804 		if(rpc->struct_add(ih, "dds", "mask", table[i].mask,
805 					"port", table[i].port,
806 					"tag",  (table[i].tag.s==NULL)?"":table[i].tag.s) < 0)
807 		{
808 			rpc->fault(c, 500, "Internal error creating rpc data");
809 			return -1;
810 		}
811 	}
812 	return 0;
813 }
814 
815 
816 /*
817  * Empty contents of subnet table
818  */
empty_subnet_table(struct subnet * table)819 void empty_subnet_table(struct subnet *table)
820 {
821 	int i;
822 	table[PERM_MAX_SUBNETS].grp = 0;
823 	for(i=0; i<PERM_MAX_SUBNETS; i++)
824 	{
825 		if(table[i].tag.s!=NULL)
826 		{
827 			shm_free(table[i].tag.s);
828 			table[i].tag.s = NULL;
829 			table[i].tag.len =0;
830 		}
831 	}
832 }
833 
834 
835 /*
836  * Release memory allocated for a subnet table
837  */
free_subnet_table(struct subnet * table)838 void free_subnet_table(struct subnet* table)
839 {
840 	int i;
841 	if (!table)
842 		return;
843 	for(i=0; i<PERM_MAX_SUBNETS; i++)
844 	{
845 		if(table[i].tag.s!=NULL)
846 		{
847 			shm_free(table[i].tag.s);
848 			table[i].tag.s = NULL;
849 			table[i].tag.len =0;
850 		}
851 	}
852 
853 	shm_free(table);
854 }
855 
856 /*
857  * Create and initialize a domain_name table
858  */
new_domain_name_table(void)859 struct domain_name_list** new_domain_name_table(void)
860 {
861 	struct domain_name_list** ptr;
862 
863 	/* Initializing hash tables and hash table variable */
864 	ptr = (struct domain_name_list **)shm_malloc
865 		(sizeof(struct domain_name_list*) * PERM_HASH_SIZE);
866 	if (!ptr) {
867 		LM_ERR("no shm memory for hash table\n");
868 		return 0;
869 	}
870 
871 	memset(ptr, 0, sizeof(struct domain_name*) * PERM_HASH_SIZE);
872 	return ptr;
873 }
874 
875 
876 /*
877  * Free contents of hash table, it doesn't destroy the
878  * hash table itself
879  */
empty_domain_name_table(struct domain_name_list ** table)880 void empty_domain_name_table(struct domain_name_list **table)
881 {
882 	int i;
883 	struct domain_name_list *np, *next;
884 
885 	for (i = 0; i < PERM_HASH_SIZE; i++) {
886 		np = table[i];
887 		while (np) {
888 			next = np->next;
889 			shm_free(np);
890 			np = next;
891 		}
892 		table[i] = 0;
893 	}
894 }
895 
896 /*
897  * Release all memory allocated for a hash table
898  */
free_domain_name_table(struct domain_name_list ** table)899 void free_domain_name_table(struct domain_name_list** table)
900 {
901 	if (!table)
902 		return;
903 
904 	empty_domain_name_table(table);
905 	shm_free(table);
906 }
907 
908 
909 /*
910  * Check if an entry exists in hash table that has given group, domain_name, and
911  * port.  Port 0 in hash table matches any port.
912  */
match_domain_name_table(struct domain_name_list ** table,unsigned int group,str * domain_name,unsigned int port)913 int match_domain_name_table(struct domain_name_list** table, unsigned int group,
914 		str *domain_name, unsigned int port)
915 {
916 	struct domain_name_list *np;
917 	avp_value_t val;
918 
919 	for (np = table[perm_hash(*domain_name)]; np != NULL; np = np->next) {
920 		if ( (np->grp == group)
921 				&& ((np->port == 0) || (np->port == port))
922 				&& np->domain.len == domain_name->len
923 				&& strncmp(np->domain.s, domain_name->s, domain_name->len)==0 ) {
924 
925 			if (tag_avp.n && np->tag.s) {
926 				val.s = np->tag;
927 				if (add_avp(tag_avp_type|AVP_VAL_STR, tag_avp, val) != 0) {
928 					LM_ERR("setting of tag_avp failed\n");
929 					return -1;
930 				}
931 			}
932 
933 			return 1;
934 		}
935 	}
936 
937 	return -1;
938 }
939 
940 
941 /*
942  * Check if an domain_name/port entry exists in hash table in any group.
943  * Returns first group in which ip_addr/port is found.
944  * Port 0 in hash table matches any port.
945  */
find_group_in_domain_name_table(struct domain_name_list ** table,str * domain_name,unsigned int port)946 int find_group_in_domain_name_table(struct domain_name_list** table,
947 		str *domain_name, unsigned int port)
948 {
949 	struct domain_name_list *np;
950 
951 	for (np = table[perm_hash(*domain_name)]; np != NULL; np = np->next) {
952 		if ( ((np->port == 0) || (np->port == port))
953 				&& np->domain.len == domain_name->len
954 				&& strncmp(np->domain.s, domain_name->s, domain_name->len)==0 ) {
955 			return np->grp;
956 		}
957 	}
958 
959 	return -1;
960 }
961 
962 
963 /*
964  * Add <grp, domain_name, port> into hash table
965  */
domain_name_table_insert(struct domain_name_list ** table,unsigned int grp,str * domain_name,unsigned int port,str * tagv)966 int domain_name_table_insert(struct domain_name_list** table, unsigned int grp,
967 		str *domain_name, unsigned int port, str *tagv)
968 {
969 	struct domain_name_list *np;
970 	unsigned int hash_val;
971 	int len;
972 
973 	len = sizeof(struct domain_name_list) + domain_name->len;
974 	if(tagv!=NULL && tagv->s!=NULL) {
975 		len += tagv->len + 1;
976 	}
977 
978 	np = (struct domain_name_list *) shm_malloc(len);
979 	if (np == NULL) {
980 		LM_ERR("no shm memory for table entry\n");
981 		return -1;
982 	}
983 
984 	memset(np, 0, len);
985 
986 	np->grp = grp;
987 	np->domain.s = (char*)np + sizeof(struct domain_name_list);
988 	memcpy(np->domain.s, domain_name->s, domain_name->len);
989 	np->domain.len = domain_name->len;
990 	np->port = port;
991 	if(tagv!=NULL && tagv->s!=NULL) {
992 		np->tag.s = (char*)np + sizeof(struct domain_name_list) + domain_name->len;
993 		np->tag.len = tagv->len;
994 		memcpy(np->tag.s, tagv->s, np->tag.len);
995 		np->tag.s[np->tag.len] = '\0';
996 	}
997 
998 	LM_DBG("** Added domain name: %.*s\n", np->domain.len, np->domain.s);
999 
1000 	hash_val = perm_hash(*domain_name);
1001 	np->next = table[hash_val];
1002 	table[hash_val] = np;
1003 
1004 	return 1;
1005 }
1006 
1007 
1008 /*! \brief
1009  * RPC: Print addresses stored in hash table
1010  */
domain_name_table_rpc_print(struct domain_name_list ** table,rpc_t * rpc,void * c)1011 int domain_name_table_rpc_print(struct domain_name_list** table, rpc_t* rpc, void* c)
1012 {
1013 	int i;
1014 	void* th;
1015 	void* ih;
1016 	struct domain_name_list *np;
1017 
1018 
1019 	if (rpc->add(c, "{", &th) < 0)
1020 	{
1021 		rpc->fault(c, 500, "Internal error creating rpc");
1022 		return -1;
1023 	}
1024 
1025 	for (i = 0; i < PERM_HASH_SIZE; i++) {
1026 		np = table[i];
1027 		while (np) {
1028 			if(rpc->struct_add(th, "dd{",
1029 						"table", i,
1030 						"group", np->grp,
1031 						"item", &ih) < 0) {
1032 				rpc->fault(c, 500, "Internal error creating rpc ih");
1033 				return -1;
1034 			}
1035 
1036 			if(rpc->struct_add(ih, "S", "domain_name", &np->domain) < 0) {
1037 				rpc->fault(c, 500, "Internal error creating rpc data (ip)");
1038 				return -1;
1039 			}
1040 			if(rpc->struct_add(ih, "ds", "port",  np->port,
1041 						"tag",  np->tag.len ? np->tag.s : "NULL") < 0) {
1042 				rpc->fault(c, 500, "Internal error creating rpc data");
1043 				return -1;
1044 			}
1045 			np = np->next;
1046 		}
1047 	}
1048 	return 0;
1049 }
1050