Caleb([email protected]) 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;