/*
- * VRRPD packet crafting
- * Copyright (C) 2018 Cumulus Networks, Inc.
- * Quentin Young
+ * VRRP packet crafting.
+ * Copyright (C) 2018-2019 Cumulus Networks, Inc.
+ * Quentin Young
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* with this program; see the file COPYING; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#ifndef __VRRP_PACKET_H__
+#define __VRRP_PACKET_H__
+
#include <zebra.h>
-#include "memory.h"
-#include "ipaddr.h"
-#include "prefix.h"
+#include "lib/ipaddr.h"
+#include "lib/memory.h"
+#include "lib/prefix.h"
-#define VRRP_VERSION 3
#define VRRP_TYPE_ADVERTISEMENT 1
-extern const char *vrrp_packet_names[16];
-
/*
* Shared header for VRRPv2/v3 packets.
*/
* When used, this is actually an array of one or the other, not an
* array of union. If N v4 addresses are stored then
* sizeof(addrs) == N * sizeof(struct in_addr).
+ *
+ * Under v2, the last 2 entries in this array are the authentication
+ * data fields. We don't support auth in v2 so these are always just 8
+ * bytes of 0x00.
*/
union {
struct in_addr v4;
} addrs[];
} __attribute__((packed));
-#define VRRP_PKT_SIZE(_f, _naddr) \
+#define VRRP_PKT_SIZE(_f, _ver, _naddr) \
({ \
size_t _asz = ((_f) == AF_INET) ? sizeof(struct in_addr) \
: sizeof(struct in6_addr); \
- sizeof(struct vrrp_hdr) + (_asz * (_naddr)); \
+ size_t _auth = 2 * sizeof(uint32_t) * (3 - (_ver)); \
+ sizeof(struct vrrp_hdr) + (_asz * (_naddr)) + _auth; \
})
-#define VRRP_MIN_PKT_SIZE_V4 VRRP_PKT_SIZE(AF_INET, 1)
-#define VRRP_MAX_PKT_SIZE_V4 VRRP_PKT_SIZE(AF_INET, 255)
-#define VRRP_MIN_PKT_SIZE_V6 VRRP_PKT_SIZE(AF_INET6, 1)
-#define VRRP_MAX_PKT_SIZE_V6 VRRP_PKT_SIZE(AF_INET6, 255)
+#define VRRP_MIN_PKT_SIZE_V4 VRRP_PKT_SIZE(AF_INET, 3, 1)
+#define VRRP_MAX_PKT_SIZE_V4 VRRP_PKT_SIZE(AF_INET, 2, 255)
+#define VRRP_MIN_PKT_SIZE_V6 VRRP_PKT_SIZE(AF_INET6, 3, 1)
+#define VRRP_MAX_PKT_SIZE_V6 VRRP_PKT_SIZE(AF_INET6, 3, 255)
#define VRRP_MIN_PKT_SIZE VRRP_MIN_PKT_SIZE_V4
#define VRRP_MAX_PKT_SIZE VRRP_MAX_PKT_SIZE_V6
/*
- * Builds a VRRP packet.
+ * Builds a VRRP ADVERTISEMENT packet.
*
* pkt
* Pointer to store pointer to result buffer in
*
+ * src
+ * Source address packet will be transmitted from. This is needed to compute
+ * the VRRP checksum. The returned packet must be sent in an IP datagram with
+ * the source address equal to this field, or the checksum will be invalid.
+ *
+ * version
+ * VRRP version; must be 2 or 3
+ *
* vrid
* Virtual Router Identifier
*
* array of pointer to either struct in_addr (v6 = false) or struct in6_addr
* (v6 = true)
*/
-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);
+ssize_t vrrp_pkt_adver_build(struct vrrp_pkt **pkt, struct ipaddr *src,
+ uint8_t version, uint8_t vrid, uint8_t prio,
+ uint16_t max_adver_int, uint8_t numip,
+ struct ipaddr **ips);
+
+/* free memory allocated by vrrp_pkt_adver_build's pkt arg */
+void vrrp_pkt_free(struct vrrp_pkt *pkt);
/*
- * Dumps a VRRP packet to a string.
+ * Dumps a VRRP ADVERTISEMENT packet to a string.
*
* Currently only dumps the header.
*
* Returns:
* # bytes written to buf
*/
-size_t vrrp_pkt_dump(char *buf, size_t buflen, struct vrrp_pkt *pkt);
+size_t vrrp_pkt_adver_dump(char *buf, size_t buflen, struct vrrp_pkt *pkt);
/*
* Parses a VRRP packet, checking for illegal or invalid data.
*
- * This function does not check that the local router is not the IPvX owner for
- * the addresses received; that should be done by the caller.
+ * This function parses both VRRPv2 and VRRPv3 packets. Which version is
+ * expected is determined by the version argument. For example, if version is 3
+ * and the received packet has version field 2 it will fail to parse.
+ *
+ * Note that this function only checks whether the packet itself is a valid
+ * VRRP packet. It is up to the caller to validate whether the VRID is correct,
+ * priority and timer values are correct, etc.
*
* family
* Address family of received packet
*
+ * version
+ * VRRP version to use for validation
+ *
* m
* msghdr containing results of recvmsg() on VRRP router socket
*
* read
- * return value of recvmsg() on VRRP router socket; must be non-negative
+ * 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
* Returns:
* Size of VRRP packet, or -1 upon error
*/
-ssize_t vrrp_parse_datagram(int family, struct msghdr *m, size_t read,
- struct vrrp_pkt **pkt, char *errmsg,
- size_t errmsg_len);
+ssize_t vrrp_pkt_parse_datagram(int family, int version, struct msghdr *m,
+ size_t read, struct ipaddr *src,
+ struct vrrp_pkt **pkt, char *errmsg,
+ size_t errmsg_len);
+
+#endif /* __VRRP_PACKET_H__ */