Allow connections via UNIX sockets.
This is mainly useful for control connections. The client must still present the control cookie from the PID file.
This commit is contained in:
parent
2c14123062
commit
94587264bd
6 changed files with 108 additions and 0 deletions
|
@ -27,6 +27,7 @@ char *netname = NULL;
|
||||||
char *confdir = NULL; /* base configuration directory */
|
char *confdir = NULL; /* base configuration directory */
|
||||||
char *confbase = NULL; /* base configuration directory for this instance of tinc */
|
char *confbase = NULL; /* base configuration directory for this instance of tinc */
|
||||||
char *identname = NULL; /* program name for syslog */
|
char *identname = NULL; /* program name for syslog */
|
||||||
|
char *unixsocketname = NULL; /* UNIX socket location */
|
||||||
char *logfilename = NULL; /* log file location */
|
char *logfilename = NULL; /* log file location */
|
||||||
char *pidfilename = NULL;
|
char *pidfilename = NULL;
|
||||||
char *program_name = NULL;
|
char *program_name = NULL;
|
||||||
|
@ -73,6 +74,9 @@ void make_names(void) {
|
||||||
if(!pidfilename)
|
if(!pidfilename)
|
||||||
xasprintf(&pidfilename, LOCALSTATEDIR SLASH "run" SLASH "%s.pid", identname);
|
xasprintf(&pidfilename, LOCALSTATEDIR SLASH "run" SLASH "%s.pid", identname);
|
||||||
|
|
||||||
|
if(!unixsocketname)
|
||||||
|
xasprintf(&unixsocketname, LOCALSTATEDIR SLASH "run" SLASH "%s.socket", identname);
|
||||||
|
|
||||||
if(netname) {
|
if(netname) {
|
||||||
if(!confbase)
|
if(!confbase)
|
||||||
xasprintf(&confbase, CONFDIR SLASH "tinc" SLASH "%s", netname);
|
xasprintf(&confbase, CONFDIR SLASH "tinc" SLASH "%s", netname);
|
||||||
|
@ -87,6 +91,7 @@ void make_names(void) {
|
||||||
void free_names(void) {
|
void free_names(void) {
|
||||||
free(identname);
|
free(identname);
|
||||||
free(netname);
|
free(netname);
|
||||||
|
free(unixsocketname);
|
||||||
free(pidfilename);
|
free(pidfilename);
|
||||||
free(logfilename);
|
free(logfilename);
|
||||||
free(confbase);
|
free(confbase);
|
||||||
|
|
|
@ -25,6 +25,7 @@ extern char *confdir;
|
||||||
extern char *confbase;
|
extern char *confbase;
|
||||||
extern char *netname;
|
extern char *netname;
|
||||||
extern char *identname;
|
extern char *identname;
|
||||||
|
extern char *unixsocketname;
|
||||||
extern char *logfilename;
|
extern char *logfilename;
|
||||||
extern char *pidfilename;
|
extern char *pidfilename;
|
||||||
extern char *program_name;
|
extern char *program_name;
|
||||||
|
|
|
@ -128,6 +128,7 @@ extern bool localdiscovery;
|
||||||
|
|
||||||
extern listen_socket_t listen_socket[MAXSOCKETS];
|
extern listen_socket_t listen_socket[MAXSOCKETS];
|
||||||
extern int listen_sockets;
|
extern int listen_sockets;
|
||||||
|
extern io_t unix_socket;
|
||||||
extern int keylifetime;
|
extern int keylifetime;
|
||||||
extern int udp_rcvbuf;
|
extern int udp_rcvbuf;
|
||||||
extern int udp_sndbuf;
|
extern int udp_sndbuf;
|
||||||
|
@ -164,6 +165,7 @@ extern void handle_incoming_vpn_data(void *, int);
|
||||||
extern void finish_connecting(struct connection_t *);
|
extern void finish_connecting(struct connection_t *);
|
||||||
extern bool do_outgoing_connection(struct outgoing_t *);
|
extern bool do_outgoing_connection(struct outgoing_t *);
|
||||||
extern void handle_new_meta_connection(void *, int);
|
extern void handle_new_meta_connection(void *, int);
|
||||||
|
extern void handle_new_unix_connection(void *, int);
|
||||||
extern int setup_listen_socket(const sockaddr_t *);
|
extern int setup_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 char *data, size_t len);
|
extern bool send_sptps_data(void *handle, uint8_t type, const char *data, size_t len);
|
||||||
|
|
|
@ -808,6 +808,37 @@ static bool setup_myself(void) {
|
||||||
|
|
||||||
/* Open sockets */
|
/* Open sockets */
|
||||||
|
|
||||||
|
#ifndef HAVE_MINGW
|
||||||
|
int unix_fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
|
if(unix_fd < 0) {
|
||||||
|
logger(DEBUG_ALWAYS, LOG_ERR, "Could not create UNIX socket: %s", sockstrerror(errno));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_un sa;
|
||||||
|
sa.sun_family = AF_UNIX;
|
||||||
|
strncpy(sa.sun_path, unixsocketname, sizeof sa.sun_path);
|
||||||
|
|
||||||
|
if(connect(unix_fd, (struct sockaddr *)&sa, sizeof sa) >= 0) {
|
||||||
|
logger(DEBUG_ALWAYS, LOG_ERR, "UNIX socket %s is still in use!", unixsocketname);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
unlink(unixsocketname);
|
||||||
|
|
||||||
|
if(bind(unix_fd, (struct sockaddr *)&sa, sizeof sa) < 0) {
|
||||||
|
logger(DEBUG_ALWAYS, LOG_ERR, "Could not bind UNIX socket to %s: %s", unixsocketname, sockstrerror(errno));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(listen(unix_fd, 3) < 0) {
|
||||||
|
logger(DEBUG_ALWAYS, LOG_ERR, "Could not listen on UNIX socket %s: %s", unixsocketname, sockstrerror(errno));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
io_add(&unix_socket, handle_new_unix_connection, &unix_socket, unix_fd, IO_READ);
|
||||||
|
#endif
|
||||||
|
|
||||||
if(!do_detach && getenv("LISTEN_FDS")) {
|
if(!do_detach && getenv("LISTEN_FDS")) {
|
||||||
sockaddr_t sa;
|
sockaddr_t sa;
|
||||||
socklen_t salen;
|
socklen_t salen;
|
||||||
|
@ -992,6 +1023,11 @@ void close_network_connections(void) {
|
||||||
close(listen_socket[i].udp.fd);
|
close(listen_socket[i].udp.fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef HAVE_MINGW
|
||||||
|
io_del(&unix_socket);
|
||||||
|
close(unix_socket.fd);
|
||||||
|
#endif
|
||||||
|
|
||||||
char *envp[5];
|
char *envp[5];
|
||||||
xasprintf(&envp[0], "NETNAME=%s", netname ? : "");
|
xasprintf(&envp[0], "NETNAME=%s", netname ? : "");
|
||||||
xasprintf(&envp[1], "DEVICE=%s", device ? : "");
|
xasprintf(&envp[1], "DEVICE=%s", device ? : "");
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
|
#include "control_common.h"
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "meta.h"
|
#include "meta.h"
|
||||||
|
@ -47,6 +48,9 @@ int udp_sndbuf = 0;
|
||||||
|
|
||||||
listen_socket_t listen_socket[MAXSOCKETS];
|
listen_socket_t listen_socket[MAXSOCKETS];
|
||||||
int listen_sockets;
|
int listen_sockets;
|
||||||
|
#ifndef HAVE_MINGW
|
||||||
|
io_t unix_socket;
|
||||||
|
#endif
|
||||||
list_t *outgoing_list = NULL;
|
list_t *outgoing_list = NULL;
|
||||||
|
|
||||||
/* Setup sockets */
|
/* Setup sockets */
|
||||||
|
@ -562,6 +566,45 @@ void handle_new_meta_connection(void *data, int flags) {
|
||||||
send_id(c);
|
send_id(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef HAVE_MINGW
|
||||||
|
/*
|
||||||
|
accept a new UNIX socket connection
|
||||||
|
*/
|
||||||
|
void handle_new_unix_connection(void *data, int flags) {
|
||||||
|
io_t *io = data;
|
||||||
|
connection_t *c;
|
||||||
|
sockaddr_t sa;
|
||||||
|
int fd;
|
||||||
|
socklen_t len = sizeof sa;
|
||||||
|
|
||||||
|
fd = accept(io->fd, &sa.sa, &len);
|
||||||
|
|
||||||
|
if(fd < 0) {
|
||||||
|
logger(DEBUG_ALWAYS, LOG_ERR, "Accepting a new connection failed: %s", sockstrerror(sockerrno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sockaddrunmap(&sa);
|
||||||
|
|
||||||
|
c = new_connection();
|
||||||
|
c->name = xstrdup("<control>");
|
||||||
|
c->address = sa;
|
||||||
|
c->hostname = xstrdup("localhost port unix");
|
||||||
|
c->socket = fd;
|
||||||
|
c->last_ping_time = time(NULL);
|
||||||
|
|
||||||
|
logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Connection from %s", c->hostname);
|
||||||
|
|
||||||
|
io_add(&c->io, handle_meta_io, c, c->socket, IO_READ);
|
||||||
|
|
||||||
|
connection_add(c);
|
||||||
|
|
||||||
|
c->allow_request = ID;
|
||||||
|
|
||||||
|
send_id(c);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void free_outgoing(outgoing_t *outgoing) {
|
static void free_outgoing(outgoing_t *outgoing) {
|
||||||
timeout_del(&outgoing->ev);
|
timeout_del(&outgoing->ev);
|
||||||
|
|
||||||
|
|
|
@ -666,6 +666,26 @@ static bool connect_tincd(bool verbose) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_MINGW
|
||||||
|
struct sockaddr_un sa;
|
||||||
|
sa.sun_family = AF_UNIX;
|
||||||
|
strncpy(sa.sun_path, unixsocketname, sizeof sa.sun_path);
|
||||||
|
|
||||||
|
fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
|
if(fd < 0) {
|
||||||
|
if(verbose)
|
||||||
|
fprintf(stderr, "Cannot create UNIX socket: %s\n", sockstrerror(sockerrno));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(connect(fd, (struct sockaddr *)&sa, sizeof sa) < 0) {
|
||||||
|
if(verbose)
|
||||||
|
fprintf(stderr, "Cannot connect to UNIX socket %s: %s\n", unixsocketname, sockstrerror(sockerrno));
|
||||||
|
close(fd);
|
||||||
|
fd = -1;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#else
|
||||||
struct addrinfo hints = {
|
struct addrinfo hints = {
|
||||||
.ai_family = AF_UNSPEC,
|
.ai_family = AF_UNSPEC,
|
||||||
.ai_socktype = SOCK_STREAM,
|
.ai_socktype = SOCK_STREAM,
|
||||||
|
@ -706,6 +726,7 @@ static bool connect_tincd(bool verbose) {
|
||||||
}
|
}
|
||||||
|
|
||||||
freeaddrinfo(res);
|
freeaddrinfo(res);
|
||||||
|
#endif
|
||||||
|
|
||||||
char data[4096];
|
char data[4096];
|
||||||
int version;
|
int version;
|
||||||
|
|
Loading…
Reference in a new issue