loose.c

Go to the documentation of this file.
00001 /*
00002  * $Id: loose.c 5575 2009-02-10 10:13:29Z henningw $
00003  *
00004  * Copyright (C) 2001-2004 FhG Fokus
00005  *
00006  * This file is part of Kamailio, a free SIP server.
00007  *
00008  * Kamailio is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version
00012  *
00013  * Kamailio is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License 
00019  * along with this program; if not, write to the Free Software 
00020  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  */
00022 
00023 /*!
00024  * \file
00025  * \brief Route & Record-Route module, loose routing support
00026  * \ingroup rr
00027  */
00028 
00029 
00030 
00031 #include <string.h>
00032 #include "../../ut.h"
00033 #include "../../str.h"
00034 #include "../../dprint.h"
00035 #include "../../forward.h"
00036 #include "../../data_lump.h"
00037 #include "../../socket_info.h"
00038 #include "../../parser/parse_rr.h"
00039 #include "../../parser/parse_uri.h"
00040 #include "../../parser/parse_from.h"
00041 #include "../../mem/mem.h"
00042 #include "../../dset.h"
00043 #include "loose.h"
00044 #include "rr_cb.h"
00045 #include "rr_mod.h"
00046 
00047 
00048 #define RR_ERROR -1     /*!< An error occured while processing route set */
00049 #define RR_DRIVEN 1     /*!< The next hop is determined from the route set */
00050 #define NOT_RR_DRIVEN -1   /*!< The next hop is not determined from the route set */
00051 
00052 #define ROUTE_PREFIX "Route: <" /*!< SIP header prefix */
00053 #define ROUTE_PREFIX_LEN (sizeof(ROUTE_PREFIX)-1)
00054 
00055 #define ROUTE_SUFFIX ">\r\n"  /*!< SIP header suffix */
00056 #define ROUTE_SUFFIX_LEN (sizeof(ROUTE_SUFFIX)-1)
00057 
00058 /*! variables used to hook the param part of the local route */
00059 static unsigned int routed_msg_id;
00060 static str routed_params = {0,0};
00061 
00062 
00063 /*!
00064  * \brief Test whether we are processing pre-loaded route set by looking at the To tag
00065  * \param msg SIP message
00066  * \return -1 on failure, 0 on success
00067  */
00068 static int is_preloaded(struct sip_msg* msg)
00069 {
00070    str tag;
00071 
00072    if (!msg->to && parse_headers(msg, HDR_TO_F, 0) == -1) {
00073       LM_ERR("failed to parse To header field\n");
00074       return -1;
00075    }
00076 
00077    if (!msg->to) {
00078       LM_ERR("To header field not found\n");
00079       return -1;
00080    }
00081 
00082    tag = get_to(msg)->tag_value;
00083    if (tag.s == 0 || tag.len == 0) {
00084       LM_DBG("is_preloaded: Yes\n");
00085       return 1;
00086    }
00087 
00088    LM_DBG("is_preloaded: No\n");
00089    return 0;
00090 }
00091 
00092 
00093 /*!
00094  * \brief Parse the message and find first occurrence of Route header field.
00095  * \param _m SIP message 
00096  * \return -1 or -2 on a parser error, 0 if there is a Route HF and 1 if there is no Route HF
00097  */
00098 static inline int find_first_route(struct sip_msg* _m)
00099 {
00100    if (parse_headers(_m, HDR_ROUTE_F, 0) == -1) {
00101       LM_ERR("failed to parse headers\n");
00102       return -1;
00103    } else {
00104       if (_m->route) {
00105          if (parse_rr(_m->route) < 0) {
00106             LM_ERR("failed to parse Route HF\n");
00107             return -2;
00108          }
00109          return 0;
00110       } else {
00111          LM_DBG("No Route headers found\n");
00112          return 1;
00113       }
00114    }
00115 }
00116 
00117 
00118 /*!
00119  * \brief Find out if a URI contains r2 parameter which indicates that we put 2 record routes
00120  * \param _params URI
00121  * \return 1 if URI contains a r2 parameter, 0 otherwise
00122  */
00123 static inline int is_2rr(str* _params)
00124 {
00125    str s;
00126    int i, state = 0;
00127 
00128    if (_params->len == 0) return 0;
00129    s = *_params;
00130 
00131    for(i = 0; i < s.len; i++) {
00132       switch(state) {
00133       case 0:
00134          switch(s.s[i]) {
00135          case ' ':
00136          case '\r':
00137          case '\n':
00138          case '\t':           break;
00139          case 'r':
00140          case 'R': state = 1; break;
00141          default:  state = 4; break;
00142          }
00143          break;
00144 
00145       case 1:
00146          switch(s.s[i]) {
00147          case '2': state = 2; break;
00148          default:  state = 4; break;
00149          }
00150          break;
00151 
00152       case 2:
00153          switch(s.s[i]) {
00154          case ';':  return 1;
00155          case '=':  return 1;
00156          case ' ':
00157          case '\r':
00158          case '\n':
00159          case '\t': state = 3; break;
00160          default:   state = 4; break;
00161          }
00162          break;
00163 
00164       case 3:
00165          switch(s.s[i]) {
00166          case ';':  return 1;
00167          case '=':  return 1;
00168          case ' ':
00169          case '\r':
00170          case '\n':
00171          case '\t': break;
00172          default:   state = 4; break;
00173          }
00174          break;
00175 
00176       case 4:
00177          switch(s.s[i]) {
00178          case '\"': state = 5; break;
00179          case ';':  state = 0; break;
00180          default:              break;
00181          }
00182          break;
00183          
00184       case 5:
00185          switch(s.s[i]) {
00186          case '\\': state = 6; break;
00187          case '\"': state = 4; break;
00188          default:              break;
00189          }
00190          break;
00191 
00192       case 6: state = 5; break;
00193       }
00194    }
00195    
00196    if ((state == 2) || (state == 3)) return 1;
00197    else return 0;
00198 }
00199 
00200 
00201 /*!
00202  * \brief Check if URI is myself
00203  * \param _host host
00204  * \param _port port
00205  * \return 0 if the URI is not myself, 1 otherwise
00206  */
00207 #ifdef ENABLE_USER_CHECK
00208 static inline int is_myself(str *_user, str* _host, unsigned short _port)
00209 #else
00210 static inline int is_myself(str* _host, unsigned short _port)
00211 #endif
00212 {
00213    int ret;
00214    
00215    ret = check_self(_host, _port ? _port : SIP_PORT, 0);/* match all protos*/
00216    if (ret < 0) return 0;
00217 
00218 #ifdef ENABLE_USER_CHECK
00219    if(i_user.len && i_user.len==_user->len
00220          && !strncmp(i_user.s, _user->s, _user->len))
00221    {
00222       LM_DBG("this URI isn't mine\n");
00223       return -1;
00224    }
00225 #endif
00226    
00227    return ret;
00228 }
00229 
00230 
00231 /*!
00232  * \brief Find and parse next Route header field
00233  * \param _m SIP message
00234  * \param _hdr SIP header
00235  * \return negative on failure, 0 if the Route header was already parsed, 1 if no next
00236  * Route header could be found
00237  */
00238 static inline int find_next_route(struct sip_msg* _m, struct hdr_field** _hdr)
00239 {
00240    struct hdr_field* ptr;
00241 
00242    ptr = (*_hdr)->next;
00243 
00244    /* Try to find already parsed Route headers */
00245    while(ptr) {
00246       if (ptr->type == HDR_ROUTE_T) goto found;
00247       ptr = ptr->next;
00248    }
00249 
00250    /* There are no already parsed Route headers, try to find next
00251     * occurrence of Route header
00252     */
00253    if (parse_headers(_m, HDR_ROUTE_F, 1) == -1) {
00254       LM_ERR("failed to parse headers\n");
00255       return -1;
00256    }
00257 
00258    if ((_m->last_header->type!=HDR_ROUTE_T) || (_m->last_header==*_hdr)) {
00259       LM_DBG("No next Route HF found\n");
00260       return 1;
00261    }
00262 
00263    ptr = _m->last_header;
00264 
00265  found:
00266    if (parse_rr(ptr) < 0) {
00267       LM_ERR("failed to parse Route body\n");
00268       return -2;
00269    }
00270 
00271    *_hdr = ptr;
00272    return 0;
00273 }
00274 
00275 
00276 /*!
00277  * \brief Check if the given uri contains lr parameter which marks loose routers
00278  * \param _params URI string
00279  * \return 1 if URI contains no lr parameter, 0 if it contains a lr parameter
00280  */
00281 static inline int is_strict(str* _params)
00282 {
00283    str s;
00284    int i, state = 0;
00285 
00286    if (_params->len == 0) return 1;
00287 
00288    s.s = _params->s;
00289    s.len = _params->len;
00290 
00291    for(i = 0; i < s.len; i++) {
00292       switch(state) {
00293       case 0:
00294          switch(s.s[i]) {
00295          case ' ':
00296          case '\r':
00297          case '\n':
00298          case '\t':           break;
00299          case 'l':
00300          case 'L': state = 1; break;
00301          default:  state = 4; break;
00302          }
00303          break;
00304 
00305       case 1:
00306          switch(s.s[i]) {
00307          case 'r':
00308          case 'R': state = 2; break;
00309          default:  state = 4; break;
00310          }
00311          break;
00312 
00313       case 2:
00314          switch(s.s[i]) {
00315          case ';':  return 0;
00316          case '=':  return 0;
00317          case ' ':
00318          case '\r':
00319          case '\n':
00320          case '\t': state = 3; break;
00321          default:   state = 4; break;
00322          }
00323          break;
00324 
00325       case 3:
00326          switch(s.s[i]) {
00327          case ';':  return 0;
00328          case '=':  return 0;
00329          case ' ':
00330          case '\r':
00331          case '\n':
00332          case '\t': break;
00333          default:   state = 4; break;
00334          }
00335          break;
00336 
00337       case 4:
00338          switch(s.s[i]) {
00339          case '\"': state = 5; break;
00340          case ';':  state = 0; break;
00341          default:              break;
00342          }
00343          break;
00344          
00345       case 5:
00346          switch(s.s[i]) {
00347          case '\\': state = 6; break;
00348          case '\"': state = 4; break;
00349          default:              break;
00350          }
00351          break;
00352 
00353       case 6: state = 5; break;
00354       }
00355    }
00356    
00357    if ((state == 2) || (state == 3)) return 0;
00358    else return 1;
00359 }
00360 
00361 
00362 /*!
00363  * \brief Set Request-URI as last Route header of a SIP
00364  *
00365  * Set Request-URI as last Route header of a SIP message,
00366  * this is necessary when forwarding to a strict router.
00367  * Allocates memory for message lump in private memory.
00368  * \param _m SIP message
00369  * \return negative on failure, 0 on success
00370  */
00371 static inline int save_ruri(struct sip_msg* _m)
00372 {
00373    struct lump* anchor;
00374    char *s;
00375    int len;
00376 
00377    /* We must parse the whole message header here, because
00378     * the Request-URI must be saved in last Route HF in the message
00379     */
00380    if (parse_headers(_m, HDR_EOH_F, 0) == -1) {
00381       LM_ERR("failed to parse message\n");
00382       return -1;
00383    }
00384 
00385    /* Create an anchor */
00386    anchor = anchor_lump(_m, _m->unparsed - _m->buf, 0, 0);
00387    if (anchor == 0) {
00388       LM_ERR("failed to get anchor\n");
00389       return -2;
00390    }
00391 
00392    /* Create buffer for new lump */
00393    len = ROUTE_PREFIX_LEN + _m->first_line.u.request.uri.len + ROUTE_SUFFIX_LEN;
00394    s = (char*)pkg_malloc(len);
00395    if (!s) {
00396       LM_ERR("No memory pkg left\n");
00397       return -3;
00398    }
00399 
00400    /* Create new header field */
00401    memcpy(s, ROUTE_PREFIX, ROUTE_PREFIX_LEN);
00402    memcpy(s + ROUTE_PREFIX_LEN, _m->first_line.u.request.uri.s, _m->first_line.u.request.uri.len);
00403    memcpy(s + ROUTE_PREFIX_LEN + _m->first_line.u.request.uri.len, ROUTE_SUFFIX, ROUTE_SUFFIX_LEN);
00404 
00405    LM_DBG("New header: '%.*s'\n", len, ZSW(s));
00406 
00407    /* Insert it */
00408    if (insert_new_lump_before(anchor, s, len, 0) == 0) {
00409       pkg_free(s);
00410       LM_ERR("failed to insert lump\n");
00411       return -4;
00412    }
00413 
00414    return 0;
00415 }
00416 
00417 
00418 /*!
00419  * \brief Parse URI and check if it has a maddr parameter
00420  * \param uri URI to be checked if it has maddr, and also the output URI
00421  * \param puri parsed URI
00422  * \return -1 on failure, 0 on success
00423  */
00424 static inline int get_maddr_uri(str *uri, struct sip_uri *puri)
00425 {
00426    /* The max length of the maddr parameter is 127 */
00427    static char builturi[127+1];
00428    struct sip_uri turi;
00429 
00430    if(uri==NULL || uri->s==NULL)
00431       return RR_ERROR;
00432    if(puri==NULL)
00433    {
00434       if (parse_uri(uri->s, uri->len, &turi) < 0)
00435       {
00436          LM_ERR("failed to parse the URI\n");
00437          return RR_ERROR;
00438       }
00439       puri = &turi;
00440    }
00441 
00442    if(puri->maddr.s==NULL)
00443       return 0;
00444 
00445    /* sip: + maddr + : + port */
00446    if( (puri->maddr_val.len) > (127 - 10) )
00447    {
00448       LM_ERR( "Too long maddr parameter\n");
00449       return RR_ERROR;
00450    }
00451    memcpy( builturi, "sip:", 4 );
00452    memcpy( builturi+4, puri->maddr_val.s, puri->maddr_val.len );
00453       
00454    if( puri->port.len > 0 )
00455    {
00456       builturi[4+puri->maddr_val.len] =':';
00457       memcpy(builturi+5+puri->maddr_val.len, puri->port.s,
00458             puri->port.len);
00459    }
00460 
00461    uri->len = 4+puri->maddr_val.len
00462                + ((puri->port.len>0)?(1+puri->port.len):0);
00463    builturi[uri->len]='\0';
00464    uri->s = builturi;
00465 
00466    LM_DBG("uri is %s\n", builturi );
00467    return 0;
00468 }
00469 
00470 
00471 /*!
00472  * \brief Necessary logic to forward request to strict routers
00473  * \param _m SIP message
00474  * \param _hdr SIP header field
00475  * \param _r Route & Record-Route header field body
00476  * \return 0 on success, negative on an error
00477  */
00478 static inline int handle_sr(struct sip_msg* _m, struct hdr_field* _hdr, rr_t* _r)
00479 {
00480    str uri;
00481    char* rem_off;
00482    int rem_len;
00483 
00484    /* Next hop is strict router, save R-URI here */
00485    if (save_ruri(_m) < 0) {
00486       LM_ERR("failed to save Request-URI\n");
00487       return -1;
00488    }
00489    
00490    /* Put the first Route in Request-URI */
00491    uri = _r->nameaddr.uri;
00492    if(get_maddr_uri(&uri, 0)!=0) {
00493       LM_ERR("failed to check maddr\n");
00494       return RR_ERROR;
00495    }
00496    if (rewrite_uri(_m, &uri) < 0) {
00497       LM_ERR("failed to rewrite request URI\n");
00498       return -2;
00499    }
00500 
00501    if (!_r->next) {
00502       rem_off = _hdr->name.s;
00503       rem_len = _hdr->len;
00504    } else {
00505       rem_off = _hdr->body.s;
00506       rem_len = _r->next->nameaddr.name.s - _hdr->body.s;
00507    }
00508 
00509    if (!del_lump(_m, rem_off - _m->buf, rem_len, 0)) {
00510       LM_ERR("failed to remove Route HF\n");
00511       return -9;
00512    }        
00513 
00514    return 0;
00515 }
00516 
00517 
00518 /*!
00519  * \brief Find last route in the last Route header field
00520  *
00521  * Find last route in the last Route header field, if there was a previous
00522  * route in the last Route header field, it will be saved in _p parameter
00523  * \param _m SIP message
00524  * \param _h SIP header field
00525  * \param _l Route & Record-Route header field body
00526  * \param _p Route & Record-Route header field body
00527  * \return negative on failure, 0 on success
00528  */
00529 static inline int find_rem_target(struct sip_msg* _m, struct hdr_field** _h, rr_t** _l, rr_t** _p)
00530 {
00531    struct hdr_field* ptr, *last;
00532 
00533    if (parse_headers(_m, HDR_EOH_F, 0) == -1) {
00534       LM_ERR("failed to parse message header\n");
00535       return -1;
00536    }
00537 
00538    ptr = _m->route;
00539    last = 0;
00540 
00541    while(ptr) {
00542       if (ptr->type == HDR_ROUTE_T) last = ptr;
00543       ptr = ptr->next;
00544    }
00545 
00546    if (last) {
00547       if (parse_rr(last) < 0) {
00548          LM_ERR("failed to parse last Route HF\n");
00549          return -2;
00550       }
00551 
00552       *_p = 0;
00553       *_l = (rr_t*)last->parsed;
00554       *_h = last;
00555       while ((*_l)->next) {
00556          *_p = *_l;
00557          *_l = (*_l)->next;
00558       }
00559       return 0;
00560    } else {
00561       LM_ERR("search for last Route HF failed\n");
00562       return 1;
00563    }
00564 }
00565 
00566 
00567 /*!
00568  * \brief Previous hop was a strict router, handle this case
00569  * \param _m SIP message
00570  * \return -1 on error, 1 on success
00571  */
00572 static inline int after_strict(struct sip_msg* _m)
00573 {
00574    int res, rem_len;
00575    struct hdr_field* hdr;
00576    struct sip_uri puri;
00577    rr_t* rt, *prev;
00578    char* rem_off;
00579    str uri;
00580    struct socket_info *si;
00581 
00582    hdr = _m->route;
00583    rt = (rr_t*)hdr->parsed;
00584    uri = rt->nameaddr.uri;
00585 
00586    if (parse_uri(uri.s, uri.len, &puri) < 0) {
00587       LM_ERR("failed to parse the first route URI\n");
00588       return RR_ERROR;
00589    }
00590 
00591    if ( enable_double_rr && is_2rr(&puri.params) &&
00592 #ifdef ENABLE_USER_CHECK
00593    is_myself(&puri.user, &puri.host, puri.port_no)
00594 #else
00595    is_myself(&puri.host, puri.port_no)
00596 #endif
00597    ) {
00598       /* double route may occure due different IP and port, so force as
00599        * send interface the one advertise in second Route */
00600       si = grep_sock_info( &puri.host, puri.port_no, puri.proto);
00601       if (si) {
00602          _m->force_send_socket = si;
00603       } else {
00604          LM_WARN("no socket found for match second RR\n");
00605       }
00606 
00607       if (!rt->next) {
00608          /* No next route in the same header, remove the whole header
00609           * field immediately
00610           */
00611          if (!del_lump(_m, hdr->name.s - _m->buf, hdr->len, 0)) {
00612             LM_ERR("failed to remove Route HF\n");
00613             return RR_ERROR;
00614          }
00615          res = find_next_route(_m, &hdr);
00616          if (res < 0) {
00617             LM_ERR("searching next route failed\n");
00618             return RR_ERROR;
00619          }
00620          if (res > 0) { /* No next route found */
00621             LM_DBG("after_strict: No next URI found\n");
00622             return NOT_RR_DRIVEN;
00623          }
00624          rt = (rr_t*)hdr->parsed;
00625       } else rt = rt->next;
00626 
00627       /* parse the new found uri */
00628       uri = rt->nameaddr.uri;
00629       if (parse_uri(uri.s, uri.len, &puri) < 0) {
00630          LM_ERR("failed to parse URI\n");
00631          return RR_ERROR;
00632       }
00633    }
00634 
00635    /* set the hooks for the param
00636     * important note: RURI is already parsed by the above function, so 
00637     * we just used it without any checking */
00638    routed_msg_id = _m->id;
00639    routed_params = _m->parsed_uri.params;
00640 
00641    if (is_strict(&puri.params)) {
00642       LM_DBG("Next hop: '%.*s' is strict router\n", uri.len, ZSW(uri.s));
00643       /* Previous hop was a strict router and the next hop is strict
00644        * router too. There is no need to save R-URI again because it
00645        * is saved already. In fact, in this case we will behave exactly
00646        * like a strict router. */
00647 
00648       /* Note: when there is only one Route URI left (endpoint), it will
00649        * always be a strict router because endpoints don't use ;lr parameter
00650        * In this case we will simply put the URI in R-URI and forward it, 
00651        * which will work perfectly */
00652       if(get_maddr_uri(&uri, &puri)!=0) {
00653          LM_ERR("failed to check maddr\n");
00654          return RR_ERROR;
00655       }
00656       if (rewrite_uri(_m, &uri) < 0) {
00657          LM_ERR("failed to rewrite request URI\n");
00658          return RR_ERROR;
00659       }
00660       
00661       if (rt->next) {
00662          rem_off = hdr->body.s;
00663          rem_len = rt->next->nameaddr.name.s - hdr->body.s;
00664       } else {
00665          rem_off = hdr->name.s;
00666          rem_len = hdr->len;
00667       }
00668       if (!del_lump(_m, rem_off - _m->buf, rem_len, 0)) {
00669          LM_ERR("failed to remove Route HF\n");
00670          return RR_ERROR;
00671       }
00672    } else {
00673       LM_DBG("Next hop: '%.*s' is loose router\n",
00674          uri.len, ZSW(uri.s));
00675 
00676       if(get_maddr_uri(&uri, &puri)!=0) {
00677          LM_ERR("failed to check maddr\n");
00678          return RR_ERROR;
00679       }
00680       if (set_dst_uri(_m, &uri) < 0) {
00681          LM_ERR("failed to set dst_uri\n");
00682          return RR_ERROR;
00683       }
00684 
00685       /* Next hop is a loose router - Which means that is is not endpoint yet
00686        * In This case we have to recover from previous strict routing, that 
00687        * means we have to find the last Route URI and put in in R-URI and 
00688        * remove the last Route URI. */
00689       if (rt != hdr->parsed) {
00690          /* There is a previous route uri which was 2nd uri of mine
00691           * and must be removed here */
00692          rem_off = hdr->body.s;
00693          rem_len = rt->nameaddr.name.s - hdr->body.s;
00694          if (!del_lump(_m, rem_off - _m->buf, rem_len, 0)) {
00695             LM_ERR("failed to remove Route HF\n");
00696             return RR_ERROR;
00697          }
00698       }
00699 
00700 
00701       res = find_rem_target(_m, &hdr, &rt, &prev);
00702       if (res < 0) {
00703          LM_ERR("searching for last Route URI failed\n");
00704          return RR_ERROR;
00705       } else if (res > 0) {
00706          /* No remote target is an error */
00707          return RR_ERROR;
00708       }
00709 
00710       uri = rt->nameaddr.uri;
00711       if(get_maddr_uri(&uri, 0)!=0) {
00712          LM_ERR("checking maddr failed\n");
00713          return RR_ERROR;
00714       }
00715       if (rewrite_uri(_m, &uri) < 0) {
00716          LM_ERR("failed to rewrite R-URI\n");
00717          return RR_ERROR;
00718       }
00719 
00720       /* The first character if uri will be either '<' when it is the 
00721        * only URI in a Route header field or ',' if there is more than 
00722        * one URI in the header field */
00723       LM_DBG("The last route URI: '%.*s'\n", rt->nameaddr.uri.len,
00724             ZSW(rt->nameaddr.uri.s));
00725 
00726       if (prev) {
00727          rem_off = prev->nameaddr.name.s + prev->len;
00728          rem_len = rt->nameaddr.name.s + rt->len - rem_off;
00729       } else {
00730          rem_off = hdr->name.s;
00731          rem_len = hdr->len;
00732       }
00733       if (!del_lump(_m, rem_off - _m->buf, rem_len, 0)) {
00734          LM_ERR("failed to remove Route HF\n");
00735          return RR_ERROR;
00736       }
00737    }
00738    
00739    /* run RR callbacks */
00740    run_rr_callbacks( _m, &routed_params );
00741 
00742    return RR_DRIVEN;
00743 }
00744 
00745 
00746 /*!
00747  * \brief Previous hop was a loose router, handle this case
00748  * \param _m SIP message
00749  * \param preloaded do we have a preloaded route set
00750  * \return -1 on failure, 1 on success
00751  */
00752 static inline int after_loose(struct sip_msg* _m, int preloaded)
00753 {
00754    struct hdr_field* hdr;
00755    struct sip_uri puri;
00756    rr_t* rt;
00757    int res;
00758    int status;
00759 #ifdef ENABLE_USER_CHECK
00760    int ret;
00761 #endif
00762    str uri;
00763    struct socket_info *si;
00764 
00765    hdr = _m->route;
00766    rt = (rr_t*)hdr->parsed;
00767    uri = rt->nameaddr.uri;
00768 
00769    if (parse_uri(uri.s, uri.len, &puri) < 0) {
00770       LM_ERR("failed to parse the first route URI\n");
00771       return RR_ERROR;
00772    }
00773 
00774    /* IF the URI was added by me, remove it */
00775 #ifdef ENABLE_USER_CHECK
00776    ret=is_myself(&puri.user, &puri.host, puri.port_no);
00777    if (ret>0)
00778 #else
00779    if (is_myself(&puri.host, puri.port_no))
00780 #endif
00781    {
00782       LM_DBG("Topmost route URI: '%.*s' is me\n",
00783          uri.len, ZSW(uri.s));
00784       /* set the hooks for the params */
00785       routed_msg_id = _m->id;
00786       routed_params = puri.params;
00787 
00788       if (!rt->next) {
00789          /* No next route in the same header, remove the whole header
00790           * field immediately
00791           */
00792          if (!del_lump(_m, hdr->name.s - _m->buf, hdr->len, 0)) {
00793             LM_ERR("failed to remove Route HF\n");
00794             return RR_ERROR;
00795          }
00796          res = find_next_route(_m, &hdr);
00797          if (res < 0) {
00798             LM_ERR("failed to find next route\n");
00799             return RR_ERROR;
00800          }
00801          if (res > 0) { /* No next route found */
00802             LM_DBG("No next URI found\n");
00803             status = (preloaded ? NOT_RR_DRIVEN : RR_DRIVEN);
00804             goto done;
00805          }
00806          rt = (rr_t*)hdr->parsed;
00807       } else rt = rt->next;
00808       
00809       if (enable_double_rr && is_2rr(&puri.params)) {
00810          /* double route may occure due different IP and port, so force as
00811           * send interface the one advertise in second Route */
00812          if (parse_uri(rt->nameaddr.uri.s,rt->nameaddr.uri.len,&puri)<0) {
00813             LM_ERR("failed to parse the double route URI\n");
00814             return RR_ERROR;
00815          }
00816          si = grep_sock_info( &puri.host, puri.port_no, puri.proto);
00817          if (si) {
00818             _m->force_send_socket = si;
00819          } else {
00820             LM_WARN("no socket found for match second RR\n");
00821          }
00822 
00823          if (!rt->next) {
00824             /* No next route in the same header, remove the whole header
00825              * field immediately */
00826             if (!del_lump(_m, hdr->name.s - _m->buf, hdr->len, 0)) {
00827                LM_ERR("failed to remove Route HF\n");
00828                return RR_ERROR;
00829             }
00830             res = find_next_route(_m, &hdr);
00831             if (res < 0) {
00832                LM_ERR("failed to find next route\n");
00833                return RR_ERROR;
00834             }
00835             if (res > 0) { /* No next route found */
00836                LM_DBG("no next URI found\n");
00837                status = (preloaded ? NOT_RR_DRIVEN : RR_DRIVEN);
00838                goto done;
00839             }
00840             rt = (rr_t*)hdr->parsed;
00841          } else rt = rt->next;
00842       }
00843       
00844       uri = rt->nameaddr.uri;
00845       if (parse_uri(uri.s, uri.len, &puri) < 0) {
00846          LM_ERR("failed to parse the first route URI\n");
00847          return RR_ERROR;
00848       }
00849    } else {
00850 #ifdef ENABLE_USER_CHECK
00851       /* check if it the ignored user */
00852       if(ret < 0)
00853          return NOT_RR_DRIVEN;
00854 #endif
00855       LM_DBG("Topmost URI is NOT myself\n");
00856    }
00857 
00858    LM_DBG("URI to be processed: '%.*s'\n", uri.len, ZSW(uri.s));
00859    if (is_strict(&puri.params)) {
00860       LM_DBG("Next URI is a strict router\n");
00861       if (handle_sr(_m, hdr, rt) < 0) {
00862          LM_ERR("failed to handle strict router\n");
00863          return RR_ERROR;
00864       }
00865    } else {
00866       /* Next hop is loose router */
00867       LM_DBG("Next URI is a loose router\n");
00868 
00869       if(get_maddr_uri(&uri, &puri)!=0) {
00870          LM_ERR("checking maddr failed\n");
00871          return RR_ERROR;
00872       }
00873       if (set_dst_uri(_m, &uri) < 0) {
00874          LM_ERR("failed to set dst_uri\n");
00875          return RR_ERROR;
00876       }
00877 
00878       /* There is a previous route uri which was 2nd uri of mine
00879        * and must be removed here */
00880       if (rt != hdr->parsed) {
00881          if (!del_lump(_m, hdr->body.s - _m->buf, 
00882          rt->nameaddr.name.s - hdr->body.s, 0)) {
00883             LM_ERR("failed to remove Route HF\n");
00884             return RR_ERROR;
00885          }
00886       }
00887    }
00888    status = RR_DRIVEN;
00889 
00890 done:
00891    /* run RR callbacks */
00892    run_rr_callbacks( _m, &routed_params );
00893    return status;
00894 }
00895 
00896 
00897 /*!
00898  * \brief Do loose routing as per RFC3261
00899  * \param _m SIP message
00900  * \param _s1 unused
00901  * \param _s2 unused
00902  * \return -1 on failure, 1 on success
00903  */
00904 int loose_route(struct sip_msg* _m, char* _s1, char* _s2)
00905 {
00906    int ret;
00907 
00908    if (find_first_route(_m) != 0) {
00909       LM_DBG("There is no Route HF\n");
00910       return -1;
00911    }
00912       
00913    if (parse_sip_msg_uri(_m)<0) {
00914       LM_ERR("failed to parse Request URI\n");
00915       return -1;
00916    }
00917 
00918    ret = is_preloaded(_m);
00919    if (ret < 0) {
00920       return -1;
00921    } else if (ret == 1) {
00922       return after_loose(_m, 1);
00923    } else {
00924 #ifdef ENABLE_USER_CHECK
00925       if (is_myself(&_m->parsed_uri.user, &_m->parsed_uri.host,
00926       _m->parsed_uri.port_no)) {
00927 #else
00928       if (is_myself(&_m->parsed_uri.host, _m->parsed_uri.port_no)) {
00929 #endif
00930          return after_strict(_m);
00931       } else {
00932          return after_loose(_m, 0);
00933       }
00934    }
00935 }
00936 
00937 
00938 /*!
00939  * \brief Check if the route hdr has the required parameter
00940  *
00941  * The function checks for the request "msg" if the URI parameters
00942  * of the local Route header (corresponding to the local server)
00943  * matches the given regular expression "re". It must be call
00944  * after the loose_route was done.
00945  *
00946  * \param msg SIP message request that will has the Route header parameters checked
00947  * \param re compiled regular expression to be checked against the Route header parameters
00948  * \return -1 on failure, 1 on success
00949  */
00950 int check_route_param(struct sip_msg * msg, regex_t* re)
00951 {
00952    regmatch_t pmatch;
00953    char bk;
00954    str params;
00955 
00956    /* check if the hooked params belong to the same message */
00957    if (routed_msg_id != msg->id)
00958       return -1;
00959 
00960    /* check if params are present */
00961    if ( !routed_params.s || !routed_params.len )
00962       return -1;
00963 
00964    /* include also the first ';' */
00965    for( params=routed_params ; params.s[0]!=';' ; params.s--,params.len++ );
00966 
00967    /* do the well-known trick to convert to null terminted */
00968    bk = params.s[params.len];
00969    params.s[params.len] = 0;
00970    LM_DBG("params are <%s>\n", params.s);
00971    if (regexec( re, params.s, 1, &pmatch, 0)!=0) {
00972       params.s[params.len] = bk;
00973       return -1;
00974    } else {
00975       params.s[params.len] = bk;
00976       return 0;
00977    }
00978 }
00979 
00980 
00981 /*!
00982  * \brief Gets the value of a route parameter
00983  *
00984  * The function search in to the "msg"'s Route header parameters
00985  * the parameter called "name" and returns its value into "val".
00986  * It must be call only after the loose_route is done.
00987  *
00988  * \param msg - request that will have the Route header parameter searched
00989  * \param name - contains the Route header parameter to be serached
00990  * \param val returns the value of the searched Route header parameter if found.
00991  * It might be an empty string if the parameter had no value.
00992  * \return 0 if parameter was found (even if it has no value), -1 otherwise
00993  */
00994 int get_route_param( struct sip_msg *msg, str *name, str *val)
00995 {
00996    char *p;
00997    char *end;
00998    char c;
00999    int quoted;
01000 
01001    /* check if the hooked params belong to the same message */
01002    if (routed_msg_id != msg->id)
01003       goto notfound;
01004 
01005    /* check if params are present */
01006    if ( !routed_params.s || !routed_params.len )
01007       goto notfound;
01008 
01009    end = routed_params.s + routed_params.len;
01010    p = routed_params.s;
01011 
01012 
01013    /* parse the parameters string and find the "name" param */
01014    while ( end-p>name->len+2 ) {
01015       if (p!=routed_params.s) {
01016          /* go to first ';' char */
01017          for( quoted=0 ; p<end && !(*p==';' && !quoted) ; p++ )
01018             if ( (*p=='"' || *p=='\'') && *(p-1)!='\\' )
01019                quoted ^= 0x1;
01020          if (p==end)
01021             goto notfound;
01022          p++;
01023       }
01024       /* get first non space char */
01025       while( p<end && (*p==' ' || *p=='\t') )
01026          p++;
01027       /* check the name - length first and content after */
01028       if ( end-p<name->len+2 )
01029          goto notfound;
01030       if ( memcmp(p,name->s,name->len)!=0 ) {
01031          p++;
01032          continue;
01033       }
01034       p+=name->len;
01035       while( p<end && (*p==' ' || *p=='\t') )
01036          p++;
01037       if (p==end|| *p==';') {
01038          /* empty val */
01039          val->len = 0;
01040          val->s = 0;
01041          goto found;
01042       }
01043       if (*(p++)!='=')
01044          continue;
01045       while( p<end && (*p==' ' || *p=='\t') )
01046          p++;
01047       if (p==end)
01048          goto notfound;
01049       /* get value */
01050       if ( *p=='\'' || *p=='"') {
01051          for( val->s = ++p ; p<end ; p++) {
01052             if ((*p=='"' || *p=='\'') && *(p-1)!='\\' )
01053                break;
01054          }
01055       } else {
01056          for( val->s=p ; p<end ; p++) {
01057             if ( (c=*p)==';' || c==' ' || c=='\t' )
01058                break;
01059          }
01060       }
01061       val->len = p-val->s;
01062       if (val->len==0)
01063          val->s = 0;
01064       goto found;
01065    }
01066 
01067 notfound:
01068    return -1;
01069 found:
01070    return 0;
01071 }
01072 
01073 
01074 /*!
01075  * \brief Check the direction of the message
01076  *
01077  * The function checks the flow direction of the request "msg". As
01078  * for checking it's used the "ftag" Route header parameter, the
01079  * append_fromtag module parameter must be enables.
01080  * Also this must be call only after the loose_route is done.
01081 
01082  * \param msg SIP message request that will have the direction checked
01083  * \param dir direction to be checked against. It may be RR_FLOW_UPSTREAM or RR_FLOW_DOWNSTREAM
01084  * \return 0 if the request flow direction is the same as the given direction, -1 otherwise
01085  */
01086 int is_direction(struct sip_msg * msg, int dir)
01087 {
01088    static str ftag_param = {"ftag",4};
01089    static unsigned int last_id = (unsigned int)-1;
01090    static unsigned int last_dir = 0;
01091    str ftag_val;
01092    str tag;
01093 
01094    if ( last_id==msg->id && last_dir!=0) {
01095       if (last_dir==RR_FLOW_UPSTREAM)
01096          goto upstream;
01097       else
01098          goto downstream;
01099    }
01100 
01101    ftag_val.s = 0;
01102    ftag_val.len = 0;
01103 
01104    if (get_route_param( msg, &ftag_param, &ftag_val)!=0) {
01105       LM_DBG("param ftag not found\n");
01106       goto downstream;
01107    }
01108 
01109    if ( ftag_val.s==0 || ftag_val.len==0 ) {
01110       LM_DBG("param ftag has empty val\n");
01111       goto downstream;
01112    }
01113 
01114    /* get the tag value from FROM hdr */
01115    if ( parse_from_header(msg)!=0 )
01116       goto downstream;
01117 
01118    tag = ((struct to_body*)msg->from->parsed)->tag_value;
01119    if (tag.s==0 || tag.len==0)
01120       goto downstream;
01121 
01122    /* compare the 2 strings */
01123    if (tag.len!=ftag_val.len || memcmp(tag.s,ftag_val.s,ftag_val.len))
01124       goto upstream;
01125 
01126 downstream:
01127    last_id = msg->id;
01128    last_dir = RR_FLOW_DOWNSTREAM;
01129    return (dir==RR_FLOW_DOWNSTREAM)?0:-1;
01130 upstream:
01131    last_id = msg->id;
01132    last_dir = RR_FLOW_UPSTREAM;
01133    return (dir==RR_FLOW_UPSTREAM)?0:-1;
01134 }

Generated on Wed May 23 18:00:28 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6