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