fixed conflict in src/sptps.c
This commit is contained in:
commit
26c7ff7fdd
15 changed files with 237 additions and 166 deletions
35
src/conf.c
35
src/conf.c
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
16
src/logger.c
16
src/logger.c
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
37
src/names.c
37
src/names.c
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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__ */
|
||||
|
|
|
|||
10
src/net.c
10
src/net.c
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
15
src/script.c
15
src/script.c
|
|
@ -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 */
|
||||
|
||||
|
|
|
|||
10
src/sptps.c
10
src/sptps.c
|
|
@ -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++)
|
||||
|
|
|
|||
170
src/tincctl.c
170
src/tincctl.c
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue