From ab08d2febfe06ca2e61b13e496253286845fb215 Mon Sep 17 00:00:00 2001 From: Thomas Ries Date: Wed, 31 Aug 2005 03:34:35 +0000 Subject: [PATCH] - allocate only even RTP port numbers - started with own name lookup routines that honor SRV and NAPTR records --- ChangeLog | 1 + config.h.in | 3 + configure.in | 7 ++ doc/FAQ | 89 +++------------- doc/siproxd.conf.example | 2 +- src/Makefile.am | 2 +- src/proxy.c | 42 ++++++++ src/resolve.c | 218 +++++++++++++++++++++++++++++++++++++++ src/rtpproxy_relay.c | 7 +- 9 files changed, 294 insertions(+), 77 deletions(-) create mode 100644 src/resolve.c diff --git a/ChangeLog b/ChangeLog index fa69564..8bb5701 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,6 @@ 0.5.12 ====== + 14-Jul-2005: - allocate only even port numbers for RTP traffic 0.5.11 ====== diff --git a/config.h.in b/config.h.in index dc4ecb8..f5c2e44 100644 --- a/config.h.in +++ b/config.h.in @@ -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 diff --git a/configure.in b/configure.in index f062396..48d3462 100644 --- a/configure.in +++ b/configure.in @@ -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 diff --git a/doc/FAQ b/doc/FAQ index 540ceee..b616add 100644 --- a/doc/FAQ +++ b/doc/FAQ @@ -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:@ - - ist frei wählbar - - MUSS einen DNS Eintrag haben, der auf die public IP - von siproxd auflöst - - - Wenn Registrierung bei "externer Registrar": - - und wird von "externer Registrar" definiert - diff --git a/doc/siproxd.conf.example b/doc/siproxd.conf.example index 97b97c8..060afba 100644 --- a/doc/siproxd.conf.example +++ b/doc/siproxd.conf.example @@ -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 diff --git a/src/Makefile.am b/src/Makefile.am index 55c53fb..f603beb 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 diff --git a/src/proxy.c b/src/proxy.c index 7d6db38..5ce1e71 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -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); diff --git a/src/resolve.c b/src/resolve.c new file mode 100644 index 0000000..88069a4 --- /dev/null +++ b/src/resolve.c @@ -0,0 +1,218 @@ +/* -*- Mode: C; c-basic-offset: 3 -*- + Copyright (C) 2005 Thomas Ries + + 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 +#include +#include +#include + +#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; iancount); + for (i=0; i 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; +} diff --git a/src/rtpproxy_relay.c b/src/rtpproxy_relay.c index c6a7284..01b362e 100644 --- a/src/rtpproxy_relay.c +++ b/src/rtpproxy_relay.c @@ -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