Module Name:    src
Committed By:   riastradh
Date:           Wed Aug 26 16:03:42 UTC 2020

Modified Files:
        src/distrib/sets/lists/base: shl.mi
        src/distrib/sets/lists/comp: mi shl.mi
        src/distrib/sets/lists/debug: mi shl.mi
        src/distrib/sets/lists/tests: mi
        src/doc: CHANGES
        src/etc/mtree: NetBSD.dist.tests
        src/share/man/man4: wg.4
        src/sys/arch/amd64/conf: ALL
        src/sys/net: if_types.h if_wg.c
        src/sys/rump/net: Makefile.rumpnetcomp
        src/tests/net: Makefile
        src/usr.sbin/wg-keygen: wg-keygen.8
        src/usr.sbin/wg-userspace: wg-userspace.8 wg-userspace.sh
        src/usr.sbin/wgconfig: wgconfig.8
Added Files:
        src/sys/rump/net/lib/libwg: Makefile WG.ioconf wg_component.c wg_user.c
            wg_user.h
        src/tests/net/if_wg: Makefile common.sh t_basic.sh
            t_interoperability.sh t_misc.sh t_tunnel.sh
Removed Files:
        src/sys/rump/net/lib/libwireguard: Makefile WG.ioconf wg_component.c
            wg_user.c wg_user.h
        src/tests/net/wireguard: Makefile common.sh t_basic.sh
            t_interoperability.sh t_misc.sh t_tunnel.sh

Log Message:
Clarify wg(4)'s relation to WireGuard, pending further discussion.

Still planning to replace wgconfig(8) and wg-keygen(8) by one wg(8)
tool compatible with wireguard-tools; update wg(4) for the minor
changes from the 2018-06-30 spec to the 2020-06-01 spec; &c.  This just
clarifies the current state of affairs as it exists in the development
tree for now.

Mark the man page EXPERIMENTAL for extra clarity.


To generate a diff of this commit:
cvs rdiff -u -r1.896 -r1.897 src/distrib/sets/lists/base/shl.mi
cvs rdiff -u -r1.2344 -r1.2345 src/distrib/sets/lists/comp/mi
cvs rdiff -u -r1.337 -r1.338 src/distrib/sets/lists/comp/shl.mi
cvs rdiff -u -r1.329 -r1.330 src/distrib/sets/lists/debug/mi
cvs rdiff -u -r1.258 -r1.259 src/distrib/sets/lists/debug/shl.mi
cvs rdiff -u -r1.906 -r1.907 src/distrib/sets/lists/tests/mi
cvs rdiff -u -r1.2732 -r1.2733 src/doc/CHANGES
cvs rdiff -u -r1.175 -r1.176 src/etc/mtree/NetBSD.dist.tests
cvs rdiff -u -r1.4 -r1.5 src/share/man/man4/wg.4
cvs rdiff -u -r1.161 -r1.162 src/sys/arch/amd64/conf/ALL
cvs rdiff -u -r1.30 -r1.31 src/sys/net/if_types.h
cvs rdiff -u -r1.23 -r1.24 src/sys/net/if_wg.c
cvs rdiff -u -r1.21 -r1.22 src/sys/rump/net/Makefile.rumpnetcomp
cvs rdiff -u -r0 -r1.1 src/sys/rump/net/lib/libwg/Makefile \
    src/sys/rump/net/lib/libwg/WG.ioconf \
    src/sys/rump/net/lib/libwg/wg_component.c \
    src/sys/rump/net/lib/libwg/wg_user.c src/sys/rump/net/lib/libwg/wg_user.h
cvs rdiff -u -r1.1 -r0 src/sys/rump/net/lib/libwireguard/Makefile \
    src/sys/rump/net/lib/libwireguard/WG.ioconf \
    src/sys/rump/net/lib/libwireguard/wg_component.c \
    src/sys/rump/net/lib/libwireguard/wg_user.c \
    src/sys/rump/net/lib/libwireguard/wg_user.h
cvs rdiff -u -r1.35 -r1.36 src/tests/net/Makefile
cvs rdiff -u -r0 -r1.1 src/tests/net/if_wg/Makefile \
    src/tests/net/if_wg/common.sh src/tests/net/if_wg/t_basic.sh \
    src/tests/net/if_wg/t_interoperability.sh src/tests/net/if_wg/t_misc.sh \
    src/tests/net/if_wg/t_tunnel.sh
cvs rdiff -u -r1.1 -r0 src/tests/net/wireguard/Makefile \
    src/tests/net/wireguard/common.sh src/tests/net/wireguard/t_basic.sh \
    src/tests/net/wireguard/t_interoperability.sh \
    src/tests/net/wireguard/t_misc.sh src/tests/net/wireguard/t_tunnel.sh
cvs rdiff -u -r1.2 -r1.3 src/usr.sbin/wg-keygen/wg-keygen.8
cvs rdiff -u -r1.2 -r1.3 src/usr.sbin/wg-userspace/wg-userspace.8
cvs rdiff -u -r1.1 -r1.2 src/usr.sbin/wg-userspace/wg-userspace.sh
cvs rdiff -u -r1.9 -r1.10 src/usr.sbin/wgconfig/wgconfig.8

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/distrib/sets/lists/base/shl.mi
diff -u src/distrib/sets/lists/base/shl.mi:1.896 src/distrib/sets/lists/base/shl.mi:1.897
--- src/distrib/sets/lists/base/shl.mi:1.896	Thu Aug 20 21:28:00 2020
+++ src/distrib/sets/lists/base/shl.mi	Wed Aug 26 16:03:40 2020
@@ -1,4 +1,4 @@
-# $NetBSD: shl.mi,v 1.896 2020/08/20 21:28:00 riastradh Exp $
+# $NetBSD: shl.mi,v 1.897 2020/08/26 16:03:40 riastradh Exp $
 #
 # Note:	Don't delete entries from here - mark them as "obsolete" instead,
 #	unless otherwise stated below.
@@ -832,9 +832,12 @@
 ./usr/lib/librumpnet_vlan.so			base-rump-shlib		rump
 ./usr/lib/librumpnet_vlan.so.0			base-rump-shlib		rump
 ./usr/lib/librumpnet_vlan.so.0.0		base-rump-shlib		rump
-./usr/lib/librumpnet_wireguard.so		base-rump-shlib		rump
-./usr/lib/librumpnet_wireguard.so.0		base-rump-shlib		rump
-./usr/lib/librumpnet_wireguard.so.0.0		base-rump-shlib		rump
+./usr/lib/librumpnet_wg.so			base-rump-shlib		rump
+./usr/lib/librumpnet_wg.so.0			base-rump-shlib		rump
+./usr/lib/librumpnet_wg.so.0.0			base-rump-shlib		rump
+./usr/lib/librumpnet_wireguard.so		base-obsolete		obsolete
+./usr/lib/librumpnet_wireguard.so.0		base-obsolete		obsolete
+./usr/lib/librumpnet_wireguard.so.0.0		base-obsolete		obsolete
 ./usr/lib/librumpres.so				base-rumpclient-shlib	compatfile,rump
 ./usr/lib/librumpres.so.0			base-rumpclient-shlib	compatfile,rump
 ./usr/lib/librumpres.so.0.0			base-rumpclient-shlib	compatfile,rump

Index: src/distrib/sets/lists/comp/mi
diff -u src/distrib/sets/lists/comp/mi:1.2344 src/distrib/sets/lists/comp/mi:1.2345
--- src/distrib/sets/lists/comp/mi:1.2344	Thu Aug 20 21:28:00 2020
+++ src/distrib/sets/lists/comp/mi	Wed Aug 26 16:03:40 2020
@@ -1,4 +1,4 @@
-#	$NetBSD: mi,v 1.2344 2020/08/20 21:28:00 riastradh Exp $
+#	$NetBSD: mi,v 1.2345 2020/08/26 16:03:40 riastradh Exp $
 #
 # Note: don't delete entries from here - mark them as "obsolete" instead.
 ./etc/mtree/set.comp				comp-sys-root
@@ -3867,8 +3867,10 @@
 ./usr/lib/librumpnet_virtif_p.a			comp-c-proflib		rump,profile
 ./usr/lib/librumpnet_vlan.a			comp-c-lib		rump
 ./usr/lib/librumpnet_vlan_p.a			comp-c-proflib		rump,profile
-./usr/lib/librumpnet_wireguard.a		comp-c-lib		rump
-./usr/lib/librumpnet_wireguard_p.a		comp-c-proflib		rump,profile
+./usr/lib/librumpnet_wg.a			comp-c-lib		rump
+./usr/lib/librumpnet_wg_p.a			comp-c-proflib		rump,profile
+./usr/lib/librumpnet_wireguard.a		comp-obsolete		obsolete
+./usr/lib/librumpnet_wireguard_p.a		comp-obsolete		obsolete
 ./usr/lib/librumpres.a				comp-c-lib		compatfile,rump
 ./usr/lib/librumpres_p.a			comp-c-proflib		compatfile,rump,profile
 ./usr/lib/librumpuser.a				comp-c-lib		compatfile,rump

Index: src/distrib/sets/lists/comp/shl.mi
diff -u src/distrib/sets/lists/comp/shl.mi:1.337 src/distrib/sets/lists/comp/shl.mi:1.338
--- src/distrib/sets/lists/comp/shl.mi:1.337	Thu Aug 20 21:28:00 2020
+++ src/distrib/sets/lists/comp/shl.mi	Wed Aug 26 16:03:40 2020
@@ -1,4 +1,4 @@
-# $NetBSD: shl.mi,v 1.337 2020/08/20 21:28:00 riastradh Exp $
+# $NetBSD: shl.mi,v 1.338 2020/08/26 16:03:40 riastradh Exp $
 #
 # Note: don't delete entries from here - mark them as "obsolete" instead.
 #
@@ -248,7 +248,8 @@
 ./usr/lib/librumpnet_tun_pic.a			comp-c-piclib		picinstall,rump
 ./usr/lib/librumpnet_virtif_pic.a		comp-c-piclib		picinstall,rump
 ./usr/lib/librumpnet_vlan_pic.a			comp-c-piclib		picinstall,rump
-./usr/lib/librumpnet_wireguard_pic.a		comp-c-piclib		picinstall,rump
+./usr/lib/librumpnet_wg_pic.a			comp-c-piclib		picinstall,rump
+./usr/lib/librumpnet_wireguard_pic.a		comp-obsolete		obsolete
 ./usr/lib/librumpres_pic.a			comp-c-piclib		compatfile,picinstall,rump
 ./usr/lib/librumpuser_pic.a			comp-c-piclib		compatfile,picinstall,rump
 ./usr/lib/librumpvfs_aio_pic.a			comp-c-piclib		picinstall,rump

Index: src/distrib/sets/lists/debug/mi
diff -u src/distrib/sets/lists/debug/mi:1.329 src/distrib/sets/lists/debug/mi:1.330
--- src/distrib/sets/lists/debug/mi:1.329	Thu Aug 20 21:28:01 2020
+++ src/distrib/sets/lists/debug/mi	Wed Aug 26 16:03:41 2020
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.329 2020/08/20 21:28:01 riastradh Exp $
+# $NetBSD: mi,v 1.330 2020/08/26 16:03:41 riastradh Exp $
 ./etc/mtree/set.debug                           comp-sys-root
 ./usr/lib					comp-sys-usr		compatdir
 ./usr/lib/i18n/libBIG5_g.a			comp-c-debuglib		debuglib,compatfile
@@ -237,7 +237,8 @@
 ./usr/lib/librumpnet_tun_g.a			comp-c-debuglib		debuglib,rump
 ./usr/lib/librumpnet_virtif_g.a			comp-c-debuglib		debuglib,rump
 ./usr/lib/librumpnet_vlan_g.a			comp-c-debuglib		debuglib,rump
-./usr/lib/librumpnet_wireguard_g.a		comp-c-debuglib		debuglib,rump
+./usr/lib/librumpnet_wg_g.a			comp-c-debuglib		debuglib,rump
+./usr/lib/librumpnet_wireguard_g.a		comp-obsolete		obsolete
 ./usr/lib/librumpres_g.a			comp-c-debuglib		debuglib,compatfile,rump
 ./usr/lib/librumpuser_g.a			comp-c-debuglib		debuglib,compatfile,rump
 ./usr/lib/librumpvfs_aio_g.a			comp-c-debuglib		debuglib,rump

Index: src/distrib/sets/lists/debug/shl.mi
diff -u src/distrib/sets/lists/debug/shl.mi:1.258 src/distrib/sets/lists/debug/shl.mi:1.259
--- src/distrib/sets/lists/debug/shl.mi:1.258	Thu Aug 20 21:28:01 2020
+++ src/distrib/sets/lists/debug/shl.mi	Wed Aug 26 16:03:41 2020
@@ -1,4 +1,4 @@
-# $NetBSD: shl.mi,v 1.258 2020/08/20 21:28:01 riastradh Exp $
+# $NetBSD: shl.mi,v 1.259 2020/08/26 16:03:41 riastradh Exp $
 ./usr/lib/libbfd_g.a						comp-c-debuglib	debuglib,compatfile,binutils
 ./usr/libdata/debug/lib						base-sys-usr	debug,dynamicroot,compatdir
 ./usr/libdata/debug/lib/libavl.so.0.0.debug			comp-zfs-debug	debug,dynamicroot,zfs
@@ -290,7 +290,8 @@
 ./usr/libdata/debug/usr/lib/librumpnet_tun.so.0.0.debug		comp-rump-debug	debug,rump
 ./usr/libdata/debug/usr/lib/librumpnet_virtif.so.0.0.debug	comp-rump-debug	debug,rump
 ./usr/libdata/debug/usr/lib/librumpnet_vlan.so.0.0.debug	comp-rump-debug	debug,rump
-./usr/libdata/debug/usr/lib/librumpnet_wireguard.so.0.0.debug	comp-rump-debug	debug,rump
+./usr/libdata/debug/usr/lib/librumpnet_wg.so.0.0.debug		comp-rump-debug	debug,rump
+./usr/libdata/debug/usr/lib/librumpnet_wireguard.so.0.0.debug	comp-obsolete	obsolete
 ./usr/libdata/debug/usr/lib/librumpres.so.0.0.debug		comp-rump-debug	debug,compatfile,rump
 ./usr/libdata/debug/usr/lib/librumpuser.so.0.1.debug		comp-rump-debug	debug,compatfile,rump
 ./usr/libdata/debug/usr/lib/librumpvfs.so.0.0.debug		comp-rump-debug	debug,compatfile,rump

Index: src/distrib/sets/lists/tests/mi
diff -u src/distrib/sets/lists/tests/mi:1.906 src/distrib/sets/lists/tests/mi:1.907
--- src/distrib/sets/lists/tests/mi:1.906	Mon Aug 24 18:41:22 2020
+++ src/distrib/sets/lists/tests/mi	Wed Aug 26 16:03:41 2020
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.906 2020/08/24 18:41:22 riastradh Exp $
+# $NetBSD: mi,v 1.907 2020/08/26 16:03:41 riastradh Exp $
 #
 # Note: don't delete entries from here - mark them as "obsolete" instead.
 #
@@ -3866,13 +3866,20 @@
 ./usr/tests/net/if_vlan/Kyuafile		tests-net-tests		atf,rump,kyua
 ./usr/tests/net/if_vlan/siocXmulti		tests-net-tests		atf,rump
 ./usr/tests/net/if_vlan/t_vlan			tests-net-tests		atf,rump
-./usr/tests/net/wireguard			tests-net-tests		compattestfile,atf
-./usr/tests/net/wireguard/Atffile		tests-net-tests		atf,rump
-./usr/tests/net/wireguard/Kyuafile		tests-net-tests		atf,rump,kyua
-./usr/tests/net/wireguard/t_basic		tests-net-tests		atf,rump
-./usr/tests/net/wireguard/t_interoperability	tests-net-tests		atf,rump
-./usr/tests/net/wireguard/t_misc		tests-net-tests		atf,rump
-./usr/tests/net/wireguard/t_tunnel		tests-net-tests		atf,rump
+./usr/tests/net/if_wg				tests-net-tests		compattestfile,atf
+./usr/tests/net/if_wg/Atffile			tests-net-tests		atf,rump
+./usr/tests/net/if_wg/Kyuafile			tests-net-tests		atf,rump,kyua
+./usr/tests/net/if_wg/t_basic			tests-net-tests		atf,rump
+./usr/tests/net/if_wg/t_interoperability	tests-net-tests		atf,rump
+./usr/tests/net/if_wg/t_misc			tests-net-tests		atf,rump
+./usr/tests/net/if_wg/t_tunnel			tests-net-tests		atf,rump
+./usr/tests/net/wireguard			tests-obsolete		obsolete
+./usr/tests/net/wireguard/Atffile		tests-obsolete		obsolete
+./usr/tests/net/wireguard/Kyuafile		tests-obsolete		obsolete
+./usr/tests/net/wireguard/t_basic		tests-obsolete		obsolete
+./usr/tests/net/wireguard/t_interoperability	tests-obsolete		obsolete
+./usr/tests/net/wireguard/t_misc		tests-obsolete		obsolete
+./usr/tests/net/wireguard/t_tunnel		tests-obsolete		obsolete
 ./usr/tests/net/in_cksum			tests-net-tests		compattestfile,atf
 ./usr/tests/net/in_cksum/Atffile		tests-net-tests		compattestfile,atf
 ./usr/tests/net/in_cksum/Kyuafile		tests-net-tests		compattestfile,atf,kyua
@@ -3953,10 +3960,14 @@
 ./usr/tests/net/sys/t_listen			tests-obsolete		obsolete
 ./usr/tests/net/sys/t_rfc6056			tests-net-tests		compattestfile,atf
 ./usr/tests/net/sys/t_socketpair		tests-obsolete		obsolete
-./usr/tests/net/wireguard			tests-net-tests		compattestfile,atf
-./usr/tests/net/wireguard/Atffile		tests-net-tests		compattestfile,atf
-./usr/tests/net/wireguard/Kyuafile		tests-net-tests		compattestfile,atf,kyua
-./usr/tests/net/wireguard/t_basic		tests-net-tests		atf,rump
+./usr/tests/net/if_wg				tests-net-tests		compattestfile,atf
+./usr/tests/net/if_wg/Atffile			tests-net-tests		compattestfile,atf
+./usr/tests/net/if_wg/Kyuafile			tests-net-tests		compattestfile,atf,kyua
+./usr/tests/net/if_wg/t_basic			tests-net-tests		atf,rump
+./usr/tests/net/wireguard			tests-obsolete		obsolete
+./usr/tests/net/wireguard/Atffile		tests-obsolete		obsolete
+./usr/tests/net/wireguard/Kyuafile		tests-obsolete		obsolete
+./usr/tests/net/wireguard/t_basic		tests-obsolete		obsolete
 ./usr/tests/opencrypto				tests-obsolete		obsolete
 ./usr/tests/rump				tests-rump-tests	compattestfile,atf
 ./usr/tests/rump/Atffile			tests-rump-tests	atf,rump

Index: src/doc/CHANGES
diff -u src/doc/CHANGES:1.2732 src/doc/CHANGES:1.2733
--- src/doc/CHANGES:1.2732	Thu Aug 20 21:45:46 2020
+++ src/doc/CHANGES	Wed Aug 26 16:03:41 2020
@@ -1,4 +1,4 @@
-# LIST OF CHANGES FROM LAST RELEASE:			<$Revision: 1.2732 $>
+# LIST OF CHANGES FROM LAST RELEASE:			<$Revision: 1.2733 $>
 #
 #
 # [Note: This file does not mention every change made to the NetBSD source tree.
@@ -273,4 +273,4 @@ Changes from NetBSD 9.0 to NetBSD 10.0:
 	kernel: Add getrandom system call. [riastradh 20200813]
 	kernel: Disable COMPAT_LINUX by default [jdolecek 20200816]
 	mips: Port crash(8) to mips.  [mrg 20200816]
-	wg(4): Add support for WireGuard. [ozaki-r 20200820]
+	wg(4): Add implementation of WireGuard protocol. [ozaki-r 20200820]

Index: src/etc/mtree/NetBSD.dist.tests
diff -u src/etc/mtree/NetBSD.dist.tests:1.175 src/etc/mtree/NetBSD.dist.tests:1.176
--- src/etc/mtree/NetBSD.dist.tests:1.175	Thu Aug 20 21:28:01 2020
+++ src/etc/mtree/NetBSD.dist.tests	Wed Aug 26 16:03:41 2020
@@ -1,4 +1,4 @@
-#	$NetBSD: NetBSD.dist.tests,v 1.175 2020/08/20 21:28:01 riastradh Exp $
+#	$NetBSD: NetBSD.dist.tests,v 1.176 2020/08/26 16:03:41 riastradh Exp $
 
 ./usr/libdata/debug/usr/tests
 ./usr/libdata/debug/usr/tests/atf
@@ -358,6 +358,7 @@
 ./usr/tests/net/if_tap
 ./usr/tests/net/if_tun
 ./usr/tests/net/if_vlan
+./usr/tests/net/if_wg
 ./usr/tests/net/in_cksum
 ./usr/tests/net/ipsec
 ./usr/tests/net/mcast
@@ -367,7 +368,6 @@
 ./usr/tests/net/npf
 ./usr/tests/net/route
 ./usr/tests/net/sys
-./usr/tests/net/wireguard
 ./usr/tests/rump
 ./usr/tests/rump/modautoload
 ./usr/tests/rump/rumpkern

Index: src/share/man/man4/wg.4
diff -u src/share/man/man4/wg.4:1.4 src/share/man/man4/wg.4:1.5
--- src/share/man/man4/wg.4:1.4	Fri Aug 21 08:09:55 2020
+++ src/share/man/man4/wg.4	Wed Aug 26 16:03:41 2020
@@ -1,4 +1,4 @@
-.\"	$NetBSD: wg.4,v 1.4 2020/08/21 08:09:55 wiz Exp $
+.\"	$NetBSD: wg.4,v 1.5 2020/08/26 16:03:41 riastradh Exp $
 .\"
 .\" Copyright (c) 2020 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -30,7 +30,7 @@
 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 .Sh NAME
 .Nm wg
-.Nd WireGuard virtual private network
+.Nd virtual private network tunnel (EXPERIMENTAL)
 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 .Sh SYNOPSIS
 .Cd pseudo-device wg
@@ -38,12 +38,16 @@
 .Sh DESCRIPTION
 The
 .Nm
-interface implements the WireGuard point-to-point roaming-capable
-virtual private network tunnel, configured with
+interface implements a point-to-point roaming-capable virtual private
+network tunnel, configured with
 .Xr ifconfig 8
 and
 .Xr wgconfig 8 .
 .Pp
+.Sy WARNING:
+.Nm
+is experimental.
+.Pp
 Packets exchanged on a
 .Nm
 interface are authenticated and encrypted with a secret key negotiated
@@ -91,14 +95,14 @@ Stationary server:                      
 .Pp
 Generate key pairs on A and B:
 .Bd -literal -offset abcd
-A# wg-keygen > /etc/wireguard/wg0
-A# wg-keygen --pub < /etc/wireguard/wg0 > /etc/wireguard/wg0.pub
-A# cat /etc/wireguard/wg0.pub
+A# wg-keygen > /etc/wg/wg0
+A# wg-keygen --pub < /etc/wg/wg0 > /etc/wg/wg0.pub
+A# cat /etc/wg/wg0.pub
 N+B4Nelg+4ysvbLW3qenxIwrJVE9MdjMyqrIisH7V0Y=
 
-B# wg-keygen > /etc/wireguard/wg0
-B# wg-keygen --pub < /etc/wireguard/wg0 > /etc/wireguard/wg0.pub
-B# cat /etc/wireguard/wg0.pub
+B# wg-keygen > /etc/wg/wg0
+B# wg-keygen --pub < /etc/wg/wg0 > /etc/wg/wg0.pub
+B# cat /etc/wg/wg0.pub
 X7EGm3T3IfodBcyilkaC89j0SH3XD6+/pwvp7Dgp5SU=
 .Ed
 .Pp
@@ -106,7 +110,7 @@ Configure A to listen on port 1234 and a
 appear in the 10.0.1.0/24 subnet:
 .Bd -literal -offset abcd
 A# ifconfig wg0 create 10.0.1.0/24
-A# wgconfig wg0 set private-key /etc/wireguard/wg0
+A# wgconfig wg0 set private-key /etc/wg/wg0
 A# wgconfig wg0 set listen-port 1234
 A# wgconfig wg0 add peer B \e
     X7EGm3T3IfodBcyilkaC89j0SH3XD6+/pwvp7Dgp5SU= \e
@@ -121,7 +125,7 @@ Configure B to connect to A at 1.2.3.4 o
 begin to flow:
 .Bd -literal -offset abcd
 B# ifconfig wg0 create 10.0.1.1/24
-B# wgconfig wg0 set private-key /etc/wireguard/wg0
+B# wgconfig wg0 set private-key /etc/wg/wg0
 B# wgconfig wg0 add peer A \e
     N+B4Nelg+4ysvbLW3qenxIwrJVE9MdjMyqrIisH7V0Y= \e
     --allowed-ips=10.0.1.0/32 \e
@@ -139,9 +143,19 @@ PING 10.0.1.0 (10.0.1.0): 56 data bytes
 .Sh SEE ALSO
 .Xr wg-keygen 8 ,
 .Xr wgconfig 8
+.\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+.Sh COMPATIBILITY
+The
+.Nm
+interface aims to be compatible with the WireGuard protocol, as
+described in:
+.Pp
 .Rs
-.%T WireGuard: fast, modern, secure VPN tunnel
-.%U https://www.wireguard.com/
+.%A Jason A. Donenfeld
+.%T WireGuard: Next Generation Kernel Network Tunnel
+.%U https://web.archive.org/web/20180805103233/https://www.wireguard.com/papers/wireguard.pdf
+.%O Document ID: 4846ada1492f5d92198df154f48c3d54205657bc
+.%D 2018-06-30
 .Re
 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 .Sh HISTORY

Index: src/sys/arch/amd64/conf/ALL
diff -u src/sys/arch/amd64/conf/ALL:1.161 src/sys/arch/amd64/conf/ALL:1.162
--- src/sys/arch/amd64/conf/ALL:1.161	Thu Aug 20 21:36:11 2020
+++ src/sys/arch/amd64/conf/ALL	Wed Aug 26 16:03:41 2020
@@ -1,4 +1,4 @@
-# $NetBSD: ALL,v 1.161 2020/08/20 21:36:11 riastradh Exp $
+# $NetBSD: ALL,v 1.162 2020/08/26 16:03:41 riastradh Exp $
 # From NetBSD: GENERIC,v 1.787 2006/10/01 18:37:54 bouyer Exp
 #
 # ALL machine description file
@@ -17,7 +17,7 @@ include 	"arch/amd64/conf/std.amd64"
 
 options 	INCLUDE_CONFIG_FILE	# embed config file in kernel binary
 
-#ident		"ALL-$Revision: 1.161 $"
+#ident		"ALL-$Revision: 1.162 $"
 
 maxusers	64		# estimated number of users
 
@@ -1641,7 +1641,7 @@ pseudo-device	npf			# NPF packet filter
 pseudo-device	kttcp
 # srt is EXPERIMENTAL
 pseudo-device	srt			# source-address-based routing
-pseudo-device	wg			# WireGuard
+pseudo-device	wg			# VPN tunnel compatible with WireGuard
 
 pseudo-device	canloop			# CAN loopback interface
 

Index: src/sys/net/if_types.h
diff -u src/sys/net/if_types.h:1.30 src/sys/net/if_types.h:1.31
--- src/sys/net/if_types.h:1.30	Thu Aug 20 21:21:32 2020
+++ src/sys/net/if_types.h	Wed Aug 26 16:03:41 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_types.h,v 1.30 2020/08/20 21:21:32 riastradh Exp $	*/
+/*	$NetBSD: if_types.h,v 1.31 2020/08/26 16:03:41 riastradh Exp $	*/
 
 /*
  * Copyright (c) 1989, 1993, 1994
@@ -267,6 +267,5 @@
 #define IFT_CARP	0xf8		/* Common Address Redundancy Protocol */
 #define IFT_IPSEC	0xf9		/* IPsec I/F */
 #define IFT_MBIM	0xfa		/* Mobile Broadband Interface Model */
-#define IFT_WIREGUARD	0xfb		/* WireGuard */
 
 #endif /* !_NET_IF_TYPES_H_ */

Index: src/sys/net/if_wg.c
diff -u src/sys/net/if_wg.c:1.23 src/sys/net/if_wg.c:1.24
--- src/sys/net/if_wg.c:1.23	Sun Aug 23 18:52:53 2020
+++ src/sys/net/if_wg.c	Wed Aug 26 16:03:41 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_wg.c,v 1.23 2020/08/23 18:52:53 riastradh Exp $	*/
+/*	$NetBSD: if_wg.c,v 1.24 2020/08/26 16:03:41 riastradh Exp $	*/
 
 /*
  * Copyright (C) Ryota Ozaki <[email protected]>
@@ -30,20 +30,18 @@
  */
 
 /*
- * This is an implementation of WireGuard, a fast, modern, secure VPN protocol,
- * for the NetBSD kernel and rump kernels.
- *
- * The implementation is based on the paper of WireGuard as of 2018-06-30 [1].
- * The paper is referred in the source code with label [W].  Also the
- * specification of the Noise protocol framework as of 2018-07-11 [2] is
- * referred with label [N].
+ * This network interface aims to implement the WireGuard protocol.
+ * The implementation is based on the paper of WireGuard as of
+ * 2018-06-30 [1].  The paper is referred in the source code with label
+ * [W].  Also the specification of the Noise protocol framework as of
+ * 2018-07-11 [2] is referred with label [N].
  *
  * [1] https://www.wireguard.com/papers/wireguard.pdf
  * [2] http://noiseprotocol.org/noise.pdf
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_wg.c,v 1.23 2020/08/23 18:52:53 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_wg.c,v 1.24 2020/08/26 16:03:41 riastradh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -120,7 +118,7 @@ __KERNEL_RCSID(0, "$NetBSD: if_wg.c,v 1.
  * Data structures
  * - struct wg_softc is an instance of wg interfaces
  *   - It has a list of peers (struct wg_peer)
- *   - It has a kthread that sends/receives WireGuard handshake messages and
+ *   - It has a kthread that sends/receives handshake messages and
  *     runs event handlers
  *   - It has its own two routing tables: one is for IPv4 and the other IPv6
  * - struct wg_peer is a representative of a peer
@@ -3346,7 +3344,7 @@ wg_if_attach(struct wg_softc *wg)
 	wg->wg_if.if_output = wg_output;
 	wg->wg_if.if_init = wg_init;
 	wg->wg_if.if_stop = wg_stop;
-	wg->wg_if.if_type = IFT_WIREGUARD;
+	wg->wg_if.if_type = IFT_OTHER;
 	wg->wg_if.if_dlt = DLT_NULL;
 	wg->wg_if.if_softc = wg;
 	IFQ_SET_READY(&wg->wg_if.if_snd);
@@ -4399,14 +4397,14 @@ wg_stop(struct ifnet *ifp, int disable)
 }
 
 #ifdef WG_DEBUG_PARAMS
-SYSCTL_SETUP(sysctl_net_wireguard_setup, "sysctl net.wireguard setup")
+SYSCTL_SETUP(sysctl_net_wg_setup, "sysctl net.wg setup")
 {
 	const struct sysctlnode *node = NULL;
 
 	sysctl_createv(clog, 0, NULL, &node,
 	    CTLFLAG_PERMANENT,
-	    CTLTYPE_NODE, "wireguard",
-	    SYSCTL_DESCR("WireGuard"),
+	    CTLTYPE_NODE, "wg",
+	    SYSCTL_DESCR("wg(4)"),
 	    NULL, 0, NULL, 0,
 	    CTL_NET, CTL_CREATE, CTL_EOL);
 	sysctl_createv(clog, 0, &node, NULL,

Index: src/sys/rump/net/Makefile.rumpnetcomp
diff -u src/sys/rump/net/Makefile.rumpnetcomp:1.21 src/sys/rump/net/Makefile.rumpnetcomp:1.22
--- src/sys/rump/net/Makefile.rumpnetcomp:1.21	Thu Aug 20 21:21:32 2020
+++ src/sys/rump/net/Makefile.rumpnetcomp	Wed Aug 26 16:03:41 2020
@@ -1,11 +1,11 @@
-#	$NetBSD: Makefile.rumpnetcomp,v 1.21 2020/08/20 21:21:32 riastradh Exp $
+#	$NetBSD: Makefile.rumpnetcomp,v 1.22 2020/08/26 16:03:41 riastradh Exp $
 #
 
 .include <bsd.own.mk>
 
 RUMPNETCOMP=	agr bridge net net80211 netbt netcan netinet netinet6 netipsec
 RUMPNETCOMP+=	gif ipsec netmpls npf l2tp local pppoe shmif tap tun vlan
-RUMPNETCOMP+=	wireguard
+RUMPNETCOMP+=	wg
 
 .if ${MKSLJIT} != "no" || make(rumpdescribe)
 RUMPNETCOMP+=	bpfjit

Index: src/tests/net/Makefile
diff -u src/tests/net/Makefile:1.35 src/tests/net/Makefile:1.36
--- src/tests/net/Makefile:1.35	Thu Aug 20 21:21:32 2020
+++ src/tests/net/Makefile	Wed Aug 26 16:03:42 2020
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.35 2020/08/20 21:21:32 riastradh Exp $
+# $NetBSD: Makefile,v 1.36 2020/08/26 16:03:42 riastradh Exp $
 
 .include <bsd.own.mk>
 
@@ -8,7 +8,7 @@ TESTS_SUBDIRS=		fdpass in_cksum net sys
 .if (${MKRUMP} != "no") && !defined(BSD_MK_COMPAT_FILE)
 TESTS_SUBDIRS+=		arp bpf bpfilter can carp icmp if if_bridge if_gif
 TESTS_SUBDIRS+=		if_ipsec if_l2tp if_loop if_pppoe if_tap if_tun ipsec
-TESTS_SUBDIRS+=		mcast mpls ndp npf route if_vlan wireguard
+TESTS_SUBDIRS+=		mcast mpls ndp npf route if_vlan if_wg
 .if (${MKSLJIT} != "no")
 TESTS_SUBDIRS+=		bpfjit
 .endif

Index: src/usr.sbin/wg-keygen/wg-keygen.8
diff -u src/usr.sbin/wg-keygen/wg-keygen.8:1.2 src/usr.sbin/wg-keygen/wg-keygen.8:1.3
--- src/usr.sbin/wg-keygen/wg-keygen.8:1.2	Thu Aug 20 21:36:00 2020
+++ src/usr.sbin/wg-keygen/wg-keygen.8	Wed Aug 26 16:03:42 2020
@@ -1,4 +1,4 @@
-.\"	$NetBSD: wg-keygen.8,v 1.2 2020/08/20 21:36:00 riastradh Exp $
+.\"	$NetBSD: wg-keygen.8,v 1.3 2020/08/26 16:03:42 riastradh Exp $
 .\"
 .\" Copyright (C) Ryota Ozaki <[email protected]>
 .\" All rights reserved.
@@ -33,7 +33,7 @@
 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 .Sh NAME
 .Nm wg-keygen
-.Nd generate keys for WireGuard interfaces
+.Nd generate keys for wg interfaces
 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 .Sh SYNOPSIS
 .Nm
@@ -42,7 +42,8 @@
 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 .Sh DESCRIPTION
 .Nm
-generates keys for WireGuard.
+generates keys for
+.Xr wg 4 .
 .Bl -tag -width abcd
 .It Nm
 Generate a private key and print it to standard output.

Index: src/usr.sbin/wg-userspace/wg-userspace.8
diff -u src/usr.sbin/wg-userspace/wg-userspace.8:1.2 src/usr.sbin/wg-userspace/wg-userspace.8:1.3
--- src/usr.sbin/wg-userspace/wg-userspace.8:1.2	Thu Aug 20 22:17:16 2020
+++ src/usr.sbin/wg-userspace/wg-userspace.8	Wed Aug 26 16:03:42 2020
@@ -1,4 +1,4 @@
-.\"	$NetBSD: wg-userspace.8,v 1.2 2020/08/20 22:17:16 riastradh Exp $
+.\"	$NetBSD: wg-userspace.8,v 1.3 2020/08/26 16:03:42 riastradh Exp $
 .\"
 .\" Copyright (C) Ryota Ozaki <[email protected]>
 .\" All rights reserved.
@@ -33,7 +33,7 @@
 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 .Sh NAME
 .Nm wg-userspace
-.Nd manipulate WireGuard userspace instances
+.Nd manipulate wg userspace instances (EXPERIMENTAL)
 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 .Sh SYNOPSIS
 .Ar id
@@ -42,39 +42,45 @@
 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 .Sh DESCRIPTION
 .Nm
-is used to create, destroy and configure WireGuard userspace instances.
+is used to create, destroy and configure
+.Xr wg 4
+userspace instances.
+.Pp
+.Sy WARNING:
+.Nm
+is experimental.
 .Pp
 The following commands are supported:
 .Bl -tag -width "destroy"
 .It Cm create
-Create a WireGuard interface.
+Create an interface.
 The interface will appear as
 .Li tun Ns Ar id
 to the rest of the system, and will be served by a rump server in whose
 context the interface appears as
 .Li wg Ns Ar id .
 .It Cm destroy
-Destroy a WireGuard interface and stop the rump server behind it.
+Destroy an interface and stop the rump server behind it.
 .It Cm ifconfig Ar wgN Ar args...
 Run
 .Xr ifconfig 8
-in the context of the WireGuard interface's rump server.
+in the context of the interface's rump server.
 For example,
 .Bd -literal -compact
 	# wg-userspace 0 ifconfig wg0 10.0.1.0/24
 .Ed
-will set the WireGuard interface's IP address.
+will set the interface's IP address.
 .It Cm wgconfig Ar wgN Ar args...
 Run
 .Xr wgconfig 8
-in the context of the WireGuard interface's rump server.
+in the context of the interface's rump server.
 For example,
 .Bd -literal -compact
 	# wg-userspace 0 wgconfig wg0 set listen-port 1234
 .Ed
-will set the WireGuard interface's listening port.
+will set the interface's listening port.
 .It Cm debug Ar command Op Ar args...
-Run an arbitrary command in the context of the WireGuard interface's
+Run an arbitrary command in the context of the interface's
 rump server, using
 .Xr rumphijack 3 .
 .El

Index: src/usr.sbin/wg-userspace/wg-userspace.sh
diff -u src/usr.sbin/wg-userspace/wg-userspace.sh:1.1 src/usr.sbin/wg-userspace/wg-userspace.sh:1.2
--- src/usr.sbin/wg-userspace/wg-userspace.sh:1.1	Thu Aug 20 21:28:02 2020
+++ src/usr.sbin/wg-userspace/wg-userspace.sh	Wed Aug 26 16:03:42 2020
@@ -2,7 +2,7 @@
 
 RUMPLIBS="-lrumpnet -lrumpnet_net -lrumpnet_netinet \
     -lrumpdev -lrumpvfs -lrumpdev_opencrypto -lrumpkern_z \
-    -lrumpkern_crypto -lrumpnet_wireguard -lrumpnet_netinet6"
+    -lrumpkern_crypto -lrumpnet_wg -lrumpnet_netinet6"
 HIJACKING="env LD_PRELOAD=/usr/lib/librumphijack.so \
     RUMPHIJACK=path=/rump,socket=all:nolocal,sysctl=yes"
 

Index: src/usr.sbin/wgconfig/wgconfig.8
diff -u src/usr.sbin/wgconfig/wgconfig.8:1.9 src/usr.sbin/wgconfig/wgconfig.8:1.10
--- src/usr.sbin/wgconfig/wgconfig.8:1.9	Fri Aug 21 03:44:58 2020
+++ src/usr.sbin/wgconfig/wgconfig.8	Wed Aug 26 16:03:42 2020
@@ -1,4 +1,4 @@
-.\"	$NetBSD: wgconfig.8,v 1.9 2020/08/21 03:44:58 uwe Exp $
+.\"	$NetBSD: wgconfig.8,v 1.10 2020/08/26 16:03:42 riastradh Exp $
 .\"
 .\" Copyright (C) Ryota Ozaki <[email protected]>
 .\" All rights reserved.
@@ -33,7 +33,7 @@
 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 .Sh NAME
 .Nm wgconfig
-.Nd configure WireGuard interface parameters
+.Nd configure wg interface parameters
 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
 .Sh SYNOPSIS
 .Nm
@@ -74,7 +74,7 @@
 .Sh DESCRIPTION
 The
 .Nm
-utility is used to configure or display a WireGuard
+utility is used to configure or display a
 .Xr wg 4
 interface's parameters and status.
 Every
@@ -91,7 +91,7 @@ have a fixed endpoint IP address and a p
 The following commands are supported:
 .Bl -tag -width abcd
 .It Cm "show all"
-Show all WireGuard peers.
+Show all peers.
 No secret keys are included in the output.
 .It Cm "show peer" Ar name Op Fl Fl show-preshared-key
 Show the peer named
@@ -117,7 +117,7 @@ to the base64-encoded private key in the
 .It Cm "set listen-port" Ar port
 Set the UDP port number that
 .Li wg Ns Ar N\|
-listens for incoming WireGuard sessions on.
+listens for incoming sessions on.
 This allows a peer to start a new session without having a specific
 endpoint IP address configured.
 .It Cm "add peer" Ar name Ar pubkey Op Ar options ...
@@ -146,14 +146,16 @@ Set a secret preshared key generated by
 If the preshared key can be arranged in advance on a medium not subject
 to eavesdropping, then it defends against possible future quantum
 cryptanalysis of the X25519 key agreement.
-WireGuard still uses X25519 key agreements in order to erase past
+.Nm
+still uses X25519 key agreements in order to erase past
 session keys so that past session transcripts remain secret should one
 of the endpoints be compromised in the future; the preshared key is an
 additional measure on top.
 .It Fl Fl endpoint Ns Li \&= Ns Ar ip Ns Li \&: Ns Ar port
 Set the peer's endpoint address outside the tunnel.
-This is optional for a VPN server if the WireGuard interface is
-configured to listen on a port number.
+This is optional for a VPN server if the
+.Nm
+interface is configured to listen on a port number.
 .It Fl Fl allowed-ips Ns Li \&= Ns Ar ip1 Ns Li \&/ Ns Ar cidr1 Ns \
     Op Li \&, Ns Ar ip2 Ns Li \&/ Ns Ar cidr2 Ns Li \&, Ns Ar ...
 Set the IP address ranges that the peer is allowed to select inside the

Added files:

Index: src/sys/rump/net/lib/libwg/Makefile
diff -u /dev/null src/sys/rump/net/lib/libwg/Makefile:1.1
--- /dev/null	Wed Aug 26 16:03:43 2020
+++ src/sys/rump/net/lib/libwg/Makefile	Wed Aug 26 16:03:42 2020
@@ -0,0 +1,27 @@
+#	$NetBSD: Makefile,v 1.1 2020/08/26 16:03:42 riastradh Exp $
+#
+
+.PATH:	${.CURDIR}/../../../../net ${.CURDIR}/../../../../netinet	\
+	${.CURDIR}/../../../../netinet6
+
+LIB=	rumpnet_wg
+COMMENT= virtual private network tunnel
+
+IOCONF=	WG.ioconf
+SRCS=	if_wg.c
+
+CPPFLAGS.if_wg.c+=	-DWG_RUMPKERNEL
+
+# For sysctl knobs
+CPPFLAGS.if_wg.c+=	-DWG_DEBUG_PARAMS
+.ifdef RUMP_DEBUG
+CPPFLAGS.if_wg.c+=	-DWG_DEBUG_TRACE -DWG_DEBUG_LOG
+.endif
+
+SRCS+=	wg_component.c
+
+#SRCS+=	wg_user.c
+RUMPCOMP_USER_SRCS=	wg_user.c
+
+.include <bsd.lib.mk>
+.include <bsd.klinks.mk>
Index: src/sys/rump/net/lib/libwg/WG.ioconf
diff -u /dev/null src/sys/rump/net/lib/libwg/WG.ioconf:1.1
--- /dev/null	Wed Aug 26 16:03:43 2020
+++ src/sys/rump/net/lib/libwg/WG.ioconf	Wed Aug 26 16:03:42 2020
@@ -0,0 +1,7 @@
+#	$NetBSD: WG.ioconf,v 1.1 2020/08/26 16:03:42 riastradh Exp $
+
+ioconf		wg
+
+include		"conf/files"
+
+pseudo-device   wg
Index: src/sys/rump/net/lib/libwg/wg_component.c
diff -u /dev/null src/sys/rump/net/lib/libwg/wg_component.c:1.1
--- /dev/null	Wed Aug 26 16:03:43 2020
+++ src/sys/rump/net/lib/libwg/wg_component.c	Wed Aug 26 16:03:42 2020
@@ -0,0 +1,42 @@
+/*	$NetBSD: wg_component.c,v 1.1 2020/08/26 16:03:42 riastradh Exp $	*/
+
+/*
+ * Copyright (c) 2015 Internet Initiative Japan Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: wg_component.c,v 1.1 2020/08/26 16:03:42 riastradh Exp $");
+
+#include <sys/param.h>
+
+#include <rump-sys/kern.h>
+
+int wgattach(int);
+
+RUMP_COMPONENT(RUMP_COMPONENT_NET_IF)
+{
+
+	wgattach(0);
+}
Index: src/sys/rump/net/lib/libwg/wg_user.c
diff -u /dev/null src/sys/rump/net/lib/libwg/wg_user.c:1.1
--- /dev/null	Wed Aug 26 16:03:43 2020
+++ src/sys/rump/net/lib/libwg/wg_user.c	Wed Aug 26 16:03:42 2020
@@ -0,0 +1,423 @@
+/*	$NetBSD: wg_user.c,v 1.1 2020/08/26 16:03:42 riastradh Exp $	*/
+
+/*
+ * Copyright (C) Ryota Ozaki <[email protected]>
+ * All rights reserved.
+ *
+ * Based on wg_user.c by Antti Kantee.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: wg_user.c,v 1.1 2020/08/26 16:03:42 riastradh Exp $");
+
+#ifndef _KERNEL
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <sys/param.h>
+
+#include <net/if.h>
+#include <net/if_tun.h>
+
+#include <netinet/in.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <poll.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <rump/rumpuser_component.h>
+
+#include "wg_user.h"
+
+struct wg_user {
+	struct wg_softc *wgu_sc;
+	int wgu_devnum;
+	char wgu_tun_name[IFNAMSIZ];
+
+	int wgu_fd;
+	int wgu_sock4;
+	int wgu_sock6;
+	int wgu_pipe[2];
+	pthread_t wgu_rcvthr;
+
+	int wgu_dying;
+
+	char wgu_rcvbuf[9018]; /* jumbo frame max len */
+};
+
+static int
+open_tun(const char *tun_name)
+{
+	char tun_path[MAXPATHLEN];
+	int n, fd, error;
+
+	n = snprintf(tun_path, sizeof(tun_path), "/dev/%s", tun_name);
+	if (n == MAXPATHLEN)
+		return E2BIG;
+
+	fd = open(tun_path, O_RDWR);
+	if (fd == -1) {
+		fprintf(stderr, "%s: can't open %s: %s\n",
+		    __func__, tun_name, strerror(errno));
+	}
+
+	int i = 1;
+	error = ioctl(fd, TUNSLMODE, &i);
+	if (error == -1) {
+		close(fd);
+		fd = -1;
+	}
+
+	return fd;
+}
+
+static void
+close_tun(struct wg_user *wgu)
+{
+	int s;
+	struct ifreq ifr = {};
+
+	close(wgu->wgu_fd);
+
+	s = socket(AF_INET, SOCK_DGRAM, 0);
+	if (s == -1)
+		return; /* XXX */
+	strcpy(ifr.ifr_name, wgu->wgu_tun_name);
+	(void)ioctl(s, SIOCIFDESTROY, &ifr);
+	close(s);
+}
+
+static void *
+wg_user_rcvthread(void *aaargh)
+{
+	struct wg_user *wgu = aaargh;
+	struct pollfd pfd[4];
+	ssize_t nn = 0;
+	int prv;
+
+	rumpuser_component_kthread();
+
+	pfd[0].fd = wgu->wgu_fd;
+	pfd[0].events = POLLIN;
+	pfd[1].fd = wgu->wgu_pipe[0];
+	pfd[1].events = POLLIN;
+	pfd[2].fd = wgu->wgu_sock4;
+	pfd[2].events = POLLIN;
+	pfd[3].fd = wgu->wgu_sock6;
+	pfd[3].events = POLLIN;
+
+	while (!wgu->wgu_dying) {
+		struct iovec iov[2];
+
+		prv = poll(pfd, 4, -1);
+		if (prv == 0)
+			continue;
+		if (prv == -1) {
+			/* XXX */
+			fprintf(stderr, "%s: poll error: %d\n",
+			    wgu->wgu_tun_name, errno);
+			sleep(1);
+			continue;
+		}
+		if (pfd[1].revents & POLLIN)
+			continue;
+
+		/* Receive user packets from tun */
+		if (pfd[0].revents & POLLIN) {
+			nn = read(wgu->wgu_fd, wgu->wgu_rcvbuf, sizeof(wgu->wgu_rcvbuf));
+			if (nn == -1 && errno == EAGAIN)
+				continue;
+
+			if (nn < 1) {
+				/* XXX */
+				fprintf(stderr, "%s: receive failed\n",
+				    wgu->wgu_tun_name);
+				sleep(1);
+				continue;
+			}
+
+			iov[0].iov_base = wgu->wgu_rcvbuf;
+			iov[0].iov_len = ((struct sockaddr *)wgu->wgu_rcvbuf)->sa_len;
+
+			iov[1].iov_base = (char *)wgu->wgu_rcvbuf + iov[0].iov_len;
+			iov[1].iov_len = nn - iov[0].iov_len;
+
+			rumpuser_component_schedule(NULL);
+			rumpkern_wg_recv_user(wgu->wgu_sc, iov, 2);
+			rumpuser_component_unschedule();
+		}
+
+		/* Receive wg UDP/IPv4 packets from a peer */
+		if (pfd[2].revents & POLLIN) {
+			struct sockaddr_in sin;
+			socklen_t len = sizeof(sin);
+			nn = recvfrom(wgu->wgu_sock4, wgu->wgu_rcvbuf,
+			    sizeof(wgu->wgu_rcvbuf), 0, (struct sockaddr *)&sin,
+			    &len);
+			if (nn == -1 && errno == EAGAIN)
+				continue;
+			if (len != sizeof(sin))
+				continue;
+			iov[0].iov_base = &sin;
+			iov[0].iov_len = sin.sin_len;
+
+			iov[1].iov_base = wgu->wgu_rcvbuf;
+			iov[1].iov_len = nn;
+
+			rumpuser_component_schedule(NULL);
+			rumpkern_wg_recv_peer(wgu->wgu_sc, iov, 2);
+			rumpuser_component_unschedule();
+		}
+
+		/* Receive wg UDP/IPv6 packets from a peer */
+		if (pfd[3].revents & POLLIN) {
+			struct sockaddr_in6 sin6;
+			socklen_t len = sizeof(sin6);
+			nn = recvfrom(wgu->wgu_sock6, wgu->wgu_rcvbuf,
+			    sizeof(wgu->wgu_rcvbuf), 0, (struct sockaddr *)&sin6,
+			    &len);
+			if (nn == -1 && errno == EAGAIN)
+				continue;
+			if (len != sizeof(sin6))
+				continue;
+			iov[0].iov_base = &sin6;
+			iov[0].iov_len = sin6.sin6_len;
+
+			iov[1].iov_base = wgu->wgu_rcvbuf;
+			iov[1].iov_len = nn;
+
+			rumpuser_component_schedule(NULL);
+			rumpkern_wg_recv_peer(wgu->wgu_sc, iov, 2);
+			rumpuser_component_unschedule();
+		}
+	}
+
+	assert(wgu->wgu_dying);
+
+	rumpuser_component_kthread_release();
+	return NULL;
+}
+
+int
+rumpuser_wg_create(const char *tun_name, struct wg_softc *wg,
+    struct wg_user **wgup)
+{
+	struct wg_user *wgu = NULL;
+	void *cookie;
+	int rv;
+
+	cookie = rumpuser_component_unschedule();
+
+	wgu = malloc(sizeof(*wgu));
+	if (wgu == NULL) {
+		rv = errno;
+		goto oerr1;
+	}
+
+	wgu->wgu_fd = open_tun(tun_name);
+	if (wgu->wgu_fd == -1) {
+		rv = errno;
+		goto oerr2;
+	}
+	strcpy(wgu->wgu_tun_name, tun_name);
+	wgu->wgu_sc = wg;
+
+	if (pipe(wgu->wgu_pipe) == -1) {
+		rv = errno;
+		goto oerr3;
+	}
+
+	wgu->wgu_sock4 = socket(AF_INET, SOCK_DGRAM, 0);
+	wgu->wgu_sock6 = socket(AF_INET6, SOCK_DGRAM, 0);
+	if (wgu->wgu_sock4 == -1 || wgu->wgu_sock6 == -1) {
+		rv = errno;
+		goto oerr4;
+	}
+
+	rv = pthread_create(&wgu->wgu_rcvthr, NULL, wg_user_rcvthread, wgu);
+	if (rv != 0)
+		goto oerr5;
+
+	rumpuser_component_schedule(cookie);
+	*wgup = wgu;
+	return 0;
+
+ oerr5:
+	close(wgu->wgu_pipe[0]);
+	close(wgu->wgu_pipe[1]);
+ oerr4:
+	if (wgu->wgu_sock4 != -1)
+		close(wgu->wgu_sock4);
+	if (wgu->wgu_sock6 != -1)
+		close(wgu->wgu_sock6);
+ oerr3:
+	close_tun(wgu);
+ oerr2:
+	free(wgu);
+ oerr1:
+	rumpuser_component_schedule(cookie);
+	return rumpuser_component_errtrans(rv);
+}
+
+/*
+ * Send decrypted packets to users via a tun.
+ */
+void
+rumpuser_wg_send_user(struct wg_user *wgu, struct iovec *iov, size_t iovlen)
+{
+	void *cookie = rumpuser_component_unschedule();
+	ssize_t idontcare __attribute__((__unused__));
+
+	/*
+	 * no need to check for return value; packets may be dropped
+	 *
+	 * ... sorry, I spoke too soon.  We need to check it because
+	 * apparently gcc reinvented const poisoning and it's very
+	 * hard to say "thanks, I know I'm not using the result,
+	 * but please STFU and let's get on with something useful".
+	 * So let's trick gcc into letting us share the compiler
+	 * experience.
+	 */
+	idontcare = writev(wgu->wgu_fd, iov, iovlen);
+
+	rumpuser_component_schedule(cookie);
+}
+
+/*
+ * Send wg messages to a peer.
+ */
+int
+rumpuser_wg_send_peer(struct wg_user *wgu, struct sockaddr *sa,
+    struct iovec *iov, size_t iovlen)
+{
+	void *cookie = rumpuser_component_unschedule();
+	int s, error = 0;
+	size_t i;
+	ssize_t sent;
+
+	if (sa->sa_family == AF_INET)
+		s = wgu->wgu_sock4;
+	else
+		s = wgu->wgu_sock6;
+
+	for (i = 0; i < iovlen; i++) {
+		sent = sendto(s, iov[i].iov_base, iov[i].iov_len, 0, sa,
+		    sa->sa_len);
+		if (sent == -1 || (size_t)sent != iov[i].iov_len) {
+			error = errno;
+			break;
+		}
+	}
+
+	rumpuser_component_schedule(cookie);
+
+	return error;
+}
+
+int
+rumpuser_wg_ioctl(struct wg_user *wgu, u_long cmd, void *data, int af)
+{
+	void *cookie = rumpuser_component_unschedule();
+	int s, error;
+
+	s = socket(af, SOCK_DGRAM, 0);
+	if (s == -1)
+		return errno;
+	error = ioctl(s, cmd, data);
+	close(s);
+
+	rumpuser_component_schedule(cookie);
+
+	return error == -1 ? errno : 0;
+}
+
+int
+rumpuser_wg_sock_bind(struct wg_user *wgu, const uint16_t port)
+{
+	int error;
+	struct sockaddr_in sin;
+	struct sockaddr_in6 sin6;
+
+	memset(&sin, 0, sizeof(sin));
+	sin.sin_family = AF_INET;
+	sin.sin_len = sizeof(sin);
+	sin.sin_addr.s_addr = INADDR_ANY;
+	sin.sin_port = htons(port);
+
+	error = bind(wgu->wgu_sock4, (struct sockaddr *)&sin, sizeof(sin));
+	if (error == -1)
+		return errno;
+
+	memset(&sin6, 0, sizeof(sin6));
+	sin6.sin6_family = AF_INET6;
+	sin6.sin6_len = sizeof(sin6);
+	sin6.sin6_addr = in6addr_any;
+	sin6.sin6_port = htons(port);
+
+	error = bind(wgu->wgu_sock6, (struct sockaddr *)&sin6, sizeof(sin6));
+	if (error == -1)
+		return errno;
+
+	return 0;
+}
+
+void
+rumpuser_wg_destroy(struct wg_user *wgu)
+{
+	void *cookie = rumpuser_component_unschedule();
+
+	wgu->wgu_dying = 1;
+	if (write(wgu->wgu_pipe[1],
+	    &wgu->wgu_dying, sizeof(wgu->wgu_dying)) == -1) {
+		/*
+		 * this is here mostly to avoid a compiler warning
+		 * about ignoring the return value of write()
+		 */
+		fprintf(stderr, "%s: failed to signal thread\n",
+		    wgu->wgu_tun_name);
+	}
+	pthread_join(wgu->wgu_rcvthr, NULL);
+	close_tun(wgu);
+	close(wgu->wgu_pipe[0]);
+	close(wgu->wgu_pipe[1]);
+	free(wgu);
+
+	rumpuser_component_schedule(cookie);
+}
+
+char *
+rumpuser_wg_get_tunname(struct wg_user *wgu)
+{
+
+	return wgu->wgu_tun_name;
+}
+#endif
Index: src/sys/rump/net/lib/libwg/wg_user.h
diff -u /dev/null src/sys/rump/net/lib/libwg/wg_user.h:1.1
--- /dev/null	Wed Aug 26 16:03:43 2020
+++ src/sys/rump/net/lib/libwg/wg_user.h	Wed Aug 26 16:03:42 2020
@@ -0,0 +1,52 @@
+/*	$NetBSD: wg_user.h,v 1.1 2020/08/26 16:03:42 riastradh Exp $	*/
+
+/*
+ * Copyright (C) Ryota Ozaki <[email protected]>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+struct wg_user;
+struct wg_softc;
+
+/*
+ * Defined in wg_user.c and called from if_wg.c.
+ */
+int	rumpuser_wg_create(const char *tun_name, struct wg_softc *,
+	    struct wg_user **);
+void	rumpuser_wg_destroy(struct wg_user *);
+
+void	rumpuser_wg_send_user(struct wg_user *, struct iovec *, size_t);
+int	rumpuser_wg_send_peer(struct wg_user *, struct sockaddr *,
+	    struct iovec *, size_t);
+
+int	rumpuser_wg_ioctl(struct wg_user *, u_long, void *, int);
+int	rumpuser_wg_sock_bind(struct wg_user *, const uint16_t);
+
+char *	rumpuser_wg_get_tunname(struct wg_user *);
+
+/*
+ * Defined in if_wg.c and called from wg_user.c.
+ */
+void	rumpkern_wg_recv_user(struct wg_softc *, struct iovec *, size_t);
+void	rumpkern_wg_recv_peer(struct wg_softc *, struct iovec *, size_t);

Index: src/tests/net/if_wg/Makefile
diff -u /dev/null src/tests/net/if_wg/Makefile:1.1
--- /dev/null	Wed Aug 26 16:03:43 2020
+++ src/tests/net/if_wg/Makefile	Wed Aug 26 16:03:42 2020
@@ -0,0 +1,13 @@
+# $NetBSD: Makefile,v 1.1 2020/08/26 16:03:42 riastradh Exp $
+#
+
+.include <bsd.own.mk>
+
+TESTSDIR=	${TESTSBASE}/net/if_wg
+
+.for name in basic interoperability misc tunnel
+TESTS_SH+=		t_${name}
+TESTS_SH_SRC_t_${name}=	../net_common.sh ./common.sh t_${name}.sh
+.endfor
+
+.include <bsd.test.mk>
Index: src/tests/net/if_wg/common.sh
diff -u /dev/null src/tests/net/if_wg/common.sh:1.1
--- /dev/null	Wed Aug 26 16:03:43 2020
+++ src/tests/net/if_wg/common.sh	Wed Aug 26 16:03:42 2020
@@ -0,0 +1,200 @@
+#	$NetBSD: common.sh,v 1.1 2020/08/26 16:03:42 riastradh Exp $
+#
+# Copyright (c) 2018 Ryota Ozaki <[email protected]>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+escape_key()
+{
+
+	echo $1 | sed 's/\+/\\+/g' | sed 's|\/|\\/|g'
+}
+
+setup_servers()
+{
+
+	rump_server_crypto_start $SOCK_LOCAL netinet6 wg
+	rump_server_add_iface $SOCK_LOCAL shmif0 $BUS
+
+	rump_server_crypto_start $SOCK_PEER netinet6 wg
+	rump_server_add_iface $SOCK_PEER shmif0 $BUS
+}
+
+check_conf_port()
+{
+	local ifname=$1
+	local port=$2
+
+	atf_check -s exit:0 -o match:"listen-port: $port" \
+	    $HIJACKING wgconfig $ifname
+}
+
+check_conf_privkey()
+{
+	local ifname=$1
+	local key_priv="$2"
+
+	atf_check -s exit:0 -o match:"private-key: $(escape_key $key_priv)" \
+	    $HIJACKING wgconfig $ifname show private-key
+}
+
+setup_common()
+{
+	local ifconfig="atf_check -s exit:0 rump.ifconfig"
+	local ifname=$1
+	local proto=$2
+	local ip=$3
+	local prefix=$4
+
+	$ifconfig $ifname $proto $ip/$prefix
+}
+
+setup_wg_common()
+{
+	local ifconfig="atf_check -s exit:0 rump.ifconfig"
+	local wgconfig="atf_check -s exit:0 $HIJACKING wgconfig"
+	local ifname=$1
+	local proto=$2
+	local ip=$3
+	local prefix=$4
+	local port=$5
+	local key_priv="$6"
+	local tun=$7
+	local privfile=./tmp
+
+	$ifconfig $ifname create
+	if [ -n "$tun" ]; then
+		$ifconfig $ifname linkstr $tun
+	fi
+	$ifconfig $ifname $proto $ip/$prefix
+	$DEBUG && rump.netstat -nr
+	echo $key_priv > $privfile
+	$wgconfig $ifname set private-key $privfile
+	$wgconfig $ifname set listen-port $port
+	rm -f $privfile
+	$ifconfig $ifname up
+	$DEBUG && rump.ifconfig $ifname
+
+	check_conf_port $ifname $port
+	check_conf_privkey $ifname "$key_priv"
+}
+
+check_ping()
+{
+	local proto=$1
+	local ip=$2
+	local ping=
+
+	if [ $proto = inet ]; then
+		ping="atf_check -s exit:0 -o ignore rump.ping -n -i 0.1 -c 3 -w 1"
+	else
+		ping="atf_check -s exit:0 -o ignore rump.ping6 -n -i 0.1 -c 3 -X 1"
+	fi
+
+	$ping $ip
+}
+
+check_ping_fail()
+{
+	local proto=$1
+	local ip=$2
+	local ping=
+
+	if [ $proto = inet ]; then
+		ping="atf_check -s not-exit:0 -o ignore rump.ping -n -c 1 -w 1"
+	else
+		ping="atf_check -s not-exit:0 -o ignore rump.ping6 -n -c 1 -X 1"
+	fi
+
+	$ping $ip
+}
+
+destroy_wg_interfaces()
+{
+	local ifconfig="atf_check -s exit:0 rump.ifconfig"
+
+	export RUMP_SERVER=$SOCK_LOCAL
+	$ifconfig wg0 destroy
+	export RUMP_SERVER=$SOCK_PEER
+	$ifconfig wg0 destroy
+}
+
+add_peer()
+{
+	local wgconfig="atf_check -s exit:0 $HIJACKING wgconfig"
+	local ifname=$1
+	local peername=$2
+	local key=$3
+	local endpoint=$4
+	local allowedips=$5
+	local pskfile=$6
+	local key_psk="$7"
+	local pskopt=
+	local endpoint_opts=
+
+	if [ -n "$pskfile" ]; then
+		pskopt="--preshared-key=$pskfile"
+	fi
+
+	if [ -n "$endpoint" ]; then
+		endpoint_opts="--endpoint=$endpoint"
+	fi
+
+	$wgconfig $ifname add peer $peername $key $endpoint_opts \
+	    --allowed-ips=$allowedips $pskopt
+	atf_check -s exit:0 -o match:"allowed-ips: $allowedips" \
+	    $HIJACKING wgconfig $ifname show peer $peername
+	if [ -n "$key_psk" ]; then
+		atf_check -s exit:0 \
+		    -o match:"preshared-key: $(escape_key $key_psk)" \
+		    $HIJACKING wgconfig $ifname show peer $peername \
+		    --show-preshared-key
+	else
+		atf_check -s exit:0 -o match:"preshared-key: \(none\)" \
+		    $HIJACKING wgconfig $ifname show peer $peername \
+		    --show-preshared-key
+	fi
+}
+
+delete_peer()
+{
+	local wgconfig="atf_check -s exit:0 $HIJACKING wgconfig"
+	local ifname=$1
+	local peername=$2
+
+	$wgconfig $ifname delete peer $peername
+	atf_check -s exit:0 -o not-match:"peer: $peername" \
+	    $HIJACKING wgconfig $ifname
+}
+
+generate_keys()
+{
+
+	key_priv_local=$(wg-keygen)
+	key_pub_local=$(echo $key_priv_local| wg-keygen --pub)
+	key_priv_peer=$(wg-keygen)
+	key_pub_peer=$(echo $key_priv_peer| wg-keygen --pub)
+
+	export key_priv_local key_pub_local key_priv_peer key_pub_peer
+}
Index: src/tests/net/if_wg/t_basic.sh
diff -u /dev/null src/tests/net/if_wg/t_basic.sh:1.1
--- /dev/null	Wed Aug 26 16:03:43 2020
+++ src/tests/net/if_wg/t_basic.sh	Wed Aug 26 16:03:42 2020
@@ -0,0 +1,485 @@
+#	$NetBSD: t_basic.sh,v 1.1 2020/08/26 16:03:42 riastradh Exp $
+#
+# Copyright (c) 2018 Ryota Ozaki <[email protected]>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+BUS=bus
+SOCK_LOCAL=unix://wg_local
+SOCK_PEER=unix://wg_peer
+SOCK_PEER2=unix://wg_peer2
+
+
+check_ping_payload()
+{
+	local proto=$1
+	local ip=$2
+	local ping= size=
+
+	if [ $proto = inet ]; then
+		ping="atf_check -s exit:0 -o ignore rump.ping -n -c 1 -w 1"
+	else
+		ping="atf_check -s exit:0 -o ignore rump.ping6 -n -c 1 -X 1"
+	fi
+
+	for size in $(seq 1 100) $(seq 450 550) $(seq 1400 1500); do
+		$ping -s $size $ip
+	done
+}
+
+test_common()
+{
+	local type=$1
+	local outer_proto=$2
+	local inner_proto=$3
+	local ifconfig="atf_check -s exit:0 rump.ifconfig"
+	local port=51820
+	local ip_local= ip_peer=
+	local ip_wg_local= ip_wg_peer=
+	local outer_prefix= outer_prefixall=
+	local inner_prefix= inner_prefixall=
+
+	if [ $outer_proto = inet ]; then
+		ip_local=192.168.1.1
+		ip_peer=192.168.1.2
+		outer_prefix=24
+		outer_prefixall=32
+	else
+		ip_local=fc00::1
+		ip_peer=fc00::2
+		outer_prefix=64
+		outer_prefixall=128
+	fi
+
+	if [ $inner_proto = inet ]; then
+		ip_wg_local=10.0.0.1
+		ip_wg_peer=10.0.0.2
+		inner_prefix=24
+		inner_prefixall=32
+	else
+		ip_wg_local=fd00::1
+		ip_wg_peer=fd00::2
+		inner_prefix=64
+		inner_prefixall=128
+	fi
+
+	setup_servers
+
+	# It sets key_priv_local key_pub_local key_priv_peer key_pub_peer
+	generate_keys
+
+	export RUMP_SERVER=$SOCK_LOCAL
+	setup_common shmif0 $outer_proto $ip_local $outer_prefix
+	setup_wg_common wg0 $inner_proto $ip_wg_local $inner_prefix $port "$key_priv_local"
+
+	export RUMP_SERVER=$SOCK_PEER
+	setup_common shmif0 $outer_proto $ip_peer $outer_prefix
+	setup_wg_common wg0 $inner_proto $ip_wg_peer $inner_prefix $port "$key_priv_peer"
+
+	export RUMP_SERVER=$SOCK_LOCAL
+	add_peer wg0 peer0 $key_pub_peer $ip_peer:$port $ip_wg_peer/$inner_prefixall
+
+	export RUMP_SERVER=$SOCK_PEER
+	add_peer wg0 peer0 $key_pub_local $ip_local:$port $ip_wg_local/$inner_prefixall
+
+	if [ $type = basic ]; then
+		export RUMP_SERVER=$SOCK_LOCAL
+		check_ping $inner_proto $ip_wg_peer
+	elif [ $type = payload ]; then
+		export RUMP_SERVER=$SOCK_LOCAL
+		check_ping_payload $inner_proto $ip_wg_peer
+	fi
+
+	destroy_wg_interfaces
+}
+
+atf_test_case wg_create_destroy cleanup
+wg_create_destroy_head()
+{
+
+	atf_set "descr" "tests to create/destroy wg(4) interfaces"
+	atf_set "require.progs" "rump_server" "wgconfig" "wg-keygen"
+}
+
+wg_create_destroy_body()
+{
+
+	rump_server_crypto_start $SOCK_LOCAL netinet6 wg
+
+	test_create_destroy_common $SOCK_LOCAL wg0 true
+}
+
+wg_create_destroy_cleanup()
+{
+
+	$DEBUG && dump
+	cleanup
+}
+
+wg_create_destroy_peers_common()
+{
+	local proto=$1
+	local ifconfig="atf_check -s exit:0 rump.ifconfig"
+	local port=51820
+	local ip_local= ip_peer=
+	local ip_wg_local= ip_wg_peer=
+	local outer_prefix= outer_prefixall=
+	local inner_prefix= inner_prefixall=
+
+	if [ $proto = inet ]; then
+		ip_local=192.168.1.1
+		ip_peer=192.168.1.2
+		outer_prefix=24
+		outer_prefixall=32
+		ip_wg_local=10.0.0.1
+		ip_wg_peer=10.0.0.2
+		inner_prefix=24
+		inner_prefixall=32
+	else
+		ip_local=fc00::1
+		ip_peer=fc00::2
+		outer_prefix=64
+		outer_prefixall=128
+		ip_wg_local=fd00::1
+		ip_wg_peer=fd00::2
+		inner_prefix=64
+		inner_prefixall=128
+	fi
+
+	rump_server_crypto_start $SOCK_LOCAL netinet6 wg
+	rump_server_add_iface $SOCK_LOCAL shmif0 $BUS
+
+	# It sets key_priv_local key_pub_local key_priv_peer key_pub_peer
+	generate_keys
+
+	export RUMP_SERVER=$SOCK_LOCAL
+	setup_common shmif0 $proto $ip_local $outer_prefix
+	setup_wg_common wg0 $proto $ip_wg_local $inner_prefix $port "$key_priv_local"
+
+	add_peer wg0 peer0 $key_pub_peer $ip_peer:$port $ip_wg_peer/$inner_prefixall
+
+	delete_peer wg0 peer0
+}
+
+atf_test_case wg_create_destroy_peers_ipv4 cleanup
+wg_create_destroy_peers_ipv4_head()
+{
+
+	atf_set "descr" "tests to create/destroy peers (IPv4)"
+	atf_set "require.progs" "rump_server" "wgconfig" "wg-keygen"
+}
+
+wg_create_destroy_peers_ipv4_body()
+{
+
+	wg_create_destroy_peers_common inet
+}
+
+wg_create_destroy_peers_ipv4_cleanup()
+{
+
+	$DEBUG && dump
+	cleanup
+}
+
+atf_test_case wg_create_destroy_peers_ipv6 cleanup
+wg_create_destroy_peers_ipv6_head()
+{
+
+	atf_set "descr" "tests to create/destroy peers (IPv6)"
+	atf_set "require.progs" "rump_server" "wgconfig" "wg-keygen"
+}
+
+wg_create_destroy_peers_ipv6_body()
+{
+
+	wg_create_destroy_peers_common inet6
+}
+
+wg_create_destroy_peers_ipv6_cleanup()
+{
+
+	$DEBUG && dump
+	cleanup
+}
+
+add_basic_test()
+{
+	local inner=$1
+	local outer=$2
+	local ipv4=inet
+	local ipv6=inet6
+
+	name="wg_basic_${inner}_over_${outer}"
+	fulldesc="Test wg(4) with ${inner} over ${outer}"
+
+	eval inner=\$$inner
+	eval outer=\$$outer
+
+	atf_test_case ${name} cleanup
+	eval "
+		${name}_head() {
+			atf_set descr \"${fulldesc}\"
+			atf_set require.progs rump_server wgconfig wg-keygen
+		}
+		${name}_body() {
+			test_common basic $outer $inner
+			rump_server_destroy_ifaces
+		}
+		${name}_cleanup() {
+			\$DEBUG && dump
+			cleanup
+		}"
+	atf_add_test_case ${name}
+}
+
+add_payload_sizes_test()
+{
+	local inner=$1
+	local outer=$2
+	local ipv4=inet
+	local ipv6=inet6
+
+	name="wg_payload_sizes_${inner}_over_${outer}"
+	fulldesc="Test wg(4) with ${inner} over ${outer} with various payload sizes"
+
+	eval inner=\$$inner
+	eval outer=\$$outer
+
+	atf_test_case ${name} cleanup
+	eval "
+		${name}_head() {
+			atf_set descr \"${fulldesc}\"
+			atf_set require.progs rump_server wgconfig wg-keygen
+		}
+		${name}_body() {
+			test_common payload $outer $inner
+			rump_server_destroy_ifaces
+		}
+		${name}_cleanup() {
+			\$DEBUG && dump
+			cleanup
+		}"
+	atf_add_test_case ${name}
+}
+
+atf_test_case wg_multiple_interfaces cleanup
+wg_multiple_interfaces_head()
+{
+
+	atf_set "descr" "tests multiple wg(4) interfaces"
+	atf_set "require.progs" "rump_server" "wgconfig" "wg-keygen"
+}
+
+wg_multiple_interfaces_body()
+{
+	local ifconfig="atf_check -s exit:0 rump.ifconfig"
+	local ping="atf_check -s exit:0 -o ignore rump.ping -n -i 0.1 -c 3 -w 1"
+	local ping_fail="atf_check -s not-exit:0 -o ignore rump.ping -n -c 1 -w 1"
+	local key_priv_peer2=
+	local key_pub_peer2=
+	local ip_local=192.168.1.1
+	local ip_local2=192.168.2.1
+	local ip_peer=192.168.1.2
+	local ip_peer2=192.168.2.2
+	local ip_wg_local=10.0.0.1
+	local ip_wg_local2=10.0.1.1
+	local ip_wg_peer=10.0.0.2
+	local ip_wg_peer2=10.0.1.2
+	local port=51820
+	local port2=51821
+	local outfile=./out
+
+	setup_servers
+	rump_server_add_iface $SOCK_LOCAL shmif1 $BUS
+
+	rump_server_crypto_start $SOCK_PEER2 netinet6 wg
+	rump_server_add_iface $SOCK_PEER2 shmif0 $BUS
+
+	# It sets key_priv_local key_pub_local key_priv_peer key_pub_peer
+	generate_keys
+	key_priv_peer2=$(wg-keygen)
+	key_pub_peer2=$(echo $key_priv_peer2| wg-keygen --pub)
+
+	export RUMP_SERVER=$SOCK_LOCAL
+	setup_common shmif0 inet $ip_local 24
+	setup_common shmif1 inet $ip_local2 24
+	setup_wg_common wg0 inet $ip_wg_local 24 $port "$key_priv_local"
+	setup_wg_common wg1 inet $ip_wg_local2 24 $port2 "$key_priv_local"
+
+	export RUMP_SERVER=$SOCK_PEER
+	setup_common shmif0 inet $ip_peer 24
+	setup_wg_common wg0 inet $ip_wg_peer 24 $port "$key_priv_peer"
+
+	export RUMP_SERVER=$SOCK_PEER2
+	setup_common shmif0 inet $ip_peer2 24
+	setup_wg_common wg0 inet $ip_wg_peer2 24 $port2 "$key_priv_peer2"
+
+	export RUMP_SERVER=$SOCK_LOCAL
+	add_peer wg0 peer0 $key_pub_peer $ip_peer:$port $ip_wg_peer/32
+	add_peer wg1 peer0 $key_pub_peer2 $ip_peer2:$port2 $ip_wg_peer2/32
+
+	export RUMP_SERVER=$SOCK_PEER
+	add_peer wg0 peer0 $key_pub_local $ip_local:$port $ip_wg_local/32
+
+	export RUMP_SERVER=$SOCK_PEER2
+	add_peer wg0 peer0 $key_pub_local $ip_local2:$port2 $ip_wg_local2/32
+
+	export RUMP_SERVER=$SOCK_LOCAL
+
+	extract_new_packets $BUS > $outfile
+	$DEBUG && cat $outfile
+
+	$ping $ip_wg_peer
+
+	extract_new_packets $BUS > $outfile
+	$DEBUG && cat $outfile
+
+	$ping $ip_wg_peer2
+
+	extract_new_packets $BUS > $outfile
+	$DEBUG && cat $outfile
+
+	export RUMP_SERVER=$SOCK_LOCAL
+	$ifconfig wg0 destroy
+	$ifconfig wg1 destroy
+	export RUMP_SERVER=$SOCK_PEER
+	$ifconfig wg0 destroy
+	export RUMP_SERVER=$SOCK_PEER2
+	$ifconfig wg0 destroy
+}
+
+wg_multiple_interfaces_cleanup()
+{
+
+	$DEBUG && dump
+	cleanup
+}
+
+atf_test_case wg_multiple_peers cleanup
+wg_multiple_peers_head()
+{
+
+	atf_set "descr" "tests multiple wg(4) peers"
+	atf_set "require.progs" "rump_server" "wgconfig" "wg-keygen"
+}
+
+wg_multiple_peers_body()
+{
+	local ifconfig="atf_check -s exit:0 rump.ifconfig"
+	local ping="atf_check -s exit:0 -o ignore rump.ping -n -i 0.1 -c 3 -w 1"
+	local ping_fail="atf_check -s not-exit:0 -o ignore rump.ping -n -c 1 -w 1"
+	local key_priv_peer2=
+	local key_pub_peer2=
+	local ip_local=192.168.1.1
+	local ip_peer=192.168.1.2
+	local ip_peer2=192.168.1.3
+	local ip_wg_local=10.0.0.1
+	local ip_wg_peer=10.0.0.2
+	local ip_wg_peer2=10.0.0.3
+	local port=51820
+	local outfile=./out
+
+	setup_servers
+	rump_server_add_iface $SOCK_LOCAL shmif1 $BUS
+
+	rump_server_crypto_start $SOCK_PEER2 netinet6 wg
+	rump_server_add_iface $SOCK_PEER2 shmif0 $BUS
+
+	# It sets key_priv_local key_pub_local key_priv_peer key_pub_peer
+	generate_keys
+	key_priv_peer2=$(wg-keygen)
+	key_pub_peer2=$(echo $key_priv_peer2| wg-keygen --pub)
+
+	export RUMP_SERVER=$SOCK_LOCAL
+	setup_common shmif0 inet $ip_local 24
+	setup_wg_common wg0 inet $ip_wg_local 24 $port "$key_priv_local"
+
+	export RUMP_SERVER=$SOCK_PEER
+	setup_common shmif0 inet $ip_peer 24
+	setup_wg_common wg0 inet $ip_wg_peer 24 $port "$key_priv_peer"
+
+	export RUMP_SERVER=$SOCK_PEER2
+	setup_common shmif0 inet $ip_peer2 24
+	setup_wg_common wg0 inet $ip_wg_peer2 24 $port "$key_priv_peer2"
+
+	export RUMP_SERVER=$SOCK_LOCAL
+	add_peer wg0 peer0 $key_pub_peer $ip_peer:$port $ip_wg_peer/32
+	add_peer wg0 peer1 $key_pub_peer2 $ip_peer2:$port $ip_wg_peer2/32
+
+	export RUMP_SERVER=$SOCK_PEER
+	add_peer wg0 peer0 $key_pub_local $ip_local:$port $ip_wg_local/32
+
+	export RUMP_SERVER=$SOCK_PEER2
+	add_peer wg0 peer0 $key_pub_local $ip_local:$port $ip_wg_local/32
+
+	export RUMP_SERVER=$SOCK_LOCAL
+
+	extract_new_packets $BUS > $outfile
+	$DEBUG && cat $outfile
+
+	$ping $ip_wg_peer
+
+	extract_new_packets $BUS > $outfile
+	$DEBUG && cat $outfile
+
+	$ping $ip_wg_peer2
+
+	extract_new_packets $BUS > $outfile
+	$DEBUG && cat $outfile
+
+	export RUMP_SERVER=$SOCK_LOCAL
+	$ifconfig wg0 destroy
+	export RUMP_SERVER=$SOCK_PEER
+	$ifconfig wg0 destroy
+	export RUMP_SERVER=$SOCK_PEER2
+	$ifconfig wg0 destroy
+}
+
+wg_multiple_peers_cleanup()
+{
+
+	$DEBUG && dump
+	cleanup
+}
+
+atf_init_test_cases()
+{
+
+	add_basic_test ipv4 ipv4
+	add_basic_test ipv4 ipv6
+	add_basic_test ipv6 ipv4
+	add_basic_test ipv6 ipv6
+
+	add_payload_sizes_test ipv4 ipv4
+	add_payload_sizes_test ipv4 ipv6
+	add_payload_sizes_test ipv6 ipv4
+	add_payload_sizes_test ipv6 ipv6
+
+	atf_add_test_case wg_create_destroy
+	atf_add_test_case wg_create_destroy_peers_ipv4
+	atf_add_test_case wg_create_destroy_peers_ipv6
+	atf_add_test_case wg_multiple_interfaces
+	atf_add_test_case wg_multiple_peers
+}
Index: src/tests/net/if_wg/t_interoperability.sh
diff -u /dev/null src/tests/net/if_wg/t_interoperability.sh:1.1
--- /dev/null	Wed Aug 26 16:03:43 2020
+++ src/tests/net/if_wg/t_interoperability.sh	Wed Aug 26 16:03:42 2020
@@ -0,0 +1,279 @@
+#	$NetBSD: t_interoperability.sh,v 1.1 2020/08/26 16:03:42 riastradh Exp $
+#
+# Copyright (c) 2018 Ryota Ozaki <[email protected]>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+BUS=bus
+SOCK_LOCAL=unix://wg_local
+SOCK_PEER=unix://wg_peer
+
+
+atf_test_case wg_interoperability_basic cleanup
+wg_interoperability_basic_head()
+{
+
+	atf_set "descr" "tests of interoperability with the WireGuard protocol"
+	atf_set "require.progs" "rump_server" "wgconfig" "wg-keygen"
+}
+
+#
+# Set ATF_NET_IF_WG_INTEROPERABILITY=yes to run the test.
+# Also to run the test, the following setups are required on the host and a peer.
+#
+# [Host]
+#   ifconfig bridge0 create
+#   ifconfig tap0 create
+#   brconfig bridge0 add tap0
+#   brconfig bridge0 add <external-interface>
+#   ifconfig tap0 up
+#   ifconfig bridge0 up
+#
+# [Peer]
+#   ip addr add 10.0.0.2/24 dev <external-interface>
+#   ip link add wg0 type wireguard
+#   ip addr add 10.0.1.2/24 dev wg0
+#   privkey="EF9D8AOkmxjlkiRFqBnfJS+RJJHbUy02u+VkGlBr9Eo="
+#   ip link set wg0 up
+#   echo $privkey > /tmp/private-key
+#   wg set wg0 listen-port 52428
+#   wg set wg0 private-key /tmp/private-key
+#   pubkey="2iWFzywbDvYu2gQW5Q7/z/g5/Cv4bDDd6L3OKXLOwxs="
+#   wg set wg0 peer $pubkey endpoint 10.0.0.3:52428 allowed-ips 10.0.1.1/32
+#
+wg_interoperability_basic_body()
+{
+	local ifconfig="atf_check -s exit:0 rump.ifconfig"
+	local ping="atf_check -s exit:0 -o ignore rump.ping -n -c 3 -w 3"
+	local ping_fail="atf_check -s not-exit:0 -o ignore rump.ping -n -c 1 -w 3"
+	local key_priv_local=
+	local key_pub_local=
+	local key_priv_peer=
+	local key_pub_peer=
+	local ip_local=10.0.0.3
+	local ip_peer=10.0.0.2
+	local ip_wg_local=10.0.1.1
+	local ip_wg_peer=10.0.1.2
+	local port=52428
+	local outfile=./out
+
+	if [ "$ATF_NET_IF_WG_INTEROPERABILITY" != yes ]; then
+		atf_skip "set ATF_NET_IF_WG_INTEROPERABILITY=yes to run the test"
+	fi
+
+	export RUMP_SERVER=$SOCK_LOCAL
+	rump_server_crypto_start $SOCK_LOCAL virtif wg netinet6
+	atf_check -s exit:0 rump.sysctl -q -w net.inet.ip.dad_count=0
+	atf_check -s exit:0 rump.ifconfig virt0 create
+	atf_check -s exit:0 rump.ifconfig virt0 $ip_local/24
+	atf_check -s exit:0 rump.ifconfig virt0 up
+
+	$ping $ip_peer
+
+	key_priv_local="aK3TbzUNDO4aeDRX54x8bOG+NaKuqXKt7Hwq0Uz69Wo="
+	key_pub_local="2iWFzywbDvYu2gQW5Q7/z/g5/Cv4bDDd6L3OKXLOwxs="
+	key_priv_peer="EF9D8AOkmxjlkiRFqBnfJS+RJJHbUy02u+VkGlBr9Eo="
+	key_pub_peer="2ZM9RvDmMZS/Nuh8OaVaJrwFbO57/WJgeU+JoQ//nko="
+
+	setup_wg_common wg0 inet $ip_wg_local 24 $port "$key_priv_local"
+	add_peer wg0 peer0 $key_pub_peer $ip_peer:$port $ip_wg_peer/32
+
+	$ping $ip_wg_peer
+
+	export RUMP_SERVER=$SOCK_LOCAL
+	$ifconfig wg0 destroy
+}
+
+wg_interoperability_basic_cleanup()
+{
+
+	$DEBUG && dump
+	cleanup
+}
+
+atf_test_case wg_interoperability_cookie cleanup
+wg_interoperability_cookie_head()
+{
+
+	atf_set "descr" "tests of interoperability with the WireGuard protocol"
+	atf_set "require.progs" "rump_server" "wgconfig" "wg-keygen"
+}
+
+wg_interoperability_cookie_body()
+{
+	local ifconfig="atf_check -s exit:0 rump.ifconfig"
+	local ping="atf_check -s exit:0 -o ignore rump.ping -n -c 3 -w 3"
+	local ping_fail="atf_check -s not-exit:0 -o ignore rump.ping -n -c 1 -w 3"
+	local key_priv_local=
+	local key_pub_local=
+	local key_priv_peer=
+	local key_pub_peer=
+	local ip_local=10.0.0.3
+	local ip_peer=10.0.0.2
+	local ip_wg_local=10.0.1.1
+	local ip_wg_peer=10.0.1.2
+	local port=52428
+	local outfile=./out
+	local rekey_timeout=5 # default
+
+	if [ "$ATF_NET_IF_WG_INTEROPERABILITY" != yes ]; then
+		atf_skip "set ATF_NET_IF_WG_INTEROPERABILITY=yes to run the test"
+	fi
+
+	export RUMP_SERVER=$SOCK_LOCAL
+	rump_server_crypto_start $SOCK_LOCAL virtif wg netinet6
+	atf_check -s exit:0 rump.sysctl -q -w net.inet.ip.dad_count=0
+	atf_check -s exit:0 rump.ifconfig virt0 create
+	atf_check -s exit:0 rump.ifconfig virt0 $ip_local/24
+	atf_check -s exit:0 rump.ifconfig virt0 up
+
+	$ping $ip_peer
+
+	key_priv_local="aK3TbzUNDO4aeDRX54x8bOG+NaKuqXKt7Hwq0Uz69Wo="
+	key_pub_local="2iWFzywbDvYu2gQW5Q7/z/g5/Cv4bDDd6L3OKXLOwxs="
+	key_priv_peer="EF9D8AOkmxjlkiRFqBnfJS+RJJHbUy02u+VkGlBr9Eo="
+	key_pub_peer="2ZM9RvDmMZS/Nuh8OaVaJrwFbO57/WJgeU+JoQ//nko="
+
+	setup_wg_common wg0 inet $ip_wg_local 24 $port "$key_priv_local"
+
+	# Emulate load to send back a cookie on receiving a response message
+	atf_check -s exit:0 -o ignore \
+	    rump.sysctl -w net.wg.force_underload=1
+
+	add_peer wg0 peer0 $key_pub_peer $ip_peer:$port $ip_wg_peer/32
+
+	# ping fails because we don't accept a response message and send a cookie
+	$ping_fail $ip_wg_peer
+
+	# Wait for retrying an initialization that works because the peer
+	# send a response message with the cookie we sent
+	atf_check -s exit:0 sleep $rekey_timeout
+
+	# So ping works
+	$ping $ip_wg_peer
+
+	export RUMP_SERVER=$SOCK_LOCAL
+	$ifconfig wg0 destroy
+}
+
+wg_interoperability_cookie_cleanup()
+{
+
+	$DEBUG && dump
+	cleanup
+}
+
+atf_test_case wg_userspace_basic cleanup
+wg_userspace_basic_head()
+{
+
+	atf_set "descr" "tests of userspace implementation of wg(4)"
+	atf_set "require.progs" "rump_server" "wgconfig" "wg-keygen"
+}
+
+#
+# Set ATF_NET_IF_WG_USERSPACE=yes to run the test.
+# Also to run the test, the following setups are required on the host and a peer.
+#
+# [Host]
+#   ifconfig bridge0 create
+#   ifconfig tap0 create
+#   brconfig bridge0 add tap0
+#   brconfig bridge0 add <external-interface>
+#   ifconfig tap0 up
+#   ifconfig bridge0 up
+#
+# [Peer]
+#   ip addr add 10.0.0.2/24 dev <external-interface>
+#   ip link add wg0 type wireguard
+#   ip addr add 10.0.4.2/24 dev wg0
+#   privkey="EF9D8AOkmxjlkiRFqBnfJS+RJJHbUy02u+VkGlBr9Eo="
+#   ip link set wg0 up
+#   echo $privkey > /tmp/private-key
+#   wg set wg0 listen-port 52428
+#   wg set wg0 private-key /tmp/private-key
+#   pubkey="6mQ4lUO3oq5O8FfGW52CFXNbmh5iFT1XMqPzpdrc0nE="
+#   wg set wg0 peer $pubkey endpoint 10.0.0.3:52428 allowed-ips 10.0.4.1/32
+#
+wg_userspace_basic_body()
+{
+	local ifconfig="atf_check -s exit:0 rump.ifconfig"
+	local ping="atf_check -s exit:0 -o ignore ping -n -c 3 -w 3"
+	local ping_fail="atf_check -s not-exit:0 -o ignore ping -n -c 1 -w 3"
+	local key_priv_local=
+	local key_pub_local=
+	local key_priv_peer=
+	local key_pub_peer=
+	local ip_local=10.0.0.3
+	local ip_peer=10.0.0.2
+	local ip_wg_local=10.0.4.1
+	local ip_wg_peer=10.0.4.2
+	local port_local=52429
+	local port_peer=52428
+	local outfile=./out
+
+	if [ "$ATF_NET_IF_WG_USERSPACE" != yes ]; then
+		atf_skip "set ATF_NET_IF_WG_USERSPACE=yes to run the test"
+	fi
+
+	export RUMP_SERVER=$SOCK_LOCAL
+	rump_server_crypto_start $SOCK_LOCAL virtif wg netinet6
+	atf_check -s exit:0 rump.sysctl -q -w net.inet.ip.dad_count=0
+
+	$DEBUG && netstat -nr -f inet
+
+	$ping $ip_peer
+
+	key_priv_local="6B0dualfIAiEG7/jFGOIHrJMhuypq87xCER/0ieIpE4="
+	key_pub_local="6mQ4lUO3oq5O8FfGW52CFXNbmh5iFT1XMqPzpdrc0nE="
+	key_priv_peer="EF9D8AOkmxjlkiRFqBnfJS+RJJHbUy02u+VkGlBr9Eo="
+	key_pub_peer="2ZM9RvDmMZS/Nuh8OaVaJrwFbO57/WJgeU+JoQ//nko="
+
+	setup_wg_common wg0 inet $ip_wg_local 24 $port_local "$key_priv_local" tun0
+	add_peer wg0 peer0 $key_pub_peer $ip_peer:$port_peer $ip_wg_peer/32
+
+	$DEBUG && rump.ifconfig wg0
+	$DEBUG && ifconfig tun0
+	$DEBUG && netstat -nr -f inet
+
+	$ping $ip_wg_peer
+
+	export RUMP_SERVER=$SOCK_LOCAL
+	$ifconfig wg0 destroy
+}
+
+wg_userspace_basic_cleanup()
+{
+
+	$DEBUG && dump
+	cleanup
+}
+
+atf_init_test_cases()
+{
+
+	atf_add_test_case wg_interoperability_basic
+	atf_add_test_case wg_interoperability_cookie
+	atf_add_test_case wg_userspace_basic
+}
Index: src/tests/net/if_wg/t_misc.sh
diff -u /dev/null src/tests/net/if_wg/t_misc.sh:1.1
--- /dev/null	Wed Aug 26 16:03:43 2020
+++ src/tests/net/if_wg/t_misc.sh	Wed Aug 26 16:03:42 2020
@@ -0,0 +1,600 @@
+#	$NetBSD: t_misc.sh,v 1.1 2020/08/26 16:03:42 riastradh Exp $
+#
+# Copyright (c) 2018 Ryota Ozaki <[email protected]>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+BUS=bus
+SOCK_LOCAL=unix://wg_local
+SOCK_PEER=unix://wg_peer
+
+
+atf_test_case wg_rekey cleanup
+wg_rekey_head()
+{
+
+	atf_set "descr" "tests of rekeying of wg(4)"
+	atf_set "require.progs" "rump_server" "wgconfig" "wg-keygen"
+}
+
+wg_rekey_body()
+{
+	local ifconfig="atf_check -s exit:0 rump.ifconfig"
+	local ping="atf_check -s exit:0 -o ignore rump.ping -n -c 1 -w 1"
+	local ip_local=192.168.1.1
+	local ip_peer=192.168.1.2
+	local ip_wg_local=10.0.0.1
+	local ip_wg_peer=10.0.0.2
+	local port=51820
+	local rekey_after_time=3
+	local latest_handshake=
+
+	setup_servers
+
+	export RUMP_SERVER=$SOCK_LOCAL
+	atf_check -s exit:0 -o ignore \
+	    rump.sysctl -w net.wg.rekey_after_time=$rekey_after_time
+	export RUMP_SERVER=$SOCK_PEER
+	atf_check -s exit:0 -o ignore \
+	    rump.sysctl -w net.wg.rekey_after_time=$rekey_after_time
+
+	# It sets key_priv_local key_pub_local key_priv_peer key_pub_peer
+	generate_keys
+
+	export RUMP_SERVER=$SOCK_LOCAL
+	setup_common shmif0 inet $ip_local 24
+	setup_wg_common wg0 inet $ip_wg_local 24 $port "$key_priv_local"
+
+	export RUMP_SERVER=$SOCK_PEER
+	setup_common shmif0 inet $ip_peer 24
+	setup_wg_common wg0 inet $ip_wg_peer 24 $port "$key_priv_peer"
+
+	export RUMP_SERVER=$SOCK_LOCAL
+	add_peer wg0 peer0 $key_pub_peer $ip_peer:$port $ip_wg_peer/32
+
+	export RUMP_SERVER=$SOCK_PEER
+	add_peer wg0 peer0 $key_pub_local $ip_local:$port $ip_wg_local/32
+
+	export RUMP_SERVER=$SOCK_LOCAL
+
+	$ping $ip_wg_peer
+
+	latest_handshake=$($HIJACKING wgconfig wg0 show peer peer0 \
+	    | awk -F : '/latest-handshake/ {print $2;}')
+	$DEBUG && echo $latest_handshake
+
+	sleep 1
+
+	$ping $ip_wg_peer
+
+	# No reinitiation is performed
+	atf_check -s exit:0 -o match:"$latest_handshake" \
+	    $HIJACKING wgconfig wg0 show peer peer0
+
+	# Wait for a reinitiation to be performed
+	sleep $rekey_after_time
+
+	$ping $ip_wg_peer
+
+	# A reinitiation should be performed
+	atf_check -s exit:0 -o not-match:"$latest_handshake" \
+	    $HIJACKING wgconfig wg0 show peer peer0
+
+	latest_handshake=$($HIJACKING wgconfig wg0 show peer peer0 \
+	    | awk -F : '/latest-handshake/ {print $2;}')
+	$DEBUG && echo $latest_handshake
+
+	# Wait for a reinitiation to be performed again
+	sleep $rekey_after_time
+
+	$ping $ip_wg_peer
+
+	# A reinitiation should be performed
+	atf_check -s exit:0 -o not-match:"$latest_handshake" \
+	    $HIJACKING wgconfig wg0 show peer peer0
+
+	destroy_wg_interfaces
+}
+
+wg_rekey_cleanup()
+{
+
+	$DEBUG && dump
+	cleanup
+}
+
+atf_test_case wg_handshake_timeout cleanup
+wg_handshake_timeout_head()
+{
+
+	atf_set "descr" "tests of handshake timeout of wg(4)"
+	atf_set "require.progs" "rump_server" "wgconfig" "wg-keygen"
+}
+
+wg_handshake_timeout_body()
+{
+	local ifconfig="atf_check -s exit:0 rump.ifconfig"
+	local ping="atf_check -s exit:0 -o ignore rump.ping -n -c 1 -w 1"
+	local ip_local=192.168.1.1
+	local ip_peer=192.168.1.2
+	local ip_wg_local=10.0.0.1
+	local ip_wg_peer=10.0.0.2
+	local port=51820
+	local rekey_after_time=3
+	local latest_handshake=
+	local outfile=./out
+	local rekey_timeout=3
+	local rekey_attempt_time=8
+	local n=
+
+	setup_servers
+
+	export RUMP_SERVER=$SOCK_LOCAL
+	atf_check -s exit:0 -o ignore \
+	    rump.sysctl -w net.wg.rekey_timeout=$rekey_timeout
+	atf_check -s exit:0 -o ignore \
+	    rump.sysctl -w net.wg.rekey_attempt_time=$rekey_attempt_time
+	export RUMP_SERVER=$SOCK_PEER
+	atf_check -s exit:0 -o ignore \
+	    rump.sysctl -w net.wg.rekey_timeout=$rekey_timeout
+	atf_check -s exit:0 -o ignore \
+	    rump.sysctl -w net.wg.rekey_attempt_time=$rekey_attempt_time
+
+	# It sets key_priv_local key_pub_local key_priv_peer key_pub_peer
+	generate_keys
+
+	export RUMP_SERVER=$SOCK_LOCAL
+	setup_common shmif0 inet $ip_local 24
+	setup_wg_common wg0 inet $ip_wg_local 24 $port "$key_priv_local"
+
+	export RUMP_SERVER=$SOCK_PEER
+	setup_common shmif0 inet $ip_peer 24
+	setup_wg_common wg0 inet $ip_wg_peer 24 $port "$key_priv_peer"
+
+	export RUMP_SERVER=$SOCK_LOCAL
+	add_peer wg0 peer0 $key_pub_peer $ip_peer:$port $ip_wg_peer/32
+
+	export RUMP_SERVER=$SOCK_PEER
+	add_peer wg0 peer0 $key_pub_local $ip_local:$port $ip_wg_local/32
+
+	# Resolve arp
+	export RUMP_SERVER=$SOCK_LOCAL
+	$ping $ip_peer
+
+	export RUMP_SERVER=$SOCK_PEER
+	$ifconfig shmif0 down
+	export RUMP_SERVER=$SOCK_LOCAL
+
+	extract_new_packets $BUS > $outfile
+
+	# Should fail
+	atf_check -s not-exit:0 -o match:'100.0% packet loss' \
+	    rump.ping -n -c 1 -w 1 $ip_wg_peer
+
+	sleep $((rekey_attempt_time + rekey_timeout))
+
+	extract_new_packets $BUS > $outfile
+	$DEBUG && cat $outfile
+
+	n=$(grep "$ip_local.$port > $ip_peer.$port" $outfile |wc -l)
+
+	# Give up handshaking after three attempts
+	atf_check_equal $n 3
+
+	export RUMP_SERVER=$SOCK_PEER
+	$ifconfig shmif0 up
+	export RUMP_SERVER=$SOCK_LOCAL
+
+	destroy_wg_interfaces
+}
+
+wg_handshake_timeout_cleanup()
+{
+
+	$DEBUG && dump
+	cleanup
+}
+
+atf_test_case wg_cookie cleanup
+wg_cookie_head()
+{
+
+	atf_set "descr" "tests of cookie messages of the wg(4) protocol"
+	atf_set "require.progs" "rump_server" "wgconfig" "wg-keygen"
+}
+
+wg_cookie_body()
+{
+	local ifconfig="atf_check -s exit:0 rump.ifconfig"
+	local ping="atf_check -s exit:0 -o ignore rump.ping -n -i 0.1 -c 3 -w 1"
+	local ping_fail="atf_check -s not-exit:0 -o ignore rump.ping -n -c 1 -w 1"
+	local ip_local=192.168.1.1
+	local ip_peer=192.168.1.2
+	local ip_wg_local=10.0.0.1
+	local ip_wg_peer=10.0.0.2
+	local port=51820
+	local outfile=./out
+	local rekey_timeout=5
+
+	setup_servers
+
+	# It sets key_priv_local key_pub_local key_priv_peer key_pub_peer
+	generate_keys
+
+	export RUMP_SERVER=$SOCK_LOCAL
+	setup_common shmif0 inet $ip_local 24
+	setup_wg_common wg0 inet $ip_wg_local 24 $port "$key_priv_local"
+
+	export RUMP_SERVER=$SOCK_PEER
+	setup_common shmif0 inet $ip_peer 24
+	setup_wg_common wg0 inet $ip_wg_peer 24 $port "$key_priv_peer"
+
+	export RUMP_SERVER=$SOCK_LOCAL
+	add_peer wg0 peer0 $key_pub_peer $ip_peer:$port $ip_wg_peer/32
+
+	export RUMP_SERVER=$SOCK_PEER
+	add_peer wg0 peer0 $key_pub_local $ip_local:$port $ip_wg_local/32
+
+	export RUMP_SERVER=$SOCK_PEER
+	# Emulate load on the peer
+	atf_check -s exit:0 -o ignore \
+	    rump.sysctl -w net.wg.force_underload=1
+
+	export RUMP_SERVER=$SOCK_LOCAL
+
+	extract_new_packets $BUS > $outfile
+	$DEBUG && cat $outfile
+
+	# The peer doesn't return a response message but a cookie message
+	# and a session doesn't start
+	$ping_fail $ip_wg_peer
+
+	extract_new_packets $BUS > $outfile
+	$DEBUG && cat $outfile
+	# XXX length 64 indicates the message is a cookie message
+	atf_check -s exit:0 \
+	    -o match:"$ip_peer.$port > $ip_local.$port: UDP, length 64" \
+	    cat $outfile
+
+	$DEBUG && $HIJACKING wgconfig wg0 show
+	atf_check -s exit:0 -o match:"latest-handshake: 0" \
+	    $HIJACKING wgconfig wg0
+
+	# Wait for restarting a session
+	sleep $rekey_timeout
+
+	# The second attempt should be success because the init message has
+	# a valid cookie.
+	$ping $ip_wg_peer
+
+	$DEBUG && $HIJACKING wgconfig wg0 show
+	atf_check -s exit:0 -o not-match:"latest-handshake: 0" \
+	    $HIJACKING wgconfig wg0
+
+	destroy_wg_interfaces
+}
+
+wg_cookie_cleanup()
+{
+
+	$DEBUG && dump
+	cleanup
+}
+
+atf_test_case wg_mobility cleanup
+wg_mobility_head()
+{
+
+	atf_set "descr" "tests of the mobility of wg(4)"
+	atf_set "require.progs" "rump_server" "wgconfig" "wg-keygen"
+}
+
+wg_mobility_body()
+{
+	local ifconfig="atf_check -s exit:0 rump.ifconfig"
+	local ping="atf_check -s exit:0 -o ignore rump.ping -n -i 0.1 -c 3 -w 1"
+	local ping_fail="atf_check -s not-exit:0 -o ignore rump.ping -n -c 1 -w 1"
+	local ip_local=192.168.1.1
+	local ip_peer=192.168.1.2
+	local ip_peer_new=192.168.1.3
+	local ip_wg_local=10.0.0.1
+	local ip_wg_peer=10.0.0.2
+	local port=51820
+	local outfile=./out
+
+	setup_servers
+
+	# It sets key_priv_local key_pub_local key_priv_peer key_pub_peer
+	generate_keys
+
+	export RUMP_SERVER=$SOCK_LOCAL
+	setup_common shmif0 inet $ip_local 24
+	setup_wg_common wg0 inet $ip_wg_local 24 $port "$key_priv_local"
+
+	export RUMP_SERVER=$SOCK_PEER
+	setup_common shmif0 inet $ip_peer 24
+	setup_wg_common wg0 inet $ip_wg_peer 24 $port "$key_priv_peer"
+
+	export RUMP_SERVER=$SOCK_LOCAL
+	# Initially, the local doesn't know the endpoint of the peer
+	add_peer wg0 peer0 $key_pub_peer "" $ip_wg_peer/32
+
+	export RUMP_SERVER=$SOCK_PEER
+	add_peer wg0 peer0 $key_pub_local $ip_local:$port $ip_wg_local/32
+
+	extract_new_packets $BUS > $outfile
+	$DEBUG && cat $outfile
+
+	# Ping from the local to the peer doesn't work because the local
+	# doesn't know the endpoint of the peer
+	export RUMP_SERVER=$SOCK_LOCAL
+	$ping_fail $ip_wg_peer
+
+	extract_new_packets $BUS > $outfile
+	$DEBUG && cat $outfile
+
+	export RUMP_SERVER=$SOCK_PEER
+	$ping $ip_wg_local
+
+	extract_new_packets $BUS > $outfile
+	$DEBUG && cat $outfile
+
+	atf_check -s exit:0 -o match:"$ip_local.$port > $ip_peer.$port" cat $outfile
+
+	# Change the IP address of the peer
+	setup_common shmif0 inet $ip_peer_new 24
+	atf_check -s exit:0 rump.ifconfig -w 10
+
+	# Ping from the local to the peer doesn't work because the local
+	# doesn't know the change of the IP address of the peer
+	export RUMP_SERVER=$SOCK_LOCAL
+	$ping_fail $ip_wg_peer
+
+	extract_new_packets $BUS > $outfile
+	$DEBUG && cat $outfile
+
+	atf_check -s exit:0 -o match:"$ip_local.$port > $ip_peer.$port" cat $outfile
+
+	# Ping from the peer to the local works because the local notices
+	# the change and updates the IP address of the peer
+	export RUMP_SERVER=$SOCK_PEER
+	$ping $ip_wg_local
+
+	extract_new_packets $BUS > $outfile
+	$DEBUG && cat $outfile
+
+	atf_check -s exit:0 -o match:"$ip_local.$port > $ip_peer_new.$port" cat $outfile
+	atf_check -s exit:0 -o match:"$ip_peer_new.$port > $ip_local.$port" cat $outfile
+	atf_check -s exit:0 -o not-match:"$ip_local.$port > $ip_peer.$port" cat $outfile
+
+	destroy_wg_interfaces
+}
+
+wg_mobility_cleanup()
+{
+
+	$DEBUG && dump
+	cleanup
+}
+
+atf_test_case wg_keepalive cleanup
+wg_keepalive_head()
+{
+
+	atf_set "descr" "tests keepalive messages"
+	atf_set "require.progs" "rump_server" "wgconfig" "wg-keygen"
+}
+
+wg_keepalive_body()
+{
+	local ifconfig="atf_check -s exit:0 rump.ifconfig"
+	local ping="atf_check -s exit:0 -o ignore rump.ping -n -i 0.1 -c 3 -w 1"
+	local ping_fail="atf_check -s not-exit:0 -o ignore rump.ping -n -c 1 -w 1"
+	local ip_local=192.168.1.1
+	local ip_peer=192.168.1.2
+	local ip_peer_new=192.168.1.3
+	local ip_wg_local=10.0.0.1
+	local ip_wg_peer=10.0.0.2
+	local port=51820
+	local outfile=./out
+	local keepalive_timeout=3
+
+	setup_servers
+
+	# It sets key_priv_local key_pub_local key_priv_peer key_pub_peer
+	generate_keys
+
+	export RUMP_SERVER=$SOCK_LOCAL
+	setup_common shmif0 inet $ip_local 24
+	setup_wg_common wg0 inet $ip_wg_local 24 $port "$key_priv_local"
+
+	export RUMP_SERVER=$SOCK_PEER
+	setup_common shmif0 inet $ip_peer 24
+	setup_wg_common wg0 inet $ip_wg_peer 24 $port "$key_priv_peer"
+
+	export RUMP_SERVER=$SOCK_LOCAL
+	add_peer wg0 peer0 $key_pub_peer $ip_peer:$port $ip_wg_peer/32
+
+	export RUMP_SERVER=$SOCK_PEER
+	add_peer wg0 peer0 $key_pub_local $ip_local:$port $ip_wg_local/32
+
+	# Shorten keepalive_timeout of the peer
+	atf_check -s exit:0 -o ignore \
+	    rump.sysctl -w net.wg.keepalive_timeout=$keepalive_timeout
+
+	export RUMP_SERVER=$SOCK_LOCAL
+
+	extract_new_packets $BUS > $outfile
+	$DEBUG && cat $outfile
+
+	$ping $ip_wg_peer
+
+	extract_new_packets $BUS > $outfile
+	$DEBUG && cat $outfile
+
+	sleep $((keepalive_timeout + 1))
+
+	$ping $ip_wg_peer
+
+	extract_new_packets $BUS > $outfile
+	$DEBUG && cat $outfile
+
+	# XXX length 32 indicates the message is a keepalive (empty) message
+	atf_check -s exit:0 -o match:"$ip_peer.$port > $ip_local.$port: UDP, length 32" \
+	    cat $outfile
+
+	destroy_wg_interfaces
+}
+
+wg_keepalive_cleanup()
+{
+
+	$DEBUG && dump
+	cleanup
+}
+
+atf_test_case wg_psk cleanup
+wg_psk_head()
+{
+
+	atf_set "descr" "tests preshared-key"
+	atf_set "require.progs" "rump_server" "wgconfig" "wg-keygen"
+}
+
+test_psk_common()
+{
+}
+
+wg_psk_body()
+{
+	local ifconfig="atf_check -s exit:0 rump.ifconfig"
+	local ping="atf_check -s exit:0 -o ignore rump.ping -n -i 0.1 -c 3 -w 1"
+	local ping_fail="atf_check -s not-exit:0 -o ignore rump.ping -n -c 1 -w 1"
+	local ip_local=192.168.1.1
+	local ip_peer=192.168.1.2
+	local ip_peer_new=192.168.1.3
+	local ip_wg_local=10.0.0.1
+	local ip_wg_peer=10.0.0.2
+	local port=51820
+	local outfile=./out
+	local pskfile=./psk
+	local rekey_after_time=3
+
+	setup_servers
+
+	export RUMP_SERVER=$SOCK_LOCAL
+	atf_check -s exit:0 -o ignore \
+	    rump.sysctl -w net.wg.rekey_after_time=$rekey_after_time
+	export RUMP_SERVER=$SOCK_PEER
+	atf_check -s exit:0 -o ignore \
+	    rump.sysctl -w net.wg.rekey_after_time=$rekey_after_time
+
+	# It sets key_priv_local key_pub_local key_priv_peer key_pub_peer
+	generate_keys
+	key_psk=$(wg-keygen --psk)
+	$DEBUG && echo $key_psk
+
+	export RUMP_SERVER=$SOCK_LOCAL
+	setup_common shmif0 inet $ip_local 24
+	setup_wg_common wg0 inet $ip_wg_local 24 $port "$key_priv_local"
+
+	export RUMP_SERVER=$SOCK_PEER
+	setup_common shmif0 inet $ip_peer 24
+	setup_wg_common wg0 inet $ip_wg_peer 24 $port "$key_priv_peer"
+
+	echo "$key_psk" > $pskfile
+
+	export RUMP_SERVER=$SOCK_LOCAL
+
+	# The local always has the preshared key
+	add_peer wg0 peer0 $key_pub_peer $ip_peer:$port $ip_wg_peer/32 \
+	    $pskfile "$key_psk"
+
+	export RUMP_SERVER=$SOCK_PEER
+
+	# First, try the peer without the preshared key
+	add_peer wg0 peer0 $key_pub_local $ip_local:$port $ip_wg_local/32
+
+	export RUMP_SERVER=$SOCK_LOCAL
+
+	extract_new_packets $BUS > $outfile
+	$DEBUG && cat $outfile
+
+	$ping_fail $ip_wg_peer
+
+	extract_new_packets $BUS > $outfile
+	$DEBUG && cat $outfile
+
+	# Next, try with the preshared key
+	export RUMP_SERVER=$SOCK_PEER
+	delete_peer wg0 peer0
+	add_peer wg0 peer0 $key_pub_local $ip_local:$port $ip_wg_local/32 \
+	    $pskfile "$key_psk"
+
+	# Need a rekey
+	atf_check -s exit:0 sleep $((rekey_after_time + 1))
+
+	export RUMP_SERVER=$SOCK_LOCAL
+
+	extract_new_packets $BUS > $outfile
+	$DEBUG && cat $outfile
+
+	$ping $ip_wg_peer
+
+	extract_new_packets $BUS > $outfile
+	$DEBUG && cat $outfile
+
+	# Then, try again without the preshared key just in case
+	export RUMP_SERVER=$SOCK_PEER
+	delete_peer wg0 peer0
+	add_peer wg0 peer0 $key_pub_local $ip_local:$port $ip_wg_local/32
+
+	# Need a rekey
+	atf_check -s exit:0 sleep $((rekey_after_time + 1))
+
+	export RUMP_SERVER=$SOCK_LOCAL
+	$ping_fail $ip_wg_peer
+
+	rm -f $pskfile
+
+	destroy_wg_interfaces
+}
+
+wg_psk_cleanup()
+{
+
+	$DEBUG && dump
+	cleanup
+}
+
+atf_init_test_cases()
+{
+
+	atf_add_test_case wg_rekey
+	atf_add_test_case wg_handshake_timeout
+	atf_add_test_case wg_cookie
+	atf_add_test_case wg_mobility
+	atf_add_test_case wg_keepalive
+	atf_add_test_case wg_psk
+}
Index: src/tests/net/if_wg/t_tunnel.sh
diff -u /dev/null src/tests/net/if_wg/t_tunnel.sh:1.1
--- /dev/null	Wed Aug 26 16:03:43 2020
+++ src/tests/net/if_wg/t_tunnel.sh	Wed Aug 26 16:03:42 2020
@@ -0,0 +1,332 @@
+#	$NetBSD: t_tunnel.sh,v 1.1 2020/08/26 16:03:42 riastradh Exp $
+#
+# Copyright (c) 2018 Ryota Ozaki <[email protected]>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+BUS_LOCAL=bus_local
+BUS_TUN=bus_tun
+BUS_PEER=bus_peer
+SOCK_LOCAL=unix://wg_local
+SOCK_TUN_LOCAL=unix://wg_tun_local
+SOCK_TUN_PEER=unix://wg_tun_peer
+SOCK_PEER=unix://wg_peer
+
+escape_key()
+{
+
+	echo $1 | sed 's/\+/\\+/g' | sed 's|\/|\\/|g'
+}
+
+setup_servers()
+{
+
+	rump_server_start $SOCK_LOCAL netinet6
+	rump_server_add_iface $SOCK_LOCAL shmif0 $BUS_LOCAL
+
+	rump_server_crypto_start $SOCK_TUN_LOCAL netinet6 wg
+	rump_server_add_iface $SOCK_TUN_LOCAL shmif0 $BUS_LOCAL
+	rump_server_add_iface $SOCK_TUN_LOCAL shmif1 $BUS_TUN
+
+	rump_server_crypto_start $SOCK_TUN_PEER netinet6 wg
+	rump_server_add_iface $SOCK_TUN_PEER shmif0 $BUS_PEER
+	rump_server_add_iface $SOCK_TUN_PEER shmif1 $BUS_TUN
+
+	rump_server_start $SOCK_PEER netinet6
+	rump_server_add_iface $SOCK_PEER shmif0 $BUS_PEER
+}
+
+setup_edge()
+{
+	local ifconfig="atf_check -s exit:0 rump.ifconfig"
+	local proto=$1
+	local ip=$2
+	local prefix=$3
+	local gw=$4
+	local ip_bad=$5
+	local alias=
+
+	atf_check -s exit:0 rump.sysctl -q -w net.inet.ip.dad_count=0
+	atf_check -s exit:0 rump.sysctl -q -w net.inet6.ip6.dad_count=0
+	$ifconfig shmif0 $proto $ip/$prefix
+	atf_check -s exit:0 -o ignore rump.route add -$proto default $gw
+
+	if [ -z "$ip_bad" ]; then
+		return
+	fi
+
+	if [ $proto = inet ]; then
+		alias="alias"
+	fi
+
+	$ifconfig shmif0 $proto $ip_bad/$prefix $alias
+}
+
+setup_ip()
+{
+	local ifconfig="atf_check -s exit:0 rump.ifconfig"
+	local proto=$1
+	local ip=$2
+	local prefix=$3
+
+	$ifconfig shmif0 $proto $ip/$prefix
+}
+setup_router()
+{
+
+	atf_check -s exit:0 rump.sysctl -q -w net.inet.ip.forwarding=1
+	atf_check -s exit:0 rump.sysctl -q -w net.inet6.ip6.forwarding=1
+	atf_check -s exit:0 rump.sysctl -q -w net.inet.ip.dad_count=0
+	atf_check -s exit:0 rump.sysctl -q -w net.inet6.ip6.dad_count=0
+}
+
+setup_wg()
+{
+	local ifconfig="atf_check -s exit:0 rump.ifconfig"
+	local wgconfig="atf_check -s exit:0 $HIJACKING wgconfig"
+	local proto=$1
+	local ip=$2
+	local prefix=$3
+	local port=$4
+	local key_priv="$5"
+	local privfile=./tmp
+
+	$ifconfig wg0 create
+	$ifconfig wg0 $proto $ip/$prefix
+	$DEBUG && rump.netstat -nr
+	echo $key_priv > $privfile
+	$wgconfig wg0 set private-key $privfile
+	$wgconfig wg0 set listen-port $port
+	rm -f $privfile
+	$ifconfig wg0 up
+
+	check_conf_port wg0 $port
+	check_conf_privkey wg0 "$key_priv"
+}
+
+setup_wg_route()
+{
+	local proto=$1
+	local subnet=$2
+	local subnet_bad=$3
+
+	atf_check -s exit:0 -o ignore rump.route add -$proto -net $subnet -link wg0 -iface
+	if [ -n "$subnet_bad" ]; then
+		atf_check -s exit:0 -o ignore rump.route add -$proto -net $subnet_bad -link wg0 -iface
+	fi
+}
+
+prepare_file()
+{
+	local file=$1
+	local data="0123456789"
+
+	touch $file
+	for i in `seq 1 200`
+	do
+		echo $data >> $file
+	done
+}
+
+test_tcp()
+{
+	local proto=$1
+	local ip_peer=$2
+	local _proto=
+
+	prepare_file ./file_send
+
+	if [ $proto = inet ]; then
+		_proto=ipv4
+	else
+		_proto=ipv6
+	fi
+	start_nc_server $SOCK_PEER 1234 ./file_recv $_proto
+
+	export RUMP_SERVER=$SOCK_LOCAL
+	# Send a file to the server
+	# XXX Need a bit longer timeout value because the packet processing
+	# of the implementation is quite inefficient...
+	atf_check -s exit:0 $HIJACKING \
+	    nc -N -w 20 $ip_peer 1234 < ./file_send
+	$DEBUG && extract_new_packets $BUS > ./out
+	$DEBUG && cat ./out
+	stop_nc_server
+	$DEBUG && ls -s ./file_send ./file_recv
+	$DEBUG && wc -l ./file_send
+	$DEBUG && wc -l ./file_recv
+	$DEBUG && diff -u ./file_send ./file_recv
+	atf_check -s exit:0 diff -q ./file_send ./file_recv
+	rm -f ./out ./file_recv ./file_send
+}
+
+wg_tunnel_common()
+{
+	local outer_proto=$1
+	local inner_proto=$2
+	local ifconfig="atf_check -s exit:0 rump.ifconfig"
+	local wgconfig="atf_check -s exit:0 $HIJACKING wgconfig"
+	local port=51820
+	local ip_local= ip_peer=
+	local ip_wg_local= ip_wg_peer=
+	local outer_prefix= outer_prefixall=
+	local inner_prefix= inner_prefixall=
+
+	if [ $outer_proto = inet ]; then
+		ip_tun_local_tun=192.168.10.1
+		ip_tun_peer_tun=192.168.10.2
+		outer_prefix=24
+		outer_prefixall=32
+	else
+		ip_tun_local_tun=fc00:10::1
+		ip_tun_peer_tun=fc00:10::2
+		outer_prefix=64
+		outer_prefixall=128
+	fi
+
+	if [ $inner_proto = inet ]; then
+		ip_local=192.168.1.2
+		ip_tun_local=192.168.1.1
+		ip_wg_local=10.0.0.1
+		ip_wg_peer=10.0.0.2
+		ip_tun_peer=192.168.2.1
+		ip_peer=192.168.2.2
+		ip_peer_bad=192.168.3.2
+		inner_prefix=24
+		inner_prefixall=32
+		subnet_local=192.168.1.0/24
+		subnet_peer=192.168.2.0/24
+		subnet_peer_bad=192.168.3.0/24
+	else
+		ip_tun_local=fc00:1::1
+		ip_local=fc00:1::2
+		ip_wg_local=fd00::1
+		ip_wg_peer=fd00::2
+		ip_tun_peer=fc00:2::1
+		ip_peer=fc00:2::2
+		ip_peer_bad=fc00:3::2
+		inner_prefix=64
+		inner_prefixall=128
+		subnet_local=fc00:1::/64
+		subnet_peer=fc00:2::/64
+		subnet_peer_bad=fc00:3::/64
+	fi
+
+	setup_servers
+
+	# It sets key_priv_local key_pub_local key_priv_peer key_pub_peer
+	generate_keys
+
+	export RUMP_SERVER=$SOCK_LOCAL
+	setup_edge $inner_proto $ip_local $inner_prefix $ip_tun_local
+
+	export RUMP_SERVER=$SOCK_TUN_LOCAL
+	setup_router
+	$ifconfig shmif0 $inner_proto $ip_tun_local/$inner_prefix
+	$ifconfig shmif1 $outer_proto $ip_tun_local_tun/$outer_prefix
+	setup_wg $inner_proto $ip_wg_local $inner_prefix $port "$key_priv_local"
+	setup_wg_route $inner_proto $subnet_peer $subnet_peer_bad
+
+	export RUMP_SERVER=$SOCK_TUN_PEER
+	setup_router
+	$ifconfig shmif0 $inner_proto $ip_tun_peer/$inner_prefix
+	$ifconfig shmif1 $outer_proto $ip_tun_peer_tun/$outer_prefix
+	setup_wg $inner_proto $ip_wg_peer $inner_prefix $port "$key_priv_peer"
+	setup_wg_route $inner_proto $subnet_local
+
+	export RUMP_SERVER=$SOCK_PEER
+	setup_edge $inner_proto $ip_peer $inner_prefix $ip_tun_peer $ip_peer_bad
+
+	export RUMP_SERVER=$SOCK_TUN_LOCAL
+	add_peer wg0 peer0 $key_pub_peer $ip_tun_peer_tun:$port \
+	    $ip_wg_peer/$inner_prefixall,$subnet_peer
+
+	export RUMP_SERVER=$SOCK_TUN_PEER
+	add_peer wg0 peer0 $key_pub_local $ip_tun_local_tun:$port \
+	    $ip_wg_local/$inner_prefixall,$subnet_local
+
+	export RUMP_SERVER=$SOCK_TUN_LOCAL
+	atf_check -s exit:0 -o match:"latest-handshake: 0" \
+	    $HIJACKING wgconfig wg0 show peer peer0
+
+	export RUMP_SERVER=$SOCK_LOCAL
+	check_ping $inner_proto $ip_peer
+
+	export RUMP_SERVER=$SOCK_TUN_LOCAL
+	atf_check -s exit:0 -o not-match:"latest-handshake: 0" \
+	    $HIJACKING wgconfig wg0 show peer peer0
+
+	export RUMP_SERVER=$SOCK_LOCAL
+	# ping fails because the subnet of the IP is not allowed
+	check_ping_fail $inner_proto $ip_peer_bad
+
+	#
+	# Test TCP stream over the tunnel
+	#
+	test_tcp $inner_proto $ip_peer
+
+	export RUMP_SERVER=$SOCK_TUN_LOCAL
+	$ifconfig wg0 destroy
+	export RUMP_SERVER=$SOCK_TUN_PEER
+	$ifconfig wg0 destroy
+}
+
+add_tunnel_test()
+{
+	local inner=$1
+	local outer=$2
+	local ipv4=inet
+	local ipv6=inet6
+
+	name="wg_tunnel_${inner}_over_${outer}"
+	fulldesc="Test wg(4) with ${inner} over ${outer}"
+
+	eval inner=\$$inner
+	eval outer=\$$outer
+
+	atf_test_case ${name} cleanup
+	eval "
+		${name}_head() {
+			atf_set descr \"${fulldesc}\"
+			atf_set require.progs rump_server wgconfig wg-keygen
+		}
+		${name}_body() {
+			wg_tunnel_common $outer $inner
+			rump_server_destroy_ifaces
+		}
+		${name}_cleanup() {
+			\$DEBUG && dump
+			cleanup
+		}"
+	atf_add_test_case ${name}
+}
+
+atf_init_test_cases()
+{
+
+	add_tunnel_test ipv4 ipv4
+	add_tunnel_test ipv4 ipv6
+	add_tunnel_test ipv6 ipv4
+	add_tunnel_test ipv6 ipv6
+}

Reply via email to