[OpenSER-Users] recover from previous strict routing triggered incorrectly in ALG scenario

Bogdan-Andrei Iancu bogdan at voice-system.ro
Wed May 7 21:26:22 CEST 2008


Hi Andrew,

Just a short question - how comes that your BYE has proxy ips in RURI 
and Route ? where the end-device IP ??

Regards,
Bogdan

Andrew Pogrebennyk wrote:
> Hi,
> Im'm cross-posting this from OpenSER-Devel because I am not 100% sure 
> this is a bug.
>
> I am trying to create openser configuration for proxy that connects 
> private (VPN) network with public network. I started with a config 
> similar to http://voipembedded.com/resources/openser_cr.cfg, added a 
> call to force_send_socket() to send from public IP and 
> rtpproxy/nathelper in bridge mode. As per config loose_route() is called 
> from openser.cfg to route a sequential request within a dialog through 
> record-routing.
> Now when a BYE from callee comes in, it contains two Route headers: 
> Route: <a.b.c.d;r2=on;lr;ftag=...> where a.b.c.d is server's public IP, 
> Route: <10.0.0.100;r2=on;lr;ftag=...> where 10.0.0.100 is a private IP 
> and username at a.b.c.d in Request-URI.
>
> Take a look at loose_route():
>
> /*
>   * Do loose routing as defined in RFC3261
>   */
> int loose_route(struct sip_msg* _m, char* _s1, char* _s2)
> {
>      int ret;
>
>      if (find_first_route(_m) != 0) {
>          LM_DBG("There is no Route HF\n");
>          return -1;
>      }
>
>      if (parse_sip_msg_uri(_m)<0) {
>          LM_ERR("failed to parse Request URI\n");
>          return -1;
>      }
>
>      ret = is_preloaded(_m);
>      if (ret < 0) {
>          return -1;
>      } else if (ret == 1) {
>          return after_loose(_m, 1);
>      } else {
> #ifdef ENABLE_USER_CHECK
>          if (is_myself(&_m->parsed_uri.user, &_m->parsed_uri.host,
>          _m->parsed_uri.port_no)) {
> #else
>          if (is_myself(&_m->parsed_uri.host, _m->parsed_uri.port_no)) {
> #endif
>              return after_strict(_m);
>          } else {
>              return after_loose(_m, 0);
>          }
>      }
> }
>
> Obviously, is_myself() check passes and after_strict() is called.
>
> when after_strict() is called, it looks if the URI given in Route 
> contains lr parameter which marks loose routers, if so this block of 
> code is executed:
>      {
>          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;
>          }
>      }
>
> Therefore recover from previous strict routing is triggered: contents of 
> request line is destroyed and 10.0.0.100 is put instead:
> Apr 15 16:16:24 vpn-proxy oser[11027]: DBG:core:rewrite_uri: rewriting 
> Request-URI with 
> 'sip:10.0.0.100;r2=on;lr;ftag=aa40c2a5-54fb-1810-970d-0015c5bf2da5'
> Apr 15 16:16:24 vpn-proxy oser[11032]: [1] Got in dialog request not 
> catched by loose_route(): BYE 
> sip:10.0.0.100;r2=on;lr;ftag=aa40c2a5-54fb-1810-970d-0015c5bf2da5 
> SIP/2.0^M Via:...
>
> And we respond with 404 to in-dialog requests not caught by 
> loose_route(). Previous hop is SER and I don't know why OpenSER 
> considered it a strict router. Looks like a peculiarity of ALG mode. 
> Please advice what should I do to solve this problem. Is it a 
> configuration issue or perhaps loose_route() should not call 
> after_strict() in case of double record-routing?
>
> --
> Thank you,
> Andrew Pogrebennyk
>
> _______________________________________________
> Users mailing list
> Users at lists.openser.org
> http://lists.openser.org/cgi-bin/mailman/listinfo/users
>
>   





More information about the Users mailing list