This patch adds the ability to specify a different boot_file for each 
client. This is useful if clients have different CPU architectures or if 
some clients are legacy BIOS and some are EFI.

It adds a config file option of the form 
"for xx:xx:xx:xx:xx:xx boot_file foo" which sets the boot_file to "foo" 
for the client with the MAC address xx:xx:xx:xx:xx:xx. If no such line 
exists, the global boot_file will be used. The syntax of the option is 
intended so that in the future, per-client options other than boot_file 
could be added.


--- networking/udhcp/dhcpd.h.orig       2023-01-03 06:17:01.000000000 -0800
+++ networking/udhcp/dhcpd.h    2023-04-16 00:56:09.000000000 -0700
@@ -16,6 +16,7 @@
 
 
 struct static_lease;
+struct boot_file_override;
 
 struct server_data_t {
        char *interface;                /* interface to use */
@@ -51,6 +52,7 @@
        char *sname;                    /* bootp server name */
        char *boot_file;                /* bootp boot file option */
        struct static_lease *static_leases; /* List of ip/mac pairs to assign 
static leases */
+       struct boot_file_override *boot_file_overrides; /* Boot files for 
specific clients */
 } FIX_ALIASING;
 
 #define server_data (*(struct server_data_t*)bb_common_bufsiz1)
--- networking/udhcp/dhcpd.c.orig       2023-01-03 06:17:01.000000000 -0800
+++ networking/udhcp/dhcpd.c    2023-05-28 17:13:51.000000000 -0700
@@ -63,6 +63,12 @@
        uint8_t opt[1];
 };
 
+struct boot_file_override {
+       struct boot_file_override *next;
+       char *boot_file;
+       uint8_t mac[6];
+};
+
 /* Takes the address of the pointer to the static_leases linked list,
  * address to a 6 byte mac address,
  * 4 byte IP address */
@@ -105,6 +111,33 @@
 #endif
 }
 
+static void add_boot_file_override(struct boot_file_override **bfo_pp,
+               uint8_t *mac,
+               const char *boot_file)
+{
+       struct boot_file_override *bfo;
+
+       /* Find the tail of the list */
+       while ((bfo = *bfo_pp) != NULL) {
+               bfo_pp = &bfo->next;
+       }
+
+       /* Add new node */
+       *bfo_pp = bfo = xzalloc(sizeof(*bfo));
+       memcpy(bfo->mac, mac, 6);
+       bfo->boot_file = strdup(boot_file);
+
+#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 2
+       if (dhcp_verbose >= 2) {
+               bb_info_msg("boot file override: 
mac:%02x:%02x:%02x:%02x:%02x:%02x boot_file:%s",
+                       bfo->mac[0], bfo->mac[1], bfo->mac[2],
+                       bfo->mac[3], bfo->mac[4], bfo->mac[5],
+                       bfo->boot_file
+               );
+       }
+#endif
+}
+
 /* Find static lease IP by mac */
 static uint32_t get_static_nip_by_mac(void *mac)
 {
@@ -380,6 +413,33 @@
        return 1;
 }
 
+static int FAST_FUNC read_bfo(const char *const_line, void *arg)
+{
+       char *line;
+       char *mac_string;
+       char *specifier;
+       struct ether_addr mac_bytes;
+       char *boot_file;
+
+       /* Read mac */
+       line = (char *) const_line;
+       mac_string = strtok_r(line, " \t", &line);
+       if (!mac_string || !ether_aton_r(mac_string, &mac_bytes))
+               return 0;
+
+       specifier = strtok_r(NULL, " \t", &line);
+       if (!specifier || strcasecmp(specifier, "boot_file")!=0)
+               return 0;
+
+       boot_file = strtok_r(NULL, " \t", &line);
+       if (!boot_file)
+               return 0;
+
+       add_boot_file_override(arg, (uint8_t*) &mac_bytes, boot_file);
+
+       return 1;
+}
+
 static int FAST_FUNC read_optset(const char *line, void *arg)
 {
        return udhcp_str2optset(line, arg,
@@ -420,6 +480,7 @@
        {"sname"        , read_str        , OFS(sname        ), NULL},
        {"boot_file"    , read_str        , OFS(boot_file    ), NULL},
        {"static_lease" , read_staticlease, OFS(static_leases), ""},
+       {"for"          , read_bfo        , OFS(boot_file_overrides), ""},
 };
 enum { KWS_WITH_DEFAULTS = ARRAY_SIZE(keywords) - 6 };
 
@@ -659,6 +720,7 @@
 {
        struct option_set *config_opts;
        uint8_t *client_hostname_opt;
+       char *boot_file;
 
        client_hostname_opt = NULL;
        if (packet->yiaddr) { /* if we aren't from send_inform()... */
@@ -704,8 +766,21 @@
 
        if (server_data.sname)
                strncpy((char*)packet->sname, server_data.sname, 
sizeof(packet->sname) - 1);
-       if (server_data.boot_file)
-               strncpy((char*)packet->file, server_data.boot_file, 
sizeof(packet->file) - 1);
+
+       boot_file = server_data.boot_file;
+       if (packet->yiaddr) { /* if we aren't from send_inform()... */
+               struct boot_file_override *bfo = 
server_data.boot_file_overrides;
+               while (bfo) {
+                       if (memcmp(bfo->mac, packet->chaddr, 6) == 0) {
+                               boot_file = bfo->boot_file;
+                               break;
+                       }
+                       bfo = bfo->next;
+               }
+       }
+
+       if (boot_file)
+               strncpy((char*)packet->file, boot_file, sizeof(packet->file) - 
1);
 }
 
 static uint32_t select_lease_time(struct dhcp_packet *packet)
--- examples/udhcp/udhcpd.conf.orig     2023-05-28 17:17:10.000000000 -0700
+++ examples/udhcp/udhcpd.conf  2023-05-28 17:30:19.000000000 -0700
@@ -61,6 +61,11 @@
 #static_lease 00:60:08:11:CE:4E 192.168.0.54
 #static_lease 00:60:08:11:CE:3E 192.168.0.44 optional_hostname
 
+# The boot_file can be specified on a client-by-client basis. If there is
+# no matching "for" line for a client, the global boot_file will be used.
+#for 12:34:56:78:90:00 boot_file syslinux32.efi
+#for 98:76:54:32:10:00 boot_file syslinux64.efi
+
 # The remainder of options are DHCP options and can be specified with the
 # keyword 'opt' or 'option'. If an option can take multiple items, such
 # as the dns option, they can be listed on the same line, or multiple

_______________________________________________
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox

Reply via email to