]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-manager.c
networkd: add a basic network daemon
[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
34 r = sd_event_new(&m->event);
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) {
76 udev_monitor_unref(m->udev_monitor);
77 udev_unref(m->udev);
78 sd_event_source_unref(m->udev_event_source);
79 sd_event_unref(m->event);
80 hashmap_free(m->links);
81 strv_free(m->network_dirs);
82 sd_rtnl_unref(m->rtnl);
83
84 free(m);
85}
86
87static int manager_process_link(Manager *m, struct udev_device *device) {
88 Link *link;
89 int r;
90
91 if (streq_ptr(udev_device_get_action(device), "remove")) {
92 uint64_t ifindex;
93
94 ifindex = udev_device_get_ifindex(device);
95 link = hashmap_get(m->links, &ifindex);
96 if (!link)
97 return 0;
98
99 link_free(link);
100 } else {
101 r = link_add(m, device);
102 if (r < 0) {
103 log_error("Could not handle link %s: %s",
104 udev_device_get_sysname(device),
105 strerror(-r));
106 }
107 }
108
109 return 0;
110}
111
112int manager_udev_enumerate_links(Manager *m) {
113 struct udev_list_entry *item = NULL, *first = NULL;
114 struct udev_enumerate *e;
115 int r;
116
117 assert(m);
118
119 e = udev_enumerate_new(m->udev);
120 if (!e) {
121 r = -ENOMEM;
122 goto finish;
123 }
124
125 r = udev_enumerate_add_match_subsystem(e, "net");
126 if (r < 0)
127 goto finish;
128
129 r = udev_enumerate_add_match_tag(e, "systemd-networkd");
130 if (r < 0)
131 goto finish;
132
133 r = udev_enumerate_scan_devices(e);
134 if (r < 0)
135 goto finish;
136
137 first = udev_enumerate_get_list_entry(e);
138 udev_list_entry_foreach(item, first) {
139 struct udev_device *d;
140 int k;
141
142 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
143 if (!d) {
144 r = -ENOMEM;
145 goto finish;
146 }
147
148 k = manager_process_link(m, d);
149 udev_device_unref(d);
150
151 if (k < 0)
152 r = k;
153 }
154
155finish:
156 if (e)
157 udev_enumerate_unref(e);
158
159 return r;
160}
161
162static int manager_dispatch_link_udev(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
163 Manager *m = userdata;
164 struct udev_monitor *monitor = m->udev_monitor;
165 struct udev_device *device;
166 int r;
167
168 device = udev_monitor_receive_device(monitor);
169 if (!device)
170 return -ENOMEM;
171
172 r = manager_process_link(m, device);
173 if (r < 0)
174 return r;
175
176 udev_device_unref(device);
177
178 return 0;
179}
180
181int manager_udev_listen(Manager *m) {
182 int r;
183
184 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_monitor, "net", NULL);
185 if (r < 0) {
186 log_error("Could not add udev monitor filter: %s", strerror(-r));
187 return r;
188 }
189
190 r = udev_monitor_filter_add_match_tag(m->udev_monitor, "systemd-networkd");
191 if (r < 0) {
192 log_error("Could not add udev monitor filter: %s", strerror(-r));
193 return r;
194 }
195
196 r = udev_monitor_enable_receiving(m->udev_monitor);
197 if (r < 0) {
198 log_error("Could not enable udev monitor");
199 return r;
200 }
201
202 r = sd_event_add_io(m->event,
203 udev_monitor_get_fd(m->udev_monitor),
204 EPOLLIN, manager_dispatch_link_udev,
205 m, &m->udev_event_source);
206 if (r < 0)
207 return r;
208
209 return 0;
210}