summaryrefslogtreecommitdiff
path: root/bfdd/bfd_packet.c
diff options
context:
space:
mode:
Diffstat (limited to 'bfdd/bfd_packet.c')
-rw-r--r--bfdd/bfd_packet.c52
1 files changed, 48 insertions, 4 deletions
diff --git a/bfdd/bfd_packet.c b/bfdd/bfd_packet.c
index dadf9c25d7..8110f434c2 100644
--- a/bfdd/bfd_packet.c
+++ b/bfdd/bfd_packet.c
@@ -12,6 +12,11 @@
*/
#include <zebra.h>
+#include <sys/ioctl.h>
+
+#ifdef GNU_LINUX
+#include <linux/filter.h>
+#endif
#ifdef BFD_LINUX
#include <linux/if_packet.h>
@@ -768,6 +773,37 @@ static void cp_debug(bool mhop, struct sockaddr_any *peer,
mhop ? "yes" : "no", peerstr, localstr, portstr, vrfstr);
}
+static bool bfd_check_auth(const struct bfd_session *bfd,
+ const struct bfd_pkt *cp)
+{
+ if (CHECK_FLAG(cp->flags, BFD_ABIT)) {
+ /* RFC5880 4.1: Authentication Section is present. */
+ struct bfd_auth *auth = (struct bfd_auth *)(cp + 1);
+ uint16_t pkt_auth_type = ntohs(auth->type);
+
+ if (cp->len < BFD_PKT_LEN + sizeof(struct bfd_auth))
+ return false;
+
+ if (cp->len < BFD_PKT_LEN + auth->length)
+ return false;
+
+ switch (pkt_auth_type) {
+ case BFD_AUTH_NULL:
+ return false;
+ case BFD_AUTH_SIMPLE:
+ /* RFC5880 6.7: To be finshed. */
+ return false;
+ case BFD_AUTH_CRYPTOGRAPHIC:
+ /* RFC5880 6.7: To be finshed. */
+ return false;
+ default:
+ /* RFC5880 6.7: To be finshed. */
+ return false;
+ }
+ }
+ return true;
+}
+
void bfd_recv_cb(struct event *t)
{
int sd = EVENT_FD(t);
@@ -884,7 +920,7 @@ void bfd_recv_cb(struct event *t)
/*
* We may have a situation where received packet is on wrong vrf
*/
- if (bfd && bfd->vrf && bfd->vrf != bvrf->vrf) {
+ if (bfd && bfd->vrf && bfd->vrf->vrf_id != vrfid) {
cp_debug(is_mhop, &peer, &local, ifindex, vrfid,
"wrong vrfid.");
return;
@@ -938,6 +974,13 @@ void bfd_recv_cb(struct event *t)
bfd->discrs.remote_discr = ntohl(cp->discrs.my_discr);
+ /* Check authentication. */
+ if (!bfd_check_auth(bfd, cp)) {
+ cp_debug(is_mhop, &peer, &local, ifindex, vrfid,
+ "Authentication failed");
+ return;
+ }
+
/* Save remote diagnostics before state switch. */
bfd->remote_diag = cp->diag & BFD_DIAGMASK;
@@ -1710,9 +1753,10 @@ void bfd_peer_mac_set(int sd, struct bfd_session *bfd,
strlcpy(arpreq_.arp_dev, ifp->name, sizeof(arpreq_.arp_dev));
if (ioctl(sd, SIOCGARP, &arpreq_) < 0) {
- zlog_warn(
- "BFD: getting peer's mac on %s failed error %s",
- ifp->name, strerror(errno));
+ if (bglobal.debug_network)
+ zlog_debug(
+ "BFD: getting peer's mac on %s failed error %s",
+ ifp->name, strerror(errno));
UNSET_FLAG(bfd->flags, BFD_SESS_FLAG_MAC_SET);
memset(bfd->peer_hw_addr, 0, sizeof(bfd->peer_hw_addr));