Skip to content

Commit 2ef04f0

Browse files
committed
[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>
1 parent c522c11 commit 2ef04f0

File tree

3 files changed

+38
-24
lines changed

3 files changed

+38
-24
lines changed

src/arch/i386/image/pxe_image.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ static int pxe_exec ( struct image *image ) {
7878
/* Activate PXE */
7979
pxe_activate ( netdev );
8080

81+
/* Construct fake DHCP packets */
82+
pxe_fake_cached_info();
83+
8184
/* Set PXE command line */
8285
pxe_cmdline = image->cmdline;
8386

src/arch/i386/include/pxe.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ extern struct net_device *pxe_netdev;
192192
extern const char *pxe_cmdline;
193193

194194
extern void pxe_set_netdev ( struct net_device *netdev );
195+
extern void pxe_fake_cached_info ( void );
195196
extern PXENV_EXIT_t pxenv_tftp_read_file ( struct s_PXENV_TFTP_READ_FILE
196197
*tftp_read_file );
197198
extern PXENV_EXIT_t undi_loader ( struct s_UNDI_LOADER *undi_loader );

src/arch/i386/interface/pxe/pxe_preboot.c

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,38 @@ pxenv_get_cached_info_name ( int packet_type ) {
128128
static union pxe_cached_info __bss16_array ( cached_info, [NUM_CACHED_INFOS] );
129129
#define cached_info __use_data16 ( cached_info )
130130

131+
/**
132+
* Construct cached DHCP packets
133+
*
134+
*/
135+
void pxe_fake_cached_info ( void ) {
136+
struct pxe_dhcp_packet_creator *creator;
137+
union pxe_cached_info *info;
138+
unsigned int i;
139+
int rc;
140+
141+
/* Sanity check */
142+
assert ( pxe_netdev != NULL );
143+
144+
/* Erase any stale packets */
145+
memset ( cached_info, 0, sizeof ( cached_info ) );
146+
147+
/* Construct all DHCP packets */
148+
for ( i = 0 ; i < ( sizeof ( pxe_dhcp_packet_creators ) /
149+
sizeof ( pxe_dhcp_packet_creators[0] ) ) ; i++ ) {
150+
151+
/* Construct DHCP packet */
152+
creator = &pxe_dhcp_packet_creators[i];
153+
info = &cached_info[i];
154+
if ( ( rc = creator->create ( pxe_netdev, info,
155+
sizeof ( *info ) ) ) != 0 ) {
156+
DBGC ( &pxe_netdev, " failed to build packet: %s\n",
157+
strerror ( rc ) );
158+
/* Continue constructing remaining packets */
159+
}
160+
}
161+
}
162+
131163
/**
132164
* UNLOAD BASE CODE STACK
133165
*
@@ -149,44 +181,26 @@ pxenv_unload_stack ( struct s_PXENV_UNLOAD_STACK *unload_stack ) {
149181
*/
150182
static PXENV_EXIT_t
151183
pxenv_get_cached_info ( struct s_PXENV_GET_CACHED_INFO *get_cached_info ) {
152-
struct pxe_dhcp_packet_creator *creator;
153184
union pxe_cached_info *info;
154185
unsigned int idx;
155186
size_t len;
156187
userptr_t buffer;
157-
int rc;
158188

159189
DBGC ( &pxe_netdev, "PXENV_GET_CACHED_INFO %s to %04x:%04x+%x",
160190
pxenv_get_cached_info_name ( get_cached_info->PacketType ),
161191
get_cached_info->Buffer.segment,
162192
get_cached_info->Buffer.offset, get_cached_info->BufferSize );
163193

164-
/* Sanity check */
165-
if ( ! pxe_netdev ) {
166-
DBGC ( &pxe_netdev, "PXENV_GET_CACHED_INFO called with no "
167-
"network device\n" );
168-
get_cached_info->Status = PXENV_STATUS_UNDI_INVALID_STATE;
169-
return PXENV_EXIT_FAILURE;
170-
}
171-
172194
/* Sanity check */
173195
idx = ( get_cached_info->PacketType - 1 );
174196
if ( idx >= NUM_CACHED_INFOS ) {
175197
DBGC ( &pxe_netdev, " bad PacketType %d\n",
176198
get_cached_info->PacketType );
177-
goto err;
199+
get_cached_info->Status = PXENV_STATUS_UNSUPPORTED;
200+
return PXENV_EXIT_FAILURE;
178201
}
179202
info = &cached_info[idx];
180203

181-
/* Construct DHCP packet */
182-
creator = &pxe_dhcp_packet_creators[idx];
183-
if ( ( rc = creator->create ( pxe_netdev, info,
184-
sizeof ( *info ) ) ) != 0 ) {
185-
DBGC ( &pxe_netdev, " failed to build packet: %s\n",
186-
strerror ( rc ) );
187-
goto err;
188-
}
189-
190204
/* Copy packet (if applicable) */
191205
len = get_cached_info->BufferSize;
192206
if ( len == 0 ) {
@@ -238,10 +252,6 @@ pxenv_get_cached_info ( struct s_PXENV_GET_CACHED_INFO *get_cached_info ) {
238252
DBGC ( &pxe_netdev, "\n" );
239253
get_cached_info->Status = PXENV_STATUS_SUCCESS;
240254
return PXENV_EXIT_SUCCESS;
241-
242-
err:
243-
get_cached_info->Status = PXENV_STATUS_OUT_OF_RESOURCES;
244-
return PXENV_EXIT_FAILURE;
245255
}
246256

247257
/* PXENV_RESTART_TFTP

0 commit comments

Comments
 (0)