summaryrefslogtreecommitdiffstats
path: root/proto/bgp/packets.c
diff options
context:
space:
mode:
Diffstat (limited to 'proto/bgp/packets.c')
-rw-r--r--proto/bgp/packets.c31
1 files changed, 22 insertions, 9 deletions
diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c
index dc3748f..1841205 100644
--- a/proto/bgp/packets.c
+++ b/proto/bgp/packets.c
@@ -104,6 +104,7 @@ bgp_create_open(struct bgp_conn *conn, byte *buf)
#ifdef IPV6
cap = bgp_put_cap_ipv6(conn, cap);
#endif
+
if (conn->want_as4_support)
cap = bgp_put_cap_as4(conn, cap);
@@ -504,6 +505,7 @@ bgp_parse_capabilities(struct bgp_conn *conn, byte *opt, int len)
static int
bgp_parse_options(struct bgp_conn *conn, byte *opt, int len)
{
+ struct bgp_proto *p = conn->bgp;
int ol;
while (len > 0)
@@ -524,7 +526,10 @@ bgp_parse_options(struct bgp_conn *conn, byte *opt, int len)
switch (opt[0])
{
case 2:
- bgp_parse_capabilities(conn, opt + 2, ol);
+ if (conn->start_state == BSS_CONNECT_NOCAP)
+ BGP_TRACE(D_PACKETS, "Ignoring received capabilities");
+ else
+ bgp_parse_capabilities(conn, opt + 2, ol);
break;
default:
@@ -550,6 +555,7 @@ bgp_rx_open(struct bgp_conn *conn, byte *pkt, int len)
struct bgp_proto *p = conn->bgp;
struct bgp_config *cf = p->cf;
unsigned hold;
+ u16 base_as;
u32 id;
/* Check state */
@@ -561,7 +567,7 @@ bgp_rx_open(struct bgp_conn *conn, byte *pkt, int len)
{ bgp_error(conn, 1, 2, pkt+16, 2); return; }
if (pkt[19] != BGP_VERSION)
{ bgp_error(conn, 2, 1, pkt+19, 1); return; } /* RFC 1771 says 16 bits, draft-09 tells to use 8 */
- conn->advertised_as = get_u16(pkt+20);
+ conn->advertised_as = base_as = get_u16(pkt+20);
hold = get_u16(pkt+22);
id = get_u32(pkt+24);
BGP_TRACE(D_PACKETS, "Got OPEN(as=%d,hold=%d,id=%08x)", conn->advertised_as, hold, id);
@@ -575,10 +581,11 @@ bgp_rx_open(struct bgp_conn *conn, byte *pkt, int len)
if (!id || id == 0xffffffff || id == p->local_id)
{ bgp_error(conn, 2, 3, pkt+24, -4); return; }
+ if ((conn->advertised_as != base_as) && (base_as != AS_TRANS))
+ log(L_WARN "%s: Peer advertised inconsistent AS numbers", p->p.name);
+
if (conn->advertised_as != p->remote_as)
- {
- bgp_error(conn, 2, 2, (byte *) &(conn->advertised_as), -4); return;
- }
+ { bgp_error(conn, 2, 2, (byte *) &(conn->advertised_as), -4); return; }
/* Check the other connection */
other = (conn == &p->outgoing_conn) ? &p->incoming_conn : &p->outgoing_conn;
@@ -963,14 +970,20 @@ bgp_rx_notification(struct bgp_conn *conn, byte *pkt, int len)
bgp_store_error(conn->bgp, conn, BE_BGP_RX, (code << 16) | subcode);
#ifndef IPV6
- if ((code == 2) && ((subcode == 4) || (subcode == 7)))
- {
+ 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
*/
- log(L_WARN "%s: Capability related error received, capabilities disabled", p->p.name);
+ && (p->cf->capabilities == 2)
+ /* Capabilities are not explicitly enabled or disabled, therefore heuristic is used */
+ && (conn->start_state == BSS_CONNECT)
+ /* Failed connection attempt have used capabilities */
+ && (p->cf->remote_as <= 0xFFFF))
+ /* Not possible with disabled capabilities */
+ {
+ /* We try connect without capabilities */
+ log(L_WARN "%s: Capability related error received, retry with capabilities disabled", p->p.name);
conn->bgp->start_state = BSS_CONNECT_NOCAP;
delay = 0;
}