BFD: Fixes crash after socket error
Thanks to Thomas King for the bugreport.
This commit is contained in:
parent
a8ad8fd649
commit
ffa398b8d8
2 changed files with 22 additions and 14 deletions
|
@ -43,7 +43,7 @@
|
||||||
* the needs of BFD sessions. When a new session is created, it requests a
|
* the needs of BFD sessions. When a new session is created, it requests a
|
||||||
* proper BFD interface by function bfd_get_iface(), which either finds an
|
* proper BFD interface by function bfd_get_iface(), which either finds an
|
||||||
* existing one in &iface_list (from &bfd_proto) or allocates a new one. When a
|
* existing one in &iface_list (from &bfd_proto) or allocates a new one. When a
|
||||||
* session is removed, an associated iface is dicharged by bfd_free_iface().
|
* session is removed, an associated iface is discharged by bfd_free_iface().
|
||||||
*
|
*
|
||||||
* BFD requests are the external API for the other protocols. When a protocol
|
* BFD requests are the external API for the other protocols. When a protocol
|
||||||
* wants a BFD session, it calls bfd_request_session(), which creates a
|
* wants a BFD session, it calls bfd_request_session(), which creates a
|
||||||
|
@ -62,7 +62,7 @@
|
||||||
* configuration (like static routes in the static protocol). BFD neighbors are
|
* configuration (like static routes in the static protocol). BFD neighbors are
|
||||||
* handled by BFD protocol like it is a BFD client -- when a BFD neighbor is
|
* handled by BFD protocol like it is a BFD client -- when a BFD neighbor is
|
||||||
* ready, the protocol just creates a BFD request like any other protocol.
|
* ready, the protocol just creates a BFD request like any other protocol.
|
||||||
*
|
*
|
||||||
* The protocol uses a new generic event loop (structure &birdloop) from |io.c|,
|
* The protocol uses a new generic event loop (structure &birdloop) from |io.c|,
|
||||||
* which supports sockets, timers and events like the main loop. Timers
|
* which supports sockets, timers and events like the main loop. Timers
|
||||||
* (structure &timer2) are new microsecond based timers, while sockets and
|
* (structure &timer2) are new microsecond based timers, while sockets and
|
||||||
|
@ -129,11 +129,11 @@ static inline void bfd_notify_kick(struct bfd_proto *p);
|
||||||
* BFD sessions
|
* BFD sessions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bfd_session_update_state(struct bfd_session *s, uint state, uint diag)
|
bfd_session_update_state(struct bfd_session *s, uint state, uint diag)
|
||||||
{
|
{
|
||||||
struct bfd_proto *p = s->ifa->bfd;
|
struct bfd_proto *p = s->ifa->bfd;
|
||||||
uint old_state = s->loc_state;
|
uint old_state = s->loc_state;
|
||||||
int notify;
|
int notify;
|
||||||
|
|
||||||
if (state == old_state)
|
if (state == old_state)
|
||||||
|
@ -201,8 +201,8 @@ bfd_session_control_tx_timer(struct bfd_session *s, int reset)
|
||||||
if (s->passive && (s->rem_id == 0))
|
if (s->passive && (s->rem_id == 0))
|
||||||
goto stop;
|
goto stop;
|
||||||
|
|
||||||
if (s->rem_demand_mode &&
|
if (s->rem_demand_mode &&
|
||||||
!s->poll_active &&
|
!s->poll_active &&
|
||||||
(s->loc_state == BFD_STATE_UP) &&
|
(s->loc_state == BFD_STATE_UP) &&
|
||||||
(s->rem_state == BFD_STATE_UP))
|
(s->rem_state == BFD_STATE_UP))
|
||||||
goto stop;
|
goto stop;
|
||||||
|
@ -303,7 +303,7 @@ bfd_session_process_ctl(struct bfd_session *s, u8 flags, u32 old_tx_int, u32 old
|
||||||
bfd_send_ctl(s->ifa->bfd, s, 1);
|
bfd_send_ctl(s->ifa->bfd, s, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bfd_session_timeout(struct bfd_session *s)
|
bfd_session_timeout(struct bfd_session *s)
|
||||||
{
|
{
|
||||||
struct bfd_proto *p = s->ifa->bfd;
|
struct bfd_proto *p = s->ifa->bfd;
|
||||||
|
@ -353,7 +353,7 @@ bfd_session_set_min_rx(struct bfd_session *s, u32 val)
|
||||||
if (val == s->req_min_rx_new)
|
if (val == s->req_min_rx_new)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
s->req_min_rx_new = val;
|
s->req_min_rx_new = val;
|
||||||
|
|
||||||
/* Postpone timer update if req_min_rx_int decreases and the session is up */
|
/* Postpone timer update if req_min_rx_int decreases and the session is up */
|
||||||
if ((s->loc_state != BFD_STATE_UP) || (val > s->req_min_rx_int))
|
if ((s->loc_state != BFD_STATE_UP) || (val > s->req_min_rx_int))
|
||||||
|
@ -575,9 +575,13 @@ bfd_free_iface(struct bfd_iface *ifa)
|
||||||
if (!ifa || --ifa->uc)
|
if (!ifa || --ifa->uc)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (ifa->sk)
|
||||||
|
{
|
||||||
|
sk_stop(ifa->sk);
|
||||||
|
rfree(ifa->sk);
|
||||||
|
}
|
||||||
|
|
||||||
rem_node(&ifa->n);
|
rem_node(&ifa->n);
|
||||||
sk_stop(ifa->sk);
|
|
||||||
rfree(ifa->sk);
|
|
||||||
mb_free(ifa);
|
mb_free(ifa);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -873,7 +877,7 @@ bfd_notify_hook(sock *sk, int len)
|
||||||
diag = s->loc_diag;
|
diag = s->loc_diag;
|
||||||
bfd_unlock_sessions(p);
|
bfd_unlock_sessions(p);
|
||||||
|
|
||||||
/* FIXME: convert to btime and move to bfd_session_update_state() */
|
/* FIXME: convert to btime and move to bfd_session_update_state() */
|
||||||
s->last_state_change = now;
|
s->last_state_change = now;
|
||||||
|
|
||||||
s->notify_running = 1;
|
s->notify_running = 1;
|
||||||
|
@ -1092,7 +1096,7 @@ bfd_show_sessions(struct proto *P)
|
||||||
/* FIXME: this is thread-unsafe, but perhaps harmless */
|
/* FIXME: this is thread-unsafe, but perhaps harmless */
|
||||||
state = s->loc_state;
|
state = s->loc_state;
|
||||||
diag = s->loc_diag;
|
diag = s->loc_diag;
|
||||||
ifname = (s->ifa && s->ifa->sk->iface) ? s->ifa->sk->iface->name : "---";
|
ifname = (s->ifa && s->ifa->iface) ? s->ifa->iface->name : "---";
|
||||||
tx_int = s->last_tx ? (MAX(s->des_min_tx_int, s->rem_min_rx_int) TO_MS) : 0;
|
tx_int = s->last_tx ? (MAX(s->des_min_tx_int, s->rem_min_rx_int) TO_MS) : 0;
|
||||||
timeout = (MAX(s->req_min_rx_int, s->rem_min_tx_int) TO_MS) * s->rem_detect_mult;
|
timeout = (MAX(s->req_min_rx_int, s->rem_min_tx_int) TO_MS) * s->rem_detect_mult;
|
||||||
|
|
||||||
|
|
|
@ -63,9 +63,13 @@ void
|
||||||
bfd_send_ctl(struct bfd_proto *p, struct bfd_session *s, int final)
|
bfd_send_ctl(struct bfd_proto *p, struct bfd_session *s, int final)
|
||||||
{
|
{
|
||||||
sock *sk = s->ifa->sk;
|
sock *sk = s->ifa->sk;
|
||||||
struct bfd_ctl_packet *pkt = (struct bfd_ctl_packet *) sk->tbuf;
|
struct bfd_ctl_packet *pkt;
|
||||||
char fb[8];
|
char fb[8];
|
||||||
|
|
||||||
|
if (!sk)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pkt = (struct bfd_ctl_packet *) sk->tbuf;
|
||||||
pkt->vdiag = bfd_pack_vdiag(1, s->loc_diag);
|
pkt->vdiag = bfd_pack_vdiag(1, s->loc_diag);
|
||||||
pkt->flags = bfd_pack_flags(s->loc_state, 0);
|
pkt->flags = bfd_pack_flags(s->loc_state, 0);
|
||||||
pkt->detect_mult = s->detect_mult;
|
pkt->detect_mult = s->detect_mult;
|
||||||
|
@ -139,7 +143,7 @@ bfd_rx_hook(sock *sk, int len)
|
||||||
u8 ps = bfd_pkt_get_state(pkt);
|
u8 ps = bfd_pkt_get_state(pkt);
|
||||||
if (ps > BFD_STATE_DOWN)
|
if (ps > BFD_STATE_DOWN)
|
||||||
DROP("invalid init state", ps);
|
DROP("invalid init state", ps);
|
||||||
|
|
||||||
s = bfd_find_session_by_addr(p, sk->faddr);
|
s = bfd_find_session_by_addr(p, sk->faddr);
|
||||||
|
|
||||||
/* FIXME: better session matching and message */
|
/* FIXME: better session matching and message */
|
||||||
|
|
Loading…
Reference in a new issue