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) {