Replace the connection_tree with a connection_list.
[tinc] / src / control.c
index 7f46a70..46300ed 100644 (file)
@@ -1,6 +1,6 @@
 /*
     control.c -- Control socket handling.
-    Copyright (C) 2007 Guus Sliepen <guus@tinc-vpn.org>
+    Copyright (C) 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
@@ -44,16 +44,16 @@ static bool control_ok(connection_t *c, int type) {
        return control_return(c, type, 0);
 }
 
-bool control_h(connection_t *c, char *request) {
+bool control_h(connection_t *c, const char *request) {
        int type;
 
        if(!c->status.control || c->allow_request != CONTROL) {
-               logger(LOG_ERR, "Unauthorized control request from %s (%s)", c->name, c->hostname);
+               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(LOG_ERR, "Got bad %s from %s (%s)", "CONTROL", c->name, c->hostname);
+               logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "CONTROL", c->name, c->hostname);
                return false;
        }
 
@@ -93,20 +93,19 @@ bool control_h(connection_t *c, char *request) {
                        return control_ok(c, REQ_RETRY);
 
                case REQ_RELOAD:
-                       logger(LOG_NOTICE, "Got '%s' command", "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];
                        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) {
+                       for(list_node_t *node = connection_list->head, *next; node; node = next) {
                                next = node->next;
                                other = node->data;
                                if(strcmp(other->name, name))
@@ -122,10 +121,17 @@ bool control_h(connection_t *c, char *request) {
                        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);
        }
@@ -137,7 +143,7 @@ bool init_control(void) {
 
        FILE *f = fopen(pidfilename, "w");
        if(!f) {
-               logger(LOG_ERR, "Cannot write control socket cookie file %s: %s", pidfilename, strerror(errno));
+               logger(DEBUG_ALWAYS, LOG_ERR, "Cannot write control socket cookie file %s: %s", pidfilename, strerror(errno));
                return false;
        }
 
@@ -152,10 +158,22 @@ bool init_control(void) {
        sockaddr_t sa;
        socklen_t len = sizeof sa;
 
-       if(getsockname(listen_socket[0].tcp, (struct sockaddr *)&sa, &len))
+       // 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, (struct sockaddr *)&sa, &len)) {
                xasprintf(&localhost, "127.0.0.1 port %d", myport);
-       else
+       } 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);