diff --git a/contrib/wireguard-tools/ipc-freebsd.h b/contrib/wireguard-tools/ipc-freebsd.h --- a/contrib/wireguard-tools/ipc-freebsd.h +++ b/contrib/wireguard-tools/ipc-freebsd.h @@ -4,6 +4,8 @@ * */ +#include + #include #include #include @@ -11,6 +13,12 @@ #define IPC_SUPPORTS_KERNEL_INTERFACE +#define KFLAG_MAPPED(wgf, kf) { .wgflag = (wgf), .kflag = (kf) } +struct kernel_allowedip_mapping { + int wgflag; + int kflag; +}; + static int get_dgram_socket(void) { static int sock = -1; @@ -19,6 +27,44 @@ return sock; } +static bool kernel_get_allowedip_flags(int flags, int *kflags) +{ + static struct kernel_allowedip_mapping allowedip_flags[] = { +#ifdef WG_ALLOWEDIP_REMOVE + KFLAG_MAPPED(WGALLOWEDIP_REMOVE_ME, WG_ALLOWEDIP_REMOVE), +#endif + }; + + /* + * Special case for older kernels that do not support any of our new + * flags just yet. + */ + if (nitems(allowedip_flags) == 0) + return false; + + *kflags = 0; + for (size_t i = 0; i < nitems(allowedip_flags); i++) { + struct kernel_allowedip_mapping *allowedip_flagp; + + allowedip_flagp = &allowedip_flags[i]; + if ((flags & allowedip_flagp->wgflag) != 0) + *kflags |= allowedip_flagp->kflag; + + /* We'll use this for validation at the end. */ + flags &= ~allowedip_flagp->wgflag; + if (flags == 0) + break; + } + + /* + * If some flag is set that we do not recognize, then the kernel we were + * built against doesn't support some operation that was attempted and + * we have to fail the mapping. + */ + return flags == 0; + +} + static int kernel_get_wireguard_interfaces(struct string_list *list) { struct ifgroupreq ifgr = { .ifgr_name = "wg" }; @@ -308,9 +354,14 @@ if (!nvl_aips[j]) goto err_peer; if (aip->flags) { - //TODO: implement me - ret = -EOPNOTSUPP; - goto err_peer; + int kflags; + + if (!kernel_get_allowedip_flags(aip->flags, &kflags)) { + ret = -EOPNOTSUPP; + goto err_peer; + } + + nvlist_add_number(nvl_aips[j], "flags", kflags); } nvlist_add_number(nvl_aips[j], "cidr", aip->cidr); if (aip->family == AF_INET)