Commit 165a6227 authored by Ondřej Zajíček's avatar Ondřej Zajíček

Adds support for fallback to capabilityless BGP connect

When capability related error is received, next connect will be
without capabilities. Also cease error subcodes descriptions
(according to [RFC4486]) are added.
parent 59121155
......@@ -368,6 +368,10 @@ bgp_conn_enter_idle_state(struct bgp_conn *conn)
static void
bgp_send_open(struct bgp_conn *conn)
{
conn->start_state = conn->bgp->start_state;
conn->want_as4_support = conn->bgp->cf->enable_as4 && (conn->start_state != BSS_CONNECT_NOCAP);
conn->peer_as4_support = 0; // Default value, possibly changed by receiving capability.
DBG("BGP: Sending open\n");
conn->sk->rx_hook = bgp_rx;
conn->sk->tx_hook = bgp_tx;
......
......@@ -51,9 +51,10 @@ struct bgp_conn {
int packets_to_send; /* Bitmap of packet types to be sent */
int notify_code, notify_subcode, notify_size;
byte *notify_data;
int error_flag; /* Error state, ignore all input */
u32 advertised_as; /* Temporary value for AS number received */
int as4_support; /* Peer supports 4B AS numbers [RFC4893] */
int start_state; /* protocol start_state snapshot when connection established */
int want_as4_support; /* Connection tries to establish AS4 session */
int peer_as4_support; /* Peer supports 4B AS numbers [RFC4893] */
unsigned hold_time, keepalive_time; /* Times calculated from my and neighbor's requirements */
};
......
......@@ -69,13 +69,21 @@ bgp_create_open(struct bgp_conn *conn, byte *buf)
put_u16(buf+1, (p->local_as < 0xFFFF) ? p->local_as : AS_TRANS);
put_u16(buf+3, p->cf->hold_time);
put_u32(buf+5, p->local_id);
if (conn->start_state == BSS_CONNECT_NOCAP)
{
BGP_TRACE(D_PACKETS, "Skipping capabilities");
buf[9] = 0;
return buf + 10;
}
/* Skipped 3 B for length field and Capabilities parameter header */
cap = buf + 12;
#ifdef IPV6
cap = bgp_put_cap_ipv6(conn, cap);
#endif
if (p->cf->enable_as4)
if (conn->want_as4_support)
cap = bgp_put_cap_as4(conn, cap);
cap_len = cap - buf - 12;
......@@ -418,9 +426,8 @@ bgp_parse_capabilities(struct bgp_conn *conn, byte *opt, int len)
case 65:
if (cl != 4)
goto err;
conn->as4_support = 1;
if (p->cf->enable_as4)
conn->peer_as4_support = 1;
if (conn->want_as4_support)
conn->advertised_as = get_u32(opt + 2);
break;
......@@ -501,7 +508,6 @@ bgp_rx_open(struct bgp_conn *conn, byte *pkt, int len)
id = get_u32(pkt+24);
BGP_TRACE(D_PACKETS, "Got OPEN(as=%d,hold=%d,id=%08x)", conn->advertised_as, hold, id);
conn->as4_support = 0; // Default value, possibly changed by capability.
if (bgp_parse_options(conn, pkt+29, pkt[28]))
return;
......@@ -548,8 +554,8 @@ bgp_rx_open(struct bgp_conn *conn, byte *pkt, int len)
conn->hold_time = MIN(hold, p->cf->hold_time);
conn->keepalive_time = p->cf->keepalive_time ? : conn->hold_time / 3;
p->remote_id = id;
p->as4_session = p->cf->enable_as4 && conn->as4_support;
p->as4_session = conn->want_as4_support && conn->peer_as4_support;
DBG("BGP: Hold timer set to %d, keepalive to %d, AS to %d, ID to %x, AS4 session to %d\n", conn->hold_time, conn->keepalive_time, p->remote_as, p->remote_id, p->as4_session);
bgp_schedule_packet(conn, PKT_KEEPALIVE);
......@@ -820,7 +826,15 @@ static struct {
{ 3, 11, "Malformed AS_PATH" },
{ 4, 0, "Hold timer expired" },
{ 5, 0, "Finite state machine error" },
{ 6, 0, "Cease" }
{ 6, 0, "Cease" }, /* Subcodes are according to [RFC4486] */
{ 6, 1, "Maximum number of prefixes reached" },
{ 6, 2, "Administrative shutdown" },
{ 6, 3, "Peer de-configured" },
{ 6, 4, "Administrative reset" },
{ 6, 5, "Connection rejected" },
{ 6, 6, "Other configuration change" },
{ 6, 7, "Connection collision resolution" },
{ 6, 8, "Out of Resources" }
};
/**
......@@ -875,6 +889,7 @@ bgp_log_error(struct bgp_proto *p, char *msg, unsigned code, unsigned subcode, b
static void
bgp_rx_notification(struct bgp_conn *conn, byte *pkt, int len)
{
struct bgp_proto *p = conn->bgp;
if (len < 21)
{
bgp_error(conn, 1, 2, pkt+16, 2);
......@@ -883,9 +898,25 @@ bgp_rx_notification(struct bgp_conn *conn, byte *pkt, int len)
unsigned code = pkt[19];
unsigned subcode = pkt[20];
int delay = 1;
#ifndef IPV6
if ((code == 2) && ((subcode == 4) || (subcode == 7)))
{
/* Error related to capability:
* 4 - Peer does not support capabilities at all.
* 7 - Peer request some capability. Strange unless it is IPv6 only peer.
* We try connect without capabilities
*/
BGP_TRACE(D_EVENTS, "Capability related error received, capabilities disabled");
conn->bgp->start_state = BSS_CONNECT_NOCAP;
delay = 0;
}
#endif
bgp_log_error(conn->bgp, "Received error notification", code, subcode, pkt+21, len-21);
bgp_store_error(conn->bgp, conn, BE_BGP_RX, (code << 16) | subcode);
bgp_update_startup_delay(conn->bgp, conn, code, subcode);
if (delay) bgp_update_startup_delay(conn->bgp, conn, code, subcode);
bgp_conn_enter_close_state(conn);
bgp_schedule_packet(conn, PKT_SCHEDULE_CLOSE);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment