static int rewrite_route_set(pjsip_rx_data *rdata, pjsip_dialog *dlg)
{
	pjsip_rr_hdr *rr = NULL;
	pjsip_sip_uri *uri;

	if (rdata->msg_info.msg->type == PJSIP_RESPONSE_MSG) {
		pjsip_hdr *iter;
		for (iter = rdata->msg_info.msg->hdr.prev; iter != &rdata->msg_info.msg->hdr; iter = iter->prev) {
			if (iter->type == PJSIP_H_RECORD_ROUTE) {
				rr = (pjsip_rr_hdr *)iter;
				break;
			}
		}
	} else if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_register_method)) {
		rr = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_RECORD_ROUTE, NULL);
	}

	if (rr) {
		uri = pjsip_uri_get_uri(&rr->name_addr);
		rewrite_uri(rdata, uri);
		if (dlg && !pj_list_empty(&dlg->route_set) && !dlg->route_set_frozen) {
			pjsip_routing_hdr *route = dlg->route_set.next;
			uri = pjsip_uri_get_uri(&route->name_addr);
			rewrite_uri(rdata, uri);
		}

		return 0;
	}

	return -1;
}
static PyObject *msg_rewrite_ruri(msgobject *self, PyObject *args)
{
	str nuri;

	if (self == NULL) {
		PyErr_SetString(PyExc_RuntimeError, "self is NULL");
		Py_INCREF(Py_None);
		return Py_None;
	}

	if (self->msg == NULL) {
		PyErr_SetString(PyExc_RuntimeError, "self->msg is NULL");
		Py_INCREF(Py_None);
		return Py_None;
	}

	if ((self->msg->first_line).type != SIP_REQUEST) {
		PyErr_SetString(PyExc_RuntimeError, "Not a request message - rewrite is not possible.\n");
		Py_INCREF(Py_None);
		return Py_None;
	}

	if(!PyArg_ParseTuple(args, "s:rewrite_ruri", &nuri.s))
		return NULL;

	nuri.len = strlen(nuri.s);

	if(rewrite_uri(self->msg, &nuri)<0) {
		LM_ERR("failed to update r-uri with [%.*s]\n", nuri.len, nuri.s);
	}

	Py_INCREF(Py_None);
	return Py_None;
}
Beispiel #3
0
/*
 * Logic necessary to forward request to strict routers
 *
 * Returns 0 on success, negative number on an error
 */
static inline int handle_sr(struct sip_msg* _m, struct hdr_field* _hdr, rr_t* _r)
{
	str* uri;
	char* rem_off;
	int rem_len;

	uri = &_r->nameaddr.uri;

	     /* Next hop is strict router, save R-URI here */
	if (save_ruri(_m) < 0) {
		LOG(L_ERR, "handle_sr: Error while saving Request-URI\n");
		return -1;
	}

	     /* Put the first Route in Request-URI */
	if (rewrite_uri(_m, uri) < 0) {
		LOG(L_ERR, "handle_sr: Error while rewriting request URI\n");
		return -2;
	}

	if (!_r->next) {
		rem_off = _hdr->name.s;
		rem_len = _hdr->len;
	} else {
		rem_off = _hdr->body.s;
		rem_len = _r->next->nameaddr.name.s - _hdr->body.s;
	}

	if (!del_lump(_m, rem_off - _m->buf, rem_len, 0)) {
		LOG(L_ERR, "handle_sr: Can't remove Route HF\n");
		return -9;
	}

	return 0;
}
Beispiel #4
0
/*
 * Converts Request-URI, if it is tel URI, to SIP URI.  Returns 1, if
 * conversion succeeded or if no conversion was needed, i.e., Request-URI
 * was not tel URI.  Returns -1, if conversion failed.
 */
int tel2sip(struct sip_msg* _msg, char* _s1, char* _s2)
{
	str *ruri, furi;
	struct sip_uri pfuri;
	str suri;
	char* at;

	ruri = GET_RURI(_msg);

	if (ruri->len < 4) return 1;

	if (strncmp(ruri->s, "tel:", 4) != 0) return 1;

	if (parse_from_header(_msg) < 0) {
		LOG(L_ERR, "tel2sip(): Error while parsing From header\n");
		return -1;
	}
	furi = get_from(_msg)->uri;
	if (parse_uri(furi.s, furi.len, &pfuri) < 0) {
		LOG(L_ERR, "tel2sip(): Error while parsing From URI\n");
		return -1;
	}

	suri.len = 4 + ruri->len - 4 + 1 + pfuri.host.len + 1 + 10;
	suri.s = pkg_malloc(suri.len);
	if (suri.s == 0) {
		LOG(L_ERR, "tel2sip(): Memory allocation failure\n");
		return -1;
	}
	at = suri.s;
	memcpy(at, "sip:", 4);
	at = at + 4;
	memcpy(at, ruri->s + 4, ruri->len - 4);
	at = at + ruri->len - 4;
	*at = '@';
	at = at + 1;
	memcpy(at, pfuri.host.s, pfuri.host.len);
	at = at + pfuri.host.len;
	*at = ';';
	at = at + 1;
	memcpy(at, "user=phone", 10);

	LOG(L_ERR, "tel2sip(): SIP URI is <%.*s>\n", suri.len, suri.s);

	if (rewrite_uri(_msg, &suri) == 1) {
		pkg_free(suri.s);
		return 1;
	} else {
		pkg_free(suri.s);
		return -1;
	}
}
Beispiel #5
0
/*
 * Build SIP message for destination
 * param msg SIP message
 * param isfirst Is first destination
 * param type Main or branch route block
 * param format URI format
 * return MODULE_RETURNCODE_TRUE success MODULE_RETURNCODE_FALSE failure
 */
static int ospPrepareDestination(
    struct sip_msg* msg, 
    int isfirst,
    int type,
    int format)
{
    str newuri = {NULL, 0};
    int result = MODULE_RETURNCODE_FALSE;

    LOG(L_DBG, "osp: ospPrepareDestination\n");

    osp_dest *dest = ospGetNextOrigDestination();

    if (dest != NULL) {
        ospRebuildDestionationUri(&newuri, dest->called, dest->host, "", format);

        LOG(L_INFO, 
            "osp: prepare route to URI '%.*s' for call_id '%.*s' transaction_id '%llu'\n",
            newuri.len,
            newuri.s,
            dest->callidsize,
            dest->callid,
            dest->transid);

        if (type == OSP_MAIN_ROUTE) {
            if (isfirst == OSP_FIRST_ROUTE) {
                rewrite_uri(msg, &newuri);
            } else {
                append_branch(msg, &newuri, NULL, NULL, Q_UNSPECIFIED,
                              0, NULL);
            }

            result = MODULE_RETURNCODE_TRUE;
        } else {
            LOG(L_ERR, "osp: ERROR: unsupported route block type\n");
        }
    } else {
        LOG(L_DBG, "osp: there is no more routes\n");
        ospReportOrigSetupUsage();
    }

    if (newuri.len > 0) {
        pkg_free(newuri.s);
    }
    
    return result;
}
Beispiel #6
0
static enum evhook_status
goto_url_hook(va_list ap, void *data)
{
	unsigned char **url = va_arg(ap, unsigned char **);
	struct session *ses = va_arg(ap, struct session *);
	unsigned char *uu = NULL;
	unsigned char *arg = "";
	unsigned char *argstart = *url + strcspn(*url, " :");

	if (get_smart_enable() && *argstart) {
		unsigned char bucket = *argstart;

		*argstart = '\0';
		uu = get_uri_rewrite_prefix(URI_REWRITE_SMART, *url);
		*argstart = bucket;
		arg = argstart + 1;
	}

	if (get_dumb_enable() && !uu && !*argstart)
		uu = get_uri_rewrite_prefix(URI_REWRITE_DUMB, *url);

	if (!uu
	    && !strchr((const char *)*url, ':')
	    && !strchr((const char *)*url, '.')
	    && !strchr((const char *)*url, '/')) {
		uu = get_opt_str("protocol.rewrite.default_template", NULL);
		if (uu && *uu) {
			arg = *url;
		} else {
			uu = NULL;
		}
	}

	if (uu) {
		struct uri *uri = ses && have_location(ses)
				? cur_loc(ses)->vs.uri : NULL;

		uu = rewrite_uri(uu, uri, arg);
		if (uu) {
			mem_free(*url);
			*url = uu;
		}
	}

	return EVENT_HOOK_STATUS_NEXT;
}
Beispiel #7
0
int set_alias_to_ruri(struct sip_msg* _msg, str *alias, int no, void *p)
{
	/* set the RURI */
	if(no==0)
	{
		if(rewrite_uri(_msg, alias)<0)
		{
			LM_ERR("cannot replace the R-URI\n");
			return -1;
		}
	} else if (ald_append_branches) {
		if (append_branch(_msg, alias, 0, 0, MIN_Q, 0, 0, 0, 0, 0, 0) == -1)
		{
			LM_ERR("error while appending branches\n");
			return -1;
		}
	}
	return 0;
}
static int rewrite_contact(pjsip_rx_data *rdata, pjsip_dialog *dlg)
{
	pjsip_contact_hdr *contact;

	contact = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT, NULL);
	if (contact && !contact->star && (PJSIP_URI_SCHEME_IS_SIP(contact->uri) || PJSIP_URI_SCHEME_IS_SIPS(contact->uri))) {
		pjsip_sip_uri *uri = pjsip_uri_get_uri(contact->uri);

		rewrite_uri(rdata, uri);

		if (dlg && pj_list_empty(&dlg->route_set) && (!dlg->remote.contact
			|| pjsip_uri_cmp(PJSIP_URI_IN_REQ_URI, dlg->remote.contact->uri, contact->uri))) {
			dlg->remote.contact = (pjsip_contact_hdr*)pjsip_hdr_clone(dlg->pool, contact);
			dlg->target = dlg->remote.contact->uri;
		}
		return 0;
	}

	return -1;
}
Beispiel #9
0
/**
 * Creates new "main" branch by making copy of branch-failure branch.
 * Currently the following branch attributes are included:
 * request-uri, ruid, path, instance, and branch flags.
 */
static int w_t_reuse_branch(sip_msg_t* msg, char *p1, char *p2)
{
	tm_cell_t *t;
	int branch;

	if (msg == NULL) return -1;

	/* first get the transaction */
	if (_tmx_tmb.t_check(msg, 0) == -1) return -1;
	if ((t = _tmx_tmb.t_gett()) == 0) {
		LM_ERR("no transaction\n");
		return -1;
	}
	switch (get_route_type()) {
		case BRANCH_FAILURE_ROUTE:
			/* use the reason of the winning reply */
			if ((branch = _tmx_tmb.t_get_picked_branch()) < 0) {
				LM_CRIT("no picked branch (%d) for a final response"
						" in MODE_ONFAILURE\n", branch);
				return -1;
			}
			if(rewrite_uri(msg, &(t->uac[branch].uri))<0) {
				LM_WARN("failed to rewrite the r-uri\n");
			}
			set_ruid(msg, &(t->uac[branch].ruid));
			if (t->uac[branch].path.len) {
				if(set_path_vector(msg, &(t->uac[branch].path))<0) {
					LM_WARN("failed to set the path vector\n");
				}
			} else {
				reset_path_vector(msg);
			}
			setbflagsval(0, t->uac[branch].branch_flags);
			set_instance(msg, &(t->uac[branch].instance));
			return 1;
		default:
			LM_ERR("unsupported route_type %d\n", get_route_type());
			return -1;
	}
}
Beispiel #10
0
/*!
 * \brief Necessary logic to forward request to strict routers
 * \param _m SIP message
 * \param _hdr SIP header field
 * \param _r Route & Record-Route header field body
 * \return 0 on success, negative on an error
 */
static inline int handle_sr(struct sip_msg* _m, struct hdr_field* _hdr, rr_t* _r)
{
    str uri;
    char* rem_off;
    int rem_len;

    /* Next hop is strict router, save R-URI here */
    if (save_ruri(_m) < 0) {
        LM_ERR("failed to save Request-URI\n");
        return -1;
    }

    /* Put the first Route in Request-URI */
    uri = _r->nameaddr.uri;
    if(get_maddr_uri(&uri, 0)!=0) {
        LM_ERR("failed to check maddr\n");
        return RR_ERROR;
    }
    if (rewrite_uri(_m, &uri) < 0) {
        LM_ERR("failed to rewrite request URI\n");
        return -2;
    }

    if (!_r->next) {
        rem_off = _hdr->name.s;
        rem_len = _hdr->len;
    } else {
        rem_off = _hdr->body.s;
        rem_len = _r->next->nameaddr.name.s - _hdr->body.s;
    }

    if (!del_lump(_m, rem_off - _m->buf, rem_len, 0)) {
        LM_ERR("failed to remove Route HF\n");
        return -9;
    }

    return 0;
}
Beispiel #11
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) {
    impurecord_t* r;
    str aor, uri;
    ucontact_t* ptr;
    int res;
    int ret;
    str path_dst;
    flag_t old_bflags;
    int i = 0;


    if (_m->new_uri.s) uri = _m->new_uri;
    else uri = _m->first_line.u.request.uri;

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

    get_act_time();

    ul.lock_udomain(_d, &aor);
    res = ul.get_impurecord(_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;
    }
    ret = -1;

    while (i < MAX_CONTACTS_PER_IMPU && (ptr = r->newcontacts[i])) {
	if (VALID_CONTACT(ptr, act_time) && allowed_method(_m, ptr)) {
	    LM_DBG("Found a valid contact [%.*s]\n", ptr->c.len, ptr->c.s);
	    i++;
	    break;
	}
	i++;
    }

    /* look first for an un-expired and suported contact */
    if (ptr == 0) {
	/* nothing found */
	goto done;
    }

    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);

	/* 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;
	    }
	}

	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);

	ptr = ptr->next;
    }

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

    //the last i was the first valid contact we found - let's go through the rest of valid contacts and append the branches.
    while (i < MAX_CONTACTS_PER_IMPU && (ptr = r->newcontacts[i])) {
	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. */
	    if (km_append_branch(_m, &ptr->c, path_dst.len ? &path_dst : &ptr->received,
		    &ptr->path, ptr->q, ptr->cflags, ptr->sock) == -1) {
		LM_ERR("failed to append a branch\n");
		/* Also give a chance to the next branches*/
		continue;
	    }
	}
	i++;
    }

done:
    ul.unlock_udomain(_d, &aor);
    return ret;
}
Beispiel #12
0
int enum_pv_query_3(struct sip_msg* _msg, char* _sp, char* _suffix,
		    char* _service)
{
	char *user_s;
	int user_len, i, j, first;
	char name[MAX_DOMAIN_SIZE];
	char uri[MAX_URI_SIZE];
	char new_uri[MAX_URI_SIZE];
	unsigned int priority, curr_prio;
	qvalue_t q;
	struct rdata* head;
	struct rdata* l;
	struct naptr_rdata* naptr;
	str pattern, replacement, result, new_result;
	str *suffix, *service;
	char string[MAX_NUM_LEN];
	pv_spec_t *sp;
	pv_value_t pv_val;

	sp = (pv_spec_t *)_sp;
	suffix = (str*)_suffix;
	service = (str*)_service;

	/*
	 * Get E.164 number from pseudo variable
         */
	if (sp && (pv_get_spec_value(_msg, sp, &pv_val) == 0)) {
	    if (pv_val.flags & PV_VAL_STR) {
		if (pv_val.rs.len == 0 || pv_val.rs.s == NULL) {
		    LM_DBG("Missing E.164 number\n");
		    return -1;
		}
	    } else {
		LM_DBG("Pseudo variable value is not string\n");
		return -1;
	}
	} else {
	    LM_DBG("Cannot get pseudo variable value\n");
	    return -1;
	}
	if (is_e164(&(pv_val.rs)) == -1) {
	    LM_ERR("pseudo variable does not contain an E164 number\n");
	    return -1;
	}

	user_s = pv_val.rs.s;
	user_len = pv_val.rs.len;

	memcpy(&(string[0]), user_s, user_len);
	string[user_len] = (char)0;

	j = 0;
	for (i = user_len - 1; i > 0; i--) {
		name[j] = user_s[i];
		name[j + 1] = '.';
		j = j + 2;
	}

	memcpy(name + j, suffix->s, suffix->len + 1);

	head = get_record(name, T_NAPTR, RES_ONLY_TYPE);

	if (head == 0) {
		LM_DBG("No NAPTR record found for %s.\n", name);
		return -1;
	}

	naptr_sort(&head);

	q = MAX_Q - 10;
	curr_prio = 0;
	first = 1;

	for (l = head; l; l = l->next) {

		if (l->type != T_NAPTR) continue; /*should never happen*/
		naptr = (struct naptr_rdata*)l->rdata;
		if (naptr == 0) {
			LM_ERR("Null rdata in DNS response\n");
			continue;
		}

		LM_DBG("ENUM query on %s: order %u, pref %u, flen %u, flags "
		       "'%.*s', slen %u, services '%.*s', rlen %u, "
		       "regexp '%.*s'\n",
		       name, naptr->order, naptr->pref,
		    naptr->flags_len, (int)(naptr->flags_len), ZSW(naptr->flags),
		    naptr->services_len,
		    (int)(naptr->services_len), ZSW(naptr->services), naptr->regexp_len,
		    (int)(naptr->regexp_len), ZSW(naptr->regexp));

		if (sip_match(naptr, service) == 0) continue;

		if (parse_naptr_regexp(&(naptr->regexp[0]), naptr->regexp_len,
				       &pattern, &replacement) < 0) {
			LM_ERR("Parsing of NAPTR regexp failed\n");
			continue;
		}
		result.s = &(uri[0]);
		result.len = MAX_URI_SIZE;
		/* Avoid making copies of pattern and replacement */
		pattern.s[pattern.len] = (char)0;
		replacement.s[replacement.len] = (char)0;
		if (reg_replace(pattern.s, replacement.s, &(string[0]),
				&result) < 0) {
			pattern.s[pattern.len] = '!';
			replacement.s[replacement.len] = '!';
			LM_ERR("Regexp replace failed\n");
			continue;
		}
		LM_DBG("Resulted in replacement: '%.*s'\n",
		       result.len, ZSW(result.s));
		pattern.s[pattern.len] = '!';
		replacement.s[replacement.len] = '!';
		
		if (param.len > 0) {
			if (result.len + param.len > MAX_URI_SIZE - 1) {
				LM_ERR("URI is too long\n");
				continue;
			}
			new_result.s = &(new_uri[0]);
			new_result.len = MAX_URI_SIZE;
			if (add_uri_param(&result, &param, &new_result) == 0) {
				LM_ERR("Parsing of URI <%.*s> failed\n",
				       result.len, result.s);
				continue;
			}
			if (new_result.len > 0) {
				result = new_result;
			}
		}

		if (first) {
			if (rewrite_uri(_msg, &result) == -1) {
				goto done;
			}
			set_ruri_q(q);
			first = 0;
			curr_prio = ((naptr->order) << 16) + naptr->pref;
		} else {
			priority = ((naptr->order) << 16) + naptr->pref;
			if (priority > curr_prio) {
				q = q - 10;
				curr_prio = priority;
			}
			if (append_branch(_msg, &result, 0, 0, q, 0, 0, 0, 0, 0, 0)
			    == -1) {
				goto done;
			}
		}
	}

done:
	free_rdata_list(head);
	return first ? -1 : 1;
}
Beispiel #13
0
/*
 * Lookup contact in the database and rewrite Request-URI
 */
int lookup(struct sip_msg* _m, char* _t, char* _s)
{
	urecord_t* r;
	str uid;
	ucontact_t* ptr;
	int res;
	unsigned int nat;
	str new_uri; 	

	nat = 0;
	
	if (get_to_uid(&uid, _m) < 0) return -1;

	get_act_time();

	ul.lock_udomain((udomain_t*)_t);
	res = ul.get_urecord((udomain_t*)_t, &uid, &r);
	if (res < 0) {
		LOG(L_ERR, "lookup(): Error while querying usrloc\n");
		ul.unlock_udomain((udomain_t*)_t);
		return -2;
	}
	
	if (res > 0) {
		DBG("lookup(): '%.*s' Not found in usrloc\n", uid.len, ZSW(uid.s));
		ul.unlock_udomain((udomain_t*)_t);
		return -3;
	}

	ptr = r->contacts;
	while ((ptr) && !VALID_CONTACT(ptr, act_time))
		ptr = ptr->next;
	
	if (ptr) {
		if (ptr->received.s && ptr->received.len) {
			if (received_to_uri){
				if (add_received(&new_uri, &ptr->c, &ptr->received)<0){
					LOG(L_ERR, "ERROR: lookup(): out of memory\n");
					return -4;
				}
			/* replace the msg uri */
			if (_m->new_uri.s)      pkg_free(_m->new_uri.s);
			_m->new_uri=new_uri;
			_m->parsed_uri_ok=0;
			ruri_mark_new();
			goto skip_rewrite_uri;
			}else if (set_dst_uri(_m, &ptr->received) < 0) {
				ul.unlock_udomain((udomain_t*)_t);
				return -4;
			}
		}
		
		if (rewrite_uri(_m, &ptr->c) < 0) {
			LOG(L_ERR, "lookup(): Unable to rewrite Request-URI\n");
			ul.unlock_udomain((udomain_t*)_t);
			return -4;
		}

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

skip_rewrite_uri:

		set_ruri_q(ptr->q);

		nat |= ptr->flags & FL_NAT;
		ptr = ptr->next;
	} else {
		     /* All contacts expired */
		ul.unlock_udomain((udomain_t*)_t);
		return -5;
	}
	
	     /* Append branches if enabled */
	if (!append_branches) goto skip;

	while(ptr) {
		if (VALID_CONTACT(ptr, act_time)) {
			if (received_to_uri && ptr->received.s && ptr->received.len){
				if (add_received(&new_uri, &ptr->c, &ptr->received)<0){
					LOG(L_ERR, "ERROR: lookup(): branch: out of memory\n");
					goto cont; /* try to continue */
				}
				if (append_branch(_m, &new_uri, 0, 0, ptr->q, 0, 0) == -1) {
					LOG(L_ERR, "lookup(): Error while appending a branch\n");
					pkg_free(new_uri.s);
					if (ser_error==E_TOO_MANY_BRANCHES) goto skip;
					else goto cont; /* try to continue, maybe we have an
							                   oversized contact */
				}
				pkg_free(new_uri.s); /* append_branch doesn't free it */
			}else{
				if (append_branch(_m, &ptr->c, &ptr->received, 0 /* path */,
									ptr->q, 0 /* brflags*/, ptr->sock) == -1) {
					LOG(L_ERR, "lookup(): Error while appending a branch\n");
					goto skip; /* Return OK here so the function succeeds */
				}
			}
			
			nat |= ptr->flags & FL_NAT; 
		} 
cont:
		ptr = ptr->next; 
	}
	
 skip:
	ul.unlock_udomain((udomain_t*)_t);
	if (nat) setflag(_m, load_nat_flag);
	return 1;
}
Beispiel #14
0
int rtjson_init_serial(sip_msg_t *msg, srjson_doc_t *jdoc, sr_xavp_t *iavp)
{
	srjson_t *tj = NULL;
	srjson_t *nj = NULL;
	srjson_t *rj = NULL;
	str val;
	unsigned int bflags = 0;
	unsigned int old_bflags = 0;
	struct socket_info* fsocket = NULL;

	tj = srjson_GetObjectItem(jdoc, jdoc->root, "routes");
	if(tj==NULL || tj->type!=srjson_Array || tj->child==NULL) {
		LM_ERR("missing or invalid routes field\n");
		goto error;
	}
	nj = tj->child;

	clear_branches();

	rj = srjson_GetObjectItem(jdoc, nj, "uri");
	if(rj!=NULL && rj->type==srjson_String && rj->valuestring!=NULL) {
		val.s = rj->valuestring;
		val.len = strlen(val.s);
		LM_DBG("rewrite r-uri to: [%.*s]\n", val.len, val.s);
		if (rewrite_uri(msg, &val) < 0) {
			LM_ERR("unable to rewrite Request-URI\n");
			goto error;
		}
	}

	reset_dst_uri(msg);
	reset_path_vector(msg);
	reset_instance(msg);
	reset_ruid(msg);
	reset_ua(msg);
	reset_force_socket(msg);
	msg->reg_id = 0;
	set_ruri_q(0);

	rj = srjson_GetObjectItem(jdoc, nj, "dst_uri");
	if(rj!=NULL && rj->type==srjson_String && rj->valuestring!=NULL) {
		val.s = rj->valuestring;
		val.len = strlen(val.s);
		LM_DBG("rewrite dst-uri to: [%.*s]\n", val.len, val.s);
		if (set_dst_uri(msg, &val) < 0) {
			LM_ERR("unable to set destination uri\n");
			goto error;
		}
	}

	rj = srjson_GetObjectItem(jdoc, nj, "path");
	if(rj!=NULL && rj->type==srjson_String && rj->valuestring!=NULL) {
		val.s = rj->valuestring;
		val.len = strlen(val.s);
		LM_DBG("rewrite path to: [%.*s]\n", val.len, val.s);
		if (set_path_vector(msg, &val) < 0) {
			LM_ERR("unable to set path\n");
			goto error;
		}
	}

	rj = srjson_GetObjectItem(jdoc, nj, "socket");
	if(rj!=NULL && rj->type==srjson_String && rj->valuestring!=NULL) {
		val.s = rj->valuestring;
		val.len = strlen(val.s);
		LM_DBG("trying to set send socket to: [%.*s]\n", val.len, val.s);
		fsocket = lookup_local_socket(&val);
		if(fsocket) {
			set_force_socket(msg, fsocket);
		}
	}

	rj = srjson_GetObjectItem(jdoc, nj, "branch_flags");
	if(rj!=NULL && rj->type==srjson_Number && SRJSON_GET_UINT(rj)!=0) {
		bflags = SRJSON_GET_UINT(rj);

		old_bflags = 0;
		getbflagsval(0, &old_bflags);
		setbflagsval(0, old_bflags|bflags);
	}

	iavp->val.v.i++;

	return 0;

error:
	return -1;
}
Beispiel #15
0
/*
 * Previous hop was a strict router, handle this case
 */
static inline int after_strict(struct sip_msg* _m, struct sip_uri* _pru, int _route_myself)
{
	int res, rem_len;
	struct hdr_field* hdr;
	rr_t* rt, *prev;
	char* rem_off;
	str* uri;
	str avp_cookie;

	get_avp_cookie_from_uri(&_m->parsed_uri.params, &avp_cookie);
	if (avp_cookie.len > 0)
		rr_set_avp_cookies(&avp_cookie, get_direction(_m, &_m->parsed_uri.params));

	hdr = _m->route;
	rt = (rr_t*)hdr->parsed;

	if (_route_myself == 1) {
		store_user_in_avps(&(_pru->user));

		if (!rt->next) {
			     /* No next route in the same header, remove the whole header
			      * field immediately
			      */
			if (!del_lump(_m, hdr->name.s - _m->buf, hdr->len, 0)) {
				LOG(L_ERR, "after_strict: Cannot remove Route HF\n");
				return RR_ERROR;
			}
			res = find_next_route(_m, &hdr);
			if (res < 0) {
				LOG(L_ERR, "after_strict: Error while searching next route\n");
				return RR_ERROR;
			}
			if (res > 0) { /* No next route found */
				DBG("after_strict: No next URI found\n");
				return NOT_RR_DRIVEN;
			}
			rt = (rr_t*)hdr->parsed;
		} else rt = rt->next;
	}

	if (rt != _m->route->parsed) {
		uri = &rt->nameaddr.uri;
		if (parse_uri(uri->s, uri->len, _pru) == -1) {
			LOG(L_ERR, "after_strict: Error while parsing URI\n");
			return RR_ERROR;
		}
	} else {
		uri = &rt->nameaddr.uri;
	}

	store_next_route_in_avps(uri);
	if (is_strict(&(_pru->params))) {
		DBG("after_strict: Next hop: '%.*s' is strict router\n", uri->len, ZSW(uri->s));
		     /* Previous hop was a strict router and the next hop is strict
		      * router too. There is no need to save R-URI again because it
		      * is saved already. In fact, in this case we will behave exactly
		      * like a strict router.
		      */

		     /* Note: when there is only one Route URI left (endpoint), it will
		      * always be a strict router because endpoints don't use ;lr parameter
		      * In this case we will simply put the URI in R-URI and forward it, which
		      * will work perfectly
		      */
		if (rewrite_uri(_m, uri) < 0) {
			LOG(L_ERR, "after_strict: Error while rewriting request URI\n");
			return RR_ERROR;
		}

		if (rt->next) {
			rem_off = hdr->body.s;
			rem_len = rt->next->nameaddr.name.s - hdr->body.s;
		} else {
			rem_off = hdr->name.s;
			rem_len = hdr->len;
		}
		if (!del_lump(_m, rem_off - _m->buf, rem_len, 0)) {
			LOG(L_ERR, "after_strict: Cannot remove Route HF\n");
			return RR_ERROR;
		}
	} else {
		DBG("after_strict: Next hop: '%.*s' is loose router\n", uri->len, ZSW(uri->s));

		if (set_dst_uri(_m, uri) < 0) {
			LOG(L_ERR, "after_strict: Error while setting dst_uri\n");
			return RR_ERROR;
		}

		     /* Next hop is a loose router - Which means that is is not endpoint yet
		      * In This case we have to recover from previous strict routing, that
		      * means we have to find the last Route URI and put in in R-URI and
		      * remove the last Route URI.
		      */
		if (rt != hdr->parsed) {
			     /* There is a previous route uri which was 2nd uri of mine
			      * and must be removed here
			      */
			rem_off = hdr->body.s;
			rem_len = rt->nameaddr.name.s - hdr->body.s;
			if (!del_lump(_m, rem_off - _m->buf, rem_len, 0)) {
				LOG(L_ERR, "after_strict: Can't remove Route HF\n");
				return RR_ERROR;
			}
		}


		res = find_rem_target(_m, &hdr, &rt, &prev);
		if (res < 0) {
			LOG(L_ERR, "after_strict: Error while looking for last Route URI\n");
			return RR_ERROR;
		} else if (res > 0) {
			     /* No remote target is an error */
			return RR_ERROR;
		}

		uri = &rt->nameaddr.uri;
		if (rewrite_uri(_m, uri) < 0) {
			LOG(L_ERR, "after_strict: Can't rewrite R-URI\n");
			return RR_ERROR;
		}

		     /* The first character if uri will be either '<' when it is the only URI in a
		      * Route header field or ',' if there is more than one URI in the header field
		      */
		DBG("after_strict: The last route URI: '%.*s'\n",
		    rt->nameaddr.uri.len, ZSW(rt->nameaddr.uri.s));

		if (prev) {
			rem_off = prev->nameaddr.name.s + prev->len;
			rem_len = rt->nameaddr.name.s + rt->len - rem_off;
		} else {
			rem_off = hdr->name.s;
			rem_len = hdr->len;
		}
		if (!del_lump(_m, rem_off - _m->buf, rem_len, 0)) {
			LOG(L_ERR, "after_strict: Can't remove Route HF\n");
			return RR_ERROR;
		}
	}

	return RR_DRIVEN;
}
Beispiel #16
0
int enum_query_2(struct sip_msg* _msg, char* _suffix, char* _service)
{
	char *user_s;
	int user_len, i, j, first;
	char name[MAX_DOMAIN_SIZE];
	char uri[MAX_URI_SIZE];
	char new_uri[MAX_URI_SIZE];
	unsigned int priority, curr_prio;
	qvalue_t q;

	struct rdata* head;
	struct rdata* l;
	struct naptr_rdata* naptr;

	str pattern, replacement, result, new_result;

	char string[17];

	str *suffix, *service;

	suffix = (str*)_suffix;
	service = (str*)_service;

	if (parse_sip_msg_uri(_msg) < 0) {
		LOG(L_ERR, "enum_query(): uri parsing failed\n");
		return -1;
	}

	if (is_e164(&(_msg->parsed_uri.user)) == -1) {
		LOG(L_ERR, "enum_query(): uri user is not an E164 number\n");
		return -1;
	}

	user_s = _msg->parsed_uri.user.s;
	user_len = _msg->parsed_uri.user.len;

	memcpy(&(string[0]), user_s, user_len);
	string[user_len] = (char)0;

	j = 0;
	for (i = user_len - 1; i > 0; i--) {
		name[j] = user_s[i];
		name[j + 1] = '.';
		j = j + 2;
	}

	memcpy(name + j, suffix->s, suffix->len + 1);

	head = get_record(name, T_NAPTR);

	if (head == 0) {
		DBG("enum_query(): No NAPTR record found for %s.\n", name);
		return -1;
	}

	naptr_sort(&head);

	q = MAX_Q - 10;
	curr_prio = 0;
	first = 1;

	for (l = head; l; l = l->next) {

		if (l->type != T_NAPTR) continue; /*should never happen*/
		naptr = (struct naptr_rdata*)l->rdata;
		if (naptr == 0) {
			LOG(L_CRIT, "enum_query: BUG: null rdata\n");
			continue;
		}

		DBG("enum_query(): order %u, pref %u, flen %u, flags '%.*s', slen %u, "
		    "services '%.*s', rlen %u, regexp '%.*s'\n", naptr->order, naptr->pref,
		    naptr->flags_len, (int)(naptr->flags_len), ZSW(naptr->flags),
		    naptr->services_len,
		    (int)(naptr->services_len), ZSW(naptr->services), naptr->regexp_len,
		    (int)(naptr->regexp_len), ZSW(naptr->regexp));

		if (sip_match(naptr, service) == 0) continue;

		if (parse_naptr_regexp(&(naptr->regexp[0]), naptr->regexp_len,
				       &pattern, &replacement) < 0) {
			LOG(L_ERR, "enum_query(): parsing of NAPTR regexp failed\n");
			continue;
		}
		result.s = &(uri[0]);
		result.len = MAX_URI_SIZE;
		/* Avoid making copies of pattern and replacement */
		pattern.s[pattern.len] = (char)0;
		replacement.s[replacement.len] = (char)0;
		if (reg_replace(pattern.s, replacement.s, &(string[0]),
				&result) < 0) {
			pattern.s[pattern.len] = '!';
			replacement.s[replacement.len] = '!';
			LOG(L_ERR, "enum_query(): regexp replace failed\n");
			continue;
		}
		DBG("enum_query(): resulted in replacement: '%.*s'\n",
		    result.len, ZSW(result.s));
		pattern.s[pattern.len] = '!';
		replacement.s[replacement.len] = '!';
		
		if (param.len > 0) {
			if (result.len + param.len > MAX_URI_SIZE - 1) {
				LOG(L_ERR, "ERROR: enum_query(): URI is too long\n");
				continue;
			}
			new_result.s = &(new_uri[0]);
			new_result.len = MAX_URI_SIZE;
			if (add_uri_param(&result, &param, &new_result) == 0) {
				LOG(L_ERR, "ERROR: enum_query(): Parsing of URI failed\n");
				continue;
			}
			if (new_result.len > 0) {
				result = new_result;
			}
		}

		if (first) {
			if (rewrite_uri(_msg, &result) == -1) {
				goto done;
			}
			set_ruri_q(q);
			first = 0;
			curr_prio = ((naptr->order) << 16) + naptr->pref;
		} else {
			priority = ((naptr->order) << 16) + naptr->pref;
			if (priority > curr_prio) {
				q = q - 10;
				curr_prio = priority;
			}
			if (append_branch(_msg, &result, 0, q, 0, 0) == -1) {
				goto done;
			}
		}
	}

done:
	free_rdata_list(head);
	return first ? -1 : 1;
}
Beispiel #17
0
int sbranch_set_ruri(sip_msg_t *msg)
{
	str sv;
	flag_t old_bflags;
	branch_t *br;
	int ret;

	ret = 0;
	br = &_pv_sbranch;
	if(br->len==0)
		return -1;

	sv.s = br->uri;
	sv.len = br->len;

	if (rewrite_uri(msg, &sv) < 0) {
		LM_ERR("unable to rewrite Request-URI\n");
		ret = -3;
		goto error;
	}

	/* reset next hop address */
	reset_dst_uri(msg);
	if(br->dst_uri_len>0) {
		sv.s = br->dst_uri;
		sv.len = br->dst_uri_len;
		if (set_dst_uri(msg, &sv) < 0) {
			ret = -3;
			goto error;
		}
	}

	reset_path_vector(msg);
	if(br->path_len==0) {
		sv.s = br->path;
		sv.len = br->path_len;
		if(set_path_vector(msg, &sv) < 0) {
			ret = -4;
			goto error;
		}
	}

	reset_instance(msg);
	if (br->instance_len) {
		sv.s = br->instance;
		sv.len = br->instance_len;
	    if (set_instance(msg, &sv) < 0) {
			ret = -5;
			goto error;
	    }
	}

	reset_ruid(msg);
	if (br->ruid_len) {
		sv.s = br->ruid;
		sv.len = br->ruid_len;
	    if (set_ruid(msg, &sv) < 0) {
			ret = -6;
			goto error;
	    }
	}

	reset_ua(msg);
	if (br->location_ua_len) {
		sv.s = br->location_ua;
		sv.len = br->location_ua_len;
	    if (set_ua(msg, &sv) < 0) {
			ret = -7;
			goto error;
	    }
	}

	if (br->force_send_socket)
		set_force_socket(msg, br->force_send_socket);

	msg->reg_id = br->reg_id;
	set_ruri_q(br->q);
	old_bflags = 0;
	getbflagsval(0, &old_bflags);
	setbflagsval(0, old_bflags|br->flags);

	return 0;
error:
	return ret;
}
Beispiel #18
0
/*
 * Adds to request a new destination set that includes all highest
 * priority class contacts in contacts_avp.   Request URI is rewritten with
 * first contact and the remaining contacts (if any) are added as branches.
 * Removes used contacts from contacts_avp.  Returns 1, if contacts_avp
 * was not empty and a destination set was successfully added.  Returns -2,
 * if contacts_avp was empty and thus there was nothing to do.
 * Returns -1 in case of an error. */
int t_next_contacts(struct sip_msg* msg, char* key, char* value)
{
    struct usr_avp *avp, *prev;
    int_str val;
    str uri, dst, path;
    struct socket_info *sock;
    unsigned int flags;
    struct search_state st;

    /* Check if contacts_avp has been defined */
    if (contacts_avp.n == 0) {
		LM_ERR("feature has been disabled - "
			   "to enable define contacts_avp module parameter");
		return -1;
    }

    /* Load Request-URI and branches */

    /* Find first contacts_avp value */
    avp = search_first_avp(contacts_avp_type, contacts_avp, &val, &st);
    if (!avp) {
	LM_DBG("no AVPs - we are done!\n");
	return -2;
    }

    LM_DBG("next contact is <%.*s>\n", STR_FMT(&val.s));

    if (decode_branch_info(val.s.s, &uri, &dst, &path, &sock, &flags)
	== 0) {
	LM_ERR("decoding of branch info <%.*s> failed\n", STR_FMT(&val.s));
	destroy_avp(avp);
	return -1;
    }
    
    /* Rewrite Request-URI */
    rewrite_uri(msg, &uri);
    if (dst.s && dst.len) set_dst_uri(msg, &dst);
    else reset_dst_uri(msg);
    if (path.s && path.len) set_path_vector(msg, &path);
    else reset_path_vector(msg);
    set_force_socket(msg, sock);
    setbflagsval(0, flags);

    if (avp->flags & Q_FLAG) {
	destroy_avp(avp);
	return 1;
    }
		
    /* Append branches until out of branches or Q_FLAG is set */
    prev = avp;
    while ((avp = search_next_avp(&st, &val))) {
	destroy_avp(prev);
	LM_DBG("next contact is <%.*s>\n", STR_FMT(&val.s));
	
	if (decode_branch_info(val.s.s, &uri, &dst, &path, &sock, &flags)
	    == 0) {
	    LM_ERR("decoding of branch info <%.*s> failed\n", STR_FMT(&val.s));
	    destroy_avp(avp);
	    return -1;
	}

	if (append_branch(msg, &uri, &dst, &path, 0, flags, sock) != 1) {
	    LM_ERR("appending branch failed\n");
	    destroy_avp(avp);
	    return -1;
	}

	if (avp->flags & Q_FLAG) {
	    destroy_avp(avp);
	    return 1;
	}
	prev = avp;
    }

    destroy_avp(prev);

    return 1;
}
Beispiel #19
0
/*
 * Lookup contact in the database and rewrite Request-URI,
 * and filter them by aor
 */
int lookup2(struct sip_msg* msg, char* table, char* p2)
{
	urecord_t* r;
	str uid;
	ucontact_t* ptr;
	int res;
	unsigned int nat;
	str new_uri, aor;
	fparam_t* fp;

	nat = 0;
	fp = (fparam_t*)p2;
	
	if (get_str_fparam(&aor, msg, (fparam_t*)p2) != 0) {
	    ERR("Unable to get the AOR value\n");
	    return -1;
	}

	if (get_to_uid(&uid, msg) < 0) return -1;
	get_act_time();

	ul.lock_udomain((udomain_t*)table);
	res = ul.get_urecord((udomain_t*)table, &uid, &r);
	if (res < 0) {
		ERR("Error while querying usrloc\n");
		ul.unlock_udomain((udomain_t*)table);
		return -2;
	}
	
	if (res > 0) {
		DBG("'%.*s' Not found in usrloc\n", uid.len, ZSW(uid.s));
		ul.unlock_udomain((udomain_t*)table);
		return -3;
	}

	ptr = r->contacts;
	while (ptr && (!VALID_CONTACT(ptr, act_time) || !VALID_AOR(ptr, aor)))
	    ptr = ptr->next;
	
	if (ptr) {
	       if (ptr->received.s && ptr->received.len) {
			if (received_to_uri){
				if (add_received(&new_uri, &ptr->c, &ptr->received) < 0) {
					ERR("Out of memory\n");
					return -4;
				}
			/* replace the msg uri */
			if (msg->new_uri.s) pkg_free(msg->new_uri.s);
			msg->new_uri = new_uri;
			msg->parsed_uri_ok = 0;
			ruri_mark_new();
			goto skip_rewrite_uri;
			} else if (set_dst_uri(msg, &ptr->received) < 0) {
			        ul.unlock_udomain((udomain_t*)table);
				return -4;
			}
		}
		
		if (rewrite_uri(msg, &ptr->c) < 0) {
			ERR("Unable to rewrite Request-URI\n");
			ul.unlock_udomain((udomain_t*)table);
			return -4;
		}

		if (ptr->sock) {
			set_force_socket(msg, ptr->sock);
		}

skip_rewrite_uri:
		set_ruri_q(ptr->q);

		nat |= ptr->flags & FL_NAT;
		ptr = ptr->next;
	} else {
		     /* All contacts expired */
		ul.unlock_udomain((udomain_t*)table);
		return -5;
	}
	
	     /* Append branches if enabled */
	if (!append_branches) goto skip;

	while(ptr) {
		if (VALID_CONTACT(ptr, act_time) && VALID_AOR(ptr, aor)) {
			if (received_to_uri && ptr->received.s && ptr->received.len) {
				if (add_received(&new_uri, &ptr->c, &ptr->received) < 0) {
					ERR("branch: out of memory\n");
					goto cont; /* try to continue */
				}
				if (append_branch(msg, &new_uri, 0, 0, ptr->q, 0, 0) == -1) {
					ERR("Error while appending a branch\n");
					pkg_free(new_uri.s);
					if (ser_error == E_TOO_MANY_BRANCHES) goto skip;
					else goto cont; /* try to continue, maybe we have an
							                   oversized contact */
				}
				pkg_free(new_uri.s); /* append_branch doesn't free it */
			} else {
				if (append_branch(msg, &ptr->c, &ptr->received, 0 /* path */,
									 ptr->q, 0, ptr->sock) == -1) {
					ERR("Error while appending a branch\n");
					goto skip; /* Return OK here so the function succeeds */
				}
			}
			
			nat |= ptr->flags & FL_NAT; 
		} 
cont:
		ptr = ptr->next; 
	}
	
 skip:
	ul.unlock_udomain((udomain_t*)table);
	if (nat) setflag(msg, load_nat_flag);
	return 1;
}
Beispiel #20
0
/*! \brief
 * Lookup contacts in the database for all branches, including R-URI
 * \return: -1 : not found
 *          -2 : found but method not allowed (for r-uri)
 *          -3 : error
 */
int lookup_branches(sip_msg_t *msg, udomain_t *d)
{
	unsigned int nr_branches_start;
	unsigned int i;
	int ret;
	int found;
	str new_uri;
	str ruri_b_uri = {0};
	str ruri_b_dst_uri = {0};
	str ruri_b_path = {0};
	int ruri_b_q = Q_UNSPECIFIED;
	struct socket_info *ruri_b_socket = 0;
	flag_t ruri_b_flags = 0;
	str ruri_b_instance = {0};
	unsigned int ruri_b_reg_id = 0;
	str ruri_b_ruid = {0};
	str ruri_b_ua = {0};
	branch_t *crt = NULL;

	ret = 1;
	found  = 0;
	nr_branches_start = nr_branches;
	/* first lookup the r-uri */
	ret = lookup(msg, d, NULL);

	/* if no other branches -- all done */
	if(nr_branches_start==0)
		return ret;

	if(ret>0)
		found = 1;

	/* backup r-uri branch */
	ruri_b_uri = msg->new_uri;
	ruri_b_dst_uri = msg->dst_uri;
	ruri_b_path = msg->path_vec;
	ruri_b_q = get_ruri_q();
	ruri_b_socket = msg->force_send_socket;
	getbflagsval(0, &ruri_b_flags);
	ruri_b_instance = msg->instance;
	ruri_b_reg_id = msg->reg_id;
	ruri_b_ruid = msg->ruid;
	ruri_b_ua = msg->location_ua;
	reset_ruri_branch(msg);
	/* set new uri buf to null, otherwise is freed or overwritten by
	 * rewrite_uri() during branch lookup */
	msg->new_uri.len=0;
	msg->new_uri.s=0;
	msg->parsed_uri_ok=0;

	for(i=0; i<nr_branches_start; i++) {
		crt = get_sip_branch(i);
		/* it has to be a clean branch to do lookup for it */
		if(crt->len <= 0 || crt->dst_uri_len > 0
				|| crt->path_len > 0 || crt->force_send_socket!=NULL
				|| crt->flags !=0)
			continue;
		/* set the new uri from branch and lookup */
		new_uri.s = crt->uri;
		new_uri.len = crt->len;
		if (rewrite_uri(msg, &new_uri) < 0) {
			LM_ERR("unable to rewrite Request-URI for branch %u\n", i);
			ret = -3;
			goto done;
		}
		ret = lookup(msg, d, NULL);
		if(ret>0) {
			/* move r-uri branch attributes to crt branch */
			found = 1;

			if (unlikely(msg->new_uri.len > MAX_URI_SIZE - 1)) {
				LM_ERR("too long uri: %.*s\n", msg->new_uri.len,
						msg->new_uri.s);
				ret = -3;
				goto done;
			}

			/* copy the dst_uri */
			if (msg->dst_uri.len>0 && msg->dst_uri.s!=NULL) {
				if (unlikely(msg->dst_uri.len > MAX_URI_SIZE - 1)) {
					LM_ERR("too long dst_uri: %.*s\n", msg->dst_uri.len,
							msg->dst_uri.s);
					ret = -3;
					goto done;
				}

				memcpy(crt->dst_uri, msg->dst_uri.s, msg->dst_uri.len);
				crt->dst_uri[msg->dst_uri.len] = 0;
				crt->dst_uri_len = msg->dst_uri.len;
			}

			/* copy the path string */
			if (unlikely(msg->path_vec.len>0 && msg->path_vec.s!=NULL)) {
				if (unlikely(msg->path_vec.len > MAX_PATH_SIZE - 1)) {
					LM_ERR("too long path: %.*s\n", msg->path_vec.len,
							msg->path_vec.s);
					ret = -3;
					goto done;
				}
				memcpy(crt->path, msg->path_vec.s, msg->path_vec.len);
				crt->path[msg->path_vec.len] = 0;
				crt->path_len = msg->path_vec.len;
			}

			/* copy the ruri */
			memcpy(crt->uri, msg->new_uri.s, msg->new_uri.len);
			crt->uri[msg->new_uri.len] = 0;
			crt->len = msg->new_uri.len;
			crt->q = get_ruri_q();

			crt->force_send_socket = msg->force_send_socket;
			getbflagsval(0, &crt->flags);
		}
		reset_ruri_branch(msg);
	}

done:
	reset_ruri_branch(msg);
	/* new uri could be set to allocated buffer by branch lookup */
	if(msg->new_uri.s!=NULL)
		pkg_free(msg->new_uri.s);
	msg->new_uri = ruri_b_uri;
	ruri_mark_new();
	msg->parsed_uri_ok = 0;
	msg->dst_uri = ruri_b_dst_uri;
	msg->path_vec = ruri_b_path;
	set_ruri_q(ruri_b_q);
	set_force_socket(msg, ruri_b_socket);
	setbflagsval(0, ruri_b_flags);
	msg->instance = ruri_b_instance;
	msg->reg_id = ruri_b_reg_id;
	msg->ruid = ruri_b_ruid;
	msg->location_ua = ruri_b_ua;

	return (found)?1:ret;
}
Beispiel #21
0
/*
 * Makes enum query on name.  On success, rewrites user part and 
 * replaces Request-URI.
 */
int do_query(struct sip_msg* _msg, char *user, char *name, str *service) {

    char uri[MAX_URI_SIZE];
    char new_uri[MAX_URI_SIZE];
    unsigned int priority, curr_prio, first;
    qvalue_t q;
    struct rdata* head;
    struct rdata* l;
    struct naptr_rdata* naptr;
    str pattern, replacement, result, new_result;

    head = get_record(name, T_NAPTR, RES_ONLY_TYPE);
    
    if (head == 0) {
	LM_DBG("No NAPTR record found for %s.\n", name);
	return -1;
    }
    
    naptr_sort(&head);

    q = MAX_Q - 10;
    curr_prio = 0;
    first = 1;

    for (l = head; l; l = l->next) {

	if (l->type != T_NAPTR) continue; /*should never happen*/
	naptr = (struct naptr_rdata*)l->rdata;
	if (naptr == 0) {
	    LM_ERR("Null rdata in DNS response\n");
	    continue;
	}

	LM_DBG("ENUM query on %s: order %u, pref %u, flen %u, flags '%.*s', "
	       "slen %u, services '%.*s', rlen %u, regexp '%.*s'\n",
	       name, naptr->order, naptr->pref,
	    naptr->flags_len, (int)(naptr->flags_len), ZSW(naptr->flags),
	    naptr->services_len,
	    (int)(naptr->services_len), ZSW(naptr->services), naptr->regexp_len,
	    (int)(naptr->regexp_len), ZSW(naptr->regexp));
	
	if (sip_match(naptr, service) == 0) continue;
	
	if (parse_naptr_regexp(&(naptr->regexp[0]), naptr->regexp_len,
			       &pattern, &replacement) < 0) {
	    LM_ERR("Parsing of NAPTR regexp failed\n");
	    continue;
	}
	result.s = &(uri[0]);
	result.len = MAX_URI_SIZE;
	/* Avoid making copies of pattern and replacement */
	pattern.s[pattern.len] = (char)0;
	replacement.s[replacement.len] = (char)0;
	if (reg_replace(pattern.s, replacement.s, user, &result) < 0) {
	    pattern.s[pattern.len] = '!';
	    replacement.s[replacement.len] = '!';
	    LM_ERR("Regexp replace failed\n");
	    continue;
	}
	LM_DBG("Resulted in replacement: '%.*s'\n", result.len, ZSW(result.s));
	pattern.s[pattern.len] = '!';
	replacement.s[replacement.len] = '!';
	
	if (param.len > 0) {
	    if (result.len + param.len > MAX_URI_SIZE - 1) {
		LM_ERR("URI is too long\n");
		continue;
	    }
	    new_result.s = &(new_uri[0]);
	    new_result.len = MAX_URI_SIZE;
	    if (add_uri_param(&result, &param, &new_result) == 0) {
		LM_ERR("Parsing of URI <%.*s> failed\n",
		       result.len, result.s);
		continue;
	    }
	    if (new_result.len > 0) {
		result = new_result;
	    }
	}
	
	if (first) {
	    if (rewrite_uri(_msg, &result) == -1) {
		goto done;
	    }
	    set_ruri_q(q);
	    first = 0;
	    curr_prio = ((naptr->order) << 16) + naptr->pref;
	} else {
	    priority = ((naptr->order) << 16) + naptr->pref;
	    if (priority > curr_prio) {
		q = q - 10;
		curr_prio = priority;
	    }
	    if (append_branch(_msg, &result, 0, 0, q, 0, 0, 0, 0, 0, 0) == -1) {
		goto done;
	    }
	}
    }

done:
    free_rdata_list(head);
    return first ? -1 : 1;
}
Beispiel #22
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;
}
Beispiel #23
0
int sd_lookup(struct sip_msg* _msg, char* _index, char* _str2)
{
    int i;
    str user_s, uid, did;
    db_res_t* res = NULL;
    db_rec_t* rec;

    /* init */
    i = (int)(long)_index;

    /* Retrieve the owner of the record */
    if (get_from_uid(&uid, _msg) < 0) {
        LOG(L_ERR, "sd_lookup: Unable to get user identity\n");
        return -1;
    }

    /* Retrieve the called domain id */
    if (get_to_did(&did, _msg) < 0) {
        LOG(L_ERR, "sd_lookup: Destination domain ID not known\n");
        return -1;
    }

    tables[i].lookup_num->match[0].v.lstr = uid;
    tables[i].lookup_num->match[1].v.lstr = did;

    /* Get the called username */
    if (parse_sip_msg_uri(_msg) < 0)
    {
        LOG(L_ERR, "sd_lookup: Error while parsing Request-URI\n");
        goto err_badreq;
    }

    tables[i].lookup_num->match[2].v.lstr = _msg->parsed_uri.user;

    DBG("speeddial: Looking up (uid:%.*s,username:%.*s,did:%.*s)\n",
        uid.len, uid.s,
        _msg->parsed_uri.user.len, _msg->parsed_uri.user.s,
        did.len, did.s);

    if (db_exec(&res, tables[i].lookup_num) < 0) {
        ERR("speeddial: Error while executing database command\n");
        goto err_server;
    }

    if (res == NULL) {
        DBG("speeddial: No SIP URI found for speeddial (num:%.*s, uid:%.*s,"
            " did:%.*s)\n",
            _msg->parsed_uri.user.len,
            _msg->parsed_uri.user.s,
            uid.len, uid.s,
            did.len, did.s);
        return -1;
    }

    user_s.s = useruri_buf + 4;
    rec = db_first(res);
    while(rec) {
        if (rec->fld[0].flags & DB_NULL) goto skip;
        strncpy(user_s.s,
                rec->fld[0].v.lstr.s,
                rec->fld[0].v.lstr.len);
        user_s.len = rec->fld[0].v.lstr.len;
        user_s.s[user_s.len] = '\0';
        goto out;

skip:
        rec = db_next(res);
    }

    if (rec == NULL) {
        DBG("speeddial: No usable SIP URI found for (num:%.*s, uid:%.*s,"
            " did:%.*s)\n",
            _msg->parsed_uri.user.len,
            _msg->parsed_uri.user.s,
            uid.len, uid.s,
            did.len, did.s);
        db_res_free(res);
        return -1;
    }

out:
    /* check 'sip:' */
    if(user_s.len<4 || strncmp(user_s.s, "sip:", 4)) {
        memcpy(useruri_buf, "sip:", 4);
        user_s.s -= 4;
        user_s.len += 4;
    }

    db_res_free(res);

    /* set the URI */
    DBG("sd_lookup: URI of sd from R-URI [%s]\n", user_s.s);
    if(rewrite_uri(_msg, &user_s)<0)
    {
        LOG(L_ERR, "sd_lookup: Cannot replace the R-URI\n");
        goto err_server;
    }

    return 1;

err_server:
    if (slb.zreply(_msg, 500, "Server Internal Error") == -1)
    {
        LOG(L_ERR, "sd_lookup: Error while sending reply\n");
    }
    return 0;
err_badreq:
    if (slb.zreply(_msg, 400, "Bad Request") == -1)
    {
        LOG(L_ERR, "sd_lookup: Error while sending reply\n");
    }
    return 0;
}
Beispiel #24
0
/*
 * Lookup contact in the database and rewrite Request-URI
 */
int lookup(struct sip_msg* _m, char* _t, char* _s)
{
	urecord_t* r;
	str aor, uri;
	ucontact_t* ptr;
	int res;
	int bflags;

	if (_m->new_uri.s) uri = _m->new_uri;
	else uri = _m->first_line.u.request.uri;
	
	if (extract_aor(&uri, &aor) < 0) {
		LOG(L_ERR, "lookup(): Error while extracting address of record\n");
		return -1;
	}
	
	get_act_time();

	ul.lock_udomain((udomain_t*)_t);
	res = ul.get_urecord((udomain_t*)_t, &aor, &r);
	if (res < 0) {
		LOG(L_ERR, "lookup(): Error while querying usrloc\n");
		ul.unlock_udomain((udomain_t*)_t);
		return -2;
	}
	
	if (res > 0) {
		DBG("lookup(): '%.*s' Not found in usrloc\n", aor.len, ZSW(aor.s));
		ul.unlock_udomain((udomain_t*)_t);
		return -3;
	}

	ptr = r->contacts;
	while ((ptr) && !VALID_CONTACT(ptr, act_time))
		ptr = ptr->next;
	
	if (ptr) {
		if (rewrite_uri(_m, &ptr->c) < 0) {
			LOG(L_ERR, "lookup(): Unable to rewrite Request-URI\n");
			ul.unlock_udomain((udomain_t*)_t);
			return -4;
		}

		if (ptr->received.s && ptr->received.len) {
			if (set_dst_uri(_m, &ptr->received) < 0) {
				ul.unlock_udomain((udomain_t*)_t);
				return -4;
			}
		}

		set_ruri_q(ptr->q);

		/* for RURI branch, the nat flag goes into msg */
		if ( ptr->flags&FL_NAT )
			_m->flags |= nat_flag;

		if (ptr->sock)
			_m->force_send_socket = ptr->sock;

		ptr = ptr->next;
	} else {
		/* All contacts expired */
		ul.unlock_udomain((udomain_t*)_t);
		return -5;
	}

	/* Append branches if enabled */
	if (!append_branches) goto skip;

	for( ; ptr ; ptr = ptr->next ) {
		if (VALID_CONTACT(ptr, act_time)) {
			/* for additional branches, the nat flag goes into dset */
			bflags = (use_branch_flags && (ptr->flags & FL_NAT))?nat_flag:0;
			if (append_branch(_m, &ptr->c, &ptr->received, ptr->q,
			bflags, ptr->sock) == -1) {
				LOG(L_ERR, "lookup(): Error while appending a branch\n");
				/* Return 1 here so the function succeeds even if
				 * appending of a branch failed */
				/* Also give a chance to the next branches*/
				continue;
			}
			if (!use_branch_flags && (ptr->flags & FL_NAT))
				_m->flags |= nat_flag;
		}
	}

skip:
	ul.unlock_udomain((udomain_t*)_t);
	return 1;
}
Beispiel #25
0
int I_scscf_select(struct sip_msg* msg, char* str1, char* str2)
{
	str call_id,scscf_name={0,0};
	struct sip_msg *req;
	int result;
	str hdr={0,0};

	//print_scscf_list(L_ERR);
		
	call_id = cscf_get_call_id(msg,0);
	LOG(L_DBG,"DBG:"M_NAME":I_scscf_select(): <%.*s>\n",call_id.len,call_id.s);
	if (!call_id.len)
		return CSCF_RETURN_FALSE;
	
	scscf_name = take_scscf_entry(call_id);
	if (!scscf_name.len){
		I_scscf_drop(msg,str1,str2);
		cscf_reply_transactional(msg,600,MSG_600_FORWARDING_FAILED);			
		return CSCF_RETURN_BREAK;
	}
	
	if (msg->first_line.u.request.method.len==8 &&
		strncasecmp(msg->first_line.u.request.method.s,"REGISTER",8)==0) {
		/* REGISTER fwding */			
		if (str1&&str1[0]=='0'){
			/* first time */	
			//LOG(L_CRIT,"rewrite uri\n");
			if (rewrite_uri(msg, &(scscf_name)) < 0) {
				LOG(L_ERR,"ERR:"M_NAME":I_UAR_forward: Unable to Rewrite URI\n");
				result = CSCF_RETURN_FALSE;
			}else
				result = CSCF_RETURN_TRUE;
		}else{
			/* subsequent */
			//LOG(L_CRIT,"append branch\n");
			req = msg;//cscf_get_request_from_reply(msg);
			append_branch(req,scscf_name.s,scscf_name.len,0,0,0,0);
			result = CSCF_RETURN_TRUE;
		}
	}else{
		/* Another request */
		result = CSCF_RETURN_TRUE;
		
		hdr.len = route_hdr_s.len+scscf_name.len+route_hdr_e.len;
		hdr.s = pkg_malloc(hdr.len);
		if (!hdr.s){
			LOG(L_ERR,"ERR:"M_NAME":Mw_REQUEST_forward: Error allocating %d bytes\n",
				hdr.len);
			result = CSCF_RETURN_TRUE;
		}
		hdr.len=0;
		STR_APPEND(hdr,route_hdr_s);
		STR_APPEND(hdr,scscf_name);
		STR_APPEND(hdr,route_hdr_e);
	
		if (!cscf_add_header_first(msg,&hdr,HDR_ROUTE_T)){
			pkg_free(hdr.s);
			result = CSCF_RETURN_TRUE;
		}
		
		if (msg->dst_uri.s) pkg_free(msg->dst_uri.s);	
		STR_PKG_DUP(msg->dst_uri,scscf_name,"pkg");
	}

	if (scscf_name.s) shm_free(scscf_name.s);
	return result;
out_of_memory:	
	if (scscf_name.s) shm_free(scscf_name.s);
	return CSCF_RETURN_ERROR;
}
Beispiel #26
0
int tps_request_received(sip_msg_t *msg, int dialog)
{
	tps_data_t mtsd;
	tps_data_t stsd;
	str lkey;
	str ftag;
	str nuri;
	uint32_t direction = TPS_DIR_DOWNSTREAM;
	int ret;

	LM_DBG("handling incoming request\n");

	if(dialog==0) {
		/* nothing to do for initial request */
		return 0;
	}

	memset(&mtsd, 0, sizeof(tps_data_t));
	memset(&stsd, 0, sizeof(tps_data_t));

	if(tps_pack_message(msg, &mtsd)<0) {
		LM_ERR("failed to extract and pack the headers\n");
		return -1;
	}

	ret = tps_dlg_message_update(msg, &mtsd);
	if(ret<0) {
		LM_ERR("failed to update on dlg message\n");
		return -1;
	}

	lkey = msg->callid->body;

	tps_storage_lock_get(&lkey);

	if(tps_storage_load_dialog(msg, &mtsd, &stsd)<0) {
		goto error;
	}

	/* detect direction - get from-tag */
	if(parse_from_header(msg)<0 || msg->from==NULL) {
		LM_ERR("failed getting 'from' header!\n");
		goto error;
	}
	ftag = get_from(msg)->tag_value;

	if(stsd.a_tag.len!=ftag.len) {
		direction = TPS_DIR_UPSTREAM;
	} else {
		if(memcmp(stsd.a_tag.s, ftag.s, ftag.len)==0) {
			direction = TPS_DIR_DOWNSTREAM;
		} else {
			direction = TPS_DIR_UPSTREAM;
		}
	}
	mtsd.direction = direction;

	tps_storage_lock_release(&lkey);

	if(direction == TPS_DIR_UPSTREAM) {
		nuri = stsd.a_contact;
	} else {
		nuri = stsd.b_contact;
	}
	if(nuri.len>0) {
		if(rewrite_uri(msg, &nuri)<0) {
			LM_ERR("failed to update r-uri\n");
			return -1;
		}
	}

	if(tps_reappend_route(msg, &stsd, &stsd.s_rr,
				(direction==TPS_DIR_UPSTREAM)?0:1)<0) {
		LM_ERR("failed to reappend s-route\n");
		return -1;
	}
	if(direction == TPS_DIR_UPSTREAM) {
		if(tps_reappend_route(msg, &stsd, &stsd.a_rr, 0)<0) {
			LM_ERR("failed to reappend a-route\n");
			return -1;
		}
	} else {
		if(tps_reappend_route(msg, &stsd, &stsd.b_rr, 0)<0) {
			LM_ERR("failed to reappend b-route\n");
			return -1;
		}
	}
	if(dialog!=0) {
		tps_append_xuuid(msg, &stsd.a_uuid);
	}
	return 0;

error:
	tps_storage_lock_release(&lkey);
	return -1;
}
Beispiel #27
0
/*!
 * \brief Previous hop was a strict router, handle this case
 * \param _m SIP message
 * \return -1 on error, 1 on success
 */
static inline int after_strict(struct sip_msg* _m)
{
    int res, rem_len;
    struct hdr_field* hdr;
    struct sip_uri puri;
    rr_t* rt, *prev;
    char* rem_off;
    str uri;
    struct socket_info *si;

    hdr = _m->route;
    rt = (rr_t*)hdr->parsed;
    uri = rt->nameaddr.uri;

    /* reset rr handling static vars for safety in error case */
    routed_msg_id = 0;
    routed_params.s = NULL;
    routed_params.len = 0;

    if (parse_uri(uri.s, uri.len, &puri) < 0) {
        LM_ERR("failed to parse the first route URI\n");
        return RR_ERROR;
    }

    if ( enable_double_rr && is_2rr(&puri.params) && is_myself(&puri)) {
        /* double route may occure due different IP and port, so force as
         * send interface the one advertise in second Route */
        si = grep_sock_info( &puri.host, puri.port_no, puri.proto);
        if (si) {
            set_force_socket(_m, si);
        } else {
            if (enable_socket_mismatch_warning)
                LM_WARN("no socket found for match second RR\n");
        }

        if (!rt->next) {
            /* No next route in the same header, remove the whole header
             * field immediately
             */
            if (!del_lump(_m, hdr->name.s - _m->buf, hdr->len, 0)) {
                LM_ERR("failed to remove Route HF\n");
                return RR_ERROR;
            }
            res = find_next_route(_m, &hdr);
            if (res < 0) {
                LM_ERR("searching next route failed\n");
                return RR_ERROR;
            }
            if (res > 0) { /* No next route found */
                LM_DBG("after_strict: No next URI found\n");
                return NOT_RR_DRIVEN;
            }
            rt = (rr_t*)hdr->parsed;
        } else rt = rt->next;

        /* parse the new found uri */
        uri = rt->nameaddr.uri;
        if (parse_uri(uri.s, uri.len, &puri) < 0) {
            LM_ERR("failed to parse URI\n");
            return RR_ERROR;
        }
    }

    /* set the hooks for the param
     * important note: RURI is already parsed by the above function, so
     * we just used it without any checking */
    routed_msg_id = _m->id;
    routed_params = _m->parsed_uri.params;

    if (is_strict(&puri.params)) {
        LM_DBG("Next hop: '%.*s' is strict router\n", uri.len, ZSW(uri.s));
        /* Previous hop was a strict router and the next hop is strict
         * router too. There is no need to save R-URI again because it
         * is saved already. In fact, in this case we will behave exactly
         * like a strict router. */

        /* Note: when there is only one Route URI left (endpoint), it will
         * always be a strict router because endpoints don't use ;lr parameter
         * In this case we will simply put the URI in R-URI and forward it,
         * which will work perfectly */
        if(get_maddr_uri(&uri, &puri)!=0) {
            LM_ERR("failed to check maddr\n");
            return RR_ERROR;
        }
        if (rewrite_uri(_m, &uri) < 0) {
            LM_ERR("failed to rewrite request URI\n");
            return RR_ERROR;
        }

        if (rt->next) {
            rem_off = hdr->body.s;
            rem_len = rt->next->nameaddr.name.s - hdr->body.s;
        } else {
            rem_off = hdr->name.s;
            rem_len = hdr->len;
        }
        if (!del_lump(_m, rem_off - _m->buf, rem_len, 0)) {
            LM_ERR("failed to remove Route HF\n");
            return RR_ERROR;
        }
    } else {
        LM_DBG("Next hop: '%.*s' is loose router\n",
               uri.len, ZSW(uri.s));

        if(get_maddr_uri(&uri, &puri)!=0) {
            LM_ERR("failed to check maddr\n");
            return RR_ERROR;
        }
        if (set_dst_uri(_m, &uri) < 0) {
            LM_ERR("failed to set dst_uri\n");
            return RR_ERROR;
        }

        /* Next hop is a loose router - Which means that is is not endpoint yet
         * In This case we have to recover from previous strict routing, that
         * means we have to find the last Route URI and put in in R-URI and
         * remove the last Route URI. */
        if (rt != hdr->parsed) {
            /* There is a previous route uri which was 2nd uri of mine
             * and must be removed here */
            rem_off = hdr->body.s;
            rem_len = rt->nameaddr.name.s - hdr->body.s;
            if (!del_lump(_m, rem_off - _m->buf, rem_len, 0)) {
                LM_ERR("failed to remove Route HF\n");
                return RR_ERROR;
            }
        }


        res = find_rem_target(_m, &hdr, &rt, &prev);
        if (res < 0) {
            LM_ERR("searching for last Route URI failed\n");
            return RR_ERROR;
        } else if (res > 0) {
            /* No remote target is an error */
            return RR_ERROR;
        }

        uri = rt->nameaddr.uri;
        if(get_maddr_uri(&uri, 0)!=0) {
            LM_ERR("checking maddr failed\n");
            return RR_ERROR;
        }
        if (rewrite_uri(_m, &uri) < 0) {
            LM_ERR("failed to rewrite R-URI\n");
            return RR_ERROR;
        }

        /* The first character if uri will be either '<' when it is the
         * only URI in a Route header field or ',' if there is more than
         * one URI in the header field */
        LM_DBG("The last route URI: '%.*s'\n", rt->nameaddr.uri.len,
               ZSW(rt->nameaddr.uri.s));

        if (prev) {
            rem_off = prev->nameaddr.name.s + prev->len;
            rem_len = rt->nameaddr.name.s + rt->len - rem_off;
        } else {
            rem_off = hdr->name.s;
            rem_len = hdr->len;
        }
        if (!del_lump(_m, rem_off - _m->buf, rem_len, 0)) {
            LM_ERR("failed to remove Route HF\n");
            return RR_ERROR;
        }
    }

    /* run RR callbacks only if we have Route URI parameters */
    if(routed_params.len > 0)
        run_rr_callbacks( _m, &routed_params );

    return RR_DRIVEN;
}
Beispiel #28
0
/*
 * Adds a new parameter to Request URI
 */
int add_uri_param(struct sip_msg* _msg, char* _param, char* _s2)
{
	str *param, *cur_uri, new_uri;
	struct sip_uri *parsed_uri;
	char *at;

	param = (str*)_param;

	if (param->len == 0) {
		return 1;
	}

	if (parse_sip_msg_uri(_msg) < 0) {
	        LM_ERR("ruri parsing failed\n");
	        return -1;
	}

	parsed_uri = &(_msg->parsed_uri);

	/* if current ruri has no headers, pad param at the end */
	if (parsed_uri->headers.len == 0) {
		cur_uri =  GET_RURI(_msg);
		new_uri.len = cur_uri->len + param->len + 1;
		if (new_uri.len > MAX_URI_SIZE) {
			LM_ERR("new ruri too long\n");
			return -1;
		}
		new_uri.s = pkg_malloc(new_uri.len);
		if (new_uri.s == 0) {
			LM_ERR("add_uri_param(): Memory allocation failure\n");
			return -1;
		}
		memcpy(new_uri.s, cur_uri->s, cur_uri->len);
		*(new_uri.s + cur_uri->len) = ';';
		memcpy(new_uri.s + cur_uri->len + 1, param->s, param->len);
		if (rewrite_uri(_msg, &new_uri ) == 1) {
			goto ok;
		} else {
			goto nok;
		}
	}

	/* otherwise take the long path */
	new_uri.len = 4 +
		(parsed_uri->user.len ? parsed_uri->user.len + 1 : 0) +
		(parsed_uri->passwd.len ? parsed_uri->passwd.len + 1 : 0) +
		parsed_uri->host.len +
		(parsed_uri->port.len ? parsed_uri->port.len + 1 : 0) +
		parsed_uri->params.len + param->len + 1 +
		parsed_uri->headers.len + 1;
	if (new_uri.len > MAX_URI_SIZE) {
	        LM_ERR("new ruri too long\n");
		return -1;
	}

	new_uri.s = pkg_malloc(new_uri.len);
	if (new_uri.s == 0) {
		LM_ERR("no more pkg memory\n");
		return -1;
	}

	at = new_uri.s;
	memcpy(at, "sip:", 4);
	at = at + 4;
	if (parsed_uri->user.len) {
		memcpy(at, parsed_uri->user.s, parsed_uri->user.len);
		if (parsed_uri->passwd.len) {
			*at = ':';
			at = at + 1;
			memcpy(at, parsed_uri->passwd.s, parsed_uri->passwd.len);
			at = at + parsed_uri->passwd.len;
		};
		*at = '@';
		at = at + 1;
	}
	memcpy(at, parsed_uri->host.s, parsed_uri->host.len);
	at = at + parsed_uri->host.len;
	if (parsed_uri->port.len) {
		*at = ':';
		at = at + 1;
		memcpy(at, parsed_uri->port.s, parsed_uri->port.len);
		at = at + parsed_uri->port.len;
	}
	memcpy(at, parsed_uri->params.s, parsed_uri->params.len);
	at = at + parsed_uri->params.len;
	*at = ';';
	at = at + 1;
	memcpy(at, param->s, param->len);
	at = at + param->len;
	*at = '?';
	at = at + 1;
	memcpy(at, parsed_uri->headers.s, parsed_uri->headers.len);

	if (rewrite_uri(_msg, &new_uri) == 1) {
		goto ok;
	}

nok:
	pkg_free(new_uri.s);
	return -1;

ok:
	pkg_free(new_uri.s);
	return 1;
}