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;  }  | 
