]> git.puffer.fish Git - matthieu/frr.git/commitdiff
vrrpd: include auth fields in v2 packet
authorQuentin Young <qlyoung@cumulusnetworks.com>
Wed, 13 Mar 2019 17:18:36 +0000 (17:18 +0000)
committerQuentin Young <qlyoung@cumulusnetworks.com>
Fri, 17 May 2019 00:27:08 +0000 (00:27 +0000)
Based on looking at other vendors, seems I misinterpreted the RFC - type
0 auth (no authentication) still requires the authentication fields to
be present, just set to all zero.

This should fix VRRPv2 interop with other vendors.

Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
vrrpd/vrrp_packet.c
vrrpd/vrrp_packet.h

index 970c8d7d7eeb7482d607643271236a55c5be878f..102750eafeb38e01380b76e258e952db13762f79 100644 (file)
@@ -119,7 +119,7 @@ ssize_t vrrp_pkt_adver_build(struct vrrp_pkt **pkt, struct ipaddr *src,
                addrsz = IPADDRSZ(ips[0]);
        }
 
-       size_t pktsize = VRRP_PKT_SIZE(v6 ? AF_INET6 : AF_INET, numip);
+       size_t pktsize = VRRP_PKT_SIZE(v6 ? AF_INET6 : AF_INET, version, numip);
        *pkt = XCALLOC(MTYPE_VRRP_PKT, pktsize);
 
        (*pkt)->hdr.vertype |= version << 4;
@@ -283,9 +283,10 @@ ssize_t vrrp_pkt_parse_datagram(int family, int version, struct msghdr *m,
        VRRP_PKT_VCHECK(((*pkt)->hdr.vertype & 0x0F) == 1, "Bad type %" PRIu8,
                        (*pkt)->hdr.vertype & 0x0f);
 
-       /* # addresses check */
-       size_t ves = VRRP_PKT_SIZE(family, (*pkt)->hdr.naddr);
-       VRRP_PKT_VCHECK(pktsize == ves, "Packet has incorrect # addresses");
+       /* Exact size check */
+       size_t ves = VRRP_PKT_SIZE(family, pktver, (*pkt)->hdr.naddr);
+       VRRP_PKT_VCHECK(pktsize == ves, "Packet has incorrect # addresses%s",
+                       pktver == 2 ? " or missing auth fields" : "");
 
        /* auth type check */
        if (version == 2)
index 2061b63c6132ba5f64cf5410e102e694f29b0303..475e4780d5d93bb687c963cb6ad909a0eca02d7b 100644 (file)
@@ -70,6 +70,10 @@ struct vrrp_pkt {
         * When used, this is actually an array of one or the other, not an
         * array of union. If N v4 addresses are stored then
         * sizeof(addrs) == N * sizeof(struct in_addr).
+        *
+        * Under v2, the last 2 entries in this array are the authentication
+        * data fields. We don't support auth in v2 so these are always just 8
+        * bytes of 0x00.
         */
        union {
                struct in_addr v4;
@@ -77,17 +81,18 @@ struct vrrp_pkt {
        } addrs[];
 } __attribute__((packed));
 
-#define VRRP_PKT_SIZE(_f, _naddr)                                              \
+#define VRRP_PKT_SIZE(_f, _ver, _naddr)                                        \
        ({                                                                     \
                size_t _asz = ((_f) == AF_INET) ? sizeof(struct in_addr)       \
                                                : sizeof(struct in6_addr);     \
-               sizeof(struct vrrp_hdr) + (_asz * (_naddr));                   \
+               size_t _auth = 2 * sizeof(uint32_t) * (3 - (_ver));            \
+               sizeof(struct vrrp_hdr) + (_asz * (_naddr)) + _auth;           \
        })
 
-#define VRRP_MIN_PKT_SIZE_V4 VRRP_PKT_SIZE(AF_INET, 1)
-#define VRRP_MAX_PKT_SIZE_V4 VRRP_PKT_SIZE(AF_INET, 255)
-#define VRRP_MIN_PKT_SIZE_V6 VRRP_PKT_SIZE(AF_INET6, 1)
-#define VRRP_MAX_PKT_SIZE_V6 VRRP_PKT_SIZE(AF_INET6, 255)
+#define VRRP_MIN_PKT_SIZE_V4 VRRP_PKT_SIZE(AF_INET, 3, 1)
+#define VRRP_MAX_PKT_SIZE_V4 VRRP_PKT_SIZE(AF_INET, 2, 255)
+#define VRRP_MIN_PKT_SIZE_V6 VRRP_PKT_SIZE(AF_INET6, 3, 1)
+#define VRRP_MAX_PKT_SIZE_V6 VRRP_PKT_SIZE(AF_INET6, 3, 255)
 
 #define VRRP_MIN_PKT_SIZE VRRP_MIN_PKT_SIZE_V4
 #define VRRP_MAX_PKT_SIZE VRRP_MAX_PKT_SIZE_V6