]> git.ozlabs.org Git - petitboot/blobdiff - discover/network.c
lib/waiter: merge time & io waiter init loops
[petitboot] / discover / network.c
index 4a4f93252f5a1f02693222e2ca1d6560d2a0995b..4b9e4f10958f733df1f661c8e8f5b087d4f8a16a 100644 (file)
@@ -3,6 +3,7 @@
 #include <stdint.h>
 #include <string.h>
 #include <stdlib.h>
+#include <errno.h>
 #include <sys/socket.h>
 #include <linux/if.h>
 #include <linux/netlink.h>
@@ -15,6 +16,7 @@
 #include <pb-config/pb-config.h>
 #include <system/system.h>
 
+#include "file.h"
 #include "network.h"
 
 #define HWADDR_SIZE    6
@@ -53,7 +55,7 @@ struct network {
        bool            dry_run;
 };
 
-static const struct network_config *find_config_by_hwaddr(
+static const struct interface_config *find_config_by_hwaddr(
                uint8_t *hwaddr)
 {
        const struct config *config;
@@ -63,11 +65,11 @@ static const struct network_config *find_config_by_hwaddr(
        if (!config)
                return NULL;
 
-       for (i = 0; i < config->n_network_configs; i++) {
-               struct network_config *netconf = config->network_configs[i];
+       for (i = 0; i < config->network.n_interfaces; i++) {
+               struct interface_config *ifconf = config->network.interfaces[i];
 
-               if (!memcmp(netconf->hwaddr, hwaddr, HWADDR_SIZE))
-                       return netconf;
+               if (!memcmp(ifconf->hwaddr, hwaddr, HWADDR_SIZE))
+                       return ifconf;
        }
 
        return NULL;
@@ -134,26 +136,42 @@ static int network_send_link_query(struct network *network)
        return 0;
 }
 
-static int interface_up(struct network *network, struct interface *interface)
+static int interface_change(struct network *network,
+               struct interface *interface,
+               bool up)
 {
        int rc;
+       const char *statestr = up ? "up" : "down";
        const char *argv[] = {
                pb_system_apps.ip,
                "link",
                "set",
                interface->name,
-               "up",
+               statestr,
                NULL,
        };
 
        rc = pb_run_cmd(argv, 1, network->dry_run);
        if (rc) {
-               pb_log("failed to bring interface %s up\n", interface->name);
+               pb_log("failed to bring interface %s %s\n", interface->name,
+                               statestr);
                return -1;
        }
        return 0;
 }
 
+static int interface_up(struct network *network,
+               struct interface *interface)
+{
+       return interface_change(network, interface, true);
+}
+
+static int interface_down(struct network *network,
+               struct interface *interface)
+{
+       return interface_change(network, interface, false);
+}
+
 static void configure_interface_dhcp(struct network *network,
                struct interface *interface)
 {
@@ -175,7 +193,7 @@ static void configure_interface_dhcp(struct network *network,
 
 static void configure_interface_static(struct network *network,
                struct interface *interface,
-               const struct network_config *config)
+               const struct interface_config *config)
 {
        const char *addr_argv[] = {
                pb_system_apps.ip,
@@ -226,7 +244,7 @@ static void configure_interface_static(struct network *network,
 static void configure_interface(struct network *network,
                struct interface *interface, bool up, bool link)
 {
-       const struct network_config *config = NULL;
+       const struct interface_config *config = NULL;
 
        if (interface->state == IFSTATE_IGNORED)
                return;
@@ -383,6 +401,60 @@ static int network_netlink_process(void *arg)
        return 0;
 }
 
+static void network_init_dns(struct network *network)
+{
+       const struct config *config;
+       int i, rc, len;
+       bool modified;
+       char *buf;
+
+       if (network->dry_run)
+               return;
+
+       config = config_get();
+       if (!config || !config->network.n_dns_servers)
+               return;
+
+       rc = read_file(network, "/etc/resolv.conf", &buf, &len);
+
+       if (rc) {
+               buf = talloc_strdup(network, "");
+               len = 0;
+       }
+
+       modified = false;
+
+       for (i = 0; i < config->network.n_dns_servers; i++) {
+               int dns_conf_len;
+               char *dns_conf;
+
+               dns_conf = talloc_asprintf(network, "nameserver %s\n",
+                               config->network.dns_servers[i]);
+
+               if (strstr(buf, dns_conf)) {
+                       talloc_free(dns_conf);
+                       continue;
+               }
+
+               dns_conf_len = strlen(dns_conf);
+               buf = talloc_realloc(network, buf, char, len + dns_conf_len);
+               memcpy(buf + len, dns_conf, dns_conf_len);
+               len += dns_conf_len;
+               modified = true;
+
+               talloc_free(dns_conf);
+       }
+
+       if (modified) {
+               rc = replace_file("/etc/resolv.conf", buf, len);
+               if (rc)
+                       pb_log("error replacing resolv.conf: %s\n",
+                                       strerror(errno));
+       }
+
+       talloc_free(buf);
+}
+
 struct network *network_init(void *ctx, struct waitset *waitset, bool dry_run)
 {
        struct network *network;
@@ -393,6 +465,8 @@ struct network *network_init(void *ctx, struct waitset *waitset, bool dry_run)
        network->manual_config = false;
        network->dry_run = dry_run;
 
+       network_init_dns(network);
+
        rc = network_init_netlink(network);
        if (rc)
                goto err;
@@ -417,9 +491,14 @@ err:
 
 int network_shutdown(struct network *network)
 {
+       struct interface *interface;
+
        if (network->waiter)
                waiter_remove(network->waiter);
 
+       list_for_each_entry(&network->interfaces, interface, list)
+               interface_down(network, interface);
+
        close(network->netlink_sd);
        talloc_free(network);
        return 0;