]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[dhcp] Request broadcast responses when we already have an IPv4 address
authorMichael Brown <mcb30@ipxe.org>
Wed, 20 Jun 2012 10:56:43 +0000 (11:56 +0100)
committerMichael Brown <mcb30@ipxe.org>
Wed, 20 Jun 2012 11:01:50 +0000 (12:01 +0100)
FCoE requires the use of multiple local unicast link-layer addresses.
To avoid the complexity of managing multiple addresses, iPXE operates
in promiscuous mode.  As a consequence, any unicast packets with
non-matching IPv4 addresses are rejected at the IPv4 layer (rather
than at the link layer).

This can cause problems when issuing a second DHCP request: if the
address chosen by the DHCP server does not match the existing address,
then the DHCP response will itself be rejected.

Fix by requesting a broadcast response from the DHCP server if the
network interface already has any IPv4 addresses.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/include/ipxe/ip.h
src/net/ipv4.c
src/net/udp/dhcp.c

index 4366d9ab388bf4efd50320e0c9a0aa1e17f1d709..ca508e274b207c46a8f68ddbda3b2695251e00df 100644 (file)
@@ -86,4 +86,6 @@ extern struct list_head ipv4_miniroutes;
 
 extern struct net_protocol ipv4_protocol __net_protocol;
 
+extern int ipv4_has_any_addr ( struct net_device *netdev );
+
 #endif /* _IPXE_IP_H */
index 08249d41fa5a66733cf2de119a75d7113a669536..791d419514440152a6182c4ca9288fa0445580c0 100644 (file)
@@ -408,7 +408,7 @@ static int ipv4_tx ( struct io_buffer *iobuf,
  * @v netdev           Network device
  * @ret has_any_addr   Network device has any IPv4 address
  */
-static int ipv4_has_any_addr ( struct net_device *netdev ) {
+int ipv4_has_any_addr ( struct net_device *netdev ) {
        struct ipv4_miniroute *miniroute;
 
        list_for_each_entry ( miniroute, &ipv4_miniroutes, list ) {
index 10482e94ddc515bf1dc838981922164c5dd4931f..9a231840dc3e16cec24ac0adf683c3def95cff41 100644 (file)
@@ -941,6 +941,13 @@ int dhcp_create_packet ( struct dhcp_packet *dhcppkt,
                                      &dhcphdr->flags );
        memcpy ( dhcphdr->options, options, options_len );
 
+       /* If the network device already has an IPv4 address then
+        * unicast responses from the DHCP server may be rejected, so
+        * request broadcast responses.
+        */
+       if ( ipv4_has_any_addr ( netdev ) )
+               dhcphdr->flags |= htons ( BOOTP_FL_BROADCAST );
+
        /* Initialise DHCP packet structure */
        memset ( dhcppkt, 0, sizeof ( *dhcppkt ) );
        dhcppkt_init ( dhcppkt, data, max_len );