]> git.puffer.fish Git - mirror/frr.git/commitdiff
vrrpd: fix packet encode
authorQuentin Young <qlyoung@cumulusnetworks.com>
Fri, 7 Dec 2018 23:36:09 +0000 (23:36 +0000)
committerQuentin Young <qlyoung@cumulusnetworks.com>
Fri, 17 May 2019 00:27:08 +0000 (00:27 +0000)
* Properly encode VRRP packets
* Calculate checksum appropriately
* Update signature to provide caller both packet and result length

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

index a5eb40fda84a124601f3e1cb4ceb5a386f7a1da2..608be06a0c98416fb40600ca392a9dcce197c38b 100644 (file)
  */
 #include <zebra.h>
 
-#include "memory.h"
-#include "ipaddr.h"
+#include "lib/memory.h"
+#include "lib/ipaddr.h"
+#include "lib/checksum.h"
 
 #include "vrrp_packet.h"
 
-/*
- * Builds a VRRP packet.
- */
-struct vrrp_pkt *vrrp_pkt_build(uint8_t vrid, uint8_t prio,
-                               uint16_t max_adver_int, bool v6, uint8_t numip,
-                               void **ips)
+ssize_t vrrp_pkt_build(struct vrrp_pkt **pkt, uint8_t vrid, uint8_t prio,
+                      uint16_t max_adver_int, bool v6, uint8_t numip,
+                      void **ips)
 {
+       /* Used for pointer math when filling IPvX field */
+       struct in6_addr *v6ptr;
+       struct in_addr *v4ptr;
+
        size_t addrsz = v6 ? sizeof(struct in6_addr) : sizeof(struct in_addr);
-       struct vrrp_pkt *pkt =
-               XCALLOC(MTYPE_TMP, sizeof(struct vrrp_pkt) + addrsz * numip);
-
-       pkt->hdr.version = VRRP_VERSION;
-       pkt->hdr.type = VRRP_TYPE_ADVERTISEMENT;
-       pkt->hdr.vrid = vrid;
-       pkt->hdr.priority = prio;
-       pkt->hdr.v3.rsvd = 0;
-       pkt->hdr.v3.adver_int = max_adver_int;
-       for (uint8_t i = 0; i < numip; i++)
-               memcpy(&pkt->addrs[i].v4, ips[i], addrsz);
-       /* FIXME */
-       pkt->hdr.chksum = 0;
-
-       return pkt;
+       size_t pktsize = sizeof(struct vrrp_hdr) + addrsz * numip;
+       *pkt = XCALLOC(MTYPE_TMP, pktsize);
+
+       v6ptr = (struct in6_addr *) (*pkt)->addrs;
+       v4ptr = (struct in_addr *) (*pkt)->addrs;
+
+       (*pkt)->hdr.vertype |= VRRP_VERSION << 4;
+       (*pkt)->hdr.vertype |= VRRP_TYPE_ADVERTISEMENT;
+       (*pkt)->hdr.vrid = vrid;
+       (*pkt)->hdr.priority = prio;
+       (*pkt)->hdr.naddr = numip;
+       (*pkt)->hdr.v3.adver_int = htons(max_adver_int);
+
+       char buf[INET_ADDRSTRLEN];
+       for (int i = 0; i < numip; i++) {
+               /* If v4, treat as array of v4 addresses */
+               inet_ntop(AF_INET, ips[i], buf, sizeof(buf));
+               if (!v6)
+                       memcpy(&v4ptr[i], ips[i], addrsz);
+               else
+                       memcpy(&v6ptr[i], ips[i], addrsz);
+               inet_ntop(AF_INET, &v4ptr[i], buf, sizeof(buf));
+       }
+       (*pkt)->hdr.chksum = 0;
+
+       uint16_t chksum = in_cksum(*pkt, pktsize);
+       (*pkt)->hdr.chksum = htons(chksum);
+
+       return pktsize;
 }
index 5ff08f95fe11a1baa7e425e84acb37d608fc9222..245fada0641879d5cc44682171e04718750184bb 100644 (file)
  * Shared header for VRRPv2/v3 packets.
  */
 struct vrrp_hdr {
-       uint8_t version : 4;
-       uint8_t type : 4;
+       /*
+        * H  L H  L
+        * 0000 0000
+        * ver  type
+        */
+       uint8_t vertype;
        uint8_t vrid;
        uint8_t priority;
        uint8_t naddr;
@@ -42,9 +46,13 @@ struct vrrp_hdr {
                        uint8_t adver_int;
                } v2;
                struct {
-                       /* advertisement interval (in centiseconds) */
-                       uint16_t rsvd : 4;
-                       uint16_t adver_int : 12;
+                       /*
+                        * advertisement interval (in centiseconds)
+                        * H  L H          L
+                        * 0000 000000000000
+                        * rsvd adver_int
+                        */
+                       uint16_t adver_int;
                } v3;
        };
        uint16_t chksum;
@@ -60,7 +68,29 @@ struct vrrp_pkt {
 
 /*
  * Builds a VRRP packet.
+ *
+ * pkt
+ *    Pointer to store pointer to result buffer in
+ *
+ * vrid
+ *    Virtual Router Identifier
+ *
+ * prio
+ *    Virtual Router Priority
+ *
+ * max_adver_int
+ *    time between ADVERTISEMENTs
+ *
+ * v6
+ *    whether 'ips' is an array of v4 or v6 addresses
+ *
+ * numip
+ *    number of IPvX addresses in 'ips'
+ *
+ * ips
+ *    array of pointer to either struct in_addr (v6 = false) or struct in6_addr
+ *    (v6 = true)
  */
-struct vrrp_pkt *vrrp_pkt_build(uint8_t vrid, uint8_t prio,
-                               uint16_t max_adver_int, bool v6, uint8_t numip,
-                               void **ips);
+ssize_t vrrp_pkt_build(struct vrrp_pkt **pkt, uint8_t vrid, uint8_t prio,
+                      uint16_t max_adver_int, bool v6, uint8_t numip,
+                      void **ips);