cipher.h \
conf.c conf.h \
connection.c connection.h \
- control.c control.h \
- control_common.h \
crypto.h \
digest.h \
dropin.c dropin.h \
#include "list.h"
#include "cipher.h"
#include "conf.h"
-#include "control_common.h"
+#include "connection.h"
#include "list.h"
#include "logger.h"
#include "rsa.h"
void connection_del(connection_t *c) {
list_delete(connection_list, c);
}
-
-bool dump_connections(connection_t *cdump) {
- for list_each(connection_t, c, connection_list) {
- send_request(cdump, "%d %d %s %s %x %d %x",
- CONTROL, REQ_DUMP_CONNECTIONS,
- c->name, c->hostname, c->options, c->socket,
- bitfield_to_int(&c->status, sizeof c->status));
- }
-
- return send_request(cdump, "%d %d", CONTROL, REQ_DUMP_CONNECTIONS);
-}
extern void free_connection(connection_t *);
extern void connection_add(connection_t *);
extern void connection_del(connection_t *);
-extern bool dump_connections(struct connection_t *);
#endif /* __TINC_CONNECTION_H__ */
+++ /dev/null
-/*
- control.c -- Control socket handling.
- Copyright (C) 2013 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
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-*/
-
-#include "system.h"
-#include "crypto.h"
-#include "conf.h"
-#include "control.h"
-#include "control_common.h"
-#include "graph.h"
-#include "logger.h"
-#include "meta.h"
-#include "names.h"
-#include "net.h"
-#include "netutl.h"
-#include "protocol.h"
-#include "route.h"
-#include "utils.h"
-#include "xalloc.h"
-
-char controlcookie[65];
-
-static bool control_return(connection_t *c, int type, int error) {
- return send_request(c, "%d %d %d", CONTROL, type, error);
-}
-
-static bool control_ok(connection_t *c, int type) {
- return control_return(c, type, 0);
-}
-
-bool control_h(connection_t *c, const char *request) {
- int type;
-
- if(!c->status.control || c->allow_request != CONTROL) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Unauthorized control request from %s (%s)", c->name, c->hostname);
- return false;
- }
-
- if(sscanf(request, "%*d %d", &type) != 1) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "CONTROL", c->name, c->hostname);
- return false;
- }
-
- switch (type) {
- case REQ_STOP:
- event_exit();
- return control_ok(c, REQ_STOP);
-
- case REQ_DUMP_NODES:
- return dump_nodes(c);
-
- case REQ_DUMP_EDGES:
- return dump_edges(c);
-
- case REQ_DUMP_CONNECTIONS:
- return dump_connections(c);
-
- case REQ_PURGE:
- purge();
- return control_ok(c, REQ_PURGE);
-
- case REQ_SET_DEBUG: {
- int new_level;
- if(sscanf(request, "%*d %*d %d", &new_level) != 1)
- return false;
- send_request(c, "%d %d %d", CONTROL, REQ_SET_DEBUG, debug_level);
- if(new_level >= 0)
- debug_level = new_level;
- return true;
- }
-
- case REQ_RETRY:
- retry();
- return control_ok(c, REQ_RETRY);
-
- case REQ_RELOAD:
- logger(DEBUG_ALWAYS, LOG_NOTICE, "Got '%s' command", "reload");
- int result = reload_configuration();
- return control_return(c, REQ_RELOAD, result);
-
- case REQ_DISCONNECT: {
- char name[MAX_STRING_SIZE];
- bool found = false;
-
- if(sscanf(request, "%*d %*d " MAX_STRING, name) != 1)
- return control_return(c, REQ_DISCONNECT, -1);
-
- for list_each(connection_t, other, connection_list) {
- if(strcmp(other->name, name))
- continue;
- terminate_connection(other, other->status.active);
- found = true;
- }
-
- return control_return(c, REQ_DISCONNECT, found ? 0 : -2);
- }
-
- case REQ_DUMP_TRAFFIC:
- return dump_traffic(c);
-
- case REQ_PCAP:
- sscanf(request, "%*d %*d %d", &c->outmaclength);
- c->status.pcap = true;
- pcap = true;
- return true;
-
- case REQ_LOG:
- sscanf(request, "%*d %*d %d", &c->outcompression);
- c->status.log = true;
- logcontrol = true;
- return true;
-
- default:
- return send_request(c, "%d %d", CONTROL, REQ_INVALID);
- }
-}
-
-bool init_control(void) {
- randomize(controlcookie, sizeof controlcookie / 2);
- bin2hex(controlcookie, controlcookie, sizeof controlcookie / 2);
-
- mode_t mask = umask(0);
- umask(mask | 077);
- FILE *f = fopen(pidfilename, "w");
- umask(mask);
-
- if(!f) {
- logger(DEBUG_ALWAYS, LOG_ERR, "Cannot write control socket cookie file %s: %s", pidfilename, strerror(errno));
- return false;
- }
-
- // Get the address and port of the first listening socket
-
- char *localhost = NULL;
- sockaddr_t sa;
- socklen_t len = sizeof sa;
-
- // Make sure we have a valid address, and map 0.0.0.0 and :: to 127.0.0.1 and ::1.
-
- if(getsockname(listen_socket[0].tcp.fd, (struct sockaddr *)&sa, &len)) {
- xasprintf(&localhost, "127.0.0.1 port %s", myport);
- } else {
- if(sa.sa.sa_family == AF_INET) {
- if(sa.in.sin_addr.s_addr == 0)
- sa.in.sin_addr.s_addr = htonl(0x7f000001);
- } else if(sa.sa.sa_family == AF_INET6) {
- static const uint8_t zero[16] = {0};
- if(!memcmp(sa.in6.sin6_addr.s6_addr, zero, sizeof zero))
- sa.in6.sin6_addr.s6_addr[15] = 1;
- }
-
- localhost = sockaddr2hostname(&sa);
- }
-
- fprintf(f, "%d %s %s\n", (int)getpid(), controlcookie, localhost);
-
- free(localhost);
- fclose(f);
-
-#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_un;
- sa_un.sun_family = AF_UNIX;
- strncpy(sa_un.sun_path, unixsocketname, sizeof sa_un.sun_path);
-
- if(connect(unix_fd, (struct sockaddr *)&sa_un, sizeof sa_un) >= 0) {
- logger(DEBUG_ALWAYS, LOG_ERR, "UNIX socket %s is still in use!", unixsocketname);
- return false;
- }
-
- unlink(unixsocketname);
-
- umask(mask | 077);
- int result = bind(unix_fd, (struct sockaddr *)&sa_un, sizeof sa_un);
- umask(mask);
-
- if(result < 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
-
- return true;
-}
-
-void exit_control(void) {
-#ifndef HAVE_MINGW
- unlink(unixsocketname);
- io_del(&unix_socket);
- close(unix_socket.fd);
-#endif
-
- unlink(pidfilename);
-}
+++ /dev/null
-/*
- control.h -- header for control.c.
- Copyright (C) 2007 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
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-*/
-
-#ifndef __TINC_CONTROL_H__
-#define __TINC_CONTROL_H__
-
-extern bool init_control();
-extern void exit_control();
-extern char controlcookie[];
-
-#endif
+++ /dev/null
-/*
- control_protocol.h -- control socket protocol.
- Copyright (C) 2007 Scott Lamb <slamb@slamb.org>
- 2009-2012 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
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-*/
-
-#ifndef __TINC_CONTROL_PROTOCOL_H__
-#define __TINC_CONTROL_PROTOCOL_H__
-
-#include "protocol.h"
-
-enum request_type {
- REQ_INVALID = -1,
- REQ_STOP = 0,
- REQ_RELOAD,
- REQ_RESTART,
- REQ_DUMP_NODES,
- REQ_DUMP_EDGES,
- REQ_DUMP_SUBNETS,
- REQ_DUMP_CONNECTIONS,
- REQ_DUMP_GRAPH,
- REQ_PURGE,
- REQ_SET_DEBUG,
- REQ_RETRY,
- REQ_CONNECT,
- REQ_DISCONNECT,
- REQ_DUMP_TRAFFIC,
- REQ_PCAP,
- REQ_LOG,
-};
-
-#define TINC_CTL_VERSION_CURRENT 0
-
-#endif
#include "system.h"
#include "splay_tree.h"
-#include "control_common.h"
#include "edge.h"
#include "logger.h"
#include "netutl.h"
return splay_search(from->edge_tree, &v);
}
-
-bool dump_edges(connection_t *c) {
- for splay_each(node_t, n, node_tree) {
- for splay_each(edge_t, e, n->edge_tree) {
- char *address = sockaddr2hostname(&e->address);
- send_request(c, "%d %d %s %s %s %x %d",
- CONTROL, REQ_DUMP_EDGES,
- e->from->name, e->to->name, address,
- e->options, e->weight);
- free(address);
- }
- }
-
- return send_request(c, "%d %d", CONTROL, REQ_DUMP_EDGES);
-}
extern void edge_add(edge_t *);
extern void edge_del(edge_t *);
extern edge_t *lookup_edge(struct node_t *, struct node_t *);
-extern bool dump_edges(struct connection_t *);
#endif /* __TINC_EDGE_H__ */
#define __TINC_GRAPH_H__
extern void graph(void);
-extern void dump_graph(void);
#endif /* __TINC_GRAPH_H__ */
if(!setup_myself())
return false;
- if(!init_control())
- return false;
-
return true;
}
#include "names.h"
#include "logger.h"
#include "connection.h"
-#include "control_common.h"
#include "sptps.h"
debug_t debug_level = DEBUG_NOTHING;
static HANDLE loghandle = NULL;
#endif
static const char *logident = NULL;
-bool logcontrol = false;
-
static void real_logger(int level, int priority, const char *message) {
char timestr[32] = "";
if(suppress)
return;
- if(!logcontrol && (level > debug_level || logmode == LOGMODE_NULL))
+ if(level > debug_level || logmode == LOGMODE_NULL)
return;
if(level <= debug_level) {
break;
}
}
-
- if(logcontrol) {
- suppress = true;
- logcontrol = false;
- for list_each(connection_t, c, connection_list) {
- if(!c->status.log)
- continue;
- logcontrol = true;
- if(level > (c->outcompression >= 0 ? c->outcompression : debug_level))
- continue;
- int len = strlen(message);
- if(send_request(c, "%d %d %d", CONTROL, REQ_LOG, len))
- send_meta(c, message, len);
- }
- suppress = false;
- }
}
void logger(int level, int priority, const char *format, ...) {
*/
static void timeout_handler(void *data) {
for list_each(connection_t, c, connection_list) {
- if(c->status.control)
- continue;
-
if(c->last_ping_time + pingtimeout <= now.tv_sec) {
if(c->status.active) {
if(c->status.pinged) {
/* Count number of active connections */
int nc = 0;
for list_each(connection_t, c, connection_list) {
- if(c->status.active && !c->status.control)
+ if(c->status.active)
nc++;
}
int i = 0;
for list_each(connection_t, c, connection_list) {
- if(!c->status.active || c->status.control)
+ if(!c->status.active)
continue;
if(i++ != r)
/* Close connections to hosts that have a changed or deleted host config file */
for list_each(connection_t, c, connection_list) {
- if(c->status.control)
- continue;
-
xasprintf(&fname, "%s" SLASH "hosts" SLASH "%s", confbase, c->name);
struct stat s;
if(stat(fname, &s) || s.st_mtime > last_config_check) {
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;
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);
#include "cipher.h"
#include "conf.h"
#include "connection.h"
-#include "control.h"
#include "digest.h"
#include "ecdsa.h"
#include "graph.h"
if(!setup_myself())
return false;
- if(!init_control())
- return false;
-
return true;
}
for(list_node_t *node = connection_list->head, *next; node; node = next) {
next = node->next;
connection_t *c = node->data;
- /* Keep control connections open until the end, so they know when we really terminated */
- if(c->status.control)
- c->socket = -1;
c->outgoing = NULL;
terminate_connection(c, false);
}
if(myport) free(myport);
- exit_control();
-
return;
}
#include "conf.h"
#include "connection.h"
-#include "control_common.h"
#include "list.h"
#include "logger.h"
#include "meta.h"
listen_socket_t listen_socket[MAXSOCKETS];
int listen_sockets;
-#ifndef HAVE_MINGW
-io_t unix_socket;
-#endif
list_t *outgoing_list = NULL;
/* Setup sockets */
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 = now.tv_sec;
-
- 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);
#include "system.h"
-#include "control_common.h"
#include "hash.h"
#include "logger.h"
#include "net.h"
logger(DEBUG_PROTOCOL, LOG_DEBUG, "UDP address of %s set to %s", n->name, n->hostname);
}
}
-
-bool dump_nodes(connection_t *c) {
- for splay_each(node_t, n, node_tree)
- send_request(c, "%d %d %s %s %d %d %d %d %x %x %s %s %d %hd %hd %hd %ld", CONTROL, REQ_DUMP_NODES,
- n->name, n->hostname ?: "unknown port unknown", cipher_get_nid(n->outcipher),
- digest_get_nid(n->outdigest), (int)digest_length(n->outdigest), n->outcompression,
- n->options, bitfield_to_int(&n->status, sizeof n->status), n->nexthop ? n->nexthop->name : "-",
- n->via ? n->via->name ?: "-" : "-", n->distance, n->mtu, n->minmtu, n->maxmtu, (long)n->last_state_change);
-
- return send_request(c, "%d %d", CONTROL, REQ_DUMP_NODES);
-}
-
-bool dump_traffic(connection_t *c) {
- for splay_each(node_t, n, node_tree)
- send_request(c, "%d %d %s %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64, CONTROL, REQ_DUMP_TRAFFIC,
- n->name, n->in_packets, n->in_bytes, n->out_packets, n->out_bytes);
-
- return send_request(c, "%d %d", CONTROL, REQ_DUMP_TRAFFIC);
-}
extern void node_del(node_t *);
extern node_t *lookup_node(char *);
extern node_t *lookup_node_udp(const sockaddr_t *);
-extern bool dump_nodes(struct connection_t *);
-extern bool dump_traffic(struct connection_t *);
extern void update_node_udp(node_t *, const sockaddr_t *);
#endif /* __TINC_NODE_H__ */
#include "conf.h"
#include "connection.h"
-#include "control.h"
#include "edge.h"
#include "event.h"
#include "logger.h"
ping_h, pong_h,
NULL, NULL, //add_subnet_h, del_subnet_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, NULL, //control_h,
};
/* Request names */
extern bool req_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 control_h(struct connection_t *, const char *);
#endif /* __TINC_PROTOCOL_H__ */
#include "conf.h"
#include "connection.h"
-#include "control.h"
-#include "control_common.h"
#include "cipher.h"
#include "crypto.h"
#include "digest.h"
return false;
}
- /* Check if this is a control connection */
-
- if(name[0] == '^' && !strcmp(name + 1, controlcookie)) {
- c->status.control = true;
- c->allow_request = CONTROL;
- c->last_ping_time = now.tv_sec + 3600;
-
- free(c->name);
- c->name = xstrdup("<control>");
-
- return send_request(c, "%d %d %d", ACK, TINC_CTL_VERSION_CURRENT, getpid());
- }
+ /* Check if this is an invitation */
if(name[0] == '?') {
if(!invitation_key) {
#include <getopt.h>
#include "conf.h"
-#include "control.h"
#include "crypto.h"
#include "logger.h"
#include "names.h"