317 lines
10 KiB
INI
317 lines
10 KiB
INI
######################################################################
|
|
# Route for handling Registrations:
|
|
######################################################################
|
|
route[REGISTER] {
|
|
# Provide some statistics
|
|
if ($sht(a=>$ci::start_time) == $null || $sht(a=>$ci::start_time) == 0) {
|
|
$sht(a=>$ci::start_time) = $TV(Sn);
|
|
}
|
|
xnotice("PCSCF REGISTER: \n Destination URI: $du\n Request URI: $ru\n");
|
|
xnotice("Source IP and Port: ($si:$sp)\n Route-URI: $route_uri\n");
|
|
xnotice("Received IP and Port: ($Ri:$Rp)\n");
|
|
xnotice("Contact header: $ct\n");
|
|
|
|
# Strip Transport from RURI:
|
|
$ru = $(ru{re.subst,/;transport=[A-Za-z]*//g});
|
|
|
|
if (is_present_hf("Contact")) {
|
|
pcscf_save_pending("location");
|
|
} else {
|
|
send_reply("403", "No contact header");
|
|
exit;
|
|
}
|
|
|
|
#!ifdef WITH_IPSEC
|
|
$sht(ipsec_clients=>$(ct{nameaddr.uri})) = $null;
|
|
if ($hdr(Security-Client) =~ ".*ipsec-3gpp.*") {
|
|
$sht(ipsec_clients=>$(ct{nameaddr.uri})) = 1;
|
|
}
|
|
#!endif
|
|
|
|
# Strip additional Tags from RURI:
|
|
if ($rU == $null)
|
|
$ru = "sip:"+$rd;
|
|
else
|
|
$ru = "sip:"+$rU+"@"+$rd;
|
|
|
|
#!ifdef WITH_RX
|
|
if ($expires(min) != 0) {
|
|
xlog("L_DBG","Subscribing to signalling bearer status\n");
|
|
|
|
Rx_AAR_Register("REG_AAR_REPLY", "location");
|
|
switch ($retcode) {
|
|
case -1:
|
|
# There was an error sending the AAR-Request:
|
|
xlog("L_ERR", "Diameter: AAR failed on subscription to signalling\n");
|
|
send_reply("403", "Can't register to QoS for signalling");
|
|
exit;
|
|
break;
|
|
case 0:
|
|
# We are waiting for an async reply, just exit here.
|
|
exit;
|
|
break;
|
|
case 1:
|
|
# We did not need to send AAR, so just continue as normal
|
|
route(REGISTER_CONTINUE);
|
|
break;
|
|
}
|
|
} else {
|
|
# Proceed with Registering:
|
|
route(REGISTER_CONTINUE);
|
|
}
|
|
exit;
|
|
}
|
|
|
|
route[REG_AAR_REPLY] {
|
|
switch ($avp(s:aar_return_code)) {
|
|
case 1:
|
|
xlog("L_DBG", "Diameter: AAR success on subscription to signalling\n");
|
|
break;
|
|
default:
|
|
xlog("L_ERR", "Diameter: AAR failed on subscription to signalling\n");
|
|
send_reply("403", "Can't register to QoS for signalling");
|
|
exit;
|
|
}
|
|
# Proceed with Registering:
|
|
route(REGISTER_CONTINUE);
|
|
}
|
|
|
|
route[REGISTER_CONTINUE] {
|
|
#!endif
|
|
append_hf("Path: <sip:term@HOSTNAME;lr>\r\n");
|
|
|
|
remove_hf("Supported");
|
|
append_hf("Supported: path\r\n");
|
|
remove_hf("Require");
|
|
append_hf("Require: path\r\n");
|
|
|
|
# Add a visited Network-ID-Header:
|
|
if (is_present_hf("P-Visited-Network-ID")) {
|
|
$var(new_hdr) = "NETWORKNAME, "+$hdr(P-Visited-Network-ID);
|
|
append_hf("P-Visited-Network-ID: $var(new_hdr)\r\n");
|
|
} else {
|
|
append_hf("P-Visited-Network-ID: NETWORKNAME\r\n");
|
|
}
|
|
#!ifdef WITH_SBC
|
|
#!ifndef WITH_SBC_CALL
|
|
t_on_failure("SBC_failure");
|
|
# Choose an SBC to send the call to:
|
|
if (!ds_select_dst(DISPATCHER_LIST_SBC, "4")) {
|
|
send_reply("503", "Service Unavailable (SBC failure)");
|
|
exit;
|
|
}
|
|
#!else
|
|
t_on_failure("REGISTER_failure");
|
|
#!endif
|
|
#!else
|
|
t_on_failure("REGISTER_failure");
|
|
#!endif
|
|
t_on_reply("REGISTER_reply");
|
|
# Forward request:
|
|
route(RELAY);
|
|
exit;
|
|
}
|
|
|
|
# Replies for REGISTER requests:
|
|
######################################################################
|
|
onreply_route[REGISTER_reply]
|
|
{
|
|
#!ifdef WITH_IMS_HDR_CACHE
|
|
if (is_present_hf("Service-Route")) {
|
|
$sht(serviceroutes=>$ci) = $hdr(Service-Route);
|
|
} else {
|
|
if ($sht(serviceroutes=>$ci) != $null) {
|
|
append_hf("Service-Route: $sht(serviceroutes=>$ci)\r\n");
|
|
msg_apply_changes();
|
|
}
|
|
}
|
|
if (is_present_hf("P-Associated-URI")) {
|
|
$sht(associateduris=>$ci) = $hdr(P-Associated-URI);
|
|
} else {
|
|
if ($sht(associateduris=>$ci) != $null) {
|
|
append_hf("P-Associated-URI: $sht(associateduris=>$ci)\r\n");
|
|
msg_apply_changes();
|
|
}
|
|
}
|
|
#!endif
|
|
|
|
if (t_check_status("200")) {
|
|
#!ifdef WITH_IPBLOCK
|
|
$sht(failedauth=>$T_req($si)) = $null;
|
|
#!endif
|
|
pcscf_save("location");
|
|
|
|
#!ifdef WITH_NATPING
|
|
#!ifdef WITH_PING_UDP
|
|
#if ($T_req($pr) == "udp") {
|
|
if ($pr == "udp") {
|
|
sht_lock("natping=>natpinglock");
|
|
if ($(T_req($hdr(Security-Client))) =~ ".*ipsec-3gpp.*") {
|
|
$var(sec_client) = $(T_req($hdr(Security-Client)));
|
|
xnotice("Security-Client=$var(sec_client)\n");
|
|
$var(sc_port_c) = $(var(sec_client){re.subst,/.*port-c=([0-9]*).*$/\1/s});
|
|
xnotice("port-c=$var(sc_port_c)\n");
|
|
$var(sc_port_s) = $(var(sec_client){re.subst,/.*port-s=([0-9]*).*$/\1/s});
|
|
xnotice("port-s=$var(sc_port_s)\n");
|
|
$var(ouri) = "sip:"+$T_req($si)+":"+$var(sc_port_s);
|
|
} else {
|
|
$var(ouri) = "sip:"+$T_req($si)+":"+$T_req($sp);
|
|
}
|
|
$sht(natping=>$var(ouri)) = $(T_req($ct){nameaddr.uri});
|
|
sht_unlock("natping=>natpinglock");
|
|
|
|
sht_lock("natpingfrom=>natpingfromlock");
|
|
if ($(T_req($hdr(Security-Verify))) =~ ".*ipsec-3gpp.*") {
|
|
$var(sec_verify) = $(T_req($hdr(Security-Verify)));
|
|
xnotice("Security-Verify=$var(sec_verify)\n");
|
|
$var(sv_port_c) = $(var(sec_verify){re.subst,/.*port-c=([0-9]*).*$/\1/s});
|
|
xnotice("port-c=$var(sv_port_c)\n");
|
|
$var(sv_port_s) = $(var(sec_verify){re.subst,/.*port-s=([0-9]*).*$/\1/s});
|
|
xnotice("port-s=$var(sv_port_s)\n");
|
|
|
|
$sht(natpingfrom=>$var(ouri)) = "udp:"+$T_req($Ri)+":"+$var(sv_port_c);
|
|
} else {
|
|
$sht(natpingfrom=>$var(ouri)) = "udp:"+$T_req($Ri)+":"+$T_req($Rp);
|
|
}
|
|
sht_unlock("natpingfrom=>natpingfromlock");
|
|
}
|
|
#!endif
|
|
#!ifdef WITH_PING_TCP
|
|
#if ($T_req($pr) == "tcp") {
|
|
if ($pr == "tcp") {
|
|
sht_lock("natping=>natpinglock");
|
|
if ($(T_req($hdr(Security-Client))) =~ ".*ipsec-3gpp.*") {
|
|
$var(sec_client) = $(T_req($hdr(Security-Client)));
|
|
xnotice("Security-Client=$var(sec_client)\n");
|
|
$var(sc_port_c) = $(var(sec_client){re.subst,/.*port-c=([0-9]*).*$/\1/s});
|
|
xnotice("port-c=$var(sc_port_c)\n");
|
|
$var(sc_port_s) = $(var(sec_client){re.subst,/.*port-s=([0-9]*).*$/\1/s});
|
|
xnotice("port-s=$var(sc_port_s)\n");
|
|
$var(ouri) = "sip:"+$T_req($si)+":"+$var(sc_port_s)+";transport=tcp";
|
|
} else {
|
|
$var(ouri) = "sip:"+$T_req($si)+":"+$T_req($sp)+";transport=tcp";
|
|
}
|
|
$sht(natping=>$var(ouri)) = $(T_req($ct){nameaddr.uri});
|
|
sht_unlock("natping=>natpinglock");
|
|
|
|
sht_lock("natpingfrom=>natpingfromlock");
|
|
if ($(T_req($hdr(Security-Verify))) =~ ".*ipsec-3gpp.*") {
|
|
$var(sec_verify) = $(T_req($hdr(Security-Verify)));
|
|
xnotice("Security-Verify=$var(sec_verify)\n");
|
|
$var(sv_port_c) = $(var(sec_verify){re.subst,/.*port-c=([0-9]*).*$/\1/s});
|
|
xnotice("port-c=$var(sv_port_c)\n");
|
|
$var(sv_port_s) = $(var(sec_verify){re.subst,/.*port-s=([0-9]*).*$/\1/s});
|
|
xnotice("port-s=$var(sv_port_s)\n");
|
|
|
|
$sht(natpingfrom=>$var(ouri)) = "tcp:"+$T_req($Ri)+":"+$var(sv_port_c);
|
|
} else {
|
|
$sht(natpingfrom=>$var(ouri)) = "tcp:"+$T_req($Ri)+":"+$T_req($Rp);
|
|
}
|
|
sht_unlock("natpingfrom=>natpingfromlock");
|
|
}
|
|
#!endif
|
|
#!ifdef WITH_PING_TLS
|
|
#if ($T_req($pr) == "tls") {
|
|
if ($pr == "tls") {
|
|
sht_lock("natping=>natpinglock");
|
|
if ($(T_req($hdr(Security-Client))) =~ ".*ipsec-3gpp.*") {
|
|
$var(sec_client) = $(T_req($hdr(Security-Client)));
|
|
xnotice("Security-Client=$var(sec_client)\n");
|
|
$var(sc_port_c) = $(var(sec_client){re.subst,/.*port-c=([0-9]*).*$/\1/s});
|
|
xnotice("port-c=$var(sc_port_c)\n");
|
|
$var(sc_port_s) = $(var(sec_client){re.subst,/.*port-s=([0-9]*).*$/\1/s});
|
|
xnotice("port-s=$var(sc_port_s)\n");
|
|
$var(ouri) = "sip:"+$T_req($si)+":"+$var(sc_port_s)+";transport=tls";
|
|
} else {
|
|
$var(ouri) = "sip:"+$T_req($si)+":"+$T_req($sp)+";transport=tls";
|
|
}
|
|
$sht(natping=>$var(ouri)) = $(T_req($ct){nameaddr.uri});
|
|
sht_unlock("natping=>natpinglock");
|
|
|
|
sht_lock("natpingfrom=>natpingfromlock");
|
|
if ($(T_req($hdr(Security-Verify))) =~ ".*ipsec-3gpp.*") {
|
|
$var(sec_verify) = $(T_req($hdr(Security-Verify)));
|
|
xnotice("Security-Verify=$var(sec_verify)\n");
|
|
$var(sv_port_c) = $(var(sec_verify){re.subst,/.*port-c=([0-9]*).*$/\1/s});
|
|
xnotice("port-c=$var(sv_port_c)\n");
|
|
$var(sv_port_s) = $(var(sec_verify){re.subst,/.*port-s=([0-9]*).*$/\1/s});
|
|
xnotice("port-s=$var(sv_port_s)\n");
|
|
|
|
$sht(natpingfrom=>$var(ouri)) = "tls:"+$T_req($Ri)+":"+$var(sv_port_c);
|
|
} else {
|
|
$sht(natpingfrom=>$var(ouri)) = "tls:"+$T_req($Ri)+":"+$T_req($Rp);
|
|
}
|
|
sht_unlock("natpingfrom=>natpingfromlock");
|
|
}
|
|
#!endif
|
|
#!endif
|
|
#update stats for register reply on success
|
|
$var(start_secs) = $(sht(a=>$ci::start_time){s.select,0,.});
|
|
$var(start_usecs) = $(sht(a=>$ci::start_time){s.select,1,.});
|
|
$var(diff_secs) = $TV(s) - $var(start_secs);
|
|
$var(diff_usecs) = $TV(u) - $var(start_usecs);
|
|
$var(diff_ms) = $var(diff_secs)*1000 + ($var(diff_usecs)/1000);
|
|
$sht(a=>$ci::start_time)=0;
|
|
$var(stat_add) = "+" + $var(diff_ms);
|
|
xlog("L_DBG", "REGISTER SUCCESS[$ci] took $var(stat_add)ms\n");
|
|
update_stat("register_success", "+1");
|
|
update_stat("register_time", "$var(stat_add)");
|
|
#!ifdef WITH_IPSEC
|
|
ipsec_forward("location", IPSEC_FORWARD_FLAGS);
|
|
}
|
|
else {
|
|
if (t_check_status("401")) {
|
|
if($(T_req($hdr(Security-Client))) != $null && ipsec_create("location", IPSEC_DELETE_UNUSED_TUNNELS)!=1) {
|
|
send_reply("503", "Service Unavailable (Create ipsec failed)");
|
|
}
|
|
if ($sht(ipsec_clients=>$(T_req($ct){nameaddr.uri})) != $null) {
|
|
$var(sec_client) = $(T_req($hdr(Security-Client)));
|
|
xnotice("Security-Client=$var(sec_client)\n");
|
|
$var(sc_port_c) = $(var(sec_client){re.subst,/.*port-c=([0-9]*).*$/\1/s});
|
|
xnotice("port-c=$var(sc_port_c)\n");
|
|
$var(sc_port_s) = $(var(sec_client){re.subst,/.*port-s=([0-9]*).*$/\1/s});
|
|
xnotice("port-s=$var(sc_port_s)\n");
|
|
}
|
|
xnotice("Expires=$(T_req($expires(min)))\n");
|
|
if (is_present_hf("WWW-Authenticate")) {
|
|
# Remove ck and ik:
|
|
$var(old_hdr) = $hdr(WWW-Authenticate);
|
|
xnotice("Old header - WWW-Authenticate=$var(old_hdr)\n");
|
|
remove_hf("WWW-Authenticate");
|
|
$var(new_hdr) = $(hdr(WWW-Authenticate){re.subst,/(, *)?(ck|ik)=\"\w+\"//gi});
|
|
if ($(var(new_hdr){s.len}) > 0) {
|
|
append_hf("WWW-Authenticate: $var(new_hdr)\r\n");
|
|
}
|
|
xnotice("New header - WWW-Authenticate=$var(new_hdr)\n");
|
|
}
|
|
}
|
|
#!endif
|
|
}
|
|
exit;
|
|
}
|
|
|
|
# Negative replies to REGISTER requests:
|
|
######################################################################
|
|
failure_route[REGISTER_failure]
|
|
{
|
|
#!ifdef WITH_IPBLOCK
|
|
if (t_check_status("403|[5-6][0-9][0-9]")) {
|
|
if ($sht(failedauth=>$si) != $null)
|
|
$sht(failedauth=>$si) = $sht(failedauth=>$si) + 1;
|
|
else
|
|
$sht(failedauth=>$si) = 1;
|
|
if ($sht(failedauth=>$si) > 10) {
|
|
xlog("L_ALERT","ALERT: blocking $rm from $fu (IP:$si:$sp), more than 5 failed auth requests!\n");
|
|
xlog("Blocking traffic from $si\n");
|
|
$sht(ipban=>$si) = 1;
|
|
}
|
|
update_stat("register_failed", "+1");
|
|
}
|
|
#!endif
|
|
if (t_check_status("408")) {
|
|
send_reply("504","Server Time-Out");
|
|
update_stat("register_failed", "+1");
|
|
exit;
|
|
}
|
|
}
|