summaryrefslogtreecommitdiff
path: root/proto/radv
diff options
context:
space:
mode:
Diffstat (limited to 'proto/radv')
-rw-r--r--proto/radv/Makefile9
-rw-r--r--proto/radv/config.Y45
-rw-r--r--proto/radv/packets.c42
-rw-r--r--proto/radv/radv.c200
-rw-r--r--proto/radv/radv.h30
5 files changed, 169 insertions, 157 deletions
diff --git a/proto/radv/Makefile b/proto/radv/Makefile
index efc4d4af..05317eff 100644
--- a/proto/radv/Makefile
+++ b/proto/radv/Makefile
@@ -1,5 +1,6 @@
-source=radv.c packets.c
-root-rel=../../
-dir-name=proto/radv
+src := packets.c radv.c
+obj := $(src-o-files)
+$(all-daemon)
+$(cf-local)
-include ../../Rules
+tests_objs := $(tests_objs) $(src-o-files) \ No newline at end of file
diff --git a/proto/radv/config.Y b/proto/radv/config.Y
index 84a2de0e..37815f0d 100644
--- a/proto/radv/config.Y
+++ b/proto/radv/config.Y
@@ -44,6 +44,7 @@ CF_ADDTO(proto, radv_proto)
radv_proto_start: proto_start RADV
{
this_proto = proto_config_new(&proto_radv, $1);
+
init_list(&RADV_CFG->patt_list);
init_list(&RADV_CFG->pref_list);
init_list(&RADV_CFG->rdnss_list);
@@ -52,15 +53,12 @@ radv_proto_start: proto_start RADV
radv_proto_item:
proto_item
+ | proto_channel
| INTERFACE radv_iface
| PREFIX radv_prefix { add_tail(&RADV_CFG->pref_list, NODE this_radv_prefix); }
| RDNSS { init_list(&radv_dns_list); } radv_rdnss { add_tail_list(&RADV_CFG->rdnss_list, &radv_dns_list); }
| DNSSL { init_list(&radv_dns_list); } radv_dnssl { add_tail_list(&RADV_CFG->dnssl_list, &radv_dns_list); }
- | TRIGGER prefix {
- RADV_CFG->trigger_prefix = $2.addr;
- RADV_CFG->trigger_pxlen = $2.len;
- RADV_CFG->trigger_valid = 1;
- }
+ | TRIGGER net_ip6 { RADV_CFG->trigger = $2; }
| PROPAGATE ROUTES bool { RADV_CFG->propagate_routes = $3; }
;
@@ -82,16 +80,16 @@ radv_iface_start:
init_list(&RADV_IFACE->rdnss_list);
init_list(&RADV_IFACE->dnssl_list);
- RADV_IFACE->min_ra_int = -1; /* undefined */
+ RADV_IFACE->min_ra_int = (u32) -1; /* undefined */
RADV_IFACE->max_ra_int = DEFAULT_MAX_RA_INT;
RADV_IFACE->min_delay = DEFAULT_MIN_DELAY;
- RADV_IFACE->prefix_linger_time = -1;
- RADV_IFACE->route_linger_time = -1;
+ RADV_IFACE->prefix_linger_time = (u32) -1;
+ RADV_IFACE->route_linger_time = (u32) -1;
RADV_IFACE->current_hop_limit = DEFAULT_CURRENT_HOP_LIMIT;
- RADV_IFACE->default_lifetime = -1;
+ RADV_IFACE->default_lifetime = (u32) -1;
RADV_IFACE->default_lifetime_sensitive = 1;
RADV_IFACE->default_preference = RA_PREF_MEDIUM;
- RADV_IFACE->route_lifetime = -1;
+ RADV_IFACE->route_lifetime = (u32) -1;
RADV_IFACE->route_lifetime_sensitive = 0;
RADV_IFACE->route_preference = RA_PREF_MEDIUM;
};
@@ -102,18 +100,18 @@ radv_iface_item:
| MIN DELAY expr { RADV_IFACE->min_delay = $3; if ($3 <= 0) cf_error("Min delay must be positive"); }
| MANAGED bool { RADV_IFACE->managed = $2; }
| OTHER CONFIG bool { RADV_IFACE->other_config = $3; }
- | LINK MTU expr { RADV_IFACE->link_mtu = $3; if ($3 < 0) cf_error("Link MTU must be 0 or positive"); }
- | REACHABLE TIME expr { RADV_IFACE->reachable_time = $3; if (($3 < 0) || ($3 > 3600000)) cf_error("Reachable time must be in range 0-3600000"); }
- | RETRANS TIMER expr { RADV_IFACE->retrans_timer = $3; if ($3 < 0) cf_error("Retrans timer must be 0 or positive"); }
- | CURRENT HOP LIMIT expr { RADV_IFACE->current_hop_limit = $4; if (($4 < 0) || ($4 > 255)) cf_error("Current hop limit must be in range 0-255"); }
+ | LINK MTU expr { RADV_IFACE->link_mtu = $3; }
+ | REACHABLE TIME expr { RADV_IFACE->reachable_time = $3; if ($3 > 3600000) cf_error("Reachable time must be in range 0-3600000"); }
+ | RETRANS TIMER expr { RADV_IFACE->retrans_timer = $3; }
+ | CURRENT HOP LIMIT expr { RADV_IFACE->current_hop_limit = $4; if ($4 > 255) cf_error("Current hop limit must be in range 0-255"); }
| DEFAULT LIFETIME expr radv_sensitive {
RADV_IFACE->default_lifetime = $3;
- if (($3 < 0) || ($3 > 9000)) cf_error("Default lifetime must be in range 0-9000");
- if ($4 != -1) RADV_IFACE->default_lifetime_sensitive = $4;
+ if ($3 > 9000) cf_error("Default lifetime must be in range 0-9000");
+ if ($4 != (uint) -1) RADV_IFACE->default_lifetime_sensitive = $4;
}
| ROUTE LIFETIME expr radv_sensitive {
RADV_IFACE->route_lifetime = $3;
- if ($4 != -1) RADV_IFACE->route_lifetime_sensitive = $4;
+ if ($4 != (uint) -1) RADV_IFACE->route_lifetime_sensitive = $4;
}
| DEFAULT PREFERENCE radv_preference { RADV_IFACE->default_preference = $3; }
| ROUTE PREFERENCE radv_preference { RADV_IFACE->route_preference = $3; }
@@ -152,7 +150,7 @@ radv_iface_finish:
if ((ic->min_ra_int > 3) &&
(ic->min_ra_int > (ic->max_ra_int * 3 / 4)))
- cf_error("Min RA interval must be at most 3/4 * Max RA interval %d %d", ic->min_ra_int, ic->max_ra_int);
+ cf_error("Min RA interval must be at most 3/4 * Max RA interval");
if ((ic->default_lifetime > 0) && (ic->default_lifetime < ic->max_ra_int))
cf_error("Default lifetime must be either 0 or at least Max RA interval");
@@ -184,11 +182,10 @@ radv_iface:
radv_iface_start iface_patt_list_nopx radv_iface_opt_list radv_iface_finish;
-radv_prefix_start: prefix
+radv_prefix_start: net_ip6
{
this_radv_prefix = cfg_allocz(sizeof(struct radv_prefix_config));
- RADV_PREFIX->prefix = $1.addr;
- RADV_PREFIX->pxlen = $1.len;
+ RADV_PREFIX->prefix = *(net_addr_ip6 *) &($1);
RADV_PREFIX->onlink = 1;
RADV_PREFIX->autonomous = 1;
@@ -202,11 +199,11 @@ radv_prefix_item:
| AUTONOMOUS bool { RADV_PREFIX->autonomous = $2; }
| VALID LIFETIME expr radv_sensitive {
RADV_PREFIX->valid_lifetime = $3;
- if ($4 != -1) RADV_PREFIX->valid_lifetime_sensitive = $4;
+ if ($4 != (uint) -1) RADV_PREFIX->valid_lifetime_sensitive = $4;
}
| PREFERRED LIFETIME expr radv_sensitive {
RADV_PREFIX->preferred_lifetime = $3;
- if ($4 != -1) RADV_PREFIX->preferred_lifetime_sensitive = $4;
+ if ($4 != (uint) -1) RADV_PREFIX->preferred_lifetime_sensitive = $4;
}
;
@@ -331,7 +328,7 @@ radv_mult:
;
radv_sensitive:
- /* empty */ { $$ = -1; }
+ /* empty */ { $$ = (uint) -1; }
| SENSITIVE bool { $$ = $2; }
;
diff --git a/proto/radv/packets.c b/proto/radv/packets.c
index 7d54a827..b12d3a12 100644
--- a/proto/radv/packets.c
+++ b/proto/radv/packets.c
@@ -39,7 +39,7 @@ struct radv_opt_prefix
u32 valid_lifetime;
u32 preferred_lifetime;
u32 reserved;
- ip_addr prefix;
+ ip6_addr prefix;
};
#define OPT_PX_ONLINK 0x80
@@ -68,7 +68,7 @@ struct radv_opt_rdnss
u8 length;
u16 reserved;
u32 lifetime;
- ip_addr servers[];
+ ip6_addr servers[];
};
struct radv_opt_dnssl
@@ -85,7 +85,7 @@ radv_prepare_route(struct radv_iface *ifa, struct radv_route *rt,
char **buf, char *bufend)
{
struct radv_proto *p = ifa->ra;
- u8 px_blocks = (rt->n.pxlen + 63) / 64;
+ u8 px_blocks = (net6_pxlen(rt->n.addr) + 63) / 64;
u8 opt_len = 8 * (1 + px_blocks);
if (*buf + opt_len > bufend)
@@ -103,17 +103,17 @@ radv_prepare_route(struct radv_iface *ifa, struct radv_route *rt,
*buf += opt_len;
opt->type = OPT_ROUTE;
opt->length = 1 + px_blocks;
- opt->pxlen = rt->n.pxlen;
+ opt->pxlen = net6_pxlen(rt->n.addr);
opt->flags = preference;
opt->lifetime = valid ? htonl(lifetime) : 0;
/* Copy the relevant part of the prefix */
- ip6_addr px_addr = ip6_hton(rt->n.prefix);
+ ip6_addr px_addr = ip6_hton(net6_prefix(rt->n.addr));
memcpy(opt->prefix, &px_addr, 8 * px_blocks);
/* Keeping track of first linger timeout */
if (!rt->valid)
- ifa->valid_time = MIN(ifa->valid_time, rt->changed + ifa->cf->route_linger_time);
+ ifa->valid_time = MIN(ifa->valid_time, rt->changed + ifa->cf->route_linger_time S);
return 0;
}
@@ -127,7 +127,7 @@ radv_prepare_rdnss(struct radv_iface *ifa, list *rdnss_list, char **buf, char *b
{
struct radv_rdnss_config *rcf_base = rcf;
struct radv_opt_rdnss *op = (void *) *buf;
- int max_i = (bufend - *buf - sizeof(struct radv_opt_rdnss)) / sizeof(ip_addr);
+ int max_i = (bufend - *buf - sizeof(struct radv_opt_rdnss)) / sizeof(ip6_addr);
int i = 0;
if (max_i < 1)
@@ -148,8 +148,7 @@ radv_prepare_rdnss(struct radv_iface *ifa, list *rdnss_list, char **buf, char *b
if (i >= max_i)
goto too_much;
- op->servers[i] = rcf->server;
- ipa_hton(op->servers[i]);
+ op->servers[i] = ip6_hton(rcf->server);
i++;
rcf = NODE_NEXT(rcf);
@@ -254,10 +253,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 *prefix,
+radv_prepare_prefix(struct radv_iface *ifa, struct radv_prefix *px,
char **buf, char *bufend)
{
- struct radv_prefix_config *pc = prefix->cf;
+ struct radv_prefix_config *pc = px->cf;
if (*buf + sizeof(struct radv_opt_prefix) > bufend)
{
@@ -269,7 +268,7 @@ radv_prepare_prefix(struct radv_iface *ifa, struct radv_prefix *prefix,
struct radv_opt_prefix *op = (void *) *buf;
op->type = OPT_PREFIX;
op->length = 4;
- op->pxlen = prefix->len;
+ op->pxlen = px->prefix.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) ?
@@ -277,13 +276,12 @@ radv_prepare_prefix(struct radv_iface *ifa, struct radv_prefix *prefix,
op->preferred_lifetime = (ifa->ra->active || !pc->preferred_lifetime_sensitive) ?
htonl(pc->preferred_lifetime) : 0;
op->reserved = 0;
- op->prefix = prefix->prefix;
- ipa_hton(op->prefix);
+ op->prefix = ip6_hton(px->prefix.prefix);
*buf += sizeof(*op);
/* Keeping track of first linger timeout */
- if (!prefix->valid)
- ifa->valid_time = MIN(ifa->valid_time, prefix->changed + ifa->cf->prefix_linger_time);
+ if (!px->valid)
+ ifa->valid_time = MIN(ifa->valid_time, px->changed + ifa->cf->prefix_linger_time S);
return 0;
}
@@ -294,6 +292,7 @@ radv_prepare_ra(struct radv_iface *ifa)
struct radv_proto *p = ifa->ra;
struct radv_config *cf = (struct radv_config *) (p->p.cf);
struct radv_iface_config *ic = ifa->cf;
+ btime now = current_time();
char *buf = ifa->sk->tbuf;
char *bufstart = buf;
@@ -330,7 +329,7 @@ radv_prepare_ra(struct radv_iface *ifa)
WALK_LIST(px, ifa->prefixes)
{
/* Skip invalid prefixes that are past linger timeout but still not pruned */
- if (!px->valid && (px->changed + ic->prefix_linger_time <= now))
+ if (!px->valid && ((px->changed + ic->prefix_linger_time S) <= now))
continue;
if (radv_prepare_prefix(ifa, px, &buf, bufend) < 0)
@@ -353,12 +352,10 @@ radv_prepare_ra(struct radv_iface *ifa)
if (p->fib_up)
{
- FIB_WALK(&p->routes, n)
+ FIB_WALK(&p->routes, struct radv_route, rt)
{
- struct radv_route *rt = (void *) n;
-
/* Skip invalid routes that are past linger timeout but still not pruned */
- if (!rt->valid && (rt->changed + ic->route_linger_time <= now))
+ if (!rt->valid && ((rt->changed + ic->route_linger_time S) <= now))
continue;
if (radv_prepare_route(ifa, rt, &buf, bufend) < 0)
@@ -396,7 +393,7 @@ radv_rx_hook(sock *sk, uint size)
if (sk->lifindex != sk->iface->index)
return 1;
- if (ipa_equal(sk->faddr, ifa->addr->ip))
+ if (ipa_equal(sk->faddr, sk->saddr))
return 1;
if (size < 8)
@@ -448,6 +445,7 @@ radv_sk_open(struct radv_iface *ifa)
{
sock *sk = sk_new(ifa->pool);
sk->type = SK_IP;
+ sk->subtype = SK_IPV6;
sk->dport = ICMPV6_PROTO;
sk->saddr = ifa->addr->ip;
sk->vrf = ifa->ra->p.vrf;
diff --git a/proto/radv/radv.c b/proto/radv/radv.c
index 7e8950c5..8a79dfaf 100644
--- a/proto/radv/radv.c
+++ b/proto/radv/radv.c
@@ -52,6 +52,7 @@ radv_timer(timer *tm)
{
struct radv_iface *ifa = tm->data;
struct radv_proto *p = ifa->ra;
+ btime now = current_time();
RADV_TRACE(D_EVENTS, "Timer fired on %s", ifa->iface->name);
@@ -68,16 +69,17 @@ radv_timer(timer *tm)
/* Update timer */
ifa->last = now;
- unsigned after = ifa->cf->min_ra_int;
- after += random() % (ifa->cf->max_ra_int - ifa->cf->min_ra_int + 1);
+ btime t = ifa->cf->min_ra_int S;
+ btime r = (ifa->cf->max_ra_int - ifa->cf->min_ra_int) S;
+ t += random() % (r + 1);
if (ifa->initial)
+ {
+ t = MIN(t, MAX_INITIAL_RTR_ADVERT_INTERVAL);
ifa->initial--;
+ }
- if (ifa->initial)
- after = MIN(after, MAX_INITIAL_RTR_ADVERT_INTERVAL);
-
- tm_start(ifa->timer, after);
+ tm_start(ifa->timer, t);
}
static struct radv_prefix_config default_prefix = {
@@ -92,21 +94,18 @@ 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)
+radv_prefix_match(struct radv_iface *ifa, net_addr_ip6 *px)
{
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))
+ if (net_in_net_ip6(px, &pc->prefix))
return pc;
WALK_LIST(pc, cf->pref_list)
- if ((a->pxlen >= pc->pxlen) && ipa_in_net(a->prefix, pc->prefix, pc->pxlen))
+ if (net_in_net_ip6(px, &pc->prefix))
return pc;
return &default_prefix;
@@ -121,6 +120,7 @@ radv_prepare_prefixes(struct radv_iface *ifa)
{
struct radv_proto *p = ifa->ra;
struct radv_prefix *pfx, *next;
+ btime now = current_time();
/* First mark all the prefixes as unused */
WALK_LIST(pfx, ifa->prefixes)
@@ -130,7 +130,12 @@ radv_prepare_prefixes(struct radv_iface *ifa)
struct ifa *addr;
WALK_LIST(addr, ifa->iface->addrs)
{
- struct radv_prefix_config *pc = radv_prefix_match(ifa, addr);
+ if ((addr->prefix.type != NET_IP6) ||
+ (addr->scope <= SCOPE_LINK))
+ continue;
+
+ net_addr_ip6 *prefix = (void *) &addr->prefix;
+ struct radv_prefix_config *pc = radv_prefix_match(ifa, prefix);
if (!pc || pc->skip)
continue;
@@ -138,7 +143,7 @@ radv_prepare_prefixes(struct radv_iface *ifa)
/* Do we have it already? */
struct radv_prefix *existing = NULL;
WALK_LIST(pfx, ifa->prefixes)
- if ((pfx->len == addr->pxlen) && ipa_equal(pfx->prefix, addr->prefix))
+ if (net_equal_ip6(&pfx->prefix, prefix))
{
existing = pfx;
break;
@@ -146,12 +151,11 @@ radv_prepare_prefixes(struct radv_iface *ifa)
if (!existing)
{
- RADV_TRACE(D_EVENTS, "Adding new prefix %I/%d on %s",
- addr->prefix, addr->pxlen, ifa->iface->name);
+ RADV_TRACE(D_EVENTS, "Adding new prefix %N on %s",
+ prefix, ifa->iface->name);
existing = mb_allocz(ifa->pool, sizeof *existing);
- existing->prefix = addr->prefix;
- existing->len = addr->pxlen;
+ net_copy_ip6(&existing->prefix, prefix);
add_tail(&ifa->prefixes, NODE existing);
}
@@ -169,8 +173,8 @@ radv_prepare_prefixes(struct radv_iface *ifa)
{
if (pfx->valid && !pfx->mark)
{
- RADV_TRACE(D_EVENTS, "Invalidating prefix %I/%d on %s",
- pfx->prefix, pfx->len, ifa->iface->name);
+ RADV_TRACE(D_EVENTS, "Invalidating prefix %N on %s",
+ pfx->prefix, ifa->iface->name);
pfx->valid = 0;
pfx->changed = now;
@@ -183,20 +187,21 @@ static void
radv_prune_prefixes(struct radv_iface *ifa)
{
struct radv_proto *p = ifa->ra;
- bird_clock_t next = TIME_INFINITY;
- bird_clock_t expires = 0;
+ btime now = current_time();
+ btime next = TIME_INFINITY;
+ btime expires = 0;
struct radv_prefix *px, *pxn;
WALK_LIST_DELSAFE(px, pxn, ifa->prefixes)
{
if (!px->valid)
{
- expires = px->changed + ifa->cf->prefix_linger_time;
+ expires = px->changed + ifa->cf->prefix_linger_time S;
if (expires <= now)
{
- RADV_TRACE(D_EVENTS, "Removing prefix %I/%d on %s",
- px->prefix, px->len, ifa->iface->name);
+ RADV_TRACE(D_EVENTS, "Removing prefix %N on %s",
+ px->prefix, ifa->iface->name);
rem_node(NODE px);
mb_free(px);
@@ -236,13 +241,8 @@ radv_iface_notify(struct radv_iface *ifa, int event)
}
/* Update timer */
- unsigned delta = now - ifa->last;
- unsigned after = 0;
-
- if (delta < ifa->cf->min_delay)
- after = ifa->cf->min_delay - delta;
-
- tm_start(ifa->timer, after);
+ btime t = ifa->last + ifa->cf->min_delay S - current_time();
+ tm_start(ifa->timer, t);
}
static void
@@ -281,17 +281,6 @@ radv_iface_add(struct object_lock *lock)
radv_iface_notify(ifa, RA_EV_INIT);
}
-static inline struct ifa *
-find_lladdr(struct iface *iface)
-{
- struct ifa *a;
- WALK_LIST(a, iface->addrs)
- if (a->scope == SCOPE_LINK)
- return a;
-
- return NULL;
-}
-
static void
radv_iface_new(struct radv_proto *p, struct iface *iface, struct radv_iface_config *cf)
{
@@ -305,24 +294,13 @@ radv_iface_new(struct radv_proto *p, struct iface *iface, struct radv_iface_conf
ifa->ra = p;
ifa->cf = cf;
ifa->iface = iface;
+ ifa->addr = iface->llv6;
init_list(&ifa->prefixes);
ifa->prune_time = TIME_INFINITY;
add_tail(&p->iface_list, NODE ifa);
- ifa->addr = find_lladdr(iface);
- if (!ifa->addr)
- {
- log(L_ERR "%s: Missing link-local address on interface %s", p->p.name, iface->name);
- return;
- }
-
- timer *tm = tm_new(pool);
- tm->hook = radv_timer;
- tm->data = ifa;
- tm->randomize = 0;
- tm->recurrent = 0;
- ifa->timer = tm;
+ ifa->timer = tm_new_init(pool, radv_timer, ifa, 0, 0);
struct object_lock *lock = olock_new(pool);
lock->type = OBJLOCK_IP;
@@ -357,8 +335,15 @@ radv_if_notify(struct proto *P, unsigned flags, struct iface *iface)
if (flags & IF_CHANGE_UP)
{
- struct radv_iface_config *ic = (struct radv_iface_config *)
- iface_patt_find(&cf->patt_list, iface, NULL);
+ struct radv_iface_config *ic = (void *) iface_patt_find(&cf->patt_list, iface, NULL);
+
+ /* Ignore non-multicast ifaces */
+ if (!(iface->flags & IF_MULTICAST))
+ return;
+
+ /* Ignore ifaces without link-local address */
+ if (!iface->llv6)
+ return;
if (ic)
radv_iface_new(p, iface, ic);
@@ -397,11 +382,16 @@ radv_ifa_notify(struct proto *P, unsigned flags UNUSED, struct ifa *a)
radv_iface_notify(ifa, RA_EV_CHANGE);
}
-static inline int radv_net_match_trigger(struct radv_config *cf, net *n)
+static inline int
+radv_trigger_valid(struct radv_config *cf)
+{
+ return cf->trigger.type != 0;
+}
+
+static inline int
+radv_net_match_trigger(struct radv_config *cf, net *n)
{
- return cf->trigger_valid &&
- (n->n.pxlen == cf->trigger_pxlen) &&
- ipa_equal(n->n.prefix, cf->trigger_prefix);
+ return radv_trigger_valid(cf) && net_equal(n->n.addr, &cf->trigger);
}
int
@@ -420,7 +410,7 @@ 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)
+radv_rt_notify(struct proto *P, struct channel *ch UNUSED, net *n, rte *new, rte *old UNUSED, ea_list *attrs)
{
struct radv_proto *p = (struct radv_proto *) P;
struct radv_config *cf = (struct radv_config *) (P->cf);
@@ -470,15 +460,15 @@ radv_rt_notify(struct proto *P, rtable *tbl UNUSED, net *n, rte *new, rte *old U
(preference != RA_PREF_MEDIUM) &&
(preference != RA_PREF_HIGH))
{
- log(L_WARN "%s: Invalid ra_preference value %u on route %I/%d",
- p->p.name, preference, n->n.prefix, n->n.pxlen);
+ log(L_WARN "%s: Invalid ra_preference value %u on route %N",
+ p->p.name, preference, n->n.addr);
preference = RA_PREF_MEDIUM;
preference_set = 1;
lifetime = 0;
lifetime_set = 1;
}
- rt = fib_get(&p->routes, &n->n.prefix, n->n.pxlen);
+ rt = fib_get(&p->routes, n->n.addr);
/* Ignore update if nothing changed */
if (rt->valid &&
@@ -492,7 +482,7 @@ radv_rt_notify(struct proto *P, rtable *tbl UNUSED, net *n, rte *new, rte *old U
log(L_WARN "%s: More than 17 routes exported to RAdv", p->p.name);
rt->valid = 1;
- rt->changed = now;
+ rt->changed = current_time();
rt->preference = preference;
rt->preference_set = preference_set;
rt->lifetime = lifetime;
@@ -501,17 +491,17 @@ radv_rt_notify(struct proto *P, rtable *tbl UNUSED, net *n, rte *new, rte *old U
else
{
/* Withdraw */
- rt = fib_find(&p->routes, &n->n.prefix, n->n.pxlen);
+ rt = fib_find(&p->routes, n->n.addr);
if (!rt || !rt->valid)
return;
/* Invalidate the route */
rt->valid = 0;
- rt->changed = now;
+ rt->changed = current_time();
/* Invalidated route will be pruned eventually */
- bird_clock_t expires = rt->changed + cf->max_linger_time;
+ btime expires = rt->changed + cf->max_linger_time S;
p->prune_time = MIN(p->prune_time, expires);
}
@@ -526,8 +516,9 @@ static void
radv_prune_routes(struct radv_proto *p)
{
struct radv_config *cf = (struct radv_config *) (p->p.cf);
- bird_clock_t next = TIME_INFINITY;
- bird_clock_t expires = 0;
+ btime now = current_time();
+ btime next = TIME_INFINITY;
+ btime expires = 0;
/* Should not happen */
if (!p->fib_up)
@@ -537,26 +528,24 @@ radv_prune_routes(struct radv_proto *p)
FIB_ITERATE_INIT(&fit, &p->routes);
again:
- FIB_ITERATE_START(&p->routes, &fit, node)
+ FIB_ITERATE_START(&p->routes, &fit, struct radv_route, rt)
{
- struct radv_route *rt = (void *) node;
-
if (!rt->valid)
{
- expires = rt->changed + cf->max_linger_time;
+ expires = rt->changed + cf->max_linger_time S;
/* Delete expired nodes */
if (expires <= now)
{
- FIB_ITERATE_PUT(&fit, node);
- fib_delete(&p->routes, node);
+ FIB_ITERATE_PUT(&fit);
+ fib_delete(&p->routes, rt);
goto again;
}
else
next = MIN(next, expires);
}
}
- FIB_ITERATE_END(node);
+ FIB_ITERATE_END;
p->prune_time = next;
}
@@ -566,19 +555,30 @@ radv_check_active(struct radv_proto *p)
{
struct radv_config *cf = (struct radv_config *) (p->p.cf);
- if (! cf->trigger_valid)
+ if (!radv_trigger_valid(cf))
return 1;
- return rt_examine(p->p.table, cf->trigger_prefix, cf->trigger_pxlen,
- &(p->p), p->p.cf->out_filter);
+ struct channel *c = p->p.main_channel;
+ return rt_examine(c->table, &cf->trigger, &p->p, c->out_filter);
+}
+
+static void
+radv_postconfig(struct proto_config *CF)
+{
+ // struct radv_config *cf = (void *) CF;
+
+ /* Define default channel */
+ if (EMPTY_LIST(CF->channels))
+ channel_config_new(NULL, net_label[NET_IP6], NET_IP6, CF);
}
static struct proto *
-radv_init(struct proto_config *c)
+radv_init(struct proto_config *CF)
{
- struct proto *P = proto_new(c, sizeof(struct radv_proto));
+ struct proto *P = proto_new(CF);
+
+ P->main_channel = proto_add_channel(P, proto_cf_main_channel(CF));
- P->accept_ra_types = RA_OPTIMAL;
P->import_control = radv_import_control;
P->rt_notify = radv_rt_notify;
P->if_notify = radv_if_notify;
@@ -594,7 +594,8 @@ radv_set_fib(struct radv_proto *p, int up)
return;
if (up)
- fib_init(&p->routes, p->p.pool, sizeof(struct radv_route), 4, NULL);
+ fib_init(&p->routes, p->p.pool, NET_IP6, sizeof(struct radv_route),
+ OFFSETOF(struct radv_route, n), 4, NULL);
else
fib_free(&p->routes);
@@ -610,7 +611,7 @@ radv_start(struct proto *P)
init_list(&(p->iface_list));
p->valid = 1;
- p->active = !cf->trigger_valid;
+ p->active = !radv_trigger_valid(cf);
p->fib_up = 0;
radv_set_fib(p, cf->propagate_routes);
@@ -644,13 +645,16 @@ radv_shutdown(struct proto *P)
}
static int
-radv_reconfigure(struct proto *P, struct proto_config *c)
+radv_reconfigure(struct proto *P, struct proto_config *CF)
{
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;
+ struct radv_config *new = (struct radv_config *) CF;
- P->cf = c; /* radv_check_active() requires proper P->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 */
p->active = radv_check_active(p);
/* Allocate or free FIB */
@@ -658,11 +662,22 @@ radv_reconfigure(struct proto *P, struct proto_config *c)
/* We started to accept routes so we need to refeed them */
if (!old->propagate_routes && new->propagate_routes)
- proto_request_feeding(&p->p);
+ channel_request_feeding(p->p.main_channel);
struct iface *iface;
WALK_LIST(iface, iface_list)
{
+ if (!(iface->flags & IF_UP))
+ continue;
+
+ /* Ignore non-multicast ifaces */
+ if (!(iface->flags & IF_MULTICAST))
+ continue;
+
+ /* Ignore ifaces without link-local address */
+ if (!iface->llv6)
+ continue;
+
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);
@@ -748,7 +763,10 @@ struct protocol proto_radv = {
.name = "RAdv",
.template = "radv%d",
.attr_class = EAP_RADV,
+ .channel_mask = NB_IP6,
+ .proto_size = sizeof(struct radv_proto),
.config_size = sizeof(struct radv_config),
+ .postconfig = radv_postconfig,
.init = radv_init,
.start = radv_start,
.shutdown = radv_shutdown,
diff --git a/proto/radv/radv.h b/proto/radv/radv.h
index ab081397..66f785a7 100644
--- a/proto/radv/radv.h
+++ b/proto/radv/radv.h
@@ -30,7 +30,7 @@
#define ICMPV6_RA 134
#define MAX_INITIAL_RTR_ADVERTISEMENTS 3
-#define MAX_INITIAL_RTR_ADVERT_INTERVAL 16
+#define MAX_INITIAL_RTR_ADVERT_INTERVAL (16 S_)
#define DEFAULT_MAX_RA_INT 600
#define DEFAULT_MIN_DELAY 3
@@ -50,9 +50,7 @@ struct radv_config
list rdnss_list; /* Global list of RDNSS configs (struct radv_rdnss_config) */
list dnssl_list; /* Global list of DNSSL configs (struct radv_dnssl_config) */
- ip_addr trigger_prefix; /* Prefix of a trigger route, if defined */
- u8 trigger_pxlen; /* Pxlen of a trigger route, if defined */
- u8 trigger_valid; /* Whether a trigger route is defined */
+ net_addr trigger; /* Prefix of a trigger route, if defined */
u8 propagate_routes; /* Do we propagate more specific routes (RFC 4191)? */
u32 max_linger_time; /* Maximum of interface route_linger_time */
};
@@ -91,8 +89,7 @@ struct radv_iface_config
struct radv_prefix_config
{
node n;
- ip_addr prefix;
- uint pxlen;
+ net_addr_ip6 prefix;
u8 skip; /* Do not include this prefix to RA */
u8 onlink; /* Standard options from RFC 4861 */
@@ -108,7 +105,7 @@ struct radv_rdnss_config
node n;
u32 lifetime; /* Valid if lifetime_mult is 0 */
u16 lifetime_mult; /* Lifetime specified as multiple of max_ra_int */
- ip_addr server; /* IP address of recursive DNS server */
+ ip6_addr server; /* IP address of recursive DNS server */
};
struct radv_dnssl_config
@@ -130,13 +127,14 @@ struct radv_dnssl_config
*/
struct radv_route
{
- struct fib_node n;
u32 lifetime; /* Lifetime from an attribute */
u8 lifetime_set; /* Whether lifetime is defined */
u8 preference; /* Preference of the route, RA_PREF_* */
u8 preference_set; /* Whether preference is defined */
u8 valid; /* Whethe route is valid or withdrawn */
- bird_clock_t changed; /* Last time when the route changed */
+ btime changed; /* Last time when the route changed */
+
+ struct fib_node n;
};
struct radv_proto
@@ -147,18 +145,18 @@ struct radv_proto
u8 active; /* Whether radv is active w.r.t. triggers */
u8 fib_up; /* FIB table (routes) is initialized */
struct fib routes; /* FIB table of specific routes (struct radv_route) */
- bird_clock_t prune_time; /* Next time of route table pruning */
+ btime prune_time; /* Next time of route table pruning */
};
struct radv_prefix /* One prefix we advertise */
{
node n;
- ip_addr prefix;
- u8 len;
+ net_addr_ip6 prefix;
+
u8 valid; /* Is the prefix valid? If not, we advertise it
with 0 lifetime, so clients stop using it */
u8 mark; /* A temporary mark for processing */
- bird_clock_t changed; /* Last time when the prefix changed */
+ btime changed; /* Last time when the prefix changed */
struct radv_prefix_config *cf; /* The config tied to this prefix */
};
@@ -171,14 +169,14 @@ struct radv_iface
struct ifa *addr; /* Link-local address of iface */
struct pool *pool; /* A pool for interface-specific things */
list prefixes; /* The prefixes we advertise (struct radv_prefix) */
- bird_clock_t prune_time; /* Next time of prefix list pruning */
- bird_clock_t valid_time; /* Cached packet is valid until first linger timeout */
+ btime prune_time; /* Next time of prefix list pruning */
+ btime valid_time; /* Cached packet is valid until first linger timeout */
timer *timer;
struct object_lock *lock;
sock *sk;
- bird_clock_t last; /* Time of last sending of RA */
+ btime last; /* Time of last sending of RA */
u16 plen; /* Length of prepared RA in tbuf, or 0 if not valid */
byte initial; /* How many RAs are still to be sent as initial */
};