mirror of
https://github.com/systemd/systemd
synced 2024-10-14 20:17:52 +00:00
Merge pull request #29442 from yuwata/network-dhcp4-preferred-address
network: introduce [DHCPv4] PreferredAddress= setting
This commit is contained in:
commit
9482d34fb6
|
@ -2098,6 +2098,17 @@ NFTSet=prefix:netdev:filter:eth_ipv4_prefix</programlisting>
|
|||
|
||||
<!-- DHCP packet contents -->
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>RequestAddress=</varname></term>
|
||||
<listitem>
|
||||
<para>Takes an IPv4 address. When specified, the Requested IP Address option (option code 50) is
|
||||
added with it to the initial DHCPDISCOVER message sent by the DHCP client. Defaults to unset, and
|
||||
an already assigned dynamic address to the interface is automatically picked.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v255"/>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>SendHostname=</varname></term>
|
||||
<listitem>
|
||||
|
@ -2232,6 +2243,7 @@ NFTSet=prefix:netdev:filter:eth_ipv4_prefix</programlisting>
|
|||
are implied and these settings in the .network file are silently ignored. Also,
|
||||
<varname>Hostname=</varname>,
|
||||
<varname>MUDURL=</varname>,
|
||||
<varname>RequestAddress</varname>,
|
||||
<varname>RequestOptions=</varname>,
|
||||
<varname>SendOption=</varname>,
|
||||
<varname>SendVendorOption=</varname>,
|
||||
|
|
|
@ -1383,15 +1383,15 @@ static int dhcp4_set_client_identifier(Link *link) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int dhcp4_set_request_address(Link *link) {
|
||||
static int dhcp4_find_dynamic_address(Link *link, struct in_addr *ret) {
|
||||
Address *a;
|
||||
|
||||
assert(link);
|
||||
assert(link->network);
|
||||
assert(link->dhcp_client);
|
||||
assert(ret);
|
||||
|
||||
if (!FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
SET_FOREACH(a, link->addresses) {
|
||||
if (a->source != NETWORK_CONFIG_SOURCE_FOREIGN)
|
||||
|
@ -1403,11 +1403,29 @@ static int dhcp4_set_request_address(Link *link) {
|
|||
}
|
||||
|
||||
if (!a)
|
||||
return false;
|
||||
|
||||
*ret = a->in_addr.in;
|
||||
return true;
|
||||
}
|
||||
|
||||
static int dhcp4_set_request_address(Link *link) {
|
||||
struct in_addr a;
|
||||
|
||||
assert(link);
|
||||
assert(link->network);
|
||||
assert(link->dhcp_client);
|
||||
|
||||
a = link->network->dhcp_request_address;
|
||||
|
||||
if (in4_addr_is_null(&a))
|
||||
(void) dhcp4_find_dynamic_address(link, &a);
|
||||
|
||||
if (in4_addr_is_null(&a))
|
||||
return 0;
|
||||
|
||||
log_link_debug(link, "DHCPv4 CLIENT: requesting " IPV4_ADDRESS_FMT_STR, IPV4_ADDRESS_FMT_VAL(a->in_addr.in));
|
||||
|
||||
return sd_dhcp_client_set_request_address(link->dhcp_client, &a->in_addr.in);
|
||||
log_link_debug(link, "DHCPv4 CLIENT: requesting %s.", IN4_ADDR_TO_STRING(&a));
|
||||
return sd_dhcp_client_set_request_address(link->dhcp_client, &a);
|
||||
}
|
||||
|
||||
static bool link_needs_dhcp_broadcast(Link *link) {
|
||||
|
@ -1487,6 +1505,10 @@ static int dhcp4_configure(Link *link) {
|
|||
}
|
||||
|
||||
if (!link->network->dhcp_anonymize) {
|
||||
r = dhcp4_set_request_address(link);
|
||||
if (r < 0)
|
||||
return log_link_debug_errno(link, r, "DHCPv4 CLIENT: Failed to set initial DHCPv4 address: %m");
|
||||
|
||||
if (link->network->dhcp_use_mtu) {
|
||||
r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_MTU_INTERFACE);
|
||||
if (r < 0)
|
||||
|
@ -1616,10 +1638,6 @@ static int dhcp4_configure(Link *link) {
|
|||
return log_link_debug_errno(link, r, "DHCPv4 CLIENT: Failed set to lease lifetime: %m");
|
||||
}
|
||||
|
||||
r = dhcp4_set_request_address(link);
|
||||
if (r < 0)
|
||||
return log_link_debug_errno(link, r, "DHCPv4 CLIENT: Failed to set initial DHCPv4 address: %m");
|
||||
|
||||
return dhcp4_set_client_identifier(link);
|
||||
}
|
||||
|
||||
|
|
|
@ -214,6 +214,7 @@ NextHop.Family, config_parse_nexthop_family,
|
|||
NextHop.OnLink, config_parse_nexthop_onlink, 0, 0
|
||||
NextHop.Blackhole, config_parse_nexthop_blackhole, 0, 0
|
||||
NextHop.Group, config_parse_nexthop_group, 0, 0
|
||||
DHCPv4.RequestAddress, config_parse_in_addr_non_null, AF_INET, offsetof(Network, dhcp_request_address)
|
||||
DHCPv4.ClientIdentifier, config_parse_dhcp_client_identifier, 0, offsetof(Network, dhcp_client_identifier)
|
||||
DHCPv4.UseDNS, config_parse_dhcp_use_dns, AF_INET, 0
|
||||
DHCPv4.RoutesToDNS, config_parse_bool, 0, offsetof(Network, dhcp_routes_to_dns)
|
||||
|
|
|
@ -114,6 +114,7 @@ struct Network {
|
|||
|
||||
/* DHCP Client Support */
|
||||
AddressFamily dhcp;
|
||||
struct in_addr dhcp_request_address;
|
||||
DHCPClientIdentifier dhcp_client_identifier;
|
||||
DUID dhcp_duid;
|
||||
uint32_t dhcp_iaid;
|
||||
|
|
|
@ -8,6 +8,7 @@ IPv6AcceptRA=no
|
|||
Address=192.168.5.250/24
|
||||
|
||||
[DHCPv4]
|
||||
RequestAddress=192.168.5.110
|
||||
UseDomains=yes
|
||||
UseMTU=yes
|
||||
UseRoutes=yes
|
||||
|
|
|
@ -5204,6 +5204,16 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
|
|||
self.assertRegex(output, r'inet 192.168.5.11[0-9]/24 metric 24 brd 192.168.5.255 scope global secondary dynamic noprefixroute test-label')
|
||||
self.assertNotIn('2600::', output)
|
||||
|
||||
output = check_output('ip -4 --json address show dev veth99')
|
||||
for i in json.loads(output)[0]['addr_info']:
|
||||
if i['label'] == 'test-label':
|
||||
address1 = i['local']
|
||||
break
|
||||
else:
|
||||
self.assertFalse(True)
|
||||
|
||||
self.assertRegex(address1, r'^192.168.5.11[0-9]$')
|
||||
|
||||
print('## ip route show table main dev veth99')
|
||||
output = check_output('ip route show table main dev veth99')
|
||||
print(output)
|
||||
|
@ -5218,11 +5228,11 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
|
|||
print('## ip route show table 211 dev veth99')
|
||||
output = check_output('ip route show table 211 dev veth99')
|
||||
print(output)
|
||||
self.assertRegex(output, 'default via 192.168.5.1 proto dhcp src 192.168.5.11[0-9] metric 24')
|
||||
self.assertRegex(output, '192.168.5.0/24 proto dhcp scope link src 192.168.5.11[0-9] metric 24')
|
||||
self.assertRegex(output, '192.168.5.1 proto dhcp scope link src 192.168.5.11[0-9] metric 24')
|
||||
self.assertRegex(output, '192.168.5.6 proto dhcp scope link src 192.168.5.11[0-9] metric 24')
|
||||
self.assertRegex(output, '192.168.5.7 proto dhcp scope link src 192.168.5.11[0-9] metric 24')
|
||||
self.assertRegex(output, f'default via 192.168.5.1 proto dhcp src {address1} metric 24')
|
||||
self.assertRegex(output, f'192.168.5.0/24 proto dhcp scope link src {address1} metric 24')
|
||||
self.assertRegex(output, f'192.168.5.1 proto dhcp scope link src {address1} metric 24')
|
||||
self.assertRegex(output, f'192.168.5.6 proto dhcp scope link src {address1} metric 24')
|
||||
self.assertRegex(output, f'192.168.5.7 proto dhcp scope link src {address1} metric 24')
|
||||
self.assertIn('10.0.0.0/8 via 192.168.5.1 proto dhcp', output)
|
||||
|
||||
print('## link state file')
|
||||
|
@ -5261,7 +5271,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
|
|||
output = read_dnsmasq_log_file()
|
||||
print(output)
|
||||
self.assertIn('vendor class: FooBarVendorTest', output)
|
||||
self.assertIn('DHCPDISCOVER(veth-peer) 12:34:56:78:9a:bc', output)
|
||||
self.assertIn('DHCPDISCOVER(veth-peer) 192.168.5.110 12:34:56:78:9a:bc', output)
|
||||
self.assertIn('client provides name: test-hostname', output)
|
||||
self.assertIn('26:mtu', output)
|
||||
|
||||
|
@ -5275,7 +5285,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
|
|||
|
||||
# Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
|
||||
print('Wait for the DHCP lease to be expired')
|
||||
self.wait_address_dropped('veth99', r'inet 192.168.5.11[0-9]*/24', ipv='-4', timeout_sec=120)
|
||||
self.wait_address_dropped('veth99', f'inet {address1}/24', ipv='-4', timeout_sec=120)
|
||||
self.wait_address('veth99', r'inet 192.168.5.12[0-9]*/24', ipv='-4')
|
||||
|
||||
self.wait_online(['veth99:routable', 'veth-peer:routable'])
|
||||
|
@ -5285,10 +5295,20 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
|
|||
print(output)
|
||||
self.assertIn('mtu 1492', output)
|
||||
self.assertIn('inet 192.168.5.250/24 brd 192.168.5.255 scope global veth99', output)
|
||||
self.assertNotIn('192.168.5.11', output)
|
||||
self.assertNotIn(f'{address1}', output)
|
||||
self.assertRegex(output, r'inet 192.168.5.12[0-9]/24 metric 24 brd 192.168.5.255 scope global secondary dynamic noprefixroute test-label')
|
||||
self.assertNotIn('2600::', output)
|
||||
|
||||
output = check_output('ip -4 --json address show dev veth99')
|
||||
for i in json.loads(output)[0]['addr_info']:
|
||||
if i['label'] == 'test-label':
|
||||
address2 = i['local']
|
||||
break
|
||||
else:
|
||||
self.assertFalse(True)
|
||||
|
||||
self.assertRegex(address2, r'^192.168.5.12[0-9]$')
|
||||
|
||||
print('## ip route show table main dev veth99')
|
||||
output = check_output('ip route show table main dev veth99')
|
||||
print(output)
|
||||
|
@ -5303,12 +5323,12 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
|
|||
print('## ip route show table 211 dev veth99')
|
||||
output = check_output('ip route show table 211 dev veth99')
|
||||
print(output)
|
||||
self.assertRegex(output, 'default via 192.168.5.1 proto dhcp src 192.168.5.12[0-9] metric 24')
|
||||
self.assertRegex(output, '192.168.5.0/24 proto dhcp scope link src 192.168.5.12[0-9] metric 24')
|
||||
self.assertRegex(output, '192.168.5.1 proto dhcp scope link src 192.168.5.12[0-9] metric 24')
|
||||
self.assertRegex(output, f'default via 192.168.5.1 proto dhcp src {address2} metric 24')
|
||||
self.assertRegex(output, f'192.168.5.0/24 proto dhcp scope link src {address2} metric 24')
|
||||
self.assertRegex(output, f'192.168.5.1 proto dhcp scope link src {address2} metric 24')
|
||||
self.assertNotIn('192.168.5.6', output)
|
||||
self.assertRegex(output, '192.168.5.7 proto dhcp scope link src 192.168.5.12[0-9] metric 24')
|
||||
self.assertRegex(output, '192.168.5.8 proto dhcp scope link src 192.168.5.12[0-9] metric 24')
|
||||
self.assertRegex(output, f'192.168.5.7 proto dhcp scope link src {address2} metric 24')
|
||||
self.assertRegex(output, f'192.168.5.8 proto dhcp scope link src {address2} metric 24')
|
||||
self.assertIn('10.0.0.0/8 via 192.168.5.1 proto dhcp', output)
|
||||
|
||||
print('## link state file')
|
||||
|
@ -5347,7 +5367,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
|
|||
output = read_dnsmasq_log_file()
|
||||
print(output)
|
||||
self.assertIn('vendor class: FooBarVendorTest', output)
|
||||
self.assertIn('DHCPDISCOVER(veth-peer) 192.168.5.11', output)
|
||||
self.assertIn(f'DHCPDISCOVER(veth-peer) {address1} 12:34:56:78:9a:bc', output)
|
||||
self.assertIn('client provides name: test-hostname', output)
|
||||
self.assertIn('26:mtu', output)
|
||||
|
||||
|
@ -5387,7 +5407,7 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
|
|||
|
||||
state = get_dbus_dhcp4_client_state('veth99')
|
||||
print(f"State = {state}")
|
||||
self.assertEqual(state, 'selecting')
|
||||
self.assertEqual(state, 'rebooting')
|
||||
|
||||
start_dnsmasq('--dhcp-option=option:dns-server,192.168.5.6,192.168.5.7',
|
||||
'--dhcp-option=option:domain-search,example.com',
|
||||
|
|
Loading…
Reference in a new issue