Esempio n. 1
0
void rpc_ip_set_commit(rpc_t* rpc, void* ctx) {
	str name;
	struct ip_set_list_item *p;
	struct ip_set_ref *new_ip_set;
	if (rpc->scan(ctx, "S", &name) < 1) {
		return;
	}
	p = ip_set_list_find_by_name(name);
	if (!p) {
		rpc->fault(ctx, 400, "Ip set not found");
		return;
	}
	lock_get(&p->write_lock);
	lock_get(&p->read_lock);
	new_ip_set = shm_malloc(sizeof(*new_ip_set));
	if (!new_ip_set) {
		rpc->fault(ctx, 500, "Not enough memory");
		goto err;
	}
	
	if (p->ip_set) {
		if (atomic_dec_and_test(&p->ip_set->refcnt)) {
			ip_set_destroy(&p->ip_set->ip_set);  /* not used in local copy */
			shm_free(p->ip_set);
		}
	}
	new_ip_set->ip_set = p->ip_set_pending;
	atomic_set(&new_ip_set->refcnt, 1);
	p->ip_set = new_ip_set;
	
	ip_set_init(&p->ip_set_pending, 1);
err:	
	lock_release(&p->read_lock);
	lock_release(&p->write_lock);
}
Esempio n. 2
0
void rpc_ip_set_print(rpc_t* rpc, void* ctx) {
	struct ip_set_list_item *p;
	struct ip_set *ip_set, ip_set2;
	void *c;
	str name;
	int pending;
	if (rpc->scan(ctx, "Sd", &name, &pending) < 1) {
		return;
	}
	p = ip_set_list_find_by_name(name);
	if (!p) {
		rpc->fault(ctx, 400, "Ip set not found");
		return;
	}
	if (pending) {
		lock_get(&p->write_lock);
		ip_set = &p->ip_set_pending;
	} else {
		lock_get(&p->read_lock);
		if (!p->ip_set) {
			ip_set_init(&ip_set2, 1); /* dummy to return empty ip set */
			ip_set = &ip_set2;
		}
		else
			ip_set = &p->ip_set->ip_set;
	}

	/* nested array/struct not supported */
	rpc->add(ctx, "{", &c);
	if (rpc->struct_add(c, "s", "IPv", "4") < 0) 
		goto err;	
	if (rpc_ip_tree_print(rpc, c, "", ip_set->ipv4_tree, 0) < 0) 
		goto err;
	rpc->add(ctx, "{", &c);
	if (rpc->struct_add(c, "s", "IPv", "6") < 0) 
		goto err;	
#ifdef USE_IPV6
	if (rpc_ip_tree_print(rpc, c, "", ip_set->ipv6_tree, 0) < 0) 
		goto err;
#endif

err:		
	if (pending)
		lock_release(&p->write_lock);
	else
		lock_release(&p->read_lock);

}
Esempio n. 3
0
void rpc_ip_set_clean(rpc_t* rpc, void* ctx) {
	str name;
	struct ip_set_list_item *p;
	if (rpc->scan(ctx, "S", &name) < 1) {
		return;
	}
	p = ip_set_list_find_by_name(name);
	if (!p) {
		rpc->fault(ctx, 400, "Ip set not found");
		return;
	}
	lock_get(&p->write_lock);
	ip_set_destroy(&p->ip_set_pending);
	ip_set_init(&p->ip_set_pending, 1);
	lock_release(&p->write_lock);
}
Esempio n. 4
0
void rpc_ip_set_add(rpc_t* rpc, void* ctx) {
	str name, ip, mask;
	struct ip_set_list_item* p;
	if (rpc->scan(ctx, "SSS", &name, &ip, &mask) < 1) {
		return;
	}
	while (mask.len && mask.s[0]=='/') {  /* rpc cannot read plain number as string, adding '/' helps */
		mask.s++;
		mask.len--;
	}
	p = ip_set_list_find_by_name(name);
	if (!p) {
		rpc->fault(ctx, 400, "Ip set not found");
		return;
	}
	lock_get(&p->write_lock);
	if (ip_set_add_ip_s(&p->ip_set_pending, ip, mask) < 0) {
		lock_release(&p->write_lock);
		rpc->fault(ctx, 400, "Cannot add ip/mask into ip set");
		return;
	}
	lock_release(&p->write_lock);
}
Esempio n. 5
0
static int fixup_ip_is_trusted(void** param, int param_no) {
	int ret = E_CFG;
	struct ip_set_param *p;
	str s;
	if (param_no == 1) {
		
		p = pkg_malloc(sizeof(*p));
		if (!p) return E_OUT_OF_MEM;
		memset(p, 0, sizeof(*p));
		s.s = *param;
		s.len = strlen(s.s);

		if (is_ip_set_name(&s)) {
			p->u.global.ip_set = ip_set_list_find_by_name(s);
			if (!p->u.global.ip_set) {
				ERR(MODULE_NAME": fixup_ip_is_trusted: ip set '%.*s' is not declared\n", s.len, s.s);			
				goto err;
			}
			p->kind = IP_SET_PARAM_KIND_GLOBAL;
		} else {
			ret = fixup_var_str_12(param, param_no);
			if (ret < 0) goto err;
			ip_set_init(&p->u.local.ip_set, 0);
			p->u.local.fparam = *param;
			*param = p;
			p->kind = IP_SET_PARAM_KIND_LOCAL;
		}
	}
	else {
		return fixup_var_str_12(param, param_no);
	
	}
	return E_OK;
err:
	pkg_free(p);
	return ret;
}
Esempio n. 6
0
static int w_ip_is_trusted(struct sip_msg* msg, char* _ip_set, char* _ip) {
	str ip_set_s, ip_s;
	struct ip_addr *ip, ip_buf;
	struct ip_set new_ip_set, *ip_set;
	struct ip_set_list_item *isli = NULL;
	int kind;
	kind = ((struct ip_set_param*)_ip_set)->kind;
	if (kind == IP_SET_PARAM_KIND_LOCAL) {
		if (get_str_fparam(&ip_set_s, msg, ((struct ip_set_param*)_ip_set)->u.local.fparam) < 0) {
		    ERR(MODULE_NAME": ip_is_trusted: Error while obtaining ip_set parameter value\n");
			return -1;
		}
		if (is_ip_set_name(&ip_set_s)) {
			isli = ip_set_list_find_by_name(ip_set_s);
			if (!isli) {
				ERR(MODULE_NAME": ip_is_trusted: ip set '%.*s' is not declared\n", ip_set_s.len, ip_set_s.s);
				return -1;
			}
			kind = IP_SET_PARAM_KIND_GLOBAL;
			goto force_global;
		}		
		ip_set = &((struct ip_set_param*)_ip_set)->u.local.ip_set;
	}
	else {
		isli = ((struct ip_set_param*)_ip_set)->u.global.ip_set;
	force_global:
		if (!isli->ip_set) return -1; /* empty ip set */
		
		if (unlikely(isli->ip_set != ip_set_list_local[isli->idx])) {   /* global ip set has changed ? */
			if (ip_set_list_local[isli->idx]) {
				if (atomic_dec_and_test(&ip_set_list_local[isli->idx]->refcnt)) {
					ip_set_destroy(&ip_set_list_local[isli->idx]->ip_set);
					shm_free(ip_set_list_local[isli->idx]);
					ip_set_list_local[isli->idx] = NULL;
				}
			}
			lock_get(&isli->read_lock);			
			atomic_inc(&isli->ip_set->refcnt);
			ip_set_list_local[isli->idx] = isli->ip_set;
			lock_release(&isli->read_lock);
		}
		ip_set = &ip_set_list_local[isli->idx]->ip_set;
	}
	
	if (get_str_fparam(&ip_s, msg, (fparam_t*)_ip) < 0) {
	    ERR(MODULE_NAME": ip_is_trusted: Error while obtaining ip parameter value\n");
	    return -1;
	}
	if (!ip_s.len || !ip_set_s.len) return -1;
	switch (ip_s.s[0]) {
		case 's':	/* src */
		case 'S':
			ip = &msg->rcv.src_ip;
			break;
		case 'd':	/* dst */
		case 'D':
			ip = &msg->rcv.dst_ip;
			break;
		case 'r':	/* rcv */
		case 'R':
			ip = &msg->rcv.bind_address->address;
			break;			
		default:
			/* string -> ip */

			if ( ((ip = str2ip(&ip_s))==0)
			                  && ((ip = str2ip6(&ip_s))==0)
							                  ){
				ERR(MODULE_NAME": ip_is_trusted: string to ip conversion error '%.*s'\n", ip_s.len, ip_s.s);
				return -1;
			}
			ip_buf = *ip;
			ip = &ip_buf;  /* value has been in static buffer */			
			break;
	}

	/* test if ip_set string has changed since last call */
	if (kind == IP_SET_PARAM_KIND_LOCAL) {
		if (((struct ip_set_param*)_ip_set)->u.local.s.len != ip_set_s.len || 
			memcmp(((struct ip_set_param*)_ip_set)->u.local.s.s, ip_set_s.s, ip_set_s.len) != 0) {

			ip_set_init(&new_ip_set, 0);
			if (ip_set_add_list(&new_ip_set, ip_set_s) < 0) {
				ip_set_destroy(&new_ip_set);
				return -1;
			};
			if (((struct ip_set_param*)_ip_set)->u.local.sz < ip_set_s.len) {
				void *p;
				p = pkg_realloc(((struct ip_set_param*)_ip_set)->u.local.s.s, ip_set_s.len);
				if (!p) {
					ip_set_destroy(&new_ip_set);
					return E_OUT_OF_MEM;
				}
				((struct ip_set_param*)_ip_set)->u.local.s.s = p;			
				((struct ip_set_param*)_ip_set)->u.local.sz = ip_set_s.len;			
			}
			memcpy(((struct ip_set_param*)_ip_set)->u.local.s.s, ip_set_s.s, ip_set_s.len);
			((struct ip_set_param*)_ip_set)->u.local.s.len = ip_set_s.len;
			ip_set_destroy(&((struct ip_set_param*)_ip_set)->u.local.ip_set);
			((struct ip_set_param*)_ip_set)->u.local.ip_set = new_ip_set;
		}
	}
/* ip_set_print(stderr, &ip_set); */
	switch (ip_set_ip_exists(ip_set, ip)) {
		case IP_TREE_FIND_FOUND:
		case IP_TREE_FIND_FOUND_UPPER_SET:
			return 1;
		default:
			return -1;
	}
}