registration.c

Go to the documentation of this file.
00001 /*
00002  * $Id: registration.c 575 2008-07-28 15:08:20Z vingarzan $
00003  *  
00004  * Copyright (C) 2004-2006 FhG Fokus
00005  *
00006  * This file is part of Open IMS Core - an open source IMS CSCFs & HSS
00007  * implementation
00008  *
00009  * Open IMS Core 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  * For a license to use the Open IMS Core software under conditions
00015  * other than those described here, or to purchase support for this
00016  * software, please contact Fraunhofer FOKUS by e-mail at the following
00017  * addresses:
00018  *     info@open-ims.org
00019  *
00020  * Open IMS Core is distributed in the hope that it will be useful,
00021  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00022  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023  * GNU General Public License for more details.
00024  * 
00025  * It has to be noted that this Open Source IMS Core System is not 
00026  * intended to become or act as a product in a commercial context! Its 
00027  * sole purpose is to provide an IMS core reference implementation for 
00028  * IMS technology testing and IMS application prototyping for research 
00029  * purposes, typically performed in IMS test-beds.
00030  * 
00031  * Users of the Open Source IMS Core System have to be aware that IMS
00032  * technology may be subject of patents and licence terms, as being 
00033  * specified within the various IMS-related IETF, ITU-T, ETSI, and 3GPP
00034  * standards. Thus all Open IMS Core users have to take notice of this 
00035  * fact and have to agree to check out carefully before installing, 
00036  * using and extending the Open Source IMS Core System, if related 
00037  * patents and licences may become applicable to the intended usage 
00038  * context.  
00039  *
00040  * You should have received a copy of the GNU General Public License
00041  * along with this program; if not, write to the Free Software
00042  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00043  * 
00044  */
00045  
00056 #include <time.h>
00057  
00058 #include "registration.h"
00059 
00060 #include "../../data_lump.h"
00061 #include "../../mem/mem.h"
00062 #include "../../locking.h"
00063 #include "../tm/tm_load.h"
00064 #include "mod.h"
00065 #include "sip.h"
00066 #include "registrar.h"
00067 #include "registrar_subscribe.h"
00068 #include "ims_pm_pcscf.h"
00069 #include "e2.h"
00070 #include "e2_avp.h"
00071 
00072 extern struct tm_binds tmb;                         
00074 extern str pcscf_name_str;                          
00075 extern str pcscf_path_hdr_str;                      
00076 extern str pcscf_path_str;                          
00077 extern str pcscf_icid_value_prefix_str;             
00078 extern str pcscf_icid_gen_addr_str;                 
00079 extern str pcscf_orig_ioi_str;                      
00080 extern str pcscf_term_ioi_str;                      
00081 extern unsigned int* pcscf_icid_value_count;        
00082 extern gen_lock_t* pcscf_icid_value_count_lock;     
00084 extern r_hash_slot *registrar;                      
00085 extern int r_hash_size;                             
00088 extern int pcscf_nat_enable;                        
00089 extern int pcscf_use_ipsec;                         
00090 extern int pcscf_use_tls;                           
00091 extern int pcscf_tls_port;                      
00093 extern struct cdp_binds cdpb;       
00094 extern int pcscf_use_e2;
00095 
00104 int P_add_path(struct sip_msg *msg,char *str1,char*str2)
00105 {
00106     str x={0,0};
00107 
00108     STR_PKG_DUP(x,pcscf_path_hdr_str,"pkg");
00109     if (!x.s) return CSCF_RETURN_ERROR;
00110     if (cscf_add_header(msg,&x,HDR_OTHER_T)) return CSCF_RETURN_TRUE;
00111     else {
00112         pkg_free(x.s);
00113         return CSCF_RETURN_ERROR;
00114     }
00115 out_of_memory:
00116     return CSCF_RETURN_ERROR;   
00117 }
00118 
00119 
00120 static str require_hdr={"Require: path\r\n",15};
00129 int P_add_require(struct sip_msg *msg,char *str1,char*str2)
00130 {
00131     str x={0,0};
00132 
00133     STR_PKG_DUP(x,require_hdr,"pkg");
00134     if (!x.s) return CSCF_RETURN_ERROR;
00135     if (cscf_add_header(msg,&x,HDR_OTHER_T)) return CSCF_RETURN_TRUE;
00136     else {
00137         pkg_free(x.s);
00138         return CSCF_RETURN_ERROR;
00139     }
00140 out_of_memory:
00141     return CSCF_RETURN_ERROR;   
00142 }
00143 
00144 
00153 int P_add_p_charging_vector(struct sip_msg *msg,char *str1,char*str2)
00154 {
00155     return cscf_add_p_charging_vector(msg);
00156 }
00157 
00158 
00166 int P_is_integrity_protected(struct sip_msg *msg,char *str1,char *str2)
00167 {
00168     int ret=CSCF_RETURN_FALSE;
00169     struct via_body *vb;
00170     unsigned long s_hash = 0;
00171 
00172 
00173     LOG(L_DBG,"DBG:"M_NAME":P_is_integrity_protected: Looking if registered\n");
00174 //  print_r(L_INFO);
00175     
00176     vb = cscf_get_ue_via(msg);
00177     
00178     LOG(L_DBG,"DBG:"M_NAME":P_is_integrity_protected: Looking for <%d://%.*s:%d,%d>\n",
00179         vb->proto,vb->host.len,vb->host.s,vb->port,msg->rcv.src_port);
00180     if (pcscf_use_tls && msg->rcv.dst_port == pcscf_tls_port){
00181         s_hash = get_tls_session_hash(msg);
00182         if (!s_hash){
00183             LOG(L_ERR,"ERR:"M_NAME":P_is_integrity_protected: Session Hash could not be obtained !\n");
00184             return CSCF_RETURN_FALSE;
00185         }
00186     }
00187     if (r_is_integrity_protected(vb->host,vb->port,msg->rcv.src_port,vb->proto, s_hash)) 
00188         ret = CSCF_RETURN_TRUE;
00189     else 
00190         ret = CSCF_RETURN_FALSE;    
00191     
00192     return ret;
00193 }
00194 
00195 
00196 static str authorization_s={"Authorization: ",15}; 
00197 static str authorization_e={"\r\n",2};
00198 static str integrity_protected_s={", integrity-protected=\"",23};
00199 static str integrity_protected_e={"\"",1};
00207 int P_add_integrity_protected(struct sip_msg *msg,char *str1,char*str2)
00208 {
00209     int r = CSCF_RETURN_FALSE;
00210     str x={0,0};
00211     str v={0,0};
00212     str auth;
00213     int i;
00214     int s=0,e=0;
00215     struct hdr_field *hdr;  
00216     
00217     v.s = str1;
00218     v.len = strlen(str1);
00219     
00220     auth = cscf_get_authorization(msg,&hdr);
00221     if (!auth.len){
00222         LOG(L_INFO,"INF:"M_NAME":P_add_integrity_protected: No authorization header found.\n");
00223         goto done; 
00224     }
00225     
00226     s=auth.len;e=auth.len;
00227     /* first we look for it */
00228     for(i=0;i<auth.len-integrity_protected_s.len;i++)
00229         if (strncasecmp(auth.s+i,integrity_protected_s.s,integrity_protected_s.len)==0){
00230             s = i;
00231             e = i+integrity_protected_s.len;
00232             while(e<auth.len && auth.s[e]!='\"') 
00233                 e++;
00234             if (e<auth.len) e++;
00235             break;          
00236         }
00237     x.len = authorization_s.len+
00238             auth.len - (e-s)+
00239             integrity_protected_s.len+v.len+integrity_protected_e.len+
00240             authorization_e.len;
00241     x.s = pkg_malloc(x.len);
00242     if (!x.s){
00243         LOG(L_ERR, "ERR"M_NAME":P_add_integrity_protected: Error allocating %d bytes\n",
00244             x.len);
00245         x.len=0;
00246         goto error;     
00247     }
00248     x.len=0;
00249     
00250     STR_APPEND(x,authorization_s);
00251     memcpy(x.s+x.len,auth.s,s);
00252     x.len += s;
00253     STR_APPEND(x,integrity_protected_s);
00254     STR_APPEND(x,v);
00255     STR_APPEND(x,integrity_protected_e);
00256     memcpy(x.s+x.len,auth.s+e,auth.len-e);
00257     x.len += auth.len-e;
00258     STR_APPEND(x,authorization_e);
00259 
00260     if (cscf_add_header(msg,&x,HDR_OTHER_T)) r = CSCF_RETURN_TRUE;
00261     else goto error;
00262 
00263 
00264     if (!cscf_del_header(msg,hdr)){
00265         LOG(L_INFO,"INF:"M_NAME":P_add_integrity_protected: Error dropping old authorization header.\n");       
00266         goto error; 
00267     }
00268 
00269 done:
00270     return r;
00271 error:
00272     r = CSCF_RETURN_ERROR;
00273     if (x.s) pkg_free(x.s);
00274     return r;
00275 }
00276 
00277 
00278 
00279 static str p_visited_network_id_s={"P-Visited-Network-ID: ",22};
00280 static str p_visited_network_id_1={", ",2};
00281 static str p_visited_network_id_e={"\r\n",2};
00289 int P_add_p_visited_network_id(struct sip_msg *msg,char *str1,char*str2)
00290 {
00291     int r = CSCF_RETURN_FALSE;
00292     str x={0,0};
00293     str v={0,0};
00294     str old={0,0};
00295     struct hdr_field *hdr;
00296     
00297     v.s = str1;
00298     v.len = strlen(str1);
00299     
00300     old = cscf_get_visited_network_id(msg,&hdr);
00301     
00302     x.len = p_visited_network_id_s.len + old.len + v.len + p_visited_network_id_e.len;
00303     if (old.len) x.len+=p_visited_network_id_1.len;
00304     
00305     x.s = pkg_malloc(x.len);
00306     if (!x.s){
00307         LOG(L_ERR, "ERR"M_NAME":P_add_p_visited_network_id: Error allocating %d bytes\n",
00308             require_hdr.len);
00309         x.len=0;
00310         goto error;     
00311     }
00312     x.len=0;
00313     memcpy(x.s+x.len,p_visited_network_id_s.s,p_visited_network_id_s.len);
00314     x.len += p_visited_network_id_s.len;
00315     
00316     if (old.len) {
00317         memcpy(x.s+x.len,old.s,old.len);
00318         x.len += old.len;
00319         
00320         memcpy(x.s+x.len,p_visited_network_id_1.s,p_visited_network_id_1.len);
00321         x.len += p_visited_network_id_1.len;
00322     }
00323     
00324     memcpy(x.s+x.len,v.s,v.len);
00325     x.len += v.len;
00326 
00327     memcpy(x.s+x.len,p_visited_network_id_e.s,p_visited_network_id_e.len);
00328     x.len += p_visited_network_id_e.len;
00329 
00330         
00331     if (cscf_add_header(msg,&x,HDR_OTHER_T)) r = CSCF_RETURN_TRUE;
00332     else goto error;
00333 
00334     if (!cscf_del_header(msg,hdr)){
00335         LOG(L_INFO,"INF:"M_NAME":P_add_p_visited_network_id: Error dropping old header.\n");        
00336         goto error; 
00337     }
00338     
00339     return r;
00340 error:
00341     r = CSCF_RETURN_ERROR;
00342     if (x.s) pkg_free(x.s);
00343     return r;
00344 }
00345 
00346 static str ck={"ck=\"",4};
00347 static str ik={"ik=\"",4};
00348 static str authenticate_s={"WWW-Authenticate: ",18};
00349 static str authenticate_e={"\r\n",2};
00350 
00358 int P_remove_ck_ik(struct sip_msg *msg,char *str1,char*str2)
00359 {
00360     int r = CSCF_RETURN_FALSE;
00361     str auth,x={0,0};
00362     struct hdr_field *hdr;  
00363     int inString = 0;
00364     int mlen,i;
00365     auth = cscf_get_authenticate(msg,&hdr);
00366     if (!auth.len){
00367         LOG(L_INFO,"INF:"M_NAME":P_remove_ck_ik: No WWW-Authenticate header found.\n");
00368         goto done; 
00369     }
00370     
00371     LOG(L_DBG,"DBG:"M_NAME":P_remove_ck_ik: Original: <%.*s>\n",
00372         auth.len,auth.s);
00373         
00374     x.s = pkg_malloc(authenticate_s.len+auth.len+authenticate_e.len);
00375     if (!x.s){
00376         LOG(L_ERR, "ERR"M_NAME":P_remove_ck_ik: Error allocating %d bytes\n",
00377             x.len);
00378         x.len=0;
00379         goto error;     
00380     }
00381     x.len=0;
00382 
00383     if (ck.len>ik.len) mlen = auth.len - ck.len;
00384     else mlen = auth.len - ik.len;
00385     
00386     STR_APPEND(x,authenticate_s);
00387     i=0;
00388     while(i<auth.len){
00389         if ((auth.s[i] == '\"') &&(i==0||auth.s[i-1]!='\\'))
00390             inString = !inString;
00391 
00392         if (!inString && i<mlen && strncasecmp(auth.s+i,ck.s,ck.len)==0){
00393             i+=ck.len;
00394             while(i<auth.len && auth.s[i]!='\"')
00395              i++;
00396             i++;
00397             while(i<auth.len &&(auth.s[i]==' '||auth.s[i]==','||auth.s[i]=='\t'))
00398              i++;
00399             continue;  
00400         }   
00401         if (!inString && i<mlen && strncasecmp(auth.s+i,ik.s,ik.len)==0){
00402             i+=ik.len;
00403             while(i<auth.len && auth.s[i]!='\"')
00404              i++;
00405             i++;
00406             while(i<auth.len &&(auth.s[i]==' '||auth.s[i]==','||auth.s[i]=='\t'))
00407              i++;
00408             continue;  
00409         }   
00410         x.s[x.len++]=auth.s[i++];   
00411     }       
00412     while(x.len>0 && (x.s[x.len-1]==' '||x.s[x.len-1]==','||x.s[x.len-1]=='\t'))
00413         x.len--;
00414     STR_APPEND(x,authenticate_e);       
00415 
00416     LOG(L_DBG,"DBG:"M_NAME":P_remove_ck_ik: Changed: <%.*s>\n",
00417         x.len,x.s);
00418 
00419     if (!cscf_del_header(msg,hdr)){
00420         LOG(L_INFO,"INF:"M_NAME":P_remove_ck_ik: Error dropping old authorization header.\n");      
00421         goto error; 
00422     }
00423     
00424     if (cscf_add_header(msg,&x,HDR_OTHER_T)) r = CSCF_RETURN_TRUE;
00425     else goto error;
00426 
00427     LOG(L_DBG,"DBG::"M_NAME":P_remove_ck_ik: Final   : <%.*s>\n",
00428         x.len,x.s);
00429 
00430 done:
00431     return r;
00432 error:
00433     r = CSCF_RETURN_ERROR;
00434     if (x.s) pkg_free(x.s);
00435     return r;
00436 }
00437 
00438 
00439 
00440 
00448 int P_is_registered(struct sip_msg *msg,char *str1,char *str2)
00449 {
00450     int ret=CSCF_RETURN_FALSE;
00451     struct via_body *vb;
00452 
00453     LOG(L_INFO,"DBG:"M_NAME":P_is_registered: Looking if registered\n");
00454 //  print_r(L_INFO);
00455 
00456     vb = cscf_get_ue_via(msg);
00457 
00458     
00459     if (vb->port==0) vb->port=5060;
00460     LOG(L_INFO,"DBG:"M_NAME":P_is_registered: Looking for <%d://%.*s:%d>\n",
00461         vb->proto,vb->host.len,vb->host.s,vb->port);
00462     
00463     if (r_is_registered(vb->host,vb->port,vb->proto)) 
00464         ret = CSCF_RETURN_TRUE;
00465     else 
00466         ret = CSCF_RETURN_FALSE;    
00467     
00468     return ret;
00469 }
00470 
00471 
00472 static str p_asserted_identity_s={"P-Asserted-Identity: ",21};
00473 static str p_asserted_identity_m={"<",1};
00474 static str p_asserted_identity_e={">\r\n",3};
00482 int P_assert_identity(struct sip_msg *msg,char *str1,char *str2)
00483 {
00484     int ret=CSCF_RETURN_FALSE;
00485     struct via_body *vb;
00486     struct hdr_field *h=0;
00487     name_addr_t preferred,asserted;
00488     str x={0,0};
00489 
00490     LOG(L_INFO,"INF:"M_NAME":P_assert_identity: Asserting Identity\n");
00491 //  print_r(L_INFO);
00492     
00493     vb = cscf_get_ue_via(msg);
00494     
00495     preferred = cscf_get_preferred_identity(msg,&h);
00496     
00497     LOG(L_INFO,"DBG:"M_NAME":P_assert_identity: Looking for <%d://%.*s:%d> Pref: %.*s\n",
00498         vb->proto,vb->host.len,vb->host.s,vb->port,
00499         preferred.len,preferred.name.s);
00500 
00501     asserted = r_assert_identity(vb->host,vb->port,vb->proto,preferred);
00502     if (!asserted.uri.len){
00503         ret = CSCF_RETURN_FALSE;    
00504     }else{
00505         cscf_del_header(msg,h);
00506         x.len = p_asserted_identity_s.len+asserted.name.len+p_asserted_identity_m.len + 
00507             asserted.uri.len+p_asserted_identity_e.len;
00508         x.s = pkg_malloc(x.len);
00509         if (!x.s){
00510             LOG(L_ERR, "ERR"M_NAME":P_assert_identity: Error allocating %d bytes\n",
00511                 require_hdr.len);
00512             x.len=0;
00513             goto error;     
00514         }
00515         x.len=0;
00516         STR_APPEND(x,p_asserted_identity_s);
00517         STR_APPEND(x,asserted.name);
00518         STR_APPEND(x,p_asserted_identity_m);
00519         STR_APPEND(x,asserted.uri);
00520         STR_APPEND(x,p_asserted_identity_e);
00521         
00522         if (cscf_add_header(msg,&x,HDR_OTHER_T))
00523             ret = CSCF_RETURN_TRUE;
00524         else
00525             ret = CSCF_RETURN_FALSE;    
00526     }
00527     
00528     
00529     return ret;
00530 error:
00531     ret=CSCF_RETURN_ERROR;
00532     return ret; 
00533 }
00534 
00542 int P_assert_called_identity(struct sip_msg *rpl,char *str1,char *str2)
00543 {
00544     int ret=CSCF_RETURN_FALSE;
00545     struct hdr_field *h=0;
00546     str called={0,0},x={0,0};
00547     struct sip_msg *req = cscf_get_request_from_reply(rpl);
00548 
00549     LOG(L_INFO,"INF:"M_NAME":P_assert_called_identity: Asserting Identity\n");
00550 
00551     cscf_get_preferred_identity(rpl,&h);
00552     cscf_del_header(rpl,h);
00553 
00554     if (!req){
00555         LOG(L_INFO,"INF:"M_NAME":P_assert_called_identity: Error finding correspondent request.\n");
00556         goto error;     
00557     }
00558 
00559     called = cscf_get_called_party_id(req,&h);
00560     if (!called.len){
00561         ret = CSCF_RETURN_FALSE;    
00562     }else{
00563         x.len = p_asserted_identity_s.len+p_asserted_identity_m.len+called.len+p_asserted_identity_e.len;
00564         x.s = pkg_malloc(x.len);
00565         if (!x.s){
00566             LOG(L_ERR, "ERR"M_NAME":P_assert_called_identity: Error allocating %d bytes\n",
00567                 require_hdr.len);
00568             x.len=0;
00569             goto error;     
00570         }
00571         x.len=0;
00572         STR_APPEND(x,p_asserted_identity_s);
00573         STR_APPEND(x,p_asserted_identity_m);
00574         STR_APPEND(x,called);
00575         STR_APPEND(x,p_asserted_identity_e);
00576         
00577         if (cscf_add_header(rpl,&x,HDR_OTHER_T))
00578             ret = CSCF_RETURN_TRUE;
00579         else
00580             ret = CSCF_RETURN_FALSE;    
00581     }
00582     
00583     return ret;
00584 error:
00585     ret=CSCF_RETURN_FALSE;
00586     return ret; 
00587 }
00588 
00589 
00590 static str reginfo={"application/reginfo+xml",23};
00601 int P_process_notification(struct sip_msg *msg,char *str1,char *str2)
00602 {
00603     int ret=CSCF_RETURN_FALSE;
00604     str content_type,body;
00605     r_notification *n=0;
00606     int expires;
00607     LOG(L_DBG,"DBG:"M_NAME":P_NOTIFY: Checking NOTIFY\n");
00608     
00609 //  print_r(L_INFO);
00610 
00611     /* check if we received what we should */
00612     if (msg->first_line.type!=SIP_REQUEST) {
00613         LOG(L_ERR,"ERR:"M_NAME":P_NOTIFY: The message is not a request\n");
00614         goto error;
00615     }
00616     if (msg->first_line.u.request.method.len!=6||
00617         memcmp(msg->first_line.u.request.method.s,"NOTIFY",6)!=0)
00618     {
00619         LOG(L_ERR,"ERR:"M_NAME":P_NOTIFY: The method is not a NOTIFY\n");
00620         goto error;     
00621     }
00622 
00623     /* update the subscription state */
00624     expires = cscf_get_subscription_state(msg);
00625     /* treat event */   
00626     content_type = cscf_get_content_type(msg);
00627     if (content_type.len==reginfo.len &&
00628         strncasecmp(content_type.s,reginfo.s,reginfo.len)==0)
00629     {
00630         body.s = get_body(msg);
00631         if (!body.s){
00632             LOG(L_ERR,"ERR:"M_NAME":P_NOTIFY: No body extracted\n");                                    
00633             goto error;
00634         }else{
00635             body.len = cscf_get_content_len(msg);
00636             LOG(L_DBG,"DBG:"M_NAME":P_NOTIFY: Found body: %.*s\n",
00637                 body.len,body.s);
00638             n = r_notification_parse(body);
00639             if (!n){
00640                 LOG(L_DBG,"DBG:"M_NAME":P_NOTIFY: Error parsing XML\n");
00641             }else {             
00642                 #ifdef WITH_IMS_PM
00643                     ims_pm_notify_reg(n,cscf_get_call_id(msg,0),cscf_get_cseq(msg,0));
00644                 #endif              
00645                 if (r_notification_process(n,expires))
00646                     ret = CSCF_RETURN_TRUE;                         
00647                 r_notification_free(n);
00648             }
00649         }
00650     }else{
00651         LOG(L_ERR,"ERR:"M_NAME":P_NOTIFY: The content should be %.*s but it is %.*s\n",
00652             reginfo.len,reginfo.s,content_type.len,content_type.s);
00653         goto error;     
00654     }
00655             
00656             
00657     return ret;
00658 error:
00659     ret=CSCF_RETURN_FALSE;
00660     return ret; 
00661 }
00662 
00663 
00672 int P_mobile_terminating(struct sip_msg *msg,char *str1,char *str2)
00673 {
00674     int ret=CSCF_RETURN_FALSE;
00675     str route={0,0};
00676     int i;
00677     
00678     route = cscf_get_first_route(msg,0);
00679     if (!route.len){
00680         LOG(L_DBG,"DBG:"M_NAME":P_mobile_terminating: No Route header.\n");
00681         goto done;
00682     }
00683     i=0;
00684     while(i<route.len && (route.s[i]==' ' ||route.s[i]=='\t'||route.s[i]=='<'))
00685         i++;
00686     route.s += i;
00687     route.len -= i;
00688     i=0;
00689     while(route.s[i]!=';' && route.s[i]!='>' && i<route.len)
00690         i++;
00691     route.len = i;
00692     
00693     if (route.len == pcscf_path_str.len &&
00694         strncasecmp(route.s,pcscf_path_str.s,pcscf_path_str.len)==0)
00695     {
00696         LOG(L_DBG,"DBG:"M_NAME":P_mobile_terminating: Term indication found.\n");
00697         ret = CSCF_RETURN_TRUE;
00698         goto done;
00699     }else{
00700         LOG(L_DBG,"DBG:"M_NAME":P_mobile_terminating: Term indication not found in <%.*s> as <%.*s>.\n",
00701             route.len,route.s,pcscf_path_str.len,pcscf_path_str.s);
00702     }
00703     
00704     
00705 done:
00706     return ret;
00707 }
00708 
00709 
00718 int P_remove_route(struct sip_msg *msg,char *str1,char *str2)
00719 {
00720     int ret=CSCF_RETURN_FALSE;
00721     str x;
00722     
00723     if (str1 && strlen(str1)){
00724         x.s = str1;
00725         x.len =strlen(str1);
00726         if (cscf_remove_first_route(msg,x)) 
00727             ret = CSCF_RETURN_TRUE;
00728         else 
00729             ret = CSCF_RETURN_FALSE;    
00730     }else{
00731         if (cscf_remove_first_route(msg,pcscf_path_str)+cscf_remove_first_route(msg,pcscf_name_str)) 
00732             ret = CSCF_RETURN_TRUE;
00733         else 
00734             ret = CSCF_RETURN_FALSE;    
00735     }
00736     
00737     return ret;
00738 }
00739 
00740 
00741 
00749 int P_follows_service_routes(struct sip_msg *msg,char *str1,char *str2)
00750 {
00751     int i;
00752     struct hdr_field *hdr=0;
00753     rr_t *r;
00754     struct via_body *vb;
00755     r_contact *c;
00756     struct sip_uri uri;
00757     
00758     vb = cscf_get_ue_via(msg);
00759     
00760     if (vb->port==0) vb->port=5060;
00761     c = get_r_contact(vb->host,vb->port,vb->proto);
00762     if (!c) return CSCF_RETURN_FALSE;
00763 
00764     hdr = cscf_get_next_route(msg,0);
00765     r = 0;
00766     if (!hdr){
00767         if (c->service_route_cnt==0) 
00768             goto ok;
00769         else 
00770             goto nok;
00771     }
00772     r = (rr_t*) hdr->parsed;    
00773     /* first let's skip route pointing to myself */
00774     if (r&&parse_uri(r->nameaddr.uri.s, r->nameaddr.uri.len, &uri)==0 &&
00775         check_self(&uri.host,uri.port_no?uri.port_no:SIP_PORT,0))
00776     {
00777         r = r->next;        
00778         if (!r) {
00779             hdr = cscf_get_next_route(msg,hdr);
00780             if (!hdr){ 
00781                 if (c->service_route_cnt==0) 
00782                     goto ok;
00783                 else 
00784                     goto nok;
00785             }
00786             r = (rr_t*) hdr->parsed;    
00787         }
00788     }
00789     /* then check the others */
00790     
00791     for(i=0;i<c->service_route_cnt;i++){
00792         LOG(L_DBG,"DBG:"M_NAME":P_follows_service_route: mst %.*s\n",
00793             c->service_route[i].len,c->service_route[i].s);     
00794         if (!r) {
00795             hdr = cscf_get_next_route(msg,hdr);
00796             if (!hdr) 
00797                 goto nok;
00798             r = (rr_t*) hdr->parsed;    
00799         }
00800         LOG(L_DBG,"DBG:"M_NAME":P_follows_service_route: src %.*s\n",
00801             r->nameaddr.uri.len,r->nameaddr.uri.s);     
00802         if (r->nameaddr.uri.len==c->service_route[i].len &&
00803                 strncasecmp(r->nameaddr.uri.s,
00804                     c->service_route[i].s,c->service_route[i].len)==0)
00805         {
00806             LOG(L_DBG,"DBG:"M_NAME":P_follows_service_route: src match\n");     
00807         } 
00808         else goto nok; 
00809             
00810         r = r->next;
00811     }
00812     if (r) goto nok;
00813     else
00814         if (cscf_get_next_route(msg,hdr)) goto nok;
00815 
00816 ok:
00817     if (c) r_unlock(c->hash);
00818     return CSCF_RETURN_TRUE;    
00819 nok:
00820     if (c) r_unlock(c->hash);
00821     return CSCF_RETURN_FALSE;   
00822 }
00823 
00824 
00825 static str route_s={"Route: <",8};
00826 static str route_1={">, <",4};
00827 static str route_e={">\r\n",3};
00835 int P_enforce_service_routes(struct sip_msg *msg,char *str1,char*str2)
00836 {
00837     int i;
00838     str newuri={0,0};
00839     struct via_body *vb;
00840     r_contact *c;
00841     str x;
00842         
00843     vb = cscf_get_ue_via(msg);
00844     
00845     if (vb->port==0) vb->port=5060;
00846     
00847     c = get_r_contact(vb->host,vb->port,vb->proto);
00848     if (!c) return CSCF_RETURN_FALSE;
00849     if (!c->service_route_cnt){
00850         r_unlock(c->hash);
00851         return CSCF_RETURN_TRUE;
00852     }
00853 
00854     x.len = route_s.len + route_e.len + (c->service_route_cnt-1)*route_1.len;
00855     for(i=0;i<c->service_route_cnt;i++)
00856         x.len+=c->service_route[i].len;
00857             
00858     x.s = pkg_malloc(x.len);
00859     if (!x.s){
00860         LOG(L_ERR, "ERR:"M_NAME":P_enforce_service_route: Error allocating %d bytes\n",
00861             x.len);
00862         x.len=0;
00863         r_unlock(c->hash);
00864         return CSCF_RETURN_ERROR;
00865     }
00866     x.len=0;
00867     STR_APPEND(x,route_s);
00868     for(i=0;i<c->service_route_cnt;i++){
00869         if (i) STR_APPEND(x,route_1);
00870         STR_APPEND(x,c->service_route[i]);
00871     }   
00872     STR_APPEND(x,route_e);
00873     
00874     newuri.s = pkg_malloc(c->service_route[0].len);
00875     if (!newuri.s){
00876         LOG(L_ERR, "ERR:"M_NAME":P_enforce_service_route: Error allocating %d bytes\n",
00877             c->service_route[0].len);
00878         r_unlock(c->hash);
00879         return CSCF_RETURN_ERROR;
00880     }
00881     newuri.len = c->service_route[0].len;
00882     memcpy(newuri.s,c->service_route[0].s,newuri.len);
00883     msg->dst_uri = newuri;
00884     
00885     //LOG(L_ERR,"%.*s",x.len,x.s);
00886     r_unlock(c->hash);
00887     if (cscf_add_header_first(msg,&x,HDR_ROUTE_T)) {
00888         if (cscf_del_all_headers(msg,HDR_ROUTE_T))
00889             return CSCF_RETURN_TRUE;
00890         else {
00891             LOG(L_ERR,"ERR:"M_NAME":P_enforce_service_route: new Route headers added, but failed to drop old ones.\n");
00892             return CSCF_RETURN_ERROR;
00893         }
00894     }
00895     else {
00896         if (x.s) pkg_free(x.s);
00897         return CSCF_RETURN_ERROR;
00898     }
00899     
00900 }
00901 
00902 
00910 int P_NAT_relay(struct sip_msg * msg, char * str1, char * str2) 
00911 {
00912     str dst={0,0};
00913     int len;
00914     struct ip_addr ip;
00915     unsigned short int port;
00916     r_contact *c=0;
00917     struct dest_info dst_info;
00918     struct cell *t=0;   
00919 
00920     if (!pcscf_nat_enable) return CSCF_RETURN_FALSE;
00921     
00922     if(msg -> first_line.type == SIP_REQUEST) {     
00923         /* on request get the destination from the Request-URI */
00924         struct sip_uri uri;
00925         str req_uri = msg -> first_line.u.request.uri;
00926         
00927         parse_uri(req_uri.s, req_uri.len, &uri);
00928         if(uri.port_no == 0)
00929             uri.port_no=5060;
00930         
00931         c = get_r_contact(uri.host, uri.port_no, uri.proto);
00932         
00933         if(c==NULL || c->pinhole == NULL) {
00934             LOG(L_DBG, "ERR:"M_NAME":P_NAT_relay: we cannot find the pinhole for contact %.*s. Sorry\n", req_uri.len, req_uri.s);
00935             if (c) r_unlock(c->hash);
00936             return CSCF_RETURN_FALSE;
00937         }   
00938         ip = c->pinhole->nat_addr;
00939         port = c->pinhole->nat_port;
00940     } else {
00941         /* on response get the destination from the received addr for the corresponding request */
00942         struct sip_msg *req;
00943         req = cscf_get_request_from_reply(msg);
00944         if(req == NULL) {
00945             LOG(L_ERR, "ERR:"M_NAME":P_NAT_relay: Cannot get request for the transaction\n");
00946             if (c) r_unlock(c->hash);
00947             return CSCF_RETURN_FALSE;
00948         }       
00949         ip = req->rcv.src_ip;
00950         port = req->rcv.src_port;   
00951     }
00952 
00953     switch(ip.af){
00954         case AF_INET:
00955             if (ip.len<4) break;
00956             len = 4 /* sip: */ + 4 * ip.len /* ip address */ + 1 /* : */ + 6 /* port */;
00957             dst.s = pkg_malloc(len);
00958             if (!dst.s){
00959                 LOG(L_ERR, "ERR:"M_NAME":P_NAT_relay: Error allocating %d bytes\n", len);                   
00960                 if (c) r_unlock(c->hash);
00961                 return CSCF_RETURN_FALSE;
00962             }
00963             dst.len = sprintf(dst.s, "sip:%d.%d.%d.%d:%d", ip.u.addr[0],ip.u.addr[1],ip.u.addr[2],ip.u.addr[3],port);       
00964             break;
00965         case AF_INET6:
00966             if (ip.len<16) break;
00967             len = 5 /* sip:[ */ + 2 * ip.len /* ip address */ + 7/*:*/ + 2/* ]: */ + 6 /* port */;
00968             dst.s = pkg_malloc(len);
00969             if (!dst.s){
00970                 LOG(L_ERR, "ERR:"M_NAME":P_NAT_relay: Error allocating %d bytes\n", len);                   
00971                 if (c) r_unlock(c->hash);
00972                 return CSCF_RETURN_FALSE;
00973             }
00974             dst.len = sprintf(dst.s, "sip:[%.02x%.02x:%.02x%.02x:%.02x%.02x:%.02x%.02x:%.02x%.02x:%.02x%.02x:%.02x%.02x:%.02x%.02x]:%d", 
00975                 ip.u.addr[0],
00976                 ip.u.addr[1],
00977                 ip.u.addr[2],
00978                 ip.u.addr[3],
00979                 ip.u.addr[4],
00980                 ip.u.addr[5],
00981                 ip.u.addr[6],
00982                 ip.u.addr[7],
00983                 ip.u.addr[8],
00984                 ip.u.addr[9],
00985                 ip.u.addr[10],
00986                 ip.u.addr[11],
00987                 ip.u.addr[12],
00988                 ip.u.addr[13],
00989                 ip.u.addr[14],
00990                 ip.u.addr[15],
00991                 port);          
00992             break;
00993     }
00994             
00995 
00996     if (c) r_unlock(c->hash);
00997     
00998     if (msg->dst_uri.s) pkg_free(msg->dst_uri.s);
00999     msg -> dst_uri = dst;
01000 
01001     if (msg -> first_line.type == SIP_REPLY) {
01002         /* on reply we have to modify the t->uas->response->dst.to.sin.sin_port/sin_addr */
01003         t = tmb.t_gett();
01004         if (!t){
01005             LOG(L_INFO, "INFO:"M_NAME":P_NAT_relay: Can't relay non-transactional responses\n");        
01006             return CSCF_RETURN_FALSE;   /* error */
01007         }
01008 #ifdef USE_DNS_FAILOVER
01009         if (!uri2dst(0,&dst_info, msg, &msg->dst_uri, PROTO_NONE)) {
01010 #else
01011         if (!uri2dst(&dst_info, msg, &msg->dst_uri, PROTO_NONE)) {
01012 #endif
01013             LOG(L_INFO, "INFO:"M_NAME":P_NAT_relay: Error setting uri as dst <%.*s>\n", msg -> dst_uri.len, msg -> dst_uri.s);      
01014             return CSCF_RETURN_FALSE;   /* error */
01015         }
01016         t->uas.response.dst = dst_info;
01017     }   
01018         
01019     LOG(L_INFO, "INFO:"M_NAME":P_NAT_relay: <%.*s>\n", msg -> dst_uri.len, msg -> dst_uri.s);
01020     return CSCF_RETURN_TRUE;
01021 }
01022 
01023 
01024 
01025 static str sip_s={"sip:",4};
01033 int P_security_relay(struct sip_msg * msg, char * str1, char * str2) 
01034 {
01035     str dst={0,0};
01036     int len;
01037     r_contact *c=0;
01038     int proto, port;
01039     str host;
01040     struct dest_info dst_info;
01041     struct cell *t=0;
01042     struct sip_msg *req = 0;
01043 
01044     if (!pcscf_use_ipsec && !pcscf_use_tls) return CSCF_RETURN_FALSE;
01045 
01046     if(msg -> first_line.type == SIP_REQUEST) {
01047         /* on request, get the destination from the Request-URI */
01048         struct sip_uri uri;
01049         str req_uri = msg->first_line.u.request.uri;
01050         if (parse_uri(req_uri.s,req_uri.len,&uri)<0){
01051             LOG(L_ERR, "ERR:"M_NAME":P_security_relay: Error parsing Request-URI: <%.*s>\n",req_uri.len,req_uri.s);
01052             return CSCF_RETURN_FALSE;
01053         }
01054         if (uri.port_no==0) uri.port_no =5060;
01055         proto = uri.proto;
01056         host = uri.host;        
01057         port = uri.port_no;
01058     } else {
01059         /* On response get the source from the first via in the corresponding request */
01060         struct via_body *vb;
01061         req = cscf_get_request_from_reply(msg);
01062         if(req == NULL) {
01063             LOG(L_ERR, "ERR:"M_NAME":P_security_relay: Cannot get request for the transaction\n");
01064             return CSCF_RETURN_FALSE;
01065         }
01066         vb = cscf_get_ue_via(req);  
01067         if (vb->port==0) vb->port=5060;
01068         proto = vb->proto;
01069         host = vb->host;        
01070         port = vb->port;
01071     }
01072     
01073     len = sip_s.len + host.len + 1 /* : */ + 6 /* port */+ 14 /*;transport=tls"*/;
01074     dst.s = pkg_malloc(len);
01075     if (!dst.s){
01076         LOG(L_ERR, "ERR:"M_NAME":P_security_relay: Error allocating %d bytes\n", len);
01077         dst.len=0;
01078         r_unlock(c->hash);
01079         return CSCF_RETURN_FALSE;
01080     }   
01081     STR_APPEND(dst,sip_s);
01082     STR_APPEND(dst,host);
01083 
01084     if (msg -> first_line.type != SIP_REQUEST && req->rcv.dst_port == pcscf_tls_port  && pcscf_use_tls)
01085     {
01086         dst.len += sprintf(dst.s + dst.len, ":%d;transport=tls", req->rcv.src_port);
01087     }   
01088     else {
01089         c = get_r_contact(host,port,proto);
01090         if (!c || !c->security || c->security->type==SEC_NONE) {
01091             LOG(L_DBG, "ERR:"M_NAME":P_security_relay: we cannot find the contact or its IPSec/TLS SAs for <%d://%.*s:%d>.\n", 
01092                 proto,host.len,host.s,port);
01093             if (c) r_unlock(c->hash);
01094             if (dst.s)
01095                 pkg_free(dst.s);
01096             return CSCF_RETURN_FALSE;
01097         }                   
01098     
01099         switch (c->security->type){
01100             case SEC_NONE:
01101                 break;
01102             case SEC_IPSEC:
01103                 if (pcscf_use_ipsec && c->security->data.ipsec) 
01104                     dst.len += sprintf(dst.s + dst.len, ":%d", c->security->data.ipsec->port_us);
01105                 else dst.len += sprintf(dst.s + dst.len, ":%d", port);
01106                 break;
01107             case SEC_TLS:
01108                 if (!pcscf_use_tls){
01109                     r_unlock(c->hash);
01110                     if (dst.s)
01111                         pkg_free(dst.s);
01112                 }
01113                 if(msg -> first_line.type != SIP_REQUEST) {
01114                     // request received on other port
01115                     if (req->rcv.dst_port != pcscf_tls_port )  
01116                     {
01117                         r_unlock(c->hash);
01118                         if (dst.s)
01119                             pkg_free(dst.s);
01120                         return CSCF_RETURN_FALSE;
01121                     }
01122                 }
01123                 dst.len += sprintf(dst.s + dst.len, ":%d;transport=tls", c->security->data.tls->port_tls);
01124                 break;
01125         }   
01126         r_unlock(c->hash);
01127     }
01128     
01129     if (msg->dst_uri.s) pkg_free(msg->dst_uri.s);
01130     msg -> dst_uri = dst;
01131     
01132     if (msg -> first_line.type == SIP_REPLY) {
01133         /* on reply we have to modify the t->uas->response->dst.to.sin.sin_port/sin_addr */
01134         t = tmb.t_gett();
01135         if (!t){
01136             LOG(L_INFO, "INFO:"M_NAME":P_security_relay: Can't relay non-transactional responses\n");       
01137             return CSCF_RETURN_FALSE;   /* error */
01138         }
01139 #ifdef USE_DNS_FAILOVER
01140         if (!uri2dst(0,&dst_info, msg, &msg->dst_uri, PROTO_NONE)) {
01141 #else
01142         if (!uri2dst(&dst_info, msg, &msg->dst_uri, PROTO_NONE)) {
01143 #endif
01144             LOG(L_INFO, "INFO:"M_NAME":P_security_relay: Error setting uri as dst <%.*s>\n", msg -> dst_uri.len, msg -> dst_uri.s);     
01145             return CSCF_RETURN_FALSE;   /* error */
01146         }
01147         t->uas.response.dst = dst_info;
01148     }   
01149     LOG(L_INFO, "INFO:"M_NAME":P_security_relay: <%.*s>\n", msg -> dst_uri.len, msg -> dst_uri.s);
01150     return CSCF_RETURN_TRUE;
01151 }
01152 
01153 
01154 static str str_a_location_info = {"; dsl-location=",15}; 
01155 static str str_p_access_network_info={"P-Access-Network-Info",21};
01156  
01164 int P_access_network_info(struct sip_msg *req,char *str1,char *str2)
01165 {
01166     struct hdr_field *h=0;
01167