net/packet: add NAT support for DCCP and GRE

Updates tailscale/corp#8020

Signed-off-by: Maisem Ali <maisem@tailscale.com>
pull/7964/head
Maisem Ali 1 year ago committed by Maisem Ali
parent ce11c82d51
commit f58751eb2b

@ -558,19 +558,42 @@ func withPort(ap netip.AddrPort, port uint16) netip.AddrPort {
// Currently (2023-03-01) only TCP/UDP/ICMP over IPv4 is supported.
// p is modified in place.
// If p.IPProto is unknown, only the IP header checksum is updated.
// TODO(maisem): more protocols (sctp, gre, dccp)
func updateV4PacketChecksums(p *Parsed, old, new netip.Addr) {
if len(p.Buffer()) < 12 {
// Not enough space for an IPv4 header.
return
}
o4, n4 := old.As4(), new.As4()
updateV4Checksum(p.Buffer()[10:12], o4[:], n4[:]) // header
// First update the checksum in the IP header.
updateV4Checksum(p.Buffer()[10:12], o4[:], n4[:])
// Now update the transport layer checksums, where applicable.
tr := p.Transport()
switch p.IPProto {
case ipproto.UDP:
updateV4Checksum(p.Transport()[6:8], o4[:], n4[:])
case ipproto.UDP, ipproto.DCCP:
if len(tr) < 8 {
// Not enough space for a UDP header.
return
}
updateV4Checksum(tr[6:8], o4[:], n4[:])
case ipproto.TCP:
updateV4Checksum(p.Transport()[16:18], o4[:], n4[:])
case ipproto.ICMPv4:
// Nothing to do.
if len(tr) < 18 {
// Not enough space for a TCP header.
return
}
updateV4Checksum(tr[16:18], o4[:], n4[:])
case ipproto.GRE:
if len(tr) < 6 {
// Not enough space for a GRE header.
return
}
if tr[0] == 1 { // checksum present
updateV4Checksum(tr[4:6], o4[:], n4[:])
}
case ipproto.SCTP, ipproto.ICMPv4:
// No transport layer update required.
}
// TODO(maisem): more protocols (sctp, gre, dccp)
}
// updateV4Checksum calculates and updates the checksum in the packet buffer for

@ -72,6 +72,19 @@ func TestHeaderChecksums(t *testing.T) {
0x45, 0x00, 0x00, 0x74, 0xe2, 0x85, 0x00, 0x00, 0x40, 0x11, 0x96, 0xb5, 0x64, 0x64, 0x64, 0x64, 0x64, 0x42, 0xd4, 0x33, 0x00, 0x35, 0xec, 0x55, 0x00, 0x60, 0xd9, 0x19, 0xed, 0xfd, 0x81, 0x80, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x34, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01, 0xc0, 0x0c, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, 0x01, 0x1e, 0x00, 0x0c, 0x07, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x01, 0x6c, 0xc0, 0x15, 0xc0, 0x31, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x1e, 0x00, 0x04, 0x8e, 0xfa, 0xbd, 0xce, 0x00, 0x00, 0x29, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
},
},
{
name: "DCCP",
packet: []byte{
0x45, 0x00, 0x00, 0x28, 0x15, 0x06, 0x40, 0x00, 0x40, 0x21, 0x5f, 0x2f, 0xc0, 0xa8, 0x01, 0x1f, 0xc9, 0x0b, 0x3b, 0xad, 0x80, 0x04, 0x13, 0x89, 0x05, 0x00, 0x08, 0xdb, 0x01, 0x00, 0x00, 0x04, 0x29, 0x01, 0x6d, 0xdc, 0x00, 0x00, 0x00, 0x00,
},
},
{
name: "SCTP",
packet: []byte{
0x45, 0x00, 0x00, 0x30, 0x09, 0xd9, 0x40, 0x00, 0xff, 0x84, 0x50, 0xe2, 0x0a, 0x1c, 0x06, 0x2c, 0x0a, 0x1c, 0x06, 0x2b, 0x0b, 0x80, 0x40, 0x00, 0x21, 0x44, 0x15, 0x23, 0x2b, 0xf2, 0x02, 0x4e, 0x03, 0x00, 0x00, 0x10, 0x28, 0x02, 0x43, 0x45, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
},
},
// TODO(maisem): add test for GRE.
}
var p Parsed
for _, tt := range tests {

@ -25,6 +25,8 @@ const (
ICMPv6 Proto = 0x3a
TCP Proto = 0x06
UDP Proto = 0x11
DCCP Proto = 0x21
GRE Proto = 0x2f
SCTP Proto = 0x84
// TSMP is the Tailscale Message Protocol (our ICMP-ish
@ -67,6 +69,10 @@ func (p Proto) String() string {
return "SCTP"
case TSMP:
return "TSMP"
case GRE:
return "GRE"
case DCCP:
return "DCCP"
default:
return fmt.Sprintf("IPProto-%d", int(p))
}

Loading…
Cancel
Save