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->filename = strdup(filename);
73 if (!network->filename)
76 network->dhcp_dns = true;
77 network->dhcp_hostname = true;
78 network->dhcp_domainname = true;
80 r = config_parse(NULL, filename, file, "Match\0Network\0Address\0Route\0DHCPv4\0", config_item_perf_lookup,
81 (void*) network_network_gperf_lookup, false, false, network);
83 log_warning("Could not parse config file %s: %s", filename, strerror(-r));
87 LIST_PREPEND(networks, manager->networks, network);
89 LIST_FOREACH(static_routes, route, network->static_routes) {
91 log_warning("Route section without Gateway field configured in %s. "
92 "Ignoring", filename);
97 LIST_FOREACH(static_addresses, address, network->static_addresses) {
98 if (!address->family) {
99 log_warning("Address section without Address field configured in %s. "
100 "Ignoring", filename);
110 int network_load(Manager *manager) {
112 _cleanup_strv_free_ char **files = NULL;
118 while ((network = manager->networks))
119 network_free(network);
121 r = conf_files_list_strv(&files, ".network", NULL, network_dirs);
123 log_error("Failed to enumerate network files: %s", strerror(-r));
127 STRV_FOREACH_BACKWARDS(f, files) {
128 r = network_load_one(manager, *f);
136 void network_free(Network *network) {
143 free(network->filename);
145 free(network->match_mac);
146 free(network->match_path);
147 free(network->match_driver);
148 free(network->match_type);
149 free(network->match_name);
151 free(network->description);
153 address_free(network->dns);
155 hashmap_free(network->vlans);
157 hashmap_free(network->macvlans);
159 while ((route = network->static_routes))
162 while ((address = network->static_addresses))
163 address_free(address);
165 hashmap_free(network->addresses_by_section);
166 hashmap_free(network->routes_by_section);
168 if (network->manager && network->manager->networks)
169 LIST_REMOVE(networks, network->manager->networks, network);
174 int network_get(Manager *manager, struct udev_device *device, Network **ret) {
181 LIST_FOREACH(networks, network, manager->networks) {
182 if (net_match_config(network->match_mac, network->match_path,
183 network->match_driver, network->match_type,
184 network->match_name, network->match_host,
185 network->match_virt, network->match_kernel,
187 udev_device_get_sysattr_value(device, "address"),
188 udev_device_get_property_value(device, "ID_PATH"),
189 udev_device_get_driver(udev_device_get_parent(device)),
190 udev_device_get_property_value(device, "ID_NET_DRIVER"),
191 udev_device_get_devtype(device),
192 udev_device_get_sysname(device))) {
193 log_debug("%s: found matching network '%s'",
194 udev_device_get_sysname(device),
206 int network_apply(Manager *manager, Network *network, Link *link) {
209 link->network = network;
212 r = manager_update_resolv_conf(manager);
220 int config_parse_bridge(const char *unit,
221 const char *filename,
224 unsigned section_line,
230 Network *network = userdata;
239 r = netdev_get(network->manager, rvalue, &netdev);
241 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
242 "Bridge is invalid, ignoring assignment: %s", rvalue);
246 if (netdev->kind != NETDEV_KIND_BRIDGE) {
247 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
248 "NetDev is not a bridge, ignoring assignment: %s", rvalue);
252 network->bridge = netdev;
257 int config_parse_bond(const char *unit,
258 const char *filename,
261 unsigned section_line,
267 Network *network = userdata;
276 r = netdev_get(network->manager, rvalue, &netdev);
278 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
279 "Bond is invalid, ignoring assignment: %s", rvalue);
283 if (netdev->kind != NETDEV_KIND_BOND) {
284 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
285 "NetDev is not a bond, ignoring assignment: %s", rvalue);
289 network->bond = netdev;
294 int config_parse_vlan(const char *unit,
295 const char *filename,
298 unsigned section_line,
304 Network *network = userdata;
313 r = netdev_get(network->manager, rvalue, &netdev);
315 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
316 "VLAN is invalid, ignoring assignment: %s", rvalue);
320 if (netdev->kind != NETDEV_KIND_VLAN) {
321 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
322 "NetDev is not a VLAN, ignoring assignment: %s", rvalue);
326 r = hashmap_put(network->vlans, &netdev->vlanid, netdev);
328 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
329 "Can not add VLAN to network: %s", rvalue);
336 int config_parse_macvlan(const char *unit,
337 const char *filename,
340 unsigned section_line,
346 Network *network = userdata;
355 r = netdev_get(network->manager, rvalue, &netdev);
357 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
358 "MACVLAN is invalid, ignoring assignment: %s", rvalue);
362 if (netdev->kind != NETDEV_KIND_MACVLAN) {
363 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
364 "NetDev is not a MACVLAN, ignoring assignment: %s", rvalue);
368 r = hashmap_put(network->macvlans, netdev->name, netdev);
370 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
371 "Can not add MACVLAN to network: %s", rvalue);