]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[pxe] Construct all fake DHCP packets before starting PXE NBP
authorMichael Brown <mcb30@ipxe.org>
Sat, 29 Aug 2015 15:49:54 +0000 (16:49 +0100)
committerMichael Brown <mcb30@ipxe.org>
Sat, 29 Aug 2015 15:58:12 +0000 (16:58 +0100)
Commit edf74df ("[pxe] Always reconstruct packet for
PXENV_GET_CACHED_INFO") fixed the problems caused by returning stale
DHCP packets (e.g. from an earlier boot attempt using a different
network device), but broke interoperability with NBPs such as WDS
which may overwrite our cached (fake) DHCP packets and expect the
modified packets to be returned by a subsequent call to
PXENV_GET_CACHED_INFO.

Fix by constructing the fake DHCP packets immediately before
transferring control to a PXE NBP.  Calls to PXENV_GET_CACHED_INFO
will now never modify the cached packets.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/arch/i386/image/pxe_image.c
src/arch/i386/include/pxe.h
src/arch/i386/interface/pxe/pxe_preboot.c

index 5b0f6eb89683734b2eecd010ac269abe2741318d..297a618b8b779fc7ee68b0228582d479ada2c7fa 100644 (file)
@@ -78,6 +78,9 @@ static int pxe_exec ( struct image *image ) {
        /* Activate PXE */
        pxe_activate ( netdev );
 
+       /* Construct fake DHCP packets */
+       pxe_fake_cached_info();
+
        /* Set PXE command line */
        pxe_cmdline = image->cmdline;
 
index 66d752683c33164020788505d2439562189b8ba2..54649b5049655b98075d17f4ca4705552593fe42 100644 (file)
@@ -192,6 +192,7 @@ extern struct net_device *pxe_netdev;
 extern const char *pxe_cmdline;
 
 extern void pxe_set_netdev ( struct net_device *netdev );
+extern void pxe_fake_cached_info ( void );
 extern PXENV_EXIT_t pxenv_tftp_read_file ( struct s_PXENV_TFTP_READ_FILE
                                           *tftp_read_file );
 extern PXENV_EXIT_t undi_loader ( struct s_UNDI_LOADER *undi_loader );
index 6e09080bc82600135b3e2db250991056e102cb46..cc9c052edf78c840add0ca6af532a817b4d39936 100644 (file)
@@ -128,6 +128,38 @@ pxenv_get_cached_info_name ( int packet_type ) {
 static union pxe_cached_info __bss16_array ( cached_info, [NUM_CACHED_INFOS] );
 #define cached_info __use_data16 ( cached_info )
 
+/**
+ * Construct cached DHCP packets
+ *
+ */
+void pxe_fake_cached_info ( void ) {
+       struct pxe_dhcp_packet_creator *creator;
+       union pxe_cached_info *info;
+       unsigned int i;
+       int rc;
+
+       /* Sanity check */
+       assert ( pxe_netdev != NULL );
+
+       /* Erase any stale packets */
+       memset ( cached_info, 0, sizeof ( cached_info ) );
+
+       /* Construct all DHCP packets */
+       for ( i = 0 ; i < ( sizeof ( pxe_dhcp_packet_creators ) /
+                           sizeof ( pxe_dhcp_packet_creators[0] ) ) ; i++ ) {
+
+               /* Construct DHCP packet */
+               creator = &pxe_dhcp_packet_creators[i];
+               info = &cached_info[i];
+               if ( ( rc = creator->create ( pxe_netdev, info,
+                                             sizeof ( *info ) ) ) != 0 ) {
+                       DBGC ( &pxe_netdev, " failed to build packet: %s\n",
+                              strerror ( rc ) );
+                       /* Continue constructing remaining packets */
+               }
+       }
+}
+
 /**
  * UNLOAD BASE CODE STACK
  *
@@ -149,44 +181,26 @@ pxenv_unload_stack ( struct s_PXENV_UNLOAD_STACK *unload_stack ) {
  */
 static PXENV_EXIT_t
 pxenv_get_cached_info ( struct s_PXENV_GET_CACHED_INFO *get_cached_info ) {
-       struct pxe_dhcp_packet_creator *creator;
        union pxe_cached_info *info;
        unsigned int idx;
        size_t len;
        userptr_t buffer;
-       int rc;
 
        DBGC ( &pxe_netdev, "PXENV_GET_CACHED_INFO %s to %04x:%04x+%x",
               pxenv_get_cached_info_name ( get_cached_info->PacketType ),
               get_cached_info->Buffer.segment,
               get_cached_info->Buffer.offset, get_cached_info->BufferSize );
 
-       /* Sanity check */
-       if ( ! pxe_netdev ) {
-               DBGC ( &pxe_netdev, "PXENV_GET_CACHED_INFO called with no "
-                      "network device\n" );
-               get_cached_info->Status = PXENV_STATUS_UNDI_INVALID_STATE;
-               return PXENV_EXIT_FAILURE;
-       }
-
        /* Sanity check */
         idx = ( get_cached_info->PacketType - 1 );
        if ( idx >= NUM_CACHED_INFOS ) {
                DBGC ( &pxe_netdev, " bad PacketType %d\n",
                       get_cached_info->PacketType );
-               goto err;
+               get_cached_info->Status = PXENV_STATUS_UNSUPPORTED;
+               return PXENV_EXIT_FAILURE;
        }
        info = &cached_info[idx];
 
-       /* Construct DHCP packet */
-       creator = &pxe_dhcp_packet_creators[idx];
-       if ( ( rc = creator->create ( pxe_netdev, info,
-                                     sizeof ( *info ) ) ) != 0 ) {
-               DBGC ( &pxe_netdev, " failed to build packet: %s\n",
-                      strerror ( rc ) );
-               goto err;
-       }
-
        /* Copy packet (if applicable) */
        len = get_cached_info->BufferSize;
        if ( len == 0 ) {
@@ -238,10 +252,6 @@ pxenv_get_cached_info ( struct s_PXENV_GET_CACHED_INFO *get_cached_info ) {
        DBGC ( &pxe_netdev, "\n" );
        get_cached_info->Status = PXENV_STATUS_SUCCESS;
        return PXENV_EXIT_SUCCESS;
-
- err:
-       get_cached_info->Status = PXENV_STATUS_OUT_OF_RESOURCES;
-       return PXENV_EXIT_FAILURE;
 }
 
 /* PXENV_RESTART_TFTP