summaryrefslogtreecommitdiff
path: root/libdhcp
diff options
context:
space:
mode:
authorLuke T. Shumaker <lukeshu@lukeshu.com>2024-11-11 21:40:22 -0700
committerLuke T. Shumaker <lukeshu@lukeshu.com>2024-11-11 21:43:25 -0700
commit06f16c5efdc5ad569d92e4cae05ff5360885077b (patch)
tree9ecc1d1814c5f46620826e9d7c8e039539ff2b30 /libdhcp
parent9817505324275efe68870d90e5976db28fb254e4 (diff)
dhcp: Add some workarounds for broken servers
Diffstat (limited to 'libdhcp')
-rw-r--r--libdhcp/dhcp_client.c18
1 files changed, 16 insertions, 2 deletions
diff --git a/libdhcp/dhcp_client.c b/libdhcp/dhcp_client.c
index fc40861..b0a2868 100644
--- a/libdhcp/dhcp_client.c
+++ b/libdhcp/dhcp_client.c
@@ -134,7 +134,7 @@ struct dhcp_client {
struct net_eth_addr self_eth_addr;
char self_hostname[63];
size_t self_id_len;
- uint8_t *self_id_dat;
+ void *self_id_dat;
/* Mutable. */
enum {
@@ -242,7 +242,10 @@ static bool dhcp_client_send(struct dhcp_client *client, uint8_t msgtyp, const c
msg.hlen = sizeof(client->self_eth_addr);
msg.hops = 0; /* relays increment this when they forward it along */
msg.xid = uint32be_marshal(client->xid);
- msg.secs = uint16be_marshal((VCALL(bootclock, get_time_ns) - client->time_ns_init)/NS_PER_S);
+ /* systemd's sd-dhcp-client.c asserts that some servers are
+ * broken and require .secs to be non-zero, even though RFC
+ * 2131 explicitly says that this is valid. */
+ msg.secs = uint16be_marshal( ((VCALL(bootclock, get_time_ns) - client->time_ns_init)/NS_PER_S) ?: 1);
switch (msgtyp) {
case DHCP_MSGTYP_DISCOVER: case DHCP_MSGTYP_INFORM: case DHCP_MSGTYP_REQUEST:
msg.flags = uint16be_marshal(server_broadcasts ? DHCP_FLAG_BROADCAST : 0);
@@ -817,11 +820,22 @@ __attribute__((noreturn)) void dhcp_client_main(implements_net_iface *iface,
char *self_hostname) {
assert(iface);
+ /* Even though a client ID is optional and not meaningful for
+ * us (the best we can do is to duplicate .chaddr), systemd's
+ * sd-dhcp-client.c asserts that some servers are broken and
+ * require it to be set. */
+ struct {uint8_t typ; struct net_eth_addr dat;} client_id = {
+ DHCP_HTYPE_ETHERNET,
+ VCALL(iface, hwaddr),
+ };
+
struct dhcp_client client = {
/* Static. */
.iface = iface,
.sock = VCALL(iface, udp_conn, DHCP_PORT_CLIENT),
.self_eth_addr = VCALL(iface, hwaddr),
+ .self_id_len = sizeof(client_id),
+ .self_id_dat = &client_id,
/* Mutable. */
.state = STATE_INIT,