- preliminary (and reduced) support for Route Headers
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
0.5.8
|
||||
=====
|
||||
27-Aug-2004: - preliminary (and reduced) support for Route Headers
|
||||
26-Aug-2004: - more DEBUG output
|
||||
22-Aug-2004: - fix: secure_enviroment - set proper EGID (by Daniel Mueller)
|
||||
19-Aug-2004: - fix: don't crash on missing Contact header during registration
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ AM_CFLAGS = -Wall -DBUILDSTR=\"`cat .buildno`\" -D_GNU_SOURCE
|
||||
sbin_PROGRAMS = siproxd
|
||||
siproxd_SOURCES = siproxd.c proxy.c register.c sock.c utils.c \
|
||||
sip_utils.c log.c readconf.c rtpproxy.c \
|
||||
rtpproxy_relay.c accessctl.c \
|
||||
rtpproxy_relay.c accessctl.c route_processing.c \
|
||||
security.c auth.c fwapi.c
|
||||
|
||||
#
|
||||
|
||||
+74
-172
@@ -84,9 +84,6 @@ int proxy_request (sip_ticket_t *ticket) {
|
||||
osip_message_t *request;
|
||||
struct sockaddr_in *from;
|
||||
|
||||
#define REQTYP_INCOMING 1
|
||||
#define REQTYP_OUTGOING 2
|
||||
|
||||
DEBUGC(DBCLASS_PROXY,"proxy_request");
|
||||
|
||||
if (ticket==NULL) {
|
||||
@@ -102,55 +99,7 @@ int proxy_request (sip_ticket_t *ticket) {
|
||||
* Proxy Behavior - Route Information Preprocessing
|
||||
* (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 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;
|
||||
osip_route_t *route;
|
||||
|
||||
route = (osip_route_t *) osip_list_get(request->routes, 0);
|
||||
|
||||
sts = get_ip_by_host(route->url->host, &addr1);
|
||||
if (get_ip_by_ifname(configuration.inbound_if, &addr2) != STS_SUCCESS) {
|
||||
ERROR("can't find inbound interface %s - configuration error?",
|
||||
configuration.inbound_if);
|
||||
return STS_FAILURE;
|
||||
}
|
||||
if (get_ip_by_ifname(configuration.outbound_if, &addr3)!= STS_SUCCESS) {
|
||||
ERROR("can't find outbound interface %s - configuration error?",
|
||||
configuration.outbound_if);
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
/* my own route header? */
|
||||
if ((sts == STS_SUCCESS) &&
|
||||
((memcmp(&addr1, &addr2, sizeof(addr1)) == 0) ||
|
||||
(memcmp(&addr1, &addr3, sizeof(addr1)) == 0)) &&
|
||||
(route->url->port ?
|
||||
configuration.sip_listen_port == atoi(route->url->port):
|
||||
configuration.sip_listen_port == SIP_PORT)) {
|
||||
osip_list_remove(request->routes, 0);
|
||||
osip_route_free(route);
|
||||
/* request->routes will be freed by osip_message_free() */
|
||||
DEBUGC(DBCLASS_PROXY, "removed Route header pointing to myself");
|
||||
}
|
||||
}
|
||||
|
||||
route_preprocess(ticket);
|
||||
|
||||
/*
|
||||
* figure out whether this is an incoming or outgoing request
|
||||
@@ -240,7 +189,7 @@ int proxy_request (sip_ticket_t *ticket) {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
ticket->direction=type;
|
||||
|
||||
/*
|
||||
* logging of passing calls
|
||||
@@ -446,63 +395,19 @@ int proxy_request (sip_ticket_t *ticket) {
|
||||
#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:
|
||||
if (get_ip_by_ifname(configuration.inbound_if, &addr) != STS_SUCCESS) {
|
||||
ERROR("can't find inbound interface %s - configuration error?",
|
||||
configuration.inbound_if);
|
||||
return STS_FAILURE;
|
||||
}
|
||||
break;
|
||||
case REQTYP_OUTGOING:
|
||||
if (get_ip_by_ifname(configuration.outbound_if, &addr) != STS_SUCCESS) {
|
||||
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 */
|
||||
|
||||
}
|
||||
route_add_recordroute(ticket);
|
||||
#endif
|
||||
/*
|
||||
* for incoming requests that DO include a Record-Route header,
|
||||
* include my own as well. The local UA will probably send its answer
|
||||
* to the topmost Route Header (8.1.2 of RFC3261)
|
||||
*/
|
||||
if ((type == REQTYP_INCOMING) &&
|
||||
(request->record_routes) &&
|
||||
(!osip_list_eol(request->record_routes, 0))) {
|
||||
DEBUGC(DBCLASS_PROXY,"Adding my Record-Route");
|
||||
route_add_recordroute(ticket);
|
||||
}
|
||||
|
||||
/*
|
||||
* RFC 3261, Section 16.6 step 5
|
||||
@@ -528,46 +433,16 @@ int proxy_request (sip_ticket_t *ticket) {
|
||||
* header field.
|
||||
*/
|
||||
#if 0
|
||||
/* we are not a real proxy - and from the outside we look like an UA.
|
||||
So we should not fiddle around with the Route headers.
|
||||
We should use the first Route header to send the packet to
|
||||
(RFC3261, section 8.1.2) */
|
||||
if (request->routes && !osip_list_eol(request->routes, 0)) {
|
||||
osip_route_t *route=NULL;
|
||||
osip_uri_param_t *param=NULL;
|
||||
|
||||
route = (osip_route_t *) osip_list_get(request->routes, 0);
|
||||
if (route->url) {
|
||||
/* check for non existing lr parameter */
|
||||
if (osip_uri_uparam_get_byname(route->url, "lr", ¶m) != 0) {
|
||||
osip_route_t *new_route=NULL;
|
||||
url=osip_message_get_uri(request);
|
||||
|
||||
/* push Request URI into Route header list at the last position */
|
||||
osip_route_init(&new_route);
|
||||
osip_uri_clone(url, &new_route->url);
|
||||
osip_list_add(request->routes, new_route, -1);
|
||||
|
||||
|
||||
/* rewrite request URI to now topmost Route header */
|
||||
DEBUGC(DBCLASS_PROXY, "Route header w/o 'lr': rewriting request "
|
||||
"URI from %s to %s", url->host, route->url->host);
|
||||
osip_uri_free(url);
|
||||
url=NULL;
|
||||
osip_uri_clone(route->url, &url);
|
||||
/* remove first Route header from list & free */
|
||||
osip_list_remove(request->routes, 0);
|
||||
osip_route_free(route);
|
||||
route = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
route_postprocess(ticket);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* RFC 3261, Section 16.6 step 7
|
||||
* Proxy Behavior - Determine Next-Hop Address
|
||||
*/
|
||||
/*
|
||||
* fixed outbound proxy defined ?
|
||||
*/
|
||||
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);
|
||||
@@ -584,31 +459,22 @@ We should use the first Route header to send the packet to
|
||||
}
|
||||
DEBUGC(DBCLASS_PROXY, "proxy_request: have outbound proxy %s:%i",
|
||||
configuration.outbound_proxy_host, port);
|
||||
/*
|
||||
* Route present?
|
||||
* If so, fetch address from topmost Route: header and remove it.
|
||||
*/
|
||||
} else if ((type == REQTYP_OUTGOING) &&
|
||||
(request->routes && !osip_list_eol(request->routes, 0))) {
|
||||
/* get the destination from the Route Header */
|
||||
osip_route_t *route=NULL;
|
||||
route = (osip_route_t *) osip_list_get(request->routes, 0);
|
||||
if (route==NULL || route->url==NULL || route->url->host==NULL) {
|
||||
DEBUGC(DBCLASS_PROXY, "proxy_request: got broken Route header "
|
||||
"- discarding packet");
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
sts = get_ip_by_host(route->url->host, &sendto_addr);
|
||||
sts=route_determine_nexthop(ticket, &sendto_addr, &port);
|
||||
if (sts == STS_FAILURE) {
|
||||
DEBUGC(DBCLASS_PROXY, "proxy_request: cannot resolve Route URI [%s]",
|
||||
route->url->host);
|
||||
DEBUGC(DBCLASS_PROXY, "proxy_request: route_determine_nexthop failed");
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
if (route->url->port) {
|
||||
port=atoi(route->url->port);
|
||||
} else {
|
||||
port=SIP_PORT;
|
||||
}
|
||||
DEBUGC(DBCLASS_PROXY, "proxy_request: have Route header to %s:%i",
|
||||
route->url->host, port);
|
||||
utils_inet_ntoa(sendto_addr), port);
|
||||
/*
|
||||
* destination from SIP URI
|
||||
*/
|
||||
} else {
|
||||
/* get the destination from the SIP URI */
|
||||
sts = get_ip_by_host(url->host, &sendto_addr);
|
||||
@@ -680,6 +546,20 @@ We should use the first Route header to send the packet to
|
||||
* RETURNS
|
||||
* STS_SUCCESS on success
|
||||
* STS_FAILURE on error
|
||||
* RFC3261
|
||||
* Section 16.7: Proxy Behavior - Response Processing
|
||||
* 1. Find the appropriate response context
|
||||
* 2. Update timer C for provisional responses
|
||||
* 3. Remove the topmost Via
|
||||
* 4. Add the response to the response context
|
||||
* 5. Check to see if this response should be forwarded immediately
|
||||
* 6. When necessary, choose the best final response from the
|
||||
* response context
|
||||
* 7. Aggregate authorization header field values if necessary
|
||||
* 8. Optionally rewrite Record-Route header field values
|
||||
* 9. Forward the response
|
||||
* 10. Generate any necessary CANCEL requests
|
||||
*
|
||||
*/
|
||||
int proxy_response (sip_ticket_t *ticket) {
|
||||
int i;
|
||||
@@ -692,9 +572,6 @@ int proxy_response (sip_ticket_t *ticket) {
|
||||
osip_message_t *response;
|
||||
struct sockaddr_in *from;
|
||||
|
||||
#define RESTYP_INCOMING 1
|
||||
#define RESTYP_OUTGOING 2
|
||||
|
||||
DEBUGC(DBCLASS_PROXY,"proxy_response");
|
||||
|
||||
if (ticket==NULL) {
|
||||
@@ -706,8 +583,8 @@ int proxy_response (sip_ticket_t *ticket) {
|
||||
from=&ticket->from;
|
||||
|
||||
/*
|
||||
* RFC 3261, Section 16.11
|
||||
* Proxy Behavior - Remove my Via header field value
|
||||
* RFC 3261, Section 16.7 step 3
|
||||
* Proxy Behavior - Response Processing - Remove my Via header field value
|
||||
*/
|
||||
/* remove my Via header line */
|
||||
sts = sip_del_myvia(ticket);
|
||||
@@ -765,10 +642,10 @@ int proxy_response (sip_ticket_t *ticket) {
|
||||
if (urlmap[i].active == 0) continue;
|
||||
|
||||
if (get_ip_by_host(urlmap[i].true_url->host, &tmp_addr) == STS_FAILURE) {
|
||||
DEBUGC(DBCLASS_PROXY, "proxy_request: cannot resolve host [%s]",
|
||||
DEBUGC(DBCLASS_PROXY, "proxy_response: cannot resolve host [%s]",
|
||||
urlmap[i].true_url);
|
||||
} else {
|
||||
DEBUGC(DBCLASS_PROXY, "proxy_request: reghost:%s ip:%s",
|
||||
DEBUGC(DBCLASS_PROXY, "proxy_response: reghost:%s ip:%s",
|
||||
urlmap[i].true_url->host, utils_inet_ntoa(from->sin_addr));
|
||||
if (memcmp(&tmp_addr, &from->sin_addr, sizeof(tmp_addr)) == 0) {
|
||||
type=RESTYP_OUTGOING;
|
||||
@@ -790,7 +667,7 @@ int proxy_response (sip_ticket_t *ticket) {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
ticket->direction=type;
|
||||
|
||||
/*
|
||||
* ok, we got a response that we are allowed to process.
|
||||
@@ -854,7 +731,7 @@ int proxy_response (sip_ticket_t *ticket) {
|
||||
(osip_strncasecmp(ua_hdr->hvalue,"grandstream", 11)==0) &&
|
||||
(MSG_IS_RESPONSE_FOR(response,"SUBSCRIBE")) &&
|
||||
(MSG_TEST_CODE(response, 202))) {
|
||||
DEBUGC(DBCLASS_PROXY, "proxy_request: Grandstream hack 202->404");
|
||||
DEBUGC(DBCLASS_PROXY, "proxy_response: Grandstream hack 202->404");
|
||||
response->status_code=404;
|
||||
}
|
||||
}
|
||||
@@ -891,6 +768,18 @@ int proxy_response (sip_ticket_t *ticket) {
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* for incoming requests that DO include a Record-Route header,
|
||||
* include my own as well. The local UA will probably send its answer
|
||||
* to the topmost Route Header (8.1.2 of RFC3261)
|
||||
*/
|
||||
if ((type == RESTYP_INCOMING) &&
|
||||
(response->record_routes) &&
|
||||
(!osip_list_eol(response->record_routes, 0))) {
|
||||
DEBUGC(DBCLASS_PROXY,"Adding my Record-Route");
|
||||
route_add_recordroute(ticket);
|
||||
}
|
||||
|
||||
/*
|
||||
* check if we need to send to an outbound proxy
|
||||
*/
|
||||
@@ -898,7 +787,7 @@ int proxy_response (sip_ticket_t *ticket) {
|
||||
/* have an outbound proxy - use it to send the packet */
|
||||
sts = get_ip_by_host(configuration.outbound_proxy_host, &sendto_addr);
|
||||
if (sts == STS_FAILURE) {
|
||||
DEBUGC(DBCLASS_PROXY, "proxy_request: cannot resolve outbound "
|
||||
DEBUGC(DBCLASS_PROXY, "proxy_response: cannot resolve outbound "
|
||||
" proxy host [%s]", configuration.outbound_proxy_host);
|
||||
return STS_FAILURE;
|
||||
}
|
||||
@@ -908,6 +797,19 @@ int proxy_response (sip_ticket_t *ticket) {
|
||||
} else {
|
||||
port = SIP_PORT;
|
||||
}
|
||||
/*
|
||||
* Route present?
|
||||
* If so, fetch address from topmost Route: header and remove it.
|
||||
*/
|
||||
} else if ((type == RESTYP_OUTGOING) &&
|
||||
(response->routes && !osip_list_eol(response->routes, 0))) {
|
||||
sts=route_determine_nexthop(ticket, &sendto_addr, &port);
|
||||
if (sts == STS_FAILURE) {
|
||||
DEBUGC(DBCLASS_PROXY, "proxy_response: route_determine_nexthop failed");
|
||||
return STS_FAILURE;
|
||||
}
|
||||
DEBUGC(DBCLASS_PROXY, "proxy_response: have Route header to %s:%i",
|
||||
utils_inet_ntoa(sendto_addr), port);
|
||||
} else {
|
||||
/* get target address and port from VIA header */
|
||||
via = (osip_via_t *) osip_list_get (response->vias, 0);
|
||||
|
||||
@@ -0,0 +1,319 @@
|
||||
/* -*- Mode: C; c-basic-offset: 3 -*-
|
||||
Copyright (C) 2002 Thomas Ries <tries@gmx.net>
|
||||
|
||||
This file is part of Siproxd.
|
||||
|
||||
Siproxd is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Siproxd is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Siproxd; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#include <osipparser2/osip_parser.h>
|
||||
#include <osipparser2/sdp_message.h>
|
||||
|
||||
#include "siproxd.h"
|
||||
#include "log.h"
|
||||
|
||||
static char const ident[]="$Id$";
|
||||
|
||||
/* configuration storage */
|
||||
extern struct siproxd_config configuration; /* defined in siproxd.c */
|
||||
|
||||
|
||||
/*
|
||||
* PROXY_PREPROCESS_ROUTE
|
||||
*
|
||||
* Route Information Preprocessing
|
||||
*
|
||||
* RETURNS
|
||||
* STS_SUCCESS on success
|
||||
*/
|
||||
int route_preprocess(sip_ticket_t *ticket){
|
||||
osip_message_t *mymsg=ticket->sipmsg;
|
||||
int sts;
|
||||
struct in_addr addr1, addr2, addr3;
|
||||
osip_route_t *route;
|
||||
int last;
|
||||
int i, j;
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 and
|
||||
* rewrite the request URI to point to the now topmost Route.
|
||||
*/
|
||||
if (mymsg->routes && !osip_list_eol(mymsg->routes, 0)) {
|
||||
last=osip_list_size(mymsg->routes)-1;
|
||||
/*
|
||||
* I have seen that some (all?) UAs do set a Route: header
|
||||
* pointing to myself AT THE END OF THE LIST!
|
||||
* I don't really understand why, reading the Routing parts
|
||||
* of the RFC3261 did not help. All I know is, this last Route
|
||||
* header must be removed, otherwise any remote Proxy/Server
|
||||
* in the path will try to forward the packet to our private net.
|
||||
*
|
||||
* so the quick and dirty HACK is to check the topmost and
|
||||
* the last Route entry if it belongs to me...
|
||||
*
|
||||
* Any proper explanation to this is heavily welcome
|
||||
*/
|
||||
for (j=0,i=last; j<2; j++, i=0) {
|
||||
DEBUGC(DBCLASS_PROXY, "route_preprocess: checking Route "
|
||||
"header[%i]", i);
|
||||
route = (osip_route_t *) osip_list_get(mymsg->routes, i);
|
||||
|
||||
sts = get_ip_by_host(route->url->host, &addr1);
|
||||
if (get_ip_by_ifname(configuration.inbound_if, &addr2) != STS_SUCCESS) {
|
||||
ERROR("can't find inbound interface %s - configuration error?",
|
||||
configuration.inbound_if);
|
||||
return STS_FAILURE;
|
||||
}
|
||||
if (get_ip_by_ifname(configuration.outbound_if, &addr3)!= STS_SUCCESS) {
|
||||
ERROR("can't find outbound interface %s - configuration error?",
|
||||
configuration.outbound_if);
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
/* my own route header? */
|
||||
if ((sts == STS_SUCCESS) &&
|
||||
((memcmp(&addr1, &addr2, sizeof(addr1)) == 0) ||
|
||||
(memcmp(&addr1, &addr3, sizeof(addr1)) == 0)) &&
|
||||
(route->url->port ?
|
||||
configuration.sip_listen_port == atoi(route->url->port):
|
||||
configuration.sip_listen_port == SIP_PORT)) {
|
||||
osip_list_remove(mymsg->routes, i);
|
||||
osip_route_free(route);
|
||||
/* request->routes will be freed by osip_message_free() */
|
||||
DEBUGC(DBCLASS_PROXY, "removed Route header pointing to myself");
|
||||
}
|
||||
}
|
||||
}
|
||||
return STS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* PROXY_POSTPROCESS_ROUTE
|
||||
*
|
||||
* Route Information Postprocessing
|
||||
*
|
||||
* RETURNS
|
||||
* STS_SUCCESS on success
|
||||
*/
|
||||
int route_postprocess(sip_ticket_t *ticket){
|
||||
osip_message_t *mymsg=ticket->sipmsg;
|
||||
osip_uri_t *url;
|
||||
osip_route_t *route=NULL;
|
||||
osip_uri_param_t *param=NULL;
|
||||
|
||||
/*
|
||||
* RFC 3261, Section 16.6 step 6
|
||||
* Proxy Behavior - Request Forwarding - Postprocess routing information
|
||||
*
|
||||
* If the copy contains a Route header field, the proxy MUST
|
||||
* inspect the URI in its first value. If that URI does not
|
||||
* contain an lr parameter, the proxy MUST modify the copy as
|
||||
* follows:
|
||||
*
|
||||
* - The proxy MUST place the Request-URI into the Route header
|
||||
* field as the last value.
|
||||
*
|
||||
* - The proxy MUST then place the first Route header field value
|
||||
* into the Request-URI and remove that value from the Route
|
||||
* header field.
|
||||
*/
|
||||
/* we are not a real proxy - and from the outside we look like an UA.
|
||||
So we should not fiddle around with the Route headers.
|
||||
We should use the first Route header to send the packet to
|
||||
(RFC3261, section 8.1.2) */
|
||||
|
||||
if (mymsg->routes && !osip_list_eol(mymsg->routes, 0)) {
|
||||
|
||||
route = (osip_route_t *) osip_list_get(mymsg->routes, 0);
|
||||
if (route->url) {
|
||||
/* check for non existing lr parameter */
|
||||
if (osip_uri_uparam_get_byname(route->url, "lr", ¶m) != 0) {
|
||||
osip_route_t *new_route=NULL;
|
||||
url=osip_message_get_uri(mymsg);
|
||||
|
||||
/* push Request URI into Route header list at the last position */
|
||||
osip_route_init(&new_route);
|
||||
osip_uri_clone(url, &new_route->url);
|
||||
osip_list_add(mymsg->routes, new_route, -1);
|
||||
|
||||
/* rewrite request URI to now topmost Route header */
|
||||
DEBUGC(DBCLASS_PROXY, "Route header w/o 'lr': rewriting request "
|
||||
"URI from %s to %s", url->host, route->url->host);
|
||||
osip_uri_free(url);
|
||||
url=NULL;
|
||||
osip_uri_clone(route->url, &url);
|
||||
/* remove first Route header from list & free */
|
||||
osip_list_remove(mymsg->routes, 0);
|
||||
osip_route_free(route);
|
||||
route = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return STS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* PROXY_ADD_RECORDROUTE
|
||||
*
|
||||
* Add a Record-route header
|
||||
*
|
||||
* RETURNS
|
||||
* STS_SUCCESS on success
|
||||
*/
|
||||
int route_add_recordroute(sip_ticket_t *ticket){
|
||||
osip_message_t *mymsg=ticket->sipmsg;
|
||||
int sts;
|
||||
struct in_addr addr;
|
||||
osip_record_route_t *r_route;
|
||||
osip_uri_t *uri_of_proxy;
|
||||
|
||||
/*
|
||||
* RFC 3261, Section 16.6 step 4
|
||||
* Proxy Behavior - Request Forwarding - Add a Record-route header
|
||||
*/
|
||||
|
||||
/*
|
||||
* get the IP address of the interface where I'm going to
|
||||
* send out this request
|
||||
*/
|
||||
switch (ticket->direction) {
|
||||
case REQTYP_INCOMING:
|
||||
case RESTYP_INCOMING:
|
||||
if (get_ip_by_ifname(configuration.inbound_if, &addr) != STS_SUCCESS) {
|
||||
ERROR("can't find inbound interface %s - configuration error?",
|
||||
configuration.inbound_if);
|
||||
return STS_FAILURE;
|
||||
}
|
||||
break;
|
||||
case REQTYP_OUTGOING:
|
||||
case RESTYP_OUTGOING:
|
||||
if (get_ip_by_ifname(configuration.outbound_if, &addr) != STS_SUCCESS) {
|
||||
ERROR("can't find outbound interface %s - configuration error?",
|
||||
configuration.outbound_if);
|
||||
return STS_FAILURE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ERROR("Oops, never should end up here (direction=%i)", ticket->direction);
|
||||
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)));
|
||||
osip_uri_set_username(uri_of_proxy, osip_strdup("siproxd"));
|
||||
|
||||
/* 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 (mymsg->record_routes, r_route, 0);
|
||||
} else {
|
||||
osip_record_route_free (r_route);
|
||||
osip_free (r_route);
|
||||
} /* if url_init */
|
||||
} /* if record route init */
|
||||
|
||||
|
||||
return STS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* PROXY_DETERMINE_NEXT_HOP
|
||||
*
|
||||
* check if a route-header exists and give back the next hop
|
||||
*
|
||||
* RETURNS
|
||||
* STS_SUCCESS on success
|
||||
*/
|
||||
int route_determine_nexthop(sip_ticket_t *ticket,
|
||||
struct in_addr *dest, int *port){
|
||||
int sts;
|
||||
osip_message_t *mymsg=ticket->sipmsg;
|
||||
osip_route_t *route=NULL;
|
||||
|
||||
/*
|
||||
* Check for existing route header. If so, the topmost will be
|
||||
* the next hop.
|
||||
*
|
||||
* If this route header does NOT have a lr parameter set, rewrite
|
||||
* the SIP URI to point to the destination of the route (NOT IMPLEMENTED)
|
||||
*/
|
||||
if (mymsg->routes && !osip_list_eol(mymsg->routes, 0)) {
|
||||
route = (osip_route_t *) osip_list_get(mymsg->routes, 0);
|
||||
|
||||
/* get the destination from the Route Header */
|
||||
route = (osip_route_t *) osip_list_get(mymsg->routes, 0);
|
||||
if (route==NULL || route->url==NULL || route->url->host==NULL) {
|
||||
DEBUGC(DBCLASS_PROXY, "route_determine_nexthop: got broken Route "
|
||||
"header - discarding packet");
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
sts = get_ip_by_host(route->url->host, dest);
|
||||
if (sts == STS_FAILURE) {
|
||||
DEBUGC(DBCLASS_PROXY, "route_determine_nexthop: cannot resolve "
|
||||
"Route URI [%s]", route->url->host);
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
if (route->url->port) {
|
||||
*port=atoi(route->url->port);
|
||||
} else {
|
||||
*port=SIP_PORT;
|
||||
}
|
||||
|
||||
osip_list_remove(mymsg->routes, 0);
|
||||
osip_route_free(route);
|
||||
/* request->routes will be freed by osip_message_free() */
|
||||
}
|
||||
|
||||
return STS_SUCCESS;
|
||||
}
|
||||
+13
-1
@@ -93,6 +93,11 @@ typedef struct {
|
||||
#define PROTO_UDP 1
|
||||
#define PROTO_TCP 2
|
||||
int protocol; /* received by protocol */
|
||||
#define REQTYP_INCOMING 1
|
||||
#define REQTYP_OUTGOING 2
|
||||
#define RESTYP_INCOMING 3
|
||||
#define RESTYP_OUTGOING 4
|
||||
int direction; /* direction as determined by proxy */
|
||||
} sip_ticket_t;
|
||||
|
||||
|
||||
@@ -123,7 +128,14 @@ int register_response(sip_ticket_t *ticket, int flag); /*X*/
|
||||
int proxy_request (sip_ticket_t *ticket); /*X*/
|
||||
int proxy_response (sip_ticket_t *ticket); /*X*/
|
||||
int proxy_rewrite_invitation_body(osip_message_t *m, int direction); /*X*/
|
||||
int proxy_rewrite_request_uri(osip_message_t *mymsg, int idx); /*X*/
|
||||
int proxy_rewrite_request_uri(osip_message_t *mymsg, int idx); /*X*/
|
||||
|
||||
/* route_preprocessing.c */
|
||||
int route_preprocess(sip_ticket_t *ticket); /*X*/
|
||||
int route_add_recordroute(sip_ticket_t *ticket); /*X*/
|
||||
int route_postprocess(sip_ticket_t *ticket); /*X*/
|
||||
int route_determine_nexthop(sip_ticket_t *ticket,
|
||||
struct in_addr *dest, int *port); /*X*/
|
||||
|
||||
/* utils.c */
|
||||
int get_ip_by_host(char *hostname, struct in_addr *addr); /*X*/
|
||||
|
||||
Reference in New Issue
Block a user