diff --git a/NEWS b/NEWS index 9669392d..6281c8a3 100644 --- a/NEWS +++ b/NEWS @@ -14,6 +14,13 @@ Version 2.0.0-pre0 (2016-12-07) doc/bird.conf.example2 for configuration examples. +Version 1.6.3 (2016-12-21) + o Large BGP communities + o BFD authentication (MD5, SHA1) + o SHA1 and SHA2 authentication for RIP and OSPF + o Improved documentation + o Several bug fixes + Version 1.6.2 (2016-09-29) o Fixes serious bug introduced in the previous version diff --git a/filter/filter.c b/filter/filter.c index 4ec04554..a6ef1e10 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -1579,6 +1579,7 @@ i_same(struct f_inst *f1, struct f_inst *f2) case P('<','='): TWOARGS; break; case '!': ONEARG; break; + case P('!', '~'): case '~': TWOARGS; break; case P('d','e'): ONEARG; break; diff --git a/lib/hash.h b/lib/hash.h index b37d8fa5..97d8f69c 100644 --- a/lib/hash.h +++ b/lib/hash.h @@ -25,6 +25,12 @@ (v).data = mb_allocz(pool, HASH_SIZE(v) * sizeof(* (v).data)); \ }) +#define HASH_FREE(v) \ + ({ \ + mb_free((v).data); \ + (v) = (typeof(v)){ }; \ + }) + #define HASH_FIND(v,id,key...) \ ({ \ u32 _h = HASH_FN(v, id, key); \ diff --git a/nest/a-set.c b/nest/a-set.c index 82bf8b0d..a2fb6953 100644 --- a/nest/a-set.c +++ b/nest/a-set.c @@ -233,6 +233,26 @@ lc_set_contains(struct adata *list, lcomm val) return 0; } +struct adata * +int_set_prepend(struct linpool *pool, struct adata *list, u32 val) +{ + struct adata *res; + int len; + + if (int_set_contains(list, val)) + return list; + + len = list ? list->length : 0; + res = lp_alloc(pool, sizeof(struct adata) + len + 4); + res->length = len + 4; + + if (list) + memcpy(res->data + 4, list->data, list->length); + + * (u32 *) res->data = val; + + return res; +} struct adata * int_set_add(struct linpool *pool, struct adata *list, u32 val) @@ -250,8 +270,7 @@ int_set_add(struct linpool *pool, struct adata *list, u32 val) if (list) memcpy(res->data, list->data, list->length); - u32 *c = (u32 *) (res->data + len); - *c = val; + * (u32 *) (res->data + len) = val; return res; } diff --git a/nest/attrs.h b/nest/attrs.h index 84403cf3..f66d4f04 100644 --- a/nest/attrs.h +++ b/nest/attrs.h @@ -181,6 +181,7 @@ int lc_set_format(struct adata *set, int from, byte *buf, uint size); int int_set_contains(struct adata *list, u32 val); int ec_set_contains(struct adata *list, u64 val); int lc_set_contains(struct adata *list, lcomm val); +struct adata *int_set_prepend(struct linpool *pool, struct adata *list, u32 val); struct adata *int_set_add(struct linpool *pool, struct adata *list, u32 val); struct adata *ec_set_add(struct linpool *pool, struct adata *list, u64 val); struct adata *lc_set_add(struct linpool *pool, struct adata *list, lcomm val); diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c index d5bf2add..73318c6a 100644 --- a/proto/bgp/attrs.c +++ b/proto/bgp/attrs.c @@ -1224,6 +1224,15 @@ bgp_init_prefix_table(struct bgp_channel *c) c->prefix_slab = alen ? sl_new(c->pool, sizeof(struct bgp_prefix) + alen) : NULL; } +void +bgp_free_prefix_table(struct bgp_channel *c) +{ + HASH_FREE(c->prefix_hash); + + rfree(c->prefix_slab); + c->prefix_slab = NULL; +} + static struct bgp_prefix * bgp_get_prefix(struct bgp_channel *c, net_addr *net, u32 path_id) { @@ -1323,6 +1332,7 @@ bgp_import_control(struct proto *P, rte **new, ea_list **attrs UNUSED, struct li return 0; } + static adata null_adata; /* adata of length 0 */ static ea_list * @@ -1394,11 +1404,11 @@ bgp_update_attrs(struct bgp_proto *p, struct bgp_channel *c, rte *e, ea_list *at /* Prepend src cluster ID */ if (src->rr_cluster_id) - ad = int_set_add(pool, ad, src->rr_cluster_id); + ad = int_set_prepend(pool, ad, src->rr_cluster_id); /* Prepend dst cluster ID if src and dst clusters are different */ if (p->rr_cluster_id && (src->rr_cluster_id != p->rr_cluster_id)) - ad = int_set_add(pool, ad, p->rr_cluster_id); + ad = int_set_prepend(pool, ad, p->rr_cluster_id); /* Should be at least one prepended cluster ID */ bgp_set_attr_ptr(&attrs, pool, BA_CLUSTER_LIST, 0, ad); diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c index 61d24f42..5e95e6b4 100644 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@ -559,6 +559,10 @@ bgp_conn_leave_established_state(struct bgp_proto *p) BGP_TRACE(D_EVENTS, "BGP session closed"); p->conn = NULL; + // XXXX free these tables to avoid memory leak during graceful restart + // bgp_free_prefix_table(p); + // bgp_free_bucket_table(p); + if (p->p.proto_state == PS_UP) bgp_stop(p, 0); } diff --git a/proto/ospf/rt.c b/proto/ospf/rt.c index 054841ca..49167ceb 100644 --- a/proto/ospf/rt.c +++ b/proto/ospf/rt.c @@ -422,10 +422,9 @@ add_network(struct ospf_area *oa, net_addr *net, int metric, struct top_hash_ent if (en == oa->rt) { /* - * Local stub networks does not have proper iface in en->nhi - * (because they all have common top_hash_entry en). - * We have to find iface responsible for that stub network. - * Configured stubnets does not have any iface. They will + * Local stub networks do not have proper iface in en->nhi (because they all + * have common top_hash_entry en). We have to find iface responsible for + * that stub network. Configured stubnets do not have any iface. They will * be removed in rt_sync(). */ @@ -1429,7 +1428,6 @@ ospf_ext_spf(struct ospf_proto *p) struct top_hash_entry *en; struct ospf_lsa_ext_local rt; ort *nf1, *nf2; - orta nfa = {}; u32 br_metric; struct ospf_area *atmp; @@ -1437,6 +1435,8 @@ ospf_ext_spf(struct ospf_proto *p) WALK_SLIST(en, p->lsal) { + orta nfa = {}; + /* 16.4. (1) */ if ((en->lsa_type != LSA_T_EXT) && (en->lsa_type != LSA_T_NSSA)) continue; @@ -1578,6 +1578,7 @@ ospf_rt_reset(struct ospf_proto *p) FIB_WALK(&p->rtf, ort, ri) { ri->area_net = 0; + ri->keep = 0; reset_ri(ri); } FIB_WALK_END; @@ -1941,9 +1942,12 @@ again1: } } - /* Remove configured stubnets */ - if (!nf->n.nhs) + /* Remove configured stubnets but keep the entries */ + if (nf->n.type && !nf->n.nhs) + { reset_ri(nf); + nf->keep = 1; + } if (nf->n.type) /* Add the route */ { @@ -1999,7 +2003,7 @@ again1: } /* Remove unused rt entry, some special entries are persistent */ - if (!nf->n.type && !nf->external_rte && !nf->area_net) + if (!nf->n.type && !nf->external_rte && !nf->area_net && !nf->keep) { if (nf->lsa_id) idm_free(&p->idm, nf->lsa_id); diff --git a/proto/ospf/rt.h b/proto/ospf/rt.h index 959d12e9..118d09b7 100644 --- a/proto/ospf/rt.h +++ b/proto/ospf/rt.h @@ -84,6 +84,7 @@ typedef struct ort u32 lsa_id; u8 external_rte; u8 area_net; + u8 keep; struct fib_node fn; } diff --git a/sysdep/bsd/sysio.h b/sysdep/bsd/sysio.h index 0c5f8fbb..0e895e20 100644 --- a/sysdep/bsd/sysio.h +++ b/sysdep/bsd/sysio.h @@ -9,6 +9,7 @@ #include #include // Workaround for some BSDs #include +#include #ifdef __NetBSD__ @@ -179,8 +180,8 @@ sk_prepare_ip_header(sock *s, void *hdr, int dlen) ip->ip_src = ipa_to_in4(s->saddr); ip->ip_dst = ipa_to_in4(s->daddr); -#ifdef __OpenBSD__ - /* OpenBSD expects ip_len in network order, other BSDs expect host order */ +#if (defined __OpenBSD__) || (defined __DragonFly__) || (defined __FreeBSD__ && (__FreeBSD_version >= 1100030)) + /* Different BSDs have different expectations of ip_len endianity */ ip->ip_len = htons(ip->ip_len); #endif } diff --git a/sysdep/linux/netlink.c b/sysdep/linux/netlink.c index ee2cd125..554f2c97 100644 --- a/sysdep/linux/netlink.c +++ b/sysdep/linux/netlink.c @@ -1608,6 +1608,7 @@ nl_async_hook(sock *sk, uint size UNUSED) * One day we might react to it by asking for route table * scan in near future. */ + log(L_WARN "Kernel dropped some netlink messages, will resync on next scan."); return 1; /* More data are likely to be ready */ } else if (errno != EWOULDBLOCK) diff --git a/sysdep/unix/io.c b/sysdep/unix/io.c index c8916378..6722fc69 100644 --- a/sysdep/unix/io.c +++ b/sysdep/unix/io.c @@ -2631,7 +2631,8 @@ io_loop(void) if (pfd[s->index].revents & (POLLHUP | POLLERR)) { sk_err(s, pfd[s->index].revents); - goto next2; + if (s != current_sock) + goto next2; } current_sock = sk_next(s);