- allocate only even RTP port numbers

- started with own name lookup routines that honor SRV and NAPTR records
This commit is contained in:
Thomas Ries 2005-08-31 03:34:35 +00:00
parent 9e817ab1f9
commit ab08d2febf
9 changed files with 294 additions and 77 deletions

View File

@ -1,5 +1,6 @@
0.5.12
======
14-Jul-2005: - allocate only even port numbers for RTP traffic
0.5.11
======

View File

@ -87,6 +87,9 @@
/* Define to 1 if you have the `osipparser2' library (-losipparser2). */
#undef HAVE_LIBOSIPPARSER2
/* Define to 1 if you have the `resolv' library (-lresolv). */
#undef HAVE_LIBRESOLV
/* Define to 1 if you have the `listen' function. */
#undef HAVE_LISTEN

View File

@ -34,6 +34,7 @@ dnl 08-Jan-2005 tries FreeBSD: check for libgnugetopt before using it
dnl Cygwin build support
dnl 13-Feb-2005 tries check for # of args on libosip2 functions
dnl 10-Apr-2005 tries check for docbook
dnl 18-Apr-2005 tries added libresolv
dnl
dnl
@ -369,6 +370,12 @@ AC_CHECK_TYPE(socklen_t,
)
dnl
dnl Checks for libraries
dnl
AC_CHECK_LIB(resolv,res_query,)
dnl
dnl Checks for library functions.
dnl

89
doc/FAQ
View File

@ -25,14 +25,14 @@ A: Scenario
private IP address range : Internet
10.0.0.x : (public IP address range)
:
: foo.bar.org xxx.org
+-------------+ +--------------+ +-------------+
! !.10 .1 ! masquerading ! publicIP ! !
:
: foo.bar.org xxx.org
+-------------+ +--------------+ +-------------+
! !.10 .1 ! masquerading ! publicIP ! !
! IntHost !-------------! Firewall !------------>>! externalHost!
! ! eth0! !ppp0 ! !
+-------------+ +--------------+ +-------------+
user: johndoe user: test
! ! eth0! !ppp0 ! !
+-------------+ +--------------+ +-------------+
user: johndoe user: test
- IntHost is running an SIP softphone (like linphone, kphone)
@ -244,20 +244,20 @@ A:
Full Name: My Name
User part of SIP URL: FWD_NUMBER
Host Part of SIP URL: fwd.pulver.com
Outbound Proxy: 192.168.1.1 <<-- local IP of siproxd
Outbound Proxy: 192.168.1.1 <<-- local IP of siproxd
Authentication Username: FWD_NUMBER
q-value: <<-- empty
q-value: <<-- empty
Preferences->SIP->Socket
------------------------
Socket Protocol: UDP
Use STUN Server: No
Symmetric Signalling: No (may also be 'Yes')
Symmetric Media: No (may also be 'Yes')
STUN Server: << n/a
Request Period for STUN Server << n/a
Media Min Port: 7070 << depend of siproxd config
Media Max Port: 7080 (RTP ports)
Symmetric Signalling: No (may also be 'Yes')
Symmetric Media: No (may also be 'Yes')
STUN Server: << n/a
Request Period for STUN Server << n/a
Media Min Port: 7070 << depend of siproxd config
Media Max Port: 7080 (RTP ports)
---------------------------------------------------------------------------
Q: If I update both inbound and outbound to
@ -276,64 +276,5 @@ A: Very likely this will not work properly. Siproxd does masquerade User
If you just want a proxy located in the public IP range you should not
use siproxd, but get a real SIP proxy server instead.
---------------------------------------------------------------------------
---------------------------------------------------------------------------
---------------------------------------------------------------------------
...
> Hier ist 40Mb logs mit overload problem. Wir haben auch probleme um neue
> verbindung einzustellen. Es ist wie ob den RTP timeout fur alle UA
> hinter den proxy bloquiert wenn eine bindung geschlossen wird. Nach 5 mn
> (oder 3 in unsere buro) geht es wieder ok (oder eine restart von
> siproxd). Manschmal, wenn eine von den beiden endpunkt die kommunikation
> schlisst, ist die andere immer noch up und denkt das die verbingun
> existiert. Wir haben den ganzen tag getestet mit lezte version von 17May:
>
> 2 intranet hinten siproxd, der eine ohne seine UA zu registrieren
> (192.168.1.0/24). Der andere hat 1 BudgeTone, 1 HandyTone, 2 xlite ten
> und 1 linphone als klient (192.168.10.0/24).
ACHTUNG!
Siproxd unterstützt zur Zeit lediglich 1 internes Netz und ein externes
Netz. ALLE lokalen UAs *müssen* sich:
- entweder bei SIPROXD registrieren
oder
- sich bei einem externen REGSITRAR registrieren (siproxd muss als
OUTBOUND PROXY konfiguriert sein).
Werden diese Spielregeln nicht eingehalten kommt es zu verschiedenen
komischen Effekten, auch solche die Du beschrieben hast.
UA1--+
|
UA2--+
|
UA3--+ +-----------+
| +-----------+ | externer |
+---------| siproxd & |------>>Internet <<---| Registrar |
| NAT | +-----------+
+-----------+
Spielregeln:
- ALLE UAs (UA1, UA2, UA3) benutzen siproxd also OUTBOUND proxy
- ALLE UAs (UA1, UA2, UA3) registrieren sich entweder direkt bei
siproxd ODER bei "externer Registrar"
Wenn Registrierung bei siproxd:
- SIP URL (address of record) hat die form SIP:<user>@<host>
- <user> ist frei wählbar
- <host> MUSS einen DNS Eintrag haben, der auf die public IP
von siproxd auflöst
Wenn Registrierung bei "externer Registrar":
- <user> und <domain> wird von "externer Registrar" definiert

View File

@ -115,7 +115,7 @@ rtp_proxy_enable = 1
# This should be a range that is not blocked by the firewall
#
rtp_port_low = 7070
rtp_port_high = 7079
rtp_port_high = 7089
######################################################################
# Timeout for RTP streams

View File

@ -29,7 +29,7 @@ sbin_PROGRAMS = siproxd
siproxd_SOURCES = siproxd.c proxy.c register.c sock.c utils.c \
sip_utils.c sip_layer.c log.c readconf.c rtpproxy.c \
rtpproxy_relay.c accessctl.c route_processing.c \
security.c auth.c fwapi.c
security.c auth.c fwapi.c resolve.c
#
# an example for a custom firewall control module

View File

@ -451,6 +451,8 @@ int proxy_request (sip_ticket_t *ticket) {
/*
* fixed or domain outbound proxy defined ?
*/
// let's try with Route header first
#if 0
if ((type == REQTYP_OUTGOING) &&
(sip_find_outbound_proxy(ticket, &sendto_addr, &port) == STS_SUCCESS)) {
DEBUGC(DBCLASS_PROXY, "proxy_request: have outbound proxy %s:%i",
@ -468,6 +470,25 @@ int proxy_request (sip_ticket_t *ticket) {
}
DEBUGC(DBCLASS_PROXY, "proxy_request: have Route header to %s:%i",
utils_inet_ntoa(sendto_addr), port);
#else
if ((type == REQTYP_OUTGOING) &&
(request->routes && !osip_list_eol(request->routes, 0))) {
sts=route_determine_nexthop(ticket, &sendto_addr, &port);
if (sts == STS_FAILURE) {
DEBUGC(DBCLASS_PROXY, "proxy_request: route_determine_nexthop failed");
return STS_FAILURE;
}
DEBUGC(DBCLASS_PROXY, "proxy_request: have Route header to %s:%i",
utils_inet_ntoa(sendto_addr), port);
} else if ((type == REQTYP_OUTGOING) &&
(sip_find_outbound_proxy(ticket, &sendto_addr, &port) == STS_SUCCESS)) {
DEBUGC(DBCLASS_PROXY, "proxy_request: have outbound proxy %s:%i",
utils_inet_ntoa(sendto_addr), port);
/*
* Route present?
* If so, fetch address from topmost Route: header and remove it.
*/
#endif
/*
* destination from SIP URI
*/
@ -872,6 +893,8 @@ int proxy_response (sip_ticket_t *ticket) {
/*
* check if we need to send to an outbound proxy
*/
// let's try with Route header first
#if 0
if ((type == RESTYP_OUTGOING) &&
(sip_find_outbound_proxy(ticket, &sendto_addr, &port) == STS_SUCCESS)) {
DEBUGC(DBCLASS_PROXY, "proxy_response: have outbound proxy %s:%i",
@ -889,6 +912,25 @@ int proxy_response (sip_ticket_t *ticket) {
}
DEBUGC(DBCLASS_PROXY, "proxy_response: have Route header to %s:%i",
utils_inet_ntoa(sendto_addr), port);
#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 if ((type == RESTYP_OUTGOING) &&
(sip_find_outbound_proxy(ticket, &sendto_addr, &port) == STS_SUCCESS)) {
DEBUGC(DBCLASS_PROXY, "proxy_response: have outbound proxy %s:%i",
utils_inet_ntoa(sendto_addr), port);
/*
* Route present?
* If so, fetch address from topmost Route: header and remove it.
*/
#endif
} else {
/* get target address and port from VIA header */
via = (osip_via_t *) osip_list_get (response->vias, 0);

218
src/resolve.c Normal file
View File

@ -0,0 +1,218 @@
/* -*- Mode: C; c-basic-offset: 3 -*-
Copyright (C) 2005 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 <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>
#include <string.h>
#include "log.h"
static char const ident[]="$Id$";
/* local functions */
static int _resolve(char *name, int proto, int type,
char *dname, int dnamelen, int *port);
#define PROTO_UDP 1
#define PROTO_TCP 2
/*
* perform a SRV record lookup
*/
int resolve_SRV(char *name, int proto, char *dname, int dnamelen, int *port) {
return _resolve(name, proto, T_SRV, dname, dnamelen, port);
}
/*
* perform a NAPTR lookup
*/
int resolve_NAPTR(char *name, char *dname, int dnamelen) {
int port=0;
return _resolve(name, 0, T_NAPTR, dname, dnamelen, &port);
}
/*
* query the DNS for a specific record type
*/
static int _resolve(char *name, int proto, int type,
char *dname, int dnamelen, int *port) {
int sts;
int class=C_ANY;
// message buffer
char msg[PACKETSZ];
int msglen=PACKETSZ;
// response header
HEADER *res_header;
// expanded name
char exp_dn[MAXDNAME];
int exp_dnlen=MAXDNAME;
int i, j, co;
char *mptr, *xptr;
unsigned short *usp,ty;
unsigned int *uip;
u_short priority = 0;
u_short weight = 0;
char tmpname[PACKETSZ];
dname[0]='\0';
*port=0;
// issue request
sts=res_query(name, class, type, msg, msglen);
if (sts<0) {
ERROR("res_query failed sts=%i\n", sts);
return 0;
}
res_header = (HEADER *)msg;
DEBUGC(DBCLASS_DNS, "_resolve: name=[%s], type=%i, qdcount=%i, ancount=%i",
name, type, ntohs(res_header->qdcount), ntohs(res_header->ancount));
mptr=msg+sizeof(HEADER);
// loop through query part
co=ntohs(res_header->qdcount);
for (i=0; i<co; i++) {
j=dn_expand(msg,msg+PACKETSZ,mptr,exp_dn,exp_dnlen);
DEBUGC(DBCLASS_DNS, "_resolve: Q - len=%i, name=[%s]", j, exp_dn);
if( j < 0 ) {
break;
} else {
mptr += j;
usp = (unsigned short *)mptr;
mptr += sizeof( short );
usp = (unsigned short *)mptr;
mptr += sizeof( short );
}
}
// loop through answer part
co=ntohs(res_header->ancount);
for (i=0; i<co; i++) {
j=dn_expand(msg,msg+PACKETSZ,mptr,exp_dn,exp_dnlen);
if( j < 0 ) {
ERROR("_resolve: dn_expand error");
break;
} else {
mptr += j;
usp = (unsigned short *)mptr;
ty = ntohs( *usp );
mptr += sizeof( short );
usp = (unsigned short *)mptr;
mptr += sizeof(short);
uip = (unsigned int *)mptr;
mptr += sizeof(int);
uip = (unsigned int *)mptr;
j = ntohs( *uip );
mptr += sizeof(short);
xptr = mptr;
mptr += j;
if( ty == T_NAPTR ) {
DEBUGC(DBCLASS_DNS, "_resolve: A - type NAPTR");
usp = (unsigned short *)xptr;
xptr += sizeof(short);
usp = (unsigned short *)xptr;
xptr += sizeof(short);
j = (int)(*xptr);
xptr += 1;
while( j > 0 ) {
xptr+=1;
j--;
}
j = (int)(*xptr);
xptr += 1;
while( j > 0 ) {
xptr += 1;
j--;
}
j=(int)(*xptr);
xptr+=1;
while( j > 0 ) {
xptr += 1;
j--;
}
j = dn_expand( msg, msg + PACKETSZ, xptr, tmpname, MAXDNAME );
if( j < 0 ) {
break;
} else {
/*
* there should be some REGEX magic, no?
*/
if( proto == PROTO_UDP ) {
if( strstr(tmpname, "_udp" ) ) {
strncpy(dname, tmpname, dnamelen);
}
} else {
if( strstr(tmpname, "_tcp" ) ) {
strncpy(dname, tmpname, dnamelen);
}
}
DEBUGC(DBCLASS_DNS, "_resolve: A[%i] - type NAPTR: %s",
i, tmpname);
xptr+=j;
}
} else if( ty == T_SRV ) {
u_short pr;
u_short we;
u_short po;
usp = (unsigned short *)xptr;
pr = ntohs( *usp );
xptr += sizeof( short );
usp = (unsigned short *)xptr;
we = ntohs( *usp );
xptr += sizeof( short );
usp = (unsigned short *)xptr;
po = ntohs( *usp );
xptr += sizeof( short );
j = dn_expand( msg, msg + PACKETSZ, xptr, tmpname, MAXDNAME );
if( j < 0 ) {
break;
} else {
DEBUGC(DBCLASS_DNS, "_resolve: A[%i] - type SRV pr=%i, we=%i, "
"po=%i name=[%s]", i, pr, we, po, tmpname);
if( !priority || pr < priority ||
(pr == priority && we < weight) ) {
priority = pr;
weight = we;
*port = po;
strncpy(dname, tmpname, dnamelen-1);
xptr+=j;
}
}
} else {
ERROR("_resolve: unknown type in DNS answer [type=%i]\n", ty);
} // if ty
} // if dn_expand
} // for i
dname[dnamelen-1]='\0';
return 0;
}

View File

@ -542,8 +542,13 @@ int rtp_relay_start_fwd (osip_call_id_t *callid, char *client_id,
num_ports = configuration.rtp_port_high - configuration.rtp_port_low + 1;
for (i2 = (prev_used_port - configuration.rtp_port_low + 1);
i2 < (num_ports + prev_used_port - configuration.rtp_port_low + 1);
i2 += 2) {
i2++) {
i = (i2%num_ports) + configuration.rtp_port_low;
DEBUGC(DBCLASS_RTP,"&&&& I=%i, i2=%i",i,i2);
/* only allow even port numbers */
if ((i % 2) != 0) continue;
for (j=0; j<RTPPROXY_SIZE; j++) {
/* check if port already in use */
if ((memcmp(&rtp_proxytable[j].local_ipaddr,