Merged new env
This commit is contained in:
commit
557adb0695
31 changed files with 543 additions and 133 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -33,6 +33,9 @@
|
|||
/src/version_git.h
|
||||
/stamp-h1
|
||||
/test-driver
|
||||
/test/*.test.*
|
||||
/test/*.log
|
||||
/test/*.trs
|
||||
Makefile
|
||||
Makefile.in
|
||||
core*
|
||||
|
|
|
@ -234,6 +234,10 @@ Do NOT connect multiple
|
|||
.Nm tinc
|
||||
daemons to the same multicast address, this will very likely cause routing loops.
|
||||
Also note that this can cause decrypted VPN packets to be sent out on a real network if misconfigured.
|
||||
.It fd
|
||||
Use a file descriptor.
|
||||
All packets are read from this interface.
|
||||
Packets received for the local node are written to it.
|
||||
.It uml Pq not compiled in by default
|
||||
Create a UNIX socket with the filename specified by
|
||||
.Va Device ,
|
||||
|
|
|
@ -958,6 +958,12 @@ This can be used to connect to UML, QEMU or KVM instances listening on the same
|
|||
Do NOT connect multiple tinc daemons to the same multicast address, this will very likely cause routing loops.
|
||||
Also note that this can cause decrypted VPN packets to be sent out on a real network if misconfigured.
|
||||
|
||||
@cindex fd
|
||||
@item fd
|
||||
Use a file descriptor.
|
||||
All packets are read from this interface.
|
||||
Packets received for the local node are written to it.
|
||||
|
||||
@cindex UML
|
||||
@item uml (not compiled in by default)
|
||||
Create a UNIX socket with the filename specified by
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
## Produce this file with automake to get Makefile.in
|
||||
|
||||
sbin_PROGRAMS = tincd tinc
|
||||
check_PROGRAMS = sptps_test sptps_keypair
|
||||
EXTRA_PROGRAMS = sptps_test sptps_keypair
|
||||
|
||||
CLEANFILES = version_git.h
|
||||
|
@ -59,6 +60,7 @@ tincd_SOURCES = \
|
|||
edge.c edge.h \
|
||||
ethernet.h \
|
||||
event.c event.h \
|
||||
fd_device.c \
|
||||
graph.c graph.h \
|
||||
hash.c hash.h \
|
||||
have.h \
|
||||
|
|
|
@ -40,6 +40,7 @@ extern const devops_t os_devops;
|
|||
extern const devops_t dummy_devops;
|
||||
extern const devops_t raw_socket_devops;
|
||||
extern const devops_t multicast_devops;
|
||||
extern const devops_t fd_devops;
|
||||
extern const devops_t uml_devops;
|
||||
extern const devops_t vde_devops;
|
||||
extern devops_t devops;
|
||||
|
|
|
@ -25,6 +25,15 @@
|
|||
#define ETH_ALEN 6
|
||||
#endif
|
||||
|
||||
#ifndef ETH_HLEN
|
||||
#define ETH_HLEN 14
|
||||
#endif
|
||||
|
||||
#ifndef ETHER_TYPE_LEN
|
||||
#define ETHER_TYPE_LEN 2
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef ARPHRD_ETHER
|
||||
#define ARPHRD_ETHER 1
|
||||
#endif
|
||||
|
@ -45,6 +54,10 @@
|
|||
#define ETH_P_8021Q 0x8100
|
||||
#endif
|
||||
|
||||
#ifndef ETH_P_MAX
|
||||
#define ETH_P_MAX 0xFFFF
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRUCT_ETHER_HEADER
|
||||
struct ether_header {
|
||||
uint8_t ether_dhost[ETH_ALEN];
|
||||
|
|
|
@ -366,10 +366,13 @@ bool event_loop(void) {
|
|||
WSANETWORKEVENTS network_events;
|
||||
if (WSAEnumNetworkEvents(io->fd, io->event, &network_events) != 0)
|
||||
return false;
|
||||
if (network_events.lNetworkEvents & WRITE_EVENTS)
|
||||
io->cb(io->data, IO_WRITE);
|
||||
if (network_events.lNetworkEvents & READ_EVENTS)
|
||||
io->cb(io->data, IO_READ);
|
||||
/*
|
||||
The fd might be available for write too. However, if we already fired the read callback, that
|
||||
callback might have deleted the io (e.g. through terminate_connection()), so we can't fire the
|
||||
write callback here. Instead, we loop back and let the writable io loop above handle it.
|
||||
*/
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
123
src/fd_device.c
Normal file
123
src/fd_device.c
Normal file
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
fd_device.c -- Interaction with Android tun fd
|
||||
Copyright (C) 2001-2005 Ivo Timmermans,
|
||||
2001-2016 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2009 Grzegorz Dymarek <gregd72002@googlemail.com>
|
||||
2016 Pacien TRAN-GIRARD <pacien@pacien.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.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "system.h"
|
||||
#include "conf.h"
|
||||
#include "device.h"
|
||||
#include "ethernet.h"
|
||||
#include "logger.h"
|
||||
#include "net.h"
|
||||
#include "route.h"
|
||||
#include "utils.h"
|
||||
|
||||
static inline bool check_config(void) {
|
||||
if(routing_mode == RMODE_SWITCH) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Switch mode not supported (requires unsupported TAP device)!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!get_config_int(lookup_config(config_tree, "Device"), &device_fd)) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Could not read fd from configuration!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool setup_device(void) {
|
||||
if(!check_config()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(device_fd < 0) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Could not open %s: %s!", device, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
logger(DEBUG_ALWAYS, LOG_INFO, "fd/%d adapter set up.", device_fd);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void close_device(void) {
|
||||
close(device_fd);
|
||||
device_fd = -1;
|
||||
}
|
||||
|
||||
static inline uint16_t get_ip_ethertype(vpn_packet_t *packet) {
|
||||
switch (DATA(packet)[ETH_HLEN] >> 4) {
|
||||
case 4:
|
||||
return ETH_P_IP;
|
||||
|
||||
case 6:
|
||||
return ETH_P_IPV6;
|
||||
|
||||
default:
|
||||
return ETH_P_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void set_etherheader(vpn_packet_t *packet, uint16_t ethertype) {
|
||||
memset(DATA(packet), 0, ETH_HLEN - ETHER_TYPE_LEN);
|
||||
|
||||
DATA(packet)[ETH_HLEN - ETHER_TYPE_LEN] = (ethertype >> 8) & 0xFF;
|
||||
DATA(packet)[ETH_HLEN - ETHER_TYPE_LEN + 1] = ethertype & 0xFF;
|
||||
}
|
||||
|
||||
static bool read_packet(vpn_packet_t *packet) {
|
||||
int lenin = read(device_fd, DATA(packet) + ETH_HLEN, MTU - ETH_HLEN);
|
||||
if(lenin <= 0) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from fd/%d: %s!", device_fd, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16_t ethertype = get_ip_ethertype(packet);
|
||||
if(ethertype == ETH_P_MAX) {
|
||||
logger(DEBUG_TRAFFIC, LOG_ERR, "Unknown IP version while reading packet from fd/%d!", device_fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
set_etherheader(packet, ethertype);
|
||||
packet->len = lenin + ETH_HLEN;
|
||||
|
||||
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Read packet of %d bytes from fd/%d.", packet->len, device_fd);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool write_packet(vpn_packet_t *packet) {
|
||||
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Writing packet of %d bytes to fd/%d.", packet->len, device_fd);
|
||||
|
||||
if(write(device_fd, DATA(packet) + ETH_HLEN, packet->len - ETH_HLEN) < 0) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Error while writing to fd/%d: %s!", device_fd, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const devops_t fd_devops = {
|
||||
.setup = setup_device,
|
||||
.close = close_device,
|
||||
.read = read_packet,
|
||||
.write = write_packet,
|
||||
};
|
23
src/graph.c
23
src/graph.c
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
graph.c -- graph algorithms
|
||||
Copyright (C) 2001-2013 Guus Sliepen <guus@tinc-vpn.org>,
|
||||
Copyright (C) 2001-2017 Guus Sliepen <guus@tinc-vpn.org>,
|
||||
2001-2005 Ivo Timmermans
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
|
@ -268,28 +268,23 @@ static void check_reachability(void) {
|
|||
char *name;
|
||||
char *address;
|
||||
char *port;
|
||||
char *envp[8] = {NULL};
|
||||
|
||||
xasprintf(&envp[0], "NETNAME=%s", netname ? : "");
|
||||
xasprintf(&envp[1], "DEVICE=%s", device ? : "");
|
||||
xasprintf(&envp[2], "INTERFACE=%s", iface ? : "");
|
||||
xasprintf(&envp[3], "NODE=%s", n->name);
|
||||
environment_t env;
|
||||
environment_init(&env);
|
||||
environment_add(&env, "NODE=%s", n->name);
|
||||
sockaddr2str(&n->address, &address, &port);
|
||||
xasprintf(&envp[4], "REMOTEADDRESS=%s", address);
|
||||
xasprintf(&envp[5], "REMOTEPORT=%s", port);
|
||||
xasprintf(&envp[6], "NAME=%s", myself->name);
|
||||
environment_add(&env, "REMOTEADDRESS=%s", address);
|
||||
environment_add(&env, "REMOTEPORT=%s", port);
|
||||
|
||||
execute_script(n->status.reachable ? "host-up" : "host-down", envp);
|
||||
execute_script(n->status.reachable ? "host-up" : "host-down", &env);
|
||||
|
||||
xasprintf(&name, n->status.reachable ? "hosts/%s-up" : "hosts/%s-down", n->name);
|
||||
execute_script(name, envp);
|
||||
execute_script(name, &env);
|
||||
|
||||
free(name);
|
||||
free(address);
|
||||
free(port);
|
||||
|
||||
for(int i = 0; i < 7; i++)
|
||||
free(envp[i]);
|
||||
environment_exit(&env);
|
||||
|
||||
subnet_update(n, NULL, n->status.reachable);
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
invitation.c -- Create and accept invitations
|
||||
Copyright (C) 2013-2015 Guus Sliepen <guus@tinc-vpn.org>
|
||||
Copyright (C) 2013-2017 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
|
||||
|
@ -239,7 +239,7 @@ int cmd_invite(int argc, char *argv[]) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
char *myname = get_my_name(true);
|
||||
myname = get_my_name(true);
|
||||
if(!myname)
|
||||
return 1;
|
||||
|
||||
|
@ -425,15 +425,13 @@ int cmd_invite(int argc, char *argv[]) {
|
|||
xasprintf(&url, "%s/%s%s", address, hash, cookie);
|
||||
|
||||
// Call the inviation-created script
|
||||
char *envp[6] = {};
|
||||
xasprintf(&envp[0], "NAME=%s", myname);
|
||||
xasprintf(&envp[1], "NETNAME=%s", netname);
|
||||
xasprintf(&envp[2], "NODE=%s", argv[1]);
|
||||
xasprintf(&envp[3], "INVITATION_FILE=%s", filename);
|
||||
xasprintf(&envp[4], "INVITATION_URL=%s", url);
|
||||
execute_script("invitation-created", envp);
|
||||
for(int i = 0; i < 6 && envp[i]; i++)
|
||||
free(envp[i]);
|
||||
environment_t env;
|
||||
environment_init(&env);
|
||||
environment_add(&env, "NODE=%s", argv[1]);
|
||||
environment_add(&env, "INVITATION_FILE=%s", filename);
|
||||
environment_add(&env, "INVITATION_URL=%s", url);
|
||||
execute_script("invitation-created", &env);
|
||||
environment_exit(&env);
|
||||
|
||||
puts(url);
|
||||
free(url);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
logger.c -- logging code
|
||||
Copyright (C) 2004-2015 Guus Sliepen <guus@tinc-vpn.org>
|
||||
Copyright (C) 2004-2017 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2004-2005 Ivo Timmermans
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
|
@ -29,7 +29,7 @@
|
|||
#include "process.h"
|
||||
#include "sptps.h"
|
||||
|
||||
debug_t debug_level = DEBUG_NOTHING;
|
||||
int debug_level = DEBUG_NOTHING;
|
||||
static logmode_t logmode = LOGMODE_STDERR;
|
||||
static pid_t logpid;
|
||||
static FILE *logfile = NULL;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
logger.h -- header file for logger.c
|
||||
Copyright (C) 1998-2005 Ivo Timmermans
|
||||
2000-2012 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2000-2017 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
|
||||
|
@ -67,7 +67,7 @@ enum {
|
|||
|
||||
#include <stdbool.h>
|
||||
|
||||
extern debug_t debug_level;
|
||||
extern int debug_level;
|
||||
extern bool logcontrol;
|
||||
extern int umbilical;
|
||||
extern void openlogger(const char *, logmode_t);
|
||||
|
|
|
@ -214,6 +214,9 @@ static bool setup_device(void) {
|
|||
|
||||
logger(DEBUG_ALWAYS, LOG_INFO, "%s (%s) is a %s", device, iface, device_info);
|
||||
|
||||
device_read_overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
device_write_overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -226,9 +229,6 @@ static void enable_device(void) {
|
|||
|
||||
/* We don't use the write event directly, but GetOverlappedResult() does, internally. */
|
||||
|
||||
device_read_overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
device_write_overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
|
||||
io_add_event(&device_read_io, device_handle_read, NULL, device_read_overlapped.hEvent);
|
||||
device_issue_read();
|
||||
}
|
||||
|
@ -237,6 +237,19 @@ static void disable_device(void) {
|
|||
logger(DEBUG_ALWAYS, LOG_INFO, "Disabling %s", device_info);
|
||||
|
||||
io_del(&device_read_io);
|
||||
|
||||
ULONG status = 0;
|
||||
DWORD len;
|
||||
DeviceIoControl(device_handle, TAP_IOCTL_SET_MEDIA_STATUS, &status, sizeof status, &status, sizeof status, &len, NULL);
|
||||
|
||||
/* Note that we don't try to cancel ongoing I/O here - we just stop listening.
|
||||
This is because some TAP-Win32 drivers don't seem to handle cancellation very well,
|
||||
especially when combined with other events such as the computer going to sleep - cases
|
||||
were observed where the GetOverlappedResult() would just block indefinitely and never
|
||||
return in that case. */
|
||||
}
|
||||
|
||||
static void close_device(void) {
|
||||
CancelIo(device_handle);
|
||||
|
||||
/* According to MSDN, CancelIo() does not necessarily wait for the operation to complete.
|
||||
|
@ -253,11 +266,6 @@ static void disable_device(void) {
|
|||
CloseHandle(device_read_overlapped.hEvent);
|
||||
CloseHandle(device_write_overlapped.hEvent);
|
||||
|
||||
ULONG status = 0;
|
||||
DeviceIoControl(device_handle, TAP_IOCTL_SET_MEDIA_STATUS, &status, sizeof status, &status, sizeof status, &len, NULL);
|
||||
}
|
||||
|
||||
static void close_device(void) {
|
||||
CloseHandle(device_handle); device_handle = INVALID_HANDLE_VALUE;
|
||||
|
||||
free(device); device = NULL;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
names.c -- generate commonly used (file)names
|
||||
Copyright (C) 1998-2005 Ivo Timmermans
|
||||
2000-2015 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2000-2017 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
|
||||
|
@ -25,6 +25,7 @@
|
|||
#include "xalloc.h"
|
||||
|
||||
char *netname = NULL;
|
||||
char *myname = NULL;
|
||||
char *confdir = NULL; /* base configuration directory */
|
||||
char *confbase = NULL; /* base configuration directory for this instance of tinc */
|
||||
bool confbase_given;
|
||||
|
@ -137,6 +138,7 @@ void free_names(void) {
|
|||
free(logfilename);
|
||||
free(confbase);
|
||||
free(confdir);
|
||||
free(myname);
|
||||
|
||||
identname = NULL;
|
||||
netname = NULL;
|
||||
|
@ -145,4 +147,5 @@ void free_names(void) {
|
|||
logfilename = NULL;
|
||||
confbase = NULL;
|
||||
confdir = NULL;
|
||||
myname = NULL;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
names.h -- header for names.c
|
||||
Copyright (C) 1998-2005 Ivo Timmermans
|
||||
2000-2015 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2000-2017 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
|
||||
|
@ -25,6 +25,7 @@ extern char *confdir;
|
|||
extern char *confbase;
|
||||
extern bool confbase_given;
|
||||
extern char *netname;
|
||||
extern char *myname;
|
||||
extern char *identname;
|
||||
extern char *unixsocketname;
|
||||
extern char *logfilename;
|
||||
|
|
|
@ -127,8 +127,9 @@ typedef struct outgoing_t {
|
|||
int timeout;
|
||||
splay_tree_t *config_tree;
|
||||
struct config_t *cfg;
|
||||
struct addrinfo *ai;
|
||||
struct addrinfo *ai; // addresses from config files
|
||||
struct addrinfo *aip;
|
||||
struct addrinfo *kai; // addresses known via other online nodes (use free_known_addresses())
|
||||
timeout_t ev;
|
||||
} outgoing_t;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
net_setup.c -- Setup.
|
||||
Copyright (C) 1998-2005 Ivo Timmermans,
|
||||
2000-2016 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2000-2017 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2006 Scott Lamb <slamb@slamb.org>
|
||||
2010 Brandon Black <blblack@gmail.com>
|
||||
|
||||
|
@ -50,7 +50,6 @@
|
|||
#endif
|
||||
|
||||
char *myport;
|
||||
static char *myname;
|
||||
static io_t device_io;
|
||||
devops_t devops;
|
||||
bool device_standby = false;
|
||||
|
@ -755,29 +754,17 @@ void device_enable(void) {
|
|||
|
||||
/* Run tinc-up script to further initialize the tap interface */
|
||||
|
||||
char *envp[5] = {NULL};
|
||||
xasprintf(&envp[0], "NETNAME=%s", netname ? : "");
|
||||
xasprintf(&envp[1], "DEVICE=%s", device ? : "");
|
||||
xasprintf(&envp[2], "INTERFACE=%s", iface ? : "");
|
||||
xasprintf(&envp[3], "NAME=%s", myname);
|
||||
|
||||
execute_script("tinc-up", envp);
|
||||
|
||||
for(int i = 0; i < 4; i++)
|
||||
free(envp[i]);
|
||||
environment_t env;
|
||||
environment_init(&env);
|
||||
execute_script("tinc-up", &env);
|
||||
environment_exit(&env);
|
||||
}
|
||||
|
||||
void device_disable(void) {
|
||||
char *envp[5] = {NULL};
|
||||
xasprintf(&envp[0], "NETNAME=%s", netname ? : "");
|
||||
xasprintf(&envp[1], "DEVICE=%s", device ? : "");
|
||||
xasprintf(&envp[2], "INTERFACE=%s", iface ? : "");
|
||||
xasprintf(&envp[3], "NAME=%s", myname);
|
||||
|
||||
execute_script("tinc-down", envp);
|
||||
|
||||
for(int i = 0; i < 4; i++)
|
||||
free(envp[i]);
|
||||
environment_t env;
|
||||
environment_init(&env);
|
||||
execute_script("tinc-down", &env);
|
||||
environment_exit(&env);
|
||||
|
||||
if (devops.disable)
|
||||
devops.disable();
|
||||
|
@ -987,6 +974,8 @@ static bool setup_myself(void) {
|
|||
devops = raw_socket_devops;
|
||||
else if(!strcasecmp(type, "multicast"))
|
||||
devops = multicast_devops;
|
||||
else if(!strcasecmp(type, "fd"))
|
||||
devops = fd_devops;
|
||||
#ifdef ENABLE_UML
|
||||
else if(!strcasecmp(type, "uml"))
|
||||
devops = uml_devops;
|
||||
|
@ -1217,7 +1206,6 @@ void close_network_connections(void) {
|
|||
|
||||
exit_control();
|
||||
|
||||
free(myname);
|
||||
free(scriptextension);
|
||||
free(scriptinterpreter);
|
||||
|
||||
|
|
|
@ -442,13 +442,20 @@ static void handle_meta_io(void *data, int flags) {
|
|||
handle_meta_connection_data(c);
|
||||
}
|
||||
|
||||
static void free_known_addresses(struct addrinfo *ai) {
|
||||
for(struct addrinfo *aip = ai, *next; aip; aip = next) {
|
||||
next = aip->ai_next;
|
||||
free(aip);
|
||||
}
|
||||
}
|
||||
|
||||
bool do_outgoing_connection(outgoing_t *outgoing) {
|
||||
char *address;
|
||||
struct addrinfo *proxyai = NULL;
|
||||
int result;
|
||||
|
||||
begin:
|
||||
if(!outgoing->ai) {
|
||||
if(!outgoing->ai && !outgoing->kai) {
|
||||
if(!outgoing->cfg) {
|
||||
logger(DEBUG_CONNECTIONS, LOG_ERR, "Could not set up a meta connection to %s", outgoing->name);
|
||||
retry_outgoing(outgoing);
|
||||
|
@ -469,6 +476,11 @@ begin:
|
|||
if(outgoing->ai)
|
||||
freeaddrinfo(outgoing->ai);
|
||||
outgoing->ai = NULL;
|
||||
|
||||
if(outgoing->kai)
|
||||
free_known_addresses(outgoing->kai);
|
||||
outgoing->kai = NULL;
|
||||
|
||||
goto begin;
|
||||
}
|
||||
|
||||
|
@ -562,6 +574,7 @@ begin:
|
|||
// Find edges pointing to this node, and use them to build a list of unique, known addresses.
|
||||
static struct addrinfo *get_known_addresses(node_t *n) {
|
||||
struct addrinfo *ai = NULL;
|
||||
struct addrinfo *oai = NULL;
|
||||
|
||||
for splay_each(edge_t, e, n->edge_tree) {
|
||||
if(!e->reverse)
|
||||
|
@ -577,16 +590,15 @@ static struct addrinfo *get_known_addresses(node_t *n) {
|
|||
if(found)
|
||||
continue;
|
||||
|
||||
struct addrinfo *nai = xzalloc(sizeof *nai);
|
||||
if(ai)
|
||||
ai->ai_next = nai;
|
||||
ai = nai;
|
||||
oai = ai;
|
||||
ai = xzalloc(sizeof *ai);
|
||||
ai->ai_family = e->reverse->address.sa.sa_family;
|
||||
ai->ai_socktype = SOCK_STREAM;
|
||||
ai->ai_protocol = IPPROTO_TCP;
|
||||
ai->ai_addrlen = SALEN(e->reverse->address.sa);
|
||||
ai->ai_addr = xmalloc(ai->ai_addrlen);
|
||||
memcpy(ai->ai_addr, &e->reverse->address, ai->ai_addrlen);
|
||||
ai->ai_next = oai;
|
||||
}
|
||||
|
||||
return ai;
|
||||
|
@ -640,8 +652,8 @@ void setup_outgoing_connection(outgoing_t *outgoing) {
|
|||
|
||||
if(!outgoing->cfg) {
|
||||
if(n)
|
||||
outgoing->aip = outgoing->ai = get_known_addresses(n);
|
||||
if(!outgoing->ai) {
|
||||
outgoing->aip = outgoing->kai = get_known_addresses(n);
|
||||
if(!outgoing->kai) {
|
||||
logger(DEBUG_ALWAYS, LOG_DEBUG, "No address known for %s", outgoing->name);
|
||||
goto remove;
|
||||
}
|
||||
|
@ -798,6 +810,9 @@ static void free_outgoing(outgoing_t *outgoing) {
|
|||
if(outgoing->ai)
|
||||
freeaddrinfo(outgoing->ai);
|
||||
|
||||
if(outgoing->kai)
|
||||
free_known_addresses(outgoing->kai);
|
||||
|
||||
if(outgoing->config_tree)
|
||||
exit_configuration(&outgoing->config_tree);
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
protocol_auth.c -- handle the meta-protocol, authentication
|
||||
Copyright (C) 1999-2005 Ivo Timmermans,
|
||||
2000-2016 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2000-2017 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
|
||||
|
@ -181,21 +181,19 @@ static bool finalize_invitation(connection_t *c, const char *data, uint16_t len)
|
|||
logger(DEBUG_CONNECTIONS, LOG_INFO, "Key succesfully received from %s (%s)", c->name, c->hostname);
|
||||
|
||||
// Call invitation-accepted script
|
||||
char *envp[7] = {NULL};
|
||||
environment_t env;
|
||||
char *address, *port;
|
||||
|
||||
xasprintf(&envp[0], "NETNAME=%s", netname ? : "");
|
||||
xasprintf(&envp[1], "DEVICE=%s", device ? : "");
|
||||
xasprintf(&envp[2], "INTERFACE=%s", iface ? : "");
|
||||
xasprintf(&envp[3], "NODE=%s", c->name);
|
||||
environment_init(&env);
|
||||
environment_add(&env, "NODE=%s", c->name);
|
||||
|
||||
sockaddr2str(&c->address, &address, &port);
|
||||
xasprintf(&envp[4], "REMOTEADDRESS=%s", address);
|
||||
xasprintf(&envp[5], "NAME=%s", myself->name);
|
||||
environment_add(&env, "REMOTEADDRESS=%s", address);
|
||||
environment_add(&env, "NAME=%s", myself->name);
|
||||
|
||||
execute_script("invitation-accepted", envp);
|
||||
execute_script("invitation-accepted", &env);
|
||||
|
||||
for(int i = 0; envp[i] && i < 7; i++)
|
||||
free(envp[i]);
|
||||
environment_exit(&env);
|
||||
|
||||
sptps_send_record(&c->sptps, 2, data, 0);
|
||||
return true;
|
||||
|
|
11
src/route.c
11
src/route.c
|
@ -734,6 +734,9 @@ static void route_ipv6(node_t *source, vpn_packet_t *packet) {
|
|||
if(!do_decrement_ttl(source, packet))
|
||||
return;
|
||||
|
||||
if(priorityinheritance)
|
||||
packet->priority = ((DATA(packet)[14] & 0x0f) << 4) | (DATA(packet)[15] >> 4);
|
||||
|
||||
via = (subnet->owner->via == myself) ? subnet->owner->nexthop : subnet->owner->via;
|
||||
|
||||
if(via == source) {
|
||||
|
@ -1005,8 +1008,12 @@ static void route_mac(node_t *source, vpn_packet_t *packet) {
|
|||
|
||||
uint16_t type = DATA(packet)[12] << 8 | DATA(packet)[13];
|
||||
|
||||
if(priorityinheritance && type == ETH_P_IP && packet->len >= ether_size + ip_size)
|
||||
packet->priority = DATA(packet)[15];
|
||||
if(priorityinheritance) {
|
||||
if(type == ETH_P_IP && packet->len >= ether_size + ip_size)
|
||||
packet->priority = DATA(packet)[15];
|
||||
else if(type == ETH_P_IPV6 && packet->len >= ether_size + ip6_size)
|
||||
packet->priority = ((DATA(packet)[14] & 0x0f) << 4) | (DATA(packet)[15] >> 4);
|
||||
}
|
||||
|
||||
// Handle packets larger than PMTU
|
||||
|
||||
|
|
64
src/script.c
64
src/script.c
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
script.c -- call an external script
|
||||
Copyright (C) 1999-2005 Ivo Timmermans,
|
||||
2000-2015 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2000-2017 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
|
||||
|
@ -21,6 +21,7 @@
|
|||
#include "system.h"
|
||||
|
||||
#include "conf.h"
|
||||
#include "device.h"
|
||||
#include "logger.h"
|
||||
#include "names.h"
|
||||
#include "script.h"
|
||||
|
@ -63,7 +64,58 @@ static void putenv(const char *p) {}
|
|||
static void unputenv(const char *p) {}
|
||||
#endif
|
||||
|
||||
bool execute_script(const char *name, char **envp) {
|
||||
static const int min_env_size;
|
||||
|
||||
int environment_add(environment_t *env, const char *format, ...) {
|
||||
if(env->n >= env->size) {
|
||||
env->size = env->n ? env->n * 2 : min_env_size;
|
||||
env->entries = xrealloc(env->entries, env->size * sizeof *env->entries);
|
||||
}
|
||||
|
||||
if(format) {
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
vasprintf(&env->entries[env->n], format, ap);
|
||||
va_end(ap);
|
||||
} else {
|
||||
env->entries[env->n] = NULL;
|
||||
}
|
||||
|
||||
return env->n++;
|
||||
}
|
||||
|
||||
void environment_update(environment_t *env, int pos, const char *format, ...) {
|
||||
free(env->entries[pos]);
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
vasprintf(&env->entries[pos], format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void environment_init(environment_t *env) {
|
||||
env->n = 0;
|
||||
env->size = min_env_size;
|
||||
env->entries = 0; //xzalloc(env->size * sizeof *env->entries);
|
||||
|
||||
if(netname)
|
||||
environment_add(env, "NETNAME=%s", netname);
|
||||
if(myname)
|
||||
environment_add(env, "NAME=%s", myname);
|
||||
if(device)
|
||||
environment_add(env, "DEVICE=%s", device);
|
||||
if(iface)
|
||||
environment_add(env, "INTERFACE=%s", iface);
|
||||
if(debug_level >= 0)
|
||||
environment_add(env, "DEBUG=%d", debug_level);
|
||||
}
|
||||
|
||||
void environment_exit(environment_t *env) {
|
||||
for(int i = 0; i < env->n; i++)
|
||||
free(env->entries[i]);
|
||||
free(env->entries);
|
||||
}
|
||||
|
||||
bool execute_script(const char *name, environment_t *env) {
|
||||
char scriptname[PATH_MAX];
|
||||
char *command;
|
||||
|
||||
|
@ -107,8 +159,8 @@ bool execute_script(const char *name, char **envp) {
|
|||
|
||||
/* Set environment */
|
||||
|
||||
for(int i = 0; envp[i]; i++)
|
||||
putenv(envp[i]);
|
||||
for(int i = 0; i < env->n; i++)
|
||||
putenv(env->entries[i]);
|
||||
|
||||
if(scriptinterpreter)
|
||||
xasprintf(&command, "%s \"%s\"", scriptinterpreter, scriptname);
|
||||
|
@ -121,8 +173,8 @@ bool execute_script(const char *name, char **envp) {
|
|||
|
||||
/* Unset environment */
|
||||
|
||||
for(int i = 0; envp[i]; i++)
|
||||
unputenv(envp[i]);
|
||||
for(int i = 0; i < env->n; i++)
|
||||
unputenv(env->entries[i]);
|
||||
|
||||
if(status != -1) {
|
||||
#ifdef WEXITSTATUS
|
||||
|
|
16
src/script.h
16
src/script.h
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
script.h -- header file for script.c
|
||||
Copyright (C) 1999-2005 Ivo Timmermans,
|
||||
2000-2013 Guus Sliepen <guus@tinc-vpn.org>
|
||||
2000-2017 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
|
||||
|
@ -21,6 +21,18 @@
|
|||
#ifndef __TINC_SCRIPT_H__
|
||||
#define __TINC_SCRIPT_H__
|
||||
|
||||
extern bool execute_script(const char *, char **);
|
||||
typedef struct environment {
|
||||
int n;
|
||||
int size;
|
||||
char **entries;
|
||||
} environment_t;
|
||||
|
||||
extern int environment_add(environment_t *env, const char *format, ...);
|
||||
extern int environment_placeholder(environment_t *env);
|
||||
extern void environment_update(environment_t *env, int pos, const char *format, ...);
|
||||
extern void environment_init(environment_t *env);
|
||||
extern void environment_exit(environment_t *env);
|
||||
|
||||
extern bool execute_script(const char *name, environment_t *env);
|
||||
|
||||
#endif /* __TINC_SCRIPT_H__ */
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include <sys/stropts.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <stropts.h>
|
||||
|
||||
#include "../conf.h"
|
||||
#include "../device.h"
|
||||
|
@ -41,6 +42,7 @@
|
|||
|
||||
#define DEFAULT_TUN_DEVICE "/dev/tun"
|
||||
#define DEFAULT_TAP_DEVICE "/dev/tap"
|
||||
#define IP_DEVICE "/dev/udp"
|
||||
|
||||
static enum {
|
||||
DEVICE_TYPE_TUN,
|
||||
|
@ -84,8 +86,8 @@ static bool setup_device(void) {
|
|||
|
||||
/* The following is black magic copied from OpenVPN. */
|
||||
|
||||
if((ip_fd = open("/dev/ip", O_RDWR, 0)) < 0) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Could not open %s: %s\n", "/dev/ip", strerror(errno));
|
||||
if((ip_fd = open(IP_DEVICE, O_RDWR, 0)) < 0) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Could not open %s: %s\n", IP_DEVICE, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -203,7 +205,7 @@ static bool setup_device(void) {
|
|||
|
||||
/* Push arp module to ip_fd */
|
||||
if(ioctl(ip_fd, I_PUSH, "arp") < 0) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Could not push ARP module onto %s!", "/dev/ip");
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Could not push ARP module onto %s!", IP_DEVICE);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -295,11 +297,16 @@ static void close_device(void) {
|
|||
}
|
||||
|
||||
static bool read_packet(vpn_packet_t *packet) {
|
||||
int inlen;
|
||||
int result;
|
||||
struct strbuf sbuf;
|
||||
int f = 0;
|
||||
|
||||
switch(device_type) {
|
||||
case DEVICE_TYPE_TUN:
|
||||
if((inlen = read(device_fd, DATA(packet) + 14, MTU - 14)) <= 0) {
|
||||
sbuf.maxlen = MTU - 14;
|
||||
sbuf.buf = (char *)DATA(packet) + 14;
|
||||
|
||||
if((result = getmsg(device_fd, NULL, &sbuf, &f)) < 0) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s", device_info, device, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
@ -319,16 +326,19 @@ static bool read_packet(vpn_packet_t *packet) {
|
|||
}
|
||||
|
||||
memset(DATA(packet), 0, 12);
|
||||
packet->len = inlen + 14;
|
||||
packet->len = sbuf.len + 14;
|
||||
break;
|
||||
|
||||
case DEVICE_TYPE_TAP:
|
||||
if((inlen = read(device_fd, DATA(packet), MTU)) <= 0) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s", device_info, device, strerror(errno));
|
||||
sbuf.maxlen = MTU;
|
||||
sbuf.buf = (char *)DATA(packet);
|
||||
|
||||
if((result = getmsg(device_fd, NULL, &sbuf, &f)) < 0) {
|
||||
logger(LOG_ERR, "Error while reading from %s %s: %s", device_info, device, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
packet->len = inlen + 14;
|
||||
packet->len = sbuf.len;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -343,17 +353,25 @@ static bool read_packet(vpn_packet_t *packet) {
|
|||
static bool write_packet(vpn_packet_t *packet) {
|
||||
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Writing packet of %d bytes to %s", packet->len, device_info);
|
||||
|
||||
struct strbuf sbuf;
|
||||
|
||||
switch(device_type) {
|
||||
case DEVICE_TYPE_TUN:
|
||||
if(write(device_fd, DATA(packet) + 14, packet->len - 14) < 0) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Can't write to %s %s: %s", device_info, device, strerror(errno));
|
||||
sbuf.len = packet->len - 14;
|
||||
sbuf.buf = (char *)DATA(packet) + 14;
|
||||
|
||||
if(putmsg(device_fd, NULL, &sbuf, 0) < 0) {
|
||||
logger(LOG_ERR, "Can't write to %s %s: %s", device_info, device, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case DEVICE_TYPE_TAP:
|
||||
if(write(device_fd, DATA(packet), packet->len) < 0) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Can't write to %s %s: %s", device_info, device, strerror(errno));
|
||||
sbuf.len = packet->len;
|
||||
sbuf.buf = (char *)DATA(packet);
|
||||
|
||||
if(putmsg(device_fd, NULL, &sbuf, 0) < 0) {
|
||||
logger(LOG_ERR, "Can't write to %s %s: %s", device_info, device, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
|
35
src/subnet.c
35
src/subnet.c
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
subnet.c -- handle subnet lookups and lists
|
||||
Copyright (C) 2000-2013 Guus Sliepen <guus@tinc-vpn.org>,
|
||||
Copyright (C) 2000-2017 Guus Sliepen <guus@tinc-vpn.org>,
|
||||
2000-2005 Ivo Timmermans
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
|
@ -206,22 +206,20 @@ void subnet_update(node_t *owner, subnet_t *subnet, bool up) {
|
|||
|
||||
// Prepare environment variables to be passed to the script
|
||||
|
||||
char *envp[10] = {NULL};
|
||||
int n = 0;
|
||||
xasprintf(&envp[n++], "NETNAME=%s", netname ? : "");
|
||||
xasprintf(&envp[n++], "DEVICE=%s", device ? : "");
|
||||
xasprintf(&envp[n++], "INTERFACE=%s", iface ? : "");
|
||||
xasprintf(&envp[n++], "NODE=%s", owner->name);
|
||||
environment_t env;
|
||||
environment_init(&env);
|
||||
environment_add(&env, "NODE=%s", owner->name);
|
||||
|
||||
if(owner != myself) {
|
||||
sockaddr2str(&owner->address, &address, &port);
|
||||
xasprintf(&envp[n++], "REMOTEADDRESS=%s", address);
|
||||
xasprintf(&envp[n++], "REMOTEPORT=%s", port);
|
||||
environment_add(&env, "REMOTEADDRESS=%s", address);
|
||||
environment_add(&env, "REMOTEPORT=%s", port);
|
||||
free(port);
|
||||
free(address);
|
||||
}
|
||||
|
||||
xasprintf(&envp[n++], "NAME=%s", myself->name);
|
||||
int env_subnet = environment_add(&env, NULL);
|
||||
int env_weight = environment_add(&env, NULL);
|
||||
|
||||
name = up ? "subnet-up" : "subnet-down";
|
||||
|
||||
|
@ -238,12 +236,10 @@ void subnet_update(node_t *owner, subnet_t *subnet, bool up) {
|
|||
weight = empty;
|
||||
|
||||
// Prepare the SUBNET and WEIGHT variables
|
||||
free(envp[n]);
|
||||
free(envp[n + 1]);
|
||||
xasprintf(&envp[n], "SUBNET=%s", netstr);
|
||||
xasprintf(&envp[n + 1], "WEIGHT=%s", weight);
|
||||
environment_update(&env, env_subnet, "SUBNET=%s", netstr);
|
||||
environment_update(&env, env_weight, "WEIGHT=%s", weight);
|
||||
|
||||
execute_script(name, envp);
|
||||
execute_script(name, &env);
|
||||
}
|
||||
} else {
|
||||
if(net2str(netstr, sizeof netstr, subnet)) {
|
||||
|
@ -255,15 +251,14 @@ void subnet_update(node_t *owner, subnet_t *subnet, bool up) {
|
|||
weight = empty;
|
||||
|
||||
// Prepare the SUBNET and WEIGHT variables
|
||||
xasprintf(&envp[n], "SUBNET=%s", netstr);
|
||||
xasprintf(&envp[n + 1], "WEIGHT=%s", weight);
|
||||
environment_update(&env, env_subnet, "SUBNET=%s", netstr);
|
||||
environment_update(&env, env_weight, "WEIGHT=%s", weight);
|
||||
|
||||
execute_script(name, envp);
|
||||
execute_script(name, &env);
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; envp[i] && i < 9; i++)
|
||||
free(envp[i]);
|
||||
environment_exit(&env);
|
||||
}
|
||||
|
||||
bool dump_subnets(connection_t *c) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
tincctl.c -- Controlling a running tincd
|
||||
Copyright (C) 2007-2016 Guus Sliepen <guus@tinc-vpn.org>
|
||||
Copyright (C) 2007-2017 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
|
||||
|
@ -73,6 +73,9 @@ bool confbasegiven = false;
|
|||
char *scriptinterpreter = NULL;
|
||||
char *scriptextension = "";
|
||||
static char *prompt;
|
||||
char *device = NULL;
|
||||
char *iface = NULL;
|
||||
int debug_level = -1;
|
||||
|
||||
static struct option const long_options[] = {
|
||||
{"batch", no_argument, NULL, 'b'},
|
||||
|
@ -88,7 +91,7 @@ static struct option const long_options[] = {
|
|||
static void version(void) {
|
||||
printf("%s version %s (built %s %s, protocol %d.%d)\n", PACKAGE,
|
||||
BUILD_VERSION, BUILD_DATE, BUILD_TIME, PROT_MAJOR, PROT_MINOR);
|
||||
printf("Copyright (C) 1998-2016 Ivo Timmermans, Guus Sliepen and others.\n"
|
||||
printf("Copyright (C) 1998-2017 Ivo Timmermans, Guus Sliepen and others.\n"
|
||||
"See the AUTHORS file for a complete list.\n\n"
|
||||
"tinc comes with ABSOLUTELY NO WARRANTY. This is free software,\n"
|
||||
"and you are welcome to redistribute it under certain conditions;\n"
|
||||
|
@ -720,6 +723,8 @@ bool connect_tincd(bool verbose) {
|
|||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
#ifndef HAVE_MINGW
|
||||
if ((pid == 0) || (kill(pid, 0) && (errno == ESRCH))) {
|
||||
fprintf(stderr, "Could not find tincd running at pid %d\n", pid);
|
||||
/* clean up the stale socket and pid file */
|
||||
|
@ -728,7 +733,6 @@ bool connect_tincd(bool verbose) {
|
|||
return false;
|
||||
}
|
||||
|
||||
#ifndef HAVE_MINGW
|
||||
struct sockaddr_un sa;
|
||||
sa.sun_family = AF_UNIX;
|
||||
strncpy(sa.sun_path, unixsocketname, sizeof sa.sun_path);
|
||||
|
|
|
@ -16,9 +16,11 @@ TESTS = \
|
|||
executables.test \
|
||||
import-export.test \
|
||||
invite-join.test \
|
||||
invite-offline.test \
|
||||
invite-tinc-up.test \
|
||||
ns-ping.test \
|
||||
ping.test \
|
||||
scripts.test \
|
||||
sptps-basic.test \
|
||||
variables.test
|
||||
|
||||
|
|
|
@ -17,8 +17,6 @@ EOF
|
|||
|
||||
# Generate an invitation and let another node join the VPN
|
||||
|
||||
sleep 1
|
||||
|
||||
$tinc $c1 invite bar | $tinc $c2 join
|
||||
|
||||
# Test equivalence of host config files
|
||||
|
|
50
test/invite-offline.test
Executable file
50
test/invite-offline.test
Executable file
|
@ -0,0 +1,50 @@
|
|||
#!/bin/sh
|
||||
|
||||
. ./testlib.sh
|
||||
|
||||
# Initialize one node
|
||||
|
||||
$tinc $c1 <<EOF
|
||||
init foo
|
||||
set DeviceType dummy
|
||||
set Mode switch
|
||||
set Broadcast no
|
||||
del Port
|
||||
set Address localhost
|
||||
set Port 32758
|
||||
EOF
|
||||
|
||||
# Generate an invitation offline and let another node join the VPN
|
||||
|
||||
invitation=`$tinc $c1 invite bar`
|
||||
|
||||
$tinc $c1 start $r1
|
||||
|
||||
$tinc $c2 join $invitation
|
||||
|
||||
# Test equivalence of host config files
|
||||
|
||||
cmp $d1/hosts/foo $d2/hosts/foo
|
||||
test "`grep ^Ed25519PublicKey $d1/hosts/bar`" = "`grep ^Ed25519PublicKey $d2/hosts/bar`"
|
||||
|
||||
# Test Mode, Broadcast and ConnectTo statements
|
||||
|
||||
test `$tinc $c2 get Mode` = switch
|
||||
test `$tinc $c2 get Broadcast` = no
|
||||
test `$tinc $c2 get ConnectTo` = foo
|
||||
|
||||
# Check whether the new node can join the VPN
|
||||
|
||||
$tinc $c2 << EOF
|
||||
set DeviceType dummy
|
||||
set Port 0
|
||||
start $r2
|
||||
EOF
|
||||
|
||||
sleep 1
|
||||
|
||||
test `$tinc $c1 dump reachable nodes | wc -l` = 2
|
||||
test `$tinc $c2 dump reachable nodes | wc -l` = 2
|
||||
|
||||
$tinc $c2 stop
|
||||
$tinc $c1 stop
|
|
@ -8,7 +8,7 @@ $tinc $c1 <<EOF
|
|||
init foo
|
||||
set DeviceType dummy
|
||||
set Address localhost
|
||||
set Port 32751
|
||||
set Port 32756
|
||||
start $r1
|
||||
EOF
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ $tinc $c1 <<EOF
|
|||
init foo
|
||||
set Mode switch
|
||||
set Interface ping.test1
|
||||
set Port 32573
|
||||
set Port 32577
|
||||
set Address localhost
|
||||
EOF
|
||||
|
||||
|
|
110
test/scripts.test
Executable file
110
test/scripts.test
Executable file
|
@ -0,0 +1,110 @@
|
|||
#!/bin/sh
|
||||
|
||||
. ./testlib.sh
|
||||
|
||||
# Initialize server node
|
||||
|
||||
$tinc $c1 <<EOF
|
||||
init foo
|
||||
set DeviceType dummy
|
||||
set Port 32759
|
||||
set Address 127.0.0.1
|
||||
add Subnet 10.0.0.1
|
||||
add Subnet fec0::/64
|
||||
EOF
|
||||
|
||||
# Set up scripts
|
||||
|
||||
OUT=$d1/scripts.out
|
||||
rm -f $OUT
|
||||
|
||||
for script in tinc-up tinc-down host-up host-down subnet-up subnet-down hosts/foo-up hosts/foo-down hosts/bar-up hosts/bar-down invitation-created invitation-accepted; do
|
||||
cat >$d1/$script << EOF
|
||||
#!/bin/sh
|
||||
echo $script \$NETNAME,\$NAME,\$DEVICE,\$IFACE,\$NODE,\$REMOTEADDRESS,\$REMOTEPORT,\$SUBNET,\$WEIGHT,\$INVITATION_FILE,\$INVITATION_URL,\$DEBUG >>$OUT
|
||||
EOF
|
||||
chmod u+x $d1/$script
|
||||
done
|
||||
|
||||
# Start server node
|
||||
|
||||
$tinc -n netname $c1 start $r1
|
||||
|
||||
echo foo-started >>$OUT
|
||||
|
||||
# Invite client node
|
||||
|
||||
url=`$tinc -n netname2 $c1 invite bar`
|
||||
file=`cd $d1/invitations; ls | grep -v ed25519_key.priv`
|
||||
echo bar-invited >>$OUT
|
||||
$tinc -n netname3 $c2 join $url
|
||||
echo bar-joined >>$OUT
|
||||
|
||||
# Start and stop client node
|
||||
|
||||
$tinc $c2 << EOF
|
||||
set DeviceType dummy
|
||||
set Port 32760
|
||||
add Subnet 10.0.0.2
|
||||
add Subnet fec0::/64#5
|
||||
start $r2
|
||||
EOF
|
||||
|
||||
sleep 1
|
||||
|
||||
echo bar-started >>$OUT
|
||||
|
||||
$tinc $c1 debug 4
|
||||
$tinc $c2 stop
|
||||
|
||||
sleep 1
|
||||
|
||||
echo bar-stopped >>$OUT
|
||||
|
||||
$tinc $c1 debug 5
|
||||
$tinc $c2 start $r2
|
||||
|
||||
sleep 1
|
||||
|
||||
echo bar-started >>$OUT
|
||||
|
||||
# Stop server node
|
||||
|
||||
$tinc $c1 stop
|
||||
|
||||
# Check if the script output is what is expected
|
||||
|
||||
cat >$OUT.expected << EOF
|
||||
tinc-up netname,foo,dummy,,,,,,,,,5
|
||||
subnet-up netname,foo,dummy,,foo,,,10.0.0.1,,,,5
|
||||
subnet-up netname,foo,dummy,,foo,,,fec0::/64,,,,5
|
||||
foo-started
|
||||
invitation-created netname2,foo,,,bar,,,,,$d1/invitations/$file,$url,
|
||||
bar-invited
|
||||
invitation-accepted netname,foo,dummy,,bar,127.0.0.1,,,,,,5
|
||||
bar-joined
|
||||
host-up netname,foo,dummy,,bar,127.0.0.1,32760,,,,,5
|
||||
hosts/bar-up netname,foo,dummy,,bar,127.0.0.1,32760,,,,,5
|
||||
subnet-up netname,foo,dummy,,bar,127.0.0.1,32760,10.0.0.2,,,,5
|
||||
subnet-up netname,foo,dummy,,bar,127.0.0.1,32760,fec0::/64,5,,,5
|
||||
bar-started
|
||||
host-down netname,foo,dummy,,bar,127.0.0.1,32760,,,,,4
|
||||
hosts/bar-down netname,foo,dummy,,bar,127.0.0.1,32760,,,,,4
|
||||
subnet-down netname,foo,dummy,,bar,127.0.0.1,32760,10.0.0.2,,,,4
|
||||
subnet-down netname,foo,dummy,,bar,127.0.0.1,32760,fec0::/64,5,,,4
|
||||
bar-stopped
|
||||
host-up netname,foo,dummy,,bar,127.0.0.1,32760,,,,,5
|
||||
hosts/bar-up netname,foo,dummy,,bar,127.0.0.1,32760,,,,,5
|
||||
subnet-up netname,foo,dummy,,bar,127.0.0.1,32760,10.0.0.2,,,,5
|
||||
subnet-up netname,foo,dummy,,bar,127.0.0.1,32760,fec0::/64,5,,,5
|
||||
bar-started
|
||||
host-down netname,foo,dummy,,bar,127.0.0.1,32760,,,,,5
|
||||
hosts/bar-down netname,foo,dummy,,bar,127.0.0.1,32760,,,,,5
|
||||
subnet-down netname,foo,dummy,,bar,127.0.0.1,32760,10.0.0.2,,,,5
|
||||
subnet-down netname,foo,dummy,,bar,127.0.0.1,32760,fec0::/64,5,,,5
|
||||
subnet-down netname,foo,dummy,,foo,,,10.0.0.1,,,,5
|
||||
subnet-down netname,foo,dummy,,foo,,,fec0::/64,,,,5
|
||||
tinc-down netname,foo,dummy,,,,,,,,,5
|
||||
EOF
|
||||
|
||||
cmp $OUT $OUT.expected
|
Loading…
Reference in a new issue