From bbfdfe25fe7deac73b8e9461085b345e7e57f095 Mon Sep 17 00:00:00 2001 From: Thomas Ries Date: Sun, 25 Aug 2002 21:38:41 +0000 Subject: [PATCH] *** empty log message *** --- AUTHORS | 4 ++ ChangeLog | 2 +- Makefile.in | 2 +- README | 16 +++---- TODO | 5 ++- src/proxy.c | 41 +++++------------- src/register.c | 3 +- src/siproxd.c | 4 +- src/siproxd.h | 22 ++++++---- src/utils.c | 113 ++++++++++++++++++++++++++++++++++++++++++++----- 10 files changed, 144 insertions(+), 68 deletions(-) diff --git a/AUTHORS b/AUTHORS index e69de29..597128e 100644 --- a/AUTHORS +++ b/AUTHORS @@ -0,0 +1,4 @@ +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 diff --git a/ChangeLog b/ChangeLog index 3bd34a3..2d4827e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,7 @@ 0.1.1 ===== -- 24-Aug-2002: Imlemented handling of a config file, +- 24-Aug-2002: Imlemented support for a config file, obsoletes siproxd_conf.h 0.1.0 diff --git a/Makefile.in b/Makefile.in index e0b936e..6743ee5 100644 --- a/Makefile.in +++ b/Makefile.in @@ -87,7 +87,7 @@ VERSION = @VERSION@ SUBDIRS = src doc -EXTRA_DIST = TODO +EXTRA_DIST = TODO RELNOTES ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 mkinstalldirs = $(SHELL) $(top_srcdir)/scripts/mkinstalldirs CONFIG_HEADER = config.h diff --git a/README b/README index 817b9cd..e5020fa 100644 --- a/README +++ b/README @@ -1,5 +1,7 @@ + + Be warned, this (and all the other) documentantation is far from -complete. This is just *very* preliminary pre-alpha release. Don't +complete. This is just a *very* preliminary pre-alpha release. Don't expect anything! @@ -12,7 +14,7 @@ connections possible via an masquerading firewall. It allows SIP clients (like kphone, linphone) to work behind an IP masquerading firewall or router. -SIP (Session Initiation Protocol, RFC2543) is used by Softphones +SIP (Session Initiation Protocol, RFC3261) is used by Softphones (Voice over IP) to initiate communication. By itself, SIP does not work via masquerading firewalls as the transfered data contains IP addresses and port numbers. @@ -46,11 +48,6 @@ How to get started: have dynamic IP addresses, then you might want to use a hostname here and use a dynamic DNS service like dyndns.org) - !! ACTUALLY, THIS IS NOT YET TRUE. The configuration of INBOUND - and OUTBOUND host ist still a compile time issue... - Edit the file siproxd_conf.h accordingly. Support for the - config file will be very next. - What siproxd does: ================= @@ -95,4 +92,7 @@ after I made the above change. Contacts: ========= -Thomas Ries +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 diff --git a/TODO b/TODO index a7b1b22..d63741e 100644 --- a/TODO +++ b/TODO @@ -1,8 +1,6 @@ TODOs, in anarchistic order: ============================ -- support for configuration file! - - 2.2.x kernels: make use of the portfw.so (ipmasqadm package) to create forwarding @@ -12,3 +10,6 @@ TODOs, in anarchistic order: - 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 diff --git a/src/proxy.c b/src/proxy.c index 6b7216d..394971d 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -79,16 +79,9 @@ int proxy_request (sip_t *request) { type = 0; for (i=0; iIP) */ /* incomming request ('to' == 'masq') */ - if ((strcmp(request->to->url->username, - urlmap[i].masq_url->username)==0) && - (strcmp(request->to->url->host, - urlmap[i].masq_url->host)==0)) { + if (compare_url(request->to->url, urlmap[i].masq_url)==0) { type=REQTYP_INCOMMING; DEBUGC(DBCLASS_PROXY,"incomming request from %s@%s from outbound", request->from->url->username, @@ -97,10 +90,7 @@ int proxy_request (sip_t *request) { } /* outgoing request ('contact' == 'true') */ - if ((strcmp(contact->url->username, - urlmap[i].true_url->username)==0) && - (strcmp(contact->url->host, - urlmap[i].true_url->host)==0)) { + 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, @@ -120,7 +110,8 @@ int proxy_request (sip_t *request) { case REQTYP_INCOMMING: /* rewrite request URI to point to the real host */ /* i still holds the valid index into the URLMAP table */ - /* THIS IS UGLY!!! I dont like it &&&&&&*/ + + /* THIS IS UGLY!!! I dont like it */ DEBUGC(DBCLASS_PROXY,"rewriting incomming Request URI"); url=msg_geturi(request); free(url->host);url->host=NULL; @@ -160,19 +151,13 @@ int proxy_request (sip_t *request) { /* get target address from request URL */ url=msg_geturi(request); -#if EXP1 -/* &&&& linphone 0.9.0pre4 +#ifdef HACK1 +/* linphone-0.9.0pre4 take To address and place it into URI (at least the host part) - Linphone 0.9.0pre4 puts the proxy host in the request URI + Linphone-0.9.0pre4 puts the proxy host in the request URI if OUTBOUNT proxy is activated! - This is only a hack to recreate the proper final request URI. - see linphone, osipdialog.c line 1172 - if (call_leg->peer == NULL) - url_2char (call_leg->to->url, &tmp); - else - url_2char (call_leg->peer->url, &tmp); - url_parse (sipmsg->strtline->rquri, tmp); <<<<---- + This issue has been fixed in 0.9.1pre1 */ { header_t *header_ua; @@ -259,10 +244,7 @@ int proxy_response (sip_t *response) { /* incomming response ('from' == 'masq') */ - if ((strcmp(response->from->url->username, - urlmap[i].masq_url->username)==0) && - (strcmp(response->from->url->host, - urlmap[i].masq_url->host)==0)) { + if (compare_url(response->from->url, urlmap[i].masq_url)==0) { type=RESTYP_INCOMMING; DEBUGC(DBCLASS_PROXY,"incomming response for %s@%s from outbound", response->from->url->username, @@ -271,10 +253,7 @@ int proxy_response (sip_t *response) { } /* outgoing response ('to' == 'masq') */ - if ((strcmp(response->to->url->username, - urlmap[i].masq_url->username)==0) && - (strcmp(response->to->url->host, - urlmap[i].masq_url->host)==0)) { + if (compare_url(response->to->url, urlmap[i].masq_url)==0) { type=RESTYP_OUTGOING; DEBUGC(DBCLASS_PROXY,"outgoing response for %s@%s from inbound", response->from->url->username, diff --git a/src/register.c b/src/register.c index 6d90566..d398462 100644 --- a/src/register.c +++ b/src/register.c @@ -109,8 +109,7 @@ int register_client(sip_t *my_msg) { url2_to=urlmap[i].masq_url; url2_contact=urlmap[i].true_url; - if ( (strcmp(url1_to->username, url2_to->username )==0) && - (strcmp(url1_to->host, url2_to->host )==0) && + if ( (compare_url(url1_to, url2_to)==0) && (strcmp(url1_contact->username, url2_contact->username)==0) && (strcmp(url1_contact->host, url2_contact->host )==0) ) { DEBUGC(DBCLASS_REG, "found entry for %s@%s at slot=%i, exp=%li", diff --git a/src/siproxd.c b/src/siproxd.c index 9f6e00e..df14b36 100644 --- a/src/siproxd.c +++ b/src/siproxd.c @@ -120,7 +120,7 @@ int main (int argc, char *argv[]) /* listen for incomming messages */ sipsock_listen(); -/*&&&& daemonize !! */ + /* daemonize if requested to */ if (configuration.daemonize) { DEBUGC(DBCLASS_CONFIG,"daemonizing"); if (fork()!=0) exit(0); @@ -129,8 +129,6 @@ int main (int argc, char *argv[]) } - - /* * Main loop */ diff --git a/src/siproxd.h b/src/siproxd.h index 1c503cb..aad48d4 100644 --- a/src/siproxd.h +++ b/src/siproxd.h @@ -45,6 +45,7 @@ sip_t * msg_make_template_reply (sip_t * request, int code); int check_vialoop (sip_t *my_msg); int is_via_local (via_t *via); int get_ip_by_host(char *hostname, struct in_addr *addr); +int compare_url(url_t *url1, url_t *url2); /* config.c */ int read_config(char *name, int search); @@ -77,20 +78,23 @@ struct siproxd_config { /* * some constant definitions */ -#define URLMAP_SIZE 128 // size of URL mapping table -#define BUFFER_SIZE 1024 // input buffer for read from socket -#define URL_STRING_SIZE 128 // - #define SIP_PORT 5060 +#define URLMAP_SIZE 128 // size of URL mapping table +#define BUFFER_SIZE 1024 // input buffer for read from socket +#define URL_STRING_SIZE 128 // max size of an URL/URI string +#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 HOSTNAME_SIZE 32 // max string length of a hostname + /* - * optionasl hacks + * optional hacks */ -#define EXP1 1 /* HACK linphone0.9.0pre4 */ +#define HACK1 /* linphone-0.9.0pre4: broken RQ URI hack */ /* 14-Aug-2002 TR Linphone puts in the proxies hostname in the request URI when OUTBOUND proxy is activated. But ONLY the hostname. Username and - Port (!!!) are kept from the SIP address givven by the user. - This is a BUG in my eyes. Linphone must send the datagrap to - the Proxy, but have the final receiver in the request URI ! + Port (!!!) are kept from the SIP address given by the user. + This issue is fixed in linphone-0.9.1pre1 */ diff --git a/src/utils.c b/src/utils.c index 451c089..6665171 100644 --- a/src/utils.c +++ b/src/utils.c @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -41,6 +42,9 @@ extern struct siproxd_config configuration; extern int h_errno; +/* + * create a reply template from an given SIP request + */ sip_t *msg_make_template_reply (sip_t * request, int code) { sip_t *response; char *tmp; @@ -48,8 +52,8 @@ sip_t *msg_make_template_reply (sip_t * request, int code) { msg_init (&response); msg_setversion (response, sgetcopy ("SIP/2.0")); - tmp = malloc(5); - snprintf (tmp, 5, "%i", code); + tmp = malloc(STATUSCODE_SIZE); + snprintf (tmp, STATUSCODE_SIZE, "%i", code); msg_setstatuscode (response, tmp); msg_setreasonphrase (response, msg_getreason (code)); @@ -76,6 +80,11 @@ sip_t *msg_make_template_reply (sip_t * request, int code) { } +/* + * check for a via loop. + * It checks for the presense of a via entry that holds one of + * my IP addresses and is *not* the topmost via. + */ int check_vialoop (sip_t *my_msg) { int sts; int pos; @@ -95,6 +104,10 @@ int check_vialoop (sip_t *my_msg) { } +/* + * check if a given via_t is local. I.e. its address is owned + * by my inbound or outbound interface + */ int is_via_local (via_t *via) { int sts; struct in_addr addr_via, addr_myself; @@ -109,10 +122,6 @@ int is_via_local (via_t *via) { get_ip_by_host(via->host, &addr_via); } -/* make this more optimized!! -do the lookup at the beginning and then compare against all -the via entries ! -*/ sts=0; for (i=0; ; i++) { ptr=my_hostnames[i]; @@ -131,11 +140,52 @@ the via entries ! return sts; } -int get_ip_by_host(char *hostname, struct in_addr *addr) { - struct hostent *hostentry; -/* &&&& bahh, figure out a way to make this stuff non-blocking*/ -/* an asynchronous name-resolving might be neat */ +/* + * resolve a hostname and return in_addr + * handles its own little DNS cache. + */ +int get_ip_by_host(char *hostname, struct in_addr *addr) { + int i, j; + time_t t; + struct hostent *hostentry; + static struct { + time_t timestamp; + struct in_addr addr; + char hostname[HOSTNAME_SIZE]; + } dns_cache[DNS_CACHE_SIZE]; + static int cache_initialized=0; + + /* first time: initialize DNS cache */ + if (cache_initialized == 0) { + DEBUGC(DBCLASS_DNS, "initializing DNS cache (%i entries)", DNS_CACHE_SIZE); + memset(dns_cache, 0, sizeof(dns_cache)); + cache_initialized=1; + } + + time(&t); + /* clean expired entries */ + for (i=0; i %s", + hostname, inet_ntoa(*addr)); + return 0; + } + } + + /* did not find it in cache, so I have to resolve it */ hostentry=gethostbyname(hostname); if (hostentry==NULL) { @@ -144,9 +194,50 @@ int get_ip_by_host(char *hostname, struct in_addr *addr) { } memcpy(addr, hostentry->h_addr, sizeof(struct in_addr)); - DEBUGC(DBCLASS_BABBLE, "resolved: %s -> %s", hostname, inet_ntoa(*addr)); + DEBUGC(DBCLASS_DNS, "resolved: %s -> %s", hostname, inet_ntoa(*addr)); + + /* + * remember the result in the cache + */ + /* find an empty slot */ + j=0; + for (i=0; i= DNS_CACHE_SIZE) i=j; + + /* store in cache */ + DEBUGC(DBCLASS_DNS, "store into DNS 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); + memcpy(&dns_cache[i].addr, addr, sizeof(struct in_addr)); return 0; } +/* + * compares two URLs + * 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; + /* 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); + if ((strcmp(url1->username, url2->username)==0) && + (strcmp(url1->host, url2->host)==0)) { + sts = 0; + } else { + sts = -1; + } + return sts; +}