Skip to content

Commit

Permalink
conn: reconstruct v4 vs v6 receive function based on symtab
Browse files Browse the repository at this point in the history
This is kind of gross but it's better than the alternatives.

Signed-off-by: Jason A. Donenfeld <[email protected]>
  • Loading branch information
zx2c4 committed Apr 12, 2021
1 parent d2fd0c0 commit 58beb0f
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 15 deletions.
8 changes: 4 additions & 4 deletions conn/bind_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -224,15 +224,15 @@ 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)
return n, &end, err
}
}

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)
Expand Down
15 changes: 11 additions & 4 deletions conn/bind_std.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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)
Expand Down
58 changes: 53 additions & 5 deletions conn/conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,12 @@ package conn

import (
"errors"
"fmt"
"net"
"reflect"
"runtime"
"strings"
"unsafe"
)

// A ReceiveFunc receives a single inbound packet from the network.
Expand Down Expand Up @@ -69,6 +73,55 @@ 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 {
ptr := reflect.ValueOf(fn).Pointer()
name := runtime.FuncForPC(ptr).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", unsafe.Pointer(ptr))
}
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

Expand Down Expand Up @@ -98,8 +151,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")
)
5 changes: 3 additions & 2 deletions device/receive.go
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down

0 comments on commit 58beb0f

Please sign in to comment.