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