Skip to content

Commit 190a2ef

Browse files
committed
Synced updates from internal repo: updated layer types for AGUEVar0, AGUEVar1, and APSP; implemented related tests; ran go mod tidy to update dependencies.
1 parent 32ee382 commit 190a2ef

File tree

10 files changed

+764
-81
lines changed

10 files changed

+764
-81
lines changed

go.mod

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ go 1.12
55
require (
66
github.com/vishvananda/netlink v1.1.0
77
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f
8-
golang.org/x/lint v0.0.0-20200302205851-738671d3881b // indirect
98
golang.org/x/net v0.0.0-20190620200207-3b0461eec859
109
golang.org/x/sys v0.0.0-20200217220822-9197077df867
1110
)

go.sum

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,10 @@ github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17
44
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f h1:p4VB7kIXpOQvVn1ZaTIVp+3vuYAXFe3OJEvjbUYJLaA=
55
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
66
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
7-
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
8-
golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k=
9-
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
10-
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
11-
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
12-
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
137
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
148
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
15-
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
169
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
17-
golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67 h1:1Fzlr8kkDLQwqMP8GxrhptBLqZG/EDpiATneiZHY998=
18-
golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
19-
golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
20-
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
2110
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
2211
golang.org/x/sys v0.0.0-20200217220822-9197077df867 h1:JoRuNIf+rpHl+VhScRQQvzbHed86tKkqwPMV34T8myw=
2312
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
2413
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
25-
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7 h1:EBZoQjiKKPaLbPrbpssUfuHtwM6KV/vb4U85g/cigFY=
26-
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
27-
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

layers/ague_var0.go

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
// Copyright 2025 Google, Inc. All rights reserved.
2+
//
3+
// Use of this source code is governed by a BSD-style license
4+
// that can be found in the LICENSE file in the root of the source
5+
// tree.
6+
7+
package layers
8+
9+
import (
10+
"errors"
11+
12+
"github.com/google/gopacket"
13+
)
14+
15+
// AGUEVar0 represents a packet encoded with Generic UDP Encapsulation.
16+
// It should sit "under" a UDP layer with dest port 666.
17+
//
18+
// For more information about the meaning of the fields, see
19+
// https://tools.ietf.org/html/draft-ietf-intarea-gue-04#section-3.1
20+
type AGUEVar0 struct {
21+
Version uint8
22+
C bool
23+
Protocol IPProtocol
24+
Flags uint16
25+
Extensions []byte
26+
Data []byte
27+
}
28+
29+
// LayerType returns this pseudo-header's type as defined in layertypes.go
30+
func (l AGUEVar0) LayerType() gopacket.LayerType {
31+
return LayerTypeAGUEVar0
32+
}
33+
34+
// LayerContents returns a byte array containing our serialized header.
35+
func (l AGUEVar0) LayerContents() []byte {
36+
b := make([]byte, 4, 4+len(l.Extensions))
37+
hlen := uint8(len(l.Extensions))
38+
b[0] = l.Version<<6 | hlen
39+
if l.C {
40+
b[0] |= 0x20
41+
}
42+
b[0] |= hlen
43+
b[1] = byte(l.Protocol)
44+
b[2] = byte(l.Flags >> 8)
45+
b[3] = byte(l.Flags & 0xff)
46+
b = append(b, l.Extensions...)
47+
return b
48+
}
49+
50+
// LayerPayload returns an IPv4 or IPv6 packet in serialized form.
51+
func (l AGUEVar0) LayerPayload() []byte {
52+
return l.Data
53+
}
54+
55+
// SerializeTo writes our header into SerializeBuffer.
56+
func (l AGUEVar0) SerializeTo(buf gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
57+
b := l.LayerContents()
58+
writeTo, err := buf.PrependBytes(len(b))
59+
if err != nil {
60+
return err
61+
}
62+
copy(writeTo, b)
63+
return nil
64+
}
65+
66+
// CanDecode returns the type of layer we can decode.
67+
func (l AGUEVar0) CanDecode() gopacket.LayerClass {
68+
return LayerTypeAGUEVar0
69+
}
70+
71+
// DecodeFromBytes extracts our header data from a serialized packet.
72+
func (l *AGUEVar0) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
73+
l.Version = data[0] >> 6
74+
l.C = data[0]&0x20 != 0
75+
l.Protocol = IPProtocol(data[1])
76+
l.Flags = (uint16(data[2]) << 8) | uint16(data[3])
77+
hlen := data[0] & 0x1f
78+
l.Extensions = data[4 : 4+hlen]
79+
l.Data = data[4+hlen:]
80+
return nil
81+
}
82+
83+
// NextLayerType returns the next layer type, e.g. LayerTypeIPv4
84+
func (l AGUEVar0) NextLayerType() gopacket.LayerType {
85+
return l.Protocol.LayerType()
86+
}
87+
88+
// decodeAGUE decodes AGUEVar0 or AGUEVar1, depending on the first data byte.
89+
// If AGUEVar1, it refers the packet to AGUEVar1 for decoding.
90+
// Else it adds AGUEVar0 layer info to the packet object, recursively decodes
91+
// remaining layers, and returns the next-layer type (IPv4 or IPv6).
92+
func decodeAGUE(data []byte, p gopacket.PacketBuilder) error {
93+
if len(data) == 0 {
94+
return errors.New("decodeAGUE() failed, no data")
95+
}
96+
if data[0]>>6 == 1 {
97+
return decodeAGUEVar1(data, p)
98+
}
99+
l := AGUEVar0{}
100+
if err := l.DecodeFromBytes(data, gopacket.NilDecodeFeedback); err != nil {
101+
return err
102+
}
103+
p.AddLayer(l)
104+
return p.NextDecoder(l.NextLayerType())
105+
}

layers/ague_var0_test.go

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
// Copyright 2025 Google, Inc. All rights reserved.
2+
//
3+
// Use of this source code is governed by a BSD-style license
4+
// that can be found in the LICENSE file in the root of the source
5+
// tree.
6+
7+
package layers
8+
9+
import (
10+
"encoding/hex"
11+
"net"
12+
"testing"
13+
14+
"github.com/google/gopacket"
15+
)
16+
17+
func TestGueDecoding(t *testing.T) {
18+
// This is a packet generated by the Linux kernel GUE implementation, captured
19+
// by pcap. It includes:
20+
// - Ethernet
21+
// - IPv4
22+
// - UDP
23+
// - AGueVar0 (port 666)
24+
// - IPv4
25+
// - ICMP (ping)
26+
// TODO: build a test packet using port 666 (0x029a)
27+
ph := `02427b2522f502420ae0d90608004500007451ea4000ff119d050ae0d9060afa9da88c0f029a00608cfa000400004500005459f240004001e2cd0ae0d9060afd0f0608000a7e005f000cea811f59000000005daa080000000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021222324252627`
28+
pr, err := hex.DecodeString(ph)
29+
if err != nil {
30+
t.Errorf("Error decoding hex packet: %v", err)
31+
}
32+
33+
p := gopacket.NewPacket(pr, LayerTypeEthernet, gopacket.Default)
34+
// require.Nil(t, p.ErrorLayer())
35+
if p.ErrorLayer() != nil {
36+
t.Errorf("AGUEVar0 layer is nil")
37+
}
38+
t.Logf("%v", p)
39+
40+
gue := p.Layer(LayerTypeAGUEVar0).(AGUEVar0)
41+
// require.NotNil(t, gue)
42+
if uint8(0) != gue.Version {
43+
t.Errorf("gue.Version is not 0")
44+
}
45+
}
46+
47+
var testIPv4OverAGUEVar0 = []gopacket.SerializableLayer{
48+
&Ethernet{
49+
SrcMAC: net.HardwareAddr{142, 122, 18, 195, 169, 113},
50+
DstMAC: net.HardwareAddr{58, 86, 107, 105, 89, 94},
51+
EthernetType: EthernetTypeIPv4,
52+
},
53+
&IPv4{
54+
Version: 4,
55+
SrcIP: net.IP{192, 168, 1, 1},
56+
DstIP: net.IP{192, 168, 1, 2},
57+
Protocol: IPProtocolUDP,
58+
Flags: IPv4DontFragment,
59+
TTL: 64,
60+
Id: 33852,
61+
IHL: 5,
62+
},
63+
&UDP{
64+
SrcPort: 8,
65+
DstPort: 666,
66+
},
67+
&AGUEVar0{
68+
Protocol: IPProtocolIPv4,
69+
},
70+
&IPv4{
71+
Version: 4,
72+
SrcIP: net.IP{172, 16, 1, 1},
73+
DstIP: net.IP{172, 16, 2, 1},
74+
Protocol: IPProtocolICMPv4,
75+
Flags: IPv4DontFragment,
76+
TTL: 64,
77+
IHL: 5,
78+
Id: 1160,
79+
},
80+
&ICMPv4{
81+
TypeCode: CreateICMPv4TypeCode(ICMPv4TypeEchoRequest, 0),
82+
Id: 4724,
83+
Seq: 1,
84+
},
85+
gopacket.Payload{
86+
0xc8, 0x92, 0xa3, 0x54, 0x00, 0x00, 0x00, 0x00, 0x38, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
87+
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
88+
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
89+
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
90+
},
91+
}
92+
93+
func TestIPv4OverAGUEVar0Encode(t *testing.T) {
94+
b := gopacket.NewSerializeBuffer()
95+
opts := gopacket.SerializeOptions{
96+
ComputeChecksums: false, // if desired, see gre_test:setNetworkLayer()
97+
FixLengths: true,
98+
}
99+
if err := gopacket.SerializeLayers(b, opts, testIPv4OverAGUEVar0...); err != nil {
100+
t.Errorf("Unable to serialize: %v", err)
101+
}
102+
p := gopacket.NewPacket(b.Bytes(), LinkTypeEthernet, gopacket.Default)
103+
if p.ErrorLayer() != nil {
104+
t.Error("Failed to decode packet:", p.ErrorLayer().Error())
105+
}
106+
checkLayers(p, []gopacket.LayerType{LayerTypeEthernet, LayerTypeIPv4, LayerTypeUDP, LayerTypeAGUEVar0, LayerTypeIPv4, LayerTypeICMPv4, gopacket.LayerTypePayload}, t)
107+
108+
// We don't have a corresponding sample packet capture, but if we did, the verify would look like this:
109+
// if got, want := b.Bytes(), testPacketAGUEVar0``; !reflect.DeepEqual(want, got) {
110+
// t.Errorf("Encoding mismatch, \nwant: %v\ngot %v\n", want, got)
111+
// }
112+
}

layers/ague_var1.go

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// Copyright 2025 Google, Inc. All rights reserved.
2+
//
3+
// Use of this source code is governed by a BSD-style license
4+
// that can be found in the LICENSE file in the root of the source
5+
// tree.
6+
7+
package layers
8+
9+
import (
10+
"errors"
11+
12+
"github.com/google/gopacket"
13+
)
14+
15+
// An AGUEVar1 header is mostly imaginary, having a length of 0 in its serialized form.
16+
// IPProtocol value is either IPProtocolIPv4 or IPProtocolIPv6, depending on the encapped
17+
// IP header contained in Data, which must begin with the high-order bits 01.
18+
type AGUEVar1 struct {
19+
Protocol IPProtocol
20+
Data []byte
21+
}
22+
23+
// LayerType returns this pseudo-header's type as defined in layertypes.go
24+
func (l AGUEVar1) LayerType() gopacket.LayerType {
25+
return LayerTypeAGUEVar1
26+
}
27+
28+
// LayerContents returns an empty byte array, because this header has no length.
29+
func (l AGUEVar1) LayerContents() []byte {
30+
b := make([]byte, 0, 0)
31+
return b
32+
}
33+
34+
// LayerPayload returns an IPv4 or IPv6 packet in serialized form.
35+
func (l AGUEVar1) LayerPayload() []byte {
36+
return l.Data
37+
}
38+
39+
// SerializeTo writes our imaginary header into SerializeBuffer. This amount to a noop.
40+
func (l AGUEVar1) SerializeTo(buf gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
41+
return nil
42+
}
43+
44+
// CanDecode returns the type of layer we can decode.
45+
func (l AGUEVar1) CanDecode() gopacket.LayerClass {
46+
return LayerTypeAGUEVar1
47+
}
48+
49+
// DecodeFromBytes extracts our pseudo-header data from a serialized packet.
50+
// There's only one thing, the next header type, which is either IPv4 or IPv6.
51+
// They are crafted to keep their own header type in the first nibble.
52+
// So we peek into the IP header to get the next-layer protocol type.
53+
func (l *AGUEVar1) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
54+
if len(data) < 1 {
55+
return errors.New("DecodeFromBytes() failed, no data")
56+
}
57+
ipVersion := data[0] >> 4
58+
if ipVersion == 4 {
59+
l.Protocol = IPProtocolIPv4
60+
} else if ipVersion == 6 {
61+
l.Protocol = IPProtocolIPv6
62+
} else {
63+
return errors.New("DecodeFromBytes() failed, unknown IP version")
64+
}
65+
l.Data = data
66+
return nil
67+
}
68+
69+
// NextLayerType returns the next layer type, e.g. LayerTypeIPv4
70+
func (l AGUEVar1) NextLayerType() gopacket.LayerType {
71+
return l.Protocol.LayerType()
72+
}
73+
74+
// decodeAGUEVar1 decodes packet data to figure out the next-layer IP type,
75+
// then adds AGUEVar1 layer info to the packet object, recursively decodes
76+
// remaining layers, and returns the next-layer type.
77+
func decodeAGUEVar1(data []byte, p gopacket.PacketBuilder) error {
78+
l := AGUEVar1{}
79+
if err := l.DecodeFromBytes(data, gopacket.NilDecodeFeedback); err != nil {
80+
return err
81+
}
82+
p.AddLayer(l)
83+
return p.NextDecoder(l.NextLayerType())
84+
}

0 commit comments

Comments
 (0)