Skip to content

Commit e3206cc

Browse files
author
Preetam Jinka
committed
Merge pull request #5 from PreetamJinka/4-errors
Add decoding errors
2 parents 65f65fa + 13f1909 commit e3206cc

File tree

12 files changed

+113
-26
lines changed

12 files changed

+113
-26
lines changed

decode_test.go

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,29 @@ func TestMultilayerDecode(t *testing.T) {
1515
10, 184, 73, 195, 65, 0, 0, 0, 0, 1, 3, 3, 7,
1616
}
1717

18-
ethernetFrame := DecodeEthernet(b)
18+
ethernetFrame, err := DecodeEthernet(b)
19+
if err != nil {
20+
t.Fatal(err)
21+
}
22+
1923
if ethernetFrame.EtherType != 0x86dd {
2024
t.Fatalf("expected to see EtherType %x, got %x", 0x86dd, ethernetFrame.EtherType)
2125
}
2226

23-
ipv6Packet := DecodeIPv6(ethernetFrame.Payload)
27+
ipv6Packet, err := DecodeIPv6(ethernetFrame.Payload)
28+
if err != nil {
29+
t.Fatal(err)
30+
}
31+
2432
if ipv6Packet.NextHeader != 0x6 {
2533
t.Fatalf("expected to see NextHeader %x, got %x", 0x6, ipv6Packet.NextHeader)
2634
}
2735

28-
tcpPacket := DecodeTCP(ipv6Packet.Payload)
36+
tcpPacket, err := DecodeTCP(ipv6Packet.Payload)
37+
if err != nil {
38+
t.Fatal(err)
39+
}
40+
2941
if tcpPacket.DestinationPort != 80 {
3042
t.Fatalf("expected to see destination port %v, got %v", 80, tcpPacket.DestinationPort)
3143
}
@@ -51,8 +63,8 @@ func BenchmarkMultilayerDecode(b *testing.B) {
5163
}
5264

5365
for i := 0; i < b.N; i++ {
54-
ethernetFrame := DecodeEthernet(buf[:])
55-
ipv6Packet := DecodeIPv6(ethernetFrame.Payload)
66+
ethernetFrame, _ := DecodeEthernet(buf[:])
67+
ipv6Packet, _ := DecodeIPv6(ethernetFrame.Payload)
5668
DecodeTCP(ipv6Packet.Payload)
5769
}
5870
}

errors.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package proto
2+
3+
import (
4+
"errors"
5+
)
6+
7+
var (
8+
ErrorNotEnoughBytes = errors.New("proto: not enough bytes available to decode")
9+
)

ethernet.go

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,35 +12,44 @@ type EthernetFrame struct {
1212
Payload []byte `json:"payload"`
1313
}
1414

15-
func DecodeEthernet(b []byte) EthernetFrame {
15+
const minEthernetFrameSize = 6 + 6 + 4 + 2
16+
17+
// DecodeEthernet decodes an Ethernet frame.
18+
func DecodeEthernet(b []byte) (EthernetFrame, error) {
1619
frame := EthernetFrame{}
1720

18-
i := 0 // just a helper for indexing
21+
if len(b) < minEthernetFrameSize {
22+
return frame, ErrorNotEnoughBytes
23+
}
24+
25+
i := 0 // Just a helper for indexing.
1926

27+
// Decode MAC addresses.
2028
frame.Destination = net.HardwareAddr(b[i : i+6])
2129
i += 6
2230
frame.Source = net.HardwareAddr(b[i : i+6])
2331
i += 6
2432

25-
// Check for a VLAN tag
33+
// Check for a VLAN tag.
2634
if b[i] == 0x81 && b[i+1] == 0x00 {
2735
i += 2
2836
frame.VlanTag = uint32(0x81<<24) | uint32(0x00<<16) | uint32(b[i]<<8) | uint32(b[i+1])
2937
i += 2
3038
}
3139

3240
// Check the Ethernet type
33-
if t := uint16(b[i])<<8 | uint16(b[i+1]); t >= 1536 { // if 1500 or less, then it's the payload length
41+
if t := uint16(b[i])<<8 | uint16(b[i+1]); t >= 1536 { // If 1500 or less, it's the payload length.
3442
frame.EtherType = t
3543
}
3644

3745
i += 2
3846

3947
frame.Payload = b[i:]
4048

41-
return frame
49+
return frame, nil
4250
}
4351

52+
// Bytes returns an encoded Ethernet frame.
4453
func (f EthernetFrame) Bytes() []byte {
4554
i := 0
4655

ethernet_test.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@ func TestEthernet(t *testing.T) {
2020
1, 0, 0, 84, 7, 0, 4, 199, 58, 162, 130,
2121
}
2222

23-
frame := DecodeEthernet(b)
23+
frame, err := DecodeEthernet(b)
24+
if err != nil {
25+
t.Fatal(err)
26+
}
27+
2428
if frame.Source.String() != "e8:de:27:bb:6b:aa" {
2529
t.Error("Got the wrong source MAC:", frame.Source.String())
2630
}
@@ -37,7 +41,10 @@ func TestEthernetEncode(t *testing.T) {
3741

3842
b := e.Bytes()
3943

40-
frame := DecodeEthernet(b)
44+
frame, err := DecodeEthernet(b)
45+
if err != nil {
46+
t.Fatal(err)
47+
}
4148

4249
if !reflect.DeepEqual(frame, e) {
4350
t.Error("Encoded and decoded Ethernet frames not equal:", frame, e)

ipv4.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,16 @@ type IPv4Packet struct {
2222
Payload []byte `json:"payload"`
2323
}
2424

25-
func DecodeIPv4(b []byte) IPv4Packet {
25+
const minIPv4PacketSize = 1 + 1 + 1 + 1 + 2 + 2 + 1 + 2 + 1 + 1 + 2 + 4 + 4
26+
27+
// DecodeIPv4 decodes an IPv4 packet.
28+
func DecodeIPv4(b []byte) (IPv4Packet, error) {
2629
packet := IPv4Packet{}
2730

31+
if len(b) < minIPv4PacketSize {
32+
return packet, ErrorNotEnoughBytes
33+
}
34+
2835
i := 0
2936

3037
packet.Version = uint8(b[i] >> 4)
@@ -66,9 +73,10 @@ func DecodeIPv4(b []byte) IPv4Packet {
6673

6774
packet.Payload = b[i:]
6875

69-
return packet
76+
return packet, nil
7077
}
7178

79+
// Bytes returns an encoded IPv4 packet.
7280
func (p IPv4Packet) Bytes() []byte {
7381
i := 0
7482

@@ -125,6 +133,7 @@ func (p IPv4Packet) Bytes() []byte {
125133
return b[:i]
126134
}
127135

136+
// ComputeChecksum returns the checksum for the IPv4 packet.
128137
func (p IPv4Packet) ComputeChecksum() uint16 {
129138
sum := ((uint32(p.Version)<<4|uint32(p.InternetHeaderLength))<<8 |
130139
(uint32(p.DSCP)<<2 | uint32(p.ECN))) +

ipv4_test.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,11 @@ func TestIPv4(t *testing.T) {
1919
58, 32, 42, 47, 42, 13, 10, 13, 10,
2020
}
2121

22-
packet := DecodeIPv4(b)
22+
packet, err := DecodeIPv4(b)
23+
if err != nil {
24+
t.Fatal(err)
25+
}
26+
2327
if packet.Source.String() != "192.168.0.103" {
2428
t.Errorf("expected source IPv4 address %v, got %v", "192.168.0.103", packet.Source)
2529
}
@@ -63,7 +67,10 @@ func TestIPv4Encode(t *testing.T) {
6367

6468
packet.HeaderChecksum = packet.ComputeChecksum()
6569

66-
decoded := DecodeIPv4(packet.Bytes())
70+
decoded, err := DecodeIPv4(packet.Bytes())
71+
if err != nil {
72+
t.Fatal(err)
73+
}
6774

6875
if !reflect.DeepEqual(packet, decoded) {
6976
t.Error("Encoded and decoded IPv4 packets not equal:", decoded, packet)

ipv6.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,16 @@ type IPv6Packet struct {
1616
Payload []byte `json:"payload"`
1717
}
1818

19-
func DecodeIPv6(b []byte) IPv6Packet {
19+
const minIPv6PacketSize = 1 + 1 + 4 + 2 + 1 + 1 + 16 + 16
20+
21+
// DecodeIPv6 decodes an IPv6 packet.
22+
func DecodeIPv6(b []byte) (IPv6Packet, error) {
2023
packet := IPv6Packet{}
2124

25+
if len(b) < minIPv6PacketSize {
26+
return packet, ErrorNotEnoughBytes
27+
}
28+
2229
i := 0
2330

2431
packet.Version = b[i] >> 4
@@ -45,9 +52,10 @@ func DecodeIPv6(b []byte) IPv6Packet {
4552

4653
packet.Payload = b[i:]
4754

48-
return packet
55+
return packet, nil
4956
}
5057

58+
// Bytes returns an encoded IPv6 packet.
5159
func (p IPv6Packet) Bytes() []byte {
5260
i := 0
5361
b := make([]byte, 40+len(p.Payload))

ipv6_test.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ func TestIPv6(t *testing.T) {
1616
187, 0, 0, 0, 0, 1, 3, 3, 7,
1717
}
1818

19-
packet := DecodeIPv6(b)
19+
packet, err := DecodeIPv6(b)
20+
if err != nil {
21+
t.Fatal(err)
22+
}
2023

2124
if packet.Destination.String() != "2620:100:5007:2::2" {
2225
t.Errorf("expected destination address %v, got %v",
@@ -42,7 +45,10 @@ func TestIPv6Encode(t *testing.T) {
4245
},
4346
}
4447

45-
p := DecodeIPv6(packet.Bytes())
48+
p, err := DecodeIPv6(packet.Bytes())
49+
if err != nil {
50+
t.Fatal(err)
51+
}
4652

4753
if !reflect.DeepEqual(packet, p) {
4854
t.Error("Encoded and decoded IPv6 packets not equal:", packet, p)

tcp.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ type TCPPacket struct {
2121
Payload []byte `json:"payload"`
2222
}
2323

24+
const minTCPPacketSize = 2 + 2 + 4 + 4 + 1 + 2 + 2 + 2 + 2
25+
2426
func (p TCPPacket) HasFIN() bool {
2527
return p.Flags&(1<<0) > 0
2628
}
@@ -57,9 +59,14 @@ func (p TCPPacket) HasNS() bool {
5759
return p.Flags>>8 > 0
5860
}
5961

60-
func DecodeTCP(b []byte) TCPPacket {
62+
// DecodeTCP decodes an TCP packet.
63+
func DecodeTCP(b []byte) (TCPPacket, error) {
6164
packet := TCPPacket{}
6265

66+
if len(b) < minTCPPacketSize {
67+
return packet, ErrorNotEnoughBytes
68+
}
69+
6370
i := 0
6471

6572
packet.SourcePort = uint16(b[i])<<8 | uint16(b[i+1])
@@ -93,5 +100,5 @@ func DecodeTCP(b []byte) TCPPacket {
93100

94101
packet.Payload = b[i:]
95102

96-
return packet
103+
return packet, nil
97104
}

tcp_test.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ func TestTCP(t *testing.T) {
1616
13, 10,
1717
}
1818

19-
tcpPacket := DecodeTCP(b)
19+
tcpPacket, err := DecodeTCP(b)
20+
if err != nil {
21+
t.Fatal(err)
22+
}
2023

2124
if tcpPacket.DestinationPort != 80 {
2225
t.Errorf("expected destination port %v, got %v", 80, tcpPacket.DestinationPort)

0 commit comments

Comments
 (0)