diff options
author | Luke T. Shumaker <lukeshu@lukeshu.com> | 2024-11-11 21:40:22 -0700 |
---|---|---|
committer | Luke T. Shumaker <lukeshu@lukeshu.com> | 2024-11-11 21:43:25 -0700 |
commit | 06f16c5efdc5ad569d92e4cae05ff5360885077b (patch) | |
tree | 9ecc1d1814c5f46620826e9d7c8e039539ff2b30 /libdhcp | |
parent | 9817505324275efe68870d90e5976db28fb254e4 (diff) |
dhcp: Add some workarounds for broken servers
Diffstat (limited to 'libdhcp')
-rw-r--r-- | libdhcp/dhcp_client.c | 18 |
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, |