*/
#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;
}
* 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;
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;
/*
* 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);