- 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...
This commit is contained in:
Guus Sliepen 2001-01-05 23:53:53 +00:00
parent 052fbc0bdf
commit e924096f62
12 changed files with 245 additions and 180 deletions

View file

@ -19,12 +19,11 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 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 "config.h"
#include <assert.h>
#include <ctype.h> #include <ctype.h>
#include <errno.h> #include <errno.h>
#include <netdb.h> #include <netdb.h>
@ -35,6 +34,7 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#include <syslog.h>
#include <xalloc.h> #include <xalloc.h>
#include <utils.h> /* for cp */ #include <utils.h> /* for cp */
@ -311,7 +311,7 @@ cp
x = read_config_file(&config, fname); x = read_config_file(&config, fname);
if(x == -1) /* System error */ if(x == -1) /* System error */
{ {
fprintf(stderr, _("Failed to read `%s': %m\n"), syslog(LOG_ERR, _("Failed to read `%s': %m"),
fname); fname);
} }
free(fname); free(fname);
@ -358,7 +358,7 @@ int isadir(const char* f)
if(stat(f, &s) < 0) if(stat(f, &s) < 0)
{ {
fprintf(stderr, _("Couldn't stat `%s': %m\n"), syslog(LOG_ERR, _("Couldn't stat `%s': %m"),
f); f);
return -1; return -1;
} }
@ -371,24 +371,29 @@ int is_safe_path(const char *file)
char *p; char *p;
struct stat s; struct stat s;
if(*file != '/')
{
syslog(LOG_ERR, _("`%s' is not an absolute path"), file);
return 0;
}
p = strrchr(file, '/'); p = strrchr(file, '/');
assert(p); /* p has to contain a / */
*p = '\0'; *p = '\0';
if(stat(file, &s) < 0) if(stat(file, &s) < 0)
{ {
fprintf(stderr, _("Couldn't stat `%s': %m\n"), syslog(LOG_ERR, _("Couldn't stat `%s': %m"),
file); file);
return 0; return 0;
} }
if(s.st_uid != geteuid()) 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()); file, s.st_uid, geteuid());
return 0; return 0;
} }
if(S_ISLNK(s.st_mode)) if(S_ISLNK(s.st_mode))
{ {
fprintf(stderr, _("Warning: `%s' is a symlink\n"), syslog(LOG_WARNING, _("Warning: `%s' is a symlink"),
file); file);
/* fixme: read the symlink and start again */ /* fixme: read the symlink and start again */
} }
@ -396,7 +401,7 @@ int is_safe_path(const char *file)
*p = '/'; *p = '/';
if(stat(file, &s) < 0 && errno != ENOENT) if(stat(file, &s) < 0 && errno != ENOENT)
{ {
fprintf(stderr, _("Couldn't stat `%s': %m\n"), syslog(LOG_ERR, _("Couldn't stat `%s': %m"),
file); file);
return 0; return 0;
} }
@ -404,20 +409,20 @@ int is_safe_path(const char *file)
return 1; return 1;
if(s.st_uid != geteuid()) 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()); file, s.st_uid, geteuid());
return 0; return 0;
} }
if(S_ISLNK(s.st_mode)) if(S_ISLNK(s.st_mode))
{ {
fprintf(stderr, _("Warning: `%s' is a symlink\n"), syslog(LOG_WARNING, _("Warning: `%s' is a symlink"),
file); file);
/* fixme: read the symlink and start again */ /* fixme: read the symlink and start again */
} }
if(s.st_mode & 0007) if(s.st_mode & 0007)
{ {
/* Accessible by others */ /* Accessible by others */
fprintf(stderr, _("`%s' has unsecure permissions.\n"), syslog(LOG_ERR, _("`%s' has unsecure permissions"),
file); file);
return 0; 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. */ /* Ask for a file and/or directory name. */
fprintf(stdout, _("Please enter a file to save %s to [%s]: "), fprintf(stdout, _("Please enter a file to save %s to [%s]: "),
what, filename); what, filename);
fflush(stdout); /* Don't wait for a newline */ fflush(stdout);
if((fn = readline(stdin, NULL, NULL)) == NULL) if((fn = readline(stdin, NULL, NULL)) == NULL)
{ {
fprintf(stderr, _("Error while reading stdin: %m\n")); fprintf(stderr, _("Error while reading stdin: %m\n"));
return NULL; return NULL;
} }
if(strlen(fn) == 0) if(strlen(fn) == 0)
/* User just pressed enter. */ /* User just pressed enter. */
fn = xstrdup(filename); fn = xstrdup(filename);

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 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__ #ifndef __TINC_CONF_H__
@ -63,7 +63,7 @@ typedef struct config_t {
int argtype; int argtype;
union data { union data {
unsigned long val; unsigned long val;
void *ptr; char *ptr;
ip_mask_t *ip; ip_mask_t *ip;
struct config_t *next; /* For nested configs! */ struct config_t *next; /* For nested configs! */
} data; } data;

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 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" #include "config.h"
@ -25,7 +25,7 @@
#include <stdio.h> #include <stdio.h>
#include <syslog.h> #include <syslog.h>
#include <rbl.h> #include <avl_tree.h>
#include "net.h" /* Don't ask. */ #include "net.h" /* Don't ask. */
#include "netutl.h" #include "netutl.h"
@ -39,8 +39,10 @@
/* Root of the connection list */ /* Root of the connection list */
rbltree_t *connection_tree; avl_tree_t *connection_tree;
rbltree_t *id_tree; avl_tree_t *id_tree;
/* Pointer to connection describing myself */
connection_t *myself = NULL; connection_t *myself = NULL;
@ -49,6 +51,7 @@ connection_t *myself = NULL;
int connection_compare(connection_t *a, connection_t *b) int connection_compare(connection_t *a, connection_t *b)
{ {
ipv4_t result; ipv4_t result;
result = a->address - b->address; result = a->address - b->address;
if(result) if(result)
return result; return result;
@ -63,8 +66,8 @@ int id_compare(connection_t *a, connection_t *b)
void init_connections(void) void init_connections(void)
{ {
connection_tree = new_rbltree((rbl_compare_t)connection_compare, (rbl_action_t)free_connection); connection_tree = avl_alloc_tree((avl_compare_t)connection_compare, (avl_action_t)free_connection);
id_tree = new_rbltree((rbl_compare_t)id_compare, NULL); id_tree = avl_alloc_tree((avl_compare_t)id_compare, NULL);
} }
/* Creation and deletion of connection elements */ /* 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)); connection_t *p = (connection_t *)xmalloc_and_zero(sizeof(*p));
cp 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 cp
return p; return p;
} }
@ -106,12 +109,13 @@ cp
*/ */
void prune_connection_tree(void) void prune_connection_tree(void)
{ {
rbl_t *rbl; avl_node_t *node, *next;
connection_t *cl; connection_t *cl;
cp 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) if(cl->status.remove)
connection_del(cl); connection_del(cl);
} }
@ -124,8 +128,8 @@ cp
void destroy_connection_tree(void) void destroy_connection_tree(void)
{ {
cp cp
rbl_delete_rbltree(id_tree); avl_delete_tree(id_tree);
rbl_delete_rbltree(connection_tree); avl_delete_tree(connection_tree);
cp cp
} }
@ -134,22 +138,22 @@ cp
void connection_add(connection_t *cl) void connection_add(connection_t *cl)
{ {
cp cp
rbl_insert(connection_tree, cl); avl_insert(connection_tree, cl);
cp cp
} }
void id_add(connection_t *cl) void id_add(connection_t *cl)
{ {
cp cp
rbl_insert(id_tree, cl); avl_insert(id_tree, cl);
cp cp
} }
void connection_del(connection_t *cl) void connection_del(connection_t *cl)
{ {
cp cp
rbl_delete(id_tree, cl); avl_delete(id_tree, cl);
rbl_delete(connection_tree, cl); avl_delete(connection_tree, cl);
cp cp
} }
@ -162,7 +166,7 @@ cp
cl.address = address; cl.address = address;
cl.port = port; cl.port = port;
return rbl_search(connection_tree, &cl); return avl_search(connection_tree, &cl);
} }
connection_t *lookup_id(char *name) connection_t *lookup_id(char *name)
@ -170,7 +174,7 @@ connection_t *lookup_id(char *name)
connection_t cl, *p; connection_t cl, *p;
cp cp
cl.name = name; cl.name = name;
p = rbl_search(id_tree, &cl); p = avl_search(id_tree, &cl);
if(p && p->status.active) if(p && p->status.active)
return p; return p;
else else
@ -181,7 +185,7 @@ cp
void dump_connection_list(void) void dump_connection_list(void)
{ {
rbl_t *rbl; avl_node_t *node;
connection_t *cl; connection_t *cl;
cp cp
syslog(LOG_DEBUG, _("Connection list:")); syslog(LOG_DEBUG, _("Connection list:"));
@ -190,9 +194,9 @@ cp
myself->name, myself->hostname, myself->port, myself->flags, myself->name, myself->hostname, myself->port, myself->flags,
myself->socket, myself->meta_socket, myself->status); 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"), syslog(LOG_DEBUG, _(" %s at %s port %hd flags %d sockets %d, %d status %04x"),
cl->name, cl->hostname, cl->port, cl->flags, cl->name, cl->hostname, cl->port, cl->flags,
cl->socket, cl->meta_socket, cl->status); cl->socket, cl->meta_socket, cl->status);

View file

@ -17,13 +17,13 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 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__ #ifndef __TINC_CONNECTION_H__
#define __TINC_CONNECTION_H__ #define __TINC_CONNECTION_H__
#include <rbl.h> #include <avl_tree.h>
#include "config.h" #include "config.h"
@ -66,8 +66,8 @@ typedef struct connection_t {
char *name; /* name of this connection */ char *name; /* name of this connection */
ipv4_t address; /* his real (internet) ip */ ipv4_t address; /* his real (internet) ip */
char *hostname; /* the hostname of its real ip */ char *hostname; /* the hostname of its real ip */
short unsigned int port; /* his portnumber */
int protocol_version; /* used protocol */ int protocol_version; /* used protocol */
short unsigned int port; /* port number for UDP traffic */
long unsigned int options; /* options turned on for this connection */ long unsigned int options; /* options turned on for this connection */
int flags; /* his flags */ int flags; /* his flags */
@ -100,12 +100,12 @@ typedef struct connection_t {
struct connection_t *nexthop; /* nearest meta-hop in this direction */ 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 */ struct config_t *config; /* Pointer to configuration tree belonging to this host */
} connection_t; } connection_t;
extern rbltree_t *connection_tree; extern avl_tree_t *connection_tree;
extern connection_t *myself; extern connection_t *myself;
extern void init_connections(void); extern void init_connections(void);

View file

@ -17,11 +17,12 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 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 "config.h"
#include <utils.h> #include <utils.h>
#include <avl_tree.h>
#include <errno.h> #include <errno.h>
#include <syslog.h> #include <syslog.h>
@ -74,12 +75,12 @@ cp
void broadcast_meta(connection_t *cl, char *buffer, int length) void broadcast_meta(connection_t *cl, char *buffer, int length)
{ {
rbl_t *rbl; avl_node_t *node;
connection_t *p; connection_t *p;
cp 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) if(p != cl && p->status.meta && p->status.active)
send_meta(p, buffer, length); send_meta(p, buffer, length);
} }

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 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" #include "config.h"
@ -71,6 +71,7 @@
#include <utils.h> #include <utils.h>
#include <xalloc.h> #include <xalloc.h>
#include <avl_tree.h>
#include "conf.h" #include "conf.h"
#include "connection.h" #include "connection.h"
@ -165,7 +166,7 @@ cp
if(debug_lvl >= DEBUG_TRAFFIC) if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_ERR, _("Writing packet of %d bytes to tap device"), syslog(LOG_ERR, _("Writing packet of %d bytes to tap device"),
outpkt.len, outlen); outpkt.len);
/* Fix mac address */ /* Fix mac address */
@ -320,7 +321,7 @@ int send_packet(ip_t to, vpn_packet_t *packet)
connection_t *cl; connection_t *cl;
subnet_t *subnet; subnet_t *subnet;
cp cp
if((subnet = lookup_subnet_ipv4(to)) == NULL) if((subnet = lookup_subnet_ipv4(&to)) == NULL)
{ {
if(debug_lvl >= DEBUG_TRAFFIC) if(debug_lvl >= DEBUG_TRAFFIC)
{ {
@ -607,6 +608,19 @@ cp
return -1; 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_family = AF_INET;
a.sin_port = htons(cl->port); a.sin_port = htons(cl->port);
a.sin_addr.s_addr = htonl(cl->address); a.sin_addr.s_addr = htonl(cl->address);
@ -656,14 +670,14 @@ cp
if(read_host_config(ncn)) 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); free_connection(ncn);
return -1; return -1;
} }
if(!(cfg = get_config_val(ncn->config, config_address))) 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); free_connection(ncn);
return -1; return -1;
} }
@ -876,7 +890,7 @@ cp
syslog(LOG_ERR, _("Unable to set up a listening UDP socket!")); syslog(LOG_ERR, _("Unable to set up a listening UDP socket!"));
return -1; return -1;
} }
cp
/* Generate packet encryption key */ /* Generate packet encryption key */
myself->cipher_pkttype = EVP_bf_cfb(); myself->cipher_pkttype = EVP_bf_cfb();
@ -892,9 +906,9 @@ cp
keylifetime = cfg->data.val; keylifetime = cfg->data.val;
keyexpires = time(NULL) + keylifetime; keyexpires = time(NULL) + keylifetime;
cp
/* Activate ourselves */ /* Activate ourselves */
myself->status.active = 1; myself->status.active = 1;
syslog(LOG_NOTICE, _("Ready: listening on port %hd"), myself->port); syslog(LOG_NOTICE, _("Ready: listening on port %hd"), myself->port);
@ -991,12 +1005,12 @@ cp
*/ */
void close_network_connections(void) void close_network_connections(void)
{ {
rbl_t *rbl; avl_node_t *node;
connection_t *p; connection_t *p;
cp 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; p->status.active = 0;
terminate_connection(p); terminate_connection(p);
} }
@ -1117,6 +1131,7 @@ cp
p->name = unknown; p->name = unknown;
p->address = ntohl(ci.sin_addr.s_addr); p->address = ntohl(ci.sin_addr.s_addr);
p->hostname = hostlookup(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->meta_socket = sfd;
p->status.meta = 1; p->status.meta = 1;
p->buffer = xmalloc(MAXBUFSIZE); p->buffer = xmalloc(MAXBUFSIZE);
@ -1137,16 +1152,16 @@ cp
*/ */
void build_fdset(fd_set *fs) void build_fdset(fd_set *fs)
{ {
rbl_t *rbl; avl_node_t *node;
connection_t *p; connection_t *p;
cp cp
FD_ZERO(fs); FD_ZERO(fs);
FD_SET(myself->socket, 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) if(p->status.meta)
FD_SET(p->meta_socket, fs); FD_SET(p->meta_socket, fs);
} }
@ -1192,7 +1207,7 @@ cp
if(!cl) 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; return 0;
} }
@ -1214,7 +1229,7 @@ void terminate_connection(connection_t *cl)
{ {
connection_t *p; connection_t *p;
subnet_t *subnet; subnet_t *subnet;
rbl_t *rbl; avl_node_t *node, *next;
cp cp
if(cl->status.remove) if(cl->status.remove)
return; return;
@ -1234,9 +1249,9 @@ cp
(the connection that was dropped). */ (the connection that was dropped). */
if(cl->status.meta) 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) if(p->nexthop == cl && p != cl)
terminate_connection(p); terminate_connection(p);
} }
@ -1244,18 +1259,19 @@ cp
/* Inform others of termination if it was still active */ /* Inform others of termination if it was still active */
if(cl->status.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) 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 :) */ send_del_host(p, cl); /* Sounds like recursion, but p does not have a meta connection :) */
} }
/* Remove the associated subnets */ /* 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); subnet_del(subnet);
} }
@ -1286,14 +1302,14 @@ cp
void check_dead_connections(void) void check_dead_connections(void)
{ {
time_t now; time_t now;
rbl_t *rbl; avl_node_t *node;
connection_t *cl; connection_t *cl;
cp cp
now = time(NULL); 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->status.active && cl->status.meta)
{ {
if(cl->last_ping_time + timeout < now) if(cl->last_ping_time + timeout < now)
@ -1352,14 +1368,14 @@ cp
void check_network_activity(fd_set *f) void check_network_activity(fd_set *f)
{ {
connection_t *p; connection_t *p;
rbl_t *rbl; avl_node_t *node;
cp cp
if(FD_ISSET(myself->socket, f)) if(FD_ISSET(myself->socket, f))
handle_incoming_vpn_data(); 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) if(p->status.remove)
return; return;

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 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" #include "config.h"
@ -159,6 +159,8 @@ cp
/* If we succeeded in doing that, detach */ /* If we succeeded in doing that, detach */
closelog();
if(do_detach) if(do_detach)
{ {
if(daemon(0, 0) < 0) if(daemon(0, 0) < 0)

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 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" #include "config.h"
@ -34,6 +34,7 @@
#include <utils.h> #include <utils.h>
#include <xalloc.h> #include <xalloc.h>
#include <avl_tree.h>
#include <netinet/in.h> #include <netinet/in.h>
@ -193,10 +194,10 @@ cp
int id_h(connection_t *cl) int id_h(connection_t *cl)
{ {
connection_t *old; connection_t *old;
config_t const *cfg; unsigned short int port;
char name[MAX_STRING_SIZE]; char name[MAX_STRING_SIZE];
cp 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); syslog(LOG_ERR, _("Got bad ID from %s"), cl->hostname);
return -1; return -1;
@ -253,6 +254,12 @@ cp
id_add(cl); 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 */ /* Read in the public key, so that we can send a challenge */
if(read_rsa_public_key(cl)) if(read_rsa_public_key(cl))
@ -283,7 +290,7 @@ cp
RAND_bytes(cl->hischallenge, len); RAND_bytes(cl->hischallenge, len);
cl->hischallenge[0] &= 0x7F; /* Somehow if the first byte is more than 0xD0 or something like that, decryption fails... */ 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) if(debug_lvl >= DEBUG_SCARY_THINGS)
{ {
bin2hex(cl->hischallenge, buffer, len); bin2hex(cl->hischallenge, buffer, len);
@ -304,7 +311,7 @@ cp
bin2hex(buffer, buffer, len); bin2hex(buffer, buffer, len);
buffer[len*2] = '\0'; buffer[len*2] = '\0';
cp
/* Send the challenge */ /* Send the challenge */
cl->allow_request = CHAL_REPLY; cl->allow_request = CHAL_REPLY;
@ -580,7 +587,7 @@ int ack_h(connection_t *cl)
{ {
connection_t *old, *p; connection_t *old, *p;
subnet_t *subnet; subnet_t *subnet;
rbl_t *rbl, *rbl2; avl_node_t *node, *node2;
cp cp
/* Okay, before we active the connection, we check if there is another entry /* 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 in the connection list with the same name. If so, it presumably is an
@ -614,16 +621,16 @@ cp
/* Send him our subnets */ /* 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); send_add_subnet(cl, subnet);
} }
/* And send him all the hosts and their subnets we know... */ /* 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) if(p != cl && p->status.active)
{ {
@ -636,9 +643,9 @@ cp
send_add_host(cl, p); 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); send_add_subnet(cl, subnet);
} }
} }
@ -667,7 +674,7 @@ int add_subnet_h(connection_t *cl)
char name[MAX_STRING_SIZE]; char name[MAX_STRING_SIZE];
connection_t *owner, *p; connection_t *owner, *p;
subnet_t *subnet; subnet_t *subnet;
rbl_t *rbl; avl_node_t *node;
cp cp
if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING, name, subnetstr) != 2) if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING, name, subnetstr) != 2)
{ {
@ -716,9 +723,9 @@ cp
/* Tell the rest */ /* 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) if(p->status.meta && p->status.active && p!= cl)
send_add_subnet(p, subnet); send_add_subnet(p, subnet);
} }
@ -744,7 +751,7 @@ int del_subnet_h(connection_t *cl)
char name[MAX_STRING_SIZE]; char name[MAX_STRING_SIZE];
connection_t *owner, *p; connection_t *owner, *p;
subnet_t *subnet; subnet_t *subnet;
rbl_t *rbl; avl_node_t *node;
cp cp
if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING, name, subnetstr) != 3) if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING, name, subnetstr) != 3)
{ {
@ -795,9 +802,9 @@ cp
/* Tell the rest */ /* 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) if(p->status.meta && p->status.active && p!= cl)
send_del_subnet(p, subnet); send_del_subnet(p, subnet);
} }
@ -818,7 +825,7 @@ int add_host_h(connection_t *cl)
{ {
connection_t *old, *new, *p; connection_t *old, *new, *p;
char name[MAX_STRING_SIZE]; char name[MAX_STRING_SIZE];
rbl_t *rbl; avl_node_t *node;
cp cp
new = new_connection(); new = new_connection();
@ -881,9 +888,9 @@ cp
/* Tell the rest about the new host */ /* 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) if(p->status.meta && p->status.active && p!=cl)
send_add_host(p, new); send_add_host(p, new);
} }
@ -912,7 +919,7 @@ int del_host_h(connection_t *cl)
port_t port; port_t port;
long int options; long int options;
connection_t *old, *p; connection_t *old, *p;
rbl_t *rbl; avl_node_t *node;
cp cp
if(sscanf(cl->buffer, "%*d "MAX_STRING" %lx:%d %lx", name, &address, &port, &options) != 4) 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 */ /* 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) if(p->status.meta && p->status.active && p!=cl)
send_del_host(p, old); send_del_host(p, old);
} }
@ -1087,11 +1094,11 @@ cp
int send_key_changed(connection_t *from, connection_t *cl) int send_key_changed(connection_t *from, connection_t *cl)
{ {
connection_t *p; connection_t *p;
rbl_t *rbl; avl_node_t *node;
cp 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) if(p != cl && p->status.meta && p->status.active)
send_request(p, "%d %s", KEY_CHANGED, from->name); send_request(p, "%d %s", KEY_CHANGED, from->name);
} }

View file

@ -17,87 +17,75 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 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 "config.h"
#include <utils.h> #include <utils.h>
#include <xalloc.h> #include <xalloc.h>
#include <syslog.h>
#include "net.h" #include "net.h"
#include "connection.h" #include "connection.h"
#include "subnet.h"
#include "route.h"
#include "system.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 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) /* FIXME: do ageing and roaming */
{
case 0x0800: /* Lookup destination address */
return route_ipv4(packet);
case 0x86DD: dst = lookup_subnet_mac((mac_t *)(&packet->data[6]))->owner;
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;
}
}
connection_t *route_mac(vpn_packet_t *packet) if(!dst)
{
connection_t *cl;
cp
cl = lookup_subnet_mac((mac_t *)(&packet.data[6]));
if(!cl)
if(debug_lvl >= DEBUG_TRAFFIC) if(debug_lvl >= DEBUG_TRAFFIC)
{ {
syslog(LOG_WARNING, _("Cannot route packet: unknown destination address %x:%x:%x:%x:%x:%x"), syslog(LOG_WARNING, _("Cannot route packet: unknown destination address %x:%x:%x:%x:%x:%x"),
packet.data[6], packet->data[6],
packet.data[7], packet->data[7],
packet.data[8], packet->data[8],
packet.data[9], packet->data[9],
packet.data[10], packet->data[10],
packet.data[11]); packet->data[11]);
} }
cp cp
return cl; return dst;
} }
connection_t *route_ipv4(vpn_packet_t *packet) connection_t *route_ipv4(vpn_packet_t *packet)
{ {
ipv4_t dest; ipv4_t dest;
connection_t *cl; connection_t *cl;
cp 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(!cl)
if(debug_lvl >= DEBUG_TRAFFIC) if(debug_lvl >= DEBUG_TRAFFIC)
{ {
syslog(LOG_WARNING, _("Cannot route packet: unknown destination address %d.%d.%d.%d"), 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 cp
return cl; return cl;
@ -106,7 +94,48 @@ cp
connection_t *route_ipv6(vpn_packet_t *packet) connection_t *route_ipv6(vpn_packet_t *packet)
{ {
cp 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 cp
return NULL; 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;
}
}
}

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 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" #include "config.h"
@ -33,16 +33,16 @@
#include <utils.h> #include <utils.h>
#include <xalloc.h> #include <xalloc.h>
#include <rbl.h> #include <avl_tree.h>
/* lists type of subnet */ /* lists type of subnet */
rbltree_t *subnet_tree; avl_tree_t *subnet_tree;
void init_subnets(void) void init_subnets(void)
{ {
cp 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 cp
} }
@ -131,17 +131,17 @@ void subnet_add(connection_t *cl, subnet_t *subnet)
{ {
cp cp
subnet->owner = cl; subnet->owner = cl;
rbl_insert(subnet_tree, subnet); avl_insert(subnet_tree, subnet);
rbl_insert(cl->subnet_tree, subnet); avl_insert(cl->subnet_tree, subnet);
cp cp
} }
void subnet_del(subnet_t *subnet) void subnet_del(subnet_t *subnet)
{ {
cp cp
rbl_delete(subnet->owner->subnet_tree, subnet); avl_delete(subnet->owner->subnet_tree, subnet);
cp cp
rbl_delete(subnet_tree, subnet); avl_delete(subnet_tree, subnet);
cp cp
} }
@ -256,62 +256,59 @@ cp
/* Subnet lookup routines */ /* Subnet lookup routines */
subnet_t *lookup_subnet_mac(mac_t address) subnet_t *lookup_subnet_mac(mac_t *address)
{ {
subnet_t subnet, *p; subnet_t subnet, *p;
cp cp
subnet.type = SUBNET_MAC; 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 cp
if(p && !memcmp(&address, &p->net.mac.address, sizeof(mac_t))) return p;
return p;
else
return NULL;
} }
subnet_t *lookup_subnet_ipv4(ipv4_t address) subnet_t *lookup_subnet_ipv4(ipv4_t *address)
{ {
subnet_t subnet, *p; subnet_t subnet, *p;
cp cp
subnet.type = SUBNET_IPV4; subnet.type = SUBNET_IPV4;
subnet.net.ipv4.address = address; subnet.net.ipv4.address = *address;
subnet.net.ipv4.mask = 0xFFFFFFFF; 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 */ /* Check if the found subnet REALLY matches */
cp 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; return p;
else else
return NULL; return NULL;
} }
subnet_t *lookup_subnet_ipv6(ipv6_t address) subnet_t *lookup_subnet_ipv6(ipv6_t *address)
{ {
subnet_t subnet; subnet_t subnet;
cp cp
subnet.type = SUBNET_IPV6; 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); memset(&subnet.net.ipv6.mask, 0xFF, 16);
/* FIXME: check if it REALLY matches */ /* 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) void dump_subnet_list(void)
{ {
char *netstr; char *netstr;
subnet_t *subnet; subnet_t *subnet;
rbl_t *rbl; avl_node_t *node;
cp cp
syslog(LOG_DEBUG, _("Subnet list:")); 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); netstr = net2str(subnet);
syslog(LOG_DEBUG, " %s owner %s", netstr, subnet->owner->name); syslog(LOG_DEBUG, " %s owner %s", netstr, subnet->owner->name);
free(netstr); free(netstr);

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 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__ #ifndef __TINC_SUBNET_H__
@ -83,9 +83,9 @@ extern void subnet_del(subnet_t *);
extern char *net2str(subnet_t *); extern char *net2str(subnet_t *);
extern subnet_t *str2net(char *); extern subnet_t *str2net(char *);
extern int subnet_compare(subnet_t *, subnet_t *); extern int subnet_compare(subnet_t *, subnet_t *);
extern subnet_t *lookup_subnet_mac(mac_t); extern subnet_t *lookup_subnet_mac(mac_t *);
extern subnet_t *lookup_subnet_ipv4(ipv4_t); extern subnet_t *lookup_subnet_ipv4(ipv4_t *);
extern subnet_t *lookup_subnet_ipv6(ipv6_t); extern subnet_t *lookup_subnet_ipv6(ipv6_t *);
extern void dump_subnet_list(void); extern void dump_subnet_list(void);
#endif /* __TINC_SUBNET_H__ */ #endif /* __TINC_SUBNET_H__ */

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 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" #include "config.h"
@ -283,6 +283,8 @@ void make_names(void)
int int
main(int argc, char **argv, char **envp) main(int argc, char **argv, char **envp)
{ {
openlog("tinc", LOG_PERROR, LOG_DAEMON); /* Catch all syslog() calls issued before detaching */
program_name = argv[0]; program_name = argv[0];
setlocale (LC_ALL, ""); setlocale (LC_ALL, "");
@ -322,9 +324,9 @@ main(int argc, char **argv, char **envp)
make_names(); make_names();
/* Slllluuuuuuurrrrp! */ /* Slllluuuuuuurrrrp! */
cp
RAND_load_file("/dev/urandom", 1024); RAND_load_file("/dev/urandom", 1024);
cp
if(generate_keys) if(generate_keys)
exit(keygen(generate_keys)); exit(keygen(generate_keys));
@ -333,10 +335,10 @@ main(int argc, char **argv, char **envp)
if(read_server_config()) if(read_server_config())
return 1; return 1;
cp
if(detach()) if(detach())
exit(0); exit(0);
cp
if(debug_lvl >= DEBUG_ERROR) if(debug_lvl >= DEBUG_ERROR)
ERR_load_crypto_strings(); ERR_load_crypto_strings();