diff options
| author | Quentin Young <qlyoung@cumulusnetworks.com> | 2019-01-22 22:49:58 +0000 |
|---|---|---|
| committer | Quentin Young <qlyoung@cumulusnetworks.com> | 2019-05-17 00:27:08 +0000 |
| commit | 8071d5c3e30a68d7bb9ca1bbf48b45f64b459a12 (patch) | |
| tree | 0426729e7f9262553096d2430331be4b6a939f07 /vrrpd/vrrp_packet.c | |
| parent | 17b48d7d1150ba4b4ee689a925f54b2a236b1d23 (diff) | |
vrrpd: compute VRRPv3 checksum
Correctly compute VRRPv3 checksum. Pseudoheaders are used for both IPv4
and IPv6.
Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
Diffstat (limited to 'vrrpd/vrrp_packet.c')
| -rw-r--r-- | vrrpd/vrrp_packet.c | 24 |
1 files changed, 19 insertions, 5 deletions
diff --git a/vrrpd/vrrp_packet.c b/vrrpd/vrrp_packet.c index 5010b4701d..8147da68e0 100644 --- a/vrrpd/vrrp_packet.c +++ b/vrrpd/vrrp_packet.c @@ -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; } |
