If it interests anyone, I've also implemented the route option
described in https://tools.ietf.org/html/rfc4191#section-2.3
I find sharing patches via this mailing list particularly unwieldy,
so I've pushed my work to a git branch at
https://github.com/cqcallaw/src/tree/rfc-4191
On Wed, Aug 7, 2019 at 11:27 PM Caleb wrote:
>
> Thank you for the code and review! I've synthesized the existing patch
> and review into something that successfully advertises router
> preferences in local testing (verified w/ rdisc6). This patch does not
> implement the route information option specified in RFC 4191 section
> 2.3.
>
> diff --git a/usr.sbin/rad/frontend.c b/usr.sbin/rad/frontend.c
> index 8178b058629..4031da6b99d 100644
> --- a/usr.sbin/rad/frontend.c
> +++ b/usr.sbin/rad/frontend.c
> @@ -411,7 +411,7 @@ frontend_dispatch_main(int fd, short event, void *bula)
> ra_prefix_conf))
>fatalx("%s: IMSG_RECONF_RA_PREFIX wrong "
> "length: %lu", __func__,
> -IMSG_DATA_SIZE(imsg));
> +IMSG_DATA_SIZE(imsg));
>if ((ra_prefix_conf = malloc(sizeof(struct
> ra_prefix_conf))) == NULL)
>fatal(NULL);
> @@ -1023,6 +1023,18 @@ build_packet(struct ra_iface *ra_iface)
>ra->nd_ra_router_lifetime =
> htons(ra_options_conf->router_lifetime);
>}
> +
> + /* add router preference flags */
> + if (ra_options_conf->preference == ND_RA_FLAG_RTPREF_RSV) {
> + fatalx("Invalid router preference found during RA packet
> construction.");
> + }
> +
> + if (ra_options_conf->router_lifetime == 0) {
> + log_debug("Router lifetime set to zero; ignoring router
> preference per https://tools.ietf.org/html/rfc4191#section-2.2";);
> + } else {
> + ra->nd_ra_flags_reserved |= ra_options_conf->preference;
> + }
> +
>ra->nd_ra_reachable = htonl(ra_options_conf->reachable_time);
>ra->nd_ra_retransmit = htonl(ra_options_conf->retrans_timer);
>p += sizeof(*ra);
> diff --git a/usr.sbin/rad/parse.y b/usr.sbin/rad/parse.y
> index 004e5e22f92..74480148246 100644
> --- a/usr.sbin/rad/parse.y
> +++ b/usr.sbin/rad/parse.y
> @@ -32,6 +32,7 @@
> #include
> #include
> +#include
> #include
> #include
> @@ -117,10 +118,12 @@ typedef struct {
> %token CONFIGURATION OTHER LIFETIME REACHABLE TIME RETRANS TIMER
> %token AUTO PREFIX VALID PREFERRED LIFETIME ONLINK AUTONOMOUS
> %token ADDRESS_CONFIGURATION DNS NAMESERVER SEARCH MTU
> +%token PREFERENCE LOW MEDIUM HIGH
> %token STRING
> %token NUMBER
> %typeyesno
> +%typepreference
> %typestring
> %%
> @@ -166,6 +169,11 @@ yesno : YES { $$ = 1; }
>| NO{ $$ = 0; }
>;
> +preference : LOW { $$ = ND_RA_FLAG_RTPREF_LOW; }
> + | MEDIUM { $$ = ND_RA_FLAG_RTPREF_MEDIUM; }
> + | HIGH { $$ = ND_RA_FLAG_RTPREF_HIGH; }
> + ;
> +
> varset : STRING '=' string {
>char *s = $1;
>if (cmd_opts & OPT_VERBOSE)
> @@ -213,6 +221,9 @@ ra_opt_block: DEFAULT ROUTER yesno {
>| MTU NUMBER {
>ra_options->mtu = $2;
>}
> + | PREFERENCE preference {
> + ra_options->preference = $2;
> + }
>| DNS dns_block
>;
> @@ -426,16 +437,20 @@ lookup(char *s)
>{"default", DEFAULT},
>{"dns", DNS},
>{"hop", HOP},
> + {"high",HIGH},
>{"include", INCLUDE},
>{"interface", RA_IFACE},
>{"lifetime",LIFETIME},
>{"limit", LIMIT},
> + {"low", LOW},
>{"managed", MANAGED},
> + {"medium", MEDIUM},
>{"mtu", MTU},
>{"nameserver", NAMESERVER},
>{"no", NO},
>{"on-link", ONLINK},
>{"other", OTHER},
> + {"preference", PREFERENCE},
>{"preferred", PREFERRED},
>{"prefix", PREFIX},
>{"reachable", REACHABLE},
> diff --git a/usr.sbin/rad/printconf.c b/usr.sbin/rad/printconf.c
> index d42890da518..c2173d2142f 100644
> --- a/usr.sbin/rad/printconf.c
> +++ b/usr.sbin/rad/printconf.c
> @@ -26,6 +26,7 @@
> #include
> #include
> +#include
> #include
> #include
> @@ -34,6 +35,7 @@
> #include "rad.h"
> const char*yesno(int);
> +const char*preference(int);
> void print_ra_options(const char*, const struct ra_options_conf*);
> void print_prefix_options(const char*, const struct ra_prefix_conf*);
> @@ -42,6 +44,20 @@ yesno(int flag)
> {
>return flag ? "yes" : "no";
> }
> +const char*
> +preference(int p)
> +{
> + switch (p) {
> + case ND_RA_FLAG_RTPREF_LOW:
> + return "low";
> + case ND_RA_FLAG_RTPREF_MEDIUM:
> + return "medium";
> + case ND_RA_FLAG_RTPREF_HIGH:
> + return "high";
> + default:
> + return "invalid";
> + }
> +}
> void
> print_ra_options(const char *indent, const struct ra_options_conf *ra