fixed conflict in src/sptps.c

This commit is contained in:
thorkill 2015-05-20 14:34:10 +02:00
commit 26c7ff7fdd
15 changed files with 237 additions and 166 deletions

View file

@ -5,7 +5,7 @@ _tinc() {
prev="${COMP_WORDS[COMP_CWORD-1]}"
opts="-c -d -D -K -n -o -L -R -U --config --no-detach --debug --net --option --mlock --logfile --pidfile --chroot --user --help --version"
confvars="Address AddressFamily BindToAddress BindToInterface Broadcast BroadcastSubnet Cipher ClampMSS Compression ConnectTo DecrementTTL Device DeviceStandby DeviceType Digest DirectOnly Ed25519PrivateKeyFile Ed25519PublicKey Ed25519PublicKeyFile ExperimentalProtocol Forwarding GraphDumpFile Hostnames IffOneQueue IndirectData Interface KeyExpire ListenAddress LocalDiscovery MACExpire MACLength MaxOutputBufferSize MaxTimeout Mode MTUInfoInterval Name PMTU PMTUDiscovery PingInterval PingTimeout Port PriorityInheritance PrivateKeyFile ProcessPriority Proxy PublicKeyFile ReplayWindow StrictSubnets Subnet TCPOnly TunnelServer UDPDiscovery UDPDiscoveryKeepaliveInterval UDPDiscoveryInterval UDPDiscoveryTimeout UDPInfoInterval UDPRcvBuf UDPSndBuf VDEGroup VDEPort Weight"
commands="add connect debug del disconnect dump edit export export-all generate-ed25519-keys generate-keys generate-rsa-keys get help import info init invite join log network pcap pid purge reload restart retry set start stop top version"
commands="add connect debug del disconnect dump edit export export-all generate-ed25519-keys generate-keys generate-rsa-keys get help import info init invite join list log network pcap pid purge reload restart retry set start stop top version"
case ${prev} in
-c|--config)
@ -57,8 +57,8 @@ _tinc() {
COMPREPLY=( $(compgen -W "${confvars}" -- ${cur}) )
return 0
;;
dump|reachable)
COMPREPLY=( $(compgen -W "reachable nodes edges subnets connections graph" -- ${cur}) )
dump|list|reachable)
COMPREPLY=( $(compgen -W "reachable nodes edges subnets connections graph invitations" -- ${cur}) )
return 0
;;
network)

View file

@ -172,6 +172,9 @@ format.
Nodes are colored according to their reachability:
red nodes are unreachable, orange nodes are indirectly reachable, green nodes are directly reachable.
Black nodes are either directly or indirectly reachable, but direct reachability has not been tried yet.
.It dump invitations
Dump a list of outstanding invitations.
The filename of the invitation, as well as the name of the node that is being invited is shown for each invitation.
.It info Ar node | subnet | address
Show information about a particular node, subnet or address.
If an address is given, any matching subnet will be shown.

View file

@ -2408,6 +2408,10 @@ Nodes are colored according to their reachability:
red nodes are unreachable, orange nodes are indirectly reachable, green nodes are directly reachable.
Black nodes are either directly or indirectly reachable, but direct reachability has not been tried yet.
@item dump invitations
Dump a list of outstanding invitations.
The filename of the invitation, as well as the name of the node that is being invited is shown for each invitation.
@cindex info
@item info @var{node} | @var{subnet} | @var{address}
Show information about a particular @var{node}, @var{subnet} or @var{address}.

View file

@ -4,7 +4,7 @@
1998-2005 Ivo Timmermans
2000 Cris van Pelt
2010-2011 Julien Muchembled <jm@jmuchemb.eu>
2000-2013 Guus Sliepen <guus@tinc-vpn.org>
2000-2015 Guus Sliepen <guus@tinc-vpn.org>
2013 Florent Clairambault <florent@clairambault.fr>
This program is free software; you can redistribute it and/or modify
@ -368,19 +368,19 @@ void read_config_options(splay_tree_t *config_tree, const char *prefix) {
}
bool read_server_config(void) {
char *fname;
char fname[PATH_MAX];
bool x;
read_config_options(config_tree, NULL);
xasprintf(&fname, "%s" SLASH "tinc.conf", confbase);
snprintf(fname, sizeof fname, "%s" SLASH "tinc.conf", confbase);
errno = 0;
x = read_config_file(config_tree, fname);
// We will try to read the conf files in the "conf.d" dir
if (x) {
char * dname;
xasprintf(&dname, "%s" SLASH "conf.d", confbase);
char dname[PATH_MAX];
snprintf(dname, sizeof dname, "%s" SLASH "conf.d", confbase);
DIR *dir = opendir (dname);
// If we can find this dir
if (dir) {
@ -390,51 +390,44 @@ bool read_server_config(void) {
size_t l = strlen(ep->d_name);
// And we try to read the ones that end with ".conf"
if (l > 5 && !strcmp(".conf", & ep->d_name[ l - 5 ])) {
free(fname);
xasprintf(&fname, "%s" SLASH "%s", dname, ep->d_name);
snprintf(fname, sizeof fname, "%s" SLASH "%s", dname, ep->d_name);
x = read_config_file(config_tree, fname);
}
}
closedir (dir);
}
free(dname);
}
if(!x && errno)
logger(DEBUG_ALWAYS, LOG_ERR, "Failed to read `%s': %s", fname, strerror(errno));
free(fname);
return x;
}
bool read_host_config(splay_tree_t *config_tree, const char *name) {
char *fname;
char fname[PATH_MAX];
bool x;
read_config_options(config_tree, name);
xasprintf(&fname, "%s" SLASH "hosts" SLASH "%s", confbase, name);
snprintf(fname, sizeof fname, "%s" SLASH "hosts" SLASH "%s", confbase, name);
x = read_config_file(config_tree, fname);
free(fname);
return x;
}
bool append_config_file(const char *name, const char *key, const char *value) {
char *fname;
xasprintf(&fname, "%s" SLASH "hosts" SLASH "%s", confbase, name);
char fname[PATH_MAX];
snprintf(fname, sizeof fname, "%s" SLASH "hosts" SLASH "%s", confbase, name);
FILE *fp = fopen(fname, "a");
if(!fp) {
logger(DEBUG_ALWAYS, LOG_ERR, "Cannot open config file %s: %s", fname, strerror(errno));
} else {
fprintf(fp, "\n# The following line was automatically added by tinc\n%s = %s\n", key, value);
fclose(fp);
return false;
}
free(fname);
return fp != NULL;
fprintf(fp, "\n# The following line was automatically added by tinc\n%s = %s\n", key, value);
fclose(fp);
return true;
}

View file

@ -1,6 +1,6 @@
/*
invitation.c -- Create and accept invitations
Copyright (C) 2013-2014 Guus Sliepen <guus@tinc-vpn.org>
Copyright (C) 2013-2015 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
@ -84,11 +84,11 @@ char *get_my_hostname() {
char *port = NULL;
char *hostport = NULL;
char *name = get_my_name(false);
char *filename = NULL;
char filename[PATH_MAX];
// Use first Address statement in own host config file
if(check_id(name)) {
xasprintf(&filename, "%s" SLASH "hosts" SLASH "%s", confbase, name);
snprintf(filename, sizeof filename, "%s" SLASH "hosts" SLASH "%s", confbase, name);
scan_for_hostname(filename, &hostname, &port);
scan_for_hostname(tinc_conf, &hostname, &port);
}
@ -207,7 +207,6 @@ done:
free(hostname);
free(port);
free(filename);
return hostport;
}
@ -243,14 +242,12 @@ int cmd_invite(int argc, char *argv[]) {
return 1;
// Ensure no host configuration file with that name exists
char *filename = NULL;
xasprintf(&filename, "%s" SLASH "hosts" SLASH "%s", confbase, argv[1]);
char filename[PATH_MAX];
snprintf(filename, sizeof filename, "%s" SLASH "hosts" SLASH "%s", confbase, argv[1]);
if(!access(filename, F_OK)) {
free(filename);
fprintf(stderr, "A host config file for %s already exists!\n", argv[1]);
return 1;
}
free(filename);
// If a daemon is running, ensure no other nodes know about this name
bool found = false;
@ -272,10 +269,9 @@ int cmd_invite(int argc, char *argv[]) {
}
}
xasprintf(&filename, "%s" SLASH "invitations", confbase);
snprintf(filename, sizeof filename, "%s" SLASH "invitations", confbase);
if(mkdir(filename, 0700) && errno != EEXIST) {
fprintf(stderr, "Could not create directory %s: %s\n", filename, strerror(errno));
free(filename);
return 1;
}
@ -283,7 +279,6 @@ int cmd_invite(int argc, char *argv[]) {
DIR *dir = opendir(filename);
if(!dir) {
fprintf(stderr, "Could not read directory %s: %s\n", filename, strerror(errno));
free(filename);
return 1;
}
@ -295,9 +290,9 @@ int cmd_invite(int argc, char *argv[]) {
while((ent = readdir(dir))) {
if(strlen(ent->d_name) != 24)
continue;
char *invname;
char invname[PATH_MAX];
struct stat st;
xasprintf(&invname, "%s" SLASH "%s", filename, ent->d_name);
snprintf(invname, sizeof invname, "%s" SLASH "%s", filename, ent->d_name);
if(!stat(invname, &st)) {
if(deadline < st.st_mtime)
count++;
@ -307,21 +302,17 @@ int cmd_invite(int argc, char *argv[]) {
fprintf(stderr, "Could not stat %s: %s\n", invname, strerror(errno));
errno = 0;
}
free(invname);
}
closedir(dir);
if(errno) {
fprintf(stderr, "Error while reading directory %s: %s\n", filename, strerror(errno));
closedir(dir);
free(filename);
return 1;
}
closedir(dir);
free(filename);
ecdsa_t *key;
xasprintf(&filename, "%s" SLASH "invitations" SLASH "ed25519_key.priv", confbase);
snprintf(filename, sizeof filename, "%s" SLASH "invitations" SLASH "ed25519_key.priv", confbase);
// Remove the key if there are no outstanding invitations.
if(!count)
@ -332,19 +323,15 @@ int cmd_invite(int argc, char *argv[]) {
if(!f) {
if(errno != ENOENT) {
fprintf(stderr, "Could not read %s: %s\n", filename, strerror(errno));
free(filename);
return 1;
}
key = ecdsa_generate();
if(!key) {
free(filename);
if(!key)
return 1;
}
f = fopen(filename, "w");
if(!f) {
fprintf(stderr, "Could not write %s: %s\n", filename, strerror(errno));
free(filename);
return 1;
}
chmod(filename, 0600);
@ -360,7 +347,6 @@ int cmd_invite(int argc, char *argv[]) {
fprintf(stderr, "Could not read private key from %s\n", filename);
}
free(filename);
if(!key)
return 1;
@ -385,11 +371,10 @@ int cmd_invite(int argc, char *argv[]) {
b64encode_urlsafe(cookie, cookie, 18);
// Create a file containing the details of the invitation.
xasprintf(&filename, "%s" SLASH "invitations" SLASH "%s", confbase, cookiehash);
snprintf(filename, sizeof filename, "%s" SLASH "invitations" SLASH "%s", confbase, cookiehash);
int ifd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
if(!ifd) {
fprintf(stderr, "Could not create invitation file %s: %s\n", filename, strerror(errno));
free(filename);
return 1;
}
f = fdopen(ifd, "w");
@ -424,11 +409,10 @@ int cmd_invite(int argc, char *argv[]) {
fprintf(f, "#---------------------------------------------------------------#\n");
fprintf(f, "Name = %s\n", myname);
char *filename2;
xasprintf(&filename2, "%s" SLASH "hosts" SLASH "%s", confbase, myname);
char filename2[PATH_MAX];
snprintf(filename2, sizeof filename2, "%s" SLASH "hosts" SLASH "%s", confbase, myname);
fcopy(f, filename2);
fclose(f);
free(filename2);
// Create an URL from the local address, key hash and cookie
char *url;
@ -447,7 +431,6 @@ int cmd_invite(int argc, char *argv[]) {
puts(url);
free(url);
free(filename);
free(address);
return 0;
@ -568,7 +551,7 @@ make_names:
confbase = NULL;
}
make_names();
make_names(false);
free(tinc_conf);
free(hosts_dir);
@ -606,8 +589,8 @@ make_names:
fprintf(f, "Name = %s\n", name);
char *filename;
xasprintf(&filename, "%s" SLASH "%s", hosts_dir, name);
char filename[PATH_MAX];
snprintf(filename, sizeof filename, "%s" SLASH "%s", hosts_dir, name);
FILE *fh = fopen(filename, "w");
if(!fh) {
fprintf(stderr, "Could not create file %s: %s\n", filename, strerror(errno));
@ -668,7 +651,6 @@ make_names:
}
fclose(f);
free(filename);
while(l && !strcasecmp(l, "Name")) {
if(!check_id(value)) {
@ -681,7 +663,7 @@ make_names:
return false;
}
xasprintf(&filename, "%s" SLASH "%s", hosts_dir, value);
snprintf(filename, sizeof filename, "%s" SLASH "%s", hosts_dir, value);
f = fopen(filename, "w");
if(!f) {
@ -709,7 +691,6 @@ make_names:
}
fclose(f);
free(filename);
}
// Generate our key and send a copy to the server
@ -721,7 +702,7 @@ make_names:
if(!b64key)
return false;
xasprintf(&filename, "%s" SLASH "ed25519_key.priv", confbase);
snprintf(filename, sizeof filename, "%s" SLASH "ed25519_key.priv", confbase);
f = fopenmask(filename, "w", 0600);
if(!ecdsa_write_pem_private_key(key, f)) {
@ -741,7 +722,7 @@ make_names:
#ifndef DISABLE_LEGACY
rsa_t *rsa = rsa_generate(2048, 0x1001);
xasprintf(&filename, "%s" SLASH "rsa_key.priv", confbase);
snprintf(filename, sizeof filename, "%s" SLASH "rsa_key.priv", confbase);
f = fopenmask(filename, "w", 0600);
rsa_write_pem_private_key(rsa, f);
@ -767,17 +748,15 @@ ask_netname:
line[strlen(line) - 1] = 0;
char *newbase;
xasprintf(&newbase, CONFDIR SLASH "tinc" SLASH "%s", line);
char newbase[PATH_MAX];
snprintf(newbase, sizeof newbase, CONFDIR SLASH "tinc" SLASH "%s", line);
if(rename(confbase, newbase)) {
fprintf(stderr, "Error trying to rename %s to %s: %s\n", confbase, newbase, strerror(errno));
free(newbase);
goto ask_netname;
}
free(newbase);
netname = line;
make_names();
make_names(false);
}
fprintf(stderr, "Configuration stored in: %s\n", confbase);

View file

@ -101,6 +101,9 @@ static bool setup_device(void) {
strncpy(ifrname, ifr.ifr_name, IFNAMSIZ);
free(iface);
iface = xstrdup(ifrname);
} else {
logger(DEBUG_ALWAYS, LOG_ERR, "Could not create a tun/tap interface from %s: %s", device, strerror(errno));
return false;
}
logger(DEBUG_ALWAYS, LOG_INFO, "%s is a %s", device, device_info);

View file

@ -1,6 +1,6 @@
/*
logger.c -- logging code
Copyright (C) 2004-2013 Guus Sliepen <guus@tinc-vpn.org>
Copyright (C) 2004-2015 Guus Sliepen <guus@tinc-vpn.org>
2004-2005 Ivo Timmermans
This program is free software; you can redistribute it and/or modify
@ -114,9 +114,17 @@ void logger(int level, int priority, const char *format, ...) {
static void sptps_logger(sptps_t *s, int s_errno, const char *format, va_list ap) {
char message[1024] = "";
int len = vsnprintf(message, sizeof message, format, ap);
if(len > 0 && len < sizeof message && message[len - 1] == '\n')
message[len - 1] = 0;
size_t msglen = sizeof message;
int len = vsnprintf(message, msglen, format, ap);
if(len > 0 && len < sizeof message) {
if(message[len - 1] == '\n')
message[--len] = 0;
connection_t *c = s->handle;
if(c)
snprintf(message + len, sizeof message - len, " from %s (%s)", c->name, c->hostname);
}
real_logger(DEBUG_ALWAYS, LOG_ERR, message);
}

View file

@ -1,7 +1,7 @@
/*
names.c -- generate commonly used (file)names
Copyright (C) 1998-2005 Ivo Timmermans
2000-2013 Guus Sliepen <guus@tinc-vpn.org>
2000-2015 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
@ -36,7 +36,7 @@ char *program_name = NULL;
/*
Set all files and paths according to netname
*/
void make_names(void) {
void make_names(bool daemon) {
#ifdef HAVE_MINGW
HKEY key;
char installdir[1024] = "";
@ -85,11 +85,36 @@ void make_names(void) {
if(!pidfilename)
xasprintf(&pidfilename, "%s" SLASH "pid", confbase);
#else
if(!logfilename)
xasprintf(&logfilename, LOCALSTATEDIR SLASH "log" SLASH "%s.log", identname);
bool fallback = false;
if(daemon) {
if(access(LOCALSTATEDIR, R_OK | W_OK | X_OK))
fallback = true;
} else {
char fname[PATH_MAX];
snprintf(fname, sizeof fname, LOCALSTATEDIR SLASH "run" SLASH "%s.pid", identname);
if(access(fname, R_OK)) {
snprintf(fname, sizeof fname, "%s" SLASH "pid", confbase);
if(!access(fname, R_OK))
fallback = true;
}
}
if(!pidfilename)
xasprintf(&pidfilename, LOCALSTATEDIR SLASH "run" SLASH "%s.pid", identname);
if(!fallback) {
if(!logfilename)
xasprintf(&logfilename, LOCALSTATEDIR SLASH "log" SLASH "%s.log", identname);
if(!pidfilename)
xasprintf(&pidfilename, LOCALSTATEDIR SLASH "run" SLASH "%s.pid", identname);
} else {
if(!logfilename)
xasprintf(&logfilename, "%s" SLASH "log", confbase);
if(!pidfilename) {
if(daemon)
logger(DEBUG_ALWAYS, LOG_WARNING, "Could not access " LOCALSTATEDIR SLASH " (%s), storing pid and socket files in %s" SLASH, strerror(errno), confbase);
xasprintf(&pidfilename, "%s" SLASH "pid", confbase);
}
}
#endif
if(!unixsocketname) {

View file

@ -1,7 +1,7 @@
/*
names.h -- header for names.c
Copyright (C) 1998-2005 Ivo Timmermans
2000-2013 Guus Sliepen <guus@tinc-vpn.org>
2000-2015 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
@ -31,7 +31,7 @@ extern char *logfilename;
extern char *pidfilename;
extern char *program_name;
extern void make_names(void);
extern void make_names(bool daemon);
extern void free_names(void);
#endif /* __TINC_NAMES_H__ */

View file

@ -1,7 +1,7 @@
/*
net.c -- most of the network code
Copyright (C) 1998-2005 Ivo Timmermans,
2000-2013 Guus Sliepen <guus@tinc-vpn.org>
2000-2015 Guus Sliepen <guus@tinc-vpn.org>
2006 Scott Lamb <slamb@slamb.org>
2011 Loïc Grenié <loic.grenie@gmail.com>
@ -314,7 +314,7 @@ static void sigalrm_handler(void *data) {
#endif
int reload_configuration(void) {
char *fname = NULL;
char fname[PATH_MAX];
/* Reread our own configuration file */
@ -328,9 +328,8 @@ int reload_configuration(void) {
read_config_options(config_tree, NULL);
xasprintf(&fname, "%s" SLASH "hosts" SLASH "%s", confbase, myself->name);
snprintf(fname, sizeof fname, "%s" SLASH "hosts" SLASH "%s", confbase, myself->name);
read_config_file(config_tree, fname);
free(fname);
/* Parse some options that are allowed to be changed while tinc is running */
@ -407,13 +406,12 @@ int reload_configuration(void) {
if(c->status.control)
continue;
xasprintf(&fname, "%s" SLASH "hosts" SLASH "%s", confbase, c->name);
snprintf(fname, sizeof fname, "%s" SLASH "hosts" SLASH "%s", confbase, c->name);
struct stat s;
if(stat(fname, &s) || s.st_mtime > last_config_check) {
logger(DEBUG_CONNECTIONS, LOG_INFO, "Host config file of %s has been changed", c->name);
terminate_connection(c, c->edge);
}
free(fname);
}
last_config_check = now.tv_sec;

View file

@ -1,7 +1,7 @@
/*
net_setup.c -- Setup.
Copyright (C) 1998-2005 Ivo Timmermans,
2000-2014 Guus Sliepen <guus@tinc-vpn.org>
2000-2015 Guus Sliepen <guus@tinc-vpn.org>
2006 Scott Lamb <slamb@slamb.org>
2010 Brandon Black <blblack@gmail.com>
@ -226,14 +226,14 @@ static bool read_ecdsa_private_key(void) {
static bool read_invitation_key(void) {
FILE *fp;
char *fname;
char fname[PATH_MAX];
if(invitation_key) {
ecdsa_free(invitation_key);
invitation_key = NULL;
}
xasprintf(&fname, "%s" SLASH "invitations" SLASH "ed25519_key.priv", confbase);
snprintf(fname, sizeof fname, "%s" SLASH "invitations" SLASH "ed25519_key.priv", confbase);
fp = fopen(fname, "r");
@ -244,7 +244,6 @@ static bool read_invitation_key(void) {
logger(DEBUG_ALWAYS, LOG_ERR, "Reading Ed25519 private key file `%s' failed", fname);
}
free(fname);
return invitation_key;
}
@ -356,13 +355,12 @@ void update_edge_weight(void) {
void load_all_subnets(void) {
DIR *dir;
struct dirent *ent;
char *dname;
char dname[PATH_MAX];
xasprintf(&dname, "%s" SLASH "hosts", confbase);
snprintf(dname, sizeof dname, "%s" SLASH "hosts", confbase);
dir = opendir(dname);
if(!dir) {
logger(DEBUG_ALWAYS, LOG_ERR, "Could not open %s: %s", dname, strerror(errno));
free(dname);
return;
}
@ -409,13 +407,12 @@ void load_all_subnets(void) {
void load_all_nodes(void) {
DIR *dir;
struct dirent *ent;
char *dname;
char dname[PATH_MAX];
xasprintf(&dname, "%s" SLASH "hosts", confbase);
snprintf(dname, sizeof dname, "%s" SLASH "hosts", confbase);
dir = opendir(dname);
if(!dir) {
logger(DEBUG_ALWAYS, LOG_ERR, "Could not open %s: %s", dname, strerror(errno));
free(dname);
return;
}

View file

@ -1,7 +1,7 @@
/*
script.c -- call an external script
Copyright (C) 1999-2005 Ivo Timmermans,
2000-2013 Guus Sliepen <guus@tinc-vpn.org>
2000-2015 Guus Sliepen <guus@tinc-vpn.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -28,10 +28,10 @@
bool execute_script(const char *name, char **envp) {
#ifdef HAVE_SYSTEM
char *scriptname;
char scriptname[PATH_MAX];
char *command;
xasprintf(&scriptname, "%s" SLASH "%s%s", confbase, name, scriptextension);
snprintf(scriptname, sizeof scriptname, "%s" SLASH "%s%s", confbase, name, scriptextension);
/* First check if there is a script */
@ -57,17 +57,13 @@ bool execute_script(const char *name, char **envp) {
break;
p = q;
}
if(!found) {
free(scriptname);
if(!found)
return true;
}
} else
#endif
if(access(scriptname, F_OK)) {
free(scriptname);
if(access(scriptname, F_OK))
return true;
}
logger(DEBUG_STATUS, LOG_INFO, "Executing script %s", name);
@ -86,7 +82,6 @@ bool execute_script(const char *name, char **envp) {
int status = system(command);
free(command);
free(scriptname);
/* Unset environment */

View file

@ -1,6 +1,6 @@
/*
sptps.c -- Simple Peer-to-Peer Security
Copyright (C) 2011-2014 Guus Sliepen <guus@tinc-vpn.org>,
Copyright (C) 2011-2015 Guus Sliepen <guus@tinc-vpn.org>,
2010 Brandon L. Black <blblack@gmail.com>
This program is free software; you can redistribute it and/or modify
@ -386,10 +386,12 @@ static bool sptps_check_seqno(sptps_t *s, uint32_t seqno, bool update_state) {
if (update_state)
s->farfuture++;
if(farfuture)
return error(s, EIO, "Packet from %s is %d seqs in the future, dropped (%u)\n", ((connection_t *)s->handle)->name, seqno - s->inseqno, s->farfuture);
return update_state ? error(s, EIO, "Packet is %d seqs in the future, dropped (%u)\n", seqno - s->inseqno, s->farfuture) : false;
// Unless we have seen lots of them, in which case we consider the others lost.
warning(s, "Lost %d packets from %s\n", seqno - s->inseqno, ((connection_t *)s->handle)->name);
if(update_state)
warning(s, "Lost %d packets\n", seqno - s->inseqno);
if (update_state) {
// Mark all packets in the replay window as being late.
memset(s->late, 255, s->replaywin);
@ -397,7 +399,7 @@ static bool sptps_check_seqno(sptps_t *s, uint32_t seqno, bool update_state) {
} else if (seqno < s->inseqno) {
// If the sequence number is farther in the past than the bitmap goes, or if the packet was already received, drop it.
if((s->inseqno >= s->replaywin * 8 && seqno < s->inseqno - s->replaywin * 8) || !(s->late[(seqno / 8) % s->replaywin] & (1 << seqno % 8)))
return error(s, EIO, "Received late or replayed packet from %s, seqno %d, last received %d\n", ((connection_t *)s->handle)->name, seqno, s->inseqno);
return update_state ? error(s, EIO, "Received late or replayed packet, seqno %d, last received %d\n", seqno, s->inseqno) : false;
} else if (update_state) {
// We missed some packets. Mark them in the bitmap as being late.
for(int i = s->inseqno; i < seqno; i++)

View file

@ -1,6 +1,6 @@
/*
tincctl.c -- Controlling a running tincd
Copyright (C) 2007-2014 Guus Sliepen <guus@tinc-vpn.org>
Copyright (C) 2007-2015 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
@ -134,6 +134,7 @@ static void usage(bool status) {
" subnets - all known subnets in the VPN\n"
" connections - all meta connections with ourself\n"
" [di]graph - graph of the VPN in dotty format\n"
" invitations - outstanding invitations\n"
" info NODE|SUBNET|ADDRESS Give information about a particular NODE, SUBNET or ADDRESS.\n"
" purge Purge unreachable nodes\n"
" debug N Set debug level\n"
@ -375,7 +376,7 @@ static FILE *ask_and_open(const char *filename, const char *what, const char *mo
static bool ed25519_keygen(bool ask) {
ecdsa_t *key;
FILE *f;
char *pubname, *privname;
char fname[PATH_MAX];
fprintf(stderr, "Generating Ed25519 keypair:\n");
@ -385,41 +386,42 @@ static bool ed25519_keygen(bool ask) {
} else
fprintf(stderr, "Done.\n");
xasprintf(&privname, "%s" SLASH "ed25519_key.priv", confbase);
f = ask_and_open(privname, "private Ed25519 key", "a", ask, 0600);
free(privname);
snprintf(fname, sizeof fname, "%s" SLASH "ed25519_key.priv", confbase);
f = ask_and_open(fname, "private Ed25519 key", "a", ask, 0600);
if(!f)
return false;
goto error;
if(!ecdsa_write_pem_private_key(key, f)) {
fprintf(stderr, "Error writing private key!\n");
ecdsa_free(key);
fclose(f);
return false;
goto error;
}
fclose(f);
if(name)
xasprintf(&pubname, "%s" SLASH "hosts" SLASH "%s", confbase, name);
snprintf(fname, sizeof fname, "%s" SLASH "hosts" SLASH "%s", confbase, name);
else
xasprintf(&pubname, "%s" SLASH "ed25519_key.pub", confbase);
snprintf(fname, sizeof fname, "%s" SLASH "ed25519_key.pub", confbase);
f = ask_and_open(pubname, "public Ed25519 key", "a", ask, 0666);
free(pubname);
f = ask_and_open(fname, "public Ed25519 key", "a", ask, 0666);
if(!f)
return false;
char *pubkey = ecdsa_get_base64_public_key(key);
fprintf(f, "Ed25519PublicKey = %s\n", pubkey);
free(pubkey);
fclose(f);
ecdsa_free(key);
return true;
error:
if(f)
fclose(f);
ecdsa_free(key);
return false;
}
#ifndef DISABLE_LEGACY
@ -430,7 +432,7 @@ static bool ed25519_keygen(bool ask) {
static bool rsa_keygen(int bits, bool ask) {
rsa_t *key;
FILE *f;
char *pubname, *privname;
char fname[PATH_MAX];
// Make sure the key size is a multiple of 8 bits.
bits &= ~0x7;
@ -449,44 +451,44 @@ static bool rsa_keygen(int bits, bool ask) {
} else
fprintf(stderr, "Done.\n");
xasprintf(&privname, "%s" SLASH "rsa_key.priv", confbase);
f = ask_and_open(privname, "private RSA key", "a", ask, 0600);
free(privname);
snprintf(fname, sizeof fname, "%s" SLASH "rsa_key.priv", confbase);
f = ask_and_open(fname, "private RSA key", "a", ask, 0600);
if(!f)
return false;
goto error;
if(!rsa_write_pem_private_key(key, f)) {
fprintf(stderr, "Error writing private key!\n");
fclose(f);
rsa_free(key);
return false;
goto error;
}
fclose(f);
if(name)
xasprintf(&pubname, "%s" SLASH "hosts" SLASH "%s", confbase, name);
snprintf(fname, sizeof fname, "%s" SLASH "hosts" SLASH "%s", confbase, name);
else
xasprintf(&pubname, "%s" SLASH "rsa_key.pub", confbase);
snprintf(fname, sizeof fname, "%s" SLASH "rsa_key.pub", confbase);
f = ask_and_open(pubname, "public RSA key", "a", ask, 0666);
free(pubname);
f = ask_and_open(fname, "public RSA key", "a", ask, 0666);
if(!f)
return false;
goto error;
if(!rsa_write_pem_public_key(key, f)) {
fprintf(stderr, "Error writing public key!\n");
fclose(f);
rsa_free(key);
return false;
goto error;
}
fclose(f);
rsa_free(key);
return true;
error:
if(f)
fclose(f);
rsa_free(key);
return false;
}
#endif
@ -943,6 +945,65 @@ static int cmd_reload(int argc, char *argv[]) {
}
static int dump_invitations(void) {
char dname[PATH_MAX];
snprintf(dname, sizeof dname, "%s" SLASH "invitations", confbase);
DIR *dir = opendir(dname);
if(!dir) {
if(errno == ENOENT) {
fprintf(stderr, "No outstanding invitations.\n");
return 0;
}
fprintf(stderr, "Cannot not read directory %s: %s\n", dname, strerror(errno));
return 1;
}
struct dirent *ent;
bool found = false;
while((ent = readdir(dir))) {
char buf[MAX_STRING_SIZE];
if(b64decode(ent->d_name, buf, 24) != 18)
continue;
char fname[PATH_MAX];
snprintf(fname, sizeof fname, "%s" SLASH "%s", dname, ent->d_name);
FILE *f = fopen(fname, "r");
if(!f) {
fprintf(stderr, "Cannot open %s: %s\n", fname, strerror(errno));
fclose(f);
continue;
}
buf[0] = 0;
if(!fgets(buf, sizeof buf, f)) {
fprintf(stderr, "Invalid invitation file %s", fname);
fclose(f);
continue;
}
fclose(f);
char *eol = buf + strlen(buf);
while(strchr("\t \r\n", *--eol))
*eol = 0;
if(strncmp(buf, "Name = ", 7) || !check_id(buf + 7)) {
fprintf(stderr, "Invalid invitation file %s", fname);
continue;
}
found = true;
printf("%s %s\n", ent->d_name, buf + 7);
}
closedir(dir);
if(!found)
fprintf(stderr, "No outstanding invitations.\n");
return 0;
}
static int cmd_dump(int argc, char *argv[]) {
bool only_reachable = false;
@ -963,6 +1024,9 @@ static int cmd_dump(int argc, char *argv[]) {
return 1;
}
if(!strcasecmp(argv[1], "invitations"))
return dump_invitations();
if(!connect_tincd(true))
return 1;
@ -1534,11 +1598,11 @@ static int cmd_config(int argc, char *argv[]) {
}
// Open the right configuration file.
char *filename;
char filename[PATH_MAX];
if(node)
xasprintf(&filename, "%s" SLASH "%s", hosts_dir, node);
snprintf(filename, sizeof filename, "%s" SLASH "%s", hosts_dir, node);
else
filename = tinc_conf;
snprintf(filename, sizeof filename, "%s", tinc_conf);
FILE *f = fopen(filename, "r");
if(!f) {
@ -1546,11 +1610,11 @@ static int cmd_config(int argc, char *argv[]) {
return 1;
}
char *tmpfile = NULL;
char tmpfile[PATH_MAX];
FILE *tf = NULL;
if(action >= -1) {
xasprintf(&tmpfile, "%s.config.tmp", filename);
snprintf(tmpfile, sizeof tmpfile, "%s.config.tmp", filename);
tf = fopen(tmpfile, "w");
if(!tf) {
fprintf(stderr, "Could not open temporary file %s: %s\n", tmpfile, strerror(errno));
@ -1736,11 +1800,11 @@ int check_port(char *name) {
for(int i = 0; i < 100; i++) {
int port = 0x1000 + (rand() & 0x7fff);
if(try_bind(port)) {
char *filename;
xasprintf(&filename, "%s" SLASH "hosts" SLASH "%s", confbase, name);
char filename[PATH_MAX];
snprintf(filename, sizeof filename, "%s" SLASH "hosts" SLASH "%s", confbase, name);
FILE *f = fopen(filename, "a");
free(filename);
if(!f) {
fprintf(stderr, "Could not open %s: %s\n", filename, strerror(errno));
fprintf(stderr, "Please change tinc's Port manually.\n");
return 0;
}
@ -1831,8 +1895,8 @@ static int cmd_init(int argc, char *argv[]) {
check_port(name);
#ifndef HAVE_MINGW
char *filename;
xasprintf(&filename, "%s" SLASH "tinc-up", confbase);
char filename[PATH_MAX];
snprintf(filename, sizeof filename, "%s" SLASH "tinc-up", confbase);
if(access(filename, F_OK)) {
FILE *f = fopenmask(filename, "w", 0777);
if(!f) {
@ -1942,12 +2006,12 @@ static int cmd_edit(int argc, char *argv[]) {
return 1;
}
char *filename = NULL;
char filename[PATH_MAX] = "";
if(strncmp(argv[1], "hosts" SLASH, 6)) {
for(int i = 0; conffiles[i]; i++) {
if(!strcmp(argv[1], conffiles[i])) {
xasprintf(&filename, "%s" SLASH "%s", confbase, argv[1]);
snprintf(filename, sizeof filename, "%s" SLASH "%s", confbase, argv[1]);
break;
}
}
@ -1955,8 +2019,8 @@ static int cmd_edit(int argc, char *argv[]) {
argv[1] += 6;
}
if(!filename) {
xasprintf(&filename, "%s" SLASH "%s", hosts_dir, argv[1]);
if(!*filename) {
snprintf(filename, sizeof filename, "%s" SLASH "%s", hosts_dir, argv[1]);
char *dash = strchr(argv[1], '-');
if(dash) {
*dash++ = 0;
@ -1974,6 +2038,7 @@ static int cmd_edit(int argc, char *argv[]) {
xasprintf(&command, "edit \"%s\"", filename);
#endif
int result = system(command);
free(command);
if(result)
return result;
@ -1985,8 +2050,8 @@ static int cmd_edit(int argc, char *argv[]) {
}
static int export(const char *name, FILE *out) {
char *filename;
xasprintf(&filename, "%s" SLASH "%s", hosts_dir, name);
char filename[PATH_MAX];
snprintf(filename, sizeof filename, "%s" SLASH "%s", hosts_dir, name);
FILE *in = fopen(filename, "r");
if(!in) {
fprintf(stderr, "Could not open configuration file %s: %s\n", filename, strerror(errno));
@ -2073,7 +2138,7 @@ static int cmd_import(int argc, char *argv[]) {
char buf[4096];
char name[4096];
char *filename = NULL;
char filename[PATH_MAX] = "";
int count = 0;
bool firstline = true;
@ -2089,8 +2154,7 @@ static int cmd_import(int argc, char *argv[]) {
if(out)
fclose(out);
free(filename);
xasprintf(&filename, "%s" SLASH "%s", hosts_dir, name);
snprintf(filename, sizeof filename, "%s" SLASH "%s", hosts_dir, name);
if(!force && !access(filename, F_OK)) {
fprintf(stderr, "Host configuration file %s already exists, skipping.\n", filename);
@ -2196,11 +2260,10 @@ static int cmd_network(int argc, char *argv[]) {
continue;
}
char *fname;
xasprintf(&fname, "%s/%s/tinc.conf", confdir, ent->d_name);
char fname[PATH_MAX];
snprintf(fname, sizeof fname, "%s/%s/tinc.conf", confdir, ent->d_name);
if(!access(fname, R_OK))
printf("%s\n", ent->d_name);
free(fname);
}
closedir(dir);
@ -2227,6 +2290,7 @@ static const struct {
{"restart", cmd_restart},
{"reload", cmd_reload},
{"dump", cmd_dump},
{"list", cmd_dump},
{"purge", cmd_purge},
{"debug", cmd_debug},
{"retry", cmd_retry},
@ -2494,7 +2558,7 @@ int main(int argc, char *argv[]) {
if(!parse_options(argc, argv))
return 1;
make_names();
make_names(false);
xasprintf(&tinc_conf, "%s" SLASH "tinc.conf", confbase);
xasprintf(&hosts_dir, "%s" SLASH "hosts", confbase);

View file

@ -1,7 +1,7 @@
/*
tincd.c -- the main file for tincd
Copyright (C) 1998-2005 Ivo Timmermans
2000-2014 Guus Sliepen <guus@tinc-vpn.org>
2000-2015 Guus Sliepen <guus@tinc-vpn.org>
2008 Max Rijevski <maksuf@gmail.com>
2009 Michael Tokarev <mjt@tls.msk.ru>
2010 Julien Muchembled <jm@jmuchemb.eu>
@ -339,7 +339,7 @@ int main(int argc, char **argv) {
if(!parse_options(argc, argv))
return 1;
make_names();
make_names(true);
if(show_version) {
printf("%s version %s (built %s %s, protocol %d.%d)\n", PACKAGE,