diff options
author | Mikael Magnusson <mikma@users.sourceforge.net> | 2021-03-15 13:34:33 +0000 |
---|---|---|
committer | Mikael Magnusson <mikma@users.sourceforge.net> | 2023-02-07 22:42:33 +0100 |
commit | 3058775eb43b3c69a42939f52e493cca804f2108 (patch) | |
tree | 06ef0a431203f5528851dd5e2c6909b3e28fe527 /tunnel/tools | |
parent | 2a4e9460fee09ec2c800b26752fd23b706d6fdad (diff) |
WIP: netstack: implement dhcp and ipvlan
Diffstat (limited to 'tunnel/tools')
-rw-r--r-- | tunnel/tools/libwg-go/api-android.go | 173 | ||||
-rw-r--r-- | tunnel/tools/libwg-go/go.mod | 2 | ||||
-rw-r--r-- | tunnel/tools/libwg-go/jni.c | 5 |
3 files changed, 178 insertions, 2 deletions
diff --git a/tunnel/tools/libwg-go/api-android.go b/tunnel/tools/libwg-go/api-android.go index db056f67..2fb6e40f 100644 --- a/tunnel/tools/libwg-go/api-android.go +++ b/tunnel/tools/libwg-go/api-android.go @@ -11,7 +11,9 @@ package main import "C" import ( + "context" "fmt" + "log" "math" "net" "os" @@ -26,6 +28,15 @@ import ( "golang.zx2c4.com/wireguard/device" "golang.zx2c4.com/wireguard/ipc" "golang.zx2c4.com/wireguard/tun" + "golang.zx2c4.com/wireguard/tun/netstack" + "golang.zx2c4.com/wireguard/tun/netstack/ipvlan" + + "gvisor.dev/gvisor/pkg/tcpip" + "gvisor.dev/gvisor/pkg/tcpip/network/ipv4" + "gvisor.dev/gvisor/pkg/tcpip/network/ipv6" + "gvisor.dev/gvisor/pkg/tcpip/stack" + "gvisor.dev/gvisor/pkg/tcpip/transport/tcp" + "gvisor.dev/gvisor/pkg/tcpip/transport/udp" ) type AndroidLogger struct { @@ -50,6 +61,8 @@ type TunnelHandle struct { device *device.Device uapi net.Listener eventHandler unsafe.Pointer + cancel context.CancelFunc + master *ipvlan.IPVLANMaster } var tunnelHandles map[int32]TunnelHandle @@ -152,6 +165,166 @@ func wgTurnOn(interfaceName string, tunFd int32, settings string, eventHandler u return i } +func createNetTUNWithStack(stack *stack.Stack, nicID tcpip.NICID, localAddresses []net.IP, dnsServers []net.IP, mtu int) (tun.Device, *netstack.Net, *ipvlan.IPVLANMaster, error) { + dev, ep, err := netstack.NewNetTUN(stack, mtu) + if err != nil { + return nil, nil, nil, err + } + + master := ipvlan.NewIPVLANMaster(ep) + + addrs := make([]tcpip.Address, 0, len(localAddresses)) + for _, addr := range localAddresses { + addrs = append(addrs, tcpip.Address(addr)) + } + ipvlanEP := master.NewIPVLAN(addrs) + + tcpipErr := stack.CreateNIC(nicID, ipvlanEP) + if tcpipErr != nil { + return nil, nil, nil, fmt.Errorf("CreateNIC: %v", tcpipErr) + } + + tnet, err := netstack.NewNetAdapter(stack, nicID, localAddresses, dnsServers) + if err != nil { + return nil, nil, nil, err + } + + return dev, tnet, master, nil +} + +//export wgTurnOnDhcp +func wgTurnOnDhcp(interfaceName 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, + 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) + + // FIXME IP address + ipStr := "fe80::101" + // FIXME name + name := "wg0" + var tundev tun.Device + var tnet *netstack.Net + tundev, tnet, master, err := createNetTUNWithStack( + stack, + 1, + []net.IP{net.ParseIP(ipStr)}, + // []net.IP{net.ParseIP("fe80::1")}, + []net.IP{net.ParseIP("fe80::1")}, + 1420) + if err != nil { + log.Panic(err) + } + + logger.Verbosef("Attaching to netstack interface") + device := device.NewDevice(tundev, conn.NewStdNetBind(), logger) + + err = device.IpcSet(settings) + if err != nil { + logger.Errorf("IpcSet: %v", err) + return -1 + } + device.DisableSomeRoamingForBrokenMobileSemantics() + + var uapi net.Listener + + uapiFile, err := ipc.UAPIOpen(name) + if err != nil { + logger.Errorf("UAPIOpen: %v", err) + } else { + uapi, err = ipc.UAPIListen(name, uapiFile) + if err != nil { + uapiFile.Close() + logger.Errorf("UAPIListen: %v", err) + } else { + go func() { + for { + conn, err := uapi.Accept() + if err != nil { + return + } + go device.IpcHandle(conn) + } + }() + } + } + + err = device.Up() + if err != nil { + logger.Errorf("Unable to bring up device: %v", err) + uapiFile.Close() + device.Close() + return -1 + } + logger.Verbosef("Device started") + + var i int32 + for i = 0; i < math.MaxInt32; i++ { + if _, exists := tunnelHandles[i]; !exists { + break + } + } + if i == math.MaxInt32 { + logger.Errorf("Unable to find empty handle") + uapiFile.Close() + device.Close() + return -1 + } + ctx, cancel := context.WithCancel(context.Background()) + + tunnelHandles[i] = TunnelHandle{device: device, uapi: uapi, eventHandler: eventHandler, cancel: cancel, master: master} + + go func(ctx context.Context) { + logger.Verbosef("Start dhcp client") + src, err := net.ResolveUDPAddr("udp6", fmt.Sprintf("[%s%%1]:546", ipStr)) + if err != nil { + logger.Errorf("ResolveUDPAddr: %v", err) + return + } + + var dst *net.UDPAddr + dst = nil + + conn, err := tnet.DialUDP(src, dst) + if err != nil { + logger.Errorf("DialUDP: %v", err) + return + } + + logger.Verbosef("Conn: %v %v %v", src, dst, conn) + hwAddr := []byte(" 101") + addrs, err := netstack.RunDhcp(ctx, conn, hwAddr) + + if err != nil { + logger.Errorf("DHCP: %v", err) + return + } + + logger.Verbosef("DHCP finished") + for _, addr := range addrs { + logger.Verbosef("Address: %v", addr) + } + + // TODO move to wgSetTunFd + // tunEP := newTun(stack, 2, "tun0") + // master.SetIntEP(tunEP) + }(ctx) + + logger.Verbosef("Before wgOnEvent %v", eventHandler) + C.wgOnEvent(tunnelHandles[i].eventHandler, C.CString("FOOBAR")) + C.wgOnEvent(tunnelHandles[i].eventHandler, C.CString("Called wgTurnOn")) + logger.Verbosef("After wgOnEvent") + return i +} + //export wgTurnOff func wgTurnOff(tunnelHandle int32) unsafe.Pointer { handle, ok := tunnelHandles[tunnelHandle] diff --git a/tunnel/tools/libwg-go/go.mod b/tunnel/tools/libwg-go/go.mod index e64d2fb1..6fdb520c 100644 --- a/tunnel/tools/libwg-go/go.mod +++ b/tunnel/tools/libwg-go/go.mod @@ -12,3 +12,5 @@ require ( golang.org/x/net v0.0.0-20220516155154-20f960328961 // indirect 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 diff --git a/tunnel/tools/libwg-go/jni.c b/tunnel/tools/libwg-go/jni.c index 52bec1e8..de6a1e85 100644 --- a/tunnel/tools/libwg-go/jni.c +++ b/tunnel/tools/libwg-go/jni.c @@ -13,6 +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 void *wgTurnOff(int handle); extern int wgGetSocketV4(int handle); extern int wgGetSocketV6(int handle); @@ -58,10 +59,10 @@ 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){ + int ret = wgTurnOnDhcp((struct go_string){ .str = ifname_str, .n = ifname_len - }, tun_fd, (struct go_string){ + }, /* tun_fd,*/ (struct go_string){ .str = settings_str, .n = settings_len }, event_handler); |