summaryrefslogtreecommitdiff
path: root/bgpd/bgp_packet.c
diff options
context:
space:
mode:
Diffstat (limited to 'bgpd/bgp_packet.c')
-rw-r--r--bgpd/bgp_packet.c88
1 files changed, 76 insertions, 12 deletions
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index 17ac1f73..1fa2fdfd 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -804,7 +804,8 @@ bgp_open_send (struct peer *peer)
/* Set open packet values. */
stream_putc (s, BGP_VERSION_4); /* BGP version */
- stream_putw (s, local_as); /* My Autonomous System*/
+ stream_putw (s, (local_as <= BGP_AS_MAX) ? (u_int16_t) local_as
+ : BGP_AS_TRANS);
stream_putw (s, send_holdtime); /* Hold Time */
stream_put_in_addr (s, &peer->local_id); /* BGP Identifier */
@@ -1168,6 +1169,7 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
u_int16_t holdtime;
u_int16_t send_holdtime;
as_t remote_as;
+ as_t as4 = 0;
struct peer *realpeer;
struct in_addr remote_id;
int capability;
@@ -1186,10 +1188,75 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
/* Receive OPEN message log */
if (BGP_DEBUG (normal, NORMAL))
- zlog_debug ("%s rcv OPEN, version %d, remote-as %d, holdtime %d, id %s",
- peer->host, version, remote_as, holdtime,
- inet_ntoa (remote_id));
-
+ zlog_debug ("%s rcv OPEN, version %d, remote-as (in open) %d,"
+ " holdtime %d, id %s",
+ peer->host, version, remote_as, holdtime,
+ inet_ntoa (remote_id));
+
+ /* BEGIN to read the capability here, but dont do it yet */
+ capability = 0;
+ optlen = stream_getc (peer->ibuf);
+
+ if (optlen != 0)
+ {
+ /* We need the as4 capability value *right now* because
+ * if it is there, we have not got the remote_as yet, and without
+ * that we do not know which peer is connecting to us now.
+ */
+ as4 = peek_for_as4_capability (peer, optlen);
+ }
+
+ /* Just in case we have a silly peer who sends AS4 capability set to 0 */
+ if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV) && !as4)
+ {
+ zlog_err ("%s bad OPEN, got AS4 capability, but AS4 set to 0",
+ peer->host);
+ bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
+ BGP_NOTIFY_OPEN_BAD_PEER_AS);
+ return -1;
+ }
+
+ if (remote_as == BGP_AS_TRANS)
+ {
+ /* Take the AS4 from the capability. We must have received the
+ * capability now! Otherwise we have a asn16 peer who uses
+ * BGP_AS_TRANS, for some unknown reason.
+ */
+ if (as4 == BGP_AS_TRANS)
+ {
+ zlog_err ("%s [AS4] NEW speaker using AS_TRANS for AS4, not allowed",
+ peer->host);
+ bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
+ BGP_NOTIFY_OPEN_BAD_PEER_AS);
+ return -1;
+ }
+
+ if (!as4 && BGP_DEBUG (as4, AS4))
+ zlog_debug ("%s [AS4] OPEN remote_as is AS_TRANS, but no AS4."
+ " Odd, but proceeding.", peer->host);
+ else if (as4 < BGP_AS_MAX && BGP_DEBUG (as4, AS4))
+ zlog_debug ("%s [AS4] OPEN remote_as is AS_TRANS, but AS4 fits "
+ "in 2-bytes, very odd peer.", peer->host, as4);
+ if (as4)
+ remote_as = as4;
+ }
+ else
+ {
+ /* We may have a partner with AS4 who has an asno < BGP_AS_MAX */
+ /* If we have got the capability, peer->as4cap must match remote_as */
+ if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)
+ && as4 != remote_as)
+ {
+ /* raise error, log this, close session */
+ zlog_err ("%s bad OPEN, got AS4 capability, but remote_as %u"
+ " mismatch with 16bit 'myasn' %u in open",
+ peer->host, as4, remote_as);
+ bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
+ BGP_NOTIFY_OPEN_BAD_PEER_AS);
+ return -1;
+ }
+ }
+
/* Lookup peer from Open packet. */
if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
{
@@ -1364,8 +1431,6 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
peer->v_keepalive = peer->v_holdtime / 3;
/* Open option part parse. */
- capability = 0;
- optlen = stream_getc (peer->ibuf);
if (optlen != 0)
{
ret = bgp_open_option_parse (peer, optlen, &capability);
@@ -2049,8 +2114,8 @@ bgp_capability_msg_parse (struct peer *peer, u_char *pnt, bgp_size_t length)
if (!bgp_afi_safi_valid_indices (afi, &safi))
{
if (BGP_DEBUG (normal, NORMAL))
- zlog_debug ("%s Dynamic Capability MP_EXT afi/safi invalid",
- peer->host, afi, safi);
+ zlog_debug ("%s Dynamic Capability MP_EXT afi/safi invalid "
+ "(%u/%u)", peer->host, afi, safi);
continue;
}
@@ -2097,7 +2162,6 @@ int
bgp_capability_receive (struct peer *peer, bgp_size_t size)
{
u_char *pnt;
- int ret;
/* Fetch pointer. */
pnt = stream_pnt (peer->ibuf);
@@ -2113,7 +2177,7 @@ bgp_capability_receive (struct peer *peer, bgp_size_t size)
bgp_notify_send (peer,
BGP_NOTIFY_HEADER_ERR,
BGP_NOTIFY_HEADER_BAD_MESTYPE);
- return;
+ return -1;
}
/* Status must be Established. */
@@ -2122,7 +2186,7 @@ bgp_capability_receive (struct peer *peer, bgp_size_t size)
plog_err (peer->log,
"%s [Error] Dynamic capability packet received under status %s", peer->host, LOOKUP (bgp_status_msg, peer->status));
bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
- return;
+ return -1;
}
/* Parse packet. */