From bd2d8190dd79645174beeef1a306c8df53db3b60 Mon Sep 17 00:00:00 2001
From: Martin Mares <mj@ucw.cz>
Date: Mon, 17 Apr 2000 13:13:08 +0000
Subject: [PATCH] Honor standard communities (no_export, no_advertise,
 no_export_subconfed) when exporting routes.

---
 proto/bgp/attrs.c | 41 +++++++++++++++++++++++++++++++++++++----
 proto/bgp/bgp.h   |  6 ++++++
 2 files changed, 43 insertions(+), 4 deletions(-)

diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c
index 22c73ca90..03f8ed37a 100644
--- a/proto/bgp/attrs.c
+++ b/proto/bgp/attrs.c
@@ -297,6 +297,42 @@ bgp_new_bucket(struct bgp_proto *p, ea_list *new, unsigned hash)
   return b;
 }
 
+static int
+bgp_export_check(struct bgp_proto *p, ea_list *new)
+{
+  eattr *a;
+  struct adata *d;
+
+  /* Check if next hop is valid */
+  a = ea_find(new, EA_CODE(EAP_BGP, BA_NEXT_HOP));
+  if (!a || ipa_equal(p->next_hop, *(ip_addr *)a->u.ptr))
+    {
+      DBG("\tInvalid NEXT_HOP\n");
+      return 0;
+    }
+
+  /* Check if we aren't forbidden to export the route by communities */
+  a = ea_find(new, EA_CODE(EAP_BGP, BA_COMMUNITY));
+  if (a)
+    {
+      d = a->u.ptr;
+      if (int_set_contains(d, BGP_COMM_NO_ADVERTISE))
+	{
+	  DBG("\tNO_ADVERTISE\n");
+	  return 0;
+	}
+      if (!p->is_internal &&
+	  (int_set_contains(d, BGP_COMM_NO_EXPORT) ||
+	   int_set_contains(d, BGP_COMM_NO_EXPORT_SUBCONFED)))
+	{
+	  DBG("\tNO_EXPORT\n");
+	  return 0;
+	}
+    }
+
+  return 1;
+}
+
 static struct bgp_bucket *
 bgp_get_bucket(struct bgp_proto *p, ea_list *old, ea_list *tmp, int originate)
 {
@@ -375,10 +411,7 @@ bgp_get_bucket(struct bgp_proto *p, ea_list *old, ea_list *tmp, int originate)
 	return NULL;
       }
 
-  /* Check if next hop is valid */
-  a = ea_find(new, EA_CODE(EAP_BGP, BA_NEXT_HOP));
-  ASSERT(a);
-  if (ipa_equal(p->next_hop, *(ip_addr *)a->u.ptr))
+  if (!bgp_export_check(p, new))
     return NULL;
 
   /* Create new bucket */
diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h
index ba4f2d4ba..f579ce66f 100644
--- a/proto/bgp/bgp.h
+++ b/proto/bgp/bgp.h
@@ -151,4 +151,10 @@ int bgp_rx(struct birdsock *sk, int size);
 #define BS_OPENCONFIRM		4
 #define BS_ESTABLISHED		5
 
+/* Well-known communities */
+
+#define BGP_COMM_NO_EXPORT		0xffffff01	/* Don't export outside local AS / confed. */
+#define BGP_COMM_NO_ADVERTISE		0xffffff02	/* Don't export at all */
+#define BGP_COMM_NO_EXPORT_SUBCONFED	0xffffff03	/* NO_EXPORT even in local confederation */
+
 #endif