static void bfd_sd_reschedule(int sd);
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,
+ ifindex_t *ifindex, 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,
+ ifindex_t *ifindex, struct sockaddr_any *local,
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);
if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_IPV6)) {
memset(&sin6, 0, sizeof(sin6));
sin6.sin6_family = AF_INET6;
- sin6.sin6_addr = bs->shop.peer.sa_sin6.sin6_addr;
+ memcpy(&sin6.sin6_addr, &bs->key.peer, sizeof(sin6.sin6_addr));
+ if (IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr))
+ sin6.sin6_scope_id = bs->ifp->ifindex;
+
sin6.sin6_port =
(port) ? *port
: (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH))
} else {
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
- sin.sin_addr = bs->shop.peer.sa_sin.sin_addr;
+ memcpy(&sin.sin_addr, &bs->key.peer, sizeof(sin.sin_addr));
sin.sin_port =
(port) ? *port
: (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH))
void ptm_bfd_echo_snd(struct bfd_session *bfd)
{
- struct sockaddr_any *sa;
+ struct sockaddr *sa;
socklen_t salen;
int sd;
struct bfd_echo_pkt bep;
bep.len = BFD_ECHO_PKT_LEN;
bep.my_discr = htonl(bfd->discrs.my_discr);
- sa = BFD_CHECK_FLAG(bfd->flags, BFD_SESS_FLAG_MH) ? &bfd->mhop.peer
- : &bfd->shop.peer;
if (BFD_CHECK_FLAG(bfd->flags, BFD_SESS_FLAG_IPV6)) {
sd = bglobal.bg_echov6;
- sin6 = sa->sa_sin6;
+ memset(&sin6, 0, sizeof(sin6));
+ sin6.sin6_family = AF_INET6;
+ memcpy(&sin6.sin6_addr, &bfd->key.peer, sizeof(sin6.sin6_addr));
+ if (bfd->ifp && IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr))
+ sin6.sin6_scope_id = bfd->ifp->ifindex;
+
sin6.sin6_port = htons(BFD_DEF_ECHO_PORT);
#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
sin6.sin6_len = sizeof(sin6);
#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
- sa = (struct sockaddr_any *)&sin6;
+ sa = (struct sockaddr *)&sin6;
salen = sizeof(sin6);
} else {
sd = bglobal.bg_echo;
- sin = sa->sa_sin;
+ memset(&sin6, 0, sizeof(sin6));
+ sin.sin_family = AF_INET;
+ memcpy(&sin.sin_addr, &bfd->key.peer, sizeof(sin.sin_addr));
sin.sin_port = htons(BFD_DEF_ECHO_PORT);
#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
sin.sin_len = sizeof(sin);
#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
- sa = (struct sockaddr_any *)&sin;
+ sa = (struct sockaddr *)&sin;
salen = sizeof(sin);
}
- if (bp_udp_send(sd, BFD_TTL_VAL, (uint8_t *)&bep, sizeof(bep),
- (struct sockaddr *)sa, salen)
+ if (bp_udp_send(sd, BFD_TTL_VAL, (uint8_t *)&bep, sizeof(bep), sa,
+ salen)
== -1)
return;
cp.flags = 0;
BFD_SETSTATE(cp.flags, bfd->ses_state);
BFD_SETDEMANDBIT(cp.flags, BFD_DEF_DEMAND);
- BFD_SETPBIT(cp.flags, bfd->polling);
+
+ /*
+ * Polling and Final can't be set at the same time.
+ *
+ * RFC 5880, Section 6.5.
+ */
BFD_SETFBIT(cp.flags, fbit);
+ if (fbit == 0)
+ BFD_SETPBIT(cp.flags, bfd->polling);
+
cp.detect_mult = bfd->detect_mult;
cp.len = BFD_PKT_LEN;
cp.discrs.my_discr = htonl(bfd->discrs.my_discr);
cp.discrs.remote_discr = htonl(bfd->discrs.remote_discr);
if (bfd->polling) {
cp.timers.desired_min_tx =
- htonl(bfd->new_timers.desired_min_tx);
+ htonl(bfd->timers.desired_min_tx);
cp.timers.required_min_rx =
- htonl(bfd->new_timers.required_min_rx);
+ htonl(bfd->timers.required_min_rx);
} else {
- cp.timers.desired_min_tx = htonl(bfd->timers.desired_min_tx);
- cp.timers.required_min_rx = htonl(bfd->timers.required_min_rx);
+ /*
+ * We can only announce current setting on poll, this
+ * avoids timing mismatch with our peer and give it
+ * the oportunity to learn. See `bs_final_handler` for
+ * more information.
+ */
+ cp.timers.desired_min_tx =
+ htonl(bfd->cur_timers.desired_min_tx);
+ cp.timers.required_min_rx =
+ htonl(bfd->cur_timers.required_min_rx);
}
cp.timers.required_min_echo = htonl(bfd->timers.required_min_echo);
}
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,
+ ifindex_t *ifindex, struct sockaddr_any *local,
struct sockaddr_any *peer)
{
- struct interface *ifp;
struct cmsghdr *cm;
- int ifindex;
ssize_t mlen;
struct sockaddr_in msgaddr;
struct msghdr msghdr;
struct iovec iov[1];
uint8_t cmsgbuf[255];
- port[0] = '\0';
-
/* Prepare the recvmsg params. */
iov[0].iov_base = msgbuf;
iov[0].iov_len = msgbuflen;
local->sa_sin.sin_len = sizeof(local->sa_sin);
#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
- ifp = if_lookup_by_index(pi->ipi_ifindex, VRF_DEFAULT);
- if (ifp == NULL)
- break;
-
- if (strlcpy(port, ifp->name, portlen) >= portlen)
- log_debug(
- "ipv4-recv: interface name truncated");
+ *ifindex = pi->ipi_ifindex;
break;
}
#endif /* BFD_LINUX */
}
/* OS agnostic way of getting interface name. */
- if (port[0] == 0) {
- ifindex = getsockopt_ifindex(AF_INET, &msghdr);
- if (ifindex <= 0)
- return mlen;
-
- ifp = if_lookup_by_index(ifindex, VRF_DEFAULT);
- if (ifp == NULL)
- return mlen;
-
- if (strlcpy(port, ifp->name, portlen) >= portlen)
- log_debug("ipv4-recv: interface name truncated");
- }
+ if (*ifindex == IFINDEX_INTERNAL)
+ *ifindex = getsockopt_ifindex(AF_INET, &msghdr);
return mlen;
}
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,
+ ifindex_t *ifindex, struct sockaddr_any *local,
struct sockaddr_any *peer)
{
- struct interface *ifp;
struct cmsghdr *cm;
struct in6_pktinfo *pi6 = NULL;
- int ifindex = 0;
ssize_t mlen;
uint32_t ttlval;
struct sockaddr_in6 msgaddr6;
local->sa_sin6.sin6_len = sizeof(local->sa_sin6);
#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
- ifindex = pi6->ipi6_ifindex;
- ifp = if_lookup_by_index(ifindex, VRF_DEFAULT);
- if (ifp == NULL)
- break;
-
- if (strlcpy(port, ifp->name, portlen)
- >= portlen)
- log_debug(
- "ipv6-recv: interface name truncated");
+ *ifindex = pi6->ipi6_ifindex;
}
}
}
/* Set scope ID for link local addresses. */
if (IN6_IS_ADDR_LINKLOCAL(&peer->sa_sin6.sin6_addr))
- peer->sa_sin6.sin6_scope_id = ifindex;
+ peer->sa_sin6.sin6_scope_id = *ifindex;
if (IN6_IS_ADDR_LINKLOCAL(&local->sa_sin6.sin6_addr))
- local->sa_sin6.sin6_scope_id = ifindex;
+ local->sa_sin6.sin6_scope_id = *ifindex;
return mlen;
}
}
static void cp_debug(bool mhop, struct sockaddr_any *peer,
- struct sockaddr_any *local, const char *port,
- const char *vrf, const char *fmt, ...)
+ struct sockaddr_any *local, ifindex_t ifindex,
+ vrf_id_t vrfid, const char *fmt, ...)
{
char buf[512], peerstr[128], localstr[128], portstr[64], vrfstr[64];
va_list vl;
else
localstr[0] = 0;
- if (port[0])
- snprintf(portstr, sizeof(portstr), " port:%s", port);
+ if (ifindex != IFINDEX_INTERNAL)
+ snprintf(portstr, sizeof(portstr), " port:%u", ifindex);
else
portstr[0] = 0;
- if (vrf[0])
- snprintf(vrfstr, sizeof(vrfstr), " vrf:%s", port);
+ if (vrfid != VRF_DEFAULT)
+ snprintf(vrfstr, sizeof(vrfstr), " vrf:%u", vrfid);
else
vrfstr[0] = 0;
struct bfd_pkt *cp;
bool is_mhop;
ssize_t mlen = 0;
- uint32_t oldEchoXmt_TO, oldXmtTime;
- uint8_t ttl;
+ uint8_t ttl = 0;
+ vrf_id_t vrfid = VRF_DEFAULT;
+ ifindex_t ifindex = IFINDEX_INTERNAL;
struct sockaddr_any local, peer;
- char port[MAXNAMELEN + 1], vrfname[MAXNAMELEN + 1];
uint8_t msgbuf[1516];
/* Schedule next read. */
}
/* Sanitize input/output. */
- memset(port, 0, sizeof(port));
- memset(vrfname, 0, sizeof(vrfname));
memset(&local, 0, sizeof(local));
memset(&peer, 0, sizeof(peer));
is_mhop = false;
if (sd == bglobal.bg_shop || sd == bglobal.bg_mhop) {
is_mhop = sd == bglobal.bg_mhop;
- mlen = bfd_recv_ipv4(sd, msgbuf, sizeof(msgbuf), &ttl, port,
- sizeof(port), vrfname, sizeof(vrfname),
+ 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;
- mlen = bfd_recv_ipv6(sd, msgbuf, sizeof(msgbuf), &ttl, port,
- sizeof(port), vrfname, sizeof(vrfname),
+ mlen = bfd_recv_ipv6(sd, msgbuf, sizeof(msgbuf), &ttl, &ifindex,
&local, &peer);
}
/* Implement RFC 5880 6.8.6 */
if (mlen < BFD_PKT_LEN) {
- cp_debug(is_mhop, &peer, &local, port, vrfname,
+ cp_debug(is_mhop, &peer, &local, ifindex, vrfid,
"too small (%ld bytes)", mlen);
return 0;
}
/* Validate packet TTL. */
- if ((is_mhop == false) && (ttl != BFD_TTL_VAL)) {
- cp_debug(is_mhop, &peer, &local, port, vrfname,
+ if ((!is_mhop) && (ttl != BFD_TTL_VAL)) {
+ cp_debug(is_mhop, &peer, &local, ifindex, vrfid,
"invalid TTL: %d expected %d", ttl, BFD_TTL_VAL);
return 0;
}
*/
cp = (struct bfd_pkt *)(msgbuf);
if (BFD_GETVER(cp->diag) != BFD_VERSION) {
- cp_debug(is_mhop, &peer, &local, port, vrfname,
+ cp_debug(is_mhop, &peer, &local, ifindex, vrfid,
"bad version %d", BFD_GETVER(cp->diag));
return 0;
}
if (cp->detect_mult == 0) {
- cp_debug(is_mhop, &peer, &local, port, vrfname,
+ cp_debug(is_mhop, &peer, &local, ifindex, vrfid,
"detect multiplier set to zero");
return 0;
}
if ((cp->len < BFD_PKT_LEN) || (cp->len > mlen)) {
- cp_debug(is_mhop, &peer, &local, port, vrfname, "too small");
+ cp_debug(is_mhop, &peer, &local, ifindex, vrfid, "too small");
return 0;
}
if (cp->discrs.my_discr == 0) {
- cp_debug(is_mhop, &peer, &local, port, vrfname,
+ cp_debug(is_mhop, &peer, &local, ifindex, vrfid,
"'my discriminator' is zero");
return 0;
}
/* Find the session that this packet belongs. */
- bfd = ptm_bfd_sess_find(cp, port, &peer, &local, vrfname, is_mhop);
+ bfd = ptm_bfd_sess_find(cp, &peer, &local, ifindex, vrfid, is_mhop);
if (bfd == NULL) {
- cp_debug(is_mhop, &peer, &local, port, vrfname,
+ cp_debug(is_mhop, &peer, &local, ifindex, vrfid,
"no session found");
return 0;
}
*/
if (is_mhop) {
if ((BFD_TTL_VAL - bfd->mh_ttl) > BFD_TTL_VAL) {
- cp_debug(is_mhop, &peer, &local, port, vrfname,
+ cp_debug(is_mhop, &peer, &local, ifindex, vrfid,
"exceeded max hop count (expected %d, got %d)",
bfd->mh_ttl, BFD_TTL_VAL);
return 0;
}
- } else if (bfd->local_ip.sa_sin.sin_family == AF_UNSPEC) {
- bfd->local_ip = local;
+ } else if (bfd->local_address.sa_sin.sin_family == AF_UNSPEC) {
+ bfd->local_address = local;
}
/*
* packet came in.
*/
if (bfd->ifp == NULL)
- bfd->ifp = if_lookup_by_name(port, VRF_DEFAULT);
+ bfd->ifp = if_lookup_by_index(ifindex, vrfid);
/* Log remote discriminator changes. */
if ((bfd->discrs.remote_discr != 0)
&& (bfd->discrs.remote_discr != ntohl(cp->discrs.my_discr)))
- cp_debug(is_mhop, &peer, &local, port, vrfname,
- "remote discriminator mismatch (expected %d, got %d)",
+ cp_debug(is_mhop, &peer, &local, ifindex, vrfid,
+ "remote discriminator mismatch (expected %u, got %u)",
bfd->discrs.remote_discr, ntohl(cp->discrs.my_discr));
bfd->discrs.remote_discr = ntohl(cp->discrs.my_discr);
- /* If received the Final bit, the new values should take effect */
- if (bfd->polling && BFD_GETFBIT(cp->flags)) {
- bfd->timers.desired_min_tx = bfd->new_timers.desired_min_tx;
- bfd->timers.required_min_rx = bfd->new_timers.required_min_rx;
- bfd->new_timers.desired_min_tx = 0;
- bfd->new_timers.required_min_rx = 0;
- bfd->polling = 0;
- }
-
- if (!bfd->demand_mode) {
- /* Compute detect time */
- bfd->detect_TO = cp->detect_mult
- * ((bfd->timers.required_min_rx
- > ntohl(cp->timers.desired_min_tx))
- ? bfd->timers.required_min_rx
- : ntohl(cp->timers.desired_min_tx));
- bfd->remote_detect_mult = cp->detect_mult;
- } else
- cp_debug(is_mhop, &peer, &local, port, vrfname,
- "unsupported demand mode");
-
/* Save remote diagnostics before state switch. */
bfd->remote_diag = cp->diag & BFD_DIAGMASK;
- /* State switch from section 6.8.6 */
- if (BFD_GETSTATE(cp->flags) == PTM_BFD_ADM_DOWN) {
- if (bfd->ses_state != PTM_BFD_DOWN)
- ptm_bfd_ses_dn(bfd, BD_NEIGHBOR_DOWN);
- } else {
- switch (bfd->ses_state) {
- case (PTM_BFD_DOWN):
- if (BFD_GETSTATE(cp->flags) == PTM_BFD_INIT)
- ptm_bfd_ses_up(bfd);
- else if (BFD_GETSTATE(cp->flags) == PTM_BFD_DOWN)
- bfd->ses_state = PTM_BFD_INIT;
- break;
- case (PTM_BFD_INIT):
- if (BFD_GETSTATE(cp->flags) == PTM_BFD_INIT
- || BFD_GETSTATE(cp->flags) == PTM_BFD_UP)
- ptm_bfd_ses_up(bfd);
- break;
- case (PTM_BFD_UP):
- if (BFD_GETSTATE(cp->flags) == PTM_BFD_DOWN)
- ptm_bfd_ses_dn(bfd, BD_NEIGHBOR_DOWN);
- break;
- }
- }
-
- /*
- * Handle echo packet status:
- * - Start echo packets if configured and permitted
- * (required_min_echo > 0);
- * - Stop echo packets if not allowed (required_min_echo == 0);
- * - Recalculate echo packet interval;
- */
- if (BFD_CHECK_FLAG(bfd->flags, BFD_SESS_FLAG_ECHO)) {
- if (BFD_CHECK_FLAG(bfd->flags, BFD_SESS_FLAG_ECHO_ACTIVE)) {
- if (!ntohl(cp->timers.required_min_echo)) {
- ptm_bfd_echo_stop(bfd, 1);
- } else {
- oldEchoXmt_TO = bfd->echo_xmt_TO;
- bfd->echo_xmt_TO =
- bfd->timers.required_min_echo;
- if (ntohl(cp->timers.required_min_echo)
- > bfd->echo_xmt_TO)
- bfd->echo_xmt_TO = ntohl(
- cp->timers.required_min_echo);
- if (oldEchoXmt_TO != bfd->echo_xmt_TO)
- ptm_bfd_echo_start(bfd);
- }
- } else if (ntohl(cp->timers.required_min_echo)) {
- bfd->echo_xmt_TO = bfd->timers.required_min_echo;
- if (ntohl(cp->timers.required_min_echo)
- > bfd->echo_xmt_TO)
- bfd->echo_xmt_TO =
- ntohl(cp->timers.required_min_echo);
- ptm_bfd_echo_start(bfd);
- }
- }
+ /* Update remote timers settings. */
+ bfd->remote_timers.desired_min_tx = ntohl(cp->timers.desired_min_tx);
+ bfd->remote_timers.required_min_rx = ntohl(cp->timers.required_min_rx);
+ bfd->remote_timers.required_min_echo =
+ ntohl(cp->timers.required_min_echo);
+ bfd->remote_detect_mult = cp->detect_mult;
- if (BFD_CHECK_FLAG(bfd->flags, BFD_SESS_FLAG_ECHO_ACTIVE)) {
- bfd->echo_xmt_TO = bfd->timers.required_min_echo;
- if (ntohl(cp->timers.required_min_echo) > bfd->echo_xmt_TO)
- bfd->echo_xmt_TO = ntohl(cp->timers.required_min_echo);
- }
+ /* State switch from section 6.2. */
+ bs_state_handler(bfd, BFD_GETSTATE(cp->flags));
- /* Calculate new transmit time */
- oldXmtTime = bfd->xmt_TO;
- bfd->xmt_TO =
- (bfd->timers.desired_min_tx > ntohl(cp->timers.required_min_rx))
- ? bfd->timers.desired_min_tx
- : ntohl(cp->timers.required_min_rx);
+ /* RFC 5880, Section 6.5: handle POLL/FINAL negotiation sequence. */
+ if (bfd->polling && BFD_GETFBIT(cp->flags)) {
+ /* Disable pooling. */
+ bfd->polling = 0;
- /* If transmit time has changed, and too much time until next xmt,
- * restart
- */
- if (BFD_GETPBIT(cp->flags)) {
- ptm_bfd_xmt_TO(bfd, 1);
- } else if (oldXmtTime != bfd->xmt_TO) {
- /* XXX add some skid to this as well */
- ptm_bfd_start_xmt_timer(bfd, false);
+ /* Handle poll finalization. */
+ bs_final_handler(bfd);
+ } else {
+ /* Received a packet, lets update the receive timer. */
+ bfd_recvtimer_update(bfd);
}
- /* Restart detection timer (packet received) */
- if (!bfd->demand_mode)
- bfd_recvtimer_update(bfd);
+ /* Handle echo timers changes. */
+ bs_echo_timer_handler(bfd);
/*
- * Save the timers and state sent by the remote end
- * for debugging and statistics.
+ * We've received a packet with the POLL bit set, we must send
+ * a control packet back with the FINAL bit set.
+ *
+ * RFC 5880, Section 6.5.
*/
- if (BFD_GETFBIT(cp->flags)) {
- bfd->remote_timers.desired_min_tx =
- ntohl(cp->timers.desired_min_tx);
- bfd->remote_timers.required_min_rx =
- ntohl(cp->timers.required_min_rx);
- bfd->remote_timers.required_min_echo =
- ntohl(cp->timers.required_min_echo);
-
- control_notify_config(BCM_NOTIFY_CONFIG_UPDATE, bfd);
+ if (BFD_GETPBIT(cp->flags)) {
+ /* We are finalizing a poll negotiation. */
+ bs_final_handler(bfd);
+
+ /* Send the control packet with the final bit immediately. */
+ ptm_bfd_snd(bfd, 1);
}
return 0;
struct bfd_echo_pkt *bep;
ssize_t rlen;
struct sockaddr_any local, peer;
- char port[MAXNAMELEN + 1], vrfname[MAXNAMELEN + 1];
+ ifindex_t ifindex = IFINDEX_INTERNAL;
+ vrf_id_t vrfid = VRF_DEFAULT;
uint8_t msgbuf[1516];
if (sd == bglobal.bg_echo)
- rlen = bfd_recv_ipv4(sd, msgbuf, sizeof(msgbuf), ttl, port,
- sizeof(port), vrfname, sizeof(vrfname),
+ rlen = bfd_recv_ipv4(sd, msgbuf, sizeof(msgbuf), ttl, &ifindex,
&local, &peer);
else
- rlen = bfd_recv_ipv6(sd, msgbuf, sizeof(msgbuf), ttl, port,
- sizeof(port), vrfname, sizeof(vrfname),
+ rlen = bfd_recv_ipv6(sd, msgbuf, sizeof(msgbuf), ttl, &ifindex,
&local, &peer);
/* Short packet, better not risk reading it. */
if (rlen < (ssize_t)sizeof(*bep)) {
- cp_debug(false, &peer, &local, port, vrfname,
+ cp_debug(false, &peer, &local, ifindex, vrfid,
"small echo packet");
return -1;
}
bep = (struct bfd_echo_pkt *)msgbuf;
*my_discr = ntohl(bep->my_discr);
if (*my_discr == 0) {
- cp_debug(false, &peer, &local, port, vrfname,
+ cp_debug(false, &peer, &local, ifindex, vrfid,
"invalid echo packet discriminator (zero)");
return -1;
}
return sd;
}
-int bp_peer_socket(struct bfd_peer_cfg *bpc)
+int bp_peer_socket(const struct bfd_session *bs)
{
int sd, pcount;
struct sockaddr_in sin;
return -1;
}
- if (bpc->bpc_has_localif) {
- if (bp_bind_dev(sd, bpc->bpc_localif) != 0) {
+ if (bs->key.ifname[0]) {
+ if (bp_bind_dev(sd, bs->key.ifname) != 0) {
close(sd);
return -1;
}
- } else if (bpc->bpc_mhop && bpc->bpc_has_vrfname) {
- if (bp_bind_dev(sd, bpc->bpc_vrfname) != 0) {
+ } 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 = bpc->bpc_local.sa_sin;
sin.sin_family = AF_INET;
#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
sin.sin_len = sizeof(sin);
#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
- if (bpc->bpc_mhop)
- sin.sin_addr = bpc->bpc_local.sa_sin.sin_addr;
- else
+ memcpy(&sin.sin_addr, &bs->key.local, sizeof(sin.sin_addr));
+ if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH) == 0)
sin.sin_addr.s_addr = INADDR_ANY;
pcount = 0;
* IPv6 sockets
*/
-int bp_peer_socketv6(struct bfd_peer_cfg *bpc)
+int bp_peer_socketv6(const struct bfd_session *bs)
{
- struct interface *ifp;
int sd, pcount;
struct sockaddr_in6 sin6;
static int srcPort = BFD_SRCPORTINIT;
#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
sin6.sin6_len = sizeof(sin6);
#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
- sin6 = bpc->bpc_local.sa_sin6;
- if (IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr)) {
- ifp = if_lookup_by_name(bpc->bpc_localif, VRF_DEFAULT);
- sin6.sin6_scope_id =
- (ifp != NULL) ? ifp->ifindex : IFINDEX_INTERNAL;
- }
+ memcpy(&sin6.sin6_addr, &bs->key.local, sizeof(sin6.sin6_addr));
+ if (IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr))
+ sin6.sin6_scope_id = bs->ifp->ifindex;
- if (bpc->bpc_has_localif) {
- if (bp_bind_dev(sd, bpc->bpc_localif) != 0) {
+ if (bs->key.ifname[0]) {
+ if (bp_bind_dev(sd, bs->key.ifname) != 0) {
close(sd);
return -1;
}
- } else if (bpc->bpc_mhop && bpc->bpc_has_vrfname) {
- if (bp_bind_dev(sd, bpc->bpc_vrfname) != 0) {
+ } 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;
}