bool resched;
char errbuf[BUFSIZ];
uint8_t control[64];
+ struct ipaddr src = {};
struct msghdr m;
struct iovec iov;
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
"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",
}
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)
/* 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)) {
*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");
}
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",
/* # 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];
* 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
*
* 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__ */