- should now be able to deal with an outbound interface

that is "temporary" DOWN (dial up internet access)
  if outbounf IF is down, send back a response to
  inbound UAs "408 Request Timeout".
- always log to syslog, also when running in foreground
- changed some WARNINGS into DEBUG statements
- re-arranged some code
- rtpproxy: prepared for proper thread termination on exit
- introduced short term caching for get_ip_by_ifname
- fixed in check for socket() return status
This commit is contained in:
Thomas Ries
2003-04-01 20:35:59 +00:00
parent d7029ce354
commit c5fc06836a
16 changed files with 503 additions and 591 deletions
+19 -3
View File
@@ -1,9 +1,25 @@
0.3.2
=====
1-Apr-2003: - should now be able to deal with an outbound interface
that is "temporary" DOWN (dial up internet access)
if outbounf IF is down, send back a response to
inbound UAs "408 Request Timeout".
- always log to syslog, also when running in foreground
- changed some WARNINGS into DEBUG statements
- re-arranged some code
- rtpproxy: prepared for proper thread termination on exit
- introduced short term caching for get_ip_by_ifname
- fixed in check for socket() return status
30-May-2003: - always log ERROR, WARNING and INFO to syslog (also
of not running as daemon)
- minor corrections on ERROR printouts
0.3.1
=====
- 29-May-2003: - released 0.3.1
- fix in configure.in for statically linking to libosip
- fix in rewriting SIP messages, figure out proper
destination if *not* rewriting the SIP URI
destination if *not* rewriting the SIP URI
- another NULL pointer related crash (no UA header present)
0.3.0
@@ -11,10 +27,10 @@
- 29-May-2003: - released 0.3.0
- supports libosip2 (automatically detect osip1/osip2)
- redone authentication - now should work with libosip2
libosip0.8.8 has a bug (fails in parse_msg)
libosip0.8.8 has a bug (fails in parse_msg)
- 28-May-2003: - changes in rewriting SIP messages - not everything
is blindly rewritten now (e.g. SUBSCRIBE is NOT)
- fixed resource leak (sockets) in get_ip_by_ifname
- fixed resource leak (sockets) in get_ip_by_ifname
- 26-Mar-2003: - Bugfix: some potential NULL pointers passed to atoi()
of optional fields in SIP message could lead to crash
- 23-Mar-2003: - send 403 FORBIDDEN response to requests addressed
+10 -8
View File
@@ -1,20 +1,19 @@
TODOs, in random order:
=======================
- kphone 3.1: authentication w/ siproxd (libosip 0.8.8, 0.9.0, libosip2)
does not work (parse error in libosip)
- TERM handler
- libosip >0.8.8, libosip2: failure in msg_setproxy_authenticate
- /var/run PID file
- check via loop and private IP addresses
can comment be used to store a unique ID in there?
- multiple inbound interfaces - do I need to be aware of inbound at all?
- Documentation (yeah, yeah...)
- support for proxy chaining - UPNP support?
- feature: don't bind to 0.0.0.0 address, but only to inbound/outbound IF's
(defined by IFNAME)
- multiple inbound interfaces
- general security issues
- security tests for received SIP messages (function securitycheck)
@@ -27,3 +26,6 @@ TODOs, in random order:
- via loop detection: send 482 error code
- support Record-Route header
- feature: don't bind to 0.0.0.0 address, but only to inbound/outbound IF's
(defined by IFNAME)
Vendored
-356
View File
@@ -1,356 +0,0 @@
dnl aclocal.m4 generated automatically by aclocal 1.4a
dnl Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.
dnl This program is distributed in the hope that it will be useful,
dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without
dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A
dnl PARTICULAR PURPOSE.
dnl --------------------------------------------------------------------
dnl @synopsis ACX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
dnl
dnl This macro figures out how to build C programs using POSIX
dnl threads. It sets the PTHREAD_LIBS output variable to the threads
dnl library and linker flags, and the PTHREAD_CFLAGS output variable
dnl to any special C compiler flags that are needed. (The user can also
dnl force certain compiler flags/libs to be tested by setting these
dnl environment variables.)
dnl
dnl Also sets PTHREAD_CC to any special C compiler that is needed for
dnl multi-threaded programs (defaults to the value of CC otherwise).
dnl (This is necessary on AIX to use the special cc_r compiler alias.)
dnl
dnl If you are only building threads programs, you may wish to
dnl use these variables in your default LIBS, CFLAGS, and CC:
dnl
dnl LIBS="$PTHREAD_LIBS $LIBS"
dnl CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
dnl CC="$PTHREAD_CC"
dnl
dnl In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute
dnl constant has a nonstandard name, defines PTHREAD_CREATE_JOINABLE
dnl to that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
dnl
dnl ACTION-IF-FOUND is a list of shell commands to run if a threads
dnl library is found, and ACTION-IF-NOT-FOUND is a list of commands
dnl to run it if it is not found. If ACTION-IF-FOUND is not specified,
dnl the default action will define HAVE_PTHREAD.
dnl
dnl Please let the authors know if this macro fails on any platform,
dnl or if you have any other suggestions or comments. This macro was
dnl based on work by SGJ on autoconf scripts for FFTW (www.fftw.org)
dnl (with help from M. Frigo), as well as ac_pthread and hb_pthread
dnl macros posted by AFC to the autoconf macro repository. We are also
dnl grateful for the helpful feedback of numerous users.
dnl
dnl @version $Id$
dnl @author Steven G. Johnson <stevenj@alum.mit.edu> and Alejandro Forero Cuervo <bachue@bachue.com>
AC_DEFUN([ACX_PTHREAD], [
AC_REQUIRE([AC_CANONICAL_HOST])
acx_pthread_ok=no
# We used to check for pthread.h first, but this fails if pthread.h
# requires special compiler flags (e.g. on True64 or Sequent).
# It gets checked for in the link test anyway.
# First of all, check if the user has set any of the PTHREAD_LIBS,
# etcetera environment variables, and if threads linking works using
# them:
if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
save_LIBS="$LIBS"
LIBS="$PTHREAD_LIBS $LIBS"
AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes)
AC_MSG_RESULT($acx_pthread_ok)
if test x"$acx_pthread_ok" = xno; then
PTHREAD_LIBS=""
PTHREAD_CFLAGS=""
fi
LIBS="$save_LIBS"
CFLAGS="$save_CFLAGS"
fi
# We must check for the threads library under a number of different
# names; the ordering is very important because some systems
# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
# libraries is broken (non-POSIX).
# Create a list of thread flags to try. Items starting with a "-" are
# C compiler flags, and other items are library names, except for "none"
# which indicates that we try without any flags at all.
acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt"
# The ordering *is* (sometimes) important. Some notes on the
# individual items follow:
# pthreads: AIX (must check this before -lpthread)
# none: in case threads are in libc; should be tried before -Kthread and
# other compiler flags to prevent continual compiler warnings
# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
# -pthreads: Solaris/gcc
# -mthreads: Mingw32/gcc, Lynx/gcc
# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
# doesn't hurt to check since this sometimes defines pthreads too;
# also defines -D_REENTRANT)
# pthread: Linux, etcetera
# --thread-safe: KAI C++
case "${host_cpu}-${host_os}" in
*solaris*)
# On Solaris (at least, for some versions), libc contains stubbed
# (non-functional) versions of the pthreads routines, so link-based
# tests will erroneously succeed. (We need to link with -pthread or
# -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
# a function called by this macro, so we could check for that, but
# who knows whether they'll stub that too in a future libc.) So,
# we'll just look for -pthreads and -lpthread first:
acx_pthread_flags="-pthread -pthreads pthread -mt $acx_pthread_flags"
;;
esac
if test x"$acx_pthread_ok" = xno; then
for flag in $acx_pthread_flags; do
case $flag in
none)
AC_MSG_CHECKING([whether pthreads work without any flags])
;;
-*)
AC_MSG_CHECKING([whether pthreads work with $flag])
PTHREAD_CFLAGS="$flag"
;;
*)
AC_MSG_CHECKING([for the pthreads library -l$flag])
PTHREAD_LIBS="-l$flag"
;;
esac
save_LIBS="$LIBS"
save_CFLAGS="$CFLAGS"
LIBS="$PTHREAD_LIBS $LIBS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
# Check for various functions. We must include pthread.h,
# since some functions may be macros. (On the Sequent, we
# need a special flag -Kthread to make this header compile.)
# We check for pthread_join because it is in -lpthread on IRIX
# while pthread_create is in libc. We check for pthread_attr_init
# due to DEC craziness with -lpthreads. We check for
# pthread_cleanup_push because it is one of the few pthread
# functions on Solaris that doesn't have a non-functional libc stub.
# We try pthread_create on general principles.
AC_TRY_LINK([#include <pthread.h>],
[pthread_t th; pthread_join(th, 0);
pthread_attr_init(0); pthread_cleanup_push(0, 0);
pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],
[acx_pthread_ok=yes])
LIBS="$save_LIBS"
CFLAGS="$save_CFLAGS"
AC_MSG_RESULT($acx_pthread_ok)
if test "x$acx_pthread_ok" = xyes; then
break;
fi
PTHREAD_LIBS=""
PTHREAD_CFLAGS=""
done
fi
# Various other checks:
if test "x$acx_pthread_ok" = xyes; then
save_LIBS="$LIBS"
LIBS="$PTHREAD_LIBS $LIBS"
save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
# Detect AIX lossage: threads are created detached by default
# and the JOINABLE attribute has a nonstandard name (UNDETACHED).
AC_MSG_CHECKING([for joinable pthread attribute])
AC_TRY_LINK([#include <pthread.h>],
[int attr=PTHREAD_CREATE_JOINABLE;],
ok=PTHREAD_CREATE_JOINABLE, ok=unknown)
if test x"$ok" = xunknown; then
AC_TRY_LINK([#include <pthread.h>],
[int attr=PTHREAD_CREATE_UNDETACHED;],
ok=PTHREAD_CREATE_UNDETACHED, ok=unknown)
fi
if test x"$ok" != xPTHREAD_CREATE_JOINABLE; then
AC_DEFINE(PTHREAD_CREATE_JOINABLE, $ok,
[Define to the necessary symbol if this constant
uses a non-standard name on your system.])
fi
AC_MSG_RESULT(${ok})
if test x"$ok" = xunknown; then
AC_MSG_WARN([we do not know how to create joinable pthreads])
fi
AC_MSG_CHECKING([if more special flags are required for pthreads])
flag=no
case "${host_cpu}-${host_os}" in
*-aix* | *-freebsd*) flag="-D_THREAD_SAFE";;
*solaris* | alpha*-osf*) flag="-D_REENTRANT";;
esac
AC_MSG_RESULT(${flag})
if test "x$flag" != xno; then
PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
fi
LIBS="$save_LIBS"
CFLAGS="$save_CFLAGS"
# More AIX lossage: must compile with cc_r
AC_CHECK_PROG(PTHREAD_CC, cc_r, cc_r, ${CC})
else
PTHREAD_CC="$CC"
fi
AC_SUBST(PTHREAD_LIBS)
AC_SUBST(PTHREAD_CFLAGS)
AC_SUBST(PTHREAD_CC)
# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
if test x"$acx_pthread_ok" = xyes; then
ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1])
:
else
acx_pthread_ok=no
$2
fi
])dnl ACX_PTHREAD
# Like AC_CONFIG_HEADER, but automatically create stamp file.
AC_DEFUN(AM_CONFIG_HEADER,
[AC_PREREQ([2.12])
AC_CONFIG_HEADER([$1])
dnl When config.status generates a header, we must update the stamp-h file.
dnl This file resides in the same directory as the config header
dnl that is generated. We must strip everything past the first ":",
dnl and everything past the last "/".
AC_OUTPUT_COMMANDS(changequote(<<,>>)dnl
ifelse(patsubst(<<$1>>, <<[^ ]>>, <<>>), <<>>,
<<test -z "<<$>>CONFIG_HEADERS" || echo timestamp > patsubst(<<$1>>, <<^\([^:]*/\)?.*>>, <<\1>>)stamp-h<<>>dnl>>,
<<am_indx=1
for am_file in <<$1>>; do
case " <<$>>CONFIG_HEADERS " in
*" <<$>>am_file "*<<)>>
echo timestamp > `echo <<$>>am_file | sed -e 's%:.*%%' -e 's%[^/]*$%%'`stamp-h$am_indx
;;
esac
am_indx=`expr "<<$>>am_indx" + 1`
done<<>>dnl>>)
changequote([,]))])
# Do all the work for Automake. This macro actually does too much --
# some checks are only needed if your package does certain things.
# But this isn't really a big deal.
# serial 1
dnl Usage:
dnl AM_INIT_AUTOMAKE(package,version, [no-define])
AC_DEFUN(AM_INIT_AUTOMAKE,
[AC_REQUIRE([AC_PROG_INSTALL])
dnl We require 2.13 because we rely on SHELL being computed by configure.
AC_PREREQ([2.13])
PACKAGE=[$1]
AC_SUBST(PACKAGE)
VERSION=[$2]
AC_SUBST(VERSION)
dnl test to see if srcdir already configured
if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then
AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
fi
ifelse([$3],,
AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package]))
AC_REQUIRE([AM_SANITY_CHECK])
AC_REQUIRE([AC_ARG_PROGRAM])
dnl FIXME This is truly gross.
missing_dir=`cd $ac_aux_dir && pwd`
AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir)
AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir)
AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir)
AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir)
AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir)
AC_REQUIRE([AC_PROG_MAKE_SET])])
#
# Check to make sure that the build environment is sane.
#
AC_DEFUN(AM_SANITY_CHECK,
[AC_MSG_CHECKING([whether build environment is sane])
# Just in case
sleep 1
echo timestamp > conftestfile
# Do `set' in a subshell so we don't clobber the current shell's
# arguments. Must try -L first in case configure is actually a
# symlink; some systems play weird games with the mod time of symlinks
# (eg FreeBSD returns the mod time of the symlink's containing
# directory).
if (
set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null`
if test "[$]*" = "X"; then
# -L didn't work.
set X `ls -t $srcdir/configure conftestfile`
fi
if test "[$]*" != "X $srcdir/configure conftestfile" \
&& test "[$]*" != "X conftestfile $srcdir/configure"; then
# If neither matched, then we have a broken ls. This can happen
# if, for instance, CONFIG_SHELL is bash and it inherits a
# broken ls alias from the environment. This has actually
# happened. Such a system could not be considered "sane".
AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
alias in your environment])
fi
test "[$]2" = conftestfile
)
then
# Ok.
:
else
AC_MSG_ERROR([newly created file is older than distributed files!
Check your system clock])
fi
rm -f conftest*
AC_MSG_RESULT(yes)])
dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY)
dnl The program must properly implement --version.
AC_DEFUN(AM_MISSING_PROG,
[AC_MSG_CHECKING(for working $2)
# Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh.
if ($2 --version) < /dev/null > /dev/null 2>&1; then
$1=$2
AC_MSG_RESULT(found)
else
$1="$3/missing $2"
AC_MSG_RESULT(missing)
fi
AC_SUBST($1)])
+1 -1
View File
@@ -24,7 +24,7 @@ dnl Release Version
dnl
SPD_MAJOR_VERSION=0
SPD_MINOR_VERSION=3
SPD_MICRO_VERSION=1
SPD_MICRO_VERSION=2
SPD_VERSION=$SPD_MAJOR_VERSION.$SPD_MINOR_VERSION.$SPD_MICRO_VERSION
+1 -1
View File
@@ -1,5 +1,5 @@
%define name siproxd
%define ver 0.3.1
%define ver 0.3.2
%define release 1
%define serial 1
%define prefix %{_prefix}
+8 -2
View File
@@ -118,7 +118,7 @@ int accesslist_check (struct sockaddr_in from) {
* STS_FAILURE for no match
*/
int process_aclist (char *aclist, struct sockaddr_in from) {
int i;
int i, sts;
int lastentry;
char *p1, *p2;
char address[32]; /* dotted decimal IP - max 15 chars*/
@@ -161,7 +161,13 @@ int process_aclist (char *aclist, struct sockaddr_in from) {
/*
* check for a match
*/
get_ip_by_host(address, &inaddr);
sts=get_ip_by_host(address, &inaddr);
if (sts == STS_FAILURE) {
DEBUGC(DBCLASS_ACCESS, "process_aclist: cannot resolve address [%s]",
address);
return STS_FAILURE;
}
bitmask=~(0xffffffff>>atoi(mask));
DEBUGC(DBCLASS_ACCESS,"[%i] (%p) <-> (%p)", i,
+12 -6
View File
@@ -104,11 +104,13 @@ void log_error(char *file, int line, const char *format, ...) {
tim->tm_min, tim->tm_sec, file, line);
vfprintf(stderr, format, ap);
fprintf(stderr,"\n");
} else {
}
// always log INFO, WARN, ERROR to syslog
// } else {
/* running as daemon - log via SYSLOG facility */
vsnprintf(string, sizeof(string), format, ap);
syslog(LOG_USER|LOG_WARNING, "%s:%i ERROR:%s", file, line, string);
}
// }
va_end(ap);
fflush(stderr);
@@ -133,11 +135,13 @@ void log_warn(char *file, int line, const char *format, ...) {
tim->tm_min, tim->tm_sec,file,line);
vfprintf(stderr, format, ap);
fprintf(stderr,"\n");
} else {
}
// always log INFO, WARN, ERROR to syslog
// } else {
/* running as daemon - log via SYSLOG facility */
vsnprintf(string, sizeof(string), format, ap);
syslog(LOG_USER|LOG_NOTICE, "%s:%i WARNING:%s", file, line, string);
}
// }
va_end(ap);
fflush(stderr);
@@ -162,11 +166,13 @@ void log_info(char *file, int line, const char *format, ...) {
tim->tm_min, tim->tm_sec,file,line);
vfprintf(stderr, format, ap);
fprintf(stderr,"\n");
} else {
}
// always log INFO, WARN, ERROR to syslog
// } else {
/* running as daemon - log via SYSLOG facility */
vsnprintf(string, sizeof(string), format, ap);
syslog(LOG_USER|LOG_NOTICE, "%s:%i INFO:%s", file, line, string);
}
// }
va_end(ap);
fflush(stderr);
+43 -156
View File
@@ -144,6 +144,11 @@ int proxy_request (sip_t *request) {
*/
case REQTYP_INCOMING:
sts = get_ip_by_host(urlmap[i].true_url->host, &sendto_addr);
if (sts == STS_FAILURE) {
DEBUGC(DBCLASS_PROXY, "proxy_request: cannot resolve URI [%s]",
url->host);
return STS_FAILURE;
}
/* rewrite request URI to point to the real host */
/* i still holds the valid index into the URLMAP table */
@@ -152,9 +157,10 @@ int proxy_request (sip_t *request) {
}
/* add my Via header line (inbound interface)*/
sts = proxy_add_myvia(request, 1);
sts = sip_add_myvia(request, IF_INBOUND);
if (sts == STS_FAILURE) {
WARN("adding my inbound via failed!");
ERROR("adding my inbound via failed!");
return STS_FAILURE;
}
/* if this is CANCEL/BYE request, stop RTP proxying */
@@ -171,7 +177,14 @@ int proxy_request (sip_t *request) {
case REQTYP_OUTGOING:
/* get destination address */
url=msg_geturi(request);
sts = get_ip_by_host(url->host, &sendto_addr);
if (sts == STS_FAILURE) {
DEBUGC(DBCLASS_PROXY, "proxy_request: cannot resolve URI [%s]",
url->host);
return STS_FAILURE;
}
/* if it is addressed to myself, then it must be some request
* method that I as a proxy do not support. Reject */
if (is_sipuri_local(request) == STS_TRUE) {
@@ -182,12 +195,11 @@ int proxy_request (sip_t *request) {
url->username? url->username : "*NULL*",
url->host? url->host : "*NULL*");
proxy_gen_response(request, 403 /*forbidden*/);
sip_gen_response(request, 403 /*forbidden*/);
return STS_FAILURE;
}
/* if an INVITE, rewrite body */
if (MSG_IS_INVITE(request)) {
sts = proxy_rewrite_invitation_body(request);
@@ -219,7 +231,7 @@ int proxy_request (sip_t *request) {
}
/* add my Via header line (outbound interface)*/
sts = proxy_add_myvia(request, 0);
sts = sip_add_myvia(request, IF_OUTBOUND);
if (sts == STS_FAILURE) {
ERROR("adding my outbound via failed!");
}
@@ -233,8 +245,8 @@ int proxy_request (sip_t *request) {
default:
url=msg_geturi(request);
DEBUGC(DBCLASS_PROXY,"proxy_request: refused to proxy");
WARN("request [%s] from/to unregistered UA (RQ: %s@%s -> %s@%s)",
DEBUGC(DBCLASS_PROXY, "request [%s] from/to unregistered UA "
"(RQ: %s@%s -> %s@%s)",
request->strtline->sipmethod? request->strtline->sipmethod:"*NULL*",
request->from->url->username? request->from->url->username:"*NULL*",
request->from->url->host? request->from->url->host : "*NULL*",
@@ -242,12 +254,18 @@ int proxy_request (sip_t *request) {
url->host? url->host : "*NULL*");
/*
* if we end up here, we deal with a request that we have
* no proxy entry - so it must be ment to be for the proxy itself.
* As we only deal with REGISTER requests, we will anser this one
* with FORBIDDEN
* we may end up here for two reasons:
* 1) An incomming request (from outbound) that is directed to
* an unknown (not registered) local UA
* 2) an outgoing request from a local UA that is not registered.
*
* Case 1) we should probably answer with "404 Not Found",
* case 2) more likely a "403 Forbidden"
*
* How about "408 Request Timeout" ?
*
*/
proxy_gen_response(request, 403 /*forbidden*/);
sip_gen_response(request, 408 /* Request Timeout */);
return STS_FAILURE;
}
@@ -304,7 +322,7 @@ int proxy_response (sip_t *response) {
}
/* ALWAYS: remove my Via header line */
sts = proxy_del_myvia(response);
sts = sip_del_myvia(response);
if (sts == STS_FAILURE) {
DEBUGC(DBCLASS_PROXY,"not addressed to my VIA, ignoring response");
return STS_FAILURE;
@@ -394,8 +412,7 @@ int proxy_response (sip_t *response) {
break;
default:
DEBUGC(DBCLASS_PROXY,"proxy_response: refused to proxy");
WARN("response from/to unregistered UA (%s@%s)",
DEBUGC(DBCLASS_PROXY, "response from/to unregistered UA (%s@%s)",
response->from->url->username? response->from->url->username:"*NULL*",
response->from->url->host? response->from->url->host : "*NULL*");
return STS_FAILURE;
@@ -409,6 +426,11 @@ int proxy_response (sip_t *response) {
}
sts = get_ip_by_host(via->host, &addr);
if (sts == STS_FAILURE) {
DEBUGC(DBCLASS_PROXY, "proxy_response: cannot resolve via [%s]",
via->host);
return STS_FAILURE;
}
sts = msg_2char(response, &buffer);
if (sts != 0) {
@@ -429,147 +451,6 @@ int proxy_response (sip_t *response) {
}
/*
* PROXY_GEN_RESPONSE
*
* send an proxy generated response back to the client.
* Only errors are reported from the proxy itself.
* code = SIP result code to deliver
*
* RETURNS
* STS_SUCCESS on success
* STS_FAILURE on error
*/
int proxy_gen_response(sip_t *request, int code) {
sip_t *response;
int sts;
via_t *via;
int port;
char *buffer;
struct in_addr addr;
/* create the response template */
if ((response=msg_make_template_reply(request, code))==NULL) {
ERROR("proxy_response: error in msg_make_template_reply");
return STS_FAILURE;
}
/* we must check if first via has x.x.x.x address. If not, we must resolve it */
msg_getvia (response, 0, &via);
if (via == NULL)
{
ERROR("proxy_response: Cannot send response - no via field");
return STS_FAILURE;
}
/* name resolution */
if (inet_aton (via->host,&addr) == 0)
{
/* need name resolution */
DEBUGC(DBCLASS_DNS,"resolving name:%s",via->host);
sts = get_ip_by_host(via->host, &addr);
}
DEBUGC(DBCLASS_PROXY,"response=%p",response);
sts = msg_2char(response, &buffer);
if (sts != 0) {
ERROR("proxy_response: msg_2char failed");
return STS_FAILURE;
}
if (via->port) {
port=atoi(via->port);
} else {
port=SIP_PORT;
}
/* send to destination */
sipsock_send_udp(&sip_socket, addr, port,
buffer, strlen(buffer), 1);
/* free the resources */
msg_free(response);
free(response);
free (buffer);
return STS_SUCCESS;
}
/*
* PROXY_ADD_MYVIA
*
* interface == 0 -> outbound interface, else inbound interface
*
* RETURNS
* STS_SUCCESS on success
* STS_FAILURE on error
*/
int proxy_add_myvia (sip_t *request, int interface) {
struct in_addr addr;
char tmp[URL_STRING_SIZE];
via_t *via;
int sts;
if (interface == 0) {
sts = get_ip_by_ifname(configuration.outbound_if, &addr);
if (sts == STS_FAILURE) {
ERROR("can't find outbound interface %s - configuration error?",
configuration.outbound_if);
return STS_FAILURE;
}
} else {
sts = get_ip_by_ifname(configuration.inbound_if, &addr);
if (sts == STS_FAILURE) {
ERROR("can't find inbound interface %s - configuration error?",
configuration.inbound_if);
return STS_FAILURE;
}
}
sprintf(tmp, "SIP/2.0/UDP %s:%i", inet_ntoa(addr),
configuration.sip_listen_port);
DEBUGC(DBCLASS_BABBLE,"adding VIA:%s",tmp);
sts = via_init(&via);
if (sts!=0) return STS_FAILURE; /* allocation failed */
sts = via_parse(via, tmp);
if (sts!=0) return STS_FAILURE;
list_add(request->vias,via,0);
return STS_SUCCESS;
}
/*
* PROXY_DEL_MYVIA
*
* RETURNS
* STS_SUCCESS on success
* STS_FAILURE on error
*/
int proxy_del_myvia (sip_t *response) {
via_t *via;
int sts;
DEBUGC(DBCLASS_PROXY,"deleting topmost VIA");
via = list_get (response->vias, 0);
if ( is_via_local(via) == STS_FALSE ) {
ERROR("I'm trying to delete a VIA but it's not mine! host=%s",via->host);
return STS_FAILURE;
}
sts = list_remove(response->vias, 0);
via_free (via);
free(via);
return STS_SUCCESS;
}
/*
* PROXY_REWRITE_INVITATION_BODY
*
@@ -619,6 +500,12 @@ int proxy_rewrite_invitation_body(sip_t *mymsg){
* start forwarding for each media stream ('m=' item in SIP message)
*/
sts = get_ip_by_host(sdp_c_addr_get(sdp,-1,0), &lcl_clnt_addr);
if (sts == STS_FAILURE) {
DEBUGC(DBCLASS_PROXY, "proxy_rewrite_invitation_body: cannot resolve "
"m= (media) host [%s]", sdp_c_addr_get(sdp,-1,0));
return STS_FAILURE;
}
sts = get_ip_by_ifname(configuration.outbound_if, &outb_addr);
if (sts == STS_FAILURE) {
ERROR("can't find outbound interface %s - configuration error?",
+25 -10
View File
@@ -112,15 +112,19 @@ int register_client(sip_t *my_msg) {
expires=600;
msg_setexpires(my_msg, "600");
}
DEBUGC(DBCLASS_REG,"expires:%i seconds",expires);
url1_to=my_msg->to->url;
url1_contact=((contact_t*)(my_msg->contacts->node->element))->url;
DEBUGC(DBCLASS_REG,"register: %s@%s expires=%i seconds",
(url1_contact->username) ? url1_contact->username : "*NULL*",
(url1_contact->host) ? url1_contact->host : "*NULL*",
expires);
/* Update registration. There are two possibilities:
* - already registered, then update the existing record
* - not registered, then create a new record
*/
url1_to=my_msg->to->url;
url1_contact=((contact_t*)(my_msg->contacts->node->element))->url;
j=-1;
for (i=0; i<URLMAP_SIZE; i++) {
@@ -134,9 +138,12 @@ int register_client(sip_t *my_msg) {
if ( (compare_url(url1_to, url2_to)==STS_SUCCESS) &&
(compare_url(url1_contact, url2_contact)==STS_SUCCESS) ) {
DEBUGC(DBCLASS_REG, "found entry for %s@%s at slot=%i, exp=%li",
DEBUGC(DBCLASS_REG, "found entry for %s@%s <-> %s@%s at "
"slot=%i, exp=%li",
(url1_contact->username) ? url1_contact->username : "*NULL*",
(url1_contact->host) ? url1_contact->host : "*NULL*",
(url2_to->username) ? url2_to->username : "*NULL*",
(url2_to->host) ? url2_to->host : "*NULL*",
i, urlmap[i].expires-time_now);
break;
}
@@ -151,10 +158,6 @@ int register_client(sip_t *my_msg) {
if (i >= URLMAP_SIZE) {
/* entry not existing, create new one */
i=j;
DEBUGC(DBCLASS_REG,"create new entry for %s@%s at slot=%i",
(url1_contact->username) ? url1_contact->username : "*NULL*",
(url1_contact->host) ? url1_contact->host : "*NULL*",
i);
/* write entry */
urlmap[i].active=1;
@@ -163,6 +166,13 @@ int register_client(sip_t *my_msg) {
url_clone( my_msg->to->url,
&urlmap[i].reg_url); /* To: field */
DEBUGC(DBCLASS_REG,"create new entry for %s@%s <-> %s@%s at slot=%i",
(url1_contact->username) ? url1_contact->username : "*NULL*",
(url1_contact->host) ? url1_contact->host : "*NULL*",
(urlmap[i].reg_url->username) ? urlmap[i].reg_url->username : "*NULL*",
(urlmap[i].reg_url->host) ? urlmap[i].reg_url->host : "*NULL*",
i);
/*
* try to figure out if we ought to do some masquerading
*/
@@ -197,10 +207,10 @@ int register_client(sip_t *my_msg) {
via_clone( ((via_t*)(my_msg->vias->node->element)),
&urlmap[i].via); /* via field */
}
} /* if new entry */
/* give some safety margin for the next update */
if (expires >0) expires+=30;
if (expires > 0) expires+=30;
/* update registration timeout */
urlmap[i].expires=time_now+expires;
@@ -304,6 +314,11 @@ int register_response(sip_t *request, int flag) {
if (inet_aton (via->host,&addr) == 0) {
/* yes, get IP address */
sts = get_ip_by_host(via->host, &addr);
if (sts == STS_FAILURE) {
DEBUGC(DBCLASS_REG, "register_response: cannot resolve VIA [%s]",
via->host);
return STS_FAILURE;
}
}
sts = msg_2char(response, &buffer);
+47 -10
View File
@@ -23,6 +23,7 @@
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
@@ -40,6 +41,10 @@
#include "siproxd.h"
#include "log.h"
static char const ident[]="$Id: " __FILE__ ": " PACKAGE "-" VERSION "-"\
BUILDSTR " $";
/* configuration storage */
extern struct siproxd_config configuration;
@@ -64,7 +69,7 @@ struct {
/* thread id of RTP proxy */
pthread_t rtpproxy_tid;
pthread_t rtpproxy_tid=0;
/* master fd_set */
fd_set master_fdset;
@@ -165,7 +170,7 @@ void *rtpproxy_main(void *arg) {
num_fd--;
}
}
} /* for i */
/* age and clean rtp_proxytable */
@@ -177,8 +182,9 @@ void *rtpproxy_main(void *arg) {
/* time one has expired, clean it up */
callid.number=rtp_proxytable[i].callid_number;
callid.host=rtp_proxytable[i].callid_host;
DEBUGC(DBCLASS_RTP,"RTP stream %s@%s (idx=%i) has expired",
callid.number, callid.host, i);
DEBUGC(DBCLASS_RTP,"RTP stream sock=%i %s@%s (idx=%i) "
"has expired", rtp_proxytable[i].sock,
callid.number, callid.host, i);
rtp_stop_fwd(&callid, 1); /* don't lock the mutex, as we own
the lock already here */
}
@@ -305,7 +311,7 @@ int rtp_start_fwd (call_id_t *callid, int media_stream_no,
/* port is available, try to allocate */
if (j == RTPPROXY_SIZE) {
port=i;
sock=sockbind(outbound_ipaddr, port);
sock=sockbind(outbound_ipaddr, port, 0);
/* if success break, else try further on */
if (sock) break;
}
@@ -384,8 +390,8 @@ unlock_and_exit:
* STS_FAILURE on error
*/
int rtp_stop_fwd (call_id_t *callid, int nolock) {
int i;
int sts=STS_SUCCESS;
int i, sts;
int retsts=STS_SUCCESS;
int got_match=0;
if (configuration.rtp_proxy_enable == 0) return STS_SUCCESS;
@@ -426,7 +432,20 @@ int rtp_stop_fwd (call_id_t *callid, int nolock) {
(strcmp(rtp_proxytable[i].callid_host, callid->host)==0) ) {
/* match: close socket and clean slot in rtp_proxytable */
close(rtp_proxytable[i].sock);
sts = close(rtp_proxytable[i].sock);
if (sts < 0) {
ERROR("Error in close(%i): %s\n", rtp_proxytable[i].sock,
strerror(errno));
}
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;
}
@@ -437,7 +456,7 @@ int rtp_stop_fwd (call_id_t *callid, int nolock) {
if (!got_match) {
DEBUGC(DBCLASS_RTP,"rtp_stop_fwd: can't find active stream for %s@%s",
callid->number, callid->host);
sts = STS_FAILURE;
retsts = STS_FAILURE;
goto unlock_and_exit;
}
@@ -460,7 +479,7 @@ unlock_and_exit:
}
#undef return
return sts;
return retsts;
}
@@ -487,3 +506,21 @@ int rtp_recreate_fdset(void) {
return STS_SUCCESS;
}
/*
* kills the rtp_proxy thread
*
* RETURNS
* -
*/
void rtpproxy_kill( void ) {
void *thread_status;
if (rtpproxy_tid) {
pthread_cancel(rtpproxy_tid);
pthread_join(rtpproxy_tid, &thread_status);
}
DEBUGC(DBCLASS_RTP,"killed RTP proxy thread");
return;
}
+4
View File
@@ -37,6 +37,10 @@
#include "log.h"
static char const ident[]="$Id: " __FILE__ ": " PACKAGE "-" VERSION "-"\
BUILDSTR " $";
/*
* do security and integrity checks on the received packet
* (raw buffer)
+168 -5
View File
@@ -54,6 +54,7 @@ static char const ident[]="$Id: " __FILE__ ": " PACKAGE "-" VERSION "-"\
extern struct siproxd_config configuration;
extern int h_errno;
extern int sip_socket; /* sending SIP datagrams */
/*
@@ -174,7 +175,12 @@ int is_via_local (via_t *via) {
DEBUGC(DBCLASS_BABBLE,"via name %s",via->host);
if (inet_aton(via->host,&addr_via) == 0) {
/* need name resolution */
get_ip_by_host(via->host, &addr_via);
sts=get_ip_by_host(via->host, &addr_via);
if (sts == STS_FAILURE) {
DEBUGC(DBCLASS_DNS, "is_via_local: cannot resolve VIA [%s]",
via->host);
return STS_FAILURE;
}
}
found=0;
@@ -233,14 +239,26 @@ int compare_url(url_t *url1, url_t *url2) {
}
/* get the IP addresses from the (possible) hostnames */
get_ip_by_host(url1->host, &addr1);
get_ip_by_host(url2->host, &addr2);
sts=get_ip_by_host(url1->host, &addr1);
if (sts == STS_FAILURE) {
DEBUGC(DBCLASS_PROXY, "compare_url: cannot resolve host [%s]",
url1->host);
return STS_FAILURE;
}
sts=get_ip_by_host(url2->host, &addr2);
if (sts == STS_FAILURE) {
DEBUGC(DBCLASS_PROXY, "compare_url: cannot resolve host [%s]",
url2->host);
return STS_FAILURE;
}
/* Broken(?) MSN messenger - does not supply a user name part.
So we simply compare the host part then */
if ((url1->username == NULL) || (url2->username == NULL)) {
WARN("compare_url: NULL username pointer: MSN messenger is known to "
"trigger this one!");
// let's be nice to Billy boy and don't complain evey time ;-)
// WARN("compare_url: NULL username pointer: MSN messenger is known to "
// "trigger this one!");
DEBUGC(DBCLASS_DNS, "comparing broken urls (no user): "
"%s[%s] -> %s[%s]",
url1->host, inet_ntoa(addr1), url2->host, inet_ntoa(addr2));
@@ -402,3 +420,148 @@ int check_rewrite_rq_uri (sip_t *sip) {
}
/*
* PROXY_GEN_RESPONSE
*
* send an proxy generated response back to the client.
* Only errors are reported from the proxy itself.
* code = SIP result code to deliver
*
* RETURNS
* STS_SUCCESS on success
* STS_FAILURE on error
*/
int sip_gen_response(sip_t *request, int code) {
sip_t *response;
int sts;
via_t *via;
int port;
char *buffer;
struct in_addr addr;
/* create the response template */
if ((response=msg_make_template_reply(request, code))==NULL) {
ERROR("proxy_response: error in msg_make_template_reply");
return STS_FAILURE;
}
/* we must check if first via has x.x.x.x address. If not, we must resolve it */
msg_getvia (response, 0, &via);
if (via == NULL)
{
ERROR("proxy_response: Cannot send response - no via field");
return STS_FAILURE;
}
/* name resolution */
if (inet_aton(via->host, &addr) == 0)
{
/* need name resolution */
DEBUGC(DBCLASS_DNS,"resolving name:%s",via->host);
sts = get_ip_by_host(via->host, &addr);
if (sts == STS_FAILURE) {
DEBUGC(DBCLASS_PROXY, "sip_gen_response: cannot resolve via [%s]",
via->host);
return STS_FAILURE;
}
}
sts = msg_2char(response, &buffer);
if (sts != 0) {
ERROR("proxy_response: msg_2char failed");
return STS_FAILURE;
}
if (via->port) {
port=atoi(via->port);
} else {
port=SIP_PORT;
}
/* send to destination */
sipsock_send_udp(&sip_socket, addr, port,
buffer, strlen(buffer), 1);
/* free the resources */
msg_free(response);
free(response);
free (buffer);
return STS_SUCCESS;
}
/*
* PROXY_ADD_MYVIA
*
* interface == IF_OUTBOUND, IF_INBOUND
*
* RETURNS
* STS_SUCCESS on success
* STS_FAILURE on error
*/
int sip_add_myvia (sip_t *request, int interface) {
struct in_addr addr;
char tmp[URL_STRING_SIZE];
via_t *via;
int sts;
if (interface == IF_OUTBOUND) {
sts = get_ip_by_ifname(configuration.outbound_if, &addr);
if (sts == STS_FAILURE) {
ERROR("can't find outbound interface %s - configuration error?",
configuration.outbound_if);
return STS_FAILURE;
}
} else {
sts = get_ip_by_ifname(configuration.inbound_if, &addr);
if (sts == STS_FAILURE) {
ERROR("can't find inbound interface %s - configuration error?",
configuration.inbound_if);
return STS_FAILURE;
}
}
sprintf(tmp, "SIP/2.0/UDP %s:%i", inet_ntoa(addr),
configuration.sip_listen_port);
DEBUGC(DBCLASS_BABBLE,"adding VIA:%s",tmp);
sts = via_init(&via);
if (sts!=0) return STS_FAILURE; /* allocation failed */
sts = via_parse(via, tmp);
if (sts!=0) return STS_FAILURE;
list_add(request->vias,via,0);
return STS_SUCCESS;
}
/*
* PROXY_DEL_MYVIA
*
* RETURNS
* STS_SUCCESS on success
* STS_FAILURE on error
*/
int sip_del_myvia (sip_t *response) {
via_t *via;
int sts;
DEBUGC(DBCLASS_PROXY,"deleting topmost VIA");
via = list_get (response->vias, 0);
if ( is_via_local(via) == STS_FALSE ) {
ERROR("I'm trying to delete a VIA but it's not mine! host=%s",via->host);
return STS_FAILURE;
}
sts = list_remove(response->vias, 0);
via_free (via);
free(via);
return STS_SUCCESS;
}
+32 -6
View File
@@ -129,6 +129,10 @@ int main (int argc, char *argv[])
/*
* Init stuff
*/
/* cancel RTP thread at exit */
atexit(rtpproxy_kill);
/* read the config file */
if (read_config(configfile, config_search) == STS_FAILURE) exit(1);
@@ -225,7 +229,10 @@ int main (int argc, char *argv[])
(my_msg->strtline->sipmethod)?
my_msg->strtline->sipmethod : "NULL") ;
/* if RQ REGISTER, just register and send an answer */
/*
* if RQ REGISTER, just register
* and send an answer
*/
if (MSG_IS_REGISTER(my_msg) && MSG_IS_REQUEST(my_msg)) {
if (access & ACCESSCTL_REG) {
sts = register_client(my_msg);
@@ -235,9 +242,24 @@ int main (int argc, char *argv[])
inet_ntoa(from.sin_addr));
}
/* MSG is a request, add current via entry,
/*
* check if outbound interface is UP.
* If not, send back error to UA and
* skip any proxying attempt
*/
} else if (get_ip_by_ifname(configuration.outbound_if,NULL) !=
STS_SUCCESS) {
DEBUGC(DBCLASS_SIP, "got a %s to proxy, but outbound interface "
"is down", (MSG_IS_REQUEST(my_msg))? "REQ" : "RES");
if (MSG_IS_REQUEST(my_msg))
sip_gen_response(my_msg, 408 /*request timeout*/);
/*
* MSG is a request, add current via entry,
* do a lookup in the URLMAP table and
* send to the final destination */
* send to the final destination
*/
} else if (MSG_IS_REQUEST(my_msg)) {
if (access & ACCESSCTL_SIP) {
sts = proxy_request(my_msg);
@@ -246,8 +268,10 @@ int main (int argc, char *argv[])
inet_ntoa(from.sin_addr));
}
/* MSG is a response, remove current via and
* send to next via in chain */
/*
* MSG is a response, remove current via and
* send to the next VIA in chain
*/
} else if (MSG_IS_RESPONSE(my_msg)) {
if (access & ACCESSCTL_SIP) {
sts = proxy_response(my_msg);
@@ -256,7 +280,9 @@ int main (int argc, char *argv[])
inet_ntoa(from.sin_addr));
}
/* unsupported message */
/*
* unsupported message
*/
} else {
ERROR("received unsupported SIP type %s %s",
(MSG_IS_REQUEST(my_msg))? "REQ" : "RES",
+15 -9
View File
@@ -26,7 +26,7 @@ int sipsock_wait(void);
int sipsock_read(void *buf, size_t bufsize, struct sockaddr_in *from);
int sipsock_send_udp(int *sock, struct in_addr addr, int port, /*X*/
char *buffer, int size, int allowdump);
int sockbind(struct in_addr ipaddr, int localport);
int sockbind(struct in_addr ipaddr, int localport, int errflg);
/* register.c */
void register_init(void);
@@ -37,9 +37,6 @@ int register_response(sip_t *request, int flag); /*X*/
/* proxy.c */
int proxy_request (sip_t *request); /*X*/
int proxy_response (sip_t *response); /*X*/
int proxy_gen_response(sip_t *request, int code); /*X*/
int proxy_add_myvia (sip_t *request, int interface); /*X*/
int proxy_del_myvia (sip_t *response); /*X*/
int proxy_rewrite_invitation_body(sip_t *mymsg); /*X*/
int proxy_rewrite_request_uri(sip_t *mymsg, int idx); /*X*/
@@ -55,16 +52,22 @@ int is_via_local (via_t *via); /*X*/
int compare_url(url_t *url1, url_t *url2); /*X*/
int is_sipuri_local (sip_t *sip); /*X*/
int check_rewrite_rq_uri (sip_t *sip); /*X*/
int sip_gen_response(sip_t *request, int code); /*X*/
#define IF_OUTBOUND 0
#define IF_INBOUND 1
int sip_add_myvia (sip_t *request, int interface); /*X*/
int sip_del_myvia (sip_t *response); /*X*/
/* readconf.c */
int read_config(char *name, int search); /*X*/
/* rtpproxy.c */
int rtpproxy_init( void ); /*X*/
int rtp_start_fwd (call_id_t *callid, int media_stream_no, /*X*/
struct in_addr outbound_ipaddr, int *outboundport,
struct in_addr lcl_client_ipaddr, int lcl_clientport);
int rtp_stop_fwd (call_id_t *callid, int nolock); /*X*/
int rtpproxy_init( void ); /*X*/
int rtp_start_fwd (call_id_t *callid, int media_stream_no, /*X*/
struct in_addr outbound_ipaddr, int *outboundport,
struct in_addr lcl_client_ipaddr, int lcl_clientport);
int rtp_stop_fwd (call_id_t *callid, int nolock); /*X*/
void rtpproxy_kill( void ); /*X*/
/* accessctl.c */
int accesslist_check(struct sockaddr_in from);
@@ -144,6 +147,9 @@ struct siproxd_config {
#define STATUSCODE_SIZE 5 /* size of string representation of status */
#define DNS_CACHE_SIZE 32 /* number of entries in internal DNS cache */
#define DNS_MAX_AGE 60 /* maximum age of an cache entry (sec) */
#define IFADR_CACHE_SIZE 32 /* number of entries in internal IFADR cache */
#define IFADR_MAX_AGE 5 /* max. age of the IF address cache (sec) */
#define IFNAME_SIZE 16 /* max string length of a interface name */
#define HOSTNAME_SIZE 64 /* max string length of a hostname */
#define USERNAME_SIZE 64 /* max string length of a username (auth) */
#define PASSWORD_SIZE 64 /* max string length of a password (auth) */
+10 -8
View File
@@ -61,8 +61,8 @@ int sipsock_listen (void) {
struct in_addr ipaddr;
memset(&ipaddr, 0, sizeof(struct in_addr));
listen_socket=sockbind(ipaddr, configuration.sip_listen_port);
if (listen_socket==0) return STS_FAILURE; /* failure*/
listen_socket=sockbind(ipaddr, configuration.sip_listen_port, 1);
if (listen_socket == 0) return STS_FAILURE; /* failure*/
INFO("listening on port %i", configuration.sip_listen_port);
DEBUGC(DBCLASS_NET,"bound listen socket %i",listen_socket);
@@ -127,7 +127,7 @@ int sipsock_send_udp(int *sock, struct in_addr addr, int port,
/* first time: allocate a socket for sending */
if (*sock == 0) {
*sock=socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (*sock == 0) {
if (*sock < 0) {
ERROR("socket() call failed:%s",strerror(errno));
return STS_FAILURE;
}
@@ -154,7 +154,8 @@ int sipsock_send_udp(int *sock, struct in_addr addr, int port,
if (sts == -1) {
if (errno != ECONNREFUSED) {
ERROR("sendto() call failed: %s",strerror(errno));
ERROR("sendto() [%s] call failed: %s",inet_ntoa(addr),
strerror(errno));
return STS_FAILURE;
}
DEBUGC(DBCLASS_BABBLE,"sendto() call failed:%s",strerror(errno));
@@ -168,27 +169,28 @@ int sipsock_send_udp(int *sock, struct in_addr addr, int port,
/*
* generic routine to allocate and bind a socket to a specified
* local address and port (UDP)
* errflg !=0 log errors, ==0 don't
*
* RETURNS socket number on success, zero on failure
*/
int sockbind(struct in_addr ipaddr, int localport) {
int sockbind(struct in_addr ipaddr, int localport, int errflg) {
struct sockaddr_in my_addr;
int sts;
int sock;
my_addr.sin_family = AF_INET;
memcpy(&my_addr.sin_addr.s_addr, &ipaddr, sizeof(struct in_addr));
my_addr.sin_port= htons(localport);
my_addr.sin_port = htons(localport);
sock=socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sock == 0) {
if (sock < 0) {
ERROR("socket() call failed:%s",strerror(errno));
return 0;
}
sts=bind(sock, (struct sockaddr *)&my_addr, sizeof(my_addr));
if (sts != 0) {
ERROR("bind failed:%s",strerror(errno));
if (errflg) ERROR("bind failed:%s",strerror(errno));
close(sock);
return 0;
}
+108 -10
View File
@@ -68,7 +68,7 @@ int get_ip_by_host(char *hostname, struct in_addr *addr) {
static struct {
time_t timestamp;
struct in_addr addr;
char hostname[HOSTNAME_SIZE];
char hostname[HOSTNAME_SIZE+1];
} dns_cache[DNS_CACHE_SIZE];
static int cache_initialized=0;
@@ -116,11 +116,22 @@ int get_ip_by_host(char *hostname, struct in_addr *addr) {
hostentry=gethostbyname(hostname);
if (hostentry==NULL) {
if (h_errno == HOST_NOT_FOUND) {
/* this is actually not really an error */
#ifdef HAVE_HSTRERROR
ERROR("gethostbyname(%s) failed: %s",hostname,hstrerror(h_errno));
DEBUGC(DBCLASS_DNS, "gethostbyname(%s) failed: %s",
hostname, hstrerror(h_errno));
#else
ERROR("gethostbyname(%s) failed: h_errno=%i",hostname,h_errno);
DEBUGC(DBCLASS_DNS, "gethostbyname(%s) failed: h_errno=%i",
hostname, h_errno);
#endif
} else {
#ifdef HAVE_HSTRERROR
ERROR("gethostbyname(%s) failed: %s",hostname, hstrerror(h_errno));
#else
ERROR("gethostbyname(%s) failed: h_errno=%i",hostname, h_errno);
#endif
}
return STS_FAILURE;
}
@@ -129,9 +140,8 @@ int get_ip_by_host(char *hostname, struct in_addr *addr) {
hostname, inet_ntoa(*addr));
/*
* remember the result in the cache
* find an empty slot in the cache
*/
/* find an empty slot */
j=0;
for (i=0; i<DNS_CACHE_SIZE; i++) {
if (dns_cache[i].hostname[0]=='\0') break;
@@ -144,7 +154,9 @@ int get_ip_by_host(char *hostname, struct in_addr *addr) {
/* if no empty slot found, take oldest one */
if (i >= DNS_CACHE_SIZE) i=j;
/* store in cache */
/*
* store the result in the cache
*/
DEBUGC(DBCLASS_DNS, "DNS lookup - store into cache, entry %i)", i);
memset(&dns_cache[i], 0, sizeof(dns_cache[0]));
strncpy(dns_cache[i].hostname, hostname, HOSTNAME_SIZE);
@@ -216,11 +228,24 @@ void secure_enviroment (void) {
/*
* get_ip_by_ifname:
* fetches own IP address by its interface name
*
* STS_SUCCESS on returning a valid IP and interface is UP
* STS_FAILURE if interface is DOWN or other problem
*/
int get_ip_by_ifname(char *ifname, struct in_addr *retaddr) {
struct ifreq ifr;
struct sockaddr_in *sin = (struct sockaddr_in *)&ifr.ifr_addr;
int sockfd;
int i, j;
int ifflags, isup;
time_t t;
static struct {
time_t timestamp;
struct in_addr ifaddr; /* IP */
int isup; /* interface is UP */
char ifname[IFNAME_SIZE+1];
} ifaddr_cache[IFADR_CACHE_SIZE];
static int cache_initialized=0;
if (ifname == NULL) {
WARN("get_ip_by_ifname: got NULL ifname passed - please check config"
@@ -228,6 +253,40 @@ int get_ip_by_ifname(char *ifname, struct in_addr *retaddr) {
return STS_FAILURE;
}
/* first time: initialize ifaddr cache */
if (cache_initialized == 0) {
DEBUGC(DBCLASS_DNS, "initializing ifaddr cache (%i entries)",
IFADR_CACHE_SIZE);
memset(ifaddr_cache, 0, sizeof(ifaddr_cache));
cache_initialized=1;
}
time(&t);
/* clean expired entries */
for (i=0; i<IFADR_CACHE_SIZE; i++) {
if (ifaddr_cache[i].ifname[0]=='\0') continue;
if ( (ifaddr_cache[i].timestamp+IFADR_MAX_AGE) < t ) {
DEBUGC(DBCLASS_DNS, "cleaning ifaddr cache (entry %i)", i);
memset (&ifaddr_cache[i], 0, sizeof(ifaddr_cache[0]));
}
}
/*
* search requested entry in cache
*/
for (i=0; i<IFADR_CACHE_SIZE; i++) {
if (ifaddr_cache[i].ifname[0]=='\0') continue;
if (strcmp(ifname, ifaddr_cache[i].ifname) == 0) { /* match */
if (retaddr) memcpy(retaddr, &ifaddr_cache[i].ifaddr,
sizeof(struct in_addr));
DEBUGC(DBCLASS_DNS, "ifaddr lookup - from cache: %s -> %s %s",
ifname, inet_ntoa(ifaddr_cache[i].ifaddr),
(ifaddr_cache[i].isup)? "UP":"DOWN");
return (ifaddr_cache[i].isup)? STS_SUCCESS: STS_FAILURE;
} /* if */
} /* for i */
/* not found in cache, go and get it */
bzero(&ifr, sizeof(ifr));
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
@@ -238,18 +297,57 @@ int get_ip_by_ifname(char *ifname, struct in_addr *retaddr) {
strcpy(ifr.ifr_name, ifname);
sin->sin_family = AF_INET;
/* get interface flags */
if(ioctl(sockfd, SIOCGIFFLAGS, &ifr) != 0) {
ERROR("Error in ioctl SIOCGIFFLAGS: %s\n",strerror(errno));
close(sockfd);
return STS_FAILURE;
}
ifflags=ifr.ifr_flags;
/* get address */
if(ioctl(sockfd, SIOCGIFADDR, &ifr) != 0) {
ERROR("Error in ioctl: %s\n",strerror(errno));
ERROR("Error in ioctl SIOCGIFADDR: %s\n",strerror(errno));
close(sockfd);
return STS_FAILURE;
}
DEBUGC(DBCLASS_DNS, "get_ip_by_ifname: interface %s has IP: %s",
ifname, inet_ntoa(sin->sin_addr));
if (ifflags & IFF_UP) isup=1;
else isup=0;
DEBUGC(DBCLASS_DNS, "get_ip_by_ifname: if %s has IP:%s (flags=%x) %s",
ifname, inet_ntoa(sin->sin_addr), ifflags,
(isup)? "UP":"DOWN");
/*
*find an empty slot in the cache
*/
j=0;
for (i=0; i<IFADR_CACHE_SIZE; i++) {
if (ifaddr_cache[i].ifname[0]=='\0') break;
if (ifaddr_cache[i].timestamp < t) {
/* remember oldest entry */
t=ifaddr_cache[i].timestamp;
j=i;
}
}
/* if no empty slot found, take oldest one */
if (i >= IFADR_CACHE_SIZE) i=j;
/*
* store the result in the cache
*/
DEBUGC(DBCLASS_DNS, "ifname lookup - store into cache, entry %i)", i);
memset(&ifaddr_cache[i], 0, sizeof(ifaddr_cache[0]));
strncpy(ifaddr_cache[i].ifname, ifname, IFNAME_SIZE);
ifaddr_cache[i].timestamp=t;
memcpy(&ifaddr_cache[i].ifaddr, &sin->sin_addr, sizeof(sin->sin_addr));
ifaddr_cache[i].isup=isup;
if (retaddr) memcpy(retaddr, &sin->sin_addr, sizeof(sin->sin_addr));
close(sockfd);
return STS_SUCCESS;
return (isup)? STS_SUCCESS : STS_FAILURE;
}