diff --git a/modules/registrar/doc/registrar_admin.xml b/modules/registrar/doc/registrar_admin.xml index 53693ef9e98..65969ed94aa 100644 --- a/modules/registrar/doc/registrar_admin.xml +++ b/modules/registrar/doc/registrar_admin.xml @@ -658,6 +658,11 @@ modparam("registrar", "path_check_local", 1)
<varname>reg_callid_avp</varname> (string) + + + obsolete. use match_option in registered function + + If reg_callid_avp is defined and populated when the registered() is invoked, the result is @@ -1102,7 +1107,7 @@ lookup_branches("location");
- <function moreinfo="none">registered(domain [, uri])</function> + <function moreinfo="none">registered(domain [, uri [, match_option [, match_action]]])</function> The function returns true if the AOR in the Request-URI is @@ -1124,6 +1129,35 @@ lookup_branches("location"); of R-URI. It can be a dynamic string with pseudo-variables. + + + match_option (optional) - flag parameter to restrict + contact search. use reg_xavp_cfg to set the values to compare to. + + flag values is as follows: + + + 1 - match_callid + + + 2 - match_received + + + 4 - match_contact + + + + + + match_action (optional) - actions to perform when match is positive. + + flag values is as follows: + + + 1 - set xavp_rcd with value from matched contact + + + This function can be used from REQUEST_ROUTE, FAILURE_ROUTE. @@ -1137,6 +1171,13 @@ if (registered("location")) { ... }; ... +$xavp(regcfg=>match_received) = $su; +if (registered("location","$rz:$Au", 2)) { + sl_send_reply("100", "Trying"); + ... +}; +... +
diff --git a/modules/registrar/lookup.c b/modules/registrar/lookup.c index 6468e54047a..1a35edabb65 100644 --- a/modules/registrar/lookup.c +++ b/modules/registrar/lookup.c @@ -619,13 +619,24 @@ int lookup_branches(sip_msg_t *msg, udomain_t *d) * it is similar to lookup but registered neither rewrites * the Request-URI nor appends branches */ -int registered(struct sip_msg* _m, udomain_t* _d, str* _uri) +int registered(struct sip_msg* _m, udomain_t* _d, str* _uri) { + return registered4(_m, _d, _uri, 0, 0); +} + +int registered3(struct sip_msg* _m, udomain_t* _d, str* _uri, int match_flag) { + return registered4(_m, _d, _uri, match_flag, 0); +} + +int registered4(struct sip_msg* _m, udomain_t* _d, str* _uri, int match_flag, int match_action_flag) { str uri, aor; urecord_t* r; ucontact_t* ptr; int res; - int_str match_callid=(int_str)0; + str match_callid = {0,0}; + str match_received = {0,0}; + str match_contact = {0,0}; + sr_xavp_t *vavp = NULL; if(_uri!=NULL) { @@ -650,26 +661,61 @@ int registered(struct sip_msg* _m, udomain_t* _d, str* _uri) } if (res == 0) { - - if (reg_callid_avp_name.n) { - struct usr_avp *avp = - search_first_avp( reg_callid_avp_type, reg_callid_avp_name, &match_callid, 0); - if (!(avp && is_avp_str_val(avp))) - match_callid.n = 0; - match_callid.s.s = NULL; - } else { - match_callid.n = 0; - match_callid.s.s = NULL; + LM_DBG("searching with match flags (%d,%d)\n", match_flag, reg_match_flag_param); + if(reg_xavp_cfg.s!=NULL) { + + if((match_flag & 1) + && (vavp = xavp_get_child_with_sval(®_xavp_cfg, &match_callid_name)) != NULL + && vavp->val.v.s.len > 0) { + match_callid = vavp->val.v.s; + LM_DBG("matching with callid %.*s\n", match_callid.len, match_callid.s); + } + + if((match_flag & 2) + && (vavp = xavp_get_child_with_sval(®_xavp_cfg, &match_received_name)) != NULL + && vavp->val.v.s.len > 0) { + match_received = vavp->val.v.s; + LM_DBG("matching with received %.*s\n", match_received.len, match_received.s); + } + + if((match_flag & 4) + && (vavp = xavp_get_child_with_sval(®_xavp_cfg, &match_contact_name)) != NULL + && vavp->val.v.s.len > 0) { + match_contact = vavp->val.v.s; + LM_DBG("matching with contact %.*s\n", match_contact.len, match_contact.s); + } } for (ptr = r->contacts; ptr; ptr = ptr->next) { if(!VALID_CONTACT(ptr, act_time)) continue; - if (match_callid.s.s && /* optionally enforce tighter matching w/ Call-ID */ - memcmp(match_callid.s.s,ptr->callid.s,match_callid.s.len)) + if (match_callid.s && /* optionally enforce tighter matching w/ Call-ID */ + match_callid.len > 0 && + (match_callid.len != ptr->callid.len || + memcmp(match_callid.s, ptr->callid.s, match_callid.len))) + continue; + if (match_received.s && /* optionally enforce tighter matching w/ ip:port */ + match_received.len > 0 && + (match_received.len != ptr->received.len || + memcmp(match_received.s, ptr->received.s, match_received.len))) continue; + if (match_contact.s && /* optionally enforce tighter matching w/ Contact */ + match_contact.len > 0 && + (match_contact.len != ptr->c.len || + memcmp(match_contact.s, ptr->c.s, match_contact.len))) + continue; + + if(ptr->xavp!=NULL && match_action_flag == 1) { + sr_xavp_t *xavp = xavp_clone_level_nodata(ptr->xavp); + if(xavp_add(xavp, NULL)<0) { + LM_ERR("error adding xavp for %.*s after successful match\n", aor.len, ZSW(aor.s)); + xavp_destroy_list(&xavp); + } + } + ul.release_urecord(r); ul.unlock_udomain(_d, &aor); LM_DBG("'%.*s' found in usrloc\n", aor.len, ZSW(aor.s)); + return 1; } } diff --git a/modules/registrar/lookup.h b/modules/registrar/lookup.h index 1e77bfeb7b1..035b8180b46 100644 --- a/modules/registrar/lookup.h +++ b/modules/registrar/lookup.h @@ -67,6 +67,7 @@ int lookup_branches(sip_msg_t *msg, udomain_t *d); * the Request-URI nor appends branches */ int registered(struct sip_msg* _m, udomain_t* _d, str* _uri); - +int registered3(struct sip_msg* _m, udomain_t* _d, str* _uri, int match_flag); +int registered4(struct sip_msg* _m, udomain_t* _d, str* _uri, int match_flag, int match_action_flag); #endif /* LOOKUP_H */ diff --git a/modules/registrar/reg_mod.c b/modules/registrar/reg_mod.c index 437883cc6c9..a9aceb1f61a 100644 --- a/modules/registrar/reg_mod.c +++ b/modules/registrar/reg_mod.c @@ -101,10 +101,9 @@ int reg_outbound_mode = 0; int reg_regid_mode = 0; int reg_flow_timer = 0; -/* Populate this AVP if testing for specific registration instance. */ -char *reg_callid_avp_param = 0; -unsigned short reg_callid_avp_type = 0; -int_str reg_callid_avp_name; +str match_callid_name = str_init("match_callid"); +str match_received_name = str_init("match_received"); +str match_contact_name = str_init("match_contact"); char* rcv_avp_param = 0; unsigned short rcv_avp_type = 0; @@ -164,6 +163,10 @@ static cmd_export_t cmds[] = { REQUEST_ROUTE | FAILURE_ROUTE }, {"registered", (cmd_function)w_registered, 2, domain_uri_fixup, 0, REQUEST_ROUTE | FAILURE_ROUTE }, + {"registered", (cmd_function)w_registered3, 3, registered_fixup, 0, + REQUEST_ROUTE | FAILURE_ROUTE }, + {"registered", (cmd_function)w_registered4, 4, registered_fixup, 0, + REQUEST_ROUTE | FAILURE_ROUTE }, {"add_sock_hdr", (cmd_function)add_sock_hdr, 1, fixup_str_null, 0, REQUEST_ROUTE }, {"unregister", (cmd_function)w_unregister, 2, unreg_fixup, 0, @@ -200,7 +203,6 @@ static param_export_t params[] = { {"max_expires", INT_PARAM, &default_registrar_cfg.max_expires }, {"received_param", PARAM_STR, &rcv_param }, {"received_avp", PARAM_STRING, &rcv_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 }, @@ -209,7 +211,7 @@ static param_export_t params[] = { {"use_path", INT_PARAM, &path_enabled }, {"path_mode", INT_PARAM, &path_mode }, {"path_use_received", INT_PARAM, &path_use_params }, - {"path_check_local", INT_PARAM, &path_check_local }, + {"path_check_local", INT_PARAM, &path_check_local }, {"xavp_cfg", PARAM_STR, ®_xavp_cfg }, {"xavp_rcd", PARAM_STR, ®_xavp_rcd }, {"gruu_enabled", INT_PARAM, ®_gruu_enabled }, @@ -306,24 +308,6 @@ static int mod_init(void) rcv_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"); @@ -488,6 +472,46 @@ static int w_registered(struct sip_msg* _m, char* _d, char* _uri) return registered(_m, (udomain_t*)_d, (uri.len>0)?&uri:NULL); } +static int w_registered3(struct sip_msg* _m, char* _d, char* _uri, char* _flags) +{ + str uri = {0}; + int flags = 0; + if(_uri!=NULL && (fixup_get_svalue(_m, (gparam_p)_uri, &uri)!=0 || uri.len<=0)) + { + LM_ERR("invalid uri parameter\n"); + return -1; + } + if(_flags!=NULL && (fixup_get_ivalue(_m, (fparam_t*)_flags, &flags)) < 0) + { + LM_ERR("invalid flags parameter\n"); + return -1; + } + return registered3(_m, (udomain_t*)_d, (uri.len>0)?&uri:NULL, flags); +} + +static int w_registered4(struct sip_msg* _m, char* _d, char* _uri, char* _flags, char* _actionflags) +{ + str uri = {0}; + int flags = 0; + int actionflags = 0; + if(_uri!=NULL && (fixup_get_svalue(_m, (gparam_p)_uri, &uri)!=0 || uri.len<=0)) + { + LM_ERR("invalid uri parameter\n"); + return -1; + } + if(_flags!=NULL && (fixup_get_ivalue(_m, (fparam_t*)_flags, &flags)) < 0) + { + LM_ERR("invalid flags parameter\n"); + return -1; + } + if(_actionflags!=NULL && (fixup_get_ivalue(_m, (fparam_t*)_actionflags, &actionflags)) < 0) + { + LM_ERR("invalid action flag parameter\n"); + return -1; + } + return registered4(_m, (udomain_t*)_d, (uri.len>0)?&uri:NULL, flags, actionflags); +} + static int w_unregister(struct sip_msg* _m, char* _d, char* _uri) { str uri = {0}; @@ -550,6 +574,19 @@ static int domain_uri_fixup(void** param, int param_no) return 0; } +static int registered_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_igp_null(param, 1); + } else if (param_no == 4) { + return fixup_igp_null(param, 1); + } + return 0; +} /*! \brief * Convert char* parameter to udomain_t* pointer diff --git a/modules/registrar/reg_mod.h b/modules/registrar/reg_mod.h index 892a60668d5..8fd0ccb2454 100644 --- a/modules/registrar/reg_mod.h +++ b/modules/registrar/reg_mod.h @@ -74,8 +74,10 @@ extern float def_q; extern unsigned short rcv_avp_type; extern int_str rcv_avp_name; -extern unsigned short reg_callid_avp_type; -extern int_str reg_callid_avp_name; + +extern str match_callid_name; +extern str match_received_name; +extern str match_contact_name; extern str rcv_param; extern int method_filtering;