]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
dhcpcd: Add support for arp persist defence (#273)
authorpradeep-brightsign <148219883+pradeep-brightsign@users.noreply.github.com>
Thu, 21 Dec 2023 10:26:09 +0000 (10:26 +0000)
committerGitHub <noreply@github.com>
Thu, 21 Dec 2023 10:26:09 +0000 (10:26 +0000)
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

src/arp.c
src/dhcpcd.conf.5.in
src/if-options.c
src/if-options.h

index 453ab2df604415efbff9ab14f4a07901f26fec95..4b894e2739247df94187f67aa09601400778f9cd 100644 (file)
--- a/src/arp.c
+++ b/src/arp.c
@@ -173,12 +173,24 @@ arp_found(struct arp_state *astate, const struct arp_msg *amsg)
         * 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 {
index 878cdb8e022b1ccda916a8a09d73ad6596fdd926..d6f73eacc8f92790170d9d9253cbdeb5bae88653 100644 (file)
@@ -24,7 +24,7 @@
 .\" 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
@@ -510,6 +510,8 @@ adding a new IPv4 address.
 .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.
index b28e4ee2616df58b22de632acd556491bcc240a1..c57f6a31fe2c71fdb812279d3bac239b05aec8c4 100644 (file)
@@ -168,6 +168,7 @@ const struct option cf_options[] = {
        {"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'}
 };
 
@@ -2337,6 +2338,9 @@ invalid_token:
        case O_NOCONFIGURE:
                ifo->options &= ~DHCPCD_CONFIGURE;
                break;
+       case O_ARP_PERSISTDEFENCE:
+               ifo->options |= DHCPCD_ARP_PERSISTDEFENCE;
+               break;
        default:
                return 0;
        }
index 53914655df50546cb1994153abbad01287af3d7d..d317d370fb70b497f0388492798b19e2a21439b3 100644 (file)
@@ -65,6 +65,7 @@
 #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[];