*** empty log message ***

This commit is contained in:
Thomas Ries 2002-08-25 21:38:41 +00:00
parent 8bcf9e6a2c
commit bbfdfe25fe
10 changed files with 144 additions and 68 deletions

View File

@ -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

View File

@ -1,7 +1,7 @@
0.1.1 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 obsoletes siproxd_conf.h
0.1.0 0.1.0

View File

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

16
README
View File

@ -1,5 +1,7 @@
Be warned, this (and all the other) documentantation is far from 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! expect anything!
@ -12,7 +14,7 @@ connections possible via an masquerading firewall.
It allows SIP clients (like kphone, linphone) to work behind It allows SIP clients (like kphone, linphone) to work behind
an IP masquerading firewall or router. 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 (Voice over IP) to initiate communication. By itself, SIP does not
work via masquerading firewalls as the transfered data contains work via masquerading firewalls as the transfered data contains
IP addresses and port numbers. 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 have dynamic IP addresses, then you might want to use a hostname
here and use a dynamic DNS service like dyndns.org) 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: What siproxd does:
================= =================
@ -95,4 +92,7 @@ after I made the above change.
Contacts: Contacts:
========= =========
Thomas Ries <tries@gmx.net> 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

5
TODO
View File

@ -1,8 +1,6 @@
TODOs, in anarchistic order: TODOs, in anarchistic order:
============================ ============================
- support for configuration file!
- 2.2.x kernels: - 2.2.x kernels:
make use of the portfw.so (ipmasqadm package) to create forwarding 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 - Is there a possibility to open up an masquerading tunnel by
a userspace program on the firewall? a userspace program on the firewall?
- logging via syslog if running in daemon mode
- get_ip_by_host: reduce DNS timeouts

View File

@ -79,16 +79,9 @@ int proxy_request (sip_t *request) {
type = 0; type = 0;
for (i=0; i<URLMAP_SIZE; i++) { for (i=0; i<URLMAP_SIZE; i++) {
if (urlmap[i].active == 0) continue; if (urlmap[i].active == 0) continue;
/*&&&& comparison of hosts should be based on IP addresses
as it looks (at least RQ URI)...*/
/*&&&& make this comparison into a subroutine - it is used a LOT !
also make the HOST comparison more flexible (name<->IP) */
/* incomming request ('to' == 'masq') */ /* incomming request ('to' == 'masq') */
if ((strcmp(request->to->url->username, if (compare_url(request->to->url, urlmap[i].masq_url)==0) {
urlmap[i].masq_url->username)==0) &&
(strcmp(request->to->url->host,
urlmap[i].masq_url->host)==0)) {
type=REQTYP_INCOMMING; type=REQTYP_INCOMMING;
DEBUGC(DBCLASS_PROXY,"incomming request from %s@%s from outbound", DEBUGC(DBCLASS_PROXY,"incomming request from %s@%s from outbound",
request->from->url->username, request->from->url->username,
@ -97,10 +90,7 @@ int proxy_request (sip_t *request) {
} }
/* outgoing request ('contact' == 'true') */ /* outgoing request ('contact' == 'true') */
if ((strcmp(contact->url->username, if (compare_url(contact->url, urlmap[i].true_url)==0) {
urlmap[i].true_url->username)==0) &&
(strcmp(contact->url->host,
urlmap[i].true_url->host)==0)) {
type=REQTYP_OUTGOING; type=REQTYP_OUTGOING;
DEBUGC(DBCLASS_PROXY,"outgoing request from %s@%s from inbound", DEBUGC(DBCLASS_PROXY,"outgoing request from %s@%s from inbound",
request->from->url->username, request->from->url->username,
@ -120,7 +110,8 @@ int proxy_request (sip_t *request) {
case REQTYP_INCOMMING: case REQTYP_INCOMMING:
/* rewrite request URI to point to the real host */ /* rewrite request URI to point to the real host */
/* i still holds the valid index into the URLMAP table */ /* 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"); DEBUGC(DBCLASS_PROXY,"rewriting incomming Request URI");
url=msg_geturi(request); url=msg_geturi(request);
free(url->host);url->host=NULL; free(url->host);url->host=NULL;
@ -160,19 +151,13 @@ int proxy_request (sip_t *request) {
/* get target address from request URL */ /* get target address from request URL */
url=msg_geturi(request); url=msg_geturi(request);
#if EXP1 #ifdef HACK1
/* &&&& linphone 0.9.0pre4 /* linphone-0.9.0pre4
take To address and place it into URI (at least the host part) 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! if OUTBOUNT proxy is activated!
This is only a hack to recreate the proper final request URI. This is only a hack to recreate the proper final request URI.
see linphone, osipdialog.c line 1172 This issue has been fixed in 0.9.1pre1
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); <<<<----
*/ */
{ {
header_t *header_ua; header_t *header_ua;
@ -259,10 +244,7 @@ int proxy_response (sip_t *response) {
/* incomming response ('from' == 'masq') */ /* incomming response ('from' == 'masq') */
if ((strcmp(response->from->url->username, if (compare_url(response->from->url, urlmap[i].masq_url)==0) {
urlmap[i].masq_url->username)==0) &&
(strcmp(response->from->url->host,
urlmap[i].masq_url->host)==0)) {
type=RESTYP_INCOMMING; type=RESTYP_INCOMMING;
DEBUGC(DBCLASS_PROXY,"incomming response for %s@%s from outbound", DEBUGC(DBCLASS_PROXY,"incomming response for %s@%s from outbound",
response->from->url->username, response->from->url->username,
@ -271,10 +253,7 @@ int proxy_response (sip_t *response) {
} }
/* outgoing response ('to' == 'masq') */ /* outgoing response ('to' == 'masq') */
if ((strcmp(response->to->url->username, if (compare_url(response->to->url, urlmap[i].masq_url)==0) {
urlmap[i].masq_url->username)==0) &&
(strcmp(response->to->url->host,
urlmap[i].masq_url->host)==0)) {
type=RESTYP_OUTGOING; type=RESTYP_OUTGOING;
DEBUGC(DBCLASS_PROXY,"outgoing response for %s@%s from inbound", DEBUGC(DBCLASS_PROXY,"outgoing response for %s@%s from inbound",
response->from->url->username, response->from->url->username,

View File

@ -109,8 +109,7 @@ int register_client(sip_t *my_msg) {
url2_to=urlmap[i].masq_url; url2_to=urlmap[i].masq_url;
url2_contact=urlmap[i].true_url; url2_contact=urlmap[i].true_url;
if ( (strcmp(url1_to->username, url2_to->username )==0) && if ( (compare_url(url1_to, url2_to)==0) &&
(strcmp(url1_to->host, url2_to->host )==0) &&
(strcmp(url1_contact->username, url2_contact->username)==0) && (strcmp(url1_contact->username, url2_contact->username)==0) &&
(strcmp(url1_contact->host, url2_contact->host )==0) ) { (strcmp(url1_contact->host, url2_contact->host )==0) ) {
DEBUGC(DBCLASS_REG, "found entry for %s@%s at slot=%i, exp=%li", DEBUGC(DBCLASS_REG, "found entry for %s@%s at slot=%i, exp=%li",

View File

@ -120,7 +120,7 @@ int main (int argc, char *argv[])
/* listen for incomming messages */ /* listen for incomming messages */
sipsock_listen(); sipsock_listen();
/*&&&& daemonize !! */ /* daemonize if requested to */
if (configuration.daemonize) { if (configuration.daemonize) {
DEBUGC(DBCLASS_CONFIG,"daemonizing"); DEBUGC(DBCLASS_CONFIG,"daemonizing");
if (fork()!=0) exit(0); if (fork()!=0) exit(0);
@ -129,8 +129,6 @@ int main (int argc, char *argv[])
} }
/* /*
* Main loop * Main loop
*/ */

View File

@ -45,6 +45,7 @@ sip_t * msg_make_template_reply (sip_t * request, int code);
int check_vialoop (sip_t *my_msg); int check_vialoop (sip_t *my_msg);
int is_via_local (via_t *via); int is_via_local (via_t *via);
int get_ip_by_host(char *hostname, struct in_addr *addr); int get_ip_by_host(char *hostname, struct in_addr *addr);
int compare_url(url_t *url1, url_t *url2);
/* config.c */ /* config.c */
int read_config(char *name, int search); int read_config(char *name, int search);
@ -77,20 +78,23 @@ struct siproxd_config {
/* /*
* some constant definitions * 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 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 /* 14-Aug-2002 TR
Linphone puts in the proxies hostname in the request URI when Linphone puts in the proxies hostname in the request URI when
OUTBOUND proxy is activated. But ONLY the hostname. Username and OUTBOUND proxy is activated. But ONLY the hostname. Username and
Port (!!!) are kept from the SIP address givven by the user. Port (!!!) are kept from the SIP address given by the user.
This is a BUG in my eyes. Linphone must send the datagrap to This issue is fixed in linphone-0.9.1pre1
the Proxy, but have the final receiver in the request URI !
*/ */

View File

@ -21,6 +21,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <time.h>
#include <signal.h> #include <signal.h>
#include <string.h> #include <string.h>
#include <netinet/in.h> #include <netinet/in.h>
@ -41,6 +42,9 @@ extern struct siproxd_config configuration;
extern int h_errno; 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 *msg_make_template_reply (sip_t * request, int code) {
sip_t *response; sip_t *response;
char *tmp; char *tmp;
@ -48,8 +52,8 @@ sip_t *msg_make_template_reply (sip_t * request, int code) {
msg_init (&response); msg_init (&response);
msg_setversion (response, sgetcopy ("SIP/2.0")); msg_setversion (response, sgetcopy ("SIP/2.0"));
tmp = malloc(5); tmp = malloc(STATUSCODE_SIZE);
snprintf (tmp, 5, "%i", code); snprintf (tmp, STATUSCODE_SIZE, "%i", code);
msg_setstatuscode (response, tmp); msg_setstatuscode (response, tmp);
msg_setreasonphrase (response, msg_getreason (code)); 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 check_vialoop (sip_t *my_msg) {
int sts; int sts;
int pos; 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 is_via_local (via_t *via) {
int sts; int sts;
struct in_addr addr_via, addr_myself; 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); 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; sts=0;
for (i=0; ; i++) { for (i=0; ; i++) {
ptr=my_hostnames[i]; ptr=my_hostnames[i];
@ -131,11 +140,52 @@ the via entries !
return sts; 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<DNS_CACHE_SIZE; i++) {
if ( (dns_cache[i].timestamp+DNS_MAX_AGE) < t ) {
DEBUGC(DBCLASS_DNS, "cleaning DNS cache, entry %i)", i);
memset (&dns_cache[i], 0, sizeof(dns_cache[0]));
}
}
/*
* search requested entry in cache
*/
for (i=0; i<DNS_CACHE_SIZE; i++) {
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",
hostname, inet_ntoa(*addr));
return 0;
}
}
/* did not find it in cache, so I have to resolve it */
hostentry=gethostbyname(hostname); hostentry=gethostbyname(hostname);
if (hostentry==NULL) { 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)); 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++) {
if (dns_cache[i].hostname[0]=='\0') break;
if (dns_cache[i].timestamp < t) {
/* remember oldest entry */
t=dns_cache[i].timestamp;
j=i;
}
}
/* if no empty slot found, take oldest one */
if (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; 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;
}