[pxe] Obey lists of PXE Boot Servers and associated Discovery Control bits
authorMichael Brown <mcb30@etherboot.org>
Thu, 5 Feb 2009 09:30:32 +0000 (09:30 +0000)
committerMichael Brown <mcb30@etherboot.org>
Thu, 5 Feb 2009 09:34:32 +0000 (09:34 +0000)
Various combinations of options 43.6, 43.7 and 43.8 dictate which
servers we send Boot Server Discovery requests to, and which servers
we should accept responses from.  Obey these options, and remove the
explicit specification of a single Boot Server from start_pxebs() and
dependent functions.

src/hci/commands/dhcp_cmd.c
src/include/gpxe/dhcp.h
src/include/usr/dhcpmgmt.h
src/net/udp/dhcp.c
src/usr/dhcpmgmt.c
src/usr/pxemenu.c

index b44433e..9b577c8 100644 (file)
@@ -109,7 +109,7 @@ static int dhcp_exec ( int argc, char **argv ) {
  */
 static void pxebs_syntax ( char **argv ) {
        printf ( "Usage:\n"
-                "  %s <interface> <discovery_ip> <server_type>\n"
+                "  %s <interface> <server_type>\n"
                 "\n"
                 "Perform PXE Boot Server discovery\n",
                 argv[0] );
@@ -128,10 +128,8 @@ static int pxebs_exec ( int argc, char **argv ) {
                { NULL, 0, NULL, 0 },
        };
        const char *netdev_txt;
-       const char *pxe_server_txt;
        const char *pxe_type_txt;
        struct net_device *netdev;
-       struct in_addr pxe_server;
        unsigned int pxe_type;
        char *end;
        int c;
@@ -148,15 +146,12 @@ static int pxebs_exec ( int argc, char **argv ) {
                        return 1;
                }
        }
-
-       /* Need exactly one interface name remaining after the options */
-       if ( optind != ( argc - 3 ) ) {
+       if ( optind != ( argc - 2 ) ) {
                pxebs_syntax ( argv );
                return 1;
        }
        netdev_txt = argv[optind];
-       pxe_server_txt = argv[ optind + 1 ];
-       pxe_type_txt = argv[ optind + 2 ];
+       pxe_type_txt = argv[ optind + 1 ];
 
        /* Parse arguments */
        netdev = find_netdev ( netdev_txt );
@@ -164,10 +159,6 @@ static int pxebs_exec ( int argc, char **argv ) {
                printf ( "No such interface: %s\n", netdev_txt );
                return 1;
        }
-       if ( inet_aton ( pxe_server_txt, &pxe_server ) == 0 ) {
-               printf ( "Bad discovery IP address: %s\n", pxe_server_txt );
-               return 1;
-       }
        pxe_type = strtoul ( pxe_type_txt, &end, 0 );
        if ( *end ) {
                printf ( "Bad server type: %s\n", pxe_type_txt );
@@ -175,7 +166,7 @@ static int pxebs_exec ( int argc, char **argv ) {
        }
 
        /* Perform Boot Server Discovery */
-       if ( ( rc = pxebs ( netdev, pxe_server, pxe_type ) ) != 0 ) {
+       if ( ( rc = pxebs ( netdev, pxe_type ) ) != 0 ) {
                printf ( "Could not discover boot server on %s: %s\n",
                         netdev->name, strerror ( rc ) );
                return 1;
index 44edd64..33e0c5d 100644 (file)
@@ -100,6 +100,19 @@ enum dhcp_pxe_discovery_control {
 /** PXE boot server multicast address */
 #define DHCP_PXE_BOOT_SERVER_MCAST DHCP_ENCAP_OPT ( DHCP_VENDOR_ENCAP, 7 )
 
+/** PXE boot servers */
+#define DHCP_PXE_BOOT_SERVERS DHCP_ENCAP_OPT ( DHCP_VENDOR_ENCAP, 8 )
+
+/** PXE boot server */
+struct dhcp_pxe_boot_server {
+       /** "Type" */
+       uint16_t type;
+       /** Number of IPv4 addresses */
+       uint8_t num_ip;
+       /** IPv4 addresses */
+       struct in_addr ip[0];
+} __attribute__ (( packed ));
+
 /** PXE boot menu */
 #define DHCP_PXE_BOOT_MENU DHCP_ENCAP_OPT ( DHCP_VENDOR_ENCAP, 9 )
 
@@ -574,6 +587,9 @@ struct dhcphdr {
 /** Maximum time that we will wait for ProxyDHCP responses */
 #define PROXYDHCP_MAX_TIMEOUT ( 2 * TICKS_PER_SEC )
 
+/** Maximum time that we will wait for Boot Server responses */
+#define PXEBS_MAX_TIMEOUT ( 3 * TICKS_PER_SEC )
+
 /** Settings block name used for DHCP responses */
 #define DHCP_SETTINGS_NAME "dhcp"
 
@@ -593,6 +609,6 @@ extern int dhcp_create_request ( struct dhcp_packet *dhcppkt,
                                 void *data, size_t max_len );
 extern int start_dhcp ( struct job_interface *job, struct net_device *netdev );
 extern int start_pxebs ( struct job_interface *job, struct net_device *netdev,
-                        struct in_addr pxe_server, unsigned int pxe_type );
+                        unsigned int pxe_type );
 
 #endif /* _GPXE_DHCP_H */
index dc9de7b..0f27560 100644 (file)
@@ -10,7 +10,6 @@
 struct net_device;
 
 extern int dhcp ( struct net_device *netdev );
-extern int pxebs ( struct net_device *netdev, struct in_addr pxe_server,
-                  unsigned int pxe_type );
+extern int pxebs ( struct net_device *netdev, unsigned int pxe_type );
 
 #endif /* _USR_DHCPMGMT_H */
index 6ebf602..d149214 100644 (file)
@@ -175,11 +175,12 @@ struct dhcp_session_state {
         * @v dhcppkt           DHCP packet
         * @v peer              DHCP server address
         * @v msgtype           DHCP message type
+        * @v server_id         DHCP server ID
         */
        void ( * rx ) ( struct dhcp_session *dhcp,
                        struct dhcp_packet *dhcppkt,
                        struct sockaddr_in *peer,
-                       uint8_t msgtype );
+                       uint8_t msgtype, struct in_addr server_id );
        /** Handle timer expiry
         *
         * @v dhcp              DHCP session
@@ -226,10 +227,12 @@ struct dhcp_session {
        /** ProxyDHCP server priority */
        int proxy_priority;
 
-       /** PXE Boot Server */
-       struct in_addr pxe_server;
        /** PXE Boot Server type */
        uint16_t pxe_type;
+       /** List of PXE Boot Servers to attempt */
+       struct in_addr *pxe_attempt;
+       /** List of PXE Boot Servers to accept */
+       struct in_addr *pxe_accept;
 
        /** Retransmission timer */
        struct retry_timer timer;
@@ -322,11 +325,12 @@ static int dhcp_discovery_tx ( struct dhcp_session *dhcp,
  * @v dhcppkt          DHCP packet
  * @v peer             DHCP server address
  * @v msgtype          DHCP message type
+ * @v server_id                DHCP server ID
  */
 static void dhcp_discovery_rx ( struct dhcp_session *dhcp,
                                struct dhcp_packet *dhcppkt,
-                               struct sockaddr_in *peer, uint8_t msgtype ) {
-       struct in_addr server_id = { 0 };
+                               struct sockaddr_in *peer, uint8_t msgtype,
+                               struct in_addr server_id ) {
        struct in_addr ip;
        char vci[9]; /* "PXEClient" */
        int vci_len;
@@ -338,10 +342,6 @@ static void dhcp_discovery_rx ( struct dhcp_session *dhcp,
        DBGC ( dhcp, "DHCP %p %s from %s:%d", dhcp,
               dhcp_msgtype_name ( msgtype ), inet_ntoa ( peer->sin_addr ),
               ntohs ( peer->sin_port ) );
-
-       /* Identify server ID */
-       dhcppkt_fetch ( dhcppkt, DHCP_SERVER_IDENTIFIER,
-                       &server_id, sizeof ( server_id ) );
        if ( server_id.s_addr != peer->sin_addr.s_addr )
                DBGC ( dhcp, " (%s)", inet_ntoa ( server_id ) );
 
@@ -480,11 +480,12 @@ static int dhcp_request_tx ( struct dhcp_session *dhcp,
  * @v dhcppkt          DHCP packet
  * @v peer             DHCP server address
  * @v msgtype          DHCP message type
+ * @v server_id                DHCP server ID
  */
 static void dhcp_request_rx ( struct dhcp_session *dhcp,
                              struct dhcp_packet *dhcppkt,
-                             struct sockaddr_in *peer, uint8_t msgtype ) {
-       struct in_addr server_id = { 0 };
+                             struct sockaddr_in *peer, uint8_t msgtype,
+                             struct in_addr server_id ) {
        struct in_addr ip;
        struct settings *parent;
        int rc;
@@ -492,10 +493,6 @@ static void dhcp_request_rx ( struct dhcp_session *dhcp,
        DBGC ( dhcp, "DHCP %p %s from %s:%d", dhcp,
               dhcp_msgtype_name ( msgtype ), inet_ntoa ( peer->sin_addr ),
               ntohs ( peer->sin_port ) );
-
-       /* Identify server ID */
-       dhcppkt_fetch ( dhcppkt, DHCP_SERVER_IDENTIFIER,
-                       &server_id, sizeof ( server_id ) );
        if ( server_id.s_addr != peer->sin_addr.s_addr )
                DBGC ( dhcp, " (%s)", inet_ntoa ( server_id ) );
 
@@ -591,20 +588,17 @@ static int dhcp_proxy_tx ( struct dhcp_session *dhcp,
  * @v dhcppkt          DHCP packet
  * @v peer             DHCP server address
  * @v msgtype          DHCP message type
+ * @v server_id                DHCP server ID
  */
 static void dhcp_proxy_rx ( struct dhcp_session *dhcp,
                            struct dhcp_packet *dhcppkt,
-                           struct sockaddr_in *peer, uint8_t msgtype ) {
-       struct in_addr server_id = { 0 };
+                           struct sockaddr_in *peer, uint8_t msgtype,
+                           struct in_addr server_id ) {
        int rc;
 
        DBGC ( dhcp, "DHCP %p %s from %s:%d", dhcp,
               dhcp_msgtype_name ( msgtype ), inet_ntoa ( peer->sin_addr ),
               ntohs ( peer->sin_port ) );
-
-       /* Identify server ID */
-       dhcppkt_fetch ( dhcppkt, DHCP_SERVER_IDENTIFIER,
-                       &server_id, sizeof ( server_id ) );
        if ( server_id.s_addr != peer->sin_addr.s_addr )
                DBGC ( dhcp, " (%s)", inet_ntoa ( server_id ) );
        DBGC ( dhcp, "\n" );
@@ -673,7 +667,7 @@ static int dhcp_pxebs_tx ( struct dhcp_session *dhcp,
        int rc;
 
        DBGC ( dhcp, "DHCP %p PXEBS REQUEST to %s:%d for type %d\n",
-              dhcp, inet_ntoa ( dhcp->pxe_server ), PXE_PORT,
+              dhcp, inet_ntoa ( *(dhcp->pxe_attempt) ), PXE_PORT,
               ntohs ( dhcp->pxe_type ) );
 
        /* Set boot menu item */
@@ -683,12 +677,38 @@ static int dhcp_pxebs_tx ( struct dhcp_session *dhcp,
                return rc;
 
        /* Set server address */
-       peer->sin_addr = dhcp->pxe_server;
+       peer->sin_addr = *(dhcp->pxe_attempt);
        peer->sin_port = htons ( PXE_PORT );
 
        return 0;
 }
 
+/**
+ * Check to see if PXE Boot Server address is acceptable
+ *
+ * @v dhcp             DHCP session
+ * @v bs               Boot Server address
+ * @ret accept         Boot Server is acceptable
+ */
+static int dhcp_pxebs_accept ( struct dhcp_session *dhcp,
+                              struct in_addr bs ) {
+       struct in_addr *accept;
+
+       /* Accept if we have no acceptance filter */
+       if ( ! dhcp->pxe_accept )
+               return 1;
+
+       /* Scan through acceptance list */
+       for ( accept = dhcp->pxe_accept ; accept->s_addr ; accept++ ) {
+               if ( accept->s_addr == bs.s_addr )
+                       return 1;
+       }
+
+       DBGC ( dhcp, "DHCP %p rejecting server %s\n",
+              dhcp, inet_ntoa ( bs ) );
+       return 0;
+}
+
 /**
  * Handle received packet during PXE Boot Server Discovery
  *
@@ -696,16 +716,20 @@ static int dhcp_pxebs_tx ( struct dhcp_session *dhcp,
  * @v dhcppkt          DHCP packet
  * @v peer             DHCP server address
  * @v msgtype          DHCP message type
+ * @v server_id                DHCP server ID
  */
 static void dhcp_pxebs_rx ( struct dhcp_session *dhcp,
                            struct dhcp_packet *dhcppkt,
-                           struct sockaddr_in *peer, uint8_t msgtype ) {
+                           struct sockaddr_in *peer, uint8_t msgtype,
+                           struct in_addr server_id ) {
        struct dhcp_pxe_boot_menu_item menu_item = { 0, 0 };
        int rc;
 
        DBGC ( dhcp, "DHCP %p %s from %s:%d", dhcp,
               dhcp_msgtype_name ( msgtype ), inet_ntoa ( peer->sin_addr ),
               ntohs ( peer->sin_port ) );
+       if ( server_id.s_addr != peer->sin_addr.s_addr )
+               DBGC ( dhcp, " (%s)", inet_ntoa ( server_id ) );
 
        /* Identify boot menu item */
        dhcppkt_fetch ( dhcppkt, DHCP_PXE_BOOT_MENU_ITEM,
@@ -721,6 +745,9 @@ static void dhcp_pxebs_rx ( struct dhcp_session *dhcp,
                return;
        if ( menu_item.type != dhcp->pxe_type )
                return;
+       if ( ! dhcp_pxebs_accept ( dhcp, ( server_id.s_addr ?
+                                          server_id : peer->sin_addr ) ) )
+               return;
 
        /* Register settings */
        dhcppkt->settings.name = PXEBS_SETTINGS_NAME;
@@ -741,6 +768,21 @@ static void dhcp_pxebs_rx ( struct dhcp_session *dhcp,
  * @v dhcp             DHCP session
  */
 static void dhcp_pxebs_expired ( struct dhcp_session *dhcp ) {
+       unsigned long elapsed = ( currticks() - dhcp->start );
+
+       /* Give up waiting before we reach the failure point, and fail
+        * over to the next server in the attempt list
+        */
+       if ( elapsed > PXEBS_MAX_TIMEOUT ) {
+               dhcp->pxe_attempt++;
+               if ( dhcp->pxe_attempt->s_addr ) {
+                       dhcp_set_state ( dhcp, &dhcp_state_pxebs );
+                       return;
+               } else {
+                       dhcp_finished ( dhcp, -ETIMEDOUT );
+                       return;
+               }
+       }
 
        /* Retransmit current packet */
        dhcp_tx ( dhcp );
@@ -1006,6 +1048,7 @@ static int dhcp_deliver_iob ( struct xfer_interface *xfer,
        struct dhcp_packet *dhcppkt;
        struct dhcphdr *dhcphdr;
        uint8_t msgtype = 0;
+       struct in_addr server_id = { 0 };
        int rc = 0;
 
        /* Sanity checks */
@@ -1042,6 +1085,10 @@ static int dhcp_deliver_iob ( struct xfer_interface *xfer,
        dhcppkt_fetch ( dhcppkt, DHCP_MESSAGE_TYPE, &msgtype,
                        sizeof ( msgtype ) );
 
+       /* Identify server ID */
+       dhcppkt_fetch ( dhcppkt, DHCP_SERVER_IDENTIFIER,
+                       &server_id, sizeof ( server_id ) );
+
        /* Check for matching transaction ID */
        if ( dhcphdr->xid != dhcp_xid ( dhcp->netdev ) ) {
                DBGC ( dhcp, "DHCP %p %s from %s:%d has bad transaction "
@@ -1053,7 +1100,7 @@ static int dhcp_deliver_iob ( struct xfer_interface *xfer,
        };
 
        /* Handle packet based on current state */
-       dhcp->state->rx ( dhcp, dhcppkt, peer, msgtype );
+       dhcp->state->rx ( dhcp, dhcppkt, peer, msgtype, server_id );
 
  err_xid:
        dhcppkt_put ( dhcppkt );
@@ -1183,12 +1230,50 @@ int start_dhcp ( struct job_interface *job, struct net_device *netdev ) {
        return rc;
 }
 
+/**
+ * Retrieve list of PXE boot servers for a given server type
+ *
+ * @v dhcp             DHCP session
+ * @v raw              DHCP PXE boot server list
+ * @v raw_len          Length of DHCP PXE boot server list
+ * @v ip               IP address list to fill in
+ *
+ * The caller must ensure that the IP address list has sufficient
+ * space.
+ */
+static void pxebs_list ( struct dhcp_session *dhcp, void *raw,
+                        size_t raw_len, struct in_addr *ip ) {
+       struct dhcp_pxe_boot_server *server = raw;
+       size_t server_len;
+       unsigned int i;
+
+       while ( raw_len ) {
+               if ( raw_len < sizeof ( *server ) ) {
+                       DBGC ( dhcp, "DHCP %p malformed PXE server list\n",
+                              dhcp );
+                       break;
+               }
+               server_len = offsetof ( typeof ( *server ),
+                                       ip[ server->num_ip ] );
+               if ( raw_len < server_len ) {
+                       DBGC ( dhcp, "DHCP %p malformed PXE server list\n",
+                              dhcp );
+                       break;
+               }
+               if ( server->type == dhcp->pxe_type ) {
+                       for ( i = 0 ; i < server->num_ip ; i++ )
+                               *(ip++) = server->ip[i];
+               }
+               server = ( ( ( void * ) server ) + server_len );
+               raw_len -= server_len;
+       }
+}
+
 /**
  * Start PXE Boot Server Discovery on a network device
  *
  * @v job              Job control interface
  * @v netdev           Network device
- * @v pxe_server       PXE server (may be a multicast address)
  * @v pxe_type         PXE server type
  * @ret rc             Return status code
  *
@@ -1197,12 +1282,28 @@ int start_dhcp ( struct job_interface *job, struct net_device *netdev ) {
  * source.
  */
 int start_pxebs ( struct job_interface *job, struct net_device *netdev,
-                 struct in_addr pxe_server, unsigned int pxe_type ) {
+                 unsigned int pxe_type ) {
+       struct setting pxe_discovery_control_setting =
+               { .tag = DHCP_PXE_DISCOVERY_CONTROL };
+       struct setting pxe_boot_servers_setting =
+               { .tag = DHCP_PXE_BOOT_SERVERS };
+       struct setting pxe_boot_server_mcast_setting =
+               { .tag = DHCP_PXE_BOOT_SERVER_MCAST };
+       ssize_t pxebs_list_len;
        struct dhcp_session *dhcp;
+       struct in_addr *ip;
+       unsigned int pxe_discovery_control;
        int rc;
 
+       /* Get upper bound for PXE boot server IP address list */
+       pxebs_list_len = fetch_setting_len ( NULL, &pxe_boot_servers_setting );
+       if ( pxebs_list_len < 0 )
+               pxebs_list_len = 0;
+
        /* Allocate and initialise structure */
-       dhcp = zalloc ( sizeof ( *dhcp ) );
+       dhcp = zalloc ( sizeof ( *dhcp ) + sizeof ( *ip ) /* mcast */ +
+                       sizeof ( *ip ) /* bcast */ + pxebs_list_len +
+                       sizeof ( *ip ) /* terminator */ );
        if ( ! dhcp )
                return -ENOMEM;
        dhcp->refcnt.free = dhcp_free;
@@ -1213,10 +1314,49 @@ int start_pxebs ( struct job_interface *job, struct net_device *netdev,
        fetch_ipv4_setting ( netdev_settings ( netdev ), &ip_setting,
                             &dhcp->local.sin_addr );
        dhcp->local.sin_port = htons ( BOOTPC_PORT );
-       dhcp->pxe_server = pxe_server;
        dhcp->pxe_type = htons ( pxe_type );
        dhcp->timer.expired = dhcp_timer_expired;
 
+       /* Construct PXE boot server IP address lists */
+       pxe_discovery_control =
+               fetch_uintz_setting ( NULL, &pxe_discovery_control_setting );
+       ip = ( ( ( void * ) dhcp ) + sizeof ( *dhcp ) );
+       dhcp->pxe_attempt = ip;
+       if ( ! ( pxe_discovery_control & PXEBS_NO_MULTICAST ) ) {
+               fetch_ipv4_setting ( NULL, &pxe_boot_server_mcast_setting, ip);
+               if ( ip->s_addr )
+                       ip++;
+       }
+       if ( ! ( pxe_discovery_control & PXEBS_NO_BROADCAST ) )
+               (ip++)->s_addr = INADDR_BROADCAST;
+       if ( pxe_discovery_control & PXEBS_NO_UNKNOWN_SERVERS )
+               dhcp->pxe_accept = ip;
+       if ( pxebs_list_len ) {
+               uint8_t buf[pxebs_list_len];
+
+               fetch_setting ( NULL, &pxe_boot_servers_setting,
+                               buf, sizeof ( buf ) );
+               pxebs_list ( dhcp, buf, sizeof ( buf ), ip );
+       }
+       if ( ! dhcp->pxe_attempt->s_addr ) {
+               DBGC ( dhcp, "DHCP %p has no PXE boot servers for type %04x\n",
+                      dhcp, pxe_type );
+               rc = -EINVAL;
+               goto err;
+       }
+
+       /* Dump out PXE server lists */
+       DBGC ( dhcp, "DHCP %p attempting", dhcp );
+       for ( ip = dhcp->pxe_attempt ; ip->s_addr ; ip++ )
+               DBGC ( dhcp, " %s", inet_ntoa ( *ip ) );
+       DBGC ( dhcp, "\n" );
+       if ( dhcp->pxe_accept ) {
+               DBGC ( dhcp, "DHCP %p accepting", dhcp );
+               for ( ip = dhcp->pxe_accept ; ip->s_addr ; ip++ )
+                       DBGC ( dhcp, " %s", inet_ntoa ( *ip ) );
+               DBGC ( dhcp, "\n" );
+       }
+
        /* Instantiate child objects and attach to our interfaces */
        if ( ( rc = xfer_open_socket ( &dhcp->xfer, SOCK_DGRAM, &dhcp_peer,
                                  ( struct sockaddr * ) &dhcp->local ) ) != 0 )
index c68808b..6acf7f6 100644 (file)
@@ -47,15 +47,12 @@ int dhcp ( struct net_device *netdev ) {
        return rc;
 }
 
-int pxebs ( struct net_device *netdev, struct in_addr pxe_server,
-           unsigned int pxe_type ) {
+int pxebs ( struct net_device *netdev, unsigned int pxe_type ) {
        int rc;
 
        /* Perform PXE Boot Server Discovery */
-       printf ( "PXEBS (%s %s type %d)",
-                netdev->name, inet_ntoa ( pxe_server ), pxe_type );
-       if ( ( rc = start_pxebs ( &monojob, netdev, pxe_server,
-                                 pxe_type ) ) == 0 )
+       printf ( "PXEBS (%s type %d)", netdev->name, pxe_type );
+       if ( ( rc = start_pxebs ( &monojob, netdev, pxe_type ) ) == 0 )
                rc = monojob_wait ( "" );
 
        return rc;
index ae97108..4cc40a6 100644 (file)
@@ -57,8 +57,6 @@ struct pxe_menu_item {
  * options.
  */
 struct pxe_menu {
-       /** Boot Server address */
-       struct in_addr server;
        /** Timeout (in seconds)
         *
         * Negative indicates no timeout (i.e. wait indefinitely)
@@ -83,7 +81,6 @@ struct pxe_menu {
  */
 static int pxe_menu_parse ( struct pxe_menu **menu ) {
        struct setting tmp_setting = { .name = NULL };
-       struct in_addr server;
        struct dhcp_pxe_boot_menu_prompt prompt = { .timeout = 0 };
        uint8_t raw_menu[256];
        int raw_menu_len;
@@ -94,10 +91,6 @@ static int pxe_menu_parse ( struct pxe_menu **menu ) {
        int rc;
 
        /* Fetch relevant settings */
-       tmp_setting.tag = DHCP_PXE_BOOT_SERVER_MCAST;
-       fetch_ipv4_setting ( NULL, &tmp_setting, &server );
-       if ( ! server.s_addr )
-               server.s_addr = INADDR_BROADCAST;
        tmp_setting.tag = DHCP_PXE_BOOT_MENU_PROMPT;
        fetch_setting ( NULL, &tmp_setting, &prompt, sizeof ( prompt ) );
        tmp_setting.tag = DHCP_PXE_BOOT_MENU;
@@ -142,7 +135,6 @@ static int pxe_menu_parse ( struct pxe_menu **menu ) {
        }
 
        /* Fill in parsed menu */
-       (*menu)->server = server;
        (*menu)->timeout =
                ( ( prompt.timeout == 0xff ) ? -1 : prompt.timeout );
        (*menu)->num_items = num_menu_items;
@@ -296,7 +288,6 @@ int pxe_menu_select ( struct pxe_menu *menu ) {
  */
 int pxe_menu_boot ( struct net_device *netdev ) {
        struct pxe_menu *menu;
-       struct in_addr pxe_server;
        unsigned int pxe_type;
        struct settings *pxebs_settings;
        struct in_addr next_server;
@@ -312,7 +303,6 @@ int pxe_menu_boot ( struct net_device *netdev ) {
                free ( menu );
                return rc;
        }
-       pxe_server = menu->server;
        pxe_type = menu->items[menu->selection].type;
 
        /* Free boot menu */
@@ -323,7 +313,7 @@ int pxe_menu_boot ( struct net_device *netdev ) {
                return 0;
 
        /* Attempt PXE Boot Server Discovery */
-       if ( ( rc = pxebs ( netdev, pxe_server, pxe_type ) ) != 0 )
+       if ( ( rc = pxebs ( netdev, pxe_type ) ) != 0 )
                return rc;
 
        /* Attempt boot */