summaryrefslogtreecommitdiff
path: root/usr.sbin/rad
diff options
context:
space:
mode:
authorFlorian Obser <florian@cvs.openbsd.org>2024-05-17 06:50:15 +0000
committerFlorian Obser <florian@cvs.openbsd.org>2024-05-17 06:50:15 +0000
commit476bd553b568fc74cdbb8ba2c50ab0abe347b054 (patch)
tree92d8108a52cd7eb6f1230ed363118b4da7e6f0d0 /usr.sbin/rad
parent30971797942947ec1c86f88daa7a9b28479e1ec3 (diff)
Send source link-layer address option in router advertisements.
With this, hosts immediately learn the layer 2 (i.e. ethernet mac) address of their default router and don't need to do another round trip. It also turns out that apple devices (macOS & iOS) install the default route as what they call "interface scoped" if a DNS option is present and the source link-layer address option is absent. This effectively makes the default route unusable. Problem with fruit devices tracked down & diff by Ryan Vogt (rvogt.ca AT gmail), thanks! OK sthen, bket
Diffstat (limited to 'usr.sbin/rad')
-rw-r--r--usr.sbin/rad/frontend.c45
-rw-r--r--usr.sbin/rad/parse.y8
-rw-r--r--usr.sbin/rad/printconf.c4
-rw-r--r--usr.sbin/rad/rad.c3
-rw-r--r--usr.sbin/rad/rad.conf.58
-rw-r--r--usr.sbin/rad/rad.h3
6 files changed, 64 insertions, 7 deletions
diff --git a/usr.sbin/rad/frontend.c b/usr.sbin/rad/frontend.c
index 6748e43732d..ca8719a4a1b 100644
--- a/usr.sbin/rad/frontend.c
+++ b/usr.sbin/rad/frontend.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: frontend.c,v 1.45 2024/04/23 22:11:59 florian Exp $ */
+/* $OpenBSD: frontend.c,v 1.46 2024/05/17 06:50:14 florian Exp $ */
/*
* Copyright (c) 2018 Florian Obser <florian@openbsd.org>
@@ -56,6 +56,7 @@
#include <sys/uio.h>
#include <net/if.h>
+#include <net/if_dl.h>
#include <net/if_types.h>
#include <net/route.h>
@@ -120,6 +121,12 @@ struct nd_opt_pref64 {
u_int8_t nd_opt_pref64[12];
};
+struct nd_opt_source_link_addr {
+ u_int8_t nd_opt_source_link_addr_type;
+ u_int8_t nd_opt_source_link_addr_len;
+ struct ether_addr nd_opt_source_link_addr_hw_addr;
+};
+
TAILQ_HEAD(, ra_iface) ra_interfaces;
__dead void frontend_shutdown(void);
@@ -1099,6 +1106,7 @@ void
build_packet(struct ra_iface *ra_iface)
{
struct nd_router_advert *ra;
+ struct nd_opt_source_link_addr *ndopt_source_link_addr;
struct nd_opt_mtu *ndopt_mtu;
struct nd_opt_prefix_info *ndopt_pi;
struct ra_iface_conf *ra_iface_conf;
@@ -1110,6 +1118,8 @@ build_packet(struct ra_iface *ra_iface)
struct ra_rdnss_conf *ra_rdnss;
struct ra_dnssl_conf *ra_dnssl;
struct ra_pref64_conf *pref64;
+ struct ifaddrs *ifap, *ifa;
+ struct sockaddr_dl *sdl;
size_t len, label_len;
uint8_t *p, buf[RA_MAX_SIZE];
char *label_start, *label_end;
@@ -1119,6 +1129,8 @@ build_packet(struct ra_iface *ra_iface)
ra_options_conf = &ra_iface_conf->ra_options;
len = sizeof(*ra);
+ if (ra_iface_conf->ra_options.source_link_addr)
+ len += sizeof(*ndopt_source_link_addr);
if (ra_options_conf->mtu > 0)
len += sizeof(*ndopt_mtu);
len += sizeof(*ndopt_pi) * ra_iface->prefix_count;
@@ -1170,6 +1182,37 @@ build_packet(struct ra_iface *ra_iface)
ra->nd_ra_retransmit = htonl(ra_options_conf->retrans_timer);
p += sizeof(*ra);
+ if (ra_iface_conf->ra_options.source_link_addr) {
+ ndopt_source_link_addr = (struct nd_opt_source_link_addr *)p;
+ ndopt_source_link_addr->nd_opt_source_link_addr_type =
+ ND_OPT_SOURCE_LINKADDR;
+ ndopt_source_link_addr->nd_opt_source_link_addr_len = 1;
+ if (getifaddrs(&ifap) != 0) {
+ ifap = NULL;
+ log_warn("getifaddrs");
+ }
+ for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
+ if (ifa->ifa_addr == NULL ||
+ ifa->ifa_addr->sa_family != AF_LINK)
+ continue;
+ if (strcmp(ra_iface->name, ifa->ifa_name) != 0)
+ continue;
+ sdl = (struct sockaddr_dl *)ifa->ifa_addr;
+ if (sdl->sdl_type != IFT_ETHER ||
+ sdl->sdl_alen != ETHER_ADDR_LEN)
+ continue;
+ memcpy(&ndopt_source_link_addr->
+ nd_opt_source_link_addr_hw_addr,
+ LLADDR(sdl), ETHER_ADDR_LEN);
+ break;
+ }
+ if (ifap != NULL) {
+ freeifaddrs(ifap);
+ p += sizeof(*ndopt_source_link_addr);
+ } else
+ len -= sizeof(*ndopt_source_link_addr);
+ }
+
if (ra_options_conf->mtu > 0) {
ndopt_mtu = (struct nd_opt_mtu *)p;
ndopt_mtu->nd_opt_mtu_type = ND_OPT_MTU;
diff --git a/usr.sbin/rad/parse.y b/usr.sbin/rad/parse.y
index 66cc0c0ab64..bf6b6e6b86d 100644
--- a/usr.sbin/rad/parse.y
+++ b/usr.sbin/rad/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.22 2024/04/23 22:11:59 florian Exp $ */
+/* $OpenBSD: parse.y,v 1.23 2024/05/17 06:50:14 florian Exp $ */
/*
* Copyright (c) 2018 Florian Obser <florian@openbsd.org>
@@ -122,6 +122,7 @@ typedef struct {
%token CONFIGURATION OTHER LIFETIME REACHABLE TIME RETRANS TIMER
%token AUTO PREFIX VALID PREFERENCE PREFERRED LIFETIME ONLINK AUTONOMOUS
%token ADDRESS_CONFIGURATION DNS NAMESERVER SEARCH MTU NAT64 HIGH MEDIUM LOW
+%token SOURCE LINK_LAYER
%token <v.string> STRING
%token <v.number> NUMBER
@@ -226,6 +227,9 @@ ra_opt_block : DEFAULT ROUTER yesno {
| RETRANS TIMER NUMBER {
ra_options->retrans_timer = $3;
}
+ | SOURCE LINK_LAYER ADDRESS yesno {
+ ra_options->source_link_addr = $4;
+ }
| MTU NUMBER {
ra_options->mtu = $2;
}
@@ -523,6 +527,7 @@ lookup(char *s)
{"interface", RA_IFACE},
{"lifetime", LIFETIME},
{"limit", LIMIT},
+ {"link-layer", LINK_LAYER},
{"low", LOW},
{"managed", MANAGED},
{"medium", MEDIUM},
@@ -539,6 +544,7 @@ lookup(char *s)
{"retrans", RETRANS},
{"router", ROUTER},
{"search", SEARCH},
+ {"source", SOURCE},
{"time", TIME},
{"timer", TIMER},
{"valid", VALID},
diff --git a/usr.sbin/rad/printconf.c b/usr.sbin/rad/printconf.c
index 184a5df2dc1..b49a7748ae7 100644
--- a/usr.sbin/rad/printconf.c
+++ b/usr.sbin/rad/printconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: printconf.c,v 1.8 2024/04/23 22:11:59 florian Exp $ */
+/* $OpenBSD: printconf.c,v 1.9 2024/05/17 06:50:14 florian Exp $ */
/*
* Copyright (c) 2018 Florian Obser <florian@openbsd.org>
@@ -78,6 +78,8 @@ print_ra_options(const char *indent, const struct ra_options_conf *ra_options)
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);
+ printf("%ssource link-layer address %s\n", indent,
+ yesno(ra_options->source_link_addr));
if (ra_options->mtu > 0)
printf("%smtu %u\n", indent, ra_options->mtu);
diff --git a/usr.sbin/rad/rad.c b/usr.sbin/rad/rad.c
index b283e58fbf1..a0c317265b0 100644
--- a/usr.sbin/rad/rad.c
+++ b/usr.sbin/rad/rad.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rad.c,v 1.29 2023/04/19 12:58:16 jsg Exp $ */
+/* $OpenBSD: rad.c,v 1.30 2024/05/17 06:50:14 florian Exp $ */
/*
* Copyright (c) 2018 Florian Obser <florian@openbsd.org>
@@ -757,6 +757,7 @@ config_new_empty(void)
xconf->ra_options.router_lifetime = ADV_DEFAULT_LIFETIME;
xconf->ra_options.reachable_time = 0;
xconf->ra_options.retrans_timer = 0;
+ xconf->ra_options.source_link_addr = 1;
xconf->ra_options.mtu = 0;
xconf->ra_options.rdns_lifetime = DEFAULT_RDNS_LIFETIME;
SIMPLEQ_INIT(&xconf->ra_options.ra_rdnss_list);
diff --git a/usr.sbin/rad/rad.conf.5 b/usr.sbin/rad/rad.conf.5
index f82ccfd216e..87c2b328662 100644
--- a/usr.sbin/rad/rad.conf.5
+++ b/usr.sbin/rad/rad.conf.5
@@ -1,4 +1,4 @@
-.\" $OpenBSD: rad.conf.5,v 1.23 2024/04/23 22:17:49 florian Exp $
+.\" $OpenBSD: rad.conf.5,v 1.24 2024/05/17 06:50:14 florian Exp $
.\"
.\" Copyright (c) 2018 Florian Obser <florian@openbsd.org>
.\" Copyright (c) 2005 Esben Norby <norby@openbsd.org>
@@ -18,7 +18,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: April 23 2024 $
+.Dd $Mdocdate: May 17 2024 $
.Dt RAD.CONF 5
.Os
.Sh NAME
@@ -127,6 +127,10 @@ The default is medium.
.\" XXX
.\" .It Ic retrans timer Ar number
.\" XXX
+.It Ic source link-layer address Pq Ic yes Ns | Ns Ic no
+Add a source link-layer address option to router advertisement messages, to
+communicate the link-layer address of the sending interface.
+The default is yes.
.El
.Sh INTERFACES
A list of interfaces or interface groups to send advertisements on:
diff --git a/usr.sbin/rad/rad.h b/usr.sbin/rad/rad.h
index 787e78c7c4a..442ff00fcce 100644
--- a/usr.sbin/rad/rad.h
+++ b/usr.sbin/rad/rad.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: rad.h,v 1.26 2024/04/23 22:11:59 florian Exp $ */
+/* $OpenBSD: rad.h,v 1.27 2024/05/17 06:50:14 florian Exp $ */
/*
* Copyright (c) 2018 Florian Obser <florian@openbsd.org>
@@ -97,6 +97,7 @@ struct ra_options_conf {
int router_lifetime; /* default router lifetime */
uint32_t reachable_time;
uint32_t retrans_timer;
+ int source_link_addr; /* source link-layer address */
uint32_t mtu;
uint32_t rdns_lifetime;
SIMPLEQ_HEAD(, ra_rdnss_conf) ra_rdnss_list;