diff options
Diffstat (limited to 'proto/bgp/packets.c')
-rw-r--r-- | proto/bgp/packets.c | 51 |
1 files changed, 31 insertions, 20 deletions
diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index 3bddbc90..7764999e 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); } } |