1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Tom Gundersen <teg@jklm.no>
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.
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.
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/>.
23 #include "network-internal.h"
24 #include "path-util.h"
25 #include "conf-files.h"
26 #include "conf-parser.h"
29 static int network_load_one(Manager *manager, const char *filename) {
30 _cleanup_network_free_ Network *network = NULL;
31 _cleanup_fclose_ FILE *file = NULL;
39 file = fopen(filename, "re");
47 if (null_or_empty_path(filename)) {
48 log_debug("skipping empty file: %s", filename);
52 network = new0(Network, 1);
56 network->manager = manager;
58 LIST_HEAD_INIT(network->static_addresses);
59 LIST_HEAD_INIT(network->static_routes);
61 network->vlans = hashmap_new(string_hash_func, string_compare_func);
65 network->macvlans = hashmap_new(uint64_hash_func, uint64_compare_func);
66 if (!network->macvlans)
69 network->addresses_by_section = hashmap_new(uint64_hash_func, uint64_compare_func);
70 if (!network->addresses_by_section)
73 network->routes_by_section = hashmap_new(uint64_hash_func, uint64_compare_func);
74 if (!network->routes_by_section)
77 network->dns = set_new(NULL, NULL);
81 network->filename = strdup(filename);
82 if (!network->filename)
85 network->dhcp_dns = true;
86 network->dhcp_hostname = true;
87 network->dhcp_domainname = true;
89 r = config_parse(NULL, filename, file, "Match\0Network\0Address\0Route\0DHCPv4\0", config_item_perf_lookup,
90 (void*) network_network_gperf_lookup, false, false, network);
92 log_warning("Could not parse config file %s: %s", filename, strerror(-r));
96 LIST_PREPEND(networks, manager->networks, network);
98 LIST_FOREACH(static_routes, route, network->static_routes) {
100 log_warning("Route section without Gateway field configured in %s. "
101 "Ignoring", filename);
106 LIST_FOREACH(static_addresses, address, network->static_addresses) {
107 if (!address->family) {
108 log_warning("Address section without Address field configured in %s. "
109 "Ignoring", filename);
119 int network_load(Manager *manager) {
121 _cleanup_strv_free_ char **files = NULL;
127 while ((network = manager->networks))
128 network_free(network);
130 r = conf_files_list_strv(&files, ".network", NULL, network_dirs);
132 log_error("Failed to enumerate network files: %s", strerror(-r));
136 STRV_FOREACH_BACKWARDS(f, files) {
137 r = network_load_one(manager, *f);
145 void network_free(Network *network) {
153 free(network->filename);
155 free(network->match_mac);
156 free(network->match_path);
157 free(network->match_driver);
158 free(network->match_type);
159 free(network->match_name);
161 free(network->description);
163 SET_FOREACH(address, network->dns, i)
164 address_free(address);
166 set_free(network->dns);
168 hashmap_free(network->vlans);
170 hashmap_free(network->macvlans);
172 while ((route = network->static_routes))
175 while ((address = network->static_addresses))
176 address_free(address);
178 hashmap_free(network->addresses_by_section);
179 hashmap_free(network->routes_by_section);
181 if (network->manager && network->manager->networks)
182 LIST_REMOVE(networks, network->manager->networks, network);
184 condition_free_list(network->match_host);
185 condition_free_list(network->match_virt);
186 condition_free_list(network->match_kernel);
187 condition_free_list(network->match_arch);
192 int network_get(Manager *manager, struct udev_device *device,
193 const char *ifname, const struct ether_addr *address,
200 LIST_FOREACH(networks, network, manager->networks) {
201 if (net_match_config(network->match_mac, network->match_path,
202 network->match_driver, network->match_type,
203 network->match_name, network->match_host,
204 network->match_virt, network->match_kernel,
207 udev_device_get_property_value(device, "ID_PATH"),
208 udev_device_get_driver(udev_device_get_parent(device)),
209 udev_device_get_property_value(device, "ID_NET_DRIVER"),
210 udev_device_get_devtype(device),
212 log_debug("%s: found matching network '%s'", ifname,
224 int network_apply(Manager *manager, Network *network, Link *link) {
227 link->network = network;
230 r = manager_update_resolv_conf(manager);
238 int config_parse_bridge(const char *unit,
239 const char *filename,
242 unsigned section_line,
248 Network *network = userdata;
257 r = netdev_get(network->manager, rvalue, &netdev);
259 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
260 "Bridge is invalid, ignoring assignment: %s", rvalue);
264 if (netdev->kind != NETDEV_KIND_BRIDGE) {
265 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
266 "NetDev is not a bridge, ignoring assignment: %s", rvalue);
270 network->bridge = netdev;
275 int config_parse_bond(const char *unit,
276 const char *filename,
279 unsigned section_line,
285 Network *network = userdata;
294 r = netdev_get(network->manager, rvalue, &netdev);
296 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
297 "Bond is invalid, ignoring assignment: %s", rvalue);
301 if (netdev->kind != NETDEV_KIND_BOND) {
302 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
303 "NetDev is not a bond, ignoring assignment: %s", rvalue);
307 network->bond = netdev;
312 int config_parse_vlan(const char *unit,
313 const char *filename,
316 unsigned section_line,
322 Network *network = userdata;
331 r = netdev_get(network->manager, rvalue, &netdev);
333 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
334 "VLAN is invalid, ignoring assignment: %s", rvalue);
338 if (netdev->kind != NETDEV_KIND_VLAN) {
339 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
340 "NetDev is not a VLAN, ignoring assignment: %s", rvalue);
344 r = hashmap_put(network->vlans, &netdev->vlanid, netdev);
346 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
347 "Can not add VLAN to network: %s", rvalue);
354 int config_parse_macvlan(const char *unit,
355 const char *filename,
358 unsigned section_line,
364 Network *network = userdata;
373 r = netdev_get(network->manager, rvalue, &netdev);
375 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
376 "MACVLAN is invalid, ignoring assignment: %s", rvalue);
380 if (netdev->kind != NETDEV_KIND_MACVLAN) {
381 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
382 "NetDev is not a MACVLAN, ignoring assignment: %s", rvalue);
386 r = hashmap_put(network->macvlans, netdev->name, netdev);
388 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
389 "Can not add MACVLAN to network: %s", rvalue);