]> git.proxmox.com Git - mirror_frr.git/blobdiff - vrrpd/vrrp_packet.h
vrrpd: allow vrrp_shutdown() on shutdown rtr
[mirror_frr.git] / vrrpd / vrrp_packet.h
index 245fada0641879d5cc44682171e04718750184bb..082935f080d4628d10e4398df5128ed833883d85 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * 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
 
 /*
@@ -56,22 +58,57 @@ struct vrrp_hdr {
                } v3;
        };
        uint16_t chksum;
-};
+} __attribute__((packed));
+
+#define VRRP_HDR_SIZE sizeof(struct vrrp_hdr)
 
 struct vrrp_pkt {
        struct vrrp_hdr hdr;
+       /*
+        * 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;
                struct in6_addr v6;
        } addrs[];
-} __attribute((packed, aligned(1)));
+} __attribute__((packed));
+
+#define VRRP_PKT_SIZE(_f, _ver, _naddr)                                        \
+       ({                                                                     \
+               size_t _asz = ((_f) == AF_INET) ? sizeof(struct in_addr)       \
+                                               : sizeof(struct in6_addr);     \
+               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, 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
  *
@@ -91,6 +128,76 @@ struct vrrp_pkt {
  *    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, uint8_t vrid, uint8_t prio,
-                      uint16_t max_adver_int, bool v6, uint8_t numip,
-                      void **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 ADVERTISEMENT packet to a string.
+ *
+ * Currently only dumps the header.
+ *
+ * buf
+ *    Buffer to store string representation
+ *
+ * buflen
+ *    Size of buf
+ *
+ * pkt
+ *    Packet to dump to a string
+ *
+ * Returns:
+ *    # bytes written to buf
+ */
+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 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
+ *
+ * src
+ *    Pointer to struct ipaddr to store address of datagram sender
+ *
+ * pkt
+ *    Pointer to pointer to set to location of VRRP packet within buf
+ *
+ * errmsg
+ *    Buffer to store human-readable error message in case of error; may be
+ *    NULL, in which case no message will be stored
+ *
+ * errmsg_len
+ *    Size of errmsg
+ *
+ * Returns:
+ *    Size of VRRP packet, or -1 upon error
+ */
+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__ */