diff options
Diffstat (limited to 'net/openbgpd/files/patch-bgpd_rde_update.c')
-rw-r--r-- | net/openbgpd/files/patch-bgpd_rde_update.c | 644 |
1 files changed, 0 insertions, 644 deletions
diff --git a/net/openbgpd/files/patch-bgpd_rde_update.c b/net/openbgpd/files/patch-bgpd_rde_update.c deleted file mode 100644 index ccd9601dcd3d..000000000000 --- a/net/openbgpd/files/patch-bgpd_rde_update.c +++ /dev/null @@ -1,644 +0,0 @@ -Index: bgpd/rde_update.c -=================================================================== -RCS file: /home/cvs/private/hrs/openbgpd/bgpd/rde_update.c,v -retrieving revision 1.1.1.7 -retrieving revision 1.8 -diff -u -p -r1.1.1.7 -r1.8 ---- bgpd/rde_update.c 14 Feb 2010 20:19:57 -0000 1.1.1.7 -+++ bgpd/rde_update.c 13 Oct 2012 18:36:00 -0000 1.8 -@@ -1,4 +1,4 @@ --/* $OpenBSD: rde_update.c,v 1.68 2009/06/06 01:10:29 claudio Exp $ */ -+/* $OpenBSD: rde_update.c,v 1.77 2010/01/13 06:02:37 claudio Exp $ */ - - /* - * Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org> -@@ -17,19 +17,27 @@ - */ - #include <sys/types.h> - #include <sys/queue.h> -+#if defined(__FreeBSD__) /* sys/hash.h */ -+#include "hash.h" -+#else - #include <sys/hash.h> -+#endif /* defined(__FreeBSD__) */ - -+#include <limits.h> - #include <stdlib.h> - #include <string.h> -+#if defined(__FreeBSD__) /* limits.h */ -+#include <limits.h> -+#endif /* defined(__FreeBSD__) */ - - #include "bgpd.h" - #include "rde.h" - - in_addr_t up_get_nexthop(struct rde_peer *, struct rde_aspath *); - int up_generate_mp_reach(struct rde_peer *, struct update_attr *, -- struct rde_aspath *, sa_family_t); -+ struct rde_aspath *, u_int8_t); - int up_generate_attr(struct rde_peer *, struct update_attr *, -- struct rde_aspath *, sa_family_t); -+ struct rde_aspath *, u_int8_t); - - /* update stuff. */ - struct update_prefix { -@@ -65,10 +73,12 @@ RB_GENERATE(uptree_attr, update_attr, en - void - up_init(struct rde_peer *peer) - { -- TAILQ_INIT(&peer->updates); -- TAILQ_INIT(&peer->withdraws); -- TAILQ_INIT(&peer->updates6); -- TAILQ_INIT(&peer->withdraws6); -+ u_int8_t i; -+ -+ for (i = 0; i < AID_MAX; i++) { -+ TAILQ_INIT(&peer->updates[i]); -+ TAILQ_INIT(&peer->withdraws[i]); -+ } - RB_INIT(&peer->up_prefix); - RB_INIT(&peer->up_attrs); - peer->up_pcnt = 0; -@@ -103,8 +113,10 @@ up_clear(struct uplist_attr *updates, st - void - up_down(struct rde_peer *peer) - { -- up_clear(&peer->updates, &peer->withdraws); -- up_clear(&peer->updates6, &peer->withdraws6); -+ u_int8_t i; -+ -+ for (i = 0; i < AID_MAX; i++) -+ up_clear(&peer->updates[i], &peer->withdraws[i]); - - RB_INIT(&peer->up_prefix); - RB_INIT(&peer->up_attrs); -@@ -120,19 +132,19 @@ up_prefix_cmp(struct update_prefix *a, s - { - int i; - -- if (a->prefix.af < b->prefix.af) -+ if (a->prefix.aid < b->prefix.aid) - return (-1); -- if (a->prefix.af > b->prefix.af) -+ if (a->prefix.aid > b->prefix.aid) - return (1); - -- switch (a->prefix.af) { -- case AF_INET: -+ switch (a->prefix.aid) { -+ case AID_INET: - if (ntohl(a->prefix.v4.s_addr) < ntohl(b->prefix.v4.s_addr)) - return (-1); - if (ntohl(a->prefix.v4.s_addr) > ntohl(b->prefix.v4.s_addr)) - return (1); - break; -- case AF_INET6: -+ case AID_INET6: - i = memcmp(&a->prefix.v6, &b->prefix.v6, - sizeof(struct in6_addr)); - if (i > 0) -@@ -140,6 +152,25 @@ up_prefix_cmp(struct update_prefix *a, s - if (i < 0) - return (-1); - break; -+ case AID_VPN_IPv4: -+ if (betoh64(a->prefix.vpn4.rd) < betoh64(b->prefix.vpn4.rd)) -+ return (-1); -+ if (betoh64(a->prefix.vpn4.rd) > betoh64(b->prefix.vpn4.rd)) -+ return (1); -+ if (ntohl(a->prefix.v4.s_addr) < ntohl(b->prefix.v4.s_addr)) -+ return (-1); -+ if (ntohl(a->prefix.v4.s_addr) > ntohl(b->prefix.v4.s_addr)) -+ return (1); -+ if (a->prefixlen < b->prefixlen) -+ return (-1); -+ if (a->prefixlen > b->prefixlen) -+ return (1); -+ if (a->prefix.vpn4.labellen < b->prefix.vpn4.labellen) -+ return (-1); -+ if (a->prefix.vpn4.labellen > b->prefix.vpn4.labellen) -+ return (1); -+ return (memcmp(a->prefix.vpn4.labelstack, -+ b->prefix.vpn4.labelstack, a->prefix.vpn4.labellen)); - default: - fatalx("pt_prefix_cmp: unknown af"); - } -@@ -174,18 +205,8 @@ up_add(struct rde_peer *peer, struct upd - struct uplist_attr *upl = NULL; - struct uplist_prefix *wdl = NULL; - -- switch (p->prefix.af) { -- case AF_INET: -- upl = &peer->updates; -- wdl = &peer->withdraws; -- break; -- case AF_INET6: -- upl = &peer->updates6; -- wdl = &peer->withdraws6; -- break; -- default: -- fatalx("up_add: unknown AF"); -- } -+ upl = &peer->updates[p->prefix.aid]; -+ wdl = &peer->withdraws[p->prefix.aid]; - - /* 1. search for attr */ - if (a != NULL && (na = RB_FIND(uptree_attr, &peer->up_attrs, a)) == -@@ -270,23 +291,16 @@ up_test_update(struct rde_peer *peer, st - /* Do not send routes back to sender */ - return (0); - -+ if (p->aspath->flags & F_ATTR_PARSE_ERR) -+ fatalx("try to send out a botched path"); - if (p->aspath->flags & F_ATTR_LOOP) - fatalx("try to send out a looped path"); - - pt_getaddr(p->prefix, &addr); -- switch (addr.af) { -- case AF_INET: -- if (peer->capa_announced.mp_v4 == SAFI_NONE && -- peer->capa_received.mp_v6 != SAFI_NONE) -- return (-1); -- break; -- case AF_INET6: -- if (peer->capa_announced.mp_v6 == SAFI_NONE) -- return (-1); -- break; -- } -+ if (peer->capa.mp[addr.aid] == 0) -+ return (-1); - -- if (p->aspath->peer->conf.ebgp == 0 && peer->conf.ebgp == 0) { -+ if (!p->aspath->peer->conf.ebgp && !peer->conf.ebgp) { - /* - * route reflector redistribution rules: - * 1. if announce is set -> announce -@@ -325,13 +339,13 @@ up_test_update(struct rde_peer *peer, st - } - - /* well known communities */ -- if (rde_filter_community(p->aspath, -+ if (community_match(p->aspath, - COMMUNITY_WELLKNOWN, COMMUNITY_NO_ADVERTISE)) - return (0); -- if (peer->conf.ebgp && rde_filter_community(p->aspath, -+ if (peer->conf.ebgp && community_match(p->aspath, - COMMUNITY_WELLKNOWN, COMMUNITY_NO_EXPORT)) - return (0); -- if (peer->conf.ebgp && rde_filter_community(p->aspath, -+ if (peer->conf.ebgp && community_match(p->aspath, - COMMUNITY_WELLKNOWN, COMMUNITY_NO_EXPSUBCONFED)) - return (0); - -@@ -362,7 +376,7 @@ up_generate(struct rde_peer *peer, struc - if (ua == NULL) - fatal("up_generate"); - -- if (up_generate_attr(peer, ua, asp, addr->af) == -1) { -+ if (up_generate_attr(peer, ua, asp, addr->aid) == -1) { - log_warnx("generation of bgp path attributes failed"); - free(ua); - return (-1); -@@ -444,18 +458,12 @@ up_generate_updates(struct filter_head * - /* send a default route to the specified peer */ - void - up_generate_default(struct filter_head *rules, struct rde_peer *peer, -- sa_family_t af) -+ u_int8_t aid) - { - struct rde_aspath *asp, *fasp; - struct bgpd_addr addr; - -- if (peer->capa_received.mp_v4 == SAFI_NONE && -- peer->capa_received.mp_v6 != SAFI_NONE && -- af == AF_INET) -- return; -- -- if (peer->capa_received.mp_v6 == SAFI_NONE && -- af == AF_INET6) -+ if (peer->capa.mp[aid] == 0) - return; - - asp = path_get(); -@@ -471,7 +479,7 @@ up_generate_default(struct filter_head * - - /* filter as usual */ - bzero(&addr, sizeof(addr)); -- addr.af = af; -+ addr.aid = aid; - - if (rde_filter(peer->ribid, &fasp, rules, peer, asp, &addr, 0, NULL, - DIR_OUT) == ACTION_DENY) { -@@ -491,6 +499,43 @@ up_generate_default(struct filter_head * - path_put(asp); - } - -+/* generate a EoR marker in the update list. This is a horrible hack. */ -+int -+up_generate_marker(struct rde_peer *peer, u_int8_t aid) -+{ -+ struct update_attr *ua; -+ struct update_attr *na = NULL; -+ struct uplist_attr *upl = NULL; -+ -+ ua = calloc(1, sizeof(struct update_attr)); -+ if (ua == NULL) -+ fatal("up_generate_marker"); -+ -+ upl = &peer->updates[aid]; -+ -+ /* 1. search for attr */ -+ if ((na = RB_FIND(uptree_attr, &peer->up_attrs, ua)) == NULL) { -+ /* 1.1 if not found -> add */ -+ TAILQ_INIT(&ua->prefix_h); -+ if (RB_INSERT(uptree_attr, &peer->up_attrs, ua) != NULL) { -+ log_warnx("uptree_attr insert failed"); -+ /* cleanup */ -+ free(ua); -+ return (-1); -+ } -+ TAILQ_INSERT_TAIL(upl, ua, attr_l); -+ peer->up_acnt++; -+ } else { -+ /* 1.2 if found -> use that, free ua */ -+ free(ua); -+ ua = na; -+ /* move to end of update queue */ -+ TAILQ_REMOVE(upl, ua, attr_l); -+ TAILQ_INSERT_TAIL(upl, ua, attr_l); -+ } -+ return (0); -+} -+ - u_char up_attr_buf[4096]; - - /* only for IPv4 */ -@@ -551,28 +596,41 @@ up_get_nexthop(struct rde_peer *peer, st - - int - up_generate_mp_reach(struct rde_peer *peer, struct update_attr *upa, -- struct rde_aspath *a, sa_family_t af) -+ struct rde_aspath *a, u_int8_t aid) - { - u_int16_t tmp; - -- switch (af) { -- case AF_INET6: -+ switch (aid) { -+ case AID_INET6: - upa->mpattr_len = 21; /* AFI + SAFI + NH LEN + NH + Reserved */ - upa->mpattr = malloc(upa->mpattr_len); - if (upa->mpattr == NULL) - fatal("up_generate_mp_reach"); -- tmp = htons(AFI_IPv6); -+ if (aid2afi(aid, &tmp, &upa->mpattr[2])) -+ fatalx("up_generate_mp_reachi: bad AID"); -+ tmp = htons(tmp); - memcpy(upa->mpattr, &tmp, sizeof(tmp)); -- upa->mpattr[2] = SAFI_UNICAST; - upa->mpattr[3] = sizeof(struct in6_addr); - upa->mpattr[20] = 0; /* Reserved must be 0 */ - - /* nexthop dance see also up_get_nexthop() */ -- if (peer->conf.ebgp == 0) { -+ if (a->flags & F_NEXTHOP_NOMODIFY) { -+ /* no modify flag set */ -+ if (a->nexthop == NULL) -+ memcpy(&upa->mpattr[4], &peer->local_v6_addr.v6, -+ sizeof(struct in6_addr)); -+ else -+ memcpy(&upa->mpattr[4], -+ &a->nexthop->exit_nexthop.v6, -+ sizeof(struct in6_addr)); -+ } else if (a->flags & F_NEXTHOP_SELF) -+ memcpy(&upa->mpattr[4], &peer->local_v6_addr.v6, -+ sizeof(struct in6_addr)); -+ else if (!peer->conf.ebgp) { - /* ibgp */ - if (a->nexthop == NULL || -- (a->nexthop->exit_nexthop.af == AF_INET6 && -- memcmp(&a->nexthop->exit_nexthop.v6, -+ (a->nexthop->exit_nexthop.aid == AID_INET6 && -+ !memcmp(&a->nexthop->exit_nexthop.v6, - &peer->remote_addr.v6, sizeof(struct in6_addr)))) - memcpy(&upa->mpattr[4], &peer->local_v6_addr.v6, - sizeof(struct in6_addr)); -@@ -603,6 +661,68 @@ up_generate_mp_reach(struct rde_peer *pe - memcpy(&upa->mpattr[4], &peer->local_v6_addr.v6, - sizeof(struct in6_addr)); - return (0); -+ case AID_VPN_IPv4: -+ upa->mpattr_len = 17; /* AFI + SAFI + NH LEN + NH + Reserved */ -+ upa->mpattr = calloc(upa->mpattr_len, 1); -+ if (upa->mpattr == NULL) -+ fatal("up_generate_mp_reach"); -+ if (aid2afi(aid, &tmp, &upa->mpattr[2])) -+ fatalx("up_generate_mp_reachi: bad AID"); -+ tmp = htons(tmp); -+ memcpy(upa->mpattr, &tmp, sizeof(tmp)); -+ upa->mpattr[3] = sizeof(u_int64_t) + sizeof(struct in_addr); -+ -+ /* nexthop dance see also up_get_nexthop() */ -+ if (a->flags & F_NEXTHOP_NOMODIFY) { -+ /* no modify flag set */ -+ if (a->nexthop == NULL) -+ memcpy(&upa->mpattr[12], -+ &peer->local_v4_addr.v4, -+ sizeof(struct in_addr)); -+ else -+ /* nexthops are stored as IPv4 addrs */ -+ memcpy(&upa->mpattr[12], -+ &a->nexthop->exit_nexthop.v4, -+ sizeof(struct in_addr)); -+ } else if (a->flags & F_NEXTHOP_SELF) -+ memcpy(&upa->mpattr[12], &peer->local_v4_addr.v4, -+ sizeof(struct in_addr)); -+ else if (!peer->conf.ebgp) { -+ /* ibgp */ -+ if (a->nexthop == NULL || -+ (a->nexthop->exit_nexthop.aid == AID_INET && -+ !memcmp(&a->nexthop->exit_nexthop.v4, -+ &peer->remote_addr.v4, sizeof(struct in_addr)))) -+ memcpy(&upa->mpattr[12], -+ &peer->local_v4_addr.v4, -+ sizeof(struct in_addr)); -+ else -+ memcpy(&upa->mpattr[12], -+ &a->nexthop->exit_nexthop.v4, -+ sizeof(struct in_addr)); -+ } else if (peer->conf.distance == 1) { -+ /* ebgp directly connected */ -+ if (a->nexthop != NULL && -+ a->nexthop->flags & NEXTHOP_CONNECTED) -+ if (prefix_compare(&peer->remote_addr, -+ &a->nexthop->nexthop_net, -+ a->nexthop->nexthop_netlen) == 0) { -+ /* -+ * nexthop and peer are in the same -+ * subnet -+ */ -+ memcpy(&upa->mpattr[12], -+ &a->nexthop->exit_nexthop.v4, -+ sizeof(struct in_addr)); -+ return (0); -+ } -+ memcpy(&upa->mpattr[12], &peer->local_v4_addr.v4, -+ sizeof(struct in_addr)); -+ } else -+ /* ebgp multihop */ -+ memcpy(&upa->mpattr[12], &peer->local_v4_addr.v4, -+ sizeof(struct in_addr)); -+ return (0); - default: - break; - } -@@ -611,7 +731,7 @@ up_generate_mp_reach(struct rde_peer *pe - - int - up_generate_attr(struct rde_peer *peer, struct update_attr *upa, -- struct rde_aspath *a, sa_family_t af) -+ struct rde_aspath *a, u_int8_t aid) - { - struct attr *oa, *newaggr = NULL; - u_char *pdata; -@@ -643,8 +763,8 @@ up_generate_attr(struct rde_peer *peer, - wlen += r; len -= r; - free(pdata); - -- switch (af) { -- case AF_INET: -+ switch (aid) { -+ case AID_INET: - nexthop = up_get_nexthop(peer, a); - if ((r = attr_write(up_attr_buf + wlen, len, ATTR_WELL_KNOWN, - ATTR_NEXTHOP, &nexthop, 4)) == -1) -@@ -659,9 +779,11 @@ up_generate_attr(struct rde_peer *peer, - /* - * The old MED from other peers MUST not be announced to others - * unless the MED is originating from us or the peer is an IBGP one. -+ * Only exception are routers with "transparent-as yes" set. - */ -- if (a->flags & F_ATTR_MED && (peer->conf.ebgp == 0 || -- a->flags & F_ATTR_MED_ANNOUNCE)) { -+ if (a->flags & F_ATTR_MED && (!peer->conf.ebgp || -+ a->flags & F_ATTR_MED_ANNOUNCE || -+ peer->conf.flags & PEERFLAG_TRANS_AS)) { - tmp32 = htonl(a->med); - if ((r = attr_write(up_attr_buf + wlen, len, ATTR_OPTIONAL, - ATTR_MED, &tmp32, 4)) == -1) -@@ -669,7 +791,7 @@ up_generate_attr(struct rde_peer *peer, - wlen += r; len -= r; - } - -- if (peer->conf.ebgp == 0) { -+ if (!peer->conf.ebgp) { - /* local preference, only valid for ibgp */ - tmp32 = htonl(a->lpref); - if ((r = attr_write(up_attr_buf + wlen, len, ATTR_WELL_KNOWN, -@@ -704,7 +826,7 @@ up_generate_attr(struct rde_peer *peer, - u_int16_t tas; - - if ((!(oa->flags & ATTR_TRANSITIVE)) && -- peer->conf.ebgp != 0) { -+ peer->conf.ebgp) { - r = 0; - break; - } -@@ -730,7 +852,7 @@ up_generate_attr(struct rde_peer *peer, - case ATTR_ORIGINATOR_ID: - case ATTR_CLUSTER_LIST: - if ((!(oa->flags & ATTR_TRANSITIVE)) && -- peer->conf.ebgp != 0) { -+ peer->conf.ebgp) { - r = 0; - break; - } -@@ -791,7 +913,7 @@ up_generate_attr(struct rde_peer *peer, - - /* write mp attribute to different buffer */ - if (ismp) -- if (up_generate_mp_reach(peer, upa, a, AF_INET6) == -1) -+ if (up_generate_mp_reach(peer, upa, a, aid) == -1) - return (-1); - - /* the bgp path attributes are now stored in the global buf */ -@@ -810,6 +932,7 @@ up_dump_prefix(u_char *buf, int len, str - { - struct update_prefix *upp; - int r, wpos = 0; -+ u_int8_t i; - - while ((upp = TAILQ_FIRST(prefix_head)) != NULL) { - if ((r = prefix_write(buf + wpos, len - wpos, -@@ -820,13 +943,14 @@ up_dump_prefix(u_char *buf, int len, str - log_warnx("dequeuing update failed."); - TAILQ_REMOVE(upp->prefix_h, upp, prefix_l); - peer->up_pcnt--; -- if (upp->prefix_h == &peer->withdraws || -- upp->prefix_h == &peer->withdraws6) { -- peer->up_wcnt--; -- peer->prefix_sent_withdraw++; -- } else { -- peer->up_nlricnt--; -- peer->prefix_sent_update++; -+ for (i = 0; i < AID_MAX; i++) { -+ if (upp->prefix_h == &peer->withdraws[i]) { -+ peer->up_wcnt--; -+ peer->prefix_sent_withdraw++; -+ } else { -+ peer->up_nlricnt--; -+ peer->prefix_sent_update++; -+ } - } - free(upp); - } -@@ -844,16 +968,21 @@ up_dump_attrnlri(u_char *buf, int len, s - * It is possible that a queued path attribute has no nlri prefix. - * Ignore and remove those path attributes. - */ -- while ((upa = TAILQ_FIRST(&peer->updates)) != NULL) -+ while ((upa = TAILQ_FIRST(&peer->updates[AID_INET])) != NULL) - if (TAILQ_EMPTY(&upa->prefix_h)) { -+ attr_len = upa->attr_len; - if (RB_REMOVE(uptree_attr, &peer->up_attrs, - upa) == NULL) - log_warnx("dequeuing update failed."); -- TAILQ_REMOVE(&peer->updates, upa, attr_l); -+ TAILQ_REMOVE(&peer->updates[AID_INET], upa, attr_l); - free(upa->attr); - free(upa->mpattr); - free(upa); - peer->up_acnt--; -+ /* XXX horrible hack, -+ * if attr_len is 0, it is a EoR marker */ -+ if (attr_len == 0) -+ return (-1); - } else - break; - -@@ -884,7 +1013,7 @@ up_dump_attrnlri(u_char *buf, int len, s - if (TAILQ_EMPTY(&upa->prefix_h)) { - if (RB_REMOVE(uptree_attr, &peer->up_attrs, upa) == NULL) - log_warnx("dequeuing update failed."); -- TAILQ_REMOVE(&peer->updates, upa, attr_l); -+ TAILQ_REMOVE(&peer->updates[AID_INET], upa, attr_l); - free(upa->attr); - free(upa->mpattr); - free(upa); -@@ -895,12 +1024,13 @@ up_dump_attrnlri(u_char *buf, int len, s - } - - u_char * --up_dump_mp_unreach(u_char *buf, u_int16_t *len, struct rde_peer *peer) -+up_dump_mp_unreach(u_char *buf, u_int16_t *len, struct rde_peer *peer, -+ u_int8_t aid) - { - int wpos; - u_int16_t datalen, tmp; - u_int16_t attrlen = 2; /* attribute header (without len) */ -- u_int8_t flags = ATTR_OPTIONAL; -+ u_int8_t flags = ATTR_OPTIONAL, safi; - - /* - * reserve space for withdraw len, attr len, the attribute header -@@ -912,7 +1042,7 @@ up_dump_mp_unreach(u_char *buf, u_int16_ - return (NULL); - - datalen = up_dump_prefix(buf + wpos, *len - wpos, -- &peer->withdraws6, peer); -+ &peer->withdraws[aid], peer); - if (datalen == 0) - return (NULL); - -@@ -920,9 +1050,11 @@ up_dump_mp_unreach(u_char *buf, u_int16_ - - /* prepend header, need to do it reverse */ - /* safi & afi */ -- buf[--wpos] = SAFI_UNICAST; -+ if (aid2afi(aid, &tmp, &safi)) -+ fatalx("up_dump_mp_unreach: bad AID"); -+ buf[--wpos] = safi; - wpos -= sizeof(u_int16_t); -- tmp = htons(AFI_IPv6); -+ tmp = htons(tmp); - memcpy(buf + wpos, &tmp, sizeof(u_int16_t)); - - /* attribute length */ -@@ -959,33 +1091,39 @@ up_dump_mp_unreach(u_char *buf, u_int16_ - return (buf + wpos); - } - --u_char * --up_dump_mp_reach(u_char *buf, u_int16_t *len, struct rde_peer *peer) -+int -+up_dump_mp_reach(u_char *buf, u_int16_t *len, struct rde_peer *peer, -+ u_int8_t aid) - { - struct update_attr *upa; - int wpos; -- u_int16_t datalen, tmp; -+ u_int16_t attr_len, datalen, tmp; - u_int8_t flags = ATTR_OPTIONAL; - - /* - * It is possible that a queued path attribute has no nlri prefix. - * Ignore and remove those path attributes. - */ -- while ((upa = TAILQ_FIRST(&peer->updates6)) != NULL) -+ while ((upa = TAILQ_FIRST(&peer->updates[aid])) != NULL) - if (TAILQ_EMPTY(&upa->prefix_h)) { -+ attr_len = upa->attr_len; - if (RB_REMOVE(uptree_attr, &peer->up_attrs, - upa) == NULL) - log_warnx("dequeuing update failed."); -- TAILQ_REMOVE(&peer->updates6, upa, attr_l); -+ TAILQ_REMOVE(&peer->updates[aid], upa, attr_l); - free(upa->attr); - free(upa->mpattr); - free(upa); - peer->up_acnt--; -+ /* XXX horrible hack, -+ * if attr_len is 0, it is a EoR marker */ -+ if (attr_len == 0) -+ return (-1); - } else - break; - - if (upa == NULL) -- return (NULL); -+ return (-2); - - /* - * reserve space for attr len, the attributes, the -@@ -993,12 +1131,12 @@ up_dump_mp_reach(u_char *buf, u_int16_t - */ - wpos = 2 + 2 + upa->attr_len + 4 + upa->mpattr_len; - if (*len < wpos) -- return (NULL); -+ return (-2); - - datalen = up_dump_prefix(buf + wpos, *len - wpos, - &upa->prefix_h, peer); - if (datalen == 0) -- return (NULL); -+ return (-2); - - if (upa->mpattr_len == 0 || upa->mpattr == NULL) - fatalx("mulitprotocol update without MP attrs"); -@@ -1038,7 +1176,7 @@ up_dump_mp_reach(u_char *buf, u_int16_t - if (TAILQ_EMPTY(&upa->prefix_h)) { - if (RB_REMOVE(uptree_attr, &peer->up_attrs, upa) == NULL) - log_warnx("dequeuing update failed."); -- TAILQ_REMOVE(&peer->updates6, upa, attr_l); -+ TAILQ_REMOVE(&peer->updates[aid], upa, attr_l); - free(upa->attr); - free(upa->mpattr); - free(upa); -@@ -1046,6 +1184,5 @@ up_dump_mp_reach(u_char *buf, u_int16_t - } - - *len = datalen + 4; -- return (buf + wpos); -+ return (wpos); - } -- |