From 60b5532cfc1393a8d34cece1b49f953bd72c303c Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 22 Dec 2022 14:59:29 +0000 Subject: [cachedhcp] Include VLAN tag in filter for applying cached DHCPACK When chainloading iPXE from a VLAN device, the MAC address within the cached DHCPACK will match the MAC address of the trunk device created by iPXE, and the cached DHCPACK will then end up being erroneously applied to the trunk device. This tends to break outbound IPv4 routing, since both the trunk and VLAN devices will have the same assigned IPv4 address. Fix by recording the VLAN tag along with the cached DHCPACK, and treating the VLAN tag as part of the filter used to match the cached DHCPACK against candidate network devices. Signed-off-by: Michael Brown --- src/core/cachedhcp.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) (limited to 'src/core') diff --git a/src/core/cachedhcp.c b/src/core/cachedhcp.c index c4ca46e3a..ef2146626 100644 --- a/src/core/cachedhcp.c +++ b/src/core/cachedhcp.c @@ -29,6 +29,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include #include +#include #include /** @file @@ -43,6 +44,8 @@ struct cached_dhcp_packet { const char *name; /** DHCP packet (if any) */ struct dhcp_packet *dhcppkt; + /** VLAN tag (if applicable) */ + unsigned int vlan; }; /** Cached DHCPACK */ @@ -136,15 +139,26 @@ static int cachedhcp_apply ( struct cached_dhcp_packet *cache, * matches this network device. */ if ( memcmp ( ll_addr, chaddr, ll_addr_len ) != 0 ) { - DBGC ( colour, "CACHEDHCP %s does not match %s\n", - cache->name, netdev->name ); + DBGC ( colour, "CACHEDHCP %s %s does not match %s\n", + cache->name, ll_protocol->ntoa ( chaddr ), + netdev->name ); + return 0; + } + + /* Do nothing unless cached packet's VLAN tag matches + * this network device. + */ + if ( vlan_tag ( netdev ) != cache->vlan ) { + DBGC ( colour, "CACHEDHCP %s VLAN %d does not match " + "%s\n", cache->name, cache->vlan, + netdev->name ); return 0; } - DBGC ( colour, "CACHEDHCP %s is for %s\n", - cache->name, netdev->name ); /* Use network device's settings block */ settings = netdev_settings ( netdev ); + DBGC ( colour, "CACHEDHCP %s is for %s\n", + cache->name, netdev->name ); } /* Register settings */ @@ -165,12 +179,13 @@ static int cachedhcp_apply ( struct cached_dhcp_packet *cache, * Record cached DHCP packet * * @v cache Cached DHCP packet + * @v vlan VLAN tag, if any * @v data DHCPACK packet buffer * @v max_len Maximum possible length * @ret rc Return status code */ -int cachedhcp_record ( struct cached_dhcp_packet *cache, userptr_t data, - size_t max_len ) { +int cachedhcp_record ( struct cached_dhcp_packet *cache, unsigned int vlan, + userptr_t data, size_t max_len ) { struct dhcp_packet *dhcppkt; struct dhcp_packet *tmp; struct dhcphdr *dhcphdr; @@ -225,6 +240,7 @@ int cachedhcp_record ( struct cached_dhcp_packet *cache, userptr_t data, DBGC ( colour, "CACHEDHCP %s at %#08lx+%#zx/%#zx\n", cache->name, user_to_phys ( data, 0 ), len, max_len ); cache->dhcppkt = dhcppkt; + cache->vlan = vlan; return 0; } -- cgit v1.2.3-55-g7522