diff options
author | Michal 'vorner' Vaner <michal.vaner@nic.cz> | 2017-08-11 12:25:36 +0200 |
---|---|---|
committer | Ondrej Zajicek (work) <santiago@crfreenet.org> | 2017-08-30 16:34:15 +0200 |
commit | e2d2b3ef21f082a034e79d0880d4b36428029a59 (patch) | |
tree | dae12f76ed7901e68be0dd24f44402fadeec9986 /proto/radv/packets.c | |
parent | 3ac5d1ce4c10719dd48555521a50d4a9c5eadd15 (diff) |
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.
Diffstat (limited to 'proto/radv/packets.c')
-rw-r--r-- | proto/radv/packets.c | 53 |
1 files changed, 9 insertions, 44 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; |