]> git.ozlabs.org Git - petitboot/blob - discover/network.c
discover/grub: Reverse BLS entries sorting to match Petitboot's boot order
[petitboot] / discover / network.c
1
2 #include <stdbool.h>
3 #include <stdint.h>
4 #include <string.h>
5 #include <stdlib.h>
6 #include <errno.h>
7 #include <sys/socket.h>
8 #include <linux/if.h>
9 #include <linux/netlink.h>
10 #include <linux/rtnetlink.h>
11 #include <i18n/i18n.h>
12
13 #include <log/log.h>
14 #include <list/list.h>
15 #include <file/file.h>
16 #include <types/types.h>
17 #include <talloc/talloc.h>
18 #include <waiter/waiter.h>
19 #include <process/process.h>
20 #include <system/system.h>
21
22 #include "network.h"
23 #include "sysinfo.h"
24 #include "platform.h"
25 #include "device-handler.h"
26 #include "paths.h"
27
28 #define HWADDR_SIZE     6
29 #define PIDFILE_BASE    (LOCAL_STATE_DIR "/petitboot/")
30 #define INITIAL_BUFSIZE 4096
31
32 #define for_each_nlmsg(buf, nlmsg, len) \
33         for (nlmsg = (struct nlmsghdr *)buf; \
34                 NLMSG_OK(nlmsg, len) && nlmsg->nlmsg_type != NLMSG_DONE; \
35                 nlmsg = NLMSG_NEXT(nlmsg, len))
36
37 #define for_each_rta(buf, rta, attrlen) \
38         for (rta = (struct rtattr *)(buf); RTA_OK(rta, attrlen); \
39                         rta = RTA_NEXT(rta, attrlen))
40
41
42 struct interface {
43         int     ifindex;
44         char    name[IFNAMSIZ];
45         uint8_t hwaddr[HWADDR_SIZE];
46
47         enum {
48                 IFSTATE_NEW,
49                 IFSTATE_UP_WAITING_LINK,
50                 IFSTATE_CONFIGURED,
51                 IFSTATE_IGNORED,
52         } state;
53
54         struct list_item list;
55         struct process *udhcpc_process;
56         struct discover_device *dev;
57         bool ready;
58 };
59
60 struct network {
61         struct list             interfaces;
62         struct device_handler   *handler;
63         struct waiter           *waiter;
64         int                     netlink_sd;
65         void                    *netlink_buf;
66         unsigned int            netlink_buf_size;
67         bool                    manual_config;
68         bool                    dry_run;
69 };
70
71 static char *mac_bytes_to_string(void *ctx, uint8_t *addr, int len)
72 {
73         const int l = strlen("xx:");
74         char *buf;
75         int i;
76
77         if (len <= 0)
78                 return talloc_strdup(ctx, "");
79
80         buf = talloc_array(ctx, char, (len * l) + 1);
81
82         for (i = 0; i < len; i++)
83                 sprintf(buf + (l * i), "%02x:", addr[i]);
84
85         *(buf + (l * len) - 1) = '\0';
86
87         return buf;
88 }
89
90 static const struct interface_config *find_config_by_hwaddr(
91                 uint8_t *hwaddr)
92 {
93         const struct config *config;
94         unsigned int i;
95
96         config = config_get();
97         if (!config)
98                 return NULL;
99
100         for (i = 0; i < config->network.n_interfaces; i++) {
101                 struct interface_config *ifconf = config->network.interfaces[i];
102
103                 if (!memcmp(ifconf->hwaddr, hwaddr, HWADDR_SIZE))
104                         return ifconf;
105         }
106
107         return NULL;
108 }
109
110 static struct interface *find_interface_by_ifindex(struct network *network,
111                 int ifindex)
112 {
113         struct interface *interface;
114
115         list_for_each_entry(&network->interfaces, interface, list)
116                 if (interface->ifindex == ifindex)
117                         return interface;
118
119         return NULL;
120 }
121
122 static struct interface *find_interface_by_name(struct network *network,
123                 const char *name)
124 {
125         struct interface *interface;
126
127         list_for_each_entry(&network->interfaces, interface, list)
128                 if (!strcmp(interface->name, name))
129                         return interface;
130
131         return NULL;
132 }
133
134 static struct interface *find_interface_by_uuid(struct network *network,
135                 const char *uuid)
136 {
137         struct interface *interface;
138         char *mac;
139
140         list_for_each_entry(&network->interfaces, interface, list) {
141                 mac = mac_bytes_to_string(interface, interface->hwaddr,
142                                         sizeof(interface->hwaddr));
143                 if (!strcmp(mac, uuid)) {
144                         talloc_free(mac);
145                         return interface;
146                 }
147                 talloc_free(mac);
148         }
149
150         return NULL;
151 }
152
153 uint8_t *find_mac_by_name(void *ctx, struct network *network,
154                 const char *name)
155 {
156         struct interface *interface;
157
158         interface = find_interface_by_name(network, name);
159         if (!interface)
160                 return NULL;
161
162         return talloc_memdup(ctx, &interface->hwaddr,
163                              sizeof(uint8_t) * HWADDR_SIZE);
164 }
165
166 static int network_init_netlink(struct network *network)
167 {
168         struct sockaddr_nl addr;
169         int rc;
170
171         memset(&addr, 0, sizeof(addr));
172         addr.nl_family = AF_NETLINK;
173         addr.nl_groups = RTMGRP_LINK;
174
175         network->netlink_sd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
176         if (network->netlink_sd < 0) {
177                 perror("socket(AF_NETLINK)");
178                 return -1;
179         }
180
181         rc = bind(network->netlink_sd, (struct sockaddr *)&addr, sizeof(addr));
182         if (rc) {
183                 perror("bind(sockaddr_nl)");
184                 close(network->netlink_sd);
185                 return -1;
186         }
187
188         network->netlink_buf_size = INITIAL_BUFSIZE;
189         network->netlink_buf = talloc_array(network, char,
190                                 network->netlink_buf_size);
191
192         return 0;
193 }
194
195 static int network_send_link_query(struct network *network)
196 {
197         int rc;
198         struct {
199                 struct nlmsghdr nlmsg;
200                 struct rtgenmsg rtmsg;
201         } msg;
202
203         memset(&msg, 0, sizeof(msg));
204
205         msg.nlmsg.nlmsg_len = sizeof(msg);
206         msg.nlmsg.nlmsg_type = RTM_GETLINK;
207         msg.nlmsg.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT;
208         msg.nlmsg.nlmsg_seq = 0;
209         msg.nlmsg.nlmsg_pid = 0;
210         msg.rtmsg.rtgen_family = AF_UNSPEC;
211
212         rc = send(network->netlink_sd, &msg, sizeof(msg), MSG_NOSIGNAL);
213         if (rc != sizeof(msg))
214                 return -1;
215
216         return 0;
217 }
218
219 static void create_interface_dev(struct network *network,
220                 struct interface *interface)
221 {
222         char *uuid = mac_bytes_to_string(interface, interface->hwaddr,
223                                                 sizeof(interface->hwaddr));
224
225         interface->dev = discover_device_create(network->handler, uuid,
226                                                 interface->name);
227         interface->dev->device->type = DEVICE_TYPE_NETWORK;
228         device_handler_add_device(network->handler, interface->dev);
229         talloc_free(uuid);
230 }
231
232 static void remove_interface(struct network *network,
233                 struct interface *interface)
234 {
235         if (interface->dev)
236                 device_handler_remove(network->handler, interface->dev);
237         list_remove(&interface->list);
238         talloc_free(interface);
239 }
240
241 void network_register_device(struct network *network,
242                 struct discover_device *dev)
243 {
244         struct interface *iface;
245
246         if (dev->uuid)
247                 iface = find_interface_by_uuid(network, dev->uuid);
248         else
249                 iface = find_interface_by_name(network, dev->label);
250         if (!iface)
251                 return;
252
253         iface->dev = dev;
254         dev->uuid = mac_bytes_to_string(iface->dev, iface->hwaddr,
255                         sizeof(iface->hwaddr));
256 }
257
258 void network_unregister_device(struct network *network,
259                 struct discover_device *dev)
260 {
261         struct interface *iface;
262
263         iface = find_interface_by_uuid(network, dev->uuid);
264         if (!iface)
265                 return;
266
267         iface->dev = NULL;
268 }
269
270 static int interface_change(struct interface *interface, bool up)
271 {
272         const char *statestr = up ? "up" : "down";
273         int rc;
274
275         if (!up && interface->udhcpc_process) {
276                 /* we don't care about the callback from here */
277                 interface->udhcpc_process->exit_cb = NULL;
278                 interface->udhcpc_process->data = NULL;
279                 process_stop_async(interface->udhcpc_process);
280                 process_release(interface->udhcpc_process);
281         }
282
283         if (!up) {
284                 rc = process_run_simple(interface, pb_system_apps.ip,
285                                 "address", "flush", "dev", interface->name,
286                                 NULL);
287                 if (rc)
288                         pb_log("failed to flush addresses from interface %s\n",
289                                 interface->name);
290         }
291
292         rc = process_run_simple(interface, pb_system_apps.ip,
293                         "link", "set", interface->name, statestr, NULL);
294         if (rc) {
295                 pb_log("failed to bring interface %s %s\n", interface->name,
296                                 statestr);
297                 return -1;
298         }
299         return 0;
300 }
301
302 static int interface_up(struct interface *interface)
303 {
304         return interface_change(interface, true);
305 }
306
307 static int interface_down(struct interface *interface)
308 {
309         return interface_change(interface, false);
310 }
311
312 static void udhcpc_process_exit(struct process *process)
313 {
314         struct interface *interface = process->data;
315         pb_debug("udhcp client [pid %d] for interface %s exited, rc %d\n",
316                         process->pid, interface->name, process->exit_status);
317         interface->udhcpc_process = NULL;
318         process_release(process);
319 }
320
321 static void configure_interface_dhcp(struct network *network,
322                 struct interface *interface)
323 {
324         const struct platform *platform;
325         char pidfile[256], id[10];
326         struct process *process;
327         int rc;
328         const char *argv[] = {
329                 pb_system_apps.udhcpc,
330                 "-R",
331                 "-f",
332                 "-O", "pxeconffile",
333                 "-O", "pxepathprefix",
334                 "-p", pidfile,
335                 "-i", interface->name,
336                 "-x", id, /* [11,12] - dhcp client identifier */
337                 NULL,
338         };
339
340         device_handler_status_dev_info(network->handler, interface->dev,
341                         _("Configuring with DHCP"));
342
343         snprintf(pidfile, sizeof(pidfile), "%s/udhcpc-%s.pid",
344                         PIDFILE_BASE, interface->name);
345
346         platform = platform_get();
347         if (platform && platform->dhcp_arch_id != 0xffff)
348                 snprintf(id, sizeof(id), "0x5d:%04x", platform->dhcp_arch_id);
349         else
350                 argv[11] = NULL;
351
352         process = process_create(interface);
353
354         process->path = pb_system_apps.udhcpc;
355         process->argv = argv;
356         process->exit_cb = udhcpc_process_exit;
357         process->data = interface;
358
359         rc = process_run_async(process);
360
361         if (rc)
362                 process_release(process);
363         else
364                 interface->udhcpc_process = process;
365
366         return;
367 }
368
369 static void configure_interface_static(struct network *network,
370                 struct interface *interface,
371                 const struct interface_config *config)
372 {
373         int rc;
374
375         device_handler_status_dev_info(network->handler, interface->dev,
376                         _("Configuring with static address (ip: %s)"),
377                         config->static_config.address);
378
379         rc = process_run_simple(interface, pb_system_apps.ip,
380                         "address", "add", config->static_config.address,
381                         "dev", interface->name, NULL);
382
383
384         if (rc) {
385                 pb_log("failed to add address %s to interface %s\n",
386                                 config->static_config.address,
387                                 interface->name);
388                 return;
389         }
390
391         system_info_set_interface_address(sizeof(interface->hwaddr),
392                                 interface->hwaddr,
393                                 config->static_config.address);
394
395         /* we need the interface up before we can route through it */
396         rc = interface_up(interface);
397         if (rc)
398                 return;
399
400         if (config->static_config.gateway)
401                 rc = process_run_simple(interface, pb_system_apps.ip,
402                                 "route", "add", "default",
403                                 "via", config->static_config.gateway,
404                                 NULL);
405
406         if (rc) {
407                 pb_log("failed to add default route %s on interface %s\n",
408                                 config->static_config.gateway,
409                                 interface->name);
410         }
411
412         if (config->static_config.url) {
413                 pb_log("config URL %s\n", config->static_config.url);
414                 device_handler_process_url(network->handler,
415                                 config->static_config.url,
416                                 mac_bytes_to_string(interface->dev,
417                                                 interface->hwaddr,
418                                                 sizeof(interface->hwaddr)),
419                                 config->static_config.address);
420         }
421
422         return;
423 }
424
425 static void configure_interface(struct network *network,
426                 struct interface *interface, bool up, bool link)
427 {
428         const struct interface_config *config = NULL;
429
430         if (interface->state == IFSTATE_IGNORED)
431                 return;
432
433         /* old interface? check that we're still up and running */
434         if (interface->state == IFSTATE_CONFIGURED) {
435                 if (!up)
436                         interface->state = IFSTATE_NEW;
437                 else if (!link)
438                         interface->state = IFSTATE_UP_WAITING_LINK;
439                 else {
440                         pb_debug("network: skipping configured interface %s\n",
441                                         interface->name);
442                         return;
443                 }
444         }
445
446         /* always up the lookback, no other handling required */
447         if (!strcmp(interface->name, "lo")) {
448                 if (interface->state == IFSTATE_NEW)
449                         interface_up(interface);
450                 interface->state = IFSTATE_CONFIGURED;
451                 return;
452         }
453
454         config = find_config_by_hwaddr(interface->hwaddr);
455         if (config && config->ignore) {
456                 pb_log("network: ignoring interface %s\n", interface->name);
457                 interface->state = IFSTATE_IGNORED;
458                 return;
459         }
460
461         /* if we're in manual config mode, we need an interface configuration */
462         if (network->manual_config && !config) {
463                 interface->state = IFSTATE_IGNORED;
464                 pb_log("network: skipping %s: manual config mode, "
465                                 "but no config for this interface\n",
466                                 interface->name);
467                 return;
468         }
469
470         /* new interface? bring up to the point so we can detect a link */
471         if (interface->state == IFSTATE_NEW) {
472                 if (!up) {
473                         interface_up(interface);
474                         pb_log("network: bringing up interface %s\n",
475                                         interface->name);
476                         return;
477
478                 } else if (!link) {
479                         interface->state = IFSTATE_UP_WAITING_LINK;
480                 }
481         }
482
483         /* no link? wait for a notification */
484         if (interface->state == IFSTATE_UP_WAITING_LINK && !link)
485                 return;
486
487         pb_log("network: configuring interface %s\n", interface->name);
488
489         if (!config || config->method == CONFIG_METHOD_DHCP) {
490                 configure_interface_dhcp(network, interface);
491
492         } else if (config->method == CONFIG_METHOD_STATIC) {
493                 configure_interface_static(network, interface, config);
494                 /* Nothing left to do for static interfaces */
495                 pending_network_jobs_start();
496         }
497
498         interface->state = IFSTATE_CONFIGURED;
499 }
500
501 static int network_handle_nlmsg(struct network *network, struct nlmsghdr *nlmsg)
502 {
503         bool have_ifaddr, have_ifname;
504         struct interface *interface, *tmp;
505         struct ifinfomsg *info;
506         struct rtattr *attr;
507         unsigned int mtu;
508         uint8_t ifaddr[6];
509         char ifname[IFNAMSIZ+1];
510         int attrlen, type;
511
512
513         /* we're only interested in NEWLINK messages */
514         type = nlmsg->nlmsg_type;
515         if (!(type == RTM_NEWLINK || type == RTM_DELLINK))
516                 return 0;
517
518         info = NLMSG_DATA(nlmsg);
519
520         have_ifaddr = have_ifname = false;
521         mtu = 1;
522
523         attrlen = nlmsg->nlmsg_len - sizeof(*info);
524
525         /* extract the interface name and hardware address attributes */
526         for_each_rta(info + 1, attr, attrlen) {
527                 void *data = RTA_DATA(attr);
528
529                 switch (attr->rta_type) {
530                 case IFLA_ADDRESS:
531                         memcpy(ifaddr, data, sizeof(ifaddr));
532                         have_ifaddr = true;
533                         break;
534
535                 case IFLA_IFNAME:
536                         strncpy(ifname, data, IFNAMSIZ);
537                         have_ifname = true;
538                         break;
539
540                 case IFLA_MTU:
541                         mtu = *(unsigned int *)data;
542                         break;
543                 }
544         }
545
546         if (!have_ifaddr || !have_ifname)
547                 return -1;
548
549         if (type == RTM_DELLINK || mtu == 0) {
550                 interface = find_interface_by_ifindex(network, info->ifi_index);
551                 if (!interface)
552                         return 0;
553                 pb_log("network: interface %s removed\n", interface->name);
554                 remove_interface(network, interface);
555                 return 0;
556         }
557
558         /* ignore the default tun device in some environments */
559         if (strncmp(ifname, "tun", strlen("tun")) == 0)
560                 return 0;
561
562         interface = find_interface_by_ifindex(network, info->ifi_index);
563         if (!interface) {
564                 interface = talloc_zero(network, struct interface);
565                 interface->ifindex = info->ifi_index;
566                 interface->state = IFSTATE_NEW;
567                 memcpy(interface->hwaddr, ifaddr, sizeof(interface->hwaddr));
568                 strncpy(interface->name, ifname, sizeof(interface->name) - 1);
569
570                 list_for_each_entry(&network->interfaces, tmp, list)
571                         if (memcmp(interface->hwaddr, tmp->hwaddr,
572                                    sizeof(interface->hwaddr)) == 0) {
573                                 pb_log("%s: %s has duplicate MAC address, ignoring\n",
574                                        __func__, interface->name);
575                                 talloc_free(interface);
576                                 return -1;
577                         }
578
579                 list_add(&network->interfaces, &interface->list);
580                 create_interface_dev(network, interface);
581         }
582
583         /* A repeated RTM_NEWLINK can represent an interface name change */
584         if (strncmp(interface->name, ifname, IFNAMSIZ)) {
585                 pb_debug("ifname update: %s -> %s\n", interface->name, ifname);
586                 strncpy(interface->name, ifname, sizeof(interface->name) - 1);
587                 talloc_free(interface->dev->device->id);
588                 interface->dev->device->id =
589                         talloc_strdup(interface->dev->device, ifname);
590         }
591
592         /* notify the sysinfo code about changes to this interface */
593         if (strcmp(interface->name, "lo"))
594                 system_info_register_interface(
595                                 sizeof(interface->hwaddr),
596                                 interface->hwaddr, interface->name,
597                                 info->ifi_flags & IFF_LOWER_UP);
598
599         if (!interface->dev)
600                 create_interface_dev(network, interface);
601
602         if (!interface->ready && strncmp(interface->name, "lo", strlen("lo"))) {
603                 pb_log("%s not marked ready yet\n", interface->name);
604                 return 0;
605         }
606
607         configure_interface(network, interface,
608                         info->ifi_flags & IFF_UP,
609                         info->ifi_flags & IFF_LOWER_UP);
610
611         return 0;
612 }
613
614 void network_mark_interface_ready(struct device_handler *handler,
615                 int ifindex, const char *ifname, uint8_t *mac, int hwsize)
616 {
617         struct network *network = device_handler_get_network(handler);
618         struct interface *interface, *tmp = NULL;
619         char *macstr;
620
621         if (!network) {
622                 pb_log("Network not ready - can not mark interface ready\n");
623                 return;
624         }
625
626         if (hwsize != HWADDR_SIZE)
627                 return;
628
629         if (strncmp(ifname, "lo", strlen("lo")) == 0)
630                 return;
631
632         interface = find_interface_by_ifindex(network, ifindex);
633         if (!interface) {
634                 pb_debug("Creating ready interface %d - %s\n",
635                                 ifindex, ifname);
636                 interface = talloc_zero(network, struct interface);
637                 interface->ifindex = ifindex;
638                 interface->state = IFSTATE_NEW;
639                 memcpy(interface->hwaddr, mac, HWADDR_SIZE);
640                 strncpy(interface->name, ifname, sizeof(interface->name) - 1);
641
642                 list_for_each_entry(&network->interfaces, tmp, list)
643                         if (memcmp(interface->hwaddr, tmp->hwaddr,
644                                    sizeof(interface->hwaddr)) == 0) {
645                                 pb_log("%s: %s has duplicate MAC address, ignoring\n",
646                                        __func__, interface->name);
647                                 talloc_free(interface);
648                                 return;
649                         }
650
651                 list_add(&network->interfaces, &interface->list);
652                 create_interface_dev(network, interface);
653         }
654
655         if (interface->ready) {
656                 pb_log("%s already ready\n", interface->name);
657                 return;
658         }
659
660         if (strncmp(interface->name, ifname, strlen(ifname)) != 0) {
661                 pb_debug("ifname update from udev: %s -> %s\n", interface->name, ifname);
662                 strncpy(interface->name, ifname, sizeof(interface->name) - 1);
663                 talloc_free(interface->dev->device->id);
664                 interface->dev->device->id =
665                         talloc_strdup(interface->dev->device, ifname);
666         }
667
668         if (memcmp(interface->hwaddr, mac, HWADDR_SIZE) != 0) {
669                 macstr = mac_bytes_to_string(interface, mac, hwsize);
670                 pb_log("Warning - new MAC for interface %d does not match: %s\n",
671                                 ifindex, macstr);
672                 talloc_free(macstr);
673         }
674
675         pb_log("Interface %s ready\n", ifname);
676         interface->ready = true;
677         configure_interface(network, interface, false, false);
678 }
679
680 static int network_netlink_process(void *arg)
681 {
682         struct network *network = arg;
683         struct nlmsghdr *nlmsg;
684         struct msghdr msg;
685         struct iovec iov;
686         unsigned int len;
687         int rc, flags;
688
689         memset(&msg, 0, sizeof(msg));
690         msg.msg_iov = &iov;
691         msg.msg_iovlen = 1;
692
693         flags = MSG_PEEK;
694
695 retry:
696         iov.iov_len = network->netlink_buf_size;
697         iov.iov_base = network->netlink_buf;
698
699         rc = recvmsg(network->netlink_sd, &msg, flags);
700
701         if (rc < 0) {
702                 perror("netlink recv header");
703                 return -1;
704         }
705
706         len = rc;
707
708         /* if the netlink message was larger than our buffer, realloc
709          * before reading again */
710         if (len > network->netlink_buf_size || msg.msg_flags & MSG_TRUNC) {
711                 network->netlink_buf_size *= 2;
712                 network->netlink_buf = talloc_realloc(network,
713                                         network->netlink_buf,
714                                         char *,
715                                         network->netlink_buf_size);
716                 goto retry;
717         }
718
719         /* otherwise, we're good to read the entire message without PEEK */
720         if (flags == MSG_PEEK) {
721                 flags = 0;
722                 goto retry;
723         }
724
725         for_each_nlmsg(network->netlink_buf, nlmsg, len)
726                 network_handle_nlmsg(network, nlmsg);
727
728         return 0;
729 }
730
731 static void network_init_dns(struct network *network)
732 {
733         const struct config *config;
734         unsigned int i;
735         int rc, len;
736         bool modified;
737         char *buf;
738
739         if (network->dry_run)
740                 return;
741
742         config = config_get();
743         if (!config || !config->network.n_dns_servers)
744                 return;
745
746         rc = read_file(network, "/etc/resolv.conf", &buf, &len);
747
748         if (rc) {
749                 buf = talloc_strdup(network, "");
750                 len = 0;
751         }
752
753         modified = false;
754
755         for (i = 0; i < config->network.n_dns_servers; i++) {
756                 int dns_conf_len;
757                 char *dns_conf;
758
759                 dns_conf = talloc_asprintf(network, "nameserver %s\n",
760                                 config->network.dns_servers[i]);
761
762                 if (strstr(buf, dns_conf)) {
763                         talloc_free(dns_conf);
764                         continue;
765                 }
766
767                 dns_conf_len = strlen(dns_conf);
768                 buf = talloc_realloc(network, buf, char, len + dns_conf_len + 1);
769                 memcpy(buf + len, dns_conf, dns_conf_len);
770                 len += dns_conf_len;
771                 buf[len] = '\0';
772                 modified = true;
773
774                 talloc_free(dns_conf);
775         }
776
777         if (modified) {
778                 rc = replace_file("/etc/resolv.conf", buf, len);
779                 if (rc)
780                         pb_log("error replacing resolv.conf: %s\n",
781                                         strerror(errno));
782         }
783
784         talloc_free(buf);
785 }
786
787 struct network *network_init(struct device_handler *handler,
788                 struct waitset *waitset, bool dry_run)
789 {
790         struct network *network;
791         int rc;
792
793         network = talloc(handler, struct network);
794         list_init(&network->interfaces);
795         network->handler = handler;
796         network->dry_run = dry_run;
797         network->manual_config = config_get()->network.n_interfaces != 0;
798
799         network_init_dns(network);
800
801         rc = network_init_netlink(network);
802         if (rc)
803                 goto err;
804
805         network->waiter = waiter_register_io(waitset, network->netlink_sd,
806                         WAIT_IN, network_netlink_process, network);
807
808         if (!network->waiter)
809                 goto err;
810
811         rc = network_send_link_query(network);
812         if (rc)
813                 goto err;
814
815         return network;
816
817 err:
818         network_shutdown(network);
819         return NULL;
820 }
821
822 int network_shutdown(struct network *network)
823 {
824         struct interface *interface;
825
826         if (network->waiter)
827                 waiter_remove(network->waiter);
828
829         list_for_each_entry(&network->interfaces, interface, list) {
830                 if (interface->state == IFSTATE_IGNORED)
831                         continue;
832                 if (!strcmp(interface->name, "lo"))
833                         continue;
834                 interface_down(interface);
835         }
836
837         close(network->netlink_sd);
838         talloc_free(network);
839         return 0;
840 }