00001
00056 #include <values.h>
00057
00058 #include "location.h"
00059
00060 #include "../../mem/shm_mem.h"
00061
00062 #include "mod.h"
00063 #include "db.h"
00064 #include "sip.h"
00065 #include "cx.h"
00066 #include "cx_avp.h"
00067 #include "registration.h"
00068
00069 #include "../../action.h"
00070 #include "../../route.h"
00071
00072 #include "../../parser/parse_uri.h"
00073
00074 extern struct tm_binds tmb;
00075 extern struct cdp_binds cdpb;
00077 extern str icscf_default_realm_str;
00079 extern int route_on_term_user_unknown_n;
00089 int I_LIR(struct sip_msg* msg, char* str1, char* str2)
00090 {
00091 int result=CSCF_RETURN_FALSE;
00092 str public_identity={0,0};
00093 str realm={0,0};
00094 AAAMessage *lia=0;
00095 int orig = 0;
00096
00097
00098 LOG(L_DBG,"DBG:"M_NAME":I_LIR: Starting ...\n");
00099
00100 if (msg->first_line.type!=SIP_REQUEST) {
00101 LOG(L_ERR,"ERR:"M_NAME":I_LIR: The message is not a request\n");
00102 goto done;
00103 }
00104
00105
00106 if (I_originating(msg, str1, str2)==CSCF_RETURN_TRUE) {
00107 orig = 1;
00108 LOG(L_DBG,"DBG:"M_NAME":I_LIR: orig\n");
00109 }
00110
00111
00112 if (orig) {
00113 public_identity = cscf_get_asserted_identity(msg);
00114 realm = cscf_get_realm_from_uri(public_identity);
00115 } else {
00116 realm = cscf_get_realm_from_ruri(msg);
00117 public_identity=cscf_get_public_identity_from_requri(msg);
00118 }
00119 if (!public_identity.len) {
00120 LOG(L_ERR,"ERR:"M_NAME":I_LIR: Public Identity not found, responding with 400\n");
00121 cscf_reply_transactional(msg,400,MSG_400_NO_PUBLIC);
00122 result=CSCF_RETURN_BREAK;
00123 goto done;
00124 }
00125 if(!realm.len) realm = icscf_default_realm_str;
00126
00127 lia = Cx_LIR(msg,public_identity,realm);
00128
00129 if (public_identity.s && !orig)
00130 shm_free(public_identity.s);
00131
00132
00133 if (!lia){
00134 LOG(L_ERR,"ERR:"M_NAME":I_LIR: Error creating/sending LIR\n");
00135 cscf_reply_transactional(msg,480,MSG_480_DIAMETER_ERROR);
00136 result=CSCF_RETURN_BREAK;
00137 goto done;
00138 }
00139
00140 result = I_LIA(msg, &lia, orig);
00141
00142 done:
00143 if (lia) cdpb.AAAFreeMessage(&lia);
00144 LOG(L_DBG,"DBG:"M_NAME":I_LIR: ... Done\n");
00145 return result;
00146 }
00147
00155 int I_LIA(struct sip_msg* msg, AAAMessage** lia, int originating)
00156 {
00157 int rc=-1,experimental_rc=-1;
00158 str server_name;
00159 int *m_capab=0,m_capab_cnt=0;
00160 int *o_capab=0,o_capab_cnt=0;
00161 str *p_server_names=0;
00162 int p_server_names_cnt=0;
00163 scscf_entry *list=0;
00164 str call_id;
00165 int status_code=999;
00166 char *reason_phrase=0;
00167
00168 if (!*lia){
00169
00170 cscf_reply_transactional(msg,480,MSG_480_DIAMETER_TIMEOUT_LIA);
00171 return CSCF_RETURN_BREAK;
00172 }
00173
00174 if (!Cx_get_result_code(*lia,&rc)&&
00175 !Cx_get_experimental_result_code(*lia,&experimental_rc))
00176 {
00177 status_code = 480;
00178 reason_phrase = MSG_480_DIAMETER_MISSING_AVP_LIA;
00179 goto reply_final_response;
00180 }
00181
00182 switch(rc){
00183 case -1:
00184 switch(experimental_rc){
00185
00186 case RC_IMS_DIAMETER_ERROR_USER_UNKNOWN:
00187 if (!originating && route_on_term_user_unknown_n > -1) {
00188 if (*lia) cdpb.AAAFreeMessage(lia);
00189 if (run_actions(main_rt.rlist[route_on_term_user_unknown_n], msg)<0){
00190 LOG(L_WARN,"ERR:"M_NAME":I_LIA: error while trying script\n");
00191 }
00192 return CSCF_RETURN_BREAK;
00193 } else {
00194 status_code = 604;
00195 reason_phrase = MSG_604_USER_UNKNOWN;
00196 goto reply_final_response;
00197 }
00198 break;
00199
00200 case RC_IMS_DIAMETER_ERROR_IDENTITY_NOT_REGISTERED:
00201 status_code = 480;
00202 reason_phrase = MSG_480_NOT_REGISTERED;
00203 goto reply_final_response;
00204
00205 case RC_IMS_DIAMETER_UNREGISTERED_SERVICE:
00206 goto success;
00207
00208 default:
00209 status_code = 403;
00210 reason_phrase = MSG_403_UNKOWN_EXPERIMENTAL_RC;
00211 goto reply_final_response;
00212 }
00213 break;
00214
00215 case AAA_UNABLE_TO_COMPLY:
00216 status_code = 403;
00217 reason_phrase = MSG_403_UNABLE_TO_COMPLY;
00218 goto reply_final_response;
00219
00220 case AAA_SUCCESS:
00221 goto success;
00222
00223 default:
00224 status_code = 403;
00225 reason_phrase = MSG_403_UNKOWN_RC;
00226 goto reply_final_response;
00227 }
00228
00229 success:
00230 server_name = Cx_get_server_name(*lia);
00231 if (server_name.len){
00232 list = new_scscf_entry(server_name,MAXINT, originating);
00233 }else{
00234 Cx_get_capabilities(*lia,&m_capab,&m_capab_cnt,&o_capab,&o_capab_cnt,&p_server_names,&p_server_names_cnt);
00235
00236 list = I_get_capab_ordered(server_name,m_capab,m_capab_cnt,o_capab,o_capab_cnt,p_server_names,p_server_names_cnt,originating);
00237 if (m_capab) shm_free(m_capab);
00238 if (o_capab) shm_free(o_capab);
00239 if (p_server_names) shm_free(p_server_names);
00240 }
00241
00242 if (!list) {
00243 status_code = 600;
00244 reason_phrase = MSG_600_EMPTY_LIST;
00245 goto reply_final_response;
00246 }
00247 call_id = cscf_get_call_id(msg,0);
00248 if (!call_id.len||!add_scscf_list(call_id,list)){
00249 status_code = 500;
00250 reason_phrase = MSG_500_ERROR_SAVING_LIST;
00251 goto reply_final_response;
00252 }
00253
00254
00255 return CSCF_RETURN_TRUE;
00256
00257 reply_final_response:
00258 if (*lia) cdpb.AAAFreeMessage(lia);
00259 cscf_reply_transactional(msg,status_code,reason_phrase);
00260 return CSCF_RETURN_BREAK;
00261 }
00262
00263
00271 int I_originating(struct sip_msg *msg,char *str1,char *str2)
00272 {
00273
00274 struct hdr_field *h;
00275 str* uri;
00276 rr_t *r;
00277
00278 if (parse_headers(msg, HDR_ROUTE_F, 0)<0){
00279 LOG(L_ERR,"ERR:"M_NAME":I_originating: error parsing headers\n");
00280 return CSCF_RETURN_FALSE;
00281 }
00282 h = msg->route;
00283 if (!h){
00284 LOG(L_DBG,"DBG:"M_NAME":I_originating: Header Route not found\n");
00285 return CSCF_RETURN_FALSE;
00286 }
00287 if (parse_rr(h)<0){
00288 LOG(L_ERR,"ERR:"M_NAME":I_originating: Error parsing as Route header\n");
00289 return CSCF_RETURN_FALSE;
00290 }
00291 r = (rr_t*)h->parsed;
00292
00293 uri = &r->nameaddr.uri;
00294 struct sip_uri puri;
00295 if (parse_uri(uri->s, uri->len, &puri) < 0) {
00296 LOG(L_ERR, "DBG:"M_NAME":I_originating: Error while parsing the first route URI\n");
00297 return -1;
00298 }
00299 if (puri.params.len < 4) return CSCF_RETURN_FALSE;
00300
00301
00302 int c = 0;
00303 int state = 0;
00304 while (c < puri.params.len) {
00305 switch (puri.params.s[c]) {
00306 case 'o': if (state==0) state=1;
00307 break;
00308 case 'r': if (state==1) state=2;
00309 break;
00310 case 'i': if (state==2) state=3;
00311 break;
00312 case 'g': if (state==3) state=4;
00313 break;
00314 case ' ':
00315 case '\t':
00316 case '\r':
00317 case '\n':
00318 case ',':
00319 case ';':
00320 if (state==4) return CSCF_RETURN_TRUE;
00321 state=0;
00322 break;
00323 case '=': if (state==4) return CSCF_RETURN_TRUE;
00324 state=-1;
00325 break;
00326 default: state=-1;
00327 }
00328 c++;
00329 }
00330
00331 return state==4 ? CSCF_RETURN_TRUE : CSCF_RETURN_FALSE;
00332 }
00333
00334
00335