net: lib: dhcpv4_server: Add callback to allow user to set address

This functionality is useful to allow for conditional or static leases.

Signed-off-by: Andreas Ålgård <aal@ixys.no>
This commit is contained in:
Andreas Ålgård 2024-06-24 11:44:10 +02:00 committed by Anas Nashif
parent dfe7cb58cb
commit a5850b794c
2 changed files with 51 additions and 0 deletions

View File

@ -109,6 +109,34 @@ int net_dhcpv4_server_foreach_lease(struct net_if *iface,
net_dhcpv4_lease_cb_t cb,
void *user_data);
/**
* @typedef net_dhcpv4_server_provider_cb_t
* @brief Callback used to let application provide an address for a given
* client ID
* @details This function is called before assigning an address to a client,
* and lets the application override the address for a given client. If the
* callback returns 0, addr needs to be a valid address and will be assigned
* to the client. If the callback returns anything non-zero, the client will
* be assigned an address from the pool.
*
* @param iface Pointer to the network interface
* @param client_id Pointer to client requesting an address
* @param addr Address to be assigned to client
* @param user_data A valid pointer to user data or NULL
*/
typedef int (*net_dhcpv4_server_provider_cb_t)(struct net_if *iface,
const struct dhcpv4_client_id *client_id,
struct in_addr *addr,
void *user_data);
/**
* @brief Set the callback used to provide addresses to the DHCP server.
*
* @param cb User-supplied callback function to call
* @param user_data A valid pointer to user data or NULL
*/
void net_dhcpv4_server_set_provider_cb(net_dhcpv4_server_provider_cb_t cb,
void *user_data);
/**
* @}
*/

View File

@ -70,6 +70,8 @@ struct dhcpv4_server_ctx {
#endif
};
static void *address_provider_callback_user_data;
static net_dhcpv4_server_provider_cb_t address_provider_callback;
static struct dhcpv4_server_ctx server_ctx[CONFIG_NET_DHCPV4_SERVER_INSTANCES];
static struct zsock_pollfd fds[CONFIG_NET_DHCPV4_SERVER_INSTANCES];
static K_MUTEX_DEFINE(server_lock);
@ -944,6 +946,18 @@ static void dhcpv4_handle_discover(struct dhcpv4_server_ctx *ctx,
selected = slot;
break;
}
struct in_addr addr = { 0 };
if (slot->state == DHCPV4_SERVER_ADDR_FREE &&
address_provider_callback) {
ret = address_provider_callback(ctx->iface, &client_id, &addr,
address_provider_callback_user_data);
if (ret == 0) {
selected = slot;
slot->addr = addr;
}
break;
}
}
/* 2. Skipped, for now expired/released entries are forgotten. */
@ -1743,8 +1757,17 @@ out:
return ret;
}
void net_dhcpv4_server_set_provider_cb(net_dhcpv4_server_provider_cb_t cb, void *user_data)
{
address_provider_callback_user_data = user_data;
address_provider_callback = cb;
}
void net_dhcpv4_server_init(void)
{
address_provider_callback = NULL;
address_provider_callback_user_data = NULL;
for (int i = 0; i < ARRAY_SIZE(fds); i++) {
fds[i].fd = -1;
}