From 54dbe2471f8ed67f49e8b5e5c92f6f4eb4a5a912 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Fri, 9 Apr 2021 17:21:35 -0600 Subject: [PATCH] conn: reconstruct v4 vs v6 receive function based on symtab This is kind of gross but it's better than the alternatives. Signed-off-by: Jason A. Donenfeld --- conn/bind_linux.go | 8 +++---- conn/bind_std.go | 15 +++++++++---- conn/conn.go | 56 +++++++++++++++++++++++++++++++++++++++++----- device/receive.go | 5 +++-- 4 files changed, 69 insertions(+), 15 deletions(-) diff --git a/conn/bind_linux.go b/conn/bind_linux.go index 9eec384..c10d8b6 100644 --- a/conn/bind_linux.go +++ b/conn/bind_linux.go @@ -148,11 +148,11 @@ again: var fns []ReceiveFunc if sock4 != -1 { - fns = append(fns, makeReceiveIPv4(sock4)) + fns = append(fns, bind.makeReceiveIPv4(sock4)) bind.sock4 = sock4 } if sock6 != -1 { - fns = append(fns, makeReceiveIPv6(sock6)) + fns = append(fns, bind.makeReceiveIPv6(sock6)) bind.sock6 = sock6 } if len(fns) == 0 { @@ -224,7 +224,7 @@ func (bind *LinuxSocketBind) Close() error { return err2 } -func makeReceiveIPv6(sock int) ReceiveFunc { +func (*LinuxSocketBind) makeReceiveIPv6(sock int) ReceiveFunc { return func(buff []byte) (int, Endpoint, error) { var end LinuxSocketEndpoint n, err := receive6(sock, buff, &end) @@ -232,7 +232,7 @@ func makeReceiveIPv6(sock int) ReceiveFunc { } } -func makeReceiveIPv4(sock int) ReceiveFunc { +func (*LinuxSocketBind) makeReceiveIPv4(sock int) ReceiveFunc { return func(buff []byte) (int, Endpoint, error) { var end LinuxSocketEndpoint n, err := receive4(sock, buff, &end) diff --git a/conn/bind_std.go b/conn/bind_std.go index 5261779..cb85cfd 100644 --- a/conn/bind_std.go +++ b/conn/bind_std.go @@ -118,11 +118,11 @@ again: } var fns []ReceiveFunc if ipv4 != nil { - fns = append(fns, makeReceiveFunc(ipv4, true)) + fns = append(fns, bind.makeReceiveIPv4(ipv4)) bind.ipv4 = ipv4 } if ipv6 != nil { - fns = append(fns, makeReceiveFunc(ipv6, false)) + fns = append(fns, bind.makeReceiveIPv6(ipv6)) bind.ipv6 = ipv6 } if len(fns) == 0 { @@ -152,16 +152,23 @@ func (bind *StdNetBind) Close() error { return err2 } -func makeReceiveFunc(conn *net.UDPConn, isIPv4 bool) ReceiveFunc { +func (*StdNetBind) makeReceiveIPv4(conn *net.UDPConn) ReceiveFunc { return func(buff []byte) (int, Endpoint, error) { n, endpoint, err := conn.ReadFromUDP(buff) - if isIPv4 && endpoint != nil { + if endpoint != nil { endpoint.IP = endpoint.IP.To4() } return n, (*StdNetEndpoint)(endpoint), err } } +func (*StdNetBind) makeReceiveIPv6(conn *net.UDPConn) ReceiveFunc { + return func(buff []byte) (int, Endpoint, error) { + n, endpoint, err := conn.ReadFromUDP(buff) + return n, (*StdNetEndpoint)(endpoint), err + } +} + func (bind *StdNetBind) Send(buff []byte, endpoint Endpoint) error { var err error nend, ok := endpoint.(*StdNetEndpoint) diff --git a/conn/conn.go b/conn/conn.go index 3c7fcd0..9cce9ad 100644 --- a/conn/conn.go +++ b/conn/conn.go @@ -8,7 +8,10 @@ package conn import ( "errors" + "fmt" "net" + "reflect" + "runtime" "strings" ) @@ -69,6 +72,54 @@ type Endpoint interface { SrcIP() net.IP } +var ( + ErrBindAlreadyOpen = errors.New("bind is already open") + ErrWrongEndpointType = errors.New("endpoint type does not correspond with bind type") +) + +func (fn ReceiveFunc) PrettyName() string { + name := runtime.FuncForPC(reflect.ValueOf(fn).Pointer()).Name() + // 0. cheese/taco.beansIPv6.func12.func21218-fm + name = strings.TrimSuffix(name, "-fm") + // 1. cheese/taco.beansIPv6.func12.func21218 + if idx := strings.LastIndexByte(name, '/'); idx != -1 { + name = name[idx+1:] + // 2. taco.beansIPv6.func12.func21218 + } + for { + var idx int + for idx = len(name) - 1; idx >= 0; idx-- { + if name[idx] < '0' || name[idx] > '9' { + break + } + } + if idx == len(name)-1 { + break + } + const dotFunc = ".func" + if !strings.HasSuffix(name[:idx+1], dotFunc) { + break + } + name = name[:idx+1-len(dotFunc)] + // 3. taco.beansIPv6.func12 + // 4. taco.beansIPv6 + } + if idx := strings.LastIndexByte(name, '.'); idx != -1 { + name = name[idx+1:] + // 5. beansIPv6 + } + if name == "" { + return fmt.Sprintf("%p", fn) + } + if strings.HasSuffix(name, "IPv4") { + return "v4" + } + if strings.HasSuffix(name, "IPv6") { + return "v6" + } + return name +} + func parseEndpoint(s string) (*net.UDPAddr, error) { // ensure that the host is an IP address @@ -98,8 +149,3 @@ func parseEndpoint(s string) (*net.UDPAddr, error) { } return addr, err } - -var ( - ErrBindAlreadyOpen = errors.New("bind is already open") - ErrWrongEndpointType = errors.New("endpoint type does not correspond with bind type") -) diff --git a/device/receive.go b/device/receive.go index 3aa4458..9af0e18 100644 --- a/device/receive.go +++ b/device/receive.go @@ -69,14 +69,15 @@ func (peer *Peer) keepKeyFreshReceiving() { * IPv4 and IPv6 (separately) */ func (device *Device) RoutineReceiveIncoming(recv conn.ReceiveFunc) { + recvName := recv.PrettyName() defer func() { - device.log.Verbosef("Routine: receive incoming %p - stopped", recv) + device.log.Verbosef("Routine: receive incoming %s - stopped", recvName) device.queue.decryption.wg.Done() device.queue.handshake.wg.Done() device.net.stopping.Done() }() - device.log.Verbosef("Routine: receive incoming %p - started", recv) + device.log.Verbosef("Routine: receive incoming %s - started", recvName) // receive datagrams until conn is closed