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.44 2001/10/10 20:34:27 guus Exp $
+ $Id: conf.c,v 1.9.4.45 2001/10/27 12:13:17 guus Exp $
*/
#include "config.h"
return 0;
}
+int get_config_port(config_t *cfg, port_t *result)
+{
+cp
+ if(!cfg)
+ return 0;
+
+ if(sscanf(cfg->value, "%hu", result) == 1)
+ return 1;
+
+ syslog(LOG_ERR, _("Port number expected for configuration variable %s in %s line %d"),
+ cfg->value, cfg->file, cfg->line);
+ return 0;
+}
+
+int get_config_subnet(config_t *cfg, subnet_t **result)
+{
+ ip_mask_t *ip;
+ subnet_t *subnet;
+cp
+ if(!cfg)
+ return 0;
+
+ ip = strtoip(cfg->value);
+
+ if(!ip)
+ {
+ syslog(LOG_ERR, _("IP address expected for configuration variable %s in %s line %d"),
+ cfg->value, cfg->file, cfg->line);
+ return 0;
+ }
+
+ /* Teach newbies what subnets are... */
+
+ if((subnet->net.ipv4.address & subnet->net.ipv4.mask) != subnet->net.ipv4.address)
+ {
+ syslog(LOG_ERR, _("Network address and subnet mask for configuration variable %s in %s line %d"),
+ cfg->value, cfg->file, cfg->line);
+ free(ip);
+ return -1;
+ }
+
+ subnet = new_subnet();
+ subnet->type = SUBNET_IPV4;
+ subnet->net.ipv4.address = ip->address;
+ subnet->net.ipv4.mask = ip->mask;
+
+ free(ip);
+
+ *result = subnet;
+
+ return 1;
+}
+
/*
Read exactly one line and strip the trailing newline if any. If the
file was on EOF, return NULL. Otherwise, return all the data in a
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.27 2001/10/10 20:34:27 guus Exp $
+ $Id: conf.h,v 1.6.4.28 2001/10/27 12:13:17 guus Exp $
*/
#ifndef __TINC_CONF_H__
#include <avl_tree.h>
#include "net.h"
+#include "subnet.h"
typedef struct config_t {
char *variable;
extern config_t *new_config(void);
extern void free_config(config_t *);
extern void config_add(avl_tree_t *, config_t *);
-extern config_t *config_lookup(avl_tree_t *, char *);
-extern config_t *config_lookup_next(avl_tree_t *, config_t *);
+extern config_t *lookup_config(avl_tree_t *, char *);
+extern config_t *lookup_config_next(avl_tree_t *, config_t *);
extern int get_config_bool(config_t *, int *);
extern int get_config_int(config_t *, int *);
+extern int get_config_port(config_t *, port_t *);
extern int get_config_string(config_t *, char **);
-extern int get_config_ip(config_t *, ip_mask_t **);
+extern int get_config_ip(config_t *, struct ip_mask_t **);
+struct subnet_t; /* Needed for next line. */
+extern int get_config_subnet(config_t *, struct subnet_t **);
extern int read_config_file(avl_tree_t *, const char *);
extern int read_server_config(void);
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.19 2001/10/10 20:35:10 guus Exp $
+ $Id: connection.c,v 1.1.2.20 2001/10/27 12:13:17 guus Exp $
*/
#include "config.h"
cp
if(c->hostname)
free(c->hostname);
- if(c->rsa_key)
- RSA_free(c->rsa_key);
if(c->inkey)
free(c->inkey);
if(c->outkey)
{
c = (connection_t *)node->data;
syslog(LOG_DEBUG, _(" %s at %s port %hd options %ld socket %d status %04x"),
- c->node->name, c->hostname, c->port, c->options,
+ c->name, c->hostname, c->port, c->options,
c->socket, c->status);
}
syslog(LOG_DEBUG, _("End of connections."));
cp
}
+
+int read_connection_config(connection_t *c)
+{
+ char *fname;
+ int x;
+cp
+ asprintf(&fname, "%s/hosts/%s", confbase, c->name);
+ x = read_config_file(c->config_tree, fname);
+ free(fname);
+cp
+ return x;
+}
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.16 2001/10/10 20:35:10 guus Exp $
+ $Id: connection.h,v 1.1.2.17 2001/10/27 12:13:17 guus Exp $
*/
#ifndef __TINC_CONNECTION_H__
#include <avl_tree.h>
#include <list.h>
-#include "config.h"
-
#ifdef HAVE_OPENSSL_EVP_H
# include <openssl/evp.h>
#else
#include "node.h"
#include "vertex.h"
-typedef struct status_bits_t {
+#define OPTION_INDIRECT 0x0001
+#define OPTION_TCPONLY 0x0002
+
+typedef struct connection_status_t {
int pinged:1; /* sent ping */
- int meta:1; /* meta connection exists */
int active:1; /* 1 if active.. */
int outgoing:1; /* I myself asked for this conn */
int termreq:1; /* the termination of this connection was requested */
int remove:1; /* Set to 1 if you want this connection removed */
int timeout:1; /* 1 if gotten timeout */
- int validkey:1; /* 1 if we currently have a valid key for him */
- int waitingforkey:1; /* 1 if we already sent out a request */
- int dataopen:1; /* 1 if we have a valid UDP connection open */
int encryptout:1; /* 1 if we can encrypt outgoing traffic */
int decryptin:1; /* 1 if we have to decrypt incoming traffic */
int unused:18;
-} status_bits_t;
-
-#define OPTION_INDIRECT 0x0001
-#define OPTION_TCPONLY 0x0002
+} connection_status_t;
typedef struct connection_t {
+ char *name; /* name he claims to have */
+
ipv4_t address; /* his real (internet) ip */
short unsigned int port; /* port number of meta connection */
char *hostname; /* the hostname of its real ip */
int socket; /* socket used for this connection */
long int options; /* options for this connection */
- status_bits_t status; /* status info */
+ struct connection_status_t status; /* status info */
struct node_t *node; /* node associated with the other end */
struct vertex_t *vertex; /* vertex associated with this connection */
int allow_request; /* defined if there's only one request possible */
time_t last_ping_time; /* last time we saw some activity from the other end */
+
+ avl_tree_t *config_tree; /* Pointer to configuration tree belonging to him */
} connection_t;
extern avl_tree_t *connection_tree;
+extern void init_connections(void);
+extern void exit_connection(void);
+extern connection_t *new_connection(void);
+extern void free_connection(connection_t *);
+extern void connection_add(connection_t *);
+extern void connection_del(connection_t *);
+extern connection_t *lookup_connection(ipv4_t, short unsigned int);
+extern void dump_connections(void);
+extern int read_connection_config(connection_t *);
+
#endif /* __TINC_CONNECTION_H__ */
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: device.h,v 1.1.2.1 2001/10/12 15:16:03 guus Exp $
+ $Id: device.h,v 1.1.2.2 2001/10/27 12:13:17 guus Exp $
*/
#ifndef __TINC_DEVICE_H__
#define __TINC_DEVICE_H__
-extern void setup_device(void);
+extern int device_fd;
+
+extern int setup_device(void);
extern void close_device(void);
extern vpn_packet_t *read_packet(void);
-extern void write_packet(vpn_packet_t *);
+extern int write_packet(vpn_packet_t *);
extern void dump_device_stats(void);
-#endif __TINC_DEVICE_H__
+#endif /* __TINC_DEVICE_H__ */
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: device.c,v 1.1.2.1 2001/10/12 15:16:03 guus Exp $
+ $Id: device.c,v 1.1.2.2 2001/10/27 12:13:17 guus Exp $
*/
+#include "config.h"
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <net/if.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <string.h>
+#include <sys/ioctl.h>
+
#ifdef HAVE_TUNTAP
#ifdef LINUX_IF_TUN_H
#include LINUX_IF_TUN_H
#define DEFAULT_DEVICE "/dev/tap0"
#endif
+#include <utils.h>
+#include "conf.h"
+#include "net.h"
+#include "subnet.h"
+
+#include "system.h"
+
#define DEVICE_TYPE_ETHERTAP 0
#define DEVICE_TYPE_TUNTAP 1
int device_total_in = 0;
int device_total_out = 0;
+subnet_t mymac;
+
/*
open the local ethertap device
*/
struct ifreq ifr;
cp
- if(!get_config_string(lookup_config(config_tree, "Device"), &device_fname)))
+ if(!get_config_string(lookup_config(config_tree, "Device"), &device_fname))
device_fname = DEFAULT_DEVICE;
cp
return -1;
}
cp
- device_fd = device_fd;
-
/* Set default MAC address for ethertap devices */
mymac.type = SUBNET_MAC;
if (!ioctl(device_fd, (('T'<< 8) | 202), (void *) &ifr))
{
syslog(LOG_WARNING, _("Old ioctl() request was needed for %s"), device_fname);
- device_type = TAP_TYPE_TUNTAP;
+ device_type = DEVICE_TYPE_TUNTAP;
device_info = _("Linux tun/tap device");
}
else
#endif
{
device_info = _("Linux ethertap device");
- device_type = TAP_TYPE_ETHERTAP;
+ device_type = DEVICE_TYPE_ETHERTAP;
}
syslog(LOG_INFO, _("%s is a %s"), device_fname, device_info);
}
else /* ethertap */
{
- struct iovec vector[2] = {{packet->len, 2}, {packet->data, MTU}};
+ struct iovec vector[2] = {{&packet->len, 2}, {packet->data, MTU}};
if((lenin = readv(device_fd, vector, 2)) <= 0)
{
packet->len = lenin - 2;
}
-#endif
device_total_in += packet->len;
if(debug_lvl >= DEBUG_TRAFFIC)
{
- syslog(LOG_DEBUG, _("Read packet of %d bytes from %s"), device_info, packet.len);
+ syslog(LOG_DEBUG, _("Read packet of %d bytes from %s"), packet->len, device_info);
}
return 0;
{
if(write(device_fd, packet->data, packet->len) < 0)
{
- syslog(LOG_ERR, _("Can't write to %s %s: %m"), device_info, packet.len);
+ syslog(LOG_ERR, _("Can't write to %s %s: %m"), device_info, device_fname);
return -1;
}
}
else/* ethertap */
{
- struct iovec vector[2] = {{packet->len, 2}, {packet->data, MTU}};
+ struct iovec vector[2] = {{&packet->len, 2}, {packet->data, MTU}};
if(writev(device_fd, vector, 2) < 0)
{
- syslog(LOG_ERR, _("Can't write to %s %s: %m"), device_info, packet.len);
+ syslog(LOG_ERR, _("Can't write to %s %s: %m"), device_info, device_fname);
return -1;
}
}
device_total_out += packet->len;
cp
+ return 0;
}
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.20 2001/07/20 13:54:19 guus Exp $
+ $Id: meta.c,v 1.1.2.21 2001/10/27 12:13:17 guus Exp $
*/
#include "config.h"
#include "system.h"
#include "protocol.h"
-int send_meta(connection_t *cl, char *buffer, int length)
+int send_meta(connection_t *c, char *buffer, int length)
{
char *bufp;
int outlen;
cp
if(debug_lvl >= DEBUG_META)
syslog(LOG_DEBUG, _("Sending %d bytes of metadata to %s (%s)"), length,
- cl->name, cl->hostname);
+ c->name, c->hostname);
- if(cl->status.encryptout)
+ if(c->status.encryptout)
{
- EVP_EncryptUpdate(cl->cipher_outctx, outbuf, &outlen, buffer, length);
+ EVP_EncryptUpdate(c->outctx, outbuf, &outlen, buffer, length);
bufp = outbuf;
length = outlen;
}
else
bufp = buffer;
- if(write(cl->meta_socket, bufp, length) < 0)
+ if(write(c->socket, bufp, length) < 0)
{
- syslog(LOG_ERR, _("Sending meta data to %s (%s) failed: %m"), cl->name, cl->hostname);
+ syslog(LOG_ERR, _("Sending meta data to %s (%s) failed: %m"), c->name, c->hostname);
return -1;
}
cp
return 0;
}
-void broadcast_meta(connection_t *cl, char *buffer, int length)
+void broadcast_meta(connection_t *from, char *buffer, int length)
{
avl_node_t *node;
- connection_t *p;
+ connection_t *c;
cp
for(node = connection_tree->head; node; node = node->next)
{
- p = (connection_t *)node->data;
- if(p != cl && p->status.active)
- send_meta(p, buffer, length);
+ c = (connection_t *)node->data;
+ if(c != from && c->status.active)
+ send_meta(c, buffer, length);
}
cp
}
-int receive_meta(connection_t *cl)
+int receive_meta(connection_t *c)
{
int x, l = sizeof(x);
int oldlen, i;
int decrypted = 0;
char inbuf[MAXBUFSIZE];
cp
- if(getsockopt(cl->meta_socket, SOL_SOCKET, SO_ERROR, &x, &l) < 0)
+ if(getsockopt(c->socket, SOL_SOCKET, SO_ERROR, &x, &l) < 0)
{
- syslog(LOG_ERR, _("This is a bug: %s:%d: %d:%m %s (%s)"), __FILE__, __LINE__, cl->meta_socket,
- cl->name, cl->hostname);
+ syslog(LOG_ERR, _("This is a bug: %s:%d: %d:%m %s (%s)"), __FILE__, __LINE__, c->socket,
+ c->name, c->hostname);
return -1;
}
if(x)
{
syslog(LOG_ERR, _("Metadata socket error for %s (%s): %s"),
- cl->name, cl->hostname, strerror(x));
+ c->name, c->hostname, strerror(x));
return -1;
}
- If not, keep stuff in buffer and exit.
*/
- lenin = read(cl->meta_socket, cl->buffer + cl->buflen, MAXBUFSIZE - cl->buflen);
+ lenin = read(c->socket, c->buffer + c->buflen, MAXBUFSIZE - c->buflen);
if(lenin<=0)
{
{
if(debug_lvl >= DEBUG_CONNECTIONS)
syslog(LOG_NOTICE, _("Connection closed by %s (%s)"),
- cl->name, cl->hostname);
+ c->name, c->hostname);
}
else
if(errno==EINTR)
return 0;
else
syslog(LOG_ERR, _("Metadata socket read error for %s (%s): %m"),
- cl->name, cl->hostname);
+ c->name, c->hostname);
return -1;
}
- oldlen = cl->buflen;
- cl->buflen += lenin;
+ oldlen = c->buflen;
+ c->buflen += lenin;
while(lenin)
{
/* Decrypt */
- if(cl->status.decryptin && !decrypted)
+ if(c->status.decryptin && !decrypted)
{
- EVP_DecryptUpdate(cl->cipher_inctx, inbuf, &lenin, cl->buffer + oldlen, lenin);
- memcpy(cl->buffer + oldlen, inbuf, lenin);
+ EVP_DecryptUpdate(c->inctx, inbuf, &lenin, c->buffer + oldlen, lenin);
+ memcpy(c->buffer + oldlen, inbuf, lenin);
decrypted = 1;
}
/* Are we receiving a TCPpacket? */
- if(cl->tcplen)
+ if(c->tcplen)
{
- if(cl->tcplen <= cl->buflen)
+ if(c->tcplen <= c->buflen)
{
- receive_tcppacket(cl, cl->buffer, cl->tcplen);
+ receive_tcppacket(c, c->buffer, c->tcplen);
- cl->buflen -= cl->tcplen;
- lenin -= cl->tcplen;
- memmove(cl->buffer, cl->buffer + cl->tcplen, cl->buflen);
+ c->buflen -= c->tcplen;
+ lenin -= c->tcplen;
+ memmove(c->buffer, c->buffer + c->tcplen, c->buflen);
oldlen = 0;
- cl->tcplen = 0;
+ c->tcplen = 0;
continue;
}
else
reqlen = 0;
- for(i = oldlen; i < cl->buflen; i++)
+ for(i = oldlen; i < c->buflen; i++)
{
- if(cl->buffer[i] == '\n')
+ if(c->buffer[i] == '\n')
{
- cl->buffer[i] = '\0'; /* replace end-of-line by end-of-string so we can use sscanf */
+ c->buffer[i] = '\0'; /* replace end-of-line by end-of-string so we can use sscanf */
reqlen = i + 1;
break;
}
if(reqlen)
{
- if(receive_request(cl))
+ if(receive_request(c))
return -1;
- cl->buflen -= reqlen;
+ c->buflen -= reqlen;
lenin -= reqlen;
- memmove(cl->buffer, cl->buffer + reqlen, cl->buflen);
+ memmove(c->buffer, c->buffer + reqlen, c->buflen);
oldlen = 0;
continue;
}
}
}
- if(cl->buflen >= MAXBUFSIZE)
+ if(c->buflen >= MAXBUFSIZE)
{
syslog(LOG_ERR, _("Metadata read buffer overflow for %s (%s)"),
- cl->name, cl->hostname);
+ c->name, c->hostname);
return -1;
}
- cl->last_ping_time = time(NULL);
+ c->last_ping_time = time(NULL);
cp
return 0;
}
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.136 2001/10/08 13:37:30 guus Exp $
+ $Id: net.c,v 1.35.4.137 2001/10/27 12:13:17 guus Exp $
*/
#include "config.h"
#define RAND_pseudo_bytes RAND_bytes
#endif
-#ifdef HAVE_TUNTAP
- #ifdef HAVE_LINUX
- #ifdef LINUX_IF_TUN_H
- #include LINUX_IF_TUN_H
- #else
- #include <linux/if_tun.h>
- #endif
- #else
- #include <net/if_tun.h>
- #endif
-#endif
-
-#ifdef HAVE_SOLARIS
- #include <sys/sockio.h>
- #include <sys/stropts.h>
- #include <net/if_tun.h>
-#endif
-
#include <utils.h>
#include <xalloc.h>
#include <avl_tree.h>
#include "subnet.h"
#include "process.h"
#include "route.h"
+#include "device.h"
#include "system.h"
-int tap_fd = -1;
-int taptype = TAP_TYPE_ETHERTAP;
-int total_tap_in = 0;
-int total_tap_out = 0;
-int total_socket_in = 0;
-int total_socket_out = 0;
-
int seconds_till_retry = 5;
+int tcp_socket = -1;
+int udp_socket = -1;
int keylifetime = 0;
int keyexpires = 0;
-void send_udppacket(connection_t *cl, vpn_packet_t *inpkt)
+/* VPN packet I/O */
+
+void receive_udppacket(node_t *n, vpn_packet_t *inpkt)
+{
+ vpn_packet_t outpkt;
+ int outlen, outpad;
+ EVP_CIPHER_CTX ctx;
+cp
+ /* Decrypt the packet */
+
+ EVP_DecryptInit(&ctx, myself->cipher, myself->key, myself->key + myself->cipher->key_len);
+ EVP_DecryptUpdate(&ctx, outpkt.salt, &outlen, inpkt->salt, inpkt->len);
+ EVP_DecryptFinal(&ctx, outpkt.salt + outlen, &outpad);
+ outlen += outpad;
+ outpkt.len = outlen - sizeof(outpkt.salt);
+
+ receive_packet(n, &outpkt);
+cp
+}
+
+void receive_tcppacket(connection_t *c, char *buffer, int len)
+{
+ vpn_packet_t outpkt;
+cp
+ outpkt.len = len;
+ memcpy(outpkt.data, buffer, len);
+
+ receive_packet(c->node, &outpkt);
+cp
+}
+
+void receive_packet(node_t *n, vpn_packet_t *packet)
+{
+cp
+ if(debug_lvl >= DEBUG_TRAFFIC)
+ syslog(LOG_DEBUG, _("Received packet of %d bytes from %s (%s)"), packet->len, n->name, n->hostname);
+
+ route_incoming(n, packet);
+cp
+}
+
+void send_udppacket(node_t *n, vpn_packet_t *inpkt)
{
vpn_packet_t outpkt;
int outlen, outpad;
socklen_t tolen = sizeof(to);
vpn_packet_t *copy;
cp
- if(!cl->status.validkey)
+ if(!n->status.validkey)
{
if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_INFO, _("No valid key known yet for %s (%s), queueing packet"),
- cl->name, cl->hostname);
+ n->name, n->hostname);
/* Since packet is on the stack of handle_tap_input(),
we have to make a copy of it first. */
copy = xmalloc(sizeof(vpn_packet_t));
memcpy(copy, inpkt, sizeof(vpn_packet_t));
- list_insert_tail(cl->queue, copy);
+ list_insert_tail(n->queue, copy);
- if(!cl->status.waitingforkey)
- send_req_key(myself, cl);
+ if(!n->status.waitingforkey)
+ send_req_key(n->nexthop->connection, myself, n);
return;
}
RAND_pseudo_bytes(inpkt->salt, sizeof(inpkt->salt));
- EVP_EncryptInit(&ctx, cl->cipher_pkttype, cl->cipher_pktkey, cl->cipher_pktkey + cl->cipher_pkttype->key_len);
+ EVP_EncryptInit(&ctx, n->cipher, n->key, n->key + n->cipher->key_len);
EVP_EncryptUpdate(&ctx, outpkt.salt, &outlen, inpkt->salt, inpkt->len + sizeof(inpkt->salt));
EVP_EncryptFinal(&ctx, outpkt.salt + outlen, &outpad);
outlen += outpad;
- total_socket_out += outlen;
-
to.sin_family = AF_INET;
- to.sin_addr.s_addr = htonl(cl->address);
- to.sin_port = htons(cl->port);
+ to.sin_addr.s_addr = htonl(n->address);
+ to.sin_port = htons(n->port);
- if((sendto(myself->socket, (char *) outpkt.salt, outlen, 0, (const struct sockaddr *)&to, tolen)) < 0)
+ if((sendto(socket, (char *) outpkt.salt, outlen, 0, (const struct sockaddr *)&to, tolen)) < 0)
{
syslog(LOG_ERR, _("Error sending packet to %s (%s): %m"),
- cl->name, cl->hostname);
+ n->name, n->hostname);
return;
}
cp
}
-void receive_packet(connection_t *cl, vpn_packet_t *packet)
-{
-cp
- if(debug_lvl >= DEBUG_TRAFFIC)
- syslog(LOG_DEBUG, _("Received packet of %d bytes from %s (%s)"), packet->len, cl->name, cl->hostname);
-
- route_incoming(cl, packet);
-cp
-}
-
-void receive_udppacket(connection_t *cl, vpn_packet_t *inpkt)
-{
- vpn_packet_t outpkt;
- int outlen, outpad;
- EVP_CIPHER_CTX ctx;
-cp
- /* Decrypt the packet */
-
- EVP_DecryptInit(&ctx, myself->cipher_pkttype, myself->cipher_pktkey, myself->cipher_pktkey + myself->cipher_pkttype->key_len);
- EVP_DecryptUpdate(&ctx, outpkt.salt, &outlen, inpkt->salt, inpkt->len);
- EVP_DecryptFinal(&ctx, outpkt.salt + outlen, &outpad);
- outlen += outpad;
- outpkt.len = outlen - sizeof(outpkt.salt);
-
- total_socket_in += outlen;
-
- receive_packet(cl, &outpkt);
-cp
-}
-
-void receive_tcppacket(connection_t *cl, char *buffer, int len)
-{
- vpn_packet_t outpkt;
-cp
- outpkt.len = len;
- memcpy(outpkt.data, buffer, len);
-
- receive_packet(cl, &outpkt);
-cp
-}
-
-void accept_packet(vpn_packet_t *packet)
-{
-cp
- if(debug_lvl >= DEBUG_TRAFFIC)
- syslog(LOG_DEBUG, _("Writing packet of %d bytes to tap device"),
- packet->len);
-
-#ifdef HAVE_SOLARIS
- if(write(tap_fd, packet->data + 14, packet->len - 14) < 0)
- syslog(LOG_ERR, _("Can't write to tun/tap device: %m"));
- else
- total_tap_out += packet->len;
-#else
- if(taptype == TAP_TYPE_TUNTAP)
- {
- if(write(tap_fd, packet->data, packet->len) < 0)
- syslog(LOG_ERR, _("Can't write to tun/tap device: %m"));
- else
- total_tap_out += packet->len;
- }
- else /* ethertap */
- {
- if(write(tap_fd, packet->data - 2, packet->len + 2) < 0)
- syslog(LOG_ERR, _("Can't write to ethertap device: %m"));
- else
- total_tap_out += packet->len;
- }
-#endif
-cp
-}
-
/*
send a packet to the given vpn ip.
*/
-void send_packet(connection_t *cl, vpn_packet_t *packet)
+void send_packet(node_t *n, vpn_packet_t *packet)
{
- connection_t *via;
cp
if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_ERR, _("Sending packet of %d bytes to %s (%s)"),
- packet->len, cl->name, cl->hostname);
+ packet->len, n->name, n->hostname);
- if(cl == myself)
+ if(n == myself)
{
if(debug_lvl >= DEBUG_TRAFFIC)
{
return;
}
- if(!cl->status.active)
+ if(!n->status.active)
{
if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_INFO, _("%s (%s) is not active, dropping packet"),
- cl->name, cl->hostname);
+ n->name, n->hostname);
return;
}
-
- if(cl->via == myself)
- via = cl->nexthop;
+/* FIXME
+ if(n->via == myself)
+ via = n->nexthop;
else
- via = cl->via;
+ via = n->via;
- if(via != cl && debug_lvl >= DEBUG_TRAFFIC)
+ if(via != n && debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_ERR, _("Sending packet to %s via %s (%s)"),
- cl->name, via->name, via->hostname);
+ n->name, via->name, via->hostname);
if((myself->options | via->options) & OPTION_TCPONLY)
{
- if(send_tcppacket(via, packet))
- terminate_connection(via, 1);
+ if(send_tcppacket(via->connection, packet))
+ terminate_connection(via->connection, 1);
}
else
send_udppacket(via, packet);
+*/
}
/* Broadcast a packet to all active direct connections */
-void broadcast_packet(connection_t *from, vpn_packet_t *packet)
+void broadcast_packet(node_t *from, vpn_packet_t *packet)
{
avl_node_t *node;
- connection_t *cl;
+ connection_t *c;
cp
if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_INFO, _("Broadcasting packet of %d bytes from %s (%s)"),
for(node = connection_tree->head; node; node = node->next)
{
- cl = (connection_t *)node->data;
- if(cl->status.active && cl != from)
- send_packet(cl, packet);
+ c = (connection_t *)node->data;
+ if(c->status.active && c != from->nexthop->connection)
+ send_packet(c->node, packet);
}
cp
}
-void flush_queue(connection_t *cl)
+void flush_queue(node_t *n)
{
list_node_t *node, *next;
cp
if(debug_lvl >= DEBUG_TRAFFIC)
- syslog(LOG_INFO, _("Flushing queue for %s (%s)"), cl->name, cl->hostname);
+ syslog(LOG_INFO, _("Flushing queue for %s (%s)"), n->name, n->hostname);
- for(node = cl->queue->head; node; node = next)
+ for(node = n->queue->head; node; node = next)
{
next = node->next;
- send_udppacket(cl, (vpn_packet_t *)node->data);
- list_delete_node(cl->queue, node);
+ send_udppacket(n, (vpn_packet_t *)node->data);
+ list_delete_node(n->queue, node);
}
cp
}
-/*
- open the local ethertap device
-*/
-int setup_tap_fd(void)
-{
- int nfd;
- const char *tapfname;
- config_t const *cfg;
-#ifdef HAVE_LINUX
-# ifdef HAVE_TUNTAP
- struct ifreq ifr;
-# endif
-#endif
-#ifdef HAVE_SOLARIS
- int ip_fd = -1, if_fd = -1;
- int ppa;
- char *ptr;
-#endif
-
-cp
- if((cfg = get_config_val(config, config_tapdevice)))
- tapfname = cfg->data.ptr;
- else
- {
-#ifdef HAVE_LINUX
-# ifdef HAVE_TUNTAP
- tapfname = "/dev/net/tun";
-# else
- tapfname = "/dev/tap0";
-# endif
-#endif
-#ifdef HAVE_FREEBSD
- tapfname = "/dev/tap0";
-#endif
-#ifdef HAVE_SOLARIS
- tapfname = "/dev/tun";
-#endif
- }
-cp
- if((nfd = open(tapfname, O_RDWR | O_NONBLOCK)) < 0)
- {
- syslog(LOG_ERR, _("Could not open %s: %m"), tapfname);
- return -1;
- }
-cp
- tap_fd = nfd;
-
- /* Set default MAC address for ethertap devices */
-
- mymac.type = SUBNET_MAC;
- mymac.net.mac.address.x[0] = 0xfe;
- mymac.net.mac.address.x[1] = 0xfd;
- mymac.net.mac.address.x[2] = 0x00;
- mymac.net.mac.address.x[3] = 0x00;
- mymac.net.mac.address.x[4] = 0x00;
- mymac.net.mac.address.x[5] = 0x00;
+/* Setup sockets */
-#ifdef HAVE_LINUX
- #ifdef HAVE_TUNTAP
- /* Ok now check if this is an old ethertap or a new tun/tap thingie */
- memset(&ifr, 0, sizeof(ifr));
-cp
- ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
- if (netname)
- strncpy(ifr.ifr_name, netname, IFNAMSIZ);
-cp
- if (!ioctl(tap_fd, TUNSETIFF, (void *) &ifr))
- {
- syslog(LOG_INFO, _("%s is a Linux tun/tap device"), tapfname);
- taptype = TAP_TYPE_TUNTAP;
- }
- else
- if (!ioctl(tap_fd, (('T'<< 8) | 202), (void *) &ifr))
- {
- syslog(LOG_INFO, _("%s is a Linux tun/tap device"), tapfname);
- syslog(LOG_WARNING, _("Old ioctl() request used"));
- taptype = TAP_TYPE_TUNTAP;
- }
- else
- #endif
- {
- syslog(LOG_INFO, _("%s is a Linux ethertap device"), tapfname);
- taptype = TAP_TYPE_ETHERTAP;
- }
-#endif
-#ifdef HAVE_FREEBSD
- syslog(LOG_INFO, _("%s is a FreeBSD tap device"), tapfname);
- taptype = TAP_TYPE_TUNTAP;
-#endif
-#ifdef HAVE_SOLARIS
- ppa = 0;
-
- ptr = tapfname;
- while(*ptr && !isdigit((int)*ptr)) ptr++;
- ppa = atoi(ptr);
-
- if( (ip_fd = open("/dev/ip", O_RDWR, 0)) < 0){
- syslog(LOG_ERR, _("Could not open /dev/ip: %m"));
- return -1;
- }
-
- /* Assign a new PPA and get its unit number. */
- if( (ppa = ioctl(nfd, TUNNEWPPA, ppa)) < 0){
- syslog(LOG_ERR, _("Can't assign new interface: %m"));
- return -1;
- }
-
- if( (if_fd = open(tapfname, O_RDWR, 0)) < 0){
- syslog(LOG_ERR, _("Could not open %s twice: %m"), tapfname);
- return -1;
- }
-
- if(ioctl(if_fd, I_PUSH, "ip") < 0){
- syslog(LOG_ERR, _("Can't push IP module: %m"));
- return -1;
- }
-
- /* Assign ppa according to the unit number returned by tun device */
- if(ioctl(if_fd, IF_UNITSEL, (char *)&ppa) < 0){
- syslog(LOG_ERR, _("Can't set PPA %d: %m"), ppa);
- return -1;
- }
-
- if(ioctl(ip_fd, I_LINK, if_fd) < 0){
- syslog(LOG_ERR, _("Can't link TUN device to IP: %m"));
- return -1;
- }
-
- syslog(LOG_INFO, _("%s is a Solaris tun device"), tapfname);
-#endif
-
-cp
- return 0;
-}
-
-/*
- set up the socket that we listen on for incoming
- (tcp) connections
-*/
-int setup_listen_meta_socket(int port)
+int setup_listen_socket(int port)
{
int nfd, flags;
struct sockaddr_in a;
int option;
- config_t const *cfg;
+ char *interface;
+ char *address;
+ ip_mask_t *ipmask;
cp
if((nfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
{
option = IPTOS_LOWDELAY;
setsockopt(nfd, SOL_IP, IP_TOS, &option, sizeof(option));
- if((cfg = get_config_val(config, config_interface)))
- {
- if(setsockopt(nfd, SOL_SOCKET, SO_BINDTODEVICE, cfg->data.ptr, strlen(cfg->data.ptr)))
- {
- close(nfd);
- syslog(LOG_ERR, _("Unable to bind listen socket to interface %s: %m"), cfg->data.ptr);
- return -1;
- }
- }
+ if(get_config_string(lookup_config(config_tree, "BindToInterface"), &interface))
+ if(setsockopt(nfd, SOL_SOCKET, SO_BINDTODEVICE, interface, strlen(interface)))
+ {
+ close(nfd);
+ syslog(LOG_ERR, _("Can't bind to interface %s: %m"), interface);
+ return -1;
+ }
#endif
memset(&a, 0, sizeof(a));
a.sin_family = AF_INET;
+ a.sin_addr.s_addr = htonl(INADDR_ANY);
a.sin_port = htons(port);
- if((cfg = get_config_val(config, config_interfaceip)))
- a.sin_addr.s_addr = htonl(cfg->data.ip->address);
- else
- a.sin_addr.s_addr = htonl(INADDR_ANY);
+ if(get_config_string(lookup_config(config_tree, "BindToAddress"), &address))
+ {
+ ipmask = strtoip(address);
+ if(ipmask)
+ {
+ a.sin_addr.s_addr = htonl(ipmask->address);
+ free(ipmask);
+ }
+ }
if(bind(nfd, (struct sockaddr *)&a, sizeof(struct sockaddr)))
{
return nfd;
}
-/*
- setup the socket for incoming encrypted
- data (the udp part)
-*/
int setup_vpn_in_socket(int port)
{
int nfd, flags;
return nfd;
}
-/*
- setup an outgoing meta (tcp) socket
-*/
-int setup_outgoing_meta_socket(connection_t *cl)
+int setup_outgoing_socket(connection_t *c)
{
int flags;
struct sockaddr_in a;
- config_t const *cfg;
int option;
cp
if(debug_lvl >= DEBUG_CONNECTIONS)
- syslog(LOG_INFO, _("Trying to connect to %s"), cl->hostname);
+ syslog(LOG_INFO, _("Trying to connect to %s (%s)"), c->name, c->hostname);
- if((cfg = get_config_val(cl->config, config_port)) == NULL)
- cl->port = 655;
- else
- cl->port = cfg->data.val;
+ c->socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
- cl->meta_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
- if(cl->meta_socket == -1)
+ if(c->socket == -1)
{
syslog(LOG_ERR, _("Creating socket for %s port %d failed: %m"),
- cl->hostname, cl->port);
+ c->hostname, c->port);
return -1;
}
- /* Bind first to get a fix on our source port */
+ /* 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)))
+ if(bind(c->socket, (struct sockaddr *)&a, sizeof(struct sockaddr)))
{
- close(cl->meta_socket);
+ close(c->socket);
syslog(LOG_ERR, _("System call `%s' failed: %m"), "bind");
return -1;
}
- /* Optimize TCP settings */
+ */
+
+ /* Optimize TCP settings?
option = 1;
- setsockopt(cl->meta_socket, SOL_SOCKET, SO_KEEPALIVE, &option, sizeof(option));
+ setsockopt(c->socket, SOL_SOCKET, SO_KEEPALIVE, &option, sizeof(option));
#ifdef HAVE_LINUX
- setsockopt(cl->meta_socket, SOL_TCP, TCP_NODELAY, &option, sizeof(option));
+ setsockopt(c->socket, SOL_TCP, TCP_NODELAY, &option, sizeof(option));
option = IPTOS_LOWDELAY;
- setsockopt(cl->meta_socket, SOL_IP, IP_TOS, &option, sizeof(option));
+ setsockopt(c->socket, SOL_IP, IP_TOS, &option, sizeof(option));
#endif
+
+ */
+
/* Connect */
a.sin_family = AF_INET;
- a.sin_port = htons(cl->port);
- a.sin_addr.s_addr = htonl(cl->address);
+ a.sin_port = htons(c->port);
+ a.sin_addr.s_addr = htonl(c->address);
- if(connect(cl->meta_socket, (struct sockaddr *)&a, sizeof(a)) == -1)
+ if(connect(c->socket, (struct sockaddr *)&a, sizeof(a)) == -1)
{
- close(cl->meta_socket);
- syslog(LOG_ERR, _("%s port %hd: %m"), cl->hostname, cl->port);
+ close(c->socket);
+ syslog(LOG_ERR, _("%s port %hd: %m"), c->hostname, c->port);
return -1;
}
- flags = fcntl(cl->meta_socket, F_GETFL);
- if(fcntl(cl->meta_socket, F_SETFL, flags | O_NONBLOCK) < 0)
+ flags = fcntl(c->socket, F_GETFL);
+
+ if(fcntl(c->socket, F_SETFL, flags | O_NONBLOCK) < 0)
{
- close(cl->meta_socket);
+ close(c->socket);
syslog(LOG_ERR, _("fcntl for %s port %d: %m"),
- cl->hostname, cl->port);
+ c->hostname, c->port);
return -1;
}
if(debug_lvl >= DEBUG_CONNECTIONS)
syslog(LOG_INFO, _("Connected to %s port %hd"),
- cl->hostname, cl->port);
-
- cl->status.meta = 1;
+ c->hostname, c->port);
cp
return 0;
}
-/*
- Setup an outgoing meta connection.
-*/
int setup_outgoing_connection(char *name)
{
- connection_t *ncn, *old;
+ connection_t *c;
struct hostent *h;
- config_t const *cfg;
cp
- if(check_id(name))
- {
- syslog(LOG_ERR, _("Invalid name for outgoing connection"));
- return -1;
- }
-
- /* Make sure we don't make an outgoing connection to a host that is already in our connection list */
+ c = new_connection();
+ c->name = xstrdup(name);
- if((old = lookup_id(name)))
- {
- if(!old->status.outgoing)
- {
- if(debug_lvl >= DEBUG_CONNECTIONS)
- syslog(LOG_NOTICE, _("We are already connected to %s."), name);
-
- old->status.outgoing = 1;
- }
- return 0;
- }
-
- ncn = new_connection();
- asprintf(&ncn->name, "%s", name);
-
- if(read_host_config(ncn))
+ read_connection_config(c);
+
+ if(!get_config_string(lookup_config(c->config_tree, "Address"), &c->hostname))
{
- syslog(LOG_ERR, _("Error reading host configuration file for %s"), ncn->name);
- free_connection(ncn);
+ syslog(LOG_ERR, _("No address specified for %s"), c->name);
+ free_connection(c);
return -1;
}
- if(!(cfg = get_config_val(ncn->config, config_address)))
+ if(!get_config_port(lookup_config(c->config_tree, "Port"), &c->port))
{
- syslog(LOG_ERR, _("No address specified for %s"), ncn->name);
- free_connection(ncn);
+ syslog(LOG_ERR, _("No port specified for %s"), c->name);
+ free_connection(c);
return -1;
}
- if(!(h = gethostbyname(cfg->data.ptr)))
+ if(!(h = gethostbyname(c->hostname)))
{
- syslog(LOG_ERR, _("Error looking up `%s': %m"), cfg->data.ptr);
- free_connection(ncn);
+ syslog(LOG_ERR, _("Error looking up `%s': %m"), c->hostname);
+ free_connection(c);
return -1;
}
- ncn->address = ntohl(*((ipv4_t*)(h->h_addr_list[0])));
- ncn->hostname = hostlookup(htonl(ncn->address));
+ c->address = ntohl(*((ipv4_t*)(h->h_addr_list[0])));
+ c->hostname = hostlookup(htonl(c->address));
- if(setup_outgoing_meta_socket(ncn) < 0)
+ if(setup_outgoing_socket(c) < 0)
{
- syslog(LOG_ERR, _("Could not set up a meta connection to %s"),
- ncn->hostname);
- free_connection(ncn);
+ syslog(LOG_ERR, _("Could not set up a meta connection to %s (%s)"),
+ c->name, c->hostname);
+ free_connection(c);
return -1;
}
- ncn->status.outgoing = 1;
- ncn->buffer = xmalloc(MAXBUFSIZE);
- ncn->buflen = 0;
- ncn->last_ping_time = time(NULL);
+ c->status.outgoing = 1;
+ c->last_ping_time = time(NULL);
- connection_add(ncn);
+ connection_add(c);
- send_id(ncn);
+ send_id(c);
cp
return 0;
}
-int read_rsa_public_key(connection_t *cl)
+int read_rsa_public_key(connection_t *c)
{
- config_t const *cfg;
FILE *fp;
char *fname;
+ char *key;
void *result;
cp
- if(!cl->rsa_key)
- cl->rsa_key = RSA_new();
+ if(!c->rsa_key)
+ c->rsa_key = RSA_new();
/* First, check for simple PublicKey statement */
- if((cfg = get_config_val(cl->config, config_publickey)))
+ if(get_config_string(lookup_config(c->config_tree, "PublicKey"), &key))
{
- BN_hex2bn(&cl->rsa_key->n, cfg->data.ptr);
- BN_hex2bn(&cl->rsa_key->e, "FFFF");
+ BN_hex2bn(&c->rsa_key->n, key);
+ BN_hex2bn(&c->rsa_key->e, "FFFF");
return 0;
}
/* Else, check for PublicKeyFile statement and read it */
- if((cfg = get_config_val(cl->config, config_publickeyfile)))
+ if(get_config_string(lookup_config(c->config_tree, "PublicKeyFile"), &fname))
{
- if(is_safe_path(cfg->data.ptr))
+ if(is_safe_path(fname))
{
- if((fp = fopen(cfg->data.ptr, "r")) == NULL)
+ if((fp = fopen(fname, "r")) == NULL)
{
syslog(LOG_ERR, _("Error reading RSA public key file `%s': %m"),
- cfg->data.ptr);
+ fname);
return -1;
}
- result = PEM_read_RSAPublicKey(fp, &cl->rsa_key, NULL, NULL);
+ result = PEM_read_RSAPublicKey(fp, &c->rsa_key, NULL, NULL);
fclose(fp);
if(!result)
{
syslog(LOG_ERR, _("Reading RSA public key file `%s' failed: %m"),
- cfg->data.ptr);
+ fname);
return -1;
}
return 0;
/* Else, check if a harnessed public key is in the config file */
- asprintf(&fname, "%s/hosts/%s", confbase, cl->name);
+ result = NULL;
+
+ asprintf(&fname, "%s/hosts/%s", confbase, c->name);
if((fp = fopen(fname, "r")))
{
- result = PEM_read_RSAPublicKey(fp, &cl->rsa_key, NULL, NULL);
+ result = PEM_read_RSAPublicKey(fp, &c->rsa_key, NULL, NULL);
fclose(fp);
free(fname);
- if(result)
- return 0;
}
free(fname);
- /* Nothing worked. */
-
- syslog(LOG_ERR, _("No public key for %s specified!"), cl->name);
-cp
- return -1;
+ if(result)
+ return 0;
+ else
+ {
+ syslog(LOG_ERR, _("No public key for %s specified!"), c->name);
+ return -1;
+ }
}
int read_rsa_private_key(void)
{
- config_t const *cfg;
FILE *fp;
void *result;
+ char *fname, *key;
cp
- if(!myself->rsa_key)
- myself->rsa_key = RSA_new();
+ if(!myself->connection->rsa_key)
+ myself->connection->rsa_key = RSA_new();
- if((cfg = get_config_val(config, config_privatekey)))
+ if(get_config_string(lookup_config(config_tree, "PrivateKey"), &key))
{
- BN_hex2bn(&myself->rsa_key->d, cfg->data.ptr);
- BN_hex2bn(&myself->rsa_key->e, "FFFF");
+ BN_hex2bn(&myself->connection->rsa_key->d, key);
+ BN_hex2bn(&myself->connection->rsa_key->e, "FFFF");
}
- else if((cfg = get_config_val(config, config_privatekeyfile)))
+ else if(get_config_string(lookup_config(config_tree, "PrivateKeyFile"), &fname))
{
- if((fp = fopen(cfg->data.ptr, "r")) == NULL)
+ if((fp = fopen(fname, "r")) == NULL)
{
syslog(LOG_ERR, _("Error reading RSA private key file `%s': %m"),
- cfg->data.ptr);
+ fname);
return -1;
}
- result = PEM_read_RSAPrivateKey(fp, &myself->rsa_key, NULL, NULL);
+ result = PEM_read_RSAPrivateKey(fp, &myself->connection->rsa_key, NULL, NULL);
fclose(fp);
if(!result)
{
syslog(LOG_ERR, _("Reading RSA private key file `%s' failed: %m"),
- cfg->data.ptr);
+ fname);
return -1;
}
}
}
/*
- Configure connection_t myself and set up the local sockets (listen only)
+ Configure node_t myself and set up the local sockets (listen only)
*/
int setup_myself(void)
{
- config_t const *cfg;
- config_t *next;
- subnet_t *net;
+ config_t *cfg;
+ subnet_t *subnet;
+ char *name, *mode;
+ int choice;
cp
- myself = new_connection();
+ myself = new_node();
+ myself->connection = new_connection();
asprintf(&myself->hostname, _("MYSELF"));
- myself->options = 0;
- myself->protocol_version = PROT_CURRENT;
+ asprintf(&myself->connection->hostname, _("MYSELF"));
- if(!(cfg = get_config_val(config, config_name))) /* Not acceptable */
+ myself->connection->options = 0;
+ myself->connection->protocol_version = PROT_CURRENT;
+
+ if(!get_config_string(lookup_config(config_tree, "Name"), &name)) /* Not acceptable */
{
syslog(LOG_ERR, _("Name for tinc daemon required!"));
return -1;
}
- else
- asprintf(&myself->name, "%s", (char*)cfg->data.val);
- if(check_id(myself->name))
+ if(check_id(name))
{
syslog(LOG_ERR, _("Invalid name for myself!"));
+ free(name);
return -1;
}
+
+ myself->name = name;
+ myself->connection->name = xstrdup(name);
+
cp
if(read_rsa_private_key())
return -1;
- if(read_host_config(myself))
+ if(read_connection_config(myself->connection))
{
syslog(LOG_ERR, _("Cannot open host configuration file for myself!"));
return -1;
}
- if(read_rsa_public_key(myself))
+ if(read_rsa_public_key(myself->connection))
return -1;
cp
/*
- if(RSA_check_key(myself->rsa_key) != 1)
+ if(RSA_check_key(rsa_key) != 1)
{
syslog(LOG_ERR, _("Invalid public/private keypair!"));
return -1;
}
*/
- if(!(cfg = get_config_val(myself->config, config_port)))
+ if(!get_config_port(lookup_config(myself->connection->config_tree, "Port"), &myself->connection->port))
myself->port = 655;
- else
- myself->port = cfg->data.val;
/* Read in all the subnets specified in the host configuration file */
- for(next = myself->config; (cfg = get_config_val(next, config_subnet)); next = cfg->next)
- {
- net = new_subnet();
- net->type = SUBNET_IPV4;
- net->net.ipv4.address = cfg->data.ip->address;
- net->net.ipv4.mask = cfg->data.ip->mask;
+ cfg = lookup_config(myself->connection->config_tree, "Subnet");
- /* Teach newbies what subnets are... */
+ while(cfg)
+ {
+ if(!get_config_subnet(cfg, &subnet))
+ return -1;
- if((net->net.ipv4.address & net->net.ipv4.mask) != net->net.ipv4.address)
- {
- syslog(LOG_ERR, _("Network address and subnet mask do not match!"));
- return -1;
- }
+ subnet_add(myself, subnet);
- subnet_add(myself, net);
+ cfg = lookup_config_next(myself->connection->config_tree, cfg);
}
cp
/* Check some options */
- if((cfg = get_config_val(config, config_indirectdata)))
- if(cfg->data.val == stupid_true)
+ if(get_config_bool(lookup_config(config_tree, "IndirectData"), &choice))
+ if(choice)
myself->options |= OPTION_INDIRECT;
- if((cfg = get_config_val(config, config_tcponly)))
- if(cfg->data.val == stupid_true)
+ if(get_config_bool(lookup_config(config_tree, "TCPOnly"), &choice))
+ if(choice)
myself->options |= OPTION_TCPONLY;
- if((cfg = get_config_val(myself->config, config_indirectdata)))
- if(cfg->data.val == stupid_true)
+ if(get_config_bool(lookup_config(myself->connection->config_tree, "IndirectData"), &choice))
+ if(choice)
myself->options |= OPTION_INDIRECT;
- if((cfg = get_config_val(myself->config, config_tcponly)))
- if(cfg->data.val == stupid_true)
+ if(get_config_bool(lookup_config(myself->connection->config_tree, "TCPOnly"), &choice))
+ if(choice)
myself->options |= OPTION_TCPONLY;
if(myself->options & OPTION_TCPONLY)
myself->options |= OPTION_INDIRECT;
- if((cfg = get_config_val(config, config_mode)))
+ if(get_config_string(lookup_config(myself->connection->config_tree, "Mode"), &mode))
{
- if(!strcasecmp(cfg->data.ptr, "router"))
+ if(!strcasecmp(mode, "router"))
routing_mode = RMODE_ROUTER;
- else if (!strcasecmp(cfg->data.ptr, "switch"))
+ else if (!strcasecmp(mode, "switch"))
routing_mode = RMODE_SWITCH;
- else if (!strcasecmp(cfg->data.ptr, "hub"))
+ else if (!strcasecmp(mode, "hub"))
routing_mode = RMODE_HUB;
else
{
cp
/* Open sockets */
- if((myself->meta_socket = setup_listen_meta_socket(myself->port)) < 0)
+ if((tcp_socket = setup_listen_socket(myself->port)) < 0)
{
syslog(LOG_ERR, _("Unable to set up a listening TCP socket!"));
return -1;
}
- if((myself->socket = setup_vpn_in_socket(myself->port)) < 0)
+ if((udp_socket = setup_vpn_in_socket(myself->port)) < 0)
{
syslog(LOG_ERR, _("Unable to set up a listening UDP socket!"));
return -1;
cp
/* Generate packet encryption key */
- myself->cipher_pkttype = EVP_bf_cbc();
+ myself->cipher = EVP_bf_cbc();
- myself->cipher_pktkeylength = myself->cipher_pkttype->key_len + myself->cipher_pkttype->iv_len;
+ myself->keylength = myself->cipher->key_len + myself->cipher->iv_len;
- myself->cipher_pktkey = (char *)xmalloc(myself->cipher_pktkeylength);
- RAND_pseudo_bytes(myself->cipher_pktkey, myself->cipher_pktkeylength);
+ myself->key = (char *)xmalloc(myself->keylength);
+ RAND_pseudo_bytes(myself->key, myself->keylength);
- if(!(cfg = get_config_val(config, config_keyexpire)))
+ if(!get_config_int(lookup_config(myself->connection->config_tree, "KeyExpire"), &keylifetime))
keylifetime = 3600;
- else
- keylifetime = cfg->data.val;
keyexpires = time(NULL) + keylifetime;
cp
/* Done */
myself->nexthop = myself;
- myself->prevhop = myself;
myself->via = myself;
myself->status.active = 1;
- id_add(myself);
+ node_add(myself);
syslog(LOG_NOTICE, _("Ready: listening on port %hd"), myself->port);
cp
return 0;
}
-void randomized_alarm(int seconds)
-{
- unsigned char r;
- RAND_pseudo_bytes(&r, 1);
- alarm((seconds * (int)r) / 128 + 1);
-}
-
-RETSIGTYPE
-try_outgoing_connections(int a)
-{
- config_t const *cfg;
- int retry = 0;
-cp
- cfg = get_config_val(config, config_connectto);
-
- while(cfg)
- {
- if(setup_outgoing_connection(cfg->data.ptr)) /* function returns 0 when there are no problems */
- retry = 1;
- cfg = get_config_val(cfg->next, config_connectto); /* Or else we try the next ConnectTo line */
- }
-
- if(retry)
- {
- seconds_till_retry += 5;
- if(seconds_till_retry > MAXTIMEOUT) /* Don't wait more than MAXTIMEOUT seconds. */
- seconds_till_retry = MAXTIMEOUT;
-
- syslog(LOG_ERR, _("Failed to setup all outgoing connections, will retry in %d seconds"),
- seconds_till_retry);
-
- /* Randomize timeout to avoid global synchronisation effects */
- randomized_alarm(seconds_till_retry);
- }
- else
- {
- seconds_till_retry = 5;
- }
-cp
-}
-
/*
setup all initial network connections
*/
int setup_network_connections(void)
{
- config_t const *cfg;
cp
init_connections();
init_subnets();
- if((cfg = get_config_val(config, config_pingtimeout)) == NULL)
- timeout = 60;
- else
+ if(get_config_int(lookup_config(myself->connection->config_tree, "PingTimeout"), &timeout))
{
- timeout = cfg->data.val;
if(timeout < 1)
{
timeout = 86400;
}
- }
+ }
+ else
+ timeout = 60;
- if(setup_tap_fd() < 0)
+ if(setup_device() < 0)
return -1;
/* Run tinc-up script to further initialize the tap interface */
void close_network_connections(void)
{
avl_node_t *node, *next;
- connection_t *p;
+ connection_t *c;
cp
for(node = connection_tree->head; node; node = next)
{
next = node->next;
- p = (connection_t *)node->data;
- p->status.outgoing = 0;
- terminate_connection(p, 0);
+ c = (connection_t *)node->data;
+ c->status.outgoing = 0;
+ terminate_connection(c, 0);
}
- terminate_connection(myself, 0);
+// terminate_connection(myself, 0);
- destroy_trees();
+// destroy_trees();
execute_script("tinc-down");
- close(tap_fd);
+ close_device();
cp
return;
}
*/
connection_t *create_new_connection(int sfd)
{
- connection_t *p;
+ connection_t *c;
struct sockaddr_in ci;
int len = sizeof(ci);
cp
- p = new_connection();
+ c = new_connection();
if(getpeername(sfd, (struct sockaddr *) &ci, (socklen_t *) &len) < 0)
{
return NULL;
}
- asprintf(&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);
- p->buflen = 0;
- p->last_ping_time = time(NULL);
+ c->address = ntohl(ci.sin_addr.s_addr);
+ c->hostname = hostlookup(ci.sin_addr.s_addr);
+ c->port = htons(ci.sin_port); /* This one will be overwritten later */
+ c->socket = sfd;
+ c->last_ping_time = time(NULL);
if(debug_lvl >= DEBUG_CONNECTIONS)
syslog(LOG_NOTICE, _("Connection from %s port %d"),
- p->hostname, htons(ci.sin_port));
+ c->hostname, htons(ci.sin_port));
- p->allow_request = ID;
+ c->allow_request = ID;
cp
- return p;
+ return c;
}
/*
void build_fdset(fd_set *fs)
{
avl_node_t *node;
- connection_t *p;
+ connection_t *c;
cp
FD_ZERO(fs);
- FD_SET(myself->socket, fs);
-
for(node = connection_tree->head; node; node = node->next)
{
- p = (connection_t *)node->data;
- FD_SET(p->meta_socket, fs);
+ c = (connection_t *)node->data;
+ FD_SET(c->socket, fs);
}
- FD_SET(myself->meta_socket, fs);
- FD_SET(tap_fd, fs);
+ FD_SET(tcp_socket, fs);
+ FD_SET(udp_socket, fs);
+ FD_SET(device_fd, fs);
cp
}
int x, l = sizeof(x);
struct sockaddr_in from;
socklen_t fromlen = sizeof(from);
- connection_t *cl;
+ node_t *n;
cp
- if(getsockopt(myself->socket, SOL_SOCKET, SO_ERROR, &x, &l) < 0)
+ if(getsockopt(udp_socket, SOL_SOCKET, SO_ERROR, &x, &l) < 0)
{
syslog(LOG_ERR, _("This is a bug: %s:%d: %d:%m"),
- __FILE__, __LINE__, myself->socket);
+ __FILE__, __LINE__, udp_socket);
return;
}
if(x)
return;
}
- if((pkt.len = recvfrom(myself->socket, (char *) pkt.salt, MTU, 0, (struct sockaddr *)&from, &fromlen)) <= 0)
+ if((pkt.len = recvfrom(udp_socket, (char *) pkt.salt, MTU, 0, (struct sockaddr *)&from, &fromlen)) <= 0)
{
syslog(LOG_ERR, _("Receiving packet failed: %m"));
return;
}
- cl = lookup_active(ntohl(from.sin_addr.s_addr), ntohs(from.sin_port));
+ n = lookup_node_udp(ntohl(from.sin_addr.s_addr), ntohs(from.sin_port));
- if(!cl)
+ if(!n)
{
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;
}
-
- cl->last_ping_time = time(NULL);
-
- receive_udppacket(cl, &pkt);
+/*
+ if(n->connection)
+ n->connection->last_ping_time = time(NULL);
+*/
+ receive_udppacket(n, &pkt);
cp
}
- Since it might still be referenced, put it on the prune list.
- If report == 1, then send DEL_HOST messages to the other tinc daemons.
*/
-void terminate_connection(connection_t *cl, int report)
+void terminate_connection(connection_t *c, int report)
{
- connection_t *p;
- subnet_t *subnet;
- avl_node_t *node, *next;
-cp
- if(cl->status.remove)
- return;
- else
- cl->status.remove = 1;
-
- if(cl->socket)
- close(cl->socket);
- if(cl->meta_socket)
- close(cl->meta_socket);
-
- connection_del(cl);
-
- if(cl->status.meta)
- {
- if(debug_lvl >= DEBUG_CONNECTIONS)
- syslog(LOG_NOTICE, _("Closing connection with %s (%s)"),
- cl->name, cl->hostname);
-
- if(cl->status.active)
- {
- /* Find all connections that were lost because they were behind cl
- (the connection that was dropped). */
-
- for(node = active_tree->head; node; node = next)
- {
- next = node->next;
- p = (connection_t *)node->data;
- if(p->nexthop == cl)
- terminate_connection(p, report);
- }
- }
- }
-
- /* Inform others of termination if needed */
-
- if(report)
- for(node = connection_tree->head; node; node = node->next)
- {
- p = (connection_t *)node->data;
- if(p->status.active)
- send_del_host(p, cl); /* Sounds like recursion, but p does not have a meta connection :) */
- }
-
- /* Remove the associated subnets */
-
- for(node = cl->subnet_tree->head; node; node = next)
- {
- next = node->next;
- subnet = (subnet_t *)node->data;
- subnet_del(subnet);
- }
-
- /* Check if this was our outgoing connection */
-
- if(cl->status.outgoing)
- {
- cl->status.outgoing = 0;
- signal(SIGALRM, try_outgoing_connections);
- alarm(seconds_till_retry);
- syslog(LOG_NOTICE, _("Trying to re-establish outgoing connection in %d seconds"), seconds_till_retry);
- }
-cp
- /* Schedule it for pruning */
-
- prune_add(cl);
+ /* Needs a serious rewrite. */
}
/*
{
time_t now;
avl_node_t *node, *next;
- connection_t *cl;
+ connection_t *c;
cp
now = time(NULL);
for(node = connection_tree->head; node; node = next)
{
next = node->next;
- cl = (connection_t *)node->data;
- if(cl->last_ping_time + timeout < now)
+ c = (connection_t *)node->data;
+ if(c->last_ping_time + timeout < now)
{
- if(cl->status.active)
+ if(c->status.active)
{
- if(cl->status.pinged)
+ if(c->status.pinged)
{
if(debug_lvl >= DEBUG_PROTOCOL)
syslog(LOG_INFO, _("%s (%s) didn't respond to PING"),
- cl->name, cl->hostname);
- cl->status.timeout = 1;
- terminate_connection(cl, 1);
+ c->name, c->hostname);
+ c->status.timeout = 1;
+ terminate_connection(c, 1);
}
else
{
- send_ping(cl);
+ send_ping(c);
}
}
else
{
if(debug_lvl >= DEBUG_CONNECTIONS)
syslog(LOG_WARNING, _("Timeout from %s (%s) during authentication"),
- cl->name, cl->hostname);
- terminate_connection(cl, 0);
+ c->name, c->hostname);
+ terminate_connection(c, 0);
}
}
}
*/
int handle_new_meta_connection()
{
- connection_t *ncn;
+ connection_t *new;
struct sockaddr client;
- int nfd, len = sizeof(client);
+ int fd, len = sizeof(client);
cp
- if((nfd = accept(myself->meta_socket, &client, &len)) < 0)
+ if((fd = accept(tcp_socket, &client, &len)) < 0)
{
syslog(LOG_ERR, _("Accepting a new connection failed: %m"));
return -1;
}
- if(!(ncn = create_new_connection(nfd)))
+ if(!(new = create_new_connection(fd)))
{
- shutdown(nfd, 2);
- close(nfd);
+ shutdown(fd, 2);
+ close(fd);
syslog(LOG_NOTICE, _("Closed attempted connection"));
return 0;
}
- connection_add(ncn);
+ connection_add(new);
- send_id(ncn);
+ send_id(new);
cp
return 0;
}
-/*
- check all connections to see if anything
- happened on their sockets
+void randomized_alarm(int seconds)
+{
+ unsigned char r;
+ RAND_pseudo_bytes(&r, 1);
+ alarm((seconds * (int)r) / 128 + 1);
+}
+
+/* This function is severely fucked up.
+ We want to redesign it so the following rules apply:
+
+ - Try all ConnectTo's in a row:
+ - if a connect() fails, try next one immediately,
+ - if it works, wait 5 seconds or so.
+ - If none of them were succesful, increase delay and retry.
+ - If all were succesful, don't try anymore.
*/
-void check_network_activity(fd_set *f)
+
+RETSIGTYPE
+try_outgoing_connections(int a)
{
- connection_t *p;
- avl_node_t *node;
+ static config_t *cfg = NULL;
+ static int retry = 0;
+ char *name;
+ int maxtimeout = 900;
cp
- if(FD_ISSET(myself->socket, f))
- handle_incoming_vpn_data();
+ if(!cfg)
+ cfg = lookup_config(config_tree, "ConnectTo");
- for(node = connection_tree->head; node; node = node->next)
+ if(!cfg)
+ return;
+
+ while(cfg)
{
- p = (connection_t *)node->data;
+ get_config_string(cfg, &name);
+ cfg = lookup_config_next(config_tree, cfg); /* Next time skip to next ConnectTo line */
- if(p->status.remove)
- return;
+ if(!setup_outgoing_connection(name)) /* function returns 0 when there are no problems */
+ retry = 1;
- if(FD_ISSET(p->meta_socket, f))
- if(receive_meta(p) < 0)
- {
- terminate_connection(p, p->status.active);
- return;
- }
}
- if(FD_ISSET(myself->meta_socket, f))
- handle_new_meta_connection();
+ get_config_int(lookup_config(config_tree, "MaxTimeout"), &maxtimeout);
+
+ if(retry)
+ {
+ seconds_till_retry += 5;
+ if(seconds_till_retry > maxtimeout) /* Don't wait more than MAXTIMEOUT seconds. */
+ seconds_till_retry = maxtimeout;
+
+ syslog(LOG_ERR, _("Failed to setup all outgoing connections, will retry in %d seconds"),
+ seconds_till_retry);
+
+ /* Randomize timeout to avoid global synchronisation effects */
+ randomized_alarm(seconds_till_retry);
+ }
+ else
+ {
+ seconds_till_retry = 5;
+ }
cp
}
/*
- read, encrypt and send data that is
- available through the ethertap device
+ check all connections to see if anything
+ happened on their sockets
*/
-void handle_tap_input(void)
+void check_network_activity(fd_set *f)
{
- vpn_packet_t vp;
- int lenin;
+ connection_t *c;
+ avl_node_t *node;
cp
-#ifdef HAVE_SOLARIS
- if((lenin = read(tap_fd, vp.data + 14, MTU)) <= 0)
- {
- syslog(LOG_ERR, _("Error while reading from tun device: %m"));
- return;
- }
- memcpy(vp.data, mymac.net.mac.address.x, 6);
- memcpy(vp.data + 6, mymac.net.mac.address.x, 6);
- vp.data[12] = 0x08;
- vp.data[13] = 0x00;
- vp.len = lenin + 14;
-#else
- if(taptype == TAP_TYPE_TUNTAP)
- {
- if((lenin = read(tap_fd, vp.data, MTU)) <= 0)
- {
- syslog(LOG_ERR, _("Error while reading from tun/tap device: %m"));
- return;
- }
- vp.len = lenin;
- }
- else /* ethertap */
- {
- if((lenin = read(tap_fd, vp.data - 2, MTU)) <= 0)
- {
- syslog(LOG_ERR, _("Error while reading from ethertap device: %m"));
- return;
- }
- vp.len = lenin - 2;
- }
-#endif
-
- total_tap_in += vp.len;
+ if(FD_ISSET(udp_socket, f))
+ handle_incoming_vpn_data();
- if(lenin < 32)
+ for(node = connection_tree->head; node; node = node->next)
{
- if(debug_lvl >= DEBUG_TRAFFIC)
- syslog(LOG_WARNING, _("Received short packet from tap device"));
- return;
- }
+ c = (connection_t *)node->data;
- if(debug_lvl >= DEBUG_TRAFFIC)
- {
- syslog(LOG_DEBUG, _("Read packet of length %d from tap device"), vp.len);
+ if(c->status.remove)
+ return;
+
+ if(FD_ISSET(c->socket, f))
+ if(receive_meta(c) < 0)
+ {
+ terminate_connection(c, c->status.active);
+ return;
+ }
}
- route_outgoing(&vp);
+ if(FD_ISSET(tcp_socket, f))
+ handle_new_meta_connection();
cp
}
tv.tv_sec = timeout;
tv.tv_usec = 0;
- prune_flush();
build_fdset(&fset);
if((r = select(FD_SETSIZE, &fset, NULL, NULL, &tv)) < 0)
syslog(LOG_INFO, _("Rereading configuration file and restarting in 5 seconds"));
sighup = 0;
close_network_connections();
- clear_config(&config);
+ exit_configuration(&config_tree);
if(read_server_config())
{
if(debug_lvl >= DEBUG_STATUS)
syslog(LOG_INFO, _("Regenerating symmetric key"));
- RAND_pseudo_bytes(myself->cipher_pktkey, myself->cipher_pktkeylength);
- send_key_changed(myself, NULL);
+ RAND_pseudo_bytes(myself->key, myself->keylength);
+ send_key_changed(myself->connection, myself);
keyexpires = time(NULL) + keylifetime;
}
}
check_network_activity(&fset);
/* local tap data */
- if(FD_ISSET(tap_fd, &fset))
+ if(FD_ISSET(device_fd, &fset))
handle_tap_input();
}
}
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: net.h,v 1.9.4.34 2001/07/21 15:34:18 guus Exp $
+ $Id: net.h,v 1.9.4.35 2001/10/27 12:13:17 guus Exp $
*/
#ifndef __TINC_NET_H__
typedef unsigned long ipv4_t;
+typedef struct ip_mask_t {
+ ipv4_t address;
+ ipv4_t mask;
+} ip_mask_t;
+
typedef struct ipv6_t
{
unsigned short x[8];
queue_element_t *tail;
} packet_queue_t;
-typedef struct enc_key_t {
- int length;
- char *key;
- time_t expiry;
-} enc_key_t;
-
-extern int tap_fd;
-
-extern int total_tap_in;
-extern int total_tap_out;
-extern int total_socket_in;
-extern int total_socket_out;
-
extern int seconds_till_retry;
extern char *request_name[256];
#include "connection.h" /* Yes, very strange placement indeed, but otherwise the typedefs get all tangled up */
-extern int str2opt(const char *);
-extern char *opt2str(int);
-extern void send_packet(connection_t *, vpn_packet_t *);
-extern void receive_packet(connection_t *, vpn_packet_t *);
-extern void receive_tcppacket(connection_t *, char *, int);
-extern void accept_packet(vpn_packet_t *);
-extern void broadcast_packet(connection_t *, vpn_packet_t *);
+extern void send_packet(struct node_t *, vpn_packet_t *);
+extern void receive_packet(struct node_t *, vpn_packet_t *);
+extern void receive_tcppacket(struct connection_t *, char *, int);
+extern void broadcast_packet(struct node_t *, vpn_packet_t *);
extern int setup_network_connections(void);
extern void close_network_connections(void);
extern void main_loop(void);
extern void terminate_connection(connection_t *, int);
-extern void flush_queue(connection_t *);
-
-#include <config.h>
-#ifdef HAVE_OPENSSL_RSA_H
-# include <openssl/rsa.h>
-#else
-# include <rsa.h>
-#endif
-
-extern int read_rsa_public_key(connection_t *);
+extern void flush_queue(struct node_t *);
+extern int read_rsa_public_key(struct connection_t *);
+extern RETSIGTYPE try_outgoing_connections(int);
#endif /* __TINC_NET_H__ */
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: netutl.c,v 1.12.4.19 2001/05/07 19:08:46 guus Exp $
+ $Id: netutl.c,v 1.12.4.20 2001/10/27 12:13:17 guus Exp $
*/
#include "config.h"
char *name;
struct hostent *host = NULL;
struct in_addr in;
- config_t const *cfg;
- int lookup_hostname;
+ int lookup_hostname = 0;
cp
in.s_addr = addr;
- lookup_hostname = 0;
- if((cfg = get_config_val(config, config_hostnames)) != NULL)
- if(cfg->data.val == stupid_true)
- lookup_hostname = 1;
+ get_config_int(lookup_config(config_tree, "Hostnames"), &lookup_hostname);
if(lookup_hostname)
host = gethostbyaddr((char *)&in, sizeof(in), AF_INET);
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: netutl.h,v 1.2.4.6 2001/01/07 17:09:02 guus Exp $
+ $Id: netutl.h,v 1.2.4.7 2001/10/27 12:13:17 guus Exp $
*/
#ifndef __TINC_NETUTL_H__
#define __TINC_NETUTL_H__
#include "net.h"
-#include "conf.h"
extern char *hostlookup(unsigned long);
extern ip_mask_t *strtoip(char*);
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: node.c,v 1.1.2.1 2001/10/10 08:49:47 guus Exp $
+ $Id: node.c,v 1.1.2.2 2001/10/27 12:13:17 guus Exp $
*/
+#include "config.h"
+
+#include <string.h>
+#include <syslog.h>
+
+#include <avl_tree.h>
+#include "node.h"
+#include "net.h"
+#include <utils.h>
+#include <xalloc.h>
+
+#include "system.h"
+
avl_tree_t *node_tree; /* Known nodes, sorted by name */
+avl_tree_t *node_udp_tree; /* Known nodes, sorted by address and port */
-int node_compare(connection_t *a, connection_t *b)
+int node_compare(node_t *a, node_t *b)
{
return strcmp(a->name, b->name);
}
+int node_udp_compare(connection_t *a, connection_t *b)
+{
+ if(a->address < b->address)
+ return -1;
+ else if (a->address > b->address)
+ return 1;
+ else
+ return a->port - b->port;
+}
+
void init_nodes(void)
{
cp
node_tree = avl_alloc_tree((avl_compare_t)node_compare, NULL);
+ node_udp_tree = avl_alloc_tree((avl_compare_t)node_udp_compare, NULL);
cp
}
{
cp
avl_delete_tree(node_tree);
+ avl_delete_tree(node_udp_tree);
cp
}
free(n->hostname);
if(n->key)
free(n->key);
- if(n->config)
- clear_config(&n->config);
free(n);
cp
}
+void node_add(node_t *n)
+{
+cp
+ avl_insert(node_tree, n);
+ avl_insert(node_udp_tree, n);
+cp
+}
+
+void node_del(node_t *n)
+{
+cp
+ avl_delete(node_tree, n);
+ avl_delete(node_udp_tree, n);
+cp
+}
+
node_t *lookup_node(char *name)
{
node_t n;
return avl_search(node_tree, &n);
}
-
-int read_host_config(nodet *n)
+node_t *lookup_node_udp(ipv4_t address, port_t port)
{
- char *fname;
- int x;
-cp
- asprintf(&fname, "%s/hosts/%s", confbase, n->name);
- x = read_config_file(&n->config, fname);
- free(fname);
+ node_t n;
cp
- return x;
+ n.address = address;
+ n.port = port;
+ return avl_search(node_udp_tree, &n);
}
void dump_nodes(void)
for(node = node_tree->head; node; node = node->next)
{
- n = (connection_t *)node->data;
- syslog(LOG_DEBUG, _(" %s at %s port %hd options %ld sockets %d, %d status %04x"),
+ n = (node_t *)node->data;
+ syslog(LOG_DEBUG, _(" %s at %s port %hd options %ld status %04x"),
n->name, n->hostname, n->port, n->options,
- n->socket, n->meta_socket, n->status);
+ n->status);
}
syslog(LOG_DEBUG, _("End of nodes."));
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: node.h,v 1.1.2.4 2001/10/10 20:35:10 guus Exp $
+ $Id: node.h,v 1.1.2.5 2001/10/27 12:13:17 guus Exp $
*/
#ifndef __TINC_NODE_H__
#include <avl_tree.h>
+#include "subnet.h"
+#include "connection.h"
+
+typedef struct node_status_t {
+ int active:1; /* 1 if active.. */
+ int validkey:1; /* 1 if we currently have a valid key for him */
+ int waitingforkey:1; /* 1 if we already sent out a request */
+ int unused:29;
+} node_status_t;
+
typedef struct node_t {
- char *name; /* name of this connection */
- int protocol_version; /* used protocol */
- long int options; /* options turned on for this connection */
+ char *name; /* name of this node */
+ long int options; /* options turned on for this node */
ipv4_t address; /* his real (internet) ip to send UDP packets to */
short unsigned int port; /* port number of UDP connection */
char *hostname; /* the hostname of its real ip */
+ struct node_status_t status;
+
EVP_CIPHER *cipher; /* Cipher type for UDP packets */
char *key; /* Cipher key and iv */
int keylength; /* Cipher key and iv length*/
- list_t *queue; /* Queue for packets awaiting to be encrypted */
+ list_t *queue; /* Queue for packets awaiting to be encrypted */
- struct node_t *nexthop; /* nearest meta-hop from us to him */
- struct node_t *prevhop; /* nearest meta-hop from him to us */
+ struct node_t *nexthop; /* nearest node from us to him */
struct node_t *via; /* next hop for UDP packets */
avl_tree_t *subnet_tree; /* Pointer to a tree of subnets belonging to this node */
- struct config_t *config; /* Pointer to configuration tree belonging to this node */
+ struct connection_t *connection; /* Connection associated with this node (if a direct connection exists) */
} node_t;
-struct node_t *myself;
+extern struct node_t *myself;
extern avl_tree_t *node_tree;
+extern void init_nodes(void);
+extern void exit_nodes(void);
+extern node_t *new_node(void);
+extern void free_node(node_t *n);
+extern void node_add(node_t *n);
+extern void node_del(node_t *n);
+extern node_t *lookup_node(char *);
+extern node_t *lookup_node_udp(ipv4_t, port_t);
+extern void dump_nodes(void);
+
+
#endif /* __TINC_NODE_H__ */
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.25 2001/09/05 18:38:09 zarq Exp $
+ $Id: process.c,v 1.1.2.26 2001/10/27 12:13:17 guus Exp $
*/
#include "config.h"
#include "conf.h"
#include "process.h"
#include "subnet.h"
+#include "device.h"
#include "connection.h"
#include "system.h"
close_network_connections();
if(debug_lvl > DEBUG_NOTHING)
- syslog(LOG_INFO, _("Total bytes written: tap %d, socket %d; bytes read: tap %d, socket %d"),
- total_tap_out, total_socket_out, total_tap_in, total_socket_in);
+ dump_device_stats();
syslog(LOG_NOTICE, _("Terminating"));
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.108 2001/10/08 15:37:14 guus Exp $
+ $Id: protocol.c,v 1.28.4.109 2001/10/27 12:13:17 guus Exp $
*/
#include "config.h"
#include "protocol.h"
#include "meta.h"
#include "connection.h"
+#include "node.h"
+#include "vertex.h"
#include "system.h"
/* Generic request routines - takes care of logging and error
detection as well */
-int send_request(connection_t *cl, const char *format, ...)
+int send_request(connection_t *c, const char *format, ...)
{
va_list args;
char buffer[MAXBUFSIZE];
if(len < 0 || len > MAXBUFSIZE-1)
{
- syslog(LOG_ERR, _("Output buffer overflow while sending %s to %s (%s)"), request_name[request], cl->name, cl->hostname);
+ syslog(LOG_ERR, _("Output buffer overflow while sending %s to %s (%s)"), request_name[request], c->name, c->hostname);
return -1;
}
if(debug_lvl >= DEBUG_PROTOCOL)
{
if(debug_lvl >= DEBUG_META)
- syslog(LOG_DEBUG, _("Sending %s to %s (%s): %s"), request_name[request], cl->name, cl->hostname, buffer);
+ syslog(LOG_DEBUG, _("Sending %s to %s (%s): %s"), request_name[request], c->name, c->hostname, buffer);
else
- syslog(LOG_DEBUG, _("Sending %s to %s (%s)"), request_name[request], cl->name, cl->hostname);
+ syslog(LOG_DEBUG, _("Sending %s to %s (%s)"), request_name[request], c->name, c->hostname);
}
buffer[len++] = '\n';
cp
- return send_meta(cl, buffer, len);
+ return send_meta(c, buffer, len);
}
-int receive_request(connection_t *cl)
+int receive_request(connection_t *c)
{
int request;
cp
- if(sscanf(cl->buffer, "%d", &request) == 1)
+ if(sscanf(c->buffer, "%d", &request) == 1)
{
if((request < 0) || (request >= LAST) || (request_handlers[request] == NULL))
{
if(debug_lvl >= DEBUG_META)
syslog(LOG_DEBUG, _("Unknown request from %s (%s): %s"),
- cl->name, cl->hostname, cl->buffer);
+ c->name, c->hostname, c->buffer);
else
syslog(LOG_ERR, _("Unknown request from %s (%s)"),
- cl->name, cl->hostname);
+ c->name, c->hostname);
return -1;
}
{
if(debug_lvl >= DEBUG_META)
syslog(LOG_DEBUG, _("Got %s from %s (%s): %s"),
- request_name[request], cl->name, cl->hostname, cl->buffer);
+ request_name[request], c->name, c->hostname, c->buffer);
else
syslog(LOG_DEBUG, _("Got %s from %s (%s)"),
- request_name[request], cl->name, cl->hostname);
+ request_name[request], c->name, c->hostname);
}
}
- if((cl->allow_request != ALL) && (cl->allow_request != request))
+ if((c->allow_request != ALL) && (c->allow_request != request))
{
- syslog(LOG_ERR, _("Unauthorized request from %s (%s)"), cl->name, cl->hostname);
+ syslog(LOG_ERR, _("Unauthorized request from %s (%s)"), c->name, c->hostname);
return -1;
}
- if(request_handlers[request](cl))
+ if(request_handlers[request](c))
/* Something went wrong. Probably scriptkiddies. Terminate. */
{
syslog(LOG_ERR, _("Error while processing %s from %s (%s)"),
- request_name[request], cl->name, cl->hostname);
+ request_name[request], c->name, c->hostname);
return -1;
}
}
else
{
syslog(LOG_ERR, _("Bogus data received from %s (%s)"),
- cl->name, cl->hostname);
+ c->name, c->hostname);
return -1;
}
cp
/* The authentication protocol is described in detail in doc/SECURITY2,
the rest will be described in doc/PROTOCOL. */
-int send_id(connection_t *cl)
+int send_id(connection_t *c)
{
cp
- return send_request(cl, "%d %s %d %lx %hd", ID, myself->name, myself->protocol_version, myself->options, myself->port);
+ return send_request(c, "%d %s %d", ID, myself->connection->name, myself->connection->protocol_version);
}
-int id_h(connection_t *cl)
+int id_h(connection_t *c)
{
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(c->buffer, "%*d "MAX_STRING" %d", name, &c->protocol_version) != 2)
{
- syslog(LOG_ERR, _("Got bad ID from %s"), cl->hostname);
+ syslog(LOG_ERR, _("Got bad %s from %s"), "ID", c->hostname);
return -1;
}
- /* Check if version matches */
-
- if(cl->protocol_version != myself->protocol_version)
- {
- syslog(LOG_ERR, _("Peer %s (%s) uses incompatible version %d"),
- cl->name, cl->hostname, cl->protocol_version);
- return -1;
- }
-
/* Check if identity is a valid name */
if(check_id(name))
{
- syslog(LOG_ERR, _("Peer %s uses invalid identity name"), cl->hostname);
+ syslog(LOG_ERR, _("Peer %s uses invalid identity name"), c->hostname);
return -1;
}
+
+ /* If we set c->name in advance, make sure we are connected to the right host */
- /* Copy string to cl */
-
- if(cl->name)
- free(cl->name);
-
- cl->name = xstrdup(name);
+ if(c->name)
+ {
+ if(strcmp(c->name, name))
+ {
+ syslog(LOG_ERR, _("Peer %s is %s instead of %s"), c->hostname, name, c->name);
+ return -1;
+ }
+ }
+ else
+ c->name = xstrdup(name);
- /* Load information about peer */
+ /* Check if version matches */
- if(read_host_config(cl))
+ if(c->protocol_version != myself->connection->protocol_version)
{
- syslog(LOG_ERR, _("Peer %s had unknown identity (%s)"), cl->hostname, cl->name);
+ syslog(LOG_ERR, _("Peer %s (%s) uses incompatible version %d"),
+ c->name, c->hostname, c->protocol_version);
return -1;
}
+
+ if(!c->config_tree)
+ {
+ if(read_connection_config(c))
+ {
+ syslog(LOG_ERR, _("Peer %s had unknown identity (%s)"), c->hostname, c->name);
+ return -1;
+ }
- /* Read in the public key, so that we can send a metakey */
-
- if(read_rsa_public_key(cl))
- return -1;
+ if(read_rsa_public_key(c))
+ {
+ return -1;
+ }
+ }
- cl->allow_request = METAKEY;
+ c->allow_request = METAKEY;
cp
- return send_metakey(cl);
+ return send_metakey(c);
}
-int ack_h(connection_t *cl)
+int send_metakey(connection_t *c)
{
- config_t const *cfg;
- connection_t *old, *p;
- subnet_t *subnet;
- avl_node_t *node, *node2;
+ char *buffer;
+ int len, x;
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
- old connection that has timed out but we don't know it yet.
- */
+ len = RSA_size(c->rsa_key);
- if((old = lookup_id(cl->name)))
- {
- if(debug_lvl >= DEBUG_CONNECTIONS)
- syslog(LOG_NOTICE, _("Removing old connection for %s at %s in favour of new connection at %s"),
- old->name, old->hostname, cl->hostname);
- if(old->status.outgoing)
- {
- cl->status.outgoing = 1;
- old->status.outgoing = 0;
- }
+ /* Allocate buffers for the meta key */
- terminate_connection(old, 0);
- }
+ buffer = xmalloc(len*2+1);
+
+ if(!c->outkey)
+ c->outkey = xmalloc(len);
- /* Also check if no other tinc daemon uses the same IP and port for UDP traffic */
+ if(!c->outctx)
+ c->outctx = xmalloc(sizeof(*c->outctx));
+cp
+ /* Copy random data to the buffer */
+
+ RAND_bytes(c->outkey, len);
+
+ /* The message we send must be smaller than the modulus of the RSA key.
+ By definition, for a key of k bits, the following formula holds:
+
+ 2^(k-1) <= modulus < 2^(k)
+
+ Where ^ means "to the power of", not "xor".
+ This means that to be sure, we must choose our message < 2^(k-1).
+ This can be done by setting the most significant bit to zero.
+ */
- old = avl_search(active_tree, cl);
- if(old)
- {
- syslog(LOG_ERR, _("%s is listening on %s:%hd, which is already in use by %s!"),
- cl->name, cl->hostname, cl->port, old->name);
- return -1;
- }
-
- /* Activate this connection */
+ c->outkey[0] &= 0x7F;
+
+ if(debug_lvl >= DEBUG_SCARY_THINGS)
+ {
+ bin2hex(c->outkey, buffer, len);
+ buffer[len*2] = '\0';
+ syslog(LOG_DEBUG, _("Generated random meta key (unencrypted): %s"), buffer);
+ }
- cl->allow_request = ALL;
- cl->nexthop = cl;
- cl->prevhop = myself;
- cl->cipher_pkttype = EVP_bf_cbc();
- cl->cipher_pktkeylength = cl->cipher_pkttype->key_len + cl->cipher_pkttype->iv_len;
+ /* Encrypt the random data
+
+ We do not use one of the PKCS padding schemes here.
+ This is allowed, because we encrypt a totally random string
+ with a length equal to that of the modulus of the RSA key.
+ */
+
+ if(RSA_public_encrypt(len, c->outkey, buffer, c->rsa_key, RSA_NO_PADDING) != len)
+ {
+ syslog(LOG_ERR, _("Error during encryption of meta key for %s (%s)"), c->name, c->hostname);
+ free(buffer);
+ return -1;
+ }
+cp
+ /* Convert the encrypted random data to a hexadecimal formatted string */
- active_add(cl);
+ bin2hex(buffer, buffer, len);
+ buffer[len*2] = '\0';
- if(debug_lvl >= DEBUG_CONNECTIONS)
- syslog(LOG_NOTICE, _("Connection with %s (%s) activated"), cl->name, cl->hostname);
+ /* Send the meta key */
+
+ x = send_request(c, "%d %s", METAKEY, buffer);
+ free(buffer);
+
+ /* Further outgoing requests are encrypted with the key we just generated */
- if(cl->status.outgoing)
- seconds_till_retry = 5; /* Reset retry timeout */
+ EVP_EncryptInit(c->outctx, EVP_bf_cfb(),
+ c->outkey + len - EVP_bf_cfb()->key_len,
+ c->outkey + len - EVP_bf_cfb()->key_len - EVP_bf_cfb()->iv_len);
+
+ c->status.encryptout = 1;
cp
- /* Check some options */
-
- if((cfg = get_config_val(cl->config, config_indirectdata)))
+ return x;
+}
+
+int metakey_h(connection_t *c)
+{
+ char buffer[MAX_STRING_SIZE];
+ int len;
+cp
+ if(sscanf(c->buffer, "%*d "MAX_STRING, buffer) != 1)
{
- if(cfg->data.val == stupid_true)
- cl->options |= OPTION_INDIRECT;
+ syslog(LOG_ERR, _("Got bad METAKEY from %s (%s)"), c->name, c->hostname);
+ return -1;
}
- if((cfg = get_config_val(cl->config, config_tcponly)))
+ len = RSA_size(myself->connection->rsa_key);
+
+ /* Check if the length of the meta key is all right */
+
+ if(strlen(buffer) != len*2)
{
- if(cfg->data.val == stupid_true)
- cl->options |= OPTION_TCPONLY;
+ syslog(LOG_ERR, _("Intruder: wrong meta key length from %s (%s)"), c->name, c->hostname);
+ return -1;
}
- if((myself->options | cl->options) & OPTION_INDIRECT)
- cl->via = myself;
- else
- cl->via = cl;
+ /* Allocate buffers for the meta key */
- /* Send him our subnets */
+ if(!c->inkey)
+ c->inkey = xmalloc(len);
+
+ if(!c->inctx)
+ c->inctx = xmalloc(sizeof(*c->inctx));
+
+ /* Convert the challenge from hexadecimal back to binary */
+
+ hex2bin(buffer,buffer,len);
+
+ /* Decrypt the meta key */
- for(node = myself->subnet_tree->head; node; node = node->next)
+ if(RSA_private_decrypt(len, buffer, c->inkey, myself->connection->rsa_key, RSA_NO_PADDING) != len) /* See challenge() */
{
- subnet = (subnet_t *)node->data;
- send_add_subnet(cl, subnet);
+ syslog(LOG_ERR, _("Error during encryption of meta key for %s (%s)"), c->name, c->hostname);
+ return -1;
}
- /* And send him all the hosts and their subnets we know... */
-
- for(node = active_tree->head; node; node = node->next)
+ if(debug_lvl >= DEBUG_SCARY_THINGS)
{
- p = (connection_t *)node->data;
-
- if(p != cl)
- {
- /* Notify others of this connection */
-
- if(p->status.meta)
- send_add_host(p, cl);
+ bin2hex(c->inkey, buffer, len);
+ buffer[len*2] = '\0';
+ syslog(LOG_DEBUG, _("Received random meta key (unencrypted): %s"), buffer);
+ }
- /* Notify new connection of everything we know */
+ /* All incoming requests will now be encrypted. */
- send_add_host(cl, p);
+ EVP_DecryptInit(c->inctx, EVP_bf_cfb(),
+ c->inkey + len - EVP_bf_cfb()->key_len,
+ c->inkey + len - EVP_bf_cfb()->key_len - EVP_bf_cfb()->iv_len);
+
+ c->status.decryptin = 1;
- for(node2 = p->subnet_tree->head; node2; node2 = node2->next)
- {
- subnet = (subnet_t *)node2->data;
- send_add_subnet(cl, subnet);
- }
- }
- }
+ c->allow_request = CHALLENGE;
cp
- return 0;
+ return send_challenge(c);
}
-int send_challenge(connection_t *cl)
+int send_challenge(connection_t *c)
{
char *buffer;
int len, x;
cp
/* CHECKME: what is most reasonable value for len? */
- len = RSA_size(cl->rsa_key);
+ len = RSA_size(c->rsa_key);
/* Allocate buffers for the challenge */
buffer = xmalloc(len*2+1);
- if(cl->hischallenge)
- free(cl->hischallenge);
+ if(c->hischallenge)
+ free(c->hischallenge);
- cl->hischallenge = xmalloc(len);
+ c->hischallenge = xmalloc(len);
cp
/* Copy random data to the buffer */
- RAND_bytes(cl->hischallenge, len);
+ RAND_bytes(c->hischallenge, len);
cp
/* Convert to hex */
- bin2hex(cl->hischallenge, buffer, len);
+ bin2hex(c->hischallenge, buffer, len);
buffer[len*2] = '\0';
cp
/* Send the challenge */
- x = send_request(cl, "%d %s", CHALLENGE, buffer);
+ x = send_request(c, "%d %s", CHALLENGE, buffer);
free(buffer);
cp
return x;
}
-int challenge_h(connection_t *cl)
+int challenge_h(connection_t *c)
{
char buffer[MAX_STRING_SIZE];
int len;
cp
- if(sscanf(cl->buffer, "%*d "MAX_STRING, buffer) != 1)
+ if(sscanf(c->buffer, "%*d "MAX_STRING, buffer) != 1)
{
- syslog(LOG_ERR, _("Got bad CHALLENGE from %s (%s)"), cl->name, cl->hostname);
+ syslog(LOG_ERR, _("Got bad CHALLENGE from %s (%s)"), c->name, c->hostname);
return -1;
}
- len = RSA_size(myself->rsa_key);
+ len = RSA_size(myself->connection->rsa_key);
/* Check if the length of the challenge is all right */
if(strlen(buffer) != len*2)
{
- syslog(LOG_ERR, _("Intruder: wrong challenge length from %s (%s)"), cl->name, cl->hostname);
+ syslog(LOG_ERR, _("Intruder: wrong challenge length from %s (%s)"), c->name, c->hostname);
return -1;
}
/* Allocate buffers for the challenge */
- if(!cl->mychallenge)
- cl->mychallenge = xmalloc(len);
+ if(!c->mychallenge)
+ c->mychallenge = xmalloc(len);
/* Convert the challenge from hexadecimal back to binary */
- hex2bin(buffer,cl->mychallenge,len);
+ hex2bin(buffer,c->mychallenge,len);
- cl->allow_request = CHAL_REPLY;
+ c->allow_request = CHAL_REPLY;
/* Rest is done by send_chal_reply() */
cp
- return send_chal_reply(cl);
+ return send_chal_reply(c);
}
-int send_chal_reply(connection_t *cl)
+int send_chal_reply(connection_t *c)
{
char hash[SHA_DIGEST_LENGTH*2+1];
cp
- if(!cl->mychallenge)
+ if(!c->mychallenge)
{
- syslog(LOG_ERR, _("Trying to send CHAL_REPLY to %s (%s) without a valid CHALLENGE"), cl->name, cl->hostname);
+ syslog(LOG_ERR, _("Trying to send CHAL_REPLY to %s (%s) without a valid CHALLENGE"), c->name, c->hostname);
return -1;
}
/* Calculate the hash from the challenge we received */
- SHA1(cl->mychallenge, RSA_size(myself->rsa_key), hash);
+ SHA1(c->mychallenge, RSA_size(myself->connection->rsa_key), hash);
/* Convert the hash to a hexadecimal formatted string */
/* Send the reply */
cp
- return send_request(cl, "%d %s", CHAL_REPLY, hash);
+ return send_request(c, "%d %s", CHAL_REPLY, hash);
}
-int chal_reply_h(connection_t *cl)
+int chal_reply_h(connection_t *c)
{
char hishash[MAX_STRING_SIZE];
char myhash[SHA_DIGEST_LENGTH];
cp
- if(sscanf(cl->buffer, "%*d "MAX_STRING, hishash) != 1)
+ if(sscanf(c->buffer, "%*d "MAX_STRING, hishash) != 1)
{
- syslog(LOG_ERR, _("Got bad CHAL_REPLY from %s (%s)"), cl->name, cl->hostname);
+ syslog(LOG_ERR, _("Got bad CHAL_REPLY from %s (%s)"), c->name, c->hostname);
return -1;
}
if(strlen(hishash) != SHA_DIGEST_LENGTH*2)
{
- syslog(LOG_ERR, _("Intruder: wrong challenge reply length from %s (%s)"), cl->name, cl->hostname);
+ syslog(LOG_ERR, _("Intruder: wrong challenge reply length from %s (%s)"), c->name, c->hostname);
return -1;
}
/* Calculate the hash from the challenge we sent */
- SHA1(cl->hischallenge, RSA_size(cl->rsa_key), myhash);
+ SHA1(c->hischallenge, RSA_size(c->rsa_key), myhash);
/* Verify the incoming hash with the calculated hash */
if(memcmp(hishash, myhash, SHA_DIGEST_LENGTH))
{
- syslog(LOG_ERR, _("Intruder: wrong challenge reply from %s (%s)"), cl->name, cl->hostname);
+ syslog(LOG_ERR, _("Intruder: wrong challenge reply from %s (%s)"), c->name, c->hostname);
if(debug_lvl >= DEBUG_SCARY_THINGS)
{
bin2hex(myhash, hishash, SHA_DIGEST_LENGTH);
}
/* Identity has now been positively verified.
- ack_h() handles the rest from now on.
+ Send an acknowledgement with the rest of the information needed.
*/
+
+ c->allow_request = ACK;
cp
- return ack_h(cl);
+ return send_ack(c);
}
-int send_metakey(connection_t *cl)
+int send_ack(connection_t *c)
{
- char *buffer;
- int len, x;
+ /* ACK message contains rest of the information the other end needs
+ to create node_t and vertex_t structures. */
cp
- len = RSA_size(cl->rsa_key);
-
- /* Allocate buffers for the meta key */
-
- buffer = xmalloc(len*2+1);
+ return send_request(c, "%d %d", ACK, myself->port);
+}
- if(!cl->cipher_outkey)
- cl->cipher_outkey = xmalloc(len);
-
- if(!cl->cipher_outctx)
- cl->cipher_outctx = xmalloc(sizeof(*cl->cipher_outctx));
+int ack_h(connection_t *c)
+{
+ port_t port;
+ node_t *n;
+ subnet_t *s;
+ avl_node_t *node, *node2;
cp
- /* Copy random data to the buffer */
+ if(sscanf(c->buffer, "%*d %hd", &port) != 1)
+ {
+ syslog(LOG_ERR, _("Got bad %s from %s"), "ACK", c->hostname);
+ return -1;
+ }
- RAND_bytes(cl->cipher_outkey, len);
+ /* Check if we already have a node_t for him */
- /* The message we send must be smaller than the modulus of the RSA key.
- By definition, for a key of k bits, the following formula holds:
-
- 2^(k-1) <= modulus < 2^(k)
-
- Where ^ means "to the power of", not "xor".
- This means that to be sure, we must choose our message < 2^(k-1).
- This can be done by setting the most significant bit to zero.
- */
+ n = lookup_node(c->name);
- cl->cipher_outkey[0] &= 0x7F;
-
- if(debug_lvl >= DEBUG_SCARY_THINGS)
+ if(!n)
{
- bin2hex(cl->cipher_outkey, buffer, len);
- buffer[len*2] = '\0';
- syslog(LOG_DEBUG, _("Generated random meta key (unencrypted): %s"), buffer);
- }
+ n = new_node();
+ n->name = xstrdup(c->name);
+ n->hostname = xstrdup(c->hostname);
+ n->port = port;
- /* Encrypt the random data
+ /* FIXME: Also check if no other tinc daemon uses the same IP and port for UDP traffic */
+
+ node_add(n);
+ }
+ else
+ {
+ if(n->connection)
+ {
+ /* Oh dear, we already have a connection to this node. */
+ syslog(LOG_DEBUG, _("Established a second connection with %s (%s), closing old connection"), n->name, n->hostname);
+ terminate_connection(n->connection, 0);
+ }
+
+ /* FIXME: check if information in existing node matches that of the other end of this connection */
+ }
- We do not use one of the PKCS padding schemes here.
- This is allowed, because we encrypt a totally random string
- with a length equal to that of the modulus of the RSA key.
- */
+ n->connection = c;
+ c->node = n;
- if(RSA_public_encrypt(len, cl->cipher_outkey, buffer, cl->rsa_key, RSA_NO_PADDING) != len)
+ /* Check some options
+
+ if((cfg = get_config_val(c->config, config_indirectdata)))
{
- syslog(LOG_ERR, _("Error during encryption of meta key for %s (%s)"), cl->name, cl->hostname);
- free(buffer);
- return -1;
+ if(cfg->data.val == stupid_true)
+ c->options |= OPTION_INDIRECT;
}
-cp
- /* Convert the encrypted random data to a hexadecimal formatted string */
- bin2hex(buffer, buffer, len);
- buffer[len*2] = '\0';
-
- /* Send the meta key */
-
- x = send_request(cl, "%d %s", METAKEY, buffer);
- free(buffer);
-
- /* Further outgoing requests are encrypted with the key we just generated */
-
- EVP_EncryptInit(cl->cipher_outctx, EVP_bf_cfb(),
- cl->cipher_outkey + len - EVP_bf_cfb()->key_len,
- cl->cipher_outkey + len - EVP_bf_cfb()->key_len - EVP_bf_cfb()->iv_len);
-
- cl->status.encryptout = 1;
-cp
- return x;
-}
-
-int metakey_h(connection_t *cl)
-{
- char buffer[MAX_STRING_SIZE];
- int len;
-cp
- if(sscanf(cl->buffer, "%*d "MAX_STRING, buffer) != 1)
+ if((cfg = get_config_val(c->config, config_tcponly)))
{
- syslog(LOG_ERR, _("Got bad METAKEY from %s (%s)"), cl->name, cl->hostname);
- return -1;
+ if(cfg->data.val == stupid_true)
+ c->options |= OPTION_TCPONLY;
}
- len = RSA_size(myself->rsa_key);
+ if((myself->options | c->options) & OPTION_INDIRECT)
+ c->via = myself;
+ else
+ c->via = c;
- /* Check if the length of the meta key is all right */
+ */
- if(strlen(buffer) != len*2)
- {
- syslog(LOG_ERR, _("Intruder: wrong meta key length from %s (%s)"), cl->name, cl->hostname);
- return -1;
- }
+ /* Create a vertex_t for this connection */
- /* Allocate buffers for the meta key */
+ c->vertex = new_vertex();
+
+ c->vertex->from = myself;
+ c->vertex->to = n;
+ c->vertex->metric = 1;
+ c->vertex->connection = c;
- if(!cl->cipher_inkey)
- cl->cipher_inkey = xmalloc(len);
+ vertex_add(c->vertex);
- if(!cl->cipher_inctx)
- cl->cipher_inctx = xmalloc(sizeof(*cl->cipher_inctx));
+ /* Activate this connection */
- /* Convert the challenge from hexadecimal back to binary */
+ c->allow_request = ALL;
- hex2bin(buffer,buffer,len);
+ if(debug_lvl >= DEBUG_CONNECTIONS)
+ syslog(LOG_NOTICE, _("Connection with %s (%s) activated"), c->name, c->hostname);
- /* Decrypt the meta key */
+cp
+ /* Send him our subnets */
- if(RSA_private_decrypt(len, buffer, cl->cipher_inkey, myself->rsa_key, RSA_NO_PADDING) != len) /* See challenge() */
+ for(node = myself->subnet_tree->head; node; node = node->next)
{
- syslog(LOG_ERR, _("Error during encryption of meta key for %s (%s)"), cl->name, cl->hostname);
- return -1;
+ s = (subnet_t *)node->data;
+ send_add_subnet(c, s);
}
- if(debug_lvl >= DEBUG_SCARY_THINGS)
+ /* And send him all known nodes and their subnets */
+
+ for(node = node_tree->head; node; node = node->next)
{
- bin2hex(cl->cipher_inkey, buffer, len);
- buffer[len*2] = '\0';
- syslog(LOG_DEBUG, _("Received random meta key (unencrypted): %s"), buffer);
- }
+ n = (node_t *)node->data;
+
+ if(n != c->node)
+ {
+ /* Notify others of this connection */
- /* All incoming requests will now be encrypted. */
+ if(n->connection)
+ send_add_node(n->connection, c->node);
- EVP_DecryptInit(cl->cipher_inctx, EVP_bf_cfb(),
- cl->cipher_inkey + len - EVP_bf_cfb()->key_len,
- cl->cipher_inkey + len - EVP_bf_cfb()->key_len - EVP_bf_cfb()->iv_len);
-
- cl->status.decryptin = 1;
+ /* Notify new connection of everything we know */
+
+ send_add_node(c, n);
- cl->allow_request = CHALLENGE;
+ for(node2 = c->node->subnet_tree->head; node2; node2 = node2->next)
+ {
+ s = (subnet_t *)node2->data;
+ send_add_subnet(c, s);
+ }
+ }
+ }
cp
- return send_challenge(cl);
+ return 0;
}
+
+
/* Address and subnet information exchange */
-int send_add_subnet(connection_t *cl, subnet_t *subnet)
+int send_add_subnet(connection_t *c, subnet_t *subnet)
{
int x;
char *netstr;
- char *owner;
cp
- owner = subnet->owner->name;
-
- x = send_request(cl, "%d %s %s", ADD_SUBNET,
- owner, netstr = net2str(subnet));
+ x = send_request(c, "%d %s %s", ADD_SUBNET,
+ subnet->owner->name, netstr = net2str(subnet));
free(netstr);
cp
return x;
}
-int add_subnet_h(connection_t *cl)
+int add_subnet_h(connection_t *c)
{
char subnetstr[MAX_STRING_SIZE];
char name[MAX_STRING_SIZE];
- connection_t *owner, *p;
- subnet_t *subnet;
+ node_t *owner;
+ connection_t *other;
+ subnet_t *s;
avl_node_t *node;
cp
- if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING, name, subnetstr) != 2)
+ if(sscanf(c->buffer, "%*d "MAX_STRING" "MAX_STRING, name, subnetstr) != 2)
{
- syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s)"), cl->name, cl->hostname);
+ syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s)"), c->name, c->hostname);
return -1;
}
if(check_id(name))
{
- syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s): invalid identity name"), cl->name, cl->hostname);
+ syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s): invalid identity name"), c->name, c->hostname);
return -1;
}
/* Check if subnet string is valid */
- if(!(subnet = str2net(subnetstr)))
+ if(!(s = str2net(subnetstr)))
{
- syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s): invalid subnet string"), cl->name, cl->hostname);
+ syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s): invalid subnet string"), c->name, c->hostname);
return -1;
}
- /* Check if somebody tries to add a subnet of ourself */
-
- if(!strcmp(name, myself->name))
- {
- syslog(LOG_ERR, _("Warning: got ADD_SUBNET from %s (%s) for ourself, restarting"),
- cl->name, cl->hostname);
- sighup = 1;
- return 0;
- }
-
/* Check if the owner of the new subnet is in the connection list */
- if(!(owner = lookup_id(name)))
+ if(!(owner = lookup_node(name)))
{
syslog(LOG_ERR, _("Got ADD_SUBNET for %s from %s (%s) which is not in our connection list"),
- name, cl->name, cl->hostname);
+ name, c->name, c->hostname);
return -1;
}
/* If everything is correct, add the subnet to the list of the owner */
- subnet_add(owner, subnet);
+ subnet_add(owner, s);
/* Tell the rest */
for(node = connection_tree->head; node; node = node->next)
{
- p = (connection_t *)node->data;
- if(p->status.active && p!= cl)
- send_add_subnet(p, subnet);
+ other = (connection_t *)node->data;
+ if(other->status.active && other != c)
+ send_add_subnet(other, s);
}
cp
return 0;
}
-int send_del_subnet(connection_t *cl, subnet_t *subnet)
+int send_del_subnet(connection_t *c, subnet_t *s)
{
int x;
char *netstr;
- char *owner;
cp
- owner = subnet->owner->name;
-
- x = send_request(cl, "%d %s %s", DEL_SUBNET, owner, netstr = net2str(subnet));
+ x = send_request(c, "%d %s %s", DEL_SUBNET, s->owner->name, netstr = net2str(s));
free(netstr);
cp
return x;
}
-int del_subnet_h(connection_t *cl)
+int del_subnet_h(connection_t *c)
{
char subnetstr[MAX_STRING_SIZE];
char name[MAX_STRING_SIZE];
- connection_t *owner, *p;
- subnet_t *subnet;
+ node_t *owner;
+ connection_t *other;
+ subnet_t *s, *find;
avl_node_t *node;
cp
- if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING, name, subnetstr) != 3)
+ if(sscanf(c->buffer, "%*d "MAX_STRING" "MAX_STRING, name, subnetstr) != 3)
{
- syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s)"), cl->name, cl->hostname);
+ syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s)"), c->name, c->hostname);
return -1;
}
if(check_id(name))
{
- syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s): invalid identity name"), cl->name, cl->hostname);
+ syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s): invalid identity name"), c->name, c->hostname);
return -1;
}
/* Check if subnet string is valid */
- if(!(subnet = str2net(subnetstr)))
+ if(!(s = str2net(subnetstr)))
{
- syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s): invalid subnet string"), cl->name, cl->hostname);
+ syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s): invalid subnet string"), c->name, c->hostname);
return -1;
}
- free(subnetstr);
-
- /* Check if somebody tries to add a subnet of ourself */
-
- if(!strcmp(name, myself->name))
- {
- syslog(LOG_ERR, _("Warning: got DEL_SUBNET from %s (%s) for ourself, restarting"),
- cl->name, cl->hostname);
- sighup = 1;
- return 0;
- }
-
/* Check if the owner of the new subnet is in the connection list */
- if(!(owner = lookup_id(name)))
+ if(!(owner = lookup_node(name)))
{
syslog(LOG_ERR, _("Got DEL_SUBNET for %s from %s (%s) which is not in our connection list"),
- name, cl->name, cl->hostname);
+ name, c->name, c->hostname);
return -1;
}
/* If everything is correct, delete the subnet from the list of the owner */
- subnet_del(subnet);
+ find = lookup_subnet(owner, s);
+
+ if(!find)
+ {
+ syslog(LOG_ERR, _("Got DEL_SUBNET for %s from %s (%s) which does not appear in his subnet tree"),
+ name, c->name, c->hostname);
+ return -1;
+ }
+
+ subnet_del(owner, s);
/* Tell the rest */
for(node = connection_tree->head; node; node = node->next)
{
- p = (connection_t *)node->data;
- if(p->status.active && p!= cl)
- send_del_subnet(p, subnet);
+ other = (connection_t *)node->data;
+ if(other->status.active && other != c)
+ send_del_subnet(other, s);
}
cp
return 0;
/* New and closed connections notification */
-int send_add_host(connection_t *cl, connection_t *other)
+int send_add_node(connection_t *c, node_t *n)
{
cp
- return send_request(cl, "%d %s %lx:%d %lx %s", ADD_HOST,
- other->name, other->address, other->port, other->options, other->prevhop->name);
+ return send_request(c, "%d %s %lx:%d", ADD_NODE,
+ n->name, n->address, n->port);
}
-int add_host_h(connection_t *cl)
+int add_node_h(connection_t *c)
{
- connection_t *old, *new, *p;
- char name[MAX_STRING_SIZE], prevhop[MAX_STRING_SIZE];
+ connection_t *other;
+ node_t *n;
+ char name[MAX_STRING_SIZE];
+ ipv4_t address;
+ port_t port;
avl_node_t *node;
cp
- new = new_connection();
-
- if(sscanf(cl->buffer, "%*d "MAX_STRING" %lx:%hd %lx "MAX_STRING, name, &new->address, &new->port, &new->options, prevhop) != 5)
+ if(sscanf(c->buffer, "%*d "MAX_STRING" %lx:%hd", name, &address, &port) != 3)
{
- syslog(LOG_ERR, _("Got bad ADD_HOST from %s (%s)"), cl->name, cl->hostname);
+ syslog(LOG_ERR, _("Got bad ADD_NODE from %s (%s)"), c->name, c->hostname);
return -1;
}
if(check_id(name))
{
- syslog(LOG_ERR, _("Got bad ADD_HOST from %s (%s): invalid identity name"), cl->name, cl->hostname);
- free_connection(new);
- return -1;
- }
-
- if(check_id(prevhop))
- {
- syslog(LOG_ERR, _("Got bad ADD_HOST from %s (%s): invalid prevhop name"), cl->name, cl->hostname);
- free_connection(new);
+ syslog(LOG_ERR, _("Got bad ADD_NODE from %s (%s): invalid identity name"), c->name, c->hostname);
return -1;
}
if(!strcmp(name, myself->name))
{
- syslog(LOG_ERR, _("Got ADD_HOST from %s (%s) for ourself!"), cl->name, cl->hostname);
- free_connection(new);
+ syslog(LOG_ERR, _("Got ADD_NODE from %s (%s) for ourself!"), c->name, c->hostname);
return -1;
}
- /* Fill in more of the new connection structure */
-
- new->hostname = hostlookup(htonl(new->address));
-
- new->prevhop = lookup_id(prevhop);
+ /* Check if node already exists */
- if(!new->prevhop)
+ n = lookup_node(name);
+
+ if(n)
{
- syslog(LOG_ERR, _("Got bad ADD_HOST from %s (%s): unknown prevhop"), cl->name, cl->hostname);
- free_connection(new);
- return -1;
+ /* Check if it matches */
}
-
- /* Check if the new host already exists in the connnection list */
-
- if((old = lookup_id(name)))
+ else
{
- if((new->address == old->address) && (new->port == old->port) && (cl->nexthop == old->nexthop))
- {
- if(debug_lvl >= DEBUG_CONNECTIONS)
- syslog(LOG_NOTICE, _("Got duplicate ADD_HOST for %s (%s) from %s (%s)"),
- old->name, old->hostname, cl->name, cl->hostname);
- free_connection(new);
- return 0;
- }
- else
- {
- if(debug_lvl >= DEBUG_CONNECTIONS)
- syslog(LOG_NOTICE, _("Removing old entry for %s (%s) from %s in favour of new connection from %s"),
- old->name, old->hostname, old->nexthop->name, cl->nexthop->name);
-
- terminate_connection(old, 0);
- }
+ n = new_node();
+ n->name = xstrdup(name);
+ n->address = address;
+ n->port = port;
+ node_add(n);
}
- /* Hook it up into the active tree */
-
- new->name = xstrdup(name);
- active_add(new);
-
- /* Tell the rest about the new host */
+ /* Tell the rest about the new node */
for(node = connection_tree->head; node; node = node->next)
{
- p = (connection_t *)node->data;
- if(p->status.active && p!=cl)
- send_add_host(p, new);
+ other = (connection_t *)node->data;
+ if(other->status.active && other !=c)
+ send_add_node(other, n);
}
- /* Fill in rest of connection structure */
-
- new->nexthop = cl;
- new->cipher_pkttype = EVP_bf_cbc();
- new->cipher_pktkeylength = cl->cipher_pkttype->key_len + cl->cipher_pkttype->iv_len;
-
- if(new->options & OPTION_INDIRECT || new->prevhop->via != new->prevhop)
- new->via = new->prevhop->via;
- else
- new->via = new;
cp
return 0;
}
-int send_del_host(connection_t *cl, connection_t *other)
+int send_del_node(connection_t *c, node_t *n)
{
cp
- return send_request(cl, "%d %s %lx:%d %lx %s", DEL_HOST,
- other->name, other->address, other->port, other->options, other->prevhop->name);
+ return send_request(c, "%d %s %lx:%d", DEL_NODE,
+ n->name, n->address, n->port);
}
-int del_host_h(connection_t *cl)
+int del_node_h(connection_t *c)
{
- char name[MAX_STRING_SIZE], prevhop[MAX_STRING_SIZE];
+ node_t *n;
+ char name[MAX_STRING_SIZE];
ipv4_t address;
port_t port;
- long int options;
- connection_t *old, *p;
+ connection_t *other;
avl_node_t *node;
cp
- if(sscanf(cl->buffer, "%*d "MAX_STRING" %lx:%hd %lx "MAX_STRING, name, &address, &port, &options, prevhop) != 5)
+ if(sscanf(c->buffer, "%*d "MAX_STRING" %lx:%hd", name, &address, &port) != 3)
{
- syslog(LOG_ERR, _("Got bad DEL_HOST from %s (%s)"),
- cl->name, cl->hostname);
+ syslog(LOG_ERR, _("Got bad DEL_NODE from %s (%s)"),
+ c->name, c->hostname);
return -1;
}
if(check_id(name))
{
- syslog(LOG_ERR, _("Got bad DEL_HOST from %s (%s): invalid identity name"), cl->name, cl->hostname);
- return -1;
- }
-
- if(check_id(prevhop))
- {
- syslog(LOG_ERR, _("Got bad DEL_HOST from %s (%s): invalid prevhop name"), cl->name, cl->hostname);
+ syslog(LOG_ERR, _("Got bad DEL_NODE from %s (%s): invalid identity name"), c->name, c->hostname);
return -1;
}
if(!strcmp(name, myself->name))
{
- syslog(LOG_ERR, _("Got DEL_HOST from %s (%s) for ourself!"),
- cl->name, cl->hostname);
+ syslog(LOG_ERR, _("Got DEL_NODE from %s (%s) for ourself!"),
+ c->name, c->hostname);
return -1;
}
- /* Check if the deleted host already exists in the connnection list */
+ /* Check if the deleted host exists */
- if(!(old = lookup_id(name)))
+ n = lookup_node(name);
+
+ if(!n)
{
- syslog(LOG_ERR, _("Got DEL_HOST from %s (%s) for %s which is not in our connection list"),
- cl->name, cl->hostname, name);
- return -1;
+ syslog(LOG_WARNING, _("Got DEL_NODE from %s (%s) for %s which does not exist"), c->name, c->hostname, n->name);
+ return 0;
}
/* Check if the rest matches */
- if(address!=old->address || port!=old->port || options!=old->options || cl!=old->nexthop || strcmp(prevhop, old->prevhop->name))
+ if(address != n->address || port != n->port)
{
- syslog(LOG_WARNING, _("Got DEL_HOST from %s (%s) for %s which doesn't match"), cl->name, cl->hostname, old->name);
+ syslog(LOG_WARNING, _("Got DEL_NODE from %s (%s) for %s which doesn't match"), c->name, c->hostname, n->name);
return 0;
}
- /* Ok, since EVERYTHING seems to check out all right, delete it */
-
- terminate_connection(old, 0);
-
- /* Tell the rest about the deleted host */
+ /* Tell the rest about the deleted node */
for(node = connection_tree->head; node; node = node->next)
{
- p = (connection_t *)node->data;
- if(p->status.active && p!=cl)
- send_del_host(p, old);
+ other = (connection_t *)node->data;
+ if(other->status.active && other != c)
+ send_del_node(other, n);
}
+
+ /* Delete the node */
+
+ node_del(n);
cp
return 0;
}
/* Status and error notification routines */
-int send_status(connection_t *cl, int statusno, char *statusstring)
+int send_status(connection_t *c, int statusno, char *statusstring)
{
cp
if(!statusstring)
statusstring = status_text[statusno];
cp
- return send_request(cl, "%d %d %s", STATUS, statusno, statusstring);
+ return send_request(c, "%d %d %s", STATUS, statusno, statusstring);
}
-int status_h(connection_t *cl)
+int status_h(connection_t *c)
{
int statusno;
char statusstring[MAX_STRING_SIZE];
cp
- if(sscanf(cl->buffer, "%*d %d "MAX_STRING, &statusno, statusstring) != 2)
+ if(sscanf(c->buffer, "%*d %d "MAX_STRING, &statusno, statusstring) != 2)
{
syslog(LOG_ERR, _("Got bad STATUS from %s (%s)"),
- cl->name, cl->hostname);
+ c->name, c->hostname);
return -1;
}
if(debug_lvl >= DEBUG_STATUS)
{
syslog(LOG_NOTICE, _("Status message from %s (%s): %s: %s"),
- cl->name, cl->hostname, status_text[statusno], statusstring);
+ c->name, c->hostname, status_text[statusno], statusstring);
}
cp
return 0;
}
-int send_error(connection_t *cl, int err, char *errstring)
+int send_error(connection_t *c, int err, char *errstring)
{
cp
if(!errstring)
errstring = strerror(err);
- return send_request(cl, "%d %d %s", ERROR, err, errstring);
+ return send_request(c, "%d %d %s", ERROR, err, errstring);
}
-int error_h(connection_t *cl)
+int error_h(connection_t *c)
{
int err;
char errorstring[MAX_STRING_SIZE];
cp
- if(sscanf(cl->buffer, "%*d %d "MAX_STRING, &err, errorstring) != 2)
+ if(sscanf(c->buffer, "%*d %d "MAX_STRING, &err, errorstring) != 2)
{
syslog(LOG_ERR, _("Got bad ERROR from %s (%s)"),
- cl->name, cl->hostname);
+ c->name, c->hostname);
return -1;
}
if(debug_lvl >= DEBUG_ERROR)
{
syslog(LOG_NOTICE, _("Error message from %s (%s): %s: %s"),
- cl->name, cl->hostname, strerror(err), errorstring);
+ c->name, c->hostname, strerror(err), errorstring);
}
- terminate_connection(cl, cl->status.meta);
+ terminate_connection(c, c->status.active);
cp
return 0;
}
-int send_termreq(connection_t *cl)
+int send_termreq(connection_t *c)
{
cp
- return send_request(cl, "%d", TERMREQ);
+ return send_request(c, "%d", TERMREQ);
}
-int termreq_h(connection_t *cl)
+int termreq_h(connection_t *c)
{
cp
- terminate_connection(cl, cl->status.meta);
+ terminate_connection(c, c->status.active);
cp
return 0;
}
-int send_ping(connection_t *cl)
+int send_ping(connection_t *c)
{
char salt[SALTLEN*2+1];
cp
- cl->status.pinged = 1;
- cl->last_ping_time = time(NULL);
+ c->status.pinged = 1;
+ c->last_ping_time = time(NULL);
RAND_pseudo_bytes(salt, SALTLEN);
bin2hex(salt, salt, SALTLEN);
salt[SALTLEN*2] = '\0';
cp
- return send_request(cl, "%d %s", PING, salt);
+ return send_request(c, "%d %s", PING, salt);
}
-int ping_h(connection_t *cl)
+int ping_h(connection_t *c)
{
cp
- return send_pong(cl);
+ return send_pong(c);
}
-int send_pong(connection_t *cl)
+int send_pong(connection_t *c)
{
char salt[SALTLEN*2+1];
cp
bin2hex(salt, salt, SALTLEN);
salt[SALTLEN*2] = '\0';
cp
- return send_request(cl, "%d %s", PONG, salt);
+ return send_request(c, "%d %s", PONG, salt);
}
-int pong_h(connection_t *cl)
+int pong_h(connection_t *c)
{
cp
- cl->status.pinged = 0;
+ c->status.pinged = 0;
cp
return 0;
}
/* Key exchange */
-int send_key_changed(connection_t *from, connection_t *cl)
+int send_key_changed(connection_t *c, node_t *n)
{
- connection_t *p;
+ connection_t *other;
avl_node_t *node;
cp
/* Only send this message if some other daemon requested our key previously.
This reduces unnecessary key_changed broadcasts.
*/
- if(from==myself && !mykeyused)
+ if(n == myself && !mykeyused)
return 0;
for(node = connection_tree->head; node; node = node->next)
{
- p = (connection_t *)node->data;
- if(p != cl && p->status.active)
- send_request(p, "%d %s", KEY_CHANGED, from->name);
+ other = (connection_t *)node->data;
+ if(other != c && other->status.active)
+ send_request(other, "%d %s", KEY_CHANGED, n->name);
}
cp
return 0;
}
-int key_changed_h(connection_t *cl)
+int key_changed_h(connection_t *c)
{
- char from_id[MAX_STRING_SIZE];
- connection_t *from;
+ char name[MAX_STRING_SIZE];
+ node_t *n;
cp
- if(sscanf(cl->buffer, "%*d "MAX_STRING, from_id) != 1)
+ if(sscanf(c->buffer, "%*d "MAX_STRING, name) != 1)
{
syslog(LOG_ERR, _("Got bad KEY_CHANGED from %s (%s)"),
- cl->name, cl->hostname);
+ c->name, c->hostname);
return -1;
}
- if(!(from = lookup_id(from_id)))
+ n = lookup_node(name);
+
+ if(!n)
{
- syslog(LOG_ERR, _("Got KEY_CHANGED from %s (%s) origin %s which does not exist in our connection list"),
- cl->name, cl->hostname, from_id);
+ syslog(LOG_ERR, _("Got KEY_CHANGED from %s (%s) origin %s which does not exist"),
+ c->name, c->hostname, name);
return -1;
}
- from->status.validkey = 0;
- from->status.waitingforkey = 0;
+ n->status.validkey = 0;
+ n->status.waitingforkey = 0;
- send_key_changed(from, cl);
+ send_key_changed(c, n);
cp
return 0;
}
-int send_req_key(connection_t *from, connection_t *to)
+int send_req_key(connection_t *c, node_t *from, node_t *to)
{
cp
- return send_request(to->nexthop, "%d %s %s", REQ_KEY,
+ return send_request(c, "%d %s %s", REQ_KEY,
from->name, to->name);
}
-int req_key_h(connection_t *cl)
+int req_key_h(connection_t *c)
{
- char from_id[MAX_STRING_SIZE];
- char to_id[MAX_STRING_SIZE];
- connection_t *from, *to;
- char pktkey[129];
+ char from_name[MAX_STRING_SIZE];
+ char to_name[MAX_STRING_SIZE];
+ node_t *from, *to;
+ char key[MAX_STRING_SIZE];
cp
- if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING, from_id, to_id) != 2)
+ if(sscanf(c->buffer, "%*d "MAX_STRING" "MAX_STRING, from_name, to_name) != 2)
{
syslog(LOG_ERR, _("Got bad REQ_KEY from %s (%s)"),
- cl->name, cl->hostname);
+ c->name, c->hostname);
return -1;
}
- if(!(from = lookup_id(from_id)))
+ from = lookup_node(from_name);
+
+ if(!from)
{
syslog(LOG_ERR, _("Got REQ_KEY from %s (%s) origin %s which does not exist in our connection list"),
- cl->name, cl->hostname, from_id);
+ c->name, c->hostname, from_name);
+ return -1;
+ }
+
+ to = lookup_node(to_name);
+
+ if(!to)
+ {
+ syslog(LOG_ERR, _("Got REQ_KEY from %s (%s) destination %s which does not exist in our connection list"),
+ c->name, c->hostname, to_name);
return -1;
}
/* Check if this key request is for us */
- if(!strcmp(to_id, myself->name)) /* Yes, send our own key back */
+ if(to == myself) /* Yes, send our own key back */
{
- bin2hex(myself->cipher_pktkey, pktkey, myself->cipher_pktkeylength);
- pktkey[myself->cipher_pktkeylength*2] = '\0';
- send_ans_key(myself, from, pktkey);
+ bin2hex(myself->key, key, myself->keylength);
+ key[myself->keylength * 2] = '\0';
+ send_ans_key(c, myself, from, key);
mykeyused = 1;
}
else
{
- if(!(to = lookup_id(to_id)))
- {
- syslog(LOG_ERR, _("Got REQ_KEY from %s (%s) destination %s which does not exist in our connection list"),
- cl->name, cl->hostname, to_id);
- return -1;
- }
-
if(to->status.validkey) /* Proxy keys */
{
- bin2hex(to->cipher_pktkey, pktkey, to->cipher_pktkeylength);
- pktkey[to->cipher_pktkeylength*2] = '\0';
- send_ans_key(to, from, pktkey);
+ bin2hex(to->key, key, to->keylength);
+ key[to->keylength * 2] = '\0';
+ send_ans_key(c, to, from, key);
}
else
- send_req_key(from, to);
+ send_req_key(to->nexthop->connection, from, to);
}
cp
return 0;
}
-int send_ans_key(connection_t *from, connection_t *to, char *pktkey)
+int send_ans_key(connection_t *c, node_t *from, node_t *to, char *key)
{
cp
- return send_request(to->nexthop, "%d %s %s %s", ANS_KEY,
- from->name, to->name, pktkey);
+ return send_request(c, "%d %s %s %s", ANS_KEY,
+ from->name, to->name, key);
}
-int ans_key_h(connection_t *cl)
+int ans_key_h(connection_t *c)
{
- char from_id[MAX_STRING_SIZE];
- char to_id[MAX_STRING_SIZE];
- char pktkey[MAX_STRING_SIZE];
+ char from_name[MAX_STRING_SIZE];
+ char to_name[MAX_STRING_SIZE];
+ char key[MAX_STRING_SIZE];
int keylength;
- connection_t *from, *to;
+ node_t *from, *to;
cp
- if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING" "MAX_STRING, from_id, to_id, pktkey) != 3)
+ if(sscanf(c->buffer, "%*d "MAX_STRING" "MAX_STRING" "MAX_STRING, from_name, to_name, key) != 3)
{
syslog(LOG_ERR, _("Got bad ANS_KEY from %s (%s)"),
- cl->name, cl->hostname);
+ c->name, c->hostname);
return -1;
}
- if(!(from = lookup_id(from_id)))
+ from = lookup_node(from_name);
+
+ if(!from)
{
syslog(LOG_ERR, _("Got ANS_KEY from %s (%s) origin %s which does not exist in our connection list"),
- cl->name, cl->hostname, from_id);
+ c->name, c->hostname, from_name);
+ return -1;
+ }
+
+ to = lookup_node(to_name);
+
+ if(!to)
+ {
+ syslog(LOG_ERR, _("Got ANS_KEY from %s (%s) destination %s which does not exist in our connection list"),
+ c->name, c->hostname, to_name);
return -1;
}
/* Check correctness of packet key */
- keylength = strlen(pktkey);
+ keylength = strlen(key);
- if(keylength != from->cipher_pktkeylength*2)
+ if(keylength != from->keylength * 2)
{
syslog(LOG_ERR, _("Got bad ANS_KEY from %s (%s) origin %s: invalid key length"),
- cl->name, cl->hostname, from->name);
+ c->name, c->hostname, from->name);
return -1;
}
/* Forward it if necessary */
- if(strcmp(to_id, myself->name))
+ if(to != myself)
{
- if(!(to = lookup_id(to_id)))
- {
- syslog(LOG_ERR, _("Got ANS_KEY from %s (%s) destination %s which does not exist in our connection list"),
- cl->name, cl->hostname, to_id);
- return -1;
- }
- send_ans_key(from, to, pktkey);
+ send_ans_key(to->nexthop->connection, from, to, key);
}
/* Update our copy of the origin's packet key */
- if(from->cipher_pktkey)
- free(from->cipher_pktkey);
+ if(from->key)
+ free(from->key);
- from->cipher_pktkey = xstrdup(pktkey);
+ from->key = xstrdup(key);
keylength /= 2;
- hex2bin(from->cipher_pktkey, from->cipher_pktkey, keylength);
- from->cipher_pktkey[keylength] = '\0';
+ hex2bin(from->key, from->key, keylength);
+ from->key[keylength] = '\0';
from->status.validkey = 1;
from->status.waitingforkey = 0;
return 0;
}
-int send_tcppacket(connection_t *cl, vpn_packet_t *packet)
+int send_tcppacket(connection_t *c, vpn_packet_t *packet)
{
int x;
cp
/* Evil hack. */
- x = send_request(cl->nexthop, "%d %hd", PACKET, packet->len);
+ x = send_request(c, "%d %hd", PACKET, packet->len);
if(x)
return x;
cp
- return send_meta(cl, packet->data, packet->len);
+ return send_meta(c, packet->data, packet->len);
}
-int tcppacket_h(connection_t *cl)
+int tcppacket_h(connection_t *c)
{
short int len;
cp
- if(sscanf(cl->buffer, "%*d %hd", &len) != 1)
+ if(sscanf(c->buffer, "%*d %hd", &len) != 1)
{
- syslog(LOG_ERR, _("Got bad PACKET from %s (%s)"), cl->name, cl->hostname);
+ syslog(LOG_ERR, _("Got bad PACKET from %s (%s)"), c->name, c->hostname);
return -1;
}
/* Set reqlen to len, this will tell receive_meta() that a tcppacket is coming. */
- cl->tcplen = len;
+ c->tcplen = len;
cp
return 0;
}
/* Jumptable for the request handlers */
int (*request_handlers[])(connection_t*) = {
- id_h, metakey_h, challenge_h, chal_reply_h,
+ id_h, metakey_h, challenge_h, chal_reply_h, ack_h,
status_h, error_h, termreq_h,
ping_h, pong_h,
- add_host_h, del_host_h,
+ add_node_h, del_node_h,
add_subnet_h, del_subnet_h,
key_changed_h, req_key_h, ans_key_h,
tcppacket_h,
/* Request names */
char (*request_name[]) = {
- "ID", "METAKEY", "CHALLENGE", "CHAL_REPLY",
+ "ID", "METAKEY", "CHALLENGE", "CHAL_REPLY", "ACK",
"STATUS", "ERROR", "TERMREQ",
"PING", "PONG",
- "ADD_HOST", "DEL_HOST",
+ "ADD_NODE", "DEL_NODE",
"ADD_SUBNET", "DEL_SUBNET",
+ "ADD_VERTEX", "DEL_VERTEX",
"KEY_CHANGED", "REQ_KEY", "ANS_KEY",
"PACKET",
};
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: protocol.h,v 1.5.4.22 2001/09/24 14:12:00 guus Exp $
+ $Id: protocol.h,v 1.5.4.23 2001/10/27 12:13:17 guus Exp $
*/
#ifndef __TINC_PROTOCOL_H__
#define __TINC_PROTOCOL_H__
#include "net.h"
+#include "node.h"
#include "subnet.h"
/* Protocol version. Different versions are incompatible,
enum {
ALL = -1, /* Guardian for allow_request */
- ID = 0, METAKEY, CHALLENGE, CHAL_REPLY,
+ ID = 0, METAKEY, CHALLENGE, CHAL_REPLY, ACK,
STATUS, ERROR, TERMREQ,
- PING, PONG,
- ADD_HOST, DEL_HOST,
+ PING, PONG,
+ ADD_NODE, DEL_NODE,
ADD_SUBNET, DEL_SUBNET,
+ ADD_VERTEX, DEL_VERTEX,
KEY_CHANGED, REQ_KEY, ANS_KEY,
PACKET,
LAST /* Guardian for the highest request number */
extern int (*request_handlers[])(connection_t*);
extern int send_id(connection_t*);
+extern int send_metakey(connection_t*);
extern int send_challenge(connection_t*);
extern int send_chal_reply(connection_t*);
-extern int send_metakey(connection_t*);
+extern int send_ack(connection_t*);
extern int send_status(connection_t*, int, char*);
extern int send_error(connection_t*, int, char*);
extern int send_termreq(connection_t*);
extern int send_ping(connection_t*);
extern int send_pong(connection_t*);
-extern int send_add_host(connection_t*, connection_t*);
-extern int send_del_host(connection_t*, connection_t*);
+extern int send_add_node(connection_t*, node_t*);
+extern int send_del_node(connection_t*, node_t*);
extern int send_add_subnet(connection_t*, subnet_t*);
extern int send_del_subnet(connection_t*, subnet_t*);
-extern int send_key_changed(connection_t*, connection_t*);
-extern int send_req_key(connection_t*, connection_t*);
-extern int send_ans_key(connection_t*, connection_t*, char*);
+extern int send_add_vertex(connection_t*, node_t*);
+extern int send_del_vertex(connection_t*, node_t*);
+extern int send_key_changed(connection_t*, node_t*);
+extern int send_req_key(connection_t*, node_t*, node_t*);
+extern int send_ans_key(connection_t*, node_t*, node_t*, char*);
extern int send_tcppacket(connection_t *, vpn_packet_t *);
/* Old functions */
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.18 2001/07/21 20:21:25 guus Exp $
+ $Id: route.c,v 1.1.2.19 2001/10/27 12:13:17 guus Exp $
*/
#include "config.h"
{
subnet_t *subnet;
avl_node_t *node;
- connection_t *p;
+ connection_t *c;
cp
subnet = lookup_subnet_mac(address);
for(node = connection_tree->head; node; node = node->next)
{
- p = (connection_t *)node->data;
- if(p->status.active)
- send_add_subnet(p, subnet);
+ c = (connection_t *)node->data;
+ if(c->status.active)
+ send_add_subnet(c, subnet);
}
}
}
-connection_t *route_mac(vpn_packet_t *packet)
+node_t *route_mac(vpn_packet_t *packet)
{
subnet_t *subnet;
cp
return NULL;
}
-connection_t *route_ipv4(vpn_packet_t *packet)
+node_t *route_ipv4(vpn_packet_t *packet)
{
ipv4_t dest;
subnet_t *subnet;
return subnet->owner;
}
-connection_t *route_ipv6(vpn_packet_t *packet)
+node_t *route_ipv6(vpn_packet_t *packet)
{
+ ipv6_t dest;
+ subnet_t *subnet;
+cp
+ memcpy(&dest, &packet->data[30], sizeof(ipv6_t));
+
+ subnet = lookup_subnet_ipv6(&dest);
cp
- if(debug_lvl > DEBUG_NOTHING)
+ if(!subnet)
{
- syslog(LOG_WARNING, _("Cannot route packet: IPv6 routing not yet implemented"));
- }
+ if(debug_lvl >= DEBUG_TRAFFIC)
+ {
+ syslog(LOG_WARNING, _("Cannot route packet: unknown IPv6 destination address"));
+ }
+
+ return NULL;
+ }
cp
- return NULL;
+ return subnet->owner;
}
void route_arp(vpn_packet_t *packet)
void route_outgoing(vpn_packet_t *packet)
{
unsigned short int type;
- connection_t *cl;
+ node_t *n;
cp
/* FIXME: multicast? */
switch(type)
{
case 0x0800:
- cl = route_ipv4(packet);
+ n = route_ipv4(packet);
break;
case 0x86DD:
- cl = route_ipv6(packet);
+ n = route_ipv6(packet);
break;
case 0x0806:
route_arp(packet);
}
return;
}
- if(cl)
- send_packet(cl, packet);
+ if(n)
+ send_packet(n, packet);
break;
case RMODE_SWITCH:
- cl = route_mac(packet);
- if(cl)
- send_packet(cl, packet);
+ n = route_mac(packet);
+ if(n)
+ send_packet(n, packet);
else
broadcast_packet(myself, packet);
break;
}
}
-void route_incoming(connection_t *source, vpn_packet_t *packet)
+void route_incoming(node_t *source, vpn_packet_t *packet)
{
switch(routing_mode)
{
}
break;
case RMODE_HUB:
- broadcast_packet(source,packet); /* Spread it on */
+ broadcast_packet(source, packet); /* Spread it on */
accept_packet(packet);
break;
}
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: route.h,v 1.1.2.3 2001/03/04 13:59:32 guus Exp $
+ $Id: route.h,v 1.1.2.4 2001/10/27 12:13:17 guus Exp $
*/
#ifndef __TINC_ROUTE_H__
};
extern int routing_mode;
-extern subnet_t mymac;
-extern void route_incoming(connection_t *, vpn_packet_t *);
+extern void route_incoming(node_t *, vpn_packet_t *);
extern void route_outgoing(vpn_packet_t *);
#endif /* __TINC_ROUTE_H__ */
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.24 2001/08/28 20:52:39 guus Exp $
+ $Id: subnet.c,v 1.1.2.25 2001/10/27 12:13:17 guus Exp $
*/
#include "config.h"
#include "conf.h"
#include "net.h"
-#include "connection.h"
+#include "node.h"
#include "subnet.h"
#include "system.h"
int subnet_compare_mac(subnet_t *a, subnet_t *b)
{
+ int result;
cp
- return memcmp(&a->net.mac.address, &b->net.mac.address, sizeof(mac_t));
+ result = memcmp(&a->net.mac.address, &b->net.mac.address, sizeof(mac_t));
+
+ if(result)
+ return result;
+
+ return strcmp(a->owner->name, b->owner->name);
}
int subnet_compare_ipv4(subnet_t *a, subnet_t *b)
cp
/* We compare as if a subnet is a number that equals (address << 32 + netmask). */
- if(a->net.ipv4.address == b->net.ipv4.address)
- {
- if(a->net.ipv4.mask < b->net.ipv4.mask)
- return -1;
- else if(a->net.ipv4.mask > b->net.ipv4.mask)
- return 1;
- else
- return 0;
- }
- else
- {
- if(a->net.ipv4.address < b->net.ipv4.address)
- return -1;
- else if(a->net.ipv4.address > b->net.ipv4.address)
- return 1;
- else
- return 0;
- }
+ if(a->net.ipv4.address < b->net.ipv4.address)
+ return -1;
+ else if(a->net.ipv4.address > b->net.ipv4.address)
+ return 1;
+
+ if(a->net.ipv4.mask < b->net.ipv4.mask)
+ return -1;
+ else if(a->net.ipv4.mask > b->net.ipv4.mask)
+ return 1;
+
+ return strcmp(a->owner->name, b->owner->name);
}
int subnet_compare_ipv6(subnet_t *a, subnet_t *b)
{
+ int result;
cp
/* Same as ipv4 case, but with nasty 128 bit addresses */
- if(memcmp(&a->net.ipv6.mask, &b->net.ipv6.mask, sizeof(ipv6_t)) > 0)
- if((a->net.ipv6.address.x[0] & b->net.ipv6.mask.x[0]) == b->net.ipv6.address.x[0] &&
- (a->net.ipv6.address.x[1] & b->net.ipv6.mask.x[1]) == b->net.ipv6.address.x[1] &&
- (a->net.ipv6.address.x[2] & b->net.ipv6.mask.x[2]) == b->net.ipv6.address.x[2] &&
- (a->net.ipv6.address.x[3] & b->net.ipv6.mask.x[3]) == b->net.ipv6.address.x[3] &&
- (a->net.ipv6.address.x[4] & b->net.ipv6.mask.x[4]) == b->net.ipv6.address.x[4] &&
- (a->net.ipv6.address.x[5] & b->net.ipv6.mask.x[5]) == b->net.ipv6.address.x[5] &&
- (a->net.ipv6.address.x[6] & b->net.ipv6.mask.x[6]) == b->net.ipv6.address.x[6] &&
- (a->net.ipv6.address.x[7] & b->net.ipv6.mask.x[7]) == b->net.ipv6.address.x[7])
- return -1;
+ result = memcmp(a->net.ipv6.address.x, b->net.ipv6.address.x, sizeof(ipv6_t));
+
+ if(result)
+ return result;
+
+ result = memcmp(a->net.ipv6.mask.x, b->net.ipv6.mask.x, sizeof(ipv6_t));
- return memcmp(&a->net.ipv6.address, &b->net.ipv6.address, sizeof(ipv6_t));
+ if(result)
+ return result;
+
+ return strcmp(a->owner->name, b->owner->name);
}
int subnet_compare(subnet_t *a, subnet_t *b)
/* Linked list management */
-void subnet_add(connection_t *cl, subnet_t *subnet)
+void subnet_add(node_t *n, subnet_t *subnet)
{
cp
- subnet->owner = cl;
+ subnet->owner = n;
- while(!avl_insert(subnet_tree, subnet))
- {
- subnet_t *old;
-
- old = (subnet_t *)avl_search(subnet_tree, subnet);
-
- if(debug_lvl >= DEBUG_PROTOCOL)
- {
- char *subnetstr;
- subnetstr = net2str(subnet);
- syslog(LOG_WARNING, _("Duplicate subnet %s for %s (%s), previous owner %s (%s)!"),
- subnetstr, cl->name, cl->hostname, old->owner->name, old->owner->hostname);
- free(subnetstr);
- }
-
- subnet_del(old);
- }
-
- avl_insert(cl->subnet_tree, subnet);
+ avl_insert(subnet_tree, subnet);
+cp
+ avl_insert(n->subnet_tree, subnet);
cp
}
-void subnet_del(subnet_t *subnet)
+void subnet_del(node_t *n, subnet_t *subnet)
{
cp
- avl_delete(subnet->owner->subnet_tree, subnet);
+ avl_delete(n->subnet_tree, subnet);
cp
avl_delete(subnet_tree, subnet);
cp
/* Subnet lookup routines */
+subnet_t *lookup_subnet(node_t *owner, subnet_t *subnet)
+{
+cp
+ return avl_search(owner->subnet_tree, subnet);
+}
+
subnet_t *lookup_subnet_mac(mac_t *address)
{
subnet_t subnet, *p;
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.10 2001/01/08 21:32:30 guus Exp $
+ $Id: subnet.h,v 1.1.2.11 2001/10/27 12:13:17 guus Exp $
*/
#ifndef __TINC_SUBNET_H__
ipv6_t mask;
} subnet_ipv6_t;
+#include "node.h"
+
typedef struct subnet_t {
- struct connection_t *owner; /* the owner of this subnet */
- struct connection_t *uplink; /* the uplink which we should send packets to for this subnet */
+ struct node_t *owner; /* the owner of this subnet */
+ struct node_t *uplink; /* the uplink which we should send packets to for this subnet */
int type; /* subnet type (IPv4? IPv6? MAC? something even weirder?) */
subnet_ipv6_t ipv6;
} net;
-} subnet_t;
-
-#include "connection.h"
+} subnet_t;
extern subnet_t *new_subnet(void);
extern void free_subnet(subnet_t *);
extern void init_subnets(void);
-extern void subnet_add(struct connection_t *, subnet_t *);
-extern void subnet_del(subnet_t *);
+extern void subnet_add(struct node_t *, subnet_t *);
+extern void subnet_del(struct node_t *, 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(struct node_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 *);
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.52 2001/09/01 12:36:53 guus Exp $
+ $Id: tincd.c,v 1.10.4.53 2001/10/27 12:13:17 guus Exp $
*/
#include "config.h"
{
RSA *rsa_key;
FILE *f;
- config_t const *cfg;
+ char *name = NULL;
char *filename;
fprintf(stderr, _("Generating %d bits keys:\n"), bits);
else
fprintf(stderr, _("Done.\n"));
- if(config && (cfg = get_config_val(config, config_name)))
- asprintf(&filename, "%s/hosts/%s", confbase, cfg->data.ptr);
+ get_config_string(lookup_config(config_tree, "Name"), &name);
+
+ if(name)
+ asprintf(&filename, "%s/hosts/%s", confbase, name);
else
asprintf(&filename, "%s/rsa_key.pub", confbase);
if(do_detach)
{
- syslog(LOG_NOTICE, _("Restarting in %d seconds!"), MAXTIMEOUT);
- sleep(MAXTIMEOUT);
+ syslog(LOG_NOTICE, _("Restarting in %d seconds!"), maxtimeout);
+ sleep(maxtimeout);
}
else
{
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: vertex.c,v 1.1.2.1 2001/10/10 08:49:47 guus Exp $
+ $Id: vertex.c,v 1.1.2.2 2001/10/27 12:13:17 guus Exp $
*/
#include "config.h"
int connection_compare(connection_t *a, connection_t *b)
{
- return a->meta_socket - b->meta_socket;
+ return a->socket - b->socket;
}
int vertex_compare(vertex_t *a, vertex_t *b)
void free_vertex(vertex_t *v)
{
cp
- if(v->from.hostname)
- free(v->from.hostname)
- if(v->to.hostname)
- free(v->to.hostname)
-
free(v);
cp
}
+void vertex_add(vertex_t *v)
+{
+cp
+ avl_insert(vertex_tree, v);
+cp
+}
+
+void vertex_del(vertex_t *v)
+{
+cp
+ avl_delete(vertex_tree, v);
+cp
+}
+
vertex_t *lookup_vertex(node_t *from, node_t *to)
{
vertex_t v, *result;
cp
- v.from.node = from;
- v.to.node = to;
+ v.from = from;
+ v.to = to;
result = avl_search(vertex_tree, &v);
if(result)
return result;
cp
- v.from.node = to;
- v.to.node = from;
+ v.from = to;
+ v.to = from;
return avl_search(vertex_tree, &v);
}
{
v = (vertex_t *)node->data;
syslog(LOG_DEBUG, _(" %s - %s options %ld"),
- v->from.node->name, v->to.node->name, v->options);
+ v->from->name, v->to->name, v->options);
}
syslog(LOG_DEBUG, _("End of vertices."));
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: vertex.h,v 1.1.2.4 2001/10/10 20:35:10 guus Exp $
+ $Id: vertex.h,v 1.1.2.5 2001/10/27 12:13:17 guus Exp $
*/
#ifndef __TINC_VERTEX_H__
#include "node.h"
#include "connection.h"
+/* I don't know if halfconnection_t is useful... */
+
typedef struct halfconnection_t {
struct node_t *node; /* node associated with this end of the connection */
} halfconnection_t;
typedef struct vertex_t {
- struct halfconnection_t from;
- struct halfconnection_t to;
+ struct node_t *from;
+ struct node_t *to;
long int options; /* options turned on for this connection */
int metric; /* weight of this vertex */
extern avl_tree_t *vertex_tree; /* Tree with all known vertices (replaces active_tree) */
+extern void init_vertices(void);
+extern void exit_vertices(void);
+extern vertex_t *new_vertex(void);
+extern void free_vertex(vertex_t *);
+extern void vertex_add(vertex_t *);
+extern void vertex_del(vertex_t *);
+extern vertex_t *lookup_vertex(struct node_t *, struct node_t *);
+extern void dump_vertices(void);
+
#endif /* __TINC_VERTEX_H__ */