- Added handling of Max-Forwards header
- a detected via loop results in an 482 Loop detected
This commit is contained in:
parent
2315f495d4
commit
af152d2bf4
20
ChangeLog
20
ChangeLog
@ -1,6 +1,8 @@
|
||||
0.5.3
|
||||
=====
|
||||
31-Jan-2004: - Allow 2 of my vias in header to let 2 UA's sitting
|
||||
1-Feb-2004: - Added handling of Max-Forwards header
|
||||
- a detected via loop results in an 482 Loop detected
|
||||
31-Jan-2004: - Allow 2 of my vias in header to let 2 UA's sitting
|
||||
behind the same siproxd to have conversation together
|
||||
UA1 -->--\ /-->--\
|
||||
siproxd Registrar
|
||||
@ -22,19 +24,20 @@
|
||||
|
||||
0.5.2
|
||||
=====
|
||||
30-Jan-2004: - If RTP proxy is disabled, don't rewrite incomming
|
||||
31-Jan-2004: - Released 0.5.2
|
||||
30-Jan-2004: - If RTP proxy is disabled, don't rewrite incomming
|
||||
SDP bodies (patch from Robert Högberg)
|
||||
29-Jan-2004: - new doc/RFC3261_compliance.txt and comments in the
|
||||
29-Jan-2004: - new doc/RFC3261_compliance.txt and comments in the
|
||||
code that refer to the RFC.
|
||||
28-Jan-2004: - don't die on INVITE requests that include no Contact
|
||||
28-Jan-2004: - don't die on INVITE requests that include no Contact
|
||||
header - which is legal. (patch from Robert Högberg)
|
||||
- RTP proxy: don't try to forward empty RTP packets
|
||||
- renamed some variables of rtp_proxytable_t to make
|
||||
better sense (changed meaning in fullduplex RTP proxy)
|
||||
27-Jan-2004: - added doc/KNOWN_BUGS
|
||||
27-Jan-2004: - added doc/KNOWN_BUGS
|
||||
- better branch parameter calculation (via header),
|
||||
now honors RFC3261 for stateless proxies (section 16.11)
|
||||
- SIP request: remove a Route-header pointing to myself.
|
||||
- SIP request: remove a Route header pointing to myself.
|
||||
This was an issue with Linphone 0.12.1.
|
||||
(patch from Robert Högberg).
|
||||
- removed IPCHAINS & IPTABLES (netfilter) proxy support
|
||||
@ -42,13 +45,13 @@
|
||||
use one single port (and socket) on each side (inbound/
|
||||
outbound) to send and receive RTP traffic for every
|
||||
active stream (patch from Christof Meerwald).
|
||||
22-Jan-2004: - ./configure option: --enable-static to build
|
||||
22-Jan-2004: - ./configure option: --enable-static to build
|
||||
a completely statically linked executable
|
||||
- REGISTER honors the expires parameter
|
||||
of the contact header
|
||||
- Contact header of REGISTER response must be
|
||||
rewritten back to the local (true) URL
|
||||
18-Jan-2004: - security_check_raw:
|
||||
18-Jan-2004: - security_check_raw:
|
||||
size check: >= 16 bytes
|
||||
- at exit, check registration file to be writable
|
||||
- no WARNING if SIP user-agent header is not supplied.
|
||||
@ -57,6 +60,7 @@
|
||||
|
||||
0.5.1
|
||||
=====
|
||||
22-Dec-2003: - Released 0.5.1
|
||||
21-Dec-2003: - possibility to log call establishment
|
||||
17-Dec-2003: - full duplex RTP proxy (many thanks to Chris Ross for
|
||||
his work on this). Up to now, only the RTP *Relay*
|
||||
|
||||
26
TODO
26
TODO
@ -22,31 +22,9 @@ TODOs, in random order:
|
||||
|
||||
- via loop detection: send 482 error code
|
||||
|
||||
- support Record-Route header
|
||||
|
||||
- feature: don't bind to 0.0.0.0 address, but only to inbound/outbound IF's
|
||||
(defined by IFNAME)
|
||||
|
||||
- support IPTABLES for RTP proxying -> use libiptc
|
||||
|
||||
- rtpproxy_masq:
|
||||
RACE CONDITIONS! A slot may be timed out, even if the actual
|
||||
masquerading tunnel is still active. A following new
|
||||
INVITE then tries to use the believed free port -> Buh
|
||||
- Can we poll (/proc/something) to figure out if the tunnel
|
||||
is still active before deleting? This would require knowledge
|
||||
of the text layout in /proc/xxx.
|
||||
- are there some other possibilities (netfilter/libiptc)?
|
||||
- introduce some kind of connection STATE to the proxy table.
|
||||
Timeout based discarding only is active for non-established.
|
||||
An INVITE would set the STATE to CONNECTING, the following
|
||||
ACK to CONNECTED. A CONNECTED entry can only be deleted by
|
||||
a BYE or CANCEL.
|
||||
- NETFILTER: during startup (RTP initialization) siproxd should
|
||||
clean left over entries that are within the RTP proxy port range
|
||||
- NETFILTER masquerading:
|
||||
it looks like it is not possible to create an entry in the
|
||||
ip_conntrack table from an userspace application. How do we proceed?
|
||||
We just might insert/delete DNAT entries in the PREROUTE NAT table.
|
||||
This the means that we must implement a connection state into the
|
||||
proxy table.
|
||||
RFC3261 non-compliance:
|
||||
- Record-Route header handling
|
||||
|
||||
@ -9,19 +9,19 @@ Request Processing: implemented
|
||||
Section 16.3: Request Validation
|
||||
1. Reasonable Syntax yes
|
||||
2. URI scheme no
|
||||
3. Max-Forwards no
|
||||
4. (Optional) Loop Detection partially
|
||||
3. Max-Forwards yes
|
||||
4. (Optional) Loop Detection yes
|
||||
5. Proxy-Require no
|
||||
6. Proxy-Authorization yes
|
||||
|
||||
Section 16.4 Route Information Preprocessing yes
|
||||
Section 16.4 Route Information Preprocessing partially
|
||||
|
||||
Section 16.5 Determining Request Targets no
|
||||
|
||||
Section 16.6 Request Forwarding
|
||||
1. Make a copy of the received request yes
|
||||
2. Update the Request-URI yes
|
||||
3. Update the Max-Forwards header field no
|
||||
3. Update the Max-Forwards header field yes
|
||||
4. Optionally add a Record-route header field value no
|
||||
5. Optionally add additional header fields no
|
||||
6. Postprocess routing information no
|
||||
@ -37,7 +37,7 @@ Response Processing: implemented
|
||||
1. Reasonable Syntax yes
|
||||
2. URI scheme no
|
||||
3. Max-Forwards no
|
||||
4. (Optional) Loop Detection partially
|
||||
4. (Optional) Loop Detection yes
|
||||
5. Proxy-Require no
|
||||
6. Proxy-Authorization yes
|
||||
|
||||
|
||||
217
src/proxy.c
217
src/proxy.c
@ -91,47 +91,26 @@ int proxy_request (osip_message_t *request, struct sockaddr_in *from) {
|
||||
|
||||
DEBUGC(DBCLASS_PROXY,"proxy_request");
|
||||
|
||||
/*
|
||||
* RFC 3261, Section 16.6 step 1
|
||||
* Proxy Behavior - Request Forwarding - Make a copy
|
||||
*/
|
||||
/* nothing to do here, copy is ready in 'request'*/
|
||||
|
||||
/*
|
||||
* RFC 3261, Section 16.6 step 3
|
||||
* Proxy Behavior - Request Forwarding - Max-Forwards
|
||||
* (if Max-Forward header exists, decrement by one, if it does not
|
||||
* exist, add a new one with value SHOULD be 70)
|
||||
*/
|
||||
/* NOT IMPLEMENTED */
|
||||
|
||||
/*
|
||||
* RFC 3261, Section 16.6 step 4
|
||||
* Proxy Behavior - Request Forwarding - Add a Record-route header
|
||||
*/
|
||||
/* NOT IMPLEMENTED (optional) */
|
||||
|
||||
/*
|
||||
* RFC 3261, Section 16.6 step 5
|
||||
* Proxy Behavior - Request Forwarding - Add Additional Header Fields
|
||||
*/
|
||||
/* NOT IMPLEMENTED (optional) */
|
||||
|
||||
/*
|
||||
* RFC 3261, Section 16.6 step 6
|
||||
* Proxy Behavior - Request Forwarding - Postprocess routing information
|
||||
*/
|
||||
/* NOT IMPLEMENTED */
|
||||
|
||||
|
||||
/*
|
||||
* RFC 3261, Section 16.4
|
||||
* RFC 3261, Section 16.4
|
||||
* Proxy Behavior - Route Information Preprocessing
|
||||
* (process Record-Route header)
|
||||
* (process Route header)
|
||||
*/
|
||||
/*
|
||||
The proxy MUST inspect the Request-URI of the request. If the
|
||||
Request-URI of the request contains a value this proxy previously
|
||||
placed into a Record-Route header field (see Section 16.6 item 4),
|
||||
the proxy MUST replace the Request-URI in the request with the last
|
||||
value from the Route header field, and remove that value from the
|
||||
Route header field. The proxy MUST then proceed as if it received
|
||||
this modified request.
|
||||
|
||||
NOT IMPLEMENTED*/
|
||||
/*
|
||||
* Check if I am listed at the topmost Route header (if any Route
|
||||
* header is existing at all). If so, remove it from the list.
|
||||
* header is existing at all). If so, remove it from the list and
|
||||
* rewrite the request URI to point to the now topmost Route.
|
||||
*/
|
||||
if (request->routes && !osip_list_eol(request->routes, 0)) {
|
||||
struct in_addr addr1, addr2, addr3;
|
||||
@ -151,7 +130,8 @@ int proxy_request (osip_message_t *request, struct sockaddr_in *from) {
|
||||
configuration.sip_listen_port == SIP_PORT)) {
|
||||
osip_list_remove(request->routes, 0);
|
||||
osip_route_free(route);
|
||||
/* possibly request->routes will be freed by osip_message_free() */
|
||||
/* request->routes will be freed by osip_message_free() */
|
||||
DEBUGC(DBCLASS_PROXY,"removed Route header pointing to myself");
|
||||
}
|
||||
}
|
||||
|
||||
@ -298,6 +278,11 @@ int proxy_request (osip_message_t *request, struct sockaddr_in *from) {
|
||||
} /* log_calls */
|
||||
|
||||
|
||||
/*
|
||||
* RFC 3261, Section 16.6 step 1
|
||||
* Proxy Behavior - Request Forwarding - Make a copy
|
||||
*/
|
||||
/* nothing to do here, copy is ready in 'request'*/
|
||||
|
||||
/* get destination address */
|
||||
url=osip_message_get_uri(request);
|
||||
@ -321,17 +306,6 @@ int proxy_request (osip_message_t *request, struct sockaddr_in *from) {
|
||||
proxy_rewrite_request_uri(request, i);
|
||||
}
|
||||
|
||||
/*
|
||||
* RFC 3261, Section 16.6 step 8
|
||||
* Proxy Behavior - Add a Via header field value
|
||||
*/
|
||||
/* add my Via header line (inbound interface)*/
|
||||
sts = sip_add_myvia(request, IF_INBOUND);
|
||||
if (sts == STS_FAILURE) {
|
||||
ERROR("adding my inbound via failed!");
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
/* if this is CANCEL/BYE request, stop RTP proxying */
|
||||
if (MSG_IS_BYE(request) || MSG_IS_CANCEL(request)) {
|
||||
/* stop the RTP proxying stream(s) */
|
||||
@ -356,7 +330,7 @@ int proxy_request (osip_message_t *request, struct sockaddr_in *from) {
|
||||
/*
|
||||
* from the internal masqueraded host to an external host
|
||||
*/
|
||||
case REQTYP_OUTGOING:
|
||||
case REQTYP_OUTGOING:
|
||||
DEBUGC(DBCLASS_PROXY,"outgoing request from %s@%s from inbound",
|
||||
request->from->url->username? request->from->url->username:"*NULL*",
|
||||
request->from->url->host? request->from->url->host: "*NULL*");
|
||||
@ -371,6 +345,9 @@ int proxy_request (osip_message_t *request, struct sockaddr_in *from) {
|
||||
/* if it is addressed to myself, then it must be some request
|
||||
* method that I as a proxy do not support. Reject */
|
||||
#if 0
|
||||
/* careful - an internal UA might send an request to another internal UA.
|
||||
This would be caught here, so don't do this. This situation should be
|
||||
caught in the default part of the CASE statement below */
|
||||
if (is_sipuri_local(request) == STS_TRUE) {
|
||||
WARN("unsupported request [%s] directed to proxy from %s@%s -> %s@%s",
|
||||
request->sip_method? request->sip_method:"*NULL*",
|
||||
@ -393,16 +370,6 @@ int proxy_request (osip_message_t *request, struct sockaddr_in *from) {
|
||||
/* rewrite Contact header to represent the masqued address */
|
||||
sip_rewrite_contact(request, DIR_OUTGOING);
|
||||
|
||||
/*
|
||||
* RFC 3261, Section 16.8
|
||||
* Proxy Behavior - Add a Via header field value
|
||||
*/
|
||||
/* add my Via header line (outbound interface)*/
|
||||
sts = sip_add_myvia(request, IF_OUTBOUND);
|
||||
if (sts == STS_FAILURE) {
|
||||
ERROR("adding my outbound via failed!");
|
||||
}
|
||||
|
||||
/* if this is CANCEL/BYE request, stop RTP proxying */
|
||||
if (MSG_IS_BYE(request) || MSG_IS_CANCEL(request)) {
|
||||
/* stop the RTP proxying stream(s) */
|
||||
@ -438,10 +405,119 @@ int proxy_request (osip_message_t *request, struct sockaddr_in *from) {
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* RFC 3261, Section 16.6 step 7
|
||||
* Proxy Behavior - Determine Next-Hop Address
|
||||
*/
|
||||
|
||||
/*
|
||||
* RFC 3261, Section 16.6 step 3
|
||||
* Proxy Behavior - Request Forwarding - Max-Forwards
|
||||
* (if Max-Forwards header exists, decrement by one, if it does not
|
||||
* exist, add a new one with value SHOULD be 70)
|
||||
*/
|
||||
{
|
||||
osip_header_t *max_forwards;
|
||||
int forwards_count = DEFAULT_MAXFWD;
|
||||
char mfwd[8];
|
||||
|
||||
osip_message_get_max_forwards(request, 0, &max_forwards);
|
||||
if (max_forwards == NULL) {
|
||||
sprintf(mfwd, "%i", forwards_count);
|
||||
osip_message_set_max_forwards(request, mfwd);
|
||||
} else {
|
||||
if (max_forwards->hvalue) {
|
||||
forwards_count = atoi(max_forwards->hvalue);
|
||||
forwards_count -=1;
|
||||
osip_free (max_forwards->hvalue);
|
||||
}
|
||||
|
||||
sprintf(mfwd, "%i", forwards_count);
|
||||
max_forwards->hvalue = osip_strdup(mfwd);
|
||||
}
|
||||
|
||||
DEBUGC(DBCLASS_PROXY,"setting Max-Forwards=%s",mfwd);
|
||||
}
|
||||
|
||||
/*
|
||||
* RFC 3261, Section 16.6 step 4
|
||||
* Proxy Behavior - Request Forwarding - Add a Record-route header
|
||||
*/
|
||||
#if 0
|
||||
/* NOT IMPLEMENTED - this requires proper implementation of
|
||||
the Route headers first. */
|
||||
{
|
||||
struct in_addr addr;
|
||||
osip_record_route_t *r_route;
|
||||
osip_uri_t *uri_of_proxy;
|
||||
|
||||
/*
|
||||
* get the IP address of the interface where I'm going to
|
||||
* send out this request
|
||||
*/
|
||||
switch (type) {
|
||||
case REQTYP_INCOMING:
|
||||
sts = get_ip_by_ifname(configuration.inbound_if, &addr);
|
||||
if (sts == STS_FAILURE) {
|
||||
ERROR("can't find inbound interface %s - configuration error?",
|
||||
configuration.outbound_if);
|
||||
return STS_FAILURE;
|
||||
}
|
||||
break;
|
||||
case REQTYP_OUTGOING:
|
||||
sts = get_ip_by_ifname(configuration.outbound_if, &addr);
|
||||
if (sts == STS_FAILURE) {
|
||||
ERROR("can't find outbound interface %s - configuration error?",
|
||||
configuration.outbound_if);
|
||||
return STS_FAILURE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ERROR("Oops, never should end up here (type=%i)", type);
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
sts = osip_record_route_init(&r_route);
|
||||
if (sts == 0) {
|
||||
sts = osip_uri_init(&uri_of_proxy);
|
||||
if (sts == 0) {
|
||||
char tmp[8];
|
||||
|
||||
/* host name / IP */
|
||||
osip_uri_set_host(uri_of_proxy, osip_strdup(utils_inet_ntoa(addr)));
|
||||
|
||||
/* port number */
|
||||
sprintf(tmp, "%i", configuration.sip_listen_port);
|
||||
osip_uri_set_port(uri_of_proxy, osip_strdup(tmp));
|
||||
|
||||
/* 'lr' parameter */
|
||||
osip_uri_uparam_add(uri_of_proxy, "lr", NULL);
|
||||
|
||||
osip_record_route_set_url(r_route, uri_of_proxy);
|
||||
|
||||
/* insert before all other record-route */
|
||||
osip_list_add (request->record_routes, r_route, 0);
|
||||
} else {
|
||||
osip_record_route_free (r_route);
|
||||
osip_free (r_route);
|
||||
} /* if url_init */
|
||||
} /* if record route init */
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* RFC 3261, Section 16.6 step 5
|
||||
* Proxy Behavior - Request Forwarding - Add Additional Header Fields
|
||||
*/
|
||||
/* NOT IMPLEMENTED (optional) */
|
||||
|
||||
|
||||
/*
|
||||
* RFC 3261, Section 16.6 step 6
|
||||
* Proxy Behavior - Request Forwarding - Postprocess routing information
|
||||
*/
|
||||
|
||||
/*
|
||||
* RFC 3261, Section 16.6 step 7
|
||||
* Proxy Behavior - Determine Next-Hop Address
|
||||
*/
|
||||
if ((type == REQTYP_OUTGOING) && (configuration.outbound_proxy_host)) {
|
||||
/* I have an outbound proxy configured */
|
||||
sts = get_ip_by_host(configuration.outbound_proxy_host, &sendto_addr);
|
||||
@ -472,6 +548,23 @@ int proxy_request (osip_message_t *request, struct sockaddr_in *from) {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* RFC 3261, Section 16.6 step 8
|
||||
* Proxy Behavior - Add a Via header field value
|
||||
*/
|
||||
/* add my Via header line (outbound interface)*/
|
||||
if (type == REQTYP_INCOMING) {
|
||||
sts = sip_add_myvia(request, IF_INBOUND);
|
||||
if (sts == STS_FAILURE) {
|
||||
ERROR("adding my inbound via failed!");
|
||||
}
|
||||
} else {
|
||||
sts = sip_add_myvia(request, IF_OUTBOUND);
|
||||
if (sts == STS_FAILURE) {
|
||||
ERROR("adding my outbound via failed!");
|
||||
return STS_FAILURE;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* RFC 3261, Section 16.6 step 9
|
||||
* Proxy Behavior - Add a Content-Length header field if necessary
|
||||
|
||||
@ -215,10 +215,9 @@ int register_client(osip_message_t *my_msg, int force_lcl_masq) {
|
||||
* look for an Contact expires parameter - in case of REGISTER
|
||||
* these two are equal. The Contact expires has higher priority!
|
||||
*/
|
||||
|
||||
osip_contact_param_get_byname(
|
||||
(osip_contact_t*) my_msg->contacts->node->element,
|
||||
"expires", &expires_param);
|
||||
EXPIRES, &expires_param);
|
||||
|
||||
if (expires_param && expires_param->gvalue) {
|
||||
/* get expires from contact Header */
|
||||
|
||||
@ -294,9 +294,25 @@ int main (int argc, char *argv[])
|
||||
/*
|
||||
* RFC 3261, Section 16.3 step 3
|
||||
* Proxy Behavior - Request Validation - Max-Forwards check
|
||||
* (check Max-Forward header and refuse with 483 if too many hops)
|
||||
* (check Max-Forwards header and refuse with 483 if too many hops)
|
||||
*/
|
||||
/* NOT IMPLEMENTED */
|
||||
{
|
||||
osip_header_t *max_forwards;
|
||||
int forwards_count = DEFAULT_MAXFWD;
|
||||
|
||||
osip_message_get_max_forwards(my_msg, 0, &max_forwards);
|
||||
if (max_forwards && max_forwards->hvalue) {
|
||||
forwards_count = atoi(max_forwards->hvalue);
|
||||
}
|
||||
|
||||
DEBUGC(DBCLASS_PROXY,"checking Max-Forwards (=%i)",forwards_count);
|
||||
if (forwards_count <= 0) {
|
||||
DEBUGC(DBCLASS_SIP, "Forward count reached 0 -> 483 response");
|
||||
sip_gen_response(my_msg, 483 /*Too many hops*/);
|
||||
goto end_loop; /* skip and free resources */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* RFC 3261, Section 16.3 step 4
|
||||
@ -304,8 +320,8 @@ int main (int argc, char *argv[])
|
||||
* (check for loop and return 482 if a loop is detected)
|
||||
*/
|
||||
if (check_vialoop(my_msg) == STS_TRUE) {
|
||||
DEBUGC(DBCLASS_PROXY,"via loop detected, ignoring request");
|
||||
/* we should return 482, NOT IMPLEMENTED */
|
||||
DEBUGC(DBCLASS_SIP,"via loop detected, ignoring request");
|
||||
sip_gen_response(my_msg, 482 /*Loop detected*/);
|
||||
goto end_loop; /* skip and free resources */
|
||||
}
|
||||
|
||||
|
||||
@ -156,7 +156,8 @@ struct siproxd_config {
|
||||
/*
|
||||
* some constant definitions
|
||||
*/
|
||||
#define SIP_PORT 5060
|
||||
#define SIP_PORT 5060 /* default port to listen */
|
||||
#define DEFAULT_MAXFWD 70 /* default Max-Forward count */
|
||||
|
||||
#define URLMAP_SIZE 32 /* number of URL mapping table entries */
|
||||
#define RTPPROXY_SIZE 64 /* number of rtp proxy entries */
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user