mirror of
https://github.com/systemd/systemd.git
synced 2025-03-22 06:50:18 +03:00
Merge pull request #19611 from yuwata/network-dhcp-server-introduce-server-address
network: dhcp-server: introduce ServerAddress= setting
This commit is contained in:
commit
e7901aba14
@ -2344,6 +2344,14 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para>
|
||||
|
||||
<variablelist class='network-directives'>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>ServerAddress=</varname></term>
|
||||
<listitem><para>Specifies server address for the DHCP server. Takes an IPv4 address with prefix
|
||||
length, e.g., <literal>192.168.0.1/24</literal>. This setting may be useful when the link which
|
||||
DHCP server running on has multiple static addresses. When unset, one of static addresses in
|
||||
the link will be automatically selected. Defaults to unset.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>PoolOffset=</varname></term>
|
||||
<term><varname>PoolSize=</varname></term>
|
||||
|
@ -225,7 +225,7 @@ int config_parse_address_label(
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (k == 0xffffffffUL) {
|
||||
if (k == UINT32_C(0xffffffff)) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0, "Address label is invalid, ignoring: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
@ -146,12 +146,38 @@ Address *address_free(Address *address) {
|
||||
static bool address_may_have_broadcast(const Address *a) {
|
||||
assert(a);
|
||||
|
||||
if (a->family != AF_INET)
|
||||
return false;
|
||||
|
||||
if (in4_addr_is_set(&a->in_addr_peer.in))
|
||||
return false;
|
||||
|
||||
/* A /31 or /32 IPv4 address does not have a broadcast address.
|
||||
* See https://tools.ietf.org/html/rfc3021 */
|
||||
if (a->prefixlen > 30)
|
||||
return false;
|
||||
|
||||
return a->family == AF_INET &&
|
||||
in4_addr_is_null(&a->in_addr_peer.in) &&
|
||||
a->prefixlen <= 30;
|
||||
if (a->set_broadcast >= 0)
|
||||
return a->set_broadcast;
|
||||
|
||||
return true; /* Defaults to true. */
|
||||
}
|
||||
|
||||
void address_set_broadcast(Address *a) {
|
||||
assert(a);
|
||||
|
||||
if (!address_may_have_broadcast(a))
|
||||
return;
|
||||
|
||||
/* If explicitly configured, do not update the address. */
|
||||
if (in4_addr_is_set(&a->broadcast))
|
||||
return;
|
||||
|
||||
/* If Address= is 0.0.0.0, then the broadcast address will be set later in address_acquire(). */
|
||||
if (in4_addr_is_null(&a->in_addr.in))
|
||||
return;
|
||||
|
||||
a->broadcast.s_addr = a->in_addr.in.s_addr | htobe32(UINT32_C(0xffffffff) >> a->prefixlen);
|
||||
}
|
||||
|
||||
static bool address_may_set_broadcast(const Address *a, const Link *link) {
|
||||
@ -161,9 +187,6 @@ static bool address_may_set_broadcast(const Address *a, const Link *link) {
|
||||
if (!address_may_have_broadcast(a))
|
||||
return false;
|
||||
|
||||
if (a->set_broadcast >= 0)
|
||||
return a->set_broadcast;
|
||||
|
||||
/* Typical configuration for wireguard does not set broadcast. */
|
||||
return !streq_ptr(link->kind, "wireguard");
|
||||
}
|
||||
@ -466,7 +489,7 @@ int address_get(Link *link, const Address *in, Address **ret) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
int link_has_ipv6_address(Link *link, const struct in6_addr *address) {
|
||||
int link_get_ipv6_address(Link *link, const struct in6_addr *address, Address **ret) {
|
||||
_cleanup_(address_freep) Address *a = NULL;
|
||||
int r;
|
||||
|
||||
@ -482,10 +505,10 @@ int link_has_ipv6_address(Link *link, const struct in6_addr *address) {
|
||||
a->family = AF_INET6;
|
||||
a->in_addr.in6 = *address;
|
||||
|
||||
return address_get(link, a, NULL) >= 0;
|
||||
return address_get(link, a, ret);
|
||||
}
|
||||
|
||||
static int link_get_ipv4_address(Set *addresses, const struct in_addr *address, Address **ret) {
|
||||
static int addresses_get_ipv4_address(Set *addresses, const struct in_addr *address, Address **ret) {
|
||||
Address *a;
|
||||
|
||||
assert(address);
|
||||
@ -506,7 +529,35 @@ static int link_get_ipv4_address(Set *addresses, const struct in_addr *address,
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
int link_get_ipv4_address(Link *link, const struct in_addr *address, unsigned char prefixlen, Address **ret) {
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(address);
|
||||
|
||||
if (prefixlen != 0) {
|
||||
_cleanup_(address_freep) Address *a = NULL;
|
||||
|
||||
/* If prefixlen is set, then we can use address_get(). */
|
||||
|
||||
r = address_new(&a);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
a->family = AF_INET;
|
||||
a->in_addr.in = *address;
|
||||
a->prefixlen = prefixlen;
|
||||
|
||||
return address_get(link, a, ret);
|
||||
}
|
||||
|
||||
if (addresses_get_ipv4_address(link->addresses, address, ret) >= 0)
|
||||
return 0;
|
||||
return addresses_get_ipv4_address(link->addresses_foreign, address, ret);
|
||||
}
|
||||
|
||||
int manager_has_address(Manager *manager, int family, const union in_addr_union *address, bool check_ready) {
|
||||
Address *a;
|
||||
Link *link;
|
||||
int r;
|
||||
|
||||
@ -514,18 +565,12 @@ int manager_has_address(Manager *manager, int family, const union in_addr_union
|
||||
assert(IN_SET(family, AF_INET, AF_INET6));
|
||||
assert(address);
|
||||
|
||||
if (family == AF_INET)
|
||||
HASHMAP_FOREACH(link, manager->links) {
|
||||
Address *a;
|
||||
|
||||
if (link_get_ipv4_address(link->addresses, &address->in, &a) >= 0)
|
||||
if (family == AF_INET) {
|
||||
HASHMAP_FOREACH(link, manager->links)
|
||||
if (link_get_ipv4_address(link, &address->in, 0, &a) >= 0)
|
||||
return !check_ready || address_is_ready(a);
|
||||
if (link_get_ipv4_address(link->addresses_foreign, &address->in, &a) >= 0)
|
||||
return !check_ready || address_is_ready(a);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
_cleanup_(address_freep) Address *tmp = NULL;
|
||||
Address *a;
|
||||
|
||||
r = address_new(&tmp);
|
||||
if (r < 0)
|
||||
@ -825,7 +870,6 @@ int link_drop_addresses(Link *link) {
|
||||
|
||||
static int address_acquire(Link *link, const Address *original, Address **ret) {
|
||||
union in_addr_union in_addr = IN_ADDR_NULL;
|
||||
struct in_addr broadcast = {};
|
||||
_cleanup_(address_freep) Address *na = NULL;
|
||||
int r;
|
||||
|
||||
@ -847,16 +891,10 @@ static int address_acquire(Link *link, const Address *original, Address **ret) {
|
||||
if (r == 0)
|
||||
return -EBUSY;
|
||||
|
||||
if (original->family == AF_INET) {
|
||||
/* Pick first address in range for ourselves ... */
|
||||
/* Pick first address in range for ourselves. */
|
||||
if (original->family == AF_INET)
|
||||
in_addr.in.s_addr = in_addr.in.s_addr | htobe32(1);
|
||||
|
||||
/* .. and use last as broadcast address */
|
||||
if (original->prefixlen > 30)
|
||||
broadcast.s_addr = 0;
|
||||
else
|
||||
broadcast.s_addr = in_addr.in.s_addr | htobe32(0xFFFFFFFFUL >> original->prefixlen);
|
||||
} else if (original->family == AF_INET6)
|
||||
else if (original->family == AF_INET6)
|
||||
in_addr.in6.s6_addr[15] |= 1;
|
||||
|
||||
r = address_new(&na);
|
||||
@ -867,8 +905,8 @@ static int address_acquire(Link *link, const Address *original, Address **ret) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
na->broadcast = broadcast;
|
||||
na->in_addr = in_addr;
|
||||
address_set_broadcast(na);
|
||||
|
||||
r = set_ensure_put(&link->pool_addresses, &address_hash_ops, na);
|
||||
if (r < 0)
|
||||
@ -1119,6 +1157,32 @@ int link_request_static_addresses(Link *link) {
|
||||
req->after_configure = static_address_after_configure;
|
||||
}
|
||||
|
||||
if (in4_addr_is_set(&link->network->dhcp_server_address)) {
|
||||
_cleanup_(address_freep) Address *address = NULL;
|
||||
|
||||
r = address_new(&address);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
address->family = AF_INET;
|
||||
address->in_addr.in = link->network->dhcp_server_address;
|
||||
address->prefixlen = link->network->dhcp_server_address_prefixlen;
|
||||
address_set_broadcast(address);
|
||||
|
||||
/* The same address may be explicitly configured in [Address] or [Network] section.
|
||||
* Configure the DHCP server address only when it is not. */
|
||||
if (!link_is_static_address_configured(link, address)) {
|
||||
Request *req;
|
||||
|
||||
r = link_request_address(link, TAKE_PTR(address), true, &link->static_address_messages,
|
||||
static_address_handler, &req);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
req->after_configure = static_address_after_configure;
|
||||
}
|
||||
}
|
||||
|
||||
if (link->static_address_messages == 0) {
|
||||
link->static_addresses_configured = true;
|
||||
link_check_ready(link);
|
||||
@ -1960,10 +2024,9 @@ static int address_section_verify(Address *address) {
|
||||
address->section->filename, address->section->line);
|
||||
}
|
||||
|
||||
if (address_may_have_broadcast(address)) {
|
||||
if (address->broadcast.s_addr == 0 && address->set_broadcast != 0)
|
||||
address->broadcast.s_addr = address->in_addr.in.s_addr | htobe32(0xfffffffflu >> address->prefixlen);
|
||||
} else if (address->broadcast.s_addr != 0) {
|
||||
if (address_may_have_broadcast(address))
|
||||
address_set_broadcast(address);
|
||||
else if (address->broadcast.s_addr != 0) {
|
||||
log_warning("%s: broadcast address is set for IPv6 address or IPv4 address with prefixlength larger than 30. "
|
||||
"Ignoring Broadcast= setting in the [Address] section from line %u.",
|
||||
address->section->filename, address->section->line);
|
||||
|
@ -57,6 +57,7 @@ int address_remove_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, Lin
|
||||
int address_remove(const Address *address, Link *link, link_netlink_message_handler_t callback);
|
||||
bool address_equal(const Address *a1, const Address *a2);
|
||||
bool address_is_ready(const Address *a);
|
||||
void address_set_broadcast(Address *a);
|
||||
|
||||
int generate_ipv6_eui_64_address(const Link *link, struct in6_addr *ret);
|
||||
|
||||
@ -65,7 +66,8 @@ DEFINE_NETWORK_SECTION_FUNCTIONS(Address, address_free);
|
||||
int link_drop_addresses(Link *link);
|
||||
int link_drop_foreign_addresses(Link *link);
|
||||
bool link_address_is_dynamic(const Link *link, const Address *address);
|
||||
int link_has_ipv6_address(Link *link, const struct in6_addr *address);
|
||||
int link_get_ipv6_address(Link *link, const struct in6_addr *address, Address **ret);
|
||||
int link_get_ipv4_address(Link *link, const struct in_addr *address, unsigned char prefixlen, Address **ret);
|
||||
int manager_has_address(Manager *manager, int family, const union in_addr_union *address, bool check_ready);
|
||||
|
||||
void ipv4_dad_unref(Link *link);
|
||||
|
@ -29,33 +29,70 @@ static bool link_dhcp4_server_enabled(Link *link) {
|
||||
if (!link->network)
|
||||
return false;
|
||||
|
||||
if (link->network->bond)
|
||||
return false;
|
||||
|
||||
if (link->iftype == ARPHRD_CAN)
|
||||
return false;
|
||||
|
||||
return link->network->dhcp_server;
|
||||
}
|
||||
|
||||
static Address* link_find_dhcp_server_address(Link *link) {
|
||||
void network_adjust_dhcp_server(Network *network) {
|
||||
assert(network);
|
||||
|
||||
if (!network->dhcp_server)
|
||||
return;
|
||||
|
||||
if (network->bond) {
|
||||
log_warning("%s: DHCPServer= is enabled for bond slave. Disabling DHCP server.",
|
||||
network->filename);
|
||||
network->dhcp_server = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!in4_addr_is_set(&network->dhcp_server_address)) {
|
||||
Address *address;
|
||||
bool have = false;
|
||||
|
||||
ORDERED_HASHMAP_FOREACH(address, network->addresses_by_section) {
|
||||
if (section_is_invalid(address->section))
|
||||
continue;
|
||||
if (address->family == AF_INET &&
|
||||
!in4_addr_is_localhost(&address->in_addr.in) &&
|
||||
in4_addr_is_null(&address->in_addr_peer.in)) {
|
||||
have = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!have) {
|
||||
log_warning("%s: DHCPServer= is enabled, but no static address configured. "
|
||||
"Disabling DHCP server.",
|
||||
network->filename);
|
||||
network->dhcp_server = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int link_find_dhcp_server_address(Link *link, Address **ret) {
|
||||
Address *address;
|
||||
|
||||
assert(link);
|
||||
assert(link->network);
|
||||
|
||||
/* The first statically configured address if there is any */
|
||||
ORDERED_HASHMAP_FOREACH(address, link->network->addresses_by_section)
|
||||
/* If ServerAddress= is specified, then use the address. */
|
||||
if (in4_addr_is_set(&link->network->dhcp_server_address))
|
||||
return link_get_ipv4_address(link, &link->network->dhcp_server_address,
|
||||
link->network->dhcp_server_address_prefixlen, ret);
|
||||
|
||||
/* If not, then select one from static addresses. */
|
||||
SET_FOREACH(address, link->static_addresses)
|
||||
if (address->family == AF_INET &&
|
||||
in_addr_is_set(address->family, &address->in_addr))
|
||||
return address;
|
||||
!in4_addr_is_localhost(&address->in_addr.in) &&
|
||||
in4_addr_is_null(&address->in_addr_peer.in)) {
|
||||
*ret = address;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If that didn't work, find a suitable address we got from the pool */
|
||||
SET_FOREACH(address, link->pool_addresses)
|
||||
if (address->family == AF_INET)
|
||||
return address;
|
||||
|
||||
return NULL;
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static int link_push_uplink_to_dhcp_server(
|
||||
@ -277,10 +314,9 @@ int dhcp4_server_configure(Link *link) {
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to set callback for DHCPv4 server instance: %m");
|
||||
|
||||
address = link_find_dhcp_server_address(link);
|
||||
if (!address)
|
||||
return log_link_error_errno(link, SYNTHETIC_ERRNO(EBUSY),
|
||||
"Failed to find suitable address for DHCPv4 server instance.");
|
||||
r = link_find_dhcp_server_address(link, &address);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Failed to find suitable address for DHCPv4 server instance: %m");
|
||||
|
||||
/* use the server address' subnet as the pool */
|
||||
r = sd_dhcp_server_configure_pool(link->dhcp_server, &address->in_addr.in, address->prefixlen,
|
||||
@ -429,7 +465,6 @@ int config_parse_dhcp_server_relay_agent_suboption(
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
|
||||
|
||||
if (isempty(rvalue)) {
|
||||
*suboption_value = mfree(*suboption_value);
|
||||
return 0;
|
||||
@ -444,32 +479,6 @@ int config_parse_dhcp_server_relay_agent_suboption(
|
||||
return free_and_strdup(suboption_value, empty_to_null(p));
|
||||
}
|
||||
|
||||
int config_parse_dhcp_server_relay_target(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
Network *network = userdata;
|
||||
union in_addr_union a;
|
||||
int r;
|
||||
|
||||
r = in_addr_from_string(AF_INET, rvalue, &a);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
||||
"Failed to parse %s= address '%s', ignoring: %m", lvalue, rvalue);
|
||||
return 0;
|
||||
}
|
||||
network->dhcp_server_relay_target = a.in;
|
||||
return r;
|
||||
}
|
||||
|
||||
int config_parse_dhcp_server_emit(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
@ -518,3 +527,48 @@ int config_parse_dhcp_server_emit(
|
||||
emit->addresses[emit->n_addresses++] = a.in;
|
||||
}
|
||||
}
|
||||
|
||||
int config_parse_dhcp_server_address(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
Network *network = userdata;
|
||||
union in_addr_union a;
|
||||
unsigned char prefixlen;
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
|
||||
if (isempty(rvalue)) {
|
||||
network->dhcp_server_address = (struct in_addr) {};
|
||||
network->dhcp_server_address_prefixlen = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = in_addr_prefix_from_string(rvalue, AF_INET, &a, &prefixlen);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
||||
"Failed to parse %s=, ignoring assignment: %s", lvalue, rvalue);
|
||||
return 0;
|
||||
}
|
||||
if (in4_addr_is_null(&a.in) || in4_addr_is_localhost(&a.in)) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0,
|
||||
"DHCP server address cannot be the ANY address or a localhost address, "
|
||||
"ignoring assignment: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
network->dhcp_server_address = a.in;
|
||||
network->dhcp_server_address_prefixlen = prefixlen;
|
||||
return 0;
|
||||
}
|
||||
|
@ -2,13 +2,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "conf-parser.h"
|
||||
#include "networkd-link.h"
|
||||
#include "networkd-util.h"
|
||||
|
||||
typedef struct Link Link;
|
||||
typedef struct Network Network;
|
||||
|
||||
void network_adjust_dhcp_server(Network *network);
|
||||
|
||||
int dhcp4_server_configure(Link *link);
|
||||
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_relay_agent_suboption);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_relay_target);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_emit);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_address);
|
||||
|
@ -1888,47 +1888,3 @@ int config_parse_dhcp6_pd_subnet_id(
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_dhcp6_pd_token(
|
||||
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) {
|
||||
|
||||
struct in6_addr *addr = data;
|
||||
union in_addr_union tmp;
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
assert(data);
|
||||
|
||||
if (isempty(rvalue)) {
|
||||
*addr = (struct in6_addr) {};
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = in_addr_from_string(AF_INET6, rvalue, &tmp);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
||||
"Failed to parse DHCPv6 Prefix Delegation token, ignoring: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (in_addr_is_null(AF_INET6, &tmp)) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0,
|
||||
"DHCPv6 Prefix Delegation token cannot be the ANY address, ignoring: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*addr = tmp.in6;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -41,7 +41,6 @@ CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_pd_hint);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_mud_url);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_client_start_mode);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_pd_subnet_id);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_pd_token);
|
||||
|
||||
const char* dhcp6_client_start_mode_to_string(DHCP6ClientStartMode i) _const_;
|
||||
DHCP6ClientStartMode dhcp6_client_start_mode_from_string(const char *s) _pure_;
|
||||
|
@ -31,9 +31,9 @@ static int address_new_from_ipv4ll(Link *link, Address **ret) {
|
||||
address->family = AF_INET;
|
||||
address->in_addr.in = addr;
|
||||
address->prefixlen = 16;
|
||||
address->broadcast.s_addr = address->in_addr.in.s_addr | htobe32(UINT32_C(0xffffffff) >> address->prefixlen);
|
||||
address->scope = RT_SCOPE_LINK;
|
||||
address->route_metric = IPV4LL_ROUTE_METRIC;
|
||||
address_set_broadcast(address);
|
||||
|
||||
*ret = TAKE_PTR(address);
|
||||
return 0;
|
||||
|
@ -541,7 +541,7 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Failed to get gateway address from RA: %m");
|
||||
|
||||
if (link_has_ipv6_address(link, &gateway) > 0) {
|
||||
if (link_get_ipv6_address(link, &gateway, NULL) >= 0) {
|
||||
if (DEBUG_LOGGING) {
|
||||
_cleanup_free_ char *buffer = NULL;
|
||||
|
||||
@ -918,7 +918,7 @@ static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) {
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Failed to get gateway address from RA: %m");
|
||||
|
||||
if (link_has_ipv6_address(link, &gateway) > 0) {
|
||||
if (link_get_ipv6_address(link, &gateway, NULL) >= 0) {
|
||||
if (DEBUG_LOGGING) {
|
||||
_cleanup_free_ char *buf = NULL;
|
||||
|
||||
|
@ -261,7 +261,8 @@ IPv6AcceptRA.PrefixAllowList, config_parse_ndisc_address_filter,
|
||||
IPv6AcceptRA.PrefixDenyList, config_parse_ndisc_address_filter, 0, offsetof(Network, ndisc_deny_listed_prefix)
|
||||
IPv6AcceptRA.RouteAllowList, config_parse_ndisc_address_filter, 0, offsetof(Network, ndisc_allow_listed_route_prefix)
|
||||
IPv6AcceptRA.RouteDenyList, config_parse_ndisc_address_filter, 0, offsetof(Network, ndisc_deny_listed_route_prefix)
|
||||
DHCPServer.RelayTarget, config_parse_dhcp_server_relay_target, 0, 0
|
||||
DHCPServer.ServerAddress, config_parse_dhcp_server_address, 0, 0
|
||||
DHCPServer.RelayTarget, config_parse_in_addr_non_null, AF_INET, offsetof(Network, dhcp_server_relay_target)
|
||||
DHCPServer.RelayAgentCircuitId, config_parse_dhcp_server_relay_agent_suboption, 0, offsetof(Network, dhcp_server_relay_agent_circuit_id)
|
||||
DHCPServer.RelayAgentRemoteId, config_parse_dhcp_server_relay_agent_suboption, 0, offsetof(Network, dhcp_server_relay_agent_remote_id)
|
||||
DHCPServer.MaxLeaseTimeSec, config_parse_sec, 0, offsetof(Network, dhcp_server_max_lease_time_usec)
|
||||
@ -314,7 +315,7 @@ DHCPv6PrefixDelegation.SubnetId, config_parse_dhcp6_pd_subnet_id,
|
||||
DHCPv6PrefixDelegation.Announce, config_parse_bool, 0, offsetof(Network, dhcp6_pd_announce)
|
||||
DHCPv6PrefixDelegation.Assign, config_parse_bool, 0, offsetof(Network, dhcp6_pd_assign)
|
||||
DHCPv6PrefixDelegation.ManageTemporaryAddress, config_parse_bool, 0, offsetof(Network, dhcp6_pd_manage_temporary_address)
|
||||
DHCPv6PrefixDelegation.Token, config_parse_dhcp6_pd_token, 0, offsetof(Network, dhcp6_pd_token)
|
||||
DHCPv6PrefixDelegation.Token, config_parse_in_addr_non_null, AF_INET6, offsetof(Network, dhcp6_pd_token)
|
||||
DHCPv6PrefixDelegation.RouteMetric, config_parse_uint32, 0, offsetof(Network, dhcp6_pd_route_metric)
|
||||
IPv6SendRA.RouterLifetimeSec, config_parse_sec, 0, offsetof(Network, router_lifetime_usec)
|
||||
IPv6SendRA.Managed, config_parse_bool, 0, offsetof(Network, router_managed)
|
||||
|
@ -240,6 +240,8 @@ int network_verify(Network *network) {
|
||||
network_drop_invalid_traffic_control(network);
|
||||
network_drop_invalid_sr_iov(network);
|
||||
|
||||
network_adjust_dhcp_server(network);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -189,10 +189,11 @@ struct Network {
|
||||
/* DHCP Server Support */
|
||||
bool dhcp_server;
|
||||
bool dhcp_server_bind_to_interface;
|
||||
unsigned char dhcp_server_address_prefixlen;
|
||||
struct in_addr dhcp_server_address;
|
||||
struct in_addr dhcp_server_relay_target;
|
||||
char *dhcp_server_relay_agent_circuit_id;
|
||||
char *dhcp_server_relay_agent_remote_id;
|
||||
|
||||
NetworkDHCPServerEmitAddress dhcp_server_emit[_SD_DHCP_LEASE_SERVER_TYPE_MAX];
|
||||
bool dhcp_server_emit_router;
|
||||
bool dhcp_server_emit_timezone;
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "fs-util.h"
|
||||
#include "in-addr-util.h"
|
||||
#include "log.h"
|
||||
#include "macro.h"
|
||||
#include "missing_network.h"
|
||||
@ -1359,5 +1360,57 @@ int config_parse_hwaddrs(
|
||||
}
|
||||
}
|
||||
|
||||
int config_parse_in_addr_non_null(
|
||||
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) {
|
||||
|
||||
/* data must be a pointer to struct in_addr or in6_addr, and the type is determined by ltype. */
|
||||
struct in_addr *ipv4 = data;
|
||||
struct in6_addr *ipv6 = data;
|
||||
union in_addr_union a;
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
assert(data);
|
||||
assert(IN_SET(ltype, AF_INET, AF_INET6));
|
||||
|
||||
if (isempty(rvalue)) {
|
||||
if (ltype == AF_INET)
|
||||
*ipv4 = (struct in_addr) {};
|
||||
else
|
||||
*ipv6 = (struct in6_addr) {};
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = in_addr_from_string(ltype, rvalue, &a);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
||||
"Failed to parse %s=, ignoring assignment: %s", lvalue, rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!in_addr_is_set(ltype, &a)) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0,
|
||||
"%s= cannot be the ANY address, ignoring: %s", lvalue, rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ltype == AF_INET)
|
||||
*ipv4 = a.in;
|
||||
else
|
||||
*ipv6 = a.in6;
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_CONFIG_PARSE(config_parse_percent, parse_percent, "Failed to parse percent value");
|
||||
DEFINE_CONFIG_PARSE(config_parse_permyriad, parse_permyriad, "Failed to parse permyriad value");
|
||||
|
@ -149,6 +149,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_rlimit);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_vlanprotocol);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_hwaddr);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_hwaddrs);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_in_addr_non_null);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_percent);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_permyriad);
|
||||
|
||||
|
@ -364,6 +364,7 @@ BindToInterface=
|
||||
RelayTarget=
|
||||
RelayAgentCircuitId=
|
||||
RelayAgentRemoteId=
|
||||
ServerAddress=
|
||||
[NextHop]
|
||||
Id=
|
||||
Gateway=
|
||||
|
@ -4,9 +4,11 @@ Name=veth-peer
|
||||
[Network]
|
||||
IPv6AcceptRA=false
|
||||
Address=192.168.5.1/24
|
||||
Address=192.168.5.2/24
|
||||
DHCPServer=yes
|
||||
|
||||
[DHCPServer]
|
||||
Address=192.168.5.1/24
|
||||
PoolOffset=10
|
||||
PoolSize=50
|
||||
EmitRouter=yes
|
||||
|
@ -2,11 +2,11 @@
|
||||
Name=veth-peer
|
||||
|
||||
[Network]
|
||||
Address=192.168.5.1/24
|
||||
IPv6AcceptRA=false
|
||||
DHCPServer=yes
|
||||
|
||||
[DHCPServer]
|
||||
ServerAddress=192.168.5.1/24
|
||||
PoolOffset=10
|
||||
PoolSize=50
|
||||
DNS=192.168.5.1
|
||||
|
Loading…
x
Reference in New Issue
Block a user