2017-11-18 17:09:20 +01:00
|
|
|
/* SPDX-License-Identifier: LGPL-2.1+ */
|
2013-10-17 03:18:36 +02:00
|
|
|
|
2014-05-08 19:22:53 +02:00
|
|
|
#include <ctype.h>
|
2014-05-15 17:43:14 +02:00
|
|
|
#include <net/if.h>
|
2014-05-08 19:22:53 +02:00
|
|
|
|
2015-10-27 03:01:06 +01:00
|
|
|
#include "alloc-util.h"
|
2013-10-17 03:18:36 +02:00
|
|
|
#include "conf-files.h"
|
|
|
|
#include "conf-parser.h"
|
2015-06-03 01:30:42 +02:00
|
|
|
#include "dns-domain.h"
|
2015-10-25 13:14:12 +01:00
|
|
|
#include "fd-util.h"
|
2015-10-24 22:58:24 +02:00
|
|
|
#include "hostname-util.h"
|
2017-08-14 11:53:10 +02:00
|
|
|
#include "in-addr-util.h"
|
2018-12-04 08:26:09 +01:00
|
|
|
#include "missing_network.h"
|
2015-08-27 13:59:06 +02:00
|
|
|
#include "network-internal.h"
|
2016-11-13 04:59:06 +01:00
|
|
|
#include "networkd-manager.h"
|
2015-10-25 13:14:12 +01:00
|
|
|
#include "networkd-network.h"
|
2015-10-26 16:18:16 +01:00
|
|
|
#include "parse-util.h"
|
2016-01-06 18:36:32 +01:00
|
|
|
#include "set.h"
|
2019-02-21 08:40:34 +01:00
|
|
|
#include "socket-util.h"
|
2015-10-26 22:01:44 +01:00
|
|
|
#include "stat-util.h"
|
2015-10-26 22:31:05 +01:00
|
|
|
#include "string-table.h"
|
2015-10-24 22:58:24 +02:00
|
|
|
#include "string-util.h"
|
2017-08-16 12:29:51 +02:00
|
|
|
#include "strv.h"
|
2015-10-24 22:58:24 +02:00
|
|
|
#include "util.h"
|
2013-10-17 03:18:36 +02:00
|
|
|
|
2019-02-27 14:45:29 +01:00
|
|
|
/* Let's assume that anything above this number is a user misconfiguration. */
|
|
|
|
#define MAX_NTP_SERVERS 128
|
|
|
|
|
2018-11-27 14:25:20 +01:00
|
|
|
static void network_config_hash_func(const NetworkConfigSection *c, struct siphash *state) {
|
2017-02-15 05:30:35 +01:00
|
|
|
siphash24_compress(c->filename, strlen(c->filename), state);
|
|
|
|
siphash24_compress(&c->line, sizeof(c->line), state);
|
|
|
|
}
|
|
|
|
|
2018-11-27 14:25:20 +01:00
|
|
|
static int network_config_compare_func(const NetworkConfigSection *x, const NetworkConfigSection *y) {
|
2017-02-15 05:30:35 +01:00
|
|
|
int r;
|
|
|
|
|
|
|
|
r = strcmp(x->filename, y->filename);
|
|
|
|
if (r != 0)
|
|
|
|
return r;
|
|
|
|
|
2018-08-03 01:00:53 +02:00
|
|
|
return CMP(x->line, y->line);
|
2017-02-15 05:30:35 +01:00
|
|
|
}
|
|
|
|
|
2018-11-27 14:25:20 +01:00
|
|
|
DEFINE_HASH_OPS(network_config_hash_ops, NetworkConfigSection, network_config_hash_func, network_config_compare_func);
|
2017-02-15 05:30:35 +01:00
|
|
|
|
|
|
|
int network_config_section_new(const char *filename, unsigned line, NetworkConfigSection **s) {
|
|
|
|
NetworkConfigSection *cs;
|
|
|
|
|
|
|
|
cs = malloc0(offsetof(NetworkConfigSection, filename) + strlen(filename) + 1);
|
|
|
|
if (!cs)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
strcpy(cs->filename, filename);
|
|
|
|
cs->line = line;
|
|
|
|
|
2018-03-22 16:53:26 +01:00
|
|
|
*s = TAKE_PTR(cs);
|
2017-02-15 05:30:35 +01:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void network_config_section_free(NetworkConfigSection *cs) {
|
2017-09-14 21:51:39 +02:00
|
|
|
free(cs);
|
2017-02-15 05:30:35 +01:00
|
|
|
}
|
|
|
|
|
2017-08-03 01:10:51 +02:00
|
|
|
/* Set defaults following RFC7844 */
|
|
|
|
void network_apply_anonymize_if_set(Network *network) {
|
|
|
|
if (!network->dhcp_anonymize)
|
|
|
|
return;
|
|
|
|
/* RFC7844 3.7
|
|
|
|
SHOULD NOT send the Host Name option */
|
|
|
|
network->dhcp_send_hostname = false;
|
|
|
|
/* RFC7844 section 3.:
|
|
|
|
MAY contain the Client Identifier option
|
|
|
|
Section 3.5:
|
|
|
|
clients MUST use client identifiers based solely
|
|
|
|
on the link-layer address */
|
|
|
|
/* NOTE: Using MAC, as it does not reveal extra information,
|
|
|
|
* and some servers might not answer if this option is not sent */
|
|
|
|
network->dhcp_client_identifier = DHCP_CLIENT_ID_MAC;
|
|
|
|
/* RFC 7844 3.10:
|
|
|
|
SHOULD NOT use the Vendor Class Identifier option */
|
2018-09-27 10:48:11 +02:00
|
|
|
network->dhcp_vendor_class_identifier = mfree(network->dhcp_vendor_class_identifier);
|
2017-08-03 01:10:51 +02:00
|
|
|
/* RFC7844 section 3.6.:
|
|
|
|
The client intending to protect its privacy SHOULD only request a
|
|
|
|
minimal number of options in the PRL and SHOULD also randomly shuffle
|
|
|
|
the ordering of option codes in the PRL. If this random ordering
|
|
|
|
cannot be implemented, the client MAY order the option codes in the
|
|
|
|
PRL by option code number (lowest to highest).
|
|
|
|
*/
|
|
|
|
/* NOTE: dhcp_use_mtu is false by default,
|
|
|
|
* though it was not initiallized to any value in network_load_one.
|
|
|
|
* Maybe there should be another var called *send*?
|
|
|
|
* (to use the MTU sent by the server but to do not send
|
|
|
|
* the option in the PRL). */
|
|
|
|
network->dhcp_use_mtu = false;
|
2017-11-10 16:03:43 +01:00
|
|
|
/* NOTE: when Anonymize=yes, the PRL route options are sent by default,
|
|
|
|
* but this is needed to use them. */
|
|
|
|
network->dhcp_use_routes = true;
|
2017-08-03 01:10:51 +02:00
|
|
|
/* RFC7844 section 3.6.
|
|
|
|
* same comments as previous option */
|
|
|
|
network->dhcp_use_timezone = false;
|
|
|
|
}
|
|
|
|
|
2019-02-21 08:40:34 +01:00
|
|
|
static int network_resolve_netdev_one(Network *network, const char *name, NetDevKind kind, NetDev **ret_netdev) {
|
|
|
|
const char *kind_string;
|
|
|
|
NetDev *netdev;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(network);
|
|
|
|
assert(network->manager);
|
|
|
|
assert(network->filename);
|
|
|
|
assert(ret_netdev);
|
|
|
|
|
|
|
|
if (!name)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (kind == _NETDEV_KIND_TUNNEL)
|
|
|
|
kind_string = "tunnel";
|
|
|
|
else {
|
|
|
|
kind_string = netdev_kind_to_string(kind);
|
|
|
|
if (!kind_string)
|
|
|
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
|
|
|
"%s: Invalid NetDev kind of %s, ignoring assignment.",
|
|
|
|
network->filename, name);
|
|
|
|
}
|
|
|
|
|
|
|
|
r = netdev_get(network->manager, name, &netdev);
|
|
|
|
if (r < 0)
|
|
|
|
return log_error_errno(r, "%s: %s NetDev could not be found, ignoring assignment.",
|
|
|
|
network->filename, name);
|
|
|
|
|
|
|
|
if (netdev->kind != kind && !(kind == _NETDEV_KIND_TUNNEL &&
|
|
|
|
IN_SET(netdev->kind,
|
|
|
|
NETDEV_KIND_IPIP,
|
|
|
|
NETDEV_KIND_SIT,
|
|
|
|
NETDEV_KIND_GRE,
|
|
|
|
NETDEV_KIND_GRETAP,
|
|
|
|
NETDEV_KIND_IP6GRE,
|
|
|
|
NETDEV_KIND_IP6GRETAP,
|
|
|
|
NETDEV_KIND_VTI,
|
|
|
|
NETDEV_KIND_VTI6,
|
|
|
|
NETDEV_KIND_IP6TNL)))
|
|
|
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
|
|
|
"%s: NetDev %s is not a %s, ignoring assignment",
|
|
|
|
network->filename, name, kind_string);
|
|
|
|
|
|
|
|
*ret_netdev = netdev_ref(netdev);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int network_resolve_stacked_netdevs(Network *network) {
|
|
|
|
void *name, *kind;
|
|
|
|
Iterator i;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(network);
|
|
|
|
|
|
|
|
HASHMAP_FOREACH_KEY(kind, name, network->stacked_netdev_names, i) {
|
|
|
|
_cleanup_(netdev_unrefp) NetDev *netdev = NULL;
|
|
|
|
|
|
|
|
r = network_resolve_netdev_one(network, name, PTR_TO_INT(kind), &netdev);
|
|
|
|
if (r <= 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
r = hashmap_ensure_allocated(&network->stacked_netdevs, &string_hash_ops);
|
|
|
|
if (r < 0)
|
|
|
|
return log_oom();
|
|
|
|
|
|
|
|
r = hashmap_put(network->stacked_netdevs, netdev->ifname, netdev);
|
|
|
|
if (r < 0)
|
|
|
|
return log_error_errno(r, "%s: Failed to add NetDev '%s' to network: %m",
|
|
|
|
network->filename, (const char *) name);
|
|
|
|
|
|
|
|
netdev = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-02-27 01:57:16 +01:00
|
|
|
static uint32_t network_get_stacked_netdevs_mtu(Network *network) {
|
|
|
|
uint32_t mtu = 0;
|
|
|
|
NetDev *dev;
|
|
|
|
Iterator i;
|
|
|
|
|
|
|
|
HASHMAP_FOREACH(dev, network->stacked_netdevs, i)
|
|
|
|
if (dev->kind == NETDEV_KIND_VLAN && dev->mtu > 0)
|
|
|
|
/* See vlan_dev_change_mtu() in kernel.
|
|
|
|
* Note that the additional 4bytes may not be necessary for all devices. */
|
|
|
|
mtu = MAX(mtu, dev->mtu + 4);
|
|
|
|
|
|
|
|
else if (dev->kind == NETDEV_KIND_MACVLAN && dev->mtu > mtu)
|
|
|
|
/* See macvlan_change_mtu() in kernel. */
|
|
|
|
mtu = dev->mtu;
|
|
|
|
|
|
|
|
return mtu;
|
|
|
|
}
|
|
|
|
|
2019-02-19 04:36:15 +01:00
|
|
|
static int network_verify(Network *network) {
|
|
|
|
Address *address;
|
|
|
|
Route *route;
|
2019-02-27 01:57:16 +01:00
|
|
|
uint32_t mtu;
|
2019-02-19 04:36:15 +01:00
|
|
|
|
|
|
|
assert(network);
|
|
|
|
assert(network->filename);
|
|
|
|
|
2019-02-21 08:40:34 +01:00
|
|
|
/* skip out early if configuration does not match the environment */
|
|
|
|
if (!net_match_config(NULL, NULL, NULL, NULL, NULL,
|
|
|
|
network->match_host, network->match_virt, network->match_kernel_cmdline,
|
|
|
|
network->match_kernel_version, network->match_arch,
|
|
|
|
NULL, NULL, NULL, NULL, NULL))
|
|
|
|
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
|
2019-02-27 13:34:51 +01:00
|
|
|
"%s: Conditions in the file do not match the system environment, skipping.",
|
|
|
|
network->filename);
|
2019-02-21 08:40:34 +01:00
|
|
|
|
|
|
|
(void) network_resolve_netdev_one(network, network->bond_name, NETDEV_KIND_BOND, &network->bond);
|
|
|
|
(void) network_resolve_netdev_one(network, network->bridge_name, NETDEV_KIND_BRIDGE, &network->bridge);
|
|
|
|
(void) network_resolve_netdev_one(network, network->vrf_name, NETDEV_KIND_VRF, &network->vrf);
|
|
|
|
(void) network_resolve_stacked_netdevs(network);
|
|
|
|
|
|
|
|
/* Free unnecessary entries. */
|
|
|
|
network->bond_name = mfree(network->bond_name);
|
|
|
|
network->bridge_name = mfree(network->bridge_name);
|
|
|
|
network->vrf_name = mfree(network->vrf_name);
|
|
|
|
network->stacked_netdev_names = hashmap_free_free_key(network->stacked_netdev_names);
|
|
|
|
|
2019-02-19 04:36:15 +01:00
|
|
|
if (network->bond) {
|
|
|
|
/* Bonding slave does not support addressing. */
|
|
|
|
if (network->ipv6_accept_ra > 0) {
|
2019-02-20 21:30:06 +01:00
|
|
|
log_warning("%s: Cannot enable IPv6AcceptRA= when Bond= is specified, disabling IPv6AcceptRA=.",
|
|
|
|
network->filename);
|
2019-02-19 04:36:15 +01:00
|
|
|
network->ipv6_accept_ra = 0;
|
|
|
|
}
|
|
|
|
if (network->link_local >= 0 && network->link_local != ADDRESS_FAMILY_NO) {
|
2019-02-20 21:30:06 +01:00
|
|
|
log_warning("%s: Cannot enable LinkLocalAddressing= when Bond= is specified, disabling LinkLocalAddressing=.",
|
|
|
|
network->filename);
|
2019-02-19 04:36:15 +01:00
|
|
|
network->link_local = ADDRESS_FAMILY_NO;
|
|
|
|
}
|
|
|
|
if (network->dhcp != ADDRESS_FAMILY_NO) {
|
2019-02-20 21:30:06 +01:00
|
|
|
log_warning("%s: Cannot enable DHCP= when Bond= is specified, disabling DHCP=.",
|
|
|
|
network->filename);
|
2019-02-19 04:36:15 +01:00
|
|
|
network->dhcp = ADDRESS_FAMILY_NO;
|
|
|
|
}
|
|
|
|
if (network->dhcp_server) {
|
2019-02-20 21:30:06 +01:00
|
|
|
log_warning("%s: Cannot enable DHCPServer= when Bond= is specified, disabling DHCPServer=.",
|
|
|
|
network->filename);
|
2019-02-19 04:36:15 +01:00
|
|
|
network->dhcp_server = false;
|
|
|
|
}
|
|
|
|
if (network->n_static_addresses > 0) {
|
2019-02-20 21:30:06 +01:00
|
|
|
log_warning("%s: Cannot set addresses when Bond= is specified, ignoring addresses.",
|
|
|
|
network->filename);
|
2019-02-19 04:36:15 +01:00
|
|
|
while ((address = network->static_addresses))
|
|
|
|
address_free(address);
|
|
|
|
}
|
|
|
|
if (network->n_static_routes > 0) {
|
2019-02-20 21:30:06 +01:00
|
|
|
log_warning("%s: Cannot set routes when Bond= is specified, ignoring routes.",
|
|
|
|
network->filename);
|
2019-02-19 04:36:15 +01:00
|
|
|
while ((route = network->static_routes))
|
|
|
|
route_free(route);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (network->link_local < 0)
|
2019-02-20 02:17:11 +01:00
|
|
|
network->link_local = network->bridge ? ADDRESS_FAMILY_NO : ADDRESS_FAMILY_IPV6;
|
|
|
|
|
|
|
|
if (network->ipv6_accept_ra < 0 && network->bridge)
|
|
|
|
network->ipv6_accept_ra = false;
|
2019-02-19 04:36:15 +01:00
|
|
|
|
|
|
|
/* IPMasquerade=yes implies IPForward=yes */
|
|
|
|
if (network->ip_masquerade)
|
|
|
|
network->ip_forward |= ADDRESS_FAMILY_IPV4;
|
|
|
|
|
2019-02-27 01:57:16 +01:00
|
|
|
network->mtu_is_set = network->mtu > 0;
|
|
|
|
mtu = network_get_stacked_netdevs_mtu(network);
|
|
|
|
if (network->mtu < mtu) {
|
|
|
|
if (network->mtu_is_set)
|
|
|
|
log_notice("%s: Bumping MTUBytes= from %"PRIu32" to %"PRIu32" because of stacked device",
|
|
|
|
network->filename, network->mtu, mtu);
|
|
|
|
network->mtu = mtu;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (network->mtu_is_set && network->dhcp_use_mtu) {
|
2019-02-19 04:36:15 +01:00
|
|
|
log_warning("%s: MTUBytes= in [Link] section and UseMTU= in [DHCP] section are set. "
|
|
|
|
"Disabling UseMTU=.", network->filename);
|
|
|
|
network->dhcp_use_mtu = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
LIST_FOREACH(routes, route, network->static_routes)
|
|
|
|
if (!route->family)
|
|
|
|
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
|
|
|
|
"%s: Route section without Gateway field configured. "
|
|
|
|
"Ignoring %s.",
|
|
|
|
network->filename, network->filename);
|
|
|
|
|
|
|
|
LIST_FOREACH(addresses, address, network->static_addresses)
|
|
|
|
if (!address->family)
|
|
|
|
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
|
|
|
|
"%s: Address section without Address field configured. "
|
|
|
|
"Ignoring %s.",
|
|
|
|
network->filename, network->filename);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-11-04 22:27:07 +01:00
|
|
|
int network_load_one(Manager *manager, const char *filename) {
|
2019-01-18 04:55:15 +01:00
|
|
|
_cleanup_free_ char *fname = NULL, *name = NULL;
|
tree-wide: drop redundant _cleanup_ macros (#8810)
This drops a good number of type-specific _cleanup_ macros, and patches
all users to just use the generic ones.
In most recent code we abstained from defining type-specific macros, and
this basically removes all those added already, with the exception of
the really low-level ones.
Having explicit macros for this is not too useful, as the expression
without the extra macro is generally just 2ch wider. We should generally
emphesize generic code, unless there are really good reasons for
specific code, hence let's follow this in this case too.
Note that _cleanup_free_ and similar really low-level, libc'ish, Linux
API'ish macros continue to be defined, only the really high-level OO
ones are dropped. From now on this should really be the rule: for really
low-level stuff, such as memory allocation, fd handling and so one, go
ahead and define explicit per-type macros, but for high-level, specific
program code, just use the generic _cleanup_() macro directly, in order
to keep things simple and as readable as possible for the uninitiated.
Note that before this patch some of the APIs (notable libudev ones) were
already used with the high-level macros at some places and with the
generic _cleanup_ macro at others. With this patch we hence unify on the
latter.
2018-04-25 12:31:45 +02:00
|
|
|
_cleanup_(network_freep) Network *network = NULL;
|
2013-10-17 03:18:36 +02:00
|
|
|
_cleanup_fclose_ FILE *file = NULL;
|
2016-07-09 16:55:26 +02:00
|
|
|
const char *dropin_dirname;
|
2019-01-18 04:55:15 +01:00
|
|
|
char *d;
|
2013-10-17 03:18:36 +02:00
|
|
|
int r;
|
|
|
|
|
2013-12-16 18:55:59 +01:00
|
|
|
assert(manager);
|
|
|
|
assert(filename);
|
|
|
|
|
2013-10-17 03:18:36 +02:00
|
|
|
file = fopen(filename, "re");
|
|
|
|
if (!file) {
|
|
|
|
if (errno == ENOENT)
|
|
|
|
return 0;
|
network: beef up ipv6 RA support considerably
This reworks sd-ndisc and networkd substantially to support IPv6 RA much more
comprehensively. Since the API is extended quite a bit networkd has been ported
over too, and the patch is not as straight-forward as one could wish. The
rework includes:
- Support for DNSSL, RDNSS and RA routing options in sd-ndisc and networkd. Two
new configuration options have been added to networkd to make this
configurable.
- sd-ndisc now exposes an sd_ndisc_router object that encapsulates a full RA
message, and has direct, friendly acessor functions for the singleton RA
properties, as well as an iterative interface to iterate through known and
unsupported options. The router object may either be retrieved from the wire,
or generated from raw data. In many ways the sd-ndisc API now matches the
sd-lldp API, except that no implicit database of seen data is kept. (Note
that sd-ndisc actually had a half-written, but unused implementaiton of such
a store, which is removed now.)
- sd-ndisc will now collect the reception timestamps of RA, which is useful to
make sd_ndisc_router fully descriptive of what it covers.
Fixes: #1079
2016-06-02 20:38:12 +02:00
|
|
|
|
|
|
|
return -errno;
|
2013-10-17 03:18:36 +02:00
|
|
|
}
|
|
|
|
|
2014-07-17 00:59:49 +02:00
|
|
|
if (null_or_empty_fd(fileno(file))) {
|
|
|
|
log_debug("Skipping empty file: %s", filename);
|
2014-04-19 19:05:37 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-01-18 04:55:15 +01:00
|
|
|
fname = strdup(filename);
|
|
|
|
if (!fname)
|
|
|
|
return log_oom();
|
|
|
|
|
|
|
|
name = strdup(basename(filename));
|
|
|
|
if (!name)
|
|
|
|
return log_oom();
|
|
|
|
|
|
|
|
d = strrchr(name, '.');
|
|
|
|
if (!d)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
*d = '\0';
|
|
|
|
|
|
|
|
dropin_dirname = strjoina(name, ".network.d");
|
|
|
|
|
2018-11-12 06:55:52 +01:00
|
|
|
network = new(Network, 1);
|
2013-10-17 03:18:36 +02:00
|
|
|
if (!network)
|
|
|
|
return log_oom();
|
|
|
|
|
2018-11-12 06:55:52 +01:00
|
|
|
*network = (Network) {
|
2019-01-18 04:55:15 +01:00
|
|
|
.filename = TAKE_PTR(fname),
|
|
|
|
.name = TAKE_PTR(name),
|
2018-11-12 06:55:52 +01:00
|
|
|
|
|
|
|
.required_for_online = true,
|
|
|
|
.dhcp = ADDRESS_FAMILY_NO,
|
|
|
|
.dhcp_use_ntp = true,
|
|
|
|
.dhcp_use_dns = true,
|
|
|
|
.dhcp_use_hostname = true,
|
|
|
|
.dhcp_use_routes = true,
|
|
|
|
/* NOTE: this var might be overwriten by network_apply_anonymize_if_set */
|
|
|
|
.dhcp_send_hostname = true,
|
|
|
|
/* To enable/disable RFC7844 Anonymity Profiles */
|
|
|
|
.dhcp_anonymize = false,
|
|
|
|
.dhcp_route_metric = DHCP_ROUTE_METRIC,
|
|
|
|
/* NOTE: this var might be overwrite by network_apply_anonymize_if_set */
|
|
|
|
.dhcp_client_identifier = DHCP_CLIENT_ID_DUID,
|
|
|
|
.dhcp_route_table = RT_TABLE_MAIN,
|
|
|
|
.dhcp_route_table_set = false,
|
|
|
|
/* NOTE: from man: UseMTU=... Defaults to false*/
|
|
|
|
.dhcp_use_mtu = false,
|
|
|
|
/* NOTE: from man: UseTimezone=... Defaults to "no".*/
|
|
|
|
.dhcp_use_timezone = false,
|
|
|
|
.rapid_commit = true,
|
|
|
|
|
|
|
|
.dhcp_server_emit_dns = true,
|
|
|
|
.dhcp_server_emit_ntp = true,
|
|
|
|
.dhcp_server_emit_router = true,
|
|
|
|
.dhcp_server_emit_timezone = true,
|
|
|
|
|
|
|
|
.router_emit_dns = true,
|
|
|
|
.router_emit_domains = true,
|
|
|
|
|
|
|
|
.use_bpdu = -1,
|
|
|
|
.hairpin = -1,
|
|
|
|
.fast_leave = -1,
|
|
|
|
.allow_port_to_be_root = -1,
|
|
|
|
.unicast_flood = -1,
|
2018-12-03 11:47:36 +01:00
|
|
|
.multicast_to_unicast = -1,
|
2018-11-12 06:55:52 +01:00
|
|
|
.priority = LINK_BRIDGE_PORT_PRIORITY_INVALID,
|
|
|
|
|
|
|
|
.lldp_mode = LLDP_MODE_ROUTERS_ONLY,
|
|
|
|
|
2018-12-04 15:34:04 +01:00
|
|
|
.dns_default_route = -1,
|
2018-11-12 06:55:52 +01:00
|
|
|
.llmnr = RESOLVE_SUPPORT_YES,
|
|
|
|
.mdns = RESOLVE_SUPPORT_NO,
|
|
|
|
.dnssec_mode = _DNSSEC_MODE_INVALID,
|
|
|
|
.dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID,
|
|
|
|
|
2019-02-19 04:36:15 +01:00
|
|
|
/* If LinkLocalAddressing= is not set, then set to ADDRESS_FAMILY_IPV6 later. */
|
|
|
|
.link_local = _ADDRESS_FAMILY_BOOLEAN_INVALID,
|
2018-11-12 06:55:52 +01:00
|
|
|
|
|
|
|
.ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_NO,
|
|
|
|
.ipv6_accept_ra = -1,
|
|
|
|
.ipv6_dad_transmits = -1,
|
|
|
|
.ipv6_hop_limit = -1,
|
|
|
|
.ipv6_proxy_ndp = -1,
|
|
|
|
.duid.type = _DUID_TYPE_INVALID,
|
|
|
|
.proxy_arp = -1,
|
|
|
|
.arp = -1,
|
|
|
|
.multicast = -1,
|
|
|
|
.allmulticast = -1,
|
|
|
|
.ipv6_accept_ra_use_dns = true,
|
2019-02-14 16:35:17 +01:00
|
|
|
.ipv6_accept_ra_use_autonomous_prefix = true,
|
|
|
|
.ipv6_accept_ra_use_onlink_prefix = true,
|
2018-11-12 06:55:52 +01:00
|
|
|
.ipv6_accept_ra_route_table = RT_TABLE_MAIN,
|
2019-02-12 04:42:10 +01:00
|
|
|
.ipv6_accept_ra_route_table_set = false,
|
2018-11-12 06:55:52 +01:00
|
|
|
};
|
2013-10-17 03:18:36 +02:00
|
|
|
|
2019-01-02 14:30:24 +01:00
|
|
|
r = config_parse_many(filename, NETWORK_DIRS, dropin_dirname,
|
2016-09-10 13:19:41 +02:00
|
|
|
"Match\0"
|
|
|
|
"Link\0"
|
|
|
|
"Network\0"
|
|
|
|
"Address\0"
|
2018-11-29 04:00:58 +01:00
|
|
|
"Neighbor\0"
|
2017-04-25 12:36:50 +02:00
|
|
|
"IPv6AddressLabel\0"
|
2017-09-14 21:51:39 +02:00
|
|
|
"RoutingPolicyRule\0"
|
2016-09-10 13:19:41 +02:00
|
|
|
"Route\0"
|
|
|
|
"DHCP\0"
|
|
|
|
"DHCPv4\0" /* compat */
|
|
|
|
"DHCPServer\0"
|
|
|
|
"IPv6AcceptRA\0"
|
2017-02-11 00:47:55 +01:00
|
|
|
"IPv6NDPProxyAddress\0"
|
2016-09-10 13:19:41 +02:00
|
|
|
"Bridge\0"
|
|
|
|
"BridgeFDB\0"
|
2017-05-12 15:48:29 +02:00
|
|
|
"BridgeVLAN\0"
|
2017-05-12 15:48:30 +02:00
|
|
|
"IPv6PrefixDelegation\0"
|
2018-04-10 17:26:20 +02:00
|
|
|
"IPv6Prefix\0"
|
|
|
|
"CAN\0",
|
2016-09-10 13:19:41 +02:00
|
|
|
config_item_perf_lookup, network_network_gperf_lookup,
|
2017-11-09 00:26:11 +01:00
|
|
|
CONFIG_PARSE_WARN, network);
|
2019-02-22 01:38:19 +01:00
|
|
|
if (r < 0)
|
2013-10-17 03:18:36 +02:00
|
|
|
return r;
|
|
|
|
|
2017-08-03 01:10:51 +02:00
|
|
|
network_apply_anonymize_if_set(network);
|
|
|
|
|
2013-10-17 03:18:36 +02:00
|
|
|
LIST_PREPEND(networks, manager->networks, network);
|
2019-02-22 01:38:19 +01:00
|
|
|
network->manager = manager;
|
2014-01-04 21:13:47 +01:00
|
|
|
|
2015-02-08 13:29:35 +01:00
|
|
|
r = hashmap_ensure_allocated(&manager->networks_by_name, &string_hash_ops);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
r = hashmap_put(manager->networks_by_name, network->name, network);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
2019-02-19 04:36:15 +01:00
|
|
|
if (network_verify(network) < 0)
|
|
|
|
return 0;
|
2014-01-04 21:13:47 +01:00
|
|
|
|
2013-10-17 03:18:36 +02:00
|
|
|
network = NULL;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int network_load(Manager *manager) {
|
|
|
|
Network *network;
|
2014-01-03 01:49:49 +01:00
|
|
|
_cleanup_strv_free_ char **files = NULL;
|
|
|
|
char **f;
|
2013-10-17 03:18:36 +02:00
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(manager);
|
|
|
|
|
|
|
|
while ((network = manager->networks))
|
|
|
|
network_free(network);
|
|
|
|
|
2019-01-02 14:30:24 +01:00
|
|
|
r = conf_files_list_strv(&files, ".network", NULL, 0, NETWORK_DIRS);
|
2014-11-28 18:50:43 +01:00
|
|
|
if (r < 0)
|
|
|
|
return log_error_errno(r, "Failed to enumerate network files: %m");
|
2013-10-17 03:18:36 +02:00
|
|
|
|
|
|
|
STRV_FOREACH_BACKWARDS(f, files) {
|
|
|
|
r = network_load_one(manager, *f);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void network_free(Network *network) {
|
2017-02-11 00:47:55 +01:00
|
|
|
IPv6ProxyNDPAddress *ipv6_proxy_ndp_address;
|
2017-09-14 21:51:39 +02:00
|
|
|
RoutingPolicyRule *rule;
|
|
|
|
FdbEntry *fdb_entry;
|
2018-11-29 04:00:58 +01:00
|
|
|
Neighbor *neighbor;
|
2017-04-25 12:36:50 +02:00
|
|
|
AddressLabel *label;
|
2017-05-12 15:48:28 +02:00
|
|
|
Prefix *prefix;
|
2017-09-14 21:51:39 +02:00
|
|
|
Address *address;
|
|
|
|
Route *route;
|
2013-10-17 03:18:36 +02:00
|
|
|
|
|
|
|
if (!network)
|
|
|
|
return;
|
|
|
|
|
|
|
|
free(network->filename);
|
|
|
|
|
2018-05-09 04:59:18 +02:00
|
|
|
set_free_free(network->match_mac);
|
2015-02-10 18:30:16 +01:00
|
|
|
strv_free(network->match_path);
|
|
|
|
strv_free(network->match_driver);
|
|
|
|
strv_free(network->match_type);
|
|
|
|
strv_free(network->match_name);
|
2013-10-17 03:18:36 +02:00
|
|
|
|
|
|
|
free(network->description);
|
2014-07-14 10:04:18 +02:00
|
|
|
free(network->dhcp_vendor_class_identifier);
|
2018-05-07 14:21:02 +02:00
|
|
|
strv_free(network->dhcp_user_class);
|
2016-01-25 21:47:02 +01:00
|
|
|
free(network->dhcp_hostname);
|
2013-10-17 03:18:36 +02:00
|
|
|
|
2014-12-04 21:57:13 +01:00
|
|
|
free(network->mac);
|
|
|
|
|
2014-07-23 13:48:18 +02:00
|
|
|
strv_free(network->ntp);
|
2016-11-18 17:04:26 +01:00
|
|
|
free(network->dns);
|
2019-02-20 22:50:25 +01:00
|
|
|
ordered_set_free_free(network->search_domains);
|
|
|
|
ordered_set_free_free(network->route_domains);
|
2015-02-17 13:06:57 +01:00
|
|
|
strv_free(network->bind_carrier);
|
2018-11-11 03:20:51 +01:00
|
|
|
|
2019-02-20 22:50:25 +01:00
|
|
|
ordered_set_free_free(network->router_search_domains);
|
2018-11-11 03:20:51 +01:00
|
|
|
free(network->router_dns);
|
2014-01-05 23:01:10 +01:00
|
|
|
|
2019-02-21 08:40:34 +01:00
|
|
|
free(network->bridge_name);
|
|
|
|
free(network->bond_name);
|
|
|
|
free(network->vrf_name);
|
|
|
|
hashmap_free_free_key(network->stacked_netdev_names);
|
2014-05-08 19:28:17 +02:00
|
|
|
netdev_unref(network->bridge);
|
|
|
|
netdev_unref(network->bond);
|
2016-06-13 01:05:49 +02:00
|
|
|
netdev_unref(network->vrf);
|
2018-11-11 03:21:13 +01:00
|
|
|
hashmap_free_with_destructor(network->stacked_netdevs, netdev_unref);
|
2014-06-16 08:24:33 +02:00
|
|
|
|
2014-01-01 15:16:10 +01:00
|
|
|
while ((route = network->static_routes))
|
2013-10-17 03:18:36 +02:00
|
|
|
route_free(route);
|
|
|
|
|
2014-01-01 15:16:10 +01:00
|
|
|
while ((address = network->static_addresses))
|
2013-10-17 03:18:36 +02:00
|
|
|
address_free(address);
|
|
|
|
|
2014-12-17 16:35:36 +01:00
|
|
|
while ((fdb_entry = network->static_fdb_entries))
|
|
|
|
fdb_entry_free(fdb_entry);
|
|
|
|
|
2017-02-11 00:47:55 +01:00
|
|
|
while ((ipv6_proxy_ndp_address = network->ipv6_proxy_ndp_addresses))
|
|
|
|
ipv6_proxy_ndp_address_free(ipv6_proxy_ndp_address);
|
|
|
|
|
2018-11-29 04:00:58 +01:00
|
|
|
while ((neighbor = network->neighbors))
|
|
|
|
neighbor_free(neighbor);
|
|
|
|
|
2017-04-25 12:36:50 +02:00
|
|
|
while ((label = network->address_labels))
|
|
|
|
address_label_free(label);
|
|
|
|
|
2017-05-12 15:48:28 +02:00
|
|
|
while ((prefix = network->static_prefixes))
|
|
|
|
prefix_free(prefix);
|
|
|
|
|
2017-09-14 21:51:39 +02:00
|
|
|
while ((rule = network->rules))
|
|
|
|
routing_policy_rule_free(rule);
|
|
|
|
|
2013-11-19 16:54:42 +01:00
|
|
|
hashmap_free(network->addresses_by_section);
|
|
|
|
hashmap_free(network->routes_by_section);
|
2014-12-17 16:35:36 +01:00
|
|
|
hashmap_free(network->fdb_entries_by_section);
|
2018-11-29 04:00:58 +01:00
|
|
|
hashmap_free(network->neighbors_by_section);
|
2017-04-25 12:36:50 +02:00
|
|
|
hashmap_free(network->address_labels_by_section);
|
2017-05-12 15:48:28 +02:00
|
|
|
hashmap_free(network->prefixes_by_section);
|
2017-09-14 21:51:39 +02:00
|
|
|
hashmap_free(network->rules_by_section);
|
2013-11-19 16:54:42 +01:00
|
|
|
|
2015-02-08 13:29:35 +01:00
|
|
|
if (network->manager) {
|
|
|
|
if (network->manager->networks)
|
|
|
|
LIST_REMOVE(networks, network->manager->networks, network);
|
|
|
|
|
2018-11-09 03:43:50 +01:00
|
|
|
if (network->manager->networks_by_name && network->name)
|
2015-02-08 13:29:35 +01:00
|
|
|
hashmap_remove(network->manager->networks_by_name, network->name);
|
2018-07-02 20:19:15 +02:00
|
|
|
|
|
|
|
if (network->manager->duids_requesting_uuid)
|
|
|
|
set_remove(network->manager->duids_requesting_uuid, &network->duid);
|
2015-02-08 13:29:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
free(network->name);
|
2013-10-17 03:18:36 +02:00
|
|
|
|
2014-03-24 23:45:33 +01:00
|
|
|
condition_free_list(network->match_host);
|
|
|
|
condition_free_list(network->match_virt);
|
core,udev,networkd: add ConditionKernelVersion=
This adds a simple condition/assert/match to the service manager, to
udev's .link handling and to networkd, for matching the kernel version
string.
In this version we only do fnmatch() based globbing, but we might want
to extend that to version comparisons later on, if we like, by slightly
extending the syntax with ">=", "<=", ">", "<" and "==" expressions.
2017-12-13 20:34:13 +01:00
|
|
|
condition_free_list(network->match_kernel_cmdline);
|
|
|
|
condition_free_list(network->match_kernel_version);
|
2014-03-24 23:45:33 +01:00
|
|
|
condition_free_list(network->match_arch);
|
|
|
|
|
2015-08-26 19:19:32 +02:00
|
|
|
free(network->dhcp_server_timezone);
|
2015-08-27 14:48:37 +02:00
|
|
|
free(network->dhcp_server_dns);
|
|
|
|
free(network->dhcp_server_ntp);
|
2015-08-26 19:19:32 +02:00
|
|
|
|
2016-01-06 18:36:32 +01:00
|
|
|
set_free_free(network->dnssec_negative_trust_anchors);
|
|
|
|
|
2013-10-17 03:18:36 +02:00
|
|
|
free(network);
|
|
|
|
}
|
|
|
|
|
2015-02-08 13:29:35 +01:00
|
|
|
int network_get_by_name(Manager *manager, const char *name, Network **ret) {
|
|
|
|
Network *network;
|
|
|
|
|
|
|
|
assert(manager);
|
|
|
|
assert(name);
|
|
|
|
assert(ret);
|
|
|
|
|
|
|
|
network = hashmap_get(manager->networks_by_name, name);
|
|
|
|
if (!network)
|
|
|
|
return -ENOENT;
|
|
|
|
|
|
|
|
*ret = network;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-08-22 07:30:49 +02:00
|
|
|
int network_get(Manager *manager, sd_device *device,
|
2014-04-15 14:21:44 +02:00
|
|
|
const char *ifname, const struct ether_addr *address,
|
|
|
|
Network **ret) {
|
2019-02-16 16:47:45 +01:00
|
|
|
const char *path = NULL, *driver = NULL, *devtype = NULL;
|
2018-08-22 07:30:49 +02:00
|
|
|
Network *network;
|
2013-10-17 03:18:36 +02:00
|
|
|
|
|
|
|
assert(manager);
|
|
|
|
assert(ret);
|
2015-03-26 21:53:38 +01:00
|
|
|
|
2015-05-12 00:22:29 +02:00
|
|
|
if (device) {
|
2018-08-22 07:30:49 +02:00
|
|
|
(void) sd_device_get_property_value(device, "ID_PATH", &path);
|
2015-03-26 21:53:38 +01:00
|
|
|
|
2018-08-22 07:30:49 +02:00
|
|
|
(void) sd_device_get_property_value(device, "ID_NET_DRIVER", &driver);
|
2015-03-26 21:53:38 +01:00
|
|
|
|
2018-08-22 07:30:49 +02:00
|
|
|
(void) sd_device_get_devtype(device, &devtype);
|
2015-05-12 00:22:29 +02:00
|
|
|
}
|
2013-10-17 03:18:36 +02:00
|
|
|
|
|
|
|
LIST_FOREACH(networks, network, manager->networks) {
|
|
|
|
if (net_match_config(network->match_mac, network->match_path,
|
2014-04-15 14:21:44 +02:00
|
|
|
network->match_driver, network->match_type,
|
|
|
|
network->match_name, network->match_host,
|
core,udev,networkd: add ConditionKernelVersion=
This adds a simple condition/assert/match to the service manager, to
udev's .link handling and to networkd, for matching the kernel version
string.
In this version we only do fnmatch() based globbing, but we might want
to extend that to version comparisons later on, if we like, by slightly
extending the syntax with ">=", "<=", ">", "<" and "==" expressions.
2017-12-13 20:34:13 +01:00
|
|
|
network->match_virt, network->match_kernel_cmdline,
|
|
|
|
network->match_kernel_version, network->match_arch,
|
2019-02-16 16:47:45 +01:00
|
|
|
address, path, driver, devtype, ifname)) {
|
2015-05-12 00:22:29 +02:00
|
|
|
if (network->match_name && device) {
|
2014-12-07 13:00:01 +01:00
|
|
|
const char *attr;
|
|
|
|
uint8_t name_assign_type = NET_NAME_UNKNOWN;
|
|
|
|
|
2018-08-22 07:30:49 +02:00
|
|
|
if (sd_device_get_sysattr_value(device, "name_assign_type", &attr) >= 0)
|
2015-03-14 03:20:01 +01:00
|
|
|
(void) safe_atou8(attr, &name_assign_type);
|
2014-12-05 15:56:10 +01:00
|
|
|
|
|
|
|
if (name_assign_type == NET_NAME_ENUM)
|
2015-09-30 19:37:52 +02:00
|
|
|
log_warning("%s: found matching network '%s', based on potentially unpredictable ifname",
|
|
|
|
ifname, network->filename);
|
2014-12-05 15:56:10 +01:00
|
|
|
else
|
2015-09-30 19:37:52 +02:00
|
|
|
log_debug("%s: found matching network '%s'", ifname, network->filename);
|
2014-12-05 15:56:10 +01:00
|
|
|
} else
|
2015-09-30 19:37:52 +02:00
|
|
|
log_debug("%s: found matching network '%s'", ifname, network->filename);
|
2014-12-05 15:56:10 +01:00
|
|
|
|
2013-10-17 03:18:36 +02:00
|
|
|
*ret = network;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*ret = NULL;
|
|
|
|
|
|
|
|
return -ENOENT;
|
|
|
|
}
|
|
|
|
|
2016-09-28 12:32:31 +02:00
|
|
|
int network_apply(Network *network, Link *link) {
|
2013-10-17 03:18:36 +02:00
|
|
|
int r;
|
|
|
|
|
2015-10-01 21:14:06 +02:00
|
|
|
assert(network);
|
|
|
|
assert(link);
|
|
|
|
|
2013-10-17 03:18:36 +02:00
|
|
|
link->network = network;
|
|
|
|
|
2014-07-25 02:09:29 +02:00
|
|
|
if (network->ipv4ll_route) {
|
|
|
|
Route *route;
|
|
|
|
|
2017-03-31 08:29:20 +02:00
|
|
|
r = route_new_static(network, NULL, 0, &route);
|
2014-07-25 02:09:29 +02:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
2015-10-25 15:09:40 +01:00
|
|
|
r = inet_pton(AF_INET, "169.254.0.0", &route->dst.in);
|
2014-07-25 02:09:29 +02:00
|
|
|
if (r == 0)
|
|
|
|
return -EINVAL;
|
|
|
|
if (r < 0)
|
|
|
|
return -errno;
|
|
|
|
|
|
|
|
route->family = AF_INET;
|
|
|
|
route->dst_prefixlen = 16;
|
|
|
|
route->scope = RT_SCOPE_LINK;
|
2015-10-26 17:04:57 +01:00
|
|
|
route->priority = IPV4LL_ROUTE_METRIC;
|
2014-07-25 02:09:29 +02:00
|
|
|
route->protocol = RTPROT_STATIC;
|
|
|
|
}
|
|
|
|
|
2016-11-18 17:04:26 +01:00
|
|
|
if (network->n_dns > 0 ||
|
networkd: rework Domains= setting
Previously, .network files only knew a vaguely defined "Domains=" concept, for which the documentation declared it was
the "DNS domain" for the network connection, without specifying what that means.
With this the Domains setting is reworked, so that there are now "routing" domains and "search" domains. The former are
to be used by resolved to route DNS request to specific network interfaces, the latter is to be used for searching
single-label hostnames with (in addition to being used for routing). Both settings are configured in the "Domains="
setting. Normal domain names listed in it are now considered search domains (for compatibility with existing setups),
while those prefixed with "~" are considered routing domains only. To route all lookups to a specific interface the
routing domain "." may be used, referring to the root domain. An alternative syntax for this is the "*", as was already
implemented before using the "wildcard" domain concept.
This commit adds proper parsers for this new logic, and exposes this via the sd-network API. This information is not
used by resolved yet, this will be added in a later commit.
2016-01-25 19:46:00 +01:00
|
|
|
!strv_isempty(network->ntp) ||
|
2019-02-20 22:50:25 +01:00
|
|
|
!ordered_set_isempty(network->search_domains) ||
|
|
|
|
!ordered_set_isempty(network->route_domains))
|
2015-09-30 18:17:43 +02:00
|
|
|
link_dirty(link);
|
2014-01-05 23:01:10 +01:00
|
|
|
|
2013-10-17 03:18:36 +02:00
|
|
|
return 0;
|
|
|
|
}
|
2013-11-24 23:37:56 +01:00
|
|
|
|
2016-04-21 02:34:13 +02:00
|
|
|
bool network_has_static_ipv6_addresses(Network *network) {
|
|
|
|
Address *address;
|
|
|
|
|
|
|
|
assert(network);
|
|
|
|
|
|
|
|
LIST_FOREACH(addresses, address, network->static_addresses) {
|
|
|
|
if (address->family == AF_INET6)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-02-21 08:40:34 +01:00
|
|
|
int config_parse_stacked_netdev(const char *unit,
|
2013-11-24 23:37:56 +01:00
|
|
|
const char *filename,
|
|
|
|
unsigned line,
|
|
|
|
const char *section,
|
|
|
|
unsigned section_line,
|
|
|
|
const char *lvalue,
|
|
|
|
int ltype,
|
|
|
|
const char *rvalue,
|
|
|
|
void *data,
|
|
|
|
void *userdata) {
|
2019-02-21 08:40:34 +01:00
|
|
|
_cleanup_free_ char *kind_string = NULL, *name = NULL;
|
|
|
|
Hashmap **h = data;
|
2014-05-08 19:22:53 +02:00
|
|
|
NetDevKind kind;
|
2019-02-21 08:40:34 +01:00
|
|
|
char *p;
|
2013-11-24 23:37:56 +01:00
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(filename);
|
|
|
|
assert(lvalue);
|
|
|
|
assert(rvalue);
|
|
|
|
assert(data);
|
|
|
|
|
2019-02-21 08:40:34 +01:00
|
|
|
if (ltype == _NETDEV_KIND_TUNNEL)
|
|
|
|
kind = _NETDEV_KIND_TUNNEL;
|
|
|
|
else {
|
|
|
|
kind_string = strdup(lvalue);
|
|
|
|
if (!kind_string)
|
|
|
|
return log_oom();
|
2014-01-21 21:58:08 +01:00
|
|
|
|
2019-02-21 08:40:34 +01:00
|
|
|
/* the keys are CamelCase versions of the kind */
|
|
|
|
for (p = kind_string; *p; p++)
|
|
|
|
*p = tolower(*p);
|
2014-01-21 21:58:08 +01:00
|
|
|
|
2019-02-21 08:40:34 +01:00
|
|
|
kind = netdev_kind_from_string(kind_string);
|
|
|
|
if (kind < 0 || IN_SET(kind, NETDEV_KIND_BRIDGE, NETDEV_KIND_BOND, NETDEV_KIND_VRF)) {
|
|
|
|
log_syntax(unit, LOG_ERR, filename, line, 0,
|
|
|
|
"Invalid NetDev kind: %s", lvalue);
|
|
|
|
return 0;
|
|
|
|
}
|
2014-01-22 14:49:24 +01:00
|
|
|
}
|
|
|
|
|
2019-02-21 08:40:34 +01:00
|
|
|
if (!ifname_valid(rvalue)) {
|
2019-02-27 13:34:51 +01:00
|
|
|
log_syntax(unit, LOG_ERR, filename, line, 0,
|
|
|
|
"Invalid netdev name in %s=, ignoring assignment: %s", lvalue, rvalue);
|
2014-01-22 14:49:24 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-02-21 08:40:34 +01:00
|
|
|
name = strdup(rvalue);
|
|
|
|
if (!name)
|
|
|
|
return log_oom();
|
2018-11-12 07:24:11 +01:00
|
|
|
|
2019-02-21 08:40:34 +01:00
|
|
|
r = hashmap_ensure_allocated(h, &string_hash_ops);
|
|
|
|
if (r < 0)
|
|
|
|
return log_oom();
|
2014-06-16 08:24:33 +02:00
|
|
|
|
2019-02-21 08:40:34 +01:00
|
|
|
r = hashmap_put(*h, name, INT_TO_PTR(kind));
|
2019-02-27 14:15:29 +01:00
|
|
|
if (r < 0)
|
2019-02-27 13:34:51 +01:00
|
|
|
log_syntax(unit, LOG_ERR, filename, line, r,
|
2019-02-27 14:15:29 +01:00
|
|
|
"Cannot add NetDev '%s' to network, ignoring assignment: %m", name);
|
|
|
|
else if (r == 0)
|
|
|
|
log_syntax(unit, LOG_DEBUG, filename, line, r,
|
|
|
|
"NetDev '%s' specified twice, ignoring.", name);
|
|
|
|
else
|
|
|
|
name = NULL;
|
2014-05-08 19:28:17 +02:00
|
|
|
|
2014-02-25 21:16:17 +01:00
|
|
|
return 0;
|
|
|
|
}
|
2014-05-12 07:18:24 +02:00
|
|
|
|
networkd: rework Domains= setting
Previously, .network files only knew a vaguely defined "Domains=" concept, for which the documentation declared it was
the "DNS domain" for the network connection, without specifying what that means.
With this the Domains setting is reworked, so that there are now "routing" domains and "search" domains. The former are
to be used by resolved to route DNS request to specific network interfaces, the latter is to be used for searching
single-label hostnames with (in addition to being used for routing). Both settings are configured in the "Domains="
setting. Normal domain names listed in it are now considered search domains (for compatibility with existing setups),
while those prefixed with "~" are considered routing domains only. To route all lookups to a specific interface the
routing domain "." may be used, referring to the root domain. An alternative syntax for this is the "*", as was already
implemented before using the "wildcard" domain concept.
This commit adds proper parsers for this new logic, and exposes this via the sd-network API. This information is not
used by resolved yet, this will be added in a later commit.
2016-01-25 19:46:00 +01:00
|
|
|
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) {
|
|
|
|
|
|
|
|
const char *p;
|
|
|
|
Network *n = data;
|
2014-08-15 14:21:08 +02:00
|
|
|
int r;
|
|
|
|
|
networkd: rework Domains= setting
Previously, .network files only knew a vaguely defined "Domains=" concept, for which the documentation declared it was
the "DNS domain" for the network connection, without specifying what that means.
With this the Domains setting is reworked, so that there are now "routing" domains and "search" domains. The former are
to be used by resolved to route DNS request to specific network interfaces, the latter is to be used for searching
single-label hostnames with (in addition to being used for routing). Both settings are configured in the "Domains="
setting. Normal domain names listed in it are now considered search domains (for compatibility with existing setups),
while those prefixed with "~" are considered routing domains only. To route all lookups to a specific interface the
routing domain "." may be used, referring to the root domain. An alternative syntax for this is the "*", as was already
implemented before using the "wildcard" domain concept.
This commit adds proper parsers for this new logic, and exposes this via the sd-network API. This information is not
used by resolved yet, this will be added in a later commit.
2016-01-25 19:46:00 +01:00
|
|
|
assert(n);
|
|
|
|
assert(lvalue);
|
|
|
|
assert(rvalue);
|
2014-08-15 14:21:08 +02:00
|
|
|
|
networkd: rework Domains= setting
Previously, .network files only knew a vaguely defined "Domains=" concept, for which the documentation declared it was
the "DNS domain" for the network connection, without specifying what that means.
With this the Domains setting is reworked, so that there are now "routing" domains and "search" domains. The former are
to be used by resolved to route DNS request to specific network interfaces, the latter is to be used for searching
single-label hostnames with (in addition to being used for routing). Both settings are configured in the "Domains="
setting. Normal domain names listed in it are now considered search domains (for compatibility with existing setups),
while those prefixed with "~" are considered routing domains only. To route all lookups to a specific interface the
routing domain "." may be used, referring to the root domain. An alternative syntax for this is the "*", as was already
implemented before using the "wildcard" domain concept.
This commit adds proper parsers for this new logic, and exposes this via the sd-network API. This information is not
used by resolved yet, this will be added in a later commit.
2016-01-25 19:46:00 +01:00
|
|
|
if (isempty(rvalue)) {
|
2019-02-20 22:50:25 +01:00
|
|
|
n->search_domains = ordered_set_free_free(n->search_domains);
|
|
|
|
n->route_domains = ordered_set_free_free(n->route_domains);
|
networkd: rework Domains= setting
Previously, .network files only knew a vaguely defined "Domains=" concept, for which the documentation declared it was
the "DNS domain" for the network connection, without specifying what that means.
With this the Domains setting is reworked, so that there are now "routing" domains and "search" domains. The former are
to be used by resolved to route DNS request to specific network interfaces, the latter is to be used for searching
single-label hostnames with (in addition to being used for routing). Both settings are configured in the "Domains="
setting. Normal domain names listed in it are now considered search domains (for compatibility with existing setups),
while those prefixed with "~" are considered routing domains only. To route all lookups to a specific interface the
routing domain "." may be used, referring to the root domain. An alternative syntax for this is the "*", as was already
implemented before using the "wildcard" domain concept.
This commit adds proper parsers for this new logic, and exposes this via the sd-network API. This information is not
used by resolved yet, this will be added in a later commit.
2016-01-25 19:46:00 +01:00
|
|
|
return 0;
|
|
|
|
}
|
2014-08-15 14:49:31 +02:00
|
|
|
|
networkd: rework Domains= setting
Previously, .network files only knew a vaguely defined "Domains=" concept, for which the documentation declared it was
the "DNS domain" for the network connection, without specifying what that means.
With this the Domains setting is reworked, so that there are now "routing" domains and "search" domains. The former are
to be used by resolved to route DNS request to specific network interfaces, the latter is to be used for searching
single-label hostnames with (in addition to being used for routing). Both settings are configured in the "Domains="
setting. Normal domain names listed in it are now considered search domains (for compatibility with existing setups),
while those prefixed with "~" are considered routing domains only. To route all lookups to a specific interface the
routing domain "." may be used, referring to the root domain. An alternative syntax for this is the "*", as was already
implemented before using the "wildcard" domain concept.
This commit adds proper parsers for this new logic, and exposes this via the sd-network API. This information is not
used by resolved yet, this will be added in a later commit.
2016-01-25 19:46:00 +01:00
|
|
|
p = rvalue;
|
|
|
|
for (;;) {
|
|
|
|
_cleanup_free_ char *w = NULL, *normalized = NULL;
|
|
|
|
const char *domain;
|
|
|
|
bool is_route;
|
|
|
|
|
|
|
|
r = extract_first_word(&p, &w, NULL, 0);
|
|
|
|
if (r < 0) {
|
2019-02-20 21:30:06 +01:00
|
|
|
log_syntax(unit, LOG_ERR, filename, line, r,
|
|
|
|
"Failed to extract search or route domain, ignoring: %s", rvalue);
|
networkd: rework Domains= setting
Previously, .network files only knew a vaguely defined "Domains=" concept, for which the documentation declared it was
the "DNS domain" for the network connection, without specifying what that means.
With this the Domains setting is reworked, so that there are now "routing" domains and "search" domains. The former are
to be used by resolved to route DNS request to specific network interfaces, the latter is to be used for searching
single-label hostnames with (in addition to being used for routing). Both settings are configured in the "Domains="
setting. Normal domain names listed in it are now considered search domains (for compatibility with existing setups),
while those prefixed with "~" are considered routing domains only. To route all lookups to a specific interface the
routing domain "." may be used, referring to the root domain. An alternative syntax for this is the "*", as was already
implemented before using the "wildcard" domain concept.
This commit adds proper parsers for this new logic, and exposes this via the sd-network API. This information is not
used by resolved yet, this will be added in a later commit.
2016-01-25 19:46:00 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (r == 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
is_route = w[0] == '~';
|
|
|
|
domain = is_route ? w + 1 : w;
|
|
|
|
|
|
|
|
if (dns_name_is_root(domain) || streq(domain, "*")) {
|
2019-02-20 21:30:06 +01:00
|
|
|
/* If the root domain appears as is, or the special token "*" is found, we'll
|
|
|
|
* consider this as routing domain, unconditionally. */
|
networkd: rework Domains= setting
Previously, .network files only knew a vaguely defined "Domains=" concept, for which the documentation declared it was
the "DNS domain" for the network connection, without specifying what that means.
With this the Domains setting is reworked, so that there are now "routing" domains and "search" domains. The former are
to be used by resolved to route DNS request to specific network interfaces, the latter is to be used for searching
single-label hostnames with (in addition to being used for routing). Both settings are configured in the "Domains="
setting. Normal domain names listed in it are now considered search domains (for compatibility with existing setups),
while those prefixed with "~" are considered routing domains only. To route all lookups to a specific interface the
routing domain "." may be used, referring to the root domain. An alternative syntax for this is the "*", as was already
implemented before using the "wildcard" domain concept.
This commit adds proper parsers for this new logic, and exposes this via the sd-network API. This information is not
used by resolved yet, this will be added in a later commit.
2016-01-25 19:46:00 +01:00
|
|
|
is_route = true;
|
2019-02-20 21:30:06 +01:00
|
|
|
domain = "."; /* make sure we don't allow empty strings, thus write the root
|
|
|
|
* domain as "." */
|
networkd: rework Domains= setting
Previously, .network files only knew a vaguely defined "Domains=" concept, for which the documentation declared it was
the "DNS domain" for the network connection, without specifying what that means.
With this the Domains setting is reworked, so that there are now "routing" domains and "search" domains. The former are
to be used by resolved to route DNS request to specific network interfaces, the latter is to be used for searching
single-label hostnames with (in addition to being used for routing). Both settings are configured in the "Domains="
setting. Normal domain names listed in it are now considered search domains (for compatibility with existing setups),
while those prefixed with "~" are considered routing domains only. To route all lookups to a specific interface the
routing domain "." may be used, referring to the root domain. An alternative syntax for this is the "*", as was already
implemented before using the "wildcard" domain concept.
This commit adds proper parsers for this new logic, and exposes this via the sd-network API. This information is not
used by resolved yet, this will be added in a later commit.
2016-01-25 19:46:00 +01:00
|
|
|
} else {
|
resolve: reject host names with leading or trailing dashes in /etc/hosts
https://tools.ietf.org/html/rfc1035#section-2.3.1 says (approximately)
that only letters, numbers, and non-leading non-trailing dashes are allowed
(for entries with A/AAAA records). We set no restrictions.
hosts(5) says:
> Host names may contain only alphanumeric characters, minus signs ("-"), and
> periods ("."). They must begin with an alphabetic character and end with an
> alphanumeric character.
nss-files follows those rules, and will ignore names in /etc/hosts that do not
follow this rule.
Let's follow the documented rules for /etc/hosts. In particular, this makes us
consitent with nss-files, reducing surprises for the user.
I'm pretty sure we should apply stricter filtering to names received over DNS
and LLMNR and MDNS, but it's a bigger project, because the rules differ
depepending on which level the label appears (rules for top-level names are
stricter), and this patch takes the minimalistic approach and only changes
behaviour for /etc/hosts.
Escape syntax is also disallowed in /etc/hosts, even if the resulting character
would be allowed. Other tools that parse /etc/hosts do not support this, and
there is no need to use it because no allowed characters benefit from escaping.
2018-11-21 22:58:13 +01:00
|
|
|
r = dns_name_normalize(domain, 0, &normalized);
|
networkd: rework Domains= setting
Previously, .network files only knew a vaguely defined "Domains=" concept, for which the documentation declared it was
the "DNS domain" for the network connection, without specifying what that means.
With this the Domains setting is reworked, so that there are now "routing" domains and "search" domains. The former are
to be used by resolved to route DNS request to specific network interfaces, the latter is to be used for searching
single-label hostnames with (in addition to being used for routing). Both settings are configured in the "Domains="
setting. Normal domain names listed in it are now considered search domains (for compatibility with existing setups),
while those prefixed with "~" are considered routing domains only. To route all lookups to a specific interface the
routing domain "." may be used, referring to the root domain. An alternative syntax for this is the "*", as was already
implemented before using the "wildcard" domain concept.
This commit adds proper parsers for this new logic, and exposes this via the sd-network API. This information is not
used by resolved yet, this will be added in a later commit.
2016-01-25 19:46:00 +01:00
|
|
|
if (r < 0) {
|
2019-02-20 21:30:06 +01:00
|
|
|
log_syntax(unit, LOG_ERR, filename, line, r,
|
|
|
|
"'%s' is not a valid domain name, ignoring.", domain);
|
networkd: rework Domains= setting
Previously, .network files only knew a vaguely defined "Domains=" concept, for which the documentation declared it was
the "DNS domain" for the network connection, without specifying what that means.
With this the Domains setting is reworked, so that there are now "routing" domains and "search" domains. The former are
to be used by resolved to route DNS request to specific network interfaces, the latter is to be used for searching
single-label hostnames with (in addition to being used for routing). Both settings are configured in the "Domains="
setting. Normal domain names listed in it are now considered search domains (for compatibility with existing setups),
while those prefixed with "~" are considered routing domains only. To route all lookups to a specific interface the
routing domain "." may be used, referring to the root domain. An alternative syntax for this is the "*", as was already
implemented before using the "wildcard" domain concept.
This commit adds proper parsers for this new logic, and exposes this via the sd-network API. This information is not
used by resolved yet, this will be added in a later commit.
2016-01-25 19:46:00 +01:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
domain = normalized;
|
|
|
|
|
|
|
|
if (is_localhost(domain)) {
|
2019-02-20 21:30:06 +01:00
|
|
|
log_syntax(unit, LOG_ERR, filename, line, 0,
|
|
|
|
"'localhost' domain may not be configured as search or route domain, ignoring assignment: %s",
|
|
|
|
domain);
|
2015-06-03 01:30:42 +02:00
|
|
|
continue;
|
networkd: rework Domains= setting
Previously, .network files only knew a vaguely defined "Domains=" concept, for which the documentation declared it was
the "DNS domain" for the network connection, without specifying what that means.
With this the Domains setting is reworked, so that there are now "routing" domains and "search" domains. The former are
to be used by resolved to route DNS request to specific network interfaces, the latter is to be used for searching
single-label hostnames with (in addition to being used for routing). Both settings are configured in the "Domains="
setting. Normal domain names listed in it are now considered search domains (for compatibility with existing setups),
while those prefixed with "~" are considered routing domains only. To route all lookups to a specific interface the
routing domain "." may be used, referring to the root domain. An alternative syntax for this is the "*", as was already
implemented before using the "wildcard" domain concept.
This commit adds proper parsers for this new logic, and exposes this via the sd-network API. This information is not
used by resolved yet, this will be added in a later commit.
2016-01-25 19:46:00 +01:00
|
|
|
}
|
2015-06-03 01:30:42 +02:00
|
|
|
}
|
2014-08-15 16:21:19 +02:00
|
|
|
|
2019-02-20 22:50:25 +01:00
|
|
|
OrderedSet **set = is_route ? &n->route_domains : &n->search_domains;
|
|
|
|
r = ordered_set_ensure_allocated(set, &string_hash_ops);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
r = ordered_set_put_strdup(*set, domain);
|
2018-12-04 15:34:37 +01:00
|
|
|
if (r < 0)
|
|
|
|
return log_oom();
|
2014-08-15 16:21:19 +02:00
|
|
|
}
|
2014-08-15 15:36:17 +02:00
|
|
|
|
2014-08-15 14:21:08 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-02-08 22:27:15 +01:00
|
|
|
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 */
|
|
|
|
|
2016-03-03 18:30:37 +01:00
|
|
|
SET_FLAG(*link_local, ADDRESS_FAMILY_IPV4, parse_boolean(rvalue));
|
2015-02-08 22:27:15 +01:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-08-03 18:45:07 +02:00
|
|
|
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) {
|
|
|
|
|
2015-01-13 19:48:19 +01:00
|
|
|
AddressFamilyBoolean *dhcp = data, s;
|
2014-08-03 18:45:07 +02:00
|
|
|
|
|
|
|
assert(filename);
|
|
|
|
assert(lvalue);
|
|
|
|
assert(rvalue);
|
|
|
|
assert(data);
|
|
|
|
|
2015-01-13 20:07:13 +01:00
|
|
|
/* Note that this is mostly like
|
|
|
|
* config_parse_address_family_boolean(), except that it
|
|
|
|
* understands some old names for the enum values */
|
|
|
|
|
2015-01-13 19:48:19 +01:00
|
|
|
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 {
|
2019-02-20 21:30:06 +01:00
|
|
|
log_syntax(unit, LOG_ERR, filename, line, 0,
|
|
|
|
"Failed to parse DHCP option, ignoring: %s", rvalue);
|
2014-08-03 18:45:07 +02:00
|
|
|
return 0;
|
|
|
|
}
|
2019-02-19 04:35:51 +01:00
|
|
|
|
|
|
|
log_syntax(unit, LOG_WARNING, filename, line, 0,
|
|
|
|
"DHCP=%s is deprecated, please use DHCP=%s instead.",
|
|
|
|
rvalue, address_family_boolean_to_string(s));
|
2014-08-03 18:45:07 +02:00
|
|
|
}
|
|
|
|
|
2015-01-13 19:48:19 +01:00
|
|
|
*dhcp = s;
|
2014-08-03 18:45:07 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-03-03 19:49:48 +01:00
|
|
|
static const char* const dhcp_client_identifier_table[_DHCP_CLIENT_ID_MAX] = {
|
|
|
|
[DHCP_CLIENT_ID_MAC] = "mac",
|
2018-03-12 17:18:07 +01:00
|
|
|
[DHCP_CLIENT_ID_DUID] = "duid",
|
|
|
|
[DHCP_CLIENT_ID_DUID_ONLY] = "duid-only",
|
2015-03-03 19:49:48 +01:00
|
|
|
};
|
|
|
|
|
2017-08-15 06:50:25 +02:00
|
|
|
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_client_identifier, DHCPClientIdentifier);
|
2019-02-20 21:30:06 +01:00
|
|
|
DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_client_identifier, dhcp_client_identifier, DHCPClientIdentifier,
|
|
|
|
"Failed to parse client identifier type");
|
2015-03-03 19:49:48 +01:00
|
|
|
|
2015-02-14 00:32:56 +01:00
|
|
|
int config_parse_ipv6token(
|
2015-02-08 23:20:56 +01:00
|
|
|
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) {
|
2019-02-20 21:30:06 +01:00
|
|
|
log_syntax(unit, LOG_ERR, filename, line, r,
|
|
|
|
"Failed to parse IPv6 token, ignoring: %s", rvalue);
|
2015-02-08 23:20:56 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-02-02 23:08:10 +01:00
|
|
|
if (in_addr_is_null(AF_INET6, &buffer)) {
|
2019-02-20 21:30:06 +01:00
|
|
|
log_syntax(unit, LOG_ERR, filename, line, 0,
|
|
|
|
"IPv6 token cannot be the ANY address, ignoring: %s", rvalue);
|
2015-02-08 23:20:56 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((buffer.in6.s6_addr32[0] | buffer.in6.s6_addr32[1]) != 0) {
|
2019-02-20 21:30:06 +01:00
|
|
|
log_syntax(unit, LOG_ERR, filename, line, 0,
|
|
|
|
"IPv6 token cannot be longer than 64 bits, ignoring: %s", rvalue);
|
2015-02-08 23:20:56 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
*token = buffer.in6;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2015-05-01 20:48:08 +02:00
|
|
|
|
2015-07-05 07:54:31 +02:00
|
|
|
static const char* const ipv6_privacy_extensions_table[_IPV6_PRIVACY_EXTENSIONS_MAX] = {
|
2015-07-06 20:29:33 +02:00
|
|
|
[IPV6_PRIVACY_EXTENSIONS_NO] = "no",
|
|
|
|
[IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC] = "prefer-public",
|
|
|
|
[IPV6_PRIVACY_EXTENSIONS_YES] = "yes",
|
2015-07-05 07:54:31 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
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)
|
2015-07-06 20:29:33 +02:00
|
|
|
*ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_YES;
|
2015-07-05 07:54:31 +02:00
|
|
|
else if (k == 0)
|
2015-07-06 20:29:33 +02:00
|
|
|
*ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_NO;
|
2015-07-05 07:54:31 +02:00
|
|
|
else {
|
2015-07-06 20:29:33 +02:00
|
|
|
IPv6PrivacyExtensions s;
|
2015-07-05 07:54:31 +02:00
|
|
|
|
|
|
|
s = ipv6_privacy_extensions_from_string(rvalue);
|
2015-07-06 20:29:33 +02:00
|
|
|
if (s < 0) {
|
|
|
|
|
|
|
|
if (streq(rvalue, "kernel"))
|
|
|
|
s = _IPV6_PRIVACY_EXTENSIONS_INVALID;
|
|
|
|
else {
|
2019-02-20 21:30:06 +01:00
|
|
|
log_syntax(unit, LOG_ERR, filename, line, 0,
|
|
|
|
"Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue);
|
2015-07-06 20:29:33 +02:00
|
|
|
return 0;
|
|
|
|
}
|
2015-07-05 07:54:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
*ipv6_privacy_extensions = s;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2015-07-10 12:12:27 +02:00
|
|
|
|
2015-08-26 19:16:52 +02:00
|
|
|
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) {
|
|
|
|
|
2018-08-02 09:28:23 +02:00
|
|
|
_cleanup_free_ char *hn = NULL;
|
|
|
|
char **hostname = data;
|
2015-07-10 12:12:27 +02:00
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(filename);
|
|
|
|
assert(lvalue);
|
|
|
|
assert(rvalue);
|
|
|
|
|
2015-08-26 19:16:52 +02:00
|
|
|
r = config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &hn, userdata);
|
2015-07-10 12:12:27 +02:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
2015-08-26 19:16:52 +02:00
|
|
|
if (!hostname_is_valid(hn, false)) {
|
2019-02-20 21:30:06 +01:00
|
|
|
log_syntax(unit, LOG_ERR, filename, line, 0,
|
|
|
|
"Hostname is not valid, ignoring assignment: %s", rvalue);
|
2015-07-10 12:12:27 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-08-02 09:28:23 +02:00
|
|
|
r = dns_name_is_valid(hn);
|
|
|
|
if (r < 0) {
|
2019-02-20 21:30:06 +01:00
|
|
|
log_syntax(unit, LOG_ERR, filename, line, r,
|
|
|
|
"Failed to check validity of hostname '%s', ignoring assignment: %m", rvalue);
|
2018-08-02 09:28:23 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (r == 0) {
|
2019-02-20 21:30:06 +01:00
|
|
|
log_syntax(unit, LOG_ERR, filename, line, 0,
|
|
|
|
"Hostname is not a valid DNS domain name, ignoring assignment: %s", rvalue);
|
2018-08-02 09:28:23 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return free_and_replace(*hostname, hn);
|
2015-07-10 12:12:27 +02:00
|
|
|
}
|
2015-08-26 19:19:32 +02:00
|
|
|
|
|
|
|
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) {
|
|
|
|
|
2018-08-02 09:28:44 +02:00
|
|
|
_cleanup_free_ char *tz = NULL;
|
|
|
|
char **datap = data;
|
2015-08-26 19:19:32 +02:00
|
|
|
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;
|
|
|
|
|
2018-05-12 21:20:13 +02:00
|
|
|
if (!timezone_is_valid(tz, LOG_ERR)) {
|
2019-02-20 21:30:06 +01:00
|
|
|
log_syntax(unit, LOG_ERR, filename, line, 0,
|
|
|
|
"Timezone is not valid, ignoring assignment: %s", rvalue);
|
2015-08-26 19:19:32 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-08-02 09:28:44 +02:00
|
|
|
return free_and_replace(*datap, tz);
|
2015-08-26 19:19:32 +02:00
|
|
|
}
|
2015-08-27 14:48:37 +02:00
|
|
|
|
|
|
|
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);
|
2016-11-18 17:03:13 +01:00
|
|
|
if (r == -ENOMEM)
|
|
|
|
return log_oom();
|
2015-08-27 14:48:37 +02:00
|
|
|
if (r < 0) {
|
2019-02-20 21:30:06 +01:00
|
|
|
log_syntax(unit, LOG_ERR, filename, line, r,
|
|
|
|
"Failed to extract word, ignoring: %s", rvalue);
|
2015-08-27 14:48:37 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (r == 0)
|
2016-11-18 17:03:13 +01:00
|
|
|
break;
|
2015-08-27 14:48:37 +02:00
|
|
|
|
|
|
|
if (inet_pton(AF_INET, w, &a) <= 0) {
|
2019-02-20 21:30:06 +01:00
|
|
|
log_syntax(unit, LOG_ERR, filename, line, 0,
|
|
|
|
"Failed to parse DNS server address, ignoring: %s", w);
|
2015-08-27 14:48:37 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2018-02-27 19:09:22 +01:00
|
|
|
m = reallocarray(n->dhcp_server_dns, n->n_dhcp_server_dns + 1, sizeof(struct in_addr));
|
2015-08-27 14:48:37 +02:00
|
|
|
if (!m)
|
|
|
|
return log_oom();
|
|
|
|
|
|
|
|
m[n->n_dhcp_server_dns++] = a;
|
|
|
|
n->dhcp_server_dns = m;
|
|
|
|
}
|
2016-11-18 17:03:13 +01:00
|
|
|
|
2017-08-14 11:53:10 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int config_parse_radv_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;
|
|
|
|
union in_addr_union a;
|
|
|
|
|
|
|
|
r = extract_first_word(&p, &w, NULL, 0);
|
|
|
|
if (r == -ENOMEM)
|
|
|
|
return log_oom();
|
|
|
|
if (r < 0) {
|
2019-02-20 21:30:06 +01:00
|
|
|
log_syntax(unit, LOG_ERR, filename, line, r,
|
|
|
|
"Failed to extract word, ignoring: %s", rvalue);
|
2017-08-14 11:53:10 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (r == 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (in_addr_from_string(AF_INET6, w, &a) >= 0) {
|
|
|
|
struct in6_addr *m;
|
|
|
|
|
2018-02-27 19:09:22 +01:00
|
|
|
m = reallocarray(n->router_dns, n->n_router_dns + 1, sizeof(struct in6_addr));
|
2017-08-14 11:53:10 +02:00
|
|
|
if (!m)
|
|
|
|
return log_oom();
|
|
|
|
|
|
|
|
m[n->n_router_dns++] = a.in6;
|
|
|
|
n->router_dns = m;
|
|
|
|
|
|
|
|
} else
|
2019-02-20 21:30:06 +01:00
|
|
|
log_syntax(unit, LOG_ERR, filename, line, 0,
|
|
|
|
"Failed to parse DNS server address, ignoring: %s", w);
|
2017-08-14 11:53:10 +02:00
|
|
|
}
|
|
|
|
|
2017-08-16 12:29:51 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int config_parse_radv_search_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 *n = data;
|
|
|
|
const char *p = rvalue;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(filename);
|
|
|
|
assert(lvalue);
|
|
|
|
assert(rvalue);
|
|
|
|
|
|
|
|
for (;;) {
|
2018-11-08 04:29:38 +01:00
|
|
|
_cleanup_free_ char *w = NULL, *idna = NULL;
|
2017-08-16 12:29:51 +02:00
|
|
|
|
|
|
|
r = extract_first_word(&p, &w, NULL, 0);
|
|
|
|
if (r == -ENOMEM)
|
|
|
|
return log_oom();
|
|
|
|
if (r < 0) {
|
2019-02-20 21:30:06 +01:00
|
|
|
log_syntax(unit, LOG_ERR, filename, line, r,
|
|
|
|
"Failed to extract word, ignoring: %s", rvalue);
|
2017-08-16 12:29:51 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (r == 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
r = dns_name_apply_idna(w, &idna);
|
2018-11-08 04:29:38 +01:00
|
|
|
if (r < 0) {
|
2019-02-20 21:30:06 +01:00
|
|
|
log_syntax(unit, LOG_ERR, filename, line, r,
|
|
|
|
"Failed to apply IDNA to domain name '%s', ignoring: %m", w);
|
2018-11-08 04:29:38 +01:00
|
|
|
continue;
|
2019-02-20 22:50:25 +01:00
|
|
|
} else if (r == 0)
|
|
|
|
/* transfer ownership to simplify subsequent operations */
|
|
|
|
idna = TAKE_PTR(w);
|
|
|
|
|
|
|
|
r = ordered_set_ensure_allocated(&n->router_search_domains, &string_hash_ops);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
r = ordered_set_consume(n->router_search_domains, TAKE_PTR(idna));
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2017-08-16 12:29:51 +02:00
|
|
|
}
|
|
|
|
|
2016-11-18 17:03:13 +01:00
|
|
|
return 0;
|
2015-08-27 14:48:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
2016-11-18 17:03:13 +01:00
|
|
|
if (r == -ENOMEM)
|
|
|
|
return log_oom();
|
2015-08-27 14:48:37 +02:00
|
|
|
if (r < 0) {
|
2019-02-20 21:30:06 +01:00
|
|
|
log_syntax(unit, LOG_ERR, filename, line, r,
|
|
|
|
"Failed to extract word, ignoring: %s", rvalue);
|
2015-08-27 14:48:37 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (r == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (inet_pton(AF_INET, w, &a) <= 0) {
|
2019-02-20 21:30:06 +01:00
|
|
|
log_syntax(unit, LOG_ERR, filename, line, 0,
|
|
|
|
"Failed to parse NTP server address, ignoring: %s", w);
|
2015-08-27 14:48:37 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2018-02-27 19:09:22 +01:00
|
|
|
m = reallocarray(n->dhcp_server_ntp, n->n_dhcp_server_ntp + 1, sizeof(struct in_addr));
|
2015-08-27 14:48:37 +02:00
|
|
|
if (!m)
|
|
|
|
return log_oom();
|
|
|
|
|
|
|
|
m[n->n_dhcp_server_ntp++] = a;
|
|
|
|
n->dhcp_server_ntp = m;
|
|
|
|
}
|
|
|
|
}
|
2016-01-06 18:36:32 +01:00
|
|
|
|
2016-10-27 01:31:04 +02:00
|
|
|
int config_parse_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 = userdata;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(filename);
|
|
|
|
assert(lvalue);
|
|
|
|
assert(rvalue);
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
_cleanup_free_ char *w = NULL;
|
|
|
|
union in_addr_union a;
|
2016-11-18 17:04:26 +01:00
|
|
|
struct in_addr_data *m;
|
2016-10-27 01:31:04 +02:00
|
|
|
int family;
|
|
|
|
|
2016-11-18 17:04:26 +01:00
|
|
|
r = extract_first_word(&rvalue, &w, NULL, 0);
|
2016-10-27 01:31:04 +02:00
|
|
|
if (r == -ENOMEM)
|
|
|
|
return log_oom();
|
|
|
|
if (r < 0) {
|
2019-02-20 21:30:06 +01:00
|
|
|
log_syntax(unit, LOG_ERR, filename, line, r,
|
|
|
|
"Invalid syntax, ignoring: %s", rvalue);
|
2016-10-27 01:31:04 +02:00
|
|
|
break;
|
|
|
|
}
|
2016-11-18 17:04:26 +01:00
|
|
|
if (r == 0)
|
|
|
|
break;
|
2016-10-27 01:31:04 +02:00
|
|
|
|
|
|
|
r = in_addr_from_string_auto(w, &family, &a);
|
|
|
|
if (r < 0) {
|
2019-02-20 21:30:06 +01:00
|
|
|
log_syntax(unit, LOG_ERR, filename, line, r,
|
|
|
|
"Failed to parse dns server address, ignoring: %s", w);
|
2016-10-27 01:31:04 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2018-02-27 19:09:22 +01:00
|
|
|
m = reallocarray(n->dns, n->n_dns + 1, sizeof(struct in_addr_data));
|
2016-11-18 17:04:26 +01:00
|
|
|
if (!m)
|
2016-10-27 01:31:04 +02:00
|
|
|
return log_oom();
|
|
|
|
|
2016-11-18 17:04:26 +01:00
|
|
|
m[n->n_dns++] = (struct in_addr_data) {
|
|
|
|
.family = family,
|
|
|
|
.address = a,
|
|
|
|
};
|
|
|
|
|
|
|
|
n->dns = m;
|
2016-10-27 01:31:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-01-06 18:36:32 +01:00
|
|
|
int config_parse_dnssec_negative_trust_anchors(
|
|
|
|
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;
|
|
|
|
Network *n = data;
|
|
|
|
int r;
|
|
|
|
|
networkd: rework Domains= setting
Previously, .network files only knew a vaguely defined "Domains=" concept, for which the documentation declared it was
the "DNS domain" for the network connection, without specifying what that means.
With this the Domains setting is reworked, so that there are now "routing" domains and "search" domains. The former are
to be used by resolved to route DNS request to specific network interfaces, the latter is to be used for searching
single-label hostnames with (in addition to being used for routing). Both settings are configured in the "Domains="
setting. Normal domain names listed in it are now considered search domains (for compatibility with existing setups),
while those prefixed with "~" are considered routing domains only. To route all lookups to a specific interface the
routing domain "." may be used, referring to the root domain. An alternative syntax for this is the "*", as was already
implemented before using the "wildcard" domain concept.
This commit adds proper parsers for this new logic, and exposes this via the sd-network API. This information is not
used by resolved yet, this will be added in a later commit.
2016-01-25 19:46:00 +01:00
|
|
|
assert(n);
|
2016-01-06 18:36:32 +01:00
|
|
|
assert(lvalue);
|
|
|
|
assert(rvalue);
|
|
|
|
|
|
|
|
if (isempty(rvalue)) {
|
|
|
|
n->dnssec_negative_trust_anchors = set_free_free(n->dnssec_negative_trust_anchors);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
_cleanup_free_ char *w = NULL;
|
|
|
|
|
|
|
|
r = extract_first_word(&p, &w, NULL, 0);
|
|
|
|
if (r < 0) {
|
2019-02-20 21:30:06 +01:00
|
|
|
log_syntax(unit, LOG_ERR, filename, line, r,
|
|
|
|
"Failed to extract negative trust anchor domain, ignoring: %s", rvalue);
|
2016-01-06 18:36:32 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (r == 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
r = dns_name_is_valid(w);
|
|
|
|
if (r <= 0) {
|
2019-02-20 21:30:06 +01:00
|
|
|
log_syntax(unit, LOG_ERR, filename, line, r,
|
|
|
|
"%s is not a valid domain name, ignoring.", w);
|
2016-01-06 18:36:32 +01:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2016-02-21 22:27:01 +01:00
|
|
|
r = set_ensure_allocated(&n->dnssec_negative_trust_anchors, &dns_name_hash_ops);
|
|
|
|
if (r < 0)
|
|
|
|
return log_oom();
|
|
|
|
|
2016-01-06 18:36:32 +01:00
|
|
|
r = set_put(n->dnssec_negative_trust_anchors, w);
|
|
|
|
if (r < 0)
|
|
|
|
return log_oom();
|
|
|
|
if (r > 0)
|
|
|
|
w = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2016-01-25 22:27:01 +01:00
|
|
|
|
2016-11-18 17:00:25 +01:00
|
|
|
int config_parse_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) {
|
|
|
|
|
|
|
|
char ***l = data;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(l);
|
|
|
|
assert(lvalue);
|
|
|
|
assert(rvalue);
|
|
|
|
|
|
|
|
if (isempty(rvalue)) {
|
|
|
|
*l = strv_free(*l);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
_cleanup_free_ char *w = NULL;
|
|
|
|
|
|
|
|
r = extract_first_word(&rvalue, &w, NULL, 0);
|
|
|
|
if (r == -ENOMEM)
|
|
|
|
return log_oom();
|
|
|
|
if (r < 0) {
|
2019-02-20 21:30:06 +01:00
|
|
|
log_syntax(unit, LOG_ERR, filename, line, r,
|
|
|
|
"Failed to extract NTP server name, ignoring: %s", rvalue);
|
2016-11-18 17:00:25 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (r == 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
r = dns_name_is_valid_or_address(w);
|
|
|
|
if (r <= 0) {
|
2019-02-20 21:30:06 +01:00
|
|
|
log_syntax(unit, LOG_ERR, filename, line, r,
|
|
|
|
"%s is not a valid domain name or IP address, ignoring.", w);
|
2016-11-18 17:00:25 +01:00
|
|
|
continue;
|
2018-05-07 14:21:02 +02:00
|
|
|
}
|
|
|
|
|
2019-02-27 14:45:29 +01:00
|
|
|
if (strv_length(*l) > MAX_NTP_SERVERS) {
|
|
|
|
log_syntax(unit, LOG_WARNING, filename, line, 0,
|
|
|
|
"More than %u NTP servers specified, ignoring \"%s\" and any subsequent entries.",
|
|
|
|
MAX_NTP_SERVERS, w);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
r = strv_consume(l, TAKE_PTR(w));
|
2018-05-07 14:21:02 +02:00
|
|
|
if (r < 0)
|
|
|
|
return log_oom();
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int config_parse_dhcp_user_class(
|
|
|
|
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 ***l = data;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(l);
|
|
|
|
assert(lvalue);
|
|
|
|
assert(rvalue);
|
|
|
|
|
|
|
|
if (isempty(rvalue)) {
|
|
|
|
*l = strv_free(*l);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
_cleanup_free_ char *w = NULL;
|
|
|
|
|
|
|
|
r = extract_first_word(&rvalue, &w, NULL, 0);
|
|
|
|
if (r == -ENOMEM)
|
|
|
|
return log_oom();
|
|
|
|
if (r < 0) {
|
2019-02-20 21:30:06 +01:00
|
|
|
log_syntax(unit, LOG_ERR, filename, line, r,
|
|
|
|
"Failed to split user classes option, ignoring: %s", rvalue);
|
2018-05-07 14:21:02 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (r == 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (strlen(w) > 255) {
|
2019-02-27 05:54:13 +01:00
|
|
|
log_syntax(unit, LOG_ERR, filename, line, 0,
|
2019-02-20 21:30:06 +01:00
|
|
|
"%s length is not in the range 1-255, ignoring.", w);
|
2018-05-07 14:21:02 +02:00
|
|
|
continue;
|
2016-11-18 17:00:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
r = strv_push(l, w);
|
|
|
|
if (r < 0)
|
|
|
|
return log_oom();
|
|
|
|
|
|
|
|
w = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-02-12 04:42:10 +01:00
|
|
|
int config_parse_section_route_table(
|
|
|
|
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) {
|
|
|
|
|
2017-09-07 11:08:39 +02:00
|
|
|
Network *network = data;
|
2016-09-19 04:26:12 +02:00
|
|
|
uint32_t rt;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(filename);
|
|
|
|
assert(lvalue);
|
|
|
|
assert(rvalue);
|
|
|
|
assert(data);
|
|
|
|
|
|
|
|
r = safe_atou32(rvalue, &rt);
|
|
|
|
if (r < 0) {
|
|
|
|
log_syntax(unit, LOG_ERR, filename, line, r,
|
2019-02-12 04:42:10 +01:00
|
|
|
"Failed to parse RouteTable=%s, ignoring assignment: %m", rvalue);
|
2016-09-19 04:26:12 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-02-12 04:42:10 +01:00
|
|
|
if (streq_ptr(section, "DHCP")) {
|
|
|
|
network->dhcp_route_table = rt;
|
|
|
|
network->dhcp_route_table_set = true;
|
|
|
|
} else { /* section is IPv6AcceptRA */
|
|
|
|
network->ipv6_accept_ra_route_table = rt;
|
|
|
|
network->ipv6_accept_ra_route_table_set = true;
|
|
|
|
}
|
2016-09-19 04:26:12 +02:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-02-20 21:30:06 +01:00
|
|
|
DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains, dhcp_use_domains, DHCPUseDomains,
|
|
|
|
"Failed to parse DHCP use domains setting");
|
2016-01-25 22:27:01 +01:00
|
|
|
|
|
|
|
static const char* const dhcp_use_domains_table[_DHCP_USE_DOMAINS_MAX] = {
|
|
|
|
[DHCP_USE_DOMAINS_NO] = "no",
|
|
|
|
[DHCP_USE_DOMAINS_ROUTE] = "route",
|
|
|
|
[DHCP_USE_DOMAINS_YES] = "yes",
|
|
|
|
};
|
|
|
|
|
|
|
|
DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dhcp_use_domains, DHCPUseDomains, DHCP_USE_DOMAINS_YES);
|
sd-lldp: rework sd-lldp API
This reworks the sd-lldp substantially, simplifying things on one hand, and
extending the logic a bit on the other.
Specifically:
- Besides the sd_lldp object only one other object is maintained now,
sd_lldp_neighbor. It's used both as storage for literal LLDP packets, and for
maintainging info about peers in the database. Separation between packet, TLV
and chassis data is not maintained anymore. This should be a major
simplification.
- The sd-lldp API has been extended so that a couple of per-neighbor fields may
be queried directly, without iterating through the object. Other fields that
may appear multiple times, OTOH have to be iterated through.
- The maximum number of entries in the neighbor database is now configurable
during runtime.
- The generation of callbacks from sd_lldp objects is more restricted:
callbacks are only invoked when actual data changed.
- The TTL information is now hooked with a timer event, so that removals from
the neighbor database due to TTLs now result in a callback event.
- Querying LLDP neighbor database will now return a strictly ordered array, to
guarantee stability.
- A "capabilities" mask may now be configured, that selects what type of LLDP
neighbor data is collected. This may be used to restrict collection of LLDP
info about routers instead of all neighbors. This is now exposed via
networkd's LLDP= setting.
- sd-lldp's API to serialize the collected data to text files has been removed.
Instead, there's now an API to extract the raw binary data from LLDP neighbor
objects, as well as one to convert this raw binary data back to an LLDP
neighbor object. networkd will save this raw binary data to /run now, and the
client side can simply parse the information.
- support for parsing the more exotic TLVs has been removed, since we are not
using that. Instead there are now APIs to extract the raw data from TLVs.
Given how easy it is to parse the TLVs clients should do so now directly
instead of relying on our APIs for that.
- A lot of the APIs that parse out LLDP strings have been simplified so that
they actually return strings, instead of char arrays with a length. To deal
with possibly dangerous characters the strings are escaped if needed.
- APIs to extract and format the chassis and port IDs as strings has been
added.
- lldp.h has been simplified a lot. The enums are anonymous now, since they
were never used as enums, but simply as constants. Most definitions we don't
actually use ourselves have eben removed.
2016-02-19 17:58:52 +01:00
|
|
|
|
|
|
|
DEFINE_CONFIG_PARSE_ENUM(config_parse_lldp_mode, lldp_mode, LLDPMode, "Failed to parse LLDP= setting.");
|
|
|
|
|
|
|
|
static const char* const lldp_mode_table[_LLDP_MODE_MAX] = {
|
|
|
|
[LLDP_MODE_NO] = "no",
|
|
|
|
[LLDP_MODE_YES] = "yes",
|
|
|
|
[LLDP_MODE_ROUTERS_ONLY] = "routers-only",
|
|
|
|
};
|
|
|
|
|
|
|
|
DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(lldp_mode, LLDPMode, LLDP_MODE_YES);
|
2018-11-23 22:19:26 +01:00
|
|
|
|
|
|
|
int config_parse_iaid(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 = data;
|
|
|
|
uint32_t iaid;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(filename);
|
|
|
|
assert(lvalue);
|
|
|
|
assert(rvalue);
|
|
|
|
assert(network);
|
|
|
|
|
|
|
|
r = safe_atou32(rvalue, &iaid);
|
|
|
|
if (r < 0) {
|
|
|
|
log_syntax(unit, LOG_ERR, filename, line, r,
|
|
|
|
"Unable to read IAID, ignoring assignment: %s", rvalue);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
network->iaid = iaid;
|
|
|
|
network->iaid_set = true;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|