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 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);
179 condition_free_list(network->match_host);
180 condition_free_list(network->match_virt);
181 condition_free_list(network->match_kernel);
182 condition_free_list(network->match_arch);
187 int network_get(Manager *manager, struct udev_device *device, Network **ret) {
194 LIST_FOREACH(networks, network, manager->networks) {
195 if (net_match_config(network->match_mac, network->match_path,
196 network->match_driver, network->match_type,
197 network->match_name, network->match_host,
198 network->match_virt, network->match_kernel,
200 udev_device_get_sysattr_value(device, "address"),
201 udev_device_get_property_value(device, "ID_PATH"),
202 udev_device_get_driver(udev_device_get_parent(device)),
203 udev_device_get_property_value(device, "ID_NET_DRIVER"),
204 udev_device_get_devtype(device),
205 udev_device_get_sysname(device))) {
206 log_debug("%s: found matching network '%s'",
207 udev_device_get_sysname(device),
219 int network_apply(Manager *manager, Network *network, Link *link) {
222 link->network = network;
225 r = manager_update_resolv_conf(manager);
233 int config_parse_bridge(const char *unit,
234 const char *filename,
237 unsigned section_line,
243 Network *network = userdata;
252 r = netdev_get(network->manager, rvalue, &netdev);
254 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
255 "Bridge is invalid, ignoring assignment: %s", rvalue);
259 if (netdev->kind != NETDEV_KIND_BRIDGE) {
260 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
261 "NetDev is not a bridge, ignoring assignment: %s", rvalue);
265 network->bridge = netdev;
270 int config_parse_bond(const char *unit,
271 const char *filename,
274 unsigned section_line,
280 Network *network = userdata;
289 r = netdev_get(network->manager, rvalue, &netdev);
291 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
292 "Bond is invalid, ignoring assignment: %s", rvalue);
296 if (netdev->kind != NETDEV_KIND_BOND) {
297 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
298 "NetDev is not a bond, ignoring assignment: %s", rvalue);
302 network->bond = netdev;
307 int config_parse_vlan(const char *unit,
308 const char *filename,
311 unsigned section_line,
317 Network *network = userdata;
326 r = netdev_get(network->manager, rvalue, &netdev);
328 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
329 "VLAN is invalid, ignoring assignment: %s", rvalue);
333 if (netdev->kind != NETDEV_KIND_VLAN) {
334 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
335 "NetDev is not a VLAN, ignoring assignment: %s", rvalue);
339 r = hashmap_put(network->vlans, &netdev->vlanid, netdev);
341 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
342 "Can not add VLAN to network: %s", rvalue);
349 int config_parse_macvlan(const char *unit,
350 const char *filename,
353 unsigned section_line,
359 Network *network = userdata;
368 r = netdev_get(network->manager, rvalue, &netdev);
370 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
371 "MACVLAN is invalid, ignoring assignment: %s", rvalue);
375 if (netdev->kind != NETDEV_KIND_MACVLAN) {
376 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
377 "NetDev is not a MACVLAN, ignoring assignment: %s", rvalue);
381 r = hashmap_put(network->macvlans, netdev->name, netdev);
383 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
384 "Can not add MACVLAN to network: %s", rvalue);