registrar.c File Reference


Detailed Description

Proxy-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 "../../dset.h"
#include "registrar.h"
#include "registrar_subscribe.h"
#include "mod.h"
#include "sip.h"
#include "nat_helper.h"
#include "security.h"
#include "ims_pm.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.
static int r_calc_expires (contact_t *c, int expires_hdr, int local_time_now)
 Calculates the expiration time for one contact.
static int update_contacts (struct sip_msg *req, struct sip_msg *rpl, unsigned char is_star, int expires_hdr, str *public_id, int public_id_cnt, str *service_route, int service_route_cnt, int requires_nat)
 Updates the registrar with the new values.
int P_save_location (struct sip_msg *rpl, char *str1, char *str2)
 Save the contacts and their associated public ids.
int r_is_integrity_protected (str host, int port, int r_port, int transport, unsigned long session_hash)
 Finds if the message is integrity protected.
int r_is_registered (str host, int port, int transport)
 Finds if the user is registered.
name_addr_t r_assert_identity (str host, int port, int transport, name_addr_t preferred)
 Asserts the identity of the user and returns the value.

Variables

tm_binds tmb
 Structure with pointers to tm funcs.
time_t time_now
 current time
r_hash_slotregistrar
 the actual registrar
int r_hash_size
 number of hash slots in the registrar
int pcscf_nat_enable
 whether to enable NAT
int pcscf_nat_ping
 whether to ping anything
int pcscf_nat_pingall
 whether to ping also the UA that don't look like being behind a NAT
int pcscf_nat_detection_type
 the NAT detection tests


Function Documentation

void registrar_timer ( unsigned int  ticks,
void *  param 
)

The Registrar timer looks for expires contacts and removes them.

For the non-deleted contacts a ping is sent if the UA is behind a NAT.

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

Definition at line 91 of file registrar.c.

Referenced by mod_init().

00092 {
00093     r_contact *c,*cn;
00094     int i;
00095     #ifdef WITH_IMS_PM
00096         int impu_cnt=0,contact_cnt=0,ipsec_cnt=0,tls_cnt=0,nat_cnt=0;
00097         r_public *rp;
00098     #endif
00099     
00100     LOG(L_DBG,"DBG:"M_NAME":registrar_timer: Called at %d\n",ticks);
00101     if (!registrar) registrar = (r_hash_slot*)param;
00102 
00103     r_act_time();
00104     
00105     for(i=0;i<r_hash_size;i++){
00106         r_lock(i);
00107             c = registrar[i].head;
00108             while(c){
00109                 cn = c->next;
00110                 switch (c->reg_state){
00111                     case NOT_REGISTERED:
00112                         LOG(L_DBG,"DBG:"M_NAME":registrar_timer: Contact <%.*s> Not Registered and removed.\n",
00113                                 c->uri.len,c->uri.s);
00114                         del_r_contact(c);
00115                         break;
00116                     case REGISTERED:
00117                         if (c->expires<=time_now) {
00118                             LOG(L_DBG,"DBG:"M_NAME":registrar_timer: Contact <%.*s> expired and Deregistered.\n",
00119                                 c->uri.len,c->uri.s);       
00120                             if (c->security){
00121                                 /* If we have IPSec SAs, we keep them 60 seconds more to relay further messages */
00122                                 c->reg_state = DEREGISTERED;
00123                                 c->expires = time_now + 60;
00124                             }else{
00125                                 LOG(L_DBG,"DBG:"M_NAME":registrar_timer: Contact <%.*s> expired and removed.\n",
00126                                     c->uri.len,c->uri.s);                       
00127                                 del_r_contact(c);
00128                             }
00129                         }
00130                         #ifdef WITH_IMS_PM
00131                             else {
00132                                     contact_cnt++;
00133                                     for(rp=c->head;rp;rp=rp->next)
00134                                         impu_cnt++;
00135                                     if (c->security && c->security->type==SEC_IPSEC) ipsec_cnt++;
00136                                     if (c->security && c->security->type==SEC_TLS) tls_cnt++;               
00137                                     if (c->pinhole) nat_cnt++;
00138                             }           
00139                         #endif
00140                         break;
00141                     case DEREGISTERED:
00142                         if (c->expires<=time_now) {
00143                             LOG(L_DBG,"DBG:"M_NAME":registrar_timer: Contact <%.*s> expired and removed.\n",
00144                                 c->uri.len,c->uri.s);       
00145                             P_security_drop(c,c->security);
00146                             P_security_drop(c,c->security_temp);
00147                             del_r_contact(c);
00148                         }
00149                         break;
00150                     case REG_PENDING:
00151                         if (c->expires<=time_now) {
00152                             LOG(L_DBG,"DBG:"M_NAME":registrar_timer: Contact <%.*s> Registration pending expired and removed.\n",
00153                                 c->uri.len,c->uri.s);       
00154                             P_security_drop(c,c->security);
00155                             P_security_drop(c,c->security_temp);
00156                             del_r_contact(c);
00157                         }
00158                         break;
00159                 }               
00160                 if (pcscf_nat_enable && pcscf_nat_ping) nat_send_ping(c);
00161                 c = cn;
00162             }
00163         r_unlock(i);
00164     }
00165     print_r(L_INFO);
00166     #ifdef WITH_IMS_PM
00167         IMS_PM_LOG01(RD_NbrContact,contact_cnt);
00168         IMS_PM_LOG01(RD_NbrIMPU,impu_cnt);
00169         IMS_PM_LOG01(RD_NbrIPSecSA,ipsec_cnt);
00170         IMS_PM_LOG01(RD_NbrTLSSA,tls_cnt);
00171         IMS_PM_LOG01(RD_NbrNATPinHoles,nat_cnt);
00172     #endif
00173 }

static int r_calc_expires ( contact_t *  c,
int  expires_hdr,
int  local_time_now 
) [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 calculate for
expires_hdr - value of expires hdr if present, if not -1
local_time_now - the local time
Returns:
the time of expiration

Definition at line 187 of file registrar.c.

Referenced by update_contacts().

00188 {
00189     unsigned int r;
00190     if (expires_hdr>=0) r = expires_hdr;
00191     if (c) 
00192         str2int(&(c->expires->body), (unsigned int*)&r);
00193         
00194     return local_time_now+r;
00195 }

static int update_contacts ( struct sip_msg *  req,
struct sip_msg *  rpl,
unsigned char  is_star,
int  expires_hdr,
str *  public_id,
int  public_id_cnt,
str *  service_route,
int  service_route_cnt,
int  requires_nat 
) [inline, static]

Updates the registrar with the new values.

Parameters:
req - the REGISTER request - to extract NAT info
rpl - the REGISTER reply - to extract contact info
is_star - whether this was a STAR contact header
expires_hdr - value of the Expires header
public_id - array of public identities attached to this contact
public_id_cnt - size of the public_id array
service_route - array of Service-Routes
service_route_cnt - size of the service_route array
requires_nat - if to create pinholes
Returns:
the maximum expiration time, -1 on error

Add the public identities

Definition at line 211 of file registrar.c.

References DEREGISTERED, _r_contact::hash, M_NAME, nat_msg_origin(), r_act_time(), r_calc_expires(), r_unlock(), REGISTERED, time_now, update_r_contact(), and update_r_public().

Referenced by P_save_location(), and save_location().

00213 {
00214     r_contact *rc;
00215     enum Reg_States reg_state=REGISTERED;
00216     int expires=0;
00217     int is_default=0,i;
00218     struct sip_uri puri;
00219     int max_expires=-1;
00220     int local_time_now;
00221     struct hdr_field *h;
00222     contact_t *c;
00223     r_nat_dest *pinhole;
00224     
00225     
00226     r_act_time();
00227     local_time_now = time_now;
00228     if (is_star){
00229         /* first of all, we shouldn't get here...
00230          * then, we will update on NOTIFY */
00231         return 0;
00232     }   
00233     for(h=rpl->contact;h;h=h->next)
00234         if (h->type==HDR_CONTACT_T && h->parsed)
00235          for(c=((contact_body_t*)h->parsed)->contacts;c;c=c->next){
00236             LOG(L_DBG,"DBG:"M_NAME":update_contact: <%.*s>\n",c->uri.len,c->uri.s);
00237             
00238             expires = r_calc_expires(c,expires_hdr,local_time_now);
00239             
00240             if (parse_uri(c->uri.s,c->uri.len,&puri)<0){
00241                 LOG(L_DBG,"DBG:"M_NAME":update_contact: Error parsing Contact URI <%.*s>\n",c->uri.len,c->uri.s);
00242                 continue;           
00243             }
00244             if (puri.port_no==0) puri.port_no=5060;
00245             LOG(L_DBG,"DBG:"M_NAME":update_contact: %d %.*s : %d\n",
00246                 puri.proto, puri.host.len,puri.host.s,puri.port_no);
00247             
00248             if (expires>local_time_now) {
00249                 if (requires_nat) {     
00250                     pinhole = nat_msg_origin(req);
00251                     rc = update_r_contact(puri.host,puri.port_no,puri.proto,
00252                         &(c->uri),&reg_state,&expires,&service_route,&service_route_cnt, &pinhole);
00253                 }else{
00254                     rc = update_r_contact(puri.host,puri.port_no,puri.proto,
00255                         &(c->uri),&reg_state,&expires,&service_route,&service_route_cnt, 0);
00256                 }
00257                 if (expires-time_now>max_expires) max_expires=expires-time_now;
00258             }
00259             else {
00260                 reg_state = DEREGISTERED;
00261                 expires = local_time_now+30;
00262                 rc = update_r_contact(puri.host,puri.port_no,puri.proto,
00263                         0,&reg_state,&expires,0,0,0);
00264                 if (rc) r_unlock(rc->hash);
00265                 if (0>max_expires) max_expires = 0;
00266                 rc = 0;
00267             }
00268             
00270             if (rc){
00271                 is_default=1;
00272                 if (public_id_cnt){
00273                     update_r_public(rc,public_id[0],&is_default);
00274                     is_default=0;
00275                     for(i=1;i<public_id_cnt;i++)
00276                         update_r_public(rc,public_id[i],&is_default);
00277                 }
00278                 r_unlock(rc->hash);
00279             }
00280     }
00281     return max_expires;
00282 }

int P_save_location ( struct sip_msg *  rpl,
char *  str1,
char *  str2 
)

Save the contacts and their associated public ids.

Parameters:
rpl - the SIP Register 200 OK response that contains the Expire and Contact headers
str1 - not used
str2 - not used
Returns:
CSCF_RETURN_TRUE if OK, CSCF_RETURN_ERROR on error

Removed because this would parse the hdr, but then it will fail to free the hdr->parsed

Definition at line 294 of file registrar.c.

References cscf_get_expires_hdr(), cscf_get_p_associated_uri(), cscf_get_realm(), cscf_get_request_from_reply(), cscf_get_service_route(), cscf_parse_contacts(), CSCF_RETURN_ERROR, CSCF_RETURN_TRUE, M_NAME, requires_nat(), and update_contacts().

00295 {
00296     struct sip_msg *req;
00297     contact_body_t* b=0;    
00298     str realm;
00299     int expires_hdr=0;
00300     str *public_id=0;
00301     int public_id_cnt=0;
00302     int expires;
00303     str *service_route=0;
00304     int service_route_cnt;
00305         
00306     req = cscf_get_request_from_reply(rpl);
00307     if (!req){
00308         LOG(L_ERR,"ERR:"M_NAME":P_save_location: No transactional request found.\n");
00309         goto error;
00310     }
00311     
00312     expires_hdr = cscf_get_expires_hdr(rpl);
00314 //  if (expires_hdr<0) 
00315 //      expires_hdr = cscf_get_expires_hdr(req);
00316     
00317     if (parse_headers(rpl, HDR_EOH_F, 0) <0) {
00318         LOG(L_ERR,"ERR:"M_NAME":r_save_location: error parsing headers\n");
00319         return CSCF_RETURN_ERROR;
00320     }   
00321     
00322     b = cscf_parse_contacts(rpl);
00323     
00324     if (!b||(!b->contacts && !b->star)) {
00325         LOG(L_DBG,"DBG:"M_NAME":r_save_location: No contacts found\n");
00326         return 0;
00327     }
00328     
00329     realm = cscf_get_realm(req);
00330     
00331     cscf_get_p_associated_uri(rpl,&public_id,&public_id_cnt);
00332     
00333     service_route = cscf_get_service_route(rpl,&service_route_cnt);
00334             
00335     if ((expires=update_contacts(req,rpl,b->star,expires_hdr,public_id,public_id_cnt,service_route,service_route_cnt,requires_nat(req)))<0) 
00336         goto error;
00337 
00338     //print_r(L_ERR);
00339     
00340     
00341     if (service_route)  pkg_free(service_route);
00342     if (public_id) pkg_free(public_id);
00343     return CSCF_RETURN_TRUE;
00344 error:
00345     if (service_route)  pkg_free(service_route);
00346     if (public_id) pkg_free(public_id);
00347     return CSCF_RETURN_ERROR;
00348 }

int r_is_integrity_protected ( str  host,
int  port,
int  r_port,
int  transport,
unsigned long  session_hash 
)

Finds if the message is integrity protected.

Parameters:
host - host of the UE
port - port of the UE
r_port - received port (added by PCSCF)
transport - transport of the UE
session_hash - TLS session hash
Returns:
1 if registered, 0 if not or error

Definition at line 360 of file registrar.c.

References _r_security::data, get_r_contact(), _r_contact::hash, _r_security::ipsec, _r_tls::port_tls, _r_ipsec::port_uc, _r_ipsec::port_us, r_unlock(), SEC_IPSEC, SEC_NONE, SEC_TLS, _r_contact::security, _r_contact::security_temp, _r_tls::session_hash, _r_security::tls, and _r_security::type.

Referenced by P_is_integrity_protected().

00361 {
00362     int ret=0;
00363     r_contact *c;
00364 
00365     if (port==0) port=5060;
00366 //  LOG(L_ERR,"DBG:"M_NAME":r_is_registered: Looking if registered <%d://%.*s:%d>\n",
00367 //      transport,host.len,host.s,port);
00368 
00369 //  print_r(L_INFO);
00370     c = get_r_contact(host,port,transport);
00371 
00372     if (!c) return 0;
00373     
00374     if (c->security){
00375         switch (c->security->type){
00376             case SEC_NONE:
00377                 break;
00378             case SEC_TLS:
00379                 if (c->security->data.tls&& 
00380                     (c->security->data.tls->port_tls==r_port) &&
00381                     (session_hash!= 0 && c->security->data.tls->session_hash == session_hash) // test same session
00382                     ){
00383                     ret = 1;
00384                 }
00385                 break;
00386             case SEC_IPSEC:
00387                 if (c->security->data.ipsec&&
00388                     (c->security->data.ipsec->port_uc==port || c->security->data.ipsec->port_us==port)){
00389                     ret = 1;
00390                 }
00391                 break;
00392         }           
00393     }
00394     if (!ret && c->security_temp){
00395         switch (c->security_temp->type){
00396             case SEC_NONE:
00397                 break;
00398             case SEC_TLS:
00399                 //nothing to do here becaues TLS security in temp does not mean that the user knows the password!
00400                 break;
00401             case SEC_IPSEC:
00402                 if (c->security_temp->data.ipsec&&
00403                     (c->security_temp->data.ipsec->port_uc==port || c->security_temp->data.ipsec->port_us==port)){
00404                     ret = 1;
00405                 }
00406                 break;
00407         }           
00408     }
00409     r_unlock(c->hash);
00410     return ret;
00411 }

int r_is_registered ( str  host,
int  port,
int  transport 
)

Finds if the user is registered.

Parameters:
host - host of the UE
port - port of the UE
transport - transport of the UE
Returns:
1 if registered, 0 if not or error

Definition at line 420 of file registrar.c.

References get_r_contact(), _r_contact::hash, r_act_time(), r_reg_contact(), and r_unlock().

Referenced by P_is_registered().

00421 {
00422     int ret=0;
00423     r_contact *c;
00424 
00425     if (port==0) port=5060;
00426 //  LOG(L_ERR,"DBG:"M_NAME":r_is_registered: Looking if registered <%d://%.*s:%d>\n",
00427 //      transport,host.len,host.s,port);
00428 
00429 //  print_r(L_INFO);
00430     c = get_r_contact(host,port,transport);
00431 
00432     if (!c){        
00433         return 0;
00434     }   
00435     r_act_time();
00436     if (r_reg_contact(c)){
00437         ret = 1;
00438     }
00439     r_unlock(c->hash);
00440     
00441     return ret;
00442 }

name_addr_t r_assert_identity ( str  host,
int  port,
int  transport,
name_addr_t  preferred 
)

Asserts the identity of the user and returns the value.

Parameters:
host - host of the UE
port - port of the UE
transport - transport of the UE
preferred - the P-Preferred-Identity header value
Returns:
1 if registered, {0,0} if not or error

Definition at line 453 of file registrar.c.

References _r_public::aor, get_r_contact(), _r_contact::hash, _r_contact::head, id, _r_public::is_default, M_NAME, _r_public::next, r_act_time(), r_reg_contact(), and r_unlock().

Referenced by P_assert_identity().

00454 {
00455     r_contact *c;
00456     r_public *p;
00457     name_addr_t id;
00458     if (port==0) port=5060;
00459 
00460     memset(&id,0,sizeof(name_addr_t));
00461     
00462     LOG(L_DBG,"DBG:"M_NAME":r_assert_identity: Asserting preferred id <%.*s>\n",
00463         preferred.uri.len,preferred.uri.s);
00464 //  print_r(L_INFO);
00465     c = get_r_contact(host,port,transport);
00466 
00467     if (!c){
00468         LOG(L_DBG,"DBG:"M_NAME":r_assert_identity: Contact not found\n");       
00469         return id;
00470     }
00471     r_act_time();
00472     if (!r_reg_contact(c)){
00473         LOG(L_DBG,"DBG:"M_NAME":r_assert_identity: Contact expired\n");
00474         r_unlock(c->hash);  
00475         return id;
00476     }
00477     
00478     if (!c->head){
00479         LOG(L_DBG,"DBG:"M_NAME":r_assert_identity: No public ids for this user\n");
00480         r_unlock(c->hash);
00481         return id;  
00482     }
00483     id.name = preferred.name;   
00484     if (!preferred.uri.len){
00485         p = c->head;
00486         while(p&&!p->is_default)
00487             p = p->next;
00488         if (p) {
00489             LOG(L_DBG,"DBG:"M_NAME":r_assert_identity: to <%.*s>\n",p->aor.len,p->aor.s);
00490             id.uri=p->aor;
00491             r_unlock(c->hash);
00492             return id;
00493         } else {
00494             LOG(L_DBG,"DBG:"M_NAME":r_assert_identity: to <%.*s>\n",c->head->aor.len,c->head->aor.s);
00495             id.uri=c->head->aor;
00496             r_unlock(c->hash);
00497             return id;  
00498         }
00499     }else{
00500         p = c->head;
00501         while(p){
00502             if (p->aor.len==preferred.uri.len &&
00503                 strncasecmp(p->aor.s,preferred.uri.s,preferred.uri.len)==0)
00504             {
00505                 LOG(L_DBG,"DBG:"M_NAME":r_assert_identity: to <%.*s>\n",p->aor.len,p->aor.s);
00506                 id.uri = preferred.uri;
00507                 r_unlock(c->hash);
00508                 return id;                  
00509             }
00510             p = p->next;
00511         }
00512     }
00513     r_unlock(c->hash);
00514     return id;
00515 }


Variable Documentation

struct tm_binds tmb

Structure with pointers to tm funcs.

Definition at line 257 of file mod.c.

time_t time_now

current time

Definition at line 71 of file registrar_storage.c.

Referenced by get_r_public_expires(), P_security_200(), print_r(), print_subs(), r_act_time(), r_calc_expires(), r_create_notifications(), r_get_reginfo_full(), r_get_reginfo_partial(), r_notification_process(), r_private_expire(), r_public_expire(), r_reg_contact(), r_update_subscription_status(), r_valid_contact(), r_valid_subscriber(), registrar_timer(), S_subscribe(), save_contact_security(), subscription_timer(), update_contacts(), and update_r_subscription().

r_hash_slot* registrar

the actual registrar

Definition at line 72 of file registrar_storage.c.

int r_hash_size

number of hash slots in the registrar

Definition at line 73 of file registrar_storage.c.

int pcscf_nat_enable

whether to enable NAT

Definition at line 142 of file mod.c.

int pcscf_nat_ping

whether to ping anything

Definition at line 143 of file mod.c.

int pcscf_nat_pingall

whether to ping also the UA that don't look like being behind a NAT

Definition at line 144 of file mod.c.

Referenced by nat_msg_origin(), nat_uac_test(), and requires_nat().

int pcscf_nat_detection_type

the NAT detection tests

Definition at line 145 of file mod.c.

Referenced by nat_uac_test().


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