|
@@ -80,8 +80,25 @@ static inline const char * dhcp_msgtype_name ( unsigned int msgtype ) {
|
80
|
80
|
}
|
81
|
81
|
}
|
82
|
82
|
|
|
83
|
+/**
|
|
84
|
+ * Calculate DHCP transaction ID for a network device
|
|
85
|
+ *
|
|
86
|
+ * @v netdev Network device
|
|
87
|
+ * @ret xid DHCP XID
|
|
88
|
+ *
|
|
89
|
+ * Extract the least significant bits of the hardware address for use
|
|
90
|
+ * as the transaction ID.
|
|
91
|
+ */
|
|
92
|
+static uint32_t dhcp_xid ( struct net_device *netdev ) {
|
|
93
|
+ uint32_t xid;
|
|
94
|
+
|
|
95
|
+ memcpy ( &xid, ( netdev->ll_addr + netdev->ll_protocol->ll_addr_len
|
|
96
|
+ - sizeof ( xid ) ), sizeof ( xid ) );
|
|
97
|
+ return xid;
|
|
98
|
+}
|
|
99
|
+
|
83
|
100
|
/** Options common to all DHCP requests */
|
84
|
|
-static struct dhcp_option_block dhcp_request_options = {
|
|
101
|
+struct dhcp_option_block dhcp_request_options = {
|
85
|
102
|
.data = dhcp_request_options_data,
|
86
|
103
|
.max_len = sizeof ( dhcp_request_options_data ),
|
87
|
104
|
.len = sizeof ( dhcp_request_options_data ),
|
|
@@ -245,15 +262,15 @@ static int copy_dhcp_packet_encap_options ( struct dhcp_packet *dhcppkt,
|
245
|
262
|
* @c options may specify a single options block, or be left as NULL
|
246
|
263
|
* in order to copy options from all registered options blocks.
|
247
|
264
|
*/
|
248
|
|
-static int copy_dhcp_packet_options ( struct dhcp_packet *dhcppkt,
|
249
|
|
- struct dhcp_option_block *options ) {
|
|
265
|
+int copy_dhcp_packet_options ( struct dhcp_packet *dhcppkt,
|
|
266
|
+ struct dhcp_option_block *options ) {
|
250
|
267
|
return copy_dhcp_packet_encap_options ( dhcppkt, options, 0 );
|
251
|
268
|
}
|
252
|
269
|
|
253
|
270
|
/**
|
254
|
271
|
* Create a DHCP packet
|
255
|
272
|
*
|
256
|
|
- * @v dhcp DHCP session
|
|
273
|
+ * @v netdev Network device
|
257
|
274
|
* @v msgtype DHCP message type
|
258
|
275
|
* @v data Buffer for DHCP packet
|
259
|
276
|
* @v max_len Size of DHCP packet buffer
|
|
@@ -264,9 +281,9 @@ static int copy_dhcp_packet_options ( struct dhcp_packet *dhcppkt,
|
264
|
281
|
* dhcp_packet structure that can be passed to
|
265
|
282
|
* set_dhcp_packet_option() or copy_dhcp_packet_options().
|
266
|
283
|
*/
|
267
|
|
-static int create_dhcp_packet ( struct dhcp_session *dhcp, uint8_t msgtype,
|
268
|
|
- void *data, size_t max_len,
|
269
|
|
- struct dhcp_packet *dhcppkt ) {
|
|
284
|
+int create_dhcp_packet ( struct net_device *netdev, uint8_t msgtype,
|
|
285
|
+ void *data, size_t max_len,
|
|
286
|
+ struct dhcp_packet *dhcppkt ) {
|
270
|
287
|
struct dhcphdr *dhcphdr = data;
|
271
|
288
|
static const uint8_t overloading = ( DHCP_OPTION_OVERLOAD_FILE |
|
272
|
289
|
DHCP_OPTION_OVERLOAD_SNAME );
|
|
@@ -278,11 +295,11 @@ static int create_dhcp_packet ( struct dhcp_session *dhcp, uint8_t msgtype,
|
278
|
295
|
|
279
|
296
|
/* Initialise DHCP packet content */
|
280
|
297
|
memset ( dhcphdr, 0, max_len );
|
281
|
|
- dhcphdr->xid = dhcp->xid;
|
|
298
|
+ dhcphdr->xid = dhcp_xid ( netdev );
|
282
|
299
|
dhcphdr->magic = htonl ( DHCP_MAGIC_COOKIE );
|
283
|
|
- dhcphdr->htype = ntohs ( dhcp->netdev->ll_protocol->ll_proto );
|
284
|
|
- dhcphdr->hlen = dhcp->netdev->ll_protocol->ll_addr_len;
|
285
|
|
- memcpy ( dhcphdr->chaddr, dhcp->netdev->ll_addr, dhcphdr->hlen );
|
|
300
|
+ dhcphdr->htype = ntohs ( netdev->ll_protocol->ll_proto );
|
|
301
|
+ dhcphdr->hlen = netdev->ll_protocol->ll_addr_len;
|
|
302
|
+ memcpy ( dhcphdr->chaddr, netdev->ll_addr, dhcphdr->hlen );
|
286
|
303
|
dhcphdr->op = dhcp_op[msgtype];
|
287
|
304
|
|
288
|
305
|
/* Initialise DHCP packet structure */
|
|
@@ -522,7 +539,7 @@ static int dhcp_senddata ( struct udp_connection *conn,
|
522
|
539
|
( dhcp->state == DHCPREQUEST ) );
|
523
|
540
|
|
524
|
541
|
/* Create DHCP packet in temporary buffer */
|
525
|
|
- if ( ( rc = create_dhcp_packet ( dhcp, dhcp->state, buf, len,
|
|
542
|
+ if ( ( rc = create_dhcp_packet ( dhcp->netdev, dhcp->state, buf, len,
|
526
|
543
|
&dhcppkt ) ) != 0 ) {
|
527
|
544
|
DBG ( "Could not create DHCP packet\n" );
|
528
|
545
|
return rc;
|
|
@@ -606,9 +623,10 @@ static int dhcp_newdata ( struct udp_connection *conn, void *data, size_t len,
|
606
|
623
|
unsigned int msgtype;
|
607
|
624
|
|
608
|
625
|
/* Check for matching transaction ID */
|
609
|
|
- if ( dhcphdr->xid != dhcp->xid ) {
|
|
626
|
+ if ( dhcphdr->xid != dhcp_xid ( dhcp->netdev ) ) {
|
610
|
627
|
DBG ( "DHCP wrong transaction ID (wanted %08lx, got %08lx)\n",
|
611
|
|
- ntohl ( dhcphdr->xid ), ntohl ( dhcp->xid ) );
|
|
628
|
+ ntohl ( dhcphdr->xid ),
|
|
629
|
+ ntohl ( dhcp_xid ( dhcp->netdev ) ) );
|
612
|
630
|
return 0;
|
613
|
631
|
};
|
614
|
632
|
|
|
@@ -683,10 +701,6 @@ struct async_operation * start_dhcp ( struct dhcp_session *dhcp ) {
|
683
|
701
|
dhcp->udp.udp_op = &dhcp_udp_operations;
|
684
|
702
|
dhcp->timer.expired = dhcp_timer_expired;
|
685
|
703
|
dhcp->state = DHCPDISCOVER;
|
686
|
|
- /* Use least significant 32 bits of link-layer address as XID */
|
687
|
|
- memcpy ( &dhcp->xid, ( dhcp->netdev->ll_addr
|
688
|
|
- + dhcp->netdev->ll_protocol->ll_addr_len
|
689
|
|
- - sizeof ( dhcp->xid ) ), sizeof ( dhcp->xid ));
|
690
|
704
|
|
691
|
705
|
/* Bind to local port */
|
692
|
706
|
if ( ( rc = udp_open ( &dhcp->udp, htons ( BOOTPC_PORT ) ) ) != 0 ) {
|