From: Florian Obser Subject: Implement RFC 4191 default router preference. To: tech Date: Tue, 23 Apr 2024 11:54:24 +0200 I'll work on RFC 4191 route information options next, which has the same option. That's how I discovered that we never implemented this for the default router. rtadvd had this feature back in the day... OK? diff --git frontend.c frontend.c index 352479ffbba..6bda00ff4c2 100644 --- frontend.c +++ frontend.c @@ -1157,6 +1157,14 @@ build_packet(struct ra_iface *ra_iface) else if (ra_options_conf->dfr) { ra->nd_ra_router_lifetime = htons(ra_options_conf->router_lifetime); + /* + * RFC 4191 + * If the Router Lifetime is zero, the preference value MUST be + * set to (00) by the sender and MUST be ignored by the + * receiver. + */ + if (ra_options_conf->router_lifetime > 0) + ra->nd_ra_flags_reserved |= ra_options_conf->rtpref; } ra->nd_ra_reachable = htonl(ra_options_conf->reachable_time); ra->nd_ra_retransmit = htonl(ra_options_conf->retrans_timer); diff --git parse.y parse.y index 6ebd4eeb5d3..5b632521aff 100644 --- parse.y +++ parse.y @@ -29,6 +29,7 @@ #include #include +#include #include #include @@ -119,8 +120,8 @@ typedef struct { %token RA_IFACE YES NO INCLUDE ERROR %token DEFAULT ROUTER HOP LIMIT MANAGED ADDRESS %token CONFIGURATION OTHER LIFETIME REACHABLE TIME RETRANS TIMER -%token AUTO PREFIX VALID PREFERRED LIFETIME ONLINK AUTONOMOUS -%token ADDRESS_CONFIGURATION DNS NAMESERVER SEARCH MTU NAT64 +%token AUTO PREFIX VALID PREFERENCE PREFERRED LIFETIME ONLINK AUTONOMOUS +%token ADDRESS_CONFIGURATION DNS NAMESERVER SEARCH MTU NAT64 HIGH MEDIUM LOW %token STRING %token NUMBER @@ -210,6 +211,15 @@ ra_opt_block : DEFAULT ROUTER yesno { | ROUTER LIFETIME NUMBER { ra_options->router_lifetime = $3; } + | ROUTER PREFERENCE HIGH { + ra_options->rtpref = ND_RA_FLAG_RTPREF_HIGH; + } + | ROUTER PREFERENCE MEDIUM { + ra_options->rtpref = ND_RA_FLAG_RTPREF_MEDIUM; + } + | ROUTER PREFERENCE LOW { + ra_options->rtpref = ND_RA_FLAG_RTPREF_LOW; + } | REACHABLE TIME NUMBER { ra_options->reachable_time = $3; } @@ -507,18 +517,22 @@ 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}, {"nat64", NAT64}, {"no", NO}, {"on-link", ONLINK}, {"other", OTHER}, + {"preference", PREFERENCE}, {"preferred", PREFERRED}, {"prefix", PREFIX}, {"reachable", REACHABLE}, diff --git printconf.c printconf.c index f664e58de83..73468936547 100644 --- printconf.c +++ printconf.c @@ -23,6 +23,7 @@ #include #include +#include #include #include @@ -34,6 +35,7 @@ #include "rad.h" const char* yesno(int); +const char* rtpref(int); void print_ra_options(const char*, const struct ra_options_conf*); void print_prefix_options(const char*, const struct ra_prefix_conf*); @@ -43,6 +45,22 @@ yesno(int flag) return flag ? "yes" : "no"; } +const char* +rtpref(int rtpref) +{ + switch (rtpref & ND_RA_FLAG_RTPREF_MASK) { + case ND_RA_FLAG_RTPREF_HIGH: + return "high"; + case ND_RA_FLAG_RTPREF_MEDIUM: + return "medium"; + case ND_RA_FLAG_RTPREF_LOW: + return "low"; + default: + return "invalid"; + } + +} + void print_ra_options(const char *indent, const struct ra_options_conf *ra_options) { @@ -56,6 +74,7 @@ print_ra_options(const char *indent, const struct ra_options_conf *ra_options) printf("%smanaged address configuration %s\n", indent, yesno(ra_options->m_flag)); printf("%sother configuration %s\n", indent, yesno(ra_options->o_flag)); + printf("%srouter preference %s\n", indent, rtpref(ra_options->rtpref)); printf("%srouter lifetime %d\n", indent, ra_options->router_lifetime); printf("%sreachable time %u\n", indent, ra_options->reachable_time); printf("%sretrans timer %u\n", indent, ra_options->retrans_timer); diff --git rad.conf.5 rad.conf.5 index 3f71a9aeee9..6b9b210a945 100644 --- rad.conf.5 +++ rad.conf.5 @@ -120,6 +120,9 @@ like NTP servers or DNS name servers. The number of seconds this router is a valid default router after receiving a router advertisement message. The default is 1800 seconds. +.It Ic router preference Pq Ic high Ns | Ns Ic medium Ns | Ns Ic low +Indicates whether to prefer this router over other default routers. +The default is medium. .\" .It Ic reachable time Ar number .\" XXX .\" .It Ic retrans timer Ar number diff --git rad.h rad.h index 714bb93765a..00f62bc9b24 100644 --- rad.h +++ rad.h @@ -93,6 +93,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 rtpref; /* router preference */ int router_lifetime; /* default router lifetime */ uint32_t reachable_time; uint32_t retrans_timer; -- In my defence, I have been left unsupervised.