obsolete/permissions/trusted_hash.c
23e49a23
 /*
836acfcc
  * $Id$
  *
23e49a23
  * Hash functions for cached trusted table
  *
  * Copyright (C) 2003 Juha Heinanen
  *
  * This file is part of ser, a free SIP server.
  *
  * ser is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
  * For a license to use the ser software under conditions
  * other than those described here, or to purchase support for this
  * software, please contact iptel.org by e-mail at the following addresses:
  *    info@iptel.org
  *
  * ser is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License 
  * along with this program; if not, write to the Free Software 
9e1ff448
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
23e49a23
  */
 
d52cc25a
 #include <sys/types.h>
23e49a23
 #include <regex.h>
 #include "../../mem/shm_mem.h"
 #include "../../parser/parse_from.h"
 #include "../../ut.h"
836acfcc
 #include "trusted_hash.h"
23e49a23
 
 
 /*
  * Create and initialize a hash table
  */
 struct trusted_list** new_hash_table(void)
 {
 	struct trusted_list** ptr;
 
 	     /* Initializing hash tables and hash table variable */
 	ptr = (struct trusted_list **)shm_malloc(sizeof(struct trusted_list*) * HASH_SIZE);
 	if (!ptr) {
 		LOG(L_ERR, "new_hash_table(): No memory for hash table\n");
 		return 0;
 	}
 
 	memset(ptr, 0, sizeof(struct trusted_list*) * HASH_SIZE);
 	return ptr;
 }
 
 
 /*
  * Release all memory allocated for a hash table
  */
 void free_hash_table(struct trusted_list** table)
 {
 	if (table) {
 	        empty_hash_table(table);
 	}
 
 	shm_free(table);
 }
 
 
 /* 
  * String hash function 
  */
 static unsigned int hash(str* src_ip)
 {
 	char *p;
 	unsigned int h = 0;
 	unsigned int len;
 	unsigned int i;
 	
 	p = src_ip->s;
 	len = src_ip->len;
 	
 	for (i = 0; i < len; i++) {
 		h = ( h << 5 ) - h + *(p + i);
 	}
 
 	return h % HASH_SIZE;
 }
 
 
 /* 
95072403
  * Add <src_ip, proto, pattern> into hash table, where proto is integer
  * representation of string argument proto.
23e49a23
  */
4eb0131b
 int hash_table_insert(struct trusted_list** hash_table, char* src_ip, char* proto, char* pattern)
23e49a23
 {
 	struct trusted_list *np;
 	unsigned int hash_val;
 
 	np = (struct trusted_list *) shm_malloc(sizeof(*np));
 	if (np == NULL) {
4eb0131b
 		LOG(L_CRIT, "hash_table_insert(): Cannot allocate memory for table entry\n");
23e49a23
 		return -1;
 	}
 
 	np->src_ip.len = strlen(src_ip);
 	np->src_ip.s = (char *) shm_malloc(np->src_ip.len);
 
 	if (np->src_ip.s == NULL) {
4eb0131b
 		LOG(L_CRIT, "hash_table_insert(): Cannot allocate memory for src_ip string\n");
23e49a23
 		return -1;
 	}
 
 	(void) strncpy(np->src_ip.s, src_ip, np->src_ip.len);
 
 	if (strcmp(proto, "any") == 0) {
 		np->proto = PROTO_NONE;
 	} else if (strcmp(proto, "udp") == 0) {
 		np->proto = PROTO_UDP;
 	} else if (strcmp(proto, "tcp") == 0) {
 		np->proto = PROTO_TCP;
 	} else if (strcmp(proto, "tls") == 0) {
 		np->proto = PROTO_TLS;
 	} else if (strcmp(proto, "sctp") == 0) {
 		np->proto = PROTO_SCTP;
 	} else {
be30ac88
 		LOG(L_CRIT, "hash_table_insert(): Unknown protocol '%s'\n", proto);
23e49a23
 		return -1;
 	}
 		
8dc63b44
 	np->pattern = (char *) shm_malloc(strlen(pattern)+1);
23e49a23
 	if (np->pattern == NULL) {
4eb0131b
 		LOG(L_CRIT, "hash_table_insert(): Cannot allocate memory for pattern string\n");
23e49a23
 		return -1;
 	}
 	(void) strcpy(np->pattern, pattern);
 
 	hash_val = hash(&(np->src_ip));
 	np->next = hash_table[hash_val];
 	hash_table[hash_val] = np;
 
 	return 1;
 }
 
 
 /* 
  * Check if an entry exists in hash table that has given src_ip and protocol
  * value and pattern that matches to From URI.
  */
 int match_hash_table(struct trusted_list** table, struct sip_msg* msg)
 {
 	str uri;
 	char uri_string[MAX_URI_SIZE + 1];
 	regex_t preg;
 	struct trusted_list *np;
 	str src_ip;
 
 	src_ip.s = ip_addr2a(&msg->rcv.src_ip);
 	src_ip.len = strlen(src_ip.s);
 
 	if (parse_from_header(msg) < 0) return -1;
 	uri = get_from(msg)->uri;
 	if (uri.len > MAX_URI_SIZE) {
 		LOG(L_ERR, "match_hash_table(): From URI too large\n");
 		return -1;
 	}
 	memcpy(uri_string, uri.s, uri.len);
 	uri_string[uri.len] = (char)0;
 
 	for (np = table[hash(&src_ip)]; np != NULL; np = np->next) {
 		if ((np->src_ip.len == src_ip.len) && 
 		    (strncasecmp(np->src_ip.s, src_ip.s, src_ip.len) == 0) &&
 		    ((np->proto == PROTO_NONE) || (np->proto == msg->rcv.proto))) {
 			if (regcomp(&preg, np->pattern, REG_NOSUB)) {
 				LOG(L_ERR, "match_hash_table(): Error in regular expression\n");
 				return -1;
 			}
 			if (regexec(&preg, uri_string, 0, (regmatch_t *)0, 0)) {
 				regfree(&preg);
 			} else {
 				regfree(&preg);
 				return 1;
 			}
 		}
 	}
 	return -1;
 }
 
 
 /* 
  * Print domains stored in hash table 
  */
01e8d3ab
 void hash_table_print(struct trusted_list** hash_table, rpc_t* rpc, void* c)
23e49a23
 {
01e8d3ab
 	void* st;
23e49a23
 	int i;
 	struct trusted_list *np;
 
 	for (i = 0; i < HASH_SIZE; i++) {
 		np = hash_table[i];
 		while (np) {
01e8d3ab
 			if (rpc->add(c, "{", &st) < 0) return;
 			rpc->struct_add(st, "Sds", "src_ip", &np->src_ip, "proto", np->proto, "pattern", np->pattern);
23e49a23
 			np = np->next;
 		}
 	}
 }
 
 /* 
  * Free contents of hash table, it doesn't destroy the
  * hash table itself
  */
 void empty_hash_table(struct trusted_list **hash_table)
 {
 	int i;
 	struct trusted_list *np, *next;
 
 	for (i = 0; i < HASH_SIZE; i++) {
 		np = hash_table[i];
 		while (np) {
 			shm_free(np->src_ip.s);
 			shm_free(np->pattern);
 			next = np->next;
 			shm_free(np);
 			np = next;
 		}
 		hash_table[i] = 0;
 	}
 }