Browse Source

[pxe] Check for a valid PXE network device when applicable

Very nasty things can happen if a NULL network device is used.  Check
that pxe_netdev is non-NULL at the applicable entry points, so that
this type of problem gets reported to the caller rather than being
allowed to crash the system.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 13 years ago
parent
commit
faf50e8fa3
2 changed files with 213 additions and 11 deletions
  1. 8
    0
      src/arch/i386/interface/pxe/pxe_preboot.c
  2. 205
    11
      src/arch/i386/interface/pxe/pxe_undi.c

+ 8
- 0
src/arch/i386/interface/pxe/pxe_preboot.c View File

155
 	       get_cached_info->Buffer.segment,
155
 	       get_cached_info->Buffer.segment,
156
 	       get_cached_info->Buffer.offset, get_cached_info->BufferSize );
156
 	       get_cached_info->Buffer.offset, get_cached_info->BufferSize );
157
 
157
 
158
+	/* Sanity check */
159
+	if ( ! pxe_netdev ) {
160
+		DBGC ( &pxe_netdev, "PXENV_GET_CACHED_INFO called with no "
161
+		       "network device\n" );
162
+		get_cached_info->Status = PXENV_STATUS_UNDI_INVALID_STATE;
163
+		return PXENV_EXIT_FAILURE;
164
+	}
165
+
158
 	/* Sanity check */
166
 	/* Sanity check */
159
         idx = ( get_cached_info->PacketType - 1 );
167
         idx = ( get_cached_info->PacketType - 1 );
160
 	if ( idx >= NUM_CACHED_INFOS ) {
168
 	if ( idx >= NUM_CACHED_INFOS ) {

+ 205
- 11
src/arch/i386/interface/pxe/pxe_undi.c View File

58
  * @v netdev		Network device, or NULL
58
  * @v netdev		Network device, or NULL
59
  */
59
  */
60
 void pxe_set_netdev ( struct net_device *netdev ) {
60
 void pxe_set_netdev ( struct net_device *netdev ) {
61
+
61
 	if ( pxe_netdev ) {
62
 	if ( pxe_netdev ) {
62
 		netdev_rx_unfreeze ( pxe_netdev );
63
 		netdev_rx_unfreeze ( pxe_netdev );
63
 		netdev_put ( pxe_netdev );
64
 		netdev_put ( pxe_netdev );
64
 	}
65
 	}
66
+
65
 	pxe_netdev = NULL;
67
 	pxe_netdev = NULL;
68
+
66
 	if ( netdev )
69
 	if ( netdev )
67
 		pxe_netdev = netdev_get ( netdev );
70
 		pxe_netdev = netdev_get ( netdev );
68
 }
71
 }
75
 static int pxe_netdev_open ( void ) {
78
 static int pxe_netdev_open ( void ) {
76
 	int rc;
79
 	int rc;
77
 
80
 
81
+	assert ( pxe_netdev != NULL );
82
+
78
 	if ( ( rc = netdev_open ( pxe_netdev ) ) != 0 )
83
 	if ( ( rc = netdev_open ( pxe_netdev ) ) != 0 )
79
 		return rc;
84
 		return rc;
80
 
85
 
81
 	netdev_rx_freeze ( pxe_netdev );
86
 	netdev_rx_freeze ( pxe_netdev );
82
 	netdev_irq ( pxe_netdev, 1 );
87
 	netdev_irq ( pxe_netdev, 1 );
88
+
83
 	return 0;
89
 	return 0;
84
 }
90
 }
85
 
91
 
88
  *
94
  *
89
  */
95
  */
90
 static void pxe_netdev_close ( void ) {
96
 static void pxe_netdev_close ( void ) {
97
+
98
+	assert ( pxe_netdev != NULL );
91
 	netdev_rx_unfreeze ( pxe_netdev );
99
 	netdev_rx_unfreeze ( pxe_netdev );
92
 	netdev_irq ( pxe_netdev, 0 );
100
 	netdev_irq ( pxe_netdev, 0 );
93
 	netdev_close ( pxe_netdev );
101
 	netdev_close ( pxe_netdev );
116
 PXENV_EXIT_t pxenv_undi_startup ( struct s_PXENV_UNDI_STARTUP *undi_startup ) {
124
 PXENV_EXIT_t pxenv_undi_startup ( struct s_PXENV_UNDI_STARTUP *undi_startup ) {
117
 	DBGC ( &pxe_netdev, "PXENV_UNDI_STARTUP\n" );
125
 	DBGC ( &pxe_netdev, "PXENV_UNDI_STARTUP\n" );
118
 
126
 
127
+	/* Sanity check */
128
+	if ( ! pxe_netdev ) {
129
+		DBGC ( &pxe_netdev, "PXENV_UNDI_STARTUP called with no "
130
+		       "network device\n" );
131
+		undi_startup->Status = PXENV_STATUS_UNDI_INVALID_STATE;
132
+		return PXENV_EXIT_FAILURE;
133
+	}
134
+
119
 	undi_startup->Status = PXENV_STATUS_SUCCESS;
135
 	undi_startup->Status = PXENV_STATUS_SUCCESS;
120
 	return PXENV_EXIT_SUCCESS;
136
 	return PXENV_EXIT_SUCCESS;
121
 }
137
 }
127
 PXENV_EXIT_t pxenv_undi_cleanup ( struct s_PXENV_UNDI_CLEANUP *undi_cleanup ) {
143
 PXENV_EXIT_t pxenv_undi_cleanup ( struct s_PXENV_UNDI_CLEANUP *undi_cleanup ) {
128
 	DBGC ( &pxe_netdev, "PXENV_UNDI_CLEANUP\n" );
144
 	DBGC ( &pxe_netdev, "PXENV_UNDI_CLEANUP\n" );
129
 
145
 
146
+	/* Sanity check */
147
+	if ( ! pxe_netdev ) {
148
+		DBGC ( &pxe_netdev, "PXENV_UNDI_CLEANUP called with no "
149
+		       "network device\n" );
150
+		undi_cleanup->Status = PXENV_STATUS_UNDI_INVALID_STATE;
151
+		return PXENV_EXIT_FAILURE;
152
+	}
153
+
154
+	/* Close network device */
130
 	pxe_netdev_close();
155
 	pxe_netdev_close();
131
 
156
 
132
 	undi_cleanup->Status = PXENV_STATUS_SUCCESS;
157
 	undi_cleanup->Status = PXENV_STATUS_SUCCESS;
142
 	DBGC ( &pxe_netdev, "PXENV_UNDI_INITIALIZE protocolini %08x\n",
167
 	DBGC ( &pxe_netdev, "PXENV_UNDI_INITIALIZE protocolini %08x\n",
143
 	       undi_initialize->ProtocolIni );
168
 	       undi_initialize->ProtocolIni );
144
 
169
 
170
+	/* Sanity check */
171
+	if ( ! pxe_netdev ) {
172
+		DBGC ( &pxe_netdev, "PXENV_UNDI_INITIALIZE called with no "
173
+		       "network device\n" );
174
+		undi_initialize->Status = PXENV_STATUS_UNDI_INVALID_STATE;
175
+		return PXENV_EXIT_FAILURE;
176
+	}
177
+
145
 	undi_initialize->Status = PXENV_STATUS_SUCCESS;
178
 	undi_initialize->Status = PXENV_STATUS_SUCCESS;
146
 	return PXENV_EXIT_SUCCESS;
179
 	return PXENV_EXIT_SUCCESS;
147
 }
180
 }
158
 	pxe_dump_mcast_list ( &undi_reset_adapter->R_Mcast_Buf );
191
 	pxe_dump_mcast_list ( &undi_reset_adapter->R_Mcast_Buf );
159
 	DBGC ( &pxe_netdev, "\n" );
192
 	DBGC ( &pxe_netdev, "\n" );
160
 
193
 
194
+	/* Sanity check */
195
+	if ( ! pxe_netdev ) {
196
+		DBGC ( &pxe_netdev, "PXENV_UNDI_RESET_ADAPTER called with no "
197
+		       "network device\n" );
198
+		undi_reset_adapter->Status = PXENV_STATUS_UNDI_INVALID_STATE;
199
+		return PXENV_EXIT_FAILURE;
200
+	}
201
+
202
+	/* Close and reopen network device */
161
 	pxe_netdev_close();
203
 	pxe_netdev_close();
162
 	if ( ( rc = pxe_netdev_open() ) != 0 ) {
204
 	if ( ( rc = pxe_netdev_open() ) != 0 ) {
163
 		DBGC ( &pxe_netdev, "PXENV_UNDI_RESET_ADAPTER could not "
205
 		DBGC ( &pxe_netdev, "PXENV_UNDI_RESET_ADAPTER could not "
178
 				   *undi_shutdown ) {
220
 				   *undi_shutdown ) {
179
 	DBGC ( &pxe_netdev, "PXENV_UNDI_SHUTDOWN\n" );
221
 	DBGC ( &pxe_netdev, "PXENV_UNDI_SHUTDOWN\n" );
180
 
222
 
223
+	/* Sanity check */
224
+	if ( ! pxe_netdev ) {
225
+		DBGC ( &pxe_netdev, "PXENV_UNDI_SHUTDOWN called with no "
226
+		       "network device\n" );
227
+		undi_shutdown->Status = PXENV_STATUS_UNDI_INVALID_STATE;
228
+		return PXENV_EXIT_FAILURE;
229
+	}
230
+
231
+	/* Close network device */
181
 	pxe_netdev_close();
232
 	pxe_netdev_close();
182
 
233
 
183
 	undi_shutdown->Status = PXENV_STATUS_SUCCESS;
234
 	undi_shutdown->Status = PXENV_STATUS_SUCCESS;
196
 	pxe_dump_mcast_list ( &undi_open->R_Mcast_Buf );
247
 	pxe_dump_mcast_list ( &undi_open->R_Mcast_Buf );
197
 	DBGC ( &pxe_netdev, "\n" );
248
 	DBGC ( &pxe_netdev, "\n" );
198
 
249
 
250
+	/* Sanity check */
251
+	if ( ! pxe_netdev ) {
252
+		DBGC ( &pxe_netdev, "PXENV_UNDI_OPEN called with no "
253
+		       "network device\n" );
254
+		undi_open->Status = PXENV_STATUS_UNDI_INVALID_STATE;
255
+		return PXENV_EXIT_FAILURE;
256
+	}
257
+
258
+	/* Open network device */
199
 	if ( ( rc = pxe_netdev_open() ) != 0 ) {
259
 	if ( ( rc = pxe_netdev_open() ) != 0 ) {
200
 		DBGC ( &pxe_netdev, "PXENV_UNDI_OPEN could not open %s: %s\n",
260
 		DBGC ( &pxe_netdev, "PXENV_UNDI_OPEN could not open %s: %s\n",
201
 		       pxe_netdev->name, strerror ( rc ) );
261
 		       pxe_netdev->name, strerror ( rc ) );
214
 PXENV_EXIT_t pxenv_undi_close ( struct s_PXENV_UNDI_CLOSE *undi_close ) {
274
 PXENV_EXIT_t pxenv_undi_close ( struct s_PXENV_UNDI_CLOSE *undi_close ) {
215
 	DBGC ( &pxe_netdev, "PXENV_UNDI_CLOSE\n" );
275
 	DBGC ( &pxe_netdev, "PXENV_UNDI_CLOSE\n" );
216
 
276
 
277
+	/* Sanity check */
278
+	if ( ! pxe_netdev ) {
279
+		DBGC ( &pxe_netdev, "PXENV_UNDI_CLOSE called with no "
280
+		       "network device\n" );
281
+		undi_close->Status = PXENV_STATUS_UNDI_INVALID_STATE;
282
+		return PXENV_EXIT_FAILURE;
283
+	}
284
+
285
+	/* Close network device */
217
 	pxe_netdev_close();
286
 	pxe_netdev_close();
218
 
287
 
219
 	undi_close->Status = PXENV_STATUS_SUCCESS;
288
 	undi_close->Status = PXENV_STATUS_SUCCESS;
230
 	struct DataBlk *datablk;
299
 	struct DataBlk *datablk;
231
 	struct io_buffer *iobuf;
300
 	struct io_buffer *iobuf;
232
 	struct net_protocol *net_protocol;
301
 	struct net_protocol *net_protocol;
233
-	struct ll_protocol *ll_protocol = pxe_netdev->ll_protocol;
302
+	struct ll_protocol *ll_protocol;
234
 	char destaddr[MAX_LL_ADDR_LEN];
303
 	char destaddr[MAX_LL_ADDR_LEN];
235
 	const void *ll_dest;
304
 	const void *ll_dest;
236
 	size_t len;
305
 	size_t len;
239
 
308
 
240
 	DBGC2 ( &pxe_netdev, "PXENV_UNDI_TRANSMIT" );
309
 	DBGC2 ( &pxe_netdev, "PXENV_UNDI_TRANSMIT" );
241
 
310
 
311
+	/* Sanity check */
312
+	if ( ! pxe_netdev ) {
313
+		DBGC ( &pxe_netdev, "PXENV_UNDI_TRANSMIT called with no "
314
+		       "network device\n" );
315
+		undi_transmit->Status = PXENV_STATUS_UNDI_INVALID_STATE;
316
+		return PXENV_EXIT_FAILURE;
317
+	}
318
+
242
 	/* Forcibly enable interrupts and freeze receive queue
319
 	/* Forcibly enable interrupts and freeze receive queue
243
 	 * processing at this point, to work around callers that never
320
 	 * processing at this point, to work around callers that never
244
 	 * call PXENV_UNDI_OPEN before attempting to use the UNDI API.
321
 	 * call PXENV_UNDI_OPEN before attempting to use the UNDI API.
299
 	if ( net_protocol != NULL ) {
376
 	if ( net_protocol != NULL ) {
300
 
377
 
301
 		/* Calculate destination address */
378
 		/* Calculate destination address */
379
+		ll_protocol = pxe_netdev->ll_protocol;
302
 		if ( undi_transmit->XmitFlag == XMT_DESTADDR ) {
380
 		if ( undi_transmit->XmitFlag == XMT_DESTADDR ) {
303
 			copy_from_real ( destaddr,
381
 			copy_from_real ( destaddr,
304
 					 undi_transmit->DestAddr.segment,
382
 					 undi_transmit->DestAddr.segment,
355
 	pxe_dump_mcast_list ( &undi_set_mcast_address->R_Mcast_Buf );
433
 	pxe_dump_mcast_list ( &undi_set_mcast_address->R_Mcast_Buf );
356
 	DBGC ( &pxe_netdev, "\n" );
434
 	DBGC ( &pxe_netdev, "\n" );
357
 
435
 
436
+	/* Sanity check */
437
+	if ( ! pxe_netdev ) {
438
+		DBGC ( &pxe_netdev, "PXENV_UNDI_SET_MCAST_ADDRESS called with "
439
+		       "no network device\n" );
440
+		undi_set_mcast_address->Status =
441
+			PXENV_STATUS_UNDI_INVALID_STATE;
442
+		return PXENV_EXIT_FAILURE;
443
+	}
444
+
358
 	undi_set_mcast_address->Status = PXENV_STATUS_SUCCESS;
445
 	undi_set_mcast_address->Status = PXENV_STATUS_SUCCESS;
359
 	return PXENV_EXIT_SUCCESS;
446
 	return PXENV_EXIT_SUCCESS;
360
 }
447
 }
366
 PXENV_EXIT_t 
453
 PXENV_EXIT_t 
367
 pxenv_undi_set_station_address ( struct s_PXENV_UNDI_SET_STATION_ADDRESS
454
 pxenv_undi_set_station_address ( struct s_PXENV_UNDI_SET_STATION_ADDRESS
368
 				 *undi_set_station_address ) {
455
 				 *undi_set_station_address ) {
369
-	struct ll_protocol *ll_protocol = pxe_netdev->ll_protocol;
456
+	struct ll_protocol *ll_protocol;
457
+
458
+	/* Sanity check */
459
+	if ( ! pxe_netdev ) {
460
+		DBGC ( &pxe_netdev, "PXENV_UNDI_SET_STATION_ADDRESS called "
461
+		       "with no network device\n" );
462
+		undi_set_station_address->Status =
463
+			PXENV_STATUS_UNDI_INVALID_STATE;
464
+		return PXENV_EXIT_FAILURE;
465
+	}
370
 
466
 
467
+	ll_protocol = pxe_netdev->ll_protocol;
371
 	DBGC ( &pxe_netdev, "PXENV_UNDI_SET_STATION_ADDRESS %s",
468
 	DBGC ( &pxe_netdev, "PXENV_UNDI_SET_STATION_ADDRESS %s",
372
 	       ll_protocol->ntoa ( undi_set_station_address->StationAddress ) );
469
 	       ll_protocol->ntoa ( undi_set_station_address->StationAddress ) );
373
 
470
 
403
 	DBGC ( &pxe_netdev, "PXENV_UNDI_SET_PACKET_FILTER %02x\n",
500
 	DBGC ( &pxe_netdev, "PXENV_UNDI_SET_PACKET_FILTER %02x\n",
404
 	       undi_set_packet_filter->filter );
501
 	       undi_set_packet_filter->filter );
405
 
502
 
503
+	/* Sanity check */
504
+	if ( ! pxe_netdev ) {
505
+		DBGC ( &pxe_netdev, "PXENV_UNDI_SET_PACKET_FILTER called with "
506
+		       "no network device\n" );
507
+		undi_set_packet_filter->Status =
508
+			PXENV_STATUS_UNDI_INVALID_STATE;
509
+		return PXENV_EXIT_FAILURE;
510
+	}
511
+
406
 	/* Pretend that we succeeded, otherwise the 3Com DOS UNDI
512
 	/* Pretend that we succeeded, otherwise the 3Com DOS UNDI
407
 	 * driver refuses to load.  (We ignore the filter value in the
513
 	 * driver refuses to load.  (We ignore the filter value in the
408
 	 * PXENV_UNDI_OPEN call anyway.)
514
 	 * PXENV_UNDI_OPEN call anyway.)
418
  */
524
  */
419
 PXENV_EXIT_t pxenv_undi_get_information ( struct s_PXENV_UNDI_GET_INFORMATION
525
 PXENV_EXIT_t pxenv_undi_get_information ( struct s_PXENV_UNDI_GET_INFORMATION
420
 					  *undi_get_information ) {
526
 					  *undi_get_information ) {
421
-	struct device *dev = pxe_netdev->dev;
422
-	struct ll_protocol *ll_protocol = pxe_netdev->ll_protocol;
423
-	size_t ll_addr_len = ll_protocol->ll_addr_len;
527
+	struct device *dev;
528
+	struct ll_protocol *ll_protocol;
424
 
529
 
425
 	DBGC ( &pxe_netdev, "PXENV_UNDI_GET_INFORMATION" );
530
 	DBGC ( &pxe_netdev, "PXENV_UNDI_GET_INFORMATION" );
426
 
531
 
532
+	/* Sanity check */
533
+	if ( ! pxe_netdev ) {
534
+		DBGC ( &pxe_netdev, "PXENV_UNDI_GET_INFORMATION called with no "
535
+		       "network device\n" );
536
+		undi_get_information->Status = PXENV_STATUS_UNDI_INVALID_STATE;
537
+		return PXENV_EXIT_FAILURE;
538
+	}
539
+
540
+	/* Fill in information */
541
+	dev = pxe_netdev->dev;
542
+	ll_protocol = pxe_netdev->ll_protocol;
427
 	undi_get_information->BaseIo = dev->desc.ioaddr;
543
 	undi_get_information->BaseIo = dev->desc.ioaddr;
428
 	undi_get_information->IntNumber =
544
 	undi_get_information->IntNumber =
429
 		( netdev_irq_supported ( pxe_netdev ) ? dev->desc.irq : 0 );
545
 		( netdev_irq_supported ( pxe_netdev ) ? dev->desc.irq : 0 );
430
 	/* Cheat: assume all cards can cope with this */
546
 	/* Cheat: assume all cards can cope with this */
431
 	undi_get_information->MaxTranUnit = ETH_MAX_MTU;
547
 	undi_get_information->MaxTranUnit = ETH_MAX_MTU;
432
 	undi_get_information->HwType = ntohs ( ll_protocol->ll_proto );
548
 	undi_get_information->HwType = ntohs ( ll_protocol->ll_proto );
433
-	undi_get_information->HwAddrLen = ll_addr_len;
434
-	assert ( ll_addr_len <=
549
+	undi_get_information->HwAddrLen = ll_protocol->ll_addr_len;
550
+	assert ( ll_protocol->ll_addr_len <=
435
 		 sizeof ( undi_get_information->CurrentNodeAddress ) );
551
 		 sizeof ( undi_get_information->CurrentNodeAddress ) );
436
 	memcpy ( &undi_get_information->CurrentNodeAddress,
552
 	memcpy ( &undi_get_information->CurrentNodeAddress,
437
 		 pxe_netdev->ll_addr,
553
 		 pxe_netdev->ll_addr,
462
 					 *undi_get_statistics ) {
578
 					 *undi_get_statistics ) {
463
 	DBGC ( &pxe_netdev, "PXENV_UNDI_GET_STATISTICS" );
579
 	DBGC ( &pxe_netdev, "PXENV_UNDI_GET_STATISTICS" );
464
 
580
 
581
+	/* Sanity check */
582
+	if ( ! pxe_netdev ) {
583
+		DBGC ( &pxe_netdev, "PXENV_UNDI_GET_STATISTICS called with no "
584
+		       "network device\n" );
585
+		undi_get_statistics->Status = PXENV_STATUS_UNDI_INVALID_STATE;
586
+		return PXENV_EXIT_FAILURE;
587
+	}
588
+
589
+	/* Report statistics */
465
 	undi_get_statistics->XmtGoodFrames = pxe_netdev->tx_stats.good;
590
 	undi_get_statistics->XmtGoodFrames = pxe_netdev->tx_stats.good;
466
 	undi_get_statistics->RcvGoodFrames = pxe_netdev->rx_stats.good;
591
 	undi_get_statistics->RcvGoodFrames = pxe_netdev->rx_stats.good;
467
 	undi_get_statistics->RcvCRCErrors = pxe_netdev->rx_stats.bad;
592
 	undi_get_statistics->RcvCRCErrors = pxe_netdev->rx_stats.bad;
468
 	undi_get_statistics->RcvResourceErrors = pxe_netdev->rx_stats.bad;
593
 	undi_get_statistics->RcvResourceErrors = pxe_netdev->rx_stats.bad;
469
-
470
 	DBGC ( &pxe_netdev, " txok %d rxok %d rxcrc %d rxrsrc %d\n",
594
 	DBGC ( &pxe_netdev, " txok %d rxok %d rxcrc %d rxrsrc %d\n",
471
 	       undi_get_statistics->XmtGoodFrames,
595
 	       undi_get_statistics->XmtGoodFrames,
472
 	       undi_get_statistics->RcvGoodFrames,
596
 	       undi_get_statistics->RcvGoodFrames,
473
 	       undi_get_statistics->RcvCRCErrors,
597
 	       undi_get_statistics->RcvCRCErrors,
474
 	       undi_get_statistics->RcvResourceErrors );
598
 	       undi_get_statistics->RcvResourceErrors );
599
+
475
 	undi_get_statistics->Status = PXENV_STATUS_SUCCESS;
600
 	undi_get_statistics->Status = PXENV_STATUS_SUCCESS;
476
 	return PXENV_EXIT_SUCCESS;
601
 	return PXENV_EXIT_SUCCESS;
477
 }
602
 }
484
 					   *undi_clear_statistics ) {
609
 					   *undi_clear_statistics ) {
485
 	DBGC ( &pxe_netdev, "PXENV_UNDI_CLEAR_STATISTICS\n" );
610
 	DBGC ( &pxe_netdev, "PXENV_UNDI_CLEAR_STATISTICS\n" );
486
 
611
 
612
+	/* Sanity check */
613
+	if ( ! pxe_netdev ) {
614
+		DBGC ( &pxe_netdev, "PXENV_UNDI_CLEAR_STATISTICS called with "
615
+		       "no network device\n" );
616
+		undi_clear_statistics->Status = PXENV_STATUS_UNDI_INVALID_STATE;
617
+		return PXENV_EXIT_FAILURE;
618
+	}
619
+
620
+	/* Clear statistics */
487
 	memset ( &pxe_netdev->tx_stats, 0, sizeof ( pxe_netdev->tx_stats ) );
621
 	memset ( &pxe_netdev->tx_stats, 0, sizeof ( pxe_netdev->tx_stats ) );
488
 	memset ( &pxe_netdev->rx_stats, 0, sizeof ( pxe_netdev->rx_stats ) );
622
 	memset ( &pxe_netdev->rx_stats, 0, sizeof ( pxe_netdev->rx_stats ) );
489
 
623
 
500
 					 *undi_initiate_diags ) {
634
 					 *undi_initiate_diags ) {
501
 	DBGC ( &pxe_netdev, "PXENV_UNDI_INITIATE_DIAGS failed: unsupported\n" );
635
 	DBGC ( &pxe_netdev, "PXENV_UNDI_INITIATE_DIAGS failed: unsupported\n" );
502
 
636
 
637
+	/* Sanity check */
638
+	if ( ! pxe_netdev ) {
639
+		DBGC ( &pxe_netdev, "PXENV_UNDI_INITIATE_DIAGS called with no "
640
+		       "network device\n" );
641
+		undi_initiate_diags->Status = PXENV_STATUS_UNDI_INVALID_STATE;
642
+		return PXENV_EXIT_FAILURE;
643
+	}
644
+
503
 	undi_initiate_diags->Status = PXENV_STATUS_UNSUPPORTED;
645
 	undi_initiate_diags->Status = PXENV_STATUS_UNSUPPORTED;
504
 	return PXENV_EXIT_FAILURE;
646
 	return PXENV_EXIT_FAILURE;
505
 }
647
 }
514
 	DBGC ( &pxe_netdev,
656
 	DBGC ( &pxe_netdev,
515
 	       "PXENV_UNDI_FORCE_INTERRUPT failed: unsupported\n" );
657
 	       "PXENV_UNDI_FORCE_INTERRUPT failed: unsupported\n" );
516
 
658
 
659
+	/* Sanity check */
660
+	if ( ! pxe_netdev ) {
661
+		DBGC ( &pxe_netdev, "PXENV_UNDI_FORCE_INTERRUPT called with no "
662
+		       "network device\n" );
663
+		undi_force_interrupt->Status = PXENV_STATUS_UNDI_INVALID_STATE;
664
+		return PXENV_EXIT_FAILURE;
665
+	}
666
+
517
 	undi_force_interrupt->Status = PXENV_STATUS_UNSUPPORTED;
667
 	undi_force_interrupt->Status = PXENV_STATUS_UNSUPPORTED;
518
 	return PXENV_EXIT_FAILURE;
668
 	return PXENV_EXIT_FAILURE;
519
 }
669
 }
525
 PXENV_EXIT_t
675
 PXENV_EXIT_t
526
 pxenv_undi_get_mcast_address ( struct s_PXENV_UNDI_GET_MCAST_ADDRESS
676
 pxenv_undi_get_mcast_address ( struct s_PXENV_UNDI_GET_MCAST_ADDRESS
527
 			       *undi_get_mcast_address ) {
677
 			       *undi_get_mcast_address ) {
528
-	struct ll_protocol *ll_protocol = pxe_netdev->ll_protocol;
678
+	struct ll_protocol *ll_protocol;
529
 	struct in_addr ip = { .s_addr = undi_get_mcast_address->InetAddr };
679
 	struct in_addr ip = { .s_addr = undi_get_mcast_address->InetAddr };
530
 	int rc;
680
 	int rc;
531
 
681
 
532
 	DBGC ( &pxe_netdev, "PXENV_UNDI_GET_MCAST_ADDRESS %s",
682
 	DBGC ( &pxe_netdev, "PXENV_UNDI_GET_MCAST_ADDRESS %s",
533
 	       inet_ntoa ( ip ) );
683
 	       inet_ntoa ( ip ) );
534
 
684
 
685
+	/* Sanity check */
686
+	if ( ! pxe_netdev ) {
687
+		DBGC ( &pxe_netdev, "PXENV_UNDI_GET_MCAST_ADDRESS called with "
688
+		       "no network device\n" );
689
+		undi_get_mcast_address->Status =
690
+			PXENV_STATUS_UNDI_INVALID_STATE;
691
+		return PXENV_EXIT_FAILURE;
692
+	}
693
+
694
+	/* Hash address using the network device's link-layer protocol */
695
+	ll_protocol = pxe_netdev->ll_protocol;
535
 	if ( ( rc = ll_protocol->mc_hash ( AF_INET, &ip,
696
 	if ( ( rc = ll_protocol->mc_hash ( AF_INET, &ip,
536
 				      undi_get_mcast_address->MediaAddr ))!=0){
697
 				      undi_get_mcast_address->MediaAddr ))!=0){
537
 		DBGC ( &pxe_netdev, " failed: %s\n", strerror ( rc ) );
698
 		DBGC ( &pxe_netdev, " failed: %s\n", strerror ( rc ) );
551
  */
712
  */
552
 PXENV_EXIT_t pxenv_undi_get_nic_type ( struct s_PXENV_UNDI_GET_NIC_TYPE
713
 PXENV_EXIT_t pxenv_undi_get_nic_type ( struct s_PXENV_UNDI_GET_NIC_TYPE
553
 				       *undi_get_nic_type ) {
714
 				       *undi_get_nic_type ) {
554
-	struct device *dev = pxe_netdev->dev;
715
+	struct device *dev;
555
 
716
 
556
 	DBGC ( &pxe_netdev, "PXENV_UNDI_GET_NIC_TYPE" );
717
 	DBGC ( &pxe_netdev, "PXENV_UNDI_GET_NIC_TYPE" );
557
 
718
 
719
+	/* Sanity check */
720
+	if ( ! pxe_netdev ) {
721
+		DBGC ( &pxe_netdev, "PXENV_UNDI_GET_NIC_TYPE called with "
722
+		       "no network device\n" );
723
+		undi_get_nic_type->Status = PXENV_STATUS_UNDI_INVALID_STATE;
724
+		return PXENV_EXIT_FAILURE;
725
+	}
726
+
727
+	/* Fill in information */
558
 	memset ( &undi_get_nic_type->info, 0,
728
 	memset ( &undi_get_nic_type->info, 0,
559
 		 sizeof ( undi_get_nic_type->info ) );
729
 		 sizeof ( undi_get_nic_type->info ) );
560
-
730
+	dev = pxe_netdev->dev;
561
 	switch ( dev->desc.bus_type ) {
731
 	switch ( dev->desc.bus_type ) {
562
 	case BUS_TYPE_PCI: {
732
 	case BUS_TYPE_PCI: {
563
 		struct pci_nic_info *info = &undi_get_nic_type->info.pci;
733
 		struct pci_nic_info *info = &undi_get_nic_type->info.pci;
615
 					 *undi_get_iface_info ) {
785
 					 *undi_get_iface_info ) {
616
 	DBGC ( &pxe_netdev, "PXENV_UNDI_GET_IFACE_INFO" );
786
 	DBGC ( &pxe_netdev, "PXENV_UNDI_GET_IFACE_INFO" );
617
 
787
 
788
+	/* Sanity check */
789
+	if ( ! pxe_netdev ) {
790
+		DBGC ( &pxe_netdev, "PXENV_UNDI_GET_IFACE_INFO called with "
791
+		       "no network device\n" );
792
+		undi_get_iface_info->Status = PXENV_STATUS_UNDI_INVALID_STATE;
793
+		return PXENV_EXIT_FAILURE;
794
+	}
795
+
618
 	/* Just hand back some info, doesn't really matter what it is.
796
 	/* Just hand back some info, doesn't really matter what it is.
619
 	 * Most PXE stacks seem to take this approach.
797
 	 * Most PXE stacks seem to take this approach.
620
 	 */
798
 	 */
645
 				    *undi_get_state ) {
823
 				    *undi_get_state ) {
646
 	DBGC ( &pxe_netdev, "PXENV_UNDI_GET_STATE failed: unsupported\n" );
824
 	DBGC ( &pxe_netdev, "PXENV_UNDI_GET_STATE failed: unsupported\n" );
647
 
825
 
826
+	/* Sanity check */
827
+	if ( ! pxe_netdev ) {
828
+		DBGC ( &pxe_netdev, "PXENV_UNDI_GET_STATE called with "
829
+		       "no network device\n" );
830
+		undi_get_state->Status = PXENV_STATUS_UNDI_INVALID_STATE;
831
+		return PXENV_EXIT_FAILURE;
832
+	}
833
+
648
 	undi_get_state->Status = PXENV_STATUS_UNSUPPORTED;
834
 	undi_get_state->Status = PXENV_STATUS_UNSUPPORTED;
649
 	return PXENV_EXIT_FAILURE;
835
 	return PXENV_EXIT_FAILURE;
650
 };
836
 };
671
 	 */
857
 	 */
672
 	DBGC2 ( &pxenv_undi_isr, "PXENV_UNDI_ISR" );
858
 	DBGC2 ( &pxenv_undi_isr, "PXENV_UNDI_ISR" );
673
 
859
 
860
+	/* Sanity check */
861
+	if ( ! pxe_netdev ) {
862
+		DBGC ( &pxe_netdev, "PXENV_UNDI_ISR called with "
863
+		       "no network device\n" );
864
+		undi_isr->Status = PXENV_STATUS_UNDI_INVALID_STATE;
865
+		return PXENV_EXIT_FAILURE;
866
+	}
867
+
674
 	/* Just in case some idiot actually looks at these fields when
868
 	/* Just in case some idiot actually looks at these fields when
675
 	 * we weren't meant to fill them in...
869
 	 * we weren't meant to fill them in...
676
 	 */
870
 	 */

Loading…
Cancel
Save