Merge branch '1.1' of github.com:gsliepen/tinc into thkr-1.1-ponyhof

This commit is contained in:
thorkill 2015-05-12 17:28:29 +02:00
commit 35af740537
21 changed files with 301 additions and 136 deletions

View file

@ -2,14 +2,22 @@
AUTOMAKE_OPTIONS = gnu
SUBDIRS = m4 src doc gui test
SUBDIRS = src doc gui test
ACLOCAL_AMFLAGS = -I m4
EXTRA_DIST = COPYING.README README.android
# If git describe works, force autoconf to run in order to make sure we have the
# current version number from git in the resulting configure script.
configure-version:
-cd $(srcdir) && git describe && autoconf --force
# Triggering the README target means we are building a distribution (make dist).
README: configure-version
ChangeLog:
git log > ChangeLog
(cd $(srcdir) && git log) > ChangeLog
deb:
dpkg-buildpackage -rfakeroot
@ -23,5 +31,5 @@ release:
rm -f ChangeLog
$(MAKE) ChangeLog
echo "Please edit the NEWS file now..."
/usr/bin/editor NEWS
/usr/bin/editor $(srcdir)/NEWS
$(MAKE) dist

View file

@ -1,10 +1,10 @@
dnl Process this file with autoconf to produce a configure script.
AC_PREREQ(2.61)
AC_INIT([tinc], [1.1pre11])
AC_INIT([tinc], m4_esyscmd_s((git describe || echo UNKNOWN) | sed 's/release-//'))
AC_CONFIG_SRCDIR([src/tincd.c])
AC_GNU_SOURCE
AM_INIT_AUTOMAKE([check-news std-options subdir-objects -Wall])
AM_INIT_AUTOMAKE([info-in-builddir std-options subdir-objects -Wall])
AC_CONFIG_HEADERS([config.h])
# Enable GNU extensions.
@ -161,13 +161,13 @@ 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 netpacket/packet.h],
[], [], [#include "src/have.h"]
[], [], [#include "$srcdir/src/have.h"]
)
AC_CHECK_HEADERS([netinet/if_ether.h netinet/ip.h netinet/ip6.h resolv.h],
[], [], [#include "src/have.h"]
[], [], [#include "$srcdir/src/have.h"]
)
AC_CHECK_HEADERS([netinet/tcp.h netinet/ip_icmp.h netinet/icmp6.h],
[], [], [#include "src/have.h"]
[], [], [#include "$srcdir/src/have.h"]
)
dnl Checks for typedefs, structures, and compiler characteristics.
@ -182,13 +182,13 @@ tinc_ATTRIBUTE(__malloc__)
tinc_ATTRIBUTE(__warn_unused_result__)
AC_CHECK_TYPES([socklen_t, struct ether_header, struct arphdr, struct ether_arp, struct in_addr, struct addrinfo, struct ip, struct icmp, struct in6_addr, struct sockaddr_in6, struct ip6_hdr, struct icmp6_hdr, struct nd_neighbor_solicit, struct nd_opt_hdr], , ,
[#include "src/have.h"]
[#include "$srcdir/src/have.h"]
)
dnl Checks for library functions.
AC_TYPE_SIGNAL
AC_CHECK_FUNCS([asprintf daemon fchmod flock ftime fork get_current_dir_name gettimeofday mlockall putenv random select strdup strerror strsignal strtol system time usleep unsetenv vsyslog writev],
[], [], [#include "src/have.h"]
[], [], [#include "$srcdir/src/have.h"]
)
dnl Support for SunOS
@ -201,7 +201,7 @@ AC_CHECK_FUNC(gethostbyname, [], [
])
AC_CHECK_DECLS([freeaddrinfo, gai_strerror, getaddrinfo, getnameinfo],
[], [], [#include "src/have.h"]
[], [], [#include "$srcdir/src/have.h"]
)
AC_CHECK_DECLS([res_init], [AC_CHECK_LIB(resolv, res_init)], [], [
@ -249,6 +249,6 @@ AC_ARG_ENABLE(jumbograms,
]
)
AC_CONFIG_FILES([Makefile src/Makefile doc/Makefile m4/Makefile gui/Makefile test/Makefile])
AC_CONFIG_FILES([Makefile src/Makefile doc/Makefile gui/Makefile test/Makefile])
AC_OUTPUT

View file

@ -17,7 +17,7 @@ transform = s/ginstall/install/; @program_transform_name@
# see GNUmakefile and Makefile.maint.
sample-config.tar.gz: sample-config
GZIP=$(GZIP_ENV) $(AMTAR) chozf sample-config.tar.gz --exclude .svn sample-config
GZIP=$(GZIP_ENV) $(AMTAR) chozf $@ --exclude .svn $<
tincd.8.html: tincd.8
w3mman2html $? > $@

View file

@ -1,4 +0,0 @@
## Process this file with automake to produce Makefile.in -*-Makefile-*-
EXTRA_DIST = README *.m4

View file

@ -2,9 +2,12 @@
sbin_PROGRAMS = tincd tinc sptps_test sptps_keypair
## Make sure version.c is always rebuilt
.PHONY: version.c
version.c:
## Make sure version.c is always rebuilt with the latest git information
.PHONY: $(srcdir)/version.c version_git.h
version_git.h:
echo >$@
-(cd $(srcdir) && git describe) && echo '#define GIT_DESCRIPTION "'`(cd $(srcdir) && git describe) | sed 's/release-//'`'"' >$@
$(srcdir)/version.c: version_git.h
if LINUX
sbin_PROGRAMS += sptps_speed
@ -257,4 +260,4 @@ if TUNEMU
LIBS += -lpcap
endif
AM_CFLAGS = -DCONFDIR=\"$(sysconfdir)\" -DLOCALSTATEDIR=\"$(localstatedir)\" -DSBINDIR=\"$(sbindir)\"
AM_CFLAGS = -DCONFDIR=\"$(sysconfdir)\" -DLOCALSTATEDIR=\"$(localstatedir)\" -DSBINDIR=\"$(sbindir)\" -I.

View file

@ -97,6 +97,7 @@ typedef struct connection_t {
struct buffer_t outbuf;
io_t io; /* input/output event on this metadata connection */
int tcplen; /* length of incoming TCPpacket */
int sptpslen; /* length of incoming SPTPS packet */
int allow_request; /* defined if there's only one request possible */
struct timeval last_ping_time; /* last time we saw some activity from the other end or pinged them */

View file

@ -78,6 +78,20 @@ bool send_meta(connection_t *c, const char *buffer, int length) {
return true;
}
void send_meta_raw(connection_t *c, const char *buffer, int length) {
if(!c) {
logger(DEBUG_ALWAYS, LOG_ERR, "send_meta() called with NULL pointer!");
abort();
}
logger(DEBUG_META, LOG_DEBUG, "Sending %d bytes of raw metadata to %s (%s)", length,
c->name, c->hostname);
buffer_add(&c->outbuf, buffer, length);
io_set(&c->io, IO_READ | IO_WRITE);
}
void broadcast_meta(connection_t *from, const char *buffer, int length) {
for list_each(connection_t, c, connection_list)
if(c != from && c->edge)
@ -159,8 +173,33 @@ bool receive_meta(connection_t *c) {
}
do {
if(c->protocol_minor >= 2)
return sptps_receive_data(&c->sptps, bufp, inlen);
/* Are we receiving a SPTPS packet? */
if(c->sptpslen) {
int len = MIN(inlen, c->sptpslen - c->inbuf.len);
buffer_add(&c->inbuf, bufp, len);
char *sptpspacket = buffer_read(&c->inbuf, c->sptpslen);
if(!sptpspacket)
return true;
if(!receive_tcppacket_sptps(c, sptpspacket, c->sptpslen))
return false;
c->sptpslen = 0;
bufp += len;
inlen -= len;
continue;
}
if(c->protocol_minor >= 2) {
int len = sptps_receive_data(&c->sptps, bufp, inlen);
if(!len)
return false;
bufp += len;
inlen -= len;
continue;
}
if(!c->status.decryptin) {
endp = memchr(bufp, '\n', inlen);

View file

@ -24,6 +24,7 @@
#include "connection.h"
extern bool send_meta(struct connection_t *, const char *, int);
extern void send_meta_raw(struct connection_t *, const char *, int);
extern bool send_meta_sptps(void *, uint8_t, const void *, size_t);
extern bool receive_meta_sptps(void *, uint8_t, const void *, uint16_t);
extern void broadcast_meta(struct connection_t *, const char *, int);

View file

@ -192,10 +192,11 @@ extern void handle_new_meta_connection(void *, int);
extern void handle_new_unix_connection(void *, int);
extern int setup_listen_socket(const sockaddr_t *);
extern int setup_vpn_in_socket(const sockaddr_t *);
extern bool send_sptps_data(void *handle, uint8_t type, const void *data, size_t len);
extern bool send_sptps_data(node_t *to, node_t *from, int type, const void *data, size_t len);
extern bool receive_sptps_record(void *handle, uint8_t type, const void *data, uint16_t len);
extern void send_packet(struct node_t *, vpn_packet_t *);
extern void receive_tcppacket(struct connection_t *, const char *, int);
extern bool receive_tcppacket_sptps(struct connection_t *, const char *, int);
extern void broadcast_packet(const struct node_t *, vpn_packet_t *);
extern char *get_name(void);
extern void device_enable(void);

View file

@ -429,6 +429,51 @@ void receive_tcppacket(connection_t *c, const char *buffer, int len) {
receive_packet(c->node, &outpkt);
}
bool receive_tcppacket_sptps(connection_t *c, const char *data, int len) {
if (len < sizeof(node_id_t) + sizeof(node_id_t)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Got too short TCP SPTPS packet from %s (%s)", c->name, c->hostname);
return false;
}
node_t *to = lookup_node_id((node_id_t *)data);
data += sizeof(node_id_t); len -= sizeof(node_id_t);
if(!to) {
logger(DEBUG_PROTOCOL, LOG_ERR, "Got TCP SPTPS packet from %s (%s) with unknown destination ID", c->name, c->hostname);
return true;
}
node_t *from = lookup_node_id((node_id_t *)data);
data += sizeof(node_id_t); len -= sizeof(node_id_t);
if(!from) {
logger(DEBUG_PROTOCOL, LOG_ERR, "Got TCP SPTPS packet from %s (%s) with unknown source ID", c->name, c->hostname);
return true;
}
/* Help the sender reach us over UDP.
Note that we only do this if we're the destination or the static relay;
otherwise every hop would initiate its own UDP info message, resulting in elevated chatter. */
if(to->via == myself)
send_udp_info(myself, from);
/* If we're not the final recipient, relay the packet. */
if(to != myself) {
send_sptps_data(to, from, 0, data, len);
try_tx(to, true);
return true;
}
/* The packet is for us */
if(!from->status.validkey) {
logger(DEBUG_PROTOCOL, LOG_ERR, "Got SPTPS packet from %s (%s) but we don't have a valid key yet", from->name, from->hostname);
return true;
}
sptps_receive_data(&from->sptps, data, len);
send_mtu_info(myself, from, MTU);
return true;
}
static void send_sptps_packet(node_t *n, vpn_packet_t *origpkt) {
if(!n->status.validkey && !n->connection)
return;
@ -682,7 +727,7 @@ end:
#endif
}
static bool send_sptps_data_priv(node_t *to, node_t *from, int type, const void *data, size_t len) {
bool send_sptps_data(node_t *to, node_t *from, int type, const void *data, size_t len) {
node_t *relay = (to->via != myself && (type == PKT_PROBE || (len - SPTPS_DATAGRAM_OVERHEAD) <= to->via->minmtu)) ? to->via : to->nexthop;
bool direct = from == myself && to == relay;
bool relay_supported = (relay->options >> 24) >= 4;
@ -691,6 +736,15 @@ static bool send_sptps_data_priv(node_t *to, node_t *from, int type, const void
/* Send it via TCP if it is a handshake packet, TCPOnly is in use, this is a relay packet that the other node cannot understand, or this packet is larger than the MTU. */
if(type == SPTPS_HANDSHAKE || tcponly || (!direct && !relay_supported) || (type != PKT_PROBE && (len - SPTPS_DATAGRAM_OVERHEAD) > relay->minmtu)) {
if((from != myself || to->status.validkey) && (to->nexthop->connection->options >> 24) >= 7) {
char buf[len + sizeof to->id + sizeof from->id]; char* buf_ptr = buf;
memcpy(buf_ptr, &to->id, sizeof to->id); buf_ptr += sizeof to->id;
memcpy(buf_ptr, &from->id, sizeof from->id); buf_ptr += sizeof from->id;
memcpy(buf_ptr, data, len); buf_ptr += len;
logger(DEBUG_TRAFFIC, LOG_INFO, "Sending packet from %s (%s) to %s (%s) via %s (%s) (TCP)", from->name, from->hostname, to->name, to->hostname, to->nexthop->name, to->nexthop->hostname);
return send_sptps_tcppacket(to->nexthop->connection, buf, sizeof buf);
}
char buf[len * 4 / 3 + 5];
b64encode(data, buf, len);
/* If no valid key is known yet, send the packets using ANS_KEY requests,
@ -699,7 +753,7 @@ static bool send_sptps_data_priv(node_t *to, node_t *from, int type, const void
to->incompression = myself->incompression;
return send_request(to->nexthop->connection, "%d %s %s %s -1 -1 -1 %d", ANS_KEY, from->name, to->name, buf, to->incompression);
} else {
return send_request(to->nexthop->connection, "%d %s %s %d %s", REQ_KEY, from->name, to->name, REQ_SPTPS, buf);
return send_request(to->nexthop->connection, "%d %s %s %d %s", REQ_KEY, from->name, to->name, SPTPS_PACKET, buf);
}
}
@ -726,7 +780,7 @@ static bool send_sptps_data_priv(node_t *to, node_t *from, int type, const void
choose_local_address(relay, &sa, &sock);
if(!sa)
choose_udp_address(relay, &sa, &sock);
logger(DEBUG_TRAFFIC, LOG_INFO, "Sending packet from %s (%s) to %s (%s) via %s (%s)", from->name, from->hostname, to->name, to->hostname, relay->name, relay->hostname);
logger(DEBUG_TRAFFIC, LOG_INFO, "Sending packet from %s (%s) to %s (%s) via %s (%s) (UDP)", from->name, from->hostname, to->name, to->hostname, relay->name, relay->hostname);
if(sendto(listen_socket[sock].udp.fd, buf, buf_ptr - buf, 0, &sa->sa, SALEN(sa->sa)) < 0 && !sockwouldblock(sockerrno)) {
if(sockmsgsize(sockerrno)) {
// Compensate for SPTPS overhead
@ -745,10 +799,6 @@ static bool send_sptps_data_priv(node_t *to, node_t *from, int type, const void
return true;
}
bool send_sptps_data(void *handle, uint8_t type, const void *data, size_t len) {
return send_sptps_data_priv(handle, myself, type, data, len);
}
bool receive_sptps_record(void *handle, uint8_t type, const void *data, uint16_t len) {
node_t *from = handle;
@ -1405,8 +1455,8 @@ skip_harder:
/* If we're not the final recipient, relay the packet. */
if(to != myself) {
send_sptps_data_priv(to, n, 0, DATA(&pkt), pkt.len - 2 * sizeof(node_id_t));
try_tx_sptps(n, true);
send_sptps_data(to, from, 0, DATA(&pkt), pkt.len - 2 * sizeof(node_id_t));
try_tx_sptps(to, true);
return;
}
} else {

View file

@ -223,7 +223,7 @@ bool detach(void) {
openlogger(identname, logmode);
logger(DEBUG_ALWAYS, LOG_NOTICE, "tincd %s (%s %s) starting, debug level %d",
VERSION, BUILD_DATE, BUILD_TIME, debug_level);
BUILD_VERSION, BUILD_DATE, BUILD_TIME, debug_level);
return true;
}

View file

@ -41,7 +41,8 @@ static bool (*request_handlers[])(connection_t *, const char *) = {
add_subnet_h, del_subnet_h,
add_edge_h, del_edge_h,
key_changed_h, req_key_h, ans_key_h, tcppacket_h, control_h,
NULL, NULL, NULL, /* Not "real" requests (yet) */
NULL, NULL, /* Not "real" requests (yet) */
sptps_tcppacket_h,
udp_info_h, mtu_info_h,
};
@ -53,7 +54,7 @@ static char (*request_name[]) = {
"PING", "PONG",
"ADD_SUBNET", "DEL_SUBNET",
"ADD_EDGE", "DEL_EDGE", "KEY_CHANGED", "REQ_KEY", "ANS_KEY", "PACKET", "CONTROL",
"REQ_PUBKEY", "ANS_PUBKEY", "REQ_SPTPS", "UDP_INFO", "MTU_INFO",
"REQ_PUBKEY", "ANS_PUBKEY", "SPTPS_PACKET", "UDP_INFO", "MTU_INFO",
};
static splay_tree_t *past_request_tree;

View file

@ -26,7 +26,7 @@
/* Protocol version. Different major versions are incompatible. */
#define PROT_MAJOR 17
#define PROT_MINOR 6 /* Should not exceed 255! */
#define PROT_MINOR 7 /* Should not exceed 255! */
/* Silly Windows */
@ -48,7 +48,7 @@ typedef enum request_t {
/* Tinc 1.1 requests */
CONTROL,
REQ_PUBKEY, ANS_PUBKEY,
REQ_SPTPS,
SPTPS_PACKET,
UDP_INFO, MTU_INFO,
LAST /* Guardian for the highest request number */
} request_t;
@ -109,6 +109,7 @@ extern void send_key_changed(void);
extern bool send_req_key(struct node_t *);
extern bool send_ans_key(struct node_t *);
extern bool send_tcppacket(struct connection_t *, const struct vpn_packet_t *);
extern bool send_sptps_tcppacket(struct connection_t *, const char*, int);
extern bool send_udp_info(struct node_t *, struct node_t *);
extern bool send_mtu_info(struct node_t *, struct node_t *, int);
@ -132,6 +133,7 @@ extern bool key_changed_h(struct connection_t *, const char *);
extern bool req_key_h(struct connection_t *, const char *);
extern bool ans_key_h(struct connection_t *, const char *);
extern bool tcppacket_h(struct connection_t *, const char *);
extern bool sptps_tcppacket_h(struct connection_t *, const char *);
extern bool control_h(struct connection_t *, const char *);
extern bool udp_info_h(struct connection_t *, const char *);
extern bool mtu_info_h(struct connection_t *, const char *);

View file

@ -87,9 +87,13 @@ bool key_changed_h(connection_t *c, const char *request) {
return true;
}
static bool send_sptps_data_myself(void *handle, uint8_t type, const void *data, size_t len) {
return send_sptps_data(handle, myself, type, data, len);
}
static bool send_initial_sptps_data(void *handle, uint8_t type, const void *data, size_t len) {
node_t *to = handle;
to->sptps.send_data = send_sptps_data;
to->sptps.send_data = send_sptps_data_myself;
char buf[len * 4 / 3 + 5];
b64encode(data, buf, len);
return send_request(to->nexthop->connection, "%d %s %s %d %s", REQ_KEY, myself->name, to->name, REQ_KEY, buf);
@ -121,7 +125,47 @@ bool send_req_key(node_t *to) {
/* REQ_KEY is overloaded to allow arbitrary requests to be routed between two nodes. */
static bool req_key_ext_h(connection_t *c, const char *request, node_t *from, int reqno) {
static bool req_key_ext_h(connection_t *c, const char *request, node_t *from, node_t *to, int reqno) {
/* If this is a SPTPS packet, see if sending UDP info helps.
Note that we only do this if we're the destination or the static relay;
otherwise every hop would initiate its own UDP info message, resulting in elevated chatter. */
if((reqno == REQ_KEY || reqno == SPTPS_PACKET) && to->via == myself)
send_udp_info(myself, from);
if(reqno == SPTPS_PACKET) {
/* This is a SPTPS data packet. */
char buf[MAX_STRING_SIZE];
int len;
if(sscanf(request, "%*d %*s %*s %*d " MAX_STRING, buf) != 1 || !(len = b64decode(buf, buf, strlen(buf)))) {
logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s) to %s (%s): %s", "SPTPS_PACKET", from->name, from->hostname, to->name, to->hostname, "invalid SPTPS data");
return true;
}
if(to != myself) {
/* We don't just forward the request, because we want to use UDP if it's available. */
send_sptps_data(to, from, 0, buf, len);
try_tx(to, true);
} else {
/* The packet is for us */
if(!from->status.validkey) {
logger(DEBUG_PROTOCOL, LOG_ERR, "Got SPTPS_PACKET from %s (%s) but we don't have a valid key yet", from->name, from->hostname);
return true;
}
sptps_receive_data(&from->sptps, buf, len);
send_mtu_info(myself, from, MTU);
}
return true;
}
/* Requests that are not SPTPS data packets are forwarded as-is. */
if (to != myself)
return send_request(to->nexthop->connection, "%s", request);
/* The request is for us */
switch(reqno) {
case REQ_PUBKEY: {
if(!node_read_ecdsa_public_key(from)) {
@ -176,24 +220,7 @@ static bool req_key_ext_h(connection_t *c, const char *request, node_t *from, in
from->status.validkey = false;
from->status.waitingforkey = true;
from->last_req_key = now.tv_sec;
sptps_start(&from->sptps, from, false, true, myself->connection->ecdsa, from->ecdsa, label, sizeof label, send_sptps_data, receive_sptps_record);
sptps_receive_data(&from->sptps, buf, len);
send_mtu_info(myself, from, MTU);
return true;
}
case REQ_SPTPS: {
if(!from->status.validkey) {
logger(DEBUG_PROTOCOL, LOG_ERR, "Got REQ_SPTPS from %s (%s) but we don't have a valid key yet", from->name, from->hostname);
return true;
}
char buf[MAX_STRING_SIZE];
int len;
if(sscanf(request, "%*d %*s %*s %*d " MAX_STRING, buf) != 1 || !(len = b64decode(buf, buf, strlen(buf)))) {
logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "REQ_SPTPS", from->name, from->hostname, "invalid SPTPS data");
return true;
}
sptps_start(&from->sptps, from, false, true, myself->connection->ecdsa, from->ecdsa, label, sizeof label, send_sptps_data_myself, receive_sptps_record);
sptps_receive_data(&from->sptps, buf, len);
send_mtu_info(myself, from, MTU);
return true;
@ -238,19 +265,12 @@ bool req_key_h(connection_t *c, const char *request) {
return true;
}
/* If this is a SPTPS packet, see if sending UDP info helps.
Note that we only do this if we're the destination or the static relay;
otherwise every hop would initiate its own UDP info message, resulting in elevated chatter. */
if(experimental && (reqno == REQ_KEY || reqno == REQ_SPTPS) && to->via == myself)
send_udp_info(myself, from);
/* Check if this key request is for us */
if(to == myself) { /* Yes */
/* Is this an extended REQ_KEY message? */
if(experimental && reqno)
return req_key_ext_h(c, request, from, reqno);
return req_key_ext_h(c, request, from, to, reqno);
/* No, just send our key back */
send_ans_key(from);
@ -264,7 +284,10 @@ bool req_key_h(connection_t *c, const char *request) {
return true;
}
/* TODO: forwarding SPTPS packets in this way is inefficient because we send them over TCP without checking for UDP connectivity */
/* Is this an extended REQ_KEY message? */
if(experimental && reqno)
return req_key_ext_h(c, request, from, to, reqno);
send_request(to->nexthop->connection, "%s", request);
}

View file

@ -193,6 +193,36 @@ bool tcppacket_h(connection_t *c, const char *request) {
return true;
}
bool send_sptps_tcppacket(connection_t *c, const char* packet, int len) {
/* If there already is a lot of data in the outbuf buffer, discard this packet.
We use a very simple Random Early Drop algorithm. */
if(2.0 * c->outbuf.len / (float)maxoutbufsize - 1 > (float)rand()/(float)RAND_MAX)
return true;
if(!send_request(c, "%d %hd", SPTPS_PACKET, len))
return false;
send_meta_raw(c, packet, len);
return true;
}
bool sptps_tcppacket_h(connection_t *c, const char* request) {
short int len;
if(sscanf(request, "%*d %hd", &len) != 1) {
logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "SPTPS_PACKET", c->name,
c->hostname);
return false;
}
/* Set sptpslen to len, this will tell receive_meta() that a SPTPS packet is coming. */
c->sptpslen = len;
return true;
}
/* Transmitting UDP information */
bool send_udp_info(node_t *from, node_t *to) {

View file

@ -495,90 +495,92 @@ static bool sptps_receive_data_datagram(sptps_t *s, const char *data, size_t len
}
// Receive incoming data. Check if it contains a complete record, if so, handle it.
bool sptps_receive_data(sptps_t *s, const void *data, size_t len) {
size_t sptps_receive_data(sptps_t *s, const void *data, size_t len) {
size_t total_read = 0;
if(!s->state)
return error(s, EIO, "Invalid session state zero");
if(s->datagram)
return sptps_receive_data_datagram(s, data, len);
return sptps_receive_data_datagram(s, data, len) ? len : false;
while(len) {
// First read the 2 length bytes.
if(s->buflen < 2) {
size_t toread = 2 - s->buflen;
if(toread > len)
toread = len;
memcpy(s->inbuf + s->buflen, data, toread);
s->buflen += toread;
len -= toread;
data += toread;
// Exit early if we don't have the full length.
if(s->buflen < 2)
return true;
// Get the length bytes
memcpy(&s->reclen, s->inbuf, 2);
s->reclen = ntohs(s->reclen);
// If we have the length bytes, ensure our buffer can hold the whole request.
s->inbuf = realloc(s->inbuf, s->reclen + 19UL);
if(!s->inbuf)
return error(s, errno, strerror(errno));
// Exit early if we have no more data to process.
if(!len)
return true;
}
// Read up to the end of the record.
size_t toread = s->reclen + (s->instate ? 19UL : 3UL) - s->buflen;
// First read the 2 length bytes.
if(s->buflen < 2) {
size_t toread = 2 - s->buflen;
if(toread > len)
toread = len;
memcpy(s->inbuf + s->buflen, data, toread);
total_read += toread;
s->buflen += toread;
len -= toread;
data += toread;
// If we don't have a whole record, exit.
if(s->buflen < s->reclen + (s->instate ? 19UL : 3UL))
return true;
// Exit early if we don't have the full length.
if(s->buflen < 2)
return total_read;
// Update sequence number.
// Get the length bytes
uint32_t seqno = s->inseqno++;
memcpy(&s->reclen, s->inbuf, 2);
s->reclen = ntohs(s->reclen);
// Check HMAC and decrypt.
if(s->instate) {
if(!chacha_poly1305_decrypt(s->incipher, seqno, s->inbuf + 2UL, s->reclen + 17UL, s->inbuf + 2UL, NULL))
return error(s, EINVAL, "Failed to decrypt and verify record");
}
// If we have the length bytes, ensure our buffer can hold the whole request.
s->inbuf = realloc(s->inbuf, s->reclen + 19UL);
if(!s->inbuf)
return error(s, errno, strerror(errno));
// Append a NULL byte for safety.
s->inbuf[s->reclen + 3UL] = 0;
uint8_t type = s->inbuf[2];
if(type < SPTPS_HANDSHAKE) {
if(!s->instate)
return error(s, EIO, "Application record received before handshake finished");
if(!s->receive_record(s->handle, type, s->inbuf + 3, s->reclen))
return false;
} else if(type == SPTPS_HANDSHAKE) {
if(!receive_handshake(s, s->inbuf + 3, s->reclen))
return false;
} else {
return error(s, EIO, "Invalid record type %d", type);
}
s->buflen = 0;
// Exit early if we have no more data to process.
if(!len)
return total_read;
}
return true;
// Read up to the end of the record.
size_t toread = s->reclen + (s->instate ? 19UL : 3UL) - s->buflen;
if(toread > len)
toread = len;
memcpy(s->inbuf + s->buflen, data, toread);
total_read += toread;
s->buflen += toread;
len -= toread;
data += toread;
// If we don't have a whole record, exit.
if(s->buflen < s->reclen + (s->instate ? 19UL : 3UL))
return total_read;
// Update sequence number.
uint32_t seqno = s->inseqno++;
// Check HMAC and decrypt.
if(s->instate) {
if(!chacha_poly1305_decrypt(s->incipher, seqno, s->inbuf + 2UL, s->reclen + 17UL, s->inbuf + 2UL, NULL))
return error(s, EINVAL, "Failed to decrypt and verify record");
}
// Append a NULL byte for safety.
s->inbuf[s->reclen + 3UL] = 0;
uint8_t type = s->inbuf[2];
if(type < SPTPS_HANDSHAKE) {
if(!s->instate)
return error(s, EIO, "Application record received before handshake finished");
if(!s->receive_record(s->handle, type, s->inbuf + 3, s->reclen))
return false;
} else if(type == SPTPS_HANDSHAKE) {
if(!receive_handshake(s, s->inbuf + 3, s->reclen))
return false;
} else {
return error(s, EIO, "Invalid record type %d", type);
}
s->buflen = 0;
return total_read;
}
// Start a SPTPS session.

View file

@ -88,7 +88,7 @@ extern void (*sptps_log)(sptps_t *s, int s_errno, const char *format, va_list ap
extern bool sptps_start(sptps_t *s, void *handle, bool initiator, bool datagram, ecdsa_t *mykey, ecdsa_t *hiskey, const void *label, size_t labellen, send_data_t send_data, receive_record_t receive_record);
extern bool sptps_stop(sptps_t *s);
extern bool sptps_send_record(sptps_t *s, uint8_t type, const void *data, uint16_t len);
extern bool sptps_receive_data(sptps_t *s, const void *data, size_t len);
extern size_t sptps_receive_data(sptps_t *s, const void *data, size_t len);
extern bool sptps_force_kex(sptps_t *s);
extern bool sptps_verify_datagram(sptps_t *s, const void *data, size_t len);

View file

@ -88,7 +88,7 @@ static struct option const long_options[] = {
static void version(void) {
printf("%s version %s (built %s %s, protocol %d.%d)\n", PACKAGE,
VERSION, BUILD_DATE, BUILD_TIME, PROT_MAJOR, PROT_MINOR);
BUILD_VERSION, BUILD_DATE, BUILD_TIME, PROT_MAJOR, PROT_MINOR);
printf("Copyright (C) 1998-2014 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"
@ -150,7 +150,7 @@ static void usage(bool status) {
" exchange Same as export followed by import\n"
" exchange-all Same as export-all followed by import\n"
" invite NODE [...] Generate an invitation for NODE\n"
" join INVITATION Join a VPN using an INVITIATION\n"
" join INVITATION Join a VPN using an INVITATION\n"
" network [NETNAME] List all known networks, or switch to the one named NETNAME.\n"
" fsck Check the configuration files for problems.\n"
"\n");

View file

@ -343,7 +343,7 @@ int main(int argc, char **argv) {
if(show_version) {
printf("%s version %s (built %s %s, protocol %d.%d)\n", PACKAGE,
VERSION, BUILD_DATE, BUILD_TIME, PROT_MAJOR, PROT_MINOR);
BUILD_VERSION, BUILD_DATE, BUILD_TIME, PROT_MAJOR, PROT_MINOR);
printf("Copyright (C) 1998-2014 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"

View file

@ -18,7 +18,14 @@
*/
#include "version.h"
#include "version_git.h"
#include "../config.h"
/* This file is always rebuilt (even if there are no changes) so that the following is updated */
const char* const BUILD_DATE = __DATE__;
const char* const BUILD_TIME = __TIME__;
#ifdef GIT_DESCRIPTION
const char* const BUILD_VERSION = GIT_DESCRIPTION;
#else
const char* const BUILD_VERSION = VERSION;
#endif

View file

@ -22,5 +22,6 @@
extern const char* const BUILD_DATE;
extern const char* const BUILD_TIME;
extern const char* const BUILD_VERSION;
#endif /* __TINC_VERSION_H__ */