Beispiel #1
0
/*
 * Rewrite Request-URI
 */
int rewrite_uri(struct sip_msg* _m, str* _s)
{
        char* buf;

        buf = (char*)pkg_malloc(_s->len + 1);
        if (!buf) {
                LOG(L_ERR, "ERROR: rewrite_uri: No memory left\n");
                return -1;
        }

        memcpy(buf, _s->s, _s->len);
        buf[_s->len] = '\0';

        _m->parsed_uri_ok = 0;
        if (_m->new_uri.s) {
                pkg_free(_m->new_uri.s);
        }

        _m->new_uri.s = buf;
        _m->new_uri.len = _s->len;
        /* mark ruri as new and available for forking */
        ruri_mark_new();

        return 1;
}
Beispiel #2
0
static PyObject *msg_set_dst_uri(msgobject *self, PyObject *args)
{
	str ruri;

	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 - set destination is not possible.\n");
		Py_INCREF(Py_None);
		return Py_None;
	}

	if(!PyArg_ParseTuple(args, "s:set_dst_uri", &ruri.s))
		return NULL;

	ruri.len = strlen(ruri.s);

	if (set_dst_uri(self->msg, &ruri) < 0) {
		LM_ERR("Error in set_dst_uri\n");
		PyErr_SetString(PyExc_RuntimeError, "Error in set_dst_uri\n");
	}
	/* dst_uri changes, so it makes sense to re-use the current uri for
	 * forking */
	ruri_mark_new(); /* re-use uri for serial forking */

	Py_INCREF(Py_None);
	return Py_None;
}
Beispiel #3
0
static inline int apply_urihdr_changes( struct sip_msg *req,
													str *uri, str *hdr)
{
	struct lump* anchor;

	/* add the uri - move it to branch directly FIXME (bogdan)*/
	if (req->new_uri.s)
	{
		pkg_free(req->new_uri.s);
		req->new_uri.len=0;
	}
	req->parsed_uri_ok=0;
	req->new_uri.s = (char*)pkg_malloc(uri->len+1);
	if (req->new_uri.s==0)
	{
		LM_ERR("no more pkg\n");
		goto error;
	}
	memcpy( req->new_uri.s, uri->s, uri->len);
	req->new_uri.s[uri->len]=0;
	req->new_uri.len=uri->len;
	ruri_mark_new();

	/* add the header */
	if (parse_headers(req, HDR_EOH_F, 0) == -1)
	{
		LM_ERR("failed to parse message\n");
		goto error;
	}

	anchor = anchor_lump(req, req->unparsed - req->buf, 0, 0);
	if (anchor==0)
	{
		LM_ERR("failed to get anchor\n");
		goto error;
	}

	if (insert_new_lump_before(anchor, hdr->s, hdr->len, 0) == 0)
	{
		LM_ERR("faield to insert lump\n");
		goto error;
	}

	return 0;
error:
	pkg_free( hdr->s );
	return -1;
}
Beispiel #4
0
int w_setdsturi(struct sip_msg *msg, char *uri, str *s2)
{
	str s;

	/* todo: fixup */
	s.s = uri;
	s.len = strlen(uri);

	if(set_dst_uri(msg, &s)!=0)
		return -1;
	/* dst_uri changes, so it makes sense to re-use the current uri for
		forking */
	ruri_mark_new(); /* re-use uri for serial forking */
	return 1;

}
Beispiel #5
0
/* from dispatcher */
static int set_new_uri_with_user(struct sip_msg *msg, str *uri, str *user)
{
	struct sip_uri dst;
	int start_len, stop_len;
	
	if (parse_uri(uri->s, uri->len, &dst) < 0) {
		ERR("can't parse destination URI\n");
		return -1;
	}
	if ((!dst.host.s) || (dst.host.len <= 0)) {
		ERR("destination URI host not set\n");
		return -1;
	}
	if (dst.user.s && (dst.user.len > 0)) {
		DBG("user already exists\n");
		/* don't replace the user */
		return set_new_uri_simple(msg, uri);
	}
	
	if (msg->new_uri.s)
	{
		pkg_free(msg->new_uri.s);
		msg->new_uri.len=0;
	}
	
	start_len = dst.host.s - uri->s;
	stop_len = uri->len - start_len;
	
	msg->parsed_uri_ok=0;
	msg->new_uri.s = (char*)pkg_malloc(uri->len+1+user->len+1);
	if (msg->new_uri.s==0)
	{
		ERR("no more pkg memory\n");
		return -1;
	}
	memcpy(msg->new_uri.s, uri->s, start_len);
	memcpy(msg->new_uri.s + start_len, user->s, user->len);
	*(msg->new_uri.s + start_len + user->len) = '@';
	memcpy(msg->new_uri.s + start_len + user->len + 1, dst.host.s, stop_len);
	
	msg->new_uri.len=uri->len + user->len + 1;
	msg->new_uri.s[msg->new_uri.len]=0;
	ruri_mark_new();
	
	return 0;
}
Beispiel #6
0
/* from dispatcher */
static int set_new_uri_simple(struct sip_msg *msg, str *uri)
{
	if (msg->new_uri.s)
	{
		pkg_free(msg->new_uri.s);
		msg->new_uri.len=0;
	}

	msg->parsed_uri_ok=0;
	msg->new_uri.s = (char*)pkg_malloc(uri->len+1);
	if (msg->new_uri.s==0)
	{
		ERR("no more pkg memory\n");
		return -1;
	}
	memcpy(msg->new_uri.s, uri->s, uri->len);
	msg->new_uri.s[uri->len]=0;
	msg->new_uri.len=uri->len;
	ruri_mark_new();
	return 0;
}
Beispiel #7
0
int
decode_contact (struct sip_msg *msg,char *unused1,char *unused2)
{

	str* uri;
	str newUri;
	str dst_uri;
	char separator;
	int res;
	

	separator = DEFAULT_SEPARATOR[0];
	if (contact_flds_separator != NULL)
		if (strlen(contact_flds_separator)>=1)
			separator = contact_flds_separator[0];
		
	if ((msg->new_uri.s == NULL) || (msg->new_uri.len == 0)) {
		uri = &msg->first_line.u.request.uri;
	}else{
		uri = &msg->new_uri;
	}
	
	res = decode_uri (uri, separator, &newUri, &dst_uri);
	
	if (res != 0) {
			LOG (L_ERR,"ERROR: decode_contact:Failed decoding contact."
						"Code %d\n", res);
			return res;
	} else {
		/* we do not modify the original first line */
		if (msg->new_uri.s)
			pkg_free(msg->new_uri.s);
		msg->new_uri = newUri;
		msg->parsed_uri_ok=0;
		msg->dst_uri = dst_uri;
		ruri_mark_new();
	}
	return 1;
}
Beispiel #8
0
/*! \brief
 * rr callback
 */
void path_rr_callback(struct sip_msg *_m, str *r_param, void *cb_param)
{
	param_hooks_t hooks;
	param_t *params;
			
	if (parse_params(r_param, CLASS_CONTACT, &hooks, &params) != 0) {
		LM_ERR("failed to parse route parameters\n");
		return;
	}

	if (hooks.contact.received) {
		if (set_dst_uri(_m, &hooks.contact.received->body) != 0) {
			LM_ERR("failed to set dst-uri\n");
			free_params(params);
			return;
		}
		/* dst_uri changed, so it makes sense to re-use the current uri for
			forking */
		ruri_mark_new(); /* re-use uri for serial forking */
	}
	free_params(params);
}
Beispiel #9
0
static int attr_destination(struct sip_msg* msg, char* p1, char* p2)
{
    avp_t* avp;
    avp_value_t val;
    
    if ((avp = search_avp(((fparam_t*)p1)->v.avp, &val, NULL))) {
	if (avp->flags & AVP_VAL_STR) {
	    if (set_destination(msg, &val.s)) {
		LOG(L_ERR, "ERROR: avp_destination: Can't set dst uri\n");
		return -1;
	    };
		/* dst_uri changed, so it makes sense to re-use the current uri for
			forking */
		ruri_mark_new(); /* re-use uri for serial forking */
	    return 1;
	} else {
	    ERR("avp_destination:AVP has numeric value\n");
	    return -1;
	}
    }
    return -1;
}
Beispiel #10
0
/*!
 * \brief Perform outbound processing - force local socket and set destination URI
 * \param _m SIP message
 * \param flow_token string containing the flow-token extracted from the Route: header
 * \param dst_uri string to write the destination URI to (extracted from flow-token)
 * \return -1 on error, 0 when outbound not in use, 1 when outbound in use
 */
static inline int process_outbound(struct sip_msg *_m, str flow_token)
{
    int ret;
    struct receive_info *rcv = NULL;
    struct socket_info *si;
    str dst_uri;

    if (!rr_obb.decode_flow_token)
        return 0;

    ret = rr_obb.decode_flow_token(_m, &rcv, flow_token);

    if (ret == -2) {
        LM_DBG("no flow token found - outbound not in use\n");
        return 0;
    } else if (ret == -1) {
        LM_INFO("failed to decode flow token\n");
        return -1;
    } else if (!ip_addr_cmp(&rcv->src_ip, &_m->rcv.src_ip)
               || rcv->src_port != _m->rcv.src_port) {
        LM_DBG("\"incoming\" request found. Using flow-token for"
               "routing\n");

        /* First, force the local socket */
        si = find_si(&rcv->dst_ip, rcv->dst_port, rcv->proto);
        if (si)
            set_force_socket(_m, si);
        else {
            LM_INFO("cannot find socket from flow-token\n");
            return -1;
        }

        /* Second, override the destination URI */
        dst_uri.s = uri_buf;
        dst_uri.len = 0;

        dst_uri.len += snprintf(dst_uri.s + dst_uri.len,
                                MAX_ROUTE_URI_LEN - dst_uri.len,
                                "sip:%s",
                                rcv->src_ip.af == AF_INET6 ? "[" : "");
        dst_uri.len += ip_addr2sbuf(&rcv->src_ip,
                                    dst_uri.s + dst_uri.len,
                                    MAX_ROUTE_URI_LEN - dst_uri.len);
        dst_uri.len += snprintf(dst_uri.s + dst_uri.len,
                                MAX_ROUTE_URI_LEN - dst_uri.len,
                                "%s:%d;transport=%s",
                                rcv->src_ip.af == AF_INET6 ? "]" : "",
                                rcv->src_port,
                                get_proto_name(rcv->proto));

        if (set_dst_uri(_m, &dst_uri) < 0) {
            LM_ERR("failed to set dst_uri\n");
            return -1;
        }
        ruri_mark_new();

        return 1;
    }

    LM_DBG("Not using flow-token for routing\n");
    return 0;
}
Beispiel #11
0
/* forwards the msg to the given location set; if flags has set the
 * CPL_PROXY_DONE, all locations will be added as branches, otherwise, the 
 * first one will set as RURI (this is ha case when this is the first proxy 
 * of the message)
 * The given list of location will be freed, returning 0 instead.
 * Returns:  0 - OK
 *          -1 - error */
int cpl_proxy_to_loc_set( struct sip_msg *msg, struct location **locs,
													unsigned char flag)
{
	struct location *foo;
	struct action act;
	struct run_act_ctx ra_ctx;
	int bflags;

	if (!*locs) {
		LM_ERR("empty loc set!!\n");
		goto error;
	}

	/* if it's the first time when this sip_msg is proxied, use the first addr
	 * in loc_set to rewrite the RURI */
	if (!(flag&CPL_PROXY_DONE)) {
		LM_DBG("rewriting Request-URI with <%s>\n",(*locs)->addr.uri.s);
		/* build a new action for setting the URI */
		memset(&act, '\0', sizeof(act));
		act.type = SET_URI_T;
		act.val[0].type = STRING_ST;
		act.val[0].u.string = (*locs)->addr.uri.s;
		init_run_actions_ctx(&ra_ctx);
		/* push the action */
		if (do_action(&ra_ctx, &act, msg) < 0) {
			LM_ERR("do_action failed\n");
			goto error;
		}
		/* build a new action for setting the DSTURI */
		if((*locs)->addr.received.s && (*locs)->addr.received.len) {
			LM_DBG("rewriting Destination URI "
				"with <%s>\n",(*locs)->addr.received.s);
			if (set_dst_uri(msg, &(*locs)->addr.received) < 0) {
				LM_ERR("Error while setting the dst uri\n");
				goto error;
			}
			/* dst_uri changes, so it makes sense to re-use the current uri for
				forking */
			ruri_mark_new(); /* re-use uri for serial forking */
		}
		/* is the location NATED? */
		if ((*locs)->flags&CPL_LOC_NATED)
			setbflag( 0, cpl_fct.ulb.nat_flag );
		/* free the location and point to the next one */
		foo = (*locs)->next;
		free_location( *locs );
		*locs = foo;
	}

	/* add the rest of the locations as branches */
	while(*locs) {
		bflags = ((*locs)->flags&CPL_LOC_NATED) ? cpl_fct.ulb.nat_flag : 0 ;
		LM_DBG("appending branch <%.*s>, flags %d\n",
			(*locs)->addr.uri.len, (*locs)->addr.uri.s, bflags);
		if(append_branch(msg, &(*locs)->addr.uri,
				 &(*locs)->addr.received, 0,
				 Q_UNSPECIFIED, bflags, 0, 0, 0, 0, 0)==-1){
			LM_ERR("failed when appending branch <%s>\n",
			       (*locs)->addr.uri.s);
			goto error;
		}
		/* free the location and point to the next one */
		foo = (*locs)->next;
		free_location( *locs );
		*locs = foo;
	}

	/* run what proxy route is set */
	if (cpl_env.proxy_route) {
		/* do not alter route type - it might be REQUEST or FAILURE */
		run_top_route( main_rt.rlist[cpl_env.proxy_route], msg, 0);
	}

	/* do t_forward */
	if (cpl_fct.tmb.t_relay(msg, 0, 0)==-1) {
		LM_ERR("t_relay failed !\n");
		goto error;
	}

	return 0;
error:
	return -1;
}
Beispiel #12
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 #13
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 #14
0
/*!
 * \brief Apply DP-DDDS policy to current SIP message
 *
 * Apply DP-DDDS policy to current SIP message. This means
 * build a new destination URI from the policy AVP and export it
 * as AVP. Then in kamailio.cfg this new target AVP can be pushed
 * into the destination URI $duri
 * \param _msg SIP message
 * \param _s1 unused
 * \param _s2 unused
 * \return negative on failure, positive on succes
 */
int dp_apply_policy(struct sip_msg* _msg, char* _s1, char* _s2) {

	str *domain;
	int_str val;
	struct usr_avp *avp;

	char duri[MAX_URI_SIZE];
	str duri_str;
	int len, didsomething;
	char *at; /* pointer to current location inside duri */

	str host;
	int port, proto;
	struct socket_info* si;

	if (!is_route_type(REQUEST_ROUTE)) {
		LM_ERR("unsupported route type\n");
		return -1;
	}

	/*
	 * set the send_socket
	 */

	/* search for send_socket AVP */
	avp = search_first_avp(send_socket_avp_name_str, send_socket_name, &val, 0);
	if (avp) {
		if ( !(avp->flags&AVP_VAL_STR) ||  !val.s.s || !val.s.len) {
			LM_ERR("empty or non-string send_socket_avp, "
					"return with error ...\n");
			return -1;
		}
		LM_DBG("send_socket_avp found = '%.*s'\n", val.s.len, ZSW(val.s.s));
		/* parse phostport - AVP str val is asciiz */
		/* FIXME: This code relies on the fact that the string value of an AVP
		 * is zero terminated, which may or may not be true in the future */
		if (parse_phostport(val.s.s, &(host.s), &(host.len), &port, &proto)) {
			LM_ERR("could not parse send_socket, return with error ...\n");
			return -1;
		}
		si = grep_sock_info( &host, (unsigned short) port, (unsigned short) proto);
		if (si) {
			set_force_socket(_msg, si);
		} else {
			LM_WARN("could not find socket for"
					"send_socket '%.*s'\n", val.s.len, ZSW(val.s.s));
		}
	} else {
		LM_DBG("send_socket_avp not found\n");
	}

	/*
	 * set the destination URI
	 */

	didsomething = 0; /* if no AVP is set, there is no need to set the DURI in the end */
	
	if (parse_sip_msg_uri(_msg) < 0) {
		LM_ERR("failed to parse R-URI\n");
		return -1;
	}

	at = (char *)&(duri[0]);
	len = 0;
	if ( (len + 4) >  MAX_URI_SIZE) {
		LM_ERR("duri buffer to small to add uri schema\n");
		return -1;
	}
	memcpy(at, "sip:", 4); at = at + 4; len = len + 4;

	domain = &(_msg->parsed_uri.host);
	LM_DBG("domain is %.*s.\n", domain->len, ZSW(domain->s));

	/* search for prefix and add it to duri buffer */
	avp = search_first_avp(domain_prefix_avp_name_str, domain_prefix_name, &val, 0);
	if (avp) {
		if ( !(avp->flags&AVP_VAL_STR) ||  !val.s.s || !val.s.len) {
			LM_ERR("empty or non-string domain_prefix_avp, return with error ...\n");
			return -1;
		}
		LM_DBG("domain_prefix_avp found = '%.*s'\n", val.s.len, ZSW(val.s.s));
		if ( (len + val.s.len +1) >  MAX_URI_SIZE) {
			LM_ERR("duri buffer to small to add domain prefix\n");
			return -1;
		}
		memcpy(at, val.s.s, val.s.len); at = at + val.s.len;
		*at = '.'; at = at + 1;	/* add . as delimiter between prefix and domain */
		didsomething = 1;
	} else {
		LM_DBG("domain_prefix_avp not found\n");
	}


	/* add domain to duri buffer */
	avp = search_first_avp(domain_replacement_avp_name_str, domain_replacement_name, &val, 0);
	if (avp) {
		if ( !(avp->flags&AVP_VAL_STR) ||  !val.s.s || !val.s.len) {
			LM_ERR("empty or non-string domain_replacement_avp, return with"
					"error ...\n");
			return -1;
		}
		LM_DBG("domain_replacement_avp found='%.*s'\n",val.s.len, ZSW(val.s.s));
		if ( (len + val.s.len +1) >  MAX_URI_SIZE) {
			LM_ERR("duri buffer to small to add domain replacement\n");
			return -1;
		}
		memcpy(at, val.s.s, val.s.len); at = at + val.s.len;
		didsomething = 1;
	} else {
	    LM_DBG("domain_replacement_avp not found, using original domain '"
				"%.*s'\n",domain->len, domain->s);
	    if ( (len + domain->len) >  MAX_URI_SIZE) {
		LM_ERR("duri buffer to small to add domain\n");
		return -1;
	    }
	    memcpy(at, domain->s, domain->len); at = at + domain->len;
	}
	
	/* search for suffix and add it to duri buffer */
	avp = search_first_avp(domain_suffix_avp_name_str, domain_suffix_name, &val, 0);
	if (avp) {
		if ( !(avp->flags&AVP_VAL_STR) ||  !val.s.s || !val.s.len) {
			LM_ERR("empty or non-string domain_suffix_avp,return with error .."
					"\n");
			return -1;
		}
		LM_DBG("domain_suffix_avp found = '%.*s'\n", val.s.len, ZSW(val.s.s));
		if ( (len + val.s.len + 1) >  MAX_URI_SIZE) {
			LM_ERR("duri buffer to small to add domain suffix\n");
			return -1;
		}
		*at = '.'; at = at + 1;	/* add . as delimiter between domain and suffix */
		memcpy(at, val.s.s, val.s.len); at = at + val.s.len;
		didsomething = 1;
	} else {
		LM_DBG("domain_suffix_avp not found\n");
	}

	/* search for port override and add it to duri buffer */
	avp = search_first_avp(port_override_avp_name_str, port_override_name, &val, 0);
	if (avp) {
		if ( !(avp->flags&AVP_VAL_STR) ||  !val.s.s || !val.s.len) {
			LM_ERR("empty or non-string port_override_avp, return with error ...\n");
			return -1;
		}
		LM_DBG("port_override_avp found = '%.*s'\n", val.s.len, ZSW(val.s.s));
		/* We do not check if the port is valid */
		if ( (len + val.s.len + 1) >  MAX_URI_SIZE) {
			LM_ERR("duri buffer to small to add domain suffix\n");
			return -1;
		}
		*at = ':'; at = at + 1;	/* add : as delimiter between domain and port */
		memcpy(at, val.s.s, val.s.len); at = at + val.s.len;
		didsomething = 1;
	} else {
		LM_DBG("port_override_avp not found, using original port\n");
		if (_msg->parsed_uri.port.len) {
			LM_DBG("port found in RURI, reusing it for DURI\n");
			if ( (len + _msg->parsed_uri.port.len + 1) >  MAX_URI_SIZE) {
				LM_ERR("duri buffer to small to copy port\n");
				return -1;
			}
			*at = ':'; at = at + 1;	
			/* add : as delimiter between domain and port */
			memcpy(at, _msg->parsed_uri.port.s, _msg->parsed_uri.port.len); 
			at = at + _msg->parsed_uri.port.len;
		} else {
			LM_DBG("port not found in RURI, no need to copy it to DURI\n");
		}
	}

	/* search for transport override and add it to duri buffer */
	avp = search_first_avp(transport_override_avp_name_str, transport_override_name, &val, 0);
	if (avp) {
		if ( !(avp->flags&AVP_VAL_STR) ||  !val.s.s || !val.s.len) {
			LM_ERR("empty or non-string transport_override_avp, "
					"return with error ...\n");
			return -1;
		}
		LM_DBG("transport_override_avp found='%.*s'\n",val.s.len, ZSW(val.s.s));

		if ( (len + val.s.len + 11) >  MAX_URI_SIZE) {
			LM_ERR("duri buffer to small to add transport override\n");
			return -1;
		}
		/* add : as transport parameter to duri; NOTE: no checks if transport parameter is valid  */
		memcpy(at, ";transport=", 11); at = at + 11;
		memcpy(at, val.s.s, val.s.len); at = at + val.s.len;
		didsomething = 1;
	} else {
		LM_DBG("transport_override_avp not found, using original transport\n");
		if (_msg->parsed_uri.transport.len) {
			LM_DBG("transport found in RURI, reusing it for DURI\n");
			if ( (len + _msg->parsed_uri.transport.len + 1) >  MAX_URI_SIZE) {
				LM_ERR("duri buffer to small to copy transport\n");
				return -1;
			}
			*at = ';'; at = at + 1; /* add : as delimiter between domain and port */
			memcpy(at, _msg->parsed_uri.transport.s, _msg->parsed_uri.transport.len); at = at + _msg->parsed_uri.transport.len;
		} else {
			LM_DBG("transport not found in RURI, no need to copy it to DURI\n");
		}
	}

	/* write new target DURI into DURI */
	if (didsomething == 0) {
		LM_DBG("no domainpolicy AVP set, no need to push new DURI\n");
		return 2;
	}
	duri_str.s = (char *)&(duri[0]);
	duri_str.len = at - duri_str.s;
	LM_DBG("new DURI is '%.*s'\n",duri_str.len, ZSW(duri_str.s));
	if(set_dst_uri(_msg, &duri_str)<0) {
		LM_ERR("failed to se dst uri\n");
		return -1;
	}
	/* dst_uri changes, so it makes sense to re-use the current uri for
		forking */
	ruri_mark_new(); /* re-use uri for serial forking */

	return 1;
}
Beispiel #15
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 #16
0
/*!
 * \brief Previous hop was a loose router, handle this case
 * \param _m SIP message
 * \param preloaded do we have a preloaded route set
 * \return -1 on failure, 1 on success
 */
static inline int after_loose(struct sip_msg* _m, int preloaded)
{
    struct hdr_field* hdr;
    struct sip_uri puri;
    rr_t* rt;
    int res;
    int status = RR_DRIVEN;
    str uri;
    struct socket_info *si;
    int uri_is_myself, next_is_strict;
    int use_ob = 0;

    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;

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

    next_is_strict = is_strict(&puri.params);
    routed_params = puri.params;
    uri_is_myself = is_myself(&puri);

    /* IF the URI was added by me, remove it */
    if (uri_is_myself>0)
    {
        LM_DBG("Topmost route URI: '%.*s' is me\n",
               uri.len, ZSW(uri.s));
        /* set the hooks for the params */
        routed_msg_id = _m->id;

        if ((use_ob = process_outbound(_m, puri.user)) < 0) {
            LM_INFO("failed to process outbound flow-token\n");
            return FLOW_TOKEN_BROKEN;
        }

        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("failed to find next route\n");
                return RR_ERROR;
            }
            if (res > 0) { /* No next route found */
                LM_DBG("No next URI found\n");
                status = (preloaded ? NOT_RR_DRIVEN : RR_DRIVEN);
                goto done;
            }
            rt = (rr_t*)hdr->parsed;
        } else rt = rt->next;

        if (enable_double_rr && is_2rr(&puri.params)) {
            /* double route may occure due different IP and port, so force as
             * send interface the one advertise in second Route */
            if (parse_uri(rt->nameaddr.uri.s,rt->nameaddr.uri.len,&puri)<0) {
                LM_ERR("failed to parse the double route URI\n");
                return RR_ERROR;
            }

            if (!use_ob) {
                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("failed to find next route\n");
                    return RR_ERROR;
                }
                if (res > 0) { /* No next route found */
                    LM_DBG("no next URI found\n");
                    status = (preloaded ? NOT_RR_DRIVEN : RR_DRIVEN);
                    goto done;
                }
                rt = (rr_t*)hdr->parsed;
            } else rt = rt->next;
        }

        uri = rt->nameaddr.uri;
        if (parse_uri(uri.s, uri.len, &puri) < 0) {
            LM_ERR("failed to parse the first route URI\n");
            return RR_ERROR;
        }
    } else {
#ifdef ENABLE_USER_CHECK
        /* check if it the ignored user */
        if(uri_is_myself < 0)
            return NOT_RR_DRIVEN;
#endif
        LM_DBG("Topmost URI is NOT myself\n");
        routed_params.s = NULL;
        routed_params.len = 0;
    }

    LM_DBG("URI to be processed: '%.*s'\n", uri.len, ZSW(uri.s));
    if (next_is_strict) {
        LM_DBG("Next URI is a strict router\n");
        if (handle_sr(_m, hdr, rt) < 0) {
            LM_ERR("failed to handle strict router\n");
            return RR_ERROR;
        }
    } else {
        /* Next hop is loose router */
        LM_DBG("Next URI is a loose router\n");

        if (!use_ob) {
            if(get_maddr_uri(&uri, &puri)!=0) {
                LM_ERR("checking maddr failed\n");
                return RR_ERROR;
            }

            if (set_dst_uri(_m, &uri) < 0) {
                LM_ERR("failed to set dst_uri\n");
                return RR_ERROR;
            }
            /* dst_uri changed, so it makes sense to re-use the current uri for
            forking */
            ruri_mark_new(); /* re-use uri for serial forking */
        }

        /* There is a previous route uri which was 2nd uri of mine
         * and must be removed here */
        if (rt != hdr->parsed) {
            if (!del_lump(_m, hdr->body.s - _m->buf,
                          rt->nameaddr.name.s - hdr->body.s, 0)) {
                LM_ERR("failed to remove Route HF\n");
                return RR_ERROR;
            }
        }
    }

done:
    if (use_ob == 1)
        status = RR_OB_DRIVEN;

    /* run RR callbacks only if we have Route URI parameters */
    if(routed_params.len > 0)
        run_rr_callbacks( _m, &routed_params );
    return status;
}
Beispiel #17
0
int ds_select_dst_impl(struct sip_msg *msg, char *set_, char *alg_, int set_new)
{
	extern int *ds_activelist;
	extern char ***ds_setp_a, ***ds_setp_b;
	extern int *ds_setlen_a, *ds_setlen_b;

	int set, alg;
	unsigned int hash;

	str uri;

	if(msg==NULL)
    {
        LOG(L_ERR, "DISPATCHER:ds_select_dst: bad parameters\n");
        return -1;
    }

	if ( get_int_fparam(&set, msg, (fparam_t*)set_) < 0 ) {
	  LOG(L_ERR, "DISPATCHER:ds_select_dst: bad set value (%d)\n", set);
	  return -1;
	}

	if ( get_int_fparam(&alg, msg, (fparam_t*)alg_) < 0 ) {
	  LOG(L_ERR, "DISPATCHER:ds_select_dst: bad algorithm (%d)\n", alg);
	  return -1;
	}

    if ((set < 0) || (set >= DS_MAX_SETS)) {
        LOG(L_ERR, "DISPATCHER:ds_select_dst: bad set offset (%d)\n", set);
        return -1;
    }
    if ((alg < 0) || (alg > 4)) {
        LOG(L_ERR, "DISPATCHER:ds_select_dst: invalid algorithm\n");
        return -1;
    }

	if (((*ds_activelist == 0) ?  ds_setlen_a[set] : ds_setlen_b[set]) <= 0) {
        LOG(L_ERR, "DISPATCHER:ds_select_dst: empty destination set\n");
        return -1;
    }
    if (msg->dst_uri.s != NULL || msg->dst_uri.len > 0) {
		if (msg->dst_uri.s)
            pkg_free(msg->dst_uri.s);
        msg->dst_uri.s = NULL;
        msg->dst_uri.len = 0;
    }
    /* get hash */
    hash = 0;
    switch (alg) {
		/* see bottom for case '0' */
        case 1: /* hash from uri */
            if (ds_hash_fromuri(msg, &hash) != 0) {
                if (ds_hash_callid(msg, &hash) != 0) {
                    LOG(L_ERR, "DISPATCHER:ds_select_dst: cannot determine from uri hash\n");
                    return -1;
                }
            }
            break;
        case 2: /* hash to uri */
            if (ds_hash_touri(msg, &hash) != 0) {
                if (ds_hash_callid(msg, &hash) != 0) {
                    LOG(L_ERR, "DISPATCHER:ds_select_dst: cannot determine from uri hash\n");
                    return -1;
                }
            }
            break;
        case 3: /* hash Request uri */
            if (ds_hash_ruri(msg, &hash) != 0) {
                if (ds_hash_callid(msg, &hash) != 0) {
                    LOG(L_ERR, "DISPATCHER:ds_select_dst: cannot determine from uri hash\n");
                    return -1;
                }
            }
            break;
		case 4:	/* Call ID hash, shifted right once to skip low bit
				 * This should allow for even distribution when using
				 * Call ID hash twice (i.e. fe + be)
				 */
            if (ds_hash_callid(msg, &hash) != 0) {
                LOG(L_ERR,
                    "DISPATCHER:ds_select_dst: cannot determine callid hash\n");
                hash = 0; /* bad default, just to be sure */
                return -1;
            }
			hash = hash >> 4; /* should be enough for even more backends */
			break;
        case 0: /* hash call id */ /* fall-through */
        default:
            if (ds_hash_callid(msg, &hash) != 0) {
                LOG(L_ERR,
                    "DISPATCHER:ds_select_dst: cannot determine callid hash\n");
                hash = 0; /* bad default, just to be sure */
                return -1;
            }
			break; /* make gcc happy */
    }

    DBG("DISPATCHER:ds_select_dst: hash: [%u]\n", hash);
    /* node list offset from hash */
    if (*ds_activelist == 0) {
        hash = hash % ds_setlen_a[set];
        uri.s = ds_setp_a[set][hash];
        uri.len = strlen(ds_setp_a[set][hash]);
    } else {
        hash = hash % ds_setlen_b[set];
        uri.s = ds_setp_b[set][hash];
        uri.len = strlen(ds_setp_b[set][hash]);
    }

	if (!set_new) {
		if (set_dst_uri(msg, &uri) < 0) {
            LOG(L_ERR,
				"DISPATCHER:dst_select_dst: Error while setting dst_uri\n");
            return -1;
        }
		/* dst_uri changed, so it makes sense to re-use the current uri for
			forking */
		ruri_mark_new(); /* re-use uri for serial forking */
    	DBG("DISPATCHER:ds_select_dst: selected [%d-%d-%d] <%.*s>\n",
        	alg, set, hash, msg->dst_uri.len, msg->dst_uri.s);
	} else {
		if (set_new_uri(msg, &uri) < 0) {
            LOG(L_ERR,
				"DISPATCHER:dst_select_dst: Error while setting new_uri\n");
            return -1;
        }
    	DBG("DISPATCHER:ds_select_dst: selected [%d-%d-%d] <%.*s>\n",
        	alg, set, hash, msg->new_uri.len, msg->dst_uri.s);
    }

    return 1;
}
Beispiel #18
0
/** Receive message
 *  WARNING: buf must be 0 terminated (buf[len]=0) or some things might
 * break (e.g.: modules/textops)
 */
int receive_msg(char* buf, unsigned int len, struct receive_info* rcv_info)
{
	struct sip_msg* msg;
	struct run_act_ctx ctx;
	struct run_act_ctx *bctx;
	int ret;
#ifdef STATS
	int skipped = 1;
	int stats_on = 1;
#else
	int stats_on = 0;
#endif
	struct timeval tvb, tve;
	struct timezone tz;
	unsigned int diff = 0;
	str inb;
	sr_net_info_t netinfo;
	sr_kemi_eng_t *keng = NULL;

	if(sr_event_enabled(SREV_NET_DATA_RECV)) {
		if(sip_check_fline(buf, len)==0) {
			memset(&netinfo, 0, sizeof(sr_net_info_t));
			netinfo.data.s = buf;
			netinfo.data.len = len;
			netinfo.rcv = rcv_info;
			sr_event_exec(SREV_NET_DATA_RECV, (void*)&netinfo);
		}
	}

	inb.s = buf;
	inb.len = len;
	sr_event_exec(SREV_NET_DATA_IN, (void*)&inb);
	len = inb.len;

	msg=pkg_malloc(sizeof(struct sip_msg));
	if (msg==0) {
		LM_ERR("no mem for sip_msg\n");
		goto error00;
	}
	msg_no++;
	/* number of vias parsed -- good for diagnostic info in replies */
	via_cnt=0;

	memset(msg,0, sizeof(struct sip_msg)); /* init everything to 0 */
	/* fill in msg */
	msg->buf=buf;
	msg->len=len;
	/* zero termination (termination of orig message bellow not that
	 * useful as most of the work is done with scratch-pad; -jiri  */
	/* buf[len]=0; */ /* WARNING: zero term removed! */
	msg->rcv=*rcv_info;
	msg->id=msg_no;
	msg->pid=my_pid();
	msg->set_global_address=default_global_address;
	msg->set_global_port=default_global_port;

	if(likely(sr_msg_time==1)) msg_set_time(msg);

	if (parse_msg(buf,len, msg)!=0){
		if((ret=sr_event_exec(SREV_RCV_NOSIP, (void*)msg))<NONSIP_MSG_DROP) {
			LOG(cfg_get(core, core_cfg, corelog),
				"core parsing of SIP message failed (%s:%d/%d)\n",
				ip_addr2a(&msg->rcv.src_ip), (int)msg->rcv.src_port,
				(int)msg->rcv.proto);
			sr_core_ert_run(msg, SR_CORE_ERT_RECEIVE_PARSE_ERROR);
		}
		else if(ret == NONSIP_MSG_DROP) goto error02;
	}

	parse_headers(msg, HDR_FROM_F|HDR_TO_F|HDR_CALLID_F|HDR_CSEQ_F, 0);
	LM_DBG("--- received sip message - %s - call-id: [%.*s] - cseq: [%.*s]\n",
			(msg->first_line.type==SIP_REQUEST)?"request":"reply",
			(msg->callid && msg->callid->body.s)?msg->callid->body.len:0,
			(msg->callid && msg->callid->body.s)?msg->callid->body.s:"",
			(msg->cseq && msg->cseq->body.s)?msg->cseq->body.len:0,
			(msg->cseq && msg->cseq->body.s)?msg->cseq->body.s:"");

	/* set log prefix */
	log_prefix_set(msg);

	/* ... clear branches from previous message */
	clear_branches();

	if (msg->first_line.type==SIP_REQUEST){
		ruri_mark_new(); /* ruri is usable for forking (not consumed yet) */
		if (!IS_SIP(msg)){
			if ((ret=nonsip_msg_run_hooks(msg))!=NONSIP_MSG_ACCEPT){
				if (unlikely(ret==NONSIP_MSG_ERROR))
					goto error03;
				goto end; /* drop the message */
			}
		}
		/* sanity checks */
		if ((msg->via1==0) || (msg->via1->error!=PARSE_OK)){
			/* no via, send back error ? */
			LM_ERR("no via found in request\n");
			STATS_BAD_MSG();
			goto error02;
		}
		/* check if necessary to add receive?->moved to forward_req */
		/* check for the alias stuff */
#ifdef USE_TCP
		if (msg->via1->alias && cfg_get(tcp, tcp_cfg, accept_aliases) &&
				(((rcv_info->proto==PROTO_TCP) && !tcp_disable)
#ifdef USE_TLS
					|| ((rcv_info->proto==PROTO_TLS) && !tls_disable)
#endif
				)
			){
			if (tcpconn_add_alias(rcv_info->proto_reserved1, msg->via1->port,
									rcv_info->proto)!=0){
				LM_ERR("tcp alias failed\n");
				/* continue */
			}
		}
#endif

	/*	skip: */
		LM_DBG("preparing to run routing scripts...\n");
		if(is_printable(cfg_get(core, core_cfg, latency_cfg_log))
				|| stats_on==1) {
			gettimeofday( & tvb, &tz );
		}
		/* execute pre-script callbacks, if any; -jiri */
		/* if some of the callbacks said not to continue with
		 * script processing, don't do so
		 * if we are here basic sanity checks are already done
		 * (like presence of at least one via), so you can count
		 * on via1 being parsed in a pre-script callback --andrei
		*/
		if (exec_pre_script_cb(msg, REQUEST_CB_TYPE)==0 )
		{
			STATS_REQ_FWD_DROP();
			goto end; /* drop the request */
		}

		set_route_type(REQUEST_ROUTE);
		/* exec the routing script */
		if(unlikely(main_rt.rlist[DEFAULT_RT]==NULL)) {
			keng = sr_kemi_eng_get();
			if(keng==NULL) {
				LM_ERR("no config routing engine registered\n");
				goto error_req;
			}
			if(keng->froute(msg, REQUEST_ROUTE, NULL, NULL)<0) {
				LM_NOTICE("negative return code from engine function\n");
			}
		} else {
			if (run_top_route(main_rt.rlist[DEFAULT_RT], msg, 0)<0){
				LM_WARN("error while trying script\n");
				goto error_req;
			}
		}

		if(is_printable(cfg_get(core, core_cfg, latency_cfg_log))
				|| stats_on==1) {
			gettimeofday( & tve, &tz );
			diff = (tve.tv_sec-tvb.tv_sec)*1000000+(tve.tv_usec-tvb.tv_usec);
			LOG(cfg_get(core, core_cfg, latency_cfg_log),
					"request-route executed in: %d usec\n", diff);
#ifdef STATS
			stats->processed_requests++;
			stats->acc_req_time += diff;
			STATS_RX_REQUEST( msg->first_line.u.request.method_value );
#endif
		}

		/* execute post request-script callbacks */
		exec_post_script_cb(msg, REQUEST_CB_TYPE);
	}else if (msg->first_line.type==SIP_REPLY){
		/* sanity checks */
		if ((msg->via1==0) || (msg->via1->error!=PARSE_OK)){
			/* no via, send back error ? */
			LM_ERR("no via found in reply\n");
			STATS_BAD_RPL();
			goto error02;
		}

		if(is_printable(cfg_get(core, core_cfg, latency_cfg_log))
				|| stats_on==1) {
			gettimeofday( & tvb, &tz );
		}
#ifdef STATS
		STATS_RX_RESPONSE ( msg->first_line.u.reply.statuscode / 100 );
#endif

		/* execute pre-script callbacks, if any; -jiri */
		/* if some of the callbacks said not to continue with
		 * script processing, don't do so
		 * if we are here basic sanity checks are already done
		 * (like presence of at least one via), so you can count
		 * on via1 being parsed in a pre-script callback --andrei
		*/
		if (exec_pre_script_cb(msg, ONREPLY_CB_TYPE)==0 )
		{
			STATS_RPL_FWD_DROP();
			goto end; /* drop the reply */
		}

		/* exec the onreply routing script */
		keng = sr_kemi_eng_get();
		if (onreply_rt.rlist[DEFAULT_RT]!=NULL || keng!=NULL){
			set_route_type(CORE_ONREPLY_ROUTE);
			ret = 1;
			if(unlikely(keng!=NULL)) {
				bctx = sr_kemi_act_ctx_get();
				init_run_actions_ctx(&ctx);
				sr_kemi_act_ctx_set(&ctx);
				ret = keng->froute(msg, CORE_ONREPLY_ROUTE, NULL, NULL);
				sr_kemi_act_ctx_set(bctx);
			} else {
				ret=run_top_route(onreply_rt.rlist[DEFAULT_RT], msg, &ctx);
			}
#ifndef NO_ONREPLY_ROUTE_ERROR
			if (unlikely(ret<0)){
				LM_WARN("error while trying onreply script\n");
				goto error_rpl;
			}else
#endif /* NO_ONREPLY_ROUTE_ERROR */
			if (unlikely(ret==0 || (ctx.run_flags&DROP_R_F))){
				STATS_RPL_FWD_DROP();
				goto skip_send_reply; /* drop the message, no error */
			}
		}
		/* send the msg */
		forward_reply(msg);
	skip_send_reply:
		if(is_printable(cfg_get(core, core_cfg, latency_cfg_log))
				|| stats_on==1) {
			gettimeofday( & tve, &tz );
			diff = (tve.tv_sec-tvb.tv_sec)*1000000+(tve.tv_usec-tvb.tv_usec);
			LOG(cfg_get(core, core_cfg, latency_cfg_log),
					"reply-route executed in: %d usec\n", diff);
#ifdef STATS
			stats->processed_responses++;
			stats->acc_res_time+=diff;
#endif
		}

		/* execute post reply-script callbacks */
		exec_post_script_cb(msg, ONREPLY_CB_TYPE);
	}

end:
#ifdef STATS
	skipped = 0;
#endif
	/* free possible loaded avps -bogdan */
	reset_avps();
#ifdef WITH_XAVP
	xavp_reset_list();
#endif
	LM_DBG("cleaning up\n");
	free_sip_msg(msg);
	pkg_free(msg);
#ifdef STATS
	if (skipped) STATS_RX_DROPS;
#endif
	/* reset log prefix */
	log_prefix_set(NULL);
	return 0;

#ifndef NO_ONREPLY_ROUTE_ERROR
error_rpl:
	/* execute post reply-script callbacks */
	exec_post_script_cb(msg, ONREPLY_CB_TYPE);
	reset_avps();
#ifdef WITH_XAVP
	xavp_reset_list();
#endif
	goto error02;
#endif /* NO_ONREPLY_ROUTE_ERROR */
error_req:
	LM_DBG("error:...\n");
	/* execute post request-script callbacks */
	exec_post_script_cb(msg, REQUEST_CB_TYPE);
error03:
	/* free possible loaded avps -bogdan */
	reset_avps();
#ifdef WITH_XAVP
	xavp_reset_list();
#endif
error02:
	free_sip_msg(msg);
	pkg_free(msg);
error00:
	STATS_RX_DROPS;
	/* reset log prefix */
	log_prefix_set(NULL);
	return -1;
}
Beispiel #19
0
/* WARNING: buf must be 0 terminated (buf[len]=0) or some things might 
 * break (e.g.: modules/textops)
 */
int receive_msg(char* buf, unsigned int len, struct receive_info* rcv_info) 
{
	struct sip_msg* msg;
	struct run_act_ctx ctx;
	int ret;
#ifdef STATS
	int skipped = 1;
	struct timeval tvb, tve;	
	struct timezone tz;
	unsigned int diff;
#endif
	str inb;

	inb.s = buf;
	inb.len = len;
	sr_event_exec(SREV_NET_DATA_IN, (void*)&inb);
	len = inb.len;

	msg=pkg_malloc(sizeof(struct sip_msg));
	if (msg==0) {
		LOG(L_ERR, "ERROR: receive_msg: no mem for sip_msg\n");
		goto error00;
	}
	msg_no++;
	/* number of vias parsed -- good for diagnostic info in replies */
	via_cnt=0;

	memset(msg,0, sizeof(struct sip_msg)); /* init everything to 0 */
	/* fill in msg */
	msg->buf=buf;
	msg->len=len;
	/* zero termination (termination of orig message bellow not that
	   useful as most of the work is done with scratch-pad; -jiri  */
	/* buf[len]=0; */ /* WARNING: zero term removed! */
	msg->rcv=*rcv_info;
	msg->id=msg_no;
	msg->pid=my_pid();
	msg->set_global_address=default_global_address;
	msg->set_global_port=default_global_port;
	
	if(likely(sr_msg_time==1)) msg_set_time(msg);

	if (parse_msg(buf,len, msg)!=0){
		if(sr_event_exec(SREV_RCV_NOSIP, (void*)msg)!=0) {
			LOG(cfg_get(core, core_cfg, corelog),
				"core parsing of SIP message failed (%s:%d/%d)\n",
				ip_addr2a(&msg->rcv.src_ip), (int)msg->rcv.src_port,
				(int)msg->rcv.proto);
			sr_core_ert_run(msg, SR_CORE_ERT_RECEIVE_PARSE_ERROR);
		}
		goto error02;
	}
	DBG("After parse_msg...\n");


	/* ... clear branches from previous message */
	clear_branches();

	if (msg->first_line.type==SIP_REQUEST){
		ruri_mark_new(); /* ruri is usable for forking (not consumed yet) */
		if (!IS_SIP(msg)){
			if ((ret=nonsip_msg_run_hooks(msg))!=NONSIP_MSG_ACCEPT){
				if (unlikely(ret==NONSIP_MSG_ERROR))
					goto error03;
				goto end; /* drop the message */
			}
		}
		/* sanity checks */
		if ((msg->via1==0) || (msg->via1->error!=PARSE_OK)){
			/* no via, send back error ? */
			LOG(L_ERR, "ERROR: receive_msg: no via found in request\n");
			STATS_BAD_MSG();
			goto error02;
		}
		/* check if necessary to add receive?->moved to forward_req */
		/* check for the alias stuff */
#ifdef USE_TCP
		if (msg->via1->alias && cfg_get(tcp, tcp_cfg, accept_aliases) && 
				(((rcv_info->proto==PROTO_TCP) && !tcp_disable)
#ifdef USE_TLS
					|| ((rcv_info->proto==PROTO_TLS) && !tls_disable)
#endif
				)
			){
			if (tcpconn_add_alias(rcv_info->proto_reserved1, msg->via1->port,
									rcv_info->proto)!=0){
				LOG(L_ERR, " ERROR: receive_msg: tcp alias failed\n");
				/* continue */
			}
		}
#endif

	/*	skip: */
		DBG("preparing to run routing scripts...\n");
#ifdef  STATS
		gettimeofday( & tvb, &tz );
#endif
		/* execute pre-script callbacks, if any; -jiri */
		/* if some of the callbacks said not to continue with
		   script processing, don't do so
		   if we are here basic sanity checks are already done
		   (like presence of at least one via), so you can count
		   on via1 being parsed in a pre-script callback --andrei
		*/
		if (exec_pre_script_cb(msg, REQUEST_CB_TYPE)==0 )
		{
			STATS_REQ_FWD_DROP();
			goto end; /* drop the request */
		}

		set_route_type(REQUEST_ROUTE);
		/* exec the routing script */
		if (run_top_route(main_rt.rlist[DEFAULT_RT], msg, 0)<0){
			LOG(L_WARN, "WARNING: receive_msg: "
					"error while trying script\n");
			goto error_req;
		}

#ifdef STATS
		gettimeofday( & tve, &tz );
		diff = (tve.tv_sec-tvb.tv_sec)*1000000+(tve.tv_usec-tvb.tv_usec);
		stats->processed_requests++;
		stats->acc_req_time += diff;
		DBG("successfully ran routing scripts...(%d usec)\n", diff);
		STATS_RX_REQUEST( msg->first_line.u.request.method_value );
#endif

		/* execute post request-script callbacks */
		exec_post_script_cb(msg, REQUEST_CB_TYPE);
	}else if (msg->first_line.type==SIP_REPLY){
		/* sanity checks */
		if ((msg->via1==0) || (msg->via1->error!=PARSE_OK)){
			/* no via, send back error ? */
			LOG(L_ERR, "ERROR: receive_msg: no via found in reply\n");
			STATS_BAD_RPL();
			goto error02;
		}

#ifdef STATS
		gettimeofday( & tvb, &tz );
		STATS_RX_RESPONSE ( msg->first_line.u.reply.statuscode / 100 );
#endif
		
		/* execute pre-script callbacks, if any; -jiri */
		/* if some of the callbacks said not to continue with
		   script processing, don't do so
		   if we are here basic sanity checks are already done
		   (like presence of at least one via), so you can count
		   on via1 being parsed in a pre-script callback --andrei
		*/
		if (exec_pre_script_cb(msg, ONREPLY_CB_TYPE)==0 )
		{
			STATS_RPL_FWD_DROP();
			goto end; /* drop the reply */
		}

		/* exec the onreply routing script */
		if (onreply_rt.rlist[DEFAULT_RT]){
			set_route_type(CORE_ONREPLY_ROUTE);
			ret=run_top_route(onreply_rt.rlist[DEFAULT_RT], msg, &ctx);
#ifndef NO_ONREPLY_ROUTE_ERROR
			if (unlikely(ret<0)){
				LOG(L_WARN, "WARNING: receive_msg: "
						"error while trying onreply script\n");
				goto error_rpl;
			}else
#endif /* NO_ONREPLY_ROUTE_ERROR */
			if (unlikely(ret==0 || (ctx.run_flags&DROP_R_F))){
				STATS_RPL_FWD_DROP();
				goto skip_send_reply; /* drop the message, no error */
			}
		}
		/* send the msg */
		forward_reply(msg);
	skip_send_reply:
#ifdef STATS
		gettimeofday( & tve, &tz );
		diff = (tve.tv_sec-tvb.tv_sec)*1000000+(tve.tv_usec-tvb.tv_usec);
		stats->processed_responses++;
		stats->acc_res_time+=diff;
		DBG("successfully ran reply processing...(%d usec)\n", diff);
#endif

		/* execute post reply-script callbacks */
		exec_post_script_cb(msg, ONREPLY_CB_TYPE);
	}

end:
#ifdef STATS
	skipped = 0;
#endif
	/* free possible loaded avps -bogdan */
	reset_avps();
#ifdef WITH_XAVP
	xavp_reset_list();
#endif
	DBG("receive_msg: cleaning up\n");
	free_sip_msg(msg);
	pkg_free(msg);
#ifdef STATS
	if (skipped) STATS_RX_DROPS;
#endif
	return 0;
#ifndef NO_ONREPLY_ROUTE_ERROR
error_rpl:
	/* execute post reply-script callbacks */
	exec_post_script_cb(msg, ONREPLY_CB_TYPE);
	reset_avps();
#ifdef WITH_XAVP
	xavp_reset_list();
#endif
	goto error02;
#endif /* NO_ONREPLY_ROUTE_ERROR */
error_req:
	DBG("receive_msg: error:...\n");
	/* execute post request-script callbacks */
	exec_post_script_cb(msg, REQUEST_CB_TYPE);
error03:
	/* free possible loaded avps -bogdan */
	reset_avps();
#ifdef WITH_XAVP
	xavp_reset_list();
#endif
error02:
	free_sip_msg(msg);
	pkg_free(msg);
error00:
	STATS_RX_DROPS;
	return -1;
}
Beispiel #20
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;
		}
	}
	/* mark for new branching */
	ruri_mark_new();

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