mirror of
https://github.com/weaveworks/scope.git
synced 2026-05-21 08:33:05 +00:00
225 lines
5.9 KiB
Go
225 lines
5.9 KiB
Go
// Copyright 2012 Google, Inc. All rights reserved.
|
|
//
|
|
// Use of this source code is governed by a BSD-style license
|
|
// that can be found in the LICENSE file in the root of the source
|
|
// tree.
|
|
|
|
// This file tests some of the functionality provided in the ip4.go
|
|
|
|
package layers
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
"encoding/hex"
|
|
"net"
|
|
"reflect"
|
|
"testing"
|
|
|
|
"github.com/google/gopacket"
|
|
)
|
|
|
|
// Test the function getIPv4OptionSize when the ipv4 has no options
|
|
func TestGetIPOptLengthNoOpt(t *testing.T) {
|
|
ip := IPv4{}
|
|
length := ip.getIPv4OptionSize()
|
|
if length != 0 {
|
|
t.Fatalf("Empty option list should have 0 length. Actual %d", length)
|
|
}
|
|
}
|
|
|
|
// Test the function getIPv4OptionSize when the ipv4 has end of list option
|
|
func TestGetIPOptLengthEndOfList(t *testing.T) {
|
|
ip := IPv4{}
|
|
ip.Options = append(ip.Options, IPv4Option{OptionType: 0, OptionLength: 1})
|
|
length := ip.getIPv4OptionSize()
|
|
if length != 4 {
|
|
t.Fatalf("After padding, the list should have 4 length. Actual %d", length)
|
|
}
|
|
}
|
|
|
|
// Test the function getIPv4OptionSize when the ipv4 has padding and end of list option
|
|
func TestGetIPOptLengthPaddingEndOfList(t *testing.T) {
|
|
ip := IPv4{}
|
|
ip.Options = append(ip.Options, IPv4Option{OptionType: 1, OptionLength: 1})
|
|
ip.Options = append(ip.Options, IPv4Option{OptionType: 0, OptionLength: 1})
|
|
length := ip.getIPv4OptionSize()
|
|
if length != 4 {
|
|
t.Fatalf("After padding, the list should have 4 length. Actual %d", length)
|
|
}
|
|
}
|
|
|
|
// Test the function getIPv4OptionSize when the ipv4 has some non-trivial option and end of list option
|
|
func TestGetIPOptLengthOptionEndOfList(t *testing.T) {
|
|
ip := IPv4{}
|
|
someByte := make([]byte, 8)
|
|
ip.Options = append(ip.Options, IPv4Option{OptionType: 2, OptionLength: 10, OptionData: someByte})
|
|
ip.Options = append(ip.Options, IPv4Option{OptionType: 0, OptionLength: 1})
|
|
length := ip.getIPv4OptionSize()
|
|
if length != 12 {
|
|
t.Fatalf("The list should have 12 length. Actual %d", length)
|
|
}
|
|
}
|
|
|
|
// Tests that the Options slice is properly reset before parsing new data
|
|
func TestIPOptResetDuringDecoding(t *testing.T) {
|
|
ip := &IPv4{
|
|
Options: []IPv4Option{{OptionType: 42, OptionLength: 4, OptionData: make([]byte, 2)}},
|
|
}
|
|
|
|
ipWithoutOptions := &IPv4{
|
|
SrcIP: net.IPv4(192, 168, 1, 1),
|
|
DstIP: net.IPv4(192, 168, 1, 1),
|
|
Protocol: IPProtocolTCP,
|
|
}
|
|
|
|
ipBytes, err := serialize(ipWithoutOptions)
|
|
|
|
if err != nil {
|
|
t.Fatalf("Failed to serialize ip layer: %v", err)
|
|
}
|
|
|
|
err = ip.DecodeFromBytes(ipBytes, gopacket.NilDecodeFeedback)
|
|
|
|
if err != nil {
|
|
t.Fatalf("Failed to deserialize ip layer: %v", err)
|
|
}
|
|
|
|
if len(ip.Options) > 0 {
|
|
t.Fatalf("Options slice has stale data from previous packet")
|
|
}
|
|
|
|
}
|
|
|
|
func serialize(ip *IPv4) ([]byte, error) {
|
|
buffer := gopacket.NewSerializeBuffer()
|
|
err := ip.SerializeTo(buffer, gopacket.SerializeOptions{
|
|
FixLengths: true,
|
|
ComputeChecksums: true,
|
|
})
|
|
return buffer.Bytes(), err
|
|
}
|
|
|
|
// Test the function checksum
|
|
func TestChecksum(t *testing.T) {
|
|
testData := []struct {
|
|
name string
|
|
header string
|
|
want string
|
|
}{{
|
|
name: "sum has two carries",
|
|
header: "4540005800000000ff11ffff0aeb1d070aed8877",
|
|
want: "fffe",
|
|
}, {
|
|
name: "wikipedia case",
|
|
header: "45000073000040004011b861c0a80001c0a800c7",
|
|
want: "b861",
|
|
}}
|
|
|
|
for _, test := range testData {
|
|
bytes, err := hex.DecodeString(test.header)
|
|
if err != nil {
|
|
t.Fatalf("Failed to Decode header: %v", err)
|
|
}
|
|
wantBytes, err := hex.DecodeString(test.want)
|
|
if err != nil {
|
|
t.Fatalf("Failed to decode want checksum: %v", err)
|
|
}
|
|
|
|
if got, want := checksum(bytes), binary.BigEndian.Uint16(wantBytes); got != want {
|
|
t.Errorf("In test %q, got incorrect checksum: got(%x), want(%x)", test.name, got, want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestIPv4InvalidOptionLength(t *testing.T) {
|
|
// ip4 Packet with option 136 length set to zero
|
|
b, err := hex.DecodeString("460000705f5b0000ff114e02af2db00295ab7e0f88001234")
|
|
if err != nil {
|
|
t.Fatalf("Failed to Decode header: %v", err)
|
|
}
|
|
var ip4 IPv4
|
|
err = ip4.DecodeFromBytes(b, gopacket.NilDecodeFeedback)
|
|
if err == nil {
|
|
t.Fatal("Expected 'invalid IP option length' error, but got none.")
|
|
}
|
|
}
|
|
|
|
func TestIPv4Options(t *testing.T) {
|
|
var ip4 IPv4 // reuse ip4 to test reset
|
|
for _, test := range []struct {
|
|
packet string
|
|
options []IPv4Option
|
|
padding []byte
|
|
}{
|
|
{
|
|
packet: "4800002803040000fe01c1e0af2db00095ab7e0b820b00000000000000000000",
|
|
options: []IPv4Option{
|
|
{
|
|
OptionType: 130,
|
|
OptionData: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0},
|
|
OptionLength: 11,
|
|
},
|
|
{
|
|
OptionType: 0,
|
|
OptionLength: 1,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
packet: "4900002803040000fe01c1e0af2db00095ab7e0b01820b00000000000000000000010203",
|
|
options: []IPv4Option{
|
|
{
|
|
OptionType: 1,
|
|
OptionLength: 1,
|
|
},
|
|
{
|
|
OptionType: 130,
|
|
OptionData: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0},
|
|
OptionLength: 11,
|
|
},
|
|
{
|
|
OptionType: 0,
|
|
OptionLength: 1,
|
|
},
|
|
},
|
|
padding: []byte{1, 2, 3},
|
|
},
|
|
{
|
|
packet: "4800002803040000fe01c1e0af2db00095ab7e0b820c00000000000000000000",
|
|
options: []IPv4Option{
|
|
{
|
|
OptionType: 130,
|
|
OptionData: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
|
OptionLength: 12,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
packet: "4900002803040000fe01c1e0af2db00095ab7e0b00820b00000000000000000000010203",
|
|
options: []IPv4Option{
|
|
{
|
|
OptionType: 0,
|
|
OptionLength: 1,
|
|
},
|
|
},
|
|
padding: []byte{0x82, 0x0b, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3},
|
|
},
|
|
} {
|
|
b, err := hex.DecodeString(test.packet)
|
|
if err != nil {
|
|
t.Fatalf("Failed to Decode header: %v", err)
|
|
}
|
|
err = ip4.DecodeFromBytes(b, gopacket.NilDecodeFeedback)
|
|
if err != nil {
|
|
t.Fatal("Unexpected error during decoding:", err)
|
|
}
|
|
if !reflect.DeepEqual(ip4.Options, test.options) {
|
|
t.Fatalf("Options mismatch.\nGot:\n%#v\nExpected:\n%#v\n", ip4.Options, test.options)
|
|
}
|
|
if !bytes.Equal(ip4.Padding, test.padding) {
|
|
t.Fatalf("Padding mismatch.\nGot:\n%#v\nExpected:\n%#v\n", ip4.Padding, test.padding)
|
|
}
|
|
}
|
|
}
|