diff options
author | Denis Kenzior <denkenz@gmail.com> | 2022-12-13 14:23:57 -0600 |
---|---|---|
committer | Denis Kenzior <denkenz@gmail.com> | 2022-12-13 14:28:22 -0600 |
commit | 341567fade59ad12d360d485f7f5cfca7cc161b4 (patch) | |
tree | 06b8e05f80dc238f6eeafd7a208587608b4243ef | |
parent | 9c59f961154bec0452adfa3b58bf79e731172b14 (diff) |
dhcp: Work around for blocked unicast requests
There may be (mis?)configured firewalls that do not allow outgoing
unicast requests on the DHCP port. In such cases the unicast RENEW
request will fail to be sent with an EPERM error. Instead of shutting
down the client immediately, simply ignore the error in this case.
Since the client is in the RENEWING state, it can be assumed that
broadcasts are successfully getting past the firewall. The client's
requests will fail until T2 timer fires and the client will enter into
the REBINDING state. At which point requests will be sent via
broadcast and hopefully succeed in renewing the lease.
-rw-r--r-- | ell/dhcp.c | 17 |
1 files changed, 16 insertions, 1 deletions
@@ -365,12 +365,27 @@ static int dhcp_client_send_unicast(struct l_dhcp_client *client, unsigned int len) { struct sockaddr_in si; + int r; memset(&si, 0, sizeof(si)); si.sin_family = AF_INET; si.sin_port = L_CPU_TO_BE16(DHCP_PORT_SERVER); si.sin_addr.s_addr = client->lease->server_address; - return client->transport->send(client->transport, &si, request, len); + + /* + * sendto() might fail with an EPERM error, which most likely means + * that the unicast was prevented by netfilter. Ignore this case + * and assume that once the REBINDING timeout is hit, a broadcast + * will go through which will have a chance of renewing the lease + */ + r = client->transport->send(client->transport, &si, request, len); + if (r == -EPERM) { + CLIENT_DEBUG("transport->send() failed with EPERM -> ignore"); + CLIENT_DEBUG("Is a firewall denying unicast DHCP packets?"); + return 0; + } + + return r; } static int dhcp_client_send_request(struct l_dhcp_client *client) |