summaryrefslogtreecommitdiff
path: root/proto/bgp/packets.c
diff options
context:
space:
mode:
Diffstat (limited to 'proto/bgp/packets.c')
-rw-r--r--proto/bgp/packets.c24
1 files changed, 17 insertions, 7 deletions
diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c
index 3fae2c24..42064332 100644
--- a/proto/bgp/packets.c
+++ b/proto/bgp/packets.c
@@ -24,6 +24,13 @@
static struct rate_limit rl_rcv_update, rl_snd_update;
+/* Table for state -> RFC 6608 FSM error subcodes */
+static byte fsm_err_subcode[BS_MAX] = {
+ [BS_OPENSENT] = 1,
+ [BS_OPENCONFIRM] = 2,
+ [BS_ESTABLISHED] = 3
+};
+
/*
* MRT Dump format is not semantically specified.
* We will use these values in appropriate fields:
@@ -58,7 +65,7 @@ mrt_put_bgp4_hdr(byte *buf, struct bgp_conn *conn, int as4)
buf+=4;
}
- put_u16(buf+0, p->neigh ? p->neigh->iface->index : 0);
+ put_u16(buf+0, (p->neigh && p->neigh->iface) ? p->neigh->iface->index : 0);
put_u16(buf+2, BGP_AF);
buf+=4;
buf = ipa_put_addr(buf, conn->sk ? conn->sk->daddr : IPA_NONE);
@@ -758,7 +765,7 @@ bgp_rx_open(struct bgp_conn *conn, byte *pkt, int len)
/* Check state */
if (conn->state != BS_OPENSENT)
- { bgp_error(conn, 5, 0, NULL, 0); return; }
+ { bgp_error(conn, 5, fsm_err_subcode[conn->state], NULL, 0); return; }
/* Check message contents */
if (len < 29 || len != 29 + pkt[28])
@@ -917,7 +924,7 @@ bgp_set_next_hop(struct bgp_proto *p, rta *a)
ip_addr *nexthop = (ip_addr *) nh->u.ptr->data;
#ifdef IPV6
- int second = (nh->u.ptr->length == NEXT_HOP_LENGTH);
+ int second = (nh->u.ptr->length == NEXT_HOP_LENGTH) && ipa_nonzero(nexthop[1]);
/* First address should not be link-local, but may be zero in direct mode */
if (ipa_has_link_scope(*nexthop))
@@ -1148,7 +1155,7 @@ bgp_rx_update(struct bgp_conn *conn, byte *pkt, int len)
bgp_conn_enter_established_state(conn);
if (conn->state != BS_ESTABLISHED)
- { bgp_error(conn, 5, 0, NULL, 0); return; }
+ { bgp_error(conn, 5, fsm_err_subcode[conn->state], NULL, 0); return; }
bgp_start_timer(conn->hold_timer, conn->hold_time);
/* Find parts of the packet and check sizes */
@@ -1210,7 +1217,10 @@ static struct {
{ 3, 10, "Invalid network field" },
{ 3, 11, "Malformed AS_PATH" },
{ 4, 0, "Hold timer expired" },
- { 5, 0, "Finite state machine error" },
+ { 5, 0, "Finite state machine error" }, /* Subcodes are according to [RFC6608] */
+ { 5, 1, "Unexpected message in OpenSent state" },
+ { 5, 2, "Unexpected message in OpenConfirm state" },
+ { 5, 3, "Unexpected message in Established state" },
{ 6, 0, "Cease" }, /* Subcodes are according to [RFC4486] */
{ 6, 1, "Maximum number of prefixes reached" },
{ 6, 2, "Administrative shutdown" },
@@ -1341,7 +1351,7 @@ bgp_rx_keepalive(struct bgp_conn *conn)
case BS_ESTABLISHED:
break;
default:
- bgp_error(conn, 5, 0, NULL, 0);
+ bgp_error(conn, 5, fsm_err_subcode[conn->state], NULL, 0);
}
}
@@ -1353,7 +1363,7 @@ bgp_rx_route_refresh(struct bgp_conn *conn, byte *pkt, int len)
BGP_TRACE(D_PACKETS, "Got ROUTE-REFRESH");
if (conn->state != BS_ESTABLISHED)
- { bgp_error(conn, 5, 0, NULL, 0); return; }
+ { bgp_error(conn, 5, fsm_err_subcode[conn->state], NULL, 0); return; }
if (!p->cf->enable_refresh)
{ bgp_error(conn, 1, 3, pkt+18, 1); return; }