Remove some assumptions about DHCP obtaining only a single options block.
authorMichael Brown <mcb30@etherboot.org>
Wed, 21 Nov 2007 04:48:18 +0000 (04:48 +0000)
committerMichael Brown <mcb30@etherboot.org>
Wed, 21 Nov 2007 04:48:18 +0000 (04:48 +0000)
src/include/gpxe/dhcp.h
src/net/dhcpopts.c
src/net/udp/dhcp.c
src/usr/dhcpmgmt.c

index b5923fd..60d2ccf 100644 (file)
@@ -512,6 +512,8 @@ dhcpopt_put ( struct dhcp_option_block *options ) {
        ref_put ( &options->refcnt );
 }
 
+extern struct list_head dhcp_option_blocks;
+
 extern unsigned long dhcp_num_option ( struct dhcp_option *option );
 extern void dhcp_ipv4_option ( struct dhcp_option *option,
                               struct in_addr *inp );
index c713909..d1837be 100644 (file)
@@ -35,7 +35,7 @@
  */
 
 /** List of registered DHCP option blocks */
-static LIST_HEAD ( option_blocks );
+LIST_HEAD ( dhcp_option_blocks );
 
 /** Registered DHCP option applicators */
 static struct dhcp_option_applicator dhcp_option_applicators[0]
@@ -259,7 +259,7 @@ struct dhcp_option * find_dhcp_option ( struct dhcp_option_block *options,
        if ( options ) {
                return find_dhcp_option_with_encap ( options, tag, NULL );
        } else {
-               list_for_each_entry ( options, &option_blocks, list ) {
+               list_for_each_entry ( options, &dhcp_option_blocks, list ) {
                        if ( ( option = find_dhcp_option ( options, tag ) ) )
                                return option;
                }
@@ -283,7 +283,7 @@ void register_dhcp_options ( struct dhcp_option_block *options ) {
              options, options->priority );
 
        /* Insert after any existing blocks which have a higher priority */
-       list_for_each_entry ( existing, &option_blocks, list ) {
+       list_for_each_entry ( existing, &dhcp_option_blocks, list ) {
                if ( options->priority > existing->priority )
                        break;
        }
index 7de05ac..3080445 100644 (file)
@@ -1006,14 +1006,18 @@ int dhcp_configure_netdev ( struct net_device *netdev,
        struct in_addr gateway = { INADDR_NONE };
        int rc;
 
-       /* Clear any existing routing table entry */
-       del_ipv4_address ( netdev );
-
        /* Retrieve IP address configuration */
        find_dhcp_ipv4_option ( options, DHCP_EB_YIADDR, &address );
        find_dhcp_ipv4_option ( options, DHCP_SUBNET_MASK, &netmask );
        find_dhcp_ipv4_option ( options, DHCP_ROUTERS, &gateway );
 
+       /* Do nothing unless we have at least an IP address to use */
+       if ( ! address.s_addr )
+               return 0;
+
+       /* Clear any existing routing table entry */
+       del_ipv4_address ( netdev );
+
        /* Set up new IP address configuration */
        if ( ( rc = add_ipv4_address ( netdev, address, netmask,
                                       gateway ) ) != 0 ) {
index bd05c5e..0c6b458 100644 (file)
  *
  */
 
-static struct dhcp_option_block *dhcp_options = NULL;
-
 static int dhcp_success ( struct net_device *netdev,
                          struct dhcp_option_block *options ) {
-       dhcp_options = dhcpopt_get ( options );
+       DBGC ( options, "DHCP client registering options %p\n", options );
        register_dhcp_options ( options );
        return dhcp_configure_netdev ( netdev, options );
 }
 
 int dhcp ( struct net_device *netdev ) {
+       struct dhcp_option_block *options;
+       struct dhcp_option_block *tmp;
        int rc;
 
        /* Check we can open the interface first */
        if ( ( rc = ifopen ( netdev ) ) != 0 )
                return rc;
 
-       /* Unregister any previously acquired options */
-       if ( dhcp_options ) {
-               unregister_dhcp_options ( dhcp_options );
-               dhcpopt_put ( dhcp_options );
-               dhcp_options = NULL;
+       /* Unregister any option blocks acquired via DHCP */
+       list_for_each_entry_safe ( options, tmp, &dhcp_option_blocks, list ) {
+               /* Skip static option blocks (e.g. from NVS) */
+               if ( find_dhcp_option ( options, DHCP_MESSAGE_TYPE ) ) {
+                       DBGC ( options, "DHCP client unregistering options "
+                              "%p\n", options );
+                       unregister_dhcp_options ( options );
+               }
        }
 
        /* Perform DHCP */