Add dhcp_configure_netdev()
authorMichael Brown <mcb30@etherboot.org>
Thu, 28 Jun 2007 14:18:26 +0000 (15:18 +0100)
committerMichael Brown <mcb30@etherboot.org>
Thu, 28 Jun 2007 14:18:26 +0000 (15:18 +0100)
src/include/gpxe/dhcp.h
src/net/udp/dhcp.c

index 1f68742..634e47c 100644 (file)
@@ -513,6 +513,9 @@ extern int create_dhcp_packet ( struct net_device *netdev, uint8_t msgtype,
 extern int copy_dhcp_packet_options ( struct dhcp_packet *dhcppkt,
                                      struct dhcp_option_block *options );
 extern int start_dhcp ( struct job_interface *job, struct net_device *netdev,
-                       int (*register_options) ( struct dhcp_option_block * ));
+                       int (*register_options) ( struct net_device *,
+                                                 struct dhcp_option_block * ));
+extern int dhcp_configure_netdev ( struct net_device *netdev,
+                                  struct dhcp_option_block *options );
 
 #endif /* _GPXE_DHCP_H */
index 5319dc0..dc826b8 100644 (file)
@@ -27,6 +27,8 @@
 #include <gpxe/open.h>
 #include <gpxe/job.h>
 #include <gpxe/retry.h>
+#include <gpxe/tcpip.h>
+#include <gpxe/ip.h>
 #include <gpxe/dhcp.h>
 
 /** @file
@@ -502,7 +504,8 @@ struct dhcp_session {
        /** Network device being configured */
        struct net_device *netdev;
        /** Option block registration routine */
-       int ( * register_options ) ( struct dhcp_option_block *options );
+       int ( * register_options ) ( struct net_device *netdev,
+                                    struct dhcp_option_block *options );
 
        /** State of the session
         *
@@ -717,7 +720,7 @@ static int dhcp_deliver_raw ( struct xfer_interface *xfer,
        if ( dhcp->state < DHCPACK ) {
                dhcp_send_request ( dhcp );
        } else {
-               dhcp->register_options ( dhcp->options );
+               dhcp->register_options ( dhcp->netdev, dhcp->options );
                dhcp_finished ( dhcp, 0 );
        }
        return 0;
@@ -782,7 +785,8 @@ static struct job_interface_operations dhcp_job_operations = {
  * options.
  */
 int start_dhcp ( struct job_interface *job, struct net_device *netdev,
-                int ( * register_options ) ( struct dhcp_option_block * ) ) {
+                int ( * register_options ) ( struct net_device *netdev,
+                                             struct dhcp_option_block * ) ) {
        static struct sockaddr_in server = {
                .sin_family = AF_INET,
                .sin_addr.s_addr = INADDR_BROADCAST,
@@ -827,3 +831,57 @@ int start_dhcp ( struct job_interface *job, struct net_device *netdev,
        ref_put ( &dhcp->refcnt );
        return rc;
 }
+
+/****************************************************************************
+ *
+ * Network device configurator
+ *
+ */
+
+/* Avoid dragging in dns.o */
+struct sockaddr_tcpip nameserver;
+
+/* Avoid dragging in syslog.o */
+struct in_addr syslogserver;
+
+/**
+ * Configure network device from DHCP options
+ *
+ * @v netdev           Network device
+ * @v options          DHCP options block
+ * @ret rc             Return status code
+ */
+int dhcp_configure_netdev ( struct net_device *netdev,
+                           struct dhcp_option_block *options ) {
+       struct in_addr address = { 0 };
+       struct in_addr netmask = { 0 };
+       struct in_addr gateway = { INADDR_NONE };
+       struct sockaddr_in *sin_nameserver;
+       int rc;
+
+       /* Clear any existing routing table entry */
+       del_ipv4_address ( netdev );
+
+       /* Retrieve IP address configuration */
+       find_dhcp_ipv4_option ( options, DHCP_EB_YIADDR, &address );
+       find_dhcp_ipv4_option ( options, DHCP_SUBNET_MASK, &netmask );
+       find_dhcp_ipv4_option ( options, DHCP_ROUTERS, &gateway );
+
+       /* Set up new IP address configuration */
+       if ( ( rc = add_ipv4_address ( netdev, address, netmask,
+                                      gateway ) ) != 0 ) {
+               DBG ( "Could not configure %s with DHCP results: %s\n",
+                     netdev->name, strerror ( rc ) );
+               return rc;
+       }
+
+       /* Retrieve other DHCP options that we care about */
+       sin_nameserver = ( struct sockaddr_in * ) &nameserver;
+       sin_nameserver->sin_family = AF_INET;
+       find_dhcp_ipv4_option ( options, DHCP_DNS_SERVERS,
+                               &sin_nameserver->sin_addr );
+       find_dhcp_ipv4_option ( options, DHCP_LOG_SERVERS,
+                               &syslogserver );
+
+       return 0;
+}