From e46128fb50e108e8cfdf6bb6e9ab040e00f5dfdc Mon Sep 17 00:00:00 2001 From: "Ondrej Zajicek (work)" Date: Mon, 19 Jun 2017 12:46:40 +0200 Subject: [PATCH 001/198] Filters: Do not clamp EC set values to 16 bit for EC_GENERICs Thanks to Lennert Buytenhek for the patch. --- filter/config.Y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/filter/config.Y b/filter/config.Y index 5ea83f81..c9f9c753 100644 --- a/filter/config.Y +++ b/filter/config.Y @@ -112,7 +112,7 @@ f_new_ec_item(u32 kind, u32 ipv4_used, u32 key, u32 vf, u32 vt) { u64 fm, to; - if (ipv4_used || (key >= 0x10000)) { + if ((kind != EC_GENERIC) && (ipv4_used || (key >= 0x10000))) { check_u16(vf); if (vt == EC_ALL) vt = 0xFFFF; From b4a33e21ea3a8d23dee3ed23a515cc7430a38643 Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Tue, 18 Jul 2017 23:48:25 +0200 Subject: [PATCH 002/198] Configure: Fix a typo in checking of backtrace() --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 9e375762..5514fb56 100644 --- a/configure.ac +++ b/configure.ac @@ -314,7 +314,7 @@ if test "$enable_debug" = yes ; then [ AC_DEFINE([HAVE_EXECINFO_H], [1], [Define to 1 if you have the header file.]) AC_SEARCH_LIBS([backtrace], [execinfo], - [] + [], [AC_MSG_ERROR([Function backtrace not available.])] ) ] From afd9845e2636146a66508639614a93167d5d1728 Mon Sep 17 00:00:00 2001 From: Michal 'vorner' Vaner Date: Fri, 4 Aug 2017 10:52:57 +0200 Subject: [PATCH 003/198] radv: Fix RFC reference in comments --- proto/radv/radv.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/proto/radv/radv.h b/proto/radv/radv.h index 735aa218..3e6c1651 100644 --- a/proto/radv/radv.h +++ b/proto/radv/radv.h @@ -60,14 +60,14 @@ struct radv_iface_config list rdnss_list; /* Local list of RDNSS configs (struct radv_rdnss_config) */ list dnssl_list; /* Local list of DNSSL configs (struct radv_dnssl_config) */ - u32 min_ra_int; /* Standard options from RFC 4261 */ + u32 min_ra_int; /* Standard options from RFC 4861 */ u32 max_ra_int; u32 min_delay; u8 rdnss_local; /* Global list is not used for RDNSS */ u8 dnssl_local; /* Global list is not used for DNSSL */ - u8 managed; /* Standard options from RFC 4261 */ + u8 managed; /* Standard options from RFC 4861 */ u8 other_config; u32 link_mtu; u32 reachable_time; @@ -84,7 +84,7 @@ struct radv_prefix_config net_addr_ip6 prefix; u8 skip; /* Do not include this prefix to RA */ - u8 onlink; /* Standard options from RFC 4261 */ + u8 onlink; /* Standard options from RFC 4861 */ u8 autonomous; u32 valid_lifetime; u32 preferred_lifetime; From 637ed49868c56c0e05467f0e0ddb6aa1231deaa4 Mon Sep 17 00:00:00 2001 From: Michal 'vorner' Vaner Date: Fri, 4 Aug 2017 10:52:57 +0200 Subject: [PATCH 004/198] radv: Fix RFC reference in comments --- proto/radv/radv.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/proto/radv/radv.h b/proto/radv/radv.h index e2bf07ba..0591486b 100644 --- a/proto/radv/radv.h +++ b/proto/radv/radv.h @@ -62,14 +62,14 @@ struct radv_iface_config list rdnss_list; /* Local list of RDNSS configs (struct radv_rdnss_config) */ list dnssl_list; /* Local list of DNSSL configs (struct radv_dnssl_config) */ - u32 min_ra_int; /* Standard options from RFC 4261 */ + u32 min_ra_int; /* Standard options from RFC 4861 */ u32 max_ra_int; u32 min_delay; u8 rdnss_local; /* Global list is not used for RDNSS */ u8 dnssl_local; /* Global list is not used for DNSSL */ - u8 managed; /* Standard options from RFC 4261 */ + u8 managed; /* Standard options from RFC 4861 */ u8 other_config; u32 link_mtu; u32 reachable_time; @@ -87,7 +87,7 @@ struct radv_prefix_config uint pxlen; u8 skip; /* Do not include this prefix to RA */ - u8 onlink; /* Standard options from RFC 4261 */ + u8 onlink; /* Standard options from RFC 4861 */ u8 autonomous; u32 valid_lifetime; u32 preferred_lifetime; From 5a41eed26d1b12861ba0ecddcd7cade335d2a192 Mon Sep 17 00:00:00 2001 From: Michal 'vorner' Vaner Date: Tue, 8 Aug 2017 14:40:51 +0200 Subject: [PATCH 005/198] RAdv: Style updates Adapt the naming conventions to be a bit closer to the other protocols. proto_radv -> radv_proto struct radv_proto *ra -> struct radv_proto *p struct proto *p -> struct proto *P --- proto/radv/packets.c | 22 ++++---- proto/radv/radv.c | 126 +++++++++++++++++++++---------------------- proto/radv/radv.h | 8 +-- 3 files changed, 78 insertions(+), 78 deletions(-) diff --git a/proto/radv/packets.c b/proto/radv/packets.c index f4352155..15ca5738 100644 --- a/proto/radv/packets.c +++ b/proto/radv/packets.c @@ -82,8 +82,8 @@ static struct radv_prefix_config default_prefix = { static struct radv_prefix_config * radv_prefix_match(struct radv_iface *ifa, struct ifa *a) { - struct proto *p = &ifa->ra->p; - struct radv_config *cf = (struct radv_config *) (p->cf); + struct radv_proto *p = ifa->ra; + struct radv_config *cf = (struct radv_config *) (p->p.cf); struct radv_prefix_config *pc; if (a->scope <= SCOPE_LINK) @@ -206,7 +206,7 @@ radv_prepare_dnssl(struct radv_iface *ifa, list *dnssl_list, char **buf, char *b else op->lifetime = htonl(dcf->lifetime); - while(NODE_VALID(dcf) && + while(NODE_VALID(dcf) && (dcf->lifetime == dcf_base->lifetime) && (dcf->lifetime_mult == dcf_base->lifetime_mult)) { @@ -237,8 +237,8 @@ radv_prepare_dnssl(struct radv_iface *ifa, list *dnssl_list, char **buf, char *b static void radv_prepare_ra(struct radv_iface *ifa) { - struct proto_radv *ra = ifa->ra; - struct radv_config *cf = (struct radv_config *) (ra->p.cf); + struct radv_proto *p = ifa->ra; + struct radv_config *cf = (struct radv_config *) (p->p.cf); struct radv_iface_config *ic = ifa->cf; char *buf = ifa->sk->tbuf; @@ -250,7 +250,7 @@ radv_prepare_ra(struct radv_iface *ifa) pkt->code = 0; pkt->checksum = 0; pkt->current_hop_limit = ic->current_hop_limit; - pkt->router_lifetime = (ra->active || !ic->default_lifetime_sensitive) ? + pkt->router_lifetime = (p->active || !ic->default_lifetime_sensitive) ? htons(ic->default_lifetime) : 0; pkt->flags = (ic->managed ? OPT_RA_MANAGED : 0) | (ic->other_config ? OPT_RA_OTHER_CFG : 0) | @@ -283,7 +283,7 @@ radv_prepare_ra(struct radv_iface *ifa) if (buf + sizeof(struct radv_opt_prefix) > bufend) { - log(L_WARN "%s: Too many prefixes on interface %s", ra->p.name, ifa->iface->name); + log(L_WARN "%s: Too many prefixes on interface %s", p->p.name, ifa->iface->name); goto done; } @@ -293,9 +293,9 @@ radv_prepare_ra(struct radv_iface *ifa) op->pxlen = net6_pxlen(&addr->prefix); op->flags = (pc->onlink ? OPT_PX_ONLINK : 0) | (pc->autonomous ? OPT_PX_AUTONOMOUS : 0); - op->valid_lifetime = (ra->active || !pc->valid_lifetime_sensitive) ? + op->valid_lifetime = (p->active || !pc->valid_lifetime_sensitive) ? htonl(pc->valid_lifetime) : 0; - op->preferred_lifetime = (ra->active || !pc->preferred_lifetime_sensitive) ? + op->preferred_lifetime = (p->active || !pc->preferred_lifetime_sensitive) ? htonl(pc->preferred_lifetime) : 0; op->reserved = 0; op->prefix = ip6_hton(net6_prefix(&addr->prefix)); @@ -324,7 +324,7 @@ radv_prepare_ra(struct radv_iface *ifa) void radv_send_ra(struct radv_iface *ifa, int shutdown) { - struct proto_radv *ra = ifa->ra; + struct radv_proto *p = ifa->ra; /* We store prepared RA in tbuf */ if (!ifa->plen) @@ -352,7 +352,7 @@ static int radv_rx_hook(sock *sk, uint size) { struct radv_iface *ifa = sk->data; - struct proto_radv *ra = ifa->ra; + struct radv_proto *p = ifa->ra; /* We want just packets from sk->iface */ if (sk->lifindex != sk->iface->index) diff --git a/proto/radv/radv.c b/proto/radv/radv.c index d7d975ab..4a6593b8 100644 --- a/proto/radv/radv.c +++ b/proto/radv/radv.c @@ -47,7 +47,7 @@ static void radv_timer(timer *tm) { struct radv_iface *ifa = tm->data; - struct proto_radv *ra = ifa->ra; + struct radv_proto *p = ifa->ra; RADV_TRACE(D_EVENTS, "Timer fired on %s", ifa->iface->name); @@ -72,7 +72,7 @@ static char* ev_name[] = { NULL, "Init", "Change", "RS" }; void radv_iface_notify(struct radv_iface *ifa, int event) { - struct proto_radv *ra = ifa->ra; + struct radv_proto *p = ifa->ra; if (!ifa->sk) return; @@ -102,21 +102,21 @@ radv_iface_notify(struct radv_iface *ifa, int event) } static void -radv_iface_notify_all(struct proto_radv *ra, int event) +radv_iface_notify_all(struct radv_proto *p, int event) { struct radv_iface *ifa; - WALK_LIST(ifa, ra->iface_list) + WALK_LIST(ifa, p->iface_list) radv_iface_notify(ifa, event); } static struct radv_iface * -radv_iface_find(struct proto_radv *ra, struct iface *what) +radv_iface_find(struct radv_proto *p, struct iface *what) { struct radv_iface *ifa; - WALK_LIST(ifa, ra->iface_list) + WALK_LIST(ifa, p->iface_list) if (ifa->iface == what) return ifa; @@ -127,11 +127,11 @@ static void radv_iface_add(struct object_lock *lock) { struct radv_iface *ifa = lock->data; - struct proto_radv *ra = ifa->ra; + struct radv_proto *p = ifa->ra; if (! radv_sk_open(ifa)) { - log(L_ERR "%s: Socket open failed on interface %s", ra->p.name, ifa->iface->name); + log(L_ERR "%s: Socket open failed on interface %s", p->p.name, ifa->iface->name); return; } @@ -150,24 +150,24 @@ find_lladdr(struct iface *iface) } static void -radv_iface_new(struct proto_radv *ra, struct iface *iface, struct radv_iface_config *cf) +radv_iface_new(struct radv_proto *p, struct iface *iface, struct radv_iface_config *cf) { - pool *pool = ra->p.pool; + pool *pool = p->p.pool; struct radv_iface *ifa; RADV_TRACE(D_EVENTS, "Adding interface %s", iface->name); ifa = mb_allocz(pool, sizeof(struct radv_iface)); - ifa->ra = ra; + ifa->ra = p; ifa->cf = cf; ifa->iface = iface; - add_tail(&ra->iface_list, NODE ifa); + add_tail(&p->iface_list, NODE ifa); ifa->addr = find_lladdr(iface); if (!ifa->addr) { - log(L_ERR "%s: Cannot find link-locad addr on interface %s", ra->p.name, iface->name); + log(L_ERR "%s: Cannot find link-locad addr on interface %s", p->p.name, iface->name); return; } @@ -193,7 +193,7 @@ radv_iface_new(struct proto_radv *ra, struct iface *iface, struct radv_iface_con static void radv_iface_remove(struct radv_iface *ifa) { - struct proto_radv *ra = ifa->ra; + struct radv_proto *p = ifa->ra; RADV_TRACE(D_EVENTS, "Removing interface %s", ifa->iface->name); rem_node(NODE ifa); @@ -206,10 +206,10 @@ radv_iface_remove(struct radv_iface *ifa) } static void -radv_if_notify(struct proto *p, unsigned flags, struct iface *iface) +radv_if_notify(struct proto *P, unsigned flags, struct iface *iface) { - struct proto_radv *ra = (struct proto_radv *) p; - struct radv_config *cf = (struct radv_config *) (p->cf); + struct radv_proto *p = (struct radv_proto *) P; + struct radv_config *cf = (struct radv_config *) (P->cf); if (iface->flags & IF_IGNORE) return; @@ -220,12 +220,12 @@ radv_if_notify(struct proto *p, unsigned flags, struct iface *iface) iface_patt_find(&cf->patt_list, iface, NULL); if (ic) - radv_iface_new(ra, iface, ic); + radv_iface_new(p, iface, ic); return; } - struct radv_iface *ifa = radv_iface_find(ra, iface); + struct radv_iface *ifa = radv_iface_find(p, iface); if (!ifa) return; @@ -240,9 +240,9 @@ radv_if_notify(struct proto *p, unsigned flags, struct iface *iface) } static void -radv_ifa_notify(struct proto *p, unsigned flags UNUSED, struct ifa *a) +radv_ifa_notify(struct proto *P, unsigned flags UNUSED, struct ifa *a) { - struct proto_radv *ra = (struct proto_radv *) p; + struct radv_proto *p = (struct radv_proto *) P; if (a->flags & IA_SECONDARY) return; @@ -250,7 +250,7 @@ radv_ifa_notify(struct proto *p, unsigned flags UNUSED, struct ifa *a) if (a->scope <= SCOPE_LINK) return; - struct radv_iface *ifa = radv_iface_find(ra, a->iface); + struct radv_iface *ifa = radv_iface_find(p, a->iface); if (ifa) radv_iface_notify(ifa, RA_EV_CHANGE); @@ -269,10 +269,10 @@ radv_net_match_trigger(struct radv_config *cf, net *n) } int -radv_import_control(struct proto *p, rte **new, ea_list **attrs UNUSED, struct linpool *pool UNUSED) +radv_import_control(struct proto *P, rte **new, ea_list **attrs UNUSED, struct linpool *pool UNUSED) { - // struct proto_radv *ra = (struct proto_radv *) p; - struct radv_config *cf = (struct radv_config *) (p->cf); + // struct radv_proto *p = (struct radv_proto *) P; + struct radv_config *cf = (struct radv_config *) (P->cf); if (radv_net_match_trigger(cf, (*new)->net)) return RIC_PROCESS; @@ -281,38 +281,38 @@ radv_import_control(struct proto *p, rte **new, ea_list **attrs UNUSED, struct l } static void -radv_rt_notify(struct proto *p, struct channel *ch UNUSED, net *n, rte *new, rte *old UNUSED, ea_list *attrs UNUSED) +radv_rt_notify(struct proto *P, struct channel *ch UNUSED, net *n, rte *new, rte *old UNUSED, ea_list *attrs UNUSED) { - struct proto_radv *ra = (struct proto_radv *) p; - struct radv_config *cf = (struct radv_config *) (p->cf); + struct radv_proto *p = (struct radv_proto *) P; + struct radv_config *cf = (struct radv_config *) (P->cf); if (radv_net_match_trigger(cf, n)) { - u8 old_active = ra->active; - ra->active = !!new; + u8 old_active = p->active; + p->active = !!new; - if (ra->active == old_active) + if (p->active == old_active) return; - if (ra->active) + if (p->active) RADV_TRACE(D_EVENTS, "Triggered"); else RADV_TRACE(D_EVENTS, "Suppressed"); - radv_iface_notify_all(ra, RA_EV_CHANGE); + radv_iface_notify_all(p, RA_EV_CHANGE); } } static int -radv_check_active(struct proto_radv *ra) +radv_check_active(struct radv_proto *p) { - struct radv_config *cf = (struct radv_config *) (ra->p.cf); + struct radv_config *cf = (struct radv_config *) (p->p.cf); if (!radv_trigger_valid(cf)) return 1; - struct channel *c = ra->p.main_channel; - return rt_examine(c->table, &cf->trigger, &ra->p, c->out_filter); + struct channel *c = p->p.main_channel; + return rt_examine(c->table, &cf->trigger, &p->p, c->out_filter); } static void @@ -328,26 +328,26 @@ radv_postconfig(struct proto_config *CF) static struct proto * radv_init(struct proto_config *CF) { - struct proto *p = proto_new(CF); + struct proto *P = proto_new(CF); - p->main_channel = proto_add_channel(p, proto_cf_main_channel(CF)); + P->main_channel = proto_add_channel(P, proto_cf_main_channel(CF)); - p->import_control = radv_import_control; - p->rt_notify = radv_rt_notify; - p->if_notify = radv_if_notify; - p->ifa_notify = radv_ifa_notify; + P->import_control = radv_import_control; + P->rt_notify = radv_rt_notify; + P->if_notify = radv_if_notify; + P->ifa_notify = radv_ifa_notify; - return p; + return P; } static int -radv_start(struct proto *p) +radv_start(struct proto *P) { - struct proto_radv *ra = (struct proto_radv *) p; - struct radv_config *cf = (struct radv_config *) (p->cf); + struct radv_proto *p = (struct radv_proto *) P; + struct radv_config *cf = (struct radv_config *) (P->cf); - init_list(&(ra->iface_list)); - ra->active = !radv_trigger_valid(cf); + init_list(&(p->iface_list)); + p->active = !radv_trigger_valid(cf); return PS_UP; } @@ -360,21 +360,21 @@ radv_iface_shutdown(struct radv_iface *ifa) } static int -radv_shutdown(struct proto *p) +radv_shutdown(struct proto *P) { - struct proto_radv *ra = (struct proto_radv *) p; + struct radv_proto *p = (struct radv_proto *) P; struct radv_iface *ifa; - WALK_LIST(ifa, ra->iface_list) + WALK_LIST(ifa, p->iface_list) radv_iface_shutdown(ifa); return PS_DOWN; } static int -radv_reconfigure(struct proto *p, struct proto_config *CF) +radv_reconfigure(struct proto *P, struct proto_config *CF) { - struct proto_radv *ra = (struct proto_radv *) p; + struct radv_proto *p = (struct radv_proto *) P; // struct radv_config *old = (struct radv_config *) (p->cf); struct radv_config *new = (struct radv_config *) CF; @@ -386,16 +386,16 @@ radv_reconfigure(struct proto *p, struct proto_config *CF) * causing nodes to temporary remove their default routes. */ - if (!proto_configure_channel(p, &p->main_channel, proto_cf_main_channel(CF))) + if (!proto_configure_channel(P, &P->main_channel, proto_cf_main_channel(CF))) return 0; - p->cf = CF; /* radv_check_active() requires proper p->cf */ - ra->active = radv_check_active(ra); + P->cf = CF; /* radv_check_active() requires proper p->cf */ + p->active = radv_check_active(p); struct iface *iface; WALK_LIST(iface, iface_list) { - struct radv_iface *ifa = radv_iface_find(ra, iface); + struct radv_iface *ifa = radv_iface_find(p, iface); struct radv_iface_config *ic = (struct radv_iface_config *) iface_patt_find(&new->patt_list, iface, NULL); @@ -415,7 +415,7 @@ radv_reconfigure(struct proto *p, struct proto_config *CF) } if (!ifa && ic) - radv_iface_new(ra, iface, ic); + radv_iface_new(p, iface, ic); } return 1; @@ -435,11 +435,11 @@ radv_copy_config(struct proto_config *dest, struct proto_config *src) } static void -radv_get_status(struct proto *p, byte *buf) +radv_get_status(struct proto *P, byte *buf) { - struct proto_radv *ra = (struct proto_radv *) p; + struct radv_proto *p = (struct radv_proto *) P; - if (!ra->active) + if (!p->active) strcpy(buf, "Suppressed"); } @@ -447,7 +447,7 @@ struct protocol proto_radv = { .name = "RAdv", .template = "radv%d", .channel_mask = NB_IP6, - .proto_size = sizeof(struct proto_radv), + .proto_size = sizeof(struct radv_proto), .config_size = sizeof(struct radv_config), .postconfig = radv_postconfig, .init = radv_init, diff --git a/proto/radv/radv.h b/proto/radv/radv.h index 3e6c1651..35eea9ba 100644 --- a/proto/radv/radv.h +++ b/proto/radv/radv.h @@ -111,7 +111,7 @@ struct radv_dnssl_config }; -struct proto_radv +struct radv_proto { struct proto p; list iface_list; /* List of active ifaces */ @@ -121,7 +121,7 @@ struct proto_radv struct radv_iface { node n; - struct proto_radv *ra; + struct radv_proto *ra; struct radv_iface_config *cf; /* Related config, must be updated in reconfigure */ struct iface *iface; struct ifa *addr; /* Link-local address of iface */ @@ -151,8 +151,8 @@ struct radv_iface #else #define RADV_FORCE_DEBUG 0 #endif -#define RADV_TRACE(flags, msg, args...) do { if ((ra->p.debug & flags) || RADV_FORCE_DEBUG) \ - log(L_TRACE "%s: " msg, ra->p.name , ## args ); } while(0) +#define RADV_TRACE(flags, msg, args...) do { if ((p->p.debug & flags) || RADV_FORCE_DEBUG) \ + log(L_TRACE "%s: " msg, p->p.name , ## args ); } while(0) /* radv.c */ From 1f182675c816e4708312f99dd817fb894f3a90b3 Mon Sep 17 00:00:00 2001 From: Michal 'vorner' Vaner Date: Tue, 8 Aug 2017 14:40:51 +0200 Subject: [PATCH 006/198] RAdv: Style updates Adapt the naming conventions to be a bit closer to the other protocols. proto_radv -> radv_proto struct radv_proto *ra -> struct radv_proto *p struct proto *p -> struct proto *P --- proto/radv/packets.c | 22 ++++---- proto/radv/radv.c | 123 ++++++++++++++++++++++--------------------- proto/radv/radv.h | 8 +-- 3 files changed, 77 insertions(+), 76 deletions(-) diff --git a/proto/radv/packets.c b/proto/radv/packets.c index 4bf960c3..1c9837a4 100644 --- a/proto/radv/packets.c +++ b/proto/radv/packets.c @@ -82,8 +82,8 @@ static struct radv_prefix_config default_prefix = { static struct radv_prefix_config * radv_prefix_match(struct radv_iface *ifa, struct ifa *a) { - struct proto *p = &ifa->ra->p; - struct radv_config *cf = (struct radv_config *) (p->cf); + struct radv_proto *p = ifa->ra; + struct radv_config *cf = (struct radv_config *) (p->p.cf); struct radv_prefix_config *pc; if (a->scope <= SCOPE_LINK) @@ -207,7 +207,7 @@ radv_prepare_dnssl(struct radv_iface *ifa, list *dnssl_list, char **buf, char *b else op->lifetime = htonl(dcf->lifetime); - while(NODE_VALID(dcf) && + while(NODE_VALID(dcf) && (dcf->lifetime == dcf_base->lifetime) && (dcf->lifetime_mult == dcf_base->lifetime_mult)) { @@ -238,8 +238,8 @@ radv_prepare_dnssl(struct radv_iface *ifa, list *dnssl_list, char **buf, char *b static void radv_prepare_ra(struct radv_iface *ifa) { - struct proto_radv *ra = ifa->ra; - struct radv_config *cf = (struct radv_config *) (ra->p.cf); + struct radv_proto *p = ifa->ra; + struct radv_config *cf = (struct radv_config *) (p->p.cf); struct radv_iface_config *ic = ifa->cf; char *buf = ifa->sk->tbuf; @@ -251,7 +251,7 @@ radv_prepare_ra(struct radv_iface *ifa) pkt->code = 0; pkt->checksum = 0; pkt->current_hop_limit = ic->current_hop_limit; - pkt->router_lifetime = (ra->active || !ic->default_lifetime_sensitive) ? + pkt->router_lifetime = (p->active || !ic->default_lifetime_sensitive) ? htons(ic->default_lifetime) : 0; pkt->flags = (ic->managed ? OPT_RA_MANAGED : 0) | (ic->other_config ? OPT_RA_OTHER_CFG : 0) | @@ -281,7 +281,7 @@ radv_prepare_ra(struct radv_iface *ifa) if (buf + sizeof(struct radv_opt_prefix) > bufend) { - log(L_WARN "%s: Too many prefixes on interface %s", ra->p.name, ifa->iface->name); + log(L_WARN "%s: Too many prefixes on interface %s", p->p.name, ifa->iface->name); goto done; } @@ -291,9 +291,9 @@ radv_prepare_ra(struct radv_iface *ifa) op->pxlen = addr->pxlen; op->flags = (pc->onlink ? OPT_PX_ONLINK : 0) | (pc->autonomous ? OPT_PX_AUTONOMOUS : 0); - op->valid_lifetime = (ra->active || !pc->valid_lifetime_sensitive) ? + op->valid_lifetime = (p->active || !pc->valid_lifetime_sensitive) ? htonl(pc->valid_lifetime) : 0; - op->preferred_lifetime = (ra->active || !pc->preferred_lifetime_sensitive) ? + op->preferred_lifetime = (p->active || !pc->preferred_lifetime_sensitive) ? htonl(pc->preferred_lifetime) : 0; op->reserved = 0; op->prefix = addr->prefix; @@ -323,7 +323,7 @@ radv_prepare_ra(struct radv_iface *ifa) void radv_send_ra(struct radv_iface *ifa, int shutdown) { - struct proto_radv *ra = ifa->ra; + struct radv_proto *p = ifa->ra; /* We store prepared RA in tbuf */ if (!ifa->plen) @@ -351,7 +351,7 @@ static int radv_rx_hook(sock *sk, uint size) { struct radv_iface *ifa = sk->data; - struct proto_radv *ra = ifa->ra; + struct radv_proto *p = ifa->ra; /* We want just packets from sk->iface */ if (sk->lifindex != sk->iface->index) diff --git a/proto/radv/radv.c b/proto/radv/radv.c index 5c52217d..4ea1f5c2 100644 --- a/proto/radv/radv.c +++ b/proto/radv/radv.c @@ -47,7 +47,7 @@ static void radv_timer(timer *tm) { struct radv_iface *ifa = tm->data; - struct proto_radv *ra = ifa->ra; + struct radv_proto *p = ifa->ra; RADV_TRACE(D_EVENTS, "Timer fired on %s", ifa->iface->name); @@ -72,7 +72,7 @@ static char* ev_name[] = { NULL, "Init", "Change", "RS" }; void radv_iface_notify(struct radv_iface *ifa, int event) { - struct proto_radv *ra = ifa->ra; + struct radv_proto *p = ifa->ra; if (!ifa->sk) return; @@ -102,21 +102,21 @@ radv_iface_notify(struct radv_iface *ifa, int event) } static void -radv_iface_notify_all(struct proto_radv *ra, int event) +radv_iface_notify_all(struct radv_proto *p, int event) { struct radv_iface *ifa; - WALK_LIST(ifa, ra->iface_list) + WALK_LIST(ifa, p->iface_list) radv_iface_notify(ifa, event); } static struct radv_iface * -radv_iface_find(struct proto_radv *ra, struct iface *what) +radv_iface_find(struct radv_proto *p, struct iface *what) { struct radv_iface *ifa; - WALK_LIST(ifa, ra->iface_list) + WALK_LIST(ifa, p->iface_list) if (ifa->iface == what) return ifa; @@ -127,11 +127,11 @@ static void radv_iface_add(struct object_lock *lock) { struct radv_iface *ifa = lock->data; - struct proto_radv *ra = ifa->ra; + struct radv_proto *p = ifa->ra; if (! radv_sk_open(ifa)) { - log(L_ERR "%s: Socket open failed on interface %s", ra->p.name, ifa->iface->name); + log(L_ERR "%s: Socket open failed on interface %s", p->p.name, ifa->iface->name); return; } @@ -150,24 +150,24 @@ find_lladdr(struct iface *iface) } static void -radv_iface_new(struct proto_radv *ra, struct iface *iface, struct radv_iface_config *cf) +radv_iface_new(struct radv_proto *p, struct iface *iface, struct radv_iface_config *cf) { - pool *pool = ra->p.pool; + pool *pool = p->p.pool; struct radv_iface *ifa; RADV_TRACE(D_EVENTS, "Adding interface %s", iface->name); ifa = mb_allocz(pool, sizeof(struct radv_iface)); - ifa->ra = ra; + ifa->ra = p; ifa->cf = cf; ifa->iface = iface; - add_tail(&ra->iface_list, NODE ifa); + add_tail(&p->iface_list, NODE ifa); ifa->addr = find_lladdr(iface); if (!ifa->addr) { - log(L_ERR "%s: Cannot find link-locad addr on interface %s", ra->p.name, iface->name); + log(L_ERR "%s: Cannot find link-locad addr on interface %s", p->p.name, iface->name); return; } @@ -193,7 +193,7 @@ radv_iface_new(struct proto_radv *ra, struct iface *iface, struct radv_iface_con static void radv_iface_remove(struct radv_iface *ifa) { - struct proto_radv *ra = ifa->ra; + struct radv_proto *p = ifa->ra; RADV_TRACE(D_EVENTS, "Removing interface %s", ifa->iface->name); rem_node(NODE ifa); @@ -206,10 +206,10 @@ radv_iface_remove(struct radv_iface *ifa) } static void -radv_if_notify(struct proto *p, unsigned flags, struct iface *iface) +radv_if_notify(struct proto *P, unsigned flags, struct iface *iface) { - struct proto_radv *ra = (struct proto_radv *) p; - struct radv_config *cf = (struct radv_config *) (p->cf); + struct radv_proto *p = (struct radv_proto *) P; + struct radv_config *cf = (struct radv_config *) (P->cf); if (iface->flags & IF_IGNORE) return; @@ -220,12 +220,12 @@ radv_if_notify(struct proto *p, unsigned flags, struct iface *iface) iface_patt_find(&cf->patt_list, iface, NULL); if (ic) - radv_iface_new(ra, iface, ic); + radv_iface_new(p, iface, ic); return; } - struct radv_iface *ifa = radv_iface_find(ra, iface); + struct radv_iface *ifa = radv_iface_find(p, iface); if (!ifa) return; @@ -240,9 +240,9 @@ radv_if_notify(struct proto *p, unsigned flags, struct iface *iface) } static void -radv_ifa_notify(struct proto *p, unsigned flags UNUSED, struct ifa *a) +radv_ifa_notify(struct proto *P, unsigned flags UNUSED, struct ifa *a) { - struct proto_radv *ra = (struct proto_radv *) p; + struct radv_proto *p = (struct radv_proto *) P; if (a->flags & IA_SECONDARY) return; @@ -250,7 +250,7 @@ radv_ifa_notify(struct proto *p, unsigned flags UNUSED, struct ifa *a) if (a->scope <= SCOPE_LINK) return; - struct radv_iface *ifa = radv_iface_find(ra, a->iface); + struct radv_iface *ifa = radv_iface_find(p, a->iface); if (ifa) radv_iface_notify(ifa, RA_EV_CHANGE); @@ -264,10 +264,10 @@ static inline int radv_net_match_trigger(struct radv_config *cf, net *n) } int -radv_import_control(struct proto *p, rte **new, ea_list **attrs UNUSED, struct linpool *pool UNUSED) +radv_import_control(struct proto *P, rte **new, ea_list **attrs UNUSED, struct linpool *pool UNUSED) { - // struct proto_radv *ra = (struct proto_radv *) p; - struct radv_config *cf = (struct radv_config *) (p->cf); + // struct radv_proto *p = (struct radv_proto *) P; + struct radv_config *cf = (struct radv_config *) (P->cf); if (radv_net_match_trigger(cf, (*new)->net)) return RIC_PROCESS; @@ -276,61 +276,62 @@ radv_import_control(struct proto *p, rte **new, ea_list **attrs UNUSED, struct l } static void -radv_rt_notify(struct proto *p, rtable *tbl UNUSED, net *n, rte *new, rte *old UNUSED, ea_list *attrs UNUSED) +radv_rt_notify(struct proto *P, rtable *tbl UNUSED, net *n, rte *new, rte *old UNUSED, ea_list *attrs UNUSED) { - struct proto_radv *ra = (struct proto_radv *) p; - struct radv_config *cf = (struct radv_config *) (p->cf); + struct radv_proto *p = (struct radv_proto *) P; + struct radv_config *cf = (struct radv_config *) (P->cf); if (radv_net_match_trigger(cf, n)) { - u8 old_active = ra->active; - ra->active = !!new; + u8 old_active = p->active; + p->active = !!new; - if (ra->active == old_active) + if (p->active == old_active) return; - if (ra->active) + if (p->active) RADV_TRACE(D_EVENTS, "Triggered"); else RADV_TRACE(D_EVENTS, "Suppressed"); - radv_iface_notify_all(ra, RA_EV_CHANGE); + radv_iface_notify_all(p, RA_EV_CHANGE); } } static int -radv_check_active(struct proto_radv *ra) +radv_check_active(struct radv_proto *p) { - struct radv_config *cf = (struct radv_config *) (ra->p.cf); + struct radv_config *cf = (struct radv_config *) (p->p.cf); if (! cf->trigger_valid) return 1; - return rt_examine(ra->p.table, cf->trigger_prefix, cf->trigger_pxlen, - &(ra->p), ra->p.cf->out_filter); + return rt_examine(p->p.table, cf->trigger_prefix, cf->trigger_pxlen, + &(p->p), p->p.cf->out_filter); } static struct proto * radv_init(struct proto_config *c) { - struct proto *p = proto_new(c, sizeof(struct proto_radv)); + struct proto *P = proto_new(c, sizeof(struct radv_proto)); - p->accept_ra_types = RA_OPTIMAL; - p->import_control = radv_import_control; - p->rt_notify = radv_rt_notify; - p->if_notify = radv_if_notify; - p->ifa_notify = radv_ifa_notify; - return p; + P->accept_ra_types = RA_OPTIMAL; + P->import_control = radv_import_control; + P->rt_notify = radv_rt_notify; + P->if_notify = radv_if_notify; + P->ifa_notify = radv_ifa_notify; + + return P; } static int -radv_start(struct proto *p) +radv_start(struct proto *P) { - struct proto_radv *ra = (struct proto_radv *) p; - struct radv_config *cf = (struct radv_config *) (p->cf); + struct radv_proto *p = (struct radv_proto *) P; + struct radv_config *cf = (struct radv_config *) (P->cf); - init_list(&(ra->iface_list)); - ra->active = !cf->trigger_valid; + init_list(&(p->iface_list)); + p->active = !cf->trigger_valid; return PS_UP; } @@ -343,21 +344,21 @@ radv_iface_shutdown(struct radv_iface *ifa) } static int -radv_shutdown(struct proto *p) +radv_shutdown(struct proto *P) { - struct proto_radv *ra = (struct proto_radv *) p; + struct radv_proto *p = (struct radv_proto *) P; struct radv_iface *ifa; - WALK_LIST(ifa, ra->iface_list) + WALK_LIST(ifa, p->iface_list) radv_iface_shutdown(ifa); return PS_DOWN; } static int -radv_reconfigure(struct proto *p, struct proto_config *c) +radv_reconfigure(struct proto *P, struct proto_config *c) { - struct proto_radv *ra = (struct proto_radv *) p; + struct radv_proto *p = (struct radv_proto *) P; // struct radv_config *old = (struct radv_config *) (p->cf); struct radv_config *new = (struct radv_config *) c; @@ -369,13 +370,13 @@ radv_reconfigure(struct proto *p, struct proto_config *c) * causing nodes to temporary remove their default routes. */ - p->cf = c; /* radv_check_active() requires proper p->cf */ - ra->active = radv_check_active(ra); + P->cf = c; /* radv_check_active() requires proper P->cf */ + p->active = radv_check_active(p); struct iface *iface; WALK_LIST(iface, iface_list) { - struct radv_iface *ifa = radv_iface_find(ra, iface); + struct radv_iface *ifa = radv_iface_find(p, iface); struct radv_iface_config *ic = (struct radv_iface_config *) iface_patt_find(&new->patt_list, iface, NULL); @@ -395,7 +396,7 @@ radv_reconfigure(struct proto *p, struct proto_config *c) } if (!ifa && ic) - radv_iface_new(ra, iface, ic); + radv_iface_new(p, iface, ic); } return 1; @@ -415,11 +416,11 @@ radv_copy_config(struct proto_config *dest, struct proto_config *src) } static void -radv_get_status(struct proto *p, byte *buf) +radv_get_status(struct proto *P, byte *buf) { - struct proto_radv *ra = (struct proto_radv *) p; + struct radv_proto *p = (struct radv_proto *) P; - if (!ra->active) + if (!p->active) strcpy(buf, "Suppressed"); } diff --git a/proto/radv/radv.h b/proto/radv/radv.h index 0591486b..559a3f3f 100644 --- a/proto/radv/radv.h +++ b/proto/radv/radv.h @@ -114,7 +114,7 @@ struct radv_dnssl_config }; -struct proto_radv +struct radv_proto { struct proto p; list iface_list; /* List of active ifaces */ @@ -124,7 +124,7 @@ struct proto_radv struct radv_iface { node n; - struct proto_radv *ra; + struct radv_proto *ra; struct radv_iface_config *cf; /* Related config, must be updated in reconfigure */ struct iface *iface; struct ifa *addr; /* Link-local address of iface */ @@ -154,8 +154,8 @@ struct radv_iface #else #define RADV_FORCE_DEBUG 0 #endif -#define RADV_TRACE(flags, msg, args...) do { if ((ra->p.debug & flags) || RADV_FORCE_DEBUG) \ - log(L_TRACE "%s: " msg, ra->p.name , ## args ); } while(0) +#define RADV_TRACE(flags, msg, args...) do { if ((p->p.debug & flags) || RADV_FORCE_DEBUG) \ + log(L_TRACE "%s: " msg, p->p.name , ## args ); } while(0) /* radv.c */ From b3fae3a81796b6deea48445402793660fade5eb6 Mon Sep 17 00:00:00 2001 From: "Ondrej Zajicek (work)" Date: Wed, 9 Aug 2017 12:41:44 +0200 Subject: [PATCH 007/198] RAdv: Fix typo --- proto/radv/radv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proto/radv/radv.c b/proto/radv/radv.c index 4ea1f5c2..91f9853d 100644 --- a/proto/radv/radv.c +++ b/proto/radv/radv.c @@ -167,7 +167,7 @@ radv_iface_new(struct radv_proto *p, struct iface *iface, struct radv_iface_conf ifa->addr = find_lladdr(iface); if (!ifa->addr) { - log(L_ERR "%s: Cannot find link-locad addr on interface %s", p->p.name, iface->name); + log(L_ERR "%s: Missing link-local address on interface %s", p->p.name, iface->name); return; } From da390bb11c8efc70767fc4b6d00bebf558d3b00f Mon Sep 17 00:00:00 2001 From: Michal 'vorner' Vaner Date: Wed, 9 Aug 2017 13:35:55 +0200 Subject: [PATCH 008/198] Drop stale TODO A TODO file last updated 5 years ago is useless. --- TODO | 45 --------------------------------------------- 1 file changed, 45 deletions(-) delete mode 100644 TODO diff --git a/TODO b/TODO deleted file mode 100644 index 23cd1877..00000000 --- a/TODO +++ /dev/null @@ -1,45 +0,0 @@ -Core -~~~~ -- socket open failure should not be fatal -- &&,||: priorities -- static: allow specifying a per-route filter program for setting route attributes? - -Globals -~~~~~~~ -- right usage of DBG vs. debug -- logging and tracing; use appropriate log levels -- check incoming packets and log errors!! -- check log calls for trailing newlines and log levels followed by comma -- check if all protocols set proper packet priorities and TTL's. -- try compiling with -Wunused -- does everybody test return value of sk_open? -- protocols: implement CLI hooks and per-procotol CLI commands -- protocols: implement reconfigure hook -- protocols: use locking -- check use of system includes and sprintf() - -Various ideas -~~~~~~~~~~~~~ -- client: Ctrl-R eats one more enter -- bgp: timing of updates? -- netlink: import Linux route attributes to our rta's, so that they can be filtered? -- config: executable config files -- filters: user defined attributes? -- io: use poll if available -- route recalculation timing and flap dampening [see RFC2439 for algorithms] -- aggregate engine: standard route aggregation and summarization [RFC2519] -- aggregate engine: injection of manually configured pseudo-static routes -- generate default route if any working BGP connection exists (aggregate engine again?) -- generate default route to IGP's (aggregate engine yet another time?) -- look at RFC 2386 (QoS-based routing) -- cli: show tables? - -OSPF -~~~~ - - check incoming packets using neighbor cache - - RFC2328 appendix E: Use a better algorithm - - automatic generation of external route tags (RFC1403) - - RFC2370 opaque LSA's - - Limit export rate of external LSAs (like Gated does) - - Bugfix in link state retransmission list (aging) - - Graceful OSPF restart - RFC3623 From 9b776458efdfae0c30b97f3670a1f4646221f072 Mon Sep 17 00:00:00 2001 From: Michal 'vorner' Vaner Date: Wed, 9 Aug 2017 13:39:20 +0200 Subject: [PATCH 009/198] Gitignore: File created by autoreconf --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 0b95d3a1..0dcebfd1 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ /config.status /configure /sysdep/autoconf.h.in +/sysdep/autoconf.h.in~ From 15a4421f9cb2c077cc484e3cda94e8710a1d68f5 Mon Sep 17 00:00:00 2001 From: Michal 'vorner' Vaner Date: Thu, 10 Aug 2017 12:32:30 +0200 Subject: [PATCH 010/198] Fix bird.conf example Make it syntactically correct, so it is accepted. --- bird.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bird.conf b/bird.conf index c2b47378..410f190c 100644 --- a/bird.conf +++ b/bird.conf @@ -52,6 +52,6 @@ protocol rip { ipv4; } -protocol ripng { +protocol rip ng { ipv6; } From 5699a2036cfb32cb3a683814f83242eb21e40d02 Mon Sep 17 00:00:00 2001 From: Michal 'vorner' Vaner Date: Thu, 10 Aug 2017 13:06:05 +0200 Subject: [PATCH 011/198] Less confusing log message A non-primary address isn't necessarily secondary, that's an independent flag. --- nest/iface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nest/iface.c b/nest/iface.c index a23cdf4f..addb1363 100644 --- a/nest/iface.c +++ b/nest/iface.c @@ -142,7 +142,7 @@ ifa_send_notify(struct proto *p, unsigned c, struct ifa *a) { if (p->debug & D_IFACES) log(L_TRACE "%s < %s address %I/%d on interface %s %s", - p->name, (a->flags & IA_PRIMARY) ? "primary" : "secondary", + p->name, (a->flags & IA_PRIMARY) ? "primary" : "non-primary", a->prefix, a->pxlen, a->iface->name, (c & IF_CHANGE_UP) ? "added" : "removed"); p->ifa_notify(p, c, a); From 080d9e4ce25f8f14e61ba0a81d5385bf8de3e48f Mon Sep 17 00:00:00 2001 From: Michal 'vorner' Vaner Date: Thu, 10 Aug 2017 14:35:14 +0200 Subject: [PATCH 012/198] Nicer log output non-primary is ugly, just omit it (and use primary in the other case). --- nest/iface.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nest/iface.c b/nest/iface.c index addb1363..ff362938 100644 --- a/nest/iface.c +++ b/nest/iface.c @@ -141,8 +141,8 @@ ifa_send_notify(struct proto *p, unsigned c, struct ifa *a) if (p->ifa_notify) { if (p->debug & D_IFACES) - log(L_TRACE "%s < %s address %I/%d on interface %s %s", - p->name, (a->flags & IA_PRIMARY) ? "primary" : "non-primary", + log(L_TRACE "%s <%s address %I/%d on interface %s %s", + p->name, (a->flags & IA_PRIMARY) ? " primary" : "", a->prefix, a->pxlen, a->iface->name, (c & IF_CHANGE_UP) ? "added" : "removed"); p->ifa_notify(p, c, a); From e7ed9ecba77162b4c09f34354378b0e752b9078e Mon Sep 17 00:00:00 2001 From: "Ondrej Zajicek (work)" Date: Tue, 22 Aug 2017 14:03:38 +0200 Subject: [PATCH 013/198] Client: Fix include --- client/client.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/client.c b/client/client.c index 0d4bdf3e..97cf6639 100644 --- a/client/client.c +++ b/client/client.c @@ -25,9 +25,10 @@ #include #include #include +#include #include -#include #include +#include #include "nest/bird.h" #include "lib/resource.h" From 3ac5d1ce4c10719dd48555521a50d4a9c5eadd15 Mon Sep 17 00:00:00 2001 From: Michal 'vorner' Vaner Date: Wed, 9 Aug 2017 16:00:16 +0200 Subject: [PATCH 014/198] RAdv: Extract prefix option preparation Put the prefix option preparation into a separate function. We're going to reuse that bit of code. --- proto/radv/packets.c | 54 +++++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/proto/radv/packets.c b/proto/radv/packets.c index 1c9837a4..bf051f62 100644 --- a/proto/radv/packets.c +++ b/proto/radv/packets.c @@ -123,7 +123,7 @@ radv_prepare_rdnss(struct radv_iface *ifa, list *rdnss_list, char **buf, char *b else op->lifetime = htonl(rcf->lifetime); - while(NODE_VALID(rcf) && + while(NODE_VALID(rcf) && (rcf->lifetime == rcf_base->lifetime) && (rcf->lifetime_mult == rcf_base->lifetime_mult)) { @@ -136,7 +136,7 @@ radv_prepare_rdnss(struct radv_iface *ifa, list *rdnss_list, char **buf, char *b rcf = NODE_NEXT(rcf); } - + op->length = 1+2*i; *buf += 8 * op->length; } @@ -235,6 +235,36 @@ radv_prepare_dnssl(struct radv_iface *ifa, list *dnssl_list, char **buf, char *b return -1; } +static int +radv_prepare_prefix(struct radv_iface *ifa, struct radv_prefix_config *pc, + struct ifa *addr, char **buf, char *bufend) +{ + struct radv_opt_prefix *op = (void *) *buf; + + if (*buf + sizeof(*op) > bufend) + { + log(L_WARN "%s: Too many prefixes on interface %s", ifa->ra->p.name, + ifa->iface->name); + return -1; + } + + op->type = OPT_PREFIX; + op->length = 4; + op->pxlen = addr->pxlen; + op->flags = (pc->onlink ? OPT_PX_ONLINK : 0) | + (pc->autonomous ? OPT_PX_AUTONOMOUS : 0); + op->valid_lifetime = (ifa->ra->active || !pc->valid_lifetime_sensitive) ? + htonl(pc->valid_lifetime) : 0; + op->preferred_lifetime = (ifa->ra->active || !pc->preferred_lifetime_sensitive) ? + htonl(pc->preferred_lifetime) : 0; + op->reserved = 0; + op->prefix = addr->prefix; + ipa_hton(op->prefix); + *buf += sizeof(*op); + + return 0; +} + static void radv_prepare_ra(struct radv_iface *ifa) { @@ -279,26 +309,8 @@ radv_prepare_ra(struct radv_iface *ifa) if (!pc || pc->skip) continue; - if (buf + sizeof(struct radv_opt_prefix) > bufend) - { - log(L_WARN "%s: Too many prefixes on interface %s", p->p.name, ifa->iface->name); + if (radv_prepare_prefix(ifa, pc, addr, &buf, bufend) < 0) goto done; - } - - struct radv_opt_prefix *op = (void *) buf; - op->type = OPT_PREFIX; - op->length = 4; - op->pxlen = addr->pxlen; - op->flags = (pc->onlink ? OPT_PX_ONLINK : 0) | - (pc->autonomous ? OPT_PX_AUTONOMOUS : 0); - op->valid_lifetime = (p->active || !pc->valid_lifetime_sensitive) ? - htonl(pc->valid_lifetime) : 0; - op->preferred_lifetime = (p->active || !pc->preferred_lifetime_sensitive) ? - htonl(pc->preferred_lifetime) : 0; - op->reserved = 0; - op->prefix = addr->prefix; - ipa_hton(op->prefix); - buf += sizeof(*op); } if (! ic->rdnss_local) From e2d2b3ef21f082a034e79d0880d4b36428029a59 Mon Sep 17 00:00:00 2001 From: Michal 'vorner' Vaner Date: Fri, 11 Aug 2017 12:25:36 +0200 Subject: [PATCH 015/198] RAdv: Buffer prefixes awhile after they disappear Keep a cache of all the relevant prefixes we send out. When a prefix appears, insert it into the cache. If it dies, keep it there for a while, marked as dead. Send out the dead prefixes with zero lifetime. --- proto/radv/packets.c | 53 +++------------- proto/radv/radv.c | 146 ++++++++++++++++++++++++++++++++++++++++--- proto/radv/radv.h | 23 ++++++- 3 files changed, 170 insertions(+), 52 deletions(-) diff --git a/proto/radv/packets.c b/proto/radv/packets.c index bf051f62..088d177c 100644 --- a/proto/radv/packets.c +++ b/proto/radv/packets.c @@ -70,36 +70,6 @@ struct radv_opt_dnssl char domain[]; }; - -static struct radv_prefix_config default_prefix = { - .onlink = 1, - .autonomous = 1, - .valid_lifetime = DEFAULT_VALID_LIFETIME, - .preferred_lifetime = DEFAULT_PREFERRED_LIFETIME -}; - - -static struct radv_prefix_config * -radv_prefix_match(struct radv_iface *ifa, struct ifa *a) -{ - struct radv_proto *p = ifa->ra; - struct radv_config *cf = (struct radv_config *) (p->p.cf); - struct radv_prefix_config *pc; - - if (a->scope <= SCOPE_LINK) - return NULL; - - WALK_LIST(pc, ifa->cf->pref_list) - if ((a->pxlen >= pc->pxlen) && ipa_in_net(a->prefix, pc->prefix, pc->pxlen)) - return pc; - - WALK_LIST(pc, cf->pref_list) - if ((a->pxlen >= pc->pxlen) && ipa_in_net(a->prefix, pc->prefix, pc->pxlen)) - return pc; - - return &default_prefix; -} - static int radv_prepare_rdnss(struct radv_iface *ifa, list *rdnss_list, char **buf, char *bufend) { @@ -236,9 +206,10 @@ radv_prepare_dnssl(struct radv_iface *ifa, list *dnssl_list, char **buf, char *b } static int -radv_prepare_prefix(struct radv_iface *ifa, struct radv_prefix_config *pc, - struct ifa *addr, char **buf, char *bufend) +radv_prepare_prefix(struct radv_iface *ifa, struct radv_prefix *prefix, + char **buf, char *bufend) { + struct radv_prefix_config *pc = prefix->config; struct radv_opt_prefix *op = (void *) *buf; if (*buf + sizeof(*op) > bufend) @@ -250,7 +221,7 @@ radv_prepare_prefix(struct radv_iface *ifa, struct radv_prefix_config *pc, op->type = OPT_PREFIX; op->length = 4; - op->pxlen = addr->pxlen; + op->pxlen = prefix->len; op->flags = (pc->onlink ? OPT_PX_ONLINK : 0) | (pc->autonomous ? OPT_PX_AUTONOMOUS : 0); op->valid_lifetime = (ifa->ra->active || !pc->valid_lifetime_sensitive) ? @@ -258,7 +229,7 @@ radv_prepare_prefix(struct radv_iface *ifa, struct radv_prefix_config *pc, op->preferred_lifetime = (ifa->ra->active || !pc->preferred_lifetime_sensitive) ? htonl(pc->preferred_lifetime) : 0; op->reserved = 0; - op->prefix = addr->prefix; + op->prefix = prefix->prefix; ipa_hton(op->prefix); *buf += sizeof(*op); @@ -300,16 +271,10 @@ radv_prepare_ra(struct radv_iface *ifa) buf += sizeof (*om); } - struct ifa *addr; - WALK_LIST(addr, ifa->iface->addrs) + struct radv_prefix *prefix; + WALK_LIST(prefix, ifa->prefixes) { - struct radv_prefix_config *pc; - pc = radv_prefix_match(ifa, addr); - - if (!pc || pc->skip) - continue; - - if (radv_prepare_prefix(ifa, pc, addr, &buf, bufend) < 0) + if (radv_prepare_prefix(ifa, prefix, &buf, bufend) < 0) goto done; } @@ -419,7 +384,7 @@ radv_err_hook(sock *sk, int err) int radv_sk_open(struct radv_iface *ifa) { - sock *sk = sk_new(ifa->ra->p.pool); + sock *sk = sk_new(ifa->pool); sk->type = SK_IP; sk->dport = ICMPV6_PROTO; sk->saddr = ifa->addr->ip; diff --git a/proto/radv/radv.c b/proto/radv/radv.c index 91f9853d..303cf251 100644 --- a/proto/radv/radv.c +++ b/proto/radv/radv.c @@ -51,6 +51,15 @@ radv_timer(timer *tm) RADV_TRACE(D_EVENTS, "Timer fired on %s", ifa->iface->name); + /* If some dead prefixes expired, regenerate the prefix list and the packet. + * We do so by pretending there was a change on the interface. + * + * This sets the timer, but we replace it just at the end of this function + * (replacing a timer is fine). + */ + if (ifa->prefix_expires != 0 && ifa->prefix_expires <= now) + radv_iface_notify(ifa, RA_EV_GC); + radv_send_ra(ifa, 0); /* Update timer */ @@ -67,7 +76,129 @@ radv_timer(timer *tm) tm_start(ifa->timer, after); } -static char* ev_name[] = { NULL, "Init", "Change", "RS" }; +static struct radv_prefix_config default_prefix = { + .onlink = 1, + .autonomous = 1, + .valid_lifetime = DEFAULT_VALID_LIFETIME, + .preferred_lifetime = DEFAULT_PREFERRED_LIFETIME +}; + +static struct radv_prefix_config dead_prefix = { +}; + +/* Find a corresponding config for the given prefix */ +static struct radv_prefix_config * +radv_prefix_match(struct radv_iface *ifa, struct ifa *a) +{ + struct radv_proto *p = ifa->ra; + struct radv_config *cf = (struct radv_config *) (p->p.cf); + struct radv_prefix_config *pc; + + if (a->scope <= SCOPE_LINK) + return NULL; + + WALK_LIST(pc, ifa->cf->pref_list) + if ((a->pxlen >= pc->pxlen) && ipa_in_net(a->prefix, pc->prefix, pc->pxlen)) + return pc; + + WALK_LIST(pc, cf->pref_list) + if ((a->pxlen >= pc->pxlen) && ipa_in_net(a->prefix, pc->prefix, pc->pxlen)) + return pc; + + return &default_prefix; +} + +/* + * Go through the list of prefixes, compare them with configs and decide if we + * want them or not. */ +static void +prefixes_prepare(struct radv_iface *ifa) +{ + struct radv_proto *p = ifa->ra; + /* First mark all the prefixes as unused */ + struct radv_prefix *pfx; + + WALK_LIST(pfx, ifa->prefixes) + pfx->mark = 0; + + /* Now find all the prefixes we want to use and make sure they are in the + * list. */ + struct ifa *addr; + WALK_LIST(addr, ifa->iface->addrs) + { + struct radv_prefix_config *pc = radv_prefix_match(ifa, addr); + + if (!pc || pc->skip) + continue; + + /* Do we have it already? */ + struct radv_prefix *existing = NULL; + WALK_LIST(pfx, ifa->prefixes) + if (pfx->len == addr->pxlen && + memcmp(&pfx->prefix, &addr->prefix, sizeof pfx->prefix) == 0) + { + existing = pfx; + break; + } + + if (!existing) + { + RADV_TRACE(D_EVENTS, "Allocating new prefix %I on %s", addr->prefix, + ifa->iface->name); + existing = mb_allocz(ifa->pool, sizeof *existing); + existing->prefix = addr->prefix; + existing->len = addr->pxlen; + add_tail(&ifa->prefixes, NODE existing); + } + /* + * Update the information (it may have changed, or even bring a prefix back + * to life). + */ + existing->alive = 1; + existing->mark = 1; + existing->config = pc; + } + + /* + * Garbage-collect the prefixes. If something isn't used, it dies (but isn't + * dropped just yet). If something is dead and rots there for long enough, + * clean it up. + */ + // XXX: Make these 5 minutes it configurable + bird_clock_t rotten = now + 300; + struct radv_prefix *next; + bird_clock_t expires_soonest = 0; + WALK_LIST_DELSAFE(pfx, next, ifa->prefixes) { + if (pfx->alive && !pfx->mark) + { + RADV_TRACE(D_EVENTS, "Marking prefix %I on %s as dead", pfx->prefix, + ifa->iface->name); + // It just died + pfx->alive = 0; + pfx->expires = rotten; + pfx->config = &dead_prefix; + } + if (!pfx->alive) + if (pfx->expires <= now) + { + RADV_TRACE(D_EVENTS, "Dropping long dead prefix %I on %s", pfx->prefix, + ifa->iface->name); + // It's dead and rotten, clean it up + rem_node(NODE pfx); + mb_free(pfx); + } + else + { + ASSERT(pfx->expires != 0); + // Let it rot for a while more, but look when it's ripe. + if (expires_soonest == 0 || pfx->expires < expires_soonest) + expires_soonest = pfx->expires; + } + } + ifa->prefix_expires = expires_soonest; +} + +static char* ev_name[] = { NULL, "Init", "Change", "RS", "Garbage collect" }; void radv_iface_notify(struct radv_iface *ifa, int event) @@ -82,6 +213,7 @@ radv_iface_notify(struct radv_iface *ifa, int event) switch (event) { case RA_EV_CHANGE: + case RA_EV_GC: ifa->plen = 0; case RA_EV_INIT: ifa->initial = MAX_INITIAL_RTR_ADVERTISEMENTS; @@ -91,6 +223,8 @@ radv_iface_notify(struct radv_iface *ifa, int event) break; } + prefixes_prepare(ifa); + /* Update timer */ unsigned delta = now - ifa->last; unsigned after = 0; @@ -152,15 +286,17 @@ find_lladdr(struct iface *iface) static void radv_iface_new(struct radv_proto *p, struct iface *iface, struct radv_iface_config *cf) { - pool *pool = p->p.pool; struct radv_iface *ifa; RADV_TRACE(D_EVENTS, "Adding interface %s", iface->name); + pool *pool = rp_new(p->p.pool, iface->name); ifa = mb_allocz(pool, sizeof(struct radv_iface)); + ifa->pool = pool; ifa->ra = p; ifa->cf = cf; ifa->iface = iface; + init_list(&ifa->prefixes); add_tail(&p->iface_list, NODE ifa); @@ -198,11 +334,7 @@ radv_iface_remove(struct radv_iface *ifa) rem_node(NODE ifa); - rfree(ifa->sk); - rfree(ifa->timer); - rfree(ifa->lock); - - mb_free(ifa); + rfree(ifa->pool); } static void diff --git a/proto/radv/radv.h b/proto/radv/radv.h index 559a3f3f..54d7c6f0 100644 --- a/proto/radv/radv.h +++ b/proto/radv/radv.h @@ -121,6 +121,23 @@ struct radv_proto u8 active; /* Whether radv is active w.r.t. triggers */ }; +struct radv_prefix /* One prefix we advertise */ +{ + node n; + ip_addr prefix; + u8 len; + /* Is the prefix alive? If not, we advertise it with 0 lifetime, so clients + * stop using it. */ + u8 alive; + u8 mark; /* A temporary mark for processing */ + /* The (absolute) time when we drop this prefix from advertising. It is valid + * only if !alive. */ + bird_clock_t expires; + /* The config tied to this prefix. Always valid (we place a dummy config here + * when !alive). */ + struct radv_prefix_config *config; +}; + struct radv_iface { node n; @@ -128,6 +145,9 @@ struct radv_iface struct radv_iface_config *cf; /* Related config, must be updated in reconfigure */ struct iface *iface; struct ifa *addr; /* Link-local address of iface */ + struct pool *pool; /* A pool for interface-specific things */ + list prefixes; /* The prefixes we advertise */ + bird_clock_t prefix_expires; /* When the soonest prefix expires (0 = none dead) */ timer *timer; struct object_lock *lock; @@ -135,12 +155,13 @@ struct radv_iface bird_clock_t last; /* Time of last sending of RA */ u16 plen; /* Length of prepared RA in tbuf, or 0 if not valid */ - byte initial; /* List of active ifaces */ + byte initial; /* How many RAs are still to be sent as initial */ }; #define RA_EV_INIT 1 /* Switch to initial mode */ #define RA_EV_CHANGE 2 /* Change of options or prefixes */ #define RA_EV_RS 3 /* Received RS */ +#define RA_EV_GC 4 /* Internal garbage collection of prefixes */ /* Default Router Preferences (RFC 4191) */ #define RA_PREF_LOW 0x18 From ec7d6a506ecae89e5019ce7fcb380a713be28bce Mon Sep 17 00:00:00 2001 From: Michal 'vorner' Vaner Date: Thu, 17 Aug 2017 11:34:25 +0200 Subject: [PATCH 016/198] RAdv: Configure how long a dead prefix is advertised --- doc/bird.sgml | 6 ++++++ proto/radv/config.Y | 4 +++- proto/radv/radv.c | 4 ++-- proto/radv/radv.h | 6 +++++- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/doc/bird.sgml b/doc/bird.sgml index ffd28964..d8dad431 100644 --- a/doc/bird.sgml +++ b/doc/bird.sgml @@ -3436,6 +3436,12 @@ dsc-iface as a default router. For . Default: 3 *