tun: disqualify tcp4 packets w/IP options from coalescing
IP options were not being compared prior to coalescing. They are not commonly used. Disqualification due to nonzero options is in line with the kernel. Reviewed-by: Denton Gentry <dgentry@tailscale.com> Signed-off-by: Jordan Whited <jordan@tailscale.com> Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
parent
6f895be10d
commit
aad7fca9c5
@ -397,9 +397,6 @@ func tcpGRO(bufs [][]byte, offset int, pktI int, table *tcpGROTable, isV6 bool)
|
|||||||
if totalLen != len(pkt) {
|
if totalLen != len(pkt) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if iphLen < 20 || iphLen > 60 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if len(pkt) < iphLen {
|
if len(pkt) < iphLen {
|
||||||
return false
|
return false
|
||||||
@ -474,13 +471,16 @@ func tcpGRO(bufs [][]byte, offset int, pktI int, table *tcpGROTable, isV6 bool)
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func isTCP4(b []byte) bool {
|
func isTCP4NoIPOptions(b []byte) bool {
|
||||||
if len(b) < 40 {
|
if len(b) < 40 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if b[0]>>4 != 4 {
|
if b[0]>>4 != 4 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if b[0]&0x0F != 5 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
if b[9] != unix.IPPROTO_TCP {
|
if b[9] != unix.IPPROTO_TCP {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -511,7 +511,7 @@ func handleGRO(bufs [][]byte, offset int, tcp4Table, tcp6Table *tcpGROTable, toW
|
|||||||
}
|
}
|
||||||
var coalesced bool
|
var coalesced bool
|
||||||
switch {
|
switch {
|
||||||
case isTCP4(bufs[i][offset:]):
|
case isTCP4NoIPOptions(bufs[i][offset:]): // ipv4 packets w/IP options do not coalesce
|
||||||
coalesced = tcpGRO(bufs, offset, i, tcp4Table, false)
|
coalesced = tcpGRO(bufs, offset, i, tcp4Table, false)
|
||||||
case isTCP6NoEH(bufs[i][offset:]): // ipv6 packets w/extension headers do not coalesce
|
case isTCP6NoEH(bufs[i][offset:]): // ipv6 packets w/extension headers do not coalesce
|
||||||
coalesced = tcpGRO(bufs, offset, i, tcp6Table, true)
|
coalesced = tcpGRO(bufs, offset, i, tcp6Table, true)
|
||||||
|
@ -271,3 +271,53 @@ func Test_handleGRO(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_isTCP4NoIPOptions(t *testing.T) {
|
||||||
|
valid := tcp4Packet(ip4PortA, ip4PortB, header.TCPFlagAck, 100, 1)[virtioNetHdrLen:]
|
||||||
|
invalidLen := valid[:39]
|
||||||
|
invalidHeaderLen := make([]byte, len(valid))
|
||||||
|
copy(invalidHeaderLen, valid)
|
||||||
|
invalidHeaderLen[0] = 0x46
|
||||||
|
invalidProtocol := make([]byte, len(valid))
|
||||||
|
copy(invalidProtocol, valid)
|
||||||
|
invalidProtocol[9] = unix.IPPROTO_TCP + 1
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
b []byte
|
||||||
|
want bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"valid",
|
||||||
|
valid,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"invalid length",
|
||||||
|
invalidLen,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"invalid version",
|
||||||
|
[]byte{0x00},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"invalid header len",
|
||||||
|
invalidHeaderLen,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"invalid protocol",
|
||||||
|
invalidProtocol,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if got := isTCP4NoIPOptions(tt.b); got != tt.want {
|
||||||
|
t.Errorf("isTCP4NoIPOptions() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user