#notify_file # default: no script
#notify_file dumpleases # useful for debugging
-# The following are bootp specific options
+# The following are BOOTP specific options
# next server to use in bootstrap
#siaddr 192.168.0.22 # default: 0.0.0.0 (none)
# tftp server name
# tftp file to download (e.g. kernel image)
#boot_file /var/nfs_root # default: none
+# NOTE: "boot_file FILE" and "opt bootfile FILE" are conceptually the same,
+# but "boot_file" goes into BOOTP-defined fixed-size field in the packet,
+# whereas "opt bootfile" goes into DHCP option 0x43.
+# Same for "sname HOST" and "opt tftp HOST".
+
# Static leases map
#static_lease 00:60:08:11:CE:4E 192.168.0.54
-#static_lease 00:60:08:11:CE:3E 192.168.0.44
+#static_lease 00:60:08:11:CE:3E 192.168.0.44 optional_hostname
# 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
#define g_leases ((struct dyn_lease*)ptr_to_globals)
/* struct server_config_t server_config is in bb_common_bufsiz1 */
+struct static_lease {
+ struct static_lease *next;
+ uint32_t nip;
+ uint8_t mac[6];
+ uint8_t opt[1];
+};
+
/* Takes the address of the pointer to the static_leases linked list,
* address to a 6 byte mac address,
* 4 byte IP address */
static void add_static_lease(struct static_lease **st_lease_pp,
uint8_t *mac,
- uint32_t nip)
+ uint32_t nip,
+ const char *opts)
{
struct static_lease *st_lease;
+ unsigned optlen;
/* Find the tail of the list */
while ((st_lease = *st_lease_pp) != NULL) {
}
/* Add new node */
- *st_lease_pp = st_lease = xzalloc(sizeof(*st_lease));
+ optlen = (opts ? 1+1+strnlen(opts, 120) : 0);
+ *st_lease_pp = st_lease = xzalloc(sizeof(*st_lease) + optlen);
memcpy(st_lease->mac, mac, 6);
st_lease->nip = nip;
/*st_lease->next = NULL;*/
+ if (optlen) {
+ st_lease->opt[OPT_CODE] = DHCP_HOST_NAME;
+ optlen -= 2;
+ st_lease->opt[OPT_LEN] = optlen;
+ memcpy(&st_lease->opt[OPT_DATA], opts, optlen);
+ }
}
/* Find static lease IP by mac */
char *line;
char *mac_string;
char *ip_string;
+ char *opts;
struct ether_addr mac_bytes; /* it's "struct { uint8_t mac[6]; }" */
uint32_t nip;
if (!ip_string || !udhcp_str2nip(ip_string, &nip))
return 0;
- add_static_lease(arg, (uint8_t*) &mac_bytes, nip);
+ opts = strtok_r(NULL, " \t", &line);
+ /* opts might be NULL, that's not an error */
+
+ add_static_lease(arg, (uint8_t*) &mac_bytes, nip, opts);
log_static_leases(arg);
*/
static void add_server_options(struct dhcp_packet *packet)
{
- struct option_set *curr = server_config.options;
+ struct option_set *config_opts;
+ uint8_t *client_hostname_opt;
+
+ client_hostname_opt = NULL;
+ if (packet->yiaddr) { /* if we aren't from send_inform()... */
+ struct static_lease *st_lease = server_config.static_leases;
+ while (st_lease) {
+ if (st_lease->nip == packet->yiaddr) {
+ if (st_lease->opt[0] != 0)
+ client_hostname_opt = st_lease->opt;
+ break;
+ }
+ st_lease = st_lease->next;
+ }
+ }
- while (curr) {
- if (curr->data[OPT_CODE] != DHCP_LEASE_TIME)
- udhcp_add_binary_option(packet, curr->data);
- curr = curr->next;
+ config_opts = server_config.options;
+ while (config_opts) {
+ if (config_opts->data[OPT_CODE] != DHCP_LEASE_TIME) {
+ /* ^^^^
+ * DHCP_LEASE_TIME is already filled, or in case of
+ * send_inform(), should not be filled at all.
+ */
+ if (config_opts->data[OPT_CODE] != DHCP_HOST_NAME
+ || !client_hostname_opt
+ ) {
+ /* Why "!client_hostname_opt":
+ * add hostname only if client has no hostname
+ * on its static lease line.
+ * (Not that "opt hostname HOST"
+ * makes much sense in udhcpd.conf,
+ * that'd give all clients the same hostname,
+ * but it's a valid configuration).
+ */
+ udhcp_add_binary_option(packet, config_opts->data);
+ }
+ }
+ config_opts = config_opts->next;
}
+ if (client_hostname_opt)
+ udhcp_add_binary_option(packet, client_hostname_opt);
+
packet->siaddr_nip = server_config.siaddr_nip;
if (server_config.sname)
lease_time_sec = select_lease_time(oldpacket);
udhcp_add_simple_option(&packet, DHCP_LEASE_TIME, htonl(lease_time_sec));
-
add_server_options(&packet);
addr.s_addr = yiaddr;