netstack: support snat target rev 1 for both IPv4 and IPv6

We had IPv6 support, and since they two are almost identical, they can share
code. The only difference is the length of the address.

PiperOrigin-RevId: 581447406
This commit is contained in:
Kevin Krakauer
2023-11-10 21:27:12 -08:00
committed by gVisor bot
parent 2f4419a668
commit cb86d3ea02
2 changed files with 23 additions and 11 deletions
+19 -10
View File
@@ -15,6 +15,8 @@
package netfilter
import (
"fmt"
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/marshal"
"gvisor.dev/gvisor/pkg/syserr"
@@ -117,11 +119,11 @@ func (*snatTargetMakerV4) unmarshal(buf []byte, filter stack.IPHeaderFilter) (ta
return &target, nil
}
type snatTargetMakerV6 struct {
type snatTargetMakerR1 struct {
NetworkProtocol tcpip.NetworkProtocolNumber
}
func (st *snatTargetMakerV6) id() targetID {
func (st *snatTargetMakerR1) id() targetID {
return targetID{
name: SNATTargetName,
networkProtocol: st.NetworkProtocol,
@@ -129,7 +131,7 @@ func (st *snatTargetMakerV6) id() targetID {
}
}
func (*snatTargetMakerV6) marshal(target target) []byte {
func (*snatTargetMakerR1) marshal(target target) []byte {
st := target.(*snatTarget)
nt := linux.XTNATTargetV1{
Target: linux.XTEntryTarget{
@@ -148,14 +150,14 @@ func (*snatTargetMakerV6) marshal(target target) []byte {
return marshal.Marshal(&nt)
}
func (*snatTargetMakerV6) unmarshal(buf []byte, filter stack.IPHeaderFilter) (target, *syserr.Error) {
func (st *snatTargetMakerR1) unmarshal(buf []byte, filter stack.IPHeaderFilter) (target, *syserr.Error) {
if size := linux.SizeOfXTNATTargetV1; len(buf) < size {
nflog("snatTargetMakerV6: buf has insufficient size (%d) for SNAT V6 target (%d)", len(buf), size)
nflog("snatTargetMakerR1: buf has insufficient size (%d) for SNAT target (%d)", len(buf), size)
return nil, syserr.ErrInvalidArgument
}
if p := filter.Protocol; p != header.TCPProtocolNumber && p != header.UDPProtocolNumber {
nflog("snatTargetMakerV6: bad proto %d", p)
nflog("snatTargetMakerR1: bad proto %d", p)
return nil, syserr.ErrInvalidArgument
}
@@ -164,27 +166,34 @@ func (*snatTargetMakerV6) unmarshal(buf []byte, filter stack.IPHeaderFilter) (ta
// TODO(gvisor.dev/issue/5697): Support port or address ranges.
if natRange.MinAddr != natRange.MaxAddr {
nflog("snatTargetMakerV6: MinAddr and MaxAddr are different")
nflog("snatTargetMakerR1: MinAddr and MaxAddr are different")
return nil, syserr.ErrInvalidArgument
}
if natRange.MinProto != natRange.MaxProto {
nflog("snatTargetMakerV6: MinProto and MaxProto are different")
nflog("snatTargetMakerR1: MinProto and MaxProto are different")
return nil, syserr.ErrInvalidArgument
}
// TODO(gvisor.dev/issue/5698): Support other NF_NAT_RANGE flags.
if natRange.Flags != linux.NF_NAT_RANGE_MAP_IPS|linux.NF_NAT_RANGE_PROTO_SPECIFIED {
nflog("snatTargetMakerV6: invalid range flags %d", natRange.Flags)
nflog("snatTargetMakerR1: invalid range flags %d", natRange.Flags)
return nil, syserr.ErrInvalidArgument
}
target := snatTarget{
SNATTarget: stack.SNATTarget{
NetworkProtocol: filter.NetworkProtocol(),
Addr: tcpip.AddrFrom16(natRange.MinAddr),
Port: ntohs(natRange.MinProto),
},
}
switch st.NetworkProtocol {
case header.IPv4ProtocolNumber:
target.SNATTarget.Addr = tcpip.AddrFrom4Slice(natRange.MinAddr[:4])
case header.IPv6ProtocolNumber:
target.SNATTarget.Addr = tcpip.AddrFrom16(natRange.MinAddr)
default:
panic(fmt.Sprintf("invalid protocol number: %d", st.NetworkProtocol))
}
return &target, nil
}
+4 -1
View File
@@ -64,7 +64,10 @@ func init() {
registerTargetMaker(&snatTargetMakerV4{
NetworkProtocol: header.IPv4ProtocolNumber,
})
registerTargetMaker(&snatTargetMakerV6{
registerTargetMaker(&snatTargetMakerR1{
NetworkProtocol: header.IPv4ProtocolNumber,
})
registerTargetMaker(&snatTargetMakerR1{
NetworkProtocol: header.IPv6ProtocolNumber,
})
}