mirror of https://github.com/ipxe/ipxe.git
[pxe] Construct all fake DHCP packets before starting PXE NBP
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>
pull/41/head
parent
c522c11c7b
commit
2ef04f092c
|
@ -78,6 +78,9 @@ static int pxe_exec ( struct image *image ) {
|
||||||
/* Activate PXE */
|
/* Activate PXE */
|
||||||
pxe_activate ( netdev );
|
pxe_activate ( netdev );
|
||||||
|
|
||||||
|
/* Construct fake DHCP packets */
|
||||||
|
pxe_fake_cached_info();
|
||||||
|
|
||||||
/* Set PXE command line */
|
/* Set PXE command line */
|
||||||
pxe_cmdline = image->cmdline;
|
pxe_cmdline = image->cmdline;
|
||||||
|
|
||||||
|
|
|
@ -192,6 +192,7 @@ extern struct net_device *pxe_netdev;
|
||||||
extern const char *pxe_cmdline;
|
extern const char *pxe_cmdline;
|
||||||
|
|
||||||
extern void pxe_set_netdev ( struct net_device *netdev );
|
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
|
extern PXENV_EXIT_t pxenv_tftp_read_file ( struct s_PXENV_TFTP_READ_FILE
|
||||||
*tftp_read_file );
|
*tftp_read_file );
|
||||||
extern PXENV_EXIT_t undi_loader ( struct s_UNDI_LOADER *undi_loader );
|
extern PXENV_EXIT_t undi_loader ( struct s_UNDI_LOADER *undi_loader );
|
||||||
|
|
|
@ -128,6 +128,38 @@ pxenv_get_cached_info_name ( int packet_type ) {
|
||||||
static union pxe_cached_info __bss16_array ( cached_info, [NUM_CACHED_INFOS] );
|
static union pxe_cached_info __bss16_array ( cached_info, [NUM_CACHED_INFOS] );
|
||||||
#define cached_info __use_data16 ( cached_info )
|
#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
|
* UNLOAD BASE CODE STACK
|
||||||
*
|
*
|
||||||
|
@ -149,44 +181,26 @@ pxenv_unload_stack ( struct s_PXENV_UNLOAD_STACK *unload_stack ) {
|
||||||
*/
|
*/
|
||||||
static PXENV_EXIT_t
|
static PXENV_EXIT_t
|
||||||
pxenv_get_cached_info ( struct s_PXENV_GET_CACHED_INFO *get_cached_info ) {
|
pxenv_get_cached_info ( struct s_PXENV_GET_CACHED_INFO *get_cached_info ) {
|
||||||
struct pxe_dhcp_packet_creator *creator;
|
|
||||||
union pxe_cached_info *info;
|
union pxe_cached_info *info;
|
||||||
unsigned int idx;
|
unsigned int idx;
|
||||||
size_t len;
|
size_t len;
|
||||||
userptr_t buffer;
|
userptr_t buffer;
|
||||||
int rc;
|
|
||||||
|
|
||||||
DBGC ( &pxe_netdev, "PXENV_GET_CACHED_INFO %s to %04x:%04x+%x",
|
DBGC ( &pxe_netdev, "PXENV_GET_CACHED_INFO %s to %04x:%04x+%x",
|
||||||
pxenv_get_cached_info_name ( get_cached_info->PacketType ),
|
pxenv_get_cached_info_name ( get_cached_info->PacketType ),
|
||||||
get_cached_info->Buffer.segment,
|
get_cached_info->Buffer.segment,
|
||||||
get_cached_info->Buffer.offset, get_cached_info->BufferSize );
|
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 */
|
/* Sanity check */
|
||||||
idx = ( get_cached_info->PacketType - 1 );
|
idx = ( get_cached_info->PacketType - 1 );
|
||||||
if ( idx >= NUM_CACHED_INFOS ) {
|
if ( idx >= NUM_CACHED_INFOS ) {
|
||||||
DBGC ( &pxe_netdev, " bad PacketType %d\n",
|
DBGC ( &pxe_netdev, " bad PacketType %d\n",
|
||||||
get_cached_info->PacketType );
|
get_cached_info->PacketType );
|
||||||
goto err;
|
get_cached_info->Status = PXENV_STATUS_UNSUPPORTED;
|
||||||
|
return PXENV_EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
info = &cached_info[idx];
|
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) */
|
/* Copy packet (if applicable) */
|
||||||
len = get_cached_info->BufferSize;
|
len = get_cached_info->BufferSize;
|
||||||
if ( len == 0 ) {
|
if ( len == 0 ) {
|
||||||
|
@ -238,10 +252,6 @@ pxenv_get_cached_info ( struct s_PXENV_GET_CACHED_INFO *get_cached_info ) {
|
||||||
DBGC ( &pxe_netdev, "\n" );
|
DBGC ( &pxe_netdev, "\n" );
|
||||||
get_cached_info->Status = PXENV_STATUS_SUCCESS;
|
get_cached_info->Status = PXENV_STATUS_SUCCESS;
|
||||||
return PXENV_EXIT_SUCCESS;
|
return PXENV_EXIT_SUCCESS;
|
||||||
|
|
||||||
err:
|
|
||||||
get_cached_info->Status = PXENV_STATUS_OUT_OF_RESOURCES;
|
|
||||||
return PXENV_EXIT_FAILURE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PXENV_RESTART_TFTP
|
/* PXENV_RESTART_TFTP
|
||||||
|
|
Loading…
Reference in New Issue