X Tutup
Skip to content

Commit 045d723

Browse files
authored
Merge pull request systemd#19852 from yuwata/network-stable-secret
network: introduce IPv6StableSecretAddress= to configure secret key for generating IPv6LL address
2 parents e68778a + 4681ab5 commit 045d723

File tree

9 files changed

+85
-37
lines changed

9 files changed

+85
-37
lines changed

man/systemd.network.xml

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -424,13 +424,27 @@
424424
<listitem>
425425
<para>Specifies how IPv6 link local address is generated. Takes one of
426426
<literal>eui64</literal>, <literal>none</literal>, <literal>stable-privacy</literal> and
427-
<literal>random</literal>. When unset, the kernel's default will be used. Note that if
428-
<varname>LinkLocalAddressing=</varname> is <literal>no</literal> or
429-
<literal>ipv4</literal>, then <varname>IPv6LinkLocalAddressGenerationMode=</varname> will
430-
be ignored. Also, even if <varname>LinkLocalAddressing=</varname> is <literal>yes</literal>
431-
or <literal>ipv6</literal>, setting
432-
<varname>IPv6LinkLocalAddressGenerationMode=none</varname> disables to configure an IPv6
433-
link-local address.</para>
427+
<literal>random</literal>. When unset, <literal>stable-privacy</literal> is used if
428+
<varname>IPv6StableSecretAddress=</varname> is specified, and if not,
429+
<literal>eui64</literal> is used. Note that if <varname>LinkLocalAddressing=</varname> is
430+
<literal>no</literal> or <literal>ipv4</literal>, then
431+
<varname>IPv6LinkLocalAddressGenerationMode=</varname> will be ignored. Also, even if
432+
<varname>LinkLocalAddressing=</varname> is <literal>yes</literal> or
433+
<literal>ipv6</literal>, setting <varname>IPv6LinkLocalAddressGenerationMode=none</varname>
434+
disables to configure an IPv6 link-local address.</para>
435+
</listitem>
436+
</varlistentry>
437+
<varlistentry>
438+
<term><varname>IPv6StableSecretAddress=</varname></term>
439+
<listitem>
440+
<para>Takes an IPv6 address. The specified address will be used as a stable secret for
441+
generating IPv6 link-local address. If this setting is specified, and
442+
<varname>IPv6LinkLocalAddressGenerationMode=</varname> is unset, then
443+
<varname>IPv6LinkLocalAddressGenerationMode=stable-privacy</varname> is implied.
444+
If this setting is not specified, and <literal>stable-privacy</literal> is set to
445+
<varname>IPv6LinkLocalAddressGenerationMode=</varname>,
446+
then a stable secret address will be generated from the local machine ID and the interface
447+
name.</para>
434448
</listitem>
435449
</varlistentry>
436450
<varlistentry>

src/network/networkd-network-gperf.gperf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ Network.DHCP, config_parse_dhcp,
9797
Network.DHCPServer, config_parse_bool, 0, offsetof(Network, dhcp_server)
9898
Network.LinkLocalAddressing, config_parse_link_local_address_family, 0, offsetof(Network, link_local)
9999
Network.IPv6LinkLocalAddressGenerationMode, config_parse_ipv6_link_local_address_gen_mode, 0, offsetof(Network, ipv6ll_address_gen_mode)
100+
Network.IPv6StableSecretAddress, config_parse_in_addr_non_null, AF_INET6, offsetof(Network, ipv6ll_stable_secret)
100101
Network.IPv4LLRoute, config_parse_bool, 0, offsetof(Network, ipv4ll_route)
101102
Network.DefaultRouteOnDevice, config_parse_bool, 0, offsetof(Network, default_route_on_device)
102103
Network.IPv6Token, config_parse_address_generation_type, 0, 0

src/network/networkd-network.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,10 @@ int network_verify(Network *network) {
175175
if (network->ipv6ll_address_gen_mode == IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_NONE)
176176
SET_FLAG(network->link_local, ADDRESS_FAMILY_IPV6, false);
177177

178+
if (in6_addr_is_set(&network->ipv6ll_stable_secret) &&
179+
network->ipv6ll_address_gen_mode < 0)
180+
network->ipv6ll_address_gen_mode = IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_STABLE_PRIVACY;
181+
178182
/* IPMasquerade implies IPForward */
179183
network->ip_forward |= network->ip_masquerade;
180184

src/network/networkd-network.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ struct Network {
209209
/* link local addressing support */
210210
AddressFamily link_local;
211211
IPv6LinkLocalAddressGenMode ipv6ll_address_gen_mode;
212+
struct in6_addr ipv6ll_stable_secret;
212213
bool ipv4ll_route;
213214

214215
/* IPv6 RA support */

src/network/networkd-setlink.c

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -591,18 +591,10 @@ int link_request_to_set_addrgen_mode(Link *link) {
591591
mode = IN6_ADDR_GEN_MODE_NONE;
592592
else if (link->network->ipv6ll_address_gen_mode >= 0)
593593
mode = link->network->ipv6ll_address_gen_mode;
594-
else {
595-
r = sysctl_read_ip_property(AF_INET6, link->ifname, "stable_secret", NULL);
596-
if (r < 0) {
597-
/* The file may not exist. And even if it exists, when stable_secret is unset,
598-
* reading the file fails with ENOMEM when read_full_virtual_file(), which uses
599-
* read() as the backend, and EIO when read_one_line_file() which uses fgetc(). */
600-
log_link_debug_errno(link, r, "Failed to read sysctl property stable_secret, ignoring: %m");
601-
602-
mode = IN6_ADDR_GEN_MODE_EUI64;
603-
} else
604-
mode = IN6_ADDR_GEN_MODE_STABLE_PRIVACY;
605-
}
594+
else if (in6_addr_is_set(&link->network->ipv6ll_stable_secret))
595+
mode = IN6_ADDR_GEN_MODE_STABLE_PRIVACY;
596+
else
597+
mode = IN6_ADDR_GEN_MODE_EUI64;
606598

607599
r = link_request_set_link(link, SET_LINK_ADDRESS_GENERATION_MODE, link_set_addrgen_mode_handler, &req);
608600
if (r < 0)

src/network/networkd-sysctl.c

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
#include "string-table.h"
1212
#include "sysctl-util.h"
1313

14+
#define STABLE_SECRET_APP_ID_1 SD_ID128_MAKE(aa,05,1d,94,43,68,45,07,b9,73,f1,e8,e4,b7,34,52)
15+
#define STABLE_SECRET_APP_ID_2 SD_ID128_MAKE(52,c4,40,a0,9f,2f,48,58,a9,3a,f6,29,25,ba,7a,7d)
16+
1417
static int link_update_ipv6_sysctl(Link *link) {
1518
assert(link);
1619

@@ -211,6 +214,48 @@ int link_set_ipv6_mtu(Link *link) {
211214
return sysctl_write_ip_property_uint32(AF_INET6, link->ifname, "mtu", mtu);
212215
}
213216

217+
static int link_set_ipv6ll_stable_secret(Link *link) {
218+
_cleanup_free_ char *str = NULL;
219+
struct in6_addr a;
220+
int r;
221+
222+
assert(link);
223+
assert(link->network);
224+
225+
if (link->network->ipv6ll_address_gen_mode != IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_STABLE_PRIVACY)
226+
return 0;
227+
228+
if (in6_addr_is_set(&link->network->ipv6ll_stable_secret))
229+
a = link->network->ipv6ll_stable_secret;
230+
else {
231+
sd_id128_t key;
232+
le64_t v;
233+
234+
/* Generate a stable secret address from machine-ID and the interface name. */
235+
236+
r = sd_id128_get_machine_app_specific(STABLE_SECRET_APP_ID_1, &key);
237+
if (r < 0)
238+
return log_link_debug_errno(link, r, "Failed to generate key: %m");
239+
240+
v = htole64(siphash24_string(link->ifname, key.bytes));
241+
memcpy(a.s6_addr, &v, sizeof(v));
242+
243+
r = sd_id128_get_machine_app_specific(STABLE_SECRET_APP_ID_2, &key);
244+
if (r < 0)
245+
return log_link_debug_errno(link, r, "Failed to generate key: %m");
246+
247+
v = htole64(siphash24_string(link->ifname, key.bytes));
248+
assert_cc(sizeof(v) * 2 == sizeof(a.s6_addr));
249+
memcpy(a.s6_addr + sizeof(v), &v, sizeof(v));
250+
}
251+
252+
r = in6_addr_to_string(&a, &str);
253+
if (r < 0)
254+
return r;
255+
256+
return sysctl_write_ip_property(AF_INET6, link->ifname, "stable_secret", str);
257+
}
258+
214259
static int link_set_ipv4_accept_local(Link *link) {
215260
assert(link);
216261

@@ -282,6 +327,10 @@ int link_set_sysctl(Link *link) {
282327
if (r < 0)
283328
log_link_warning_errno(link, r, "Cannot set IPv6 MTU, ignoring: %m");
284329

330+
r = link_set_ipv6ll_stable_secret(link);
331+
if (r < 0)
332+
log_link_warning_errno(link, r, "Cannot set stable secret address for IPv6 link local address: %m");
333+
285334
r = link_set_ipv4_accept_local(link);
286335
if (r < 0)
287336
log_link_warning_errno(link, r, "Cannot set IPv4 accept_local flag for interface, ignoring: %m");

test/fuzz/fuzz-network-parser/directives.network

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ L2TP=
222222
MACsec=
223223
LinkLocalAddressing=
224224
IPv6LinkLocalAddressGenerationMode=
225+
IPv6StableSecretAddress=
225226
ConfigureWithoutCarrier=
226227
NTP=
227228
DHCP=

test/test-network/conf/25-link-local-addressing-yes.network

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ Name=test1
44
[Network]
55
LinkLocalAddressing=yes
66
IPv6AcceptRA=no
7+
IPv6StableSecretAddress=0123:4567:89ab:cdef:0123:4567:89ab:cdef

test/test-network/systemd-networkd-tests.py

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2619,24 +2619,9 @@ def test_link_local_addressing(self):
26192619
3: generate stable privacy addresses, using a random secret if unset
26202620
'''
26212621

2622-
test1_addr_gen_mode = ''
2623-
if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'stable_secret')):
2624-
with open(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'stable_secret')) as f:
2625-
try:
2626-
f.readline()
2627-
except IOError:
2628-
# if stable_secret is unset, then EIO is returned
2629-
test1_addr_gen_mode = '0'
2630-
else:
2631-
test1_addr_gen_mode = '2'
2632-
else:
2633-
test1_addr_gen_mode = '0'
2634-
2635-
if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'addr_gen_mode')):
2636-
self.assertEqual(read_ipv6_sysctl_attr('test1', 'addr_gen_mode'), test1_addr_gen_mode)
2637-
2638-
if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'dummy98'), 'addr_gen_mode')):
2639-
self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'addr_gen_mode'), '1')
2622+
self.assertEqual(read_ipv6_sysctl_attr('test1', 'stable_secret'), '0123:4567:89ab:cdef:0123:4567:89ab:cdef')
2623+
self.assertEqual(read_ipv6_sysctl_attr('test1', 'addr_gen_mode'), '2')
2624+
self.assertEqual(read_ipv6_sysctl_attr('dummy98', 'addr_gen_mode'), '1')
26402625

26412626
def test_link_local_addressing_remove_ipv6ll(self):
26422627
copy_unit_to_networkd_unit_path('26-link-local-addressing-ipv6.network', '12-dummy.netdev')

0 commit comments

Comments
 (0)
X Tutup