Packet forwarding to enable NAT
This change forwards a packet from one NIC to another NIC if Forwarding
is enabled on the stack.
Change-Id: I845c7bad9d1cff5e99e9b812d00d1b4b7e8f2038
diff --git a/tcpip/stack/nic.go b/tcpip/stack/nic.go
index 07e4f04..1307848 100644
--- a/tcpip/stack/nic.go
+++ b/tcpip/stack/nic.go
@@ -307,8 +307,45 @@
}
if ref == nil {
- atomic.AddUint64(&n.stack.stats.IP.InvalidAddressesReceived, 1)
- return
+ // This NIC doesn't care the packet. Find a NIC that cares about the packet and
+ // forward it to the NIC.
+ // TODO: Should forward the packet even if 'promiscuous' is enabled?
+ if n.stack.Forwarding() {
+ r, err := n.stack.FindRoute(0, "", dst, protocol)
+ if err != nil {
+ // Can't find a NIC.
+ atomic.AddUint64(&n.stack.stats.IP.InvalidAddressesReceived, 1)
+ return
+ }
+ defer r.Release()
+
+ // Found a NIC.
+ n2 := r.ref.nic
+ n2.mu.RLock()
+ ref := n2.endpoints[id]
+ if ref != nil && !ref.tryIncRef() {
+ ref = nil
+ }
+ n2.mu.RUnlock()
+
+ r.LocalLinkAddress = n2.linkEP.LinkAddress()
+ r.RemoteLinkAddress = remoteLinkAddr
+
+ if ref == nil {
+ // n2 doesn't have a destination endpoint.
+ // Send the packet out of n2.
+ if ep, ok := n2.linkEP.(BufferWritingLinkEndpoint); ok {
+ ep.WriteBuffer(&r, vv, protocol)
+ }
+ } else {
+ ref.ep.HandlePacket(&r, vv)
+ ref.decRef()
+ }
+ return
+ } else {
+ atomic.AddUint64(&n.stack.stats.IP.InvalidAddressesReceived, 1)
+ return
+ }
}
r := makeRoute(protocol, dst, src, ref)
diff --git a/tcpip/stack/stack.go b/tcpip/stack/stack.go
index ae74759..0fee5c8 100644
--- a/tcpip/stack/stack.go
+++ b/tcpip/stack/stack.go
@@ -43,6 +43,8 @@
linkAddrCache *linkAddrCache
+ forwarding bool
+
mu sync.RWMutex
nics map[tcpip.NICID]*NIC
@@ -185,6 +187,16 @@
return &s.stats
}
+// SetForwarding enables or disables the packet forwarding between NICs.
+func (s *Stack) SetForwarding(enable bool) {
+ s.forwarding = enable
+}
+
+// Forwarding returns if the packet forwarding between NICs is enabled.
+func (s *Stack) Forwarding() bool {
+ return s.forwarding
+}
+
// SetRouteTable assigns the route table to be used by this stack. It
// specifies which NIC to use for given destination address ranges.
func (s *Stack) SetRouteTable(table []tcpip.Route) {