RTP traversal using UDP masquerading tunnels from user space

This commit is contained in:
Thomas Ries 2003-09-07 14:53:50 +00:00
parent d72215a733
commit a19661887f
10 changed files with 531 additions and 165 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
View 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
View 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
View 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;
}

View File

@ -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",