Added dhcp_ipv4_option() and friends.
authorMichael Brown <mcb30@etherboot.org>
Thu, 20 Jul 2006 02:49:59 +0000 (02:49 +0000)
committerMichael Brown <mcb30@etherboot.org>
Thu, 20 Jul 2006 02:49:59 +0000 (02:49 +0000)
Added test code to configure the interface for IPv4 after DHCP.

src/include/gpxe/dhcp.h
src/net/dhcpopts.c
src/tests/dhcptest.c

index 1dbb290..115ce2b 100644 (file)
@@ -250,6 +250,7 @@ struct dhcp_option {
                uint8_t byte;
                uint16_t word;
                uint32_t dword;
+               struct in_addr in;
                uint8_t bytes[0];
        } data;
 } __attribute__ (( packed ));
@@ -429,6 +430,8 @@ struct dhcp_session {
 };
 
 extern unsigned long dhcp_num_option ( struct dhcp_option *option );
+extern void dhcp_ipv4_option ( struct dhcp_option *option,
+                              struct in_addr *inp );
 extern struct dhcp_option *
 find_dhcp_option ( struct dhcp_option_block *options, unsigned int tag );
 extern void register_dhcp_options ( struct dhcp_option_block *options );
@@ -444,6 +447,10 @@ extern struct dhcp_option * find_global_dhcp_option ( unsigned int tag );
 extern unsigned long find_dhcp_num_option ( struct dhcp_option_block *options,
                                            unsigned int tag );
 extern unsigned long find_global_dhcp_num_option ( unsigned int tag );
+extern void find_dhcp_ipv4_option ( struct dhcp_option_block *options,
+                                   unsigned int tag, struct in_addr *inp );
+extern void find_global_dhcp_ipv4_option ( unsigned int tag,
+                                          struct in_addr *inp );
 extern void delete_dhcp_option ( struct dhcp_option_block *options,
                                 unsigned int tag );
 
index 4f67f84..ebd6de7 100644 (file)
@@ -24,6 +24,7 @@
 #include <assert.h>
 #include <vsprintf.h>
 #include <gpxe/list.h>
+#include <gpxe/in.h>
 #include <gpxe/dhcp.h>
 
 /** @file
@@ -85,6 +86,21 @@ unsigned long dhcp_num_option ( struct dhcp_option *option ) {
        return value;
 }
 
+/**
+ * Obtain value of an IPv4-address DHCP option
+ *
+ * @v option           DHCP option, or NULL
+ * @v inp              IPv4 address to fill in
+ *
+ * Parses the IPv4 address value from a DHCP option, if present.  It
+ * is permitted to call dhcp_ipv4_option() with @c option set to NULL;
+ * in this case the address will be set to 0.0.0.0.
+ */
+void dhcp_ipv4_option ( struct dhcp_option *option, struct in_addr *inp ) {
+       if ( option )
+               *inp = option->data.in;
+}
+
 /**
  * Calculate length of a normal DHCP option
  *
@@ -460,6 +476,45 @@ unsigned long find_global_dhcp_num_option ( unsigned int tag ) {
        return dhcp_num_option ( find_global_dhcp_option ( tag ) );
 }
 
+/**
+ * Find DHCP IPv4-address option, and return its value
+ *
+ * @v options          DHCP options block
+ * @v tag              DHCP option tag to search for
+ * @v inp              IPv4 address to fill in
+ * @ret value          Numerical value of the option, or 0 if not found
+ *
+ * This function exists merely as a notational shorthand for a call to
+ * find_dhcp_option() followed by a call to dhcp_ipv4_option().  It is
+ * not possible to distinguish between the cases "option not found"
+ * and "option has a value of 0.0.0.0" using this function; if this
+ * matters to you then issue the two constituent calls directly and
+ * check that find_dhcp_option() returns a non-NULL value.
+ */
+void find_dhcp_ipv4_option ( struct dhcp_option_block *options,
+                            unsigned int tag, struct in_addr *inp ) {
+       dhcp_ipv4_option ( find_dhcp_option ( options, tag ), inp );
+}
+
+/**
+ * Find DHCP IPv4-address option, and return its value
+ *
+ * @v options          DHCP options block
+ * @v tag              DHCP option tag to search for
+ * @v inp              IPv4 address to fill in
+ * @ret value          Numerical value of the option, or 0 if not found
+ *
+ * This function exists merely as a notational shorthand for a call to
+ * find_dhcp_option() followed by a call to dhcp_ipv4_option().  It is
+ * not possible to distinguish between the cases "option not found"
+ * and "option has a value of 0.0.0.0" using this function; if this
+ * matters to you then issue the two constituent calls directly and
+ * check that find_dhcp_option() returns a non-NULL value.
+ */
+void find_global_dhcp_ipv4_option ( unsigned int tag, struct in_addr *inp ) {
+       dhcp_ipv4_option ( find_global_dhcp_option ( tag ), inp );
+}
+
 /**
  * Delete DHCP option
  *
index d35e02c..b61535f 100644 (file)
@@ -1,10 +1,49 @@
 #include <string.h>
+#include <vsprintf.h>
+#include <byteswap.h>
+#include <gpxe/ip.h>
 #include <gpxe/dhcp.h>
 
 int test_dhcp ( struct net_device *netdev ) {
        struct dhcp_session dhcp;
+       struct in_addr address = { htonl ( 0 ) };
+       struct in_addr netmask = { htonl ( 0 ) };
+       struct in_addr gateway = { INADDR_NONE };
+       int rc;
 
+       /* Bring IP interface up with address 0.0.0.0 */
+       if ( ( rc = add_ipv4_address ( netdev, address, netmask,
+                                      gateway ) ) != 0 )
+               goto out_no_del_ipv4;
+
+       /* Issue DHCP request */
        memset ( &dhcp, 0, sizeof ( dhcp ) );
        dhcp.netdev = netdev;
-       return async_wait ( start_dhcp ( &dhcp ) );
+       if ( ( rc = async_wait ( start_dhcp ( &dhcp ) ) ) != 0 )
+               goto out_no_options;
+
+       /* Retrieve IP address configuration */
+       find_dhcp_ipv4_option ( dhcp.options, DHCP_EB_YIADDR, &address );
+       find_dhcp_ipv4_option ( dhcp.options, DHCP_SUBNET_MASK, &netmask );
+       find_dhcp_ipv4_option ( dhcp.options, DHCP_ROUTERS, &gateway );
+
+       /* Remove old IP address configuration */
+       del_ipv4_address ( netdev );
+
+       /* Set up new IP address configuration */
+       if ( ( rc = add_ipv4_address ( netdev, address, netmask,
+                                      gateway ) ) != 0 )
+               goto out_no_del_ipv4;
+
+       printf ( "IP %s", inet_ntoa ( address ) );
+       printf ( " netmask %s", inet_ntoa ( netmask ) );
+       printf ( " gateway %s\n", inet_ntoa ( gateway ) );
+
+       /* Free DHCP options */
+       free_dhcp_options ( dhcp.options );
+ out_no_options:
+       /* Take down IP interface */
+       del_ipv4_address ( netdev );
+ out_no_del_ipv4:
+       return rc;
 }