aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDenis Kenzior <denkenz@gmail.com>2022-12-13 14:23:57 -0600
committerDenis Kenzior <denkenz@gmail.com>2022-12-13 14:28:22 -0600
commit341567fade59ad12d360d485f7f5cfca7cc161b4 (patch)
tree06b8e05f80dc238f6eeafd7a208587608b4243ef
parent9c59f961154bec0452adfa3b58bf79e731172b14 (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.c17
1 files changed, 16 insertions, 1 deletions
diff --git a/ell/dhcp.c b/ell/dhcp.c
index 9b401722..a818102d 100644
--- a/ell/dhcp.c
+++ b/ell/dhcp.c
@@ -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)