Example #1
0
/*
 * Do loose routing as defined in RFC3621
 */
int loose_route(struct sip_msg* _m, char* _s1, char* _s2)
{
	struct hdr_field* hdr;
	struct sip_uri puri;
	rr_t* rt;
	int ret;
	str* uri;

	if (find_first_route(_m) != 0) {
		DBG("loose_route: There is no Route HF\n");
		return -1;
	}

	if (parse_sip_msg_uri(_m) == -1) {
		LOG(L_ERR, "loose_route: Error while parsing Request URI\n");
		return -1;
	}

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

	if (parse_uri(uri->s, uri->len, &puri) < 0) {
		LOG(L_ERR, "loose_route: Error while parsing the first route URI\n");
		return -1;
	}

	if (is_myself(&_m->parsed_uri.host, _m->parsed_uri.port_no)||
			_m->parsed_uri.type == TEL_URI_T ||
			_m->parsed_uri.type == TELS_URI_T) {
		DBG("loose_route: RURI is myself (or tel URI)\n");
		if ((ret = is_myself(&puri.host, puri.port_no)) == 1 &&
			!(enable_double_rr && is_2rr(&puri.params))) {
			DBG("loose_route: found preloaded loose route\n");
			return after_loose(_m, &puri, ret, 1);
		} else {
			if (has_to_tag(_m) == 1) {
				return after_strict(_m, &puri, ret);
			} else {
				LOG(L_WARN, "loose_route: pre-loaded strict routing?!\n");
				return -1;
			}
		}
	} else {
		DBG("loose_route: RURI is NOT myself\n");
		if (is_myself(&puri.host, puri.port_no)) {
			return after_loose(_m, &puri, 1, 0);
		} else {
			store_next_route_in_avps(uri);
			//LOG(L_WARN, "loose_route: no routing target is local\n");
			//return -1;
			return after_loose(_m, &puri, 0, 0);
		}
	}
}
Example #2
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;
}
Example #3
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;
}
Example #4
0
static inline int after_loose(struct sip_msg* _m, int preloaded)
{
	struct hdr_field* hdr;
	struct sip_uri puri;
	struct sip_uri puri2;
	rr_t* rt;
	int res;
	int status;
#ifdef ENABLE_USER_CHECK
	int ret;
#endif
	str uri;
	struct socket_info *si;
	int force_ss = 0;

	hdr = _m->route;
	rt = (rr_t*)hdr->parsed;
	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;
	}

	/* IF the URI was added by me, remove it */
#ifdef ENABLE_USER_CHECK
	ret=is_myself(&puri.user, &puri.host, puri.port_no);
	if (ret>0)
#else
	if (is_myself(&puri.host, puri.port_no))
#endif
	{
		LM_DBG("Topmost route URI: '%.*s' is me\n",
			uri.len, ZSW(uri.s));
		/* set the hooks for the params -bogdan */
		ctx_rrparam_set( &puri.params );

		/* if last route in header, gonna get del_lumped now,
		 * if not, it will be taken care of later
		 * Mark it now as deleted */
		rt->deleted = 1;

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

			rt->deleted = 1;

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

				/*same case as LL , if there is no next route*/
				ctx_routing_set( ROUTING_LL );
				force_ss = 1;

				goto done;
			}
			rt = (rr_t*)hdr->parsed;
		} else rt = rt->next;

		if (enable_double_rr && is_2rr(&puri.params)) {
			force_ss = 0;
			/* 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;
			}
			set_sip_defaults( puri.port_no, puri.proto);
			si = grep_sock_info( &puri.host, puri.port_no, puri.proto);
			if (si) {
				_m->force_send_socket = si;
			} else {
				if (enable_socket_mismatch_warning)
					LM_WARN("no socket found to match 2nd RR [%d][%.*s:%d]\n",
						puri.proto, puri.host.len, puri.host.s, puri.port_no);
			}

			rt->deleted = 1;

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

					/* same case as LL , if there is no next route */
					ctx_routing_set( ROUTING_LL );

					goto done;
				}
				rt = (rr_t*)hdr->parsed;
			} else rt = rt->next;
		} else {
			force_ss = 1;
		}

		uri = rt->nameaddr.uri;
		if (parse_uri(uri.s, uri.len, &puri2) < 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(ret < 0)
			return NOT_RR_DRIVEN;
#endif
		LM_DBG("Topmost URI is NOT myself\n");
		memcpy(&puri2, &puri, sizeof(struct sip_uri));
	}

	LM_DBG("URI to be processed: '%.*s'\n", uri.len, ZSW(uri.s));
	if (is_strict(&puri2.params)) {
		LM_DBG("Next URI is a strict router\n");

		ctx_routing_set( ROUTING_LS );
		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");

		ctx_routing_set( ROUTING_LL );

		if(get_maddr_uri(&uri, &puri2)!=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;
		}

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

			((rr_t *)hdr->parsed)->deleted = 1;
		}
	}
	status = RR_DRIVEN;

done:
	if (force_ss && !preloaded)
		_m->force_send_socket = _m->rcv.bind_address;
	/* run RR callbacks -bogdan */
	run_rr_callbacks( _m, &puri.params );
	return status;
}
Example #5
0
static inline int after_loose(struct sip_msg* _m, struct sip_uri* _pru, int _route_myself, int _ruri_myself)
{
	struct hdr_field* hdr;
	rr_t* rt;
	int res;
#ifdef ENABLE_USER_CHECK
	int ret;
#endif
	str* uri;
	str avp_cookie;

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

	     /* IF the URI was added by me, remove it */
	if (_route_myself == 1) {
		store_user_in_avps(&(_pru->user));

		DBG("after_loose: Topmost route URI: '%.*s' is me\n", uri->len, ZSW(uri->s));
		get_avp_cookie_from_uri(&(_pru->params), &avp_cookie);
		if (avp_cookie.len > 0)
			rr_set_avp_cookies(&avp_cookie, get_direction(_m, &(_pru->params)));
		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_loose: Can't remove Route HF\n");
				return RR_ERROR;
			}
			res = find_next_route(_m, &hdr);
			if (res < 0) {
				LOG(L_ERR, "after_loose: Error while finding next route\n");
				return RR_ERROR;
			}
			if (res > 0) { /* No next route found */
				DBG("after_loose: No next URI found\n");
				if (_ruri_myself == 1) {
					/* this a preloaded request. we do not check for the To-tag
					 * because the ACK for a negative reply will contain such
					 * a tag but the original INVITE not */
					return NOT_RR_DRIVEN;
				} else {
					return RR_DRIVEN;
				}
			}
			rt = (rr_t*)hdr->parsed;
		} else rt = rt->next;

		if (enable_double_rr && is_2rr(&(_pru->params))) {
			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_loose: Can't remove Route HF\n");
					return RR_ERROR;
				}
				res = find_next_route(_m, &hdr);
				if (res < 0) {
					LOG(L_ERR, "after_loose: Error while finding next route\n");
					return RR_ERROR;
				}
				if (res > 0) { /* No next route found */
					DBG("after_loose: No next URI found\n");
					/* preloaded routes can not happen with double_rr, so
					 * we were just the last hop with double_rr */
					return 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) < 0) {
				LOG(L_ERR, "after_loose: Error while parsing the next route URI\n");
				return RR_ERROR;
			}
		}
	} else {
#ifdef ENABLE_USER_CHECK
		/* check if it the ignored user */
		if(ret < 0)
			return NOT_RR_DRIVEN;
#endif
		DBG("after_loose: Topmost URI is NOT myself\n");
	}
	
	store_next_route_in_avps(uri);
	DBG("after_loose: URI to be processed: '%.*s'\n", uri->len, ZSW(uri->s));
	if (is_strict(&(_pru->params))) {
		DBG("after_loose: Next URI is a strict router\n");
		if (handle_sr(_m, hdr, rt) < 0) {
			LOG(L_ERR, "after_loose: Error while handling strict router\n");
			return RR_ERROR;
		}
	} else {
		     /* Next hop is loose router */
		DBG("after_loose: Next URI is a loose router\n");

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

		     /* 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)) {
				LOG(L_ERR, "after_loose: Can't remove Route HF\n");
				return RR_ERROR;
			}
		}
	}

	return RR_DRIVEN;
}