diff options
-rw-r--r-- | tunnel/src/main/java/com/wireguard/android/backend/GoBackend.java | 58 | ||||
-rw-r--r-- | tunnel/tools/libwg-go/Makefile | 2 | ||||
-rw-r--r-- | tunnel/tools/libwg-go/api-android.go | 60 | ||||
-rw-r--r-- | tunnel/tools/libwg-go/go.mod | 4 | ||||
-rw-r--r-- | tunnel/tools/libwg-go/jni.c | 10 |
5 files changed, 116 insertions, 18 deletions
diff --git a/tunnel/src/main/java/com/wireguard/android/backend/GoBackend.java b/tunnel/src/main/java/com/wireguard/android/backend/GoBackend.java index fdbf0e9c..57071f63 100644 --- a/tunnel/src/main/java/com/wireguard/android/backend/GoBackend.java +++ b/tunnel/src/main/java/com/wireguard/android/backend/GoBackend.java @@ -25,8 +25,12 @@ import com.wireguard.crypto.KeyFormatException; import com.wireguard.util.NonNullForAll; import java.net.InetAddress; +import java.net.Inet4Address; +import java.net.Inet6Address; +import java.net.UnknownHostException; import java.util.Collections; import java.util.LinkedHashSet; +import java.util.Random; import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; @@ -50,6 +54,7 @@ public final class GoBackend implements Backend, EventHandler { private final Context context; @Nullable private Config currentConfig; @Nullable private Tunnel currentTunnel; + @Nullable private String currentDhcpEvent; private int currentTunnelHandle = -1; /** @@ -84,7 +89,7 @@ public final class GoBackend implements Backend, EventHandler { private static native int wgTurnOn(String ifName, int tunFd, String settings, EventHandler handler); - private static native int wgTurnOnDhcp(String ifName, String settings, EventHandler handler); + private static native int wgTurnOnDhcp(String ifName, String lladdr, String settings, EventHandler handler); private static native String wgVersion(); @@ -94,8 +99,8 @@ public final class GoBackend implements Backend, EventHandler { if (tunnel != currentTunnel) { return info; } - // TODO update info - info.set("FIXME"); + // TODO use nicer format + info.set(currentDhcpEvent); return info; } @@ -349,13 +354,18 @@ public final class GoBackend implements Backend, EventHandler { } else { // Build config final String goConfig = config.toWgUserspaceString(); + // TODO verify that an address is available + final String llAddr = config.getInterface().getAddresses().iterator().next().getAddress().getHostAddress(); - currentTunnelHandle = wgTurnOnDhcp(tunnel.getName(), goConfig, this); + Log.w(TAG, "Using DHCPv6 src=" + llAddr); + + currentTunnelHandle = wgTurnOnDhcp(tunnel.getName(), llAddr, goConfig, this); if (currentTunnelHandle < 0) throw new BackendException(Reason.GO_ACTIVATION_ERROR_CODE, currentTunnelHandle); currentTunnel = tunnel; currentConfig = config; + currentDhcpEvent = null; } } else { if (currentTunnelHandle == -1) { @@ -366,12 +376,22 @@ public final class GoBackend implements Backend, EventHandler { currentTunnel = null; currentTunnelHandle = -1; currentConfig = null; + currentDhcpEvent = null; wgTurnOff(handleToClose); } tunnel.onStateChange(state); } + private byte[] generateIID() { + // The resulting IID MUST be compared against the reserved IPv6 IIDs + // [RFC5453] [IANA-RESERVED-IID] and against those IIDs already + Random rnd = new Random(); + byte[] data = new byte[8]; + rnd.nextBytes(data); + return data; + } + public void onEvent(String event) { boolean isEvent = false; Set<InetNetwork> addresses = new LinkedHashSet<>(); @@ -392,17 +412,45 @@ public final class GoBackend implements Backend, EventHandler { } if ("address".equals(key)) { + boolean hasPD = false; + byte[] iid = null; + for (final String strAddr : value.split(",")) { try { InetNetwork addr = InetNetwork.parse(strAddr); - if (addr.getMask() < 33 || addr.getMask() == 128) + if (addr.getAddress() instanceof Inet4Address) + // Add IPv4 address addresses.add(addr); + else if (addr.getMask() <= 64) { + // IPv6 prefix delegation + if (!hasPD) { + iid = generateIID(); + } + hasPD = true; + byte[] raw = addr.getAddress().getAddress(); + System.arraycopy(iid, 0, raw, 8, 8); + InetAddress tempAddr = Inet6Address.getByAddress(null, raw, 0); + addresses.add(InetNetwork.parse(tempAddr.getHostAddress() + '/' + addr.getMask())); + } + } catch(final UnknownHostException ignored) { } catch(final ParseException ignored) { } } + + // TODO add ipv6 addresses from DHCPv6-NA if no PD. } } + if (isEvent) { + StringBuilder buf = new StringBuilder(); + buf.append("addresses:\n"); + for (final InetNetwork addr : addresses) { + buf.append(addr.toString()); + buf.append('\n'); + } + currentDhcpEvent = buf.toString(); + } + if (addresses.size() > 0) { try { setStateInternalFinalize(currentTunnel, currentConfig, addresses); diff --git a/tunnel/tools/libwg-go/Makefile b/tunnel/tools/libwg-go/Makefile index a2aefef7..ede83094 100644 --- a/tunnel/tools/libwg-go/Makefile +++ b/tunnel/tools/libwg-go/Makefile @@ -46,7 +46,7 @@ $(BUILDDIR)/go-$(GO_VERSION)/.prepared: $(GRADLE_USER_HOME)/caches/golang/$(GO_T touch "$@"' $(DESTDIR)/libwg-go.so: export PATH := $(BUILDDIR)/go-$(GO_VERSION)/bin/:$(PATH) -$(DESTDIR)/libwg-go.so: $(BUILDDIR)/go-$(GO_VERSION)/.prepared go.mod +$(DESTDIR)/libwg-go.so: $(BUILDDIR)/go-$(GO_VERSION)/.prepared go.mod jni.c api-android.go go build -tags linux -ldflags="-X golang.zx2c4.com/wireguard/ipc.socketDirectory=/data/data/$(ANDROID_PACKAGE_NAME)/cache/wireguard" -v -trimpath -o "$@" -buildmode c-shared .DELETE_ON_ERROR: diff --git a/tunnel/tools/libwg-go/api-android.go b/tunnel/tools/libwg-go/api-android.go index cadbab12..23276c28 100644 --- a/tunnel/tools/libwg-go/api-android.go +++ b/tunnel/tools/libwg-go/api-android.go @@ -64,7 +64,7 @@ type TunnelHandle struct { eventHandler unsafe.Pointer cancel context.CancelFunc master *ipvlan.IPVLANMaster - // tunEP *stack.LinkEndpoint + tunEP stack.LinkEndpoint tunFd int } @@ -203,7 +203,7 @@ func createNetTUNWithStack(stack *stack.Stack, nicID tcpip.NICID, localAddresses } //export wgTurnOnDhcp -func wgTurnOnDhcp(interfaceName string, settings string, eventHandler unsafe.Pointer) int32 { +func wgTurnOnDhcp(interfaceName string, lladdr string, settings string, eventHandler unsafe.Pointer) int32 { tag := cstring("WireGuard/GoBackend/" + interfaceName) logger := &device.Logger{ Verbosef: AndroidLogger{level: C.ANDROID_LOG_DEBUG, tag: tag}.Printf, @@ -212,18 +212,16 @@ func wgTurnOnDhcp(interfaceName string, settings string, eventHandler unsafe.Poi stack := globalStack - // FIXME IP address - ipStr := "fe80::101" // FIXME name name := "wg0" var tundev tun.Device var tnet *netstack.Net + llipaddr := net.ParseIP(lladdr) tundev, tnet, master, err := createNetTUNWithStack( stack, 1, - []net.IP{net.ParseIP(ipStr)}, - // []net.IP{net.ParseIP("fe80::1")}, - []net.IP{net.ParseIP("fe80::1")}, + []net.IP{llipaddr}, + []net.IP{net.ParseIP("ff02::1:2")}, 1420) if err != nil { log.Panic(err) @@ -289,7 +287,7 @@ func wgTurnOnDhcp(interfaceName string, settings string, eventHandler unsafe.Poi go func(ctx context.Context) { logger.Verbosef("Start dhcp client") - src, err := net.ResolveUDPAddr("udp6", fmt.Sprintf("[%s%%1]:546", ipStr)) + src, err := net.ResolveUDPAddr("udp6", fmt.Sprintf("[%s%%1]:546", lladdr)) if err != nil { logger.Errorf("ResolveUDPAddr: %v", err) return @@ -305,10 +303,18 @@ func wgTurnOnDhcp(interfaceName string, settings string, eventHandler unsafe.Poi } logger.Verbosef("Conn: %v %v %v", src, dst, conn) - hwAddr := []byte(" 101") + // TODO check byte 11, 12 of lladdr is ff fe + hwAddr := []byte{0, 0, 0, 0, 0, 0} + hwAddr[0] = llipaddr[8] ^ 0x02 + hwAddr[1] = llipaddr[9] + hwAddr[2] = llipaddr[10] + hwAddr[3] = llipaddr[13] + hwAddr[4] = llipaddr[14] + hwAddr[5] = llipaddr[15] addrs, err := netstack.RunDhcp(ctx, conn, hwAddr) if err != nil { + conn.Close() logger.Errorf("DHCP: %v", err) return } @@ -316,6 +322,9 @@ func wgTurnOnDhcp(interfaceName string, settings string, eventHandler unsafe.Poi msg := "" logger.Verbosef("DHCP finished") + + conn.Close() + for _, addr := range addrs { logger.Verbosef("Address: %v", addr) if msg == "" { @@ -337,6 +346,12 @@ func wgTurnOnDhcp(interfaceName string, settings string, eventHandler unsafe.Poi //export wgSetFd func wgSetFd(tunnelHandle int32, tunFd int32) { + tag := cstring(fmt.Sprintf("WireGuard/GoBackend/%x", tunnelHandle)) + logger := &device.Logger{ + Verbosef: AndroidLogger{level: C.ANDROID_LOG_DEBUG, tag: tag}.Printf, + Errorf: AndroidLogger{level: C.ANDROID_LOG_ERROR, tag: tag}.Printf, + } + handle, ok := tunnelHandles[tunnelHandle] if !ok { return @@ -349,19 +364,46 @@ func wgSetFd(tunnelHandle int32, tunFd int32) { log.Fatal(err) } handle.tunFd = int(tunFd) + handle.tunEP = tunEP + // FIXME panic +// 03-23 22:19:25.182 9818 0 E Go : panic: runtime error: invalid memory address or nil pointer dereference +// 03-23 22:19:25.182 9818 0 E Go : [signal SIGSEGV: segmentation violation code=0x1 addr=0x34 pc=0x9f0f5d58] +// 03-23 22:19:25.182 9818 0 E Go : goroutine 59 [running]: +// 03-23 22:19:25.182 9818 0 E Go : golang.zx2c4.com/wireguard/tun/netstack/ipvlan.(*dispatcher).DeliverNetworkPacket(0x4f1a2008, 0x0, 0x0, 0x0, 0x0, 0x86dd, 0x4f1fe000) +// 03-23 22:19:25.182 9818 0 E Go : golang.zx2c4.com/wireguard/tun/netstack@v0.0.0-00010101000000-000000000000/ipvlan/endpoint.go:104 +0x48 +// 03-23 22:19:25.182 9818 0 E Go : golang.zx2c4.com/wireguard/tun/netstack.(*netTun).Write(0x4f1ac000, 0x4f1ec900, 0x77, 0x898, 0x10, 0x1, 0x0, 0x0) +// 03-23 22:19:25.182 9818 0 E Go : golang.zx2c4.com/wireguard/tun/netstack@v0.0.0-00010101000000-000000000000/tun.go:187 +0x1d4 +// 03-23 22:19:25.182 9818 0 E Go : golang.zx2c4.com/wireguard/device.(*Peer).RoutineSequentialReceiver(0x4f1f2000) +// 03-23 22:19:25.182 9818 0 E Go : golang.zx2c4.com/wireguard@v0.0.0-20210306154438-593658d9755b/device/receive.go:479 +0x3d8 +// 03-23 22:19:25.183 9818 0 E Go : created by golang.zx2c4.com/wireguard/device.(*Peer).Start +// 03-23 22:19:25.183 9818 0 E Go : golang.zx2c4.com/wireguard@v0.0.0-20210306154438-593658d9755b/device/peer.go:187 +0x254 +// 03-23 22:19:25.183 9818 9907 F libc : Fatal signal 6 (SIGABRT), code -6 in tid 9907 (DefaultDispatch) + handle.master.SetIntEP(tunEP) + logger.Verbosef("wgSetFd: %v %v", tunFd, tunEP) + tunnelHandles[tunnelHandle] = handle } //export wgTurnOff func wgTurnOff(tunnelHandle int32) unsafe.Pointer { + tag := cstring(fmt.Sprintf("WireGuard/GoBackend/%x", tunnelHandle)) + logger := &device.Logger{ + Verbosef: AndroidLogger{level: C.ANDROID_LOG_DEBUG, tag: tag}.Printf, + Errorf: AndroidLogger{level: C.ANDROID_LOG_ERROR, tag: tag}.Printf, + } + handle, ok := tunnelHandles[tunnelHandle] if !ok { return nil } if handle.master != nil { + logger.Verbosef("IPLAN master: %v %v", handle.tunFd, handle.tunEP) globalStack.RemoveNIC(1) handle.master.SetIntEP(nil) +// handle.tunEP.Wait() unix.Close(handle.tunFd) + } else { + logger.Verbosef("No IPLAN master") } eventHandler := handle.eventHandler diff --git a/tunnel/tools/libwg-go/go.mod b/tunnel/tools/libwg-go/go.mod index 98bbf52a..fd1062e4 100644 --- a/tunnel/tools/libwg-go/go.mod +++ b/tunnel/tools/libwg-go/go.mod @@ -13,4 +13,6 @@ require ( golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 // indirect ) -replace golang.zx2c4.com/wireguard/tun/netstack => golang.m7n.se/wireguard/tun/netstack v0.0.0-20210315192121-e7c9dcf39d3f +replace golang.zx2c4.com/wireguard/tun/netstack => golang.m7n.se/wireguard/tun/netstack v0.0.0-20210323213515-b1d14fde2868 + +replace gvisor.dev/gvisor => golang.m7n.se/gvisor v0.0.0-20210323153804-db430c5fd7a9 diff --git a/tunnel/tools/libwg-go/jni.c b/tunnel/tools/libwg-go/jni.c index 3897b2b7..3660e96a 100644 --- a/tunnel/tools/libwg-go/jni.c +++ b/tunnel/tools/libwg-go/jni.c @@ -13,7 +13,7 @@ struct go_string { const char *str; long n; }; extern int wgTurnOn(struct go_string ifname, int tun_fd, struct go_string settings, void *eventHandler); -extern int wgTurnOnDhcp(struct go_string ifname, struct go_string settings, void *eventHandler); +extern int wgTurnOnDhcp(struct go_string ifname, struct go_string lladdr, struct go_string settings, void *eventHandler); extern void wgSetFd(int handle, int tun_fd); extern void *wgTurnOff(int handle); extern int wgGetSocketV4(int handle); @@ -72,10 +72,12 @@ JNIEXPORT jint JNICALL Java_com_wireguard_android_backend_GoBackend_wgTurnOn(JNI return ret; } -JNIEXPORT jint JNICALL Java_com_wireguard_android_backend_GoBackend_wgTurnOnDhcp(JNIEnv *env, jclass c, jstring ifname, jstring settings, jobject eventHandler) +JNIEXPORT jint JNICALL Java_com_wireguard_android_backend_GoBackend_wgTurnOnDhcp(JNIEnv *env, jclass c, jstring ifname, jstring lladdr, jstring settings, jobject eventHandler) { const char *ifname_str = (*env)->GetStringUTFChars(env, ifname, 0); size_t ifname_len = (*env)->GetStringUTFLength(env, ifname); + const char *lladdr_str = (*env)->GetStringUTFChars(env, lladdr, 0); + size_t lladdr_len = (*env)->GetStringUTFLength(env, lladdr); const char *settings_str = (*env)->GetStringUTFChars(env, settings, 0); size_t settings_len = (*env)->GetStringUTFLength(env, settings); jobject event_handler = (*env)->NewGlobalRef(env, eventHandler); @@ -83,10 +85,14 @@ JNIEXPORT jint JNICALL Java_com_wireguard_android_backend_GoBackend_wgTurnOnDhcp .str = ifname_str, .n = ifname_len }, (struct go_string){ + .str = lladdr_str, + .n = lladdr_len + }, (struct go_string){ .str = settings_str, .n = settings_len }, event_handler); (*env)->ReleaseStringUTFChars(env, ifname, ifname_str); + (*env)->ReleaseStringUTFChars(env, lladdr, lladdr_str); (*env)->ReleaseStringUTFChars(env, settings, settings_str); return ret; } |