topoh_mod.c

Go to the documentation of this file.
00001 
00036 #include <stdio.h>
00037 #include <string.h>
00038 #include <stdlib.h>
00039 #include <unistd.h>
00040 
00041 #include "../../sr_module.h"
00042 #include "../../events.h"
00043 #include "../../dprint.h"
00044 #include "../../tcp_options.h"
00045 #include "../../ut.h"
00046 #include "../../forward.h"
00047 #include "../../parser/msg_parser.h"
00048 #include "../../parser/parse_to.h"
00049 #include "../../parser/parse_from.h"
00050 
00051 #include "../../modules/sanity/api.h"
00052 
00053 #include "th_mask.h"
00054 #include "th_msg.h"
00055 
00056 MODULE_VERSION
00057 
00058 
00060 str _th_key = { "aL9.n8~Hm]Z", 0 };
00061 str th_cookie_name = {"TH", 0};
00062 str th_cookie_value = {0, 0};
00063 str th_ip = {"10.1.1.10", 0};
00064 str th_uparam_name = {"line", 0};
00065 str th_uparam_prefix = {"sr-", 0};
00066 str th_vparam_name = {"branch", 0};
00067 str th_vparam_prefix = {"z9hG4bKsr-", 0};
00068 
00069 str th_callid_prefix = {"!!:", 3};
00070 str th_via_prefix = {0, 0};
00071 str th_uri_prefix = {0, 0};
00072 
00073 int th_param_mask_callid = 0;
00074 
00075 int th_sanity_checks = 0;
00076 sanity_api_t scb;
00077 
00078 int th_msg_received(void *data);
00079 int th_msg_sent(void *data);
00080 
00082 static int mod_init(void);
00083 
00084 static param_export_t params[]={
00085         {"mask_key",            STR_PARAM, &_th_key.s},
00086         {"mask_ip",                     STR_PARAM, &th_ip.s},
00087         {"mask_callid",         INT_PARAM, &th_param_mask_callid},
00088         {"uparam_name",         STR_PARAM, &th_uparam_name.s},
00089         {"uparam_prefix",       STR_PARAM, &th_uparam_prefix.s},
00090         {"vparam_name",         STR_PARAM, &th_vparam_name.s},
00091         {"vparam_prefix",       STR_PARAM, &th_vparam_prefix.s},
00092         {"callid_prefix",       STR_PARAM, &th_callid_prefix.s},
00093         {"sanity_checks",       INT_PARAM, &th_sanity_checks},
00094         {0,0,0}
00095 };
00096 
00097 
00099 struct module_exports exports= {
00100         "topoh",
00101         DEFAULT_DLFLAGS, /* dlopen flags */
00102         0,
00103         params,
00104         0,          /* exported statistics */
00105         0,          /* exported MI functions */
00106         0,          /* exported pseudo-variables */
00107         0,          /* extra processes */
00108         mod_init,   /* module initialization function */
00109         0,
00110         0,
00111         0           /* per-child init function */
00112 };
00113 
00117 static int mod_init(void)
00118 {
00119         if(th_sanity_checks!=0)
00120         {
00121                 if(sanity_load_api(&scb)<0)
00122                 {
00123                         LM_ERR("cannot bind to sanity module\n");
00124                         goto error;
00125                 }
00126         }
00127         th_cookie_name.len = strlen(th_cookie_name.s);
00128         th_ip.len = strlen(th_ip.s);
00129         if(th_ip.len<=0)
00130         {
00131                 LM_ERR("mask IP parameter is invalid\n");
00132                 goto error;
00133         }
00134         if(check_self(&th_ip, 0, 0)==1)
00135         {
00136                 LM_ERR("mask IP must be different than SIP server local IP\n");
00137                 goto error;
00138         }
00139         th_uparam_name.len = strlen(th_uparam_name.s);
00140         th_uparam_prefix.len = strlen(th_uparam_prefix.s);
00141         th_vparam_name.len = strlen(th_vparam_name.s);
00142         th_vparam_prefix.len = strlen(th_vparam_prefix.s);
00143         th_callid_prefix.len = strlen(th_callid_prefix.s);
00144 
00145         /* 'SIP/2.0/UDP ' + ip + ';' + param + '=' + prefix (+ '\0') */
00146         th_via_prefix.len = 12 + th_ip.len + 1 + th_vparam_name.len + 1
00147                 + th_vparam_prefix.len;
00148         th_via_prefix.s = (char*)pkg_malloc(th_via_prefix.len+1);
00149         if(th_via_prefix.s==NULL)
00150         {
00151                 LM_ERR("via prefix parameter is invalid\n");
00152                 goto error;
00153         }
00154         /* 'sip:' + ip + ';' + param + '=' + prefix (+ '\0') */
00155         th_uri_prefix.len = 4 + th_ip.len + 1 + th_uparam_name.len + 1
00156                 + th_uparam_prefix.len;
00157         th_uri_prefix.s = (char*)pkg_malloc(th_uri_prefix.len+1);
00158         if(th_uri_prefix.s==NULL)
00159         {
00160                 LM_ERR("uri prefix parameter is invalid\n");
00161                 goto error;
00162         }
00163         /* build via prefix */
00164         memcpy(th_via_prefix.s, "SIP/2.0/UDP ", 12);
00165         memcpy(th_via_prefix.s+12, th_ip.s, th_ip.len);
00166         th_via_prefix.s[12+th_ip.len] = ';';
00167         memcpy(th_via_prefix.s+12+th_ip.len+1, th_vparam_name.s,
00168                         th_vparam_name.len);
00169         th_via_prefix.s[12+th_ip.len+1+th_vparam_name.len] = '=';
00170         memcpy(th_via_prefix.s+12+th_ip.len+1+th_vparam_name.len+1,
00171                         th_vparam_prefix.s, th_vparam_prefix.len);
00172         th_via_prefix.s[th_via_prefix.len] = '\0';
00173         LM_DBG("VIA prefix: [%s]\n", th_via_prefix.s);
00174         /* build uri prefix */
00175         memcpy(th_uri_prefix.s, "sip:", 4);
00176         memcpy(th_uri_prefix.s+4, th_ip.s, th_ip.len);
00177         th_uri_prefix.s[4+th_ip.len] = ';';
00178         memcpy(th_uri_prefix.s+4+th_ip.len+1, th_uparam_name.s, th_uparam_name.len);
00179         th_uri_prefix.s[4+th_ip.len+1+th_uparam_name.len] = '=';
00180         memcpy(th_uri_prefix.s+4+th_ip.len+1+th_uparam_name.len+1,
00181                         th_uparam_prefix.s, th_uparam_prefix.len);
00182         th_uri_prefix.s[th_uri_prefix.len] = '\0';
00183         LM_DBG("URI prefix: [%s]\n", th_uri_prefix.s);
00184 
00185         th_mask_init();
00186         sr_event_register_cb(SREV_NET_DATA_IN, th_msg_received);
00187         sr_event_register_cb(SREV_NET_DATA_OUT, th_msg_sent);
00188 #ifdef USE_TCP
00189         tcp_set_clone_rcvbuf(1);
00190 #endif
00191         return 0;
00192 error:
00193         return -1;
00194 }
00195 
00199 int th_prepare_msg(sip_msg_t *msg)
00200 {
00201         if (parse_msg(msg->buf, msg->len, msg)!=0)
00202         {
00203                 LM_DBG("outbuf buffer parsing failed!");
00204                 return 1;
00205         }
00206 
00207         if (parse_headers(msg, HDR_EOH_F, 0)==-1)
00208         {
00209                 LM_DBG("parsing headers failed");
00210                 return 2;
00211         }
00212 
00213         if(parse_from_header(msg)<0)
00214         {
00215                 LM_ERR("cannot parse FROM header\n");
00216                 return 3;
00217         }
00218         
00219         return 0;
00220 }
00221 
00225 int th_msg_received(void *data)
00226 {
00227         sip_msg_t msg;
00228         str *obuf;
00229         char *nbuf = NULL;
00230         int direction;
00231         int dialog;
00232 
00233         obuf = (str*)data;
00234         memset(&msg, 0, sizeof(sip_msg_t));
00235         msg.buf = obuf->s;
00236         msg.len = obuf->len;
00237 
00238         if(th_prepare_msg(&msg)!=0)
00239         {
00240                 goto done;
00241         }
00242 
00243         if(th_skip_msg(&msg))
00244         {
00245                 goto done;
00246         }
00247 
00248         direction = 0;
00249         th_cookie_value.s = "xx";
00250         th_cookie_value.len = 2;
00251         if(msg.first_line.type==SIP_REQUEST)
00252         {
00253                 if(th_sanity_checks!=0)
00254                 {
00255                         if(scb.check_defaults(&msg)<1)
00256                         {
00257                                 LM_ERR("sanity checks failed\n");
00258                                 goto done;
00259                         }
00260                 }
00261                 dialog = (get_to(&msg)->tag_value.len>0)?1:0;
00262                 if(dialog)
00263                 {
00264                         direction = th_route_direction(&msg);
00265                         if(direction<0)
00266                         {
00267                                 LM_ERR("not able to detect direction\n");
00268                                 goto done;
00269                         }
00270                         th_cookie_value.s = (direction==0)?"dc":"uc";
00271                 } else {
00272                         th_cookie_value.s = "di";
00273                 }
00274                 if(dialog)
00275                 {
00276                         /* dialog request */
00277                         th_unmask_ruri(&msg);
00278                         th_unmask_route(&msg);
00279                         th_unmask_refer_to(&msg);
00280                         if(direction==1)
00281                         {
00282                                 th_unmask_callid(&msg);
00283                         }
00284                 }
00285         } else {
00286                 /* reply */
00287                 th_unmask_via(&msg, &th_cookie_value);
00288                 th_flip_record_route(&msg, 0);
00289                 if(th_cookie_value.s[0]=='u')
00290                 {
00291                         th_cookie_value.s = "dc";
00292                 } else {
00293                         th_cookie_value.s = "uc";
00294                         th_unmask_callid(&msg);
00295                 }
00296                 th_cookie_value.len = 2;
00297         }
00298 
00299         th_add_cookie(&msg);
00300         nbuf = th_msg_update(&msg, (unsigned int*)&obuf->len);
00301 
00302         if(obuf->len>=BUF_SIZE)
00303         {
00304                 LM_ERR("new buffer overflow (%d)\n", obuf->len);
00305                 pkg_free(nbuf);
00306                 return -1;
00307         }
00308         memcpy(obuf->s, nbuf, obuf->len);
00309         obuf->s[obuf->len] = '\0';
00310 
00311 done:
00312         if(nbuf!=NULL)
00313                 pkg_free(nbuf);
00314         free_sip_msg(&msg);
00315         return 0;
00316 }
00317 
00321 int th_msg_sent(void *data)
00322 {
00323         sip_msg_t msg;
00324         str *obuf;
00325         int direction;
00326         int dialog;
00327         int local;
00328 
00329         obuf = (str*)data;
00330         memset(&msg, 0, sizeof(sip_msg_t));
00331         msg.buf = obuf->s;
00332         msg.len = obuf->len;
00333 
00334         if(th_prepare_msg(&msg)!=0)
00335         {
00336                 goto done;
00337         }
00338 
00339         if(th_skip_msg(&msg))
00340         {
00341                 goto done;
00342         }
00343 
00344         th_cookie_value.s = th_get_cookie(&msg, &th_cookie_value.len);
00345         LM_DBG("the COOKIE is [%.*s]\n", th_cookie_value.len, th_cookie_value.s);
00346         if(th_cookie_value.s[0]!='x')
00347                 th_del_cookie(&msg);
00348         if(msg.first_line.type==SIP_REQUEST)
00349         {
00350                 direction = (th_cookie_value.s[0]=='u')?1:0; /* upstream/downstram */
00351                 dialog = (get_to(&msg)->tag_value.len>0)?1:0;
00352                 local = (th_cookie_value.s[0]!='d'&&th_cookie_value.s[0]!='u')?1:0;
00353                 /* local generated requests */
00354                 if(local)
00355                 {
00356                         /* ACK and CANCEL go downstream */
00357                         if(get_cseq(&msg)->method_id==METHOD_ACK
00358                                         || get_cseq(&msg)->method_id==METHOD_CANCEL)
00359                         {
00360                                 th_mask_callid(&msg);
00361                                 goto ready;
00362                         } else {
00363                                 /* should be for upstream */
00364                                 goto done;
00365                         }
00366                 }
00367                 th_mask_via(&msg);
00368                 th_mask_contact(&msg);
00369                 th_mask_record_route(&msg);
00370                 if(dialog)
00371                 {
00372                         /* dialog request */
00373                         if(direction==0)
00374                         {
00375                                 /* downstream */
00376                                 th_mask_callid(&msg);
00377                         }
00378                 } else {
00379                         /* initial request */
00380                         th_update_hdr_replaces(&msg);
00381                         th_mask_callid(&msg);
00382                 }
00383         } else {
00384                 /* reply */
00385                 if(th_cookie_value.s[th_cookie_value.len-1]=='x')
00386                 {
00387                         /* ?!?! - we should have a cookie in any reply case */
00388                         goto done;
00389                 }
00390                 if(th_cookie_value.s[th_cookie_value.len-1]=='v')
00391                 {
00392                         /* reply generated locally - direction was set by request */
00393                         if(th_cookie_value.s[0]=='u')
00394                         {
00395                                 th_mask_callid(&msg);
00396                         }
00397                 } else {
00398                         th_flip_record_route(&msg, 1);
00399                         th_mask_contact(&msg);
00400                         if(th_cookie_value.s[0]=='d')
00401                         {
00402                                 th_mask_callid(&msg);
00403                         }
00404                 }
00405         }
00406 
00407 ready:
00408         obuf->s = th_msg_update(&msg, (unsigned int*)&obuf->len);
00409 
00410 done:
00411         free_sip_msg(&msg);
00412         return 0;
00413 }
00414