diff options
author | Ghanan Gowripalan <ghanan@google.com> | 2021-10-12 19:36:55 -0700 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2021-10-12 19:39:10 -0700 |
commit | 747cb92460bc30983263fcd85562a8586842d824 (patch) | |
tree | 5087778a134e917381947dbc6ac4c441a543ece1 /pkg/tcpip/stack/conntrack.go | |
parent | 049fa8ea9999799cc304fe811ca8028a195be493 (diff) |
Support Twice NAT
This CL allows both SNAT and DNAT targets to be performed on the same
packet.
Fixes #5696.
PiperOrigin-RevId: 402714738
Diffstat (limited to 'pkg/tcpip/stack/conntrack.go')
-rw-r--r-- | pkg/tcpip/stack/conntrack.go | 24 |
1 files changed, 16 insertions, 8 deletions
diff --git a/pkg/tcpip/stack/conntrack.go b/pkg/tcpip/stack/conntrack.go index 48f290187..c9a8e72a3 100644 --- a/pkg/tcpip/stack/conntrack.go +++ b/pkg/tcpip/stack/conntrack.go @@ -409,18 +409,19 @@ func (cn *conn) performNATIfNoop(port uint16, address tcpip.Address, dnat bool) } } -func (cn *conn) handlePacket(pkt *PacketBuffer, hook Hook, r *Route) { - if pkt.NatDone { - return - } - +// handlePacket attempts to handle a packet and perform NAT if the connection +// has had NAT performed on it. +// +// Returns true if the packet can skip the NAT table. +func (cn *conn) handlePacket(pkt *PacketBuffer, hook Hook, r *Route) bool { transportHeader, ok := getTransportHeader(pkt) if !ok { - return + return false } fullChecksum := false updatePseudoHeader := false + natDone := &pkt.SNATDone dnat := false switch hook { case Prerouting: @@ -429,11 +430,13 @@ func (cn *conn) handlePacket(pkt *PacketBuffer, hook Hook, r *Route) { fullChecksum = true updatePseudoHeader = true + natDone = &pkt.DNATDone dnat = true case Input: case Forward: panic("should not handle packet in the forwarding hook") case Output: + natDone = &pkt.DNATDone dnat = true fallthrough case Postrouting: @@ -447,6 +450,10 @@ func (cn *conn) handlePacket(pkt *PacketBuffer, hook Hook, r *Route) { panic(fmt.Sprintf("unrecognized hook = %d", hook)) } + if *natDone { + panic(fmt.Sprintf("packet already had NAT(dnat=%t) performed at hook=%s; pkt=%#v", dnat, hook, pkt)) + } + // TODO(gvisor.dev/issue/5748): TCP checksums on inbound packets should be // validated if checksum offloading is off. It may require IP defrag if the // packets are fragmented. @@ -490,7 +497,7 @@ func (cn *conn) handlePacket(pkt *PacketBuffer, hook Hook, r *Route) { return tuple.id(), true }() if !performManip { - return + return false } newPort := tid.dstPort @@ -510,7 +517,8 @@ func (cn *conn) handlePacket(pkt *PacketBuffer, hook Hook, r *Route) { newAddr, ) - pkt.NatDone = true + *natDone = true + return true } // bucket gets the conntrack bucket for a tupleID. |