summaryrefslogtreecommitdiff
path: root/proto/bfd/packets.c
diff options
context:
space:
mode:
Diffstat (limited to 'proto/bfd/packets.c')
-rw-r--r--proto/bfd/packets.c66
1 files changed, 48 insertions, 18 deletions
diff --git a/proto/bfd/packets.c b/proto/bfd/packets.c
index 893d582d..a22f223b 100644
--- a/proto/bfd/packets.c
+++ b/proto/bfd/packets.c
@@ -290,11 +290,9 @@ bfd_send_ctl(struct bfd_proto *p, struct bfd_session *s, int final)
if (!sk)
return;
- struct bfd_session_state loc = BFD_LOC_STATE(s);
-
pkt = (struct bfd_ctl_packet *) sk->tbuf;
- pkt->vdiag = bfd_pack_vdiag(1, loc.diag);
- pkt->flags = bfd_pack_flags(loc.state, 0);
+ pkt->vdiag = bfd_pack_vdiag(1, s->loc_diag);
+ pkt->flags = bfd_pack_flags(s->loc_state, 0);
pkt->detect_mult = s->detect_mult;
pkt->length = BFD_BASE_LEN;
pkt->snd_id = htonl(s->loc_id);
@@ -315,7 +313,7 @@ bfd_send_ctl(struct bfd_proto *p, struct bfd_session *s, int final)
log(L_WARN "%s: Old packet overwritten in TX buffer", p->p.name);
TRACE(D_PACKETS, "Sending CTL to %I [%s%s]", s->addr,
- bfd_state_names[loc.state], bfd_format_flags(pkt->flags, fb));
+ bfd_state_names[s->loc_state], bfd_format_flags(pkt->flags, fb));
sk_send_to(sk, pkt->length, s->addr, sk->dport);
}
@@ -368,12 +366,18 @@ bfd_rx_hook(sock *sk, uint len)
if (ps > BFD_STATE_DOWN)
DROP("invalid init state", ps);
- uint ifindex = (sk->sport == BFD_CONTROL_PORT) ? sk->lifindex : 0;
+ uint ifindex = (sk->sport == BFD_CONTROL_PORT) ?
+ (sk->iface ? sk->iface->index : sk->lifindex) :
+ 0;
s = bfd_find_session_by_addr(p, sk->faddr, ifindex);
/* FIXME: better session matching and message */
if (!s)
return 1;
+
+ /* For active sessions we require matching remote id */
+ if ((s->loc_state == BFD_STATE_UP) && (ntohl(pkt->snd_id) != s->rem_id))
+ DROP("mismatched remote id", ntohl(pkt->snd_id));
}
/* bfd_check_authentication() has its own error logging */
@@ -384,17 +388,16 @@ bfd_rx_hook(sock *sk, uint len)
u32 old_rx_int = s->rem_min_rx_int;
s->rem_id= ntohl(pkt->snd_id);
- s->rem.state = bfd_pkt_get_state(pkt);
- s->rem.diag = bfd_pkt_get_diag(pkt);
+ s->rem_state = bfd_pkt_get_state(pkt);
+ s->rem_diag = bfd_pkt_get_diag(pkt);
s->rem_demand_mode = pkt->flags & BFD_FLAG_DEMAND;
s->rem_min_tx_int = ntohl(pkt->des_min_tx_int);
s->rem_min_rx_int = ntohl(pkt->req_min_rx_int);
s->rem_detect_mult = pkt->detect_mult;
TRACE(D_PACKETS, "CTL received from %I [%s%s]", sk->faddr,
- bfd_state_names[s->rem.state], bfd_format_flags(pkt->flags, fb));
+ bfd_state_names[s->rem_state], bfd_format_flags(pkt->flags, fb));
- /* This call may drop the session, must be called in tail position */
bfd_session_process_ctl(s, pkt->flags, old_tx_int, old_rx_int);
return 1;
@@ -427,13 +430,42 @@ bfd_open_rx_sk(struct bfd_proto *p, int multihop, int af)
/* TODO: configurable ToS and priority */
sk->tos = IP_PREC_INTERNET_CONTROL;
sk->priority = sk_priority_control;
- sk->flags = SKF_THREAD | SKF_LADDR_RX | (!multihop ? SKF_TTL_RX : 0);
- sk->loop = p->p.loop;
+ sk->flags = SKF_LADDR_RX | (!multihop ? SKF_TTL_RX : 0);
+
+ if (sk_open(sk, p->p.loop) < 0)
+ goto err;
+
+ return sk;
+
+ err:
+ sk_log_error(sk, p->p.name);
+ rfree(sk);
+ return NULL;
+}
+
+sock *
+bfd_open_rx_sk_bound(struct bfd_proto *p, ip_addr local, struct iface *ifa)
+{
+ sock *sk = sk_new(p->tpool);
+ sk->type = SK_UDP;
+ sk->saddr = local;
+ sk->sport = ifa ? BFD_CONTROL_PORT : BFD_MULTI_CTL_PORT;
+ sk->iface = ifa;
+ sk->vrf = p->p.vrf;
+ sk->data = p;
+
+ sk->rbsize = BFD_MAX_LEN;
+ sk->rx_hook = bfd_rx_hook;
+ sk->err_hook = bfd_err_hook;
+
+ /* TODO: configurable ToS and priority */
+ sk->tos = IP_PREC_INTERNET_CONTROL;
+ sk->priority = sk_priority_control;
+ sk->flags = SKF_BIND | (ifa ? SKF_TTL_RX : 0);
- if (sk_open(sk) < 0)
+ if (sk_open(sk, p->p.loop) < 0)
goto err;
- sk_start(sk);
return sk;
err:
@@ -460,13 +492,11 @@ bfd_open_tx_sk(struct bfd_proto *p, ip_addr local, struct iface *ifa)
sk->tos = IP_PREC_INTERNET_CONTROL;
sk->priority = sk_priority_control;
sk->ttl = ifa ? 255 : -1;
- sk->flags = SKF_THREAD | SKF_BIND | SKF_HIGH_PORT;
- sk->loop = p->p.loop;
+ sk->flags = SKF_BIND | SKF_HIGH_PORT;
- if (sk_open(sk) < 0)
+ if (sk_open(sk, p->p.loop) < 0)
goto err;
- sk_start(sk);
return sk;
err: