diff options
author | Fabricio Voznika <fvoznika@google.com> | 2018-07-03 11:38:08 -0700 |
---|---|---|
committer | Shentubot <shentubot@google.com> | 2018-07-03 11:39:17 -0700 |
commit | 0ef606616732e1daf9d424658c31e5fed8f1ee4a (patch) | |
tree | deb3d6808e14e8f37b61a50a8bec1ebbecc6b2c6 /pkg/tcpip/link/fdbased | |
parent | c1b4c1ffee850aea2880f5f91a1e48e840933c71 (diff) |
Resend packets back to netstack if destined to itself
Add option to redirect packet back to netstack if it's destined to itself.
This fixes the problem where connecting to the local NIC address would
not work, e.g.:
echo bar | nc -l -p 8080 &
echo foo | nc 192.168.0.2 8080
PiperOrigin-RevId: 203157739
Change-Id: I31c9f7c501e3f55007f25e1852c27893a16ac6c4
Diffstat (limited to 'pkg/tcpip/link/fdbased')
-rw-r--r-- | pkg/tcpip/link/fdbased/endpoint.go | 51 |
1 files changed, 31 insertions, 20 deletions
diff --git a/pkg/tcpip/link/fdbased/endpoint.go b/pkg/tcpip/link/fdbased/endpoint.go index 668514454..0c844c05b 100644 --- a/pkg/tcpip/link/fdbased/endpoint.go +++ b/pkg/tcpip/link/fdbased/endpoint.go @@ -45,10 +45,14 @@ type endpoint struct { // its end of the communication pipe. closed func(*tcpip.Error) - vv *buffer.VectorisedView - iovecs []syscall.Iovec - views []buffer.View - attached bool + vv *buffer.VectorisedView + iovecs []syscall.Iovec + views []buffer.View + dispatcher stack.NetworkDispatcher + + // egressLocal indicates whether packets destined to itself should be + // forwarded to the FD endpoint (true) or be sent back to netstack (false). + egressLocal bool } // Options specify the details about the fd-based endpoint to be created. @@ -59,6 +63,7 @@ type Options struct { ChecksumOffload bool ClosedFunc func(*tcpip.Error) Address tcpip.LinkAddress + EgressLocal bool } // New creates a new fd-based endpoint. @@ -80,14 +85,15 @@ func New(opts *Options) tcpip.LinkEndpointID { } e := &endpoint{ - fd: opts.FD, - mtu: opts.MTU, - caps: caps, - closed: opts.ClosedFunc, - addr: opts.Address, - hdrSize: hdrSize, - views: make([]buffer.View, len(BufConfig)), - iovecs: make([]syscall.Iovec, len(BufConfig)), + fd: opts.FD, + mtu: opts.MTU, + caps: caps, + closed: opts.ClosedFunc, + addr: opts.Address, + hdrSize: hdrSize, + views: make([]buffer.View, len(BufConfig)), + iovecs: make([]syscall.Iovec, len(BufConfig)), + egressLocal: opts.EgressLocal, } vv := buffer.NewVectorisedView(0, e.views) e.vv = &vv @@ -97,13 +103,13 @@ func New(opts *Options) tcpip.LinkEndpointID { // Attach launches the goroutine that reads packets from the file descriptor and // dispatches them via the provided dispatcher. func (e *endpoint) Attach(dispatcher stack.NetworkDispatcher) { - e.attached = true - go e.dispatchLoop(dispatcher) // S/R-FIXME + e.dispatcher = dispatcher + go e.dispatchLoop() // S/R-FIXME } // IsAttached implements stack.LinkEndpoint.IsAttached. func (e *endpoint) IsAttached() bool { - return e.attached + return e.dispatcher != nil } // MTU implements stack.LinkEndpoint.MTU. It returns the value initialized @@ -130,6 +136,12 @@ func (e *endpoint) LinkAddress() tcpip.LinkAddress { // WritePacket writes outbound packets to the file descriptor. If it is not // currently writable, the packet is dropped. func (e *endpoint) WritePacket(r *stack.Route, hdr *buffer.Prependable, payload buffer.View, protocol tcpip.NetworkProtocolNumber) *tcpip.Error { + if !e.egressLocal && r.LocalAddress != "" && r.LocalAddress == r.RemoteAddress { + hdrView := hdr.View() + vv := buffer.NewVectorisedView(len(hdrView)+len(payload), []buffer.View{hdrView, payload}) + e.dispatcher.DeliverNetworkPacket(e, r.RemoteLinkAddress, protocol, &vv) + return nil + } if e.hdrSize > 0 { // Add ethernet header if needed. eth := header.Ethernet(hdr.Prepend(header.EthernetMinimumSize)) @@ -142,7 +154,6 @@ func (e *endpoint) WritePacket(r *stack.Route, hdr *buffer.Prependable, payload if len(payload) == 0 { return rawfile.NonBlockingWrite(e.fd, hdr.UsedBytes()) - } return rawfile.NonBlockingWrite2(e.fd, hdr.UsedBytes(), payload) @@ -175,7 +186,7 @@ func (e *endpoint) allocateViews(bufConfig []int) { } // dispatch reads one packet from the file descriptor and dispatches it. -func (e *endpoint) dispatch(d stack.NetworkDispatcher, largeV buffer.View) (bool, *tcpip.Error) { +func (e *endpoint) dispatch(largeV buffer.View) (bool, *tcpip.Error) { e.allocateViews(BufConfig) n, err := rawfile.BlockingReadv(e.fd, e.iovecs) @@ -211,7 +222,7 @@ func (e *endpoint) dispatch(d stack.NetworkDispatcher, largeV buffer.View) (bool e.vv.SetSize(n) e.vv.TrimFront(e.hdrSize) - d.DeliverNetworkPacket(e, addr, p, e.vv) + e.dispatcher.DeliverNetworkPacket(e, addr, p, e.vv) // Prepare e.views for another packet: release used views. for i := 0; i < used; i++ { @@ -223,10 +234,10 @@ func (e *endpoint) dispatch(d stack.NetworkDispatcher, largeV buffer.View) (bool // dispatchLoop reads packets from the file descriptor in a loop and dispatches // them to the network stack. -func (e *endpoint) dispatchLoop(d stack.NetworkDispatcher) *tcpip.Error { +func (e *endpoint) dispatchLoop() *tcpip.Error { v := buffer.NewView(header.MaxIPPacketSize) for { - cont, err := e.dispatch(d, v) + cont, err := e.dispatch(v) if err != nil || !cont { if e.closed != nil { e.closed(err) |