diff --git a/src/modules/ims_registrar_scscf/api.h b/src/modules/ims_registrar_scscf/api.h index cd78ee2cb46..94bf4c2bd01 100644 --- a/src/modules/ims_registrar_scscf/api.h +++ b/src/modules/ims_registrar_scscf/api.h @@ -40,14 +40,15 @@ int regapi_lookup(struct sip_msg *msg, char *table); /** * @brief REGISTRAR API structure */ -typedef struct registrar_api { - regapi_save_f save; - regapi_lookup_f lookup; - regapi_lookup_f registered; +typedef struct registrar_api +{ + regapi_save_f save; + regapi_lookup_f lookup; + regapi_lookup_f registered; } registrar_api_t; -typedef int (*bind_registrar_f)(registrar_api_t* api); -int bind_registrar(registrar_api_t* api); +typedef int (*bind_registrar_f)(registrar_api_t *api); +int bind_registrar(registrar_api_t *api); /** * @brief Load the REGISTRAR API @@ -61,8 +62,7 @@ static inline int registrar_load_api(registrar_api_t *api) LM_ERR("cannot find bind_registrar\n"); return -1; } - if (bindregistrar(api) < 0) - { + if(bindregistrar(api) < 0) { LM_ERR("cannot bind registrar api\n"); return -1; } diff --git a/src/modules/ims_registrar_scscf/common.c b/src/modules/ims_registrar_scscf/common.c index 3b4ab685e3a..acf4dc70699 100644 --- a/src/modules/ims_registrar_scscf/common.c +++ b/src/modules/ims_registrar_scscf/common.c @@ -34,7 +34,7 @@ * \ingroup registrar */ -#include +#include #include "../../core/dprint.h" #include "../../core/parser/parse_uri.h" #include "rerrno.h" @@ -47,7 +47,8 @@ /*! \brief * Extract Address of Record */ -int extract_aor(str* _uri, str* _a) { +int extract_aor(str *_uri, str *_a) +{ static char aor_buf[MAX_AOR_LEN]; str tmp; struct sip_uri puri; @@ -58,9 +59,9 @@ int extract_aor(str* _uri, str* _a) { str realm_prefix; memset(aor_buf, 0, MAX_AOR_LEN); - if (aor_avp_name.n != 0) { + if(aor_avp_name.n != 0) { avp = search_first_avp(aor_avp_type, aor_avp_name, &avp_val, 0); - if (avp && is_avp_str_val(avp)) { + if(avp && is_avp_str_val(avp)) { uri = &avp_val.s; } else { uri = _uri; @@ -69,13 +70,13 @@ int extract_aor(str* _uri, str* _a) { uri = _uri; } - if (parse_uri(uri->s, uri->len, &puri) < 0) { + if(parse_uri(uri->s, uri->len, &puri) < 0) { rerrno = R_AOR_PARSE; LM_ERR("failed to parse Address of Record\n"); return -1; } - if ((puri.user.len + puri.host.len + 1 + 4) > MAX_AOR_LEN + if((puri.user.len + puri.host.len + 1 + 4) > MAX_AOR_LEN || puri.user.len > USERNAME_MAX_SIZE || puri.host.len > DOMAIN_MAX_SIZE) { rerrno = R_AOR_LEN; @@ -91,20 +92,20 @@ int extract_aor(str* _uri, str* _a) { tmps.s = _a->s + 4; tmps.len = puri.user.len; - if (un_escape(&puri.user, &tmps) < 0) { + if(un_escape(&puri.user, &tmps) < 0) { rerrno = R_UNESCAPE; LM_ERR("failed to unescape username\n"); return -3; } - user_len = tmps.len + 4;//_a->len; + user_len = tmps.len + 4; //_a->len; - if (user_len>4) + if(user_len > 4) aor_buf[_a->len++] = '@'; /* strip prefix (if defined) */ realm_prefix.s = cfg_get(registrar, registrar_cfg, realm_pref); realm_prefix.len = strlen(realm_prefix.s); - if (realm_prefix.len && realm_prefix.len < puri.host.len + if(realm_prefix.len && realm_prefix.len < puri.host.len && (memcmp(realm_prefix.s, puri.host.s, realm_prefix.len) == 0)) { memcpy(aor_buf + _a->len, puri.host.s + realm_prefix.len, puri.host.len - realm_prefix.len); @@ -114,7 +115,7 @@ int extract_aor(str* _uri, str* _a) { _a->len += puri.host.len; } - if (cfg_get(registrar, registrar_cfg, case_sensitive) && user_len) { + if(cfg_get(registrar, registrar_cfg, case_sensitive) && user_len) { tmp.s = _a->s + user_len + 1; tmp.len = _a->s + _a->len - tmp.s; strlower(&tmp); diff --git a/src/modules/ims_registrar_scscf/common.h b/src/modules/ims_registrar_scscf/common.h index 34913faf470..43feab87d7c 100644 --- a/src/modules/ims_registrar_scscf/common.h +++ b/src/modules/ims_registrar_scscf/common.h @@ -26,7 +26,7 @@ * \file * \brief SIP registrar module - common stuff * \ingroup registrar - */ + */ #ifndef COMMON_H @@ -38,7 +38,7 @@ /*! \brief * Extract Address Of Record */ -int extract_aor(str* _uri, str* _a); +int extract_aor(str *_uri, str *_a); #endif /* COMMON_H */ diff --git a/src/modules/ims_registrar_scscf/config.c b/src/modules/ims_registrar_scscf/config.c index 0c55f111006..45cbab33b18 100644 --- a/src/modules/ims_registrar_scscf/config.c +++ b/src/modules/ims_registrar_scscf/config.c @@ -30,49 +30,65 @@ #include "config.h" -struct cfg_group_registrar default_registrar_cfg = { - 3600, /* default_expires */ - 0, /* default_expires_range */ - 60, /* min_expires */ - 0, /* max_expires */ - 3600, /* emergency contact default expires */ - 60, /* emergency contact max expires */ - 0, /* emergency contact min expires */ - 0, /* max_contacts */ - 0, /* retry_after */ - 0, /* case_sensitive */ - Q_UNSPECIFIED, /* default_q */ - 1, /* append_branches */ - "" /* realm_pref */ - }; +struct cfg_group_registrar default_registrar_cfg = { + 3600, /* default_expires */ + 0, /* default_expires_range */ + 60, /* min_expires */ + 0, /* max_expires */ + 3600, /* emergency contact default expires */ + 60, /* emergency contact max expires */ + 0, /* emergency contact min expires */ + 0, /* max_contacts */ + 0, /* retry_after */ + 0, /* case_sensitive */ + Q_UNSPECIFIED, /* default_q */ + 1, /* append_branches */ + "" /* realm_pref */ +}; -void *registrar_cfg = &default_registrar_cfg; +void *registrar_cfg = &default_registrar_cfg; -cfg_def_t registrar_cfg_def[] = { - {"default_expires", CFG_VAR_INT | CFG_CB_ONLY_ONCE, 0, 0, 0, default_expires_stats_update, - "Contains number of second to expire if no expire hf or contact expire present" }, - {"default_expires_range", CFG_VAR_INT | CFG_CB_ONLY_ONCE, 0, 100, 0, default_expires_range_update, - "Percent from default_expires that will be used in generating the range for the expire interval"}, - {"min_expires", CFG_VAR_INT | CFG_CB_ONLY_ONCE, 0, 0, 0, 0, - "The minimum expires value of a Contact. Value 0 disables the checking. "}, - {"max_expires", CFG_VAR_INT | CFG_CB_ONLY_ONCE, 0, 0, 0, max_expires_stats_update, - "The maximum expires value of a Contact. Value 0 disables the checking. "}, - {"em_default_expires", CFG_VAR_INT | CFG_CB_ONLY_ONCE, 0, 0, 0, 0, - "The default emergency expires value of a Contact."}, - {"em_max_expires", CFG_VAR_INT | CFG_CB_ONLY_ONCE, 0, 0, 0, 0, - "The maximum emergency expires value of a Contact. Value 0 disables the checking. "}, - {"em_min_expires", CFG_VAR_INT | CFG_CB_ONLY_ONCE, 0, 0, 0, 0, - "The maximum emergency expires value of a Contact. Value 0 disables the checking. "}, - {"max_contacts", CFG_VAR_INT | CFG_ATOMIC, 0, 0, 0, 0, - "The maximum number of Contacts for an AOR. Value 0 disables the checking. "}, - {"retry_after", CFG_VAR_INT | CFG_ATOMIC, 0, 0, 0, 0, - "If you want to add the Retry-After header field in 5xx replies, set this parameter to a value grater than zero"}, - {"case_sensitive", CFG_VAR_INT | CFG_ATOMIC, 0, 0, 0, 0, - "If set to 1 then AOR comparison will be case sensitive. Recommended and default is 0, case insensitive"}, - {"default_q", CFG_VAR_INT | CFG_ATOMIC, -1, 1000, 0, 0, - "The parameter represents default q value for new contacts."}, /* Q_UNSPECIFIED is -1 */ - {"append_branches", CFG_VAR_INT , 0, 0, 0, 0, - "If set to 1(default), lookup will put all contacts found in msg structure"}, - {"realm_pref", CFG_VAR_STRING , 0, 0, 0, 0, "Realm prefix to be removed. Default is \"\""}, - {0, 0, 0, 0, 0, 0} -}; +cfg_def_t registrar_cfg_def[] = + {{"default_expires", CFG_VAR_INT | CFG_CB_ONLY_ONCE, 0, 0, 0, + default_expires_stats_update, + "Contains number of second to expire if no expire hf or " + "contact expire present"}, + {"default_expires_range", CFG_VAR_INT | CFG_CB_ONLY_ONCE, 0, + 100, 0, default_expires_range_update, + "Percent from default_expires that will be used in " + "generating the range for the expire interval"}, + {"min_expires", CFG_VAR_INT | CFG_CB_ONLY_ONCE, 0, 0, 0, 0, + "The minimum expires value of a Contact. Value 0 " + "disables the checking. "}, + {"max_expires", CFG_VAR_INT | CFG_CB_ONLY_ONCE, 0, 0, 0, + max_expires_stats_update, + "The maximum expires value of a Contact. Value 0 " + "disables the checking. "}, + {"em_default_expires", CFG_VAR_INT | CFG_CB_ONLY_ONCE, 0, 0, 0, + 0, "The default emergency expires value of a Contact."}, + {"em_max_expires", CFG_VAR_INT | CFG_CB_ONLY_ONCE, 0, 0, 0, 0, + "The maximum emergency expires value of a Contact. " + "Value 0 disables the checking. "}, + {"em_min_expires", CFG_VAR_INT | CFG_CB_ONLY_ONCE, 0, 0, 0, 0, + "The maximum emergency expires value of a Contact. " + "Value 0 disables the checking. "}, + {"max_contacts", CFG_VAR_INT | CFG_ATOMIC, 0, 0, 0, 0, + "The maximum number of Contacts for an AOR. Value 0 " + "disables the checking. "}, + {"retry_after", CFG_VAR_INT | CFG_ATOMIC, 0, 0, 0, 0, + "If you want to add the Retry-After header field in " + "5xx replies, set this parameter to a value grater " + "than zero"}, + {"case_sensitive", CFG_VAR_INT | CFG_ATOMIC, 0, 0, 0, 0, + "If set to 1 then AOR comparison will be case " + "sensitive. Recommended and default is 0, case " + "insensitive"}, + {"default_q", CFG_VAR_INT | CFG_ATOMIC, -1, 1000, 0, 0, + "The parameter represents default q value for new " + "contacts."}, /* Q_UNSPECIFIED is -1 */ + {"append_branches", CFG_VAR_INT, 0, 0, 0, 0, + "If set to 1(default), lookup will put all contacts " + "found in msg structure"}, + {"realm_pref", CFG_VAR_STRING, 0, 0, 0, 0, + "Realm prefix to be removed. Default is \"\""}, + {0, 0, 0, 0, 0, 0}}; diff --git a/src/modules/ims_registrar_scscf/config.h b/src/modules/ims_registrar_scscf/config.h index ef1bccf3eff..5310c63dfe0 100644 --- a/src/modules/ims_registrar_scscf/config.h +++ b/src/modules/ims_registrar_scscf/config.h @@ -26,28 +26,29 @@ #include "../../core/cfg/cfg.h" #include "../../core/str.h" -struct cfg_group_registrar { - unsigned int default_expires; - unsigned int default_expires_range; - unsigned int min_expires; - unsigned int max_expires; - unsigned int em_default_expires; - unsigned int em_max_expires; - unsigned int em_min_expires; - unsigned int max_contacts; - unsigned int retry_after; - unsigned int case_sensitive; - qvalue_t default_q; - unsigned int append_branches; - char* realm_pref; +struct cfg_group_registrar +{ + unsigned int default_expires; + unsigned int default_expires_range; + unsigned int min_expires; + unsigned int max_expires; + unsigned int em_default_expires; + unsigned int em_max_expires; + unsigned int em_min_expires; + unsigned int max_contacts; + unsigned int retry_after; + unsigned int case_sensitive; + qvalue_t default_q; + unsigned int append_branches; + char *realm_pref; }; -extern struct cfg_group_registrar default_registrar_cfg; -extern void *registrar_cfg; -extern cfg_def_t registrar_cfg_def[]; +extern struct cfg_group_registrar default_registrar_cfg; +extern void *registrar_cfg; +extern cfg_def_t registrar_cfg_def[]; -extern void default_expires_stats_update(str*, str*); -extern void default_expires_range_update(str*, str*); -extern void max_expires_stats_update(str*, str*); +extern void default_expires_stats_update(str *, str *); +extern void default_expires_range_update(str *, str *); +extern void max_expires_stats_update(str *, str *); #endif diff --git a/src/modules/ims_registrar_scscf/cxdx_avp.c b/src/modules/ims_registrar_scscf/cxdx_avp.c index 2310b9899d9..c66752cc317 100644 --- a/src/modules/ims_registrar_scscf/cxdx_avp.c +++ b/src/modules/ims_registrar_scscf/cxdx_avp.c @@ -49,7 +49,6 @@ #include "cxdx_avp.h" - static str s_empty = {0, 0}; /** @@ -64,18 +63,19 @@ static str s_empty = {0, 0}; * @param func - the name of the calling function, for debugging purposes * @returns 1 on success or 0 on failure */ -static int cxdx_add_avp(AAAMessage *m,char *d,int len,int avp_code, - int flags,int vendorid,int data_do,const char *func) +static int cxdx_add_avp(AAAMessage *m, char *d, int len, int avp_code, + int flags, int vendorid, int data_do, const char *func) { AAA_AVP *avp; - if (vendorid!=0) flags |= AAA_AVP_FLAG_VENDOR_SPECIFIC; - avp = cdpb.AAACreateAVP(avp_code,flags,vendorid,d,len,data_do); - if (!avp) { - LM_ERR("%s: Failed creating avp\n",func); + if(vendorid != 0) + flags |= AAA_AVP_FLAG_VENDOR_SPECIFIC; + avp = cdpb.AAACreateAVP(avp_code, flags, vendorid, d, len, data_do); + if(!avp) { + LM_ERR("%s: Failed creating avp\n", func); return 0; } - if (cdpb.AAAAddAVPToMessage(m,avp,m->avpList.tail)!=AAA_ERR_SUCCESS) { - LM_ERR("%s: Failed adding avp to message\n",func); + if(cdpb.AAAAddAVPToMessage(m, avp, m->avpList.tail) != AAA_ERR_SUCCESS) { + LM_ERR("%s: Failed adding avp to message\n", func); cdpb.AAAFreeAVP(&avp); return 0; } @@ -94,28 +94,29 @@ static int cxdx_add_avp(AAAMessage *m,char *d,int len,int avp_code, * @param func - the name of the calling function, for debugging purposes * @returns 1 on success or 0 on failure */ -static int cxdx_add_avp_list(AAA_AVP_LIST *list,char *d,int len,int avp_code, - int flags,int vendorid,int data_do,const char *func) +static int cxdx_add_avp_list(AAA_AVP_LIST *list, char *d, int len, int avp_code, + int flags, int vendorid, int data_do, const char *func) { AAA_AVP *avp; - if (vendorid!=0) flags |= AAA_AVP_FLAG_VENDOR_SPECIFIC; - avp = cdpb.AAACreateAVP(avp_code,flags,vendorid,d,len,data_do); - if (!avp) { - LM_ERR("%s: Failed creating avp\n",func); + if(vendorid != 0) + flags |= AAA_AVP_FLAG_VENDOR_SPECIFIC; + avp = cdpb.AAACreateAVP(avp_code, flags, vendorid, d, len, data_do); + if(!avp) { + LM_ERR("%s: Failed creating avp\n", func); return 0; } - if (list->tail) { - avp->prev=list->tail; - avp->next=0; + if(list->tail) { + avp->prev = list->tail; + avp->next = 0; list->tail->next = avp; - list->tail=avp; + list->tail = avp; } else { list->head = avp; list->tail = avp; - avp->next=0; - avp->prev=0; + avp->next = 0; + avp->prev = 0; } - + return 1; } @@ -127,30 +128,24 @@ static int cxdx_add_avp_list(AAA_AVP_LIST *list,char *d,int len,int avp_code, * @param func - the name of the calling function, for debugging purposes * @returns the str with the payload on success or an empty string on failure */ -static str cxdx_get_avp(AAAMessage *msg,int avp_code,int vendor_id, - const char *func) +static str cxdx_get_avp( + AAAMessage *msg, int avp_code, int vendor_id, const char *func) { AAA_AVP *avp; - str r={0,0}; - - avp = cdpb.AAAFindMatchingAVP(msg,0,avp_code,vendor_id,0); - if (avp==0){ - LM_INFO("%s: Failed finding avp\n",func); + str r = {0, 0}; + + avp = cdpb.AAAFindMatchingAVP(msg, 0, avp_code, vendor_id, 0); + if(avp == 0) { + LM_INFO("%s: Failed finding avp\n", func); return r; - } - else + } else return avp->data; } -int cxdx_add_call_id(AAAMessage *msg, str data) +int cxdx_add_call_id(AAAMessage *msg, str data) { - return - cxdx_add_avp(msg,data.s,data.len, - AVP_Call_Id, - AAA_AVP_FLAG_VENDOR_SPECIFIC, - 50, - AVP_DUPLICATE_DATA, - __FUNCTION__); + return cxdx_add_avp(msg, data.s, data.len, AVP_Call_Id, + AAA_AVP_FLAG_VENDOR_SPECIFIC, 50, AVP_DUPLICATE_DATA, __FUNCTION__); } /** @@ -159,15 +154,10 @@ int cxdx_add_call_id(AAAMessage *msg, str data) * @param data - the value for the AVP payload * @returns 1 on success or 0 on error */ -int cxdx_add_destination_realm(AAAMessage *msg,str data) +int cxdx_add_destination_realm(AAAMessage *msg, str data) { - return - cxdx_add_avp(msg,data.s,data.len, - AVP_Destination_Realm, - AAA_AVP_FLAG_MANDATORY, - 0, - AVP_DUPLICATE_DATA, - __FUNCTION__); + return cxdx_add_avp(msg, data.s, data.len, AVP_Destination_Realm, + AAA_AVP_FLAG_MANDATORY, 0, AVP_DUPLICATE_DATA, __FUNCTION__); } @@ -179,56 +169,38 @@ int cxdx_add_destination_realm(AAAMessage *msg,str data) * @param acct_id - the accounting application id * @returns 1 on success or 0 on error */ -int cxdx_add_vendor_specific_appid(AAAMessage *msg,unsigned int vendor_id, - unsigned int auth_id,unsigned int acct_id) +int cxdx_add_vendor_specific_appid(AAAMessage *msg, unsigned int vendor_id, + unsigned int auth_id, unsigned int acct_id) { AAA_AVP_LIST list; str group; char x[4]; - list.head=0;list.tail=0; - - set_4bytes(x,vendor_id); - cxdx_add_avp_list(&list, - x,4, - AVP_Vendor_Id, - AAA_AVP_FLAG_MANDATORY, - 0, - AVP_DUPLICATE_DATA, - __FUNCTION__); - - if (auth_id) { - set_4bytes(x,auth_id); - cxdx_add_avp_list(&list, - x,4, - AVP_Auth_Application_Id, - AAA_AVP_FLAG_MANDATORY, - 0, - AVP_DUPLICATE_DATA, - __FUNCTION__); + list.head = 0; + list.tail = 0; + + set_4bytes(x, vendor_id); + cxdx_add_avp_list(&list, x, 4, AVP_Vendor_Id, AAA_AVP_FLAG_MANDATORY, 0, + AVP_DUPLICATE_DATA, __FUNCTION__); + + if(auth_id) { + set_4bytes(x, auth_id); + cxdx_add_avp_list(&list, x, 4, AVP_Auth_Application_Id, + AAA_AVP_FLAG_MANDATORY, 0, AVP_DUPLICATE_DATA, __FUNCTION__); } - if (acct_id) { - set_4bytes(x,acct_id); - cxdx_add_avp_list(&list, - x,4, - AVP_Acct_Application_Id, - AAA_AVP_FLAG_MANDATORY, - 0, - AVP_DUPLICATE_DATA, - __FUNCTION__); - } - + if(acct_id) { + set_4bytes(x, acct_id); + cxdx_add_avp_list(&list, x, 4, AVP_Acct_Application_Id, + AAA_AVP_FLAG_MANDATORY, 0, AVP_DUPLICATE_DATA, __FUNCTION__); + } + group = cdpb.AAAGroupAVPS(list); - + cdpb.AAAFreeAVPList(&list); - - return - cxdx_add_avp(msg,group.s,group.len, - AVP_Vendor_Specific_Application_Id, - AAA_AVP_FLAG_MANDATORY, - 0, - AVP_FREE_DATA, - __FUNCTION__); + + return cxdx_add_avp(msg, group.s, group.len, + AVP_Vendor_Specific_Application_Id, AAA_AVP_FLAG_MANDATORY, 0, + AVP_FREE_DATA, __FUNCTION__); } /** @@ -237,17 +209,12 @@ int cxdx_add_vendor_specific_appid(AAAMessage *msg,unsigned int vendor_id, * @param data - the value for the AVP payload * @returns 1 on success or 0 on error */ -int cxdx_add_auth_session_state(AAAMessage *msg,unsigned int data) +int cxdx_add_auth_session_state(AAAMessage *msg, unsigned int data) { char x[4]; - set_4bytes(x,data); - return - cxdx_add_avp(msg,x,4, - AVP_Auth_Session_State, - AAA_AVP_FLAG_MANDATORY, - 0, - AVP_DUPLICATE_DATA, - __FUNCTION__); + set_4bytes(x, data); + return cxdx_add_avp(msg, x, 4, AVP_Auth_Session_State, + AAA_AVP_FLAG_MANDATORY, 0, AVP_DUPLICATE_DATA, __FUNCTION__); } /** @@ -256,15 +223,10 @@ int cxdx_add_auth_session_state(AAAMessage *msg,unsigned int data) * @param data - the value for the AVP payload * @returns 1 on success or 0 on error */ -int cxdx_add_user_name(AAAMessage *msg,str data) +int cxdx_add_user_name(AAAMessage *msg, str data) { - return - cxdx_add_avp(msg,data.s,data.len, - AVP_User_Name, - AAA_AVP_FLAG_MANDATORY, - 0, - AVP_DUPLICATE_DATA, - __FUNCTION__); + return cxdx_add_avp(msg, data.s, data.len, AVP_User_Name, + AAA_AVP_FLAG_MANDATORY, 0, AVP_DUPLICATE_DATA, __FUNCTION__); } /** @@ -273,15 +235,11 @@ int cxdx_add_user_name(AAAMessage *msg,str data) * @param data - the value for the AVP payload * @returns 1 on success or 0 on error */ -int cxdx_add_public_identity(AAAMessage *msg,str data) +int cxdx_add_public_identity(AAAMessage *msg, str data) { - return - cxdx_add_avp(msg,data.s,data.len, - AVP_IMS_Public_Identity, - AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC, - IMS_vendor_id_3GPP, - AVP_DUPLICATE_DATA, - __FUNCTION__); + return cxdx_add_avp(msg, data.s, data.len, AVP_IMS_Public_Identity, + AAA_AVP_FLAG_MANDATORY | AAA_AVP_FLAG_VENDOR_SPECIFIC, + IMS_vendor_id_3GPP, AVP_DUPLICATE_DATA, __FUNCTION__); } /** @@ -290,15 +248,12 @@ int cxdx_add_public_identity(AAAMessage *msg,str data) * @param data - the value for the AVP payload * @returns 1 on success or 0 on error */ -int cxdx_add_visited_network_id(AAAMessage *msg,str data) +int cxdx_add_visited_network_id(AAAMessage *msg, str data) { - return - cxdx_add_avp(msg,data.s,data.len, - AVP_IMS_Visited_Network_Identifier, - AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC, - IMS_vendor_id_3GPP, - AVP_DUPLICATE_DATA, - __FUNCTION__); + return cxdx_add_avp(msg, data.s, data.len, + AVP_IMS_Visited_Network_Identifier, + AAA_AVP_FLAG_MANDATORY | AAA_AVP_FLAG_VENDOR_SPECIFIC, + IMS_vendor_id_3GPP, AVP_DUPLICATE_DATA, __FUNCTION__); } /** @@ -314,16 +269,11 @@ int cxdx_add_UAR_flags(AAAMessage *msg, unsigned int sos_reg) /* optional AVP*/ if(!sos_reg) return 1; - - set_4bytes(x, AVP_IMS_UAR_Flags_Emergency_Registration); - return - cxdx_add_avp(msg,x,4, - AVP_IMS_UAR_Flags, - AAA_AVP_FLAG_VENDOR_SPECIFIC, - IMS_vendor_id_3GPP, - AVP_DUPLICATE_DATA, - __FUNCTION__); + set_4bytes(x, AVP_IMS_UAR_Flags_Emergency_Registration); + return cxdx_add_avp(msg, x, 4, AVP_IMS_UAR_Flags, + AAA_AVP_FLAG_VENDOR_SPECIFIC, IMS_vendor_id_3GPP, + AVP_DUPLICATE_DATA, __FUNCTION__); } /** * Creates and adds an Authorization-Type AVP. @@ -331,17 +281,13 @@ int cxdx_add_UAR_flags(AAAMessage *msg, unsigned int sos_reg) * @param data - the value for the AVP payload * @returns 1 on success or 0 on error */ -int cxdx_add_authorization_type(AAAMessage *msg,unsigned int data) +int cxdx_add_authorization_type(AAAMessage *msg, unsigned int data) { char x[4]; - set_4bytes(x,data); - return - cxdx_add_avp(msg,x,4, - AVP_IMS_User_Authorization_Type, - AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC, - IMS_vendor_id_3GPP, - AVP_DUPLICATE_DATA, - __FUNCTION__); + set_4bytes(x, data); + return cxdx_add_avp(msg, x, 4, AVP_IMS_User_Authorization_Type, + AAA_AVP_FLAG_MANDATORY | AAA_AVP_FLAG_VENDOR_SPECIFIC, + IMS_vendor_id_3GPP, AVP_DUPLICATE_DATA, __FUNCTION__); } /** @@ -352,11 +298,9 @@ int cxdx_add_authorization_type(AAAMessage *msg,unsigned int data) int cxdx_get_result_code(AAAMessage *msg, int *data) { str s; - s = cxdx_get_avp(msg, - AVP_Result_Code, - 0, - __FUNCTION__); - if (!s.s) return 0; + s = cxdx_get_avp(msg, AVP_Result_Code, 0, __FUNCTION__); + if(!s.s) + return 0; *data = get_4bytes(s.s); return 1; } @@ -371,16 +315,15 @@ int cxdx_get_experimental_result_code(AAAMessage *msg, int *data) AAA_AVP_LIST list; AAA_AVP *avp; str grp; - grp = cxdx_get_avp(msg, - AVP_IMS_Experimental_Result, - 0, - __FUNCTION__); - if (!grp.s) return 0; + grp = cxdx_get_avp(msg, AVP_IMS_Experimental_Result, 0, __FUNCTION__); + if(!grp.s) + return 0; list = cdpb.AAAUngroupAVPS(grp); - - avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_IMS_Experimental_Result_Code,0,0); - if (!avp||!avp->data.s) { + + avp = cdpb.AAAFindMatchingAVPList( + list, 0, AVP_IMS_Experimental_Result_Code, 0, 0); + if(!avp || !avp->data.s) { cdpb.AAAFreeAVPList(&list); return 0; } @@ -397,11 +340,9 @@ int cxdx_get_experimental_result_code(AAAMessage *msg, int *data) * @returns the AVP payload on success or an empty string on error */ str cxdx_get_server_name(AAAMessage *msg) -{ - return cxdx_get_avp(msg, - AVP_IMS_Server_Name, - IMS_vendor_id_3GPP, - __FUNCTION__); +{ + return cxdx_get_avp( + msg, AVP_IMS_Server_Name, IMS_vendor_id_3GPP, __FUNCTION__); } /** @@ -413,73 +354,75 @@ str cxdx_get_server_name(AAAMessage *msg) * @param o_cnt - size of the array above to be filled * @returns 1 on success 0 on fail */ -int cxdx_get_capabilities(AAAMessage *msg,int **m,int *m_cnt,int **o,int *o_cnt, - str **p,int *p_cnt) +int cxdx_get_capabilities(AAAMessage *msg, int **m, int *m_cnt, int **o, + int *o_cnt, str **p, int *p_cnt) { AAA_AVP_LIST list; AAA_AVP *avp; str grp; - grp = cxdx_get_avp(msg, - AVP_IMS_Server_Capabilities, - IMS_vendor_id_3GPP, - __FUNCTION__); - if (!grp.s) return 0; + grp = cxdx_get_avp( + msg, AVP_IMS_Server_Capabilities, IMS_vendor_id_3GPP, __FUNCTION__); + if(!grp.s) + return 0; list = cdpb.AAAUngroupAVPS(grp); - + avp = list.head; - *m_cnt=0; - *o_cnt=0; - *p_cnt=0; - while(avp){ - if (avp->code == AVP_IMS_Mandatory_Capability) (*m_cnt)++; - if (avp->code == AVP_IMS_Optional_Capability) (*o_cnt)++; - if (avp->code == AVP_IMS_Server_Name) (*p_cnt)++; + *m_cnt = 0; + *o_cnt = 0; + *p_cnt = 0; + while(avp) { + if(avp->code == AVP_IMS_Mandatory_Capability) + (*m_cnt)++; + if(avp->code == AVP_IMS_Optional_Capability) + (*o_cnt)++; + if(avp->code == AVP_IMS_Server_Name) + (*p_cnt)++; avp = avp->next; } avp = list.head; - *m=shm_malloc(sizeof(int)*(*m_cnt)); - if (!*m){ - LM_ERR("cannot allocated %lx bytes of shm.\n", - sizeof(int)*(*m_cnt)); + *m = shm_malloc(sizeof(int) * (*m_cnt)); + if(!*m) { + LM_ERR("cannot allocated %lx bytes of shm.\n", sizeof(int) * (*m_cnt)); goto error; } - *o=shm_malloc(sizeof(int)*(*o_cnt)); - if (!*o){ - LM_ERR("cannot allocated %lx bytes of shm.\n", - sizeof(int)*(*o_cnt)); + *o = shm_malloc(sizeof(int) * (*o_cnt)); + if(!*o) { + LM_ERR("cannot allocated %lx bytes of shm.\n", sizeof(int) * (*o_cnt)); goto error; } - *p=shm_malloc(sizeof(str)*(*p_cnt)); - if (!*p){ - LM_ERR("cannot allocated %lx bytes of shm.\n", - sizeof(str)*(*p_cnt)); + *p = shm_malloc(sizeof(str) * (*p_cnt)); + if(!*p) { + LM_ERR("cannot allocated %lx bytes of shm.\n", sizeof(str) * (*p_cnt)); goto error; } - - *m_cnt=0; - *o_cnt=0; - *p_cnt=0; - while(avp){ - if (avp->code == AVP_IMS_Mandatory_Capability) - (*m)[(*m_cnt)++]=get_4bytes(avp->data.s); - if (avp->code == AVP_IMS_Optional_Capability) - (*o)[(*o_cnt)++]=get_4bytes(avp->data.s); - if (avp->code == AVP_IMS_Server_Name) - (*p)[(*p_cnt)++]=avp->data; + + *m_cnt = 0; + *o_cnt = 0; + *p_cnt = 0; + while(avp) { + if(avp->code == AVP_IMS_Mandatory_Capability) + (*m)[(*m_cnt)++] = get_4bytes(avp->data.s); + if(avp->code == AVP_IMS_Optional_Capability) + (*o)[(*o_cnt)++] = get_4bytes(avp->data.s); + if(avp->code == AVP_IMS_Server_Name) + (*p)[(*p_cnt)++] = avp->data; avp = avp->next; } cdpb.AAAFreeAVPList(&list); return 1; - + error: cdpb.AAAFreeAVPList(&list); - if (*m) shm_free(*m); - if (*o) shm_free(*o); - if (*p) shm_free(*p); - *m_cnt=0; - *o_cnt=0; - *p_cnt=0; + if(*m) + shm_free(*m); + if(*o) + shm_free(*o); + if(*p) + shm_free(*p); + *m_cnt = 0; + *o_cnt = 0; + *p_cnt = 0; return 0; } @@ -492,13 +435,13 @@ int cxdx_get_capabilities(AAAMessage *msg,int **m,int *m_cnt,int **o,int *o_cnt, */ int cscf_reply_transactional(struct sip_msg *msg, int code, char *text) { - unsigned int hash,label; - if (tmb.t_get_trans_ident(msg,&hash,&label)<0){ - - if (tmb.t_newtran(msg)<0) + unsigned int hash, label; + if(tmb.t_get_trans_ident(msg, &hash, &label) < 0) { + + if(tmb.t_newtran(msg) < 0) LM_ERR("Failed creating SIP transaction\n"); } - return tmb.t_reply(msg,code,text); + return tmb.t_reply(msg, code, text); } /** @@ -507,17 +450,13 @@ int cscf_reply_transactional(struct sip_msg *msg, int code, char *text) * @param data - the value for the AVP payload * @returns 1 on success or 0 on error */ -int cxdx_add_sip_number_auth_items(AAAMessage *msg,unsigned int data) +int cxdx_add_sip_number_auth_items(AAAMessage *msg, unsigned int data) { char x[4]; - set_4bytes(x,data); - return - cxdx_add_avp(msg,x,4, - AVP_IMS_SIP_Number_Auth_Items, - AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC, - IMS_vendor_id_3GPP, - AVP_DUPLICATE_DATA, - __FUNCTION__); + set_4bytes(x, data); + return cxdx_add_avp(msg, x, 4, AVP_IMS_SIP_Number_Auth_Items, + AAA_AVP_FLAG_MANDATORY | AAA_AVP_FLAG_VENDOR_SPECIFIC, + IMS_vendor_id_3GPP, AVP_DUPLICATE_DATA, __FUNCTION__); } /** @@ -527,59 +466,48 @@ int cxdx_add_sip_number_auth_items(AAAMessage *msg,unsigned int data) * @param auth - the value for the authorization AVP * @returns 1 on success or 0 on error */ -int cxdx_add_sip_auth_data_item_request(AAAMessage *msg, str auth_scheme, str auth, str username, str realm,str method, str server_name) +int cxdx_add_sip_auth_data_item_request(AAAMessage *msg, str auth_scheme, + str auth, str username, str realm, str method, str server_name) { AAA_AVP_LIST list; str group; str etsi_authorization = {0, 0}; - list.head=0;list.tail=0; - - if (auth_scheme.len){ - cxdx_add_avp_list(&list, - auth_scheme.s,auth_scheme.len, - AVP_IMS_SIP_Authentication_Scheme, - AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC, - IMS_vendor_id_3GPP, - AVP_DONT_FREE_DATA, - __FUNCTION__); - } - if (auth.len){ - cxdx_add_avp_list(&list, - auth.s,auth.len, - AVP_IMS_SIP_Authorization, - AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC, - IMS_vendor_id_3GPP, - AVP_DONT_FREE_DATA, - __FUNCTION__); + list.head = 0; + list.tail = 0; + + if(auth_scheme.len) { + cxdx_add_avp_list(&list, auth_scheme.s, auth_scheme.len, + AVP_IMS_SIP_Authentication_Scheme, + AAA_AVP_FLAG_MANDATORY | AAA_AVP_FLAG_VENDOR_SPECIFIC, + IMS_vendor_id_3GPP, AVP_DONT_FREE_DATA, __FUNCTION__); + } + if(auth.len) { + cxdx_add_avp_list(&list, auth.s, auth.len, AVP_IMS_SIP_Authorization, + AAA_AVP_FLAG_MANDATORY | AAA_AVP_FLAG_VENDOR_SPECIFIC, + IMS_vendor_id_3GPP, AVP_DONT_FREE_DATA, __FUNCTION__); } - if (server_name.len) - { - etsi_authorization = cxdx_ETSI_sip_authorization(username, realm, s_empty, server_name, s_empty, s_empty, method, s_empty); - - if (etsi_authorization.len){ - cxdx_add_avp_list(&list, - etsi_authorization.s,etsi_authorization.len, - AVP_ETSI_SIP_Authorization, - AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC, - IMS_vendor_id_ETSI, - AVP_FREE_DATA, - __FUNCTION__); - } + if(server_name.len) { + etsi_authorization = cxdx_ETSI_sip_authorization(username, realm, + s_empty, server_name, s_empty, s_empty, method, s_empty); + + if(etsi_authorization.len) { + cxdx_add_avp_list(&list, etsi_authorization.s, + etsi_authorization.len, AVP_ETSI_SIP_Authorization, + AAA_AVP_FLAG_MANDATORY | AAA_AVP_FLAG_VENDOR_SPECIFIC, + IMS_vendor_id_ETSI, AVP_FREE_DATA, __FUNCTION__); + } } - if (!list.head) return 1; + if(!list.head) + return 1; group = cdpb.AAAGroupAVPS(list); - + cdpb.AAAFreeAVPList(&list); - - return - cxdx_add_avp(msg,group.s,group.len, - AVP_IMS_SIP_Auth_Data_Item, - AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC, - IMS_vendor_id_3GPP, - AVP_FREE_DATA, - __FUNCTION__); + + return cxdx_add_avp(msg, group.s, group.len, AVP_IMS_SIP_Auth_Data_Item, + AAA_AVP_FLAG_MANDATORY | AAA_AVP_FLAG_VENDOR_SPECIFIC, + IMS_vendor_id_3GPP, AVP_FREE_DATA, __FUNCTION__); } /** @@ -588,15 +516,11 @@ int cxdx_add_sip_auth_data_item_request(AAAMessage *msg, str auth_scheme, str au * @param data - the value for the AVP payload * @returns 1 on success or 0 on error */ -int cxdx_add_server_name(AAAMessage *msg,str data) +int cxdx_add_server_name(AAAMessage *msg, str data) { - return - cxdx_add_avp(msg,data.s,data.len, - AVP_IMS_Server_Name, - AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC, - IMS_vendor_id_3GPP, - AVP_DUPLICATE_DATA, - __FUNCTION__); + return cxdx_add_avp(msg, data.s, data.len, AVP_IMS_Server_Name, + AAA_AVP_FLAG_MANDATORY | AAA_AVP_FLAG_VENDOR_SPECIFIC, + IMS_vendor_id_3GPP, AVP_DUPLICATE_DATA, __FUNCTION__); } /** @@ -607,11 +531,10 @@ int cxdx_add_server_name(AAAMessage *msg,str data) int cxdx_get_sip_number_auth_items(AAAMessage *msg, int *data) { str s; - s = cxdx_get_avp(msg, - AVP_IMS_SIP_Number_Auth_Items, - IMS_vendor_id_3GPP, - __FUNCTION__); - if (!s.s) return 0; + s = cxdx_get_avp(msg, AVP_IMS_SIP_Number_Auth_Items, IMS_vendor_id_3GPP, + __FUNCTION__); + if(!s.s) + return 0; *data = get_4bytes(s.s); return 1; } @@ -629,174 +552,210 @@ int cxdx_get_sip_number_auth_items(AAAMessage *msg, int *data) * @returns the AVP payload on success or an empty string on error */ int cxdx_get_auth_data_item_answer(AAAMessage *msg, AAA_AVP **auth_data, - int *item_number,str *auth_scheme,str *authenticate,str *authorization, - str *ck,str *ik, - str *ip, - str *ha1, str *response_auth, str *digest_realm, - str *line_identifier) + int *item_number, str *auth_scheme, str *authenticate, + str *authorization, str *ck, str *ik, str *ip, str *ha1, + str *response_auth, str *digest_realm, str *line_identifier) { AAA_AVP_LIST list; AAA_AVP_LIST list2; AAA_AVP *avp; AAA_AVP *avp2; str grp; - ha1->s = 0; ha1->len = 0; - *auth_data = cdpb.AAAFindMatchingAVP(msg,*auth_data,AVP_IMS_SIP_Auth_Data_Item, - IMS_vendor_id_3GPP,0); - if (!*auth_data) return 0; - + ha1->s = 0; + ha1->len = 0; + *auth_data = cdpb.AAAFindMatchingAVP( + msg, *auth_data, AVP_IMS_SIP_Auth_Data_Item, IMS_vendor_id_3GPP, 0); + if(!*auth_data) + return 0; + grp = (*auth_data)->data; - if (!grp.len) return 0; + if(!grp.len) + return 0; list = cdpb.AAAUngroupAVPS(grp); - avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_IMS_SIP_Item_Number, - IMS_vendor_id_3GPP,0); - if (!avp||avp->data.len!=4) *item_number=0; - else *item_number = get_4bytes(avp->data.s); - - avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_IMS_SIP_Authentication_Scheme, - IMS_vendor_id_3GPP,0); - if (!avp||!avp->data.s) {auth_scheme->s=0;auth_scheme->len=0;} - else *auth_scheme = avp->data; + avp = cdpb.AAAFindMatchingAVPList( + list, 0, AVP_IMS_SIP_Item_Number, IMS_vendor_id_3GPP, 0); + if(!avp || avp->data.len != 4) + *item_number = 0; + else + *item_number = get_4bytes(avp->data.s); + + avp = cdpb.AAAFindMatchingAVPList( + list, 0, AVP_IMS_SIP_Authentication_Scheme, IMS_vendor_id_3GPP, 0); + if(!avp || !avp->data.s) { + auth_scheme->s = 0; + auth_scheme->len = 0; + } else + *auth_scheme = avp->data; /* Early-IMS */ - ip->s=0;ip->len=0; - avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_Framed_IP_Address,0,0); - if (avp && avp->data.s){ - if (avp->data.len!=4){ - LM_ERR("Invalid length of AVP Framed IP Address (should be 4 for AVP_Framed_IP_Address) >%d.\n", - avp->data.len); + ip->s = 0; + ip->len = 0; + avp = cdpb.AAAFindMatchingAVPList(list, 0, AVP_Framed_IP_Address, 0, 0); + if(avp && avp->data.s) { + if(avp->data.len != 4) { + LM_ERR("Invalid length of AVP Framed IP Address (should be 4 for " + "AVP_Framed_IP_Address) >%d.\n", + avp->data.len); } ip->len = 4; ip->s = avp->data.s; - } else { - avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_Framed_IPv6_Prefix,0,0); - if (avp && avp->data.s){ - if (avp->data.len==0){ - LM_ERR("Invalid length of AVP Framed IPv6 Prefix (should be >0 for AVP_Framed_IPv6_Prefix) >%d.\n", - avp->data.len); + } else { + avp = cdpb.AAAFindMatchingAVPList( + list, 0, AVP_Framed_IPv6_Prefix, 0, 0); + if(avp && avp->data.s) { + if(avp->data.len == 0) { + LM_ERR("Invalid length of AVP Framed IPv6 Prefix (should be >0 " + "for AVP_Framed_IPv6_Prefix) >%d.\n", + avp->data.len); } ip->len = avp->data.len; - ip->s = avp->data.s; - } + ip->s = avp->data.s; + } } /* Digest */ - avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_CableLabs_SIP_Digest_Authenticate,IMS_vendor_id_CableLabs,0); - if (avp && avp->data.s) - { + avp = cdpb.AAAFindMatchingAVPList(list, 0, + AVP_CableLabs_SIP_Digest_Authenticate, IMS_vendor_id_CableLabs, 0); + if(avp && avp->data.s) { list2 = cdpb.AAAUngroupAVPS(avp->data); - - avp2 = cdpb.AAAFindMatchingAVPList(list2,0,AVP_CableLabs_Digest_HA1,IMS_vendor_id_CableLabs,0); - if (!avp2||!avp2->data.s) { - ha1->s = 0; ha1->len = 0; + + avp2 = cdpb.AAAFindMatchingAVPList( + list2, 0, AVP_CableLabs_Digest_HA1, IMS_vendor_id_CableLabs, 0); + if(!avp2 || !avp2->data.s) { + ha1->s = 0; + ha1->len = 0; cdpb.AAAFreeAVPList(&list2); return 0; } *ha1 = avp2->data; cdpb.AAAFreeAVPList(&list2); } - - + + /* SIP Digest */ - avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_IMS_SIP_Digest_Authenticate,IMS_vendor_id_3GPP,0); - if (avp && avp->data.s) - { + avp = cdpb.AAAFindMatchingAVPList( + list, 0, AVP_IMS_SIP_Digest_Authenticate, IMS_vendor_id_3GPP, 0); + if(avp && avp->data.s) { list2 = cdpb.AAAUngroupAVPS(avp->data); - - avp2 = cdpb.AAAFindMatchingAVPList(list2,0,AVP_IMS_Digest_HA1,0,0); - if (!avp2||!avp2->data.s) { - ha1->s = 0; ha1->len = 0; + + avp2 = cdpb.AAAFindMatchingAVPList(list2, 0, AVP_IMS_Digest_HA1, 0, 0); + if(!avp2 || !avp2->data.s) { + ha1->s = 0; + ha1->len = 0; cdpb.AAAFreeAVPList(&list2); return 0; } *ha1 = avp2->data; cdpb.AAAFreeAVPList(&list2); } - - + + /* AKA, MD5 */ - avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_IMS_SIP_Authenticate, - IMS_vendor_id_3GPP,0); - if (!avp||!avp->data.s) {authenticate->s=0;authenticate->len=0;} - else *authenticate = avp->data; - - avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_IMS_SIP_Authorization, - IMS_vendor_id_3GPP,0); - if (!avp||!avp->data.s) {authorization->s=0;authorization->len=0;} - else *authorization = avp->data; - - avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_IMS_Confidentiality_Key, - IMS_vendor_id_3GPP,0); - if (!avp||!avp->data.s) {ck->s=0;ck->len=0;} - else *ck = avp->data; - - avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_IMS_Integrity_Key, - IMS_vendor_id_3GPP,0); - if (!avp||!avp->data.s) {ik->s=0;ik->len=0;} - else *ik = avp->data; + avp = cdpb.AAAFindMatchingAVPList( + list, 0, AVP_IMS_SIP_Authenticate, IMS_vendor_id_3GPP, 0); + if(!avp || !avp->data.s) { + authenticate->s = 0; + authenticate->len = 0; + } else + *authenticate = avp->data; + + avp = cdpb.AAAFindMatchingAVPList( + list, 0, AVP_IMS_SIP_Authorization, IMS_vendor_id_3GPP, 0); + if(!avp || !avp->data.s) { + authorization->s = 0; + authorization->len = 0; + } else + *authorization = avp->data; + + avp = cdpb.AAAFindMatchingAVPList( + list, 0, AVP_IMS_Confidentiality_Key, IMS_vendor_id_3GPP, 0); + if(!avp || !avp->data.s) { + ck->s = 0; + ck->len = 0; + } else + *ck = avp->data; + + avp = cdpb.AAAFindMatchingAVPList( + list, 0, AVP_IMS_Integrity_Key, IMS_vendor_id_3GPP, 0); + if(!avp || !avp->data.s) { + ik->s = 0; + ik->len = 0; + } else + *ik = avp->data; /* ETSI HTTP Digest */ - avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_ETSI_SIP_Authenticate,IMS_vendor_id_ETSI,0); - if (avp && avp->data.s) - { + avp = cdpb.AAAFindMatchingAVPList( + list, 0, AVP_ETSI_SIP_Authenticate, IMS_vendor_id_ETSI, 0); + if(avp && avp->data.s) { list2 = cdpb.AAAUngroupAVPS(avp->data); - - avp2 = cdpb.AAAFindMatchingAVPList(list2,0,AVP_ETSI_Digest_Realm, IMS_vendor_id_ETSI,0); - if (!avp2||!avp2->data.s) { - digest_realm->s=0;digest_realm->len=0; + + avp2 = cdpb.AAAFindMatchingAVPList( + list2, 0, AVP_ETSI_Digest_Realm, IMS_vendor_id_ETSI, 0); + if(!avp2 || !avp2->data.s) { + digest_realm->s = 0; + digest_realm->len = 0; cdpb.AAAFreeAVPList(&list2); return 0; } *digest_realm = avp2->data; - avp2 = cdpb.AAAFindMatchingAVPList(list2,0,AVP_ETSI_Digest_Nonce, IMS_vendor_id_ETSI,0); - if (!avp2||!avp2->data.s) { - authenticate->s=0;authenticate->len=0; + avp2 = cdpb.AAAFindMatchingAVPList( + list2, 0, AVP_ETSI_Digest_Nonce, IMS_vendor_id_ETSI, 0); + if(!avp2 || !avp2->data.s) { + authenticate->s = 0; + authenticate->len = 0; cdpb.AAAFreeAVPList(&list2); return 0; } *authenticate = avp2->data; - - avp2 = cdpb.AAAFindMatchingAVPList(list2,0,AVP_ETSI_Digest_HA1, IMS_vendor_id_ETSI,0); - if (!avp2||!avp2->data.s) { - ha1->s = 0; ha1->len = 0; + + avp2 = cdpb.AAAFindMatchingAVPList( + list2, 0, AVP_ETSI_Digest_HA1, IMS_vendor_id_ETSI, 0); + if(!avp2 || !avp2->data.s) { + ha1->s = 0; + ha1->len = 0; cdpb.AAAFreeAVPList(&list2); return 0; } *ha1 = avp2->data; - + cdpb.AAAFreeAVPList(&list2); } - avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_ETSI_SIP_Authentication_Info,IMS_vendor_id_ETSI,0); - if (avp && avp->data.s) - { + avp = cdpb.AAAFindMatchingAVPList( + list, 0, AVP_ETSI_SIP_Authentication_Info, IMS_vendor_id_ETSI, 0); + if(avp && avp->data.s) { list2 = cdpb.AAAUngroupAVPS(avp->data); - - avp2 = cdpb.AAAFindMatchingAVPList(list2,0,AVP_ETSI_Digest_Response_Auth, IMS_vendor_id_ETSI,0); - if (!avp2||!avp2->data.s) { - response_auth->s=0;response_auth->len=0; + + avp2 = cdpb.AAAFindMatchingAVPList( + list2, 0, AVP_ETSI_Digest_Response_Auth, IMS_vendor_id_ETSI, 0); + if(!avp2 || !avp2->data.s) { + response_auth->s = 0; + response_auth->len = 0; cdpb.AAAFreeAVPList(&list2); return 0; } *response_auth = avp2->data; cdpb.AAAFreeAVPList(&list2); + } else { + response_auth->s = 0; + response_auth->len = 0; } - else - { - response_auth->s=0;response_auth->len=0; - } - + /* NASS Bundled */ - avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_ETSI_Line_Identifier, IMS_vendor_id_ETSI,0); - if (!avp||!avp->data.s) {line_identifier->s=0;line_identifier->len=0;} - else *line_identifier = avp->data; - + avp = cdpb.AAAFindMatchingAVPList( + list, 0, AVP_ETSI_Line_Identifier, IMS_vendor_id_ETSI, 0); + if(!avp || !avp->data.s) { + line_identifier->s = 0; + line_identifier->len = 0; + } else + *line_identifier = avp->data; + cdpb.AAAFreeAVPList(&list); return 1; } @@ -813,97 +772,72 @@ int cxdx_get_auth_data_item_answer(AAAMessage *msg, AAA_AVP **auth_data, * @param hash - Enitity-Body-Hash * @returns grouped str on success */ -str cxdx_ETSI_sip_authorization(str username, str realm, str nonce, str URI, str response, str algorithm, str method, str hash) +str cxdx_ETSI_sip_authorization(str username, str realm, str nonce, str URI, + str response, str algorithm, str method, str hash) { AAA_AVP_LIST list; str group = {0, 0}; - list.head=0;list.tail=0; - - if (username.len){ - cxdx_add_avp_list(&list, - username.s,username.len, - AVP_ETSI_Digest_Username, - AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC, - IMS_vendor_id_ETSI, - AVP_DONT_FREE_DATA, - __FUNCTION__); - } - - if (realm.len){ - cxdx_add_avp_list(&list, - realm.s,realm.len, - AVP_ETSI_Digest_Realm, - AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC, - IMS_vendor_id_ETSI, - AVP_DONT_FREE_DATA, - __FUNCTION__); - } - - if (nonce.len){ - cxdx_add_avp_list(&list, - nonce.s,nonce.len, - AVP_ETSI_Digest_Nonce, - AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC, - IMS_vendor_id_ETSI, - AVP_DONT_FREE_DATA, - __FUNCTION__); + list.head = 0; + list.tail = 0; + + if(username.len) { + cxdx_add_avp_list(&list, username.s, username.len, + AVP_ETSI_Digest_Username, + AAA_AVP_FLAG_MANDATORY | AAA_AVP_FLAG_VENDOR_SPECIFIC, + IMS_vendor_id_ETSI, AVP_DONT_FREE_DATA, __FUNCTION__); } - if (URI.len){ - cxdx_add_avp_list(&list, - URI.s,URI.len, - AVP_ETSI_Digest_URI, - AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC, - IMS_vendor_id_ETSI, - AVP_DONT_FREE_DATA, - __FUNCTION__); + if(realm.len) { + cxdx_add_avp_list(&list, realm.s, realm.len, AVP_ETSI_Digest_Realm, + AAA_AVP_FLAG_MANDATORY | AAA_AVP_FLAG_VENDOR_SPECIFIC, + IMS_vendor_id_ETSI, AVP_DONT_FREE_DATA, __FUNCTION__); } - if (response.len){ - cxdx_add_avp_list(&list, - response.s,response.len, - AVP_ETSI_Digest_Response, - AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC, - IMS_vendor_id_ETSI, - AVP_DONT_FREE_DATA, - __FUNCTION__); + if(nonce.len) { + cxdx_add_avp_list(&list, nonce.s, nonce.len, AVP_ETSI_Digest_Nonce, + AAA_AVP_FLAG_MANDATORY | AAA_AVP_FLAG_VENDOR_SPECIFIC, + IMS_vendor_id_ETSI, AVP_DONT_FREE_DATA, __FUNCTION__); } - if (algorithm.len){ - cxdx_add_avp_list(&list, - algorithm.s,algorithm.len, - AVP_ETSI_Digest_Algorithm, - AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC, - IMS_vendor_id_ETSI, - AVP_DONT_FREE_DATA, - __FUNCTION__); + if(URI.len) { + cxdx_add_avp_list(&list, URI.s, URI.len, AVP_ETSI_Digest_URI, + AAA_AVP_FLAG_MANDATORY | AAA_AVP_FLAG_VENDOR_SPECIFIC, + IMS_vendor_id_ETSI, AVP_DONT_FREE_DATA, __FUNCTION__); } - if (method.len){ - cxdx_add_avp_list(&list, - method.s,method.len, - AVP_ETSI_Digest_Method, - AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC, - IMS_vendor_id_ETSI, - AVP_DONT_FREE_DATA, - __FUNCTION__); + if(response.len) { + cxdx_add_avp_list(&list, response.s, response.len, + AVP_ETSI_Digest_Response, + AAA_AVP_FLAG_MANDATORY | AAA_AVP_FLAG_VENDOR_SPECIFIC, + IMS_vendor_id_ETSI, AVP_DONT_FREE_DATA, __FUNCTION__); } - if (hash.len){ - cxdx_add_avp_list(&list, - hash.s,hash.len, - AVP_ETSI_Digest_Entity_Body_Hash, - AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC, - IMS_vendor_id_ETSI, - AVP_DONT_FREE_DATA, - __FUNCTION__); + if(algorithm.len) { + cxdx_add_avp_list(&list, algorithm.s, algorithm.len, + AVP_ETSI_Digest_Algorithm, + AAA_AVP_FLAG_MANDATORY | AAA_AVP_FLAG_VENDOR_SPECIFIC, + IMS_vendor_id_ETSI, AVP_DONT_FREE_DATA, __FUNCTION__); + } + + if(method.len) { + cxdx_add_avp_list(&list, method.s, method.len, AVP_ETSI_Digest_Method, + AAA_AVP_FLAG_MANDATORY | AAA_AVP_FLAG_VENDOR_SPECIFIC, + IMS_vendor_id_ETSI, AVP_DONT_FREE_DATA, __FUNCTION__); } - if (!list.head) return group; + if(hash.len) { + cxdx_add_avp_list(&list, hash.s, hash.len, + AVP_ETSI_Digest_Entity_Body_Hash, + AAA_AVP_FLAG_MANDATORY | AAA_AVP_FLAG_VENDOR_SPECIFIC, + IMS_vendor_id_ETSI, AVP_DONT_FREE_DATA, __FUNCTION__); + } + + if(!list.head) + return group; group = cdpb.AAAGroupAVPS(list); - + cdpb.AAAFreeAVPList(&list); - + return group; } @@ -914,11 +848,9 @@ str cxdx_ETSI_sip_authorization(str username, str realm, str nonce, str URI, str */ str cxdx_get_user_data(AAAMessage *msg) -{ - return cxdx_get_avp(msg, - AVP_IMS_User_Data_Cx, - IMS_vendor_id_3GPP, - __FUNCTION__); +{ + return cxdx_get_avp( + msg, AVP_IMS_User_Data_Cx, IMS_vendor_id_3GPP, __FUNCTION__); } /** @@ -926,43 +858,50 @@ str cxdx_get_user_data(AAAMessage *msg) * @param msg - the Diameter message * @returns the AVP payload on success or an empty string on error */ -int cxdx_get_charging_info(AAAMessage *msg,str *ccf1,str *ccf2,str *ecf1,str *ecf2) -{ +int cxdx_get_charging_info( + AAAMessage *msg, str *ccf1, str *ccf2, str *ecf1, str *ecf2) +{ AAA_AVP_LIST list; AAA_AVP *avp; str grp; - grp = cxdx_get_avp(msg, - AVP_IMS_Charging_Information, - IMS_vendor_id_3GPP, - __FUNCTION__); - if (!grp.s) return 0; + grp = cxdx_get_avp(msg, AVP_IMS_Charging_Information, IMS_vendor_id_3GPP, + __FUNCTION__); + if(!grp.s) + return 0; list = cdpb.AAAUngroupAVPS(grp); - - if (ccf1){ - avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_IMS_Primary_Charging_Collection_Function_Name, - IMS_vendor_id_3GPP,0); - if (avp) *ccf1 = avp->data; - } - if (ccf2){ - avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_IMS_Secondary_Charging_Collection_Function_Name, - IMS_vendor_id_3GPP,0); - if (avp) *ccf2 = avp->data; - } - if (ecf1){ - avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_IMS_Primary_Event_Charging_Function_Name, - IMS_vendor_id_3GPP,0); - if (avp) *ecf1 = avp->data; - } - if (ecf2){ - avp = cdpb.AAAFindMatchingAVPList(list,0,AVP_IMS_Secondary_Event_Charging_Function_Name, - IMS_vendor_id_3GPP,0); - if (avp) *ecf2 = avp->data; - } - + + if(ccf1) { + avp = cdpb.AAAFindMatchingAVPList(list, 0, + AVP_IMS_Primary_Charging_Collection_Function_Name, + IMS_vendor_id_3GPP, 0); + if(avp) + *ccf1 = avp->data; + } + if(ccf2) { + avp = cdpb.AAAFindMatchingAVPList(list, 0, + AVP_IMS_Secondary_Charging_Collection_Function_Name, + IMS_vendor_id_3GPP, 0); + if(avp) + *ccf2 = avp->data; + } + if(ecf1) { + avp = cdpb.AAAFindMatchingAVPList(list, 0, + AVP_IMS_Primary_Event_Charging_Function_Name, + IMS_vendor_id_3GPP, 0); + if(avp) + *ecf1 = avp->data; + } + if(ecf2) { + avp = cdpb.AAAFindMatchingAVPList(list, 0, + AVP_IMS_Secondary_Event_Charging_Function_Name, + IMS_vendor_id_3GPP, 0); + if(avp) + *ecf2 = avp->data; + } + cdpb.AAAFreeAVPList(&list); - return 1; - + return 1; } /** @@ -971,17 +910,13 @@ int cxdx_get_charging_info(AAAMessage *msg,str *ccf1,str *ccf2,str *ecf1,str *ec * @param data - the value for the AVP payload * @returns 1 on success or 0 on error */ -int cxdx_add_server_assignment_type(AAAMessage *msg,unsigned int data) +int cxdx_add_server_assignment_type(AAAMessage *msg, unsigned int data) { char x[4]; - set_4bytes(x,data); - return - cxdx_add_avp(msg,x,4, - AVP_IMS_Server_Assignment_Type, - AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC, - IMS_vendor_id_3GPP, - AVP_DUPLICATE_DATA, - __FUNCTION__); + set_4bytes(x, data); + return cxdx_add_avp(msg, x, 4, AVP_IMS_Server_Assignment_Type, + AAA_AVP_FLAG_MANDATORY | AAA_AVP_FLAG_VENDOR_SPECIFIC, + IMS_vendor_id_3GPP, AVP_DUPLICATE_DATA, __FUNCTION__); } /** @@ -990,17 +925,13 @@ int cxdx_add_server_assignment_type(AAAMessage *msg,unsigned int data) * @param data - the value for the AVP payload * @returns 1 on success or 0 on error */ -int cxdx_add_userdata_available(AAAMessage *msg,unsigned int data) +int cxdx_add_userdata_available(AAAMessage *msg, unsigned int data) { char x[4]; - set_4bytes(x,data); - return - cxdx_add_avp(msg,x,4, - AVP_IMS_User_Data_Already_Available, - AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC, - IMS_vendor_id_3GPP, - AVP_DUPLICATE_DATA, - __FUNCTION__); + set_4bytes(x, data); + return cxdx_add_avp(msg, x, 4, AVP_IMS_User_Data_Already_Available, + AAA_AVP_FLAG_MANDATORY | AAA_AVP_FLAG_VENDOR_SPECIFIC, + IMS_vendor_id_3GPP, AVP_DUPLICATE_DATA, __FUNCTION__); } /** @@ -1012,16 +943,16 @@ int cxdx_add_userdata_available(AAAMessage *msg,unsigned int data) * @param func - the name of the calling function for debugging purposes * @returns the AVP payload on success or an empty string on error */ -AAA_AVP* cxdx_get_next_public_identity(AAAMessage *msg,AAA_AVP* pos,int avp_code,int vendor_id,const char *func) -{ +AAA_AVP *cxdx_get_next_public_identity(AAAMessage *msg, AAA_AVP *pos, + int avp_code, int vendor_id, const char *func) +{ AAA_AVP *avp; - - avp = cdpb.AAAFindMatchingAVP(msg,pos,avp_code,vendor_id,0); - if (avp==0){ - LM_DBG("INFO:%s: Failed finding avp\n",func); + + avp = cdpb.AAAFindMatchingAVP(msg, pos, avp_code, vendor_id, 0); + if(avp == 0) { + LM_DBG("INFO:%s: Failed finding avp\n", func); return avp; - } - else + } else return avp; } @@ -1032,10 +963,7 @@ AAA_AVP* cxdx_get_next_public_identity(AAAMessage *msg,AAA_AVP* pos,int avp_code */ str cxdx_get_user_name(AAAMessage *msg) { - return cxdx_get_avp(msg, - AVP_User_Name, - 0, - __FUNCTION__); + return cxdx_get_avp(msg, AVP_User_Name, 0, __FUNCTION__); } /** @@ -1044,15 +972,10 @@ str cxdx_get_user_name(AAAMessage *msg) * @param data - the value for the AVP payload * @returns 1 on success or 0 on error */ -int cxdx_add_result_code(AAAMessage *msg,unsigned int data) +int cxdx_add_result_code(AAAMessage *msg, unsigned int data) { char x[4]; - set_4bytes(x,data); - return - cxdx_add_avp(msg,x,4, - AVP_Result_Code, - AAA_AVP_FLAG_MANDATORY, - 0, - AVP_DUPLICATE_DATA, - __FUNCTION__); + set_4bytes(x, data); + return cxdx_add_avp(msg, x, 4, AVP_Result_Code, AAA_AVP_FLAG_MANDATORY, 0, + AVP_DUPLICATE_DATA, __FUNCTION__); } diff --git a/src/modules/ims_registrar_scscf/cxdx_avp.h b/src/modules/ims_registrar_scscf/cxdx_avp.h index b0830bce941..e5fed2678e2 100644 --- a/src/modules/ims_registrar_scscf/cxdx_avp.h +++ b/src/modules/ims_registrar_scscf/cxdx_avp.h @@ -46,7 +46,7 @@ #ifndef IS_CSCF_CXDX_AVP_H #define IS_CSCF_CXDX_AVP_H -extern struct cdp_binds cdpb; /**< Structure with pointers to cdp funcs */ +extern struct cdp_binds cdpb; /**< Structure with pointers to cdp funcs */ extern struct tm_binds tmb; struct AAAMessage; @@ -70,7 +70,8 @@ int cxdx_add_destination_realm(AAAMessage *msg, str data); * @param acct_id - the accounting application id * @returns 1 on success or 0 on error */ -int cxdx_add_vendor_specific_appid(AAAMessage *msg,unsigned int vendor_id,unsigned int auth_id,unsigned int acct_id); +int cxdx_add_vendor_specific_appid(AAAMessage *msg, unsigned int vendor_id, + unsigned int auth_id, unsigned int acct_id); /** * Creates and adds an Auth-Session-State AVP. @@ -78,7 +79,7 @@ int cxdx_add_vendor_specific_appid(AAAMessage *msg,unsigned int vendor_id,unsign * @param data - the value for the AVP payload * @returns 1 on success or 0 on error */ -int cxdx_add_auth_session_state(AAAMessage *msg,unsigned int data); +int cxdx_add_auth_session_state(AAAMessage *msg, unsigned int data); /** * Creates and adds a User-Name AVP. @@ -86,7 +87,7 @@ int cxdx_add_auth_session_state(AAAMessage *msg,unsigned int data); * @param data - the value for the AVP payload * @returns 1 on success or 0 on error */ -int cxdx_add_user_name(AAAMessage *msg,str data); +int cxdx_add_user_name(AAAMessage *msg, str data); /** * Creates and adds a Public Identity AVP. @@ -94,7 +95,7 @@ int cxdx_add_user_name(AAAMessage *msg,str data); * @param data - the value for the AVP payload * @returns 1 on success or 0 on error */ -int cxdx_add_public_identity(AAAMessage *msg,str data); +int cxdx_add_public_identity(AAAMessage *msg, str data); /** * Creates and adds a Visited-Network-ID AVP. @@ -102,7 +103,7 @@ int cxdx_add_public_identity(AAAMessage *msg,str data); * @param data - the value for the AVP payload * @returns 1 on success or 0 on error */ -int cxdx_add_visited_network_id(AAAMessage *msg,str data); +int cxdx_add_visited_network_id(AAAMessage *msg, str data); /** * Creates and adds a UAR-Flags AVP. @@ -118,7 +119,7 @@ int cxdx_add_UAR_flags(AAAMessage *msg, unsigned int sos_reg); * @param data - the value for the AVP payload * @returns 1 on success or 0 on error */ -int cxdx_add_authorization_type(AAAMessage *msg,unsigned int data); +int cxdx_add_authorization_type(AAAMessage *msg, unsigned int data); /** * Returns the Result-Code AVP from a Diameter message. @@ -150,7 +151,8 @@ str cxdx_get_server_name(AAAMessage *msg); * @param o_cnt - size of the array above to be filled * @returns 1 on success 0 on fail */ -int cxdx_get_capabilities(AAAMessage *msg,int **m,int *m_cnt,int **o,int *o_cnt, str **p,int *p_cnt); +int cxdx_get_capabilities(AAAMessage *msg, int **m, int *m_cnt, int **o, + int *o_cnt, str **p, int *p_cnt); /** * Creates and adds a SIP-Number-Auth-Items AVP. @@ -158,7 +160,7 @@ int cxdx_get_capabilities(AAAMessage *msg,int **m,int *m_cnt,int **o,int *o_cnt, * @param data - the value for the AVP payload * @returns 1 on success or 0 on error */ -int cxdx_add_sip_number_auth_items(AAAMessage *msg,unsigned int data); +int cxdx_add_sip_number_auth_items(AAAMessage *msg, unsigned int data); /** * Creates and adds a SIP-Auth-Data-Item AVP. @@ -167,7 +169,8 @@ int cxdx_add_sip_number_auth_items(AAAMessage *msg,unsigned int data); * @param auth - the value for the authorization AVP * @returns 1 on success or 0 on error */ -int cxdx_add_sip_auth_data_item_request(AAAMessage *msg, str auth_scheme, str auth, str username, str realm,str method, str server_name); +int cxdx_add_sip_auth_data_item_request(AAAMessage *msg, str auth_scheme, + str auth, str username, str realm, str method, str server_name); /** * Creates and adds a Server-Name AVP. @@ -175,7 +178,7 @@ int cxdx_add_sip_auth_data_item_request(AAAMessage *msg, str auth_scheme, str au * @param data - the value for the AVP payload * @returns 1 on success or 0 on error */ -int cxdx_add_server_name(AAAMessage *msg,str data); +int cxdx_add_server_name(AAAMessage *msg, str data); /** * Returns the SIP-Number-Auth-Items AVP from a Diameter message. @@ -197,11 +200,9 @@ int cxdx_get_sip_number_auth_items(AAAMessage *msg, int *data); * @returns the AVP payload on success or an empty string on error */ int cxdx_get_auth_data_item_answer(AAAMessage *msg, AAA_AVP **auth_data, - int *item_number,str *auth_scheme,str *authenticate,str *authorization, - str *ck,str *ik, - str *ip, - str *ha1, str *response_auth, str *digest_realm, - str *line_identifier); + int *item_number, str *auth_scheme, str *authenticate, + str *authorization, str *ck, str *ik, str *ip, str *ha1, + str *response_auth, str *digest_realm, str *line_identifier); /** * Creates and adds an ETSI_sip_authorization AVP. @@ -215,7 +216,8 @@ int cxdx_get_auth_data_item_answer(AAAMessage *msg, AAA_AVP **auth_data, * @param hash - Enitity-Body-Hash * @returns grouped str on success */ -str cxdx_ETSI_sip_authorization(str username, str realm, str nonce, str URI, str response, str algorithm, str method, str hash); +str cxdx_ETSI_sip_authorization(str username, str realm, str nonce, str URI, + str response, str algorithm, str method, str hash); /** * Returns the User-Data from a Diameter message. @@ -230,7 +232,8 @@ str cxdx_get_user_data(AAAMessage *msg); * @param msg - the Diameter message * @returns the AVP payload on success or an empty string on error */ -int cxdx_get_charging_info(AAAMessage *msg,str *ccf1,str *ccf2,str *ecf1,str *ecf2); +int cxdx_get_charging_info( + AAAMessage *msg, str *ccf1, str *ccf2, str *ecf1, str *ecf2); /** * Creates and adds a Server-Assignment-Type AVP. @@ -238,7 +241,7 @@ int cxdx_get_charging_info(AAAMessage *msg,str *ccf1,str *ccf2,str *ecf1,str *ec * @param data - the value for the AVP payload * @returns 1 on success or 0 on error */ -int cxdx_add_server_assignment_type(AAAMessage *msg,unsigned int data); +int cxdx_add_server_assignment_type(AAAMessage *msg, unsigned int data); /** * Creates and adds Userdata-Available AVP. @@ -246,7 +249,7 @@ int cxdx_add_server_assignment_type(AAAMessage *msg,unsigned int data); * @param data - the value for the AVP payload * @returns 1 on success or 0 on error */ -int cxdx_add_userdata_available(AAAMessage *msg,unsigned int data); +int cxdx_add_userdata_available(AAAMessage *msg, unsigned int data); /** * Finds out the next Public-Identity AVP from a Diameter message. @@ -257,7 +260,8 @@ int cxdx_add_userdata_available(AAAMessage *msg,unsigned int data); * @param func - the name of the calling function for debugging purposes * @returns the AVP payload on success or an empty string on error */ -AAA_AVP* cxdx_get_next_public_identity(AAAMessage *msg,AAA_AVP* pos,int avp_code,int vendor_id,const char *func); +AAA_AVP *cxdx_get_next_public_identity(AAAMessage *msg, AAA_AVP *pos, + int avp_code, int vendor_id, const char *func); /** * Returns the User-Name AVP from a Diameter message. @@ -272,7 +276,7 @@ str cxdx_get_user_name(AAAMessage *msg); * @param data - the value for the AVP payload * @returns 1 on success or 0 on error */ -int cxdx_add_result_code(AAAMessage *msg,unsigned int data); +int cxdx_add_result_code(AAAMessage *msg, unsigned int data); /** * Transactional SIP response - tries to create a transaction if none found. diff --git a/src/modules/ims_registrar_scscf/cxdx_callbacks.c b/src/modules/ims_registrar_scscf/cxdx_callbacks.c index 00fc280b4d5..59e6db15f6b 100644 --- a/src/modules/ims_registrar_scscf/cxdx_callbacks.c +++ b/src/modules/ims_registrar_scscf/cxdx_callbacks.c @@ -45,99 +45,116 @@ extern char *domain; return 0; }*/ -AAAMessage* cxdx_process_rtr(AAAMessage *rtr) { - LM_DBG("Processing RTR"); - - AAAMessage *rta_msg; - AAA_AVP* avp; - str public_id; - impurecord_t* r; - int res = 0; - udomain_t* udomain; +AAAMessage *cxdx_process_rtr(AAAMessage *rtr) +{ + LM_DBG("Processing RTR"); + + AAAMessage *rta_msg; + AAA_AVP *avp; + str public_id; + impurecord_t *r; + int res = 0; + udomain_t *udomain; impu_contact_t *impucontact; - - rta_msg = cdpb.AAACreateResponse(rtr);//session ID? - if (!rta_msg) return 0; - - avp = cxdx_get_next_public_identity(rtr,0,AVP_IMS_Public_Identity,IMS_vendor_id_3GPP,__FUNCTION__); - if(avp==0){ - LM_WARN("RTR received with only IMPI (username AVP) - currently S-CSCF does not support this kind of RTR\n"); - return 0; - //TODO add support for receiving RTR with IMPI - //get all impus related to this impu - //get all contacts related to each impu - //set the contact expire for each contact to now - }else{ - public_id=avp->data; - LM_DBG("RTR received with IMPU [%.*s] in public identity AVP - this is supported\n", public_id.len, public_id.s); - - //TODO this should be a configurable module param - if (ul.register_udomain(domain, &udomain) < 0) { - LM_ERR("Unable to register usrloc domain....aborting\n"); + + rta_msg = cdpb.AAACreateResponse(rtr); //session ID? + if(!rta_msg) + return 0; + + avp = cxdx_get_next_public_identity( + rtr, 0, AVP_IMS_Public_Identity, IMS_vendor_id_3GPP, __FUNCTION__); + if(avp == 0) { + LM_WARN("RTR received with only IMPI (username AVP) - currently S-CSCF " + "does not support this kind of RTR\n"); return 0; - } - - ul.lock_udomain(udomain, &public_id); - res = ul.get_impurecord(udomain, &public_id, &r); - if (res != 0) { - LM_WARN("Strange, '%.*s' Not found in usrloc\n", public_id.len, public_id.s); - ul.unlock_udomain(udomain, &public_id); - //no point in continuing - return 0; - } - + //TODO add support for receiving RTR with IMPI + //get all impus related to this impu + //get all contacts related to each impu + //set the contact expire for each contact to now + } else { + public_id = avp->data; + LM_DBG("RTR received with IMPU [%.*s] in public identity AVP - this is " + "supported\n", + public_id.len, public_id.s); + + //TODO this should be a configurable module param + if(ul.register_udomain(domain, &udomain) < 0) { + LM_ERR("Unable to register usrloc domain....aborting\n"); + return 0; + } + + ul.lock_udomain(udomain, &public_id); + res = ul.get_impurecord(udomain, &public_id, &r); + if(res != 0) { + LM_WARN("Strange, '%.*s' Not found in usrloc\n", public_id.len, + public_id.s); + ul.unlock_udomain(udomain, &public_id); + //no point in continuing + return 0; + } + impucontact = r->linked_contacts.head; - while (impucontact) { - LM_DBG("Deleting contact with AOR [%.*s]\n", impucontact->contact->aor.len, impucontact->contact->aor.s); + while(impucontact) { + LM_DBG("Deleting contact with AOR [%.*s]\n", + impucontact->contact->aor.len, impucontact->contact->aor.s); ul.lock_contact_slot_i(impucontact->contact->sl); - if (r->shead) { + if(r->shead) { //send NOTIFY to all subscribers of this IMPU. - notify_subscribers(r, impucontact->contact, 0, 0, IMS_REGISTRAR_CONTACT_DEREGISTERED); + notify_subscribers(r, impucontact->contact, 0, 0, + IMS_REGISTRAR_CONTACT_DEREGISTERED); } impucontact->contact->state = CONTACT_DELETED; ul.unlock_contact_slot_i(impucontact->contact->sl); - + impucontact = impucontact->next; } - - ul.unlock_udomain(udomain, &public_id); - - while(cdpb.AAAGetNextAVP(avp) && (avp=cxdx_get_next_public_identity(rtr,cdpb.AAAGetNextAVP(avp),AVP_IMS_Public_Identity,IMS_vendor_id_3GPP,__FUNCTION__))!=0){ - public_id=avp->data; - LM_DBG("RTR also has public id [%.*s]\n", public_id.len, public_id.s); - ul.lock_udomain(udomain, &public_id); - res = ul.get_impurecord(udomain, &public_id, &r); - if (res != 0) { - LM_WARN("Strange, '%.*s' Not found in usrloc\n", public_id.len, public_id.s); - ul.unlock_udomain(udomain, &public_id); - //no point in continuing - return 0; - } - impucontact = r->linked_contacts.head; - while (impucontact) { - LM_DBG("Deleting contact with AOR [%.*s]\n", impucontact->contact->aor.len, impucontact->contact->aor.s); + ul.unlock_udomain(udomain, &public_id); + + while(cdpb.AAAGetNextAVP(avp) + && (avp = cxdx_get_next_public_identity(rtr, + cdpb.AAAGetNextAVP(avp), AVP_IMS_Public_Identity, + IMS_vendor_id_3GPP, __FUNCTION__)) + != 0) { + public_id = avp->data; + LM_DBG("RTR also has public id [%.*s]\n", public_id.len, + public_id.s); + ul.lock_udomain(udomain, &public_id); + res = ul.get_impurecord(udomain, &public_id, &r); + if(res != 0) { + LM_WARN("Strange, '%.*s' Not found in usrloc\n", public_id.len, + public_id.s); + ul.unlock_udomain(udomain, &public_id); + //no point in continuing + return 0; + } + + impucontact = r->linked_contacts.head; + while(impucontact) { + LM_DBG("Deleting contact with AOR [%.*s]\n", + impucontact->contact->aor.len, + impucontact->contact->aor.s); ul.lock_contact_slot_i(impucontact->contact->sl); - if (r->shead) { + if(r->shead) { //send NOTIFY to all subscribers of this IMPU. - notify_subscribers(r, impucontact->contact, 0, 0, IMS_REGISTRAR_CONTACT_DEREGISTERED); + notify_subscribers(r, impucontact->contact, 0, 0, + IMS_REGISTRAR_CONTACT_DEREGISTERED); } impucontact->contact->state = CONTACT_DELETED; ul.unlock_contact_slot_i(impucontact->contact->sl); impucontact = impucontact->next; - } - - ul.unlock_udomain(udomain, &public_id); - } - } - cxdx_add_vendor_specific_appid(rta_msg,IMS_vendor_id_3GPP,IMS_Cx,0 /*IMS_Cx*/); - - cxdx_add_auth_session_state(rta_msg,1); - - /* send an RTA back to the HSS */ - cxdx_add_result_code(rta_msg,DIAMETER_SUCCESS); - - return rta_msg; - - + } + + ul.unlock_udomain(udomain, &public_id); + } + } + cxdx_add_vendor_specific_appid( + rta_msg, IMS_vendor_id_3GPP, IMS_Cx, 0 /*IMS_Cx*/); + + cxdx_add_auth_session_state(rta_msg, 1); + + /* send an RTA back to the HSS */ + cxdx_add_result_code(rta_msg, DIAMETER_SUCCESS); + + return rta_msg; } diff --git a/src/modules/ims_registrar_scscf/cxdx_callbacks.h b/src/modules/ims_registrar_scscf/cxdx_callbacks.h index 9b47976c504..7438d288464 100644 --- a/src/modules/ims_registrar_scscf/cxdx_callbacks.h +++ b/src/modules/ims_registrar_scscf/cxdx_callbacks.h @@ -29,6 +29,6 @@ */ int PPR_RTR_Event(void *parsed_message, int type, void *param); -AAAMessage* cxdx_process_rtr(AAAMessage *request); +AAAMessage *cxdx_process_rtr(AAAMessage *request); #endif /* CXDX_CALLBACKS_H */ diff --git a/src/modules/ims_registrar_scscf/cxdx_sar.c b/src/modules/ims_registrar_scscf/cxdx_sar.c index 95fed9602c9..0b53969e496 100644 --- a/src/modules/ims_registrar_scscf/cxdx_sar.c +++ b/src/modules/ims_registrar_scscf/cxdx_sar.c @@ -67,245 +67,267 @@ extern struct cdp_binds cdpb; extern unsigned int send_vs_callid_avp; -int create_return_code(int result) { - int rc; - int_str avp_val, avp_name; - avp_name.s.s = "saa_return_code"; - avp_name.s.len = 15; +int create_return_code(int result) +{ + int rc; + int_str avp_val, avp_name; + avp_name.s.s = "saa_return_code"; + avp_name.s.len = 15; - //build avp spec for saa_return_code - avp_val.n = result; + //build avp spec for saa_return_code + avp_val.n = result; - rc = add_avp(AVP_NAME_STR, avp_name, avp_val); + rc = add_avp(AVP_NAME_STR, avp_name, avp_val); - if (rc < 0) - LM_ERR("couldnt create AVP\n"); - else - LM_INFO("created AVP successfully : [%.*s] - [%d]\n", avp_name.s.len, avp_name.s.s, result); + if(rc < 0) + LM_ERR("couldnt create AVP\n"); + else + LM_INFO("created AVP successfully : [%.*s] - [%d]\n", avp_name.s.len, + avp_name.s.s, result); - return 1; + return 1; } -void free_saved_transaction_data(saved_transaction_t* data) { - if (!data) - return; +void free_saved_transaction_data(saved_transaction_t *data) +{ + if(!data) + return; - if (data->public_identity.s && data->public_identity.len) { - shm_free(data->public_identity.s); - data->public_identity.len = 0; - } - free_contact_buf(data->contact_header); - shm_free(data); + if(data->public_identity.s && data->public_identity.len) { + shm_free(data->public_identity.s); + data->public_identity.len = 0; + } + free_contact_buf(data->contact_header); + shm_free(data); } -void async_cdp_callback(int is_timeout, void *param, AAAMessage *saa, long elapsed_msecs) { - struct cell *t = 0; - int rc = -1, experimental_rc = -1; - int result = CSCF_RETURN_TRUE; - saved_transaction_t* data = 0; - struct sip_msg* req; - - str xml_data = {0, 0}, ccf1 = {0, 0}, ccf2 = {0, 0}, ecf1 = {0, 0}, ecf2 = {0, 0}; - ims_subscription* s = 0; - rerrno = R_FINE; - - if (!param) { - LM_DBG("No transaction data this must have been called from usrloc cb impu deleted - just log result code and then exit"); - cxdx_get_result_code(saa, &rc); - cxdx_get_experimental_result_code(saa, &experimental_rc); - - if (saa) cdpb.AAAFreeMessage(&saa); - - if (!rc && !experimental_rc) { - LM_ERR("bad SAA result code\n"); - return; - } - switch (rc) { - case -1: - LM_DBG("Received Diameter error\n"); - return; - - case AAA_UNABLE_TO_COMPLY: - LM_DBG("Unable to comply\n"); - return; - - case AAA_SUCCESS: - LM_DBG("received AAA success\n"); - return; - - default: - LM_ERR("Unknown error\n"); - return; - } - - } else { - LM_DBG("There is transaction data this must have been called from save or assign server unreg"); - data = (saved_transaction_t*) param; - if (tmb.t_lookup_ident(&t, data->tindex, data->tlabel) < 0) { - LM_ERR("t_continue: transaction not found and t is now pointing to %p and will be set to NULL\n", t); - t = NULL; - rerrno = R_SAR_FAILED; - goto error_no_send; - } - - set_avp_list(AVP_TRACK_FROM | AVP_CLASS_URI, &t->uri_avps_from); - set_avp_list(AVP_TRACK_TO | AVP_CLASS_URI, &t->uri_avps_to); - set_avp_list(AVP_TRACK_FROM | AVP_CLASS_USER, &t->user_avps_from); - set_avp_list(AVP_TRACK_TO | AVP_CLASS_USER, &t->user_avps_to); - set_avp_list(AVP_TRACK_FROM | AVP_CLASS_DOMAIN, &t->domain_avps_from); - set_avp_list(AVP_TRACK_TO | AVP_CLASS_DOMAIN, &t->domain_avps_to); - - get_act_time(); - - req = get_request_from_tx(t); - if (!req) { - LM_ERR("Failed to get SIP Request from Transaction\n"); - goto error_no_send; - } - - if (is_timeout) { - update_stat(stat_sar_timeouts, 1); - LM_ERR("Transaction timeout - did not get SAA\n"); - rerrno = R_SAR_FAILED; - goto error; - } - if (!saa) { - LM_ERR("Error sending message via CDP\n"); - rerrno = R_SAR_FAILED; - goto error; - } - - update_stat(sar_replies_received, 1); - update_stat(sar_replies_response_time, elapsed_msecs); - - - /* check and see that all the required headers are available and can be parsed */ - if (parse_message_for_register(req) < 0) { - LM_ERR("Unable to parse register message correctly\n"); - rerrno = R_SAR_FAILED; - goto error; - } - - LM_DBG("callid for found transaction is [%.*s]\n", req->callid->body.len, req->callid->body.s); - - - cxdx_get_result_code(saa, &rc); - cxdx_get_experimental_result_code(saa, &experimental_rc); - cxdx_get_charging_info(saa, &ccf1, &ccf2, &ecf1, &ecf2); - - if (!rc && !experimental_rc) { - LM_ERR("bad SAA result code\n"); - rerrno = R_SAR_FAILED; - goto error; - } - - switch (rc) { - case -1: - LM_DBG("Received Diameter error\n"); - rerrno = R_SAR_FAILED; - goto error; - - case AAA_UNABLE_TO_COMPLY: - LM_DBG("Unable to comply\n"); - rerrno = R_SAR_FAILED; - goto error; - - case AAA_SUCCESS: - LM_DBG("received AAA success for SAR - SAA\n"); - break; - - default: - LM_ERR("Unknown error\n"); - rerrno = R_SAR_FAILED; - goto error; - } - //success - //if this is from a save (not a server assign unreg) and expires is zero we don't update usrloc as this is a dereg and usrloc was updated previously - if (data->sar_assignment_type != AVP_IMS_SAR_UNREGISTERED_USER && data->expires == 0) { - LM_DBG("no need to update usrloc - already done for de-reg\n"); - result = CSCF_RETURN_TRUE; - goto success; - } - - xml_data = cxdx_get_user_data(saa); - /*If there is XML user data we must be able to parse it*/ - if (xml_data.s && xml_data.len > 0) { - LM_DBG("Parsing user data string from SAA\n"); - s = parse_user_data(xml_data); - if (!s) { - LM_ERR("Unable to parse user data XML string\n"); - rerrno = R_SAR_FAILED; - goto error; - } - LM_DBG("Successfully parse user data XML setting ref to 1 (we are referencing it)\n"); - s->ref_count = 1; //no need to lock as nobody else will be referencing this piece of memory just yet - } else { - if (data->require_user_data) { - LM_ERR("We require User data for this assignment/register and none was supplied\n"); - rerrno = R_SAR_FAILED; - result = CSCF_RETURN_FALSE; - goto done; - } - } - - //here we update the contacts and also build the new contact header for the 200 OK reply - if (update_contacts(req, data->domain, &data->public_identity, data->sar_assignment_type, &s, &ccf1, &ccf2, &ecf1, &ecf2, &data->contact_header) <= 0) { - LM_ERR("Error processing REGISTER\n"); - rerrno = R_SAR_FAILED; - goto error; - } - - if (data->contact_header) { - LM_DBG("Updated contacts: %.*s\n", data->contact_header->data_len, data->contact_header->buf); - } else { - LM_DBG("Updated unreg contact\n"); - } - - } +void async_cdp_callback( + int is_timeout, void *param, AAAMessage *saa, long elapsed_msecs) +{ + struct cell *t = 0; + int rc = -1, experimental_rc = -1; + int result = CSCF_RETURN_TRUE; + saved_transaction_t *data = 0; + struct sip_msg *req; + + str xml_data = {0, 0}, ccf1 = {0, 0}, ccf2 = {0, 0}, ecf1 = {0, 0}, + ecf2 = {0, 0}; + ims_subscription *s = 0; + rerrno = R_FINE; + + if(!param) { + LM_DBG("No transaction data this must have been called from usrloc cb " + "impu deleted - just log result code and then exit"); + cxdx_get_result_code(saa, &rc); + cxdx_get_experimental_result_code(saa, &experimental_rc); + + if(saa) + cdpb.AAAFreeMessage(&saa); + + if(!rc && !experimental_rc) { + LM_ERR("bad SAA result code\n"); + return; + } + switch(rc) { + case -1: + LM_DBG("Received Diameter error\n"); + return; + + case AAA_UNABLE_TO_COMPLY: + LM_DBG("Unable to comply\n"); + return; + + case AAA_SUCCESS: + LM_DBG("received AAA success\n"); + return; + + default: + LM_ERR("Unknown error\n"); + return; + } + + } else { + LM_DBG("There is transaction data this must have been called from save " + "or assign server unreg"); + data = (saved_transaction_t *)param; + if(tmb.t_lookup_ident(&t, data->tindex, data->tlabel) < 0) { + LM_ERR("t_continue: transaction not found and t is now pointing to " + "%p and will be set to NULL\n", + t); + t = NULL; + rerrno = R_SAR_FAILED; + goto error_no_send; + } + + set_avp_list(AVP_TRACK_FROM | AVP_CLASS_URI, &t->uri_avps_from); + set_avp_list(AVP_TRACK_TO | AVP_CLASS_URI, &t->uri_avps_to); + set_avp_list(AVP_TRACK_FROM | AVP_CLASS_USER, &t->user_avps_from); + set_avp_list(AVP_TRACK_TO | AVP_CLASS_USER, &t->user_avps_to); + set_avp_list(AVP_TRACK_FROM | AVP_CLASS_DOMAIN, &t->domain_avps_from); + set_avp_list(AVP_TRACK_TO | AVP_CLASS_DOMAIN, &t->domain_avps_to); + + get_act_time(); + + req = get_request_from_tx(t); + if(!req) { + LM_ERR("Failed to get SIP Request from Transaction\n"); + goto error_no_send; + } + + if(is_timeout) { + update_stat(stat_sar_timeouts, 1); + LM_ERR("Transaction timeout - did not get SAA\n"); + rerrno = R_SAR_FAILED; + goto error; + } + if(!saa) { + LM_ERR("Error sending message via CDP\n"); + rerrno = R_SAR_FAILED; + goto error; + } + + update_stat(sar_replies_received, 1); + update_stat(sar_replies_response_time, elapsed_msecs); + + + /* check and see that all the required headers are available and can be parsed */ + if(parse_message_for_register(req) < 0) { + LM_ERR("Unable to parse register message correctly\n"); + rerrno = R_SAR_FAILED; + goto error; + } + + LM_DBG("callid for found transaction is [%.*s]\n", + req->callid->body.len, req->callid->body.s); + + + cxdx_get_result_code(saa, &rc); + cxdx_get_experimental_result_code(saa, &experimental_rc); + cxdx_get_charging_info(saa, &ccf1, &ccf2, &ecf1, &ecf2); + + if(!rc && !experimental_rc) { + LM_ERR("bad SAA result code\n"); + rerrno = R_SAR_FAILED; + goto error; + } + + switch(rc) { + case -1: + LM_DBG("Received Diameter error\n"); + rerrno = R_SAR_FAILED; + goto error; + + case AAA_UNABLE_TO_COMPLY: + LM_DBG("Unable to comply\n"); + rerrno = R_SAR_FAILED; + goto error; + + case AAA_SUCCESS: + LM_DBG("received AAA success for SAR - SAA\n"); + break; + + default: + LM_ERR("Unknown error\n"); + rerrno = R_SAR_FAILED; + goto error; + } + //success + //if this is from a save (not a server assign unreg) and expires is zero we don't update usrloc as this is a dereg and usrloc was updated previously + if(data->sar_assignment_type != AVP_IMS_SAR_UNREGISTERED_USER + && data->expires == 0) { + LM_DBG("no need to update usrloc - already done for de-reg\n"); + result = CSCF_RETURN_TRUE; + goto success; + } + + xml_data = cxdx_get_user_data(saa); + /*If there is XML user data we must be able to parse it*/ + if(xml_data.s && xml_data.len > 0) { + LM_DBG("Parsing user data string from SAA\n"); + s = parse_user_data(xml_data); + if(!s) { + LM_ERR("Unable to parse user data XML string\n"); + rerrno = R_SAR_FAILED; + goto error; + } + LM_DBG("Successfully parse user data XML setting ref to 1 (we are " + "referencing it)\n"); + s->ref_count = + 1; //no need to lock as nobody else will be referencing this piece of memory just yet + } else { + if(data->require_user_data) { + LM_ERR("We require User data for this assignment/register and " + "none was supplied\n"); + rerrno = R_SAR_FAILED; + result = CSCF_RETURN_FALSE; + goto done; + } + } + + //here we update the contacts and also build the new contact header for the 200 OK reply + if(update_contacts(req, data->domain, &data->public_identity, + data->sar_assignment_type, &s, &ccf1, &ccf2, &ecf1, &ecf2, + &data->contact_header) + <= 0) { + LM_ERR("Error processing REGISTER\n"); + rerrno = R_SAR_FAILED; + goto error; + } + + if(data->contact_header) { + LM_DBG("Updated contacts: %.*s\n", data->contact_header->data_len, + data->contact_header->buf); + } else { + LM_DBG("Updated unreg contact\n"); + } + } success: - update_stat(accepted_registrations, 1); + update_stat(accepted_registrations, 1); done: - if (data->sar_assignment_type != AVP_IMS_SAR_UNREGISTERED_USER) - reg_send_reply_transactional(req, data->contact_header, t); - LM_DBG("DBG:SAR Async CDP callback: ... Done resuming transaction\n"); - - create_return_code(result); - - //release our reference on subscription (s) - if (s) - ul.unref_subscription(s); - - //free memory - if (saa) cdpb.AAAFreeMessage(&saa); - if (t) { -// del_nonshm_lump_rpl(&req->reply_lump); - tmb.unref_cell(t); - } - //free path vector pkg memory -// reset_path_vector(req); - - tmb.t_continue_skip_timer(data->tindex, data->tlabel, data->act); - free_saved_transaction_data(data); - return; + if(data->sar_assignment_type != AVP_IMS_SAR_UNREGISTERED_USER) + reg_send_reply_transactional(req, data->contact_header, t); + LM_DBG("DBG:SAR Async CDP callback: ... Done resuming transaction\n"); + + create_return_code(result); + + //release our reference on subscription (s) + if(s) + ul.unref_subscription(s); + + //free memory + if(saa) + cdpb.AAAFreeMessage(&saa); + if(t) { + // del_nonshm_lump_rpl(&req->reply_lump); + tmb.unref_cell(t); + } + //free path vector pkg memory + // reset_path_vector(req); + + tmb.t_continue_skip_timer(data->tindex, data->tlabel, data->act); + free_saved_transaction_data(data); + return; error: - create_return_code(-2); - if (data->sar_assignment_type != AVP_IMS_SAR_UNREGISTERED_USER) - reg_send_reply_transactional(req, data->contact_header, t); - -error_no_send: //if we don't have the transaction then we can't send a transaction response - update_stat(rejected_registrations, 1); - //free memory - if (saa) cdpb.AAAFreeMessage(&saa); - if (t) { -// del_nonshm_lump_rpl(&req->reply_lump); - tmb.unref_cell(t); - } - tmb.t_continue(data->tindex, data->tlabel, data->act); - free_saved_transaction_data(data); - return; + create_return_code(-2); + if(data->sar_assignment_type != AVP_IMS_SAR_UNREGISTERED_USER) + reg_send_reply_transactional(req, data->contact_header, t); + +error_no_send + : //if we don't have the transaction then we can't send a transaction response + update_stat(rejected_registrations, 1); + //free memory + if(saa) + cdpb.AAAFreeMessage(&saa); + if(t) { + // del_nonshm_lump_rpl(&req->reply_lump); + tmb.unref_cell(t); + } + tmb.t_continue(data->tindex, data->tlabel, data->act); + free_saved_transaction_data(data); + return; } /** @@ -318,60 +340,74 @@ void async_cdp_callback(int is_timeout, void *param, AAAMessage *saa, long elaps * @param data_available - if the data is already available * @returns the SAA */ -int cxdx_send_sar(struct sip_msg *msg, str public_identity, str private_identity, - str server_name, int assignment_type, int data_available, saved_transaction_t* transaction_data) { - AAAMessage *sar = 0; - AAASession *session = 0; - unsigned int hash = 0, label = 0; - struct hdr_field *hdr; +int cxdx_send_sar(struct sip_msg *msg, str public_identity, + str private_identity, str server_name, int assignment_type, + int data_available, saved_transaction_t *transaction_data) +{ + AAAMessage *sar = 0; + AAASession *session = 0; + unsigned int hash = 0, label = 0; + struct hdr_field *hdr; str call_id; - session = cdpb.AAACreateSession(0); + session = cdpb.AAACreateSession(0); - sar = cdpb.AAACreateRequest(IMS_Cx, IMS_SAR, Flag_Proxyable, session); - if (session) { - cdpb.AAADropSession(session); - session = 0; - } - if (!sar) goto error1; + sar = cdpb.AAACreateRequest(IMS_Cx, IMS_SAR, Flag_Proxyable, session); + if(session) { + cdpb.AAADropSession(session); + session = 0; + } + if(!sar) + goto error1; - if (msg && send_vs_callid_avp) { + if(msg && send_vs_callid_avp) { call_id = cscf_get_call_id(msg, &hdr); - if (call_id.len>0 && call_id.s) { - if (!cxdx_add_call_id(sar, call_id)) - LM_WARN("Failed to add call-id to SAR.... continuing... assuming non-critical\n"); + if(call_id.len > 0 && call_id.s) { + if(!cxdx_add_call_id(sar, call_id)) + LM_WARN("Failed to add call-id to SAR.... continuing... " + "assuming non-critical\n"); } } - - if (!cxdx_add_destination_realm(sar, cxdx_dest_realm)) goto error1; - if (!cxdx_add_vendor_specific_appid(sar, IMS_vendor_id_3GPP, IMS_Cx, 0 /*IMS_Cx*/)) goto error1; - if (!cxdx_add_auth_session_state(sar, 1)) goto error1; - - if (!cxdx_add_public_identity(sar, public_identity)) goto error1; - if (!cxdx_add_server_name(sar, server_name)) goto error1; - if (private_identity.len) - if (!cxdx_add_user_name(sar, private_identity)) goto error1; - if (!cxdx_add_server_assignment_type(sar, assignment_type)) goto error1; - if (!cxdx_add_userdata_available(sar, data_available)) goto error1; - - if (msg && tmb.t_get_trans_ident(msg, &hash, &label) < 0) { - // it's ok cause we can call this async with a message for ul callbacks! - LM_DBG("SIP message without transaction... must be a ul callback\n"); - //return 0; - } + if(!cxdx_add_destination_realm(sar, cxdx_dest_realm)) + goto error1; + + if(!cxdx_add_vendor_specific_appid( + sar, IMS_vendor_id_3GPP, IMS_Cx, 0 /*IMS_Cx*/)) + goto error1; + if(!cxdx_add_auth_session_state(sar, 1)) + goto error1; + + if(!cxdx_add_public_identity(sar, public_identity)) + goto error1; + if(!cxdx_add_server_name(sar, server_name)) + goto error1; + if(private_identity.len) + if(!cxdx_add_user_name(sar, private_identity)) + goto error1; + if(!cxdx_add_server_assignment_type(sar, assignment_type)) + goto error1; + if(!cxdx_add_userdata_available(sar, data_available)) + goto error1; + + if(msg && tmb.t_get_trans_ident(msg, &hash, &label) < 0) { + // it's ok cause we can call this async with a message for ul callbacks! + LM_DBG("SIP message without transaction... must be a ul callback\n"); + //return 0; + } - if (cxdx_forced_peer.len) - cdpb.AAASendMessageToPeer(sar, &cxdx_forced_peer, (void*) async_cdp_callback, (void*) transaction_data); - else - cdpb.AAASendMessage(sar, (void*) async_cdp_callback, (void*) transaction_data); + if(cxdx_forced_peer.len) + cdpb.AAASendMessageToPeer(sar, &cxdx_forced_peer, + (void *)async_cdp_callback, (void *)transaction_data); + else + cdpb.AAASendMessage( + sar, (void *)async_cdp_callback, (void *)transaction_data); - return 0; + return 0; error1: //Only free SAR IFF it has not been passed to CDP - if (sar) cdpb.AAAFreeMessage(&sar); - - return -1; - + if(sar) + cdpb.AAAFreeMessage(&sar); + return -1; } diff --git a/src/modules/ims_registrar_scscf/cxdx_sar.h b/src/modules/ims_registrar_scscf/cxdx_sar.h index 0d9537592aa..4382c44245d 100644 --- a/src/modules/ims_registrar_scscf/cxdx_sar.h +++ b/src/modules/ims_registrar_scscf/cxdx_sar.h @@ -48,20 +48,23 @@ extern struct cdp_binds cdpb; -extern str cxdx_forced_peer; /**< FQDN of the Diameter peer to send requests to */ +extern str + cxdx_forced_peer; /**< FQDN of the Diameter peer to send requests to */ extern str cxdx_dest_realm; -typedef struct saved_transaction { +typedef struct saved_transaction +{ unsigned int tindex; unsigned int tlabel; unsigned int ticks; cfg_action_t *act; - int expires; //used to see if this is a dereg as then we don't need to touch usrloc! > 0 if not dereg - 0 id de-reg - int require_user_data; - int sar_assignment_type; - str public_identity; - udomain_t* domain; - contact_for_header_t* contact_header;//used to send the 200 OK with contacts after async callback for dereg where we don't rebuild the contacts + int expires; //used to see if this is a dereg as then we don't need to touch usrloc! > 0 if not dereg - 0 id de-reg + int require_user_data; + int sar_assignment_type; + str public_identity; + udomain_t *domain; + contact_for_header_t * + contact_header; //used to send the 200 OK with contacts after async callback for dereg where we don't rebuild the contacts } saved_transaction_t; /** @@ -75,12 +78,12 @@ typedef struct saved_transaction { * @param data_available - if the data is already available * @returns the SAA */ -int cxdx_send_sar(struct sip_msg *msg, str public_identity, str private_identity, - str server_name,int assignment_type, int data_available, saved_transaction_t* transaction_data); +int cxdx_send_sar(struct sip_msg *msg, str public_identity, + str private_identity, str server_name, int assignment_type, + int data_available, saved_transaction_t *transaction_data); -void free_saved_transaction_data(saved_transaction_t* data); +void free_saved_transaction_data(saved_transaction_t *data); int create_return_code(int result); - -#endif +#endif diff --git a/src/modules/ims_registrar_scscf/ims_registrar_scscf_mod.c b/src/modules/ims_registrar_scscf/ims_registrar_scscf_mod.c index 4b65ccb1475..c2418548bd6 100644 --- a/src/modules/ims_registrar_scscf/ims_registrar_scscf_mod.c +++ b/src/modules/ims_registrar_scscf/ims_registrar_scscf_mod.c @@ -77,13 +77,13 @@ MODULE_VERSION -extern gen_lock_t* process_lock; /* lock on the process table */ +extern gen_lock_t *process_lock; /* lock on the process table */ int *callback_singleton; /**< Cx callback singleton */ -stat_var* stat_sar_timeouts; -stat_var* sar_replies_received; -stat_var* sar_replies_response_time; +stat_var *stat_sar_timeouts; +stat_var *sar_replies_received; +stat_var *sar_replies_response_time; struct tm_binds tmb; @@ -94,13 +94,18 @@ cdp_avp_bind_t *cdp_avp; usrloc_api_t ul; /*!< Structure containing pointers to usrloc functions*/ char *scscf_user_data_dtd = 0; /* Path to "CxDataType.dtd" */ -char *scscf_user_data_xsd = 0; /* Path to "CxDataType_Rel6.xsd" or "CxDataType_Rel7.xsd" */ +char *scscf_user_data_xsd = + 0; /* Path to "CxDataType_Rel6.xsd" or "CxDataType_Rel7.xsd" */ int scscf_support_wildcardPSI = 0; -int store_data_on_dereg = 0; /**< should we store SAR data on de-registration */ -unsigned int send_vs_callid_avp = 1; /* flag to enable/disable proprietary use of a callid AVP. TODO: add call-id as per TS129.229 */ -int skip_multiple_bindings_on_reg_resp = 0; /* For RE-REGISTRATION in 200 OK add only the current contact and skip all other bindings */ - -int ue_unsubscribe_on_dereg = 0; /*many UEs do not unsubscribe on de reg - therefore we should remove their subscription and not send a notify +int store_data_on_dereg = + 0; /**< should we store SAR data on de-registration */ +unsigned int send_vs_callid_avp = + 1; /* flag to enable/disable proprietary use of a callid AVP. TODO: add call-id as per TS129.229 */ +int skip_multiple_bindings_on_reg_resp = + 0; /* For RE-REGISTRATION in 200 OK add only the current contact and skip all other bindings */ + +int ue_unsubscribe_on_dereg = + 0; /*many UEs do not unsubscribe on de reg - therefore we should remove their subscription and not send a notify Some UEs do unsubscribe then everything is fine*/ int user_data_always = 0; /* Always Reports that user data is missing to HSS */ @@ -112,12 +117,13 @@ str cxdx_dest_realm = str_init("ims.smilecoms.com"); //Only used if we want to force the Rx peer //Usually this is configured at a stack level and the first request uses realm routing -str cxdx_forced_peer = {0,0}; +str cxdx_forced_peer = {0, 0}; -str scscf_name_str = str_init("sip:scscf2.ims.smilecoms.com:6060"); /* default scscf_name - actual should be set via parameter*/ +str scscf_name_str = str_init( + "sip:scscf2.ims.smilecoms.com:6060"); /* default scscf_name - actual should be set via parameter*/ str scscf_serviceroute_uri_str; /* Service Route URI */ -char *domain = "location"; ///TODO should be configurable mod param +char *domain = "location"; ///TODO should be configurable mod param struct _pv_req_data _pv_treq; @@ -125,36 +131,42 @@ struct _pv_req_data _pv_treq; static int mod_init(void); static int child_init(int); static void mod_destroy(void); -static int w_save(struct sip_msg* _m, char * _route, char* _d, char* mode, char* _cflags); -static int w_assign_server_unreg(struct sip_msg* _m, char* _route, char* _d, char* _direction); -static int w_lookup(struct sip_msg* _m, char* _d, char* _p2); -static int w_lookup_ue_type(struct sip_msg* _m, char* _d, char* _p2); -static int w_lookup_path_to_contact(struct sip_msg* _m, char* contact_uri); +static int w_save( + struct sip_msg *_m, char *_route, char *_d, char *mode, char *_cflags); +static int w_assign_server_unreg( + struct sip_msg *_m, char *_route, char *_d, char *_direction); +static int w_lookup(struct sip_msg *_m, char *_d, char *_p2); +static int w_lookup_ue_type(struct sip_msg *_m, char *_d, char *_p2); +static int w_lookup_path_to_contact(struct sip_msg *_m, char *contact_uri); /*! \brief Fixup functions */ -static int domain_fixup(void** param, int param_no); -static int assign_save_fixup3_async(void** param, int param_no); -static int free_uint_fixup(void** param, int param_no); -static int save_fixup3(void** param, int param_no); -static int unreg_fixup(void** param, int param_no); -static int fetchc_fixup(void** param, int param_no); +static int domain_fixup(void **param, int param_no); +static int assign_save_fixup3_async(void **param, int param_no); +static int free_uint_fixup(void **param, int param_no); +static int save_fixup3(void **param, int param_no); +static int unreg_fixup(void **param, int param_no); +static int fetchc_fixup(void **param, int param_no); /*! \brief Functions */ -static int add_sock_hdr(struct sip_msg* msg, char *str, char *foo); +static int add_sock_hdr(struct sip_msg *msg, char *str, char *foo); -AAAMessage* callback_cdp_request(AAAMessage *request, void *param); +AAAMessage *callback_cdp_request(AAAMessage *request, void *param); int tcp_persistent_flag = -1; /*!< if the TCP connection should be kept open */ -int method_filtering = 0; /*!< if the looked up contacts should be filtered based on supported methods */ +int method_filtering = + 0; /*!< if the looked up contacts should be filtered based on supported methods */ int path_enabled = 0; /*!< if the Path HF should be handled */ -int path_mode = PATH_MODE_STRICT; /*!< if the Path HF should be inserted in the reply. +int path_mode = + PATH_MODE_STRICT; /*!< if the Path HF should be inserted in the reply. * - STRICT (2): always insert, error if no support indicated in request * - LAZY (1): insert only if support indicated in request * - OFF (0): never insert */ -int path_use_params = 0; /*!< if the received- and nat-parameters of last Path uri should be used +int path_use_params = + 0; /*!< if the received- and nat-parameters of last Path uri should be used * to determine if UAC is nat'ed */ -char *aor_avp_param = 0; /*!< if instead of extacting the AOR from the request, it should be +char *aor_avp_param = + 0; /*!< if instead of extacting the AOR from the request, it should be * fetched via this AVP ID */ unsigned short aor_avp_type = 0; int_str aor_avp_name; @@ -164,25 +176,32 @@ char *reg_callid_avp_param = 0; unsigned short reg_callid_avp_type = 0; int_str reg_callid_avp_name; -char* rcv_avp_param = 0; +char *rcv_avp_param = 0; unsigned short rcv_avp_type = 0; int_str rcv_avp_name; int sock_flag = -1; str sock_hdr_name = {0, 0}; -int subscription_default_expires = 3600; /**< the default value for expires if none found*/ -int subscription_min_expires = 10; /**< minimum subscription expiration time */ -int subscription_max_expires = 1000000; /**< maximum subscription expiration time */ +int subscription_default_expires = + 3600; /**< the default value for expires if none found*/ +int subscription_min_expires = + 10; /**< minimum subscription expiration time */ +int subscription_max_expires = + 1000000; /**< maximum subscription expiration time */ int subscription_expires_range = 0; -int contact_expires_buffer_percentage = 10; /**< percentage we expiry for contact we will substrace from reg response to UE */ +int contact_expires_buffer_percentage = + 10; /**< percentage we expiry for contact we will substrace from reg response to UE */ -int notification_list_size_threshold = 0; /**Threshold for size of notification list after which a warning is logged */ +int notification_list_size_threshold = + 0; /**Threshold for size of notification list after which a warning is logged */ int max_notification_list_size = 0; -int notification_processes = 4; /*Number of processes that processes the notification queue*/ +int notification_processes = + 4; /*Number of processes that processes the notification queue*/ -reg_notification_list *notification_list; /**< list of notifications for reg to be sent */ +reg_notification_list * + notification_list; /**< list of notifications for reg to be sent */ IMS_Events_enum_t IMS_Events; IMS_Registrar_events_enum_t IMS_Registrar_events; @@ -203,123 +222,139 @@ sl_api_t slb; * Exported PV */ static pv_export_t mod_pvs[] = { - { - {"ulc", sizeof ("ulc") - 1}, PVT_OTHER, pv_get_ulc, pv_set_ulc, - pv_parse_ulc_name, pv_parse_index, 0, 0 - }, - { - {0, 0}, 0, 0, 0, 0, 0, 0, 0 - } -}; + {{"ulc", sizeof("ulc") - 1}, PVT_OTHER, pv_get_ulc, pv_set_ulc, + pv_parse_ulc_name, pv_parse_index, 0, 0}, + {{0, 0}, 0, 0, 0, 0, 0, 0, 0}}; /*! \brief * Exported functions */ static cmd_export_t cmds[] = { - {"save", (cmd_function) w_save, 2, assign_save_fixup3_async, 0, REQUEST_ROUTE | ONREPLY_ROUTE}, - {"save", (cmd_function) w_save, 3, assign_save_fixup3_async, 0, REQUEST_ROUTE | ONREPLY_ROUTE}, - {"save", (cmd_function) w_save, 4, save_fixup3, free_uint_fixup, REQUEST_ROUTE | ONREPLY_ROUTE}, - {"lookup", (cmd_function) w_lookup, 1, domain_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE}, - {"lookup", (cmd_function) w_lookup_ue_type, 2, domain_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE}, - {"lookup_path_to_contact", (cmd_function) w_lookup_path_to_contact, 1, fixup_var_str_12, 0, REQUEST_ROUTE}, - {"term_impu_registered", (cmd_function) term_impu_registered, 1, domain_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE}, - {"term_impu_has_contact", (cmd_function) term_impu_has_contact, 1, domain_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE}, - {"impu_registered", (cmd_function) impu_registered, 1, domain_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE}, - {"assign_server_unreg", (cmd_function) w_assign_server_unreg, 3, assign_save_fixup3_async, 0, REQUEST_ROUTE}, - {"add_sock_hdr", (cmd_function) add_sock_hdr, 1, fixup_str_null, 0, REQUEST_ROUTE}, - {"unregister", (cmd_function) unregister, 2, unreg_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE}, - {"reg_fetch_contacts", (cmd_function) pv_fetch_contacts, 3, fetchc_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE}, - {"reg_free_contacts", (cmd_function) pv_free_contacts, 1, fixup_str_null, 0, REQUEST_ROUTE | FAILURE_ROUTE}, - {"can_subscribe_to_reg", (cmd_function) can_subscribe_to_reg, 1, domain_fixup, 0, REQUEST_ROUTE}, - {"subscribe_to_reg", (cmd_function) subscribe_to_reg, 1, domain_fixup, 0, REQUEST_ROUTE}, - {"can_publish_reg", (cmd_function) can_publish_reg, 1, domain_fixup, 0, REQUEST_ROUTE}, - {"publish_reg", (cmd_function) publish_reg, 1, domain_fixup, 0, REQUEST_ROUTE}, - //{"bind_registrar", (cmd_function) bind_registrar, 0, 0, 0, 0}, TODO put this back in ! - {0, 0, 0, 0, 0, 0} -}; + {"save", (cmd_function)w_save, 2, assign_save_fixup3_async, 0, + REQUEST_ROUTE | ONREPLY_ROUTE}, + {"save", (cmd_function)w_save, 3, assign_save_fixup3_async, 0, + REQUEST_ROUTE | ONREPLY_ROUTE}, + {"save", (cmd_function)w_save, 4, save_fixup3, free_uint_fixup, + REQUEST_ROUTE | ONREPLY_ROUTE}, + {"lookup", (cmd_function)w_lookup, 1, domain_fixup, 0, + REQUEST_ROUTE | FAILURE_ROUTE}, + {"lookup", (cmd_function)w_lookup_ue_type, 2, domain_fixup, 0, + REQUEST_ROUTE | FAILURE_ROUTE}, + {"lookup_path_to_contact", (cmd_function)w_lookup_path_to_contact, 1, + fixup_var_str_12, 0, REQUEST_ROUTE}, + {"term_impu_registered", (cmd_function)term_impu_registered, 1, + domain_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE}, + {"term_impu_has_contact", (cmd_function)term_impu_has_contact, 1, + domain_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE}, + {"impu_registered", (cmd_function)impu_registered, 1, domain_fixup, 0, + REQUEST_ROUTE | FAILURE_ROUTE}, + {"assign_server_unreg", (cmd_function)w_assign_server_unreg, 3, + assign_save_fixup3_async, 0, REQUEST_ROUTE}, + {"add_sock_hdr", (cmd_function)add_sock_hdr, 1, fixup_str_null, 0, + REQUEST_ROUTE}, + {"unregister", (cmd_function)unregister, 2, unreg_fixup, 0, + REQUEST_ROUTE | FAILURE_ROUTE}, + {"reg_fetch_contacts", (cmd_function)pv_fetch_contacts, 3, fetchc_fixup, + 0, REQUEST_ROUTE | FAILURE_ROUTE}, + {"reg_free_contacts", (cmd_function)pv_free_contacts, 1, fixup_str_null, + 0, REQUEST_ROUTE | FAILURE_ROUTE}, + {"can_subscribe_to_reg", (cmd_function)can_subscribe_to_reg, 1, + domain_fixup, 0, REQUEST_ROUTE}, + {"subscribe_to_reg", (cmd_function)subscribe_to_reg, 1, domain_fixup, 0, + REQUEST_ROUTE}, + {"can_publish_reg", (cmd_function)can_publish_reg, 1, domain_fixup, 0, + REQUEST_ROUTE}, + {"publish_reg", (cmd_function)publish_reg, 1, domain_fixup, 0, + REQUEST_ROUTE}, + //{"bind_registrar", (cmd_function) bind_registrar, 0, 0, 0, 0}, TODO put this back in ! + {0, 0, 0, 0, 0, 0}}; /*! \brief * Exported parameters */ static param_export_t params[] = { - {"default_expires", INT_PARAM, &default_registrar_cfg.default_expires}, - {"default_expires_range", INT_PARAM, &default_registrar_cfg.default_expires_range}, - {"min_expires", INT_PARAM, &default_registrar_cfg.min_expires}, - {"max_expires", INT_PARAM, &default_registrar_cfg.max_expires}, - {"em_default_expires", INT_PARAM, &default_registrar_cfg.em_default_expires}, - {"em_min_expires", INT_PARAM, &default_registrar_cfg.em_max_expires}, - {"em_min_expires", INT_PARAM, &default_registrar_cfg.em_min_expires}, - - {"default_q", INT_PARAM, &default_registrar_cfg.default_q}, - {"append_branches", INT_PARAM, &default_registrar_cfg.append_branches}, - {"case_sensitive", INT_PARAM, &default_registrar_cfg.case_sensitive}, - {"realm_prefix", PARAM_STRING, &default_registrar_cfg.realm_pref}, - - {"received_param", PARAM_STR, &rcv_param}, - {"received_avp", PARAM_STRING, &rcv_avp_param}, - {"aor_avp", PARAM_STRING, &aor_avp_param}, - {"reg_callid_avp", PARAM_STRING, ®_callid_avp_param}, - {"max_contacts", INT_PARAM, &default_registrar_cfg.max_contacts}, - {"retry_after", INT_PARAM, &default_registrar_cfg.retry_after}, - {"sock_flag", INT_PARAM, &sock_flag}, - {"sock_hdr_name", PARAM_STR, &sock_hdr_name}, - {"method_filtering", INT_PARAM, &method_filtering}, - {"use_path", INT_PARAM, &path_enabled}, - {"path_mode", INT_PARAM, &path_mode}, - {"path_use_received", INT_PARAM, &path_use_params}, - {"user_data_dtd", PARAM_STRING, &scscf_user_data_dtd}, - {"user_data_xsd", PARAM_STRING, &scscf_user_data_xsd}, - {"support_wildcardPSI", INT_PARAM, &scscf_support_wildcardPSI}, - {"scscf_name", PARAM_STR, &scscf_name_str}, //TODO: need to set this to default - {"store_profile_dereg", INT_PARAM, &store_data_on_dereg}, - {"cxdx_forced_peer", PARAM_STR, &cxdx_forced_peer}, - {"cxdx_dest_realm", PARAM_STR, &cxdx_dest_realm}, - {"subscription_default_expires", INT_PARAM, &subscription_default_expires}, - {"subscription_min_expires", INT_PARAM, &subscription_min_expires}, - {"subscription_max_expires", INT_PARAM, &subscription_max_expires}, - {"expires_buffer_percent", INT_PARAM, &contact_expires_buffer_percentage}, - {"ue_unsubscribe_on_dereg", INT_PARAM, &ue_unsubscribe_on_dereg}, - {"subscription_expires_range", INT_PARAM, &subscription_expires_range}, - {"user_data_always", INT_PARAM, &user_data_always}, - {"error_reply_code", INT_PARAM, &error_reply_code}, - {"notification_list_size_threshold", INT_PARAM, ¬ification_list_size_threshold}, - {"max_notification_list_size", INT_PARAM, &max_notification_list_size}, - {"notification_processes", INT_PARAM, ¬ification_processes}, - {"send_vs_callid_avp", INT_PARAM, &send_vs_callid_avp}, - {"skip_multiple_bindings_on_reg_resp", INT_PARAM, &skip_multiple_bindings_on_reg_resp}, - {0, 0, 0} -}; + {"default_expires", INT_PARAM, &default_registrar_cfg.default_expires}, + {"default_expires_range", INT_PARAM, + &default_registrar_cfg.default_expires_range}, + {"min_expires", INT_PARAM, &default_registrar_cfg.min_expires}, + {"max_expires", INT_PARAM, &default_registrar_cfg.max_expires}, + {"em_default_expires", INT_PARAM, + &default_registrar_cfg.em_default_expires}, + {"em_min_expires", INT_PARAM, &default_registrar_cfg.em_max_expires}, + {"em_min_expires", INT_PARAM, &default_registrar_cfg.em_min_expires}, + + {"default_q", INT_PARAM, &default_registrar_cfg.default_q}, + {"append_branches", INT_PARAM, &default_registrar_cfg.append_branches}, + {"case_sensitive", INT_PARAM, &default_registrar_cfg.case_sensitive}, + {"realm_prefix", PARAM_STRING, &default_registrar_cfg.realm_pref}, + + {"received_param", PARAM_STR, &rcv_param}, + {"received_avp", PARAM_STRING, &rcv_avp_param}, + {"aor_avp", PARAM_STRING, &aor_avp_param}, + {"reg_callid_avp", PARAM_STRING, ®_callid_avp_param}, + {"max_contacts", INT_PARAM, &default_registrar_cfg.max_contacts}, + {"retry_after", INT_PARAM, &default_registrar_cfg.retry_after}, + {"sock_flag", INT_PARAM, &sock_flag}, + {"sock_hdr_name", PARAM_STR, &sock_hdr_name}, + {"method_filtering", INT_PARAM, &method_filtering}, + {"use_path", INT_PARAM, &path_enabled}, + {"path_mode", INT_PARAM, &path_mode}, + {"path_use_received", INT_PARAM, &path_use_params}, + {"user_data_dtd", PARAM_STRING, &scscf_user_data_dtd}, + {"user_data_xsd", PARAM_STRING, &scscf_user_data_xsd}, + {"support_wildcardPSI", INT_PARAM, &scscf_support_wildcardPSI}, + {"scscf_name", PARAM_STR, + &scscf_name_str}, //TODO: need to set this to default + {"store_profile_dereg", INT_PARAM, &store_data_on_dereg}, + {"cxdx_forced_peer", PARAM_STR, &cxdx_forced_peer}, + {"cxdx_dest_realm", PARAM_STR, &cxdx_dest_realm}, + {"subscription_default_expires", INT_PARAM, + &subscription_default_expires}, + {"subscription_min_expires", INT_PARAM, &subscription_min_expires}, + {"subscription_max_expires", INT_PARAM, &subscription_max_expires}, + {"expires_buffer_percent", INT_PARAM, + &contact_expires_buffer_percentage}, + {"ue_unsubscribe_on_dereg", INT_PARAM, &ue_unsubscribe_on_dereg}, + {"subscription_expires_range", INT_PARAM, &subscription_expires_range}, + {"user_data_always", INT_PARAM, &user_data_always}, + {"error_reply_code", INT_PARAM, &error_reply_code}, + {"notification_list_size_threshold", INT_PARAM, + ¬ification_list_size_threshold}, + {"max_notification_list_size", INT_PARAM, &max_notification_list_size}, + {"notification_processes", INT_PARAM, ¬ification_processes}, + {"send_vs_callid_avp", INT_PARAM, &send_vs_callid_avp}, + {"skip_multiple_bindings_on_reg_resp", INT_PARAM, + &skip_multiple_bindings_on_reg_resp}, + {0, 0, 0}}; /*! \brief We expose internal variables via the statistic framework below.*/ -stat_export_t mod_stats[] = { - {"max_expires", STAT_NO_RESET, &max_expires_stat}, - {"max_contacts", STAT_NO_RESET, &max_contacts_stat}, - {"default_expire", STAT_NO_RESET, &default_expire_stat}, - {"default_expires_range", STAT_NO_RESET, &default_expire_range_stat}, - {"accepted_regs", 0, &accepted_registrations}, - {"rejected_regs", 0, &rejected_registrations}, - {"sar_avg_response_time", STAT_IS_FUNC, (stat_var**) get_avg_sar_response_time}, - {"notifies_in_q", STAT_IS_FUNC, (stat_var**) get_notification_list_size}, - {"sar_timeouts", 0, (stat_var**) & stat_sar_timeouts}, - {0, 0, 0} -}; +stat_export_t mod_stats[] = {{"max_expires", STAT_NO_RESET, &max_expires_stat}, + {"max_contacts", STAT_NO_RESET, &max_contacts_stat}, + {"default_expire", STAT_NO_RESET, &default_expire_stat}, + {"default_expires_range", STAT_NO_RESET, &default_expire_range_stat}, + {"accepted_regs", 0, &accepted_registrations}, + {"rejected_regs", 0, &rejected_registrations}, + {"sar_avg_response_time", STAT_IS_FUNC, + (stat_var **)get_avg_sar_response_time}, + {"notifies_in_q", STAT_IS_FUNC, + (stat_var **)get_notification_list_size}, + {"sar_timeouts", 0, (stat_var **)&stat_sar_timeouts}, {0, 0, 0}}; /*! \brief * Module exports structure */ struct module_exports exports = { - "ims_registrar_scscf", - DEFAULT_DLFLAGS, /* dlopen flags */ - cmds, /* Exported functions */ - params, /* Exported parameters */ - 0, /* exported RPC methods */ - mod_pvs, /* exported pseudo-variables */ - 0, /* response handling function */ - mod_init, /* module initialization function */ - child_init, /* Per-child init function */ - mod_destroy /* destroy function */ + "ims_registrar_scscf", DEFAULT_DLFLAGS, /* dlopen flags */ + cmds, /* Exported functions */ + params, /* Exported parameters */ + 0, /* exported RPC methods */ + mod_pvs, /* exported pseudo-variables */ + 0, /* response handling function */ + mod_init, /* module initialization function */ + child_init, /* Per-child init function */ + mod_destroy /* destroy function */ }; static str orig_prefix = {"sip:orig@", 9}; @@ -328,264 +363,273 @@ static str orig_prefix = {"sip:orig@", 9}; * Initialize parent */ -static int mod_init(void) { - pv_spec_t avp_spec; - str s; - bind_usrloc_t bind_usrloc; - qvalue_t dq; +static int mod_init(void) +{ + pv_spec_t avp_spec; + str s; + bind_usrloc_t bind_usrloc; + qvalue_t dq; - if (rpc_register_array(reg_rpc) != 0) { + if(rpc_register_array(reg_rpc) != 0) { LM_ERR("failed to register RPC commands\n"); return -1; } - - callback_singleton = shm_malloc(sizeof (int)); - *callback_singleton = 0; - - /*build the required strings */ - scscf_serviceroute_uri_str.s = - (char*) pkg_malloc(orig_prefix.len + scscf_name_str.len); - - if (!scscf_serviceroute_uri_str.s) { - LM_ERR("Unable to allocate memory for service route uri\n"); - return -1; - } - - if (contact_expires_buffer_percentage < 0 || contact_expires_buffer_percentage > 90) { - LM_ERR("contact expires percentage not valid, must be >0 and <=90"); - return -1; - } - - memcpy(scscf_serviceroute_uri_str.s, orig_prefix.s, orig_prefix.len); - scscf_serviceroute_uri_str.len = orig_prefix.len; - if (scscf_name_str.len > 4 - && strncasecmp(scscf_name_str.s, "sip:", 4) == 0) { - memcpy(scscf_serviceroute_uri_str.s + scscf_serviceroute_uri_str.len, - scscf_name_str.s + 4, scscf_name_str.len - 4); - scscf_serviceroute_uri_str.len += scscf_name_str.len - 4; - } else { - memcpy(scscf_serviceroute_uri_str.s + scscf_serviceroute_uri_str.len, - scscf_name_str.s, scscf_name_str.len); - scscf_serviceroute_uri_str.len += scscf_name_str.len; - } - - pv_tmx_data_init(); - - /* */ + + callback_singleton = shm_malloc(sizeof(int)); + *callback_singleton = 0; + + /*build the required strings */ + scscf_serviceroute_uri_str.s = + (char *)pkg_malloc(orig_prefix.len + scscf_name_str.len); + + if(!scscf_serviceroute_uri_str.s) { + LM_ERR("Unable to allocate memory for service route uri\n"); + return -1; + } + + if(contact_expires_buffer_percentage < 0 + || contact_expires_buffer_percentage > 90) { + LM_ERR("contact expires percentage not valid, must be >0 and <=90"); + return -1; + } + + memcpy(scscf_serviceroute_uri_str.s, orig_prefix.s, orig_prefix.len); + scscf_serviceroute_uri_str.len = orig_prefix.len; + if(scscf_name_str.len > 4 + && strncasecmp(scscf_name_str.s, "sip:", 4) == 0) { + memcpy(scscf_serviceroute_uri_str.s + scscf_serviceroute_uri_str.len, + scscf_name_str.s + 4, scscf_name_str.len - 4); + scscf_serviceroute_uri_str.len += scscf_name_str.len - 4; + } else { + memcpy(scscf_serviceroute_uri_str.s + scscf_serviceroute_uri_str.len, + scscf_name_str.s, scscf_name_str.len); + scscf_serviceroute_uri_str.len += scscf_name_str.len; + } + + pv_tmx_data_init(); + + /* */ #ifdef STATISTICS - /* register statistics */ - if (register_module_stats(exports.name, mod_stats) != 0) { - LM_ERR("failed to register core statistics\n"); - return -1; - } - if (!register_stats()) { - LM_ERR("Unable to register statistics\n"); - return -1; - } + /* register statistics */ + if(register_module_stats(exports.name, mod_stats) != 0) { + LM_ERR("failed to register core statistics\n"); + return -1; + } + if(!register_stats()) { + LM_ERR("Unable to register statistics\n"); + return -1; + } #endif - /*register space for notification processors*/ - register_procs(notification_processes); - cfg_register_child(notification_processes); - - /* bind the SL API */ - if (sl_load_api(&slb) != 0) { - LM_ERR("cannot bind to SL API\n"); - return -1; - } - - /* load the TM API */ - if (load_tm_api(&tmb) != 0) { - LM_ERR("can't load TM API\n"); - return -1; - } - - /* load the CDP API */ - if (load_cdp_api(&cdpb) != 0) { - LM_ERR("can't load CDP API\n"); - return -1; - } - - cdp_avp = load_cdp_avp(); - if (!cdp_avp) { - LM_ERR("can't load CDP_AVP API\n"); - return -1; - } - - if (cfg_declare("registrar", registrar_cfg_def, &default_registrar_cfg, - cfg_sizeof(registrar), ®istrar_cfg)) { - LM_ERR("Fail to declare the configuration\n"); - return -1; - } - - if (rcv_avp_param && *rcv_avp_param) { - s.s = rcv_avp_param; - s.len = strlen(s.s); - if (pv_parse_spec(&s, &avp_spec) == 0 || avp_spec.type != PVT_AVP) { - LM_ERR("malformed or non AVP %s AVP definition\n", rcv_avp_param); - return -1; - } - - if (pv_get_avp_name(0, &avp_spec.pvp, &rcv_avp_name, &rcv_avp_type) - != 0) { - LM_ERR("[%s]- invalid AVP definition\n", rcv_avp_param); - return -1; - } - } else { - rcv_avp_name.n = 0; - rcv_avp_type = 0; - } - if (aor_avp_param && *aor_avp_param) { - s.s = aor_avp_param; - s.len = strlen(s.s); - if (pv_parse_spec(&s, &avp_spec) == 0 || avp_spec.type != PVT_AVP) { - LM_ERR("malformed or non AVP %s AVP definition\n", aor_avp_param); - return -1; - } - - if (pv_get_avp_name(0, &avp_spec.pvp, &aor_avp_name, &aor_avp_type) - != 0) { - LM_ERR("[%s]- invalid AVP definition\n", aor_avp_param); - return -1; - } - } else { - aor_avp_name.n = 0; - aor_avp_type = 0; - } - - if (reg_callid_avp_param && *reg_callid_avp_param) { - s.s = reg_callid_avp_param; - s.len = strlen(s.s); - if (pv_parse_spec(&s, &avp_spec) == 0 || avp_spec.type != PVT_AVP) { - LM_ERR("malformed or non AVP %s AVP definition\n", reg_callid_avp_param); - return -1; - } - - if (pv_get_avp_name(0, &avp_spec.pvp, ®_callid_avp_name, - ®_callid_avp_type) != 0) { - LM_ERR("[%s]- invalid AVP definition\n", reg_callid_avp_param); - return -1; - } - } else { - reg_callid_avp_name.n = 0; - reg_callid_avp_type = 0; - } - - bind_usrloc = (bind_usrloc_t) find_export("ul_bind_usrloc", 1, 0); - if (!bind_usrloc) { - LM_ERR("can't bind usrloc\n"); - return -1; - } - - /* Normalize default_q parameter */ - dq = cfg_get(registrar, registrar_cfg, default_q); - if (dq != Q_UNSPECIFIED) { - if (dq > MAX_Q) { - LM_DBG("default_q = %d, lowering to MAX_Q: %d\n", dq, MAX_Q); - dq = MAX_Q; - } else if (dq < MIN_Q) { - LM_DBG("default_q = %d, raising to MIN_Q: %d\n", dq, MIN_Q); - dq = MIN_Q; - } - } - cfg_get(registrar, registrar_cfg, default_q) = dq; - - if (bind_usrloc(&ul) < 0) { - return -1; - } - - /*Register for callback of URECORD being deleted - so we can send a SAR*/ - - if (ul.register_ulcb == NULL) { - LM_ERR("Could not import ul_register_ulcb\n"); - return -1; - } - - if (ul.register_ulcb(0, 0, UL_IMPU_INSERT, ul_impu_inserted, 0) < 0) { - LM_ERR("can not register callback for insert\n"); - return -1; - } - - if (sock_hdr_name.s) { - if (sock_hdr_name.len == 0 || sock_flag == -1) { - LM_WARN("empty sock_hdr_name or sock_flag no set -> resetting\n"); - sock_hdr_name.len = 0; - sock_flag = -1; - } - } else if (sock_flag != -1) { - LM_WARN("sock_flag defined but no sock_hdr_name -> resetting flag\n"); - sock_flag = -1; - } - - /* fix the flags */ - sock_flag = (sock_flag != -1) ? (1 << sock_flag) : 0; - tcp_persistent_flag = - (tcp_persistent_flag != -1) ? (1 << tcp_persistent_flag) : 0; - - /* init the registrar notifications */ - if (!notify_init()) return -1; - - /* register the registrar notifications timer */ - //Currently we do not use this - we send notifies immediately - //if (register_timer(notification_timer, notification_list, 5) < 0) return -1; - - return 0; -} + /*register space for notification processors*/ + register_procs(notification_processes); + cfg_register_child(notification_processes); + + /* bind the SL API */ + if(sl_load_api(&slb) != 0) { + LM_ERR("cannot bind to SL API\n"); + return -1; + } + + /* load the TM API */ + if(load_tm_api(&tmb) != 0) { + LM_ERR("can't load TM API\n"); + return -1; + } + + /* load the CDP API */ + if(load_cdp_api(&cdpb) != 0) { + LM_ERR("can't load CDP API\n"); + return -1; + } + + cdp_avp = load_cdp_avp(); + if(!cdp_avp) { + LM_ERR("can't load CDP_AVP API\n"); + return -1; + } + + if(cfg_declare("registrar", registrar_cfg_def, &default_registrar_cfg, + cfg_sizeof(registrar), ®istrar_cfg)) { + LM_ERR("Fail to declare the configuration\n"); + return -1; + } + + if(rcv_avp_param && *rcv_avp_param) { + s.s = rcv_avp_param; + s.len = strlen(s.s); + if(pv_parse_spec(&s, &avp_spec) == 0 || avp_spec.type != PVT_AVP) { + LM_ERR("malformed or non AVP %s AVP definition\n", rcv_avp_param); + return -1; + } + + if(pv_get_avp_name(0, &avp_spec.pvp, &rcv_avp_name, &rcv_avp_type) + != 0) { + LM_ERR("[%s]- invalid AVP definition\n", rcv_avp_param); + return -1; + } + } else { + rcv_avp_name.n = 0; + rcv_avp_type = 0; + } + if(aor_avp_param && *aor_avp_param) { + s.s = aor_avp_param; + s.len = strlen(s.s); + if(pv_parse_spec(&s, &avp_spec) == 0 || avp_spec.type != PVT_AVP) { + LM_ERR("malformed or non AVP %s AVP definition\n", aor_avp_param); + return -1; + } + + if(pv_get_avp_name(0, &avp_spec.pvp, &aor_avp_name, &aor_avp_type) + != 0) { + LM_ERR("[%s]- invalid AVP definition\n", aor_avp_param); + return -1; + } + } else { + aor_avp_name.n = 0; + aor_avp_type = 0; + } + + if(reg_callid_avp_param && *reg_callid_avp_param) { + s.s = reg_callid_avp_param; + s.len = strlen(s.s); + if(pv_parse_spec(&s, &avp_spec) == 0 || avp_spec.type != PVT_AVP) { + LM_ERR("malformed or non AVP %s AVP definition\n", + reg_callid_avp_param); + return -1; + } + + if(pv_get_avp_name( + 0, &avp_spec.pvp, ®_callid_avp_name, ®_callid_avp_type) + != 0) { + LM_ERR("[%s]- invalid AVP definition\n", reg_callid_avp_param); + return -1; + } + } else { + reg_callid_avp_name.n = 0; + reg_callid_avp_type = 0; + } + + bind_usrloc = (bind_usrloc_t)find_export("ul_bind_usrloc", 1, 0); + if(!bind_usrloc) { + LM_ERR("can't bind usrloc\n"); + return -1; + } -static int child_init(int rank) { - int pid; - int k=0; - - LM_DBG("Initialization of module in child [%d] \n", rank); - -if (rank == PROC_MAIN) { - - /* fork notification workers */ - for(k=0;k MAX_Q) { + LM_DBG("default_q = %d, lowering to MAX_Q: %d\n", dq, MAX_Q); + dq = MAX_Q; + } else if(dq < MIN_Q) { + LM_DBG("default_q = %d, raising to MIN_Q: %d\n", dq, MIN_Q); + dq = MIN_Q; } - if (pid==0) { - if (cfg_child_init()) return 0; - notification_event_process(); - LM_CRIT("init_notification_worker():: worker_process finished without exit!\n"); - exit(-1); + } + cfg_get(registrar, registrar_cfg, default_q) = dq; + + if(bind_usrloc(&ul) < 0) { + return -1; + } + + /*Register for callback of URECORD being deleted - so we can send a SAR*/ + + if(ul.register_ulcb == NULL) { + LM_ERR("Could not import ul_register_ulcb\n"); + return -1; + } + + if(ul.register_ulcb(0, 0, UL_IMPU_INSERT, ul_impu_inserted, 0) < 0) { + LM_ERR("can not register callback for insert\n"); + return -1; + } + + if(sock_hdr_name.s) { + if(sock_hdr_name.len == 0 || sock_flag == -1) { + LM_WARN("empty sock_hdr_name or sock_flag no set -> resetting\n"); + sock_hdr_name.len = 0; + sock_flag = -1; + } + } else if(sock_flag != -1) { + LM_WARN("sock_flag defined but no sock_hdr_name -> resetting flag\n"); + sock_flag = -1; + } + + /* fix the flags */ + sock_flag = (sock_flag != -1) ? (1 << sock_flag) : 0; + tcp_persistent_flag = + (tcp_persistent_flag != -1) ? (1 << tcp_persistent_flag) : 0; + + /* init the registrar notifications */ + if(!notify_init()) + return -1; + + /* register the registrar notifications timer */ + //Currently we do not use this - we send notifies immediately + //if (register_timer(notification_timer, notification_list, 5) < 0) return -1; + + return 0; +} + +static int child_init(int rank) +{ + int pid; + int k = 0; + + LM_DBG("Initialization of module in child [%d] \n", rank); + + if(rank == PROC_MAIN) { + + /* fork notification workers */ + for(k = 0; k < notification_processes; k++) { + pid = fork_process(PROC_XWORKER, "notification_worker", 1); + if(pid == -1) { + LM_CRIT("init_notification_worker(): Error on fork() for " + "worker!\n"); + return 0; + } + if(pid == 0) { + if(cfg_child_init()) + return 0; + notification_event_process(); + LM_CRIT("init_notification_worker():: worker_process finished " + "without exit!\n"); + exit(-1); + } } } - } - - - if (rank == PROC_MAIN || rank == PROC_TCP_MAIN) - return 0; - if (rank == 1) { - /* init stats */ - //TODO if parameters are modified via cfg framework do i change them? - update_stat(max_expires_stat, default_registrar_cfg.max_expires); - update_stat(max_contacts_stat, default_registrar_cfg.max_contacts); - update_stat(default_expire_stat, default_registrar_cfg.default_expires); - } - /* don't do anything for main process and TCP manager process */ - - /* don't do anything for main process and TCP manager process */ - if (rank == PROC_MAIN || rank == PROC_TCP_MAIN) - return 0; - - /* Init the user data parser */ - if (!parser_init(scscf_user_data_dtd, scscf_user_data_xsd)) - return -1; - - - lock_get(process_lock); - if ((*callback_singleton) == 0) { - *callback_singleton = 1; - cdpb.AAAAddRequestHandler(callback_cdp_request, NULL); - } - lock_release(process_lock); - - return 0; + + + if(rank == PROC_MAIN || rank == PROC_TCP_MAIN) + return 0; + if(rank == 1) { + /* init stats */ + //TODO if parameters are modified via cfg framework do i change them? + update_stat(max_expires_stat, default_registrar_cfg.max_expires); + update_stat(max_contacts_stat, default_registrar_cfg.max_contacts); + update_stat(default_expire_stat, default_registrar_cfg.default_expires); + } + /* don't do anything for main process and TCP manager process */ + + /* don't do anything for main process and TCP manager process */ + if(rank == PROC_MAIN || rank == PROC_TCP_MAIN) + return 0; + + /* Init the user data parser */ + if(!parser_init(scscf_user_data_dtd, scscf_user_data_xsd)) + return -1; + + + lock_get(process_lock); + if((*callback_singleton) == 0) { + *callback_singleton = 1; + cdpb.AAAAddRequestHandler(callback_cdp_request, NULL); + } + lock_release(process_lock); + + return 0; } @@ -595,182 +639,200 @@ if (rank == PROC_MAIN) { * @param param - generic pointer * @returns the answer to this request */ -AAAMessage* callback_cdp_request(AAAMessage *request, void *param) { - if (is_req(request)) { - - switch (request->applicationId) { - case IMS_Cx: - //case IMS_Dx: IMS_Cx is same as IMS_Dx 16777216 - switch (request->commandCode) { - case IMS_RTR: - LM_INFO("Cx/Dx request handler():- Received an IMS_RTR \n"); - return cxdx_process_rtr(request); - break; - default: - LM_ERR("Cx/Dx request handler(): - Received unknown request for Cx/Dx command %d, flags %#1x endtoend %u hopbyhop %u\n", request->commandCode, request->flags, request->endtoendId, request->hopbyhopId); - return 0; - break; - } - break; - default: - LM_ERR("Cx/Dx request handler(): - Received unknown request for app %d command %d\n", request->applicationId, request->commandCode); - return 0; - break; - } - } - return 0; +AAAMessage *callback_cdp_request(AAAMessage *request, void *param) +{ + if(is_req(request)) { + + switch(request->applicationId) { + case IMS_Cx: + //case IMS_Dx: IMS_Cx is same as IMS_Dx 16777216 + switch(request->commandCode) { + case IMS_RTR: + LM_INFO("Cx/Dx request handler():- Received an IMS_RTR " + "\n"); + return cxdx_process_rtr(request); + break; + default: + LM_ERR("Cx/Dx request handler(): - Received unknown " + "request for Cx/Dx command %d, flags %#1x " + "endtoend %u hopbyhop %u\n", + request->commandCode, request->flags, + request->endtoendId, request->hopbyhopId); + return 0; + break; + } + break; + default: + LM_ERR("Cx/Dx request handler(): - Received unknown request " + "for app %d command %d\n", + request->applicationId, request->commandCode); + return 0; + break; + } + } + return 0; } /*! \brief * Wrapper to save(location) */ -static int w_save(struct sip_msg* _m, char* _route, char* _d, char* mode, char* _cflags) { - if(_cflags){ - return save(_m, _d, _route, ((int)(*_cflags))); - } +static int w_save( + struct sip_msg *_m, char *_route, char *_d, char *mode, char *_cflags) +{ + if(_cflags) { + return save(_m, _d, _route, ((int)(*_cflags))); + } - return save(_m, _d, _route, 0); + return save(_m, _d, _route, 0); } -static int w_assign_server_unreg(struct sip_msg* _m, char* _route, char* _d, char* _direction) { - str direction; - - direction.s = _direction; - direction.len = strlen(_direction); - return assign_server_unreg(_m, _d, &direction, _route); +static int w_assign_server_unreg( + struct sip_msg *_m, char *_route, char *_d, char *_direction) +{ + str direction; + direction.s = _direction; + direction.len = strlen(_direction); + return assign_server_unreg(_m, _d, &direction, _route); } -static int w_lookup_path_to_contact(struct sip_msg* _m, char* contact_uri) { - return lookup_path_to_contact(_m, contact_uri); +static int w_lookup_path_to_contact(struct sip_msg *_m, char *contact_uri) +{ + return lookup_path_to_contact(_m, contact_uri); } /*! \brief * Wrapper to lookup(location) */ -static int w_lookup(struct sip_msg* _m, char* _d, char* _p2) { - return lookup(_m, (udomain_t*) _d, "any"); +static int w_lookup(struct sip_msg *_m, char *_d, char *_p2) +{ + return lookup(_m, (udomain_t *)_d, "any"); } -static int w_lookup_ue_type(struct sip_msg* _m, char* _d, char* _p2) { - return lookup(_m, (udomain_t*) _d, _p2); +static int w_lookup_ue_type(struct sip_msg *_m, char *_d, char *_p2) +{ + return lookup(_m, (udomain_t *)_d, _p2); } -static int domain_fixup(void** param, int param_no) { - udomain_t* d; +static int domain_fixup(void **param, int param_no) +{ + udomain_t *d; - if (param_no == 1) { - if (ul.register_udomain((char*) *param, &d) < 0) { - LM_ERR("failed to register domain\n"); - return E_UNSPEC; - } + if(param_no == 1) { + if(ul.register_udomain((char *)*param, &d) < 0) { + LM_ERR("failed to register domain\n"); + return E_UNSPEC; + } - *param = (void*) d; - } - return 0; + *param = (void *)d; + } + return 0; } /*! \brief * Convert char* parameter to udomain_t* pointer * Convert char* parameter to pv_elem_t* pointer */ -static int unreg_fixup(void** param, int param_no) { - if (param_no == 1) { - return domain_fixup(param, 1); - } else if (param_no == 2) { - return fixup_spve_null(param, 1); - } - return 0; +static int unreg_fixup(void **param, int param_no) +{ + if(param_no == 1) { + return domain_fixup(param, 1); + } else if(param_no == 2) { + return fixup_spve_null(param, 1); + } + return 0; } /* * Convert the char* parameters */ -static int assign_save_fixup3_async(void** param, int param_no) { - - if (strlen((char*) *param) <= 0) { - LM_ERR("empty parameter %d not allowed\n", param_no); - return -1; - } - - if (param_no == 1) { //route name - static or dynamic string (config vars) - if (fixup_spve_null(param, param_no) < 0) - return -1; - return 0; - } else if (param_no == 2) { - udomain_t* d; - - if (ul.register_udomain((char*) *param, &d) < 0) { - LM_ERR("Error doing fixup on assign save"); - return -1; - } - *param = (void*) d; - } - - return 0; +static int assign_save_fixup3_async(void **param, int param_no) +{ + + if(strlen((char *)*param) <= 0) { + LM_ERR("empty parameter %d not allowed\n", param_no); + return -1; + } + + if(param_no == 1) { //route name - static or dynamic string (config vars) + if(fixup_spve_null(param, param_no) < 0) + return -1; + return 0; + } else if(param_no == 2) { + udomain_t *d; + + if(ul.register_udomain((char *)*param, &d) < 0) { + LM_ERR("Error doing fixup on assign save"); + return -1; + } + *param = (void *)d; + } + + return 0; } -static int unit_fixup(void** param, int param_no) +static int unit_fixup(void **param, int param_no) { str s; - unsigned int* num; + unsigned int *num; - if(*param){ - num = (unsigned int*)pkg_malloc(sizeof(unsigned int)); + if(*param) { + num = (unsigned int *)pkg_malloc(sizeof(unsigned int)); *num = 0; s.s = *param; s.len = strlen(s.s); - if (likely(str2int(&s, num) == 0)) { - *param = (void*)(long)num; - }else{ + if(likely(str2int(&s, num) == 0)) { + *param = (void *)(long)num; + } else { LM_ERR("failed to convert to int\n"); pkg_free(num); return E_UNSPEC; } - }else{ + } else { return E_UNSPEC; } return 0; } -static int free_uint_fixup(void** param, int param_no) +static int free_uint_fixup(void **param, int param_no) { - if(*param && param_no == 2){ + if(*param && param_no == 2) { pkg_free(*param); *param = 0; } return 0; } -static int save_fixup3(void** param, int param_no) { - if (strlen((char*) *param) <= 0) { - LM_ERR("empty parameter %d not allowed\n", param_no); - return -1; - } - - if (param_no == 1) { //route name - static or dynamic string (config vars) - if (fixup_spve_null(param, param_no) < 0) - return -1; - return 0; - } else if (param_no == 2) { - udomain_t* d; - - if (ul.register_udomain((char*) *param, &d) < 0) { - LM_ERR("Error doing fixup on save"); - return -1; - } - *param = (void*) d; - } else if (param_no == 3) { - return 0; - } else if (param_no == 4) { - return unit_fixup(param, param_no); - } - - return 0; +static int save_fixup3(void **param, int param_no) +{ + if(strlen((char *)*param) <= 0) { + LM_ERR("empty parameter %d not allowed\n", param_no); + return -1; + } + + if(param_no == 1) { //route name - static or dynamic string (config vars) + if(fixup_spve_null(param, param_no) < 0) + return -1; + return 0; + } else if(param_no == 2) { + udomain_t *d; + + if(ul.register_udomain((char *)*param, &d) < 0) { + LM_ERR("Error doing fixup on save"); + return -1; + } + *param = (void *)d; + } else if(param_no == 3) { + return 0; + } else if(param_no == 4) { + return unit_fixup(param, param_no); + } + + return 0; } /*! \brief @@ -778,86 +840,95 @@ static int save_fixup3(void** param, int param_no) { * Convert char* parameter to pv_elem_t* pointer * Convert char* parameter to str* pointer */ -static int fetchc_fixup(void** param, int param_no) { - if (param_no == 1) { - return domain_fixup(param, 1); - } else if (param_no == 2) { - return fixup_spve_null(param, 1); - } else if (param_no == 3) { - return fixup_str_null(param, 1); - } - return 0; +static int fetchc_fixup(void **param, int param_no) +{ + if(param_no == 1) { + return domain_fixup(param, 1); + } else if(param_no == 2) { + return fixup_spve_null(param, 1); + } else if(param_no == 3) { + return fixup_str_null(param, 1); + } + return 0; } -static void mod_destroy(void) { - free_p_associated_uri_buf(); - free_expired_contact_buf(); +static void mod_destroy(void) +{ + free_p_associated_uri_buf(); + free_expired_contact_buf(); } -static int add_sock_hdr(struct sip_msg* msg, char *name, char *foo) { - struct socket_info* si; - struct lump* anchor; - str *hdr_name; - str hdr; - char *p; - - hdr_name = (str*) name; - si = msg->rcv.bind_address; - - if (parse_headers(msg, HDR_EOH_F, 0) == -1) { - LM_ERR("failed to parse message\n"); - goto error; - } - - anchor = anchor_lump(msg, msg->unparsed - msg->buf, 0, 0); - if (anchor == 0) { - LM_ERR("can't get anchor\n"); - goto error; - } - - hdr.len = hdr_name->len + 2 + si->sock_str.len + CRLF_LEN; - if ((hdr.s = (char*) pkg_malloc(hdr.len)) == 0) { - LM_ERR("no more pkg mem\n"); - goto error; - } - - p = hdr.s; - memcpy(p, hdr_name->s, hdr_name->len); - p += hdr_name->len; - *(p++) = ':'; - *(p++) = ' '; - - memcpy(p, si->sock_str.s, si->sock_str.len); - p += si->sock_str.len; - - memcpy(p, CRLF, CRLF_LEN); - p += CRLF_LEN; - - if (p - hdr.s != hdr.len) { - LM_CRIT("buffer overflow (%d!=%d)\n", (int) (long) (p - hdr.s), hdr.len); - goto error1; - } - - if (insert_new_lump_before(anchor, hdr.s, hdr.len, 0) == 0) { - LM_ERR("can't insert lump\n"); - goto error1; - } - - return 1; +static int add_sock_hdr(struct sip_msg *msg, char *name, char *foo) +{ + struct socket_info *si; + struct lump *anchor; + str *hdr_name; + str hdr; + char *p; + + hdr_name = (str *)name; + si = msg->rcv.bind_address; + + if(parse_headers(msg, HDR_EOH_F, 0) == -1) { + LM_ERR("failed to parse message\n"); + goto error; + } + + anchor = anchor_lump(msg, msg->unparsed - msg->buf, 0, 0); + if(anchor == 0) { + LM_ERR("can't get anchor\n"); + goto error; + } + + hdr.len = hdr_name->len + 2 + si->sock_str.len + CRLF_LEN; + if((hdr.s = (char *)pkg_malloc(hdr.len)) == 0) { + LM_ERR("no more pkg mem\n"); + goto error; + } + + p = hdr.s; + memcpy(p, hdr_name->s, hdr_name->len); + p += hdr_name->len; + *(p++) = ':'; + *(p++) = ' '; + + memcpy(p, si->sock_str.s, si->sock_str.len); + p += si->sock_str.len; + + memcpy(p, CRLF, CRLF_LEN); + p += CRLF_LEN; + + if(p - hdr.s != hdr.len) { + LM_CRIT("buffer overflow (%d!=%d)\n", (int)(long)(p - hdr.s), hdr.len); + goto error1; + } + + if(insert_new_lump_before(anchor, hdr.s, hdr.len, 0) == 0) { + LM_ERR("can't insert lump\n"); + goto error1; + } + + return 1; error1: - pkg_free(hdr.s); + pkg_free(hdr.s); error: - return -1; + return -1; } -void default_expires_stats_update(str* gname, str* name) { - update_stat(default_expire_stat, cfg_get(registrar, registrar_cfg, default_expires)); +void default_expires_stats_update(str *gname, str *name) +{ + update_stat(default_expire_stat, + cfg_get(registrar, registrar_cfg, default_expires)); } -void max_expires_stats_update(str* gname, str* name) { - update_stat(max_expires_stat, cfg_get(registrar, registrar_cfg, max_expires)); +void max_expires_stats_update(str *gname, str *name) +{ + update_stat( + max_expires_stat, cfg_get(registrar, registrar_cfg, max_expires)); } -void default_expires_range_update(str* gname, str* name) { - update_stat(default_expire_range_stat, cfg_get(registrar, registrar_cfg, default_expires_range)); +void default_expires_range_update(str *gname, str *name) +{ + update_stat(default_expire_range_stat, + cfg_get(registrar, registrar_cfg, default_expires_range)); } diff --git a/src/modules/ims_registrar_scscf/ims_registrar_scscf_mod.h b/src/modules/ims_registrar_scscf/ims_registrar_scscf_mod.h index 2d3e39956b4..ff5f5e06a43 100644 --- a/src/modules/ims_registrar_scscf/ims_registrar_scscf_mod.h +++ b/src/modules/ims_registrar_scscf/ims_registrar_scscf_mod.h @@ -58,26 +58,26 @@ /* if DB support is used, this values must not exceed the * storage capacity of the DB columns! See db/schema/entities.xml */ -#define CONTACT_MAX_SIZE 255 -#define RECEIVED_MAX_SIZE 255 -#define USERNAME_MAX_SIZE 64 -#define DOMAIN_MAX_SIZE 128 -#define CALLID_MAX_SIZE 255 +#define CONTACT_MAX_SIZE 255 +#define RECEIVED_MAX_SIZE 255 +#define USERNAME_MAX_SIZE 64 +#define DOMAIN_MAX_SIZE 128 +#define CALLID_MAX_SIZE 255 -#define PATH_MODE_STRICT 2 -#define PATH_MODE_LAZY 1 -#define PATH_MODE_OFF 0 +#define PATH_MODE_STRICT 2 +#define PATH_MODE_LAZY 1 +#define PATH_MODE_OFF 0 -#define REG_SAVE_MEM_FL (1<<0) -#define REG_SAVE_NORPL_FL (1<<1) -#define REG_SAVE_REPL_FL (1<<2) -#define REG_SAVE_ALL_FL ((1<<3)-1) +#define REG_SAVE_MEM_FL (1 << 0) +#define REG_SAVE_NORPL_FL (1 << 1) +#define REG_SAVE_REPL_FL (1 << 2) +#define REG_SAVE_ALL_FL ((1 << 3) - 1) #define MOD_NAME "ims_registrar_scscf" /** Return and break the execution of routng script */ -#define CSCF_RETURN_BREAK 0 +#define CSCF_RETURN_BREAK 0 /** Return true in the routing script */ -#define CSCF_RETURN_TRUE 1 +#define CSCF_RETURN_TRUE 1 /** Return false in the routing script */ #define CSCF_RETURN_FALSE -1 /** Return error in the routing script */ @@ -105,7 +105,7 @@ extern int path_use_params; extern str sock_hdr_name; extern int sock_flag; -extern usrloc_api_t ul;/*!< Structure containing pointers to usrloc functions*/ +extern usrloc_api_t ul; /*!< Structure containing pointers to usrloc functions*/ extern sl_api_t slb; diff --git a/src/modules/ims_registrar_scscf/lookup.c b/src/modules/ims_registrar_scscf/lookup.c index 640dbb97071..836ce9ca11b 100644 --- a/src/modules/ims_registrar_scscf/lookup.c +++ b/src/modules/ims_registrar_scscf/lookup.c @@ -50,7 +50,7 @@ #include "pvt_message.h" #define allowed_method(_msg, _c) \ - ( !method_filtering || ((_msg)->REQ_METHOD)&((_c)->methods) ) + (!method_filtering || ((_msg)->REQ_METHOD) & ((_c)->methods)) /*! \brief * Lookup contact in the database and rewrite Request-URI @@ -59,50 +59,51 @@ * -2 : found but method not allowed * -3 : error */ -int lookup(struct sip_msg* _m, udomain_t* _d, char* ue_type_c) { - impurecord_t* r; - str aor, tmp_aor; - ucontact_t* ptr = 0; - int res; - int ret; - str path_dst; - flag_t old_bflags; - int ue_type; /*0=any, 1=3gpp, 2=sip */ +int lookup(struct sip_msg *_m, udomain_t *_d, char *ue_type_c) +{ + impurecord_t *r; + str aor, tmp_aor; + ucontact_t *ptr = 0; + int res; + int ret; + str path_dst; + flag_t old_bflags; + int ue_type; /*0=any, 1=3gpp, 2=sip */ impu_contact_t *impucontact; - if (!_m) { - LM_ERR("NULL message!!!\n"); - return -1; - } - - switch (ue_type_c[0]) { - case '3': - LM_DBG("looking for 3gpp terminals\n"); - ue_type = 1; - break; - case 's': - case 'S': - LM_DBG("looking for sip terminals\n"); - ue_type = 2; - break; - default: - LM_DBG("looking for any type of terminal\n"); - ue_type=0; - } - - if (parse_sip_msg_uri(_m) < 0) { + if(!_m) { + LM_ERR("NULL message!!!\n"); + return -1; + } + + switch(ue_type_c[0]) { + case '3': + LM_DBG("looking for 3gpp terminals\n"); + ue_type = 1; + break; + case 's': + case 'S': + LM_DBG("looking for sip terminals\n"); + ue_type = 2; + break; + default: + LM_DBG("looking for any type of terminal\n"); + ue_type = 0; + } + + if(parse_sip_msg_uri(_m) < 0) { LM_ERR("Error while parsing the Request-URI\n"); return -1; } - if (_m->new_uri.s) { + if(_m->new_uri.s) { tmp_aor = _m->new_uri; } else { tmp_aor = _m->first_line.u.request.uri; } aor.s = pkg_malloc(tmp_aor.len); - if (aor.s == NULL) { + if(aor.s == NULL) { LM_ERR("memory allocation failure\n"); return -1; } @@ -120,193 +121,204 @@ int lookup(struct sip_msg* _m, udomain_t* _d, char* ue_type_c) { memcpy(aor.s + aor.len, _m->parsed_uri.host.s, _m->parsed_uri.host.len); aor.len += _m->parsed_uri.host.len; - LM_DBG("Looking for <%.*s>\n", aor.len, aor.s); + LM_DBG("Looking for <%.*s>\n", aor.len, aor.s); - get_act_time(); + get_act_time(); - ul.lock_udomain(_d, &aor); - res = ul.get_impurecord(_d, &aor, &r); - if (res != 0) { - LM_DBG("'%.*s' Not found in usrloc\n", aor.len, ZSW(aor.s)); - pkg_free(aor.s); - ul.unlock_udomain(_d, &aor); - return -1; - } - ret = -1; + ul.lock_udomain(_d, &aor); + res = ul.get_impurecord(_d, &aor, &r); + if(res != 0) { + LM_DBG("'%.*s' Not found in usrloc\n", aor.len, ZSW(aor.s)); + pkg_free(aor.s); + ul.unlock_udomain(_d, &aor); + return -1; + } + ret = -1; impucontact = r->linked_contacts.head; - while (impucontact && (ptr = impucontact->contact)) { - if (VALID_UE_TYPE(ptr, ue_type) && VALID_CONTACT(ptr, act_time) && allowed_method(_m, ptr)) { - LM_DBG("Found a valid contact [%.*s]\n", ptr->c.len, ptr->c.s); - break; - } + while(impucontact && (ptr = impucontact->contact)) { + if(VALID_UE_TYPE(ptr, ue_type) && VALID_CONTACT(ptr, act_time) + && allowed_method(_m, ptr)) { + LM_DBG("Found a valid contact [%.*s]\n", ptr->c.len, ptr->c.s); + break; + } impucontact = impucontact->next; - } - - /* look first for an un-expired and supported contact */ - if (ptr == 0) { - LM_INFO("No contacts founds for IMPU <%.*s>\n", aor.len, aor.s); - /* nothing found */ - goto done; - } - - ret = 1; - if (ptr) { - if (rewrite_uri(_m, &ptr->c) < 0) { - LM_ERR("unable to rewrite Request-URI\n"); - ret = -3; - goto done; - } - - /* reset next hop address */ - reset_dst_uri(_m); - - /* If a Path is present, use first path-uri in favour of + } + + /* look first for an un-expired and supported contact */ + if(ptr == 0) { + LM_INFO("No contacts founds for IMPU <%.*s>\n", aor.len, aor.s); + /* nothing found */ + goto done; + } + + ret = 1; + if(ptr) { + if(rewrite_uri(_m, &ptr->c) < 0) { + LM_ERR("unable to rewrite Request-URI\n"); + ret = -3; + goto done; + } + + /* reset next hop address */ + reset_dst_uri(_m); + + /* If a Path is present, use first path-uri in favour of * received-uri because in that case the last hop towards the uac * has to handle NAT. - agranig */ - if (ptr->path.s && ptr->path.len) { - if (get_path_dst_uri(&ptr->path, &path_dst) < 0) { - LM_ERR("failed to get dst_uri for Path\n"); - ret = -3; - goto done; - } - if (set_path_vector(_m, &ptr->path) < 0) { - LM_ERR("failed to set path vector\n"); - ret = -1; - goto done; - } - if (set_dst_uri(_m, &path_dst) < 0) { - LM_ERR("failed to set dst_uri of Path\n"); - ret = -3; - goto done; - } - } else if (ptr->received.s && ptr->received.len) { - if (set_dst_uri(_m, &ptr->received) < 0) { - ret = -3; - goto done; - } - } - - set_ruri_q(ptr->q); - - old_bflags = 0; - getbflagsval(0, &old_bflags); - setbflagsval(0, old_bflags | ptr->cflags); - - if (ptr->sock) - set_force_socket(_m, ptr->sock); - - ptr = ptr->next; - } - - /* Append branches if enabled */ - if (!cfg_get(registrar, registrar_cfg, append_branches)) goto done; - - //the last i was the first valid contact we found - let's go through the rest of valid contacts and append the branches. - if (impucontact) impucontact = impucontact->next; - while (impucontact) { + if(ptr->path.s && ptr->path.len) { + if(get_path_dst_uri(&ptr->path, &path_dst) < 0) { + LM_ERR("failed to get dst_uri for Path\n"); + ret = -3; + goto done; + } + if(set_path_vector(_m, &ptr->path) < 0) { + LM_ERR("failed to set path vector\n"); + ret = -1; + goto done; + } + if(set_dst_uri(_m, &path_dst) < 0) { + LM_ERR("failed to set dst_uri of Path\n"); + ret = -3; + goto done; + } + } else if(ptr->received.s && ptr->received.len) { + if(set_dst_uri(_m, &ptr->received) < 0) { + ret = -3; + goto done; + } + } + + set_ruri_q(ptr->q); + + old_bflags = 0; + getbflagsval(0, &old_bflags); + setbflagsval(0, old_bflags | ptr->cflags); + + if(ptr->sock) + set_force_socket(_m, ptr->sock); + + ptr = ptr->next; + } + + /* Append branches if enabled */ + if(!cfg_get(registrar, registrar_cfg, append_branches)) + goto done; + + //the last i was the first valid contact we found - let's go through the rest of valid contacts and append the branches. + if(impucontact) + impucontact = impucontact->next; + while(impucontact) { ptr = impucontact->contact; - if (VALID_UE_TYPE(ptr, ue_type) && VALID_CONTACT(ptr, act_time) && allowed_method(_m, ptr)) { - path_dst.len = 0; - if (ptr->path.s && ptr->path.len - && get_path_dst_uri(&ptr->path, &path_dst) < 0) { - LM_ERR("failed to get dst_uri for Path\n"); - continue; - } - - /* The same as for the first contact applies for branches + if(VALID_UE_TYPE(ptr, ue_type) && VALID_CONTACT(ptr, act_time) + && allowed_method(_m, ptr)) { + path_dst.len = 0; + if(ptr->path.s && ptr->path.len + && get_path_dst_uri(&ptr->path, &path_dst) < 0) { + LM_ERR("failed to get dst_uri for Path\n"); + continue; + } + + /* The same as for the first contact applies for branches * regarding path vs. received. */ - if (km_append_branch(_m, &ptr->c, path_dst.len ? &path_dst : &ptr->received, - &ptr->path, ptr->q, ptr->cflags, ptr->sock) == -1) { - LM_ERR("failed to append a branch\n"); - /* Also give a chance to the next branches*/ - continue; - } - } - impucontact = impucontact->next; - } + if(km_append_branch(_m, &ptr->c, + path_dst.len ? &path_dst : &ptr->received, &ptr->path, + ptr->q, ptr->cflags, ptr->sock) + == -1) { + LM_ERR("failed to append a branch\n"); + /* Also give a chance to the next branches*/ + continue; + } + } + impucontact = impucontact->next; + } done: - pkg_free(aor.s); - ul.unlock_udomain(_d, &aor); - return ret; + pkg_free(aor.s); + ul.unlock_udomain(_d, &aor); + return ret; } -int lookup_path_to_contact(struct sip_msg* _m, char* contact_uri) { - ucontact_t* contact; - str s_contact_uri; - str path_dst; - - get_act_time(); - if (get_str_fparam(&s_contact_uri, _m, (fparam_t*) contact_uri) < 0) { - LM_ERR("failed to get RURI\n"); - return -1; - } - LM_DBG("Looking up contact [%.*s]\n", s_contact_uri.len, s_contact_uri.s); - - if (ul.get_ucontact(&s_contact_uri, 0, 0, 0, &contact) == 0) { //get_contact returns with lock - - if (!VALID_CONTACT(contact, act_time)) { - LM_DBG("Contact is not valid...ignoring\n"); - ul.release_ucontact(contact); - } else { - LM_DBG("CONTACT FOUND and path is [%.*s]\n", contact->path.len, contact->path.s); - - if (get_path_dst_uri(&contact->path, &path_dst) < 0) { - LM_ERR("failed to get dst_uri for Path\n"); - ul.release_ucontact(contact); - return -1; - } - if (set_path_vector(_m, &contact->path) < 0) { - LM_ERR("failed to set path vector\n"); - ul.release_ucontact(contact); - return -1; - } - if (set_dst_uri(_m, &path_dst) < 0) { - LM_ERR("failed to set dst_uri of Path\n"); - ul.release_ucontact(contact); - return -1; - } - - ul.release_ucontact(contact); - return 1; - } - } - LM_DBG("no contact found for [%.*s]\n", s_contact_uri.len, s_contact_uri.s); - return -1; +int lookup_path_to_contact(struct sip_msg *_m, char *contact_uri) +{ + ucontact_t *contact; + str s_contact_uri; + str path_dst; + + get_act_time(); + if(get_str_fparam(&s_contact_uri, _m, (fparam_t *)contact_uri) < 0) { + LM_ERR("failed to get RURI\n"); + return -1; + } + LM_DBG("Looking up contact [%.*s]\n", s_contact_uri.len, s_contact_uri.s); + + if(ul.get_ucontact(&s_contact_uri, 0, 0, 0, &contact) + == 0) { //get_contact returns with lock + + if(!VALID_CONTACT(contact, act_time)) { + LM_DBG("Contact is not valid...ignoring\n"); + ul.release_ucontact(contact); + } else { + LM_DBG("CONTACT FOUND and path is [%.*s]\n", contact->path.len, + contact->path.s); + + if(get_path_dst_uri(&contact->path, &path_dst) < 0) { + LM_ERR("failed to get dst_uri for Path\n"); + ul.release_ucontact(contact); + return -1; + } + if(set_path_vector(_m, &contact->path) < 0) { + LM_ERR("failed to set path vector\n"); + ul.release_ucontact(contact); + return -1; + } + if(set_dst_uri(_m, &path_dst) < 0) { + LM_ERR("failed to set dst_uri of Path\n"); + ul.release_ucontact(contact); + return -1; + } + + ul.release_ucontact(contact); + return 1; + } + } + LM_DBG("no contact found for [%.*s]\n", s_contact_uri.len, s_contact_uri.s); + return -1; } /*! \brief the impu_registered() function * Return true if the AOR in the To Header is registered */ -int impu_registered(struct sip_msg* _m, char* _t, char* _s) { - impurecord_t* r; - int res, ret = -1; - - str impu; - impu = cscf_get_public_identity(_m); - - LM_DBG("Looking for IMPU <%.*s>\n", impu.len, impu.s); - - ul.lock_udomain((udomain_t*) _t, &impu); - res = ul.get_impurecord((udomain_t*) _t, &impu, &r); - - if (res < 0) { - ul.unlock_udomain((udomain_t*) _t, &impu); - LM_ERR("failed to query usrloc for IMPU <%.*s>\n", impu.len, impu.s); - return ret; - } - - if (res == 0) { - if (r->reg_state == IMPU_REGISTERED) ret = 1; - ul.unlock_udomain((udomain_t*) _t, &impu); - LM_DBG("'%.*s' found in usrloc\n", impu.len, ZSW(impu.s)); - return ret; - } - - ul.unlock_udomain((udomain_t*) _t, &impu); - LM_DBG("'%.*s' not found in usrloc\n", impu.len, ZSW(impu.s)); - return ret; +int impu_registered(struct sip_msg *_m, char *_t, char *_s) +{ + impurecord_t *r; + int res, ret = -1; + + str impu; + impu = cscf_get_public_identity(_m); + + LM_DBG("Looking for IMPU <%.*s>\n", impu.len, impu.s); + + ul.lock_udomain((udomain_t *)_t, &impu); + res = ul.get_impurecord((udomain_t *)_t, &impu, &r); + + if(res < 0) { + ul.unlock_udomain((udomain_t *)_t, &impu); + LM_ERR("failed to query usrloc for IMPU <%.*s>\n", impu.len, impu.s); + return ret; + } + + if(res == 0) { + if(r->reg_state == IMPU_REGISTERED) + ret = 1; + ul.unlock_udomain((udomain_t *)_t, &impu); + LM_DBG("'%.*s' found in usrloc\n", impu.len, ZSW(impu.s)); + return ret; + } + + ul.unlock_udomain((udomain_t *)_t, &impu); + LM_DBG("'%.*s' not found in usrloc\n", impu.len, ZSW(impu.s)); + return ret; } /** @@ -316,103 +328,110 @@ int impu_registered(struct sip_msg* _m, char* _t, char* _s) { * @param _s - s * @return true if there is at least one valid contact. false if not */ -int term_impu_has_contact(struct sip_msg* _m, udomain_t* _d, char* _s) { - impurecord_t* r; - str aor, uri; - ucontact_t* ptr = 0; - int res; - int ret; +int term_impu_has_contact(struct sip_msg *_m, udomain_t *_d, char *_s) +{ + impurecord_t *r; + str aor, uri; + ucontact_t *ptr = 0; + int res; + int ret; impu_contact_t *impucontact; - if (_m->new_uri.s) uri = _m->new_uri; - else uri = _m->first_line.u.request.uri; + if(_m->new_uri.s) + uri = _m->new_uri; + else + uri = _m->first_line.u.request.uri; - if (extract_aor(&uri, &aor) < 0) { - LM_ERR("failed to extract address of record\n"); - return -3; - } + if(extract_aor(&uri, &aor) < 0) { + LM_ERR("failed to extract address of record\n"); + return -3; + } - get_act_time(); + get_act_time(); - ul.lock_udomain(_d, &aor); - res = ul.get_impurecord(_d, &aor, &r); - if (res != 0) { - LM_DBG("'%.*s' Not found in usrloc\n", aor.len, ZSW(aor.s)); - ul.unlock_udomain(_d, &aor); - return -1; - } + ul.lock_udomain(_d, &aor); + res = ul.get_impurecord(_d, &aor, &r); + if(res != 0) { + LM_DBG("'%.*s' Not found in usrloc\n", aor.len, ZSW(aor.s)); + ul.unlock_udomain(_d, &aor); + return -1; + } - impucontact = r->linked_contacts.head; - while (impucontact) { + impucontact = r->linked_contacts.head; + while(impucontact) { ptr = impucontact->contact; - if (VALID_CONTACT(ptr, act_time) && allowed_method(_m, ptr)) { - LM_DBG("Found a valid contact [%.*s]\n", ptr->c.len, ptr->c.s); - ret = 1; - break; - } + if(VALID_CONTACT(ptr, act_time) && allowed_method(_m, ptr)) { + LM_DBG("Found a valid contact [%.*s]\n", ptr->c.len, ptr->c.s); + ret = 1; + break; + } impucontact = impucontact->next; - } + } - /* look first for an un-expired and supported contact */ - if (ptr == 0) { - /* nothing found */ - ret = -1; - } + /* look first for an un-expired and supported contact */ + if(ptr == 0) { + /* nothing found */ + ret = -1; + } - ul.unlock_udomain(_d, &aor); + ul.unlock_udomain(_d, &aor); - return ret; + return ret; } /*! \brief the term_impu_registered() function * Return true if the AOR in the Request-URI for the terminating user is registered */ -int term_impu_registered(struct sip_msg* _m, char* _t, char* _s) { - struct sip_msg *req; - int i; - str uri; - impurecord_t* r; - int res; - - // if (_m->new_uri.s) uri = _m->new_uri; - // else uri = _m->first_line.u.request.uri; - // - // if (extract_aor(&uri, &aor) < 0) { - // LM_ERR("failed to extract address of record\n"); - // return -1; - // } - - req = _m; - if (!req) { - LM_ERR(":term_impu_registered: NULL message!!!\n"); - return -1; - } - if (req->first_line.type != SIP_REQUEST) { - req = get_request_from_tx(0); - } - - if (_m->new_uri.s) uri = _m->new_uri; - else uri = _m->first_line.u.request.uri; - - for (i = 0; i < uri.len; i++) - if (uri.s[i] == ';' || uri.s[i] == '?' || (i > 3 /*sip:*/ && uri.s[i] == ':' /*strip port*/)) { - uri.len = i; - break; - } - LM_DBG("term_impu_registered: Looking for <%.*s>\n", uri.len, uri.s); - - ul.lock_udomain((udomain_t*) _t, &uri); - res = ul.get_impurecord((udomain_t*) _t, &uri, &r); - - if (res != 0) { - ul.unlock_udomain((udomain_t*) _t, &uri); - LM_DBG("failed to query for terminating IMPU or not found <%.*s>\n", uri.len, uri.s); - return -1; - } - - ul.unlock_udomain((udomain_t*) _t, &uri); - LM_DBG("'%.*s' found in usrloc\n", uri.len, ZSW(uri.s)); - return 1; +int term_impu_registered(struct sip_msg *_m, char *_t, char *_s) +{ + struct sip_msg *req; + int i; + str uri; + impurecord_t *r; + int res; + + // if (_m->new_uri.s) uri = _m->new_uri; + // else uri = _m->first_line.u.request.uri; + // + // if (extract_aor(&uri, &aor) < 0) { + // LM_ERR("failed to extract address of record\n"); + // return -1; + // } + + req = _m; + if(!req) { + LM_ERR(":term_impu_registered: NULL message!!!\n"); + return -1; + } + if(req->first_line.type != SIP_REQUEST) { + req = get_request_from_tx(0); + } + + if(_m->new_uri.s) + uri = _m->new_uri; + else + uri = _m->first_line.u.request.uri; + + for(i = 0; i < uri.len; i++) + if(uri.s[i] == ';' || uri.s[i] == '?' + || (i > 3 /*sip:*/ && uri.s[i] == ':' /*strip port*/)) { + uri.len = i; + break; + } + LM_DBG("term_impu_registered: Looking for <%.*s>\n", uri.len, uri.s); + + ul.lock_udomain((udomain_t *)_t, &uri); + res = ul.get_impurecord((udomain_t *)_t, &uri, &r); + + if(res != 0) { + ul.unlock_udomain((udomain_t *)_t, &uri); + LM_DBG("failed to query for terminating IMPU or not found <%.*s>\n", + uri.len, uri.s); + return -1; + } + ul.unlock_udomain((udomain_t *)_t, &uri); + LM_DBG("'%.*s' found in usrloc\n", uri.len, ZSW(uri.s)); + return 1; } diff --git a/src/modules/ims_registrar_scscf/lookup.h b/src/modules/ims_registrar_scscf/lookup.h index 913e9d31d0f..ea50e26edd2 100644 --- a/src/modules/ims_registrar_scscf/lookup.h +++ b/src/modules/ims_registrar_scscf/lookup.h @@ -26,7 +26,7 @@ * \file * \brief SIP registrar module - lookup contacts in usrloc * \ingroup registrar - */ + */ #ifndef LOOKUP_H @@ -39,17 +39,17 @@ /*! \brief * Lookup a contact in usrloc and rewrite R-URI if found */ -int lookup(struct sip_msg* _m, udomain_t* _d, char * ue_type); -int lookup_path_to_contact(struct sip_msg* _m, char* contact_uri); +int lookup(struct sip_msg *_m, udomain_t *_d, char *ue_type); +int lookup_path_to_contact(struct sip_msg *_m, char *contact_uri); /*! \brief * Return true if the AOR in the Request-URI is registered, * it is similar to lookup but registered neither rewrites * the Request-URI nor appends branches */ -int impu_registered(struct sip_msg* _m, char* _t, char* _s); -int term_impu_registered(struct sip_msg* _m, char* _t, char* _s); -int term_impu_has_contact(struct sip_msg* _m, udomain_t* _d, char* _s); +int impu_registered(struct sip_msg *_m, char *_t, char *_s); +int term_impu_registered(struct sip_msg *_m, char *_t, char *_s); +int term_impu_has_contact(struct sip_msg *_m, udomain_t *_d, char *_s); #endif /* LOOKUP_H */ diff --git a/src/modules/ims_registrar_scscf/path.c b/src/modules/ims_registrar_scscf/path.c index 90692a8fecd..fe711e9a02b 100644 --- a/src/modules/ims_registrar_scscf/path.c +++ b/src/modules/ims_registrar_scscf/path.c @@ -26,7 +26,7 @@ * \file * \brief SIP registrar module - Helper functions for Path support * \ingroup registrar - */ + */ #include "../../core/data_lump.h" @@ -57,44 +57,46 @@ int build_path_vector(struct sip_msg *_m, str *path, str *received) goto error; } - for( hdr=_m->path,p=buf ; hdr ; hdr = next_sibling_hdr(hdr)) { + for(hdr = _m->path, p = buf; hdr; hdr = next_sibling_hdr(hdr)) { /* check for max. Path length */ - if( p-buf+hdr->body.len+1 >= MAX_PATH_BUFFER) { - LM_ERR("Overall Path body exceeds max. length of %d - trying to add header [%.*s] and already have [%.*s]\n", - MAX_PATH_BUFFER, - hdr->body.len, hdr->body.s, - (int)(p-buf), buf); + if(p - buf + hdr->body.len + 1 >= MAX_PATH_BUFFER) { + LM_ERR("Overall Path body exceeds max. length of %d - trying to " + "add header [%.*s] and already have [%.*s]\n", + MAX_PATH_BUFFER, hdr->body.len, hdr->body.s, (int)(p - buf), + buf); goto error; } - if(p!=buf) + if(p != buf) *(p++) = ','; - memcpy( p, hdr->body.s, hdr->body.len); - p += hdr->body.len; + memcpy(p, hdr->body.s, hdr->body.len); + p += hdr->body.len; } - if (p!=buf) { + if(p != buf) { /* check if next hop is a loose router */ - if (parse_rr_body( buf, p-buf, &route) < 0) { + if(parse_rr_body(buf, p - buf, &route) < 0) { LM_ERR("failed to parse Path body, no head found\n"); goto error; } - if (parse_uri(route->nameaddr.uri.s,route->nameaddr.uri.len,&puri)<0){ + if(parse_uri(route->nameaddr.uri.s, route->nameaddr.uri.len, &puri) + < 0) { LM_ERR("failed to parse the first Path URI\n"); goto error; } - if (!puri.lr.s) { + if(!puri.lr.s) { LM_ERR("first Path URI is not a loose-router, not supported\n"); goto error; } - if (path_use_params) { + if(path_use_params) { param_hooks_t hooks; param_t *params; - if (parse_params(&(puri.params),CLASS_CONTACT,&hooks,¶ms)!=0){ + if(parse_params(&(puri.params), CLASS_CONTACT, &hooks, ¶ms) + != 0) { LM_ERR("failed to parse parameters of first hop\n"); goto error; } - if (hooks.contact.received) + if(hooks.contact.received) *received = hooks.contact.received->body; /*for (;params; params = params->next) { if (params->type == P_RECEIVED) { @@ -108,10 +110,10 @@ int build_path_vector(struct sip_msg *_m, str *path, str *received) } path->s = buf; - path->len = p-buf; + path->len = p - buf; return 0; error: - if(route) free_rr(&route); + if(route) + free_rr(&route); return -1; } - diff --git a/src/modules/ims_registrar_scscf/path.h b/src/modules/ims_registrar_scscf/path.h index e4e1670552f..05e56e7016a 100644 --- a/src/modules/ims_registrar_scscf/path.h +++ b/src/modules/ims_registrar_scscf/path.h @@ -26,7 +26,7 @@ * \file * \brief SIP registrar module - helper functions for Path support * \ingroup registrar - */ + */ #ifndef REG_PATH_H #define REG_PATH_H diff --git a/src/modules/ims_registrar_scscf/pvt_message.c b/src/modules/ims_registrar_scscf/pvt_message.c index 388af23fb13..e402007f942 100644 --- a/src/modules/ims_registrar_scscf/pvt_message.c +++ b/src/modules/ims_registrar_scscf/pvt_message.c @@ -49,84 +49,88 @@ extern struct tm_binds tmb; extern struct _pv_req_data _pv_treq; -void pv_tmx_data_init(void) { - memset(&_pv_treq, 0, sizeof (struct _pv_req_data)); +void pv_tmx_data_init(void) +{ + memset(&_pv_treq, 0, sizeof(struct _pv_req_data)); } -int pv_t_copy_msg(struct sip_msg *src, struct sip_msg *dst) { - dst->id = src->id; - dst->rcv = src->rcv; - dst->set_global_address = src->set_global_address; - dst->set_global_port = src->set_global_port; - dst->flags = src->flags; - dst->fwd_send_flags = src->fwd_send_flags; - dst->rpl_send_flags = src->rpl_send_flags; - dst->force_send_socket = src->force_send_socket; +int pv_t_copy_msg(struct sip_msg *src, struct sip_msg *dst) +{ + dst->id = src->id; + dst->rcv = src->rcv; + dst->set_global_address = src->set_global_address; + dst->set_global_port = src->set_global_port; + dst->flags = src->flags; + dst->fwd_send_flags = src->fwd_send_flags; + dst->rpl_send_flags = src->rpl_send_flags; + dst->force_send_socket = src->force_send_socket; - if (parse_msg(dst->buf, dst->len, dst) != 0) { - LM_ERR("parse msg failed\n"); - return -1; - } - return 0; + if(parse_msg(dst->buf, dst->len, dst) != 0) { + LM_ERR("parse msg failed\n"); + return -1; + } + return 0; } -struct sip_msg* get_request_from_tx(struct cell *t) { - if (t == NULL) { - t = tmb.t_gett(); - } - if (!t || t == (void*) - 1) { - LM_ERR("Reply without transaction\n"); - return 0; - } - if (t) { +struct sip_msg *get_request_from_tx(struct cell *t) +{ + if(t == NULL) { + t = tmb.t_gett(); + } + if(!t || t == (void *)-1) { + LM_ERR("Reply without transaction\n"); + return 0; + } + if(t) { - /* we may need the request message from here on.. if there are headers we need that were not parsed in the original request + /* we may need the request message from here on.. if there are headers we need that were not parsed in the original request (which we cannot assume) then we would pollute the shm_msg t->uas.request if we did any parsing on it. Instead, we need to make a private copy of the message and free it when we are done */ - if (_pv_treq.label != t->label || _pv_treq.index != t->hash_index) { - /* make a copy */ - if (_pv_treq.buf == NULL || _pv_treq.buf_size < t->uas.request->len + 1) { - if (_pv_treq.buf != NULL) - pkg_free(_pv_treq.buf); - if (_pv_treq.tmsgp) - free_sip_msg(&_pv_treq.msg); - _pv_treq.tmsgp = NULL; - _pv_treq.index = 0; - _pv_treq.label = 0; - _pv_treq.buf_size = t->uas.request->len + 1; - _pv_treq.buf = (char*) pkg_malloc(_pv_treq.buf_size * sizeof (char)); - if (_pv_treq.buf == NULL) { - LM_ERR("no more pkg\n"); - _pv_treq.buf_size = 0; - return 0; - } - } - if (_pv_treq.tmsgp) - free_sip_msg(&_pv_treq.msg); - memset(&_pv_treq.msg, 0, sizeof (struct sip_msg)); - memcpy(_pv_treq.buf, t->uas.request->buf, t->uas.request->len); - _pv_treq.buf[t->uas.request->len] = '\0'; - _pv_treq.msg.len = t->uas.request->len; - _pv_treq.msg.buf = _pv_treq.buf; - _pv_treq.tmsgp = t->uas.request; - _pv_treq.index = t->hash_index; - _pv_treq.label = t->label; + if(_pv_treq.label != t->label || _pv_treq.index != t->hash_index) { + /* make a copy */ + if(_pv_treq.buf == NULL + || _pv_treq.buf_size < t->uas.request->len + 1) { + if(_pv_treq.buf != NULL) + pkg_free(_pv_treq.buf); + if(_pv_treq.tmsgp) + free_sip_msg(&_pv_treq.msg); + _pv_treq.tmsgp = NULL; + _pv_treq.index = 0; + _pv_treq.label = 0; + _pv_treq.buf_size = t->uas.request->len + 1; + _pv_treq.buf = + (char *)pkg_malloc(_pv_treq.buf_size * sizeof(char)); + if(_pv_treq.buf == NULL) { + LM_ERR("no more pkg\n"); + _pv_treq.buf_size = 0; + return 0; + } + } + if(_pv_treq.tmsgp) + free_sip_msg(&_pv_treq.msg); + memset(&_pv_treq.msg, 0, sizeof(struct sip_msg)); + memcpy(_pv_treq.buf, t->uas.request->buf, t->uas.request->len); + _pv_treq.buf[t->uas.request->len] = '\0'; + _pv_treq.msg.len = t->uas.request->len; + _pv_treq.msg.buf = _pv_treq.buf; + _pv_treq.tmsgp = t->uas.request; + _pv_treq.index = t->hash_index; + _pv_treq.label = t->label; - if (pv_t_copy_msg(t->uas.request, &_pv_treq.msg) != 0) { - pkg_free(_pv_treq.buf); - _pv_treq.buf_size = 0; - _pv_treq.buf = NULL; - _pv_treq.tmsgp = NULL; - _pv_treq.index = 0; - _pv_treq.label = 0; - return 0; - } - } - - return &_pv_treq.msg; - } else - return 0; + if(pv_t_copy_msg(t->uas.request, &_pv_treq.msg) != 0) { + pkg_free(_pv_treq.buf); + _pv_treq.buf_size = 0; + _pv_treq.buf = NULL; + _pv_treq.tmsgp = NULL; + _pv_treq.index = 0; + _pv_treq.label = 0; + return 0; + } + } + return &_pv_treq.msg; + } else + return 0; } diff --git a/src/modules/ims_registrar_scscf/pvt_message.h b/src/modules/ims_registrar_scscf/pvt_message.h index ebe6092d4af..5e3288286fe 100644 --- a/src/modules/ims_registrar_scscf/pvt_message.h +++ b/src/modules/ims_registrar_scscf/pvt_message.h @@ -41,7 +41,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * - */ + */ #ifndef PVT_MESSAGE_H @@ -51,19 +51,20 @@ #include "../../core/parser/msg_parser.h" #include "../tm/tm_load.h" -struct _pv_req_data { - struct sip_msg msg; - struct sip_msg *tmsgp; - unsigned int index; - unsigned int label; - char *buf; - int buf_size; +struct _pv_req_data +{ + struct sip_msg msg; + struct sip_msg *tmsgp; + unsigned int index; + unsigned int label; + char *buf; + int buf_size; }; void pv_tmx_data_init(void); int pv_t_copy_msg(struct sip_msg *src, struct sip_msg *dst); -struct sip_msg* get_request_from_tx(struct cell* t); +struct sip_msg *get_request_from_tx(struct cell *t); #endif /* PVT_MESSAGE_H */ diff --git a/src/modules/ims_registrar_scscf/reg_rpc.c b/src/modules/ims_registrar_scscf/reg_rpc.c index 5e5f6683212..cd07989c59c 100644 --- a/src/modules/ims_registrar_scscf/reg_rpc.c +++ b/src/modules/ims_registrar_scscf/reg_rpc.c @@ -26,59 +26,60 @@ #include "registrar_notify.h" -static const char* reg_rpc_dereg_impu_doc[2] = {"De-register IMPU from S-CSCF", 0}; +static const char *reg_rpc_dereg_impu_doc[2] = { + "De-register IMPU from S-CSCF", 0}; extern usrloc_api_t ul; -static void reg_rpc_dereg_impu(rpc_t* rpc, void* ctx) +static void reg_rpc_dereg_impu(rpc_t *rpc, void *ctx) { - str impu; - int res; - udomain_t* domain; - struct impurecord* impu_rec; - impu_contact_t *impucontact; + str impu; + int res; + udomain_t *domain; + struct impurecord *impu_rec; + impu_contact_t *impucontact; - if (rpc->scan(ctx, "S", &impu) < 1) { - rpc->fault(ctx, 400, "required IMPU argument"); - return; - } + if(rpc->scan(ctx, "S", &impu) < 1) { + rpc->fault(ctx, 400, "required IMPU argument"); + return; + } - LM_DBG("Request to re-register impu <%.*s>\n", impu.len, impu.s); + LM_DBG("Request to re-register impu <%.*s>\n", impu.len, impu.s); - res = ul.get_udomain("location", &domain); - if (res != 0) { - LM_ERR("Failed to get domain\n"); - return; - } - - ul.lock_udomain(domain, &impu); - res = ul.get_impurecord(domain, &impu, &impu_rec); - if (res != 0) { - LM_ERR("Trying to de-register '%.*s' Not found in usrloc\n", impu.len, impu.s); - ul.unlock_udomain(domain, &impu); - return; - } + res = ul.get_udomain("location", &domain); + if(res != 0) { + LM_ERR("Failed to get domain\n"); + return; + } + + ul.lock_udomain(domain, &impu); + res = ul.get_impurecord(domain, &impu, &impu_rec); + if(res != 0) { + LM_ERR("Trying to de-register '%.*s' Not found in usrloc\n", impu.len, + impu.s); + ul.unlock_udomain(domain, &impu); + return; + } - impucontact = impu_rec->linked_contacts.head; - while (impucontact) { - LM_DBG("Deleting contact with AOR [%.*s]\n", impucontact->contact->aor.len, impucontact->contact->aor.s); - ul.lock_contact_slot_i(impucontact->contact->sl); - impucontact->contact->state = CONTACT_DELETE_PENDING; - if (impu_rec->shead) { - //send NOTIFY to all subscribers of this IMPU. - notify_subscribers(impu_rec, impucontact->contact, 0, 0, IMS_REGISTRAR_CONTACT_UNREGISTERED); - } - impucontact->contact->state = CONTACT_DELETED; - ul.unlock_contact_slot_i(impucontact->contact->sl); - impucontact = impucontact->next; + impucontact = impu_rec->linked_contacts.head; + while(impucontact) { + LM_DBG("Deleting contact with AOR [%.*s]\n", + impucontact->contact->aor.len, impucontact->contact->aor.s); + ul.lock_contact_slot_i(impucontact->contact->sl); + impucontact->contact->state = CONTACT_DELETE_PENDING; + if(impu_rec->shead) { + //send NOTIFY to all subscribers of this IMPU. + notify_subscribers(impu_rec, impucontact->contact, 0, 0, + IMS_REGISTRAR_CONTACT_UNREGISTERED); } + impucontact->contact->state = CONTACT_DELETED; + ul.unlock_contact_slot_i(impucontact->contact->sl); + impucontact = impucontact->next; + } - ul.unlock_udomain(domain, &impu); + ul.unlock_udomain(domain, &impu); } rpc_export_t reg_rpc[] = { {"regscscf.dereg_impu", reg_rpc_dereg_impu, reg_rpc_dereg_impu_doc, 0}, - {0, 0, 0, 0} -}; - - + {0, 0, 0, 0}}; diff --git a/src/modules/ims_registrar_scscf/registrar_notify.c b/src/modules/ims_registrar_scscf/registrar_notify.c index ef2b4a8fe74..6b19c4e9774 100644 --- a/src/modules/ims_registrar_scscf/registrar_notify.c +++ b/src/modules/ims_registrar_scscf/registrar_notify.c @@ -100,447 +100,502 @@ extern char *domain; * RFC allows only value less or equal to the one provided by UAC. */ -static inline int randomize_expires(int expires, int range) { - /* if no range is given just return expires */ - if (range == 0) return expires; +static inline int randomize_expires(int expires, int range) +{ + /* if no range is given just return expires */ + if(range == 0) + return expires; - int range_min = expires - (float) range / 100 * expires; + int range_min = expires - (float)range / 100 * expires; - return range_min + (float) (kam_rand() % 100) / 100 * (expires - range_min); + return range_min + (float)(kam_rand() % 100) / 100 * (expires - range_min); } -int notify_init() { - notification_list = shm_malloc(sizeof (reg_notification_list)); - if (!notification_list) { - LM_ERR("No more SHM mem\n"); - return 0; - } - memset(notification_list, 0, sizeof (reg_notification_list)); - notification_list->lock = lock_alloc(); - if (!notification_list->lock) { - LM_ERR("failed to create cdp event list lock\n"); - return 0; - } - if (lock_init(notification_list->lock) == 0) { - lock_dealloc(notification_list->lock); - notification_list->lock = 0; - LM_ERR("failed to initialize cdp event list lock\n"); - return 0; - } - notification_list->size = 0; - sem_new(notification_list->empty, 0); //pre-locked - as we assume list is empty at start - return 1; +int notify_init() +{ + notification_list = shm_malloc(sizeof(reg_notification_list)); + if(!notification_list) { + LM_ERR("No more SHM mem\n"); + return 0; + } + memset(notification_list, 0, sizeof(reg_notification_list)); + notification_list->lock = lock_alloc(); + if(!notification_list->lock) { + LM_ERR("failed to create cdp event list lock\n"); + return 0; + } + if(lock_init(notification_list->lock) == 0) { + lock_dealloc(notification_list->lock); + notification_list->lock = 0; + LM_ERR("failed to initialize cdp event list lock\n"); + return 0; + } + notification_list->size = 0; + sem_new(notification_list->empty, + 0); //pre-locked - as we assume list is empty at start + return 1; } /** * Destroys the reg notifications list. */ -void notify_destroy() { - reg_notification *n, *nn; - lock_get(notification_list->lock); - n = notification_list->head; - while (n) { - nn = n->next; - free_notification(n); - n = nn; - } - lock_destroy(notification_list->lock); - lock_dealloc(notification_list->lock); - shm_free(notification_list); +void notify_destroy() +{ + reg_notification *n, *nn; + lock_get(notification_list->lock); + n = notification_list->head; + while(n) { + nn = n->next; + free_notification(n); + n = nn; + } + lock_destroy(notification_list->lock); + lock_dealloc(notification_list->lock); + shm_free(notification_list); } -int can_publish_reg(struct sip_msg *msg, char *_t, char *str2) { - - int ret = CSCF_RETURN_FALSE; - str presentity_uri = {0, 0}; - str event; - str asserted_id; - ucontact_t* c = 0; - impurecord_t* r; - int res; - ims_public_identity *pi = 0; - int i, j; - impu_contact_t *impucontact; - - LM_DBG("Checking if allowed to publish reg event\n"); - - //check that this is a request - if (msg->first_line.type != SIP_REQUEST) { - LM_ERR("This message is not a request\n"); - goto error; - } - - //check that this is a subscribe request - if (msg->first_line.u.request.method.len != 7 || - memcmp(msg->first_line.u.request.method.s, "PUBLISH", 7) != 0) { - LM_ERR("This message is not a PUBLISH\n"); - goto error; - } - - //check that this is a reg event - currently we only support reg event! - event = cscf_get_event(msg); - if (event.len != 3 || strncasecmp(event.s, "reg", 3) != 0) { - LM_ERR("Accepting only . Found: <%.*s>\n", - event.len, event.s); - goto done; - } - - asserted_id = cscf_get_asserted_identity(msg, 0); - if (!asserted_id.len) { - LM_ERR("P-Asserted-Identity empty.\n"); - goto error; - } - LM_DBG("P-Asserted-Identity <%.*s>.\n", asserted_id.len, asserted_id.s); - - //get presentity URI - presentity_uri = cscf_get_public_identity_from_requri(msg); - - LM_DBG("Looking for IMPU in usrloc <%.*s>\n", presentity_uri.len, presentity_uri.s); - - ul.lock_udomain((udomain_t*) _t, &presentity_uri); - res = ul.get_impurecord((udomain_t*) _t, &presentity_uri, &r); - - if (res != 0) { - LM_DBG("'%.*s' Not found in usrloc\n", presentity_uri.len, presentity_uri.s); - ul.unlock_udomain((udomain_t*) _t, &presentity_uri); - goto done; - } - - LM_DBG("<%.*s> found in usrloc\n", presentity_uri.len, presentity_uri.s); - - //check if the asserted identity is in the same group as that presentity uri - if (r->public_identity.len == asserted_id.len && - strncasecmp(r->public_identity.s, asserted_id.s, asserted_id.len) == 0) { - LM_DBG("Identity found as AOR <%.*s>\n", - presentity_uri.len, presentity_uri.s); - ul.unlock_udomain((udomain_t*) _t, &presentity_uri); - ret = CSCF_RETURN_TRUE; - goto done; - } - - //check if asserted identity is in service profile - ul.lock_subscription(r->s); - if (r->s) { - for (i = 0; i < r->s->service_profiles_cnt; i++) - for (j = 0; j < r->s->service_profiles[i].public_identities_cnt; j++) { - pi = &(r->s->service_profiles[i].public_identities[j]); - if (!pi->barring && - pi->public_identity.len == asserted_id.len && - strncasecmp(pi->public_identity.s, asserted_id.s, asserted_id.len) == 0) { - LM_DBG("Identity found in SP[%d][%d]\n", - i, j); - ret = CSCF_RETURN_TRUE; - ul.unlock_subscription(r->s); - ul.unlock_udomain((udomain_t*) _t, &presentity_uri); - goto done; - } - } - } - ul.unlock_subscription(r->s); - LM_DBG("Did not find p-asserted-identity <%.*s> in SP\n", asserted_id.len, asserted_id.s); - - //check if asserted is present in any of the path headers - j = 0; +int can_publish_reg(struct sip_msg *msg, char *_t, char *str2) +{ + + int ret = CSCF_RETURN_FALSE; + str presentity_uri = {0, 0}; + str event; + str asserted_id; + ucontact_t *c = 0; + impurecord_t *r; + int res; + ims_public_identity *pi = 0; + int i, j; + impu_contact_t *impucontact; + + LM_DBG("Checking if allowed to publish reg event\n"); + + //check that this is a request + if(msg->first_line.type != SIP_REQUEST) { + LM_ERR("This message is not a request\n"); + goto error; + } + + //check that this is a subscribe request + if(msg->first_line.u.request.method.len != 7 + || memcmp(msg->first_line.u.request.method.s, "PUBLISH", 7) != 0) { + LM_ERR("This message is not a PUBLISH\n"); + goto error; + } + + //check that this is a reg event - currently we only support reg event! + event = cscf_get_event(msg); + if(event.len != 3 || strncasecmp(event.s, "reg", 3) != 0) { + LM_ERR("Accepting only . Found: <%.*s>\n", event.len, + event.s); + goto done; + } + + asserted_id = cscf_get_asserted_identity(msg, 0); + if(!asserted_id.len) { + LM_ERR("P-Asserted-Identity empty.\n"); + goto error; + } + LM_DBG("P-Asserted-Identity <%.*s>.\n", asserted_id.len, asserted_id.s); + + //get presentity URI + presentity_uri = cscf_get_public_identity_from_requri(msg); + + LM_DBG("Looking for IMPU in usrloc <%.*s>\n", presentity_uri.len, + presentity_uri.s); + + ul.lock_udomain((udomain_t *)_t, &presentity_uri); + res = ul.get_impurecord((udomain_t *)_t, &presentity_uri, &r); + + if(res != 0) { + LM_DBG("'%.*s' Not found in usrloc\n", presentity_uri.len, + presentity_uri.s); + ul.unlock_udomain((udomain_t *)_t, &presentity_uri); + goto done; + } + + LM_DBG("<%.*s> found in usrloc\n", presentity_uri.len, presentity_uri.s); + + //check if the asserted identity is in the same group as that presentity uri + if(r->public_identity.len == asserted_id.len + && strncasecmp(r->public_identity.s, asserted_id.s, asserted_id.len) + == 0) { + LM_DBG("Identity found as AOR <%.*s>\n", presentity_uri.len, + presentity_uri.s); + ul.unlock_udomain((udomain_t *)_t, &presentity_uri); + ret = CSCF_RETURN_TRUE; + goto done; + } + + //check if asserted identity is in service profile + ul.lock_subscription(r->s); + if(r->s) { + for(i = 0; i < r->s->service_profiles_cnt; i++) + for(j = 0; j < r->s->service_profiles[i].public_identities_cnt; + j++) { + pi = &(r->s->service_profiles[i].public_identities[j]); + if(!pi->barring && pi->public_identity.len == asserted_id.len + && strncasecmp(pi->public_identity.s, asserted_id.s, + asserted_id.len) + == 0) { + LM_DBG("Identity found in SP[%d][%d]\n", i, j); + ret = CSCF_RETURN_TRUE; + ul.unlock_subscription(r->s); + ul.unlock_udomain((udomain_t *)_t, &presentity_uri); + goto done; + } + } + } + ul.unlock_subscription(r->s); + LM_DBG("Did not find p-asserted-identity <%.*s> in SP\n", asserted_id.len, + asserted_id.s); + + //check if asserted is present in any of the path headers + j = 0; impucontact = r->linked_contacts.head; - while (impucontact) { + while(impucontact) { c = impucontact->contact; - if (c->path.len) { - LM_DBG("Path: <%.*s>.\n", - c->path.len, c->path.s); - for (i = 0; i < c->path.len - (asserted_id.len - 4); i++) { - //we compare the asserted_id without "sip:" to the path - if (strncasecmp(c->path.s + i, asserted_id.s + 4, asserted_id.len - 4) == 0) { - LM_DBG("Identity found in Path <%.*s>\n", - c->path.len, c->path.s); - ret = CSCF_RETURN_TRUE; - ul.unlock_udomain((udomain_t*) _t, &presentity_uri); - goto done; - } - } - } + if(c->path.len) { + LM_DBG("Path: <%.*s>.\n", c->path.len, c->path.s); + for(i = 0; i < c->path.len - (asserted_id.len - 4); i++) { + //we compare the asserted_id without "sip:" to the path + if(strncasecmp(c->path.s + i, asserted_id.s + 4, + asserted_id.len - 4) + == 0) { + LM_DBG("Identity found in Path <%.*s>\n", c->path.len, + c->path.s); + ret = CSCF_RETURN_TRUE; + ul.unlock_udomain((udomain_t *)_t, &presentity_uri); + goto done; + } + } + } impucontact = impucontact->next; - } - LM_DBG("Did not find p-asserted-identity <%.*s> on Path\n", asserted_id.len, asserted_id.s); + } + LM_DBG("Did not find p-asserted-identity <%.*s> on Path\n", asserted_id.len, + asserted_id.s); - ul.unlock_udomain((udomain_t*) _t, &presentity_uri); - LM_DBG("Publish forbidden\n"); + ul.unlock_udomain((udomain_t *)_t, &presentity_uri); + LM_DBG("Publish forbidden\n"); done: - if (presentity_uri.s) shm_free(presentity_uri.s); // shm_malloc in cscf_get_public_identity_from_requri - return ret; + if(presentity_uri.s) + shm_free( + presentity_uri + .s); // shm_malloc in cscf_get_public_identity_from_requri + return ret; error: - if (presentity_uri.s) shm_free(presentity_uri.s); // shm_malloc in cscf_get_public_identity_from_requri - ret = CSCF_RETURN_ERROR; - return ret; + if(presentity_uri.s) + shm_free( + presentity_uri + .s); // shm_malloc in cscf_get_public_identity_from_requri + ret = CSCF_RETURN_ERROR; + return ret; } -int can_subscribe_to_reg(struct sip_msg *msg, char *_t, char *str2) { - - int ret = CSCF_RETURN_FALSE; - str presentity_uri = {0, 0}; - str callid = {0, 0}; - str ftag = {0, 0}; - str ttag = {0, 0}; - str event; - str asserted_id; - ucontact_t* c = 0; - impurecord_t* r; - int res; +int can_subscribe_to_reg(struct sip_msg *msg, char *_t, char *str2) +{ + + int ret = CSCF_RETURN_FALSE; + str presentity_uri = {0, 0}; + str callid = {0, 0}; + str ftag = {0, 0}; + str ttag = {0, 0}; + str event; + str asserted_id; + ucontact_t *c = 0; + impurecord_t *r; + int res; impu_contact_t *impucontact; - ims_public_identity *pi = 0; - int i, j; - - LM_DBG("Checking if allowed to subscribe to event\n"); - - //check that this is a request - if (msg->first_line.type != SIP_REQUEST) { - LM_ERR("This message is not a request\n"); - goto error; - } - - //check that this is a subscribe request - if (msg->first_line.u.request.method.len != 9 || - memcmp(msg->first_line.u.request.method.s, "SUBSCRIBE", 9) != 0) { - LM_ERR("This message is not a SUBSCRIBE\n"); - goto error; - } - - //check that this is a reg event - currently we only support reg event! - event = cscf_get_event(msg); - if (event.len != 3 || strncasecmp(event.s, "reg", 3) != 0) { - LM_ERR("Accepting only . Found: <%.*s>\n", - event.len, event.s); - goto done; - } - - //get callid, from and to tags to be able to identify dialog - //callid - callid = cscf_get_call_id(msg, 0); - if (callid.len <= 0 || !callid.s) { - LM_ERR("unable to get callid\n"); - goto error; - } - //ftag - if (!cscf_get_from_tag(msg, &ftag)) { - LM_ERR("Unable to get ftag\n"); - goto error; - } - - //ttag - if (!cscf_get_to_tag(msg, &ttag)) { - LM_ERR("Unable to get ttag\n"); - goto error; - } - - //get presentity URI - //check if SUBSCRIBE is initial or SUBSEQUENT - if (ttag.len == 0) { - LM_DBG("Msg has no ttag - this is initial subscribe - get presentity URI from req URI\n"); - presentity_uri = cscf_get_public_identity_from_requri(msg); - } else { - presentity_uri = ul.get_presentity_from_subscriber_dialog(&callid, &ttag, &ftag); - if (presentity_uri.len == 0) { - LM_ERR("Unable to get presentity uri from subscriber dialog with callid <%.*s>, ttag <%.*s> and ftag <%.*s>\n", - callid.len, callid.s, ttag.len, ttag.s, ftag.len, ftag.s); - goto done; - } - } - - - asserted_id = cscf_get_asserted_identity(msg, 0); - if (!asserted_id.len) { - LM_ERR("P-Asserted-Identity empty.\n"); - goto error; - } - LM_DBG("P-Asserted-Identity <%.*s>.\n", - asserted_id.len, asserted_id.s); - - LM_DBG("Looking for IMPU in usrloc <%.*s>\n", presentity_uri.len, presentity_uri.s); - - ul.lock_udomain((udomain_t*) _t, &presentity_uri); - res = ul.get_impurecord((udomain_t*) _t, &presentity_uri, &r); - - if (res != 0) { - LM_DBG("'%.*s' Not found in usrloc\n", presentity_uri.len, presentity_uri.s); - ul.unlock_udomain((udomain_t*) _t, &presentity_uri); - goto done; - } - - LM_DBG("<%.*s> found in usrloc\n", presentity_uri.len, presentity_uri.s); - - //check if the asserted identity is in the same group as that presentity uri - if (r->public_identity.len == asserted_id.len && - strncasecmp(r->public_identity.s, asserted_id.s, asserted_id.len) == 0) { - LM_DBG("Identity found as AOR <%.*s>\n", - presentity_uri.len, presentity_uri.s); - ul.unlock_udomain((udomain_t*) _t, &presentity_uri); - ret = CSCF_RETURN_TRUE; - goto done; - } - - //check if asserted identity is in service profile - ul.lock_subscription(r->s); - if (r->s) { - for (i = 0; i < r->s->service_profiles_cnt; i++) - for (j = 0; j < r->s->service_profiles[i].public_identities_cnt; j++) { - pi = &(r->s->service_profiles[i].public_identities[j]); - if (!pi->barring && - pi->public_identity.len == asserted_id.len && - strncasecmp(pi->public_identity.s, asserted_id.s, asserted_id.len) == 0) { - LM_DBG("Identity found in SP[%d][%d]\n", - i, j); - ret = CSCF_RETURN_TRUE; - ul.unlock_subscription(r->s); - ul.unlock_udomain((udomain_t*) _t, &presentity_uri); - goto done; - } - } - } - ul.unlock_subscription(r->s); - LM_DBG("Did not find p-asserted-identity <%.*s> in SP\n", asserted_id.len, asserted_id.s); - - //check if asserted is present in any of the path headers + ims_public_identity *pi = 0; + int i, j; + + LM_DBG("Checking if allowed to subscribe to event\n"); + + //check that this is a request + if(msg->first_line.type != SIP_REQUEST) { + LM_ERR("This message is not a request\n"); + goto error; + } + + //check that this is a subscribe request + if(msg->first_line.u.request.method.len != 9 + || memcmp(msg->first_line.u.request.method.s, "SUBSCRIBE", 9) + != 0) { + LM_ERR("This message is not a SUBSCRIBE\n"); + goto error; + } + + //check that this is a reg event - currently we only support reg event! + event = cscf_get_event(msg); + if(event.len != 3 || strncasecmp(event.s, "reg", 3) != 0) { + LM_ERR("Accepting only . Found: <%.*s>\n", event.len, + event.s); + goto done; + } + + //get callid, from and to tags to be able to identify dialog + //callid + callid = cscf_get_call_id(msg, 0); + if(callid.len <= 0 || !callid.s) { + LM_ERR("unable to get callid\n"); + goto error; + } + //ftag + if(!cscf_get_from_tag(msg, &ftag)) { + LM_ERR("Unable to get ftag\n"); + goto error; + } + + //ttag + if(!cscf_get_to_tag(msg, &ttag)) { + LM_ERR("Unable to get ttag\n"); + goto error; + } + + //get presentity URI + //check if SUBSCRIBE is initial or SUBSEQUENT + if(ttag.len == 0) { + LM_DBG("Msg has no ttag - this is initial subscribe - get presentity " + "URI from req URI\n"); + presentity_uri = cscf_get_public_identity_from_requri(msg); + } else { + presentity_uri = + ul.get_presentity_from_subscriber_dialog(&callid, &ttag, &ftag); + if(presentity_uri.len == 0) { + LM_ERR("Unable to get presentity uri from subscriber dialog with " + "callid <%.*s>, ttag <%.*s> and ftag <%.*s>\n", + callid.len, callid.s, ttag.len, ttag.s, ftag.len, ftag.s); + goto done; + } + } + + + asserted_id = cscf_get_asserted_identity(msg, 0); + if(!asserted_id.len) { + LM_ERR("P-Asserted-Identity empty.\n"); + goto error; + } + LM_DBG("P-Asserted-Identity <%.*s>.\n", asserted_id.len, asserted_id.s); + + LM_DBG("Looking for IMPU in usrloc <%.*s>\n", presentity_uri.len, + presentity_uri.s); + + ul.lock_udomain((udomain_t *)_t, &presentity_uri); + res = ul.get_impurecord((udomain_t *)_t, &presentity_uri, &r); + + if(res != 0) { + LM_DBG("'%.*s' Not found in usrloc\n", presentity_uri.len, + presentity_uri.s); + ul.unlock_udomain((udomain_t *)_t, &presentity_uri); + goto done; + } + + LM_DBG("<%.*s> found in usrloc\n", presentity_uri.len, presentity_uri.s); + + //check if the asserted identity is in the same group as that presentity uri + if(r->public_identity.len == asserted_id.len + && strncasecmp(r->public_identity.s, asserted_id.s, asserted_id.len) + == 0) { + LM_DBG("Identity found as AOR <%.*s>\n", presentity_uri.len, + presentity_uri.s); + ul.unlock_udomain((udomain_t *)_t, &presentity_uri); + ret = CSCF_RETURN_TRUE; + goto done; + } + + //check if asserted identity is in service profile + ul.lock_subscription(r->s); + if(r->s) { + for(i = 0; i < r->s->service_profiles_cnt; i++) + for(j = 0; j < r->s->service_profiles[i].public_identities_cnt; + j++) { + pi = &(r->s->service_profiles[i].public_identities[j]); + if(!pi->barring && pi->public_identity.len == asserted_id.len + && strncasecmp(pi->public_identity.s, asserted_id.s, + asserted_id.len) + == 0) { + LM_DBG("Identity found in SP[%d][%d]\n", i, j); + ret = CSCF_RETURN_TRUE; + ul.unlock_subscription(r->s); + ul.unlock_udomain((udomain_t *)_t, &presentity_uri); + goto done; + } + } + } + ul.unlock_subscription(r->s); + LM_DBG("Did not find p-asserted-identity <%.*s> in SP\n", asserted_id.len, + asserted_id.s); + + //check if asserted is present in any of the path headers impucontact = r->linked_contacts.head; - - while (impucontact) { + + while(impucontact) { c = impucontact->contact; - if (c->path.len) { - LM_DBG("Path: <%.*s>.\n", - c->path.len, c->path.s); - for (i = 0; i < c->path.len - (asserted_id.len - 4); i++) { - //we compare the asserted_id without "sip:" to the path - if (strncasecmp(c->path.s + i, asserted_id.s + 4, asserted_id.len - 4) == 0) { - LM_DBG("Identity found in Path <%.*s>\n", - c->path.len, c->path.s); - ret = CSCF_RETURN_TRUE; - ul.unlock_udomain((udomain_t*) _t, &presentity_uri); - goto done; - } - } - } - impucontact = impucontact->next; - } - - LM_DBG("Did not find p-asserted-identity <%.*s> on Path\n", asserted_id.len, asserted_id.s); - - ul.unlock_udomain((udomain_t*) _t, &presentity_uri); - LM_DBG("Subscribe forbidden\n"); + if(c->path.len) { + LM_DBG("Path: <%.*s>.\n", c->path.len, c->path.s); + for(i = 0; i < c->path.len - (asserted_id.len - 4); i++) { + //we compare the asserted_id without "sip:" to the path + if(strncasecmp(c->path.s + i, asserted_id.s + 4, + asserted_id.len - 4) + == 0) { + LM_DBG("Identity found in Path <%.*s>\n", c->path.len, + c->path.s); + ret = CSCF_RETURN_TRUE; + ul.unlock_udomain((udomain_t *)_t, &presentity_uri); + goto done; + } + } + } + impucontact = impucontact->next; + } + + LM_DBG("Did not find p-asserted-identity <%.*s> on Path\n", asserted_id.len, + asserted_id.s); + + ul.unlock_udomain((udomain_t *)_t, &presentity_uri); + LM_DBG("Subscribe forbidden\n"); done: - if (presentity_uri.s) shm_free(presentity_uri.s); // shm_malloc in cscf_get_public_identity_from_requri or get_presentity_from_subscriber_dialog - return ret; + if(presentity_uri.s) + shm_free( + presentity_uri + .s); // shm_malloc in cscf_get_public_identity_from_requri or get_presentity_from_subscriber_dialog + return ret; error: - ret = CSCF_RETURN_ERROR; - if (presentity_uri.s) shm_free(presentity_uri.s); // shm_malloc in cscf_get_public_identity_from_requri or get_presentity_from_subscriber_dialog - return ret; + ret = CSCF_RETURN_ERROR; + if(presentity_uri.s) + shm_free( + presentity_uri + .s); // shm_malloc in cscf_get_public_identity_from_requri or get_presentity_from_subscriber_dialog + return ret; } /* * called to deliver new event into notification process * return 0 on success. anything else failure */ -int event_reg(udomain_t* _d, impurecord_t* r_passed, ucontact_t* c_passed, int event_type, str *presentity_uri, str *watcher_contact, str *contact_uri, - str *explit_dereg_contact, int num_explit_dereg_contact) { - impurecord_t* r; - int num_impus; - str* impu_list = 0; - int res = 0; - udomain_t* udomain; - - get_act_time(); - - LM_DBG("Sending Reg event notifies\n"); - LM_DBG("Switching on event type: %d\n", event_type); - switch (event_type) { - case IMS_REGISTRAR_NONE: - return 0; - case IMS_REGISTRAR_SUBSCRIBE: - if (r_passed || !presentity_uri || !watcher_contact || !_d) { - LM_ERR("this is a subscribe called from cfg file: r_passed be zero and presentity_uri, watcher_contact and _d should be valid for a subscribe"); - return 0; - } - LM_DBG("Event type is IMS REGISTRAR SUBSCRIBE about to get reginfo_full\n"); - //lets get IMPU list for presentity as well as register for callbacks (IFF it is a new SUBSCRIBE) - - ul.lock_udomain(_d, presentity_uri); - res = ul.get_impurecord(_d, presentity_uri, &r); - if (res != 0) { - LM_WARN("Strange, '%.*s' Not found in usrloc\n", presentity_uri->len, presentity_uri->s); - ul.unlock_udomain(_d, presentity_uri); - //no point in continuing - return 1; - } - - //get IMPU set from the presentity's subscription - res = ul.get_impus_from_subscription_as_string(_d, r, - 0/*all unbarred impus*/, &impu_list, &num_impus, 0/*pkg*/); - if (res != 0) { - LM_WARN("failed to get IMPUs from subscription\n"); - ul.unlock_udomain(_d, presentity_uri); - if (impu_list) { - pkg_free(impu_list); - } - return 1; - } - ul.unlock_udomain((udomain_t*) _d, presentity_uri); - LM_DBG("About to create notification\n"); - - create_notifications(_d, r_passed, c_passed, presentity_uri, watcher_contact, contact_uri, impu_list, num_impus, event_type, explit_dereg_contact, num_explit_dereg_contact); - if (impu_list) { - pkg_free(impu_list); - } +int event_reg(udomain_t *_d, impurecord_t *r_passed, ucontact_t *c_passed, + int event_type, str *presentity_uri, str *watcher_contact, + str *contact_uri, str *explit_dereg_contact, + int num_explit_dereg_contact) +{ + impurecord_t *r; + int num_impus; + str *impu_list = 0; + int res = 0; + udomain_t *udomain; + + get_act_time(); + + LM_DBG("Sending Reg event notifies\n"); + LM_DBG("Switching on event type: %d\n", event_type); + switch(event_type) { + case IMS_REGISTRAR_NONE: return 0; - break; - - //richard: we only use reg unreg expired and refresh - case IMS_REGISTRAR_CONTACT_UNREGISTERED: - case IMS_REGISTRAR_CONTACT_DEREGISTERED: - case IMS_REGISTRAR_CONTACT_UNREGISTERED_IMPLICIT: - case IMS_REGISTRAR_CONTACT_REGISTERED: - case IMS_REGISTRAR_CONTACT_REFRESHED: - case IMS_REGISTRAR_CONTACT_EXPIRED: - if (!r_passed || presentity_uri || watcher_contact || _d) { - LM_ERR("this is a contact change passed from ul callback: r_passed and c_passed should both be valid and presentity_uri, watcher_contact and _d should be 0 for ul callback\n"); - return 0; - } - //this is a ulcallback so r_passed domain is already locked - res = ul.get_impus_from_subscription_as_string(_d, r_passed, - 0/*all unbarred impus*/, &impu_list, &num_impus, 0/*pkg*/); - if (res != 0) { - LM_WARN("failed to get IMPUs from subscription\n"); - if (impu_list) { - pkg_free(impu_list); - } - return 1; - } - - //TODO this should be a configurable module param - if (ul.register_udomain(domain, &udomain) < 0) { - LM_ERR("Unable to register usrloc domain....aborting\n"); - if (impu_list) { - pkg_free(impu_list); - } + case IMS_REGISTRAR_SUBSCRIBE: + if(r_passed || !presentity_uri || !watcher_contact || !_d) { + LM_ERR("this is a subscribe called from cfg file: r_passed be " + "zero and presentity_uri, watcher_contact and _d should " + "be valid for a subscribe"); return 0; - } - LM_DBG("About to create notification\n"); - create_notifications(_d, r_passed, c_passed, presentity_uri, watcher_contact, contact_uri, impu_list, num_impus, event_type, explit_dereg_contact, num_explit_dereg_contact); - if (impu_list) { - pkg_free(impu_list); - } + } + LM_DBG("Event type is IMS REGISTRAR SUBSCRIBE about to get " + "reginfo_full\n"); + //lets get IMPU list for presentity as well as register for callbacks (IFF it is a new SUBSCRIBE) + + ul.lock_udomain(_d, presentity_uri); + res = ul.get_impurecord(_d, presentity_uri, &r); + if(res != 0) { + LM_WARN("Strange, '%.*s' Not found in usrloc\n", + presentity_uri->len, presentity_uri->s); + ul.unlock_udomain(_d, presentity_uri); + //no point in continuing + return 1; + } + + //get IMPU set from the presentity's subscription + res = ul.get_impus_from_subscription_as_string(_d, r, + 0 /*all unbarred impus*/, &impu_list, &num_impus, + 0 /*pkg*/); + if(res != 0) { + LM_WARN("failed to get IMPUs from subscription\n"); + ul.unlock_udomain(_d, presentity_uri); + if(impu_list) { + pkg_free(impu_list); + } + return 1; + } + ul.unlock_udomain((udomain_t *)_d, presentity_uri); + LM_DBG("About to create notification\n"); + + create_notifications(_d, r_passed, c_passed, presentity_uri, + watcher_contact, contact_uri, impu_list, num_impus, + event_type, explit_dereg_contact, num_explit_dereg_contact); + if(impu_list) { + pkg_free(impu_list); + } + return 0; + break; + + //richard: we only use reg unreg expired and refresh + case IMS_REGISTRAR_CONTACT_UNREGISTERED: + case IMS_REGISTRAR_CONTACT_DEREGISTERED: + case IMS_REGISTRAR_CONTACT_UNREGISTERED_IMPLICIT: + case IMS_REGISTRAR_CONTACT_REGISTERED: + case IMS_REGISTRAR_CONTACT_REFRESHED: + case IMS_REGISTRAR_CONTACT_EXPIRED: + if(!r_passed || presentity_uri || watcher_contact || _d) { + LM_ERR("this is a contact change passed from ul callback: " + "r_passed and c_passed should both be valid and " + "presentity_uri, watcher_contact and _d should be 0 for " + "ul callback\n"); + return 0; + } + //this is a ulcallback so r_passed domain is already locked + res = ul.get_impus_from_subscription_as_string(_d, r_passed, + 0 /*all unbarred impus*/, &impu_list, &num_impus, + 0 /*pkg*/); + if(res != 0) { + LM_WARN("failed to get IMPUs from subscription\n"); + if(impu_list) { + pkg_free(impu_list); + } + return 1; + } + + //TODO this should be a configurable module param + if(ul.register_udomain(domain, &udomain) < 0) { + LM_ERR("Unable to register usrloc domain....aborting\n"); + if(impu_list) { + pkg_free(impu_list); + } + return 0; + } + LM_DBG("About to create notification\n"); + create_notifications(_d, r_passed, c_passed, presentity_uri, + watcher_contact, contact_uri, impu_list, num_impus, + event_type, explit_dereg_contact, num_explit_dereg_contact); + if(impu_list) { + pkg_free(impu_list); + } return 1; - default: - LM_ERR("ERR:event_reg: Unknown event %d\n", event_type); - // if (send_now) notification_timer(0, 0); - return 1; - } + default: + LM_ERR("ERR:event_reg: Unknown event %d\n", event_type); + // if (send_now) notification_timer(0, 0); + return 1; + } } -int notify_subscribers(impurecord_t* impurecord, ucontact_t* contact, str *explit_dereg_contact, int num_explit_dereg_contact, int event_type) { - event_reg(0, impurecord, contact, event_type, 0, 0, 0, explit_dereg_contact, num_explit_dereg_contact); +int notify_subscribers(impurecord_t *impurecord, ucontact_t *contact, + str *explit_dereg_contact, int num_explit_dereg_contact, int event_type) +{ + event_reg(0, impurecord, contact, event_type, 0, 0, 0, explit_dereg_contact, + num_explit_dereg_contact); - return 0; + return 0; } /*! Called to process a contact in a received publish document. No locks held when calling this function @@ -552,381 +607,436 @@ int notify_subscribers(impurecord_t* impurecord, ucontact_t* contact, str *expli * @param contact_state * @return */ -int process_contact(ims_subscription* subscription, udomain_t * _d, int expires, str contact_uri, int contact_state) { - - int ret = CSCF_RETURN_TRUE; - int i, j; - ims_public_identity* pi = 0; - struct ucontact* ucontact; - str callid = {0, 0}; - str path = {0, 0}; - impurecord_t* implicit_impurecord = 0; - get_act_time(); - - //first get the subscription - //then go through each implicit public identity (exclude the explicit identity) - //get the IMPU rec for each implicit public identity - //then get the contact for each implicit IMPU and delete if contact_state == STATE_TERMINATED - //then get the contact for each explicit IMPU and delete if contact_state == STATE_TERMINATED - - - //now update the implicit set - for (i = 0; i < subscription->service_profiles_cnt; i++) { - for (j = 0; j < subscription->service_profiles[i].public_identities_cnt; j++) { - pi = &(subscription->service_profiles[i].public_identities[j]); - - // if ((presentity_aor->len == pi->public_identity.len) && memcmp(presentity_aor.s, pi->public_identity.s, presentity_aor->len) == 0) { //we don't need to update the explicit IMPU - // LM_DBG("Ignoring explicit identity <%.*s>, updating later..... end of fn\n", presentity_aor.len, presentity_aor->s); - // goto next_implicit_impu; - // } - ul.lock_udomain(_d, &pi->public_identity); - if (ul.get_impurecord(_d, &pi->public_identity, &implicit_impurecord) != 0) { - LM_DBG("usrloc does not have impurecord for implicitly IMPU, ignore\n"); - goto next_implicit_impu; - } - if (ul.get_ucontact(&contact_uri, &callid, &path, 0/*cseq*/, &ucontact) != 0) { //contact does not exist - LM_DBG("This contact: <%.*s> is not in usrloc, ignore - NOTE: You need S-CSCF usrloc set to match_mode CONTACT_ONLY\n", contact_uri.len, contact_uri.s); - goto next_implicit_impu; - } else {//contact exists - if (ucontact->state != CONTACT_DELETED) { - if (contact_state == STATE_TERMINATED) { - //delete contact - LM_DBG("This contact <%.*s> is in state terminated and is in usrloc so removing it from usrloc\n", contact_uri.len, contact_uri.s); - ul.lock_contact_slot(&contact_uri); - ucontact->state = CONTACT_DELETE_PENDING; - if (implicit_impurecord->shead) { - //send NOTIFY to all subscribers of this IMPU. - notify_subscribers(implicit_impurecord, ucontact, 0, 0, IMS_REGISTRAR_CONTACT_UNREGISTERED); - } - ul.unlock_contact_slot(&contact_uri); - // if (ul.unlink_contact_from_impu(implicit_impurecord, ucontact, 1, 0 /*implicit dereg of contact from IMPU*/) != 0) { - // LM_ERR("Failed to delete ucontact <%.*s> from implicit IMPU\n", contact_uri.len, contact_uri.s); - // ul.unlock_contact_slot(&contact_uri); - // ul.release_ucontact(ucontact); - // goto next_implicit_impu; //TODO: don't need to use goto here... - // } - } else {//state is active - LM_DBG("This contact: <%.*s> is not in state terminated and is in usrloc, ignore\n", contact_uri.len, contact_uri.s); - ul.release_ucontact(ucontact); - goto next_implicit_impu; - } - } - ul.release_ucontact(ucontact); - } -next_implicit_impu: - ul.unlock_udomain(_d, &pi->public_identity); - } - } - - if (contact_state == STATE_TERMINATED) { - //at this point we can assume that all notifies were sent out to the subscribers of the IMPUs related to the explicit and implicit impus. - //we must now change the state of the contact to deleted so they can be removed from the IMPU in the timer process... - if (ul.get_ucontact(&contact_uri, &callid, &path, 0/*cseq*/, &ucontact) != 0) { //contact does not exist - LM_DBG("This contact: <%.*s> is not in usrloc, ignore - NOTE: You need S-CSCF usrloc set to match_mode CONTACT_ONLY\n", contact_uri.len, contact_uri.s); - } else { - ul.lock_contact_slot(&contact_uri); - ucontact->state = CONTACT_DELETED; - ul.unlock_contact_slot(&contact_uri); - ul.release_ucontact(ucontact); - } - } - - // ul.lock_subscription(subscription); - // subscription->ref_count--; - // LM_DBG("subscription ref count after sub is now %d\n", subscription->ref_count); - // ul.unlock_subscription(subscription); - - // ul.lock_udomain(_d, &presentity_impurecord->public_identity); - - // if (ul.get_ucontact(&contact_uri, &callid, &path, 0/*cseq*/, &ucontact) != 0) { //contact does not exist - // LM_DBG("This contact: <%.*s> is not in usrloc, ignore - NOTE: You need S-CSCF usrloc set to match_mode CONTACT_ONLY\n", contact_uri.len, contact_uri.s); - // return ret; - // } else {//contact exists - // if (VALID_CONTACT(ucontact, act_time)) { - // if (contact_state == STATE_TERMINATED) { - // //delete contact - // LM_DBG("This contact <%.*s> is in state terminated and is in usrloc so removing it from usrloc\n", contact_uri.len, contact_uri.s); - //// ul.lock_contact_slot(&contact_uri); - //// if (ul.unlink_contact_from_impu(presentity_impurecord, ucontact, 1, 0 /*implicit dereg of contact from IMPU */) != 0) { - //// LM_ERR("Failed to delete ucontact <%.*s>\n", contact_uri.len, contact_uri.s); - //// ret = CSCF_RETURN_FALSE; - //// ul.unlock_contact_slot(&contact_uri); - //// ul.release_ucontact(ucontact); - //// goto done; - //// } - //// ul.unlock_contact_slot(&contact_uri); - // ucontact->state = CONTACT_DELETE_PENDING; - // if (implicit_impurecord->shead) { - // //send NOTIFY to all subscribers of this IMPU. - // notify_subscribers(implicit_impurecord); - // } - // } else {//state is active - // LM_DBG("This contact: <%.*s> is not in state terminated and is in usrloc, ignore\n", contact_uri.len, contact_uri.s); - // ul.release_ucontact(ucontact); - // goto done; - // } - // } - // ul.release_ucontact(ucontact); - // } - - //done: - // ul.unlock_udomain(_d, &presentity_impurecord->public_identity); - return ret; +int process_contact(ims_subscription *subscription, udomain_t *_d, int expires, + str contact_uri, int contact_state) +{ + + int ret = CSCF_RETURN_TRUE; + int i, j; + ims_public_identity *pi = 0; + struct ucontact *ucontact; + str callid = {0, 0}; + str path = {0, 0}; + impurecord_t *implicit_impurecord = 0; + get_act_time(); + + //first get the subscription + //then go through each implicit public identity (exclude the explicit identity) + //get the IMPU rec for each implicit public identity + //then get the contact for each implicit IMPU and delete if contact_state == STATE_TERMINATED + //then get the contact for each explicit IMPU and delete if contact_state == STATE_TERMINATED + + + //now update the implicit set + for(i = 0; i < subscription->service_profiles_cnt; i++) { + for(j = 0; j < subscription->service_profiles[i].public_identities_cnt; + j++) { + pi = &(subscription->service_profiles[i].public_identities[j]); + + // if ((presentity_aor->len == pi->public_identity.len) && memcmp(presentity_aor.s, pi->public_identity.s, presentity_aor->len) == 0) { //we don't need to update the explicit IMPU + // LM_DBG("Ignoring explicit identity <%.*s>, updating later..... end of fn\n", presentity_aor.len, presentity_aor->s); + // goto next_implicit_impu; + // } + ul.lock_udomain(_d, &pi->public_identity); + if(ul.get_impurecord(_d, &pi->public_identity, &implicit_impurecord) + != 0) { + LM_DBG("usrloc does not have impurecord for implicitly IMPU, " + "ignore\n"); + goto next_implicit_impu; + } + if(ul.get_ucontact( + &contact_uri, &callid, &path, 0 /*cseq*/, &ucontact) + != 0) { //contact does not exist + LM_DBG("This contact: <%.*s> is not in usrloc, ignore - NOTE: " + "You need S-CSCF usrloc set to match_mode " + "CONTACT_ONLY\n", + contact_uri.len, contact_uri.s); + goto next_implicit_impu; + } else { //contact exists + if(ucontact->state != CONTACT_DELETED) { + if(contact_state == STATE_TERMINATED) { + //delete contact + LM_DBG("This contact <%.*s> is in state terminated and " + "is in usrloc so removing it from usrloc\n", + contact_uri.len, contact_uri.s); + ul.lock_contact_slot(&contact_uri); + ucontact->state = CONTACT_DELETE_PENDING; + if(implicit_impurecord->shead) { + //send NOTIFY to all subscribers of this IMPU. + notify_subscribers(implicit_impurecord, ucontact, 0, + 0, IMS_REGISTRAR_CONTACT_UNREGISTERED); + } + ul.unlock_contact_slot(&contact_uri); + // if (ul.unlink_contact_from_impu(implicit_impurecord, ucontact, 1, 0 /*implicit dereg of contact from IMPU*/) != 0) { + // LM_ERR("Failed to delete ucontact <%.*s> from implicit IMPU\n", contact_uri.len, contact_uri.s); + // ul.unlock_contact_slot(&contact_uri); + // ul.release_ucontact(ucontact); + // goto next_implicit_impu; //TODO: don't need to use goto here... + // } + } else { //state is active + LM_DBG("This contact: <%.*s> is not in state " + "terminated and is in usrloc, ignore\n", + contact_uri.len, contact_uri.s); + ul.release_ucontact(ucontact); + goto next_implicit_impu; + } + } + ul.release_ucontact(ucontact); + } + next_implicit_impu: + ul.unlock_udomain(_d, &pi->public_identity); + } + } + + if(contact_state == STATE_TERMINATED) { + //at this point we can assume that all notifies were sent out to the subscribers of the IMPUs related to the explicit and implicit impus. + //we must now change the state of the contact to deleted so they can be removed from the IMPU in the timer process... + if(ul.get_ucontact(&contact_uri, &callid, &path, 0 /*cseq*/, &ucontact) + != 0) { //contact does not exist + LM_DBG("This contact: <%.*s> is not in usrloc, ignore - NOTE: You " + "need S-CSCF usrloc set to match_mode CONTACT_ONLY\n", + contact_uri.len, contact_uri.s); + } else { + ul.lock_contact_slot(&contact_uri); + ucontact->state = CONTACT_DELETED; + ul.unlock_contact_slot(&contact_uri); + ul.release_ucontact(ucontact); + } + } + + // ul.lock_subscription(subscription); + // subscription->ref_count--; + // LM_DBG("subscription ref count after sub is now %d\n", subscription->ref_count); + // ul.unlock_subscription(subscription); + + // ul.lock_udomain(_d, &presentity_impurecord->public_identity); + + // if (ul.get_ucontact(&contact_uri, &callid, &path, 0/*cseq*/, &ucontact) != 0) { //contact does not exist + // LM_DBG("This contact: <%.*s> is not in usrloc, ignore - NOTE: You need S-CSCF usrloc set to match_mode CONTACT_ONLY\n", contact_uri.len, contact_uri.s); + // return ret; + // } else {//contact exists + // if (VALID_CONTACT(ucontact, act_time)) { + // if (contact_state == STATE_TERMINATED) { + // //delete contact + // LM_DBG("This contact <%.*s> is in state terminated and is in usrloc so removing it from usrloc\n", contact_uri.len, contact_uri.s); + //// ul.lock_contact_slot(&contact_uri); + //// if (ul.unlink_contact_from_impu(presentity_impurecord, ucontact, 1, 0 /*implicit dereg of contact from IMPU */) != 0) { + //// LM_ERR("Failed to delete ucontact <%.*s>\n", contact_uri.len, contact_uri.s); + //// ret = CSCF_RETURN_FALSE; + //// ul.unlock_contact_slot(&contact_uri); + //// ul.release_ucontact(ucontact); + //// goto done; + //// } + //// ul.unlock_contact_slot(&contact_uri); + // ucontact->state = CONTACT_DELETE_PENDING; + // if (implicit_impurecord->shead) { + // //send NOTIFY to all subscribers of this IMPU. + // notify_subscribers(implicit_impurecord); + // } + // } else {//state is active + // LM_DBG("This contact: <%.*s> is not in state terminated and is in usrloc, ignore\n", contact_uri.len, contact_uri.s); + // ul.release_ucontact(ucontact); + // goto done; + // } + // } + // ul.release_ucontact(ucontact); + // } + + //done: + // ul.unlock_udomain(_d, &presentity_impurecord->public_identity); + return ret; } -int reginfo_parse_state(char * s) { - if (s == NULL) { - return STATE_UNKNOWN; - } - switch (strlen(s)) { - case 6: - if (strncmp(s, "active", 6) == 0) return STATE_ACTIVE; - break; - case 10: - if (strncmp(s, "terminated", 10) == 0) return STATE_TERMINATED; - break; - default: - LM_ERR("Unknown State %s\n", s); - return STATE_UNKNOWN; - } - LM_ERR("Unknown State %s\n", s); - return STATE_UNKNOWN; +int reginfo_parse_state(char *s) +{ + if(s == NULL) { + return STATE_UNKNOWN; + } + switch(strlen(s)) { + case 6: + if(strncmp(s, "active", 6) == 0) + return STATE_ACTIVE; + break; + case 10: + if(strncmp(s, "terminated", 10) == 0) + return STATE_TERMINATED; + break; + default: + LM_ERR("Unknown State %s\n", s); + return STATE_UNKNOWN; + } + LM_ERR("Unknown State %s\n", s); + return STATE_UNKNOWN; } -int reginfo_parse_event(char * s) { - if (s == NULL) { - return EVENT_UNKNOWN; - } - switch (strlen(s)) { - case 7: - if (strncmp(s, "created", 7) == 0) return EVENT_CREATED; - if (strncmp(s, "expired", 7) == 0) return EVENT_EXPIRED; - break; - case 9: - if (strncmp(s, "refreshed", 9) == 0) return EVENT_CREATED; - break; - case 10: - if (strncmp(s, "registered", 10) == 0) return EVENT_REGISTERED; - if (strncmp(s, "terminated", 10) == 0) return EVENT_TERMINATED; - break; - case 12: - if (strncmp(s, "unregistered", 12) == 0) return EVENT_UNREGISTERED; - break; - default: - LM_ERR("Unknown Event %s\n", s); - return EVENT_UNKNOWN; - } - LM_ERR("Unknown Event %s\n", s); - return EVENT_UNKNOWN; +int reginfo_parse_event(char *s) +{ + if(s == NULL) { + return EVENT_UNKNOWN; + } + switch(strlen(s)) { + case 7: + if(strncmp(s, "created", 7) == 0) + return EVENT_CREATED; + if(strncmp(s, "expired", 7) == 0) + return EVENT_EXPIRED; + break; + case 9: + if(strncmp(s, "refreshed", 9) == 0) + return EVENT_CREATED; + break; + case 10: + if(strncmp(s, "registered", 10) == 0) + return EVENT_REGISTERED; + if(strncmp(s, "terminated", 10) == 0) + return EVENT_TERMINATED; + break; + case 12: + if(strncmp(s, "unregistered", 12) == 0) + return EVENT_UNREGISTERED; + break; + default: + LM_ERR("Unknown Event %s\n", s); + return EVENT_UNKNOWN; + } + LM_ERR("Unknown Event %s\n", s); + return EVENT_UNKNOWN; } -xmlNodePtr xmlGetNodeByName(xmlNodePtr parent, const char *name) { - xmlNodePtr cur = parent; - xmlNodePtr match = NULL; - while (cur) { - if (xmlStrcasecmp(cur->name, (unsigned char*) name) == 0) - return cur; - match = xmlGetNodeByName(cur->children, name); - if (match) - return match; - cur = cur->next; - } - return NULL; +xmlNodePtr xmlGetNodeByName(xmlNodePtr parent, const char *name) +{ + xmlNodePtr cur = parent; + xmlNodePtr match = NULL; + while(cur) { + if(xmlStrcasecmp(cur->name, (unsigned char *)name) == 0) + return cur; + match = xmlGetNodeByName(cur->children, name); + if(match) + return match; + cur = cur->next; + } + return NULL; } -char * xmlGetAttrContentByName(xmlNodePtr node, const char *name) { - xmlAttrPtr attr = node->properties; - while (attr) { - if (xmlStrcasecmp(attr->name, (unsigned char*) name) == 0) - return (char*) xmlNodeGetContent(attr->children); - attr = attr->next; - } - return NULL; +char *xmlGetAttrContentByName(xmlNodePtr node, const char *name) +{ + xmlAttrPtr attr = node->properties; + while(attr) { + if(xmlStrcasecmp(attr->name, (unsigned char *)name) == 0) + return (char *)xmlNodeGetContent(attr->children); + attr = attr->next; + } + return NULL; } -int process_publish_body(struct sip_msg* msg, str publish_body, udomain_t * domain) { - xmlDocPtr doc = NULL; - xmlNodePtr doc_root = NULL, registrations = NULL, contacts = NULL, uris = NULL; - str aor = {0, 0}; - str callid = {0, 0}; - str contact_uri = {0, 0}; - str received = {0, 0}; - str path = {0, 0}; - str user_agent = {0, 0}; - int reg_state, contact_state, event, expires, result, final_result = CSCF_RETURN_FALSE; - char * expires_char, * cseq_char; - int cseq = 0; - impurecord_t* presentity_impurecord; - ims_subscription* subscription = 0; - int subscription_locked; - - doc = xmlParseMemory(publish_body.s, publish_body.len); - if (doc == NULL) { - LM_ERR("Error while parsing the xml body message, Body is:\n%.*s\n", - publish_body.len, publish_body.s); - return -1; - } - doc_root = xmlGetNodeByName(doc->children, "reginfo"); - if (doc_root == NULL) { - LM_ERR("while extracting the reginfo node\n"); - goto error; - } - registrations = doc_root->children; - while (registrations) { - subscription_locked = 0; - /* Only process registration sub-items */ - if (xmlStrcasecmp(registrations->name, BAD_CAST "registration") != 0) - goto next_registration; - reg_state = reginfo_parse_state(xmlGetAttrContentByName(registrations, "state")); - aor.s = xmlGetAttrContentByName(registrations, "aor"); - if (aor.s == NULL) { - LM_ERR("No AOR for this registration!\n"); - goto next_registration; - } - aor.len = strlen(aor.s); - LM_DBG("AOR %.*s has reg_state \"%d\"\n", aor.len, aor.s, reg_state); - - //TOD get IMPU record here - ul.lock_udomain(domain, &aor); - if (ul.get_impurecord(domain, &aor, &presentity_impurecord) != 0) { - LM_DBG("usrloc does not have impurecord for presentity being published too, ignore\n"); - ul.unlock_udomain(domain, &aor); - goto next_registration; - } - //get the subscription which we will use later - - subscription = presentity_impurecord->s; - if (!subscription) { - LM_DBG("No subscriber info associated with <%.*s>, so no implicit IMPUs to process\n", presentity_impurecord->public_identity.len, presentity_impurecord->public_identity.s); - ul.unlock_udomain(domain, &aor); - goto next_registration; - } - ul.lock_subscription(subscription); - subscription->ref_count++; - LM_DBG("subscription ref count after add is now %d\n", subscription->ref_count); - ul.unlock_subscription(subscription); - subscription_locked = 1; - - ul.unlock_udomain(domain, &aor); - - LM_DBG("Received impurecord for presentity being published on [%.*s]\n", aor.len, aor.s); - - if (reg_state == STATE_TERMINATED) { - LM_DBG("This impurecord is in STATE_TERMINATED - TODO we should should delete all contacts\n"); - } else { - /* Now lets process the Contact's from this Registration: */ - contacts = registrations->children; - while (contacts) { - if (xmlStrcasecmp(contacts->name, BAD_CAST "contact") != 0) - goto next_contact; - callid.s = xmlGetAttrContentByName(contacts, "callid"); - if (callid.s == NULL) { - LM_DBG("No Call-ID for this contact!\n"); - callid.len = 0; - } else { - callid.len = strlen(callid.s); - LM_DBG("contact has callid <%.*s>\n", callid.len, callid.s); - } - - received.s = xmlGetAttrContentByName(contacts, "received"); - if (received.s == NULL) { - LM_DBG("No received for this contact!\n"); - received.len = 0; - } else { - received.len = strlen(received.s); - LM_DBG("contact has received <%.*s>\n", received.len, received.s); - } - - path.s = xmlGetAttrContentByName(contacts, "path"); - if (path.s == NULL) { - LM_DBG("No path for this contact!\n"); - path.len = 0; - } else { - path.len = strlen(path.s); - LM_DBG("contact has path <%.*s>\n", path.len, path.s); - } - - user_agent.s = xmlGetAttrContentByName(contacts, "user_agent"); - if (user_agent.s == NULL) { - LM_DBG("No user_agent for this contact!\n"); - user_agent.len = 0; - } else { - user_agent.len = strlen(user_agent.s); - LM_DBG("contact has user_agent <%.*s>\n", user_agent.len, user_agent.s); - } - event = reginfo_parse_event(xmlGetAttrContentByName(contacts, "event")); - if (event == EVENT_UNKNOWN) { - LM_ERR("No event for this contact - going to next contact!\n"); - goto next_contact; - } - expires_char = xmlGetAttrContentByName(contacts, "expires"); - if (expires_char == NULL) { - LM_ERR("No expires for this contact - going to next contact!\n"); - goto next_contact; - } - expires = atoi(expires_char); - if (expires < 0) { - LM_ERR("No valid expires for this contact - going to next contact!\n"); - goto next_contact; - } - - contact_state = reginfo_parse_state(xmlGetAttrContentByName(contacts, "state")); - if (contact_state == STATE_UNKNOWN) { - LM_ERR("No state for this contact - going to next contact!\n"); - goto next_contact; - } - - LM_DBG("Contact state %d: Event \"%d\", expires %d\n", contact_state, event, expires); - - cseq_char = xmlGetAttrContentByName(contacts, "cseq"); - if (cseq_char == NULL) { - LM_DBG("No cseq for this contact!\n"); - } else { - cseq = atoi(cseq_char); - if (cseq < 0) { - LM_DBG("No valid cseq for this contact!\n"); - } - } - - /* Now lets process the URI's from this Contact: */ - uris = contacts->children; - while (uris) { - if (xmlStrcasecmp(uris->name, BAD_CAST "uri") != 0) - goto next_uri; - contact_uri.s = (char*) xmlNodeGetContent(uris); - if (contact_uri.s == NULL) { - LM_ERR("No URI for this contact - going to next registration!\n"); - goto next_registration; - } - contact_uri.len = strlen(contact_uri.s); - LM_DBG("Contact: %.*s\n", - contact_uri.len, contact_uri.s); - - /* Add to Usrloc: */ - result = process_contact(subscription, domain, expires, contact_uri, contact_state); - - /* Process the result */ - if (final_result != CSCF_RETURN_TRUE) final_result = result; -next_uri: - uris = uris->next; - } -next_contact: - contacts = contacts->next; - } - } -next_registration: - registrations = registrations->next; - if (subscription_locked) { - ul.lock_subscription(subscription); - subscription->ref_count--; - LM_DBG("subscription ref count after sub is now %d\n", subscription->ref_count); - ul.unlock_subscription(subscription); - } - } +int process_publish_body( + struct sip_msg *msg, str publish_body, udomain_t *domain) +{ + xmlDocPtr doc = NULL; + xmlNodePtr doc_root = NULL, registrations = NULL, contacts = NULL, + uris = NULL; + str aor = {0, 0}; + str callid = {0, 0}; + str contact_uri = {0, 0}; + str received = {0, 0}; + str path = {0, 0}; + str user_agent = {0, 0}; + int reg_state, contact_state, event, expires, result, + final_result = CSCF_RETURN_FALSE; + char *expires_char, *cseq_char; + int cseq = 0; + impurecord_t *presentity_impurecord; + ims_subscription *subscription = 0; + int subscription_locked; + + doc = xmlParseMemory(publish_body.s, publish_body.len); + if(doc == NULL) { + LM_ERR("Error while parsing the xml body message, Body is:\n%.*s\n", + publish_body.len, publish_body.s); + return -1; + } + doc_root = xmlGetNodeByName(doc->children, "reginfo"); + if(doc_root == NULL) { + LM_ERR("while extracting the reginfo node\n"); + goto error; + } + registrations = doc_root->children; + while(registrations) { + subscription_locked = 0; + /* Only process registration sub-items */ + if(xmlStrcasecmp(registrations->name, BAD_CAST "registration") != 0) + goto next_registration; + reg_state = reginfo_parse_state( + xmlGetAttrContentByName(registrations, "state")); + aor.s = xmlGetAttrContentByName(registrations, "aor"); + if(aor.s == NULL) { + LM_ERR("No AOR for this registration!\n"); + goto next_registration; + } + aor.len = strlen(aor.s); + LM_DBG("AOR %.*s has reg_state \"%d\"\n", aor.len, aor.s, reg_state); + + //TOD get IMPU record here + ul.lock_udomain(domain, &aor); + if(ul.get_impurecord(domain, &aor, &presentity_impurecord) != 0) { + LM_DBG("usrloc does not have impurecord for presentity being " + "published too, ignore\n"); + ul.unlock_udomain(domain, &aor); + goto next_registration; + } + //get the subscription which we will use later + + subscription = presentity_impurecord->s; + if(!subscription) { + LM_DBG("No subscriber info associated with <%.*s>, so no implicit " + "IMPUs to process\n", + presentity_impurecord->public_identity.len, + presentity_impurecord->public_identity.s); + ul.unlock_udomain(domain, &aor); + goto next_registration; + } + ul.lock_subscription(subscription); + subscription->ref_count++; + LM_DBG("subscription ref count after add is now %d\n", + subscription->ref_count); + ul.unlock_subscription(subscription); + subscription_locked = 1; + + ul.unlock_udomain(domain, &aor); + + LM_DBG("Received impurecord for presentity being published on [%.*s]\n", + aor.len, aor.s); + + if(reg_state == STATE_TERMINATED) { + LM_DBG("This impurecord is in STATE_TERMINATED - TODO we should " + "should delete all contacts\n"); + } else { + /* Now lets process the Contact's from this Registration: */ + contacts = registrations->children; + while(contacts) { + if(xmlStrcasecmp(contacts->name, BAD_CAST "contact") != 0) + goto next_contact; + callid.s = xmlGetAttrContentByName(contacts, "callid"); + if(callid.s == NULL) { + LM_DBG("No Call-ID for this contact!\n"); + callid.len = 0; + } else { + callid.len = strlen(callid.s); + LM_DBG("contact has callid <%.*s>\n", callid.len, callid.s); + } + + received.s = xmlGetAttrContentByName(contacts, "received"); + if(received.s == NULL) { + LM_DBG("No received for this contact!\n"); + received.len = 0; + } else { + received.len = strlen(received.s); + LM_DBG("contact has received <%.*s>\n", received.len, + received.s); + } + + path.s = xmlGetAttrContentByName(contacts, "path"); + if(path.s == NULL) { + LM_DBG("No path for this contact!\n"); + path.len = 0; + } else { + path.len = strlen(path.s); + LM_DBG("contact has path <%.*s>\n", path.len, path.s); + } + + user_agent.s = xmlGetAttrContentByName(contacts, "user_agent"); + if(user_agent.s == NULL) { + LM_DBG("No user_agent for this contact!\n"); + user_agent.len = 0; + } else { + user_agent.len = strlen(user_agent.s); + LM_DBG("contact has user_agent <%.*s>\n", user_agent.len, + user_agent.s); + } + event = reginfo_parse_event( + xmlGetAttrContentByName(contacts, "event")); + if(event == EVENT_UNKNOWN) { + LM_ERR("No event for this contact - going to next " + "contact!\n"); + goto next_contact; + } + expires_char = xmlGetAttrContentByName(contacts, "expires"); + if(expires_char == NULL) { + LM_ERR("No expires for this contact - going to next " + "contact!\n"); + goto next_contact; + } + expires = atoi(expires_char); + if(expires < 0) { + LM_ERR("No valid expires for this contact - going to next " + "contact!\n"); + goto next_contact; + } + + contact_state = reginfo_parse_state( + xmlGetAttrContentByName(contacts, "state")); + if(contact_state == STATE_UNKNOWN) { + LM_ERR("No state for this contact - going to next " + "contact!\n"); + goto next_contact; + } + + LM_DBG("Contact state %d: Event \"%d\", expires %d\n", + contact_state, event, expires); + + cseq_char = xmlGetAttrContentByName(contacts, "cseq"); + if(cseq_char == NULL) { + LM_DBG("No cseq for this contact!\n"); + } else { + cseq = atoi(cseq_char); + if(cseq < 0) { + LM_DBG("No valid cseq for this contact!\n"); + } + } + + /* Now lets process the URI's from this Contact: */ + uris = contacts->children; + while(uris) { + if(xmlStrcasecmp(uris->name, BAD_CAST "uri") != 0) + goto next_uri; + contact_uri.s = (char *)xmlNodeGetContent(uris); + if(contact_uri.s == NULL) { + LM_ERR("No URI for this contact - going to next " + "registration!\n"); + goto next_registration; + } + contact_uri.len = strlen(contact_uri.s); + LM_DBG("Contact: %.*s\n", contact_uri.len, contact_uri.s); + + /* Add to Usrloc: */ + result = process_contact(subscription, domain, expires, + contact_uri, contact_state); + + /* Process the result */ + if(final_result != CSCF_RETURN_TRUE) + final_result = result; + next_uri: + uris = uris->next; + } + next_contact: + contacts = contacts->next; + } + } + next_registration: + registrations = registrations->next; + if(subscription_locked) { + ul.lock_subscription(subscription); + subscription->ref_count--; + LM_DBG("subscription ref count after sub is now %d\n", + subscription->ref_count); + ul.unlock_subscription(subscription); + } + } error: - /* Free the XML-Document */ - if (doc) xmlFreeDoc(doc); - return final_result; + /* Free the XML-Document */ + if(doc) + xmlFreeDoc(doc); + return final_result; } /** @@ -936,49 +1046,52 @@ int process_publish_body(struct sip_msg* msg, str publish_body, udomain_t * doma * @param str2 - not used * @returns #CSCF_RETURN_TRUE if allowed, #CSCF_RETURN_FALSE if not, #CSCF_RETURN_ERROR on error */ -int publish_reg(struct sip_msg *msg, char *_t, char *str2) { - - udomain_t* domain = (udomain_t*) _t; - int expires = 0; - int ret = CSCF_RETURN_FALSE; - str body; - - LM_DBG("Publishing reg info\n"); - - - /* If not done yet, parse the whole message now: */ - if (parse_headers(msg, HDR_EOH_F, 0) == -1) { - LM_ERR("Error parsing headers\n"); - return -1; - } - if (get_content_length(msg) == 0) { - LM_DBG("Content length = 0\n"); - /* No Body? Then there is no published information available, which is ok. */ - goto done; - } else { - body.s = get_body(msg); - if (body.s == NULL) { - LM_ERR("cannot extract body from msg\n"); - goto done; - } - body.len = get_content_length(msg); - } - - LM_DBG("Body is %.*s\n", body.len, body.s); - - ret = process_publish_body(msg, body, (udomain_t*) domain); +int publish_reg(struct sip_msg *msg, char *_t, char *str2) +{ + + udomain_t *domain = (udomain_t *)_t; + int expires = 0; + int ret = CSCF_RETURN_FALSE; + str body; + + LM_DBG("Publishing reg info\n"); -done: - //get expires - expires = cscf_get_expires_hdr(msg, 0); - if (expires == -1) expires = subscription_default_expires; - if (ret == CSCF_RETURN_TRUE) { - LM_DBG("Sending 200 OK to publishing user\n"); - subscribe_reply(msg, 200, MSG_REG_PUBLISH_OK, &expires, &scscf_name_str); - } + /* If not done yet, parse the whole message now: */ + if(parse_headers(msg, HDR_EOH_F, 0) == -1) { + LM_ERR("Error parsing headers\n"); + return -1; + } + if(get_content_length(msg) == 0) { + LM_DBG("Content length = 0\n"); + /* No Body? Then there is no published information available, which is ok. */ + goto done; + } else { + body.s = get_body(msg); + if(body.s == NULL) { + LM_ERR("cannot extract body from msg\n"); + goto done; + } + body.len = get_content_length(msg); + } + + LM_DBG("Body is %.*s\n", body.len, body.s); + + ret = process_publish_body(msg, body, (udomain_t *)domain); + +done: + //get expires + expires = cscf_get_expires_hdr(msg, 0); + if(expires == -1) + expires = subscription_default_expires; + + if(ret == CSCF_RETURN_TRUE) { + LM_DBG("Sending 200 OK to publishing user\n"); + subscribe_reply( + msg, 200, MSG_REG_PUBLISH_OK, &expires, &scscf_name_str); + } - return ret; + return ret; } /** @@ -988,243 +1101,284 @@ int publish_reg(struct sip_msg *msg, char *_t, char *str2) { * @param str2 - not used * @returns #CSCF_RETURN_TRUE if allowed, #CSCF_RETURN_FALSE if not, #CSCF_RETURN_ERROR on error */ -int subscribe_to_reg(struct sip_msg *msg, char *_t, char *str2) { - int ret = CSCF_RETURN_FALSE; - int res; - str presentity_uri = {0, 0}; - str event; - int event_i = IMS_EVENT_NONE; - int expires = 0, expires_time = 0; - str watcher_impu; - str watcher_contact; - impurecord_t* presentity_impurecord; - reg_subscriber *reg_subscriber; - subscriber_data_t subscriber_data; - - int event_type = IMS_REGISTRAR_NONE; - - int rt = 0; - - str callid = {0, 0}; - str ftag = {0, 0}; - str ttag = {0, 0}; - str record_route = {0, 0}; - - int remote_cseq = 0; - int local_cseq = 0; - - udomain_t* domain = (udomain_t*) _t; - - LM_DBG("Saving SUBSCRIBE\n"); - - //check we have a valid transaction, if not, create one TODO - - //check that this is a request - if (msg->first_line.type != SIP_REQUEST) { - LM_ERR("This message is not a request\n"); - ret = CSCF_RETURN_FALSE; - goto doneorerror; - } - - //check that this is a subscribe - if (msg->first_line.type != SIP_REQUEST || msg->first_line.u.request.method_value != METHOD_SUBSCRIBE) { - LM_ERR("This message is not a SUBSCRIBE\n"); - ret = CSCF_RETURN_FALSE; - goto doneorerror; - } - - //check that this is a reg event - we currently only support reg event - event = cscf_get_event(msg); - if (event.len != 3 || strncasecmp(event.s, "reg", 3) != 0) { - LM_WARN("Accepting only . Found: <%.*s>\n", - event.len, event.s); - ret = CSCF_RETURN_FALSE; - goto doneorerror; - } - event_i = IMS_EVENT_REG; - - //get callid, from and to tags to be able to identify dialog - //callid - callid = cscf_get_call_id(msg, 0); - if (callid.len <= 0 || !callid.s) { - LM_ERR("unable to get callid\n"); - ret = CSCF_RETURN_FALSE; - goto doneorerror; - } - //ftag - if (!cscf_get_from_tag(msg, &ftag)) { - LM_ERR("Unable to get ftag\n"); - ret = CSCF_RETURN_FALSE; - goto doneorerror; - } - - //ttag - if (!cscf_get_to_tag(msg, &ttag)) { - LM_ERR("Unable to get ttag\n"); - ret = CSCF_RETURN_FALSE; - goto doneorerror; - } - - //check if SUBSCRIBE is initial or SUBSEQUENT - if (ttag.len == 0) { - LM_DBG("Msg has no ttag - this is initial subscribe\n"); - //to tag - doesn't exist in initial request, must use tm to get it - tmb.t_get_reply_totag(msg, &ttag); - LM_DBG("Got to tag from sent response: [%.*s]\n", ttag.len, ttag.s); - LM_DBG("This is initial subscribe - get presentity URI from req URI\n"); - presentity_uri = cscf_get_public_identity_from_requri(msg); +int subscribe_to_reg(struct sip_msg *msg, char *_t, char *str2) +{ + int ret = CSCF_RETURN_FALSE; + int res; + str presentity_uri = {0, 0}; + str event; + int event_i = IMS_EVENT_NONE; + int expires = 0, expires_time = 0; + str watcher_impu; + str watcher_contact; + impurecord_t *presentity_impurecord; + reg_subscriber *reg_subscriber; + subscriber_data_t subscriber_data; + + int event_type = IMS_REGISTRAR_NONE; + + int rt = 0; + + str callid = {0, 0}; + str ftag = {0, 0}; + str ttag = {0, 0}; + str record_route = {0, 0}; + + int remote_cseq = 0; + int local_cseq = 0; + + udomain_t *domain = (udomain_t *)_t; + + LM_DBG("Saving SUBSCRIBE\n"); + + //check we have a valid transaction, if not, create one TODO + + //check that this is a request + if(msg->first_line.type != SIP_REQUEST) { + LM_ERR("This message is not a request\n"); + ret = CSCF_RETURN_FALSE; + goto doneorerror; + } + + //check that this is a subscribe + if(msg->first_line.type != SIP_REQUEST + || msg->first_line.u.request.method_value != METHOD_SUBSCRIBE) { + LM_ERR("This message is not a SUBSCRIBE\n"); + ret = CSCF_RETURN_FALSE; + goto doneorerror; + } + + //check that this is a reg event - we currently only support reg event + event = cscf_get_event(msg); + if(event.len != 3 || strncasecmp(event.s, "reg", 3) != 0) { + LM_WARN("Accepting only . Found: <%.*s>\n", event.len, + event.s); + ret = CSCF_RETURN_FALSE; + goto doneorerror; + } + event_i = IMS_EVENT_REG; + + //get callid, from and to tags to be able to identify dialog + //callid + callid = cscf_get_call_id(msg, 0); + if(callid.len <= 0 || !callid.s) { + LM_ERR("unable to get callid\n"); + ret = CSCF_RETURN_FALSE; + goto doneorerror; + } + //ftag + if(!cscf_get_from_tag(msg, &ftag)) { + LM_ERR("Unable to get ftag\n"); + ret = CSCF_RETURN_FALSE; + goto doneorerror; + } + + //ttag + if(!cscf_get_to_tag(msg, &ttag)) { + LM_ERR("Unable to get ttag\n"); + ret = CSCF_RETURN_FALSE; + goto doneorerror; + } + + //check if SUBSCRIBE is initial or SUBSEQUENT + if(ttag.len == 0) { + LM_DBG("Msg has no ttag - this is initial subscribe\n"); + //to tag - doesn't exist in initial request, must use tm to get it + tmb.t_get_reply_totag(msg, &ttag); + LM_DBG("Got to tag from sent response: [%.*s]\n", ttag.len, ttag.s); + LM_DBG("This is initial subscribe - get presentity URI from req URI\n"); + presentity_uri = cscf_get_public_identity_from_requri(msg); event_type = IMS_REGISTRAR_SUBSCRIBE; - } else { - LM_DBG("Msg has ttag: [%.*s] - this is subsequent subscribe\n", ttag.len, ttag.s); - //cscf_get_to_uri(msg, &presentity_uri); - LM_DBG("This is subsequent subscribe - get presentity URI from stored subscriber dialog\n"); - //get the presentity uri from To Header - //cscf_get_to_uri(msg, &presentity_uri); - presentity_uri = ul.get_presentity_from_subscriber_dialog(&callid, &ttag, &ftag); - if (presentity_uri.len == 0) { - LM_ERR("Unable to get presentity uri from subscriber dialog with callid <%.*s>, ttag <%.*s> and ftag <%.*s>\n", - callid.len, callid.s, ttag.len, ttag.s, ftag.len, ftag.s); - ret = CSCF_RETURN_FALSE; - goto doneorerror; - } + } else { + LM_DBG("Msg has ttag: [%.*s] - this is subsequent subscribe\n", + ttag.len, ttag.s); + //cscf_get_to_uri(msg, &presentity_uri); + LM_DBG("This is subsequent subscribe - get presentity URI from stored " + "subscriber dialog\n"); + //get the presentity uri from To Header + //cscf_get_to_uri(msg, &presentity_uri); + presentity_uri = + ul.get_presentity_from_subscriber_dialog(&callid, &ttag, &ftag); + if(presentity_uri.len == 0) { + LM_ERR("Unable to get presentity uri from subscriber dialog with " + "callid <%.*s>, ttag <%.*s> and ftag <%.*s>\n", + callid.len, callid.s, ttag.len, ttag.s, ftag.len, ftag.s); + ret = CSCF_RETURN_FALSE; + goto doneorerror; + } event_type = IMS_REGISTRAR_SUBSEQUENT_SUBSCRIBE; - } - - //get cseq - remote_cseq = cscf_get_cseq(msg, 0); - local_cseq = remote_cseq + 1; - - //get sockinfo_str - str sockinfo_str = msg->rcv.bind_address->sock_str; - - //get record route - /*process record route and add it to a string*/ - if (msg->record_route != NULL) { - rt = print_rr_body(msg->record_route, &record_route, 0, 0); - if (rt != 0) { - LM_ERR("Failed processing the record route [%d]\n", rt); - record_route.s = NULL; - record_route.len = 0; - ret = CSCF_RETURN_FALSE; - goto doneorerror; - } - } - - //get the presentity uri from To Header - //cscf_get_to_uri(msg, &presentity_uri); - - //get the watcher uri from the to header - cscf_get_from_uri(msg, &watcher_impu); - - if (!watcher_impu.len) { - LM_ERR("Failed to get URI from To header.\n"); - ret = CSCF_RETURN_FALSE; - goto doneorerror; - } - LM_DBG("To header URI (watcher URI) <%.*s>.\n", watcher_impu.len, watcher_impu.s); - - //get the watcher contact from contact header - watcher_contact = cscf_get_contact(msg); - if (!watcher_contact.len) { - LM_ERR("ERR: Contact empty.\n"); - ret = CSCF_RETURN_FALSE; - goto doneorerror; - } - LM_DBG("watcher Contact <%.*s>.\n", watcher_contact.len, watcher_contact.s); - - //get expires - expires = cscf_get_expires_hdr(msg, 0); - if (expires == -1) expires = subscription_default_expires; - - //build subscriber parcel for passing data around more easily - subscriber_data.callid = &callid; - subscriber_data.event = event_i; - subscriber_data.ftag = &ftag; - subscriber_data.ttag = &ttag; - subscriber_data.record_route = &record_route; - subscriber_data.sockinfo_str = &sockinfo_str; - subscriber_data.local_cseq = local_cseq; - subscriber_data.watcher_uri = &watcher_impu; - subscriber_data.watcher_contact = &watcher_contact; - subscriber_data.version = 1; /*default version starts at 1*/ - - if (expires > 0) { - LM_DBG("expires is more than zero - SUBSCRIBE\n"); - - if (expires < subscription_min_expires) expires = subscription_min_expires; - if (expires > subscription_max_expires) expires = subscription_max_expires; - expires = randomize_expires(expires, subscription_expires_range); - get_act_time(); - expires_time = expires + act_time; - subscriber_data.expires = expires_time; - - LM_DBG("Subscription expires time <%d> expiry length <%d>\n", - expires_time, expires); - - LM_DBG("Received a new subscription (expires > 0), checking to see of impurecord for presentity exists\n"); - ul.lock_udomain(domain, &presentity_uri); - res = ul.get_impurecord(domain, &presentity_uri, &presentity_impurecord); - if (res != 0) { - LM_WARN("usrloc does not have impurecord for presentity being subscribed too, This a problem we shouldn't get here as offline users should have been assigned in config file\n"); - ul.unlock_udomain(domain, &presentity_uri); - ret = CSCF_RETURN_FALSE; - goto doneorerror; - } - - LM_DBG("Received impurecord for presentity being subscribed to [%.*s]\n", presentity_impurecord->public_identity.len, presentity_impurecord->public_identity.s); - - res = ul.get_subscriber(presentity_impurecord, &presentity_uri, &watcher_contact, event_i, ®_subscriber); - if (res != 0) { - LM_DBG("this must be a new subscriber, lets add it\n"); - subscriber_data.presentity_uri = &presentity_impurecord->public_identity; - res = ul.add_subscriber(presentity_impurecord, &subscriber_data, ®_subscriber, 0 /*not a db_load*/); - if (res != 0) { - LM_ERR("Failed to add new subscription\n"); - ul.unlock_udomain(domain, &presentity_uri); - ret = CSCF_RETURN_FALSE; - goto doneorerror; - } - } else { - if (memcmp(reg_subscriber->call_id.s, subscriber_data.callid->s, reg_subscriber->call_id.len) == 0 && - memcmp(reg_subscriber->from_tag.s, subscriber_data.ftag->s, reg_subscriber->from_tag.len) == 0 && - memcmp(reg_subscriber->to_tag.s, subscriber_data.ttag->s, reg_subscriber->to_tag.len) == 0) { - LM_DBG("This has same callid, fromtag and totag - must be a re subscribe, lets update it\n"); - res = ul.update_subscriber(presentity_impurecord, ®_subscriber, &expires_time, 0, 0); - if (res != 1) { - LM_ERR("Failed to update subscription - expires is %d\n", expires_time); - ul.unlock_udomain(domain, &presentity_uri); - ret = CSCF_RETURN_FALSE; - goto doneorerror; - } - } else { - LM_ERR("Re-subscribe for same watcher_contact, presentity_uri, event but with different callid [%.*s], fromtag [%.*s] and totag [%.*s] for presentity [%.*s] and watcher contact [%.*s] - What happened?\n", - subscriber_data.callid->len, subscriber_data.callid->s, - subscriber_data.ftag->len, subscriber_data.ftag->s, - subscriber_data.ttag->len, subscriber_data.ttag->s, - presentity_impurecord->public_identity.len, presentity_impurecord->public_identity.s, - subscriber_data.watcher_contact->len, subscriber_data.watcher_contact->s); - LM_DBG("Removing old subscriber and adding new one\n"); - subscriber_data.presentity_uri = &presentity_impurecord->public_identity; - ul.external_delete_subscriber(reg_subscriber, (udomain_t*) _t, 0 /*domain is already locked*/); - res = ul.add_subscriber(presentity_impurecord, &subscriber_data, ®_subscriber, 0 /*not a db_load*/); - if (res != 0) { - LM_ERR("Failed to add new subscription\n"); - ul.unlock_udomain(domain, &presentity_uri); - ret = CSCF_RETURN_FALSE; - goto doneorerror; - } - } - } - - ul.unlock_udomain(domain, &presentity_uri); - - ret = CSCF_RETURN_TRUE; - LM_DBG("Sending 200 OK to subscribing user\n"); - subscribe_reply(msg, 200, MSG_REG_SUBSCRIBE_OK, &expires, &scscf_name_str); + } + + //get cseq + remote_cseq = cscf_get_cseq(msg, 0); + local_cseq = remote_cseq + 1; + + //get sockinfo_str + str sockinfo_str = msg->rcv.bind_address->sock_str; + + //get record route + /*process record route and add it to a string*/ + if(msg->record_route != NULL) { + rt = print_rr_body(msg->record_route, &record_route, 0, 0); + if(rt != 0) { + LM_ERR("Failed processing the record route [%d]\n", rt); + record_route.s = NULL; + record_route.len = 0; + ret = CSCF_RETURN_FALSE; + goto doneorerror; + } + } + + //get the presentity uri from To Header + //cscf_get_to_uri(msg, &presentity_uri); + + //get the watcher uri from the to header + cscf_get_from_uri(msg, &watcher_impu); + + if(!watcher_impu.len) { + LM_ERR("Failed to get URI from To header.\n"); + ret = CSCF_RETURN_FALSE; + goto doneorerror; + } + LM_DBG("To header URI (watcher URI) <%.*s>.\n", watcher_impu.len, + watcher_impu.s); + + //get the watcher contact from contact header + watcher_contact = cscf_get_contact(msg); + if(!watcher_contact.len) { + LM_ERR("ERR: Contact empty.\n"); + ret = CSCF_RETURN_FALSE; + goto doneorerror; + } + LM_DBG("watcher Contact <%.*s>.\n", watcher_contact.len, watcher_contact.s); + + //get expires + expires = cscf_get_expires_hdr(msg, 0); + if(expires == -1) + expires = subscription_default_expires; + + //build subscriber parcel for passing data around more easily + subscriber_data.callid = &callid; + subscriber_data.event = event_i; + subscriber_data.ftag = &ftag; + subscriber_data.ttag = &ttag; + subscriber_data.record_route = &record_route; + subscriber_data.sockinfo_str = &sockinfo_str; + subscriber_data.local_cseq = local_cseq; + subscriber_data.watcher_uri = &watcher_impu; + subscriber_data.watcher_contact = &watcher_contact; + subscriber_data.version = 1; /*default version starts at 1*/ + + if(expires > 0) { + LM_DBG("expires is more than zero - SUBSCRIBE\n"); + + if(expires < subscription_min_expires) + expires = subscription_min_expires; + if(expires > subscription_max_expires) + expires = subscription_max_expires; + expires = randomize_expires(expires, subscription_expires_range); + get_act_time(); + expires_time = expires + act_time; + subscriber_data.expires = expires_time; + + LM_DBG("Subscription expires time <%d> expiry length <%d>\n", + expires_time, expires); + + LM_DBG("Received a new subscription (expires > 0), checking to see of " + "impurecord for presentity exists\n"); + ul.lock_udomain(domain, &presentity_uri); + res = ul.get_impurecord( + domain, &presentity_uri, &presentity_impurecord); + if(res != 0) { + LM_WARN("usrloc does not have impurecord for presentity being " + "subscribed too, This a problem we shouldn't get here as " + "offline users should have been assigned in config file\n"); + ul.unlock_udomain(domain, &presentity_uri); + ret = CSCF_RETURN_FALSE; + goto doneorerror; + } + + LM_DBG("Received impurecord for presentity being subscribed to " + "[%.*s]\n", + presentity_impurecord->public_identity.len, + presentity_impurecord->public_identity.s); + + res = ul.get_subscriber(presentity_impurecord, &presentity_uri, + &watcher_contact, event_i, ®_subscriber); + if(res != 0) { + LM_DBG("this must be a new subscriber, lets add it\n"); + subscriber_data.presentity_uri = + &presentity_impurecord->public_identity; + res = ul.add_subscriber(presentity_impurecord, &subscriber_data, + ®_subscriber, 0 /*not a db_load*/); + if(res != 0) { + LM_ERR("Failed to add new subscription\n"); + ul.unlock_udomain(domain, &presentity_uri); + ret = CSCF_RETURN_FALSE; + goto doneorerror; + } + } else { + if(memcmp(reg_subscriber->call_id.s, subscriber_data.callid->s, + reg_subscriber->call_id.len) + == 0 + && memcmp(reg_subscriber->from_tag.s, + subscriber_data.ftag->s, + reg_subscriber->from_tag.len) + == 0 + && memcmp(reg_subscriber->to_tag.s, subscriber_data.ttag->s, + reg_subscriber->to_tag.len) + == 0) { + LM_DBG("This has same callid, fromtag and totag - must be a re " + "subscribe, lets update it\n"); + res = ul.update_subscriber(presentity_impurecord, + ®_subscriber, &expires_time, 0, 0); + if(res != 1) { + LM_ERR("Failed to update subscription - expires is %d\n", + expires_time); + ul.unlock_udomain(domain, &presentity_uri); + ret = CSCF_RETURN_FALSE; + goto doneorerror; + } + } else { + LM_ERR("Re-subscribe for same watcher_contact, presentity_uri, " + "event but with different callid [%.*s], fromtag [%.*s] " + "and totag [%.*s] for presentity [%.*s] and watcher " + "contact [%.*s] - What happened?\n", + subscriber_data.callid->len, subscriber_data.callid->s, + subscriber_data.ftag->len, subscriber_data.ftag->s, + subscriber_data.ttag->len, subscriber_data.ttag->s, + presentity_impurecord->public_identity.len, + presentity_impurecord->public_identity.s, + subscriber_data.watcher_contact->len, + subscriber_data.watcher_contact->s); + LM_DBG("Removing old subscriber and adding new one\n"); + subscriber_data.presentity_uri = + &presentity_impurecord->public_identity; + ul.external_delete_subscriber(reg_subscriber, (udomain_t *)_t, + 0 /*domain is already locked*/); + res = ul.add_subscriber(presentity_impurecord, &subscriber_data, + ®_subscriber, 0 /*not a db_load*/); + if(res != 0) { + LM_ERR("Failed to add new subscription\n"); + ul.unlock_udomain(domain, &presentity_uri); + ret = CSCF_RETURN_FALSE; + goto doneorerror; + } + } + } + + ul.unlock_udomain(domain, &presentity_uri); + + ret = CSCF_RETURN_TRUE; + LM_DBG("Sending 200 OK to subscribing user\n"); + subscribe_reply( + msg, 200, MSG_REG_SUBSCRIBE_OK, &expires, &scscf_name_str); if(event_type == IMS_REGISTRAR_SUBSCRIBE) { //do reg event only for the initial subscribe - if (event_reg(domain, 0, 0, event_type, &presentity_uri, &watcher_contact, 0, 0, 0) != 0) { + if(event_reg(domain, 0, 0, event_type, &presentity_uri, + &watcher_contact, 0, 0, 0) + != 0) { LM_ERR("failed adding notification for reg events\n"); ret = CSCF_RETURN_ERROR; goto doneorerror; @@ -1232,47 +1386,58 @@ int subscribe_to_reg(struct sip_msg *msg, char *_t, char *str2) { LM_DBG("success adding notification for reg events\n"); } } - } else { - event_type = IMS_REGISTRAR_UNSUBSCRIBE; - LM_DBG("expires is zero or less - UNSUBSCRIBE\n"); - - ul.lock_udomain(domain, &presentity_uri); - res = ul.get_impurecord(domain, &presentity_uri, &presentity_impurecord); - if (res != 0) { - LM_DBG("usrloc does not have imprecord for presentity being subscribed too, we should create one.... TODO\n"); - ul.unlock_udomain(domain, &presentity_uri); - goto doneorerror; - } - LM_DBG("Received impurecord for presentity being unsubscribed to [%.*s]\n", presentity_impurecord->public_identity.len, presentity_impurecord->public_identity.s); - // //get the subscription if it exists - LM_DBG("Getting subscription s from usrloc\n"); - - res = ul.get_subscriber(presentity_impurecord, &presentity_uri, &watcher_contact, event_i, ®_subscriber); - if (res != 0) { - LM_WARN("could not get subscriber\n"); - ret = CSCF_RETURN_FALSE; - ul.unlock_udomain(domain, &presentity_uri); - goto doneorerror; - } else { - LM_DBG("subscription s exists\n"); - LM_DBG("deleting subscriber from usrloc\n"); - ul.external_delete_subscriber(reg_subscriber, (udomain_t*) _t, 0 /*domain is already locked*/); - ul.unlock_udomain(domain, &presentity_uri); - } - ret = CSCF_RETURN_TRUE; - LM_DBG("Sending 200 OK to subscribing user\n"); - subscribe_reply(msg, 200, MSG_REG_UNSUBSCRIBE_OK, &expires, &scscf_name_str); - } + } else { + event_type = IMS_REGISTRAR_UNSUBSCRIBE; + LM_DBG("expires is zero or less - UNSUBSCRIBE\n"); + + ul.lock_udomain(domain, &presentity_uri); + res = ul.get_impurecord( + domain, &presentity_uri, &presentity_impurecord); + if(res != 0) { + LM_DBG("usrloc does not have imprecord for presentity being " + "subscribed too, we should create one.... TODO\n"); + ul.unlock_udomain(domain, &presentity_uri); + goto doneorerror; + } + LM_DBG("Received impurecord for presentity being unsubscribed to " + "[%.*s]\n", + presentity_impurecord->public_identity.len, + presentity_impurecord->public_identity.s); + // //get the subscription if it exists + LM_DBG("Getting subscription s from usrloc\n"); + + res = ul.get_subscriber(presentity_impurecord, &presentity_uri, + &watcher_contact, event_i, ®_subscriber); + if(res != 0) { + LM_WARN("could not get subscriber\n"); + ret = CSCF_RETURN_FALSE; + ul.unlock_udomain(domain, &presentity_uri); + goto doneorerror; + } else { + LM_DBG("subscription s exists\n"); + LM_DBG("deleting subscriber from usrloc\n"); + ul.external_delete_subscriber(reg_subscriber, (udomain_t *)_t, + 0 /*domain is already locked*/); + ul.unlock_udomain(domain, &presentity_uri); + } + ret = CSCF_RETURN_TRUE; + LM_DBG("Sending 200 OK to subscribing user\n"); + subscribe_reply( + msg, 200, MSG_REG_UNSUBSCRIBE_OK, &expires, &scscf_name_str); + } doneorerror: - //free memory - if (presentity_uri.s) shm_free(presentity_uri.s); // shm_malloc in cscf_get_public_identity_from_requri or get_presentity_from_subscriber_dialog - if (record_route.s) pkg_free(record_route.s); - return ret; + //free memory + if(presentity_uri.s) + shm_free( + presentity_uri + .s); // shm_malloc in cscf_get_public_identity_from_requri or get_presentity_from_subscriber_dialog + if(record_route.s) + pkg_free(record_route.s); + return ret; } - str expires_hdr1 = {"Expires: ", 9}; str expires_hdr2 = {"\r\n", 2}; str contact_hdr1 = {"Contact: <", 10}; @@ -1288,72 +1453,72 @@ str contact_hdr2 = {">\r\n", 3}; * @param contact - contact to add to reply * @returns the tmn.r_reply returned value value */ -int subscribe_reply(struct sip_msg *msg, int code, char *text, int *expires, str * contact) { - str hdr = {0, 0}; - - if (expires) { - hdr.len = expires_hdr1.len + 12 + expires_hdr1.len; - hdr.s = pkg_malloc(hdr.len); - if (!hdr.s) { - LM_ERR("Error allocating %d bytes.\n", - hdr.len); - } else { - hdr.len = 0; - STR_APPEND(hdr, expires_hdr1); - sprintf(hdr.s + hdr.len, "%d", *expires); - hdr.len += strlen(hdr.s + hdr.len); - STR_APPEND(hdr, expires_hdr2); - cscf_add_header_rpl(msg, &hdr); - pkg_free(hdr.s); - } - } - - if (contact) { - hdr.len = contact_hdr1.len + contact->len + contact_hdr2.len; - hdr.s = pkg_malloc(hdr.len); - if (!hdr.s) { - LM_ERR("Error allocating %d bytes.\n", - hdr.len); - } else { - hdr.len = 0; - STR_APPEND(hdr, contact_hdr1); - STR_APPEND(hdr, *contact); - STR_APPEND(hdr, contact_hdr2); - cscf_add_header_rpl(msg, &hdr); - pkg_free(hdr.s); - } - } - - return tmb.t_reply(msg, code, text); +int subscribe_reply( + struct sip_msg *msg, int code, char *text, int *expires, str *contact) +{ + str hdr = {0, 0}; + + if(expires) { + hdr.len = expires_hdr1.len + 12 + expires_hdr1.len; + hdr.s = pkg_malloc(hdr.len); + if(!hdr.s) { + LM_ERR("Error allocating %d bytes.\n", hdr.len); + } else { + hdr.len = 0; + STR_APPEND(hdr, expires_hdr1); + sprintf(hdr.s + hdr.len, "%d", *expires); + hdr.len += strlen(hdr.s + hdr.len); + STR_APPEND(hdr, expires_hdr2); + cscf_add_header_rpl(msg, &hdr); + pkg_free(hdr.s); + } + } + + if(contact) { + hdr.len = contact_hdr1.len + contact->len + contact_hdr2.len; + hdr.s = pkg_malloc(hdr.len); + if(!hdr.s) { + LM_ERR("Error allocating %d bytes.\n", hdr.len); + } else { + hdr.len = 0; + STR_APPEND(hdr, contact_hdr1); + STR_APPEND(hdr, *contact); + STR_APPEND(hdr, contact_hdr2); + cscf_add_header_rpl(msg, &hdr); + pkg_free(hdr.s); + } + } + return tmb.t_reply(msg, code, text); } /* function to convert contact aor to only have data after @ - ie strip user part */ -int aor_to_contact(str* aor, str* contact) { - char* p; - int ret = 0; //success - - contact->s = aor->s; - contact->len = aor->len; - if (memcmp(aor->s, "sip:", 4) == 0) { - contact->s = aor->s + 4; - contact->len -= 4; - } - - if ((p = memchr(contact->s, '@', contact->len))) { - contact->len -= (p - contact->s + 1); - contact->s = p + 1; - } - - if ((p = memchr(contact->s, ';', contact->len))) { - contact->len = p - contact->s; - } - - if ((p = memchr(contact->s, '>', contact->len))) { - contact->len = p - contact->s; - } - - return ret; +int aor_to_contact(str *aor, str *contact) +{ + char *p; + int ret = 0; //success + + contact->s = aor->s; + contact->len = aor->len; + if(memcmp(aor->s, "sip:", 4) == 0) { + contact->s = aor->s + 4; + contact->len -= 4; + } + + if((p = memchr(contact->s, '@', contact->len))) { + contact->len -= (p - contact->s + 1); + contact->s = p + 1; + } + + if((p = memchr(contact->s, ';', contact->len))) { + contact->len = p - contact->s; + } + + if((p = memchr(contact->s, '>', contact->len))) { + contact->len = p - contact->s; + } + + return ret; } /*! @@ -1362,9 +1527,11 @@ int aor_to_contact(str* aor, str* contact) { * \param c2 contact string 2 * \return 1 when they match, 0 when they not match */ -static int contact_match(str* c1, str* c2) { - LM_DBG("Matching full contact string - comparing [%.*s] and [%.*s]\n", c1->len, c1->s, c2->len, c2->s); - if ((c1->len == c2->len) && !memcmp(c1->s, c2->s, c1->len)) { +static int contact_match(str *c1, str *c2) +{ + LM_DBG("Matching full contact string - comparing [%.*s] and [%.*s]\n", + c1->len, c1->s, c2->len, c2->s); + if((c1->len == c2->len) && !memcmp(c1->s, c2->s, c1->len)) { return 1; } @@ -1377,17 +1544,20 @@ static int contact_match(str* c1, str* c2) { * \param _c contact string * \return ptr on successfull match, 0 when they not match */ -int contact_port_ip_match(str *c1, str *c2) { - - str ip_port1, ip_port2; - aor_to_contact(c1, &ip_port1); //strip userpart from test contact - aor_to_contact(c2, &ip_port2); //strip userpart from test contact - LM_DBG("Matching contact using only port and ip - comparing [%.*s] and [%.*s]\n", - ip_port1.len, ip_port1.s, ip_port2.len, ip_port2.s); - if ((ip_port1.len == ip_port2.len) && !memcmp(ip_port1.s, ip_port2.s, ip_port1.len)) { - return 1; - } - return 0; +int contact_port_ip_match(str *c1, str *c2) +{ + + str ip_port1, ip_port2; + aor_to_contact(c1, &ip_port1); //strip userpart from test contact + aor_to_contact(c2, &ip_port2); //strip userpart from test contact + LM_DBG("Matching contact using only port and ip - comparing [%.*s] and " + "[%.*s]\n", + ip_port1.len, ip_port1.s, ip_port2.len, ip_port2.s); + if((ip_port1.len == ip_port2.len) + && !memcmp(ip_port1.s, ip_port2.s, ip_port1.len)) { + return 1; + } + return 0; } /*! @@ -1396,26 +1566,29 @@ int contact_port_ip_match(str *c1, str *c2) { * \param port_ip extracted ip and port * \return 0 on successfull, 1 failed */ -static int extract_alias_ip_port(str* contact, str* port_ip) { - char* p, *port_s; +static int extract_alias_ip_port(str *contact, str *port_ip) +{ + char *p, *port_s; int tmp_len; port_ip->s = contact->s; port_ip->len = contact->len; // if NULL -> alias is not present - if (port_ip->len > 6 && (p = _strnistr(port_ip->s, "alias=", port_ip->len)) != NULL) { + if(port_ip->len > 6 + && (p = _strnistr(port_ip->s, "alias=", port_ip->len)) != NULL) { // strip all before 'alias=' and 'alias=' itself // this is the length of 'IP~PORT~PROTO' string port_ip->len -= (p - port_ip->s + 6); // this is the IP's starting position port_ip->s = p + 6; - LM_DBG("alias->len=%d [%.*s]\n", port_ip->len, port_ip->len, port_ip->s); + LM_DBG("alias->len=%d [%.*s]\n", port_ip->len, port_ip->len, + port_ip->s); // find the first '~' separates IP from PORT // if NULL -> alias contains only IP - if ((p = memchr(port_ip->s, '~', port_ip->len))) { + if((p = memchr(port_ip->s, '~', port_ip->len))) { // this is the temporary length of 'PORT~PROTO' string tmp_len = port_ip->s + port_ip->len - p - 1; // set PORT starting position @@ -1424,20 +1597,22 @@ static int extract_alias_ip_port(str* contact, str* port_ip) { LM_DBG("port~proto->len=%d [%.*s]\n", tmp_len, tmp_len, port_s); // find the second '~' separates PORT from PROTO - if ((p = memchr(port_s, '~', tmp_len))) { + if((p = memchr(port_s, '~', tmp_len))) { // strip '~PROTO' string tmp_len = (port_ip->len + port_ip->s - p); port_ip->len -= (port_ip->len + port_ip->s - p); LM_DBG("~proto->len=%d [%.*s]\n", tmp_len, tmp_len, p); - }else{ - LM_DBG("No alias proto in contact[%.*s]\n", contact->len, contact->s); + } else { + LM_DBG("No alias proto in contact[%.*s]\n", contact->len, + contact->s); } - }else{ - LM_DBG("No alias port~proto in contact[%.*s]\n", contact->len, contact->s); + } else { + LM_DBG("No alias port~proto in contact[%.*s]\n", contact->len, + contact->s); } - }else{ + } else { LM_DBG("No alias in contact [%.*s]\n", contact->len, contact->s); } @@ -1450,12 +1625,15 @@ static int extract_alias_ip_port(str* contact, str* port_ip) { * \param c2 contact string 2 * \return 1 on successfull match, 0 when they not match */ -static int alias_port_ip_match(str *c1, str *c2) { +static int alias_port_ip_match(str *c1, str *c2) +{ str ip_port1, ip_port2; extract_alias_ip_port(c1, &ip_port1); extract_alias_ip_port(c2, &ip_port2); - LM_DBG("Matching contact alias ip and port - comparing [%.*s] and [%.*s]\n", ip_port1.len, ip_port1.s, ip_port2.len, ip_port2.s); - if ((ip_port1.len == ip_port2.len) && !memcmp(ip_port1.s, ip_port2.s, ip_port1.len)) { + LM_DBG("Matching contact alias ip and port - comparing [%.*s] and [%.*s]\n", + ip_port1.len, ip_port1.s, ip_port2.len, ip_port2.s); + if((ip_port1.len == ip_port2.len) + && !memcmp(ip_port1.s, ip_port2.s, ip_port1.len)) { return 1; } return 0; @@ -1471,91 +1649,121 @@ static str subs_active = {"active;expires=", 15}; * @param content - the body content * @param expires - the remaining subscription expiration time in seconds */ -void create_notifications(udomain_t* _t, impurecord_t* r_passed, ucontact_t* c_passed, str *presentity_uri, str *watcher_contact, str *contact_uri, - str* impus, int num_impus, int event_type, str *explit_dereg_contact, int num_explit_dereg_contact) { - - reg_notification *n; - reg_subscriber *s; - impurecord_t* r; - int local_cseq = 0; - int version = 0; - int create_notification; - - str subscription_state = {"active;expires=10000000000", 26}, - content_type = {"application/reginfo+xml", 23}; - - int domain_locked = -1; - - get_act_time(); - - int res; - - LM_DBG("Creating notification\n"); - - if (r_passed && !presentity_uri && !watcher_contact) { - LM_DBG("r_passed and c_passed are valid and presentity uri and watcher_contact is 0 - this must be a ul callback no need to lock domain\n"); - r = r_passed; - - } else { - LM_DBG("This must be a cfg file subscribe need to lock domain and get impurecord\n"); - ul.lock_udomain(_t, presentity_uri); - res = ul.get_impurecord(_t, presentity_uri, &r); - if (res != 0) { - LM_WARN("No IMPU... ignoring\n"); - ul.unlock_udomain(_t, presentity_uri); - return; - } - domain_locked = 1; - } - - s = r->shead; - while (s) { - LM_DBG("Scrolling through reg subscribers for this IMPU [%.*s]\n", r->public_identity.len, r->public_identity.s); - - create_notification = 0; - - if (s->expires > act_time) { - subscription_state.s = (char*) pkg_malloc(32 * sizeof (char*)); - subscription_state.len = 0; - if (subscription_state.s) { - - sprintf(subscription_state.s, "%.*s%" TIME_T_FMT, subs_active.len, - subs_active.s, TIME_T_CAST(s->expires - act_time)); - subscription_state.len = strlen(subscription_state.s); - } - - LM_DBG("Expires is greater than current time! Subscription state: [%.*s]\n", subscription_state.len, subscription_state.s); - - } else { - STR_PKG_DUP(subscription_state, subs_terminated, "pkg subs state"); - LM_DBG("Expires is past than current time! Subscription state: [%.*s]\n", subscription_state.len, subscription_state.s); - } - - //This is a fix to ensure that when a user subscribes a full reg info is only sent to that UE - if (event_type == IMS_REGISTRAR_SUBSCRIBE) { - if (contact_match(watcher_contact, &s->watcher_contact) && - (presentity_uri->len == s->presentity_uri.len) && (memcmp(s->presentity_uri.s, presentity_uri->s, presentity_uri->len) == 0)) { - LM_DBG("This is a fix to ensure that we only send full reg info XML to the UE that just subscribed.\n"); - create_notification = 1; - } - } else if (event_type == IMS_REGISTRAR_CONTACT_REGISTERED || event_type == IMS_REGISTRAR_CONTACT_REFRESHED) { - if(contact_match(contact_uri, &s->watcher_contact) && - (r_passed->public_identity.len == s->presentity_uri.len) && (memcmp(s->presentity_uri.s, r_passed->public_identity.s, r_passed->public_identity.len) == 0)) { - LM_DBG("This is a fix to ensure that we only send full reg info XML to the UE that just registered.\n"); +void create_notifications(udomain_t *_t, impurecord_t *r_passed, + ucontact_t *c_passed, str *presentity_uri, str *watcher_contact, + str *contact_uri, str *impus, int num_impus, int event_type, + str *explit_dereg_contact, int num_explit_dereg_contact) +{ + + reg_notification *n; + reg_subscriber *s; + impurecord_t *r; + int local_cseq = 0; + int version = 0; + int create_notification; + + str subscription_state = {"active;expires=10000000000", 26}, + content_type = {"application/reginfo+xml", 23}; + + int domain_locked = -1; + + get_act_time(); + + int res; + + LM_DBG("Creating notification\n"); + + if(r_passed && !presentity_uri && !watcher_contact) { + LM_DBG("r_passed and c_passed are valid and presentity uri and " + "watcher_contact is 0 - this must be a ul callback no need to " + "lock domain\n"); + r = r_passed; + + } else { + LM_DBG("This must be a cfg file subscribe need to lock domain and get " + "impurecord\n"); + ul.lock_udomain(_t, presentity_uri); + res = ul.get_impurecord(_t, presentity_uri, &r); + if(res != 0) { + LM_WARN("No IMPU... ignoring\n"); + ul.unlock_udomain(_t, presentity_uri); + return; + } + domain_locked = 1; + } + + s = r->shead; + while(s) { + LM_DBG("Scrolling through reg subscribers for this IMPU [%.*s]\n", + r->public_identity.len, r->public_identity.s); + + create_notification = 0; + + if(s->expires > act_time) { + subscription_state.s = (char *)pkg_malloc(32 * sizeof(char *)); + subscription_state.len = 0; + if(subscription_state.s) { + + sprintf(subscription_state.s, "%.*s%" TIME_T_FMT, + subs_active.len, subs_active.s, + TIME_T_CAST(s->expires - act_time)); + subscription_state.len = strlen(subscription_state.s); + } + + LM_DBG("Expires is greater than current time! Subscription state: " + "[%.*s]\n", + subscription_state.len, subscription_state.s); + + } else { + STR_PKG_DUP(subscription_state, subs_terminated, "pkg subs state"); + LM_DBG("Expires is past than current time! Subscription state: " + "[%.*s]\n", + subscription_state.len, subscription_state.s); + } + + //This is a fix to ensure that when a user subscribes a full reg info is only sent to that UE + if(event_type == IMS_REGISTRAR_SUBSCRIBE) { + if(contact_match(watcher_contact, &s->watcher_contact) + && (presentity_uri->len == s->presentity_uri.len) + && (memcmp(s->presentity_uri.s, presentity_uri->s, + presentity_uri->len) + == 0)) { + LM_DBG("This is a fix to ensure that we only send full reg " + "info XML to the UE that just subscribed.\n"); create_notification = 1; } - } else if (event_type == IMS_REGISTRAR_CONTACT_EXPIRED || event_type == IMS_REGISTRAR_CONTACT_UNREGISTERED) { - if(!ue_unsubscribe_on_dereg && - contact_port_ip_match(&c_passed->c, &s->watcher_contact) && alias_port_ip_match(&c_passed->c, &s->watcher_contact) && - r_passed->public_identity.len == s->presentity_uri.len && - memcmp(s->presentity_uri.s, r_passed->public_identity.s, r_passed->public_identity.len) == 0) { - LM_DBG("This is an UNREGISTER/EXPIRE event for a UE that subscribed to its own state that does not unsubscribe to dereg - therefore no notification\n"); + } else if(event_type == IMS_REGISTRAR_CONTACT_REGISTERED + || event_type == IMS_REGISTRAR_CONTACT_REFRESHED) { + if(contact_match(contact_uri, &s->watcher_contact) + && (r_passed->public_identity.len == s->presentity_uri.len) + && (memcmp(s->presentity_uri.s, r_passed->public_identity.s, + r_passed->public_identity.len) + == 0)) { + LM_DBG("This is a fix to ensure that we only send full reg " + "info XML to the UE that just registered.\n"); + create_notification = 1; + } + } else if(event_type == IMS_REGISTRAR_CONTACT_EXPIRED + || event_type == IMS_REGISTRAR_CONTACT_UNREGISTERED) { + if(!ue_unsubscribe_on_dereg + && contact_port_ip_match(&c_passed->c, &s->watcher_contact) + && alias_port_ip_match(&c_passed->c, &s->watcher_contact) + && r_passed->public_identity.len == s->presentity_uri.len + && memcmp(s->presentity_uri.s, r_passed->public_identity.s, + r_passed->public_identity.len) + == 0) { + LM_DBG("This is an UNREGISTER/EXPIRE event for a UE that " + "subscribed to its own state that does not unsubscribe " + "to dereg - therefore no notification\n"); if(r->linked_contacts.numcontacts < 2) { // marking the contact as Notify ready if there aren't other linked contacts to the current impu record ul.lock_contact_slot_i(c_passed->sl); if(c_passed->state == CONTACT_EXPIRE_PENDING_NOTIFY) { - LM_DBG("Setting contact state from CONTACT_EXPIRE_PENDING_NOTIFY to CONTACT_NOTIFY_READY for contact [%.*s]\n", c_passed->c.len, c_passed->c.s); + LM_DBG("Setting contact state from " + "CONTACT_EXPIRE_PENDING_NOTIFY to " + "CONTACT_NOTIFY_READY for contact [%.*s]\n", + c_passed->c.len, c_passed->c.s); c_passed->state = CONTACT_NOTIFY_READY; } ul.unlock_contact_slot_i(c_passed->sl); @@ -1567,37 +1775,41 @@ void create_notifications(udomain_t* _t, impurecord_t* r_passed, ucontact_t* c_p create_notification = 1; } - if(create_notification) { - LM_DBG("About to make new notification! We always increment the local cseq and version before we send a new notification\n"); - - local_cseq = s->local_cseq + 1; - version = s->version + 1; - ul.update_subscriber(r, &s, 0, &local_cseq, &version); - - n = new_notification(subscription_state, content_type, &impus, num_impus, s, &explit_dereg_contact, num_explit_dereg_contact); - if (n) { - n->_d = _t; - LM_DBG("Notification exists - about to add it\n"); - add_notification(n); - } else { - LM_DBG("Notification does not exist\n"); - } - } + if(create_notification) { + LM_DBG("About to make new notification! We always increment the " + "local cseq and version before we send a new " + "notification\n"); + + local_cseq = s->local_cseq + 1; + version = s->version + 1; + ul.update_subscriber(r, &s, 0, &local_cseq, &version); + + n = new_notification(subscription_state, content_type, &impus, + num_impus, s, &explit_dereg_contact, + num_explit_dereg_contact); + if(n) { + n->_d = _t; + LM_DBG("Notification exists - about to add it\n"); + add_notification(n); + } else { + LM_DBG("Notification does not exist\n"); + } + } - s = s->next; + s = s->next; - if (subscription_state.s) { - pkg_free(subscription_state.s); - } - } + if(subscription_state.s) { + pkg_free(subscription_state.s); + } + } - if (domain_locked == 1) { - ul.unlock_udomain(_t, presentity_uri); - } + if(domain_locked == 1) { + ul.unlock_udomain(_t, presentity_uri); + } - return; + return; out_of_memory: - return; + return; } /*We currently only support certain unknown params to be sent in NOTIFY bodies @@ -1611,23 +1823,28 @@ static str param_sip_instance = {"+sip.instance", 13}; static str param_3gpp_smsip = {"+g.3gpp.smsip", 13}; static str param_3gpp_icsi_ref = {"+g.3gpp.icsi-ref", 16}; -static int inline supported_param(str *param_name) { - - if (strncasecmp(param_name->s, param_q.s, param_name->len) == 0) { - return 0; - } else if (strncasecmp(param_name->s, param_video.s, param_name->len) == 0) { - return 0; - } else if (strncasecmp(param_name->s, param_expires.s, param_name->len) == 0) { - return 0; - } else if (strncasecmp(param_name->s, param_sip_instance.s, param_name->len) == 0) { - return 0; - } else if (strncasecmp(param_name->s, param_3gpp_smsip.s, param_name->len) == 0) { - return 0; - } else if (strncasecmp(param_name->s, param_3gpp_icsi_ref.s, param_name->len) == 0) { - return 0; - } else { - return -1; - } +static int inline supported_param(str *param_name) +{ + + if(strncasecmp(param_name->s, param_q.s, param_name->len) == 0) { + return 0; + } else if(strncasecmp(param_name->s, param_video.s, param_name->len) == 0) { + return 0; + } else if(strncasecmp(param_name->s, param_expires.s, param_name->len) + == 0) { + return 0; + } else if(strncasecmp(param_name->s, param_sip_instance.s, param_name->len) + == 0) { + return 0; + } else if(strncasecmp(param_name->s, param_3gpp_smsip.s, param_name->len) + == 0) { + return 0; + } else if(strncasecmp(param_name->s, param_3gpp_icsi_ref.s, param_name->len) + == 0) { + return 0; + } else { + return -1; + } } /** Maximum reginfo XML size */ @@ -1637,12 +1854,15 @@ static str xml_start = {"\n", 22}; static str r_full = {"full", 4}; static str r_partial = {"partial", 7}; -static str r_reginfo_s = {"\n", 74}; +static str r_reginfo_s = {"\n", + 74}; static str r_reginfo_e = {"\n", 11}; static str r_active = {"active", 6}; static str r_terminated = {"terminated", 10}; -static str registration_s = {"\t\n", 48}; +static str registration_s = { + "\t\n", 48}; static str registration_e = {"\t\n", 17}; //richard: we only use reg unreg refrsh and expire @@ -1650,103 +1870,125 @@ static str r_registered = {"registered", 10}; static str r_refreshed = {"refreshed", 9}; static str r_expired = {"expired", 7}; static str r_unregistered = {"unregistered", 12}; -static str contact_s = {"\t\t\n", 59}; -static str contact_s_q = {"\t\t\n", 69}; -static str contact_s_params_with_body = {"\t\t\"%.*s\"\n", 1}; +static str contact_s = {"\t\t\n", + 59}; +static str contact_s_q = {"\t\t\n", + 69}; +static str contact_s_params_with_body = { + "\t\t\"%.*s\"\n", 1}; /**NOTIFY XML needs < to be replaced by < and > to be replaced by >*/ /*For params that need to be fixed we pass in str removing first and last character and replace them with < and >**/ -static str contact_s_params_with_body_fix = {"\t\t\"<%.*s>\"\n", 1}; -static str contact_s_params_no_body = {"\t\t\n", 1}; +static str contact_s_params_with_body_fix = { + "\t\t\"<%.*s>\"\n", + 1}; +static str contact_s_params_no_body = { + "\t\t\n", 1}; static str contact_e = {"\t\t\n", 13}; static str uri_s = {"\t\t\t", 8}; static str uri_e = {"\n", 7}; -static void process_xml_for_explit_dereg_contact(str* buf, str* pad, str explit_dereg_contact) { +static void process_xml_for_explit_dereg_contact( + str *buf, str *pad, str explit_dereg_contact) +{ - LM_DBG("Processing XML for explicit dereg contact address: <%.*s>\n", explit_dereg_contact.len, explit_dereg_contact.s); + LM_DBG("Processing XML for explicit dereg contact address: <%.*s>\n", + explit_dereg_contact.len, explit_dereg_contact.s); - sprintf(pad->s, contact_s_q.s, 1, r_terminated.len, r_terminated.s, - r_expired.len, r_expired.s, 0); + sprintf(pad->s, contact_s_q.s, 1, r_terminated.len, r_terminated.s, + r_expired.len, r_expired.s, 0); - pad->len = strlen(pad->s); - STR_APPEND(*buf, *pad); - STR_APPEND(*buf, uri_s); + pad->len = strlen(pad->s); + STR_APPEND(*buf, *pad); + STR_APPEND(*buf, uri_s); - STR_APPEND(*buf, (explit_dereg_contact)); - STR_APPEND(*buf, uri_e); - STR_APPEND(*buf, contact_e); + STR_APPEND(*buf, (explit_dereg_contact)); + STR_APPEND(*buf, uri_e); + STR_APPEND(*buf, contact_e); } -static void process_xml_for_contact(str* buf, str* pad, ucontact_t* ptr) { - int expires; - param_t *param; - - if (ptr->state == CONTACT_DELETED) - return; - - expires = ptr->expires - act_time; - if (expires < 0 || (ptr->state == CONTACT_DELETE_PENDING) || (ptr->state == CONTACT_EXPIRE_PENDING_NOTIFY)) { - LM_WARN("Contact expires is negative - setting to 0\n"); - expires = 0; - } - if (expires == 0) { - if (ptr->q != -1) { - float q = (float) ptr->q / 1000; - sprintf(pad->s, contact_s_q.s, ptr, r_terminated.len, r_terminated.s, - r_expired.len, r_expired.s, expires, q); - } else { - sprintf(pad->s, contact_s_q.s, ptr, r_terminated.len, r_terminated.s, - r_expired.len, r_expired.s, expires); - } - } else { - if (ptr->q != -1) { - float q = (float) ptr->q / 1000; - sprintf(pad->s, contact_s_q.s, ptr, r_active.len, r_active.s, - r_registered.len, r_registered.s, expires, - q); - } else { - sprintf(pad->s, contact_s_q.s, ptr, r_active.len, r_active.s, - r_registered.len, r_registered.s, expires); - } - } - - pad->len = strlen(pad->s); - STR_APPEND(*buf, *pad); - STR_APPEND(*buf, uri_s); - - LM_DBG("Appending contact address: <%.*s>\n", ptr->c.len, ptr->c.s); - - STR_APPEND(*buf, (ptr->c)); - STR_APPEND(*buf, uri_e); - - param = ptr->params; - while (param) { - if (supported_param(¶m->name) != 0) { - param = param->next; - continue; - } - - if (param->body.len > 0) { - LM_DBG("This contact has params name: [%.*s] body [%.*s]\n", param->name.len, param->name.s, param->body.len, param->body.s); - if (param->body.s[0] == '<' && param->body.s[param->body.len - 1] == '>') { - LM_DBG("This param body starts with '<' and ends with '>' we will clean these for the NOTIFY XML with < and >\n"); - sprintf(pad->s, contact_s_params_with_body_fix.s, param->name.len, param->name.s, param->body.len - 2, param->body.s + 1); - } else { - sprintf(pad->s, contact_s_params_with_body.s, param->name.len, param->name.s, param->body.len, param->body.s); - } - - pad->len = strlen(pad->s); - STR_APPEND(*buf, *pad); - } else { - LM_DBG("This contact has params name: [%.*s] \n", param->name.len, param->name.s); - sprintf(pad->s, contact_s_params_no_body.s, param->name.len, param->name.s); - pad->len = strlen(pad->s); - STR_APPEND(*buf, *pad); - } - param = param->next; - } - STR_APPEND(*buf, contact_e); +static void process_xml_for_contact(str *buf, str *pad, ucontact_t *ptr) +{ + int expires; + param_t *param; + + if(ptr->state == CONTACT_DELETED) + return; + + expires = ptr->expires - act_time; + if(expires < 0 || (ptr->state == CONTACT_DELETE_PENDING) + || (ptr->state == CONTACT_EXPIRE_PENDING_NOTIFY)) { + LM_WARN("Contact expires is negative - setting to 0\n"); + expires = 0; + } + if(expires == 0) { + if(ptr->q != -1) { + float q = (float)ptr->q / 1000; + sprintf(pad->s, contact_s_q.s, ptr, r_terminated.len, + r_terminated.s, r_expired.len, r_expired.s, expires, q); + } else { + sprintf(pad->s, contact_s_q.s, ptr, r_terminated.len, + r_terminated.s, r_expired.len, r_expired.s, expires); + } + } else { + if(ptr->q != -1) { + float q = (float)ptr->q / 1000; + sprintf(pad->s, contact_s_q.s, ptr, r_active.len, r_active.s, + r_registered.len, r_registered.s, expires, q); + } else { + sprintf(pad->s, contact_s_q.s, ptr, r_active.len, r_active.s, + r_registered.len, r_registered.s, expires); + } + } + + pad->len = strlen(pad->s); + STR_APPEND(*buf, *pad); + STR_APPEND(*buf, uri_s); + + LM_DBG("Appending contact address: <%.*s>\n", ptr->c.len, ptr->c.s); + + STR_APPEND(*buf, (ptr->c)); + STR_APPEND(*buf, uri_e); + + param = ptr->params; + while(param) { + if(supported_param(¶m->name) != 0) { + param = param->next; + continue; + } + + if(param->body.len > 0) { + LM_DBG("This contact has params name: [%.*s] body [%.*s]\n", + param->name.len, param->name.s, param->body.len, + param->body.s); + if(param->body.s[0] == '<' + && param->body.s[param->body.len - 1] == '>') { + LM_DBG("This param body starts with '<' and ends with '>' we " + "will clean these for the NOTIFY XML with < and " + ">\n"); + sprintf(pad->s, contact_s_params_with_body_fix.s, + param->name.len, param->name.s, param->body.len - 2, + param->body.s + 1); + } else { + sprintf(pad->s, contact_s_params_with_body.s, param->name.len, + param->name.s, param->body.len, param->body.s); + } + + pad->len = strlen(pad->s); + STR_APPEND(*buf, *pad); + } else { + LM_DBG("This contact has params name: [%.*s] \n", param->name.len, + param->name.s); + sprintf(pad->s, contact_s_params_no_body.s, param->name.len, + param->name.s); + pad->len = strlen(pad->s); + STR_APPEND(*buf, *pad); + } + param = param->next; + } + STR_APPEND(*buf, contact_e); } /** @@ -1757,40 +1999,43 @@ static void process_xml_for_contact(str* buf, str* pad, ucontact_t* ptr) { * @returns the str with the XML content * if it is a new subscription we do things like subscribe to updates on IMPU, etc */ -str generate_reginfo_full(udomain_t* _t, str* impu_list, int num_impus, str *explit_dereg_contact, str* watcher_contact, int num_explit_dereg_contact, unsigned int reginfo_version) { - str x = {0, 0}; - str buf, pad; - char bufc[MAX_REGINFO_SIZE], padc[MAX_REGINFO_SIZE]; - impurecord_t *r; - int i, k, res; - ucontact_t* ptr; - - buf.s = bufc; - buf.len = 0; - pad.s = padc; - pad.len = 0; - get_act_time(); - // int domain_locked = 1; - int terminate_impu = 1; +str generate_reginfo_full(udomain_t *_t, str *impu_list, int num_impus, + str *explit_dereg_contact, str *watcher_contact, + int num_explit_dereg_contact, unsigned int reginfo_version) +{ + str x = {0, 0}; + str buf, pad; + char bufc[MAX_REGINFO_SIZE], padc[MAX_REGINFO_SIZE]; + impurecord_t *r; + int i, k, res; + ucontact_t *ptr; + + buf.s = bufc; + buf.len = 0; + pad.s = padc; + pad.len = 0; + get_act_time(); + // int domain_locked = 1; + int terminate_impu = 1; impu_contact_t *impucontact; unsigned int num_pending_notify_contacts = 0; unsigned int max_num_pending_notify_contacts = 0; - ucontact_t** pending_notify_contacts = 0; + ucontact_t **pending_notify_contacts = 0; - LM_DBG("Getting reginfo_full\n"); + LM_DBG("Getting reginfo_full\n"); - STR_APPEND(buf, xml_start); - sprintf(pad.s, r_reginfo_s.s, reginfo_version, r_full.len, r_full.s); - pad.len = strlen(pad.s); - STR_APPEND(buf, pad); + STR_APPEND(buf, xml_start); + sprintf(pad.s, r_reginfo_s.s, reginfo_version, r_full.len, r_full.s); + pad.len = strlen(pad.s); + STR_APPEND(buf, pad); // reserve memory for all contacts for all impus - for (i = 0; i < num_impus; i++) { + for(i = 0; i < num_impus; i++) { ul.lock_udomain(_t, &impu_list[i]); res = ul.get_impurecord(_t, (&impu_list[i]), &r); - if (res != 0) { + if(res != 0) { LM_DBG("impu disappeared, ignoring it\n"); ul.unlock_udomain(_t, &impu_list[i]); continue; @@ -1801,85 +2046,97 @@ str generate_reginfo_full(udomain_t* _t, str* impu_list, int num_impus, str *exp ul.unlock_udomain(_t, &impu_list[i]); } - pending_notify_contacts = (ucontact_t**)pkg_malloc(max_num_pending_notify_contacts*sizeof(ucontact_t**)); - if (!pending_notify_contacts) { - LM_WARN("no more pkg mem trying to allocate [%lu] bytes\n", max_num_pending_notify_contacts*sizeof(ucontact_t**)); + pending_notify_contacts = (ucontact_t **)pkg_malloc( + max_num_pending_notify_contacts * sizeof(ucontact_t **)); + if(!pending_notify_contacts) { + LM_WARN("no more pkg mem trying to allocate [%lu] bytes\n", + max_num_pending_notify_contacts * sizeof(ucontact_t **)); max_num_pending_notify_contacts = 0; } - for (i = 0; i < num_impus; i++) { - LM_DBG("Scrolling through public identities, current one <%.*s>\n", impu_list[i].len, impu_list[i].s); - // if (primary_locked && strncasecmp(impu_list[i].s, primary_impu->s, impu_list[i].len) == 0) { - // LM_DBG("Don't need to lock this impu [%.*s] as it is a ul callback so already locked\n", impu_list[i].len, impu_list[i].s); - // domain_locked = 0; - // } else { - // LM_DBG("Need to lock this impu\n"); - // ul.lock_udomain(_t, &impu_list[i]); - // domain_locked = 1; - // } - - ul.lock_udomain(_t, &impu_list[i]); - - res = ul.get_impurecord(_t, (&impu_list[i]), &r); - if (res != 0) { - LM_DBG("impu disappeared, ignoring it\n"); - // if (domain_locked) { - ul.unlock_udomain(_t, &impu_list[i]); - // } - continue; - } - // domain_locked = 1; - - LM_DBG("Retrieved IMPU record\n"); - - terminate_impu = 1; - + for(i = 0; i < num_impus; i++) { + LM_DBG("Scrolling through public identities, current one <%.*s>\n", + impu_list[i].len, impu_list[i].s); + // if (primary_locked && strncasecmp(impu_list[i].s, primary_impu->s, impu_list[i].len) == 0) { + // LM_DBG("Don't need to lock this impu [%.*s] as it is a ul callback so already locked\n", impu_list[i].len, impu_list[i].s); + // domain_locked = 0; + // } else { + // LM_DBG("Need to lock this impu\n"); + // ul.lock_udomain(_t, &impu_list[i]); + // domain_locked = 1; + // } + + ul.lock_udomain(_t, &impu_list[i]); + + res = ul.get_impurecord(_t, (&impu_list[i]), &r); + if(res != 0) { + LM_DBG("impu disappeared, ignoring it\n"); + // if (domain_locked) { + ul.unlock_udomain(_t, &impu_list[i]); + // } + continue; + } + // domain_locked = 1; + + LM_DBG("Retrieved IMPU record\n"); + + terminate_impu = 1; + impucontact = r->linked_contacts.head; - while (impucontact) { + while(impucontact) { ptr = impucontact->contact; - if (VALID_CONTACT(ptr, act_time)) { - LM_DBG("IMPU <%.*s> has another active contact <%.*s> so will set its state to active\n", - r->public_identity.len, r->public_identity.s, ptr->c.len, ptr->c.s); - terminate_impu = 0; - break; - } + if(VALID_CONTACT(ptr, act_time)) { + LM_DBG("IMPU <%.*s> has another active contact <%.*s> so will " + "set its state to active\n", + r->public_identity.len, r->public_identity.s, + ptr->c.len, ptr->c.s); + terminate_impu = 0; + break; + } impucontact = impucontact->next; - } - if (terminate_impu) { - LM_DBG("IMPU reg state has no active contacts so putting in status terminated\n"); - sprintf(pad.s, registration_s.s, r->public_identity.len, - r->public_identity.s, r, r_terminated.len, - r_terminated.s); - } else { - LM_DBG("IMPU has active contacts so putting in status active\n"); - sprintf(pad.s, registration_s.s, r->public_identity.len, - r->public_identity.s, r, r_active.len, r_active.s); - } - - pad.len = strlen(pad.s); - STR_APPEND(buf, pad); - - LM_DBG("Scrolling through contact for this IMPU\n"); - // if (contact && !domain_locked /* we're dealing with the primary impu most likely related to de-reg */) { - // LM_DBG("We're dealing with the primary IMPU here AND a contact was passed in - must have been an explicit dereg\n"); - // process_xml_for_contact(&buf, &pad, contact); //we do this because in the unlink_contact_from_impu the contact has already gone so we pass it in as a param... - // } - - for (k = 0; k < num_explit_dereg_contact; k++) { - LM_DBG("This must have been an explicit dereg - therefore we need to include the de-reged contact(s) that have already been unlinked\n"); - LM_DBG("Scrolling through list of provided num_explit_dereg_contact: [%.*s]\n", explit_dereg_contact[k].len, explit_dereg_contact[k].s); - process_xml_for_explit_dereg_contact(&buf, &pad, explit_dereg_contact[k]); - } + } + if(terminate_impu) { + LM_DBG("IMPU reg state has no active contacts so putting in status " + "terminated\n"); + sprintf(pad.s, registration_s.s, r->public_identity.len, + r->public_identity.s, r, r_terminated.len, r_terminated.s); + } else { + LM_DBG("IMPU has active contacts so putting in status active\n"); + sprintf(pad.s, registration_s.s, r->public_identity.len, + r->public_identity.s, r, r_active.len, r_active.s); + } + + pad.len = strlen(pad.s); + STR_APPEND(buf, pad); + + LM_DBG("Scrolling through contact for this IMPU\n"); + // if (contact && !domain_locked /* we're dealing with the primary impu most likely related to de-reg */) { + // LM_DBG("We're dealing with the primary IMPU here AND a contact was passed in - must have been an explicit dereg\n"); + // process_xml_for_contact(&buf, &pad, contact); //we do this because in the unlink_contact_from_impu the contact has already gone so we pass it in as a param... + // } + + for(k = 0; k < num_explit_dereg_contact; k++) { + LM_DBG("This must have been an explicit dereg - therefore we need " + "to include the de-reged contact(s) that have already been " + "unlinked\n"); + LM_DBG("Scrolling through list of provided " + "num_explit_dereg_contact: [%.*s]\n", + explit_dereg_contact[k].len, explit_dereg_contact[k].s); + process_xml_for_explit_dereg_contact( + &buf, &pad, explit_dereg_contact[k]); + } impucontact = r->linked_contacts.head; - while (impucontact) { + while(impucontact) { ptr = impucontact->contact; ul.lock_contact_slot_i(ptr->sl); process_xml_for_contact(&buf, &pad, ptr); - if (ptr->state == CONTACT_EXPIRE_PENDING_NOTIFY && num_pending_notify_contacts < max_num_pending_notify_contacts) { + if(ptr->state == CONTACT_EXPIRE_PENDING_NOTIFY + && num_pending_notify_contacts + < max_num_pending_notify_contacts) { pending_notify_contacts[num_pending_notify_contacts++] = ptr; } @@ -1888,44 +2145,46 @@ str generate_reginfo_full(udomain_t* _t, str* impu_list, int num_impus, str *exp impucontact = impucontact->next; } - STR_APPEND(buf, registration_e); + STR_APPEND(buf, registration_e); - // if (domain_locked) { - ul.unlock_udomain(_t, &impu_list[i]); - // } - } + // if (domain_locked) { + ul.unlock_udomain(_t, &impu_list[i]); + // } + } // set all expire pending notify contacts to notify ready state - for (i = 0; i < num_pending_notify_contacts; ++i) { + for(i = 0; i < num_pending_notify_contacts; ++i) { ptr = pending_notify_contacts[i]; ul.lock_contact_slot_i(ptr->sl); if(ptr->state == CONTACT_EXPIRE_PENDING_NOTIFY) { - LM_DBG("Setting contact state from CONTACT_EXPIRE_PENDING_NOTIFY to CONTACT_NOTIFY_READY for contact [%.*s]\n", ptr->c.len, ptr->c.s); + LM_DBG("Setting contact state from CONTACT_EXPIRE_PENDING_NOTIFY " + "to CONTACT_NOTIFY_READY for contact [%.*s]\n", + ptr->c.len, ptr->c.s); ptr->state = CONTACT_NOTIFY_READY; } ul.unlock_contact_slot_i(ptr->sl); } - if (pending_notify_contacts){ + if(pending_notify_contacts) { pkg_free(pending_notify_contacts); } - STR_APPEND(buf, r_reginfo_e); + STR_APPEND(buf, r_reginfo_e); - x.s = pkg_malloc(buf.len + 1); - if (x.s) { - x.len = buf.len; - memcpy(x.s, buf.s, buf.len); - x.s[x.len] = 0; - } else { - LM_ERR("no more pkg memory\n"); - } + x.s = pkg_malloc(buf.len + 1); + if(x.s) { + x.len = buf.len; + memcpy(x.s, buf.s, buf.len); + x.s[x.len] = 0; + } else { + LM_ERR("no more pkg memory\n"); + } - LM_DBG("Returned full reg-info: [%.*s]\n", x.len, x.s); + LM_DBG("Returned full reg-info: [%.*s]\n", x.len, x.s); - return x; + return x; } /** @@ -1937,157 +2196,180 @@ str generate_reginfo_full(udomain_t* _t, str* impu_list, int num_impus, str *exp * @returns the str with the XML content */ -str get_reginfo_partial(impurecord_t *r, ucontact_t *c, int event_type, unsigned int reginfo_version) { - str x = {0, 0}; - str buf, pad; - char bufc[MAX_REGINFO_SIZE], padc[MAX_REGINFO_SIZE]; - int expires = -1; - int terminate_impu = 1; - ucontact_t *c_tmp; - str state, event; - param_t *param; +str get_reginfo_partial(impurecord_t *r, ucontact_t *c, int event_type, + unsigned int reginfo_version) +{ + str x = {0, 0}; + str buf, pad; + char bufc[MAX_REGINFO_SIZE], padc[MAX_REGINFO_SIZE]; + int expires = -1; + int terminate_impu = 1; + ucontact_t *c_tmp; + str state, event; + param_t *param; impu_contact_t *impurecord; - buf.s = bufc; - buf.len = 0; - pad.s = padc; - pad.len = 0; + buf.s = bufc; + buf.len = 0; + pad.s = padc; + pad.len = 0; - STR_APPEND(buf, xml_start); - sprintf(pad.s, r_reginfo_s.s, reginfo_version, r_partial.len, r_partial.s); - pad.len = strlen(pad.s); - STR_APPEND(buf, pad); + STR_APPEND(buf, xml_start); + sprintf(pad.s, r_reginfo_s.s, reginfo_version, r_partial.len, r_partial.s); + pad.len = strlen(pad.s); + STR_APPEND(buf, pad); - if (r) { - expires = c->expires - act_time; - if (expires < 0) { - LM_WARN("Contact expires is negative - setting to 0\n"); - expires = 0; - } + if(r) { + expires = c->expires - act_time; + if(expires < 0) { + LM_WARN("Contact expires is negative - setting to 0\n"); + expires = 0; + } - if (//richard we only use expired and unregistered - (event_type == IMS_REGISTRAR_CONTACT_EXPIRED || - event_type == IMS_REGISTRAR_CONTACT_UNREGISTERED || - event_type == IMS_REGISTRAR_CONTACT_DEREGISTERED) - ) { - //check if impu record has any other active contacts - if not then set this to terminated - if so then keep this active - //check if asserted is present in any of the path headers + if( //richard we only use expired and unregistered + (event_type == IMS_REGISTRAR_CONTACT_EXPIRED + || event_type == IMS_REGISTRAR_CONTACT_UNREGISTERED + || event_type == IMS_REGISTRAR_CONTACT_DEREGISTERED)) { + //check if impu record has any other active contacts - if not then set this to terminated - if so then keep this active + //check if asserted is present in any of the path headers - impurecord = r->linked_contacts.head; - while (impurecord) { + impurecord = r->linked_contacts.head; + while(impurecord) { c_tmp = impurecord->contact; - if ((strncasecmp(c_tmp->c.s, c->c.s, c_tmp->c.len) != 0) && ((c_tmp->expires - act_time) > 0)) { - LM_DBG("IMPU <%.*s> has another active contact <%.*s> so will set its state to active\n", - r->public_identity.len, r->public_identity.s, c_tmp->c.len, c_tmp->c.s); - terminate_impu = 0; - break; - } - impurecord = impurecord->next; - } - if (terminate_impu) - sprintf(pad.s, registration_s.s, r->public_identity.len, r->public_identity.s, r, r_terminated.len, r_terminated.s); - else - sprintf(pad.s, registration_s.s, r->public_identity.len, r->public_identity.s, r, r_active.len, r_active.s); - } else { - sprintf(pad.s, registration_s.s, r->public_identity.len, r->public_identity.s, r, r_active.len, r_active.s); - } - - pad.len = strlen(pad.s); - STR_APPEND(buf, pad); - if (c) { - switch (event_type) { - - //richard we only use registered and refreshed and expired and unregistered - case IMS_REGISTRAR_CONTACT_REGISTERED: - state = r_active; - event = r_registered; - break; - case IMS_REGISTRAR_CONTACT_REFRESHED: - state = r_active; - event = r_refreshed; - break; - case IMS_REGISTRAR_CONTACT_EXPIRED: - state = r_terminated; - event = r_expired; - expires = 0; - break; - case IMS_REGISTRAR_CONTACT_DEREGISTERED: - case IMS_REGISTRAR_CONTACT_UNREGISTERED: - state = r_terminated; - event = r_unregistered; - expires = 0; - break; - default: - state = r_active; - event = r_registered; - } - if (c->q != -1) { - float q = (float) c->q / 1000; - sprintf(pad.s, contact_s_q.s, c, state.len, state.s, event.len, event.s, expires, q); - } else - sprintf(pad.s, contact_s.s, c, state.len, state.s, event.len, event.s, expires); - pad.len = strlen(pad.s); - STR_APPEND(buf, pad); - STR_APPEND(buf, uri_s); - STR_APPEND(buf, (c->c)); - STR_APPEND(buf, uri_e); - - param = c->params; - while (param && supported_param(¶m->name) == 0) { - - if (param->body.len > 0) { - LM_DBG("This contact has params name: [%.*s] body [%.*s]\n", param->name.len, param->name.s, param->body.len, param->body.s); - if (param->body.s[0] == '<' && param->body.s[param->body.len - 1] == '>') { - LM_DBG("This param body starts with '<' and ends with '>' we will clean these for the NOTIFY XML with < and >\n"); - sprintf(pad.s, contact_s_params_with_body_fix.s, param->name.len, param->name.s, param->body.len - 2, param->body.s + 1); - } else { - sprintf(pad.s, contact_s_params_with_body.s, param->name.len, param->name.s, param->body.len, param->body.s); - } - - pad.len = strlen(pad.s); - STR_APPEND(buf, pad); - } else { - LM_DBG("This contact has params name: [%.*s] \n", param->name.len, param->name.s); - sprintf(pad.s, contact_s_params_no_body.s, param->name.len, param->name.s); - pad.len = strlen(pad.s); - STR_APPEND(buf, pad); - } - param = param->next; - } - - STR_APPEND(buf, contact_e); - STR_APPEND(buf, registration_e); - } - } - - STR_APPEND(buf, r_reginfo_e); - - - x.s = pkg_malloc(buf.len + 1); - if (x.s) { - x.len = buf.len; - memcpy(x.s, buf.s, buf.len); - x.s[x.len] = 0; - } - return x; + if((strncasecmp(c_tmp->c.s, c->c.s, c_tmp->c.len) != 0) + && ((c_tmp->expires - act_time) > 0)) { + LM_DBG("IMPU <%.*s> has another active contact <%.*s> so " + "will set its state to active\n", + r->public_identity.len, r->public_identity.s, + c_tmp->c.len, c_tmp->c.s); + terminate_impu = 0; + break; + } + impurecord = impurecord->next; + } + if(terminate_impu) + sprintf(pad.s, registration_s.s, r->public_identity.len, + r->public_identity.s, r, r_terminated.len, + r_terminated.s); + else + sprintf(pad.s, registration_s.s, r->public_identity.len, + r->public_identity.s, r, r_active.len, r_active.s); + } else { + sprintf(pad.s, registration_s.s, r->public_identity.len, + r->public_identity.s, r, r_active.len, r_active.s); + } + + pad.len = strlen(pad.s); + STR_APPEND(buf, pad); + if(c) { + switch(event_type) { + + //richard we only use registered and refreshed and expired and unregistered + case IMS_REGISTRAR_CONTACT_REGISTERED: + state = r_active; + event = r_registered; + break; + case IMS_REGISTRAR_CONTACT_REFRESHED: + state = r_active; + event = r_refreshed; + break; + case IMS_REGISTRAR_CONTACT_EXPIRED: + state = r_terminated; + event = r_expired; + expires = 0; + break; + case IMS_REGISTRAR_CONTACT_DEREGISTERED: + case IMS_REGISTRAR_CONTACT_UNREGISTERED: + state = r_terminated; + event = r_unregistered; + expires = 0; + break; + default: + state = r_active; + event = r_registered; + } + if(c->q != -1) { + float q = (float)c->q / 1000; + sprintf(pad.s, contact_s_q.s, c, state.len, state.s, event.len, + event.s, expires, q); + } else + sprintf(pad.s, contact_s.s, c, state.len, state.s, event.len, + event.s, expires); + pad.len = strlen(pad.s); + STR_APPEND(buf, pad); + STR_APPEND(buf, uri_s); + STR_APPEND(buf, (c->c)); + STR_APPEND(buf, uri_e); + + param = c->params; + while(param && supported_param(¶m->name) == 0) { + + if(param->body.len > 0) { + LM_DBG("This contact has params name: [%.*s] body [%.*s]\n", + param->name.len, param->name.s, param->body.len, + param->body.s); + if(param->body.s[0] == '<' + && param->body.s[param->body.len - 1] == '>') { + LM_DBG("This param body starts with '<' and ends with " + "'>' we will clean these for the NOTIFY XML " + "with < and >\n"); + sprintf(pad.s, contact_s_params_with_body_fix.s, + param->name.len, param->name.s, + param->body.len - 2, param->body.s + 1); + } else { + sprintf(pad.s, contact_s_params_with_body.s, + param->name.len, param->name.s, param->body.len, + param->body.s); + } + + pad.len = strlen(pad.s); + STR_APPEND(buf, pad); + } else { + LM_DBG("This contact has params name: [%.*s] \n", + param->name.len, param->name.s); + sprintf(pad.s, contact_s_params_no_body.s, param->name.len, + param->name.s); + pad.len = strlen(pad.s); + STR_APPEND(buf, pad); + } + param = param->next; + } + + STR_APPEND(buf, contact_e); + STR_APPEND(buf, registration_e); + } + } + + STR_APPEND(buf, r_reginfo_e); + + + x.s = pkg_malloc(buf.len + 1); + if(x.s) { + x.len = buf.len; + memcpy(x.s, buf.s, buf.len); + x.s[x.len] = 0; + } + return x; } /** * Callback for the UAC response to NOTIFY */ -void uac_request_cb(struct cell *t, int type, struct tmcb_params * ps) { - LM_DBG("received NOTIFY reply type [%d] and code [%d]\n", type, ps->code); +void uac_request_cb(struct cell *t, int type, struct tmcb_params *ps) +{ + LM_DBG("received NOTIFY reply type [%d] and code [%d]\n", type, ps->code); } -static int free_tm_dlg(dlg_t * td) { - if (td) { - if (td->route_set) - free_rr(&td->route_set); - pkg_free(td); - } - return 0; +static int free_tm_dlg(dlg_t *td) +{ + if(td) { + if(td->route_set) + free_rr(&td->route_set); + pkg_free(td); + } + return 0; } /** @@ -2096,111 +2378,127 @@ static int free_tm_dlg(dlg_t * td) { */ -void send_notification(reg_notification * n) { - str h = {0, 0}; - str content = {0, 0}; - uac_req_t uac_r; - dlg_t* td = NULL; - char bufc[MAX_REGINFO_SIZE]; - str buf; - - struct udomain* domain = (struct udomain*) n->_d; - if (!domain) { - ul.register_udomain("location", &domain); - } - - LM_DBG("Have a notification to send for the following IMPUs using domain [%.*s]\n", domain->name->len, domain->name->s); - - - content = generate_reginfo_full(domain, n->impus, n->num_impus, n->explit_dereg_contact, &n->watcher_contact, n->num_explit_dereg_contact, n->reginfo_s_version); - - if (content.len > MAX_REGINFO_SIZE) { - LM_ERR("content size (%d) exceeds MAX_REGINFO_SIZE (%d)!\n", content.len, MAX_REGINFO_SIZE); - if (content.s) { - pkg_free(content.s); - } - return; - } - - memset(bufc, 0, sizeof(bufc)); - memcpy(bufc, content.s, content.len); - - buf.s = bufc; - buf.len = strlen(bufc); - - str method = {"NOTIFY", 6}; - - LM_DBG("Notification content: [%.*s]\n", buf.len, buf.s); - LM_DBG("DBG:send_notification: NOTIFY about <%.*s>\n", n->watcher_uri.len, n->watcher_uri.s); - - h.len = 0; - h.len += contact_hdr1.len + scscf_name_str.len + contact_hdr2.len; - if (n->subscription_state.len) h.len += subss_hdr1.len + subss_hdr2.len + n->subscription_state.len; - h.len += event_hdr.len; - h.len += maxfwds_hdr.len; - if (n->content_type.len) h.len += ctype_hdr1.len + ctype_hdr2.len + n->content_type.len; - h.s = pkg_malloc(h.len); - if (!h.s) { - LM_ERR("ERR:send_notification: Error allocating %d bytes\n", h.len); - h.len = 0; - } - - - //Add SCSCF name as contact address - h.len = 0; - STR_APPEND(h, contact_hdr1); - STR_APPEND(h, scscf_name_str); - STR_APPEND(h, contact_hdr2); - - STR_APPEND(h, event_hdr); - STR_APPEND(h, maxfwds_hdr); - if (n->subscription_state.len) { - STR_APPEND(h, subss_hdr1); - STR_APPEND(h, n->subscription_state); - STR_APPEND(h, subss_hdr2); - } - if (n->content_type.len) { - STR_APPEND(h, ctype_hdr1); - STR_APPEND(h, n->content_type); - STR_APPEND(h, ctype_hdr2); - } - - /* construct the dlg_t structure */ - td = build_dlg_t_from_notification(n); - if (td == NULL) { - LM_ERR("while building dlg_t structure\n"); - free_tm_dlg(td); - if (content.s) { - pkg_free(content.s); - } - return; - } - - if (buf.len) { - LM_DBG("Notification content exists - about to send notification with subscription state: [%.*s] content_type: [%.*s] content: [%.*s] : presentity_uri: [%.*s] watcher_uri: [%.*s]\n", - n->subscription_state.len, n->subscription_state.s, n->content_type.len, n->content_type.s, buf.len, buf.s, - n->presentity_uri.len, n->presentity_uri.s, n->watcher_uri.len, n->watcher_uri.s); - - set_uac_req(&uac_r, &method, &h, &buf, td, TMCB_LOCAL_COMPLETED, - uac_request_cb, 0); - tmb.t_request_within(&uac_r); - } else { - LM_DBG("o notification content - about to send notification with subscription state: [%.*s] presentity_uri: [%.*s] watcher_uri: [%.*s]\n", - n->subscription_state.len, n->subscription_state.s, n->presentity_uri.len, n->presentity_uri.s, - n->watcher_uri.len, n->watcher_uri.s); - - - set_uac_req(&uac_r, &method, &h, 0, td, TMCB_LOCAL_COMPLETED, - uac_request_cb, 0); - tmb.t_request_within(&uac_r); - } - if (h.s) pkg_free(h.s); - if (content.s) { - pkg_free(content.s); - } - - free_tm_dlg(td); +void send_notification(reg_notification *n) +{ + str h = {0, 0}; + str content = {0, 0}; + uac_req_t uac_r; + dlg_t *td = NULL; + char bufc[MAX_REGINFO_SIZE]; + str buf; + + struct udomain *domain = (struct udomain *)n->_d; + if(!domain) { + ul.register_udomain("location", &domain); + } + + LM_DBG("Have a notification to send for the following IMPUs using domain " + "[%.*s]\n", + domain->name->len, domain->name->s); + + + content = generate_reginfo_full(domain, n->impus, n->num_impus, + n->explit_dereg_contact, &n->watcher_contact, + n->num_explit_dereg_contact, n->reginfo_s_version); + + if(content.len > MAX_REGINFO_SIZE) { + LM_ERR("content size (%d) exceeds MAX_REGINFO_SIZE (%d)!\n", + content.len, MAX_REGINFO_SIZE); + if(content.s) { + pkg_free(content.s); + } + return; + } + + memset(bufc, 0, sizeof(bufc)); + memcpy(bufc, content.s, content.len); + + buf.s = bufc; + buf.len = strlen(bufc); + + str method = {"NOTIFY", 6}; + + LM_DBG("Notification content: [%.*s]\n", buf.len, buf.s); + LM_DBG("DBG:send_notification: NOTIFY about <%.*s>\n", n->watcher_uri.len, + n->watcher_uri.s); + + h.len = 0; + h.len += contact_hdr1.len + scscf_name_str.len + contact_hdr2.len; + if(n->subscription_state.len) + h.len += subss_hdr1.len + subss_hdr2.len + n->subscription_state.len; + h.len += event_hdr.len; + h.len += maxfwds_hdr.len; + if(n->content_type.len) + h.len += ctype_hdr1.len + ctype_hdr2.len + n->content_type.len; + h.s = pkg_malloc(h.len); + if(!h.s) { + LM_ERR("ERR:send_notification: Error allocating %d bytes\n", h.len); + h.len = 0; + } + + + //Add SCSCF name as contact address + h.len = 0; + STR_APPEND(h, contact_hdr1); + STR_APPEND(h, scscf_name_str); + STR_APPEND(h, contact_hdr2); + + STR_APPEND(h, event_hdr); + STR_APPEND(h, maxfwds_hdr); + if(n->subscription_state.len) { + STR_APPEND(h, subss_hdr1); + STR_APPEND(h, n->subscription_state); + STR_APPEND(h, subss_hdr2); + } + if(n->content_type.len) { + STR_APPEND(h, ctype_hdr1); + STR_APPEND(h, n->content_type); + STR_APPEND(h, ctype_hdr2); + } + + /* construct the dlg_t structure */ + td = build_dlg_t_from_notification(n); + if(td == NULL) { + LM_ERR("while building dlg_t structure\n"); + free_tm_dlg(td); + if(content.s) { + pkg_free(content.s); + } + return; + } + + if(buf.len) { + LM_DBG("Notification content exists - about to send notification with " + "subscription state: [%.*s] content_type: [%.*s] content: " + "[%.*s] : presentity_uri: [%.*s] watcher_uri: [%.*s]\n", + n->subscription_state.len, n->subscription_state.s, + n->content_type.len, n->content_type.s, buf.len, buf.s, + n->presentity_uri.len, n->presentity_uri.s, n->watcher_uri.len, + n->watcher_uri.s); + + set_uac_req(&uac_r, &method, &h, &buf, td, TMCB_LOCAL_COMPLETED, + uac_request_cb, 0); + tmb.t_request_within(&uac_r); + } else { + LM_DBG("o notification content - about to send notification with " + "subscription state: [%.*s] presentity_uri: [%.*s] watcher_uri: " + "[%.*s]\n", + n->subscription_state.len, n->subscription_state.s, + n->presentity_uri.len, n->presentity_uri.s, n->watcher_uri.len, + n->watcher_uri.s); + + + set_uac_req(&uac_r, &method, &h, 0, td, TMCB_LOCAL_COMPLETED, + uac_request_cb, 0); + tmb.t_request_within(&uac_r); + } + if(h.s) + pkg_free(h.s); + if(content.s) { + pkg_free(content.s); + } + free_tm_dlg(td); } /** @@ -2214,285 +2512,307 @@ void send_notification(reg_notification * n) { * @param dialog - dialog to send on * @returns the r_notification or NULL on error */ -reg_notification * new_notification(str subscription_state, - str content_type, str** impus, int num_impus, reg_subscriber * r, str** explit_dereg_contact, int num_explit_dereg_contact) { - int i; - reg_notification *n = 0; - int len; - char *p; - - len = sizeof (reg_notification) + r->call_id.len + r->from_tag.len + r->to_tag.len + r->watcher_uri.len + r->watcher_contact.len + - r->record_route.len + r->sockinfo_str.len + r->presentity_uri.len + subscription_state.len + content_type.len + (num_impus) * sizeof (str) + (num_explit_dereg_contact) * sizeof (str); // + buf.len; - for (i = 0; i < num_impus; i++) { - len += (*impus)[i].len; - } - - for (i = 0; i < num_explit_dereg_contact; i++) { - len += (*explit_dereg_contact)[i].len; - } - - LM_DBG("Creating new notification\n"); - - n = (reg_notification*) shm_malloc(len); - if (n == 0) { - LM_ERR("no more shm mem (%d)\n", len); - return 0; - } - memset(n, 0, len); - - p = (char*) (n + 1); - - n->reginfo_s_version = r->version; - - n->local_cseq = r->local_cseq; - - n->call_id.s = p; - n->call_id.len = r->call_id.len; - memcpy(p, r->call_id.s, r->call_id.len); - p += r->call_id.len; - LM_DBG("call id: [%.*s]\n", n->call_id.len, n->call_id.s); - - n->from_tag.s = p; - n->from_tag.len = r->from_tag.len; - memcpy(p, r->from_tag.s, r->from_tag.len); - p += r->from_tag.len; - LM_DBG("from tag: [%.*s]\n", n->from_tag.len, n->from_tag.s); - - n->to_tag.s = p; - n->to_tag.len = r->to_tag.len; - memcpy(p, r->to_tag.s, r->to_tag.len); - p += r->to_tag.len; - LM_DBG("to tag: [%.*s]\n", n->to_tag.len, n->to_tag.s); - - n->watcher_uri.s = p; - n->watcher_uri.len = r->watcher_uri.len; - memcpy(p, r->watcher_uri.s, r->watcher_uri.len); - p += r->watcher_uri.len; - LM_DBG("watcher_uri: [%.*s]\n", n->watcher_uri.len, n->watcher_uri.s); - - n->watcher_contact.s = p; - n->watcher_contact.len = r->watcher_contact.len; - memcpy(p, r->watcher_contact.s, r->watcher_contact.len); - p += r->watcher_contact.len; - LM_DBG("watcher_contact: [%.*s]\n", n->watcher_contact.len, n->watcher_contact.s); - - n->record_route.s = p; - n->record_route.len = r->record_route.len; - memcpy(p, r->record_route.s, r->record_route.len); - p += r->record_route.len; - LM_DBG("record_route: [%.*s]\n", n->record_route.len, n->record_route.s); - - n->sockinfo_str.s = p; - n->sockinfo_str.len = r->sockinfo_str.len; - memcpy(p, r->sockinfo_str.s, r->sockinfo_str.len); - p += r->sockinfo_str.len; - LM_DBG("sockinfo_str: [%.*s]\n", n->sockinfo_str.len, n->sockinfo_str.s); - - n->presentity_uri.s = p; - n->presentity_uri.len = r->presentity_uri.len; - memcpy(p, r->presentity_uri.s, r->presentity_uri.len); - p += r->presentity_uri.len; - LM_DBG("presentity_uri: [%.*s]\n", n->presentity_uri.len, n->presentity_uri.s); - - n->subscription_state.s = p; - n->subscription_state.len = subscription_state.len; - memcpy(p, subscription_state.s, subscription_state.len); - p += subscription_state.len; - LM_DBG("Notification subscription state: [%.*s]\n", n->subscription_state.len, n->subscription_state.s); - - n->content_type.s = p; - n->content_type.len = content_type.len; - memcpy(p, content_type.s, content_type.len); - p += content_type.len; - LM_DBG("Notification content type: [%.*s]\n", n->content_type.len, n->content_type.s); - - n->impus = (str*) p; - p += sizeof (str) * num_impus; - - for (i = 0; i < num_impus; i++) { - n->impus[i].s = p; - memcpy(p, (*impus)[i].s, (*impus)[i].len); - n->impus[i].len = (*impus)[i].len; - p += (*impus)[i].len; - } - n->num_impus = num_impus; - - if (num_explit_dereg_contact > 0) { - n->explit_dereg_contact = (str*) p; - p += sizeof (str) * num_explit_dereg_contact; - - for (i = 0; i < num_explit_dereg_contact; i++) { - n->explit_dereg_contact[i].s = p; - memcpy(p, (*explit_dereg_contact)[i].s, (*explit_dereg_contact)[i].len); - n->explit_dereg_contact[i].len = (*explit_dereg_contact)[i].len; - p += (*explit_dereg_contact)[i].len; - } - n->num_explit_dereg_contact = num_explit_dereg_contact; - } - - if (p != (((char*) n) + len)) { - LM_CRIT("buffer overflow\n"); - free_notification(n); - return 0; - } - - return n; +reg_notification *new_notification(str subscription_state, str content_type, + str **impus, int num_impus, reg_subscriber *r, + str **explit_dereg_contact, int num_explit_dereg_contact) +{ + int i; + reg_notification *n = 0; + int len; + char *p; + + len = sizeof(reg_notification) + r->call_id.len + r->from_tag.len + + r->to_tag.len + r->watcher_uri.len + r->watcher_contact.len + + r->record_route.len + r->sockinfo_str.len + r->presentity_uri.len + + subscription_state.len + content_type.len + + (num_impus) * sizeof(str) + + (num_explit_dereg_contact) * sizeof(str); // + buf.len; + for(i = 0; i < num_impus; i++) { + len += (*impus)[i].len; + } + + for(i = 0; i < num_explit_dereg_contact; i++) { + len += (*explit_dereg_contact)[i].len; + } + + LM_DBG("Creating new notification\n"); + + n = (reg_notification *)shm_malloc(len); + if(n == 0) { + LM_ERR("no more shm mem (%d)\n", len); + return 0; + } + memset(n, 0, len); + + p = (char *)(n + 1); + + n->reginfo_s_version = r->version; + + n->local_cseq = r->local_cseq; + + n->call_id.s = p; + n->call_id.len = r->call_id.len; + memcpy(p, r->call_id.s, r->call_id.len); + p += r->call_id.len; + LM_DBG("call id: [%.*s]\n", n->call_id.len, n->call_id.s); + + n->from_tag.s = p; + n->from_tag.len = r->from_tag.len; + memcpy(p, r->from_tag.s, r->from_tag.len); + p += r->from_tag.len; + LM_DBG("from tag: [%.*s]\n", n->from_tag.len, n->from_tag.s); + + n->to_tag.s = p; + n->to_tag.len = r->to_tag.len; + memcpy(p, r->to_tag.s, r->to_tag.len); + p += r->to_tag.len; + LM_DBG("to tag: [%.*s]\n", n->to_tag.len, n->to_tag.s); + + n->watcher_uri.s = p; + n->watcher_uri.len = r->watcher_uri.len; + memcpy(p, r->watcher_uri.s, r->watcher_uri.len); + p += r->watcher_uri.len; + LM_DBG("watcher_uri: [%.*s]\n", n->watcher_uri.len, n->watcher_uri.s); + + n->watcher_contact.s = p; + n->watcher_contact.len = r->watcher_contact.len; + memcpy(p, r->watcher_contact.s, r->watcher_contact.len); + p += r->watcher_contact.len; + LM_DBG("watcher_contact: [%.*s]\n", n->watcher_contact.len, + n->watcher_contact.s); + + n->record_route.s = p; + n->record_route.len = r->record_route.len; + memcpy(p, r->record_route.s, r->record_route.len); + p += r->record_route.len; + LM_DBG("record_route: [%.*s]\n", n->record_route.len, n->record_route.s); + + n->sockinfo_str.s = p; + n->sockinfo_str.len = r->sockinfo_str.len; + memcpy(p, r->sockinfo_str.s, r->sockinfo_str.len); + p += r->sockinfo_str.len; + LM_DBG("sockinfo_str: [%.*s]\n", n->sockinfo_str.len, n->sockinfo_str.s); + + n->presentity_uri.s = p; + n->presentity_uri.len = r->presentity_uri.len; + memcpy(p, r->presentity_uri.s, r->presentity_uri.len); + p += r->presentity_uri.len; + LM_DBG("presentity_uri: [%.*s]\n", n->presentity_uri.len, + n->presentity_uri.s); + + n->subscription_state.s = p; + n->subscription_state.len = subscription_state.len; + memcpy(p, subscription_state.s, subscription_state.len); + p += subscription_state.len; + LM_DBG("Notification subscription state: [%.*s]\n", + n->subscription_state.len, n->subscription_state.s); + + n->content_type.s = p; + n->content_type.len = content_type.len; + memcpy(p, content_type.s, content_type.len); + p += content_type.len; + LM_DBG("Notification content type: [%.*s]\n", n->content_type.len, + n->content_type.s); + + n->impus = (str *)p; + p += sizeof(str) * num_impus; + + for(i = 0; i < num_impus; i++) { + n->impus[i].s = p; + memcpy(p, (*impus)[i].s, (*impus)[i].len); + n->impus[i].len = (*impus)[i].len; + p += (*impus)[i].len; + } + n->num_impus = num_impus; + + if(num_explit_dereg_contact > 0) { + n->explit_dereg_contact = (str *)p; + p += sizeof(str) * num_explit_dereg_contact; + + for(i = 0; i < num_explit_dereg_contact; i++) { + n->explit_dereg_contact[i].s = p; + memcpy(p, (*explit_dereg_contact)[i].s, + (*explit_dereg_contact)[i].len); + n->explit_dereg_contact[i].len = (*explit_dereg_contact)[i].len; + p += (*explit_dereg_contact)[i].len; + } + n->num_explit_dereg_contact = num_explit_dereg_contact; + } + + if(p != (((char *)n) + len)) { + LM_CRIT("buffer overflow\n"); + free_notification(n); + return 0; + } + + return n; } /** * Adds a notification to the list of notifications at the end (FIFO). * @param n - the notification to be added */ -void add_notification(reg_notification * n) { - - LM_DBG("Adding notification\n"); - if (!n) { - LM_DBG("Notification does not exist\n"); - return; - } else { - LM_DBG("Notification exists\n"); - } - - if (max_notification_list_size > 0 && ((notification_list->size+1) > max_notification_list_size )) { - LM_WARN("Dropping notification, list too big [%d]\n", notification_list->size); +void add_notification(reg_notification *n) +{ + + LM_DBG("Adding notification\n"); + if(!n) { + LM_DBG("Notification does not exist\n"); + return; + } else { + LM_DBG("Notification exists\n"); + } + + if(max_notification_list_size > 0 + && ((notification_list->size + 1) > max_notification_list_size)) { + LM_WARN("Dropping notification, list too big [%d]\n", + notification_list->size); return; } - - LM_DBG("Adding to notification list\n"); - lock_get(notification_list->lock); - n->next = 0; - n->prev = notification_list->tail; - if (notification_list->tail) notification_list->tail->next = n; - notification_list->tail = n; - if (!notification_list->head) notification_list->head = n; - notification_list->size++; - if (notification_list_size_threshold > 0 && notification_list->size > notification_list_size_threshold) { - LM_WARN("notification_list is size [%d] and has exceed notification_list_size_threshold of [%d]\n", notification_list->size, notification_list_size_threshold); - } - - sem_release(notification_list->empty); - lock_release(notification_list->lock); + + LM_DBG("Adding to notification list\n"); + lock_get(notification_list->lock); + n->next = 0; + n->prev = notification_list->tail; + if(notification_list->tail) + notification_list->tail->next = n; + notification_list->tail = n; + if(!notification_list->head) + notification_list->head = n; + notification_list->size++; + if(notification_list_size_threshold > 0 + && notification_list->size > notification_list_size_threshold) { + LM_WARN("notification_list is size [%d] and has exceed " + "notification_list_size_threshold of [%d]\n", + notification_list->size, notification_list_size_threshold); + } + + sem_release(notification_list->empty); + lock_release(notification_list->lock); } /** * Pop a notification to the list of notifications from the top */ -reg_notification* get_notification() { - reg_notification * n; - - lock_get(notification_list->lock); - while (notification_list->head == 0) { - lock_release(notification_list->lock); - sem_get(notification_list->empty); - lock_get(notification_list->lock); - } - - n = notification_list->head; - notification_list->head = n->next; - - if (n == notification_list->tail) { //list now empty - notification_list->tail = 0; - } - n->next = 0; //make sure whoever gets this can't access our list - notification_list->size--; - lock_release(notification_list->lock); - - return n; +reg_notification *get_notification() +{ + reg_notification *n; + + lock_get(notification_list->lock); + while(notification_list->head == 0) { + lock_release(notification_list->lock); + sem_get(notification_list->empty); + lock_get(notification_list->lock); + } + + n = notification_list->head; + notification_list->head = n->next; + + if(n == notification_list->tail) { //list now empty + notification_list->tail = 0; + } + n->next = 0; //make sure whoever gets this can't access our list + notification_list->size--; + lock_release(notification_list->lock); + + return n; } /** * This is the main event process for notifications to be sent */ -void notification_event_process() { +void notification_event_process() +{ - reg_notification *n = 0; + reg_notification *n = 0; - LM_DBG("Running notification_event_process\n"); + LM_DBG("Running notification_event_process\n"); - for (;;) { - n = get_notification(); - LM_DBG("About to send notification\n"); - send_notification(n); - LM_DBG("About to free notification\n"); - free_notification(n); - } + for(;;) { + n = get_notification(); + LM_DBG("About to send notification\n"); + send_notification(n); + LM_DBG("About to free notification\n"); + free_notification(n); + } } /** * Frees up space taken by a notification * @param n - the notification to be freed */ -void free_notification(reg_notification * n) { - if (n) { - shm_free(n); - } +void free_notification(reg_notification *n) +{ + if(n) { + shm_free(n); + } } -dlg_t * build_dlg_t_from_notification(reg_notification * n) { - dlg_t* td = NULL; - td = (dlg_t*) pkg_malloc(sizeof (dlg_t)); - if (td == NULL) { - LM_ERR("Error ran out of package memory\n"); - } - memset(td, 0, sizeof (dlg_t)); - - LM_DBG("Building dlg_t structure\n"); - - td->loc_seq.value = n->local_cseq; - LM_DBG("local cseq %d\n", n->local_cseq); - td->loc_seq.is_set = 1; - - td->id.call_id = n->call_id; - LM_DBG("call id %.*s\n", n->call_id.len, n->call_id.s); - - td->id.rem_tag = n->from_tag; - LM_DBG("ftag %.*s\n", n->from_tag.len, n->from_tag.s); - - - td->id.loc_tag = n->to_tag; - LM_DBG("ttag %.*s\n", n->to_tag.len, n->to_tag.s); - - - td->loc_uri = n->presentity_uri; - LM_DBG("loc uri %.*s\n", n->presentity_uri.len, n->presentity_uri.s); - - td->rem_target = n->watcher_contact; - LM_DBG("rem target %.*s\n", n->watcher_contact.len, n->watcher_contact.s); - - td->rem_uri = n->watcher_uri; - LM_DBG("rem uri %.*s\n", n->watcher_uri.len, n->watcher_uri.s); - - if (n->record_route.s && n->record_route.len) { - if (parse_rr_body(n->record_route.s, n->record_route.len, - &td->route_set) < 0) { - LM_ERR("in function parse_rr_body\n"); - goto error; - } - } - td->state = DLG_CONFIRMED; - - if (n->sockinfo_str.len) { - int port, proto; - str host; - char* tmp; - if ((tmp = as_asciiz(&n->sockinfo_str)) == NULL) { - LM_ERR("no pkg memory left\n"); - goto error; - } - if (parse_phostport(tmp, &host.s, - &host.len, &port, &proto)) { - LM_ERR("bad sockinfo string\n"); - pkg_free(tmp); - goto error; - } - pkg_free(tmp); - td->send_sock = grep_sock_info( - &host, (unsigned short) port, (unsigned short) proto); - } - - return td; +dlg_t *build_dlg_t_from_notification(reg_notification *n) +{ + dlg_t *td = NULL; + td = (dlg_t *)pkg_malloc(sizeof(dlg_t)); + if(td == NULL) { + LM_ERR("Error ran out of package memory\n"); + } + memset(td, 0, sizeof(dlg_t)); + + LM_DBG("Building dlg_t structure\n"); + + td->loc_seq.value = n->local_cseq; + LM_DBG("local cseq %d\n", n->local_cseq); + td->loc_seq.is_set = 1; + + td->id.call_id = n->call_id; + LM_DBG("call id %.*s\n", n->call_id.len, n->call_id.s); + + td->id.rem_tag = n->from_tag; + LM_DBG("ftag %.*s\n", n->from_tag.len, n->from_tag.s); + + + td->id.loc_tag = n->to_tag; + LM_DBG("ttag %.*s\n", n->to_tag.len, n->to_tag.s); + + + td->loc_uri = n->presentity_uri; + LM_DBG("loc uri %.*s\n", n->presentity_uri.len, n->presentity_uri.s); + + td->rem_target = n->watcher_contact; + LM_DBG("rem target %.*s\n", n->watcher_contact.len, n->watcher_contact.s); + + td->rem_uri = n->watcher_uri; + LM_DBG("rem uri %.*s\n", n->watcher_uri.len, n->watcher_uri.s); + + if(n->record_route.s && n->record_route.len) { + if(parse_rr_body(n->record_route.s, n->record_route.len, &td->route_set) + < 0) { + LM_ERR("in function parse_rr_body\n"); + goto error; + } + } + td->state = DLG_CONFIRMED; + + if(n->sockinfo_str.len) { + int port, proto; + str host; + char *tmp; + if((tmp = as_asciiz(&n->sockinfo_str)) == NULL) { + LM_ERR("no pkg memory left\n"); + goto error; + } + if(parse_phostport(tmp, &host.s, &host.len, &port, &proto)) { + LM_ERR("bad sockinfo string\n"); + pkg_free(tmp); + goto error; + } + pkg_free(tmp); + td->send_sock = grep_sock_info( + &host, (unsigned short)port, (unsigned short)proto); + } + + return td; error: - free_tm_dlg(td); - return NULL; + free_tm_dlg(td); + return NULL; } diff --git a/src/modules/ims_registrar_scscf/registrar_notify.h b/src/modules/ims_registrar_scscf/registrar_notify.h index 04d4958488d..841dfd0f504 100644 --- a/src/modules/ims_registrar_scscf/registrar_notify.h +++ b/src/modules/ims_registrar_scscf/registrar_notify.h @@ -56,73 +56,77 @@ #define MSG_REG_UNSUBSCRIBE_OK "Subscription to REG dropped" #define MSG_REG_PUBLISH_OK "Publish to REG saved" -typedef struct _reg_notification { - - str subscription_state; /**< Subscription-state header value*/ - str content_type; /**< content type */ - - str watcher_contact; - str watcher_uri; - str presentity_uri; - - struct udomain* _d; - str* impus; - int num_impus; - - unsigned int local_cseq; - unsigned int reginfo_s_version; - str call_id; - str from_tag; - str to_tag; - str record_route; - str sockinfo_str; - - str *explit_dereg_contact; - int num_explit_dereg_contact; - - struct _reg_notification *next; /**< next notification in the list */ - struct _reg_notification *prev; /**< previous notification in the list */ -} reg_notification; +typedef struct _reg_notification +{ + + str subscription_state; /**< Subscription-state header value*/ + str content_type; /**< content type */ + + str watcher_contact; + str watcher_uri; + str presentity_uri; + + struct udomain *_d; + str *impus; + int num_impus; + unsigned int local_cseq; + unsigned int reginfo_s_version; + str call_id; + str from_tag; + str to_tag; + str record_route; + str sockinfo_str; + + str *explit_dereg_contact; + int num_explit_dereg_contact; + + struct _reg_notification *next; /**< next notification in the list */ + struct _reg_notification *prev; /**< previous notification in the list */ +} reg_notification; /** Notification List Structure */ -typedef struct { - gen_lock_t *lock; /**< lock for notifications ops */ - reg_notification *head; /**< first notification in the list */ - reg_notification *tail; /**< last notification in the list */ - gen_sem_t *empty; - int size; +typedef struct +{ + gen_lock_t *lock; /**< lock for notifications ops */ + reg_notification *head; /**< first notification in the list */ + reg_notification *tail; /**< last notification in the list */ + gen_sem_t *empty; + int size; } reg_notification_list; /** Events for subscriptions */ -typedef enum { - IMS_EVENT_NONE, /**< Generic, no event */ - IMS_EVENT_REG /**< Registration event */ +typedef enum +{ + IMS_EVENT_NONE, /**< Generic, no event */ + IMS_EVENT_REG /**< Registration event */ } IMS_Events_enum_t; extern IMS_Events_enum_t IMS_Events; /** Event types for "reg" to generated notifications after */ -typedef enum { - IMS_REGISTRAR_NONE, /**< no event - donothing */ - IMS_REGISTRAR_SUBSCRIBE, /**< Initial SUBSCRIBE - just send all data - this should not be treated though */ - IMS_REGISTRAR_UNSUBSCRIBE, /**< Final UnSUBSCRIBE - just send a NOTIFY which will probably fail */ - IMS_REGISTRAR_SUBSCRIBE_EXPIRED, /**< The subscribe has expired */ - - //richard we only use contact reg, refresh, expired and unreg - IMS_REGISTRAR_CONTACT_REGISTERED, /**< Registered with REGISTER */ - IMS_REGISTRAR_CONTACT_REFRESHED, /**< The expiration was refreshed */ - IMS_REGISTRAR_CONTACT_EXPIRED, /**< A contact has expired and will be removed */ - IMS_REGISTRAR_CONTACT_UNREGISTERED, /**< User unregistered with Expires 0 */ - IMS_REGISTRAR_CONTACT_UNREGISTERED_IMPLICIT, /**< User unregistered implicitly, ie not via explicit deregister */ - IMS_REGISTRAR_SUBSEQUENT_SUBSCRIBE, - IMS_REGISTRAR_CONTACT_DEREGISTERED, /**< User's registration was terminated with RTR */ +typedef enum +{ + IMS_REGISTRAR_NONE, /**< no event - donothing */ + IMS_REGISTRAR_SUBSCRIBE, /**< Initial SUBSCRIBE - just send all data - this should not be treated though */ + IMS_REGISTRAR_UNSUBSCRIBE, /**< Final UnSUBSCRIBE - just send a NOTIFY which will probably fail */ + IMS_REGISTRAR_SUBSCRIBE_EXPIRED, /**< The subscribe has expired */ + + //richard we only use contact reg, refresh, expired and unreg + IMS_REGISTRAR_CONTACT_REGISTERED, /**< Registered with REGISTER */ + IMS_REGISTRAR_CONTACT_REFRESHED, /**< The expiration was refreshed */ + IMS_REGISTRAR_CONTACT_EXPIRED, /**< A contact has expired and will be removed */ + IMS_REGISTRAR_CONTACT_UNREGISTERED, /**< User unregistered with Expires 0 */ + IMS_REGISTRAR_CONTACT_UNREGISTERED_IMPLICIT, /**< User unregistered implicitly, ie not via explicit deregister */ + IMS_REGISTRAR_SUBSEQUENT_SUBSCRIBE, + IMS_REGISTRAR_CONTACT_DEREGISTERED, /**< User's registration was terminated with RTR */ } IMS_Registrar_events_enum_t; extern IMS_Registrar_events_enum_t IMS_Registrar_events; -extern reg_notification_list *notification_list; //< List of pending notifications +extern reg_notification_list + *notification_list; //< List of pending notifications int can_subscribe_to_reg(struct sip_msg *msg, char *str1, char *str2); @@ -132,39 +136,50 @@ int can_publish_reg(struct sip_msg *msg, char *str1, char *str2); int publish_reg(struct sip_msg *msg, char *str1, char *str2); -int subscribe_reply(struct sip_msg *msg, int code, char *text, int *expires, str *contact); +int subscribe_reply( + struct sip_msg *msg, int code, char *text, int *expires, str *contact); -int event_reg(udomain_t* _d, impurecord_t* r_passed, ucontact_t* c_passed, int event_type, str *presentity_uri, str *watcher_contact, str *contact_uri, - str *explit_dereg_contact, int num_explit_dereg_contact); +int event_reg(udomain_t *_d, impurecord_t *r_passed, ucontact_t *c_passed, + int event_type, str *presentity_uri, str *watcher_contact, + str *contact_uri, str *explit_dereg_contact, + int num_explit_dereg_contact); -str generate_reginfo_full(udomain_t* _t, str* impu_list, int new_subscription, str *explit_dereg_contact, str* watcher_contact, int num_explit_dereg_contact, unsigned int reginfo_version); +str generate_reginfo_full(udomain_t *_t, str *impu_list, int new_subscription, + str *explit_dereg_contact, str *watcher_contact, + int num_explit_dereg_contact, unsigned int reginfo_version); -str get_reginfo_partial(impurecord_t *r, ucontact_t *c, int event_type, unsigned int reginfo_version); +str get_reginfo_partial(impurecord_t *r, ucontact_t *c, int event_type, + unsigned int reginfo_version); -void create_notifications(udomain_t* _t, impurecord_t* r_passed, ucontact_t* c_passed, str *presentity_uri, str *watcher_contact, str *contact_uri, - str* impus, int num_impus, int event_type, str *explit_dereg_contact, int num_explit_dereg_contact); +void create_notifications(udomain_t *_t, impurecord_t *r_passed, + ucontact_t *c_passed, str *presentity_uri, str *watcher_contact, + str *contact_uri, str *impus, int num_impus, int event_type, + str *explit_dereg_contact, int num_explit_dereg_contact); void notification_event_process(); void free_notification(reg_notification *n); -void send_notification(reg_notification * n); +void send_notification(reg_notification *n); void add_notification(reg_notification *n); -reg_notification* new_notification(str subscription_state, - str content_type, str** impus, int num_impus, reg_subscriber* r, str **explit_dereg_contact, int num_explit_dereg_contact); +reg_notification *new_notification(str subscription_state, str content_type, + str **impus, int num_impus, reg_subscriber *r, + str **explit_dereg_contact, int num_explit_dereg_contact); -dlg_t* build_dlg_t_from_notification(reg_notification* n); +dlg_t *build_dlg_t_from_notification(reg_notification *n); int notify_init(); void notify_destroy(); -int aor_to_contact(str* aor, str* contact); +int aor_to_contact(str *aor, str *contact); int contact_port_ip_match(str *c1, str *c2); -int notify_subscribers(impurecord_t* impurecord, ucontact_t* contact, str *explit_dereg_contact, int num_explit_dereg_contact, int event_type); +int notify_subscribers(impurecord_t *impurecord, ucontact_t *contact, + str *explit_dereg_contact, int num_explit_dereg_contact, + int event_type); #endif //S_CSCF_REGISTRAR_NOTIFY_H_ diff --git a/src/modules/ims_registrar_scscf/regpv.c b/src/modules/ims_registrar_scscf/regpv.c index d6d7027053a..81b80c55671 100644 --- a/src/modules/ims_registrar_scscf/regpv.c +++ b/src/modules/ims_registrar_scscf/regpv.c @@ -26,7 +26,7 @@ * \file * \brief SIP registrar module - export contacts as PV * \ingroup registrar - */ + */ #include @@ -38,53 +38,51 @@ #include "common.h" #include "regpv.h" -typedef struct _regpv_profile { +typedef struct _regpv_profile +{ str pname; str domain; str aor; int flags; unsigned int aorhash; int nrc; - ucontact_t* contacts; + ucontact_t *contacts; struct _regpv_profile *next; } regpv_profile_t; -typedef struct _regpv_name { +typedef struct _regpv_name +{ regpv_profile_t *rp; int attr; } regpv_name_t; static regpv_profile_t *_regpv_profile_list = NULL; -static inline regpv_profile_t* regpv_get_profile(str *name) +static inline regpv_profile_t *regpv_get_profile(str *name) { regpv_profile_t *rp; - if(name==NULL || name->len<=0) - { + if(name == NULL || name->len <= 0) { LM_ERR("invalid parameters\n"); return NULL; } rp = _regpv_profile_list; - while(rp) - { + while(rp) { if(rp->pname.len == name->len - && strncmp(rp->pname.s, name->s, name->len)==0) + && strncmp(rp->pname.s, name->s, name->len) == 0) return rp; rp = rp->next; } - rp = (regpv_profile_t*)pkg_malloc(sizeof(regpv_profile_t)); - if(rp==NULL) - { + rp = (regpv_profile_t *)pkg_malloc(sizeof(regpv_profile_t)); + if(rp == NULL) { LM_ERR("no more pkg\n"); return NULL; } memset(rp, 0, sizeof(regpv_profile_t)); - rp->pname.s = (char*)pkg_malloc((name->len+1)*sizeof(char)); - if(rp->pname.s==NULL) - { + rp->pname.s = (char *)pkg_malloc((name->len + 1) * sizeof(char)); + if(rp->pname.s == NULL) { LM_ERR("no more pkg\n"); pkg_free(rp); return NULL; @@ -100,26 +98,23 @@ static inline regpv_profile_t* regpv_get_profile(str *name) static void regpv_free_profile(regpv_profile_t *rpp) { - ucontact_t* ptr; - ucontact_t* ptr0; + ucontact_t *ptr; + ucontact_t *ptr0; - if(rpp==NULL) + if(rpp == NULL) return; ptr = rpp->contacts; - while(ptr) - { + while(ptr) { ptr0 = ptr; ptr = ptr->next; pkg_free(ptr0); } - if(rpp->domain.s!=NULL) - { + if(rpp->domain.s != NULL) { rpp->domain.s = 0; rpp->domain.len = 0; } - if(rpp->aor.s!=NULL) - { + if(rpp->aor.s != NULL) { pkg_free(rpp->aor.s); rpp->aor.s = 0; rpp->aor.len = 0; @@ -129,7 +124,6 @@ static void regpv_free_profile(regpv_profile_t *rpp) rpp->aorhash = 0; rpp->nrc = 0; rpp->contacts = 0; - } void regpv_free_profiles(void) @@ -139,9 +133,8 @@ void regpv_free_profiles(void) rp = _regpv_profile_list; - while(rp) - { - if(rp->pname.s!=NULL) + while(rp) { + if(rp->pname.s != NULL) pkg_free(rp->pname.s); rp0 = rp; regpv_free_profile(rp0); @@ -150,8 +143,7 @@ void regpv_free_profiles(void) _regpv_profile_list = 0; } -int pv_get_ulc(struct sip_msg *msg, pv_param_t *param, - pv_value_t *res) +int pv_get_ulc(struct sip_msg *msg, pv_param_t *param, pv_value_t *res) { regpv_name_t *rp; regpv_profile_t *rpp; @@ -159,112 +151,104 @@ int pv_get_ulc(struct sip_msg *msg, pv_param_t *param, int idx; int i; - if(param==NULL) - { + if(param == NULL) { LM_ERR("invalid params\n"); return -1; } - rp = (regpv_name_t*)param->pvn.u.dname; - if(rp==NULL || rp->rp==NULL) - { + rp = (regpv_name_t *)param->pvn.u.dname; + if(rp == NULL || rp->rp == NULL) { LM_DBG("no profile in params\n"); return pv_get_null(msg, param, res); } rpp = rp->rp; - if(rpp->flags==0 || rpp->contacts==NULL) - { + if(rpp->flags == 0 || rpp->contacts == NULL) { LM_DBG("profile not set or no contacts there\n"); return pv_get_null(msg, param, res); } /* get index */ - if(pv_get_spec_index(msg, param, &idx, &i)!=0) - { + if(pv_get_spec_index(msg, param, &idx, &i) != 0) { LM_ERR("invalid index\n"); return -1; } /* work only with positive indexes by now */ - if(idx<0) + if(idx < 0) idx = 0; /* get contact */ i = 0; c = rpp->contacts; - while(rpp) - { + while(rpp) { if(i == idx) break; i++; c = c->next; } - if(c==NULL) + if(c == NULL) return pv_get_null(msg, param, res); - switch(rp->attr) - { + switch(rp->attr) { case 0: /* aor */ - return pv_get_strval(msg, param, res, &rpp->aor); - break; + return pv_get_strval(msg, param, res, &rpp->aor); + break; case 1: /* domain */ - return pv_get_strval(msg, param, res, &rpp->domain); - break; + return pv_get_strval(msg, param, res, &rpp->domain); + break; case 2: /* aorhash */ return pv_get_uintval(msg, param, res, rpp->aorhash); - break; + break; case 3: /* addr */ - return pv_get_strval(msg, param, res, &c->c); - break; + return pv_get_strval(msg, param, res, &c->c); + break; case 4: /* path */ - return pv_get_strval(msg, param, res, &c->path); - break; + return pv_get_strval(msg, param, res, &c->path); + break; case 5: /* received */ - return pv_get_strval(msg, param, res, &c->received); - break; + return pv_get_strval(msg, param, res, &c->received); + break; case 6: /* expires */ - return pv_get_uintval(msg, param, res, - (unsigned int)c->expires); - break; + return pv_get_uintval(msg, param, res, (unsigned int)c->expires); + break; case 7: /* callid */ - return pv_get_strval(msg, param, res, &c->callid); - break; + return pv_get_strval(msg, param, res, &c->callid); + break; case 8: /* q */ return pv_get_sintval(msg, param, res, (int)c->q); - break; + break; case 9: /* cseq */ return pv_get_sintval(msg, param, res, c->cseq); - break; + break; case 10: /* flags */ return pv_get_uintval(msg, param, res, c->flags); - break; + break; case 11: /* cflags */ return pv_get_uintval(msg, param, res, c->cflags); - break; + break; case 12: /* user agent */ - return pv_get_strval(msg, param, res, &c->user_agent); - break; + return pv_get_strval(msg, param, res, &c->user_agent); + break; case 14: /* socket */ - if(c->sock==NULL) + if(c->sock == NULL) return pv_get_null(msg, param, res); return pv_get_strval(msg, param, res, &c->sock->sock_str); - break; + break; case 15: /* modified */ - return pv_get_uintval(msg, param, res, - (unsigned int)c->last_modified); - break; + return pv_get_uintval( + msg, param, res, (unsigned int)c->last_modified); + break; case 16: /* methods */ return pv_get_uintval(msg, param, res, c->methods); - break; + break; case 17: /* count */ return pv_get_sintval(msg, param, res, rpp->nrc); - break; + break; } return pv_get_null(msg, param, res); } -int pv_set_ulc(struct sip_msg* msg, pv_param_t *param, - int op, pv_value_t *val) +int pv_set_ulc(struct sip_msg *msg, pv_param_t *param, int op, pv_value_t *val) { return 0; } @@ -276,24 +260,21 @@ int pv_parse_ulc_name(pv_spec_p sp, str *in) regpv_name_t *rp; regpv_profile_t *rpp; - if(sp==NULL || in==NULL || in->len<=0) + if(sp == NULL || in == NULL || in->len <= 0) return -1; pa.s = in->s; - while(pa.s < in->s + in->len - 2) - { - if(*pa.s=='=') + while(pa.s < in->s + in->len - 2) { + if(*pa.s == '=') break; pa.s++; } - - if(pa.s >= in->s + in->len - 2) - { + + if(pa.s >= in->s + in->len - 2) { LM_ERR("invalid contact pv name %.*s\n", in->len, in->s); return -1; } - if(*(pa.s+1) != '>') - { + if(*(pa.s + 1) != '>') { LM_ERR("invalid contact pv name %.*s.\n", in->len, in->s); return -1; } @@ -304,8 +285,7 @@ int pv_parse_ulc_name(pv_spec_p sp, str *in) LM_DBG("get profile [%.*s]\n", pn.len, pn.s); rpp = regpv_get_profile(&pn); - if(rpp==NULL) - { + if(rpp == NULL) { LM_ERR("cannot get profile [%.*s]\n", pn.len, pn.s); return -1; } @@ -313,79 +293,85 @@ int pv_parse_ulc_name(pv_spec_p sp, str *in) pa.len = in->s + in->len - pa.s; LM_DBG("get attr [%.*s]\n", pa.len, pa.s); - rp = (regpv_name_t*)pkg_malloc(sizeof(regpv_name_t)); - if(rp==0) - { + rp = (regpv_name_t *)pkg_malloc(sizeof(regpv_name_t)); + if(rp == 0) { LM_ERR("no more pkg\n"); return -1; } memset(rp, 0, sizeof(regpv_name_t)); rp->rp = rpp; - switch(pa.len) - { - case 1: - if(strncmp(pa.s, "q", 1)==0) + switch(pa.len) { + case 1: + if(strncmp(pa.s, "q", 1) == 0) rp->attr = 8; - else goto error; - break; - case 3: - if(strncmp(pa.s, "aor", 3)==0) + else + goto error; + break; + case 3: + if(strncmp(pa.s, "aor", 3) == 0) rp->attr = 0; - else goto error; - break; - case 4: - if(strncmp(pa.s, "addr", 4)==0) + else + goto error; + break; + case 4: + if(strncmp(pa.s, "addr", 4) == 0) rp->attr = 3; - else if(strncmp(pa.s, "path", 4)==0) + else if(strncmp(pa.s, "path", 4) == 0) rp->attr = 4; - else if(strncmp(pa.s, "cseq", 4)==0) + else if(strncmp(pa.s, "cseq", 4) == 0) rp->attr = 9; - else goto error; - break; - case 5: - if(strncmp(pa.s, "flags", 5)==0) + else + goto error; + break; + case 5: + if(strncmp(pa.s, "flags", 5) == 0) rp->attr = 10; - else if(strncmp(pa.s, "count", 5)==0) + else if(strncmp(pa.s, "count", 5) == 0) rp->attr = 17; - else goto error; - break; - case 6: - if(strncmp(pa.s, "domain", 6)==0) + else + goto error; + break; + case 6: + if(strncmp(pa.s, "domain", 6) == 0) rp->attr = 1; - else if(strncmp(pa.s, "callid", 6)==0) + else if(strncmp(pa.s, "callid", 6) == 0) rp->attr = 7; - else if(strncmp(pa.s, "cflags", 6)==0) + else if(strncmp(pa.s, "cflags", 6) == 0) rp->attr = 11; - else if(strncmp(pa.s, "socket", 6)==0) + else if(strncmp(pa.s, "socket", 6) == 0) rp->attr = 14; - else goto error; - break; - case 7: - if(strncmp(pa.s, "aorhash", 7)==0) + else + goto error; + break; + case 7: + if(strncmp(pa.s, "aorhash", 7) == 0) rp->attr = 2; - else if(strncmp(pa.s, "expires", 7)==0) + else if(strncmp(pa.s, "expires", 7) == 0) rp->attr = 6; - else if(strncmp(pa.s, "methods", 7)==0) + else if(strncmp(pa.s, "methods", 7) == 0) rp->attr = 16; - else goto error; - break; - case 8: - if(strncmp(pa.s, "received", 8)==0) + else + goto error; + break; + case 8: + if(strncmp(pa.s, "received", 8) == 0) rp->attr = 5; - else if(strncmp(pa.s, "modified", 8)==0) + else if(strncmp(pa.s, "modified", 8) == 0) rp->attr = 15; - else goto error; - break; - case 10: - if(strncmp(pa.s, "user_agent", 10)==0) + else + goto error; + break; + case 10: + if(strncmp(pa.s, "user_agent", 10) == 0) rp->attr = 12; - else goto error; - break; + else + goto error; + break; default: goto error; } - sp->pvp.pvn.u.dname = (void*)rp; + sp->pvp.pvn.u.dname = (void *)rp; sp->pvp.pvn.type = PV_NAME_PVAR; return 0; @@ -395,13 +381,13 @@ int pv_parse_ulc_name(pv_spec_p sp, str *in) return -1; } -int pv_fetch_contacts(struct sip_msg* msg, char* table, char* uri, - char* profile) +int pv_fetch_contacts( + struct sip_msg *msg, char *table, char *uri, char *profile) { - impurecord_t* r; - ucontact_t* ptr; - ucontact_t* ptr0; - ucontact_t* c0; + impurecord_t *r; + ucontact_t *ptr; + ucontact_t *ptr0; + ucontact_t *c0; regpv_profile_t *rpp; str aor = {0, 0}; str u = {0, 0}; @@ -411,9 +397,8 @@ int pv_fetch_contacts(struct sip_msg* msg, char* table, char* uri, int n; char *p; - rpp = regpv_get_profile((str*)profile); - if(rpp==0) - { + rpp = regpv_get_profile((str *)profile); + if(rpp == 0) { LM_ERR("invalid parameters\n"); return -1; } @@ -422,51 +407,49 @@ int pv_fetch_contacts(struct sip_msg* msg, char* table, char* uri, if(rpp->flags) regpv_free_profile(rpp); - if(fixup_get_svalue(msg, (gparam_p)uri, &u)!=0 || u.len<=0) - { + if(fixup_get_svalue(msg, (gparam_p)uri, &u) != 0 || u.len <= 0) { LM_ERR("invalid uri parameter\n"); return -1; } - if (extract_aor(&u, &aor) < 0) { + if(extract_aor(&u, &aor) < 0) { LM_ERR("failed to extract Address Of Record\n"); return -1; } /* copy aor and ul domain */ - rpp->aor.s = (char*)pkg_malloc(aor.len*sizeof(char)); - if(rpp->aor.s==NULL) - { + rpp->aor.s = (char *)pkg_malloc(aor.len * sizeof(char)); + if(rpp->aor.s == NULL) { LM_ERR("no more pkg\n"); return -1; } memcpy(rpp->aor.s, aor.s, aor.len); rpp->aor.len = aor.len; - rpp->domain = *((udomain_head_t*)table)->name; + rpp->domain = *((udomain_head_t *)table)->name; rpp->flags = 1; /* copy contacts */ ilen = sizeof(ucontact_t); - ul.lock_udomain((udomain_t*)table, &aor); - res = ul.get_impurecord((udomain_t*)table, &aor, &r); - if (res != 0) { + ul.lock_udomain((udomain_t *)table, &aor); + res = ul.get_impurecord((udomain_t *)table, &aor, &r); + if(res != 0) { LM_DBG("'%.*s' Not found in usrloc\n", aor.len, ZSW(aor.s)); - ul.unlock_udomain((udomain_t*)table, &aor); + ul.unlock_udomain((udomain_t *)table, &aor); return -1; } - ptr = 0;//r->contacts;TODO + ptr = 0; //r->contacts;TODO ptr0 = NULL; n = 0; - while(ptr) - { - olen = (ptr->c.len + ptr->received.len + ptr->path.len - + ptr->callid.len + ptr->user_agent.len)*sizeof(char) + ilen; - c0 = (ucontact_t*)pkg_malloc(olen); - if(c0==NULL) - { + while(ptr) { + olen = (ptr->c.len + ptr->received.len + ptr->path.len + ptr->callid.len + + ptr->user_agent.len) + * sizeof(char) + + ilen; + c0 = (ucontact_t *)pkg_malloc(olen); + if(c0 == NULL) { LM_ERR("no more pkg\n"); - ul.unlock_udomain((udomain_t*)table, &aor); + ul.unlock_udomain((udomain_t *)table, &aor); goto error; } memcpy(c0, ptr, ilen); @@ -475,20 +458,18 @@ int pv_fetch_contacts(struct sip_msg* msg, char* table, char* uri, c0->next = NULL; c0->prev = NULL; - c0->c.s = (char*)c0 + ilen; + c0->c.s = (char *)c0 + ilen; memcpy(c0->c.s, ptr->c.s, ptr->c.len); c0->c.len = ptr->c.len; p = c0->c.s + c0->c.len; - - if(ptr->received.s!=NULL) - { + + if(ptr->received.s != NULL) { c0->received.s = p; memcpy(c0->received.s, ptr->received.s, ptr->received.len); c0->received.len = ptr->received.len; p += c0->received.len; } - if(ptr->path.s!=NULL) - { + if(ptr->path.s != NULL) { c0->path.s = p; memcpy(c0->path.s, ptr->path.s, ptr->path.len); c0->path.len = ptr->path.len; @@ -498,16 +479,14 @@ int pv_fetch_contacts(struct sip_msg* msg, char* table, char* uri, memcpy(c0->callid.s, ptr->callid.s, ptr->callid.len); c0->callid.len = ptr->callid.len; p += c0->callid.len; - if(ptr->user_agent.s!=NULL) - { + if(ptr->user_agent.s != NULL) { c0->user_agent.s = p; memcpy(c0->user_agent.s, ptr->user_agent.s, ptr->user_agent.len); c0->user_agent.len = ptr->user_agent.len; p += c0->user_agent.len; } - if(ptr0==NULL) - { + if(ptr0 == NULL) { rpp->contacts = c0; } else { ptr0->next = c0; @@ -517,22 +496,22 @@ int pv_fetch_contacts(struct sip_msg* msg, char* table, char* uri, ptr0 = c0; ptr = ptr->next; } - ul.unlock_udomain((udomain_t*)table, &aor); + ul.unlock_udomain((udomain_t *)table, &aor); rpp->nrc = n; - LM_DBG("fetched <%d> contacts for <%.*s> in [%.*s]\n", - n, aor.len, aor.s, rpp->pname.len, rpp->pname.s); + LM_DBG("fetched <%d> contacts for <%.*s> in [%.*s]\n", n, aor.len, aor.s, + rpp->pname.len, rpp->pname.s); return 1; error: regpv_free_profile(rpp); return -1; } -int pv_free_contacts(struct sip_msg* msg, char* profile, char* s2) +int pv_free_contacts(struct sip_msg *msg, char *profile, char *s2) { regpv_profile_t *rpp; - rpp = regpv_get_profile((str*)profile); - if(rpp==0) + rpp = regpv_get_profile((str *)profile); + if(rpp == 0) return -1; regpv_free_profile(rpp); diff --git a/src/modules/ims_registrar_scscf/regpv.h b/src/modules/ims_registrar_scscf/regpv.h index 98d469f5483..194ae30658f 100644 --- a/src/modules/ims_registrar_scscf/regpv.h +++ b/src/modules/ims_registrar_scscf/regpv.h @@ -26,7 +26,7 @@ * \file * \brief SIP registrar module - export contacts as PV * \ingroup registrar - */ + */ #ifndef _REGPV_H_ @@ -34,15 +34,13 @@ #include "../../core/pvar.h" -int pv_get_ulc(struct sip_msg *msg, pv_param_t *param, - pv_value_t *res); -int pv_set_ulc(struct sip_msg* msg, pv_param_t *param, - int op, pv_value_t *val); +int pv_get_ulc(struct sip_msg *msg, pv_param_t *param, pv_value_t *res); +int pv_set_ulc(struct sip_msg *msg, pv_param_t *param, int op, pv_value_t *val); int pv_parse_ulc_name(pv_spec_p sp, str *in); -int pv_fetch_contacts(struct sip_msg* msg, char* table, char* uri, - char* profile); -int pv_free_contacts(struct sip_msg* msg, char* profile, char *s2); +int pv_fetch_contacts( + struct sip_msg *msg, char *table, char *uri, char *profile); +int pv_free_contacts(struct sip_msg *msg, char *profile, char *s2); void regpv_free_profiles(void); diff --git a/src/modules/ims_registrar_scscf/regtime.h b/src/modules/ims_registrar_scscf/regtime.h index cf2d6e08c01..3c51dff17f9 100644 --- a/src/modules/ims_registrar_scscf/regtime.h +++ b/src/modules/ims_registrar_scscf/regtime.h @@ -26,7 +26,7 @@ * \file * \brief SIP registrar module - time related functions * \ingroup registrar - */ + */ #ifndef REGTIME_H diff --git a/src/modules/ims_registrar_scscf/reply.c b/src/modules/ims_registrar_scscf/reply.c index a0ffa35d5b1..620aec9abc2 100644 --- a/src/modules/ims_registrar_scscf/reply.c +++ b/src/modules/ims_registrar_scscf/reply.c @@ -70,10 +70,11 @@ extern int contact_expires_buffer_percentage; extern struct tm_binds tmb; -static struct { - char* buf; - int buf_len; - int data_len; +static struct +{ + char *buf; + int buf_len; + int data_len; } p_associated_uri = {0, 0, 0}; @@ -90,61 +91,68 @@ static struct { * Calculate the length of buffer needed to * print contacts */ -static inline unsigned int calc_buf_len(impurecord_t* impurec) { - unsigned int len; - int qlen; - ucontact_t* c; - param_t *tmp; +static inline unsigned int calc_buf_len(impurecord_t *impurec) +{ + unsigned int len; + int qlen; + ucontact_t *c; + param_t *tmp; impu_contact_t *impucontact; - len = 0; + len = 0; impucontact = impurec->linked_contacts.head; - while (impucontact) { + while(impucontact) { c = impucontact->contact; - if (VALID_CONTACT(c, act_time)) { - if (len) len += CONTACT_SEP_LEN; - len += 2 /* < > */ + c->c.len; - qlen = len_q(c->q); - if (qlen) len += Q_PARAM_LEN + qlen; - len += EXPIRES_PARAM_LEN + INT2STR_MAX_LEN; - if (c->received.s) { - len += 1 /* ; */ - + rcv_param.len - + 1 /* = */ - + 1 /* dquote */ - + c->received.len - + 1 /* dquote */ - ; - } - tmp = c->params; - while (tmp) { - if (tmp->name.len > 0 && tmp->name.s) { - if ((tmp->name.s[0] == 'R' || tmp->name.s[0]=='r') && tmp->name.len == 8 && !memcmp(tmp->name.s+1, "eceived", 7)) { + if(VALID_CONTACT(c, act_time)) { + if(len) + len += CONTACT_SEP_LEN; + len += 2 /* < > */ + c->c.len; + qlen = len_q(c->q); + if(qlen) + len += Q_PARAM_LEN + qlen; + len += EXPIRES_PARAM_LEN + INT2STR_MAX_LEN; + if(c->received.s) { + len += 1 /* ; */ + + rcv_param.len + 1 /* = */ + + 1 /* dquote */ + + c->received.len + 1 /* dquote */ + ; + } + tmp = c->params; + while(tmp) { + if(tmp->name.len > 0 && tmp->name.s) { + if((tmp->name.s[0] == 'R' || tmp->name.s[0] == 'r') + && tmp->name.len == 8 + && !memcmp(tmp->name.s + 1, "eceived", 7)) { tmp = tmp->next; continue; } - if ((tmp->name.s[0] == 'Q' || tmp->name.s[0]=='q') && tmp->name.len == 1) { + if((tmp->name.s[0] == 'Q' || tmp->name.s[0] == 'q') + && tmp->name.len == 1) { tmp = tmp->next; continue; } - if ((tmp->name.s[0] == 'E' || tmp->name.s[0] == 'e') && tmp->name.len == 7 && !memcmp(tmp->name.s + 1, "xpires", 6)) { + if((tmp->name.s[0] == 'E' || tmp->name.s[0] == 'e') + && tmp->name.len == 7 + && !memcmp(tmp->name.s + 1, "xpires", 6)) { tmp = tmp->next; continue; } len += tmp->name.len + 1 /*separator ; */; } - if (tmp->body.len > 0) { - len = len + 1/*=*/ + 2/*2 x "*/; - len += tmp->body.len; - } - tmp=tmp->next; - } - } + if(tmp->body.len > 0) { + len = len + 1 /*=*/ + 2 /*2 x "*/; + len += tmp->body.len; + } + tmp = tmp->next; + } + } impucontact = impucontact->next; - } + } - if (len) len += CONTACT_BEGIN_LEN + CRLF_LEN; - return len; + if(len) + len += CONTACT_BEGIN_LEN + CRLF_LEN; + return len; } @@ -154,268 +162,276 @@ static inline unsigned int calc_buf_len(impurecord_t* impurec) { #define MSG_500 "Server Internal Error" #define MSG_503 "Service Unavailable" -#define EI_R_FINE "No problem" /* R_FINE */ -#define EI_R_UL_DEL_R "usrloc_record_delete failed" /* R_UL_DEL_R */ -#define EI_R_UL_GET_R "usrloc_record_get failed" /* R_UL_GET */ -#define EI_R_UL_NEW_R "usrloc_record_new failed" /* R_UL_NEW_R */ -#define EI_R_INV_CSEQ "Invalid CSeq number" /* R_INV_CSEQ */ -#define EI_R_UL_INS_C "usrloc_contact_insert failed" /* R_UL_INS_C */ -#define EI_R_UL_INS_R "usrloc_record_insert failed" /* R_UL_INS_R */ -#define EI_R_UL_DEL_C "usrloc_contact_delete failed" /* R_UL_DEL_C */ -#define EI_R_UL_UPD_C "usrloc_contact_update failed" /* R_UL_UPD_C */ -#define EI_R_TO_USER "No username in To URI" /* R_TO_USER */ -#define EI_R_AOR_LEN "Address Of Record too long" /* R_AOR_LEN */ -#define EI_R_AOR_PARSE "Error while parsing AOR" /* R_AOR_PARSE */ -#define EI_R_INV_EXP "Invalid expires param in contact" /* R_INV_EXP */ -#define EI_R_INV_Q "Invalid q param in contact" /* R_INV_Q */ -#define EI_R_PARSE "Message parse error" /* R_PARSE */ -#define EI_R_TO_MISS "To header not found" /* R_TO_MISS */ -#define EI_R_CID_MISS "Call-ID header not found" /* R_CID_MISS */ -#define EI_R_CS_MISS "CSeq header not found" /* R_CS_MISS */ -#define EI_R_PARSE_EXP "Expires parse error" /* R_PARSE_EXP */ -#define EI_R_PARSE_CONT "Contact parse error" /* R_PARSE_CONT */ -#define EI_R_STAR_EXP "* used in contact and expires is not zero" /* R_STAR__EXP */ -#define EI_R_STAR_CONT "* used in contact and more than 1 contact" /* R_STAR_CONT */ -#define EI_R_OOO "Out of order request" /* R_OOO */ -#define EI_R_RETRANS "Retransmission" /* R_RETRANS */ -#define EI_R_UNESCAPE "Error while unescaping username" /* R_UNESCAPE */ -#define EI_R_TOO_MANY "Too many registered contacts" /* R_TOO_MANY */ -#define EI_R_CONTACT_LEN "Contact/received too long" /* R_CONTACT_LEN */ -#define EI_R_CALLID_LEN "Callid too long" /* R_CALLID_LEN */ -#define EI_R_PARSE_PATH "Path parse error" /* R_PARSE_PATH */ -#define EI_R_PATH_UNSUP "No support for found Path indicated" /* R_PATH_UNSUP */ -#define EI_R_SAR_FAILED "SAR failed" /* R_SAR_FAILED */ - -str error_info[] = { - {EI_R_FINE, sizeof (EI_R_FINE) - 1}, - {EI_R_UL_DEL_R, sizeof (EI_R_UL_DEL_R) - 1}, - {EI_R_UL_GET_R, sizeof (EI_R_UL_GET_R) - 1}, - {EI_R_UL_NEW_R, sizeof (EI_R_UL_NEW_R) - 1}, - {EI_R_INV_CSEQ, sizeof (EI_R_INV_CSEQ) - 1}, - {EI_R_UL_INS_C, sizeof (EI_R_UL_INS_C) - 1}, - {EI_R_UL_INS_R, sizeof (EI_R_UL_INS_R) - 1}, - {EI_R_UL_DEL_C, sizeof (EI_R_UL_DEL_C) - 1}, - {EI_R_UL_UPD_C, sizeof (EI_R_UL_UPD_C) - 1}, - {EI_R_TO_USER, sizeof (EI_R_TO_USER) - 1}, - {EI_R_AOR_LEN, sizeof (EI_R_AOR_LEN) - 1}, - {EI_R_AOR_PARSE, sizeof (EI_R_AOR_PARSE) - 1}, - {EI_R_INV_EXP, sizeof (EI_R_INV_EXP) - 1}, - {EI_R_INV_Q, sizeof (EI_R_INV_Q) - 1}, - {EI_R_PARSE, sizeof (EI_R_PARSE) - 1}, - {EI_R_TO_MISS, sizeof (EI_R_TO_MISS) - 1}, - {EI_R_CID_MISS, sizeof (EI_R_CID_MISS) - 1}, - {EI_R_CS_MISS, sizeof (EI_R_CS_MISS) - 1}, - {EI_R_PARSE_EXP, sizeof (EI_R_PARSE_EXP) - 1}, - {EI_R_PARSE_CONT, sizeof (EI_R_PARSE_CONT) - 1}, - {EI_R_STAR_EXP, sizeof (EI_R_STAR_EXP) - 1}, - {EI_R_STAR_CONT, sizeof (EI_R_STAR_CONT) - 1}, - {EI_R_OOO, sizeof (EI_R_OOO) - 1}, - {EI_R_RETRANS, sizeof (EI_R_RETRANS) - 1}, - {EI_R_UNESCAPE, sizeof (EI_R_UNESCAPE) - 1}, - {EI_R_TOO_MANY, sizeof (EI_R_TOO_MANY) - 1}, - {EI_R_CONTACT_LEN, sizeof (EI_R_CONTACT_LEN) - 1}, - {EI_R_CALLID_LEN, sizeof (EI_R_CALLID_LEN) - 1}, - {EI_R_PARSE_PATH, sizeof (EI_R_PARSE_PATH) - 1}, - {EI_R_PATH_UNSUP, sizeof (EI_R_PATH_UNSUP) - 1}, - {EI_R_SAR_FAILED, sizeof (EI_R_SAR_FAILED) - 1} +#define EI_R_FINE "No problem" /* R_FINE */ +#define EI_R_UL_DEL_R "usrloc_record_delete failed" /* R_UL_DEL_R */ +#define EI_R_UL_GET_R "usrloc_record_get failed" /* R_UL_GET */ +#define EI_R_UL_NEW_R "usrloc_record_new failed" /* R_UL_NEW_R */ +#define EI_R_INV_CSEQ "Invalid CSeq number" /* R_INV_CSEQ */ +#define EI_R_UL_INS_C "usrloc_contact_insert failed" /* R_UL_INS_C */ +#define EI_R_UL_INS_R "usrloc_record_insert failed" /* R_UL_INS_R */ +#define EI_R_UL_DEL_C "usrloc_contact_delete failed" /* R_UL_DEL_C */ +#define EI_R_UL_UPD_C "usrloc_contact_update failed" /* R_UL_UPD_C */ +#define EI_R_TO_USER "No username in To URI" /* R_TO_USER */ +#define EI_R_AOR_LEN "Address Of Record too long" /* R_AOR_LEN */ +#define EI_R_AOR_PARSE "Error while parsing AOR" /* R_AOR_PARSE */ +#define EI_R_INV_EXP "Invalid expires param in contact" /* R_INV_EXP */ +#define EI_R_INV_Q "Invalid q param in contact" /* R_INV_Q */ +#define EI_R_PARSE "Message parse error" /* R_PARSE */ +#define EI_R_TO_MISS "To header not found" /* R_TO_MISS */ +#define EI_R_CID_MISS "Call-ID header not found" /* R_CID_MISS */ +#define EI_R_CS_MISS "CSeq header not found" /* R_CS_MISS */ +#define EI_R_PARSE_EXP "Expires parse error" /* R_PARSE_EXP */ +#define EI_R_PARSE_CONT "Contact parse error" /* R_PARSE_CONT */ +#define EI_R_STAR_EXP \ + "* used in contact and expires is not zero" /* R_STAR__EXP */ +#define EI_R_STAR_CONT \ + "* used in contact and more than 1 contact" /* R_STAR_CONT */ +#define EI_R_OOO "Out of order request" /* R_OOO */ +#define EI_R_RETRANS "Retransmission" /* R_RETRANS */ +#define EI_R_UNESCAPE "Error while unescaping username" /* R_UNESCAPE */ +#define EI_R_TOO_MANY "Too many registered contacts" /* R_TOO_MANY */ +#define EI_R_CONTACT_LEN "Contact/received too long" /* R_CONTACT_LEN */ +#define EI_R_CALLID_LEN "Callid too long" /* R_CALLID_LEN */ +#define EI_R_PARSE_PATH "Path parse error" /* R_PARSE_PATH */ +#define EI_R_PATH_UNSUP "No support for found Path indicated" /* R_PATH_UNSUP */ +#define EI_R_SAR_FAILED "SAR failed" /* R_SAR_FAILED */ + +str error_info[] = {{EI_R_FINE, sizeof(EI_R_FINE) - 1}, + {EI_R_UL_DEL_R, sizeof(EI_R_UL_DEL_R) - 1}, + {EI_R_UL_GET_R, sizeof(EI_R_UL_GET_R) - 1}, + {EI_R_UL_NEW_R, sizeof(EI_R_UL_NEW_R) - 1}, + {EI_R_INV_CSEQ, sizeof(EI_R_INV_CSEQ) - 1}, + {EI_R_UL_INS_C, sizeof(EI_R_UL_INS_C) - 1}, + {EI_R_UL_INS_R, sizeof(EI_R_UL_INS_R) - 1}, + {EI_R_UL_DEL_C, sizeof(EI_R_UL_DEL_C) - 1}, + {EI_R_UL_UPD_C, sizeof(EI_R_UL_UPD_C) - 1}, + {EI_R_TO_USER, sizeof(EI_R_TO_USER) - 1}, + {EI_R_AOR_LEN, sizeof(EI_R_AOR_LEN) - 1}, + {EI_R_AOR_PARSE, sizeof(EI_R_AOR_PARSE) - 1}, + {EI_R_INV_EXP, sizeof(EI_R_INV_EXP) - 1}, + {EI_R_INV_Q, sizeof(EI_R_INV_Q) - 1}, + {EI_R_PARSE, sizeof(EI_R_PARSE) - 1}, + {EI_R_TO_MISS, sizeof(EI_R_TO_MISS) - 1}, + {EI_R_CID_MISS, sizeof(EI_R_CID_MISS) - 1}, + {EI_R_CS_MISS, sizeof(EI_R_CS_MISS) - 1}, + {EI_R_PARSE_EXP, sizeof(EI_R_PARSE_EXP) - 1}, + {EI_R_PARSE_CONT, sizeof(EI_R_PARSE_CONT) - 1}, + {EI_R_STAR_EXP, sizeof(EI_R_STAR_EXP) - 1}, + {EI_R_STAR_CONT, sizeof(EI_R_STAR_CONT) - 1}, + {EI_R_OOO, sizeof(EI_R_OOO) - 1}, + {EI_R_RETRANS, sizeof(EI_R_RETRANS) - 1}, + {EI_R_UNESCAPE, sizeof(EI_R_UNESCAPE) - 1}, + {EI_R_TOO_MANY, sizeof(EI_R_TOO_MANY) - 1}, + {EI_R_CONTACT_LEN, sizeof(EI_R_CONTACT_LEN) - 1}, + {EI_R_CALLID_LEN, sizeof(EI_R_CALLID_LEN) - 1}, + {EI_R_PARSE_PATH, sizeof(EI_R_PARSE_PATH) - 1}, + {EI_R_PATH_UNSUP, sizeof(EI_R_PATH_UNSUP) - 1}, + {EI_R_SAR_FAILED, sizeof(EI_R_SAR_FAILED) - 1} }; int codes[] = { - 200, /* R_FINE */ - 500, /* R_UL_DEL_R */ - 500, /* R_UL_GET */ - 500, /* R_UL_NEW_R */ - 400, /* R_INV_CSEQ */ - 500, /* R_UL_INS_C */ - 500, /* R_UL_INS_R */ - 500, /* R_UL_DEL_C */ - 500, /* R_UL_UPD_C */ - 400, /* R_TO_USER */ - 500, /* R_AOR_LEN */ - 400, /* R_AOR_PARSE */ - 400, /* R_INV_EXP */ - 400, /* R_INV_Q */ - 400, /* R_PARSE */ - 400, /* R_TO_MISS */ - 400, /* R_CID_MISS */ - 400, /* R_CS_MISS */ - 400, /* R_PARSE_EXP */ - 400, /* R_PARSE_CONT */ - 400, /* R_STAR_EXP */ - 400, /* R_STAR_CONT */ - 200, /* R_OOO */ - 200, /* R_RETRANS */ - 400, /* R_UNESCAPE */ - 503, /* R_TOO_MANY */ - 400, /* R_CONTACT_LEN */ - 400, /* R_CALLID_LEN */ - 400, /* R_PARSE_PATH */ - 420, /* R_PATH_UNSUP */ - 500 /* R_SAR_FAILED */ + 200, /* R_FINE */ + 500, /* R_UL_DEL_R */ + 500, /* R_UL_GET */ + 500, /* R_UL_NEW_R */ + 400, /* R_INV_CSEQ */ + 500, /* R_UL_INS_C */ + 500, /* R_UL_INS_R */ + 500, /* R_UL_DEL_C */ + 500, /* R_UL_UPD_C */ + 400, /* R_TO_USER */ + 500, /* R_AOR_LEN */ + 400, /* R_AOR_PARSE */ + 400, /* R_INV_EXP */ + 400, /* R_INV_Q */ + 400, /* R_PARSE */ + 400, /* R_TO_MISS */ + 400, /* R_CID_MISS */ + 400, /* R_CS_MISS */ + 400, /* R_PARSE_EXP */ + 400, /* R_PARSE_CONT */ + 400, /* R_STAR_EXP */ + 400, /* R_STAR_CONT */ + 200, /* R_OOO */ + 200, /* R_RETRANS */ + 400, /* R_UNESCAPE */ + 503, /* R_TOO_MANY */ + 400, /* R_CONTACT_LEN */ + 400, /* R_CALLID_LEN */ + 400, /* R_PARSE_PATH */ + 420, /* R_PATH_UNSUP */ + 500 /* R_SAR_FAILED */ }; #define RETRY_AFTER "Retry-After: " #define RETRY_AFTER_LEN (sizeof(RETRY_AFTER) - 1) -static int add_retry_after(struct sip_msg* _m) { - char* buf, *ra_s; - int ra_len; - - ra_s = int2str(cfg_get(registrar, registrar_cfg, retry_after), &ra_len); - buf = (char*) pkg_malloc(RETRY_AFTER_LEN + ra_len + CRLF_LEN); - if (!buf) { - LM_ERR("no pkg memory left\n"); - return -1; - } - memcpy(buf, RETRY_AFTER, RETRY_AFTER_LEN); - memcpy(buf + RETRY_AFTER_LEN, ra_s, ra_len); - memcpy(buf + RETRY_AFTER_LEN + ra_len, CRLF, CRLF_LEN); - add_lump_rpl(_m, buf, RETRY_AFTER_LEN + ra_len + CRLF_LEN, - LUMP_RPL_HDR | LUMP_RPL_NODUP); - return 0; +static int add_retry_after(struct sip_msg *_m) +{ + char *buf, *ra_s; + int ra_len; + + ra_s = int2str(cfg_get(registrar, registrar_cfg, retry_after), &ra_len); + buf = (char *)pkg_malloc(RETRY_AFTER_LEN + ra_len + CRLF_LEN); + if(!buf) { + LM_ERR("no pkg memory left\n"); + return -1; + } + memcpy(buf, RETRY_AFTER, RETRY_AFTER_LEN); + memcpy(buf + RETRY_AFTER_LEN, ra_s, ra_len); + memcpy(buf + RETRY_AFTER_LEN + ra_len, CRLF, CRLF_LEN); + add_lump_rpl(_m, buf, RETRY_AFTER_LEN + ra_len + CRLF_LEN, + LUMP_RPL_HDR | LUMP_RPL_NODUP); + return 0; } #define PATH "Path: " #define PATH_LEN (sizeof(PATH) - 1) -static int add_path(struct sip_msg* _m, str* _p) { - char* buf; - - buf = (char*) pkg_malloc(PATH_LEN + _p->len + CRLF_LEN); - if (!buf) { - LM_ERR("no pkg memory left\n"); - return -1; - } - memcpy(buf, PATH, PATH_LEN); - memcpy(buf + PATH_LEN, _p->s, _p->len); - memcpy(buf + PATH_LEN + _p->len, CRLF, CRLF_LEN); - add_lump_rpl(_m, buf, PATH_LEN + _p->len + CRLF_LEN, - LUMP_RPL_HDR | LUMP_RPL_NODUP); - return 0; +static int add_path(struct sip_msg *_m, str *_p) +{ + char *buf; + + buf = (char *)pkg_malloc(PATH_LEN + _p->len + CRLF_LEN); + if(!buf) { + LM_ERR("no pkg memory left\n"); + return -1; + } + memcpy(buf, PATH, PATH_LEN); + memcpy(buf + PATH_LEN, _p->s, _p->len); + memcpy(buf + PATH_LEN + _p->len, CRLF, CRLF_LEN); + add_lump_rpl(_m, buf, PATH_LEN + _p->len + CRLF_LEN, + LUMP_RPL_HDR | LUMP_RPL_NODUP); + return 0; } #define SERVICEROUTE_START "Service-Route: <" -#define SERVICEROUTE_START_LEN (sizeof(SERVICEROUTE_START) -1) +#define SERVICEROUTE_START_LEN (sizeof(SERVICEROUTE_START) - 1) #define SERVICEROUTE_END ";lr>\r\n" -#define SERVICEROUTE_END_LEN (sizeof(SERVICEROUTE_END) -1) - -static int add_service_route(struct sip_msg* _m, str* _uri) { - char* buf; - - buf = (char*) pkg_malloc(SERVICEROUTE_START_LEN + _uri->len + SERVICEROUTE_END_LEN); - if (!buf) { - LM_ERR("no pkg memory left\n"); - return -1; - } - - memcpy(buf, SERVICEROUTE_START, SERVICEROUTE_START_LEN); - memcpy(buf + SERVICEROUTE_START_LEN, _uri->s, _uri->len); - memcpy(buf + SERVICEROUTE_START_LEN + _uri->len, SERVICEROUTE_END, SERVICEROUTE_END_LEN); - add_lump_rpl(_m, buf, SERVICEROUTE_START_LEN + _uri->len + SERVICEROUTE_END_LEN, LUMP_RPL_HDR | LUMP_RPL_NODUP); - return 0; +#define SERVICEROUTE_END_LEN (sizeof(SERVICEROUTE_END) - 1) + +static int add_service_route(struct sip_msg *_m, str *_uri) +{ + char *buf; + + buf = (char *)pkg_malloc( + SERVICEROUTE_START_LEN + _uri->len + SERVICEROUTE_END_LEN); + if(!buf) { + LM_ERR("no pkg memory left\n"); + return -1; + } + + memcpy(buf, SERVICEROUTE_START, SERVICEROUTE_START_LEN); + memcpy(buf + SERVICEROUTE_START_LEN, _uri->s, _uri->len); + memcpy(buf + SERVICEROUTE_START_LEN + _uri->len, SERVICEROUTE_END, + SERVICEROUTE_END_LEN); + add_lump_rpl(_m, buf, + SERVICEROUTE_START_LEN + _uri->len + SERVICEROUTE_END_LEN, + LUMP_RPL_HDR | LUMP_RPL_NODUP); + return 0; } #define UNSUPPORTED "Unsupported: " #define UNSUPPORTED_LEN (sizeof(UNSUPPORTED) - 1) -static int add_unsupported(struct sip_msg* _m, str* _p) { - char* buf; - - buf = (char*) pkg_malloc(UNSUPPORTED_LEN + _p->len + CRLF_LEN); - if (!buf) { - LM_ERR("no pkg memory left\n"); - return -1; - } - memcpy(buf, UNSUPPORTED, UNSUPPORTED_LEN); - memcpy(buf + UNSUPPORTED_LEN, _p->s, _p->len); - memcpy(buf + UNSUPPORTED_LEN + _p->len, CRLF, CRLF_LEN); - add_lump_rpl(_m, buf, UNSUPPORTED_LEN + _p->len + CRLF_LEN, - LUMP_RPL_HDR | LUMP_RPL_NODUP); - return 0; +static int add_unsupported(struct sip_msg *_m, str *_p) +{ + char *buf; + + buf = (char *)pkg_malloc(UNSUPPORTED_LEN + _p->len + CRLF_LEN); + if(!buf) { + LM_ERR("no pkg memory left\n"); + return -1; + } + memcpy(buf, UNSUPPORTED, UNSUPPORTED_LEN); + memcpy(buf + UNSUPPORTED_LEN, _p->s, _p->len); + memcpy(buf + UNSUPPORTED_LEN + _p->len, CRLF, CRLF_LEN); + add_lump_rpl(_m, buf, UNSUPPORTED_LEN + _p->len + CRLF_LEN, + LUMP_RPL_HDR | LUMP_RPL_NODUP); + return 0; } -int build_expired_contact(contact_t* chi, contact_for_header_t** contact_header) { - - char *p, *cp; - int len; - char *tmp; - int old_data_len = 0; - - contact_for_header_t* c_header = 0; - - len = chi->uri.len - + 2 /*<>*/ - + chi->uri.len - + EXPIRES_PARAM_LEN + INT2STR_MAX_LEN; - - if (c_header && c_header->data_len > 0) { - //contact header has already been started - old_data_len = c_header->data_len - CRLF_LEN; - c_header->data_len = c_header->data_len + len + CONTACT_SEP_LEN; - } else { - if (!c_header) {//not yet built one - c_header = shm_malloc(sizeof(contact_for_header_t)); - if (!c_header) { - LM_ERR("no more shm mem\n"); - return 0; - } - memset(c_header, 0, sizeof(contact_for_header_t)); - } - c_header->data_len = CONTACT_BEGIN_LEN + len + CRLF_LEN; - } - - if (!c_header->data_len) - return 0; - - if (!c_header->buf || (c_header->buf_len < c_header->data_len)) { - tmp = (char*) shm_malloc(c_header->data_len); - if (!tmp) { - c_header->data_len = 0; - c_header->buf_len = 0; - LM_ERR("no pkg memory left\n"); - return -1; - } - if (c_header->buf) { - //copy and free - memcpy(tmp, c_header->buf, old_data_len); - shm_free(c_header->buf); - c_header->buf = tmp; - } else { - c_header->buf = tmp; - } - } - p = c_header->buf + old_data_len; //just in case we append - - if (old_data_len) { - //copy new contact - memcpy(p, CONTACT_SEP, CONTACT_SEP_LEN); - p += CONTACT_SEP_LEN; - - } else { - //copy full new structure plus new contact - memcpy(p, CONTACT_BEGIN, CONTACT_BEGIN_LEN); - p += CONTACT_BEGIN_LEN; - } - memcpy(p++, "<", 1); - memcpy(p, chi->uri.s, chi->uri.len); - p += chi->uri.len; - memcpy(p++, ">", 1); - memcpy(p, EXPIRES_PARAM, EXPIRES_PARAM_LEN); - p += EXPIRES_PARAM_LEN; - cp = int2str((int) (0), &len); - memcpy(p, cp, len); - p += len; - memcpy(p, CRLF, CRLF_LEN); - p += CRLF_LEN; - c_header->data_len = p - c_header->buf; - - LM_DBG("de-reg contact is [%.*s]\n", c_header->data_len, c_header->buf); - *contact_header = c_header; - return 0; +int build_expired_contact(contact_t *chi, contact_for_header_t **contact_header) +{ + + char *p, *cp; + int len; + char *tmp; + int old_data_len = 0; + + contact_for_header_t *c_header = 0; + + len = chi->uri.len + 2 /*<>*/ + + chi->uri.len + EXPIRES_PARAM_LEN + INT2STR_MAX_LEN; + + if(c_header && c_header->data_len > 0) { + //contact header has already been started + old_data_len = c_header->data_len - CRLF_LEN; + c_header->data_len = c_header->data_len + len + CONTACT_SEP_LEN; + } else { + if(!c_header) { //not yet built one + c_header = shm_malloc(sizeof(contact_for_header_t)); + if(!c_header) { + LM_ERR("no more shm mem\n"); + return 0; + } + memset(c_header, 0, sizeof(contact_for_header_t)); + } + c_header->data_len = CONTACT_BEGIN_LEN + len + CRLF_LEN; + } + + if(!c_header->data_len) + return 0; + + if(!c_header->buf || (c_header->buf_len < c_header->data_len)) { + tmp = (char *)shm_malloc(c_header->data_len); + if(!tmp) { + c_header->data_len = 0; + c_header->buf_len = 0; + LM_ERR("no pkg memory left\n"); + return -1; + } + if(c_header->buf) { + //copy and free + memcpy(tmp, c_header->buf, old_data_len); + shm_free(c_header->buf); + c_header->buf = tmp; + } else { + c_header->buf = tmp; + } + } + p = c_header->buf + old_data_len; //just in case we append + + if(old_data_len) { + //copy new contact + memcpy(p, CONTACT_SEP, CONTACT_SEP_LEN); + p += CONTACT_SEP_LEN; + + } else { + //copy full new structure plus new contact + memcpy(p, CONTACT_BEGIN, CONTACT_BEGIN_LEN); + p += CONTACT_BEGIN_LEN; + } + memcpy(p++, "<", 1); + memcpy(p, chi->uri.s, chi->uri.len); + p += chi->uri.len; + memcpy(p++, ">", 1); + memcpy(p, EXPIRES_PARAM, EXPIRES_PARAM_LEN); + p += EXPIRES_PARAM_LEN; + cp = int2str((int)(0), &len); + memcpy(p, cp, len); + p += len; + memcpy(p, CRLF, CRLF_LEN); + p += CRLF_LEN; + c_header->data_len = p - c_header->buf; + + LM_DBG("de-reg contact is [%.*s]\n", c_header->data_len, c_header->buf); + *contact_header = c_header; + return 0; } /*! \brief @@ -425,445 +441,496 @@ int build_expired_contact(contact_t* chi, contact_for_header_t** contact_header) //We use shared memory for this so we can use it when we use async diameter -int build_contact(impurecord_t* impurec, contact_for_header_t** contact_header, struct sip_msg* msg) { - char *p, *cp; - int fl, len, expires, expires_orig; - ucontact_t* c; - param_t* tmp; - *contact_header = 0; +int build_contact(impurecord_t *impurec, contact_for_header_t **contact_header, + struct sip_msg *msg) +{ + char *p, *cp; + int fl, len, expires, expires_orig; + ucontact_t *c; + param_t *tmp; + *contact_header = 0; impu_contact_t *impucontact; - struct hdr_field* h; - contact_t* chi; //contact header information - int contact_match = 1; - - contact_for_header_t* tmp_contact_header = shm_malloc(sizeof (contact_for_header_t)); - if (!tmp_contact_header) { - LM_ERR("no more memory\n"); - return -1; - } - memset(tmp_contact_header, 0, sizeof (contact_for_header_t)); - - tmp_contact_header->data_len = calc_buf_len(impurec); - tmp_contact_header->buf = (char*)shm_malloc(tmp_contact_header->data_len); + struct hdr_field *h; + contact_t *chi; //contact header information + int contact_match = 1; + + contact_for_header_t *tmp_contact_header = + shm_malloc(sizeof(contact_for_header_t)); + if(!tmp_contact_header) { + LM_ERR("no more memory\n"); + return -1; + } + memset(tmp_contact_header, 0, sizeof(contact_for_header_t)); + + tmp_contact_header->data_len = calc_buf_len(impurec); + tmp_contact_header->buf = (char *)shm_malloc(tmp_contact_header->data_len); memset(tmp_contact_header->buf, 0, tmp_contact_header->data_len); - if (tmp_contact_header->data_len) { - p = tmp_contact_header->buf; + if(tmp_contact_header->data_len) { + p = tmp_contact_header->buf; + + memcpy(p, CONTACT_BEGIN, CONTACT_BEGIN_LEN); + p += CONTACT_BEGIN_LEN; - memcpy(p, CONTACT_BEGIN, CONTACT_BEGIN_LEN); - p += CONTACT_BEGIN_LEN; + fl = 0; - fl = 0; - impucontact = impurec->linked_contacts.head; - while (impucontact) { + while(impucontact) { c = impucontact->contact; - if (VALID_CONTACT(c, act_time)) { - if (msg) { - contact_match = 0; - for (h = msg->contact; h; h = h->next) { - if (h->type == HDR_CONTACT_T && h->parsed) { - for (chi = ((contact_body_t*) h->parsed)->contacts; chi; chi = chi->next) { - if ((c->c.len == chi->uri.len) && !memcmp(c->c.s, chi->uri.s, c->c.len)) { - contact_match = 1; - break; - } - } - } - } - } - - if (contact_match) { - if (fl) { - memcpy(p, CONTACT_SEP, CONTACT_SEP_LEN); - p += CONTACT_SEP_LEN; - } else { - fl = 1; - } - - *p++ = '<'; - memcpy(p, c->c.s, c->c.len); - p += c->c.len; - *p++ = '>'; - - len = len_q(c->q); - if (len) { - memcpy(p, Q_PARAM, Q_PARAM_LEN); - p += Q_PARAM_LEN; - memcpy(p, q2str(c->q, 0), len); - p += len; - } - - memcpy(p, EXPIRES_PARAM, EXPIRES_PARAM_LEN); - p += EXPIRES_PARAM_LEN; - - /* the expires we put in the contact header is decremented to give the UE some grace before we expires them */ - expires = expires_orig = (int)(c->expires - act_time); - expires = expires - (contact_expires_buffer_percentage*expires/100); - if (expires <= 0) { - LM_WARN("expires after buffer change was <= 0, not adding buffer space\n"); - expires = expires_orig; - } - cp = int2str(expires, &len); - memcpy(p, cp, len); - p += len; - - if (c->received.s) { - *p++ = ';'; - memcpy(p, rcv_param.s, rcv_param.len); - p += rcv_param.len; - *p++ = '='; - *p++ = '\"'; - memcpy(p, c->received.s, c->received.len); - p += c->received.len; - *p++ = '\"'; - } - - /* put in the rest of the params except Q and received */ - tmp = c->params; - while (tmp) { - if (tmp->name.len>0 && tmp->name.s) { - if ((tmp->name.s[0] == 'R' || tmp->name.s[0]=='r') && tmp->name.len == 8 && !memcmp(tmp->name.s+1, "eceived", 7)) { - tmp = tmp->next; - continue; - } - if ((tmp->name.s[0] == 'Q' || tmp->name.s[0]=='q') && tmp->name.len == 1) { - tmp = tmp->next; - continue; - } - if ((tmp->name.s[0] == 'E' || tmp->name.s[0]=='e') && tmp->name.len == 7 && !memcmp(tmp->name.s+1, "xpires", 6)) { - tmp = tmp->next; - continue; - } - *p++ = ';'; - memcpy(p, tmp->name.s, tmp->name.len); - p += tmp->name.len; - } - - if (tmp->body.len > 0) { - *p++ = '='; - *p++ = '\"'; - memcpy(p, tmp->body.s, tmp->body.len); - p += tmp->body.len; - *p++ = '\"'; - } - tmp = tmp->next; - } - } - } + if(VALID_CONTACT(c, act_time)) { + if(msg) { + contact_match = 0; + for(h = msg->contact; h; h = h->next) { + if(h->type == HDR_CONTACT_T && h->parsed) { + for(chi = ((contact_body_t *)h->parsed)->contacts; + chi; chi = chi->next) { + if((c->c.len == chi->uri.len) + && !memcmp( + c->c.s, chi->uri.s, c->c.len)) { + contact_match = 1; + break; + } + } + } + } + } + + if(contact_match) { + if(fl) { + memcpy(p, CONTACT_SEP, CONTACT_SEP_LEN); + p += CONTACT_SEP_LEN; + } else { + fl = 1; + } + + *p++ = '<'; + memcpy(p, c->c.s, c->c.len); + p += c->c.len; + *p++ = '>'; + + len = len_q(c->q); + if(len) { + memcpy(p, Q_PARAM, Q_PARAM_LEN); + p += Q_PARAM_LEN; + memcpy(p, q2str(c->q, 0), len); + p += len; + } + + memcpy(p, EXPIRES_PARAM, EXPIRES_PARAM_LEN); + p += EXPIRES_PARAM_LEN; + + /* the expires we put in the contact header is decremented to give the UE some grace before we expires them */ + expires = expires_orig = (int)(c->expires - act_time); + expires = expires + - (contact_expires_buffer_percentage * expires + / 100); + if(expires <= 0) { + LM_WARN("expires after buffer change was <= 0, not " + "adding buffer space\n"); + expires = expires_orig; + } + cp = int2str(expires, &len); + memcpy(p, cp, len); + p += len; + + if(c->received.s) { + *p++ = ';'; + memcpy(p, rcv_param.s, rcv_param.len); + p += rcv_param.len; + *p++ = '='; + *p++ = '\"'; + memcpy(p, c->received.s, c->received.len); + p += c->received.len; + *p++ = '\"'; + } + + /* put in the rest of the params except Q and received */ + tmp = c->params; + while(tmp) { + if(tmp->name.len > 0 && tmp->name.s) { + if((tmp->name.s[0] == 'R' || tmp->name.s[0] == 'r') + && tmp->name.len == 8 + && !memcmp(tmp->name.s + 1, "eceived", 7)) { + tmp = tmp->next; + continue; + } + if((tmp->name.s[0] == 'Q' || tmp->name.s[0] == 'q') + && tmp->name.len == 1) { + tmp = tmp->next; + continue; + } + if((tmp->name.s[0] == 'E' || tmp->name.s[0] == 'e') + && tmp->name.len == 7 + && !memcmp(tmp->name.s + 1, "xpires", 6)) { + tmp = tmp->next; + continue; + } + *p++ = ';'; + memcpy(p, tmp->name.s, tmp->name.len); + p += tmp->name.len; + } + + if(tmp->body.len > 0) { + *p++ = '='; + *p++ = '\"'; + memcpy(p, tmp->body.s, tmp->body.len); + p += tmp->body.len; + *p++ = '\"'; + } + tmp = tmp->next; + } + } + } impucontact = impucontact->next; - } - memcpy(p, CRLF, CRLF_LEN); - p += CRLF_LEN; + } + memcpy(p, CRLF, CRLF_LEN); + p += CRLF_LEN; - tmp_contact_header->data_len = p - tmp_contact_header->buf; + tmp_contact_header->data_len = p - tmp_contact_header->buf; - LM_DBG("created Contact HF: %.*s\n", tmp_contact_header->data_len, tmp_contact_header->buf); - } else - LM_DBG("No Contact HF created, no contacts.\n"); + LM_DBG("created Contact HF: %.*s\n", tmp_contact_header->data_len, + tmp_contact_header->buf); + } else + LM_DBG("No Contact HF created, no contacts.\n"); - *contact_header = tmp_contact_header; - return 0; + *contact_header = tmp_contact_header; + return 0; } #define PASSOCIATEDURI "P-Associated-URI: " -#define PASSOCIATEDURI_LEN (sizeof(PASSOCIATEDURI)-1) +#define PASSOCIATEDURI_LEN (sizeof(PASSOCIATEDURI) - 1) /*! \brief * Calculate the length of buffer needed to * print p-associated-uri */ -static inline unsigned int calc_associateduri_buf_len(ims_subscription* s) { - unsigned int len; - int i, j; - ims_public_identity* id; - - len = 0; - for (i = 0; i < s->service_profiles_cnt; i++) - for (j = 0; j < s->service_profiles[i].public_identities_cnt; j++) { - id = &(s->service_profiles[i].public_identities[j]); - if (!id->barring) - len += 4 + id->public_identity.len; /*4 is for ">, <""*/ - } - - if (len) len += PASSOCIATEDURI_LEN + 2 + CRLF_LEN; // <> and \r\n; - - return len; +static inline unsigned int calc_associateduri_buf_len(ims_subscription *s) +{ + unsigned int len; + int i, j; + ims_public_identity *id; + + len = 0; + for(i = 0; i < s->service_profiles_cnt; i++) + for(j = 0; j < s->service_profiles[i].public_identities_cnt; j++) { + id = &(s->service_profiles[i].public_identities[j]); + if(!id->barring) + len += 4 + id->public_identity.len; /*4 is for ">, <""*/ + } + + if(len) + len += PASSOCIATEDURI_LEN + 2 + CRLF_LEN; // <> and \r\n; + + return len; } /*! \brief * Allocate a memory buffer and print P-Associated_URI * header fields into it */ -int build_p_associated_uri(ims_subscription* s) { - char *p; - int i, j, cnt = 0; - ims_public_identity* id; - - LM_DBG("Building P-Associated-URI\n"); - - if (!s) { - LM_ERR("Strange, no ims subscription data - how did we get here\n"); - return -1; - } - p_associated_uri.data_len = calc_associateduri_buf_len(s); - if (!p_associated_uri.data_len) - return -1; - - if (!p_associated_uri.buf || (p_associated_uri.buf_len < p_associated_uri.data_len)) { - if (p_associated_uri.buf) - pkg_free(p_associated_uri.buf); - p_associated_uri.buf = (char*) pkg_malloc(p_associated_uri.data_len); - if (!p_associated_uri.buf) { - p_associated_uri.data_len = 0; - p_associated_uri.buf_len = 0; - LM_ERR("no pkg memory left\n"); - return -1; - } else { - p_associated_uri.buf_len = p_associated_uri.data_len; - } - } - - p = p_associated_uri.buf; - memcpy(p, PASSOCIATEDURI, PASSOCIATEDURI_LEN); - p += PASSOCIATEDURI_LEN; - - for (i = 0; i < s->service_profiles_cnt; i++) - for (j = 0; j < s->service_profiles[i].public_identities_cnt; j++) { - id = &(s->service_profiles[i].public_identities[j]); - if (!id->barring) { - if (cnt == 0) - *p++ = '<'; - else { - memcpy(p, ">, <", 4); - p += 4; - } - memcpy(p, id->public_identity.s, id->public_identity.len); - p += id->public_identity.len; - cnt++; - } - } - if (cnt) - *p++ = '>'; - - memcpy(p, "\r\n", CRLF_LEN); - p += CRLF_LEN; - p_associated_uri.data_len = p - p_associated_uri.buf; - LM_DBG("Created P-Associated-URI HF %.*s\n", p_associated_uri.data_len, p_associated_uri.buf); - - return 0; +int build_p_associated_uri(ims_subscription *s) +{ + char *p; + int i, j, cnt = 0; + ims_public_identity *id; + + LM_DBG("Building P-Associated-URI\n"); + + if(!s) { + LM_ERR("Strange, no ims subscription data - how did we get here\n"); + return -1; + } + p_associated_uri.data_len = calc_associateduri_buf_len(s); + if(!p_associated_uri.data_len) + return -1; + + if(!p_associated_uri.buf + || (p_associated_uri.buf_len < p_associated_uri.data_len)) { + if(p_associated_uri.buf) + pkg_free(p_associated_uri.buf); + p_associated_uri.buf = (char *)pkg_malloc(p_associated_uri.data_len); + if(!p_associated_uri.buf) { + p_associated_uri.data_len = 0; + p_associated_uri.buf_len = 0; + LM_ERR("no pkg memory left\n"); + return -1; + } else { + p_associated_uri.buf_len = p_associated_uri.data_len; + } + } + + p = p_associated_uri.buf; + memcpy(p, PASSOCIATEDURI, PASSOCIATEDURI_LEN); + p += PASSOCIATEDURI_LEN; + + for(i = 0; i < s->service_profiles_cnt; i++) + for(j = 0; j < s->service_profiles[i].public_identities_cnt; j++) { + id = &(s->service_profiles[i].public_identities[j]); + if(!id->barring) { + if(cnt == 0) + *p++ = '<'; + else { + memcpy(p, ">, <", 4); + p += 4; + } + memcpy(p, id->public_identity.s, id->public_identity.len); + p += id->public_identity.len; + cnt++; + } + } + if(cnt) + *p++ = '>'; + + memcpy(p, "\r\n", CRLF_LEN); + p += CRLF_LEN; + p_associated_uri.data_len = p - p_associated_uri.buf; + LM_DBG("Created P-Associated-URI HF %.*s\n", p_associated_uri.data_len, + p_associated_uri.buf); + + return 0; } /*! \brief * Send a reply */ -int reg_send_reply_transactional(struct sip_msg* _m, contact_for_header_t* contact_header, struct cell* t_cell) { - str unsup = str_init(OPTION_TAG_PATH_STR); - long code; - str msg = str_init(MSG_200); /* makes gcc shut up */ - char* buf; - - if (contact_header && contact_header->buf && contact_header->data_len > 0) { - LM_DBG("Contacts: %.*s\n", contact_header->data_len, contact_header->buf); - add_lump_rpl(_m, contact_header->buf, contact_header->data_len, LUMP_RPL_HDR | LUMP_RPL_NODUP | LUMP_RPL_NOFREE); - contact_header->data_len = 0; - } - - if (rerrno == R_FINE && path_enabled && _m->path_vec.s) { - if (path_mode != PATH_MODE_OFF) { - if (parse_supported(_m) < 0 && path_mode == PATH_MODE_STRICT) { - rerrno = R_PATH_UNSUP; - if (add_unsupported(_m, &unsup) < 0) - return -1; - if (add_path(_m, &_m->path_vec) < 0) - return -1; - } else if (get_supported(_m) & F_OPTION_TAG_PATH) { - if (add_path(_m, &_m->path_vec) < 0) - return -1; - } else if (path_mode == PATH_MODE_STRICT) { - rerrno = R_PATH_UNSUP; - if (add_unsupported(_m, &unsup) < 0) - return -1; - if (add_path(_m, &_m->path_vec) < 0) - return -1; - } - } - } - - code = codes[rerrno]; - if ((code == 500) && (error_reply_code > 0)) code = error_reply_code; - switch (code) { - case 200: msg.s = MSG_200; - msg.len = sizeof (MSG_200) - 1; - break; - case 400: msg.s = MSG_400; - msg.len = sizeof (MSG_400) - 1; - break; - case 420: msg.s = MSG_420; - msg.len = sizeof (MSG_420) - 1; - break; - case 500: msg.s = MSG_500; - msg.len = sizeof (MSG_500) - 1; - break; - case 503: msg.s = MSG_503; - msg.len = sizeof (MSG_503) - 1; - break; - } - - if (code != 200) { - buf = (char*) pkg_malloc(E_INFO_LEN + error_info[rerrno].len + CRLF_LEN + 1); - if (!buf) { - LM_ERR("no pkg memory left\n"); - return -1; - } - memcpy(buf, E_INFO, E_INFO_LEN); - memcpy(buf + E_INFO_LEN, error_info[rerrno].s, error_info[rerrno].len); - memcpy(buf + E_INFO_LEN + error_info[rerrno].len, CRLF, CRLF_LEN); - add_lump_rpl(_m, buf, E_INFO_LEN + error_info[rerrno].len + CRLF_LEN, - LUMP_RPL_HDR | LUMP_RPL_NODUP); - - if (code >= 500 && code < 600 && cfg_get(registrar, registrar_cfg, retry_after)) { - if (add_retry_after(_m) < 0) { - return -1; - } - } - } - - if ((code > 199) && (code < 299)) { - if (p_associated_uri.data_len > 0) { - add_lump_rpl(_m, p_associated_uri.buf, p_associated_uri.data_len, - LUMP_RPL_HDR | LUMP_RPL_NODUP | LUMP_RPL_NOFREE); - p_associated_uri.data_len = 0; - } - if (add_service_route(_m, &scscf_serviceroute_uri_str) < 0) { //TODO - need to insert orig into this scscf_name - return -1; - } - } - - //if (slb.freply(_m, code, &msg) < 0) { - if (tmb.t_reply_trans(t_cell, _m, code, msg.s) < 0){ - LM_ERR("failed to send %ld %.*s\n", code, msg.len, msg.s); - return -1; - } else return 0; +int reg_send_reply_transactional(struct sip_msg *_m, + contact_for_header_t *contact_header, struct cell *t_cell) +{ + str unsup = str_init(OPTION_TAG_PATH_STR); + long code; + str msg = str_init(MSG_200); /* makes gcc shut up */ + char *buf; + + if(contact_header && contact_header->buf && contact_header->data_len > 0) { + LM_DBG("Contacts: %.*s\n", contact_header->data_len, + contact_header->buf); + add_lump_rpl(_m, contact_header->buf, contact_header->data_len, + LUMP_RPL_HDR | LUMP_RPL_NODUP | LUMP_RPL_NOFREE); + contact_header->data_len = 0; + } + + if(rerrno == R_FINE && path_enabled && _m->path_vec.s) { + if(path_mode != PATH_MODE_OFF) { + if(parse_supported(_m) < 0 && path_mode == PATH_MODE_STRICT) { + rerrno = R_PATH_UNSUP; + if(add_unsupported(_m, &unsup) < 0) + return -1; + if(add_path(_m, &_m->path_vec) < 0) + return -1; + } else if(get_supported(_m) & F_OPTION_TAG_PATH) { + if(add_path(_m, &_m->path_vec) < 0) + return -1; + } else if(path_mode == PATH_MODE_STRICT) { + rerrno = R_PATH_UNSUP; + if(add_unsupported(_m, &unsup) < 0) + return -1; + if(add_path(_m, &_m->path_vec) < 0) + return -1; + } + } + } + + code = codes[rerrno]; + if((code == 500) && (error_reply_code > 0)) + code = error_reply_code; + switch(code) { + case 200: + msg.s = MSG_200; + msg.len = sizeof(MSG_200) - 1; + break; + case 400: + msg.s = MSG_400; + msg.len = sizeof(MSG_400) - 1; + break; + case 420: + msg.s = MSG_420; + msg.len = sizeof(MSG_420) - 1; + break; + case 500: + msg.s = MSG_500; + msg.len = sizeof(MSG_500) - 1; + break; + case 503: + msg.s = MSG_503; + msg.len = sizeof(MSG_503) - 1; + break; + } + + if(code != 200) { + buf = (char *)pkg_malloc( + E_INFO_LEN + error_info[rerrno].len + CRLF_LEN + 1); + if(!buf) { + LM_ERR("no pkg memory left\n"); + return -1; + } + memcpy(buf, E_INFO, E_INFO_LEN); + memcpy(buf + E_INFO_LEN, error_info[rerrno].s, error_info[rerrno].len); + memcpy(buf + E_INFO_LEN + error_info[rerrno].len, CRLF, CRLF_LEN); + add_lump_rpl(_m, buf, E_INFO_LEN + error_info[rerrno].len + CRLF_LEN, + LUMP_RPL_HDR | LUMP_RPL_NODUP); + + if(code >= 500 && code < 600 + && cfg_get(registrar, registrar_cfg, retry_after)) { + if(add_retry_after(_m) < 0) { + return -1; + } + } + } + + if((code > 199) && (code < 299)) { + if(p_associated_uri.data_len > 0) { + add_lump_rpl(_m, p_associated_uri.buf, p_associated_uri.data_len, + LUMP_RPL_HDR | LUMP_RPL_NODUP | LUMP_RPL_NOFREE); + p_associated_uri.data_len = 0; + } + if(add_service_route(_m, &scscf_serviceroute_uri_str) + < 0) { //TODO - need to insert orig into this scscf_name + return -1; + } + } + + //if (slb.freply(_m, code, &msg) < 0) { + if(tmb.t_reply_trans(t_cell, _m, code, msg.s) < 0) { + LM_ERR("failed to send %ld %.*s\n", code, msg.len, msg.s); + return -1; + } else + return 0; } /*! \brief * Send a reply */ -int reg_send_reply(struct sip_msg* _m, contact_for_header_t* contact_header) { - str unsup = str_init(OPTION_TAG_PATH_STR); - long code; - str msg = str_init(MSG_200); /* makes gcc shut up */ - char* buf; - - if (contact_header && contact_header->buf && (contact_header->buf_len > 0) && (contact_header->data_len > 0)) { - LM_DBG("Contacts: %.*s\n", contact_header->data_len, contact_header->buf); - add_lump_rpl(_m, contact_header->buf, contact_header->data_len, LUMP_RPL_HDR | LUMP_RPL_NODUP | LUMP_RPL_NOFREE); - contact_header->data_len = 0; - } - - if (rerrno == R_FINE && path_enabled && _m->path_vec.s) { - if (path_mode != PATH_MODE_OFF) { - if (parse_supported(_m) < 0 && path_mode == PATH_MODE_STRICT) { - rerrno = R_PATH_UNSUP; - if (add_unsupported(_m, &unsup) < 0) - return -1; - if (add_path(_m, &_m->path_vec) < 0) - return -1; - } else if (get_supported(_m) & F_OPTION_TAG_PATH) { - if (add_path(_m, &_m->path_vec) < 0) - return -1; - } else if (path_mode == PATH_MODE_STRICT) { - rerrno = R_PATH_UNSUP; - if (add_unsupported(_m, &unsup) < 0) - return -1; - if (add_path(_m, &_m->path_vec) < 0) - return -1; - } - } - } - - code = codes[rerrno]; - if ((code == 500) && (error_reply_code > 0)) code = error_reply_code; - - switch (code) { - case 200: msg.s = MSG_200; - msg.len = sizeof (MSG_200) - 1; - break; - case 400: msg.s = MSG_400; - msg.len = sizeof (MSG_400) - 1; - break; - case 420: msg.s = MSG_420; - msg.len = sizeof (MSG_420) - 1; - break; - case 500: msg.s = MSG_500; - msg.len = sizeof (MSG_500) - 1; - break; - case 503: msg.s = MSG_503; - msg.len = sizeof (MSG_503) - 1; - break; - } - - if (code != 200) { - buf = (char*) pkg_malloc(E_INFO_LEN + error_info[rerrno].len + CRLF_LEN + 1); - if (!buf) { - LM_ERR("no pkg memory left\n"); - return -1; - } - memcpy(buf, E_INFO, E_INFO_LEN); - memcpy(buf + E_INFO_LEN, error_info[rerrno].s, error_info[rerrno].len); - memcpy(buf + E_INFO_LEN + error_info[rerrno].len, CRLF, CRLF_LEN); - add_lump_rpl(_m, buf, E_INFO_LEN + error_info[rerrno].len + CRLF_LEN, - LUMP_RPL_HDR | LUMP_RPL_NODUP); - - if (code >= 500 && code < 600 && cfg_get(registrar, registrar_cfg, retry_after)) { - if (add_retry_after(_m) < 0) { - return -1; - } - } - } - - if ((code > 199) && (code < 299)) { - if (p_associated_uri.data_len > 0) { - add_lump_rpl(_m, p_associated_uri.buf, p_associated_uri.data_len, - LUMP_RPL_HDR | LUMP_RPL_NODUP | LUMP_RPL_NOFREE); - p_associated_uri.data_len = 0; - } - if (add_service_route(_m, &scscf_serviceroute_uri_str) < 0) { //TODO - need to insert orig into this scscf_name - return -1; - } - } - - if (slb.freply(_m, code, &msg) < 0) { - LM_ERR("failed to send %ld %.*s\n", code, msg.len, msg.s); - return -1; - } else return 0; +int reg_send_reply(struct sip_msg *_m, contact_for_header_t *contact_header) +{ + str unsup = str_init(OPTION_TAG_PATH_STR); + long code; + str msg = str_init(MSG_200); /* makes gcc shut up */ + char *buf; + + if(contact_header && contact_header->buf && (contact_header->buf_len > 0) + && (contact_header->data_len > 0)) { + LM_DBG("Contacts: %.*s\n", contact_header->data_len, + contact_header->buf); + add_lump_rpl(_m, contact_header->buf, contact_header->data_len, + LUMP_RPL_HDR | LUMP_RPL_NODUP | LUMP_RPL_NOFREE); + contact_header->data_len = 0; + } + + if(rerrno == R_FINE && path_enabled && _m->path_vec.s) { + if(path_mode != PATH_MODE_OFF) { + if(parse_supported(_m) < 0 && path_mode == PATH_MODE_STRICT) { + rerrno = R_PATH_UNSUP; + if(add_unsupported(_m, &unsup) < 0) + return -1; + if(add_path(_m, &_m->path_vec) < 0) + return -1; + } else if(get_supported(_m) & F_OPTION_TAG_PATH) { + if(add_path(_m, &_m->path_vec) < 0) + return -1; + } else if(path_mode == PATH_MODE_STRICT) { + rerrno = R_PATH_UNSUP; + if(add_unsupported(_m, &unsup) < 0) + return -1; + if(add_path(_m, &_m->path_vec) < 0) + return -1; + } + } + } + + code = codes[rerrno]; + if((code == 500) && (error_reply_code > 0)) + code = error_reply_code; + + switch(code) { + case 200: + msg.s = MSG_200; + msg.len = sizeof(MSG_200) - 1; + break; + case 400: + msg.s = MSG_400; + msg.len = sizeof(MSG_400) - 1; + break; + case 420: + msg.s = MSG_420; + msg.len = sizeof(MSG_420) - 1; + break; + case 500: + msg.s = MSG_500; + msg.len = sizeof(MSG_500) - 1; + break; + case 503: + msg.s = MSG_503; + msg.len = sizeof(MSG_503) - 1; + break; + } + + if(code != 200) { + buf = (char *)pkg_malloc( + E_INFO_LEN + error_info[rerrno].len + CRLF_LEN + 1); + if(!buf) { + LM_ERR("no pkg memory left\n"); + return -1; + } + memcpy(buf, E_INFO, E_INFO_LEN); + memcpy(buf + E_INFO_LEN, error_info[rerrno].s, error_info[rerrno].len); + memcpy(buf + E_INFO_LEN + error_info[rerrno].len, CRLF, CRLF_LEN); + add_lump_rpl(_m, buf, E_INFO_LEN + error_info[rerrno].len + CRLF_LEN, + LUMP_RPL_HDR | LUMP_RPL_NODUP); + + if(code >= 500 && code < 600 + && cfg_get(registrar, registrar_cfg, retry_after)) { + if(add_retry_after(_m) < 0) { + return -1; + } + } + } + + if((code > 199) && (code < 299)) { + if(p_associated_uri.data_len > 0) { + add_lump_rpl(_m, p_associated_uri.buf, p_associated_uri.data_len, + LUMP_RPL_HDR | LUMP_RPL_NODUP | LUMP_RPL_NOFREE); + p_associated_uri.data_len = 0; + } + if(add_service_route(_m, &scscf_serviceroute_uri_str) + < 0) { //TODO - need to insert orig into this scscf_name + return -1; + } + } + + if(slb.freply(_m, code, &msg) < 0) { + LM_ERR("failed to send %ld %.*s\n", code, msg.len, msg.s); + return -1; + } else + return 0; } /*! \brief * Release contact buffer if any */ -void free_contact_buf(contact_for_header_t* contact_header) { - if (contact_header && contact_header->buf) { - shm_free(contact_header->buf); - contact_header->buf = 0; - contact_header->buf_len = 0; - contact_header->data_len = 0; - } - if (contact_header)shm_free(contact_header); +void free_contact_buf(contact_for_header_t *contact_header) +{ + if(contact_header && contact_header->buf) { + shm_free(contact_header->buf); + contact_header->buf = 0; + contact_header->buf_len = 0; + contact_header->data_len = 0; + } + if(contact_header) + shm_free(contact_header); } -void free_p_associated_uri_buf(void) { - if (p_associated_uri.buf) { - pkg_free(p_associated_uri.buf); - p_associated_uri.buf = 0; - p_associated_uri.buf_len = 0; - p_associated_uri.data_len = 0; - } +void free_p_associated_uri_buf(void) +{ + if(p_associated_uri.buf) { + pkg_free(p_associated_uri.buf); + p_associated_uri.buf = 0; + p_associated_uri.buf_len = 0; + p_associated_uri.data_len = 0; + } } -void free_expired_contact_buf(void) { - +void free_expired_contact_buf(void) +{ } diff --git a/src/modules/ims_registrar_scscf/reply.h b/src/modules/ims_registrar_scscf/reply.h index d425f3fa6c4..470ed3fa881 100644 --- a/src/modules/ims_registrar_scscf/reply.h +++ b/src/modules/ims_registrar_scscf/reply.h @@ -26,7 +26,7 @@ * \file * \brief SIP registrar module - send a reply * \ingroup registrar - */ + */ #ifndef REPLY_H @@ -42,8 +42,9 @@ /*! \brief * Buffer for Contact header field */ -typedef struct contact_for_header { - char* buf; +typedef struct contact_for_header +{ + char *buf; int buf_len; int data_len; } contact_for_header_t; @@ -52,33 +53,36 @@ typedef struct contact_for_header { /*! \brief * Send a reply */ -int reg_send_reply(struct sip_msg* _m, contact_for_header_t* contact_header); +int reg_send_reply(struct sip_msg *_m, contact_for_header_t *contact_header); /*! \brief * Send a reply using tm */ -int reg_send_reply_transactional(struct sip_msg* _m, contact_for_header_t* contact_header, struct cell* t_cell); +int reg_send_reply_transactional(struct sip_msg *_m, + contact_for_header_t *contact_header, struct cell *t_cell); /*! \brief * Build Contact HF for reply */ -int build_contact(impurecord_t* impurec, contact_for_header_t** contact_header, struct sip_msg* msg); -int build_expired_contact(contact_t* chi, contact_for_header_t** contact_header); //this is for building the expired response - ie reply to dereg +int build_contact(impurecord_t *impurec, contact_for_header_t **contact_header, + struct sip_msg *msg); +int build_expired_contact(contact_t *chi, + contact_for_header_t ** + contact_header); //this is for building the expired response - ie reply to dereg -int build_p_associated_uri(ims_subscription* s); +int build_p_associated_uri(ims_subscription *s); /*! \brief * Release contact buffer if any */ -void free_contact_buf(contact_for_header_t* contact_header); +void free_contact_buf(contact_for_header_t *contact_header); void free_p_associated_uri_buf(void); void free_expired_contact_buf(void); - #endif /* REPLY_H */ diff --git a/src/modules/ims_registrar_scscf/rerrno.c b/src/modules/ims_registrar_scscf/rerrno.c index 227aaf0ffbc..930aa81100d 100644 --- a/src/modules/ims_registrar_scscf/rerrno.c +++ b/src/modules/ims_registrar_scscf/rerrno.c @@ -26,10 +26,9 @@ * \file * \brief SIP registrar module - registrar errno * \ingroup registrar - */ + */ #include "rerrno.h" rerr_t rerrno; - diff --git a/src/modules/ims_registrar_scscf/rerrno.h b/src/modules/ims_registrar_scscf/rerrno.h index 5f8029d9695..e288d21cd8c 100644 --- a/src/modules/ims_registrar_scscf/rerrno.h +++ b/src/modules/ims_registrar_scscf/rerrno.h @@ -31,38 +31,39 @@ #ifndef RERRNO_H #define RERRNO_H -typedef enum rerr { - R_FINE = 0, /*!< Everything went OK */ - R_UL_DEL_R, /*!< Usrloc record delete failed */ - R_UL_GET_R, /*!< Usrloc record get failed */ - R_UL_NEW_R, /*!< Usrloc new record failed */ - R_INV_CSEQ, /*!< Invalid CSeq value */ - R_UL_INS_C, /*!< Usrloc insert contact failed */ - R_UL_INS_R, /*!< Usrloc insert record failed */ - R_UL_DEL_C, /*!< Usrloc contact delete failed */ - R_UL_UPD_C, /*!< Usrloc contact update failed */ - R_TO_USER, /*!< No username part in To URI */ - R_AOR_LEN, /*!< Address Of Record too long */ - R_AOR_PARSE, /*!< Error while parsing Address Of Record */ - R_INV_EXP, /*!< Invalid expires parameter in contact */ - R_INV_Q, /*!< Invalid q parameter in contact */ - R_PARSE, /*!< Error while parsing message */ - R_TO_MISS, /*!< Missing To header field */ - R_CID_MISS, /*!< Missing Call-ID header field */ - R_CS_MISS, /*!< Missing CSeq header field */ - R_PARSE_EXP, /*!< Error while parsing Expires */ - R_PARSE_CONT, /*!< Error while parsing Contact */ - R_STAR_EXP, /*!< star and expires != 0 */ - R_STAR_CONT, /*!< star and more contacts */ - R_OOO, /*!< Out-Of-Order request */ - R_RETRANS, /*!< Request is retransmission */ - R_UNESCAPE, /*!< Error while unescaping username */ - R_TOO_MANY, /*!< Too many contacts */ - R_CONTACT_LEN, /*!< Contact URI or RECEIVED too long */ - R_CALLID_LEN, /*!< Callid too long */ - R_PARSE_PATH, /*!< Error while parsing Path */ - R_PATH_UNSUP, /*!< Path not supported by UAC */ - R_SAR_FAILED /*!< SAR failed */ +typedef enum rerr +{ + R_FINE = 0, /*!< Everything went OK */ + R_UL_DEL_R, /*!< Usrloc record delete failed */ + R_UL_GET_R, /*!< Usrloc record get failed */ + R_UL_NEW_R, /*!< Usrloc new record failed */ + R_INV_CSEQ, /*!< Invalid CSeq value */ + R_UL_INS_C, /*!< Usrloc insert contact failed */ + R_UL_INS_R, /*!< Usrloc insert record failed */ + R_UL_DEL_C, /*!< Usrloc contact delete failed */ + R_UL_UPD_C, /*!< Usrloc contact update failed */ + R_TO_USER, /*!< No username part in To URI */ + R_AOR_LEN, /*!< Address Of Record too long */ + R_AOR_PARSE, /*!< Error while parsing Address Of Record */ + R_INV_EXP, /*!< Invalid expires parameter in contact */ + R_INV_Q, /*!< Invalid q parameter in contact */ + R_PARSE, /*!< Error while parsing message */ + R_TO_MISS, /*!< Missing To header field */ + R_CID_MISS, /*!< Missing Call-ID header field */ + R_CS_MISS, /*!< Missing CSeq header field */ + R_PARSE_EXP, /*!< Error while parsing Expires */ + R_PARSE_CONT, /*!< Error while parsing Contact */ + R_STAR_EXP, /*!< star and expires != 0 */ + R_STAR_CONT, /*!< star and more contacts */ + R_OOO, /*!< Out-Of-Order request */ + R_RETRANS, /*!< Request is retransmission */ + R_UNESCAPE, /*!< Error while unescaping username */ + R_TOO_MANY, /*!< Too many contacts */ + R_CONTACT_LEN, /*!< Contact URI or RECEIVED too long */ + R_CALLID_LEN, /*!< Callid too long */ + R_PARSE_PATH, /*!< Error while parsing Path */ + R_PATH_UNSUP, /*!< Path not supported by UAC */ + R_SAR_FAILED /*!< SAR failed */ } rerr_t; diff --git a/src/modules/ims_registrar_scscf/save.c b/src/modules/ims_registrar_scscf/save.c index 3e75fdb46c4..d2aed2c18ac 100644 --- a/src/modules/ims_registrar_scscf/save.c +++ b/src/modules/ims_registrar_scscf/save.c @@ -79,25 +79,28 @@ #include "cxdx_sar.h" extern struct tm_binds tmb; -extern int store_data_on_dereg; /**< should we store SAR user data on de-registration */ +extern int + store_data_on_dereg; /**< should we store SAR user data on de-registration */ extern int ue_unsubscribe_on_dereg; extern int user_data_always; extern int skip_multiple_bindings_on_reg_resp; -#define DO_NOT_USE_REALM_FOR_PRIVATE_IDENTITY 0x01 +#define DO_NOT_USE_REALM_FOR_PRIVATE_IDENTITY 0x01 /* \brief * Return randomized expires between expires-range% and expires. * RFC allows only value less or equal to the one provided by UAC. */ -static inline int randomize_expires(int expires, int range) { - /* if no range is given just return expires */ - if (range == 0) return expires; +static inline int randomize_expires(int expires, int range) +{ + /* if no range is given just return expires */ + if(range == 0) + return expires; - int range_min = expires - (float) range / 100 * expires; + int range_min = expires - (float)range / 100 * expires; - return range_min + (float) (kam_rand() % 100) / 100 * (expires - range_min); + return range_min + (float)(kam_rand() % 100) / 100 * (expires - range_min); } /*! \brief @@ -109,29 +112,32 @@ static inline int randomize_expires(int expires, int range) { * 3) If the message contained no expires header field, use * the default value */ -static inline int calc_contact_expires(contact_t *c, int expires_hdr, int sos_reg) { +static inline int calc_contact_expires( + contact_t *c, int expires_hdr, int sos_reg) +{ int r = 0; if(c && c->expires) - str2int(&(c->expires->body), (unsigned int*) &r); - else if (expires_hdr >= 0) + str2int(&(c->expires->body), (unsigned int *)&r); + else if(expires_hdr >= 0) r = expires_hdr; else { - r = (sos_reg > 0) ? default_registrar_cfg.em_default_expires : default_registrar_cfg.default_expires; + r = (sos_reg > 0) ? default_registrar_cfg.em_default_expires + : default_registrar_cfg.default_expires; goto end; } - if (!sos_reg && r < default_registrar_cfg.min_expires) { + if(!sos_reg && r < default_registrar_cfg.min_expires) { r = default_registrar_cfg.min_expires; goto end; } - if (sos_reg && r < default_registrar_cfg.em_min_expires) { + if(sos_reg && r < default_registrar_cfg.em_min_expires) { r = default_registrar_cfg.em_min_expires; goto end; } - if (!sos_reg && r > default_registrar_cfg.max_expires) { + if(!sos_reg && r > default_registrar_cfg.max_expires) { r = default_registrar_cfg.max_expires; goto end; } - if (sos_reg && r > default_registrar_cfg.em_max_expires) { + if(sos_reg && r > default_registrar_cfg.em_max_expires) { r = default_registrar_cfg.em_min_expires; goto end; } @@ -146,234 +152,237 @@ static inline int calc_contact_expires(contact_t *c, int expires_hdr, int sos_re * we will remove all bindings with the given impu * from the usrloc and return 200 OK response */ -static inline int star(udomain_t* _d, str* _a) { - impurecord_t* r; +static inline int star(udomain_t *_d, str *_a) +{ + impurecord_t *r; - ul.lock_udomain(_d, _a); + ul.lock_udomain(_d, _a); - if (ul.delete_impurecord(_d, _a, 0) != 0) { - LM_ERR("failed to remove record from usrloc\n"); + if(ul.delete_impurecord(_d, _a, 0) != 0) { + LM_ERR("failed to remove record from usrloc\n"); - /* Delete failed, try to get corresponding + /* Delete failed, try to get corresponding * record structure and send back all existing * contacts */ - rerrno = R_UL_DEL_R; - - if (ul.get_impurecord(_d, _a, &r) == 0) { - contact_for_header_t** contact_header = 0; - build_contact(r, contact_header, 0); - free_contact_buf(*contact_header); - ul.unlock_udomain(_d, _a); - } - return -1; - } - ul.unlock_udomain(_d, _a); - return 0; + rerrno = R_UL_DEL_R; + + if(ul.get_impurecord(_d, _a, &r) == 0) { + contact_for_header_t **contact_header = 0; + build_contact(r, contact_header, 0); + free_contact_buf(*contact_header); + ul.unlock_udomain(_d, _a); + } + return -1; + } + ul.unlock_udomain(_d, _a); + return 0; } /*! \brief */ -static struct socket_info *get_sock_hdr(struct sip_msg *msg) { - struct socket_info *sock; - struct hdr_field *hf; - str socks; - str hosts; - int port; - int proto; - char c; - - if (parse_headers(msg, HDR_EOH_F, 0) == -1) { - LM_ERR("failed to parse message\n"); - return 0; - } - - for (hf = msg->headers; hf; hf = hf->next) { - if (cmp_hdrname_str(&hf->name, &sock_hdr_name) == 0) - break; - } - - /* hdr found? */ - if (hf == 0) - return 0; - - trim_len(socks.len, socks.s, hf->body); - if (socks.len == 0) - return 0; - - /*FIXME: This is a hack */ - c = socks.s[socks.len]; - socks.s[socks.len] = '\0'; - if (parse_phostport(socks.s, &hosts.s, &hosts.len, &port, &proto) != 0) { - socks.s[socks.len] = c; - LM_ERR("bad socket <%.*s> in \n", - socks.len, socks.s); - return 0; - } - socks.s[socks.len] = c; - sock = grep_sock_info(&hosts, (unsigned short) port, - (unsigned short) proto); - if (sock == 0) { - LM_ERR("non-local socket <%.*s>\n", socks.len, socks.s); - return 0; - } - - LM_DBG("%d:<%.*s>:%d -> p=%p\n", proto, socks.len, socks.s, port_no, sock); - - return sock; +static struct socket_info *get_sock_hdr(struct sip_msg *msg) +{ + struct socket_info *sock; + struct hdr_field *hf; + str socks; + str hosts; + int port; + int proto; + char c; + + if(parse_headers(msg, HDR_EOH_F, 0) == -1) { + LM_ERR("failed to parse message\n"); + return 0; + } + + for(hf = msg->headers; hf; hf = hf->next) { + if(cmp_hdrname_str(&hf->name, &sock_hdr_name) == 0) + break; + } + + /* hdr found? */ + if(hf == 0) + return 0; + + trim_len(socks.len, socks.s, hf->body); + if(socks.len == 0) + return 0; + + /*FIXME: This is a hack */ + c = socks.s[socks.len]; + socks.s[socks.len] = '\0'; + if(parse_phostport(socks.s, &hosts.s, &hosts.len, &port, &proto) != 0) { + socks.s[socks.len] = c; + LM_ERR("bad socket <%.*s> in \n", socks.len, socks.s); + return 0; + } + socks.s[socks.len] = c; + sock = grep_sock_info(&hosts, (unsigned short)port, (unsigned short)proto); + if(sock == 0) { + LM_ERR("non-local socket <%.*s>\n", socks.len, socks.s); + return 0; + } + + LM_DBG("%d:<%.*s>:%d -> p=%p\n", proto, socks.len, socks.s, port_no, sock); + + return sock; } /*! \brief * Fills the common part (for all contacts) of the info structure */ -static inline ucontact_info_t* pack_ci(struct sip_msg* _m, contact_t* _c, unsigned int _e, unsigned int _f) { - static ucontact_info_t ci; - static str no_ua = str_init("n/a"); - static str callid; - static str path_received = {0, 0}; - static str path; - static str received = {0, 0}; - static int received_found; - static unsigned int allowed, allow_parsed; - static struct sip_msg *m = 0; - int_str val; - - if (_m != 0) { - memset(&ci, 0, sizeof (ucontact_info_t)); - - /* Get callid of the message */ - callid = _m->callid->body; - trim_trailing(&callid); - if (callid.len > CALLID_MAX_SIZE) { - rerrno = R_CALLID_LEN; - LM_ERR("callid too long\n"); - goto error; - } - ci.callid = &callid; - - /* Get CSeq number of the message */ - if (str2int(&get_cseq(_m)->number, (unsigned int*) &ci.cseq) < 0) { - rerrno = R_INV_CSEQ; - LM_ERR("failed to convert cseq number\n"); - goto error; - } - - /* set received socket */ - if (_m->flags & sock_flag) { - ci.sock = get_sock_hdr(_m); - if (ci.sock == 0) - ci.sock = _m->rcv.bind_address; - } else { - ci.sock = _m->rcv.bind_address; - } - - /* additional info from message */ - if (parse_headers(_m, HDR_USERAGENT_F, 0) != -1 && _m->user_agent - && _m->user_agent->body.len > 0 && _m->user_agent->body.len < MAX_UA_SIZE) { - ci.user_agent = &_m->user_agent->body; - } else { - ci.user_agent = &no_ua; - } - - /* extract Path headers */ - if (path_enabled) { - if (build_path_vector(_m, &path, &path_received) < 0) { - rerrno = R_PARSE_PATH; - goto error; - } - if (path.len && path.s) { - ci.path = &path; - if (path_mode != PATH_MODE_OFF) { - /* save in msg too for reply */ - if (set_path_vector(_m, &path) < 0) { - rerrno = R_PARSE_PATH; - goto error; - } - } - } - } - - if (_c->params) { - ci.params = _c->params; - } - - /* set flags */ - ci.flags = _f; - getbflagsval(0, &ci.cflags); - - /* get received */ - if (path_received.len && path_received.s) { - ci.cflags |= ul.nat_flag; - ci.received = path_received; - } - - allow_parsed = 0; /* not parsed yet */ - received_found = 0; /* not found yet */ - m = _m; /* remember the message */ - } - - if (_c != 0) { - /* Calculate q value of the contact */ - if (calc_contact_q(_c->q, &ci.q) < 0) { - rerrno = R_INV_Q; - LM_ERR("failed to calculate q\n"); - goto error; - } - - /* set expire time */ - ci.expires = _e; - - /* Get methods of contact */ - if (_c->methods) { - if (parse_methods(&(_c->methods->body), &ci.methods) < 0) { - rerrno = R_PARSE; - LM_ERR("failed to parse contact methods\n"); - goto error; - } - } else { - /* check on Allow hdr */ - if (allow_parsed == 0) { - if (m && parse_allow(m) != -1) { - allowed = get_allow_methods(m); - } else { - allowed = ALL_METHODS; - } - allow_parsed = 1; - } - ci.methods = allowed; - } - - /* get received */ - if (ci.received.len == 0) { - if (_c->received) { - ci.received = _c->received->body; - } else { - if (received_found == 0) { - memset(&val, 0, sizeof (int_str)); - if (rcv_avp_name.n != 0 - && search_first_avp(rcv_avp_type, rcv_avp_name, - &val, 0) && val.s.len > 0) { - if (val.s.len > RECEIVED_MAX_SIZE) { - rerrno = R_CONTACT_LEN; - LM_ERR("received too long\n"); - goto error; - } - received = val.s; - } else { - received.s = 0; - received.len = 0; - } - received_found = 1; - } - ci.received = received; - } - } - - } - - return &ci; +static inline ucontact_info_t *pack_ci( + struct sip_msg *_m, contact_t *_c, unsigned int _e, unsigned int _f) +{ + static ucontact_info_t ci; + static str no_ua = str_init("n/a"); + static str callid; + static str path_received = {0, 0}; + static str path; + static str received = {0, 0}; + static int received_found; + static unsigned int allowed, allow_parsed; + static struct sip_msg *m = 0; + int_str val; + + if(_m != 0) { + memset(&ci, 0, sizeof(ucontact_info_t)); + + /* Get callid of the message */ + callid = _m->callid->body; + trim_trailing(&callid); + if(callid.len > CALLID_MAX_SIZE) { + rerrno = R_CALLID_LEN; + LM_ERR("callid too long\n"); + goto error; + } + ci.callid = &callid; + + /* Get CSeq number of the message */ + if(str2int(&get_cseq(_m)->number, (unsigned int *)&ci.cseq) < 0) { + rerrno = R_INV_CSEQ; + LM_ERR("failed to convert cseq number\n"); + goto error; + } + + /* set received socket */ + if(_m->flags & sock_flag) { + ci.sock = get_sock_hdr(_m); + if(ci.sock == 0) + ci.sock = _m->rcv.bind_address; + } else { + ci.sock = _m->rcv.bind_address; + } + + /* additional info from message */ + if(parse_headers(_m, HDR_USERAGENT_F, 0) != -1 && _m->user_agent + && _m->user_agent->body.len > 0 + && _m->user_agent->body.len < MAX_UA_SIZE) { + ci.user_agent = &_m->user_agent->body; + } else { + ci.user_agent = &no_ua; + } + + /* extract Path headers */ + if(path_enabled) { + if(build_path_vector(_m, &path, &path_received) < 0) { + rerrno = R_PARSE_PATH; + goto error; + } + if(path.len && path.s) { + ci.path = &path; + if(path_mode != PATH_MODE_OFF) { + /* save in msg too for reply */ + if(set_path_vector(_m, &path) < 0) { + rerrno = R_PARSE_PATH; + goto error; + } + } + } + } + + if(_c->params) { + ci.params = _c->params; + } + + /* set flags */ + ci.flags = _f; + getbflagsval(0, &ci.cflags); + + /* get received */ + if(path_received.len && path_received.s) { + ci.cflags |= ul.nat_flag; + ci.received = path_received; + } + + allow_parsed = 0; /* not parsed yet */ + received_found = 0; /* not found yet */ + m = _m; /* remember the message */ + } + + if(_c != 0) { + /* Calculate q value of the contact */ + if(calc_contact_q(_c->q, &ci.q) < 0) { + rerrno = R_INV_Q; + LM_ERR("failed to calculate q\n"); + goto error; + } + + /* set expire time */ + ci.expires = _e; + + /* Get methods of contact */ + if(_c->methods) { + if(parse_methods(&(_c->methods->body), &ci.methods) < 0) { + rerrno = R_PARSE; + LM_ERR("failed to parse contact methods\n"); + goto error; + } + } else { + /* check on Allow hdr */ + if(allow_parsed == 0) { + if(m && parse_allow(m) != -1) { + allowed = get_allow_methods(m); + } else { + allowed = ALL_METHODS; + } + allow_parsed = 1; + } + ci.methods = allowed; + } + + /* get received */ + if(ci.received.len == 0) { + if(_c->received) { + ci.received = _c->received->body; + } else { + if(received_found == 0) { + memset(&val, 0, sizeof(int_str)); + if(rcv_avp_name.n != 0 + && search_first_avp( + rcv_avp_type, rcv_avp_name, &val, 0) + && val.s.len > 0) { + if(val.s.len > RECEIVED_MAX_SIZE) { + rerrno = R_CONTACT_LEN; + LM_ERR("received too long\n"); + goto error; + } + received = val.s; + } else { + received.s = 0; + received.len = 0; + } + received_found = 1; + } + ci.received = received; + } + } + } + + return &ci; error: - return 0; + return 0; } /** @@ -381,291 +390,357 @@ static inline ucontact_info_t* pack_ci(struct sip_msg* _m, contact_t* _c, unsign * \note Must be called with the lock got to avoid races * @param s - the ims_subscription to free */ -void free_ims_subscription_data(ims_subscription *s) { - int i, j, k; - if (!s) - return; - /* lock_get(s->lock); - must be called with the lock got */ - for (i = 0; i < s->service_profiles_cnt; i++) { - for (j = 0; j < s->service_profiles[i].public_identities_cnt; j++) { - if (s->service_profiles[i].public_identities[j].public_identity.s) - shm_free( - s->service_profiles[i].public_identities[j].public_identity.s); - if (s->service_profiles[i].public_identities[j].wildcarded_psi.s) - shm_free( - s->service_profiles[i].public_identities[j].wildcarded_psi.s); - - } - if (s->service_profiles[i].public_identities) - shm_free(s->service_profiles[i].public_identities); - - for (j = 0; j < s->service_profiles[i].filter_criteria_cnt; j++) { - if (s->service_profiles[i].filter_criteria[j].trigger_point) { - for (k = 0; - k - < s->service_profiles[i].filter_criteria[j].trigger_point->spt_cnt; - k++) { - switch (s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].type) { - case IFC_REQUEST_URI: - if (s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].request_uri.s) - shm_free( - s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].request_uri.s); - break; - case IFC_METHOD: - if (s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].method.s) - shm_free( - s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].method.s); - break; - case IFC_SIP_HEADER: - if (s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].sip_header.header.s) - shm_free( - s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].sip_header.header.s); - if (s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].sip_header.content.s) - shm_free( - s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].sip_header.content.s); - break; - case IFC_SESSION_CASE: - break; - case IFC_SESSION_DESC: - if (s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].session_desc.line.s) - shm_free( - s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].session_desc.line.s); - if (s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].session_desc.content.s) - shm_free( - s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].session_desc.content.s); - break; - - } - } - if (s->service_profiles[i].filter_criteria[j].trigger_point->spt) - shm_free( - s->service_profiles[i].filter_criteria[j].trigger_point->spt); - shm_free( - s->service_profiles[i].filter_criteria[j].trigger_point); - } - if (s->service_profiles[i].filter_criteria[j].application_server.server_name.s) - shm_free( - s->service_profiles[i].filter_criteria[j].application_server.server_name.s); - if (s->service_profiles[i].filter_criteria[j].application_server.service_info.s) - shm_free( - s->service_profiles[i].filter_criteria[j].application_server.service_info.s); - if (s->service_profiles[i].filter_criteria[j].profile_part_indicator) - shm_free( - s->service_profiles[i].filter_criteria[j].profile_part_indicator); - } - if (s->service_profiles[i].filter_criteria) - shm_free(s->service_profiles[i].filter_criteria); - - if (s->service_profiles[i].cn_service_auth) - shm_free(s->service_profiles[i].cn_service_auth); - - if (s->service_profiles[i].shared_ifc_set) - shm_free(s->service_profiles[i].shared_ifc_set); - } - if (s->service_profiles) - shm_free(s->service_profiles); - if (s->private_identity.s) - shm_free(s->private_identity.s); - ul.unlock_subscription(s); +void free_ims_subscription_data(ims_subscription *s) +{ + int i, j, k; + if(!s) + return; + /* lock_get(s->lock); - must be called with the lock got */ + for(i = 0; i < s->service_profiles_cnt; i++) { + for(j = 0; j < s->service_profiles[i].public_identities_cnt; j++) { + if(s->service_profiles[i].public_identities[j].public_identity.s) + shm_free(s->service_profiles[i] + .public_identities[j] + .public_identity.s); + if(s->service_profiles[i].public_identities[j].wildcarded_psi.s) + shm_free(s->service_profiles[i] + .public_identities[j] + .wildcarded_psi.s); + } + if(s->service_profiles[i].public_identities) + shm_free(s->service_profiles[i].public_identities); + + for(j = 0; j < s->service_profiles[i].filter_criteria_cnt; j++) { + if(s->service_profiles[i].filter_criteria[j].trigger_point) { + for(k = 0; k < s->service_profiles[i] + .filter_criteria[j] + .trigger_point->spt_cnt; + k++) { + switch(s->service_profiles[i] + .filter_criteria[j] + .trigger_point->spt[k] + .type) { + case IFC_REQUEST_URI: + if(s->service_profiles[i] + .filter_criteria[j] + .trigger_point->spt[k] + .request_uri.s) + shm_free(s->service_profiles[i] + .filter_criteria[j] + .trigger_point->spt[k] + .request_uri.s); + break; + case IFC_METHOD: + if(s->service_profiles[i] + .filter_criteria[j] + .trigger_point->spt[k] + .method.s) + shm_free(s->service_profiles[i] + .filter_criteria[j] + .trigger_point->spt[k] + .method.s); + break; + case IFC_SIP_HEADER: + if(s->service_profiles[i] + .filter_criteria[j] + .trigger_point->spt[k] + .sip_header.header.s) + shm_free(s->service_profiles[i] + .filter_criteria[j] + .trigger_point->spt[k] + .sip_header.header.s); + if(s->service_profiles[i] + .filter_criteria[j] + .trigger_point->spt[k] + .sip_header.content.s) + shm_free(s->service_profiles[i] + .filter_criteria[j] + .trigger_point->spt[k] + .sip_header.content.s); + break; + case IFC_SESSION_CASE: + break; + case IFC_SESSION_DESC: + if(s->service_profiles[i] + .filter_criteria[j] + .trigger_point->spt[k] + .session_desc.line.s) + shm_free(s->service_profiles[i] + .filter_criteria[j] + .trigger_point->spt[k] + .session_desc.line.s); + if(s->service_profiles[i] + .filter_criteria[j] + .trigger_point->spt[k] + .session_desc.content.s) + shm_free(s->service_profiles[i] + .filter_criteria[j] + .trigger_point->spt[k] + .session_desc.content.s); + break; + } + } + if(s->service_profiles[i].filter_criteria[j].trigger_point->spt) + shm_free(s->service_profiles[i] + .filter_criteria[j] + .trigger_point->spt); + shm_free(s->service_profiles[i] + .filter_criteria[j] + .trigger_point); + } + if(s->service_profiles[i] + .filter_criteria[j] + .application_server.server_name.s) + shm_free(s->service_profiles[i] + .filter_criteria[j] + .application_server.server_name.s); + if(s->service_profiles[i] + .filter_criteria[j] + .application_server.service_info.s) + shm_free(s->service_profiles[i] + .filter_criteria[j] + .application_server.service_info.s); + if(s->service_profiles[i].filter_criteria[j].profile_part_indicator) + shm_free(s->service_profiles[i] + .filter_criteria[j] + .profile_part_indicator); + } + if(s->service_profiles[i].filter_criteria) + shm_free(s->service_profiles[i].filter_criteria); + + if(s->service_profiles[i].cn_service_auth) + shm_free(s->service_profiles[i].cn_service_auth); + + if(s->service_profiles[i].shared_ifc_set) + shm_free(s->service_profiles[i].shared_ifc_set); + } + if(s->service_profiles) + shm_free(s->service_profiles); + if(s->private_identity.s) + shm_free(s->private_identity.s); + ul.unlock_subscription(s); #ifdef EXTRA_DEBUG - LM_DBG("SUBSCRIPTION LOCK %p destroyed\n", s->lock); + LM_DBG("SUBSCRIPTION LOCK %p destroyed\n", s->lock); #endif - lock_destroy(s->lock); - lock_dealloc(s->lock); - shm_free(s); - + lock_destroy(s->lock); + lock_dealloc(s->lock); + shm_free(s); } /** Check if an impu record exists. * 1. must be in registered state (impurecord) * 2. must have at least one valid contact */ -static inline int is_impu_registered(udomain_t* _d, str* public_identity) { - int res, ret = 1; - impurecord_t* impu; - - ul.lock_udomain(_d, public_identity); - res = ul.get_impurecord(_d, public_identity, &impu); - if (res != 0) { - ul.unlock_udomain(_d, public_identity); - return 0; - } else { - //check reg status - if (impu->reg_state != IMPU_REGISTERED) { - LM_DBG("IMPU <%.*s> is not currently registered\n", public_identity->len, public_identity->s); - ret = 0; - } - - //check valid contacts - if ((impu->linked_contacts.numcontacts <= 0) || (impu->linked_contacts.head == 0)) { - LM_DBG("IMPU <%.*s> has no valid contacts\n", public_identity->len, public_identity->s); - ret = 0; - } - ul.unlock_udomain(_d, public_identity); - } - return ret; +static inline int is_impu_registered(udomain_t *_d, str *public_identity) +{ + int res, ret = 1; + impurecord_t *impu; + + ul.lock_udomain(_d, public_identity); + res = ul.get_impurecord(_d, public_identity, &impu); + if(res != 0) { + ul.unlock_udomain(_d, public_identity); + return 0; + } else { + //check reg status + if(impu->reg_state != IMPU_REGISTERED) { + LM_DBG("IMPU <%.*s> is not currently registered\n", + public_identity->len, public_identity->s); + ret = 0; + } + + //check valid contacts + if((impu->linked_contacts.numcontacts <= 0) + || (impu->linked_contacts.head == 0)) { + LM_DBG("IMPU <%.*s> has no valid contacts\n", public_identity->len, + public_identity->s); + ret = 0; + } + ul.unlock_udomain(_d, public_identity); + } + return ret; } /** * update the contacts for a public identity. Make sure you have the lock on the domain before calling this * returns 0 on success, -1 on failure */ -static inline int update_contacts_helper(struct sip_msg* msg, impurecord_t* impu_rec, int assignment_type, int expires_hdr) { - struct hdr_field* h; - contact_t* chi; //contact header information - ucontact_info_t* ci; //ucontact info - qvalue_t qvalue; - int sos = 0, expires; - struct ucontact* ucontact; - int result, sl; - - LM_DBG("updating the contacts for IMPU <%.*s>\n", impu_rec->public_identity.len, impu_rec->public_identity.s); - - switch (assignment_type) { - - case AVP_IMS_SAR_USER_DEREGISTRATION: - LM_DBG("update_contacts_helper: doing de-reg\n"); - break; - - case AVP_IMS_SAR_REGISTRATION: - case AVP_IMS_SAR_RE_REGISTRATION: - for (h = msg->contact; h; h = h->next) { - if (h->type == HDR_CONTACT_T && h->parsed) { - - for (chi = ((contact_body_t*) h->parsed)->contacts; chi; chi = - chi->next) { - if (calc_contact_q(chi->q, &qvalue) != 0) { - LM_ERR("error on <%.*s>\n", chi->uri.len, chi->uri.s); - goto error; - } - sos = cscf_get_sos_uri_param(chi->uri); - if (sos < 0) { - LM_ERR("Error trying to determine if this is a sos contact <%.*s>\n", chi->uri.len, chi->uri.s); - goto error; - } - expires = calc_contact_expires(chi, expires_hdr, sos); - //TODO: this next line will fail if the expires is in the main body and not the contact body //FIXED - LM_DBG("Need to update contact: <%.*s>: " - "q_value [%d]," - "sos: [%d]," - "expires [%" TIME_T_FMT "]\n", chi->uri.len, chi->uri.s, qvalue, sos, TIME_T_CAST(expires - time(NULL))); - - LM_DBG("packing contact information\n"); - if ((ci = pack_ci(msg, chi, expires, 0)) == 0) { - LM_ERR("Failed to extract contact info\n"); - goto error; - } - - LM_DBG("adding/updating contact based on prior existence\n"); - //stick the contacts into usrloc - //ul.lock_contact_slot(&chi->uri); - result = ul.get_ucontact(&chi->uri, ci->callid, - ci->path, ci->cseq, &ucontact); - if (result != 0) { //get_contact returns with lock - LM_DBG("inserting new contact\n"); - if (ul.insert_ucontact(impu_rec, &chi->uri, ci, - &ucontact) != 0) { - LM_ERR("Error inserting contact <%.*s>\n", chi->uri.len, chi->uri.s); - // ul.unlock_contact_slot(&chi->uri); - goto error; - } - } else { - LM_DBG("Contact already exists - updating - it's currently in state [%d]\n", ucontact->state); - sl = ucontact->sl; - ul.lock_contact_slot_i(sl); - if (ucontact->state != CONTACT_VALID) { - LM_WARN("contact is not in state valid - this is a race between dereg and reg/re-reg"); - ucontact->state = CONTACT_VALID; //TODO this should prob move into the contact info structure - ie pass state into update - } - if (ul.update_ucontact(impu_rec, ucontact, ci) != 0) { - LM_ERR("Error updating contact <%.*s>\n", chi->uri.len, chi->uri.s); - ul.unlock_contact_slot_i(sl); - ul.release_ucontact(ucontact); - // ul.unlock_contact_slot(&chi->uri); - goto error; - } - ul.unlock_contact_slot_i(sl); - ul.release_ucontact(ucontact); - } - // ul.unlock_contact_slot(&chi->uri); - } - } - } - break; - } - - return 0; +static inline int update_contacts_helper(struct sip_msg *msg, + impurecord_t *impu_rec, int assignment_type, int expires_hdr) +{ + struct hdr_field *h; + contact_t *chi; //contact header information + ucontact_info_t *ci; //ucontact info + qvalue_t qvalue; + int sos = 0, expires; + struct ucontact *ucontact; + int result, sl; + + LM_DBG("updating the contacts for IMPU <%.*s>\n", + impu_rec->public_identity.len, impu_rec->public_identity.s); + + switch(assignment_type) { + + case AVP_IMS_SAR_USER_DEREGISTRATION: + LM_DBG("update_contacts_helper: doing de-reg\n"); + break; + + case AVP_IMS_SAR_REGISTRATION: + case AVP_IMS_SAR_RE_REGISTRATION: + for(h = msg->contact; h; h = h->next) { + if(h->type == HDR_CONTACT_T && h->parsed) { + + for(chi = ((contact_body_t *)h->parsed)->contacts; chi; + chi = chi->next) { + if(calc_contact_q(chi->q, &qvalue) != 0) { + LM_ERR("error on <%.*s>\n", chi->uri.len, + chi->uri.s); + goto error; + } + sos = cscf_get_sos_uri_param(chi->uri); + if(sos < 0) { + LM_ERR("Error trying to determine if this is a sos " + "contact <%.*s>\n", + chi->uri.len, chi->uri.s); + goto error; + } + expires = calc_contact_expires(chi, expires_hdr, sos); + //TODO: this next line will fail if the expires is in the main body and not the contact body //FIXED + LM_DBG("Need to update contact: <%.*s>: " + "q_value [%d]," + "sos: [%d]," + "expires [%" TIME_T_FMT "]\n", + chi->uri.len, chi->uri.s, qvalue, sos, + TIME_T_CAST(expires - time(NULL))); + + LM_DBG("packing contact information\n"); + if((ci = pack_ci(msg, chi, expires, 0)) == 0) { + LM_ERR("Failed to extract contact info\n"); + goto error; + } + + LM_DBG("adding/updating contact based on prior " + "existence\n"); + //stick the contacts into usrloc + //ul.lock_contact_slot(&chi->uri); + result = ul.get_ucontact(&chi->uri, ci->callid, + ci->path, ci->cseq, &ucontact); + if(result != 0) { //get_contact returns with lock + LM_DBG("inserting new contact\n"); + if(ul.insert_ucontact( + impu_rec, &chi->uri, ci, &ucontact) + != 0) { + LM_ERR("Error inserting contact <%.*s>\n", + chi->uri.len, chi->uri.s); + // ul.unlock_contact_slot(&chi->uri); + goto error; + } + } else { + LM_DBG("Contact already exists - updating - it's " + "currently in state [%d]\n", + ucontact->state); + sl = ucontact->sl; + ul.lock_contact_slot_i(sl); + if(ucontact->state != CONTACT_VALID) { + LM_WARN("contact is not in state valid - this " + "is a race between dereg and " + "reg/re-reg"); + ucontact->state = + CONTACT_VALID; //TODO this should prob move into the contact info structure - ie pass state into update + } + if(ul.update_ucontact(impu_rec, ucontact, ci) + != 0) { + LM_ERR("Error updating contact <%.*s>\n", + chi->uri.len, chi->uri.s); + ul.unlock_contact_slot_i(sl); + ul.release_ucontact(ucontact); + // ul.unlock_contact_slot(&chi->uri); + goto error; + } + ul.unlock_contact_slot_i(sl); + ul.release_ucontact(ucontact); + } + // ul.unlock_contact_slot(&chi->uri); + } + } + } + break; + } + + return 0; error: - return -1; + return -1; } /*NB remember to lock udomain prior to calling this*/ -static inline int unregister_contact(contact_t* chi, contact_state_t state) { - struct ucontact* ucontact; - str callid = {0, 0}; - str path = {0, 0}; - - - // if (_impu_rec) { - // LM_DBG("already have impurecord....\n"); - // impu_rec = _impu_rec; - // } else { - // if (ul.get_impurecord(_d, public_identity, &impu_rec) != 0) { - // LM_ERR("Error, no public identity exists for <%.*s>\n", public_identity->len, public_identity->s); - // goto error; - // } - // } - - if (ul.get_ucontact(&chi->uri, &callid, &path, 0/*cseq*/, &ucontact) != 0) { - LM_DBG("Can't unregister contact that does not exist <%.*s>\n", chi->uri.len, chi->uri.s); - // ul.unlock_udomain(_d, public_identity); - goto error; - } - - get_act_time(); - if (ucontact->state == CONTACT_DELETED) { - LM_DBG("Contact is not valid (expired/deleted).... ignoring\n"); - ul.release_ucontact(ucontact); - return 0; - } - - //Richard added this - fix to remove subscribes that have presentity and watcher uri same as a contact aor that is being removed - //When UEs explicitly dereg - they don't unsubscribe, so we remove subscriptions for them - //only do this if ue_unsubscribe_on_dereg is set to 0 - // if (!ue_unsubscribe_on_dereg) { - // s = impu_rec->shead; - // LM_DBG("Checking if there is a subscription to this IMPU that has same watcher contact as this contact"); - // while (s) { - // - // LM_DBG("Subscription for this impurecord: watcher uri [%.*s] presentity uri [%.*s] watcher contact [%.*s] ", s->watcher_uri.len, s->watcher_uri.s, - // s->presentity_uri.len, s->presentity_uri.s, s->watcher_contact.len, s->watcher_contact.s); - // LM_DBG("Contact to be removed [%.*s] ", ucontact->c.len, ucontact->c.s); - // if (contact_port_ip_match(&s->watcher_contact, &ucontact->c)) { - // //if ((s->watcher_contact.len == ucontact->c.len) && (strncasecmp(s->watcher_contact.s, ucontact->c.s, ucontact->c.len) == 0)) { - // LM_DBG("This contact has a subscription to its own status - so going to delete the subscription"); - // ul.external_delete_subscriber(s, _d, 0 /*domain is locked*/); - // } - // s = s->next; - // } - // } - - // if (ul.delete_ucontact(impu_rec, ucontact) != 0) { - ul.lock_contact_slot_i(ucontact->sl); - ucontact->state = state; - // notify_subscribers(impu_rec); - // ucontact->state = CONTACT_DELETED; - // if (ul.unlink_contact_from_impu(impu_rec, ucontact, 1, 1/*explicit dereg of contact*/) != 0) { - // LM_ERR("Failed to delete ucontact <%.*s>\n", chi->uri.len, chi->uri.s); - // } - ul.unlock_contact_slot_i(ucontact->sl); - ul.release_ucontact(ucontact); - // LM_DBG("Contact unlinked successfully <%.*s>\n", chi->uri.len, chi->uri.s); - // ul.unlock_udomain(_d, public_identity); - return 0; +static inline int unregister_contact(contact_t *chi, contact_state_t state) +{ + struct ucontact *ucontact; + str callid = {0, 0}; + str path = {0, 0}; + + + // if (_impu_rec) { + // LM_DBG("already have impurecord....\n"); + // impu_rec = _impu_rec; + // } else { + // if (ul.get_impurecord(_d, public_identity, &impu_rec) != 0) { + // LM_ERR("Error, no public identity exists for <%.*s>\n", public_identity->len, public_identity->s); + // goto error; + // } + // } + + if(ul.get_ucontact(&chi->uri, &callid, &path, 0 /*cseq*/, &ucontact) != 0) { + LM_DBG("Can't unregister contact that does not exist <%.*s>\n", + chi->uri.len, chi->uri.s); + // ul.unlock_udomain(_d, public_identity); + goto error; + } + + get_act_time(); + if(ucontact->state == CONTACT_DELETED) { + LM_DBG("Contact is not valid (expired/deleted).... ignoring\n"); + ul.release_ucontact(ucontact); + return 0; + } + + //Richard added this - fix to remove subscribes that have presentity and watcher uri same as a contact aor that is being removed + //When UEs explicitly dereg - they don't unsubscribe, so we remove subscriptions for them + //only do this if ue_unsubscribe_on_dereg is set to 0 + // if (!ue_unsubscribe_on_dereg) { + // s = impu_rec->shead; + // LM_DBG("Checking if there is a subscription to this IMPU that has same watcher contact as this contact"); + // while (s) { + // + // LM_DBG("Subscription for this impurecord: watcher uri [%.*s] presentity uri [%.*s] watcher contact [%.*s] ", s->watcher_uri.len, s->watcher_uri.s, + // s->presentity_uri.len, s->presentity_uri.s, s->watcher_contact.len, s->watcher_contact.s); + // LM_DBG("Contact to be removed [%.*s] ", ucontact->c.len, ucontact->c.s); + // if (contact_port_ip_match(&s->watcher_contact, &ucontact->c)) { + // //if ((s->watcher_contact.len == ucontact->c.len) && (strncasecmp(s->watcher_contact.s, ucontact->c.s, ucontact->c.len) == 0)) { + // LM_DBG("This contact has a subscription to its own status - so going to delete the subscription"); + // ul.external_delete_subscriber(s, _d, 0 /*domain is locked*/); + // } + // s = s->next; + // } + // } + + // if (ul.delete_ucontact(impu_rec, ucontact) != 0) { + ul.lock_contact_slot_i(ucontact->sl); + ucontact->state = state; + // notify_subscribers(impu_rec); + // ucontact->state = CONTACT_DELETED; + // if (ul.unlink_contact_from_impu(impu_rec, ucontact, 1, 1/*explicit dereg of contact*/) != 0) { + // LM_ERR("Failed to delete ucontact <%.*s>\n", chi->uri.len, chi->uri.s); + // } + ul.unlock_contact_slot_i(ucontact->sl); + ul.release_ucontact(ucontact); + // LM_DBG("Contact unlinked successfully <%.*s>\n", chi->uri.len, chi->uri.s); + // ul.unlock_udomain(_d, public_identity); + return 0; error: - return -1; + return -1; } /** @@ -673,79 +748,94 @@ static inline int unregister_contact(contact_t* chi, contact_state_t state) { * @param impu * @return */ -int get_number_of_valid_contacts(impurecord_t* impu) { - int ret = 0; +int get_number_of_valid_contacts(impurecord_t *impu) +{ + int ret = 0; impu_contact_t *impucontact; - get_act_time(); - + get_act_time(); + impucontact = impu->linked_contacts.head; - while (impucontact) { - if (impucontact->contact) { - if VALID_CONTACT(impucontact->contact, act_time) - ret++; - } else { - //if we hit a null ref then we are at the end of the list. - return ret; - } + while(impucontact) { + if(impucontact->contact) { + if VALID_CONTACT(impucontact->contact, act_time) + ret++; + } else { + //if we hit a null ref then we are at the end of the list. + return ret; + } impucontact = impucontact->next; - } + } - return ret; + return ret; } -int store_explicit_dereg_contact(struct sip_msg* msg, str ** explicit_dereg_contact, int *num_explicit_dereg_contact) { - int bytes_needed_explicit_dereg_contact = 0; - int len_num_explicit_dereg_contact = 0; - struct hdr_field* h; - contact_t* chi; //contact header information - - LM_DBG("This is an explicit deregistration so we need to store the contact URI to send out NOTIFY\n"); - - //get lengths - for (h = msg->contact; h; h = h->next) { - if (h->type == HDR_CONTACT_T && h->parsed) { - for (chi = ((contact_body_t*) h->parsed)->contacts; chi; chi = chi->next) { - LM_DBG("URI [%.*s] len [%d]\n", chi->uri.len, chi->uri.s, chi->uri.len); - (*num_explicit_dereg_contact)++; - bytes_needed_explicit_dereg_contact += chi->uri.len; - LM_DBG("URI [%.*s] and current bytes needed [%d]\n", chi->uri.len, chi->uri.s, bytes_needed_explicit_dereg_contact); - - } - } - } - - LM_DBG("We have [%d] explicit contacts of total length [%d] to store\n", (*num_explicit_dereg_contact), bytes_needed_explicit_dereg_contact); - - //now load data - - len_num_explicit_dereg_contact = (sizeof (str)*(*num_explicit_dereg_contact)) + bytes_needed_explicit_dereg_contact; - - *explicit_dereg_contact = (str*) shm_malloc(len_num_explicit_dereg_contact); - memset(*explicit_dereg_contact, 0, len_num_explicit_dereg_contact); - - char* ptr = (char*) (*explicit_dereg_contact + *num_explicit_dereg_contact); - - int count = 0; - //populate data - for (h = msg->contact; h; h = h->next) { - if (h->type == HDR_CONTACT_T && h->parsed) { - for (chi = ((contact_body_t*) h->parsed)->contacts; chi; chi = chi->next) { - LM_DBG("Adding [%.*s] to list of explicit contacts that have been de-reged\n", chi->uri.len, chi->uri.s); - (*explicit_dereg_contact)[count].s = ptr; - memcpy(ptr, chi->uri.s, chi->uri.len); - (*explicit_dereg_contact)[count].len = chi->uri.len; - ptr += chi->uri.len; - count++; - } - } - } - - if (ptr != ((char*) *explicit_dereg_contact + len_num_explicit_dereg_contact)) { - LM_CRIT("buffer overflow\n"); - return -1; - } - - return 1; +int store_explicit_dereg_contact(struct sip_msg *msg, + str **explicit_dereg_contact, int *num_explicit_dereg_contact) +{ + int bytes_needed_explicit_dereg_contact = 0; + int len_num_explicit_dereg_contact = 0; + struct hdr_field *h; + contact_t *chi; //contact header information + + LM_DBG("This is an explicit deregistration so we need to store the contact " + "URI to send out NOTIFY\n"); + + //get lengths + for(h = msg->contact; h; h = h->next) { + if(h->type == HDR_CONTACT_T && h->parsed) { + for(chi = ((contact_body_t *)h->parsed)->contacts; chi; + chi = chi->next) { + LM_DBG("URI [%.*s] len [%d]\n", chi->uri.len, chi->uri.s, + chi->uri.len); + (*num_explicit_dereg_contact)++; + bytes_needed_explicit_dereg_contact += chi->uri.len; + LM_DBG("URI [%.*s] and current bytes needed [%d]\n", + chi->uri.len, chi->uri.s, + bytes_needed_explicit_dereg_contact); + } + } + } + + LM_DBG("We have [%d] explicit contacts of total length [%d] to store\n", + (*num_explicit_dereg_contact), bytes_needed_explicit_dereg_contact); + + //now load data + + len_num_explicit_dereg_contact = + (sizeof(str) * (*num_explicit_dereg_contact)) + + bytes_needed_explicit_dereg_contact; + + *explicit_dereg_contact = (str *)shm_malloc(len_num_explicit_dereg_contact); + memset(*explicit_dereg_contact, 0, len_num_explicit_dereg_contact); + + char *ptr = (char *)(*explicit_dereg_contact + *num_explicit_dereg_contact); + + int count = 0; + //populate data + for(h = msg->contact; h; h = h->next) { + if(h->type == HDR_CONTACT_T && h->parsed) { + for(chi = ((contact_body_t *)h->parsed)->contacts; chi; + chi = chi->next) { + LM_DBG("Adding [%.*s] to list of explicit contacts that have " + "been de-reged\n", + chi->uri.len, chi->uri.s); + (*explicit_dereg_contact)[count].s = ptr; + memcpy(ptr, chi->uri.s, chi->uri.len); + (*explicit_dereg_contact)[count].len = chi->uri.len; + ptr += chi->uri.len; + count++; + } + } + } + + if(ptr + != ((char *)*explicit_dereg_contact + + len_num_explicit_dereg_contact)) { + LM_CRIT("buffer overflow\n"); + return -1; + } + + return 1; } /** @@ -765,508 +855,638 @@ int store_explicit_dereg_contact(struct sip_msg* msg, str ** explicit_dereg_cont * <=0 - on failure */ -int update_contacts(struct sip_msg* msg, udomain_t* _d, - str* public_identity, int assignment_type, ims_subscription** s, - str* ccf1, str* ccf2, str* ecf1, str* ecf2, contact_for_header_t** contact_header) { - int reg_state, i, j, k; - ims_public_identity* pi = 0; - impurecord_t* impu_rec, *tmp_impu_rec; - int expires_hdr = -1; //by default registration doesn't expire - struct hdr_field* h; - contact_t* chi; //contact header information - qvalue_t qvalue; - int sos = 0; - ims_subscription* subscription = 0; - int first_unbarred_impu = 1; //this is used to flag the IMPU as anchor for implicit set - int is_primary_impu = 0; - int ret = 1; +int update_contacts(struct sip_msg *msg, udomain_t *_d, str *public_identity, + int assignment_type, ims_subscription **s, str *ccf1, str *ccf2, + str *ecf1, str *ecf2, contact_for_header_t **contact_header) +{ + int reg_state, i, j, k; + ims_public_identity *pi = 0; + impurecord_t *impu_rec, *tmp_impu_rec; + int expires_hdr = -1; //by default registration doesn't expire + struct hdr_field *h; + contact_t *chi; //contact header information + qvalue_t qvalue; + int sos = 0; + ims_subscription *subscription = 0; + int first_unbarred_impu = + 1; //this is used to flag the IMPU as anchor for implicit set + int is_primary_impu = 0; + int ret = 1; str callid = {0, 0}; str path = {0, 0}; - ucontact_t* ucontact; - - int num_explicit_dereg_contact = 0; - str *explicit_dereg_contact = 0; - - if (msg) { - expires_hdr = cscf_get_expires_hdr(msg, 0); //get the expires from the main body of the sip message (global) - } - - switch (assignment_type) { - case AVP_IMS_SAR_REGISTRATION: - LM_DBG("updating contacts in REGISTRATION state\n"); - reg_state = IMS_USER_REGISTERED; - if (!s) { - LM_ERR("no userdata supplied for AVP_IMS_SAR_REGISTRATION\n"); - goto error; - } - - for (i = 0; i < (*s)->service_profiles_cnt; i++) { - for (j = 0; j < (*s)->service_profiles[i].public_identities_cnt; j++) { - pi = &((*s)->service_profiles[i].public_identities[j]); - ul.lock_udomain(_d, &pi->public_identity); - if (first_unbarred_impu && !pi->barring) { - is_primary_impu = 1; - first_unbarred_impu = 0; - } else { - is_primary_impu = 0; - } - if (ul.update_impurecord(_d, &pi->public_identity, 0, reg_state, -1 /*do not change send sar on delete */, - pi->barring, is_primary_impu, s, ccf1, ccf2, ecf1, ecf2, &impu_rec) != 0) { - LM_ERR("Unable to update impurecord for <%.*s>\n", pi->public_identity.len, pi->public_identity.s); - ul.unlock_udomain(_d, &pi->public_identity); - goto error; - } - //here we can do something with impu_rec if we want but we must unlock when done - //lets update the contacts - if (update_contacts_helper(msg, impu_rec, assignment_type, expires_hdr) != 0) { - LM_ERR("Failed trying to update contacts\n"); - ul.unlock_udomain(_d, &pi->public_identity); - goto error; - } - ul.unlock_udomain(_d, &pi->public_identity); - } - } - //if we were successful up to this point, then we need to copy the contacts from main impu record (asserted IMPU) into the register response - ul.lock_udomain(_d, public_identity); - if (ul.get_impurecord(_d, public_identity, &impu_rec) != 0) { - LM_ERR("Error, we should have a record after registration\n"); - ul.unlock_udomain(_d, public_identity); - goto error; - } - //now build the contact buffer to be include in the reply message and unlock - build_contact(impu_rec, contact_header, 0); - build_p_associated_uri(*s); - - - for (h = msg->contact; h; h = h->next) { - if (h->type == HDR_CONTACT_T && h->parsed) { - for (chi = ((contact_body_t*) h->parsed)->contacts; chi; chi = chi->next) { - if (ul.get_ucontact(&chi->uri, &callid, &path, 0, &ucontact) != 0) { - LM_DBG("Contact does not exist <%.*s>\n", chi->uri.len, chi->uri.s); + ucontact_t *ucontact; + + int num_explicit_dereg_contact = 0; + str *explicit_dereg_contact = 0; + + if(msg) { + expires_hdr = cscf_get_expires_hdr(msg, + 0); //get the expires from the main body of the sip message (global) + } + + switch(assignment_type) { + case AVP_IMS_SAR_REGISTRATION: + LM_DBG("updating contacts in REGISTRATION state\n"); + reg_state = IMS_USER_REGISTERED; + if(!s) { + LM_ERR("no userdata supplied for AVP_IMS_SAR_REGISTRATION\n"); + goto error; + } + + for(i = 0; i < (*s)->service_profiles_cnt; i++) { + for(j = 0; j < (*s)->service_profiles[i].public_identities_cnt; + j++) { + pi = &((*s)->service_profiles[i].public_identities[j]); + ul.lock_udomain(_d, &pi->public_identity); + if(first_unbarred_impu && !pi->barring) { + is_primary_impu = 1; + first_unbarred_impu = 0; + } else { + is_primary_impu = 0; + } + if(ul.update_impurecord(_d, &pi->public_identity, 0, + reg_state, + -1 /*do not change send sar on delete */, + pi->barring, is_primary_impu, s, ccf1, ccf2, + ecf1, ecf2, &impu_rec) + != 0) { + LM_ERR("Unable to update impurecord for <%.*s>\n", + pi->public_identity.len, pi->public_identity.s); + ul.unlock_udomain(_d, &pi->public_identity); + goto error; + } + //here we can do something with impu_rec if we want but we must unlock when done + //lets update the contacts + if(update_contacts_helper( + msg, impu_rec, assignment_type, expires_hdr) + != 0) { + LM_ERR("Failed trying to update contacts\n"); + ul.unlock_udomain(_d, &pi->public_identity); + goto error; + } + ul.unlock_udomain(_d, &pi->public_identity); + } + } + //if we were successful up to this point, then we need to copy the contacts from main impu record (asserted IMPU) into the register response + ul.lock_udomain(_d, public_identity); + if(ul.get_impurecord(_d, public_identity, &impu_rec) != 0) { + LM_ERR("Error, we should have a record after registration\n"); + ul.unlock_udomain(_d, public_identity); + goto error; + } + //now build the contact buffer to be include in the reply message and unlock + build_contact(impu_rec, contact_header, 0); + build_p_associated_uri(*s); + + + for(h = msg->contact; h; h = h->next) { + if(h->type == HDR_CONTACT_T && h->parsed) { + for(chi = ((contact_body_t *)h->parsed)->contacts; chi; + chi = chi->next) { + if(ul.get_ucontact( + &chi->uri, &callid, &path, 0, &ucontact) + != 0) { + LM_DBG("Contact does not exist <%.*s>\n", + chi->uri.len, chi->uri.s); goto error; } - event_reg(0, impu_rec, ucontact, IMS_REGISTRAR_CONTACT_REGISTERED, 0, 0, &chi->uri, 0, 0); + event_reg(0, impu_rec, ucontact, + IMS_REGISTRAR_CONTACT_REGISTERED, 0, 0, + &chi->uri, 0, 0); ul.release_ucontact(ucontact); - } - } - } + } + } + } - ul.unlock_udomain(_d, public_identity); - break; - case AVP_IMS_SAR_RE_REGISTRATION: - /* first update all the implicit IMPU based on the existing IMPUs subscription + ul.unlock_udomain(_d, public_identity); + break; + case AVP_IMS_SAR_RE_REGISTRATION: + /* first update all the implicit IMPU based on the existing IMPUs subscription * then, once done with the implicits, update the explicit with the new subscription data */ - LM_DBG("updating contacts in RE-REGISTRATION state\n"); - reg_state = IMS_USER_REGISTERED; - ul.lock_udomain(_d, public_identity); - if (ul.get_impurecord(_d, public_identity, &impu_rec) != 0) { - LM_ERR("No IMPU record fond for re-registration...aborting\n"); - ul.unlock_udomain(_d, public_identity); - goto error; - } - - if (update_contacts_helper(msg, impu_rec, assignment_type, expires_hdr) != 0) { //update the contacts for the explicit IMPU - LM_ERR("Failed trying to update contacts for re-registration\n"); - ul.unlock_udomain(_d, public_identity); - goto error; - } - //build the contact buffer for the exact registered contact for reply on explicit IMPU - build_contact(impu_rec, contact_header, skip_multiple_bindings_on_reg_resp == 1 ? msg : 0); - build_p_associated_uri(impu_rec->s); - - subscription = impu_rec->s; - if (!subscription) { - LM_ERR("No subscriber info associated with <%.*s>, not doing any implicit re-registrations\n", impu_rec->public_identity.len, impu_rec->public_identity.s); - //update the new subscription infor for the explicit IMPU - if (ul.update_impurecord(_d, public_identity, 0, reg_state, -1 /*do not change send sar on delete */, 0 /*this is explicit so barring must be 0*/, 0, s, ccf1, ccf2, - ecf1, ecf2, &impu_rec) != 0) { - LM_ERR("Unable to update explicit impurecord for <%.*s>\n", public_identity->len, public_identity->s); - } - build_contact(impu_rec, contact_header, skip_multiple_bindings_on_reg_resp == 1 ? msg : 0); - ul.unlock_udomain(_d, public_identity); - break; - } - - ul.lock_subscription(subscription); - subscription->ref_count++; - LM_DBG("ref count after add is now %d\n", subscription->ref_count); - ul.unlock_subscription(subscription); - ul.unlock_udomain(_d, public_identity); - - //now update the implicit set - for (i = 0; i < subscription->service_profiles_cnt; i++) { - for (j = 0; j < subscription->service_profiles[i].public_identities_cnt; j++) { - pi = &(subscription->service_profiles[i].public_identities[j]); - - if (memcmp(public_identity->s, pi->public_identity.s, public_identity->len) == 0) { //we don't need to update the explicit IMPU - LM_DBG("Ignoring explicit identity <%.*s>, updating later.....\n", public_identity->len, public_identity->s); - continue; - } - ul.lock_udomain(_d, &pi->public_identity); - - //update the implicit IMPU with the new data - if (ul.update_impurecord(_d, &pi->public_identity, 0, - reg_state, -1 /*do not change send sar on delete */, pi->barring, 0, s, ccf1, ccf2, ecf1, ecf2, - &impu_rec) != 0) { - LM_ERR("Unable to update implicit impurecord for <%.*s>.... continuing\n", pi->public_identity.len, pi->public_identity.s); - ul.unlock_udomain(_d, &pi->public_identity); - continue; - } - - //update the contacts for the explicit IMPU - if (update_contacts_helper(msg, impu_rec, assignment_type, expires_hdr) != 0) { - LM_ERR("Failed trying to update contacts for re-registration of implicit IMPU <%.*s>.......continuing\n", pi->public_identity.len, pi->public_identity.s); - ul.unlock_udomain(_d, &pi->public_identity); - continue; - } - ul.unlock_udomain(_d, &pi->public_identity); - } - } - ul.lock_subscription(subscription); - subscription->ref_count--; - LM_DBG("ref count after sub is now %d\n", subscription->ref_count); - ul.unlock_subscription(subscription); - - ul.lock_udomain(_d, public_identity); - //finally we update the explicit IMPU record with the new data - if (ul.update_impurecord(_d, public_identity, 0, reg_state, -1 /*do not change send sar on delete */, 0 /*this is explicit so barring must be 0*/, 0, s, ccf1, ccf2, ecf1, ecf2, &impu_rec) != 0) { - LM_ERR("Unable to update explicit impurecord for <%.*s>\n", public_identity->len, public_identity->s); - } - - for (h = msg->contact; h; h = h->next) { - if (h->type == HDR_CONTACT_T && h->parsed) { - for (chi = ((contact_body_t*) h->parsed)->contacts; chi; chi = chi->next) { - if (ul.get_ucontact(&chi->uri, &callid, &path, 0, &ucontact) != 0) { - LM_DBG("Contact does not exist <%.*s>\n", chi->uri.len, chi->uri.s); + LM_DBG("updating contacts in RE-REGISTRATION state\n"); + reg_state = IMS_USER_REGISTERED; + ul.lock_udomain(_d, public_identity); + if(ul.get_impurecord(_d, public_identity, &impu_rec) != 0) { + LM_ERR("No IMPU record fond for re-registration...aborting\n"); + ul.unlock_udomain(_d, public_identity); + goto error; + } + + if(update_contacts_helper( + msg, impu_rec, assignment_type, expires_hdr) + != 0) { //update the contacts for the explicit IMPU + LM_ERR("Failed trying to update contacts for " + "re-registration\n"); + ul.unlock_udomain(_d, public_identity); + goto error; + } + //build the contact buffer for the exact registered contact for reply on explicit IMPU + build_contact(impu_rec, contact_header, + skip_multiple_bindings_on_reg_resp == 1 ? msg : 0); + build_p_associated_uri(impu_rec->s); + + subscription = impu_rec->s; + if(!subscription) { + LM_ERR("No subscriber info associated with <%.*s>, not doing " + "any implicit re-registrations\n", + impu_rec->public_identity.len, + impu_rec->public_identity.s); + //update the new subscription infor for the explicit IMPU + if(ul.update_impurecord(_d, public_identity, 0, reg_state, + -1 /*do not change send sar on delete */, + 0 /*this is explicit so barring must be 0*/, 0, s, + ccf1, ccf2, ecf1, ecf2, &impu_rec) + != 0) { + LM_ERR("Unable to update explicit impurecord for <%.*s>\n", + public_identity->len, public_identity->s); + } + build_contact(impu_rec, contact_header, + skip_multiple_bindings_on_reg_resp == 1 ? msg : 0); + ul.unlock_udomain(_d, public_identity); + break; + } + + ul.lock_subscription(subscription); + subscription->ref_count++; + LM_DBG("ref count after add is now %d\n", subscription->ref_count); + ul.unlock_subscription(subscription); + ul.unlock_udomain(_d, public_identity); + + //now update the implicit set + for(i = 0; i < subscription->service_profiles_cnt; i++) { + for(j = 0; j < subscription->service_profiles[i] + .public_identities_cnt; + j++) { + pi = &(subscription->service_profiles[i] + .public_identities[j]); + + if(memcmp(public_identity->s, pi->public_identity.s, + public_identity->len) + == 0) { //we don't need to update the explicit IMPU + LM_DBG("Ignoring explicit identity <%.*s>, updating " + "later.....\n", + public_identity->len, public_identity->s); + continue; + } + ul.lock_udomain(_d, &pi->public_identity); + + //update the implicit IMPU with the new data + if(ul.update_impurecord(_d, &pi->public_identity, 0, + reg_state, + -1 /*do not change send sar on delete */, + pi->barring, 0, s, ccf1, ccf2, ecf1, ecf2, + &impu_rec) + != 0) { + LM_ERR("Unable to update implicit impurecord for " + "<%.*s>.... continuing\n", + pi->public_identity.len, pi->public_identity.s); + ul.unlock_udomain(_d, &pi->public_identity); + continue; + } + + //update the contacts for the explicit IMPU + if(update_contacts_helper( + msg, impu_rec, assignment_type, expires_hdr) + != 0) { + LM_ERR("Failed trying to update contacts for " + "re-registration of implicit IMPU " + "<%.*s>.......continuing\n", + pi->public_identity.len, pi->public_identity.s); + ul.unlock_udomain(_d, &pi->public_identity); + continue; + } + ul.unlock_udomain(_d, &pi->public_identity); + } + } + ul.lock_subscription(subscription); + subscription->ref_count--; + LM_DBG("ref count after sub is now %d\n", subscription->ref_count); + ul.unlock_subscription(subscription); + + ul.lock_udomain(_d, public_identity); + //finally we update the explicit IMPU record with the new data + if(ul.update_impurecord(_d, public_identity, 0, reg_state, + -1 /*do not change send sar on delete */, + 0 /*this is explicit so barring must be 0*/, 0, s, ccf1, + ccf2, ecf1, ecf2, &impu_rec) + != 0) { + LM_ERR("Unable to update explicit impurecord for <%.*s>\n", + public_identity->len, public_identity->s); + } + + for(h = msg->contact; h; h = h->next) { + if(h->type == HDR_CONTACT_T && h->parsed) { + for(chi = ((contact_body_t *)h->parsed)->contacts; chi; + chi = chi->next) { + if(ul.get_ucontact( + &chi->uri, &callid, &path, 0, &ucontact) + != 0) { + LM_DBG("Contact does not exist <%.*s>\n", + chi->uri.len, chi->uri.s); goto error; } - event_reg(0, impu_rec, ucontact, IMS_REGISTRAR_CONTACT_REFRESHED, 0, 0, &chi->uri, 0, 0); + event_reg(0, impu_rec, ucontact, + IMS_REGISTRAR_CONTACT_REFRESHED, 0, 0, + &chi->uri, 0, 0); ul.release_ucontact(ucontact); - } - } - } - - ul.unlock_udomain(_d, public_identity); - break; - case AVP_IMS_SAR_USER_DEREGISTRATION: - /*TODO: if it is not a star lets find all the contact records and remove them*/ - //first we update the state of the contact/s - for (h = msg->contact; h; h = h->next) { - if (h->type == HDR_CONTACT_T && h->parsed) { - for (chi = ((contact_body_t*) h->parsed)->contacts; chi; chi = chi->next) { - if (calc_contact_q(chi->q, &qvalue) != 0) { - LM_ERR("error on <%.*s>\n", chi->uri.len, chi->uri.s); - goto error; - } - sos = cscf_get_sos_uri_param(chi->uri); - if (sos < 0) { - LM_ERR("Error trying to determine if this is a sos contact <%.*s>\n", chi->uri.len, chi->uri.s); - goto error; - } - calc_contact_expires(chi, expires_hdr, sos); - if (unregister_contact(chi, CONTACT_DELETE_PENDING) != 0) { - LM_DBG("Unable to remove contact <%.*s\n", chi->uri.len, chi->uri.s); - - } - //add this contact to the successful unregistered in the 200OK so the PCSCF can also see what is de-registered - build_expired_contact(chi, contact_header); - } - } - } - - if (store_explicit_dereg_contact(msg, &explicit_dereg_contact, &num_explicit_dereg_contact) == -1) { - LM_ERR("Error trying to store explicit dereg contacts\n"); - goto error; - } - - for (k = 0; k < num_explicit_dereg_contact; k++) { - LM_DBG("Stored explicit contact to dereg: [%.*s]\n", (explicit_dereg_contact)[k].len, (explicit_dereg_contact)[k].s); - } - - //now, we get the subscription - ul.lock_udomain(_d, public_identity); - if (ul.get_impurecord(_d, public_identity, &impu_rec) != 0) { - LM_DBG("Error retrieving impu record on explicit de-reg nothing we can do from here on... aborting..\n"); - ul.unlock_udomain(_d, public_identity); - goto error; - } - int num_contacts = get_number_of_valid_contacts(impu_rec); - if (num_contacts > 0) { - LM_DBG("contacts still available\n"); - //TODO: add all other remaining contacts to reply message (contacts still registered for this IMPU) - ret = 1; - } else { - LM_DBG("no more contacts available\n"); - ret = 2; - } - ims_subscription* subscription = impu_rec->s; - - if (!subscription) { - LM_WARN("subscription is null..... continuing without de-registering implicit set\n"); - } else { - ul.lock_subscription(subscription); - subscription->ref_count++; //this is so we can de-reg the implicit set just now without holding the lock on the current IMPU - ul.unlock_subscription(subscription); - } - - ul.unlock_udomain(_d, public_identity); - - if (subscription) { - for (i = 0; i < subscription->service_profiles_cnt; i++) { - for (j = 0; j < subscription->service_profiles[i].public_identities_cnt; j++) { - pi = &(subscription->service_profiles[i].public_identities[j]); - // if (memcmp(public_identity->s, pi->public_identity.s, public_identity->len) == 0) { //we don't need to update the explicit IMPU - // LM_DBG("Ignoring explicit identity <%.*s>, already de-reg/updated\n", public_identity->len, public_identity->s); - // continue; - // } - ul.lock_udomain(_d, &pi->public_identity); - if (ul.get_impurecord(_d, &pi->public_identity, &tmp_impu_rec) != 0) { - LM_ERR("Can't find IMPU for implicit de-registration update....continuing\n"); - ul.unlock_udomain(_d, &pi->public_identity); - continue; - } - LM_DBG("Implicit deregistration of IMPU <%.*s>\n", pi->public_identity.len, pi->public_identity.s); - //TODO_LATEST: need to add back the following functionality - // if (!ue_unsubscribe_on_dereg) { - // subscriber = tmp_impu_rec->shead; - // LM_DBG("Checking if there is a subscription to this IMPU that has same watcher contact as this contact"); - // while (s) { - // - // LM_DBG("Subscription for this impurecord: watcher uri [%.*s] presentity uri [%.*s] watcher contact [%.*s] ", subscriber->watcher_uri.len, subscriber->watcher_uri.s, - // subscriber->presentity_uri.len, subscriber->presentity_uri.s, subscriber->watcher_contact.len, subscriber->watcher_contact.s); - // LM_DBG("Contact to be removed [%.*s] ", ucontact->c.len, ucontact->c.s); - // if (contact_port_ip_match(&subscriber->watcher_contact, &ucontact->c)) { - // //if ((s->watcher_contact.len == ucontact->c.len) && (strncasecmp(s->watcher_contact.s, ucontact->c.s, ucontact->c.len) == 0)) { - // LM_DBG("This contact has a subscription to its own status - so going to delete the subscription"); - // ul.external_delete_subscriber(subscriber, _d, 0 /*domain is locked*/); - // } - // s = s->next; - // } - // } - - for (h = msg->contact; h; h = h->next) { - if (h->type == HDR_CONTACT_T && h->parsed) { - for (chi = ((contact_body_t*) h->parsed)->contacts; chi; chi = chi->next) { - if (ul.get_ucontact(&chi->uri, &callid, &path, 0, &ucontact) != 0) { - LM_DBG("Contact does not exist <%.*s>\n", chi->uri.len, chi->uri.s); + } + } + } + + ul.unlock_udomain(_d, public_identity); + break; + case AVP_IMS_SAR_USER_DEREGISTRATION: + /*TODO: if it is not a star lets find all the contact records and remove them*/ + //first we update the state of the contact/s + for(h = msg->contact; h; h = h->next) { + if(h->type == HDR_CONTACT_T && h->parsed) { + for(chi = ((contact_body_t *)h->parsed)->contacts; chi; + chi = chi->next) { + if(calc_contact_q(chi->q, &qvalue) != 0) { + LM_ERR("error on <%.*s>\n", chi->uri.len, + chi->uri.s); + goto error; + } + sos = cscf_get_sos_uri_param(chi->uri); + if(sos < 0) { + LM_ERR("Error trying to determine if this is a sos " + "contact <%.*s>\n", + chi->uri.len, chi->uri.s); + goto error; + } + calc_contact_expires(chi, expires_hdr, sos); + if(unregister_contact(chi, CONTACT_DELETE_PENDING) + != 0) { + LM_DBG("Unable to remove contact <%.*s\n", + chi->uri.len, chi->uri.s); + } + //add this contact to the successful unregistered in the 200OK so the PCSCF can also see what is de-registered + build_expired_contact(chi, contact_header); + } + } + } + + if(store_explicit_dereg_contact(msg, &explicit_dereg_contact, + &num_explicit_dereg_contact) + == -1) { + LM_ERR("Error trying to store explicit dereg contacts\n"); + goto error; + } + + for(k = 0; k < num_explicit_dereg_contact; k++) { + LM_DBG("Stored explicit contact to dereg: [%.*s]\n", + (explicit_dereg_contact)[k].len, + (explicit_dereg_contact)[k].s); + } + + //now, we get the subscription + ul.lock_udomain(_d, public_identity); + if(ul.get_impurecord(_d, public_identity, &impu_rec) != 0) { + LM_DBG("Error retrieving impu record on explicit de-reg " + "nothing we can do from here on... aborting..\n"); + ul.unlock_udomain(_d, public_identity); + goto error; + } + int num_contacts = get_number_of_valid_contacts(impu_rec); + if(num_contacts > 0) { + LM_DBG("contacts still available\n"); + //TODO: add all other remaining contacts to reply message (contacts still registered for this IMPU) + ret = 1; + } else { + LM_DBG("no more contacts available\n"); + ret = 2; + } + ims_subscription *subscription = impu_rec->s; + + if(!subscription) { + LM_WARN("subscription is null..... continuing without " + "de-registering implicit set\n"); + } else { + ul.lock_subscription(subscription); + subscription + ->ref_count++; //this is so we can de-reg the implicit set just now without holding the lock on the current IMPU + ul.unlock_subscription(subscription); + } + + ul.unlock_udomain(_d, public_identity); + + if(subscription) { + for(i = 0; i < subscription->service_profiles_cnt; i++) { + for(j = 0; j < subscription->service_profiles[i] + .public_identities_cnt; + j++) { + pi = &(subscription->service_profiles[i] + .public_identities[j]); + // if (memcmp(public_identity->s, pi->public_identity.s, public_identity->len) == 0) { //we don't need to update the explicit IMPU + // LM_DBG("Ignoring explicit identity <%.*s>, already de-reg/updated\n", public_identity->len, public_identity->s); + // continue; + // } + ul.lock_udomain(_d, &pi->public_identity); + if(ul.get_impurecord( + _d, &pi->public_identity, &tmp_impu_rec) + != 0) { + LM_ERR("Can't find IMPU for implicit " + "de-registration update....continuing\n"); + ul.unlock_udomain(_d, &pi->public_identity); + continue; + } + LM_DBG("Implicit deregistration of IMPU <%.*s>\n", + pi->public_identity.len, pi->public_identity.s); + //TODO_LATEST: need to add back the following functionality + // if (!ue_unsubscribe_on_dereg) { + // subscriber = tmp_impu_rec->shead; + // LM_DBG("Checking if there is a subscription to this IMPU that has same watcher contact as this contact"); + // while (s) { + // + // LM_DBG("Subscription for this impurecord: watcher uri [%.*s] presentity uri [%.*s] watcher contact [%.*s] ", subscriber->watcher_uri.len, subscriber->watcher_uri.s, + // subscriber->presentity_uri.len, subscriber->presentity_uri.s, subscriber->watcher_contact.len, subscriber->watcher_contact.s); + // LM_DBG("Contact to be removed [%.*s] ", ucontact->c.len, ucontact->c.s); + // if (contact_port_ip_match(&subscriber->watcher_contact, &ucontact->c)) { + // //if ((s->watcher_contact.len == ucontact->c.len) && (strncasecmp(s->watcher_contact.s, ucontact->c.s, ucontact->c.len) == 0)) { + // LM_DBG("This contact has a subscription to its own status - so going to delete the subscription"); + // ul.external_delete_subscriber(subscriber, _d, 0 /*domain is locked*/); + // } + // s = s->next; + // } + // } + + for(h = msg->contact; h; h = h->next) { + if(h->type == HDR_CONTACT_T && h->parsed) { + for(chi = ((contact_body_t *)h->parsed) + ->contacts; + chi; chi = chi->next) { + if(ul.get_ucontact(&chi->uri, &callid, + &path, 0, &ucontact) + != 0) { + LM_DBG("Contact does not exist " + "<%.*s>\n", + chi->uri.len, chi->uri.s); goto error; } - notify_subscribers(tmp_impu_rec, ucontact, (str*) explicit_dereg_contact, num_explicit_dereg_contact, IMS_REGISTRAR_CONTACT_UNREGISTERED); + notify_subscribers(tmp_impu_rec, ucontact, + (str *)explicit_dereg_contact, + num_explicit_dereg_contact, + IMS_REGISTRAR_CONTACT_UNREGISTERED); ul.release_ucontact(ucontact); - if (calc_contact_q(chi->q, &qvalue) != 0) { - LM_ERR("error on <%.*s>\n", chi->uri.len, chi->uri.s); - ul.unlock_udomain(_d, &pi->public_identity); - LM_ERR("no q value of implicit de-reg....continuing\n"); - continue; - } - sos = cscf_get_sos_uri_param(chi->uri); - if (sos < 0) { - LM_ERR("Error trying to determine if this is a sos contact <%.*s>\n", chi->uri.len, chi->uri.s); - ul.unlock_udomain(_d, public_identity); - goto error; - } - calc_contact_expires(chi, expires_hdr, sos); - if (unregister_contact(chi, CONTACT_DELETED) != 0) { - LM_ERR("Unable to remove contact <%.*s>\n", chi->uri.len, chi->uri.s); - - } - } - } - } - /*now lets see if we still have any contacts left to decide on return value*/ - int num_valid_contacts = get_number_of_valid_contacts(tmp_impu_rec); - if (num_valid_contacts) - LM_DBG("contacts still available after implicit dereg for IMPU: <%.*s>\n", pi->public_identity.len, pi->public_identity.s); - else { - LM_DBG("no contacts left after implicit dereg for IMPU: <%.*s>\n", pi->public_identity.len, pi->public_identity.s); - LM_DBG("Updating impu record to not send SAR on delete as this is explicit dereg"); - reg_state = IMS_USER_REGISTERED; //keep reg_state as it is - if (ul.update_impurecord(_d, 0/*&pi->public_identity*/, tmp_impu_rec, reg_state, 0 /*do not send sar on delete */, -1 /*do not change barring*/, 0, 0, 0, 0, 0, 0, &tmp_impu_rec) != 0) { - LM_ERR("Unable to update explicit impurecord for <%.*s>\n", pi->public_identity.len, pi->public_identity.s); - } - } - - ul.unlock_udomain(_d, &pi->public_identity); - } - } - ul.lock_subscription(subscription); - subscription->ref_count--; - ul.unlock_subscription(subscription); - } - - //TODO: clean here too - maybe do earlier with the lock on the domain already held... - if (ret == 2) { - LM_DBG("no contacts left after explicit dereg for IMPU: <%.*s>\n", public_identity->len, public_identity->s); - LM_DBG("Updating impu record to not send SAR on delete as this is explicit dereg"); - reg_state = IMS_USER_REGISTERED; //keep reg_state as it is - ul.lock_udomain(_d, public_identity); - if (ul.update_impurecord(_d, public_identity, 0, reg_state, 0 /*do not send sar on delete */, -1 /*do not change barring*/, 0, 0, 0, 0, 0, 0, &tmp_impu_rec) != 0) { - LM_ERR("Unable to update explicit impurecord for <%.*s>\n", public_identity->len, public_identity->s); - } - ul.unlock_udomain(_d, public_identity); - } - break; - - case AVP_IMS_SAR_UNREGISTERED_USER: - LM_DBG("updating contacts for UNREGISTERED_USER state\n"); - reg_state = IMS_USER_UNREGISTERED; - for (i = 0; i < (*s)->service_profiles_cnt; i++) - for (j = 0; j < (*s)->service_profiles[i].public_identities_cnt; - j++) { - pi = &((*s)->service_profiles[i].public_identities[j]); - ul.lock_udomain(_d, &pi->public_identity); - if (ul.update_impurecord(_d, &pi->public_identity, 0, reg_state, -1 /*do not change send sar on delete */, - pi->barring, 0, s, ccf1, ccf2, ecf1, ecf2, &impu_rec) - != 0) { - LM_ERR("Unable to update impurecord for <%.*s>\n", pi->public_identity.len, pi->public_identity.s); - ul.unlock_udomain(_d, &pi->public_identity); - goto error; - } - ul.unlock_udomain(_d, &pi->public_identity); - } - //if we were successful up to this point, then we need to copy the contacts from main impu record (asserted IMPU) into the register response - break; - default: - LM_ERR("unimplemented assignment_type when trying to update contacts\n"); - } - - if (explicit_dereg_contact) { - shm_free(explicit_dereg_contact); - } - - - return ret; + if(calc_contact_q(chi->q, &qvalue) != 0) { + LM_ERR("error on <%.*s>\n", + chi->uri.len, chi->uri.s); + ul.unlock_udomain( + _d, &pi->public_identity); + LM_ERR("no q value of implicit " + "de-reg....continuing\n"); + continue; + } + sos = cscf_get_sos_uri_param(chi->uri); + if(sos < 0) { + LM_ERR("Error trying to determine if " + "this is a sos contact <%.*s>\n", + chi->uri.len, chi->uri.s); + ul.unlock_udomain(_d, public_identity); + goto error; + } + calc_contact_expires(chi, expires_hdr, sos); + if(unregister_contact(chi, CONTACT_DELETED) + != 0) { + LM_ERR("Unable to remove contact " + "<%.*s>\n", + chi->uri.len, chi->uri.s); + } + } + } + } + /*now lets see if we still have any contacts left to decide on return value*/ + int num_valid_contacts = + get_number_of_valid_contacts(tmp_impu_rec); + if(num_valid_contacts) + LM_DBG("contacts still available after implicit " + "dereg for IMPU: <%.*s>\n", + pi->public_identity.len, + pi->public_identity.s); + else { + LM_DBG("no contacts left after implicit dereg for " + "IMPU: <%.*s>\n", + pi->public_identity.len, + pi->public_identity.s); + LM_DBG("Updating impu record to not send SAR on " + "delete as this is explicit dereg"); + reg_state = + IMS_USER_REGISTERED; //keep reg_state as it is + if(ul.update_impurecord(_d, + 0 /*&pi->public_identity*/, tmp_impu_rec, + reg_state, + 0 /*do not send sar on delete */, + -1 /*do not change barring*/, 0, 0, 0, 0, + 0, 0, &tmp_impu_rec) + != 0) { + LM_ERR("Unable to update explicit impurecord " + "for <%.*s>\n", + pi->public_identity.len, + pi->public_identity.s); + } + } -error: - return -1; + ul.unlock_udomain(_d, &pi->public_identity); + } + } + ul.lock_subscription(subscription); + subscription->ref_count--; + ul.unlock_subscription(subscription); + } + + //TODO: clean here too - maybe do earlier with the lock on the domain already held... + if(ret == 2) { + LM_DBG("no contacts left after explicit dereg for IMPU: " + "<%.*s>\n", + public_identity->len, public_identity->s); + LM_DBG("Updating impu record to not send SAR on delete as this " + "is explicit dereg"); + reg_state = IMS_USER_REGISTERED; //keep reg_state as it is + ul.lock_udomain(_d, public_identity); + if(ul.update_impurecord(_d, public_identity, 0, reg_state, + 0 /*do not send sar on delete */, + -1 /*do not change barring*/, 0, 0, 0, 0, 0, 0, + &tmp_impu_rec) + != 0) { + LM_ERR("Unable to update explicit impurecord for <%.*s>\n", + public_identity->len, public_identity->s); + } + ul.unlock_udomain(_d, public_identity); + } + break; + + case AVP_IMS_SAR_UNREGISTERED_USER: + LM_DBG("updating contacts for UNREGISTERED_USER state\n"); + reg_state = IMS_USER_UNREGISTERED; + for(i = 0; i < (*s)->service_profiles_cnt; i++) + for(j = 0; j < (*s)->service_profiles[i].public_identities_cnt; + j++) { + pi = &((*s)->service_profiles[i].public_identities[j]); + ul.lock_udomain(_d, &pi->public_identity); + if(ul.update_impurecord(_d, &pi->public_identity, 0, + reg_state, + -1 /*do not change send sar on delete */, + pi->barring, 0, s, ccf1, ccf2, ecf1, ecf2, + &impu_rec) + != 0) { + LM_ERR("Unable to update impurecord for <%.*s>\n", + pi->public_identity.len, pi->public_identity.s); + ul.unlock_udomain(_d, &pi->public_identity); + goto error; + } + ul.unlock_udomain(_d, &pi->public_identity); + } + //if we were successful up to this point, then we need to copy the contacts from main impu record (asserted IMPU) into the register response + break; + default: + LM_ERR("unimplemented assignment_type when trying to update " + "contacts\n"); + } -} + if(explicit_dereg_contact) { + shm_free(explicit_dereg_contact); + } -int assign_server_unreg(struct sip_msg* _m, char* str1, str* direction, char* route) { - str private_identity = {0, 0}, public_identity = {0, 0}; - int assignment_type = AVP_IMS_SAR_NO_ASSIGNMENT; - int data_available = AVP_IMS_SAR_USER_DATA_NOT_AVAILABLE; - int require_user_data = 1; - rerrno = R_FINE; - tm_cell_t *t = 0; - str route_name; - - saved_transaction_t* saved_t; - cfg_action_t* cfg_action; - - udomain_t* _d = (udomain_t*) str1; - - if (fixup_get_svalue(_m, (gparam_t*) route, &route_name) != 0) { - LM_ERR("no async route block for assign_server_unreg\n"); - return -1; - } - - LM_DBG("Looking for route block [%.*s]\n", route_name.len, route_name.s); - int ri = route_get(&main_rt, route_name.s); - if (ri < 0) { - LM_ERR("unable to find route block [%.*s]\n", route_name.len, route_name.s); - return -1; - } - cfg_action = main_rt.rlist[ri]; - if (cfg_action == NULL) { - LM_ERR("empty action lists in route block [%.*s]\n", route_name.len, route_name.s); - return -1; - } - - LM_DBG("Assigning unregistered user for direction [%.*s]\n", direction->len, direction->s); - - enum cscf_dialog_direction dir = cscf_get_dialog_direction(direction->s); - switch (dir) { - case CSCF_MOBILE_ORIGINATING: - public_identity = cscf_get_asserted_identity(_m, 0); - break; - case CSCF_MOBILE_TERMINATING: - public_identity = cscf_get_public_identity_from_requri(_m); - break; - default: - LM_ERR("Bad dialog direction [%.*s]\n", direction->len, direction->s); - rerrno = R_SAR_FAILED; - goto error; - } - - if (!public_identity.s || public_identity.len <= 0) { - LM_ERR("No public identity\n"); - rerrno = R_SAR_FAILED; - goto error; - } - - assignment_type = AVP_IMS_SAR_UNREGISTERED_USER; - data_available = AVP_IMS_SAR_USER_DATA_NOT_AVAILABLE; //TODO: check this - - - //before we send lets suspend the transaction - t = tmb.t_gett(); - if (t == NULL || t == T_UNDEFINED) { - if (tmb.t_newtran(_m) < 0) { - LM_ERR("cannot create the transaction for SAR async\n"); - rerrno = R_SAR_FAILED; - goto error; - } - t = tmb.t_gett(); - if (t == NULL || t == T_UNDEFINED) { - LM_ERR("cannot lookup the transaction\n"); - rerrno = R_SAR_FAILED; - goto error; - } - } - - saved_t = shm_malloc(sizeof (saved_transaction_t)); - if (!saved_t) { - LM_ERR("no more memory trying to save transaction state\n"); - rerrno = R_SAR_FAILED; - goto error; - - } - memset(saved_t, 0, sizeof (saved_transaction_t)); - saved_t->act = cfg_action; - - saved_t->expires = 1; //not a dereg as this is server_assign_unreg - saved_t->require_user_data = require_user_data; - saved_t->sar_assignment_type = assignment_type; - saved_t->domain = (udomain_t*) _d; - - saved_t->contact_header = 0; - - LM_DBG("Setting default AVP return code used for async callbacks to default as ERROR \n"); - create_return_code(CSCF_RETURN_ERROR); - - LM_DBG("Suspending SIP TM transaction\n"); - if (tmb.t_suspend(_m, &saved_t->tindex, &saved_t->tlabel) != 0) { - LM_ERR("failed to suspend the TM processing\n"); - free_saved_transaction_data(saved_t); - rerrno = R_SAR_FAILED; - goto error; - } - - if (scscf_assign_server(_m, public_identity, private_identity, assignment_type, data_available, saved_t) != 0) { - LM_ERR("ERR:I_MAR: Error sending SAR or SAR time-out\n"); - tmb.t_cancel_suspend(saved_t->tindex, saved_t->tlabel); - free_saved_transaction_data(saved_t); - rerrno = R_SAR_FAILED; - goto error; - } - - if (public_identity.s && dir == CSCF_MOBILE_TERMINATING) - shm_free(public_identity.s); // shm_malloc in cscf_get_public_identity_from_requri - - return CSCF_RETURN_BREAK; + return ret; error: - update_stat(rejected_registrations, 1); - if ((is_route_type(REQUEST_ROUTE)) && (reg_send_reply(_m, 0) < 0)) - return CSCF_RETURN_ERROR; - return CSCF_RETURN_BREAK; + return -1; +} +int assign_server_unreg( + struct sip_msg *_m, char *str1, str *direction, char *route) +{ + str private_identity = {0, 0}, public_identity = {0, 0}; + int assignment_type = AVP_IMS_SAR_NO_ASSIGNMENT; + int data_available = AVP_IMS_SAR_USER_DATA_NOT_AVAILABLE; + int require_user_data = 1; + rerrno = R_FINE; + tm_cell_t *t = 0; + str route_name; + + saved_transaction_t *saved_t; + cfg_action_t *cfg_action; + + udomain_t *_d = (udomain_t *)str1; + + if(fixup_get_svalue(_m, (gparam_t *)route, &route_name) != 0) { + LM_ERR("no async route block for assign_server_unreg\n"); + return -1; + } + + LM_DBG("Looking for route block [%.*s]\n", route_name.len, route_name.s); + int ri = route_get(&main_rt, route_name.s); + if(ri < 0) { + LM_ERR("unable to find route block [%.*s]\n", route_name.len, + route_name.s); + return -1; + } + cfg_action = main_rt.rlist[ri]; + if(cfg_action == NULL) { + LM_ERR("empty action lists in route block [%.*s]\n", route_name.len, + route_name.s); + return -1; + } + + LM_DBG("Assigning unregistered user for direction [%.*s]\n", direction->len, + direction->s); + + enum cscf_dialog_direction dir = cscf_get_dialog_direction(direction->s); + switch(dir) { + case CSCF_MOBILE_ORIGINATING: + public_identity = cscf_get_asserted_identity(_m, 0); + break; + case CSCF_MOBILE_TERMINATING: + public_identity = cscf_get_public_identity_from_requri(_m); + break; + default: + LM_ERR("Bad dialog direction [%.*s]\n", direction->len, + direction->s); + rerrno = R_SAR_FAILED; + goto error; + } + + if(!public_identity.s || public_identity.len <= 0) { + LM_ERR("No public identity\n"); + rerrno = R_SAR_FAILED; + goto error; + } + + assignment_type = AVP_IMS_SAR_UNREGISTERED_USER; + data_available = AVP_IMS_SAR_USER_DATA_NOT_AVAILABLE; //TODO: check this + + + //before we send lets suspend the transaction + t = tmb.t_gett(); + if(t == NULL || t == T_UNDEFINED) { + if(tmb.t_newtran(_m) < 0) { + LM_ERR("cannot create the transaction for SAR async\n"); + rerrno = R_SAR_FAILED; + goto error; + } + t = tmb.t_gett(); + if(t == NULL || t == T_UNDEFINED) { + LM_ERR("cannot lookup the transaction\n"); + rerrno = R_SAR_FAILED; + goto error; + } + } + + saved_t = shm_malloc(sizeof(saved_transaction_t)); + if(!saved_t) { + LM_ERR("no more memory trying to save transaction state\n"); + rerrno = R_SAR_FAILED; + goto error; + } + memset(saved_t, 0, sizeof(saved_transaction_t)); + saved_t->act = cfg_action; + + saved_t->expires = 1; //not a dereg as this is server_assign_unreg + saved_t->require_user_data = require_user_data; + saved_t->sar_assignment_type = assignment_type; + saved_t->domain = (udomain_t *)_d; + + saved_t->contact_header = 0; + + LM_DBG("Setting default AVP return code used for async callbacks to " + "default as ERROR \n"); + create_return_code(CSCF_RETURN_ERROR); + + LM_DBG("Suspending SIP TM transaction\n"); + if(tmb.t_suspend(_m, &saved_t->tindex, &saved_t->tlabel) != 0) { + LM_ERR("failed to suspend the TM processing\n"); + free_saved_transaction_data(saved_t); + rerrno = R_SAR_FAILED; + goto error; + } + + if(scscf_assign_server(_m, public_identity, private_identity, + assignment_type, data_available, saved_t) + != 0) { + LM_ERR("ERR:I_MAR: Error sending SAR or SAR time-out\n"); + tmb.t_cancel_suspend(saved_t->tindex, saved_t->tlabel); + free_saved_transaction_data(saved_t); + rerrno = R_SAR_FAILED; + goto error; + } + + if(public_identity.s && dir == CSCF_MOBILE_TERMINATING) + shm_free( + public_identity + .s); // shm_malloc in cscf_get_public_identity_from_requri + + return CSCF_RETURN_BREAK; + +error: + update_stat(rejected_registrations, 1); + if((is_route_type(REQUEST_ROUTE)) && (reg_send_reply(_m, 0) < 0)) + return CSCF_RETURN_ERROR; + return CSCF_RETURN_BREAK; } /*!\brief @@ -1279,254 +1499,270 @@ int assign_server_unreg(struct sip_msg* _m, char* str1, str* direction, char* ro */ //int save(struct sip_msg* msg, udomain_t* _d) { -int save(struct sip_msg* msg, char* str1, char *route, int _cflags) { - int expires; - int require_user_data = 0; - int data_available; - contact_t* c; - int st; - str public_identity, private_identity, realm={0,0}; - int sar_assignment_type = AVP_IMS_SAR_NO_ASSIGNMENT; - str route_name; - - udomain_t* _d = (udomain_t*) str1; - - rerrno = R_FINE; - get_act_time(); - - tm_cell_t *t = 0; - - saved_transaction_t* saved_t; - cfg_action_t* cfg_action; - - contact_for_header_t* contact_header = 0; - - if (fixup_get_svalue(msg, (gparam_t*) route, &route_name) != 0) { - LM_ERR("no async route block for assign_server_unreg\n"); - return -1; - } - - LM_DBG("Looking for route block [%.*s]\n", route_name.len, route_name.s); - int ri = route_get(&main_rt, route_name.s); - if (ri < 0) { - LM_ERR("unable to find route block [%.*s]\n", route_name.len, route_name.s); - return -1; - } - cfg_action = main_rt.rlist[ri]; - if (cfg_action == NULL) { - LM_ERR("empty action lists in route block [%.*s]\n", route_name.len, route_name.s); - return -1; - } - - //check which route block we are in - if not request then we fail out. - if (!is_route_type(REQUEST_ROUTE)) { - LM_ERR("Should only be called in REQUEST route\n"); - rerrno = R_SAR_FAILED; - goto error; - } - - /* check and see that all the required headers are available and can be parsed */ - if (parse_message_for_register(msg) < 0) { - LM_ERR("Unable to parse register message correctly\n"); - rerrno = R_SAR_FAILED; - goto error; - } - /** check we have valid contacts according to IMS spec. */ - if (check_contacts(msg, &st) > 0) { - LM_ERR("contacts not valid for REGISTER\n"); - rerrno = R_SAR_FAILED; - goto error; - } - - /* get IMPU,IMPI,realm,expires */ - public_identity = cscf_get_public_identity(msg); - if (public_identity.len <= 0 || !public_identity.s) { - LM_ERR("failed to extract Address Of Record\n"); - rerrno = R_SAR_FAILED; - goto error; - } - - if (!(_cflags & DO_NOT_USE_REALM_FOR_PRIVATE_IDENTITY)) { - realm = cscf_get_realm_from_uri(public_identity); - if (realm.len <= 0 || !realm.s) { - LM_ERR("can't get realm\n"); - rerrno = R_SAR_FAILED; - goto error; - } - } - - private_identity = cscf_get_private_identity(msg, realm); - if (private_identity.len <= 0 || !private_identity.s) { - LM_ERR("cant get private identity\n"); - } - - expires = cscf_get_max_expires(msg, 0); //check all contacts for max expires - if (expires != 0) { //if <0 then no expires was found in which case we treat as reg/re-reg with default expires. - if (is_impu_registered(_d, &public_identity)) { - LM_DBG("preparing for SAR assignment for RE-REGISTRATION <%.*s>\n", public_identity.len, public_identity.s); - sar_assignment_type = AVP_IMS_SAR_RE_REGISTRATION; - } else { - LM_DBG("preparing for SAR assignment for new REGISTRATION <%.*s>\n", public_identity.len, public_identity.s); - sar_assignment_type = AVP_IMS_SAR_REGISTRATION; - require_user_data = 1; - } - } else {//de-reg - if (store_data_on_dereg) { - LM_DBG("preparing for SAR assignment for DE-REGISTRATION with storage <%.*s>\n", public_identity.len, public_identity.s); - sar_assignment_type = AVP_IMS_SAR_USER_DEREGISTRATION_STORE_SERVER_NAME; - } else { - LM_DBG("preparing for SAR assignment for DE-REGISTRATION <%.*s>\n", public_identity.len, public_identity.s); - sar_assignment_type = AVP_IMS_SAR_USER_DEREGISTRATION; - } - - c = get_first_contact(msg); - if (!c && !st) { //no contacts found - no need to do anything - LM_ERR("no contacts found for de-registration and no star\n"); - rerrno = R_SAR_FAILED; - goto error; - } - - //if we get here there are contacts to deregister, BUT we only send a SAR if there are no contacts (valid) left. - if (!st) { //if it is a star then we delete all contacts and send a SAR - //unregister the requested contacts, if none left at the end then send a SAR, otherwise return successfully - LM_DBG("need to unregister contacts\n"); - //lets update the contacts - we need to know if all were deleted or not for the public identity - int res = update_contacts(msg, _d, &public_identity, sar_assignment_type, 0, 0, 0, 0, 0, &contact_header); - if (res <= 0) { - LM_DBG("Error processing REGISTER for de-registration\n"); - free_contact_buf(contact_header); - rerrno = R_SAR_FAILED; - goto error; - } else if (res == 2) { - //send sar - LM_DBG("no contacts left after explicit de-registration, doing SAR\n"); - } else { //res=1 - //still contacts left so return success - LM_DBG("contacts still available after deregister.... not doing SAR\n"); - //we must send the de reged contacts in this! so we only free the contact header after sending - //free_contact_buf(contact_header); - rerrno = R_FINE; - goto no_sar; - } - } - } - - if (!user_data_always) { - if (require_user_data) - data_available = AVP_IMS_SAR_USER_DATA_NOT_AVAILABLE; - else - data_available = AVP_IMS_SAR_USER_DATA_ALREADY_AVAILABLE; - } else { - data_available = AVP_IMS_SAR_USER_DATA_NOT_AVAILABLE; - } - - //before we send lets suspend the transaction - t = tmb.t_gett(); - if (t == NULL || t == T_UNDEFINED) { - if (tmb.t_newtran(msg) < 0) { - LM_ERR("cannot create the transaction for SAR async\n"); - rerrno = R_SAR_FAILED; - goto error; - } - t = tmb.t_gett(); - if (t == NULL || t == T_UNDEFINED) { - LM_ERR("cannot lookup the transaction\n"); - rerrno = R_SAR_FAILED; - goto error; - } - } - - saved_t = shm_malloc(sizeof (saved_transaction_t)); - if (!saved_t) { - LM_ERR("no more memory trying to save transaction state\n"); - free_contact_buf(contact_header); - rerrno = R_SAR_FAILED; - goto error; - - } - memset(saved_t, 0, sizeof (saved_transaction_t)); - saved_t->act = cfg_action; - - //this is not server assign unreg - this is a save - saved_t->expires = expires; - saved_t->require_user_data = require_user_data; - saved_t->sar_assignment_type = sar_assignment_type; - - saved_t->domain = _d; - - saved_t->public_identity.s = (char*) shm_malloc(public_identity.len + 1); - if (!saved_t->public_identity.s) { - LM_ERR("no more memory trying to save transaction state : callid\n"); - shm_free(saved_t); - free_contact_buf(contact_header); - rerrno = R_SAR_FAILED; - goto error; - } - memset(saved_t->public_identity.s, 0, public_identity.len + 1); - memcpy(saved_t->public_identity.s, public_identity.s, public_identity.len); - saved_t->public_identity.len = public_identity.len; - - saved_t->contact_header = contact_header; - - create_return_code(CSCF_RETURN_ERROR); - - LM_DBG("Suspending SIP TM transaction with index [%d] and label [%d]\n", saved_t->tindex, saved_t->tlabel); - if (tmb.t_suspend(msg, &saved_t->tindex, &saved_t->tlabel) != 0) { - LM_ERR("failed to suspend the TM processing\n"); - free_saved_transaction_data(saved_t); - rerrno = R_SAR_FAILED; - goto error; - } - - if (scscf_assign_server(msg, public_identity, private_identity, sar_assignment_type, data_available, saved_t) != 0) { - LM_ERR("ERR:I_MAR: Error sending SAR or SAR time-out\n"); - tmb.t_cancel_suspend(saved_t->tindex, saved_t->tlabel); - free_saved_transaction_data(saved_t); - rerrno = R_SAR_FAILED; - goto error; - } - - return CSCF_RETURN_BREAK; +int save(struct sip_msg *msg, char *str1, char *route, int _cflags) +{ + int expires; + int require_user_data = 0; + int data_available; + contact_t *c; + int st; + str public_identity, private_identity, realm = {0, 0}; + int sar_assignment_type = AVP_IMS_SAR_NO_ASSIGNMENT; + str route_name; + + udomain_t *_d = (udomain_t *)str1; + + rerrno = R_FINE; + get_act_time(); + + tm_cell_t *t = 0; + + saved_transaction_t *saved_t; + cfg_action_t *cfg_action; + + contact_for_header_t *contact_header = 0; + + if(fixup_get_svalue(msg, (gparam_t *)route, &route_name) != 0) { + LM_ERR("no async route block for assign_server_unreg\n"); + return -1; + } + + LM_DBG("Looking for route block [%.*s]\n", route_name.len, route_name.s); + int ri = route_get(&main_rt, route_name.s); + if(ri < 0) { + LM_ERR("unable to find route block [%.*s]\n", route_name.len, + route_name.s); + return -1; + } + cfg_action = main_rt.rlist[ri]; + if(cfg_action == NULL) { + LM_ERR("empty action lists in route block [%.*s]\n", route_name.len, + route_name.s); + return -1; + } + + //check which route block we are in - if not request then we fail out. + if(!is_route_type(REQUEST_ROUTE)) { + LM_ERR("Should only be called in REQUEST route\n"); + rerrno = R_SAR_FAILED; + goto error; + } + + /* check and see that all the required headers are available and can be parsed */ + if(parse_message_for_register(msg) < 0) { + LM_ERR("Unable to parse register message correctly\n"); + rerrno = R_SAR_FAILED; + goto error; + } + /** check we have valid contacts according to IMS spec. */ + if(check_contacts(msg, &st) > 0) { + LM_ERR("contacts not valid for REGISTER\n"); + rerrno = R_SAR_FAILED; + goto error; + } + + /* get IMPU,IMPI,realm,expires */ + public_identity = cscf_get_public_identity(msg); + if(public_identity.len <= 0 || !public_identity.s) { + LM_ERR("failed to extract Address Of Record\n"); + rerrno = R_SAR_FAILED; + goto error; + } + + if(!(_cflags & DO_NOT_USE_REALM_FOR_PRIVATE_IDENTITY)) { + realm = cscf_get_realm_from_uri(public_identity); + if(realm.len <= 0 || !realm.s) { + LM_ERR("can't get realm\n"); + rerrno = R_SAR_FAILED; + goto error; + } + } + + private_identity = cscf_get_private_identity(msg, realm); + if(private_identity.len <= 0 || !private_identity.s) { + LM_ERR("cant get private identity\n"); + } + + expires = cscf_get_max_expires(msg, 0); //check all contacts for max expires + if(expires + != 0) { //if <0 then no expires was found in which case we treat as reg/re-reg with default expires. + if(is_impu_registered(_d, &public_identity)) { + LM_DBG("preparing for SAR assignment for RE-REGISTRATION <%.*s>\n", + public_identity.len, public_identity.s); + sar_assignment_type = AVP_IMS_SAR_RE_REGISTRATION; + } else { + LM_DBG("preparing for SAR assignment for new REGISTRATION <%.*s>\n", + public_identity.len, public_identity.s); + sar_assignment_type = AVP_IMS_SAR_REGISTRATION; + require_user_data = 1; + } + } else { //de-reg + if(store_data_on_dereg) { + LM_DBG("preparing for SAR assignment for DE-REGISTRATION with " + "storage <%.*s>\n", + public_identity.len, public_identity.s); + sar_assignment_type = + AVP_IMS_SAR_USER_DEREGISTRATION_STORE_SERVER_NAME; + } else { + LM_DBG("preparing for SAR assignment for DE-REGISTRATION <%.*s>\n", + public_identity.len, public_identity.s); + sar_assignment_type = AVP_IMS_SAR_USER_DEREGISTRATION; + } + + c = get_first_contact(msg); + if(!c && !st) { //no contacts found - no need to do anything + LM_ERR("no contacts found for de-registration and no star\n"); + rerrno = R_SAR_FAILED; + goto error; + } + + //if we get here there are contacts to deregister, BUT we only send a SAR if there are no contacts (valid) left. + if(!st) { //if it is a star then we delete all contacts and send a SAR + //unregister the requested contacts, if none left at the end then send a SAR, otherwise return successfully + LM_DBG("need to unregister contacts\n"); + //lets update the contacts - we need to know if all were deleted or not for the public identity + int res = update_contacts(msg, _d, &public_identity, + sar_assignment_type, 0, 0, 0, 0, 0, &contact_header); + if(res <= 0) { + LM_DBG("Error processing REGISTER for de-registration\n"); + free_contact_buf(contact_header); + rerrno = R_SAR_FAILED; + goto error; + } else if(res == 2) { + //send sar + LM_DBG("no contacts left after explicit de-registration, doing " + "SAR\n"); + } else { //res=1 + //still contacts left so return success + LM_DBG("contacts still available after deregister.... not " + "doing SAR\n"); + //we must send the de reged contacts in this! so we only free the contact header after sending + //free_contact_buf(contact_header); + rerrno = R_FINE; + goto no_sar; + } + } + } + + if(!user_data_always) { + if(require_user_data) + data_available = AVP_IMS_SAR_USER_DATA_NOT_AVAILABLE; + else + data_available = AVP_IMS_SAR_USER_DATA_ALREADY_AVAILABLE; + } else { + data_available = AVP_IMS_SAR_USER_DATA_NOT_AVAILABLE; + } + + //before we send lets suspend the transaction + t = tmb.t_gett(); + if(t == NULL || t == T_UNDEFINED) { + if(tmb.t_newtran(msg) < 0) { + LM_ERR("cannot create the transaction for SAR async\n"); + rerrno = R_SAR_FAILED; + goto error; + } + t = tmb.t_gett(); + if(t == NULL || t == T_UNDEFINED) { + LM_ERR("cannot lookup the transaction\n"); + rerrno = R_SAR_FAILED; + goto error; + } + } + + saved_t = shm_malloc(sizeof(saved_transaction_t)); + if(!saved_t) { + LM_ERR("no more memory trying to save transaction state\n"); + free_contact_buf(contact_header); + rerrno = R_SAR_FAILED; + goto error; + } + memset(saved_t, 0, sizeof(saved_transaction_t)); + saved_t->act = cfg_action; + + //this is not server assign unreg - this is a save + saved_t->expires = expires; + saved_t->require_user_data = require_user_data; + saved_t->sar_assignment_type = sar_assignment_type; + + saved_t->domain = _d; + + saved_t->public_identity.s = (char *)shm_malloc(public_identity.len + 1); + if(!saved_t->public_identity.s) { + LM_ERR("no more memory trying to save transaction state : callid\n"); + shm_free(saved_t); + free_contact_buf(contact_header); + rerrno = R_SAR_FAILED; + goto error; + } + memset(saved_t->public_identity.s, 0, public_identity.len + 1); + memcpy(saved_t->public_identity.s, public_identity.s, public_identity.len); + saved_t->public_identity.len = public_identity.len; + + saved_t->contact_header = contact_header; + + create_return_code(CSCF_RETURN_ERROR); + + LM_DBG("Suspending SIP TM transaction with index [%d] and label [%d]\n", + saved_t->tindex, saved_t->tlabel); + if(tmb.t_suspend(msg, &saved_t->tindex, &saved_t->tlabel) != 0) { + LM_ERR("failed to suspend the TM processing\n"); + free_saved_transaction_data(saved_t); + rerrno = R_SAR_FAILED; + goto error; + } + + if(scscf_assign_server(msg, public_identity, private_identity, + sar_assignment_type, data_available, saved_t) + != 0) { + LM_ERR("ERR:I_MAR: Error sending SAR or SAR time-out\n"); + tmb.t_cancel_suspend(saved_t->tindex, saved_t->tlabel); + free_saved_transaction_data(saved_t); + rerrno = R_SAR_FAILED; + goto error; + } + + return CSCF_RETURN_BREAK; no_sar: - update_stat(accepted_registrations, 1); + update_stat(accepted_registrations, 1); - //we must send the de reged contacts in this! so we only free the contact header after sending - /* Only send reply upon request, not upon reply */ - if ((is_route_type(REQUEST_ROUTE)) && (reg_send_reply(msg, contact_header) < 0)) { - free_contact_buf(contact_header); - return CSCF_RETURN_ERROR; - } - free_contact_buf(contact_header); - return CSCF_RETURN_BREAK; + //we must send the de reged contacts in this! so we only free the contact header after sending + /* Only send reply upon request, not upon reply */ + if((is_route_type(REQUEST_ROUTE)) + && (reg_send_reply(msg, contact_header) < 0)) { + free_contact_buf(contact_header); + return CSCF_RETURN_ERROR; + } + free_contact_buf(contact_header); + return CSCF_RETURN_BREAK; error: - update_stat(rejected_registrations, 1); - if ((is_route_type(REQUEST_ROUTE)) && (reg_send_reply(msg, contact_header) < 0)) - return CSCF_RETURN_ERROR; - return CSCF_RETURN_BREAK; - + update_stat(rejected_registrations, 1); + if((is_route_type(REQUEST_ROUTE)) + && (reg_send_reply(msg, contact_header) < 0)) + return CSCF_RETURN_ERROR; + return CSCF_RETURN_BREAK; } -int unregister(struct sip_msg* _m, char* _d, char* _uri) { - str aor = {0, 0}; - str uri = {0, 0}; - - if (fixup_get_svalue(_m, (gparam_p) _uri, &uri) != 0 || uri.len <= 0) { - LM_ERR("invalid uri parameter\n"); - return -1; - } - - if (extract_aor(&uri, &aor) < 0) { - LM_ERR("failed to extract Address Of Record\n"); - return -1; - } - - if (star((udomain_t*) _d, &aor) < 0) { - LM_ERR("error unregistering user [%.*s]\n", aor.len, aor.s); - return -1; - } - return 1; -} +int unregister(struct sip_msg *_m, char *_d, char *_uri) +{ + str aor = {0, 0}; + str uri = {0, 0}; + + if(fixup_get_svalue(_m, (gparam_p)_uri, &uri) != 0 || uri.len <= 0) { + LM_ERR("invalid uri parameter\n"); + return -1; + } + if(extract_aor(&uri, &aor) < 0) { + LM_ERR("failed to extract Address Of Record\n"); + return -1; + } + + if(star((udomain_t *)_d, &aor) < 0) { + LM_ERR("error unregistering user [%.*s]\n", aor.len, aor.s); + return -1; + } + return 1; +} diff --git a/src/modules/ims_registrar_scscf/save.h b/src/modules/ims_registrar_scscf/save.h index 19b5dd560cf..688e1433732 100644 --- a/src/modules/ims_registrar_scscf/save.h +++ b/src/modules/ims_registrar_scscf/save.h @@ -41,7 +41,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * - */ + */ #ifndef SAVE_H @@ -56,14 +56,15 @@ /*! \brief * Process REGISTER request and save its contacts */ -int assign_server_unreg(struct sip_msg* _m, char* str1, str* direction, char* route); +int assign_server_unreg( + struct sip_msg *_m, char *str1, str *direction, char *route); -int save(struct sip_msg* msg, char* str1, char* route, int _cflags); +int save(struct sip_msg *msg, char *str1, char *route, int _cflags); -int unregister(struct sip_msg* _m, char* _d, char* _uri); +int unregister(struct sip_msg *_m, char *_d, char *_uri); -int update_contacts(struct sip_msg* msg, udomain_t* _d, - str* public_identity, int assignment_type, ims_subscription** s, - str* ccf1, str* ccf2, str* ecf1, str* ecf2, contact_for_header_t** contact_header); +int update_contacts(struct sip_msg *msg, udomain_t *_d, str *public_identity, + int assignment_type, ims_subscription **s, str *ccf1, str *ccf2, + str *ecf1, str *ecf2, contact_for_header_t **contact_header); #endif /* SAVE_H */ diff --git a/src/modules/ims_registrar_scscf/sem.h b/src/modules/ims_registrar_scscf/sem.h index 48a2431f767..891d55d3dda 100644 --- a/src/modules/ims_registrar_scscf/sem.h +++ b/src/modules/ims_registrar_scscf/sem.h @@ -51,40 +51,40 @@ #ifndef __SEM_H #define __SEM_H - #include +#include - typedef sem_t gen_sem_t; +typedef sem_t gen_sem_t; - /** +/** * Create a new unnamed semaphore and initialize it * @param value - 0 if it should be pre-locked, 1 if not, or how many locks until block * @return */ - #define sem_new(sem_ptr,value)\ - do {\ - sem_ptr=shm_malloc(sizeof(gen_sem_t));\ - if (!sem_ptr){\ - LM_ERR("Error allocating %lx bytes of shm!\n",sizeof(gen_sem_t));\ - } \ - if (sem_init(sem_ptr, 1, value)<0) {\ - LM_ERR("Error > %s\n",strerror(errno));\ - }\ +#define sem_new(sem_ptr, value) \ + do { \ + sem_ptr = shm_malloc(sizeof(gen_sem_t)); \ + if(!sem_ptr) { \ + LM_ERR("Error allocating %lx bytes of shm!\n", sizeof(gen_sem_t)); \ + } \ + if(sem_init(sem_ptr, 1, value) < 0) { \ + LM_ERR("Error > %s\n", strerror(errno)); \ + } \ } while(0) - - #define sem_free(sem)\ - do {\ - if (sem) {\ - sem_destroy(sem);\ - shm_free(sem);\ - sem=0;\ - }\ + +#define sem_free(sem) \ + do { \ + if(sem) { \ + sem_destroy(sem); \ + shm_free(sem); \ + sem = 0; \ + } \ } while(0) - - - #define sem_get(sem) sem_wait(sem) - #define sem_tryget(sem) sem_trywait(sem) - #define sem_timedget(sem,abs_timeout) sem_trywait(sem,abs_timeout) - - #define sem_release(sem) sem_post(sem) + + +#define sem_get(sem) sem_wait(sem) +#define sem_tryget(sem) sem_trywait(sem) +#define sem_timedget(sem, abs_timeout) sem_trywait(sem, abs_timeout) + +#define sem_release(sem) sem_post(sem) #endif diff --git a/src/modules/ims_registrar_scscf/server_assignment.c b/src/modules/ims_registrar_scscf/server_assignment.c index 4d091843cf4..adece1b7bd5 100644 --- a/src/modules/ims_registrar_scscf/server_assignment.c +++ b/src/modules/ims_registrar_scscf/server_assignment.c @@ -69,24 +69,26 @@ extern str scscf_name_str; * @param str2 - not used * @returns true if ok, false if not, break on error */ -int scscf_assign_server(struct sip_msg *msg, - str public_identity, str private_identity, int assignment_type, - int data_available, saved_transaction_t* transaction_data) { +int scscf_assign_server(struct sip_msg *msg, str public_identity, + str private_identity, int assignment_type, int data_available, + saved_transaction_t *transaction_data) +{ - int result = -1; + int result = -1; - if (assignment_type != AVP_IMS_SAR_REGISTRATION + if(assignment_type != AVP_IMS_SAR_REGISTRATION && assignment_type != AVP_IMS_SAR_RE_REGISTRATION && assignment_type != AVP_IMS_SAR_USER_DEREGISTRATION - && assignment_type != AVP_IMS_SAR_USER_DEREGISTRATION_STORE_SERVER_NAME + && assignment_type + != AVP_IMS_SAR_USER_DEREGISTRATION_STORE_SERVER_NAME && assignment_type != AVP_IMS_SAR_UNREGISTERED_USER) { LM_DBG("Invalid SAR assignment type\n"); - return result; + return result; } - result = cxdx_send_sar(msg, public_identity, private_identity, + result = cxdx_send_sar(msg, public_identity, private_identity, scscf_name_str, assignment_type, data_available, transaction_data); - - return result; + + return result; } diff --git a/src/modules/ims_registrar_scscf/server_assignment.h b/src/modules/ims_registrar_scscf/server_assignment.h index 04c36175683..6602d326aeb 100644 --- a/src/modules/ims_registrar_scscf/server_assignment.h +++ b/src/modules/ims_registrar_scscf/server_assignment.h @@ -44,7 +44,7 @@ */ #ifndef SERVER_ASSIGNMENT_H -#define SERVER_ASSIGNMENT_H +#define SERVER_ASSIGNMENT_H #include "ims_registrar_scscf_mod.h" #include "../cdp/diameter.h" @@ -54,10 +54,9 @@ extern struct cxdx_binds cxdxb; -int scscf_assign_server(struct sip_msg *msg, - str public_identity, str private_identity, int assignment_type, - int data_available, saved_transaction_t* transaction_data); +int scscf_assign_server(struct sip_msg *msg, str public_identity, + str private_identity, int assignment_type, int data_available, + saved_transaction_t *transaction_data); -#endif /* SERVER_ASSIGNMENT_H */ - +#endif /* SERVER_ASSIGNMENT_H */ diff --git a/src/modules/ims_registrar_scscf/sip_msg.c b/src/modules/ims_registrar_scscf/sip_msg.c index e61a2204e4e..368eb5c14ab 100644 --- a/src/modules/ims_registrar_scscf/sip_msg.c +++ b/src/modules/ims_registrar_scscf/sip_msg.c @@ -30,30 +30,31 @@ #include "../../core/parser/hf.h" #include "../../core/dprint.h" -#include "../../core/parser/parse_expires.h" +#include "../../core/parser/parse_expires.h" #include "../../core/ut.h" #include "../../core/qvalue.h" -#include "ims_registrar_scscf_mod.h" /* Module parameters */ -#include "regtime.h" /* act_time */ +#include "ims_registrar_scscf_mod.h" /* Module parameters */ +#include "regtime.h" /* act_time */ #include "rerrno.h" #include "sip_msg.h" #include "config.h" #include "../../lib/ims/ims_getters.h" -static struct hdr_field* act_contact; +static struct hdr_field *act_contact; /*! \brief * Return an expire value in the range [ default_expires - range%, default_expires + range% ] */ -static inline int get_expire_val(void) { +static inline int get_expire_val(void) +{ int expires = cfg_get(registrar, registrar_cfg, default_expires); int range = cfg_get(registrar, registrar_cfg, default_expires_range); /* if no range is given just return default_expires */ - if (range == 0) + if(range == 0) return expires; /* select a random value in the range */ - return expires - (float) range / 100 * expires - + (float) (kam_rand() % 100) / 100 * 2 * (float) range / 100 * expires; + return expires - (float)range / 100 * expires + + (float)(kam_rand() % 100) / 100 * 2 * (float)range / 100 * expires; } /*! \brief @@ -62,12 +63,13 @@ static inline int get_expire_val(void) { * time, if the HF doesn't exist, returns * default value; */ -static inline int get_expires_hf(struct sip_msg* _m) { - exp_body_t* p; - if (_m->expires) { - p = (exp_body_t*) _m->expires->parsed; - if (p->valid) { - if (p->val != 0) { +static inline int get_expires_hf(struct sip_msg *_m) +{ + exp_body_t *p; + if(_m->expires) { + p = (exp_body_t *)_m->expires->parsed; + if(p->valid) { + if(p->val != 0) { return p->val + act_time; } else return 0; @@ -81,25 +83,27 @@ static inline int get_expires_hf(struct sip_msg* _m) { /*! \brief * Get the first contact in message */ -contact_t* get_first_contact(struct sip_msg* _m) { - if (_m->contact == 0) +contact_t *get_first_contact(struct sip_msg *_m) +{ + if(_m->contact == 0) return 0; act_contact = _m->contact; - return (((contact_body_t*) _m->contact->parsed)->contacts); + return (((contact_body_t *)_m->contact->parsed)->contacts); } /*! \brief * Get next contact in message */ -contact_t* get_next_contact(contact_t* _c) { - struct hdr_field* p; - if (_c->next == 0) { +contact_t *get_next_contact(contact_t *_c) +{ + struct hdr_field *p; + if(_c->next == 0) { p = act_contact->next; - while (p) { - if (p->type == HDR_CONTACT_T) { + while(p) { + if(p->type == HDR_CONTACT_T) { act_contact = p; - return (((contact_body_t*) p->parsed)->contacts); + return (((contact_body_t *)p->parsed)->contacts); } p = p->next; } @@ -148,11 +152,12 @@ contact_t* get_next_contact(contact_t* _c) { * 1) If q parameter exists, use it * 2) If the parameter doesn't exist, use the default value */ -int calc_contact_q(param_t* _q, qvalue_t* _r) { - if (!_q || (_q->body.len == 0)) { +int calc_contact_q(param_t *_q, qvalue_t *_r) +{ + if(!_q || (_q->body.len == 0)) { *_r = cfg_get(registrar, registrar_cfg, default_q); } else { - if (str2q(_r, _q->body.s, _q->body.len) < 0) { + if(str2q(_r, _q->body.s, _q->body.len) < 0) { rerrno = R_INV_Q; /* Invalid q parameter */ LM_ERR("invalid q parameter\n"); return -1; @@ -166,34 +171,35 @@ int calc_contact_q(param_t* _q, qvalue_t* _r) { * The whole message must be parsed before calling the function * _s indicates whether the contact was star */ -int check_contacts(struct sip_msg* _m, int* _s) { - struct hdr_field* p; - contact_t* c; +int check_contacts(struct sip_msg *_m, int *_s) +{ + struct hdr_field *p; + contact_t *c; *_s = 0; /* Message without contacts is OK */ - if (_m->contact == 0) + if(_m->contact == 0) return 0; - if (((contact_body_t*) _m->contact->parsed)->star == 1) { + if(((contact_body_t *)_m->contact->parsed)->star == 1) { /* The first Contact HF is star */ /* Expires must be zero */ - if (cscf_get_expires(_m) != 0) { + if(cscf_get_expires(_m) != 0) { rerrno = R_STAR_EXP; return 1; } /* Message must contain no contacts */ - if (((contact_body_t*) _m->contact->parsed)->contacts) { + if(((contact_body_t *)_m->contact->parsed)->contacts) { rerrno = R_STAR_CONT; return 1; } /* Message must contain no other Contact HFs */ p = _m->contact->next; - while (p) { - if (p->type == HDR_CONTACT_T) { + while(p) { + if(p->type == HDR_CONTACT_T) { rerrno = R_STAR_CONT; return 1; } @@ -204,16 +210,16 @@ int check_contacts(struct sip_msg* _m, int* _s) { } else { /* The first Contact HF is not star */ /* Message must contain no star Contact HF */ p = _m->contact->next; - while (p) { - if (p->type == HDR_CONTACT_T) { - if (((contact_body_t*) p->parsed)->star == 1) { + while(p) { + if(p->type == HDR_CONTACT_T) { + if(((contact_body_t *)p->parsed)->star == 1) { rerrno = R_STAR_CONT; return 1; } /* check also the length of all contacts */ - for (c = ((contact_body_t*) p->parsed)->contacts; c; + for(c = ((contact_body_t *)p->parsed)->contacts; c; c = c->next) { - if (c->uri.len > CONTACT_MAX_SIZE + if(c->uri.len > CONTACT_MAX_SIZE || (c->received && c->received->len > RECEIVED_MAX_SIZE)) { rerrno = R_CONTACT_LEN; @@ -232,45 +238,46 @@ int check_contacts(struct sip_msg* _m, int* _s) { * Parse the whole message and bodies of all header fields * that will be needed by registrar */ -int parse_message_for_register(struct sip_msg* _m) { - struct hdr_field* ptr; +int parse_message_for_register(struct sip_msg *_m) +{ + struct hdr_field *ptr; - if (parse_headers(_m, HDR_EOH_F, 0) == -1) { + if(parse_headers(_m, HDR_EOH_F, 0) == -1) { rerrno = R_PARSE; LM_ERR("failed to parse headers\n"); return -1; } - if (!_m->to) { + if(!_m->to) { rerrno = R_TO_MISS; LM_ERR("To not found\n"); return -2; } - if (!_m->callid) { + if(!_m->callid) { rerrno = R_CID_MISS; LM_ERR("Call-ID not found\n"); return -3; } - if (!_m->cseq) { + if(!_m->cseq) { rerrno = R_CS_MISS; LM_ERR("CSeq not found\n"); return -4; } - if (_m->expires && !_m->expires->parsed + if(_m->expires && !_m->expires->parsed && (parse_expires(_m->expires) < 0)) { rerrno = R_PARSE_EXP; LM_ERR("failed to parse expires body\n"); return -5; } - if (_m->contact) { + if(_m->contact) { ptr = _m->contact; - while (ptr) { - if (ptr->type == HDR_CONTACT_T) { - if (!ptr->parsed && (parse_contact(ptr) < 0)) { + while(ptr) { + if(ptr->type == HDR_CONTACT_T) { + if(!ptr->parsed && (parse_contact(ptr) < 0)) { rerrno = R_PARSE_CONT; LM_ERR("failed to parse Contact body\n"); return -6; diff --git a/src/modules/ims_registrar_scscf/sip_msg.h b/src/modules/ims_registrar_scscf/sip_msg.h index 1ba58fef36f..c73517eca7f 100644 --- a/src/modules/ims_registrar_scscf/sip_msg.h +++ b/src/modules/ims_registrar_scscf/sip_msg.h @@ -25,7 +25,7 @@ * \file * \brief SIP registrar module - SIP message related functions * \ingroup registrar - */ + */ #ifndef SIP_MSG_H @@ -40,7 +40,7 @@ * Parse the whole message and bodies of all header fields * that will be needed by registrar */ -int parse_message_for_register(struct sip_msg* _m); +int parse_message_for_register(struct sip_msg *_m); /*! \brief @@ -48,7 +48,7 @@ int parse_message_for_register(struct sip_msg* _m); * The whole message must be parsed before calling the function * _s indicates whether the contact was star */ -int check_contacts(struct sip_msg* _m, int* _s); +int check_contacts(struct sip_msg *_m, int *_s); /*! \brief @@ -68,10 +68,10 @@ int check_contacts(struct sip_msg* _m, int* _s); * 1) If q parameter exist, use it * 2) If the parameter doesn't exist, use default value */ -int calc_contact_q(param_t* _q, qvalue_t* _r); +int calc_contact_q(param_t *_q, qvalue_t *_r); -contact_t* get_first_contact(struct sip_msg* _m); -contact_t* get_next_contact(contact_t* _c); +contact_t *get_first_contact(struct sip_msg *_m); +contact_t *get_next_contact(contact_t *_c); #endif /* SIP_MSG_H */ diff --git a/src/modules/ims_registrar_scscf/stats.c b/src/modules/ims_registrar_scscf/stats.c index e0fa51aa2a4..b31d1789a19 100644 --- a/src/modules/ims_registrar_scscf/stats.c +++ b/src/modules/ims_registrar_scscf/stats.c @@ -43,14 +43,16 @@ #include "stats.h" #include "registrar_notify.h" -int register_stats() { +int register_stats() +{ //SAR - if (register_stat(MOD_NAME, "sar_replies_response_time", &sar_replies_response_time,0 ) + if(register_stat(MOD_NAME, "sar_replies_response_time", + &sar_replies_response_time, 0) != 0) { LM_ERR("failed to register stat\n"); return -1; } - if (register_stat(MOD_NAME, "sar_replies_received", &sar_replies_received, 0) + if(register_stat(MOD_NAME, "sar_replies_received", &sar_replies_received, 0) != 0) { LM_ERR("failed to register stat\n"); return -1; @@ -59,16 +61,17 @@ int register_stats() { return 1; } -unsigned long get_avg_sar_response_time() { +unsigned long get_avg_sar_response_time() +{ long rpls_received = get_stat_val(sar_replies_received); - if (!rpls_received) + if(!rpls_received) return 0; - return get_stat_val(sar_replies_response_time)/rpls_received; + return get_stat_val(sar_replies_response_time) / rpls_received; } -unsigned long get_notification_list_size() { +unsigned long get_notification_list_size() +{ return notification_list->size; } - diff --git a/src/modules/ims_registrar_scscf/stats.h b/src/modules/ims_registrar_scscf/stats.h index ea4418f4264..0d5579be601 100644 --- a/src/modules/ims_registrar_scscf/stats.h +++ b/src/modules/ims_registrar_scscf/stats.h @@ -43,9 +43,9 @@ #include "../../core/counters.h" -extern stat_var* stat_sar_timeouts; -extern stat_var* sar_replies_received; -extern stat_var* sar_replies_response_time; +extern stat_var *stat_sar_timeouts; +extern stat_var *sar_replies_received; +extern stat_var *sar_replies_response_time; int register_stats(); unsigned long get_avg_sar_response_time(); diff --git a/src/modules/ims_registrar_scscf/userdata_parser.c b/src/modules/ims_registrar_scscf/userdata_parser.c index 0c382e3bcd2..f1026da0123 100644 --- a/src/modules/ims_registrar_scscf/userdata_parser.c +++ b/src/modules/ims_registrar_scscf/userdata_parser.c @@ -44,10 +44,10 @@ #include "userdata_parser.h" #include "../../core/parser/parse_hname2.h" -int ctxtInit=0; /**< the XML context */ +int ctxtInit = 0; /**< the XML context */ static xmlDtdPtr dtd; static xmlValidCtxtPtr dtdCtxt; -static xmlSchemaValidCtxtPtr xsdCtxt=0; /**< Schema Validating context */ +static xmlSchemaValidCtxtPtr xsdCtxt = 0; /**< Schema Validating context */ static xmlSchemaPtr xsd; /** @@ -55,30 +55,34 @@ static xmlSchemaPtr xsd; * @param dest - destination * @param src - source */ -void space_quotes_trim_dup(str *dest,char * src) { +void space_quotes_trim_dup(str *dest, char *src) +{ int i = 0; //right space trim - if (src == NULL) return ; + if(src == NULL) + return; dest->len = strlen(src); i = dest->len - 1; - while((src[i] == ' '||src[i]=='\t') && i > 0) { + while((src[i] == ' ' || src[i] == '\t') && i > 0) { dest->len--; i--; } //left space trim i = 0; - while((src[i] == ' '||src[i]=='\t') && ilen) + while((src[i] == ' ' || src[i] == '\t') && i < dest->len) i++; - while(ilen &&(src[i]=='\"'&&src[dest->len-1]=='\"')){ + while(i < dest->len && (src[i] == '\"' && src[dest->len - 1] == '\"')) { i++; - if (ilen) dest->len--; + if(i < dest->len) + dest->len--; } dest->len -= i; - if (dest->len<=0) return; + if(dest->len <= 0) + return; dest->s = shm_malloc(dest->len); - memcpy(dest->s, src+i , dest->len); + memcpy(dest->s, src + i, dest->len); } /** @@ -90,13 +94,19 @@ void space_quotes_trim_dup(str *dest,char * src) { */ static inline char ifc_tBool2char(xmlChar *x) { - int r=0; - while(x[r]){ - switch(x[r]){ - case '0': return 0; - case '1': return 1; - case 't': case 'T': return 1; - case 'f': case 'F': return 0; + int r = 0; + while(x[r]) { + switch(x[r]) { + case '0': + return 0; + case '1': + return 1; + case 't': + case 'T': + return 1; + case 'f': + case 'F': + return 0; } r++; } @@ -112,17 +122,19 @@ static inline char ifc_tBool2char(xmlChar *x) */ static inline char ifc_tDefaultHandling2char(xmlChar *x) { - char r; - r = strtol((char*)x, (char **)NULL, 10); - if (errno==EINVAL){ - while(x[0]){ - if (x[0]=='c'||x[0]=='C') return 0;//SESSION_CONTINUED - if (x[0]=='r'||x[0]=='R') return 1;//SESSION_TERMINATED + char r; + r = strtol((char *)x, (char **)NULL, 10); + if(errno == EINVAL) { + while(x[0]) { + if(x[0] == 'c' || x[0] == 'C') + return 0; //SESSION_CONTINUED + if(x[0] == 'r' || x[0] == 'R') + return 1; //SESSION_TERMINATED x++; } return 0; - } - else return (char)r; + } else + return (char)r; } /** @@ -135,18 +147,21 @@ static inline char ifc_tDefaultHandling2char(xmlChar *x) */ static inline char ifc_tDirectionOfRequest2char(xmlChar *x) { - int r; - r = strtol((char*)x, (char **)NULL, 10); - if (errno==EINVAL){ - while(x[0]){ - if (x[0]=='o'||x[0]=='O') return 0;//ORIGINATING_SESSION - if (x[0]=='s'||x[0]=='S') return 1;//TERMINATING_REGISTERED - if (x[0]=='u'||x[0]=='U') return 2;//TERMINATING_UNREGISTERED + int r; + r = strtol((char *)x, (char **)NULL, 10); + if(errno == EINVAL) { + while(x[0]) { + if(x[0] == 'o' || x[0] == 'O') + return 0; //ORIGINATING_SESSION + if(x[0] == 's' || x[0] == 'S') + return 1; //TERMINATING_REGISTERED + if(x[0] == 'u' || x[0] == 'U') + return 2; //TERMINATING_UNREGISTERED x++; } return 0; - } - else return (char)r; + } else + return (char)r; } /** @@ -159,18 +174,21 @@ static inline char ifc_tDirectionOfRequest2char(xmlChar *x) */ static inline char ifc_tProfilePartIndicator2char(xmlChar *x) { - int r; - if (x==0||x[0]==0) return -1; - r = strtol((char*)x, (char **)NULL, 10); - if (errno==EINVAL){ - while(x[0]){ - if (x[0]=='r'||x[0]=='R') return 0;//REGISTERED - if (x[0]=='u'||x[0]=='U') return 1;//UNREGISTERED + int r; + if(x == 0 || x[0] == 0) + return -1; + r = strtol((char *)x, (char **)NULL, 10); + if(errno == EINVAL) { + while(x[0]) { + if(x[0] == 'r' || x[0] == 'R') + return 0; //REGISTERED + if(x[0] == 'u' || x[0] == 'U') + return 1; //UNREGISTERED x++; } return 0; - } - else return (char)r; + } else + return (char)r; } /** @@ -180,26 +198,27 @@ static inline char ifc_tProfilePartIndicator2char(xmlChar *x) */ static inline void space_trim_dup(str *dest, char *src) { - int i; - dest->s=0; - dest->len=0; - if (!src) return; + int i; + dest->s = 0; + dest->len = 0; + if(!src) + return; dest->len = strlen(src); - i = dest->len-1; - while((src[i]==' '||src[i]=='\t') && i>0) + i = dest->len - 1; + while((src[i] == ' ' || src[i] == '\t') && i > 0) i--; - i=0; - while((src[i]==' '||src[i]=='\t') && ilen) + i = 0; + while((src[i] == ' ' || src[i] == '\t') && i < dest->len) i++; dest->len -= i; - + dest->s = shm_malloc(dest->len); - if (!dest->s) { - LM_ERR("Out of memory allocating %d bytes\n",dest->len); - dest->len=0; + if(!dest->s) { + LM_ERR("Out of memory allocating %d bytes\n", dest->len); + dest->len = 0; return; } - memcpy(dest->s,src+i,dest->len); + memcpy(dest->s, src + i, dest->len); } /** @@ -209,26 +228,30 @@ static inline void space_trim_dup(str *dest, char *src) * @param as - structure to fill * @returns 1 on success, 0 on failure */ -static int parse_application_server_extension(xmlDocPtr doc,xmlNodePtr node,ims_application_server *as) +static int parse_application_server_extension( + xmlDocPtr doc, xmlNodePtr node, ims_application_server *as) { - xmlNodePtr child; - - for(child=node->children ; child ; child=child->next) - if (child->type==XML_ELEMENT_NODE) - switch (child->name[0]) { - case 'I':case 'i': {//IncludeRegisterRequest / IncludeRegisterResponse - switch (child->name[17]) { - case 'Q':case 'q': //IncludeRegisterRequest - as->include_register_request = 1; - break; - case 'S':case 's': //IncludeRegisterResponse - as->include_register_response = 1; - break; - } - break; - } - } - return 1; + xmlNodePtr child; + + for(child = node->children; child; child = child->next) + if(child->type == XML_ELEMENT_NODE) + switch(child->name[0]) { + case 'I': + case 'i': { //IncludeRegisterRequest / IncludeRegisterResponse + switch(child->name[17]) { + case 'Q': + case 'q': //IncludeRegisterRequest + as->include_register_request = 1; + break; + case 'S': + case 's': //IncludeRegisterResponse + as->include_register_response = 1; + break; + } + break; + } + } + return 1; } /** @@ -238,41 +261,51 @@ static int parse_application_server_extension(xmlDocPtr doc,xmlNodePtr node,ims_ * @param as - structure to fill * @returns 1 on success, 0 on failure */ -static int parse_application_server(xmlDocPtr doc,xmlNodePtr node,ims_application_server *as) +static int parse_application_server( + xmlDocPtr doc, xmlNodePtr node, ims_application_server *as) { xmlNodePtr child; xmlChar *x; - as->server_name.s=NULL;as->server_name.len=0; - as->default_handling=IFC_NO_DEFAULT_HANDLING; - as->service_info.s=NULL;as->service_info.len=0; + as->server_name.s = NULL; + as->server_name.len = 0; + as->default_handling = IFC_NO_DEFAULT_HANDLING; + as->service_info.s = NULL; + as->service_info.len = 0; as->include_register_request = 0; as->include_register_response = 0; - for(child=node->children ; child ; child=child->next) - if (child->type==XML_ELEMENT_NODE) - switch (child->name[0]) { - case 'S':case 's': {//ServerName / ServiceInfo - switch (child->name[4]) { - case 'E':case 'e': //ServerName - x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1); - space_trim_dup(&(as->server_name),(char*)x); - xmlFree((char*)x); + for(child = node->children; child; child = child->next) + if(child->type == XML_ELEMENT_NODE) + switch(child->name[0]) { + case 'S': + case 's': { //ServerName / ServiceInfo + switch(child->name[4]) { + case 'E': + case 'e': //ServerName + x = xmlNodeListGetString( + doc, child->xmlChildrenNode, 1); + space_trim_dup(&(as->server_name), (char *)x); + xmlFree((char *)x); break; - case 'I':case 'i': //ServiceInfo - x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1); - space_trim_dup(&(as->service_info),(char*)x); + case 'I': + case 'i': //ServiceInfo + x = xmlNodeListGetString( + doc, child->xmlChildrenNode, 1); + space_trim_dup(&(as->service_info), (char *)x); xmlFree(x); break; } break; } - case 'D':case 'd': //DefaultHandling + case 'D': + case 'd': //DefaultHandling x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1); - as->default_handling=ifc_tDefaultHandling2char(x); + as->default_handling = ifc_tDefaultHandling2char(x); xmlFree(x); break; - case 'E':case 'e': //Extension - parse_application_server_extension(doc,child,as); + case 'E': + case 'e': //Extension + parse_application_server_extension(doc, child, as); break; } return 1; @@ -285,34 +318,38 @@ static int parse_application_server(xmlDocPtr doc,xmlNodePtr node,ims_applicatio * @param sh - structure to fill * @returns 1 on success, 0 on failure */ -static int parse_sip_header(xmlDocPtr doc,xmlNodePtr node,ims_sip_header *sh) +static int parse_sip_header(xmlDocPtr doc, xmlNodePtr node, ims_sip_header *sh) { xmlNodePtr child; xmlChar *x; char c[256]; int len; struct hdr_field hf; - sh->header.s=NULL;sh->header.len=0; - sh->content.s=NULL;sh->content.len=0; + sh->header.s = NULL; + sh->header.len = 0; + sh->content.s = NULL; + sh->content.len = 0; - for(child=node->children ; child ; child=child->next) - if (child->type==XML_ELEMENT_NODE) - switch (child->name[0]) { - case 'H':case 'h': //Header + for(child = node->children; child; child = child->next) + if(child->type == XML_ELEMENT_NODE) + switch(child->name[0]) { + case 'H': + case 'h': //Header x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1); - len = strlen((char*)x); - memcpy(c,x,len); - c[len++]=':'; - c[len]=0; - space_trim_dup(&(sh->header),(char*)x); - parse_hname2(c,c+(len<4?4:len),&hf); - sh->type=(short)hf.type; + len = strlen((char *)x); + memcpy(c, x, len); + c[len++] = ':'; + c[len] = 0; + space_trim_dup(&(sh->header), (char *)x); + parse_hname2(c, c + (len < 4 ? 4 : len), &hf); + sh->type = (short)hf.type; //LOG(L_CRIT,"[%.*s(%d)]\n",sh->header.len,sh->header.s,sh->type); xmlFree(x); break; - case 'C':case 'c': //Content + case 'C': + case 'c': //Content x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1); - space_quotes_trim_dup(&(sh->content),(char*)x); + space_quotes_trim_dup(&(sh->content), (char *)x); xmlFree(x); break; } @@ -326,24 +363,29 @@ static int parse_sip_header(xmlDocPtr doc,xmlNodePtr node,ims_sip_header *sh) * @param sd - structure to fill * @returns 1 on success, 0 on failure */ -static int parse_session_desc(xmlDocPtr doc,xmlNodePtr node,ims_session_desc *sd) +static int parse_session_desc( + xmlDocPtr doc, xmlNodePtr node, ims_session_desc *sd) { xmlNodePtr child; xmlChar *x; - sd->line.s=NULL;sd->line.len=0; - sd->content.s=NULL;sd->content.len=0; + sd->line.s = NULL; + sd->line.len = 0; + sd->content.s = NULL; + sd->content.len = 0; - for(child=node->children ; child ; child=child->next) - if (child->type==XML_ELEMENT_NODE) - switch (child->name[0]) { - case 'L':case 'l': //Line + for(child = node->children; child; child = child->next) + if(child->type == XML_ELEMENT_NODE) + switch(child->name[0]) { + case 'L': + case 'l': //Line x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1); - space_trim_dup(&(sd->line),(char*)x); + space_trim_dup(&(sd->line), (char *)x); xmlFree(x); break; - case 'C':case 'c': //Content + case 'C': + case 'c': //Content x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1); - space_quotes_trim_dup(&(sd->content),(char*)x); + space_quotes_trim_dup(&(sd->content), (char *)x); xmlFree(x); break; } @@ -357,15 +399,16 @@ static int parse_session_desc(xmlDocPtr doc,xmlNodePtr node,ims_session_desc *sd * @param spt - structure to fill * @returns 1 on success, 0 on failure */ -static int parse_spt_extension(xmlDocPtr doc,xmlNodePtr node,ims_spt *spt) +static int parse_spt_extension(xmlDocPtr doc, xmlNodePtr node, ims_spt *spt) { xmlNodePtr child; xmlChar *x; - for(child=node->children ; child ; child=child->next) { - if (child->type==XML_ELEMENT_NODE && (child->name[0]=='R' || child->name[0]=='r')) { + for(child = node->children; child; child = child->next) { + if(child->type == XML_ELEMENT_NODE + && (child->name[0] == 'R' || child->name[0] == 'r')) { x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1); - switch(atoi((char*)x)) { + switch(atoi((char *)x)) { case 0: spt->registration_type |= IFC_INITIAL_REGISTRATION; break; @@ -375,12 +418,12 @@ static int parse_spt_extension(xmlDocPtr doc,xmlNodePtr node,ims_spt *spt) case 2: spt->registration_type |= IFC_DE_REGISTRATION; break; - } + } xmlFree(x); } } -// LOG(L_CRIT,"INFO:"M_NAME":parse_spt_extension: spt->registration_type=%d\n",spt->registration_type); - return 1; + // LOG(L_CRIT,"INFO:"M_NAME":parse_spt_extension: spt->registration_type=%d\n",spt->registration_type); + return 1; } /** @@ -391,122 +434,143 @@ static int parse_spt_extension(xmlDocPtr doc,xmlNodePtr node,ims_spt *spt) * @param spt_cnt - structure to fill with the spt count * @returns 1 on success, 0 on failure */ -static int parse_spt(xmlDocPtr doc,xmlNodePtr node,ims_spt *spt_to,unsigned short *spt_cnt) +static int parse_spt(xmlDocPtr doc, xmlNodePtr node, ims_spt *spt_to, + unsigned short *spt_cnt) { - xmlNodePtr child,saved=0; + xmlNodePtr child, saved = 0; xmlChar *x; - ims_spt *spt,*spt2; + ims_spt *spt, *spt2; int group; - + spt = spt_to + *spt_cnt; - - spt->condition_negated=0; - spt->group=0; - spt->type=IFC_UNKNOWN; - spt->registration_type=0; - - for(child=node->children ; child ; child=child->next) - if (child->type==XML_ELEMENT_NODE) - switch (child->name[0]) { - case 'C':case 'c': //ConditionNegated + + spt->condition_negated = 0; + spt->group = 0; + spt->type = IFC_UNKNOWN; + spt->registration_type = 0; + + for(child = node->children; child; child = child->next) + if(child->type == XML_ELEMENT_NODE) + switch(child->name[0]) { + case 'C': + case 'c': //ConditionNegated x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1); - spt->condition_negated=ifc_tBool2char(x); + spt->condition_negated = ifc_tBool2char(x); xmlFree(x); break; - case 'G':case 'g': //Group + case 'G': + case 'g': //Group x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1); - spt->group=atoi((char*)x); + spt->group = atoi((char *)x); xmlFree(x); break; - case 'R':case 'r': //RequestUri - spt->type=IFC_REQUEST_URI; + case 'R': + case 'r': //RequestUri + spt->type = IFC_REQUEST_URI; x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1); - space_trim_dup(&(spt->request_uri),(char*)x); + space_trim_dup(&(spt->request_uri), (char *)x); xmlFree(x); break; - case 'E':case 'e': //Extension - parse_spt_extension(doc,child,spt); + case 'E': + case 'e': //Extension + parse_spt_extension(doc, child, spt); break; - case 'M':case 'm': //method - spt->type=IFC_METHOD; + case 'M': + case 'm': //method + spt->type = IFC_METHOD; x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1); - space_trim_dup(&(spt->method),(char*)x); + space_trim_dup(&(spt->method), (char *)x); xmlFree(x); break; - case 'S':case 's': {//SIPHeader/SessionCase/SessionDescription + case 'S': + case 's': { //SIPHeader/SessionCase/SessionDescription switch(child->name[7]) { - case 'E':case 'e'://SIP_HEADER - spt->type=IFC_SIP_HEADER; - parse_sip_header(doc,child,&(spt->sip_header)); + case 'E': + case 'e': //SIP_HEADER + spt->type = IFC_SIP_HEADER; + parse_sip_header(doc, child, &(spt->sip_header)); saved = child; break; - case 'C':case 'c'://Session Case - spt->type=IFC_SESSION_CASE; - x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1); - spt->session_case=ifc_tDirectionOfRequest2char(x); + case 'C': + case 'c': //Session Case + spt->type = IFC_SESSION_CASE; + x = xmlNodeListGetString( + doc, child->xmlChildrenNode, 1); + spt->session_case = ifc_tDirectionOfRequest2char(x); xmlFree(x); break; - case 'D':case 'd'://Session Description - spt->type=IFC_SESSION_DESC; - parse_session_desc(doc,child,&(spt->session_desc)); + case 'D': + case 'd': //Session Description + spt->type = IFC_SESSION_DESC; + parse_session_desc( + doc, child, &(spt->session_desc)); saved = child; break; } - } - break; + } break; } - *spt_cnt=*spt_cnt+1; + *spt_cnt = *spt_cnt + 1; - /* adding the other nodes for multiple groups */ - for(child=node->children ; child ; child=child->next) - if (child->type==XML_ELEMENT_NODE) - switch (child->name[0]) { - case 'G':case 'g': //Group + /* adding the other nodes for multiple groups */ + for(child = node->children; child; child = child->next) + if(child->type == XML_ELEMENT_NODE) + switch(child->name[0]) { + case 'G': + case 'g': //Group x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1); - group=atoi((char*)x); + group = atoi((char *)x); xmlFree(x); - if (group != spt->group){ + if(group != spt->group) { spt2 = spt_to + *spt_cnt; spt2->condition_negated = spt->condition_negated; spt2->group = group; spt2->type = spt->type; - switch(spt2->type){ + switch(spt2->type) { case IFC_REQUEST_URI: spt2->request_uri.len = spt->request_uri.len; - spt2->request_uri.s = shm_malloc(spt2->request_uri.len); - if (!spt2->request_uri.s){ - LM_ERR("Out of memory allocating %d bytes\n",spt->request_uri.len); + spt2->request_uri.s = + shm_malloc(spt2->request_uri.len); + if(!spt2->request_uri.s) { + LM_ERR("Out of memory allocating %d " + "bytes\n", + spt->request_uri.len); break; } - memcpy(spt2->request_uri.s,spt->request_uri.s,spt->request_uri.len); + memcpy(spt2->request_uri.s, spt->request_uri.s, + spt->request_uri.len); break; case IFC_METHOD: spt2->method.len = spt->method.len; spt2->method.s = shm_malloc(spt2->method.len); - if (!spt2->method.s){ - LM_ERR("Out of memory allocating %d bytes\n",spt->method.len); + if(!spt2->method.s) { + LM_ERR("Out of memory allocating %d " + "bytes\n", + spt->method.len); break; } - memcpy(spt2->method.s,spt->method.s,spt->method.len); + memcpy(spt2->method.s, spt->method.s, + spt->method.len); break; case IFC_SIP_HEADER: - parse_sip_header(doc,saved,&(spt2->sip_header)); + parse_sip_header( + doc, saved, &(spt2->sip_header)); break; case IFC_SESSION_CASE: spt2->session_case = spt->session_case; break; case IFC_SESSION_DESC: - parse_session_desc(doc,saved,&(spt2->session_desc)); - break; + parse_session_desc( + doc, saved, &(spt2->session_desc)); + break; } spt2->registration_type = spt->registration_type; - *spt_cnt = *spt_cnt+1; + *spt_cnt = *spt_cnt + 1; } break; } - return 1; + return 1; } @@ -518,45 +582,51 @@ static int parse_spt(xmlDocPtr doc,xmlNodePtr node,ims_spt *spt_to,unsigned shor * @returns 1 on success, 0 on failure * \todo An effective sort for the priority */ -static int parse_trigger_point(xmlDocPtr doc,xmlNodePtr node,ims_trigger_point *tp) +static int parse_trigger_point( + xmlDocPtr doc, xmlNodePtr node, ims_trigger_point *tp) { - xmlNodePtr child,child2; + xmlNodePtr child, child2; xmlChar *x; - unsigned short spt_cnt=0; - int i,j; + unsigned short spt_cnt = 0; + int i, j; ims_spt spttemp; - tp->condition_type_cnf=IFC_DNF;//0 - tp->spt=NULL; - tp->spt_cnt=0; - - for(child=node->children ; child ; child=child->next) - if (child->type==XML_ELEMENT_NODE) - switch (child->name[0]) { - case 'C':case 'c': //ConditionTypeCNF + tp->condition_type_cnf = IFC_DNF; //0 + tp->spt = NULL; + tp->spt_cnt = 0; + + for(child = node->children; child; child = child->next) + if(child->type == XML_ELEMENT_NODE) + switch(child->name[0]) { + case 'C': + case 'c': //ConditionTypeCNF x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1); - tp->condition_type_cnf=ifc_tBool2char(x); + tp->condition_type_cnf = ifc_tBool2char(x); xmlFree(x); break; - case 'S':case 's': //SPT - Service Point Trigger + case 'S': + case 's': //SPT - Service Point Trigger // COUNT all in another groups - for(child2=child->children ; child2 ; child2=child2->next) - if (child2->type==XML_ELEMENT_NODE) - switch (child2->name[0]) { - case 'G':case 'g': + for(child2 = child->children; child2; child2 = child2->next) + if(child2->type == XML_ELEMENT_NODE) + switch(child2->name[0]) { + case 'G': + case 'g': spt_cnt++; } break; } - tp->spt = (ims_spt*) shm_malloc(sizeof(ims_spt)*spt_cnt); - if (!tp->spt){ - LM_ERR("Out of memory allocating %lx bytes\n",sizeof(ims_spt)*spt_cnt); + tp->spt = (ims_spt *)shm_malloc(sizeof(ims_spt) * spt_cnt); + if(!tp->spt) { + LM_ERR("Out of memory allocating %lx bytes\n", + sizeof(ims_spt) * spt_cnt); return 0; } - for(child=node->children ; child ; child=child->next) - if (child->type==XML_ELEMENT_NODE) - switch (child->name[0]) { - case 'S':case 's': //SPT - Service Point Trigger - parse_spt(doc,child,tp->spt,&(tp->spt_cnt)); + for(child = node->children; child; child = child->next) + if(child->type == XML_ELEMENT_NODE) + switch(child->name[0]) { + case 'S': + case 's': //SPT - Service Point Trigger + parse_spt(doc, child, tp->spt, &(tp->spt_cnt)); /*i=0; while(ispt_cnt&&tp->spt[i].groupspt[j+1]=tp->spt[j]; tp->spt[i]=spttemp; tp->spt_cnt++;*/ - + break; } - - j=1; - while(j){ - j=0; - for(i=0;ispt_cnt-1;i++) - if (tp->spt[i].group > tp->spt[i+1].group){ - j=1; + + j = 1; + while(j) { + j = 0; + for(i = 0; i < tp->spt_cnt - 1; i++) + if(tp->spt[i].group > tp->spt[i + 1].group) { + j = 1; spttemp = tp->spt[i]; - tp->spt[i]=tp->spt[i+1]; - tp->spt[i+1]=spttemp; - } + tp->spt[i] = tp->spt[i + 1]; + tp->spt[i + 1] = spttemp; + } } return 1; } @@ -589,48 +659,59 @@ static int parse_trigger_point(xmlDocPtr doc,xmlNodePtr node,ims_trigger_point * * @param fc - structure to fill * @returns 1 on success, 0 on failure */ -static int parse_filter_criteria(xmlDocPtr doc,xmlNodePtr node,ims_filter_criteria *fc) +static int parse_filter_criteria( + xmlDocPtr doc, xmlNodePtr node, ims_filter_criteria *fc) { xmlNodePtr child; xmlChar *x; char k; - fc->priority=0; - fc->trigger_point=NULL; - fc->profile_part_indicator=NULL; + fc->priority = 0; + fc->trigger_point = NULL; + fc->profile_part_indicator = NULL; //fc->apllication_server init mai tarziu - for(child=node->children ; child ; child=child->next) - if (child->type==XML_ELEMENT_NODE) - switch (child->name[3]) { - case 'O':case 'o': //Priority + for(child = node->children; child; child = child->next) + if(child->type == XML_ELEMENT_NODE) + switch(child->name[3]) { + case 'O': + case 'o': //Priority x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1); - fc->priority=atoi((char*)x); + fc->priority = atoi((char *)x); xmlFree(x); break; - case 'G':case 'g': //TriggerPoint - fc->trigger_point=(ims_trigger_point*) shm_malloc(sizeof(ims_trigger_point)); - if (!fc->trigger_point){ - LM_ERR("Out of memory allocating %lx bytes\n",sizeof(ims_trigger_point)); + case 'G': + case 'g': //TriggerPoint + fc->trigger_point = (ims_trigger_point *)shm_malloc( + sizeof(ims_trigger_point)); + if(!fc->trigger_point) { + LM_ERR("Out of memory allocating %lx bytes\n", + sizeof(ims_trigger_point)); break; } - if (!parse_trigger_point(doc,child,fc->trigger_point)){ + if(!parse_trigger_point(doc, child, fc->trigger_point)) { shm_free(fc->trigger_point); - fc->trigger_point=0; + fc->trigger_point = 0; return 0; } break; - case 'L':case 'l': //ApplicationServer - parse_application_server(doc,child,&(fc->application_server)); + case 'L': + case 'l': //ApplicationServer + parse_application_server( + doc, child, &(fc->application_server)); break; - case 'F':case 'f': //ProfilePartIndicator + case 'F': + case 'f': //ProfilePartIndicator x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1); k = ifc_tProfilePartIndicator2char(x); - if (k<0) break; - fc->profile_part_indicator=(char*)shm_malloc(sizeof(char)); - if (!fc->profile_part_indicator){ - LM_ERR("Out of memory allocating %lx bytes\n",sizeof(ims_trigger_point)); + if(k < 0) + break; + fc->profile_part_indicator = + (char *)shm_malloc(sizeof(char)); + if(!fc->profile_part_indicator) { + LM_ERR("Out of memory allocating %lx bytes\n", + sizeof(ims_trigger_point)); break; } - *fc->profile_part_indicator=k; + *fc->profile_part_indicator = k; xmlFree(x); break; } @@ -638,7 +719,6 @@ static int parse_filter_criteria(xmlDocPtr doc,xmlNodePtr node,ims_filter_criter } - /** * Parse the Public Identity. * @param doc - the XML document @@ -646,69 +726,84 @@ static int parse_filter_criteria(xmlDocPtr doc,xmlNodePtr node,ims_filter_criter * @param pi - structure to fill * @returns 1 on success, 0 on failure , 2 if it is a wildcardpsi */ -static int parse_public_identity(xmlDocPtr doc, xmlNodePtr root, ims_public_identity *pi) +static int parse_public_identity( + xmlDocPtr doc, xmlNodePtr root, ims_public_identity *pi) { xmlNodePtr child; xmlNodePtr grandson; xmlChar *x; - int return_code=1; - - for(child=root->children;child;child=child->next) - if (child->type==XML_ELEMENT_NODE) - switch (child->name[0]){ - case 'I': case 'i': - if (!pi->public_identity.len){ - x = xmlNodeListGetString(doc,child->xmlChildrenNode,1); - space_trim_dup(&(pi->public_identity),(char*)x); + int return_code = 1; + + for(child = root->children; child; child = child->next) + if(child->type == XML_ELEMENT_NODE) + switch(child->name[0]) { + case 'I': + case 'i': + if(!pi->public_identity.len) { + x = xmlNodeListGetString( + doc, child->xmlChildrenNode, 1); + space_trim_dup(&(pi->public_identity), (char *)x); xmlFree(x); - } + } break; - case 'B': case 'b': - x = xmlNodeListGetString(doc,child->xmlChildrenNode,1); + case 'B': + case 'b': + x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1); pi->barring = ifc_tBool2char(x); xmlFree(x); break; - //lets add something - case 'E' : case 'e': + //lets add something + case 'E': + case 'e': // that would be Extension - // here i need to parse Identity Type + // here i need to parse Identity Type // if its two then wildcardedpsi // and then extension!!! // I have to check how you parse this shit - for(grandson=child->children;grandson;grandson=grandson->next) - { - - if (grandson->type==XML_ELEMENT_NODE) - { - switch (grandson->name[0]) { - case 'I' : case 'i': + for(grandson = child->children; grandson; + grandson = grandson->next) { + + if(grandson->type == XML_ELEMENT_NODE) { + switch(grandson->name[0]) { + case 'I': + case 'i': //identity type 0 public identity 1 distinct psi 2 wildcard psi //x = xmlNodeListGetString(doc,grandson->xmlChildrenNode,1); - // i need to compare x with 2, but i have to trim leading - // space characters or tabs + // i need to compare x with 2, but i have to trim leading + // space characters or tabs //xmlFree(x); break; - case 'W' : case 'w': + case 'W': + case 'w': //wildcardpsi if(!scscf_support_wildcardPSI) { - LOG(L_ERR,"Configured without support for Wildcard PSI and got one from HSS\n"); - LOG(L_ERR,"the identity will be stored but never be matched, please include the parameter to support wildcard PSI in the config file\n"); + LOG(L_ERR, "Configured without support " + "for Wildcard PSI and got " + "one from HSS\n"); + LOG(L_ERR, + "the identity will be stored " + "but never be matched, please " + "include the parameter to " + "support wildcard PSI in the " + "config file\n"); } - - x = xmlNodeListGetString(doc,grandson->xmlChildrenNode,1); - space_trim_dup(&(pi->wildcarded_psi),(char*)x); - + + x = xmlNodeListGetString( + doc, grandson->xmlChildrenNode, 1); + space_trim_dup( + &(pi->wildcarded_psi), (char *)x); + xmlFree(x); - return_code=2; + return_code = 2; break; - default : + default: break; } } } - - break; + + break; } return return_code; @@ -721,21 +816,22 @@ static int parse_public_identity(xmlDocPtr doc, xmlNodePtr root, ims_public_iden * @param cn - structure to fill * @returns 1 on success, 0 on failure */ -static int parse_cn_service_auth(xmlDocPtr doc,xmlNodePtr node,ims_cn_service_auth *cn) +static int parse_cn_service_auth( + xmlDocPtr doc, xmlNodePtr node, ims_cn_service_auth *cn) { xmlNodePtr child; xmlChar *x; - cn->subscribed_media_profile_id=-1; - for(child=node->children ; child ; child=child->next) - if (child->type==XML_ELEMENT_NODE) - switch (child->name[0]) { - case 'S':case 's': //BarringIndication + cn->subscribed_media_profile_id = -1; + for(child = node->children; child; child = child->next) + if(child->type == XML_ELEMENT_NODE) + switch(child->name[0]) { + case 'S': + case 's': //BarringIndication x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1); - cn->subscribed_media_profile_id=atoi((char*)x); + cn->subscribed_media_profile_id = atoi((char *)x); xmlFree(x); return 1; break; - } return 0; } @@ -747,91 +843,108 @@ static int parse_cn_service_auth(xmlDocPtr doc,xmlNodePtr node,ims_cn_service_au * @param sp - structure to fill * @returns 1 on success, 0 on failure */ -static int parse_service_profile(xmlDocPtr doc, xmlNodePtr root, ims_service_profile *sp) { - xmlNodePtr child; - xmlChar *x; - unsigned short pi_cnt = 0, ifc_cnt = 0, sh_cnt = 0; - int i, j; - ims_filter_criteria fctemp; - int returncode = 0; - - for (child = root->children; child; child = child->next) - if (child->type == XML_ELEMENT_NODE) { - LM_DBG("child name is [%s]\n", child->name); - switch (child->name[0]) { - case 'P': case 'p': - pi_cnt++; - break; - case 'i':case 'I': //InitialFilterCriteria - ifc_cnt++; - break; - case 'c':case 'C': //CoreNetworkServiceAuthorization - sp->cn_service_auth = (ims_cn_service_auth*) shm_malloc( - sizeof (ims_cn_service_auth)); - break; - case 's':case 'S': //SharedIFCSet - sh_cnt++; - break; - - } - - } - - sp->public_identities = shm_malloc(pi_cnt * sizeof (ims_public_identity)); - if (!sp->public_identities) { - LM_ERR("Out of memory allocating %lx bytes\n", pi_cnt * sizeof (ims_public_identity)); - return 0; - } - memset(sp->public_identities, 0, pi_cnt * sizeof (ims_public_identity)); - - sp->filter_criteria = (ims_filter_criteria*) shm_malloc(sizeof (ims_filter_criteria) * ifc_cnt); - if (!sp->filter_criteria) { - LM_ERR("Out of memory allocating %lx bytes\n", ifc_cnt * sizeof (ims_filter_criteria)); - return 0; - } - memset(sp->filter_criteria, 0, ifc_cnt * sizeof (ims_filter_criteria)); - - sp->shared_ifc_set = (int*) shm_malloc(sizeof (int) *sh_cnt); - if (!sp->shared_ifc_set) { - LM_ERR("Out of memory allocating %lx bytes\n", sh_cnt * sizeof (int)); - return 0; - } - memset(sp->shared_ifc_set, 0, sh_cnt * sizeof (int)); - - for (child = root->children; child; child = child->next) - if (child->type == XML_ELEMENT_NODE) - switch (child->name[0]) { - case 'P': case 'p': - returncode = parse_public_identity(doc, child, &(sp->public_identities[sp->public_identities_cnt])); - if (returncode) - sp->public_identities_cnt++; - break; - case 'I':case 'i': //InitialFilterCriteria - if (!parse_filter_criteria(doc, child, &(fctemp))) - break; - i = 0; - while (i < sp->filter_criteria_cnt && sp->filter_criteria[i].priority < fctemp.priority) - i++; - for (j = sp->filter_criteria_cnt - 1; j >= i; j--) - sp->filter_criteria[j + 1] = sp->filter_criteria[j]; - sp->filter_criteria[i] = fctemp; - sp->filter_criteria_cnt++; - break; - case 'C':case 'c': //CoreNetworkServiceAuthorization - if (!parse_cn_service_auth(doc, child, sp->cn_service_auth)) { - shm_free(sp->cn_service_auth); - sp->cn_service_auth = 0; - } - break; - case 'S':case 's': //SharedIFCSet - x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1); - sp->shared_ifc_set[sp->shared_ifc_set_cnt++] = atoi((char*) x); - xmlFree(x); - break; - } - if (returncode == 2) - return 2; // i need to know if there is a wildcardpsi hiding in the public_identity - return 1; +static int parse_service_profile( + xmlDocPtr doc, xmlNodePtr root, ims_service_profile *sp) +{ + xmlNodePtr child; + xmlChar *x; + unsigned short pi_cnt = 0, ifc_cnt = 0, sh_cnt = 0; + int i, j; + ims_filter_criteria fctemp; + int returncode = 0; + + for(child = root->children; child; child = child->next) + if(child->type == XML_ELEMENT_NODE) { + LM_DBG("child name is [%s]\n", child->name); + switch(child->name[0]) { + case 'P': + case 'p': + pi_cnt++; + break; + case 'i': + case 'I': //InitialFilterCriteria + ifc_cnt++; + break; + case 'c': + case 'C': //CoreNetworkServiceAuthorization + sp->cn_service_auth = (ims_cn_service_auth *)shm_malloc( + sizeof(ims_cn_service_auth)); + break; + case 's': + case 'S': //SharedIFCSet + sh_cnt++; + break; + } + } + + sp->public_identities = shm_malloc(pi_cnt * sizeof(ims_public_identity)); + if(!sp->public_identities) { + LM_ERR("Out of memory allocating %lx bytes\n", + pi_cnt * sizeof(ims_public_identity)); + return 0; + } + memset(sp->public_identities, 0, pi_cnt * sizeof(ims_public_identity)); + + sp->filter_criteria = (ims_filter_criteria *)shm_malloc( + sizeof(ims_filter_criteria) * ifc_cnt); + if(!sp->filter_criteria) { + LM_ERR("Out of memory allocating %lx bytes\n", + ifc_cnt * sizeof(ims_filter_criteria)); + return 0; + } + memset(sp->filter_criteria, 0, ifc_cnt * sizeof(ims_filter_criteria)); + + sp->shared_ifc_set = (int *)shm_malloc(sizeof(int) * sh_cnt); + if(!sp->shared_ifc_set) { + LM_ERR("Out of memory allocating %lx bytes\n", sh_cnt * sizeof(int)); + return 0; + } + memset(sp->shared_ifc_set, 0, sh_cnt * sizeof(int)); + + for(child = root->children; child; child = child->next) + if(child->type == XML_ELEMENT_NODE) + switch(child->name[0]) { + case 'P': + case 'p': + returncode = parse_public_identity(doc, child, + &(sp->public_identities + [sp->public_identities_cnt])); + if(returncode) + sp->public_identities_cnt++; + break; + case 'I': + case 'i': //InitialFilterCriteria + if(!parse_filter_criteria(doc, child, &(fctemp))) + break; + i = 0; + while(i < sp->filter_criteria_cnt + && sp->filter_criteria[i].priority + < fctemp.priority) + i++; + for(j = sp->filter_criteria_cnt - 1; j >= i; j--) + sp->filter_criteria[j + 1] = sp->filter_criteria[j]; + sp->filter_criteria[i] = fctemp; + sp->filter_criteria_cnt++; + break; + case 'C': + case 'c': //CoreNetworkServiceAuthorization + if(!parse_cn_service_auth( + doc, child, sp->cn_service_auth)) { + shm_free(sp->cn_service_auth); + sp->cn_service_auth = 0; + } + break; + case 'S': + case 's': //SharedIFCSet + x = xmlNodeListGetString(doc, child->xmlChildrenNode, 1); + sp->shared_ifc_set[sp->shared_ifc_set_cnt++] = + atoi((char *)x); + xmlFree(x); + break; + } + if(returncode == 2) + return 2; // i need to know if there is a wildcardpsi hiding in the public_identity + return 1; } /** @@ -840,75 +953,84 @@ static int parse_service_profile(xmlDocPtr doc, xmlNodePtr root, ims_service_pro * @param root - the current node * @returns the ims_subscription* on success or NULL on error */ -static ims_subscription* parse_ims_subscription(xmlDocPtr doc, xmlNodePtr root) +static ims_subscription *parse_ims_subscription(xmlDocPtr doc, xmlNodePtr root) { xmlNodePtr child; xmlChar *x; ims_subscription *s; - unsigned short sp_cnt=0; + unsigned short sp_cnt = 0; int rc; - - if (!root) return 0; - while(root->type!=XML_ELEMENT_NODE || strcasecmp((char*)root->name,"IMSSubscription")!=0){ + + if(!root) + return 0; + while(root->type != XML_ELEMENT_NODE + || strcasecmp((char *)root->name, "IMSSubscription") != 0) { root = root->next; } - if (!root) { + if(!root) { LM_ERR("No IMSSubscription node found\n"); return 0; } - s = (ims_subscription*) shm_malloc(sizeof(ims_subscription)); - if (!s) { - LM_ERR("Out of memory allocating %lx bytes\n",sizeof(ims_subscription)); + s = (ims_subscription *)shm_malloc(sizeof(ims_subscription)); + if(!s) { + LM_ERR("Out of memory allocating %lx bytes\n", + sizeof(ims_subscription)); return 0; } - memset(s,0,sizeof(ims_subscription)); - for(child=root->children;child;child=child->next) - if (child->type==XML_ELEMENT_NODE) - switch (child->name[0]){ - case 'P':case 'p': /* Private Identity */ - if (!s->private_identity.len){ - x = xmlNodeListGetString(doc,child->xmlChildrenNode,1); - space_trim_dup(&(s->private_identity),(char*)x); + memset(s, 0, sizeof(ims_subscription)); + for(child = root->children; child; child = child->next) + if(child->type == XML_ELEMENT_NODE) + switch(child->name[0]) { + case 'P': + case 'p': /* Private Identity */ + if(!s->private_identity.len) { + x = xmlNodeListGetString( + doc, child->xmlChildrenNode, 1); + space_trim_dup(&(s->private_identity), (char *)x); xmlFree(x); } break; - case 'S':case 's': /* Service Profile */ + case 'S': + case 's': /* Service Profile */ sp_cnt++; - break; + break; } - s->service_profiles = (ims_service_profile*) shm_malloc(sp_cnt * sizeof(ims_service_profile)); - if (!s->service_profiles) { - LM_ERR("Out of memory allocating %lx bytes\n",sp_cnt*sizeof(ims_service_profile)); - return s; + s->service_profiles = (ims_service_profile *)shm_malloc( + sp_cnt * sizeof(ims_service_profile)); + if(!s->service_profiles) { + LM_ERR("Out of memory allocating %lx bytes\n", + sp_cnt * sizeof(ims_service_profile)); + return s; } - memset(s->service_profiles,0,sp_cnt * sizeof(ims_service_profile)); - for(child=root->children;child;child=child->next) - if (child->type==XML_ELEMENT_NODE) - if (child->name[0]=='S' || child->name[0]=='s') - { - rc=parse_service_profile(doc,child,&(s->service_profiles[s->service_profiles_cnt])); - if (rc==2) - s->wpsi=1; - if (rc) + memset(s->service_profiles, 0, sp_cnt * sizeof(ims_service_profile)); + for(child = root->children; child; child = child->next) + if(child->type == XML_ELEMENT_NODE) + if(child->name[0] == 'S' || child->name[0] == 's') { + rc = parse_service_profile(doc, child, + &(s->service_profiles[s->service_profiles_cnt])); + if(rc == 2) + s->wpsi = 1; + if(rc) s->service_profiles_cnt++; - } + } s->lock = lock_alloc(); - if (s->lock==0) { + if(s->lock == 0) { LM_ERR("Failed to allocate Lock for IMS Subscription\n"); shm_free(s); return 0; } - if (lock_init(s->lock)==0){ + if(lock_init(s->lock) == 0) { LM_ERR("Failed to initialize Lock for IMS Subscription\n"); lock_dealloc(s->lock); - s->lock=0; + s->lock = 0; shm_free(s); return 0; } - - s->sl = -1; //this tells us the subscription is not linked to a list.... + + s->sl = -1; //this tells us the subscription is not linked to a list.... #ifdef EXTRA_DEBUG - LM_DBG("LOCK CREATED FOR SUBSCRIPTION [%.*s]: %p\n", s->private_identity.len, s->private_identity.s, s->lock); + LM_DBG("LOCK CREATED FOR SUBSCRIPTION [%.*s]: %p\n", + s->private_identity.len, s->private_identity.s, s->lock); #endif return s; } @@ -921,48 +1043,51 @@ static ims_subscription* parse_ims_subscription(xmlDocPtr doc, xmlNodePtr root) */ ims_subscription *parse_user_data(str xml) { - xmlDocPtr doc=0; - xmlNodePtr root=0; + xmlDocPtr doc = 0; + xmlNodePtr root = 0; ims_subscription *s = 0; - if (!ctxtInit) parser_init(scscf_user_data_dtd,scscf_user_data_xsd); - doc=0; - + if(!ctxtInit) + parser_init(scscf_user_data_dtd, scscf_user_data_xsd); + doc = 0; + doc = xmlParseMemory(xml.s, xml.len); - if (!doc){ - LM_ERR("This is not a valid XML <%.*s>\n", xml.len,xml.s); + if(!doc) { + LM_ERR("This is not a valid XML <%.*s>\n", xml.len, xml.s); goto error; } - if (dtdCtxt){ - if (xmlValidateDtd(dtdCtxt,doc,dtd)!=1){ - LM_ERR("Verification of XML against DTD failed <%.*s>\n", xml.len,xml.s); + if(dtdCtxt) { + if(xmlValidateDtd(dtdCtxt, doc, dtd) != 1) { + LM_ERR("Verification of XML against DTD failed <%.*s>\n", xml.len, + xml.s); goto error; } } - if (xsdCtxt){ - if (xmlSchemaValidateDoc(xsdCtxt,doc)!=0){ - LM_ERR("Verification of XML against XSD failed <%.*s>\n", xml.len,xml.s); + if(xsdCtxt) { + if(xmlSchemaValidateDoc(xsdCtxt, doc) != 0) { + LM_ERR("Verification of XML against XSD failed <%.*s>\n", xml.len, + xml.s); goto error; } } root = xmlDocGetRootElement(doc); - if (!root){ - LM_ERR("Empty XML <%.*s>\n", - xml.len,xml.s); + if(!root) { + LM_ERR("Empty XML <%.*s>\n", xml.len, xml.s); goto error; } - s = parse_ims_subscription(doc,root); - if (!s){ + s = parse_ims_subscription(doc, root); + if(!s) { LM_ERR("Error while loading into ims subscription structure\n"); - goto error; + goto error; } xmlFreeDoc(doc); print_user_data(s); return s; -error: - if (doc) xmlFreeDoc(doc); - return 0; +error: + if(doc) + xmlFreeDoc(doc); + return 0; } /** @@ -973,34 +1098,34 @@ ims_subscription *parse_user_data(str xml) */ int parser_init(char *dtd_filename, char *xsd_filename) { - if (dtd_filename){ - dtd = xmlParseDTD(NULL,(unsigned char*)dtd_filename); - if (!dtd){ - LM_ERR("unsuccessful DTD parsing from file <%s>\n", - dtd_filename); + if(dtd_filename) { + dtd = xmlParseDTD(NULL, (unsigned char *)dtd_filename); + if(!dtd) { + LM_ERR("unsuccessful DTD parsing from file <%s>\n", dtd_filename); return 0; } dtdCtxt = xmlNewValidCtxt(); - dtdCtxt->userData = (void*)stderr; - dtdCtxt->error = (xmlValidityErrorFunc) fprintf; - dtdCtxt->warning = (xmlValidityWarningFunc) fprintf; + dtdCtxt->userData = (void *)stderr; + dtdCtxt->error = (xmlValidityErrorFunc)fprintf; + dtdCtxt->warning = (xmlValidityWarningFunc)fprintf; } - if (xsd_filename){ + if(xsd_filename) { xmlSchemaParserCtxtPtr ctxt; ctxt = xmlSchemaNewParserCtxt(xsd_filename); - if (!ctxt) { - LM_ERR("unsuccessful XSD parsing from file <%s>\n", - xsd_filename); + if(!ctxt) { + LM_ERR("unsuccessful XSD parsing from file <%s>\n", xsd_filename); return 0; } - xmlSchemaSetParserErrors(ctxt,(xmlValidityErrorFunc) fprintf,(xmlValidityWarningFunc) fprintf,stderr); + xmlSchemaSetParserErrors(ctxt, (xmlValidityErrorFunc)fprintf, + (xmlValidityWarningFunc)fprintf, stderr); xsd = xmlSchemaParse(ctxt); - xmlSchemaFreeParserCtxt(ctxt); - + xmlSchemaFreeParserCtxt(ctxt); + xsdCtxt = xmlSchemaNewValidCtxt(xsd); - xmlSchemaSetValidErrors(xsdCtxt,(xmlValidityErrorFunc) fprintf,(xmlValidityWarningFunc) fprintf,stderr); + xmlSchemaSetValidErrors(xsdCtxt, (xmlValidityErrorFunc)fprintf, + (xmlValidityWarningFunc)fprintf, stderr); } - ctxtInit=1; + ctxtInit = 1; return 1; } @@ -1010,97 +1135,186 @@ int parser_init(char *dtd_filename, char *xsd_filename) * @param log_level - level to log on * @param s - the ims_subscription to be printed */ -void print_user_data(ims_subscription *s) { - int i, j, k; - - LM_DBG("IMSSubscription:\n"); - if (!s) return; - - LM_DBG("Private Identity: <%.*s>\n", s->private_identity.len, s->private_identity.s); - for (i = 0; i < s->service_profiles_cnt; i++) { - LM_DBG("\tService Profile:\n"); - for (j = 0; j < s->service_profiles[i].public_identities_cnt; j++) { - LM_DBG("\t\tPublic Identity: Barring [%d] <%.*s> \n", - s->service_profiles[i].public_identities[j].barring, - s->service_profiles[i].public_identities[j].public_identity.len, - s->service_profiles[i].public_identities[j].public_identity.s); - } - for (j = 0; j < s->service_profiles[i].filter_criteria_cnt; j++) { - LM_DBG("\t\tFilter Criteria: Priority [%d]ProfilePartInd [%d]\n", - s->service_profiles[i].filter_criteria[j].priority, - s->service_profiles[i].filter_criteria[j].profile_part_indicator ? - *(s->service_profiles[i].filter_criteria[j].profile_part_indicator) : -1); - if (s->service_profiles[i].filter_criteria[j].trigger_point) { - LM_DBG("\t\t\tTrigger Point: CNF [%c] %s\n", - s->service_profiles[i].filter_criteria[j].trigger_point->condition_type_cnf ? 'X' : ' ', - s->service_profiles[i].filter_criteria[j].trigger_point->condition_type_cnf ? "(_|_)&(_|_)" : "(_&_)|(_&_)" - ); - for (k = 0; k < s->service_profiles[i].filter_criteria[j].trigger_point->spt_cnt; k++) { - LM_DBG("\t\t\t\tSPT: Grp[%d] NOT[%c] RegType[%d]\n", - s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].group, - s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].condition_negated ? 'X' : ' ', - s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].registration_type - ); - switch (s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].type) { - case 1: - LM_DBG("\t\t\t\t\t Request-URI == <%.*s>\n", - s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].request_uri.len, - s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].request_uri.s); - break; - case 2: - LM_DBG("\t\t\t\t\t Method == <%.*s>\n", - s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].method.len, - s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].method.s); - break; - case 3: - LM_DBG("\t\t\t\t\t Hdr(%.*s(%d)) == <%.*s>\n", - s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].sip_header.header.len, - s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].sip_header.header.s, - s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].sip_header.type, - s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].sip_header.content.len, - s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].sip_header.content.s); - break; - case 4: - LM_DBG("\t\t\t\t\t SessionCase [%d]\n", - s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].session_case); - break; - case 5: - LM_DBG("\t\t\t\t\t SDP(%.*s) == <%.*s>\n", - s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].session_desc.line.len, - s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].session_desc.line.s, - s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].session_desc.content.len, - s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].session_desc.content.s); - break; - } - } - } - LM_DBG("\t\t\tAS: <%.*s> Handling [%d] SrvInfo: <%.*s>\n", - s->service_profiles[i].filter_criteria[j].application_server.server_name.len, - s->service_profiles[i].filter_criteria[j].application_server.server_name.s, - s->service_profiles[i].filter_criteria[j].application_server.default_handling, - s->service_profiles[i].filter_criteria[j].application_server.service_info.len, - s->service_profiles[i].filter_criteria[j].application_server.service_info.s); - } - if (s->service_profiles[i].cn_service_auth) { - LM_DBG("\t\tCN Serv Auth: Subs Media Profile ID [%d]\n", - s->service_profiles[i].cn_service_auth->subscribed_media_profile_id); - } - for (j = 0; j < s->service_profiles[i].shared_ifc_set_cnt; j++) { - LM_DBG("\t\tShared IFC Set: [%d]\n", - s->service_profiles[i].shared_ifc_set[j]); - } - } +void print_user_data(ims_subscription *s) +{ + int i, j, k; + + LM_DBG("IMSSubscription:\n"); + if(!s) + return; + + LM_DBG("Private Identity: <%.*s>\n", s->private_identity.len, + s->private_identity.s); + for(i = 0; i < s->service_profiles_cnt; i++) { + LM_DBG("\tService Profile:\n"); + for(j = 0; j < s->service_profiles[i].public_identities_cnt; j++) { + LM_DBG("\t\tPublic Identity: Barring [%d] <%.*s> \n", + s->service_profiles[i].public_identities[j].barring, + s->service_profiles[i] + .public_identities[j] + .public_identity.len, + s->service_profiles[i] + .public_identities[j] + .public_identity.s); + } + for(j = 0; j < s->service_profiles[i].filter_criteria_cnt; j++) { + LM_DBG("\t\tFilter Criteria: Priority [%d]ProfilePartInd [%d]\n", + s->service_profiles[i].filter_criteria[j].priority, + s->service_profiles[i] + .filter_criteria[j] + .profile_part_indicator + ? *(s->service_profiles[i] + .filter_criteria[j] + .profile_part_indicator) + : -1); + if(s->service_profiles[i].filter_criteria[j].trigger_point) { + LM_DBG("\t\t\tTrigger Point: CNF [%c] %s\n", + s->service_profiles[i] + .filter_criteria[j] + .trigger_point->condition_type_cnf + ? 'X' + : ' ', + s->service_profiles[i] + .filter_criteria[j] + .trigger_point->condition_type_cnf + ? "(_|_)&(_|_)" + : "(_&_)|(_&_)"); + for(k = 0; k < s->service_profiles[i] + .filter_criteria[j] + .trigger_point->spt_cnt; + k++) { + LM_DBG("\t\t\t\tSPT: Grp[%d] NOT[%c] RegType[%d]\n", + s->service_profiles[i] + .filter_criteria[j] + .trigger_point->spt[k] + .group, + s->service_profiles[i] + .filter_criteria[j] + .trigger_point->spt[k] + .condition_negated + ? 'X' + : ' ', + s->service_profiles[i] + .filter_criteria[j] + .trigger_point->spt[k] + .registration_type); + switch(s->service_profiles[i] + .filter_criteria[j] + .trigger_point->spt[k] + .type) { + case 1: + LM_DBG("\t\t\t\t\t Request-URI == <%.*s>\n", + s->service_profiles[i] + .filter_criteria[j] + .trigger_point->spt[k] + .request_uri.len, + s->service_profiles[i] + .filter_criteria[j] + .trigger_point->spt[k] + .request_uri.s); + break; + case 2: + LM_DBG("\t\t\t\t\t Method == <%.*s>\n", + s->service_profiles[i] + .filter_criteria[j] + .trigger_point->spt[k] + .method.len, + s->service_profiles[i] + .filter_criteria[j] + .trigger_point->spt[k] + .method.s); + break; + case 3: + LM_DBG("\t\t\t\t\t Hdr(%.*s(%d)) == <%.*s>\n", + s->service_profiles[i] + .filter_criteria[j] + .trigger_point->spt[k] + .sip_header.header.len, + s->service_profiles[i] + .filter_criteria[j] + .trigger_point->spt[k] + .sip_header.header.s, + s->service_profiles[i] + .filter_criteria[j] + .trigger_point->spt[k] + .sip_header.type, + s->service_profiles[i] + .filter_criteria[j] + .trigger_point->spt[k] + .sip_header.content.len, + s->service_profiles[i] + .filter_criteria[j] + .trigger_point->spt[k] + .sip_header.content.s); + break; + case 4: + LM_DBG("\t\t\t\t\t SessionCase [%d]\n", + s->service_profiles[i] + .filter_criteria[j] + .trigger_point->spt[k] + .session_case); + break; + case 5: + LM_DBG("\t\t\t\t\t SDP(%.*s) == <%.*s>\n", + s->service_profiles[i] + .filter_criteria[j] + .trigger_point->spt[k] + .session_desc.line.len, + s->service_profiles[i] + .filter_criteria[j] + .trigger_point->spt[k] + .session_desc.line.s, + s->service_profiles[i] + .filter_criteria[j] + .trigger_point->spt[k] + .session_desc.content.len, + s->service_profiles[i] + .filter_criteria[j] + .trigger_point->spt[k] + .session_desc.content.s); + break; + } + } + } + LM_DBG("\t\t\tAS: <%.*s> Handling [%d] SrvInfo: <%.*s>\n", + s->service_profiles[i] + .filter_criteria[j] + .application_server.server_name.len, + s->service_profiles[i] + .filter_criteria[j] + .application_server.server_name.s, + s->service_profiles[i] + .filter_criteria[j] + .application_server.default_handling, + s->service_profiles[i] + .filter_criteria[j] + .application_server.service_info.len, + s->service_profiles[i] + .filter_criteria[j] + .application_server.service_info.s); + } + if(s->service_profiles[i].cn_service_auth) { + LM_DBG("\t\tCN Serv Auth: Subs Media Profile ID [%d]\n", + s->service_profiles[i] + .cn_service_auth->subscribed_media_profile_id); + } + for(j = 0; j < s->service_profiles[i].shared_ifc_set_cnt; j++) { + LM_DBG("\t\tShared IFC Set: [%d]\n", + s->service_profiles[i].shared_ifc_set[j]); + } + } } -str cscf_get_realm_from_ruri(struct sip_msg *msg) { - str realm = { 0, 0 }; - if (!msg || msg->first_line.type != SIP_REQUEST) { +str cscf_get_realm_from_ruri(struct sip_msg *msg) +{ + str realm = {0, 0}; + if(!msg || msg->first_line.type != SIP_REQUEST) { LM_ERR("This is not a request!!!\n"); return realm; } - if (!msg->parsed_orig_ruri_ok) - if (parse_orig_ruri(msg) < 0) + if(!msg->parsed_orig_ruri_ok) + if(parse_orig_ruri(msg) < 0) return realm; realm = msg->parsed_orig_ruri.host; diff --git a/src/modules/ims_registrar_scscf/userdata_parser.h b/src/modules/ims_registrar_scscf/userdata_parser.h index 3544bdc64f5..d511cddee85 100644 --- a/src/modules/ims_registrar_scscf/userdata_parser.h +++ b/src/modules/ims_registrar_scscf/userdata_parser.h @@ -41,7 +41,7 @@ */ #ifndef USERDATA_PARSER_H -#define USERDATA_PARSER_H +#define USERDATA_PARSER_H #include "../../modules/ims_usrloc_scscf/usrloc.h" #include @@ -62,5 +62,4 @@ int parser_init(char *dtd_filename, char *xsd_filename); ims_subscription *parse_user_data(str xml); void print_user_data(ims_subscription *s); -#endif /* USERDATA_PARSER */ - +#endif /* USERDATA_PARSER */ diff --git a/src/modules/ims_registrar_scscf/usrloc_cb.c b/src/modules/ims_registrar_scscf/usrloc_cb.c index d560704a784..89fc7c03e06 100644 --- a/src/modules/ims_registrar_scscf/usrloc_cb.c +++ b/src/modules/ims_registrar_scscf/usrloc_cb.c @@ -48,55 +48,74 @@ extern str scscf_name_str; -void ul_impu_inserted(impurecord_t* r, ucontact_t* c, int type, void* param) { +void ul_impu_inserted(impurecord_t *r, ucontact_t *c, int type, void *param) +{ - LM_DBG("Received notification of UL IMPU insert for IMPU <%.*s>\n", r->public_identity.len, r->public_identity.s); + LM_DBG("Received notification of UL IMPU insert for IMPU <%.*s>\n", + r->public_identity.len, r->public_identity.s); - LM_DBG("Registering for callbacks on this IMPU for contact insert, update, delete or expire to send notifications if there are any subscriptions\n"); - ul.register_ulcb(r, 0, UL_IMPU_NEW_CONTACT, ul_contact_changed, 0); //this allows us to receive cbs on new contact for IMPU - ul.register_ulcb(r, 0, UL_IMPU_UPDATE_CONTACT | UL_IMPU_EXPIRE_CONTACT | UL_IMPU_DELETE_CONTACT | UL_IMPU_DELETE_CONTACT_IMPLICIT, ul_contact_changed, 0); + LM_DBG("Registering for callbacks on this IMPU for contact insert, update, " + "delete or expire to send notifications if there are any " + "subscriptions\n"); + ul.register_ulcb(r, 0, UL_IMPU_NEW_CONTACT, ul_contact_changed, + 0); //this allows us to receive cbs on new contact for IMPU + ul.register_ulcb(r, 0, + UL_IMPU_UPDATE_CONTACT | UL_IMPU_EXPIRE_CONTACT + | UL_IMPU_DELETE_CONTACT | UL_IMPU_DELETE_CONTACT_IMPLICIT, + ul_contact_changed, 0); - LM_DBG("Selectively asking for expire or no contact delete callbacks only on the anchor of the implicit set so that we only send one SAR per implicit set\n"); - if (r->is_primary) { - //TODO only do this if a flag in the IMPU record identifies this as the implicit set anchor - if (ul.register_ulcb(r, 0, UL_IMPU_REG_NC_DELETE | UL_IMPU_UNREG_EXPIRED, ul_impu_removed, 0) < 0) { - LM_ERR("can not register callback for no contacts delete or IMPI expire\n"); - return; - } - } + LM_DBG("Selectively asking for expire or no contact delete callbacks only " + "on the anchor of the implicit set so that we only send one SAR per " + "implicit set\n"); + if(r->is_primary) { + //TODO only do this if a flag in the IMPU record identifies this as the implicit set anchor + if(ul.register_ulcb(r, 0, UL_IMPU_REG_NC_DELETE | UL_IMPU_UNREG_EXPIRED, + ul_impu_removed, 0) + < 0) { + LM_ERR("can not register callback for no contacts delete or IMPI " + "expire\n"); + return; + } + } } -void ul_impu_removed(impurecord_t* r, ucontact_t* c, int type, void* param) { - int assignment_type = AVP_IMS_SAR_USER_DEREGISTRATION; - int data_available = AVP_IMS_SAR_USER_DATA_NOT_AVAILABLE; +void ul_impu_removed(impurecord_t *r, ucontact_t *c, int type, void *param) +{ + int assignment_type = AVP_IMS_SAR_USER_DEREGISTRATION; + int data_available = AVP_IMS_SAR_USER_DATA_NOT_AVAILABLE; - //we only send SAR if the REGISTRATION state is (NOT) IMPU_NOT_REGISTERED and if send_sar_on_delete is set - //send_sar_on_delete is set by default - only unset if impu is deleted due to explicit dereg - LM_DBG("Received notification of UL IMPU removed for IMPU <%.*s>\n", r->public_identity.len, r->public_identity.s); + //we only send SAR if the REGISTRATION state is (NOT) IMPU_NOT_REGISTERED and if send_sar_on_delete is set + //send_sar_on_delete is set by default - only unset if impu is deleted due to explicit dereg + LM_DBG("Received notification of UL IMPU removed for IMPU <%.*s>\n", + r->public_identity.len, r->public_identity.s); - if (r->reg_state != IMPU_NOT_REGISTERED && r->send_sar_on_delete) { - LM_DBG("Sending SAR to DeRegister [%.*s] (pvt: <%.*s>)\n", - r->public_identity.len, r->public_identity.s, - r->s->private_identity.len, r->s->private_identity.s); - LM_DBG("Sending SAR\n"); - cxdx_send_sar(NULL, r->public_identity, r->s->private_identity, scscf_name_str, assignment_type, data_available, 0); - } + if(r->reg_state != IMPU_NOT_REGISTERED && r->send_sar_on_delete) { + LM_DBG("Sending SAR to DeRegister [%.*s] (pvt: <%.*s>)\n", + r->public_identity.len, r->public_identity.s, + r->s->private_identity.len, r->s->private_identity.s); + LM_DBG("Sending SAR\n"); + cxdx_send_sar(NULL, r->public_identity, r->s->private_identity, + scscf_name_str, assignment_type, data_available, 0); + } } -void ul_contact_changed(impurecord_t* r, ucontact_t* c, int type, void* param) { +void ul_contact_changed(impurecord_t *r, ucontact_t *c, int type, void *param) +{ - LM_DBG("Received notification of type %d on contact Address <%.*s>\n", type, c->c.len, c->c.s); - - if(!r->shead) { - LM_DBG("There are no subscriptions for this IMPU therefore breaking out now as nothing to do\n"); - return; - } -// - if (type == UL_IMPU_DELETE_CONTACT) { - LM_DBG("Received notification of UL CONTACT DELETE\n"); - event_reg(0, r, c, IMS_REGISTRAR_CONTACT_UNREGISTERED, 0, 0, 0, 0, 0); - } else if (type == UL_IMPU_EXPIRE_CONTACT) { - LM_DBG("Received notification of UL CONTACT EXPIRED\n"); - event_reg(0, r, c, IMS_REGISTRAR_CONTACT_EXPIRED, 0, 0, 0, 0, 0); - } + LM_DBG("Received notification of type %d on contact Address <%.*s>\n", type, + c->c.len, c->c.s); + + if(!r->shead) { + LM_DBG("There are no subscriptions for this IMPU therefore breaking " + "out now as nothing to do\n"); + return; + } + // + if(type == UL_IMPU_DELETE_CONTACT) { + LM_DBG("Received notification of UL CONTACT DELETE\n"); + event_reg(0, r, c, IMS_REGISTRAR_CONTACT_UNREGISTERED, 0, 0, 0, 0, 0); + } else if(type == UL_IMPU_EXPIRE_CONTACT) { + LM_DBG("Received notification of UL CONTACT EXPIRED\n"); + event_reg(0, r, c, IMS_REGISTRAR_CONTACT_EXPIRED, 0, 0, 0, 0, 0); + } } diff --git a/src/modules/ims_registrar_scscf/usrloc_cb.h b/src/modules/ims_registrar_scscf/usrloc_cb.h index 486274352e6..a63618d613f 100644 --- a/src/modules/ims_registrar_scscf/usrloc_cb.h +++ b/src/modules/ims_registrar_scscf/usrloc_cb.h @@ -41,15 +41,14 @@ */ #ifndef USRLOC_CB_H -#define USRLOC_CB_H +#define USRLOC_CB_H #include "../ims_usrloc_scscf/usrloc.h" -void ul_impu_removed(impurecord_t* r, ucontact_t* c, int type, void* param); +void ul_impu_removed(impurecord_t *r, ucontact_t *c, int type, void *param); -void ul_impu_inserted(impurecord_t* r, ucontact_t* c, int type, void* param); +void ul_impu_inserted(impurecord_t *r, ucontact_t *c, int type, void *param); -void ul_contact_changed(impurecord_t* r, ucontact_t* c, int type, void* param); - -#endif /* USRLOC_CB_H */ +void ul_contact_changed(impurecord_t *r, ucontact_t *c, int type, void *param); +#endif /* USRLOC_CB_H */