this is 0.1.3

- Bugfixes in the SIP proxy part
 - Performance imporvement in RTP proxy part
 - some documentation updates
 - include ./scripts subdirectory in the distribution,
   was an error in the autoconf/automake setup
This commit is contained in:
Thomas Ries 2002-09-11 17:12:30 +00:00
parent 038f5ef904
commit c3e10ec745
13 changed files with 296 additions and 153 deletions

View File

@ -1,3 +1,21 @@
0.1.3
=====
- 11-Sep-2002: - Fixed a error in the autoconf/automake part of the project.
(scripts subdirectory was missing in the tar.gz archive.
This resulted in an error during ./configure - complaining
about non existent install-sh script)
- startup is more silent - set initial debug level to 0
- 10-Sep-2002: - Some (yea, I know...) -minor- docu updates
- 8-Sep-2002: - Masquerade Contact Headers of inbound clients
(Contact header will be used by the remote SIP
user agent to directly contact the local user agent -
and bypassing the proxy. This of course will *not* work
if the local user agent is located in a private IP range.)
- Performance optimizations in RTP proxy
- Bugfix: now masqueraded clients work with any
SIP port (other than 5060). Before, incomming
requests/responses where always sent to port 5060.
0.1.2
=====
- 7-Sep-2002: - Releases version 0.1.2

View File

@ -21,4 +21,4 @@
SUBDIRS = src doc
EXTRA_DIST = TODO RELNOTES
EXTRA_DIST = scripts TODO RELNOTES

View File

@ -87,7 +87,7 @@ VERSION = @VERSION@
SUBDIRS = src doc
EXTRA_DIST = TODO RELNOTES
EXTRA_DIST = scripts TODO RELNOTES
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
mkinstalldirs = $(SHELL) $(top_srcdir)/scripts/mkinstalldirs
CONFIG_HEADER = config.h

157
README
View File

@ -4,8 +4,8 @@ Be warned, this (and all the other) documentantation is far from
complete. This is still considered an alpha release.
Overview:
=========
OVERVIEW
========
Siprox is an proxy/masquerading daemon for the SIP protocol.
It handles registrations of SIP clients on a private IP network
and performs rewriting of the SIP message bodies to make SIP
@ -20,17 +20,18 @@ IP addresses and port numbers.
Requirements:
=============
REQUIREMENTS
============
- libosip-0.8.8 (http://www.fsf.org/software/osip/)
- pthreads (should be part of any Linux distribution)
Up to now, this packages only has been tested under an i386 Redhat Linux 6.0.
Up to now, siporxd only has been tested under an i386 Redhat Linux 6.0.
However, it should build and run under newer versions (feedback is welcome).
How to get started:
===================
HOW TO GET STARTED
==================
- ./configure
@ -38,82 +39,124 @@ How to get started:
- make install
- copy sipproxd.conf.example to /etc/siproxd.conf
- copy doc/sipproxd.conf.example to /etc/siproxd.conf
- edit /etc/siproxd.conf according to your situation
At least 'host_inbound' and 'host_outbound' have to be adapted!
host_inbound is your IP address of your private network,
host_outbound is your publich IP address or hostname (if you
have dynamic IP addresses, then you might want to use a hostname
here and use a dynamic DNS service like dyndns.org)
At least 'host_inbound' and 'host_outbound' *must* be adapted!
'host_inbound' is the firewalls IP address of your private network,
'host_outbound' is the publich IP address or hostname of the
firewall. (If you have dynamic IP addresses, then you might want
to use a hostname here and use a dynamic DNS service like [1])
- start siproxd (siproxd does *not* require root privilegdes)
$ siproxd
What siproxd does:
WHAT SIPROXD DOES
=================
Siproxd's main purpose (up to now) is to rewrite SIP messages
to be able to operate via an masquerading firewall.
Since release 0.1.2 siproxd can proxy incomming RTP streams.
Siproxd's purpose is to act as an SIP proxy for softphones located
in private IP ranges. Therefore it will rewrite SIP messages to allow a
softphone to communicate to a counterpart that is located in the Internet.
There usually will be a masquerading firewall in between to 'hide' the
private IP range (either via NAT - network address translation or
masuerading). Check the scenario drawn below.
With release 0.1.2 siproxd is also able to proxy incomming RTP data
streams. The config parameters 'rtp_port_low' and rtp_port_high' define
the port range that siproxd will use for incomming RTP data streams.
'rtp_timeout' defines after what time an unused (no data received)
rtp stream is considered dead and removed.
** RTP data stream proxying is still experimental code.
** As I had not yet the possibility to test this feature extensively,
** I'm happy about any feedback.
What siproxd does NOT do:
=========================
Scenario
--------
SINCE RELEASE 0.1.2:
Siproxd should be able to proxy incomming RTP data streams (UDP only).
This is still very experimental code ;-)
The config parameters 'rtp_port_low' and rtp_port_high' define
the port range that siproxd will use for incomming RTP data streams.
'rtp_timeout' defines after what time an unused (no data received)
rtp stream is considered dead and removed.
** As I had not yet the possibility to test this feature,
** I'd be glad about feedback.
PRIOR TO RELEASE 0.1.2:
Siproxd does *not* (yet) create masquerading tunnels or port-forwarding
for the data stream through the firewall.
These forwarding rules have to be set-up manually (currently)
Example, using ipchains (mfw):
# ipchains -A input --proto udp --dport 7078 -m 100 -j ACCEPT
# ipmasqadm mfw -A -m 100 -r <remoteaddress> 7078
Example, using ipchains (portfw):
# portfw -a -P udp -L <localaddress> 7078 -R <remoteaddress> 7078
private IP address range : Internet
10.0.0.x : (publich IP address range)
:
: foo.bar.org
+-------------+ +--------------+
! !.10 .1 ! masquerading ! publicIP
! IntHost !---------------! Firewall !------------>>
! ! ! !
+-------------+ +--------------+
:
Limitations:
============
- currently, only UDP is supported
- very likely it does not follow the SIP spec in all details ;-)
- The Firewall does IP masquerading and is running siproxd
- IntHost is running an SIP softphone (like linphone, kphone)
- The SIP address used by the softphone is sip:johndoe@foo.bar.org
- The softphone is configured to register itself at siproxd
running on the firewall host (10.0.0.1) as sip:johndoe@foo.bar.org
- foo.bar.org is the domain name corresponding to the public IP address
of the firewall (eg use some dynamic DNS service [1])
Firewall rules for incomming traffic (ipchains example):
$ ipchains -A input --proto udp --dport 5060 --log -j ACCEPT
$ ipchains -A input --proto udp --dport 7070:7080 -j ACCEPT
The first line will allow incomming SIP traffic. The second line will
allow incomming RTP traffic on the ports 7070 - 7080 (the default port
range used by siproxd for incomming RTP traffic).
Important Notice:
=================
The gethostbyname() function leaks memory in RedHat 6.0 with glibc 2.1.1.
The quick fix is to delete nisplus service from hosts entry in
/etc/nsswitch.conf. In my tests, memory use remained stable after I
made the mentioned change.
REFERENCES
==========
[1] dynamic DNS service http://www.dyndns.org
LIMITATIONS
===========
- currently, the SIP part only supports UDP
- RTP proxy support is still experimantal (so as the rest of siproxd ;-)
- very likely it does not follow the SIP spec (RFC3261) in all details
- check the TODO file for more things that we-cannot-do-but-would-like-to
IMPORTANT NOTICE
================
The gethostbyname() function leaks memory in glibc 2.1.1 (-> RedHat 6.0).
The quick fix is to delete the nisplus service from hosts entry in
/etc/nsswitch.conf.
In my tests, memory use remained stable after I made the mentioned change.
(source: http://www.squid-cache.org/Doc/FAQ/FAQ-14.html)
Contacts:
=========
CONTACTS
========
Please feel free to contact the author to:
- provide feedback
- report bugs,
- provide feedback, report bugs,
- request for additional features
- report interoperability with softphones
- ...
and visit the website at http://siproxd.sourceforge.net/
There also is a siproxd mailinglist available on sourceforge.
Thomas Ries (tries@gmx.net)
GnuPG Public Key:
pub 1024D/87BCDC94 2000-03-19 Thomas Ries (tries@gmx.net)
Key fingerprint = 13D1 19F5 77D0 4CEC 8D3F A24E 09FC C18A 87BC DC94
CREDITS
=======
Thanks to sourceforge.net for providing the distribution platform and
infrastructure.

21
TODO
View File

@ -1,20 +1,19 @@
TODOs, in anarchistic order:
============================
TODOs, in random order:
=======================
- re-think the registration mechanism (mapping and decision criteria
for in- and outgoing stuff...
- 2.2.x kernels:
make use of the portfw.so (ipmasqadm package) to create forwarding
tunnels for incomming data streams
How to determine when finished? Is it possible to keep it stateless?
- Is there a possibility to open up an masquerading tunnel by
a userspace program on the firewall?
- logging via syslog if running in daemon mode
- get_ip_by_host: reduce DNS timeouts
- Documentation
- automagically create a proper config file during install
- client authentication
- portability to other platforms / operating systems
first goal: other Unixes

View File

@ -21,18 +21,57 @@
/* Define if your <sys/time.h> declares struct tm. */
#undef TM_IN_SYS_TIME
/* Define if you have the bind function. */
#undef HAVE_BIND
/* Define if you have the fgets function. */
#undef HAVE_FGETS
/* Define if you have the gethostbyname function. */
#undef HAVE_GETHOSTBYNAME
/* Define if you have the getopt_long_only function. */
#undef HAVE_GETOPT_LONG_ONLY
/* Define if you have the read function. */
#undef HAVE_READ
/* Define if you have the select function. */
#undef HAVE_SELECT
/* Define if you have the send function. */
#undef HAVE_SEND
/* Define if you have the sendto function. */
#undef HAVE_SENDTO
/* Define if you have the socket function. */
#undef HAVE_SOCKET
/* Define if you have the sprintf function. */
#undef HAVE_SPRINTF
/* Define if you have the sscanf function. */
#undef HAVE_SSCANF
/* Define if you have the strchr function. */
#undef HAVE_STRCHR
/* Define if you have the strerror function. */
#undef HAVE_STRERROR
/* Define if you have the strncpy function. */
#undef HAVE_STRNCPY
/* Define if you have the strstr function. */
#undef HAVE_STRSTR
/* Define if you have the vfprintf function. */
#undef HAVE_VFPRINTF
/* Define if you have the <errno.h> header file. */
#undef HAVE_ERRNO_H
/* Define if you have the <stdarg.h> header file. */
#undef HAVE_STDARG_H

View File

@ -1,3 +1,13 @@
dnl
dnl History
dnl -------
dnl before time a lot happend before start of history
dnl 8-Sep-2002 tries included more tests for used functions
dnl
dnl
dnl
dnl
dnl Process this file with autoconf to produce a configure script.
AC_INIT(src/siproxd.c)
@ -5,7 +15,7 @@ dnl ******************************************************************
dnl
SPD_MAJOR_VERSION=0
SPD_MINOR_VERSION=1
SPD_MICRO_VERSION=2
SPD_MICRO_VERSION=3
SPD_VERSION=$SPD_MAJOR_VERSION.$SPD_MINOR_VERSION.$SPD_MICRO_VERSION
dnl *********************************************************************
@ -26,7 +36,7 @@ AC_CHECK_LIB(pthread, pthread_create)
dnl Checks for header files.
AC_HEADER_STDC
AC_CHECK_HEADERS(sys/time.h unistd.h)
AC_CHECK_HEADERS(sys/time.h unistd.h errno.h)
AC_CHECK_HEADERS(stdarg.h varargs.h)
dnl Checks for typedefs, structures, and compiler characteristics.
@ -38,7 +48,12 @@ AC_STRUCT_TM
dnl Checks for library functions.
AC_FUNC_MEMCMP
AC_FUNC_VPRINTF
AC_CHECK_FUNCS(select socket strerror strstr)
AC_CHECK_FUNCS(strerror)
AC_CHECK_FUNCS(gethostbyname)
AC_CHECK_FUNCS(socket bind select read send sendto)
AC_CHECK_FUNCS(getopt_long_only)
AC_CHECK_FUNCS(strncpy strchr strstr sprintf vfprintf fgets sscanf)
AC_OUTPUT(Makefile \
src/Makefile \

View File

@ -4,20 +4,6 @@
# !! This is a sample file, adapt it to your needs before using it
#
######################################################################
# DBCLASS_BABBLE 0x00000001 // babble (like entering/leaving fnc)
# DBCLASS_NET 0x00000002 // network
# DBCLASS_SIP 0x00000004 // SIP manipulations
# DBCLASS_REG 0x00000008 // Client registration
# DBCLASS_NOSPEC 0x00000010 // non specified class
# DBCLASS_PROXY 0x00000020 // proxy
# DBCLASS_DNS 0x00000040 // DNS stuff
# DBCLASS_NETTRAF 0x00000080 // network traffic
# DBCLASS_CONFIG 0x00000100 // configuration
# DBCLASS_RTP 0x00000200 // RTP proxy
#
debug_level = 0x000002fe
######################################################################
# The IP addresses of the INBOUND and OUTBOUND interface can
# be specified as hostnames or in dotted decimal form:
@ -59,8 +45,22 @@ rtp_port_high = 7080
######################################################################
# Timeout for RTP streams
# after this number of seconds, at RTP stream is considered dead
# after this number of seconds, an RTP stream is considered dead
# and proxying it will be stopped.
#
rtp_timeout = 60
######################################################################
# DBCLASS_BABBLE 0x00000001 // babble (like entering/leaving fnc)
# DBCLASS_NET 0x00000002 // network
# DBCLASS_SIP 0x00000004 // SIP manipulations
# DBCLASS_REG 0x00000008 // Client registration
# DBCLASS_NOSPEC 0x00000010 // non specified class
# DBCLASS_PROXY 0x00000020 // proxy
# DBCLASS_DNS 0x00000040 // DNS stuff
# DBCLASS_NETTRAF 0x00000080 // network traffic
# DBCLASS_CONFIG 0x00000100 // configuration
# DBCLASS_RTP 0x00000200 // RTP proxy
#
debug_level = 0x00000218

View File

@ -41,10 +41,6 @@ static char const ident[]="$Id: " __FILE__ ": " PACKAGE "-" VERSION "-"\
/* configuration storage */
extern struct siproxd_config configuration;
/*
* knows hot to rewrite the SIP URLs in a request/response
*/
extern int errno;
extern struct urlmap_s urlmap[]; /* URL mapping table */
extern struct lcl_if_s local_addresses;
@ -60,7 +56,7 @@ int proxy_request (sip_t *request) {
int sts;
int type;
struct in_addr addr;
// contact_t *contact; /* contact header issue */
contact_t *contact;
url_t *url;
int port;
char *buffer;
@ -77,25 +73,6 @@ int proxy_request (sip_t *request) {
return 1;
}
#if 0 /* Contact Header Issue */
/* figure out if this is an request comming from the outside
* world to one of our registered clients ('to' == 'masq' URL)
* or if this is a request sent by on e of our registered clients
* ('from' == 'true' URL)
*/
msg_getcontact(request,0,&contact);
/* seen with linphone-0.9.1pre1 w/ user-agent: oSIP/Linphone-0.8.0
no contact header in reequest */
if (contact==NULL) {
ERROR("Contact header is missing!");
/* THIS IS SEVERE - I HAVE NO WAY TO FIGURE OUT WHO THE
REAL CLIENT IS BEHIND THIS PACKET...
what can I do here? */
return 1;
}
#endif
type = 0;
for (i=0; i<URLMAP_SIZE; i++) {
if (urlmap[i].active == 0) continue;
@ -109,16 +86,6 @@ int proxy_request (sip_t *request) {
break;
}
#if 0 /* Contact Header Issue */
/* outgoing request ('contact' == 'true') */
if (compare_url(contact->url, urlmap[i].true_url)==0) {
type=REQTYP_OUTGOING;
DEBUGC(DBCLASS_PROXY,"outgoing request from %s@%s from inbound",
request->from->url->username,
request->from->url->host);
break;
}
#endif
/* outgoing request ('from' == 'masq') */
if (compare_url(request->from->url, urlmap[i].masq_url)==0) {
type=REQTYP_OUTGOING;
@ -146,11 +113,23 @@ int proxy_request (sip_t *request) {
url=msg_geturi(request);
free(url->host);url->host=NULL;
{
char *copy;
copy = (char *)malloc(strlen(urlmap[i].true_url->host)+1);
memcpy(copy, urlmap[i].true_url->host, strlen(urlmap[i].true_url->host));
copy[strlen(urlmap[i].true_url->host)]='\0';
url_sethost(url, copy);
char *host;
char *port;
/* set the true host */
if(urlmap[i].true_url->host) {
host = (char *)malloc(strlen(urlmap[i].true_url->host)+1);
memcpy(host, urlmap[i].true_url->host, strlen(urlmap[i].true_url->host));
host[strlen(urlmap[i].true_url->host)]='\0';
url_sethost(url, host);
}
/* set the true port */
if(urlmap[i].true_url->port) {
port = (char *)malloc(strlen(urlmap[i].true_url->port)+1);
memcpy(port, urlmap[i].true_url->port, strlen(urlmap[i].true_url->port));
port[strlen(urlmap[i].true_url->port)]='\0';
url_setport(url, port);
}
}
/* add my Via header line (inbound interface)*/
@ -159,7 +138,7 @@ int proxy_request (sip_t *request) {
/* if this is CANCEL/BYE request, stop RTP proxying */
if (MSG_IS_BYE(request) || MSG_IS_CANCEL(request)) {
/* stop the RTP proxying stream */
sts = rtp_stop_fwd(msg_getcall_id(request));
rtp_stop_fwd(msg_getcall_id(request));
}
break;
@ -173,13 +152,36 @@ int proxy_request (sip_t *request) {
sts = proxy_rewrite_invitation_body(request);
}
/* rewrite Contact header to represent the masqued address */
msg_getcontact(request,0,&contact);
if (contact != NULL) {
for (i=0;i<URLMAP_SIZE;i++){
if (urlmap[i].active == 0) continue;
if (compare_url(contact->url, urlmap[i].true_url)==0) break;
}
/* found a mapping entry */
if (i<URLMAP_SIZE) {
DEBUGC(DBCLASS_PROXY, "rewrote Contact header %s@%s -> %s@%s",
contact->url->username, contact->url->host,
urlmap[i].masq_url->username, urlmap[i].masq_url->host);
/* remove old entry */
list_remove(request->contacts,0);
contact_free(contact);
free(contact);
/* clone the masquerading url */
contact_init(&contact);
url_clone(urlmap[i].masq_url, &contact->url);
list_add(request->contacts,contact,-1);
}
}
/* add my Via header line (outbound interface)*/
sts = proxy_add_myvia(request, 0);
/* if this is CANCEL/BYE request, stop RTP proxying */
if (MSG_IS_BYE(request) || MSG_IS_CANCEL(request)) {
/* stop the RTP proxying stream */
sts = rtp_stop_fwd(msg_getcall_id(request));
rtp_stop_fwd(msg_getcall_id(request));
}
break;
@ -252,6 +254,7 @@ int proxy_response (sip_t *response) {
int type;
struct in_addr addr;
via_t *via;
contact_t *contact;
int port;
char *buffer;
@ -318,16 +321,6 @@ int proxy_response (sip_t *response) {
* from an external host to the internal masqueraded host
*/
case RESTYP_INCOMMING:
#if 0 /* do we really have to?? in the incomming response
we have the correct address. But we must rewrite an
outgoing response to an incomming INVITE request ! */
/* If an 200 answer to an INVITE request, rewrite body */
if ((MSG_IS_RESPONSEFOR(response,"INVITE") &&
(MSG_TEST_CODE(response, 200)) ) {
sts = proxy_rewrite_invitation_body(response);
}
#endif
break;
/*
@ -340,6 +333,30 @@ int proxy_response (sip_t *response) {
(MSG_TEST_CODE(response, 200))) {
sts = proxy_rewrite_invitation_body(response);
}
/* rewrite Contact header to represent the masqued address */
msg_getcontact(response,0,&contact);
if (contact != NULL) {
for (i=0;i<URLMAP_SIZE;i++){
if (urlmap[i].active == 0) continue;
if (compare_url(contact->url, urlmap[i].true_url)==0) break;
}
/* found a mapping entry */
if (i<URLMAP_SIZE) {
DEBUGC(DBCLASS_PROXY, "rewrote Contact header %s@%s -> %s@%s",
contact->url->username, contact->url->host,
urlmap[i].masq_url->username, urlmap[i].masq_url->host);
/* remove old entry */
list_remove(response->contacts,0);
contact_free(contact);
free(contact);
/* clone the masquerading url */
contact_init(&contact);
url_clone(urlmap[i].masq_url, &contact->url);
list_add(response->contacts,contact,-1);
}
}
break;
default:
@ -529,7 +546,7 @@ int proxy_rewrite_invitation_body(sip_t *mymsg){
sts = get_ip_by_host(configuration.outboundhost, &outb_addr);
inb_clnt_port = atoi(sdp_m_port_get(sdp,0));
/* start an RTP proxying stream */
sts = rtp_start_fwd(msg_getcall_id(mymsg),
rtp_start_fwd(msg_getcall_id(mymsg),
outb_addr, &outb_rtp_port,
lcl_clnt_addr, inb_clnt_port);

View File

@ -243,7 +243,7 @@ int register_response(sip_t *request, int flag) {
/* free the resources */
msg_free(response);
free(response);
free (buffer);
free(buffer);
return 0;
}

View File

@ -53,11 +53,11 @@ int main (int argc, char *argv[])
extern char *optarg;
int ch1;
char configfile[64]="siproxd";
int config_search=1;
char configfile[64]="siproxd"; /* basename of configfile */
int config_search=1; /* search the config file */
/* prepare default configuration */
configuration.debuglevel=-1;
configuration.debuglevel=0;
configuration.daemonize=0;
configuration.sip_listen_port=SIP_PORT;
configuration.inboundhost=NULL;
@ -121,7 +121,12 @@ int main (int argc, char *argv[])
register_init();
/* listen for incomming messages */
sipsock_listen();
sts=sipsock_listen();
if (sts != 0) {
/* failure to allocate SIP socket... */
ERROR("unable to bind to SIP listening socket - aborting");
return 0;
}
/* initialize the RTP proxy thread */
rtpproxy_init();

View File

@ -21,6 +21,7 @@
#include "config.h"
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
@ -43,8 +44,6 @@ static char const ident[]="$Id: " __FILE__ ": " PACKAGE "-" VERSION "-"\
/* configuration storage */
extern struct siproxd_config configuration;
extern int errno;
static int listen_socket=0;
/*
@ -57,6 +56,7 @@ int sipsock_listen (void) {
memset(&ipaddr, 0, sizeof(struct in_addr));
listen_socket=sockbind(ipaddr, configuration.sip_listen_port);
if (listen_socket==0) return 1; /* failure*/
DEBUGC(DBCLASS_NET,"bound listen socket %i",listen_socket);
return 0;
@ -121,8 +121,11 @@ int sipsock_send_udp(int *sock, struct in_addr addr, int port,
sts = sendto (*sock, buffer, size, 0, &dst_addr, sizeof(dst_addr));
if (sts == -1) {
ERROR("sendto() call failed:%s",strerror(errno));
return 1;
if (errno != ECONNREFUSED) {
ERROR("sendto() call failed:%s",strerror(errno));
return 1;
}
DEBUGC(DBCLASS_BABBLE,"sendto() call failed:%s",strerror(errno));
}
return 0;

View File

@ -187,7 +187,7 @@ int get_ip_by_host(char *hostname, struct in_addr *addr) {
if (dns_cache[i].hostname[0]=='\0') continue; /* empty */
if (strcmp(hostname, dns_cache[i].hostname) == 0) { /* match */
memcpy(addr, &dns_cache[i].addr, sizeof(struct in_addr));
DEBUGC(DBCLASS_DNS, "from cache: %s -> %s",
DEBUGC(DBCLASS_DNS, "DNS lookup - from cache: %s -> %s",
hostname, inet_ntoa(*addr));
return 0;
}
@ -202,7 +202,8 @@ int get_ip_by_host(char *hostname, struct in_addr *addr) {
}
memcpy(addr, hostentry->h_addr, sizeof(struct in_addr));
DEBUGC(DBCLASS_DNS, "resolved: %s -> %s", hostname, inet_ntoa(*addr));
DEBUGC(DBCLASS_DNS, "DNS lookup - resolved: %s -> %s",
hostname, inet_ntoa(*addr));
/*
* remember the result in the cache
@ -221,7 +222,7 @@ int get_ip_by_host(char *hostname, struct in_addr *addr) {
if (i >= DNS_CACHE_SIZE) i=j;
/* store in cache */
DEBUGC(DBCLASS_DNS, "store into DNS cache, entry %i)", i);
DEBUGC(DBCLASS_DNS, "DNS lookup - store into cache, entry %i)", i);
memset(&dns_cache[i], 0, sizeof(dns_cache[0]));
strncpy(dns_cache[i].hostname, hostname, HOSTNAME_SIZE);
time(&dns_cache[i].timestamp);
@ -232,11 +233,14 @@ int get_ip_by_host(char *hostname, struct in_addr *addr) {
/*
* compares two URLs
* returns 0 if equal, >0 if non equal, <0 if error
* returns 0 if equal, <0 if non equal, >0 if error
* (by now, only hostname and username are compared)
*/
int compare_url(url_t *url1, url_t *url2) {
int sts;
if ((url1 == NULL) || (url2 == NULL)) return 1;
/* comparison of hosts should be based on IP addresses, no? */
DEBUGC(DBCLASS_BABBLE, "comparng urls: %s@%s -> %s@%s",
url1->username, url1->host, url2->username, url2->host);