7 #include <sys/socket.h>
9 #include <linux/netlink.h>
10 #include <linux/rtnetlink.h>
13 #include <list/list.h>
14 #include <talloc/talloc.h>
15 #include <waiter/waiter.h>
16 #include <pb-config/pb-config.h>
17 #include <system/system.h>
23 #define PIDFILE_BASE (LOCAL_STATE_DIR "/petitboot/")
25 #define for_each_nlmsg(buf, nlmsg, len) \
26 for (nlmsg = (struct nlmsghdr *)buf; \
27 NLMSG_OK(nlmsg, len) && nlmsg->nlmsg_type != NLMSG_DONE; \
28 nlmsg = NLMSG_NEXT(nlmsg, len))
30 #define for_each_rta(buf, rta, attrlen) \
31 for (rta = (struct rtattr *)(buf); RTA_OK(rta, attrlen); \
32 rta = RTA_NEXT(rta, attrlen))
38 uint8_t hwaddr[HWADDR_SIZE];
42 IFSTATE_UP_WAITING_LINK,
47 struct list_item list;
51 struct list interfaces;
52 struct waiter *waiter;
58 static const struct interface_config *find_config_by_hwaddr(
61 const struct config *config;
64 config = config_get();
68 for (i = 0; i < config->network.n_interfaces; i++) {
69 struct interface_config *ifconf = config->network.interfaces[i];
71 if (!memcmp(ifconf->hwaddr, hwaddr, HWADDR_SIZE))
78 static struct interface *find_interface_by_ifindex(struct network *network,
81 struct interface *interface;
83 list_for_each_entry(&network->interfaces, interface, list)
84 if (interface->ifindex == ifindex)
90 static int network_init_netlink(struct network *network)
92 struct sockaddr_nl addr;
95 memset(&addr, 0, sizeof(addr));
96 addr.nl_family = AF_NETLINK;
97 addr.nl_groups = RTMGRP_LINK;
99 network->netlink_sd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
100 if (network->netlink_sd < 0) {
101 perror("socket(AF_NETLINK)");
105 rc = bind(network->netlink_sd, (struct sockaddr *)&addr, sizeof(addr));
107 perror("bind(sockaddr_nl)");
108 close(network->netlink_sd);
115 static int network_send_link_query(struct network *network)
119 struct nlmsghdr nlmsg;
120 struct rtgenmsg rtmsg;
123 memset(&msg, 0, sizeof(msg));
125 msg.nlmsg.nlmsg_len = sizeof(msg);
126 msg.nlmsg.nlmsg_type = RTM_GETLINK;
127 msg.nlmsg.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT;
128 msg.nlmsg.nlmsg_seq = 0;
129 msg.nlmsg.nlmsg_pid = 0;
130 msg.rtmsg.rtgen_family = AF_UNSPEC;
132 rc = send(network->netlink_sd, &msg, sizeof(msg), MSG_NOSIGNAL);
133 if (rc != sizeof(msg))
139 static int interface_change(struct network *network,
140 struct interface *interface,
144 const char *statestr = up ? "up" : "down";
145 const char *argv[] = {
154 rc = pb_run_cmd(argv, 1, network->dry_run);
156 pb_log("failed to bring interface %s %s\n", interface->name,
163 static int interface_up(struct network *network,
164 struct interface *interface)
166 return interface_change(network, interface, true);
169 static int interface_down(struct network *network,
170 struct interface *interface)
172 return interface_change(network, interface, false);
175 static void configure_interface_dhcp(struct network *network,
176 struct interface *interface)
179 const char *argv[] = {
180 pb_system_apps.udhcpc,
184 "-i", interface->name,
187 snprintf(pidfile, sizeof(pidfile), "%s/udhcpc-%s.pid",
188 PIDFILE_BASE, interface->name);
190 pb_run_cmd(argv, 0, network->dry_run);
194 static void configure_interface_static(struct network *network,
195 struct interface *interface,
196 const struct interface_config *config)
198 const char *addr_argv[] = {
202 config->static_config.address,
207 const char *route_argv[] = {
213 config->static_config.gateway,
219 rc = pb_run_cmd(addr_argv, 1, network->dry_run);
221 pb_log("failed to add address %s to interface %s\n",
222 config->static_config.address,
227 /* we need the interface up before we can route through it */
228 rc = interface_up(network, interface);
232 if (config->static_config.gateway)
233 rc = pb_run_cmd(route_argv, 1, network->dry_run);
236 pb_log("failed to add default route %s on interface %s\n",
237 config->static_config.gateway,
244 static void configure_interface(struct network *network,
245 struct interface *interface, bool up, bool link)
247 const struct interface_config *config = NULL;
249 if (interface->state == IFSTATE_IGNORED)
252 /* old interface? check that we're still up and running */
253 if (interface->state == IFSTATE_CONFIGURED) {
255 interface->state = IFSTATE_NEW;
257 interface->state = IFSTATE_UP_WAITING_LINK;
262 /* always up the lookback, no other handling required */
263 if (!strcmp(interface->name, "lo")) {
264 if (interface->state == IFSTATE_NEW)
265 interface_up(network, interface);
266 interface->state = IFSTATE_CONFIGURED;
270 config = find_config_by_hwaddr(interface->hwaddr);
271 if (config && config->ignore) {
272 pb_log("network: ignoring interface %s\n", interface->name);
273 interface->state = IFSTATE_IGNORED;
277 /* if we're in manual config mode, we need an interface configuration */
278 if (network->manual_config && !config) {
279 interface->state = IFSTATE_IGNORED;
280 pb_log("network: skipping %s: manual config mode, "
281 "but no config for this interface\n",
286 /* new interface? bring up to the point so we can detect a link */
287 if (interface->state == IFSTATE_NEW) {
289 interface_up(network, interface);
290 pb_log("network: bringing up interface %s\n",
295 interface->state = IFSTATE_UP_WAITING_LINK;
299 /* no link? wait for a notification */
300 if (interface->state == IFSTATE_UP_WAITING_LINK && !link)
303 pb_log("network: configuring interface %s\n", interface->name);
305 if (!config || config->method == CONFIG_METHOD_DHCP) {
306 configure_interface_dhcp(network, interface);
308 } else if (config->method == CONFIG_METHOD_STATIC) {
309 configure_interface_static(network, interface, config);
313 static int network_handle_nlmsg(struct network *network, struct nlmsghdr *nlmsg)
315 bool have_ifaddr, have_ifname;
316 struct interface *interface;
317 struct ifinfomsg *info;
320 char ifname[IFNAMSIZ+1];
324 /* we're only interested in NEWLINK messages */
325 type = nlmsg->nlmsg_type;
326 if (!(type == RTM_NEWLINK || type == RTM_DELLINK))
329 info = NLMSG_DATA(nlmsg);
331 have_ifaddr = have_ifname = false;
333 attrlen = nlmsg->nlmsg_len - sizeof(*info);
335 /* extract the interface name and hardware address attributes */
336 for_each_rta(info + 1, attr, attrlen) {
337 void *data = RTA_DATA(attr);
339 switch (attr->rta_type) {
341 memcpy(ifaddr, data, sizeof(ifaddr));
346 strncpy(ifname, data, IFNAMSIZ);
352 if (!have_ifaddr || !have_ifname)
355 if (type == RTM_DELLINK) {
356 interface = find_interface_by_ifindex(network, info->ifi_index);
359 pb_log("network: interface %s removed\n", interface->name);
360 list_remove(&interface->list);
361 talloc_free(interface);
366 interface = find_interface_by_ifindex(network, info->ifi_index);
368 interface = talloc_zero(network, struct interface);
369 interface->ifindex = info->ifi_index;
370 interface->state = IFSTATE_NEW;
371 memcpy(interface->hwaddr, ifaddr, sizeof(interface->hwaddr));
372 strncpy(interface->name, ifname, sizeof(interface->name) - 1);
375 configure_interface(network, interface,
376 info->ifi_flags & IFF_UP,
377 info->ifi_flags & IFF_LOWER_UP);
382 static int network_netlink_process(void *arg)
384 struct network *network = arg;
385 struct nlmsghdr *nlmsg;
390 rc = recv(network->netlink_sd, buf, sizeof(buf), 0);
392 perror("netlink recv");
398 for_each_nlmsg(buf, nlmsg, len)
399 network_handle_nlmsg(network, nlmsg);
404 static void network_init_dns(struct network *network)
406 const struct config *config;
411 if (network->dry_run)
414 config = config_get();
415 if (!config || !config->network.n_dns_servers)
418 rc = read_file(network, "/etc/resolv.conf", &buf, &len);
421 buf = talloc_strdup(network, "");
427 for (i = 0; i < config->network.n_dns_servers; i++) {
431 dns_conf = talloc_asprintf(network, "nameserver %s\n",
432 config->network.dns_servers[i]);
434 if (strstr(buf, dns_conf)) {
435 talloc_free(dns_conf);
439 dns_conf_len = strlen(dns_conf);
440 buf = talloc_realloc(network, buf, char, len + dns_conf_len);
441 memcpy(buf + len, dns_conf, dns_conf_len);
445 talloc_free(dns_conf);
449 rc = replace_file("/etc/resolv.conf", buf, len);
451 pb_log("error replacing resolv.conf: %s\n",
458 struct network *network_init(void *ctx, struct waitset *waitset, bool dry_run)
460 struct network *network;
463 network = talloc(ctx, struct network);
464 list_init(&network->interfaces);
465 network->manual_config = false;
466 network->dry_run = dry_run;
468 network_init_dns(network);
470 rc = network_init_netlink(network);
474 network->waiter = waiter_register_io(waitset, network->netlink_sd,
475 WAIT_IN, network_netlink_process, network);
477 if (!network->waiter)
480 rc = network_send_link_query(network);
487 network_shutdown(network);
492 int network_shutdown(struct network *network)
494 struct interface *interface;
497 waiter_remove(network->waiter);
499 list_for_each_entry(&network->interfaces, interface, list)
500 interface_down(network, interface);
502 close(network->netlink_sd);
503 talloc_free(network);