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