networkd-network.c revision a2fae7bbb21bdcc9d0a2094b7fd6b364ffbaae86
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering This file is part of systemd.
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering Copyright 2013 Tom Gundersen <teg@jklm.no>
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 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 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 Poetteringstatic int network_load_one(Manager *manager, const char *filename) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering _cleanup_network_free_ Network *network = NULL;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_debug("Skipping empty file: %s", filename);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering LIST_HEAD_INIT(network->static_addresses);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering LIST_HEAD_INIT(network->static_fdb_entries);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering network->stacked_netdevs = hashmap_new(&string_hash_ops);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering network->addresses_by_section = hashmap_new(NULL);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering network->routes_by_section = hashmap_new(NULL);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering network->fdb_entries_by_section = hashmap_new(NULL);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering network->name = strdup(basename(filename));
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering network->dhcp_route_metric = DHCP_ROUTE_METRIC;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering network->dhcp_client_identifier = DHCP_CLIENT_ID_DUID;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering network->dhcp_server_emit_timezone = true;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering network->link_local = ADDRESS_FAMILY_IPV6;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering network->ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_NO;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering "DHCPServer\0"
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering "BridgeFDB\0",
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering config_item_perf_lookup, network_network_gperf_lookup,
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering false, false, true, network);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering /* IPMasquerade=yes implies IPForward=yes */
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering network->ip_forward |= ADDRESS_FAMILY_IPV4;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering LIST_PREPEND(networks, manager->networks, network);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering r = hashmap_ensure_allocated(&manager->networks_by_name, &string_hash_ops);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering r = hashmap_put(manager->networks_by_name, network->name, network);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering LIST_FOREACH(routes, route, network->static_routes) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_warning("Route section without Gateway field configured in %s. "
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering LIST_FOREACH(addresses, address, network->static_addresses) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_warning("Address section without Address field configured in %s. "
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering r = conf_files_list_strv(&files, ".network", NULL, network_dirs);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return log_error_errno(r, "Failed to enumerate network files: %m");
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering free(network->dhcp_vendor_class_identifier);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering HASHMAP_FOREACH(netdev, network->stacked_netdevs, i) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering hashmap_remove(network->stacked_netdevs, netdev->ifname);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering while ((address = network->static_addresses))
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering while ((fdb_entry = network->static_fdb_entries))
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 LIST_REMOVE(networks, network->manager->networks, network);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering hashmap_remove(network->manager->networks_by_name, network->name);
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 Poetteringint network_get_by_name(Manager *manager, const char *name, Network **ret) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering network = hashmap_get(manager->networks_by_name, name);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringint network_get(Manager *manager, struct udev_device *device,
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering const char *ifname, const struct ether_addr *address,
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering const char *path = NULL, *parent_driver = NULL, *driver = NULL, *devtype = NULL;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering path = udev_device_get_property_value(device, "ID_PATH");
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering parent_driver = udev_device_get_driver(parent);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering driver = udev_device_get_property_value(device, "ID_NET_DRIVER");
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering devtype = udev_device_get_devtype(device);
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 uint8_t name_assign_type = NET_NAME_UNKNOWN;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering attr = udev_device_get_sysattr_value(device, "name_assign_type");
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering (void) safe_atou8(attr, &name_assign_type);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_warning("%s: found matching network '%s', based on potentially unpredictable ifname",
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_debug("%s: found matching network '%s'", ifname, network->filename);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_debug("%s: found matching network '%s'", ifname, network->filename);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringint network_apply(Manager *manager, Network *network, Link *link) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering r = route_new_static(network, 0, &route);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering r = inet_pton(AF_INET, "169.254.0.0", &route->dst_addr.in);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering /* the keys are CamelCase versions of the kind */
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering for (p = kind_string; *p; p++)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering kind = netdev_kind_from_string(kind_string);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid NetDev kind: %s", lvalue);
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering r = netdev_get(network->manager, rvalue, &netdev);
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering log_syntax(unit, LOG_ERR, filename, line, r, "%s could not be found, ignoring assignment: %s", lvalue, rvalue);
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering log_syntax(unit, LOG_ERR, filename, line, 0, "NetDev is not a %s, ignoring assignment: %s", lvalue, rvalue);
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering r = hashmap_put(network->stacked_netdevs, netdev->ifname, netdev);
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering log_syntax(unit, LOG_ERR, filename, line, r, "Can not add VLAN '%s' to network: %m", rvalue);
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
char **domain;
log_syntax(unit, LOG_ERR, filename, line, 0, "'localhost' domain names may not be configured, ignoring assignment: %s", *domain);
domain--;
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
log_syntax(unit, LOG_ERR, filename, line, r, "Cannot add VLAN '%s' to network, ignoring: %m", rvalue);
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) {
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) {
s = ADDRESS_FAMILY_NO;
s = ADDRESS_FAMILY_IPV4;
s = ADDRESS_FAMILY_IPV6;
s = ADDRESS_FAMILY_YES;
*dhcp = s;
DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_client_identifier, dhcp_client_identifier, DCHPClientIdentifier, "Failed to parse client identifier type");
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) {
log_syntax(unit, LOG_ERR, filename, line, r, "IPv6 token can not be the ANY address, ignoring: %s", rvalue);
log_syntax(unit, LOG_ERR, filename, line, 0, "IPv6 token can not be longer than 64 bits, ignoring: %s", rvalue);
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) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue);
*ipv6_privacy_extensions = s;
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) {
r = config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &hn, userdata);
log_syntax(unit, LOG_ERR, filename, line, 0, "Hostname is not valid, ignoring assignment: %s", rvalue);
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) {
r = config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &tz, userdata);
log_syntax(unit, LOG_ERR, filename, line, 0, "Timezone is not valid, ignoring assignment: %s", rvalue);
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) {
const char *p = rvalue;
struct in_addr a, *m;
log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse DNS server address, ignoring: %s", w);
return log_oom();
m[n->n_dhcp_server_dns++] = a;
n->dhcp_server_dns = m;
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) {
const char *p = rvalue;
struct in_addr a, *m;
log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse NTP server address, ignoring: %s", w);
return log_oom();
m[n->n_dhcp_server_ntp++] = a;
n->dhcp_server_ntp = m;