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;
211 r = link_configure(link);
216 r = manager_update_resolv_conf(manager);
224 int config_parse_bridge(const char *unit,
225 const char *filename,
228 unsigned section_line,
234 Network *network = userdata;
243 r = netdev_get(network->manager, rvalue, &netdev);
245 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
246 "Bridge is invalid, ignoring assignment: %s", rvalue);
250 if (netdev->kind != NETDEV_KIND_BRIDGE) {
251 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
252 "NetDev is not a bridge, ignoring assignment: %s", rvalue);
256 network->bridge = netdev;
261 int config_parse_bond(const char *unit,
262 const char *filename,
265 unsigned section_line,
271 Network *network = userdata;
280 r = netdev_get(network->manager, rvalue, &netdev);
282 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
283 "Bond is invalid, ignoring assignment: %s", rvalue);
287 if (netdev->kind != NETDEV_KIND_BOND) {
288 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
289 "NetDev is not a bond, ignoring assignment: %s", rvalue);
293 network->bond = netdev;
298 int config_parse_vlan(const char *unit,
299 const char *filename,
302 unsigned section_line,
308 Network *network = userdata;
317 r = netdev_get(network->manager, rvalue, &netdev);
319 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
320 "VLAN is invalid, ignoring assignment: %s", rvalue);
324 if (netdev->kind != NETDEV_KIND_VLAN) {
325 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
326 "NetDev is not a VLAN, ignoring assignment: %s", rvalue);
330 r = hashmap_put(network->vlans, &netdev->vlanid, netdev);
332 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
333 "Can not add VLAN to network: %s", rvalue);
340 int config_parse_macvlan(const char *unit,
341 const char *filename,
344 unsigned section_line,
350 Network *network = userdata;
359 r = netdev_get(network->manager, rvalue, &netdev);
361 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
362 "MACVLAN is invalid, ignoring assignment: %s", rvalue);
366 if (netdev->kind != NETDEV_KIND_MACVLAN) {
367 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
368 "NetDev is not a MACVLAN, ignoring assignment: %s", rvalue);
372 r = hashmap_put(network->macvlans, netdev->name, netdev);
374 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
375 "Can not add MACVLAN to network: %s", rvalue);