Now capable of sending what, to me, looks like a valid DHCPDISCOVER
authorMichael Brown <mcb30@etherboot.org>
Wed, 19 Jul 2006 20:50:50 +0000 (20:50 +0000)
committerMichael Brown <mcb30@etherboot.org>
Wed, 19 Jul 2006 20:50:50 +0000 (20:50 +0000)
(apart from the bad UDP checksum).

src/include/gpxe/dhcp.h
src/net/udp/dhcp.c

index 2cb4f01..6825e40 100644 (file)
 #include <gpxe/udp.h>
 #include <gpxe/async.h>
 
+/** BOOTP/DHCP server port */
+#define BOOTPS_PORT 67
+
+/** BOOTP/DHCP client port */
+#define BOOTPC_PORT 68
+
 /** Construct a tag value for an encapsulated option
  *
  * This tag value can be passed to Etherboot functions when searching
@@ -345,9 +351,11 @@ struct dhcphdr {
        uint32_t magic;
        /** DHCP options
         *
-        * Variable length; extends to the end of the packet.
+        * Variable length; extends to the end of the packet.  Minimum
+        * length (for the sake of sanity) is 1, to allow for a single
+        * @c DHCP_END tag.
         */
-       uint8_t options[0];
+       uint8_t options[1];
 };
 
 /** Opcode for a request from client to server */
index a2b3ed5..63e8baf 100644 (file)
@@ -233,6 +233,10 @@ static int create_dhcp_packet ( struct dhcp_session *dhcp, uint8_t msgtype,
                                             DHCP_OPTION_OVERLOAD_SNAME );
        int rc;
 
+       /* Sanity check */
+       if ( max_len < sizeof ( *dhcphdr ) )
+               return -ENOSPC;
+
        /* Initialise DHCP packet content */
        memset ( dhcphdr, 0, max_len );
        dhcphdr->xid = dhcp->xid;
@@ -428,6 +432,15 @@ udp_to_dhcp ( struct udp_connection *conn ) {
        return container_of ( conn, struct dhcp_session, udp );
 }
 
+/** Address for transmitting DHCP requests */
+static struct sockaddr sa_dhcp_server = {
+       .sa_family = AF_INET,
+       .sin = {
+               .sin_addr.s_addr = INADDR_BROADCAST,
+               .sin_port = htons ( BOOTPS_PORT ),
+       },
+};
+
 /**
  * Transmit DHCP request
  *
@@ -461,7 +474,11 @@ static void dhcp_senddata ( struct udp_connection *conn,
        }
 
        /* Transmit the packet */
-       udp_send ( conn, dhcppkt.dhcphdr, dhcppkt.len );
+       if ( ( rc = udp_sendto ( conn, &sa_dhcp_server,
+                                dhcppkt.dhcphdr, dhcppkt.len ) ) != 0 ) {
+               DBG ( "Could not transmit UDP packet\n" );
+               return;
+       }
 }
 
 /**
@@ -513,6 +530,8 @@ static struct udp_operations dhcp_udp_operations = {
  * @ret aop            Asynchronous operation
  */
 struct async_operation * start_dhcp ( struct dhcp_session *dhcp ) {
+       int rc;
+
        dhcp->udp.udp_op = &dhcp_udp_operations;
        dhcp->state = DHCPDISCOVER;
        /* Use least significant 32 bits of link-layer address as XID */
@@ -520,8 +539,15 @@ struct async_operation * start_dhcp ( struct dhcp_session *dhcp ) {
                               + dhcp->netdev->ll_protocol->ll_addr_len
                               - sizeof ( dhcp->xid ) ), sizeof ( dhcp->xid ));
 
+       /* Bind to local port */
+       if ( ( rc = udp_open ( &dhcp->udp, BOOTPC_PORT ) ) != 0 ) {
+               async_done ( &dhcp->aop, rc );
+               goto out;
+       }
+
        /* Proof of concept: just send a single DHCPDISCOVER */
        udp_senddata ( &dhcp->udp );
 
+ out:
        return &dhcp->aop;
 }