net/packet: s/ParsedPacket/Parsed/ to avoid package stuttering.

Signed-off-by: David Anderson <danderson@tailscale.com>
pull/910/head
David Anderson 4 years ago
parent c48253e63b
commit 093431f5dd

@ -4,9 +4,9 @@
// Package packet contains packet parsing and marshaling utilities. // Package packet contains packet parsing and marshaling utilities.
// //
// ParsedPacket provides allocation-free minimal packet header // Parsed provides allocation-free minimal packet header decoding, for
// decoding, for use in packet filtering. The other types in the // use in packet filtering. The other types in the package are for
// package are for constructing and marshaling packets into []bytes. // constructing and marshaling packets into []bytes.
// //
// To support allocation-free parsing, this package defines IPv4 and // To support allocation-free parsing, this package defines IPv4 and
// IPv6 address types. You should prefer to use netaddr's types, // IPv6 address types. You should prefer to use netaddr's types,

@ -29,10 +29,10 @@ var (
put32 = binary.BigEndian.PutUint32 put32 = binary.BigEndian.PutUint32
) )
// ParsedPacket is a minimal decoding of a packet suitable for use in filters. // Parsed is a minimal decoding of a packet suitable for use in filters.
// //
// In general, it only supports IPv4. The IPv6 parsing is very minimal. // In general, it only supports IPv4. The IPv6 parsing is very minimal.
type ParsedPacket struct { type Parsed struct {
// b is the byte buffer that this decodes. // b is the byte buffer that this decodes.
b []byte b []byte
// subofs is the offset of IP subprotocol. // subofs is the offset of IP subprotocol.
@ -55,7 +55,7 @@ type ParsedPacket struct {
// NextHeader // NextHeader
type NextHeader uint8 type NextHeader uint8
func (p *ParsedPacket) String() string { func (p *Parsed) String() string {
if p.IPVersion == 6 { if p.IPVersion == 6 {
return fmt.Sprintf("IPv6{Proto=%d}", p.IPProto) return fmt.Sprintf("IPv6{Proto=%d}", p.IPProto)
} }
@ -108,7 +108,7 @@ func ipChecksum(b []byte) uint16 {
// It performs extremely simple packet decoding for basic IPv4 packet types. // It performs extremely simple packet decoding for basic IPv4 packet types.
// It extracts only the subprotocol id, IP addresses, and (if any) ports, // It extracts only the subprotocol id, IP addresses, and (if any) ports,
// and shouldn't need any memory allocation. // and shouldn't need any memory allocation.
func (q *ParsedPacket) Decode(b []byte) { func (q *Parsed) Decode(b []byte) {
q.b = b q.b = b
if len(b) < ipHeaderLength { if len(b) < ipHeaderLength {
@ -224,7 +224,7 @@ func (q *ParsedPacket) Decode(b []byte) {
} }
} }
func (q *ParsedPacket) IPHeader() IP4Header { func (q *Parsed) IPHeader() IP4Header {
ipid := get16(q.b[4:6]) ipid := get16(q.b[4:6])
return IP4Header{ return IP4Header{
IPID: ipid, IPID: ipid,
@ -234,7 +234,7 @@ func (q *ParsedPacket) IPHeader() IP4Header {
} }
} }
func (q *ParsedPacket) ICMPHeader() ICMP4Header { func (q *Parsed) ICMPHeader() ICMP4Header {
return ICMP4Header{ return ICMP4Header{
IP4Header: q.IPHeader(), IP4Header: q.IPHeader(),
Type: ICMP4Type(q.b[q.subofs+0]), Type: ICMP4Type(q.b[q.subofs+0]),
@ -242,7 +242,7 @@ func (q *ParsedPacket) ICMPHeader() ICMP4Header {
} }
} }
func (q *ParsedPacket) UDPHeader() UDP4Header { func (q *Parsed) UDPHeader() UDP4Header {
return UDP4Header{ return UDP4Header{
IP4Header: q.IPHeader(), IP4Header: q.IPHeader(),
SrcPort: q.SrcPort, SrcPort: q.SrcPort,
@ -252,37 +252,37 @@ func (q *ParsedPacket) UDPHeader() UDP4Header {
// Buffer returns the entire packet buffer. // Buffer returns the entire packet buffer.
// This is a read-only view; that is, q retains the ownership of the buffer. // This is a read-only view; that is, q retains the ownership of the buffer.
func (q *ParsedPacket) Buffer() []byte { func (q *Parsed) Buffer() []byte {
return q.b return q.b
} }
// Sub returns the IP subprotocol section. // Sub returns the IP subprotocol section.
// This is a read-only view; that is, q retains the ownership of the buffer. // This is a read-only view; that is, q retains the ownership of the buffer.
func (q *ParsedPacket) Sub(begin, n int) []byte { func (q *Parsed) Sub(begin, n int) []byte {
return q.b[q.subofs+begin : q.subofs+begin+n] return q.b[q.subofs+begin : q.subofs+begin+n]
} }
// Payload returns the payload of the IP subprotocol section. // Payload returns the payload of the IP subprotocol section.
// This is a read-only view; that is, q retains the ownership of the buffer. // This is a read-only view; that is, q retains the ownership of the buffer.
func (q *ParsedPacket) Payload() []byte { func (q *Parsed) Payload() []byte {
return q.b[q.dataofs:q.length] return q.b[q.dataofs:q.length]
} }
// Trim trims the buffer to its IPv4 length. // Trim trims the buffer to its IPv4 length.
// Sometimes packets arrive from an interface with extra bytes on the end. // Sometimes packets arrive from an interface with extra bytes on the end.
// This removes them. // This removes them.
func (q *ParsedPacket) Trim() []byte { func (q *Parsed) Trim() []byte {
return q.b[:q.length] return q.b[:q.length]
} }
// IsTCPSyn reports whether q is a TCP SYN packet // IsTCPSyn reports whether q is a TCP SYN packet
// (i.e. the first packet in a new connection). // (i.e. the first packet in a new connection).
func (q *ParsedPacket) IsTCPSyn() bool { func (q *Parsed) IsTCPSyn() bool {
return (q.TCPFlags & TCPSynAck) == TCPSyn return (q.TCPFlags & TCPSynAck) == TCPSyn
} }
// IsError reports whether q is an IPv4 ICMP "Error" packet. // IsError reports whether q is an IPv4 ICMP "Error" packet.
func (q *ParsedPacket) IsError() bool { func (q *Parsed) IsError() bool {
if q.IPProto == ICMP && len(q.b) >= q.subofs+8 { if q.IPProto == ICMP && len(q.b) >= q.subofs+8 {
switch ICMP4Type(q.b[q.subofs]) { switch ICMP4Type(q.b[q.subofs]) {
case ICMP4Unreachable, ICMP4TimeExceeded: case ICMP4Unreachable, ICMP4TimeExceeded:
@ -293,7 +293,7 @@ func (q *ParsedPacket) IsError() bool {
} }
// IsEchoRequest reports whether q is an IPv4 ICMP Echo Request. // IsEchoRequest reports whether q is an IPv4 ICMP Echo Request.
func (q *ParsedPacket) IsEchoRequest() bool { func (q *Parsed) IsEchoRequest() bool {
if q.IPProto == ICMP && len(q.b) >= q.subofs+8 { if q.IPProto == ICMP && len(q.b) >= q.subofs+8 {
return ICMP4Type(q.b[q.subofs]) == ICMP4EchoRequest && return ICMP4Type(q.b[q.subofs]) == ICMP4EchoRequest &&
ICMP4Code(q.b[q.subofs+1]) == ICMP4NoCode ICMP4Code(q.b[q.subofs+1]) == ICMP4NoCode
@ -302,7 +302,7 @@ func (q *ParsedPacket) IsEchoRequest() bool {
} }
// IsEchoRequest reports whether q is an IPv4 ICMP Echo Response. // IsEchoRequest reports whether q is an IPv4 ICMP Echo Response.
func (q *ParsedPacket) IsEchoResponse() bool { func (q *Parsed) IsEchoResponse() bool {
if q.IPProto == ICMP && len(q.b) >= q.subofs+8 { if q.IPProto == ICMP && len(q.b) >= q.subofs+8 {
return ICMP4Type(q.b[q.subofs]) == ICMP4EchoReply && return ICMP4Type(q.b[q.subofs]) == ICMP4EchoReply &&
ICMP4Code(q.b[q.subofs+1]) == ICMP4NoCode ICMP4Code(q.b[q.subofs+1]) == ICMP4NoCode

@ -41,7 +41,7 @@ var icmpRequestBuffer = []byte{
0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64,
} }
var icmpRequestDecode = ParsedPacket{ var icmpRequestDecode = Parsed{
b: icmpRequestBuffer, b: icmpRequestBuffer,
subofs: 20, subofs: 20,
dataofs: 24, dataofs: 24,
@ -67,7 +67,7 @@ var icmpReplyBuffer = []byte{
0x72, 0x65, 0x70, 0x6c, 0x79, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x72, 0x65, 0x70, 0x6c, 0x79, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64,
} }
var icmpReplyDecode = ParsedPacket{ var icmpReplyDecode = Parsed{
b: icmpReplyBuffer, b: icmpReplyBuffer,
subofs: 20, subofs: 20,
dataofs: 24, dataofs: 24,
@ -91,7 +91,7 @@ var ipv6PacketBuffer = []byte{
0x85, 0x00, 0x38, 0x04, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x38, 0x04, 0x00, 0x00, 0x00, 0x00,
} }
var ipv6PacketDecode = ParsedPacket{ var ipv6PacketDecode = Parsed{
b: ipv6PacketBuffer, b: ipv6PacketBuffer,
IPVersion: 6, IPVersion: 6,
IPProto: ICMPv6, IPProto: ICMPv6,
@ -103,7 +103,7 @@ var unknownPacketBuffer = []byte{
0x45, 0x74, 0x63, 0x70, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x45, 0x74, 0x63, 0x70, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64,
} }
var unknownPacketDecode = ParsedPacket{ var unknownPacketDecode = Parsed{
b: unknownPacketBuffer, b: unknownPacketBuffer,
IPVersion: 0, IPVersion: 0,
IPProto: Unknown, IPProto: Unknown,
@ -123,7 +123,7 @@ var tcpPacketBuffer = []byte{
0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64,
} }
var tcpPacketDecode = ParsedPacket{ var tcpPacketDecode = Parsed{
b: tcpPacketBuffer, b: tcpPacketBuffer,
subofs: 20, subofs: 20,
dataofs: 40, dataofs: 40,
@ -151,7 +151,7 @@ var udpRequestBuffer = []byte{
0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64,
} }
var udpRequestDecode = ParsedPacket{ var udpRequestDecode = Parsed{
b: udpRequestBuffer, b: udpRequestBuffer,
subofs: 20, subofs: 20,
dataofs: 28, dataofs: 28,
@ -178,7 +178,7 @@ var udpReplyBuffer = []byte{
0x72, 0x65, 0x70, 0x6c, 0x79, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x72, 0x65, 0x70, 0x6c, 0x79, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64,
} }
var udpReplyDecode = ParsedPacket{ var udpReplyDecode = Parsed{
b: udpReplyBuffer, b: udpReplyBuffer,
subofs: 20, subofs: 20,
dataofs: 28, dataofs: 28,
@ -191,10 +191,10 @@ var udpReplyDecode = ParsedPacket{
DstPort: 123, DstPort: 123,
} }
func TestParsedPacket(t *testing.T) { func TestParsed(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
qdecode ParsedPacket qdecode Parsed
want string want string
}{ }{
{"tcp", tcpPacketDecode, "TCP{1.2.3.4:123 > 5.6.7.8:567}"}, {"tcp", tcpPacketDecode, "TCP{1.2.3.4:123 > 5.6.7.8:567}"},
@ -226,7 +226,7 @@ func TestDecode(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
buf []byte buf []byte
want ParsedPacket want Parsed
}{ }{
{"icmp", icmpRequestBuffer, icmpRequestDecode}, {"icmp", icmpRequestBuffer, icmpRequestDecode},
{"ipv6", ipv6PacketBuffer, ipv6PacketDecode}, {"ipv6", ipv6PacketBuffer, ipv6PacketDecode},
@ -237,7 +237,7 @@ func TestDecode(t *testing.T) {
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
var got ParsedPacket var got Parsed
got.Decode(tt.buf) got.Decode(tt.buf)
if !reflect.DeepEqual(got, tt.want) { if !reflect.DeepEqual(got, tt.want) {
t.Errorf("mismatch\n got: %#v\nwant: %#v", got, tt.want) t.Errorf("mismatch\n got: %#v\nwant: %#v", got, tt.want)
@ -246,7 +246,7 @@ func TestDecode(t *testing.T) {
} }
allocs := testing.AllocsPerRun(1000, func() { allocs := testing.AllocsPerRun(1000, func() {
var got ParsedPacket var got Parsed
got.Decode(tests[0].buf) got.Decode(tests[0].buf)
}) })
if allocs != 0 { if allocs != 0 {
@ -267,7 +267,7 @@ func BenchmarkDecode(b *testing.B) {
for _, bench := range benches { for _, bench := range benches {
b.Run(bench.name, func(b *testing.B) { b.Run(bench.name, func(b *testing.B) {
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
var p ParsedPacket var p Parsed
p.Decode(bench.buf) p.Decode(bench.buf)
} }
}) })

@ -153,7 +153,7 @@ func maybeHexdump(flag RunFlags, b []byte) string {
var acceptBucket = rate.NewLimiter(rate.Every(10*time.Second), 3) var acceptBucket = rate.NewLimiter(rate.Every(10*time.Second), 3)
var dropBucket = rate.NewLimiter(rate.Every(5*time.Second), 10) var dropBucket = rate.NewLimiter(rate.Every(5*time.Second), 10)
func (f *Filter) logRateLimit(runflags RunFlags, q *packet.ParsedPacket, dir direction, r Response, why string) { func (f *Filter) logRateLimit(runflags RunFlags, q *packet.Parsed, dir direction, r Response, why string) {
var verdict string var verdict string
if r == Drop && omitDropLogging(q, dir) { if r == Drop && omitDropLogging(q, dir) {
@ -186,7 +186,7 @@ var dummyPacket = []byte{
// CheckTCP determines whether TCP traffic from srcIP to dstIP:dstPort // CheckTCP determines whether TCP traffic from srcIP to dstIP:dstPort
// is allowed. // is allowed.
func (f *Filter) CheckTCP(srcIP, dstIP netaddr.IP, dstPort uint16) Response { func (f *Filter) CheckTCP(srcIP, dstIP netaddr.IP, dstPort uint16) Response {
pkt := &packet.ParsedPacket{} pkt := &packet.Parsed{}
pkt.Decode(dummyPacket) // initialize private fields pkt.Decode(dummyPacket) // initialize private fields
pkt.IPVersion = 4 pkt.IPVersion = 4
pkt.IPProto = packet.TCP pkt.IPProto = packet.TCP
@ -201,7 +201,7 @@ func (f *Filter) CheckTCP(srcIP, dstIP netaddr.IP, dstPort uint16) Response {
// RunIn determines whether this node is allowed to receive q from a // RunIn determines whether this node is allowed to receive q from a
// Tailscale peer. // Tailscale peer.
func (f *Filter) RunIn(q *packet.ParsedPacket, rf RunFlags) Response { func (f *Filter) RunIn(q *packet.Parsed, rf RunFlags) Response {
dir := in dir := in
r := f.pre(q, rf, dir) r := f.pre(q, rf, dir)
if r == Accept || r == Drop { if r == Accept || r == Drop {
@ -216,7 +216,7 @@ func (f *Filter) RunIn(q *packet.ParsedPacket, rf RunFlags) Response {
// RunOut determines whether this node is allowed to send q to a // RunOut determines whether this node is allowed to send q to a
// Tailscale peer. // Tailscale peer.
func (f *Filter) RunOut(q *packet.ParsedPacket, rf RunFlags) Response { func (f *Filter) RunOut(q *packet.Parsed, rf RunFlags) Response {
dir := out dir := out
r := f.pre(q, rf, dir) r := f.pre(q, rf, dir)
if r == Drop || r == Accept { if r == Drop || r == Accept {
@ -229,7 +229,7 @@ func (f *Filter) RunOut(q *packet.ParsedPacket, rf RunFlags) Response {
} }
// runIn runs the input-specific part of the filter logic. // runIn runs the input-specific part of the filter logic.
func (f *Filter) runIn(q *packet.ParsedPacket) (r Response, why string) { func (f *Filter) runIn(q *packet.Parsed) (r Response, why string) {
// A compromised peer could try to send us packets for // A compromised peer could try to send us packets for
// destinations we didn't explicitly advertise. This check is to // destinations we didn't explicitly advertise. This check is to
// prevent that. // prevent that.
@ -290,7 +290,7 @@ func (f *Filter) runIn(q *packet.ParsedPacket) (r Response, why string) {
} }
// runIn runs the output-specific part of the filter logic. // runIn runs the output-specific part of the filter logic.
func (f *Filter) runOut(q *packet.ParsedPacket) (r Response, why string) { func (f *Filter) runOut(q *packet.Parsed) (r Response, why string) {
if q.IPProto == packet.UDP { if q.IPProto == packet.UDP {
t := tuple{q.DstIP, q.SrcIP, q.DstPort, q.SrcPort} t := tuple{q.DstIP, q.SrcIP, q.DstPort, q.SrcPort}
var ti interface{} = t // allocate once, rather than twice inside mutex var ti interface{} = t // allocate once, rather than twice inside mutex
@ -324,7 +324,7 @@ func (d direction) String() string {
// pre runs the direction-agnostic filter logic. dir is only used for // pre runs the direction-agnostic filter logic. dir is only used for
// logging. // logging.
func (f *Filter) pre(q *packet.ParsedPacket, rf RunFlags, dir direction) Response { func (f *Filter) pre(q *packet.Parsed, rf RunFlags, dir direction) Response {
if len(q.Buffer()) == 0 { if len(q.Buffer()) == 0 {
// wireguard keepalive packet, always permit. // wireguard keepalive packet, always permit.
return Accept return Accept
@ -354,7 +354,7 @@ func (f *Filter) pre(q *packet.ParsedPacket, rf RunFlags, dir direction) Respons
return Drop return Drop
case packet.Fragment: case packet.Fragment:
// Fragments after the first always need to be passed through. // Fragments after the first always need to be passed through.
// Very small fragments are considered Junk by ParsedPacket. // Very small fragments are considered Junk by Parsed.
f.logRateLimit(rf, q, dir, Accept, "fragment") f.logRateLimit(rf, q, dir, Accept, "fragment")
return Accept return Accept
} }
@ -373,13 +373,13 @@ const (
// deemed a packet to Drop, should bypass the [rate-limited] logging. // deemed a packet to Drop, should bypass the [rate-limited] logging.
// We don't want to log scary & spammy reject warnings for packets // We don't want to log scary & spammy reject warnings for packets
// that are totally normal, like IPv6 route announcements. // that are totally normal, like IPv6 route announcements.
func omitDropLogging(p *packet.ParsedPacket, dir direction) bool { func omitDropLogging(p *packet.Parsed, dir direction) bool {
b := p.Buffer() b := p.Buffer()
switch dir { switch dir {
case out: case out:
switch p.IPVersion { switch p.IPVersion {
case 4: case 4:
// ParsedPacket.Decode zeros out ParsedPacket.IPProtocol for protocols // Parsed.Decode zeros out Parsed.IPProtocol for protocols
// it doesn't know about, so parse it out ourselves if needed. // it doesn't know about, so parse it out ourselves if needed.
ipProto := p.IPProto ipProto := p.IPProto
if ipProto == 0 && len(b) > 8 { if ipProto == 0 && len(b) > 8 {

@ -134,7 +134,7 @@ func TestFilter(t *testing.T) {
type InOut struct { type InOut struct {
want Response want Response
p packet.ParsedPacket p packet.Parsed
} }
tests := []InOut{ tests := []InOut{
// Basic // Basic
@ -199,7 +199,7 @@ func TestNoAllocs(t *testing.T) {
for _, test := range tests { for _, test := range tests {
t.Run(test.name, func(t *testing.T) { t.Run(test.name, func(t *testing.T) {
got := int(testing.AllocsPerRun(1000, func() { got := int(testing.AllocsPerRun(1000, func() {
q := &packet.ParsedPacket{} q := &packet.Parsed{}
q.Decode(test.packet) q.Decode(test.packet)
if test.in { if test.in {
acl.RunIn(q, 0) acl.RunIn(q, 0)
@ -274,7 +274,7 @@ func BenchmarkFilter(b *testing.B) {
b.Run(bench.name, func(b *testing.B) { b.Run(bench.name, func(b *testing.B) {
b.ReportAllocs() b.ReportAllocs()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
q := &packet.ParsedPacket{} q := &packet.Parsed{}
q.Decode(bench.packet) q.Decode(bench.packet)
// This branch seems to have no measurable impact on performance. // This branch seems to have no measurable impact on performance.
if bench.in { if bench.in {
@ -303,7 +303,7 @@ func TestPreFilter(t *testing.T) {
} }
f := NewAllowNone(t.Logf) f := NewAllowNone(t.Logf)
for _, testPacket := range packets { for _, testPacket := range packets {
p := &packet.ParsedPacket{} p := &packet.Parsed{}
p.Decode(testPacket.b) p.Decode(testPacket.b)
got := f.pre(p, LogDrops|LogAccepts, in) got := f.pre(p, LogDrops|LogAccepts, in)
if got != testPacket.want { if got != testPacket.want {
@ -312,8 +312,8 @@ func TestPreFilter(t *testing.T) {
} }
} }
func parsed(proto packet.IP4Proto, src, dst packet.IP4, sport, dport uint16) packet.ParsedPacket { func parsed(proto packet.IP4Proto, src, dst packet.IP4, sport, dport uint16) packet.Parsed {
return packet.ParsedPacket{ return packet.Parsed{
IPProto: proto, IPProto: proto,
SrcIP: src, SrcIP: src,
DstIP: dst, DstIP: dst,
@ -385,13 +385,13 @@ func rawdefault(proto packet.IP4Proto, trimLength int) []byte {
return rawpacket(proto, ip, ip, port, port, trimLength) return rawpacket(proto, ip, ip, port, port, trimLength)
} }
func parseHexPkt(t *testing.T, h string) *packet.ParsedPacket { func parseHexPkt(t *testing.T, h string) *packet.Parsed {
t.Helper() t.Helper()
b, err := hex.DecodeString(strings.ReplaceAll(h, " ", "")) b, err := hex.DecodeString(strings.ReplaceAll(h, " ", ""))
if err != nil { if err != nil {
t.Fatalf("failed to read hex %q: %v", h, err) t.Fatalf("failed to read hex %q: %v", h, err)
} }
p := new(packet.ParsedPacket) p := new(packet.Parsed)
p.Decode(b) p.Decode(b)
return p return p
} }
@ -399,13 +399,13 @@ func parseHexPkt(t *testing.T, h string) *packet.ParsedPacket {
func TestOmitDropLogging(t *testing.T) { func TestOmitDropLogging(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
pkt *packet.ParsedPacket pkt *packet.Parsed
dir direction dir direction
want bool want bool
}{ }{
{ {
name: "v4_tcp_out", name: "v4_tcp_out",
pkt: &packet.ParsedPacket{IPVersion: 4, IPProto: packet.TCP}, pkt: &packet.Parsed{IPVersion: 4, IPProto: packet.TCP},
dir: out, dir: out,
want: false, want: false,
}, },
@ -435,19 +435,19 @@ func TestOmitDropLogging(t *testing.T) {
}, },
{ {
name: "v4_multicast_out_low", name: "v4_multicast_out_low",
pkt: &packet.ParsedPacket{IPVersion: 4, DstIP: packet.NewIP4(net.ParseIP("224.0.0.0"))}, pkt: &packet.Parsed{IPVersion: 4, DstIP: packet.NewIP4(net.ParseIP("224.0.0.0"))},
dir: out, dir: out,
want: true, want: true,
}, },
{ {
name: "v4_multicast_out_high", name: "v4_multicast_out_high",
pkt: &packet.ParsedPacket{IPVersion: 4, DstIP: packet.NewIP4(net.ParseIP("239.255.255.255"))}, pkt: &packet.Parsed{IPVersion: 4, DstIP: packet.NewIP4(net.ParseIP("239.255.255.255"))},
dir: out, dir: out,
want: true, want: true,
}, },
{ {
name: "v4_link_local_unicast", name: "v4_link_local_unicast",
pkt: &packet.ParsedPacket{IPVersion: 4, DstIP: packet.NewIP4(net.ParseIP("169.254.1.2"))}, pkt: &packet.Parsed{IPVersion: 4, DstIP: packet.NewIP4(net.ParseIP("169.254.1.2"))},
dir: out, dir: out,
want: true, want: true,
}, },

@ -102,7 +102,7 @@ func newMatches4(ms []Match) (ret matches4) {
// match returns whether q's source IP and destination IP:port match // match returns whether q's source IP and destination IP:port match
// any of ms. // any of ms.
func (ms matches4) match(q *packet.ParsedPacket) bool { func (ms matches4) match(q *packet.Parsed) bool {
for _, m := range ms { for _, m := range ms {
if !ip4InList(q.SrcIP, m.srcs) { if !ip4InList(q.SrcIP, m.srcs) {
continue continue
@ -122,7 +122,7 @@ func (ms matches4) match(q *packet.ParsedPacket) bool {
// matchIPsOnly returns whether q's source and destination IP match // matchIPsOnly returns whether q's source and destination IP match
// any of ms. // any of ms.
func (ms matches4) matchIPsOnly(q *packet.ParsedPacket) bool { func (ms matches4) matchIPsOnly(q *packet.Parsed) bool {
for _, m := range ms { for _, m := range ms {
if !ip4InList(q.SrcIP, m.srcs) { if !ip4InList(q.SrcIP, m.srcs) {
continue continue

@ -45,14 +45,14 @@ var (
errOffsetTooSmall = errors.New("offset smaller than PacketStartOffset") errOffsetTooSmall = errors.New("offset smaller than PacketStartOffset")
) )
// parsedPacketPool holds a pool of ParsedPacket structs for use in filtering. // parsedPacketPool holds a pool of Parsed structs for use in filtering.
// This is needed because escape analysis cannot see that parsed packets // This is needed because escape analysis cannot see that parsed packets
// do not escape through {Pre,Post}Filter{In,Out}. // do not escape through {Pre,Post}Filter{In,Out}.
var parsedPacketPool = sync.Pool{New: func() interface{} { return new(packet.ParsedPacket) }} var parsedPacketPool = sync.Pool{New: func() interface{} { return new(packet.Parsed) }}
// FilterFunc is a packet-filtering function with access to the TUN device. // FilterFunc is a packet-filtering function with access to the TUN device.
// It must not hold onto the packet struct, as its backing storage will be reused. // It must not hold onto the packet struct, as its backing storage will be reused.
type FilterFunc func(*packet.ParsedPacket, *TUN) filter.Response type FilterFunc func(*packet.Parsed, *TUN) filter.Response
// TUN wraps a tun.Device from wireguard-go, // TUN wraps a tun.Device from wireguard-go,
// augmenting it with filtering and packet injection. // augmenting it with filtering and packet injection.
@ -214,7 +214,7 @@ func (t *TUN) poll() {
} }
} }
func (t *TUN) filterOut(p *packet.ParsedPacket) filter.Response { func (t *TUN) filterOut(p *packet.Parsed) filter.Response {
if t.PreFilterOut != nil { if t.PreFilterOut != nil {
if t.PreFilterOut(p, t) == filter.Drop { if t.PreFilterOut(p, t) == filter.Drop {
@ -278,7 +278,7 @@ func (t *TUN) Read(buf []byte, offset int) (int, error) {
} }
} }
p := parsedPacketPool.Get().(*packet.ParsedPacket) p := parsedPacketPool.Get().(*packet.Parsed)
defer parsedPacketPool.Put(p) defer parsedPacketPool.Put(p)
p.Decode(buf[offset : offset+n]) p.Decode(buf[offset : offset+n])
@ -301,7 +301,7 @@ func (t *TUN) Read(buf []byte, offset int) (int, error) {
} }
func (t *TUN) filterIn(buf []byte) filter.Response { func (t *TUN) filterIn(buf []byte) filter.Response {
p := parsedPacketPool.Get().(*packet.ParsedPacket) p := parsedPacketPool.Get().(*packet.Parsed)
defer parsedPacketPool.Put(p) defer parsedPacketPool.Put(p)
p.Decode(buf) p.Decode(buf)

@ -370,7 +370,7 @@ func newUserspaceEngineAdvanced(conf EngineConfig) (_ Engine, reterr error) {
} }
// echoRespondToAll is an inbound post-filter responding to all echo requests. // echoRespondToAll is an inbound post-filter responding to all echo requests.
func echoRespondToAll(p *packet.ParsedPacket, t *tstun.TUN) filter.Response { func echoRespondToAll(p *packet.Parsed, t *tstun.TUN) filter.Response {
if p.IsEchoRequest() { if p.IsEchoRequest() {
header := p.ICMPHeader() header := p.ICMPHeader()
header.ToResponse() header.ToResponse()
@ -391,7 +391,7 @@ func echoRespondToAll(p *packet.ParsedPacket, t *tstun.TUN) filter.Response {
// stack, and intercepts any packets that should be handled by // stack, and intercepts any packets that should be handled by
// tailscaled directly. Other packets are allowed to proceed into the // tailscaled directly. Other packets are allowed to proceed into the
// main ACL filter. // main ACL filter.
func (e *userspaceEngine) handleLocalPackets(p *packet.ParsedPacket, t *tstun.TUN) filter.Response { func (e *userspaceEngine) handleLocalPackets(p *packet.Parsed, t *tstun.TUN) filter.Response {
if verdict := e.handleDNS(p, t); verdict == filter.Drop { if verdict := e.handleDNS(p, t); verdict == filter.Drop {
// local DNS handled the packet. // local DNS handled the packet.
return filter.Drop return filter.Drop
@ -420,7 +420,7 @@ func (e *userspaceEngine) isLocalAddr(ip packet.IP4) bool {
} }
// handleDNS is an outbound pre-filter resolving Tailscale domains. // handleDNS is an outbound pre-filter resolving Tailscale domains.
func (e *userspaceEngine) handleDNS(p *packet.ParsedPacket, t *tstun.TUN) filter.Response { func (e *userspaceEngine) handleDNS(p *packet.Parsed, t *tstun.TUN) filter.Response {
if p.DstIP == magicDNSIP && p.DstPort == magicDNSPort && p.IPProto == packet.UDP { if p.DstIP == magicDNSIP && p.DstPort == magicDNSPort && p.IPProto == packet.UDP {
request := tsdns.Packet{ request := tsdns.Packet{
Payload: append([]byte(nil), p.Payload()...), Payload: append([]byte(nil), p.Payload()...),

Loading…
Cancel
Save