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