Browse Source

[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>
tags/v1.20.1
Michael Brown 9 years ago
parent
commit
2ef04f092c

+ 3
- 0
src/arch/i386/image/pxe_image.c View File

78
 	/* Activate PXE */
78
 	/* Activate PXE */
79
 	pxe_activate ( netdev );
79
 	pxe_activate ( netdev );
80
 
80
 
81
+	/* Construct fake DHCP packets */
82
+	pxe_fake_cached_info();
83
+
81
 	/* Set PXE command line */
84
 	/* Set PXE command line */
82
 	pxe_cmdline = image->cmdline;
85
 	pxe_cmdline = image->cmdline;
83
 
86
 

+ 1
- 0
src/arch/i386/include/pxe.h View File

192
 extern const char *pxe_cmdline;
192
 extern const char *pxe_cmdline;
193
 
193
 
194
 extern void pxe_set_netdev ( struct net_device *netdev );
194
 extern void pxe_set_netdev ( struct net_device *netdev );
195
+extern void pxe_fake_cached_info ( void );
195
 extern PXENV_EXIT_t pxenv_tftp_read_file ( struct s_PXENV_TFTP_READ_FILE
196
 extern PXENV_EXIT_t pxenv_tftp_read_file ( struct s_PXENV_TFTP_READ_FILE
196
 					   *tftp_read_file );
197
 					   *tftp_read_file );
197
 extern PXENV_EXIT_t undi_loader ( struct s_UNDI_LOADER *undi_loader );
198
 extern PXENV_EXIT_t undi_loader ( struct s_UNDI_LOADER *undi_loader );

+ 34
- 24
src/arch/i386/interface/pxe/pxe_preboot.c View File

128
 static union pxe_cached_info __bss16_array ( cached_info, [NUM_CACHED_INFOS] );
128
 static union pxe_cached_info __bss16_array ( cached_info, [NUM_CACHED_INFOS] );
129
 #define cached_info __use_data16 ( cached_info )
129
 #define cached_info __use_data16 ( cached_info )
130
 
130
 
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
+
131
 /**
163
 /**
132
  * UNLOAD BASE CODE STACK
164
  * UNLOAD BASE CODE STACK
133
  *
165
  *
149
  */
181
  */
150
 static PXENV_EXIT_t
182
 static PXENV_EXIT_t
151
 pxenv_get_cached_info ( struct s_PXENV_GET_CACHED_INFO *get_cached_info ) {
183
 pxenv_get_cached_info ( struct s_PXENV_GET_CACHED_INFO *get_cached_info ) {
152
-	struct pxe_dhcp_packet_creator *creator;
153
 	union pxe_cached_info *info;
184
 	union pxe_cached_info *info;
154
 	unsigned int idx;
185
 	unsigned int idx;
155
 	size_t len;
186
 	size_t len;
156
 	userptr_t buffer;
187
 	userptr_t buffer;
157
-	int rc;
158
 
188
 
159
 	DBGC ( &pxe_netdev, "PXENV_GET_CACHED_INFO %s to %04x:%04x+%x",
189
 	DBGC ( &pxe_netdev, "PXENV_GET_CACHED_INFO %s to %04x:%04x+%x",
160
 	       pxenv_get_cached_info_name ( get_cached_info->PacketType ),
190
 	       pxenv_get_cached_info_name ( get_cached_info->PacketType ),
161
 	       get_cached_info->Buffer.segment,
191
 	       get_cached_info->Buffer.segment,
162
 	       get_cached_info->Buffer.offset, get_cached_info->BufferSize );
192
 	       get_cached_info->Buffer.offset, get_cached_info->BufferSize );
163
 
193
 
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
-
172
 	/* Sanity check */
194
 	/* Sanity check */
173
         idx = ( get_cached_info->PacketType - 1 );
195
         idx = ( get_cached_info->PacketType - 1 );
174
 	if ( idx >= NUM_CACHED_INFOS ) {
196
 	if ( idx >= NUM_CACHED_INFOS ) {
175
 		DBGC ( &pxe_netdev, " bad PacketType %d\n",
197
 		DBGC ( &pxe_netdev, " bad PacketType %d\n",
176
 		       get_cached_info->PacketType );
198
 		       get_cached_info->PacketType );
177
-		goto err;
199
+		get_cached_info->Status = PXENV_STATUS_UNSUPPORTED;
200
+		return PXENV_EXIT_FAILURE;
178
 	}
201
 	}
179
 	info = &cached_info[idx];
202
 	info = &cached_info[idx];
180
 
203
 
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
-
190
 	/* Copy packet (if applicable) */
204
 	/* Copy packet (if applicable) */
191
 	len = get_cached_info->BufferSize;
205
 	len = get_cached_info->BufferSize;
192
 	if ( len == 0 ) {
206
 	if ( len == 0 ) {
238
 	DBGC ( &pxe_netdev, "\n" );
252
 	DBGC ( &pxe_netdev, "\n" );
239
 	get_cached_info->Status = PXENV_STATUS_SUCCESS;
253
 	get_cached_info->Status = PXENV_STATUS_SUCCESS;
240
 	return PXENV_EXIT_SUCCESS;
254
 	return PXENV_EXIT_SUCCESS;
241
-
242
- err:
243
-	get_cached_info->Status = PXENV_STATUS_OUT_OF_RESOURCES;
244
-	return PXENV_EXIT_FAILURE;
245
 }
255
 }
246
 
256
 
247
 /* PXENV_RESTART_TFTP
257
 /* PXENV_RESTART_TFTP

Loading…
Cancel
Save