fix: updated gopacket to fix compilation issues on macOS (ref #357)

This commit is contained in:
evilsocket 2018-10-12 18:11:01 +02:00
parent 5be3fcbf20
commit a95ae94957
23 changed files with 1625 additions and 205 deletions

5
Gopkg.lock generated
View file

@ -106,7 +106,7 @@
version = "v1.0.0"
[[projects]]
digest = "1:eebcd2c096c6e4dada58e468e794146753d035fed7150cc0e2ff79ef28650709"
digest = "1:65e00adfb37f64ce3c24f139bc73db70bfe45224ebaf88250eff4038e32ac9cf"
name = "github.com/google/gopacket"
packages = [
".",
@ -115,8 +115,7 @@
"pcapgo",
]
pruneopts = "UT"
revision = "a6b099ece4680a8bdea84fa78166d0712108a95c"
version = "v1.1.15"
revision = "d67ddb98d5a1b7c79a8977ec2d552e1db45eda86"
[[projects]]
digest = "1:c79fb010be38a59d657c48c6ba1d003a8aa651fa56b579d959d74573b7dff8e1"

View file

@ -55,7 +55,7 @@
[[constraint]]
name = "github.com/google/gopacket"
version = "1.1.15"
revision = "d67ddb98d5a1b7c79a8977ec2d552e1db45eda86"
[[constraint]]
name = "github.com/gorilla/mux"

View file

@ -2,12 +2,15 @@ package packets
import (
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
)
type DHCPv6Layer struct {
Raw []byte
}
func (l *DHCPv6Layer) LayerType() gopacket.LayerType { return layers.LayerTypeDHCPv6 }
func (l DHCPv6Layer) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
bytes, err := b.PrependBytes(len(l.Raw))
if err != nil {

View file

@ -13,6 +13,7 @@ Hiroaki Kawai <Hiroaki.Kawai@gmail.com>
Lukas Lueg <lukas.lueg@gmail.com>
Laurent Hausermann <laurent.hausermann@gmail.com>
Bill Green <bgreen@newrelic.com>
Christian Mäder <christian.maeder@nine.ch>
CONTRIBUTORS:
Attila Oláh <attila@attilaolah.eu>
@ -26,6 +27,7 @@ Satoshi Matsumoto <kaorimatz@gmail.com>
David Stainton <dstainton415@gmail.com>
Jesse Ward <jesse@jesseward.com>
Kane Mathers <kane@kanemathers.name>
Jose Selvi <jselvi@pentester.es>
-----------------------------------------------
FORKED FROM github.com/akrennmair/gopcap

View file

@ -27,6 +27,12 @@ sctp.go
sflow.go
tcp.go
tcpip.go
tls.go
tls_alert.go
tls_appdata.go
tls_cipherspec.go
tls_hanshake.go
tls_test.go
udp.go
udplite.go
usb.go

View file

@ -188,7 +188,7 @@ func decodeDHCPv6(data []byte, p gopacket.PacketBuilder) error {
}
// DHCPv6StatusCode represents a DHCP status code - RFC-3315
type DHCPv6StatusCode byte
type DHCPv6StatusCode uint16
// Constants for the DHCPv6StatusCode.
const (

View file

@ -8,6 +8,7 @@ package layers
import (
"encoding/binary"
"errors"
"github.com/google/gopacket"
)
@ -52,19 +53,25 @@ func (gn *Geneve) LayerType() gopacket.LayerType { return LayerTypeGeneve }
func decodeGeneveOption(data []byte, gn *Geneve) (*GeneveOption, uint8) {
opt := &GeneveOption{}
opt.Class = binary.BigEndian.Uint16(data[0:1])
opt.Class = binary.BigEndian.Uint16(data[0:2])
opt.Type = data[2]
opt.Flags = data[3] >> 4
opt.Length = data[3] & 0xf
opt.Length = (data[3]&0xf)*4 + 4
opt.Data = make([]byte, opt.Length-4)
copy(opt.Data, data[4:opt.Length])
return opt, 4 + opt.Length
return opt, opt.Length
}
func (gn *Geneve) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
if len(data) < 7 {
df.SetTruncated()
return errors.New("geneve packet too short")
}
gn.Version = data[0] >> 7
gn.OptionsLength = data[0] & 0x3f
gn.OptionsLength = (data[0] & 0x3f) * 4
gn.OAMPacket = data[1]&0x80 > 0
gn.CriticalOption = data[1]&0x40 > 0
@ -74,12 +81,17 @@ func (gn *Geneve) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error
copy(buf[1:], data[4:7])
gn.VNI = binary.BigEndian.Uint32(buf[:])
offset, length := uint8(8), gn.OptionsLength
offset, length := uint8(8), int32(gn.OptionsLength)
if len(data) < int(length+7) {
df.SetTruncated()
return errors.New("geneve packet too short")
}
for length > 0 {
opt, len := decodeGeneveOption(data[offset:], gn)
gn.Options = append(gn.Options, opt)
length -= len
length -= int32(len)
offset += len
}

View file

@ -24,12 +24,21 @@ const (
ICMPv6TypeParameterProblem = 4
ICMPv6TypeEchoRequest = 128
ICMPv6TypeEchoReply = 129
// The following are from RFC 4861
ICMPv6TypeRouterSolicitation = 133
ICMPv6TypeRouterAdvertisement = 134
ICMPv6TypeNeighborSolicitation = 135
ICMPv6TypeNeighborAdvertisement = 136
ICMPv6TypeRedirect = 137
// The following are from RFC 2710
ICMPv6TypeMLDv1MulticastListenerQueryMessage = 130
ICMPv6TypeMLDv1MulticastListenerReportMessage = 131
ICMPv6TypeMLDv1MulticastListenerDoneMessage = 132
// The following are from RFC 3810
ICMPv6TypeMLDv2MulticastListenerReportMessageV2 = 143
)
const (
@ -234,6 +243,18 @@ func (i *ICMPv6) NextLayerType() gopacket.LayerType {
return LayerTypeICMPv6NeighborAdvertisement
case ICMPv6TypeRedirect:
return LayerTypeICMPv6Redirect
case ICMPv6TypeMLDv1MulticastListenerQueryMessage: // Same Code for MLDv1 Query and MLDv2 Query
if len(i.Payload) > 20 { // Only payload size differs
return LayerTypeMLDv2MulticastListenerQuery
} else {
return LayerTypeMLDv1MulticastListenerQuery
}
case ICMPv6TypeMLDv1MulticastListenerDoneMessage:
return LayerTypeMLDv1MulticastListenerDone
case ICMPv6TypeMLDv1MulticastListenerReportMessage:
return LayerTypeMLDv1MulticastListenerReport
case ICMPv6TypeMLDv2MulticastListenerReportMessageV2:
return LayerTypeMLDv2MulticastListenerReport
}
return gopacket.LayerTypePayload

View file

@ -17,7 +17,8 @@ import (
)
const (
IPv6HopByHopOptionJumbogram = 0xC2 // RFC 2675
// IPv6HopByHopOptionJumbogram code as defined in RFC 2675
IPv6HopByHopOptionJumbogram = 0xC2
)
const (
@ -42,10 +43,11 @@ type IPv6 struct {
}
// LayerType returns LayerTypeIPv6
func (i *IPv6) LayerType() gopacket.LayerType { return LayerTypeIPv6 }
func (ipv6 *IPv6) LayerType() gopacket.LayerType { return LayerTypeIPv6 }
func (i *IPv6) NetworkFlow() gopacket.Flow {
return gopacket.NewFlow(EndpointIPv6, i.SrcIP, i.DstIP)
// NetworkFlow returns this new Flow (EndpointIPv6, SrcIP, DstIP)
func (ipv6 *IPv6) NetworkFlow() gopacket.Flow {
return gopacket.NewFlow(EndpointIPv6, ipv6.SrcIP, ipv6.DstIP)
}
// Search for Jumbo Payload TLV in IPv6HopByHop and return (length, true) if found
@ -115,7 +117,7 @@ func setIPv6PayloadJumboLength(hbh []byte) error {
opt := hbh[offset]
if opt == 0 {
//Pad1
offset += 1
offset++
continue
}
optLen := int(hbh[offset+1])
@ -134,7 +136,7 @@ func setIPv6PayloadJumboLength(hbh []byte) error {
// SerializeTo writes the serialized form of this layer into the
// SerializationBuffer, implementing gopacket.SerializableLayer.
// See the docs for gopacket.SerializableLayer for more info.
func (ip6 *IPv6) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
func (ipv6 *IPv6) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
var jumbo bool
var err error
@ -145,11 +147,11 @@ func (ip6 *IPv6) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.Serialize
if opts.FixLengths {
// We need to set the length later because the hop-by-hop header may
// not exist or else need padding, so pLen may yet change
addIPv6JumboOption(ip6)
} else if ip6.HopByHop == nil {
addIPv6JumboOption(ipv6)
} else if ipv6.HopByHop == nil {
return fmt.Errorf("Cannot fit payload length of %d into IPv6 packet", pLen)
} else {
_, ok, err := getIPv6HopByHopJumboLength(ip6.HopByHop)
_, ok, err := getIPv6HopByHopJumboLength(ipv6.HopByHop)
if err != nil {
return err
}
@ -158,12 +160,22 @@ func (ip6 *IPv6) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.Serialize
}
}
}
if ip6.HopByHop != nil {
if ip6.NextHeader != IPProtocolIPv6HopByHop {
// Just fix it instead of throwing an error
ip6.NextHeader = IPProtocolIPv6HopByHop
hbhAlreadySerialized := false
if ipv6.HopByHop != nil {
for _, l := range b.Layers() {
if l == LayerTypeIPv6HopByHop {
hbhAlreadySerialized = true
break
}
err = ip6.HopByHop.SerializeTo(b, opts)
}
}
if ipv6.HopByHop != nil && !hbhAlreadySerialized {
if ipv6.NextHeader != IPProtocolIPv6HopByHop {
// Just fix it instead of throwing an error
ipv6.NextHeader = IPProtocolIPv6HopByHop
}
err = ipv6.HopByHop.SerializeTo(b, opts)
if err != nil {
return err
}
@ -176,6 +188,7 @@ func (ip6 *IPv6) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.Serialize
}
}
}
if !jumbo && pLen > ipv6MaxPayloadLength {
return errors.New("Cannot fit payload into IPv6 header")
}
@ -183,90 +196,94 @@ func (ip6 *IPv6) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.Serialize
if err != nil {
return err
}
bytes[0] = (ip6.Version << 4) | (ip6.TrafficClass >> 4)
bytes[1] = (ip6.TrafficClass << 4) | uint8(ip6.FlowLabel>>16)
binary.BigEndian.PutUint16(bytes[2:], uint16(ip6.FlowLabel))
bytes[0] = (ipv6.Version << 4) | (ipv6.TrafficClass >> 4)
bytes[1] = (ipv6.TrafficClass << 4) | uint8(ipv6.FlowLabel>>16)
binary.BigEndian.PutUint16(bytes[2:], uint16(ipv6.FlowLabel))
if opts.FixLengths {
if jumbo {
ip6.Length = 0
ipv6.Length = 0
} else {
ip6.Length = uint16(pLen)
ipv6.Length = uint16(pLen)
}
}
binary.BigEndian.PutUint16(bytes[4:], ip6.Length)
bytes[6] = byte(ip6.NextHeader)
bytes[7] = byte(ip6.HopLimit)
if err := ip6.AddressTo16(); err != nil {
binary.BigEndian.PutUint16(bytes[4:], ipv6.Length)
bytes[6] = byte(ipv6.NextHeader)
bytes[7] = byte(ipv6.HopLimit)
if err := ipv6.AddressTo16(); err != nil {
return err
}
copy(bytes[8:], ip6.SrcIP)
copy(bytes[24:], ip6.DstIP)
copy(bytes[8:], ipv6.SrcIP)
copy(bytes[24:], ipv6.DstIP)
return nil
}
func (ip6 *IPv6) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
ip6.Version = uint8(data[0]) >> 4
ip6.TrafficClass = uint8((binary.BigEndian.Uint16(data[0:2]) >> 4) & 0x00FF)
ip6.FlowLabel = binary.BigEndian.Uint32(data[0:4]) & 0x000FFFFF
ip6.Length = binary.BigEndian.Uint16(data[4:6])
ip6.NextHeader = IPProtocol(data[6])
ip6.HopLimit = data[7]
ip6.SrcIP = data[8:24]
ip6.DstIP = data[24:40]
ip6.HopByHop = nil
ip6.BaseLayer = BaseLayer{data[:40], data[40:]}
// DecodeFromBytes implementation according to gopacket.DecodingLayer
func (ipv6 *IPv6) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
ipv6.Version = uint8(data[0]) >> 4
ipv6.TrafficClass = uint8((binary.BigEndian.Uint16(data[0:2]) >> 4) & 0x00FF)
ipv6.FlowLabel = binary.BigEndian.Uint32(data[0:4]) & 0x000FFFFF
ipv6.Length = binary.BigEndian.Uint16(data[4:6])
ipv6.NextHeader = IPProtocol(data[6])
ipv6.HopLimit = data[7]
ipv6.SrcIP = data[8:24]
ipv6.DstIP = data[24:40]
ipv6.HopByHop = nil
ipv6.BaseLayer = BaseLayer{data[:40], data[40:]}
// We treat a HopByHop IPv6 option as part of the IPv6 packet, since its
// options are crucial for understanding what's actually happening per packet.
if ip6.NextHeader == IPProtocolIPv6HopByHop {
err := ip6.hbh.DecodeFromBytes(ip6.Payload, df)
if ipv6.NextHeader == IPProtocolIPv6HopByHop {
err := ipv6.hbh.DecodeFromBytes(ipv6.Payload, df)
if err != nil {
return err
}
ip6.HopByHop = &ip6.hbh
pEnd, jumbo, err := getIPv6HopByHopJumboLength(ip6.HopByHop)
ipv6.HopByHop = &ipv6.hbh
pEnd, jumbo, err := getIPv6HopByHopJumboLength(ipv6.HopByHop)
if err != nil {
return err
}
if jumbo && ip6.Length == 0 {
if jumbo && ipv6.Length == 0 {
pEnd := int(pEnd)
if pEnd > len(ip6.Payload) {
if pEnd > len(ipv6.Payload) {
df.SetTruncated()
pEnd = len(ip6.Payload)
pEnd = len(ipv6.Payload)
}
ip6.Payload = ip6.Payload[:pEnd]
ipv6.Payload = ipv6.Payload[:pEnd]
return nil
} else if jumbo && ip6.Length != 0 {
} else if jumbo && ipv6.Length != 0 {
return errors.New("IPv6 has jumbo length and IPv6 length is not 0")
} else if !jumbo && ip6.Length == 0 {
} else if !jumbo && ipv6.Length == 0 {
return errors.New("IPv6 length 0, but HopByHop header does not have jumbogram option")
} else {
ip6.Payload = ip6.Payload[ip6.hbh.ActualLength:]
ipv6.Payload = ipv6.Payload[ipv6.hbh.ActualLength:]
}
}
if ip6.Length == 0 {
return fmt.Errorf("IPv6 length 0, but next header is %v, not HopByHop", ip6.NextHeader)
} else {
pEnd := int(ip6.Length)
if pEnd > len(ip6.Payload) {
if ipv6.Length == 0 {
return fmt.Errorf("IPv6 length 0, but next header is %v, not HopByHop", ipv6.NextHeader)
}
pEnd := int(ipv6.Length)
if pEnd > len(ipv6.Payload) {
df.SetTruncated()
pEnd = len(ip6.Payload)
}
ip6.Payload = ip6.Payload[:pEnd]
pEnd = len(ipv6.Payload)
}
ipv6.Payload = ipv6.Payload[:pEnd]
return nil
}
func (i *IPv6) CanDecode() gopacket.LayerClass {
// CanDecode implementation according to gopacket.DecodingLayer
func (ipv6 *IPv6) CanDecode() gopacket.LayerClass {
return LayerTypeIPv6
}
func (i *IPv6) NextLayerType() gopacket.LayerType {
if i.HopByHop != nil {
return i.HopByHop.NextHeader.LayerType()
// NextLayerType implementation according to gopacket.DecodingLayer
func (ipv6 *IPv6) NextLayerType() gopacket.LayerType {
if ipv6.HopByHop != nil {
return ipv6.HopByHop.NextHeader.LayerType()
}
return i.NextHeader.LayerType()
return ipv6.NextHeader.LayerType()
}
func decodeIPv6(data []byte, p gopacket.PacketBuilder) error {
@ -403,6 +420,7 @@ type IPv6ExtensionSkipper struct {
BaseLayer
}
// DecodeFromBytes implementation according to gopacket.DecodingLayer
func (i *IPv6ExtensionSkipper) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
extension := decodeIPv6ExtensionBase(data)
i.BaseLayer = BaseLayer{data[:extension.ActualLength], data[extension.ActualLength:]}
@ -410,10 +428,12 @@ func (i *IPv6ExtensionSkipper) DecodeFromBytes(data []byte, df gopacket.DecodeFe
return nil
}
// CanDecode implementation according to gopacket.DecodingLayer
func (i *IPv6ExtensionSkipper) CanDecode() gopacket.LayerClass {
return LayerClassIPv6Extension
}
// NextLayerType implementation according to gopacket.DecodingLayer
func (i *IPv6ExtensionSkipper) NextLayerType() gopacket.LayerType {
return i.NextHeader.LayerType()
}
@ -430,6 +450,7 @@ type IPv6HopByHop struct {
// LayerType returns LayerTypeIPv6HopByHop.
func (i *IPv6HopByHop) LayerType() gopacket.LayerType { return LayerTypeIPv6HopByHop }
// SerializeTo implementation according to gopacket.SerializableLayer
func (i *IPv6HopByHop) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
var bytes []byte
var err error
@ -462,6 +483,7 @@ func (i *IPv6HopByHop) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.Ser
return nil
}
// DecodeFromBytes implementation according to gopacket.DecodingLayer
func (i *IPv6HopByHop) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
i.ipv6ExtensionBase = decodeIPv6ExtensionBase(data)
offset := 2
@ -483,6 +505,7 @@ func decodeIPv6HopByHop(data []byte, p gopacket.PacketBuilder) error {
return p.NextDecoder(i.NextHeader)
}
// SetJumboLength adds the IPv6HopByHopOptionJumbogram with the given length
func (o *IPv6HopByHopOption) SetJumboLength(len uint32) {
o.OptionType = IPv6HopByHopOptionJumbogram
o.OptionLength = 4
@ -575,6 +598,7 @@ type IPv6Destination struct {
// LayerType returns LayerTypeIPv6Destination.
func (i *IPv6Destination) LayerType() gopacket.LayerType { return LayerTypeIPv6Destination }
// DecodeFromBytes implementation according to gopacket.DecodingLayer
func (i *IPv6Destination) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
i.ipv6ExtensionBase = decodeIPv6ExtensionBase(data)
offset := 2
@ -641,11 +665,12 @@ func checkIPv6Address(addr net.IP) error {
return fmt.Errorf("wrong length of %d bytes instead of %d", len(addr), net.IPv6len)
}
func (ip *IPv6) AddressTo16() error {
if err := checkIPv6Address(ip.SrcIP); err != nil {
// AddressTo16 ensures IPv6.SrcIP and IPv6.DstIP are actually IPv6 addresses (i.e. 16 byte addresses)
func (ipv6 *IPv6) AddressTo16() error {
if err := checkIPv6Address(ipv6.SrcIP); err != nil {
return fmt.Errorf("Invalid source IPv6 address (%s)", err)
}
if err := checkIPv6Address(ip.DstIP); err != nil {
if err := checkIPv6Address(ipv6.DstIP); err != nil {
return fmt.Errorf("Invalid destination IPv6 address (%s)", err)
}
return nil

View file

@ -11,6 +11,7 @@ import (
)
var (
// Pending to set the proper number
LayerTypeARP = gopacket.RegisterLayerType(10, gopacket.LayerTypeMetadata{Name: "ARP", Decoder: gopacket.DecodeFunc(decodeARP)})
LayerTypeCiscoDiscovery = gopacket.RegisterLayerType(11, gopacket.LayerTypeMetadata{Name: "CiscoDiscovery", Decoder: gopacket.DecodeFunc(decodeCiscoDiscovery)})
LayerTypeEthernetCTP = gopacket.RegisterLayerType(12, gopacket.LayerTypeMetadata{Name: "EthernetCTP", Decoder: gopacket.DecodeFunc(decodeEthernetCTP)})
@ -136,6 +137,12 @@ var (
LayerTypeICMPv6Echo = gopacket.RegisterLayerType(132, gopacket.LayerTypeMetadata{Name: "ICMPv6Echo", Decoder: gopacket.DecodeFunc(decodeICMPv6Echo)})
LayerTypeSIP = gopacket.RegisterLayerType(133, gopacket.LayerTypeMetadata{Name: "SIP", Decoder: gopacket.DecodeFunc(decodeSIP)})
LayerTypeDHCPv6 = gopacket.RegisterLayerType(134, gopacket.LayerTypeMetadata{Name: "DHCPv6", Decoder: gopacket.DecodeFunc(decodeDHCPv6)})
LayerTypeMLDv1MulticastListenerReport = gopacket.RegisterLayerType(135, gopacket.LayerTypeMetadata{Name: "MLDv1MulticastListenerReport", Decoder: gopacket.DecodeFunc(decodeMLDv1MulticastListenerReport)})
LayerTypeMLDv1MulticastListenerDone = gopacket.RegisterLayerType(136, gopacket.LayerTypeMetadata{Name: "MLDv1MulticastListenerDone", Decoder: gopacket.DecodeFunc(decodeMLDv1MulticastListenerDone)})
LayerTypeMLDv1MulticastListenerQuery = gopacket.RegisterLayerType(137, gopacket.LayerTypeMetadata{Name: "MLDv1MulticastListenerQuery", Decoder: gopacket.DecodeFunc(decodeMLDv1MulticastListenerQuery)})
LayerTypeMLDv2MulticastListenerReport = gopacket.RegisterLayerType(138, gopacket.LayerTypeMetadata{Name: "MLDv2MulticastListenerReport", Decoder: gopacket.DecodeFunc(decodeMLDv2MulticastListenerReport)})
LayerTypeMLDv2MulticastListenerQuery = gopacket.RegisterLayerType(139, gopacket.LayerTypeMetadata{Name: "MLDv2MulticastListenerQuery", Decoder: gopacket.DecodeFunc(decodeMLDv2MulticastListenerQuery)})
LayerTypeTLS = gopacket.RegisterLayerType(140, gopacket.LayerTypeMetadata{Name: "TLS", Decoder: gopacket.DecodeFunc(decodeTLS)})
)
var (
@ -194,4 +201,18 @@ var (
LayerTypeICMPv6NeighborAdvertisement,
LayerTypeICMPv6Redirect,
})
// LayerClassMLDv1 contains multicast listener discovery protocol
LayerClassMLDv1 = gopacket.NewLayerClass([]gopacket.LayerType{
LayerTypeMLDv1MulticastListenerQuery,
LayerTypeMLDv1MulticastListenerReport,
LayerTypeMLDv1MulticastListenerDone,
})
// LayerClassMLDv2 contains multicast listener discovery protocol v2
LayerClassMLDv2 = gopacket.NewLayerClass([]gopacket.LayerType{
LayerTypeMLDv1MulticastListenerReport,
LayerTypeMLDv1MulticastListenerDone,
LayerTypeMLDv2MulticastListenerReport,
LayerTypeMLDv1MulticastListenerQuery,
LayerTypeMLDv2MulticastListenerQuery,
})
)

182
vendor/github.com/google/gopacket/layers/mldv1.go generated vendored Normal file
View file

@ -0,0 +1,182 @@
// Copyright 2018 GoPacket Authors. 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.
package layers
import (
"encoding/binary"
"errors"
"fmt"
"math"
"net"
"time"
"github.com/google/gopacket"
)
// MLDv1Message represents the common structure of all MLDv1 messages
type MLDv1Message struct {
BaseLayer
// 3.4. Maximum Response Delay
MaximumResponseDelay time.Duration
// 3.6. Multicast Address
// Zero in general query
// Specific IPv6 multicast address otherwise
MulticastAddress net.IP
}
// DecodeFromBytes decodes the given bytes into this layer.
func (m *MLDv1Message) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
if len(data) < 20 {
df.SetTruncated()
return errors.New("ICMP layer less than 20 bytes for Multicast Listener Query Message V1")
}
m.MaximumResponseDelay = time.Duration(binary.BigEndian.Uint16(data[0:2])) * time.Millisecond
// data[2:4] is reserved and not used in mldv1
m.MulticastAddress = data[4:20]
return nil
}
// NextLayerType returns the layer type contained by this DecodingLayer.
func (*MLDv1Message) NextLayerType() gopacket.LayerType {
return gopacket.LayerTypeZero
}
// SerializeTo writes the serialized form of this layer into the
// SerializationBuffer, implementing gopacket.SerializableLayer.
// See the docs for gopacket.SerializableLayer for more info.
func (m *MLDv1Message) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
buf, err := b.PrependBytes(20)
if err != nil {
return err
}
if m.MaximumResponseDelay < 0 {
return errors.New("maximum response delay must not be negative")
}
dms := m.MaximumResponseDelay / time.Millisecond
if dms > math.MaxUint16 {
return fmt.Errorf("maximum response delay %dms is more than the allowed 65535ms", dms)
}
binary.BigEndian.PutUint16(buf[0:2], uint16(dms))
copy(buf[2:4], []byte{0x0, 0x0})
ma16 := m.MulticastAddress.To16()
if ma16 == nil {
return fmt.Errorf("invalid multicast address '%s'", m.MulticastAddress)
}
copy(buf[4:20], ma16)
return nil
}
// Sums this layer up nicely formatted
func (m *MLDv1Message) String() string {
return fmt.Sprintf(
"Maximum Response Delay: %dms, Multicast Address: %s",
m.MaximumResponseDelay/time.Millisecond,
m.MulticastAddress)
}
// MLDv1MulticastListenerQueryMessage are sent by the router to determine
// whether there are multicast listeners on the link.
// https://tools.ietf.org/html/rfc2710 Page 5
type MLDv1MulticastListenerQueryMessage struct {
MLDv1Message
}
// DecodeFromBytes decodes the given bytes into this layer.
func (m *MLDv1MulticastListenerQueryMessage) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
err := m.MLDv1Message.DecodeFromBytes(data, df)
if err != nil {
return err
}
if len(data) > 20 {
m.Payload = data[20:]
}
return nil
}
// LayerType returns LayerTypeMLDv1MulticastListenerQuery.
func (*MLDv1MulticastListenerQueryMessage) LayerType() gopacket.LayerType {
return LayerTypeMLDv1MulticastListenerQuery
}
// CanDecode returns the set of layer types that this DecodingLayer can decode.
func (*MLDv1MulticastListenerQueryMessage) CanDecode() gopacket.LayerClass {
return LayerTypeMLDv1MulticastListenerQuery
}
// IsGeneralQuery is true when this is a general query.
// In a Query message, the Multicast Address field is set to zero when
// sending a General Query.
// https://tools.ietf.org/html/rfc2710#section-3.6
func (m *MLDv1MulticastListenerQueryMessage) IsGeneralQuery() bool {
return net.IPv6zero.Equal(m.MulticastAddress)
}
// IsSpecificQuery is true when this is not a general query.
// In a Query message, the Multicast Address field is set to a specific
// IPv6 multicast address when sending a Multicast-Address-Specific Query.
// https://tools.ietf.org/html/rfc2710#section-3.6
func (m *MLDv1MulticastListenerQueryMessage) IsSpecificQuery() bool {
return !m.IsGeneralQuery()
}
// MLDv1MulticastListenerReportMessage is sent by a client listening on
// a specific multicast address to indicate that it is (still) listening
// on the specific multicast address.
// https://tools.ietf.org/html/rfc2710 Page 6
type MLDv1MulticastListenerReportMessage struct {
MLDv1Message
}
// LayerType returns LayerTypeMLDv1MulticastListenerReport.
func (*MLDv1MulticastListenerReportMessage) LayerType() gopacket.LayerType {
return LayerTypeMLDv1MulticastListenerReport
}
// CanDecode returns the set of layer types that this DecodingLayer can decode.
func (*MLDv1MulticastListenerReportMessage) CanDecode() gopacket.LayerClass {
return LayerTypeMLDv1MulticastListenerReport
}
// MLDv1MulticastListenerDoneMessage should be sent by a client when it ceases
// to listen to a multicast address on an interface.
// https://tools.ietf.org/html/rfc2710 Page 7
type MLDv1MulticastListenerDoneMessage struct {
MLDv1Message
}
// LayerType returns LayerTypeMLDv1MulticastListenerDone.
func (*MLDv1MulticastListenerDoneMessage) LayerType() gopacket.LayerType {
return LayerTypeMLDv1MulticastListenerDone
}
// CanDecode returns the set of layer types that this DecodingLayer can decode.
func (*MLDv1MulticastListenerDoneMessage) CanDecode() gopacket.LayerClass {
return LayerTypeMLDv1MulticastListenerDone
}
func decodeMLDv1MulticastListenerReport(data []byte, p gopacket.PacketBuilder) error {
m := &MLDv1MulticastListenerReportMessage{}
return decodingLayerDecoder(m, data, p)
}
func decodeMLDv1MulticastListenerQuery(data []byte, p gopacket.PacketBuilder) error {
m := &MLDv1MulticastListenerQueryMessage{}
return decodingLayerDecoder(m, data, p)
}
func decodeMLDv1MulticastListenerDone(data []byte, p gopacket.PacketBuilder) error {
m := &MLDv1MulticastListenerDoneMessage{}
return decodingLayerDecoder(m, data, p)
}

619
vendor/github.com/google/gopacket/layers/mldv2.go generated vendored Normal file
View file

@ -0,0 +1,619 @@
// Copyright 2018 GoPacket Authors. 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.
package layers
import (
"encoding/binary"
"errors"
"fmt"
"math"
"net"
"time"
"github.com/google/gopacket"
)
const (
// S Flag bit is 1
mldv2STrue uint8 = 0x8
// S Flag value mask
// mldv2STrue & mldv2SMask == mldv2STrue // true
// 0x1 & mldv2SMask == mldv2STrue // true
// 0x0 & mldv2SMask == mldv2STrue // false
mldv2SMask uint8 = 0x8
// QRV value mask
mldv2QRVMask uint8 = 0x7
)
// MLDv2MulticastListenerQueryMessage are sent by multicast routers to query the
// multicast listening state of neighboring interfaces.
// https://tools.ietf.org/html/rfc3810#section-5.1
//
// Some information, like Maximum Response Code and Multicast Address are in the
// previous layer LayerTypeMLDv1MulticastListenerQuery
type MLDv2MulticastListenerQueryMessage struct {
BaseLayer
// 5.1.3. Maximum Response Delay COde
MaximumResponseCode uint16
// 5.1.5. Multicast Address
// Zero in general query
// Specific IPv6 multicast address otherwise
MulticastAddress net.IP
// 5.1.7. S Flag (Suppress Router-Side Processing)
SuppressRoutersideProcessing bool
// 5.1.8. QRV (Querier's Robustness Variable)
QueriersRobustnessVariable uint8
// 5.1.9. QQIC (Querier's Query Interval Code)
QueriersQueryIntervalCode uint8
// 5.1.10. Number of Sources (N)
NumberOfSources uint16
// 5.1.11 Source Address [i]
SourceAddresses []net.IP
}
// DecodeFromBytes decodes the given bytes into this layer.
func (m *MLDv2MulticastListenerQueryMessage) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
if len(data) < 24 {
df.SetTruncated()
return errors.New("ICMP layer less than 24 bytes for Multicast Listener Query Message V2")
}
m.MaximumResponseCode = binary.BigEndian.Uint16(data[0:2])
// ignore data[2:4] as per https://tools.ietf.org/html/rfc3810#section-5.1.4
m.MulticastAddress = data[4:20]
m.SuppressRoutersideProcessing = (data[20] & mldv2SMask) == mldv2STrue
m.QueriersRobustnessVariable = data[20] & mldv2QRVMask
m.QueriersQueryIntervalCode = data[21]
m.NumberOfSources = binary.BigEndian.Uint16(data[22:24])
var end int
for i := uint16(0); i < m.NumberOfSources; i++ {
begin := 24 + (int(i) * 16)
end = begin + 16
if end > len(data) {
df.SetTruncated()
return fmt.Errorf("ICMP layer less than %d bytes for Multicast Listener Query Message V2", end)
}
m.SourceAddresses = append(m.SourceAddresses, data[begin:end])
}
return nil
}
// NextLayerType returns the layer type contained by this DecodingLayer.
func (*MLDv2MulticastListenerQueryMessage) NextLayerType() gopacket.LayerType {
return gopacket.LayerTypeZero
}
// SerializeTo writes the serialized form of this layer into the
// SerializationBuffer, implementing gopacket.SerializableLayer.
// See the docs for gopacket.SerializableLayer for more info.
func (m *MLDv2MulticastListenerQueryMessage) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
if err := m.serializeSourceAddressesTo(b, opts); err != nil {
return err
}
buf, err := b.PrependBytes(24)
if err != nil {
return err
}
binary.BigEndian.PutUint16(buf[0:2], m.MaximumResponseCode)
copy(buf[2:4], []byte{0x00, 0x00}) // set reserved bytes to zero
ma16 := m.MulticastAddress.To16()
if ma16 == nil {
return fmt.Errorf("invalid MulticastAddress '%s'", m.MulticastAddress)
}
copy(buf[4:20], ma16)
byte20 := m.QueriersRobustnessVariable & mldv2QRVMask
if m.SuppressRoutersideProcessing {
byte20 |= mldv2STrue
} else {
byte20 &= ^mldv2STrue // the complement of mldv2STrue
}
byte20 &= 0x0F // set reserved bits to zero
buf[20] = byte20
binary.BigEndian.PutUint16(buf[22:24], m.NumberOfSources)
buf[21] = m.QueriersQueryIntervalCode
return nil
}
// writes each source address to the buffer preserving the order
func (m *MLDv2MulticastListenerQueryMessage) serializeSourceAddressesTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
numberOfSourceAddresses := len(m.SourceAddresses)
if numberOfSourceAddresses > math.MaxUint16 {
return fmt.Errorf(
"there are more than %d source addresses, but 65535 is the maximum number of supported addresses",
numberOfSourceAddresses)
}
if opts.FixLengths {
m.NumberOfSources = uint16(numberOfSourceAddresses)
}
lastSAIdx := numberOfSourceAddresses - 1
for k := range m.SourceAddresses {
i := lastSAIdx - k // reverse order
buf, err := b.PrependBytes(16)
if err != nil {
return err
}
sa16 := m.SourceAddresses[i].To16()
if sa16 == nil {
return fmt.Errorf("invalid source address [%d] '%s'", i, m.SourceAddresses[i])
}
copy(buf[0:16], sa16)
}
return nil
}
// String sums this layer up nicely formatted
func (m *MLDv2MulticastListenerQueryMessage) String() string {
return fmt.Sprintf(
"Maximum Response Code: %#x (%dms), Multicast Address: %s, Suppress Routerside Processing: %t, QRV: %#x, QQIC: %#x (%ds), Number of Source Address: %d (actual: %d), Source Addresses: %s",
m.MaximumResponseCode,
m.MaximumResponseDelay(),
m.MulticastAddress,
m.SuppressRoutersideProcessing,
m.QueriersRobustnessVariable,
m.QueriersQueryIntervalCode,
m.QQI()/time.Second,
m.NumberOfSources,
len(m.SourceAddresses),
m.SourceAddresses)
}
// LayerType returns LayerTypeMLDv2MulticastListenerQuery.
func (*MLDv2MulticastListenerQueryMessage) LayerType() gopacket.LayerType {
return LayerTypeMLDv2MulticastListenerQuery
}
// CanDecode returns the set of layer types that this DecodingLayer can decode.
func (*MLDv2MulticastListenerQueryMessage) CanDecode() gopacket.LayerClass {
return LayerTypeMLDv2MulticastListenerQuery
}
// QQI calculates the Querier's Query Interval based on the QQIC
// according to https://tools.ietf.org/html/rfc3810#section-5.1.9
func (m *MLDv2MulticastListenerQueryMessage) QQI() time.Duration {
data := m.QueriersQueryIntervalCode
if data < 128 {
return time.Second * time.Duration(data)
}
exp := uint16(data) & 0x70 >> 4
mant := uint16(data) & 0x0F
return time.Second * time.Duration(mant|0x1000<<(exp+3))
}
// SetQQI calculates and updates the Querier's Query Interval Code (QQIC)
// according to https://tools.ietf.org/html/rfc3810#section-5.1.9
func (m *MLDv2MulticastListenerQueryMessage) SetQQI(d time.Duration) error {
if d < 0 {
m.QueriersQueryIntervalCode = 0
return errors.New("QQI duration is negative")
}
if d == 0 {
m.QueriersQueryIntervalCode = 0
return nil
}
dms := d / time.Second
if dms < 128 {
m.QueriersQueryIntervalCode = uint8(dms)
}
if dms > 31744 { // mant=0xF, exp=0x7
m.QueriersQueryIntervalCode = 0xFF
return fmt.Errorf("QQI duration %ds is, maximum allowed is 31744s", dms)
}
value := uint16(dms) // ok, because 31744 < math.MaxUint16
exp := uint8(7)
for mask := uint16(0x4000); exp > 0; exp-- {
if mask&value != 0 {
break
}
mask >>= 1
}
mant := uint8(0x000F & (value >> (exp + 3)))
sig := uint8(0x10)
m.QueriersQueryIntervalCode = sig | exp<<4 | mant
return nil
}
// MaximumResponseDelay returns the Maximum Response Delay based on the
// Maximum Response Code according to
// https://tools.ietf.org/html/rfc3810#section-5.1.3
func (m *MLDv2MulticastListenerQueryMessage) MaximumResponseDelay() time.Duration {
if m.MaximumResponseCode < 0x8000 {
return time.Duration(m.MaximumResponseCode)
}
exp := m.MaximumResponseCode & 0x7000 >> 12
mant := m.MaximumResponseCode & 0x0FFF
return time.Millisecond * time.Duration(mant|0x1000<<(exp+3))
}
// SetMLDv2MaximumResponseDelay updates the Maximum Response Code according to
// https://tools.ietf.org/html/rfc3810#section-5.1.3
func (m *MLDv2MulticastListenerQueryMessage) SetMLDv2MaximumResponseDelay(d time.Duration) error {
if d == 0 {
m.MaximumResponseCode = 0
return nil
}
if d < 0 {
return errors.New("maximum response delay must not be negative")
}
dms := d / time.Millisecond
if dms < 32768 {
m.MaximumResponseCode = uint16(dms)
}
if dms > 4193280 { // mant=0xFFF, exp=0x7
return fmt.Errorf("maximum response delay %dms is bigger the than maximum of 4193280ms", dms)
}
value := uint32(dms) // ok, because 4193280 < math.MaxUint32
exp := uint8(7)
for mask := uint32(0x40000000); exp > 0; exp-- {
if mask&value != 0 {
break
}
mask >>= 1
}
mant := uint16(0x00000FFF & (value >> (exp + 3)))
sig := uint16(0x1000)
m.MaximumResponseCode = sig | uint16(exp)<<12 | mant
return nil
}
// MLDv2MulticastListenerReportMessage is sent by an IP node to report the
// current multicast listening state, or changes therein.
// https://tools.ietf.org/html/rfc3810#section-5.2
type MLDv2MulticastListenerReportMessage struct {
BaseLayer
// 5.2.3. Nr of Mcast Address Records
NumberOfMulticastAddressRecords uint16
// 5.2.4. Multicast Address Record [i]
MulticastAddressRecords []MLDv2MulticastAddressRecord
}
// DecodeFromBytes decodes the given bytes into this layer.
func (m *MLDv2MulticastListenerReportMessage) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
if len(data) < 4 {
df.SetTruncated()
return errors.New("ICMP layer less than 4 bytes for Multicast Listener Report Message V2")
}
// ignore data[0:2] as per RFC
// https://tools.ietf.org/html/rfc3810#section-5.2.1
m.NumberOfMulticastAddressRecords = binary.BigEndian.Uint16(data[2:4])
begin := 4
for i := uint16(0); i < m.NumberOfMulticastAddressRecords; i++ {
mar := MLDv2MulticastAddressRecord{}
read, err := mar.decode(data[begin:], df)
if err != nil {
return err
}
m.MulticastAddressRecords = append(m.MulticastAddressRecords, mar)
begin += read
}
return nil
}
// SerializeTo writes the serialized form of this layer into the
// SerializationBuffer, implementing gopacket.SerializableLayer.
// See the docs for gopacket.SerializableLayer for more info.
func (m *MLDv2MulticastListenerReportMessage) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
lastItemIdx := len(m.MulticastAddressRecords) - 1
for k := range m.MulticastAddressRecords {
i := lastItemIdx - k // reverse order
err := m.MulticastAddressRecords[i].serializeTo(b, opts)
if err != nil {
return err
}
}
if opts.FixLengths {
numberOfMAR := len(m.MulticastAddressRecords)
if numberOfMAR > math.MaxUint16 {
return fmt.Errorf(
"%d multicast address records added, but the maximum is 65535",
numberOfMAR)
}
m.NumberOfMulticastAddressRecords = uint16(numberOfMAR)
}
buf, err := b.PrependBytes(4)
if err != nil {
return err
}
copy(buf[0:2], []byte{0x0, 0x0})
binary.BigEndian.PutUint16(buf[2:4], m.NumberOfMulticastAddressRecords)
return nil
}
// Sums this layer up nicely formatted
func (m *MLDv2MulticastListenerReportMessage) String() string {
return fmt.Sprintf(
"Number of Mcast Addr Records: %d (actual %d), Multicast Address Records: %+v",
m.NumberOfMulticastAddressRecords,
len(m.MulticastAddressRecords),
m.MulticastAddressRecords)
}
// LayerType returns LayerTypeMLDv2MulticastListenerQuery.
func (*MLDv2MulticastListenerReportMessage) LayerType() gopacket.LayerType {
return LayerTypeMLDv2MulticastListenerReport
}
// CanDecode returns the set of layer types that this DecodingLayer can decode.
func (*MLDv2MulticastListenerReportMessage) CanDecode() gopacket.LayerClass {
return LayerTypeMLDv2MulticastListenerReport
}
// NextLayerType returns the layer type contained by this DecodingLayer.
func (*MLDv2MulticastListenerReportMessage) NextLayerType() gopacket.LayerType {
return gopacket.LayerTypePayload
}
// MLDv2MulticastAddressRecordType holds the type of a
// Multicast Address Record, according to
// https://tools.ietf.org/html/rfc3810#section-5.2.5 and
// https://tools.ietf.org/html/rfc3810#section-5.2.12
type MLDv2MulticastAddressRecordType uint8
const (
// MLDv2MulticastAddressRecordTypeModeIsIncluded stands for
// MODE_IS_INCLUDE - indicates that the interface has a filter
// mode of INCLUDE for the specified multicast address.
MLDv2MulticastAddressRecordTypeModeIsIncluded MLDv2MulticastAddressRecordType = 1
// MLDv2MulticastAddressRecordTypeModeIsExcluded stands for
// MODE_IS_EXCLUDE - indicates that the interface has a filter
// mode of EXCLUDE for the specified multicast address.
MLDv2MulticastAddressRecordTypeModeIsExcluded MLDv2MulticastAddressRecordType = 2
// MLDv2MulticastAddressRecordTypeChangeToIncludeMode stands for
// CHANGE_TO_INCLUDE_MODE - indicates that the interface has
// changed to INCLUDE filter mode for the specified multicast
// address.
MLDv2MulticastAddressRecordTypeChangeToIncludeMode MLDv2MulticastAddressRecordType = 3
// MLDv2MulticastAddressRecordTypeChangeToExcludeMode stands for
// CHANGE_TO_EXCLUDE_MODE - indicates that the interface has
// changed to EXCLUDE filter mode for the specified multicast
// address
MLDv2MulticastAddressRecordTypeChangeToExcludeMode MLDv2MulticastAddressRecordType = 4
// MLDv2MulticastAddressRecordTypeAllowNewSources stands for
// ALLOW_NEW_SOURCES - indicates that the Source Address [i]
// fields in this Multicast Address Record contain a list of
// the additional sources that the node wishes to listen to,
// for packets sent to the specified multicast address.
MLDv2MulticastAddressRecordTypeAllowNewSources MLDv2MulticastAddressRecordType = 5
// MLDv2MulticastAddressRecordTypeBlockOldSources stands for
// BLOCK_OLD_SOURCES - indicates that the Source Address [i]
// fields in this Multicast Address Record contain a list of
// the sources that the node no longer wishes to listen to,
// for packets sent to the specified multicast address.
MLDv2MulticastAddressRecordTypeBlockOldSources MLDv2MulticastAddressRecordType = 6
)
// Human readable record types
// Naming follows https://tools.ietf.org/html/rfc3810#section-5.2.12
func (m MLDv2MulticastAddressRecordType) String() string {
switch m {
case MLDv2MulticastAddressRecordTypeModeIsIncluded:
return "MODE_IS_INCLUDE"
case MLDv2MulticastAddressRecordTypeModeIsExcluded:
return "MODE_IS_EXCLUDE"
case MLDv2MulticastAddressRecordTypeChangeToIncludeMode:
return "CHANGE_TO_INCLUDE_MODE"
case MLDv2MulticastAddressRecordTypeChangeToExcludeMode:
return "CHANGE_TO_EXCLUDE_MODE"
case MLDv2MulticastAddressRecordTypeAllowNewSources:
return "ALLOW_NEW_SOURCES"
case MLDv2MulticastAddressRecordTypeBlockOldSources:
return "BLOCK_OLD_SOURCES"
default:
return fmt.Sprintf("UNKNOWN(%d)", m)
}
}
// MLDv2MulticastAddressRecord contains information on the sender listening to a
// single multicast address on the interface the report is sent.
// https://tools.ietf.org/html/rfc3810#section-5.2.4
type MLDv2MulticastAddressRecord struct {
// 5.2.5. Record Type
RecordType MLDv2MulticastAddressRecordType
// 5.2.6. Auxiliary Data Length (number of 32-bit words)
AuxDataLen uint8
// 5.2.7. Number Of Sources (N)
N uint16
// 5.2.8. Multicast Address
MulticastAddress net.IP
// 5.2.9 Source Address [i]
SourceAddresses []net.IP
// 5.2.10 Auxiliary Data
AuxiliaryData []byte
}
// decodes a multicast address record from bytes
func (m *MLDv2MulticastAddressRecord) decode(data []byte, df gopacket.DecodeFeedback) (int, error) {
if len(data) < 4 {
df.SetTruncated()
return 0, errors.New(
"Multicast Listener Report Message V2 layer less than 4 bytes for Multicast Address Record")
}
m.RecordType = MLDv2MulticastAddressRecordType(data[0])
m.AuxDataLen = data[1]
m.N = binary.BigEndian.Uint16(data[2:4])
m.MulticastAddress = data[4:20]
for i := uint16(0); i < m.N; i++ {
begin := 20 + (int(i) * 16)
end := begin + 16
if len(data) < end {
df.SetTruncated()
return begin, fmt.Errorf(
"Multicast Listener Report Message V2 layer less than %d bytes for Multicast Address Record", end)
}
m.SourceAddresses = append(m.SourceAddresses, data[begin:end])
}
expectedLengthWithouAuxData := 20 + (int(m.N) * 16)
expectedTotalLength := (int(m.AuxDataLen) * 4) + expectedLengthWithouAuxData // *4 because AuxDataLen are 32bit words
if len(data) < expectedTotalLength {
return expectedLengthWithouAuxData, fmt.Errorf(
"Multicast Listener Report Message V2 layer less than %d bytes for Multicast Address Record",
expectedLengthWithouAuxData)
}
m.AuxiliaryData = data[expectedLengthWithouAuxData:expectedTotalLength]
return expectedTotalLength, nil
}
// String sums this layer up nicely formatted
func (m *MLDv2MulticastAddressRecord) String() string {
return fmt.Sprintf(
"RecordType: %d (%s), AuxDataLen: %d [32-bit words], N: %d, Multicast Address: %s, SourceAddresses: %s, Auxiliary Data: %#x",
m.RecordType,
m.RecordType.String(),
m.AuxDataLen,
m.N,
m.MulticastAddress.To16(),
m.SourceAddresses,
m.AuxiliaryData)
}
// serializes a multicast address record
func (m *MLDv2MulticastAddressRecord) serializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
if err := m.serializeAuxiliaryDataTo(b, opts); err != nil {
return err
}
if err := m.serializeSourceAddressesTo(b, opts); err != nil {
return err
}
buf, err := b.PrependBytes(20)
if err != nil {
return err
}
buf[0] = uint8(m.RecordType)
buf[1] = m.AuxDataLen
binary.BigEndian.PutUint16(buf[2:4], m.N)
ma16 := m.MulticastAddress.To16()
if ma16 == nil {
return fmt.Errorf("invalid multicast address '%s'", m.MulticastAddress)
}
copy(buf[4:20], ma16)
return nil
}
// serializes the auxiliary data of a multicast address record
func (m *MLDv2MulticastAddressRecord) serializeAuxiliaryDataTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
if remainder := len(m.AuxiliaryData) % 4; remainder != 0 {
zeroWord := []byte{0x0, 0x0, 0x0, 0x0}
m.AuxiliaryData = append(m.AuxiliaryData, zeroWord[:remainder]...)
}
if opts.FixLengths {
auxDataLen := len(m.AuxiliaryData) / 4
if auxDataLen > math.MaxUint8 {
return fmt.Errorf("auxilary data is %d 32-bit words, but the maximum is 255 32-bit words", auxDataLen)
}
m.AuxDataLen = uint8(auxDataLen)
}
buf, err := b.PrependBytes(len(m.AuxiliaryData))
if err != nil {
return err
}
copy(buf, m.AuxiliaryData)
return nil
}
// serializes the source addresses of a multicast address record preserving the order
func (m *MLDv2MulticastAddressRecord) serializeSourceAddressesTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
if opts.FixLengths {
numberOfSourceAddresses := len(m.SourceAddresses)
if numberOfSourceAddresses > math.MaxUint16 {
return fmt.Errorf(
"%d source addresses added, but the maximum is 65535",
numberOfSourceAddresses)
}
m.N = uint16(numberOfSourceAddresses)
}
lastItemIdx := len(m.SourceAddresses) - 1
for k := range m.SourceAddresses {
i := lastItemIdx - k // reverse order
buf, err := b.PrependBytes(16)
if err != nil {
return err
}
sa16 := m.SourceAddresses[i].To16()
if sa16 == nil {
return fmt.Errorf("invalid source address [%d] '%s'", i, m.SourceAddresses[i])
}
copy(buf, sa16)
}
return nil
}
func decodeMLDv2MulticastListenerReport(data []byte, p gopacket.PacketBuilder) error {
m := &MLDv2MulticastListenerReportMessage{}
return decodingLayerDecoder(m, data, p)
}
func decodeMLDv2MulticastListenerQuery(data []byte, p gopacket.PacketBuilder) error {
m := &MLDv2MulticastListenerQueryMessage{}
return decodingLayerDecoder(m, data, p)
}

View file

@ -61,6 +61,15 @@ func (a TCPPort) LayerType() gopacket.LayerType {
var tcpPortLayerType = [65536]gopacket.LayerType{
53: LayerTypeDNS,
443: LayerTypeTLS, // https
636: LayerTypeTLS, // ldaps
989: LayerTypeTLS, // ftps-data
990: LayerTypeTLS, // ftps
992: LayerTypeTLS, // telnets
993: LayerTypeTLS, // imaps
994: LayerTypeTLS, // ircs
995: LayerTypeTLS, // pop3s
5061: LayerTypeTLS, // ips
}
// RegisterTCPPortLayerType creates a new mapping between a TCPPort

208
vendor/github.com/google/gopacket/layers/tls.go generated vendored Normal file
View file

@ -0,0 +1,208 @@
// Copyright 2018 The GoPacket Authors. 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.
package layers
import (
"encoding/binary"
"errors"
"github.com/google/gopacket"
)
// TLSType defines the type of data after the TLS Record
type TLSType uint8
// TLSType known values.
const (
TLSChangeCipherSpec TLSType = 20
TLSAlert TLSType = 21
TLSHandshake TLSType = 22
TLSApplicationData TLSType = 23
TLSUnknown TLSType = 255
)
// String shows the register type nicely formatted
func (tt TLSType) String() string {
switch tt {
default:
return "Unknown"
case TLSChangeCipherSpec:
return "Change Cipher Spec"
case TLSAlert:
return "Alert"
case TLSHandshake:
return "Handshake"
case TLSApplicationData:
return "Application Data"
}
}
// TLSVersion represents the TLS version in numeric format
type TLSVersion uint16
// Strings shows the TLS version nicely formatted
func (tv TLSVersion) String() string {
switch tv {
default:
return "Unknown"
case 0x0200:
return "SSL 2.0"
case 0x0300:
return "SSL 3.0"
case 0x0301:
return "TLS 1.0"
case 0x0302:
return "TLS 1.1"
case 0x0303:
return "TLS 1.2"
case 0x0304:
return "TLS 1.3"
}
}
// TLS is specified in RFC 5246
//
// TLS Record Protocol
// 0 1 2 3 4 5 6 7 8
// +--+--+--+--+--+--+--+--+
// | Content Type |
// +--+--+--+--+--+--+--+--+
// | Version (major) |
// +--+--+--+--+--+--+--+--+
// | Version (minor) |
// +--+--+--+--+--+--+--+--+
// | Length |
// +--+--+--+--+--+--+--+--+
// | Length |
// +--+--+--+--+--+--+--+--+
// TLS is actually a slide of TLSrecord structures
type TLS struct {
BaseLayer
// TLS Records
ChangeCipherSpec []TLSChangeCipherSpecRecord
Handshake []TLSHandshakeRecord
AppData []TLSAppDataRecord
Alert []TLSAlertRecord
}
// TLSRecordHeader contains all the information that each TLS Record types should have
type TLSRecordHeader struct {
ContentType TLSType
Version TLSVersion
Length uint16
}
// LayerType returns gopacket.LayerTypeTLS.
func (t *TLS) LayerType() gopacket.LayerType { return LayerTypeTLS }
// decodeTLS decodes the byte slice into a TLS type. It also
// setups the application Layer in PacketBuilder.
func decodeTLS(data []byte, p gopacket.PacketBuilder) error {
t := &TLS{}
err := t.DecodeFromBytes(data, p)
if err != nil {
return err
}
p.AddLayer(t)
p.SetApplicationLayer(t)
return nil
}
// DecodeFromBytes decodes the slice into the TLS struct.
func (t *TLS) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
t.BaseLayer.Contents = data
t.BaseLayer.Payload = nil
t.ChangeCipherSpec = t.ChangeCipherSpec[:0]
t.Handshake = t.Handshake[:0]
t.AppData = t.AppData[:0]
t.Alert = t.Alert[:0]
return t.decodeTLSRecords(data, df)
}
func (t *TLS) decodeTLSRecords(data []byte, df gopacket.DecodeFeedback) error {
if len(data) < 5 {
df.SetTruncated()
return errors.New("TLS record too short")
}
// since there are no further layers, the baselayer's content is
// pointing to this layer
t.BaseLayer = BaseLayer{Contents: data[:len(data)]}
var h TLSRecordHeader
h.ContentType = TLSType(data[0])
h.Version = TLSVersion(binary.BigEndian.Uint16(data[1:3]))
h.Length = binary.BigEndian.Uint16(data[3:5])
if h.ContentType.String() == "Unknown" {
return errors.New("Unknown TLS record type")
}
hl := 5 // header length
tl := hl + int(h.Length)
if len(data) < tl {
df.SetTruncated()
return errors.New("TLS packet length mismatch")
}
switch h.ContentType {
default:
return errors.New("Unknown TLS record type")
case TLSChangeCipherSpec:
var r TLSChangeCipherSpecRecord
e := r.decodeFromBytes(h, data[hl:tl], df)
if e != nil {
return e
}
t.ChangeCipherSpec = append(t.ChangeCipherSpec, r)
case TLSAlert:
var r TLSAlertRecord
e := r.decodeFromBytes(h, data[hl:tl], df)
if e != nil {
return e
}
t.Alert = append(t.Alert, r)
case TLSHandshake:
var r TLSHandshakeRecord
e := r.decodeFromBytes(h, data[hl:tl], df)
if e != nil {
return e
}
t.Handshake = append(t.Handshake, r)
case TLSApplicationData:
var r TLSAppDataRecord
e := r.decodeFromBytes(h, data[hl:tl], df)
if e != nil {
return e
}
t.AppData = append(t.AppData, r)
}
if len(data) == tl {
return nil
}
return t.decodeTLSRecords(data[tl:len(data)], df)
}
// CanDecode implements gopacket.DecodingLayer.
func (t *TLS) CanDecode() gopacket.LayerClass {
return LayerTypeTLS
}
// NextLayerType implements gopacket.DecodingLayer.
func (t *TLS) NextLayerType() gopacket.LayerType {
return gopacket.LayerTypeZero
}
// Payload returns nil, since TLS encrypted payload is inside TLSAppDataRecord
func (t *TLS) Payload() []byte {
return nil
}

165
vendor/github.com/google/gopacket/layers/tls_alert.go generated vendored Normal file
View file

@ -0,0 +1,165 @@
// Copyright 2018 The GoPacket Authors. 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.
package layers
import (
"errors"
"fmt"
"github.com/google/gopacket"
)
// TLSAlertLevel defines the alert level data type
type TLSAlertLevel uint8
// TLSAlertDescr defines the alert descrption data type
type TLSAlertDescr uint8
const (
TLSAlertWarning TLSAlertLevel = 1
TLSAlertFatal TLSAlertLevel = 2
TLSAlertUnknownLevel TLSAlertLevel = 255
TLSAlertCloseNotify TLSAlertDescr = 0
TLSAlertUnexpectedMessage TLSAlertDescr = 10
TLSAlertBadRecordMac TLSAlertDescr = 20
TLSAlertDecryptionFailedRESERVED TLSAlertDescr = 21
TLSAlertRecordOverflow TLSAlertDescr = 22
TLSAlertDecompressionFailure TLSAlertDescr = 30
TLSAlertHandshakeFailure TLSAlertDescr = 40
TLSAlertNoCertificateRESERVED TLSAlertDescr = 41
TLSAlertBadCertificate TLSAlertDescr = 42
TLSAlertUnsupportedCertificate TLSAlertDescr = 43
TLSAlertCertificateRevoked TLSAlertDescr = 44
TLSAlertCertificateExpired TLSAlertDescr = 45
TLSAlertCertificateUnknown TLSAlertDescr = 46
TLSAlertIllegalParameter TLSAlertDescr = 47
TLSAlertUnknownCa TLSAlertDescr = 48
TLSAlertAccessDenied TLSAlertDescr = 49
TLSAlertDecodeError TLSAlertDescr = 50
TLSAlertDecryptError TLSAlertDescr = 51
TLSAlertExportRestrictionRESERVED TLSAlertDescr = 60
TLSAlertProtocolVersion TLSAlertDescr = 70
TLSAlertInsufficientSecurity TLSAlertDescr = 71
TLSAlertInternalError TLSAlertDescr = 80
TLSAlertUserCanceled TLSAlertDescr = 90
TLSAlertNoRenegotiation TLSAlertDescr = 100
TLSAlertUnsupportedExtension TLSAlertDescr = 110
TLSAlertUnknownDescription TLSAlertDescr = 255
)
// TLS Alert
// 0 1 2 3 4 5 6 7 8
// +--+--+--+--+--+--+--+--+
// | Level |
// +--+--+--+--+--+--+--+--+
// | Description |
// +--+--+--+--+--+--+--+--+
// TLSAlertRecord contains all the information that each Alert Record type should have
type TLSAlertRecord struct {
TLSRecordHeader
Level TLSAlertLevel
Description TLSAlertDescr
EncryptedMsg []byte
}
// DecodeFromBytes decodes the slice into the TLS struct.
func (t *TLSAlertRecord) decodeFromBytes(h TLSRecordHeader, data []byte, df gopacket.DecodeFeedback) error {
// TLS Record Header
t.ContentType = h.ContentType
t.Version = h.Version
t.Length = h.Length
if len(data) < 2 {
df.SetTruncated()
return errors.New("TLS Alert packet too short")
}
if t.Length == 2 {
t.Level = TLSAlertLevel(data[0])
t.Description = TLSAlertDescr(data[1])
} else {
t.Level = TLSAlertUnknownLevel
t.Description = TLSAlertUnknownDescription
t.EncryptedMsg = data
}
return nil
}
// Strings shows the TLS alert level nicely formatted
func (al TLSAlertLevel) String() string {
switch al {
default:
return fmt.Sprintf("Unknown(%d)", al)
case TLSAlertWarning:
return "Warning"
case TLSAlertFatal:
return "Fatal"
}
}
// Strings shows the TLS alert description nicely formatted
func (ad TLSAlertDescr) String() string {
switch ad {
default:
return "Unknown"
case TLSAlertCloseNotify:
return "close_notify"
case TLSAlertUnexpectedMessage:
return "unexpected_message"
case TLSAlertBadRecordMac:
return "bad_record_mac"
case TLSAlertDecryptionFailedRESERVED:
return "decryption_failed_RESERVED"
case TLSAlertRecordOverflow:
return "record_overflow"
case TLSAlertDecompressionFailure:
return "decompression_failure"
case TLSAlertHandshakeFailure:
return "handshake_failure"
case TLSAlertNoCertificateRESERVED:
return "no_certificate_RESERVED"
case TLSAlertBadCertificate:
return "bad_certificate"
case TLSAlertUnsupportedCertificate:
return "unsupported_certificate"
case TLSAlertCertificateRevoked:
return "certificate_revoked"
case TLSAlertCertificateExpired:
return "certificate_expired"
case TLSAlertCertificateUnknown:
return "certificate_unknown"
case TLSAlertIllegalParameter:
return "illegal_parameter"
case TLSAlertUnknownCa:
return "unknown_ca"
case TLSAlertAccessDenied:
return "access_denied"
case TLSAlertDecodeError:
return "decode_error"
case TLSAlertDecryptError:
return "decrypt_error"
case TLSAlertExportRestrictionRESERVED:
return "export_restriction_RESERVED"
case TLSAlertProtocolVersion:
return "protocol_version"
case TLSAlertInsufficientSecurity:
return "insufficient_security"
case TLSAlertInternalError:
return "internal_error"
case TLSAlertUserCanceled:
return "user_canceled"
case TLSAlertNoRenegotiation:
return "no_renegotiation"
case TLSAlertUnsupportedExtension:
return "unsupported_extension"
}
}

View file

@ -0,0 +1,34 @@
// Copyright 2018 The GoPacket Authors. 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.
package layers
import (
"errors"
"github.com/google/gopacket"
)
// TLSAppDataRecord contains all the information that each AppData Record types should have
type TLSAppDataRecord struct {
TLSRecordHeader
Payload []byte
}
// DecodeFromBytes decodes the slice into the TLS struct.
func (t *TLSAppDataRecord) decodeFromBytes(h TLSRecordHeader, data []byte, df gopacket.DecodeFeedback) error {
// TLS Record Header
t.ContentType = h.ContentType
t.Version = h.Version
t.Length = h.Length
if len(data) != int(t.Length) {
return errors.New("TLS Application Data length mismatch")
}
t.Payload = data
return nil
}

View file

@ -0,0 +1,64 @@
// Copyright 2018 The GoPacket Authors. 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.
package layers
import (
"errors"
"github.com/google/gopacket"
)
// TLSchangeCipherSpec defines the message value inside ChangeCipherSpec Record
type TLSchangeCipherSpec uint8
const (
TLSChangecipherspecMessage TLSchangeCipherSpec = 1
TLSChangecipherspecUnknown TLSchangeCipherSpec = 255
)
// TLS Change Cipher Spec
// 0 1 2 3 4 5 6 7 8
// +--+--+--+--+--+--+--+--+
// | Message |
// +--+--+--+--+--+--+--+--+
// TLSChangeCipherSpecRecord defines the type of data inside ChangeCipherSpec Record
type TLSChangeCipherSpecRecord struct {
TLSRecordHeader
Message TLSchangeCipherSpec
}
// DecodeFromBytes decodes the slice into the TLS struct.
func (t *TLSChangeCipherSpecRecord) decodeFromBytes(h TLSRecordHeader, data []byte, df gopacket.DecodeFeedback) error {
// TLS Record Header
t.ContentType = h.ContentType
t.Version = h.Version
t.Length = h.Length
if len(data) != 1 {
df.SetTruncated()
return errors.New("TLS Change Cipher Spec record incorrect length")
}
t.Message = TLSchangeCipherSpec(data[0])
if t.Message != TLSChangecipherspecMessage {
t.Message = TLSChangecipherspecUnknown
}
return nil
}
// String shows the message value nicely formatted
func (ccs TLSchangeCipherSpec) String() string {
switch ccs {
default:
return "Unknown"
case TLSChangecipherspecMessage:
return "Change Cipher Spec Message"
}
}

View file

@ -0,0 +1,28 @@
// Copyright 2018 The GoPacket Authors. 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.
package layers
import (
"github.com/google/gopacket"
)
// TLSHandshakeRecord defines the structure of a Handshare Record
type TLSHandshakeRecord struct {
TLSRecordHeader
}
// DecodeFromBytes decodes the slice into the TLS struct.
func (t *TLSHandshakeRecord) decodeFromBytes(h TLSRecordHeader, data []byte, df gopacket.DecodeFeedback) error {
// TLS Record Header
t.ContentType = h.ContentType
t.Version = h.Version
t.Length = h.Length
// TODO
return nil
}

View file

@ -10,6 +10,7 @@ package layers
import (
"encoding/binary"
"fmt"
"github.com/google/gopacket"
)

View file

@ -116,7 +116,7 @@ func NewDecodingLayerParser(first LayerType, decoders ...DecodingLayer) *Decodin
// decodedLayers := make([]gopacket.LayerType, 0, 10)
// for {
// data, _, err := source.ReadPacketData()
// if err == nil {
// if err != nil {
// fmt.Println("Error reading packet data: ", err)
// continue
// }

View file

@ -154,6 +154,10 @@ const bpfInstructionBufferSize = 8 * MaxBpfInstructions
//
// Handles are already pcap_activate'd
type Handle struct {
// stop is set to a non-zero value by Handle.Close to signal to
// getNextBufPtrLocked to stop trying to read packets
// This must be the first entry to ensure alignment for sync.atomic
stop uint64
// cptr is the handle for the actual pcap C object.
cptr *C.pcap_t
timeout time.Duration
@ -161,9 +165,6 @@ type Handle struct {
deviceIndex int
mu sync.Mutex
closeMu sync.Mutex
// stop is set to a non-zero value by Handle.Close to signal to
// getNextBufPtrLocked to stop trying to read packets
stop uint64
// Since pointers to these objects are passed into a C function, if
// they're declared locally then the Go compiler thinks they may have

View file

@ -3,6 +3,7 @@
// 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.
// +build linux
package pcapgo

View file

@ -36,6 +36,8 @@ type SerializableLayer interface {
// LayerPayload. It just serializes based on struct fields, neither
// modifying nor using contents/payload.
SerializeTo(b SerializeBuffer, opts SerializeOptions) error
// LayerType returns the type of the layer that is being serialized to the buffer
LayerType() LayerType
}
// SerializeOptions provides options for behaviors that SerializableLayers may want to
@ -97,12 +99,19 @@ type SerializeBuffer interface {
// the byte slice returned by any previous call to Bytes() for this buffer
// should be considered invalidated.
Clear() error
// Layers returns all the Layers that have been successfully serialized into this buffer
// already.
Layers() []LayerType
// PushLayer adds the current Layer to the list of Layers that have been serialized
// into this buffer.
PushLayer(LayerType)
}
type serializeBuffer struct {
data []byte
start int
prepended, appended int
layers []LayerType
}
// NewSerializeBuffer creates a new instance of the default implementation of
@ -171,9 +180,18 @@ func (w *serializeBuffer) AppendBytes(num int) ([]byte, error) {
func (w *serializeBuffer) Clear() error {
w.start = w.prepended
w.data = w.data[:w.start]
w.layers = w.layers[:0]
return nil
}
func (w *serializeBuffer) Layers() []LayerType {
return w.layers
}
func (w *serializeBuffer) PushLayer(l LayerType) {
w.layers = append(w.layers, l)
}
// SerializeLayers clears the given write buffer, then writes all layers into it so
// they correctly wrap each other. Note that by clearing the buffer, it
// invalidates all slices previously returned by w.Bytes()
@ -193,6 +211,7 @@ func SerializeLayers(w SerializeBuffer, opts SerializeOptions, layers ...Seriali
if err != nil {
return err
}
w.PushLayer(layer.LayerType())
}
return nil
}