diff --git a/src/control.c b/src/control.c index e3901a6d..b8e5204b 100644 --- a/src/control.c +++ b/src/control.c @@ -92,6 +92,27 @@ bool control_h(connection_t *c, char *request) { int result = reload_configuration(); return control_return(c, REQ_RELOAD, result); + case REQ_DISCONNECT: { + char name[MAX_STRING_SIZE]; + connection_t *other; + splay_node_t *node, *next; + bool found = false; + + if(sscanf(request, "%*d %*d " MAX_STRING, name) != 1) + return control_return(c, REQ_DISCONNECT, -1); + + for(node = connection_tree->head; node; node = next) { + next = node->next; + other = node->data; + if(strcmp(other->name, name)) + continue; + terminate_connection(other, other->status.active); + found = true; + } + + return control_return(c, REQ_DISCONNECT, found ? 0 : -2); + } + default: return send_request(c, "%d %d", CONTROL, REQ_INVALID); } diff --git a/src/control_common.h b/src/control_common.h index c89f9de7..99cf8aff 100644 --- a/src/control_common.h +++ b/src/control_common.h @@ -35,6 +35,8 @@ enum request_type { REQ_PURGE, REQ_SET_DEBUG, REQ_RETRY, + REQ_CONNECT, + REQ_DISCONNECT, }; #define TINC_CTL_VERSION_CURRENT 0 diff --git a/src/tincctl.c b/src/tincctl.c index ede186ad..632e7ac6 100644 --- a/src/tincctl.c +++ b/src/tincctl.c @@ -92,6 +92,7 @@ static void usage(bool status) { " debug N Set debug level\n" " retry Retry all outgoing connections\n" " reload Partial reload of configuration\n" + " disconnect NODE Close meta connection with NODE\n" "\n"); printf("Report bugs to tinc@tinc-vpn.org.\n"); } @@ -595,6 +596,36 @@ int main(int argc, char *argv[], char *envp[]) { return 0; } + if(!strcasecmp(argv[optind], "connect")) { + if(argc != optind + 2) { + fprintf(stderr, "Invalid arguments.\n"); + return 1; + } + char *name = argv[optind + 1]; + + sendline(fd, "%d %d %s", CONTROL, REQ_CONNECT, name); + if(!recvline(fd, line, sizeof line) || sscanf(line, "%d %d %d", &code, &req, &result) != 3 || code != CONTROL || req != REQ_CONNECT || result) { + fprintf(stderr, "Could not connect to %s\n", name); + return 1; + } + return 0; + } + + if(!strcasecmp(argv[optind], "disconnect")) { + if(argc != optind + 2) { + fprintf(stderr, "Invalid arguments.\n"); + return 1; + } + char *name = argv[optind + 1]; + + sendline(fd, "%d %d %s", CONTROL, REQ_DISCONNECT, name); + if(!recvline(fd, line, sizeof line) || sscanf(line, "%d %d %d", &code, &req, &result) != 3 || code != CONTROL || req != REQ_DISCONNECT || result) { + fprintf(stderr, "Could not disconnect %s\n", name); + return 1; + } + return 0; + } + fprintf(stderr, "Unknown command `%s'.\n", argv[optind]); usage(true);