From 5cc70846fd466c5b71e2b6a3bc2792a94ee7c8b8 Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Wed, 30 Apr 2025 15:50:37 -0400 Subject: [PATCH] Fix asymmetric ipv4/ipv6 attribute PXE response If a nic were aliased *and* the node had attributes for ipv6 but used host resolution for ipv4 identity, it was possible for PXE to pick the wrong way to respond. Instruct netutil to specifically consider only the matching family for the PXE/HTTP boot context --- confluent_server/confluent/discovery/protocols/pxe.py | 7 +++++-- confluent_server/confluent/netutil.py | 6 ++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/confluent_server/confluent/discovery/protocols/pxe.py b/confluent_server/confluent/discovery/protocols/pxe.py index 853e0b8d..11922793 100644 --- a/confluent_server/confluent/discovery/protocols/pxe.py +++ b/confluent_server/confluent/discovery/protocols/pxe.py @@ -673,7 +673,7 @@ def reply_dhcp6(node, addr, cfg, packet, cfd, profile, sock): if not myaddrs: log.log({'info': 'Unable to provide IPv6 boot services to {0}, no viable IPv6 configuration on interface index "{1}" to respond through.'.format(node, addr[-1])}) return - niccfg = netutil.get_nic_config(cfg, node, ifidx=addr[-1]) + niccfg = netutil.get_nic_config(cfg, node, ifidx=addr[-1], onlyfamily=socket.AF_INET6) ipv6addr = niccfg.get('ipv6_address', None) ipv6prefix = niccfg.get('ipv6_prefix', None) ipv6method = niccfg.get('ipv6_method', 'static') @@ -798,7 +798,7 @@ def reply_dhcp4(node, info, packet, cfg, reqview, httpboot, cfd, profile, sock=N relayipa = socket.inet_ntoa(relayip) gateway = None netmask = None - niccfg = netutil.get_nic_config(cfg, node, ifidx=info['netinfo']['ifidx'], relayipn=relayip) + niccfg = netutil.get_nic_config(cfg, node, ifidx=info['netinfo']['ifidx'], relayipn=relayip, onlyfamily=socket.AF_INET) nicerr = niccfg.get('error_msg', False) if nicerr: log.log({'error': nicerr}) @@ -827,6 +827,9 @@ def reply_dhcp4(node, info, packet, cfg, reqview, httpboot, cfd, profile, sock=N myipn = niccfg['deploy_server'] if not myipn: myipn = info['netinfo']['recvip'] + if niccfg['ipv4_address'] == myipn: + log.log({'error': 'Unable to serve {0} due to duplicated address between node and interface index "{}"'.format(node, info['netinfo']['ifidx'])}) + return if httpboot: proto = 'https' if insecuremode == 'never' else 'http' bootfile = '{0}://{1}/confluent-public/os/{2}/boot.img'.format( diff --git a/confluent_server/confluent/netutil.py b/confluent_server/confluent/netutil.py index 92cc0bfa..dbd0859d 100644 --- a/confluent_server/confluent/netutil.py +++ b/confluent_server/confluent/netutil.py @@ -429,7 +429,7 @@ def noneify(cfgdata): # if switch and port available, that should match. def get_nic_config(configmanager, node, ip=None, mac=None, ifidx=None, serverip=None, relayipn=b'\x00\x00\x00\x00', - clientip=None): + clientip=None, onlyfamily=None): """Fetch network configuration parameters for a nic For a given node and interface, find and retrieve the pertinent network @@ -508,9 +508,11 @@ def get_nic_config(configmanager, node, ip=None, mac=None, ifidx=None, 'ipv6_method': None, } myaddrs = [] + if onlyfamily is None: + onlyfamily = 0 if ifidx is not None: dhcprequested = False - myaddrs = get_my_addresses(ifidx) + myaddrs = get_my_addresses(ifidx, family=onlyfamily) v4broken = True v6broken = True for addr in myaddrs: