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