summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--vrrpd/vrrp.c9
-rw-r--r--vrrpd/vrrp_packet.c23
-rw-r--r--vrrpd/vrrp_packet.h7
3 files changed, 30 insertions, 9 deletions
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__ */