location.c

Go to the documentation of this file.
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" /* run_actions */
00070 #include "../../route.h" /* route_get */
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     /* check if we received what we should */
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     /* check orig uri parameter in topmost Route */
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     /* extract data from message */ 
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); // shm_malloc in cscf_get_public_identity_from_requri      
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         //TODO - add the warning code 99 in the reply   
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     //print_s_list(L_ERR);  
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     //int ret=CSCF_RETURN_FALSE;
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     //LOG(L_DBG,"DBG:"M_NAME":I_originating: uri params <%.*s>\n", puri.params.len, puri.params.s);
00301     // parse_uri does not support orig param...
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 

Generated on Thu Oct 23 04:14:38 2008 for Open IMS Core CSCFs by  doxygen 1.5.2