]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Basic analysis of UPDATE packets.
authorMartin Mares <mj@ucw.cz>
Thu, 30 Mar 2000 18:44:23 +0000 (18:44 +0000)
committerMartin Mares <mj@ucw.cz>
Thu, 30 Mar 2000 18:44:23 +0000 (18:44 +0000)
proto/bgp/bgp.c
proto/bgp/bgp.h
proto/bgp/packets.c

index 4ea148d6e184dc89ae65ea860e8e6e7b5bc6f019..e4157565f6ddfa2067204188139e17e5847d390b 100644 (file)
 #include "nest/locks.h"
 #include "conf/conf.h"
 #include "lib/socket.h"
+#include "lib/resource.h"
 
 #include "bgp.h"
 
+struct linpool *bgp_linpool;           /* Global temporary pool */
 static sock *bgp_listen_sk;            /* Global listening socket */
 static int bgp_counter;                        /* Number of protocol instances using the listening socket */
 static list bgp_list;                  /* List of active BGP instances */
+static char *bgp_state_names[] = { "Idle", "Connect", "Active", "OpenSent", "OpenConfirm", "Established" };
 
 static void bgp_connect(struct bgp_proto *p);
 static void bgp_setup_sk(struct bgp_proto *p, struct bgp_conn *conn, sock *s);
@@ -56,6 +59,8 @@ bgp_close(struct bgp_proto *p)
     {
       rfree(bgp_listen_sk);
       bgp_listen_sk = NULL;
+      rfree(bgp_linpool);
+      bgp_linpool = NULL;
     }
   /* FIXME: Automatic restart after errors? */
 }
@@ -275,6 +280,8 @@ bgp_start_locked(struct object_lock *lock)
       else
        bgp_listen_sk = s;
     }
+  if (!bgp_linpool)
+    bgp_linpool = lp_new(&root_pool, 4080);
   add_tail(&bgp_list, &p->bgp_node);
   bgp_connect(p);                      /* FIXME: Use neighbor cache for fast up/down transitions? */
 }
@@ -385,16 +392,25 @@ bgp_check(struct bgp_config *c)
     cf_error("Neighbor must be configured");
 }
 
+void
+bgp_get_status(struct proto *P, byte *buf)
+{
+  struct bgp_proto *p = (struct bgp_proto *) P;
+
+  strcpy(buf, bgp_state_names[MAX(p->incoming_conn.state, p->outgoing_conn.state)]);
+}
+
 struct protocol proto_bgp = {
   name:                        "BGP",
   template:            "bgp%d",
   init:                        bgp_init,
   start:               bgp_start,
   shutdown:            bgp_shutdown,
+  get_status:          bgp_get_status,
 #if 0
   dump:                        bgp_dump,
-  get_status:          bgp_get_status,
   get_route_info:      bgp_get_route_info,
   show_route_data:     bgp_show_route_data
+  /* FIXME: Reconfiguration */
 #endif
 };
index 1631d123acd397b5f0e850ef47d310df4558345a..e93b06eb43549deca9c0dc706604c4640c264599 100644 (file)
@@ -54,6 +54,8 @@ struct bgp_proto {
 #define BGP_RX_BUFFER_SIZE     4096
 #define BGP_TX_BUFFER_SIZE     BGP_MAX_PACKET_LENGTH
 
+extern struct linpool *bgp_linpool;
+
 void bgp_start_timer(struct timer *t, int value);
 void bgp_check(struct bgp_config *c);
 void bgp_error(struct bgp_conn *c, unsigned code, unsigned subcode, unsigned data, unsigned len);
index e530f815acbf905b2b795852deb1e0e287a24f10..3bddbc902ccece04dd4e3937db89094e4e09410e 100644 (file)
@@ -215,14 +215,77 @@ bgp_rx_open(struct bgp_conn *conn, byte *pkt, int len)
   conn->state = BS_OPENCONFIRM;
 }
 
+#define DECODE_PREFIX(pp, ll) do {             \
+  int b = *pp++;                               \
+  int q;                                       \
+  ip_addr temp;                                        \
+  ll--;                                                \
+  if (b > BITS_PER_IP_ADDRESS) { bgp_error(conn, 3, 10, b, 0); return; } \
+  q = (b+7) / 8;                               \
+  if (ll < q) goto too_small;                  \
+  memcpy(&temp, pp, q);                                \
+  pp += q;                                     \
+  ll -= q;                                     \
+  n.n.prefix = ipa_and(ipa_ntoh(temp), ipa_mkmask(b)); \
+  n.n.pxlen = b;                               \
+} while (0)
+
 static void
 bgp_rx_update(struct bgp_conn *conn, byte *pkt, int len)
 {
+  byte *withdrawn, *attrs, *nlri;
+  int withdrawn_len, attr_len, nlri_len;
+  net n;
+  rte e;
+
+  DBG("BGP: UPDATE\n");
   if (conn->state != BS_ESTABLISHED)
     { bgp_error(conn, 5, 0, conn->state, 0); return; }
   bgp_start_timer(conn->hold_timer, conn->hold_time);
 
-  DBG("BGP: UPDATE (ignored)\n");
+  /* Find parts of the packet and check sizes */
+  if (len < 23)
+    {
+    too_small:
+      bgp_error(conn, 1, 2, len, 2);
+      return;
+    }
+  withdrawn = pkt + 21;
+  withdrawn_len = get_u16(pkt + 19);
+  if (withdrawn_len + 23 > len)
+    goto too_small;
+  attrs = withdrawn + withdrawn_len + 2;
+  attr_len = get_u16(attrs - 2);
+  if (withdrawn_len + attr_len + 23 > len)
+    goto too_small;
+  nlri = attrs + attr_len;
+  nlri_len = len - withdrawn_len - attr_len - 23;
+  if (!attr_len && nlri_len)
+    goto too_small;
+  DBG("Sizes: withdrawn=%d, attrs=%d, NLRI=%d\n", withdrawn_len, attr_len, nlri_len);
+
+  /* Withdraw routes */
+  while (withdrawn_len)
+    {
+      DECODE_PREFIX(withdrawn, withdrawn_len);
+      DBG("Withdraw %I/%d\n", n.n.prefix, n.n.pxlen);
+    }
+
+  if (nlri_len)
+    {
+#if 0
+      rta *a = bgp_decode_attrs(conn, attrs, attr_len, bgp_linpool);
+      if (a)
+#endif
+       {
+         while (nlri_len)
+           {
+             DECODE_PREFIX(nlri, nlri_len);
+             DBG("Add %I/%d\n", n.n.prefix, n.n.pxlen);
+           }
+       }
+      lp_flush(bgp_linpool);
+    }
 }
 
 static void