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)
}
if (!a)
- return 0;
+ 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);
- log_link_debug(link, "DHCPv4 CLIENT: requesting " IPV4_ADDRESS_FMT_STR, IPV4_ADDRESS_FMT_VAL(a->in_addr.in));
+ if (in4_addr_is_null(&a))
+ return 0;
- 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) {
}
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)
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);
}
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)
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')
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)
# 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'])
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)
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')
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)
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',