diff options
author | Kurt Jaeger <pi@FreeBSD.org> | 2019-06-03 20:08:36 +0000 |
---|---|---|
committer | Kurt Jaeger <pi@FreeBSD.org> | 2019-06-03 20:08:36 +0000 |
commit | 713c2289b8d66d3752c1225ca18d740daa50c8fc (patch) | |
tree | 26af7b6de4c410d2e2810fec4c81c3ab0b9c5e76 /net/openbgpd/files/patch-bgpd_rde_rib.c | |
parent | Upgrade to 0.0.5 (diff) |
net/openbgpd: revert upgrade from 6.5p0 to 5.2.20121209
- openbgpd version 6.5p0 was the "portable" version, which specifically
does *not* support kernel routing updates.
- Therefore this is only suitable for route servers/collectors, not
for production use in routers. This significantly violates POLA :)
PR: 213445
Submitted by: Oliver H <oliver@watershed.co.uk>
Diffstat (limited to 'net/openbgpd/files/patch-bgpd_rde_rib.c')
-rw-r--r-- | net/openbgpd/files/patch-bgpd_rde_rib.c | 513 |
1 files changed, 513 insertions, 0 deletions
diff --git a/net/openbgpd/files/patch-bgpd_rde_rib.c b/net/openbgpd/files/patch-bgpd_rde_rib.c new file mode 100644 index 000000000000..2fe781c69c4b --- /dev/null +++ b/net/openbgpd/files/patch-bgpd_rde_rib.c @@ -0,0 +1,513 @@ +Index: bgpd/rde_rib.c +=================================================================== +RCS file: /home/cvs/private/hrs/openbgpd/bgpd/rde_rib.c,v +retrieving revision 1.1.1.7 +retrieving revision 1.8 +diff -u -p -r1.1.1.7 -r1.8 +--- bgpd/rde_rib.c 14 Feb 2010 20:19:57 -0000 1.1.1.7 ++++ bgpd/rde_rib.c 13 Oct 2012 18:36:00 -0000 1.8 +@@ -1,4 +1,4 @@ +-/* $OpenBSD: rde_rib.c,v 1.116 2009/06/29 14:13:48 claudio Exp $ */ ++/* $OpenBSD: rde_rib.c,v 1.133 2012/07/01 11:55:13 sthen Exp $ */ + + /* + * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> +@@ -18,7 +18,11 @@ + + #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 <stdlib.h> + #include <string.h> +@@ -50,16 +54,15 @@ RB_GENERATE(rib_tree, rib_entry, rib_e, + + /* RIB specific functions */ + u_int16_t +-rib_new(int id, char *name, u_int16_t flags) ++rib_new(char *name, u_int rtableid, u_int16_t flags) + { + struct rib *xribs; + size_t newsize; ++ u_int16_t id; + +- if (id < 0) { +- for (id = 0; id < rib_size; id++) { +- if (*ribs[id].name == '\0') +- break; +- } ++ for (id = 0; id < rib_size; id++) { ++ if (*ribs[id].name == '\0') ++ break; + } + + if (id == RIB_FAILED) +@@ -78,9 +81,10 @@ rib_new(int id, char *name, u_int16_t fl + bzero(&ribs[id], sizeof(struct rib)); + strlcpy(ribs[id].name, name, sizeof(ribs[id].name)); + RB_INIT(&ribs[id].rib); +- ribs[id].state = RIB_ACTIVE; ++ ribs[id].state = RECONF_REINIT; + ribs[id].id = id; + ribs[id].flags = flags; ++ ribs[id].rtableid = rtableid; + + return (id); + } +@@ -173,15 +177,16 @@ rib_lookup(struct rib *rib, struct bgpd_ + struct rib_entry *re; + int i; + +- switch (addr->af) { +- case AF_INET: ++ switch (addr->aid) { ++ case AID_INET: ++ case AID_VPN_IPv4: + for (i = 32; i >= 0; i--) { + re = rib_get(rib, addr, i); + if (re != NULL) + return (re); + } + break; +- case AF_INET6: ++ case AID_INET6: + for (i = 128; i >= 0; i--) { + re = rib_get(rib, addr, i); + if (re != NULL) +@@ -215,6 +220,7 @@ rib_add(struct rib *rib, struct bgpd_add + + if (RB_INSERT(rib_tree, &rib->rib, re) != NULL) { + log_warnx("rib_add: insert failed"); ++ free(re); + return (NULL); + } + +@@ -254,7 +260,7 @@ rib_empty(struct rib_entry *re) + + void + rib_dump(struct rib *rib, void (*upcall)(struct rib_entry *, void *), +- void *arg, sa_family_t af) ++ void *arg, u_int8_t aid) + { + struct rib_context *ctx; + +@@ -263,7 +269,7 @@ rib_dump(struct rib *rib, void (*upcall) + ctx->ctx_rib = rib; + ctx->ctx_upcall = upcall; + ctx->ctx_arg = arg; +- ctx->ctx_af = af; ++ ctx->ctx_aid = aid; + rib_dump_r(ctx); + } + +@@ -280,7 +286,8 @@ rib_dump_r(struct rib_context *ctx) + re = rib_restart(ctx); + + for (i = 0; re != NULL; re = RB_NEXT(rib_tree, unused, re)) { +- if (ctx->ctx_af != AF_UNSPEC && ctx->ctx_af != re->prefix->af) ++ if (ctx->ctx_aid != AID_UNSPEC && ++ ctx->ctx_aid != re->prefix->aid) + continue; + if (ctx->ctx_count && i++ >= ctx->ctx_count && + (re->flags & F_RIB_ENTRYLOCK) == 0) { +@@ -308,7 +315,7 @@ rib_restart(struct rib_context *ctx) + re->flags &= ~F_RIB_ENTRYLOCK; + + /* find first non empty element */ +- while (rib_empty(re)) ++ while (re && rib_empty(re)) + re = RB_NEXT(rib_tree, unused, re); + + /* free the previously locked rib element if empty */ +@@ -502,6 +509,36 @@ path_remove(struct rde_aspath *asp) + } + } + ++/* remove all stale routes or if staletime is 0 remove all routes for ++ a specified AID. */ ++void ++path_remove_stale(struct rde_aspath *asp, u_int8_t aid) ++{ ++ struct prefix *p, *np; ++ time_t staletime; ++ ++ staletime = asp->peer->staletime[aid]; ++ for (p = LIST_FIRST(&asp->prefix_h); p != NULL; p = np) { ++ np = LIST_NEXT(p, path_l); ++ if (p->prefix->aid != aid) ++ continue; ++ ++ if (staletime && p->lastchange > staletime) ++ continue; ++ ++ if (asp->pftableid) { ++ struct bgpd_addr addr; ++ ++ pt_getaddr(p->prefix, &addr); ++ /* Commit is done in peer_flush() */ ++ rde_send_pftable(p->aspath->pftableid, &addr, ++ p->prefix->prefixlen, 1); ++ } ++ prefix_destroy(p); ++ } ++} ++ ++ + /* this function is only called by prefix_remove and path_remove */ + void + path_destroy(struct rde_aspath *asp) +@@ -624,48 +661,6 @@ static void prefix_link(struct prefix + struct rde_aspath *); + static void prefix_unlink(struct prefix *); + +-int +-prefix_compare(const struct bgpd_addr *a, const struct bgpd_addr *b, +- int prefixlen) +-{ +- in_addr_t mask, aa, ba; +- int i; +- u_int8_t m; +- +- if (a->af != b->af) +- return (a->af - b->af); +- +- switch (a->af) { +- case AF_INET: +- if (prefixlen > 32) +- fatalx("prefix_cmp: bad IPv4 prefixlen"); +- mask = htonl(prefixlen2mask(prefixlen)); +- aa = ntohl(a->v4.s_addr & mask); +- ba = ntohl(b->v4.s_addr & mask); +- if (aa != ba) +- return (aa - ba); +- return (0); +- case AF_INET6: +- if (prefixlen > 128) +- fatalx("prefix_cmp: bad IPv6 prefixlen"); +- for (i = 0; i < prefixlen / 8; i++) +- if (a->v6.s6_addr[i] != b->v6.s6_addr[i]) +- return (a->v6.s6_addr[i] - b->v6.s6_addr[i]); +- i = prefixlen % 8; +- if (i) { +- m = 0xff00 >> i; +- if ((a->v6.s6_addr[prefixlen / 8] & m) != +- (b->v6.s6_addr[prefixlen / 8] & m)) +- return ((a->v6.s6_addr[prefixlen / 8] & m) - +- (b->v6.s6_addr[prefixlen / 8] & m)); +- } +- return (0); +- default: +- fatalx("prefix_cmp: unknown af"); +- } +- return (-1); +-} +- + /* + * search for specified prefix of a peer. Returns NULL if not found. + */ +@@ -806,16 +801,58 @@ prefix_write(u_char *buf, int len, struc + { + int totlen; + +- if (prefix->af != AF_INET && prefix->af != AF_INET6) ++ switch (prefix->aid) { ++ case AID_INET: ++ case AID_INET6: ++ totlen = PREFIX_SIZE(plen); ++ ++ if (totlen > len) ++ return (-1); ++ *buf++ = plen; ++ memcpy(buf, &prefix->ba, totlen - 1); ++ return (totlen); ++ case AID_VPN_IPv4: ++ totlen = PREFIX_SIZE(plen) + sizeof(prefix->vpn4.rd) + ++ prefix->vpn4.labellen; ++ plen += (sizeof(prefix->vpn4.rd) + prefix->vpn4.labellen) * 8; ++ ++ if (totlen > len) ++ return (-1); ++ *buf++ = plen; ++ memcpy(buf, &prefix->vpn4.labelstack, prefix->vpn4.labellen); ++ buf += prefix->vpn4.labellen; ++ memcpy(buf, &prefix->vpn4.rd, sizeof(prefix->vpn4.rd)); ++ buf += sizeof(prefix->vpn4.rd); ++ memcpy(buf, &prefix->vpn4.addr, PREFIX_SIZE(plen) - 1); ++ return (totlen); ++ default: + return (-1); ++ } ++} + +- totlen = PREFIX_SIZE(plen); ++int ++prefix_writebuf(struct ibuf *buf, struct bgpd_addr *prefix, u_int8_t plen) ++{ ++ int totlen; ++ void *bptr; + +- if (totlen > len) ++ switch (prefix->aid) { ++ case AID_INET: ++ case AID_INET6: ++ totlen = PREFIX_SIZE(plen); ++ break; ++ case AID_VPN_IPv4: ++ totlen = PREFIX_SIZE(plen) + sizeof(prefix->vpn4.rd) + ++ prefix->vpn4.labellen; ++ default: + return (-1); +- *buf++ = plen; +- memcpy(buf, &prefix->ba, totlen - 1); +- return (totlen); ++ } ++ ++ if ((bptr = ibuf_reserve(buf, totlen)) == NULL) ++ return (-1); ++ if (prefix_write(bptr, totlen, prefix, plen) == -1) ++ return (-1); ++ return (0); + } + + /* +@@ -861,7 +898,7 @@ prefix_updateall(struct rde_aspath *asp, + */ + if ((p->rib->flags & F_RIB_NOFIB) == 0 && + p == p->rib->active) +- rde_send_kroute(p, NULL); ++ rde_send_kroute(p, NULL, p->rib->ribid); + continue; + } + +@@ -871,7 +908,7 @@ prefix_updateall(struct rde_aspath *asp, + * If the prefix is the active one remove it first, + * this has to be done because we can not detect when + * the active prefix changes its state. In this case +- * we know that this is a withdrawl and so the second ++ * we know that this is a withdrawal and so the second + * prefix_evaluate() will generate no update because + * the nexthop is unreachable or ineligible. + */ +@@ -885,16 +922,12 @@ prefix_updateall(struct rde_aspath *asp, + void + prefix_destroy(struct prefix *p) + { +- struct rib_entry *re; + struct rde_aspath *asp; + +- re = p->rib; + asp = p->aspath; + prefix_unlink(p); + prefix_free(p); + +- if (rib_empty(re)) +- rib_remove(re); + if (path_empty(asp)) + path_destroy(asp); + } +@@ -907,21 +940,16 @@ prefix_network_clean(struct rde_peer *pe + { + struct rde_aspath *asp, *xasp; + struct prefix *p, *xp; +- struct pt_entry *pte; + + for (asp = LIST_FIRST(&peer->path_h); asp != NULL; asp = xasp) { + xasp = LIST_NEXT(asp, peer_l); +- if ((asp->flags & F_ANN_DYNAMIC) == flags) ++ if ((asp->flags & F_ANN_DYNAMIC) != flags) + continue; + for (p = LIST_FIRST(&asp->prefix_h); p != NULL; p = xp) { + xp = LIST_NEXT(p, path_l); + if (reloadtime > p->lastchange) { +- pte = p->prefix; + prefix_unlink(p); + prefix_free(p); +- +- if (pt_empty(pte)) +- pt_remove(pte); + } + } + if (path_empty(asp)) +@@ -954,11 +982,11 @@ prefix_link(struct prefix *pref, struct + static void + prefix_unlink(struct prefix *pref) + { +- if (pref->rib) { +- /* make route decision */ +- LIST_REMOVE(pref, rib_l); +- prefix_evaluate(NULL, pref->rib); +- } ++ struct rib_entry *re = pref->rib; ++ ++ /* make route decision */ ++ LIST_REMOVE(pref, rib_l); ++ prefix_evaluate(NULL, re); + + LIST_REMOVE(pref, path_l); + PREFIX_COUNT(pref->aspath, -1); +@@ -966,6 +994,8 @@ prefix_unlink(struct prefix *pref) + pt_unref(pref->prefix); + if (pt_empty(pref->prefix)) + pt_remove(pref->prefix); ++ if (rib_empty(re)) ++ rib_remove(re); + + /* destroy all references to other objects */ + pref->aspath = NULL; +@@ -973,8 +1003,8 @@ prefix_unlink(struct prefix *pref) + pref->rib = NULL; + + /* +- * It's the caller's duty to remove empty aspath respectively pt_entry +- * structures. Also freeing the unlinked prefix is the caller's duty. ++ * It's the caller's duty to remove empty aspath structures. ++ * Also freeing the unlinked prefix is the caller's duty. + */ + } + +@@ -1070,10 +1100,6 @@ nexthop_update(struct kroute_nexthop *ms + return; + } + +- if (nexthop_delete(nh)) +- /* nexthop no longer used */ +- return; +- + oldstate = nh->state; + if (msg->valid) + nh->state = NEXTHOP_REACH; +@@ -1088,21 +1114,13 @@ nexthop_update(struct kroute_nexthop *ms + memcpy(&nh->true_nexthop, &msg->gateway, + sizeof(nh->true_nexthop)); + +- switch (msg->nexthop.af) { +- case AF_INET: +- nh->nexthop_netlen = msg->kr.kr4.prefixlen; +- nh->nexthop_net.af = AF_INET; +- nh->nexthop_net.v4.s_addr = msg->kr.kr4.prefix.s_addr; +- break; +- case AF_INET6: +- nh->nexthop_netlen = msg->kr.kr6.prefixlen; +- nh->nexthop_net.af = AF_INET6; +- memcpy(&nh->nexthop_net.v6, &msg->kr.kr6.prefix, +- sizeof(struct in6_addr)); +- break; +- default: +- fatalx("nexthop_update: unknown af"); +- } ++ memcpy(&nh->nexthop_net, &msg->net, ++ sizeof(nh->nexthop_net)); ++ nh->nexthop_netlen = msg->netlen; ++ ++ if (nexthop_delete(nh)) ++ /* nexthop no longer used */ ++ return; + + if (rde_noevaluate()) + /* +@@ -1118,35 +1136,38 @@ nexthop_update(struct kroute_nexthop *ms + + void + nexthop_modify(struct rde_aspath *asp, struct bgpd_addr *nexthop, +- enum action_types type, sa_family_t af) ++ enum action_types type, u_int8_t aid) + { + struct nexthop *nh; + +- if (type == ACTION_SET_NEXTHOP_REJECT) { +- asp->flags |= F_NEXTHOP_REJECT; ++ if (type == ACTION_SET_NEXTHOP && aid != nexthop->aid) + return; +- } +- if (type == ACTION_SET_NEXTHOP_BLACKHOLE) { ++ ++ asp->flags &= ~F_NEXTHOP_MASK; ++ switch (type) { ++ case ACTION_SET_NEXTHOP_REJECT: ++ asp->flags |= F_NEXTHOP_REJECT; ++ break; ++ case ACTION_SET_NEXTHOP_BLACKHOLE: + asp->flags |= F_NEXTHOP_BLACKHOLE; +- return; +- } +- if (type == ACTION_SET_NEXTHOP_NOMODIFY) { ++ break; ++ case ACTION_SET_NEXTHOP_NOMODIFY: + asp->flags |= F_NEXTHOP_NOMODIFY; +- return; +- } +- if (type == ACTION_SET_NEXTHOP_SELF) { ++ break; ++ case ACTION_SET_NEXTHOP_SELF: + asp->flags |= F_NEXTHOP_SELF; +- return; ++ break; ++ case ACTION_SET_NEXTHOP: ++ nh = nexthop_get(nexthop); ++ if (asp->flags & F_ATTR_LINKED) ++ nexthop_unlink(asp); ++ asp->nexthop = nh; ++ if (asp->flags & F_ATTR_LINKED) ++ nexthop_link(asp); ++ break; ++ default: ++ break; + } +- if (af != nexthop->af) +- return; +- +- nh = nexthop_get(nexthop); +- if (asp->flags & F_ATTR_LINKED) +- nexthop_unlink(asp); +- asp->nexthop = nh; +- if (asp->flags & F_ATTR_LINKED) +- nexthop_link(asp); + } + + void +@@ -1233,17 +1254,17 @@ nexthop_compare(struct nexthop *na, stru + a = &na->exit_nexthop; + b = &nb->exit_nexthop; + +- if (a->af != b->af) +- return (a->af - b->af); ++ if (a->aid != b->aid) ++ return (a->aid - b->aid); + +- switch (a->af) { +- case AF_INET: ++ switch (a->aid) { ++ case AID_INET: + if (ntohl(a->v4.s_addr) > ntohl(b->v4.s_addr)) + return (1); + if (ntohl(a->v4.s_addr) < ntohl(b->v4.s_addr)) + return (-1); + return (0); +- case AF_INET6: ++ case AID_INET6: + return (memcmp(&a->v6, &b->v6, sizeof(struct in6_addr))); + default: + fatalx("nexthop_cmp: unknown af"); +@@ -1269,14 +1290,14 @@ nexthop_hash(struct bgpd_addr *nexthop) + { + u_int32_t h = 0; + +- switch (nexthop->af) { +- case AF_INET: ++ switch (nexthop->aid) { ++ case AID_INET: + h = (AF_INET ^ ntohl(nexthop->v4.s_addr) ^ + ntohl(nexthop->v4.s_addr) >> 13) & + nexthoptable.nexthop_hashmask; + break; +- case AF_INET6: +- h = hash32_buf(nexthop->v6.s6_addr, sizeof(struct in6_addr), ++ case AID_INET6: ++ h = hash32_buf(&nexthop->v6, sizeof(struct in6_addr), + HASHINIT) & nexthoptable.nexthop_hashmask; + break; + default: |