registrar.c

Go to the documentation of this file.
00001 /*
00002  * $Id: registrar.c 591 2008-10-15 12:46:34Z vingarzan $
00003  *  
00004  * Copyright (C) 2004-2006 FhG Fokus
00005  *
00006  * This file is part of Open IMS Core - an open source IMS CSCFs & HSS
00007  * implementation
00008  *
00009  * Open IMS Core is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * For a license to use the Open IMS Core software under conditions
00015  * other than those described here, or to purchase support for this
00016  * software, please contact Fraunhofer FOKUS by e-mail at the following
00017  * addresses:
00018  *     info@open-ims.org
00019  *
00020  * Open IMS Core is distributed in the hope that it will be useful,
00021  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00022  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023  * GNU General Public License for more details.
00024  * 
00025  * It has to be noted that this Open Source IMS Core System is not 
00026  * intended to become or act as a product in a commercial context! Its 
00027  * sole purpose is to provide an IMS core reference implementation for 
00028  * IMS technology testing and IMS application prototyping for research 
00029  * purposes, typically performed in IMS test-beds.
00030  * 
00031  * Users of the Open Source IMS Core System have to be aware that IMS
00032  * technology may be subject of patents and licence terms, as being 
00033  * specified within the various IMS-related IETF, ITU-T, ETSI, and 3GPP
00034  * standards. Thus all Open IMS Core users have to take notice of this 
00035  * fact and have to agree to check out carefully before installing, 
00036  * using and extending the Open Source IMS Core System, if related 
00037  * patents and licences may become applicable to the intended usage 
00038  * context.  
00039  *
00040  * You should have received a copy of the GNU General Public License
00041  * along with this program; if not, write to the Free Software
00042  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00043  * 
00044  */
00045  
00056 #include <time.h>
00057 
00058 #include "../../parser/contact/contact.h"
00059 #include "../../parser/contact/parse_contact.h"
00060 #include "../../ut.h"
00061 #include "../tm/tm_load.h"
00062 #include "../cdp/cdp_load.h"
00063 #include "../../dset.h"
00064 
00065 #include "registrar.h"
00066 #include "registration.h"
00067 #include "mod.h"
00068 #include "registrar_parser.h"
00069 #include "registrar_storage.h"
00070 #include "sip.h"
00071 #include "cx.h"
00072 #include "cx_avp.h"
00073 #include "sip_messages.h"
00074 #include "dlg_state.h"
00075 
00076 
00077 extern struct tm_binds tmb;             
00078 extern struct cdp_binds cdpb;           
00080 extern int r_hash_size;                 
00081 extern r_hash_slot *registrar;      
00083 extern str scscf_name_str;              
00084 extern str scscf_service_route_uri;     
00085 extern str scscf_registration_min_expires;
00086 extern int server_assignment_store_data;
00089 extern int registration_default_expires;
00090 extern int registration_min_expires;    
00091 extern int registration_max_expires;    
00092 extern int registration_disable_early_ims;  
00094 extern time_t time_now;                 
00096 extern int append_branches;             
00099 #ifdef WITH_IMS_PM
00100         static str zero={0,0};
00101 #endif
00102 
00103 
00109 void registrar_timer(unsigned int ticks, void* param)
00110 {
00111     r_public *p,*pn,*rpublic;
00112     r_contact *c,*c2=0,*cn,*cn2=0;
00113     r_subscriber *s,*sn,*s2=0,*sn2=0;
00114     int i,j,n,assignment_type,sar_res;
00115     ims_public_identity *pi=0;
00116     r_hash_slot *r;
00117     int rpublic_hash;
00118     
00119     #ifdef WITH_IMS_PM
00120         int impu_cnt=0,contact_cnt=0,subs_cnt=0;
00121     #endif
00122 
00123 
00124     r = param;
00125     
00126     LOG(L_DBG,"DBG:"M_NAME":registrar_timer: Called at %d\n",ticks);
00127 
00128     r_act_time();
00129 
00130     for(i=0;i<r_hash_size;i++){
00131         r_lock(i);
00132             p = r[i].head;
00133             while(p){
00134                 pn = p->next;
00135                 c = p->head;
00136                                     
00137                 while(c){
00138                     cn = c->next;
00139                     if (!r_valid_contact(c)){
00140                         LOG(L_DBG,"DBG:"M_NAME":registrar_timer: Contact <%.*s> expired and removed.\n",
00141                             c->uri.len,c->uri.s);                           
00142                         S_event_reg(p,c,0,IMS_REGISTRAR_CONTACT_EXPIRED,1);/* send now because we might drop the dialog soon */ 
00143                         del_r_contact(p,c);
00144                     }
00145                     #ifdef WITH_IMS_PM
00146                         else contact_cnt++;
00147                     #endif
00148                     c = cn;
00149                 }
00150                 s = p->shead;
00151                 while(s){
00152                     sn = s->next;
00153                     if (!r_valid_subscriber(s)){
00154                         LOG(L_DBG,"DBG:"M_NAME":registrar_timer: Subscriber <%.*s> expired and removed.\n",
00155                             s->subscriber.len,s->subscriber.s);
00156                         del_r_subscriber(p,s);
00157                     }
00158                     #ifdef WITH_IMS_PM
00159                         else subs_cnt++;
00160                     #endif
00161                     s = sn;
00162                 }
00163                 
00164                 if (!p->head){/* no more contacts, then deregister it */
00165                     switch (p->reg_state){
00166                         case REGISTERED:
00167                             if (server_assignment_store_data) 
00168                                 assignment_type = AVP_IMS_SAR_TIMEOUT_DEREGISTRATION_STORE_SERVER_NAME;
00169                             else assignment_type = AVP_IMS_SAR_TIMEOUT_DEREGISTRATION;
00170                             sar_res = SAR(0,cscf_get_realm_from_uri(p->aor),p->aor,p->s->private_identity,assignment_type,0);
00171                             
00172                             if (sar_res==1){
00173                                 /* SAR successful, de-register everything in this implicit set */
00174                                 if (!p->s){
00175                                     LOG(L_DBG,"DBG:"M_NAME":registrar_timer: Problem r_public does not contain IMS Subscription <%.*s> \n",
00176                                         p->aor.len,p->aor.s);
00177                                     break;
00178                                 }
00179                                 for(j=0;j<p->s->service_profiles_cnt;j++)
00180                                     for(n=0;n<p->s->service_profiles[j].public_identities_cnt;n++){
00181                                         pi = &(p->s->service_profiles[j].public_identities[n]);
00182                                         if (pi->public_identity.len == p->aor.len &&
00183                                             strncasecmp(pi->public_identity.s,p->aor.s,p->aor.len)==0) continue;
00184                                         rpublic = get_r_public_previous_lock(pi->public_identity,p->hash);
00185                                         
00186                                         if(!rpublic){
00187                                             LOG(L_INFO,"INFO:"M_NAME":registrar_timer: The implicit set public identity <%.*s> was not found in the registrar",
00188                                                 pi->public_identity.len,pi->public_identity.s);
00189                                             continue;
00190                                         }
00191                                         rpublic_hash = rpublic->hash;
00192                                         
00193                                         c2 = rpublic->head;
00194                                         while(c2){
00195                                             cn2 = c2->next;
00196                                             if (!r_valid_contact(c2)){
00197                                                 LOG(L_DBG,"DBG:"M_NAME":registrar_timer: Contact <%.*s> expired and removed (because of implicit set).\n",c2->uri.len,c2->uri.s);
00198                                                 S_event_reg(rpublic,c2,0,IMS_REGISTRAR_CONTACT_EXPIRED,1);/* send now because we might drop the dialog soon */  
00199                                                 del_r_contact(rpublic,c2);
00200                                             }
00201                                             c2 = cn2;
00202                                         }
00203                                         
00204                                         s2 = rpublic->shead;
00205                                         while(s2){
00206                                             sn2 = s2->next;
00207                                             if (!r_valid_subscriber(s2)){
00208                                                 LOG(L_DBG,"DBG:"M_NAME":registrar_timer: Subscriber <%.*s> expired and removed (because of implicit set).\n",s2->subscriber.len,s2->subscriber.s);
00209                                                 del_r_subscriber(rpublic,s2);
00210                                             }                                         
00211                                             s2 = sn2;
00212                                         }
00213                                 
00214                                         if (!rpublic->head){/* no more contacts, then deregister it */
00215                                             if (!rpublic->shead)  {/* delete it if there are no more subscribers for it */     
00216                                                 LOG(L_DBG,"DBG:"M_NAME":registrar_timer: User <%.*s> removed (because of implicit set).\n",
00217                                                     rpublic->aor.len,rpublic->aor.s);
00218                                                 del_r_public(rpublic);
00219                                             }else{/* else mark it unregistered - to avoid more SAR */
00220                                                 LOG(L_DBG,"DBG:"M_NAME":registrar_timer: User <%.*s> kept unregistered - has subscribers (because of implicit set).\n",
00221                                                     rpublic->aor.len,rpublic->aor.s);                                                
00222                                                 rpublic->reg_state = NOT_REGISTERED;                                       
00223                                             }
00224                                         }
00225                                         /* because the lock was taken with a previous lock */
00226                                         if (rpublic_hash!=i) r_unlock(rpublic_hash);
00227                                     }
00228 
00229                               LOG(L_DBG,"DBG:"M_NAME":registrar_timer: User <%.*s> deregistered.\n",
00230                                     p->aor.len,p->aor.s);
00231                               if (!p->shead)    {/* delete it if there are no more subscribers for it */                        
00232                                 LOG(L_DBG,"DBG:"M_NAME":registrar_timer: User <%.*s> removed.\n",
00233                                     p->aor.len,p->aor.s);
00234                                 del_r_public(p);
00235                               }else{/* else mark it unregistered - to avoid more SAR */
00236                                 LOG(L_DBG,"DBG:"M_NAME":registrar_timer: User <%.*s> kept unregistered - has subscribers.\n",
00237                                 p->aor.len,p->aor.s);                               
00238                                 p->reg_state = NOT_REGISTERED;                              
00239                               }
00240                             }else{
00241                                 LOG(L_DBG,"DBG:"M_NAME":registrar_timer: User <%.*s> deregistration SAR failed.Keeping into registrar, but with no contacts\n",
00242                                     p->aor.len,p->aor.s);
00243                                 #ifdef WITH_IMS_PM
00244                                     impu_cnt++;
00245                                 #endif
00246                             }                                       
00247                             break;
00248                             
00249                         case UNREGISTERED:
00250                             /* Don't drop it, just keep it for unregistered triggering*/
00251                              #ifdef WITH_IMS_PM
00252                                 impu_cnt++;
00253                             #endif
00254                             break;
00255                             
00256                         case NOT_REGISTERED:                                
00257                             /* to avoid sending SAR when we still have subscribers, but no contact */
00258                             if (!p->shead)  {/* delete it if there are no more subscribers for it */                        
00259                                 LOG(L_DBG,"DBG:"M_NAME":registrar_timer: User <%.*s> removed - no more subscribers.\n",
00260                                     p->aor.len,p->aor.s);
00261                                 del_r_public(p);                            
00262                             }
00263                             break;
00264                     }
00265                 }
00266                 #ifdef WITH_IMS_PM
00267                     else impu_cnt++;
00268                 #endif
00269                 p = pn;
00270             }
00271         r_unlock(i);        
00272     }
00273     print_r(L_INFO);
00274     #ifdef WITH_IMS_PM
00275         IMS_PM_LOG01(RD_NbrIMPU,impu_cnt);
00276         IMS_PM_LOG01(RD_NbrContact,contact_cnt);
00277         IMS_PM_LOG01(RD_NbrSubs,subs_cnt);
00278     #endif
00279 }
00280 
00302 int S_assign_server(struct sip_msg *msg,char *str1,char *str2 )
00303 {
00304     int ret=CSCF_RETURN_FALSE;
00305     str private_identity,public_identity,realm;
00306     int assignment_type = AVP_IMS_SAR_NO_ASSIGNMENT;
00307     int data_available = AVP_IMS_SAR_USER_DATA_NOT_AVAILABLE;
00308     int expires;
00309     r_public *p;
00310     int require_user_data=0;
00311     contact_body_t* b=0;
00312     struct hdr_field *h=0;
00313     contact_t *ci=0;
00314     r_contact *c=0;
00315     int n_contacts=0,contacts_reg=0;
00316 
00317     LOG(L_DBG,"DBG:"M_NAME":S_assign_server: Assigning server...\n");
00318     
00319     /* First check the parameters */
00320     if (msg->first_line.type!=SIP_REQUEST)
00321     {
00322         LOG(L_ERR,"ERR:"M_NAME":S_assign_server: This message is not a request\n");
00323         goto error;
00324     }       
00325 
00326     realm.s = str1; realm.len = strlen(str1);
00327     if (!realm.len) {
00328         LOG(L_ERR,"ERR:"M_NAME":S_assign_server: No realm found\n");
00329         return CSCF_RETURN_BREAK;
00330     }
00331         
00332     private_identity = cscf_get_private_identity(msg,realm);
00333     
00334     public_identity = cscf_get_public_identity(msg);
00335     if (!public_identity.len) {
00336         LOG(L_ERR,"ERR:"M_NAME":S_assign_server: public identity missing\n");       
00337         return ret;
00338     }
00339         
00340     expires = cscf_get_max_expires(msg);
00341     
00342     if (expires>0) {
00343         if (r_is_registered_id(public_identity)) 
00344             assignment_type = AVP_IMS_SAR_RE_REGISTRATION;
00345         else{
00346             assignment_type = AVP_IMS_SAR_REGISTRATION;
00347             require_user_data=1;
00348         }
00349     }
00350     else {
00351         if (server_assignment_store_data) 
00352             assignment_type = AVP_IMS_SAR_USER_DEREGISTRATION_STORE_SERVER_NAME;
00353         else assignment_type = AVP_IMS_SAR_USER_DEREGISTRATION;
00354 
00355         b = cscf_parse_contacts(msg);
00356         
00357         if (!b||(!b->contacts && !b->star)) {
00358             LOG(L_ERR,"ERR:"M_NAME":S_assign_server: No contacts found - this was just bindings fetch, no SAR done\n");
00359             ret = CSCF_RETURN_TRUE;
00360             goto done;
00361         }
00362         
00363         if (!b->star){
00364             // If not all contacts would be de-registered now, then we actually skip the SAR
00365             p = get_r_public(public_identity);
00366             if(!p)  goto error;
00367             
00368             for(h=msg->contact;h;h=h->next){
00369                 if (h->type==HDR_CONTACT_T && h->parsed){
00370                     for(ci=((contact_body_t*)h->parsed)->contacts;ci;ci=ci->next){
00371                         if (get_r_contact(p,ci->uri))
00372                             n_contacts++;
00373                     }
00374                 }
00375             }
00376             
00377             for(c=p->head;c;c=c->next)
00378                 contacts_reg++;
00379             r_unlock(p->hash);
00380             
00381             if (n_contacts < contacts_reg){
00382                 // There are still contacts left for this public id
00383                 drop_auth_userdata(private_identity,public_identity);
00384                 ret = save_location(msg,assignment_type,0,0,0,0,0); 
00385                 goto done;
00386             }           
00387         }
00388     }
00389     
00390     //TODO
00391     //if (userdataavailable) data_available = AVP_IMS_SAR_USER_DATA_ALREADY_AVAILABLE;
00392     //else
00393 
00394     if(require_user_data)
00395         data_available = AVP_IMS_SAR_USER_DATA_NOT_AVAILABLE;
00396     else
00397         data_available = AVP_IMS_SAR_USER_DATA_ALREADY_AVAILABLE;
00398     
00399     ret = SAR(msg,realm,public_identity,private_identity,assignment_type,data_available);
00400 
00401 done:           
00402     return ret; 
00403 error:
00404     ret = CSCF_RETURN_ERROR;        
00405     return ret;
00406 }
00407 
00429 int S_assign_server_unreg(struct sip_msg *msg,char *str1,char *str2 )
00430 {
00431     int ret=CSCF_RETURN_FALSE;
00432     str private_identity={0,0},public_identity={0,0},realm={0,0};
00433     int assignment_type = AVP_IMS_SAR_NO_ASSIGNMENT;
00434     int data_available = AVP_IMS_SAR_USER_DATA_NOT_AVAILABLE;
00435 
00436     /* First check the parameters */
00437     if (msg->first_line.type!=SIP_REQUEST)
00438     {
00439         LOG(L_ERR,"ERR:"M_NAME":S_assign_server_unreg: This message is not a request\n");
00440         goto error;
00441     }       
00442 
00443     realm.s = str1; realm.len = strlen(str1);
00444     if (!realm.len) {
00445         LOG(L_ERR,"ERR:"M_NAME":S_assign_server_unreg: No realm found\n");
00446         return CSCF_RETURN_BREAK;
00447     }
00448 
00449     enum s_dialog_direction dir = get_dialog_direction(str2);
00450     
00451     switch (dir){
00452         case DLG_MOBILE_ORIGINATING:
00453             public_identity = cscf_get_asserted_identity(msg);
00454             if (!public_identity.len) {
00455                 LOG(L_DBG,"DBG:"M_NAME":S_assign_server_unreg(orig): public identity missing\n");       
00456                 return ret;
00457             }
00458             break;
00459         case DLG_MOBILE_TERMINATING:
00460             public_identity = cscf_get_public_identity_from_requri(msg);
00461             if (!public_identity.len) {
00462                 LOG(L_DBG,"DBG:"M_NAME":S_assign_server_unreg(term): public identity missing\n");       
00463                 return ret;
00464             }
00465             break;
00466         default:
00467             LOG(L_ERR,"ERR:"M_NAME":S_assign_server_unreg: bad dialog direction parameter\n");
00468             goto error;
00469     }
00470     
00471     assignment_type = AVP_IMS_SAR_UNREGISTERED_USER;
00472     
00473     //TODO
00474     //if (userdataavailable) data_available = AVP_IMS_SAR_USER_DATA_ALREADY_AVAILABLE;
00475     //else
00476     data_available = AVP_IMS_SAR_USER_DATA_NOT_AVAILABLE;
00477     
00478     ret = SAR(0,realm,public_identity,private_identity,assignment_type,data_available);
00479     
00480     return ret; 
00481 error:
00482     ret = CSCF_RETURN_ERROR;        
00483     return ret;
00484 }
00485 
00486 
00498 int SAR(struct sip_msg *msg, str realm, str public_identity, str private_identity,
00499                 int assignment_type,int data_available)
00500 {
00501     AAAMessage *saa;
00502     int rc=-1,experimental_rc=-1;
00503     str xml={0,0},ccf1={0,0},ccf2={0,0},ecf1={0,0},ecf2={0,0};
00504         
00505     if (realm.len==0){
00506         realm = cscf_get_realm_from_uri(private_identity);
00507     }       
00508     saa = Cx_SAR(msg,public_identity,private_identity,scscf_name_str,realm,
00509         assignment_type,data_available);
00510     
00511     if (!saa){
00512         //TODO - add the warning code 99 in the reply   
00513         if (msg) S_REGISTER_reply(msg,480,MSG_480_DIAMETER_TIMEOUT_SAR);        
00514         goto error;
00515     }
00516     
00517     if (!Cx_get_result_code(saa,&rc)&&
00518         !Cx_get_experimental_result_code(saa,&experimental_rc))
00519     {
00520         if (msg) S_REGISTER_reply(msg,480,MSG_480_DIAMETER_MISSING_AVP);
00521         goto done;
00522     }
00523     
00524     switch(rc){
00525         case -1:
00526             switch(experimental_rc){
00527                 case RC_IMS_DIAMETER_ERROR_USER_UNKNOWN:
00528                     if (msg) S_REGISTER_reply(msg,403,MSG_403_USER_UNKNOWN);        
00529                     break;
00530                 case RC_IMS_DIAMETER_ERROR_IDENTITIES_DONT_MATCH:
00531                     if (msg) S_REGISTER_reply(msg,403,MSG_403_IDENTITIES_DONT_MATCH);       
00532                     break;
00533                 case RC_IMS_DIAMETER_ERROR_AUTH_SCHEME_NOT_SUPPORTED:
00534                     if (msg) S_REGISTER_reply(msg,403,MSG_403_AUTH_SCHEME_UNSOPPORTED);     
00535                     break;
00536                 
00537                 default:
00538                     if (msg) S_REGISTER_reply(msg,403,MSG_403_UNKOWN_EXPERIMENTAL_RC);      
00539             }
00540             break;
00541         
00542         case AAA_UNABLE_TO_COMPLY:
00543             if (msg) S_REGISTER_reply(msg,403,MSG_403_UNABLE_TO_COMPLY);        
00544             break;
00545                 
00546         case AAA_SUCCESS:
00547             goto success;           
00548             break;
00549                         
00550         default:
00551             if (msg) S_REGISTER_reply(msg,403,MSG_403_UNKOWN_RC);       
00552     }
00553     
00554 goto done;      
00555     
00556 success:
00557     xml = Cx_get_user_data(saa);
00558     
00559     if (assignment_type==AVP_IMS_SAR_TIMEOUT_DEREGISTRATION ||
00560         assignment_type==AVP_IMS_SAR_USER_DEREGISTRATION ||
00561         assignment_type==AVP_IMS_SAR_TIMEOUT_DEREGISTRATION_STORE_SERVER_NAME ||
00562         assignment_type==AVP_IMS_SAR_USER_DEREGISTRATION_STORE_SERVER_NAME ||
00563         assignment_type==AVP_IMS_SAR_ADMINISTRATIVE_DEREGISTRATION
00564        )
00565     {
00566         drop_auth_userdata(private_identity,public_identity);
00567     }
00568     
00569     Cx_get_charging_info(saa,&ccf1,&ccf2,&ecf1,&ecf2);
00570     if (msg||assignment_type==AVP_IMS_SAR_UNREGISTERED_USER){
00571         int ret = save_location(msg,assignment_type,&xml,&ccf1,&ccf2,&ecf1,&ecf2);
00572         if (saa) cdpb.AAAFreeMessage(&saa);
00573         return ret;
00574     }else{
00575         /* it was called internally and there is no SIP message to respond to */        
00576     }
00577     if (saa) cdpb.AAAFreeMessage(&saa);
00578     return CSCF_RETURN_TRUE;
00579 done:   
00580     if (saa) cdpb.AAAFreeMessage(&saa);
00581     return CSCF_RETURN_FALSE;
00582 error:  
00583     if (saa) cdpb.AAAFreeMessage(&saa);
00584     return CSCF_RETURN_BREAK;
00585 }
00586 
00587 
00588 
00599 static inline int r_calc_expires(contact_t *c,unsigned int expires_hdr)
00600 {
00601     unsigned int r;
00602     if (expires_hdr>=0) r = expires_hdr;
00603     else r = registration_default_expires;
00604     if (c && c->expires)
00605         str2int(&(c->expires->body), (unsigned int*)&r); 
00606     if (r>0 && r<registration_min_expires) r = registration_min_expires;
00607     if (r>registration_max_expires) r = registration_max_expires;
00608     return time_now+r;
00609 }
00610 
00611 /*
00612  * Calculate contact q value as follows:
00613  * 1) If q parameter exists, use it
00614  * 2) If the parameter doesn't exist, use the default value
00615  */
00616 int r_calc_contact_q(param_t* _q, qvalue_t* _r)
00617 {
00618         if (!_q || (_q->body.len == 0)) {
00619                 *_r = -1;
00620         } else {
00621                 if (str2q(_r, _q->body.s, _q->body.len) < 0) {
00622                         LOG(L_ERR, "r_calc_contact_q(): Invalid q parameter\n");
00623                         return -1;
00624                 }
00625         }
00626         return 0;
00627 }
00628 
00637 static int r_add_contact(struct sip_msg *msg,str uri,int expires,qvalue_t qvalue)
00638 {
00639     str hdr;
00640     int r;
00641     hdr.s = pkg_malloc(10+uri.len+10+12+3+1);
00642     if (!hdr.s) return 0;
00643     if(qvalue != -1) {
00644         float q = (float)qvalue/1000;
00645         sprintf(hdr.s,"Contact: <%.*s>;expires=%d;q=%.3f\r\n",uri.len,uri.s,expires,q);
00646     }       
00647     else
00648         sprintf(hdr.s,"Contact: <%.*s>;expires=%d\r\n",uri.len,uri.s,expires);
00649     hdr.len = strlen(hdr.s);
00650     r = cscf_add_header_rpl(msg,&hdr);
00651     pkg_free(hdr.s);
00652     return r;
00653 }
00654 
00655 
00656 
00669 static inline int update_contacts(struct sip_msg* msg, int assignment_type,
00670      unsigned char is_star, ims_subscription **s, str* ua,str *path, str *ccf1,str *ccf2,str *ecf1,str *ecf2)
00671 {
00672     int i,j,s_used=0;
00673     r_public *p,*rpublic;
00674     r_contact *c=0;
00675     ims_public_identity *pi=0;
00676     struct hdr_field *h;
00677     contact_t *ci;
00678     int reg_state,expires_hdr=-1,expires,hash,rpublic_hash;
00679     str public_identity,sent_by={0,0};
00680     int contacts_added=0;
00681     qvalue_t qvalue;
00682     
00683 //  if (!*s) return 1;
00684     if (msg) {
00685         /* check for Early-IMS case */
00686         if (!registration_disable_early_ims && !msg->authorization){
00687             str received={0,0};     
00688             sent_by = cscf_get_last_via_sent_by(msg);
00689             if (sent_by.len){
00690                 received = cscf_get_last_via_received(msg);
00691                 if (received.len) sent_by=received;             
00692             }
00693         }
00694         expires_hdr = cscf_get_expires_hdr(msg);
00695     }
00696     
00697     r_act_time();
00698     LOG(L_DBG,"DBG:"M_NAME":update_contacts: Assign Type %d\n",assignment_type);
00699     switch (assignment_type){
00700         case AVP_IMS_SAR_REGISTRATION:
00701             reg_state = IMS_USER_REGISTERED;
00702             if (!*s) break;
00703             for(i=0;i<(*s)->service_profiles_cnt;i++)
00704                 for(j=0;j<(*s)->service_profiles[i].public_identities_cnt;j++){
00705                     pi = &((*s)->service_profiles[i].public_identities[j]);
00706                     if (!pi->barring){
00707                         if (!(p=update_r_public(pi->public_identity,&reg_state,s,ccf1,ccf2,ecf1,ecf2))){
00708                             LOG(L_ERR,"ERR:"M_NAME":update_contacts: error on <%.*s>\n",
00709                                 pi->public_identity.len,pi->public_identity.s);
00710                             goto error;
00711                         }
00712                         s_used++;
00713                         if (!registration_disable_early_ims && sent_by.len) {
00714                             if (p->early_ims_ip.s) shm_free(p->early_ims_ip.s);
00715                             STR_SHM_DUP(p->early_ims_ip,sent_by,"IP Early IMS");
00716                         }
00717                         if (is_star){
00718                             LOG(L_ERR,"ERR:"M_NAME":update_contacts: STAR not accepted in contact for Registration.\n");
00719                         }else{
00720                             for(h=msg->contact;h;h=h->next)
00721                                 if (h->type==HDR_CONTACT_T && h->parsed)
00722                                  for(ci=((contact_body_t*)h->parsed)->contacts;ci;ci=ci->next){
00723                                     if(r_calc_contact_q(ci->q, &qvalue) != 0){
00724                                         LOG(L_ERR,"ERR:"M_NAME":update_contacts: error on <%.*s>\n",
00725                                                                                         ci->uri.len,ci->uri.s);
00726                                                                                 goto error;
00727                                     }
00728                                     expires = r_calc_expires(ci,expires_hdr);
00729                                     if (!(c=update_r_contact(p,ci->uri,&expires,ua,path,qvalue))){
00730                                         LOG(L_ERR,"ERR:"M_NAME":update_contacts: error on <%.*s>\n",
00731                                             ci->uri.len,ci->uri.s);
00732                                         goto error;
00733                                     }
00734                                     if (assignment_type == AVP_IMS_SAR_REGISTRATION)
00735                                         S_event_reg(p,c,0,IMS_REGISTRAR_CONTACT_REGISTERED,0);
00736                                     else 
00737                                         S_event_reg(p,c,0,IMS_REGISTRAR_CONTACT_REFRESHED,0);
00738                                     
00739                                 }
00740                             if (!contacts_added){
00741                                 for(c=p->head;c;c=c->next)
00742                                     r_add_contact(msg,c->uri,c->expires-time_now,c->qvalue);
00743                                 contacts_added = 1;
00744                             }
00745                         }
00746                         r_unlock(p->hash);
00747                     }
00748                 }
00749             break;
00750         case AVP_IMS_SAR_RE_REGISTRATION:
00751             reg_state = IMS_USER_REGISTERED;
00752             public_identity = cscf_get_public_identity(msg);
00753             if (!public_identity.len) {
00754                     LOG(L_ERR,"ERR:"M_NAME":update_contacts: message contains no public identity\n");
00755                     goto error;
00756             }
00757 
00758             p = get_r_public(public_identity);
00759             if (!p){
00760                 LOG(L_ERR,"ERR:"M_NAME":update_contacts: error on <%.*s> - not found in registrar\n",
00761                     public_identity.len,public_identity.s);
00762                 goto error;
00763             }
00764 
00765             if (!registration_disable_early_ims && sent_by.len) {
00766                 if (p->early_ims_ip.s) shm_free(p->early_ims_ip.s);
00767                 STR_SHM_DUP(p->early_ims_ip,sent_by,"IP Early IMS");
00768             }
00769             if (is_star){
00770                 LOG(L_ERR,"ERR:"M_NAME":update_contacts: STAR not accepted in contact for Re-Registration.\n");
00771             }else{
00772                 for(h=msg->contact;h;h=h->next)
00773                     if (h->type==HDR_CONTACT_T && h->parsed)
00774                      for(ci=((contact_body_t*)h->parsed)->contacts;ci;ci=ci->next){
00775             if(r_calc_contact_q(ci->q, &qvalue) != 0){
00776                             LOG(L_ERR,"ERR:"M_NAME":update_contacts: error on <%.*s>\n",
00777                                    ci->uri.len,ci->uri.s);
00778                                 goto error;
00779                         }
00780                         expires = r_calc_expires(ci,expires_hdr);
00781                         if (!(c=update_r_contact(p,ci->uri,&expires,ua,path,qvalue))){
00782                             LOG(L_ERR,"ERR:"M_NAME":update_contacts: error on <%.*s>\n",
00783                                 ci->uri.len,ci->uri.s);
00784                             goto error;
00785                         }
00786                         if (assignment_type == AVP_IMS_SAR_REGISTRATION)
00787                             S_event_reg(p,c,0,IMS_REGISTRAR_CONTACT_REGISTERED,0);
00788                         else
00789                             S_event_reg(p,c,0,IMS_REGISTRAR_CONTACT_REFRESHED,0);                        
00790                     }
00791                 for(c=p->head;c;c=c->next)
00792                     r_add_contact(msg,c->uri,c->expires-time_now,c->qvalue);
00793             }            
00794 
00795             /* now update the implicit set */
00796             if (p->s)
00797             for(i=0;i<p->s->service_profiles_cnt;i++)
00798                 for(j=0;j<p->s->service_profiles[i].public_identities_cnt;j++){
00799                     pi = &(p->s->service_profiles[i].public_identities[j]);
00800                     if (public_identity.len==pi->public_identity.len &&
00801                         strncasecmp(pi->public_identity.s,public_identity.s,public_identity.len)==0) continue;
00802 
00803                     rpublic = update_r_public_previous_lock(pi->public_identity,p->hash,&reg_state,s,ccf1,ccf2,ecf1,ecf2);
00804                     if (!rpublic){
00805                         LOG(L_ERR,"ERR:"M_NAME":update_contacts: error on <%.*s>\n",
00806                             pi->public_identity.len,pi->public_identity.s);
00807                         continue;
00808                     }
00809 
00810                     if (!registration_disable_early_ims && sent_by.len) {
00811                         if (rpublic->early_ims_ip.s) shm_free(rpublic->early_ims_ip.s);
00812                             STR_SHM_DUP(rpublic->early_ims_ip,sent_by,"IP Early IMS");
00813                     }
00814                     if (is_star){
00815                             LOG(L_ERR,"ERR:"M_NAME":update_contacts: STAR not accepted in contact for Re-Registration.\n");
00816                     }else{
00817                         for(h=msg->contact;h;h=h->next)
00818                             if (h->type==HDR_CONTACT_T && h->parsed)
00819                                 for(ci=((contact_body_t*)h->parsed)->contacts;ci;ci=ci->next){
00820                     if(r_calc_contact_q(ci->q, &qvalue) != 0){
00821                                             LOG(L_ERR,"ERR:"M_NAME":update_contacts: error on <%.*s>\n",
00822                                                     ci->uri.len,ci->uri.s);
00823                                             goto error;
00824                                         }
00825                                     expires = r_calc_expires(ci,expires_hdr);
00826                                     if (!(c=update_r_contact(rpublic,ci->uri,&expires,ua,path,qvalue))){
00827                                         LOG(L_ERR,"ERR:"M_NAME":update_contacts: error on <%.*s> - implicit identity not found in registrar\n",
00828                                             ci->uri.len,ci->uri.s);
00829                                         goto error;
00830                                     }
00831                                     if (assignment_type == AVP_IMS_SAR_REGISTRATION)
00832                                         S_event_reg(rpublic,c,0,IMS_REGISTRAR_CONTACT_REGISTERED,0);
00833                                     else
00834                                         S_event_reg(rpublic,c,0,IMS_REGISTRAR_CONTACT_REFRESHED,0);
00835                                 }
00836                     }
00837                     if (rpublic->hash!=p->hash) r_unlock(rpublic->hash);                            
00838             }
00839             r_unlock(p->hash);
00840             break;      
00841             
00842         case AVP_IMS_SAR_USER_DEREGISTRATION:
00843             public_identity = cscf_get_public_identity(msg);
00844             if (!public_identity.len) {
00845                 LOG(L_ERR,"ERR:"M_NAME":update_contacts: message contains no public identity\n");
00846                 goto error;
00847             }
00848             p = get_r_public(public_identity);
00849 
00850             if (!p){
00851                 LOG(L_ERR,"ERR:"M_NAME":update_contacts: error on <%.*s> - not found in registrar\n",
00852                     public_identity.len,public_identity.s);
00853                 goto error;
00854             }
00855 
00856             //deregister public identity that is on the message
00857             if (is_star){
00858                 c = p->head;
00859                 while(c){
00860                     c->expires = time_now;
00861                     S_event_reg(p,c,0,IMS_REGISTRAR_CONTACT_UNREGISTERED,0);
00862                     r_add_contact(msg,c->uri,0,c->qvalue);
00863                     del_r_contact(p,c);
00864                     c = c->next;
00865                 }
00866             }else{
00867                 for(h=msg->contact;h;h=h->next)
00868                     if (h->type==HDR_CONTACT_T && h->parsed)
00869                         for(ci=((contact_body_t*)h->parsed)->contacts;ci;ci=ci->next){
00870                             c = get_r_contact(p,ci->uri);
00871                             if (c) {
00872                                 c->expires = time_now;
00873                                 S_event_reg(p,c,0,IMS_REGISTRAR_CONTACT_UNREGISTERED,0);
00874                                 r_add_contact(msg,c->uri,0,c->qvalue);
00875                                 del_r_contact(p,c);
00876                             }
00877                         }
00878                 for(c=p->head;c;c=c->next)
00879                     r_add_contact(msg,c->uri,c->expires-time_now,c->qvalue);                        
00880             }
00881 
00882             /* now update the implicit set */
00883             if (p->s)
00884             for(i=0;i<p->s->service_profiles_cnt;i++)
00885                 for(j=0;j<p->s->service_profiles[i].public_identities_cnt;j++){
00886                     pi = &(p->s->service_profiles[i].public_identities[j]);
00887                     if (public_identity.len == pi->public_identity.len && 
00888                         strncasecmp(pi->public_identity.s,public_identity.s,public_identity.len)==0)    continue;
00889                         
00890                     rpublic = update_r_public_previous_lock(pi->public_identity,p->hash,&reg_state,s,ccf1,ccf2,ecf1,ecf2);              
00891                     if (!rpublic){
00892                         LOG(L_ERR,"ERR:"M_NAME":update_contacts: error on <%.*s> - implicit identity not found in registrar\n",
00893                             pi->public_identity.len,pi->public_identity.s);
00894                         continue;
00895                     }
00896                     s_used++;
00897                     if (is_star){
00898                         c = rpublic->head;
00899                         while(c){
00900                             c->expires = time_now;
00901                             S_event_reg(rpublic,c,0,IMS_REGISTRAR_CONTACT_UNREGISTERED,0);                                                                          
00902                             del_r_contact(rpublic,c);   
00903                             c = c->next;
00904                         }
00905                     }else{
00906                         for(h=msg->contact;h;h=h->next)
00907                             if (h->type==HDR_CONTACT_T && h->parsed)
00908                                 for(ci=((contact_body_t*)h->parsed)->contacts;ci;ci=ci->next){
00909                                     c = get_r_contact(rpublic,ci->uri);
00910                                     if (c) {
00911                                         c->expires = time_now;
00912                                         S_event_reg(rpublic,c,0,IMS_REGISTRAR_CONTACT_UNREGISTERED,0);                     
00913                                         del_r_contact(rpublic,c);
00914                                     }
00915                             }
00916                     }
00917                     rpublic_hash = rpublic->hash;
00918                     if (!rpublic->head) 
00919                         del_r_public(rpublic);
00920                                                 
00921                     if (p->hash!=rpublic_hash) r_unlock(rpublic_hash);
00922                 }
00923 
00924             hash = p->hash;
00925             if (!p->head) 
00926                 del_r_public(p);
00927             r_unlock(hash);         
00928             break;
00929                         
00930         case AVP_IMS_SAR_UNREGISTERED_USER:         
00931             reg_state = IMS_USER_UNREGISTERED;
00932             r_act_time();
00933             if (!*s) break;
00934             for(i=0;i<(*s)->service_profiles_cnt;i++)
00935                 for(j=0;j<(*s)->service_profiles[i].public_identities_cnt;j++){
00936                     pi = &((*s)->service_profiles[i].public_identities[j]);
00937                     if (!pi->barring){
00938                         if (!(p=update_r_public(pi->public_identity,&reg_state,s,ccf1,ccf2,ecf1,ecf2))){
00939                             LOG(L_ERR,"ERR:"M_NAME":update_contacts: error on <%.*s>\n",
00940                                 pi->public_identity.len,pi->public_identity.s);
00941