Check if devops is valid before closing the device.
[tinc] / src / net_setup.c
index 7c9f23a..d83c572 100644 (file)
@@ -46,6 +46,7 @@
 char *myport;
 static io_t device_io;
 devops_t devops;
+bool device_standby = false;
 
 char *proxyhost;
 char *proxyport;
@@ -416,7 +417,7 @@ char *get_name(void) {
                                return false;
                        }
                        if(gethostname(hostname, sizeof hostname) || !*hostname) {
-                               logger(DEBUG_ALWAYS, LOG_ERR, "Could not get hostname: %s\n", strerror(errno));
+                               logger(DEBUG_ALWAYS, LOG_ERR, "Could not get hostname: %s\n", sockstrerror(sockerrno));
                                return false;
                        }
                        hostname[31] = 0;
@@ -444,7 +445,6 @@ bool setup_myself_reloadable(void) {
        char *fmode = NULL;
        char *bmode = NULL;
        char *afname = NULL;
-       char *address = NULL;
        char *space;
        bool choice;
 
@@ -531,16 +531,6 @@ bool setup_myself_reloadable(void) {
        get_config_bool(lookup_config(config_tree, "DirectOnly"), &directonly);
        get_config_bool(lookup_config(config_tree, "LocalDiscovery"), &localdiscovery);
 
-       memset(&localdiscovery_address, 0, sizeof localdiscovery_address);
-       if(get_config_string(lookup_config(config_tree, "LocalDiscoveryAddress"), &address)) {
-               struct addrinfo *ai = str2addrinfo(address, myport, SOCK_DGRAM);
-               free(address);
-               if(!ai)
-                       return false;
-               memcpy(&localdiscovery_address, ai->ai_addr, ai->ai_addrlen);
-       }
-
-
        if(get_config_string(lookup_config(config_tree, "Mode"), &rmode)) {
                if(!strcasecmp(rmode, "router"))
                        routing_mode = RMODE_ROUTER;
@@ -595,6 +585,20 @@ bool setup_myself_reloadable(void) {
                free(bmode);
        }
 
+       const char* const DEFAULT_BROADCAST_SUBNETS[] = { "ff:ff:ff:ff:ff:ff", "255.255.255.255", "224.0.0.0/4", "ff00::/8" };
+       for (size_t i = 0; i < sizeof(DEFAULT_BROADCAST_SUBNETS) / sizeof(*DEFAULT_BROADCAST_SUBNETS); i++) {
+               subnet_t *s = new_subnet();
+               if (!str2net(s, DEFAULT_BROADCAST_SUBNETS[i]))
+                       abort();
+               subnet_add(NULL, s);
+       }
+       for (config_t* cfg = lookup_config(config_tree, "BroadcastSubnet"); cfg; cfg = lookup_config_next(config_tree, cfg)) {
+               subnet_t *s;
+               if (!get_config_subnet(cfg, &s))
+                       continue;
+               subnet_add(NULL, s);
+       }
+
 #if !defined(SOL_IP) || !defined(IP_TOS)
        if(priorityinheritance)
                logger(DEBUG_ALWAYS, LOG_WARNING, "%s not supported on this platform", "PriorityInheritance");
@@ -726,6 +730,40 @@ static bool add_listen_address(char *address, bool bindto) {
        return true;
 }
 
+void device_enable(void) {
+       if (devops.enable)
+               devops.enable();
+
+       /* Run tinc-up script to further initialize the tap interface */
+
+       char *envp[5] = {NULL};
+       xasprintf(&envp[0], "NETNAME=%s", netname ? : "");
+       xasprintf(&envp[1], "DEVICE=%s", device ? : "");
+       xasprintf(&envp[2], "INTERFACE=%s", iface ? : "");
+       xasprintf(&envp[3], "NAME=%s", myself->name);
+
+       execute_script("tinc-up", envp);
+
+       for(int i = 0; i < 4; i++)
+               free(envp[i]);
+}
+
+void device_disable(void) {
+       char *envp[5] = {NULL};
+       xasprintf(&envp[0], "NETNAME=%s", netname ? : "");
+       xasprintf(&envp[1], "DEVICE=%s", device ? : "");
+       xasprintf(&envp[2], "INTERFACE=%s", iface ? : "");
+       xasprintf(&envp[3], "NAME=%s", myself->name);
+
+       execute_script("tinc-down", envp);
+
+       for(int i = 0; i < 4; i++)
+               free(envp[i]);
+
+       if (devops.disable)
+               devops.disable();
+}
+
 /*
   Configure node_t myself and set up the local sockets (listen only)
 */
@@ -918,6 +956,8 @@ static bool setup_myself(void) {
 #endif
        }
 
+       get_config_bool(lookup_config(config_tree, "DeviceStandby"), &device_standby);
+
        if(!devops.setup())
                return false;
 
@@ -943,7 +983,7 @@ static bool setup_myself(void) {
                for(int i = 0; i < listen_sockets; i++) {
                        salen = sizeof sa;
                        if(getsockname(i + 3, &sa.sa, &salen) < 0) {
-                               logger(DEBUG_ALWAYS, LOG_ERR, "Could not get address of listen fd %d: %s", i + 3, sockstrerror(errno));
+                               logger(DEBUG_ALWAYS, LOG_ERR, "Could not get address of listen fd %d: %s", i + 3, sockstrerror(sockerrno));
                                return false;
                        }
 
@@ -996,7 +1036,7 @@ static bool setup_myself(void) {
 
        /* If no Port option was specified, set myport to the port used by the first listening socket. */
 
-       if(!port_specified) {
+       if(!port_specified || atoi(myport) == 0) {
                sockaddr_t sa;
                socklen_t salen = sizeof sa;
                if(!getsockname(listen_socket[0].udp.fd, &sa.sa, &salen)) {
@@ -1048,18 +1088,8 @@ bool setup_network(void) {
        if(!init_control())
                return false;
 
-       /* Run tinc-up script to further initialize the tap interface */
-
-       char *envp[5] = {NULL};
-       xasprintf(&envp[0], "NETNAME=%s", netname ? : "");
-       xasprintf(&envp[1], "DEVICE=%s", device ? : "");
-       xasprintf(&envp[2], "INTERFACE=%s", iface ? : "");
-       xasprintf(&envp[3], "NAME=%s", myself->name);
-
-       execute_script("tinc-up", envp);
-
-       for(int i = 0; i < 4; i++)
-               free(envp[i]);
+       if (!device_standby)
+               device_enable();
 
        /* Run subnet-up scripts for our own subnets */
 
@@ -1098,26 +1128,21 @@ void close_network_connections(void) {
                close(listen_socket[i].udp.fd);
        }
 
-       char *envp[5] = {NULL};
-       xasprintf(&envp[0], "NETNAME=%s", netname ? : "");
-       xasprintf(&envp[1], "DEVICE=%s", device ? : "");
-       xasprintf(&envp[2], "INTERFACE=%s", iface ? : "");
-       xasprintf(&envp[3], "NAME=%s", myself->name);
-
        exit_requests();
        exit_edges();
        exit_subnets();
        exit_nodes();
        exit_connections();
 
-       execute_script("tinc-down", envp);
+       if (!device_standby)
+               device_disable();
 
        if(myport) free(myport);
 
-       for(int i = 0; i < 4; i++)
-               free(envp[i]);
-
-       devops.close();
+       if (device_fd >= 0)
+               io_del(&device_io);
+       if (devops.close)
+               devops.close();
 
        exit_control();