|
@@ -22,6 +22,7 @@
|
22
|
22
|
#include <byteswap.h>
|
23
|
23
|
#include <gpxe/if_ether.h>
|
24
|
24
|
#include <gpxe/netdevice.h>
|
|
25
|
+#include <gpxe/udp.h>
|
25
|
26
|
#include <gpxe/dhcp.h>
|
26
|
27
|
|
27
|
28
|
/** @file
|
|
@@ -301,7 +302,7 @@ static void merge_dhcp_field ( struct dhcp_option_block *options,
|
301
|
302
|
/**
|
302
|
303
|
* Parse DHCP packet and construct DHCP options block
|
303
|
304
|
*
|
304
|
|
- * @v data DHCP packet
|
|
305
|
+ * @v dhcphdr DHCP packet
|
305
|
306
|
* @v len Length of DHCP packet
|
306
|
307
|
* @ret options DHCP options block, or NULL
|
307
|
308
|
*
|
|
@@ -320,8 +321,8 @@ static void merge_dhcp_field ( struct dhcp_option_block *options,
|
320
|
321
|
* options block; it is the responsibility of the caller to eventually
|
321
|
322
|
* free this memory.
|
322
|
323
|
*/
|
323
|
|
-struct dhcp_option_block * dhcp_parse ( const void *data, size_t len ) {
|
324
|
|
- const struct dhcphdr *dhcphdr = data;
|
|
324
|
+static struct dhcp_option_block * dhcp_parse ( struct dhcphdr *dhcphdr,
|
|
325
|
+ size_t len ) {
|
325
|
326
|
struct dhcp_option_block *options;
|
326
|
327
|
size_t options_len;
|
327
|
328
|
unsigned int overloading;
|
|
@@ -435,7 +436,8 @@ static void dhcp_senddata ( struct udp_connection *conn,
|
435
|
436
|
return;
|
436
|
437
|
}
|
437
|
438
|
|
438
|
|
-
|
|
439
|
+ /* Transmit the packet */
|
|
440
|
+ udp_send ( conn, dhcppkt.dhcphdr, dhcppkt.len );
|
439
|
441
|
}
|
440
|
442
|
|
441
|
443
|
/**
|
|
@@ -448,6 +450,26 @@ static void dhcp_senddata ( struct udp_connection *conn,
|
448
|
450
|
static void dhcp_newdata ( struct udp_connection *conn,
|
449
|
451
|
void *data, size_t len ) {
|
450
|
452
|
struct dhcp_session *dhcp = udp_to_dhcp ( conn );
|
|
453
|
+ struct dhcphdr *dhcphdr = data;
|
|
454
|
+ struct dhcp_option_block *options;
|
|
455
|
+
|
|
456
|
+ /* Check for matching transaction ID */
|
|
457
|
+ if ( dhcphdr->xid != dhcp->xid ) {
|
|
458
|
+ DBG ( "DHCP wrong transaction ID (wanted %08x, got %08x)\n",
|
|
459
|
+ ntohl ( dhcphdr->xid ), ntohl ( dhcp->xid ) );
|
|
460
|
+ return;
|
|
461
|
+ };
|
|
462
|
+
|
|
463
|
+ /* Parse packet and create options structure */
|
|
464
|
+ options = dhcp_parse ( dhcphdr, len );
|
|
465
|
+ if ( ! options ) {
|
|
466
|
+ DBG ( "Could not parse DHCP packet\n" );
|
|
467
|
+ return;
|
|
468
|
+ }
|
|
469
|
+
|
|
470
|
+ /* Proof of concept: just dump out the parsed options */
|
|
471
|
+ hex_dump ( options->data, options->len );
|
|
472
|
+ free_dhcp_options ( options );
|
451
|
473
|
}
|
452
|
474
|
|
453
|
475
|
/** DHCP UDP operations */
|
|
@@ -455,3 +477,23 @@ static struct udp_operations dhcp_udp_operations = {
|
455
|
477
|
.senddata = dhcp_senddata,
|
456
|
478
|
.newdata = dhcp_newdata,
|
457
|
479
|
};
|
|
480
|
+
|
|
481
|
+/**
|
|
482
|
+ * Initiate DHCP on a network interface
|
|
483
|
+ *
|
|
484
|
+ * @v dhcp DHCP session
|
|
485
|
+ * @ret aop Asynchronous operation
|
|
486
|
+ */
|
|
487
|
+struct async_operation * start_dhcp ( struct dhcp_session *dhcp ) {
|
|
488
|
+ dhcp->udp.udp_op = &dhcp_udp_operations;
|
|
489
|
+ dhcp->state = DHCPDISCOVER;
|
|
490
|
+ /* Use least significant 32 bits of link-layer address as XID */
|
|
491
|
+ memcpy ( &dhcp->xid, ( dhcp->netdev->ll_addr
|
|
492
|
+ + dhcp->netdev->ll_protocol->ll_addr_len
|
|
493
|
+ - sizeof ( dhcp->xid ) ), sizeof ( dhcp->xid ));
|
|
494
|
+
|
|
495
|
+ /* Proof of concept: just send a single DHCPDISCOVER */
|
|
496
|
+ udp_senddata ( &dhcp->udp );
|
|
497
|
+
|
|
498
|
+ return &dhcp->aop;
|
|
499
|
+}
|