[Dnsmasq-discuss] ProxyDHCP with UEFI systems

Michael Kuron michael-lists at physcip.uni-stuttgart.de
Sat Oct 24 15:51:07 BST 2015


Actually, I shouldn’t set the siaddr in the initial Offer. It’s fine for VMware UEFI and BIOS, but the Asus UEFI will end up trying to download the boot file from the Offer’s siaddr instead of the ACK’s siaddr if it’s present. So the small additional modification below will also allow the TFTP server to be on a different machine than the proxy DHCP server.

--- a/src/rfc2131.c
+++ b/src/rfc2131.c
@@ -898,9 +898,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
 					if (pxearch == service->CSA && match_netid(service->netid, netid, 1))
 						++num_services;
 				
-				if (num_services == 1 && !pxe)
-					mess->siaddr = tmp->local;
-				else if (num_services == 1)
+				if (num_services == 1 && pxe)
 				{
 					for (service = daemon->pxe_services; service; service = service->next)
 						if (pxearch == service->CSA && match_netid(service->netid, netid, 1))


> On 24.10.2015, at 15:21, Michael Kuron <michael-lists at PHYSCIP.UNI-STUTTGART.DE> wrote:
> 
> More wiresharking helped me figure this out. So when UEFI receives a DHCP Offer or Proxy DHCP Offer with Vendor Class Identifier (option 60) set to PXEClient, it sends a DHCP Request to the siaddr from the offer, but on port 4011. If the server then sends a DHCP ACK back to port 4011, containing an siaddr and file name, that file is then booted. The PXE menu system does not appear to be supported by UEFI.
> 
> So here’s a new patch. It does two things if there is only one applicable --pxe-service specified:
> - If it receives a Discover on port 68 with a Vendor class identifier equal to PXEClient, it sets the siaddr in the Offer to the local address.
> - If it receives a Request on port 4011 with a Vendor class identifier equal to PXEClient, it sets the siaddr and file as specified using the --pxe-service option.
> 
> This is actually working for me with VMware Fusion 8 and with a recent Asus laptop. This is also backwards compatible with BIOS PXE booting (the port 4011 stuff was specified a long time ago).
> 
> Regards,
> Michael
> 
> 
> 
> diff --git a/src/rfc2131.c b/src/rfc2131.c
> index 9f69ed5..32f18d1 100644
> --- a/src/rfc2131.c
> +++ b/src/rfc2131.c
> @@ -859,6 +859,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
> 	      
> 	      if (tmp)
> 		{
> +		  int num_services = 0;
> 		  struct dhcp_boot *boot;
> 		  
> 		  if (tmp->netid.net)
> @@ -890,13 +891,44 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
> 		      if (boot->file)
> 			strncpy((char *)mess->file, boot->file, sizeof(mess->file)-1);
> 		    }
> +		  else
> +		    {
> +				struct pxe_service *service;
> +				for (service = daemon->pxe_services; service; service = service->next)
> +					if (pxearch == service->CSA && match_netid(service->netid, netid, 1))
> +						++num_services;
> +				
> +				if (num_services == 1 && !pxe)
> +					mess->siaddr = tmp->local;
> +				else if (num_services == 1)
> +				{
> +					for (service = daemon->pxe_services; service; service = service->next)
> +						if (pxearch == service->CSA && match_netid(service->netid, netid, 1))
> +					{
> +						if (service->sname)
> +							mess->siaddr = a_record_from_hosts(service->sname, now);
> +						else if (service->server.s_addr != 0)
> +							mess->siaddr = service->server; 
> +						else
> +							mess->siaddr = tmp->local;
> +						
> +						if (service->CSA == 0)
> +							snprintf((char *)mess->file, sizeof(mess->file), "%s.0", service->basename);
> +						else if (service->CSA == 6 || service->CSA == 7 || service->CSA == 8 || service->CSA == 9)
> +							snprintf((char *)mess->file, sizeof(mess->file), "%s.efi", service->basename);
> +						else
> +							strncpy((char *)mess->file, service->basename, sizeof(mess->file)-1);
> +					}
> +				}
> +		    }
> 		  
> 		  option_put(mess, end, OPTION_MESSAGE_TYPE, 1, 
> 			     mess_type == DHCPDISCOVER ? DHCPOFFER : DHCPACK);
> 		  option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, htonl(tmp->local.s_addr));
> 		  pxe_misc(mess, end, uuid);
> 		  prune_vendor_opts(tagif_netid);
> -		  do_encap_opts(pxe_opts(pxearch, tagif_netid, tmp->local, now), OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0);
> +		  if (num_services != 1)
> +		    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);
> 		  log_tags(tagif_netid, ntohl(mess->xid));
> 
> 
> 
> _______________________________________________
> Dnsmasq-discuss mailing list
> Dnsmasq-discuss at lists.thekelleys.org.uk
> http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss




More information about the Dnsmasq-discuss mailing list