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/>.
25 #include "network-internal.h"
26 #include "path-util.h"
27 #include "conf-files.h"
28 #include "conf-parser.h"
31 static int network_load_one(Manager *manager, const char *filename) {
32 _cleanup_network_free_ Network *network = NULL;
33 _cleanup_fclose_ FILE *file = NULL;
41 file = fopen(filename, "re");
49 if (null_or_empty_path(filename)) {
50 log_debug("skipping empty file: %s", filename);
54 network = new0(Network, 1);
58 network->manager = manager;
60 LIST_HEAD_INIT(network->static_addresses);
61 LIST_HEAD_INIT(network->static_routes);
63 network->vlans = hashmap_new(string_hash_func, string_compare_func);
67 network->macvlans = hashmap_new(uint64_hash_func, uint64_compare_func);
68 if (!network->macvlans)
71 network->addresses_by_section = hashmap_new(uint64_hash_func, uint64_compare_func);
72 if (!network->addresses_by_section)
75 network->routes_by_section = hashmap_new(uint64_hash_func, uint64_compare_func);
76 if (!network->routes_by_section)
79 network->dns = set_new(NULL, NULL);
83 network->filename = strdup(filename);
84 if (!network->filename)
87 network->dhcp_dns = true;
88 network->dhcp_hostname = true;
89 network->dhcp_domainname = true;
91 r = config_parse(NULL, filename, file, "Match\0Network\0Address\0Route\0DHCPv4\0", config_item_perf_lookup,
92 (void*) network_network_gperf_lookup, false, false, network);
94 log_warning("Could not parse config file %s: %s", filename, strerror(-r));
98 LIST_PREPEND(networks, manager->networks, network);
100 LIST_FOREACH(static_routes, route, network->static_routes) {
101 if (!route->family) {
102 log_warning("Route section without Gateway field configured in %s. "
103 "Ignoring", filename);
108 LIST_FOREACH(static_addresses, address, network->static_addresses) {
109 if (!address->family) {
110 log_warning("Address section without Address field configured in %s. "
111 "Ignoring", filename);
121 int network_load(Manager *manager) {
123 _cleanup_strv_free_ char **files = NULL;
129 while ((network = manager->networks))
130 network_free(network);
132 r = conf_files_list_strv(&files, ".network", NULL, network_dirs);
134 log_error("Failed to enumerate network files: %s", strerror(-r));
138 STRV_FOREACH_BACKWARDS(f, files) {
139 r = network_load_one(manager, *f);
147 void network_free(Network *network) {
156 free(network->filename);
158 free(network->match_mac);
159 free(network->match_path);
160 free(network->match_driver);
161 free(network->match_type);
162 free(network->match_name);
164 free(network->description);
166 SET_FOREACH(address, network->dns, i)
167 address_free(address);
169 set_free(network->dns);
171 netdev_unref(network->bridge);
173 netdev_unref(network->bond);
175 HASHMAP_FOREACH(netdev, network->vlans, i)
176 netdev_unref(netdev);
177 hashmap_free(network->vlans);
179 HASHMAP_FOREACH(netdev, network->macvlans, i)
180 netdev_unref(netdev);
181 hashmap_free(network->macvlans);
183 while ((route = network->static_routes))
186 while ((address = network->static_addresses))
187 address_free(address);
189 hashmap_free(network->addresses_by_section);
190 hashmap_free(network->routes_by_section);
192 if (network->manager && network->manager->networks)
193 LIST_REMOVE(networks, network->manager->networks, network);
195 condition_free_list(network->match_host);
196 condition_free_list(network->match_virt);
197 condition_free_list(network->match_kernel);
198 condition_free_list(network->match_arch);
203 int network_get(Manager *manager, struct udev_device *device,
204 const char *ifname, const struct ether_addr *address,
211 LIST_FOREACH(networks, network, manager->networks) {
212 if (net_match_config(network->match_mac, network->match_path,
213 network->match_driver, network->match_type,
214 network->match_name, network->match_host,
215 network->match_virt, network->match_kernel,
218 udev_device_get_property_value(device, "ID_PATH"),
219 udev_device_get_driver(udev_device_get_parent(device)),
220 udev_device_get_property_value(device, "ID_NET_DRIVER"),
221 udev_device_get_devtype(device),
223 log_debug("%s: found matching network '%s'", ifname,
235 int network_apply(Manager *manager, Network *network, Link *link) {
238 link->network = network;
241 r = manager_update_resolv_conf(manager);
249 int config_parse_netdev(const char *unit,
250 const char *filename,
253 unsigned section_line,
259 Network *network = userdata;
260 char *kind_string, *p;
270 kind_string = strdup(lvalue);
274 /* the keys are CamelCase versions of the kind */
275 for (p = kind_string; *p; p++)
278 kind = netdev_kind_from_string(kind_string);
279 if (kind == _NETDEV_KIND_INVALID) {
280 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
281 "Invalid NetDev kind: %s", lvalue);
285 r = netdev_get(network->manager, rvalue, &netdev);
287 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
288 "%s could not be found, ignoring assignment: %s", lvalue, rvalue);
292 if (netdev->kind != kind) {
293 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
294 "NetDev is not a %s, ignoring assignment: %s", lvalue, rvalue);
299 case NETDEV_KIND_BRIDGE:
300 network->bridge = netdev;
303 case NETDEV_KIND_BOND:
304 network->bond = netdev;
307 case NETDEV_KIND_VLAN:
308 r = hashmap_put(network->vlans, &netdev->vlanid, netdev);
310 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
311 "Can not add VLAN to network: %s", rvalue);
316 case NETDEV_KIND_MACVLAN:
317 r = hashmap_put(network->macvlans, netdev->name, netdev);
319 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
320 "Can not add MACVLAN to network: %s", rvalue);
326 assert_not_reached("Can not parse NetDev");