summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMikael Magnusson <mikma@users.sourceforge.net>2021-03-15 20:22:58 +0000
committerMikael Magnusson <mikma@users.sourceforge.net>2023-02-07 22:43:22 +0100
commit421bae85375dbef7fb64759eae22134d3c42a1fe (patch)
treeeb94e3fd7d448a1f11fba03fa39f7f555cabd615
parent3058775eb43b3c69a42939f52e493cca804f2108 (diff)
WIP: implement dhcp in tunnel
-rw-r--r--tunnel/src/main/java/com/wireguard/android/backend/GoBackend.java104
-rw-r--r--tunnel/tools/libwg-go/api-android.go51
-rw-r--r--tunnel/tools/libwg-go/go.mod2
-rw-r--r--tunnel/tools/libwg-go/jni.c27
4 files changed, 155 insertions, 29 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 edf6ac9e..f077189a 100644
--- a/tunnel/src/main/java/com/wireguard/android/backend/GoBackend.java
+++ b/tunnel/src/main/java/com/wireguard/android/backend/GoBackend.java
@@ -18,6 +18,7 @@ import com.wireguard.android.util.SharedLibraryLoader;
import com.wireguard.config.Config;
import com.wireguard.config.InetEndpoint;
import com.wireguard.config.InetNetwork;
+import com.wireguard.config.ParseException;
import com.wireguard.config.Peer;
import com.wireguard.crypto.Key;
import com.wireguard.crypto.KeyFormatException;
@@ -25,6 +26,7 @@ import com.wireguard.util.NonNullForAll;
import java.net.InetAddress;
import java.util.Collections;
+import java.util.LinkedHashSet;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
@@ -76,10 +78,14 @@ public final class GoBackend implements Backend, EventHandler {
private static native int wgGetSocketV6(int handle);
+ private static native void wgSetFd(int handle, int tunFd);
+
private static native void wgTurnOff(int handle);
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 String wgVersion();
/**
@@ -205,14 +211,9 @@ public final class GoBackend implements Backend, EventHandler {
return getState(tunnel);
}
- private void setStateInternal(final Tunnel tunnel, @Nullable final Config config, final State state)
+ private void setStateInternalFinalize(final Tunnel tunnel, final Config config, Set<InetNetwork> addresses)
throws Exception {
- Log.i(TAG, "Bringing tunnel " + tunnel.getName() + ' ' + state);
-
- if (state == State.UP) {
- if (config == null)
- throw new BackendException(Reason.TUNNEL_MISSING_CONFIG);
-
+ if (true) { // Add scope to avoid changing indentation level
if (VpnService.prepare(context) != null)
throw new BackendException(Reason.VPN_NOT_AUTHORIZED);
@@ -231,12 +232,6 @@ public final class GoBackend implements Backend, EventHandler {
}
service.setOwner(this);
- if (currentTunnelHandle != -1) {
- Log.w(TAG, "Tunnel already up");
- return;
- }
-
-
dnsRetry: for (int i = 0; i < DNS_RESOLUTION_RETRIES; ++i) {
// Pre-resolve IPs so they're cached when building the userspace string
for (final Peer peer : config.getPeers()) {
@@ -268,9 +263,13 @@ public final class GoBackend implements Backend, EventHandler {
for (final String includedApplication : config.getInterface().getIncludedApplications())
builder.addAllowedApplication(includedApplication);
- for (final InetNetwork addr : config.getInterface().getAddresses())
- builder.addAddress(addr.getAddress(), addr.getMask());
-
+ if (addresses.size() > 0) {
+ for (final InetNetwork addr : addresses)
+ builder.addAddress(addr.getAddress(), addr.getMask());
+ } else {
+ for (final InetNetwork addr : config.getInterface().getAddresses())
+ builder.addAddress(addr.getAddress(), addr.getMask());
+ }
for (final InetAddress addr : config.getInterface().getDnsServers())
builder.addDnsServer(addr.getHostAddress());
@@ -304,7 +303,11 @@ public final class GoBackend implements Backend, EventHandler {
if (tun == null)
throw new BackendException(Reason.TUN_CREATION_ERROR);
Log.d(TAG, "Go backend " + wgVersion());
- currentTunnelHandle = wgTurnOn(tunnel.getName(), tun.detachFd(), goConfig, this);
+ if (currentTunnelHandle < 0) {
+ currentTunnelHandle = wgTurnOn(tunnel.getName(), tun.detachFd(), goConfig, this);
+ } else {
+ wgSetFd(currentTunnelHandle, tun.detachFd());
+ }
}
if (currentTunnelHandle < 0)
throw new BackendException(Reason.GO_ACTIVATION_ERROR_CODE, currentTunnelHandle);
@@ -314,6 +317,35 @@ public final class GoBackend implements Backend, EventHandler {
service.protect(wgGetSocketV4(currentTunnelHandle));
service.protect(wgGetSocketV6(currentTunnelHandle));
+ }
+ }
+
+ private void setStateInternal(final Tunnel tunnel, @Nullable final Config config, final State state)
+ throws Exception {
+ Log.i(TAG, "Bringing tunnel " + tunnel.getName() + ' ' + state);
+
+ if (state == State.UP) {
+ if (config == null)
+ throw new BackendException(Reason.TUNNEL_MISSING_CONFIG);
+
+ if (currentTunnelHandle != -1) {
+ Log.w(TAG, "Tunnel already up");
+ return;
+ }
+
+ if (false) {
+ setStateInternalFinalize(tunnel, config, null);
+ } else {
+ // Build config
+ final String goConfig = config.toWgUserspaceString();
+
+ currentTunnelHandle = wgTurnOnDhcp(tunnel.getName(), goConfig, this);
+ if (currentTunnelHandle < 0)
+ throw new BackendException(Reason.GO_ACTIVATION_ERROR_CODE, currentTunnelHandle);
+
+ currentTunnel = tunnel;
+ currentConfig = config;
+ }
} else {
if (currentTunnelHandle == -1) {
Log.w(TAG, "Tunnel already down");
@@ -330,7 +362,43 @@ public final class GoBackend implements Backend, EventHandler {
}
public void onEvent(String event) {
- Log.d(TAG, "onEvent: " + event);
+ boolean isEvent = false;
+ Set<InetNetwork> addresses = new LinkedHashSet<>();
+
+ Log.d(TAG, "onEvent: " + event);
+ for (final String line : event.split("\\n")) {
+ final String[] params = line.split("=", 2);
+ if (params.length != 2)
+ break;
+
+ final String key = params[0];
+ final String value = params[1];
+
+ if ("event".equals(key)) {
+ isEvent = true;
+ } else if (!isEvent) {
+ break;
+ }
+
+ if ("address".equals(key)) {
+ for (final String strAddr : value.split(",")) {
+ try {
+ InetNetwork addr = InetNetwork.parse(strAddr);
+ if (addr.getMask() < 33 || addr.getMask() == 128)
+ addresses.add(addr);
+ } catch(final ParseException ignored) {
+ }
+ }
+ }
+ }
+
+ if (addresses.size() > 0) {
+ try {
+ setStateInternalFinalize(currentTunnel, currentConfig, addresses);
+ } catch (final Exception e) {
+ Log.d(TAG, "setStateInternalFinalize", e);
+ }
+ }
}
/**
diff --git a/tunnel/tools/libwg-go/api-android.go b/tunnel/tools/libwg-go/api-android.go
index 2fb6e40f..cadbab12 100644
--- a/tunnel/tools/libwg-go/api-android.go
+++ b/tunnel/tools/libwg-go/api-android.go
@@ -32,6 +32,7 @@ import (
"golang.zx2c4.com/wireguard/tun/netstack/ipvlan"
"gvisor.dev/gvisor/pkg/tcpip"
+ "gvisor.dev/gvisor/pkg/tcpip/link/fdbased"
"gvisor.dev/gvisor/pkg/tcpip/network/ipv4"
"gvisor.dev/gvisor/pkg/tcpip/network/ipv6"
"gvisor.dev/gvisor/pkg/tcpip/stack"
@@ -63,12 +64,21 @@ type TunnelHandle struct {
eventHandler unsafe.Pointer
cancel context.CancelFunc
master *ipvlan.IPVLANMaster
+ // tunEP *stack.LinkEndpoint
+ tunFd int
}
+var globalStack *stack.Stack
var tunnelHandles map[int32]TunnelHandle
func init() {
tunnelHandles = make(map[int32]TunnelHandle)
+ opts := stack.Options{
+ NetworkProtocols: []stack.NetworkProtocolFactory{ipv4.NewProtocol, ipv6.NewProtocol},
+ TransportProtocols: []stack.TransportProtocolFactory{tcp.NewProtocol, udp.NewProtocol},
+ HandleLocal: true,
+ }
+ globalStack = stack.New(opts)
signals := make(chan os.Signal)
signal.Notify(signals, unix.SIGUSR2)
go func() {
@@ -200,12 +210,7 @@ func wgTurnOnDhcp(interfaceName string, settings string, eventHandler unsafe.Poi
Errorf: AndroidLogger{level: C.ANDROID_LOG_ERROR, tag: tag}.Printf,
}
- opts := stack.Options{
- NetworkProtocols: []stack.NetworkProtocolFactory{ipv4.NewProtocol, ipv6.NewProtocol},
- TransportProtocols: []stack.TransportProtocolFactory{tcp.NewProtocol, udp.NewProtocol},
- HandleLocal: true,
- }
- stack := stack.New(opts)
+ stack := globalStack
// FIXME IP address
ipStr := "fe80::101"
@@ -308,14 +313,19 @@ func wgTurnOnDhcp(interfaceName string, settings string, eventHandler unsafe.Poi
return
}
+ msg := ""
+
logger.Verbosef("DHCP finished")
for _, addr := range addrs {
logger.Verbosef("Address: %v", addr)
+ if msg == "" {
+ msg = "event=1\naddress=" + addr.String()
+ } else {
+ msg += "," + addr.String()
+ }
}
- // TODO move to wgSetTunFd
- // tunEP := newTun(stack, 2, "tun0")
- // master.SetIntEP(tunEP)
+ C.wgOnEvent(tunnelHandles[i].eventHandler, C.CString(msg))
}(ctx)
logger.Verbosef("Before wgOnEvent %v", eventHandler)
@@ -325,12 +335,35 @@ func wgTurnOnDhcp(interfaceName string, settings string, eventHandler unsafe.Poi
return i
}
+//export wgSetFd
+func wgSetFd(tunnelHandle int32, tunFd int32) {
+ handle, ok := tunnelHandles[tunnelHandle]
+ if !ok {
+ return
+ }
+
+ // FIXME MTU
+ var mtu uint32 = 1280
+ tunEP, err := fdbased.New(&fdbased.Options{FDs: []int{int(tunFd)}, MTU: mtu})
+ if err != nil {
+ log.Fatal(err)
+ }
+ handle.tunFd = int(tunFd)
+ handle.master.SetIntEP(tunEP)
+}
+
//export wgTurnOff
func wgTurnOff(tunnelHandle int32) unsafe.Pointer {
handle, ok := tunnelHandles[tunnelHandle]
if !ok {
return nil
}
+ if handle.master != nil {
+ globalStack.RemoveNIC(1)
+ handle.master.SetIntEP(nil)
+ unix.Close(handle.tunFd)
+ }
+
eventHandler := handle.eventHandler
C.wgOnEvent(handle.eventHandler, C.CString("Called wgTurnOff"))
delete(tunnelHandles, tunnelHandle)
diff --git a/tunnel/tools/libwg-go/go.mod b/tunnel/tools/libwg-go/go.mod
index 6fdb520c..98bbf52a 100644
--- a/tunnel/tools/libwg-go/go.mod
+++ b/tunnel/tools/libwg-go/go.mod
@@ -13,4 +13,4 @@ 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-20210315004706-824f10afd504
+replace golang.zx2c4.com/wireguard/tun/netstack => golang.m7n.se/wireguard/tun/netstack v0.0.0-20210315192121-e7c9dcf39d3f
diff --git a/tunnel/tools/libwg-go/jni.c b/tunnel/tools/libwg-go/jni.c
index de6a1e85..3897b2b7 100644
--- a/tunnel/tools/libwg-go/jni.c
+++ b/tunnel/tools/libwg-go/jni.c
@@ -14,6 +14,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 void wgSetFd(int handle, int tun_fd);
extern void *wgTurnOff(int handle);
extern int wgGetSocketV4(int handle);
extern int wgGetSocketV6(int handle);
@@ -59,10 +60,29 @@ JNIEXPORT jint JNICALL Java_com_wireguard_android_backend_GoBackend_wgTurnOn(JNI
const char *settings_str = (*env)->GetStringUTFChars(env, settings, 0);
size_t settings_len = (*env)->GetStringUTFLength(env, settings);
jobject event_handler = (*env)->NewGlobalRef(env, eventHandler);
+ int ret = wgTurnOn((struct go_string){
+ .str = ifname_str,
+ .n = ifname_len
+ }, tun_fd, (struct go_string){
+ .str = settings_str,
+ .n = settings_len
+ }, event_handler);
+ (*env)->ReleaseStringUTFChars(env, ifname, ifname_str);
+ (*env)->ReleaseStringUTFChars(env, settings, settings_str);
+ return ret;
+}
+
+JNIEXPORT jint JNICALL Java_com_wireguard_android_backend_GoBackend_wgTurnOnDhcp(JNIEnv *env, jclass c, jstring ifname, jstring settings, jobject eventHandler)
+{
+ const char *ifname_str = (*env)->GetStringUTFChars(env, ifname, 0);
+ size_t ifname_len = (*env)->GetStringUTFLength(env, ifname);
+ const char *settings_str = (*env)->GetStringUTFChars(env, settings, 0);
+ size_t settings_len = (*env)->GetStringUTFLength(env, settings);
+ jobject event_handler = (*env)->NewGlobalRef(env, eventHandler);
int ret = wgTurnOnDhcp((struct go_string){
.str = ifname_str,
.n = ifname_len
- }, /* tun_fd,*/ (struct go_string){
+ }, (struct go_string){
.str = settings_str,
.n = settings_len
}, event_handler);
@@ -71,6 +91,11 @@ JNIEXPORT jint JNICALL Java_com_wireguard_android_backend_GoBackend_wgTurnOn(JNI
return ret;
}
+JNIEXPORT void JNICALL Java_com_wireguard_android_backend_GoBackend_wgSetFd(JNIEnv *env, jclass c, jint handle, jint tun_fd)
+{
+ wgSetFd(handle, tun_fd);
+}
+
JNIEXPORT void JNICALL Java_com_wireguard_android_backend_GoBackend_wgTurnOff(JNIEnv *env, jclass c, jint handle)
{
jobject event_handler = wgTurnOff(handle);