[Overview] [Code Structure] [Configuration and usage] [Example]
To use you need the The Serving-CSCF Module (scscf) loaded. This is because this module uses the registrar in there for Initial Filter Criteria storage.
The messages forwarded to the Application Server have the following marking:
Route: <AS>, <sip:ifcmark@[isc_my_uri];lr;s=xxx;h=xxx;d=xxx>
For detailed information on marking take a look at mark.c.
To check if a message is matching the next unchecked IFC you should do the following for checking triggers for the originating user:
{
...
if (ISC_match_filter("orig")){
t_on_reply("ISC_Orig_reply");
t_on_failure("ISC_Orig_failure");
# here the message matched and was forwarded to the AS already and we can exit
exit;
}
# here the message did not match any (more) IFCs
...
}
onreply_route[ISC_Orig_reply]
{
log(1,">> ISC_Orig_reply\n");
#if you would like to do some processing on responses from AS, do it here
break;
}
failure_route[ISC_Orig_failure]
{
log(1,">> ISC_Orig_failure\n");
if (!t_check_status("408")){
#if you would like to do some processing on responses from AS, do it here
break;
}
if (ISC_is_session_continued()){
#here the AS failed to respond and we should continue processing
break;
}else{
#here the AS failed to respond and the session should be terminated
t_reply("555","AS failed to respond");
}
}
Or, if the AS responded with the request modified, or with another request and it wishes to resume the IFC triggering session, the following should be applied to identify this case:
...
if (ISC_from_AS("orig")){
#do resume of processing - probably call ISC_match_filter("orig")
}
...
# # $Id: scscf.cfg 575 2008-07-28 15:08:20Z vingarzan $ # # Serving - CSCF configuration script # # ----------- global configuration parameters ------------------------ debug=3 log_stderror=yes memlog=5 sip_warning=yes fork=yes children=4 listen=127.0.0.1 port=6060 alias=scscf.open-ims.test:6060 check_via=no # (cmd. line: -v) dns=no # (cmd. line: -r) rev_dns=no # (cmd. line: -R) # ------------------ module loading ---------------------------------- loadmodule "/opt/OpenIMSCore/ser_ims/modules/sl/sl.so" loadmodule "/opt/OpenIMSCore/ser_ims/modules/tm/tm.so" loadmodule "/opt/OpenIMSCore/ser_ims/modules/dialog/dialog.so" loadmodule "/opt/OpenIMSCore/ser_ims/modules/rr/rr.so" loadmodule "/opt/OpenIMSCore/ser_ims/modules/maxfwd/maxfwd.so" loadmodule "/opt/OpenIMSCore/ser_ims/modules/textops/textops.so" loadmodule "/opt/OpenIMSCore/ser_ims/modules/enum/enum.so" loadmodule "/opt/OpenIMSCore/ser_ims/modules/scscf/scscf.so" modparam("scscf","name","sip:scscf.open-ims.test:6060") #Comment the following line to allow for realm routing on the Cx interface #modparam("scscf","forced_hss_peer","hss.open-ims.test") modparam("scscf","auth_data_hash_size",64) modparam("scscf","auth_vector_timeout",60) modparam("scscf","auth_data_timeout",60) modparam("scscf","av_request_at_once",1) modparam("scscf","av_request_at_sync",1) modparam("scscf","server_assignment_store_data",0) # only one of user_data validation file should normaly be declared here # because if both are specified the data will be checked twice #modparam("scscf","user_data_dtd","/opt/OpenIMSCore/ser_ims/modules/scscf/CxDataType.dtd") modparam("scscf","user_data_xsd","/opt/OpenIMSCore/ser_ims/modules/scscf/CxDataType_Rel7.xsd") modparam("scscf","registrar_hash_size",256) modparam("scscf","registration_default_expires",3600) modparam("scscf","registration_min_expires",30) modparam("scscf","registration_max_expires",1000000) modparam("scscf","registration_qop","auth,auth-int") modparam("scscf","registration_default_algorithm","AKAv1-MD5") #modparam("scscf","registration_default_algorithm","AKAv2-MD5") #modparam("scscf","registration_default_algorithm","MD5") #modparam("scscf","registration_default_algorithm","CableLabs-Digest") #modparam("scscf","registration_default_algorithm","TISPAN-HTTP_DIGEST_MD5") # Let the HSS decide #modparam("scscf","registration_default_algorithm","HSS-Selected") # The next authentication methods are implemented here but not yet completed in FHoSS # please do not complain about bugs when using with FHoSS, yet! #modparam("scscf","registration_default_algorithm","NASS-Bundled") modparam("scscf","registration_disable_early_ims",1) modparam("scscf","registration_disable_nass_bundled",1) modparam("scscf","subscription_default_expires",3600) modparam("scscf","subscription_min_expires",30) modparam("scscf","subscription_max_expires",1000000) modparam("scscf","dialogs_hash_size",256) modparam("scscf","dialogs_expiration_time",3600) modparam("scscf","dialogs_enable_release",1) modparam("scscf","max_dialog_count",20000) modparam("scscf","min_se",90) # persistency_mode - 0 None / 1 Files / 2 Databases modparam("scscf","persistency_mode",0) # support for wildcard PSI 0 No 1 Yes modparam("scscf","support_wildcardPSI",0) #modparam("scscf","persistency_mode",1) #modparam("scscf","persistency_location","/opt/OpenIMSCore/persistency") #modparam("scscf","persistency_timer_authdata",60) #modparam("scscf","persistency_timer_dialogs",60) #modparam("scscf","persistency_timer_registrar",60) loadmodule "/opt/OpenIMSCore/ser_ims/modules/isc/isc.so" modparam("isc","my_uri","scscf.open-ims.test:6060") modparam("isc","isc_fr_timeout",5000) modparam("isc","isc_fr_inv_timeout",20000) modparam("isc","expires_grace",120) loadmodule "/opt/OpenIMSCore/ser_ims/modules/cdp/cdp.so" modparam("cdp","config_file","/opt/OpenIMSCore/scscf.xml") # add value to ;lr param to make some broken UAs happy modparam("rr", "enable_full_lr", 1) # ------------------------- request routing logic ------------------- # main routing logic route{ route(Sanity_Checks); # don't repeat work for a transaction already in processing if (method!="ACK" && S_trans_in_processing()) { log(1,"Trans already in processing... skip\n"); break; } if (method=="REGISTER") { route(REGISTER); break; } if (method=="SUBSCRIBE" && search("^(Event|o)([ \t]*):([ \t]*)reg")) { route(SUBSCRIBE); break; } if (method=="ACK") { loose_route(); t_relay(); exit; } if (S_mobile_originating()||ISC_from_AS("orig")){ # support for AS origination on behalf of unregistered user if (S_orig_not_registered()) { S_assign_server_unreg("open-ims.test", "orig"); } # Originating route(Orig); break; }else{ if (S_is_in_dialog("orig")){ route(Orig_Subsequent); break; } if (S_is_in_dialog("term")){ route(Term_Subsequent); break; } # Terminating if (uri=~"sip:(.*)@open-ims\.test(.*)" || uri=~"tel:.*"){ if (S_term_not_registered()) S_assign_server_unreg("open-ims.test", "term"); }else{ sl_send_reply("403","Forbidden - Dialog not found on S-CSCF or Terminating user not suitable for unregistered services"); exit(); } route(Term); break; } } route[Sanity_Checks] { # initial sanity checks -- messages with # max_forwards==0, or excessively long requests if (!mf_process_maxfwd_header("10")) { sl_send_reply("483","Too Many Hops"); exit; }; if (msg:len >= max_len ) { sl_send_reply("513", "Message too big"); exit; }; if(@hf_value.max_forwards=="0"){ exit; } } route[Check_Session_Expires] { if (!S_check_session_expires()) { S_422_session_expires(); exit; }; } route[REGISTER] { if (uri=~"sip:(.*)open-ims\.test(.*)"){ t_newtran(); # if ( !t_newtran()) { # sl_reply_error(); # break; # }; if (!S_is_integrity_protected("open-ims.test")){ # Unprotected REGISTER # Variant 1 - accept also non IPSec clients if (!S_is_authorized("open-ims.test")) { S_challenge("open-ims.test"); route(Service_Routes); t_reply("401", "Unauthorized - Challenging the UE"); exit; }else{ if (S_is_not_registered()){ if (S_assign_server("open-ims.test")){ route(Service_Routes); route(Charging_Function_Addresses); t_reply("200","OK - SAR succesful and registrar saved"); ISC_match_filter_reg("0"); exit; }else{ t_reply("500","Server Internal Error - Server Assignment failed"); exit; } }else{ ISC_match_filter_reg("1"); if (S_assign_server("open-ims.test")){ route(Service_Routes); route(Charging_Function_Addresses); t_reply("200","OK - SAR succesful and registrar saved"); exit; }else{ t_reply("500","Server Internal Error - Server Assignment failed"); exit; } } } # Variant 2 - accept only IPSec clients #S_challenge("open-ims.test"); #route(Service_Routes); #t_reply("401", "Unauthorized - Challenging the UE"); break; }else{ # Protected REGISTER # Variant 1 - Always require reauthentication #if (!S_is_authorized("open-ims.test")) { # S_challenge("open-ims.test"); # route(Service_Routes); # t_reply("401", "Unauthorized - Challenging the UE"); # exit; #} # Variant 2 - trust protected REGISTER if (S_is_not_registered()){ if (S_assign_server("open-ims.test")){ route(Service_Routes); route(Charging_Function_Addresses); t_reply("200","OK - SAR succesful and registrar saved"); ISC_match_filter_reg("0"); exit; }else{ t_reply("500","Server Internal Error - Server Assignment failed"); exit; } }else{ ISC_match_filter_reg("1"); if (S_assign_server("open-ims.test")){ route(Service_Routes); route(Charging_Function_Addresses); t_reply("200","OK - SAR succesful and registrar saved"); exit; }else{ t_reply("500","Server Internal Error - Update Contacts failed"); exit; } } } } else { sl_send_reply("403", "Forbidden - Domain not serviced"); } } route[Service_Routes] { # if (!S_check_visited_network_id("open-ims\.test")){ # S_add_service_route("sip:thig@icscf.open-ims.test"); # } S_add_path_service_routes(); S_add_allow("INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, PUBLISH, MESSAGE, INFO"); } route[Charging_Function_Addresses] { if (S_check_visited_network_id("open-ims\.test")){ S_add_p_charging_function_addresses(); } } route[SUBSCRIBE] { if ( !t_newtran()) { sl_reply_error(); break; } if (!S_term_registered()){ t_reply("404","Not Found - User not registered on this S-CSCF"); exit; } if (S_can_subscribe()){ if (S_subscribe()){ # This is replied from S_subscribe, as that also add extra headers #t_reply("200","OK - Subscription saved"); exit; }else{ t_reply("500","Server Error saving subscription"); exit; } }else{ t_reply("403","Forbidden to SUBSCRIBE"); exit; }; } # ORIGINATING route[Orig] { log(1,">> Orig\n"); if (S_originating_barred()){ sl_send_reply("403","Forbidden - Originating Public Identity barred"); exit; } if (method=="INVITE"||method=="SUBSCRIBE"){ route(Check_Session_Expires); if (!S_is_record_routed("orig")) S_record_route("orig"); if (!S_save_dialog("orig")){ sl_send_reply("514","Originating dialog save failure - S-CSCF maximum dialog count reached!"); exit; } } loose_route(); S_privacy_hook(); # check if dialog saved as fwded to AS if (ISC_match_filter("orig")){ t_on_reply("ISC_Orig_reply"); t_on_failure("ISC_Orig_failure"); log(1,">> Orig - msg was fwded to AS\n"); exit; } # if THIG_required -> add THIG route if (!ISC_from_AS("orig")){ S_add_p_asserted_identity(); } if (method=="INVITE") { route(PSTN_handling); } t_on_reply("Orig_reply"); #t_on_failure("Orig_failure"); # Do not loop through the I-CSCF if the terminating user is here # might not work if other routes are present if (S_term_registered()){ t_relay_to_udp("127.0.0.1",6060); exit; } if (!t_relay()) { sl_send_reply("500","Error forwarding towards terminating leg"); exit; }; } onreply_route[Orig_reply] { log(1,">> Orig_reply\n"); if (!S_update_dialog("orig")){ log(1,">> Error updating orig dialog - maybe non-dialog request...\n"); } } failure_route[Orig_failure] { log(1,">> Orig_failure\n"); } onreply_route[ISC_Orig_reply] { log(1,">> ISC_Orig_reply\n"); if (!S_update_dialog("orig")){ log(1,">> Error updating orig dialog - maybe non-dialog request...\n"); } break; } failure_route[ISC_Orig_failure] { log(1,">> ISC_Orig_failure\n"); # if (t_check_status("408")) { # if (ISC_is_session_continued()){ # log(1,">> ISC continue session not implemented :(\n"); # break; # }else{ # t_reply("555","AS failed to respond"); # } # } if (t_check_status("408")||t_check_status("5..")){ t_on_reply("ISC_Orig_reply"); t_on_failure("ISC_Orig_failure"); if (ISC_match_filter("orig")){ log(1,">> ISC_Orig_failure - msg was fwded to AS\n"); exit; } # if THIG_required -> add THIG route if (!ISC_from_AS("origfail")){ S_add_p_asserted_identity(); } if (method=="INVITE") { route(PSTN_handling); } t_on_reply("Orig_reply"); t_on_failure("Orig_failure"); # Do not loop through the I-CSCF if the terminating user is here # might not work if other routes are present if (S_term_registered()){ append_branch(); t_relay_to_udp("127.0.0.1",6060); exit; } if (!t_relay()) { append_branch(); if (!t_relay()) { t_reply("500","Error forwarding towards terminating leg"); exit; } }; } } route[Orig_Subsequent] { log(1,">> Orig_Subsequent\n"); loose_route(); if (method=="INVITE"){ route(Check_Session_Expires); S_update_dialog("orig"); } #S_record_route("orig"); if (method!="ACK"){ S_privacy_hook(); t_on_reply("Orig_Subsequent_reply"); #t_on_failure("Orig_Subsequent_failure"); } if (!t_relay()) { sl_send_reply("500","Error forwarding subsequent request towards terminating leg"); exit; }; } onreply_route[Orig_Subsequent_reply] { log(1,">> Orig_Subsequent_reply\n"); # if (t_check_status("305")){ # S_proxy_request(); # break; # } S_update_dialog("orig"); break; } failure_route[Orig_Subsequent_failure] { log(1,">> Orig_Subsequent_failure\n"); } # TERMINATING route[Term] { log(1,">> Term\n"); if (S_terminating_barred()){ sl_send_reply("404","Not Found - Terminating user barred"); exit; } if (method=="INVITE"||method=="SUBSCRIBE"){ route(Check_Session_Expires); if (!S_is_record_routed("term")) S_record_route("term"); if (!S_save_dialog("term")){ sl_send_reply("514","Terminating dialog save failure - S-CSCF maximum dialog count reached!"); exit; } } loose_route(); # check if dialog saved as fwded to AS if (ISC_match_filter("term")){ t_on_reply("ISC_Term_reply"); t_on_failure("ISC_Term_failure"); log(1,">> Term - msg was fwded to AS\n"); exit; } if (!S_lookup()){ if (uri=~"sip:(.*)@open-ims\.test(.*)") { if ( !t_newtran()) { sl_reply_error(); exit; }; t_reply("404","Not Found - destination user not found on this S-CSCF"); exit; } } t_on_reply("Term_reply"); #t_on_failure("Term_failure"); S_apply_privacy(); if (!t_relay()) { sl_send_reply("500","Error forwarding towards terminating leg"); exit; }; } onreply_route[Term_reply] { log(1,">> Term_reply\n"); if (!S_update_dialog("term")){ log(1,">> Error updating term dialog - maybe non-dialog request...\n"); } } failure_route[Term_failure] { log(1,">> Term_failure\n"); } onreply_route[ISC_Term_reply] { log(1,">> ISC_Term_reply\n"); if (!S_update_dialog("term")){ log(1,">> Error updating term dialog - maybe non-dialog request...\n"); } break; } failure_route[ISC_Term_failure] { log(1,">> ISC_Term_failure\n"); # if (t_check_status("408")) { # if (ISC_is_session_continued()){ # log(1,">> ISC continue session not implemented :(\n"); # break; # }else{ # t_reply("555","AS failed to respond"); # } # } if (t_check_status("408")||t_check_status("5..")){ t_on_reply("ISC_Term_reply"); t_on_failure("ISC_Term_failure"); if (ISC_match_filter("term")){ log(1,">> Term - msg was fwded to AS\n"); exit; } if (!S_lookup()){ if (uri=~"sip:(.*)@open-ims\.test(.*)") { #if ( !t_newtran()) { # sl_reply_error(); # exit; #}; t_reply("404","Not Found - destination user not found on this S-CSCF"); exit; } } t_on_reply("Term_reply"); t_on_failure("Term_failure"); if (!t_relay()) { append_branch(); if (!t_relay()) { t_reply("500","Error forwarding towards terminating leg"); exit; } }; } } route[Term_Subsequent] { log(1,">> Term_Subsequent\n"); loose_route(); if (method=="INVITE"){ route(Check_Session_Expires); S_update_dialog("term"); } S_apply_privacy(); #S_record_route("term"); if (method!="ACK") { t_on_reply("Term_Subsequent_reply"); #t_on_failure("Term_Subsequent_failure"); } if (!t_relay()) { sl_send_reply("500","Error forwarding subsequent request towards user"); exit; }; } onreply_route[Term_Subsequent_reply] { log(1,">> Term_Subsequent_reply\n"); # if (t_check_status("305")){ # S_proxy_request(); # break; # } S_update_dialog("term"); break; } failure_route[Term_Subsequent_failure] { log(1,">> Term_Subsequent_failure\n"); } route[PSTN_handling] { #PSTN gateway handling if (uri=~"tel:\+(.*)"){ if(!enum_query()){ route(PSTN); break; } } #if (uri=~"sip:[0-9]+@open-ims\.test(.*)"){ # route(PSTN); # break; #} # a tel URI in non-international format (i.e. the local service number analysis and handling is either failed in the appropriate AS or the request has not been forwarded to AS for local service number analysis and handling at all) if (uri=~"tel:[^+]*") { route(PSTN); break; } # a SIP URI with the user part starting with a + and user=phone if (uri=~"sip:\+[0-9]+@open-ims\.test.*user=phone.*"){ route(PSTN); break; } } route[PSTN] { t_on_reply("PSTN_reply"); t_relay_to_udp("127.0.0.1", "9060"); exit; } onreply_route[PSTN_reply] { log(1,">> PSTN_reply\n"); if (!S_update_dialog("orig")){ log(1,">> Error updating orig dialog - maybe non-dialog request...\n"); } }
1.5.2