this is 0.1.3
- Bugfixes in the SIP proxy part - Performance imporvement in RTP proxy part - some documentation updates - include ./scripts subdirectory in the distribution, was an error in the autoconf/automake setup
This commit is contained in:
parent
038f5ef904
commit
c3e10ec745
18
ChangeLog
18
ChangeLog
@ -1,3 +1,21 @@
|
|||||||
|
0.1.3
|
||||||
|
=====
|
||||||
|
- 11-Sep-2002: - Fixed a error in the autoconf/automake part of the project.
|
||||||
|
(scripts subdirectory was missing in the tar.gz archive.
|
||||||
|
This resulted in an error during ./configure - complaining
|
||||||
|
about non existent install-sh script)
|
||||||
|
- startup is more silent - set initial debug level to 0
|
||||||
|
- 10-Sep-2002: - Some (yea, I know...) -minor- docu updates
|
||||||
|
- 8-Sep-2002: - Masquerade Contact Headers of inbound clients
|
||||||
|
(Contact header will be used by the remote SIP
|
||||||
|
user agent to directly contact the local user agent -
|
||||||
|
and bypassing the proxy. This of course will *not* work
|
||||||
|
if the local user agent is located in a private IP range.)
|
||||||
|
- Performance optimizations in RTP proxy
|
||||||
|
- Bugfix: now masqueraded clients work with any
|
||||||
|
SIP port (other than 5060). Before, incomming
|
||||||
|
requests/responses where always sent to port 5060.
|
||||||
|
|
||||||
0.1.2
|
0.1.2
|
||||||
=====
|
=====
|
||||||
- 7-Sep-2002: - Releases version 0.1.2
|
- 7-Sep-2002: - Releases version 0.1.2
|
||||||
|
|||||||
@ -21,4 +21,4 @@
|
|||||||
|
|
||||||
SUBDIRS = src doc
|
SUBDIRS = src doc
|
||||||
|
|
||||||
EXTRA_DIST = TODO RELNOTES
|
EXTRA_DIST = scripts TODO RELNOTES
|
||||||
|
|||||||
@ -87,7 +87,7 @@ VERSION = @VERSION@
|
|||||||
|
|
||||||
SUBDIRS = src doc
|
SUBDIRS = src doc
|
||||||
|
|
||||||
EXTRA_DIST = TODO RELNOTES
|
EXTRA_DIST = scripts TODO RELNOTES
|
||||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||||
mkinstalldirs = $(SHELL) $(top_srcdir)/scripts/mkinstalldirs
|
mkinstalldirs = $(SHELL) $(top_srcdir)/scripts/mkinstalldirs
|
||||||
CONFIG_HEADER = config.h
|
CONFIG_HEADER = config.h
|
||||||
|
|||||||
155
README
155
README
@ -4,8 +4,8 @@ Be warned, this (and all the other) documentantation is far from
|
|||||||
complete. This is still considered an alpha release.
|
complete. This is still considered an alpha release.
|
||||||
|
|
||||||
|
|
||||||
Overview:
|
OVERVIEW
|
||||||
=========
|
========
|
||||||
Siprox is an proxy/masquerading daemon for the SIP protocol.
|
Siprox is an proxy/masquerading daemon for the SIP protocol.
|
||||||
It handles registrations of SIP clients on a private IP network
|
It handles registrations of SIP clients on a private IP network
|
||||||
and performs rewriting of the SIP message bodies to make SIP
|
and performs rewriting of the SIP message bodies to make SIP
|
||||||
@ -20,17 +20,18 @@ IP addresses and port numbers.
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
Requirements:
|
REQUIREMENTS
|
||||||
=============
|
============
|
||||||
- libosip-0.8.8 (http://www.fsf.org/software/osip/)
|
- libosip-0.8.8 (http://www.fsf.org/software/osip/)
|
||||||
|
- pthreads (should be part of any Linux distribution)
|
||||||
|
|
||||||
Up to now, this packages only has been tested under an i386 Redhat Linux 6.0.
|
Up to now, siporxd only has been tested under an i386 Redhat Linux 6.0.
|
||||||
However, it should build and run under newer versions (feedback is welcome).
|
However, it should build and run under newer versions (feedback is welcome).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
How to get started:
|
HOW TO GET STARTED
|
||||||
===================
|
==================
|
||||||
|
|
||||||
- ./configure
|
- ./configure
|
||||||
|
|
||||||
@ -38,82 +39,124 @@ How to get started:
|
|||||||
|
|
||||||
- make install
|
- make install
|
||||||
|
|
||||||
- copy sipproxd.conf.example to /etc/siproxd.conf
|
- copy doc/sipproxd.conf.example to /etc/siproxd.conf
|
||||||
|
|
||||||
- edit /etc/siproxd.conf according to your situation
|
- edit /etc/siproxd.conf according to your situation
|
||||||
At least 'host_inbound' and 'host_outbound' have to be adapted!
|
At least 'host_inbound' and 'host_outbound' *must* be adapted!
|
||||||
host_inbound is your IP address of your private network,
|
'host_inbound' is the firewalls IP address of your private network,
|
||||||
host_outbound is your publich IP address or hostname (if you
|
'host_outbound' is the publich IP address or hostname of the
|
||||||
have dynamic IP addresses, then you might want to use a hostname
|
firewall. (If you have dynamic IP addresses, then you might want
|
||||||
here and use a dynamic DNS service like dyndns.org)
|
to use a hostname here and use a dynamic DNS service like [1])
|
||||||
|
|
||||||
|
- start siproxd (siproxd does *not* require root privilegdes)
|
||||||
|
$ siproxd
|
||||||
|
|
||||||
|
|
||||||
|
WHAT SIPROXD DOES
|
||||||
What siproxd does:
|
|
||||||
=================
|
=================
|
||||||
Siproxd's main purpose (up to now) is to rewrite SIP messages
|
Siproxd's purpose is to act as an SIP proxy for softphones located
|
||||||
to be able to operate via an masquerading firewall.
|
in private IP ranges. Therefore it will rewrite SIP messages to allow a
|
||||||
Since release 0.1.2 siproxd can proxy incomming RTP streams.
|
softphone to communicate to a counterpart that is located in the Internet.
|
||||||
|
There usually will be a masquerading firewall in between to 'hide' the
|
||||||
|
private IP range (either via NAT - network address translation or
|
||||||
|
masuerading). Check the scenario drawn below.
|
||||||
|
|
||||||
|
With release 0.1.2 siproxd is also able to proxy incomming RTP data
|
||||||
|
streams. The config parameters 'rtp_port_low' and rtp_port_high' define
|
||||||
What siproxd does NOT do:
|
|
||||||
=========================
|
|
||||||
|
|
||||||
SINCE RELEASE 0.1.2:
|
|
||||||
Siproxd should be able to proxy incomming RTP data streams (UDP only).
|
|
||||||
This is still very experimental code ;-)
|
|
||||||
The config parameters 'rtp_port_low' and rtp_port_high' define
|
|
||||||
the port range that siproxd will use for incomming RTP data streams.
|
the port range that siproxd will use for incomming RTP data streams.
|
||||||
'rtp_timeout' defines after what time an unused (no data received)
|
'rtp_timeout' defines after what time an unused (no data received)
|
||||||
rtp stream is considered dead and removed.
|
rtp stream is considered dead and removed.
|
||||||
|
|
||||||
** As I had not yet the possibility to test this feature,
|
** RTP data stream proxying is still experimental code.
|
||||||
** I'd be glad about feedback.
|
** As I had not yet the possibility to test this feature extensively,
|
||||||
|
** I'm happy about any feedback.
|
||||||
PRIOR TO RELEASE 0.1.2:
|
|
||||||
Siproxd does *not* (yet) create masquerading tunnels or port-forwarding
|
|
||||||
for the data stream through the firewall.
|
|
||||||
|
|
||||||
These forwarding rules have to be set-up manually (currently)
|
|
||||||
|
|
||||||
Example, using ipchains (mfw):
|
|
||||||
# ipchains -A input --proto udp --dport 7078 -m 100 -j ACCEPT
|
|
||||||
# ipmasqadm mfw -A -m 100 -r <remoteaddress> 7078
|
|
||||||
|
|
||||||
Example, using ipchains (portfw):
|
|
||||||
# portfw -a -P udp -L <localaddress> 7078 -R <remoteaddress> 7078
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Limitations:
|
Scenario
|
||||||
============
|
--------
|
||||||
- currently, only UDP is supported
|
|
||||||
- very likely it does not follow the SIP spec in all details ;-)
|
private IP address range : Internet
|
||||||
|
10.0.0.x : (publich IP address range)
|
||||||
|
:
|
||||||
|
: foo.bar.org
|
||||||
|
+-------------+ +--------------+
|
||||||
|
! !.10 .1 ! masquerading ! publicIP
|
||||||
|
! IntHost !---------------! Firewall !------------>>
|
||||||
|
! ! ! !
|
||||||
|
+-------------+ +--------------+
|
||||||
|
:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Important Notice:
|
- The Firewall does IP masquerading and is running siproxd
|
||||||
=================
|
|
||||||
The gethostbyname() function leaks memory in RedHat 6.0 with glibc 2.1.1.
|
- IntHost is running an SIP softphone (like linphone, kphone)
|
||||||
The quick fix is to delete nisplus service from hosts entry in
|
|
||||||
/etc/nsswitch.conf. In my tests, memory use remained stable after I
|
- The SIP address used by the softphone is sip:johndoe@foo.bar.org
|
||||||
made the mentioned change.
|
|
||||||
|
- The softphone is configured to register itself at siproxd
|
||||||
|
running on the firewall host (10.0.0.1) as sip:johndoe@foo.bar.org
|
||||||
|
|
||||||
|
- foo.bar.org is the domain name corresponding to the public IP address
|
||||||
|
of the firewall (eg use some dynamic DNS service [1])
|
||||||
|
|
||||||
|
Firewall rules for incomming traffic (ipchains example):
|
||||||
|
$ ipchains -A input --proto udp --dport 5060 --log -j ACCEPT
|
||||||
|
$ ipchains -A input --proto udp --dport 7070:7080 -j ACCEPT
|
||||||
|
|
||||||
|
The first line will allow incomming SIP traffic. The second line will
|
||||||
|
allow incomming RTP traffic on the ports 7070 - 7080 (the default port
|
||||||
|
range used by siproxd for incomming RTP traffic).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
REFERENCES
|
||||||
|
==========
|
||||||
|
[1] dynamic DNS service http://www.dyndns.org
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
LIMITATIONS
|
||||||
|
===========
|
||||||
|
- currently, the SIP part only supports UDP
|
||||||
|
- RTP proxy support is still experimantal (so as the rest of siproxd ;-)
|
||||||
|
- very likely it does not follow the SIP spec (RFC3261) in all details
|
||||||
|
- check the TODO file for more things that we-cannot-do-but-would-like-to
|
||||||
|
|
||||||
|
|
||||||
|
IMPORTANT NOTICE
|
||||||
|
================
|
||||||
|
The gethostbyname() function leaks memory in glibc 2.1.1 (-> RedHat 6.0).
|
||||||
|
The quick fix is to delete the nisplus service from hosts entry in
|
||||||
|
/etc/nsswitch.conf.
|
||||||
|
In my tests, memory use remained stable after I made the mentioned change.
|
||||||
|
|
||||||
(source: http://www.squid-cache.org/Doc/FAQ/FAQ-14.html)
|
(source: http://www.squid-cache.org/Doc/FAQ/FAQ-14.html)
|
||||||
|
|
||||||
|
|
||||||
Contacts:
|
CONTACTS
|
||||||
=========
|
========
|
||||||
Please feel free to contact the author to:
|
Please feel free to contact the author to:
|
||||||
- provide feedback
|
- provide feedback, report bugs,
|
||||||
- report bugs,
|
|
||||||
- request for additional features
|
- request for additional features
|
||||||
- report interoperability with softphones
|
- report interoperability with softphones
|
||||||
- ...
|
- ...
|
||||||
|
|
||||||
and visit the website at http://siproxd.sourceforge.net/
|
and visit the website at http://siproxd.sourceforge.net/
|
||||||
|
|
||||||
|
There also is a siproxd mailinglist available on sourceforge.
|
||||||
|
|
||||||
Thomas Ries (tries@gmx.net)
|
Thomas Ries (tries@gmx.net)
|
||||||
GnuPG Public Key:
|
GnuPG Public Key:
|
||||||
pub 1024D/87BCDC94 2000-03-19 Thomas Ries (tries@gmx.net)
|
pub 1024D/87BCDC94 2000-03-19 Thomas Ries (tries@gmx.net)
|
||||||
Key fingerprint = 13D1 19F5 77D0 4CEC 8D3F A24E 09FC C18A 87BC DC94
|
Key fingerprint = 13D1 19F5 77D0 4CEC 8D3F A24E 09FC C18A 87BC DC94
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CREDITS
|
||||||
|
=======
|
||||||
|
|
||||||
|
Thanks to sourceforge.net for providing the distribution platform and
|
||||||
|
infrastructure.
|
||||||
|
|
||||||
|
|||||||
21
TODO
21
TODO
@ -1,20 +1,19 @@
|
|||||||
TODOs, in anarchistic order:
|
TODOs, in random order:
|
||||||
============================
|
=======================
|
||||||
|
|
||||||
|
|
||||||
- re-think the registration mechanism (mapping and decision criteria
|
- re-think the registration mechanism (mapping and decision criteria
|
||||||
for in- and outgoing stuff...
|
for in- and outgoing stuff...
|
||||||
|
|
||||||
- 2.2.x kernels:
|
|
||||||
make use of the portfw.so (ipmasqadm package) to create forwarding
|
|
||||||
tunnels for incomming data streams
|
|
||||||
How to determine when finished? Is it possible to keep it stateless?
|
|
||||||
|
|
||||||
- Is there a possibility to open up an masquerading tunnel by
|
|
||||||
a userspace program on the firewall?
|
|
||||||
|
|
||||||
- logging via syslog if running in daemon mode
|
- logging via syslog if running in daemon mode
|
||||||
|
|
||||||
- get_ip_by_host: reduce DNS timeouts
|
- get_ip_by_host: reduce DNS timeouts
|
||||||
|
|
||||||
|
- Documentation
|
||||||
|
|
||||||
|
- automagically create a proper config file during install
|
||||||
|
|
||||||
|
- client authentication
|
||||||
|
|
||||||
|
- portability to other platforms / operating systems
|
||||||
|
first goal: other Unixes
|
||||||
|
|
||||||
|
|||||||
39
config.h.in
39
config.h.in
@ -21,18 +21,57 @@
|
|||||||
/* Define if your <sys/time.h> declares struct tm. */
|
/* Define if your <sys/time.h> declares struct tm. */
|
||||||
#undef TM_IN_SYS_TIME
|
#undef TM_IN_SYS_TIME
|
||||||
|
|
||||||
|
/* Define if you have the bind function. */
|
||||||
|
#undef HAVE_BIND
|
||||||
|
|
||||||
|
/* Define if you have the fgets function. */
|
||||||
|
#undef HAVE_FGETS
|
||||||
|
|
||||||
|
/* Define if you have the gethostbyname function. */
|
||||||
|
#undef HAVE_GETHOSTBYNAME
|
||||||
|
|
||||||
|
/* Define if you have the getopt_long_only function. */
|
||||||
|
#undef HAVE_GETOPT_LONG_ONLY
|
||||||
|
|
||||||
|
/* Define if you have the read function. */
|
||||||
|
#undef HAVE_READ
|
||||||
|
|
||||||
/* Define if you have the select function. */
|
/* Define if you have the select function. */
|
||||||
#undef HAVE_SELECT
|
#undef HAVE_SELECT
|
||||||
|
|
||||||
|
/* Define if you have the send function. */
|
||||||
|
#undef HAVE_SEND
|
||||||
|
|
||||||
|
/* Define if you have the sendto function. */
|
||||||
|
#undef HAVE_SENDTO
|
||||||
|
|
||||||
/* Define if you have the socket function. */
|
/* Define if you have the socket function. */
|
||||||
#undef HAVE_SOCKET
|
#undef HAVE_SOCKET
|
||||||
|
|
||||||
|
/* Define if you have the sprintf function. */
|
||||||
|
#undef HAVE_SPRINTF
|
||||||
|
|
||||||
|
/* Define if you have the sscanf function. */
|
||||||
|
#undef HAVE_SSCANF
|
||||||
|
|
||||||
|
/* Define if you have the strchr function. */
|
||||||
|
#undef HAVE_STRCHR
|
||||||
|
|
||||||
/* Define if you have the strerror function. */
|
/* Define if you have the strerror function. */
|
||||||
#undef HAVE_STRERROR
|
#undef HAVE_STRERROR
|
||||||
|
|
||||||
|
/* Define if you have the strncpy function. */
|
||||||
|
#undef HAVE_STRNCPY
|
||||||
|
|
||||||
/* Define if you have the strstr function. */
|
/* Define if you have the strstr function. */
|
||||||
#undef HAVE_STRSTR
|
#undef HAVE_STRSTR
|
||||||
|
|
||||||
|
/* Define if you have the vfprintf function. */
|
||||||
|
#undef HAVE_VFPRINTF
|
||||||
|
|
||||||
|
/* Define if you have the <errno.h> header file. */
|
||||||
|
#undef HAVE_ERRNO_H
|
||||||
|
|
||||||
/* Define if you have the <stdarg.h> header file. */
|
/* Define if you have the <stdarg.h> header file. */
|
||||||
#undef HAVE_STDARG_H
|
#undef HAVE_STDARG_H
|
||||||
|
|
||||||
|
|||||||
21
configure.in
21
configure.in
@ -1,3 +1,13 @@
|
|||||||
|
dnl
|
||||||
|
dnl History
|
||||||
|
dnl -------
|
||||||
|
dnl before time a lot happend before start of history
|
||||||
|
dnl 8-Sep-2002 tries included more tests for used functions
|
||||||
|
dnl
|
||||||
|
dnl
|
||||||
|
dnl
|
||||||
|
dnl
|
||||||
|
|
||||||
dnl Process this file with autoconf to produce a configure script.
|
dnl Process this file with autoconf to produce a configure script.
|
||||||
AC_INIT(src/siproxd.c)
|
AC_INIT(src/siproxd.c)
|
||||||
|
|
||||||
@ -5,7 +15,7 @@ dnl ******************************************************************
|
|||||||
dnl
|
dnl
|
||||||
SPD_MAJOR_VERSION=0
|
SPD_MAJOR_VERSION=0
|
||||||
SPD_MINOR_VERSION=1
|
SPD_MINOR_VERSION=1
|
||||||
SPD_MICRO_VERSION=2
|
SPD_MICRO_VERSION=3
|
||||||
SPD_VERSION=$SPD_MAJOR_VERSION.$SPD_MINOR_VERSION.$SPD_MICRO_VERSION
|
SPD_VERSION=$SPD_MAJOR_VERSION.$SPD_MINOR_VERSION.$SPD_MICRO_VERSION
|
||||||
|
|
||||||
dnl *********************************************************************
|
dnl *********************************************************************
|
||||||
@ -26,7 +36,7 @@ AC_CHECK_LIB(pthread, pthread_create)
|
|||||||
|
|
||||||
dnl Checks for header files.
|
dnl Checks for header files.
|
||||||
AC_HEADER_STDC
|
AC_HEADER_STDC
|
||||||
AC_CHECK_HEADERS(sys/time.h unistd.h)
|
AC_CHECK_HEADERS(sys/time.h unistd.h errno.h)
|
||||||
AC_CHECK_HEADERS(stdarg.h varargs.h)
|
AC_CHECK_HEADERS(stdarg.h varargs.h)
|
||||||
|
|
||||||
dnl Checks for typedefs, structures, and compiler characteristics.
|
dnl Checks for typedefs, structures, and compiler characteristics.
|
||||||
@ -38,7 +48,12 @@ AC_STRUCT_TM
|
|||||||
dnl Checks for library functions.
|
dnl Checks for library functions.
|
||||||
AC_FUNC_MEMCMP
|
AC_FUNC_MEMCMP
|
||||||
AC_FUNC_VPRINTF
|
AC_FUNC_VPRINTF
|
||||||
AC_CHECK_FUNCS(select socket strerror strstr)
|
AC_CHECK_FUNCS(strerror)
|
||||||
|
AC_CHECK_FUNCS(gethostbyname)
|
||||||
|
AC_CHECK_FUNCS(socket bind select read send sendto)
|
||||||
|
AC_CHECK_FUNCS(getopt_long_only)
|
||||||
|
AC_CHECK_FUNCS(strncpy strchr strstr sprintf vfprintf fgets sscanf)
|
||||||
|
|
||||||
|
|
||||||
AC_OUTPUT(Makefile \
|
AC_OUTPUT(Makefile \
|
||||||
src/Makefile \
|
src/Makefile \
|
||||||
|
|||||||
@ -4,20 +4,6 @@
|
|||||||
# !! This is a sample file, adapt it to your needs before using it
|
# !! This is a sample file, adapt it to your needs before using it
|
||||||
#
|
#
|
||||||
|
|
||||||
######################################################################
|
|
||||||
# DBCLASS_BABBLE 0x00000001 // babble (like entering/leaving fnc)
|
|
||||||
# DBCLASS_NET 0x00000002 // network
|
|
||||||
# DBCLASS_SIP 0x00000004 // SIP manipulations
|
|
||||||
# DBCLASS_REG 0x00000008 // Client registration
|
|
||||||
# DBCLASS_NOSPEC 0x00000010 // non specified class
|
|
||||||
# DBCLASS_PROXY 0x00000020 // proxy
|
|
||||||
# DBCLASS_DNS 0x00000040 // DNS stuff
|
|
||||||
# DBCLASS_NETTRAF 0x00000080 // network traffic
|
|
||||||
# DBCLASS_CONFIG 0x00000100 // configuration
|
|
||||||
# DBCLASS_RTP 0x00000200 // RTP proxy
|
|
||||||
#
|
|
||||||
debug_level = 0x000002fe
|
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
# The IP addresses of the INBOUND and OUTBOUND interface can
|
# The IP addresses of the INBOUND and OUTBOUND interface can
|
||||||
# be specified as hostnames or in dotted decimal form:
|
# be specified as hostnames or in dotted decimal form:
|
||||||
@ -59,8 +45,22 @@ rtp_port_high = 7080
|
|||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
# Timeout for RTP streams
|
# Timeout for RTP streams
|
||||||
# after this number of seconds, at RTP stream is considered dead
|
# after this number of seconds, an RTP stream is considered dead
|
||||||
# and proxying it will be stopped.
|
# and proxying it will be stopped.
|
||||||
#
|
#
|
||||||
rtp_timeout = 60
|
rtp_timeout = 60
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
# DBCLASS_BABBLE 0x00000001 // babble (like entering/leaving fnc)
|
||||||
|
# DBCLASS_NET 0x00000002 // network
|
||||||
|
# DBCLASS_SIP 0x00000004 // SIP manipulations
|
||||||
|
# DBCLASS_REG 0x00000008 // Client registration
|
||||||
|
# DBCLASS_NOSPEC 0x00000010 // non specified class
|
||||||
|
# DBCLASS_PROXY 0x00000020 // proxy
|
||||||
|
# DBCLASS_DNS 0x00000040 // DNS stuff
|
||||||
|
# DBCLASS_NETTRAF 0x00000080 // network traffic
|
||||||
|
# DBCLASS_CONFIG 0x00000100 // configuration
|
||||||
|
# DBCLASS_RTP 0x00000200 // RTP proxy
|
||||||
|
#
|
||||||
|
debug_level = 0x00000218
|
||||||
|
|
||||||
|
|||||||
121
src/proxy.c
121
src/proxy.c
@ -41,10 +41,6 @@ static char const ident[]="$Id: " __FILE__ ": " PACKAGE "-" VERSION "-"\
|
|||||||
/* configuration storage */
|
/* configuration storage */
|
||||||
extern struct siproxd_config configuration;
|
extern struct siproxd_config configuration;
|
||||||
|
|
||||||
/*
|
|
||||||
* knows hot to rewrite the SIP URLs in a request/response
|
|
||||||
*/
|
|
||||||
|
|
||||||
extern int errno;
|
extern int errno;
|
||||||
extern struct urlmap_s urlmap[]; /* URL mapping table */
|
extern struct urlmap_s urlmap[]; /* URL mapping table */
|
||||||
extern struct lcl_if_s local_addresses;
|
extern struct lcl_if_s local_addresses;
|
||||||
@ -60,7 +56,7 @@ int proxy_request (sip_t *request) {
|
|||||||
int sts;
|
int sts;
|
||||||
int type;
|
int type;
|
||||||
struct in_addr addr;
|
struct in_addr addr;
|
||||||
// contact_t *contact; /* contact header issue */
|
contact_t *contact;
|
||||||
url_t *url;
|
url_t *url;
|
||||||
int port;
|
int port;
|
||||||
char *buffer;
|
char *buffer;
|
||||||
@ -77,25 +73,6 @@ int proxy_request (sip_t *request) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0 /* Contact Header Issue */
|
|
||||||
/* figure out if this is an request comming from the outside
|
|
||||||
* world to one of our registered clients ('to' == 'masq' URL)
|
|
||||||
* or if this is a request sent by on e of our registered clients
|
|
||||||
* ('from' == 'true' URL)
|
|
||||||
*/
|
|
||||||
msg_getcontact(request,0,&contact);
|
|
||||||
|
|
||||||
/* seen with linphone-0.9.1pre1 w/ user-agent: oSIP/Linphone-0.8.0
|
|
||||||
no contact header in reequest */
|
|
||||||
if (contact==NULL) {
|
|
||||||
ERROR("Contact header is missing!");
|
|
||||||
/* THIS IS SEVERE - I HAVE NO WAY TO FIGURE OUT WHO THE
|
|
||||||
REAL CLIENT IS BEHIND THIS PACKET...
|
|
||||||
what can I do here? */
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
type = 0;
|
type = 0;
|
||||||
for (i=0; i<URLMAP_SIZE; i++) {
|
for (i=0; i<URLMAP_SIZE; i++) {
|
||||||
if (urlmap[i].active == 0) continue;
|
if (urlmap[i].active == 0) continue;
|
||||||
@ -109,16 +86,6 @@ int proxy_request (sip_t *request) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0 /* Contact Header Issue */
|
|
||||||
/* outgoing request ('contact' == 'true') */
|
|
||||||
if (compare_url(contact->url, urlmap[i].true_url)==0) {
|
|
||||||
type=REQTYP_OUTGOING;
|
|
||||||
DEBUGC(DBCLASS_PROXY,"outgoing request from %s@%s from inbound",
|
|
||||||
request->from->url->username,
|
|
||||||
request->from->url->host);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
/* outgoing request ('from' == 'masq') */
|
/* outgoing request ('from' == 'masq') */
|
||||||
if (compare_url(request->from->url, urlmap[i].masq_url)==0) {
|
if (compare_url(request->from->url, urlmap[i].masq_url)==0) {
|
||||||
type=REQTYP_OUTGOING;
|
type=REQTYP_OUTGOING;
|
||||||
@ -146,11 +113,23 @@ int proxy_request (sip_t *request) {
|
|||||||
url=msg_geturi(request);
|
url=msg_geturi(request);
|
||||||
free(url->host);url->host=NULL;
|
free(url->host);url->host=NULL;
|
||||||
{
|
{
|
||||||
char *copy;
|
char *host;
|
||||||
copy = (char *)malloc(strlen(urlmap[i].true_url->host)+1);
|
char *port;
|
||||||
memcpy(copy, urlmap[i].true_url->host, strlen(urlmap[i].true_url->host));
|
/* set the true host */
|
||||||
copy[strlen(urlmap[i].true_url->host)]='\0';
|
if(urlmap[i].true_url->host) {
|
||||||
url_sethost(url, copy);
|
host = (char *)malloc(strlen(urlmap[i].true_url->host)+1);
|
||||||
|
memcpy(host, urlmap[i].true_url->host, strlen(urlmap[i].true_url->host));
|
||||||
|
host[strlen(urlmap[i].true_url->host)]='\0';
|
||||||
|
url_sethost(url, host);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set the true port */
|
||||||
|
if(urlmap[i].true_url->port) {
|
||||||
|
port = (char *)malloc(strlen(urlmap[i].true_url->port)+1);
|
||||||
|
memcpy(port, urlmap[i].true_url->port, strlen(urlmap[i].true_url->port));
|
||||||
|
port[strlen(urlmap[i].true_url->port)]='\0';
|
||||||
|
url_setport(url, port);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add my Via header line (inbound interface)*/
|
/* add my Via header line (inbound interface)*/
|
||||||
@ -159,7 +138,7 @@ int proxy_request (sip_t *request) {
|
|||||||
/* if this is CANCEL/BYE request, stop RTP proxying */
|
/* if this is CANCEL/BYE request, stop RTP proxying */
|
||||||
if (MSG_IS_BYE(request) || MSG_IS_CANCEL(request)) {
|
if (MSG_IS_BYE(request) || MSG_IS_CANCEL(request)) {
|
||||||
/* stop the RTP proxying stream */
|
/* stop the RTP proxying stream */
|
||||||
sts = rtp_stop_fwd(msg_getcall_id(request));
|
rtp_stop_fwd(msg_getcall_id(request));
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -173,13 +152,36 @@ int proxy_request (sip_t *request) {
|
|||||||
sts = proxy_rewrite_invitation_body(request);
|
sts = proxy_rewrite_invitation_body(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* rewrite Contact header to represent the masqued address */
|
||||||
|
msg_getcontact(request,0,&contact);
|
||||||
|
if (contact != NULL) {
|
||||||
|
for (i=0;i<URLMAP_SIZE;i++){
|
||||||
|
if (urlmap[i].active == 0) continue;
|
||||||
|
if (compare_url(contact->url, urlmap[i].true_url)==0) break;
|
||||||
|
}
|
||||||
|
/* found a mapping entry */
|
||||||
|
if (i<URLMAP_SIZE) {
|
||||||
|
DEBUGC(DBCLASS_PROXY, "rewrote Contact header %s@%s -> %s@%s",
|
||||||
|
contact->url->username, contact->url->host,
|
||||||
|
urlmap[i].masq_url->username, urlmap[i].masq_url->host);
|
||||||
|
/* remove old entry */
|
||||||
|
list_remove(request->contacts,0);
|
||||||
|
contact_free(contact);
|
||||||
|
free(contact);
|
||||||
|
/* clone the masquerading url */
|
||||||
|
contact_init(&contact);
|
||||||
|
url_clone(urlmap[i].masq_url, &contact->url);
|
||||||
|
list_add(request->contacts,contact,-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* add my Via header line (outbound interface)*/
|
/* add my Via header line (outbound interface)*/
|
||||||
sts = proxy_add_myvia(request, 0);
|
sts = proxy_add_myvia(request, 0);
|
||||||
|
|
||||||
/* if this is CANCEL/BYE request, stop RTP proxying */
|
/* if this is CANCEL/BYE request, stop RTP proxying */
|
||||||
if (MSG_IS_BYE(request) || MSG_IS_CANCEL(request)) {
|
if (MSG_IS_BYE(request) || MSG_IS_CANCEL(request)) {
|
||||||
/* stop the RTP proxying stream */
|
/* stop the RTP proxying stream */
|
||||||
sts = rtp_stop_fwd(msg_getcall_id(request));
|
rtp_stop_fwd(msg_getcall_id(request));
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -252,6 +254,7 @@ int proxy_response (sip_t *response) {
|
|||||||
int type;
|
int type;
|
||||||
struct in_addr addr;
|
struct in_addr addr;
|
||||||
via_t *via;
|
via_t *via;
|
||||||
|
contact_t *contact;
|
||||||
int port;
|
int port;
|
||||||
char *buffer;
|
char *buffer;
|
||||||
|
|
||||||
@ -318,16 +321,6 @@ int proxy_response (sip_t *response) {
|
|||||||
* from an external host to the internal masqueraded host
|
* from an external host to the internal masqueraded host
|
||||||
*/
|
*/
|
||||||
case RESTYP_INCOMMING:
|
case RESTYP_INCOMMING:
|
||||||
#if 0 /* do we really have to?? in the incomming response
|
|
||||||
we have the correct address. But we must rewrite an
|
|
||||||
outgoing response to an incomming INVITE request ! */
|
|
||||||
/* If an 200 answer to an INVITE request, rewrite body */
|
|
||||||
if ((MSG_IS_RESPONSEFOR(response,"INVITE") &&
|
|
||||||
(MSG_TEST_CODE(response, 200)) ) {
|
|
||||||
sts = proxy_rewrite_invitation_body(response);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -340,6 +333,30 @@ int proxy_response (sip_t *response) {
|
|||||||
(MSG_TEST_CODE(response, 200))) {
|
(MSG_TEST_CODE(response, 200))) {
|
||||||
sts = proxy_rewrite_invitation_body(response);
|
sts = proxy_rewrite_invitation_body(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* rewrite Contact header to represent the masqued address */
|
||||||
|
msg_getcontact(response,0,&contact);
|
||||||
|
if (contact != NULL) {
|
||||||
|
for (i=0;i<URLMAP_SIZE;i++){
|
||||||
|
if (urlmap[i].active == 0) continue;
|
||||||
|
if (compare_url(contact->url, urlmap[i].true_url)==0) break;
|
||||||
|
}
|
||||||
|
/* found a mapping entry */
|
||||||
|
if (i<URLMAP_SIZE) {
|
||||||
|
DEBUGC(DBCLASS_PROXY, "rewrote Contact header %s@%s -> %s@%s",
|
||||||
|
contact->url->username, contact->url->host,
|
||||||
|
urlmap[i].masq_url->username, urlmap[i].masq_url->host);
|
||||||
|
/* remove old entry */
|
||||||
|
list_remove(response->contacts,0);
|
||||||
|
contact_free(contact);
|
||||||
|
free(contact);
|
||||||
|
/* clone the masquerading url */
|
||||||
|
contact_init(&contact);
|
||||||
|
url_clone(urlmap[i].masq_url, &contact->url);
|
||||||
|
list_add(response->contacts,contact,-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -529,7 +546,7 @@ int proxy_rewrite_invitation_body(sip_t *mymsg){
|
|||||||
sts = get_ip_by_host(configuration.outboundhost, &outb_addr);
|
sts = get_ip_by_host(configuration.outboundhost, &outb_addr);
|
||||||
inb_clnt_port = atoi(sdp_m_port_get(sdp,0));
|
inb_clnt_port = atoi(sdp_m_port_get(sdp,0));
|
||||||
/* start an RTP proxying stream */
|
/* start an RTP proxying stream */
|
||||||
sts = rtp_start_fwd(msg_getcall_id(mymsg),
|
rtp_start_fwd(msg_getcall_id(mymsg),
|
||||||
outb_addr, &outb_rtp_port,
|
outb_addr, &outb_rtp_port,
|
||||||
lcl_clnt_addr, inb_clnt_port);
|
lcl_clnt_addr, inb_clnt_port);
|
||||||
|
|
||||||
|
|||||||
@ -53,11 +53,11 @@ int main (int argc, char *argv[])
|
|||||||
extern char *optarg;
|
extern char *optarg;
|
||||||
int ch1;
|
int ch1;
|
||||||
|
|
||||||
char configfile[64]="siproxd";
|
char configfile[64]="siproxd"; /* basename of configfile */
|
||||||
int config_search=1;
|
int config_search=1; /* search the config file */
|
||||||
|
|
||||||
/* prepare default configuration */
|
/* prepare default configuration */
|
||||||
configuration.debuglevel=-1;
|
configuration.debuglevel=0;
|
||||||
configuration.daemonize=0;
|
configuration.daemonize=0;
|
||||||
configuration.sip_listen_port=SIP_PORT;
|
configuration.sip_listen_port=SIP_PORT;
|
||||||
configuration.inboundhost=NULL;
|
configuration.inboundhost=NULL;
|
||||||
@ -121,7 +121,12 @@ int main (int argc, char *argv[])
|
|||||||
register_init();
|
register_init();
|
||||||
|
|
||||||
/* listen for incomming messages */
|
/* listen for incomming messages */
|
||||||
sipsock_listen();
|
sts=sipsock_listen();
|
||||||
|
if (sts != 0) {
|
||||||
|
/* failure to allocate SIP socket... */
|
||||||
|
ERROR("unable to bind to SIP listening socket - aborting");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* initialize the RTP proxy thread */
|
/* initialize the RTP proxy thread */
|
||||||
rtpproxy_init();
|
rtpproxy_init();
|
||||||
|
|||||||
@ -21,6 +21,7 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
@ -43,8 +44,6 @@ static char const ident[]="$Id: " __FILE__ ": " PACKAGE "-" VERSION "-"\
|
|||||||
/* configuration storage */
|
/* configuration storage */
|
||||||
extern struct siproxd_config configuration;
|
extern struct siproxd_config configuration;
|
||||||
|
|
||||||
extern int errno;
|
|
||||||
|
|
||||||
static int listen_socket=0;
|
static int listen_socket=0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -57,6 +56,7 @@ int sipsock_listen (void) {
|
|||||||
|
|
||||||
memset(&ipaddr, 0, sizeof(struct in_addr));
|
memset(&ipaddr, 0, sizeof(struct in_addr));
|
||||||
listen_socket=sockbind(ipaddr, configuration.sip_listen_port);
|
listen_socket=sockbind(ipaddr, configuration.sip_listen_port);
|
||||||
|
if (listen_socket==0) return 1; /* failure*/
|
||||||
|
|
||||||
DEBUGC(DBCLASS_NET,"bound listen socket %i",listen_socket);
|
DEBUGC(DBCLASS_NET,"bound listen socket %i",listen_socket);
|
||||||
return 0;
|
return 0;
|
||||||
@ -121,9 +121,12 @@ int sipsock_send_udp(int *sock, struct in_addr addr, int port,
|
|||||||
sts = sendto (*sock, buffer, size, 0, &dst_addr, sizeof(dst_addr));
|
sts = sendto (*sock, buffer, size, 0, &dst_addr, sizeof(dst_addr));
|
||||||
|
|
||||||
if (sts == -1) {
|
if (sts == -1) {
|
||||||
|
if (errno != ECONNREFUSED) {
|
||||||
ERROR("sendto() call failed:%s",strerror(errno));
|
ERROR("sendto() call failed:%s",strerror(errno));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
DEBUGC(DBCLASS_BABBLE,"sendto() call failed:%s",strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
12
src/utils.c
12
src/utils.c
@ -187,7 +187,7 @@ int get_ip_by_host(char *hostname, struct in_addr *addr) {
|
|||||||
if (dns_cache[i].hostname[0]=='\0') continue; /* empty */
|
if (dns_cache[i].hostname[0]=='\0') continue; /* empty */
|
||||||
if (strcmp(hostname, dns_cache[i].hostname) == 0) { /* match */
|
if (strcmp(hostname, dns_cache[i].hostname) == 0) { /* match */
|
||||||
memcpy(addr, &dns_cache[i].addr, sizeof(struct in_addr));
|
memcpy(addr, &dns_cache[i].addr, sizeof(struct in_addr));
|
||||||
DEBUGC(DBCLASS_DNS, "from cache: %s -> %s",
|
DEBUGC(DBCLASS_DNS, "DNS lookup - from cache: %s -> %s",
|
||||||
hostname, inet_ntoa(*addr));
|
hostname, inet_ntoa(*addr));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -202,7 +202,8 @@ int get_ip_by_host(char *hostname, struct in_addr *addr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
memcpy(addr, hostentry->h_addr, sizeof(struct in_addr));
|
memcpy(addr, hostentry->h_addr, sizeof(struct in_addr));
|
||||||
DEBUGC(DBCLASS_DNS, "resolved: %s -> %s", hostname, inet_ntoa(*addr));
|
DEBUGC(DBCLASS_DNS, "DNS lookup - resolved: %s -> %s",
|
||||||
|
hostname, inet_ntoa(*addr));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* remember the result in the cache
|
* remember the result in the cache
|
||||||
@ -221,7 +222,7 @@ int get_ip_by_host(char *hostname, struct in_addr *addr) {
|
|||||||
if (i >= DNS_CACHE_SIZE) i=j;
|
if (i >= DNS_CACHE_SIZE) i=j;
|
||||||
|
|
||||||
/* store in cache */
|
/* store in cache */
|
||||||
DEBUGC(DBCLASS_DNS, "store into DNS cache, entry %i)", i);
|
DEBUGC(DBCLASS_DNS, "DNS lookup - store into cache, entry %i)", i);
|
||||||
memset(&dns_cache[i], 0, sizeof(dns_cache[0]));
|
memset(&dns_cache[i], 0, sizeof(dns_cache[0]));
|
||||||
strncpy(dns_cache[i].hostname, hostname, HOSTNAME_SIZE);
|
strncpy(dns_cache[i].hostname, hostname, HOSTNAME_SIZE);
|
||||||
time(&dns_cache[i].timestamp);
|
time(&dns_cache[i].timestamp);
|
||||||
@ -232,11 +233,14 @@ int get_ip_by_host(char *hostname, struct in_addr *addr) {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* compares two URLs
|
* compares two URLs
|
||||||
* returns 0 if equal, >0 if non equal, <0 if error
|
* returns 0 if equal, <0 if non equal, >0 if error
|
||||||
* (by now, only hostname and username are compared)
|
* (by now, only hostname and username are compared)
|
||||||
*/
|
*/
|
||||||
int compare_url(url_t *url1, url_t *url2) {
|
int compare_url(url_t *url1, url_t *url2) {
|
||||||
int sts;
|
int sts;
|
||||||
|
|
||||||
|
if ((url1 == NULL) || (url2 == NULL)) return 1;
|
||||||
|
|
||||||
/* comparison of hosts should be based on IP addresses, no? */
|
/* comparison of hosts should be based on IP addresses, no? */
|
||||||
DEBUGC(DBCLASS_BABBLE, "comparng urls: %s@%s -> %s@%s",
|
DEBUGC(DBCLASS_BABBLE, "comparng urls: %s@%s -> %s@%s",
|
||||||
url1->username, url1->host, url2->username, url2->host);
|
url1->username, url1->host, url2->username, url2->host);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user