I have included a patch below that makes essentially two modifications to get 
PXE working with the UEFI firmware in VMware.
- It only appends the layer number to the file name on BIOS x86.
- It always redirects the client to port 4011. To do that, only the siaddr is 
set and neither a boot file nor a PXE menu are included in the Offer sent upon 
receiving the Discover. In reaction to the ACK it then sends an ACK which 
includes either the single boot file name and server, or the PXE menu.

This patch works to the same degree as my patch did. VMware boots fine with a 
single boot service, and the menu also works if you specify multiple, however 
you have to blindly navigate the menu because it is not shown on screen.

Michael


--- a/src/rfc2131.c
+++ b/src/rfc2131.c
@@ -63,7 +63,7 @@ static void pxe_misc(struct dhcp_packet *mess, unsigned char 
*end, unsigned char
 static int prune_vendor_opts(struct dhcp_netid *netid);
 static struct dhcp_opt *pxe_opts(int pxe_arch, struct dhcp_netid *netid, 
struct in_addr local, time_t now);
 struct dhcp_boot *find_boot(struct dhcp_netid *netid);
-static int pxe_uefi_workaround(int pxe_arch, struct dhcp_netid *netid, struct 
dhcp_packet *mess, struct in_addr local, time_t now);
+static int pxe_uefi_workaround(int pxe_arch, struct dhcp_netid *netid, struct 
dhcp_packet *mess, struct in_addr local, time_t now, int pxe);
   
 size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int 
int_index,
                  size_t sz, time_t now, int unicast_dest, int *is_inform, int 
pxe, struct in_addr fallback)
@@ -824,7 +824,10 @@ size_t dhcp_reply(struct dhcp_context *context, char 
*iface_name, int int_index,
          else
            mess->siaddr = context->local; 
          
-         snprintf((char *)mess->file, sizeof(mess->file), "%s.%d", 
service->basename, layer);
+         if (pxearch == 0)
+             snprintf((char *)mess->file, sizeof(mess->file), "%s.%d", 
service->basename, layer);
+         else
+             strncpy((char *)mess->file, service->basename, 
sizeof(mess->file));
          option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
          option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, 
htonl(context->local.s_addr));
          pxe_misc(mess, end, uuid);
@@ -879,11 +882,10 @@ size_t dhcp_reply(struct dhcp_context *context, char 
*iface_name, int int_index,
                  
                  clear_packet(mess, end);
                  
-                 /* Only do workaround for replies to 4011 */
-                 if (!pxe)
-                   mess->siaddr = tmp->local;
-                 else 
-                   workaround = pxe_uefi_workaround(pxearch, tagif_netid, 
mess, tmp->local, now);
+                 /* Redirect the client to port 4011 */
+                 mess->siaddr = tmp->local;
+                 /* Returns true if only one matching service is available. On 
port 4011, it also inserts the boot file and server name. */
+                 workaround = pxe_uefi_workaround(pxearch, tagif_netid, mess, 
tmp->local, now, pxe);
                  
                  if (!workaround && boot)
                    {
@@ -903,7 +905,7 @@ size_t dhcp_reply(struct dhcp_context *context, char 
*iface_name, int int_index,
                  option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, 
htonl(tmp->local.s_addr));
                  pxe_misc(mess, end, uuid);
                  prune_vendor_opts(tagif_netid);
-                 if (!workaround)
+                 if (pxe && !workaround)
                    do_encap_opts(pxe_opts(pxearch, tagif_netid, tmp->local, 
now), OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0);
            
                  log_packet("PXE", NULL, emac, emac_len, iface_name, ignore ? 
"proxy-ignored" : "proxy", NULL, mess->xid);
@@ -1989,7 +1991,7 @@ static int prune_vendor_opts(struct dhcp_netid *netid)
    and jamb the data direct into the DHCP file, siaddr and sname fields.
    Note that in this case, we have to assume that layer zero would be requested
    by the client PXE stack. */
-static int pxe_uefi_workaround(int pxe_arch, struct dhcp_netid *netid, struct 
dhcp_packet *mess, struct in_addr local, time_t now)
+static int pxe_uefi_workaround(int pxe_arch, struct dhcp_netid *netid, struct 
dhcp_packet *mess, struct in_addr local, time_t now, int pxe)
 {
   struct pxe_service *service, *found;
 
@@ -2009,6 +2011,9 @@ static int pxe_uefi_workaround(int pxe_arch, struct 
dhcp_netid *netid, struct dh
   if (!found)
     return 0; /* No relevant menu items. */
   
+  if (!pxe)
+     return 1;
+  
   if (found->sname)
     {
       mess->siaddr = a_record_from_hosts(found->sname, now);
@@ -2024,7 +2029,10 @@ static int pxe_uefi_workaround(int pxe_arch, struct 
dhcp_netid *netid, struct dh
       inet_ntop(AF_INET, &mess->siaddr, (char *)mess->sname, INET_ADDRSTRLEN);
     }
   
-  snprintf((char *)mess->file, sizeof(mess->file), "%s.0", found->basename);
+  if (pxe_arch == 0)
+      snprintf((char *)mess->file, sizeof(mess->file), "%s.0", 
service->basename);
+  else
+      strncpy((char *)mess->file, found->basename, sizeof(mess->file));
 
   return 1;
 }
@@ -2563,7 +2571,7 @@ static void do_options(struct dhcp_context *context,
   if (context && pxe_arch != -1)
     {
       pxe_misc(mess, end, uuid);
-      if (!pxe_uefi_workaround(pxe_arch, tagif, mess, context->local, now))
+      if (!pxe_uefi_workaround(pxe_arch, tagif, mess, context->local, now, 0))
        config_opts = pxe_opts(pxe_arch, tagif, context->local, now);
     }


_______________________________________________
Dnsmasq-discuss mailing list
Dnsmasq-discuss@lists.thekelleys.org.uk
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss

Reply via email to