Commit 973399ae authored by Martin Mareš's avatar Martin Mareš

Basic analysis of UPDATE packets.

parent b552ecc4
......@@ -15,12 +15,15 @@
#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
};
......@@ -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);
......
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment