summaryrefslogtreecommitdiffstats
path: root/bgpd/bgp_open.c
diff options
context:
space:
mode:
Diffstat (limited to 'bgpd/bgp_open.c')
-rw-r--r--bgpd/bgp_open.c134
1 files changed, 134 insertions, 0 deletions
diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c
index e44bd2a0..841dcef8 100644
--- a/bgpd/bgp_open.c
+++ b/bgpd/bgp_open.c
@@ -33,6 +33,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "bgpd/bgp_fsm.h"
#include "bgpd/bgp_packet.h"
#include "bgpd/bgp_open.h"
+#include "bgpd/bgp_aspath.h"
#include "bgpd/bgp_vty.h"
/* BGP-4 Multiprotocol Extentions lead us to the complex world. We can
@@ -483,6 +484,40 @@ bgp_capability_parse (struct peer *peer, u_char *pnt, u_char length,
SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV);
}
+ else if (cap.code == CAPABILITY_CODE_AS4)
+ {
+ /* Check length */
+ if (cap.length != CAPABILITY_CODE_AS4_LEN)
+ {
+ zlog_info ("%s AS4 Capability length error %d",
+ peer->host, cap.length);
+ bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
+ return -1;
+ }
+ if (BGP_DEBUG (normal, NORMAL))
+ zlog_debug ("%s OPEN has AS4 capability", peer->host);
+
+ {
+ /*
+ * We did not make a "stream_getl" but read into
+ * the struct.
+ * Do the byte swivveling now
+ */
+ u_char *gotthis = (char *) &cap.mpc;
+ peer->as4cap = ((u_char) *gotthis++) << 24;
+ peer->as4cap |= ((u_char) *gotthis++) << 16;
+ peer->as4cap |= ((u_char) *gotthis++) << 8;
+ peer->as4cap |= ((u_char) *gotthis);
+ }
+
+ if (BGP_DEBUG (as4, AS4))
+ zlog_debug ("[AS4] %s about to set cap PEER_CAP_AS4_RCV at address %08x, value now %d, as4cap is %s", peer->host, &peer->cap, peer->cap,as2str(peer->as4cap));
+
+ SET_FLAG (peer->cap, PEER_CAP_AS4_RCV);
+
+ if (BGP_DEBUG (as4, AS4))
+ zlog_debug ("[AS4] %s set cap PEER_CAP_AS4_RCV at address %08x, value now %d", peer->host, &peer->cap, peer->cap);
+ }
else if (cap.code > 128)
{
@@ -525,6 +560,92 @@ strict_capability_same (struct peer *peer)
return 1;
}
+/* peek into option, set as4 value if it is there */
+void peek_for_as4_capability( struct peer *peer, u_char length )
+{
+ u_char *pnt;
+ u_char *end;
+ u_char opt_type;
+ u_char opt_length;
+ struct capability cap;
+
+ pnt = stream_pnt (peer->ibuf);
+ end = pnt + length;
+
+ if (BGP_DEBUG (as4, AS4))
+ zlog_debug ("[AS4] %s rcv OPEN w/ OPTION parameter len: %u, peeking for as4",
+ peer->host, length);
+
+ /* the error cases we DONT handle, we ONLY try to read as4 out of
+ * correctly formatted options
+ */
+ while (pnt < end)
+ {
+
+ /* Check the length. */
+ if (pnt + 2 > end)
+ return;
+
+ /* Fetch option type and length. */
+ opt_type = *pnt++;
+ opt_length = *pnt++;
+
+ /* Option length check. */
+ if (pnt + opt_length > end)
+ return;
+
+ if ( opt_type == BGP_OPEN_OPT_CAP )
+ {
+ u_char *mypnt = pnt;
+ u_char mylength = opt_length;
+ u_char *myend ;
+
+ myend = mypnt + mylength;
+ while (mypnt < myend)
+ {
+ afi_t afi;
+ safi_t safi;
+
+ /* Fetch structure to the byte stream. */
+ memcpy (&cap, mypnt, sizeof (struct capability));
+
+ afi = ntohs(cap.mpc.afi);
+ safi = cap.mpc.safi;
+
+ if (mypnt + 2 > myend)
+ return;
+ if (mypnt + (cap.length + 2) > myend)
+ return;
+
+ if (cap.code == CAPABILITY_CODE_AS4)
+ {
+ if (cap.length != CAPABILITY_CODE_AS4_LEN)
+ return;
+ if (BGP_DEBUG (as4, AS4))
+ zlog_debug ("[AS4] %s OPEN peeking found AS4 capability", peer->host);
+
+ {
+ /*
+ * We did not make a "stream_getl"
+ * Do the byte swivveling now
+ */
+ u_char *gotthis = (char *) &cap.mpc;
+ peer->as4cap = ((u_char) *gotthis++) << 24;
+ peer->as4cap |= ((u_char) *gotthis++) << 16;
+ peer->as4cap |= ((u_char) *gotthis++) << 8;
+ peer->as4cap |= ((u_char) *gotthis);
+
+ }
+ SET_FLAG (peer->cap, PEER_CAP_AS4_RCV);
+
+ }
+ mypnt += cap.length + 2;
+ }
+ }
+ pnt += opt_length;
+ }
+}
+
/* Parse open option */
int
bgp_open_option_parse (struct peer *peer, u_char length, int *capability)
@@ -733,6 +854,7 @@ bgp_open_capability (struct stream *s, struct peer *peer)
unsigned long cp;
afi_t afi;
safi_t safi;
+ as_t local_as;
/* Remember current pointer for Opt Parm Len. */
cp = stream_get_endp (s);
@@ -819,6 +941,18 @@ bgp_open_capability (struct stream *s, struct peer *peer)
stream_putc (s, CAPABILITY_CODE_REFRESH);
stream_putc (s, CAPABILITY_CODE_REFRESH_LEN);
+ /* AS4 */
+ SET_FLAG (peer->cap, PEER_CAP_AS4_ADV);
+ stream_putc (s, BGP_OPEN_OPT_CAP);
+ stream_putc (s, CAPABILITY_CODE_AS4_LEN + 2);
+ stream_putc (s, CAPABILITY_CODE_AS4);
+ stream_putc (s, CAPABILITY_CODE_AS4_LEN);
+ if ( peer->change_local_as )
+ local_as = peer->change_local_as;
+ else
+ local_as = peer->local_as;
+ stream_putl (s, local_as );
+
/* ORF capability. */
for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)