Enable slaacd(8) to set MTU on an interface.
authorbket <bket@openbsd.org>
Fri, 27 Jul 2018 06:20:01 +0000 (06:20 +0000)
committerbket <bket@openbsd.org>
Fri, 27 Jul 2018 06:20:01 +0000 (06:20 +0000)
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@

sbin/slaacd/engine.c
sbin/slaacd/engine.h
sbin/slaacd/slaacd.c

index 58c39fb..228e057 100644 (file)
@@ -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 <florian@openbsd.org>
@@ -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;
index e7f520f..8a9dbb7 100644 (file)
@@ -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 <norby@openbsd.org>
@@ -34,6 +34,7 @@ struct imsg_configure_address {
        struct in6_addr          mask;
        uint32_t                 vltime;
        uint32_t                 pltime;
+       uint32_t                 mtu;
        int                      privacy;
 };
 
index 7afd9dc..344fc14 100644 (file)
@@ -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 <florian@openbsd.org>
@@ -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