]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-manager.c
networkd: minor fixes
[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"
25
26int manager_new(Manager **ret) {
27 _cleanup_manager_free_ Manager *m = NULL;
28 int r;
29
30 m = new0(Manager, 1);
31 if (!m)
32 return -ENOMEM;
33
afc6adb5 34 r = sd_event_default(&m->event);
f579559b
TG
35 if (r < 0)
36 return r;
37
38 r = sd_rtnl_open(0, &m->rtnl);
39 if (r < 0)
40 return r;
41
42 m->udev = udev_new();
43 if (!m->udev)
44 return -ENOMEM;
45
46 m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
47 if (!m->udev_monitor)
48 return -ENOMEM;
49
50 m->links = hashmap_new(uint64_hash_func, uint64_compare_func);
51 if (!m->links)
52 return -ENOMEM;
53
54 LIST_HEAD_INIT(m->networks);
55
56 m->network_dirs = strv_new("/etc/systemd/network/",
57 "/run/systemd/network/",
58 "/usr/lib/systemd/network",
59#ifdef HAVE_SPLIT_USER
60 "/lib/systemd/network",
61#endif
62 NULL);
63 if (!m->network_dirs)
64 return -ENOMEM;
65
66 if (!path_strv_canonicalize_uniq(m->network_dirs))
67 return -ENOMEM;
68
69 *ret = m;
70 m = NULL;
71
72 return 0;
73}
74
75void manager_free(Manager *m) {
0617ffab
TG
76 Network *network;
77 Link *link;
78
f579559b
TG
79 udev_monitor_unref(m->udev_monitor);
80 udev_unref(m->udev);
81 sd_event_source_unref(m->udev_event_source);
82 sd_event_unref(m->event);
0617ffab
TG
83
84 while ((network = m->networks))
85 network_free(network);
86
87 while ((link = hashmap_first(m->links)))
88 link_free(link);
f579559b 89 hashmap_free(m->links);
0617ffab 90
f579559b
TG
91 strv_free(m->network_dirs);
92 sd_rtnl_unref(m->rtnl);
93
94 free(m);
95}
96
97static int manager_process_link(Manager *m, struct udev_device *device) {
98 Link *link;
99 int r;
100
101 if (streq_ptr(udev_device_get_action(device), "remove")) {
102 uint64_t ifindex;
103
002f5de9
TG
104 log_debug("Link removed: %s", udev_device_get_sysname(device));
105
f579559b
TG
106 ifindex = udev_device_get_ifindex(device);
107 link = hashmap_get(m->links, &ifindex);
108 if (!link)
109 return 0;
110
111 link_free(link);
112 } else {
002f5de9
TG
113 log_debug("New link: %s", udev_device_get_sysname(device));
114
f579559b
TG
115 r = link_add(m, device);
116 if (r < 0) {
117 log_error("Could not handle link %s: %s",
118 udev_device_get_sysname(device),
119 strerror(-r));
120 }
121 }
122
123 return 0;
124}
125
126int manager_udev_enumerate_links(Manager *m) {
127 struct udev_list_entry *item = NULL, *first = NULL;
128 struct udev_enumerate *e;
129 int r;
130
131 assert(m);
132
133 e = udev_enumerate_new(m->udev);
134 if (!e) {
135 r = -ENOMEM;
136 goto finish;
137 }
138
139 r = udev_enumerate_add_match_subsystem(e, "net");
140 if (r < 0)
141 goto finish;
142
f579559b
TG
143 r = udev_enumerate_scan_devices(e);
144 if (r < 0)
145 goto finish;
146
147 first = udev_enumerate_get_list_entry(e);
148 udev_list_entry_foreach(item, first) {
149 struct udev_device *d;
150 int k;
151
152 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
153 if (!d) {
154 r = -ENOMEM;
155 goto finish;
156 }
157
158 k = manager_process_link(m, d);
159 udev_device_unref(d);
160
161 if (k < 0)
162 r = k;
163 }
164
165finish:
166 if (e)
167 udev_enumerate_unref(e);
168
169 return r;
170}
171
172static int manager_dispatch_link_udev(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
173 Manager *m = userdata;
174 struct udev_monitor *monitor = m->udev_monitor;
175 struct udev_device *device;
176 int r;
177
178 device = udev_monitor_receive_device(monitor);
179 if (!device)
180 return -ENOMEM;
181
182 r = manager_process_link(m, device);
183 if (r < 0)
184 return r;
185
186 udev_device_unref(device);
187
188 return 0;
189}
190
191int manager_udev_listen(Manager *m) {
192 int r;
193
194 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_monitor, "net", NULL);
195 if (r < 0) {
196 log_error("Could not add udev monitor filter: %s", strerror(-r));
197 return r;
198 }
199
f579559b
TG
200 r = udev_monitor_enable_receiving(m->udev_monitor);
201 if (r < 0) {
202 log_error("Could not enable udev monitor");
203 return r;
204 }
205
206 r = sd_event_add_io(m->event,
207 udev_monitor_get_fd(m->udev_monitor),
208 EPOLLIN, manager_dispatch_link_udev,
209 m, &m->udev_event_source);
210 if (r < 0)
211 return r;
212
213 return 0;
214}
f882c247
TG
215
216int manager_rtnl_listen(Manager *m) {
217 int r;
218
219 r = sd_rtnl_attach_event(m->rtnl, m->event, 0);
220 if (r < 0)
221 return r;
222
223 return 0;
224}