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/>.
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 network = new0(Network, 1);
51 network->manager = manager;
53 LIST_HEAD_INIT(network->static_addresses);
54 LIST_HEAD_INIT(network->static_routes);
56 network->vlans = hashmap_new(string_hash_func, string_compare_func);
60 network->macvlans = hashmap_new(uint64_hash_func, uint64_compare_func);
61 if (!network->macvlans)
64 network->addresses_by_section = hashmap_new(uint64_hash_func, uint64_compare_func);
65 if (!network->addresses_by_section)
68 network->routes_by_section = hashmap_new(uint64_hash_func, uint64_compare_func);
69 if (!network->routes_by_section)
72 network->dns = set_new(NULL, NULL);
76 network->filename = strdup(filename);
77 if (!network->filename)
80 network->dhcp_dns = true;
81 network->dhcp_hostname = true;
82 network->dhcp_domainname = true;
84 r = config_parse(NULL, filename, file, "Match\0Network\0Address\0Route\0DHCPv4\0", config_item_perf_lookup,
85 (void*) network_network_gperf_lookup, false, false, network);
87 log_warning("Could not parse config file %s: %s", filename, strerror(-r));
91 LIST_PREPEND(networks, manager->networks, network);
93 LIST_FOREACH(static_routes, route, network->static_routes) {
95 log_warning("Route section without Gateway field configured in %s. "
96 "Ignoring", filename);
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);
114 int network_load(Manager *manager) {
116 _cleanup_strv_free_ char **files = NULL;
122 while ((network = manager->networks))
123 network_free(network);
125 r = conf_files_list_strv(&files, ".network", NULL, network_dirs);
127 log_error("Failed to enumerate network files: %s", strerror(-r));
131 STRV_FOREACH_BACKWARDS(f, files) {
132 r = network_load_one(manager, *f);
140 void network_free(Network *network) {
148 free(network->filename);
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);
156 free(network->description);
158 SET_FOREACH(address, network->dns, i)
159 address_free(address);
161 set_free(network->dns);
163 hashmap_free(network->vlans);
165 hashmap_free(network->macvlans);
167 while ((route = network->static_routes))
170 while ((address = network->static_addresses))
171 address_free(address);
173 hashmap_free(network->addresses_by_section);
174 hashmap_free(network->routes_by_section);
176 if (network->manager && network->manager->networks)
177 LIST_REMOVE(networks, network->manager->networks, network);
182 int network_get(Manager *manager, struct udev_device *device, Network **ret) {
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,
192 network->match_name, network->match_host,
193 network->match_virt, network->match_kernel,
195 udev_device_get_sysattr_value(device, "address"),
196 udev_device_get_property_value(device, "ID_PATH"),
197 udev_device_get_driver(udev_device_get_parent(device)),
198 udev_device_get_property_value(device, "ID_NET_DRIVER"),
199 udev_device_get_devtype(device),
200 udev_device_get_sysname(device))) {
201 log_debug("%s: found matching network '%s'",
202 udev_device_get_sysname(device),
214 int network_apply(Manager *manager, Network *network, Link *link) {
217 link->network = network;
220 r = manager_update_resolv_conf(manager);
228 int config_parse_bridge(const char *unit,
229 const char *filename,
232 unsigned section_line,
238 Network *network = userdata;
247 r = netdev_get(network->manager, rvalue, &netdev);
249 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
250 "Bridge is invalid, ignoring assignment: %s", rvalue);
254 if (netdev->kind != NETDEV_KIND_BRIDGE) {
255 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
256 "NetDev is not a bridge, ignoring assignment: %s", rvalue);
260 network->bridge = netdev;
265 int config_parse_bond(const char *unit,
266 const char *filename,
269 unsigned section_line,
275 Network *network = userdata;
284 r = netdev_get(network->manager, rvalue, &netdev);
286 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
287 "Bond is invalid, ignoring assignment: %s", rvalue);
291 if (netdev->kind != NETDEV_KIND_BOND) {
292 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
293 "NetDev is not a bond, ignoring assignment: %s", rvalue);
297 network->bond = netdev;
302 int config_parse_vlan(const char *unit,
303 const char *filename,
306 unsigned section_line,
312 Network *network = userdata;
321 r = netdev_get(network->manager, rvalue, &netdev);
323 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
324 "VLAN is invalid, ignoring assignment: %s", rvalue);
328 if (netdev->kind != NETDEV_KIND_VLAN) {
329 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
330 "NetDev is not a VLAN, ignoring assignment: %s", rvalue);
334 r = hashmap_put(network->vlans, &netdev->vlanid, netdev);
336 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
337 "Can not add VLAN to network: %s", rvalue);
344 int config_parse_macvlan(const char *unit,
345 const char *filename,
348 unsigned section_line,
354 Network *network = userdata;
363 r = netdev_get(network->manager, rvalue, &netdev);
365 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
366 "MACVLAN is invalid, ignoring assignment: %s", rvalue);
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);
376 r = hashmap_put(network->macvlans, netdev->name, netdev);
378 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
379 "Can not add MACVLAN to network: %s", rvalue);