mirror of
https://github.com/systemd/systemd.git
synced 2026-11-06 05:17:24 +00:00
networkd: preserve exact host-prefix pool addresses
Address pool allocation checks a selected prefix before address_acquire() forces its lowest bit to one. For /32 and /128, this changes the checked address and can return an address that is already in use. Keep exact host-prefix addresses unchanged and only select the first host address when the prefix leaves host bits available. (cherry picked from commita0a493a038) (cherry picked from commit27e2f6b49d)
This commit is contained in:
1 parent
950525d9fa
commit
b79761ddc3
3 files changed
+23
-7
No files matched your search
@@ -1641,13 +1641,13 @@ static int address_acquire(Link *link, const Address *address, union in_addr_uni
|
||||
if (r == 0)
|
||||
return -EBUSY;
|
||||
|
||||
/* Pick first address in range for ourselves. */
|
||||
if (address->family == AF_INET)
|
||||
a.in.s_addr |= htobe32(1);
|
||||
else if (address->family == AF_INET6)
|
||||
a.in6.s6_addr[15] |= 1;
|
||||
else
|
||||
assert_not_reached();
|
||||
/* Pick first address in range for ourselves. A host prefix already identifies the exact address. */
|
||||
if (address->prefixlen < FAMILY_ADDRESS_SIZE(address->family) * 8) {
|
||||
if (address->family == AF_INET)
|
||||
a.in.s_addr |= htobe32(1);
|
||||
else
|
||||
a.in6.s6_addr[15] |= 1;
|
||||
}
|
||||
|
||||
*ret = a;
|
||||
return 0;
|
||||
|
||||
@@ -170,12 +170,19 @@ Label=subnet16
|
||||
Address=0.0.0.0/24
|
||||
Label=subnet24
|
||||
|
||||
[Address]
|
||||
Address=0.0.0.0/32
|
||||
Label=host32
|
||||
|
||||
[Address]
|
||||
Address=::/73
|
||||
|
||||
[Address]
|
||||
Address=::/74
|
||||
|
||||
[Address]
|
||||
Address=::/128
|
||||
|
||||
[Address]
|
||||
Address=10.10.1.1/24
|
||||
# just a random label which should exist
|
||||
|
||||
@@ -4191,25 +4191,34 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
|
||||
|
||||
ip4_null_16 = None
|
||||
ip4_null_24 = None
|
||||
ip4_null_32 = None
|
||||
output = check_output('ip -4 --json address show dev dummy98')
|
||||
for i in json.loads(output)[0]['addr_info']:
|
||||
if i['label'] == 'subnet16':
|
||||
ip4_null_16 = i['local']
|
||||
elif i['label'] == 'subnet24':
|
||||
ip4_null_24 = i['local']
|
||||
elif i['label'] == 'host32':
|
||||
ip4_null_32 = i
|
||||
self.assertTrue(ip4_null_16.endswith('.0.1'))
|
||||
self.assertTrue(ip4_null_24.endswith('.1'))
|
||||
self.assertIsNotNone(ip4_null_32)
|
||||
self.assertEqual(ip4_null_32['prefixlen'], 32)
|
||||
|
||||
ip6_null_73 = None
|
||||
ip6_null_74 = None
|
||||
ip6_null_128 = None
|
||||
output = check_output('ip -6 --json address show dev dummy98')
|
||||
for i in json.loads(output)[0]['addr_info']:
|
||||
if i['prefixlen'] == 73:
|
||||
ip6_null_73 = i['local']
|
||||
elif i['prefixlen'] == 74:
|
||||
ip6_null_74 = i['local']
|
||||
elif i['prefixlen'] == 128 and i['local'].startswith('fd'):
|
||||
ip6_null_128 = i
|
||||
self.assertTrue(ip6_null_73.endswith(':1'))
|
||||
self.assertTrue(ip6_null_74.endswith(':1'))
|
||||
self.assertIsNotNone(ip6_null_128)
|
||||
|
||||
self.verify_address_static(
|
||||
label1='label1',
|
||||
|
||||
Reference in new issue
Block a user