#include <log/log.h>
#include <list/list.h>
+#include <types/types.h>
#include <talloc/talloc.h>
#include <waiter/waiter.h>
#include <pb-config/pb-config.h>
#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; \
struct list_item list;
struct process *udhcpc_process;
+ struct discover_device *dev;
};
struct network {
- struct list interfaces;
- struct waiter *waiter;
- int netlink_sd;
- bool manual_config;
- bool dry_run;
+ struct list interfaces;
+ struct device_handler *handler;
+ struct waiter *waiter;
+ int netlink_sd;
+ void *netlink_buf;
+ unsigned int netlink_buf_size;
+ bool manual_config;
+ bool dry_run;
};
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)
return -1;
}
+ network->netlink_buf_size = INITIAL_BUFSIZE;
+ network->netlink_buf = talloc_array(network, char,
+ network->netlink_buf_size);
+
return 0;
}
struct interface *interface)
{
list_add(&network->interfaces, &interface->list);
+ interface->dev = discover_device_create(network->handler,
+ interface->name);
+ interface->dev->device->type = DEVICE_TYPE_NETWORK;
+ device_handler_add_device(network->handler, interface->dev);
}
-static void remove_interface(struct interface *interface)
+static void remove_interface(struct network *network,
+ struct interface *interface)
{
+ device_handler_remove(network->handler, interface->dev);
list_remove(&interface->list);
talloc_free(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);
info = NLMSG_DATA(nlmsg);
have_ifaddr = have_ifname = false;
+ mtu = 1;
attrlen = nlmsg->nlmsg_len - sizeof(*info);
if (!interface)
return 0;
pb_log("network: interface %s removed\n", interface->name);
- remove_interface(interface);
+ remove_interface(network, interface);
return 0;
}
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,
{
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;
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;
}
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);
talloc_free(buf);
}
-struct network *network_init(void *ctx, struct waitset *waitset, bool dry_run)
+struct network *network_init(struct device_handler *handler,
+ struct waitset *waitset, bool dry_run)
{
struct network *network;
int rc;
- network = talloc(ctx, struct network);
+ network = talloc(handler, struct network);
list_init(&network->interfaces);
+ network->handler = handler;
network->manual_config = false;
network->dry_run = dry_run;