]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-network.c
networkd: netdev - fix error handling in set_ifindex()
[thirdparty/systemd.git] / src / network / networkd-network.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 "networkd.h"
c6f7c917 23#include "network-internal.h"
f579559b
TG
24#include "path-util.h"
25#include "conf-files.h"
26#include "conf-parser.h"
477e73b5 27#include "util.h"
f579559b
TG
28
29static int network_load_one(Manager *manager, const char *filename) {
30 _cleanup_network_free_ Network *network = NULL;
31 _cleanup_fclose_ FILE *file = NULL;
b3070dc0
TG
32 Route *route;
33 Address *address;
f579559b
TG
34 int r;
35
bf1bc670
TA
36 assert(manager);
37 assert(filename);
38
f579559b
TG
39 file = fopen(filename, "re");
40 if (!file) {
41 if (errno == ENOENT)
42 return 0;
43 else
44 return errno;
45 }
46
47 network = new0(Network, 1);
48 if (!network)
49 return log_oom();
50
5a3eb5a7
TG
51 network->manager = manager;
52
f048a16b
TG
53 LIST_HEAD_INIT(network->static_addresses);
54 LIST_HEAD_INIT(network->static_routes);
f579559b 55
fe6b2d55 56 network->vlans = hashmap_new(string_hash_func, string_compare_func);
672682a6
TG
57 if (!network->vlans)
58 return log_oom();
59
fe6b2d55
TG
60 network->macvlans = hashmap_new(uint64_hash_func, uint64_compare_func);
61 if (!network->macvlans)
62 return log_oom();
63
6ae115c1
TG
64 network->addresses_by_section = hashmap_new(uint64_hash_func, uint64_compare_func);
65 if (!network->addresses_by_section)
66 return log_oom();
67
68 network->routes_by_section = hashmap_new(uint64_hash_func, uint64_compare_func);
69 if (!network->routes_by_section)
70 return log_oom();
71
06f021a8
TG
72 network->dns = set_new(NULL, NULL);
73 if (!network->dns)
74 return log_oom();
75
6ae115c1
TG
76 network->filename = strdup(filename);
77 if (!network->filename)
78 return log_oom();
79
5be4d38e 80 network->dhcp_dns = true;
1346b1f0 81 network->dhcp_hostname = true;
039ebe6a 82 network->dhcp_domainname = true;
5be4d38e
TG
83
84 r = config_parse(NULL, filename, file, "Match\0Network\0Address\0Route\0DHCPv4\0", config_item_perf_lookup,
c0dda186 85 (void*) network_network_gperf_lookup, false, false, network);
f579559b
TG
86 if (r < 0) {
87 log_warning("Could not parse config file %s: %s", filename, strerror(-r));
88 return r;
449f7554 89 }
f579559b 90
f579559b 91 LIST_PREPEND(networks, manager->networks, network);
b3070dc0
TG
92
93 LIST_FOREACH(static_routes, route, network->static_routes) {
94 if (!route->family) {
95 log_warning("Route section without Gateway field configured in %s. "
96 "Ignoring", filename);
97 return 0;
98 }
b3070dc0
TG
99 }
100
101 LIST_FOREACH(static_addresses, address, network->static_addresses) {
102 if (!address->family) {
103 log_warning("Address section without Address field configured in %s. "
104 "Ignoring", filename);
105 return 0;
106 }
107 }
108
f579559b
TG
109 network = NULL;
110
111 return 0;
112}
113
114int network_load(Manager *manager) {
115 Network *network;
477e73b5
ZJS
116 _cleanup_strv_free_ char **files = NULL;
117 char **f;
f579559b
TG
118 int r;
119
120 assert(manager);
121
122 while ((network = manager->networks))
123 network_free(network);
124
2ad8416d 125 r = conf_files_list_strv(&files, ".network", NULL, network_dirs);
f579559b 126 if (r < 0) {
449f7554 127 log_error("Failed to enumerate network files: %s", strerror(-r));
f579559b
TG
128 return r;
129 }
130
131 STRV_FOREACH_BACKWARDS(f, files) {
132 r = network_load_one(manager, *f);
133 if (r < 0)
134 return r;
135 }
136
f579559b
TG
137 return 0;
138}
139
f579559b
TG
140void network_free(Network *network) {
141 Route *route;
142 Address *address;
06f021a8 143 Iterator i;
f579559b
TG
144
145 if (!network)
146 return;
147
148 free(network->filename);
149
150 free(network->match_mac);
151 free(network->match_path);
152 free(network->match_driver);
153 free(network->match_type);
154 free(network->match_name);
155
156 free(network->description);
157
06f021a8
TG
158 SET_FOREACH(address, network->dns, i)
159 address_free(address);
160
161 set_free(network->dns);
3bef724f 162
672682a6
TG
163 hashmap_free(network->vlans);
164
fe6b2d55
TG
165 hashmap_free(network->macvlans);
166
f048a16b 167 while ((route = network->static_routes))
f579559b
TG
168 route_free(route);
169
f048a16b 170 while ((address = network->static_addresses))
f579559b
TG
171 address_free(address);
172
6ae115c1
TG
173 hashmap_free(network->addresses_by_section);
174 hashmap_free(network->routes_by_section);
175
b3070dc0 176 if (network->manager && network->manager->networks)
7384fa92 177 LIST_REMOVE(networks, network->manager->networks, network);
f579559b
TG
178
179 free(network);
180}
181
182int network_get(Manager *manager, struct udev_device *device, Network **ret) {
183 Network *network;
184
185 assert(manager);
186 assert(device);
187 assert(ret);
188
f579559b
TG
189 LIST_FOREACH(networks, network, manager->networks) {
190 if (net_match_config(network->match_mac, network->match_path,
191 network->match_driver, network->match_type,
2cc412b5
TG
192 network->match_name, network->match_host,
193 network->match_virt, network->match_kernel,
edbb03e9 194 network->match_arch,
f579559b
TG
195 udev_device_get_sysattr_value(device, "address"),
196 udev_device_get_property_value(device, "ID_PATH"),
9b1c2626 197 udev_device_get_driver(udev_device_get_parent(device)),
bf175aaf 198 udev_device_get_property_value(device, "ID_NET_DRIVER"),
f579559b
TG
199 udev_device_get_devtype(device),
200 udev_device_get_sysname(device))) {
449f7554
TG
201 log_debug("%s: found matching network '%s'",
202 udev_device_get_sysname(device),
203 network->filename);
f579559b
TG
204 *ret = network;
205 return 0;
206 }
207 }
208
209 *ret = NULL;
210
211 return -ENOENT;
212}
213
214int network_apply(Manager *manager, Network *network, Link *link) {
f579559b
TG
215 int r;
216
f579559b
TG
217 link->network = network;
218
3bef724f
TG
219 if (network->dns) {
220 r = manager_update_resolv_conf(manager);
221 if (r < 0)
222 return r;
223 }
224
f579559b
TG
225 return 0;
226}
02b59d57
TG
227
228int config_parse_bridge(const char *unit,
229 const char *filename,
230 unsigned line,
231 const char *section,
232 unsigned section_line,
233 const char *lvalue,
234 int ltype,
235 const char *rvalue,
236 void *data,
237 void *userdata) {
238 Network *network = userdata;
1a436809 239 NetDev *netdev;
02b59d57
TG
240 int r;
241
242 assert(filename);
243 assert(lvalue);
244 assert(rvalue);
245 assert(data);
246
52433f6b 247 r = netdev_get(network->manager, rvalue, &netdev);
02b59d57
TG
248 if (r < 0) {
249 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
250 "Bridge is invalid, ignoring assignment: %s", rvalue);
251 return 0;
252 }
253
52433f6b
TG
254 if (netdev->kind != NETDEV_KIND_BRIDGE) {
255 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1a436809 256 "NetDev is not a bridge, ignoring assignment: %s", rvalue);
52433f6b
TG
257 return 0;
258 }
259
260 network->bridge = netdev;
261
262 return 0;
263}
264
265int config_parse_bond(const char *unit,
266 const char *filename,
267 unsigned line,
268 const char *section,
269 unsigned section_line,
270 const char *lvalue,
271 int ltype,
272 const char *rvalue,
273 void *data,
274 void *userdata) {
275 Network *network = userdata;
1a436809 276 NetDev *netdev;
52433f6b
TG
277 int r;
278
279 assert(filename);
280 assert(lvalue);
281 assert(rvalue);
282 assert(data);
283
284 r = netdev_get(network->manager, rvalue, &netdev);
285 if (r < 0) {
286 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
287 "Bond is invalid, ignoring assignment: %s", rvalue);
288 return 0;
289 }
290
291 if (netdev->kind != NETDEV_KIND_BOND) {
292 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1a436809 293 "NetDev is not a bond, ignoring assignment: %s", rvalue);
52433f6b
TG
294 return 0;
295 }
296
297 network->bond = netdev;
02b59d57
TG
298
299 return 0;
300}
54abf461
TG
301
302int config_parse_vlan(const char *unit,
303 const char *filename,
304 unsigned line,
305 const char *section,
306 unsigned section_line,
307 const char *lvalue,
308 int ltype,
309 const char *rvalue,
310 void *data,
311 void *userdata) {
312 Network *network = userdata;
1a436809 313 NetDev *netdev;
54abf461
TG
314 int r;
315
316 assert(filename);
317 assert(lvalue);
318 assert(rvalue);
319 assert(data);
320
321 r = netdev_get(network->manager, rvalue, &netdev);
322 if (r < 0) {
323 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
324 "VLAN is invalid, ignoring assignment: %s", rvalue);
325 return 0;
326 }
327
328 if (netdev->kind != NETDEV_KIND_VLAN) {
329 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1a436809 330 "NetDev is not a VLAN, ignoring assignment: %s", rvalue);
54abf461
TG
331 return 0;
332 }
333
672682a6
TG
334 r = hashmap_put(network->vlans, &netdev->vlanid, netdev);
335 if (r < 0) {
336 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
337 "Can not add VLAN to network: %s", rvalue);
338 return 0;
339 }
54abf461
TG
340
341 return 0;
342}
fe6b2d55
TG
343
344int config_parse_macvlan(const char *unit,
345 const char *filename,
346 unsigned line,
347 const char *section,
348 unsigned section_line,
349 const char *lvalue,
350 int ltype,
351 const char *rvalue,
352 void *data,
353 void *userdata) {
354 Network *network = userdata;
355 NetDev *netdev;
356 int r;
357
358 assert(filename);
359 assert(lvalue);
360 assert(rvalue);
361 assert(data);
362
363 r = netdev_get(network->manager, rvalue, &netdev);
364 if (r < 0) {
365 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
366 "MACVLAN is invalid, ignoring assignment: %s", rvalue);
367 return 0;
368 }
369
370 if (netdev->kind != NETDEV_KIND_MACVLAN) {
371 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
372 "NetDev is not a MACVLAN, ignoring assignment: %s", rvalue);
373 return 0;
374 }
375
376 r = hashmap_put(network->macvlans, netdev->name, netdev);
377 if (r < 0) {
378 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
379 "Can not add MACVLAN to network: %s", rvalue);
380 return 0;
381 }
382
383 return 0;
384}