diff options
Diffstat (limited to 'proto/radv')
-rw-r--r-- | proto/radv/Makefile | 9 | ||||
-rw-r--r-- | proto/radv/config.Y | 35 | ||||
-rw-r--r-- | proto/radv/packets.c | 21 | ||||
-rw-r--r-- | proto/radv/radv.c | 166 | ||||
-rw-r--r-- | proto/radv/radv.h | 21 |
5 files changed, 130 insertions, 122 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 0ff84aeb..0e43c237 100644 --- a/proto/radv/config.Y +++ b/proto/radv/config.Y @@ -41,6 +41,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); @@ -49,15 +50,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; } ; radv_proto_opts: @@ -94,15 +92,15 @@ 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"); } - | LINGER TIME expr { RADV_IFACE->linger_time = $3; if (($3 < 0) || ($3 > 3600)) cf_error("Linger time must be in range 0-3600"); } - | 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; } + | LINGER TIME expr { RADV_IFACE->linger_time = $3; if ($3 > 3600) cf_error("Linger time must be in range 0-3600"); } + | 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; } | DEFAULT PREFERENCE radv_preference { RADV_IFACE->default_preference = $3; } | PREFIX radv_prefix { add_tail(&RADV_IFACE->pref_list, NODE this_radv_prefix); } @@ -129,7 +127,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"); @@ -150,11 +148,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; @@ -168,13 +165,11 @@ radv_prefix_item: | AUTONOMOUS bool { RADV_PREFIX->autonomous = $2; } | VALID LIFETIME expr radv_sensitive { RADV_PREFIX->valid_lifetime = $3; - if ($3 < 0) cf_error("Valid lifetime must be 0 or positive"); - 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 ($3 < 0) cf_error("Preferred lifetime must be 0 or positive"); - if ($4 != -1) RADV_PREFIX->preferred_lifetime_sensitive = $4; + if ($4 != (uint) -1) RADV_PREFIX->preferred_lifetime_sensitive = $4; } ; diff --git a/proto/radv/packets.c b/proto/radv/packets.c index 8a301854..7c148b7d 100644 --- a/proto/radv/packets.c +++ b/proto/radv/packets.c @@ -38,7 +38,7 @@ struct radv_opt_prefix u32 valid_lifetime; u32 preferred_lifetime; u32 reserved; - ip_addr prefix; + ip6_addr prefix; }; #define OPT_PX_ONLINK 0x80 @@ -58,7 +58,7 @@ struct radv_opt_rdnss u8 length; u16 reserved; u32 lifetime; - ip_addr servers[]; + ip6_addr servers[]; }; struct radv_opt_dnssl @@ -79,7 +79,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) @@ -100,8 +100,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); @@ -206,10 +205,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) { @@ -221,7 +220,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) ? @@ -229,8 +228,7 @@ 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); return 0; @@ -334,7 +332,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) @@ -386,6 +384,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 c53a0a95..e9140115 100644 --- a/proto/radv/radv.c +++ b/proto/radv/radv.c @@ -58,23 +58,24 @@ radv_timer(timer *tm) * This sets the timer, but we replace it just at the end of this function * (replacing a timer is fine). */ - if (ifa->prefix_expires && (ifa->prefix_expires <= now)) + if (ifa->prefix_expires && (ifa->prefix_expires <= current_time())) radv_iface_notify(ifa, RA_EV_GC); radv_send_ra(ifa, 0); /* 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); + ifa->last = current_time(); + 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 = { @@ -89,21 +90,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; @@ -128,7 +126,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; @@ -136,7 +139,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; @@ -144,12 +147,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); } @@ -167,15 +169,16 @@ radv_prepare_prefixes(struct radv_iface *ifa) * dropped just yet). If something is dead and rots there for long enough, * clean it up. */ - bird_clock_t expires = now + cf->linger_time; - bird_clock_t expires_min = 0; + btime now_ = current_time(); + btime expires = now_ + cf->linger_time S; + btime expires_min = 0; struct radv_prefix *next; WALK_LIST_DELSAFE(pfx, next, ifa->prefixes) { if (pfx->alive && !pfx->mark) { - RADV_TRACE(D_EVENTS, "Marking prefix %I/$d on %s as dead", - pfx->prefix, pfx->len, ifa->iface->name); + RADV_TRACE(D_EVENTS, "Marking prefix %N on %s as dead", + pfx->prefix, ifa->iface->name); pfx->alive = 0; pfx->expires = expires; @@ -184,10 +187,10 @@ radv_prepare_prefixes(struct radv_iface *ifa) if (!pfx->alive) { - if (pfx->expires <= now) + if (pfx->expires <= now_) { - RADV_TRACE(D_EVENTS, "Removing prefix %I/%d on %s", - pfx->prefix, pfx->len, ifa->iface->name); + RADV_TRACE(D_EVENTS, "Removing prefix %N on %s", + pfx->prefix, ifa->iface->name); rem_node(NODE pfx); mb_free(pfx); @@ -232,13 +235,8 @@ radv_iface_notify(struct radv_iface *ifa, int event) radv_prepare_prefixes(ifa); /* 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 @@ -278,17 +276,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) { @@ -302,23 +289,12 @@ 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); 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; @@ -353,8 +329,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); @@ -393,11 +376,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 @@ -413,7 +401,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 UNUSED) +radv_rt_notify(struct proto *P, struct channel *ch UNUSED, net *n, rte *new, rte *old UNUSED, ea_list *attrs UNUSED) { struct radv_proto *p = (struct radv_proto *) P; struct radv_config *cf = (struct radv_config *) (P->cf); @@ -440,19 +428,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_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; @@ -468,7 +467,7 @@ radv_start(struct proto *P) struct radv_config *cf = (struct radv_config *) (P->cf); init_list(&(p->iface_list)); - p->active = !cf->trigger_valid; + p->active = !radv_trigger_valid(cf); return PS_UP; } @@ -493,11 +492,11 @@ 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; /* * The question is why there is a reconfigure function for RAdv if @@ -507,12 +506,26 @@ 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 */ + 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); 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); @@ -564,7 +577,10 @@ radv_get_status(struct proto *P, byte *buf) struct protocol proto_radv = { .name = "RAdv", .template = "radv%d", + .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 60b9980f..4672e3b2 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 @@ -51,9 +51,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 */ }; struct radv_iface_config @@ -87,8 +85,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 */ @@ -104,7 +101,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 @@ -128,12 +125,12 @@ struct radv_proto struct radv_prefix /* One prefix we advertise */ { node n; - ip_addr prefix; - u8 len; + net_addr_ip6 prefix; + u8 alive; /* Is the prefix alive? If not, we advertise it with 0 lifetime, so clients stop using it */ u8 mark; /* A temporary mark for processing */ - bird_clock_t expires; /* The time when we drop this prefix from + btime expires; /* The time when we drop this prefix from advertising. It is valid only if !alive. */ struct radv_prefix_config *cf; /* The config tied to this prefix */ }; @@ -147,13 +144,13 @@ 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 prefix_expires; /* When the soonest prefix expires (0 = none dead) */ + btime prefix_expires; /* When the soonest prefix expires (0 = none dead) */ 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 */ }; |