summaryrefslogtreecommitdiffhomepage
path: root/pkg/tcpip/link
diff options
context:
space:
mode:
authorFabricio Voznika <fvoznika@google.com>2018-08-08 22:02:09 -0700
committerShentubot <shentubot@google.com>2018-08-08 22:03:35 -0700
commitea1e39a314d3a248d8b682a9f63e686530597d61 (patch)
tree160e0fd447cb80d06324311ebb4d14f2e5f64824 /pkg/tcpip/link
parentdbbe9ec91541dba387f8044cbf73fd29f604f902 (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: 207995083 Change-Id: I17adc2a04df48bfea711011a5df206326a1fb8ef
Diffstat (limited to 'pkg/tcpip/link')
-rw-r--r--pkg/tcpip/link/fdbased/endpoint.go52
1 files changed, 32 insertions, 20 deletions
diff --git a/pkg/tcpip/link/fdbased/endpoint.go b/pkg/tcpip/link/fdbased/endpoint.go
index 4e20cfbf8..152d8f0b2 100644
--- a/pkg/tcpip/link/fdbased/endpoint.go
+++ b/pkg/tcpip/link/fdbased/endpoint.go
@@ -55,10 +55,15 @@ 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
+
+ // handleLocal indicates whether packets destined to itself should be
+ // handled by the netstack internally (true) or be forwarded to the FD
+ // endpoint (false).
+ handleLocal bool
}
// Options specify the details about the fd-based endpoint to be created.
@@ -71,6 +76,7 @@ type Options struct {
Address tcpip.LinkAddress
SaveRestore bool
DisconnectOk bool
+ HandleLocal bool
}
// New creates a new fd-based endpoint.
@@ -100,14 +106,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)),
+ handleLocal: opts.HandleLocal,
}
vv := buffer.NewVectorisedView(0, e.views)
e.vv = &vv
@@ -117,16 +124,16 @@ 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
+ e.dispatcher = dispatcher
// Link endpoints are not savable. When transportation endpoints are
// saved, they stop sending outgoing packets and all incoming packets
// are rejected.
- go e.dispatchLoop(dispatcher) // S/R-SAFE: See above.
+ go e.dispatchLoop() // S/R-SAFE: See above.
}
// 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
@@ -153,6 +160,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.handleLocal && 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))
@@ -165,7 +178,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)
@@ -198,7 +210,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)
@@ -234,7 +246,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++ {
@@ -246,10 +258,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)