RTP traversal using UDP masquerading tunnels from user space
This commit is contained in:
parent
d72215a733
commit
a19661887f
@ -1,3 +1,8 @@
|
||||
0.3.6
|
||||
=====
|
||||
07-Sep-2003: - IPCHAINS based UPD tunneling (kernel masquerading)
|
||||
for RTP traffic (still experimental - but seems to work)
|
||||
|
||||
0.3.5
|
||||
=====
|
||||
30-Aug-2003: - released 0.3.5
|
||||
|
||||
@ -102,6 +102,9 @@
|
||||
/* Define if you have the <errno.h> header file. */
|
||||
#undef HAVE_ERRNO_H
|
||||
|
||||
/* Define if you have the <linux/ip_masq.h> header file. */
|
||||
#undef HAVE_LINUX_IP_MASQ_H
|
||||
|
||||
/* Define if you have the <pwd.h> header file. */
|
||||
#undef HAVE_PWD_H
|
||||
|
||||
|
||||
59
configure.in
59
configure.in
@ -13,6 +13,8 @@ dnl 6-Apr-2003 tries redone the fli4l specific build options
|
||||
dnl now: --enable-fli4l-libc5, --enable-fli4l-uclibc
|
||||
dnl 7-Apr-2003 tries added siproxd.spec to autoconf process
|
||||
dnl 31-Jul-2003 tries changed to support OSIP2 only
|
||||
dnl 1-Sep-2003 tries check for IPCHAINS
|
||||
dnl 5-Sep-2003 tries test for pthreads before libosip stuff
|
||||
dnl
|
||||
dnl
|
||||
dnl
|
||||
@ -28,7 +30,7 @@ dnl Release Version
|
||||
dnl
|
||||
SPD_MAJOR_VERSION=0
|
||||
SPD_MINOR_VERSION=3
|
||||
SPD_MICRO_VERSION=5
|
||||
SPD_MICRO_VERSION=6
|
||||
|
||||
SPD_VERSION=$SPD_MAJOR_VERSION.$SPD_MINOR_VERSION.$SPD_MICRO_VERSION
|
||||
|
||||
@ -86,6 +88,7 @@ case "$target" in
|
||||
*-*-linux*)
|
||||
AC_MSG_RESULT("Linux")
|
||||
AC_DEFINE(_LINUX,,[building on Linux platform])
|
||||
AC_CHECK_HEADERS(linux/ip_masq.h)
|
||||
;;
|
||||
*-*-freebsd*)
|
||||
AC_MSG_RESULT("FreeBSD")
|
||||
@ -166,6 +169,33 @@ else
|
||||
fi
|
||||
|
||||
|
||||
dnl
|
||||
dnl Check for pthreads
|
||||
dnl
|
||||
ACX_PTHREAD(,
|
||||
echo "*** ERROR: pthreads is required!"; exit 1;)
|
||||
if test "x$build_static_pthread" = "xno"; then
|
||||
dnl link dynamically (default)
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
CC="$PTHREAD_CC"
|
||||
else
|
||||
dnl link statically to this lib
|
||||
dnl (this probably only will work on linux yet...)
|
||||
AC_MSG_CHECKING("where I can find static threads library")
|
||||
libpthreads_static=`find $extra_libs /lib /usr/lib /usr/local/lib \
|
||||
-name 'lib*thread*.a' 2>/dev/null| \
|
||||
egrep 'lib[p]?thread[s]?.a' |head -1`
|
||||
if test "x$libpthreads_static" != "x"; then
|
||||
LIBS="$libpthreads_static $LIBS"
|
||||
AC_MSG_RESULT($libpthreads_static)
|
||||
else
|
||||
echo "*** ERROR: a static threads library is required!";exit 1;
|
||||
fi
|
||||
CC="$PTHREAD_CC"
|
||||
fi
|
||||
|
||||
|
||||
dnl
|
||||
dnl Check for libosip
|
||||
dnl
|
||||
@ -201,33 +231,6 @@ else
|
||||
fi
|
||||
|
||||
|
||||
dnl
|
||||
dnl Check for pthreads
|
||||
dnl
|
||||
ACX_PTHREAD(,
|
||||
echo "*** ERROR: pthreads is required!"; exit 1;)
|
||||
if test "x$build_static_pthread" = "xno"; then
|
||||
dnl link dynamically (default)
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
CC="$PTHREAD_CC"
|
||||
else
|
||||
dnl link statically to this lib
|
||||
dnl (this probably only will work on linux yet...)
|
||||
AC_MSG_CHECKING("where I can find static threads library")
|
||||
libpthreads_static=`find $extra_libs /lib /usr/lib /usr/local/lib \
|
||||
-name 'lib*thread*.a' 2>/dev/null| \
|
||||
egrep 'lib[p]?thread[s]?.a' |head -1`
|
||||
if test "x$libpthreads_static" != "x"; then
|
||||
LIBS="$libpthreads_static $LIBS"
|
||||
AC_MSG_RESULT($libpthreads_static)
|
||||
else
|
||||
echo "*** ERROR: a static threads library is required!";exit 1;
|
||||
fi
|
||||
CC="$PTHREAD_CC"
|
||||
fi
|
||||
|
||||
|
||||
dnl
|
||||
dnl Checks for header files.
|
||||
dnl
|
||||
|
||||
@ -68,7 +68,12 @@ user = nobody
|
||||
#chrootjail = /var/lib/siproxd/
|
||||
|
||||
######################################################################
|
||||
# global switch to enable (1) or disable (0) the RTP proxy feature
|
||||
# global switch to control the RTP proxy behaviour
|
||||
# 0 - RTP proxy disabled
|
||||
# 1 - RTP proxy (UDP relay of siproxd)
|
||||
# 2 - RTP masquerading (Siproxd will open masquerading tunnels
|
||||
# in the firewall. Requires ipchains.
|
||||
# NOTE: siproxd must be started by root!)
|
||||
#
|
||||
rtp_proxy_enable = 1
|
||||
|
||||
|
||||
@ -23,10 +23,11 @@ CFLAGS =@CFLAGS@ -Wall -DBUILDSTR=\"`cat .buildno`\" -D_GNU_SOURCE
|
||||
|
||||
bin_PROGRAMS = siproxd
|
||||
siproxd_SOURCES = siproxd.c proxy.c register.c sock.c utils.c \
|
||||
sip_utils.c log.c readconf.c rtpproxy.c accessctl.c \
|
||||
sip_utils.c log.c readconf.c rtpproxy.c \
|
||||
rtpproxy_relay.c rtpproxy_masq.c accessctl.c \
|
||||
security.c auth.c
|
||||
|
||||
noinst_HEADERS = log.h rewrite_rules.h siproxd.h digcalc.h
|
||||
noinst_HEADERS = log.h rewrite_rules.h siproxd.h digcalc.h rtpproxy.h
|
||||
|
||||
EXTRA_DIST = .buildno
|
||||
|
||||
|
||||
229
src/rtpproxy.c
229
src/rtpproxy.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (C) 2002 Thomas Ries <tries@gmx.net>
|
||||
Copyright (C) 2003 Thomas Ries <tries@gmx.net>
|
||||
|
||||
This file is part of Siproxd.
|
||||
|
||||
@ -35,6 +35,7 @@
|
||||
#include <osipparser2/osip_parser.h>
|
||||
|
||||
#include "siproxd.h"
|
||||
#include "rtpproxy.h"
|
||||
#include "log.h"
|
||||
|
||||
static char const ident[]="$Id: " __FILE__ ": " PACKAGE "-" VERSION "-"\
|
||||
@ -50,19 +51,7 @@ pthread_mutex_t rtp_proxytable_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
/*
|
||||
* table to remember all active rtp proxy streams
|
||||
*/
|
||||
#define CALLIDNUM_SIZE 256
|
||||
#define CALLIDHOST_SIZE 32
|
||||
struct {
|
||||
int sock;
|
||||
char callid_number[CALLIDNUM_SIZE];
|
||||
char callid_host[CALLIDHOST_SIZE];
|
||||
int media_stream_no;
|
||||
struct in_addr outbound_ipaddr;
|
||||
int outboundport;
|
||||
struct in_addr inbound_client_ipaddr;
|
||||
int inbound_client_port;
|
||||
time_t timestamp;
|
||||
} rtp_proxytable[RTPPROXY_SIZE];
|
||||
rtp_proxytable_t rtp_proxytable[RTPPROXY_SIZE];
|
||||
|
||||
|
||||
/* thread id of RTP proxy */
|
||||
@ -85,7 +74,7 @@ void sighdl_alm(int sig) {/* do nothing, just wake up from select() */};
|
||||
*/
|
||||
int rtpproxy_init( void ) {
|
||||
int sts;
|
||||
int arg=7;
|
||||
int arg=0;
|
||||
struct sigaction sigact;
|
||||
|
||||
/* clean proxy table */
|
||||
@ -106,11 +95,6 @@ int rtpproxy_init( void ) {
|
||||
sts=pthread_create(&rtpproxy_tid, NULL, rtpproxy_main, (void *)&arg);
|
||||
DEBUGC(DBCLASS_RTP,"created, sts=%i", sts);
|
||||
|
||||
#if 0 /* don't detach */
|
||||
// sts=pthread_detach(rtpproxy_tid);
|
||||
// DEBUGC(DBCLASS_RTP,"detached, sts=%i", sts);
|
||||
#endif
|
||||
|
||||
return STS_SUCCESS;
|
||||
}
|
||||
|
||||
@ -122,11 +106,9 @@ void *rtpproxy_main(void *arg) {
|
||||
fd_set fdset;
|
||||
int fd_max;
|
||||
time_t t, last_t=0;
|
||||
int i, count, sts;
|
||||
int i;
|
||||
int num_fd;
|
||||
static int rtp_socket=0;
|
||||
osip_call_id_t callid;
|
||||
char rtp_buff[RTP_BUFFER_SIZE];
|
||||
|
||||
memcpy(&fdset, &master_fdset, sizeof(fdset));
|
||||
fd_max=master_fd_max;
|
||||
@ -164,44 +146,42 @@ if (num_fd<0) {
|
||||
#endif
|
||||
time(&t);
|
||||
|
||||
if (configuration.rtp_proxy_enable) {
|
||||
|
||||
/*
|
||||
* LOCK the MUTEX
|
||||
*/
|
||||
pthread_mutex_lock(&rtp_proxytable_mutex);
|
||||
|
||||
/*
|
||||
* RTP relay configured
|
||||
*/
|
||||
if (configuration.rtp_proxy_enable == 1) {
|
||||
/* do the relaying of received UDP packets */
|
||||
rtp_relay(num_fd, &fdset, t);
|
||||
}
|
||||
|
||||
/* check for data available and send to destination */
|
||||
for (i=0;(i<RTPPROXY_SIZE) && (num_fd>0);i++) {
|
||||
if ( (rtp_proxytable[i].sock != 0) &&
|
||||
FD_ISSET(rtp_proxytable[i].sock, &fdset) ) {
|
||||
/* yup, have some data to send */
|
||||
|
||||
/* read from sock rtp_proxytable[i].sock*/
|
||||
count=read(rtp_proxytable[i].sock, rtp_buff, RTP_BUFFER_SIZE);
|
||||
|
||||
#ifdef MOREDEBUG /*&&&&*/
|
||||
if (count<0) {WARN("read() returned error [%s]",strerror(errno));}
|
||||
/*
|
||||
* RTP masquerading configured
|
||||
*/
|
||||
#if 0
|
||||
if (configuration.rtp_proxy_enable == 2) {
|
||||
/* do the masquerading - which means nothing here.
|
||||
* we only have to care that the UDP tunnels are
|
||||
* opened and closed */
|
||||
/* &&&&
|
||||
actually we have a problem here - as the incomming
|
||||
RTP data is out of our hands, how shall I know if
|
||||
this RTP stream now really has timed out or not...
|
||||
We might do a 'poll' for the local maddr & mport
|
||||
if it is still occupied.
|
||||
So... what do we do here? I think for now I just let
|
||||
the RTP stream expire and finished.
|
||||
*/
|
||||
}
|
||||
#endif
|
||||
|
||||
/* write to dest via socket rtp_inbound*/
|
||||
sts=sipsock_send_udp(&rtp_socket,
|
||||
rtp_proxytable[i].inbound_client_ipaddr,
|
||||
rtp_proxytable[i].inbound_client_port,
|
||||
rtp_buff, count, 0); /* don't dump it */
|
||||
#ifdef MOREDEBUG /*&&&&*/
|
||||
if (sts != STS_SUCCESS) {WARN("sipsock_send_udp() returned error");}
|
||||
#endif
|
||||
/* update timestamp of last usage */
|
||||
rtp_proxytable[i].timestamp=t;
|
||||
|
||||
num_fd--;
|
||||
}
|
||||
} /* for i */
|
||||
|
||||
|
||||
/* age and clean rtp_proxytable (check every 10 seconds)*/
|
||||
/*
|
||||
* age and clean rtp_proxytable (check every 10 seconds)
|
||||
*/
|
||||
if (t > (last_t+10) ) {
|
||||
last_t = t;
|
||||
for (i=0;i<RTPPROXY_SIZE; i++) {
|
||||
@ -210,11 +190,6 @@ if (sts != STS_SUCCESS) {WARN("sipsock_send_udp() returned error");}
|
||||
/* time one has expired, clean it up */
|
||||
callid.number=rtp_proxytable[i].callid_number;
|
||||
callid.host=rtp_proxytable[i].callid_host;
|
||||
#ifdef MOREDEBUG /*&&&&*/
|
||||
INFO("RTP stream sock=%i %s@%s (idx=%i) "
|
||||
"has expired", rtp_proxytable[i].sock,
|
||||
callid.number, callid.host, i);
|
||||
#endif
|
||||
DEBUGC(DBCLASS_RTP,"RTP stream sock=%i %s@%s (idx=%i) "
|
||||
"has expired", rtp_proxytable[i].sock,
|
||||
callid.number, callid.host, i);
|
||||
@ -232,8 +207,6 @@ INFO("RTP stream sock=%i %s@%s (idx=%i) "
|
||||
* UNLOCK the MUTEX
|
||||
*/
|
||||
pthread_mutex_unlock(&rtp_proxytable_mutex);
|
||||
|
||||
} /* rtp proxy enabled? */
|
||||
} /* for(;;) */
|
||||
|
||||
return NULL;
|
||||
@ -255,7 +228,7 @@ INFO("RTP stream sock=%i %s@%s (idx=%i) "
|
||||
int rtp_start_fwd (osip_call_id_t *callid, int media_stream_no,
|
||||
struct in_addr outbound_ipaddr, int *outboundport,
|
||||
struct in_addr lcl_client_ipaddr, int lcl_clientport) {
|
||||
int i, j;
|
||||
int j;
|
||||
int sock, port;
|
||||
int freeidx;
|
||||
int sts=STS_SUCCESS;
|
||||
@ -287,10 +260,6 @@ int rtp_start_fwd (osip_call_id_t *callid, int media_stream_no,
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
#ifdef MOREDEBUG /*&&&&*/
|
||||
INFO("starting RTP proxy stream for: %s@%s #=%i",
|
||||
callid->number, callid->host, media_stream_no);
|
||||
#endif
|
||||
DEBUGC(DBCLASS_RTP,"starting RTP proxy stream for: %s@%s #=%i",
|
||||
callid->number, callid->host, media_stream_no);
|
||||
|
||||
@ -306,7 +275,6 @@ INFO("starting RTP proxy stream for: %s@%s #=%i",
|
||||
* !! this minimizes the risk of deadlocks.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* figure out, if this is an request to start an RTP proxy stream
|
||||
* that is already existing (identified by SIP Call-ID and
|
||||
@ -329,35 +297,9 @@ INFO("starting RTP proxy stream for: %s@%s #=%i",
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* TODO: randomize the port allocation - start at a random offset to
|
||||
search in the allowed port range (so some modulo stuff w/
|
||||
random start offset
|
||||
- for i=x to (p1-p0)+x; p=p0+mod(x,p1-p0) */
|
||||
|
||||
/* find a local outbound port number to use and bind to it*/
|
||||
sock=0;
|
||||
port=0;
|
||||
for (i=configuration.rtp_port_low; i<=configuration.rtp_port_high; i++) {
|
||||
for (j=0; j<RTPPROXY_SIZE; j++) {
|
||||
/* outbound port already in use */
|
||||
if ((memcmp(&rtp_proxytable[j].outbound_ipaddr,
|
||||
&outbound_ipaddr, sizeof(struct in_addr))== 0) &&
|
||||
(rtp_proxytable[j].outboundport == i) ) break;
|
||||
}
|
||||
|
||||
/* port is available, try to allocate */
|
||||
if (j == RTPPROXY_SIZE) {
|
||||
port=i;
|
||||
sock=sockbind(outbound_ipaddr, port, 0);
|
||||
/* if success break, else try further on */
|
||||
if (sock) break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* find first free slot in rtp_proxytable */
|
||||
/*
|
||||
* find first free slot in rtp_proxytable
|
||||
*/
|
||||
freeidx=-1;
|
||||
for (j=0; j<RTPPROXY_SIZE; j++) {
|
||||
if (rtp_proxytable[j].sock==0) {
|
||||
@ -366,6 +308,44 @@ INFO("starting RTP proxy stream for: %s@%s #=%i",
|
||||
}
|
||||
}
|
||||
|
||||
/* rtp_proxytable port pool full? */
|
||||
if (freeidx == -1) {
|
||||
ERROR("rtp_start_fwd: rtp_proxytable is full!");
|
||||
sts = STS_FAILURE;
|
||||
goto unlock_and_exit;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* RTP relay configured
|
||||
*/
|
||||
if (configuration.rtp_proxy_enable == 1) {
|
||||
sts = rtp_relay_start_fwd(&sock, &port, outbound_ipaddr);
|
||||
|
||||
/* could bind to desired port? */
|
||||
if (sock == 0) {
|
||||
ERROR("rtp_start_fwd: unable to bind to outbound port!");
|
||||
sts = STS_FAILURE;
|
||||
goto unlock_and_exit;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* RTP masquerading configured
|
||||
*/
|
||||
if (configuration.rtp_proxy_enable == 2) {
|
||||
/* do the masquerading - which means to open up
|
||||
* an UDP tunnel in the firewall within the desired range */
|
||||
sts = rtp_masq_start_fwd(freeidx, outbound_ipaddr, &port,
|
||||
lcl_client_ipaddr, lcl_clientport);
|
||||
if (sts != STS_SUCCESS) {
|
||||
ERROR("rtp_start_fwd: unable to create masquerading tunnel!");
|
||||
sts = STS_FAILURE;
|
||||
goto unlock_and_exit;
|
||||
}
|
||||
sock=1; /* 0 indicates 'not allocated' - so we simply put in non-zero */
|
||||
}
|
||||
|
||||
DEBUGC(DBCLASS_RTP,"rtp_start_fwd: port=%i, sock=%i freeidx=%i",
|
||||
port, sock, freeidx);
|
||||
|
||||
@ -376,20 +356,6 @@ INFO("starting RTP proxy stream for: %s@%s #=%i",
|
||||
goto unlock_and_exit;
|
||||
}
|
||||
|
||||
/* could bind to desired port? */
|
||||
if (sock == 0) {
|
||||
ERROR("rtp_start_fwd: unable to allocate outbound port!");
|
||||
sts = STS_FAILURE;
|
||||
goto unlock_and_exit;
|
||||
}
|
||||
|
||||
/* rtp_proxytable port pool full? */
|
||||
if (freeidx == -1) {
|
||||
ERROR("rtp_start_fwd: rtp_proxytable is full!");
|
||||
sts = STS_FAILURE;
|
||||
goto unlock_and_exit;
|
||||
}
|
||||
|
||||
/* write entry into rtp_proxytable slot (freeidx) */
|
||||
rtp_proxytable[freeidx].sock=sock;
|
||||
strcpy(rtp_proxytable[freeidx].callid_number, callid->number);
|
||||
@ -440,10 +406,6 @@ int rtp_stop_fwd (osip_call_id_t *callid, int nolock) {
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
#ifdef MOREDEBUG /*&&&&*/
|
||||
INFO("stopping RTP proxy stream for: %s@%s",
|
||||
callid->number, callid->host);
|
||||
#endif
|
||||
DEBUGC(DBCLASS_RTP,"stopping RTP proxy stream for: %s@%s",
|
||||
callid->number, callid->host);
|
||||
|
||||
@ -484,23 +446,34 @@ INFO("stopping RTP proxy stream for: %s@%s",
|
||||
(strcmp(rtp_proxytable[i].callid_number, callid->number)==0) &&
|
||||
(strcmp(rtp_proxytable[i].callid_host, callid->host)==0) ) {
|
||||
|
||||
/* match: close socket and clean slot in rtp_proxytable */
|
||||
sts = close(rtp_proxytable[i].sock);
|
||||
if (sts < 0) {
|
||||
ERROR("Error in close(%i): %s nolock=%i %s:%s\n",
|
||||
rtp_proxytable[i].sock,
|
||||
strerror(errno), nolock,
|
||||
callid->number, callid->host);
|
||||
/*
|
||||
* RTP relay configured
|
||||
*/
|
||||
if (configuration.rtp_proxy_enable == 1) {
|
||||
sts = rtp_relay_stop_fwd(rtp_proxytable[i].sock);
|
||||
DEBUGC(DBCLASS_RTP,"closed socket %i for RTP stream "
|
||||
"%s:%s == %s:%s (idx=%i) sts=%i",
|
||||
rtp_proxytable[i].sock,
|
||||
rtp_proxytable[i].callid_number,
|
||||
rtp_proxytable[i].callid_host,
|
||||
callid->number, callid->host, i, sts);
|
||||
if (sts < 0) {
|
||||
ERROR("Error in close(%i): %s nolock=%i %s:%s\n",
|
||||
rtp_proxytable[i].sock,
|
||||
strerror(errno), nolock,
|
||||
callid->number, callid->host);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* RTP masquerading configured
|
||||
*/
|
||||
if (configuration.rtp_proxy_enable == 2) {
|
||||
/* do the masquerading - which means to open up
|
||||
* an UDP tunnel in the firewall within the desired range */
|
||||
sts = rtp_masq_stop_fwd(i);
|
||||
}
|
||||
|
||||
DEBUGC(DBCLASS_RTP,"closing socket %i for RTP stream "
|
||||
"%s:%s == %s:%s (idx=%i) sts=%i",
|
||||
rtp_proxytable[i].sock,
|
||||
rtp_proxytable[i].callid_number,
|
||||
rtp_proxytable[i].callid_host,
|
||||
callid->number,
|
||||
callid->host,
|
||||
i, sts);
|
||||
memset(&rtp_proxytable[i], 0, sizeof(rtp_proxytable[0]));
|
||||
got_match=1;
|
||||
}
|
||||
|
||||
50
src/rtpproxy.h
Normal file
50
src/rtpproxy.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
Copyright (C) 2003 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
|
||||
*/
|
||||
|
||||
#define CALLIDNUM_SIZE 256
|
||||
#define CALLIDHOST_SIZE 32
|
||||
|
||||
typedef struct {
|
||||
int sock;
|
||||
char callid_number[CALLIDNUM_SIZE]; /* call ID */
|
||||
char callid_host[CALLIDHOST_SIZE]; /* --"-- */
|
||||
int media_stream_no;
|
||||
struct in_addr outbound_ipaddr; /* lcl outbound IP */
|
||||
int outboundport; /* lcl allocd outbound port */
|
||||
struct in_addr inbound_client_ipaddr; /* lcl inbound UA IP */
|
||||
int inbound_client_port; /* lcl inbound UA port */
|
||||
time_t timestamp; /* last 'stream alive' TS */
|
||||
} rtp_proxytable_t;
|
||||
|
||||
/*
|
||||
* RTP relay
|
||||
*/
|
||||
void rtp_relay (int num_fd, fd_set *fdset, time_t t);
|
||||
int rtp_relay_start_fwd(int *sock, int *port, struct in_addr outbound_ipaddr);
|
||||
int rtp_relay_stop_fwd(int sock);
|
||||
|
||||
|
||||
/*
|
||||
* RTP masquerading
|
||||
*/
|
||||
int rtp_masq_start_fwd(int proxy_idx,
|
||||
struct in_addr outbound_ipaddr, int *outbound_lcl_port,
|
||||
struct in_addr lcl_client_ipaddr, int lcl_clientport);
|
||||
int rtp_masq_stop_fwd(int proxy_idx);
|
||||
201
src/rtpproxy_masq.c
Normal file
201
src/rtpproxy_masq.c
Normal file
@ -0,0 +1,201 @@
|
||||
/*
|
||||
Copyright (C) 2003 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 <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#if defined(HAVE_LINUX_IP_MASQ_H)
|
||||
/* masq specific stuff */
|
||||
#include <asm/types.h> /* For __uXX types */
|
||||
#include <net/if.h>
|
||||
#include <netinet/ip_icmp.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <linux/ip_fw.h> /* For IP_FW_MASQ_CTL */
|
||||
#include <linux/ip_masq.h> /* For specific masq defs */
|
||||
#include <asm/param.h>
|
||||
#endif
|
||||
|
||||
#include <osipparser2/osip_parser.h>
|
||||
|
||||
#include "siproxd.h"
|
||||
#include "rtpproxy.h"
|
||||
#include "log.h"
|
||||
|
||||
static char const ident[]="$Id: " __FILE__ ": " PACKAGE "-" VERSION "-"\
|
||||
BUILDSTR " $";
|
||||
|
||||
|
||||
/* configuration storage */
|
||||
extern struct siproxd_config configuration;
|
||||
|
||||
/* table to remember all active rtp proxy streams */
|
||||
extern rtp_proxytable_t rtp_proxytable[];
|
||||
|
||||
#if defined(HAVE_LINUX_IP_MASQ_H)
|
||||
/* socket for controlling the MASQ tunnels */
|
||||
static int masq_ctl_sock=0;
|
||||
|
||||
/* table to remember all masquerading tunnels (1:1 with rtp_proxytable) */
|
||||
struct ip_masq_ctl masq_table[RTPPROXY_SIZE];
|
||||
|
||||
/*
|
||||
* local prototypes
|
||||
*/
|
||||
int _create_listening_masq(struct ip_masq_ctl *masq,
|
||||
struct in_addr lcl_addr, int lcl_port,
|
||||
struct in_addr msq_addr, int msq_port);
|
||||
|
||||
int _delete_listening_masq(struct ip_masq_ctl *masq);
|
||||
|
||||
/************************************************************
|
||||
THIS HERE WILL ONLY WORK IF SIPROXD IS STARTED SUID ROOT !!
|
||||
However it is working when started root and then changed
|
||||
UID to eg. nobody - we'll just raise the privileged when
|
||||
we need to fiddle with the masquerading
|
||||
*************************************************************/
|
||||
|
||||
int rtp_masq_start_fwd(int proxy_idx,
|
||||
struct in_addr outbound_ipaddr, int *outbound_lcl_port,
|
||||
struct in_addr lcl_client_ipaddr, int lcl_clientport) {
|
||||
int sts, i;
|
||||
DEBUGC(DBCLASS_RTP,"rtp_masq_start_fwd: local UA:%s:%i",
|
||||
inet_ntoa(lcl_client_ipaddr),lcl_clientport);
|
||||
/*
|
||||
* do loop over the range of available ports (7070-...) until able to
|
||||
* allocate a UDP tunnel. If not successful - Buh! return port=0
|
||||
*/
|
||||
for (i=configuration.rtp_port_low; i<=configuration.rtp_port_high; i++) {
|
||||
*outbound_lcl_port=i;
|
||||
sts = _create_listening_masq(&masq_table[proxy_idx],
|
||||
lcl_client_ipaddr, lcl_clientport,
|
||||
outbound_ipaddr, *outbound_lcl_port);
|
||||
/* if success break, else try further on */
|
||||
if (sts == STS_SUCCESS) break;
|
||||
*outbound_lcl_port=0;
|
||||
} /* for i */
|
||||
|
||||
DEBUGC(DBCLASS_RTP,"rtp_masq_start_fwd: masq address & port:%s:%i",
|
||||
inet_ntoa(outbound_ipaddr),outbound_lcl_port);
|
||||
return (*outbound_lcl_port)?STS_SUCCESS:STS_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
int rtp_masq_stop_fwd(int proxy_idx) {
|
||||
return _delete_listening_masq(&masq_table[proxy_idx]);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* helper routines
|
||||
*/
|
||||
int _create_listening_masq(struct ip_masq_ctl *masq,
|
||||
struct in_addr lcl_addr, int lcl_port,
|
||||
struct in_addr msq_addr, int msq_port) {
|
||||
int uid,euid;
|
||||
int sts=STS_SUCCESS;
|
||||
|
||||
/* elevate privileges */
|
||||
uid=getuid();
|
||||
euid=geteuid();
|
||||
if (uid != euid) seteuid(0);
|
||||
|
||||
if (geteuid()!=0) {
|
||||
ERROR("create_listening_masq: must be running under UID root!");
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
if (masq_ctl_sock==0) {
|
||||
masq_ctl_sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
|
||||
if (masq_ctl_sock<0) {
|
||||
ERROR("create_listening_masq: allocating control socket() failed: %s",
|
||||
strerror(errno));
|
||||
sts = STS_FAILURE;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
memset (masq, 0, sizeof (*masq));
|
||||
|
||||
masq->m_target = IP_MASQ_TARGET_USER;
|
||||
masq->m_cmd = IP_MASQ_CMD_INSERT;
|
||||
masq->u.user.protocol= IPPROTO_UDP;
|
||||
|
||||
memcpy(&masq->u.user.saddr, &lcl_addr, sizeof(lcl_addr));
|
||||
masq->u.user.sport = htons(lcl_port);
|
||||
|
||||
memcpy(&masq->u.user.maddr, &msq_addr, sizeof(msq_addr));
|
||||
masq->u.user.mport = htons(msq_port);
|
||||
|
||||
if (setsockopt(masq_ctl_sock, IPPROTO_IP,
|
||||
IP_FW_MASQ_CTL, (char *)masq, sizeof(*masq))) {
|
||||
ERROR("create_listening_masq: setsockopt() failed: %s",
|
||||
strerror(errno));
|
||||
sts = STS_FAILURE;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* set short timeout for expiration
|
||||
*/
|
||||
masq->m_cmd = IP_MASQ_CMD_SET;
|
||||
masq->u.user.timeout = 10*HZ;
|
||||
if (setsockopt(masq_ctl_sock, IPPROTO_IP,
|
||||
IP_FW_MASQ_CTL, (char *)masq, sizeof(*masq))) {
|
||||
ERROR("create_listening_masq: setsockopt() failed: %s",
|
||||
strerror(errno));
|
||||
sts = STS_FAILURE;
|
||||
goto exit;
|
||||
}
|
||||
#endif
|
||||
|
||||
exit:
|
||||
/* drop privileges */
|
||||
if (uid != euid) seteuid(euid);
|
||||
return sts;
|
||||
}
|
||||
|
||||
int _delete_listening_masq(struct ip_masq_ctl *masq) {
|
||||
return STS_SUCCESS;
|
||||
}
|
||||
#else
|
||||
/*
|
||||
* don't have ipchains or iptables - dummy routines and complain
|
||||
*/
|
||||
|
||||
int rtp_masq_start_fwd(int proxy_idx,
|
||||
struct in_addr outbound_ipaddr, int *outbound_lcl_port,
|
||||
struct in_addr lcl_client_ipaddr, int lcl_clientport){
|
||||
outbound_lcl_port=0;
|
||||
ERROR("Masquerading support is not enabled (compile time config option)");
|
||||
return STS_FAILURE;
|
||||
}
|
||||
int rtp_masq_stop_fwd(int proxy_idx) {
|
||||
return STS_FAILURE;
|
||||
}
|
||||
#endif
|
||||
125
src/rtpproxy_relay.c
Normal file
125
src/rtpproxy_relay.c
Normal file
@ -0,0 +1,125 @@
|
||||
/*
|
||||
Copyright (C) 2003 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 <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <osipparser2/osip_parser.h>
|
||||
|
||||
#include "siproxd.h"
|
||||
#include "rtpproxy.h"
|
||||
#include "log.h"
|
||||
|
||||
static char const ident[]="$Id: " __FILE__ ": " PACKAGE "-" VERSION "-"\
|
||||
BUILDSTR " $";
|
||||
|
||||
|
||||
/* configuration storage */
|
||||
extern struct siproxd_config configuration;
|
||||
|
||||
/*
|
||||
* table to remember all active rtp proxy streams
|
||||
*/
|
||||
extern rtp_proxytable_t rtp_proxytable[];
|
||||
|
||||
|
||||
|
||||
void rtp_relay (int num_fd, fd_set *fdset, time_t t) {
|
||||
int i;
|
||||
int count;
|
||||
int sts;
|
||||
static int rtp_socket=0;
|
||||
static char rtp_buff[RTP_BUFFER_SIZE];
|
||||
/* check for data available and send to destination */
|
||||
for (i=0;(i<RTPPROXY_SIZE) && (num_fd>0);i++) {
|
||||
if ( (rtp_proxytable[i].sock != 0) &&
|
||||
FD_ISSET(rtp_proxytable[i].sock, fdset) ) {
|
||||
/* yup, have some data to send */
|
||||
|
||||
/* read from sock rtp_proxytable[i].sock*/
|
||||
count=read(rtp_proxytable[i].sock, rtp_buff, RTP_BUFFER_SIZE);
|
||||
|
||||
#ifdef MOREDEBUG /*&&&&*/
|
||||
if (count<0) {WARN("read() returned error [%s]",strerror(errno));}
|
||||
#endif
|
||||
|
||||
/* write to dest via socket rtp_inbound*/
|
||||
sts=sipsock_send_udp(&rtp_socket,
|
||||
rtp_proxytable[i].inbound_client_ipaddr,
|
||||
rtp_proxytable[i].inbound_client_port,
|
||||
rtp_buff, count, 0); /* don't dump it */
|
||||
#ifdef MOREDEBUG /*&&&&*/
|
||||
if (sts != STS_SUCCESS) {WARN("sipsock_send_udp() returned error");}
|
||||
#endif
|
||||
/* update timestamp of last usage */
|
||||
rtp_proxytable[i].timestamp=t;
|
||||
|
||||
num_fd--;
|
||||
}
|
||||
} /* for i */
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
int rtp_relay_start_fwd(int *sock, int *port, struct in_addr outbound_ipaddr) {
|
||||
int i, j;
|
||||
/* TODO: randomize the port allocation - start at a random offset to
|
||||
search in the allowed port range (so some modulo stuff w/
|
||||
random start offset
|
||||
- for i=x to (p1-p0)+x; p=p0+mod(x,p1-p0) */
|
||||
|
||||
/* find a local outbound port number to use and bind to it*/
|
||||
*sock=0;
|
||||
*port=0;
|
||||
for (i=configuration.rtp_port_low; i<=configuration.rtp_port_high; i++) {
|
||||
for (j=0; j<RTPPROXY_SIZE; j++) {
|
||||
/* outbound port already in use */
|
||||
if ((memcmp(&rtp_proxytable[j].outbound_ipaddr,
|
||||
&outbound_ipaddr, sizeof(struct in_addr))== 0) &&
|
||||
(rtp_proxytable[j].outboundport == i) ) break;
|
||||
}
|
||||
|
||||
/* port is available, try to allocate */
|
||||
if (j == RTPPROXY_SIZE) {
|
||||
*port=i;
|
||||
*sock=sockbind(outbound_ipaddr, *port, 0);
|
||||
/* if success break, else try further on */
|
||||
if (*sock) break;
|
||||
}
|
||||
} /* for i */
|
||||
|
||||
return (*sock)?STS_SUCCESS:STS_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
int rtp_relay_stop_fwd(int sock) {
|
||||
int sts;
|
||||
|
||||
sts = close(sock);
|
||||
return sts;
|
||||
}
|
||||
12
src/utils.c
12
src/utils.c
@ -175,13 +175,12 @@ void secure_enviroment (void) {
|
||||
DEBUGC(DBCLASS_CONFIG,"running w/uid=%i, euid=%i, gid=%i, egid=%i",
|
||||
getuid(), geteuid(), getgid(), getegid());
|
||||
|
||||
if ((getuid()==0)|| (geteuid()==0)) {
|
||||
if ((getuid()==0) || (geteuid()==0)) {
|
||||
/*
|
||||
* preparation - after chrooting there will be NOTHING more around
|
||||
*/
|
||||
if (configuration.user) passwd=getpwnam(configuration.user);
|
||||
|
||||
|
||||
/*
|
||||
* change root directory into chroot jail
|
||||
*/
|
||||
@ -194,7 +193,6 @@ void secure_enviroment (void) {
|
||||
chdir("/");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* change user ID and group ID
|
||||
*/
|
||||
@ -209,9 +207,11 @@ void secure_enviroment (void) {
|
||||
DEBUGC(DBCLASS_CONFIG,"changed egid to %i - %s",
|
||||
passwd->pw_gid, (sts==0)?"Ok":"Failed");
|
||||
|
||||
sts = setuid(passwd->pw_uid);
|
||||
DEBUGC(DBCLASS_CONFIG,"changed uid to %i - %s",
|
||||
passwd->pw_uid, (sts==0)?"Ok":"Failed");
|
||||
/* don't set the real user id - as we need to elevate privs
|
||||
when setting up an RTP masquerading tunnel */
|
||||
// sts = setuid(passwd->pw_uid);
|
||||
// DEBUGC(DBCLASS_CONFIG,"changed uid to %i - %s",
|
||||
// passwd->pw_uid, (sts==0)?"Ok":"Failed");
|
||||
|
||||
sts = seteuid(passwd->pw_uid);
|
||||
DEBUGC(DBCLASS_CONFIG,"changed euid to %i - %s",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user