How do I publish default router preferences using rad?

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

How do I publish default router preferences using rad?

Caleb Callaway
How do I publish default router preferences as defined in RFC 4191
(https://tools.ietf.org/html/rfc4191) using rad in OpenBSD 6.5?
I've read the friendly rad.conf man page
(https://man.openbsd.org/rad.conf.5) and scanned the source
(https://github.com/openbsd/src/tree/master/usr.sbin/rad) with no
success.

Thanks,
-Caleb

Reply | Threaded
Open this post in threaded view
|

Re: How do I publish default router preferences using rad?

Sebastian Benoit
Caleb([hidden email]) on 2019.08.06 08:05:48 -0700:
> How do I publish default router preferences as defined in RFC 4191
> (https://tools.ietf.org/html/rfc4191) using rad in OpenBSD 6.5?
> I've read the friendly rad.conf man page
> (https://man.openbsd.org/rad.conf.5) and scanned the source
> (https://github.com/openbsd/src/tree/master/usr.sbin/rad) with no
> success.

You can't, because it was not implemented.

That is, until now.

I wrote a patch, which you can test if you like. It's completly untested
though.


diff --git usr.sbin/rad/frontend.c usr.sbin/rad/frontend.c
index 8178b058629..75723797fcf 100644
--- usr.sbin/rad/frontend.c
+++ usr.sbin/rad/frontend.c
@@ -1016,6 +1016,8 @@ build_packet(struct ra_iface *ra_iface)
  ra->nd_ra_flags_reserved |= ND_RA_FLAG_MANAGED;
  if (ra_options_conf->o_flag)
  ra->nd_ra_flags_reserved |= ND_RA_FLAG_OTHER;
+ ra->nd_ra_flags_reserved |=
+    ra_options_conf->preference;
  if (ra_iface->removed)
  /* tell clients that we are no longer a default router */
  ra->nd_ra_router_lifetime = 0;
@@ -1048,6 +1050,8 @@ build_packet(struct ra_iface *ra_iface)
  if (ra_prefix_conf->aflag)
  ndopt_pi->nd_opt_pi_flags_reserved |=
     ND_OPT_PI_FLAG_AUTO;
+ ndopt_pi->nd_opt_pi_flags_reserved |=
+    ra_prefix_conf->preference;
  ndopt_pi->nd_opt_pi_valid_time = htonl(ra_prefix_conf->vltime);
  ndopt_pi->nd_opt_pi_preferred_time =
     htonl(ra_prefix_conf->pltime);
diff --git usr.sbin/rad/parse.y usr.sbin/rad/parse.y
index 004e5e22f92..b004ab37356 100644
--- usr.sbin/rad/parse.y
+++ usr.sbin/rad/parse.y
@@ -106,6 +106,7 @@ typedef struct {
  union {
  int64_t number;
  char *string;
+ short pref;
  } v;
  int lineno;
 } YYSTYPE;
@@ -117,11 +118,13 @@ 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 <v.string> STRING
 %token <v.number> NUMBER
 %type <v.number> yesno
 %type <v.string> string
+%type <v.pref> preftype
 
 %%
 
@@ -213,6 +216,9 @@ ra_opt_block : DEFAULT ROUTER yesno {
  | MTU NUMBER {
  ra_options->mtu = $2;
  }
+ | PREFERENCE preftype {
+ ra_options->preference = $2;
+ }
  | DNS dns_block
  ;
 
@@ -298,6 +304,19 @@ ra_prefixoptsl : VALID LIFETIME NUMBER {
  | AUTONOMOUS ADDRESS_CONFIGURATION yesno {
  ra_prefix_conf->aflag = $3;
  }
+ | PREFERENCE preftype {
+ ra_prefix_conf->preference = $2;
+ }
+ ;
+preftype : LOW {
+ $$ = RA_PREFIXOPT_PREF_LOW;
+ }
+ | MEDIUM {
+ $$ = RA_PREFIXOPT_PREF_MEDIUM;
+ }
+ | HIGH {
+ $$ = RA_PREFIXOPT_PREF_HIGH;
+ }
  ;
 dns_block : '{' optnl dnsopts_l '}'
  | '{' optnl '}'
@@ -425,17 +444,21 @@ lookup(char *s)
  {"configuration", CONFIGURATION},
  {"default", DEFAULT},
  {"dns", DNS},
+ {"high", HIGH},
  {"hop", HOP},
  {"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 usr.sbin/rad/printconf.c usr.sbin/rad/printconf.c
index d42890da518..e063daaa19f 100644
--- usr.sbin/rad/printconf.c
+++ usr.sbin/rad/printconf.c
@@ -34,6 +34,7 @@
 #include "rad.h"
 
 const char* yesno(int);
+const char* preference(short);
 void print_ra_options(const char*, const struct ra_options_conf*);
 void print_prefix_options(const char*, const struct ra_prefix_conf*);
 
@@ -43,6 +44,21 @@ yesno(int flag)
  return flag ? "yes" : "no";
 }
 
+const char*
+preference(short p)
+{
+ switch (p) {
+ case RA_PREFIXOPT_PREF_LOW:
+ return "low";
+ case RA_PREFIXOPT_PREF_MEDIUM:
+ return "medium";
+ case RA_PREFIXOPT_PREF_HIGH:
+ return "high";
+ default:
+ return "invalid";
+ }
+}
+
 void
 print_ra_options(const char *indent, const struct ra_options_conf *ra_options)
 {
@@ -60,6 +76,9 @@ print_ra_options(const char *indent, const struct ra_options_conf *ra_options)
  printf("%sretrans timer %u\n", indent, ra_options->retrans_timer);
  if (ra_options->mtu > 0)
  printf("%smtu %u\n", indent, ra_options->mtu);
+ if (ra_options->preference > 0)
+ printf("%spreference %s\n", indent,
+    preference(ra_options->preference));
 
  if (!SIMPLEQ_EMPTY(&ra_options->ra_rdnss_list) ||
     !SIMPLEQ_EMPTY(&ra_options->ra_dnssl_list)) {
@@ -95,6 +114,8 @@ print_prefix_options(const char *indent, const struct ra_prefix_conf
  printf("%son-link %s\n", indent, yesno(ra_prefix_conf->lflag));
  printf("%sautonomous address-configuration %s\n", indent,
     yesno(ra_prefix_conf->aflag));
+ printf("%spreference %s\n", indent,
+    preference(ra_prefix_conf->preference));
 }
 
 void
diff --git usr.sbin/rad/rad.conf.5 usr.sbin/rad/rad.conf.5
index f651a715d1a..888a8f79b76 100644
--- usr.sbin/rad/rad.conf.5
+++ usr.sbin/rad/rad.conf.5
@@ -107,6 +107,11 @@ The default is 1800 seconds.
 .\" XXX
 .\" .It Ic retrans timer Ar number
 .\" XXX
+.It Ic preference Pq Ic low Ns | Ns Ic medium Ns | Ns Ic high
+Specify the router preference that is communicated to hosts through
+router advertisements.
+It can be used to communicate a prefered default router to IPv6 hosts.
+The default is medium.
 .El
 .Sh INTERFACES
 A list of interfaces or interface groups to send advertisments on:
@@ -147,6 +152,9 @@ The default is 604800.
 The valid lifetime (vltime) in seconds for addresses generated from this
 prefix.
 The default is 2592000.
+.It Ic preference Pq Ic low Ns | Ns Ic medium Ns | Ns Ic high
+The preference of the prefix is low, medium or high.
+The default is medium.
 .El
 .Sh FILES
 .Bl -tag -width "/etc/rad.conf" -compact
diff --git usr.sbin/rad/rad.h usr.sbin/rad/rad.h
index 2bbf7c8ed5c..9508783da2e 100644
--- usr.sbin/rad/rad.h
+++ usr.sbin/rad/rad.h
@@ -93,6 +93,7 @@ struct ra_options_conf {
  int m_flag; /* managed address conf flag */
  int o_flag; /* other conf flag */
  int router_lifetime; /* default router lifetime */
+ short preference; /* rfc4191 def. router pref. */
  uint32_t reachable_time;
  uint32_t retrans_timer;
  uint32_t mtu;
@@ -112,8 +113,17 @@ struct ra_prefix_conf {
  uint32_t pltime; /* prefered lifetime */
  int lflag; /* on-link flag*/
  int aflag; /* autonom. addr flag */
+ short preference; /* preference rfc4191 */
 };
 
+/*
+  RFC4191 preference values, in the middle of the 8bit reserved field.
+  01 High, 00 Medium (default),  11 Low, 10 Reserved - MUST NOT be sent
+*/
+#define RA_PREFIXOPT_PREF_LOW 0x18
+#define RA_PREFIXOPT_PREF_MEDIUM 0x00
+#define RA_PREFIXOPT_PREF_HIGH 0x08
+
 struct ra_iface_conf {
  SIMPLEQ_ENTRY(ra_iface_conf) entry;
  struct ra_options_conf ra_options;

Reply | Threaded
Open this post in threaded view
|

Re: How do I publish default router preferences using rad?

Florian Obser-2
On Tue, Aug 06, 2019 at 11:17:04PM +0200, Sebastian Benoit wrote:

> Caleb([hidden email]) on 2019.08.06 08:05:48 -0700:
> > How do I publish default router preferences as defined in RFC 4191
> > (https://tools.ietf.org/html/rfc4191) using rad in OpenBSD 6.5?
> > I've read the friendly rad.conf man page
> > (https://man.openbsd.org/rad.conf.5) and scanned the source
> > (https://github.com/openbsd/src/tree/master/usr.sbin/rad) with no
> > success.
>
> You can't, because it was not implemented.
>
> That is, until now.
>
> I wrote a patch, which you can test if you like. It's completly untested
> though.
>

needs more yak shaving

>
> diff --git usr.sbin/rad/frontend.c usr.sbin/rad/frontend.c
> index 8178b058629..75723797fcf 100644
> --- usr.sbin/rad/frontend.c
> +++ usr.sbin/rad/frontend.c
> @@ -1016,6 +1016,8 @@ build_packet(struct ra_iface *ra_iface)
>   ra->nd_ra_flags_reserved |= ND_RA_FLAG_MANAGED;
>   if (ra_options_conf->o_flag)
>   ra->nd_ra_flags_reserved |= ND_RA_FLAG_OTHER;
> + ra->nd_ra_flags_reserved |=
> +    ra_options_conf->preference;
>   if (ra_iface->removed)
>   /* tell clients that we are no longer a default router */
>   ra->nd_ra_router_lifetime = 0;
> @@ -1048,6 +1050,8 @@ build_packet(struct ra_iface *ra_iface)
>   if (ra_prefix_conf->aflag)
>   ndopt_pi->nd_opt_pi_flags_reserved |=
>      ND_OPT_PI_FLAG_AUTO;
> + ndopt_pi->nd_opt_pi_flags_reserved |=
> +    ra_prefix_conf->preference;

This is a prefix information option (type 3) not a route information option (type 24).
Option 3 does not have a preference.

>   ndopt_pi->nd_opt_pi_valid_time = htonl(ra_prefix_conf->vltime);
>   ndopt_pi->nd_opt_pi_preferred_time =
>      htonl(ra_prefix_conf->pltime);
> diff --git usr.sbin/rad/parse.y usr.sbin/rad/parse.y
> index 004e5e22f92..b004ab37356 100644
> --- usr.sbin/rad/parse.y
> +++ usr.sbin/rad/parse.y
> @@ -106,6 +106,7 @@ typedef struct {
>   union {
>   int64_t number;
>   char *string;
> + short pref;

eek, just treat it as a number?

>   } v;
>   int lineno;
>  } YYSTYPE;
> @@ -117,11 +118,13 @@ 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 <v.string> STRING
>  %token <v.number> NUMBER
>  %type <v.number> yesno
>  %type <v.string> string
> +%type <v.pref> preftype
>  
>  %%
>  
> @@ -213,6 +216,9 @@ ra_opt_block : DEFAULT ROUTER yesno {
>   | MTU NUMBER {
>   ra_options->mtu = $2;
>   }
> + | PREFERENCE preftype {
> + ra_options->preference = $2;
> + }
>   | DNS dns_block
>   ;
>  
> @@ -298,6 +304,19 @@ ra_prefixoptsl : VALID LIFETIME NUMBER {
>   | AUTONOMOUS ADDRESS_CONFIGURATION yesno {
>   ra_prefix_conf->aflag = $3;
>   }
> + | PREFERENCE preftype {
> + ra_prefix_conf->preference = $2;
> + }
> + ;

see above, we are announcing prefix information, not route information

> +preftype : LOW {
> + $$ = RA_PREFIXOPT_PREF_LOW;
> + }
> + | MEDIUM {
> + $$ = RA_PREFIXOPT_PREF_MEDIUM;
> + }
> + | HIGH {
> + $$ = RA_PREFIXOPT_PREF_HIGH;
> + }

please use the defines from icmp6.h:

#define ND_RA_FLAG_RTPREF_HIGH  0x08    /* 00001000 */
#define ND_RA_FLAG_RTPREF_MEDIUM        0x00    /* 00000000 */
#define ND_RA_FLAG_RTPREF_LOW   0x18    /* 00011000 */
#define ND_RA_FLAG_RTPREF_RSV   0x10    /* 00010000 */


>   ;
>  dns_block : '{' optnl dnsopts_l '}'
>   | '{' optnl '}'
> @@ -425,17 +444,21 @@ lookup(char *s)
>   {"configuration", CONFIGURATION},
>   {"default", DEFAULT},
>   {"dns", DNS},
> + {"high", HIGH},
>   {"hop", HOP},
>   {"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 usr.sbin/rad/printconf.c usr.sbin/rad/printconf.c
> index d42890da518..e063daaa19f 100644
> --- usr.sbin/rad/printconf.c
> +++ usr.sbin/rad/printconf.c
> @@ -34,6 +34,7 @@
>  #include "rad.h"
>  
>  const char* yesno(int);
> +const char* preference(short);

make this an in            ^

>  void print_ra_options(const char*, const struct ra_options_conf*);
>  void print_prefix_options(const char*, const struct ra_prefix_conf*);
>  
> @@ -43,6 +44,21 @@ yesno(int flag)
>   return flag ? "yes" : "no";
>  }
>  
> +const char*
> +preference(short p)
              ^ and here

> +{
> + switch (p) {
> + case RA_PREFIXOPT_PREF_LOW:
> + return "low";
> + case RA_PREFIXOPT_PREF_MEDIUM:
> + return "medium";
> + case RA_PREFIXOPT_PREF_HIGH:
> + return "high";
> + default:
> + return "invalid";

use the defines from icmp6.h

> + }
> +}
> +
>  void
>  print_ra_options(const char *indent, const struct ra_options_conf *ra_options)
>  {
> @@ -60,6 +76,9 @@ print_ra_options(const char *indent, const struct ra_options_conf *ra_options)
>   printf("%sretrans timer %u\n", indent, ra_options->retrans_timer);
>   if (ra_options->mtu > 0)
>   printf("%smtu %u\n", indent, ra_options->mtu);
> + if (ra_options->preference > 0)

this does not work, if you set the default in the config file (medium)
it will never get printed since it's 0, but maybe that's your
intention? I'd store ND_RA_FLAG_RTPREF_RSV as default and map it to
medium when building the packet. Then you can match on it here.


> + printf("%spreference %s\n", indent,
> +    preference(ra_options->preference));
>  
>   if (!SIMPLEQ_EMPTY(&ra_options->ra_rdnss_list) ||
>      !SIMPLEQ_EMPTY(&ra_options->ra_dnssl_list)) {
> @@ -95,6 +114,8 @@ print_prefix_options(const char *indent, const struct ra_prefix_conf
>   printf("%son-link %s\n", indent, yesno(ra_prefix_conf->lflag));
>   printf("%sautonomous address-configuration %s\n", indent,
>      yesno(ra_prefix_conf->aflag));
> + printf("%spreference %s\n", indent,
> +    preference(ra_prefix_conf->preference));

Prefix Information, not Route Information

>  }
>  
>  void
> diff --git usr.sbin/rad/rad.conf.5 usr.sbin/rad/rad.conf.5
> index f651a715d1a..888a8f79b76 100644
> --- usr.sbin/rad/rad.conf.5
> +++ usr.sbin/rad/rad.conf.5
> @@ -107,6 +107,11 @@ The default is 1800 seconds.
>  .\" XXX
>  .\" .It Ic retrans timer Ar number
>  .\" XXX
> +.It Ic preference Pq Ic low Ns | Ns Ic medium Ns | Ns Ic high
> +Specify the router preference that is communicated to hosts through
> +router advertisements.
> +It can be used to communicate a prefered default router to IPv6 hosts.
> +The default is medium.
>  .El
>  .Sh INTERFACES
>  A list of interfaces or interface groups to send advertisments on:
> @@ -147,6 +152,9 @@ The default is 604800.
>  The valid lifetime (vltime) in seconds for addresses generated from this
>  prefix.
>  The default is 2592000.
> +.It Ic preference Pq Ic low Ns | Ns Ic medium Ns | Ns Ic high
> +The preference of the prefix is low, medium or high.
> +The default is medium.

Prefix Information vs. Route Informatiuon

>  .El
>  .Sh FILES
>  .Bl -tag -width "/etc/rad.conf" -compact
> diff --git usr.sbin/rad/rad.h usr.sbin/rad/rad.h
> index 2bbf7c8ed5c..9508783da2e 100644
> --- usr.sbin/rad/rad.h
> +++ usr.sbin/rad/rad.h
> @@ -93,6 +93,7 @@ struct ra_options_conf {
>   int m_flag; /* managed address conf flag */
>   int o_flag; /* other conf flag */
>   int router_lifetime; /* default router lifetime */
> + short preference; /* rfc4191 def. router pref. */

        ^ make it an int

>   uint32_t reachable_time;
>   uint32_t retrans_timer;
>   uint32_t mtu;
> @@ -112,8 +113,17 @@ struct ra_prefix_conf {
>   uint32_t pltime; /* prefered lifetime */
>   int lflag; /* on-link flag*/
>   int aflag; /* autonom. addr flag */
> + short preference; /* preference rfc4191 */


Prefix Information vs. Route Information

>  };
>  
> +/*
> +  RFC4191 preference values, in the middle of the 8bit reserved field.
> +  01 High, 00 Medium (default),  11 Low, 10 Reserved - MUST NOT be sent
> +*/
> +#define RA_PREFIXOPT_PREF_LOW 0x18
> +#define RA_PREFIXOPT_PREF_MEDIUM 0x00
> +#define RA_PREFIXOPT_PREF_HIGH 0x08
> +

see above, use the defines from icmp6.h

>  struct ra_iface_conf {
>   SIMPLEQ_ENTRY(ra_iface_conf) entry;
>   struct ra_options_conf ra_options;

--
I'm not entirely sure you are real.

Reply | Threaded
Open this post in threaded view
|

Re: How do I publish default router preferences using rad?

Caleb Callaway
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 <net/if.h>
#include <arpa/inet.h>
+#include <netinet/icmp6.h>
#include <ctype.h>
#include <err.h>
@@ -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 <v.string>  STRING
%token <v.number>  NUMBER
%type  <v.number>  yesno
+%type  <v.number>  preference
%type  <v.string>  string
%%
@@ -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 <net/if.h>
#include <arpa/inet.h>
+#include <netinet/icmp6.h>
#include <event.h>
#include <imsg.h>
@@ -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_options)
@@ -60,6 +76,9 @@ print_ra_options(const char *indent, const struct
ra_options_conf *ra_options)
   printf("%sretrans timer %u\n", indent, ra_options->retrans_timer);
   if (ra_options->mtu > 0)
       printf("%smtu %u\n", indent, ra_options->mtu);
+   if (ra_options->preference != ND_RA_FLAG_RTPREF_RSV)
+       printf("%spreference %s\n", indent,
+        preference(ra_options->preference));
   if (!SIMPLEQ_EMPTY(&ra_options->ra_rdnss_list) ||
    !SIMPLEQ_EMPTY(&ra_options->ra_dnssl_list)) {
diff --git a/usr.sbin/rad/rad.c b/usr.sbin/rad/rad.c
index 93675167b6b..cb0593f11ab 100644
--- a/usr.sbin/rad/rad.c
+++ b/usr.sbin/rad/rad.c
@@ -433,7 +433,7 @@ main_dispatch_frontend(int fd, short event, void *bula)
       case IMSG_CTL_LOG_VERBOSE:
           if (IMSG_DATA_SIZE(imsg) != sizeof(verbose))
               fatalx("%s: IMSG_CTL_LOG_VERBOSE wrong length: "
-                "%lu", __func__, IMSG_DATA_SIZE(imsg));
+                "%lu", __func__, IMSG_DATA_SIZE(imsg));
           memcpy(&verbose, imsg.data, sizeof(verbose));
           log_setverbose(verbose);
           break;
@@ -754,6 +754,7 @@ config_new_empty(void)
   xconf->ra_options.cur_hl = 0;
   xconf->ra_options.m_flag = 0;
   xconf->ra_options.o_flag = 0;
+   xconf->ra_options.preference = ND_RA_FLAG_RTPREF_MEDIUM;
   xconf->ra_options.router_lifetime = 1800;
   xconf->ra_options.reachable_time = 0;
   xconf->ra_options.retrans_timer = 0;
diff --git a/usr.sbin/rad/rad.conf.5 b/usr.sbin/rad/rad.conf.5
index f651a715d1a..b822f3d195d 100644
--- a/usr.sbin/rad/rad.conf.5
+++ b/usr.sbin/rad/rad.conf.5
@@ -107,6 +107,8 @@ The default is 1800 seconds.
.\" XXX
.\" .It Ic retrans timer Ar number
.\" XXX
+.It Ic preference Pq Ic low Ns | Ns Ic medium Ns | Ns Ic high
+Communicate router preference to clients. The default is medium.
.El
.Sh INTERFACES
A list of interfaces or interface groups to send advertisments on:
diff --git a/usr.sbin/rad/rad.h b/usr.sbin/rad/rad.h
index 2bbf7c8ed5c..cfaa5e88638 100644
--- a/usr.sbin/rad/rad.h
+++ b/usr.sbin/rad/rad.h
@@ -92,6 +92,7 @@ struct ra_options_conf {
   int     cur_hl;         /* current hop limit */
   int     m_flag;         /* managed address conf flag */
   int     o_flag;         /* other conf flag */
+   int     preference;     /* router preference (see RFC 4191 2.2) */
   int     router_lifetime;    /* default router lifetime */
   uint32_t    reachable_time;
   uint32_t    retrans_timer;


On Wed, Aug 7, 2019 at 2:04 AM Florian Obser <[hidden email]> wrote:

>
> On Tue, Aug 06, 2019 at 11:17:04PM +0200, Sebastian Benoit wrote:
> > Caleb([hidden email]) on 2019.08.06 08:05:48 -0700:
> > > How do I publish default router preferences as defined in RFC 4191
> > > (https://tools.ietf.org/html/rfc4191) using rad in OpenBSD 6.5?
> > > I've read the friendly rad.conf man page
> > > (https://man.openbsd.org/rad.conf.5) and scanned the source
> > > (https://github.com/openbsd/src/tree/master/usr.sbin/rad) with no
> > > success.
> >
> > You can't, because it was not implemented.
> >
> > That is, until now.
> >
> > I wrote a patch, which you can test if you like. It's completly untested
> > though.
> >
>
> needs more yak shaving
>
> >
> > diff --git usr.sbin/rad/frontend.c usr.sbin/rad/frontend.c
> > index 8178b058629..75723797fcf 100644
> > --- usr.sbin/rad/frontend.c
> > +++ usr.sbin/rad/frontend.c
> > @@ -1016,6 +1016,8 @@ build_packet(struct ra_iface *ra_iface)
> >               ra->nd_ra_flags_reserved |= ND_RA_FLAG_MANAGED;
> >       if (ra_options_conf->o_flag)
> >               ra->nd_ra_flags_reserved |= ND_RA_FLAG_OTHER;
> > +     ra->nd_ra_flags_reserved |=
> > +         ra_options_conf->preference;
> >       if (ra_iface->removed)
> >               /* tell clients that we are no longer a default router */
> >               ra->nd_ra_router_lifetime = 0;
> > @@ -1048,6 +1050,8 @@ build_packet(struct ra_iface *ra_iface)
> >               if (ra_prefix_conf->aflag)
> >                       ndopt_pi->nd_opt_pi_flags_reserved |=
> >                           ND_OPT_PI_FLAG_AUTO;
> > +             ndopt_pi->nd_opt_pi_flags_reserved |=
> > +                         ra_prefix_conf->preference;
>
> This is a prefix information option (type 3) not a route information option (type 24).
> Option 3 does not have a preference.
>
> >               ndopt_pi->nd_opt_pi_valid_time = htonl(ra_prefix_conf->vltime);
> >               ndopt_pi->nd_opt_pi_preferred_time =
> >                   htonl(ra_prefix_conf->pltime);
> > diff --git usr.sbin/rad/parse.y usr.sbin/rad/parse.y
> > index 004e5e22f92..b004ab37356 100644
> > --- usr.sbin/rad/parse.y
> > +++ usr.sbin/rad/parse.y
> > @@ -106,6 +106,7 @@ typedef struct {
> >       union {
> >               int64_t          number;
> >               char            *string;
> > +             short            pref;
>
> eek, just treat it as a number?
>
> >       } v;
> >       int lineno;
> >  } YYSTYPE;
> > @@ -117,11 +118,13 @@ 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       <v.string>      STRING
> >  %token       <v.number>      NUMBER
> >  %type        <v.number>      yesno
> >  %type        <v.string>      string
> > +%type        <v.pref>        preftype
> >
> >  %%
> >
> > @@ -213,6 +216,9 @@ ra_opt_block      : DEFAULT ROUTER yesno {
> >               | MTU NUMBER {
> >                       ra_options->mtu = $2;
> >               }
> > +             | PREFERENCE preftype {
> > +                     ra_options->preference = $2;
> > +             }
> >               | DNS dns_block
> >               ;
> >
> > @@ -298,6 +304,19 @@ ra_prefixoptsl   : VALID LIFETIME NUMBER {
> >               | AUTONOMOUS ADDRESS_CONFIGURATION yesno {
> >                       ra_prefix_conf->aflag = $3;
> >               }
> > +             | PREFERENCE preftype {
> > +                     ra_prefix_conf->preference = $2;
> > +             }
> > +             ;
>
> see above, we are announcing prefix information, not route information
>
> > +preftype     : LOW {
> > +                     $$ = RA_PREFIXOPT_PREF_LOW;
> > +             }
> > +             | MEDIUM {
> > +                     $$ = RA_PREFIXOPT_PREF_MEDIUM;
> > +             }
> > +             | HIGH {
> > +                     $$ = RA_PREFIXOPT_PREF_HIGH;
> > +             }
>
> please use the defines from icmp6.h:
>
> #define ND_RA_FLAG_RTPREF_HIGH  0x08    /* 00001000 */
> #define ND_RA_FLAG_RTPREF_MEDIUM        0x00    /* 00000000 */
> #define ND_RA_FLAG_RTPREF_LOW   0x18    /* 00011000 */
> #define ND_RA_FLAG_RTPREF_RSV   0x10    /* 00010000 */
>
>
> >               ;
> >  dns_block    : '{' optnl dnsopts_l '}'
> >               | '{' optnl '}'
> > @@ -425,17 +444,21 @@ lookup(char *s)
> >               {"configuration",       CONFIGURATION},
> >               {"default",             DEFAULT},
> >               {"dns",                 DNS},
> > +             {"high",                HIGH},
> >               {"hop",                 HOP},
> >               {"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 usr.sbin/rad/printconf.c usr.sbin/rad/printconf.c
> > index d42890da518..e063daaa19f 100644
> > --- usr.sbin/rad/printconf.c
> > +++ usr.sbin/rad/printconf.c
> > @@ -34,6 +34,7 @@
> >  #include "rad.h"
> >
> >  const char*  yesno(int);
> > +const char*  preference(short);
>
> make this an in            ^
>
> >  void         print_ra_options(const char*, const struct ra_options_conf*);
> >  void         print_prefix_options(const char*, const struct ra_prefix_conf*);
> >
> > @@ -43,6 +44,21 @@ yesno(int flag)
> >       return flag ? "yes" : "no";
> >  }
> >
> > +const char*
> > +preference(short p)
>               ^ and here
> > +{
> > +     switch (p) {
> > +             case RA_PREFIXOPT_PREF_LOW:
> > +                     return "low";
> > +             case RA_PREFIXOPT_PREF_MEDIUM:
> > +                     return "medium";
> > +             case RA_PREFIXOPT_PREF_HIGH:
> > +                     return "high";
> > +             default:
> > +                     return "invalid";
>
> use the defines from icmp6.h
>
> > +     }
> > +}
> > +
> >  void
> >  print_ra_options(const char *indent, const struct ra_options_conf *ra_options)
> >  {
> > @@ -60,6 +76,9 @@ print_ra_options(const char *indent, const struct ra_options_conf *ra_options)
> >       printf("%sretrans timer %u\n", indent, ra_options->retrans_timer);
> >       if (ra_options->mtu > 0)
> >               printf("%smtu %u\n", indent, ra_options->mtu);
> > +     if (ra_options->preference > 0)
>
> this does not work, if you set the default in the config file (medium)
> it will never get printed since it's 0, but maybe that's your
> intention? I'd store ND_RA_FLAG_RTPREF_RSV as default and map it to
> medium when building the packet. Then you can match on it here.
>
>
> > +             printf("%spreference %s\n", indent,
> > +                 preference(ra_options->preference));
> >
> >       if (!SIMPLEQ_EMPTY(&ra_options->ra_rdnss_list) ||
> >           !SIMPLEQ_EMPTY(&ra_options->ra_dnssl_list)) {
> > @@ -95,6 +114,8 @@ print_prefix_options(const char *indent, const struct ra_prefix_conf
> >       printf("%son-link %s\n", indent, yesno(ra_prefix_conf->lflag));
> >       printf("%sautonomous address-configuration %s\n", indent,
> >           yesno(ra_prefix_conf->aflag));
> > +     printf("%spreference %s\n", indent,
> > +         preference(ra_prefix_conf->preference));
>
> Prefix Information, not Route Information
>
> >  }
> >
> >  void
> > diff --git usr.sbin/rad/rad.conf.5 usr.sbin/rad/rad.conf.5
> > index f651a715d1a..888a8f79b76 100644
> > --- usr.sbin/rad/rad.conf.5
> > +++ usr.sbin/rad/rad.conf.5
> > @@ -107,6 +107,11 @@ The default is 1800 seconds.
> >  .\" XXX
> >  .\" .It Ic retrans timer Ar number
> >  .\" XXX
> > +.It Ic preference Pq Ic low Ns | Ns Ic medium Ns | Ns Ic high
> > +Specify the router preference that is communicated to hosts through
> > +router advertisements.
> > +It can be used to communicate a prefered default router to IPv6 hosts.
> > +The default is medium.
> >  .El
> >  .Sh INTERFACES
> >  A list of interfaces or interface groups to send advertisments on:
> > @@ -147,6 +152,9 @@ The default is 604800.
> >  The valid lifetime (vltime) in seconds for addresses generated from this
> >  prefix.
> >  The default is 2592000.
> > +.It Ic preference Pq Ic low Ns | Ns Ic medium Ns | Ns Ic high
> > +The preference of the prefix is low, medium or high.
> > +The default is medium.
>
> Prefix Information vs. Route Informatiuon
>
> >  .El
> >  .Sh FILES
> >  .Bl -tag -width "/etc/rad.conf" -compact
> > diff --git usr.sbin/rad/rad.h usr.sbin/rad/rad.h
> > index 2bbf7c8ed5c..9508783da2e 100644
> > --- usr.sbin/rad/rad.h
> > +++ usr.sbin/rad/rad.h
> > @@ -93,6 +93,7 @@ struct ra_options_conf {
> >       int             m_flag;                 /* managed address conf flag */
> >       int             o_flag;                 /* other conf flag */
> >       int             router_lifetime;        /* default router lifetime */
> > +     short           preference;             /* rfc4191 def. router pref. */
>
>         ^ make it an int
>
> >       uint32_t        reachable_time;
> >       uint32_t        retrans_timer;
> >       uint32_t        mtu;
> > @@ -112,8 +113,17 @@ struct ra_prefix_conf {
> >       uint32_t                         pltime;        /* prefered lifetime */
> >       int                              lflag;         /* on-link flag*/
> >       int                              aflag;         /* autonom. addr flag */
> > +     short                            preference;    /* preference rfc4191 */
>
>
> Prefix Information vs. Route Information
>
> >  };
> >
> > +/*
> > +  RFC4191 preference values, in the middle of the 8bit reserved field.
> > +  01 High, 00 Medium (default),  11 Low, 10 Reserved - MUST NOT be sent
> > +*/
> > +#define RA_PREFIXOPT_PREF_LOW                0x18
> > +#define RA_PREFIXOPT_PREF_MEDIUM     0x00
> > +#define RA_PREFIXOPT_PREF_HIGH               0x08
> > +
>
> see above, use the defines from icmp6.h
>
> >  struct ra_iface_conf {
> >       SIMPLEQ_ENTRY(ra_iface_conf)             entry;
> >       struct ra_options_conf                   ra_options;
>
> --
> I'm not entirely sure you are real.

Reply | Threaded
Open this post in threaded view
|

Re: How do I publish default router preferences using rad?

Caleb Callaway
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 <[hidden email]> 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 <net/if.h>
> #include <arpa/inet.h>
> +#include <netinet/icmp6.h>
> #include <ctype.h>
> #include <err.h>
> @@ -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 <v.string>  STRING
> %token <v.number>  NUMBER
> %type  <v.number>  yesno
> +%type  <v.number>  preference
> %type  <v.string>  string
> %%
> @@ -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 <net/if.h>
> #include <arpa/inet.h>
> +#include <netinet/icmp6.h>
> #include <event.h>
> #include <imsg.h>
> @@ -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_options)
> @@ -60,6 +76,9 @@ print_ra_options(const char *indent, const struct
> ra_options_conf *ra_options)
>    printf("%sretrans timer %u\n", indent, ra_options->retrans_timer);
>    if (ra_options->mtu > 0)
>        printf("%smtu %u\n", indent, ra_options->mtu);
> +   if (ra_options->preference != ND_RA_FLAG_RTPREF_RSV)
> +       printf("%spreference %s\n", indent,
> +        preference(ra_options->preference));
>    if (!SIMPLEQ_EMPTY(&ra_options->ra_rdnss_list) ||
>     !SIMPLEQ_EMPTY(&ra_options->ra_dnssl_list)) {
> diff --git a/usr.sbin/rad/rad.c b/usr.sbin/rad/rad.c
> index 93675167b6b..cb0593f11ab 100644
> --- a/usr.sbin/rad/rad.c
> +++ b/usr.sbin/rad/rad.c
> @@ -433,7 +433,7 @@ main_dispatch_frontend(int fd, short event, void *bula)
>        case IMSG_CTL_LOG_VERBOSE:
>            if (IMSG_DATA_SIZE(imsg) != sizeof(verbose))
>                fatalx("%s: IMSG_CTL_LOG_VERBOSE wrong length: "
> -                "%lu", __func__, IMSG_DATA_SIZE(imsg));
> +                "%lu", __func__, IMSG_DATA_SIZE(imsg));
>            memcpy(&verbose, imsg.data, sizeof(verbose));
>            log_setverbose(verbose);
>            break;
> @@ -754,6 +754,7 @@ config_new_empty(void)
>    xconf->ra_options.cur_hl = 0;
>    xconf->ra_options.m_flag = 0;
>    xconf->ra_options.o_flag = 0;
> +   xconf->ra_options.preference = ND_RA_FLAG_RTPREF_MEDIUM;
>    xconf->ra_options.router_lifetime = 1800;
>    xconf->ra_options.reachable_time = 0;
>    xconf->ra_options.retrans_timer = 0;
> diff --git a/usr.sbin/rad/rad.conf.5 b/usr.sbin/rad/rad.conf.5
> index f651a715d1a..b822f3d195d 100644
> --- a/usr.sbin/rad/rad.conf.5
> +++ b/usr.sbin/rad/rad.conf.5
> @@ -107,6 +107,8 @@ The default is 1800 seconds.
> .\" XXX
> .\" .It Ic retrans timer Ar number
> .\" XXX
> +.It Ic preference Pq Ic low Ns | Ns Ic medium Ns | Ns Ic high
> +Communicate router preference to clients. The default is medium.
> .El
> .Sh INTERFACES
> A list of interfaces or interface groups to send advertisments on:
> diff --git a/usr.sbin/rad/rad.h b/usr.sbin/rad/rad.h
> index 2bbf7c8ed5c..cfaa5e88638 100644
> --- a/usr.sbin/rad/rad.h
> +++ b/usr.sbin/rad/rad.h
> @@ -92,6 +92,7 @@ struct ra_options_conf {
>    int     cur_hl;         /* current hop limit */
>    int     m_flag;         /* managed address conf flag */
>    int     o_flag;         /* other conf flag */
> +   int     preference;     /* router preference (see RFC 4191 2.2) */
>    int     router_lifetime;    /* default router lifetime */
>    uint32_t    reachable_time;
>    uint32_t    retrans_timer;
>
>
> On Wed, Aug 7, 2019 at 2:04 AM Florian Obser <[hidden email]> wrote:
> >
> > On Tue, Aug 06, 2019 at 11:17:04PM +0200, Sebastian Benoit wrote:
> > > Caleb([hidden email]) on 2019.08.06 08:05:48 -0700:
> > > > How do I publish default router preferences as defined in RFC 4191
> > > > (https://tools.ietf.org/html/rfc4191) using rad in OpenBSD 6.5?
> > > > I've read the friendly rad.conf man page
> > > > (https://man.openbsd.org/rad.conf.5) and scanned the source
> > > > (https://github.com/openbsd/src/tree/master/usr.sbin/rad) with no
> > > > success.
> > >
> > > You can't, because it was not implemented.
> > >
> > > That is, until now.
> > >
> > > I wrote a patch, which you can test if you like. It's completly untested
> > > though.
> > >
> >
> > needs more yak shaving
> >
> > >
> > > diff --git usr.sbin/rad/frontend.c usr.sbin/rad/frontend.c
> > > index 8178b058629..75723797fcf 100644
> > > --- usr.sbin/rad/frontend.c
> > > +++ usr.sbin/rad/frontend.c
> > > @@ -1016,6 +1016,8 @@ build_packet(struct ra_iface *ra_iface)
> > >               ra->nd_ra_flags_reserved |= ND_RA_FLAG_MANAGED;
> > >       if (ra_options_conf->o_flag)
> > >               ra->nd_ra_flags_reserved |= ND_RA_FLAG_OTHER;
> > > +     ra->nd_ra_flags_reserved |=
> > > +         ra_options_conf->preference;
> > >       if (ra_iface->removed)
> > >               /* tell clients that we are no longer a default router */
> > >               ra->nd_ra_router_lifetime = 0;
> > > @@ -1048,6 +1050,8 @@ build_packet(struct ra_iface *ra_iface)
> > >               if (ra_prefix_conf->aflag)
> > >                       ndopt_pi->nd_opt_pi_flags_reserved |=
> > >                           ND_OPT_PI_FLAG_AUTO;
> > > +             ndopt_pi->nd_opt_pi_flags_reserved |=
> > > +                         ra_prefix_conf->preference;
> >
> > This is a prefix information option (type 3) not a route information option (type 24).
> > Option 3 does not have a preference.
> >
> > >               ndopt_pi->nd_opt_pi_valid_time = htonl(ra_prefix_conf->vltime);
> > >               ndopt_pi->nd_opt_pi_preferred_time =
> > >                   htonl(ra_prefix_conf->pltime);
> > > diff --git usr.sbin/rad/parse.y usr.sbin/rad/parse.y
> > > index 004e5e22f92..b004ab37356 100644
> > > --- usr.sbin/rad/parse.y
> > > +++ usr.sbin/rad/parse.y
> > > @@ -106,6 +106,7 @@ typedef struct {
> > >       union {
> > >               int64_t          number;
> > >               char            *string;
> > > +             short            pref;
> >
> > eek, just treat it as a number?
> >
> > >       } v;
> > >       int lineno;
> > >  } YYSTYPE;
> > > @@ -117,11 +118,13 @@ 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       <v.string>      STRING
> > >  %token       <v.number>      NUMBER
> > >  %type        <v.number>      yesno
> > >  %type        <v.string>      string
> > > +%type        <v.pref>        preftype
> > >
> > >  %%
> > >
> > > @@ -213,6 +216,9 @@ ra_opt_block      : DEFAULT ROUTER yesno {
> > >               | MTU NUMBER {
> > >                       ra_options->mtu = $2;
> > >               }
> > > +             | PREFERENCE preftype {
> > > +                     ra_options->preference = $2;
> > > +             }
> > >               | DNS dns_block
> > >               ;
> > >
> > > @@ -298,6 +304,19 @@ ra_prefixoptsl   : VALID LIFETIME NUMBER {
> > >               | AUTONOMOUS ADDRESS_CONFIGURATION yesno {
> > >                       ra_prefix_conf->aflag = $3;
> > >               }
> > > +             | PREFERENCE preftype {
> > > +                     ra_prefix_conf->preference = $2;
> > > +             }
> > > +             ;
> >
> > see above, we are announcing prefix information, not route information
> >
> > > +preftype     : LOW {
> > > +                     $$ = RA_PREFIXOPT_PREF_LOW;
> > > +             }
> > > +             | MEDIUM {
> > > +                     $$ = RA_PREFIXOPT_PREF_MEDIUM;
> > > +             }
> > > +             | HIGH {
> > > +                     $$ = RA_PREFIXOPT_PREF_HIGH;
> > > +             }
> >
> > please use the defines from icmp6.h:
> >
> > #define ND_RA_FLAG_RTPREF_HIGH  0x08    /* 00001000 */
> > #define ND_RA_FLAG_RTPREF_MEDIUM        0x00    /* 00000000 */
> > #define ND_RA_FLAG_RTPREF_LOW   0x18    /* 00011000 */
> > #define ND_RA_FLAG_RTPREF_RSV   0x10    /* 00010000 */
> >
> >
> > >               ;
> > >  dns_block    : '{' optnl dnsopts_l '}'
> > >               | '{' optnl '}'
> > > @@ -425,17 +444,21 @@ lookup(char *s)
> > >               {"configuration",       CONFIGURATION},
> > >               {"default",             DEFAULT},
> > >               {"dns",                 DNS},
> > > +             {"high",                HIGH},
> > >               {"hop",                 HOP},
> > >               {"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 usr.sbin/rad/printconf.c usr.sbin/rad/printconf.c
> > > index d42890da518..e063daaa19f 100644
> > > --- usr.sbin/rad/printconf.c
> > > +++ usr.sbin/rad/printconf.c
> > > @@ -34,6 +34,7 @@
> > >  #include "rad.h"
> > >
> > >  const char*  yesno(int);
> > > +const char*  preference(short);
> >
> > make this an in            ^
> >
> > >  void         print_ra_options(const char*, const struct ra_options_conf*);
> > >  void         print_prefix_options(const char*, const struct ra_prefix_conf*);
> > >
> > > @@ -43,6 +44,21 @@ yesno(int flag)
> > >       return flag ? "yes" : "no";
> > >  }
> > >
> > > +const char*
> > > +preference(short p)
> >               ^ and here
> > > +{
> > > +     switch (p) {
> > > +             case RA_PREFIXOPT_PREF_LOW:
> > > +                     return "low";
> > > +             case RA_PREFIXOPT_PREF_MEDIUM:
> > > +                     return "medium";
> > > +             case RA_PREFIXOPT_PREF_HIGH:
> > > +                     return "high";
> > > +             default:
> > > +                     return "invalid";
> >
> > use the defines from icmp6.h
> >
> > > +     }
> > > +}
> > > +
> > >  void
> > >  print_ra_options(const char *indent, const struct ra_options_conf *ra_options)
> > >  {
> > > @@ -60,6 +76,9 @@ print_ra_options(const char *indent, const struct ra_options_conf *ra_options)
> > >       printf("%sretrans timer %u\n", indent, ra_options->retrans_timer);
> > >       if (ra_options->mtu > 0)
> > >               printf("%smtu %u\n", indent, ra_options->mtu);
> > > +     if (ra_options->preference > 0)
> >
> > this does not work, if you set the default in the config file (medium)
> > it will never get printed since it's 0, but maybe that's your
> > intention? I'd store ND_RA_FLAG_RTPREF_RSV as default and map it to
> > medium when building the packet. Then you can match on it here.
> >
> >
> > > +             printf("%spreference %s\n", indent,
> > > +                 preference(ra_options->preference));
> > >
> > >       if (!SIMPLEQ_EMPTY(&ra_options->ra_rdnss_list) ||
> > >           !SIMPLEQ_EMPTY(&ra_options->ra_dnssl_list)) {
> > > @@ -95,6 +114,8 @@ print_prefix_options(const char *indent, const struct ra_prefix_conf
> > >       printf("%son-link %s\n", indent, yesno(ra_prefix_conf->lflag));
> > >       printf("%sautonomous address-configuration %s\n", indent,
> > >           yesno(ra_prefix_conf->aflag));
> > > +     printf("%spreference %s\n", indent,
> > > +         preference(ra_prefix_conf->preference));
> >
> > Prefix Information, not Route Information
> >
> > >  }
> > >
> > >  void
> > > diff --git usr.sbin/rad/rad.conf.5 usr.sbin/rad/rad.conf.5
> > > index f651a715d1a..888a8f79b76 100644
> > > --- usr.sbin/rad/rad.conf.5
> > > +++ usr.sbin/rad/rad.conf.5
> > > @@ -107,6 +107,11 @@ The default is 1800 seconds.
> > >  .\" XXX
> > >  .\" .It Ic retrans timer Ar number
> > >  .\" XXX
> > > +.It Ic preference Pq Ic low Ns | Ns Ic medium Ns | Ns Ic high
> > > +Specify the router preference that is communicated to hosts through
> > > +router advertisements.
> > > +It can be used to communicate a prefered default router to IPv6 hosts.
> > > +The default is medium.
> > >  .El
> > >  .Sh INTERFACES
> > >  A list of interfaces or interface groups to send advertisments on:
> > > @@ -147,6 +152,9 @@ The default is 604800.
> > >  The valid lifetime (vltime) in seconds for addresses generated from this
> > >  prefix.
> > >  The default is 2592000.
> > > +.It Ic preference Pq Ic low Ns | Ns Ic medium Ns | Ns Ic high
> > > +The preference of the prefix is low, medium or high.
> > > +The default is medium.
> >
> > Prefix Information vs. Route Informatiuon
> >
> > >  .El
> > >  .Sh FILES
> > >  .Bl -tag -width "/etc/rad.conf" -compact
> > > diff --git usr.sbin/rad/rad.h usr.sbin/rad/rad.h
> > > index 2bbf7c8ed5c..9508783da2e 100644
> > > --- usr.sbin/rad/rad.h
> > > +++ usr.sbin/rad/rad.h
> > > @@ -93,6 +93,7 @@ struct ra_options_conf {
> > >       int             m_flag;                 /* managed address conf flag */
> > >       int             o_flag;                 /* other conf flag */
> > >       int             router_lifetime;        /* default router lifetime */
> > > +     short           preference;             /* rfc4191 def. router pref. */
> >
> >         ^ make it an int
> >
> > >       uint32_t        reachable_time;
> > >       uint32_t        retrans_timer;
> > >       uint32_t        mtu;
> > > @@ -112,8 +113,17 @@ struct ra_prefix_conf {
> > >       uint32_t                         pltime;        /* prefered lifetime */
> > >       int                              lflag;         /* on-link flag*/
> > >       int                              aflag;         /* autonom. addr flag */
> > > +     short                            preference;    /* preference rfc4191 */
> >
> >
> > Prefix Information vs. Route Information
> >
> > >  };
> > >
> > > +/*
> > > +  RFC4191 preference values, in the middle of the 8bit reserved field.
> > > +  01 High, 00 Medium (default),  11 Low, 10 Reserved - MUST NOT be sent
> > > +*/
> > > +#define RA_PREFIXOPT_PREF_LOW                0x18
> > > +#define RA_PREFIXOPT_PREF_MEDIUM     0x00
> > > +#define RA_PREFIXOPT_PREF_HIGH               0x08
> > > +
> >
> > see above, use the defines from icmp6.h
> >
> > >  struct ra_iface_conf {
> > >       SIMPLEQ_ENTRY(ra_iface_conf)             entry;
> > >       struct ra_options_conf                   ra_options;
> >
> > --
> > I'm not entirely sure you are real.

Reply | Threaded
Open this post in threaded view
|

Re: How do I publish default router preferences using rad?

Florian Obser-2
I'm curious, how are you using the router preference, could you tell
us a bit more about your network topology?
Also, what clients pay attention to it and how are they using it?

Same goes for the route option, are you aware of clients using it?

Thanks,
Florian

On Sat, Aug 17, 2019 at 08:09:54PM -0700, Caleb Callaway wrote:

> 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 <[hidden email]> 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 <net/if.h>
> > #include <arpa/inet.h>
> > +#include <netinet/icmp6.h>
> > #include <ctype.h>
> > #include <err.h>
> > @@ -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 <v.string>  STRING
> > %token <v.number>  NUMBER
> > %type  <v.number>  yesno
> > +%type  <v.number>  preference
> > %type  <v.string>  string
> > %%
> > @@ -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 <net/if.h>
> > #include <arpa/inet.h>
> > +#include <netinet/icmp6.h>
> > #include <event.h>
> > #include <imsg.h>
> > @@ -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_options)
> > @@ -60,6 +76,9 @@ print_ra_options(const char *indent, const struct
> > ra_options_conf *ra_options)
> >    printf("%sretrans timer %u\n", indent, ra_options->retrans_timer);
> >    if (ra_options->mtu > 0)
> >        printf("%smtu %u\n", indent, ra_options->mtu);
> > +   if (ra_options->preference != ND_RA_FLAG_RTPREF_RSV)
> > +       printf("%spreference %s\n", indent,
> > +        preference(ra_options->preference));
> >    if (!SIMPLEQ_EMPTY(&ra_options->ra_rdnss_list) ||
> >     !SIMPLEQ_EMPTY(&ra_options->ra_dnssl_list)) {
> > diff --git a/usr.sbin/rad/rad.c b/usr.sbin/rad/rad.c
> > index 93675167b6b..cb0593f11ab 100644
> > --- a/usr.sbin/rad/rad.c
> > +++ b/usr.sbin/rad/rad.c
> > @@ -433,7 +433,7 @@ main_dispatch_frontend(int fd, short event, void *bula)
> >        case IMSG_CTL_LOG_VERBOSE:
> >            if (IMSG_DATA_SIZE(imsg) != sizeof(verbose))
> >                fatalx("%s: IMSG_CTL_LOG_VERBOSE wrong length: "
> > -                "%lu", __func__, IMSG_DATA_SIZE(imsg));
> > +                "%lu", __func__, IMSG_DATA_SIZE(imsg));
> >            memcpy(&verbose, imsg.data, sizeof(verbose));
> >            log_setverbose(verbose);
> >            break;
> > @@ -754,6 +754,7 @@ config_new_empty(void)
> >    xconf->ra_options.cur_hl = 0;
> >    xconf->ra_options.m_flag = 0;
> >    xconf->ra_options.o_flag = 0;
> > +   xconf->ra_options.preference = ND_RA_FLAG_RTPREF_MEDIUM;
> >    xconf->ra_options.router_lifetime = 1800;
> >    xconf->ra_options.reachable_time = 0;
> >    xconf->ra_options.retrans_timer = 0;
> > diff --git a/usr.sbin/rad/rad.conf.5 b/usr.sbin/rad/rad.conf.5
> > index f651a715d1a..b822f3d195d 100644
> > --- a/usr.sbin/rad/rad.conf.5
> > +++ b/usr.sbin/rad/rad.conf.5
> > @@ -107,6 +107,8 @@ The default is 1800 seconds.
> > .\" XXX
> > .\" .It Ic retrans timer Ar number
> > .\" XXX
> > +.It Ic preference Pq Ic low Ns | Ns Ic medium Ns | Ns Ic high
> > +Communicate router preference to clients. The default is medium.
> > .El
> > .Sh INTERFACES
> > A list of interfaces or interface groups to send advertisments on:
> > diff --git a/usr.sbin/rad/rad.h b/usr.sbin/rad/rad.h
> > index 2bbf7c8ed5c..cfaa5e88638 100644
> > --- a/usr.sbin/rad/rad.h
> > +++ b/usr.sbin/rad/rad.h
> > @@ -92,6 +92,7 @@ struct ra_options_conf {
> >    int     cur_hl;         /* current hop limit */
> >    int     m_flag;         /* managed address conf flag */
> >    int     o_flag;         /* other conf flag */
> > +   int     preference;     /* router preference (see RFC 4191 2.2) */
> >    int     router_lifetime;    /* default router lifetime */
> >    uint32_t    reachable_time;
> >    uint32_t    retrans_timer;
> >
> >
> > On Wed, Aug 7, 2019 at 2:04 AM Florian Obser <[hidden email]> wrote:
> > >
> > > On Tue, Aug 06, 2019 at 11:17:04PM +0200, Sebastian Benoit wrote:
> > > > Caleb([hidden email]) on 2019.08.06 08:05:48 -0700:
> > > > > How do I publish default router preferences as defined in RFC 4191
> > > > > (https://tools.ietf.org/html/rfc4191) using rad in OpenBSD 6.5?
> > > > > I've read the friendly rad.conf man page
> > > > > (https://man.openbsd.org/rad.conf.5) and scanned the source
> > > > > (https://github.com/openbsd/src/tree/master/usr.sbin/rad) with no
> > > > > success.
> > > >
> > > > You can't, because it was not implemented.
> > > >
> > > > That is, until now.
> > > >
> > > > I wrote a patch, which you can test if you like. It's completly untested
> > > > though.
> > > >
> > >
> > > needs more yak shaving
> > >
> > > >
> > > > diff --git usr.sbin/rad/frontend.c usr.sbin/rad/frontend.c
> > > > index 8178b058629..75723797fcf 100644
> > > > --- usr.sbin/rad/frontend.c
> > > > +++ usr.sbin/rad/frontend.c
> > > > @@ -1016,6 +1016,8 @@ build_packet(struct ra_iface *ra_iface)
> > > >               ra->nd_ra_flags_reserved |= ND_RA_FLAG_MANAGED;
> > > >       if (ra_options_conf->o_flag)
> > > >               ra->nd_ra_flags_reserved |= ND_RA_FLAG_OTHER;
> > > > +     ra->nd_ra_flags_reserved |=
> > > > +         ra_options_conf->preference;
> > > >       if (ra_iface->removed)
> > > >               /* tell clients that we are no longer a default router */
> > > >               ra->nd_ra_router_lifetime = 0;
> > > > @@ -1048,6 +1050,8 @@ build_packet(struct ra_iface *ra_iface)
> > > >               if (ra_prefix_conf->aflag)
> > > >                       ndopt_pi->nd_opt_pi_flags_reserved |=
> > > >                           ND_OPT_PI_FLAG_AUTO;
> > > > +             ndopt_pi->nd_opt_pi_flags_reserved |=
> > > > +                         ra_prefix_conf->preference;
> > >
> > > This is a prefix information option (type 3) not a route information option (type 24).
> > > Option 3 does not have a preference.
> > >
> > > >               ndopt_pi->nd_opt_pi_valid_time = htonl(ra_prefix_conf->vltime);
> > > >               ndopt_pi->nd_opt_pi_preferred_time =
> > > >                   htonl(ra_prefix_conf->pltime);
> > > > diff --git usr.sbin/rad/parse.y usr.sbin/rad/parse.y
> > > > index 004e5e22f92..b004ab37356 100644
> > > > --- usr.sbin/rad/parse.y
> > > > +++ usr.sbin/rad/parse.y
> > > > @@ -106,6 +106,7 @@ typedef struct {
> > > >       union {
> > > >               int64_t          number;
> > > >               char            *string;
> > > > +             short            pref;
> > >
> > > eek, just treat it as a number?
> > >
> > > >       } v;
> > > >       int lineno;
> > > >  } YYSTYPE;
> > > > @@ -117,11 +118,13 @@ 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       <v.string>      STRING
> > > >  %token       <v.number>      NUMBER
> > > >  %type        <v.number>      yesno
> > > >  %type        <v.string>      string
> > > > +%type        <v.pref>        preftype
> > > >
> > > >  %%
> > > >
> > > > @@ -213,6 +216,9 @@ ra_opt_block      : DEFAULT ROUTER yesno {
> > > >               | MTU NUMBER {
> > > >                       ra_options->mtu = $2;
> > > >               }
> > > > +             | PREFERENCE preftype {
> > > > +                     ra_options->preference = $2;
> > > > +             }
> > > >               | DNS dns_block
> > > >               ;
> > > >
> > > > @@ -298,6 +304,19 @@ ra_prefixoptsl   : VALID LIFETIME NUMBER {
> > > >               | AUTONOMOUS ADDRESS_CONFIGURATION yesno {
> > > >                       ra_prefix_conf->aflag = $3;
> > > >               }
> > > > +             | PREFERENCE preftype {
> > > > +                     ra_prefix_conf->preference = $2;
> > > > +             }
> > > > +             ;
> > >
> > > see above, we are announcing prefix information, not route information
> > >
> > > > +preftype     : LOW {
> > > > +                     $$ = RA_PREFIXOPT_PREF_LOW;
> > > > +             }
> > > > +             | MEDIUM {
> > > > +                     $$ = RA_PREFIXOPT_PREF_MEDIUM;
> > > > +             }
> > > > +             | HIGH {
> > > > +                     $$ = RA_PREFIXOPT_PREF_HIGH;
> > > > +             }
> > >
> > > please use the defines from icmp6.h:
> > >
> > > #define ND_RA_FLAG_RTPREF_HIGH  0x08    /* 00001000 */
> > > #define ND_RA_FLAG_RTPREF_MEDIUM        0x00    /* 00000000 */
> > > #define ND_RA_FLAG_RTPREF_LOW   0x18    /* 00011000 */
> > > #define ND_RA_FLAG_RTPREF_RSV   0x10    /* 00010000 */
> > >
> > >
> > > >               ;
> > > >  dns_block    : '{' optnl dnsopts_l '}'
> > > >               | '{' optnl '}'
> > > > @@ -425,17 +444,21 @@ lookup(char *s)
> > > >               {"configuration",       CONFIGURATION},
> > > >               {"default",             DEFAULT},
> > > >               {"dns",                 DNS},
> > > > +             {"high",                HIGH},
> > > >               {"hop",                 HOP},
> > > >               {"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 usr.sbin/rad/printconf.c usr.sbin/rad/printconf.c
> > > > index d42890da518..e063daaa19f 100644
> > > > --- usr.sbin/rad/printconf.c
> > > > +++ usr.sbin/rad/printconf.c
> > > > @@ -34,6 +34,7 @@
> > > >  #include "rad.h"
> > > >
> > > >  const char*  yesno(int);
> > > > +const char*  preference(short);
> > >
> > > make this an in            ^
> > >
> > > >  void         print_ra_options(const char*, const struct ra_options_conf*);
> > > >  void         print_prefix_options(const char*, const struct ra_prefix_conf*);
> > > >
> > > > @@ -43,6 +44,21 @@ yesno(int flag)
> > > >       return flag ? "yes" : "no";
> > > >  }
> > > >
> > > > +const char*
> > > > +preference(short p)
> > >               ^ and here
> > > > +{
> > > > +     switch (p) {
> > > > +             case RA_PREFIXOPT_PREF_LOW:
> > > > +                     return "low";
> > > > +             case RA_PREFIXOPT_PREF_MEDIUM:
> > > > +                     return "medium";
> > > > +             case RA_PREFIXOPT_PREF_HIGH:
> > > > +                     return "high";
> > > > +             default:
> > > > +                     return "invalid";
> > >
> > > use the defines from icmp6.h
> > >
> > > > +     }
> > > > +}
> > > > +
> > > >  void
> > > >  print_ra_options(const char *indent, const struct ra_options_conf *ra_options)
> > > >  {
> > > > @@ -60,6 +76,9 @@ print_ra_options(const char *indent, const struct ra_options_conf *ra_options)
> > > >       printf("%sretrans timer %u\n", indent, ra_options->retrans_timer);
> > > >       if (ra_options->mtu > 0)
> > > >               printf("%smtu %u\n", indent, ra_options->mtu);
> > > > +     if (ra_options->preference > 0)
> > >
> > > this does not work, if you set the default in the config file (medium)
> > > it will never get printed since it's 0, but maybe that's your
> > > intention? I'd store ND_RA_FLAG_RTPREF_RSV as default and map it to
> > > medium when building the packet. Then you can match on it here.
> > >
> > >
> > > > +             printf("%spreference %s\n", indent,
> > > > +                 preference(ra_options->preference));
> > > >
> > > >       if (!SIMPLEQ_EMPTY(&ra_options->ra_rdnss_list) ||
> > > >           !SIMPLEQ_EMPTY(&ra_options->ra_dnssl_list)) {
> > > > @@ -95,6 +114,8 @@ print_prefix_options(const char *indent, const struct ra_prefix_conf
> > > >       printf("%son-link %s\n", indent, yesno(ra_prefix_conf->lflag));
> > > >       printf("%sautonomous address-configuration %s\n", indent,
> > > >           yesno(ra_prefix_conf->aflag));
> > > > +     printf("%spreference %s\n", indent,
> > > > +         preference(ra_prefix_conf->preference));
> > >
> > > Prefix Information, not Route Information
> > >
> > > >  }
> > > >
> > > >  void
> > > > diff --git usr.sbin/rad/rad.conf.5 usr.sbin/rad/rad.conf.5
> > > > index f651a715d1a..888a8f79b76 100644
> > > > --- usr.sbin/rad/rad.conf.5
> > > > +++ usr.sbin/rad/rad.conf.5
> > > > @@ -107,6 +107,11 @@ The default is 1800 seconds.
> > > >  .\" XXX
> > > >  .\" .It Ic retrans timer Ar number
> > > >  .\" XXX
> > > > +.It Ic preference Pq Ic low Ns | Ns Ic medium Ns | Ns Ic high
> > > > +Specify the router preference that is communicated to hosts through
> > > > +router advertisements.
> > > > +It can be used to communicate a prefered default router to IPv6 hosts.
> > > > +The default is medium.
> > > >  .El
> > > >  .Sh INTERFACES
> > > >  A list of interfaces or interface groups to send advertisments on:
> > > > @@ -147,6 +152,9 @@ The default is 604800.
> > > >  The valid lifetime (vltime) in seconds for addresses generated from this
> > > >  prefix.
> > > >  The default is 2592000.
> > > > +.It Ic preference Pq Ic low Ns | Ns Ic medium Ns | Ns Ic high
> > > > +The preference of the prefix is low, medium or high.
> > > > +The default is medium.
> > >
> > > Prefix Information vs. Route Informatiuon
> > >
> > > >  .El
> > > >  .Sh FILES
> > > >  .Bl -tag -width "/etc/rad.conf" -compact
> > > > diff --git usr.sbin/rad/rad.h usr.sbin/rad/rad.h
> > > > index 2bbf7c8ed5c..9508783da2e 100644
> > > > --- usr.sbin/rad/rad.h
> > > > +++ usr.sbin/rad/rad.h
> > > > @@ -93,6 +93,7 @@ struct ra_options_conf {
> > > >       int             m_flag;                 /* managed address conf flag */
> > > >       int             o_flag;                 /* other conf flag */
> > > >       int             router_lifetime;        /* default router lifetime */
> > > > +     short           preference;             /* rfc4191 def. router pref. */
> > >
> > >         ^ make it an int
> > >
> > > >       uint32_t        reachable_time;
> > > >       uint32_t        retrans_timer;
> > > >       uint32_t        mtu;
> > > > @@ -112,8 +113,17 @@ struct ra_prefix_conf {
> > > >       uint32_t                         pltime;        /* prefered lifetime */
> > > >       int                              lflag;         /* on-link flag*/
> > > >       int                              aflag;         /* autonom. addr flag */
> > > > +     short                            preference;    /* preference rfc4191 */
> > >
> > >
> > > Prefix Information vs. Route Information
> > >
> > > >  };
> > > >
> > > > +/*
> > > > +  RFC4191 preference values, in the middle of the 8bit reserved field.
> > > > +  01 High, 00 Medium (default),  11 Low, 10 Reserved - MUST NOT be sent
> > > > +*/
> > > > +#define RA_PREFIXOPT_PREF_LOW                0x18
> > > > +#define RA_PREFIXOPT_PREF_MEDIUM     0x00
> > > > +#define RA_PREFIXOPT_PREF_HIGH               0x08
> > > > +
> > >
> > > see above, use the defines from icmp6.h
> > >
> > > >  struct ra_iface_conf {
> > > >       SIMPLEQ_ENTRY(ra_iface_conf)             entry;
> > > >       struct ra_options_conf                   ra_options;
> > >
> > > --
> > > I'm not entirely sure you are real.

--
I'm not entirely sure you are real.

Reply | Threaded
Open this post in threaded view
|

Re: How do I publish default router preferences using rad?

Caleb Callaway-2
I want to enable a scenario similar to what's described in
https://tools.ietf.org/html/rfc4191#section-5.1

I run local network services for which I want a stable, publicly routed
prefix, but my ISP's delegated prefix isn't static. I've setup a
Hurricane Electric IPv6 tunnel to get a static prefix along side the
dynamic, ISP-delegated prefix; https://github.com/cqcallaw/openbsd-router
has details.

Everything is functionally correct with the source-based routing
configuration described in the docs, but the HE tunnel is necessarily
slow because of the overhead incurred by the 6in4 tunnel. Connections
are faster if my multihomed hosts prefer the native route for traffic
that doesn't require use of the tunnel.

I had patched rad to experiment with route preferences as a solution to
this performance issue, but my local hosts don't seem to honor the
advertised route preferences. I'm still researching what's required on
the client side for route preferences to be honored.

On Sun, Aug 18, 2019 at 4:28 AM Florian Obser <[hidden email]> wrote:

> I'm curious, how are you using the router preference, could you tell
> us a bit more about your network topology?
> Also, what clients pay attention to it and how are they using it?
>
> Same goes for the route option, are you aware of clients using it?
>
> Thanks,
> Florian
>
> On Sat, Aug 17, 2019 at 08:09:54PM -0700, Caleb Callaway wrote:
> > 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 <[hidden email]>
> 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 <net/if.h>
> > > #include <arpa/inet.h>
> > > +#include <netinet/icmp6.h>
> > > #include <ctype.h>
> > > #include <err.h>
> > > @@ -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 <v.string>  STRING
> > > %token <v.number>  NUMBER
> > > %type  <v.number>  yesno
> > > +%type  <v.number>  preference
> > > %type  <v.string>  string
> > > %%
> > > @@ -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 <net/if.h>
> > > #include <arpa/inet.h>
> > > +#include <netinet/icmp6.h>
> > > #include <event.h>
> > > #include <imsg.h>
> > > @@ -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_options)
> > > @@ -60,6 +76,9 @@ print_ra_options(const char *indent, const struct
> > > ra_options_conf *ra_options)
> > >    printf("%sretrans timer %u\n", indent, ra_options->retrans_timer);
> > >    if (ra_options->mtu > 0)
> > >        printf("%smtu %u\n", indent, ra_options->mtu);
> > > +   if (ra_options->preference != ND_RA_FLAG_RTPREF_RSV)
> > > +       printf("%spreference %s\n", indent,
> > > +        preference(ra_options->preference));
> > >    if (!SIMPLEQ_EMPTY(&ra_options->ra_rdnss_list) ||
> > >     !SIMPLEQ_EMPTY(&ra_options->ra_dnssl_list)) {
> > > diff --git a/usr.sbin/rad/rad.c b/usr.sbin/rad/rad.c
> > > index 93675167b6b..cb0593f11ab 100644
> > > --- a/usr.sbin/rad/rad.c
> > > +++ b/usr.sbin/rad/rad.c
> > > @@ -433,7 +433,7 @@ main_dispatch_frontend(int fd, short event, void
> *bula)
> > >        case IMSG_CTL_LOG_VERBOSE:
> > >            if (IMSG_DATA_SIZE(imsg) != sizeof(verbose))
> > >                fatalx("%s: IMSG_CTL_LOG_VERBOSE wrong length: "
> > > -                "%lu", __func__, IMSG_DATA_SIZE(imsg));
> > > +                "%lu", __func__, IMSG_DATA_SIZE(imsg));
> > >            memcpy(&verbose, imsg.data, sizeof(verbose));
> > >            log_setverbose(verbose);
> > >            break;
> > > @@ -754,6 +754,7 @@ config_new_empty(void)
> > >    xconf->ra_options.cur_hl = 0;
> > >    xconf->ra_options.m_flag = 0;
> > >    xconf->ra_options.o_flag = 0;
> > > +   xconf->ra_options.preference = ND_RA_FLAG_RTPREF_MEDIUM;
> > >    xconf->ra_options.router_lifetime = 1800;
> > >    xconf->ra_options.reachable_time = 0;
> > >    xconf->ra_options.retrans_timer = 0;
> > > diff --git a/usr.sbin/rad/rad.conf.5 b/usr.sbin/rad/rad.conf.5
> > > index f651a715d1a..b822f3d195d 100644
> > > --- a/usr.sbin/rad/rad.conf.5
> > > +++ b/usr.sbin/rad/rad.conf.5
> > > @@ -107,6 +107,8 @@ The default is 1800 seconds.
> > > .\" XXX
> > > .\" .It Ic retrans timer Ar number
> > > .\" XXX
> > > +.It Ic preference Pq Ic low Ns | Ns Ic medium Ns | Ns Ic high
> > > +Communicate router preference to clients. The default is medium.
> > > .El
> > > .Sh INTERFACES
> > > A list of interfaces or interface groups to send advertisments on:
> > > diff --git a/usr.sbin/rad/rad.h b/usr.sbin/rad/rad.h
> > > index 2bbf7c8ed5c..cfaa5e88638 100644
> > > --- a/usr.sbin/rad/rad.h
> > > +++ b/usr.sbin/rad/rad.h
> > > @@ -92,6 +92,7 @@ struct ra_options_conf {
> > >    int     cur_hl;         /* current hop limit */
> > >    int     m_flag;         /* managed address conf flag */
> > >    int     o_flag;         /* other conf flag */
> > > +   int     preference;     /* router preference (see RFC 4191 2.2) */
> > >    int     router_lifetime;    /* default router lifetime */
> > >    uint32_t    reachable_time;
> > >    uint32_t    retrans_timer;
> > >
> > >
> > > On Wed, Aug 7, 2019 at 2:04 AM Florian Obser <[hidden email]>
> wrote:
> > > >
> > > > On Tue, Aug 06, 2019 at 11:17:04PM +0200, Sebastian Benoit wrote:
> > > > > Caleb([hidden email]) on 2019.08.06 08:05:48 -0700:
> > > > > > How do I publish default router preferences as defined in RFC
> 4191
> > > > > > (https://tools.ietf.org/html/rfc4191) using rad in OpenBSD 6.5?
> > > > > > I've read the friendly rad.conf man page
> > > > > > (https://man.openbsd.org/rad.conf.5) and scanned the source
> > > > > > (https://github.com/openbsd/src/tree/master/usr.sbin/rad) with
> no
> > > > > > success.
> > > > >
> > > > > You can't, because it was not implemented.
> > > > >
> > > > > That is, until now.
> > > > >
> > > > > I wrote a patch, which you can test if you like. It's completly
> untested
> > > > > though.
> > > > >
> > > >
> > > > needs more yak shaving
> > > >
> > > > >
> > > > > diff --git usr.sbin/rad/frontend.c usr.sbin/rad/frontend.c
> > > > > index 8178b058629..75723797fcf 100644
> > > > > --- usr.sbin/rad/frontend.c
> > > > > +++ usr.sbin/rad/frontend.c
> > > > > @@ -1016,6 +1016,8 @@ build_packet(struct ra_iface *ra_iface)
> > > > >               ra->nd_ra_flags_reserved |= ND_RA_FLAG_MANAGED;
> > > > >       if (ra_options_conf->o_flag)
> > > > >               ra->nd_ra_flags_reserved |= ND_RA_FLAG_OTHER;
> > > > > +     ra->nd_ra_flags_reserved |=
> > > > > +         ra_options_conf->preference;
> > > > >       if (ra_iface->removed)
> > > > >               /* tell clients that we are no longer a default
> router */
> > > > >               ra->nd_ra_router_lifetime = 0;
> > > > > @@ -1048,6 +1050,8 @@ build_packet(struct ra_iface *ra_iface)
> > > > >               if (ra_prefix_conf->aflag)
> > > > >                       ndopt_pi->nd_opt_pi_flags_reserved |=
> > > > >                           ND_OPT_PI_FLAG_AUTO;
> > > > > +             ndopt_pi->nd_opt_pi_flags_reserved |=
> > > > > +                         ra_prefix_conf->preference;
> > > >
> > > > This is a prefix information option (type 3) not a route information
> option (type 24).
> > > > Option 3 does not have a preference.
> > > >
> > > > >               ndopt_pi->nd_opt_pi_valid_time =
> htonl(ra_prefix_conf->vltime);
> > > > >               ndopt_pi->nd_opt_pi_preferred_time =
> > > > >                   htonl(ra_prefix_conf->pltime);
> > > > > diff --git usr.sbin/rad/parse.y usr.sbin/rad/parse.y
> > > > > index 004e5e22f92..b004ab37356 100644
> > > > > --- usr.sbin/rad/parse.y
> > > > > +++ usr.sbin/rad/parse.y
> > > > > @@ -106,6 +106,7 @@ typedef struct {
> > > > >       union {
> > > > >               int64_t          number;
> > > > >               char            *string;
> > > > > +             short            pref;
> > > >
> > > > eek, just treat it as a number?
> > > >
> > > > >       } v;
> > > > >       int lineno;
> > > > >  } YYSTYPE;
> > > > > @@ -117,11 +118,13 @@ 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       <v.string>      STRING
> > > > >  %token       <v.number>      NUMBER
> > > > >  %type        <v.number>      yesno
> > > > >  %type        <v.string>      string
> > > > > +%type        <v.pref>        preftype
> > > > >
> > > > >  %%
> > > > >
> > > > > @@ -213,6 +216,9 @@ ra_opt_block      : DEFAULT ROUTER yesno {
> > > > >               | MTU NUMBER {
> > > > >                       ra_options->mtu = $2;
> > > > >               }
> > > > > +             | PREFERENCE preftype {
> > > > > +                     ra_options->preference = $2;
> > > > > +             }
> > > > >               | DNS dns_block
> > > > >               ;
> > > > >
> > > > > @@ -298,6 +304,19 @@ ra_prefixoptsl   : VALID LIFETIME NUMBER {
> > > > >               | AUTONOMOUS ADDRESS_CONFIGURATION yesno {
> > > > >                       ra_prefix_conf->aflag = $3;
> > > > >               }
> > > > > +             | PREFERENCE preftype {
> > > > > +                     ra_prefix_conf->preference = $2;
> > > > > +             }
> > > > > +             ;
> > > >
> > > > see above, we are announcing prefix information, not route
> information
> > > >
> > > > > +preftype     : LOW {
> > > > > +                     $$ = RA_PREFIXOPT_PREF_LOW;
> > > > > +             }
> > > > > +             | MEDIUM {
> > > > > +                     $$ = RA_PREFIXOPT_PREF_MEDIUM;
> > > > > +             }
> > > > > +             | HIGH {
> > > > > +                     $$ = RA_PREFIXOPT_PREF_HIGH;
> > > > > +             }
> > > >
> > > > please use the defines from icmp6.h:
> > > >
> > > > #define ND_RA_FLAG_RTPREF_HIGH  0x08    /* 00001000 */
> > > > #define ND_RA_FLAG_RTPREF_MEDIUM        0x00    /* 00000000 */
> > > > #define ND_RA_FLAG_RTPREF_LOW   0x18    /* 00011000 */
> > > > #define ND_RA_FLAG_RTPREF_RSV   0x10    /* 00010000 */
> > > >
> > > >
> > > > >               ;
> > > > >  dns_block    : '{' optnl dnsopts_l '}'
> > > > >               | '{' optnl '}'
> > > > > @@ -425,17 +444,21 @@ lookup(char *s)
> > > > >               {"configuration",       CONFIGURATION},
> > > > >               {"default",             DEFAULT},
> > > > >               {"dns",                 DNS},
> > > > > +             {"high",                HIGH},
> > > > >               {"hop",                 HOP},
> > > > >               {"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 usr.sbin/rad/printconf.c usr.sbin/rad/printconf.c
> > > > > index d42890da518..e063daaa19f 100644
> > > > > --- usr.sbin/rad/printconf.c
> > > > > +++ usr.sbin/rad/printconf.c
> > > > > @@ -34,6 +34,7 @@
> > > > >  #include "rad.h"
> > > > >
> > > > >  const char*  yesno(int);
> > > > > +const char*  preference(short);
> > > >
> > > > make this an in            ^
> > > >
> > > > >  void         print_ra_options(const char*, const struct
> ra_options_conf*);
> > > > >  void         print_prefix_options(const char*, const struct
> ra_prefix_conf*);
> > > > >
> > > > > @@ -43,6 +44,21 @@ yesno(int flag)
> > > > >       return flag ? "yes" : "no";
> > > > >  }
> > > > >
> > > > > +const char*
> > > > > +preference(short p)
> > > >               ^ and here
> > > > > +{
> > > > > +     switch (p) {
> > > > > +             case RA_PREFIXOPT_PREF_LOW:
> > > > > +                     return "low";
> > > > > +             case RA_PREFIXOPT_PREF_MEDIUM:
> > > > > +                     return "medium";
> > > > > +             case RA_PREFIXOPT_PREF_HIGH:
> > > > > +                     return "high";
> > > > > +             default:
> > > > > +                     return "invalid";
> > > >
> > > > use the defines from icmp6.h
> > > >
> > > > > +     }
> > > > > +}
> > > > > +
> > > > >  void
> > > > >  print_ra_options(const char *indent, const struct ra_options_conf
> *ra_options)
> > > > >  {
> > > > > @@ -60,6 +76,9 @@ print_ra_options(const char *indent, const
> struct ra_options_conf *ra_options)
> > > > >       printf("%sretrans timer %u\n", indent,
> ra_options->retrans_timer);
> > > > >       if (ra_options->mtu > 0)
> > > > >               printf("%smtu %u\n", indent, ra_options->mtu);
> > > > > +     if (ra_options->preference > 0)
> > > >
> > > > this does not work, if you set the default in the config file
> (medium)
> > > > it will never get printed since it's 0, but maybe that's your
> > > > intention? I'd store ND_RA_FLAG_RTPREF_RSV as default and map it to
> > > > medium when building the packet. Then you can match on it here.
> > > >
> > > >
> > > > > +             printf("%spreference %s\n", indent,
> > > > > +                 preference(ra_options->preference));
> > > > >
> > > > >       if (!SIMPLEQ_EMPTY(&ra_options->ra_rdnss_list) ||
> > > > >           !SIMPLEQ_EMPTY(&ra_options->ra_dnssl_list)) {
> > > > > @@ -95,6 +114,8 @@ print_prefix_options(const char *indent, const
> struct ra_prefix_conf
> > > > >       printf("%son-link %s\n", indent,
> yesno(ra_prefix_conf->lflag));
> > > > >       printf("%sautonomous address-configuration %s\n", indent,
> > > > >           yesno(ra_prefix_conf->aflag));
> > > > > +     printf("%spreference %s\n", indent,
> > > > > +         preference(ra_prefix_conf->preference));
> > > >
> > > > Prefix Information, not Route Information
> > > >
> > > > >  }
> > > > >
> > > > >  void
> > > > > diff --git usr.sbin/rad/rad.conf.5 usr.sbin/rad/rad.conf.5
> > > > > index f651a715d1a..888a8f79b76 100644
> > > > > --- usr.sbin/rad/rad.conf.5
> > > > > +++ usr.sbin/rad/rad.conf.5
> > > > > @@ -107,6 +107,11 @@ The default is 1800 seconds.
> > > > >  .\" XXX
> > > > >  .\" .It Ic retrans timer Ar number
> > > > >  .\" XXX
> > > > > +.It Ic preference Pq Ic low Ns | Ns Ic medium Ns | Ns Ic high
> > > > > +Specify the router preference that is communicated to hosts
> through
> > > > > +router advertisements.
> > > > > +It can be used to communicate a prefered default router to IPv6
> hosts.
> > > > > +The default is medium.
> > > > >  .El
> > > > >  .Sh INTERFACES
> > > > >  A list of interfaces or interface groups to send advertisments on:
> > > > > @@ -147,6 +152,9 @@ The default is 604800.
> > > > >  The valid lifetime (vltime) in seconds for addresses generated
> from this
> > > > >  prefix.
> > > > >  The default is 2592000.
> > > > > +.It Ic preference Pq Ic low Ns | Ns Ic medium Ns | Ns Ic high
> > > > > +The preference of the prefix is low, medium or high.
> > > > > +The default is medium.
> > > >
> > > > Prefix Information vs. Route Informatiuon
> > > >
> > > > >  .El
> > > > >  .Sh FILES
> > > > >  .Bl -tag -width "/etc/rad.conf" -compact
> > > > > diff --git usr.sbin/rad/rad.h usr.sbin/rad/rad.h
> > > > > index 2bbf7c8ed5c..9508783da2e 100644
> > > > > --- usr.sbin/rad/rad.h
> > > > > +++ usr.sbin/rad/rad.h
> > > > > @@ -93,6 +93,7 @@ struct ra_options_conf {
> > > > >       int             m_flag;                 /* managed address
> conf flag */
> > > > >       int             o_flag;                 /* other conf flag */
> > > > >       int             router_lifetime;        /* default router
> lifetime */
> > > > > +     short           preference;             /* rfc4191 def.
> router pref. */
> > > >
> > > >         ^ make it an int
> > > >
> > > > >       uint32_t        reachable_time;
> > > > >       uint32_t        retrans_timer;
> > > > >       uint32_t        mtu;
> > > > > @@ -112,8 +113,17 @@ struct ra_prefix_conf {
> > > > >       uint32_t                         pltime;        /* prefered
> lifetime */
> > > > >       int                              lflag;         /* on-link
> flag*/
> > > > >       int                              aflag;         /* autonom.
> addr flag */
> > > > > +     short                            preference;    /*
> preference rfc4191 */
> > > >
> > > >
> > > > Prefix Information vs. Route Information
> > > >
> > > > >  };
> > > > >
> > > > > +/*
> > > > > +  RFC4191 preference values, in the middle of the 8bit reserved
> field.
> > > > > +  01 High, 00 Medium (default),  11 Low, 10 Reserved - MUST NOT
> be sent
> > > > > +*/
> > > > > +#define RA_PREFIXOPT_PREF_LOW                0x18
> > > > > +#define RA_PREFIXOPT_PREF_MEDIUM     0x00
> > > > > +#define RA_PREFIXOPT_PREF_HIGH               0x08
> > > > > +
> > > >
> > > > see above, use the defines from icmp6.h
> > > >
> > > > >  struct ra_iface_conf {
> > > > >       SIMPLEQ_ENTRY(ra_iface_conf)             entry;
> > > > >       struct ra_options_conf                   ra_options;
> > > >
> > > > --
> > > > I'm not entirely sure you are real.
>
> --
> I'm not entirely sure you are real.
>