Switch to K&R style indentation.

This commit is contained in:
Guus Sliepen 2002-09-09 21:25:28 +00:00
parent 5fc1ed17f4
commit f75dcef72a
44 changed files with 6039 additions and 6132 deletions

File diff suppressed because it is too large Load diff

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: conf.h,v 1.6.4.33 2002/06/21 10:11:12 guus Exp $
$Id: conf.h,v 1.6.4.34 2002/09/09 21:24:31 guus Exp $
*/
#ifndef __TINC_CONF_H__
@ -32,10 +32,10 @@
#include "subnet.h"
typedef struct config_t {
char *variable;
char *value;
char *file;
int line;
char *variable;
char *value;
char *file;
int line;
} config_t;
extern avl_tree_t *config_tree;
@ -59,12 +59,12 @@ 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_address(config_t *, struct addrinfo **);
struct subnet_t; /* Needed for next line. */
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);
extern FILE *ask_and_safe_open(const char*, const char*, const char *);
extern FILE *ask_and_safe_open(const char *, const char *, const char *);
extern int is_safe_path(const char *);
#endif /* __TINC_CONF_H__ */
#endif /* __TINC_CONF_H__ */

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: connection.c,v 1.1.2.32 2002/09/09 19:39:58 guus Exp $
$Id: connection.c,v 1.1.2.33 2002/09/09 21:24:31 guus Exp $
*/
#include "config.h"
@ -30,7 +30,7 @@
#include <avl_tree.h>
#include <list.h>
#include "net.h" /* Don't ask. */
#include "net.h" /* Don't ask. */
#include "netutl.h"
#include "config.h"
#include "conf.h"
@ -43,102 +43,109 @@
avl_tree_t *connection_tree; /* Meta connections */
connection_t *broadcast;
int connection_compare(connection_t *a, connection_t *b)
int connection_compare(connection_t * a, connection_t * b)
{
return a - b;
return a - b;
}
void init_connections(void)
{
cp();
connection_tree = avl_alloc_tree((avl_compare_t)connection_compare, NULL);
cp();
broadcast = new_connection();
broadcast->name = xstrdup(_("everyone"));
broadcast->hostname = xstrdup(_("BROADCAST"));
cp();
cp();
connection_tree = avl_alloc_tree((avl_compare_t) connection_compare, NULL);
broadcast = new_connection();
broadcast->name = xstrdup(_("everyone"));
broadcast->hostname = xstrdup(_("BROADCAST"));
}
void exit_connections(void)
{
cp();
avl_delete_tree(connection_tree);
cp();
free_connection(broadcast);
cp();
cp();
avl_delete_tree(connection_tree);
free_connection(broadcast);
}
connection_t *new_connection(void)
{
connection_t *c;
cp();
c = (connection_t *)xmalloc_and_zero(sizeof(connection_t));
connection_t *c;
if(!c)
return NULL;
cp();
gettimeofday(&c->start, NULL);
cp();
return c;
c = (connection_t *) xmalloc_and_zero(sizeof(connection_t));
if(!c)
return NULL;
gettimeofday(&c->start, NULL);
return c;
}
void free_connection(connection_t *c)
void free_connection(connection_t * c)
{
cp();
if(c->hostname)
free(c->hostname);
if(c->inkey)
free(c->inkey);
if(c->outkey)
free(c->outkey);
if(c->mychallenge)
free(c->mychallenge);
if(c->hischallenge)
free(c->hischallenge);
free(c);
cp();
cp();
if(c->hostname)
free(c->hostname);
if(c->inkey)
free(c->inkey);
if(c->outkey)
free(c->outkey);
if(c->mychallenge)
free(c->mychallenge);
if(c->hischallenge)
free(c->hischallenge);
free(c);
}
void connection_add(connection_t *c)
void connection_add(connection_t * c)
{
cp();
avl_insert(connection_tree, c);
cp();
cp();
avl_insert(connection_tree, c);
}
void connection_del(connection_t *c)
void connection_del(connection_t * c)
{
cp();
avl_delete(connection_tree, c);
cp();
cp();
avl_delete(connection_tree, c);
}
void dump_connections(void)
{
avl_node_t *node;
connection_t *c;
cp();
syslog(LOG_DEBUG, _("Connections:"));
avl_node_t *node;
connection_t *c;
for(node = connection_tree->head; node; node = node->next)
{
c = (connection_t *)node->data;
syslog(LOG_DEBUG, _(" %s at %s options %lx socket %d status %04x"),
c->name, c->hostname, c->options, c->socket, c->status);
}
syslog(LOG_DEBUG, _("End of connections."));
cp();
cp();
syslog(LOG_DEBUG, _("Connections:"));
for(node = connection_tree->head; node; node = node->next) {
c = (connection_t *) node->data;
syslog(LOG_DEBUG, _(" %s at %s options %lx socket %d status %04x"),
c->name, c->hostname, c->options, c->socket, c->status);
}
syslog(LOG_DEBUG, _("End of connections."));
}
int read_connection_config(connection_t *c)
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;
char *fname;
int x;
cp();
asprintf(&fname, "%s/hosts/%s", confbase, c->name);
x = read_config_file(c->config_tree, fname);
free(fname);
return x;
}

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: connection.h,v 1.1.2.30 2002/09/04 16:26:44 guus Exp $
$Id: connection.h,v 1.1.2.31 2002/09/09 21:24:31 guus Exp $
*/
#ifndef __TINC_CONNECTION_H__
@ -50,62 +50,62 @@
#define OPTION_TCPONLY 0x0002
typedef struct connection_status_t {
int pinged:1; /* sent ping */
int active:1; /* 1 if active.. */
int connecting:1; /* 1 if we are waiting for a non-blocking connect() to finish */
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 encryptout:1; /* 1 if we can encrypt outgoing traffic */
int decryptin:1; /* 1 if we have to decrypt incoming traffic */
int mst:1; /* 1 if this connection is part of a minimum spanning tree */
int unused:18;
int pinged:1; /* sent ping */
int active:1; /* 1 if active.. */
int connecting:1; /* 1 if we are waiting for a non-blocking connect() to finish */
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 encryptout:1; /* 1 if we can encrypt outgoing traffic */
int decryptin:1; /* 1 if we have to decrypt incoming traffic */
int mst:1; /* 1 if this connection is part of a minimum spanning tree */
int unused:18;
} connection_status_t;
typedef struct connection_t {
char *name; /* name he claims to have */
char *name; /* name he claims to have */
sockaddr_t address; /* his real (internet) ip */
char *hostname; /* the hostname of its real ip */
int protocol_version; /* used protocol */
sockaddr_t address; /* his real (internet) ip */
char *hostname; /* the hostname of its real ip */
int protocol_version; /* used protocol */
int socket; /* socket used for this connection */
long int options; /* options for this connection */
struct connection_status_t status; /* status info */
int estimated_weight; /* estimation for the weight of the edge for this connection */
struct timeval start; /* time this connection was started, used for above estimation */
struct outgoing_t *outgoing; /* used to keep track of outgoing connections */
int socket; /* socket used for this connection */
long int options; /* options for this connection */
struct connection_status_t status; /* status info */
int estimated_weight; /* estimation for the weight of the edge for this connection */
struct timeval start; /* time this connection was started, used for above estimation */
struct outgoing_t *outgoing; /* used to keep track of outgoing connections */
struct node_t *node; /* node associated with the other end */
struct edge_t *edge; /* edge associated with this connection */
struct node_t *node; /* node associated with the other end */
struct edge_t *edge; /* edge associated with this connection */
RSA *rsa_key; /* his public/private key */
const EVP_CIPHER *incipher; /* Cipher he will use to send data to us */
const EVP_CIPHER *outcipher; /* Cipher we will use to send data to him */
EVP_CIPHER_CTX *inctx; /* Context of encrypted meta data that will come from him to us */
EVP_CIPHER_CTX *outctx; /* Context of encrypted meta data that will be sent from us to him */
char *inkey; /* His symmetric meta key + iv */
char *outkey; /* Our symmetric meta key + iv */
int inkeylength; /* Length of his key + iv */
int outkeylength; /* Length of our key + iv */
const EVP_MD *indigest;
const EVP_MD *outdigest;
int inmaclength;
int outmaclength;
int incompression;
int outcompression;
char *mychallenge; /* challenge we received from him */
char *hischallenge; /* challenge we sent to him */
RSA *rsa_key; /* his public/private key */
const EVP_CIPHER *incipher; /* Cipher he will use to send data to us */
const EVP_CIPHER *outcipher; /* Cipher we will use to send data to him */
EVP_CIPHER_CTX *inctx; /* Context of encrypted meta data that will come from him to us */
EVP_CIPHER_CTX *outctx; /* Context of encrypted meta data that will be sent from us to him */
char *inkey; /* His symmetric meta key + iv */
char *outkey; /* Our symmetric meta key + iv */
int inkeylength; /* Length of his key + iv */
int outkeylength; /* Length of our key + iv */
const EVP_MD *indigest;
const EVP_MD *outdigest;
int inmaclength;
int outmaclength;
int incompression;
int outcompression;
char *mychallenge; /* challenge we received from him */
char *hischallenge; /* challenge we sent to him */
char buffer[MAXBUFSIZE]; /* metadata input buffer */
int buflen; /* bytes read into buffer */
int reqlen; /* length of incoming request */
int tcplen; /* length of incoming TCPpacket */
int allow_request; /* defined if there's only one request possible */
char buffer[MAXBUFSIZE]; /* metadata input buffer */
int buflen; /* bytes read into buffer */
int reqlen; /* length of incoming request */
int tcplen; /* length of incoming TCPpacket */
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 */
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 */
avl_tree_t *config_tree; /* Pointer to configuration tree belonging to him */
} connection_t;
extern avl_tree_t *connection_tree;
@ -120,4 +120,4 @@ extern void connection_del(connection_t *);
extern void dump_connections(void);
extern int read_connection_config(connection_t *);
#endif /* __TINC_CONNECTION_H__ */
#endif /* __TINC_CONNECTION_H__ */

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: device.c,v 1.1.2.1 2002/07/11 12:57:06 guus Exp $
$Id: device.c,v 1.1.2.2 2002/09/09 21:25:18 guus Exp $
*/
#include "config.h"
@ -51,90 +51,78 @@ extern subnet_t mymac;
int setup_device(void)
{
struct ifreq ifr;
struct ifreq ifr;
cp
if(!get_config_string(lookup_config(config_tree, "Device"), &device))
device = DEFAULT_DEVICE;
cp if(!get_config_string(lookup_config(config_tree, "Device"), &device))
device = DEFAULT_DEVICE;
if(!get_config_string(lookup_config(config_tree, "Interface"), &interface))
interface = rindex(device, '/')?rindex(device, '/')+1:device;
cp
if((device_fd = open(device, O_RDWR | O_NONBLOCK)) < 0)
{
syslog(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno));
return -1;
}
cp
/* Set default MAC address for ethertap devices */
if(!get_config_string(lookup_config(config_tree, "Interface"), &interface))
interface = rindex(device, '/') ? rindex(device, '/') + 1 : device;
cp if((device_fd = open(device, O_RDWR | O_NONBLOCK)) < 0) {
syslog(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno));
return -1;
}
cp
/* 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;
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;
device_info = _("Stub device for Cygwin environment");
device_info = _("Stub device for Cygwin environment");
syslog(LOG_INFO, _("%s is a %s"), device, device_info);
cp
return 0;
syslog(LOG_INFO, _("%s is a %s"), device, device_info);
cp return 0;
}
void close_device(void)
{
cp
close(device_fd);
cp close(device_fd);
}
int read_packet(vpn_packet_t *packet)
int read_packet(vpn_packet_t * packet)
{
int lenin;
cp
if((lenin = read(device_fd, packet->data, MTU)) <= 0)
{
syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, device, strerror(errno));
return -1;
}
int lenin;
cp if((lenin = read(device_fd, packet->data, MTU)) <= 0) {
syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info,
device, strerror(errno));
return -1;
}
packet->len = lenin;
packet->len = lenin;
device_total_in += packet->len;
device_total_in += packet->len;
if(debug_lvl >= DEBUG_TRAFFIC)
{
syslog(LOG_DEBUG, _("Read packet of %d bytes from %s"), packet->len, device_info);
}
if(debug_lvl >= DEBUG_TRAFFIC) {
syslog(LOG_DEBUG, _("Read packet of %d bytes from %s"), packet->len,
device_info);
}
return 0;
cp
}
return 0;
cp}
int write_packet(vpn_packet_t *packet)
int write_packet(vpn_packet_t * packet)
{
cp
if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_DEBUG, _("Writing packet of %d bytes to %s"),
packet->len, device_info);
cp if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_DEBUG, _("Writing packet of %d bytes to %s"),
packet->len, device_info);
if(write(device_fd, packet->data, packet->len) < 0)
{
syslog(LOG_ERR, _("Can't write to %s %s: %s"), device_info, device, strerror(errno));
return -1;
}
if(write(device_fd, packet->data, packet->len) < 0) {
syslog(LOG_ERR, _("Can't write to %s %s: %s"), device_info, device,
strerror(errno));
return -1;
}
device_total_out += packet->len;
cp
return 0;
device_total_out += packet->len;
cp return 0;
}
void dump_device_stats(void)
{
cp
syslog(LOG_DEBUG, _("Statistics for %s %s:"), device_info, device);
syslog(LOG_DEBUG, _(" total bytes in: %10d"), device_total_in);
syslog(LOG_DEBUG, _(" total bytes out: %10d"), device_total_out);
cp
}
cp syslog(LOG_DEBUG, _("Statistics for %s %s:"), device_info, device);
syslog(LOG_DEBUG, _(" total bytes in: %10d"), device_total_in);
syslog(LOG_DEBUG, _(" total bytes out: %10d"), device_total_out);
cp}

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: device.c,v 1.1.2.2 2002/06/21 10:11:34 guus Exp $
$Id: device.c,v 1.1.2.3 2002/09/09 21:25:19 guus Exp $
*/
#include "config.h"
@ -58,96 +58,83 @@ extern subnet_t mymac;
*/
int setup_device(void)
{
cp
if(!get_config_string(lookup_config(config_tree, "Device"), &device))
device = DEFAULT_DEVICE;
cp if(!get_config_string(lookup_config(config_tree, "Device"), &device))
device = DEFAULT_DEVICE;
if(!get_config_string(lookup_config(config_tree, "Interface"), &interface))
interface = rindex(device, '/')?rindex(device, '/')+1:device;
cp
if((device_fd = open(device, O_RDWR | O_NONBLOCK)) < 0)
{
syslog(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno));
return -1;
}
cp
if(!get_config_string(lookup_config(config_tree, "Interface"), &interface))
interface = rindex(device, '/') ? rindex(device, '/') + 1 : device;
cp if((device_fd = open(device, O_RDWR | O_NONBLOCK)) < 0) {
syslog(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno));
return -1;
}
cp
/* 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;
/* Set default MAC address for ethertap devices */
device_info = _("MacOS/X tun device");
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;
device_info = _("MacOS/X tun device");
syslog(LOG_INFO, _("%s is a %s"), device, device_info);
cp
return 0;
syslog(LOG_INFO, _("%s is a %s"), device, device_info);
cp return 0;
}
void close_device(void)
{
cp
close(device_fd);
cp close(device_fd);
}
/*
read, encrypt and send data that is
available through the ethertap device
*/
int read_packet(vpn_packet_t *packet)
int read_packet(vpn_packet_t * packet)
{
int lenin;
cp
if((lenin = read(device_fd, packet->data + 14, MTU - 14)) <= 0)
{
syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, device, strerror(errno));
return -1;
}
int lenin;
cp if((lenin = read(device_fd, packet->data + 14, MTU - 14)) <= 0) {
syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info,
device, strerror(errno));
return -1;
}
memcpy(packet->data, mymac.net.mac.address.x, 6);
memcpy(packet->data + 6, mymac.net.mac.address.x, 6);
packet->data[12] = 0x08;
packet->data[13] = 0x00;
memcpy(packet->data, mymac.net.mac.address.x, 6);
memcpy(packet->data + 6, mymac.net.mac.address.x, 6);
packet->data[12] = 0x08;
packet->data[13] = 0x00;
packet->len = lenin + 14;
packet->len = lenin + 14;
device_total_in += packet->len;
device_total_in += packet->len;
if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_DEBUG, _("Read packet of %d bytes from %s"),
packet->len, device_info);
if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_DEBUG, _("Read packet of %d bytes from %s"),
packet->len, device_info);
return 0;
cp
}
return 0;
cp}
int write_packet(vpn_packet_t *packet)
int write_packet(vpn_packet_t * packet)
{
cp
if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_DEBUG, _("Writing packet of %d bytes to %s"),
packet->len, device_info);
cp if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_DEBUG, _("Writing packet of %d bytes to %s"),
packet->len, device_info);
if(write(device_fd, packet->data + 14, packet->len - 14) < 0)
{
syslog(LOG_ERR, _("Error while writing to %s %s: %s"), device_info, device, strerror(errno));
return -1;
}
if(write(device_fd, packet->data + 14, packet->len - 14) < 0) {
syslog(LOG_ERR, _("Error while writing to %s %s: %s"), device_info,
device, strerror(errno));
return -1;
}
device_total_out += packet->len;
cp
}
device_total_out += packet->len;
cp}
void dump_device_stats(void)
{
cp
syslog(LOG_DEBUG, _("Statistics for %s %s:"), device_info, device);
syslog(LOG_DEBUG, _(" total bytes in: %10d"), device_total_in);
syslog(LOG_DEBUG, _(" total bytes out: %10d"), device_total_out);
cp
}
cp syslog(LOG_DEBUG, _("Statistics for %s %s:"), device_info, device);
syslog(LOG_DEBUG, _(" total bytes in: %10d"), device_total_in);
syslog(LOG_DEBUG, _(" total bytes out: %10d"), device_total_out);
cp}

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: device.h,v 1.1.2.6 2002/06/21 10:11:12 guus Exp $
$Id: device.h,v 1.1.2.7 2002/09/09 21:24:31 guus Exp $
*/
#ifndef __TINC_DEVICE_H__
@ -33,4 +33,4 @@ extern int read_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__ */

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: edge.c,v 1.1.2.15 2002/09/09 19:39:58 guus Exp $
$Id: edge.c,v 1.1.2.16 2002/09/09 21:24:31 guus Exp $
*/
#include "config.h"
@ -29,7 +29,7 @@
#include <avl_tree.h>
#include <list.h>
#include "net.h" /* Don't ask. */
#include "net.h" /* Don't ask. */
#include "netutl.h"
#include "config.h"
#include "conf.h"
@ -41,132 +41,132 @@
#include "xalloc.h"
#include "system.h"
avl_tree_t *edge_weight_tree; /* Tree with all edges, sorted on weight */
avl_tree_t *edge_weight_tree; /* Tree with all edges, sorted on weight */
int edge_compare(edge_t *a, edge_t *b)
int edge_compare(edge_t * a, edge_t * b)
{
return strcmp(a->to->name, b->to->name);
return strcmp(a->to->name, b->to->name);
}
int edge_weight_compare(edge_t *a, edge_t *b)
int edge_weight_compare(edge_t * a, edge_t * b)
{
int result;
int result;
result = a->weight - b->weight;
result = a->weight - b->weight;
if(result)
return result;
if(result)
return result;
result = strcmp(a->from->name, b->from->name);
result = strcmp(a->from->name, b->from->name);
if(result)
return result;
if(result)
return result;
return strcmp(a->to->name, b->to->name);
return strcmp(a->to->name, b->to->name);
}
void init_edges(void)
{
cp();
edge_weight_tree = avl_alloc_tree((avl_compare_t)edge_weight_compare, NULL);
cp();
cp();
edge_weight_tree =
avl_alloc_tree((avl_compare_t) edge_weight_compare, NULL);
}
avl_tree_t *new_edge_tree(void)
{
cp();
return avl_alloc_tree((avl_compare_t)edge_compare, NULL);
cp();
cp();
return avl_alloc_tree((avl_compare_t) edge_compare, NULL);
}
void free_edge_tree(avl_tree_t *edge_tree)
void free_edge_tree(avl_tree_t * edge_tree)
{
cp();
avl_delete_tree(edge_tree);
cp();
cp();
avl_delete_tree(edge_tree);
}
void exit_edges(void)
{
cp();
avl_delete_tree(edge_weight_tree);
cp();
cp();
avl_delete_tree(edge_weight_tree);
}
/* Creation and deletion of connection elements */
edge_t *new_edge(void)
{
edge_t *e;
cp();
e = (edge_t *)xmalloc_and_zero(sizeof(*e));
cp();
return e;
cp();
return (edge_t *) xmalloc_and_zero(sizeof(edge_t));
}
void free_edge(edge_t *e)
void free_edge(edge_t * e)
{
cp();
free(e);
cp();
cp();
free(e);
}
void edge_add(edge_t *e)
void edge_add(edge_t * e)
{
cp();
avl_insert(edge_weight_tree, e);
avl_insert(e->from->edge_tree, e);
cp();
e->reverse = lookup_edge(e->to, e->from);
if(e->reverse)
e->reverse->reverse = e;
cp();
cp();
avl_insert(edge_weight_tree, e);
avl_insert(e->from->edge_tree, e);
e->reverse = lookup_edge(e->to, e->from);
if(e->reverse)
e->reverse->reverse = e;
}
void edge_del(edge_t *e)
void edge_del(edge_t * e)
{
cp();
if(e->reverse)
e->reverse->reverse = NULL;
cp();
avl_delete(edge_weight_tree, e);
avl_delete(e->from->edge_tree, e);
cp();
cp();
if(e->reverse)
e->reverse->reverse = NULL;
avl_delete(e->from->edge_tree, e);
avl_delete(edge_weight_tree, e);
}
edge_t *lookup_edge(node_t *from, node_t *to)
edge_t *lookup_edge(node_t * from, node_t * to)
{
edge_t v;
cp();
v.from = from;
v.to = to;
edge_t v;
return avl_search(from->edge_tree, &v);
cp();
v.from = from;
v.to = to;
return avl_search(from->edge_tree, &v);
}
void dump_edges(void)
{
avl_node_t *node, *node2;
node_t *n;
edge_t *e;
char *address;
cp();
syslog(LOG_DEBUG, _("Edges:"));
avl_node_t *node, *node2;
node_t *n;
edge_t *e;
char *address;
for(node = node_tree->head; node; node = node->next)
{
n = (node_t *)node->data;
for(node2 = n->edge_tree->head; node2; node2 = node2->next)
{
e = (edge_t *)node2->data;
address = sockaddr2hostname(&e->address);
syslog(LOG_DEBUG, _(" %s to %s at %s options %lx weight %d"),
e->from->name, e->to->name, address,
e->options, e->weight);
free(address);
cp();
syslog(LOG_DEBUG, _("Edges:"));
for(node = node_tree->head; node; node = node->next) {
n = (node_t *) node->data;
for(node2 = n->edge_tree->head; node2; node2 = node2->next) {
e = (edge_t *) node2->data;
address = sockaddr2hostname(&e->address);
syslog(LOG_DEBUG, _(" %s to %s at %s options %lx weight %d"),
e->from->name, e->to->name, address, e->options, e->weight);
free(address);
}
}
}
syslog(LOG_DEBUG, _("End of edges."));
cp();
syslog(LOG_DEBUG, _("End of edges."));
}

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: edge.h,v 1.1.2.10 2002/09/06 10:23:52 guus Exp $
$Id: edge.h,v 1.1.2.11 2002/09/09 21:24:31 guus Exp $
*/
#ifndef __TINC_EDGE_H__
@ -30,18 +30,18 @@
#include "connection.h"
typedef struct edge_t {
struct node_t *from;
struct node_t *to;
sockaddr_t address;
struct node_t *from;
struct node_t *to;
sockaddr_t address;
long int options; /* options turned on for this edge */
int weight; /* weight of this edge */
struct connection_t *connection; /* connection associated with this edge, if available */
struct edge_t *reverse; /* edge in the opposite direction, if available */
long int options; /* options turned on for this edge */
int weight; /* weight of this edge */
struct connection_t *connection; /* connection associated with this edge, if available */
struct edge_t *reverse; /* edge in the opposite direction, if available */
} edge_t;
extern avl_tree_t *edge_weight_tree; /* Tree with all known edges sorted on weight */
extern avl_tree_t *edge_weight_tree; /* Tree with all known edges sorted on weight */
extern void init_edges(void);
extern void exit_edges(void);
@ -54,4 +54,4 @@ extern void edge_del(edge_t *);
extern edge_t *lookup_edge(struct node_t *, struct node_t *);
extern void dump_edges(void);
#endif /* __TINC_EDGE_H__ */
#endif /* __TINC_EDGE_H__ */

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: event.c,v 1.1.4.4 2002/09/09 19:39:58 guus Exp $
$Id: event.c,v 1.1.4.5 2002/09/09 21:24:31 guus Exp $
*/
#include "config.h"
@ -38,73 +38,74 @@ extern time_t now;
int id;
int event_compare(event_t *a, event_t *b)
int event_compare(event_t * a, event_t * b)
{
if(a->time > b->time)
return 1;
if(a->time < b->time)
return -1;
return a->id - b->id;
if(a->time > b->time)
return 1;
if(a->time < b->time)
return -1;
return a->id - b->id;
}
void init_events(void)
{
cp();
event_tree = avl_alloc_tree((avl_compare_t)event_compare, NULL);
cp();
cp();
event_tree = avl_alloc_tree((avl_compare_t) event_compare, NULL);
}
void exit_events(void)
{
cp();
avl_delete_tree(event_tree);
cp();
cp();
avl_delete_tree(event_tree);
}
event_t *new_event(void)
{
event_t *event;
cp();
event = (event_t *)xmalloc_and_zero(sizeof(*event));
cp();
return event;
cp();
return (event_t *) xmalloc_and_zero(sizeof(event_t));
}
void free_event(event_t *event)
void free_event(event_t * event)
{
cp();
free(event);
cp();
cp();
free(event);
}
void event_add(event_t *event)
void event_add(event_t * event)
{
cp();
event->id = ++id;
avl_insert(event_tree, event);
cp();
cp();
event->id = ++id;
avl_insert(event_tree, event);
}
void event_del(event_t *event)
void event_del(event_t * event)
{
cp();
avl_delete(event_tree, event);
cp();
cp();
avl_delete(event_tree, event);
}
event_t *get_expired_event(void)
{
event_t *event;
cp();
if(event_tree->head)
{
event = (event_t *)event_tree->head->data;
if(event->time < now)
{
avl_delete(event_tree, event);
return event;
}
}
cp();
return NULL;
event_t *event;
cp();
if(event_tree->head) {
event = (event_t *) event_tree->head->data;
if(event->time < now) {
avl_delete(event_tree, event);
return event;
}
}
return NULL;
}

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: event.h,v 1.1.4.2 2002/06/21 10:11:12 guus Exp $
$Id: event.h,v 1.1.4.3 2002/09/09 21:24:34 guus Exp $
*/
#ifndef __TINC_EVENT_H__
@ -28,13 +28,13 @@
avl_tree_t *event_tree;
typedef void (*event_handler_t)(void *);
typedef void (*event_handler_t) (void *);
typedef struct {
time_t time;
int id;
event_handler_t handler;
void *data;
time_t time;
int id;
event_handler_t handler;
void *data;
} event_t;
extern void init_events(void);
@ -45,4 +45,4 @@ extern void event_add(event_t *);
extern void event_del(event_t *);
extern event_t *get_expired_event(void);
#endif /* __TINC_EVENT_H__ */
#endif /* __TINC_EVENT_H__ */

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: device.c,v 1.1.2.5 2002/06/21 10:11:35 guus Exp $
$Id: device.c,v 1.1.2.6 2002/09/09 21:25:19 guus Exp $
*/
#include "config.h"
@ -58,91 +58,78 @@ extern subnet_t mymac;
*/
int setup_device(void)
{
cp
if(!get_config_string(lookup_config(config_tree, "Device"), &device))
device = DEFAULT_DEVICE;
cp if(!get_config_string(lookup_config(config_tree, "Device"), &device))
device = DEFAULT_DEVICE;
if(!get_config_string(lookup_config(config_tree, "Interface"), &interface))
interface = rindex(device, '/')?rindex(device, '/')+1:device;
cp
if((device_fd = open(device, O_RDWR | O_NONBLOCK)) < 0)
{
syslog(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno));
return -1;
}
cp
if(!get_config_string(lookup_config(config_tree, "Interface"), &interface))
interface = rindex(device, '/') ? rindex(device, '/') + 1 : device;
cp if((device_fd = open(device, O_RDWR | O_NONBLOCK)) < 0) {
syslog(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno));
return -1;
}
cp
/* 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;
/* Set default MAC address for ethertap devices */
device_info = _("FreeBSD tap device");
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;
device_info = _("FreeBSD tap device");
syslog(LOG_INFO, _("%s is a %s"), device, device_info);
cp
return 0;
syslog(LOG_INFO, _("%s is a %s"), device, device_info);
cp return 0;
}
void close_device(void)
{
cp
close(device_fd);
cp close(device_fd);
}
/*
read, encrypt and send data that is
available through the ethertap device
*/
int read_packet(vpn_packet_t *packet)
int read_packet(vpn_packet_t * packet)
{
int lenin;
cp
if((lenin = read(device_fd, packet->data, MTU)) <= 0)
{
syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, device, strerror(errno));
return -1;
}
int lenin;
cp if((lenin = read(device_fd, packet->data, MTU)) <= 0) {
syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info,
device, strerror(errno));
return -1;
}
packet->len = lenin;
packet->len = lenin;
device_total_in += packet->len;
device_total_in += packet->len;
if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_DEBUG, _("Read packet of %d bytes from %s"),
packet->len, device_info);
if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_DEBUG, _("Read packet of %d bytes from %s"),
packet->len, device_info);
return 0;
cp
}
return 0;
cp}
int write_packet(vpn_packet_t *packet)
int write_packet(vpn_packet_t * packet)
{
cp
if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_DEBUG, _("Writing packet of %d bytes to %s"),
packet->len, device_info);
cp if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_DEBUG, _("Writing packet of %d bytes to %s"),
packet->len, device_info);
if(write(device_fd, packet->data, packet->len) < 0)
{
syslog(LOG_ERR, _("Error while writing to %s %s: %s"), device_info, device, strerror(errno));
return -1;
}
if(write(device_fd, packet->data, packet->len) < 0) {
syslog(LOG_ERR, _("Error while writing to %s %s: %s"), device_info,
device, strerror(errno));
return -1;
}
device_total_out += packet->len;
cp
}
device_total_out += packet->len;
cp}
void dump_device_stats(void)
{
cp
syslog(LOG_DEBUG, _("Statistics for %s %s:"), device_info, device);
syslog(LOG_DEBUG, _(" total bytes in: %10d"), device_total_in);
syslog(LOG_DEBUG, _(" total bytes out: %10d"), device_total_out);
cp
}
cp syslog(LOG_DEBUG, _("Statistics for %s %s:"), device_info, device);
syslog(LOG_DEBUG, _(" total bytes in: %10d"), device_total_in);
syslog(LOG_DEBUG, _(" total bytes out: %10d"), device_total_out);
cp}

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: graph.c,v 1.1.2.18 2002/09/09 19:39:58 guus Exp $
$Id: graph.c,v 1.1.2.19 2002/09/09 21:24:34 guus Exp $
*/
/* We need to generate two trees from the graph:
@ -51,7 +51,7 @@
#include "config.h"
#include <string.h>
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#include <sys/param.h>
#endif
#include <netinet/in.h>
@ -74,78 +74,79 @@
void mst_kruskal(void)
{
avl_node_t *node, *next;
edge_t *e;
node_t *n;
connection_t *c;
int nodes = 0;
int safe_edges = 0;
int skipped;
avl_node_t *node, *next;
edge_t *e;
node_t *n;
connection_t *c;
int nodes = 0;
int safe_edges = 0;
int skipped;
/* Clear MST status on connections */
cp();
/* Clear MST status on connections */
for(node = connection_tree->head; node; node = node->next)
{
c = (connection_t *)node->data;
c->status.mst = 0;
}
for(node = connection_tree->head; node; node = node->next) {
c = (connection_t *) node->data;
c->status.mst = 0;
}
/* Do we have something to do at all? */
if(!edge_weight_tree->head)
return;
/* Do we have something to do at all? */
if(debug_lvl >= DEBUG_SCARY_THINGS)
syslog(LOG_DEBUG, "Running Kruskal's algorithm:");
if(!edge_weight_tree->head)
return;
/* Clear visited status on nodes */
if(debug_lvl >= DEBUG_SCARY_THINGS)
syslog(LOG_DEBUG, "Running Kruskal's algorithm:");
for(node = node_tree->head; node; node = node->next)
{
n = (node_t *)node->data;
n->status.visited = 0;
nodes++;
}
/* Clear visited status on nodes */
/* Starting point */
((edge_t *)edge_weight_tree->head->data)->from->status.visited = 1;
for(node = node_tree->head; node; node = node->next) {
n = (node_t *) node->data;
n->status.visited = 0;
nodes++;
}
/* Add safe edges */
/* Starting point */
for(skipped = 0, node = edge_weight_tree->head; node; node = next)
{
next = node->next;
e = (edge_t *)node->data;
((edge_t *) edge_weight_tree->head->data)->from->status.visited = 1;
if(!e->reverse || e->from->status.visited == e->to->status.visited)
{
skipped = 1;
continue;
}
/* Add safe edges */
e->from->status.visited = 1;
e->to->status.visited = 1;
if(e->connection)
e->connection->status.mst = 1;
if(e->reverse->connection)
e->reverse->connection->status.mst = 1;
for(skipped = 0, node = edge_weight_tree->head; node; node = next) {
next = node->next;
e = (edge_t *) node->data;
safe_edges++;
if(!e->reverse || e->from->status.visited == e->to->status.visited) {
skipped = 1;
continue;
}
if(debug_lvl >= DEBUG_SCARY_THINGS)
syslog(LOG_DEBUG, " Adding edge %s - %s weight %d", e->from->name, e->to->name, e->weight);
e->from->status.visited = 1;
e->to->status.visited = 1;
if(skipped)
{
skipped = 0;
next = edge_weight_tree->head;
continue;
}
}
if(e->connection)
e->connection->status.mst = 1;
if(debug_lvl >= DEBUG_SCARY_THINGS)
syslog(LOG_DEBUG, "Done, counted %d nodes and %d safe edges.", nodes, safe_edges);
if(e->reverse->connection)
e->reverse->connection->status.mst = 1;
safe_edges++;
if(debug_lvl >= DEBUG_SCARY_THINGS)
syslog(LOG_DEBUG, " Adding edge %s - %s weight %d", e->from->name,
e->to->name, e->weight);
if(skipped) {
skipped = 0;
next = edge_weight_tree->head;
continue;
}
}
if(debug_lvl >= DEBUG_SCARY_THINGS)
syslog(LOG_DEBUG, "Done, counted %d nodes and %d safe edges.", nodes,
safe_edges);
}
/* Implementation of a simple breadth-first search algorithm.
@ -154,144 +155,152 @@ void mst_kruskal(void)
void sssp_bfs(void)
{
avl_node_t *node, *from, *next, *to;
edge_t *e;
node_t *n;
avl_tree_t *todo_tree;
int indirect;
char *name;
char *address, *port;
char *envp[7];
int i;
avl_node_t *node, *from, *next, *to;
edge_t *e;
node_t *n;
avl_tree_t *todo_tree;
int indirect;
char *name;
char *address, *port;
char *envp[7];
int i;
todo_tree = avl_alloc_tree(NULL, NULL);
cp();
/* Clear visited status on nodes */
todo_tree = avl_alloc_tree(NULL, NULL);
for(node = node_tree->head; node; node = node->next)
{
n = (node_t *)node->data;
n->status.visited = 0;
n->status.indirect = 1;
}
/* Clear visited status on nodes */
/* Begin with myself */
for(node = node_tree->head; node; node = node->next) {
n = (node_t *) node->data;
n->status.visited = 0;
n->status.indirect = 1;
}
myself->status.visited = 1;
myself->status.indirect = 0;
myself->nexthop = myself;
myself->via = myself;
node = avl_alloc_node();
node->data = myself;
avl_insert_top(todo_tree, node);
/* Begin with myself */
/* Loop while todo_tree is filled */
myself->status.visited = 1;
myself->status.indirect = 0;
myself->nexthop = myself;
myself->via = myself;
node = avl_alloc_node();
node->data = myself;
avl_insert_top(todo_tree, node);
while(todo_tree->head)
{
for(from = todo_tree->head; from; from = next) /* "from" is the node from which we start */
{
next = from->next;
n = (node_t *)from->data;
/* Loop while todo_tree is filled */
for(to = n->edge_tree->head; to; to = to->next) /* "to" is the edge connected to "from" */
{
e = (edge_t *)to->data;
if(!e->reverse)
continue;
while(todo_tree->head) {
for(from = todo_tree->head; from; from = next) { /* "from" is the node from which we start */
next = from->next;
n = (node_t *) from->data;
/* Situation:
for(to = n->edge_tree->head; to; to = to->next) { /* "to" is the edge connected to "from" */
e = (edge_t *) to->data;
/
/
------(n)-----(e->to)
\
\
if(!e->reverse)
continue;
n->address is set to the e->address of the edge left of n to n.
We are currently examining the edge e right of n from n:
/* Situation:
- If e->reverse->address != n->address, then e->to is probably
not reachable for the nodes left of n. We do as if the indirectdata
flag is set on edge e.
- If edge e provides for better reachability of e->to, update
e->to and (re)add it to the todo_tree to (re)examine the reachability
of nodes behind it.
*/
/
/
------(n)-----(e->to)
\
\
indirect = n->status.indirect || e->options & OPTION_INDIRECT || ((n != myself) && sockaddrcmp(&n->address, &e->reverse->address));
n->address is set to the e->address of the edge left of n to n.
We are currently examining the edge e right of n from n:
if(e->to->status.visited && (!e->to->status.indirect || indirect))
continue;
- If e->reverse->address != n->address, then e->to is probably
not reachable for the nodes left of n. We do as if the indirectdata
flag is set on edge e.
- If edge e provides for better reachability of e->to, update
e->to and (re)add it to the todo_tree to (re)examine the reachability
of nodes behind it.
*/
e->to->status.visited = 1;
e->to->status.indirect = indirect;
e->to->nexthop = (n->nexthop == myself) ? e->to : n->nexthop;
e->to->via = indirect ? n->via : e->to;
e->to->options = e->options;
if(sockaddrcmp(&e->to->address, &e->address))
{
node = avl_unlink(node_udp_tree, e->to);
e->to->address = e->address;
if(e->to->hostname)
free(e->to->hostname);
e->to->hostname = sockaddr2hostname(&e->to->address);
avl_insert_node(node_udp_tree, node);
}
node = avl_alloc_node();
node->data = e->to;
avl_insert_before(todo_tree, from, node);
}
indirect = n->status.indirect || e->options & OPTION_INDIRECT
|| ((n != myself)
&& sockaddrcmp(&n->address, &e->reverse->address));
avl_delete_node(todo_tree, from);
}
}
if(e->to->status.visited
&& (!e->to->status.indirect || indirect))
continue;
avl_free_tree(todo_tree);
/* Check reachability status. */
e->to->status.visited = 1;
e->to->status.indirect = indirect;
e->to->nexthop = (n->nexthop == myself) ? e->to : n->nexthop;
e->to->via = indirect ? n->via : e->to;
e->to->options = e->options;
for(node = node_tree->head; node; node = next)
{
next = node->next;
n = (node_t *)node->data;
if(sockaddrcmp(&e->to->address, &e->address)) {
node = avl_unlink(node_udp_tree, e->to);
e->to->address = e->address;
if(n->status.visited != n->status.reachable)
{
n->status.reachable = !n->status.reachable;
if(debug_lvl >= DEBUG_TRAFFIC)
if(n->status.reachable)
syslog(LOG_DEBUG, _("Node %s (%s) became reachable"), n->name, n->hostname);
else
syslog(LOG_DEBUG, _("Node %s (%s) became unreachable"), n->name, n->hostname);
if(e->to->hostname)
free(e->to->hostname);
n->status.validkey = 0;
n->status.waitingforkey = 0;
e->to->hostname = sockaddr2hostname(&e->to->address);
avl_insert_node(node_udp_tree, node);
}
asprintf(&envp[0], "NETNAME=%s", netname?:"");
asprintf(&envp[1], "DEVICE=%s", device?:"");
asprintf(&envp[2], "INTERFACE=%s", interface?:"");
asprintf(&envp[3], "NODE=%s", n->name);
sockaddr2str(&n->address, &address, &port);
asprintf(&envp[4], "REMOTEADDRESS=%s", address);
asprintf(&envp[5], "REMOTEPORT=%s", port);
envp[6] = NULL;
node = avl_alloc_node();
node->data = e->to;
avl_insert_before(todo_tree, from, node);
}
asprintf(&name, n->status.reachable?"hosts/%s-up":"hosts/%s-down", n->name);
execute_script(name, envp);
free(name);
free(address);
free(port);
avl_delete_node(todo_tree, from);
}
}
for(i = 0; i < 7; i++)
free(envp[i]);
}
}
avl_free_tree(todo_tree);
/* Check reachability status. */
for(node = node_tree->head; node; node = next) {
next = node->next;
n = (node_t *) node->data;
if(n->status.visited != n->status.reachable) {
n->status.reachable = !n->status.reachable;
if(debug_lvl >= DEBUG_TRAFFIC)
if(n->status.reachable)
syslog(LOG_DEBUG, _("Node %s (%s) became reachable"),
n->name, n->hostname);
else
syslog(LOG_DEBUG, _("Node %s (%s) became unreachable"),
n->name, n->hostname);
n->status.validkey = 0;
n->status.waitingforkey = 0;
asprintf(&envp[0], "NETNAME=%s", netname ? : "");
asprintf(&envp[1], "DEVICE=%s", device ? : "");
asprintf(&envp[2], "INTERFACE=%s", interface ? : "");
asprintf(&envp[3], "NODE=%s", n->name);
sockaddr2str(&n->address, &address, &port);
asprintf(&envp[4], "REMOTEADDRESS=%s", address);
asprintf(&envp[5], "REMOTEPORT=%s", port);
envp[6] = NULL;
asprintf(&name,
n->status.reachable ? "hosts/%s-up" : "hosts/%s-down",
n->name);
execute_script(name, envp);
free(name);
free(address);
free(port);
for(i = 0; i < 7; i++)
free(envp[i]);
}
}
}
void graph(void)
{
mst_kruskal();
sssp_bfs();
mst_kruskal();
sssp_bfs();
}

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: device.c,v 1.1.2.10 2002/09/09 19:40:12 guus Exp $
$Id: device.c,v 1.1.2.11 2002/09/09 21:25:23 guus Exp $
*/
#include "config.h"
@ -34,14 +34,14 @@
#include <sys/ioctl.h>
#ifdef HAVE_TUNTAP
#ifdef LINUX_IF_TUN_H
#include LINUX_IF_TUN_H
#else
#include <linux/if_tun.h>
#endif
#define DEFAULT_DEVICE "/dev/misc/net/tun"
#ifdef LINUX_IF_TUN_H
#include LINUX_IF_TUN_H
#else
#define DEFAULT_DEVICE "/dev/tap0"
#include <linux/if_tun.h>
#endif
#define DEFAULT_DEVICE "/dev/misc/net/tun"
#else
#define DEFAULT_DEVICE "/dev/tap0"
#endif
#include <utils.h>
@ -71,160 +71,137 @@ extern subnet_t mymac;
*/
int setup_device(void)
{
struct ifreq ifr;
struct ifreq ifr;
cp
if(!get_config_string(lookup_config(config_tree, "Device"), &device))
device = DEFAULT_DEVICE;
cp if(!get_config_string(lookup_config(config_tree, "Device"), &device))
device = DEFAULT_DEVICE;
if(!get_config_string(lookup_config(config_tree, "Interface"), &interface))
if(!get_config_string(lookup_config(config_tree, "Interface"), &interface))
#ifdef HAVE_TUNTAP
interface = netname;
interface = netname;
#else
interface = rindex(device, '/')?rindex(device, '/')+1:device;
interface = rindex(device, '/') ? rindex(device, '/') + 1 : device;
#endif
cp
device_fd = open(device, O_RDWR | O_NONBLOCK);
cp device_fd = open(device, O_RDWR | O_NONBLOCK);
if(device_fd < 0)
{
syslog(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno));
return -1;
}
cp
/* 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;
if(device_fd < 0) {
syslog(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno));
return -1;
}
cp
/* 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;
#ifdef HAVE_TUNTAP
/* Ok now check if this is an old ethertap or a new tun/tap thingie */
/* 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 (interface)
strncpy(ifr.ifr_name, interface, IFNAMSIZ);
cp
if (!ioctl(device_fd, TUNSETIFF, (void *) &ifr))
{
device_info = _("Linux tun/tap device");
device_type = DEVICE_TYPE_TUNTAP;
strncpy(ifrname, ifr.ifr_name, IFNAMSIZ);
interface = ifrname;
}
else
if (!ioctl(device_fd, (('T'<< 8) | 202), (void *) &ifr))
{
syslog(LOG_WARNING, _("Old ioctl() request was needed for %s"), device);
device_type = DEVICE_TYPE_TUNTAP;
device_info = _("Linux tun/tap device");
strncpy(ifrname, ifr.ifr_name, IFNAMSIZ);
interface = ifrname;
}
else
memset(&ifr, 0, sizeof(ifr));
cp ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
if(interface)
strncpy(ifr.ifr_name, interface, IFNAMSIZ);
cp if(!ioctl(device_fd, TUNSETIFF, (void *) &ifr)) {
device_info = _("Linux tun/tap device");
device_type = DEVICE_TYPE_TUNTAP;
strncpy(ifrname, ifr.ifr_name, IFNAMSIZ);
interface = ifrname;
} else if(!ioctl(device_fd, (('T' << 8) | 202), (void *) &ifr)) {
syslog(LOG_WARNING, _("Old ioctl() request was needed for %s"), device);
device_type = DEVICE_TYPE_TUNTAP;
device_info = _("Linux tun/tap device");
strncpy(ifrname, ifr.ifr_name, IFNAMSIZ);
interface = ifrname;
} else
#endif
{
device_info = _("Linux ethertap device");
device_type = DEVICE_TYPE_ETHERTAP;
interface = rindex(device, '/')?rindex(device, '/')+1:device;
}
{
device_info = _("Linux ethertap device");
device_type = DEVICE_TYPE_ETHERTAP;
interface = rindex(device, '/') ? rindex(device, '/') + 1 : device;
}
syslog(LOG_INFO, _("%s is a %s"), device, device_info);
cp
return 0;
syslog(LOG_INFO, _("%s is a %s"), device, device_info);
cp return 0;
}
void close_device(void)
{
cp
close(device_fd);
cp close(device_fd);
}
/*
read, encrypt and send data that is
available through the ethertap device
*/
int read_packet(vpn_packet_t *packet)
int read_packet(vpn_packet_t * packet)
{
int lenin;
cp
if(device_type == DEVICE_TYPE_TUNTAP)
{
lenin = read(device_fd, packet->data, MTU);
int lenin;
cp if(device_type == DEVICE_TYPE_TUNTAP) {
lenin = read(device_fd, packet->data, MTU);
if(lenin <= 0)
{
syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, device, strerror(errno));
return -1;
}
if(lenin <= 0) {
syslog(LOG_ERR, _("Error while reading from %s %s: %s"),
device_info, device, strerror(errno));
return -1;
}
packet->len = lenin;
}
else /* ethertap */
{
lenin = read(device_fd, packet->data - 2, MTU + 2);
packet->len = lenin;
} else { /* ethertap */
if(lenin <= 0)
{
syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, device, strerror(errno));
return -1;
}
lenin = read(device_fd, packet->data - 2, MTU + 2);
packet->len = lenin - 2;
}
if(lenin <= 0) {
syslog(LOG_ERR, _("Error while reading from %s %s: %s"),
device_info, device, strerror(errno));
return -1;
}
device_total_in += packet->len;
packet->len = lenin - 2;
}
if(debug_lvl >= DEBUG_TRAFFIC)
{
syslog(LOG_DEBUG, _("Read packet of %d bytes from %s"), packet->len, device_info);
}
device_total_in += packet->len;
return 0;
cp
}
if(debug_lvl >= DEBUG_TRAFFIC) {
syslog(LOG_DEBUG, _("Read packet of %d bytes from %s"), packet->len,
device_info);
}
int write_packet(vpn_packet_t *packet)
return 0;
cp}
int write_packet(vpn_packet_t * packet)
{
cp
if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_DEBUG, _("Writing packet of %d bytes to %s"),
packet->len, device_info);
cp if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_DEBUG, _("Writing packet of %d bytes to %s"),
packet->len, device_info);
if(device_type == DEVICE_TYPE_TUNTAP)
{
if(write(device_fd, packet->data, packet->len) < 0)
{
syslog(LOG_ERR, _("Can't write to %s %s: %s"), device_info, device, strerror(errno));
return -1;
}
}
else/* ethertap */
{
*(short int *)(packet->data - 2) = packet->len;
if(write(device_fd, packet->data - 2, packet->len + 2) < 0)
{
syslog(LOG_ERR, _("Can't write to %s %s: %s"), device_info, device, strerror(errno));
return -1;
}
}
if(device_type == DEVICE_TYPE_TUNTAP) {
if(write(device_fd, packet->data, packet->len) < 0) {
syslog(LOG_ERR, _("Can't write to %s %s: %s"), device_info, device,
strerror(errno));
return -1;
}
} else { /* ethertap */
device_total_out += packet->len;
cp
return 0;
*(short int *) (packet->data - 2) = packet->len;
if(write(device_fd, packet->data - 2, packet->len + 2) < 0) {
syslog(LOG_ERR, _("Can't write to %s %s: %s"), device_info, device,
strerror(errno));
return -1;
}
}
device_total_out += packet->len;
cp return 0;
}
void dump_device_stats(void)
{
cp
syslog(LOG_DEBUG, _("Statistics for %s %s:"), device_info, device);
syslog(LOG_DEBUG, _(" total bytes in: %10d"), device_total_in);
syslog(LOG_DEBUG, _(" total bytes out: %10d"), device_total_out);
cp
}
cp syslog(LOG_DEBUG, _("Statistics for %s %s:"), device_info, device);
syslog(LOG_DEBUG, _(" total bytes in: %10d"), device_total_in);
syslog(LOG_DEBUG, _(" total bytes out: %10d"), device_total_out);
cp}

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: meta.c,v 1.1.2.28 2002/09/09 19:39:58 guus Exp $
$Id: meta.c,v 1.1.2.29 2002/09/09 21:24:34 guus Exp $
*/
#include "config.h"
@ -39,173 +39,160 @@
#include "system.h"
#include "protocol.h"
int send_meta(connection_t *c, char *buffer, int length)
int send_meta(connection_t * c, char *buffer, int length)
{
char *bufp;
int outlen;
char outbuf[MAXBUFSIZE];
cp();
if(debug_lvl >= DEBUG_META)
syslog(LOG_DEBUG, _("Sending %d bytes of metadata to %s (%s)"), length,
c->name, c->hostname);
char *bufp;
int outlen;
char outbuf[MAXBUFSIZE];
if(c->status.encryptout)
{
EVP_EncryptUpdate(c->outctx, outbuf, &outlen, buffer, length);
bufp = outbuf;
length = outlen;
}
else
bufp = buffer;
cp();
if(write(c->socket, bufp, length) < 0)
{
syslog(LOG_ERR, _("Sending meta data to %s (%s) failed: %s"), c->name, c->hostname, strerror(errno));
return -1;
}
cp();
return 0;
if(debug_lvl >= DEBUG_META)
syslog(LOG_DEBUG, _("Sending %d bytes of metadata to %s (%s)"), length,
c->name, c->hostname);
if(c->status.encryptout) {
EVP_EncryptUpdate(c->outctx, outbuf, &outlen, buffer, length);
bufp = outbuf;
length = outlen;
} else
bufp = buffer;
if(write(c->socket, bufp, length) < 0) {
syslog(LOG_ERR, _("Sending meta data to %s (%s) failed: %s"), c->name,
c->hostname, strerror(errno));
return -1;
}
return 0;
}
void broadcast_meta(connection_t *from, char *buffer, int length)
void broadcast_meta(connection_t * from, char *buffer, int length)
{
avl_node_t *node;
connection_t *c;
cp();
for(node = connection_tree->head; node; node = node->next)
{
c = (connection_t *)node->data;
if(c != from && c->status.active)
send_meta(c, buffer, length);
}
cp();
avl_node_t *node;
connection_t *c;
cp();
for(node = connection_tree->head; node; node = node->next) {
c = (connection_t *) node->data;
if(c != from && c->status.active)
send_meta(c, buffer, length);
}
}
int receive_meta(connection_t *c)
int receive_meta(connection_t * c)
{
int x, l = sizeof(x);
int oldlen, i;
int lenin, reqlen;
int decrypted = 0;
char inbuf[MAXBUFSIZE];
cp();
if(getsockopt(c->socket, SOL_SOCKET, SO_ERROR, &x, &l) < 0)
{
syslog(LOG_ERR, _("This is a bug: %s:%d: %d:%s %s (%s)"), __FILE__, __LINE__, c->socket, strerror(errno),
c->name, c->hostname);
return -1;
}
if(x)
{
syslog(LOG_ERR, _("Metadata socket error for %s (%s): %s"),
c->name, c->hostname, strerror(x));
return -1;
}
int x, l = sizeof(x);
int oldlen, i;
int lenin, reqlen;
int decrypted = 0;
char inbuf[MAXBUFSIZE];
/* Strategy:
- Read as much as possible from the TCP socket in one go.
- Decrypt it.
- Check if a full request is in the input buffer.
- If yes, process request and remove it from the buffer,
then check again.
- If not, keep stuff in buffer and exit.
*/
cp();
lenin = read(c->socket, c->buffer + c->buflen, MAXBUFSIZE - c->buflen);
if(getsockopt(c->socket, SOL_SOCKET, SO_ERROR, &x, &l) < 0) {
syslog(LOG_ERR, _("This is a bug: %s:%d: %d:%s %s (%s)"), __FILE__,
__LINE__, c->socket, strerror(errno), c->name, c->hostname);
return -1;
}
if(lenin<=0)
{
if(lenin==0)
{
if(debug_lvl >= DEBUG_CONNECTIONS)
syslog(LOG_NOTICE, _("Connection closed by %s (%s)"),
c->name, c->hostname);
}
else
if(errno==EINTR)
return 0;
else
syslog(LOG_ERR, _("Metadata socket read error for %s (%s): %s"),
c->name, c->hostname, strerror(errno));
if(x) {
syslog(LOG_ERR, _("Metadata socket error for %s (%s): %s"),
c->name, c->hostname, strerror(x));
return -1;
}
return -1;
}
/* Strategy:
- Read as much as possible from the TCP socket in one go.
- Decrypt it.
- Check if a full request is in the input buffer.
- If yes, process request and remove it from the buffer,
then check again.
- If not, keep stuff in buffer and exit.
*/
oldlen = c->buflen;
c->buflen += lenin;
lenin = read(c->socket, c->buffer + c->buflen, MAXBUFSIZE - c->buflen);
while(lenin)
{
/* Decrypt */
if(lenin <= 0) {
if(lenin == 0) {
if(debug_lvl >= DEBUG_CONNECTIONS)
syslog(LOG_NOTICE, _("Connection closed by %s (%s)"),
c->name, c->hostname);
} else if(errno == EINTR)
return 0;
else
syslog(LOG_ERR, _("Metadata socket read error for %s (%s): %s"),
c->name, c->hostname, strerror(errno));
if(c->status.decryptin && !decrypted)
{
EVP_DecryptUpdate(c->inctx, inbuf, &lenin, c->buffer + oldlen, lenin);
memcpy(c->buffer + oldlen, inbuf, lenin);
decrypted = 1;
}
return -1;
}
/* Are we receiving a TCPpacket? */
oldlen = c->buflen;
c->buflen += lenin;
if(c->tcplen)
{
if(c->tcplen <= c->buflen)
{
receive_tcppacket(c, c->buffer, c->tcplen);
while(lenin) {
/* Decrypt */
c->buflen -= c->tcplen;
lenin -= c->tcplen;
memmove(c->buffer, c->buffer + c->tcplen, c->buflen);
oldlen = 0;
c->tcplen = 0;
continue;
}
else
{
break;
}
}
if(c->status.decryptin && !decrypted) {
EVP_DecryptUpdate(c->inctx, inbuf, &lenin, c->buffer + oldlen,
lenin);
memcpy(c->buffer + oldlen, inbuf, lenin);
decrypted = 1;
}
/* Otherwise we are waiting for a request */
/* Are we receiving a TCPpacket? */
reqlen = 0;
if(c->tcplen) {
if(c->tcplen <= c->buflen) {
receive_tcppacket(c, c->buffer, c->tcplen);
for(i = oldlen; i < c->buflen; i++)
{
if(c->buffer[i] == '\n')
{
c->buffer[i] = '\0'; /* replace end-of-line by end-of-string so we can use sscanf */
reqlen = i + 1;
break;
}
}
c->buflen -= c->tcplen;
lenin -= c->tcplen;
memmove(c->buffer, c->buffer + c->tcplen, c->buflen);
oldlen = 0;
c->tcplen = 0;
continue;
} else {
break;
}
}
if(reqlen)
{
c->reqlen = reqlen;
if(receive_request(c))
return -1;
/* Otherwise we are waiting for a request */
c->buflen -= reqlen;
lenin -= reqlen;
memmove(c->buffer, c->buffer + reqlen, c->buflen);
oldlen = 0;
continue;
}
else
{
break;
}
}
reqlen = 0;
if(c->buflen >= MAXBUFSIZE)
{
syslog(LOG_ERR, _("Metadata read buffer overflow for %s (%s)"),
c->name, c->hostname);
return -1;
}
for(i = oldlen; i < c->buflen; i++) {
if(c->buffer[i] == '\n') {
c->buffer[i] = '\0'; /* replace end-of-line by end-of-string so we can use sscanf */
reqlen = i + 1;
break;
}
}
c->last_ping_time = now;
cp();
return 0;
if(reqlen) {
c->reqlen = reqlen;
if(receive_request(c))
return -1;
c->buflen -= reqlen;
lenin -= reqlen;
memmove(c->buffer, c->buffer + reqlen, c->buflen);
oldlen = 0;
continue;
} else {
break;
}
}
if(c->buflen >= MAXBUFSIZE) {
syslog(LOG_ERR, _("Metadata read buffer overflow for %s (%s)"),
c->name, c->hostname);
return -1;
}
c->last_ping_time = now;
return 0;
}

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: meta.h,v 1.1.2.7 2002/06/21 10:11:12 guus Exp $
$Id: meta.h,v 1.1.2.8 2002/09/09 21:24:34 guus Exp $
*/
#ifndef __TINC_META_H__
@ -29,4 +29,4 @@ extern int send_meta(connection_t *, const char *, int);
extern int broadcast_meta(connection_t *, const char *, int);
extern int receive_meta(connection_t *);
#endif /* __TINC_META_H__ */
#endif /* __TINC_META_H__ */

507
src/net.c
View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: net.c,v 1.35.4.179 2002/09/09 19:39:58 guus Exp $
$Id: net.c,v 1.35.4.180 2002/09/09 21:24:34 guus Exp $
*/
#include "config.h"
@ -27,13 +27,13 @@
#include <netdb.h>
#include <netinet/in.h>
#ifdef HAVE_NETINET_IN_SYSTM_H
#include <netinet/in_systm.h>
#include <netinet/in_systm.h>
#endif
#ifdef HAVE_NETINET_IP_H
#include <netinet/ip.h>
#include <netinet/ip.h>
#endif
#ifdef HAVE_NETINET_TCP_H
#include <netinet/tcp.h>
#include <netinet/tcp.h>
#endif
#include <stdio.h>
#include <stdlib.h>
@ -87,81 +87,76 @@ time_t now = 0;
void purge(void)
{
avl_node_t *nnode, *nnext, *enode, *enext, *snode, *snext;
node_t *n;
edge_t *e;
subnet_t *s;
cp();
if(debug_lvl >= DEBUG_PROTOCOL)
syslog(LOG_DEBUG, _("Purging unreachable nodes"));
avl_node_t *nnode, *nnext, *enode, *enext, *snode, *snext;
node_t *n;
edge_t *e;
subnet_t *s;
for(nnode = node_tree->head; nnode; nnode = nnext)
{
nnext = nnode->next;
n = (node_t *)nnode->data;
cp();
if(!n->status.reachable)
{
if(debug_lvl >= DEBUG_SCARY_THINGS)
syslog(LOG_DEBUG, _("Purging node %s (%s)"), n->name, n->hostname);
if(debug_lvl >= DEBUG_PROTOCOL)
syslog(LOG_DEBUG, _("Purging unreachable nodes"));
for(snode = n->subnet_tree->head; snode; snode = snext)
{
snext = snode->next;
s = (subnet_t *)snode->data;
send_del_subnet(broadcast, s);
subnet_del(n, s);
}
for(nnode = node_tree->head; nnode; nnode = nnext) {
nnext = nnode->next;
n = (node_t *) nnode->data;
for(enode = n->edge_tree->head; enode; enode = enext)
{
enext = enode->next;
e = (edge_t *)enode->data;
send_del_edge(broadcast, e);
edge_del(e);
}
if(!n->status.reachable) {
if(debug_lvl >= DEBUG_SCARY_THINGS)
syslog(LOG_DEBUG, _("Purging node %s (%s)"), n->name,
n->hostname);
node_del(n);
}
}
cp();
for(snode = n->subnet_tree->head; snode; snode = snext) {
snext = snode->next;
s = (subnet_t *) snode->data;
send_del_subnet(broadcast, s);
subnet_del(n, s);
}
for(enode = n->edge_tree->head; enode; enode = enext) {
enext = enode->next;
e = (edge_t *) enode->data;
send_del_edge(broadcast, e);
edge_del(e);
}
node_del(n);
}
}
}
/*
put all file descriptors in an fd_set array
While we're at it, purge stuff that needs to be removed.
*/
void build_fdset(fd_set *fs)
void build_fdset(fd_set * fs)
{
avl_node_t *node, *next;
connection_t *c;
int i;
cp();
FD_ZERO(fs);
avl_node_t *node, *next;
connection_t *c;
int i;
for(node = connection_tree->head; node; node = next)
{
next = node->next;
c = (connection_t *)node->data;
cp();
if(c->status.remove)
{
connection_del(c);
if(!connection_tree->head)
purge();
}
else
FD_SET(c->socket, fs);
}
FD_ZERO(fs);
for(i = 0; i < listen_sockets; i++)
{
FD_SET(listen_socket[i].tcp, fs);
FD_SET(listen_socket[i].udp, fs);
}
for(node = connection_tree->head; node; node = next) {
next = node->next;
c = (connection_t *) node->data;
FD_SET(device_fd, fs);
cp();
if(c->status.remove) {
connection_del(c);
if(!connection_tree->head)
purge();
} else
FD_SET(c->socket, fs);
}
for(i = 0; i < listen_sockets; i++) {
FD_SET(listen_socket[i].tcp, fs);
FD_SET(listen_socket[i].udp, fs);
}
FD_SET(device_fd, fs);
}
/*
@ -171,45 +166,43 @@ void build_fdset(fd_set *fs)
- Check if we need to retry making an outgoing connection
- Deactivate the host
*/
void terminate_connection(connection_t *c, int report)
void terminate_connection(connection_t * c, int report)
{
cp();
if(c->status.remove)
return;
cp();
if(debug_lvl >= DEBUG_CONNECTIONS)
syslog(LOG_NOTICE, _("Closing connection with %s (%s)"),
c->name, c->hostname);
if(c->status.remove)
return;
c->status.remove = 1;
c->status.active = 0;
if(debug_lvl >= DEBUG_CONNECTIONS)
syslog(LOG_NOTICE, _("Closing connection with %s (%s)"),
c->name, c->hostname);
if(c->node)
c->node->connection = NULL;
c->status.remove = 1;
c->status.active = 0;
if(c->socket)
close(c->socket);
if(c->node)
c->node->connection = NULL;
if(c->edge)
{
if(report)
send_del_edge(broadcast, c->edge);
if(c->socket)
close(c->socket);
edge_del(c->edge);
if(c->edge) {
if(report)
send_del_edge(broadcast, c->edge);
/* Run MST and SSSP algorithms */
edge_del(c->edge);
graph();
}
/* Run MST and SSSP algorithms */
/* Check if this was our outgoing connection */
graph();
}
if(c->outgoing)
{
retry_outgoing(c->outgoing);
c->outgoing = NULL;
}
cp();
/* Check if this was our outgoing connection */
if(c->outgoing) {
retry_outgoing(c->outgoing);
c->outgoing = NULL;
}
}
/*
@ -222,106 +215,99 @@ void terminate_connection(connection_t *c, int report)
*/
void check_dead_connections(void)
{
avl_node_t *node, *next;
connection_t *c;
cp();
for(node = connection_tree->head; node; node = next)
{
next = node->next;
c = (connection_t *)node->data;
if(c->last_ping_time + pingtimeout < now)
{
if(c->status.active)
{
if(c->status.pinged)
{
if(debug_lvl >= DEBUG_PROTOCOL)
syslog(LOG_INFO, _("%s (%s) didn't respond to PING"),
c->name, c->hostname);
c->status.timeout = 1;
terminate_connection(c, 1);
}
else
{
send_ping(c);
}
}
else
{
if(c->status.remove)
{
syslog(LOG_WARNING, _("Old connection_t for %s (%s) status %04x still lingering, deleting..."), c->name, c->hostname, c->status);
connection_del(c);
continue;
}
if(debug_lvl >= DEBUG_CONNECTIONS)
syslog(LOG_WARNING, _("Timeout from %s (%s) during authentication"),
c->name, c->hostname);
terminate_connection(c, 0);
}
}
}
cp();
avl_node_t *node, *next;
connection_t *c;
cp();
for(node = connection_tree->head; node; node = next) {
next = node->next;
c = (connection_t *) node->data;
if(c->last_ping_time + pingtimeout < now) {
if(c->status.active) {
if(c->status.pinged) {
if(debug_lvl >= DEBUG_PROTOCOL)
syslog(LOG_INFO, _("%s (%s) didn't respond to PING"),
c->name, c->hostname);
c->status.timeout = 1;
terminate_connection(c, 1);
} else {
send_ping(c);
}
} else {
if(c->status.remove) {
syslog(LOG_WARNING, _("Old connection_t for %s (%s) status %04x still lingering, deleting..."),
c->name, c->hostname, c->status);
connection_del(c);
continue;
}
if(debug_lvl >= DEBUG_CONNECTIONS)
syslog(LOG_WARNING, _("Timeout from %s (%s) during authentication"),
c->name, c->hostname);
terminate_connection(c, 0);
}
}
}
}
/*
check all connections to see if anything
happened on their sockets
*/
void check_network_activity(fd_set *f)
void check_network_activity(fd_set * f)
{
connection_t *c;
avl_node_t *node;
int result, i;
int len = sizeof(result);
vpn_packet_t packet;
cp();
if(FD_ISSET(device_fd, f))
{
if(!read_packet(&packet))
route_outgoing(&packet);
}
connection_t *c;
avl_node_t *node;
int result, i;
int len = sizeof(result);
vpn_packet_t packet;
for(node = connection_tree->head; node; node = node->next)
{
c = (connection_t *)node->data;
cp();
if(c->status.remove)
continue;
if(FD_ISSET(device_fd, f)) {
if(!read_packet(&packet))
route_outgoing(&packet);
}
if(FD_ISSET(c->socket, f))
{
if(c->status.connecting)
{
c->status.connecting = 0;
getsockopt(c->socket, SOL_SOCKET, SO_ERROR, &result, &len);
if(!result)
finish_connecting(c);
else
{
if(debug_lvl >= DEBUG_CONNECTIONS)
syslog(LOG_DEBUG, _("Error while connecting to %s (%s): %s"), c->name, c->hostname, strerror(result));
close(c->socket);
do_outgoing_connection(c);
continue;
}
}
if(receive_meta(c) < 0)
{
terminate_connection(c, c->status.active);
continue;
}
}
}
for(node = connection_tree->head; node; node = node->next) {
c = (connection_t *) node->data;
for(i = 0; i < listen_sockets; i++)
{
if(FD_ISSET(listen_socket[i].udp, f))
handle_incoming_vpn_data(listen_socket[i].udp);
if(FD_ISSET(listen_socket[i].tcp, f))
handle_new_meta_connection(listen_socket[i].tcp);
}
cp();
if(c->status.remove)
continue;
if(FD_ISSET(c->socket, f)) {
if(c->status.connecting) {
c->status.connecting = 0;
getsockopt(c->socket, SOL_SOCKET, SO_ERROR, &result, &len);
if(!result)
finish_connecting(c);
else {
if(debug_lvl >= DEBUG_CONNECTIONS)
syslog(LOG_DEBUG,
_("Error while connecting to %s (%s): %s"),
c->name, c->hostname, strerror(result));
close(c->socket);
do_outgoing_connection(c);
continue;
}
}
if(receive_meta(c) < 0) {
terminate_connection(c, c->status.active);
continue;
}
}
}
for(i = 0; i < listen_sockets; i++) {
if(FD_ISSET(listen_socket[i].udp, f))
handle_incoming_vpn_data(listen_socket[i].udp);
if(FD_ISSET(listen_socket[i].tcp, f))
handle_new_meta_connection(listen_socket[i].tcp);
}
}
/*
@ -329,115 +315,106 @@ void check_network_activity(fd_set *f)
*/
void main_loop(void)
{
fd_set fset;
struct timeval tv;
int r;
time_t last_ping_check;
event_t *event;
cp();
last_ping_check = now;
fd_set fset;
struct timeval tv;
int r;
time_t last_ping_check;
event_t *event;
srand(now);
cp();
for(;;)
{
now = time(NULL);
last_ping_check = now;
srand(now);
tv.tv_sec = 1 + (rand() & 7); /* Approx. 5 seconds, randomized to prevent global synchronisation effects */
tv.tv_usec = 0;
for(;;) {
now = time(NULL);
build_fdset(&fset);
tv.tv_sec = 1 + (rand() & 7); /* Approx. 5 seconds, randomized to prevent global synchronisation effects */
tv.tv_usec = 0;
r = select(FD_SETSIZE, &fset, NULL, NULL, &tv);
build_fdset(&fset);
if(r < 0)
{
if(errno != EINTR && errno != EAGAIN)
{
syslog(LOG_ERR, _("Error while waiting for input: %s"), strerror(errno));
cp_trace();
dump_connections();
return;
}
r = select(FD_SETSIZE, &fset, NULL, NULL, &tv);
continue;
}
if(r < 0) {
if(errno != EINTR && errno != EAGAIN) {
syslog(LOG_ERR, _("Error while waiting for input: %s"),
strerror(errno));
cp_trace();
dump_connections();
return;
}
check_network_activity(&fset);
continue;
}
if(do_purge)
{
purge();
do_purge = 0;
}
check_network_activity(&fset);
/* Let's check if everybody is still alive */
if(do_purge) {
purge();
do_purge = 0;
}
if(last_ping_check + pingtimeout < now)
{
check_dead_connections();
last_ping_check = now;
/* Let's check if everybody is still alive */
if(routing_mode== RMODE_SWITCH)
age_mac();
if(last_ping_check + pingtimeout < now) {
check_dead_connections();
last_ping_check = now;
age_past_requests();
if(routing_mode == RMODE_SWITCH)
age_mac();
/* Should we regenerate our key? */
age_past_requests();
if(keyexpires < now)
{
if(debug_lvl >= DEBUG_STATUS)
syslog(LOG_INFO, _("Regenerating symmetric key"));
/* Should we regenerate our key? */
RAND_pseudo_bytes(myself->key, myself->keylength);
send_key_changed(broadcast, myself);
keyexpires = now + keylifetime;
}
}
if(keyexpires < now) {
if(debug_lvl >= DEBUG_STATUS)
syslog(LOG_INFO, _("Regenerating symmetric key"));
RAND_pseudo_bytes(myself->key, myself->keylength);
send_key_changed(broadcast, myself);
keyexpires = now + keylifetime;
}
}
while((event = get_expired_event()))
{
event->handler(event->data);
free(event);
}
while((event = get_expired_event())) {
event->handler(event->data);
free(event);
}
if(sigalrm)
{
syslog(LOG_INFO, _("Flushing event queue"));
if(sigalrm) {
syslog(LOG_INFO, _("Flushing event queue"));
while(event_tree->head)
{
event = (event_t *)event_tree->head->data;
event->handler(event->data);
event_del(event);
}
sigalrm = 0;
}
while(event_tree->head) {
event = (event_t *) event_tree->head->data;
event->handler(event->data);
event_del(event);
}
sigalrm = 0;
}
if(sighup)
{
sighup = 0;
close_network_connections();
exit_configuration(&config_tree);
if(sighup) {
sighup = 0;
close_network_connections();
exit_configuration(&config_tree);
syslog(LOG_INFO, _("Rereading configuration file and restarting in 5 seconds..."));
sleep(5);
syslog(LOG_INFO, _("Rereading configuration file and restarting in 5 seconds..."));
sleep(5);
init_configuration(&config_tree);
init_configuration(&config_tree);
if(read_server_config())
{
syslog(LOG_ERR, _("Unable to reread configuration file, exitting."));
exit(1);
}
if(read_server_config()) {
syslog(LOG_ERR,
_("Unable to reread configuration file, exitting."));
exit(1);
}
if(setup_network_connections())
return;
if(setup_network_connections())
return;
continue;
}
}
cp();
continue;
}
}
}

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: net.h,v 1.9.4.52 2002/06/21 10:11:12 guus Exp $
$Id: net.h,v 1.9.4.53 2002/09/09 21:24:36 guus Exp $
*/
#ifndef __TINC_NET_H__
@ -29,43 +29,40 @@
#include <sys/time.h>
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#include <inttypes.h>
#endif
#include "config.h"
#ifdef ENABLE_JUMBOGRAMS
#define MTU 9014 /* 9000 bytes payload + 14 bytes ethernet header */
#define MAXSIZE 9100 /* MTU + header (seqno) and trailer (CBC padding and HMAC) */
#define MAXBUFSIZE 9100 /* Must support TCP packets of length 9000. */
#define MTU 9014 /* 9000 bytes payload + 14 bytes ethernet header */
#define MAXSIZE 9100 /* MTU + header (seqno) and trailer (CBC padding and HMAC) */
#define MAXBUFSIZE 9100 /* Must support TCP packets of length 9000. */
#else
#define MTU 1514 /* 1500 bytes payload + 14 bytes ethernet header */
#define MAXSIZE 1600 /* MTU + header (seqno) and trailer (CBC padding and HMAC) */
#define MAXBUFSIZE 2100 /* Quite large but needed for support of keys up to 8192 bits. */
#define MTU 1514 /* 1500 bytes payload + 14 bytes ethernet header */
#define MAXSIZE 1600 /* MTU + header (seqno) and trailer (CBC padding and HMAC) */
#define MAXBUFSIZE 2100 /* Quite large but needed for support of keys up to 8192 bits. */
#endif
#define MAXSOCKETS 128 /* Overkill... */
#define MAXSOCKETS 128 /* Overkill... */
#define MAXQUEUELENGTH 8 /* Maximum number of packats in a single queue */
#define MAXQUEUELENGTH 8 /* Maximum number of packats in a single queue */
typedef struct mac_t
{
uint8_t x[6];
typedef struct mac_t {
uint8_t x[6];
} mac_t;
typedef struct ipv4_t
{
uint8_t x[4];
typedef struct ipv4_t {
uint8_t x[4];
} ipv4_t;
typedef struct ip_mask_t {
ipv4_t address;
ipv4_t mask;
ipv4_t address;
ipv4_t mask;
} ip_mask_t;
typedef struct ipv6_t
{
uint16_t x[8];
typedef struct ipv6_t {
uint16_t x[8];
} ipv6_t;
typedef unsigned short port_t;
@ -73,9 +70,9 @@ typedef unsigned short port_t;
typedef short length_t;
typedef union {
struct sockaddr sa;
struct sockaddr_in in;
struct sockaddr_in6 in6;
struct sockaddr sa;
struct sockaddr_in in;
struct sockaddr_in6 in6;
} sockaddr_t;
#ifdef SA_LEN
@ -85,35 +82,35 @@ typedef union {
#endif
typedef struct vpn_packet_t {
length_t len; /* the actual number of bytes in the `data' field */
int priority; /* priority or TOS */
uint32_t seqno; /* 32 bits sequence number (network byte order of course) */
uint8_t data[MAXSIZE];
length_t len; /* the actual number of bytes in the `data' field */
int priority; /* priority or TOS */
uint32_t seqno; /* 32 bits sequence number (network byte order of course) */
uint8_t data[MAXSIZE];
} vpn_packet_t;
typedef struct queue_element_t {
void *packet;
struct queue_element_t *prev;
struct queue_element_t *next;
void *packet;
struct queue_element_t *prev;
struct queue_element_t *next;
} queue_element_t;
typedef struct packet_queue_t {
queue_element_t *head;
queue_element_t *tail;
queue_element_t *head;
queue_element_t *tail;
} packet_queue_t;
typedef struct outgoing_t {
char *name;
int timeout;
struct config_t *cfg;
struct addrinfo *ai;
struct addrinfo *aip;
char *name;
int timeout;
struct config_t *cfg;
struct addrinfo *ai;
struct addrinfo *aip;
} outgoing_t;
typedef struct listen_socket_t {
int tcp;
int udp;
sockaddr_t sa;
int tcp;
int udp;
sockaddr_t sa;
} listen_socket_t;
extern int maxtimeout;
@ -123,7 +120,7 @@ extern int addressfamily;
extern char *request_name[];
extern char *status_text[];
#include "connection.h" /* Yes, very strange placement indeed, but otherwise the typedefs get all tangled up */
#include "connection.h" /* Yes, very strange placement indeed, but otherwise the typedefs get all tangled up */
extern listen_socket_t listen_socket[MAXSOCKETS];
extern int listen_sockets;
@ -154,4 +151,4 @@ extern void terminate_connection(connection_t *, int);
extern void flush_queue(struct node_t *);
extern int read_rsa_public_key(struct connection_t *);
#endif /* __TINC_NET_H__ */
#endif /* __TINC_NET_H__ */

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: net_packet.c,v 1.1.2.21 2002/09/09 19:39:58 guus Exp $
$Id: net_packet.c,v 1.1.2.22 2002/09/09 21:24:41 guus Exp $
*/
#include "config.h"
@ -27,13 +27,13 @@
#include <netdb.h>
#include <netinet/in.h>
#ifdef HAVE_NETINET_IN_SYSTM_H
#include <netinet/in_systm.h>
#include <netinet/in_systm.h>
#endif
#ifdef HAVE_NETINET_IP_H
#include <netinet/ip.h>
#include <netinet/ip.h>
#endif
#ifdef HAVE_NETINET_TCP_H
#include <netinet/tcp.h>
#include <netinet/tcp.h>
#endif
#include <stdio.h>
#include <stdlib.h>
@ -85,349 +85,353 @@ int keyexpires = 0;
/* VPN packet I/O */
void receive_udppacket(node_t *n, vpn_packet_t *inpkt)
void receive_udppacket(node_t * n, vpn_packet_t * inpkt)
{
vpn_packet_t pkt1, pkt2;
vpn_packet_t *pkt[] = {&pkt1, &pkt2, &pkt1, &pkt2};
int nextpkt = 0;
vpn_packet_t *outpkt = pkt[0];
int outlen, outpad;
long int complen = MTU + 12;
EVP_CIPHER_CTX ctx;
char hmac[EVP_MAX_MD_SIZE];
cp();
/* Check the message authentication code */
vpn_packet_t pkt1, pkt2;
vpn_packet_t *pkt[] = { &pkt1, &pkt2, &pkt1, &pkt2 };
int nextpkt = 0;
vpn_packet_t *outpkt = pkt[0];
int outlen, outpad;
long int complen = MTU + 12;
EVP_CIPHER_CTX ctx;
char hmac[EVP_MAX_MD_SIZE];
if(myself->digest && myself->maclength)
{
inpkt->len -= myself->maclength;
HMAC(myself->digest, myself->key, myself->keylength, (char *)&inpkt->seqno, inpkt->len, hmac, NULL);
if(memcmp(hmac, (char *)&inpkt->seqno + inpkt->len, myself->maclength))
{
if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_DEBUG, _("Got unauthenticated packet from %s (%s)"), n->name, n->hostname);
return;
}
}
cp();
/* Decrypt the packet */
/* Check the message authentication code */
if(myself->cipher)
{
outpkt = pkt[nextpkt++];
if(myself->digest && myself->maclength) {
inpkt->len -= myself->maclength;
HMAC(myself->digest, myself->key, myself->keylength,
(char *) &inpkt->seqno, inpkt->len, hmac, NULL);
EVP_DecryptInit(&ctx, myself->cipher, myself->key, myself->key + myself->cipher->key_len);
EVP_DecryptUpdate(&ctx, (char *)&outpkt->seqno, &outlen, (char *)&inpkt->seqno, inpkt->len);
EVP_DecryptFinal(&ctx, (char *)&outpkt->seqno + outlen, &outpad);
if(memcmp(hmac, (char *) &inpkt->seqno + inpkt->len, myself->maclength)) {
if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_DEBUG, _("Got unauthenticated packet from %s (%s)"),
n->name, n->hostname);
return;
}
}
outpkt->len = outlen + outpad;
inpkt = outpkt;
}
/* Decrypt the packet */
/* Check the sequence number */
if(myself->cipher) {
outpkt = pkt[nextpkt++];
inpkt->len -= sizeof(inpkt->seqno);
inpkt->seqno = ntohl(inpkt->seqno);
EVP_DecryptInit(&ctx, myself->cipher, myself->key,
myself->key + myself->cipher->key_len);
EVP_DecryptUpdate(&ctx, (char *) &outpkt->seqno, &outlen,
(char *) &inpkt->seqno, inpkt->len);
EVP_DecryptFinal(&ctx, (char *) &outpkt->seqno + outlen, &outpad);
if(inpkt->seqno <= n->received_seqno)
{
if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_DEBUG, _("Got late or replayed packet from %s (%s), seqno %d"), n->name, n->hostname, inpkt->seqno);
return;
}
n->received_seqno = inpkt->seqno;
outpkt->len = outlen + outpad;
inpkt = outpkt;
}
if(n->received_seqno > MAX_SEQNO)
keyexpires = 0;
/* Check the sequence number */
/* Decompress the packet */
if(myself->compression)
{
outpkt = pkt[nextpkt++];
inpkt->len -= sizeof(inpkt->seqno);
inpkt->seqno = ntohl(inpkt->seqno);
if(uncompress(outpkt->data, &complen, inpkt->data, inpkt->len) != Z_OK)
{
syslog(LOG_ERR, _("Error while uncompressing packet from %s (%s)"), n->name, n->hostname);
return;
}
outpkt->len = complen;
inpkt = outpkt;
}
if(inpkt->seqno <= n->received_seqno) {
if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_DEBUG,
_("Got late or replayed packet from %s (%s), seqno %d"),
n->name, n->hostname, inpkt->seqno);
return;
}
receive_packet(n, inpkt);
cp();
n->received_seqno = inpkt->seqno;
if(n->received_seqno > MAX_SEQNO)
keyexpires = 0;
/* Decompress the packet */
if(myself->compression) {
outpkt = pkt[nextpkt++];
if(uncompress(outpkt->data, &complen, inpkt->data, inpkt->len) != Z_OK) {
syslog(LOG_ERR, _("Error while uncompressing packet from %s (%s)"),
n->name, n->hostname);
return;
}
outpkt->len = complen;
inpkt = outpkt;
}
receive_packet(n, inpkt);
}
void receive_tcppacket(connection_t *c, char *buffer, int len)
void receive_tcppacket(connection_t * c, char *buffer, int len)
{
vpn_packet_t outpkt;
cp();
outpkt.len = len;
memcpy(outpkt.data, buffer, len);
vpn_packet_t outpkt;
receive_packet(c->node, &outpkt);
cp();
cp();
outpkt.len = len;
memcpy(outpkt.data, buffer, len);
receive_packet(c->node, &outpkt);
}
void receive_packet(node_t *n, vpn_packet_t *packet)
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);
cp();
route_incoming(n, 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);
}
void send_udppacket(node_t *n, vpn_packet_t *inpkt)
void send_udppacket(node_t * n, vpn_packet_t * inpkt)
{
vpn_packet_t pkt1, pkt2;
vpn_packet_t *pkt[] = {&pkt1, &pkt2, &pkt1, &pkt2};
int nextpkt = 0;
vpn_packet_t *outpkt;
int origlen;
int outlen, outpad;
long int complen = MTU + 12;
EVP_CIPHER_CTX ctx;
vpn_packet_t *copy;
static int priority = 0;
int origpriority;
int sock;
cp();
/* Make sure we have a valid key */
vpn_packet_t pkt1, pkt2;
vpn_packet_t *pkt[] = { &pkt1, &pkt2, &pkt1, &pkt2 };
int nextpkt = 0;
vpn_packet_t *outpkt;
int origlen;
int outlen, outpad;
long int complen = MTU + 12;
EVP_CIPHER_CTX ctx;
vpn_packet_t *copy;
static int priority = 0;
int origpriority;
int sock;
if(!n->status.validkey)
{
if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_INFO, _("No valid key known yet for %s (%s), queueing packet"),
n->name, n->hostname);
cp();
/* Since packet is on the stack of handle_tap_input(),
we have to make a copy of it first. */
/* Make sure we have a valid key */
copy = xmalloc(sizeof(vpn_packet_t));
memcpy(copy, inpkt, sizeof(vpn_packet_t));
if(!n->status.validkey) {
if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_INFO,
_("No valid key known yet for %s (%s), queueing packet"),
n->name, n->hostname);
list_insert_tail(n->queue, copy);
/* Since packet is on the stack of handle_tap_input(), we have to make a copy of it first. */
if(n->queue->count > MAXQUEUELENGTH)
list_delete_head(n->queue);
copy = xmalloc(sizeof(vpn_packet_t));
memcpy(copy, inpkt, sizeof(vpn_packet_t));
if(!n->status.waitingforkey)
send_req_key(n->nexthop->connection, myself, n);
list_insert_tail(n->queue, copy);
n->status.waitingforkey = 1;
if(n->queue->count > MAXQUEUELENGTH)
list_delete_head(n->queue);
return;
}
if(!n->status.waitingforkey)
send_req_key(n->nexthop->connection, myself, n);
origlen = inpkt->len;
origpriority = inpkt->priority;
n->status.waitingforkey = 1;
/* Compress the packet */
return;
}
if(n->compression)
{
outpkt = pkt[nextpkt++];
origlen = inpkt->len;
origpriority = inpkt->priority;
if(compress2(outpkt->data, &complen, inpkt->data, inpkt->len, n->compression) != Z_OK)
{
syslog(LOG_ERR, _("Error while compressing packet to %s (%s)"), n->name, n->hostname);
return;
}
outpkt->len = complen;
inpkt = outpkt;
}
/* Compress the packet */
/* Add sequence number */
if(n->compression) {
outpkt = pkt[nextpkt++];
inpkt->seqno = htonl(++(n->sent_seqno));
inpkt->len += sizeof(inpkt->seqno);
if(compress2
(outpkt->data, &complen, inpkt->data, inpkt->len,
n->compression) != Z_OK) {
syslog(LOG_ERR, _("Error while compressing packet to %s (%s)"),
n->name, n->hostname);
return;
}
/* Encrypt the packet */
outpkt->len = complen;
inpkt = outpkt;
}
if(n->cipher)
{
outpkt = pkt[nextpkt++];
/* Add sequence number */
EVP_EncryptInit(&ctx, n->cipher, n->key, n->key + n->cipher->key_len);
EVP_EncryptUpdate(&ctx, (char *)&outpkt->seqno, &outlen, (char *)&inpkt->seqno, inpkt->len);
EVP_EncryptFinal(&ctx, (char *)&outpkt->seqno + outlen, &outpad);
inpkt->seqno = htonl(++(n->sent_seqno));
inpkt->len += sizeof(inpkt->seqno);
outpkt->len = outlen + outpad;
inpkt = outpkt;
}
/* Encrypt the packet */
/* Add the message authentication code */
if(n->cipher) {
outpkt = pkt[nextpkt++];
if(n->digest && n->maclength)
{
HMAC(n->digest, n->key, n->keylength, (char *)&inpkt->seqno, inpkt->len, (char *)&inpkt->seqno + inpkt->len, &outlen);
inpkt->len += n->maclength;
}
EVP_EncryptInit(&ctx, n->cipher, n->key, n->key + n->cipher->key_len);
EVP_EncryptUpdate(&ctx, (char *) &outpkt->seqno, &outlen,
(char *) &inpkt->seqno, inpkt->len);
EVP_EncryptFinal(&ctx, (char *) &outpkt->seqno + outlen, &outpad);
/* Determine which socket we have to use */
outpkt->len = outlen + outpad;
inpkt = outpkt;
}
for(sock = 0; sock < listen_sockets; sock++)
if(n->address.sa.sa_family == listen_socket[sock].sa.sa.sa_family)
break;
/* Add the message authentication code */
if(sock >= listen_sockets)
sock = 0; /* If none is available, just use the first and hope for the best. */
/* Send the packet */
if(n->digest && n->maclength) {
HMAC(n->digest, n->key, n->keylength, (char *) &inpkt->seqno,
inpkt->len, (char *) &inpkt->seqno + inpkt->len, &outlen);
inpkt->len += n->maclength;
}
/* Determine which socket we have to use */
for(sock = 0; sock < listen_sockets; sock++)
if(n->address.sa.sa_family == listen_socket[sock].sa.sa.sa_family)
break;
if(sock >= listen_sockets)
sock = 0; /* If none is available, just use the first and hope for the best. */
/* Send the packet */
#if defined(SOL_IP) && defined(IP_TOS)
if(priorityinheritance && origpriority != priority && listen_socket[sock].sa.sa.sa_family == AF_INET)
{
priority = origpriority;
if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_DEBUG, _("Setting outgoing packet priority to %d"), priority);
if(setsockopt(sock, SOL_IP, IP_TOS, &priority, sizeof(priority))) /* SO_PRIORITY doesn't seem to work */
syslog(LOG_ERR, _("System call `%s' failed: %s"), "setsockopt", strerror(errno));
}
if(priorityinheritance && origpriority != priority
&& listen_socket[sock].sa.sa.sa_family == AF_INET) {
priority = origpriority;
if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_DEBUG, _("Setting outgoing packet priority to %d"),
priority);
if(setsockopt(sock, SOL_IP, IP_TOS, &priority, sizeof(priority))) /* SO_PRIORITY doesn't seem to work */
syslog(LOG_ERR, _("System call `%s' failed: %s"), "setsockopt",
strerror(errno));
}
#endif
if((sendto(listen_socket[sock].udp, (char *)&inpkt->seqno, inpkt->len, 0, &(n->address.sa), SALEN(n->address.sa))) < 0)
{
syslog(LOG_ERR, _("Error sending packet to %s (%s): %s"),
n->name, n->hostname, strerror(errno));
return;
}
inpkt->len = origlen;
cp();
if((sendto(listen_socket[sock].udp, (char *) &inpkt->seqno, inpkt->len, 0, &(n->address.sa), SALEN(n->address.sa))) < 0) {
syslog(LOG_ERR, _("Error sending packet to %s (%s): %s"), n->name,
n->hostname, strerror(errno));
return;
}
inpkt->len = origlen;
}
/*
send a packet to the given vpn ip.
*/
void send_packet(node_t *n, vpn_packet_t *packet)
void send_packet(node_t * n, vpn_packet_t * packet)
{
node_t *via;
cp();
if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_ERR, _("Sending packet of %d bytes to %s (%s)"),
packet->len, n->name, n->hostname);
node_t *via;
if(n == myself)
{
if(debug_lvl >= DEBUG_TRAFFIC)
{
syslog(LOG_NOTICE, _("Packet is looping back to us!"));
}
cp();
return;
}
if(!n->status.reachable)
{
if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_INFO, _("Node %s (%s) is not reachable"),
n->name, n->hostname);
return;
}
if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_ERR, _("Sending packet of %d bytes to %s (%s)"),
packet->len, n->name, n->hostname);
via = (n->via == myself)?n->nexthop:n->via;
if(n == myself) {
if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_NOTICE, _("Packet is looping back to us!"));
if(via != n && debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_ERR, _("Sending packet to %s via %s (%s)"),
n->name, via->name, n->via->hostname);
return;
}
if((myself->options | via->options) & OPTION_TCPONLY)
{
if(send_tcppacket(via->connection, packet))
terminate_connection(via->connection, 1);
}
else
send_udppacket(via, packet);
if(!n->status.reachable) {
if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_INFO, _("Node %s (%s) is not reachable"),
n->name, n->hostname);
return;
}
via = (n->via == myself) ? n->nexthop : n->via;
if(via != n && debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_ERR, _("Sending packet to %s via %s (%s)"),
n->name, via->name, n->via->hostname);
if((myself->options | via->options) & OPTION_TCPONLY) {
if(send_tcppacket(via->connection, packet))
terminate_connection(via->connection, 1);
} else
send_udppacket(via, packet);
}
/* Broadcast a packet using the minimum spanning tree */
void broadcast_packet(node_t *from, vpn_packet_t *packet)
void broadcast_packet(node_t * from, vpn_packet_t * packet)
{
avl_node_t *node;
connection_t *c;
cp();
if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_INFO, _("Broadcasting packet of %d bytes from %s (%s)"),
packet->len, from->name, from->hostname);
avl_node_t *node;
connection_t *c;
for(node = connection_tree->head; node; node = node->next)
{
c = (connection_t *)node->data;
if(c->status.active && c->status.mst && c != from->nexthop->connection)
send_packet(c->node, packet);
}
cp();
cp();
if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_INFO, _("Broadcasting packet of %d bytes from %s (%s)"),
packet->len, from->name, from->hostname);
for(node = connection_tree->head; node; node = node->next) {
c = (connection_t *) node->data;
if(c->status.active && c->status.mst && c != from->nexthop->connection)
send_packet(c->node, packet);
}
}
void flush_queue(node_t *n)
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)"), n->name, n->hostname);
list_node_t *node, *next;
for(node = n->queue->head; node; node = next)
{
next = node->next;
send_udppacket(n, (vpn_packet_t *)node->data);
list_delete_node(n->queue, node);
}
cp();
cp();
if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_INFO, _("Flushing queue for %s (%s)"), n->name, n->hostname);
for(node = n->queue->head; node; node = next) {
next = node->next;
send_udppacket(n, (vpn_packet_t *) node->data);
list_delete_node(n->queue, node);
}
}
void handle_incoming_vpn_data(int sock)
{
vpn_packet_t pkt;
int x, l = sizeof(x);
char *hostname;
sockaddr_t from;
socklen_t fromlen = sizeof(from);
node_t *n;
cp();
if(getsockopt(sock, SOL_SOCKET, SO_ERROR, &x, &l) < 0)
{
syslog(LOG_ERR, _("This is a bug: %s:%d: %d:%s"),
__FILE__, __LINE__, sock, strerror(errno));
cp_trace();
exit(1);
}
if(x)
{
syslog(LOG_ERR, _("Incoming data socket error: %s"), strerror(x));
return;
}
vpn_packet_t pkt;
int x, l = sizeof(x);
char *hostname;
sockaddr_t from;
socklen_t fromlen = sizeof(from);
node_t *n;
pkt.len = recvfrom(sock, (char *)&pkt.seqno, MAXSIZE, 0, &from.sa, &fromlen);
cp();
if(pkt.len <= 0)
{
syslog(LOG_ERR, _("Receiving packet failed: %s"), strerror(errno));
return;
}
if(getsockopt(sock, SOL_SOCKET, SO_ERROR, &x, &l) < 0) {
syslog(LOG_ERR, _("This is a bug: %s:%d: %d:%s"),
__FILE__, __LINE__, sock, strerror(errno));
cp_trace();
exit(1);
}
sockaddrunmap(&from); /* Some braindead IPv6 implementations do stupid things. */
if(x) {
syslog(LOG_ERR, _("Incoming data socket error: %s"), strerror(x));
return;
}
n = lookup_node_udp(&from);
pkt.len = recvfrom(sock, (char *) &pkt.seqno, MAXSIZE, 0, &from.sa, &fromlen);
if(!n)
{
hostname = sockaddr2hostname(&from);
syslog(LOG_WARNING, _("Received UDP packet from unknown source %s"), hostname);
free(hostname);
return;
}
if(pkt.len <= 0) {
syslog(LOG_ERR, _("Receiving packet failed: %s"), strerror(errno));
return;
}
if(n->connection)
n->connection->last_ping_time = now;
sockaddrunmap(&from); /* Some braindead IPv6 implementations do stupid things. */
receive_udppacket(n, &pkt);
cp();
n = lookup_node_udp(&from);
if(!n) {
hostname = sockaddr2hostname(&from);
syslog(LOG_WARNING, _("Received UDP packet from unknown source %s"),
hostname);
free(hostname);
return;
}
if(n->connection)
n->connection->last_ping_time = now;
receive_udppacket(n, &pkt);
}

File diff suppressed because it is too large Load diff

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: net_socket.c,v 1.1.2.19 2002/09/09 19:39:59 guus Exp $
$Id: net_socket.c,v 1.1.2.20 2002/09/09 21:24:41 guus Exp $
*/
#include "config.h"
@ -27,13 +27,13 @@
#include <netdb.h>
#include <netinet/in.h>
#ifdef HAVE_NETINET_IN_SYSTM_H
#include <netinet/in_systm.h>
#include <netinet/in_systm.h>
#endif
#ifdef HAVE_NETINET_IP_H
#include <netinet/ip.h>
#include <netinet/ip.h>
#endif
#ifdef HAVE_NETINET_TCP_H
#include <netinet/tcp.h>
#include <netinet/tcp.h>
#endif
#include <stdio.h>
#include <stdlib.h>
@ -84,357 +84,369 @@ int listen_sockets;
/* Setup sockets */
int setup_listen_socket(sockaddr_t *sa)
int setup_listen_socket(sockaddr_t * sa)
{
int nfd, flags;
char *addrstr;
int option;
int nfd, flags;
char *addrstr;
int option;
#if defined(SOL_SOCKET) && defined(SO_BINDTODEVICE)
char *interface;
struct ifreq ifr;
char *interface;
struct ifreq ifr;
#endif
cp();
nfd = socket(sa->sa.sa_family, SOCK_STREAM, IPPROTO_TCP);
if(nfd < 0)
{
syslog(LOG_ERR, _("Creating metasocket failed: %s"), strerror(errno));
return -1;
}
cp();
flags = fcntl(nfd, F_GETFL);
if(fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0)
{
close(nfd);
syslog(LOG_ERR, _("System call `%s' failed: %s"), "fcntl", strerror(errno));
return -1;
}
nfd = socket(sa->sa.sa_family, SOCK_STREAM, IPPROTO_TCP);
/* Optimize TCP settings */
if(nfd < 0) {
syslog(LOG_ERR, _("Creating metasocket failed: %s"), strerror(errno));
return -1;
}
option = 1;
setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option));
flags = fcntl(nfd, F_GETFL);
if(fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0) {
close(nfd);
syslog(LOG_ERR, _("System call `%s' failed: %s"), "fcntl",
strerror(errno));
return -1;
}
/* Optimize TCP settings */
option = 1;
setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option));
#if defined(SOL_TCP) && defined(TCP_NODELAY)
setsockopt(nfd, SOL_TCP, TCP_NODELAY, &option, sizeof(option));
setsockopt(nfd, SOL_TCP, TCP_NODELAY, &option, sizeof(option));
#endif
#if defined(SOL_IP) && defined(IP_TOS) && defined(IPTOS_LOWDELAY)
option = IPTOS_LOWDELAY;
setsockopt(nfd, SOL_IP, IP_TOS, &option, sizeof(option));
option = IPTOS_LOWDELAY;
setsockopt(nfd, SOL_IP, IP_TOS, &option, sizeof(option));
#endif
if(get_config_string(lookup_config(config_tree, "BindToInterface"), &interface))
{
if(get_config_string
(lookup_config(config_tree, "BindToInterface"), &interface)) {
#if defined(SOL_SOCKET) && defined(SO_BINDTODEVICE)
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_ifrn.ifrn_name, interface, IFNAMSIZ);
if(setsockopt(nfd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)))
{
close(nfd);
syslog(LOG_ERR, _("Can't bind to interface %s: %s"), interface, strerror(errno));
return -1;
}
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_ifrn.ifrn_name, interface, IFNAMSIZ);
if(setsockopt(nfd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr))) {
close(nfd);
syslog(LOG_ERR, _("Can't bind to interface %s: %s"), interface,
strerror(errno));
return -1;
}
#else
syslog(LOG_WARNING, _("BindToDevice not supported on this platform"));
syslog(LOG_WARNING, _("BindToDevice not supported on this platform"));
#endif
}
if(bind(nfd, &sa->sa, SALEN(sa->sa)))
{
close(nfd);
addrstr = sockaddr2hostname(sa);
syslog(LOG_ERR, _("Can't bind to %s/tcp: %s"), addrstr, strerror(errno));
free(addrstr);
return -1;
}
if(listen(nfd, 3))
{
close(nfd);
syslog(LOG_ERR, _("System call `%s' failed: %s"), "listen", strerror(errno));
return -1;
}
cp();
return nfd;
}
int setup_vpn_in_socket(sockaddr_t *sa)
{
int nfd, flags;
char *addrstr;
int option;
#if defined(SOL_SOCKET) && defined(SO_BINDTODEVICE)
char *interface;
struct ifreq ifr;
#endif
cp();
nfd = socket(sa->sa.sa_family, SOCK_DGRAM, IPPROTO_UDP);
if(nfd < 0)
{
syslog(LOG_ERR, _("Creating UDP socket failed: %s"), strerror(errno));
return -1;
}
flags = fcntl(nfd, F_GETFL);
if(fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0)
{
close(nfd);
syslog(LOG_ERR, _("System call `%s' failed: %s"), "fcntl", strerror(errno));
return -1;
}
option = 1;
setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option));
#if defined(SOL_SOCKET) && defined(SO_BINDTODEVICE)
if(get_config_string(lookup_config(config_tree, "BindToInterface"), &interface))
{
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_ifrn.ifrn_name, interface, IFNAMSIZ);
if(setsockopt(nfd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)))
{
close(nfd);
syslog(LOG_ERR, _("Can't bind to interface %s: %s"), interface, strerror(errno));
return -1;
}
}
if(bind(nfd, &sa->sa, SALEN(sa->sa))) {
close(nfd);
addrstr = sockaddr2hostname(sa);
syslog(LOG_ERR, _("Can't bind to %s/tcp: %s"), addrstr,
strerror(errno));
free(addrstr);
return -1;
}
if(listen(nfd, 3)) {
close(nfd);
syslog(LOG_ERR, _("System call `%s' failed: %s"), "listen",
strerror(errno));
return -1;
}
return nfd;
}
int setup_vpn_in_socket(sockaddr_t * sa)
{
int nfd, flags;
char *addrstr;
int option;
#if defined(SOL_SOCKET) && defined(SO_BINDTODEVICE)
char *interface;
struct ifreq ifr;
#endif
if(bind(nfd, &sa->sa, SALEN(sa->sa)))
{
close(nfd);
addrstr = sockaddr2hostname(sa);
syslog(LOG_ERR, _("Can't bind to %s/udp: %s"), addrstr, strerror(errno));
free(addrstr);
return -1;
}
cp();
return nfd;
cp();
nfd = socket(sa->sa.sa_family, SOCK_DGRAM, IPPROTO_UDP);
if(nfd < 0) {
syslog(LOG_ERR, _("Creating UDP socket failed: %s"), strerror(errno));
return -1;
}
flags = fcntl(nfd, F_GETFL);
if(fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0) {
close(nfd);
syslog(LOG_ERR, _("System call `%s' failed: %s"), "fcntl",
strerror(errno));
return -1;
}
option = 1;
setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option));
#if defined(SOL_SOCKET) && defined(SO_BINDTODEVICE)
if(get_config_string
(lookup_config(config_tree, "BindToInterface"), &interface)) {
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_ifrn.ifrn_name, interface, IFNAMSIZ);
if(setsockopt(nfd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr))) {
close(nfd);
syslog(LOG_ERR, _("Can't bind to interface %s: %s"), interface,
strerror(errno));
return -1;
}
}
#endif
if(bind(nfd, &sa->sa, SALEN(sa->sa))) {
close(nfd);
addrstr = sockaddr2hostname(sa);
syslog(LOG_ERR, _("Can't bind to %s/udp: %s"), addrstr,
strerror(errno));
free(addrstr);
return -1;
}
return nfd;
}
void retry_outgoing(outgoing_t *outgoing)
void retry_outgoing(outgoing_t * outgoing)
{
event_t *event;
cp();
outgoing->timeout += 5;
if(outgoing->timeout > maxtimeout)
outgoing->timeout = maxtimeout;
event_t *event;
event = new_event();
event->handler = (event_handler_t)setup_outgoing_connection;
event->time = now + outgoing->timeout;
event->data = outgoing;
event_add(event);
cp();
if(debug_lvl >= DEBUG_CONNECTIONS)
syslog(LOG_NOTICE, _("Trying to re-establish outgoing connection in %d seconds"), outgoing->timeout);
cp();
outgoing->timeout += 5;
if(outgoing->timeout > maxtimeout)
outgoing->timeout = maxtimeout;
event = new_event();
event->handler = (event_handler_t) setup_outgoing_connection;
event->time = now + outgoing->timeout;
event->data = outgoing;
event_add(event);
if(debug_lvl >= DEBUG_CONNECTIONS)
syslog(LOG_NOTICE,
_("Trying to re-establish outgoing connection in %d seconds"),
outgoing->timeout);
}
int setup_outgoing_socket(connection_t *c)
int setup_outgoing_socket(connection_t * c)
{
int option;
cp();
if(debug_lvl >= DEBUG_CONNECTIONS)
syslog(LOG_INFO, _("Trying to connect to %s (%s)"), c->name, c->hostname);
int option;
c->socket = socket(c->address.sa.sa_family, SOCK_STREAM, IPPROTO_TCP);
cp();
if(c->socket == -1)
{
syslog(LOG_ERR, _("Creating socket for %s failed: %s"), c->hostname, strerror(errno));
return -1;
}
if(debug_lvl >= DEBUG_CONNECTIONS)
syslog(LOG_INFO, _("Trying to connect to %s (%s)"), c->name,
c->hostname);
/* Optimize TCP settings */
c->socket = socket(c->address.sa.sa_family, SOCK_STREAM, IPPROTO_TCP);
if(c->socket == -1) {
syslog(LOG_ERR, _("Creating socket for %s failed: %s"), c->hostname,
strerror(errno));
return -1;
}
/* Optimize TCP settings */
#if defined(SOL_TCP) && defined(TCP_NODELAY)
option = 1;
setsockopt(c->socket, SOL_TCP, TCP_NODELAY, &option, sizeof(option));
option = 1;
setsockopt(c->socket, SOL_TCP, TCP_NODELAY, &option, sizeof(option));
#endif
#if defined(SOL_IP) && defined(IP_TOS)
option = IPTOS_LOWDELAY;
setsockopt(c->socket, SOL_IP, IP_TOS, &option, sizeof(option));
option = IPTOS_LOWDELAY;
setsockopt(c->socket, SOL_IP, IP_TOS, &option, sizeof(option));
#endif
/* Connect */
/* Connect */
if(connect(c->socket, &c->address.sa, SALEN(c->address.sa)) == -1)
{
close(c->socket);
syslog(LOG_ERR, _("Error while connecting to %s (%s): %s"), c->name, c->hostname, strerror(errno));
return -1;
}
if(connect(c->socket, &c->address.sa, SALEN(c->address.sa)) == -1) {
close(c->socket);
syslog(LOG_ERR, _("Error while connecting to %s (%s): %s"), c->name,
c->hostname, strerror(errno));
return -1;
}
if(debug_lvl >= DEBUG_CONNECTIONS)
syslog(LOG_INFO, _("Connected to %s (%s)"), c->name, c->hostname);
cp();
return 0;
if(debug_lvl >= DEBUG_CONNECTIONS)
syslog(LOG_INFO, _("Connected to %s (%s)"), c->name, c->hostname);
return 0;
}
void finish_connecting(connection_t *c)
void finish_connecting(connection_t * c)
{
cp();
if(debug_lvl >= DEBUG_CONNECTIONS)
syslog(LOG_INFO, _("Connected to %s (%s)"), c->name, c->hostname);
cp();
c->last_ping_time = now;
if(debug_lvl >= DEBUG_CONNECTIONS)
syslog(LOG_INFO, _("Connected to %s (%s)"), c->name, c->hostname);
send_id(c);
cp();
c->last_ping_time = now;
send_id(c);
}
void do_outgoing_connection(connection_t *c)
void do_outgoing_connection(connection_t * c)
{
char *address, *port;
int option, result, flags;
cp();
char *address, *port;
int option, result, flags;
cp();
begin:
if(!c->outgoing->ai)
{
if(!c->outgoing->cfg)
{
if(debug_lvl >= DEBUG_CONNECTIONS)
syslog(LOG_ERR, _("Could not set up a meta connection to %s"), c->name);
c->status.remove = 1;
retry_outgoing(c->outgoing);
return;
}
if(!c->outgoing->ai) {
if(!c->outgoing->cfg) {
if(debug_lvl >= DEBUG_CONNECTIONS)
syslog(LOG_ERR, _("Could not set up a meta connection to %s"),
c->name);
c->status.remove = 1;
retry_outgoing(c->outgoing);
return;
}
get_config_string(c->outgoing->cfg, &address);
get_config_string(c->outgoing->cfg, &address);
if(!get_config_string(lookup_config(c->config_tree, "Port"), &port))
asprintf(&port, "655");
if(!get_config_string(lookup_config(c->config_tree, "Port"), &port))
asprintf(&port, "655");
c->outgoing->ai = str2addrinfo(address, port, SOCK_STREAM);
free(address);
free(port);
c->outgoing->ai = str2addrinfo(address, port, SOCK_STREAM);
free(address);
free(port);
c->outgoing->aip = c->outgoing->ai;
c->outgoing->cfg = lookup_config_next(c->config_tree, c->outgoing->cfg);
}
c->outgoing->aip = c->outgoing->ai;
c->outgoing->cfg = lookup_config_next(c->config_tree, c->outgoing->cfg);
}
if(!c->outgoing->aip)
{
freeaddrinfo(c->outgoing->ai);
c->outgoing->ai = NULL;
goto begin;
}
if(!c->outgoing->aip) {
freeaddrinfo(c->outgoing->ai);
c->outgoing->ai = NULL;
goto begin;
}
memcpy(&c->address, c->outgoing->aip->ai_addr, c->outgoing->aip->ai_addrlen);
c->outgoing->aip = c->outgoing->aip->ai_next;
memcpy(&c->address, c->outgoing->aip->ai_addr,
c->outgoing->aip->ai_addrlen);
c->outgoing->aip = c->outgoing->aip->ai_next;
if(c->hostname)
free(c->hostname);
if(c->hostname)
free(c->hostname);
c->hostname = sockaddr2hostname(&c->address);
c->hostname = sockaddr2hostname(&c->address);
if(debug_lvl >= DEBUG_CONNECTIONS)
syslog(LOG_INFO, _("Trying to connect to %s (%s)"), c->name, c->hostname);
if(debug_lvl >= DEBUG_CONNECTIONS)
syslog(LOG_INFO, _("Trying to connect to %s (%s)"), c->name,
c->hostname);
c->socket = socket(c->address.sa.sa_family, SOCK_STREAM, IPPROTO_TCP);
c->socket = socket(c->address.sa.sa_family, SOCK_STREAM, IPPROTO_TCP);
if(c->socket == -1)
{
if(debug_lvl >= DEBUG_CONNECTIONS)
syslog(LOG_ERR, _("Creating socket for %s failed: %s"), c->hostname, strerror(errno));
if(c->socket == -1) {
if(debug_lvl >= DEBUG_CONNECTIONS)
syslog(LOG_ERR, _("Creating socket for %s failed: %s"), c->hostname,
strerror(errno));
goto begin;
}
goto begin;
}
/* Optimize TCP settings */
/* Optimize TCP settings */
#if defined(SOL_TCP) && defined(TCP_NODELAY)
option = 1;
setsockopt(c->socket, SOL_TCP, TCP_NODELAY, &option, sizeof(option));
option = 1;
setsockopt(c->socket, SOL_TCP, TCP_NODELAY, &option, sizeof(option));
#endif
#if defined(SOL_IP) && defined(IP_TOS)
option = IPTOS_LOWDELAY;
setsockopt(c->socket, SOL_IP, IP_TOS, &option, sizeof(option));
option = IPTOS_LOWDELAY;
setsockopt(c->socket, SOL_IP, IP_TOS, &option, sizeof(option));
#endif
/* Non-blocking */
/* Non-blocking */
flags = fcntl(c->socket, F_GETFL);
flags = fcntl(c->socket, F_GETFL);
if(fcntl(c->socket, F_SETFL, flags | O_NONBLOCK) < 0)
{
syslog(LOG_ERR, _("fcntl for %s: %s"), c->hostname, strerror(errno));
}
/* Connect */
result = connect(c->socket, &c->address.sa, SALEN(c->address.sa));
if(result == -1)
{
if(errno == EINPROGRESS)
{
c->status.connecting = 1;
return;
if(fcntl(c->socket, F_SETFL, flags | O_NONBLOCK) < 0) {
syslog(LOG_ERR, _("fcntl for %s: %s"), c->hostname, strerror(errno));
}
close(c->socket);
/* Connect */
if(debug_lvl >= DEBUG_CONNECTIONS)
syslog(LOG_ERR, _("%s: %s"), c->hostname, strerror(errno));
result = connect(c->socket, &c->address.sa, SALEN(c->address.sa));
goto begin;
}
if(result == -1) {
if(errno == EINPROGRESS) {
c->status.connecting = 1;
return;
}
finish_connecting(c);
return;
cp();
close(c->socket);
if(debug_lvl >= DEBUG_CONNECTIONS)
syslog(LOG_ERR, _("%s: %s"), c->hostname, strerror(errno));
goto begin;
}
finish_connecting(c);
return;
}
void setup_outgoing_connection(outgoing_t *outgoing)
void setup_outgoing_connection(outgoing_t * outgoing)
{
connection_t *c;
node_t *n;
cp();
n = lookup_node(outgoing->name);
if(n)
if(n->connection)
{
if(debug_lvl >= DEBUG_CONNECTIONS)
syslog(LOG_INFO, _("Already connected to %s"), outgoing->name);
n->connection->outgoing = outgoing;
return;
}
connection_t *c;
node_t *n;
c = new_connection();
c->name = xstrdup(outgoing->name);
c->outcipher = myself->connection->outcipher;
c->outdigest = myself->connection->outdigest;
c->outmaclength = myself->connection->outmaclength;
c->outcompression = myself->connection->outcompression;
cp();
init_configuration(&c->config_tree);
read_connection_config(c);
outgoing->cfg = lookup_config(c->config_tree, "Address");
if(!outgoing->cfg)
{
syslog(LOG_ERR, _("No address specified for %s"), c->name);
free_connection(c);
free(outgoing->name);
free(outgoing);
return;
}
c->outgoing = outgoing;
c->last_ping_time = now;
n = lookup_node(outgoing->name);
connection_add(c);
if(n)
if(n->connection) {
if(debug_lvl >= DEBUG_CONNECTIONS)
syslog(LOG_INFO, _("Already connected to %s"), outgoing->name);
do_outgoing_connection(c);
n->connection->outgoing = outgoing;
return;
}
c = new_connection();
c->name = xstrdup(outgoing->name);
c->outcipher = myself->connection->outcipher;
c->outdigest = myself->connection->outdigest;
c->outmaclength = myself->connection->outmaclength;
c->outcompression = myself->connection->outcompression;
init_configuration(&c->config_tree);
read_connection_config(c);
outgoing->cfg = lookup_config(c->config_tree, "Address");
if(!outgoing->cfg) {
syslog(LOG_ERR, _("No address specified for %s"), c->name);
free_connection(c);
free(outgoing->name);
free(outgoing);
return;
}
c->outgoing = outgoing;
c->last_ping_time = now;
connection_add(c);
do_outgoing_connection(c);
}
/*
@ -443,61 +455,66 @@ void setup_outgoing_connection(outgoing_t *outgoing)
*/
int handle_new_meta_connection(int sock)
{
connection_t *c;
sockaddr_t sa;
int fd, len = sizeof(sa);
cp();
fd = accept(sock, &sa.sa, &len);
connection_t *c;
sockaddr_t sa;
int fd, len = sizeof(sa);
if(fd < 0)
{
syslog(LOG_ERR, _("Accepting a new connection failed: %s"), strerror(errno));
return -1;
}
cp();
sockaddrunmap(&sa);
fd = accept(sock, &sa.sa, &len);
c = new_connection();
c->outcipher = myself->connection->outcipher;
c->outdigest = myself->connection->outdigest;
c->outmaclength = myself->connection->outmaclength;
c->outcompression = myself->connection->outcompression;
if(fd < 0) {
syslog(LOG_ERR, _("Accepting a new connection failed: %s"),
strerror(errno));
return -1;
}
c->address = sa;
c->hostname = sockaddr2hostname(&sa);
c->socket = fd;
c->last_ping_time = now;
sockaddrunmap(&sa);
if(debug_lvl >= DEBUG_CONNECTIONS)
syslog(LOG_NOTICE, _("Connection from %s"), c->hostname);
c = new_connection();
c->outcipher = myself->connection->outcipher;
c->outdigest = myself->connection->outdigest;
c->outmaclength = myself->connection->outmaclength;
c->outcompression = myself->connection->outcompression;
connection_add(c);
c->address = sa;
c->hostname = sockaddr2hostname(&sa);
c->socket = fd;
c->last_ping_time = now;
c->allow_request = ID;
send_id(c);
cp();
return 0;
if(debug_lvl >= DEBUG_CONNECTIONS)
syslog(LOG_NOTICE, _("Connection from %s"), c->hostname);
connection_add(c);
c->allow_request = ID;
send_id(c);
return 0;
}
void try_outgoing_connections(void)
{
static config_t *cfg = NULL;
char *name;
outgoing_t *outgoing;
cp();
for(cfg = lookup_config(config_tree, "ConnectTo"); cfg; cfg = lookup_config_next(config_tree, cfg))
{
get_config_string(cfg, &name);
static config_t *cfg = NULL;
char *name;
outgoing_t *outgoing;
if(check_id(name))
{
syslog(LOG_ERR, _("Invalid name for outgoing connection in %s line %d"), cfg->file, cfg->line);
free(name);
continue;
}
cp();
outgoing = xmalloc_and_zero(sizeof(*outgoing));
outgoing->name = name;
setup_outgoing_connection(outgoing);
}
for(cfg = lookup_config(config_tree, "ConnectTo"); cfg;
cfg = lookup_config_next(config_tree, cfg)) {
get_config_string(cfg, &name);
if(check_id(name)) {
syslog(LOG_ERR,
_("Invalid name for outgoing connection in %s line %d"),
cfg->file, cfg->line);
free(name);
continue;
}
outgoing = xmalloc_and_zero(sizeof(*outgoing));
outgoing->name = name;
setup_outgoing_connection(outgoing);
}
}

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: device.c,v 1.1.2.4 2002/06/21 10:11:36 guus Exp $
$Id: device.c,v 1.1.2.5 2002/09/09 21:25:23 guus Exp $
*/
#include "config.h"
@ -63,93 +63,80 @@ extern subnet_t mymac;
*/
int setup_device(void)
{
if(!get_config_string(lookup_config(config_tree, "Device"), &device))
device = DEFAULT_DEVICE;
if(!get_config_string(lookup_config(config_tree, "Device"), &device))
device = DEFAULT_DEVICE;
if(!get_config_string(lookup_config(config_tree, "Interface"), &interface))
interface = rindex(device, '/')?rindex(device, '/')+1:device;
cp
if((device_fd = open(device, O_RDWR | O_NONBLOCK)) < 0)
{
syslog(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno));
return -1;
}
cp
/* Set default MAC address for ethertap devices */
if(!get_config_string(lookup_config(config_tree, "Interface"), &interface))
interface = rindex(device, '/') ? rindex(device, '/') + 1 : device;
cp if((device_fd = open(device, O_RDWR | O_NONBLOCK)) < 0) {
syslog(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno));
return -1;
}
cp
/* 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;
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;
device_info = _("NetBSD tun device");
device_info = _("NetBSD tun device");
syslog(LOG_INFO, _("%s is a %s"), device, device_info);
cp
return 0;
syslog(LOG_INFO, _("%s is a %s"), device, device_info);
cp return 0;
}
void close_device(void)
{
cp
close(device_fd);
cp
}
cp close(device_fd);
cp}
int read_packet(vpn_packet_t *packet)
int read_packet(vpn_packet_t * packet)
{
int lenin;
cp
int lenin;
cp if((lenin = read(device_fd, packet->data + 14, MTU - 14)) <= 0) {
syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info,
device, strerror(errno));
return -1;
}
if((lenin = read(device_fd, packet->data + 14, MTU - 14)) <= 0)
{
syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, device, strerror(errno));
return -1;
}
memcpy(packet->data, mymac.net.mac.address.x, 6);
memcpy(packet->data + 6, mymac.net.mac.address.x, 6);
packet->data[12] = 0x08;
packet->data[13] = 0x00;
memcpy(packet->data, mymac.net.mac.address.x, 6);
memcpy(packet->data + 6, mymac.net.mac.address.x, 6);
packet->data[12] = 0x08;
packet->data[13] = 0x00;
packet->len = lenin + 14;
packet->len = lenin + 14;
device_total_in += packet->len;
device_total_in += packet->len;
if(debug_lvl >= DEBUG_TRAFFIC) {
syslog(LOG_DEBUG, _("Read packet of %d bytes from %s"), packet->len,
device_info);
}
if(debug_lvl >= DEBUG_TRAFFIC)
{
syslog(LOG_DEBUG, _("Read packet of %d bytes from %s"), packet->len, device_info);
}
return 0;
cp}
return 0;
cp
}
int write_packet(vpn_packet_t *packet)
int write_packet(vpn_packet_t * packet)
{
cp
if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_DEBUG, _("Writing packet of %d bytes to %s"),
packet->len, device_info);
cp if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_DEBUG, _("Writing packet of %d bytes to %s"),
packet->len, device_info);
if(write(device_fd, packet->data + 14, packet->len - 14) < 0)
{
syslog(LOG_ERR, _("Can't write to %s %s: %s"), device_info, device, strerror(errno));
return -1;
}
if(write(device_fd, packet->data + 14, packet->len - 14) < 0) {
syslog(LOG_ERR, _("Can't write to %s %s: %s"), device_info, device,
strerror(errno));
return -1;
}
device_total_out += packet->len;
cp
}
device_total_out += packet->len;
cp}
void dump_device_stats(void)
{
cp
syslog(LOG_DEBUG, _("Statistics for %s %s:"), device_info, device);
syslog(LOG_DEBUG, _(" total bytes in: %10d"), device_total_in);
syslog(LOG_DEBUG, _(" total bytes out: %10d"), device_total_out);
cp
}
cp syslog(LOG_DEBUG, _("Statistics for %s %s:"), device_info, device);
syslog(LOG_DEBUG, _(" total bytes in: %10d"), device_total_in);
syslog(LOG_DEBUG, _(" total bytes out: %10d"), device_total_out);
cp}

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: netutl.c,v 1.12.4.42 2002/09/09 19:39:59 guus Exp $
$Id: netutl.c,v 1.12.4.43 2002/09/09 21:24:41 guus Exp $
*/
#include "config.h"
@ -28,7 +28,7 @@
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#include <inttypes.h>
#endif
#include <string.h>
#include <signal.h>
@ -54,211 +54,232 @@ int hostnames = 0;
*/
struct addrinfo *str2addrinfo(char *address, char *service, int socktype)
{
struct addrinfo hint, *ai;
int err;
cp();
memset(&hint, 0, sizeof(hint));
struct addrinfo hint, *ai;
int err;
hint.ai_family = addressfamily;
hint.ai_socktype = socktype;
cp();
err = getaddrinfo(address, service, &hint, &ai);
memset(&hint, 0, sizeof(hint));
if(err)
{
if(debug_lvl >= DEBUG_ERROR)
syslog(LOG_WARNING, _("Error looking up %s port %s: %s\n"), address, service, gai_strerror(err));
cp_trace();
return NULL;
}
hint.ai_family = addressfamily;
hint.ai_socktype = socktype;
cp();
return ai;
err = getaddrinfo(address, service, &hint, &ai);
if(err) {
if(debug_lvl >= DEBUG_ERROR)
syslog(LOG_WARNING, _("Error looking up %s port %s: %s\n"), address,
service, gai_strerror(err));
cp_trace();
return NULL;
}
return ai;
}
sockaddr_t str2sockaddr(char *address, char *port)
{
struct addrinfo hint, *ai;
sockaddr_t result;
int err;
cp();
memset(&hint, 0, sizeof(hint));
struct addrinfo hint, *ai;
sockaddr_t result;
int err;
hint.ai_family = AF_UNSPEC;
hint.ai_flags = AI_NUMERICHOST;
hint.ai_socktype = SOCK_STREAM;
cp();
err = getaddrinfo(address, port, &hint, &ai);
memset(&hint, 0, sizeof(hint));
if(err || !ai)
{
syslog(LOG_ERR, _("Error looking up %s port %s: %s\n"), address, port, gai_strerror(err));
cp_trace();
raise(SIGFPE);
exit(0);
}
hint.ai_family = AF_UNSPEC;
hint.ai_flags = AI_NUMERICHOST;
hint.ai_socktype = SOCK_STREAM;
result = *(sockaddr_t *)ai->ai_addr;
freeaddrinfo(ai);
cp();
return result;
err = getaddrinfo(address, port, &hint, &ai);
if(err || !ai) {
syslog(LOG_ERR, _("Error looking up %s port %s: %s\n"), address, port,
gai_strerror(err));
cp_trace();
raise(SIGFPE);
exit(0);
}
result = *(sockaddr_t *) ai->ai_addr;
freeaddrinfo(ai);
return result;
}
void sockaddr2str(sockaddr_t *sa, char **addrstr, char **portstr)
void sockaddr2str(sockaddr_t * sa, char **addrstr, char **portstr)
{
char address[NI_MAXHOST];
char port[NI_MAXSERV];
char *scopeid;
int err;
cp();
err = getnameinfo(&sa->sa, SALEN(sa->sa), address, sizeof(address), port, sizeof(port), NI_NUMERICHOST|NI_NUMERICSERV);
char address[NI_MAXHOST];
char port[NI_MAXSERV];
char *scopeid;
int err;
if(err)
{
syslog(LOG_ERR, _("Error while translating addresses: %s"), gai_strerror(err));
cp_trace();
raise(SIGFPE);
exit(0);
}
cp();
scopeid = strchr(address, '%');
err = getnameinfo(&sa->sa, SALEN(sa->sa), address, sizeof(address), port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV);
if(scopeid)
*scopeid = '\0'; /* Descope. */
if(err) {
syslog(LOG_ERR, _("Error while translating addresses: %s"),
gai_strerror(err));
cp_trace();
raise(SIGFPE);
exit(0);
}
*addrstr = xstrdup(address);
*portstr = xstrdup(port);
cp();
scopeid = strchr(address, '%');
if(scopeid)
*scopeid = '\0'; /* Descope. */
*addrstr = xstrdup(address);
*portstr = xstrdup(port);
}
char *sockaddr2hostname(sockaddr_t *sa)
char *sockaddr2hostname(sockaddr_t * sa)
{
char *str;
char address[NI_MAXHOST] = "unknown";
char port[NI_MAXSERV] = "unknown";
int err;
cp();
err = getnameinfo(&sa->sa, SALEN(sa->sa), address, sizeof(address), port, sizeof(port), hostnames?0:(NI_NUMERICHOST|NI_NUMERICSERV));
if(err)
{
syslog(LOG_ERR, _("Error while looking up hostname: %s"), gai_strerror(err));
}
char *str;
char address[NI_MAXHOST] = "unknown";
char port[NI_MAXSERV] = "unknown";
int err;
asprintf(&str, _("%s port %s"), address, port);
cp();
return str;
cp();
err = getnameinfo(&sa->sa, SALEN(sa->sa), address, sizeof(address), port, sizeof(port),
hostnames ? 0 : (NI_NUMERICHOST | NI_NUMERICSERV));
if(err) {
syslog(LOG_ERR, _("Error while looking up hostname: %s"),
gai_strerror(err));
}
asprintf(&str, _("%s port %s"), address, port);
return str;
}
int sockaddrcmp(sockaddr_t *a, sockaddr_t *b)
int sockaddrcmp(sockaddr_t * a, sockaddr_t * b)
{
int result;
cp();
result = a->sa.sa_family - b->sa.sa_family;
if(result)
return result;
switch(a->sa.sa_family)
{
case AF_UNSPEC:
return 0;
case AF_INET:
result = memcmp(&a->in.sin_addr, &b->in.sin_addr, sizeof(a->in.sin_addr));
int result;
cp();
result = a->sa.sa_family - b->sa.sa_family;
if(result)
return result;
return memcmp(&a->in.sin_port, &b->in.sin_port, sizeof(a->in.sin_port));
case AF_INET6:
result = memcmp(&a->in6.sin6_addr, &b->in6.sin6_addr, sizeof(a->in6.sin6_addr));
if(result)
return result;
return memcmp(&a->in6.sin6_port, &b->in6.sin6_port, sizeof(a->in6.sin6_port));
default:
syslog(LOG_ERR, _("sockaddrcmp() was called with unknown address family %d, exitting!"), a->sa.sa_family);
cp_trace();
raise(SIGFPE);
exit(0);
}
cp();
return result;
switch (a->sa.sa_family) {
case AF_UNSPEC:
return 0;
case AF_INET:
result = memcmp(&a->in.sin_addr, &b->in.sin_addr, sizeof(a->in.sin_addr));
if(result)
return result;
return memcmp(&a->in.sin_port, &b->in.sin_port, sizeof(a->in.sin_port));
case AF_INET6:
result = memcmp(&a->in6.sin6_addr, &b->in6.sin6_addr, sizeof(a->in6.sin6_addr));
if(result)
return result;
return memcmp(&a->in6.sin6_port, &b->in6.sin6_port, sizeof(a->in6.sin6_port));
default:
syslog(LOG_ERR, _("sockaddrcmp() was called with unknown address family %d, exitting!"),
a->sa.sa_family);
cp_trace();
raise(SIGFPE);
exit(0);
}
}
void sockaddrunmap(sockaddr_t *sa)
void sockaddrunmap(sockaddr_t * sa)
{
if(sa->sa.sa_family == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&sa->in6.sin6_addr))
{
sa->in.sin_addr.s_addr = ((uint32_t *)&sa->in6.sin6_addr)[3];
sa->in.sin_family = AF_INET;
}
if(sa->sa.sa_family == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&sa->in6.sin6_addr)) {
sa->in.sin_addr.s_addr = ((uint32_t *) & sa->in6.sin6_addr)[3];
sa->in.sin_family = AF_INET;
}
}
/* Subnet mask handling */
int maskcmp(void *va, void *vb, int masklen, int len)
{
int i, m, result;
char *a = va;
char *b = vb;
cp();
for(m = masklen, i = 0; m >= 8; m -= 8, i++)
{
result = a[i] - b[i];
if(result)
return result;
}
if(m)
return (a[i] & (0x100 - (1 << (8 - m)))) - (b[i] & (0x100 - (1 << (8 - m))));
int i, m, result;
char *a = va;
char *b = vb;
return 0;
cp();
for(m = masklen, i = 0; m >= 8; m -= 8, i++) {
result = a[i] - b[i];
if(result)
return result;
}
if(m)
return (a[i] & (0x100 - (1 << (8 - m)))) -
(b[i] & (0x100 - (1 << (8 - m))));
return 0;
}
void mask(void *va, int masklen, int len)
{
int i;
char *a = va;
cp();
i = masklen / 8;
masklen %= 8;
if(masklen)
a[i++] &= (0x100 - (1 << masklen));
for(; i < len; i++)
a[i] = 0;
int i;
char *a = va;
cp();
i = masklen / 8;
masklen %= 8;
if(masklen)
a[i++] &= (0x100 - (1 << masklen));
for(; i < len; i++)
a[i] = 0;
}
void maskcpy(void *va, void *vb, int masklen, int len)
{
int i, m;
char *a = va;
char *b = vb;
cp();
for(m = masklen, i = 0; m >= 8; m -= 8, i++)
a[i] = b[i];
int i, m;
char *a = va;
char *b = vb;
if(m)
{
a[i] = b[i] & (0x100 - (1 << m));
i++;
}
cp();
for(; i < len; i++)
a[i] = 0;
for(m = masklen, i = 0; m >= 8; m -= 8, i++)
a[i] = b[i];
if(m) {
a[i] = b[i] & (0x100 - (1 << m));
i++;
}
for(; i < len; i++)
a[i] = 0;
}
int maskcheck(void *va, int masklen, int len)
{
int i;
char *a = va;
cp();
i = masklen / 8;
masklen %= 8;
int i;
char *a = va;
if(masklen && a[i++] & (0xff >> masklen))
return -1;
cp();
for(; i < len; i++)
if(a[i] != 0)
return -2;
i = masklen / 8;
masklen %= 8;
return 0;
if(masklen && a[i++] & (0xff >> masklen))
return -1;
for(; i < len; i++)
if(a[i] != 0)
return -2;
return 0;
}

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: netutl.h,v 1.2.4.13 2002/06/21 10:11:13 guus Exp $
$Id: netutl.h,v 1.2.4.14 2002/09/09 21:24:41 guus Exp $
*/
#ifndef __TINC_NETUTL_H__
@ -42,4 +42,4 @@ extern void maskcpy(void *, void *, int, int);
extern void mask(void *, int, int);
extern int maskcheck(void *, int, int);
#endif /* __TINC_NETUTL_H__ */
#endif /* __TINC_NETUTL_H__ */

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: node.c,v 1.1.2.16 2002/09/09 19:39:59 guus Exp $
$Id: node.c,v 1.1.2.17 2002/09/09 21:24:41 guus Exp $
*/
#include "config.h"
@ -34,140 +34,151 @@
#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 */
avl_tree_t *node_tree; /* Known nodes, sorted by name */
avl_tree_t *node_udp_tree; /* Known nodes, sorted by address and port */
node_t *myself;
int node_compare(node_t *a, node_t *b)
int node_compare(node_t * a, node_t * b)
{
return strcmp(a->name, b->name);
return strcmp(a->name, b->name);
}
int node_udp_compare(node_t *a, node_t *b)
int node_udp_compare(node_t * a, node_t * b)
{
int result;
cp();
result = sockaddrcmp(&a->address, &b->address);
int result;
if(result)
return result;
cp();
return (a->name && b->name)?strcmp(a->name, b->name):0;
result = sockaddrcmp(&a->address, &b->address);
if(result)
return result;
return (a->name && b->name) ? strcmp(a->name, b->name) : 0;
}
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();
node_tree = avl_alloc_tree((avl_compare_t) node_compare, NULL);
node_udp_tree = avl_alloc_tree((avl_compare_t) node_udp_compare, NULL);
}
void exit_nodes(void)
{
cp();
avl_delete_tree(node_tree);
avl_delete_tree(node_udp_tree);
cp();
cp();
avl_delete_tree(node_tree);
avl_delete_tree(node_udp_tree);
}
node_t *new_node(void)
{
node_t *n = (node_t *)xmalloc_and_zero(sizeof(*n));
cp();
n->subnet_tree = new_subnet_tree();
n->edge_tree = new_edge_tree();
n->queue = list_alloc((list_action_t)free);
cp();
return n;
node_t *n = (node_t *) xmalloc_and_zero(sizeof(*n));
cp();
n->subnet_tree = new_subnet_tree();
n->edge_tree = new_edge_tree();
n->queue = list_alloc((list_action_t) free);
return n;
}
void free_node(node_t *n)
void free_node(node_t * n)
{
cp();
if(n->queue)
list_delete_list(n->queue);
if(n->name)
free(n->name);
if(n->hostname)
free(n->hostname);
if(n->key)
free(n->key);
if(n->subnet_tree)
free_subnet_tree(n->subnet_tree);
if(n->edge_tree)
free_edge_tree(n->edge_tree);
free(n);
cp();
cp();
if(n->queue)
list_delete_list(n->queue);
if(n->name)
free(n->name);
if(n->hostname)
free(n->hostname);
if(n->key)
free(n->key);
if(n->subnet_tree)
free_subnet_tree(n->subnet_tree);
if(n->edge_tree)
free_edge_tree(n->edge_tree);
free(n);
}
void node_add(node_t *n)
void node_add(node_t * n)
{
cp();
avl_insert(node_tree, n);
avl_insert(node_udp_tree, n);
cp();
cp();
avl_insert(node_tree, n);
avl_insert(node_udp_tree, n);
}
void node_del(node_t *n)
void node_del(node_t * n)
{
avl_node_t *node, *next;
edge_t *e;
subnet_t *s;
cp();
for(node = n->subnet_tree->head; node; node = next)
{
next = node->next;
s = (subnet_t *)node->data;
subnet_del(n, s);
}
avl_node_t *node, *next;
edge_t *e;
subnet_t *s;
for(node = n->edge_tree->head; node; node = next)
{
next = node->next;
e = (edge_t *)node->data;
edge_del(e);
}
cp();
avl_delete(node_tree, n);
avl_delete(node_udp_tree, n);
cp();
cp();
for(node = n->subnet_tree->head; node; node = next) {
next = node->next;
s = (subnet_t *) node->data;
subnet_del(n, s);
}
for(node = n->edge_tree->head; node; node = next) {
next = node->next;
e = (edge_t *) node->data;
edge_del(e);
}
avl_delete(node_tree, n);
avl_delete(node_udp_tree, n);
}
node_t *lookup_node(char *name)
{
node_t n;
cp();
n.name = name;
return avl_search(node_tree, &n);
node_t n;
cp();
n.name = name;
return avl_search(node_tree, &n);
}
node_t *lookup_node_udp(sockaddr_t *sa)
node_t *lookup_node_udp(sockaddr_t * sa)
{
node_t n;
cp();
n.address = *sa;
n.name = NULL;
node_t n;
cp();
n.address = *sa;
n.name = NULL;
return avl_search(node_udp_tree, &n);
return avl_search(node_udp_tree, &n);
}
void dump_nodes(void)
{
avl_node_t *node;
node_t *n;
cp();
syslog(LOG_DEBUG, _("Nodes:"));
avl_node_t *node;
node_t *n;
for(node = node_tree->head; node; node = node->next)
{
n = (node_t *)node->data;
syslog(LOG_DEBUG, _(" %s at %s cipher %d digest %d maclength %d compression %d options %lx status %04x nexthop %s via %s"),
n->name, n->hostname, n->cipher?n->cipher->nid:0, n->digest?n->digest->type:0, n->maclength, n->compression, n->options,
n->status, n->nexthop?n->nexthop->name:"-", n->via?n->via->name:"-");
}
syslog(LOG_DEBUG, _("End of nodes."));
cp();
cp();
syslog(LOG_DEBUG, _("Nodes:"));
for(node = node_tree->head; node; node = node->next) {
n = (node_t *) node->data;
syslog(LOG_DEBUG, _(" %s at %s cipher %d digest %d maclength %d compression %d options %lx status %04x nexthop %s via %s"),
n->name, n->hostname, n->cipher ? n->cipher->nid : 0,
n->digest ? n->digest->type : 0, n->maclength, n->compression,
n->options, n->status, n->nexthop ? n->nexthop->name : "-",
n->via ? n->via->name : "-");
}
syslog(LOG_DEBUG, _("End of nodes."));
}

View file

@ -17,14 +17,14 @@
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.19 2002/09/04 13:48:52 guus Exp $
$Id: node.h,v 1.1.2.20 2002/09/09 21:24:41 guus Exp $
*/
#ifndef __TINC_NODE_H__
#define __TINC_NODE_H__
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#include <inttypes.h>
#endif
#include <avl_tree.h>
@ -33,46 +33,46 @@
#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 visited:1; /* 1 if this node has been visited by one of the graph algorithms */
int reachable:1; /* 1 if this node is reachable in the graph */
int indirect:1; /* 1 if this node is not directly reachable by us */
int unused:26;
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 visited:1; /* 1 if this node has been visited by one of the graph algorithms */
int reachable:1; /* 1 if this node is reachable in the graph */
int indirect:1; /* 1 if this node is not directly reachable by us */
int unused:26;
} node_status_t;
typedef struct node_t {
char *name; /* name of this node */
long int options; /* options turned on for this node */
char *name; /* name of this node */
long int options; /* options turned on for this node */
sockaddr_t address; /* his real (internet) ip to send UDP packets to */
char *hostname; /* the hostname of its real ip */
sockaddr_t address; /* his real (internet) ip to send UDP packets to */
char *hostname; /* the hostname of its real ip */
struct node_status_t status;
struct node_status_t status;
const EVP_CIPHER *cipher; /* Cipher type for UDP packets */
char *key; /* Cipher key and iv */
int keylength; /* Cipher key and iv length*/
const EVP_CIPHER *cipher; /* Cipher type for UDP packets */
char *key; /* Cipher key and iv */
int keylength; /* Cipher key and iv length */
const EVP_MD *digest; /* Digest type for MAC */
int maclength; /* Length of MAC */
const EVP_MD *digest; /* Digest type for MAC */
int maclength; /* Length of MAC */
int compression; /* Compressionlevel, 0 = no compression */
int compression; /* Compressionlevel, 0 = no compression */
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 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 node_t *nexthop; /* nearest node from us to him */
struct node_t *via; /* next hop for UDP packets */
avl_tree_t *edge_tree; /* Edges with this node as one of the endpoints */
avl_tree_t *subnet_tree; /* Pointer to a tree of subnets belonging to this node */
struct connection_t *connection; /* Connection associated with this node (if a direct connection exists) */
avl_tree_t *edge_tree; /* Edges with this node as one of the endpoints */
uint32_t sent_seqno; /* Sequence number last sent to this node */
uint32_t received_seqno; /* Sequence number last received from this node */
struct connection_t *connection; /* Connection associated with this node (if a direct connection exists) */
uint32_t sent_seqno; /* Sequence number last sent to this node */
uint32_t received_seqno; /* Sequence number last received from this node */
} node_t;
extern struct node_t *myself;
@ -89,4 +89,4 @@ extern node_t *lookup_node(char *);
extern node_t *lookup_node_udp(sockaddr_t *);
extern void dump_nodes(void);
#endif /* __TINC_NODE_H__ */
#endif /* __TINC_NODE_H__ */

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: device.c,v 1.1.2.9 2002/06/21 10:11:36 guus Exp $
$Id: device.c,v 1.1.2.10 2002/09/09 21:25:26 guus Exp $
*/
#include "config.h"
@ -63,133 +63,125 @@ extern subnet_t mymac;
*/
int setup_device(void)
{
if(!get_config_string(lookup_config(config_tree, "Device"), &device))
device = DEFAULT_DEVICE;
if(!get_config_string(lookup_config(config_tree, "Device"), &device))
device = DEFAULT_DEVICE;
if(!get_config_string(lookup_config(config_tree, "Interface"), &interface))
interface = rindex(device, '/')?rindex(device, '/')+1:device;
cp
if((device_fd = open(device, O_RDWR | O_NONBLOCK)) < 0)
{
syslog(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno));
return -1;
}
cp
/* Set default MAC address for ethertap devices */
if(!get_config_string(lookup_config(config_tree, "Interface"), &interface))
interface = rindex(device, '/') ? rindex(device, '/') + 1 : device;
cp if((device_fd = open(device, O_RDWR | O_NONBLOCK)) < 0) {
syslog(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno));
return -1;
}
cp
/* 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;
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;
device_info = _("OpenBSD tun device");
device_info = _("OpenBSD tun device");
syslog(LOG_INFO, _("%s is a %s"), device, device_info);
cp
return 0;
syslog(LOG_INFO, _("%s is a %s"), device, device_info);
cp return 0;
}
void close_device(void)
{
cp
close(device_fd);
cp
}
cp close(device_fd);
cp}
int read_packet(vpn_packet_t *packet)
int read_packet(vpn_packet_t * packet)
{
int lenin;
u_int32_t type;
struct iovec vector[2] = {{&type, sizeof(type)}, {packet->data + 14, MTU - 14}};
cp
int lenin;
u_int32_t type;
struct iovec vector[2] = { {&type, sizeof(type)}
, {packet->data + 14, MTU - 14}
};
cp if((lenin = readv(device_fd, vector, 2)) <= 0) {
syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info,
device, strerror(errno));
return -1;
}
if((lenin = readv(device_fd, vector, 2)) <= 0)
{
syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, device, strerror(errno));
return -1;
}
memcpy(packet->data, mymac.net.mac.address.x, 6);
memcpy(packet->data + 6, mymac.net.mac.address.x, 6);
memcpy(packet->data, mymac.net.mac.address.x, 6);
memcpy(packet->data + 6, mymac.net.mac.address.x, 6);
switch (ntohl(type)) {
case AF_INET:
packet->data[12] = 0x8;
packet->data[13] = 0x0;
break;
case AF_INET6:
packet->data[12] = 0x86;
packet->data[13] = 0xDD;
break;
default:
if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_ERR,
_
("Unknown address family %d while reading packet from %s %s"),
ntohl(type), device_info, device);
return -1;
}
switch(ntohl(type))
{
case AF_INET:
packet->data[12] = 0x8;
packet->data[13] = 0x0;
break;
case AF_INET6:
packet->data[12] = 0x86;
packet->data[13] = 0xDD;
break;
default:
if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_ERR, _("Unknown address family %d while reading packet from %s %s"), ntohl(type), device_info, device);
return -1;
}
packet->len = lenin + 10;
packet->len = lenin + 10;
device_total_in += packet->len;
device_total_in += packet->len;
if(debug_lvl >= DEBUG_TRAFFIC) {
syslog(LOG_DEBUG, _("Read packet of %d bytes from %s"), packet->len,
device_info);
}
if(debug_lvl >= DEBUG_TRAFFIC)
{
syslog(LOG_DEBUG, _("Read packet of %d bytes from %s"), packet->len, device_info);
}
return 0;
cp}
return 0;
cp
}
int write_packet(vpn_packet_t *packet)
int write_packet(vpn_packet_t * packet)
{
u_int32_t type;
struct iovec vector[2];
int af;
cp
if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_DEBUG, _("Writing packet of %d bytes to %s"),
packet->len, device_info);
u_int32_t type;
struct iovec vector[2];
int af;
cp if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_DEBUG, _("Writing packet of %d bytes to %s"),
packet->len, device_info);
af = (packet->data[12] << 8) + packet->data[13];
af = (packet->data[12] << 8) + packet->data[13];
switch(af)
{
case 0x800:
type = htonl(AF_INET);
break;
case 0x86DD:
type = htonl(AF_INET6);
break;
default:
if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_ERR, _("Unknown address family %d while writing packet to %s %s"), af, device_info, device);
return -1;
}
switch (af) {
case 0x800:
type = htonl(AF_INET);
break;
case 0x86DD:
type = htonl(AF_INET6);
break;
default:
if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_ERR,
_("Unknown address family %d while writing packet to %s %s"),
af, device_info, device);
return -1;
}
vector[0].iov_base = &type;
vector[0].iov_len = sizeof(type);
vector[1].iov_base = packet->data + 14;
vector[1].iov_len = packet->len - 14;
vector[0].iov_base = &type;
vector[0].iov_len = sizeof(type);
vector[1].iov_base = packet->data + 14;
vector[1].iov_len = packet->len - 14;
if(writev(device_fd, vector, 2) < 0)
{
syslog(LOG_ERR, _("Can't write to %s %s: %s"), device_info, device, strerror(errno));
return -1;
}
if(writev(device_fd, vector, 2) < 0) {
syslog(LOG_ERR, _("Can't write to %s %s: %s"), device_info, device,
strerror(errno));
return -1;
}
device_total_out += packet->len;
cp
}
device_total_out += packet->len;
cp}
void dump_device_stats(void)
{
cp
syslog(LOG_DEBUG, _("Statistics for %s %s:"), device_info, device);
syslog(LOG_DEBUG, _(" total bytes in: %10d"), device_total_in);
syslog(LOG_DEBUG, _(" total bytes out: %10d"), device_total_out);
cp
}
cp syslog(LOG_DEBUG, _("Statistics for %s %s:"), device_info, device);
syslog(LOG_DEBUG, _(" total bytes in: %10d"), device_total_in);
syslog(LOG_DEBUG, _(" total bytes out: %10d"), device_total_out);
cp}

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: process.c,v 1.1.2.45 2002/09/09 19:39:59 guus Exp $
$Id: process.c,v 1.1.2.46 2002/09/09 21:24:41 guus Exp $
*/
#include "config.h"
@ -66,9 +66,9 @@ extern int do_purge;
void memory_full(int size)
{
syslog(LOG_ERR, _("Memory exhausted (couldn't allocate %d bytes), exitting."), size);
cp_trace();
exit(1);
syslog(LOG_ERR, _("Memory exhausted (couldn't allocate %d bytes), exitting."), size);
cp_trace();
exit(1);
}
/* Some functions the less gifted operating systems might lack... */
@ -76,13 +76,13 @@ void memory_full(int size)
#ifndef HAVE_FCLOSEALL
int fcloseall(void)
{
fflush(stdin);
fflush(stdout);
fflush(stderr);
fclose(stdin);
fclose(stdout);
fclose(stderr);
return 0;
fflush(stdin);
fflush(stdout);
fflush(stderr);
fclose(stdin);
fclose(stdout);
fclose(stderr);
return 0;
}
#endif
@ -91,16 +91,17 @@ int fcloseall(void)
*/
void cleanup_and_exit(int c)
{
cp();
close_network_connections();
cp();
if(debug_lvl > DEBUG_NOTHING)
dump_device_stats();
close_network_connections();
syslog(LOG_NOTICE, _("Terminating"));
if(debug_lvl > DEBUG_NOTHING)
dump_device_stats();
closelog();
exit(c);
syslog(LOG_NOTICE, _("Terminating"));
closelog();
exit(c);
}
/*
@ -108,25 +109,26 @@ void cleanup_and_exit(int c)
*/
int write_pidfile(void)
{
int pid;
cp();
pid = check_pid(pidfilename);
int pid;
if(pid)
{
if(netname)
fprintf(stderr, _("A tincd is already running for net `%s' with pid %d.\n"),
netname, pid);
else
fprintf(stderr, _("A tincd is already running with pid %d.\n"), pid);
return 1;
}
cp();
/* if it's locked, write-protected, or whatever */
if(!write_pid(pidfilename))
return 1;
cp();
return 0;
pid = check_pid(pidfilename);
if(pid) {
if(netname)
fprintf(stderr, _("A tincd is already running for net `%s' with pid %d.\n"),
netname, pid);
else
fprintf(stderr, _("A tincd is already running with pid %d.\n"), pid);
return 1;
}
/* if it's locked, write-protected, or whatever */
if(!write_pid(pidfilename))
return 1;
return 0;
}
/*
@ -134,33 +136,36 @@ int write_pidfile(void)
*/
int kill_other(int signal)
{
int pid;
cp();
pid = read_pid(pidfilename);
int pid;
if(!pid)
{
if(netname)
fprintf(stderr, _("No other tincd is running for net `%s'.\n"), netname);
else
fprintf(stderr, _("No other tincd is running.\n"));
return 1;
}
cp();
errno = 0; /* No error, sometimes errno is only changed on error */
/* ESRCH is returned when no process with that pid is found */
if(kill(pid, signal) && errno == ESRCH)
{
if(netname)
fprintf(stderr, _("The tincd for net `%s' is no longer running. "), netname);
else
fprintf(stderr, _("The tincd is no longer running. "));
pid = read_pid(pidfilename);
fprintf(stderr, _("Removing stale lock file.\n"));
remove_pid(pidfilename);
}
cp();
return 0;
if(!pid) {
if(netname)
fprintf(stderr, _("No other tincd is running for net `%s'.\n"),
netname);
else
fprintf(stderr, _("No other tincd is running.\n"));
return 1;
}
errno = 0; /* No error, sometimes errno is only changed on error */
/* ESRCH is returned when no process with that pid is found */
if(kill(pid, signal) && errno == ESRCH) {
if(netname)
fprintf(stderr, _("The tincd for net `%s' is no longer running. "),
netname);
else
fprintf(stderr, _("The tincd is no longer running. "));
fprintf(stderr, _("Removing stale lock file.\n"));
remove_pid(pidfilename);
}
return 0;
}
/*
@ -168,69 +173,73 @@ int kill_other(int signal)
*/
int detach(void)
{
cp();
setup_signals();
cp();
/* First check if we can open a fresh new pidfile */
if(write_pidfile())
return -1;
setup_signals();
/* If we succeeded in doing that, detach */
/* First check if we can open a fresh new pidfile */
closelog();
if(write_pidfile())
return -1;
if(do_detach)
{
if(daemon(0, 0) < 0)
{
fprintf(stderr, _("Couldn't detach from terminal: %s"), strerror(errno));
return -1;
/* If we succeeded in doing that, detach */
closelog();
if(do_detach) {
if(daemon(0, 0) < 0) {
fprintf(stderr, _("Couldn't detach from terminal: %s"),
strerror(errno));
return -1;
}
/* Now UPDATE the pid in the pidfile, because we changed it... */
if(!write_pid(pidfilename))
return -1;
}
/* Now UPDATE the pid in the pidfile, because we changed it... */
if(!write_pid(pidfilename))
return -1;
}
openlog(identname, LOG_CONS | LOG_PID, LOG_DAEMON);
openlog(identname, LOG_CONS | LOG_PID, LOG_DAEMON);
if(debug_lvl > DEBUG_NOTHING)
syslog(LOG_NOTICE, _("tincd %s (%s %s) starting, debug level %d"),
VERSION, __DATE__, __TIME__, debug_lvl);
else
syslog(LOG_NOTICE, _("tincd %s starting"), VERSION);
if(debug_lvl > DEBUG_NOTHING)
syslog(LOG_NOTICE, _("tincd %s (%s %s) starting, debug level %d"),
VERSION, __DATE__, __TIME__, debug_lvl);
else
syslog(LOG_NOTICE, _("tincd %s starting"), VERSION);
xalloc_fail_func = memory_full;
cp();
return 0;
xalloc_fail_func = memory_full;
return 0;
}
/*
Execute the program name, with sane environment. All output will be
redirected to syslog.
*/
void _execute_script(const char *scriptname, char **envp) __attribute__ ((noreturn));
void _execute_script(const char *scriptname, char **envp)
__attribute__ ((noreturn));
void _execute_script(const char *scriptname, char **envp)
{
char *s;
cp();
while(*envp)
putenv(*envp++);
chdir("/");
/* Close all file descriptors */
closelog(); /* <- this means we cannot use syslog() here anymore! */
fcloseall();
char *s;
execl(scriptname, NULL);
/* No return on success */
cp();
openlog("tinc", LOG_CONS | LOG_PID, LOG_DAEMON);
syslog(LOG_ERR, _("Could not execute `%s': %s"), scriptname, strerror(errno));
exit(errno);
while(*envp)
putenv(*envp++);
chdir("/");
/* Close all file descriptors */
closelog(); /* <- this means we cannot use syslog() here anymore! */
fcloseall();
execl(scriptname, NULL);
/* No return on success */
openlog("tinc", LOG_CONS | LOG_PID, LOG_DAEMON);
syslog(LOG_ERR, _("Could not execute `%s': %s"), scriptname,
strerror(errno));
exit(errno);
}
/*
@ -238,67 +247,62 @@ void _execute_script(const char *scriptname, char **envp)
*/
int execute_script(const char *name, char **envp)
{
pid_t pid;
int status;
struct stat s;
char *scriptname;
cp();
asprintf(&scriptname, "%s/%s", confbase, name);
pid_t pid;
int status;
struct stat s;
char *scriptname;
/* First check if there is a script */
cp();
if(stat(scriptname, &s))
return 0;
asprintf(&scriptname, "%s/%s", confbase, name);
pid = fork();
if(pid < 0)
{
syslog(LOG_ERR, _("System call `%s' failed: %s"), "fork", strerror(errno));
return -1;
}
/* First check if there is a script */
if(pid)
{
if(debug_lvl >= DEBUG_STATUS)
syslog(LOG_INFO, _("Executing script %s"), name);
if(stat(scriptname, &s))
return 0;
free(scriptname);
pid = fork();
if(waitpid(pid, &status, 0) == pid)
{
if(WIFEXITED(status)) /* Child exited by itself */
{
if(WEXITSTATUS(status))
{
syslog(LOG_ERR, _("Process %d (%s) exited with non-zero status %d"), pid, name, WEXITSTATUS(status));
return -1;
}
else
return 0;
}
else if(WIFSIGNALED(status)) /* Child was killed by a signal */
{
syslog(LOG_ERR, _("Process %d (%s) was killed by signal %d (%s)"),
pid, name, WTERMSIG(status), strsignal(WTERMSIG(status)));
return -1;
}
else /* Something strange happened */
{
syslog(LOG_ERR, _("Process %d (%s) terminated abnormally"), pid, name);
return -1;
}
}
else
{
syslog(LOG_ERR, _("System call `%s' failed: %s"), "waitpid", strerror(errno));
return -1;
}
}
cp();
/* Child here */
if(pid < 0) {
syslog(LOG_ERR, _("System call `%s' failed: %s"), "fork",
strerror(errno));
return -1;
}
_execute_script(scriptname, envp);
if(pid) {
if(debug_lvl >= DEBUG_STATUS)
syslog(LOG_INFO, _("Executing script %s"), name);
free(scriptname);
if(waitpid(pid, &status, 0) == pid) {
if(WIFEXITED(status)) { /* Child exited by itself */
if(WEXITSTATUS(status)) {
syslog(LOG_ERR, _("Process %d (%s) exited with non-zero status %d"),
pid, name, WEXITSTATUS(status));
return -1;
} else
return 0;
} else if(WIFSIGNALED(status)) { /* Child was killed by a signal */
syslog(LOG_ERR, _("Process %d (%s) was killed by signal %d (%s)"), pid,
name, WTERMSIG(status), strsignal(WTERMSIG(status)));
return -1;
} else { /* Something strange happened */
syslog(LOG_ERR, _("Process %d (%s) terminated abnormally"), pid,
name);
return -1;
}
} else {
syslog(LOG_ERR, _("System call `%s' failed: %s"), "waitpid",
strerror(errno));
return -1;
}
}
/* Child here */
_execute_script(scriptname, envp);
}
@ -306,186 +310,171 @@ int execute_script(const char *name, char **envp)
Signal handlers.
*/
RETSIGTYPE
sigterm_handler(int a)
RETSIGTYPE sigterm_handler(int a)
{
if(debug_lvl > DEBUG_NOTHING)
syslog(LOG_NOTICE, _("Got TERM signal"));
if(debug_lvl > DEBUG_NOTHING)
syslog(LOG_NOTICE, _("Got TERM signal"));
cleanup_and_exit(0);
cleanup_and_exit(0);
}
RETSIGTYPE
sigquit_handler(int a)
RETSIGTYPE sigquit_handler(int a)
{
if(debug_lvl > DEBUG_NOTHING)
syslog(LOG_NOTICE, _("Got QUIT signal"));
cleanup_and_exit(0);
if(debug_lvl > DEBUG_NOTHING)
syslog(LOG_NOTICE, _("Got QUIT signal"));
cleanup_and_exit(0);
}
RETSIGTYPE
fatal_signal_square(int a)
RETSIGTYPE fatal_signal_square(int a)
{
syslog(LOG_ERR, _("Got another fatal signal %d (%s): not restarting."), a, strsignal(a));
cp_trace();
exit(1);
syslog(LOG_ERR, _("Got another fatal signal %d (%s): not restarting."), a,
strsignal(a));
cp_trace();
exit(1);
}
RETSIGTYPE
fatal_signal_handler(int a)
RETSIGTYPE fatal_signal_handler(int a)
{
struct sigaction act;
syslog(LOG_ERR, _("Got fatal signal %d (%s)"), a, strsignal(a));
cp_trace();
struct sigaction act;
syslog(LOG_ERR, _("Got fatal signal %d (%s)"), a, strsignal(a));
cp_trace();
if(do_detach)
{
syslog(LOG_NOTICE, _("Trying to re-execute in 5 seconds..."));
if(do_detach) {
syslog(LOG_NOTICE, _("Trying to re-execute in 5 seconds..."));
act.sa_handler = fatal_signal_square;
act.sa_mask = emptysigset;
act.sa_flags = 0;
sigaction(SIGSEGV, &act, NULL);
act.sa_handler = fatal_signal_square;
act.sa_mask = emptysigset;
act.sa_flags = 0;
sigaction(SIGSEGV, &act, NULL);
close_network_connections();
sleep(5);
remove_pid(pidfilename);
execvp(g_argv[0], g_argv);
}
else
{
syslog(LOG_NOTICE, _("Not restarting."));
exit(1);
}
close_network_connections();
sleep(5);
remove_pid(pidfilename);
execvp(g_argv[0], g_argv);
} else {
syslog(LOG_NOTICE, _("Not restarting."));
exit(1);
}
}
RETSIGTYPE
sighup_handler(int a)
RETSIGTYPE sighup_handler(int a)
{
if(debug_lvl > DEBUG_NOTHING)
syslog(LOG_NOTICE, _("Got HUP signal"));
sighup = 1;
if(debug_lvl > DEBUG_NOTHING)
syslog(LOG_NOTICE, _("Got HUP signal"));
sighup = 1;
}
RETSIGTYPE
sigint_handler(int a)
RETSIGTYPE sigint_handler(int a)
{
if(saved_debug_lvl)
{
syslog(LOG_NOTICE, _("Reverting to old debug level (%d)"),
saved_debug_lvl);
debug_lvl = saved_debug_lvl;
saved_debug_lvl = 0;
}
else
{
syslog(LOG_NOTICE, _("Temporarily setting debug level to 5. Kill me with SIGINT again to go back to level %d."),
debug_lvl);
saved_debug_lvl = debug_lvl;
debug_lvl = 5;
}
if(saved_debug_lvl) {
syslog(LOG_NOTICE, _("Reverting to old debug level (%d)"),
saved_debug_lvl);
debug_lvl = saved_debug_lvl;
saved_debug_lvl = 0;
} else {
syslog(LOG_NOTICE,
_
("Temporarily setting debug level to 5. Kill me with SIGINT again to go back to level %d."),
debug_lvl);
saved_debug_lvl = debug_lvl;
debug_lvl = 5;
}
}
RETSIGTYPE
sigalrm_handler(int a)
RETSIGTYPE sigalrm_handler(int a)
{
if(debug_lvl > DEBUG_NOTHING)
syslog(LOG_NOTICE, _("Got ALRM signal"));
sigalrm = 1;
if(debug_lvl > DEBUG_NOTHING)
syslog(LOG_NOTICE, _("Got ALRM signal"));
sigalrm = 1;
}
RETSIGTYPE
sigusr1_handler(int a)
RETSIGTYPE sigusr1_handler(int a)
{
dump_connections();
dump_connections();
}
RETSIGTYPE
sigusr2_handler(int a)
RETSIGTYPE sigusr2_handler(int a)
{
dump_device_stats();
dump_nodes();
dump_edges();
dump_subnets();
dump_device_stats();
dump_nodes();
dump_edges();
dump_subnets();
}
RETSIGTYPE
sigwinch_handler(int a)
RETSIGTYPE sigwinch_handler(int a)
{
extern int do_purge;
do_purge = 1;
extern int do_purge;
do_purge = 1;
}
RETSIGTYPE
unexpected_signal_handler(int a)
RETSIGTYPE unexpected_signal_handler(int a)
{
syslog(LOG_WARNING, _("Got unexpected signal %d (%s)"), a, strsignal(a));
cp_trace();
syslog(LOG_WARNING, _("Got unexpected signal %d (%s)"), a, strsignal(a));
cp_trace();
}
RETSIGTYPE
ignore_signal_handler(int a)
RETSIGTYPE ignore_signal_handler(int a)
{
if(debug_lvl >= DEBUG_SCARY_THINGS)
{
syslog(LOG_DEBUG, _("Ignored signal %d (%s)"), a, strsignal(a));
cp_trace();
}
if(debug_lvl >= DEBUG_SCARY_THINGS) {
syslog(LOG_DEBUG, _("Ignored signal %d (%s)"), a, strsignal(a));
cp_trace();
}
}
struct {
int signal;
void (*handler)(int);
int signal;
void (*handler) (int);
} sighandlers[] = {
{ SIGHUP, sighup_handler },
{ SIGTERM, sigterm_handler },
{ SIGQUIT, sigquit_handler },
{ SIGSEGV, fatal_signal_handler },
{ SIGBUS, fatal_signal_handler },
{ SIGILL, fatal_signal_handler },
{ SIGPIPE, ignore_signal_handler },
{ SIGINT, sigint_handler },
{ SIGUSR1, sigusr1_handler },
{ SIGUSR2, sigusr2_handler },
{ SIGCHLD, ignore_signal_handler },
{ SIGALRM, sigalrm_handler },
{ SIGWINCH, sigwinch_handler },
{ 0, NULL }
{
SIGHUP, sighup_handler}, {
SIGTERM, sigterm_handler}, {
SIGQUIT, sigquit_handler}, {
SIGSEGV, fatal_signal_handler}, {
SIGBUS, fatal_signal_handler}, {
SIGILL, fatal_signal_handler}, {
SIGPIPE, ignore_signal_handler}, {
SIGINT, sigint_handler}, {
SIGUSR1, sigusr1_handler}, {
SIGUSR2, sigusr2_handler}, {
SIGCHLD, ignore_signal_handler}, {
SIGALRM, sigalrm_handler}, {
SIGWINCH, sigwinch_handler}, {
0, NULL}
};
void
setup_signals(void)
void setup_signals(void)
{
int i;
struct sigaction act;
int i;
struct sigaction act;
sigemptyset(&emptysigset);
act.sa_handler = NULL;
act.sa_mask = emptysigset;
act.sa_flags = 0;
sigemptyset(&emptysigset);
act.sa_handler = NULL;
act.sa_mask = emptysigset;
act.sa_flags = 0;
/* Set a default signal handler for every signal, errors will be
ignored. */
for(i = 0; i < NSIG; i++)
{
if(!do_detach)
act.sa_handler = SIG_DFL;
else
act.sa_handler = unexpected_signal_handler;
sigaction(i, &act, NULL);
}
/* Set a default signal handler for every signal, errors will be
ignored. */
for(i = 0; i < NSIG; i++) {
if(!do_detach)
act.sa_handler = SIG_DFL;
else
act.sa_handler = unexpected_signal_handler;
sigaction(i, &act, NULL);
}
/* If we didn't detach, allow coredumps */
if(!do_detach)
sighandlers[3].handler = SIG_DFL;
/* If we didn't detach, allow coredumps */
if(!do_detach)
sighandlers[3].handler = SIG_DFL;
/* Then, for each known signal that we want to catch, assign a
handler to the signal, with error checking this time. */
for(i = 0; sighandlers[i].signal; i++)
{
act.sa_handler = sighandlers[i].handler;
if(sigaction(sighandlers[i].signal, &act, NULL) < 0)
fprintf(stderr, _("Installing signal handler for signal %d (%s) failed: %s\n"),
sighandlers[i].signal, strsignal(sighandlers[i].signal), strerror(errno));
}
/* Then, for each known signal that we want to catch, assign a
handler to the signal, with error checking this time. */
for(i = 0; sighandlers[i].signal; i++) {
act.sa_handler = sighandlers[i].handler;
if(sigaction(sighandlers[i].signal, &act, NULL) < 0)
fprintf(stderr,
_
("Installing signal handler for signal %d (%s) failed: %s\n"),
sighandlers[i].signal, strsignal(sighandlers[i].signal),
strerror(errno));
}
}

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: process.h,v 1.1.2.12 2002/07/10 11:27:06 guus Exp $
$Id: process.h,v 1.1.2.13 2002/09/09 21:24:41 guus Exp $
*/
#ifndef __TINC_PROCESS_H__
@ -33,4 +33,4 @@ extern int detach(void);
extern int kill_other(int);
extern void cleanup_and_exit(int);
#endif /* __TINC_PROCESS_H__ */
#endif /* __TINC_PROCESS_H__ */

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: protocol.c,v 1.28.4.135 2002/09/09 19:39:59 guus Exp $
$Id: protocol.c,v 1.28.4.136 2002/09/09 21:24:41 guus Exp $
*/
#include "config.h"
@ -45,221 +45,221 @@ avl_tree_t *past_request_tree;
int check_id(char *id)
{
int i;
int i;
for (i = 0; i < strlen(id); i++)
if(!isalnum(id[i]) && id[i] != '_')
return -1;
return 0;
for(i = 0; i < strlen(id); i++)
if(!isalnum(id[i]) && id[i] != '_')
return -1;
return 0;
}
/* Generic request routines - takes care of logging and error
detection as well */
int send_request(connection_t *c, const char *format, ...)
int send_request(connection_t * c, const char *format, ...)
{
va_list args;
char buffer[MAXBUFSIZE];
int len, request;
va_list args;
char buffer[MAXBUFSIZE];
int len, request;
cp();
/* Use vsnprintf instead of vasprintf: faster, no memory
fragmentation, cleanup is automatic, and there is a limit on the
input buffer anyway */
cp();
va_start(args, format);
len = vsnprintf(buffer, MAXBUFSIZE, format, args);
va_end(args);
/* Use vsnprintf instead of vasprintf: faster, no memory
fragmentation, cleanup is automatic, and there is a limit on the
input buffer anyway */
if(len < 0 || len > MAXBUFSIZE-1)
{
syslog(LOG_ERR, _("Output buffer overflow while sending request to %s (%s)"), c->name, c->hostname);
return -1;
}
va_start(args, format);
len = vsnprintf(buffer, MAXBUFSIZE, format, args);
va_end(args);
if(debug_lvl >= DEBUG_PROTOCOL)
{
sscanf(buffer, "%d", &request);
if(debug_lvl >= DEBUG_META)
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], c->name, c->hostname);
}
buffer[len++] = '\n';
cp();
if(c == broadcast)
return broadcast_meta(NULL, buffer, len);
else
return send_meta(c, buffer, len);
}
int forward_request(connection_t *from)
{
int request;
cp();
if(debug_lvl >= DEBUG_PROTOCOL)
{
sscanf(from->buffer, "%d", &request);
if(debug_lvl >= DEBUG_META)
syslog(LOG_DEBUG, _("Forwarding %s from %s (%s): %s"), request_name[request], from->name, from->hostname, from->buffer);
else
syslog(LOG_DEBUG, _("Forwarding %s from %s (%s)"), request_name[request], from->name, from->hostname);
}
from->buffer[from->reqlen - 1] = '\n';
cp();
return broadcast_meta(from, from->buffer, from->reqlen);
}
int receive_request(connection_t *c)
{
int request;
cp();
if(sscanf(c->buffer, "%d", &request) == 1)
{
if((request < 0) || (request >= LAST) || !request_handlers[request])
{
if(debug_lvl >= DEBUG_META)
syslog(LOG_DEBUG, _("Unknown request from %s (%s): %s"),
c->name, c->hostname, c->buffer);
else
syslog(LOG_ERR, _("Unknown request from %s (%s)"),
c->name, c->hostname);
return -1;
}
else
{
if(debug_lvl >= DEBUG_PROTOCOL)
{
if(debug_lvl >= DEBUG_META)
syslog(LOG_DEBUG, _("Got %s from %s (%s): %s"),
request_name[request], c->name, c->hostname, c->buffer);
else
syslog(LOG_DEBUG, _("Got %s from %s (%s)"),
request_name[request], c->name, c->hostname);
}
if(len < 0 || len > MAXBUFSIZE - 1) {
syslog(LOG_ERR, _("Output buffer overflow while sending request to %s (%s)"),
c->name, c->hostname);
return -1;
}
if((c->allow_request != ALL) && (c->allow_request != request))
{
syslog(LOG_ERR, _("Unauthorized request from %s (%s)"), c->name, c->hostname);
return -1;
}
if(debug_lvl >= DEBUG_PROTOCOL) {
sscanf(buffer, "%d", &request);
if(debug_lvl >= DEBUG_META)
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],
c->name, c->hostname);
}
if(request_handlers[request](c))
/* Something went wrong. Probably scriptkiddies. Terminate. */
{
syslog(LOG_ERR, _("Error while processing %s from %s (%s)"),
request_name[request], c->name, c->hostname);
return -1;
}
}
else
{
syslog(LOG_ERR, _("Bogus data received from %s (%s)"),
c->name, c->hostname);
return -1;
}
cp();
return 0;
buffer[len++] = '\n';
if(c == broadcast)
return broadcast_meta(NULL, buffer, len);
else
return send_meta(c, buffer, len);
}
int past_request_compare(past_request_t *a, past_request_t *b)
int forward_request(connection_t * from)
{
cp();
return strcmp(a->request, b->request);
int request;
cp();
cp();
if(debug_lvl >= DEBUG_PROTOCOL) {
sscanf(from->buffer, "%d", &request);
if(debug_lvl >= DEBUG_META)
syslog(LOG_DEBUG, _("Forwarding %s from %s (%s): %s"),
request_name[request], from->name, from->hostname,
from->buffer);
else
syslog(LOG_DEBUG, _("Forwarding %s from %s (%s)"),
request_name[request], from->name, from->hostname);
}
from->buffer[from->reqlen - 1] = '\n';
return broadcast_meta(from, from->buffer, from->reqlen);
}
void free_past_request(past_request_t *r)
int receive_request(connection_t * c)
{
cp();
if(r->request)
free(r->request);
free(r);
cp();
int request;
cp();
if(sscanf(c->buffer, "%d", &request) == 1) {
if((request < 0) || (request >= LAST) || !request_handlers[request]) {
if(debug_lvl >= DEBUG_META)
syslog(LOG_DEBUG, _("Unknown request from %s (%s): %s"),
c->name, c->hostname, c->buffer);
else
syslog(LOG_ERR, _("Unknown request from %s (%s)"),
c->name, c->hostname);
return -1;
} else {
if(debug_lvl >= DEBUG_PROTOCOL) {
if(debug_lvl >= DEBUG_META)
syslog(LOG_DEBUG, _("Got %s from %s (%s): %s"),
request_name[request], c->name, c->hostname,
c->buffer);
else
syslog(LOG_DEBUG, _("Got %s from %s (%s)"),
request_name[request], c->name, c->hostname);
}
}
if((c->allow_request != ALL) && (c->allow_request != request)) {
syslog(LOG_ERR, _("Unauthorized request from %s (%s)"), c->name,
c->hostname);
return -1;
}
if(request_handlers[request] (c))
/* Something went wrong. Probably scriptkiddies. Terminate. */
{
syslog(LOG_ERR, _("Error while processing %s from %s (%s)"),
request_name[request], c->name, c->hostname);
return -1;
}
} else {
syslog(LOG_ERR, _("Bogus data received from %s (%s)"),
c->name, c->hostname);
return -1;
}
return 0;
}
int past_request_compare(past_request_t * a, past_request_t * b)
{
return strcmp(a->request, b->request);
}
void free_past_request(past_request_t * r)
{
cp();
if(r->request)
free(r->request);
free(r);
}
void init_requests(void)
{
cp();
past_request_tree = avl_alloc_tree((avl_compare_t)past_request_compare, (avl_action_t)free_past_request);
cp();
cp();
past_request_tree = avl_alloc_tree((avl_compare_t) past_request_compare, (avl_action_t) free_past_request);
}
void exit_requests(void)
{
cp();
avl_delete_tree(past_request_tree);
cp();
cp();
avl_delete_tree(past_request_tree);
}
int seen_request(char *request)
{
past_request_t p, *new;
cp();
p.request = request;
past_request_t p, *new;
if(avl_search(past_request_tree, &p))
{
if(debug_lvl >= DEBUG_SCARY_THINGS)
syslog(LOG_DEBUG, _("Already seen request"));
return 1;
}
else
{
new = (past_request_t *)xmalloc(sizeof(*new));
new->request = xstrdup(request);
new->firstseen = now;
avl_insert(past_request_tree, new);
return 0;
}
cp();
cp();
p.request = request;
if(avl_search(past_request_tree, &p)) {
if(debug_lvl >= DEBUG_SCARY_THINGS)
syslog(LOG_DEBUG, _("Already seen request"));
return 1;
} else {
new = (past_request_t *) xmalloc(sizeof(*new));
new->request = xstrdup(request);
new->firstseen = now;
avl_insert(past_request_tree, new);
return 0;
}
}
void age_past_requests(void)
{
avl_node_t *node, *next;
past_request_t *p;
int left = 0, deleted = 0;
cp();
for(node = past_request_tree->head; node; node = next)
{
next = node->next;
p = (past_request_t *)node->data;
if(p->firstseen + pingtimeout < now)
avl_delete_node(past_request_tree, node), deleted++;
else
left++;
}
avl_node_t *node, *next;
past_request_t *p;
int left = 0, deleted = 0;
if(debug_lvl >= DEBUG_SCARY_THINGS && left + deleted)
syslog(LOG_DEBUG, _("Aging past requests: deleted %d, left %d\n"), deleted, left);
cp();
cp();
for(node = past_request_tree->head; node; node = next) {
next = node->next;
p = (past_request_t *) node->data;
if(p->firstseen + pingtimeout < now)
avl_delete_node(past_request_tree, node), deleted++;
else
left++;
}
if(debug_lvl >= DEBUG_SCARY_THINGS && left + deleted)
syslog(LOG_DEBUG, _("Aging past requests: deleted %d, left %d\n"),
deleted, left);
}
/* Jumptable for the request handlers */
int (*request_handlers[])(connection_t*) = {
id_h, metakey_h, challenge_h, chal_reply_h, ack_h,
status_h, error_h, termreq_h,
ping_h, pong_h,
add_subnet_h, del_subnet_h,
add_edge_h, del_edge_h,
key_changed_h, req_key_h, ans_key_h,
tcppacket_h,
int (*request_handlers[]) (connection_t *) = {
id_h, metakey_h, challenge_h, chal_reply_h, ack_h,
status_h, error_h, termreq_h,
ping_h, pong_h,
add_subnet_h, del_subnet_h,
add_edge_h, del_edge_h,
key_changed_h, req_key_h, ans_key_h, tcppacket_h,
};
/* Request names */
char (*request_name[]) = {
"ID", "METAKEY", "CHALLENGE", "CHAL_REPLY", "ACK",
"STATUS", "ERROR", "TERMREQ",
"PING", "PONG",
"ADD_SUBNET", "DEL_SUBNET",
"ADD_EDGE", "DEL_EDGE",
"KEY_CHANGED", "REQ_KEY", "ANS_KEY",
"PACKET",
"ID", "METAKEY", "CHALLENGE", "CHAL_REPLY", "ACK",
"STATUS", "ERROR", "TERMREQ",
"PING", "PONG",
"ADD_SUBNET", "DEL_SUBNET",
"ADD_EDGE", "DEL_EDGE", "KEY_CHANGED", "REQ_KEY", "ANS_KEY", "PACKET",
};

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: protocol.h,v 1.5.4.34 2002/09/04 16:26:45 guus Exp $
$Id: protocol.h,v 1.5.4.35 2002/09/09 21:24:42 guus Exp $
*/
#ifndef __TINC_PROTOCOL_H__
@ -37,21 +37,20 @@
/* Request numbers */
enum {
ALL = -1, /* Guardian for allow_request */
ID = 0, METAKEY, CHALLENGE, CHAL_REPLY, ACK,
STATUS, ERROR, TERMREQ,
PING, PONG,
// ADD_NODE, DEL_NODE,
ADD_SUBNET, DEL_SUBNET,
ADD_EDGE, DEL_EDGE,
KEY_CHANGED, REQ_KEY, ANS_KEY,
PACKET,
LAST /* Guardian for the highest request number */
ALL = -1, /* Guardian for allow_request */
ID = 0, METAKEY, CHALLENGE, CHAL_REPLY, ACK,
STATUS, ERROR, TERMREQ,
PING, PONG,
ADD_SUBNET, DEL_SUBNET,
ADD_EDGE, DEL_EDGE,
KEY_CHANGED, REQ_KEY, ANS_KEY,
PACKET,
LAST /* Guardian for the highest request number */
};
typedef struct past_request_t {
char *request;
time_t firstseen;
char *request;
time_t firstseen;
} past_request_t;
/* Maximum size of strings in a request */
@ -61,7 +60,7 @@ typedef struct past_request_t {
/* Basic functions */
extern int send_request(connection_t*, const char*, ...);
extern int send_request(connection_t *, const char *, ...);
extern int forward_request(connection_t *);
extern int receive_request(connection_t *);
extern int check_id(char *);
@ -83,8 +82,6 @@ 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_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_add_edge(connection_t *, edge_t *);
@ -96,7 +93,7 @@ extern int send_tcppacket(connection_t *, vpn_packet_t *);
/* Request handlers */
extern int (*request_handlers[])(connection_t *);
extern int (*request_handlers[]) (connection_t *);
extern int id_h(connection_t *);
extern int metakey_h(connection_t *);
@ -108,8 +105,6 @@ extern int error_h(connection_t *);
extern int termreq_h(connection_t *);
extern int ping_h(connection_t *);
extern int pong_h(connection_t *);
// extern int add_node_h(connection_t *);
// extern int del_node_h(connection_t *);
extern int add_subnet_h(connection_t *);
extern int del_subnet_h(connection_t *);
extern int add_edge_h(connection_t *);
@ -119,4 +114,4 @@ extern int req_key_h(connection_t *);
extern int ans_key_h(connection_t *);
extern int tcppacket_h(connection_t *);
#endif /* __TINC_PROTOCOL_H__ */
#endif /* __TINC_PROTOCOL_H__ */

File diff suppressed because it is too large Load diff

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: protocol_edge.c,v 1.1.4.11 2002/09/09 19:40:04 guus Exp $
$Id: protocol_edge.c,v 1.1.4.12 2002/09/09 21:24:48 guus Exp $
*/
#include "config.h"
@ -45,225 +45,231 @@
#include "system.h"
int send_add_edge(connection_t *c, edge_t *e)
int send_add_edge(connection_t * c, edge_t * e)
{
int x;
char *address, *port;
cp();
sockaddr2str(&e->address, &address, &port);
x = send_request(c, "%d %lx %s %s %s %s %lx %d", ADD_EDGE, random(),
e->from->name, e->to->name, address, port,
e->options, e->weight);
free(address);
free(port);
cp();
return x;
int x;
char *address, *port;
cp();
sockaddr2str(&e->address, &address, &port);
x = send_request(c, "%d %lx %s %s %s %s %lx %d", ADD_EDGE, random(),
e->from->name, e->to->name, address, port,
e->options, e->weight);
free(address);
free(port);
return x;
}
int add_edge_h(connection_t *c)
int add_edge_h(connection_t * c)
{
edge_t *e;
node_t *from, *to;
char from_name[MAX_STRING_SIZE];
char to_name[MAX_STRING_SIZE];
char to_address[MAX_STRING_SIZE];
char to_port[MAX_STRING_SIZE];
sockaddr_t address;
long int options;
int weight;
cp();
if(sscanf(c->buffer, "%*d %*x "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" %lx %d",
from_name, to_name, to_address, to_port, &options, &weight) != 6)
{
syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "ADD_EDGE", c->name, c->hostname);
return -1;
}
edge_t *e;
node_t *from, *to;
char from_name[MAX_STRING_SIZE];
char to_name[MAX_STRING_SIZE];
char to_address[MAX_STRING_SIZE];
char to_port[MAX_STRING_SIZE];
sockaddr_t address;
long int options;
int weight;
/* Check if names are valid */
cp();
if(check_id(from_name))
{
syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "ADD_EDGE", c->name, c->hostname, _("invalid name"));
return -1;
}
if(sscanf(c->buffer, "%*d %*x "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" %lx %d",
from_name, to_name, to_address, to_port, &options, &weight) != 6) {
syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "ADD_EDGE", c->name,
c->hostname);
return -1;
}
if(check_id(to_name))
{
syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "ADD_EDGE", c->name, c->hostname, _("invalid name"));
return -1;
}
/* Check if names are valid */
if(seen_request(c->buffer))
return 0;
if(check_id(from_name)) {
syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "ADD_EDGE", c->name,
c->hostname, _("invalid name"));
return -1;
}
/* Lookup nodes */
if(check_id(to_name)) {
syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "ADD_EDGE", c->name,
c->hostname, _("invalid name"));
return -1;
}
from = lookup_node(from_name);
if(!from)
{
from = new_node();
from->name = xstrdup(from_name);
node_add(from);
}
if(seen_request(c->buffer))
return 0;
to = lookup_node(to_name);
if(!to)
{
to = new_node();
to->name = xstrdup(to_name);
node_add(to);
}
/* Lookup nodes */
/* Convert addresses */
address = str2sockaddr(to_address, to_port);
from = lookup_node(from_name);
/* Check if edge already exists */
e = lookup_edge(from, to);
if(e)
{
if(e->weight != weight || e->options != options || sockaddrcmp(&e->address, &address))
{
if(from == myself)
{
if(debug_lvl >= DEBUG_PROTOCOL)
syslog(LOG_WARNING, _("Got %s from %s (%s) for ourself which does not match existing entry"), "ADD_EDGE", c->name, c->hostname);
send_add_edge(c, e);
return 0;
}
else
{
if(debug_lvl >= DEBUG_PROTOCOL)
syslog(LOG_WARNING, _("Got %s from %s (%s) which does not match existing entry"), "ADD_EDGE", c->name, c->hostname);
edge_del(e);
}
}
else
return 0;
}
else if(from == myself)
{
if(debug_lvl >= DEBUG_PROTOCOL)
syslog(LOG_WARNING, _("Got %s from %s (%s) for ourself which does not exist"), "ADD_EDGE", c->name, c->hostname);
e = new_edge();
e->from = from;
e->to = to;
send_del_edge(c, e);
free_edge(e);
return 0;
}
if(!from) {
from = new_node();
from->name = xstrdup(from_name);
node_add(from);
}
e = new_edge();
e->from = from;
e->to = to;
e->address = address;
e->options = options;
e->weight = weight;
edge_add(e);
to = lookup_node(to_name);
/* Tell the rest about the new edge */
if(!to) {
to = new_node();
to->name = xstrdup(to_name);
node_add(to);
}
forward_request(c);
/* Convert addresses */
/* Run MST before or after we tell the rest? */
address = str2sockaddr(to_address, to_port);
graph();
cp();
return 0;
/* Check if edge already exists */
e = lookup_edge(from, to);
if(e) {
if(e->weight != weight || e->options != options || sockaddrcmp(&e->address, &address)) {
if(from == myself) {
if(debug_lvl >= DEBUG_PROTOCOL)
syslog(LOG_WARNING, _("Got %s from %s (%s) for ourself which does not match existing entry"),
"ADD_EDGE", c->name, c->hostname);
send_add_edge(c, e);
return 0;
} else {
if(debug_lvl >= DEBUG_PROTOCOL)
syslog(LOG_WARNING, _("Got %s from %s (%s) which does not match existing entry"),
"ADD_EDGE", c->name, c->hostname);
edge_del(e);
}
} else
return 0;
} else if(from == myself) {
if(debug_lvl >= DEBUG_PROTOCOL)
syslog(LOG_WARNING, _("Got %s from %s (%s) for ourself which does not exist"),
"ADD_EDGE", c->name, c->hostname);
e = new_edge();
e->from = from;
e->to = to;
send_del_edge(c, e);
free_edge(e);
return 0;
}
e = new_edge();
e->from = from;
e->to = to;
e->address = address;
e->options = options;
e->weight = weight;
edge_add(e);
/* Tell the rest about the new edge */
forward_request(c);
/* Run MST before or after we tell the rest? */
graph();
return 0;
}
int send_del_edge(connection_t *c, edge_t *e)
int send_del_edge(connection_t * c, edge_t * e)
{
cp();
return send_request(c, "%d %lx %s %s", DEL_EDGE, random(),
e->from->name, e->to->name);
cp();
return send_request(c, "%d %lx %s %s", DEL_EDGE, random(),
e->from->name, e->to->name);
}
int del_edge_h(connection_t *c)
int del_edge_h(connection_t * c)
{
edge_t *e;
char from_name[MAX_STRING_SIZE];
char to_name[MAX_STRING_SIZE];
node_t *from, *to;
cp();
if(sscanf(c->buffer, "%*d %*x "MAX_STRING" "MAX_STRING"", from_name, to_name) != 2)
{
syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "DEL_EDGE",
c->name, c->hostname);
return -1;
}
edge_t *e;
char from_name[MAX_STRING_SIZE];
char to_name[MAX_STRING_SIZE];
node_t *from, *to;
/* Check if names are valid */
cp();
if(check_id(from_name))
{
syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "DEL_EDGE", c->name, c->hostname, _("invalid name"));
return -1;
}
if(sscanf(c->buffer, "%*d %*x "MAX_STRING" "MAX_STRING, from_name, to_name) != 2) {
syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "DEL_EDGE", c->name,
c->hostname);
return -1;
}
if(check_id(to_name))
{
syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "DEL_EDGE", c->name, c->hostname, _("invalid name"));
return -1;
}
/* Check if names are valid */
if(seen_request(c->buffer))
return 0;
if(check_id(from_name)) {
syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "DEL_EDGE", c->name,
c->hostname, _("invalid name"));
return -1;
}
/* Lookup nodes */
if(check_id(to_name)) {
syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "DEL_EDGE", c->name,
c->hostname, _("invalid name"));
return -1;
}
from = lookup_node(from_name);
if(!from)
{
if(debug_lvl >= DEBUG_PROTOCOL)
syslog(LOG_ERR, _("Got %s from %s (%s) which does not appear in the edge tree"), "DEL_EDGE", c->name, c->hostname);
return 0;
}
if(seen_request(c->buffer))
return 0;
to = lookup_node(to_name);
if(!to)
{
if(debug_lvl >= DEBUG_PROTOCOL)
syslog(LOG_ERR, _("Got %s from %s (%s) which does not appear in the edge tree"), "DEL_EDGE", c->name, c->hostname);
return 0;
}
/* Lookup nodes */
/* Check if edge exists */
e = lookup_edge(from, to);
if(!e)
{
if(debug_lvl >= DEBUG_PROTOCOL)
syslog(LOG_WARNING, _("Got %s from %s (%s) which does not appear in the edge tree"), "DEL_EDGE", c->name, c->hostname);
return 0;
}
from = lookup_node(from_name);
if(e->from == myself)
{
if(debug_lvl >= DEBUG_PROTOCOL)
syslog(LOG_WARNING, _("Got %s from %s (%s) for ourself"), "DEL_EDGE", c->name, c->hostname);
send_add_edge(c, e); /* Send back a correction */
return 0;
}
if(!from) {
if(debug_lvl >= DEBUG_PROTOCOL)
syslog(LOG_ERR,
_
("Got %s from %s (%s) which does not appear in the edge tree"),
"DEL_EDGE", c->name, c->hostname);
return 0;
}
/* Tell the rest about the deleted edge */
to = lookup_node(to_name);
forward_request(c);
if(!to) {
if(debug_lvl >= DEBUG_PROTOCOL)
syslog(LOG_ERR,
_
("Got %s from %s (%s) which does not appear in the edge tree"),
"DEL_EDGE", c->name, c->hostname);
return 0;
}
/* Delete the edge */
edge_del(e);
/* Check if edge exists */
/* Run MST before or after we tell the rest? */
e = lookup_edge(from, to);
graph();
cp();
return 0;
if(!e) {
if(debug_lvl >= DEBUG_PROTOCOL)
syslog(LOG_WARNING,
_
("Got %s from %s (%s) which does not appear in the edge tree"),
"DEL_EDGE", c->name, c->hostname);
return 0;
}
if(e->from == myself) {
if(debug_lvl >= DEBUG_PROTOCOL)
syslog(LOG_WARNING, _("Got %s from %s (%s) for ourself"),
"DEL_EDGE", c->name, c->hostname);
send_add_edge(c, e); /* Send back a correction */
return 0;
}
/* Tell the rest about the deleted edge */
forward_request(c);
/* Delete the edge */
edge_del(e);
/* Run MST before or after we tell the rest? */
graph();
return 0;
}

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: protocol_key.c,v 1.1.4.12 2002/09/09 19:40:05 guus Exp $
$Id: protocol_key.c,v 1.1.4.13 2002/09/09 21:24:56 guus Exp $
*/
#include "config.h"
@ -45,225 +45,217 @@
int mykeyused = 0;
int send_key_changed(connection_t *c, node_t *n)
int send_key_changed(connection_t * c, node_t * n)
{
cp();
/* Only send this message if some other daemon requested our key previously.
This reduces unnecessary key_changed broadcasts.
*/
cp();
if(n == myself && !mykeyused)
return 0;
cp();
return send_request(c, "%d %lx %s", KEY_CHANGED, random(), n->name);
/* Only send this message if some other daemon requested our key previously.
This reduces unnecessary key_changed broadcasts.
*/
if(n == myself && !mykeyused)
return 0;
return send_request(c, "%d %lx %s", KEY_CHANGED, random(), n->name);
}
int key_changed_h(connection_t *c)
int key_changed_h(connection_t * c)
{
char name[MAX_STRING_SIZE];
node_t *n;
cp();
if(sscanf(c->buffer, "%*d %*x "MAX_STRING, name) != 1)
{
syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "KEY_CHANGED",
c->name, c->hostname);
return -1;
}
char name[MAX_STRING_SIZE];
node_t *n;
if(seen_request(c->buffer))
return 0;
cp();
n = lookup_node(name);
if(!n)
{
syslog(LOG_ERR, _("Got %s from %s (%s) origin %s which does not exist"), "KEY_CHANGED",
c->name, c->hostname, name);
return -1;
}
n->status.validkey = 0;
n->status.waitingforkey = 0;
/* Tell the others */
forward_request(c);
cp();
return 0;
}
int send_req_key(connection_t *c, node_t *from, node_t *to)
{
cp();
return send_request(c, "%d %s %s", REQ_KEY,
from->name, to->name);
}
int req_key_h(connection_t *c)
{
char from_name[MAX_STRING_SIZE];
char to_name[MAX_STRING_SIZE];
node_t *from, *to;
cp();
if(sscanf(c->buffer, "%*d "MAX_STRING" "MAX_STRING, from_name, to_name) != 2)
{
syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "REQ_KEY",
c->name, c->hostname);
return -1;
}
from = lookup_node(from_name);
if(!from)
{
syslog(LOG_ERR, _("Got %s from %s (%s) origin %s which does not exist in our connection list"), "REQ_KEY",
c->name, c->hostname, from_name);
return -1;
}
to = lookup_node(to_name);
if(!to)
{
syslog(LOG_ERR, _("Got %s from %s (%s) destination %s which does not exist in our connection list"), "REQ_KEY",
c->name, c->hostname, to_name);
return -1;
}
/* Check if this key request is for us */
if(to == myself) /* Yes, send our own key back */
{
mykeyused = 1;
from->received_seqno = 0;
send_ans_key(c, myself, from);
}
else
{
/* Proxy keys
if(to->status.validkey)
{
send_ans_key(c, to, from);
}
else
*/
send_req_key(to->nexthop->connection, from, to);
}
cp();
return 0;
}
int send_ans_key(connection_t *c, node_t *from, node_t *to)
{
char key[MAX_STRING_SIZE];
cp();
bin2hex(from->key, key, from->keylength);
key[from->keylength * 2] = '\0';
cp();
return send_request(c, "%d %s %s %s %d %d %d %d", ANS_KEY,
from->name, to->name, key, from->cipher?from->cipher->nid:0, from->digest?from->digest->type:0, from->maclength, from->compression);
}
int ans_key_h(connection_t *c)
{
char from_name[MAX_STRING_SIZE];
char to_name[MAX_STRING_SIZE];
char key[MAX_STRING_SIZE];
int cipher, digest, maclength, compression;
node_t *from, *to;
cp();
if(sscanf(c->buffer, "%*d "MAX_STRING" "MAX_STRING" "MAX_STRING" %d %d %d %d", from_name, to_name, key, &cipher, &digest, &maclength, &compression) != 7)
{
syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "ANS_KEY",
c->name, c->hostname);
return -1;
}
from = lookup_node(from_name);
if(!from)
{
syslog(LOG_ERR, _("Got %s from %s (%s) origin %s which does not exist in our connection list"), "ANS_KEY",
c->name, c->hostname, from_name);
return -1;
}
to = lookup_node(to_name);
if(!to)
{
syslog(LOG_ERR, _("Got %s from %s (%s) destination %s which does not exist in our connection list"), "ANS_KEY",
c->name, c->hostname, to_name);
return -1;
}
/* Forward it if necessary */
if(to != myself)
{
return send_request(to->nexthop->connection, "%s", c->buffer);
}
/* Update our copy of the origin's packet key */
if(from->key)
free(from->key);
from->key = xstrdup(key);
from->keylength = strlen(key) / 2;
hex2bin(from->key, from->key, from->keylength);
from->key[from->keylength] = '\0';
from->status.validkey = 1;
from->status.waitingforkey = 0;
from->sent_seqno = 0;
/* Check and lookup cipher and digest algorithms */
if(cipher)
{
from->cipher = EVP_get_cipherbynid(cipher);
if(!from->cipher)
{
syslog(LOG_ERR, _("Node %s (%s) uses unknown cipher!"), from->name, from->hostname);
return -1;
if(sscanf(c->buffer, "%*d %*x " MAX_STRING, name) != 1) {
syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "KEY_CHANGED",
c->name, c->hostname);
return -1;
}
if(from->keylength != from->cipher->key_len + from->cipher->iv_len)
{
syslog(LOG_ERR, _("Node %s (%s) uses wrong keylength!"), from->name, from->hostname);
return -1;
}
}
else
{
from->cipher = NULL;
}
from->maclength = maclength;
if(seen_request(c->buffer))
return 0;
if(digest)
{
from->digest = EVP_get_digestbynid(digest);
if(!from->digest)
{
syslog(LOG_ERR, _("Node %s (%s) uses unknown digest!"), from->name, from->hostname);
return -1;
n = lookup_node(name);
if(!n) {
syslog(LOG_ERR, _("Got %s from %s (%s) origin %s which does not exist"),
"KEY_CHANGED", c->name, c->hostname, name);
return -1;
}
if(from->maclength > from->digest->md_size || from->maclength < 0)
{
syslog(LOG_ERR, _("Node %s (%s) uses bogus MAC length!"), from->name, from->hostname);
return -1;
}
}
else
{
from->digest = NULL;
}
from->compression = compression;
flush_queue(from);
cp();
return 0;
n->status.validkey = 0;
n->status.waitingforkey = 0;
/* Tell the others */
forward_request(c);
return 0;
}
int send_req_key(connection_t * c, node_t * from, node_t * to)
{
cp();
return send_request(c, "%d %s %s", REQ_KEY, from->name, to->name);
}
int req_key_h(connection_t * c)
{
char from_name[MAX_STRING_SIZE];
char to_name[MAX_STRING_SIZE];
node_t *from, *to;
cp();
if(sscanf(c->buffer, "%*d " MAX_STRING " " MAX_STRING, from_name, to_name) != 2) {
syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "REQ_KEY", c->name,
c->hostname);
return -1;
}
from = lookup_node(from_name);
if(!from) {
syslog(LOG_ERR, _("Got %s from %s (%s) origin %s which does not exist in our connection list"),
"REQ_KEY", c->name, c->hostname, from_name);
return -1;
}
to = lookup_node(to_name);
if(!to) {
syslog(LOG_ERR, _("Got %s from %s (%s) destination %s which does not exist in our connection list"),
"REQ_KEY", c->name, c->hostname, to_name);
return -1;
}
/* Check if this key request is for us */
if(to == myself) { /* Yes, send our own key back */
mykeyused = 1;
from->received_seqno = 0;
send_ans_key(c, myself, from);
} else {
send_req_key(to->nexthop->connection, from, to);
}
return 0;
}
int send_ans_key(connection_t * c, node_t * from, node_t * to)
{
char key[MAX_STRING_SIZE];
cp();
bin2hex(from->key, key, from->keylength);
key[from->keylength * 2] = '\0';
return send_request(c, "%d %s %s %s %d %d %d %d", ANS_KEY,
from->name, to->name, key,
from->cipher ? from->cipher->nid : 0,
from->digest ? from->digest->type : 0, from->maclength,
from->compression);
}
int ans_key_h(connection_t * c)
{
char from_name[MAX_STRING_SIZE];
char to_name[MAX_STRING_SIZE];
char key[MAX_STRING_SIZE];
int cipher, digest, maclength, compression;
node_t *from, *to;
cp();
if(sscanf(c->buffer, "%*d "MAX_STRING" "MAX_STRING" "MAX_STRING" %d %d %d %d",
from_name, to_name, key, &cipher, &digest, &maclength,
&compression) != 7) {
syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "ANS_KEY", c->name,
c->hostname);
return -1;
}
from = lookup_node(from_name);
if(!from) {
syslog(LOG_ERR, _("Got %s from %s (%s) origin %s which does not exist in our connection list"),
"ANS_KEY", c->name, c->hostname, from_name);
return -1;
}
to = lookup_node(to_name);
if(!to) {
syslog(LOG_ERR, _("Got %s from %s (%s) destination %s which does not exist in our connection list"),
"ANS_KEY", c->name, c->hostname, to_name);
return -1;
}
/* Forward it if necessary */
if(to != myself) {
return send_request(to->nexthop->connection, "%s", c->buffer);
}
/* Update our copy of the origin's packet key */
if(from->key)
free(from->key);
from->key = xstrdup(key);
from->keylength = strlen(key) / 2;
hex2bin(from->key, from->key, from->keylength);
from->key[from->keylength] = '\0';
from->status.validkey = 1;
from->status.waitingforkey = 0;
from->sent_seqno = 0;
/* Check and lookup cipher and digest algorithms */
if(cipher) {
from->cipher = EVP_get_cipherbynid(cipher);
if(!from->cipher) {
syslog(LOG_ERR, _("Node %s (%s) uses unknown cipher!"), from->name,
from->hostname);
return -1;
}
if(from->keylength != from->cipher->key_len + from->cipher->iv_len) {
syslog(LOG_ERR, _("Node %s (%s) uses wrong keylength!"), from->name,
from->hostname);
return -1;
}
} else {
from->cipher = NULL;
}
from->maclength = maclength;
if(digest) {
from->digest = EVP_get_digestbynid(digest);
if(!from->digest) {
syslog(LOG_ERR, _("Node %s (%s) uses unknown digest!"), from->name,
from->hostname);
return -1;
}
if(from->maclength > from->digest->md_size || from->maclength < 0) {
syslog(LOG_ERR, _("Node %s (%s) uses bogus MAC length!"),
from->name, from->hostname);
return -1;
}
} else {
from->digest = NULL;
}
from->compression = compression;
flush_queue(from);
return 0;
}

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: protocol_misc.c,v 1.1.4.5 2002/09/09 19:40:08 guus Exp $
$Id: protocol_misc.c,v 1.1.4.6 2002/09/09 21:25:02 guus Exp $
*/
#include "config.h"
@ -42,157 +42,169 @@
/* Status and error notification routines */
int send_status(connection_t *c, 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(c, "%d %d %s", STATUS, statusno, statusstring);
cp();
if(!statusstring)
statusstring = status_text[statusno];
return send_request(c, "%d %d %s", STATUS, statusno, statusstring);
}
int status_h(connection_t *c)
int status_h(connection_t * c)
{
int statusno;
char statusstring[MAX_STRING_SIZE];
cp();
if(sscanf(c->buffer, "%*d %d "MAX_STRING, &statusno, statusstring) != 2)
{
syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "STATUS",
c->name, c->hostname);
return -1;
}
int statusno;
char statusstring[MAX_STRING_SIZE];
if(debug_lvl >= DEBUG_STATUS)
{
syslog(LOG_NOTICE, _("Status message from %s (%s): %s: %s"),
c->name, c->hostname, status_text[statusno], statusstring);
}
cp();
cp();
return 0;
if(sscanf(c->buffer, "%*d %d " MAX_STRING, &statusno, statusstring) != 2) {
syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "STATUS",
c->name, c->hostname);
return -1;
}
if(debug_lvl >= DEBUG_STATUS) {
syslog(LOG_NOTICE, _("Status message from %s (%s): %s: %s"),
c->name, c->hostname, status_text[statusno], statusstring);
}
return 0;
}
int send_error(connection_t *c, int err, char *errstring)
int send_error(connection_t * c, int err, char *errstring)
{
cp();
if(!errstring)
errstring = strerror(err);
return send_request(c, "%d %d %s", ERROR, err, errstring);
cp();
if(!errstring)
errstring = strerror(err);
return send_request(c, "%d %d %s", ERROR, err, errstring);
}
int error_h(connection_t *c)
int error_h(connection_t * c)
{
int err;
char errorstring[MAX_STRING_SIZE];
cp();
if(sscanf(c->buffer, "%*d %d "MAX_STRING, &err, errorstring) != 2)
{
syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "ERROR",
c->name, c->hostname);
return -1;
}
int err;
char errorstring[MAX_STRING_SIZE];
if(debug_lvl >= DEBUG_ERROR)
{
syslog(LOG_NOTICE, _("Error message from %s (%s): %s: %s"),
c->name, c->hostname, strerror(err), errorstring);
}
cp();
terminate_connection(c, c->status.active);
cp();
return 0;
if(sscanf(c->buffer, "%*d %d " MAX_STRING, &err, errorstring) != 2) {
syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "ERROR",
c->name, c->hostname);
return -1;
}
if(debug_lvl >= DEBUG_ERROR) {
syslog(LOG_NOTICE, _("Error message from %s (%s): %s: %s"),
c->name, c->hostname, strerror(err), errorstring);
}
terminate_connection(c, c->status.active);
return 0;
}
int send_termreq(connection_t *c)
int send_termreq(connection_t * c)
{
cp();
return send_request(c, "%d", TERMREQ);
cp();
return send_request(c, "%d", TERMREQ);
}
int termreq_h(connection_t *c)
int termreq_h(connection_t * c)
{
cp();
terminate_connection(c, c->status.active);
cp();
return 0;
cp();
terminate_connection(c, c->status.active);
return 0;
}
int send_ping(connection_t *c)
int send_ping(connection_t * c)
{
cp();
c->status.pinged = 1;
c->last_ping_time = now;
cp();
return send_request(c, "%d", PING);
cp();
c->status.pinged = 1;
c->last_ping_time = now;
return send_request(c, "%d", PING);
}
int ping_h(connection_t *c)
int ping_h(connection_t * c)
{
cp();
return send_pong(c);
cp();
return send_pong(c);
}
int send_pong(connection_t *c)
int send_pong(connection_t * c)
{
cp();
return send_request(c, "%d", PONG);
cp();
return send_request(c, "%d", PONG);
}
int pong_h(connection_t *c)
int pong_h(connection_t * c)
{
cp();
c->status.pinged = 0;
cp();
/* Succesful connection, reset timeout if this is an outgoing connection. */
if(c->outgoing)
c->outgoing->timeout = 0;
cp();
return 0;
c->status.pinged = 0;
/* Succesful connection, reset timeout if this is an outgoing connection. */
if(c->outgoing)
c->outgoing->timeout = 0;
return 0;
}
/* Sending and receiving packets via TCP */
int send_tcppacket(connection_t *c, vpn_packet_t *packet)
int send_tcppacket(connection_t * c, vpn_packet_t * packet)
{
int x;
cp();
/* Evil hack. */
int x;
x = send_request(c, "%d %hd", PACKET, packet->len);
cp();
if(x)
return x;
cp();
return send_meta(c, packet->data, packet->len);
/* Evil hack. */
x = send_request(c, "%d %hd", PACKET, packet->len);
if(x)
return x;
return send_meta(c, packet->data, packet->len);
}
int tcppacket_h(connection_t *c)
int tcppacket_h(connection_t * c)
{
short int len;
cp();
if(sscanf(c->buffer, "%*d %hd", &len) != 1)
{
syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "PACKET", c->name, c->hostname);
return -1;
}
short int len;
/* Set reqlen to len, this will tell receive_meta() that a tcppacket is coming. */
cp();
c->tcplen = len;
cp();
return 0;
if(sscanf(c->buffer, "%*d %hd", &len) != 1) {
syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "PACKET", c->name,
c->hostname);
return -1;
}
/* Set reqlen to len, this will tell receive_meta() that a tcppacket is coming. */
c->tcplen = len;
return 0;
}
/* Status strings */
char (*status_text[]) = {
"Warning",
"Warning",
};
/* Error strings */
char (*error_text[]) = {
"Error",
"Error",
};

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: protocol_node.c,v 1.1.4.7 2002/09/09 19:40:08 guus Exp $
$Id: protocol_node.c,v 1.1.4.8 2002/09/09 21:25:02 guus Exp $
*/
#include "config.h"
@ -43,204 +43,202 @@
#include "system.h"
int send_add_node(connection_t *c, node_t *n)
int send_add_node(connection_t * c, node_t * n)
{
int x;
char *address, *port;
cp();
if(!n->status.reachable)
return 0;
int x;
char *address, *port;
cp();
if(!n->status.reachable)
return 0;
sockaddr2str(&n->address, &address, &port);
x = send_request(c, "%d %s %s %s %lx %d %s %s", ADD_NODE,
n->name, address, port,
n->options, n->distance + 1, // Alternatively, use n->distance + c->estimated_weight
n->prevhop->name, n->via->name);
free(address);
free(port);
cp();
return x;
sockaddr2str(&n->address, &address, &port);
x = send_request(c, "%d %s %s %s %lx %d %s %s", ADD_NODE, n->name, address, port, n->options, n->distance + 1, // Alternatively, use n->distance + c->estimated_weight
n->prevhop->name, n->via->name);
free(address);
free(port);
cp();
return x;
}
int add_node_h(connection_t *c)
int add_node_h(connection_t * c)
{
connection_t *other;
node_t *n, *prevhop, *via;
char name[MAX_STRING_SIZE];
char address[MAX_STRING_SIZE];
char port[MAX_STRING_SIZE];
char prevhopname[MAX_STRING_SIZE];
char vianame[MAX_STRING_SIZE];
long int options;
int distance;
avl_node_t *node;
cp();
if(sscanf(c->buffer, "%*d "MAX_STRING" "MAX_STRING" "MAX_STRING" %lx %d "MAX_STRING" "MAX_STRING,
name, address, port, &options, &distance, prevhopname, vianame) != 7)
{
syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "ADD_NODE", c->name, c->hostname);
return -1;
}
connection_t *other;
node_t *n, *prevhop, *via;
char name[MAX_STRING_SIZE];
char address[MAX_STRING_SIZE];
char port[MAX_STRING_SIZE];
char prevhopname[MAX_STRING_SIZE];
char vianame[MAX_STRING_SIZE];
long int options;
int distance;
avl_node_t *node;
cp();
if(sscanf
(c->buffer,
"%*d " MAX_STRING " " MAX_STRING " " MAX_STRING " %lx %d " MAX_STRING
" " MAX_STRING, name, address, port, &options, &distance, prevhopname,
vianame) != 7) {
syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "ADD_NODE", c->name,
c->hostname);
return -1;
}
/* Check if names are valid */
/* Check if names are valid */
if(check_id(name))
{
syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "ADD_NODE", c->name, c->hostname, _("invalid name"));
return -1;
}
if(check_id(name)) {
syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "ADD_NODE", c->name,
c->hostname, _("invalid name"));
return -1;
}
/* This node is indirect if it's nexthop is as well */
if(c->node->options & OPTION_INDIRECT)
options |= OPTION_INDIRECT;
/* This node is indirect if it's nexthop is as well */
/* Lookup nodes */
if(c->node->options & OPTION_INDIRECT)
options |= OPTION_INDIRECT;
prevhop = lookup_node(prevhopname);
if(!prevhop)
{
prevhop = new_node();
prevhop->name = xstrdup(prevhopname);
node_add(prevhop);
}
/* Lookup nodes */
via = lookup_node(vianame);
if(!via)
{
via = new_node();
via->name = xstrdup(vianame);
node_add(via);
}
prevhop = lookup_node(prevhopname);
n = lookup_node(name);
if(!n)
{
// It's a new node. Add it and tell the others.
n = new_node();
n->name = xstrdup(name);
n->address = str2sockaddr(address, port);
n->hostname = sockaddr2hostname(&n->address);
n->options = options;
n->distance = distance;
n->nexthop = c->node;
n->prevhop = prevhop;
n->via = via;
node_add(n);
if(prevhop == myself)
{
syslog(LOG_WARNING, _("Got ADD_NODE %s prevhop %s via %s from %s, sending back a DEL_NODE!"), name, prevhopname, vianame, c->name);
// send_del_node(c, n);
return 0;
}
n->status.reachable = 1;
}
else
{
// If this ADD_NODE is closer or more direct, use it instead of the old one.
if(!n->status.reachable || ((n->options & OPTION_INDIRECT) && !(options & OPTION_INDIRECT)) || n->distance > distance)
{
if(prevhop == myself)
{
syslog(LOG_WARNING, _("Got ADD_NODE %s prevhop %s via %s from %s!"), name, prevhopname, vianame, c->name);
// send_del_node(c, n);
return 0;
}
node = avl_unlink(node_udp_tree, n);
n->address = str2sockaddr(address, port);
avl_insert_node(node_udp_tree, node);
if(n->hostname)
free(n->hostname);
n->hostname = sockaddr2hostname(&n->address);
n->options = options;
n->distance = distance;
n->via = n->nexthop = c->node;
n->status.reachable = 1;
n->status.validkey = 0;
n->status.waitingforkey = 0;
}
else
// Otherwise, just ignore it.
return 0;
}
if(!prevhop) {
prevhop = new_node();
prevhop->name = xstrdup(prevhopname);
node_add(prevhop);
}
/* Tell the rest about the new node */
via = lookup_node(vianame);
for(node = connection_tree->head; node; node = node->next)
{
other = (connection_t *)node->data;
if(other->status.active && other != c)
send_add_node(other, n);
}
if(!via) {
via = new_node();
via->name = xstrdup(vianame);
node_add(via);
}
cp();
return 0;
n = lookup_node(name);
if(!n) {
// It's a new node. Add it and tell the others.
n = new_node();
n->name = xstrdup(name);
n->address = str2sockaddr(address, port);
n->hostname = sockaddr2hostname(&n->address);
n->options = options;
n->distance = distance;
n->nexthop = c->node;
n->prevhop = prevhop;
n->via = via;
node_add(n);
if(prevhop == myself) {
syslog(LOG_WARNING,
_
("Got ADD_NODE %s prevhop %s via %s from %s, sending back a DEL_NODE!"),
name, prevhopname, vianame, c->name);
// send_del_node(c, n);
return 0;
}
n->status.reachable = 1;
} else {
// If this ADD_NODE is closer or more direct, use it instead of the old one.
if(!n->status.reachable
|| ((n->options & OPTION_INDIRECT) && !(options & OPTION_INDIRECT))
|| n->distance > distance) {
if(prevhop == myself) {
syslog(LOG_WARNING,
_("Got ADD_NODE %s prevhop %s via %s from %s!"), name,
prevhopname, vianame, c->name);
// send_del_node(c, n);
return 0;
}
node = avl_unlink(node_udp_tree, n);
n->address = str2sockaddr(address, port);
avl_insert_node(node_udp_tree, node);
if(n->hostname)
free(n->hostname);
n->hostname = sockaddr2hostname(&n->address);
n->options = options;
n->distance = distance;
n->via = n->nexthop = c->node;
n->status.reachable = 1;
n->status.validkey = 0;
n->status.waitingforkey = 0;
} else
// Otherwise, just ignore it.
return 0;
}
/* Tell the rest about the new node */
for(node = connection_tree->head; node; node = node->next) {
other = (connection_t *) node->data;
if(other->status.active && other != c)
send_add_node(other, n);
}
cp();
return 0;
}
int send_del_node(connection_t *c, node_t *n)
int send_del_node(connection_t * c, node_t * n)
{
cp();
return send_request(c, "%d %s %s", DEL_NODE, n->name, n->prevhop->name);
cp();
return send_request(c, "%d %s %s", DEL_NODE, n->name, n->prevhop->name);
}
int del_node_h(connection_t *c)
int del_node_h(connection_t * c)
{
char name[MAX_STRING_SIZE];
char prevhopname[MAX_STRING_SIZE];
node_t *n, *prevhop;
connection_t *other;
avl_node_t *node;
cp();
if(sscanf(c->buffer, "%*d "MAX_STRING" "MAX_STRING, name, prevhopname) != 2)
{
syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "DEL_NODE",
c->name, c->hostname);
return -1;
}
char name[MAX_STRING_SIZE];
char prevhopname[MAX_STRING_SIZE];
node_t *n, *prevhop;
connection_t *other;
avl_node_t *node;
cp();
if(sscanf(c->buffer, "%*d " MAX_STRING " " MAX_STRING, name, prevhopname) !=
2) {
syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "DEL_NODE", c->name,
c->hostname);
return -1;
}
/* Check if names are valid */
/* Check if names are valid */
if(check_id(name))
{
syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "DEL_NODE", c->name, c->hostname, _("invalid name"));
return -1;
}
if(check_id(name)) {
syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "DEL_NODE", c->name,
c->hostname, _("invalid name"));
return -1;
}
/* Lookup nodes */
/* Lookup nodes */
n = lookup_node(name);
prevhop = lookup_node(prevhopname);
n = lookup_node(name);
prevhop = lookup_node(prevhopname);
if(!n || !prevhop)
{
if(debug_lvl >= DEBUG_PROTOCOL)
syslog(LOG_WARNING, _("Got %s from %s (%s) which does not appear in the node tree"), "DEL_NODE", c->name, c->hostname);
return 0;
}
if(!n || !prevhop) {
if(debug_lvl >= DEBUG_PROTOCOL)
syslog(LOG_WARNING,
_
("Got %s from %s (%s) which does not appear in the node tree"),
"DEL_NODE", c->name, c->hostname);
return 0;
}
/* If we got a DEL_NODE but we know of a different route to it, tell the one who send the DEL_NODE */
/* If we got a DEL_NODE but we know of a different route to it, tell the one who send the DEL_NODE */
if(n->nexthop != c->node)
{
return send_add_node(c, n);
}
/* Otherwise, tell the rest about the deleted node */
if(n->nexthop != c->node) {
return send_add_node(c, n);
}
for(node = connection_tree->head; node; node = node->next)
{
other = (connection_t *)node->data;
if(other->status.active && other != c)
send_del_node(other, n);
}
/* Otherwise, tell the rest about the deleted node */
/* "Delete" the node */
n->status.reachable = 0;
n->status.validkey = 0;
cp();
return 0;
for(node = connection_tree->head; node; node = node->next) {
other = (connection_t *) node->data;
if(other->status.active && other != c)
send_del_node(other, n);
}
/* "Delete" the node */
n->status.reachable = 0;
n->status.validkey = 0;
cp();
return 0;
}

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: protocol_subnet.c,v 1.1.4.7 2002/09/09 19:40:09 guus Exp $
$Id: protocol_subnet.c,v 1.1.4.8 2002/09/09 21:25:02 guus Exp $
*/
#include "config.h"
@ -43,185 +43,191 @@
#include "system.h"
int send_add_subnet(connection_t *c, subnet_t *subnet)
int send_add_subnet(connection_t * c, subnet_t * subnet)
{
int x;
char *netstr;
cp();
x = send_request(c, "%d %lx %s %s", ADD_SUBNET, random(),
subnet->owner->name, netstr = net2str(subnet));
free(netstr);
cp();
return x;
int x;
char *netstr;
cp();
x = send_request(c, "%d %lx %s %s", ADD_SUBNET, random(),
subnet->owner->name, netstr = net2str(subnet));
free(netstr);
return x;
}
int add_subnet_h(connection_t *c)
int add_subnet_h(connection_t * c)
{
char subnetstr[MAX_STRING_SIZE];
char name[MAX_STRING_SIZE];
node_t *owner;
subnet_t *s;
cp();
if(sscanf(c->buffer, "%*d %*x "MAX_STRING" "MAX_STRING, name, subnetstr) != 2)
{
syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "ADD_SUBNET", c->name, c->hostname);
return -1;
}
char subnetstr[MAX_STRING_SIZE];
char name[MAX_STRING_SIZE];
node_t *owner;
subnet_t *s;
/* Check if owner name is a valid */
cp();
if(check_id(name))
{
syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "ADD_SUBNET", c->name, c->hostname, _("invalid name"));
return -1;
}
if(sscanf(c->buffer, "%*d %*x " MAX_STRING " " MAX_STRING, name, subnetstr) != 2) {
syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "ADD_SUBNET", c->name,
c->hostname);
return -1;
}
/* Check if subnet string is valid */
/* Check if owner name is a valid */
s = str2net(subnetstr);
if(check_id(name)) {
syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "ADD_SUBNET", c->name,
c->hostname, _("invalid name"));
return -1;
}
if(!s)
{
syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "ADD_SUBNET", c->name, c->hostname, _("invalid subnet string"));
return -1;
}
/* Check if subnet string is valid */
if(seen_request(c->buffer))
return 0;
/* Check if the owner of the new subnet is in the connection list */
s = str2net(subnetstr);
owner = lookup_node(name);
if(!s) {
syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "ADD_SUBNET", c->name,
c->hostname, _("invalid subnet string"));
return -1;
}
if(!owner)
{
owner = new_node();
owner->name = xstrdup(name);
node_add(owner);
}
if(seen_request(c->buffer))
return 0;
/* Check if we already know this subnet */
if(lookup_subnet(owner, s))
{
free_subnet(s);
return 0;
}
/* Check if the owner of the new subnet is in the connection list */
/* If we don't know this subnet, but we are the owner, retaliate with a DEL_SUBNET */
owner = lookup_node(name);
if(owner == myself)
{
if(debug_lvl >= DEBUG_PROTOCOL)
syslog(LOG_WARNING, _("Got %s from %s (%s) for ourself"), "ADD_SUBNET", c->name, c->hostname);
s->owner = myself;
send_del_subnet(c, s);
return 0;
}
if(!owner) {
owner = new_node();
owner->name = xstrdup(name);
node_add(owner);
}
/* If everything is correct, add the subnet to the list of the owner */
/* Check if we already know this subnet */
subnet_add(owner, s);
if(lookup_subnet(owner, s)) {
free_subnet(s);
return 0;
}
/* Tell the rest */
/* If we don't know this subnet, but we are the owner, retaliate with a DEL_SUBNET */
forward_request(c);
cp();
return 0;
if(owner == myself) {
if(debug_lvl >= DEBUG_PROTOCOL)
syslog(LOG_WARNING, _("Got %s from %s (%s) for ourself"),
"ADD_SUBNET", c->name, c->hostname);
s->owner = myself;
send_del_subnet(c, s);
return 0;
}
/* If everything is correct, add the subnet to the list of the owner */
subnet_add(owner, s);
/* Tell the rest */
forward_request(c);
return 0;
}
int send_del_subnet(connection_t *c, subnet_t *s)
int send_del_subnet(connection_t * c, subnet_t * s)
{
int x;
char *netstr;
cp();
netstr = net2str(s);
x = send_request(c, "%d %lx %s %s", DEL_SUBNET, random(), s->owner->name, netstr);
free(netstr);
cp();
return x;
int x;
char *netstr;
cp();
netstr = net2str(s);
x = send_request(c, "%d %lx %s %s", DEL_SUBNET, random(), s->owner->name, netstr);
free(netstr);
return x;
}
int del_subnet_h(connection_t *c)
int del_subnet_h(connection_t * c)
{
char subnetstr[MAX_STRING_SIZE];
char name[MAX_STRING_SIZE];
node_t *owner;
subnet_t *s, *find;
cp();
if(sscanf(c->buffer, "%*d %*x "MAX_STRING" "MAX_STRING, name, subnetstr) != 2)
{
syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "DEL_SUBNET", c->name, c->hostname);
return -1;
}
char subnetstr[MAX_STRING_SIZE];
char name[MAX_STRING_SIZE];
node_t *owner;
subnet_t *s, *find;
/* Check if owner name is a valid */
cp();
if(check_id(name))
{
syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "DEL_SUBNET", c->name, c->hostname, _("invalid name"));
return -1;
}
if(sscanf(c->buffer, "%*d %*x " MAX_STRING " " MAX_STRING, name, subnetstr) != 2) {
syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "DEL_SUBNET", c->name,
c->hostname);
return -1;
}
/* Check if the owner of the new subnet is in the connection list */
/* Check if owner name is a valid */
owner = lookup_node(name);
if(check_id(name)) {
syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "DEL_SUBNET", c->name,
c->hostname, _("invalid name"));
return -1;
}
if(!owner)
{
if(debug_lvl >= DEBUG_PROTOCOL)
syslog(LOG_WARNING, _("Got %s from %s (%s) for %s which is not in our node tree"),
"DEL_SUBNET", c->name, c->hostname, name);
return 0;
}
/* Check if the owner of the new subnet is in the connection list */
/* Check if subnet string is valid */
owner = lookup_node(name);
s = str2net(subnetstr);
if(!owner) {
if(debug_lvl >= DEBUG_PROTOCOL)
syslog(LOG_WARNING, _("Got %s from %s (%s) for %s which is not in our node tree"),
"DEL_SUBNET", c->name, c->hostname, name);
return 0;
}
if(!s)
{
syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "DEL_SUBNET", c->name, c->hostname, _("invalid subnet string"));
return -1;
}
/* Check if subnet string is valid */
if(seen_request(c->buffer))
return 0;
s = str2net(subnetstr);
/* If everything is correct, delete the subnet from the list of the owner */
if(!s) {
syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "DEL_SUBNET", c->name,
c->hostname, _("invalid subnet string"));
return -1;
}
s->owner = owner;
if(seen_request(c->buffer))
return 0;
find = lookup_subnet(owner, s);
free_subnet(s);
/* If everything is correct, delete the subnet from the list of the owner */
if(!find)
{
if(debug_lvl >= DEBUG_PROTOCOL)
syslog(LOG_WARNING, _("Got %s from %s (%s) for %s which does not appear in his subnet tree"),
"DEL_SUBNET", c->name, c->hostname, name);
return 0;
}
/* If we are the owner of this subnet, retaliate with an ADD_SUBNET */
if(owner == myself)
{
if(debug_lvl >= DEBUG_PROTOCOL)
syslog(LOG_WARNING, _("Got %s from %s (%s) for ourself"), "DEL_SUBNET", c->name, c->hostname);
send_add_subnet(c, find);
return 0;
}
s->owner = owner;
/* Tell the rest */
find = lookup_subnet(owner, s);
forward_request(c);
free_subnet(s);
/* Finally, delete it. */
if(!find) {
if(debug_lvl >= DEBUG_PROTOCOL)
syslog(LOG_WARNING, _("Got %s from %s (%s) for %s which does not appear in his subnet tree"),
"DEL_SUBNET", c->name, c->hostname, name);
return 0;
}
subnet_del(owner, find);
/* If we are the owner of this subnet, retaliate with an ADD_SUBNET */
cp();
return 0;
if(owner == myself) {
if(debug_lvl >= DEBUG_PROTOCOL)
syslog(LOG_WARNING, _("Got %s from %s (%s) for ourself"),
"DEL_SUBNET", c->name, c->hostname);
send_add_subnet(c, find);
return 0;
}
/* Tell the rest */
forward_request(c);
/* Finally, delete it. */
subnet_del(owner, find);
return 0;
}

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: device.c,v 1.1.2.1 2002/07/18 14:30:45 guus Exp $
$Id: device.c,v 1.1.2.2 2002/09/09 21:25:28 guus Exp $
*/
#include "config.h"
@ -60,115 +60,103 @@ extern subnet_t mymac;
*/
int setup_device(void)
{
struct ifreq ifr;
struct sockaddr_ll sa;
cp
if(!get_config_string(lookup_config(config_tree, "Interface"), &interface))
interface = "eth0";
struct ifreq ifr;
struct sockaddr_ll sa;
cp if(!get_config_string
(lookup_config(config_tree, "Interface"), &interface))
interface = "eth0";
if(!get_config_string(lookup_config(config_tree, "Device"), &device))
device = interface;
if(!get_config_string(lookup_config(config_tree, "Device"), &device))
device = interface;
device_info = _("raw socket");
cp
if((device_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0)
{
syslog(LOG_ERR, _("Could not open %s: %s"), device_info, strerror(errno));
return -1;
}
device_info = _("raw socket");
cp if((device_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0) {
syslog(LOG_ERR, _("Could not open %s: %s"), device_info,
strerror(errno));
return -1;
}
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_ifrn.ifrn_name, interface, IFNAMSIZ);
if(ioctl(device_fd, SIOCGIFINDEX, &ifr))
{
close(device_fd);
syslog(LOG_ERR, _("Can't find interface %s: %s"), interface, strerror(errno));
return -1;
}
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_ifrn.ifrn_name, interface, IFNAMSIZ);
if(ioctl(device_fd, SIOCGIFINDEX, &ifr)) {
close(device_fd);
syslog(LOG_ERR, _("Can't find interface %s: %s"), interface,
strerror(errno));
return -1;
}
memset(&sa, '0', sizeof(sa));
sa.sll_family = AF_PACKET;
sa.sll_protocol = htons(ETH_P_ALL);
sa.sll_ifindex = ifr.ifr_ifindex;
memset(&sa, '0', sizeof(sa));
sa.sll_family = AF_PACKET;
sa.sll_protocol = htons(ETH_P_ALL);
sa.sll_ifindex = ifr.ifr_ifindex;
if(bind(device_fd, (struct sockaddr *)&sa, (socklen_t)sizeof(sa)))
{
syslog(LOG_ERR, _("Could not bind to %s: %s"), device, strerror(errno));
return -1;
}
cp
/* Set default MAC address for ethertap devices */
if(bind(device_fd, (struct sockaddr *) &sa, (socklen_t) sizeof(sa))) {
syslog(LOG_ERR, _("Could not bind to %s: %s"), device, strerror(errno));
return -1;
}
cp
/* 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;
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;
syslog(LOG_INFO, _("%s is a %s"), device, device_info);
cp
return 0;
syslog(LOG_INFO, _("%s is a %s"), device, device_info);
cp return 0;
}
void close_device(void)
{
cp
close(device_fd);
cp close(device_fd);
}
/*
read, encrypt and send data that is
available through the ethertap device
*/
int read_packet(vpn_packet_t *packet)
int read_packet(vpn_packet_t * packet)
{
int lenin;
cp
int lenin;
cp if((lenin = read(device_fd, packet->data, MTU)) <= 0) {
syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info,
device, strerror(errno));
return -1;
}
if((lenin = read(device_fd, packet->data, MTU)) <= 0)
{
syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, device, strerror(errno));
return -1;
}
packet->len = lenin;
packet->len = lenin;
device_total_in += packet->len;
device_total_in += packet->len;
if(debug_lvl >= DEBUG_TRAFFIC) {
syslog(LOG_DEBUG, _("Read packet of %d bytes from %s"), packet->len,
device_info);
}
if(debug_lvl >= DEBUG_TRAFFIC)
{
syslog(LOG_DEBUG, _("Read packet of %d bytes from %s"), packet->len, device_info);
}
return 0;
cp}
return 0;
cp
}
int write_packet(vpn_packet_t *packet)
int write_packet(vpn_packet_t * packet)
{
cp
if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_DEBUG, _("Writing packet of %d bytes to %s"),
packet->len, device_info);
cp if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_DEBUG, _("Writing packet of %d bytes to %s"),
packet->len, device_info);
if(write(device_fd, packet->data, packet->len) < 0)
{
syslog(LOG_ERR, _("Can't write to %s %s: %s"), device_info, device, strerror(errno));
return -1;
}
if(write(device_fd, packet->data, packet->len) < 0) {
syslog(LOG_ERR, _("Can't write to %s %s: %s"), device_info, device,
strerror(errno));
return -1;
}
device_total_out += packet->len;
cp
return 0;
device_total_out += packet->len;
cp return 0;
}
void dump_device_stats(void)
{
cp
syslog(LOG_DEBUG, _("Statistics for %s %s:"), device_info, device);
syslog(LOG_DEBUG, _(" total bytes in: %10d"), device_total_in);
syslog(LOG_DEBUG, _(" total bytes out: %10d"), device_total_out);
cp
}
cp syslog(LOG_DEBUG, _("Statistics for %s %s:"), device_info, device);
syslog(LOG_DEBUG, _(" total bytes in: %10d"), device_total_in);
syslog(LOG_DEBUG, _(" total bytes out: %10d"), device_total_out);
cp}

View file

@ -17,24 +17,24 @@
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.44 2002/09/09 19:40:11 guus Exp $
$Id: route.c,v 1.1.2.45 2002/09/09 21:25:07 guus Exp $
*/
#include "config.h"
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#include <sys/param.h>
#endif
#include <sys/socket.h>
#include <netinet/in.h>
#ifdef HAVE_NET_IF_H
#include <net/if.h>
#include <net/if.h>
#endif
#ifdef HAVE_NET_ETHERNET_H
#include <net/ethernet.h>
#include <net/ethernet.h>
#endif
#ifdef HAVE_NETINET_IN_SYSTM_H
#include <netinet/in_systm.h>
#include <netinet/in_systm.h>
#endif
#include <netinet/ip6.h>
#include <netinet/icmp6.h>
@ -44,7 +44,7 @@
#include <syslog.h>
#include <string.h>
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#include <inttypes.h>
#endif
#include <avl_tree.h>
@ -59,7 +59,7 @@
#include "system.h"
#ifndef ETHER_ADDR_LEN
#define ETHER_ADDR_LEN 6
#define ETHER_ADDR_LEN 6
#endif
int routing_mode = RMODE_ROUTER;
@ -67,437 +67,437 @@ int priorityinheritance = 0;
int macexpire = 600;
subnet_t mymac;
void learn_mac(mac_t *address)
void learn_mac(mac_t * address)
{
subnet_t *subnet;
avl_node_t *node;
connection_t *c;
cp();
subnet = lookup_subnet_mac(address);
subnet_t *subnet;
avl_node_t *node;
connection_t *c;
/* If we don't know this MAC address yet, store it */
if(!subnet || subnet->owner!=myself)
{
if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_INFO, _("Learned new MAC address %hx:%hx:%hx:%hx:%hx:%hx"),
address->x[0], address->x[1], address->x[2], address->x[3], address->x[4], address->x[5]);
subnet = new_subnet();
subnet->type = SUBNET_MAC;
memcpy(&subnet->net.mac.address, address, sizeof(mac_t));
subnet_add(myself, subnet);
cp();
/* And tell all other tinc daemons it's our MAC */
for(node = connection_tree->head; node; node = node->next)
{
c = (connection_t *)node->data;
if(c->status.active)
send_add_subnet(c, subnet);
}
}
subnet = lookup_subnet_mac(address);
subnet->net.mac.lastseen = now;
/* If we don't know this MAC address yet, store it */
if(!subnet || subnet->owner != myself) {
if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_INFO, _("Learned new MAC address %hx:%hx:%hx:%hx:%hx:%hx"),
address->x[0], address->x[1], address->x[2], address->x[3],
address->x[4], address->x[5]);
subnet = new_subnet();
subnet->type = SUBNET_MAC;
memcpy(&subnet->net.mac.address, address, sizeof(mac_t));
subnet_add(myself, subnet);
/* And tell all other tinc daemons it's our MAC */
for(node = connection_tree->head; node; node = node->next) {
c = (connection_t *) node->data;
if(c->status.active)
send_add_subnet(c, subnet);
}
}
subnet->net.mac.lastseen = now;
}
void age_mac(void)
{
subnet_t *s;
connection_t *c;
avl_node_t *node, *next, *node2;
cp();
for(node = myself->subnet_tree->head; node; node = next)
{
next = node->next;
s = (subnet_t *)node->data;
if(s->type == SUBNET_MAC && s->net.mac.lastseen && s->net.mac.lastseen + macexpire < now)
{
if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_INFO, _("MAC address %hx:%hx:%hx:%hx:%hx:%hx expired"),
s->net.mac.address.x[0], s->net.mac.address.x[1], s->net.mac.address.x[2], s->net.mac.address.x[3], s->net.mac.address.x[4], s->net.mac.address.x[5]);
for(node2 = connection_tree->head; node2; node2 = node2->next)
{
c = (connection_t *)node2->data;
if(c->status.active)
send_del_subnet(c, s);
}
subnet_del(myself, s);
subnet_t *s;
connection_t *c;
avl_node_t *node, *next, *node2;
cp();
for(node = myself->subnet_tree->head; node; node = next) {
next = node->next;
s = (subnet_t *) node->data;
if(s->type == SUBNET_MAC && s->net.mac.lastseen && s->net.mac.lastseen + macexpire < now) {
if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_INFO, _("MAC address %hx:%hx:%hx:%hx:%hx:%hx expired"),
s->net.mac.address.x[0], s->net.mac.address.x[1],
s->net.mac.address.x[2], s->net.mac.address.x[3],
s->net.mac.address.x[4], s->net.mac.address.x[5]);
for(node2 = connection_tree->head; node2; node2 = node2->next) {
c = (connection_t *) node2->data;
if(c->status.active)
send_del_subnet(c, s);
}
subnet_del(myself, s);
}
}
}
cp();
}
node_t *route_mac(vpn_packet_t *packet)
node_t *route_mac(vpn_packet_t * packet)
{
subnet_t *subnet;
cp();
/* Learn source address */
subnet_t *subnet;
learn_mac((mac_t *)(&packet->data[6]));
/* Lookup destination address */
subnet = lookup_subnet_mac((mac_t *)(&packet->data[0]));
cp();
if(subnet)
return subnet->owner;
else
return NULL;
/* Learn source address */
learn_mac((mac_t *) (&packet->data[6]));
/* Lookup destination address */
subnet = lookup_subnet_mac((mac_t *) (&packet->data[0]));
if(subnet)
return subnet->owner;
else
return NULL;
}
node_t *route_ipv4(vpn_packet_t *packet)
node_t *route_ipv4(vpn_packet_t * packet)
{
subnet_t *subnet;
cp();
if(priorityinheritance)
packet->priority = packet->data[15];
subnet_t *subnet;
subnet = lookup_subnet_ipv4((ipv4_t *)&packet->data[30]);
cp();
if(!subnet)
{
if(debug_lvl >= DEBUG_TRAFFIC)
{
syslog(LOG_WARNING, _("Cannot route packet: unknown IPv4 destination address %d.%d.%d.%d"),
packet->data[30], packet->data[31], packet->data[32], packet->data[33]);
}
cp();
return NULL;
}
cp();
return subnet->owner;
}
if(priorityinheritance)
packet->priority = packet->data[15];
node_t *route_ipv6(vpn_packet_t *packet)
{
subnet_t *subnet;
cp();
subnet = lookup_subnet_ipv6((ipv6_t *)&packet->data[38]);
cp();
if(!subnet)
{
if(debug_lvl >= DEBUG_TRAFFIC)
{
syslog(LOG_WARNING, _("Cannot route packet: unknown IPv6 destination address %hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx"),
ntohs(*(uint16_t *)&packet->data[38]),
ntohs(*(uint16_t *)&packet->data[40]),
ntohs(*(uint16_t *)&packet->data[42]),
ntohs(*(uint16_t *)&packet->data[44]),
ntohs(*(uint16_t *)&packet->data[46]),
ntohs(*(uint16_t *)&packet->data[48]),
ntohs(*(uint16_t *)&packet->data[50]),
ntohs(*(uint16_t *)&packet->data[52]));
}
subnet = lookup_subnet_ipv4((ipv4_t *) & packet->data[30]);
return NULL;
}
cp();
return subnet->owner;
}
uint16_t inet_checksum(uint16_t *data, int len, uint16_t prevsum)
{
uint32_t checksum = prevsum ^ 0xFFFF;
while(len--)
checksum += ntohs(*data++);
while(checksum >> 16)
checksum = (checksum & 0xFFFF) + (checksum >> 16);
return checksum ^ 0xFFFF;
}
void route_neighborsol(vpn_packet_t *packet)
{
struct ip6_hdr *hdr;
struct nd_neighbor_solicit *ns;
struct nd_opt_hdr *opt;
subnet_t *subnet;
uint16_t checksum;
struct {
struct in6_addr ip6_src; /* source address */
struct in6_addr ip6_dst; /* destination address */
uint32_t length;
uint8_t junk[4];
} pseudo;
cp();
hdr = (struct ip6_hdr *)(packet->data + 14);
ns = (struct nd_neighbor_solicit *)(packet->data + 14 + sizeof(*hdr));
opt = (struct nd_opt_hdr *)(packet->data + 14 + sizeof(*hdr) + sizeof(*ns));
/* First, snatch the source address from the neighbor solicitation packet */
memcpy(mymac.net.mac.address.x, packet->data + 6, 6);
/* Check if this is a valid neighbor solicitation request */
if(ns->nd_ns_hdr.icmp6_type != ND_NEIGHBOR_SOLICIT ||
opt->nd_opt_type != ND_OPT_SOURCE_LINKADDR)
{
if(debug_lvl > DEBUG_TRAFFIC)
{
syslog(LOG_WARNING, _("Cannot route packet: received unknown type neighbor solicitation request"));
}
return;
}
/* Create pseudo header */
memcpy(&pseudo.ip6_src, &hdr->ip6_src, 16);
memcpy(&pseudo.ip6_dst, &hdr->ip6_dst, 16);
pseudo.length = htonl(sizeof(*ns) + sizeof(*opt) + 6);
pseudo.junk[0] = pseudo.junk[1] = pseudo.junk[2] = 0;
pseudo.junk[3] = IPPROTO_ICMPV6;
/* Generate checksum */
checksum = inet_checksum((uint16_t *)&pseudo, sizeof(pseudo)/2, ~0);
checksum = inet_checksum((uint16_t *)ns, sizeof(*ns)/2 + 4, checksum);
if(checksum)
{
if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_WARNING, _("Cannot route packet: checksum error for neighbor solicitation request"));
return;
}
/* Check if the IPv6 address exists on the VPN */
subnet = lookup_subnet_ipv6((ipv6_t *)&ns->nd_ns_target);
if(!subnet)
{
if(debug_lvl >= DEBUG_TRAFFIC)
{
syslog(LOG_WARNING, _("Cannot route packet: neighbor solicitation request for unknown address %hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx"),
ntohs(((uint16_t *)&ns->nd_ns_target)[0]), ntohs(((uint16_t *)&ns->nd_ns_target)[1]), ntohs(((uint16_t *)&ns->nd_ns_target)[2]), ntohs(((uint16_t *)&ns->nd_ns_target)[3]),
ntohs(((uint16_t *)&ns->nd_ns_target)[4]), ntohs(((uint16_t *)&ns->nd_ns_target)[5]), ntohs(((uint16_t *)&ns->nd_ns_target)[6]), ntohs(((uint16_t *)&ns->nd_ns_target)[7]));
}
return;
}
/* Check if it is for our own subnet */
if(subnet->owner == myself)
return; /* silently ignore */
/* Create neighbor advertation reply */
memcpy(packet->data, packet->data + ETHER_ADDR_LEN, ETHER_ADDR_LEN); /* copy destination address */
packet->data[ETHER_ADDR_LEN*2 - 1] ^= 0xFF; /* mangle source address so it looks like it's not from us */
memcpy(&hdr->ip6_dst, &hdr->ip6_src, 16); /* swap destination and source protocol address */
memcpy(&hdr->ip6_src, &ns->nd_ns_target, 16); /* ... */
memcpy((char *)opt + sizeof(*opt), packet->data + ETHER_ADDR_LEN, 6); /* add fake source hard addr */
ns->nd_ns_hdr.icmp6_cksum = 0;
ns->nd_ns_hdr.icmp6_type = ND_NEIGHBOR_ADVERT;
ns->nd_ns_hdr.icmp6_dataun.icmp6_un_data8[0] = 0x40; /* Set solicited flag */
ns->nd_ns_hdr.icmp6_dataun.icmp6_un_data8[1] = ns->nd_ns_hdr.icmp6_dataun.icmp6_un_data8[2] = ns->nd_ns_hdr.icmp6_dataun.icmp6_un_data8[3] = 0;
opt->nd_opt_type = ND_OPT_TARGET_LINKADDR;
/* Create pseudo header */
memcpy(&pseudo.ip6_src, &hdr->ip6_src, 16);
memcpy(&pseudo.ip6_dst, &hdr->ip6_dst, 16);
pseudo.length = htonl(sizeof(*ns) + sizeof(*opt) + 6);
pseudo.junk[0] = pseudo.junk[1] = pseudo.junk[2] = 0;
pseudo.junk[3] = IPPROTO_ICMPV6;
/* Generate checksum */
checksum = inet_checksum((uint16_t *)&pseudo, sizeof(pseudo)/2, ~0);
checksum = inet_checksum((uint16_t *)ns, sizeof(*ns)/2 + 4, checksum);
ns->nd_ns_hdr.icmp6_cksum = htons(checksum);
write_packet(packet);
cp();
}
void route_arp(vpn_packet_t *packet)
{
struct ether_arp *arp;
subnet_t *subnet;
uint8_t ipbuf[4];
cp();
/* First, snatch the source address from the ARP packet */
memcpy(mymac.net.mac.address.x, packet->data + 6, 6);
/* This routine generates replies to ARP requests.
You don't need to set NOARP flag on the interface anymore (which is broken on FreeBSD).
Most of the code here is taken from choparp.c by Takamichi Tateoka (tree@mma.club.uec.ac.jp)
*/
arp = (struct ether_arp *)(packet->data + 14);
/* Check if this is a valid ARP request */
if(ntohs(arp->arp_hrd) != ARPHRD_ETHER ||
ntohs(arp->arp_pro) != ETHERTYPE_IP ||
arp->arp_hln != ETHER_ADDR_LEN ||
arp->arp_pln != 4 ||
ntohs(arp->arp_op) != ARPOP_REQUEST )
{
if(debug_lvl > DEBUG_TRAFFIC)
{
syslog(LOG_WARNING, _("Cannot route packet: received unknown type ARP request"));
}
return;
}
/* Check if the IPv4 address exists on the VPN */
subnet = lookup_subnet_ipv4((ipv4_t *)arp->arp_tpa);
if(!subnet)
{
if(debug_lvl >= DEBUG_TRAFFIC)
{
syslog(LOG_WARNING, _("Cannot route packet: ARP request for unknown address %d.%d.%d.%d"),
arp->arp_tpa[0], arp->arp_tpa[1], arp->arp_tpa[2], arp->arp_tpa[3]);
}
return;
}
/* Check if it is for our own subnet */
if(subnet->owner == myself)
return; /* silently ignore */
memcpy(packet->data, packet->data + ETHER_ADDR_LEN, ETHER_ADDR_LEN); /* copy destination address */
packet->data[ETHER_ADDR_LEN*2 - 1] ^= 0xFF; /* mangle source address so it looks like it's not from us */
memcpy(ipbuf, arp->arp_tpa, 4); /* save protocol addr */
memcpy(arp->arp_tpa, arp->arp_spa, 4); /* swap destination and source protocol address */
memcpy(arp->arp_spa, ipbuf, 4); /* ... */
memcpy(arp->arp_tha, arp->arp_sha, 10); /* set target hard/proto addr */
memcpy(arp->arp_sha, packet->data + ETHER_ADDR_LEN, ETHER_ADDR_LEN); /* add fake source hard addr */
arp->arp_op = htons(ARPOP_REPLY);
write_packet(packet);
cp();
}
void route_outgoing(vpn_packet_t *packet)
{
uint16_t type;
node_t *n = NULL;
cp();
/* FIXME: multicast? */
switch(routing_mode)
{
case RMODE_ROUTER:
type = ntohs(*((uint16_t *)(&packet->data[12])));
switch(type)
{
case 0x0800:
n = route_ipv4(packet);
break;
case 0x86DD:
if(packet->data[20] == IPPROTO_ICMPV6 && packet->data[54] == ND_NEIGHBOR_SOLICIT)
{
route_neighborsol(packet);
return;
if(!subnet) {
if(debug_lvl >= DEBUG_TRAFFIC) {
syslog(LOG_WARNING, _("Cannot route packet: unknown IPv4 destination address %d.%d.%d.%d"),
packet->data[30], packet->data[31], packet->data[32],
packet->data[33]);
}
n = route_ipv6(packet);
break;
case 0x0806:
route_arp(packet);
return;
default:
if(debug_lvl >= DEBUG_TRAFFIC)
{
syslog(LOG_WARNING, _("Cannot route packet: unknown type %hx"), type);
}
return;
}
if(n)
send_packet(n, packet);
break;
case RMODE_SWITCH:
n = route_mac(packet);
if(n)
send_packet(n, packet);
else
broadcast_packet(myself, packet);
break;
case RMODE_HUB:
broadcast_packet(myself, packet);
break;
}
return NULL;
}
return subnet->owner;
}
void route_incoming(node_t *source, vpn_packet_t *packet)
node_t *route_ipv6(vpn_packet_t * packet)
{
switch(routing_mode)
{
case RMODE_ROUTER:
{
node_t *n = NULL;
uint16_t type;
subnet_t *subnet;
type = ntohs(*((uint16_t *)(&packet->data[12])));
switch(type)
{
case 0x0800:
n = route_ipv4(packet);
break;
case 0x86DD:
n = route_ipv6(packet);
break;
default:
n = myself;
break;
}
cp();
if(n)
{
if(n == myself)
{
memcpy(packet->data, mymac.net.mac.address.x, 6);
write_packet(packet);
subnet = lookup_subnet_ipv6((ipv6_t *) & packet->data[38]);
if(!subnet) {
if(debug_lvl >= DEBUG_TRAFFIC) {
syslog(LOG_WARNING, _("Cannot route packet: unknown IPv6 destination address %hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx"),
ntohs(*(uint16_t *) & packet->data[38]),
ntohs(*(uint16_t *) & packet->data[40]),
ntohs(*(uint16_t *) & packet->data[42]),
ntohs(*(uint16_t *) & packet->data[44]),
ntohs(*(uint16_t *) & packet->data[46]),
ntohs(*(uint16_t *) & packet->data[48]),
ntohs(*(uint16_t *) & packet->data[50]),
ntohs(*(uint16_t *) & packet->data[52]));
}
else
send_packet(n, packet);
}
}
break;
case RMODE_SWITCH:
{
subnet_t *subnet;
subnet = lookup_subnet_mac((mac_t *)(&packet->data[0]));
return NULL;
}
if(subnet)
{
if(subnet->owner == myself)
write_packet(packet);
else
send_packet(subnet->owner, packet);
}
else
{
broadcast_packet(source, packet);
write_packet(packet);
}
}
break;
case RMODE_HUB:
broadcast_packet(source, packet); /* Spread it on */
write_packet(packet);
break;
}
return subnet->owner;
}
uint16_t inet_checksum(uint16_t * data, int len, uint16_t prevsum)
{
uint32_t checksum = prevsum ^ 0xFFFF;
while(len--)
checksum += ntohs(*data++);
while(checksum >> 16)
checksum = (checksum & 0xFFFF) + (checksum >> 16);
return checksum ^ 0xFFFF;
}
void route_neighborsol(vpn_packet_t * packet)
{
struct ip6_hdr *hdr;
struct nd_neighbor_solicit *ns;
struct nd_opt_hdr *opt;
subnet_t *subnet;
uint16_t checksum;
struct {
struct in6_addr ip6_src; /* source address */
struct in6_addr ip6_dst; /* destination address */
uint32_t length;
uint8_t junk[4];
} pseudo;
cp();
hdr = (struct ip6_hdr *) (packet->data + 14);
ns = (struct nd_neighbor_solicit *) (packet->data + 14 + sizeof(*hdr));
opt = (struct nd_opt_hdr *) (packet->data + 14 + sizeof(*hdr) + sizeof(*ns));
/* First, snatch the source address from the neighbor solicitation packet */
memcpy(mymac.net.mac.address.x, packet->data + 6, 6);
/* Check if this is a valid neighbor solicitation request */
if(ns->nd_ns_hdr.icmp6_type != ND_NEIGHBOR_SOLICIT ||
opt->nd_opt_type != ND_OPT_SOURCE_LINKADDR) {
if(debug_lvl > DEBUG_TRAFFIC) {
syslog(LOG_WARNING, _("Cannot route packet: received unknown type neighbor solicitation request"));
}
return;
}
/* Create pseudo header */
memcpy(&pseudo.ip6_src, &hdr->ip6_src, 16);
memcpy(&pseudo.ip6_dst, &hdr->ip6_dst, 16);
pseudo.length = htonl(sizeof(*ns) + sizeof(*opt) + 6);
pseudo.junk[0] = pseudo.junk[1] = pseudo.junk[2] = 0;
pseudo.junk[3] = IPPROTO_ICMPV6;
/* Generate checksum */
checksum = inet_checksum((uint16_t *) & pseudo, sizeof(pseudo) / 2, ~0);
checksum = inet_checksum((uint16_t *) ns, sizeof(*ns) / 2 + 4, checksum);
if(checksum) {
if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_WARNING, _("Cannot route packet: checksum error for neighbor solicitation request"));
return;
}
/* Check if the IPv6 address exists on the VPN */
subnet = lookup_subnet_ipv6((ipv6_t *) & ns->nd_ns_target);
if(!subnet) {
if(debug_lvl >= DEBUG_TRAFFIC) {
syslog(LOG_WARNING, _("Cannot route packet: neighbor solicitation request for unknown address %hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx"),
ntohs(((uint16_t *) & ns->nd_ns_target)[0]),
ntohs(((uint16_t *) & ns->nd_ns_target)[1]),
ntohs(((uint16_t *) & ns->nd_ns_target)[2]),
ntohs(((uint16_t *) & ns->nd_ns_target)[3]),
ntohs(((uint16_t *) & ns->nd_ns_target)[4]),
ntohs(((uint16_t *) & ns->nd_ns_target)[5]),
ntohs(((uint16_t *) & ns->nd_ns_target)[6]),
ntohs(((uint16_t *) & ns->nd_ns_target)[7]));
}
return;
}
/* Check if it is for our own subnet */
if(subnet->owner == myself)
return; /* silently ignore */
/* Create neighbor advertation reply */
memcpy(packet->data, packet->data + ETHER_ADDR_LEN, ETHER_ADDR_LEN); /* copy destination address */
packet->data[ETHER_ADDR_LEN * 2 - 1] ^= 0xFF; /* mangle source address so it looks like it's not from us */
memcpy(&hdr->ip6_dst, &hdr->ip6_src, 16); /* swap destination and source protocol address */
memcpy(&hdr->ip6_src, &ns->nd_ns_target, 16); /* ... */
memcpy((char *) opt + sizeof(*opt), packet->data + ETHER_ADDR_LEN, 6); /* add fake source hard addr */
ns->nd_ns_hdr.icmp6_cksum = 0;
ns->nd_ns_hdr.icmp6_type = ND_NEIGHBOR_ADVERT;
ns->nd_ns_hdr.icmp6_dataun.icmp6_un_data8[0] = 0x40; /* Set solicited flag */
ns->nd_ns_hdr.icmp6_dataun.icmp6_un_data8[1] =
ns->nd_ns_hdr.icmp6_dataun.icmp6_un_data8[2] =
ns->nd_ns_hdr.icmp6_dataun.icmp6_un_data8[3] = 0;
opt->nd_opt_type = ND_OPT_TARGET_LINKADDR;
/* Create pseudo header */
memcpy(&pseudo.ip6_src, &hdr->ip6_src, 16);
memcpy(&pseudo.ip6_dst, &hdr->ip6_dst, 16);
pseudo.length = htonl(sizeof(*ns) + sizeof(*opt) + 6);
pseudo.junk[0] = pseudo.junk[1] = pseudo.junk[2] = 0;
pseudo.junk[3] = IPPROTO_ICMPV6;
/* Generate checksum */
checksum = inet_checksum((uint16_t *) & pseudo, sizeof(pseudo) / 2, ~0);
checksum = inet_checksum((uint16_t *) ns, sizeof(*ns) / 2 + 4, checksum);
ns->nd_ns_hdr.icmp6_cksum = htons(checksum);
write_packet(packet);
}
void route_arp(vpn_packet_t * packet)
{
struct ether_arp *arp;
subnet_t *subnet;
uint8_t ipbuf[4];
cp();
/* First, snatch the source address from the ARP packet */
memcpy(mymac.net.mac.address.x, packet->data + 6, 6);
/* This routine generates replies to ARP requests.
You don't need to set NOARP flag on the interface anymore (which is broken on FreeBSD).
Most of the code here is taken from choparp.c by Takamichi Tateoka (tree@mma.club.uec.ac.jp)
*/
arp = (struct ether_arp *) (packet->data + 14);
/* Check if this is a valid ARP request */
if(ntohs(arp->arp_hrd) != ARPHRD_ETHER || ntohs(arp->arp_pro) != ETHERTYPE_IP ||
arp->arp_hln != ETHER_ADDR_LEN || arp->arp_pln != 4 || ntohs(arp->arp_op) != ARPOP_REQUEST) {
if(debug_lvl > DEBUG_TRAFFIC) {
syslog(LOG_WARNING, _("Cannot route packet: received unknown type ARP request"));
}
return;
}
/* Check if the IPv4 address exists on the VPN */
subnet = lookup_subnet_ipv4((ipv4_t *) arp->arp_tpa);
if(!subnet) {
if(debug_lvl >= DEBUG_TRAFFIC) {
syslog(LOG_WARNING, _("Cannot route packet: ARP request for unknown address %d.%d.%d.%d"),
arp->arp_tpa[0], arp->arp_tpa[1], arp->arp_tpa[2],
arp->arp_tpa[3]);
}
return;
}
/* Check if it is for our own subnet */
if(subnet->owner == myself)
return; /* silently ignore */
memcpy(packet->data, packet->data + ETHER_ADDR_LEN, ETHER_ADDR_LEN); /* copy destination address */
packet->data[ETHER_ADDR_LEN * 2 - 1] ^= 0xFF; /* mangle source address so it looks like it's not from us */
memcpy(ipbuf, arp->arp_tpa, 4); /* save protocol addr */
memcpy(arp->arp_tpa, arp->arp_spa, 4); /* swap destination and source protocol address */
memcpy(arp->arp_spa, ipbuf, 4); /* ... */
memcpy(arp->arp_tha, arp->arp_sha, 10); /* set target hard/proto addr */
memcpy(arp->arp_sha, packet->data + ETHER_ADDR_LEN, ETHER_ADDR_LEN); /* add fake source hard addr */
arp->arp_op = htons(ARPOP_REPLY);
write_packet(packet);
}
void route_outgoing(vpn_packet_t * packet)
{
uint16_t type;
node_t *n = NULL;
cp();
/* FIXME: multicast? */
switch (routing_mode) {
case RMODE_ROUTER:
type = ntohs(*((uint16_t *) (&packet->data[12])));
switch (type) {
case 0x0800:
n = route_ipv4(packet);
break;
case 0x86DD:
if(packet->data[20] == IPPROTO_ICMPV6 && packet->data[54] == ND_NEIGHBOR_SOLICIT) {
route_neighborsol(packet);
return;
}
n = route_ipv6(packet);
break;
case 0x0806:
route_arp(packet);
return;
default:
if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_WARNING, _("Cannot route packet: unknown type %hx"), type);
return;
}
if(n)
send_packet(n, packet);
break;
case RMODE_SWITCH:
n = route_mac(packet);
if(n)
send_packet(n, packet);
else
broadcast_packet(myself, packet);
break;
case RMODE_HUB:
broadcast_packet(myself, packet);
break;
}
}
void route_incoming(node_t * source, vpn_packet_t * packet)
{
switch (routing_mode) {
case RMODE_ROUTER:
{
node_t *n = NULL;
uint16_t type;
type = ntohs(*((uint16_t *) (&packet->data[12])));
switch (type) {
case 0x0800:
n = route_ipv4(packet);
break;
case 0x86DD:
n = route_ipv6(packet);
break;
default:
n = myself;
break;
}
if(n) {
if(n == myself) {
memcpy(packet->data, mymac.net.mac.address.x, 6);
write_packet(packet);
} else
send_packet(n, packet);
}
}
break;
case RMODE_SWITCH:
{
subnet_t *subnet;
subnet = lookup_subnet_mac((mac_t *) (&packet->data[0]));
if(subnet) {
if(subnet->owner == myself)
write_packet(packet);
else
send_packet(subnet->owner, packet);
} else {
broadcast_packet(source, packet);
write_packet(packet);
}
}
break;
case RMODE_HUB:
broadcast_packet(source, packet); /* Spread it on */
write_packet(packet);
break;
}
}

View file

@ -17,17 +17,16 @@
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.8 2002/06/21 10:11:33 guus Exp $
$Id: route.h,v 1.1.2.9 2002/09/09 21:25:07 guus Exp $
*/
#ifndef __TINC_ROUTE_H__
#define __TINC_ROUTE_H__
enum
{
RMODE_HUB = 0,
RMODE_SWITCH,
RMODE_ROUTER,
enum {
RMODE_HUB = 0,
RMODE_SWITCH,
RMODE_ROUTER,
};
extern int routing_mode;
@ -38,4 +37,4 @@ extern void age_mac(void);
extern void route_incoming(node_t *, vpn_packet_t *);
extern void route_outgoing(vpn_packet_t *);
#endif /* __TINC_ROUTE_H__ */
#endif /* __TINC_ROUTE_H__ */

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: device.c,v 1.1.2.8 2002/06/21 10:11:37 guus Exp $
$Id: device.c,v 1.1.2.9 2002/09/09 21:25:28 guus Exp $
*/
@ -61,136 +61,126 @@ subnet_t mymac;
int setup_device(void)
{
int ip_fd = -1, if_fd = -1;
int ppa;
char *ptr;
int ip_fd = -1, if_fd = -1;
int ppa;
char *ptr;
cp
if(!get_config_string(lookup_config(config_tree, "Device"), &device))
device = DEFAULT_DEVICE;
cp if(!get_config_string(lookup_config(config_tree, "Device"), &device))
device = DEFAULT_DEVICE;
cp
if((device_fd = open(device, O_RDWR | O_NONBLOCK)) < 0)
{
syslog(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno));
return -1;
}
cp
ppa = 0;
cp if((device_fd = open(device, O_RDWR | O_NONBLOCK)) < 0) {
syslog(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno));
return -1;
}
cp ppa = 0;
ptr = device;
while(*ptr && !isdigit((int)*ptr)) ptr++;
ppa = atoi(ptr);
ptr = device;
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: %s"), strerror(errno));
return -1;
}
if((ip_fd = open("/dev/ip", O_RDWR, 0)) < 0) {
syslog(LOG_ERR, _("Could not open /dev/ip: %s"), strerror(errno));
return -1;
}
/* Assign a new PPA and get its unit number. */
if( (ppa = ioctl(device_fd, TUNNEWPPA, ppa)) < 0){
syslog(LOG_ERR, _("Can't assign new interface: %s"), strerror(errno));
return -1;
}
/* Assign a new PPA and get its unit number. */
if((ppa = ioctl(device_fd, TUNNEWPPA, ppa)) < 0) {
syslog(LOG_ERR, _("Can't assign new interface: %s"), strerror(errno));
return -1;
}
if( (if_fd = open(device, O_RDWR, 0)) < 0){
syslog(LOG_ERR, _("Could not open %s twice: %s"), device, strerror(errno));
return -1;
}
if((if_fd = open(device, O_RDWR, 0)) < 0) {
syslog(LOG_ERR, _("Could not open %s twice: %s"), device,
strerror(errno));
return -1;
}
if(ioctl(if_fd, I_PUSH, "ip") < 0){
syslog(LOG_ERR, _("Can't push IP module: %s"), strerror(errno));
return -1;
}
if(ioctl(if_fd, I_PUSH, "ip") < 0) {
syslog(LOG_ERR, _("Can't push IP module: %s"), strerror(errno));
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: %s"), ppa, strerror(errno));
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: %s"), ppa, strerror(errno));
return -1;
}
if(ioctl(ip_fd, I_LINK, if_fd) < 0){
syslog(LOG_ERR, _("Can't link TUN device to IP: %s"), strerror(errno));
return -1;
}
if(ioctl(ip_fd, I_LINK, if_fd) < 0) {
syslog(LOG_ERR, _("Can't link TUN device to IP: %s"), strerror(errno));
return -1;
}
if(!get_config_string(lookup_config(config_tree, "Interface"), &interface))
asprintf(&interface, "tun%d", ppa);
if(!get_config_string(lookup_config(config_tree, "Interface"), &interface))
asprintf(&interface, "tun%d", ppa);
device_info = _("Solaris tun device");
device_info = _("Solaris tun device");
/* Set default MAC address for ethertap devices */
/* 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;
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;
syslog(LOG_INFO, _("%s is a %s"), device, device_info);
cp
return 0;
syslog(LOG_INFO, _("%s is a %s"), device, device_info);
cp return 0;
}
void close_device(void)
{
cp
close(device_fd);
cp close(device_fd);
}
int read_packet(vpn_packet_t *packet)
int read_packet(vpn_packet_t * packet)
{
int lenin;
cp
if((lenin = read(device_fd, packet->data + 14, MTU - 14)) <= 0)
{
syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, device, strerror(errno));
return -1;
}
int lenin;
cp if((lenin = read(device_fd, packet->data + 14, MTU - 14)) <= 0) {
syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info,
device, strerror(errno));
return -1;
}
memcpy(packet->data, mymac.net.mac.address.x, 6);
memcpy(packet->data + 6, mymac.net.mac.address.x, 6);
packet->data[12] = 0x08;
packet->data[13] = 0x00;
memcpy(packet->data, mymac.net.mac.address.x, 6);
memcpy(packet->data + 6, mymac.net.mac.address.x, 6);
packet->data[12] = 0x08;
packet->data[13] = 0x00;
packet->len = lenin + 14;
packet->len = lenin + 14;
device_total_in += packet->len;
device_total_in += packet->len;
if(debug_lvl >= DEBUG_TRAFFIC)
{
syslog(LOG_DEBUG, _("Read packet of %d bytes from %s"), packet->len, device_info);
}
if(debug_lvl >= DEBUG_TRAFFIC) {
syslog(LOG_DEBUG, _("Read packet of %d bytes from %s"), packet->len,
device_info);
}
return 0;
cp
}
return 0;
cp}
int write_packet(vpn_packet_t *packet)
int write_packet(vpn_packet_t * packet)
{
cp
if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_DEBUG, _("Writing packet of %d bytes to %s"),
packet->len, device_info);
cp if(debug_lvl >= DEBUG_TRAFFIC)
syslog(LOG_DEBUG, _("Writing packet of %d bytes to %s"),
packet->len, device_info);
if(write(device_fd, packet->data + 14, packet->len - 14) < 0)
{
syslog(LOG_ERR, _("Can't write to %s %s: %s"), device_info, packet->len, strerror(errno));
return -1;
}
if(write(device_fd, packet->data + 14, packet->len - 14) < 0) {
syslog(LOG_ERR, _("Can't write to %s %s: %s"), device_info, packet->len,
strerror(errno));
return -1;
}
device_total_out += packet->len;
cp
return 0;
device_total_out += packet->len;
cp return 0;
}
void dump_device_stats(void)
{
cp
syslog(LOG_DEBUG, _("Statistics for %s %s:"), device_info, device);
syslog(LOG_DEBUG, _(" total bytes in: %10d"), device_total_in);
syslog(LOG_DEBUG, _(" total bytes out: %10d"), device_total_out);
cp
}
cp syslog(LOG_DEBUG, _("Statistics for %s %s:"), device_info, device);
syslog(LOG_DEBUG, _(" total bytes in: %10d"), device_total_in);
syslog(LOG_DEBUG, _(" total bytes out: %10d"), device_total_out);
cp}

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: subnet.c,v 1.1.2.40 2002/09/09 19:40:11 guus Exp $
$Id: subnet.c,v 1.1.2.41 2002/09/09 21:25:10 guus Exp $
*/
#include "config.h"
@ -48,366 +48,379 @@ avl_tree_t *subnet_tree;
/* Subnet comparison */
int subnet_compare_mac(subnet_t *a, subnet_t *b)
int subnet_compare_mac(subnet_t * a, subnet_t * b)
{
int result;
cp();
result = memcmp(&a->net.mac.address, &b->net.mac.address, sizeof(mac_t));
if(result || !a->owner || !b->owner)
return result;
int result;
return strcmp(a->owner->name, b->owner->name);
result = memcmp(&a->net.mac.address, &b->net.mac.address, sizeof(mac_t));
if(result || !a->owner || !b->owner)
return result;
return strcmp(a->owner->name, b->owner->name);
}
int subnet_compare_ipv4(subnet_t *a, subnet_t *b)
int subnet_compare_ipv4(subnet_t * a, subnet_t * b)
{
int result;
cp();
result = memcmp(&a->net.ipv4.address, &b->net.ipv4.address, sizeof(ipv4_t));
if(result)
return result;
int result;
result = a->net.ipv4.prefixlength - b->net.ipv4.prefixlength;
if(result || !a->owner || !b->owner)
return result;
result = memcmp(&a->net.ipv4.address, &b->net.ipv4.address, sizeof(ipv4_t));
return strcmp(a->owner->name, b->owner->name);
if(result)
return result;
result = a->net.ipv4.prefixlength - b->net.ipv4.prefixlength;
if(result || !a->owner || !b->owner)
return result;
return strcmp(a->owner->name, b->owner->name);
}
int subnet_compare_ipv6(subnet_t *a, subnet_t *b)
int subnet_compare_ipv6(subnet_t * a, subnet_t * b)
{
int result;
cp();
result = memcmp(&a->net.ipv6.address, &b->net.ipv6.address, sizeof(ipv6_t));
if(result)
return result;
int result;
result = a->net.ipv6.prefixlength - b->net.ipv6.prefixlength;
if(result || !a->owner || !b->owner)
return result;
result = memcmp(&a->net.ipv6.address, &b->net.ipv6.address, sizeof(ipv6_t));
return strcmp(a->owner->name, b->owner->name);
if(result)
return result;
result = a->net.ipv6.prefixlength - b->net.ipv6.prefixlength;
if(result || !a->owner || !b->owner)
return result;
return strcmp(a->owner->name, b->owner->name);
}
int subnet_compare(subnet_t *a, subnet_t *b)
int subnet_compare(subnet_t * a, subnet_t * b)
{
int result;
cp();
result = a->type - b->type;
if(result)
return result;
switch(a->type)
{
case SUBNET_MAC:
return subnet_compare_mac(a, b);
case SUBNET_IPV4:
return subnet_compare_ipv4(a, b);
case SUBNET_IPV6:
return subnet_compare_ipv6(a, b);
default:
syslog(LOG_ERR, _("subnet_compare() was called with unknown subnet type %d, exitting!"), a->type);
cp_trace();
exit(0);
}
int result;
return 0;
result = a->type - b->type;
if(result)
return result;
switch (a->type) {
case SUBNET_MAC:
return subnet_compare_mac(a, b);
case SUBNET_IPV4:
return subnet_compare_ipv4(a, b);
case SUBNET_IPV6:
return subnet_compare_ipv6(a, b);
default:
syslog(LOG_ERR,
_
("subnet_compare() was called with unknown subnet type %d, exitting!"),
a->type);
cp_trace();
exit(0);
}
return 0;
}
/* Initialising trees */
void init_subnets(void)
{
cp();
subnet_tree = avl_alloc_tree((avl_compare_t)subnet_compare, (avl_action_t)free_subnet);
cp();
cp();
subnet_tree = avl_alloc_tree((avl_compare_t) subnet_compare, (avl_action_t) free_subnet);
}
void exit_subnets(void)
{
cp();
avl_delete_tree(subnet_tree);
cp();
cp();
avl_delete_tree(subnet_tree);
}
avl_tree_t *new_subnet_tree(void)
{
cp();
return avl_alloc_tree((avl_compare_t)subnet_compare, NULL);
cp();
cp();
return avl_alloc_tree((avl_compare_t) subnet_compare, NULL);
}
void free_subnet_tree(avl_tree_t *subnet_tree)
void free_subnet_tree(avl_tree_t * subnet_tree)
{
cp();
avl_delete_tree(subnet_tree);
cp();
cp();
avl_delete_tree(subnet_tree);
}
/* Allocating and freeing space for subnets */
subnet_t *new_subnet(void)
{
cp();
return (subnet_t *)xmalloc_and_zero(sizeof(subnet_t));
cp();
return (subnet_t *) xmalloc_and_zero(sizeof(subnet_t));
}
void free_subnet(subnet_t *subnet)
void free_subnet(subnet_t * subnet)
{
cp();
free(subnet);
cp();
free(subnet);
}
/* Adding and removing subnets */
void subnet_add(node_t *n, subnet_t *subnet)
void subnet_add(node_t * n, subnet_t * subnet)
{
cp();
subnet->owner = n;
cp();
avl_insert(subnet_tree, subnet);
cp();
avl_insert(n->subnet_tree, subnet);
cp();
subnet->owner = n;
avl_insert(subnet_tree, subnet);
avl_insert(n->subnet_tree, subnet);
}
void subnet_del(node_t *n, subnet_t *subnet)
void subnet_del(node_t * n, subnet_t * subnet)
{
cp();
avl_delete(n->subnet_tree, subnet);
cp();
avl_delete(subnet_tree, subnet);
cp();
cp();
avl_delete(n->subnet_tree, subnet);
avl_delete(subnet_tree, subnet);
}
/* Ascii representation of subnets */
subnet_t *str2net(char *subnetstr)
{
int i, l;
subnet_t *subnet;
uint16_t x[8];
cp();
subnet = new_subnet();
cp();
if(sscanf(subnetstr, "%hu.%hu.%hu.%hu/%d",
&x[0], &x[1], &x[2], &x[3],
&l) == 5)
{
subnet->type = SUBNET_IPV4;
subnet->net.ipv4.prefixlength = l;
for(i = 0; i < 4; i++)
subnet->net.ipv4.address.x[i] = x[i];
return subnet;
}
if(sscanf(subnetstr, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx/%d",
&x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7],
&l) == 9)
{
subnet->type = SUBNET_IPV6;
subnet->net.ipv6.prefixlength = l;
for(i = 0; i < 8; i++)
subnet->net.ipv6.address.x[i] = htons(x[i]);
return subnet;
}
int i, l;
subnet_t *subnet;
uint16_t x[8];
if(sscanf(subnetstr, "%hu.%hu.%hu.%hu",
&x[0], &x[1], &x[2], &x[3]) == 4)
{
subnet->type = SUBNET_IPV4;
subnet->net.ipv4.prefixlength = 32;
for(i = 0; i < 4; i++)
subnet->net.ipv4.address.x[i] = x[i];
return subnet;
}
if(sscanf(subnetstr, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx",
&x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7]) == 8)
{
subnet->type = SUBNET_IPV6;
subnet->net.ipv6.prefixlength = 128;
for(i = 0; i < 8; i++)
subnet->net.ipv6.address.x[i] = htons(x[i]);
return subnet;
}
cp();
if(sscanf(subnetstr, "%hx:%hx:%hx:%hx:%hx:%hx",
&x[0], &x[1], &x[2], &x[3], &x[4], &x[5]) == 6)
{
subnet->type = SUBNET_MAC;
for(i = 0; i < 6; i++)
subnet->net.mac.address.x[i] = x[i];
return subnet;
}
subnet = new_subnet();
free(subnet);
return NULL;
if(sscanf(subnetstr, "%hu.%hu.%hu.%hu/%d",
&x[0], &x[1], &x[2], &x[3], &l) == 5) {
subnet->type = SUBNET_IPV4;
subnet->net.ipv4.prefixlength = l;
for(i = 0; i < 4; i++)
subnet->net.ipv4.address.x[i] = x[i];
return subnet;
}
if(sscanf(subnetstr, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx/%d",
&x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7],
&l) == 9) {
subnet->type = SUBNET_IPV6;
subnet->net.ipv6.prefixlength = l;
for(i = 0; i < 8; i++)
subnet->net.ipv6.address.x[i] = htons(x[i]);
return subnet;
}
if(sscanf(subnetstr, "%hu.%hu.%hu.%hu", &x[0], &x[1], &x[2], &x[3]) == 4) {
subnet->type = SUBNET_IPV4;
subnet->net.ipv4.prefixlength = 32;
for(i = 0; i < 4; i++)
subnet->net.ipv4.address.x[i] = x[i];
return subnet;
}
if(sscanf(subnetstr, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx",
&x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7]) == 8) {
subnet->type = SUBNET_IPV6;
subnet->net.ipv6.prefixlength = 128;
for(i = 0; i < 8; i++)
subnet->net.ipv6.address.x[i] = htons(x[i]);
return subnet;
}
if(sscanf(subnetstr, "%hx:%hx:%hx:%hx:%hx:%hx",
&x[0], &x[1], &x[2], &x[3], &x[4], &x[5]) == 6) {
subnet->type = SUBNET_MAC;
for(i = 0; i < 6; i++)
subnet->net.mac.address.x[i] = x[i];
return subnet;
}
free(subnet);
return NULL;
}
char *net2str(subnet_t *subnet)
char *net2str(subnet_t * subnet)
{
char *netstr;
cp();
switch(subnet->type)
{
case SUBNET_MAC:
asprintf(&netstr, "%hx:%hx:%hx:%hx:%hx:%hx",
subnet->net.mac.address.x[0],
subnet->net.mac.address.x[1],
subnet->net.mac.address.x[2],
subnet->net.mac.address.x[3],
subnet->net.mac.address.x[4],
subnet->net.mac.address.x[5]);
break;
case SUBNET_IPV4:
asprintf(&netstr, "%hu.%hu.%hu.%hu/%d",
subnet->net.ipv4.address.x[0],
subnet->net.ipv4.address.x[1],
subnet->net.ipv4.address.x[2],
subnet->net.ipv4.address.x[3],
subnet->net.ipv4.prefixlength);
break;
case SUBNET_IPV6:
asprintf(&netstr, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx/%d",
ntohs(subnet->net.ipv6.address.x[0]),
ntohs(subnet->net.ipv6.address.x[1]),
ntohs(subnet->net.ipv6.address.x[2]),
ntohs(subnet->net.ipv6.address.x[3]),
ntohs(subnet->net.ipv6.address.x[4]),
ntohs(subnet->net.ipv6.address.x[5]),
ntohs(subnet->net.ipv6.address.x[6]),
ntohs(subnet->net.ipv6.address.x[7]),
subnet->net.ipv6.prefixlength);
break;
default:
syslog(LOG_ERR, _("net2str() was called with unknown subnet type %d, exiting!"), subnet->type);
cp_trace();
exit(0);
}
cp();
return netstr;
char *netstr;
cp();
switch (subnet->type) {
case SUBNET_MAC:
asprintf(&netstr, "%hx:%hx:%hx:%hx:%hx:%hx",
subnet->net.mac.address.x[0],
subnet->net.mac.address.x[1],
subnet->net.mac.address.x[2],
subnet->net.mac.address.x[3],
subnet->net.mac.address.x[4], subnet->net.mac.address.x[5]);
break;
case SUBNET_IPV4:
asprintf(&netstr, "%hu.%hu.%hu.%hu/%d",
subnet->net.ipv4.address.x[0],
subnet->net.ipv4.address.x[1],
subnet->net.ipv4.address.x[2],
subnet->net.ipv4.address.x[3], subnet->net.ipv4.prefixlength);
break;
case SUBNET_IPV6:
asprintf(&netstr, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx/%d",
ntohs(subnet->net.ipv6.address.x[0]),
ntohs(subnet->net.ipv6.address.x[1]),
ntohs(subnet->net.ipv6.address.x[2]),
ntohs(subnet->net.ipv6.address.x[3]),
ntohs(subnet->net.ipv6.address.x[4]),
ntohs(subnet->net.ipv6.address.x[5]),
ntohs(subnet->net.ipv6.address.x[6]),
ntohs(subnet->net.ipv6.address.x[7]),
subnet->net.ipv6.prefixlength);
break;
default:
syslog(LOG_ERR,
_("net2str() was called with unknown subnet type %d, exiting!"),
subnet->type);
cp_trace();
exit(0);
}
return netstr;
}
/* Subnet lookup routines */
subnet_t *lookup_subnet(node_t *owner, subnet_t *subnet)
subnet_t *lookup_subnet(node_t * owner, subnet_t * subnet)
{
cp();
return avl_search(owner->subnet_tree, subnet);
cp();
return avl_search(owner->subnet_tree, subnet);
}
subnet_t *lookup_subnet_mac(mac_t *address)
subnet_t *lookup_subnet_mac(mac_t * address)
{
subnet_t subnet, *p;
cp();
subnet.type = SUBNET_MAC;
memcpy(&subnet.net.mac.address, address, sizeof(mac_t));
subnet.owner = NULL;
subnet_t subnet, *p;
p = (subnet_t *)avl_search(subnet_tree, &subnet);
cp();
return p;
cp();
subnet.type = SUBNET_MAC;
memcpy(&subnet.net.mac.address, address, sizeof(mac_t));
subnet.owner = NULL;
p = (subnet_t *) avl_search(subnet_tree, &subnet);
return p;
}
subnet_t *lookup_subnet_ipv4(ipv4_t *address)
subnet_t *lookup_subnet_ipv4(ipv4_t * address)
{
subnet_t subnet, *p;
cp();
subnet.type = SUBNET_IPV4;
memcpy(&subnet.net.ipv4.address, address, sizeof(ipv4_t));
subnet.net.ipv4.prefixlength = 32;
subnet.owner = NULL;
subnet_t subnet, *p;
do
{
/* Go find subnet */
p = (subnet_t *)avl_search_closest_smaller(subnet_tree, &subnet);
cp();
/* Check if the found subnet REALLY matches */
cp();
if(p)
{
if(p->type != SUBNET_IPV4)
{
p = NULL;
break;
}
subnet.type = SUBNET_IPV4;
memcpy(&subnet.net.ipv4.address, address, sizeof(ipv4_t));
subnet.net.ipv4.prefixlength = 32;
subnet.owner = NULL;
if (!maskcmp(address, &p->net.ipv4.address, p->net.ipv4.prefixlength, sizeof(ipv4_t)))
break;
else
{
/* Otherwise, see if there is a bigger enclosing subnet */
do {
/* Go find subnet */
subnet.net.ipv4.prefixlength = p->net.ipv4.prefixlength - 1;
maskcpy(&subnet.net.ipv4.address, &p->net.ipv4.address, subnet.net.ipv4.prefixlength, sizeof(ipv4_t));
}
}
} while (p);
cp();
return p;
p = (subnet_t *) avl_search_closest_smaller(subnet_tree, &subnet);
/* Check if the found subnet REALLY matches */
if(p) {
if(p->type != SUBNET_IPV4) {
p = NULL;
break;
}
if(!maskcmp(address, &p->net.ipv4.address, p->net.ipv4.prefixlength, sizeof(ipv4_t)))
break;
else {
/* Otherwise, see if there is a bigger enclosing subnet */
subnet.net.ipv4.prefixlength = p->net.ipv4.prefixlength - 1;
maskcpy(&subnet.net.ipv4.address, &p->net.ipv4.address, subnet.net.ipv4.prefixlength, sizeof(ipv4_t));
}
}
} while(p);
return p;
}
subnet_t *lookup_subnet_ipv6(ipv6_t *address)
subnet_t *lookup_subnet_ipv6(ipv6_t * address)
{
subnet_t subnet, *p;
cp();
subnet.type = SUBNET_IPV6;
memcpy(&subnet.net.ipv6.address, address, sizeof(ipv6_t));
subnet.net.ipv6.prefixlength = 128;
subnet.owner = NULL;
do
{
/* Go find subnet */
p = (subnet_t *)avl_search_closest_smaller(subnet_tree, &subnet);
subnet_t subnet, *p;
/* Check if the found subnet REALLY matches */
cp();
cp();
if(p)
{
if(p->type != SUBNET_IPV6)
return NULL;
subnet.type = SUBNET_IPV6;
memcpy(&subnet.net.ipv6.address, address, sizeof(ipv6_t));
subnet.net.ipv6.prefixlength = 128;
subnet.owner = NULL;
if (!maskcmp(address, &p->net.ipv6.address, p->net.ipv6.prefixlength, sizeof(ipv6_t)))
break;
else
{
/* Otherwise, see if there is a bigger enclosing subnet */
do {
/* Go find subnet */
subnet.net.ipv6.prefixlength = p->net.ipv6.prefixlength - 1;
maskcpy(&subnet.net.ipv6.address, &p->net.ipv6.address, subnet.net.ipv6.prefixlength, sizeof(ipv6_t));
}
}
} while (p);
cp();
return p;
p = (subnet_t *) avl_search_closest_smaller(subnet_tree, &subnet);
/* Check if the found subnet REALLY matches */
if(p) {
if(p->type != SUBNET_IPV6)
return NULL;
if(!maskcmp(address, &p->net.ipv6.address, p->net.ipv6.prefixlength, sizeof(ipv6_t)))
break;
else {
/* Otherwise, see if there is a bigger enclosing subnet */
subnet.net.ipv6.prefixlength = p->net.ipv6.prefixlength - 1;
maskcpy(&subnet.net.ipv6.address, &p->net.ipv6.address, subnet.net.ipv6.prefixlength, sizeof(ipv6_t));
}
}
} while(p);
return p;
}
void dump_subnets(void)
{
char *netstr;
subnet_t *subnet;
avl_node_t *node;
cp();
syslog(LOG_DEBUG, _("Subnet list:"));
for(node = subnet_tree->head; node; node = node->next)
{
subnet = (subnet_t *)node->data;
netstr = net2str(subnet);
syslog(LOG_DEBUG, _(" %s owner %s"), netstr, subnet->owner->name);
free(netstr);
}
syslog(LOG_DEBUG, _("End of subnet list."));
cp();
char *netstr;
subnet_t *subnet;
avl_node_t *node;
cp();
syslog(LOG_DEBUG, _("Subnet list:"));
for(node = subnet_tree->head; node; node = node->next) {
subnet = (subnet_t *) node->data;
netstr = net2str(subnet);
syslog(LOG_DEBUG, _(" %s owner %s"), netstr, subnet->owner->name);
free(netstr);
}
syslog(LOG_DEBUG, _("End of subnet list."));
}

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: subnet.h,v 1.1.2.19 2002/06/21 10:11:34 guus Exp $
$Id: subnet.h,v 1.1.2.20 2002/09/09 21:25:16 guus Exp $
*/
#ifndef __TINC_SUBNET_H__
@ -25,48 +25,43 @@
#include "net.h"
enum
{
SUBNET_MAC = 0,
SUBNET_IPV4,
SUBNET_IPV6,
SUBNET_TYPES /* Guardian */
enum {
SUBNET_MAC = 0,
SUBNET_IPV4,
SUBNET_IPV6,
SUBNET_TYPES /* Guardian */
};
typedef struct subnet_mac_t
{
mac_t address;
time_t lastseen;
typedef struct subnet_mac_t {
mac_t address;
time_t lastseen;
} subnet_mac_t;
typedef struct subnet_ipv4_t
{
ipv4_t address;
int prefixlength;
typedef struct subnet_ipv4_t {
ipv4_t address;
int prefixlength;
} subnet_ipv4_t;
typedef struct subnet_ipv6_t
{
ipv6_t address;
int prefixlength;
typedef struct subnet_ipv6_t {
ipv6_t address;
int prefixlength;
} subnet_ipv6_t;
#include "node.h"
typedef struct subnet_t {
struct node_t *owner; /* the owner of this subnet */
struct node_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?) */
int type; /* subnet type (IPv4? IPv6? MAC? something even weirder?) */
/* And now for the actual subnet: */
/* And now for the actual subnet: */
union net
{
subnet_mac_t mac;
subnet_ipv4_t ipv4;
subnet_ipv6_t ipv6;
} net;
union net {
subnet_mac_t mac;
subnet_ipv4_t ipv4;
subnet_ipv6_t ipv6;
} net;
} subnet_t;
extern subnet_t *new_subnet(void);
@ -85,4 +80,4 @@ extern subnet_t *lookup_subnet_ipv4(ipv4_t *);
extern subnet_t *lookup_subnet_ipv6(ipv6_t *);
extern void dump_subnets(void);
#endif /* __TINC_SUBNET_H__ */
#endif /* __TINC_SUBNET_H__ */

View file

@ -17,7 +17,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: tincd.c,v 1.10.4.62 2002/09/09 19:40:12 guus Exp $
$Id: tincd.c,v 1.10.4.63 2002/09/09 21:25:16 guus Exp $
*/
#include "config.h"
@ -77,167 +77,178 @@ int bypass_security = 0;
/* If nonzero, disable swapping for this process. */
int do_mlock = 0;
char *identname; /* program name for syslog */
char *pidfilename; /* pid file location */
char **g_argv; /* a copy of the cmdline arguments */
char **environment; /* A pointer to the environment on
startup */
char *identname; /* program name for syslog */
char *pidfilename; /* pid file location */
char **g_argv; /* a copy of the cmdline arguments */
char **environment; /* A pointer to the environment on
startup */
static struct option const long_options[] =
{
{ "config", required_argument, NULL, 'c' },
{ "kill", optional_argument, NULL, 'k' },
{ "net", required_argument, NULL, 'n' },
{ "help", no_argument, &show_help, 1 },
{ "version", no_argument, &show_version, 1 },
{ "no-detach", no_argument, &do_detach, 0 },
{ "generate-keys", optional_argument, NULL, 'K'},
{ "debug", optional_argument, NULL, 'd'},
{ "bypass-security", no_argument, &bypass_security, 1 },
{ "mlock", no_argument, &do_mlock, 1},
{ NULL, 0, NULL, 0 }
static struct option const long_options[] = {
{"config", required_argument, NULL, 'c'},
{"kill", optional_argument, NULL, 'k'},
{"net", required_argument, NULL, 'n'},
{"help", no_argument, &show_help, 1},
{"version", no_argument, &show_version, 1},
{"no-detach", no_argument, &do_detach, 0},
{"generate-keys", optional_argument, NULL, 'K'},
{"debug", optional_argument, NULL, 'd'},
{"bypass-security", no_argument, &bypass_security, 1},
{"mlock", no_argument, &do_mlock, 1},
{NULL, 0, NULL, 0}
};
static void
usage(int status)
static void usage(int status)
{
if(status != 0)
fprintf(stderr, _("Try `%s --help\' for more information.\n"), program_name);
else
{
printf(_("Usage: %s [option]...\n\n"), program_name);
printf(_(" -c, --config=DIR Read configuration options from DIR.\n"
" -D, --no-detach Don't fork and detach.\n"
" -d, --debug[=LEVEL] Increase debug level or set it to LEVEL.\n"
" -k, --kill[=SIGNAL] Attempt to kill a running tincd and exit.\n"
" -n, --net=NETNAME Connect to net NETNAME.\n"
" -K, --generate-keys[=BITS] Generate public/private RSA keypair.\n"
" -L, --mlock Lock tinc into main memory.\n"
" --help Display this help and exit.\n"
" --version Output version information and exit.\n\n"));
printf(_("Report bugs to tinc@nl.linux.org.\n"));
}
exit(status);
if(status != 0)
fprintf(stderr, _("Try `%s --help\' for more information.\n"),
program_name);
else {
printf(_("Usage: %s [option]...\n\n"), program_name);
printf(_
(" -c, --config=DIR Read configuration options from DIR.\n"
" -D, --no-detach Don't fork and detach.\n"
" -d, --debug[=LEVEL] Increase debug level or set it to LEVEL.\n"
" -k, --kill[=SIGNAL] Attempt to kill a running tincd and exit.\n"
" -n, --net=NETNAME Connect to net NETNAME.\n"
" -K, --generate-keys[=BITS] Generate public/private RSA keypair.\n"
" -L, --mlock Lock tinc into main memory.\n"
" --help Display this help and exit.\n"
" --version Output version information and exit.\n\n"));
printf(_("Report bugs to tinc@nl.linux.org.\n"));
}
exit(status);
}
void
parse_options(int argc, char **argv, char **envp)
void parse_options(int argc, char **argv, char **envp)
{
int r;
int option_index = 0;
int r;
int option_index = 0;
while((r = getopt_long(argc, argv, "c:DLd::k::n:K::", long_options, &option_index)) != EOF)
{
switch(r)
{
case 0: /* long option */
break;
case 'c': /* config file */
confbase = xmalloc(strlen(optarg)+1);
strcpy(confbase, optarg);
break;
case 'D': /* no detach */
do_detach = 0;
break;
case 'L': /* no detach */
do_mlock = 1;
break;
case 'd': /* inc debug level */
if(optarg)
debug_lvl = atoi(optarg);
else
debug_lvl++;
break;
case 'k': /* kill old tincds */
if(optarg)
{
if(!strcasecmp(optarg, "HUP"))
kill_tincd = SIGHUP;
else if(!strcasecmp(optarg, "TERM"))
kill_tincd = SIGTERM;
else if(!strcasecmp(optarg, "KILL"))
kill_tincd = SIGKILL;
else if(!strcasecmp(optarg, "USR1"))
kill_tincd = SIGUSR1;
else if(!strcasecmp(optarg, "USR2"))
kill_tincd = SIGUSR2;
else if(!strcasecmp(optarg, "WINCH"))
kill_tincd = SIGWINCH;
else if(!strcasecmp(optarg, "INT"))
kill_tincd = SIGINT;
else if(!strcasecmp(optarg, "ALRM"))
kill_tincd = SIGALRM;
else
{
kill_tincd = atoi(optarg);
if(!kill_tincd)
{
fprintf(stderr, _("Invalid argument `%s'; SIGNAL must be a number or one of HUP, TERM, KILL, USR1, USR2, WINCH, INT or ALRM.\n"), optarg);
usage(1);
}
}
}
else
kill_tincd = SIGTERM;
break;
case 'n': /* net name given */
netname = xmalloc(strlen(optarg)+1);
strcpy(netname, optarg);
break;
case 'K': /* generate public/private keypair */
if(optarg)
{
generate_keys = atoi(optarg);
if(generate_keys < 512)
{
fprintf(stderr, _("Invalid argument `%s'; BITS must be a number equal to or greater than 512.\n"),
optarg);
usage(1);
}
generate_keys &= ~7; /* Round it to bytes */
}
else
generate_keys = 1024;
break;
case '?':
usage(1);
default:
break;
}
}
while((r = getopt_long(argc, argv, "c:DLd::k::n:K::", long_options, &option_index)) != EOF) {
switch (r) {
case 0: /* long option */
break;
case 'c': /* config file */
confbase = xmalloc(strlen(optarg) + 1);
strcpy(confbase, optarg);
break;
case 'D': /* no detach */
do_detach = 0;
break;
case 'L': /* no detach */
do_mlock = 1;
break;
case 'd': /* inc debug level */
if(optarg)
debug_lvl = atoi(optarg);
else
debug_lvl++;
break;
case 'k': /* kill old tincds */
if(optarg) {
if(!strcasecmp(optarg, "HUP"))
kill_tincd = SIGHUP;
else if(!strcasecmp(optarg, "TERM"))
kill_tincd = SIGTERM;
else if(!strcasecmp(optarg, "KILL"))
kill_tincd = SIGKILL;
else if(!strcasecmp(optarg, "USR1"))
kill_tincd = SIGUSR1;
else if(!strcasecmp(optarg, "USR2"))
kill_tincd = SIGUSR2;
else if(!strcasecmp(optarg, "WINCH"))
kill_tincd = SIGWINCH;
else if(!strcasecmp(optarg, "INT"))
kill_tincd = SIGINT;
else if(!strcasecmp(optarg, "ALRM"))
kill_tincd = SIGALRM;
else {
kill_tincd = atoi(optarg);
if(!kill_tincd) {
fprintf(stderr,
_
("Invalid argument `%s'; SIGNAL must be a number or one of HUP, TERM, KILL, USR1, USR2, WINCH, INT or ALRM.\n"),
optarg);
usage(1);
}
}
} else
kill_tincd = SIGTERM;
break;
case 'n': /* net name given */
netname = xmalloc(strlen(optarg) + 1);
strcpy(netname, optarg);
break;
case 'K': /* generate public/private keypair */
if(optarg) {
generate_keys = atoi(optarg);
if(generate_keys < 512) {
fprintf(stderr,
_
("Invalid argument `%s'; BITS must be a number equal to or greater than 512.\n"),
optarg);
usage(1);
}
generate_keys &= ~7; /* Round it to bytes */
} else
generate_keys = 1024;
break;
case '?':
usage(1);
default:
break;
}
}
}
/* This function prettyprints the key generation process */
void indicator(int a, int b, void *p)
{
switch(a)
{
case 0:
fprintf(stderr, ".");
break;
case 1:
fprintf(stderr, "+");
break;
case 2:
fprintf(stderr, "-");
break;
case 3:
switch(b)
{
case 0:
fprintf(stderr, " p\n");
break;
case 1:
fprintf(stderr, " q\n");
break;
default:
fprintf(stderr, "?");
}
break;
default:
fprintf(stderr, "?");
}
switch (a) {
case 0:
fprintf(stderr, ".");
break;
case 1:
fprintf(stderr, "+");
break;
case 2:
fprintf(stderr, "-");
break;
case 3:
switch (b) {
case 0:
fprintf(stderr, " p\n");
break;
case 1:
fprintf(stderr, " q\n");
break;
default:
fprintf(stderr, "?");
}
break;
default:
fprintf(stderr, "?");
}
}
/*
@ -246,55 +257,53 @@ void indicator(int a, int b, void *p)
*/
int keygen(int bits)
{
RSA *rsa_key;
FILE *f;
char *name = NULL;
char *filename;
RSA *rsa_key;
FILE *f;
char *name = NULL;
char *filename;
fprintf(stderr, _("Generating %d bits keys:\n"), bits);
rsa_key = RSA_generate_key(bits, 0xFFFF, indicator, NULL);
fprintf(stderr, _("Generating %d bits keys:\n"), bits);
rsa_key = RSA_generate_key(bits, 0xFFFF, indicator, NULL);
if(!rsa_key)
{
fprintf(stderr, _("Error during key generation!\n"));
return -1;
}
else
fprintf(stderr, _("Done.\n"));
if(!rsa_key) {
fprintf(stderr, _("Error during key generation!\n"));
return -1;
} else
fprintf(stderr, _("Done.\n"));
get_config_string(lookup_config(config_tree, "Name"), &name);
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(name)
asprintf(&filename, "%s/hosts/%s", confbase, name);
else
asprintf(&filename, "%s/rsa_key.pub", confbase);
f = ask_and_safe_open(filename, _("public RSA key"), "a");
if(!f)
return -1;
f = ask_and_safe_open(filename, _("public RSA key"), "a");
if(ftell(f))
fprintf(stderr, _("Appending key to existing contents.\nMake sure only one key is stored in the file.\n"));
if(!f)
return -1;
PEM_write_RSAPublicKey(f, rsa_key);
fclose(f);
free(filename);
if(ftell(f))
fprintf(stderr, _("Appending key to existing contents.\nMake sure only one key is stored in the file.\n"));
asprintf(&filename, "%s/rsa_key.priv", confbase);
f = ask_and_safe_open(filename, _("private RSA key"), "a");
if(!f)
return -1;
PEM_write_RSAPublicKey(f, rsa_key);
fclose(f);
free(filename);
if(ftell(f))
fprintf(stderr, _("Appending key to existing contents.\nMake sure only one key is stored in the file.\n"));
asprintf(&filename, "%s/rsa_key.priv", confbase);
f = ask_and_safe_open(filename, _("private RSA key"), "a");
PEM_write_RSAPrivateKey(f, rsa_key, NULL, NULL, 0, NULL, NULL);
fclose(f);
free(filename);
if(!f)
return -1;
return 0;
if(ftell(f))
fprintf(stderr, _("Appending key to existing contents.\nMake sure only one key is stored in the file.\n"));
PEM_write_RSAPrivateKey(f, rsa_key, NULL, NULL, 0, NULL, NULL);
fclose(f);
free(filename);
return 0;
}
/*
@ -302,126 +311,119 @@ int keygen(int bits)
*/
void make_names(void)
{
if(netname)
{
if(!pidfilename)
asprintf(&pidfilename, LOCALSTATEDIR "/run/tinc.%s.pid", netname);
if(!confbase)
asprintf(&confbase, "%s/tinc/%s", CONFDIR, netname);
else
syslog(LOG_INFO, _("Both netname and configuration directory given, using the latter..."));
if(!identname)
asprintf(&identname, "tinc.%s", netname);
}
else
{
if(!pidfilename)
pidfilename = LOCALSTATEDIR "/run/tinc.pid";
if(!confbase)
asprintf(&confbase, "%s/tinc", CONFDIR);
if(!identname)
identname = "tinc";
}
if(netname) {
if(!pidfilename)
asprintf(&pidfilename, LOCALSTATEDIR "/run/tinc.%s.pid", netname);
if(!confbase)
asprintf(&confbase, "%s/tinc/%s", CONFDIR, netname);
else
syslog(LOG_INFO, _("Both netname and configuration directory given, using the latter..."));
if(!identname)
asprintf(&identname, "tinc.%s", netname);
} else {
if(!pidfilename)
pidfilename = LOCALSTATEDIR "/run/tinc.pid";
if(!confbase)
asprintf(&confbase, "%s/tinc", CONFDIR);
if(!identname)
identname = "tinc";
}
}
int
main(int argc, char **argv, char **envp)
int main(int argc, char **argv, char **envp)
{
program_name = argv[0];
program_name = argv[0];
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
environment = envp;
parse_options(argc, argv, envp);
environment = envp;
parse_options(argc, argv, envp);
if(show_version)
{
printf(_("%s version %s (built %s %s, protocol %d)\n"), PACKAGE, VERSION, __DATE__, __TIME__, PROT_CURRENT);
printf(_("Copyright (C) 1998-2002 Ivo Timmermans, Guus Sliepen and others.\n"
"See the AUTHORS file for a complete list.\n\n"
"tinc comes with ABSOLUTELY NO WARRANTY. This is free software,\n"
"and you are welcome to redistribute it under certain conditions;\n"
"see the file COPYING for details.\n"));
if(show_version) {
printf(_("%s version %s (built %s %s, protocol %d)\n"), PACKAGE,
VERSION, __DATE__, __TIME__, PROT_CURRENT);
printf(_("Copyright (C) 1998-2002 Ivo Timmermans, Guus Sliepen and others.\n"
"See the AUTHORS file for a complete list.\n\n"
"tinc comes with ABSOLUTELY NO WARRANTY. This is free software,\n"
"and you are welcome to redistribute it under certain conditions;\n"
"see the file COPYING for details.\n"));
return 0;
}
return 0;
}
if(show_help)
usage(0);
if(show_help)
usage(0);
#ifndef LOG_PERROR
openlog("tinc", LOG_CONS, LOG_DAEMON); /* Catch all syslog() calls issued before detaching */
openlog("tinc", LOG_CONS, LOG_DAEMON); /* Catch all syslog() calls issued before detaching */
#else
openlog("tinc", LOG_PERROR, LOG_DAEMON); /* Catch all syslog() calls issued before detaching */
openlog("tinc", LOG_PERROR, LOG_DAEMON); /* Catch all syslog() calls issued before detaching */
#endif
/* Lock all pages into memory if requested */
if(do_mlock)
/* Lock all pages into memory if requested */
if(do_mlock)
#ifdef HAVE_MLOCKALL
if(mlockall(MCL_CURRENT | MCL_FUTURE))
{
syslog(LOG_ERR, _("System call `%s' failed: %s"), "mlockall", strerror(errno));
if(mlockall(MCL_CURRENT | MCL_FUTURE)) {
syslog(LOG_ERR, _("System call `%s' failed: %s"), "mlockall",
strerror(errno));
#else
{
syslog(LOG_ERR, _("mlockall() not supported on this platform!"));
{
syslog(LOG_ERR, _("mlockall() not supported on this platform!"));
#endif
return -1;
}
g_argv = argv;
return -1;
}
make_names();
init_configuration(&config_tree);
g_argv = argv;
/* Slllluuuuuuurrrrp! */
cp();
RAND_load_file("/dev/urandom", 1024);
make_names();
init_configuration(&config_tree);
/* Slllluuuuuuurrrrp! */
RAND_load_file("/dev/urandom", 1024);
#ifdef HAVE_SSLEAY_ADD_ALL_ALGORITHMS
SSLeay_add_all_algorithms();
SSLeay_add_all_algorithms();
#else
OpenSSL_add_all_algorithms();
OpenSSL_add_all_algorithms();
#endif
cp();
if(generate_keys)
{
read_server_config();
exit(keygen(generate_keys));
}
if(generate_keys) {
read_server_config();
exit(keygen(generate_keys));
}
if(kill_tincd)
exit(kill_other(kill_tincd));
if(kill_tincd)
exit(kill_other(kill_tincd));
if(read_server_config())
exit(1);
cp();
if(detach())
exit(0);
cp();
for(;;)
{
if(!setup_network_connections())
{
main_loop();
cleanup_and_exit(1);
}
if(read_server_config())
exit(1);
syslog(LOG_ERR, _("Unrecoverable error"));
cp_trace();
if(detach())
exit(0);
if(do_detach)
{
syslog(LOG_NOTICE, _("Restarting in %d seconds!"), maxtimeout);
sleep(maxtimeout);
}
else
{
syslog(LOG_ERR, _("Not restarting."));
exit(1);
}
}
for(;;) {
if(!setup_network_connections()) {
main_loop();
cleanup_and_exit(1);
}
syslog(LOG_ERR, _("Unrecoverable error"));
cp_trace();
if(do_detach) {
syslog(LOG_NOTICE, _("Restarting in %d seconds!"), maxtimeout);
sleep(maxtimeout);
} else {
syslog(LOG_ERR, _("Not restarting."));
exit(1);
}
}
}