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 *confbase = NULL; /* base configuration directory for this instance of tinc */
|
||||
char *identname = NULL; /* program name for syslog */
|
||||
char *unixsocketname = NULL; /* UNIX socket location */
|
||||
char *logfilename = NULL; /* log file location */
|
||||
char *pidfilename = NULL;
|
||||
char *program_name = NULL;
|
||||
|
@ -73,6 +74,9 @@ void make_names(void) {
|
|||
if(!pidfilename)
|
||||
xasprintf(&pidfilename, LOCALSTATEDIR SLASH "run" SLASH "%s.pid", identname);
|
||||
|
||||
if(!unixsocketname)
|
||||
xasprintf(&unixsocketname, LOCALSTATEDIR SLASH "run" SLASH "%s.socket", identname);
|
||||
|
||||
if(netname) {
|
||||
if(!confbase)
|
||||
xasprintf(&confbase, CONFDIR SLASH "tinc" SLASH "%s", netname);
|
||||
|
@ -87,6 +91,7 @@ void make_names(void) {
|
|||
void free_names(void) {
|
||||
free(identname);
|
||||
free(netname);
|
||||
free(unixsocketname);
|
||||
free(pidfilename);
|
||||
free(logfilename);
|
||||
free(confbase);
|
||||
|
|
|
@ -25,6 +25,7 @@ extern char *confdir;
|
|||
extern char *confbase;
|
||||
extern char *netname;
|
||||
extern char *identname;
|
||||
extern char *unixsocketname;
|
||||
extern char *logfilename;
|
||||
extern char *pidfilename;
|
||||
extern char *program_name;
|
||||
|
|
|
@ -128,6 +128,7 @@ extern bool localdiscovery;
|
|||
|
||||
extern listen_socket_t listen_socket[MAXSOCKETS];
|
||||
extern int listen_sockets;
|
||||
extern io_t unix_socket;
|
||||
extern int keylifetime;
|
||||
extern int udp_rcvbuf;
|
||||
extern int udp_sndbuf;
|
||||
|
@ -164,6 +165,7 @@ extern void handle_incoming_vpn_data(void *, int);
|
|||
extern void finish_connecting(struct connection_t *);
|
||||
extern bool do_outgoing_connection(struct outgoing_t *);
|
||||
extern void handle_new_meta_connection(void *, int);
|
||||
extern void handle_new_unix_connection(void *, int);
|
||||
extern int setup_listen_socket(const sockaddr_t *);
|
||||
extern int setup_vpn_in_socket(const sockaddr_t *);
|
||||
extern bool send_sptps_data(void *handle, uint8_t type, const char *data, size_t len);
|
||||
|
|
|
@ -808,6 +808,37 @@ static bool setup_myself(void) {
|
|||
|
||||
/* 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")) {
|
||||
sockaddr_t sa;
|
||||
socklen_t salen;
|
||||
|
@ -992,6 +1023,11 @@ void close_network_connections(void) {
|
|||
close(listen_socket[i].udp.fd);
|
||||
}
|
||||
|
||||
#ifndef HAVE_MINGW
|
||||
io_del(&unix_socket);
|
||||
close(unix_socket.fd);
|
||||
#endif
|
||||
|
||||
char *envp[5];
|
||||
xasprintf(&envp[0], "NETNAME=%s", netname ? : "");
|
||||
xasprintf(&envp[1], "DEVICE=%s", device ? : "");
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include "conf.h"
|
||||
#include "connection.h"
|
||||
#include "control_common.h"
|
||||
#include "list.h"
|
||||
#include "logger.h"
|
||||
#include "meta.h"
|
||||
|
@ -47,6 +48,9 @@ int udp_sndbuf = 0;
|
|||
|
||||
listen_socket_t listen_socket[MAXSOCKETS];
|
||||
int listen_sockets;
|
||||
#ifndef HAVE_MINGW
|
||||
io_t unix_socket;
|
||||
#endif
|
||||
list_t *outgoing_list = NULL;
|
||||
|
||||
/* Setup sockets */
|
||||
|
@ -562,6 +566,45 @@ void handle_new_meta_connection(void *data, int flags) {
|
|||
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) {
|
||||
timeout_del(&outgoing->ev);
|
||||
|
||||
|
|
|
@ -666,6 +666,26 @@ static bool connect_tincd(bool verbose) {
|
|||
}
|
||||
#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 = {
|
||||
.ai_family = AF_UNSPEC,
|
||||
.ai_socktype = SOCK_STREAM,
|
||||
|
@ -706,6 +726,7 @@ static bool connect_tincd(bool verbose) {
|
|||
}
|
||||
|
||||
freeaddrinfo(res);
|
||||
#endif
|
||||
|
||||
char data[4096];
|
||||
int version;
|
||||
|
|
Loading…
Reference in a new issue