Esempio n. 1
0
str* get_remote_target(struct sip_msg *msg)
{
	int res;
	struct hdr_field *hdr;
	rr_t *rt,*prev;
	str *uri;
	int routing_type;

	if (msg == NULL) {
		LM_ERR("null sip msg\n");
		return 0;
	}

	routing_type = ctx_routing_get();
	if ((routing_type == ROUTING_LL) || (routing_type == ROUTING_LS))
		return &msg->first_line.u.request.uri;
	else if (routing_type == ROUTING_SL)
		/* set by loose_route(), recovered from previous strict routing */
		return &msg->new_uri;
	else if (routing_type == ROUTING_SS)
	{
		/* searching for last header field */
		res = find_rem_target(msg, &hdr, &rt, &prev);
		if (res < 0)
		{
			LM_ERR("searching for last Route URI failed\n");
			return 0;
		}
		else if (res > 0)
		{
			/* No remote target is an error */
			LM_ERR("couldn't find any remote target !\n");
			return 0;
		}

		uri = &rt->nameaddr.uri;
		if(get_maddr_uri(uri, 0)!=0)
		{
			LM_ERR("failed to check maddr\n");
			return 0;
		}

		return uri;
	}
	else
	{
		LM_ERR("Invalid routing type - %d\n",routing_type);
		return 0;
	}
}
Esempio n. 2
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;
}
Esempio n. 3
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;
}