From 00dfe93a0d9e30caa79085e030229b52a5f7bcf8 Mon Sep 17 00:00:00 2001 From: Thomas Ries Date: Sat, 22 Nov 2003 21:54:21 +0000 Subject: [PATCH] - Introduced the use of gethostbyname_r() if available. As siproxd uses threads it probably is a very good idea (some funny things seen with Linux 2.4.18 kernel & RTP proxy - gethostbyname() did return a NULL result but has h_errno set to 0 "every fine, thanks") Future will show it this helps. - Had overlooked one inet_aton in register.c - replaced to utils_inet_aton - Fixed a compiler warning in log.c for Solaris. Siproxd now at least builds on Solaris (tested on: SunOS 5.9 sun4u sparc SUNW,Ultra-60) --- ChangeLog | 3 +++ README | 5 +++- TODO | 2 +- acinclude.m4 | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++ config.h.in | 12 +++++++++ configure.in | 14 ++++++++-- src/log.c | 2 +- src/register.c | 2 +- src/siproxd.h | 6 +++++ src/utils.c | 44 +++++++++++++++++++++++++++++++ 10 files changed, 155 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index f08470c..d2545b3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 0.5.0 ===== + 22-Nov-2003: - utils.c: use gethostbyname_r() in favor of + gethostbyname - if available (siproxd uses threads!) + - some small items & cleanup 19-Nov-2003: - Integrated a patch from Chris Ross: * have siproxd compile on Solaris and BSD/OS (more to come) * ./configure option --with-libosip-prefix diff --git a/README b/README index 5572618..39a9d8f 100644 --- a/README +++ b/README @@ -60,8 +60,11 @@ PROBLEM REPORTING If you encounter problems/crashes and ask for support, please include as much information as possible. Very helpful is a debug log that has been recorded at the time of the misbehaviour. +Also include the exact versions of the siproxd package and libosip2 +that you are using. You should also include your siproxd.conf. + -The easiest way to do this: +The easiest way to generate a debug log is: 1) make sure siproxd is not started as daemon. -> 'daemonize = 0' in the config file. 2) start siproxd: diff --git a/TODO b/TODO index dfa0d36..a10661c 100644 --- a/TODO +++ b/TODO @@ -29,7 +29,7 @@ TODOs, in random order: - feature: don't bind to 0.0.0.0 address, but only to inbound/outbound IF's (defined by IFNAME) -- support IPTABLES for RTP proxying +- support IPTABLES for RTP proxying -> use libiptc - rtpproxy_masq: RACE CONDITIONS! A slot may be timed out, even if the actual diff --git a/acinclude.m4 b/acinclude.m4 index a7710c8..6c81b99 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -224,3 +224,74 @@ fi ])dnl ACX_PTHREAD +dnl @synopsis ACX_WHICH_GETHOSTBYNAME_R +dnl +dnl Provides a test to determine the correct +dnl way to call gethostbyname_r +dnl +dnl defines HAVE_FUNC_GETHOSTBYNAME_R_6 if it needs 6 arguments (e.g linux) +dnl defines HAVE_FUNC_GETHOSTBYNAME_R_5 if it needs 5 arguments (e.g. solaris) +dnl defines HAVE_FUNC_GETHOSTBYNAME_R_3 if it needs 3 arguments (e.g. osf/1) +dnl +dnl if used in conjunction in gethostname.c the api demonstrated +dnl in test.c can be used regardless of which gethostbyname_r +dnl exists. These example files found at +dnl http://www.csn.ul.ie/~caolan/publink/gethostbyname_r +dnl +dnl @version $Id$ +dnl @author Caolan McNamara +dnl +dnl based on David Arnold's autoconf suggestion in the threads faq +dnl +AC_DEFUN([ACX_WHICH_GETHOSTBYNAME_R], [ + +AC_CHECK_FUNC(gethostbyname_r, [ + AC_MSG_CHECKING(how many arguments takes gethostbyname_r) + AC_TRY_COMPILE([ + #include + #include ], [ + char *name; + struct hostent *he; + struct hostent_data data; + (void) gethostbyname_r(name, he, &data); + ],acx_which_gethostname_r=three, [ +dnl + AC_TRY_COMPILE([ + #include + #include ], [ + char *name; + struct hostent *he, *res; + char buffer[2048]; + int buflen = 2048; + int h_errnop; + (void) gethostbyname_r(name, he, buffer, buflen, &res, &h_errnop) + ],acx_which_gethostname_r=six, [ +dnl + AC_TRY_COMPILE([ + #include + #include ], [ + char *name; + struct hostent *he; + char buffer[2048]; + int buflen = 2048; + int h_errnop; + (void) gethostbyname_r(name, he, buffer, buflen, &h_errnop) + ],acx_which_gethostname_r=five,acx_which_gethostname_r=no) + + ]) + ]) +], acx_which_gethostname_r=no) + +if test $acx_which_gethostname_r = six; then + AC_DEFINE(HAVE_FUNC_GETHOSTBYNAME_R_6,,[gethostbyname_r takes 6 arguments]) +elif test $acx_which_gethostname_r = five; then + AC_DEFINE(HAVE_FUNC_GETHOSTBYNAME_R_5,,[gethostbyname_r takes 5 arguments]) +elif test $acx_which_gethostname_r = three; then + AC_DEFINE(HAVE_FUNC_GETHOSTBYNAME_R_3,,[gethostbyname_r takes 3 arguments]) + +fi + +AC_MSG_RESULT($acx_which_gethostname_r) + +])dnl ACX_WHICH_GETHOSTBYNAME_R + diff --git a/config.h.in b/config.h.in index ceaf657..b182335 100644 --- a/config.h.in +++ b/config.h.in @@ -39,6 +39,9 @@ /* Define if you have the gethostbyname function. */ #undef HAVE_GETHOSTBYNAME +/* Define if you have the gethostbyname_r function. */ +#undef HAVE_GETHOSTBYNAME_R + /* Define if you have the getopt_long function. */ #undef HAVE_GETOPT_LONG @@ -190,6 +193,15 @@ /* typedef socklen_t available */ #undef socklen_t +/* gethostbyname_r takes 6 arguments */ +#undef HAVE_FUNC_GETHOSTBYNAME_R_6 + +/* gethostbyname_r takes 5 arguments */ +#undef HAVE_FUNC_GETHOSTBYNAME_R_5 + +/* gethostbyname_r takes 3 arguments */ +#undef HAVE_FUNC_GETHOSTBYNAME_R_3 + /* will search for config file here */ #undef SIPROXDCONFPATH diff --git a/configure.in b/configure.in index 69db52e..93020bd 100644 --- a/configure.in +++ b/configure.in @@ -19,6 +19,7 @@ dnl 19-Sep-2003 tries DMALLOC support dnl 1-Nov-2003 tries check for NETFILTER (IPTABLES) dnl 18-Nov-2003 tries include sysconfdir to search for config dnl 19-Nov-2003 tries changes to support Solaris & BSD/OS +dnl 22-Nov-2003 tries test for gethostbyname_r() & # of args dnl dnl dnl @@ -87,13 +88,19 @@ done dnl dnl add dnl --enable-dmalloc - AC_MSG_CHECKING("building with DMALLOC support") + AC_MSG_CHECKING(building with DMALLOC support) AC_ARG_ENABLE(dmalloc, [ --enable-dmalloc build with DMALLOC support], CFLAGS="$CFLAGS -DDMALLOC ";LIBS="-ldmallocth $LIBS"; AC_MSG_RESULT(yes), AC_MSG_RESULT(no)) +dnl +dnl general stuff +dnl _POSIX_THREAD_SAFE_FUNCTIONS needed by some platforms to make +dnl reentrant functions available (gethostbyname_r) +CFLAGS="$CFLAGS -D_POSIX_THREAD_SAFE_FUNCTIONS" + dnl dnl system specific stuff dnl @@ -304,7 +311,10 @@ dnl AC_FUNC_MEMCMP AC_FUNC_VPRINTF AC_CHECK_FUNCS(strerror) -AC_CHECK_FUNCS(gethostbyname) + +AC_CHECK_FUNCS(gethostbyname gethostbyname_r) +ACX_WHICH_GETHOSTBYNAME_R() + AC_CHECK_FUNCS(getopt_long daemon syslog) AC_CHECK_FUNCS(getuid setuid getgid setgid getpwnam chroot) AC_CHECK_FUNCS(socket bind select read send sendto) diff --git a/src/log.c b/src/log.c index b83dbd2..8811f12 100644 --- a/src/log.c +++ b/src/log.c @@ -205,7 +205,7 @@ void log_dump_buffer(int class, char *file, int line, for (j=0;(j<16) && (i+j)host,&addr) == 0) { + if (utils_inet_aton(via->host,&addr) == 0) { /* yes, get IP address */ sts = get_ip_by_host(via->host, &addr); if (sts == STS_FAILURE) { diff --git a/src/siproxd.h b/src/siproxd.h index e8499e8..76187f3 100644 --- a/src/siproxd.h +++ b/src/siproxd.h @@ -167,6 +167,12 @@ struct siproxd_config { #define USERNAME_SIZE 64 /* max string length of a username (auth) */ #define PASSWORD_SIZE 64 /* max string length of a password (auth) */ + /* scratch buffer for gethostbyname_r() */ +#if defined(PR_NETDB_BUF_SIZE) + #define GETHOSTBYNAME_BUFLEN PR_NETDB_BUF_SIZE +#else + #define GETHOSTBYNAME_BUFLEN 1024 +#endif #define ACCESSCTL_SIP 1 /* for access control - SIP allowed */ #define ACCESSCTL_REG 2 /* --"-- - registr. allowed */ diff --git a/src/utils.c b/src/utils.c index fd30236..77e7c46 100644 --- a/src/utils.c +++ b/src/utils.c @@ -65,6 +65,7 @@ int get_ip_by_host(char *hostname, struct in_addr *addr) { int i, j; time_t t; struct hostent *hostentry; + int error; static struct { time_t timestamp; struct in_addr addr; @@ -113,7 +114,50 @@ int get_ip_by_host(char *hostname, struct in_addr *addr) { } /* did not find it in cache, so I have to resolve it */ + + /* need to deal with reentrant versions of gethostbyname_r() + * as we may use threads... */ +#if defined(HAVE_GETHOSTBYNAME_R) + { + struct hostent result_buffer; + char tmp[GETHOSTBYNAME_BUFLEN]; + + /* gethostbyname_r() with 3 arguments (e.g. osf/1) */ + #if defined(HAVE_FUNC_GETHOSTBYNAME_R_3) + gethostbyname_r(hostname, /* the FQDN */ + &result_buffer, /* the result buffer */ + &hostentry + ); + if (hostentry == NULL) my_error = h_errno; + + /* gethostbyname_r() with 5 arguments (e.g. solaris, linux libc5) */ + #elif defined(HAVE_FUNC_GETHOSTBYNAME_R_5) + hostentry = gethostbyname_r(hostname, /* the FQDN */ + &result_buffer, /* the result buffer */ + tmp, + GETHOSTBYNAME_BUFLEN - 1, + &error); + + /* gethostbyname_r() with 6 arguments (e.g. linux glibc) */ + #elif defined(HAVE_FUNC_GETHOSTBYNAME_R_6) + gethostbyname_r(hostname, /* the FQDN */ + &result_buffer, /* the result buffer */ + tmp, + GETHOSTBYNAME_BUFLEN - 1, + &hostentry, + &error); + #else + #error "gethostbyname_s() with 3, 5 or 6 arguments supported only" + #endif + } +#elif defined(HAVE_GETHOSTBYNAME) + #warning "did not find reentrant version of gethostbyname_r()" + #warning "depending of your OS this may or may not work" hostentry=gethostbyname(hostname); + if (hostentry == NULL) error = h_errno; +#else + #error "need gethostbyname() or gethostbyname_r()" +#endif if (hostentry==NULL) { if (h_errno == HOST_NOT_FOUND) {