]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-manager.c
networkd: improve link state change logging
[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
449f7554 137 log_debug("%s: link removed", udev_device_get_sysname(device));
002f5de9 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 {
449f7554 146 log_debug("%s: link added", udev_device_get_sysname(device));
002f5de9 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
e1202047
LP
174 r = udev_enumerate_add_match_is_initialized(e);
175 if (r < 0)
176 return r;
177
f579559b
TG
178 r = udev_enumerate_scan_devices(e);
179 if (r < 0)
bf5332d2 180 return r;
f579559b
TG
181
182 first = udev_enumerate_get_list_entry(e);
183 udev_list_entry_foreach(item, first) {
bf5332d2 184 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
f579559b
TG
185 int k;
186
187 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
bf5332d2
LP
188 if (!d)
189 return -ENOMEM;
f579559b 190
bf5332d2 191 k = manager_process_link(m, d);
f579559b
TG
192 if (k < 0)
193 r = k;
194 }
195
f579559b
TG
196 return r;
197}
198
199static int manager_dispatch_link_udev(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
200 Manager *m = userdata;
201 struct udev_monitor *monitor = m->udev_monitor;
7b77ed8c 202 _cleanup_udev_device_unref_ struct udev_device *device = NULL;
f579559b
TG
203
204 device = udev_monitor_receive_device(monitor);
205 if (!device)
206 return -ENOMEM;
207
7b77ed8c 208 manager_process_link(m, device);
f579559b
TG
209 return 0;
210}
211
212int manager_udev_listen(Manager *m) {
213 int r;
214
215 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_monitor, "net", NULL);
216 if (r < 0) {
217 log_error("Could not add udev monitor filter: %s", strerror(-r));
218 return r;
219 }
220
f579559b
TG
221 r = udev_monitor_enable_receiving(m->udev_monitor);
222 if (r < 0) {
223 log_error("Could not enable udev monitor");
224 return r;
225 }
226
227 r = sd_event_add_io(m->event,
228 udev_monitor_get_fd(m->udev_monitor),
229 EPOLLIN, manager_dispatch_link_udev,
230 m, &m->udev_event_source);
231 if (r < 0)
232 return r;
233
234 return 0;
235}
f882c247 236
dd3efc09
TG
237static int manager_rtnl_process_link(sd_rtnl *rtnl, sd_rtnl_message *message, void *userdata) {
238 Manager *m = userdata;
239 Link *link;
dd3efc09
TG
240 int r, ifindex;
241
242 r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
d0d311d6
TG
243 if (r < 0) {
244 log_debug("received RTM_NEWLINK message without valid ifindex");
dd3efc09 245 return 0;
d0d311d6 246 }
dd3efc09
TG
247
248 link = hashmap_get(m->links, &ifindex);
d0d311d6
TG
249 if (!link) {
250 log_debug("received RTM_NEWLINK message for ifindex we are not tracking (%d)", ifindex);
dd3efc09 251 return 0;
d0d311d6 252 }
dd3efc09 253
06a6e593
TG
254 /* only track the status of links we want to manage */
255 if (link->network) {
256 r = link_update(link, message);
257 if (r < 0)
258 return 0;
d0d311d6
TG
259 } else
260 log_debug("received RTM_NEWLINK message for link we are not managing (%d)", ifindex);
dd3efc09
TG
261
262 return 1;
263}
264
f882c247
TG
265int manager_rtnl_listen(Manager *m) {
266 int r;
267
268 r = sd_rtnl_attach_event(m->rtnl, m->event, 0);
269 if (r < 0)
270 return r;
271
dd3efc09
TG
272 r = sd_rtnl_add_match(m->rtnl, RTM_NEWLINK, &manager_rtnl_process_link, m);
273 if (r < 0)
274 return r;
275
f882c247
TG
276 return 0;
277}