wgengine/tstun/faketun: it's a null tunnel, not a loopback.
At some point faketun got implemented as a loopback (put a packet in from wireguard, the same packet goes back to wireguard) which is not useful. It's supposed to be an interface that just sinks all packets, and then wgengine adds *only* and ICMP Echo responder as a layer on top. This caused extremely odd bugs on darwin, where the special case that reinjects packets from local->local was filling the loopback channel and creating an infinite loop (which became jammed since the reader and writer were in the same goroutine). Signed-off-by: Avery Pennarun <apenwarr@tailscale.com>
This commit is contained in:
@@ -12,7 +12,6 @@ import (
|
||||
)
|
||||
|
||||
type fakeTUN struct {
|
||||
datachan chan []byte
|
||||
evchan chan tun.Event
|
||||
closechan chan struct{}
|
||||
}
|
||||
@@ -22,7 +21,6 @@ type fakeTUN struct {
|
||||
// It primarily exists for testing.
|
||||
func NewFakeTUN() tun.Device {
|
||||
return &fakeTUN{
|
||||
datachan: make(chan []byte),
|
||||
evchan: make(chan tun.Event),
|
||||
closechan: make(chan struct{}),
|
||||
}
|
||||
@@ -39,22 +37,17 @@ func (t *fakeTUN) Close() error {
|
||||
}
|
||||
|
||||
func (t *fakeTUN) Read(out []byte, offset int) (int, error) {
|
||||
select {
|
||||
case <-t.closechan:
|
||||
return 0, io.EOF
|
||||
case b := <-t.datachan:
|
||||
copy(out[offset:offset+len(b)], b)
|
||||
return len(b), nil
|
||||
}
|
||||
<-t.closechan
|
||||
return 0, io.EOF
|
||||
}
|
||||
|
||||
func (t *fakeTUN) Write(b []byte, n int) (int, error) {
|
||||
select {
|
||||
case <-t.closechan:
|
||||
return 0, ErrClosed
|
||||
case t.datachan <- b[n:]:
|
||||
return len(b), nil
|
||||
default:
|
||||
}
|
||||
return len(b), nil
|
||||
}
|
||||
|
||||
func (t *fakeTUN) Flush() error { return nil }
|
||||
|
||||
Reference in New Issue
Block a user