]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-manager.c
core,logind,networkd: don't pick up devices from udev before they finished udev initi...
[thirdparty/systemd.git] / src / network / networkd-manager.c
CommitLineData
f579559b
TG
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2013 Tom Gundersen <teg@jklm.no>
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22#include "path-util.h"
23#include "networkd.h"
24#include "libudev-private.h"
7b77ed8c 25#include "udev-util.h"
f579559b
TG
26
27int manager_new(Manager **ret) {
28 _cleanup_manager_free_ Manager *m = NULL;
29 int r;
30
31 m = new0(Manager, 1);
32 if (!m)
33 return -ENOMEM;
34
afc6adb5 35 r = sd_event_default(&m->event);
f579559b
TG
36 if (r < 0)
37 return r;
38
cde93897
LP
39 sd_event_set_watchdog(m->event, true);
40
dd3efc09 41 r = sd_rtnl_open(RTMGRP_LINK | RTMGRP_IPV4_IFADDR, &m->rtnl);
f579559b
TG
42 if (r < 0)
43 return r;
44
45 m->udev = udev_new();
46 if (!m->udev)
47 return -ENOMEM;
48
49 m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
50 if (!m->udev_monitor)
51 return -ENOMEM;
52
53 m->links = hashmap_new(uint64_hash_func, uint64_compare_func);
54 if (!m->links)
55 return -ENOMEM;
56
02b59d57
TG
57 m->bridges = hashmap_new(string_hash_func, string_compare_func);
58 if (!m->bridges)
59 return -ENOMEM;
60
f579559b
TG
61 LIST_HEAD_INIT(m->networks);
62
63 m->network_dirs = strv_new("/etc/systemd/network/",
64 "/run/systemd/network/",
65 "/usr/lib/systemd/network",
66#ifdef HAVE_SPLIT_USER
67 "/lib/systemd/network",
68#endif
69 NULL);
70 if (!m->network_dirs)
71 return -ENOMEM;
72
73 if (!path_strv_canonicalize_uniq(m->network_dirs))
74 return -ENOMEM;
75
76 *ret = m;
77 m = NULL;
78
79 return 0;
80}
81
82void manager_free(Manager *m) {
0617ffab 83 Network *network;
02b59d57 84 Bridge *bridge;
0617ffab
TG
85 Link *link;
86
f579559b
TG
87 udev_monitor_unref(m->udev_monitor);
88 udev_unref(m->udev);
89 sd_event_source_unref(m->udev_event_source);
90 sd_event_unref(m->event);
0617ffab
TG
91
92 while ((network = m->networks))
93 network_free(network);
94
95 while ((link = hashmap_first(m->links)))
96 link_free(link);
f579559b 97 hashmap_free(m->links);
0617ffab 98
02b59d57
TG
99 while ((bridge = hashmap_first(m->bridges)))
100 bridge_free(bridge);
101 hashmap_free(m->bridges);
102
f579559b
TG
103 strv_free(m->network_dirs);
104 sd_rtnl_unref(m->rtnl);
105
106 free(m);
107}
108
02b59d57
TG
109int manager_load_config(Manager *m) {
110 int r;
111
112 /* update timestamp */
113 paths_check_timestamp(m->network_dirs, &m->network_dirs_ts_usec, true);
114
115 r = bridge_load(m);
116 if (r < 0)
117 return r;
118
119 r = network_load(m);
120 if (r < 0)
121 return r;
122
123 return 0;
124}
125
126bool manager_should_reload(Manager *m) {
127 return paths_check_timestamp(m->network_dirs, &m->network_dirs_ts_usec, false);
128}
129
f579559b
TG
130static int manager_process_link(Manager *m, struct udev_device *device) {
131 Link *link;
132 int r;
133
134 if (streq_ptr(udev_device_get_action(device), "remove")) {
135 uint64_t ifindex;
136
002f5de9
TG
137 log_debug("Link removed: %s", udev_device_get_sysname(device));
138
f579559b
TG
139 ifindex = udev_device_get_ifindex(device);
140 link = hashmap_get(m->links, &ifindex);
141 if (!link)
142 return 0;
143
144 link_free(link);
145 } else {
002f5de9
TG
146 log_debug("New link: %s", udev_device_get_sysname(device));
147
f579559b
TG
148 r = link_add(m, device);
149 if (r < 0) {
150 log_error("Could not handle link %s: %s",
151 udev_device_get_sysname(device),
152 strerror(-r));
153 }
154 }
155
156 return 0;
157}
158
159int manager_udev_enumerate_links(Manager *m) {
bf5332d2 160 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
f579559b 161 struct udev_list_entry *item = NULL, *first = NULL;
f579559b
TG
162 int r;
163
164 assert(m);
165
166 e = udev_enumerate_new(m->udev);
bf5332d2
LP
167 if (!e)
168 return -ENOMEM;
f579559b
TG
169
170 r = udev_enumerate_add_match_subsystem(e, "net");
171 if (r < 0)
bf5332d2 172 return r;
f579559b 173
f579559b
TG
174 r = udev_enumerate_scan_devices(e);
175 if (r < 0)
bf5332d2 176 return r;
f579559b
TG
177
178 first = udev_enumerate_get_list_entry(e);
179 udev_list_entry_foreach(item, first) {
bf5332d2 180 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
f579559b
TG
181 int k;
182
183 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
bf5332d2
LP
184 if (!d)
185 return -ENOMEM;
f579559b 186
bf5332d2
LP
187 if (!udev_device_get_is_initialized(d))
188 continue;
f579559b 189
bf5332d2 190 k = manager_process_link(m, d);
f579559b
TG
191 if (k < 0)
192 r = k;
193 }
194
f579559b
TG
195 return r;
196}
197
198static int manager_dispatch_link_udev(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
199 Manager *m = userdata;
200 struct udev_monitor *monitor = m->udev_monitor;
7b77ed8c 201 _cleanup_udev_device_unref_ struct udev_device *device = NULL;
f579559b
TG
202
203 device = udev_monitor_receive_device(monitor);
204 if (!device)
205 return -ENOMEM;
206
7b77ed8c 207 manager_process_link(m, device);
f579559b
TG
208 return 0;
209}
210
211int manager_udev_listen(Manager *m) {
212 int r;
213
214 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_monitor, "net", NULL);
215 if (r < 0) {
216 log_error("Could not add udev monitor filter: %s", strerror(-r));
217 return r;
218 }
219
f579559b
TG
220 r = udev_monitor_enable_receiving(m->udev_monitor);
221 if (r < 0) {
222 log_error("Could not enable udev monitor");
223 return r;
224 }
225
226 r = sd_event_add_io(m->event,
227 udev_monitor_get_fd(m->udev_monitor),
228 EPOLLIN, manager_dispatch_link_udev,
229 m, &m->udev_event_source);
230 if (r < 0)
231 return r;
232
233 return 0;
234}
f882c247 235
dd3efc09
TG
236static int manager_rtnl_process_link(sd_rtnl *rtnl, sd_rtnl_message *message, void *userdata) {
237 Manager *m = userdata;
238 Link *link;
dd3efc09
TG
239 int r, ifindex;
240
241 r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
242 if (r < 0)
243 return 0;
244
245 link = hashmap_get(m->links, &ifindex);
246 if (!link)
247 return 0;
248
22936833 249 r = link_update(link, message);
dd3efc09
TG
250 if (r < 0)
251 return 0;
252
253 return 1;
254}
255
f882c247
TG
256int manager_rtnl_listen(Manager *m) {
257 int r;
258
259 r = sd_rtnl_attach_event(m->rtnl, m->event, 0);
260 if (r < 0)
261 return r;
262
dd3efc09
TG
263 r = sd_rtnl_add_match(m->rtnl, RTM_NEWLINK, &manager_rtnl_process_link, m);
264 if (r < 0)
265 return r;
266
f882c247
TG
267 return 0;
268}