- Non-blocking connect()s.
- Socket handling revamped to use sockaddr_t. - tinc can now tunnel over IPv6. - Handle all addresses and subnets in network byte order. Only convert them when they need to be printed. - IPv6 subnets bigger than /128 now work. - Use %s and strerror(errno) instead of %m.
This commit is contained in:
parent
fc674eaae1
commit
c2b9c06062
33 changed files with 2487 additions and 2018 deletions
|
@ -100,6 +100,12 @@ If you leave it out, remember to replace it with at least one space character.
|
|||
Here are all valid variables, listed in alphabetical order.
|
||||
The default value is given between parentheses.
|
||||
.Bl -tag -width indent
|
||||
.It Va AddressFamily Li = ipv4 | ipv6 | any Pq ipv4
|
||||
This option affects the address family of listening and outgoing sockets.
|
||||
If
|
||||
.Qq any
|
||||
is selected, then the listening sockets will be IPv6 sockets,
|
||||
but on most platforms those will also accept IPv4 connections.
|
||||
.It Va BindToInterface Li = Ar interface Bq experimental
|
||||
If your computer has more than one network interface,
|
||||
.Nm tinc
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
\input texinfo @c -*-texinfo-*-
|
||||
@c $Id: tinc.texi,v 1.8.4.20 2002/02/11 15:59:18 guus Exp $
|
||||
@c $Id: tinc.texi,v 1.8.4.21 2002/02/18 16:25:15 guus Exp $
|
||||
@c %**start of header
|
||||
@setfilename tinc.info
|
||||
@settitle tinc Manual
|
||||
|
@ -18,7 +18,7 @@ Copyright @copyright{} 1998-2002 Ivo Timmermans
|
|||
<itimmermans@@bigfoot.com>, Guus Sliepen <guus@@sliepen.warande.net> and
|
||||
Wessel Dankers <wsl@@nl.linux.org>.
|
||||
|
||||
$Id: tinc.texi,v 1.8.4.20 2002/02/11 15:59:18 guus Exp $
|
||||
$Id: tinc.texi,v 1.8.4.21 2002/02/18 16:25:15 guus Exp $
|
||||
|
||||
Permission is granted to make and distribute verbatim copies of this
|
||||
manual provided the copyright notice and this permission notice are
|
||||
|
@ -43,7 +43,7 @@ Copyright @copyright{} 1998-2002 Ivo Timmermans
|
|||
<itimmermans@@bigfoot.com>, Guus Sliepen <guus@@sliepen.warande.net> and
|
||||
Wessel Dankers <wsl@@nl.linux.org>.
|
||||
|
||||
$Id: tinc.texi,v 1.8.4.20 2002/02/11 15:59:18 guus Exp $
|
||||
$Id: tinc.texi,v 1.8.4.21 2002/02/18 16:25:15 guus Exp $
|
||||
|
||||
Permission is granted to make and distribute verbatim copies of this
|
||||
manual provided the copyright notice and this permission notice are
|
||||
|
@ -736,6 +736,12 @@ required directives are given in @strong{bold}.
|
|||
@subsection Main configuration variables
|
||||
|
||||
@table @asis
|
||||
@cindex AddressFamily
|
||||
@item AddressFamily = <ipv4|ipv6|any> (ipv4)
|
||||
This option affects the address family of listening and outgoing sockets.
|
||||
If "any" is selected, then the listening sockets will be IPv6 sockets,
|
||||
but on most platforms those will also accept IPv4 connections.
|
||||
|
||||
@cindex BindToInterface
|
||||
@item BindToInterface = <interface>
|
||||
If you have more than one network interface in your computer, tinc will
|
||||
|
|
|
@ -9,6 +9,9 @@ src/conf.c
|
|||
src/connection.c
|
||||
src/meta.c
|
||||
src/net.c
|
||||
src/net_packet.c
|
||||
src/net_setup.c
|
||||
src/net_socket.c
|
||||
src/netutl.c
|
||||
src/protocol.c
|
||||
src/protocol_auth.c
|
||||
|
@ -25,5 +28,6 @@ src/edge.c
|
|||
src/graph.c
|
||||
src/linux/device.c
|
||||
src/freebsd/device.c
|
||||
src/openbsd/device.c
|
||||
src/solaris/device.c
|
||||
src/netbsd/device.c
|
||||
src/openbsd/device.c
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
## Produce this file with automake to get Makefile.in
|
||||
# $Id: Makefile.am,v 1.4.4.19 2002/02/10 21:57:52 guus Exp $
|
||||
# $Id: Makefile.am,v 1.4.4.20 2002/02/18 16:25:16 guus Exp $
|
||||
|
||||
sbin_PROGRAMS = tincd
|
||||
|
||||
EXTRA_DIST = linux/device.c freebsd/device.c openbsd/device.c solaris/device.c
|
||||
|
||||
tincd_SOURCES = conf.c connection.c device.c edge.c event.c graph.c meta.c net.c netutl.c node.c process.c \
|
||||
protocol.c protocol_auth.c protocol_edge.c protocol_misc.c protocol_key.c protocol_subnet.c \
|
||||
route.c subnet.c tincd.c
|
||||
tincd_SOURCES = conf.c connection.c device.c edge.c event.c graph.c meta.c net.c net_packet.c net_setup.c \
|
||||
net_socket.c netutl.c node.c process.c protocol.c protocol_auth.c protocol_edge.c protocol_misc.c \
|
||||
protocol_key.c protocol_subnet.c route.c subnet.c tincd.c
|
||||
|
||||
INCLUDES = @INCLUDES@ -I$(top_builddir) -I$(top_srcdir)/lib -I$(top_srcdir)/intl
|
||||
|
||||
|
|
109
src/conf.c
109
src/conf.c
|
@ -19,7 +19,7 @@
|
|||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
$Id: conf.c,v 1.9.4.52 2002/02/10 21:57:53 guus Exp $
|
||||
$Id: conf.c,v 1.9.4.53 2002/02/18 16:25:16 guus Exp $
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
@ -56,14 +56,14 @@ char *netname = NULL; /* name of the vpn network */
|
|||
int config_compare(config_t *a, config_t *b)
|
||||
{
|
||||
int result;
|
||||
|
||||
result = strcmp(a->variable, b->variable);
|
||||
|
||||
|
||||
result = strcasecmp(a->variable, b->variable);
|
||||
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
result = a->line - b->line;
|
||||
|
||||
|
||||
if(result)
|
||||
return result;
|
||||
else
|
||||
|
@ -90,7 +90,7 @@ config_t *new_config(void)
|
|||
config_t *cfg;
|
||||
cp
|
||||
cfg = (config_t *)xmalloc_and_zero(sizeof(*cfg));
|
||||
|
||||
|
||||
return cfg;
|
||||
}
|
||||
|
||||
|
@ -126,7 +126,7 @@ cp
|
|||
|
||||
if(!found)
|
||||
return NULL;
|
||||
|
||||
|
||||
if(strcmp(found->variable, variable))
|
||||
return NULL;
|
||||
|
||||
|
@ -139,7 +139,7 @@ config_t *lookup_config_next(avl_tree_t *config_tree, config_t *cfg)
|
|||
config_t *found;
|
||||
cp
|
||||
node = avl_search_node(config_tree, cfg);
|
||||
|
||||
|
||||
if(node)
|
||||
{
|
||||
if(node->next)
|
||||
|
@ -149,10 +149,10 @@ cp
|
|||
return found;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int get_config_bool(config_t *cfg, int *result)
|
||||
{
|
||||
cp
|
||||
|
@ -184,7 +184,7 @@ cp
|
|||
|
||||
if(sscanf(cfg->value, "%d", result) == 1)
|
||||
return 1;
|
||||
|
||||
|
||||
syslog(LOG_ERR, _("Integer expected for configuration variable %s in %s line %d"),
|
||||
cfg->variable, cfg->file, cfg->line);
|
||||
return 0;
|
||||
|
@ -196,27 +196,26 @@ cp
|
|||
if(!cfg)
|
||||
return 0;
|
||||
|
||||
*result = cfg->value;
|
||||
*result = xstrdup(cfg->value);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int get_config_address(config_t *cfg, ipv4_t **result)
|
||||
int get_config_address(config_t *cfg, struct addrinfo **result)
|
||||
{
|
||||
ipv4_t *ip;
|
||||
struct addrinfo *ai;
|
||||
cp
|
||||
if(!cfg)
|
||||
return 0;
|
||||
|
||||
ip = xmalloc(sizeof(*ip));
|
||||
*ip = str2address(cfg->value);
|
||||
ai = str2addrinfo(cfg->value, NULL, 0);
|
||||
|
||||
if(ip)
|
||||
if(ai)
|
||||
{
|
||||
*result = ip;
|
||||
*result = ai;
|
||||
return 1;
|
||||
}
|
||||
|
||||
syslog(LOG_ERR, _("IP address expected for configuration variable %s in %s line %d"),
|
||||
syslog(LOG_ERR, _("Hostname or IP address expected for configuration variable %s in %s line %d"),
|
||||
cfg->variable, cfg->file, cfg->line);
|
||||
return 0;
|
||||
}
|
||||
|
@ -228,8 +227,11 @@ cp
|
|||
return 0;
|
||||
|
||||
if(sscanf(cfg->value, "%hu", result) == 1)
|
||||
return 1;
|
||||
|
||||
{
|
||||
*result = htons(*result);
|
||||
return 1;
|
||||
}
|
||||
|
||||
syslog(LOG_ERR, _("Port number expected for configuration variable %s in %s line %d"),
|
||||
cfg->variable, cfg->file, cfg->line);
|
||||
return 0;
|
||||
|
@ -250,20 +252,20 @@ cp
|
|||
cfg->variable, cfg->file, cfg->line);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Teach newbies what subnets are... */
|
||||
|
||||
if(subnet->type == SUBNET_IPV4)
|
||||
if((subnet->net.ipv4.address & subnet->net.ipv4.mask) != subnet->net.ipv4.address)
|
||||
{
|
||||
syslog(LOG_ERR, _("Network address and mask length do not match for configuration variable %s in %s line %d"),
|
||||
cfg->variable, cfg->file, cfg->line);
|
||||
free(subnet);
|
||||
return 0;
|
||||
}
|
||||
if(((subnet->type == SUBNET_IPV4) && maskcheck((char *)&subnet->net.ipv4.address, subnet->net.ipv4.masklength, sizeof(ipv4_t)))
|
||||
|| ((subnet->type == SUBNET_IPV6) && maskcheck((char *)&subnet->net.ipv6.address, subnet->net.ipv6.masklength, sizeof(ipv6_t))))
|
||||
{
|
||||
syslog(LOG_ERR, _("Network address and mask length do not match for configuration variable %s in %s line %d"),
|
||||
cfg->variable, cfg->file, cfg->line);
|
||||
free(subnet);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*result = subnet;
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -271,7 +273,7 @@ cp
|
|||
Read exactly one line and strip the trailing newline if any. If the
|
||||
file was on EOF, return NULL. Otherwise, return all the data in a
|
||||
dynamically allocated buffer.
|
||||
|
||||
|
||||
If line is non-NULL, it will be used as an initial buffer, to avoid
|
||||
unnecessary mallocing each time this function is called. If buf is
|
||||
given, and buf needs to be expanded, the var pointed to by buflen
|
||||
|
@ -360,17 +362,17 @@ int read_config_file(avl_tree_t *config_tree, const char *fname)
|
|||
int lineno = 0, ignore = 0;
|
||||
config_t *cfg;
|
||||
size_t bufsize;
|
||||
|
||||
|
||||
cp
|
||||
if((fp = fopen (fname, "r")) == NULL)
|
||||
{
|
||||
syslog(LOG_ERR, _("Cannot open config file %s: %m"), fname);
|
||||
syslog(LOG_ERR, _("Cannot open config file %s: %s"), fname, strerror(errno));
|
||||
return -3;
|
||||
}
|
||||
|
||||
bufsize = 100;
|
||||
buffer = xmalloc(bufsize);
|
||||
|
||||
|
||||
for(;;)
|
||||
{
|
||||
if((line = readline(fp, &buffer, &bufsize)) == NULL)
|
||||
|
@ -395,7 +397,7 @@ cp
|
|||
|
||||
if(!strcmp(variable, "-----BEGIN"))
|
||||
ignore = 1;
|
||||
|
||||
|
||||
if(!ignore)
|
||||
{
|
||||
if(((value = strtok(NULL, "\t\n\r =")) == NULL) || value[0] == '#')
|
||||
|
@ -433,12 +435,11 @@ cp
|
|||
x = read_config_file(config_tree, fname);
|
||||
if(x == -1) /* System error: complain */
|
||||
{
|
||||
syslog(LOG_ERR, _("Failed to read `%s': %m"),
|
||||
fname);
|
||||
syslog(LOG_ERR, _("Failed to read `%s': %s"), fname, strerror(errno));
|
||||
}
|
||||
free(fname);
|
||||
cp
|
||||
return x;
|
||||
return x;
|
||||
}
|
||||
|
||||
int isadir(const char* f)
|
||||
|
@ -466,10 +467,10 @@ int is_safe_path(const char *file)
|
|||
}
|
||||
|
||||
p = strrchr(file, '/');
|
||||
|
||||
|
||||
if(p == file) /* It's in the root */
|
||||
p++;
|
||||
|
||||
|
||||
x = *p;
|
||||
*p = '\0';
|
||||
|
||||
|
@ -477,8 +478,7 @@ int is_safe_path(const char *file)
|
|||
check1:
|
||||
if(lstat(f, &s) < 0)
|
||||
{
|
||||
syslog(LOG_ERR, _("Couldn't stat `%s': %m"),
|
||||
f);
|
||||
syslog(LOG_ERR, _("Couldn't stat `%s': %s"), f, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -496,25 +496,24 @@ check1:
|
|||
|
||||
if(readlink(f, l, MAXBUFSIZE) < 0)
|
||||
{
|
||||
syslog(LOG_ERR, _("Unable to read symbolic link `%s': %m"), f);
|
||||
syslog(LOG_ERR, _("Unable to read symbolic link `%s': %s"), f, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
f = l;
|
||||
goto check1;
|
||||
}
|
||||
|
||||
*p = x;
|
||||
f = file;
|
||||
|
||||
|
||||
check2:
|
||||
if(lstat(f, &s) < 0 && errno != ENOENT)
|
||||
{
|
||||
syslog(LOG_ERR, _("Couldn't stat `%s': %m"),
|
||||
f);
|
||||
syslog(LOG_ERR, _("Couldn't stat `%s': %s"), f, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if(errno == ENOENT)
|
||||
return 1;
|
||||
|
||||
|
@ -532,10 +531,10 @@ check2:
|
|||
|
||||
if(readlink(f, l, MAXBUFSIZE) < 0)
|
||||
{
|
||||
syslog(LOG_ERR, _("Unable to read symbolic link `%s': %m"), f);
|
||||
syslog(LOG_ERR, _("Unable to read symbolic link `%s': %s"), f, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
f = l;
|
||||
goto check2;
|
||||
}
|
||||
|
@ -547,7 +546,7 @@ check2:
|
|||
f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -587,7 +586,7 @@ FILE *ask_and_safe_open(const char* filename, const char* what, const char* mode
|
|||
{
|
||||
/* The directory is a relative path or a filename. */
|
||||
char *p;
|
||||
|
||||
|
||||
directory = get_current_dir_name();
|
||||
asprintf(&p, "%s/%s", directory, fn);
|
||||
free(fn);
|
||||
|
@ -596,7 +595,7 @@ FILE *ask_and_safe_open(const char* filename, const char* what, const char* mode
|
|||
}
|
||||
|
||||
umask(0077); /* Disallow everything for group and other */
|
||||
|
||||
|
||||
/* Open it first to keep the inode busy */
|
||||
if((r = fopen(fn, mode)) == NULL)
|
||||
{
|
||||
|
@ -605,7 +604,7 @@ FILE *ask_and_safe_open(const char* filename, const char* what, const char* mode
|
|||
free(fn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Then check the file for nasty attacks */
|
||||
if(!is_safe_path(fn)) /* Do not permit any directories that are
|
||||
readable or writeable by other users. */
|
||||
|
|
|
@ -17,12 +17,16 @@
|
|||
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.31 2002/02/10 21:57:53 guus Exp $
|
||||
$Id: conf.h,v 1.6.4.32 2002/02/18 16:25:16 guus Exp $
|
||||
*/
|
||||
|
||||
#ifndef __TINC_CONF_H__
|
||||
#define __TINC_CONF_H__
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#include <avl_tree.h>
|
||||
#include "net.h"
|
||||
#include "subnet.h"
|
||||
|
@ -54,7 +58,7 @@ extern int get_config_bool(config_t *, int *);
|
|||
extern int get_config_int(config_t *, int *);
|
||||
extern int get_config_port(config_t *, port_t *);
|
||||
extern int get_config_string(config_t *, char **);
|
||||
extern int get_config_address(config_t *, ipv4_t **);
|
||||
extern int get_config_address(config_t *, struct addrinfo **);
|
||||
struct subnet_t; /* Needed for next line. */
|
||||
extern int get_config_subnet(config_t *, struct subnet_t **);
|
||||
|
||||
|
|
|
@ -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.27 2002/02/10 21:57:53 guus Exp $
|
||||
$Id: connection.c,v 1.1.2.28 2002/02/18 16:25:16 guus Exp $
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
@ -44,7 +44,7 @@ avl_tree_t *connection_tree; /* Meta connections */
|
|||
|
||||
int connection_compare(connection_t *a, connection_t *b)
|
||||
{
|
||||
return a->socket - b->socket;
|
||||
return a - b;
|
||||
}
|
||||
|
||||
void init_connections(void)
|
||||
|
@ -106,16 +106,6 @@ cp
|
|||
cp
|
||||
}
|
||||
|
||||
connection_t *lookup_connection(ipv4_t address, port_t port)
|
||||
{
|
||||
connection_t c;
|
||||
cp
|
||||
c.address = address;
|
||||
c.port = port;
|
||||
|
||||
return avl_search(connection_tree, &c);
|
||||
}
|
||||
|
||||
void dump_connections(void)
|
||||
{
|
||||
avl_node_t *node;
|
||||
|
@ -126,9 +116,8 @@ cp
|
|||
for(node = connection_tree->head; node; node = node->next)
|
||||
{
|
||||
c = (connection_t *)node->data;
|
||||
syslog(LOG_DEBUG, _(" %s at %s port %hd options %ld socket %d status %04x"),
|
||||
c->name, c->hostname, c->port, c->options,
|
||||
c->socket, c->status);
|
||||
syslog(LOG_DEBUG, _(" %s at %s options %ld socket %d status %04x"),
|
||||
c->name, c->hostname, c->options, c->socket, c->status);
|
||||
}
|
||||
|
||||
syslog(LOG_DEBUG, _("End of connections."));
|
||||
|
|
|
@ -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.24 2002/02/10 21:57:53 guus Exp $
|
||||
$Id: connection.h,v 1.1.2.25 2002/02/18 16:25:16 guus Exp $
|
||||
*/
|
||||
|
||||
#ifndef __TINC_CONNECTION_H__
|
||||
|
@ -52,6 +52,7 @@
|
|||
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 */
|
||||
|
@ -64,8 +65,7 @@ typedef struct connection_status_t {
|
|||
typedef struct connection_t {
|
||||
char *name; /* name he claims to have */
|
||||
|
||||
ipv4_t address; /* his real (internet) ip */
|
||||
port_t port; /* port number of meta connection */
|
||||
sockaddr_t address; /* his real (internet) ip */
|
||||
char *hostname; /* the hostname of its real ip */
|
||||
int protocol_version; /* used protocol */
|
||||
|
||||
|
@ -77,7 +77,7 @@ typedef struct connection_t {
|
|||
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 edge_t *edge; /* edge associated with this connection */
|
||||
|
||||
RSA *rsa_key; /* his public/private key */
|
||||
EVP_CIPHER *incipher; /* Cipher he will use to send data to us */
|
||||
|
@ -109,7 +109,6 @@ extern connection_t *new_connection(void);
|
|||
extern void free_connection(connection_t *);
|
||||
extern void connection_add(connection_t *);
|
||||
extern void connection_del(connection_t *);
|
||||
extern connection_t *lookup_connection(ipv4_t, short unsigned int);
|
||||
extern void dump_connections(void);
|
||||
extern int read_connection_config(connection_t *);
|
||||
|
||||
|
|
35
src/edge.c
35
src/edge.c
|
@ -17,7 +17,7 @@
|
|||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
$Id: edge.c,v 1.1.2.6 2002/02/10 21:57:54 guus Exp $
|
||||
$Id: edge.c,v 1.1.2.7 2002/02/18 16:25:16 guus Exp $
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
@ -47,7 +47,7 @@ int edge_compare(edge_t *a, edge_t *b)
|
|||
int result;
|
||||
|
||||
result = strcmp(a->from.node->name, b->from.node->name);
|
||||
|
||||
|
||||
if(result)
|
||||
return result;
|
||||
else
|
||||
|
@ -69,7 +69,7 @@ int edge_name_compare(edge_t *a, edge_t *b)
|
|||
{
|
||||
int result;
|
||||
char *name_a1, *name_a2, *name_b1, *name_b2;
|
||||
|
||||
|
||||
if(strcmp(a->from.node->name, a->to.node->name) < 0)
|
||||
name_a1 = a->from.node->name, name_a2 = a->to.node->name;
|
||||
else
|
||||
|
@ -81,7 +81,7 @@ int edge_name_compare(edge_t *a, edge_t *b)
|
|||
name_b1 = b->to.node->name, name_b2 = b->from.node->name;
|
||||
|
||||
result = strcmp(name_a1, name_b1);
|
||||
|
||||
|
||||
if(result)
|
||||
return result;
|
||||
else
|
||||
|
@ -91,9 +91,9 @@ int edge_name_compare(edge_t *a, edge_t *b)
|
|||
int edge_weight_compare(edge_t *a, edge_t *b)
|
||||
{
|
||||
int result;
|
||||
|
||||
|
||||
result = a->weight - b->weight;
|
||||
|
||||
|
||||
if(result)
|
||||
return result;
|
||||
else
|
||||
|
@ -189,23 +189,28 @@ void dump_edges(void)
|
|||
{
|
||||
avl_node_t *node;
|
||||
edge_t *e;
|
||||
char *from_address, *to_address;
|
||||
char *from_tcp, *from_udp;
|
||||
char *to_tcp, *to_udp;
|
||||
cp
|
||||
syslog(LOG_DEBUG, _("Edges:"));
|
||||
|
||||
for(node = edge_tree->head; node; node = node->next)
|
||||
{
|
||||
e = (edge_t *)node->data;
|
||||
from_address = address2str(e->from.address);
|
||||
to_address = address2str(e->to.address);
|
||||
syslog(LOG_DEBUG, _(" %s at %s port %hd - %s at %s port %hd options %ld weight %d"),
|
||||
e->from.node->name, from_address, e->from.port,
|
||||
e->to.node->name, to_address, e->to.port,
|
||||
from_tcp = sockaddr2hostname(&e->from.tcpaddress);
|
||||
from_udp = sockaddr2hostname(&e->from.udpaddress);
|
||||
to_tcp = sockaddr2hostname(&e->to.tcpaddress);
|
||||
to_udp = sockaddr2hostname(&e->to.udpaddress);
|
||||
syslog(LOG_DEBUG, _(" %s tcp at %s udp at %s - %s tcp at %s udp at %s options %ld weight %d"),
|
||||
e->from.node->name, from_tcp, from_udp,
|
||||
e->to.node->name, to_tcp, to_udp,
|
||||
e->options, e->weight);
|
||||
free(from_address);
|
||||
free(to_address);
|
||||
free(from_tcp);
|
||||
free(from_udp);
|
||||
free(to_tcp);
|
||||
free(to_udp);
|
||||
}
|
||||
|
||||
|
||||
syslog(LOG_DEBUG, _("End of edges."));
|
||||
cp
|
||||
}
|
||||
|
|
|
@ -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.5 2002/02/10 21:57:54 guus Exp $
|
||||
$Id: edge.h,v 1.1.2.6 2002/02/18 16:25:16 guus Exp $
|
||||
*/
|
||||
|
||||
#ifndef __TINC_EDGE_H__
|
||||
|
@ -25,14 +25,14 @@
|
|||
|
||||
#include <avl_tree.h>
|
||||
|
||||
#include "net.h"
|
||||
#include "node.h"
|
||||
#include "connection.h"
|
||||
|
||||
typedef struct halfconnection_t {
|
||||
struct node_t *node; /* node associated with this end of the connection */
|
||||
|
||||
ipv4_t address; /* real (internet) ip on this end of the meta connection */
|
||||
port_t port; /* port number of this end of the meta connection */
|
||||
sockaddr_t tcpaddress; /* real (internet) ip on this end of the meta connection */
|
||||
sockaddr_t udpaddress; /* real (internet) ip on this end of the vpn connection */
|
||||
} halfconnection_t;
|
||||
|
||||
typedef struct edge_t {
|
||||
|
|
|
@ -17,12 +17,13 @@
|
|||
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.3 2002/02/11 12:33:01 guus Exp $
|
||||
$Id: device.c,v 1.1.2.4 2002/02/18 16:25:19 guus Exp $
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
@ -66,7 +67,7 @@ cp
|
|||
cp
|
||||
if((device_fd = open(device, O_RDWR | O_NONBLOCK)) < 0)
|
||||
{
|
||||
syslog(LOG_ERR, _("Could not open %s: %m"), device);
|
||||
syslog(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
cp
|
||||
|
@ -104,7 +105,7 @@ int read_packet(vpn_packet_t *packet)
|
|||
cp
|
||||
if((lenin = read(device_fd, packet->data, MTU)) <= 0)
|
||||
{
|
||||
syslog(LOG_ERR, _("Error while reading from %s %s: %m"), device_info, device);
|
||||
syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, device, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -129,7 +130,7 @@ cp
|
|||
|
||||
if(write(device_fd, packet->data, packet->len) < 0)
|
||||
{
|
||||
syslog(LOG_ERR, _("Error while writing to %s %s: %m"), device_info, device);
|
||||
syslog(LOG_ERR, _("Error while writing to %s %s: %s"), device_info, device, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
10
src/graph.c
10
src/graph.c
|
@ -17,7 +17,7 @@
|
|||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
$Id: graph.c,v 1.1.2.6 2002/02/10 21:57:54 guus Exp $
|
||||
$Id: graph.c,v 1.1.2.7 2002/02/18 16:25:16 guus Exp $
|
||||
*/
|
||||
|
||||
/* We need to generate two trees from the graph:
|
||||
|
@ -186,17 +186,15 @@ void sssp_bfs(void)
|
|||
to_hc.node->nexthop = (n->nexthop == myself) ? to_hc.node : n->nexthop;
|
||||
to_hc.node->via = (e->options & OPTION_INDIRECT || n->via != n) ? n->via : to_hc.node;
|
||||
to_hc.node->options = e->options;
|
||||
if(to_hc.node->address != to_hc.address || to_hc.node->port != to_hc.port)
|
||||
if(sockaddrcmp(&to_hc.node->address, &to_hc.udpaddress))
|
||||
{
|
||||
node = avl_unlink(node_udp_tree, to_hc.node);
|
||||
to_hc.node->address = to_hc.address;
|
||||
to_hc.node->port = to_hc.port;
|
||||
to_hc.node->address = to_hc.udpaddress;
|
||||
if(to_hc.node->hostname)
|
||||
free(to_hc.node->hostname);
|
||||
to_hc.node->hostname = hostlookup(htonl(to_hc.address));
|
||||
to_hc.node->hostname = sockaddr2hostname(&to_hc.udpaddress);
|
||||
avl_insert_node(node_udp_tree, node);
|
||||
}
|
||||
to_hc.node->port = to_hc.port;
|
||||
node = avl_alloc_node();
|
||||
node->data = to_hc.node;
|
||||
avl_insert_before(todo_tree, from, node);
|
||||
|
|
|
@ -17,12 +17,13 @@
|
|||
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.6 2002/02/11 12:33:01 guus Exp $
|
||||
$Id: device.c,v 1.1.2.7 2002/02/18 16:25:19 guus Exp $
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
@ -85,7 +86,7 @@ cp
|
|||
cp
|
||||
if((device_fd = open(device, O_RDWR | O_NONBLOCK)) < 0)
|
||||
{
|
||||
syslog(LOG_ERR, _("Could not open %s: %m"), device);
|
||||
syslog(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
cp
|
||||
|
@ -154,7 +155,7 @@ cp
|
|||
{
|
||||
if((lenin = read(device_fd, packet->data, MTU)) <= 0)
|
||||
{
|
||||
syslog(LOG_ERR, _("Error while reading from %s %s: %m"), device_info, device);
|
||||
syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, device, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -164,7 +165,7 @@ cp
|
|||
{
|
||||
if((lenin = read(device_fd, packet->data - 2, MTU + 2)) <= 0)
|
||||
{
|
||||
syslog(LOG_ERR, _("Error while reading from %s %s: %m"), device_info, device);
|
||||
syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, device, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -193,7 +194,7 @@ cp
|
|||
{
|
||||
if(write(device_fd, packet->data, packet->len) < 0)
|
||||
{
|
||||
syslog(LOG_ERR, _("Can't write to %s %s: %m"), device_info, device);
|
||||
syslog(LOG_ERR, _("Can't write to %s %s: %s"), device_info, device, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -202,7 +203,7 @@ cp
|
|||
*(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: %m"), device_info, device);
|
||||
syslog(LOG_ERR, _("Can't write to %s %s: %s"), device_info, device, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
|
10
src/meta.c
10
src/meta.c
|
@ -17,7 +17,7 @@
|
|||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
$Id: meta.c,v 1.1.2.23 2002/02/12 14:36:45 guus Exp $
|
||||
$Id: meta.c,v 1.1.2.24 2002/02/18 16:25:16 guus Exp $
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
@ -60,7 +60,7 @@ cp
|
|||
|
||||
if(write(c->socket, bufp, length) < 0)
|
||||
{
|
||||
syslog(LOG_ERR, _("Sending meta data to %s (%s) failed: %m"), c->name, c->hostname);
|
||||
syslog(LOG_ERR, _("Sending meta data to %s (%s) failed: %s"), c->name, c->hostname, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
cp
|
||||
|
@ -91,7 +91,7 @@ int receive_meta(connection_t *c)
|
|||
cp
|
||||
if(getsockopt(c->socket, SOL_SOCKET, SO_ERROR, &x, &l) < 0)
|
||||
{
|
||||
syslog(LOG_ERR, _("This is a bug: %s:%d: %d:%m %s (%s)"), __FILE__, __LINE__, c->socket,
|
||||
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;
|
||||
}
|
||||
|
@ -125,8 +125,8 @@ cp
|
|||
if(errno==EINTR)
|
||||
return 0;
|
||||
else
|
||||
syslog(LOG_ERR, _("Metadata socket read error for %s (%s): %m"),
|
||||
c->name, c->hostname);
|
||||
syslog(LOG_ERR, _("Metadata socket read error for %s (%s): %s"),
|
||||
c->name, c->hostname, strerror(errno));
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
|
37
src/net.h
37
src/net.h
|
@ -17,12 +17,15 @@
|
|||
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.38 2002/02/10 21:57:54 guus Exp $
|
||||
$Id: net.h,v 1.9.4.39 2002/02/18 16:25:16 guus Exp $
|
||||
*/
|
||||
|
||||
#ifndef __TINC_NET_H__
|
||||
#define __TINC_NET_H__
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "config.h"
|
||||
|
@ -37,7 +40,10 @@ typedef struct mac_t
|
|||
unsigned char x[6];
|
||||
} mac_t;
|
||||
|
||||
typedef unsigned long ipv4_t;
|
||||
typedef struct ipv4_t
|
||||
{
|
||||
unsigned char x[4];
|
||||
} ipv4_t;
|
||||
|
||||
typedef struct ip_mask_t {
|
||||
ipv4_t address;
|
||||
|
@ -53,6 +59,14 @@ typedef unsigned short port_t;
|
|||
|
||||
typedef short length_t;
|
||||
|
||||
typedef union {
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_in in;
|
||||
struct sockaddr_in6 in6;
|
||||
} sockaddr_t;
|
||||
|
||||
#define SA_PORT(s) ((s.sa.sa_family==AF_INET)?s.in.sin_port:(s.sa.sa_family==AF_INET6)?s.in6.sin6_port:0)
|
||||
|
||||
typedef struct vpn_packet_t {
|
||||
length_t len; /* the actual number of bytes in the `data' field */
|
||||
unsigned int seqno; /* 32 bits sequence number (network byte order of course) */
|
||||
|
@ -73,16 +87,35 @@ typedef struct packet_queue_t {
|
|||
typedef struct outgoing_t {
|
||||
char *name;
|
||||
int timeout;
|
||||
struct config_t *cfg;
|
||||
struct addrinfo *ai;
|
||||
struct addrinfo *aip;
|
||||
} outgoing_t;
|
||||
|
||||
extern int maxtimeout;
|
||||
extern int seconds_till_retry;
|
||||
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 */
|
||||
|
||||
extern int tcp_socket;
|
||||
extern int udp_socket;
|
||||
extern int keyexpires;
|
||||
extern int keylifetime;
|
||||
extern int do_prune;
|
||||
extern int do_purge;
|
||||
extern char *myport;
|
||||
|
||||
extern void retry_outgoing(outgoing_t *);
|
||||
extern void handle_incoming_vpn_data(void);
|
||||
extern void finish_connecting(connection_t *);
|
||||
extern void do_outgoing_connection(connection_t *);
|
||||
extern int handle_new_meta_connection(void);
|
||||
extern int setup_listen_socket(sockaddr_t *);
|
||||
extern int setup_vpn_in_socket(sockaddr_t *);
|
||||
extern void send_packet(struct node_t *, vpn_packet_t *);
|
||||
extern void receive_packet(struct node_t *, vpn_packet_t *);
|
||||
extern void receive_tcppacket(struct connection_t *, char *, int);
|
||||
|
|
391
src/net_packet.c
Normal file
391
src/net_packet.c
Normal file
|
@ -0,0 +1,391 @@
|
|||
/*
|
||||
net_packet.c -- Handles in- and outgoing VPN packets
|
||||
Copyright (C) 1998-2002 Ivo Timmermans <itimmermans@bigfoot.com>,
|
||||
2000-2002 Guus Sliepen <guus@sliepen.warande.net>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
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.1 2002/02/18 16:25:16 guus Exp $
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#ifdef HAVE_LINUX
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/tcp.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
/* SunOS really wants sys/socket.h BEFORE net/if.h,
|
||||
and FreeBSD wants these lines below the rest. */
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/if.h>
|
||||
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/hmac.h>
|
||||
|
||||
#ifndef HAVE_RAND_PSEUDO_BYTES
|
||||
#define RAND_pseudo_bytes RAND_bytes
|
||||
#endif
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
#include <utils.h>
|
||||
#include <xalloc.h>
|
||||
#include <avl_tree.h>
|
||||
#include <list.h>
|
||||
|
||||
#include "conf.h"
|
||||
#include "connection.h"
|
||||
#include "meta.h"
|
||||
#include "net.h"
|
||||
#include "netutl.h"
|
||||
#include "process.h"
|
||||
#include "protocol.h"
|
||||
#include "subnet.h"
|
||||
#include "graph.h"
|
||||
#include "process.h"
|
||||
#include "route.h"
|
||||
#include "device.h"
|
||||
#include "event.h"
|
||||
|
||||
#include "system.h"
|
||||
|
||||
int keylifetime = 0;
|
||||
int keyexpires = 0;
|
||||
|
||||
#define MAX_SEQNO 1073741824
|
||||
|
||||
/* VPN packet I/O */
|
||||
|
||||
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 */
|
||||
|
||||
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))
|
||||
{
|
||||
syslog(LOG_DEBUG, _("Got unauthenticated packet from %s (%s)"), n->name, n->hostname);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Decrypt the packet */
|
||||
|
||||
if(myself->cipher)
|
||||
{
|
||||
outpkt = pkt[nextpkt++];
|
||||
|
||||
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);
|
||||
|
||||
outpkt->len = outlen + outpad;
|
||||
inpkt = outpkt;
|
||||
}
|
||||
|
||||
/* Check the sequence number */
|
||||
|
||||
inpkt->len -= sizeof(inpkt->seqno);
|
||||
inpkt->seqno = ntohl(inpkt->seqno);
|
||||
|
||||
if(inpkt->seqno <= n->received_seqno)
|
||||
{
|
||||
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;
|
||||
|
||||
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);
|
||||
cp
|
||||
}
|
||||
|
||||
void receive_tcppacket(connection_t *c, char *buffer, int len)
|
||||
{
|
||||
vpn_packet_t outpkt;
|
||||
cp
|
||||
outpkt.len = len;
|
||||
memcpy(outpkt.data, buffer, len);
|
||||
|
||||
receive_packet(c->node, &outpkt);
|
||||
cp
|
||||
}
|
||||
|
||||
void receive_packet(node_t *n, vpn_packet_t *packet)
|
||||
{
|
||||
cp
|
||||
if(debug_lvl >= DEBUG_TRAFFIC)
|
||||
syslog(LOG_DEBUG, _("Received packet of %d bytes from %s (%s)"), packet->len, n->name, n->hostname);
|
||||
|
||||
route_incoming(n, packet);
|
||||
cp
|
||||
}
|
||||
|
||||
void send_udppacket(node_t *n, vpn_packet_t *inpkt)
|
||||
{
|
||||
vpn_packet_t pkt1, pkt2;
|
||||
vpn_packet_t *pkt[] = {&pkt1, &pkt2, &pkt1, &pkt2};
|
||||
int nextpkt = 0;
|
||||
vpn_packet_t *outpkt;
|
||||
int outlen, outpad;
|
||||
long int complen = MTU + 12;
|
||||
EVP_CIPHER_CTX ctx;
|
||||
vpn_packet_t *copy;
|
||||
cp
|
||||
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);
|
||||
|
||||
/* Since packet is on the stack of handle_tap_input(),
|
||||
we have to make a copy of it first. */
|
||||
|
||||
copy = xmalloc(sizeof(vpn_packet_t));
|
||||
memcpy(copy, inpkt, sizeof(vpn_packet_t));
|
||||
|
||||
list_insert_tail(n->queue, copy);
|
||||
|
||||
if(!n->status.waitingforkey)
|
||||
send_req_key(n->nexthop->connection, myself, n);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Compress the packet */
|
||||
|
||||
if(n->compression)
|
||||
{
|
||||
outpkt = pkt[nextpkt++];
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* Add sequence number */
|
||||
|
||||
inpkt->seqno = htonl(++(n->sent_seqno));
|
||||
inpkt->len += sizeof(inpkt->seqno);
|
||||
|
||||
/* Encrypt the packet */
|
||||
|
||||
if(n->cipher)
|
||||
{
|
||||
outpkt = pkt[nextpkt++];
|
||||
|
||||
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);
|
||||
|
||||
outpkt->len = outlen + outpad;
|
||||
inpkt = outpkt;
|
||||
}
|
||||
|
||||
/* Add the message authentication code */
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* Send the packet */
|
||||
|
||||
if((sendto(udp_socket, (char *)&inpkt->seqno, inpkt->len, 0, &(n->address.sa), sizeof(sockaddr_t))) < 0)
|
||||
{
|
||||
syslog(LOG_ERR, _("Error sending packet to %s (%s): %s"),
|
||||
n->name, n->hostname, strerror(errno));
|
||||
return;
|
||||
}
|
||||
cp
|
||||
}
|
||||
|
||||
/*
|
||||
send a packet to the given vpn ip.
|
||||
*/
|
||||
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);
|
||||
|
||||
if(n == myself)
|
||||
{
|
||||
if(debug_lvl >= DEBUG_TRAFFIC)
|
||||
{
|
||||
syslog(LOG_NOTICE, _("Packet is looping back to us!"));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
void handle_incoming_vpn_data(void)
|
||||
{
|
||||
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(udp_socket, SOL_SOCKET, SO_ERROR, &x, &l) < 0)
|
||||
{
|
||||
syslog(LOG_ERR, _("This is a bug: %s:%d: %d:%s"),
|
||||
__FILE__, __LINE__, udp_socket, strerror(errno));
|
||||
return;
|
||||
}
|
||||
if(x)
|
||||
{
|
||||
syslog(LOG_ERR, _("Incoming data socket error: %s"), strerror(x));
|
||||
return;
|
||||
}
|
||||
|
||||
if((pkt.len = recvfrom(udp_socket, (char *)&pkt.seqno, MAXSIZE, 0, &from.sa, &fromlen)) <= 0)
|
||||
{
|
||||
syslog(LOG_ERR, _("Receiving packet failed: %s"), strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
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 = time(NULL);
|
||||
*/
|
||||
receive_udppacket(n, &pkt);
|
||||
cp
|
||||
}
|
||||
|
557
src/net_setup.c
Normal file
557
src/net_setup.c
Normal file
|
@ -0,0 +1,557 @@
|
|||
/*
|
||||
net_setup.c -- Setup.
|
||||
Copyright (C) 1998-2002 Ivo Timmermans <itimmermans@bigfoot.com>,
|
||||
2000-2002 Guus Sliepen <guus@sliepen.warande.net>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
$Id: net_setup.c,v 1.1.2.1 2002/02/18 16:25:16 guus Exp $
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#ifdef HAVE_LINUX
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/tcp.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
/* SunOS really wants sys/socket.h BEFORE net/if.h,
|
||||
and FreeBSD wants these lines below the rest. */
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/if.h>
|
||||
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/rand.h>
|
||||
|
||||
#include <utils.h>
|
||||
#include <xalloc.h>
|
||||
#include <avl_tree.h>
|
||||
#include <list.h>
|
||||
|
||||
#include "conf.h"
|
||||
#include "connection.h"
|
||||
#include "meta.h"
|
||||
#include "net.h"
|
||||
#include "netutl.h"
|
||||
#include "process.h"
|
||||
#include "protocol.h"
|
||||
#include "subnet.h"
|
||||
#include "graph.h"
|
||||
#include "process.h"
|
||||
#include "route.h"
|
||||
#include "device.h"
|
||||
#include "event.h"
|
||||
|
||||
#include "system.h"
|
||||
|
||||
char *myport;
|
||||
|
||||
int read_rsa_public_key(connection_t *c)
|
||||
{
|
||||
FILE *fp;
|
||||
char *fname;
|
||||
char *key;
|
||||
cp
|
||||
if(!c->rsa_key)
|
||||
c->rsa_key = RSA_new();
|
||||
|
||||
/* First, check for simple PublicKey statement */
|
||||
|
||||
if(get_config_string(lookup_config(c->config_tree, "PublicKey"), &key))
|
||||
{
|
||||
BN_hex2bn(&c->rsa_key->n, key);
|
||||
BN_hex2bn(&c->rsa_key->e, "FFFF");
|
||||
free(key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Else, check for PublicKeyFile statement and read it */
|
||||
|
||||
if(get_config_string(lookup_config(c->config_tree, "PublicKeyFile"), &fname))
|
||||
{
|
||||
if(is_safe_path(fname))
|
||||
{
|
||||
if((fp = fopen(fname, "r")) == NULL)
|
||||
{
|
||||
syslog(LOG_ERR, _("Error reading RSA public key file `%s': %s"),
|
||||
fname, strerror(errno));
|
||||
free(fname);
|
||||
return -1;
|
||||
}
|
||||
free(fname);
|
||||
c->rsa_key = PEM_read_RSAPublicKey(fp, &c->rsa_key, NULL, NULL);
|
||||
fclose(fp);
|
||||
if(!c->rsa_key)
|
||||
{
|
||||
syslog(LOG_ERR, _("Reading RSA public key file `%s' failed: %s"),
|
||||
fname, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
free(fname);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Else, check if a harnessed public key is in the config file */
|
||||
|
||||
asprintf(&fname, "%s/hosts/%s", confbase, c->name);
|
||||
if((fp = fopen(fname, "r")))
|
||||
{
|
||||
c->rsa_key = PEM_read_RSAPublicKey(fp, &c->rsa_key, NULL, NULL);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
free(fname);
|
||||
|
||||
if(c->rsa_key)
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
syslog(LOG_ERR, _("No public key for %s specified!"), c->name);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int read_rsa_private_key(void)
|
||||
{
|
||||
FILE *fp;
|
||||
char *fname, *key;
|
||||
cp
|
||||
if(get_config_string(lookup_config(config_tree, "PrivateKey"), &key))
|
||||
{
|
||||
myself->connection->rsa_key = RSA_new();
|
||||
BN_hex2bn(&myself->connection->rsa_key->d, key);
|
||||
BN_hex2bn(&myself->connection->rsa_key->e, "FFFF");
|
||||
free(key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!get_config_string(lookup_config(config_tree, "PrivateKeyFile"), &fname))
|
||||
asprintf(&fname, "%s/rsa_key.priv", confbase);
|
||||
|
||||
if(is_safe_path(fname))
|
||||
{
|
||||
if((fp = fopen(fname, "r")) == NULL)
|
||||
{
|
||||
syslog(LOG_ERR, _("Error reading RSA private key file `%s': %s"),
|
||||
fname, strerror(errno));
|
||||
free(fname);
|
||||
return -1;
|
||||
}
|
||||
free(fname);
|
||||
myself->connection->rsa_key = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
|
||||
fclose(fp);
|
||||
if(!myself->connection->rsa_key)
|
||||
{
|
||||
syslog(LOG_ERR, _("Reading RSA private key file `%s' failed: %s"),
|
||||
fname, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
free(fname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int check_rsa_key(RSA *rsa_key)
|
||||
{
|
||||
char *test1, *test2, *test3;
|
||||
cp
|
||||
if(rsa_key->p && rsa_key->q)
|
||||
{
|
||||
if(RSA_check_key(rsa_key) != 1)
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
test1 = xmalloc(RSA_size(rsa_key));
|
||||
test2 = xmalloc(RSA_size(rsa_key));
|
||||
test3 = xmalloc(RSA_size(rsa_key));
|
||||
|
||||
if(RSA_public_encrypt(RSA_size(rsa_key), test1, test2, rsa_key, RSA_NO_PADDING) != RSA_size(rsa_key))
|
||||
return -1;
|
||||
|
||||
if(RSA_private_decrypt(RSA_size(rsa_key), test2, test3, rsa_key, RSA_NO_PADDING) != RSA_size(rsa_key))
|
||||
return -1;
|
||||
|
||||
if(memcmp(test1, test3, RSA_size(rsa_key)))
|
||||
return -1;
|
||||
}
|
||||
cp
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Configure node_t myself and set up the local sockets (listen only)
|
||||
*/
|
||||
int setup_myself(void)
|
||||
{
|
||||
config_t *cfg;
|
||||
subnet_t *subnet;
|
||||
char *name, *mode, *afname, *cipher, *digest;
|
||||
struct addrinfo hint, *ai;
|
||||
int choice;
|
||||
cp
|
||||
myself = new_node();
|
||||
myself->connection = new_connection();
|
||||
init_configuration(&myself->connection->config_tree);
|
||||
|
||||
asprintf(&myself->hostname, _("MYSELF"));
|
||||
asprintf(&myself->connection->hostname, _("MYSELF"));
|
||||
|
||||
myself->connection->options = 0;
|
||||
myself->connection->protocol_version = PROT_CURRENT;
|
||||
|
||||
if(!get_config_string(lookup_config(config_tree, "Name"), &name)) /* Not acceptable */
|
||||
{
|
||||
syslog(LOG_ERR, _("Name for tinc daemon required!"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(check_id(name))
|
||||
{
|
||||
syslog(LOG_ERR, _("Invalid name for myself!"));
|
||||
free(name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
myself->name = name;
|
||||
myself->connection->name = xstrdup(name);
|
||||
|
||||
cp
|
||||
if(read_rsa_private_key())
|
||||
return -1;
|
||||
|
||||
if(read_connection_config(myself->connection))
|
||||
{
|
||||
syslog(LOG_ERR, _("Cannot open host configuration file for myself!"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(read_rsa_public_key(myself->connection))
|
||||
return -1;
|
||||
cp
|
||||
|
||||
if(check_rsa_key(myself->connection->rsa_key))
|
||||
{
|
||||
syslog(LOG_ERR, _("Invalid public/private keypair!"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!get_config_string(lookup_config(myself->connection->config_tree, "Port"), &myport))
|
||||
asprintf(&myport, "655");
|
||||
|
||||
/* Read in all the subnets specified in the host configuration file */
|
||||
|
||||
cfg = lookup_config(myself->connection->config_tree, "Subnet");
|
||||
|
||||
while(cfg)
|
||||
{
|
||||
if(!get_config_subnet(cfg, &subnet))
|
||||
return -1;
|
||||
|
||||
subnet_add(myself, subnet);
|
||||
|
||||
cfg = lookup_config_next(myself->connection->config_tree, cfg);
|
||||
}
|
||||
|
||||
cp
|
||||
/* Check some options */
|
||||
|
||||
if(get_config_bool(lookup_config(config_tree, "IndirectData"), &choice))
|
||||
if(choice)
|
||||
myself->options |= OPTION_INDIRECT;
|
||||
|
||||
if(get_config_bool(lookup_config(config_tree, "TCPOnly"), &choice))
|
||||
if(choice)
|
||||
myself->options |= OPTION_TCPONLY;
|
||||
|
||||
if(get_config_bool(lookup_config(myself->connection->config_tree, "IndirectData"), &choice))
|
||||
if(choice)
|
||||
myself->options |= OPTION_INDIRECT;
|
||||
|
||||
if(get_config_bool(lookup_config(myself->connection->config_tree, "TCPOnly"), &choice))
|
||||
if(choice)
|
||||
myself->options |= OPTION_TCPONLY;
|
||||
|
||||
if(myself->options & OPTION_TCPONLY)
|
||||
myself->options |= OPTION_INDIRECT;
|
||||
|
||||
if(get_config_string(lookup_config(config_tree, "Mode"), &mode))
|
||||
{
|
||||
if(!strcasecmp(mode, "router"))
|
||||
routing_mode = RMODE_ROUTER;
|
||||
else if (!strcasecmp(mode, "switch"))
|
||||
routing_mode = RMODE_SWITCH;
|
||||
else if (!strcasecmp(mode, "hub"))
|
||||
routing_mode = RMODE_HUB;
|
||||
else
|
||||
{
|
||||
syslog(LOG_ERR, _("Invalid routing mode!"));
|
||||
return -1;
|
||||
}
|
||||
free(mode);
|
||||
}
|
||||
else
|
||||
routing_mode = RMODE_ROUTER;
|
||||
|
||||
if(get_config_int(lookup_config(myself->connection->config_tree, "MaxTimeout"), &maxtimeout))
|
||||
{
|
||||
if(maxtimeout <= 0)
|
||||
{
|
||||
syslog(LOG_ERR, _("Bogus maximum timeout!"));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
maxtimeout = 900;
|
||||
|
||||
if(get_config_string(lookup_config(config_tree, "AddressFamily"), &afname))
|
||||
{
|
||||
if(!strcasecmp(afname, "IPv4"))
|
||||
addressfamily = AF_INET;
|
||||
else if (!strcasecmp(afname, "IPv6"))
|
||||
addressfamily = AF_INET6;
|
||||
else if (!strcasecmp(afname, "any"))
|
||||
addressfamily = AF_UNSPEC;
|
||||
else
|
||||
{
|
||||
syslog(LOG_ERR, _("Invalid address family!"));
|
||||
return -1;
|
||||
}
|
||||
free(afname);
|
||||
}
|
||||
else
|
||||
addressfamily = AF_INET;
|
||||
|
||||
get_config_bool(lookup_config(config_tree, "Hostnames"), &hostnames);
|
||||
cp
|
||||
/* Generate packet encryption key */
|
||||
|
||||
if(get_config_string(lookup_config(myself->connection->config_tree, "Cipher"), &cipher))
|
||||
{
|
||||
if(!strcasecmp(cipher, "none"))
|
||||
{
|
||||
myself->cipher = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!(myself->cipher = EVP_get_cipherbyname(cipher)))
|
||||
{
|
||||
syslog(LOG_ERR, _("Unrecognized cipher type!"));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
myself->cipher = EVP_bf_cbc();
|
||||
|
||||
if(myself->cipher)
|
||||
myself->keylength = myself->cipher->key_len + myself->cipher->iv_len;
|
||||
else
|
||||
myself->keylength = 1;
|
||||
|
||||
myself->key = (char *)xmalloc(myself->keylength);
|
||||
RAND_pseudo_bytes(myself->key, myself->keylength);
|
||||
|
||||
if(!get_config_int(lookup_config(config_tree, "KeyExpire"), &keylifetime))
|
||||
keylifetime = 3600;
|
||||
|
||||
keyexpires = time(NULL) + keylifetime;
|
||||
|
||||
/* Check if we want to use message authentication codes... */
|
||||
|
||||
if(get_config_string(lookup_config(myself->connection->config_tree, "Digest"), &digest))
|
||||
{
|
||||
if(!strcasecmp(digest, "none"))
|
||||
{
|
||||
myself->digest = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!(myself->digest = EVP_get_digestbyname(digest)))
|
||||
{
|
||||
syslog(LOG_ERR, _("Unrecognized digest type!"));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
myself->digest = EVP_sha1();
|
||||
|
||||
if(get_config_int(lookup_config(myself->connection->config_tree, "MACLength"), &myself->maclength))
|
||||
{
|
||||
if(myself->digest)
|
||||
{
|
||||
if(myself->maclength > myself->digest->md_size)
|
||||
{
|
||||
syslog(LOG_ERR, _("MAC length exceeds size of digest!"));
|
||||
return -1;
|
||||
}
|
||||
else if (myself->maclength < 0)
|
||||
{
|
||||
syslog(LOG_ERR, _("Bogus MAC length!"));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
myself->maclength = 4;
|
||||
|
||||
/* Compression */
|
||||
|
||||
if(get_config_int(lookup_config(myself->connection->config_tree, "Compression"), &myself->compression))
|
||||
{
|
||||
if(myself->compression < 0 || myself->compression > 9)
|
||||
{
|
||||
syslog(LOG_ERR, _("Bogus compression level!"));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
myself->compression = 0;
|
||||
cp
|
||||
/* Done */
|
||||
|
||||
myself->nexthop = myself;
|
||||
myself->via = myself;
|
||||
myself->status.active = 1;
|
||||
node_add(myself);
|
||||
|
||||
graph();
|
||||
|
||||
cp
|
||||
/* Open sockets */
|
||||
|
||||
hint.ai_family = (addressfamily == AF_UNSPEC)?AF_INET6:addressfamily;
|
||||
hint.ai_socktype = SOCK_STREAM;
|
||||
hint.ai_protocol = IPPROTO_TCP;
|
||||
hint.ai_flags = AI_PASSIVE;
|
||||
|
||||
if(getaddrinfo(NULL, myport, &hint, &ai) || !ai)
|
||||
{
|
||||
syslog(LOG_ERR, _("System call `%s' failed: %s"), "getaddrinfo", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if((tcp_socket = setup_listen_socket((sockaddr_t *)ai->ai_addr)) < 0)
|
||||
{
|
||||
syslog(LOG_ERR, _("Unable to set up a listening TCP socket!"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if((udp_socket = setup_vpn_in_socket((sockaddr_t *)ai->ai_addr)) < 0)
|
||||
{
|
||||
syslog(LOG_ERR, _("Unable to set up a listening UDP socket!"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
freeaddrinfo(ai);
|
||||
|
||||
syslog(LOG_NOTICE, _("Ready: listening on port %s"), myport);
|
||||
cp
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
setup all initial network connections
|
||||
*/
|
||||
int setup_network_connections(void)
|
||||
{
|
||||
cp
|
||||
init_connections();
|
||||
init_subnets();
|
||||
init_nodes();
|
||||
init_edges();
|
||||
init_events();
|
||||
|
||||
if(get_config_int(lookup_config(config_tree, "PingTimeout"), &pingtimeout))
|
||||
{
|
||||
if(pingtimeout < 1)
|
||||
{
|
||||
pingtimeout = 86400;
|
||||
}
|
||||
}
|
||||
else
|
||||
pingtimeout = 60;
|
||||
|
||||
if(setup_device() < 0)
|
||||
return -1;
|
||||
|
||||
/* Run tinc-up script to further initialize the tap interface */
|
||||
execute_script("tinc-up");
|
||||
|
||||
if(setup_myself() < 0)
|
||||
return -1;
|
||||
|
||||
try_outgoing_connections();
|
||||
cp
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
close all open network connections
|
||||
*/
|
||||
void close_network_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->outgoing)
|
||||
free(c->outgoing->name), free(c->outgoing);
|
||||
terminate_connection(c, 0);
|
||||
}
|
||||
|
||||
if(myself && myself->connection)
|
||||
terminate_connection(myself->connection, 0);
|
||||
|
||||
close(udp_socket);
|
||||
close(tcp_socket);
|
||||
|
||||
exit_events();
|
||||
exit_edges();
|
||||
exit_subnets();
|
||||
exit_nodes();
|
||||
exit_connections();
|
||||
|
||||
execute_script("tinc-down");
|
||||
|
||||
close_device();
|
||||
cp
|
||||
return;
|
||||
}
|
456
src/net_socket.c
Normal file
456
src/net_socket.c
Normal file
|
@ -0,0 +1,456 @@
|
|||
/*
|
||||
net_socket.c -- Handle various kinds of sockets.
|
||||
Copyright (C) 1998-2002 Ivo Timmermans <itimmermans@bigfoot.com>,
|
||||
2000-2002 Guus Sliepen <guus@sliepen.warande.net>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
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.1 2002/02/18 16:25:16 guus Exp $
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#ifdef HAVE_LINUX
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/tcp.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
/* SunOS really wants sys/socket.h BEFORE net/if.h,
|
||||
and FreeBSD wants these lines below the rest. */
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/if.h>
|
||||
|
||||
#include <utils.h>
|
||||
#include <xalloc.h>
|
||||
#include <avl_tree.h>
|
||||
#include <list.h>
|
||||
|
||||
#include "conf.h"
|
||||
#include "connection.h"
|
||||
#include "meta.h"
|
||||
#include "net.h"
|
||||
#include "netutl.h"
|
||||
#include "process.h"
|
||||
#include "protocol.h"
|
||||
#include "subnet.h"
|
||||
#include "graph.h"
|
||||
#include "process.h"
|
||||
#include "route.h"
|
||||
#include "device.h"
|
||||
#include "event.h"
|
||||
|
||||
#include "system.h"
|
||||
|
||||
int addressfamily = AF_INET;
|
||||
int maxtimeout = 900;
|
||||
int seconds_till_retry = 5;
|
||||
|
||||
int tcp_socket = -1;
|
||||
int udp_socket = -1;
|
||||
/* Setup sockets */
|
||||
|
||||
int setup_listen_socket(sockaddr_t *sa)
|
||||
{
|
||||
int nfd, flags;
|
||||
char *addrstr;
|
||||
int option;
|
||||
#ifdef HAVE_LINUX
|
||||
char *interface;
|
||||
#endif
|
||||
cp
|
||||
if((nfd = socket(sa->sa.sa_family, SOCK_STREAM, IPPROTO_TCP)) < 0)
|
||||
{
|
||||
syslog(LOG_ERR, _("Creating metasocket 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;
|
||||
}
|
||||
|
||||
/* Optimize TCP settings */
|
||||
|
||||
option = 1;
|
||||
setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option));
|
||||
#ifdef HAVE_LINUX
|
||||
setsockopt(nfd, SOL_TCP, TCP_NODELAY, &option, sizeof(option));
|
||||
|
||||
option = IPTOS_LOWDELAY;
|
||||
setsockopt(nfd, SOL_IP, IP_TOS, &option, sizeof(option));
|
||||
|
||||
if(get_config_string(lookup_config(config_tree, "BindToInterface"), &interface))
|
||||
if(setsockopt(nfd, SOL_SOCKET, SO_BINDTODEVICE, interface, strlen(interface)))
|
||||
{
|
||||
close(nfd);
|
||||
syslog(LOG_ERR, _("Can't bind to interface %s: %s"), interface, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(bind(nfd, &sa->sa, sizeof(*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;
|
||||
#ifdef HAVE_LINUX
|
||||
char *interface;
|
||||
#endif
|
||||
cp
|
||||
if((nfd = socket(sa->sa.sa_family, SOCK_DGRAM, IPPROTO_UDP)) < 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));
|
||||
#ifdef HAVE_LINUX
|
||||
if(get_config_string(lookup_config(config_tree, "BindToInterface"), &interface))
|
||||
if(setsockopt(nfd, SOL_SOCKET, SO_BINDTODEVICE, interface, strlen(interface)))
|
||||
{
|
||||
close(nfd);
|
||||
syslog(LOG_ERR, _("Can't bind to interface %s: %s"), interface, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(bind(nfd, &sa->sa, sizeof(*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;
|
||||
}
|
||||
|
||||
void retry_outgoing(outgoing_t *outgoing)
|
||||
{
|
||||
event_t *event;
|
||||
cp
|
||||
outgoing->timeout += 5;
|
||||
if(outgoing->timeout > maxtimeout)
|
||||
outgoing->timeout = maxtimeout;
|
||||
|
||||
event = new_event();
|
||||
event->handler = (event_handler_t)setup_outgoing_connection;
|
||||
event->time = time(NULL) + 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);
|
||||
cp
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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 */
|
||||
|
||||
#ifdef HAVE_LINUX
|
||||
option = 1;
|
||||
setsockopt(c->socket, SOL_TCP, TCP_NODELAY, &option, sizeof(option));
|
||||
|
||||
option = IPTOS_LOWDELAY;
|
||||
setsockopt(c->socket, SOL_IP, IP_TOS, &option, sizeof(option));
|
||||
#endif
|
||||
|
||||
/* Connect */
|
||||
|
||||
if(connect(c->socket, &c->address.sa, sizeof(c->address)) == -1)
|
||||
{
|
||||
close(c->socket);
|
||||
syslog(LOG_ERR, _("%s: %s"), 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;
|
||||
}
|
||||
|
||||
|
||||
void finish_connecting(connection_t *c)
|
||||
{
|
||||
cp
|
||||
if(debug_lvl >= DEBUG_CONNECTIONS)
|
||||
syslog(LOG_INFO, _("Connected to %s (%s)"), c->name, c->hostname);
|
||||
|
||||
c->last_ping_time = time(NULL);
|
||||
|
||||
send_id(c);
|
||||
cp
|
||||
}
|
||||
|
||||
void do_outgoing_connection(connection_t *c)
|
||||
{
|
||||
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;
|
||||
do_prune = 1;
|
||||
retry_outgoing(c->outgoing);
|
||||
return;
|
||||
}
|
||||
|
||||
get_config_string(c->outgoing->cfg, &address);
|
||||
|
||||
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->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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
c->hostname = sockaddr2hostname(&c->address);
|
||||
|
||||
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);
|
||||
|
||||
if(c->socket == -1)
|
||||
{
|
||||
if(debug_lvl >= DEBUG_CONNECTIONS)
|
||||
syslog(LOG_ERR, _("Creating socket for %s failed: %s"), c->hostname, strerror(errno));
|
||||
|
||||
goto begin;
|
||||
}
|
||||
|
||||
/* Optimize TCP settings */
|
||||
|
||||
#ifdef HAVE_LINUX
|
||||
option = 1;
|
||||
setsockopt(c->socket, SOL_TCP, TCP_NODELAY, &option, sizeof(option));
|
||||
|
||||
option = IPTOS_LOWDELAY;
|
||||
setsockopt(c->socket, SOL_IP, IP_TOS, &option, sizeof(option));
|
||||
#endif
|
||||
|
||||
/* Non-blocking */
|
||||
|
||||
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, sizeof(c->address));
|
||||
|
||||
if(result == -1)
|
||||
{
|
||||
if(errno == EINPROGRESS)
|
||||
{
|
||||
c->status.connecting = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
close(c->socket);
|
||||
|
||||
if(debug_lvl >= DEBUG_CONNECTIONS)
|
||||
syslog(LOG_ERR, _("%s: %s"), c->hostname, strerror(errno));
|
||||
|
||||
goto begin;
|
||||
}
|
||||
|
||||
finish_connecting(c);
|
||||
return;
|
||||
cp
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
c = new_connection();
|
||||
c->name = xstrdup(outgoing->name);
|
||||
|
||||
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 = time(NULL);
|
||||
|
||||
connection_add(c);
|
||||
|
||||
do_outgoing_connection(c);
|
||||
}
|
||||
|
||||
/*
|
||||
accept a new tcp connect and create a
|
||||
new connection
|
||||
*/
|
||||
int handle_new_meta_connection()
|
||||
{
|
||||
connection_t *c;
|
||||
sockaddr_t sa;
|
||||
int fd, len = sizeof(sa);
|
||||
cp
|
||||
if((fd = accept(tcp_socket, &sa.sa, &len)) < 0)
|
||||
{
|
||||
syslog(LOG_ERR, _("Accepting a new connection failed: %s"), strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
c = new_connection();
|
||||
|
||||
c->address = sa;
|
||||
c->hostname = sockaddr2hostname(&sa);
|
||||
c->socket = fd;
|
||||
c->last_ping_time = time(NULL);
|
||||
|
||||
if(debug_lvl >= DEBUG_CONNECTIONS)
|
||||
syslog(LOG_NOTICE, _("Connection from %s"), c->hostname);
|
||||
|
||||
connection_add(c);
|
||||
|
||||
c->allow_request = ID;
|
||||
send_id(c);
|
||||
cp
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
|
@ -17,12 +17,13 @@
|
|||
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/02/12 14:40:12 guus Exp $
|
||||
$Id: device.c,v 1.1.2.2 2002/02/18 16:25:19 guus Exp $
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/stat.h>
|
||||
|
@ -70,7 +71,7 @@ int setup_device(void)
|
|||
cp
|
||||
if((device_fd = open(device, O_RDWR | O_NONBLOCK)) < 0)
|
||||
{
|
||||
syslog(LOG_ERR, _("Could not open %s: %m"), device);
|
||||
syslog(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
cp
|
||||
|
@ -107,7 +108,7 @@ cp
|
|||
|
||||
if((lenin = readv(device_fd, vector, 2)) <= 0)
|
||||
{
|
||||
syslog(LOG_ERR, _("Error while reading from %s %s: %m"), device_info, device);
|
||||
syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, device, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -145,7 +146,7 @@ cp
|
|||
|
||||
if(writev(device_fd, vector, 2) < 0)
|
||||
{
|
||||
syslog(LOG_ERR, _("Can't write to %s %s: %m"), device_info, device);
|
||||
syslog(LOG_ERR, _("Can't write to %s %s: %s"), device_info, device, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
208
src/netutl.c
208
src/netutl.c
|
@ -17,7 +17,7 @@
|
|||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
$Id: netutl.c,v 1.12.4.23 2002/02/11 10:16:18 guus Exp $
|
||||
$Id: netutl.c,v 1.12.4.24 2002/02/18 16:25:16 guus Exp $
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
@ -28,6 +28,7 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <sys/socket.h>
|
||||
#include <syslog.h>
|
||||
#include <arpa/inet.h>
|
||||
|
@ -42,64 +43,183 @@
|
|||
|
||||
#include "system.h"
|
||||
|
||||
char *hostlookup(unsigned long addr)
|
||||
{
|
||||
char *name;
|
||||
struct hostent *host = NULL;
|
||||
struct in_addr in;
|
||||
int lookup_hostname = 0;
|
||||
cp
|
||||
in.s_addr = addr;
|
||||
|
||||
get_config_bool(lookup_config(config_tree, "Hostnames"), &lookup_hostname);
|
||||
|
||||
if(lookup_hostname)
|
||||
host = gethostbyaddr((char *)&in, sizeof(in), AF_INET);
|
||||
|
||||
if(!lookup_hostname || !host)
|
||||
{
|
||||
asprintf(&name, "%s", inet_ntoa(in));
|
||||
}
|
||||
else
|
||||
{
|
||||
asprintf(&name, "%s", host->h_name);
|
||||
}
|
||||
cp
|
||||
return name;
|
||||
}
|
||||
int hostnames = 0;
|
||||
|
||||
/*
|
||||
Turn a string into an IP address
|
||||
return NULL on failure
|
||||
Should support IPv6 and other stuff in the future.
|
||||
Turn a string into a struct addrinfo.
|
||||
Return NULL on failure.
|
||||
*/
|
||||
ipv4_t str2address(char *str)
|
||||
struct addrinfo *str2addrinfo(char *address, char *service, int socktype)
|
||||
{
|
||||
ipv4_t address;
|
||||
struct hostent *h;
|
||||
struct addrinfo hint, *ai;
|
||||
int err;
|
||||
cp
|
||||
if(!(h = gethostbyname(str)))
|
||||
memset(&hint, 0, sizeof(hint));
|
||||
|
||||
hint.ai_family = addressfamily;
|
||||
hint.ai_socktype = socktype;
|
||||
|
||||
if((err = getaddrinfo(address, service, &hint, &ai)))
|
||||
{
|
||||
if(debug_lvl >= DEBUG_ERROR)
|
||||
syslog(LOG_WARNING, _("Error looking up `%s': %s\n"), str, strerror(errno));
|
||||
|
||||
return 0;
|
||||
syslog(LOG_WARNING, _("Error looking up %s port %s: %s\n"), address, service, gai_strerror(err));
|
||||
cp_trace();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
address = ntohl(*((ipv4_t*)(h->h_addr_list[0])));
|
||||
cp
|
||||
return address;
|
||||
return ai;
|
||||
}
|
||||
|
||||
char *address2str(ipv4_t address)
|
||||
sockaddr_t str2sockaddr(char *address, char *port)
|
||||
{
|
||||
struct addrinfo hint, *ai;
|
||||
sockaddr_t result;
|
||||
int err;
|
||||
cp
|
||||
memset(&hint, 0, sizeof(hint));
|
||||
|
||||
hint.ai_family = AF_UNSPEC;
|
||||
hint.ai_flags = AI_NUMERICHOST;
|
||||
hint.ai_socktype = SOCK_STREAM;
|
||||
|
||||
if((err = getaddrinfo(address, port, &hint, &ai) || !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);
|
||||
cp
|
||||
return result;
|
||||
}
|
||||
|
||||
void sockaddr2str(sockaddr_t *sa, char **addrstr, char **portstr)
|
||||
{
|
||||
char address[NI_MAXHOST];
|
||||
char port[NI_MAXSERV];
|
||||
int err;
|
||||
cp
|
||||
if((err = getnameinfo((struct sockaddr *)sa, sizeof(sockaddr_t), address, sizeof(address), port, sizeof(port), NI_NUMERICHOST|NI_NUMERICSERV)))
|
||||
{
|
||||
syslog(LOG_ERR, _("Error while translating addresses: %s"), gai_strerror(err));
|
||||
cp_trace();
|
||||
raise(SIGFPE);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
*addrstr = xstrdup(address);
|
||||
*portstr = xstrdup(port);
|
||||
cp
|
||||
}
|
||||
|
||||
char *sockaddr2hostname(sockaddr_t *sa)
|
||||
{
|
||||
char *str;
|
||||
char address[NI_MAXHOST] = "unknown";
|
||||
char port[NI_MAXSERV] = "unknown";
|
||||
int err;
|
||||
cp
|
||||
asprintf(&str, "%hu.%hu.%hu.%hu",
|
||||
(unsigned short int)((address >> 24) & 255),
|
||||
(unsigned short int)((address >> 16) & 255),
|
||||
(unsigned short int)((address >> 8) & 255),
|
||||
(unsigned short int)(address & 255));
|
||||
if((err = getnameinfo((struct sockaddr *)sa, sizeof(sockaddr_t), address, sizeof(address), port, sizeof(port), hostnames?0:(NI_NUMERICHOST|NI_NUMERICSERV))))
|
||||
{
|
||||
syslog(LOG_ERR, _("Error while looking up hostname: %s"), gai_strerror(err));
|
||||
}
|
||||
|
||||
asprintf(&str, _("%s port %s"), address, port);
|
||||
cp
|
||||
return str;
|
||||
}
|
||||
|
||||
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:
|
||||
return memcmp(&a->in, &b->in, sizeof(a->in));
|
||||
case AF_INET6:
|
||||
return memcmp(&a->in6, &b->in6, sizeof(a->in6));
|
||||
default:
|
||||
syslog(LOG_ERR, _("sockaddrcmp() was called with unknown address family %d, exitting!"), a->sa.sa_family);
|
||||
cp_trace();
|
||||
raise(SIGFPE);
|
||||
exit(0);
|
||||
}
|
||||
cp
|
||||
}
|
||||
|
||||
/* Subnet mask handling */
|
||||
|
||||
int maskcmp(char *a, char *b, int masklen, int len)
|
||||
{
|
||||
int i, m, result;
|
||||
cp
|
||||
for(m = masklen, i = 0; m > 8; m -= 8, i++)
|
||||
if((result = a[i] - b[i]))
|
||||
return result;
|
||||
|
||||
if(m)
|
||||
return (a[i] & (0x100 - (m << 1))) - (b[i] & (0x100 - (m << 1)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mask(char *a, int masklen, int len)
|
||||
{
|
||||
int i;
|
||||
cp
|
||||
i = masklen / 8;
|
||||
masklen %= 8;
|
||||
|
||||
if(masklen)
|
||||
a[i++] &= (0x100 - (masklen << 1));
|
||||
|
||||
for(; i < len; i++)
|
||||
a[i] = 0;
|
||||
}
|
||||
|
||||
void maskcpy(char *a, char *b, int masklen, int len)
|
||||
{
|
||||
int i, m;
|
||||
cp
|
||||
for(m = masklen, i = 0; m > 8; m -= 8, i++)
|
||||
a[i] = b[i];
|
||||
|
||||
if(m)
|
||||
{
|
||||
a[i] = b[i] & (0x100 - (m << 1));
|
||||
i++;
|
||||
}
|
||||
|
||||
for(; i < len; i++)
|
||||
a[i] = 0;
|
||||
}
|
||||
|
||||
int maskcheck(char *a, int masklen, int len)
|
||||
{
|
||||
int i;
|
||||
cp
|
||||
i = masklen / 8;
|
||||
masklen %= 8;
|
||||
|
||||
if(masklen)
|
||||
if(a[i++] & ~(0x100 - (masklen << 1)))
|
||||
return -1;
|
||||
|
||||
for(; i < len; i++)
|
||||
if(a[i] != 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
19
src/netutl.h
19
src/netutl.h
|
@ -17,16 +17,29 @@
|
|||
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.9 2002/02/11 10:16:18 guus Exp $
|
||||
$Id: netutl.h,v 1.2.4.10 2002/02/18 16:25:16 guus Exp $
|
||||
*/
|
||||
|
||||
#ifndef __TINC_NETUTL_H__
|
||||
#define __TINC_NETUTL_H__
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#include "net.h"
|
||||
|
||||
extern int hostnames;
|
||||
|
||||
extern char *hostlookup(unsigned long);
|
||||
extern ipv4_t str2address(char*);
|
||||
extern char *address2str(ipv4_t);
|
||||
extern struct addrinfo *str2addrinfo(char *, char *, int);
|
||||
extern sockaddr_t str2sockaddr(char *, char *);
|
||||
extern void sockaddr2str(sockaddr_t *, char **, char **);
|
||||
extern char *sockaddr2hostname(sockaddr_t *);
|
||||
extern int sockaddrcmp(sockaddr_t *, sockaddr_t *);
|
||||
extern int maskcmp(char *, char *, int, int);
|
||||
extern void maskcpy(char *, char *, int, int);
|
||||
extern void mask(char *, int, int);
|
||||
extern int maskcheck(char *, int, int);
|
||||
|
||||
#endif /* __TINC_NETUTL_H__ */
|
||||
|
|
28
src/node.c
28
src/node.c
|
@ -17,7 +17,7 @@
|
|||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
$Id: node.c,v 1.1.2.9 2002/02/11 15:59:18 guus Exp $
|
||||
$Id: node.c,v 1.1.2.10 2002/02/18 16:25:16 guus Exp $
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include <avl_tree.h>
|
||||
#include "node.h"
|
||||
#include "netutl.h"
|
||||
#include "net.h"
|
||||
#include <utils.h>
|
||||
#include <xalloc.h>
|
||||
|
@ -45,14 +46,13 @@ int node_compare(node_t *a, node_t *b)
|
|||
|
||||
int node_udp_compare(node_t *a, node_t *b)
|
||||
{
|
||||
if(a->address < b->address)
|
||||
return -1;
|
||||
if (a->address > b->address)
|
||||
return 1;
|
||||
if (a->port < b->port)
|
||||
return -1;
|
||||
if (a->port > b->port)
|
||||
return 1;
|
||||
int result;
|
||||
cp
|
||||
result = sockaddrcmp(&a->address, &b->address);
|
||||
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
return (a->name && b->name)?strcmp(a->name, b->name):0;
|
||||
}
|
||||
|
||||
|
@ -143,13 +143,13 @@ cp
|
|||
return avl_search(node_tree, &n);
|
||||
}
|
||||
|
||||
node_t *lookup_node_udp(ipv4_t address, port_t port)
|
||||
node_t *lookup_node_udp(sockaddr_t *sa)
|
||||
{
|
||||
node_t n;
|
||||
cp
|
||||
n.address = *sa;
|
||||
n.name = NULL;
|
||||
n.address = address;
|
||||
n.port = port;
|
||||
|
||||
return avl_search(node_udp_tree, &n);
|
||||
}
|
||||
|
||||
|
@ -163,8 +163,8 @@ cp
|
|||
for(node = node_tree->head; node; node = node->next)
|
||||
{
|
||||
n = (node_t *)node->data;
|
||||
syslog(LOG_DEBUG, _(" %s at %s port %hd cipher %d digest %d maclength %d compression %d options %ld status %04x nexthop %s via %s"),
|
||||
n->name, n->hostname, n->port, n->cipher?n->cipher->nid:0, n->digest?n->digest->type:0, n->maclength, n->compression, n->options,
|
||||
syslog(LOG_DEBUG, _(" %s at %s cipher %d digest %d maclength %d compression %d options %ld 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:"-");
|
||||
}
|
||||
|
||||
|
|
13
src/node.h
13
src/node.h
|
@ -17,7 +17,7 @@
|
|||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
$Id: node.h,v 1.1.2.11 2002/02/11 15:59:18 guus Exp $
|
||||
$Id: node.h,v 1.1.2.12 2002/02/18 16:25:16 guus Exp $
|
||||
*/
|
||||
|
||||
#ifndef __TINC_NODE_H__
|
||||
|
@ -41,8 +41,7 @@ typedef struct node_t {
|
|||
char *name; /* name of this node */
|
||||
long int options; /* options turned on for this node */
|
||||
|
||||
ipv4_t address; /* his real (internet) ip to send UDP packets to */
|
||||
port_t port; /* port number of UDP connection */
|
||||
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;
|
||||
|
@ -78,11 +77,11 @@ extern avl_tree_t *node_udp_tree;
|
|||
extern void init_nodes(void);
|
||||
extern void exit_nodes(void);
|
||||
extern node_t *new_node(void);
|
||||
extern void free_node(node_t *n);
|
||||
extern void node_add(node_t *n);
|
||||
extern void node_del(node_t *n);
|
||||
extern void free_node(node_t *);
|
||||
extern void node_add(node_t *);
|
||||
extern void node_del(node_t *);
|
||||
extern node_t *lookup_node(char *);
|
||||
extern node_t *lookup_node_udp(ipv4_t, port_t);
|
||||
extern node_t *lookup_node_udp(sockaddr_t *);
|
||||
extern void dump_nodes(void);
|
||||
|
||||
#endif /* __TINC_NODE_H__ */
|
||||
|
|
|
@ -17,12 +17,13 @@
|
|||
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/02/11 12:33:01 guus Exp $
|
||||
$Id: device.c,v 1.1.2.5 2002/02/18 16:25:19 guus Exp $
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/stat.h>
|
||||
|
@ -70,7 +71,7 @@ int setup_device(void)
|
|||
cp
|
||||
if((device_fd = open(device, O_RDWR | O_NONBLOCK)) < 0)
|
||||
{
|
||||
syslog(LOG_ERR, _("Could not open %s: %m"), device);
|
||||
syslog(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
cp
|
||||
|
@ -107,7 +108,7 @@ cp
|
|||
|
||||
if((lenin = readv(device_fd, vector, 2)) <= 0)
|
||||
{
|
||||
syslog(LOG_ERR, _("Error while reading from %s %s: %m"), device_info, device);
|
||||
syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, device, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -145,7 +146,7 @@ cp
|
|||
|
||||
if(writev(device_fd, vector, 2) < 0)
|
||||
{
|
||||
syslog(LOG_ERR, _("Can't write to %s %s: %m"), device_info, device);
|
||||
syslog(LOG_ERR, _("Can't write to %s %s: %s"), device_info, device, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -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.34 2002/02/12 14:29:00 guus Exp $
|
||||
$Id: process.c,v 1.1.2.35 2002/02/18 16:25:16 guus Exp $
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
@ -255,8 +255,7 @@ int execute_script(const char *name)
|
|||
cp
|
||||
if((pid = fork()) < 0)
|
||||
{
|
||||
syslog(LOG_ERR, _("System call `%s' failed: %m"),
|
||||
"fork");
|
||||
syslog(LOG_ERR, _("System call `%s' failed: %s"), "fork", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -291,7 +290,7 @@ cp
|
|||
}
|
||||
else
|
||||
{
|
||||
syslog(LOG_ERR, _("System call `%s' failed: %m"), "waitpid");
|
||||
syslog(LOG_ERR, _("System call `%s' failed: %s"), "waitpid", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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_auth.c,v 1.1.4.1 2002/02/11 10:05:58 guus Exp $
|
||||
$Id: protocol_auth.c,v 1.1.4.2 2002/02/18 16:25:16 guus Exp $
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
@ -413,16 +413,17 @@ int send_ack(connection_t *c)
|
|||
to create node_t and edge_t structures. */
|
||||
|
||||
int x;
|
||||
char *addrstr;
|
||||
char *address, *port;
|
||||
struct timeval now;
|
||||
cp
|
||||
/* Estimate weight */
|
||||
|
||||
gettimeofday(&now, NULL);
|
||||
c->estimated_weight = (now.tv_sec - c->start.tv_sec) * 1000 + (now.tv_usec - c->start.tv_usec) / 1000;
|
||||
addrstr = address2str(c->address);
|
||||
x = send_request(c, "%d %hd %s %d %d", ACK, myself->port, addrstr, c->estimated_weight, c->options);
|
||||
free(addrstr);
|
||||
sockaddr2str(&c->address, &address, &port);
|
||||
x = send_request(c, "%d %s %s %s %d %d", ACK, myport, address, port, c->estimated_weight, c->options);
|
||||
free(address);
|
||||
free(port);
|
||||
cp
|
||||
return x;
|
||||
}
|
||||
|
@ -462,15 +463,17 @@ void send_everything(connection_t *c)
|
|||
|
||||
int ack_h(connection_t *c)
|
||||
{
|
||||
port_t hisport;
|
||||
char addrstr[MAX_STRING_SIZE];
|
||||
char address[MAX_STRING_SIZE];
|
||||
char port[MAX_STRING_SIZE];
|
||||
char hisport[MAX_STRING_SIZE];
|
||||
char *hisaddress, *dummy;
|
||||
int weight;
|
||||
int options;
|
||||
node_t *n;
|
||||
connection_t *other;
|
||||
avl_node_t *node;
|
||||
cp
|
||||
if(sscanf(c->buffer, "%*d %hd "MAX_STRING" %d %d", &hisport, addrstr, &weight, &options) != 4)
|
||||
if(sscanf(c->buffer, "%*d "MAX_STRING" "MAX_STRING" "MAX_STRING" %d %d", hisport, address, port, &weight, &options) != 5)
|
||||
{
|
||||
syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "ACK", c->name, c->hostname);
|
||||
return -1;
|
||||
|
@ -484,12 +487,6 @@ cp
|
|||
{
|
||||
n = new_node();
|
||||
n->name = xstrdup(c->name);
|
||||
n->address = c->address;
|
||||
n->hostname = xstrdup(c->hostname);
|
||||
n->port = hisport;
|
||||
|
||||
/* FIXME: Also check if no other tinc daemon uses the same IP and port for UDP traffic */
|
||||
|
||||
node_add(n);
|
||||
}
|
||||
else
|
||||
|
@ -512,17 +509,20 @@ cp
|
|||
/* Create an edge_t for this connection */
|
||||
|
||||
c->edge = new_edge();
|
||||
|
||||
cp
|
||||
c->edge->from.node = myself;
|
||||
c->edge->from.address = str2address(addrstr);
|
||||
c->edge->from.port = myself->port;
|
||||
c->edge->from.tcpaddress = str2sockaddr(address, port);
|
||||
c->edge->from.udpaddress = str2sockaddr(address, myport);
|
||||
c->edge->to.node = n;
|
||||
c->edge->to.address = c->address;
|
||||
c->edge->to.port = hisport;
|
||||
c->edge->to.tcpaddress = c->address;
|
||||
sockaddr2str(&c->address, &hisaddress, &dummy);
|
||||
c->edge->to.udpaddress = str2sockaddr(hisaddress, hisport);
|
||||
free(hisaddress);
|
||||
free(dummy);
|
||||
c->edge->weight = (weight + c->estimated_weight) / 2;
|
||||
c->edge->connection = c;
|
||||
c->edge->options = c->options;
|
||||
|
||||
cp
|
||||
edge_add(c->edge);
|
||||
|
||||
/* Activate this connection */
|
||||
|
|
|
@ -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.1 2002/02/11 10:05:58 guus Exp $
|
||||
$Id: protocol_edge.c,v 1.1.4.2 2002/02/18 16:25:18 guus Exp $
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
@ -48,16 +48,25 @@
|
|||
int send_add_edge(connection_t *c, edge_t *e)
|
||||
{
|
||||
int x;
|
||||
char *from_addrstr, *to_addrstr;
|
||||
char *from_tcpaddress, *from_tcpport, *from_udpaddress, *from_udpport;
|
||||
char *to_tcpaddress, *to_tcpport, *to_udpaddress, *to_udpport;
|
||||
cp
|
||||
from_addrstr = address2str(e->from.address);
|
||||
to_addrstr = address2str(e->to.address);
|
||||
x = send_request(c, "%d %s %s %hd %s %s %hd %lx %d", ADD_EDGE,
|
||||
e->from.node->name, from_addrstr, e->from.port,
|
||||
e->to.node->name, to_addrstr, e->to.port,
|
||||
sockaddr2str(&e->from.tcpaddress, &from_tcpaddress, &from_tcpport);
|
||||
sockaddr2str(&e->from.udpaddress, &from_udpaddress, &from_udpport);
|
||||
sockaddr2str(&e->to.tcpaddress, &to_tcpaddress, &to_tcpport);
|
||||
sockaddr2str(&e->to.udpaddress, &to_udpaddress, &to_udpport);
|
||||
x = send_request(c, "%d %s %s %s %s %s %s %s %s %lx %d", ADD_EDGE,
|
||||
e->from.node->name, from_tcpaddress, from_tcpport, from_udpport,
|
||||
e->to.node->name, to_tcpaddress, to_tcpport, to_udpport,
|
||||
e->options, e->weight);
|
||||
free(from_addrstr);
|
||||
free(to_addrstr);
|
||||
free(from_tcpaddress);
|
||||
free(from_tcpport);
|
||||
free(from_udpaddress);
|
||||
free(from_udpport);
|
||||
free(to_tcpaddress);
|
||||
free(to_tcpport);
|
||||
free(to_udpaddress);
|
||||
free(to_udpport);
|
||||
cp
|
||||
return x;
|
||||
}
|
||||
|
@ -69,18 +78,22 @@ int add_edge_h(connection_t *c)
|
|||
node_t *from, *to;
|
||||
char from_name[MAX_STRING_SIZE];
|
||||
char to_name[MAX_STRING_SIZE];
|
||||
char from_addrstr[MAX_STRING_SIZE];
|
||||
char to_addrstr[MAX_STRING_SIZE];
|
||||
ipv4_t from_address, to_address;
|
||||
port_t from_port, to_port;
|
||||
char from_address[MAX_STRING_SIZE];
|
||||
char from_tcpport[MAX_STRING_SIZE];
|
||||
char from_udpport[MAX_STRING_SIZE];
|
||||
char to_address[MAX_STRING_SIZE];
|
||||
char to_tcpport[MAX_STRING_SIZE];
|
||||
char to_udpport[MAX_STRING_SIZE];
|
||||
sockaddr_t from_tcpaddress, from_udpaddress;
|
||||
sockaddr_t to_tcpaddress, to_udpaddress;
|
||||
long int options;
|
||||
int weight;
|
||||
avl_node_t *node;
|
||||
cp
|
||||
if(sscanf(c->buffer, "%*d "MAX_STRING" "MAX_STRING" %hd "MAX_STRING" "MAX_STRING" %hd %lx %d",
|
||||
from_name, from_addrstr, &from_port,
|
||||
to_name, to_addrstr, &to_port,
|
||||
&options, &weight) != 8)
|
||||
if(sscanf(c->buffer, "%*d "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" %lx %d",
|
||||
from_name, from_address, from_tcpport, from_udpport,
|
||||
to_name, to_address, to_tcpport, to_udpport,
|
||||
&options, &weight) != 10)
|
||||
{
|
||||
syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "ADD_EDGE", c->name, c->hostname);
|
||||
return -1;
|
||||
|
@ -122,8 +135,10 @@ cp
|
|||
|
||||
/* Convert addresses */
|
||||
|
||||
from_address = str2address(from_addrstr);
|
||||
to_address = str2address(to_addrstr);
|
||||
from_tcpaddress = str2sockaddr(from_address, from_tcpport);
|
||||
from_udpaddress = str2sockaddr(from_address, from_udpport);
|
||||
to_tcpaddress = str2sockaddr(to_address, to_tcpport);
|
||||
to_udpaddress = str2sockaddr(to_address, to_udpport);
|
||||
|
||||
/* Check if edge already exists */
|
||||
|
||||
|
@ -132,9 +147,9 @@ cp
|
|||
if(e)
|
||||
{
|
||||
if(e->weight != weight || e->options != options
|
||||
|| ((e->from.node == from) && (e->from.address != from_address || e->from.port != from_port || e->to.address != to_address || e->to.port != to_port))
|
||||
|| ((e->from.node == to) && (e->from.address != to_address || e->from.port != to_port || e->to.address != from_address || e->to.port != from_port))
|
||||
)
|
||||
|| ((e->from.node == from) && (sockaddrcmp(&e->from.tcpaddress, &from_tcpaddress) || sockaddrcmp(&e->from.udpaddress, &from_udpaddress) || sockaddrcmp(&e->to.tcpaddress, &to_tcpaddress) || sockaddrcmp(&e->to.udpaddress, &to_udpaddress)))
|
||||
|| ((e->from.node == to) && (sockaddrcmp(&e->from.tcpaddress, &to_tcpaddress) || sockaddrcmp(&e->from.udpaddress, &to_udpaddress) || sockaddrcmp(&e->to.tcpaddress, &from_tcpaddress) || sockaddrcmp(&e->to.udpaddress, &from_udpaddress)))
|
||||
)
|
||||
{
|
||||
if(from == myself || to == myself)
|
||||
{
|
||||
|
@ -169,11 +184,11 @@ cp
|
|||
|
||||
e = new_edge();
|
||||
e->from.node = from;
|
||||
e->from.address = from_address;
|
||||
e->from.port = from_port;
|
||||
e->from.tcpaddress = from_tcpaddress;
|
||||
e->from.udpaddress = from_udpaddress;
|
||||
e->to.node = to;
|
||||
e->to.address = to_address;
|
||||
e->to.port = to_port;
|
||||
e->to.tcpaddress = to_tcpaddress;
|
||||
e->to.udpaddress = to_udpaddress;
|
||||
e->options = options;
|
||||
e->weight = weight;
|
||||
edge_add(e);
|
||||
|
|
18
src/route.c
18
src/route.c
|
@ -17,7 +17,7 @@
|
|||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
$Id: route.c,v 1.1.2.22 2002/02/10 21:57:54 guus Exp $
|
||||
$Id: route.c,v 1.1.2.23 2002/02/18 16:25:19 guus Exp $
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
@ -105,23 +105,15 @@ cp
|
|||
|
||||
node_t *route_ipv4(vpn_packet_t *packet)
|
||||
{
|
||||
ipv4_t dest;
|
||||
subnet_t *subnet;
|
||||
cp
|
||||
#ifdef HAVE_SOLARIS
|
||||
/* The other form gives bus errors on a SparcStation 20. */
|
||||
dest = ((packet->data[30] * 0x100 + packet->data[31]) * 0x100 + packet->data[32]) * 0x100 + packet->data[33];
|
||||
#else
|
||||
dest = ntohl(*((unsigned long*)(&packet->data[30])));
|
||||
#endif
|
||||
cp
|
||||
subnet = lookup_subnet_ipv4(&dest);
|
||||
subnet = lookup_subnet_ipv4((ipv4_t *)&packet->data[30]);
|
||||
cp
|
||||
if(!subnet)
|
||||
{
|
||||
if(debug_lvl >= DEBUG_TRAFFIC)
|
||||
{
|
||||
syslog(LOG_WARNING, _("Cannot route packet: unknown destination address %d.%d.%d.%d"),
|
||||
syslog(LOG_WARNING, _("Cannot route packet: unknown IPv4 destination address %d.%d.%d.%d"),
|
||||
packet->data[30], packet->data[31], packet->data[32], packet->data[33]);
|
||||
}
|
||||
|
||||
|
@ -163,7 +155,6 @@ void route_arp(vpn_packet_t *packet)
|
|||
struct ether_arp *arp;
|
||||
subnet_t *subnet;
|
||||
unsigned char ipbuf[4];
|
||||
ipv4_t dest;
|
||||
cp
|
||||
/* First, snatch the source address from the ARP packet */
|
||||
|
||||
|
@ -193,8 +184,7 @@ cp
|
|||
|
||||
/* Check if the IP address exists on the VPN */
|
||||
|
||||
dest = ntohl(*((unsigned long*)(arp->arp_tpa)));
|
||||
subnet = lookup_subnet_ipv4(&dest);
|
||||
subnet = lookup_subnet_ipv4((ipv4_t *)arp->arp_tpa);
|
||||
|
||||
if(!subnet)
|
||||
{
|
||||
|
|
|
@ -17,13 +17,14 @@
|
|||
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.6 2002/02/11 14:20:46 guus Exp $
|
||||
$Id: device.c,v 1.1.2.7 2002/02/18 16:25:19 guus Exp $
|
||||
*/
|
||||
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
@ -71,7 +72,7 @@ cp
|
|||
cp
|
||||
if((device_fd = open(device, O_RDWR | O_NONBLOCK)) < 0)
|
||||
{
|
||||
syslog(LOG_ERR, _("Could not open %s: %m"), device);
|
||||
syslog(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
cp
|
||||
|
@ -82,34 +83,34 @@ cp
|
|||
ppa = atoi(ptr);
|
||||
|
||||
if( (ip_fd = open("/dev/ip", O_RDWR, 0)) < 0){
|
||||
syslog(LOG_ERR, _("Could not open /dev/ip: %m"));
|
||||
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: %m"));
|
||||
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: %m"), device);
|
||||
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: %m"));
|
||||
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: %m"), ppa);
|
||||
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: %m"));
|
||||
syslog(LOG_ERR, _("Can't link TUN device to IP: %s"), strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -145,7 +146,7 @@ int read_packet(vpn_packet_t *packet)
|
|||
cp
|
||||
if((lenin = read(device_fd, packet->data + 14, MTU - 14)) <= 0)
|
||||
{
|
||||
syslog(LOG_ERR, _("Error while reading from %s %s: %m"), device_info, device);
|
||||
syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, device, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -176,7 +177,7 @@ cp
|
|||
|
||||
if(write(device_fd, packet->data + 14, packet->len - 14) < 0)
|
||||
{
|
||||
syslog(LOG_ERR, _("Can't write to %s %s: %m"), device_info, packet->len);
|
||||
syslog(LOG_ERR, _("Can't write to %s %s: %s"), device_info, packet->len, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
192
src/subnet.c
192
src/subnet.c
|
@ -17,7 +17,7 @@
|
|||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
$Id: subnet.c,v 1.1.2.29 2002/02/10 21:57:54 guus Exp $
|
||||
$Id: subnet.c,v 1.1.2.30 2002/02/18 16:25:19 guus Exp $
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
@ -30,15 +30,17 @@
|
|||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <utils.h>
|
||||
#include <xalloc.h>
|
||||
#include <avl_tree.h>
|
||||
|
||||
#include "conf.h"
|
||||
#include "net.h"
|
||||
#include "node.h"
|
||||
#include "subnet.h"
|
||||
#include "system.h"
|
||||
#include "netutl.h"
|
||||
|
||||
#include <utils.h>
|
||||
#include <xalloc.h>
|
||||
#include <avl_tree.h>
|
||||
#include "system.h"
|
||||
|
||||
/* lists type of subnet */
|
||||
|
||||
|
@ -54,48 +56,36 @@ cp
|
|||
|
||||
int subnet_compare_ipv4(subnet_t *a, subnet_t *b)
|
||||
{
|
||||
int result;
|
||||
cp
|
||||
/* We compare as if a subnet is a number that equals (address << 32 + netmask). */
|
||||
|
||||
if(a->net.ipv4.address < b->net.ipv4.address)
|
||||
return -1;
|
||||
else if(a->net.ipv4.address > b->net.ipv4.address)
|
||||
return 1;
|
||||
result = memcmp(&a->net.ipv4.address, &b->net.ipv4.address, sizeof(ipv4_t));
|
||||
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
if(a->net.ipv4.mask < b->net.ipv4.mask)
|
||||
return -1;
|
||||
else if(a->net.ipv4.mask > b->net.ipv4.mask)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
return a->net.ipv4.masklength - b->net.ipv4.masklength;
|
||||
}
|
||||
|
||||
int subnet_compare_ipv6(subnet_t *a, subnet_t *b)
|
||||
{
|
||||
int result;
|
||||
cp
|
||||
/* Same as ipv4 case, but with nasty 128 bit addresses */
|
||||
|
||||
result = memcmp(a->net.ipv6.address.x, b->net.ipv6.address.x, sizeof(ipv6_t));
|
||||
result = memcmp(&a->net.ipv6.address, &b->net.ipv6.address, sizeof(ipv6_t));
|
||||
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
result = memcmp(a->net.ipv6.mask.x, b->net.ipv6.mask.x, sizeof(ipv6_t));
|
||||
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
return 0;
|
||||
return a->net.ipv6.masklength - b->net.ipv6.masklength;
|
||||
}
|
||||
|
||||
int subnet_compare(subnet_t *a, subnet_t *b)
|
||||
{
|
||||
int x;
|
||||
int result;
|
||||
cp
|
||||
x = a->type - b->type;
|
||||
if(x)
|
||||
return x;
|
||||
result = a->type - b->type;
|
||||
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
switch(a->type)
|
||||
{
|
||||
|
@ -186,101 +176,58 @@ subnet_t *str2net(char *subnetstr)
|
|||
{
|
||||
int i, l;
|
||||
subnet_t *subnet;
|
||||
unsigned short int x[6];
|
||||
unsigned short int x[8];
|
||||
cp
|
||||
subnet = new_subnet();
|
||||
cp
|
||||
if(sscanf(subnetstr, "%hu.%hu.%hu.%hu/%d",
|
||||
&x[0],
|
||||
&x[1],
|
||||
&x[2],
|
||||
&x[3],
|
||||
&subnet->net.ipv4.masklength) == 5)
|
||||
&x[0], &x[1], &x[2], &x[3],
|
||||
&l) == 5)
|
||||
{
|
||||
subnet->type = SUBNET_IPV4;
|
||||
subnet->net.ipv4.address = (((((x[0] << 8) + x[1]) << 8) + x[2]) << 8) + x[3];
|
||||
subnet->net.ipv4.mask = ~((1 << (32 - subnet->net.ipv4.masklength)) - 1);
|
||||
subnet->net.ipv4.masklength = 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",
|
||||
&subnet->net.ipv6.address.x[0],
|
||||
&subnet->net.ipv6.address.x[1],
|
||||
&subnet->net.ipv6.address.x[2],
|
||||
&subnet->net.ipv6.address.x[3],
|
||||
&subnet->net.ipv6.address.x[4],
|
||||
&subnet->net.ipv6.address.x[5],
|
||||
&subnet->net.ipv6.address.x[6],
|
||||
&subnet->net.ipv6.address.x[7],
|
||||
&subnet->net.ipv6.masklength) == 9)
|
||||
&x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7],
|
||||
&l) == 9)
|
||||
{
|
||||
subnet->type = SUBNET_IPV6;
|
||||
for(l = subnet->net.ipv6.masklength, i = 0; i < 8; l -= 16, i++)
|
||||
{
|
||||
subnet->net.ipv6.address.x[i] = htons(subnet->net.ipv6.address.x[i]);
|
||||
if(l >= 16)
|
||||
subnet->net.ipv6.mask.x[i] = 65535;
|
||||
else if (l > 0)
|
||||
subnet->net.ipv6.mask.x[i] = htons(65536 - (1 << l));
|
||||
else
|
||||
subnet->net.ipv6.mask.x[i] = 0;
|
||||
}
|
||||
subnet->net.ipv6.masklength = 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)
|
||||
&x[0], &x[1], &x[2], &x[3]) == 4)
|
||||
{
|
||||
subnet->type = SUBNET_IPV4;
|
||||
subnet->net.ipv4.address = (((((x[0] << 8) + x[1]) << 8) + x[2]) << 8) + x[3];
|
||||
subnet->net.ipv4.mask = ~0;
|
||||
subnet->net.ipv4.masklength = 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",
|
||||
&subnet->net.ipv6.address.x[0],
|
||||
&subnet->net.ipv6.address.x[1],
|
||||
&subnet->net.ipv6.address.x[2],
|
||||
&subnet->net.ipv6.address.x[3],
|
||||
&subnet->net.ipv6.address.x[4],
|
||||
&subnet->net.ipv6.address.x[5],
|
||||
&subnet->net.ipv6.address.x[6],
|
||||
&subnet->net.ipv6.address.x[7]) == 8)
|
||||
&x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7]) == 8)
|
||||
{
|
||||
subnet->type = SUBNET_IPV6;
|
||||
subnet->net.ipv6.masklength = 128;
|
||||
for(l = subnet->net.ipv6.masklength, i = 0; i < 8; l -= 16, i++)
|
||||
{
|
||||
subnet->net.ipv6.address.x[i] = htons(subnet->net.ipv6.address.x[i]);
|
||||
if(l >= 16)
|
||||
subnet->net.ipv6.mask.x[i] = 65535;
|
||||
else if (l > 0)
|
||||
subnet->net.ipv6.mask.x[i] = htons(65536 - (1 << l));
|
||||
else
|
||||
subnet->net.ipv6.mask.x[i] = 0;
|
||||
}
|
||||
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)
|
||||
&x[0], &x[1], &x[2], &x[3], &x[4], &x[5]) == 6)
|
||||
{
|
||||
subnet->type = SUBNET_MAC;
|
||||
subnet->net.mac.address.x[0] = x[0];
|
||||
subnet->net.mac.address.x[1] = x[1];
|
||||
subnet->net.mac.address.x[2] = x[2];
|
||||
subnet->net.mac.address.x[3] = x[3];
|
||||
subnet->net.mac.address.x[4] = x[4];
|
||||
subnet->net.mac.address.x[5] = x[5];
|
||||
for(i = 0; i < 6; i++)
|
||||
subnet->net.mac.address.x[i] = x[i];
|
||||
return subnet;
|
||||
}
|
||||
|
||||
|
@ -305,10 +252,10 @@ cp
|
|||
break;
|
||||
case SUBNET_IPV4:
|
||||
asprintf(&netstr, "%hu.%hu.%hu.%hu/%d",
|
||||
(unsigned short int)((subnet->net.ipv4.address >> 24) & 255),
|
||||
(unsigned short int)((subnet->net.ipv4.address >> 16) & 255),
|
||||
(unsigned short int)((subnet->net.ipv4.address >> 8) & 255),
|
||||
(unsigned short int)(subnet->net.ipv4.address & 255),
|
||||
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.masklength);
|
||||
break;
|
||||
case SUBNET_IPV6:
|
||||
|
@ -324,7 +271,9 @@ cp
|
|||
subnet->net.ipv6.masklength);
|
||||
break;
|
||||
default:
|
||||
asprintf(&netstr, _("unknown subnet type"));
|
||||
syslog(LOG_ERR, _("net2str() was called with unknown subnet type %d, exitting!"), subnet->type);
|
||||
cp_trace();
|
||||
exit(0);
|
||||
}
|
||||
cp
|
||||
return netstr;
|
||||
|
@ -355,8 +304,8 @@ subnet_t *lookup_subnet_ipv4(ipv4_t *address)
|
|||
subnet_t subnet, *p;
|
||||
cp
|
||||
subnet.type = SUBNET_IPV4;
|
||||
subnet.net.ipv4.address = *address;
|
||||
subnet.net.ipv4.mask = 0xFFFFFFFF;
|
||||
memcpy(&subnet.net.ipv4.address, address, sizeof(ipv4_t));
|
||||
subnet.net.ipv4.masklength = 32;
|
||||
|
||||
do
|
||||
{
|
||||
|
@ -368,14 +317,17 @@ cp
|
|||
cp
|
||||
if(p)
|
||||
{
|
||||
if ((*address & p->net.ipv4.mask) == p->net.ipv4.address)
|
||||
if(p->type != SUBNET_IPV4)
|
||||
return NULL;
|
||||
|
||||
if (!maskcmp((char *)address, (char *)&p->net.ipv4.address, p->net.ipv4.masklength, sizeof(ipv4_t)))
|
||||
break;
|
||||
else
|
||||
{
|
||||
/* Otherwise, see if there is a bigger enclosing subnet */
|
||||
|
||||
subnet.net.ipv4.mask = p->net.ipv4.mask << 1;
|
||||
subnet.net.ipv4.address = p->net.ipv4.address & subnet.net.ipv4.mask;
|
||||
subnet.net.ipv4.masklength = p->net.ipv4.masklength - 1;
|
||||
maskcpy((char *)&subnet.net.ipv4.address, (char *)&p->net.ipv4.address, subnet.net.ipv4.masklength, sizeof(ipv4_t));
|
||||
}
|
||||
}
|
||||
} while (p);
|
||||
|
@ -386,18 +338,36 @@ cp
|
|||
subnet_t *lookup_subnet_ipv6(ipv6_t *address)
|
||||
{
|
||||
subnet_t subnet, *p;
|
||||
int i;
|
||||
cp
|
||||
subnet.type = SUBNET_IPV6;
|
||||
memcpy(subnet.net.ipv6.address.x, address, sizeof(ipv6_t));
|
||||
memset(subnet.net.ipv6.mask.x, 0xFF, 16);
|
||||
memcpy(&subnet.net.ipv6.address, address, sizeof(ipv6_t));
|
||||
subnet.net.ipv6.masklength = 128;
|
||||
|
||||
p = (subnet_t *)avl_search_closest_greater(subnet_tree, &subnet);
|
||||
do
|
||||
{
|
||||
/* Go find subnet */
|
||||
|
||||
if(p)
|
||||
for(i=0; i<8; i++)
|
||||
if((address->x[i] & p->net.ipv6.address.x[i]) != p->net.ipv6.address.x[i])
|
||||
return NULL;
|
||||
p = (subnet_t *)avl_search_closest_smaller(subnet_tree, &subnet);
|
||||
|
||||
/* Check if the found subnet REALLY matches */
|
||||
|
||||
cp
|
||||
if(p)
|
||||
{
|
||||
if(p->type != SUBNET_IPV6)
|
||||
return NULL;
|
||||
|
||||
if (!maskcmp((char *)address, (char *)&p->net.ipv6.address, p->net.ipv6.masklength, sizeof(ipv6_t)))
|
||||
break;
|
||||
else
|
||||
{
|
||||
/* Otherwise, see if there is a bigger enclosing subnet */
|
||||
|
||||
subnet.net.ipv6.masklength = p->net.ipv6.masklength - 1;
|
||||
maskcpy((char *)&subnet.net.ipv6.address, (char *)&p->net.ipv6.address, subnet.net.ipv6.masklength, sizeof(ipv6_t));
|
||||
}
|
||||
}
|
||||
} while (p);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
|
|
@ -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.15 2002/02/10 21:57:54 guus Exp $
|
||||
$Id: subnet.h,v 1.1.2.16 2002/02/18 16:25:19 guus Exp $
|
||||
*/
|
||||
|
||||
#ifndef __TINC_SUBNET_H__
|
||||
|
@ -41,14 +41,12 @@ typedef struct subnet_mac_t
|
|||
typedef struct subnet_ipv4_t
|
||||
{
|
||||
ipv4_t address;
|
||||
ipv4_t mask;
|
||||
int masklength;
|
||||
} subnet_ipv4_t;
|
||||
|
||||
typedef struct subnet_ipv6_t
|
||||
{
|
||||
ipv6_t address;
|
||||
ipv6_t mask;
|
||||
int masklength;
|
||||
} subnet_ipv6_t;
|
||||
|
||||
|
|
Loading…
Reference in a new issue