diff --git a/sys/net/if_ovpn.c b/sys/net/if_ovpn.c index 524640639e76..14634cfc969b 100644 --- a/sys/net/if_ovpn.c +++ b/sys/net/if_ovpn.c @@ -1081,6 +1081,45 @@ ovpn_set_peer(struct ifnet *ifp, const nvlist_t *nvl) return (0); } +static int +ovpn_set_ifmode(struct ifnet *ifp, const nvlist_t *nvl) +{ + struct ovpn_softc *sc = ifp->if_softc; + int ifmode; + + if (nvl == NULL) + return (EINVAL); + + if (! nvlist_exists_number(nvl, "ifmode") ) + return (EINVAL); + + ifmode = nvlist_get_number(nvl, "ifmode"); + + OVPN_WLOCK(sc); + + /* deny this if UP */ + if (ifp->if_flags & IFF_UP) { + OVPN_WUNLOCK(sc); + return (EBUSY); + } + + switch (ifmode & ~IFF_MULTICAST) { + case IFF_POINTOPOINT: + case IFF_BROADCAST: + ifp->if_flags &= + ~(IFF_BROADCAST|IFF_POINTOPOINT|IFF_MULTICAST); + ifp->if_flags |= ifmode; + break; + default: + OVPN_WUNLOCK(sc); + return (EINVAL); + } + + OVPN_WUNLOCK(sc); + + return (0); +} + static int ovpn_ioctl_set(struct ifnet *ifp, struct ifdrv *ifd) { @@ -1135,6 +1174,9 @@ ovpn_ioctl_set(struct ifnet *ifp, struct ifdrv *ifd) case OVPN_SET_PEER: ret = ovpn_set_peer(ifp, nvl); break; + case OVPN_SET_IFMODE: + ret = ovpn_set_ifmode(ifp, nvl); + break; default: ret = ENOTSUP; } diff --git a/sys/net/if_ovpn.h b/sys/net/if_ovpn.h index 26a9907711ce..fd1c21e70435 100644 --- a/sys/net/if_ovpn.h +++ b/sys/net/if_ovpn.h @@ -60,5 +60,6 @@ enum ovpn_key_cipher { #define OVPN_SEND_PKT _IO ('D', 9) #define OVPN_POLL_PKT _IO ('D', 10) #define OVPN_GET_PKT _IO ('D', 11) +#define OVPN_SET_IFMODE _IO ('D', 12) #endif