]> git.proxmox.com Git - mirror_frr.git/commitdiff
vrrpd: compute VRRPv3 checksum
authorQuentin Young <qlyoung@cumulusnetworks.com>
Tue, 22 Jan 2019 22:49:58 +0000 (22:49 +0000)
committerQuentin Young <qlyoung@cumulusnetworks.com>
Fri, 17 May 2019 00:27:08 +0000 (00:27 +0000)
Correctly compute VRRPv3 checksum. Pseudoheaders are used for both IPv4
and IPv6.

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

index 93ede7b88fa636ab671116a99f5f1040bf6b78e3..fcc1cec51cbe6df48bf2f19865b2d10057f03b45 100644 (file)
@@ -327,7 +327,7 @@ static void vrrp_send_advertisement(struct vrrp_router *r)
 
        list_to_array(r->addrs, (void **)addrs, r->addrs->count);
 
-       pktlen = vrrp_pkt_build(&pkt, r->vr->vrid, r->priority,
+       pktlen = vrrp_pkt_build(&pkt, &r->src, r->vr->vrid, r->priority,
                                r->vr->advertisement_interval, r->addrs->count,
                                (struct ipaddr **)&addrs);
 
@@ -347,8 +347,8 @@ static void vrrp_send_advertisement(struct vrrp_router *r)
 
        if (sent < 0) {
                zlog_warn(VRRP_LOGPFX VRRP_LOGPFX_VRID
-                         "Failed to send VRRP Advertisement",
-                         r->vr->vrid);
+                         "Failed to send VRRP Advertisement: %s",
+                         r->vr->vrid, safe_strerror(errno));
        }
 }
 
@@ -523,6 +523,8 @@ done:
  * router's interface and binds the Tx socket of the VRRP router to that
  * address.
  *
+ * Also sets src field of vrrp_router.
+ *
  * r
  *    VRRP router to operate on
  *
@@ -559,10 +561,14 @@ static int vrrp_bind_to_primary_connected(struct vrrp_router *r)
 
        switch (r->family) {
        case AF_INET:
+               r->src.ipa_type = IPADDR_V4;
+               r->src.ipaddr_v4 = c->address->u.prefix4;
                su.sin.sin_family = AF_INET;
                su.sin.sin_addr = c->address->u.prefix4;
                break;
        case AF_INET6:
+               r->src.ipa_type = IPADDR_V6;
+               r->src.ipaddr_v6 = c->address->u.prefix6;
                su.sin6.sin6_family = AF_INET6;
                su.sin6.sin6_scope_id = ifp->ifindex;
                su.sin6.sin6_addr = c->address->u.prefix6;
index 98948a76fcf32aefd581c21acc44ba4fcd7da0c7..f68ff85224442c5f193300688344e2ed9ff87b5b 100644 (file)
@@ -75,6 +75,9 @@ struct vrrp_router {
        /* macvlan interface */
        struct interface *mvl_ifp;
 
+       /* Source address for advertisements */
+       struct ipaddr src;
+
        /* Socket read buffer */
        uint8_t ibuf[IP_MAXPACKET];
 
index 5010b4701d1f31d9e275989749d706c030bd434e..8147da68e0fdba4563c15bb2daef3bd817141201 100644 (file)
@@ -26,6 +26,7 @@
 #include "lib/ipaddr.h"
 #include "lib/memory.h"
 
+#include "vrrp.h"
 #include "vrrp_packet.h"
 
 /* clang-format off */
@@ -49,8 +50,8 @@ const char *vrrp_packet_names[16] = {
 };
 /* clang-format on */
 
-ssize_t vrrp_pkt_build(struct vrrp_pkt **pkt, uint8_t vrid, uint8_t prio,
-                      uint16_t max_adver_int, uint8_t numip,
+ssize_t vrrp_pkt_build(struct vrrp_pkt **pkt, struct ipaddr *src, uint8_t vrid,
+                      uint8_t prio, uint16_t max_adver_int, uint8_t numip,
                       struct ipaddr **ips)
 {
        bool v6 = IS_IPADDR_V6(ips[0]);
@@ -72,11 +73,24 @@ ssize_t vrrp_pkt_build(struct vrrp_pkt **pkt, uint8_t vrid, uint8_t prio,
                memcpy(aptr, &ips[i]->ip.addr, addrsz);
                aptr += addrsz;
        }
+
        (*pkt)->hdr.chksum = 0;
 
-       /* FIXME: v6 checksum */
-       uint16_t chksum = in_cksum(*pkt, pktsize);
-       (*pkt)->hdr.chksum = htons(chksum);
+       if (v6) {
+               struct ipv6_ph ph = {};
+               ph.src = src->ipaddr_v6;
+               inet_pton(AF_INET6, VRRP_MCASTV6_GROUP_STR, &ph.dst);
+               ph.ulpl = htons(pktsize);
+               ph.next_hdr = 112;
+               (*pkt)->hdr.chksum = in_cksum_with_ph6(&ph, *pkt, pktsize);
+       } else {
+               struct ipv4_ph ph = {};
+               ph.src = src->ipaddr_v4;
+               inet_pton(AF_INET, VRRP_MCASTV4_GROUP_STR, &ph.dst);
+               ph.proto = 112;
+               ph.len = htons(pktsize);
+               (*pkt)->hdr.chksum = in_cksum_with_ph4(&ph, *pkt, pktsize);
+       }
 
        return pktsize;
 }
index 7a4a338dae2a1557f0ec37fe27ea082db7403d3b..3a5b161fb7cc4b0aee535b7bdee2781eed24377c 100644 (file)
@@ -115,8 +115,8 @@ struct vrrp_pkt {
  *    array of pointer to either struct in_addr (v6 = false) or struct in6_addr
  *    (v6 = true)
  */
-ssize_t vrrp_pkt_build(struct vrrp_pkt **pkt, uint8_t vrid, uint8_t prio,
-                      uint16_t max_adver_int, uint8_t numip,
+ssize_t vrrp_pkt_build(struct vrrp_pkt **pkt, struct ipaddr *src, uint8_t vrid,
+                      uint8_t prio, uint16_t max_adver_int, uint8_t numip,
                       struct ipaddr **ips);
 
 /*