discover/network: In static config mode, only configure defined interfaces
[petitboot] / discover / network.c
index c853a97b0cf21d8350f702d3c83dac780a79c3b5..bc7e186a1921e8531bb2fd37ed026f5e47e5977e 100644 (file)
 
 #include "file.h"
 #include "network.h"
+#include "sysinfo.h"
 #include "device-handler.h"
 
 #define HWADDR_SIZE    6
 #define PIDFILE_BASE   (LOCAL_STATE_DIR "/petitboot/")
+#define INITIAL_BUFSIZE        4096
 
 #define for_each_nlmsg(buf, nlmsg, len) \
        for (nlmsg = (struct nlmsghdr *)buf; \
@@ -57,6 +59,8 @@ struct network {
        struct device_handler   *handler;
        struct waiter           *waiter;
        int                     netlink_sd;
+       void                    *netlink_buf;
+       unsigned int            netlink_buf_size;
        bool                    manual_config;
        bool                    dry_run;
 };
@@ -65,7 +69,7 @@ static const struct interface_config *find_config_by_hwaddr(
                uint8_t *hwaddr)
 {
        const struct config *config;
-       int i;
+       unsigned int i;
 
        config = config_get();
        if (!config)
@@ -115,6 +119,10 @@ static int network_init_netlink(struct network *network)
                return -1;
        }
 
+       network->netlink_buf_size = INITIAL_BUFSIZE;
+       network->netlink_buf = talloc_array(network, char,
+                               network->netlink_buf_size);
+
        return 0;
 }
 
@@ -196,7 +204,7 @@ static int interface_down(struct interface *interface)
 static void udhcpc_process_exit(struct process *process)
 {
        struct interface *interface = process->data;
-       pb_log("udhcp client [pid %d] for interface %s exited, rc %d\n",
+       pb_debug("udhcp client [pid %d] for interface %s exited, rc %d\n",
                        process->pid, interface->name, process->exit_status);
        interface->udhcpc_process = NULL;
        process_release(process);
@@ -211,6 +219,7 @@ static void configure_interface_dhcp(struct interface *interface)
                pb_system_apps.udhcpc,
                "-R",
                "-n",
+               "-O", "pxeconffile",
                "-p", pidfile,
                "-i", interface->name,
                NULL,
@@ -361,6 +370,7 @@ static int network_handle_nlmsg(struct network *network, struct nlmsghdr *nlmsg)
        info = NLMSG_DATA(nlmsg);
 
        have_ifaddr = have_ifname = false;
+       mtu = 1;
 
        attrlen = nlmsg->nlmsg_len - sizeof(*info);
 
@@ -406,6 +416,12 @@ static int network_handle_nlmsg(struct network *network, struct nlmsghdr *nlmsg)
                memcpy(interface->hwaddr, ifaddr, sizeof(interface->hwaddr));
                strncpy(interface->name, ifname, sizeof(interface->name) - 1);
                add_interface(network, interface);
+
+               /* tell the sysinfo code about this interface */
+               if (strcmp(interface->name, "lo"))
+                       system_info_register_interface(
+                                       sizeof(interface->hwaddr),
+                                       interface->hwaddr, interface->name);
        }
 
        configure_interface(network, interface,
@@ -419,19 +435,48 @@ static int network_netlink_process(void *arg)
 {
        struct network *network = arg;
        struct nlmsghdr *nlmsg;
+       struct msghdr msg;
+       struct iovec iov;
        unsigned int len;
-       char buf[4096];
-       int rc;
+       int rc, flags;
+
+       memset(&msg, 0, sizeof(msg));
+       msg.msg_iov = &iov;
+       msg.msg_iovlen = 1;
+
+       flags = MSG_PEEK;
+
+retry:
+       iov.iov_len = network->netlink_buf_size;
+       iov.iov_base = network->netlink_buf;
+
+       rc = recvmsg(network->netlink_sd, &msg, flags);
 
-       rc = recv(network->netlink_sd, buf, sizeof(buf), 0);
        if (rc < 0) {
-               perror("netlink recv");
+               perror("netlink recv header");
                return -1;
        }
 
        len = rc;
 
-       for_each_nlmsg(buf, nlmsg, len)
+       /* if the netlink message was larger than our buffer, realloc
+        * before reading again */
+       if (len > network->netlink_buf_size || msg.msg_flags & MSG_TRUNC) {
+               network->netlink_buf_size *= 2;
+               network->netlink_buf = talloc_realloc(network,
+                                       network->netlink_buf,
+                                       char *,
+                                       network->netlink_buf_size);
+               goto retry;
+       }
+
+       /* otherwise, we're good to read the entire message without PEEK */
+       if (flags == MSG_PEEK) {
+               flags = 0;
+               goto retry;
+       }
+
+       for_each_nlmsg(network->netlink_buf, nlmsg, len)
                network_handle_nlmsg(network, nlmsg);
 
        return 0;
@@ -440,7 +485,8 @@ static int network_netlink_process(void *arg)
 static void network_init_dns(struct network *network)
 {
        const struct config *config;
-       int i, rc, len;
+       unsigned int i;
+       int rc, len;
        bool modified;
        char *buf;
 
@@ -473,9 +519,10 @@ static void network_init_dns(struct network *network)
                }
 
                dns_conf_len = strlen(dns_conf);
-               buf = talloc_realloc(network, buf, char, len + dns_conf_len);
+               buf = talloc_realloc(network, buf, char, len + dns_conf_len + 1);
                memcpy(buf + len, dns_conf, dns_conf_len);
                len += dns_conf_len;
+               buf[len - 1] = '\0';
                modified = true;
 
                talloc_free(dns_conf);
@@ -500,8 +547,8 @@ struct network *network_init(struct device_handler *handler,
        network = talloc(handler, struct network);
        list_init(&network->interfaces);
        network->handler = handler;
-       network->manual_config = false;
        network->dry_run = dry_run;
+       network->manual_config = config_get()->network.n_interfaces != 0;
 
        network_init_dns(network);