00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
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
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
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
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
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
00610
00611
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
00624 expires = cscf_get_subscription_state(msg);
00625
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
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
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
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
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
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 + 4 * ip.len + 1 + 6 ;
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 + 2 * ip.len + 7 + 2 + 6 ;
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
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;
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;
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
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
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 + 14 ;
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
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
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;
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;
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