modules_k/rr/rr_mod.c

Go to the documentation of this file.
00001 /*
00002  * $Id$
00003  *
00004  * Copyright (C) 2001-2003 FhG Fokus
00005  * Copyright (C) 2011 Carsten Bock, carsten@ng-voice.com
00006  *
00007  * This file is part of Kamailio, a free SIP server.
00008  *
00009  * Kamailio is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version
00013  *
00014  * Kamailio is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License 
00020  * along with this program; if not, write to the Free Software 
00021  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022  */
00023 
00031 #include <stdio.h>
00032 #include <stdlib.h>
00033 #include <sys/types.h>
00034 #include <regex.h>
00035 
00036 #include "../../sr_module.h"
00037 #include "../../ut.h"
00038 #include "../../error.h"
00039 #include "../../pvar.h"
00040 #include "../../mem/mem.h"
00041 #include "../../mod_fix.h"
00042 #include "../../parser/parse_rr.h"
00043 #include "loose.h"
00044 #include "record.h"
00045 #include "rr_cb.h"
00046 #include "api.h"
00047 
00048 #ifdef ENABLE_USER_CHECK
00049 #include <string.h>
00050 #include "../../str.h"
00051 str i_user;
00052 char *ignore_user = NULL;
00053 #endif
00054 
00055 int append_fromtag = 1;         
00056 int enable_double_rr = 1;       
00057 int enable_full_lr = 0;         
00058 int add_username = 0;           
00059  int enable_socket_mismatch_warning = 1; 
00061 static unsigned int last_rr_msg;
00062 
00063 MODULE_VERSION
00064 
00065 static int  mod_init(void);static void mod_destroy(void);
00066 /* fixup functions */
00067 static int direction_fixup(void** param, int param_no);
00068 static int it_list_fixup(void** param, int param_no);
00069 /* wrapper functions */
00070 static int w_loose_route(struct sip_msg *, char *, char *);
00071 static int w_record_route(struct sip_msg *, char *, char *);
00072 static int w_record_route_preset(struct sip_msg *,char *, char *);
00073 static int w_record_route_advertised_address(struct sip_msg *, char *, char *);
00074 static int w_add_rr_param(struct sip_msg *,char *, char *);
00075 static int w_check_route_param(struct sip_msg *,char *, char *);
00076 static int w_is_direction(struct sip_msg *,char *, char *);
00077 /* PV functions */
00078 static int pv_get_route_uri_f(struct sip_msg *, pv_param_t *, pv_value_t *);
00082 static cmd_export_t cmds[] = {
00083         {"loose_route",          (cmd_function)w_loose_route,           0, 0, 0,
00084                         REQUEST_ROUTE},
00085         {"record_route",         (cmd_function)w_record_route,          0, 0, 0,
00086                         REQUEST_ROUTE|BRANCH_ROUTE|FAILURE_ROUTE},
00087         {"record_route",         (cmd_function)w_record_route,          1, it_list_fixup, 0,
00088                         REQUEST_ROUTE|BRANCH_ROUTE|FAILURE_ROUTE},
00089         {"record_route_preset",  (cmd_function)w_record_route_preset, 1, it_list_fixup, 0,
00090                         REQUEST_ROUTE|BRANCH_ROUTE|FAILURE_ROUTE},
00091         {"record_route_preset",  (cmd_function)w_record_route_preset, 2, it_list_fixup, 0,
00092                         REQUEST_ROUTE|BRANCH_ROUTE|FAILURE_ROUTE},
00093         {"record_route_advertised_address",  (cmd_function)w_record_route_advertised_address, 1, it_list_fixup, 0,
00094                         REQUEST_ROUTE|BRANCH_ROUTE|FAILURE_ROUTE},
00095         {"add_rr_param",         (cmd_function)w_add_rr_param,  1, it_list_fixup, 0,
00096                         REQUEST_ROUTE|BRANCH_ROUTE|FAILURE_ROUTE},
00097         {"check_route_param",    (cmd_function)w_check_route_param, 1, fixup_regexp_null, fixup_free_regexp_null,
00098                         REQUEST_ROUTE},
00099         {"is_direction",         (cmd_function)w_is_direction,          1, direction_fixup, 0,
00100                         REQUEST_ROUTE},
00101         {"load_rr",              (cmd_function)load_rr,                                 0, 0, 0, 0},
00102         {0, 0, 0, 0, 0, 0}
00103 };
00104 
00105 
00109 static param_export_t params[] ={ 
00110         {"append_fromtag",      INT_PARAM, &append_fromtag},
00111         {"enable_double_rr",    INT_PARAM, &enable_double_rr},
00112         {"enable_full_lr",              INT_PARAM, &enable_full_lr},
00113 #ifdef ENABLE_USER_CHECK
00114         {"ignore_user",         STR_PARAM, &ignore_user},
00115 #endif
00116         {"add_username",                INT_PARAM, &add_username},
00117         {"enable_socket_mismatch_warning",INT_PARAM,&enable_socket_mismatch_warning},
00118         {0, 0, 0 }
00119 };
00120 
00124 static pv_export_t mod_pvs[] = {
00125     {{"route_uri", (sizeof("route_uri")-1)}, /* URI of the first Route-Header */
00126      PVT_OTHER, pv_get_route_uri_f, 0, 0, 0, 0, 0},
00127     {{0, 0}, 0, 0, 0, 0, 0, 0, 0}
00128 };
00129 
00130 
00131 
00132 struct module_exports exports = {
00133         "rr",
00134         DEFAULT_DLFLAGS,        
00135         cmds,                   
00136         params,                 
00137         0,                              
00138         0,                              
00139         mod_pvs,                        
00140         0,                              
00141         mod_init,                       
00142         0,                              
00143         mod_destroy,            
00144         0                               
00145 };
00146 
00147 
00148 static int mod_init(void)
00149 {
00150 #ifdef ENABLE_USER_CHECK
00151         if(ignore_user)
00152         {
00153                 i_user.s = ignore_user;
00154                 i_user.len = strlen(ignore_user);
00155         }
00156         else
00157         {
00158                 i_user.s = 0;
00159                 i_user.len = 0;
00160         }
00161 #endif
00162         return 0;
00163 }
00164 
00165 
00166 static void mod_destroy(void)
00167 {
00168         destroy_rrcb_lists();
00169 }
00170 
00171 
00172 static int it_list_fixup(void** param, int param_no)
00173 {
00174         pv_elem_t *model;
00175         str s;
00176         if(*param)
00177         {
00178                 s.s = (char*)(*param); s.len = strlen(s.s);
00179                 if(pv_parse_format(&s, &model)<0)
00180                 {
00181                         LM_ERR("wrong format[%s]\n",(char*)(*param));
00182                         return E_UNSPEC;
00183                 }
00184                 *param = (void*)model;
00185         }
00186         return 0;
00187 }
00188 
00189 
00190 static int direction_fixup(void** param, int param_no)
00191 {
00192         char *s;
00193         int n;
00194 
00195         if (!append_fromtag) {
00196                 LM_ERR("usage of \"is_direction\" function requires parameter"
00197                                 "\"append_fromtag\" enabled!!");
00198                 return E_CFG;
00199         }
00200         if (param_no==1) {
00201                 n = 0;
00202                 s = (char*) *param;
00203                 if ( strcasecmp(s,"downstream")==0 ) {
00204                         n = RR_FLOW_DOWNSTREAM;
00205                 } else if ( strcasecmp(s,"upstream")==0 ) {
00206                         n = RR_FLOW_UPSTREAM;
00207                 } else {
00208                         LM_ERR("unknown direction '%s'\n",s);
00209                         return E_CFG;
00210                 }
00211                 /* free string */
00212                 pkg_free(*param);
00213                 /* replace it with the flag */
00214                 *param = (void*)(unsigned long)n;
00215         }
00216         return 0;
00217 }
00218 
00222 static int w_loose_route(struct sip_msg *msg, char *p1, char *p2)
00223 {
00224         return loose_route(msg);
00225 }
00226 
00230 static int w_record_route(struct sip_msg *msg, char *key, char *bar)
00231 {
00232         str s;
00233 
00234         if (msg->id == last_rr_msg) {
00235                 LM_ERR("Double attempt to record-route\n");
00236                 return -1;
00237         }
00238 
00239         if (key && pv_printf_s(msg, (pv_elem_t*)key, &s)<0) {
00240                 LM_ERR("failed to print the format\n");
00241                 return -1;
00242         }
00243         if ( record_route( msg, key?&s:0 )<0 )
00244                 return -1;
00245 
00246         last_rr_msg = msg->id;
00247         return 1;
00248 }
00249 
00250 
00251 static int w_record_route_preset(struct sip_msg *msg, char *key, char *key2)
00252 {
00253         str s;
00254 
00255         if (msg->id == last_rr_msg) {
00256                 LM_ERR("Duble attempt to record-route\n");
00257                 return -1;
00258         }
00259         if (key2 && !enable_double_rr) {
00260                 LM_ERR("Attempt to double record-route while 'enable_double_rr' param is disabled\n");
00261                 return -1;
00262         }
00263 
00264         if (pv_printf_s(msg, (pv_elem_t*)key, &s)<0) {
00265                 LM_ERR("failed to print the format\n");
00266                 return -1;
00267         }
00268         if ( record_route_preset( msg, &s)<0 )
00269                 return -1;
00270 
00271         if (!key2)
00272                 goto done;
00273 
00274         if (pv_printf_s(msg, (pv_elem_t*)key2, &s)<0) {
00275                 LM_ERR("failed to print the format\n");
00276                 return -1;
00277         }
00278         if ( record_route_preset( msg, &s)<0 )
00279                 return -1;
00280 
00281 done:
00282         last_rr_msg = msg->id;
00283         return 1;
00284 }
00285 
00286 
00290 static int w_record_route_advertised_address(struct sip_msg *msg, char *addr, char *bar)
00291 {
00292         str s;
00293 
00294         if (msg->id == last_rr_msg) {
00295                 LM_ERR("Double attempt to record-route\n");
00296                 return -1;
00297         }
00298 
00299         if (pv_printf_s(msg, (pv_elem_t*)addr, &s) < 0) {
00300                 LM_ERR("failed to print the format\n");
00301                 return -1;
00302         }
00303         if ( record_route_advertised_address( msg, &s ) < 0)
00304                 return -1;
00305 
00306         last_rr_msg = msg->id;
00307         return 1;
00308 }
00309 
00310 
00311 static int w_add_rr_param(struct sip_msg *msg, char *key, char *foo)
00312 {
00313         str s;
00314 
00315         if (pv_printf_s(msg, (pv_elem_t*)key, &s)<0) {
00316                 LM_ERR("failed to print the format\n");
00317                 return -1;
00318         }
00319         return ((add_rr_param( msg, &s)==0)?1:-1);
00320 }
00321 
00322 
00323 
00324 static int w_check_route_param(struct sip_msg *msg,char *re, char *foo)
00325 {
00326         return ((check_route_param(msg,(regex_t*)re)==0)?1:-1);
00327 }
00328 
00329 
00330 
00331 static int w_is_direction(struct sip_msg *msg,char *dir, char *foo)
00332 {
00333         return ((is_direction(msg,(int)(long)dir)==0)?1:-1);
00334 }
00335 
00336 
00337 /*
00338  * Return the URI of the topmost Route-Header.
00339  */
00340 static int
00341 pv_get_route_uri_f(struct sip_msg *msg, pv_param_t *param,
00342                   pv_value_t *res)
00343 {
00344         struct hdr_field* hdr;
00345         rr_t* rt;
00346         str uri;
00347 
00348         if (!msg) {
00349                 LM_ERR("No message?!?\n");
00350                 return -1;
00351         }
00352 
00353         /* Parse the message until the First-Route-Header: */
00354         if (parse_headers(msg, HDR_ROUTE_F, 0) == -1) {
00355                 LM_ERR("while parsing message\n");
00356                 return -1;
00357         }
00358         
00359         if (!msg->route) {
00360                 LM_INFO("No route header present.\n");
00361                 return -1;
00362         }
00363         hdr = msg->route;
00364 
00365         /* Parse the contents of the header: */
00366         if (parse_rr(hdr) == -1) {
00367                 LM_ERR("Error while parsing Route header\n");
00368                 return -1;
00369         }
00370 
00371 
00372         /* Retrieve the Route-Header */ 
00373         rt = (rr_t*)hdr->parsed;
00374         uri = rt->nameaddr.uri;
00375 
00376         return pv_get_strval(msg, param, res, &uri);
00377 }
00378