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