RFC 5227 recommends 3 ways to deal with address conflict detection.
a) Stop everything.
b) Defend and then stop on fail - this is what dhcpcd currently does.
c) Notify and carry on.
The current change implements the option c. A new option arp_persistdefence
has been added and when this is enabled, the a defence is attempted upon a
conflict and when that fails, an error is logged on every other conflict
within the DEFEND_INTERVAL and the current IP address is retained.
Fixes #272
* the other IPv4LL client will receieve two ARP
* messages.
* If another conflict happens within DEFEND_INTERVAL
- * then we must drop our address and negotiate a new one. */
+ * then we must drop our address and negotiate a new one.
+ * If DHCPCD_ARP_PERSISTDEFENCE is set, that enables
+ * RFC5227 section 2.4.c behaviour. Upon conflict
+ * detection, the host records the time that the
+ * conflicting ARP packet was received, and then
+ * broadcasts one single ARP Announcement. The host then
+ * continues to use the address normally. All further
+ * conflict notifications within the DEFEND_INTERVAL are
+ * ignored. */
clock_gettime(CLOCK_MONOTONIC, &now);
if (timespecisset(&astate->defend) &&
eloop_timespec_diff(&now, &astate->defend, NULL) < DEFEND_INTERVAL)
+ {
logwarnx("%s: %d second defence failed for %s",
ifp->name, DEFEND_INTERVAL, inet_ntoa(astate->addr));
+ if (ifp->options->options & DHCPCD_ARP_PERSISTDEFENCE)
+ return;
+ }
else if (arp_request(astate, &astate->addr) == -1)
logerr(__func__);
else {
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd December 18, 2023
+.Dd December 21, 2023
.Dt DHCPCD.CONF 5
.Os
.Sh NAME
.It Ic noarp
Don't send any ARP requests.
This also disables IPv4LL.
+.It Ic arp_persistdefence
+Keep the IP address even if defence fails upon IP Address conflict.
.It Ic noauthrequired
Don't require authentication even though we requested it.
Also allows FORCERENEW and RECONFIGURE messages without authentication.
{"link_rcvbuf", required_argument, NULL, O_LINK_RCVBUF},
{"configure", no_argument, NULL, O_CONFIGURE},
{"noconfigure", no_argument, NULL, O_NOCONFIGURE},
+ {"arp_persistdefence", no_argument, NULL, O_ARP_PERSISTDEFENCE},
{NULL, 0, NULL, '\0'}
};
case O_NOCONFIGURE:
ifo->options &= ~DHCPCD_CONFIGURE;
break;
+ case O_ARP_PERSISTDEFENCE:
+ ifo->options |= DHCPCD_ARP_PERSISTDEFENCE;
+ break;
default:
return 0;
}
#define DHCPCD_GATEWAY (1ULL << 3)
#define DHCPCD_STATIC (1ULL << 4)
#define DHCPCD_DEBUG (1ULL << 5)
+#define DHCPCD_ARP_PERSISTDEFENCE (1ULL << 6)
#define DHCPCD_LASTLEASE (1ULL << 7)
#define DHCPCD_INFORM (1ULL << 8)
#define DHCPCD_REQUEST (1ULL << 9)
#define O_CONFIGURE O_BASE + 50
#define O_NOCONFIGURE O_BASE + 51
#define O_RANDOMISE_HWADDR O_BASE + 52
+#define O_ARP_PERSISTDEFENCE O_BASE + 53
extern const struct option cf_options[];