Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 819283c

Browse files
committedJun 23, 2023
[uac_registrant] New parameter to match reply Contact with binding_URI
Added new string module parameter 'match_contact' to choose, what parts of URI from Contact header should match binding_URI when OpenSIPS chooses expiration time for registration.
1 parent f69b150 commit 819283c

File tree

4 files changed

+212
-2
lines changed

4 files changed

+212
-2
lines changed
 

‎modules/uac_registrant/doc/uac_registrant_admin.xml

+41
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,47 @@ modparam("uac_registrant", "enable_clustering", 1)
181181
</example>
182182
</section>
183183

184+
<section id="param_match_contact" xreflabel="match_contact">
185+
<title><varname>match_contact</varname> (string)</title>
186+
<para>
187+
A list of URI parts delimited by ';'.
188+
This parameter lets you select which parts of the URI from the Contact
189+
header of the 200 OK reply should match the binding_URI.
190+
The module compares the Contact header with the binding_URI when it
191+
receives a 200 OK reply to the REGISTER request. If they match,
192+
it uses the expiration time given in the reply.
193+
The default behavior is to compare the entire URI.
194+
</para>
195+
<para>Possible URI parts for matching:</para>
196+
<para>
197+
<itemizedlist>
198+
<listitem><para>type</para></listitem>
199+
<listitem><para>user</para></listitem>
200+
<listitem><para>host</para></listitem>
201+
<listitem><para>port</para></listitem>
202+
<listitem><para>transport</para></listitem>
203+
<listitem><para>ttl</para></listitem>
204+
<listitem><para>userparam</para></listitem>
205+
<listitem><para>maddr</para></listitem>
206+
<listitem><para>method</para></listitem>
207+
<listitem><para>all</para></listitem>
208+
</itemizedlist>
209+
</para>
210+
<para>
211+
<emphasis>
212+
Default value is "all".
213+
</emphasis>
214+
</para>
215+
<example>
216+
<title>Set <varname>match_contact</varname> parameter</title>
217+
<programlisting format="linespecific">
218+
...
219+
modparam("uac_registrant", "match_contact", "type;user")
220+
...
221+
</programlisting>
222+
</example>
223+
</section>
224+
184225
<section id="param_db_url" xreflabel="db_url">
185226
<title><varname>db_url</varname> (string)</title>
186227
<para>

‎modules/uac_registrant/registrant.c

+9-2
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ uac_auth_api_t uac_auth_api;
110110

111111
unsigned int default_expires = 3600;
112112
unsigned int timer_interval = 100;
113+
enum uri_match_flags match_contact = URI_MATCH_NONE;
114+
str match_contact_str = str_init("all");
113115

114116
reg_table_t reg_htable = NULL;
115117
unsigned int reg_hsize = 1;
@@ -140,6 +142,7 @@ static const param_export_t params[]= {
140142
{"default_expires", INT_PARAM, &default_expires},
141143
{"timer_interval", INT_PARAM, &timer_interval},
142144
{"enable_clustering", INT_PARAM, &enable_clustering},
145+
{"match_contact", STR_PARAM, &match_contact_str.s},
143146
{"db_url", STR_PARAM, &db_url.s},
144147
{"table_name", STR_PARAM, &reg_table_name.s},
145148
{"registrar_column", STR_PARAM, &registrar_column.s},
@@ -258,6 +261,11 @@ static int mod_init(void)
258261
return -1;
259262
}
260263

264+
if(match_contact_str.s) {
265+
match_contact = parse_uri_options(&match_contact_str);
266+
}
267+
LM_DBG("Match contact value: [%d]\n", (unsigned)match_contact);
268+
261269
reg_table_name.len = strlen(reg_table_name.s);
262270
registrar_column.len = strlen(registrar_column.s);
263271
proxy_column.len = strlen(proxy_column.s);
@@ -481,8 +489,7 @@ int run_reg_tm_cback(void *e_data, void *data, void *r_data)
481489
contact = ((contact_body_t*)msg->contact->parsed)->contacts;
482490
while (contact) {
483491
/* Check for binding */
484-
if (contact->uri.len==rec->contact_uri.len &&
485-
strncmp(contact->uri.s,rec->contact_uri.s,contact->uri.len)==0){
492+
if (compare_uris_parts(&contact->uri, &rec->contact_uri, match_contact) == 0) {
486493
if (contact->expires && contact->expires->body.len) {
487494
if (str2int(&contact->expires->body, &exp)<0) {
488495
LM_ERR("Unable to extract expires from [%.*s]"

‎parser/parse_uri.c

+132
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,52 @@ static const str uri_type_names[7] = {
5353
str_init("urn:nena:service")
5454
};
5555

56+
struct uri_match_part uri_match_parts[] = {
57+
{ str_const_init("type"), URI_MATCH_TYPE },
58+
{ str_const_init("user"), URI_MATCH_USER },
59+
{ str_const_init("password"), URI_MATCH_PASSWD },
60+
{ str_const_init("host"), URI_MATCH_HOST },
61+
{ str_const_init("port"), URI_MATCH_PORT },
62+
{ str_const_init("transport"), URI_MATCH_TRANSPORT },
63+
{ str_const_init("ttl"), URI_MATCH_TTL },
64+
{ str_const_init("userparam"), URI_MATCH_USERPARAM },
65+
{ str_const_init("maddr"), URI_MATCH_MADDR },
66+
{ str_const_init("method"), URI_MATCH_METHOD },
67+
{ str_const_init("lr"), URI_MATCH_LR },
68+
{ str_const_init("r2"), URI_MATCH_R2 },
69+
{ str_const_init("all"), URI_MATCH_ALL },
70+
};
71+
72+
enum uri_match_flags parse_uri_options(str *options_str)
73+
{
74+
enum uri_match_flags flags = URI_MATCH_NONE;
75+
char *p, *e;
76+
str *s = options_str;
77+
int i;
78+
79+
if (options_str == NULL || options_str->s == NULL || options_str->len == 0) {
80+
return flags;
81+
}
82+
e = s->s + strlen(s->s);
83+
while (s->s < e) {
84+
p = strchr(s->s, ';');
85+
s->len = (p ? (p - s->s) : strlen(s->s));
86+
str_trim_spaces_lr(*s);
87+
/* check if this is among the possible options */
88+
for(i = 0; i< (sizeof(uri_match_parts)/sizeof(uri_match_parts[0])); i++) {
89+
if (s->len == uri_match_parts[i].name.len &&
90+
strncasecmp(s->s, uri_match_parts[i].name.s,
91+
uri_match_parts[i].name.len) == 0)
92+
flags |= uri_match_parts[i].flag;
93+
}
94+
if (p)
95+
s->s = p + 1;
96+
else
97+
break;
98+
}
99+
return flags;
100+
}
101+
56102
char* uri_type2str(const uri_type type, char *result)
57103
{
58104
if (type == ERROR_URI_T)
@@ -1855,3 +1901,89 @@ int compare_uris(str *raw_uri_a,struct sip_uri* parsed_uri_a,
18551901
compare_uri_val(headers,strncasecmp);
18561902
return 0;
18571903
}
1904+
1905+
/* Compare 2 SIP URIs by parts according to opts
1906+
*
1907+
* Return value : 0 if URIs match
1908+
* 1 if URIs don't match
1909+
* -1 if errors have occurred
1910+
*/
1911+
int compare_uris_parts(str *raw_uri_a, str *raw_uri_b, enum uri_match_flags opts)
1912+
{
1913+
#define UNESCAPED_BUF_LEN 1024
1914+
char unescaped_a[UNESCAPED_BUF_LEN], unescaped_b[UNESCAPED_BUF_LEN];
1915+
1916+
str unescaped_userA={unescaped_a, UNESCAPED_BUF_LEN};
1917+
str unescaped_userB={unescaped_b, UNESCAPED_BUF_LEN};
1918+
1919+
struct sip_uri first;
1920+
struct sip_uri second;
1921+
1922+
if ( (!raw_uri_a) || (!raw_uri_b) )
1923+
{
1924+
LM_ERR("Provide either a raw form of a SIP URI\n");
1925+
return -1;
1926+
}
1927+
1928+
/* maybe we're lucky and straight-forward comparison succeeds */
1929+
if ((opts & URI_MATCH_ALL) && (raw_uri_a->len == raw_uri_b->len))
1930+
if (strncasecmp(raw_uri_a->s,raw_uri_b->s,raw_uri_a->len) == 0)
1931+
{
1932+
LM_DBG("straight-forward URI match\n");
1933+
return 0;
1934+
}
1935+
1936+
if (parse_uri(raw_uri_a->s,raw_uri_a->len,&first) < 0)
1937+
{
1938+
LM_ERR("Failed to parse first URI\n");
1939+
return -1;
1940+
}
1941+
1942+
if (parse_uri(raw_uri_b->s,raw_uri_b->len,&second) < 0)
1943+
{
1944+
LM_ERR("Failed to parse second URI\n");
1945+
return -1;
1946+
}
1947+
1948+
if (opts & URI_MATCH_TYPE)
1949+
if (first.type != second.type)
1950+
{
1951+
LM_DBG("Different uri types\n");
1952+
return 1;
1953+
}
1954+
1955+
if (unescape_user(&first.user, &unescaped_userA) < 0 ||
1956+
unescape_user(&second.user, &unescaped_userB) < 0) {
1957+
LM_ERR("Failed to unescape user!\n");
1958+
return -1;
1959+
}
1960+
1961+
first.user = unescaped_userA;
1962+
second.user = unescaped_userB;
1963+
1964+
if (opts & URI_MATCH_USER)
1965+
compare_uri_val(user,strncmp);
1966+
if (opts & URI_MATCH_PASSWD)
1967+
compare_uri_val(passwd,strncmp);
1968+
if (opts & URI_MATCH_HOST)
1969+
compare_uri_val(host,strncasecmp);
1970+
if (opts & URI_MATCH_PORT)
1971+
compare_uri_val(port,strncmp);
1972+
1973+
if (opts & URI_MATCH_TRANSPORT)
1974+
compare_uri_val(transport_val,strncasecmp);
1975+
if (opts & URI_MATCH_TTL)
1976+
compare_uri_val(ttl_val,strncasecmp);
1977+
if (opts & URI_MATCH_USERPARAM)
1978+
compare_uri_val(user_param_val,strncasecmp);
1979+
if (opts & URI_MATCH_MADDR)
1980+
compare_uri_val(maddr_val,strncasecmp);
1981+
if (opts & URI_MATCH_METHOD)
1982+
compare_uri_val(method_val,strncasecmp);
1983+
if (opts & URI_MATCH_LR)
1984+
compare_uri_val(lr_val,strncasecmp);
1985+
if (opts & URI_MATCH_R2)
1986+
compare_uri_val(r2_val,strncasecmp);
1987+
1988+
return 0;
1989+
}

‎parser/parse_uri.h

+30
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,35 @@
4242
#define URN_NENA_SERVICE_STR ":nena:service:"
4343
#define URN_NENA_SERVICE_STR_LEN (sizeof(URN_NENA_SERVICE_STR) - 1)
4444

45+
/* The possible values of the URI parts used for compare URIs
46+
*/
47+
enum uri_match_flags {
48+
URI_MATCH_NONE = 0,
49+
URI_MATCH_TYPE = (1<<0),
50+
URI_MATCH_USER = (1<<1),
51+
URI_MATCH_PASSWD = (1<<2),
52+
URI_MATCH_HOST = (1<<3),
53+
URI_MATCH_PORT = (1<<4),
54+
URI_MATCH_TRANSPORT = (1<<5),
55+
URI_MATCH_TTL = (1<<6),
56+
URI_MATCH_USERPARAM = (1<<7),
57+
URI_MATCH_MADDR = (1<<8),
58+
URI_MATCH_METHOD = (1<<9),
59+
URI_MATCH_LR = (1<<10),
60+
URI_MATCH_R2 = (1<<11),
61+
URI_MATCH_ALL = (URI_MATCH_TYPE | URI_MATCH_USER | URI_MATCH_PASSWD | URI_MATCH_HOST | URI_MATCH_PORT | URI_MATCH_TRANSPORT |
62+
URI_MATCH_TTL | URI_MATCH_USERPARAM | URI_MATCH_MADDR | URI_MATCH_METHOD | URI_MATCH_LR | URI_MATCH_R2),
63+
};
64+
struct uri_match_part {
65+
str_const name;
66+
enum uri_match_flags flag;
67+
};
68+
69+
/* options_str= options to match Contact URI for uac_registrant
70+
* returns: binary flags to match URI
71+
*/
72+
enum uri_match_flags parse_uri_options(str *options_str);
73+
4574
/* buf= pointer to beginning of uri (sip:x@foo.bar:5060;a=b?h=i)
4675
* len= len of uri
4776
* returns: fills uri & returns <0 on error or 0 if ok
@@ -69,6 +98,7 @@ int parse_sip_msg_uri(struct sip_msg* msg);
6998
int parse_orig_ruri(struct sip_msg* msg);
7099
int compare_uris(str *raw_uri_a,struct sip_uri* parsed_uri_a,
71100
str *raw_uri_b,struct sip_uri *parsed_uri_b);
101+
int compare_uris_parts(str *raw_uri_a, str *raw_uri_b, enum uri_match_flags opts);
72102
static inline int get_uri_param_val(const struct sip_uri *uri,
73103
const str *param, str *val);
74104
static inline int get_uri_param_idx(const str *param,

0 commit comments

Comments
 (0)
Please sign in to comment.