summaryrefslogtreecommitdiffstats
path: root/bgpd/bgp_packet.c
diff options
context:
space:
mode:
Diffstat (limited to 'bgpd/bgp_packet.c')
-rw-r--r--bgpd/bgp_packet.c87
1 files changed, 77 insertions, 10 deletions
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index 9859e50b..e422af7a 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -804,7 +804,15 @@ 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*/
+ if ( local_as <= BGP_AS_MAX )
+ /* fits in 16 bit, so send real as number in 16 bit */
+ stream_putw (s, (u_int16_t) local_as); /* My Autonomous System*/
+ else
+ /* does not fit in 16 bit, so as per */
+ /* draft_ietf_idr_as4bytes-13: */
+ /* AS_TRANS is put in the My Autonomous System field */
+ /* of the open message of a NEW BGP speaker */
+ stream_putw (s, BGP_AS_TRANS); /* My Autonomous System*/
stream_putw (s, send_holdtime); /* Hold Time */
stream_put_in_addr (s, &peer->local_id); /* BGP Identifier */
@@ -815,8 +823,8 @@ bgp_open_send (struct peer *peer)
length = bgp_packet_set_size (s);
if (BGP_DEBUG (normal, NORMAL))
- zlog_debug ("%s sending OPEN, version %d, my as %d, holdtime %d, id %s",
- peer->host, BGP_VERSION_4, local_as,
+ zlog_debug ("%s sending OPEN, version %d, my as %s, holdtime %d, id %s",
+ peer->host, BGP_VERSION_4, as2str(local_as),
send_holdtime, inet_ntoa (peer->local_id));
if (BGP_DEBUG (normal, NORMAL))
@@ -1184,12 +1192,73 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
memcpy (notify_data_remote_id, stream_pnt (peer->ibuf), 4);
remote_id.s_addr = stream_get_ipv4 (peer->ibuf);
+ /* BEGIN to read the capability here, but dont do it yet */
+ capability = 0;
+ optlen = stream_getc (peer->ibuf);
+ if (optlen != 0)
+ {
+ /* We got capabilities. Now, for simplicity, we always read
+ * them when we were through the basic things, i.e. at the end
+ * of this function.
+ * But 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.
+ *
+ * So, keep everything safe, and peek into the capabilites,
+ * and look just for as4!
+ */
+ peek_for_as4_capability( peer, optlen );
+ }
+
/* Receive OPEN message log */
if (BGP_DEBUG (normal, NORMAL))
- zlog_debug ("%s rcv OPEN, version %d, remote-as %d, holdtime %d, id %s",
+ 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));
+ if ( remote_as == BGP_AS_TRANS )
+ {
+ if ( peer->as4cap > BGP_AS_MAX )
+ {
+ /* Take the AS4 from the capability.
+ * We must have received the capability now!
+ * Otherwise we have a asn16 peer who uses BGP_AS_TRANS,
+ * which we will not tolerate
+ */
+
+ if ( !CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV) )
+ {
+ /* raise error, log this, close session */
+ zlog_err ("%s bad OPEN, got AS_TRANS but no AS4 capability address peer->cap is %08x, value %d",
+ peer->host, (u_int32_t) &peer->cap, peer->cap);
+ /* which error to notify? well, use something generic,
+ * our log has the right reason
+ */
+ bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+ BGP_NOTIFY_CEASE_CONNECT_REJECT);
+ return -1;
+ }
+ else
+ remote_as = peer->as4cap;
+ }
+ } 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) &&
+ peer->as4cap != 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, peer->as4cap, remote_as);
+ bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+ BGP_NOTIFY_CEASE_CONNECT_REJECT);
+ /* which error to notify? well, use something generic,
+ * our log has the right reason
+ */
+ return -1;
+ }
+ }
+
/* Lookup peer from Open packet. */
if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
{
@@ -1214,8 +1283,8 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
else
{
if (BGP_DEBUG (normal, NORMAL))
- zlog_debug ("%s bad OPEN, remote AS is %d, expected %d",
- peer->host, remote_as, peer->as);
+ zlog_debug ("%s bad OPEN, remote AS is %s, expected %s",
+ peer->host, as2str(remote_as), as2str(peer->as));
bgp_notify_send_with_data (peer, BGP_NOTIFY_OPEN_ERR,
BGP_NOTIFY_OPEN_BAD_PEER_AS,
notify_data_remote_as, 2);
@@ -1322,8 +1391,8 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
if (remote_as != peer->as)
{
if (BGP_DEBUG (normal, NORMAL))
- zlog_debug ("%s bad OPEN, remote AS is %d, expected %d",
- peer->host, remote_as, peer->as);
+ zlog_debug ("%s bad OPEN, remote AS is %s, expected %s",
+ peer->host, as2str(remote_as), as2str(peer->as));
bgp_notify_send_with_data (peer,
BGP_NOTIFY_OPEN_ERR,
BGP_NOTIFY_OPEN_BAD_PEER_AS,
@@ -1364,8 +1433,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);