summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2024-01-15 11:55:27 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2024-01-15 11:55:27 +0000
commitfdfe2c2dccaa9b537a444fc3710d15aa96a0abdb (patch)
tree2b995c85b889a87683deb77ef56d8a603b748e28
parentb59c26f781778c82036ad1364f0ebac396df399b (diff)
A cache can send a 'NO_DATA_AVAILABLE' error during version negotiation
so handle this case as well. This error triggers an RTR_EVNT_NO_DATA event that moves the session to RTR_STATE_ESTABLISHED (and out of negotiation). When there is no data available the session_id remains unset until data becomes available. So handle this case not only in rtr_parse_cache_response() but also in rtr_parse_notify(). RTR_EVNT_NO_DATA arms the RTR_EVNT_TIMER_RETRY timer. On expiry send a reset or serial query depending on the cache session state. OK tb@
-rw-r--r--usr.sbin/bgpd/rtr_proto.c25
1 files changed, 19 insertions, 6 deletions
diff --git a/usr.sbin/bgpd/rtr_proto.c b/usr.sbin/bgpd/rtr_proto.c
index 46a04340845..958d4385e73 100644
--- a/usr.sbin/bgpd/rtr_proto.c
+++ b/usr.sbin/bgpd/rtr_proto.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtr_proto.c,v 1.31 2024/01/11 15:38:05 claudio Exp $ */
+/* $OpenBSD: rtr_proto.c,v 1.32 2024/01/15 11:55:26 claudio Exp $ */
/*
* Copyright (c) 2020 Claudio Jeker <claudio@openbsd.org>
@@ -419,6 +419,7 @@ rtr_parse_header(struct rtr_session *rs, struct ibuf *hdr,
{
struct rtr_header rh;
size_t len;
+ uint16_t errcode;
if (ibuf_get(hdr, &rh, sizeof(rh)) == -1)
fatal("%s: ibuf_get", __func__);
@@ -443,7 +444,14 @@ rtr_parse_header(struct rtr_session *rs, struct ibuf *hdr,
rtr_fsm(rs, RTR_EVNT_NEGOTIATION_DONE);
break;
case ERROR_REPORT:
- /* version handled in rtr_parse_error() */
+ errcode = ntohs(rh.session_id);
+ if (errcode == UNSUPP_PROTOCOL_VERS ||
+ errcode == NO_DATA_AVAILABLE) {
+ if (rh.version < rs->version) {
+ rs->prev_version = rs->version;
+ rs->version = rh.version;
+ }
+ }
break;
case SERIAL_NOTIFY:
/* ignore SERIAL_NOTIFY */
@@ -537,6 +545,10 @@ rtr_parse_notify(struct rtr_session *rs, struct ibuf *pdu)
if (ibuf_get(pdu, &notify, sizeof(notify)) == -1)
goto badlen;
+ /* set session_id if not yet happened */
+ if (rs->session_id == -1)
+ rs->session_id = ntohs(notify.hdr.session_id);
+
if (rtr_check_session_id(rs, rs->session_id, &notify.hdr, pdu) == -1)
return -1;
@@ -960,10 +972,6 @@ rtr_parse_error(struct rtr_session *rs, struct ibuf *pdu)
rtr_fsm(rs, RTR_EVNT_NO_DATA);
rv = 0;
} else if (errcode == UNSUPP_PROTOCOL_VERS) {
- if (rh.version < rs->version) {
- rs->prev_version = rs->version;
- rs->version = rh.version;
- }
rtr_fsm(rs, RTR_EVNT_UNSUPP_PROTO_VERSION);
rv = 0;
} else
@@ -1126,6 +1134,11 @@ rtr_fsm(struct rtr_session *rs, enum rtr_event event)
timer_set(&rs->timers, Timer_Rtr_Retry, rs->retry);
rtr_imsg_compose(IMSG_SOCKET_CONN, rs->id, 0, NULL, 0);
break;
+ case RTR_STATE_ESTABLISHED:
+ if (rs->session_id == -1)
+ rtr_send_reset_query(rs);
+ else
+ rtr_send_serial_query(rs);
default:
break;
}