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.c189
1 files changed, 105 insertions, 84 deletions
diff --git a/bfdd/bfd_packet.c b/bfdd/bfd_packet.c
index 93677ec85a..f3acfa4167 100644
--- a/bfdd/bfd_packet.c
+++ b/bfdd/bfd_packet.c
@@ -37,15 +37,14 @@
#include "bfd.h"
-
/*
* Prototypes
*/
-static int ptm_bfd_process_echo_pkt(int s);
+static int ptm_bfd_process_echo_pkt(struct bfd_vrf_global *bvrf, int s);
int _ptm_bfd_send(struct bfd_session *bs, uint16_t *port, const void *data,
size_t datalen);
-static void bfd_sd_reschedule(int sd);
+static void bfd_sd_reschedule(struct bfd_vrf_global *bvrf, int sd);
ssize_t bfd_recv_ipv4(int sd, uint8_t *msgbuf, size_t msgbuflen, uint8_t *ttl,
ifindex_t *ifindex, struct sockaddr_any *local,
struct sockaddr_any *peer);
@@ -54,7 +53,8 @@ ssize_t bfd_recv_ipv6(int sd, uint8_t *msgbuf, size_t msgbuflen, uint8_t *ttl,
struct sockaddr_any *peer);
int bp_udp_send(int sd, uint8_t ttl, uint8_t *data, size_t datalen,
struct sockaddr *to, socklen_t tolen);
-int bp_bfd_echo_in(int sd, uint8_t *ttl, uint32_t *my_discr);
+int bp_bfd_echo_in(struct bfd_vrf_global *bvrf, int sd,
+ uint8_t *ttl, uint32_t *my_discr);
/* socket related prototypes */
static void bp_set_ipopts(int sd);
@@ -129,7 +129,10 @@ void ptm_bfd_echo_snd(struct bfd_session *bfd)
struct bfd_echo_pkt bep;
struct sockaddr_in sin;
struct sockaddr_in6 sin6;
+ struct bfd_vrf_global *bvrf = bfd_vrf_look_by_session(bfd);
+ if (!bvrf)
+ return;
if (!BFD_CHECK_FLAG(bfd->flags, BFD_SESS_FLAG_ECHO_ACTIVE))
BFD_SET_FLAG(bfd->flags, BFD_SESS_FLAG_ECHO_ACTIVE);
@@ -139,7 +142,7 @@ void ptm_bfd_echo_snd(struct bfd_session *bfd)
bep.my_discr = htonl(bfd->discrs.my_discr);
if (BFD_CHECK_FLAG(bfd->flags, BFD_SESS_FLAG_IPV6)) {
- sd = bglobal.bg_echov6;
+ sd = bvrf->bg_echov6;
memset(&sin6, 0, sizeof(sin6));
sin6.sin6_family = AF_INET6;
memcpy(&sin6.sin6_addr, &bfd->key.peer, sizeof(sin6.sin6_addr));
@@ -154,7 +157,7 @@ void ptm_bfd_echo_snd(struct bfd_session *bfd)
sa = (struct sockaddr *)&sin6;
salen = sizeof(sin6);
} else {
- sd = bglobal.bg_echo;
+ sd = bvrf->bg_echo;
memset(&sin6, 0, sizeof(sin6));
sin.sin_family = AF_INET;
memcpy(&sin.sin_addr, &bfd->key.peer, sizeof(sin.sin_addr));
@@ -174,14 +177,14 @@ void ptm_bfd_echo_snd(struct bfd_session *bfd)
bfd->stats.tx_echo_pkt++;
}
-static int ptm_bfd_process_echo_pkt(int s)
+static int ptm_bfd_process_echo_pkt(struct bfd_vrf_global *bvrf, int s)
{
struct bfd_session *bfd;
uint32_t my_discr = 0;
uint8_t ttl = 0;
/* Receive and parse echo packet. */
- if (bp_bfd_echo_in(s, &ttl, &my_discr) == -1)
+ if (bp_bfd_echo_in(bvrf, s, &ttl, &my_discr) == -1)
return 0;
/* Your discriminator not zero - use it to find session */
@@ -218,6 +221,10 @@ void ptm_bfd_snd(struct bfd_session *bfd, int fbit)
BFD_SETVER(cp.diag, BFD_VERSION);
cp.flags = 0;
BFD_SETSTATE(cp.flags, bfd->ses_state);
+
+ if (BFD_CHECK_FLAG(bfd->flags, BFD_SESS_FLAG_CBIT))
+ BFD_SETCBIT(cp.flags, BFD_CBIT);
+
BFD_SETDEMANDBIT(cp.flags, BFD_DEF_DEMAND);
/*
@@ -441,32 +448,32 @@ ssize_t bfd_recv_ipv6(int sd, uint8_t *msgbuf, size_t msgbuflen, uint8_t *ttl,
return mlen;
}
-static void bfd_sd_reschedule(int sd)
+static void bfd_sd_reschedule(struct bfd_vrf_global *bvrf, int sd)
{
- if (sd == bglobal.bg_shop) {
- THREAD_OFF(bglobal.bg_ev[0]);
- thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_shop,
- &bglobal.bg_ev[0]);
- } else if (sd == bglobal.bg_mhop) {
- THREAD_OFF(bglobal.bg_ev[1]);
- thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_mhop,
- &bglobal.bg_ev[1]);
- } else if (sd == bglobal.bg_shop6) {
- THREAD_OFF(bglobal.bg_ev[2]);
- thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_shop6,
- &bglobal.bg_ev[2]);
- } else if (sd == bglobal.bg_mhop6) {
- THREAD_OFF(bglobal.bg_ev[3]);
- thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_mhop6,
- &bglobal.bg_ev[3]);
- } else if (sd == bglobal.bg_echo) {
- THREAD_OFF(bglobal.bg_ev[4]);
- thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_echo,
- &bglobal.bg_ev[4]);
- } else if (sd == bglobal.bg_echov6) {
- THREAD_OFF(bglobal.bg_ev[5]);
- thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_echov6,
- &bglobal.bg_ev[5]);
+ if (sd == bvrf->bg_shop) {
+ THREAD_OFF(bvrf->bg_ev[0]);
+ thread_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_shop,
+ &bvrf->bg_ev[0]);
+ } else if (sd == bvrf->bg_mhop) {
+ THREAD_OFF(bvrf->bg_ev[1]);
+ thread_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_mhop,
+ &bvrf->bg_ev[1]);
+ } else if (sd == bvrf->bg_shop6) {
+ THREAD_OFF(bvrf->bg_ev[2]);
+ thread_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_shop6,
+ &bvrf->bg_ev[2]);
+ } else if (sd == bvrf->bg_mhop6) {
+ THREAD_OFF(bvrf->bg_ev[3]);
+ thread_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_mhop6,
+ &bvrf->bg_ev[3]);
+ } else if (sd == bvrf->bg_echo) {
+ THREAD_OFF(bvrf->bg_ev[4]);
+ thread_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_echo,
+ &bvrf->bg_ev[4]);
+ } else if (sd == bvrf->bg_echov6) {
+ THREAD_OFF(bvrf->bg_ev[5]);
+ thread_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_echov6,
+ &bvrf->bg_ev[5]);
}
}
@@ -518,13 +525,16 @@ int bfd_recv_cb(struct thread *t)
ifindex_t ifindex = IFINDEX_INTERNAL;
struct sockaddr_any local, peer;
uint8_t msgbuf[1516];
+ struct bfd_vrf_global *bvrf = THREAD_ARG(t);
+ if (bvrf)
+ vrfid = bvrf->vrf->vrf_id;
/* Schedule next read. */
- bfd_sd_reschedule(sd);
+ bfd_sd_reschedule(bvrf, sd);
/* Handle echo packets. */
- if (sd == bglobal.bg_echo || sd == bglobal.bg_echov6) {
- ptm_bfd_process_echo_pkt(sd);
+ if (sd == bvrf->bg_echo || sd == bvrf->bg_echov6) {
+ ptm_bfd_process_echo_pkt(bvrf, sd);
return 0;
}
@@ -534,12 +544,12 @@ int bfd_recv_cb(struct thread *t)
/* Handle control packets. */
is_mhop = false;
- if (sd == bglobal.bg_shop || sd == bglobal.bg_mhop) {
- is_mhop = sd == bglobal.bg_mhop;
+ if (sd == bvrf->bg_shop || sd == bvrf->bg_mhop) {
+ is_mhop = sd == bvrf->bg_mhop;
mlen = bfd_recv_ipv4(sd, msgbuf, sizeof(msgbuf), &ttl, &ifindex,
&local, &peer);
- } else if (sd == bglobal.bg_shop6 || sd == bglobal.bg_mhop6) {
- is_mhop = sd == bglobal.bg_mhop6;
+ } else if (sd == bvrf->bg_shop6 || sd == bvrf->bg_mhop6) {
+ is_mhop = sd == bvrf->bg_mhop6;
mlen = bfd_recv_ipv6(sd, msgbuf, sizeof(msgbuf), &ttl, &ifindex,
&local, &peer);
}
@@ -640,6 +650,11 @@ int bfd_recv_cb(struct thread *t)
ntohl(cp->timers.required_min_echo);
bfd->remote_detect_mult = cp->detect_mult;
+ if (BFD_GETCBIT(cp->flags))
+ bfd->remote_cbit = 1;
+ else
+ bfd->remote_cbit = 0;
+
/* State switch from section 6.2. */
bs_state_handler(bfd, BFD_GETSTATE(cp->flags));
@@ -682,7 +697,8 @@ int bfd_recv_cb(struct thread *t)
*
* Returns -1 on error or loopback or 0 on success.
*/
-int bp_bfd_echo_in(int sd, uint8_t *ttl, uint32_t *my_discr)
+int bp_bfd_echo_in(struct bfd_vrf_global *bvrf, int sd,
+ uint8_t *ttl, uint32_t *my_discr)
{
struct bfd_echo_pkt *bep;
ssize_t rlen;
@@ -691,7 +707,7 @@ int bp_bfd_echo_in(int sd, uint8_t *ttl, uint32_t *my_discr)
vrf_id_t vrfid = VRF_DEFAULT;
uint8_t msgbuf[1516];
- if (sd == bglobal.bg_echo)
+ if (sd == bvrf->bg_echo)
rlen = bfd_recv_ipv4(sd, msgbuf, sizeof(msgbuf), ttl, &ifindex,
&local, &peer);
else
@@ -709,7 +725,7 @@ int bp_bfd_echo_in(int sd, uint8_t *ttl, uint32_t *my_discr)
if (*ttl == BFD_TTL_VAL) {
bp_udp_send(sd, *ttl - 1, msgbuf, rlen,
(struct sockaddr *)&peer,
- (sd == bglobal.bg_echo) ? sizeof(peer.sa_sin)
+ (sd == bvrf->bg_echo) ? sizeof(peer.sa_sin)
: sizeof(peer.sa_sin6));
return -1;
}
@@ -872,25 +888,28 @@ static void bp_bind_ip(int sd, uint16_t port)
log_fatal("bind-ip: bind: %s", strerror(errno));
}
-int bp_udp_shop(void)
+int bp_udp_shop(vrf_id_t vrf_id)
{
int sd;
- sd = socket(AF_INET, SOCK_DGRAM, PF_UNSPEC);
+ frr_elevate_privs(&bglobal.bfdd_privs) {
+ sd = vrf_socket(AF_INET, SOCK_DGRAM, PF_UNSPEC, vrf_id, NULL);
+ }
if (sd == -1)
log_fatal("udp-shop: socket: %s", strerror(errno));
bp_set_ipopts(sd);
bp_bind_ip(sd, BFD_DEFDESTPORT);
-
return sd;
}
-int bp_udp_mhop(void)
+int bp_udp_mhop(vrf_id_t vrf_id)
{
int sd;
- sd = socket(AF_INET, SOCK_DGRAM, PF_UNSPEC);
+ frr_elevate_privs(&bglobal.bfdd_privs) {
+ sd = vrf_socket(AF_INET, SOCK_DGRAM, PF_UNSPEC, vrf_id, NULL);
+ }
if (sd == -1)
log_fatal("udp-mhop: socket: %s", strerror(errno));
@@ -905,8 +924,18 @@ int bp_peer_socket(const struct bfd_session *bs)
int sd, pcount;
struct sockaddr_in sin;
static int srcPort = BFD_SRCPORTINIT;
+ const char *device_to_bind = NULL;
- sd = socket(AF_INET, SOCK_DGRAM, PF_UNSPEC);
+ if (bs->key.ifname[0])
+ device_to_bind = (const char *)bs->key.ifname;
+ else if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH)
+ && bs->key.vrfname[0])
+ device_to_bind = (const char *)bs->key.vrfname;
+
+ frr_elevate_privs(&bglobal.bfdd_privs) {
+ sd = vrf_socket(AF_INET, SOCK_DGRAM, PF_UNSPEC,
+ bs->vrf->vrf_id, device_to_bind);
+ }
if (sd == -1) {
log_error("ipv4-new: failed to create socket: %s",
strerror(errno));
@@ -925,19 +954,6 @@ int bp_peer_socket(const struct bfd_session *bs)
return -1;
}
- if (bs->key.ifname[0]) {
- if (bp_bind_dev(sd, bs->key.ifname) != 0) {
- close(sd);
- return -1;
- }
- } else if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH)
- && bs->key.vrfname[0]) {
- if (bp_bind_dev(sd, bs->key.vrfname) != 0) {
- close(sd);
- return -1;
- }
- }
-
/* Find an available source port in the proper range */
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
@@ -975,8 +991,18 @@ int bp_peer_socketv6(const struct bfd_session *bs)
int sd, pcount;
struct sockaddr_in6 sin6;
static int srcPort = BFD_SRCPORTINIT;
+ const char *device_to_bind = NULL;
- sd = socket(AF_INET6, SOCK_DGRAM, PF_UNSPEC);
+ if (bs->key.ifname[0])
+ device_to_bind = (const char *)bs->key.ifname;
+ else if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH)
+ && bs->key.vrfname[0])
+ device_to_bind = (const char *)bs->key.vrfname;
+
+ frr_elevate_privs(&bglobal.bfdd_privs) {
+ sd = vrf_socket(AF_INET6, SOCK_DGRAM, PF_UNSPEC,
+ bs->vrf->vrf_id, device_to_bind);
+ }
if (sd == -1) {
log_error("ipv6-new: failed to create socket: %s",
strerror(errno));
@@ -1005,19 +1031,6 @@ int bp_peer_socketv6(const struct bfd_session *bs)
if (IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr))
sin6.sin6_scope_id = bs->ifp->ifindex;
- if (bs->key.ifname[0]) {
- if (bp_bind_dev(sd, bs->key.ifname) != 0) {
- close(sd);
- return -1;
- }
- } else if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH)
- && bs->key.vrfname[0]) {
- if (bp_bind_dev(sd, bs->key.vrfname) != 0) {
- close(sd);
- return -1;
- }
- }
-
pcount = 0;
do {
if ((++pcount) > (BFD_SRCPORTMAX - BFD_SRCPORTINIT)) {
@@ -1102,11 +1115,13 @@ static void bp_bind_ipv6(int sd, uint16_t port)
log_fatal("bind-ipv6: bind: %s", strerror(errno));
}
-int bp_udp6_shop(void)
+int bp_udp6_shop(vrf_id_t vrf_id)
{
int sd;
- sd = socket(AF_INET6, SOCK_DGRAM, PF_UNSPEC);
+ frr_elevate_privs(&bglobal.bfdd_privs) {
+ sd = vrf_socket(AF_INET6, SOCK_DGRAM, PF_UNSPEC, vrf_id, NULL);
+ }
if (sd == -1)
log_fatal("udp6-shop: socket: %s", strerror(errno));
@@ -1116,11 +1131,13 @@ int bp_udp6_shop(void)
return sd;
}
-int bp_udp6_mhop(void)
+int bp_udp6_mhop(vrf_id_t vrf_id)
{
int sd;
- sd = socket(AF_INET6, SOCK_DGRAM, PF_UNSPEC);
+ frr_elevate_privs(&bglobal.bfdd_privs) {
+ sd = vrf_socket(AF_INET6, SOCK_DGRAM, PF_UNSPEC, vrf_id, NULL);
+ }
if (sd == -1)
log_fatal("udp6-mhop: socket: %s", strerror(errno));
@@ -1130,11 +1147,13 @@ int bp_udp6_mhop(void)
return sd;
}
-int bp_echo_socket(void)
+int bp_echo_socket(vrf_id_t vrf_id)
{
int s;
- s = socket(AF_INET, SOCK_DGRAM, 0);
+ frr_elevate_privs(&bglobal.bfdd_privs) {
+ s = vrf_socket(AF_INET, SOCK_DGRAM, 0, vrf_id, NULL);
+ }
if (s == -1)
log_fatal("echo-socket: socket: %s", strerror(errno));
@@ -1144,11 +1163,13 @@ int bp_echo_socket(void)
return s;
}
-int bp_echov6_socket(void)
+int bp_echov6_socket(vrf_id_t vrf_id)
{
int s;
- s = socket(AF_INET6, SOCK_DGRAM, 0);
+ frr_elevate_privs(&bglobal.bfdd_privs) {
+ s = vrf_socket(AF_INET6, SOCK_DGRAM, 0, vrf_id, NULL);
+ }
if (s == -1)
log_fatal("echov6-socket: socket: %s", strerror(errno));