Merge branch 'master' of git://tinc-vpn.org/tinc into 1.1
Conflicts: NEWS README configure.in doc/tincd.8.in src/Makefile.am src/bsd/device.c src/connection.c src/connection.h src/cygwin/device.c src/device.h src/dropin.h src/linux/device.c src/mingw/device.c src/net.c src/net_packet.c src/net_setup.c src/net_socket.c src/process.c src/protocol.c src/protocol_key.c src/raw_socket_device.c src/route.c src/solaris/device.c src/tincd.c src/uml_device.c
This commit is contained in:
commit
3fba80174d
33 changed files with 614 additions and 273 deletions
7
NEWS
7
NEWS
|
@ -28,6 +28,13 @@ Version 1.1pre1 June 25 2011
|
|||
Thanks to Scott Lamb and Sven-Haegar Koch for their contributions to this
|
||||
version of tinc.
|
||||
|
||||
Version 1.0.16 July 23 2011
|
||||
|
||||
* Fixed a performance issue with TCP communication under Windows.
|
||||
|
||||
* Fixed code that, during network outages, would cause tinc to exit when it
|
||||
thought two nodes with identical Names were on the VPN.
|
||||
|
||||
Version 1.0.15 June 24 2011
|
||||
|
||||
* Improved logging to file.
|
||||
|
|
1
THANKS
1
THANKS
|
@ -32,6 +32,7 @@ We would like to thank the following people for their contributions to tinc:
|
|||
* Menno Smits
|
||||
* Michael Tokarev
|
||||
* Miles Nordin
|
||||
* Nick Hibma
|
||||
* Nick Patavalis
|
||||
* Paul Littlefield
|
||||
* Robert van der Meulen
|
||||
|
|
19
configure.in
19
configure.in
|
@ -73,6 +73,21 @@ case $host_os in
|
|||
;;
|
||||
esac
|
||||
|
||||
AC_ARG_ENABLE(uml,
|
||||
AS_HELP_STRING([--enable-uml], [enable support for User Mode Linux]),
|
||||
[ AC_DEFINE(ENABLE_UML, 1, [Support for UML])
|
||||
uml=true
|
||||
]
|
||||
)
|
||||
|
||||
AC_ARG_ENABLE(vde,
|
||||
AS_HELP_STRING([--enable-vde], [enable support for Virtual Distributed Ethernet]),
|
||||
[ AC_CHECK_HEADERS(libvdeplug_dyn.h, [], [AC_MSG_ERROR([VDE plug header files not found.]); break])
|
||||
AC_DEFINE(ENABLE_VDE, 1, [Support for VDE])
|
||||
vde=true
|
||||
]
|
||||
)
|
||||
|
||||
AC_ARG_ENABLE(tunemu,
|
||||
AS_HELP_STRING([--enable-tunemu], [enable support for the tunemu driver]),
|
||||
[ AC_DEFINE(ENABLE_TUNEMU, 1, [Support for tunemu])
|
||||
|
@ -85,6 +100,8 @@ AC_ARG_WITH(windows2000,
|
|||
[AC_DEFINE(WITH_WINDOWS2000, 1, [Compile with support for Windows 2000])]
|
||||
)
|
||||
|
||||
AM_CONDITIONAL(UML, test "$uml" = true)
|
||||
AM_CONDITIONAL(VDE, test "$vde" = true)
|
||||
AM_CONDITIONAL(TUNEMU, test "$tunemu" = true)
|
||||
|
||||
AC_CACHE_SAVE
|
||||
|
@ -101,7 +118,7 @@ dnl We do this in multiple stages, because unlike Linux all the other operating
|
|||
|
||||
AC_HEADER_STDC
|
||||
AC_CHECK_HEADERS([stdbool.h syslog.h sys/file.h sys/ioctl.h sys/mman.h sys/param.h sys/resource.h sys/socket.h sys/time.h sys/uio.h sys/un.h sys/wait.h netdb.h arpa/inet.h dirent.h])
|
||||
AC_CHECK_HEADERS([net/if.h net/if_types.h linux/if_tun.h net/if_tun.h net/tun/if_tun.h net/if_tap.h net/tap/if_tap.h net/ethernet.h net/if_arp.h netinet/in_systm.h netinet/in.h netinet/in6.h time.h],
|
||||
AC_CHECK_HEADERS([net/if.h net/if_types.h linux/if_tun.h net/if_tun.h net/tun/if_tun.h net/if_tap.h net/tap/if_tap.h net/ethernet.h net/if_arp.h netinet/in_systm.h netinet/in.h netinet/in6.h time.h netpacket/packet.h],
|
||||
[], [], [#include "have.h"]
|
||||
)
|
||||
AC_CHECK_HEADERS([netinet/if_ether.h netinet/ip.h netinet/ip6.h],
|
||||
|
|
|
@ -133,7 +133,10 @@ IPv6 listening sockets will be created.
|
|||
If your computer has more than one IPv4 or IPv6 address,
|
||||
.Nm tinc
|
||||
will by default listen on all of them for incoming connections.
|
||||
It is possible to bind only to a single address with this variable.
|
||||
Multiple
|
||||
.Va BindToAddress
|
||||
variables may be specified,
|
||||
in which case listening sockets for each specified address are made.
|
||||
|
||||
.Pp
|
||||
This option may not work on all platforms.
|
||||
|
@ -147,6 +150,9 @@ It is possible to bind only to a single interface with this variable.
|
|||
.Pp
|
||||
This option may not work on all platforms.
|
||||
|
||||
.It Va Broadcast Li = yes | no Po yes Pc Bq experimental
|
||||
When disabled, tinc will drop all broadcast and multicast packets, in both router and switch mode.
|
||||
|
||||
.It Va ConnectTo Li = Ar name
|
||||
Specifies which other tinc daemon to connect to on startup.
|
||||
Multiple
|
||||
|
@ -165,6 +171,14 @@ If you don't specify a host with
|
|||
won't try to connect to other daemons at all,
|
||||
and will instead just listen for incoming connections.
|
||||
|
||||
.It Va DecrementTTL Li = yes | no Po yes Pc
|
||||
When enabled,
|
||||
.Nm tinc
|
||||
will decrement the Time To Live field in IPv4 packets, or the Hop Limit field in IPv6 packets,
|
||||
before forwarding a received packet to the virtual network device or to another node,
|
||||
and will drop packets that have a TTL value of zero,
|
||||
in which case it will send an ICMP Time Exceeded packet back.
|
||||
|
||||
.It Va Device Li = Ar device Po Pa /dev/tap0 , Pa /dev/net/tun No or other depending on platform Pc
|
||||
The virtual network device to use.
|
||||
.Nm tinc
|
||||
|
@ -177,30 +191,65 @@ instead of
|
|||
The info pages of the tinc package contain more information
|
||||
about configuring the virtual network device.
|
||||
|
||||
.It Va DeviceType Li = tun | tunnohead | tunifhead | tap Po only supported on BSD platforms Pc
|
||||
.It Va DeviceType Li = Ar type Pq platform dependent
|
||||
The type of the virtual network device.
|
||||
Tinc will normally automatically select the right type, and this option should not be used.
|
||||
However, in case tinc does not seem to correctly interpret packets received from the virtual network device,
|
||||
using this option might help.
|
||||
Tinc will normally automatically select the right type of tun/tap interface, and this option should not be used.
|
||||
However, this option can be used to select one of the special interface types, if support for them is compiled in.
|
||||
.Bl -tag -width indent
|
||||
|
||||
.It tun
|
||||
.It dummy
|
||||
Use a dummy interface.
|
||||
No packets are ever read or written to a virtual network device.
|
||||
Useful for testing, or when setting up a node that only forwards packets for other nodes.
|
||||
|
||||
.It raw_socket
|
||||
Open a raw socket, and bind it to a pre-existing
|
||||
.Va Interface
|
||||
(eth0 by default).
|
||||
All packets are read from this interface.
|
||||
Packets received for the local node are written to the raw socket.
|
||||
However, at least on Linux, the operating system does not process IP packets destined for the local host.
|
||||
|
||||
.It uml Pq not compiled in by default
|
||||
Create a UNIX socket with the filename specified by
|
||||
.Va Device ,
|
||||
or
|
||||
.Pa @localstatedir@/run/ Ns Ar NETNAME Ns Pa .umlsocket
|
||||
if not specified.
|
||||
.Nm tinc
|
||||
will wait for a User Mode Linux instance to connect to this socket.
|
||||
|
||||
.It vde Pq not compiled in by default
|
||||
Uses the libvdeplug library to connect to a Virtual Distributed Ethernet switch,
|
||||
using the UNIX socket specified by
|
||||
.Va Device ,
|
||||
or
|
||||
.Pa @localstatedir@/run/vde.ctl
|
||||
if not specified.
|
||||
.El
|
||||
|
||||
Also, in case tinc does not seem to correctly interpret packets received from the virtual network device,
|
||||
it can be used to change the way packets are interpreted:
|
||||
|
||||
.Bl -tag -width indent
|
||||
|
||||
.It tun Pq BSD and Linux
|
||||
Set type to tun.
|
||||
Depending on the platform, this can either be with or without an address family header (see below).
|
||||
|
||||
.It tunnohead
|
||||
.It tunnohead Pq BSD
|
||||
Set type to tun without an address family header.
|
||||
Tinc will expect packets read from the virtual network device to start with an IP header.
|
||||
On some platforms IPv6 packets cannot be read from or written to the device in this mode.
|
||||
|
||||
.It tunifhead
|
||||
.It tunifhead Pq BSD
|
||||
Set type to tun with an address family header.
|
||||
Tinc will expect packets read from the virtual network device
|
||||
to start with a four byte header containing the address family,
|
||||
followed by an IP header.
|
||||
This mode should support both IPv4 and IPv6 packets.
|
||||
|
||||
.It tap
|
||||
.It tap Pq BSD and Linux
|
||||
Set type to tap.
|
||||
Tinc will expect packets read from the virtual network device
|
||||
to start with an Ethernet header.
|
||||
|
|
|
@ -782,7 +782,8 @@ both IPv4 and IPv6 or just IPv6 listening sockets will be created.
|
|||
@item BindToAddress = <@var{address}> [experimental]
|
||||
If your computer has more than one IPv4 or IPv6 address, tinc
|
||||
will by default listen on all of them for incoming connections.
|
||||
It is possible to bind only to a single address with this variable.
|
||||
Multiple BindToAddress variables may be specified,
|
||||
in which case listening sockets for each specified address are made.
|
||||
|
||||
This option may not work on all platforms.
|
||||
|
||||
|
@ -795,6 +796,10 @@ variable.
|
|||
|
||||
This option may not work on all platforms.
|
||||
|
||||
@cindex Broadcast
|
||||
@item Broadcast = <yes | no> (yes) [experimental]
|
||||
When disabled, tinc will drop all broadcast and multicast packets, in both router and switch mode.
|
||||
|
||||
@cindex ConnectTo
|
||||
@item ConnectTo = <@var{name}>
|
||||
Specifies which other tinc daemon to connect to on startup.
|
||||
|
@ -807,6 +812,13 @@ If you don't specify a host with ConnectTo,
|
|||
tinc won't try to connect to other daemons at all,
|
||||
and will instead just listen for incoming connections.
|
||||
|
||||
@cindex DecrementTTL
|
||||
@item DecrementTTL = <yes | no> (yes)
|
||||
When enabled, tinc will decrement the Time To Live field in IPv4 packets, or the Hop Limit field in IPv6 packets,
|
||||
before forwarding a received packet to the virtual network device or to another node,
|
||||
and will drop packets that have a TTL value of zero,
|
||||
in which case it will send an ICMP Time Exceeded packet back.
|
||||
|
||||
@cindex Device
|
||||
@item Device = <@var{device}> (@file{/dev/tap0}, @file{/dev/net/tun} or other depending on platform)
|
||||
The virtual network device to use.
|
||||
|
@ -817,32 +829,64 @@ Note that you can only use one device per daemon.
|
|||
See also @ref{Device files}.
|
||||
|
||||
@cindex DeviceType
|
||||
@item DeviceType = <tun|tunnohead|tunifhead|tap> (only supported on BSD platforms)
|
||||
@item DeviceType = <@var{type}> (platform dependent)
|
||||
The type of the virtual network device.
|
||||
Tinc will normally automatically select the right type, and this option should not be used.
|
||||
However, in case tinc does not seem to correctly interpret packets received from the virtual network device,
|
||||
using this option might help.
|
||||
Tinc will normally automatically select the right type of tun/tap interface, and this option should not be used.
|
||||
However, this option can be used to select one of the special interface types, if support for them is compiled in.
|
||||
|
||||
@table @asis
|
||||
@item tun
|
||||
@cindex dummy
|
||||
@item dummy
|
||||
Use a dummy interface.
|
||||
No packets are ever read or written to a virtual network device.
|
||||
Useful for testing, or when setting up a node that only forwards packets for other nodes.
|
||||
|
||||
@cindex raw_socket
|
||||
@item raw_socket
|
||||
Open a raw socket, and bind it to a pre-existing
|
||||
@var{Interface} (eth0 by default).
|
||||
All packets are read from this interface.
|
||||
Packets received for the local node are written to the raw socket.
|
||||
However, at least on Linux, the operating system does not process IP packets destined for the local host.
|
||||
|
||||
@cindex UML
|
||||
@item uml (not compiled in by default)
|
||||
Create a UNIX socket with the filename specified by
|
||||
@var{Device}, or @file{@value{localstatedir}/run/@var{netname}.umlsocket}
|
||||
if not specified.
|
||||
Tinc will wait for a User Mode Linux instance to connect to this socket.
|
||||
|
||||
@cindex VDE
|
||||
@item vde (not compiled in by default)
|
||||
Uses the libvdeplug library to connect to a Virtual Distributed Ethernet switch,
|
||||
using the UNIX socket specified by
|
||||
@var{Device}, or @file{@value{localstatedir}/run/vde.ctl}
|
||||
if not specified.
|
||||
@end table
|
||||
|
||||
Also, in case tinc does not seem to correctly interpret packets received from the virtual network device,
|
||||
it can be used to change the way packets are interpreted:
|
||||
|
||||
@table @asis
|
||||
@item tun (BSD and Linux)
|
||||
Set type to tun.
|
||||
Depending on the platform, this can either be with or without an address family header (see below).
|
||||
|
||||
@cindex tunnohead
|
||||
@item tunnohead
|
||||
@item tunnohead (BSD)
|
||||
Set type to tun without an address family header.
|
||||
Tinc will expect packets read from the virtual network device to start with an IP header.
|
||||
On some platforms IPv6 packets cannot be read from or written to the device in this mode.
|
||||
|
||||
@cindex tunifhead
|
||||
@item tunifhead
|
||||
@item tunifhead (BSD)
|
||||
Set type to tun with an address family header.
|
||||
Tinc will expect packets read from the virtual network device
|
||||
to start with a four byte header containing the address family,
|
||||
followed by an IP header.
|
||||
This mode should support both IPv4 and IPv6 packets.
|
||||
|
||||
@item tap
|
||||
@item tap (BSD and Linux)
|
||||
Set type to tap.
|
||||
Tinc will expect packets read from the virtual network device
|
||||
to start with an Ethernet header.
|
||||
|
@ -1600,6 +1644,12 @@ Store a cookie in @var{filename} which allows tincctl to authenticate.
|
|||
If unspecified, the default is
|
||||
@file{@value{localstatedir}/run/tinc.@var{netname}.pid}.
|
||||
|
||||
@item -o, --option=[@var{HOST}.]@var{KEY}=@var{VALUE}
|
||||
Without specifying a @var{HOST}, this will set server configuration variable @var{KEY} to @var{VALUE}.
|
||||
If specified as @var{HOST}.@var{KEY}=@var{VALUE},
|
||||
this will set the host configuration variable @var{KEY} of the host named @var{HOST} to @var{VALUE}.
|
||||
This option can be used more than once to specify multiple configuration variables.
|
||||
|
||||
@item -L, --mlock
|
||||
Lock tinc into main memory.
|
||||
This will prevent sensitive data like shared private keys to be written to the system swap files/partitions.
|
||||
|
|
|
@ -8,11 +8,12 @@
|
|||
.Nd tinc VPN daemon
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl cdDKnLRU
|
||||
.Op Fl cdDKnoLRU
|
||||
.Op Fl -config Ns = Ns Ar DIR
|
||||
.Op Fl -no-detach
|
||||
.Op Fl -debug Ns Op = Ns Ar LEVEL
|
||||
.Op Fl -net Ns = Ns Ar NETNAME
|
||||
.Op Fl -option Ns = Ns Ar [HOST.]KEY=VALUE
|
||||
.Op Fl -mlock
|
||||
.Op Fl -logfile Ns Op = Ns Ar FILE
|
||||
.Op Fl -bypass-security
|
||||
|
@ -61,6 +62,22 @@ for
|
|||
.Ar NETNAME
|
||||
is the same as not specifying any
|
||||
.Ar NETNAME .
|
||||
.It Fl o, -option Ns = Ns Ar [HOST.]KEY=VALUE
|
||||
Without specifying a
|
||||
.Ar HOST ,
|
||||
this will set server configuration variable
|
||||
.Ar KEY
|
||||
to
|
||||
.Ar VALUE .
|
||||
If specified as
|
||||
.Ar HOST.KEY=VALUE ,
|
||||
this will set the host configuration variable
|
||||
.Ar KEY
|
||||
of the host named
|
||||
.Ar HOST
|
||||
to
|
||||
.Ar VALUE .
|
||||
This option can be used more than once to specify multiple configuration variables.
|
||||
.It Fl L, -mlock
|
||||
Lock tinc into main memory.
|
||||
This will prevent sensitive data like shared private keys to be written to the system swap files/partitions.
|
||||
|
|
|
@ -2,13 +2,22 @@
|
|||
|
||||
sbin_PROGRAMS = tincd tincctl sptps_test
|
||||
|
||||
EXTRA_DIST = linux bsd solaris cygwin mingw raw_socket uml_socket openssl gcrypt
|
||||
EXTRA_DIST = linux bsd solaris cygwin mingw openssl gcrypt
|
||||
|
||||
tincd_SOURCES = \
|
||||
utils.c getopt.c getopt1.c list.c splay_tree.c dropin.c fake-getaddrinfo.c fake-getnameinfo.c \
|
||||
buffer.c conf.c connection.c control.c edge.c graph.c logger.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
|
||||
protocol_key.c protocol_subnet.c route.c subnet.c tincd.c \
|
||||
dummy_device.c raw_socket_device.c
|
||||
|
||||
if UML
|
||||
tincd_SOURCES += uml_device.c
|
||||
endif
|
||||
|
||||
if VDE
|
||||
tincd_SOURCES += vde_device.c
|
||||
endif
|
||||
|
||||
nodist_tincd_SOURCES = \
|
||||
device.c cipher.c crypto.c ecdh.c ecdsa.c digest.c prf.c rsa.c
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
device.c -- Interaction BSD tun/tap device
|
||||
Copyright (C) 2001-2005 Ivo Timmermans,
|
||||
2001-2011 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2001-2012 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2009 Grzegorz Dymarek <gregd72002@googlemail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
|
@ -58,7 +58,7 @@ static device_type_t device_type = DEVICE_TYPE_TUNIFHEAD;
|
|||
static device_type_t device_type = DEVICE_TYPE_TUN;
|
||||
#endif
|
||||
|
||||
bool setup_device(void) {
|
||||
static bool setup_device(void) {
|
||||
char *type;
|
||||
|
||||
if(!get_config_string(lookup_config(config_tree, "Device"), &device))
|
||||
|
@ -106,6 +106,10 @@ bool setup_device(void) {
|
|||
return false;
|
||||
}
|
||||
|
||||
#ifdef FD_CLOEXEC
|
||||
fcntl(device_fd, F_SETFD, FD_CLOEXEC);
|
||||
#endif
|
||||
|
||||
switch(device_type) {
|
||||
default:
|
||||
device_type = DEVICE_TYPE_TUN;
|
||||
|
@ -175,7 +179,7 @@ bool setup_device(void) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void close_device(void) {
|
||||
static void close_device(void) {
|
||||
switch(device_type) {
|
||||
#ifdef HAVE_TUNEMU
|
||||
case DEVICE_TYPE_TUNEMU:
|
||||
|
@ -190,7 +194,7 @@ void close_device(void) {
|
|||
free(iface);
|
||||
}
|
||||
|
||||
bool read_packet(vpn_packet_t *packet) {
|
||||
static bool read_packet(vpn_packet_t *packet) {
|
||||
int inlen;
|
||||
|
||||
switch(device_type) {
|
||||
|
@ -282,7 +286,7 @@ bool read_packet(vpn_packet_t *packet) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool write_packet(vpn_packet_t *packet) {
|
||||
static bool write_packet(vpn_packet_t *packet) {
|
||||
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Writing packet of %d bytes to %s",
|
||||
packet->len, device_info);
|
||||
|
||||
|
@ -351,8 +355,16 @@ bool write_packet(vpn_packet_t *packet) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void dump_device_stats(void) {
|
||||
static void dump_device_stats(void) {
|
||||
logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device);
|
||||
logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in);
|
||||
logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out);
|
||||
}
|
||||
|
||||
const devops_t os_devops = {
|
||||
.setup = setup_device,
|
||||
.close = close_device,
|
||||
.read = read_packet,
|
||||
.write = write_packet,
|
||||
.dump_stats = dump_device_stats,
|
||||
};
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
#include "xalloc.h"
|
||||
|
||||
splay_tree_t *connection_tree; /* Meta connections */
|
||||
connection_t *broadcast;
|
||||
connection_t *everyone;
|
||||
|
||||
static int connection_compare(const connection_t *a, const connection_t *b) {
|
||||
return a < b ? -1 : a == b ? 0 : 1;
|
||||
|
@ -40,14 +40,14 @@ static int connection_compare(const connection_t *a, const connection_t *b) {
|
|||
|
||||
void init_connections(void) {
|
||||
connection_tree = splay_alloc_tree((splay_compare_t) connection_compare, (splay_action_t) free_connection);
|
||||
broadcast = new_connection();
|
||||
broadcast->name = xstrdup("everyone");
|
||||
broadcast->hostname = xstrdup("BROADCAST");
|
||||
everyone = new_connection();
|
||||
everyone->name = xstrdup("everyone");
|
||||
everyone->hostname = xstrdup("BROADCAST");
|
||||
}
|
||||
|
||||
void exit_connections(void) {
|
||||
splay_delete_tree(connection_tree);
|
||||
free_connection(broadcast);
|
||||
free_connection(everyone);
|
||||
}
|
||||
|
||||
connection_t *new_connection(void) {
|
||||
|
|
|
@ -99,7 +99,7 @@ typedef struct connection_t {
|
|||
} connection_t;
|
||||
|
||||
extern splay_tree_t *connection_tree;
|
||||
extern connection_t *broadcast;
|
||||
extern connection_t *everyone;
|
||||
|
||||
extern void init_connections(void);
|
||||
extern void exit_connections(void);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
device.c -- Interaction with Windows tap driver in a Cygwin environment
|
||||
Copyright (C) 2002-2005 Ivo Timmermans,
|
||||
2002-2009 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2002-2011 Guus Sliepen <guus@tinc-vpn.org>
|
||||
|
||||
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
|
||||
|
@ -45,7 +45,7 @@ static uint64_t device_total_out = 0;
|
|||
static pid_t reader_pid;
|
||||
static int sp[2];
|
||||
|
||||
bool setup_device(void) {
|
||||
static bool setup_device(void) {
|
||||
HKEY key, key2;
|
||||
int i, err;
|
||||
|
||||
|
@ -214,7 +214,7 @@ bool setup_device(void) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void close_device(void) {
|
||||
static void close_device(void) {
|
||||
close(sp[0]);
|
||||
close(sp[1]);
|
||||
CloseHandle(device_handle);
|
||||
|
@ -225,7 +225,7 @@ void close_device(void) {
|
|||
free(iface);
|
||||
}
|
||||
|
||||
bool read_packet(vpn_packet_t *packet) {
|
||||
static bool read_packet(vpn_packet_t *packet) {
|
||||
int inlen;
|
||||
|
||||
if((inlen = read(sp[0], packet->data, MTU)) <= 0) {
|
||||
|
@ -244,7 +244,7 @@ bool read_packet(vpn_packet_t *packet) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool write_packet(vpn_packet_t *packet) {
|
||||
static bool write_packet(vpn_packet_t *packet) {
|
||||
long outlen;
|
||||
|
||||
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Writing packet of %d bytes to %s",
|
||||
|
@ -260,8 +260,16 @@ bool write_packet(vpn_packet_t *packet) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void dump_device_stats(void) {
|
||||
static void dump_device_stats(void) {
|
||||
logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device);
|
||||
logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in);
|
||||
logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out);
|
||||
}
|
||||
|
||||
const devops_t os_devops = {
|
||||
.setup = setup_device,
|
||||
.close = close_device,
|
||||
.read = read_packet,
|
||||
.write = write_packet,
|
||||
.dump_stats = dump_device_stats,
|
||||
};
|
||||
|
|
23
src/device.h
23
src/device.h
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
net.h -- generic header for device.c
|
||||
device.h -- generic header for device.c
|
||||
Copyright (C) 2001-2005 Ivo Timmermans
|
||||
2001-2006 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2001-2011 Guus Sliepen <guus@tinc-vpn.org>
|
||||
|
||||
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
|
||||
|
@ -32,10 +32,19 @@ extern uint64_t device_in_bytes;
|
|||
extern uint64_t device_out_packets;
|
||||
extern uint64_t device_out_bytes;
|
||||
|
||||
extern bool setup_device(void);
|
||||
extern void close_device(void);
|
||||
extern bool read_packet(struct vpn_packet_t *);
|
||||
extern bool write_packet(struct vpn_packet_t *);
|
||||
extern void dump_device_stats(void);
|
||||
typedef struct devops_t {
|
||||
bool (*setup)(void);
|
||||
void (*close)(void);
|
||||
bool (*read)(struct vpn_packet_t *);
|
||||
bool (*write)(struct vpn_packet_t *);
|
||||
void (*dump_stats)(void);
|
||||
} devops_t;
|
||||
|
||||
extern const devops_t os_devops;
|
||||
extern const devops_t dummy_devops;
|
||||
extern const devops_t raw_socket_devops;
|
||||
extern const devops_t uml_devops;
|
||||
extern const devops_t vde_devops;
|
||||
extern devops_t devops;
|
||||
|
||||
#endif /* __TINC_DEVICE_H__ */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
device.c -- Dummy device
|
||||
Copyright (C) 2009 Guus Sliepen <guus@tinc-vpn.org>
|
||||
Copyright (C) 2011 Guus Sliepen <guus@tinc-vpn.org>
|
||||
|
||||
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
|
||||
|
@ -23,33 +23,40 @@
|
|||
#include "logger.h"
|
||||
#include "net.h"
|
||||
|
||||
int device_fd = -1;
|
||||
char *device = "dummy";
|
||||
char *iface = "dummy";
|
||||
static char *device_info = "dummy device";
|
||||
|
||||
static uint64_t device_total_in = 0;
|
||||
static uint64_t device_total_out = 0;
|
||||
|
||||
bool setup_device(void) {
|
||||
static bool setup_device(void) {
|
||||
device = "dummy";
|
||||
iface = "dummy";
|
||||
logger(LOG_INFO, "%s (%s) is a %s", device, iface, device_info);
|
||||
return true;
|
||||
}
|
||||
|
||||
void close_device(void) {
|
||||
static void close_device(void) {
|
||||
}
|
||||
|
||||
bool read_packet(vpn_packet_t *packet) {
|
||||
static bool read_packet(vpn_packet_t *packet) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool write_packet(vpn_packet_t *packet) {
|
||||
static bool write_packet(vpn_packet_t *packet) {
|
||||
device_total_out += packet->len;
|
||||
return true;
|
||||
}
|
||||
|
||||
void dump_device_stats(void) {
|
||||
static void dump_device_stats(void) {
|
||||
logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device);
|
||||
logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in);
|
||||
logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out);
|
||||
}
|
||||
|
||||
const devops_t dummy_devops = {
|
||||
.setup = setup_device,
|
||||
.close = close_device,
|
||||
.read = read_packet,
|
||||
.write = write_packet,
|
||||
.dump_stats = dump_device_stats,
|
||||
};
|
|
@ -41,6 +41,14 @@
|
|||
#define ICMP_NET_UNKNOWN 6
|
||||
#endif
|
||||
|
||||
#ifndef ICMP_TIME_EXCEEDED
|
||||
#define ICMP_TIME_EXCEEDED 11
|
||||
#endif
|
||||
|
||||
#ifndef ICMP_EXC_TTL
|
||||
#define ICMP_EXC_TTL 0
|
||||
#endif
|
||||
|
||||
#ifndef ICMP_NET_UNREACH
|
||||
#define ICMP_NET_UNREACH 0
|
||||
#endif
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
device.c -- Interaction with Linux ethertap and tun/tap device
|
||||
Copyright (C) 2001-2005 Ivo Timmermans,
|
||||
2001-2009 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2001-2012 Guus Sliepen <guus@tinc-vpn.org>
|
||||
|
||||
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
|
||||
|
@ -41,6 +41,7 @@ int device_fd = -1;
|
|||
static device_type_t device_type;
|
||||
char *device = NULL;
|
||||
char *iface = NULL;
|
||||
static char *type = NULL;
|
||||
static char ifrname[IFNAMSIZ];
|
||||
static char *device_info;
|
||||
|
||||
|
@ -49,7 +50,7 @@ uint64_t device_in_bytes = 0;
|
|||
uint64_t device_out_packets = 0;
|
||||
uint64_t device_out_bytes = 0;
|
||||
|
||||
bool setup_device(void) {
|
||||
static bool setup_device(void) {
|
||||
if(!get_config_string(lookup_config(config_tree, "Device"), &device))
|
||||
device = xstrdup(DEFAULT_DEVICE);
|
||||
|
||||
|
@ -67,9 +68,20 @@ bool setup_device(void) {
|
|||
return false;
|
||||
}
|
||||
|
||||
#ifdef FD_CLOEXEC
|
||||
fcntl(device_fd, F_SETFD, FD_CLOEXEC);
|
||||
#endif
|
||||
|
||||
struct ifreq ifr = {{{0}}};
|
||||
|
||||
if(routing_mode == RMODE_ROUTER) {
|
||||
get_config_string(lookup_config(config_tree, "DeviceType"), &type);
|
||||
|
||||
if(type && strcasecmp(type, "tun") && strcasecmp(type, "tap")) {
|
||||
logger(LOG_ERR, "Unknown device type %s!", type);
|
||||
return false;
|
||||
}
|
||||
|
||||
if((type && !strcasecmp(type, "tun")) || (!type && routing_mode == RMODE_ROUTER)) {
|
||||
ifr.ifr_flags = IFF_TUN;
|
||||
device_type = DEVICE_TYPE_TUN;
|
||||
device_info = "Linux tun/tap device (tun mode)";
|
||||
|
@ -106,14 +118,15 @@ bool setup_device(void) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void close_device(void) {
|
||||
static void close_device(void) {
|
||||
close(device_fd);
|
||||
|
||||
free(type);
|
||||
free(device);
|
||||
free(iface);
|
||||
}
|
||||
|
||||
bool read_packet(vpn_packet_t *packet) {
|
||||
static bool read_packet(vpn_packet_t *packet) {
|
||||
int inlen;
|
||||
|
||||
switch(device_type) {
|
||||
|
@ -152,7 +165,7 @@ bool read_packet(vpn_packet_t *packet) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool write_packet(vpn_packet_t *packet) {
|
||||
static bool write_packet(vpn_packet_t *packet) {
|
||||
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Writing packet of %d bytes to %s",
|
||||
packet->len, device_info);
|
||||
|
||||
|
@ -182,8 +195,16 @@ bool write_packet(vpn_packet_t *packet) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void dump_device_stats(void) {
|
||||
static void dump_device_stats(void) {
|
||||
logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device);
|
||||
logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_in_bytes);
|
||||
logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_out_bytes);
|
||||
}
|
||||
|
||||
const devops_t os_devops = {
|
||||
.setup = setup_device,
|
||||
.close = close_device,
|
||||
.read = read_packet,
|
||||
.write = write_packet,
|
||||
.dump_stats = dump_device_stats,
|
||||
};
|
||||
|
|
|
@ -83,7 +83,7 @@ static DWORD WINAPI tapreader(void *bla) {
|
|||
}
|
||||
}
|
||||
|
||||
bool setup_device(void) {
|
||||
static bool setup_device(void) {
|
||||
HKEY key, key2;
|
||||
int i;
|
||||
|
||||
|
@ -210,18 +210,18 @@ bool setup_device(void) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void close_device(void) {
|
||||
static void close_device(void) {
|
||||
CloseHandle(device_handle);
|
||||
|
||||
free(device);
|
||||
free(iface);
|
||||
}
|
||||
|
||||
bool read_packet(vpn_packet_t *packet) {
|
||||
static bool read_packet(vpn_packet_t *packet) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool write_packet(vpn_packet_t *packet) {
|
||||
static bool write_packet(vpn_packet_t *packet) {
|
||||
long outlen;
|
||||
OVERLAPPED overlapped = {0};
|
||||
|
||||
|
@ -238,8 +238,16 @@ bool write_packet(vpn_packet_t *packet) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void dump_device_stats(void) {
|
||||
static void dump_device_stats(void) {
|
||||
logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device);
|
||||
logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in);
|
||||
logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out);
|
||||
}
|
||||
|
||||
const devops_t os_devops = {
|
||||
.setup = setup_device,
|
||||
.close = close_device,
|
||||
.read = read_packet,
|
||||
.write = write_packet,
|
||||
.dump_stats = dump_device_stats,
|
||||
};
|
||||
|
|
12
src/net.c
12
src/net.c
|
@ -64,7 +64,7 @@ void purge(void) {
|
|||
for(snode = n->subnet_tree->head; snode; snode = snext) {
|
||||
snext = snode->next;
|
||||
s = snode->data;
|
||||
send_del_subnet(broadcast, s);
|
||||
send_del_subnet(everyone, s);
|
||||
if(!strictsubnets)
|
||||
subnet_del(n, s);
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ void purge(void) {
|
|||
enext = enode->next;
|
||||
e = enode->data;
|
||||
if(!tunnelserver)
|
||||
send_del_edge(broadcast, e);
|
||||
send_del_edge(everyone, e);
|
||||
edge_del(e);
|
||||
}
|
||||
}
|
||||
|
@ -119,7 +119,7 @@ void terminate_connection(connection_t *c, bool report) {
|
|||
|
||||
if(c->edge) {
|
||||
if(report && !tunnelserver)
|
||||
send_del_edge(broadcast, c->edge);
|
||||
send_del_edge(everyone, c->edge);
|
||||
|
||||
edge_del(c->edge);
|
||||
|
||||
|
@ -134,7 +134,7 @@ void terminate_connection(connection_t *c, bool report) {
|
|||
e = lookup_edge(c->node, myself);
|
||||
if(e) {
|
||||
if(!tunnelserver)
|
||||
send_del_edge(broadcast, e);
|
||||
send_del_edge(everyone, e);
|
||||
edge_del(e);
|
||||
}
|
||||
}
|
||||
|
@ -310,14 +310,14 @@ int reload_configuration(void) {
|
|||
next = node->next;
|
||||
subnet = node->data;
|
||||
if(subnet->expires == 1) {
|
||||
send_del_subnet(broadcast, subnet);
|
||||
send_del_subnet(everyone, subnet);
|
||||
if(subnet->owner->status.reachable)
|
||||
subnet_update(subnet->owner, subnet, false);
|
||||
subnet_del(subnet->owner, subnet);
|
||||
} else if(subnet->expires == -1) {
|
||||
subnet->expires = 0;
|
||||
} else {
|
||||
send_add_subnet(broadcast, subnet);
|
||||
send_add_subnet(everyone, subnet);
|
||||
if(subnet->owner->status.reachable)
|
||||
subnet_update(subnet->owner, subnet, true);
|
||||
}
|
||||
|
|
|
@ -381,7 +381,6 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
|
|||
static int priority = 0;
|
||||
int origpriority = origpkt->priority;
|
||||
#endif
|
||||
int sock;
|
||||
|
||||
if(!n->status.reachable) {
|
||||
ifdebug(TRAFFIC) logger(LOG_INFO, "Trying to send UDP packet to unreachable node %s (%s)", n->name, n->hostname);
|
||||
|
@ -463,26 +462,28 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
|
|||
|
||||
/* Determine which socket we have to use */
|
||||
|
||||
for(sock = 0; sock < listen_sockets; sock++)
|
||||
if(n->address.sa.sa_family == listen_socket[sock].sa.sa.sa_family)
|
||||
break;
|
||||
|
||||
if(sock >= listen_sockets)
|
||||
sock = 0; /* If none is available, just use the first and hope for the best. */
|
||||
if(n->address.sa.sa_family != listen_socket[n->sock].sa.sa.sa_family) {
|
||||
for(int sock = 0; sock < listen_sockets; sock++) {
|
||||
if(n->address.sa.sa_family == listen_socket[sock].sa.sa.sa_family) {
|
||||
n->sock = sock;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Send the packet */
|
||||
|
||||
#if defined(SOL_IP) && defined(IP_TOS)
|
||||
if(priorityinheritance && origpriority != priority
|
||||
&& listen_socket[sock].sa.sa.sa_family == AF_INET) {
|
||||
&& listen_socket[n->sock].sa.sa.sa_family == AF_INET) {
|
||||
priority = origpriority;
|
||||
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Setting outgoing packet priority to %d", priority);
|
||||
if(setsockopt(listen_socket[sock].udp, SOL_IP, IP_TOS, &priority, sizeof priority)) /* SO_PRIORITY doesn't seem to work */
|
||||
if(setsockopt(listen_socket[n->sock].udp, SOL_IP, IP_TOS, &priority, sizeof(priority))) /* SO_PRIORITY doesn't seem to work */
|
||||
logger(LOG_ERR, "System call `%s' failed: %s", "setsockopt", strerror(errno));
|
||||
}
|
||||
#endif
|
||||
|
||||
if(sendto(listen_socket[sock].udp, (char *) &inpkt->seqno, inpkt->len, 0, &(n->address.sa), SALEN(n->address.sa)) < 0 && !sockwouldblock(sockerrno)) {
|
||||
if(sendto(listen_socket[n->sock].udp, (char *) &inpkt->seqno, inpkt->len, 0, &(n->address.sa), SALEN(n->address.sa)) < 0 && !sockwouldblock(sockerrno)) {
|
||||
if(sockmsgsize(sockerrno)) {
|
||||
if(n->maxmtu >= origlen)
|
||||
n->maxmtu = origlen - 1;
|
||||
|
@ -507,7 +508,7 @@ void send_packet(node_t *n, vpn_packet_t *packet) {
|
|||
memcpy(packet->data, mymac.x, ETH_ALEN);
|
||||
n->out_packets++;
|
||||
n->out_bytes += packet->len;
|
||||
write_packet(packet);
|
||||
devops.write(packet);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -631,6 +632,8 @@ void handle_incoming_vpn_data(int sock, short events, void *data) {
|
|||
return;
|
||||
}
|
||||
|
||||
n->sock = (intptr_t)data;
|
||||
|
||||
receive_udppacket(n, &pkt);
|
||||
}
|
||||
|
||||
|
@ -639,7 +642,7 @@ void handle_device_data(int sock, short events, void *data) {
|
|||
|
||||
packet.priority = 0;
|
||||
|
||||
if(read_packet(&packet)) {
|
||||
if(devops.read(&packet)) {
|
||||
myself->in_packets++;
|
||||
myself->in_bytes += packet.len;
|
||||
route(myself, &packet);
|
||||
|
|
156
src/net_setup.c
156
src/net_setup.c
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
net_setup.c -- Setup.
|
||||
Copyright (C) 1998-2005 Ivo Timmermans,
|
||||
2000-2010 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2000-2012 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2006 Scott Lamb <slamb@slamb.org>
|
||||
2010 Brandon Black <blblack@gmail.com>
|
||||
|
||||
|
@ -44,6 +44,7 @@
|
|||
|
||||
char *myport;
|
||||
static struct event device_ev;
|
||||
devops_t devops;
|
||||
|
||||
bool node_read_ecdsa_public_key(node_t *n) {
|
||||
if(ecdsa_active(&n->ecdsa))
|
||||
|
@ -151,8 +152,7 @@ bool read_rsa_public_key(connection_t *c) {
|
|||
fp = fopen(fname, "r");
|
||||
|
||||
if(!fp) {
|
||||
logger(LOG_ERR, "Error reading RSA public key file `%s': %s",
|
||||
fname, strerror(errno));
|
||||
logger(LOG_ERR, "Error reading RSA public key file `%s': %s", fname, strerror(errno));
|
||||
free(fname);
|
||||
return false;
|
||||
}
|
||||
|
@ -179,8 +179,7 @@ static bool read_ecdsa_private_key(void) {
|
|||
fp = fopen(fname, "r");
|
||||
|
||||
if(!fp) {
|
||||
logger(LOG_ERR, "Error reading ECDSA private key file `%s': %s",
|
||||
fname, strerror(errno));
|
||||
logger(LOG_ERR, "Error reading ECDSA private key file `%s': %s", fname, strerror(errno));
|
||||
free(fname);
|
||||
return false;
|
||||
}
|
||||
|
@ -349,7 +348,7 @@ void load_all_subnets(void) {
|
|||
static bool setup_myself(void) {
|
||||
config_t *cfg;
|
||||
subnet_t *subnet;
|
||||
char *name, *hostname, *mode, *afname, *cipher, *digest;
|
||||
char *name, *hostname, *mode, *afname, *cipher, *digest, *type;
|
||||
char *fname = NULL;
|
||||
char *address = NULL;
|
||||
char *envp[5];
|
||||
|
@ -475,6 +474,8 @@ static bool setup_myself(void) {
|
|||
myself->options |= OPTION_CLAMP_MSS;
|
||||
|
||||
get_config_bool(lookup_config(config_tree, "PriorityInheritance"), &priorityinheritance);
|
||||
get_config_bool(lookup_config(config_tree, "DecrementTTL"), &decrement_ttl);
|
||||
get_config_bool(lookup_config(config_tree, "Broadcast"), &broadcast);
|
||||
|
||||
#if !defined(SOL_IP) || !defined(IP_TOS)
|
||||
if(priorityinheritance)
|
||||
|
@ -589,7 +590,24 @@ static bool setup_myself(void) {
|
|||
|
||||
/* Open device */
|
||||
|
||||
if(!setup_device())
|
||||
devops = os_devops;
|
||||
|
||||
if(get_config_string(lookup_config(config_tree, "DeviceType"), &type)) {
|
||||
if(!strcasecmp(type, "dummy"))
|
||||
devops = dummy_devops;
|
||||
else if(!strcasecmp(type, "raw_socket"))
|
||||
devops = raw_socket_devops;
|
||||
#ifdef ENABLE_UML
|
||||
else if(!strcasecmp(type, "uml"))
|
||||
devops = uml_devops;
|
||||
#endif
|
||||
#ifdef ENABLE_VDE
|
||||
else if(!strcasecmp(type, "vde"))
|
||||
devops = vde_devops;
|
||||
#endif
|
||||
}
|
||||
|
||||
if(!devops.setup())
|
||||
return false;
|
||||
|
||||
if(device_fd >= 0) {
|
||||
|
@ -597,7 +615,7 @@ static bool setup_myself(void) {
|
|||
|
||||
if (event_add(&device_ev, NULL) < 0) {
|
||||
logger(LOG_ERR, "event_add failed: %s", strerror(errno));
|
||||
close_device();
|
||||
devops.close();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -620,72 +638,78 @@ static bool setup_myself(void) {
|
|||
|
||||
/* Open sockets */
|
||||
|
||||
get_config_string(lookup_config(config_tree, "BindToAddress"), &address);
|
||||
|
||||
hint.ai_family = addressfamily;
|
||||
hint.ai_socktype = SOCK_STREAM;
|
||||
hint.ai_protocol = IPPROTO_TCP;
|
||||
hint.ai_flags = AI_PASSIVE;
|
||||
|
||||
err = getaddrinfo(address, myport, &hint, &ai);
|
||||
|
||||
if(err || !ai) {
|
||||
logger(LOG_ERR, "System call `%s' failed: %s", "getaddrinfo",
|
||||
gai_strerror(err));
|
||||
return false;
|
||||
}
|
||||
|
||||
listen_sockets = 0;
|
||||
cfg = lookup_config(config_tree, "BindToAddress");
|
||||
|
||||
for(aip = ai; aip; aip = aip->ai_next) {
|
||||
listen_socket[listen_sockets].tcp =
|
||||
setup_listen_socket((sockaddr_t *) aip->ai_addr);
|
||||
do {
|
||||
get_config_string(cfg, &address);
|
||||
if(cfg)
|
||||
cfg = lookup_config_next(config_tree, cfg);
|
||||
|
||||
if(listen_socket[listen_sockets].tcp < 0)
|
||||
continue;
|
||||
hint.ai_family = addressfamily;
|
||||
hint.ai_socktype = SOCK_STREAM;
|
||||
hint.ai_protocol = IPPROTO_TCP;
|
||||
hint.ai_flags = AI_PASSIVE;
|
||||
|
||||
listen_socket[listen_sockets].udp =
|
||||
setup_vpn_in_socket((sockaddr_t *) aip->ai_addr);
|
||||
err = getaddrinfo(address, myport, &hint, &ai);
|
||||
free(address);
|
||||
|
||||
if(listen_socket[listen_sockets].udp < 0) {
|
||||
close(listen_socket[listen_sockets].tcp);
|
||||
continue;
|
||||
if(err || !ai) {
|
||||
logger(LOG_ERR, "System call `%s' failed: %s", "getaddrinfo",
|
||||
gai_strerror(err));
|
||||
return false;
|
||||
}
|
||||
|
||||
event_set(&listen_socket[listen_sockets].ev_tcp,
|
||||
listen_socket[listen_sockets].tcp,
|
||||
EV_READ|EV_PERSIST,
|
||||
handle_new_meta_connection, NULL);
|
||||
if(event_add(&listen_socket[listen_sockets].ev_tcp, NULL) < 0) {
|
||||
logger(LOG_ERR, "event_add failed: %s", strerror(errno));
|
||||
abort();
|
||||
for(aip = ai; aip; aip = aip->ai_next) {
|
||||
if(listen_sockets >= MAXSOCKETS) {
|
||||
logger(LOG_ERR, "Too many listening sockets");
|
||||
return false;
|
||||
}
|
||||
|
||||
listen_socket[listen_sockets].tcp =
|
||||
setup_listen_socket((sockaddr_t *) aip->ai_addr);
|
||||
|
||||
if(listen_socket[listen_sockets].tcp < 0)
|
||||
continue;
|
||||
|
||||
listen_socket[listen_sockets].udp =
|
||||
setup_vpn_in_socket((sockaddr_t *) aip->ai_addr);
|
||||
|
||||
if(listen_socket[listen_sockets].udp < 0) {
|
||||
close(listen_socket[listen_sockets].tcp);
|
||||
continue;
|
||||
}
|
||||
|
||||
event_set(&listen_socket[listen_sockets].ev_tcp,
|
||||
listen_socket[listen_sockets].tcp,
|
||||
EV_READ|EV_PERSIST,
|
||||
handle_new_meta_connection, NULL);
|
||||
if(event_add(&listen_socket[listen_sockets].ev_tcp, NULL) < 0) {
|
||||
logger(LOG_ERR, "event_add failed: %s", strerror(errno));
|
||||
abort();
|
||||
}
|
||||
|
||||
event_set(&listen_socket[listen_sockets].ev_udp,
|
||||
listen_socket[listen_sockets].udp,
|
||||
EV_READ|EV_PERSIST,
|
||||
handle_incoming_vpn_data, (void *)(intptr_t)listen_sockets);
|
||||
if(event_add(&listen_socket[listen_sockets].ev_udp, NULL) < 0) {
|
||||
logger(LOG_ERR, "event_add failed: %s", strerror(errno));
|
||||
abort();
|
||||
}
|
||||
|
||||
ifdebug(CONNECTIONS) {
|
||||
hostname = sockaddr2hostname((sockaddr_t *) aip->ai_addr);
|
||||
logger(LOG_NOTICE, "Listening on %s", hostname);
|
||||
free(hostname);
|
||||
}
|
||||
|
||||
memcpy(&listen_socket[listen_sockets].sa, aip->ai_addr, aip->ai_addrlen);
|
||||
listen_sockets++;
|
||||
}
|
||||
|
||||
event_set(&listen_socket[listen_sockets].ev_udp,
|
||||
listen_socket[listen_sockets].udp,
|
||||
EV_READ|EV_PERSIST,
|
||||
handle_incoming_vpn_data, NULL);
|
||||
if(event_add(&listen_socket[listen_sockets].ev_udp, NULL) < 0) {
|
||||
logger(LOG_ERR, "event_add failed: %s", strerror(errno));
|
||||
abort();
|
||||
}
|
||||
|
||||
ifdebug(CONNECTIONS) {
|
||||
hostname = sockaddr2hostname((sockaddr_t *) aip->ai_addr);
|
||||
logger(LOG_NOTICE, "Listening on %s", hostname);
|
||||
free(hostname);
|
||||
}
|
||||
|
||||
memcpy(&listen_socket[listen_sockets].sa, aip->ai_addr, aip->ai_addrlen);
|
||||
listen_sockets++;
|
||||
|
||||
if(listen_sockets >= MAXSOCKETS) {
|
||||
logger(LOG_WARNING, "Maximum of %d listening sockets reached", MAXSOCKETS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
freeaddrinfo(ai);
|
||||
freeaddrinfo(ai);
|
||||
} while(cfg);
|
||||
|
||||
if(listen_sockets)
|
||||
logger(LOG_NOTICE, "Ready");
|
||||
|
@ -778,7 +802,7 @@ void close_network_connections(void) {
|
|||
for(i = 0; i < 4; i++)
|
||||
free(envp[i]);
|
||||
|
||||
close_device();
|
||||
devops.close();
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
net_socket.c -- Handle various kinds of sockets.
|
||||
Copyright (C) 1998-2005 Ivo Timmermans,
|
||||
2000-2010 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2000-2012 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2006 Scott Lamb <slamb@slamb.org>
|
||||
2009 Florian Forster <octo@verplant.org>
|
||||
|
||||
|
@ -33,8 +33,6 @@
|
|||
#include "utils.h"
|
||||
#include "xalloc.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
/* Needed on Mac OS/X */
|
||||
#ifndef SOL_TCP
|
||||
#define SOL_TCP IPPROTO_TCP
|
||||
|
@ -109,63 +107,6 @@ static bool bind_to_interface(int sd) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool bind_to_address(connection_t *c) {
|
||||
char *node;
|
||||
struct addrinfo *ai_list;
|
||||
struct addrinfo *ai_ptr;
|
||||
struct addrinfo ai_hints;
|
||||
int status;
|
||||
|
||||
assert(c != NULL);
|
||||
assert(c->socket >= 0);
|
||||
|
||||
node = NULL;
|
||||
if(!get_config_string(lookup_config(config_tree, "BindToAddress"),
|
||||
&node))
|
||||
return true;
|
||||
|
||||
assert(node != NULL);
|
||||
|
||||
memset(&ai_hints, 0, sizeof(ai_hints));
|
||||
ai_hints.ai_family = c->address.sa.sa_family;
|
||||
/* We're called from `do_outgoing_connection' only. */
|
||||
ai_hints.ai_socktype = SOCK_STREAM;
|
||||
ai_hints.ai_protocol = IPPROTO_TCP;
|
||||
|
||||
ai_list = NULL;
|
||||
|
||||
status = getaddrinfo(node, /* service = */ NULL,
|
||||
&ai_hints, &ai_list);
|
||||
if(status) {
|
||||
logger(LOG_WARNING, "Error looking up %s port %s: %s",
|
||||
node, "any", gai_strerror(status));
|
||||
free(node);
|
||||
return false;
|
||||
}
|
||||
assert(ai_list != NULL);
|
||||
|
||||
status = -1;
|
||||
for(ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) {
|
||||
status = bind(c->socket,
|
||||
ai_list->ai_addr, ai_list->ai_addrlen);
|
||||
if(!status)
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if(status) {
|
||||
logger(LOG_ERR, "Can't bind to %s/tcp: %s", node, sockstrerror(sockerrno));
|
||||
} else ifdebug(CONNECTIONS) {
|
||||
logger(LOG_DEBUG, "Successfully bound outgoing "
|
||||
"TCP socket to %s", node);
|
||||
}
|
||||
|
||||
free(node);
|
||||
freeaddrinfo(ai_list);
|
||||
|
||||
return status ? false : true;
|
||||
}
|
||||
|
||||
int setup_listen_socket(const sockaddr_t *sa) {
|
||||
int nfd;
|
||||
char *addrstr;
|
||||
|
@ -179,6 +120,10 @@ int setup_listen_socket(const sockaddr_t *sa) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
#ifdef FD_CLOEXEC
|
||||
fcntl(nfd, F_SETFD, FD_CLOEXEC);
|
||||
#endif
|
||||
|
||||
/* Optimize TCP settings */
|
||||
|
||||
option = 1;
|
||||
|
@ -237,6 +182,10 @@ int setup_vpn_in_socket(const sockaddr_t *sa) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
#ifdef FD_CLOEXEC
|
||||
fcntl(nfd, F_SETFD, FD_CLOEXEC);
|
||||
#endif
|
||||
|
||||
#ifdef O_NONBLOCK
|
||||
{
|
||||
int flags = fcntl(nfd, F_GETFL);
|
||||
|
@ -409,6 +358,10 @@ begin:
|
|||
|
||||
c->socket = socket(c->address.sa.sa_family, SOCK_STREAM, IPPROTO_TCP);
|
||||
|
||||
#ifdef FD_CLOEXEC
|
||||
fcntl(c->socket, F_SETFD, FD_CLOEXEC);
|
||||
#endif
|
||||
|
||||
if(c->socket == -1) {
|
||||
ifdebug(CONNECTIONS) logger(LOG_ERR, "Creating socket for %s failed: %s", c->hostname, sockstrerror(sockerrno));
|
||||
goto begin;
|
||||
|
@ -421,7 +374,6 @@ begin:
|
|||
#endif
|
||||
|
||||
bind_to_interface(c->socket);
|
||||
bind_to_address(c);
|
||||
|
||||
/* Optimize TCP settings */
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ typedef struct node_t {
|
|||
char *name; /* name of this node */
|
||||
uint32_t options; /* options turned on for this node */
|
||||
|
||||
int sock; /* Socket to use for outgoing UDP packets */
|
||||
sockaddr_t address; /* his real (internet) ip to send UDP packets to */
|
||||
char *hostname; /* the hostname of its real ip */
|
||||
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
#include "system.h"
|
||||
|
||||
#include <openssl/obj_mac.h>
|
||||
|
||||
#include "digest.h"
|
||||
#include "prf.h"
|
||||
|
||||
|
|
|
@ -96,7 +96,7 @@ bool send_request(connection_t *c, const char *format, ...) {
|
|||
|
||||
request[len++] = '\n';
|
||||
|
||||
if(c == broadcast) {
|
||||
if(c == everyone) {
|
||||
broadcast_meta(NULL, request, len);
|
||||
return true;
|
||||
} else
|
||||
|
|
|
@ -651,7 +651,7 @@ bool ack_h(connection_t *c, char *request) {
|
|||
if(tunnelserver)
|
||||
send_add_edge(c, c->edge);
|
||||
else
|
||||
send_add_edge(broadcast, c->edge);
|
||||
send_add_edge(everyone, c->edge);
|
||||
|
||||
/* Run MST and SSSP algorithms */
|
||||
|
||||
|
|
|
@ -254,7 +254,7 @@ bool del_edge_h(connection_t *c, char *request) {
|
|||
e = lookup_edge(to, myself);
|
||||
if(e) {
|
||||
if(!tunnelserver)
|
||||
send_del_edge(broadcast, e);
|
||||
send_del_edge(everyone, e);
|
||||
edge_del(e);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ void send_key_changed(void) {
|
|||
splay_node_t *node;
|
||||
connection_t *c;
|
||||
|
||||
send_request(broadcast, "%d %x %s", KEY_CHANGED, rand(), myself->name);
|
||||
send_request(everyone, "%d %x %s", KEY_CHANGED, rand(), myself->name);
|
||||
|
||||
/* Immediately send new keys to directly connected nodes to keep UDP mappings alive */
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
device.c -- raw socket
|
||||
Copyright (C) 2002-2005 Ivo Timmermans,
|
||||
2002-2009 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2002-2012 Guus Sliepen <guus@tinc-vpn.org>
|
||||
|
||||
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
|
||||
|
@ -20,7 +20,9 @@
|
|||
|
||||
#include "system.h"
|
||||
|
||||
#ifdef HAVE_NETPACKET_PACKET_H
|
||||
#include <netpacket/packet.h>
|
||||
#endif
|
||||
|
||||
#include "conf.h"
|
||||
#include "device.h"
|
||||
|
@ -30,16 +32,13 @@
|
|||
#include "route.h"
|
||||
#include "xalloc.h"
|
||||
|
||||
int device_fd = -1;
|
||||
char *device = NULL;
|
||||
char *iface = NULL;
|
||||
static char ifrname[IFNAMSIZ];
|
||||
#if defined(PF_PACKET) && defined(ETH_P_ALL) && defined(AF_PACKET)
|
||||
static char *device_info;
|
||||
|
||||
static uint64_t device_total_in = 0;
|
||||
static uint64_t device_total_out = 0;
|
||||
|
||||
bool setup_device(void) {
|
||||
static bool setup_device(void) {
|
||||
struct ifreq ifr;
|
||||
struct sockaddr_ll sa;
|
||||
|
||||
|
@ -58,6 +57,11 @@ bool setup_device(void) {
|
|||
}
|
||||
|
||||
memset(&ifr, 0, sizeof ifr);
|
||||
|
||||
#ifdef FD_CLOEXEC
|
||||
fcntl(device_fd, F_SETFD, FD_CLOEXEC);
|
||||
#endif
|
||||
|
||||
strncpy(ifr.ifr_ifrn.ifrn_name, iface, IFNAMSIZ);
|
||||
if(ioctl(device_fd, SIOCGIFINDEX, &ifr)) {
|
||||
close(device_fd);
|
||||
|
@ -81,14 +85,14 @@ bool setup_device(void) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void close_device(void) {
|
||||
static void close_device(void) {
|
||||
close(device_fd);
|
||||
|
||||
free(device);
|
||||
free(iface);
|
||||
}
|
||||
|
||||
bool read_packet(vpn_packet_t *packet) {
|
||||
static bool read_packet(vpn_packet_t *packet) {
|
||||
int inlen;
|
||||
|
||||
if((inlen = read(device_fd, packet->data, MTU)) <= 0) {
|
||||
|
@ -107,7 +111,7 @@ bool read_packet(vpn_packet_t *packet) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool write_packet(vpn_packet_t *packet) {
|
||||
static bool write_packet(vpn_packet_t *packet) {
|
||||
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Writing packet of %d bytes to %s",
|
||||
packet->len, device_info);
|
||||
|
||||
|
@ -122,8 +126,32 @@ bool write_packet(vpn_packet_t *packet) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void dump_device_stats(void) {
|
||||
static void dump_device_stats(void) {
|
||||
logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device);
|
||||
logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in);
|
||||
logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out);
|
||||
}
|
||||
|
||||
const devops_t raw_socket_devops = {
|
||||
.setup = setup_device,
|
||||
.close = close_device,
|
||||
.read = read_packet,
|
||||
.write = write_packet,
|
||||
.dump_stats = dump_device_stats,
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
static bool not_supported(void) {
|
||||
logger(LOG_ERR, "Raw socket device not supported on this platform");
|
||||
return false;
|
||||
}
|
||||
|
||||
const devops_t raw_socket_devops = {
|
||||
.setup = not_supported,
|
||||
.close = NULL,
|
||||
.read = NULL,
|
||||
.write = NULL,
|
||||
.dump_stats = NULL,
|
||||
};
|
||||
#endif
|
59
src/route.c
59
src/route.c
|
@ -36,10 +36,12 @@
|
|||
|
||||
rmode_t routing_mode = RMODE_ROUTER;
|
||||
fmode_t forwarding_mode = FMODE_INTERNAL;
|
||||
bool decrement_ttl = true;
|
||||
bool directonly = false;
|
||||
bool priorityinheritance = false;
|
||||
int macexpire = 600;
|
||||
bool overwrite_mac = false;
|
||||
bool broadcast = true;
|
||||
mac_t mymac = {{0xFE, 0xFD, 0, 0, 0, 0}};
|
||||
bool pcap = false;
|
||||
|
||||
|
@ -439,11 +441,11 @@ static void route_ipv4(node_t *source, vpn_packet_t *packet) {
|
|||
if(!checklength(source, packet, ether_size + ip_size))
|
||||
return;
|
||||
|
||||
if(((packet->data[30] & 0xf0) == 0xe0) || (
|
||||
if(broadcast && (((packet->data[30] & 0xf0) == 0xe0) || (
|
||||
packet->data[30] == 255 &&
|
||||
packet->data[31] == 255 &&
|
||||
packet->data[32] == 255 &&
|
||||
packet->data[33] == 255))
|
||||
packet->data[33] == 255)))
|
||||
broadcast_packet(source, packet);
|
||||
else
|
||||
route_ipv4_unicast(source, packet);
|
||||
|
@ -731,7 +733,7 @@ static void route_ipv6(node_t *source, vpn_packet_t *packet) {
|
|||
return;
|
||||
}
|
||||
|
||||
if(packet->data[38] == 255)
|
||||
if(broadcast && packet->data[38] == 255)
|
||||
broadcast_packet(source, packet);
|
||||
else
|
||||
route_ipv6_unicast(source, packet);
|
||||
|
@ -821,7 +823,8 @@ static void route_mac(node_t *source, vpn_packet_t *packet) {
|
|||
subnet = lookup_subnet_mac(NULL, &dest);
|
||||
|
||||
if(!subnet) {
|
||||
broadcast_packet(source, packet);
|
||||
if(broadcast)
|
||||
broadcast_packet(source, packet);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -876,6 +879,50 @@ static void send_pcap(vpn_packet_t *packet) {
|
|||
}
|
||||
}
|
||||
|
||||
static bool do_decrement_ttl(node_t *source, vpn_packet_t *packet) {
|
||||
uint16_t type = packet->data[12] << 8 | packet->data[13];
|
||||
|
||||
switch (type) {
|
||||
case ETH_P_IP:
|
||||
if(!checklength(source, packet, 14 + 32))
|
||||
return false;
|
||||
|
||||
if(packet->data[22] < 1) {
|
||||
route_ipv4_unreachable(source, packet, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16_t old = packet->data[22] << 8 | packet->data[23];
|
||||
packet->data[22]--;
|
||||
uint16_t new = packet->data[22] << 8 | packet->data[23];
|
||||
|
||||
uint32_t checksum = packet->data[24] << 8 | packet->data[25];
|
||||
checksum += old + (~new & 0xFFFF);
|
||||
while(checksum >> 16)
|
||||
checksum = (checksum & 0xFFFF) + (checksum >> 16);
|
||||
packet->data[24] = checksum >> 8;
|
||||
packet->data[25] = checksum & 0xff;
|
||||
|
||||
return true;
|
||||
|
||||
case ETH_P_IPV6:
|
||||
if(!checklength(source, packet, 14 + 40))
|
||||
return false;
|
||||
|
||||
if(packet->data[21] < 1) {
|
||||
route_ipv6_unreachable(source, packet, ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_TRANSIT);
|
||||
return false;
|
||||
}
|
||||
|
||||
packet->data[21]--;
|
||||
|
||||
return true;
|
||||
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void route(node_t *source, vpn_packet_t *packet) {
|
||||
if(pcap)
|
||||
send_pcap(packet);
|
||||
|
@ -888,6 +935,10 @@ void route(node_t *source, vpn_packet_t *packet) {
|
|||
if(!checklength(source, packet, ether_size))
|
||||
return;
|
||||
|
||||
if(decrement_ttl && source != myself)
|
||||
if(!do_decrement_ttl(source, packet))
|
||||
return;
|
||||
|
||||
switch (routing_mode) {
|
||||
case RMODE_ROUTER:
|
||||
{
|
||||
|
|
|
@ -38,8 +38,10 @@ typedef enum fmode_t {
|
|||
|
||||
extern rmode_t routing_mode;
|
||||
extern fmode_t forwarding_mode;
|
||||
extern bool decrement_ttl;
|
||||
extern bool directonly;
|
||||
extern bool overwrite_mac;
|
||||
extern bool broadcast;
|
||||
extern bool priorityinheritance;
|
||||
extern int macexpire;
|
||||
extern bool pcap;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
device.c -- Interaction with Solaris tun device
|
||||
Copyright (C) 2001-2005 Ivo Timmermans,
|
||||
2001-2011 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2001-2012 Guus Sliepen <guus@tinc-vpn.org>
|
||||
|
||||
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
|
||||
|
@ -35,7 +35,7 @@
|
|||
#define DEFAULT_DEVICE "/dev/tun"
|
||||
|
||||
int device_fd = -1;
|
||||
int ip_fd = -1, if_fd = -1;
|
||||
static int ip_fd = -1, if_fd = -1;
|
||||
char *device = NULL;
|
||||
char *iface = NULL;
|
||||
static char *device_info = NULL;
|
||||
|
@ -43,7 +43,7 @@ static char *device_info = NULL;
|
|||
static uint64_t device_total_in = 0;
|
||||
static uint64_t device_total_out = 0;
|
||||
|
||||
bool setup_device(void) {
|
||||
static bool setup_device(void) {
|
||||
int ppa;
|
||||
char *ptr;
|
||||
|
||||
|
@ -55,6 +55,10 @@ bool setup_device(void) {
|
|||
return false;
|
||||
}
|
||||
|
||||
#ifdef FD_CLOEXEC
|
||||
fcntl(device_fd, F_SETFD, FD_CLOEXEC);
|
||||
#endif
|
||||
|
||||
ppa = 0;
|
||||
|
||||
ptr = device;
|
||||
|
@ -67,6 +71,10 @@ bool setup_device(void) {
|
|||
return false;
|
||||
}
|
||||
|
||||
#ifdef FD_CLOEXEC
|
||||
fcntl(ip_fd, F_SETFD, FD_CLOEXEC);
|
||||
#endif
|
||||
|
||||
/* Assign a new PPA and get its unit number. */
|
||||
if((ppa = ioctl(device_fd, TUNNEWPPA, ppa)) < 0) {
|
||||
logger(LOG_ERR, "Can't assign new interface: %s", strerror(errno));
|
||||
|
@ -79,6 +87,10 @@ bool setup_device(void) {
|
|||
return false;
|
||||
}
|
||||
|
||||
#ifdef FD_CLOEXEC
|
||||
fcntl(if_fd, F_SETFD, FD_CLOEXEC);
|
||||
#endif
|
||||
|
||||
if(ioctl(if_fd, I_PUSH, "ip") < 0) {
|
||||
logger(LOG_ERR, "Can't push IP module: %s", strerror(errno));
|
||||
return false;
|
||||
|
@ -105,7 +117,7 @@ bool setup_device(void) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void close_device(void) {
|
||||
static void close_device(void) {
|
||||
close(if_fd);
|
||||
close(ip_fd);
|
||||
close(device_fd);
|
||||
|
@ -114,7 +126,7 @@ void close_device(void) {
|
|||
free(iface);
|
||||
}
|
||||
|
||||
bool read_packet(vpn_packet_t *packet) {
|
||||
static bool read_packet(vpn_packet_t *packet) {
|
||||
int inlen;
|
||||
|
||||
if((inlen = read(device_fd, packet->data + 14, MTU - 14)) <= 0) {
|
||||
|
@ -149,7 +161,7 @@ bool read_packet(vpn_packet_t *packet) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool write_packet(vpn_packet_t *packet) {
|
||||
static bool write_packet(vpn_packet_t *packet) {
|
||||
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Writing packet of %d bytes to %s",
|
||||
packet->len, device_info);
|
||||
|
||||
|
@ -164,8 +176,16 @@ bool write_packet(vpn_packet_t *packet) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void dump_device_stats(void) {
|
||||
static void dump_device_stats(void) {
|
||||
logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device);
|
||||
logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in);
|
||||
logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out);
|
||||
}
|
||||
|
||||
const devops_t os_devops = {
|
||||
.setup = setup_device,
|
||||
.close = close_device,
|
||||
.read = read_packet,
|
||||
.write = write_packet,
|
||||
.dump_stats = dump_device_stats,
|
||||
};
|
||||
|
|
30
src/tincd.c
30
src/tincd.c
|
@ -107,6 +107,7 @@ static struct option const long_options[] = {
|
|||
{"user", required_argument, NULL, 'U'},
|
||||
{"logfile", optional_argument, NULL, 4},
|
||||
{"pidfile", required_argument, NULL, 5},
|
||||
{"option", required_argument, NULL, 'o'},
|
||||
{NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
|
@ -122,18 +123,18 @@ static void usage(bool status) {
|
|||
program_name);
|
||||
else {
|
||||
printf("Usage: %s [option]...\n\n", program_name);
|
||||
printf( " -c, --config=DIR Read configuration options from DIR.\n"
|
||||
" -D, --no-detach Don't fork and detach.\n"
|
||||
" -d, --debug[=LEVEL] Increase debug level or set it to LEVEL.\n"
|
||||
" -n, --net=NETNAME Connect to net NETNAME.\n"
|
||||
" -L, --mlock Lock tinc into main memory.\n"
|
||||
" --logfile[=FILENAME] Write log entries to a logfile.\n"
|
||||
" --pidfile=FILENAME Write PID and control socket cookie to FILENAME.\n"
|
||||
" --bypass-security Disables meta protocol security, for debugging.\n"
|
||||
" -o [HOST.]KEY=VALUE Set global/host configuration value.\n"
|
||||
" -R, --chroot chroot to NET dir at startup.\n"
|
||||
" -U, --user=USER setuid to given USER at startup.\n" " --help Display this help and exit.\n"
|
||||
" --version Output version information and exit.\n\n");
|
||||
printf( " -c, --config=DIR Read configuration options from DIR.\n"
|
||||
" -D, --no-detach Don't fork and detach.\n"
|
||||
" -d, --debug[=LEVEL] Increase debug level or set it to LEVEL.\n"
|
||||
" -n, --net=NETNAME Connect to net NETNAME.\n"
|
||||
" -L, --mlock Lock tinc into main memory.\n"
|
||||
" --logfile[=FILENAME] Write log entries to a logfile.\n"
|
||||
" --pidfile=FILENAME Write PID and control socket cookie to FILENAME.\n"
|
||||
" --bypass-security Disables meta protocol security, for debugging.\n"
|
||||
" -o, --option[HOST.]KEY=VALUE Set global/host configuration value.\n"
|
||||
" -R, --chroot chroot to NET dir at startup.\n"
|
||||
" -U, --user=USER setuid to given USER at startup.\n" " --help Display this help and exit.\n"
|
||||
" --version Output version information and exit.\n\n");
|
||||
printf("Report bugs to tinc@tinc-vpn.org.\n");
|
||||
}
|
||||
}
|
||||
|
@ -416,6 +417,7 @@ int main2(int argc, char **argv) {
|
|||
InitializeCriticalSection(&mutex);
|
||||
EnterCriticalSection(&mutex);
|
||||
#endif
|
||||
char *priority = NULL;
|
||||
|
||||
if(!detach())
|
||||
return 1;
|
||||
|
@ -445,8 +447,6 @@ int main2(int argc, char **argv) {
|
|||
|
||||
/* Change process priority */
|
||||
|
||||
char *priority = NULL;
|
||||
|
||||
if(get_config_string(lookup_config(config_tree, "ProcessPriority"), &priority)) {
|
||||
if(!strcasecmp(priority, "Normal")) {
|
||||
if (setpriority(NORMAL_PRIORITY_CLASS) != 0) {
|
||||
|
@ -483,7 +483,7 @@ int main2(int argc, char **argv) {
|
|||
/* Shutdown properly. */
|
||||
|
||||
ifdebug(CONNECTIONS)
|
||||
dump_device_stats();
|
||||
devops.dump_stats();
|
||||
|
||||
close_network_connections();
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
device.c -- UML network socket
|
||||
Copyright (C) 2002-2005 Ivo Timmermans,
|
||||
2002-2009 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2002-2012 Guus Sliepen <guus@tinc-vpn.org>
|
||||
|
||||
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
|
||||
|
@ -28,19 +28,17 @@
|
|||
#include "logger.h"
|
||||
#include "utils.h"
|
||||
#include "route.h"
|
||||
#include "xalloc.h"
|
||||
|
||||
int device_fd = -1;
|
||||
static int listen_fd = -1;
|
||||
static int request_fd = -1;
|
||||
static int data_fd = -1;
|
||||
static int write_fd = -1;
|
||||
static int state = 0;
|
||||
char *device = NULL;
|
||||
char *iface = NULL;
|
||||
static char *device_info;
|
||||
|
||||
extern char *identname;
|
||||
extern bool running;
|
||||
extern volatile bool running;
|
||||
|
||||
static uint64_t device_total_in = 0;
|
||||
static uint64_t device_total_out = 0;
|
||||
|
@ -56,7 +54,7 @@ static struct request {
|
|||
|
||||
static struct sockaddr_un data_sun;
|
||||
|
||||
bool setup_device(void) {
|
||||
static bool setup_device(void) {
|
||||
struct sockaddr_un listen_sun;
|
||||
static const int one = 1;
|
||||
struct {
|
||||
|
@ -79,6 +77,10 @@ bool setup_device(void) {
|
|||
return false;
|
||||
}
|
||||
|
||||
#ifdef FD_CLOEXEC
|
||||
fcntl(write_fd, F_SETFD, FD_CLOEXEC);
|
||||
#endif
|
||||
|
||||
setsockopt(write_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof one);
|
||||
|
||||
if(fcntl(write_fd, F_SETFL, O_NONBLOCK) < 0) {
|
||||
|
@ -93,6 +95,10 @@ bool setup_device(void) {
|
|||
return false;
|
||||
}
|
||||
|
||||
#ifdef FD_CLOEXEC
|
||||
fcntl(data_fd, F_SETFD, FD_CLOEXEC);
|
||||
#endif
|
||||
|
||||
setsockopt(data_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof one);
|
||||
|
||||
if(fcntl(data_fd, F_SETFL, O_NONBLOCK) < 0) {
|
||||
|
@ -120,6 +126,10 @@ bool setup_device(void) {
|
|||
return false;
|
||||
}
|
||||
|
||||
#ifdef FD_CLOEXEC
|
||||
fcntl(device_fd, F_SETFD, FD_CLOEXEC);
|
||||
#endif
|
||||
|
||||
setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof one);
|
||||
|
||||
if(fcntl(listen_fd, F_SETFL, O_NONBLOCK) < 0) {
|
||||
|
@ -169,13 +179,13 @@ void close_device(void) {
|
|||
if(iface) free(iface);
|
||||
}
|
||||
|
||||
bool read_packet(vpn_packet_t *packet) {
|
||||
static bool read_packet(vpn_packet_t *packet) {
|
||||
int inlen;
|
||||
|
||||
switch(state) {
|
||||
case 0: {
|
||||
struct sockaddr sa;
|
||||
int salen = sizeof sa;
|
||||
socklen_t salen = sizeof sa;
|
||||
|
||||
request_fd = accept(listen_fd, &sa, &salen);
|
||||
if(request_fd < 0) {
|
||||
|
@ -183,6 +193,10 @@ bool read_packet(vpn_packet_t *packet) {
|
|||
return false;
|
||||
}
|
||||
|
||||
#ifdef FD_CLOEXEC
|
||||
fcntl(request_fd, F_SETFD, FD_CLOEXEC);
|
||||
#endif
|
||||
|
||||
if(fcntl(listen_fd, F_SETFL, O_NONBLOCK) < 0) {
|
||||
logger(LOG_ERR, "System call `%s' failed: %s", "fcntl", strerror(errno));
|
||||
running = false;
|
||||
|
@ -244,10 +258,14 @@ bool read_packet(vpn_packet_t *packet) {
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
default:
|
||||
logger(LOG_ERR, "Invalid value for state variable in " __FILE__);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
bool write_packet(vpn_packet_t *packet) {
|
||||
static bool write_packet(vpn_packet_t *packet) {
|
||||
if(state != 2) {
|
||||
ifdebug(TRAFFIC) logger(LOG_DEBUG, "Dropping packet of %d bytes to %s: not connected to UML yet",
|
||||
packet->len, device_info);
|
||||
|
@ -271,8 +289,16 @@ bool write_packet(vpn_packet_t *packet) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void dump_device_stats(void) {
|
||||
static void dump_device_stats(void) {
|
||||
logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device);
|
||||
logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in);
|
||||
logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out);
|
||||
}
|
||||
|
||||
const devops_t uml_devops = {
|
||||
.setup = setup_device,
|
||||
.close = close_device,
|
||||
.read = read_packet,
|
||||
.write = write_packet,
|
||||
.dump_stats = dump_device_stats,
|
||||
};
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
device.c -- VDE plug
|
||||
Copyright (C) 2011 Guus Sliepen <guus@tinc-vpn.org>
|
||||
Copyright (C) 2012 Guus Sliepen <guus@tinc-vpn.org>
|
||||
|
||||
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
|
||||
|
@ -29,22 +29,19 @@
|
|||
#include "route.h"
|
||||
#include "xalloc.h"
|
||||
|
||||
int device_fd = -1;
|
||||
static struct vdepluglib plug;
|
||||
static struct vdeconn *conn = NULL;
|
||||
static int port = 0;
|
||||
static char *group = NULL;
|
||||
char *device = NULL;
|
||||
char *iface = NULL;
|
||||
static char *device_info;
|
||||
|
||||
extern char *identname;
|
||||
extern bool running;
|
||||
extern volatile bool running;
|
||||
|
||||
static uint64_t device_total_in = 0;
|
||||
static uint64_t device_total_out = 0;
|
||||
|
||||
bool setup_device(void) {
|
||||
static bool setup_device(void) {
|
||||
libvdeplug_dynopen(plug);
|
||||
|
||||
if(!plug.dl_handle) {
|
||||
|
@ -77,6 +74,10 @@ bool setup_device(void) {
|
|||
|
||||
device_fd = plug.vde_datafd(conn);
|
||||
|
||||
#ifdef FD_CLOEXEC
|
||||
fcntl(device_fd, F_SETFD, FD_CLOEXEC);
|
||||
#endif
|
||||
|
||||
logger(LOG_INFO, "%s is a %s", device, device_info);
|
||||
|
||||
if(routing_mode == RMODE_ROUTER)
|
||||
|
@ -85,7 +86,7 @@ bool setup_device(void) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void close_device(void) {
|
||||
static void close_device(void) {
|
||||
if(conn)
|
||||
plug.vde_close(conn);
|
||||
|
||||
|
@ -97,7 +98,7 @@ void close_device(void) {
|
|||
free(iface);
|
||||
}
|
||||
|
||||
bool read_packet(vpn_packet_t *packet) {
|
||||
static bool read_packet(vpn_packet_t *packet) {
|
||||
int lenin = plug.vde_recv(conn, packet->data, MTU, 0);
|
||||
if(lenin <= 0) {
|
||||
logger(LOG_ERR, "Error while reading from %s %s: %s", device_info, device, strerror(errno));
|
||||
|
@ -112,7 +113,7 @@ bool read_packet(vpn_packet_t *packet) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool write_packet(vpn_packet_t *packet) {
|
||||
static bool write_packet(vpn_packet_t *packet) {
|
||||
if(plug.vde_send(conn, packet->data, packet->len, 0) < 0) {
|
||||
if(errno != EINTR && errno != EAGAIN) {
|
||||
logger(LOG_ERR, "Can't write to %s %s: %s", device_info, device, strerror(errno));
|
||||
|
@ -127,8 +128,16 @@ bool write_packet(vpn_packet_t *packet) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void dump_device_stats(void) {
|
||||
static void dump_device_stats(void) {
|
||||
logger(LOG_DEBUG, "Statistics for %s %s:", device_info, device);
|
||||
logger(LOG_DEBUG, " total bytes in: %10"PRIu64, device_total_in);
|
||||
logger(LOG_DEBUG, " total bytes out: %10"PRIu64, device_total_out);
|
||||
}
|
||||
|
||||
const devops_t vde_devops = {
|
||||
.setup = setup_device,
|
||||
.close = close_device,
|
||||
.read = read_packet,
|
||||
.write = write_packet,
|
||||
.dump_stats = dump_device_stats,
|
||||
};
|
Loading…
Reference in a new issue