summaryrefslogtreecommitdiffstats
path: root/proto/bgp/packets.c
diff options
context:
space:
mode:
Diffstat (limited to 'proto/bgp/packets.c')
-rw-r--r--proto/bgp/packets.c51
1 files changed, 31 insertions, 20 deletions
diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c
index 3bddbc9..7764999 100644
--- a/proto/bgp/packets.c
+++ b/proto/bgp/packets.c
@@ -218,24 +218,26 @@ bgp_rx_open(struct bgp_conn *conn, byte *pkt, int len)
#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); \
+ if (ll < q) goto malformed; \
+ memcpy(&prefix, pp, q); \
pp += q; \
ll -= q; \
- n.n.prefix = ipa_and(ipa_ntoh(temp), ipa_mkmask(b)); \
- n.n.pxlen = b; \
+ prefix = ipa_and(ipa_ntoh(prefix), ipa_mkmask(b)); \
+ pxlen = b; \
} while (0)
+/* FIXME: Check validity of prefixes */
static void
bgp_rx_update(struct bgp_conn *conn, byte *pkt, int len)
{
+ struct bgp_proto *bgp = conn->bgp;
byte *withdrawn, *attrs, *nlri;
- int withdrawn_len, attr_len, nlri_len;
- net n;
+ ip_addr prefix;
+ int withdrawn_len, attr_len, nlri_len, pxlen;
+ net *n;
rte e;
DBG("BGP: UPDATE\n");
@@ -246,45 +248,54 @@ bgp_rx_update(struct bgp_conn *conn, byte *pkt, int len)
/* 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;
+ {
+ malformed:
+ bgp_error(conn, 3, 1, len, 0);
+ return;
+ }
attrs = withdrawn + withdrawn_len + 2;
attr_len = get_u16(attrs - 2);
if (withdrawn_len + attr_len + 23 > len)
- goto too_small;
+ goto malformed;
nlri = attrs + attr_len;
nlri_len = len - withdrawn_len - attr_len - 23;
if (!attr_len && nlri_len)
- goto too_small;
+ goto malformed;
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);
+ DBG("Withdraw %I/%d\n", prefix, pxlen);
+ if (n = net_find(bgp->p.table, prefix, pxlen))
+ rte_update(bgp->p.table, n, &bgp->p, NULL);
}
if (nlri_len)
{
-#if 0
rta *a = bgp_decode_attrs(conn, attrs, attr_len, bgp_linpool);
- if (a)
-#endif
+ if (!a)
+ return;
+ while (nlri_len)
{
- while (nlri_len)
- {
- DECODE_PREFIX(nlri, nlri_len);
- DBG("Add %I/%d\n", n.n.prefix, n.n.pxlen);
- }
+ rte *e;
+ DECODE_PREFIX(nlri, nlri_len); /* FIXME: Uncache rta ! */
+ DBG("Add %I/%d\n", prefix, pxlen);
+ e = rte_get_temp(a);
+ n = net_get(bgp->p.table, prefix, pxlen);
+ e->net = n;
+ e->pflags = 0;
+ rte_update(bgp->p.table, n, &bgp->p, e);
}
lp_flush(bgp_linpool);
+ rta_free(a);
}
}