path/path.c

Go to the documentation of this file.
00001 /*
00002  * $Id: path.c 4960 2008-09-18 22:26:15Z miconda $
00003  *
00004  * Path handling for intermediate proxies.
00005  *
00006  * Copyright (C) 2006 Inode GmbH (Andreas Granig <andreas.granig@inode.info>)
00007  *
00008  * This file is part of Kamailio, a free SIP server.
00009  *
00010  * Kamailio is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version
00014  *
00015  * Kamailio is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License 
00021  * along with this program; if not, write to the Free Software 
00022  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00023  *
00024  */
00025 
00026 /*! \file
00027  * \brief Path :: Utilities
00028  *
00029  * \ingroup path
00030  * - Module: path
00031  */
00032 
00033 #include <string.h>
00034 #include <stdio.h>
00035 
00036 #include "../../mem/mem.h"
00037 #include "../../data_lump.h"
00038 #include "../../parser/parse_param.h"
00039 
00040 #include "path.h"
00041 #include "path_mod.h"
00042 
00043 #define PATH_PREFIX     "Path: <sip:"
00044 #define PATH_PREFIX_LEN    (sizeof(PATH_PREFIX)-1)
00045 
00046 #define PATH_LR_PARAM      ";lr"
00047 #define PATH_LR_PARAM_LEN  (sizeof(PATH_LR_PARAM)-1)
00048 
00049 #define PATH_RC_PARAM      ";received="
00050 #define PATH_RC_PARAM_LEN  (sizeof(PATH_RC_PARAM)-1)
00051 
00052 #define  PATH_CRLF      ">\r\n"
00053 #define PATH_CRLF_LEN      (sizeof(PATH_CRLF)-1)
00054 
00055 static int prepend_path(struct sip_msg* _m, str *user, int recv)
00056 {
00057    struct lump *l;
00058    char *prefix, *suffix, *crlf;
00059    int prefix_len, suffix_len;
00060    struct hdr_field *hf;
00061    str rcv_addr = {0, 0};
00062    char *src_ip;
00063       
00064    prefix = suffix = crlf = 0;
00065 
00066    prefix_len = PATH_PREFIX_LEN + (user->len ? (user->len+1) : 0);
00067    prefix = pkg_malloc(prefix_len);
00068    if (!prefix) {
00069       LM_ERR("no pkg memory left for prefix\n");
00070       goto out1;
00071    }
00072    memcpy(prefix, PATH_PREFIX, PATH_PREFIX_LEN);
00073    if (user->len) {
00074       memcpy(prefix + PATH_PREFIX_LEN, user->s, user->len);
00075       memcpy(prefix + prefix_len - 1, "@", 1);
00076    }
00077 
00078    suffix_len = PATH_LR_PARAM_LEN + (recv ? PATH_RC_PARAM_LEN : 0);
00079    suffix = pkg_malloc(suffix_len);
00080    if (!suffix) {
00081       LM_ERR("no pkg memory left for suffix\n");
00082       goto out1;
00083    }
00084    memcpy(suffix, PATH_LR_PARAM, PATH_LR_PARAM_LEN);
00085    if(recv)
00086       memcpy(suffix+PATH_LR_PARAM_LEN, PATH_RC_PARAM, PATH_RC_PARAM_LEN);
00087 
00088    crlf = pkg_malloc(PATH_CRLF_LEN);
00089    if (!crlf) {
00090       LM_ERR("no pkg memory left for crlf\n");
00091       goto out1;
00092    }
00093    memcpy(crlf, PATH_CRLF, PATH_CRLF_LEN);
00094 
00095    if (parse_headers(_m, HDR_PATH_F, 0) < 0) {
00096       LM_ERR("failed to parse message for Path header\n");
00097       goto out1;
00098    }
00099    for (hf = _m->headers; hf; hf = hf->next) {
00100       if (hf->type == HDR_PATH_T) {
00101          break;
00102       } 
00103    }
00104    if (hf)
00105       /* path found, add ours in front of that */
00106       l = anchor_lump(_m, hf->name.s - _m->buf, 0, 0);
00107    else
00108       /* no path, append to message */
00109       l = anchor_lump(_m, _m->unparsed - _m->buf, 0, 0);
00110    if (!l) {
00111       LM_ERR("failed to get anchor\n");
00112       goto out1;
00113    }
00114 
00115    l = insert_new_lump_before(l, prefix, prefix_len, 0);
00116    if (!l) goto out1;
00117    l = insert_subst_lump_before(l, SUBST_SND_ALL, 0);
00118    if (!l) goto out2;
00119    l = insert_new_lump_before(l, suffix, suffix_len, 0);
00120    if (!l) goto out2;
00121    if (recv) {
00122       /* TODO: agranig: optimize this one! */
00123       src_ip = ip_addr2a(&_m->rcv.src_ip);
00124       rcv_addr.s = pkg_malloc(6 + IP_ADDR_MAX_STR_SIZE + 22); /* "sip:<ip>:<port>;transport=sctp"\0 */
00125       if(!rcv_addr.s) {
00126          LM_ERR("no pkg memory left for receive-address\n");
00127          goto out3;
00128       }
00129       switch (_m->rcv.proto) {
00130          case PROTO_UDP:
00131             rcv_addr.len = snprintf(rcv_addr.s, 6 + IP_ADDR_MAX_STR_SIZE + 6, "\"sip:%s:%u\"", src_ip, _m->rcv.src_port);
00132             break;
00133          case PROTO_TCP:
00134             rcv_addr.len = snprintf(rcv_addr.s, 6 + IP_ADDR_MAX_STR_SIZE + 20, "\"sip:%s:%u;transport=tcp\"", src_ip, _m->rcv.src_port);
00135             break;
00136          case PROTO_TLS:
00137             rcv_addr.len = snprintf(rcv_addr.s, 6 + IP_ADDR_MAX_STR_SIZE + 20, "\"sip:%s:%u;transport=tls\"", src_ip, _m->rcv.src_port);
00138             break;
00139          case PROTO_SCTP:
00140             rcv_addr.len = snprintf(rcv_addr.s, 6 + IP_ADDR_MAX_STR_SIZE + 21, "\"sip:%s:%u;transport=sctp\"", src_ip, _m->rcv.src_port);
00141             break;
00142        }
00143 
00144       l = insert_new_lump_before(l, rcv_addr.s, rcv_addr.len, 0);
00145       if (!l) goto out3;
00146    }
00147    l = insert_new_lump_before(l, crlf, CRLF_LEN+1, 0);
00148    if (!l) goto out4;
00149    
00150    return 1;
00151    
00152 out1:
00153    if (prefix) pkg_free(prefix);
00154 out2:
00155    if (suffix) pkg_free(suffix);
00156 out3:
00157    if (rcv_addr.s) pkg_free(rcv_addr.s);
00158 out4:
00159    if (crlf) pkg_free(crlf);
00160 
00161    LM_ERR("failed to insert prefix lump\n");
00162 
00163    return -1;
00164 }
00165 
00166 /*! \brief
00167  * Prepend own uri to Path header
00168  */
00169 int add_path(struct sip_msg* _msg, char* _a, char* _b)
00170 {
00171    str user = {0,0};
00172    return prepend_path(_msg, &user, 0);
00173 }
00174 
00175 /*! \brief
00176  * Prepend own uri to Path header and take care of given
00177  * user.
00178  */
00179 int add_path_usr(struct sip_msg* _msg, char* _usr, char* _b)
00180 {
00181    return prepend_path(_msg, (str*)_usr, 0);
00182 }
00183 
00184 /*! \brief
00185  * Prepend own uri to Path header and append received address as
00186  * "received"-param to that uri.
00187  */
00188 int add_path_received(struct sip_msg* _msg, char* _a, char* _b)
00189 {
00190    str user = {0,0};
00191    return prepend_path(_msg, &user, 1);
00192 }
00193 
00194 /*! \brief
00195  * Prepend own uri to Path header and append received address as
00196  * "received"-param to that uri and take care of given user.
00197  */
00198 int add_path_received_usr(struct sip_msg* _msg, char* _usr, char* _b)
00199 {
00200    return prepend_path(_msg, (str*)_usr, 1);
00201 }
00202 
00203 /*! \brief
00204  * rr callback
00205  */
00206 void path_rr_callback(struct sip_msg *_m, str *r_param, void *cb_param)
00207 {
00208    param_hooks_t hooks;
00209    param_t *params;
00210          
00211    if (parse_params(r_param, CLASS_CONTACT, &hooks, &params) != 0) {
00212       LM_ERR("failed to parse route parametes\n");
00213       return;
00214    }
00215 
00216    if (hooks.contact.received) {
00217       if (set_dst_uri(_m, &hooks.contact.received->body) != 0) {
00218          LM_ERR("failed to set dst-uri\n");
00219          free_params(params);
00220          return;
00221       }
00222    }
00223    free_params(params);
00224 }

Generated on Thu May 24 02:00:28 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6