From: bket Date: Fri, 27 Jul 2018 06:20:01 +0000 (+0000) Subject: Enable slaacd(8) to set MTU on an interface. X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=2d9ad356f15e330ce92a208225331854e4d8a737;p=openbsd Enable slaacd(8) to set MTU on an interface. If a router advertisement message with the MTU option is received on an interface slaacd will set the specified MTU on that interface. Lots of help from florian@. Thank you! OK florian@ --- diff --git a/sbin/slaacd/engine.c b/sbin/slaacd/engine.c index 58c39fb5c4a..228e0576409 100644 --- a/sbin/slaacd/engine.c +++ b/sbin/slaacd/engine.c @@ -1,4 +1,4 @@ -/* $OpenBSD: engine.c,v 1.29 2018/07/23 17:25:52 florian Exp $ */ +/* $OpenBSD: engine.c,v 1.30 2018/07/27 06:20:01 bket Exp $ */ /* * Copyright (c) 2017 Florian Obser @@ -164,6 +164,7 @@ struct radv { LIST_HEAD(, radv_rdns) rdns_servers; uint32_t dnssl_lifetime; LIST_HEAD(, radv_dnssl) dnssls; + uint32_t mtu; }; struct address_proposal { @@ -185,6 +186,7 @@ struct address_proposal { uint32_t vltime; uint32_t pltime; uint8_t soiikey[SLAACD_SOIIKEY_LEN]; + uint32_t mtu; }; struct dfr_proposal { @@ -215,6 +217,7 @@ struct slaacd_iface { struct sockaddr_in6 ll_address; uint8_t soiikey[SLAACD_SOIIKEY_LEN]; int link_state; + uint32_t cur_mtu; LIST_HEAD(, radv) radvs; LIST_HEAD(, address_proposal) addr_proposals; LIST_HEAD(, dfr_proposal) dfr_proposals; @@ -1193,6 +1196,7 @@ parse_ra(struct slaacd_iface *iface, struct imsg_ra *ra) struct nd_opt_prefix_info *prf; struct nd_opt_rdnss *rdnss; struct nd_opt_dnssl *dnssl; + struct nd_opt_mtu *mtu; struct in6_addr *in6; int i; char *nssl; @@ -1293,11 +1297,25 @@ parse_ra(struct slaacd_iface *iface, struct imsg_ra *ra) LIST_INSERT_HEAD(&radv->dnssls, ra_dnssl, entries); + break; + case ND_OPT_MTU: + if (nd_opt_hdr->nd_opt_len != 1) { + log_warnx("invalid ND_OPT_MTU: len != 1"); + goto err; + } + mtu = (struct nd_opt_mtu*) nd_opt_hdr; + radv->mtu = ntohl(mtu->nd_opt_mtu_mtu); + + /* path MTU cannot be less than IPV6_MMTU */ + if (radv->mtu < IPV6_MMTU) { + radv->mtu = 0; + log_warnx("invalid advertised MTU"); + } + break; case ND_OPT_REDIRECTED_HEADER: case ND_OPT_SOURCE_LINKADDR: case ND_OPT_TARGET_LINKADDR: - case ND_OPT_MTU: case ND_OPT_ROUTE_INFO: #if 0 log_debug("\tOption: %u (len: %u) not implemented", @@ -1812,6 +1830,13 @@ void update_iface_ra(struct slaacd_iface *iface, struct radv *ra) addr_proposal->vltime = TWO_HOURS; addr_proposal->pltime = prefix->pltime; + if (ra->mtu == iface->cur_mtu) + addr_proposal->mtu = 0; + else { + addr_proposal->mtu = ra->mtu; + iface->cur_mtu = ra->mtu; + } + log_debug("%s, addr state: %s", __func__, proposal_state_name[addr_proposal->state]); @@ -1902,6 +1927,7 @@ configure_address(struct address_proposal *addr_proposal) address.vltime = addr_proposal->vltime; address.pltime = addr_proposal->pltime; address.privacy = addr_proposal->privacy; + address.mtu = addr_proposal->mtu; engine_imsg_compose_main(IMSG_CONFIGURE_ADDRESS, 0, &address, sizeof(address)); @@ -1950,6 +1976,13 @@ gen_address_proposal(struct slaacd_iface *iface, struct radv *ra, struct addr_proposal->pltime = prefix->pltime; } + if (ra->mtu == iface->cur_mtu) + addr_proposal->mtu = 0; + else { + addr_proposal->mtu = ra->mtu; + iface->cur_mtu = ra->mtu; + } + gen_addr(iface, prefix, addr_proposal, privacy); tv.tv_sec = 0; diff --git a/sbin/slaacd/engine.h b/sbin/slaacd/engine.h index e7f520f1fba..8a9dbb7af35 100644 --- a/sbin/slaacd/engine.h +++ b/sbin/slaacd/engine.h @@ -1,4 +1,4 @@ -/* $OpenBSD: engine.h,v 1.1 2017/06/03 10:00:29 florian Exp $ */ +/* $OpenBSD: engine.h,v 1.2 2018/07/27 06:20:01 bket Exp $ */ /* * Copyright (c) 2004, 2005 Esben Norby @@ -34,6 +34,7 @@ struct imsg_configure_address { struct in6_addr mask; uint32_t vltime; uint32_t pltime; + uint32_t mtu; int privacy; }; diff --git a/sbin/slaacd/slaacd.c b/sbin/slaacd/slaacd.c index 7afd9dc3ec7..344fc148537 100644 --- a/sbin/slaacd/slaacd.c +++ b/sbin/slaacd/slaacd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: slaacd.c,v 1.27 2018/07/23 17:25:52 florian Exp $ */ +/* $OpenBSD: slaacd.c,v 1.28 2018/07/27 06:20:01 bket Exp $ */ /* * Copyright (c) 2017 Florian Obser @@ -761,6 +761,18 @@ configure_interface(struct imsg_configure_address *address) if (ioctl(ioctl_sock, SIOCAIFADDR_IN6, &in6_addreq) < 0) fatal("SIOCAIFADDR_IN6"); + + if (address->mtu) { + struct ifreq ifr; + + (void)strlcpy(ifr.ifr_name, in6_addreq.ifra_name, + sizeof(ifr.ifr_name)); + ifr.ifr_mtu = address->mtu; + log_debug("Setting MTU to %d", ifr.ifr_mtu); + + if (ioctl(ioctl_sock, SIOCSIFMTU, &ifr) < 0) + log_warn("failed to set MTU"); + } } void