Exemplo n.º 1
0
int xavp_insert(sr_xavp_t *xavp, int idx, sr_xavp_t **list)
{
	sr_xavp_t *crt = 0;
	sr_xavp_t *lst = 0;
	sr_xval_t val;
	int n = 0;
	int i = 0;

	crt = xavp_get_internal(&xavp->name, list, 0, NULL);

	if (idx == 0 && (!crt || crt->val.type != SR_XTYPE_NULL))
		return xavp_add(xavp, list);

	while(crt!=NULL && n<idx) {
		lst = crt;
		n++;
		crt = xavp_get_next(lst);
	}

	if (crt && crt->val.type == SR_XTYPE_NULL) {
		xavp->next = crt->next;
		crt->next = xavp;

		xavp_rm(crt, list);
		return 0;
	}

	memset(&val, 0, sizeof(sr_xval_t));
	val.type = SR_XTYPE_NULL;
	for(i=0; i<idx-n; i++) {
		crt = xavp_new_value(&xavp->name, &val);
		if(crt==NULL)
			return -1;
		if (lst == NULL) {
			xavp_add(crt, list);
		} else {
			crt->next = lst->next;
			lst->next = crt;
		}
		lst = crt;
	}

	if(lst==NULL) {
		LM_ERR("cannot link the xavp\n");
		return -1;
	}
	xavp->next = lst->next;
	lst->next = xavp;

	return 0;
}
Exemplo n.º 2
0
/*! \brief
 * Lookup contact in the database and rewrite Request-URI
 * \return: -1 : not found
 *          -2 : found but method not allowed
 *          -3 : error
 */
int lookup(struct sip_msg* _m, udomain_t* _d, str* _uri)
{
	urecord_t* r;
	str aor, uri;
	sip_uri_t puri;
	ucontact_t* ptr = 0;
	int res;
	int ret;
	str path_dst;
	flag_t old_bflags;
	int i;
	str inst = {0};
	unsigned int ahash = 0;
	sr_xavp_t *xavp=NULL;
	sr_xavp_t *list=NULL;
	str xname = {"ruid", 4};
	sr_xval_t xval;

	ret = -1;

	if (_m->new_uri.s) uri = _m->new_uri;
	else uri = _m->first_line.u.request.uri;
	
	if (extract_aor((_uri)?_uri:&uri, &aor, &puri) < 0) {
		LM_ERR("failed to extract address of record\n");
		return -3;
	}
	/* check if gruu */
	if(puri.gr.s!=NULL)
	{
		if(puri.gr_val.len>0) {
			/* pub-gruu */
			inst = puri.gr_val;
			LM_DBG("looking up pub gruu [%.*s]\n", inst.len, inst.s);
		} else {
			/* temp-gruu */
			ahash = 0;
			inst = puri.user;
			for(i=inst.len-1; i>=0; i--)
			{
				if(inst.s[i]==REG_GRUU_SEP)
					break;
				ahash <<= 4;
				if(inst.s[i] >='0' && inst.s[i] <='9') ahash+=inst.s[i] -'0';
				else if (inst.s[i] >='a' && inst.s[i] <='f') ahash+=inst.s[i] -'a'+10;
				else if (inst.s[i] >='A' && inst.s[i] <='F') ahash+=inst.s[i] -'A'+10;
				else {
					LM_ERR("failed to extract temp gruu - invalid hash\n");
					return -3;
				}
			}
			if(i<0) {
				LM_ERR("failed to extract temp gruu - invalid format\n");
				return -3;
			}
			inst.len = i;
			LM_DBG("looking up temp gruu [%u / %.*s]\n", ahash, inst.len, inst.s);
		}
	}

	get_act_time();

	if(puri.gr.s==NULL || puri.gr_val.len>0)
	{
		/* aor or pub-gruu lookup */
		ul.lock_udomain(_d, &aor);
		res = ul.get_urecord(_d, &aor, &r);
		if (res > 0) {
			LM_DBG("'%.*s' Not found in usrloc\n", aor.len, ZSW(aor.s));
			ul.unlock_udomain(_d, &aor);
			return -1;
		}

		ptr = r->contacts;
		ret = -1;
		/* look first for an un-expired and suported contact */
		while (ptr) {
			if(VALID_CONTACT(ptr,act_time)) {
				if(allowed_method(_m,ptr)) {
					/* match on instance, if pub-gruu */
					if(inst.len>0) {
						if(reg_cmp_instances(&inst, &ptr->instance)==0)
						{
							/* pub-gruu - found by instance */
							LM_DBG("contact for [%.*s] found by pub gruu [%.*s]\n",
								aor.len, ZSW(aor.s), inst.len, inst.s);
							break;
						}
					} else {
						/* no-gruu - found by address */
						LM_DBG("contact for [%.*s] found by address\n",
								aor.len, ZSW(aor.s));
						break;
					}
				} else {
					LM_DBG("contact for [%.*s] cannot handle the SIP method\n",
							aor.len, ZSW(aor.s));
					ret = -2;
				}
			}
			ptr = ptr->next;
		}
		if (ptr==0) {
			/* nothing found */
			LM_DBG("'%.*s' has no valid contact in usrloc\n", aor.len, ZSW(aor.s));
			goto done;
		}
	} else {
		/* temp-gruu lookup */
		res = ul.get_urecord_by_ruid(_d, ahash, &inst, &r, &ptr);
		if(res<0) {
			LM_DBG("temp gruu '%.*s' not found in usrloc\n", aor.len, ZSW(aor.s));
			return -1;
		}
		aor = *ptr->aor;
		/* test if un-expired and suported contact */
		if( (ptr) && !(VALID_CONTACT(ptr,act_time)
					&& (ret=-2) && allowed_method(_m,ptr)))
			goto done;
		LM_DBG("contact for [%.*s] found by temp gruu [%.*s / %u]\n",
							aor.len, ZSW(aor.s), inst.len, inst.s, ahash);
	}

	ret = 1;
	if (ptr) {
		if (rewrite_uri(_m, &ptr->c) < 0) {
			LM_ERR("unable to rewrite Request-URI\n");
			ret = -3;
			goto done;
		}

		/* reset next hop address */
		reset_dst_uri(_m);

		/* add xavp with details of the record (ruid, ...) */
		if(reg_xavp_rcd.s!=NULL)
		{
			list = xavp_get(&reg_xavp_rcd, NULL);
			xavp = list;
			memset(&xval, 0, sizeof(sr_xval_t));
			xval.type = SR_XTYPE_STR;
			xval.v.s = ptr->ruid;
			xavp_add_value(&xname, &xval, &xavp);
			if(list==NULL)
			{
				/* no reg_xavp_rcd xavp in root list - add it */
				xval.type = SR_XTYPE_XAVP;
				xval.v.xavp = xavp;
				xavp_add_value(&reg_xavp_rcd, &xval, NULL);
			}
		}
		/* If a Path is present, use first path-uri in favour of
		 * received-uri because in that case the last hop towards the uac
		 * has to handle NAT. - agranig */
		if (ptr->path.s && ptr->path.len) {
			if (get_path_dst_uri(&ptr->path, &path_dst) < 0) {
				LM_ERR("failed to get dst_uri for Path\n");
				ret = -3;
				goto done;
			}
			if (set_path_vector(_m, &ptr->path) < 0) {
				LM_ERR("failed to set path vector\n");
				ret = -3;
				goto done;
			}
			if (set_dst_uri(_m, &path_dst) < 0) {
				LM_ERR("failed to set dst_uri of Path\n");
				ret = -3;
				goto done;
			}
		} else if (ptr->received.s && ptr->received.len) {
			if (set_dst_uri(_m, &ptr->received) < 0) {
				ret = -3;
				goto done;
			}
		}

		if (ptr->instance.len) {
		    if (set_instance(_m, &(ptr->instance)) < 0) {
				ret = -3;
				goto done;
		    }
		}
		
		_m->reg_id = ptr->reg_id;

		if (ptr->ruid.len) {
		    if (set_ruid(_m, &(ptr->ruid)) < 0) {
				ret = -3;
				goto done;
		    }
		}

		if (ptr->user_agent.len) {
		    if (set_ua(_m, &(ptr->user_agent)) < 0) {
				ret = -3;
				goto done;
		    }
		}

		set_ruri_q(ptr->q);

		old_bflags = 0;
		getbflagsval(0, &old_bflags);
		setbflagsval(0, old_bflags|ptr->cflags);

		if (ptr->sock)
			set_force_socket(_m, ptr->sock);

		if(ptr->xavp!=NULL) {
			xavp = xavp_clone_level_nodata(ptr->xavp);
			if(xavp_add(xavp, NULL)<0) {
				ret = -3;
				goto done;
			}
		}
		ptr = ptr->next;
	}

	/* if was gruu, no more branches */
	if(inst.len>0) goto done;

	/* Append branches if enabled */
	if (!cfg_get(registrar, registrar_cfg, append_branches)) goto done;

	for( ; ptr ; ptr = ptr->next ) {
		if (VALID_CONTACT(ptr, act_time) && allowed_method(_m, ptr)) {
			path_dst.len = 0;
			if(ptr->path.s && ptr->path.len 
			&& get_path_dst_uri(&ptr->path, &path_dst) < 0) {
				LM_ERR("failed to get dst_uri for Path\n");
				continue;
			}

			/* The same as for the first contact applies for branches 
			 * regarding path vs. received. */
			LM_DBG("instance is %.*s\n",
			       ptr->instance.len, ptr->instance.s);
			if (append_branch(_m, &ptr->c,
					  path_dst.len?&path_dst:&ptr->received,
					  &ptr->path, ptr->q, ptr->cflags,
					  ptr->sock,
					  ptr->instance.len?&(ptr->instance):0,
				          ptr->instance.len?ptr->reg_id:0,
					  &ptr->ruid, &ptr->user_agent)
			    == -1) {
				LM_ERR("failed to append a branch\n");
				/* Also give a chance to the next branches*/
				continue;
			}
			if(ptr->xavp!=NULL) {
				xavp = xavp_clone_level_nodata(ptr->xavp);
				if(xavp_insert(xavp, nr_branches, NULL)<0) {
					ret = -3;
					goto done;
				}
			}
		}
	}

done:
	ul.release_urecord(r);
	ul.unlock_udomain(_d, &aor);
	return ret;
}
Exemplo n.º 3
0
int registered4(struct sip_msg* _m, udomain_t* _d, str* _uri, int match_flag,
		int match_action_flag)
{
	str uri, aor;
	urecord_t* r;
	ucontact_t* ptr;
	int res;
	str match_callid = {0,0};
	str match_received = {0,0};
	str match_contact = {0,0};
	sr_xavp_t *vavp = NULL;

	if(_uri!=NULL)
	{
		uri = *_uri;
	} else {
		if(IS_SIP_REPLY(_m)) {
			if (parse_to_header(_m) < 0) {
				LM_ERR("failed to prepare the message\n");
				return -1;
			}
			uri = get_to(_m)->uri;
		} else {
			if (_m->new_uri.s) uri = _m->new_uri;
			else uri = _m->first_line.u.request.uri;
		}
	}

	if (extract_aor(&uri, &aor, NULL) < 0) {
		LM_ERR("failed to extract address of record\n");
		return -1;
	}

	ul.lock_udomain(_d, &aor);
	res = ul.get_urecord(_d, &aor, &r);

	if (res < 0) {
		ul.unlock_udomain(_d, &aor);
		LM_ERR("failed to query usrloc\n");
		return -1;
	}

	if (res == 0) {
		LM_DBG("searching with match flags (%d,%d)\n", match_flag,
				match_action_flag);
		if(reg_xavp_cfg.s!=NULL) {

			if((match_flag & 1)
					&& (vavp = xavp_get_child_with_sval(&reg_xavp_cfg,
							&match_callid_name)) != NULL
					&& vavp->val.v.s.len > 0) {
				match_callid = vavp->val.v.s;
				LM_DBG("matching with callid %.*s\n", match_callid.len,
						match_callid.s);
			}

			if((match_flag & 2)
					&& (vavp = xavp_get_child_with_sval(&reg_xavp_cfg,
							&match_received_name)) != NULL
					&& vavp->val.v.s.len > 0) {
				match_received = vavp->val.v.s;
				LM_DBG("matching with received %.*s\n", match_received.len,
						match_received.s);
			}

			if((match_flag & 4)
					&& (vavp = xavp_get_child_with_sval(&reg_xavp_cfg,
							&match_contact_name)) != NULL
					&& vavp->val.v.s.len > 0) {
				match_contact = vavp->val.v.s;
				LM_DBG("matching with contact %.*s\n", match_contact.len,
						match_contact.s);
			}
		}

		for (ptr = r->contacts; ptr; ptr = ptr->next) {
			if(!VALID_CONTACT(ptr, act_time)) continue;
			if (match_callid.s && /* optionally enforce tighter matching w/ Call-ID */
				match_callid.len > 0 &&
				(match_callid.len != ptr->callid.len ||
				memcmp(match_callid.s, ptr->callid.s, match_callid.len)))
				continue;
			if (match_received.s && /* optionally enforce tighter matching w/ ip:port */
				match_received.len > 0 &&
				(match_received.len != ptr->received.len ||
				memcmp(match_received.s, ptr->received.s, match_received.len)))
				continue;
			if (match_contact.s && /* optionally enforce tighter matching w/ Contact */
				match_contact.len > 0 &&
				(match_contact.len != ptr->c.len ||
				memcmp(match_contact.s, ptr->c.s, match_contact.len)))
				continue;

			if(!(match_action_flag & 2)) {
				xavp_rcd_helper(ptr);
			}

			if((ptr->xavp!=NULL) && (match_action_flag & 1)) {
				sr_xavp_t *xavp = xavp_clone_level_nodata(ptr->xavp);
				if(xavp_add(xavp, NULL)<0) {
					LM_ERR("error adding xavp for %.*s after successful match\n",
							aor.len, ZSW(aor.s));
					xavp_destroy_list(&xavp);
				}
			}

			ul.release_urecord(r);
			ul.unlock_udomain(_d, &aor);
			LM_DBG("'%.*s' found in usrloc\n", aor.len, ZSW(aor.s));

			return 1;
		}
	}

	ul.unlock_udomain(_d, &aor);
	LM_DBG("'%.*s' not found in usrloc\n", aor.len, ZSW(aor.s));
	return -1;
}