networkd-network.c revision a2fae7bbb21bdcc9d0a2094b7fd6b364ffbaae86
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering/***
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering This file is part of systemd.
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering Copyright 2013 Tom Gundersen <teg@jklm.no>
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering systemd is free software; you can redistribute it and/or modify it
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering under the terms of the GNU Lesser General Public License as published by
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering (at your option) any later version.
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering systemd is distributed in the hope that it will be useful, but
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering Lesser General Public License for more details.
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering You should have received a copy of the GNU Lesser General Public License
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering***/
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering#include <ctype.h>
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering#include <net/if.h>
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering#include "conf-files.h"
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering#include "conf-parser.h"
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering#include "util.h"
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering#include "hostname-util.h"
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering#include "dns-domain.h"
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering#include "network-internal.h"
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering#include "networkd.h"
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering#include "networkd-network.h"
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringstatic int network_load_one(Manager *manager, const char *filename) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering _cleanup_network_free_ Network *network = NULL;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering _cleanup_fclose_ FILE *file = NULL;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering char *d;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering Route *route;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering Address *address;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering int r;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering assert(manager);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering assert(filename);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering file = fopen(filename, "re");
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (!file) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (errno == ENOENT)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return 0;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering else
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return -errno;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (null_or_empty_fd(fileno(file))) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_debug("Skipping empty file: %s", filename);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return 0;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering network = new0(Network, 1);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (!network)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return log_oom();
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering network->manager = manager;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering LIST_HEAD_INIT(network->static_addresses);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering LIST_HEAD_INIT(network->static_routes);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering LIST_HEAD_INIT(network->static_fdb_entries);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering network->stacked_netdevs = hashmap_new(&string_hash_ops);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (!network->stacked_netdevs)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return log_oom();
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering network->addresses_by_section = hashmap_new(NULL);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (!network->addresses_by_section)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return log_oom();
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering network->routes_by_section = hashmap_new(NULL);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (!network->routes_by_section)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return log_oom();
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering network->fdb_entries_by_section = hashmap_new(NULL);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (!network->fdb_entries_by_section)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return log_oom();
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering network->filename = strdup(filename);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (!network->filename)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return log_oom();
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering network->name = strdup(basename(filename));
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (!network->name)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return log_oom();
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering d = strrchr(network->name, '.');
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (!d)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return -EINVAL;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering assert(streq(d, ".network"));
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering *d = '\0';
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering network->dhcp = ADDRESS_FAMILY_NO;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering network->dhcp_ntp = true;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering network->dhcp_dns = true;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering network->dhcp_hostname = true;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering network->dhcp_routes = true;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering network->dhcp_sendhost = true;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering network->dhcp_route_metric = DHCP_ROUTE_METRIC;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering network->dhcp_client_identifier = DHCP_CLIENT_ID_DUID;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering network->dhcp_server_emit_dns = true;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering network->dhcp_server_emit_ntp = true;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering network->dhcp_server_emit_timezone = true;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering network->use_bpdu = true;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering network->allow_port_to_be_root = true;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering network->unicast_flood = true;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering network->llmnr = RESOLVE_SUPPORT_YES;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering network->link_local = ADDRESS_FAMILY_IPV6;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering network->ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_NO;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering network->ipv6_accept_ra = -1;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering r = config_parse(NULL, filename, file,
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering "Match\0"
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering "Link\0"
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering "Network\0"
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering "Address\0"
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering "Route\0"
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering "DHCP\0"
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering "DHCPv4\0" /* compat */
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering "DHCPServer\0"
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering "Bridge\0"
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering "BridgeFDB\0",
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering config_item_perf_lookup, network_network_gperf_lookup,
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering false, false, true, network);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (r < 0)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return r;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering /* IPMasquerade=yes implies IPForward=yes */
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (network->ip_masquerade)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering network->ip_forward |= ADDRESS_FAMILY_IPV4;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering LIST_PREPEND(networks, manager->networks, network);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering r = hashmap_ensure_allocated(&manager->networks_by_name, &string_hash_ops);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (r < 0)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return r;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering r = hashmap_put(manager->networks_by_name, network->name, network);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (r < 0)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return r;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering LIST_FOREACH(routes, route, network->static_routes) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (!route->family) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_warning("Route section without Gateway field configured in %s. "
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering "Ignoring", filename);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return 0;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering LIST_FOREACH(addresses, address, network->static_addresses) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (!address->family) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_warning("Address section without Address field configured in %s. "
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering "Ignoring", filename);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return 0;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering network = NULL;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return 0;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering}
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringint network_load(Manager *manager) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering Network *network;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering _cleanup_strv_free_ char **files = NULL;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering char **f;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering int r;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering assert(manager);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering while ((network = manager->networks))
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering network_free(network);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering r = conf_files_list_strv(&files, ".network", NULL, network_dirs);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (r < 0)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return log_error_errno(r, "Failed to enumerate network files: %m");
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering STRV_FOREACH_BACKWARDS(f, files) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering r = network_load_one(manager, *f);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (r < 0)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return r;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return 0;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering}
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringvoid network_free(Network *network) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering NetDev *netdev;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering Route *route;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering Address *address;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering FdbEntry *fdb_entry;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering Iterator i;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (!network)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering free(network->filename);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering free(network->match_mac);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering strv_free(network->match_path);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering strv_free(network->match_driver);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering strv_free(network->match_type);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering strv_free(network->match_name);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering free(network->description);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering free(network->dhcp_vendor_class_identifier);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering free(network->hostname);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering free(network->mac);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering strv_free(network->ntp);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering strv_free(network->dns);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering strv_free(network->domains);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering strv_free(network->bind_carrier);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering netdev_unref(network->bridge);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering netdev_unref(network->bond);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering HASHMAP_FOREACH(netdev, network->stacked_netdevs, i) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering hashmap_remove(network->stacked_netdevs, netdev->ifname);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering netdev_unref(netdev);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering hashmap_free(network->stacked_netdevs);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering while ((route = network->static_routes))
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering route_free(route);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering while ((address = network->static_addresses))
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering address_free(address);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering while ((fdb_entry = network->static_fdb_entries))
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering fdb_entry_free(fdb_entry);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering hashmap_free(network->addresses_by_section);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering hashmap_free(network->routes_by_section);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering hashmap_free(network->fdb_entries_by_section);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (network->manager) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (network->manager->networks)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering LIST_REMOVE(networks, network->manager->networks, network);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (network->manager->networks_by_name)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering hashmap_remove(network->manager->networks_by_name, network->name);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering free(network->name);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering condition_free_list(network->match_host);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering condition_free_list(network->match_virt);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering condition_free_list(network->match_kernel);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering condition_free_list(network->match_arch);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering free(network->dhcp_server_timezone);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering free(network->dhcp_server_dns);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering free(network->dhcp_server_ntp);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering free(network);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering}
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringint network_get_by_name(Manager *manager, const char *name, Network **ret) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering Network *network;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering assert(manager);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering assert(name);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering assert(ret);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering network = hashmap_get(manager->networks_by_name, name);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (!network)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return -ENOENT;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering *ret = network;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return 0;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering}
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringint network_get(Manager *manager, struct udev_device *device,
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering const char *ifname, const struct ether_addr *address,
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering Network **ret) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering Network *network;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering struct udev_device *parent;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering const char *path = NULL, *parent_driver = NULL, *driver = NULL, *devtype = NULL;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering assert(manager);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering assert(ret);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (device) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering path = udev_device_get_property_value(device, "ID_PATH");
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering parent = udev_device_get_parent(device);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (parent)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering parent_driver = udev_device_get_driver(parent);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering driver = udev_device_get_property_value(device, "ID_NET_DRIVER");
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering devtype = udev_device_get_devtype(device);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering LIST_FOREACH(networks, network, manager->networks) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (net_match_config(network->match_mac, network->match_path,
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering network->match_driver, network->match_type,
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering network->match_name, network->match_host,
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering network->match_virt, network->match_kernel,
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering network->match_arch,
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering address, path, parent_driver, driver,
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering devtype, ifname)) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (network->match_name && device) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering const char *attr;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering uint8_t name_assign_type = NET_NAME_UNKNOWN;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering attr = udev_device_get_sysattr_value(device, "name_assign_type");
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (attr)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering (void) safe_atou8(attr, &name_assign_type);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (name_assign_type == NET_NAME_ENUM)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_warning("%s: found matching network '%s', based on potentially unpredictable ifname",
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering ifname, network->filename);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering else
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_debug("%s: found matching network '%s'", ifname, network->filename);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering } else
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_debug("%s: found matching network '%s'", ifname, network->filename);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering *ret = network;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return 0;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering *ret = NULL;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return -ENOENT;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering}
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringint network_apply(Manager *manager, Network *network, Link *link) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering int r;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering link->network = network;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (network->ipv4ll_route) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering Route *route;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering r = route_new_static(network, 0, &route);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (r < 0)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return r;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering r = inet_pton(AF_INET, "169.254.0.0", &route->dst_addr.in);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (r == 0)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return -EINVAL;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (r < 0)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return -errno;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering route->family = AF_INET;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering route->dst_prefixlen = 16;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering route->scope = RT_SCOPE_LINK;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering route->metrics = IPV4LL_ROUTE_METRIC;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering route->protocol = RTPROT_STATIC;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (network->dns || network->ntp) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering r = link_save(link);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (r < 0)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return r;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return 0;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering}
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringint config_parse_netdev(const char *unit,
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering const char *filename,
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering unsigned line,
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering const char *section,
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering unsigned section_line,
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering const char *lvalue,
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering int ltype,
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering const char *rvalue,
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering void *data,
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering void *userdata) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering Network *network = userdata;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering _cleanup_free_ char *kind_string = NULL;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering char *p;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering NetDev *netdev;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering NetDevKind kind;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering int r;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering assert(filename);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering assert(lvalue);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering assert(rvalue);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering assert(data);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering kind_string = strdup(lvalue);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (!kind_string)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return log_oom();
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering /* the keys are CamelCase versions of the kind */
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering for (p = kind_string; *p; p++)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering *p = tolower(*p);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering kind = netdev_kind_from_string(kind_string);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (kind == _NETDEV_KIND_INVALID) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid NetDev kind: %s", lvalue);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return 0;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering r = netdev_get(network->manager, rvalue, &netdev);
5fa89b2cb366d533e56a9b7a9ce548480776f973Lennart Poettering if (r < 0) {
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering log_syntax(unit, LOG_ERR, filename, line, r, "%s could not be found, ignoring assignment: %s", lvalue, rvalue);
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering return 0;
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering }
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering if (netdev->kind != kind) {
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering log_syntax(unit, LOG_ERR, filename, line, 0, "NetDev is not a %s, ignoring assignment: %s", lvalue, rvalue);
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering return 0;
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering }
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering switch (kind) {
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering case NETDEV_KIND_BRIDGE:
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering network->bridge = netdev;
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering break;
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering case NETDEV_KIND_BOND:
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering network->bond = netdev;
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering break;
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering case NETDEV_KIND_VLAN:
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering case NETDEV_KIND_MACVLAN:
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering case NETDEV_KIND_MACVTAP:
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering case NETDEV_KIND_IPVLAN:
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering case NETDEV_KIND_VXLAN:
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering r = hashmap_put(network->stacked_netdevs, netdev->ifname, netdev);
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering if (r < 0) {
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering log_syntax(unit, LOG_ERR, filename, line, r, "Can not add VLAN '%s' to network: %m", rvalue);
5fa89b2cb366d533e56a9b7a9ce548480776f973Lennart Poettering return 0;
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering }
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering
break;
default:
assert_not_reached("Can not parse NetDev");
}
netdev_ref(netdev);
return 0;
}
int config_parse_domains(const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
Network *network = userdata;
char ***domains = data;
char **domain;
int r;
r = config_parse_strv(unit, filename, line, section, section_line,
lvalue, ltype, rvalue, domains, userdata);
if (r < 0)
return r;
strv_uniq(*domains);
network->wildcard_domain = !!strv_find(*domains, "*");
STRV_FOREACH(domain, *domains) {
if (is_localhost(*domain))
log_syntax(unit, LOG_ERR, filename, line, 0, "'localhost' domain names may not be configured, ignoring assignment: %s", *domain);
else {
r = dns_name_is_valid(*domain);
if (r <= 0 && !streq(*domain, "*")) {
if (r < 0)
log_error_errno(r, "Failed to validate domain name: %s: %m", *domain);
if (r == 0)
log_warning("Domain name is not valid, ignoring assignment: %s", *domain);
} else
continue;
}
strv_remove(*domains, *domain);
/* We removed one entry, make sure we don't skip the next one */
domain--;
}
return 0;
}
int config_parse_tunnel(const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
Network *network = userdata;
NetDev *netdev;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
r = netdev_get(network->manager, rvalue, &netdev);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, "Tunnel is invalid, ignoring assignment: %s", rvalue);
return 0;
}
if (netdev->kind != NETDEV_KIND_IPIP &&
netdev->kind != NETDEV_KIND_SIT &&
netdev->kind != NETDEV_KIND_GRE &&
netdev->kind != NETDEV_KIND_GRETAP &&
netdev->kind != NETDEV_KIND_IP6GRE &&
netdev->kind != NETDEV_KIND_IP6GRETAP &&
netdev->kind != NETDEV_KIND_VTI &&
netdev->kind != NETDEV_KIND_VTI6 &&
netdev->kind != NETDEV_KIND_IP6TNL
) {
log_syntax(unit, LOG_ERR, filename, line, 0,
"NetDev is not a tunnel, ignoring assignment: %s", rvalue);
return 0;
}
r = hashmap_put(network->stacked_netdevs, netdev->ifname, netdev);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, "Cannot add VLAN '%s' to network, ignoring: %m", rvalue);
return 0;
}
netdev_ref(netdev);
return 0;
}
int config_parse_ipv4ll(
const char* unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
AddressFamilyBoolean *link_local = data;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
/* Note that this is mostly like
* config_parse_address_family_boolean(), except that it
* applies only to IPv4 */
if (parse_boolean(rvalue))
*link_local |= ADDRESS_FAMILY_IPV4;
else
*link_local &= ~ADDRESS_FAMILY_IPV4;
return 0;
}
int config_parse_dhcp(
const char* unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
AddressFamilyBoolean *dhcp = data, s;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
/* Note that this is mostly like
* config_parse_address_family_boolean(), except that it
* understands some old names for the enum values */
s = address_family_boolean_from_string(rvalue);
if (s < 0) {
/* Previously, we had a slightly different enum here,
* support its values for compatbility. */
if (streq(rvalue, "none"))
s = ADDRESS_FAMILY_NO;
else if (streq(rvalue, "v4"))
s = ADDRESS_FAMILY_IPV4;
else if (streq(rvalue, "v6"))
s = ADDRESS_FAMILY_IPV6;
else if (streq(rvalue, "both"))
s = ADDRESS_FAMILY_YES;
else {
log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse DHCP option, ignoring: %s", rvalue);
return 0;
}
}
*dhcp = s;
return 0;
}
static const char* const dhcp_client_identifier_table[_DHCP_CLIENT_ID_MAX] = {
[DHCP_CLIENT_ID_MAC] = "mac",
[DHCP_CLIENT_ID_DUID] = "duid"
};
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_client_identifier, DCHPClientIdentifier);
DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_client_identifier, dhcp_client_identifier, DCHPClientIdentifier, "Failed to parse client identifier type");
int config_parse_ipv6token(
const char* unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
union in_addr_union buffer;
struct in6_addr *token = data;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(token);
r = in_addr_from_string(AF_INET6, rvalue, &buffer);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse IPv6 token, ignoring: %s", rvalue);
return 0;
}
r = in_addr_is_null(AF_INET6, &buffer);
if (r != 0) {
log_syntax(unit, LOG_ERR, filename, line, r, "IPv6 token can not be the ANY address, ignoring: %s", rvalue);
return 0;
}
if ((buffer.in6.s6_addr32[0] | buffer.in6.s6_addr32[1]) != 0) {
log_syntax(unit, LOG_ERR, filename, line, 0, "IPv6 token can not be longer than 64 bits, ignoring: %s", rvalue);
return 0;
}
*token = buffer.in6;
return 0;
}
static const char* const ipv6_privacy_extensions_table[_IPV6_PRIVACY_EXTENSIONS_MAX] = {
[IPV6_PRIVACY_EXTENSIONS_NO] = "no",
[IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC] = "prefer-public",
[IPV6_PRIVACY_EXTENSIONS_YES] = "yes",
};
DEFINE_STRING_TABLE_LOOKUP(ipv6_privacy_extensions, IPv6PrivacyExtensions);
int config_parse_ipv6_privacy_extensions(
const char* unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
IPv6PrivacyExtensions *ipv6_privacy_extensions = data;
int k;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(ipv6_privacy_extensions);
/* Our enum shall be a superset of booleans, hence first try
* to parse as boolean, and then as enum */
k = parse_boolean(rvalue);
if (k > 0)
*ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_YES;
else if (k == 0)
*ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_NO;
else {
IPv6PrivacyExtensions s;
s = ipv6_privacy_extensions_from_string(rvalue);
if (s < 0) {
if (streq(rvalue, "kernel"))
s = _IPV6_PRIVACY_EXTENSIONS_INVALID;
else {
log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue);
return 0;
}
}
*ipv6_privacy_extensions = s;
}
return 0;
}
int config_parse_hostname(
const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
char **hostname = data, *hn = NULL;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
r = config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &hn, userdata);
if (r < 0)
return r;
if (!hostname_is_valid(hn, false)) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Hostname is not valid, ignoring assignment: %s", rvalue);
free(hn);
return 0;
}
free(*hostname);
*hostname = hostname_cleanup(hn);
return 0;
}
int config_parse_timezone(
const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
char **datap = data, *tz = NULL;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
r = config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &tz, userdata);
if (r < 0)
return r;
if (!timezone_is_valid(tz)) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Timezone is not valid, ignoring assignment: %s", rvalue);
free(tz);
return 0;
}
free(*datap);
*datap = tz;
return 0;
}
int config_parse_dhcp_server_dns(
const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
Network *n = data;
const char *p = rvalue;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
for (;;) {
_cleanup_free_ char *w = NULL;
struct in_addr a, *m;
r = extract_first_word(&p, &w, NULL, 0);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract word, ignoring: %s", rvalue);
return 0;
}
if (r == 0)
return 0;
if (inet_pton(AF_INET, w, &a) <= 0) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse DNS server address, ignoring: %s", w);
continue;
}
m = realloc(n->dhcp_server_dns, (n->n_dhcp_server_dns + 1) * sizeof(struct in_addr));
if (!m)
return log_oom();
m[n->n_dhcp_server_dns++] = a;
n->dhcp_server_dns = m;
}
}
int config_parse_dhcp_server_ntp(
const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
Network *n = data;
const char *p = rvalue;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
for (;;) {
_cleanup_free_ char *w = NULL;
struct in_addr a, *m;
r = extract_first_word(&p, &w, NULL, 0);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract word, ignoring: %s", rvalue);
return 0;
}
if (r == 0)
return 0;
if (inet_pton(AF_INET, w, &a) <= 0) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse NTP server address, ignoring: %s", w);
continue;
}
m = realloc(n->dhcp_server_ntp, (n->n_dhcp_server_ntp + 1) * sizeof(struct in_addr));
if (!m)
return log_oom();
m[n->n_dhcp_server_ntp++] = a;
n->dhcp_server_ntp = m;
}
}