- 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:
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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,
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user