Skip to content

Commit 8bc32a5

Browse files
committed
fix: sip route/record-route uri parse error
1 parent 043853e commit 8bc32a5

7 files changed

+160
-11
lines changed

libsip/include/sip-header.h

+4
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,10 @@ int sip_header_vias(const char* s, const char* end, struct sip_vias_t* vias);
189189
int sip_via_write(const struct sip_via_t* via, char* data, const char* end);
190190
const struct cstring_t* sip_vias_top_branch(const struct sip_vias_t* vias);
191191

192+
int sip_header_route(const char* s, const char* end, struct sip_uri_t* route);
193+
int sip_header_routes(const char* s, const char* end, struct sip_uris_t* route);
194+
int sip_route_write(const struct sip_uri_t* route, char* data, const char* end);
195+
192196
int sip_header_contact(const char* s, const char* end, struct sip_contact_t* contact);
193197
int sip_header_contacts(const char* s, const char* end, struct sip_contacts_t* contacts);
194198
int sip_contact_write(const struct sip_contact_t* contact, char* data, const char* end);

libsip/libsip.vcxproj

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
<ClCompile Include="src\header\sip-header-contact.c" />
3737
<ClCompile Include="src\header\sip-header-param.c" />
3838
<ClCompile Include="src\header\sip-header-cseq.c" />
39+
<ClCompile Include="src\header\sip-header-route.c" />
3940
<ClCompile Include="src\header\sip-header-substate.c" />
4041
<ClCompile Include="src\header\sip-header-uri.c" />
4142
<ClCompile Include="src\header\sip-header-via.c" />

libsip/libsip.vcxproj.filters

+3
Original file line numberDiff line numberDiff line change
@@ -173,5 +173,8 @@
173173
<ClCompile Include="src\uas\sip-uas-prack.c">
174174
<Filter>Source Files\uas</Filter>
175175
</ClCompile>
176+
<ClCompile Include="src\header\sip-header-route.c">
177+
<Filter>SIP Header</Filter>
178+
</ClCompile>
176179
</ItemGroup>
177180
</Project>

libsip/src/header/sip-header-route.c

+140
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
// RFC3261 20.30 Record-Route / 20.43 Route
2+
// Record-Route: <sip:p1.example.com;lr>
3+
// Route: <sip:p1.example.com;lr>,<sip:p2.domain.com;lr>
4+
5+
/*
6+
Record-Route = "Record-Route" HCOLON rec-route *(COMMA rec-route)
7+
rec-route = name-addr *( SEMI rr-param )
8+
rr-param = generic-param
9+
Route = "Route" HCOLON route-param *(COMMA route-param)
10+
route-param = name-addr *( SEMI rr-param )
11+
name-addr = [ display-name ] LAQUOT addr-spec RAQUOT
12+
addr-spec = SIP-URI / SIPS-URI / absoluteURI
13+
*/
14+
15+
#include "sip-header.h"
16+
#include <stdlib.h>
17+
#include <ctype.h>
18+
19+
int sip_header_route(const char* s, const char* end, struct sip_uri_t* uri)
20+
{
21+
const char* p;
22+
23+
p = (s && s < end) ? strpbrk(s, "<\"") : NULL;
24+
if (!p || p > end)
25+
{
26+
// addr-spec only
27+
return sip_header_uri(s, end, uri);
28+
}
29+
30+
if ('"' == *p)
31+
{
32+
// name-addr: [ display-name ]
33+
p = strchr(p + 1, '"');
34+
if (!p || p > end)
35+
return -EINVAL;
36+
37+
// LAQUOT addr-spec RAQUOT
38+
p = strchr(p + 1, '<');
39+
if (!p || p > end)
40+
return -EINVAL;
41+
}
42+
43+
if ('<' == *p)
44+
{
45+
s = p + 1;
46+
p = s < end ? strchr(s, '>') : NULL;
47+
if (!p || p > end)
48+
return -EINVAL;
49+
}
50+
51+
return sip_header_uri(s, p, uri);
52+
}
53+
54+
int sip_header_routes(const char* s, const char* end, struct sip_uris_t* routes)
55+
{
56+
int r;
57+
const char* p;
58+
struct sip_uri_t c;
59+
60+
for (r = 0; 0 == r && s && s < end; s = p + 1)
61+
{
62+
// filter ","
63+
p = strpbrk(s, ",\"");
64+
while (p && p + 1 < end && '"' == *p)
65+
{
66+
p = strchr(p + 1, '"');
67+
if (p && p < end)
68+
p = strpbrk(p + 1, ",\"");
69+
}
70+
if (!p || p >= end)
71+
p = end;
72+
73+
r = sip_header_route(s, p, &c);
74+
if (0 == r)
75+
r = sip_uris_push(routes, &c);
76+
}
77+
78+
return r;
79+
}
80+
81+
// Route: <sip:p1.example.com;lr>,<sip:p2.domain.com;lr>
82+
int sip_route_write(const struct sip_uri_t* route, char* data, const char* end)
83+
{
84+
int n;
85+
char* p;
86+
87+
p = data;
88+
if (p < end) *p++ = '<';
89+
n = sip_uri_write(route, p, end);
90+
if (n < 0) return n;
91+
p += n;
92+
if (p < end) *p++ = '>';
93+
94+
if (p < end) *p = '\0';
95+
return (int)(p - data);
96+
}
97+
98+
#if defined(DEBUG) || defined(_DEBUG)
99+
void sip_header_route_test(void)
100+
{
101+
char p[1024];
102+
const char* s;
103+
const struct sip_uri_t* c;
104+
struct sip_uri_t route;
105+
struct sip_uris_t routes;
106+
107+
sip_uris_init(&routes);
108+
s = "\"Mr.Watson\" <sip:[email protected]>;q=0.7; expires=3600,\"Mr.Watson\" <mailto:[email protected]> ;q=0.1";
109+
assert(0 == sip_header_routes(s, s + strlen(s), &routes) && 2 == sip_uris_count(&routes));
110+
c = sip_uris_get(&routes, 0);
111+
assert(0 == cstrcmp(&c->scheme, "sip") && 0 == cstrcmp(&c->host, "[email protected]") && 0 == sip_params_count(&c->headers) && 0 == sip_params_count(&c->parameters));
112+
c = sip_uris_get(&routes, 1);
113+
assert(0 == cstrcmp(&c->scheme, "mailto") && 0 == cstrcmp(&c->host, "[email protected]") && 0 == sip_params_count(&c->headers) && 0 == sip_params_count(&c->parameters));
114+
sip_uris_free(&routes);
115+
116+
s = "<sips:[email protected]>;expires=60";
117+
assert(0 == sip_header_route(s, s + strlen(s), &route));
118+
assert(0 == cstrcmp(&route.scheme, "sips") && 0 == cstrcmp(&route.host, "[email protected]") && 0 == sip_params_count(&route.headers) && 0 == sip_params_count(&route.parameters));
119+
assert(sip_route_write(&route, p, p + sizeof(p)) < sizeof(p) && 0 == strncmp(s, p, 20));
120+
sip_uri_free(&route);
121+
122+
s = "\"<sip:[email protected]>\" <sip:[email protected]>";
123+
assert(0 == sip_header_route(s, s + strlen(s), &route));
124+
assert(0 == cstrcmp(&route.scheme, "sip") && 0 == cstrcmp(&route.host, "[email protected]") && 0 == sip_params_count(&route.headers) && 0 == sip_params_count(&route.parameters));
125+
assert(sip_route_write(&route, p, p + sizeof(p)) < sizeof(p) && 0 == strcmp(s+20, p));
126+
sip_uri_free(&route);
127+
128+
s = "<sip:p1.example.com;lr>,<sip:p2.domain.com;lr>";
129+
sip_uris_init(&routes);
130+
assert(0 == sip_header_routes(s, s + strlen(s), &routes) && 2 == sip_uris_count(&routes));
131+
c = sip_uris_get(&routes, 0);
132+
assert(0 == cstrcmp(&c->scheme, "sip") && 0 == cstrcmp(&c->host, "p1.example.com") && 0 == sip_params_count(&c->headers) && 1 == sip_params_count(&c->parameters));
133+
assert(0 == cstrcmp(&sip_params_get(&c->parameters, 0)->name, "lr") && c->lr);
134+
c = sip_uris_get(&routes, 1);
135+
assert(0 == cstrcmp(&c->scheme, "sip") && 0 == cstrcmp(&c->host, "p2.domain.com") && 0 == sip_params_count(&c->headers) && 1 == sip_params_count(&c->parameters));
136+
assert(0 == cstrcmp(&sip_params_get(&c->parameters, 0)->name, "lr") && c->lr);
137+
//assert(sip_route_write(c, p, p + sizeof(p)) < sizeof(p) && 0 == strcmp(s, p));
138+
sip_uris_free(&routes);
139+
}
140+
#endif

libsip/src/sip-message.c

+5-11
Original file line numberDiff line numberDiff line change
@@ -567,14 +567,14 @@ static char* sip_message_routers(const struct sip_message_t* msg, char* p, const
567567
for (i = strict_router; i < sip_uris_count((struct sip_uris_t*)&msg->routers) && p < end; i++)
568568
{
569569
if (p < end) p += snprintf(p, end - p, "\r\n%s: ", SIP_HEADER_ROUTE);
570-
if (p < end) p += sip_uri_write(sip_uris_get((struct sip_uris_t*)&msg->routers, i), p, end);
570+
if (p < end) p += sip_route_write(sip_uris_get((struct sip_uris_t*)&msg->routers, i), p, end);
571571
}
572572

573573
// place the remote target URI into the Route header field as the last value
574574
if (strict_router)
575575
{
576576
if (p < end) p += snprintf(p, end - p, "\r\n%s: ", SIP_HEADER_ROUTE);
577-
if (p < end) p += sip_uri_write(&msg->u.c.uri, p, end);
577+
if (p < end) p += sip_route_write(&msg->u.c.uri, p, end);
578578
}
579579

580580
return p;
@@ -630,7 +630,7 @@ int sip_message_write(const struct sip_message_t* msg, uint8_t* data, int bytes)
630630
for (i = 0; i < sip_uris_count((struct sip_uris_t*)&msg->record_routers); i++)
631631
{
632632
if (p < end) p += snprintf(p, end - p, "\r\n%s: ", SIP_HEADER_RECORD_ROUTE);
633-
if (p < end) p += sip_uri_write(sip_uris_get((struct sip_uris_t*)&msg->record_routers, i), p, end);
633+
if (p < end) p += sip_route_write(sip_uris_get((struct sip_uris_t*)&msg->record_routers, i), p, end);
634634
}
635635

636636
// PRACK
@@ -758,17 +758,11 @@ int sip_message_add_header(struct sip_message_t* msg, const char* name, const ch
758758
}
759759
else if (0 == strcasecmp(SIP_HEADER_ROUTE, name))
760760
{
761-
memset(&uri, 0, sizeof(uri));
762-
r = sip_header_uri(header.value.p, header.value.p + header.value.n, &uri);
763-
if (0 == r)
764-
sip_uris_push(&msg->routers, &uri);
761+
r = sip_header_routes(header.value.p, header.value.p + header.value.n, &msg->routers);
765762
}
766763
else if (0 == strcasecmp(SIP_HEADER_RECORD_ROUTE, name))
767764
{
768-
memset(&uri, 0, sizeof(uri));
769-
r = sip_header_uri(header.value.p, header.value.p + header.value.n, &uri);
770-
if (0 == r)
771-
sip_uris_push(&msg->record_routers, &uri);
765+
r = sip_header_routes(header.value.p, header.value.p + header.value.n, &msg->record_routers);
772766
}
773767
else if (0 == strcasecmp(SIP_HEADER_RECV_INFO, name))
774768
{

libsip/test/sip-header-test.c

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ void sip_header_param_test(void);
22
void sip_uri_parse_test(void);
33
void sip_uri_equal_test(void);
44
void sip_header_contact_test(void);
5+
void sip_header_route_test(void);
56
void sip_header_via_test(void);
67
void sip_header_cseq_test(void);
78
void sip_header_substate_test(void);
@@ -13,6 +14,7 @@ void sip_header_test(void)
1314
sip_uri_parse_test();
1415
sip_uri_equal_test();
1516
sip_header_contact_test();
17+
sip_header_route_test();
1618
sip_header_via_test();
1719
sip_header_cseq_test();
1820
sip_header_substate_test();

libsip/test/sip-message-test.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ static int sip_test_invite(struct sip_message_test_t* alice, struct sip_message_
223223
"Max-Forwards: 70\r\n"
224224
"Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8;received=192.0.2.1\r\n"
225225
"Contact: <sip:[email protected]>\r\n"
226+
"Record-Route: <sip:[email protected];lr>\r\n"
226227
"Content-Length: 0\r\n\r\n";
227228

228229
// F8 180 Ringing atlanta.com proxy -> Alice (217)
@@ -234,6 +235,7 @@ static int sip_test_invite(struct sip_message_test_t* alice, struct sip_message_
234235
"Max-Forwards: 70\r\n"
235236
"Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8;received=192.0.2.1\r\n"
236237
"Contact: <sip:[email protected]>\r\n"
238+
"Record-Route: <sip:[email protected];lr>\r\n"
237239
"Content-Length: 0\r\n\r\n";
238240

239241
// F11 200 OK atlanta.com proxy -> Alice (p218)
@@ -245,6 +247,7 @@ static int sip_test_invite(struct sip_message_test_t* alice, struct sip_message_
245247
"Max-Forwards: 70\r\n"
246248
"Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8;received=192.0.2.1\r\n"
247249
"Contact: <sip:[email protected]>\r\n"
250+
"Record-Route: <sip:[email protected];lr>\r\n"
248251
//"Content-Type: application/sdp\r\n"
249252
"Content-Length: 0\r\n\r\n";
250253

@@ -256,6 +259,7 @@ static int sip_test_invite(struct sip_message_test_t* alice, struct sip_message_
256259
"CSeq: 314159 ACK\r\n"
257260
"Max-Forwards: 70\r\n"
258261
"Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds9\r\n"
262+
"Route: <sip:[email protected];lr>\r\n"
259263
"Content-Length: 0\r\n\r\n";
260264

261265
const char* f13 = "SIP/2.0 603 Decline\r\n"
@@ -284,6 +288,7 @@ static int sip_test_invite(struct sip_message_test_t* alice, struct sip_message_
284288
assert(0 == sip_agent_input(bob->sip, req, bob));
285289
sip_message_add_header(bob->st->reply, "To", "Bob <sip:[email protected]>;tag=a6c85cf"); // modify to.tag
286290
sip_message_add_header(bob->st->reply, "Contact", "<sip:[email protected]>");
291+
sip_message_add_header(bob->st->reply, "Record-Route", "<sip:[email protected];lr>");
287292
assert(0 == sip_uas_reply(bob->st.get(), 100, NULL, 0, bob) && 0 == strcmp(bob->buf, f2));
288293
assert(0 == sip_agent_input(alice->sip, reply100, alice));
289294
assert(0 == sip_uas_reply(bob->st.get(), 180, NULL, 0, bob) && 0 == strcmp(bob->buf, f8));

0 commit comments

Comments
 (0)