]> git.proxmox.com Git - mirror_frr.git/blobdiff - vrrpd/vrrp_packet.c
Merge pull request #5793 from ton31337/fix/formatting_show_bgp_summary_failed
[mirror_frr.git] / vrrpd / vrrp_packet.c
index 551e142e54404e38fc4585ad0120b5bea38f28d7..e4fee2d792cec4b98ce0ea5facd30f48226119c5 100644 (file)
 
 #include "vrrp.h"
 #include "vrrp_debug.h"
-#include "vrrp_memory.h"
 #include "vrrp_packet.h"
 
+DEFINE_MTYPE_STATIC(VRRPD, VRRP_PKT, "VRRP packet")
+
 /* clang-format off */
-const char *vrrp_packet_names[16] = {
+static const char *const vrrp_packet_names[16] = {
        [0] = "Unknown",
        [VRRP_TYPE_ADVERTISEMENT] = "ADVERTISEMENT",
        [2] = "Unknown",
@@ -76,20 +77,23 @@ static uint16_t vrrp_pkt_checksum(struct vrrp_pkt *pkt, size_t pktsize,
        bool v6 = (src->ipa_type == IPADDR_V6);
 
        uint16_t chksum_pre = pkt->hdr.chksum;
+
        pkt->hdr.chksum = 0;
 
        if (v6) {
                struct ipv6_ph ph = {};
+
                ph.src = src->ipaddr_v6;
                inet_pton(AF_INET6, VRRP_MCASTV6_GROUP_STR, &ph.dst);
                ph.ulpl = htons(pktsize);
-               ph.next_hdr = 112;
+               ph.next_hdr = IPPROTO_VRRP;
                chksum = in_cksum_with_ph6(&ph, pkt, pktsize);
        } else if (!v6 && ((pkt->hdr.vertype >> 4) == 3)) {
                struct ipv4_ph ph = {};
+
                ph.src = src->ipaddr_v4;
                inet_pton(AF_INET, VRRP_MCASTV4_GROUP_STR, &ph.dst);
-               ph.proto = 112;
+               ph.proto = IPPROTO_VRRP;
                ph.len = htons(pktsize);
                chksum = in_cksum_with_ph4(&ph, pkt, pktsize);
        } else if (!v6 && ((pkt->hdr.vertype >> 4) == 2)) {
@@ -112,14 +116,16 @@ ssize_t vrrp_pkt_adver_build(struct vrrp_pkt **pkt, struct ipaddr *src,
        size_t addrsz = 0;
 
        assert(version >= 2 && version <= 3);
-       assert(!(version == 2 && v6));
 
        if (numip > 0) {
                v6 = IS_IPADDR_V6(ips[0]);
                addrsz = IPADDRSZ(ips[0]);
        }
 
-       size_t pktsize = VRRP_PKT_SIZE(v6 ? AF_INET6 : AF_INET, numip);
+       assert(!(version == 2 && v6));
+
+       size_t pktsize = VRRP_PKT_SIZE(v6 ? AF_INET6 : AF_INET, version, numip);
+
        *pkt = XCALLOC(MTYPE_VRRP_PKT, pktsize);
 
        (*pkt)->hdr.vertype |= version << 4;
@@ -146,6 +152,11 @@ ssize_t vrrp_pkt_adver_build(struct vrrp_pkt **pkt, struct ipaddr *src,
        return pktsize;
 }
 
+void vrrp_pkt_free(struct vrrp_pkt *pkt)
+{
+       XFREE(MTYPE_VRRP_PKT, pkt);
+}
+
 size_t vrrp_pkt_adver_dump(char *buf, size_t buflen, struct vrrp_pkt *pkt)
 {
        if (buflen < 1)
@@ -156,22 +167,22 @@ size_t vrrp_pkt_adver_dump(char *buf, size_t buflen, struct vrrp_pkt *pkt)
        struct vrrp_hdr *hdr = &pkt->hdr;
 
        buf[0] = 0x00;
-       snprintf(tmpbuf, sizeof(tmpbuf), "Version: %u\n", (hdr->vertype >> 4));
+       snprintf(tmpbuf, sizeof(tmpbuf), "version %u, ", (hdr->vertype >> 4));
        rs += strlcat(buf, tmpbuf, buflen);
-       snprintf(tmpbuf, sizeof(tmpbuf), "Type: %u (%s)\n",
+       snprintf(tmpbuf, sizeof(tmpbuf), "type %u (%s), ",
                 (hdr->vertype & 0x0F),
                 vrrp_packet_names[(hdr->vertype & 0x0F)]);
        rs += strlcat(buf, tmpbuf, buflen);
-       snprintf(tmpbuf, sizeof(tmpbuf), "VRID: %u\n", hdr->vrid);
+       snprintf(tmpbuf, sizeof(tmpbuf), "vrid %u, ", hdr->vrid);
        rs += strlcat(buf, tmpbuf, buflen);
-       snprintf(tmpbuf, sizeof(tmpbuf), "Priority: %u\n", hdr->priority);
+       snprintf(tmpbuf, sizeof(tmpbuf), "priority %u, ", hdr->priority);
        rs += strlcat(buf, tmpbuf, buflen);
-       snprintf(tmpbuf, sizeof(tmpbuf), "Count IPvX: %u\n", hdr->naddr);
+       snprintf(tmpbuf, sizeof(tmpbuf), "#%u addresses, ", hdr->naddr);
        rs += strlcat(buf, tmpbuf, buflen);
-       snprintf(tmpbuf, sizeof(tmpbuf), "Max Adver Int: %u\n",
+       snprintf(tmpbuf, sizeof(tmpbuf), "max adver int %u, ",
                 ntohs(hdr->v3.adver_int));
        rs += strlcat(buf, tmpbuf, buflen);
-       snprintf(tmpbuf, sizeof(tmpbuf), "Checksum: %x\n", ntohs(hdr->chksum));
+       snprintf(tmpbuf, sizeof(tmpbuf), "checksum %x", ntohs(hdr->chksum));
        rs += strlcat(buf, tmpbuf, buflen);
 
        return rs;
@@ -228,10 +239,12 @@ ssize_t vrrp_pkt_parse_datagram(int family, int version, struct msghdr *m,
 
                /* Extract source address */
                struct sockaddr_in *sa = m->msg_name;
+
                src->ipa_type = IPADDR_V4;
                src->ipaddr_v4 = sa->sin_addr;
        } else if (family == AF_INET6) {
                struct cmsghdr *c;
+
                for (c = CMSG_FIRSTHDR(m); c != NULL; CMSG_NXTHDR(m, c)) {
                        if (c->cmsg_level == IPPROTO_IPV6
                            && c->cmsg_type == IPV6_HOPLIMIT)
@@ -241,6 +254,7 @@ ssize_t vrrp_pkt_parse_datagram(int family, int version, struct msghdr *m,
                VRRP_PKT_VCHECK(!!c, "IPv6 Hop Limit not received");
 
                uint8_t *hoplimit = CMSG_DATA(c);
+
                VRRP_PKT_VCHECK(*hoplimit == 255,
                                "IPv6 Hop Limit is %" PRIu8 "; should be 255",
                                *hoplimit);
@@ -250,6 +264,7 @@ ssize_t vrrp_pkt_parse_datagram(int family, int version, struct msghdr *m,
 
                /* Extract source address */
                struct sockaddr_in6 *sa = m->msg_name;
+
                src->ipa_type = IPADDR_V6;
                memcpy(&src->ipaddr_v6, &sa->sin6_addr,
                       sizeof(struct in6_addr));
@@ -271,10 +286,12 @@ ssize_t vrrp_pkt_parse_datagram(int family, int version, struct msghdr *m,
 
        /* Version check */
        uint8_t pktver = (*pkt)->hdr.vertype >> 4;
+
        VRRP_PKT_VCHECK(pktver == version, "Bad version %u", pktver);
 
        /* Checksum check */
        uint16_t chksum = vrrp_pkt_checksum(*pkt, pktsize, src);
+
        VRRP_PKT_VCHECK((*pkt)->hdr.chksum == chksum,
                        "Bad VRRP checksum %" PRIx16 "; should be %" PRIx16 "",
                        (*pkt)->hdr.chksum, chksum);
@@ -283,9 +300,11 @@ ssize_t vrrp_pkt_parse_datagram(int family, int version, struct msghdr *m,
        VRRP_PKT_VCHECK(((*pkt)->hdr.vertype & 0x0F) == 1, "Bad type %" PRIu8,
                        (*pkt)->hdr.vertype & 0x0f);
 
-       /* # addresses check */
-       size_t ves = VRRP_PKT_SIZE(family, (*pkt)->hdr.naddr);
-       VRRP_PKT_VCHECK(pktsize == ves, "Packet has incorrect # addresses");
+       /* Exact size check */
+       size_t ves = VRRP_PKT_SIZE(family, pktver, (*pkt)->hdr.naddr);
+
+       VRRP_PKT_VCHECK(pktsize == ves, "Packet has incorrect # addresses%s",
+                       pktver == 2 ? " or missing auth fields" : "");
 
        /* auth type check */
        if (version == 2)
@@ -296,6 +315,7 @@ ssize_t vrrp_pkt_parse_datagram(int family, int version, struct msghdr *m,
        /* Addresses check */
        char vbuf[INET6_ADDRSTRLEN];
        uint8_t *p = (uint8_t *)(*pkt)->addrs;
+
        for (uint8_t i = 0; i < (*pkt)->hdr.naddr; i++) {
                VRRP_PKT_VCHECK(inet_ntop(family, p, vbuf, sizeof(vbuf)),
                                "Bad IP address, #%" PRIu8, i);