1
0
mirror of https://github.com/systemd/systemd.git synced 2025-03-19 22:50:17 +03:00

Merge pull request #23927 from AndreKalb/feature/ipv4-link-local-start-address

network: Feature IPv4 link-local start address
This commit is contained in:
Yu Watanabe 2022-07-15 03:21:26 +09:00 committed by GitHub
commit c1dd250f18
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 111 additions and 11 deletions

View File

@ -398,6 +398,18 @@
</listitem>
</varlistentry>
<varlistentry>
<term><varname>IPv4LLStartAddress=</varname></term>
<listitem>
<para>Specifies the first IPv4 link-local address to try. Takes an IPv4 address
for example 169.254.1.2, from the link-local address range 169.254.0.0/16.
This setting may be useful if the device should always have the same address
as long as there is no address conflict. When unset, a random address will be automatically selected.
Defaults to unset.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>IPv4LLRoute=</varname></term>
<listitem>
@ -2534,7 +2546,7 @@ Token=prefixstable:2002:da8:1::</programlisting></para>
<varlistentry>
<term><varname>ServerAddress=</varname></term>
<listitem><para>Specifies server address for the DHCP server. Takes an IPv4 address with prefix
length, for example <literal>192.168.0.1/24</literal>. This setting may be useful when the link on
length, for example 192.168.0.1/24. This setting may be useful when the link on
which the DHCP server is running has multiple static addresses. When unset, one of static addresses
in the link will be automatically selected. Defaults to unset.</para></listitem>
</varlistentry>

View File

@ -39,7 +39,7 @@ static void ll_handler(sd_ipv4ll *ll, int event, void *userdata) {
}
}
static int client_run(int ifindex, const char *seed_str, const struct ether_addr *ha, sd_event *e) {
static int client_run(int ifindex, const char *seed_str, const struct in_addr *start_address, const struct ether_addr *ha, sd_event *e) {
sd_ipv4ll *ll;
assert_se(sd_ipv4ll_new(&ll) >= 0);
@ -57,6 +57,9 @@ static int client_run(int ifindex, const char *seed_str, const struct ether_addr
assert_se(sd_ipv4ll_set_address_seed(ll, seed) >= 0);
}
if (start_address && in4_addr_is_set(start_address))
assert_se(sd_ipv4ll_set_address(ll, start_address) >= 0);
log_info("starting IPv4LL client");
assert_se(sd_ipv4ll_start(ll) >= 0);
@ -68,7 +71,7 @@ static int client_run(int ifindex, const char *seed_str, const struct ether_addr
return EXIT_SUCCESS;
}
static int test_ll(const char *ifname, const char *seed) {
static int test_ll(const char *ifname, const char *seed, const struct in_addr *start_address) {
_cleanup_(sd_event_unrefp) sd_event *e = NULL;
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *reply = NULL;
@ -87,7 +90,7 @@ static int test_ll(const char *ifname, const char *seed) {
assert_se(sd_rtnl_message_link_get_ifindex(reply, &ifindex) >= 0);
assert_se(sd_netlink_message_read_ether_addr(reply, IFLA_ADDRESS, &ha) >= 0);
client_run(ifindex, seed, &ha, e);
client_run(ifindex, seed, start_address, &ha, e);
return EXIT_SUCCESS;
}
@ -96,12 +99,19 @@ int main(int argc, char *argv[]) {
test_setup_logging(LOG_DEBUG);
if (argc == 2)
return test_ll(argv[1], NULL);
else if (argc == 3)
return test_ll(argv[1], argv[2]);
else {
return test_ll(argv[1], NULL, NULL);
else if (argc == 3) {
int r;
union in_addr_union a;
r = in_addr_from_string(AF_INET, argv[2], &a);
if (r < 0)
return test_ll(argv[1], argv[2], NULL);
else
return test_ll(argv[1], NULL, &a.in);
} else {
log_error("This program takes one or two arguments.\n"
"\t %s <ifname> [<seed>]", program_invocation_short_name);
"\t %s <ifname> [<seed>|<start_address>]", program_invocation_short_name);
return EXIT_FAILURE;
}
}

View File

@ -122,7 +122,7 @@ static void test_public_api_setters(sd_event *e) {
assert_se(sd_ipv4ll_unref(ll) == NULL);
}
static void test_basic_request(sd_event *e) {
static void test_basic_request(sd_event *e, const struct in_addr *start_address) {
sd_ipv4ll *ll;
struct ether_arp arp;
@ -133,6 +133,8 @@ static void test_basic_request(sd_event *e) {
printf("* %s\n", __func__);
assert_se(sd_ipv4ll_new(&ll) == 0);
if (in4_addr_is_set(start_address))
assert_se(sd_ipv4ll_set_address(ll, start_address) >= 0);
assert_se(sd_ipv4ll_start(ll) == -EINVAL);
assert_se(sd_ipv4ll_attach_event(ll, e, 0) == 0);
@ -168,6 +170,13 @@ static void test_basic_request(sd_event *e) {
sd_event_run(e, UINT64_MAX);
assert_se(basic_request_handler_bind == 1);
if (in4_addr_is_set(start_address)) {
struct in_addr address;
assert_se(sd_ipv4ll_get_address(ll, &address) >= 0);
assert_se(start_address->s_addr == address.s_addr);
}
}
sd_ipv4ll_stop(ll);
@ -179,6 +188,7 @@ static void test_basic_request(sd_event *e) {
}
int main(int argc, char *argv[]) {
struct in_addr start_address = {};
_cleanup_(sd_event_unrefp) sd_event *e = NULL;
test_setup_logging(LOG_DEBUG);
@ -186,7 +196,12 @@ int main(int argc, char *argv[]) {
assert_se(sd_event_new(&e) >= 0);
test_public_api_setters(e);
test_basic_request(e);
test_basic_request(e, &start_address);
basic_request_handler_bind = 0;
basic_request_handler_stop = 0;
start_address.s_addr = htobe32(169U << 24 | 254U << 16 | 1U << 8 | 2U);
test_basic_request(e, &start_address);
return 0;
}

View File

@ -1071,6 +1071,12 @@ static int dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {
if (link->ipv4ll) {
log_link_debug(link, "DHCP client is stopped. Acquiring IPv4 link-local address");
if (in4_addr_is_set(&link->network->ipv4ll_start_address)) {
r = sd_ipv4ll_set_address(link->ipv4ll, &link->network->ipv4ll_start_address);
if (r < 0)
return log_link_warning_errno(link, r, "Could not set IPv4 link-local start address: %m");;
}
r = sd_ipv4ll_start(link->ipv4ll);
if (r < 0)
return log_link_warning_errno(link, r, "Could not acquire IPv4 link-local address: %m");
@ -1154,6 +1160,12 @@ static int dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {
if (link->ipv4ll && !sd_ipv4ll_is_running(link->ipv4ll)) {
log_link_debug(link, "Problems acquiring DHCP lease, acquiring IPv4 link-local address");
if (in4_addr_is_set(&link->network->ipv4ll_start_address)) {
r = sd_ipv4ll_set_address(link->ipv4ll, &link->network->ipv4ll_start_address);
if (r < 0)
return log_link_warning_errno(link, r, "Could not set IPv4 link-local start address: %m");;
}
r = sd_ipv4ll_start(link->ipv4ll);
if (r < 0)
return log_link_warning_errno(link, r, "Could not acquire IPv4 link-local address: %m");

View File

@ -263,3 +263,44 @@ int config_parse_ipv4ll(
return 0;
}
int config_parse_ipv4ll_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) {
union in_addr_union a;
struct in_addr *ipv4ll_address = ASSERT_PTR(data);
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
if (isempty(rvalue)) {
*ipv4ll_address = (struct in_addr) {};
return 0;
}
r = in_addr_from_string(AF_INET, 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 (!in4_addr_is_link_local(&a.in)) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Not a IPv4 link local address, ignoring assignment: %s", rvalue);
return 0;
}
*ipv4ll_address = a.in;
return 0;
}

View File

@ -11,3 +11,4 @@ int ipv4ll_configure(Link *link);
int ipv4ll_update_mac(Link *link);
CONFIG_PARSER_PROTOTYPE(config_parse_ipv4ll);
CONFIG_PARSER_PROTOTYPE(config_parse_ipv4ll_address);

View File

@ -611,6 +611,12 @@ static int link_acquire_dynamic_ipv4_conf(Link *link) {
log_link_debug(link, "Acquiring DHCPv4 lease.");
} else if (link->ipv4ll) {
if (in4_addr_is_set(&link->network->ipv4ll_start_address)) {
r = sd_ipv4ll_set_address(link->ipv4ll, &link->network->ipv4ll_start_address);
if (r < 0)
return log_link_warning_errno(link, r, "Could not set IPv4 link-local start address: %m");
}
r = sd_ipv4ll_start(link->ipv4ll);
if (r < 0)
return log_link_warning_errno(link, r, "Could not acquire IPv4 link-local address: %m");

View File

@ -106,6 +106,7 @@ Network.DHCPServer, config_parse_bool,
Network.LinkLocalAddressing, config_parse_link_local_address_family, 0, offsetof(Network, link_local)
Network.IPv6LinkLocalAddressGenerationMode, config_parse_ipv6_link_local_address_gen_mode, 0, offsetof(Network, ipv6ll_address_gen_mode)
Network.IPv6StableSecretAddress, config_parse_in_addr_non_null, AF_INET6, offsetof(Network, ipv6ll_stable_secret)
Network.IPv4LLStartAddress, config_parse_ipv4ll_address, 0, offsetof(Network, ipv4ll_start_address)
Network.IPv4LLRoute, config_parse_bool, 0, offsetof(Network, ipv4ll_route)
Network.DefaultRouteOnDevice, config_parse_bool, 0, offsetof(Network, default_route_on_device)
Network.LLDP, config_parse_lldp_mode, 0, offsetof(Network, lldp_mode)

View File

@ -208,6 +208,7 @@ struct Network {
AddressFamily link_local;
IPv6LinkLocalAddressGenMode ipv6ll_address_gen_mode;
struct in6_addr ipv6ll_stable_secret;
struct in_addr ipv4ll_start_address;
bool ipv4ll_route;
/* IPv6 RA support */

View File

@ -235,6 +235,7 @@ VXLAN=
L2TP=
MACsec=
LinkLocalAddressing=
IPv4LLStartAddress=
IPv6LinkLocalAddressGenerationMode=
IPv6StableSecretAddress=
ConfigureWithoutCarrier=