Merge branch '1.1' of github.com:gsliepen/tinc into thkr-1.1-ponyhof
This commit is contained in:
commit
35af740537
21 changed files with 301 additions and 136 deletions
14
Makefile.am
14
Makefile.am
|
@ -2,14 +2,22 @@
|
||||||
|
|
||||||
AUTOMAKE_OPTIONS = gnu
|
AUTOMAKE_OPTIONS = gnu
|
||||||
|
|
||||||
SUBDIRS = m4 src doc gui test
|
SUBDIRS = src doc gui test
|
||||||
|
|
||||||
ACLOCAL_AMFLAGS = -I m4
|
ACLOCAL_AMFLAGS = -I m4
|
||||||
|
|
||||||
EXTRA_DIST = COPYING.README README.android
|
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:
|
ChangeLog:
|
||||||
git log > ChangeLog
|
(cd $(srcdir) && git log) > ChangeLog
|
||||||
|
|
||||||
deb:
|
deb:
|
||||||
dpkg-buildpackage -rfakeroot
|
dpkg-buildpackage -rfakeroot
|
||||||
|
@ -23,5 +31,5 @@ release:
|
||||||
rm -f ChangeLog
|
rm -f ChangeLog
|
||||||
$(MAKE) ChangeLog
|
$(MAKE) ChangeLog
|
||||||
echo "Please edit the NEWS file now..."
|
echo "Please edit the NEWS file now..."
|
||||||
/usr/bin/editor NEWS
|
/usr/bin/editor $(srcdir)/NEWS
|
||||||
$(MAKE) dist
|
$(MAKE) dist
|
||||||
|
|
18
configure.ac
18
configure.ac
|
@ -1,10 +1,10 @@
|
||||||
dnl Process this file with autoconf to produce a configure script.
|
dnl Process this file with autoconf to produce a configure script.
|
||||||
|
|
||||||
AC_PREREQ(2.61)
|
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_CONFIG_SRCDIR([src/tincd.c])
|
||||||
AC_GNU_SOURCE
|
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])
|
AC_CONFIG_HEADERS([config.h])
|
||||||
|
|
||||||
# Enable GNU extensions.
|
# 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_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([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],
|
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],
|
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],
|
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.
|
dnl Checks for typedefs, structures, and compiler characteristics.
|
||||||
|
@ -182,13 +182,13 @@ tinc_ATTRIBUTE(__malloc__)
|
||||||
tinc_ATTRIBUTE(__warn_unused_result__)
|
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], , ,
|
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.
|
dnl Checks for library functions.
|
||||||
AC_TYPE_SIGNAL
|
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],
|
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
|
dnl Support for SunOS
|
||||||
|
@ -201,7 +201,7 @@ AC_CHECK_FUNC(gethostbyname, [], [
|
||||||
])
|
])
|
||||||
|
|
||||||
AC_CHECK_DECLS([freeaddrinfo, gai_strerror, getaddrinfo, getnameinfo],
|
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)], [], [
|
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
|
AC_OUTPUT
|
||||||
|
|
|
@ -17,7 +17,7 @@ transform = s/ginstall/install/; @program_transform_name@
|
||||||
# see GNUmakefile and Makefile.maint.
|
# see GNUmakefile and Makefile.maint.
|
||||||
|
|
||||||
sample-config.tar.gz: sample-config
|
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
|
tincd.8.html: tincd.8
|
||||||
w3mman2html $? > $@
|
w3mman2html $? > $@
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
## Process this file with automake to produce Makefile.in -*-Makefile-*-
|
|
||||||
|
|
||||||
EXTRA_DIST = README *.m4
|
|
||||||
|
|
|
@ -2,9 +2,12 @@
|
||||||
|
|
||||||
sbin_PROGRAMS = tincd tinc sptps_test sptps_keypair
|
sbin_PROGRAMS = tincd tinc sptps_test sptps_keypair
|
||||||
|
|
||||||
## Make sure version.c is always rebuilt
|
## Make sure version.c is always rebuilt with the latest git information
|
||||||
.PHONY: version.c
|
.PHONY: $(srcdir)/version.c version_git.h
|
||||||
version.c:
|
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
|
if LINUX
|
||||||
sbin_PROGRAMS += sptps_speed
|
sbin_PROGRAMS += sptps_speed
|
||||||
|
@ -257,4 +260,4 @@ if TUNEMU
|
||||||
LIBS += -lpcap
|
LIBS += -lpcap
|
||||||
endif
|
endif
|
||||||
|
|
||||||
AM_CFLAGS = -DCONFDIR=\"$(sysconfdir)\" -DLOCALSTATEDIR=\"$(localstatedir)\" -DSBINDIR=\"$(sbindir)\"
|
AM_CFLAGS = -DCONFDIR=\"$(sysconfdir)\" -DLOCALSTATEDIR=\"$(localstatedir)\" -DSBINDIR=\"$(sbindir)\" -I.
|
||||||
|
|
|
@ -97,6 +97,7 @@ typedef struct connection_t {
|
||||||
struct buffer_t outbuf;
|
struct buffer_t outbuf;
|
||||||
io_t io; /* input/output event on this metadata connection */
|
io_t io; /* input/output event on this metadata connection */
|
||||||
int tcplen; /* length of incoming TCPpacket */
|
int tcplen; /* length of incoming TCPpacket */
|
||||||
|
int sptpslen; /* length of incoming SPTPS packet */
|
||||||
int allow_request; /* defined if there's only one request possible */
|
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 */
|
struct timeval last_ping_time; /* last time we saw some activity from the other end or pinged them */
|
||||||
|
|
43
src/meta.c
43
src/meta.c
|
@ -78,6 +78,20 @@ bool send_meta(connection_t *c, const char *buffer, int length) {
|
||||||
return true;
|
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) {
|
void broadcast_meta(connection_t *from, const char *buffer, int length) {
|
||||||
for list_each(connection_t, c, connection_list)
|
for list_each(connection_t, c, connection_list)
|
||||||
if(c != from && c->edge)
|
if(c != from && c->edge)
|
||||||
|
@ -159,8 +173,33 @@ bool receive_meta(connection_t *c) {
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if(c->protocol_minor >= 2)
|
/* Are we receiving a SPTPS packet? */
|
||||||
return sptps_receive_data(&c->sptps, bufp, inlen);
|
|
||||||
|
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) {
|
if(!c->status.decryptin) {
|
||||||
endp = memchr(bufp, '\n', inlen);
|
endp = memchr(bufp, '\n', inlen);
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
|
|
||||||
extern bool send_meta(struct connection_t *, const char *, int);
|
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 send_meta_sptps(void *, uint8_t, const void *, size_t);
|
||||||
extern bool receive_meta_sptps(void *, uint8_t, const void *, uint16_t);
|
extern bool receive_meta_sptps(void *, uint8_t, const void *, uint16_t);
|
||||||
extern void broadcast_meta(struct connection_t *, const char *, int);
|
extern void broadcast_meta(struct connection_t *, const char *, int);
|
||||||
|
|
|
@ -192,10 +192,11 @@ extern void handle_new_meta_connection(void *, int);
|
||||||
extern void handle_new_unix_connection(void *, int);
|
extern void handle_new_unix_connection(void *, int);
|
||||||
extern int setup_listen_socket(const sockaddr_t *);
|
extern int setup_listen_socket(const sockaddr_t *);
|
||||||
extern int setup_vpn_in_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 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 send_packet(struct node_t *, vpn_packet_t *);
|
||||||
extern void receive_tcppacket(struct connection_t *, const char *, int);
|
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 void broadcast_packet(const struct node_t *, vpn_packet_t *);
|
||||||
extern char *get_name(void);
|
extern char *get_name(void);
|
||||||
extern void device_enable(void);
|
extern void device_enable(void);
|
||||||
|
|
|
@ -429,6 +429,51 @@ void receive_tcppacket(connection_t *c, const char *buffer, int len) {
|
||||||
receive_packet(c->node, &outpkt);
|
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) {
|
static void send_sptps_packet(node_t *n, vpn_packet_t *origpkt) {
|
||||||
if(!n->status.validkey && !n->connection)
|
if(!n->status.validkey && !n->connection)
|
||||||
return;
|
return;
|
||||||
|
@ -682,7 +727,7 @@ end:
|
||||||
#endif
|
#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;
|
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 direct = from == myself && to == relay;
|
||||||
bool relay_supported = (relay->options >> 24) >= 4;
|
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. */
|
/* 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(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];
|
char buf[len * 4 / 3 + 5];
|
||||||
b64encode(data, buf, len);
|
b64encode(data, buf, len);
|
||||||
/* If no valid key is known yet, send the packets using ANS_KEY requests,
|
/* 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;
|
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);
|
return send_request(to->nexthop->connection, "%d %s %s %s -1 -1 -1 %d", ANS_KEY, from->name, to->name, buf, to->incompression);
|
||||||
} else {
|
} 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);
|
choose_local_address(relay, &sa, &sock);
|
||||||
if(!sa)
|
if(!sa)
|
||||||
choose_udp_address(relay, &sa, &sock);
|
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(sendto(listen_socket[sock].udp.fd, buf, buf_ptr - buf, 0, &sa->sa, SALEN(sa->sa)) < 0 && !sockwouldblock(sockerrno)) {
|
||||||
if(sockmsgsize(sockerrno)) {
|
if(sockmsgsize(sockerrno)) {
|
||||||
// Compensate for SPTPS overhead
|
// 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;
|
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) {
|
bool receive_sptps_record(void *handle, uint8_t type, const void *data, uint16_t len) {
|
||||||
node_t *from = handle;
|
node_t *from = handle;
|
||||||
|
|
||||||
|
@ -1405,8 +1455,8 @@ skip_harder:
|
||||||
/* If we're not the final recipient, relay the packet. */
|
/* If we're not the final recipient, relay the packet. */
|
||||||
|
|
||||||
if(to != myself) {
|
if(to != myself) {
|
||||||
send_sptps_data_priv(to, n, 0, DATA(&pkt), pkt.len - 2 * sizeof(node_id_t));
|
send_sptps_data(to, from, 0, DATA(&pkt), pkt.len - 2 * sizeof(node_id_t));
|
||||||
try_tx_sptps(n, true);
|
try_tx_sptps(to, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -223,7 +223,7 @@ bool detach(void) {
|
||||||
openlogger(identname, logmode);
|
openlogger(identname, logmode);
|
||||||
|
|
||||||
logger(DEBUG_ALWAYS, LOG_NOTICE, "tincd %s (%s %s) starting, debug level %d",
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,8 @@ static bool (*request_handlers[])(connection_t *, const char *) = {
|
||||||
add_subnet_h, del_subnet_h,
|
add_subnet_h, del_subnet_h,
|
||||||
add_edge_h, del_edge_h,
|
add_edge_h, del_edge_h,
|
||||||
key_changed_h, req_key_h, ans_key_h, tcppacket_h, control_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,
|
udp_info_h, mtu_info_h,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -53,7 +54,7 @@ static char (*request_name[]) = {
|
||||||
"PING", "PONG",
|
"PING", "PONG",
|
||||||
"ADD_SUBNET", "DEL_SUBNET",
|
"ADD_SUBNET", "DEL_SUBNET",
|
||||||
"ADD_EDGE", "DEL_EDGE", "KEY_CHANGED", "REQ_KEY", "ANS_KEY", "PACKET", "CONTROL",
|
"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;
|
static splay_tree_t *past_request_tree;
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
/* Protocol version. Different major versions are incompatible. */
|
/* Protocol version. Different major versions are incompatible. */
|
||||||
|
|
||||||
#define PROT_MAJOR 17
|
#define PROT_MAJOR 17
|
||||||
#define PROT_MINOR 6 /* Should not exceed 255! */
|
#define PROT_MINOR 7 /* Should not exceed 255! */
|
||||||
|
|
||||||
/* Silly Windows */
|
/* Silly Windows */
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ typedef enum request_t {
|
||||||
/* Tinc 1.1 requests */
|
/* Tinc 1.1 requests */
|
||||||
CONTROL,
|
CONTROL,
|
||||||
REQ_PUBKEY, ANS_PUBKEY,
|
REQ_PUBKEY, ANS_PUBKEY,
|
||||||
REQ_SPTPS,
|
SPTPS_PACKET,
|
||||||
UDP_INFO, MTU_INFO,
|
UDP_INFO, MTU_INFO,
|
||||||
LAST /* Guardian for the highest request number */
|
LAST /* Guardian for the highest request number */
|
||||||
} request_t;
|
} request_t;
|
||||||
|
@ -109,6 +109,7 @@ extern void send_key_changed(void);
|
||||||
extern bool send_req_key(struct node_t *);
|
extern bool send_req_key(struct node_t *);
|
||||||
extern bool send_ans_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_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_udp_info(struct node_t *, struct node_t *);
|
||||||
extern bool send_mtu_info(struct node_t *, struct node_t *, int);
|
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 req_key_h(struct connection_t *, const char *);
|
||||||
extern bool ans_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 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 control_h(struct connection_t *, const char *);
|
||||||
extern bool udp_info_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 *);
|
extern bool mtu_info_h(struct connection_t *, const char *);
|
||||||
|
|
|
@ -87,9 +87,13 @@ bool key_changed_h(connection_t *c, const char *request) {
|
||||||
return true;
|
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) {
|
static bool send_initial_sptps_data(void *handle, uint8_t type, const void *data, size_t len) {
|
||||||
node_t *to = handle;
|
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];
|
char buf[len * 4 / 3 + 5];
|
||||||
b64encode(data, buf, len);
|
b64encode(data, buf, len);
|
||||||
return send_request(to->nexthop->connection, "%d %s %s %d %s", REQ_KEY, myself->name, to->name, REQ_KEY, buf);
|
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. */
|
/* 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) {
|
switch(reqno) {
|
||||||
case REQ_PUBKEY: {
|
case REQ_PUBKEY: {
|
||||||
if(!node_read_ecdsa_public_key(from)) {
|
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.validkey = false;
|
||||||
from->status.waitingforkey = true;
|
from->status.waitingforkey = true;
|
||||||
from->last_req_key = now.tv_sec;
|
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_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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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_receive_data(&from->sptps, buf, len);
|
sptps_receive_data(&from->sptps, buf, len);
|
||||||
send_mtu_info(myself, from, MTU);
|
send_mtu_info(myself, from, MTU);
|
||||||
return true;
|
return true;
|
||||||
|
@ -238,19 +265,12 @@ bool req_key_h(connection_t *c, const char *request) {
|
||||||
return true;
|
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 */
|
/* Check if this key request is for us */
|
||||||
|
|
||||||
if(to == myself) { /* Yes */
|
if(to == myself) { /* Yes */
|
||||||
/* Is this an extended REQ_KEY message? */
|
/* Is this an extended REQ_KEY message? */
|
||||||
if(experimental && reqno)
|
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 */
|
/* No, just send our key back */
|
||||||
send_ans_key(from);
|
send_ans_key(from);
|
||||||
|
@ -264,7 +284,10 @@ bool req_key_h(connection_t *c, const char *request) {
|
||||||
return true;
|
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);
|
send_request(to->nexthop->connection, "%s", request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -193,6 +193,36 @@ bool tcppacket_h(connection_t *c, const char *request) {
|
||||||
return true;
|
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 */
|
/* Transmitting UDP information */
|
||||||
|
|
||||||
bool send_udp_info(node_t *from, node_t *to) {
|
bool send_udp_info(node_t *from, node_t *to) {
|
||||||
|
|
18
src/sptps.c
18
src/sptps.c
|
@ -495,14 +495,15 @@ 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.
|
// 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)
|
if(!s->state)
|
||||||
return error(s, EIO, "Invalid session state zero");
|
return error(s, EIO, "Invalid session state zero");
|
||||||
|
|
||||||
if(s->datagram)
|
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.
|
// First read the 2 length bytes.
|
||||||
if(s->buflen < 2) {
|
if(s->buflen < 2) {
|
||||||
size_t toread = 2 - s->buflen;
|
size_t toread = 2 - s->buflen;
|
||||||
|
@ -511,13 +512,14 @@ bool sptps_receive_data(sptps_t *s, const void *data, size_t len) {
|
||||||
|
|
||||||
memcpy(s->inbuf + s->buflen, data, toread);
|
memcpy(s->inbuf + s->buflen, data, toread);
|
||||||
|
|
||||||
|
total_read += toread;
|
||||||
s->buflen += toread;
|
s->buflen += toread;
|
||||||
len -= toread;
|
len -= toread;
|
||||||
data += toread;
|
data += toread;
|
||||||
|
|
||||||
// Exit early if we don't have the full length.
|
// Exit early if we don't have the full length.
|
||||||
if(s->buflen < 2)
|
if(s->buflen < 2)
|
||||||
return true;
|
return total_read;
|
||||||
|
|
||||||
// Get the length bytes
|
// Get the length bytes
|
||||||
|
|
||||||
|
@ -531,7 +533,7 @@ bool sptps_receive_data(sptps_t *s, const void *data, size_t len) {
|
||||||
|
|
||||||
// Exit early if we have no more data to process.
|
// Exit early if we have no more data to process.
|
||||||
if(!len)
|
if(!len)
|
||||||
return true;
|
return total_read;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read up to the end of the record.
|
// Read up to the end of the record.
|
||||||
|
@ -540,13 +542,14 @@ bool sptps_receive_data(sptps_t *s, const void *data, size_t len) {
|
||||||
toread = len;
|
toread = len;
|
||||||
|
|
||||||
memcpy(s->inbuf + s->buflen, data, toread);
|
memcpy(s->inbuf + s->buflen, data, toread);
|
||||||
|
total_read += toread;
|
||||||
s->buflen += toread;
|
s->buflen += toread;
|
||||||
len -= toread;
|
len -= toread;
|
||||||
data += toread;
|
data += toread;
|
||||||
|
|
||||||
// If we don't have a whole record, exit.
|
// If we don't have a whole record, exit.
|
||||||
if(s->buflen < s->reclen + (s->instate ? 19UL : 3UL))
|
if(s->buflen < s->reclen + (s->instate ? 19UL : 3UL))
|
||||||
return true;
|
return total_read;
|
||||||
|
|
||||||
// Update sequence number.
|
// Update sequence number.
|
||||||
|
|
||||||
|
@ -576,9 +579,8 @@ bool sptps_receive_data(sptps_t *s, const void *data, size_t len) {
|
||||||
}
|
}
|
||||||
|
|
||||||
s->buflen = 0;
|
s->buflen = 0;
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return total_read;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start a SPTPS session.
|
// Start a SPTPS session.
|
||||||
|
|
|
@ -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_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_stop(sptps_t *s);
|
||||||
extern bool sptps_send_record(sptps_t *s, uint8_t type, const void *data, uint16_t len);
|
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_force_kex(sptps_t *s);
|
||||||
extern bool sptps_verify_datagram(sptps_t *s, const void *data, size_t len);
|
extern bool sptps_verify_datagram(sptps_t *s, const void *data, size_t len);
|
||||||
|
|
||||||
|
|
|
@ -88,7 +88,7 @@ static struct option const long_options[] = {
|
||||||
|
|
||||||
static void version(void) {
|
static void version(void) {
|
||||||
printf("%s version %s (built %s %s, protocol %d.%d)\n", PACKAGE,
|
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"
|
printf("Copyright (C) 1998-2014 Ivo Timmermans, Guus Sliepen and others.\n"
|
||||||
"See the AUTHORS file for a complete list.\n\n"
|
"See the AUTHORS file for a complete list.\n\n"
|
||||||
"tinc comes with ABSOLUTELY NO WARRANTY. This is free software,\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 Same as export followed by import\n"
|
||||||
" exchange-all Same as export-all followed by import\n"
|
" exchange-all Same as export-all followed by import\n"
|
||||||
" invite NODE [...] Generate an invitation for NODE\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"
|
" network [NETNAME] List all known networks, or switch to the one named NETNAME.\n"
|
||||||
" fsck Check the configuration files for problems.\n"
|
" fsck Check the configuration files for problems.\n"
|
||||||
"\n");
|
"\n");
|
||||||
|
|
|
@ -343,7 +343,7 @@ int main(int argc, char **argv) {
|
||||||
|
|
||||||
if(show_version) {
|
if(show_version) {
|
||||||
printf("%s version %s (built %s %s, protocol %d.%d)\n", PACKAGE,
|
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"
|
printf("Copyright (C) 1998-2014 Ivo Timmermans, Guus Sliepen and others.\n"
|
||||||
"See the AUTHORS file for a complete list.\n\n"
|
"See the AUTHORS file for a complete list.\n\n"
|
||||||
"tinc comes with ABSOLUTELY NO WARRANTY. This is free software,\n"
|
"tinc comes with ABSOLUTELY NO WARRANTY. This is free software,\n"
|
||||||
|
|
|
@ -18,7 +18,14 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "version.h"
|
#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 */
|
/* 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_DATE = __DATE__;
|
||||||
const char* const BUILD_TIME = __TIME__;
|
const char* const BUILD_TIME = __TIME__;
|
||||||
|
#ifdef GIT_DESCRIPTION
|
||||||
|
const char* const BUILD_VERSION = GIT_DESCRIPTION;
|
||||||
|
#else
|
||||||
|
const char* const BUILD_VERSION = VERSION;
|
||||||
|
#endif
|
||||||
|
|
|
@ -22,5 +22,6 @@
|
||||||
|
|
||||||
extern const char* const BUILD_DATE;
|
extern const char* const BUILD_DATE;
|
||||||
extern const char* const BUILD_TIME;
|
extern const char* const BUILD_TIME;
|
||||||
|
extern const char* const BUILD_VERSION;
|
||||||
|
|
||||||
#endif /* __TINC_VERSION_H__ */
|
#endif /* __TINC_VERSION_H__ */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue