From: Quentin Young Date: Fri, 1 Feb 2019 20:54:44 +0000 (+0000) Subject: vrrpd: check rx'd advertisement checksum X-Git-Tag: base_7.2~330^2~109 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=d04bb25aced1db97f9af795acea99ba682a3ad14;p=matthieu%2Ffrr.git vrrpd: check rx'd advertisement checksum And retrieve source address, since we need it anyway. Signed-off-by: Quentin Young --- diff --git a/vrrpd/vrrp.c b/vrrpd/vrrp.c index edac0f66cb..411c3c7e7b 100644 --- a/vrrpd/vrrp.c +++ b/vrrpd/vrrp.c @@ -568,6 +568,7 @@ static int vrrp_read(struct thread *thread) bool resched; char errbuf[BUFSIZ]; uint8_t control[64]; + struct ipaddr src = {}; struct msghdr m; struct iovec iov; @@ -595,8 +596,8 @@ static int vrrp_read(struct thread *thread) r->vr->vrid, family2str(r->family)); zlog_hexdump(r->ibuf, nbytes); - pktsize = vrrp_pkt_parse_datagram(r->family, &m, nbytes, &pkt, errbuf, - sizeof(errbuf)); + pktsize = vrrp_pkt_parse_datagram(r->family, &m, nbytes, &src, &pkt, + errbuf, sizeof(errbuf)); if (pktsize < 0) { zlog_warn(VRRP_LOGPFX VRRP_LOGPFX_VRID @@ -847,7 +848,9 @@ static int vrrp_socket(struct vrrp_router *r) "Failed to set outgoing multicast hop count to 255; RFC 5798 compliant implementations will drop our packets", r->vr->vrid); } - ret = setsockopt_ipv6_hoplimit(r->sock_rx, 1); + + /* Request hop limit delivery */ + setsockopt_ipv6_hoplimit(r->sock_rx, 1); if (ret < 0) { zlog_warn(VRRP_LOGPFX VRRP_LOGPFX_VRID "Failed to request IPv6 Hop Limit delivery", diff --git a/vrrpd/vrrp_packet.c b/vrrpd/vrrp_packet.c index 2d5129b285..ccfdd8f883 100644 --- a/vrrpd/vrrp_packet.c +++ b/vrrpd/vrrp_packet.c @@ -162,8 +162,8 @@ size_t vrrp_pkt_adver_dump(char *buf, size_t buflen, struct vrrp_pkt *pkt) } ssize_t vrrp_pkt_parse_datagram(int family, struct msghdr *m, size_t read, - struct vrrp_pkt **pkt, char *errmsg, - size_t errmsg_len) + struct ipaddr *src, struct vrrp_pkt **pkt, + char *errmsg, size_t errmsg_len) { /* Source (MAC & IP), Dest (MAC & IP) TTL validation done by kernel */ size_t addrsz = (family == AF_INET) ? sizeof(struct in_addr) @@ -207,6 +207,10 @@ ssize_t vrrp_pkt_parse_datagram(int family, struct msghdr *m, size_t read, /* IP empty packet check */ VRRP_PKT_VCHECK(pktsize > 0, "IPv4 packet has no payload"); + + /* Extract source address */ + src->ipa_type = IPADDR_V4; + src->ipaddr_v4 = ip->ip_src; } else if (family == AF_INET6) { struct cmsghdr *c; for (c = CMSG_FIRSTHDR(m); c != NULL; CMSG_NXTHDR(m, c)) { @@ -224,6 +228,12 @@ ssize_t vrrp_pkt_parse_datagram(int family, struct msghdr *m, size_t read, *pkt = (struct vrrp_pkt *)buf; pktsize = read; + + /* Extract source address */ + src->ipa_type = IPADDR_V6; + struct sockaddr_in6 *sa = m->msg_name; + memcpy(&src->ipaddr_v6, &sa->sin6_addr, + sizeof(struct in6_addr)); } else { assert(!"Unknown address family"); } @@ -239,6 +249,13 @@ ssize_t vrrp_pkt_parse_datagram(int family, struct msghdr *m, size_t read, VRRP_PKT_VCHECK(pktsize <= maxsize, "VRRP packet is oversized (%lu > %lu)", pktsize, VRRP_MAX_PKT_SIZE); + + /* Checksum check */ + uint16_t chksum = vrrp_pkt_checksum(*pkt, pktsize, src); + VRRP_PKT_VCHECK((*pkt)->hdr.chksum == chksum, + "Bad VRRP checksum %" PRIu16 "; should be %" PRIu16 "", + (*pkt)->hdr.chksum, chksum); + /* Version check */ VRRP_PKT_VCHECK(((*pkt)->hdr.vertype >> 4) != 2, "VRPPv2 unsupported"); VRRP_PKT_VCHECK(((*pkt)->hdr.vertype >> 4) == 3, "Bad version %u", @@ -249,8 +266,6 @@ ssize_t vrrp_pkt_parse_datagram(int family, struct msghdr *m, size_t read, /* # addresses check */ size_t ves = VRRP_PKT_SIZE(family, (*pkt)->hdr.naddr); VRRP_PKT_VCHECK(pktsize == ves, "Packet has incorrect # addresses"); - /* FIXME: checksum check */ - /* ... */ /* Addresses check */ char vbuf[INET6_ADDRSTRLEN]; diff --git a/vrrpd/vrrp_packet.h b/vrrpd/vrrp_packet.h index ed577ddcfa..af51287718 100644 --- a/vrrpd/vrrp_packet.h +++ b/vrrpd/vrrp_packet.h @@ -165,6 +165,9 @@ size_t vrrp_pkt_adver_dump(char *buf, size_t buflen, struct vrrp_pkt *pkt); * read * return value of recvmsg() on VRRP router socket; must be non-negative * + * src + * Pointer to struct ipaddr to store address of datagram sender + * * pkt * Pointer to pointer to set to location of VRRP packet within buf * @@ -179,7 +182,7 @@ size_t vrrp_pkt_adver_dump(char *buf, size_t buflen, struct vrrp_pkt *pkt); * Size of VRRP packet, or -1 upon error */ ssize_t vrrp_pkt_parse_datagram(int family, struct msghdr *m, size_t read, - struct vrrp_pkt **pkt, char *errmsg, - size_t errmsg_len); + struct ipaddr *src, struct vrrp_pkt **pkt, + char *errmsg, size_t errmsg_len); #endif /* __VRRP_PACKET_H__ */