modules_k/rr/loose.c

Go to the documentation of this file.
00001 /*
00002  * $Id$
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 
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             
00049 #define RR_DRIVEN 1             
00050 #define NOT_RR_DRIVEN -1        
00052 #define ROUTE_SUFFIX ">\r\n"  
00053 #define ROUTE_SUFFIX_LEN (sizeof(ROUTE_SUFFIX)-1)
00054 
00056 static unsigned int routed_msg_id;
00057 static str routed_params = {0,0};
00058 
00059 
00065 static int is_preloaded(struct sip_msg* msg)
00066 {
00067         str tag;
00068 
00069         if (!msg->to && parse_headers(msg, HDR_TO_F, 0) == -1) {
00070                 LM_ERR("failed to parse To header field\n");
00071                 return -1;
00072         }
00073 
00074         if (!msg->to) {
00075                 LM_ERR("To header field not found\n");
00076                 return -1;
00077         }
00078 
00079         tag = get_to(msg)->tag_value;
00080         if (tag.s == 0 || tag.len == 0) {
00081                 LM_DBG("is_preloaded: Yes\n");
00082                 return 1;
00083         }
00084 
00085         LM_DBG("is_preloaded: No\n");
00086         return 0;
00087 }
00088 
00089 
00095 static inline int find_first_route(struct sip_msg* _m)
00096 {
00097         if (parse_headers(_m, HDR_ROUTE_F, 0) == -1) {
00098                 LM_ERR("failed to parse headers\n");
00099                 return -1;
00100         } else {
00101                 if (_m->route) {
00102                         if (parse_rr(_m->route) < 0) {
00103                                 LM_ERR("failed to parse Route HF\n");
00104                                 return -2;
00105                         }
00106                         return 0;
00107                 } else {
00108                         LM_DBG("No Route headers found\n");
00109                         return 1;
00110                 }
00111         }
00112 }
00113 
00114 
00121 static inline int is_myself(sip_uri_t *_puri)
00122 {
00123         int ret;
00124         
00125         ret = check_self(&_puri->host,
00126                         _puri->port_no?_puri->port_no:SIP_PORT, 0);/* match all protos*/
00127         if (ret < 0) return 0;
00128 
00129 #ifdef ENABLE_USER_CHECK
00130         if(ret==1 && i_user.len && i_user.len==_puri->user.len
00131                         && strncmp(i_user.s, _puri->user.s, _puri->user.len)==0)
00132         {
00133                 LM_DBG("ignore user matched - URI is not to the server itself\n");
00134                 return 0;
00135         }
00136 #endif
00137         
00138         if(ret==1) {
00139                 /* match on host:port, but if gruu, then fail */
00140                 if(_puri->gr.s!=NULL)
00141                         return 0;
00142         }
00143 
00144         return ret;
00145 }
00146 
00147 
00155 static inline int find_next_route(struct sip_msg* _m, struct hdr_field** _hdr)
00156 {
00157         struct hdr_field* ptr;
00158 
00159         ptr = (*_hdr)->next;
00160 
00161         /* Try to find already parsed Route headers */
00162         while(ptr) {
00163                 if (ptr->type == HDR_ROUTE_T) goto found;
00164                 ptr = ptr->next;
00165         }
00166 
00167         /* There are no already parsed Route headers, try to find next
00168          * occurrence of Route header
00169          */
00170         if (parse_headers(_m, HDR_ROUTE_F, 1) == -1) {
00171                 LM_ERR("failed to parse headers\n");
00172                 return -1;
00173         }
00174 
00175         if ((_m->last_header->type!=HDR_ROUTE_T) || (_m->last_header==*_hdr)) {
00176                 LM_DBG("No next Route HF found\n");
00177                 return 1;
00178         }
00179 
00180         ptr = _m->last_header;
00181 
00182  found:
00183         if (parse_rr(ptr) < 0) {
00184                 LM_ERR("failed to parse Route body\n");
00185                 return -2;
00186         }
00187 
00188         *_hdr = ptr;
00189         return 0;
00190 }
00191 
00192 
00198 static inline int is_strict(str* _params)
00199 {
00200         str s;
00201         int i, state = 0;
00202 
00203         if (_params->len == 0) return 1;
00204 
00205         s.s = _params->s;
00206         s.len = _params->len;
00207 
00208         for(i = 0; i < s.len; i++) {
00209                 switch(state) {
00210                 case 0:
00211                         switch(s.s[i]) {
00212                         case ' ':
00213                         case '\r':
00214                         case '\n':
00215                         case '\t':           break;
00216                         case 'l':
00217                         case 'L': state = 1; break;
00218                         default:  state = 4; break;
00219                         }
00220                         break;
00221 
00222                 case 1:
00223                         switch(s.s[i]) {
00224                         case 'r':
00225                         case 'R': state = 2; break;
00226                         default:  state = 4; break;
00227                         }
00228                         break;
00229 
00230                 case 2:
00231                         switch(s.s[i]) {
00232                         case ';':  return 0;
00233                         case '=':  return 0;
00234                         case ' ':
00235                         case '\r':
00236                         case '\n':
00237                         case '\t': state = 3; break;
00238                         default:   state = 4; break;
00239                         }
00240                         break;
00241 
00242                 case 3:
00243                         switch(s.s[i]) {
00244                         case ';':  return 0;
00245                         case '=':  return 0;
00246                         case ' ':
00247                         case '\r':
00248                         case '\n':
00249                         case '\t': break;
00250                         default:   state = 4; break;
00251                         }
00252                         break;
00253 
00254                 case 4:
00255                         switch(s.s[i]) {
00256                         case '\"': state = 5; break;
00257                         case ';':  state = 0; break;
00258                         default:              break;
00259                         }
00260                         break;
00261                         
00262                 case 5:
00263                         switch(s.s[i]) {
00264                         case '\\': state = 6; break;
00265                         case '\"': state = 4; break;
00266                         default:              break;
00267                         }
00268                         break;
00269 
00270                 case 6: state = 5; break;
00271                 }
00272         }
00273         
00274         if ((state == 2) || (state == 3)) return 0;
00275         else return 1;
00276 }
00277 
00278 
00288 static inline int save_ruri(struct sip_msg* _m)
00289 {
00290         struct lump* anchor;
00291         char *s;
00292         int len;
00293 
00294         /* We must parse the whole message header here, because
00295          * the Request-URI must be saved in last Route HF in the message
00296          */
00297         if (parse_headers(_m, HDR_EOH_F, 0) == -1) {
00298                 LM_ERR("failed to parse message\n");
00299                 return -1;
00300         }
00301 
00302         /* Create an anchor */
00303         anchor = anchor_lump(_m, _m->unparsed - _m->buf, 0, 0);
00304         if (anchor == 0) {
00305                 LM_ERR("failed to get anchor\n");
00306                 return -2;
00307         }
00308 
00309         /* Create buffer for new lump */
00310         len = ROUTE_PREFIX_LEN + _m->first_line.u.request.uri.len + ROUTE_SUFFIX_LEN;
00311         s = (char*)pkg_malloc(len);
00312         if (!s) {
00313                 LM_ERR("No memory pkg left\n");
00314                 return -3;
00315         }
00316 
00317         /* Create new header field */
00318         memcpy(s, ROUTE_PREFIX, ROUTE_PREFIX_LEN);
00319         memcpy(s + ROUTE_PREFIX_LEN, _m->first_line.u.request.uri.s, _m->first_line.u.request.uri.len);
00320         memcpy(s + ROUTE_PREFIX_LEN + _m->first_line.u.request.uri.len, ROUTE_SUFFIX, ROUTE_SUFFIX_LEN);
00321 
00322         LM_DBG("New header: '%.*s'\n", len, ZSW(s));
00323 
00324         /* Insert it */
00325         if (insert_new_lump_before(anchor, s, len, 0) == 0) {
00326                 pkg_free(s);
00327                 LM_ERR("failed to insert lump\n");
00328                 return -4;
00329         }
00330 
00331         return 0;
00332 }
00333 
00334 
00341 static inline int get_maddr_uri(str *uri, struct sip_uri *puri)
00342 {
00343         /* The max length of the maddr parameter is 127 */
00344         static char builturi[127+1];
00345         struct sip_uri turi;
00346 
00347         if(uri==NULL || uri->s==NULL)
00348                 return RR_ERROR;
00349         if(puri==NULL)
00350         {
00351                 if (parse_uri(uri->s, uri->len, &turi) < 0)
00352                 {
00353                         LM_ERR("failed to parse the URI\n");
00354                         return RR_ERROR;
00355                 }
00356                 puri = &turi;
00357         }
00358 
00359         if(puri->maddr.s==NULL)
00360                 return 0;
00361 
00362         /* sip: + maddr + : + port */
00363         if( (puri->maddr_val.len) > (127 - 10) )
00364         {
00365                 LM_ERR( "Too long maddr parameter\n");
00366                 return RR_ERROR;
00367         }
00368         memcpy( builturi, "sip:", 4 );
00369         memcpy( builturi+4, puri->maddr_val.s, puri->maddr_val.len );
00370                 
00371         if( puri->port.len > 0 )
00372         {
00373                 builturi[4+puri->maddr_val.len] =':';
00374                 memcpy(builturi+5+puri->maddr_val.len, puri->port.s,
00375                                 puri->port.len);
00376         }
00377 
00378         uri->len = 4+puri->maddr_val.len
00379                                         + ((puri->port.len>0)?(1+puri->port.len):0);
00380         builturi[uri->len]='\0';
00381         uri->s = builturi;
00382 
00383         LM_DBG("uri is %s\n", builturi );
00384         return 0;
00385 }
00386 
00387 
00395 static inline int handle_sr(struct sip_msg* _m, struct hdr_field* _hdr, rr_t* _r)
00396 {
00397         str uri;
00398         char* rem_off;
00399         int rem_len;
00400 
00401         /* Next hop is strict router, save R-URI here */
00402         if (save_ruri(_m) < 0) {
00403                 LM_ERR("failed to save Request-URI\n");
00404                 return -1;
00405         }
00406         
00407         /* Put the first Route in Request-URI */
00408         uri = _r->nameaddr.uri;
00409         if(get_maddr_uri(&uri, 0)!=0) {
00410                 LM_ERR("failed to check maddr\n");
00411                 return RR_ERROR;
00412         }
00413         if (rewrite_uri(_m, &uri) < 0) {
00414                 LM_ERR("failed to rewrite request URI\n");
00415                 return -2;
00416         }
00417 
00418         if (!_r->next) {
00419                 rem_off = _hdr->name.s;
00420                 rem_len = _hdr->len;
00421         } else {
00422                 rem_off = _hdr->body.s;
00423                 rem_len = _r->next->nameaddr.name.s - _hdr->body.s;
00424         }
00425 
00426         if (!del_lump(_m, rem_off - _m->buf, rem_len, 0)) {
00427                 LM_ERR("failed to remove Route HF\n");
00428                 return -9;
00429         }                       
00430 
00431         return 0;
00432 }
00433 
00434 
00446 static inline int find_rem_target(struct sip_msg* _m, struct hdr_field** _h, rr_t** _l, rr_t** _p)
00447 {
00448         struct hdr_field* ptr, *last;
00449 
00450         if (parse_headers(_m, HDR_EOH_F, 0) == -1) {
00451                 LM_ERR("failed to parse message header\n");
00452                 return -1;
00453         }
00454 
00455         ptr = _m->route;
00456         last = 0;
00457 
00458         while(ptr) {
00459                 if (ptr->type == HDR_ROUTE_T) last = ptr;
00460                 ptr = ptr->next;
00461         }
00462 
00463         if (last) {
00464                 if (parse_rr(last) < 0) {
00465                         LM_ERR("failed to parse last Route HF\n");
00466                         return -2;
00467                 }
00468 
00469                 *_p = 0;
00470                 *_l = (rr_t*)last->parsed;
00471                 *_h = last;
00472                 while ((*_l)->next) {
00473                         *_p = *_l;
00474                         *_l = (*_l)->next;
00475                 }
00476                 return 0;
00477         } else {
00478                 LM_ERR("search for last Route HF failed\n");
00479                 return 1;
00480         }
00481 }
00482 
00483 
00489 static inline int after_strict(struct sip_msg* _m)
00490 {
00491         int res, rem_len;
00492         struct hdr_field* hdr;
00493         struct sip_uri puri;
00494         rr_t* rt, *prev;
00495         char* rem_off;
00496         str uri;
00497         struct socket_info *si;
00498 
00499         hdr = _m->route;
00500         rt = (rr_t*)hdr->parsed;
00501         uri = rt->nameaddr.uri;
00502 
00503         /* reset rr handling static vars for safety in error case */
00504         routed_msg_id = 0;
00505         routed_params.s = NULL;
00506         routed_params.len = 0;
00507 
00508         if (parse_uri(uri.s, uri.len, &puri) < 0) {
00509                 LM_ERR("failed to parse the first route URI\n");
00510                 return RR_ERROR;
00511         }
00512 
00513         if ( enable_double_rr && is_2rr(&puri.params) && is_myself(&puri)) {
00514                 /* double route may occure due different IP and port, so force as
00515                  * send interface the one advertise in second Route */
00516                 si = grep_sock_info( &puri.host, puri.port_no, puri.proto);
00517                 if (si) {
00518                         set_force_socket(_m, si);
00519                 } else {
00520                         if (enable_socket_mismatch_warning)
00521                                 LM_WARN("no socket found for match second RR\n");
00522                 }
00523 
00524                 if (!rt->next) {
00525                         /* No next route in the same header, remove the whole header
00526                          * field immediately
00527                          */
00528                         if (!del_lump(_m, hdr->name.s - _m->buf, hdr->len, 0)) {
00529                                 LM_ERR("failed to remove Route HF\n");
00530                                 return RR_ERROR;
00531                         }
00532                         res = find_next_route(_m, &hdr);
00533                         if (res < 0) {
00534                                 LM_ERR("searching next route failed\n");
00535                                 return RR_ERROR;
00536                         }
00537                         if (res > 0) { /* No next route found */
00538                                 LM_DBG("after_strict: No next URI found\n");
00539                                 return NOT_RR_DRIVEN;
00540                         }
00541                         rt = (rr_t*)hdr->parsed;
00542                 } else rt = rt->next;
00543 
00544                 /* parse the new found uri */
00545                 uri = rt->nameaddr.uri;
00546                 if (parse_uri(uri.s, uri.len, &puri) < 0) {
00547                         LM_ERR("failed to parse URI\n");
00548                         return RR_ERROR;
00549                 }
00550         }
00551 
00552         /* set the hooks for the param
00553          * important note: RURI is already parsed by the above function, so 
00554          * we just used it without any checking */
00555         routed_msg_id = _m->id;
00556         routed_params = _m->parsed_uri.params;
00557 
00558         if (is_strict(&puri.params)) {
00559                 LM_DBG("Next hop: '%.*s' is strict router\n", uri.len, ZSW(uri.s));
00560                 /* Previous hop was a strict router and the next hop is strict
00561                  * router too. There is no need to save R-URI again because it
00562                  * is saved already. In fact, in this case we will behave exactly
00563                  * like a strict router. */
00564 
00565                 /* Note: when there is only one Route URI left (endpoint), it will
00566                  * always be a strict router because endpoints don't use ;lr parameter
00567                  * In this case we will simply put the URI in R-URI and forward it, 
00568                  * which will work perfectly */
00569                 if(get_maddr_uri(&uri, &puri)!=0) {
00570                         LM_ERR("failed to check maddr\n");
00571                         return RR_ERROR;
00572                 }
00573                 if (rewrite_uri(_m, &uri) < 0) {
00574                         LM_ERR("failed to rewrite request URI\n");
00575                         return RR_ERROR;
00576                 }
00577                 
00578                 if (rt->next) {
00579                         rem_off = hdr->body.s;
00580                         rem_len = rt->next->nameaddr.name.s - hdr->body.s;
00581                 } else {
00582                         rem_off = hdr->name.s;
00583                         rem_len = hdr->len;
00584                 }
00585                 if (!del_lump(_m, rem_off - _m->buf, rem_len, 0)) {
00586                         LM_ERR("failed to remove Route HF\n");
00587                         return RR_ERROR;
00588                 }
00589         } else {
00590                 LM_DBG("Next hop: '%.*s' is loose router\n",
00591                         uri.len, ZSW(uri.s));
00592 
00593                 if(get_maddr_uri(&uri, &puri)!=0) {
00594                         LM_ERR("failed to check maddr\n");
00595                         return RR_ERROR;
00596                 }
00597                 if (set_dst_uri(_m, &uri) < 0) {
00598                         LM_ERR("failed to set dst_uri\n");
00599                         return RR_ERROR;
00600                 }
00601 
00602                 /* Next hop is a loose router - Which means that is is not endpoint yet
00603                  * In This case we have to recover from previous strict routing, that 
00604                  * means we have to find the last Route URI and put in in R-URI and 
00605                  * remove the last Route URI. */
00606                 if (rt != hdr->parsed) {
00607                         /* There is a previous route uri which was 2nd uri of mine
00608                          * and must be removed here */
00609                         rem_off = hdr->body.s;
00610                         rem_len = rt->nameaddr.name.s - hdr->body.s;
00611                         if (!del_lump(_m, rem_off - _m->buf, rem_len, 0)) {
00612                                 LM_ERR("failed to remove Route HF\n");
00613                                 return RR_ERROR;
00614                         }
00615                 }
00616 
00617 
00618                 res = find_rem_target(_m, &hdr, &rt, &prev);
00619                 if (res < 0) {
00620                         LM_ERR("searching for last Route URI failed\n");
00621                         return RR_ERROR;
00622                 } else if (res > 0) {
00623                         /* No remote target is an error */
00624                         return RR_ERROR;
00625                 }
00626 
00627                 uri = rt->nameaddr.uri;
00628                 if(get_maddr_uri(&uri, 0)!=0) {
00629                         LM_ERR("checking maddr failed\n");
00630                         return RR_ERROR;
00631                 }
00632                 if (rewrite_uri(_m, &uri) < 0) {
00633                         LM_ERR("failed to rewrite R-URI\n");
00634                         return RR_ERROR;
00635                 }
00636 
00637                 /* The first character if uri will be either '<' when it is the 
00638                  * only URI in a Route header field or ',' if there is more than 
00639                  * one URI in the header field */
00640                 LM_DBG("The last route URI: '%.*s'\n", rt->nameaddr.uri.len,
00641                                 ZSW(rt->nameaddr.uri.s));
00642 
00643                 if (prev) {
00644                         rem_off = prev->nameaddr.name.s + prev->len;
00645                         rem_len = rt->nameaddr.name.s + rt->len - rem_off;
00646                 } else {
00647                         rem_off = hdr->name.s;
00648                         rem_len = hdr->len;
00649                 }
00650                 if (!del_lump(_m, rem_off - _m->buf, rem_len, 0)) {
00651                         LM_ERR("failed to remove Route HF\n");
00652                         return RR_ERROR;
00653                 }
00654         }
00655         
00656         /* run RR callbacks only if we have Route URI parameters */
00657         if(routed_params.len > 0)
00658                 run_rr_callbacks( _m, &routed_params );
00659 
00660         return RR_DRIVEN;
00661 }
00662 
00663 
00670 static inline int after_loose(struct sip_msg* _m, int preloaded)
00671 {
00672         struct hdr_field* hdr;
00673         struct sip_uri puri;
00674         rr_t* rt;
00675         int res;
00676         int status;
00677         int ret;
00678         str uri;
00679         struct socket_info *si;
00680 
00681         hdr = _m->route;
00682         rt = (rr_t*)hdr->parsed;
00683         uri = rt->nameaddr.uri;
00684 
00685         /* reset rr handling static vars for safety in error case */
00686         routed_msg_id = 0;
00687         routed_params.s = NULL;
00688         routed_params.len = 0;
00689 
00690         if (parse_uri(uri.s, uri.len, &puri) < 0) {
00691                 LM_ERR("failed to parse the first route URI\n");
00692                 return RR_ERROR;
00693         }
00694 
00695         /* IF the URI was added by me, remove it */
00696         ret=is_myself(&puri);
00697         if (ret>0)
00698         {
00699                 LM_DBG("Topmost route URI: '%.*s' is me\n",
00700                         uri.len, ZSW(uri.s));
00701                 /* set the hooks for the params */
00702                 routed_msg_id = _m->id;
00703                 routed_params = puri.params;
00704 
00705                 if (!rt->next) {
00706                         /* No next route in the same header, remove the whole header
00707                          * field immediately
00708                          */
00709                         if (!del_lump(_m, hdr->name.s - _m->buf, hdr->len, 0)) {
00710                                 LM_ERR("failed to remove Route HF\n");
00711                                 return RR_ERROR;
00712                         }
00713                         res = find_next_route(_m, &hdr);
00714                         if (res < 0) {
00715                                 LM_ERR("failed to find next route\n");
00716                                 return RR_ERROR;
00717                         }
00718                         if (res > 0) { /* No next route found */
00719                                 LM_DBG("No next URI found\n");
00720                                 status = (preloaded ? NOT_RR_DRIVEN : RR_DRIVEN);
00721                                 goto done;
00722                         }
00723                         rt = (rr_t*)hdr->parsed;
00724                 } else rt = rt->next;
00725                 
00726                 if (enable_double_rr && is_2rr(&puri.params)) {
00727                         /* double route may occure due different IP and port, so force as
00728                          * send interface the one advertise in second Route */
00729                         if (parse_uri(rt->nameaddr.uri.s,rt->nameaddr.uri.len,&puri)<0) {
00730                                 LM_ERR("failed to parse the double route URI\n");
00731                                 return RR_ERROR;
00732                         }
00733                         si = grep_sock_info( &puri.host, puri.port_no, puri.proto);
00734                         if (si) {
00735                                 set_force_socket(_m, si);
00736                         } else {
00737                                 if (enable_socket_mismatch_warning)
00738                                         LM_WARN("no socket found for match second RR\n");
00739                         }
00740 
00741                         if (!rt->next) {
00742                                 /* No next route in the same header, remove the whole header
00743                                  * field immediately */
00744                                 if (!del_lump(_m, hdr->name.s - _m->buf, hdr->len, 0)) {
00745                                         LM_ERR("failed to remove Route HF\n");
00746                                         return RR_ERROR;
00747                                 }
00748                                 res = find_next_route(_m, &hdr);
00749                                 if (res < 0) {
00750                                         LM_ERR("failed to find next route\n");
00751                                         return RR_ERROR;
00752                                 }
00753                                 if (res > 0) { /* No next route found */
00754                                         LM_DBG("no next URI found\n");
00755                                         status = (preloaded ? NOT_RR_DRIVEN : RR_DRIVEN);
00756                                         goto done;
00757                                 }
00758                                 rt = (rr_t*)hdr->parsed;
00759                         } else rt = rt->next;
00760                 }
00761                 
00762                 uri = rt->nameaddr.uri;
00763                 if (parse_uri(uri.s, uri.len, &puri) < 0) {
00764                         LM_ERR("failed to parse the first route URI\n");
00765                         return RR_ERROR;
00766                 }
00767         } else {
00768 #ifdef ENABLE_USER_CHECK
00769                 /* check if it the ignored user */
00770                 if(ret < 0)
00771                         return NOT_RR_DRIVEN;
00772 #endif
00773                 LM_DBG("Topmost URI is NOT myself\n");
00774         }
00775 
00776         LM_DBG("URI to be processed: '%.*s'\n", uri.len, ZSW(uri.s));
00777         if (is_strict(&puri.params)) {
00778                 LM_DBG("Next URI is a strict router\n");
00779                 if (handle_sr(_m, hdr, rt) < 0) {
00780                         LM_ERR("failed to handle strict router\n");
00781                         return RR_ERROR;
00782                 }
00783         } else {
00784                 /* Next hop is loose router */
00785                 LM_DBG("Next URI is a loose router\n");
00786 
00787                 if(get_maddr_uri(&uri, &puri)!=0) {
00788                         LM_ERR("checking maddr failed\n");
00789                         return RR_ERROR;
00790                 }
00791                 if (set_dst_uri(_m, &uri) < 0) {
00792                         LM_ERR("failed to set dst_uri\n");
00793                         return RR_ERROR;
00794                 }
00795                 /* dst_uri changed, so it makes sense to re-use the current uri for
00796                         forking */
00797                 ruri_mark_new(); /* re-use uri for serial forking */
00798 
00799                 /* There is a previous route uri which was 2nd uri of mine
00800                  * and must be removed here */
00801                 if (rt != hdr->parsed) {
00802                         if (!del_lump(_m, hdr->body.s - _m->buf, 
00803                         rt->nameaddr.name.s - hdr->body.s, 0)) {
00804                                 LM_ERR("failed to remove Route HF\n");
00805                                 return RR_ERROR;
00806                         }
00807                 }
00808         }
00809         status = RR_DRIVEN;
00810 
00811 done:
00812         /* run RR callbacks only if we have Route URI parameters */
00813         if(routed_params.len > 0)
00814                 run_rr_callbacks( _m, &routed_params );
00815         return status;
00816 }
00817 
00818 
00824 int loose_route(struct sip_msg* _m)
00825 {
00826         int ret;
00827 
00828         if (find_first_route(_m) != 0) {
00829                 LM_DBG("There is no Route HF\n");
00830                 return -1;
00831         }
00832                 
00833         if (parse_sip_msg_uri(_m)<0) {
00834                 LM_ERR("failed to parse Request URI\n");
00835                 return -1;
00836         }
00837 
00838         ret = is_preloaded(_m);
00839         if (ret < 0) {
00840                 return -1;
00841         } else if (ret == 1) {
00842                 return after_loose(_m, 1);
00843         } else {
00844                 if (is_myself(&_m->parsed_uri)) {
00845                         return after_strict(_m);
00846                 } else {
00847                         return after_loose(_m, 0);
00848                 }
00849         }
00850 }
00851 
00852 
00865 int check_route_param(struct sip_msg * msg, regex_t* re)
00866 {
00867         regmatch_t pmatch;
00868         char bk;
00869         str params;
00870 
00871         /* check if the hooked params belong to the same message */
00872         if (routed_msg_id != msg->id)
00873                 return -1;
00874 
00875         /* check if params are present */
00876         if ( !routed_params.s || !routed_params.len )
00877                 return -1;
00878 
00879         /* include also the first ';' */
00880         for( params=routed_params ; params.s[0]!=';' ; params.s--,params.len++ );
00881 
00882         /* do the well-known trick to convert to null terminted */
00883         bk = params.s[params.len];
00884         params.s[params.len] = 0;
00885         LM_DBG("params are <%s>\n", params.s);
00886         if (regexec( re, params.s, 1, &pmatch, 0)!=0) {
00887                 params.s[params.len] = bk;
00888                 return -1;
00889         } else {
00890                 params.s[params.len] = bk;
00891                 return 0;
00892         }
00893 }
00894 
00895 
00909 int get_route_param( struct sip_msg *msg, str *name, str *val)
00910 {
00911         char *p;
00912         char *end;
00913         char c;
00914         int quoted;
00915 
00916         /* check if the hooked params belong to the same message */
00917         if (routed_msg_id != msg->id)
00918                 goto notfound;
00919 
00920         /* check if params are present */
00921         if ( !routed_params.s || !routed_params.len )
00922                 goto notfound;
00923 
00924         end = routed_params.s + routed_params.len;
00925         p = routed_params.s;
00926 
00927 
00928         /* parse the parameters string and find the "name" param */
00929         while ( end-p>name->len+2 ) {
00930                 if (p!=routed_params.s) {
00931                         /* go to first ';' char */
00932                         for( quoted=0 ; p<end && !(*p==';' && !quoted) ; p++ )
00933                                 if ( (*p=='"' || *p=='\'') && *(p-1)!='\\' )
00934                                         quoted ^= 0x1;
00935                         if (p==end)
00936                                 goto notfound;
00937                         p++;
00938                 }
00939                 /* get first non space char */
00940                 while( p<end && (*p==' ' || *p=='\t') )
00941                         p++;
00942                 /* check the name - length first and content after */
00943                 if ( end-p<name->len+2 )
00944                         goto notfound;
00945                 if ( memcmp(p,name->s,name->len)!=0 ) {
00946                         p++;
00947                         continue;
00948                 }
00949                 p+=name->len;
00950                 while( p<end && (*p==' ' || *p=='\t') )
00951                         p++;
00952                 if (p==end|| *p==';') {
00953                         /* empty val */
00954                         val->len = 0;
00955                         val->s = 0;
00956                         goto found;
00957                 }
00958                 if (*(p++)!='=')
00959                         continue;
00960                 while( p<end && (*p==' ' || *p=='\t') )
00961                         p++;
00962                 if (p==end)
00963                         goto notfound;
00964                 /* get value */
00965                 if ( *p=='\'' || *p=='"') {
00966                         for( val->s = ++p ; p<end ; p++) {
00967                                 if ((*p=='"' || *p=='\'') && *(p-1)!='\\' )
00968                                         break;
00969                         }
00970                 } else {
00971                         for( val->s=p ; p<end ; p++) {
00972                                 if ( (c=*p)==';' || c==' ' || c=='\t' )
00973                                         break;
00974                         }
00975                 }
00976                 val->len = p-val->s;
00977                 if (val->len==0)
00978                         val->s = 0;
00979                 goto found;
00980         }
00981 
00982 notfound:
00983         return -1;
00984 found:
00985         return 0;
00986 }
00987 
00988 
01001 int is_direction(struct sip_msg * msg, int dir)
01002 {
01003         static str ftag_param = {"ftag",4};
01004         static unsigned int last_id = (unsigned int)-1;
01005         static unsigned int last_dir = 0;
01006         str ftag_val;
01007         str tag;
01008 
01009         if ( last_id==msg->id && last_dir!=0) {
01010                 if (last_dir==RR_FLOW_UPSTREAM)
01011                         goto upstream;
01012                 else
01013                         goto downstream;
01014         }
01015 
01016         ftag_val.s = 0;
01017         ftag_val.len = 0;
01018 
01019         if (get_route_param( msg, &ftag_param, &ftag_val)!=0) {
01020                 LM_DBG("param ftag not found\n");
01021                 goto downstream;
01022         }
01023 
01024         if ( ftag_val.s==0 || ftag_val.len==0 ) {
01025                 LM_DBG("param ftag has empty val\n");
01026                 goto downstream;
01027         }
01028 
01029         /* get the tag value from FROM hdr */
01030         if ( parse_from_header(msg)!=0 )
01031                 goto downstream;
01032 
01033         tag = ((struct to_body*)msg->from->parsed)->tag_value;
01034         if (tag.s==0 || tag.len==0)
01035                 goto downstream;
01036 
01037         /* compare the 2 strings */
01038         if (tag.len!=ftag_val.len || memcmp(tag.s,ftag_val.s,ftag_val.len))
01039                 goto upstream;
01040 
01041 downstream:
01042         last_id = msg->id;
01043         last_dir = RR_FLOW_DOWNSTREAM;
01044         return (dir==RR_FLOW_DOWNSTREAM)?0:-1;
01045 upstream:
01046         last_id = msg->id;
01047         last_dir = RR_FLOW_UPSTREAM;
01048         return (dir==RR_FLOW_UPSTREAM)?0:-1;
01049 }