registrar.c File Reference


Detailed Description

Serving-CSCF - Registrar-Related Operations.

Author:
Dragos Vingarzan vingarzan -at- fokus dot fraunhofer dot de

Definition in file registrar.c.

#include <time.h>
#include "../../parser/contact/contact.h"
#include "../../parser/contact/parse_contact.h"
#include "../../ut.h"
#include "../tm/tm_load.h"
#include "../cdp/cdp_load.h"
#include "../../dset.h"
#include "registrar.h"
#include "registration.h"
#include "mod.h"
#include "registrar_parser.h"
#include "registrar_storage.h"
#include "sip.h"
#include "cx.h"
#include "cx_avp.h"
#include "sip_messages.h"
#include "dlg_state.h"

Go to the source code of this file.

Functions

void registrar_timer (unsigned int ticks, void *param)
 The Registrar timer looks for expires contacts and removes them.
int S_assign_server (struct sip_msg *msg, char *str1, char *str2)
 Does the Server Assignment procedures, assigning this S-CSCF to the user.
int S_assign_server_unreg (struct sip_msg *msg, char *str1, char *str2)
 Does the Server Assignment procedures, assigning this S-CSCF to the user without previous registration.
int SAR (struct sip_msg *msg, str realm, str public_identity, str private_identity, int assignment_type, int data_available)
 Sends a SAR.
static int r_calc_expires (contact_t *c, unsigned int expires_hdr)
 Calculates the expiration time for one contact.
int r_calc_contact_q (param_t *_q, qvalue_t *_r)
static int r_add_contact (struct sip_msg *msg, str uri, int expires, qvalue_t qvalue)
 Adds a Contact header to the reply, containing the approved expires.
static int update_contacts (struct sip_msg *msg, int assignment_type, unsigned char is_star, ims_subscription **s, str *ua, str *path, str *ccf1, str *ccf2, str *ecf1, str *ecf2)
 Updates the contacts in the registrar with the new values received, for the addresses received in the SAA.
int insert_p_associated_uri (struct sip_msg *msg, ims_subscription *s)
 Adds to the response the P-Associated-URI header.
int save_location (struct sip_msg *msg, int assignment_type, str *xml, str *ccf1, str *ccf2, str *ecf1, str *ecf2)
 Save the contacts.
int S_update_contacts (struct sip_msg *msg, char *str1, char *str2)
 Save the contacts.
static int r_add_route_path (struct sip_msg *msg, r_contact *c)
 Adds a Route header containing the saved Path.
static int r_add_p_called_party_id (struct sip_msg *msg)
 Adds the P-Called-Party-ID header containing the Request-URI before that will be resolved to the contact address.
int S_lookup (struct sip_msg *msg, char *str1, char *str2)
 Lookup for the Request-URI in registrar and rewrite request URI with the contact address.
int r_is_registered_id (str public_identity)
 Finds if the user is registered at this S-CSCF.
int r_is_not_registered_id (str public_identity)
 Finds if the user is not registered at this S-CSCF.
int r_is_unregistered_id (str public_identity)
 Finds if the user is unregistered at this S-CSCF.
int S_term_registered (struct sip_msg *msg, char *str1, char *str2)
 Finds if the terminating user (in the RequestURI) is registered at this S-CSCF.
int S_term_not_registered (struct sip_msg *msg, char *str1, char *str2)
 Finds if the terminating user (in the RequestURI) is not registered at this S-CSCF.
int S_term_unregistered (struct sip_msg *msg, char *str1, char *str2)
 Finds if the terminating user (in the RequestURI) is unregistered at this S-CSCF.
int S_orig_registered (struct sip_msg *msg, char *str1, char *str2)
 Finds if the originating user (in P-Asserted-Identity) is registered at this S-CSCF.
int S_add_p_asserted_identity (struct sip_msg *msg, char *str1, char *str2)
 Adds suplimentary P-Asserted-Identity.
int S_orig_not_registered (struct sip_msg *msg, char *str1, char *str2)
 Finds if the originating user (in P-Asserted-Identity) is not registered at this S-CSCF.
int S_orig_unregistered (struct sip_msg *msg, char *str1, char *str2)
 Finds if the originating user (in P-Asserted-Identity) is unregistered at this S-CSCF.
int S_is_not_registered (struct sip_msg *msg, char *str1, char *str2)
 Finds if the user in To header is not registered at this S-CSCF.
int S_mobile_originating (struct sip_msg *msg, char *str1, char *str2)
 Finds if the message contains as first route the specific service route for originating case (indicated in the Service-Route at registration), or if the topmost route contains the "orig" parameter.
int S_is_barred (str public_identity)
 Finds if the user exists and it is barred.
int S_originating_barred (struct sip_msg *msg, char *str1, char *str2)
 Finds if the originating user is barred.
int S_terminating_barred (struct sip_msg *msg, char *str1, char *str2)
 Finds if the terminating user is barred.

Variables

tm_binds tmb
 Structure with pointers to tm funcs.
cdp_binds cdpb
 Structure with pointers to cdp funcs.
int r_hash_size
 Size of S-CSCF registrar hash table.
r_hash_slotregistrar
 The S-CSCF registrar.
str scscf_name_str
 fixed name of the S-CSCF
str scscf_service_route_uri
 just the service route uri
str scscf_registration_min_expires
 fixed minimum registration expiration time
int server_assignment_store_data
 whether to ask to keep the data in SAR
int registration_default_expires
 the default value for expires if none found
int registration_min_expires
 minimum registration expiration time
int registration_max_expires
 maximum registration expiration time
int registration_disable_early_ims
 if to disable the Early-IMS checks
time_t time_now
 Current time of the S-CSCF registrar.
int append_branches
 if to append branches
str hdr_p_associated_uri1 = {"P-Associated-URI: <",19}
str hdr_p_associated_uri2 = {">, <",4}
str hdr_p_associated_uri3 = {">\r\n",3}
str route_hdr1 = {"Route: ",7}
str route_hdr2 = {"\r\n",2}
str p_called_party_id_hdr1 = {"P-Called-Party-ID: <",20}
str p_called_party_id_hdr2 = {">\r\n",3}
static str p_asserted_identity_s = {"P-Asserted-Identity: <",22}
static str p_asserted_identity_e = {">\r\n",3}
static str p_asserted_identity_param = {";user=phone",11}
static str p_asserted_identity_tel = {"tel:",4}
static str route_header = {"Route",5}


Function Documentation

void registrar_timer ( unsigned int  ticks,
void *  param 
)

The Registrar timer looks for expires contacts and removes them.

Parameters:
ticks - the current time
param - pointer to the domain_list

Definition at line 109 of file registrar.c.

References _r_public::aor, AVP_IMS_SAR_TIMEOUT_DEREGISTRATION, AVP_IMS_SAR_TIMEOUT_DEREGISTRATION_STORE_SERVER_NAME, cscf_get_realm_from_uri(), del_r_contact(), del_r_public(), del_r_subscriber(), DEREGISTERED, _r_contact::expires, get_r_public_previous_lock(), _r_public::hash, _r_contact::head, _r_public::head, r_hash_slot::head, if, IMS_REGISTRAR_CONTACT_EXPIRED, M_NAME, _r_subscriber::next, _r_contact::next, _r_public::next, NOT_REGISTERED, P_security_drop(), _r_contact::pinhole, ims_subscription::private_identity, ims_service_profile::public_identities, ims_service_profile::public_identities_cnt, ims_public_identity::public_identity, r_act_time(), r_hash_size, r_lock(), r_unlock(), r_valid_contact(), r_valid_subscriber(), REG_PENDING, _r_contact::reg_state, _r_public::reg_state, REGISTERED, registrar, _r_public::s, S_event_reg(), SAR(), SEC_IPSEC, SEC_TLS, _r_contact::security, _r_contact::security_temp, server_assignment_store_data, ims_subscription::service_profiles, ims_subscription::service_profiles_cnt, _r_public::shead, _r_subscriber::subscriber, time_now, _r_security::type, UNREGISTERED, and _r_contact::uri.

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 }

int S_assign_server ( struct sip_msg *  msg,
char *  str1,
char *  str2 
)

Does the Server Assignment procedures, assigning this S-CSCF to the user.

Covered cases: AVP_IMS_SAR_NO_ASSIGNMENT = 0 AVP_IMS_SAR_REGISTRATION = 1, YES,HERE AVP_IMS_SAR_RE_REGISTRATION = 2, AVP_IMS_SAR_UNREGISTERED_USER = 3, in S_assign_server_unreg AVP_IMS_SAR_TIMEOUT_DEREGISTRATION = 4, AVP_IMS_SAR_USER_DEREGISTRATION = 5, YES,HERE AVP_IMS_SAR_TIMEOUT_DEREGISTRATION_STORE_SERVER_NAME = 6, AVP_IMS_SAR_USER_DEREGISTRATION_STORE_SERVER_NAME = 7, YES,HERE AVP_IMS_SAR_ADMINISTRATIVE_DEREGISTRATION = 8, AVP_IMS_SAR_AUTHENTICATION_FAILURE = 9, AVP_IMS_SAR_AUTHENTICATION_TIMEOUT = 10, AVP_IMS_SAR_DEREGISTRATION_TOO_MUCH_DATA

Parameters:
msg - the SIP REGISTER message (that is authorized)
str1 - the realm to look for in Authorization
str2 - not used
Returns:
true if ok, false if not, break on error

Definition at line 302 of file registrar.c.

References AVP_IMS_SAR_NO_ASSIGNMENT, AVP_IMS_SAR_RE_REGISTRATION, AVP_IMS_SAR_REGISTRATION, AVP_IMS_SAR_USER_DATA_ALREADY_AVAILABLE, AVP_IMS_SAR_USER_DATA_NOT_AVAILABLE, AVP_IMS_SAR_USER_DEREGISTRATION, AVP_IMS_SAR_USER_DEREGISTRATION_STORE_SERVER_NAME, ci, cscf_get_max_expires(), cscf_get_private_identity(), cscf_get_public_identity(), cscf_parse_contacts(), CSCF_RETURN_BREAK, CSCF_RETURN_ERROR, CSCF_RETURN_FALSE, CSCF_RETURN_TRUE, drop_auth_userdata(), get_r_contact(), get_r_public(), _r_public::hash, _r_public::head, M_NAME, _r_contact::next, r_is_registered_id(), r_unlock(), SAR(), save_location(), and server_assignment_store_data.

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 }

int S_assign_server_unreg ( struct sip_msg *  msg,
char *  str1,
char *  str2 
)

Does the Server Assignment procedures, assigning this S-CSCF to the user without previous registration.

Covered cases: AVP_IMS_SAR_NO_ASSIGNMENT = 0 AVP_IMS_SAR_REGISTRATION = 1, YES, NOT HERE AVP_IMS_SAR_RE_REGISTRATION = 2, AVP_IMS_SAR_UNREGISTERED_USER = 3, YES, HERE AVP_IMS_SAR_TIMEOUT_DEREGISTRATION = 4, AVP_IMS_SAR_USER_DEREGISTRATION = 5, YES, NOT HERE AVP_IMS_SAR_TIMEOUT_DEREGISTRATION_STORE_SERVER_NAME = 6, AVP_IMS_SAR_USER_DEREGISTRATION_STORE_SERVER_NAME = 7, YES, NOT HERE AVP_IMS_SAR_ADMINISTRATIVE_DEREGISTRATION = 8, AVP_IMS_SAR_AUTHENTICATION_FAILURE = 9, AVP_IMS_SAR_AUTHENTICATION_TIMEOUT = 10, AVP_IMS_SAR_DEREGISTRATION_TOO_MUCH_DATA

Parameters:
msg - the SIP REGISTER message (that is authorized)
str1 - the realm to look for in Authorization
str2 - direction - "orig" or "term"
Returns:
true if ok, false if not, break on error

Definition at line 429 of file registrar.c.

References AVP_IMS_SAR_NO_ASSIGNMENT, AVP_IMS_SAR_UNREGISTERED_USER, AVP_IMS_SAR_USER_DATA_NOT_AVAILABLE, cscf_get_asserted_identity(), cscf_get_public_identity_from_requri(), CSCF_RETURN_BREAK, CSCF_RETURN_ERROR, CSCF_RETURN_FALSE, DLG_MOBILE_ORIGINATING, DLG_MOBILE_TERMINATING, get_dialog_direction(), M_NAME, and SAR().

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 }

int SAR ( struct sip_msg *  msg,
str  realm,
str  public_identity,
str  private_identity,
int  assignment_type,
int  data_available 
)

Sends a SAR.

Can respond with a SIP reply if msg!=0

Parameters:
msg - the SIP message
realm - the realm
public_identity - public identity
private_identity - private identity
assignment_type - assignment type
data_available - if the data is already available
Returns:
CSCF_RETURN_TRUE if ok, CSCF_RETURN_FALSE on error or CSCF_RETURN_BREAK on response sent out

Definition at line 498 of file registrar.c.

References AAA_SUCCESS, AAA_UNABLE_TO_COMPLY, cdp_binds::AAAFreeMessage, AVP_IMS_SAR_ADMINISTRATIVE_DEREGISTRATION, AVP_IMS_SAR_TIMEOUT_DEREGISTRATION, AVP_IMS_SAR_TIMEOUT_DEREGISTRATION_STORE_SERVER_NAME, AVP_IMS_SAR_UNREGISTERED_USER, AVP_IMS_SAR_USER_DEREGISTRATION, AVP_IMS_SAR_USER_DEREGISTRATION_STORE_SERVER_NAME, cdpb, cscf_get_realm_from_uri(), CSCF_RETURN_BREAK, CSCF_RETURN_FALSE, CSCF_RETURN_TRUE, Cx_get_charging_info(), Cx_get_experimental_result_code(), Cx_get_result_code(), Cx_get_user_data(), Cx_SAR(), drop_auth_userdata(), MSG_403_AUTH_SCHEME_UNSOPPORTED, MSG_403_IDENTITIES_DONT_MATCH, MSG_403_UNABLE_TO_COMPLY, MSG_403_UNKOWN_EXPERIMENTAL_RC, MSG_403_UNKOWN_RC, MSG_403_USER_UNKNOWN, MSG_480_DIAMETER_MISSING_AVP, MSG_480_DIAMETER_TIMEOUT_SAR, RC_IMS_DIAMETER_ERROR_AUTH_SCHEME_NOT_SUPPORTED, RC_IMS_DIAMETER_ERROR_IDENTITIES_DONT_MATCH, RC_IMS_DIAMETER_ERROR_USER_UNKNOWN, S_REGISTER_reply(), save_location(), and scscf_name_str.

Referenced by registrar_timer(), S_assign_server(), and S_assign_server_unreg().

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 }

static int r_calc_expires ( contact_t *  c,
unsigned int  expires_hdr 
) [inline, static]

Calculates the expiration time for one contact.

Tries to use the Expiration header, if not present then use the expires parameter of the contact, if param not present it defaults to the default value. Also checks

Parameters:
c - the contact to calcualte for
expires_hdr - value of expires hdr if present, if not -1
Returns:
the time of expiration

Definition at line 599 of file registrar.c.

References registration_default_expires, registration_max_expires, registration_min_expires, and time_now.

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 }

int r_calc_contact_q ( param_t *  _q,
qvalue_t *  _r 
)

Definition at line 616 of file registrar.c.

Referenced by update_contacts().

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 }

static int r_add_contact ( struct sip_msg *  msg,
str  uri,
int  expires,
qvalue_t  qvalue 
) [static]

Adds a Contact header to the reply, containing the approved expires.

Parameters:
msg - the SIP message to add contact header to its reply
uri - the contact uri
expires - the expiration time
qvalue - q-value
Returns:
1 if ok, 0 if not

Definition at line 637 of file registrar.c.

References cscf_add_header_rpl().

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 }

static int update_contacts ( struct sip_msg *  msg,
int  assignment_type,
unsigned char  is_star,
ims_subscription **  s,
str *  ua,
str *  path,
str *  ccf1,
str *  ccf2,
str *  ecf1,
str *  ecf2 
) [inline, static]

Updates the contacts in the registrar with the new values received, for the addresses received in the SAA.

Parameters:
msg - the SIP REGISTER message, if available
assignment_type - the value sent in SAR
ct - SIP contact list from message
is_star - if the contact header was of type STAR
s - the ims_subscription received in the SAA
ua - the user agent string
path - the path to save
Returns:
CSCF_RETURN_TRUE if ok, CSCF_RETURN_FALSE on error or CSCF_RETURN_BREAK on response sent out

Definition at line 669 of file registrar.c.

References AVP_IMS_SAR_REGISTRATION, ims_public_identity::barring, ci, cscf_get_expires_hdr(), cscf_get_last_via_received(), cscf_get_last_via_sent_by(), _r_public::early_ims_ip, if, IMS_REGISTRAR_CONTACT_REFRESHED, IMS_REGISTRAR_CONTACT_REGISTERED, IMS_USER_REGISTERED, M_NAME, ims_public_identity::public_identity, r_act_time(), r_calc_contact_q(), r_calc_expires(), registration_disable_early_ims, S_event_reg(), STR_SHM_DUP, update_r_contact(), and update_r_public().

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->