From e924096f62655d711cd2d114a8d1ef0fecbb593b Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Fri, 5 Jan 2001 23:53:53 +0000 Subject: [PATCH] - Let user choose whether keys are in the config files or separate - Use AVL trees instead of RBL trees - Fixed a lot of annoying subtle bugs! Thanks to gdb... --- src/conf.c | 33 +++++++------ src/conf.h | 4 +- src/connection.c | 46 +++++++++--------- src/connection.h | 10 ++-- src/meta.c | 9 ++-- src/net.c | 72 +++++++++++++++++----------- src/process.c | 4 +- src/protocol.c | 61 +++++++++++++----------- src/route.c | 119 +++++++++++++++++++++++++++++------------------ src/subnet.c | 47 +++++++++---------- src/subnet.h | 8 ++-- src/tincd.c | 12 +++-- 12 files changed, 245 insertions(+), 180 deletions(-) diff --git a/src/conf.c b/src/conf.c index 3edcb302..5aaa22a0 100644 --- a/src/conf.c +++ b/src/conf.c @@ -19,12 +19,11 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: conf.c,v 1.9.4.35 2000/12/22 21:34:20 guus Exp $ + $Id: conf.c,v 1.9.4.36 2001/01/05 23:53:49 guus Exp $ */ #include "config.h" -#include #include #include #include @@ -35,6 +34,7 @@ #include #include #include +#include #include #include /* for cp */ @@ -311,7 +311,7 @@ cp x = read_config_file(&config, fname); if(x == -1) /* System error */ { - fprintf(stderr, _("Failed to read `%s': %m\n"), + syslog(LOG_ERR, _("Failed to read `%s': %m"), fname); } free(fname); @@ -358,7 +358,7 @@ int isadir(const char* f) if(stat(f, &s) < 0) { - fprintf(stderr, _("Couldn't stat `%s': %m\n"), + syslog(LOG_ERR, _("Couldn't stat `%s': %m"), f); return -1; } @@ -371,24 +371,29 @@ int is_safe_path(const char *file) char *p; struct stat s; + if(*file != '/') + { + syslog(LOG_ERR, _("`%s' is not an absolute path"), file); + return 0; + } + p = strrchr(file, '/'); - assert(p); /* p has to contain a / */ *p = '\0'; if(stat(file, &s) < 0) { - fprintf(stderr, _("Couldn't stat `%s': %m\n"), + syslog(LOG_ERR, _("Couldn't stat `%s': %m"), file); return 0; } if(s.st_uid != geteuid()) { - fprintf(stderr, _("`%s' is owned by UID %d instead of %d.\n"), + syslog(LOG_ERR, _("`%s' is owned by UID %d instead of %d"), file, s.st_uid, geteuid()); return 0; } if(S_ISLNK(s.st_mode)) { - fprintf(stderr, _("Warning: `%s' is a symlink\n"), + syslog(LOG_WARNING, _("Warning: `%s' is a symlink"), file); /* fixme: read the symlink and start again */ } @@ -396,7 +401,7 @@ int is_safe_path(const char *file) *p = '/'; if(stat(file, &s) < 0 && errno != ENOENT) { - fprintf(stderr, _("Couldn't stat `%s': %m\n"), + syslog(LOG_ERR, _("Couldn't stat `%s': %m"), file); return 0; } @@ -404,20 +409,20 @@ int is_safe_path(const char *file) return 1; if(s.st_uid != geteuid()) { - fprintf(stderr, _("`%s' is owned by UID %d instead of %d.\n"), + syslog(LOG_ERR, _("`%s' is owned by UID %d instead of %d"), file, s.st_uid, geteuid()); return 0; } if(S_ISLNK(s.st_mode)) { - fprintf(stderr, _("Warning: `%s' is a symlink\n"), + syslog(LOG_WARNING, _("Warning: `%s' is a symlink"), file); /* fixme: read the symlink and start again */ } if(s.st_mode & 0007) { /* Accessible by others */ - fprintf(stderr, _("`%s' has unsecure permissions.\n"), + syslog(LOG_ERR, _("`%s' has unsecure permissions"), file); return 0; } @@ -445,12 +450,14 @@ FILE *ask_and_safe_open(const char* filename, const char* what) /* Ask for a file and/or directory name. */ fprintf(stdout, _("Please enter a file to save %s to [%s]: "), what, filename); - fflush(stdout); /* Don't wait for a newline */ + fflush(stdout); + if((fn = readline(stdin, NULL, NULL)) == NULL) { fprintf(stderr, _("Error while reading stdin: %m\n")); return NULL; } + if(strlen(fn) == 0) /* User just pressed enter. */ fn = xstrdup(filename); diff --git a/src/conf.h b/src/conf.h index de527d25..00fbcb19 100644 --- a/src/conf.h +++ b/src/conf.h @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: conf.h,v 1.6.4.19 2000/12/22 21:34:20 guus Exp $ + $Id: conf.h,v 1.6.4.20 2001/01/05 23:53:49 guus Exp $ */ #ifndef __TINC_CONF_H__ @@ -63,7 +63,7 @@ typedef struct config_t { int argtype; union data { unsigned long val; - void *ptr; + char *ptr; ip_mask_t *ip; struct config_t *next; /* For nested configs! */ } data; diff --git a/src/connection.c b/src/connection.c index 7f48697d..59ff1201 100644 --- a/src/connection.c +++ b/src/connection.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: connection.c,v 1.1.2.6 2000/11/24 23:13:01 guus Exp $ + $Id: connection.c,v 1.1.2.7 2001/01/05 23:53:49 guus Exp $ */ #include "config.h" @@ -25,7 +25,7 @@ #include #include -#include +#include #include "net.h" /* Don't ask. */ #include "netutl.h" @@ -39,8 +39,10 @@ /* Root of the connection list */ -rbltree_t *connection_tree; -rbltree_t *id_tree; +avl_tree_t *connection_tree; +avl_tree_t *id_tree; + +/* Pointer to connection describing myself */ connection_t *myself = NULL; @@ -49,6 +51,7 @@ connection_t *myself = NULL; int connection_compare(connection_t *a, connection_t *b) { ipv4_t result; + result = a->address - b->address; if(result) return result; @@ -63,8 +66,8 @@ int id_compare(connection_t *a, connection_t *b) void init_connections(void) { - connection_tree = new_rbltree((rbl_compare_t)connection_compare, (rbl_action_t)free_connection); - id_tree = new_rbltree((rbl_compare_t)id_compare, NULL); + connection_tree = avl_alloc_tree((avl_compare_t)connection_compare, (avl_action_t)free_connection); + id_tree = avl_alloc_tree((avl_compare_t)id_compare, NULL); } /* Creation and deletion of connection elements */ @@ -73,7 +76,7 @@ connection_t *new_connection(void) { connection_t *p = (connection_t *)xmalloc_and_zero(sizeof(*p)); cp - p->subnet_tree = new_rbltree((rbl_compare_t)subnet_compare, NULL); + p->subnet_tree = avl_alloc_tree((avl_compare_t)subnet_compare, NULL); cp return p; } @@ -106,12 +109,13 @@ cp */ void prune_connection_tree(void) { - rbl_t *rbl; + avl_node_t *node, *next; connection_t *cl; cp - RBL_FOREACH(connection_tree, rbl) + for(node = connection_tree->head; node; node = next) { - cl = (connection_t *) rbl->data; + next = node->next; + cl = (connection_t *)node->data; if(cl->status.remove) connection_del(cl); } @@ -124,8 +128,8 @@ cp void destroy_connection_tree(void) { cp - rbl_delete_rbltree(id_tree); - rbl_delete_rbltree(connection_tree); + avl_delete_tree(id_tree); + avl_delete_tree(connection_tree); cp } @@ -134,22 +138,22 @@ cp void connection_add(connection_t *cl) { cp - rbl_insert(connection_tree, cl); + avl_insert(connection_tree, cl); cp } void id_add(connection_t *cl) { cp - rbl_insert(id_tree, cl); + avl_insert(id_tree, cl); cp } void connection_del(connection_t *cl) { cp - rbl_delete(id_tree, cl); - rbl_delete(connection_tree, cl); + avl_delete(id_tree, cl); + avl_delete(connection_tree, cl); cp } @@ -162,7 +166,7 @@ cp cl.address = address; cl.port = port; - return rbl_search(connection_tree, &cl); + return avl_search(connection_tree, &cl); } connection_t *lookup_id(char *name) @@ -170,7 +174,7 @@ connection_t *lookup_id(char *name) connection_t cl, *p; cp cl.name = name; - p = rbl_search(id_tree, &cl); + p = avl_search(id_tree, &cl); if(p && p->status.active) return p; else @@ -181,7 +185,7 @@ cp void dump_connection_list(void) { - rbl_t *rbl; + avl_node_t *node; connection_t *cl; cp syslog(LOG_DEBUG, _("Connection list:")); @@ -190,9 +194,9 @@ cp myself->name, myself->hostname, myself->port, myself->flags, myself->socket, myself->meta_socket, myself->status); - RBL_FOREACH(connection_tree, rbl) + for(node = connection_tree->head; node; node = node->next) { - cl = (connection_t *)rbl->data; + cl = (connection_t *)node->data; syslog(LOG_DEBUG, _(" %s at %s port %hd flags %d sockets %d, %d status %04x"), cl->name, cl->hostname, cl->port, cl->flags, cl->socket, cl->meta_socket, cl->status); diff --git a/src/connection.h b/src/connection.h index e7397810..195cb1bb 100644 --- a/src/connection.h +++ b/src/connection.h @@ -17,13 +17,13 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: connection.h,v 1.1.2.3 2000/11/22 22:18:03 guus Exp $ + $Id: connection.h,v 1.1.2.4 2001/01/05 23:53:49 guus Exp $ */ #ifndef __TINC_CONNECTION_H__ #define __TINC_CONNECTION_H__ -#include +#include #include "config.h" @@ -66,8 +66,8 @@ typedef struct connection_t { char *name; /* name of this connection */ ipv4_t address; /* his real (internet) ip */ char *hostname; /* the hostname of its real ip */ - short unsigned int port; /* his portnumber */ int protocol_version; /* used protocol */ + short unsigned int port; /* port number for UDP traffic */ long unsigned int options; /* options turned on for this connection */ int flags; /* his flags */ @@ -100,12 +100,12 @@ typedef struct connection_t { struct connection_t *nexthop; /* nearest meta-hop in this direction */ - rbltree_t *subnet_tree; /* Pointer to a tree of subnets belonging to this connection */ + avl_tree_t *subnet_tree; /* Pointer to a tree of subnets belonging to this connection */ struct config_t *config; /* Pointer to configuration tree belonging to this host */ } connection_t; -extern rbltree_t *connection_tree; +extern avl_tree_t *connection_tree; extern connection_t *myself; extern void init_connections(void); diff --git a/src/meta.c b/src/meta.c index 289d0b87..14a3c1d0 100644 --- a/src/meta.c +++ b/src/meta.c @@ -17,11 +17,12 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: meta.c,v 1.1.2.12 2000/11/20 19:12:12 guus Exp $ + $Id: meta.c,v 1.1.2.13 2001/01/05 23:53:49 guus Exp $ */ #include "config.h" #include +#include #include #include @@ -74,12 +75,12 @@ cp void broadcast_meta(connection_t *cl, char *buffer, int length) { - rbl_t *rbl; + avl_node_t *node; connection_t *p; cp - RBL_FOREACH(connection_tree, rbl) + for(node = connection_tree->head; node; node = node->next) { - p = (connection_t *)rbl->data; + p = (connection_t *)node->data; if(p != cl && p->status.meta && p->status.active) send_meta(p, buffer, length); } diff --git a/src/net.c b/src/net.c index cb32caba..a42ebce4 100644 --- a/src/net.c +++ b/src/net.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: net.c,v 1.35.4.88 2000/12/22 21:34:20 guus Exp $ + $Id: net.c,v 1.35.4.89 2001/01/05 23:53:49 guus Exp $ */ #include "config.h" @@ -71,6 +71,7 @@ #include #include +#include #include "conf.h" #include "connection.h" @@ -165,7 +166,7 @@ cp if(debug_lvl >= DEBUG_TRAFFIC) syslog(LOG_ERR, _("Writing packet of %d bytes to tap device"), - outpkt.len, outlen); + outpkt.len); /* Fix mac address */ @@ -320,7 +321,7 @@ int send_packet(ip_t to, vpn_packet_t *packet) connection_t *cl; subnet_t *subnet; cp - if((subnet = lookup_subnet_ipv4(to)) == NULL) + if((subnet = lookup_subnet_ipv4(&to)) == NULL) { if(debug_lvl >= DEBUG_TRAFFIC) { @@ -607,6 +608,19 @@ cp return -1; } + /* Bind first to get a fix on our source port */ + + a.sin_family = AF_INET; + a.sin_port = htons(0); + a.sin_addr.s_addr = htonl(INADDR_ANY); + + if(bind(cl->meta_socket, (struct sockaddr *)&a, sizeof(struct sockaddr))) + { + close(cl->meta_socket); + syslog(LOG_ERR, _("System call `%s' failed: %m"), "bind"); + return -1; + } + a.sin_family = AF_INET; a.sin_port = htons(cl->port); a.sin_addr.s_addr = htonl(cl->address); @@ -656,14 +670,14 @@ cp if(read_host_config(ncn)) { - syslog(LOG_ERR, _("Error reading host configuration file for %s")); + syslog(LOG_ERR, _("Error reading host configuration file for %s"), ncn->name); free_connection(ncn); return -1; } if(!(cfg = get_config_val(ncn->config, config_address))) { - syslog(LOG_ERR, _("No address specified for %s")); + syslog(LOG_ERR, _("No address specified for %s"), ncn->name); free_connection(ncn); return -1; } @@ -876,7 +890,7 @@ cp syslog(LOG_ERR, _("Unable to set up a listening UDP socket!")); return -1; } - +cp /* Generate packet encryption key */ myself->cipher_pkttype = EVP_bf_cfb(); @@ -892,9 +906,9 @@ cp keylifetime = cfg->data.val; keyexpires = time(NULL) + keylifetime; - +cp /* Activate ourselves */ - + myself->status.active = 1; syslog(LOG_NOTICE, _("Ready: listening on port %hd"), myself->port); @@ -991,12 +1005,12 @@ cp */ void close_network_connections(void) { - rbl_t *rbl; + avl_node_t *node; connection_t *p; cp - RBL_FOREACH(connection_tree, rbl) + for(node = connection_tree->head; node; node = node->next) { - p = (connection_t *)rbl->data; + p = (connection_t *)node->data; p->status.active = 0; terminate_connection(p); } @@ -1117,6 +1131,7 @@ cp p->name = unknown; p->address = ntohl(ci.sin_addr.s_addr); p->hostname = hostlookup(ci.sin_addr.s_addr); + p->port = htons(ci.sin_port); /* This one will be overwritten later */ p->meta_socket = sfd; p->status.meta = 1; p->buffer = xmalloc(MAXBUFSIZE); @@ -1137,16 +1152,16 @@ cp */ void build_fdset(fd_set *fs) { - rbl_t *rbl; + avl_node_t *node; connection_t *p; cp FD_ZERO(fs); FD_SET(myself->socket, fs); - RBL_FOREACH(connection_tree, rbl) + for(node = connection_tree->head; node; node = node->next) { - p = (connection_t *)rbl->data; + p = (connection_t *)node->data; if(p->status.meta) FD_SET(p->meta_socket, fs); } @@ -1192,7 +1207,7 @@ cp if(!cl) { - syslog(LOG_WARNING, _("Received UDP packets on port %d from unknown source %lx:%d"), myself->port, ntohl(from.sin_addr.s_addr), ntohs(from.sin_port)); + syslog(LOG_WARNING, _("Received UDP packets on port %hd from unknown source %x:%hd"), myself->port, ntohl(from.sin_addr.s_addr), ntohs(from.sin_port)); return 0; } @@ -1214,7 +1229,7 @@ void terminate_connection(connection_t *cl) { connection_t *p; subnet_t *subnet; - rbl_t *rbl; + avl_node_t *node, *next; cp if(cl->status.remove) return; @@ -1234,9 +1249,9 @@ cp (the connection that was dropped). */ if(cl->status.meta) - RBL_FOREACH(connection_tree, rbl) + for(node = connection_tree->head; node; node = node->next) { - p = (connection_t *)rbl->data; + p = (connection_t *)node->data; if(p->nexthop == cl && p != cl) terminate_connection(p); } @@ -1244,18 +1259,19 @@ cp /* Inform others of termination if it was still active */ if(cl->status.active) - RBL_FOREACH(connection_tree, rbl) + for(node = connection_tree->head; node; node = node->next) { - p = (connection_t *)rbl->data; + p = (connection_t *)node->data; if(p->status.meta && p->status.active && p!=cl) send_del_host(p, cl); /* Sounds like recursion, but p does not have a meta connection :) */ } /* Remove the associated subnets */ - RBL_FOREACH(cl->subnet_tree, rbl) + for(node = cl->subnet_tree->head; node; node = next) { - subnet = (subnet_t *)rbl->data; + next = node->next; + subnet = (subnet_t *)node->data; subnet_del(subnet); } @@ -1286,14 +1302,14 @@ cp void check_dead_connections(void) { time_t now; - rbl_t *rbl; + avl_node_t *node; connection_t *cl; cp now = time(NULL); - RBL_FOREACH(connection_tree, rbl) + for(node = connection_tree->head; node; node = node->next) { - cl = (connection_t *)rbl->data; + cl = (connection_t *)node->data; if(cl->status.active && cl->status.meta) { if(cl->last_ping_time + timeout < now) @@ -1352,14 +1368,14 @@ cp void check_network_activity(fd_set *f) { connection_t *p; - rbl_t *rbl; + avl_node_t *node; cp if(FD_ISSET(myself->socket, f)) handle_incoming_vpn_data(); - RBL_FOREACH(connection_tree, rbl) + for(node = connection_tree->head; node; node = node->next) { - p = (connection_t *)rbl->data; + p = (connection_t *)node->data; if(p->status.remove) return; diff --git a/src/process.c b/src/process.c index 695f1f7e..01ca31e1 100644 --- a/src/process.c +++ b/src/process.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: process.c,v 1.1.2.17 2000/11/28 08:59:27 zarq Exp $ + $Id: process.c,v 1.1.2.18 2001/01/05 23:53:51 guus Exp $ */ #include "config.h" @@ -159,6 +159,8 @@ cp /* If we succeeded in doing that, detach */ + closelog(); + if(do_detach) { if(daemon(0, 0) < 0) diff --git a/src/protocol.c b/src/protocol.c index 57814fdd..85a4047c 100644 --- a/src/protocol.c +++ b/src/protocol.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: protocol.c,v 1.28.4.70 2000/12/22 21:34:24 guus Exp $ + $Id: protocol.c,v 1.28.4.71 2001/01/05 23:53:51 guus Exp $ */ #include "config.h" @@ -34,6 +34,7 @@ #include #include +#include #include @@ -193,10 +194,10 @@ cp int id_h(connection_t *cl) { connection_t *old; - config_t const *cfg; + unsigned short int port; char name[MAX_STRING_SIZE]; cp - if(sscanf(cl->buffer, "%*d "MAX_STRING" %d %lx %hd", name, &cl->protocol_version, &cl->options, &cl->port) != 4) + if(sscanf(cl->buffer, "%*d "MAX_STRING" %d %lx %hd", name, &cl->protocol_version, &cl->options, &port) != 4) { syslog(LOG_ERR, _("Got bad ID from %s"), cl->hostname); return -1; @@ -253,6 +254,12 @@ cp id_add(cl); + /* And uhr... cl->port just changed so we have to unlink it from the connection tree and re-insert... */ + + avl_unlink(connection_tree, cl); + cl->port = port; + avl_insert(connection_tree, cl); + /* Read in the public key, so that we can send a challenge */ if(read_rsa_public_key(cl)) @@ -283,7 +290,7 @@ cp RAND_bytes(cl->hischallenge, len); cl->hischallenge[0] &= 0x7F; /* Somehow if the first byte is more than 0xD0 or something like that, decryption fails... */ - +cp if(debug_lvl >= DEBUG_SCARY_THINGS) { bin2hex(cl->hischallenge, buffer, len); @@ -304,7 +311,7 @@ cp bin2hex(buffer, buffer, len); buffer[len*2] = '\0'; - +cp /* Send the challenge */ cl->allow_request = CHAL_REPLY; @@ -580,7 +587,7 @@ int ack_h(connection_t *cl) { connection_t *old, *p; subnet_t *subnet; - rbl_t *rbl, *rbl2; + avl_node_t *node, *node2; cp /* Okay, before we active the connection, we check if there is another entry in the connection list with the same name. If so, it presumably is an @@ -614,16 +621,16 @@ cp /* Send him our subnets */ - RBL_FOREACH(myself->subnet_tree, rbl) + for(node = myself->subnet_tree->head; node; node = node->next) { - subnet = (subnet_t *)rbl->data; + subnet = (subnet_t *)node->data; send_add_subnet(cl, subnet); } /* And send him all the hosts and their subnets we know... */ - RBL_FOREACH(connection_tree, rbl) + for(node = connection_tree->head; node; node = node->next) { - p = (connection_t *)rbl->data; + p = (connection_t *)node->data; if(p != cl && p->status.active) { @@ -636,9 +643,9 @@ cp send_add_host(cl, p); - RBL_FOREACH(p->subnet_tree, rbl2) + for(node2 = p->subnet_tree->head; node2; node2 = node2->next) { - subnet = (subnet_t *)rbl2->data; + subnet = (subnet_t *)node2->data; send_add_subnet(cl, subnet); } } @@ -667,7 +674,7 @@ int add_subnet_h(connection_t *cl) char name[MAX_STRING_SIZE]; connection_t *owner, *p; subnet_t *subnet; - rbl_t *rbl; + avl_node_t *node; cp if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING, name, subnetstr) != 2) { @@ -716,9 +723,9 @@ cp /* Tell the rest */ - RBL_FOREACH(connection_tree, rbl) + for(node = connection_tree->head; node; node = node->next) { - p = (connection_t *)rbl->data; + p = (connection_t *)node->data; if(p->status.meta && p->status.active && p!= cl) send_add_subnet(p, subnet); } @@ -744,7 +751,7 @@ int del_subnet_h(connection_t *cl) char name[MAX_STRING_SIZE]; connection_t *owner, *p; subnet_t *subnet; - rbl_t *rbl; + avl_node_t *node; cp if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING, name, subnetstr) != 3) { @@ -795,9 +802,9 @@ cp /* Tell the rest */ - RBL_FOREACH(connection_tree, rbl) + for(node = connection_tree->head; node; node = node->next) { - p = (connection_t *)rbl->data; + p = (connection_t *)node->data; if(p->status.meta && p->status.active && p!= cl) send_del_subnet(p, subnet); } @@ -818,7 +825,7 @@ int add_host_h(connection_t *cl) { connection_t *old, *new, *p; char name[MAX_STRING_SIZE]; - rbl_t *rbl; + avl_node_t *node; cp new = new_connection(); @@ -881,9 +888,9 @@ cp /* Tell the rest about the new host */ - RBL_FOREACH(connection_tree, rbl) + for(node = connection_tree->head; node; node = node->next) { - p = (connection_t *)rbl->data; + p = (connection_t *)node->data; if(p->status.meta && p->status.active && p!=cl) send_add_host(p, new); } @@ -912,7 +919,7 @@ int del_host_h(connection_t *cl) port_t port; long int options; connection_t *old, *p; - rbl_t *rbl; + avl_node_t *node; cp if(sscanf(cl->buffer, "%*d "MAX_STRING" %lx:%d %lx", name, &address, &port, &options) != 4) { @@ -963,9 +970,9 @@ cp /* Tell the rest about the new host */ - RBL_FOREACH(connection_tree, rbl) + for(node = connection_tree->head; node; node = node->next) { - p = (connection_t *)rbl->data; + p = (connection_t *)node->data; if(p->status.meta && p->status.active && p!=cl) send_del_host(p, old); } @@ -1087,11 +1094,11 @@ cp int send_key_changed(connection_t *from, connection_t *cl) { connection_t *p; - rbl_t *rbl; + avl_node_t *node; cp - RBL_FOREACH(connection_tree, rbl) + for(node = connection_tree->head; node; node = node->next) { - p = (connection_t *)rbl->data; + p = (connection_t *)node->data; if(p != cl && p->status.meta && p->status.active) send_request(p, "%d %s", KEY_CHANGED, from->name); } diff --git a/src/route.c b/src/route.c index 46206654..8ff2e39c 100644 --- a/src/route.c +++ b/src/route.c @@ -17,87 +17,75 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: route.c,v 1.1.2.3 2000/11/20 19:12:17 guus Exp $ + $Id: route.c,v 1.1.2.4 2001/01/05 23:53:53 guus Exp $ */ #include "config.h" #include #include +#include #include "net.h" #include "connection.h" +#include "subnet.h" +#include "route.h" #include "system.h" -int routing_mode = 0; /* Will be used to determine if we route by MAC or by payload's protocol */ +int routing_mode = RMODE_ROUTER; /* Will be used to determine if we route by MAC or by payload's protocol */ -connection_t *route_packet(vpn_packet_t *packet) +connection_t *route_mac(connection_t *source, vpn_packet_t *packet) { - unsigned short type; + connection_t *oldsrc, *dst; + subnet_t *subnet; cp - type = ntohs(*((unsigned short*)(&packet.data[12]))) + /* Learn source address */ - if(routing_mode) + oldsrc = lookup_subnet_mac((mac_t *)(&packet->data[0]))->owner; + + if(!oldsrc) { - return route_mac(packet); + subnet = new_subnet(); + subnet->type = SUBNET_MAC; + memcpy(&subnet->net.mac.address, (mac_t *)(&packet->data[0]), sizeof(mac_t)); + subnet_add(source, subnet); } - switch(type) - { - case 0x0800: - return route_ipv4(packet); - case 0x86DD: - return route_ipv6(packet); -/* - case 0x8137: - return route_ipx(packet); - case 0x0806: - return route_arp(packet); -*/ - default: - if(debug_lvl >= DEBUG_TRAFFIC) - { - syslog(LOG_WARNING, _("Cannot route packet: unknown type %hx"), type); - } - return NULL; - } -} + /* FIXME: do ageing and roaming */ + + /* Lookup destination address */ + + dst = lookup_subnet_mac((mac_t *)(&packet->data[6]))->owner; -connection_t *route_mac(vpn_packet_t *packet) -{ - connection_t *cl; -cp - cl = lookup_subnet_mac((mac_t *)(&packet.data[6])); - if(!cl) + if(!dst) if(debug_lvl >= DEBUG_TRAFFIC) { syslog(LOG_WARNING, _("Cannot route packet: unknown destination address %x:%x:%x:%x:%x:%x"), - packet.data[6], - packet.data[7], - packet.data[8], - packet.data[9], - packet.data[10], - packet.data[11]); + packet->data[6], + packet->data[7], + packet->data[8], + packet->data[9], + packet->data[10], + packet->data[11]); } cp - return cl; + return dst; } - connection_t *route_ipv4(vpn_packet_t *packet) { ipv4_t dest; connection_t *cl; cp - dest = ntohl(*((unsigned long*)(&packet.data[30]); + dest = ntohl(*((unsigned long*)(&packet->data[30]))); - cl = lookup_subnet_ipv4(dest); + cl = lookup_subnet_ipv4(&dest)->owner; if(!cl) if(debug_lvl >= DEBUG_TRAFFIC) { syslog(LOG_WARNING, _("Cannot route packet: unknown destination address %d.%d.%d.%d"), - packet.data[30], packet.data[31], packet.data[32], packet.data[33]); + packet->data[30], packet->data[31], packet->data[32], packet->data[33]); } cp return cl; @@ -106,7 +94,48 @@ cp connection_t *route_ipv6(vpn_packet_t *packet) { cp - syslog(LOG_WARNING, _("Cannot route packet: IPv6 routing not implemented yet")); + if(debug_lvl > DEBUG_NOTHING) + { + syslog(LOG_WARNING, _("Cannot route packet: IPv6 routing not implemented yet")); + } cp return NULL; } + +connection_t *route_packet(connection_t *source, vpn_packet_t *packet) +{ + unsigned short int type; +cp + /* FIXME: multicast? */ + + switch(routing_mode) + { + case RMODE_HUB: + return broadcast; + + case RMODE_SWITCH: + return route_mac(source, packet); + + case RMODE_ROUTER: + type = ntohs(*((unsigned short*)(&packet->data[12]))); + switch(type) + { + case 0x0800: + return route_ipv4(packet); + case 0x86DD: + return route_ipv6(packet); + /* + case 0x8137: + return route_ipx(packet); + case 0x0806: + return route_arp(packet); + */ + default: + if(debug_lvl >= DEBUG_TRAFFIC) + { + syslog(LOG_WARNING, _("Cannot route packet: unknown type %hx"), type); + } + return NULL; + } + } +} diff --git a/src/subnet.c b/src/subnet.c index 574e7a06..28a203dc 100644 --- a/src/subnet.c +++ b/src/subnet.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: subnet.c,v 1.1.2.15 2000/11/24 23:13:06 guus Exp $ + $Id: subnet.c,v 1.1.2.16 2001/01/05 23:53:53 guus Exp $ */ #include "config.h" @@ -33,16 +33,16 @@ #include #include -#include +#include /* lists type of subnet */ -rbltree_t *subnet_tree; +avl_tree_t *subnet_tree; void init_subnets(void) { cp - subnet_tree = new_rbltree((rbl_compare_t)subnet_compare, (rbl_action_t)free_subnet); + subnet_tree = avl_alloc_tree((avl_compare_t)subnet_compare, (avl_action_t)free_subnet); cp } @@ -131,17 +131,17 @@ void subnet_add(connection_t *cl, subnet_t *subnet) { cp subnet->owner = cl; - rbl_insert(subnet_tree, subnet); - rbl_insert(cl->subnet_tree, subnet); + avl_insert(subnet_tree, subnet); + avl_insert(cl->subnet_tree, subnet); cp } void subnet_del(subnet_t *subnet) { cp - rbl_delete(subnet->owner->subnet_tree, subnet); + avl_delete(subnet->owner->subnet_tree, subnet); cp - rbl_delete(subnet_tree, subnet); + avl_delete(subnet_tree, subnet); cp } @@ -256,62 +256,59 @@ cp /* Subnet lookup routines */ -subnet_t *lookup_subnet_mac(mac_t address) +subnet_t *lookup_subnet_mac(mac_t *address) { subnet_t subnet, *p; cp subnet.type = SUBNET_MAC; - subnet.net.mac.address = address; + memcpy(&subnet.net.mac.address, address, sizeof(mac_t)); - p = (subnet_t *)rbl_search_closest(subnet_tree, &subnet); + p = (subnet_t *)avl_search(subnet_tree, &subnet); cp - if(p && !memcmp(&address, &p->net.mac.address, sizeof(mac_t))) - return p; - else - return NULL; + return p; } -subnet_t *lookup_subnet_ipv4(ipv4_t address) +subnet_t *lookup_subnet_ipv4(ipv4_t *address) { subnet_t subnet, *p; cp subnet.type = SUBNET_IPV4; - subnet.net.ipv4.address = address; + subnet.net.ipv4.address = *address; subnet.net.ipv4.mask = 0xFFFFFFFF; - p = (subnet_t *)rbl_search_closest_greater(subnet_tree, &subnet); + p = (subnet_t *)avl_search_closest_greater(subnet_tree, &subnet); /* Check if the found subnet REALLY matches */ cp - if(p && ((address & p->net.ipv4.mask) == p->net.ipv4.address)) + if(p && ((*address & p->net.ipv4.mask) == p->net.ipv4.address)) return p; else return NULL; } -subnet_t *lookup_subnet_ipv6(ipv6_t address) +subnet_t *lookup_subnet_ipv6(ipv6_t *address) { subnet_t subnet; cp subnet.type = SUBNET_IPV6; - subnet.net.ipv6.address = address; + memcpy(&subnet.net.ipv6.address, address, sizeof(ipv6_t)); memset(&subnet.net.ipv6.mask, 0xFF, 16); /* FIXME: check if it REALLY matches */ - return (subnet_t *)rbl_search_closest(subnet_tree, &subnet); + return (subnet_t *)avl_search_closest_greater(subnet_tree, &subnet); } void dump_subnet_list(void) { char *netstr; subnet_t *subnet; - rbl_t *rbl; + avl_node_t *node; cp syslog(LOG_DEBUG, _("Subnet list:")); - RBL_FOREACH(subnet_tree, rbl) + for(node = subnet_tree->head; node; node = node->next) { - subnet = (subnet_t *)rbl->data; + subnet = (subnet_t *)node->data; netstr = net2str(subnet); syslog(LOG_DEBUG, " %s owner %s", netstr, subnet->owner->name); free(netstr); diff --git a/src/subnet.h b/src/subnet.h index 1aab681a..a572953c 100644 --- a/src/subnet.h +++ b/src/subnet.h @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: subnet.h,v 1.1.2.7 2000/11/20 19:41:13 guus Exp $ + $Id: subnet.h,v 1.1.2.8 2001/01/05 23:53:53 guus Exp $ */ #ifndef __TINC_SUBNET_H__ @@ -83,9 +83,9 @@ extern void subnet_del(subnet_t *); extern char *net2str(subnet_t *); extern subnet_t *str2net(char *); extern int subnet_compare(subnet_t *, subnet_t *); -extern subnet_t *lookup_subnet_mac(mac_t); -extern subnet_t *lookup_subnet_ipv4(ipv4_t); -extern subnet_t *lookup_subnet_ipv6(ipv6_t); +extern subnet_t *lookup_subnet_mac(mac_t *); +extern subnet_t *lookup_subnet_ipv4(ipv4_t *); +extern subnet_t *lookup_subnet_ipv6(ipv6_t *); extern void dump_subnet_list(void); #endif /* __TINC_SUBNET_H__ */ diff --git a/src/tincd.c b/src/tincd.c index 3dbac7e3..535fdb32 100644 --- a/src/tincd.c +++ b/src/tincd.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: tincd.c,v 1.10.4.38 2000/12/03 12:23:06 zarq Exp $ + $Id: tincd.c,v 1.10.4.39 2001/01/05 23:53:53 guus Exp $ */ #include "config.h" @@ -283,6 +283,8 @@ void make_names(void) int main(int argc, char **argv, char **envp) { + openlog("tinc", LOG_PERROR, LOG_DAEMON); /* Catch all syslog() calls issued before detaching */ + program_name = argv[0]; setlocale (LC_ALL, ""); @@ -322,9 +324,9 @@ main(int argc, char **argv, char **envp) make_names(); /* Slllluuuuuuurrrrp! */ - +cp RAND_load_file("/dev/urandom", 1024); - +cp if(generate_keys) exit(keygen(generate_keys)); @@ -333,10 +335,10 @@ main(int argc, char **argv, char **envp) if(read_server_config()) return 1; - +cp if(detach()) exit(0); - +cp if(debug_lvl >= DEBUG_ERROR) ERR_load_crypto_strings(); -- 2.20.1