From c2a5f1a57a5aed41a7d3b813e8e6e0bff98b7abe Mon Sep 17 00:00:00 2001 From: Hiroki Sato Date: Sun, 31 Jan 2010 08:16:37 +0000 Subject: [PATCH] - Check if_type of "addm " before setting the interface's MTU to the if_bridge(4) interface. This fixes a bug that MTU value of "addm " is used even when it is invalid for the if_bridge(4) member: # ifconfig bridge0 create # ifconfig bridge0 bridge0: flags=8802 metric 0 mtu 1500 ... # ifconfig bridge0 addm lo0 ifconfig: BRDGADD lo0: Invalid argument # ifconfig bridge0 bridge0: flags=8802 metric 0 mtu 16384 ... - Do not ignore MTU value of an interface even when if_type == IFT_GIF. This fixes MTU mismatch when an if_bridge(4) interface has a gif(4) interface and no other interface as the member, and it is directly used for L2 communication with EtherIP tunneling enabled. - Implement SIOCSIFMTU ioctl. Changing the MTU is allowed only when all members have the same MTU value. --- sys/net/if_bridge.c | 48 ++++++++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c index 7084fe6cb5f0..d985e987abdc 100644 --- a/sys/net/if_bridge.c +++ b/sys/net/if_bridge.c @@ -683,6 +683,8 @@ static int bridge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) { struct bridge_softc *sc = ifp->if_softc; + struct ifreq *ifr = (struct ifreq *)data; + struct bridge_iflist *bif; struct thread *td = curthread; union { struct ifbreq ifbreq; @@ -772,10 +774,29 @@ bridge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) break; case SIOCSIFMTU: - /* Do not allow the MTU to be changed on the bridge */ - error = EINVAL; + if (ifr->ifr_mtu < 576) { + error = EINVAL; + break; + } + if (LIST_EMPTY(&sc->sc_iflist)) { + sc->sc_ifp->if_mtu = ifr->ifr_mtu; + break; + } + BRIDGE_LOCK(sc); + LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { + if (bif->bif_ifp->if_mtu != ifr->ifr_mtu) { + log(LOG_NOTICE, "%s: invalid MTU: %lu(%s)" + " != %d\n", sc->sc_ifp->if_xname, + bif->bif_ifp->if_mtu, + bif->bif_ifp->if_xname, ifr->ifr_mtu); + error = EINVAL; + break; + } + } + if (!error) + sc->sc_ifp->if_mtu = ifr->ifr_mtu; + BRIDGE_UNLOCK(sc); break; - default: /* * drop the lock as ether_ioctl() will call bridge_start() and @@ -989,17 +1010,6 @@ bridge_ioctl_add(struct bridge_softc *sc, void *arg) if (ifs == bif->bif_ifp) return (EBUSY); - /* Allow the first Ethernet member to define the MTU */ - if (ifs->if_type != IFT_GIF) { - if (LIST_EMPTY(&sc->sc_iflist)) - sc->sc_ifp->if_mtu = ifs->if_mtu; - else if (sc->sc_ifp->if_mtu != ifs->if_mtu) { - if_printf(sc->sc_ifp, "invalid MTU for %s\n", - ifs->if_xname); - return (EINVAL); - } - } - if (ifs->if_bridge == sc) return (EEXIST); @@ -1025,6 +1035,16 @@ bridge_ioctl_add(struct bridge_softc *sc, void *arg) goto out; } + /* Allow the first Ethernet member to define the MTU */ + if (LIST_EMPTY(&sc->sc_iflist)) + sc->sc_ifp->if_mtu = ifs->if_mtu; + else if (sc->sc_ifp->if_mtu != ifs->if_mtu) { + if_printf(sc->sc_ifp, "invalid MTU: %lu(%s) != %lu\n", + ifs->if_mtu, ifs->if_xname, sc->sc_ifp->if_mtu); + error = EINVAL; + goto out; + } + /* * Assign the interface's MAC address to the bridge if it's the first * member and the MAC address of the bridge has not been changed from