From 56a1142f033234e3ee3b6361e9a1bcdbe606f816 Mon Sep 17 00:00:00 2001
From: Simon Kelley <simon@thekelleys.org.uk>
Date: Tue, 2 Apr 2013 17:02:58 +0100
Subject: [PATCH 1/1] SO_REUSEPORT may be defined, but not supported.
---
src/dhcp.c | 16 ++++++++++++----
src/dhcp6.c | 18 +++++++++++++-----
2 files changed, 25 insertions(+), 9 deletions(-)
diff --git a/src/dhcp.c b/src/dhcp.c
index 6b8b803..dd25632 100644
--- a/src/dhcp.c
+++ b/src/dhcp.c
@@ -65,14 +65,22 @@ static int make_fd(int port)
/* When bind-interfaces is set, there might be more than one dnmsasq
instance binding port 67. That's OK if they serve different networks.
- Need to set REUSEADDR to make this posible, or REUSEPORT on *BSD. */
+ Need to set REUSEADDR|REUSEPORT to make this posible.
+ Handle the case that REUSEPORT is defined, but the kernel doesn't
+ support it. This handles the introduction of REUSEPORT on Linux. */
if (option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND))
{
+ int rc = -1, porterr = 0;
+
#ifdef SO_REUSEPORT
- int rc = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &oneopt, sizeof(oneopt));
-#else
- int rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &oneopt, sizeof(oneopt));
+ if ((rc = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &oneopt, sizeof(oneopt))) == -1 &&
+ errno != ENOPROTOOPT)
+ porterr = 1;
#endif
+
+ if (rc == -1 && !porterr)
+ rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &oneopt, sizeof(oneopt));
+
if (rc == -1)
die(_("failed to set SO_REUSE{ADDR|PORT} on DHCP socket: %s"), NULL, EC_BADNET);
}
diff --git a/src/dhcp6.c b/src/dhcp6.c
index dd53f86..a827b2f 100644
--- a/src/dhcp6.c
+++ b/src/dhcp6.c
@@ -48,16 +48,24 @@ void dhcp6_init(void)
!set_ipv6pktinfo(fd))
die (_("cannot create DHCPv6 socket: %s"), NULL, EC_BADNET);
- /* When bind-interfaces is set, there might be more than one dnmsasq
+ /* When bind-interfaces is set, there might be more than one dnmsasq
instance binding port 547. That's OK if they serve different networks.
- Need to set REUSEADDR to make this posible, or REUSEPORT on *BSD. */
+ Need to set REUSEADDR|REUSEPORT to make this posible.
+ Handle the case that REUSEPORT is defined, but the kernel doesn't
+ support it. This handles the introduction of REUSEPORT on Linux. */
if (option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND))
{
+ int rc = -1, porterr = 0;
+
#ifdef SO_REUSEPORT
- int rc = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &oneopt, sizeof(oneopt));
-#else
- int rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &oneopt, sizeof(oneopt));
+ if ((rc = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &oneopt, sizeof(oneopt))) == -1 &&
+ errno != ENOPROTOOPT)
+ porterr = 1;
#endif
+
+ if (rc == -1 && !porterr)
+ rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &oneopt, sizeof(oneopt));
+
if (rc == -1)
die(_("failed to set SO_REUSE{ADDR|PORT} on DHCPv6 socket: %s"), NULL, EC_BADNET);
}
--
1.7.2.5