summaryrefslogtreecommitdiff
path: root/proto/radv/packets.c
diff options
context:
space:
mode:
authorMichal 'vorner' Vaner <michal.vaner@nic.cz>2017-08-11 12:25:36 +0200
committerOndrej Zajicek (work) <santiago@crfreenet.org>2017-08-30 16:34:15 +0200
commite2d2b3ef21f082a034e79d0880d4b36428029a59 (patch)
treedae12f76ed7901e68be0dd24f44402fadeec9986 /proto/radv/packets.c
parent3ac5d1ce4c10719dd48555521a50d4a9c5eadd15 (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.c53
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;