aboutsummaryrefslogtreecommitdiff
path: root/src/core/cachedhcp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/cachedhcp.c')
-rw-r--r--src/core/cachedhcp.c51
1 files changed, 42 insertions, 9 deletions
diff --git a/src/core/cachedhcp.c b/src/core/cachedhcp.c
index 2fa9b0c..c4ca46e 100644
--- a/src/core/cachedhcp.c
+++ b/src/core/cachedhcp.c
@@ -90,29 +90,62 @@ static void cachedhcp_free ( struct cached_dhcp_packet *cache ) {
*/
static int cachedhcp_apply ( struct cached_dhcp_packet *cache,
struct net_device *netdev ) {
- struct settings *settings;
+ struct settings *settings = NULL;
+ struct ll_protocol *ll_protocol;
+ const uint8_t *chaddr;
+ uint8_t *hw_addr;
+ uint8_t *ll_addr;
+ size_t ll_addr_len;
int rc;
/* Do nothing if cache is empty */
if ( ! cache->dhcppkt )
return 0;
+ chaddr = cache->dhcppkt->dhcphdr->chaddr;
- /* Do nothing unless cached packet's MAC address matches this
- * network device, if specified.
- */
+ /* Handle association with network device, if specified */
if ( netdev ) {
- if ( memcmp ( netdev->ll_addr, cache->dhcppkt->dhcphdr->chaddr,
- netdev->ll_protocol->ll_addr_len ) != 0 ) {
+ hw_addr = netdev->hw_addr;
+ ll_addr = netdev->ll_addr;
+ ll_protocol = netdev->ll_protocol;
+ ll_addr_len = ll_protocol->ll_addr_len;
+
+ /* If cached packet's MAC address matches the network
+ * device's permanent MAC address, then assume that
+ * the permanent MAC address ought to be the network
+ * device's current link-layer address.
+ *
+ * This situation can arise when the PXE ROM does not
+ * understand the system-specific mechanism for
+ * overriding the MAC address, and so uses the
+ * permanent MAC address instead. We choose to match
+ * this behaviour in order to minimise surprise.
+ */
+ if ( memcmp ( hw_addr, chaddr, ll_addr_len ) == 0 ) {
+ if ( memcmp ( hw_addr, ll_addr, ll_addr_len ) != 0 ) {
+ DBGC ( colour, "CACHEDHCP %s resetting %s MAC "
+ "%s ", cache->name, netdev->name,
+ ll_protocol->ntoa ( ll_addr ) );
+ DBGC ( colour, "-> %s\n",
+ ll_protocol->ntoa ( hw_addr ) );
+ }
+ memcpy ( ll_addr, hw_addr, ll_addr_len );
+ }
+
+ /* Do nothing unless cached packet's MAC address
+ * 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 );
return 0;
}
DBGC ( colour, "CACHEDHCP %s is for %s\n",
cache->name, netdev->name );
- }
- /* Select appropriate parent settings block */
- settings = ( netdev ? netdev_settings ( netdev ) : NULL );
+ /* Use network device's settings block */
+ settings = netdev_settings ( netdev );
+ }
/* Register settings */
if ( ( rc = register_settings ( &cache->dhcppkt->settings, settings,