aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrank Behrens <frank@harz.behrens.de>2021-03-19 17:06:07 +0100
committerJason A. Donenfeld <Jason@zx2c4.com>2021-03-22 12:08:49 -0600
commit0a5c6abdfaa1f4f09269a222c1720e2ff3b8aa02 (patch)
tree4b8a908e49f062a4fc9b8e1aced2ceec26361267
parentwg_noise: ensure non-zero'd handshakes have a valid local index (diff)
downloadwireguard-freebsd-0a5c6abdfaa1f4f09269a222c1720e2ff3b8aa02.tar.xz
wireguard-freebsd-0a5c6abdfaa1f4f09269a222c1720e2ff3b8aa02.zip
if_wg: implement selection of FIB (routing table) for tunneled packets
The outgoing, encrypted packets can use a specified FIB and therefore utilize specific (default) routes. The implementation follows the existing convention for other tunnel interfaces and reuses some code from gre(4) implementation. The FIB for wg(4) interface is set by standard ifconfig(8) with parameter "tunnelfib", e.g. "ifconfig wg0 tunnelfib 1". Signed-off-by: Frank Behrens <frank@harz.behrens.de> [Jason: rewritten to avoid sosockopt and simplify] Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
-rw-r--r--src/if_wg.c37
1 files changed, 37 insertions, 0 deletions
diff --git a/src/if_wg.c b/src/if_wg.c
index d589842..020e595 100644
--- a/src/if_wg.c
+++ b/src/if_wg.c
@@ -277,6 +277,7 @@ struct wg_socket {
struct socket *so_so4;
struct socket *so_so6;
uint32_t so_user_cookie;
+ int so_fibnum;
in_port_t so_port;
};
@@ -377,6 +378,7 @@ static int wg_socket_bind(struct socket *, struct socket *, in_port_t *);
static void wg_socket_set(struct wg_softc *, struct socket *, struct socket *);
static void wg_socket_uninit(struct wg_softc *);
static void wg_socket_set_cookie(struct wg_softc *, uint32_t);
+static int wg_socket_set_fibnum(struct wg_softc *, int);
static int wg_send(struct wg_softc *, struct wg_endpoint *, struct mbuf *);
static void wg_timers_event_data_sent(struct wg_timers *);
static void wg_timers_event_data_received(struct wg_timers *);
@@ -971,6 +973,7 @@ wg_socket_init(struct wg_softc *sc, in_port_t port)
MPASS(rc == 0);
so4->so_user_cookie = so6->so_user_cookie = sc->sc_socket.so_user_cookie;
+ so4->so_fibnum = so6->so_fibnum = sc->sc_socket.so_fibnum;
rc = wg_socket_bind(so4, so6, &port);
if (rc == 0) {
@@ -1000,6 +1003,23 @@ static void wg_socket_set_cookie(struct wg_softc *sc, uint32_t user_cookie)
so->so_so6->so_user_cookie = user_cookie;
}
+static int wg_socket_set_fibnum(struct wg_softc *sc, int fibnum)
+{
+ struct wg_socket *so = &sc->sc_socket;
+
+ if (fibnum < 0 || fibnum >= rt_numfibs)
+ return EINVAL;
+
+ sx_assert(&sc->sc_lock, SX_XLOCKED);
+
+ so->so_fibnum = fibnum;
+ if (so->so_so4)
+ so->so_so4->so_fibnum = fibnum;
+ if (so->so_so6)
+ so->so_so6->so_fibnum = fibnum;
+ return 0;
+}
+
static void
wg_socket_uninit(struct wg_softc *sc)
{
@@ -3079,6 +3099,22 @@ wg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
case SIOCADDMULTI:
case SIOCDELMULTI:
break;
+ case SIOCGTUNFIB:
+ sx_slock(&sc->sc_lock);
+ ifr->ifr_fib = sc->sc_socket.so_fibnum;
+ sx_sunlock(&sc->sc_lock);
+ break;
+ case SIOCSTUNFIB:
+ ret = priv_check(curthread, PRIV_NET_WG);
+ if (ret)
+ break;
+ ret = priv_check(curthread, PRIV_NET_SETIFFIB);
+ if (ret)
+ break;
+ sx_xlock(&sc->sc_lock);
+ ret = wg_socket_set_fibnum(sc, ifr->ifr_fib);
+ sx_xunlock(&sc->sc_lock);
+ break;
default:
ret = ENOTTY;
}
@@ -3196,6 +3232,7 @@ wg_clone_create(struct if_clone *ifc, int unit, caddr_t params)
sc = malloc(sizeof(*sc), M_WG, M_WAITOK | M_ZERO);
sc->sc_ucred = crhold(curthread->td_ucred);
+ sc->sc_socket.so_fibnum = curthread->td_proc->p_fibnum;
ifp = sc->sc_ifp = if_alloc(IFT_WIREGUARD);
ifp->if_softc = sc;
if_initname(ifp, wgname, unit);