modules_k/rr/record.c

Go to the documentation of this file.
00001 /*
00002  * $Id$
00003  *
00004  * Copyright (C) 2001-2003 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 
00035 #include <string.h>
00036 #include "../../mem/mem.h"
00037 #include "../../dprint.h"
00038 #include "../../parser/parse_uri.h"
00039 #include "../../parser/parse_from.h"
00040 #include "../../str.h"
00041 #include "../../data_lump.h"
00042 #include "record.h"
00043 #include "rr_mod.h"
00044 
00045 
00046 #define RR_PREFIX "Record-Route: <sip:"
00047 #define RR_PREFIX_LEN (sizeof(RR_PREFIX)-1)
00048 
00049 #define RR_LR ";lr"
00050 #define RR_LR_LEN (sizeof(RR_LR)-1)
00051 
00052 #define RR_LR_FULL ";lr=on"
00053 #define RR_LR_FULL_LEN (sizeof(RR_LR_FULL)-1)
00054 
00055 #define RR_FROMTAG ";ftag="
00056 #define RR_FROMTAG_LEN (sizeof(RR_FROMTAG)-1)
00057 
00058 #define RR_R2 ";r2=on"
00059 #define RR_R2_LEN (sizeof(RR_R2)-1)
00060 
00061 #define RR_TERM ">"CRLF
00062 #define RR_TERM_LEN (sizeof(RR_TERM)-1)
00063 
00064 #define INBOUND  1      
00065 #define OUTBOUND 0      
00067 #define RR_PARAM_BUF_SIZE 512 
00074 static char rr_param_buf_ptr[RR_PARAM_BUF_SIZE];
00075 static str rr_param_buf = {rr_param_buf_ptr,0};
00076 static unsigned int rr_param_msg;
00077 
00078 
00088 static inline int get_username(struct sip_msg* _m, str* _user)
00089 {
00090         struct sip_uri puri;
00091 
00092              /* first try to look at r-uri for a username */
00093         if (parse_uri(_m->first_line.u.request.uri.s, _m->first_line.u.request.uri.len, &puri) < 0) {
00094                 LM_ERR("failed to parse R-URI\n");
00095                 return -1;
00096         }
00097 
00098         /* no username in original uri -- hmm; maybe it is a uri
00099          * with just host address and username is in a preloaded route,
00100          * which is now no rewritten r-uri (assumed rewriteFromRoute
00101          * was called somewhere in script's beginning) 
00102          */
00103         if (!puri.user.len && _m->new_uri.s) {
00104                 if (parse_uri(_m->new_uri.s, _m->new_uri.len, &puri) < 0) {
00105                         LM_ERR("failed to parse new_uri\n");
00106                         return -2;
00107                 }
00108         }
00109 
00110         _user->s = puri.user.s;
00111         _user->len = puri.user.len;
00112         return 0;
00113 }
00114 
00115 
00123 static inline struct lump *insert_rr_param_lump(struct lump *before,
00124                                                 char *s, int l)
00125 {
00126         struct lump *rrp_l;
00127         char *s1;
00128 
00129         /* duplicate data in pkg mem */
00130         s1 = (char*)pkg_malloc(l);
00131         if (s1==0) {
00132                 LM_ERR("no more pkg mem (%d)\n",l);
00133                 return 0;
00134         }
00135         memcpy( s1, s, l);
00136 
00137         /* add lump */
00138         rrp_l = insert_new_lump_before( before, s1, l, HDR_RECORDROUTE_T);
00139         if (rrp_l==0) {
00140                 LM_ERR("failed to add before lump\n");
00141                 pkg_free(s1);
00142                 return 0;
00143         }
00144         return rrp_l;
00145 }
00146 
00147 
00160 static inline int build_rr(struct lump* _l, struct lump* _l2, str* user,
00161                                                 str *tag, str *params, int _inbound)
00162 {
00163         char* prefix, *suffix, *term, *r2;
00164         int suffix_len, prefix_len;
00165         char *p;
00166 
00167         prefix_len = RR_PREFIX_LEN + (user->len ? (user->len + 1) : 0);
00168         if (enable_full_lr) {
00169                 suffix_len = RR_LR_FULL_LEN + (params?params->len:0) +
00170                                 ((tag && tag->len) ? (RR_FROMTAG_LEN + tag->len) : 0);
00171         } else {
00172                 suffix_len = RR_LR_LEN + (params?params->len:0) +
00173                                 ((tag && tag->len) ? (RR_FROMTAG_LEN + tag->len) : 0);
00174         }
00175 
00176         prefix = pkg_malloc(prefix_len);
00177         suffix = pkg_malloc(suffix_len);
00178         term = pkg_malloc(RR_TERM_LEN);
00179         r2 = pkg_malloc(RR_R2_LEN);
00180 
00181         if (!prefix || !suffix || !term || !r2) {
00182                 LM_ERR("No more pkg memory\n");
00183                 if (suffix) pkg_free(suffix);
00184                 if (prefix) pkg_free(prefix);
00185                 if (term) pkg_free(term);
00186                 if (r2) pkg_free(r2);
00187                 return -3;
00188         }
00189         
00190         memcpy(prefix, RR_PREFIX, RR_PREFIX_LEN);
00191         if (user->len) {
00192                 memcpy(prefix + RR_PREFIX_LEN, user->s, user->len);
00193 #ifdef ENABLE_USER_CHECK
00194                 /* don't add the ignored user into a RR */
00195                 if(i_user.len && i_user.len == user->len && 
00196                                 !strncmp(i_user.s, user->s, i_user.len))
00197                 {
00198                         if(prefix[RR_PREFIX_LEN]=='x')
00199                                 prefix[RR_PREFIX_LEN]='y';
00200                         else
00201                                 prefix[RR_PREFIX_LEN]='x';
00202                 }
00203 #endif
00204                 prefix[RR_PREFIX_LEN + user->len] = '@';
00205         }
00206 
00207         p = suffix;
00208         if (enable_full_lr) {
00209                 memcpy( p, RR_LR_FULL, RR_LR_FULL_LEN);
00210                 p += RR_LR_FULL_LEN;
00211         } else {
00212                 memcpy( p, RR_LR, RR_LR_LEN);
00213                 p += RR_LR_LEN;
00214         }
00215         if (tag && tag->len) {
00216                 memcpy(p, RR_FROMTAG, RR_FROMTAG_LEN);
00217                 p += RR_FROMTAG_LEN;
00218                 memcpy(p, tag->s, tag->len);
00219                 p += tag->len;
00220         }
00221         if (params && params->len) {
00222                 memcpy(p, params->s, params->len);
00223                 p += params->len;
00224         }
00225         
00226         memcpy(term, RR_TERM, RR_TERM_LEN);
00227         memcpy(r2, RR_R2, RR_R2_LEN);
00228 
00229         if (!(_l = insert_new_lump_after(_l, prefix, prefix_len, 0))) 
00230                 goto lump_err;
00231         prefix = 0;
00232         _l = insert_subst_lump_after(_l, _inbound?SUBST_RCV_ALL:SUBST_SND_ALL, 0);
00233         if (_l ==0 )
00234                 goto lump_err;
00235         if (enable_double_rr) {
00236                 if (!(_l = insert_cond_lump_after(_l, COND_IF_DIFF_REALMS, 0)))
00237                         goto lump_err;
00238                 if (!(_l = insert_new_lump_after(_l, r2, RR_R2_LEN, 0)))
00239                         goto lump_err;
00240                 r2 = 0;
00241         } else {
00242                 pkg_free(r2);
00243                 r2 = 0;
00244         }
00245         _l2 = insert_new_lump_before(_l2, suffix, suffix_len, HDR_RECORDROUTE_T);
00246         if (_l2 == 0)
00247                 goto lump_err;
00248         if (rr_param_buf.len) {
00249                 _l2 = insert_rr_param_lump(_l2, rr_param_buf.s, rr_param_buf.len);
00250                 if (_l2 == 0)
00251                         goto lump_err;
00252         }
00253         suffix = 0;
00254         if (!(_l2 = insert_new_lump_before(_l2, term, RR_TERM_LEN, 0)))
00255                 goto lump_err;
00256         term = 0;
00257         return 0;
00258         
00259 lump_err:
00260         LM_ERR("failed to insert lumps\n");
00261         if (prefix) pkg_free(prefix);
00262         if (suffix) pkg_free(suffix);
00263         if (r2) pkg_free(r2);
00264         if (term) pkg_free(term);
00265         return -4;
00266 }
00267 
00268 
00278 int record_route(struct sip_msg* _m, str *params)
00279 {
00280         struct lump* l, *l2;
00281         str user;
00282         struct to_body* from = NULL;
00283         str* tag;
00284         
00285         user.len = 0;
00286         
00287         if (add_username) {
00288                 if (get_username(_m, &user) < 0) {
00289                         LM_ERR("failed to extract username\n");
00290                         return -1;
00291                 }
00292         }
00293 
00294         if (append_fromtag) {
00295                 if (parse_from_header(_m) < 0) {
00296                         LM_ERR("From parsing failed\n");
00297                         return -2;
00298                 }
00299                 from = (struct to_body*)_m->from->parsed;
00300                 tag = &from->tag_value;
00301         } else {
00302                 tag = 0;
00303         }
00304 
00305         if (rr_param_buf.len && rr_param_msg!=_m->id) {
00306                 /* rr_params were set for a different message -> reset buffer */
00307                 rr_param_buf.len = 0;
00308         }
00309 
00310         if (enable_double_rr) {
00311                 l = anchor_lump(_m, _m->headers->name.s - _m->buf,0,HDR_RECORDROUTE_T);
00312                 l2 = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, 0);
00313                 if (!l || !l2) {
00314                         LM_ERR("failed to create an anchor\n");
00315                         return -5;
00316                 }
00317                 l = insert_cond_lump_after(l, COND_IF_DIFF_REALMS, 0);
00318                 l2 = insert_cond_lump_before(l2, COND_IF_DIFF_REALMS, 0);
00319                 if (!l || !l2) {
00320                         LM_ERR("failed to insert conditional lump\n");
00321                         return -6;
00322                 }
00323                 if (build_rr(l, l2, &user, tag, params, OUTBOUND) < 0) {
00324                         LM_ERR("failed to insert outbound Record-Route\n");
00325                         return -7;
00326                 }
00327         }
00328         
00329         l = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, HDR_RECORDROUTE_T);
00330         l2 = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, 0);
00331         if (!l || !l2) {
00332                 LM_ERR("failed to create an anchor\n");
00333                 return -3;
00334         }
00335         
00336         if (build_rr(l, l2, &user, tag, params, INBOUND) < 0) {
00337                 LM_ERR("failed to insert inbound Record-Route\n");
00338                 return -4;
00339         }
00340 
00341         /* reset the rr_param buffer */
00342         rr_param_buf.len = 0;
00343         return 0;
00344 }
00345 
00346 
00357 int record_route_preset(struct sip_msg* _m, str* _data)
00358 {
00359         str user;
00360         struct to_body* from;
00361         struct lump* l;
00362         char* hdr, *p;
00363         int hdr_len;
00364 
00365         from = 0;
00366         user.len = 0;
00367         user.s = 0;
00368 
00369         if (add_username) {
00370                 if (get_username(_m, &user) < 0) {
00371                         LM_ERR("failed to extract username\n");
00372                         return -1;
00373                 }
00374         }
00375 
00376         if (append_fromtag) {
00377                 if (parse_from_header(_m) < 0) {
00378                         LM_ERR("From parsing failed\n");
00379                         return -2;
00380                 }
00381                 from = (struct to_body*)_m->from->parsed;
00382         }
00383         
00384         l = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, HDR_RECORDROUTE_T);
00385         if (!l) {
00386                 LM_ERR("failed to create lump anchor\n");
00387                 return -3;
00388         }
00389 
00390         hdr_len = RR_PREFIX_LEN;
00391         if (user.len)
00392                 hdr_len += user.len + 1; /* @ */
00393         hdr_len += _data->len;
00394 
00395         if (append_fromtag && from->tag_value.len) {
00396                 hdr_len += RR_FROMTAG_LEN + from->tag_value.len;
00397         }
00398         
00399         if (enable_full_lr) {
00400                 hdr_len += RR_LR_FULL_LEN;
00401         } else {
00402                 hdr_len += RR_LR_LEN;
00403         }
00404 
00405         hdr_len += RR_TERM_LEN;
00406 
00407         hdr = pkg_malloc(hdr_len);
00408         if (!hdr) {
00409                 LM_ERR("no pkg memory left\n");
00410                 return -4;
00411         }
00412 
00413         p = hdr;
00414         memcpy(p, RR_PREFIX, RR_PREFIX_LEN);
00415         p += RR_PREFIX_LEN;
00416 
00417         if (user.len) {
00418                 memcpy(p, user.s, user.len);
00419                 p += user.len;
00420                 *p = '@';
00421                 p++;
00422         }
00423 
00424         memcpy(p, _data->s, _data->len);
00425         p += _data->len;
00426         
00427         if (append_fromtag && from->tag_value.len) {
00428                 memcpy(p, RR_FROMTAG, RR_FROMTAG_LEN);
00429                 p += RR_FROMTAG_LEN;
00430                 memcpy(p, from->tag_value.s, from->tag_value.len);
00431                 p += from->tag_value.len;
00432         }
00433 
00434         if (enable_full_lr) {
00435                 memcpy(p, RR_LR_FULL, RR_LR_FULL_LEN);
00436                 p += RR_LR_FULL_LEN;
00437         } else {
00438                 memcpy(p, RR_LR, RR_LR_LEN);
00439                 p += RR_LR_LEN;
00440         }
00441 
00442         memcpy(p, RR_TERM, RR_TERM_LEN);
00443 
00444         if (!insert_new_lump_after(l, hdr, hdr_len, 0)) {
00445                 LM_ERR("failed to insert new lump\n");
00446                 pkg_free(hdr);
00447                 return -5;
00448         }
00449         return 1;
00450 }
00451 
00463 #define RR_TRANS_LEN 11
00464 #define RR_TRANS ";transport="
00465 static inline int build_advertised_rr(struct lump* _l, struct lump* _l2, str *_data,
00466                                 str* user, str *tag, int _inbound)
00467 {
00468         char *p;
00469         char *hdr, *trans, *r2, *suffix, *term;
00470         int hdr_len, suffix_len;
00471 
00472         hdr_len = RR_PREFIX_LEN;
00473         if (user && user->len)
00474                 hdr_len += user->len + 1; /* @ */
00475         hdr_len += _data->len;
00476 
00477         suffix_len = 0;
00478         if (tag && tag->len) {
00479                 suffix_len += RR_FROMTAG_LEN + tag->len;
00480         }
00481         
00482         if (enable_full_lr) {
00483                 suffix_len += RR_LR_FULL_LEN;
00484         } else {
00485                 suffix_len += RR_LR_LEN;
00486         }
00487 
00488         hdr = pkg_malloc(hdr_len);
00489         trans = pkg_malloc(RR_TRANS_LEN);
00490         suffix = pkg_malloc(suffix_len);
00491         r2 = pkg_malloc(RR_R2_LEN);
00492         term = pkg_malloc(RR_TERM_LEN);
00493         if (!hdr || !trans || !suffix || !term || !r2) {
00494                 LM_ERR("no pkg memory left\n");
00495                 if (hdr) pkg_free(hdr);
00496                 if (trans) pkg_free(trans);
00497                 if (suffix) pkg_free(suffix);
00498                 if (r2) pkg_free(r2);
00499                 if (term) pkg_free(term);
00500                 return -1;
00501         }
00502 
00503         p = hdr;
00504         memcpy(p, RR_PREFIX, RR_PREFIX_LEN);
00505         p += RR_PREFIX_LEN;
00506 
00507         if (user->len) {
00508                 memcpy(p, user->s, user->len);
00509                 p += user->len;
00510                 *p = '@';
00511                 p++;
00512         }
00513 
00514         memcpy(p, _data->s, _data->len);
00515         p += _data->len;
00516         
00517         p = suffix;
00518         if (tag && tag->len) {
00519                 memcpy(p, RR_FROMTAG, RR_FROMTAG_LEN);
00520                 p += RR_FROMTAG_LEN;
00521                 memcpy(p, tag->s, tag->len);
00522                 p += tag->len;
00523         }
00524 
00525         if (enable_full_lr) {
00526                 memcpy(p, RR_LR_FULL, RR_LR_FULL_LEN);
00527                 p += RR_LR_FULL_LEN;
00528         } else {
00529                 memcpy(p, RR_LR, RR_LR_LEN);
00530                 p += RR_LR_LEN;
00531         }
00532 
00533         memcpy(trans, RR_TRANS, RR_TRANS_LEN);
00534         memcpy(term, RR_TERM, RR_TERM_LEN);
00535         memcpy(r2, RR_R2, RR_R2_LEN);
00536 
00537         if (!(_l = insert_new_lump_after(_l, hdr, hdr_len, 0))) {
00538                 LM_ERR("failed to insert new lump\n");
00539                 goto lump_err;
00540         }
00541         hdr = NULL;
00542         if (!(_l = insert_cond_lump_after(_l, COND_IF_DIFF_PROTO, 0)))
00543                 goto lump_err;
00544         if (!(_l = insert_new_lump_after(_l, trans, RR_TRANS_LEN, 0)))
00545                 goto lump_err;
00546         if (!(_l = insert_subst_lump_after(_l, _inbound?SUBST_RCV_PROTO:SUBST_SND_PROTO, 0)))
00547                 goto lump_err;
00548         if (enable_double_rr) {
00549                 if (!(_l = insert_cond_lump_after(_l, COND_IF_DIFF_REALMS, 0)))
00550                         goto lump_err;
00551                 if (!(_l = insert_new_lump_after(_l, r2, RR_R2_LEN, 0)))
00552                         goto lump_err;
00553                 r2 = 0;
00554         } else {
00555                 pkg_free(r2);
00556                 r2 = 0;
00557         }
00558         if (!(_l2 = insert_new_lump_before(_l2, suffix, suffix_len, HDR_RECORDROUTE_T)))
00559                 goto lump_err;
00560         suffix = NULL;
00561         if (rr_param_buf.len) {
00562                 if (!(_l2 = insert_rr_param_lump(_l2, rr_param_buf.s, rr_param_buf.len)))
00563                         goto lump_err;
00564         }
00565         if (!(_l2 = insert_new_lump_before(_l2, term, RR_TERM_LEN, 0)))
00566                 goto lump_err;
00567         return 1;
00568 lump_err:
00569         if (hdr) pkg_free(hdr);
00570         if (suffix) pkg_free(suffix);
00571         if (term) pkg_free(term);
00572         if (r2) pkg_free(r2);
00573         return -7;
00574 }
00575 
00576 int record_route_advertised_address(struct sip_msg* _m, str* _data)
00577 {
00578         str user;
00579         str *tag = NULL;
00580         struct lump* l;
00581         struct lump* l2;
00582 
00583         user.len = 0;
00584         user.s = 0;
00585 
00586         if (add_username) {
00587                 if (get_username(_m, &user) < 0) {
00588                         LM_ERR("failed to extract username\n");
00589                         return -1;
00590                 }
00591         }
00592 
00593         if (append_fromtag) {
00594                 if (parse_from_header(_m) < 0) {
00595                         LM_ERR("From parsing failed\n");
00596                         return -2;
00597                 }
00598                 tag = &((struct to_body*)_m->from->parsed)->tag_value;
00599         }
00600 
00601         if (enable_double_rr) {
00602                 l = anchor_lump(_m, _m->headers->name.s - _m->buf,0,HDR_RECORDROUTE_T);
00603                 l2 = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, 0);
00604                 if (!l || !l2) {
00605                         LM_ERR("failed to create an anchor\n");
00606                         return -3;
00607                 }
00608                 l = insert_cond_lump_after(l, COND_IF_DIFF_PROTO, 0);
00609                 l2 = insert_cond_lump_before(l2, COND_IF_DIFF_PROTO, 0);
00610                 if (!l || !l2) {
00611                         LM_ERR("failed to insert conditional lump\n");
00612                         return -4;
00613                 }
00614                 if (build_advertised_rr(l, l2, _data, &user, tag, OUTBOUND) < 0) {
00615                         LM_ERR("failed to insert outbound Record-Route\n");
00616                         return -5;
00617                 }
00618         }
00619         
00620         l = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, HDR_RECORDROUTE_T);
00621         l2 = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, 0);
00622         if (!l || !l2) {
00623                 LM_ERR("failed to create an anchor\n");
00624                 return -6;
00625         }
00626         
00627         if (build_advertised_rr(l, l2, _data, &user, tag, INBOUND) < 0) {
00628                 LM_ERR("failed to insert outbound Record-Route\n");
00629                 return -7;
00630         }
00631         return 1;
00632 }
00633 
00634 
00640 static struct lump *get_rr_param_lump( struct lump** root)
00641 {
00642         struct lump *r, *crt, *last;
00643         /* look on the "before" branch for the last added lump */
00644 
00645         last = 0;
00646         for( crt=*root ; crt && !last ; crt=crt->next,(*root)=crt ) {
00647                 /* check on before list */
00648                 for( r=crt->before ; r ; r=r->before ) {
00649                         /* we are looking for the lump that adds the 
00650                          * suffix of the RR header */
00651                         if ( r->type==HDR_RECORDROUTE_T && r->op==LUMP_ADD)
00652                                 last = r;
00653                 }
00654         }
00655         return last;
00656 }
00657 
00658 
00665 int add_rr_param(struct sip_msg* msg, str* rr_param)
00666 {
00667         struct lump *last_param;
00668         struct lump *root;
00669 
00670         root = msg->add_rm;
00671         last_param = get_rr_param_lump( &root );
00672         if (last_param) {
00673                 /* RR was already done -> have to add a new lump before this one */
00674                 if (insert_rr_param_lump( last_param, rr_param->s, rr_param->len)==0) {
00675                         LM_ERR("failed to add lump\n");
00676                         goto error;
00677                 }
00678                 /* double routing enabled? */
00679                 if (enable_double_rr) {
00680                         if (root==0 || (last_param=get_rr_param_lump(&root))==0) {
00681                                 LM_CRIT("failed to locate double RR lump\n");
00682                                 goto error;
00683                         }
00684                         if (insert_rr_param_lump(last_param,rr_param->s,rr_param->len)==0){
00685                                 LM_ERR("failed to add 2nd lump\n");
00686                                 goto error;
00687                         }
00688                 }
00689         } else {
00690                 /* RR not done yet -> store the param in the static buffer */
00691                 if (rr_param_msg!=msg->id) {
00692                         /* it's about a different message -> reset buffer */
00693                         rr_param_buf.len = 0;
00694                         rr_param_msg = msg->id;
00695                 }
00696                 if (rr_param_buf.len+rr_param->len>RR_PARAM_BUF_SIZE) {
00697                         LM_ERR("maximum size of rr_param_buf exceeded\n");
00698                         goto error;
00699                 }
00700                 memcpy( rr_param_buf.s+rr_param_buf.len, rr_param->s, rr_param->len);
00701                 rr_param_buf.len += rr_param->len;
00702                 LM_DBG("rr_param_buf=<%.*s>\n",rr_param_buf.len, rr_param_buf.s);
00703         }
00704         return 0;
00705 
00706 error:
00707         return -1;
00708 }