]> git.proxmox.com Git - mirror_frr.git/commitdiff
bfdd: make bfd_recv_* more generic
authorRafael Zalamena <rzalamena@opensourcerouting.org>
Wed, 29 Aug 2018 17:17:29 +0000 (14:17 -0300)
committerRafael Zalamena <rzalamena@opensourcerouting.org>
Mon, 3 Sep 2018 13:41:33 +0000 (10:41 -0300)
We'll reuse these functions later to receive echo packets, so we need
to despecialize them first. Another improvement here is that we are
going to remove the global buffer variable and opt to use the stack.

Signed-off-by: Rafael Zalamena <rzalamena@opensourcerouting.org>
bfdd/bfd_packet.c

index a2f52364ae82c7a624f943ccb20682f804fd0294..76427c8f54bd599bc9ac44c7c5680ef148db3b53 100644 (file)
@@ -54,8 +54,6 @@ struct bfd_raw_echo_pkt {
 #define IP_ECHO_PKT_LEN (IP_HDR_LEN + UDP_HDR_LEN + BFD_ECHO_PKT_LEN)
 #define UDP_ECHO_PKT_LEN (UDP_HDR_LEN + BFD_ECHO_PKT_LEN)
 
-static uint8_t msgbuf[BFD_PKT_LEN];
-
 
 /*
  * Prototypes
@@ -67,14 +65,14 @@ static int ptm_bfd_echo_loopback(uint8_t *pkt, int pkt_len, struct sockaddr *ss,
 static int ptm_bfd_process_echo_pkt(int s);
 
 static void bfd_sd_reschedule(int sd);
-static ssize_t bfd_recv_ipv4(int sd, bool is_mhop, char *port, size_t portlen,
-                            char *vrfname, size_t vrfnamelen,
-                            struct sockaddr_any *local,
-                            struct sockaddr_any *peer);
-static ssize_t bfd_recv_ipv6(int sd, bool is_mhop, char *port, size_t portlen,
-                            char *vrfname, size_t vrfnamelen,
-                            struct sockaddr_any *local,
-                            struct sockaddr_any *peer);
+ssize_t bfd_recv_ipv4(int sd, uint8_t *msgbuf, size_t msgbuflen, uint8_t *ttl,
+                     char *port, size_t portlen, char *vrfname,
+                     size_t vrfnamelen, struct sockaddr_any *local,
+                     struct sockaddr_any *peer);
+ssize_t bfd_recv_ipv6(int sd, uint8_t *msgbuf, size_t msgbuflen, uint8_t *ttl,
+                     char *port, size_t portlen, char *vrfname,
+                     size_t vrfnamelen, struct sockaddr_any *local,
+                     struct sockaddr_any *peer);
 
 /* socket related prototypes */
 static void bp_set_ipopts(int sd);
@@ -490,10 +488,10 @@ void ptm_bfd_snd(struct bfd_session *bfd, int fbit)
        bfd->stats.tx_ctrl_pkt++;
 }
 
-static ssize_t bfd_recv_ipv4(int sd, bool is_mhop, char *port, size_t portlen,
-                            char *vrfname, size_t vrfnamelen,
-                            struct sockaddr_any *local,
-                            struct sockaddr_any *peer)
+ssize_t bfd_recv_ipv4(int sd, uint8_t *msgbuf, size_t msgbuflen, uint8_t *ttl,
+                     char *port, size_t portlen, char *vrfname,
+                     size_t vrfnamelen, struct sockaddr_any *local,
+                     struct sockaddr_any *peer)
 {
        struct cmsghdr *cm;
        int ifindex;
@@ -505,7 +503,7 @@ static ssize_t bfd_recv_ipv4(int sd, bool is_mhop, char *port, size_t portlen,
 
        /* Prepare the recvmsg params. */
        iov[0].iov_base = msgbuf;
-       iov[0].iov_len = sizeof(msgbuf);
+       iov[0].iov_len = msgbuflen;
 
        memset(&msghdr, 0, sizeof(msghdr));
        msghdr.msg_name = &msgaddr;
@@ -536,16 +534,14 @@ static ssize_t bfd_recv_ipv4(int sd, bool is_mhop, char *port, size_t portlen,
                switch (cm->cmsg_type) {
 #ifdef BFD_LINUX
                case IP_TTL: {
-                       uint32_t ttl;
-
-                       memcpy(&ttl, CMSG_DATA(cm), sizeof(ttl));
-                       if ((is_mhop == false) && (ttl != BFD_TTL_VAL)) {
-                               log_debug(
-                                       "ipv4-recv: invalid TTL from %s (expected %d, got %d flags %d)",
-                                       satostr(peer), ttl, BFD_TTL_VAL,
-                                       msghdr.msg_flags);
+                       uint32_t ttlval;
+
+                       memcpy(&ttlval, CMSG_DATA(cm), sizeof(ttlval));
+                       if (ttlval > 255) {
+                               log_debug("ipv4-recv: invalid TTL: %u", ttlval);
                                return -1;
                        }
+                       *ttl = ttlval;
                        break;
                }
 
@@ -565,16 +561,7 @@ static ssize_t bfd_recv_ipv4(int sd, bool is_mhop, char *port, size_t portlen,
 #endif /* BFD_LINUX */
 #ifdef BFD_BSD
                case IP_RECVTTL: {
-                       uint8_t ttl;
-
-                       memcpy(&ttl, CMSG_DATA(cm), sizeof(ttl));
-                       if ((is_mhop == false) && (ttl != BFD_TTL_VAL)) {
-                               log_debug(
-                                       "ipv4-recv: invalid TTL from %s (expected %d, got %d flags %d)",
-                                       satostr(peer), ttl, BFD_TTL_VAL,
-                                       msghdr.msg_flags);
-                               return -1;
-                       }
+                       memcpy(ttl, CMSG_DATA(cm), sizeof(*ttl));
                        break;
                }
 
@@ -609,9 +596,10 @@ static ssize_t bfd_recv_ipv4(int sd, bool is_mhop, char *port, size_t portlen,
        return mlen;
 }
 
-ssize_t bfd_recv_ipv6(int sd, bool is_mhop, char *port, size_t portlen,
-                     char *vrfname, size_t vrfnamelen,
-                     struct sockaddr_any *local, struct sockaddr_any *peer)
+ssize_t bfd_recv_ipv6(int sd, uint8_t *msgbuf, size_t msgbuflen, uint8_t *ttl,
+                     char *port, size_t portlen, char *vrfname,
+                     size_t vrfnamelen, struct sockaddr_any *local,
+                     struct sockaddr_any *peer)
 {
        struct cmsghdr *cm;
        struct in6_pktinfo *pi6 = NULL;
@@ -625,7 +613,7 @@ ssize_t bfd_recv_ipv6(int sd, bool is_mhop, char *port, size_t portlen,
 
        /* Prepare the recvmsg params. */
        iov[0].iov_base = msgbuf;
-       iov[0].iov_len = sizeof(msgbuf);
+       iov[0].iov_len = msgbuflen;
 
        memset(&msghdr6, 0, sizeof(msghdr6));
        msghdr6.msg_name = &msgaddr6;
@@ -655,13 +643,12 @@ ssize_t bfd_recv_ipv6(int sd, bool is_mhop, char *port, size_t portlen,
 
                if (cm->cmsg_type == IPV6_HOPLIMIT) {
                        memcpy(&ttlval, CMSG_DATA(cm), sizeof(ttlval));
-                       if ((is_mhop == false) && (ttlval != BFD_TTL_VAL)) {
-                               log_debug(
-                                       "ipv6-recv: invalid TTL from %s (expected %d, got %d flags %d)",
-                                       satostr(peer), ttlval, BFD_TTL_VAL,
-                                       msghdr6.msg_flags);
+                       if (ttlval > 255) {
+                               log_debug("ipv6-recv: invalid TTL: %u", ttlval);
                                return -1;
                        }
+
+                       *ttl = ttlval;
                } else if (cm->cmsg_type == IPV6_PKTINFO) {
                        pi6 = (struct in6_pktinfo *)CMSG_DATA(cm);
                        if (pi6) {
@@ -752,8 +739,10 @@ int bfd_recv_cb(struct thread *t)
        bool is_mhop;
        ssize_t mlen = 0;
        uint32_t oldEchoXmt_TO, oldXmtTime;
+       uint8_t ttl;
        struct sockaddr_any local, peer;
        char port[MAXNAMELEN + 1], vrfname[MAXNAMELEN + 1];
+       uint8_t msgbuf[1516];
 
        /* Schedule next read. */
        bfd_sd_reschedule(sd);
@@ -774,12 +763,14 @@ int bfd_recv_cb(struct thread *t)
        is_mhop = false;
        if (sd == bglobal.bg_shop || sd == bglobal.bg_mhop) {
                is_mhop = sd == bglobal.bg_mhop;
-               mlen = bfd_recv_ipv4(sd, is_mhop, port, sizeof(port), vrfname,
-                                    sizeof(vrfname), &local, &peer);
+               mlen = bfd_recv_ipv4(sd, msgbuf, sizeof(msgbuf), &ttl, port,
+                                    sizeof(port), vrfname, sizeof(vrfname),
+                                    &local, &peer);
        } else if (sd == bglobal.bg_shop6 || sd == bglobal.bg_mhop6) {
                is_mhop = sd == bglobal.bg_mhop6;
-               mlen = bfd_recv_ipv6(sd, is_mhop, port, sizeof(port), vrfname,
-                                    sizeof(vrfname), &local, &peer);
+               mlen = bfd_recv_ipv6(sd, msgbuf, sizeof(msgbuf), &ttl, port,
+                                    sizeof(port), vrfname, sizeof(vrfname),
+                                    &local, &peer);
        }
 
        /* Implement RFC 5880 6.8.6 */
@@ -789,6 +780,13 @@ int bfd_recv_cb(struct thread *t)
                return 0;
        }
 
+       /* Validate packet TTL. */
+       if ((is_mhop == false) && (ttl != BFD_TTL_VAL)) {
+               cp_debug(is_mhop, &peer, &local, port, vrfname,
+                        "invalid TTL: %d expected %d", ttl, BFD_TTL_VAL);
+               return 0;
+       }
+
        /*
         * Parse the control header for inconsistencies:
         * - Invalid version;