mirror of
https://github.com/bettercap/bettercap.git
synced 2025-03-12 04:36:03 -07:00
fix: updating gopacket to v1.1.16 fixed a bug which made wifi.recon off to timeout
This commit is contained in:
parent
4c5a776f86
commit
b450747f4e
Gopkg.lockGopkg.toml
modules
vendor/github.com/google/gopacket
.travis.golint.shAUTHORSREADME.mddoc.go
layers
dhcpv6.godhcpv6_options.godns.godot11.goenums.gogre.goicmp6msg.goip4.goip6.golayertypes.golinux_sll.gomodbustcp.goports.goppp.gosflow.gosip.gotcp.goudp.go
packet.gopcap
defs_windows_386.godefs_windows_amd64.godoc.gogenerate_defs.gopcap.gopcap_tester.gopcap_unix.gopcap_windows.go
pcapgo
time.go
4
Gopkg.lock
generated
4
Gopkg.lock
generated
@ -108,7 +108,7 @@
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:65e00adfb37f64ce3c24f139bc73db70bfe45224ebaf88250eff4038e32ac9cf"
|
||||
digest = "1:b23296076e13a960263285b98907623e5d45f12fc405b14da19c6afa2a113deb"
|
||||
name = "github.com/google/gopacket"
|
||||
packages = [
|
||||
".",
|
||||
@ -117,7 +117,7 @@
|
||||
"pcapgo",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "d67ddb98d5a1b7c79a8977ec2d552e1db45eda86"
|
||||
revision = "v1.1.16"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:c79fb010be38a59d657c48c6ba1d003a8aa651fa56b579d959d74573b7dff8e1"
|
||||
|
@ -57,7 +57,7 @@
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/google/gopacket"
|
||||
revision = "d67ddb98d5a1b7c79a8977ec2d552e1db45eda86"
|
||||
revision = "v1.1.16"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/gorilla/mux"
|
||||
|
@ -404,6 +404,7 @@ func (w *WiFiModule) Start() error {
|
||||
w.updateStats(dot11, packet)
|
||||
}
|
||||
}
|
||||
|
||||
w.pktSourceChanClosed = true
|
||||
})
|
||||
|
||||
@ -418,10 +419,8 @@ func (w *WiFiModule) Stop() error {
|
||||
if !w.pktSourceChanClosed {
|
||||
w.pktSourceChan <- nil
|
||||
}
|
||||
w.reads.Wait()
|
||||
// close the pcap handle to make the main for exit
|
||||
w.handle.Close()
|
||||
// close the pcap handle to make the main for exit
|
||||
// wait for the loop to exit.
|
||||
w.reads.Wait()
|
||||
})
|
||||
}
|
||||
|
2
vendor/github.com/google/gopacket/.travis.golint.sh
generated
vendored
2
vendor/github.com/google/gopacket/.travis.golint.sh
generated
vendored
@ -2,7 +2,7 @@
|
||||
|
||||
cd "$(dirname $0)"
|
||||
|
||||
go get github.com/golang/lint/golint
|
||||
go get golang.org/x/lint/golint
|
||||
DIRS=". tcpassembly tcpassembly/tcpreader ip4defrag reassembly macs pcapgo pcap afpacket pfring routing defrag/lcmdefrag"
|
||||
# Add subdirectories here as we clean up golint on each.
|
||||
for subdir in $DIRS; do
|
||||
|
3
vendor/github.com/google/gopacket/AUTHORS
generated
vendored
3
vendor/github.com/google/gopacket/AUTHORS
generated
vendored
@ -14,6 +14,8 @@ Lukas Lueg <lukas.lueg@gmail.com>
|
||||
Laurent Hausermann <laurent.hausermann@gmail.com>
|
||||
Bill Green <bgreen@newrelic.com>
|
||||
Christian Mäder <christian.maeder@nine.ch>
|
||||
Gernot Vormayr <gvormayr@gmail.com>
|
||||
Vitor Garcia Graveto <victor.graveto@gmail.com>
|
||||
|
||||
CONTRIBUTORS:
|
||||
Attila Oláh <attila@attilaolah.eu>
|
||||
@ -28,6 +30,7 @@ David Stainton <dstainton415@gmail.com>
|
||||
Jesse Ward <jesse@jesseward.com>
|
||||
Kane Mathers <kane@kanemathers.name>
|
||||
Jose Selvi <jselvi@pentester.es>
|
||||
Yerden Zhumabekov <yerden.zhumabekov@gmail.com>
|
||||
|
||||
-----------------------------------------------
|
||||
FORKED FROM github.com/akrennmair/gopcap
|
||||
|
2
vendor/github.com/google/gopacket/README.md
generated
vendored
2
vendor/github.com/google/gopacket/README.md
generated
vendored
@ -6,5 +6,7 @@ See [godoc](https://godoc.org/github.com/google/gopacket) for more details.
|
||||
[](https://travis-ci.org/google/gopacket)
|
||||
[](https://godoc.org/github.com/google/gopacket)
|
||||
|
||||
Minimum Go version required is 1.5.
|
||||
|
||||
Originally forked from the gopcap project written by Andreas
|
||||
Krennmair <ak@synflood.at> (http://github.com/akrennmair/gopcap).
|
||||
|
7
vendor/github.com/google/gopacket/doc.go
generated
vendored
7
vendor/github.com/google/gopacket/doc.go
generated
vendored
@ -22,6 +22,8 @@ useful, including:
|
||||
Also, if you're looking to dive right into code, see the examples subdirectory
|
||||
for numerous simple binaries built using gopacket libraries.
|
||||
|
||||
Minimum go version required is 1.5.
|
||||
|
||||
Basic Usage
|
||||
|
||||
gopacket takes in packet data as a []byte and decodes it into a packet with
|
||||
@ -288,7 +290,10 @@ the packet's information. A quick example:
|
||||
parser := gopacket.NewDecodingLayerParser(layers.LayerTypeEthernet, ð, &ip4, &ip6, &tcp)
|
||||
decoded := []gopacket.LayerType{}
|
||||
for packetData := range somehowGetPacketData() {
|
||||
err := parser.DecodeLayers(packetData, &decoded)
|
||||
if err := parser.DecodeLayers(packetData, &decoded); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Could not decode layers: %v\n", err)
|
||||
continue
|
||||
}
|
||||
for _, layerType := range decoded {
|
||||
switch layerType {
|
||||
case layers.LayerTypeIPv6:
|
||||
|
156
vendor/github.com/google/gopacket/layers/dhcpv6.go
generated
vendored
156
vendor/github.com/google/gopacket/layers/dhcpv6.go
generated
vendored
@ -7,7 +7,6 @@
|
||||
package layers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
@ -158,7 +157,7 @@ func (d *DHCPv6) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.Serialize
|
||||
|
||||
if len(d.Options) > 0 {
|
||||
for _, o := range d.Options {
|
||||
if err := o.encode(data[offset:]); err != nil {
|
||||
if err := o.encode(data[offset:], opts); err != nil {
|
||||
return err
|
||||
}
|
||||
offset += int(o.Length) + 4 // 2 from option code, 2 from option length
|
||||
@ -220,159 +219,6 @@ func (o DHCPv6StatusCode) String() string {
|
||||
}
|
||||
}
|
||||
|
||||
// DHCPv6Opt represents a DHCP option or parameter from RFC-3315
|
||||
type DHCPv6Opt uint16
|
||||
|
||||
// Constants for the DHCPv6Opt options.
|
||||
const (
|
||||
DHCPv6OptClientID DHCPv6Opt = 1
|
||||
DHCPv6OptServerID DHCPv6Opt = 2
|
||||
DHCPv6OptIANA DHCPv6Opt = 3
|
||||
DHCPv6OptIATA DHCPv6Opt = 4
|
||||
DHCPv6OptIAAddr DHCPv6Opt = 5
|
||||
DHCPv6OptOro DHCPv6Opt = 6
|
||||
DHCPv6OptPreference DHCPv6Opt = 7
|
||||
DHCPv6OptElapsedTime DHCPv6Opt = 8
|
||||
DHCPv6OptRelayMessage DHCPv6Opt = 9
|
||||
DHCPv6OptAuth DHCPv6Opt = 11
|
||||
DHCPv6OptUnicast DHCPv6Opt = 12
|
||||
DHCPv6OptStatusCode DHCPv6Opt = 13
|
||||
DHCPv6OptRapidCommit DHCPv6Opt = 14
|
||||
DHCPv6OptUserClass DHCPv6Opt = 15
|
||||
DHCPv6OptVendorClass DHCPv6Opt = 16
|
||||
DHCPv6OptVendorOpts DHCPv6Opt = 17
|
||||
DHCPv6OptInterfaceID DHCPv6Opt = 18
|
||||
DHCPv6OptReconfigureMessage DHCPv6Opt = 19
|
||||
DHCPv6OptReconfigureAccept DHCPv6Opt = 20
|
||||
)
|
||||
|
||||
// String returns a string version of a DHCPv6Opt.
|
||||
func (o DHCPv6Opt) String() string {
|
||||
switch o {
|
||||
case DHCPv6OptClientID:
|
||||
return "ClientID"
|
||||
case DHCPv6OptServerID:
|
||||
return "ServerID"
|
||||
case DHCPv6OptIANA:
|
||||
return "IA_NA"
|
||||
case DHCPv6OptIATA:
|
||||
return "IA_TA"
|
||||
case DHCPv6OptIAAddr:
|
||||
return "IAAddr"
|
||||
case DHCPv6OptOro:
|
||||
return "Oro"
|
||||
case DHCPv6OptPreference:
|
||||
return "Preference"
|
||||
case DHCPv6OptElapsedTime:
|
||||
return "ElapsedTime"
|
||||
case DHCPv6OptRelayMessage:
|
||||
return "RelayMessage"
|
||||
case DHCPv6OptAuth:
|
||||
return "Auth"
|
||||
case DHCPv6OptUnicast:
|
||||
return "Unicast"
|
||||
case DHCPv6OptStatusCode:
|
||||
return "StatusCode"
|
||||
case DHCPv6OptRapidCommit:
|
||||
return "RapidCommit"
|
||||
case DHCPv6OptUserClass:
|
||||
return "UserClass"
|
||||
case DHCPv6OptVendorClass:
|
||||
return "VendorClass"
|
||||
case DHCPv6OptVendorOpts:
|
||||
return "VendorOpts"
|
||||
case DHCPv6OptInterfaceID:
|
||||
return "InterfaceID"
|
||||
case DHCPv6OptReconfigureMessage:
|
||||
return "ReconfigureMessage"
|
||||
case DHCPv6OptReconfigureAccept:
|
||||
return "ReconfigureAccept"
|
||||
default:
|
||||
return "Unknown"
|
||||
}
|
||||
}
|
||||
|
||||
// DHCPv6Options is used to get nicely printed option lists which would normally
|
||||
// be cut off after 5 options.
|
||||
type DHCPv6Options []DHCPv6Option
|
||||
|
||||
// String returns a string version of the options list.
|
||||
func (o DHCPv6Options) String() string {
|
||||
buf := &bytes.Buffer{}
|
||||
buf.WriteByte('[')
|
||||
for i, opt := range o {
|
||||
buf.WriteString(opt.String())
|
||||
if i+1 != len(o) {
|
||||
buf.WriteString(", ")
|
||||
}
|
||||
}
|
||||
buf.WriteByte(']')
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// DHCPv6Option rerpresents a DHCP option.
|
||||
type DHCPv6Option struct {
|
||||
Code DHCPv6Opt
|
||||
Length uint16
|
||||
Data []byte
|
||||
}
|
||||
|
||||
// String returns a string version of a DHCP Option.
|
||||
func (o DHCPv6Option) String() string {
|
||||
switch o.Code {
|
||||
case DHCPv6OptClientID, DHCPv6OptServerID:
|
||||
duid, err := decodeDHCPv6DUID(o.Data)
|
||||
if err != nil {
|
||||
return fmt.Sprintf("Option(%s:INVALID)", o.Code)
|
||||
}
|
||||
return fmt.Sprintf("Option(%s:[%s])", o.Code, duid.String())
|
||||
case DHCPv6OptOro:
|
||||
options := ""
|
||||
for i := 0; i < int(o.Length); i += 2 {
|
||||
if options != "" {
|
||||
options += ","
|
||||
}
|
||||
option := DHCPv6Opt(binary.BigEndian.Uint16(o.Data[i : i+2]))
|
||||
options += option.String()
|
||||
}
|
||||
return fmt.Sprintf("Option(%s:[%s])", o.Code, options)
|
||||
default:
|
||||
return fmt.Sprintf("Option(%s:%v)", o.Code, o.Data)
|
||||
}
|
||||
}
|
||||
|
||||
// NewDHCPv6Option constructs a new DHCPv6Option with a given type and data.
|
||||
func NewDHCPv6Option(code DHCPv6Opt, data []byte) DHCPv6Option {
|
||||
o := DHCPv6Option{Code: code}
|
||||
if data != nil {
|
||||
o.Data = data
|
||||
o.Length = uint16(len(data))
|
||||
}
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
func (o *DHCPv6Option) encode(b []byte) error {
|
||||
binary.BigEndian.PutUint16(b[0:2], uint16(o.Code))
|
||||
binary.BigEndian.PutUint16(b[2:4], o.Length)
|
||||
copy(b[4:], o.Data)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *DHCPv6Option) decode(data []byte) error {
|
||||
if len(data) < 2 {
|
||||
return errors.New("Not enough data to decode")
|
||||
}
|
||||
o.Code = DHCPv6Opt(binary.BigEndian.Uint16(data[0:2]))
|
||||
if len(data) < 3 {
|
||||
return errors.New("Not enough data to decode")
|
||||
}
|
||||
o.Length = binary.BigEndian.Uint16(data[2:4])
|
||||
o.Data = data[4 : 4+o.Length]
|
||||
return nil
|
||||
}
|
||||
|
||||
// DHCPv6DUIDType represents a DHCP DUID - RFC-3315
|
||||
type DHCPv6DUIDType uint16
|
||||
|
||||
|
621
vendor/github.com/google/gopacket/layers/dhcpv6_options.go
generated
vendored
Normal file
621
vendor/github.com/google/gopacket/layers/dhcpv6_options.go
generated
vendored
Normal file
@ -0,0 +1,621 @@
|
||||
// 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 (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/google/gopacket"
|
||||
)
|
||||
|
||||
// DHCPv6Opt represents a DHCP option or parameter from RFC-3315
|
||||
type DHCPv6Opt uint16
|
||||
|
||||
// Constants for the DHCPv6Opt options.
|
||||
const (
|
||||
DHCPv6OptClientID DHCPv6Opt = 1
|
||||
DHCPv6OptServerID DHCPv6Opt = 2
|
||||
DHCPv6OptIANA DHCPv6Opt = 3
|
||||
DHCPv6OptIATA DHCPv6Opt = 4
|
||||
DHCPv6OptIAAddr DHCPv6Opt = 5
|
||||
DHCPv6OptOro DHCPv6Opt = 6
|
||||
DHCPv6OptPreference DHCPv6Opt = 7
|
||||
DHCPv6OptElapsedTime DHCPv6Opt = 8
|
||||
DHCPv6OptRelayMessage DHCPv6Opt = 9
|
||||
DHCPv6OptAuth DHCPv6Opt = 11
|
||||
DHCPv6OptUnicast DHCPv6Opt = 12
|
||||
DHCPv6OptStatusCode DHCPv6Opt = 13
|
||||
DHCPv6OptRapidCommit DHCPv6Opt = 14
|
||||
DHCPv6OptUserClass DHCPv6Opt = 15
|
||||
DHCPv6OptVendorClass DHCPv6Opt = 16
|
||||
DHCPv6OptVendorOpts DHCPv6Opt = 17
|
||||
DHCPv6OptInterfaceID DHCPv6Opt = 18
|
||||
DHCPv6OptReconfigureMessage DHCPv6Opt = 19
|
||||
DHCPv6OptReconfigureAccept DHCPv6Opt = 20
|
||||
|
||||
// RFC 3319 Session Initiation Protocol (SIP)
|
||||
DHCPv6OptSIPServersDomainList DHCPv6Opt = 21
|
||||
DHCPv6OptSIPServersAddressList DHCPv6Opt = 22
|
||||
|
||||
// RFC 3646 DNS Configuration
|
||||
DHCPv6OptDNSServers DHCPv6Opt = 23
|
||||
DHCPv6OptDomainList DHCPv6Opt = 24
|
||||
|
||||
// RFC 3633 Prefix Delegation
|
||||
DHCPv6OptIAPD DHCPv6Opt = 25
|
||||
DHCPv6OptIAPrefix DHCPv6Opt = 26
|
||||
|
||||
// RFC 3898 Network Information Service (NIS)
|
||||
DHCPv6OptNISServers DHCPv6Opt = 27
|
||||
DHCPv6OptNISPServers DHCPv6Opt = 28
|
||||
DHCPv6OptNISDomainName DHCPv6Opt = 29
|
||||
DHCPv6OptNISPDomainName DHCPv6Opt = 30
|
||||
|
||||
// RFC 4075 Simple Network Time Protocol (SNTP)
|
||||
DHCPv6OptSNTPServers DHCPv6Opt = 31
|
||||
|
||||
// RFC 4242 Information Refresh Time Option
|
||||
DHCPv6OptInformationRefreshTime DHCPv6Opt = 32
|
||||
|
||||
// RFC 4280 Broadcast and Multicast Control Servers
|
||||
DHCPv6OptBCMCSServerDomainNameList DHCPv6Opt = 33
|
||||
DHCPv6OptBCMCSServerAddressList DHCPv6Opt = 34
|
||||
|
||||
// RFC 4776 Civic Address ConfigurationOption
|
||||
DHCPv6OptGeoconfCivic DHCPv6Opt = 36
|
||||
|
||||
// RFC 4649 Relay Agent Remote-ID
|
||||
DHCPv6OptRemoteID DHCPv6Opt = 37
|
||||
|
||||
// RFC 4580 Relay Agent Subscriber-ID
|
||||
DHCPv6OptSubscriberID DHCPv6Opt = 38
|
||||
|
||||
// RFC 4704 Client Full Qualified Domain Name (FQDN)
|
||||
DHCPv6OptClientFQDN DHCPv6Opt = 39
|
||||
|
||||
// RFC 5192 Protocol for Carrying Authentication for Network Access (PANA)
|
||||
DHCPv6OptPanaAgent DHCPv6Opt = 40
|
||||
|
||||
// RFC 4833 Timezone Options
|
||||
DHCPv6OptNewPOSIXTimezone DHCPv6Opt = 41
|
||||
DHCPv6OptNewTZDBTimezone DHCPv6Opt = 42
|
||||
|
||||
// RFC 4994 Relay Agent Echo Request
|
||||
DHCPv6OptEchoRequestOption DHCPv6Opt = 43
|
||||
|
||||
// RFC 5007 Leasequery
|
||||
DHCPv6OptLQQuery DHCPv6Opt = 44
|
||||
DHCPv6OptCLTTime DHCPv6Opt = 45
|
||||
DHCPv6OptClientData DHCPv6Opt = 46
|
||||
DHCPv6OptLQRelayData DHCPv6Opt = 47
|
||||
DHCPv6OptLQClientLink DHCPv6Opt = 48
|
||||
|
||||
// RFC 6610 Home Information Discovery in Mobile IPv6 (MIPv6)
|
||||
DHCPv6OptMIP6HNIDF DHCPv6Opt = 49
|
||||
DHCPv6OptMIP6VDINF DHCPv6Opt = 50
|
||||
DHCPv6OptMIP6IDINF DHCPv6Opt = 69
|
||||
DHCPv6OptMIP6UDINF DHCPv6Opt = 70
|
||||
DHCPv6OptMIP6HNP DHCPv6Opt = 71
|
||||
DHCPv6OptMIP6HAA DHCPv6Opt = 72
|
||||
DHCPv6OptMIP6HAF DHCPv6Opt = 73
|
||||
|
||||
// RFC 5223 Discovering Location-to-Service Translation (LoST) Servers
|
||||
DHCPv6OptV6LOST DHCPv6Opt = 51
|
||||
|
||||
// RFC 5417 Control And Provisioning of Wireless Access Points (CAPWAP)
|
||||
DHCPv6OptCAPWAPACV6 DHCPv6Opt = 52
|
||||
|
||||
// RFC 5460 Bulk Leasequery
|
||||
DHCPv6OptRelayID DHCPv6Opt = 53
|
||||
|
||||
// RFC 5678 IEEE 802.21 Mobility Services (MoS) Discovery
|
||||
DHCPv6OptIPv6AddressMoS DHCPv6Opt = 54
|
||||
DHCPv6OptIPv6FQDNMoS DHCPv6Opt = 55
|
||||
|
||||
// RFC 5908 NTP Server Option
|
||||
DHCPv6OptNTPServer DHCPv6Opt = 56
|
||||
|
||||
// RFC 5986 Discovering the Local Location Information Server (LIS)
|
||||
DHCPv6OptV6AccessDomain DHCPv6Opt = 57
|
||||
|
||||
// RFC 5986 SIP User Agent
|
||||
DHCPv6OptSIPUACSList DHCPv6Opt = 58
|
||||
|
||||
// RFC 5970 Options for Network Boot
|
||||
DHCPv6OptBootFileURL DHCPv6Opt = 59
|
||||
DHCPv6OptBootFileParam DHCPv6Opt = 60
|
||||
DHCPv6OptClientArchType DHCPv6Opt = 61
|
||||
DHCPv6OptNII DHCPv6Opt = 62
|
||||
|
||||
// RFC 6225 Coordinate-Based Location Configuration Information
|
||||
DHCPv6OptGeolocation DHCPv6Opt = 63
|
||||
|
||||
// RFC 6334 Dual-Stack Lite
|
||||
DHCPv6OptAFTRName DHCPv6Opt = 64
|
||||
|
||||
// RFC 6440 EAP Re-authentication Protocol (ERP)
|
||||
DHCPv6OptERPLocalDomainName DHCPv6Opt = 65
|
||||
|
||||
// RFC 6422 Relay-Supplied DHCP Options
|
||||
DHCPv6OptRSOO DHCPv6Opt = 66
|
||||
|
||||
// RFC 6603 Prefix Exclude Option for DHCPv6-based Prefix Delegation
|
||||
DHCPv6OptPDExclude DHCPv6Opt = 67
|
||||
|
||||
// RFC 6607 Virtual Subnet Selection
|
||||
DHCPv6OptVSS DHCPv6Opt = 68
|
||||
|
||||
// RFC 6731 Improved Recursive DNS Server Selection for Multi-Interfaced Nodes
|
||||
DHCPv6OptRDNSSSelection DHCPv6Opt = 74
|
||||
|
||||
// RFC 6784 Kerberos Options for DHCPv6
|
||||
DHCPv6OptKRBPrincipalName DHCPv6Opt = 75
|
||||
DHCPv6OptKRBRealmName DHCPv6Opt = 76
|
||||
DHCPv6OptKRBKDC DHCPv6Opt = 77
|
||||
|
||||
// RFC 6939 Client Link-Layer Address Option
|
||||
DHCPv6OptClientLinkLayerAddress DHCPv6Opt = 79
|
||||
|
||||
// RFC 6977 Triggering DHCPv6 Reconfiguration from Relay Agents
|
||||
DHCPv6OptLinkAddress DHCPv6Opt = 80
|
||||
|
||||
// RFC 7037 RADIUS Option for the DHCPv6 Relay Agent
|
||||
DHCPv6OptRADIUS DHCPv6Opt = 81
|
||||
|
||||
// RFC 7083 Modification to Default Values of SOL_MAX_RT and INF_MAX_RT
|
||||
DHCPv6OptSolMaxRt DHCPv6Opt = 82
|
||||
DHCPv6OptInfMaxRt DHCPv6Opt = 83
|
||||
|
||||
// RFC 7078 Distributing Address Selection Policy
|
||||
DHCPv6OptAddrSel DHCPv6Opt = 84
|
||||
DHCPv6OptAddrSelTable DHCPv6Opt = 85
|
||||
|
||||
// RFC 7291 DHCP Options for the Port Control Protocol (PCP)
|
||||
DHCPv6OptV6PCPServer DHCPv6Opt = 86
|
||||
|
||||
// RFC 7341 DHCPv4-over-DHCPv6 (DHCP 4o6) Transport
|
||||
DHCPv6OptDHCPv4Message DHCPv6Opt = 87
|
||||
DHCPv6OptDHCPv4OverDHCPv6Server DHCPv6Opt = 88
|
||||
|
||||
// RFC 7598 Configuration of Softwire Address and Port-Mapped Clients
|
||||
DHCPv6OptS46Rule DHCPv6Opt = 89
|
||||
DHCPv6OptS46BR DHCPv6Opt = 90
|
||||
DHCPv6OptS46DMR DHCPv6Opt = 91
|
||||
DHCPv6OptS46V4V4Bind DHCPv6Opt = 92
|
||||
DHCPv6OptS46PortParameters DHCPv6Opt = 93
|
||||
DHCPv6OptS46ContMAPE DHCPv6Opt = 94
|
||||
DHCPv6OptS46ContMAPT DHCPv6Opt = 95
|
||||
DHCPv6OptS46ContLW DHCPv6Opt = 96
|
||||
|
||||
// RFC 7600 IPv4 Residual Deployment via IPv6
|
||||
DHCPv6Opt4RD DHCPv6Opt = 97
|
||||
DHCPv6Opt4RDMapRule DHCPv6Opt = 98
|
||||
DHCPv6Opt4RDNonMapRule DHCPv6Opt = 99
|
||||
|
||||
// RFC 7653 Active Leasequery
|
||||
DHCPv6OptLQBaseTime DHCPv6Opt = 100
|
||||
DHCPv6OptLQStartTime DHCPv6Opt = 101
|
||||
DHCPv6OptLQEndTime DHCPv6Opt = 102
|
||||
|
||||
// RFC 7710 Captive-Portal Identification
|
||||
DHCPv6OptCaptivePortal DHCPv6Opt = 103
|
||||
|
||||
// RFC 7774 Multicast Protocol for Low-Power and Lossy Networks (MPL) Parameter Configuration
|
||||
DHCPv6OptMPLParameters DHCPv6Opt = 104
|
||||
|
||||
// RFC 7839 Access-Network-Identifier (ANI)
|
||||
DHCPv6OptANIATT DHCPv6Opt = 105
|
||||
DHCPv6OptANINetworkName DHCPv6Opt = 106
|
||||
DHCPv6OptANIAPName DHCPv6Opt = 107
|
||||
DHCPv6OptANIAPBSSID DHCPv6Opt = 108
|
||||
DHCPv6OptANIOperatorID DHCPv6Opt = 109
|
||||
DHCPv6OptANIOperatorRealm DHCPv6Opt = 110
|
||||
|
||||
// RFC 8026 Unified IPv4-in-IPv6 Softwire Customer Premises Equipment (CPE)
|
||||
DHCPv6OptS46Priority DHCPv6Opt = 111
|
||||
|
||||
// draft-ietf-opsawg-mud-25 Manufacturer Usage Description (MUD)
|
||||
DHCPv6OptMUDURLV6 DHCPv6Opt = 112
|
||||
|
||||
// RFC 8115 IPv4-Embedded Multicast and Unicast IPv6 Prefixes
|
||||
DHCPv6OptV6Prefix64 DHCPv6Opt = 113
|
||||
|
||||
// RFC 8156 DHCPv6 Failover Protocol
|
||||
DHCPv6OptFBindingStatus DHCPv6Opt = 114
|
||||
DHCPv6OptFConnectFlags DHCPv6Opt = 115
|
||||
DHCPv6OptFDNSRemovalInfo DHCPv6Opt = 116
|
||||
DHCPv6OptFDNSHostName DHCPv6Opt = 117
|
||||
DHCPv6OptFDNSZoneName DHCPv6Opt = 118
|
||||
DHCPv6OptFDNSFlags DHCPv6Opt = 119
|
||||
DHCPv6OptFExpirationTime DHCPv6Opt = 120
|
||||
DHCPv6OptFMaxUnacknowledgedBNDUPD DHCPv6Opt = 121
|
||||
DHCPv6OptFMCLT DHCPv6Opt = 122
|
||||
DHCPv6OptFPartnerLifetime DHCPv6Opt = 123
|
||||
DHCPv6OptFPartnerLifetimeSent DHCPv6Opt = 124
|
||||
DHCPv6OptFPartnerDownTime DHCPv6Opt = 125
|
||||
DHCPv6OptFPartnerRawCltTime DHCPv6Opt = 126
|
||||
DHCPv6OptFProtocolVersion DHCPv6Opt = 127
|
||||
DHCPv6OptFKeepaliveTime DHCPv6Opt = 128
|
||||
DHCPv6OptFReconfigureData DHCPv6Opt = 129
|
||||
DHCPv6OptFRelationshipName DHCPv6Opt = 130
|
||||
DHCPv6OptFServerFlags DHCPv6Opt = 131
|
||||
DHCPv6OptFServerState DHCPv6Opt = 132
|
||||
DHCPv6OptFStartTimeOfState DHCPv6Opt = 133
|
||||
DHCPv6OptFStateExpirationTime DHCPv6Opt = 134
|
||||
|
||||
// RFC 8357 Generalized UDP Source Port for DHCP Relay
|
||||
DHCPv6OptRelayPort DHCPv6Opt = 135
|
||||
|
||||
// draft-ietf-netconf-zerotouch-25 Zero Touch Provisioning for Networking Devices
|
||||
DHCPv6OptV6ZeroTouchRedirect DHCPv6Opt = 136
|
||||
|
||||
// RFC 6153 Access Network Discovery and Selection Function (ANDSF) Discovery
|
||||
DHCPv6OptIPV6AddressANDSF DHCPv6Opt = 143
|
||||
)
|
||||
|
||||
// String returns a string version of a DHCPv6Opt.
|
||||
func (o DHCPv6Opt) String() string {
|
||||
switch o {
|
||||
case DHCPv6OptClientID:
|
||||
return "ClientID"
|
||||
case DHCPv6OptServerID:
|
||||
return "ServerID"
|
||||
case DHCPv6OptIANA:
|
||||
return "IA_NA"
|
||||
case DHCPv6OptIATA:
|
||||
return "IA_TA"
|
||||
case DHCPv6OptIAAddr:
|
||||
return "IAAddr"
|
||||
case DHCPv6OptOro:
|
||||
return "Oro"
|
||||
case DHCPv6OptPreference:
|
||||
return "Preference"
|
||||
case DHCPv6OptElapsedTime:
|
||||
return "ElapsedTime"
|
||||
case DHCPv6OptRelayMessage:
|
||||
return "RelayMessage"
|
||||
case DHCPv6OptAuth:
|
||||
return "Auth"
|
||||
case DHCPv6OptUnicast:
|
||||
return "Unicast"
|
||||
case DHCPv6OptStatusCode:
|
||||
return "StatusCode"
|
||||
case DHCPv6OptRapidCommit:
|
||||
return "RapidCommit"
|
||||
case DHCPv6OptUserClass:
|
||||
return "UserClass"
|
||||
case DHCPv6OptVendorClass:
|
||||
return "VendorClass"
|
||||
case DHCPv6OptVendorOpts:
|
||||
return "VendorOpts"
|
||||
case DHCPv6OptInterfaceID:
|
||||
return "InterfaceID"
|
||||
case DHCPv6OptReconfigureMessage:
|
||||
return "ReconfigureMessage"
|
||||
case DHCPv6OptReconfigureAccept:
|
||||
return "ReconfigureAccept"
|
||||
case DHCPv6OptSIPServersDomainList:
|
||||
return "SIPServersDomainList"
|
||||
case DHCPv6OptSIPServersAddressList:
|
||||
return "SIPServersAddressList"
|
||||
case DHCPv6OptDNSServers:
|
||||
return "DNSRecursiveNameServer"
|
||||
case DHCPv6OptDomainList:
|
||||
return "DomainSearchList"
|
||||
case DHCPv6OptIAPD:
|
||||
return "IdentityAssociationPrefixDelegation"
|
||||
case DHCPv6OptIAPrefix:
|
||||
return "IAPDPrefix"
|
||||
case DHCPv6OptNISServers:
|
||||
return "NISServers"
|
||||
case DHCPv6OptNISPServers:
|
||||
return "NISv2Servers"
|
||||
case DHCPv6OptNISDomainName:
|
||||
return "NISDomainName"
|
||||
case DHCPv6OptNISPDomainName:
|
||||
return "NISv2DomainName"
|
||||
case DHCPv6OptSNTPServers:
|
||||
return "SNTPServers"
|
||||
case DHCPv6OptInformationRefreshTime:
|
||||
return "InformationRefreshTime"
|
||||
case DHCPv6OptBCMCSServerDomainNameList:
|
||||
return "BCMCSControlServersDomainNameList"
|
||||
case DHCPv6OptBCMCSServerAddressList:
|
||||
return "BCMCSControlServersAddressList"
|
||||
case DHCPv6OptGeoconfCivic:
|
||||
return "CivicAddress"
|
||||
case DHCPv6OptRemoteID:
|
||||
return "RelayAgentRemoteID"
|
||||
case DHCPv6OptSubscriberID:
|
||||
return "RelayAgentSubscriberID"
|
||||
case DHCPv6OptClientFQDN:
|
||||
return "ClientFQDN"
|
||||
case DHCPv6OptPanaAgent:
|
||||
return "PANAAuthenticationAgent"
|
||||
case DHCPv6OptNewPOSIXTimezone:
|
||||
return "NewPOSIXTimezone"
|
||||
case DHCPv6OptNewTZDBTimezone:
|
||||
return "NewTZDBTimezone"
|
||||
case DHCPv6OptEchoRequestOption:
|
||||
return "EchoRequest"
|
||||
case DHCPv6OptLQQuery:
|
||||
return "LeasequeryQuery"
|
||||
case DHCPv6OptClientData:
|
||||
return "LeasequeryClientData"
|
||||
case DHCPv6OptCLTTime:
|
||||
return "LeasequeryClientLastTransactionTime"
|
||||
case DHCPv6OptLQRelayData:
|
||||
return "LeasequeryRelayData"
|
||||
case DHCPv6OptLQClientLink:
|
||||
return "LeasequeryClientLink"
|
||||
case DHCPv6OptMIP6HNIDF:
|
||||
return "MIPv6HomeNetworkIDFQDN"
|
||||
case DHCPv6OptMIP6VDINF:
|
||||
return "MIPv6VisitedHomeNetworkInformation"
|
||||
case DHCPv6OptMIP6IDINF:
|
||||
return "MIPv6IdentifiedHomeNetworkInformation"
|
||||
case DHCPv6OptMIP6UDINF:
|
||||
return "MIPv6UnrestrictedHomeNetworkInformation"
|
||||
case DHCPv6OptMIP6HNP:
|
||||
return "MIPv6HomeNetworkPrefix"
|
||||
case DHCPv6OptMIP6HAA:
|
||||
return "MIPv6HomeAgentAddress"
|
||||
case DHCPv6OptMIP6HAF:
|
||||
return "MIPv6HomeAgentFQDN"
|
||||
case DHCPv6OptV6LOST:
|
||||
return "LoST Server"
|
||||
case DHCPv6OptCAPWAPACV6:
|
||||
return "CAPWAPAccessControllerV6"
|
||||
case DHCPv6OptRelayID:
|
||||
return "LeasequeryRelayID"
|
||||
case DHCPv6OptIPv6AddressMoS:
|
||||
return "MoSIPv6Address"
|
||||
case DHCPv6OptIPv6FQDNMoS:
|
||||
return "MoSDomainNameList"
|
||||
case DHCPv6OptNTPServer:
|
||||
return "NTPServer"
|
||||
case DHCPv6OptV6AccessDomain:
|
||||
return "AccessNetworkDomainName"
|
||||
case DHCPv6OptSIPUACSList:
|
||||
return "SIPUserAgentConfigurationServiceDomains"
|
||||
case DHCPv6OptBootFileURL:
|
||||
return "BootFileURL"
|
||||
case DHCPv6OptBootFileParam:
|
||||
return "BootFileParameters"
|
||||
case DHCPv6OptClientArchType:
|
||||
return "ClientSystemArchitectureType"
|
||||
case DHCPv6OptNII:
|
||||
return "ClientNetworkInterfaceIdentifier"
|
||||
case DHCPv6OptGeolocation:
|
||||
return "Geolocation"
|
||||
case DHCPv6OptAFTRName:
|
||||
return "AFTRName"
|
||||
case DHCPv6OptERPLocalDomainName:
|
||||
return "AFTRName"
|
||||
case DHCPv6OptRSOO:
|
||||
return "RSOOption"
|
||||
case DHCPv6OptPDExclude:
|
||||
return "PrefixExclude"
|
||||
case DHCPv6OptVSS:
|
||||
return "VirtualSubnetSelection"
|
||||
case DHCPv6OptRDNSSSelection:
|
||||
return "RDNSSSelection"
|
||||
case DHCPv6OptKRBPrincipalName:
|
||||
return "KerberosPrincipalName"
|
||||
case DHCPv6OptKRBRealmName:
|
||||
return "KerberosRealmName"
|
||||
case DHCPv6OptKRBKDC:
|
||||
return "KerberosKDC"
|
||||
case DHCPv6OptClientLinkLayerAddress:
|
||||
return "ClientLinkLayerAddress"
|
||||
case DHCPv6OptLinkAddress:
|
||||
return "LinkAddress"
|
||||
case DHCPv6OptRADIUS:
|
||||
return "RADIUS"
|
||||
case DHCPv6OptSolMaxRt:
|
||||
return "SolMaxRt"
|
||||
case DHCPv6OptInfMaxRt:
|
||||
return "InfMaxRt"
|
||||
case DHCPv6OptAddrSel:
|
||||
return "AddressSelection"
|
||||
case DHCPv6OptAddrSelTable:
|
||||
return "AddressSelectionTable"
|
||||
case DHCPv6OptV6PCPServer:
|
||||
return "PCPServer"
|
||||
case DHCPv6OptDHCPv4Message:
|
||||
return "DHCPv4Message"
|
||||
case DHCPv6OptDHCPv4OverDHCPv6Server:
|
||||
return "DHCP4o6ServerAddress"
|
||||
case DHCPv6OptS46Rule:
|
||||
return "S46Rule"
|
||||
case DHCPv6OptS46BR:
|
||||
return "S46BR"
|
||||
case DHCPv6OptS46DMR:
|
||||
return "S46DMR"
|
||||
case DHCPv6OptS46V4V4Bind:
|
||||
return "S46IPv4IPv6AddressBinding"
|
||||
case DHCPv6OptS46PortParameters:
|
||||
return "S46PortParameters"
|
||||
case DHCPv6OptS46ContMAPE:
|
||||
return "S46MAPEContainer"
|
||||
case DHCPv6OptS46ContMAPT:
|
||||
return "S46MAPTContainer"
|
||||
case DHCPv6OptS46ContLW:
|
||||
return "S46Lightweight4Over6Container"
|
||||
case DHCPv6Opt4RD:
|
||||
return "4RD"
|
||||
case DHCPv6Opt4RDMapRule:
|
||||
return "4RDMapRule"
|
||||
case DHCPv6Opt4RDNonMapRule:
|
||||
return "4RDNonMapRule"
|
||||
case DHCPv6OptLQBaseTime:
|
||||
return "LQBaseTime"
|
||||
case DHCPv6OptLQStartTime:
|
||||
return "LQStartTime"
|
||||
case DHCPv6OptLQEndTime:
|
||||
return "LQEndTime"
|
||||
case DHCPv6OptCaptivePortal:
|
||||
return "CaptivePortal"
|
||||
case DHCPv6OptMPLParameters:
|
||||
return "MPLParameterConfiguration"
|
||||
case DHCPv6OptANIATT:
|
||||
return "ANIAccessTechnologyType"
|
||||
case DHCPv6OptANINetworkName:
|
||||
return "ANINetworkName"
|
||||
case DHCPv6OptANIAPName:
|
||||
return "ANIAccessPointName"
|
||||
case DHCPv6OptANIAPBSSID:
|
||||
return "ANIAccessPointBSSID"
|
||||
case DHCPv6OptANIOperatorID:
|
||||
return "ANIOperatorIdentifier"
|
||||
case DHCPv6OptANIOperatorRealm:
|
||||
return "ANIOperatorRealm"
|
||||
case DHCPv6OptS46Priority:
|
||||
return "S64Priority"
|
||||
case DHCPv6OptMUDURLV6:
|
||||
return "ManufacturerUsageDescriptionURL"
|
||||
case DHCPv6OptV6Prefix64:
|
||||
return "V6Prefix64"
|
||||
case DHCPv6OptFBindingStatus:
|
||||
return "FailoverBindingStatus"
|
||||
case DHCPv6OptFConnectFlags:
|
||||
return "FailoverConnectFlags"
|
||||
case DHCPv6OptFDNSRemovalInfo:
|
||||
return "FailoverDNSRemovalInfo"
|
||||
case DHCPv6OptFDNSHostName:
|
||||
return "FailoverDNSHostName"
|
||||
case DHCPv6OptFDNSZoneName:
|
||||
return "FailoverDNSZoneName"
|
||||
case DHCPv6OptFDNSFlags:
|
||||
return "FailoverDNSFlags"
|
||||
case DHCPv6OptFExpirationTime:
|
||||
return "FailoverExpirationTime"
|
||||
case DHCPv6OptFMaxUnacknowledgedBNDUPD:
|
||||
return "FailoverMaxUnacknowledgedBNDUPDMessages"
|
||||
case DHCPv6OptFMCLT:
|
||||
return "FailoverMaximumClientLeadTime"
|
||||
case DHCPv6OptFPartnerLifetime:
|
||||
return "FailoverPartnerLifetime"
|
||||
case DHCPv6OptFPartnerLifetimeSent:
|
||||
return "FailoverPartnerLifetimeSent"
|
||||
case DHCPv6OptFPartnerDownTime:
|
||||
return "FailoverPartnerDownTime"
|
||||
case DHCPv6OptFPartnerRawCltTime:
|
||||
return "FailoverPartnerRawClientLeadTime"
|
||||
case DHCPv6OptFProtocolVersion:
|
||||
return "FailoverProtocolVersion"
|
||||
case DHCPv6OptFKeepaliveTime:
|
||||
return "FailoverKeepaliveTime"
|
||||
case DHCPv6OptFReconfigureData:
|
||||
return "FailoverReconfigureData"
|
||||
case DHCPv6OptFRelationshipName:
|
||||
return "FailoverRelationshipName"
|
||||
case DHCPv6OptFServerFlags:
|
||||
return "FailoverServerFlags"
|
||||
case DHCPv6OptFServerState:
|
||||
return "FailoverServerState"
|
||||
case DHCPv6OptFStartTimeOfState:
|
||||
return "FailoverStartTimeOfState"
|
||||
case DHCPv6OptFStateExpirationTime:
|
||||
return "FailoverStateExpirationTime"
|
||||
case DHCPv6OptRelayPort:
|
||||
return "RelayPort"
|
||||
case DHCPv6OptV6ZeroTouchRedirect:
|
||||
return "ZeroTouch"
|
||||
case DHCPv6OptIPV6AddressANDSF:
|
||||
return "ANDSFIPv6Address"
|
||||
default:
|
||||
return fmt.Sprintf("Unknown(%d)", uint16(o))
|
||||
}
|
||||
}
|
||||
|
||||
// DHCPv6Options is used to get nicely printed option lists which would normally
|
||||
// be cut off after 5 options.
|
||||
type DHCPv6Options []DHCPv6Option
|
||||
|
||||
// String returns a string version of the options list.
|
||||
func (o DHCPv6Options) String() string {
|
||||
buf := &bytes.Buffer{}
|
||||
buf.WriteByte('[')
|
||||
for i, opt := range o {
|
||||
buf.WriteString(opt.String())
|
||||
if i+1 != len(o) {
|
||||
buf.WriteString(", ")
|
||||
}
|
||||
}
|
||||
buf.WriteByte(']')
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// DHCPv6Option rerpresents a DHCP option.
|
||||
type DHCPv6Option struct {
|
||||
Code DHCPv6Opt
|
||||
Length uint16
|
||||
Data []byte
|
||||
}
|
||||
|
||||
// String returns a string version of a DHCP Option.
|
||||
func (o DHCPv6Option) String() string {
|
||||
switch o.Code {
|
||||
case DHCPv6OptClientID, DHCPv6OptServerID:
|
||||
duid, err := decodeDHCPv6DUID(o.Data)
|
||||
if err != nil {
|
||||
return fmt.Sprintf("Option(%s:INVALID)", o.Code)
|
||||
}
|
||||
return fmt.Sprintf("Option(%s:[%s])", o.Code, duid.String())
|
||||
case DHCPv6OptOro:
|
||||
options := ""
|
||||
for i := 0; i < int(o.Length); i += 2 {
|
||||
if options != "" {
|
||||
options += ","
|
||||
}
|
||||
option := DHCPv6Opt(binary.BigEndian.Uint16(o.Data[i : i+2]))
|
||||
options += option.String()
|
||||
}
|
||||
return fmt.Sprintf("Option(%s:[%s])", o.Code, options)
|
||||
default:
|
||||
return fmt.Sprintf("Option(%s:%v)", o.Code, o.Data)
|
||||
}
|
||||
}
|
||||
|
||||
// NewDHCPv6Option constructs a new DHCPv6Option with a given type and data.
|
||||
func NewDHCPv6Option(code DHCPv6Opt, data []byte) DHCPv6Option {
|
||||
o := DHCPv6Option{Code: code}
|
||||
if data != nil {
|
||||
o.Data = data
|
||||
o.Length = uint16(len(data))
|
||||
}
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
func (o *DHCPv6Option) encode(b []byte, opts gopacket.SerializeOptions) error {
|
||||
binary.BigEndian.PutUint16(b[0:2], uint16(o.Code))
|
||||
if opts.FixLengths {
|
||||
binary.BigEndian.PutUint16(b[2:4], uint16(len(o.Data)))
|
||||
} else {
|
||||
binary.BigEndian.PutUint16(b[2:4], o.Length)
|
||||
}
|
||||
copy(b[4:], o.Data)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *DHCPv6Option) decode(data []byte) error {
|
||||
if len(data) < 2 {
|
||||
return errors.New("not enough data to decode")
|
||||
}
|
||||
o.Code = DHCPv6Opt(binary.BigEndian.Uint16(data[0:2]))
|
||||
if len(data) < 3 {
|
||||
return errors.New("not enough data to decode")
|
||||
}
|
||||
o.Length = binary.BigEndian.Uint16(data[2:4])
|
||||
o.Data = data[4 : 4+o.Length]
|
||||
return nil
|
||||
}
|
54
vendor/github.com/google/gopacket/layers/dns.go
generated
vendored
54
vendor/github.com/google/gopacket/layers/dns.go
generated
vendored
@ -296,7 +296,7 @@ func (d *DNS) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||||
|
||||
if len(data) < 12 {
|
||||
df.SetTruncated()
|
||||
return errors.New("DNS packet too short")
|
||||
return errDNSPacketTooShort
|
||||
}
|
||||
|
||||
// since there are no further layers, the baselayer's content is
|
||||
@ -366,13 +366,13 @@ func (d *DNS) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||||
}
|
||||
|
||||
if uint16(len(d.Questions)) != d.QDCount {
|
||||
return errors.New("Invalid query decoding, not the right number of questions")
|
||||
return errDecodeQueryBadQDCount
|
||||
} else if uint16(len(d.Answers)) != d.ANCount {
|
||||
return errors.New("Invalid query decoding, not the right number of answers")
|
||||
return errDecodeQueryBadANCount
|
||||
} else if uint16(len(d.Authorities)) != d.NSCount {
|
||||
return errors.New("Invalid query decoding, not the right number of authorities")
|
||||
return errDecodeQueryBadNSCount
|
||||
} else if uint16(len(d.Additionals)) != d.ARCount {
|
||||
return errors.New("Invalid query decoding, not the right number of additionals info")
|
||||
return errDecodeQueryBadARCount
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -504,17 +504,15 @@ func (d *DNS) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOpt
|
||||
return nil
|
||||
}
|
||||
|
||||
var errMaxRecursion = errors.New("max DNS recursion level hit")
|
||||
|
||||
const maxRecursionLevel = 255
|
||||
|
||||
func decodeName(data []byte, offset int, buffer *[]byte, level int) ([]byte, int, error) {
|
||||
if level > maxRecursionLevel {
|
||||
return nil, 0, errMaxRecursion
|
||||
} else if offset >= len(data) {
|
||||
return nil, 0, errors.New("dns name offset too high")
|
||||
return nil, 0, errDNSNameOffsetTooHigh
|
||||
} else if offset < 0 {
|
||||
return nil, 0, errors.New("dns name offset is negative")
|
||||
return nil, 0, errDNSNameOffsetNegative
|
||||
}
|
||||
start := len(*buffer)
|
||||
index := offset
|
||||
@ -535,9 +533,9 @@ loop:
|
||||
*/
|
||||
index2 := index + int(data[index]) + 1
|
||||
if index2-offset > 255 {
|
||||
return nil, 0, errors.New("dns name is too long")
|
||||
return nil, 0, errDNSNameTooLong
|
||||
} else if index2 < index+1 || index2 > len(data) {
|
||||
return nil, 0, errors.New("dns name uncomputable: invalid index")
|
||||
return nil, 0, errDNSNameInvalidIndex
|
||||
}
|
||||
*buffer = append(*buffer, '.')
|
||||
*buffer = append(*buffer, data[index+1:index2]...)
|
||||
@ -564,11 +562,11 @@ loop:
|
||||
- a sequence of labels ending with a pointer
|
||||
*/
|
||||
if index+2 > len(data) {
|
||||
return nil, 0, errors.New("dns offset pointer too high")
|
||||
return nil, 0, errDNSPointerOffsetTooHigh
|
||||
}
|
||||
offsetp := int(binary.BigEndian.Uint16(data[index:index+2]) & 0x3fff)
|
||||
if offsetp > len(data) {
|
||||
return nil, 0, errors.New("dns offset pointer too high")
|
||||
return nil, 0, errDNSPointerOffsetTooHigh
|
||||
}
|
||||
// This looks a little tricky, but actually isn't. Because of how
|
||||
// decodeName is written, calling it appends the decoded name to the
|
||||
@ -590,11 +588,11 @@ loop:
|
||||
data[index], index)
|
||||
}
|
||||
if index >= len(data) {
|
||||
return nil, 0, errors.New("dns index walked out of range")
|
||||
return nil, 0, errDNSIndexOutOfRange
|
||||
}
|
||||
}
|
||||
if len(*buffer) <= start {
|
||||
return nil, 0, errors.New("no dns data found for name")
|
||||
return nil, 0, errDNSNameHasNoData
|
||||
}
|
||||
return (*buffer)[start+1:], index + 1, nil
|
||||
}
|
||||
@ -686,7 +684,7 @@ func (rr *DNSResourceRecord) decode(data []byte, offset int, df gopacket.DecodeF
|
||||
rr.DataLength = binary.BigEndian.Uint16(data[endq+8 : endq+10])
|
||||
end := endq + 10 + int(rr.DataLength)
|
||||
if end > len(data) {
|
||||
return 0, fmt.Errorf("resource record length exceeds data")
|
||||
return 0, errDecodeRecordLength
|
||||
}
|
||||
rr.Data = data[endq+10 : end]
|
||||
|
||||
@ -798,7 +796,7 @@ func decodeCharacterStrings(data []byte) ([][]byte, error) {
|
||||
for index, index2 := 0, 0; index != end; index = index2 {
|
||||
index2 = index + 1 + int(data[index]) // index increases by 1..256 and does not overflow
|
||||
if index2 > end {
|
||||
return nil, errors.New("Insufficient data for a <character-string>")
|
||||
return nil, errCharStringMissData
|
||||
}
|
||||
strings = append(strings, data[index+1:index2])
|
||||
}
|
||||
@ -892,3 +890,25 @@ type DNSMX struct {
|
||||
Preference uint16
|
||||
Name []byte
|
||||
}
|
||||
|
||||
var (
|
||||
errMaxRecursion = errors.New("max DNS recursion level hit")
|
||||
|
||||
errDNSNameOffsetTooHigh = errors.New("dns name offset too high")
|
||||
errDNSNameOffsetNegative = errors.New("dns name offset is negative")
|
||||
errDNSPacketTooShort = errors.New("DNS packet too short")
|
||||
errDNSNameTooLong = errors.New("dns name is too long")
|
||||
errDNSNameInvalidIndex = errors.New("dns name uncomputable: invalid index")
|
||||
errDNSPointerOffsetTooHigh = errors.New("dns offset pointer too high")
|
||||
errDNSIndexOutOfRange = errors.New("dns index walked out of range")
|
||||
errDNSNameHasNoData = errors.New("no dns data found for name")
|
||||
|
||||
errCharStringMissData = errors.New("Insufficient data for a <character-string>")
|
||||
|
||||
errDecodeRecordLength = errors.New("resource record length exceeds data")
|
||||
|
||||
errDecodeQueryBadQDCount = errors.New("Invalid query decoding, not the right number of questions")
|
||||
errDecodeQueryBadANCount = errors.New("Invalid query decoding, not the right number of answers")
|
||||
errDecodeQueryBadNSCount = errors.New("Invalid query decoding, not the right number of authorities")
|
||||
errDecodeQueryBadARCount = errors.New("Invalid query decoding, not the right number of additionals info")
|
||||
)
|
||||
|
18
vendor/github.com/google/gopacket/layers/dot11.go
generated
vendored
18
vendor/github.com/google/gopacket/layers/dot11.go
generated
vendored
@ -405,6 +405,12 @@ const (
|
||||
Dot11InformationElementIDVHTTxPowerEnvelope Dot11InformationElementID = 195
|
||||
Dot11InformationElementIDChannelSwitchWrapper Dot11InformationElementID = 196
|
||||
Dot11InformationElementIDOperatingModeNotification Dot11InformationElementID = 199
|
||||
Dot11InformationElementIDUPSIM Dot11InformationElementID = 200
|
||||
Dot11InformationElementIDReducedNeighborReport Dot11InformationElementID = 201
|
||||
Dot11InformationElementIDTVHTOperation Dot11InformationElementID = 202
|
||||
Dot11InformationElementIDDeviceLocation Dot11InformationElementID = 204
|
||||
Dot11InformationElementIDWhiteSpaceMap Dot11InformationElementID = 205
|
||||
Dot11InformationElementIDFineTuningMeasureParams Dot11InformationElementID = 206
|
||||
Dot11InformationElementIDVendor Dot11InformationElementID = 221
|
||||
)
|
||||
|
||||
@ -742,6 +748,18 @@ func (a Dot11InformationElementID) String() string {
|
||||
return "Channel Switch Wrapper"
|
||||
case Dot11InformationElementIDOperatingModeNotification:
|
||||
return "Operating Mode Notification"
|
||||
case Dot11InformationElementIDUPSIM:
|
||||
return "UP SIM"
|
||||
case Dot11InformationElementIDReducedNeighborReport:
|
||||
return "Reduced Neighbor Report"
|
||||
case Dot11InformationElementIDTVHTOperation:
|
||||
return "TVHT Op"
|
||||
case Dot11InformationElementIDDeviceLocation:
|
||||
return "Device Location"
|
||||
case Dot11InformationElementIDWhiteSpaceMap:
|
||||
return "White Space Map"
|
||||
case Dot11InformationElementIDFineTuningMeasureParams:
|
||||
return "Fine Tuning Measure Parameters"
|
||||
case Dot11InformationElementIDVendor:
|
||||
return "Vendor"
|
||||
default:
|
||||
|
10
vendor/github.com/google/gopacket/layers/enums.go
generated
vendored
10
vendor/github.com/google/gopacket/layers/enums.go
generated
vendored
@ -10,6 +10,7 @@ package layers
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"runtime"
|
||||
|
||||
"github.com/google/gopacket"
|
||||
)
|
||||
@ -49,6 +50,7 @@ const (
|
||||
EthernetTypeNortelDiscovery EthernetType = 0x01a2
|
||||
EthernetTypeTransparentEthernetBridging EthernetType = 0x6558
|
||||
EthernetTypeDot1Q EthernetType = 0x8100
|
||||
EthernetTypePPP EthernetType = 0x880b
|
||||
EthernetTypePPPoEDiscovery EthernetType = 0x8863
|
||||
EthernetTypePPPoESession EthernetType = 0x8864
|
||||
EthernetTypeMPLSUnicast EthernetType = 0x8847
|
||||
@ -310,6 +312,7 @@ func initActualTypeData() {
|
||||
EthernetTypeMetadata[EthernetTypeIPv6] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeIPv6), Name: "IPv6", LayerType: LayerTypeIPv6}
|
||||
EthernetTypeMetadata[EthernetTypeARP] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeARP), Name: "ARP", LayerType: LayerTypeARP}
|
||||
EthernetTypeMetadata[EthernetTypeDot1Q] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeDot1Q), Name: "Dot1Q", LayerType: LayerTypeDot1Q}
|
||||
EthernetTypeMetadata[EthernetTypePPP] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodePPP), Name: "PPP", LayerType: LayerTypePPP}
|
||||
EthernetTypeMetadata[EthernetTypePPPoEDiscovery] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodePPPoE), Name: "PPPoEDiscovery", LayerType: LayerTypePPPoE}
|
||||
EthernetTypeMetadata[EthernetTypePPPoESession] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodePPPoE), Name: "PPPoESession", LayerType: LayerTypePPPoE}
|
||||
EthernetTypeMetadata[EthernetTypeEthernetCTP] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeEthernetCTP), Name: "EthernetCTP", LayerType: LayerTypeEthernetCTP}
|
||||
@ -375,6 +378,13 @@ func initActualTypeData() {
|
||||
LinkTypeMetadata[LinkTypeLoop] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeLoopback), Name: "Loop"}
|
||||
LinkTypeMetadata[LinkTypeIEEE802_11] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeDot11), Name: "802.11"}
|
||||
LinkTypeMetadata[LinkTypeRaw] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeIPv4or6), Name: "Raw"}
|
||||
// See https://github.com/the-tcpdump-group/libpcap/blob/170f717e6e818cdc4bcbbfd906b63088eaa88fa0/pcap/dlt.h#L85
|
||||
// Or https://github.com/wireshark/wireshark/blob/854cfe53efe44080609c78053ecfb2342ad84a08/wiretap/pcap-common.c#L508
|
||||
if runtime.GOOS == "openbsd" {
|
||||
LinkTypeMetadata[14] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeIPv4or6), Name: "Raw"}
|
||||
} else {
|
||||
LinkTypeMetadata[12] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeIPv4or6), Name: "Raw"}
|
||||
}
|
||||
LinkTypeMetadata[LinkTypePFLog] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodePFLog), Name: "PFLog"}
|
||||
LinkTypeMetadata[LinkTypeIEEE80211Radio] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeRadioTap), Name: "RadioTap"}
|
||||
LinkTypeMetadata[LinkTypeLinuxUSB] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeUSB), Name: "USB"}
|
||||
|
25
vendor/github.com/google/gopacket/layers/gre.go
generated
vendored
25
vendor/github.com/google/gopacket/layers/gre.go
generated
vendored
@ -15,11 +15,11 @@ import (
|
||||
// GRE is a Generic Routing Encapsulation header.
|
||||
type GRE struct {
|
||||
BaseLayer
|
||||
ChecksumPresent, RoutingPresent, KeyPresent, SeqPresent, StrictSourceRoute bool
|
||||
RecursionControl, Flags, Version uint8
|
||||
Protocol EthernetType
|
||||
Checksum, Offset uint16
|
||||
Key, Seq uint32
|
||||
ChecksumPresent, RoutingPresent, KeyPresent, SeqPresent, StrictSourceRoute, AckPresent bool
|
||||
RecursionControl, Flags, Version uint8
|
||||
Protocol EthernetType
|
||||
Checksum, Offset uint16
|
||||
Key, Seq, Ack uint32
|
||||
*GRERouting
|
||||
}
|
||||
|
||||
@ -42,6 +42,7 @@ func (g *GRE) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||||
g.KeyPresent = data[0]&0x20 != 0
|
||||
g.SeqPresent = data[0]&0x10 != 0
|
||||
g.StrictSourceRoute = data[0]&0x08 != 0
|
||||
g.AckPresent = data[1]&0x80 != 0
|
||||
g.RecursionControl = data[0] & 0x7
|
||||
g.Flags = data[1] >> 3
|
||||
g.Version = data[1] & 0x7
|
||||
@ -77,6 +78,10 @@ func (g *GRE) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||||
tail = &sre.Next
|
||||
}
|
||||
}
|
||||
if g.AckPresent {
|
||||
g.Ack = binary.BigEndian.Uint32(data[offset : offset+4])
|
||||
offset += 4
|
||||
}
|
||||
g.BaseLayer = BaseLayer{data[:offset], data[offset:]}
|
||||
return nil
|
||||
}
|
||||
@ -102,6 +107,9 @@ func (g *GRE) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOpt
|
||||
}
|
||||
size += 4
|
||||
}
|
||||
if g.AckPresent {
|
||||
size += 4
|
||||
}
|
||||
buf, err := b.PrependBytes(size)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -124,6 +132,9 @@ func (g *GRE) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOpt
|
||||
if g.StrictSourceRoute {
|
||||
buf[0] |= 0x08
|
||||
}
|
||||
if g.AckPresent {
|
||||
buf[1] |= 0x80
|
||||
}
|
||||
buf[0] |= g.RecursionControl
|
||||
buf[1] |= g.Flags << 3
|
||||
buf[1] |= g.Version
|
||||
@ -159,6 +170,10 @@ func (g *GRE) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOpt
|
||||
// Terminate routing field with a "NULL" SRE.
|
||||
binary.BigEndian.PutUint32(buf[offset:offset+4], 0)
|
||||
}
|
||||
if g.AckPresent {
|
||||
binary.BigEndian.PutUint32(buf[offset:offset+4], g.Ack)
|
||||
offset += 4
|
||||
}
|
||||
if g.ChecksumPresent {
|
||||
if opts.ComputeChecksums {
|
||||
g.Checksum = tcpipChecksum(b.Bytes(), 0)
|
||||
|
5
vendor/github.com/google/gopacket/layers/icmp6msg.go
generated
vendored
5
vendor/github.com/google/gopacket/layers/icmp6msg.go
generated
vendored
@ -129,6 +129,11 @@ func (i ICMPv6Opt) String() string {
|
||||
}
|
||||
}
|
||||
|
||||
// CanDecode returns the set of layer types that this DecodingLayer can decode.
|
||||
func (i *ICMPv6Echo) CanDecode() gopacket.LayerClass {
|
||||
return LayerTypeICMPv6Echo
|
||||
}
|
||||
|
||||
// LayerType returns LayerTypeICMPv6Echo.
|
||||
func (i *ICMPv6Echo) LayerType() gopacket.LayerType {
|
||||
return LayerTypeICMPv6Echo
|
||||
|
26
vendor/github.com/google/gopacket/layers/ip4.go
generated
vendored
26
vendor/github.com/google/gopacket/layers/ip4.go
generated
vendored
@ -186,6 +186,10 @@ func (ip *IPv4) flagsfrags() (ff uint16) {
|
||||
|
||||
// DecodeFromBytes decodes the given bytes into this layer.
|
||||
func (ip *IPv4) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||||
if len(data) < 20 {
|
||||
df.SetTruncated()
|
||||
return fmt.Errorf("Invalid ip4 header. Length %d less than 20", len(data))
|
||||
}
|
||||
flagsfrags := binary.BigEndian.Uint16(data[6:8])
|
||||
|
||||
ip.Version = uint8(data[0]) >> 4
|
||||
@ -201,6 +205,7 @@ func (ip *IPv4) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||||
ip.SrcIP = data[12:16]
|
||||
ip.DstIP = data[16:20]
|
||||
ip.Options = ip.Options[:0]
|
||||
ip.Padding = nil
|
||||
// Set up an initial guess for contents/payload... we'll reset these soon.
|
||||
ip.BaseLayer = BaseLayer{Contents: data}
|
||||
|
||||
@ -243,19 +248,28 @@ func (ip *IPv4) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||||
opt.OptionLength = 1
|
||||
ip.Options = append(ip.Options, opt)
|
||||
ip.Padding = data[1:]
|
||||
break
|
||||
return nil
|
||||
case 1: // 1 byte padding
|
||||
opt.OptionLength = 1
|
||||
data = data[1:]
|
||||
ip.Options = append(ip.Options, opt)
|
||||
default:
|
||||
if len(data) < 2 {
|
||||
df.SetTruncated()
|
||||
return fmt.Errorf("Invalid ip4 option length. Length %d less than 2", len(data))
|
||||
}
|
||||
opt.OptionLength = data[1]
|
||||
if len(data) < int(opt.OptionLength) {
|
||||
df.SetTruncated()
|
||||
return fmt.Errorf("IP option length exceeds remaining IP header size, option type %v length %v", opt.OptionType, opt.OptionLength)
|
||||
}
|
||||
if opt.OptionLength <= 2 {
|
||||
return fmt.Errorf("Invalid IP option type %v length %d. Must be greater than 2", opt.OptionType, opt.OptionLength)
|
||||
}
|
||||
opt.OptionData = data[2:opt.OptionLength]
|
||||
}
|
||||
if len(data) >= int(opt.OptionLength) {
|
||||
data = data[opt.OptionLength:]
|
||||
} else {
|
||||
return fmt.Errorf("IP option length exceeds remaining IP header size, option type %v length %v", opt.OptionType, opt.OptionLength)
|
||||
ip.Options = append(ip.Options, opt)
|
||||
}
|
||||
ip.Options = append(ip.Options, opt)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
40
vendor/github.com/google/gopacket/layers/ip6.go
generated
vendored
40
vendor/github.com/google/gopacket/layers/ip6.go
generated
vendored
@ -219,6 +219,10 @@ func (ipv6 *IPv6) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.Serializ
|
||||
|
||||
// DecodeFromBytes implementation according to gopacket.DecodingLayer
|
||||
func (ipv6 *IPv6) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||||
if len(data) < 40 {
|
||||
df.SetTruncated()
|
||||
return fmt.Errorf("Invalid ip6 header. Length %d less than 40", len(data))
|
||||
}
|
||||
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
|
||||
@ -403,10 +407,17 @@ type ipv6ExtensionBase struct {
|
||||
ActualLength int
|
||||
}
|
||||
|
||||
func decodeIPv6ExtensionBase(data []byte) (i ipv6ExtensionBase) {
|
||||
func decodeIPv6ExtensionBase(data []byte, df gopacket.DecodeFeedback) (i ipv6ExtensionBase, returnedErr error) {
|
||||
if len(data) < 2 {
|
||||
df.SetTruncated()
|
||||
return ipv6ExtensionBase{}, fmt.Errorf("Invalid ip6-extension header. Length %d less than 2", len(data))
|
||||
}
|
||||
i.NextHeader = IPProtocol(data[0])
|
||||
i.HeaderLength = data[1]
|
||||
i.ActualLength = int(i.HeaderLength)*8 + 8
|
||||
if len(data) < i.ActualLength {
|
||||
return ipv6ExtensionBase{}, fmt.Errorf("Invalid ip6-extension header. Length %d less than specified length %d", len(data), i.ActualLength)
|
||||
}
|
||||
i.Contents = data[:i.ActualLength]
|
||||
i.Payload = data[i.ActualLength:]
|
||||
return
|
||||
@ -422,7 +433,10 @@ type IPv6ExtensionSkipper struct {
|
||||
|
||||
// DecodeFromBytes implementation according to gopacket.DecodingLayer
|
||||
func (i *IPv6ExtensionSkipper) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||||
extension := decodeIPv6ExtensionBase(data)
|
||||
extension, err := decodeIPv6ExtensionBase(data, df)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
i.BaseLayer = BaseLayer{data[:extension.ActualLength], data[extension.ActualLength:]}
|
||||
i.NextHeader = extension.NextHeader
|
||||
return nil
|
||||
@ -485,7 +499,11 @@ func (i *IPv6HopByHop) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.Ser
|
||||
|
||||
// DecodeFromBytes implementation according to gopacket.DecodingLayer
|
||||
func (i *IPv6HopByHop) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||||
i.ipv6ExtensionBase = decodeIPv6ExtensionBase(data)
|
||||
var err error
|
||||
i.ipv6ExtensionBase, err = decodeIPv6ExtensionBase(data, df)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
offset := 2
|
||||
for offset < i.ActualLength {
|
||||
opt := decodeIPv6HeaderTLVOption(data[offset:])
|
||||
@ -534,8 +552,12 @@ type IPv6Routing struct {
|
||||
func (i *IPv6Routing) LayerType() gopacket.LayerType { return LayerTypeIPv6Routing }
|
||||
|
||||
func decodeIPv6Routing(data []byte, p gopacket.PacketBuilder) error {
|
||||
base, err := decodeIPv6ExtensionBase(data, p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
i := &IPv6Routing{
|
||||
ipv6ExtensionBase: decodeIPv6ExtensionBase(data),
|
||||
ipv6ExtensionBase: base,
|
||||
RoutingType: data[2],
|
||||
SegmentsLeft: data[3],
|
||||
Reserved: data[4:8],
|
||||
@ -573,6 +595,10 @@ type IPv6Fragment struct {
|
||||
func (i *IPv6Fragment) LayerType() gopacket.LayerType { return LayerTypeIPv6Fragment }
|
||||
|
||||
func decodeIPv6Fragment(data []byte, p gopacket.PacketBuilder) error {
|
||||
if len(data) < 8 {
|
||||
p.SetTruncated()
|
||||
return fmt.Errorf("Invalid ip6-fragment header. Length %d less than 8", len(data))
|
||||
}
|
||||
i := &IPv6Fragment{
|
||||
BaseLayer: BaseLayer{data[:8], data[8:]},
|
||||
NextHeader: IPProtocol(data[0]),
|
||||
@ -600,7 +626,11 @@ func (i *IPv6Destination) LayerType() gopacket.LayerType { return LayerTypeIPv6D
|
||||
|
||||
// DecodeFromBytes implementation according to gopacket.DecodingLayer
|
||||
func (i *IPv6Destination) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||||
i.ipv6ExtensionBase = decodeIPv6ExtensionBase(data)
|
||||
var err error
|
||||
i.ipv6ExtensionBase, err = decodeIPv6ExtensionBase(data, df)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
offset := 2
|
||||
for offset < i.ActualLength {
|
||||
opt := decodeIPv6HeaderTLVOption(data[offset:])
|
||||
|
2
vendor/github.com/google/gopacket/layers/layertypes.go
generated
vendored
2
vendor/github.com/google/gopacket/layers/layertypes.go
generated
vendored
@ -11,7 +11,6 @@ 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)})
|
||||
@ -143,6 +142,7 @@ var (
|
||||
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)})
|
||||
LayerTypeModbusTCP = gopacket.RegisterLayerType(141, gopacket.LayerTypeMetadata{Name: "ModbusTCP", Decoder: gopacket.DecodeFunc(decodeModbusTCP)})
|
||||
)
|
||||
|
||||
var (
|
||||
|
2
vendor/github.com/google/gopacket/layers/linux_sll.go
generated
vendored
2
vendor/github.com/google/gopacket/layers/linux_sll.go
generated
vendored
@ -54,6 +54,7 @@ type LinuxSLL struct {
|
||||
AddrLen uint16
|
||||
Addr net.HardwareAddr
|
||||
EthernetType EthernetType
|
||||
AddrType uint16
|
||||
}
|
||||
|
||||
// LayerType returns LayerTypeLinuxSLL.
|
||||
@ -76,6 +77,7 @@ func (sll *LinuxSLL) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) er
|
||||
return errors.New("Linux SLL packet too small")
|
||||
}
|
||||
sll.PacketType = LinuxSLLPacketType(binary.BigEndian.Uint16(data[0:2]))
|
||||
sll.AddrType = binary.BigEndian.Uint16(data[2:4])
|
||||
sll.AddrLen = binary.BigEndian.Uint16(data[4:6])
|
||||
|
||||
sll.Addr = net.HardwareAddr(data[6 : sll.AddrLen+6])
|
||||
|
150
vendor/github.com/google/gopacket/layers/modbustcp.go
generated
vendored
Normal file
150
vendor/github.com/google/gopacket/layers/modbustcp.go
generated
vendored
Normal file
@ -0,0 +1,150 @@
|
||||
// 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"
|
||||
)
|
||||
|
||||
//******************************************************************************
|
||||
//
|
||||
// ModbusTCP Decoding Layer
|
||||
// ------------------------------------------
|
||||
// This file provides a GoPacket decoding layer for ModbusTCP.
|
||||
//
|
||||
//******************************************************************************
|
||||
|
||||
const mbapRecordSizeInBytes int = 7
|
||||
const modbusPDUMinimumRecordSizeInBytes int = 2
|
||||
const modbusPDUMaximumRecordSizeInBytes int = 253
|
||||
|
||||
// ModbusProtocol type
|
||||
type ModbusProtocol uint16
|
||||
|
||||
// ModbusProtocol known values.
|
||||
const (
|
||||
ModbusProtocolModbus ModbusProtocol = 0
|
||||
)
|
||||
|
||||
func (mp ModbusProtocol) String() string {
|
||||
switch mp {
|
||||
default:
|
||||
return "Unknown"
|
||||
case ModbusProtocolModbus:
|
||||
return "Modbus"
|
||||
}
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
|
||||
// ModbusTCP Type
|
||||
// --------
|
||||
// Type ModbusTCP implements the DecodingLayer interface. Each ModbusTCP object
|
||||
// represents in a structured form the MODBUS Application Protocol header (MBAP) record present as the TCP
|
||||
// payload in an ModbusTCP TCP packet.
|
||||
//
|
||||
type ModbusTCP struct {
|
||||
BaseLayer // Stores the packet bytes and payload (Modbus PDU) bytes .
|
||||
|
||||
TransactionIdentifier uint16 // Identification of a MODBUS Request/Response transaction
|
||||
ProtocolIdentifier ModbusProtocol // It is used for intra-system multiplexing
|
||||
Length uint16 // Number of following bytes (includes 1 byte for UnitIdentifier + Modbus data length
|
||||
UnitIdentifier uint8 // Identification of a remote slave connected on a serial line or on other buses
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
|
||||
// LayerType returns the layer type of the ModbusTCP object, which is LayerTypeModbusTCP.
|
||||
func (d *ModbusTCP) LayerType() gopacket.LayerType {
|
||||
return LayerTypeModbusTCP
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
|
||||
// decodeModbusTCP analyses a byte slice and attempts to decode it as an ModbusTCP
|
||||
// record of a TCP packet.
|
||||
//
|
||||
// If it succeeds, it loads p with information about the packet and returns nil.
|
||||
// If it fails, it returns an error (non nil).
|
||||
//
|
||||
// This function is employed in layertypes.go to register the ModbusTCP layer.
|
||||
func decodeModbusTCP(data []byte, p gopacket.PacketBuilder) error {
|
||||
|
||||
// Attempt to decode the byte slice.
|
||||
d := &ModbusTCP{}
|
||||
err := d.DecodeFromBytes(data, p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// If the decoding worked, add the layer to the packet and set it
|
||||
// as the application layer too, if there isn't already one.
|
||||
p.AddLayer(d)
|
||||
p.SetApplicationLayer(d)
|
||||
|
||||
return p.NextDecoder(d.NextLayerType())
|
||||
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
|
||||
// DecodeFromBytes analyses a byte slice and attempts to decode it as an ModbusTCP
|
||||
// record of a TCP packet.
|
||||
//
|
||||
// Upon succeeds, it loads the ModbusTCP object with information about the packet
|
||||
// and returns nil.
|
||||
// Upon failure, it returns an error (non nil).
|
||||
func (d *ModbusTCP) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||||
|
||||
// If the data block is too short to be a MBAP record, then return an error.
|
||||
if len(data) < mbapRecordSizeInBytes+modbusPDUMinimumRecordSizeInBytes {
|
||||
df.SetTruncated()
|
||||
return errors.New("ModbusTCP packet too short")
|
||||
}
|
||||
|
||||
if len(data) > mbapRecordSizeInBytes+modbusPDUMaximumRecordSizeInBytes {
|
||||
df.SetTruncated()
|
||||
return errors.New("ModbusTCP packet too long")
|
||||
}
|
||||
|
||||
// ModbusTCP type embeds type BaseLayer which contains two fields:
|
||||
// Contents is supposed to contain the bytes of the data at this level (MPBA).
|
||||
// Payload is supposed to contain the payload of this level (PDU).
|
||||
d.BaseLayer = BaseLayer{Contents: data[:mbapRecordSizeInBytes], Payload: data[mbapRecordSizeInBytes:len(data)]}
|
||||
|
||||
// Extract the fields from the block of bytes.
|
||||
// The fields can just be copied in big endian order.
|
||||
d.TransactionIdentifier = binary.BigEndian.Uint16(data[:2])
|
||||
d.ProtocolIdentifier = ModbusProtocol(binary.BigEndian.Uint16(data[2:4]))
|
||||
d.Length = binary.BigEndian.Uint16(data[4:6])
|
||||
|
||||
// Length should have the size of the payload plus one byte (size of UnitIdentifier)
|
||||
if d.Length != uint16(len(d.BaseLayer.Payload)+1) {
|
||||
df.SetTruncated()
|
||||
return errors.New("ModbusTCP packet with wrong field value (Length)")
|
||||
}
|
||||
d.UnitIdentifier = uint8(data[6])
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
|
||||
// NextLayerType returns the layer type of the ModbusTCP payload, which is LayerTypePayload.
|
||||
func (d *ModbusTCP) NextLayerType() gopacket.LayerType {
|
||||
return gopacket.LayerTypePayload
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
|
||||
// Payload returns Modbus Protocol Data Unit (PDU) composed by Function Code and Data, it is carried within ModbusTCP packets
|
||||
func (d *ModbusTCP) Payload() []byte {
|
||||
return d.BaseLayer.Payload
|
||||
}
|
19
vendor/github.com/google/gopacket/layers/ports.go
generated
vendored
19
vendor/github.com/google/gopacket/layers/ports.go
generated
vendored
@ -61,15 +61,16 @@ 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
|
||||
443: LayerTypeTLS, // https
|
||||
502: LayerTypeModbusTCP, // modbustcp
|
||||
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
|
||||
|
32
vendor/github.com/google/gopacket/layers/ppp.go
generated
vendored
32
vendor/github.com/google/gopacket/layers/ppp.go
generated
vendored
@ -15,7 +15,8 @@ import (
|
||||
// PPP is the layer for PPP encapsulation headers.
|
||||
type PPP struct {
|
||||
BaseLayer
|
||||
PPPType PPPType
|
||||
PPPType PPPType
|
||||
HasPPTPHeader bool
|
||||
}
|
||||
|
||||
// PPPEndpoint is a singleton endpoint for PPP. Since there is no actual
|
||||
@ -36,17 +37,22 @@ func (p *PPP) LinkFlow() gopacket.Flow { return PPPFlow }
|
||||
|
||||
func decodePPP(data []byte, p gopacket.PacketBuilder) error {
|
||||
ppp := &PPP{}
|
||||
if data[0]&0x1 == 0 {
|
||||
if data[1]&0x1 == 0 {
|
||||
offset := 0
|
||||
if data[0] == 0xff && data[1] == 0x03 {
|
||||
offset = 2
|
||||
ppp.HasPPTPHeader = true
|
||||
}
|
||||
if data[offset]&0x1 == 0 {
|
||||
if data[offset+1]&0x1 == 0 {
|
||||
return errors.New("PPP has invalid type")
|
||||
}
|
||||
ppp.PPPType = PPPType(binary.BigEndian.Uint16(data[:2]))
|
||||
ppp.Contents = data[:2]
|
||||
ppp.Payload = data[2:]
|
||||
ppp.PPPType = PPPType(binary.BigEndian.Uint16(data[offset : offset+2]))
|
||||
ppp.Contents = data[offset : offset+2]
|
||||
ppp.Payload = data[offset+2:]
|
||||
} else {
|
||||
ppp.PPPType = PPPType(data[0])
|
||||
ppp.Contents = data[:1]
|
||||
ppp.Payload = data[1:]
|
||||
ppp.PPPType = PPPType(data[offset])
|
||||
ppp.Contents = data[offset : offset+1]
|
||||
ppp.Payload = data[offset+1:]
|
||||
}
|
||||
p.AddLayer(ppp)
|
||||
p.SetLinkLayer(ppp)
|
||||
@ -70,5 +76,13 @@ func (p *PPP) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOpt
|
||||
}
|
||||
bytes[0] = uint8(p.PPPType)
|
||||
}
|
||||
if p.HasPPTPHeader {
|
||||
bytes, err := b.PrependBytes(2)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
bytes[0] = 0xff
|
||||
bytes[1] = 0x03
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
550
vendor/github.com/google/gopacket/layers/sflow.go
generated
vendored
550
vendor/github.com/google/gopacket/layers/sflow.go
generated
vendored
@ -486,139 +486,148 @@ func decodeFlowSample(data *[]byte, expanded bool) (SFlowFlowSample, error) {
|
||||
|
||||
for i := uint32(0); i < s.RecordCount; i++ {
|
||||
rdf := SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
|
||||
_, flowRecordType := rdf.decode()
|
||||
enterpriseID, flowRecordType := rdf.decode()
|
||||
|
||||
switch flowRecordType {
|
||||
case SFlowTypeRawPacketFlow:
|
||||
if record, err := decodeRawPacketFlowRecord(data); err == nil {
|
||||
s.Records = append(s.Records, record)
|
||||
} else {
|
||||
return s, err
|
||||
// Try to decode when EnterpriseID is 0 signaling
|
||||
// default sflow structs are used according specification
|
||||
// Unexpected behavior detected for e.g. with pmacct
|
||||
if enterpriseID == 0 {
|
||||
switch flowRecordType {
|
||||
case SFlowTypeRawPacketFlow:
|
||||
if record, err := decodeRawPacketFlowRecord(data); err == nil {
|
||||
s.Records = append(s.Records, record)
|
||||
} else {
|
||||
return s, err
|
||||
}
|
||||
case SFlowTypeExtendedUserFlow:
|
||||
if record, err := decodeExtendedUserFlow(data); err == nil {
|
||||
s.Records = append(s.Records, record)
|
||||
} else {
|
||||
return s, err
|
||||
}
|
||||
case SFlowTypeExtendedUrlFlow:
|
||||
if record, err := decodeExtendedURLRecord(data); err == nil {
|
||||
s.Records = append(s.Records, record)
|
||||
} else {
|
||||
return s, err
|
||||
}
|
||||
case SFlowTypeExtendedSwitchFlow:
|
||||
if record, err := decodeExtendedSwitchFlowRecord(data); err == nil {
|
||||
s.Records = append(s.Records, record)
|
||||
} else {
|
||||
return s, err
|
||||
}
|
||||
case SFlowTypeExtendedRouterFlow:
|
||||
if record, err := decodeExtendedRouterFlowRecord(data); err == nil {
|
||||
s.Records = append(s.Records, record)
|
||||
} else {
|
||||
return s, err
|
||||
}
|
||||
case SFlowTypeExtendedGatewayFlow:
|
||||
if record, err := decodeExtendedGatewayFlowRecord(data); err == nil {
|
||||
s.Records = append(s.Records, record)
|
||||
} else {
|
||||
return s, err
|
||||
}
|
||||
case SFlowTypeEthernetFrameFlow:
|
||||
if record, err := decodeEthernetFrameFlowRecord(data); err == nil {
|
||||
s.Records = append(s.Records, record)
|
||||
} else {
|
||||
return s, err
|
||||
}
|
||||
case SFlowTypeIpv4Flow:
|
||||
if record, err := decodeSFlowIpv4Record(data); err == nil {
|
||||
s.Records = append(s.Records, record)
|
||||
} else {
|
||||
return s, err
|
||||
}
|
||||
case SFlowTypeIpv6Flow:
|
||||
if record, err := decodeSFlowIpv6Record(data); err == nil {
|
||||
s.Records = append(s.Records, record)
|
||||
} else {
|
||||
return s, err
|
||||
}
|
||||
case SFlowTypeExtendedMlpsFlow:
|
||||
// TODO
|
||||
skipRecord(data)
|
||||
return s, errors.New("skipping TypeExtendedMlpsFlow")
|
||||
case SFlowTypeExtendedNatFlow:
|
||||
// TODO
|
||||
skipRecord(data)
|
||||
return s, errors.New("skipping TypeExtendedNatFlow")
|
||||
case SFlowTypeExtendedMlpsTunnelFlow:
|
||||
// TODO
|
||||
skipRecord(data)
|
||||
return s, errors.New("skipping TypeExtendedMlpsTunnelFlow")
|
||||
case SFlowTypeExtendedMlpsVcFlow:
|
||||
// TODO
|
||||
skipRecord(data)
|
||||
return s, errors.New("skipping TypeExtendedMlpsVcFlow")
|
||||
case SFlowTypeExtendedMlpsFecFlow:
|
||||
// TODO
|
||||
skipRecord(data)
|
||||
return s, errors.New("skipping TypeExtendedMlpsFecFlow")
|
||||
case SFlowTypeExtendedMlpsLvpFecFlow:
|
||||
// TODO
|
||||
skipRecord(data)
|
||||
return s, errors.New("skipping TypeExtendedMlpsLvpFecFlow")
|
||||
case SFlowTypeExtendedVlanFlow:
|
||||
// TODO
|
||||
skipRecord(data)
|
||||
return s, errors.New("skipping TypeExtendedVlanFlow")
|
||||
case SFlowTypeExtendedIpv4TunnelEgressFlow:
|
||||
if record, err := decodeExtendedIpv4TunnelEgress(data); err == nil {
|
||||
s.Records = append(s.Records, record)
|
||||
} else {
|
||||
return s, err
|
||||
}
|
||||
case SFlowTypeExtendedIpv4TunnelIngressFlow:
|
||||
if record, err := decodeExtendedIpv4TunnelIngress(data); err == nil {
|
||||
s.Records = append(s.Records, record)
|
||||
} else {
|
||||
return s, err
|
||||
}
|
||||
case SFlowTypeExtendedIpv6TunnelEgressFlow:
|
||||
if record, err := decodeExtendedIpv6TunnelEgress(data); err == nil {
|
||||
s.Records = append(s.Records, record)
|
||||
} else {
|
||||
return s, err
|
||||
}
|
||||
case SFlowTypeExtendedIpv6TunnelIngressFlow:
|
||||
if record, err := decodeExtendedIpv6TunnelIngress(data); err == nil {
|
||||
s.Records = append(s.Records, record)
|
||||
} else {
|
||||
return s, err
|
||||
}
|
||||
case SFlowTypeExtendedDecapsulateEgressFlow:
|
||||
if record, err := decodeExtendedDecapsulateEgress(data); err == nil {
|
||||
s.Records = append(s.Records, record)
|
||||
} else {
|
||||
return s, err
|
||||
}
|
||||
case SFlowTypeExtendedDecapsulateIngressFlow:
|
||||
if record, err := decodeExtendedDecapsulateIngress(data); err == nil {
|
||||
s.Records = append(s.Records, record)
|
||||
} else {
|
||||
return s, err
|
||||
}
|
||||
case SFlowTypeExtendedVniEgressFlow:
|
||||
if record, err := decodeExtendedVniEgress(data); err == nil {
|
||||
s.Records = append(s.Records, record)
|
||||
} else {
|
||||
return s, err
|
||||
}
|
||||
case SFlowTypeExtendedVniIngressFlow:
|
||||
if record, err := decodeExtendedVniIngress(data); err == nil {
|
||||
s.Records = append(s.Records, record)
|
||||
} else {
|
||||
return s, err
|
||||
}
|
||||
default:
|
||||
return s, fmt.Errorf("Unsupported flow record type: %d", flowRecordType)
|
||||
}
|
||||
case SFlowTypeExtendedUserFlow:
|
||||
if record, err := decodeExtendedUserFlow(data); err == nil {
|
||||
s.Records = append(s.Records, record)
|
||||
} else {
|
||||
return s, err
|
||||
}
|
||||
case SFlowTypeExtendedUrlFlow:
|
||||
if record, err := decodeExtendedURLRecord(data); err == nil {
|
||||
s.Records = append(s.Records, record)
|
||||
} else {
|
||||
return s, err
|
||||
}
|
||||
case SFlowTypeExtendedSwitchFlow:
|
||||
if record, err := decodeExtendedSwitchFlowRecord(data); err == nil {
|
||||
s.Records = append(s.Records, record)
|
||||
} else {
|
||||
return s, err
|
||||
}
|
||||
case SFlowTypeExtendedRouterFlow:
|
||||
if record, err := decodeExtendedRouterFlowRecord(data); err == nil {
|
||||
s.Records = append(s.Records, record)
|
||||
} else {
|
||||
return s, err
|
||||
}
|
||||
case SFlowTypeExtendedGatewayFlow:
|
||||
if record, err := decodeExtendedGatewayFlowRecord(data); err == nil {
|
||||
s.Records = append(s.Records, record)
|
||||
} else {
|
||||
return s, err
|
||||
}
|
||||
case SFlowTypeEthernetFrameFlow:
|
||||
// TODO
|
||||
} else {
|
||||
skipRecord(data)
|
||||
return s, errors.New("skipping TypeEthernetFrameFlow")
|
||||
case SFlowTypeIpv4Flow:
|
||||
if record, err := decodeSFlowIpv4Record(data); err == nil {
|
||||
s.Records = append(s.Records, record)
|
||||
} else {
|
||||
return s, err
|
||||
}
|
||||
case SFlowTypeIpv6Flow:
|
||||
if record, err := decodeSFlowIpv6Record(data); err == nil {
|
||||
s.Records = append(s.Records, record)
|
||||
} else {
|
||||
return s, err
|
||||
}
|
||||
case SFlowTypeExtendedMlpsFlow:
|
||||
// TODO
|
||||
skipRecord(data)
|
||||
return s, errors.New("skipping TypeExtendedMlpsFlow")
|
||||
case SFlowTypeExtendedNatFlow:
|
||||
// TODO
|
||||
skipRecord(data)
|
||||
return s, errors.New("skipping TypeExtendedNatFlow")
|
||||
case SFlowTypeExtendedMlpsTunnelFlow:
|
||||
// TODO
|
||||
skipRecord(data)
|
||||
return s, errors.New("skipping TypeExtendedMlpsTunnelFlow")
|
||||
case SFlowTypeExtendedMlpsVcFlow:
|
||||
// TODO
|
||||
skipRecord(data)
|
||||
return s, errors.New("skipping TypeExtendedMlpsVcFlow")
|
||||
case SFlowTypeExtendedMlpsFecFlow:
|
||||
// TODO
|
||||
skipRecord(data)
|
||||
return s, errors.New("skipping TypeExtendedMlpsFecFlow")
|
||||
case SFlowTypeExtendedMlpsLvpFecFlow:
|
||||
// TODO
|
||||
skipRecord(data)
|
||||
return s, errors.New("skipping TypeExtendedMlpsLvpFecFlow")
|
||||
case SFlowTypeExtendedVlanFlow:
|
||||
// TODO
|
||||
skipRecord(data)
|
||||
return s, errors.New("skipping TypeExtendedVlanFlow")
|
||||
case SFlowTypeExtendedIpv4TunnelEgressFlow:
|
||||
if record, err := decodeExtendedIpv4TunnelEgress(data); err == nil {
|
||||
s.Records = append(s.Records, record)
|
||||
} else {
|
||||
return s, err
|
||||
}
|
||||
case SFlowTypeExtendedIpv4TunnelIngressFlow:
|
||||
if record, err := decodeExtendedIpv4TunnelIngress(data); err == nil {
|
||||
s.Records = append(s.Records, record)
|
||||
} else {
|
||||
return s, err
|
||||
}
|
||||
case SFlowTypeExtendedIpv6TunnelEgressFlow:
|
||||
if record, err := decodeExtendedIpv6TunnelEgress(data); err == nil {
|
||||
s.Records = append(s.Records, record)
|
||||
} else {
|
||||
return s, err
|
||||
}
|
||||
case SFlowTypeExtendedIpv6TunnelIngressFlow:
|
||||
if record, err := decodeExtendedIpv6TunnelIngress(data); err == nil {
|
||||
s.Records = append(s.Records, record)
|
||||
} else {
|
||||
return s, err
|
||||
}
|
||||
case SFlowTypeExtendedDecapsulateEgressFlow:
|
||||
if record, err := decodeExtendedDecapsulateEgress(data); err == nil {
|
||||
s.Records = append(s.Records, record)
|
||||
} else {
|
||||
return s, err
|
||||
}
|
||||
case SFlowTypeExtendedDecapsulateIngressFlow:
|
||||
if record, err := decodeExtendedDecapsulateIngress(data); err == nil {
|
||||
s.Records = append(s.Records, record)
|
||||
} else {
|
||||
return s, err
|
||||
}
|
||||
case SFlowTypeExtendedVniEgressFlow:
|
||||
if record, err := decodeExtendedVniEgress(data); err == nil {
|
||||
s.Records = append(s.Records, record)
|
||||
} else {
|
||||
return s, err
|
||||
}
|
||||
case SFlowTypeExtendedVniIngressFlow:
|
||||
if record, err := decodeExtendedVniIngress(data); err == nil {
|
||||
s.Records = append(s.Records, record)
|
||||
} else {
|
||||
return s, err
|
||||
}
|
||||
default:
|
||||
return s, fmt.Errorf("Unsupported flow record type: %d", flowRecordType)
|
||||
}
|
||||
}
|
||||
return s, nil
|
||||
@ -684,7 +693,12 @@ const (
|
||||
SFlowTypeTokenRingInterfaceCounters SFlowCounterRecordType = 3
|
||||
SFlowType100BaseVGInterfaceCounters SFlowCounterRecordType = 4
|
||||
SFlowTypeVLANCounters SFlowCounterRecordType = 5
|
||||
SFlowTypeLACPCounters SFlowCounterRecordType = 7
|
||||
SFlowTypeProcessorCounters SFlowCounterRecordType = 1001
|
||||
SFlowTypeOpenflowPortCounters SFlowCounterRecordType = 1004
|
||||
SFlowTypePORTNAMECounters SFlowCounterRecordType = 1005
|
||||
SFLowTypeAPPRESOURCESCounters SFlowCounterRecordType = 2203
|
||||
SFlowTypeOVSDPCounters SFlowCounterRecordType = 2207
|
||||
)
|
||||
|
||||
func (cr SFlowCounterRecordType) String() string {
|
||||
@ -699,8 +713,18 @@ func (cr SFlowCounterRecordType) String() string {
|
||||
return "100BaseVG Interface Counters"
|
||||
case SFlowTypeVLANCounters:
|
||||
return "VLAN Counters"
|
||||
case SFlowTypeLACPCounters:
|
||||
return "LACP Counters"
|
||||
case SFlowTypeProcessorCounters:
|
||||
return "Processor Counters"
|
||||
case SFlowTypeOpenflowPortCounters:
|
||||
return "Openflow Port Counters"
|
||||
case SFlowTypePORTNAMECounters:
|
||||
return "PORT NAME Counters"
|
||||
case SFLowTypeAPPRESOURCESCounters:
|
||||
return "App Resources Counters"
|
||||
case SFlowTypeOVSDPCounters:
|
||||
return "OVSDP Counters"
|
||||
default:
|
||||
return ""
|
||||
|
||||
@ -749,14 +773,47 @@ func decodeCounterSample(data *[]byte, expanded bool) (SFlowCounterSample, error
|
||||
skipRecord(data)
|
||||
return s, errors.New("skipping Type100BaseVGInterfaceCounters")
|
||||
case SFlowTypeVLANCounters:
|
||||
skipRecord(data)
|
||||
return s, errors.New("skipping TypeVLANCounters")
|
||||
if record, err := decodeVLANCounters(data); err == nil {
|
||||
s.Records = append(s.Records, record)
|
||||
} else {
|
||||
return s, err
|
||||
}
|
||||
case SFlowTypeLACPCounters:
|
||||
if record, err := decodeLACPCounters(data); err == nil {
|
||||
s.Records = append(s.Records, record)
|
||||
} else {
|
||||
return s, err
|
||||
}
|
||||
case SFlowTypeProcessorCounters:
|
||||
if record, err := decodeProcessorCounters(data); err == nil {
|
||||
s.Records = append(s.Records, record)
|
||||
} else {
|
||||
return s, err
|
||||
}
|
||||
case SFlowTypeOpenflowPortCounters:
|
||||
if record, err := decodeOpenflowportCounters(data); err == nil {
|
||||
s.Records = append(s.Records, record)
|
||||
} else {
|
||||
return s, err
|
||||
}
|
||||
case SFlowTypePORTNAMECounters:
|
||||
if record, err := decodePortnameCounters(data); err == nil {
|
||||
s.Records = append(s.Records, record)
|
||||
} else {
|
||||
return s, err
|
||||
}
|
||||
case SFLowTypeAPPRESOURCESCounters:
|
||||
if record, err := decodeAppresourcesCounters(data); err == nil {
|
||||
s.Records = append(s.Records, record)
|
||||
} else {
|
||||
return s, err
|
||||
}
|
||||
case SFlowTypeOVSDPCounters:
|
||||
if record, err := decodeOVSDPCounters(data); err == nil {
|
||||
s.Records = append(s.Records, record)
|
||||
} else {
|
||||
return s, err
|
||||
}
|
||||
default:
|
||||
return s, fmt.Errorf("Invalid counter record type: %d", counterRecordType)
|
||||
}
|
||||
@ -1970,9 +2027,18 @@ func (bcr SFlowBaseCounterRecord) GetType() SFlowCounterRecordType {
|
||||
return SFlowType100BaseVGInterfaceCounters
|
||||
case SFlowTypeVLANCounters:
|
||||
return SFlowTypeVLANCounters
|
||||
case SFlowTypeLACPCounters:
|
||||
return SFlowTypeLACPCounters
|
||||
case SFlowTypeProcessorCounters:
|
||||
return SFlowTypeProcessorCounters
|
||||
|
||||
case SFlowTypeOpenflowPortCounters:
|
||||
return SFlowTypeOpenflowPortCounters
|
||||
case SFlowTypePORTNAMECounters:
|
||||
return SFlowTypePORTNAMECounters
|
||||
case SFLowTypeAPPRESOURCESCounters:
|
||||
return SFLowTypeAPPRESOURCESCounters
|
||||
case SFlowTypeOVSDPCounters:
|
||||
return SFlowTypeOVSDPCounters
|
||||
}
|
||||
unrecognized := fmt.Sprint("Unrecognized counter record type:", bcr.Format)
|
||||
panic(unrecognized)
|
||||
@ -2135,6 +2201,83 @@ func decodeEthernetCounters(data *[]byte) (SFlowEthernetCounters, error) {
|
||||
return ec, nil
|
||||
}
|
||||
|
||||
// VLAN Counter
|
||||
|
||||
type SFlowVLANCounters struct {
|
||||
SFlowBaseCounterRecord
|
||||
VlanID uint32
|
||||
Octets uint64
|
||||
UcastPkts uint32
|
||||
MulticastPkts uint32
|
||||
BroadcastPkts uint32
|
||||
Discards uint32
|
||||
}
|
||||
|
||||
func decodeVLANCounters(data *[]byte) (SFlowVLANCounters, error) {
|
||||
vc := SFlowVLANCounters{}
|
||||
var cdf SFlowCounterDataFormat
|
||||
|
||||
*data, cdf = (*data)[4:], SFlowCounterDataFormat(binary.BigEndian.Uint32((*data)[:4]))
|
||||
vc.EnterpriseID, vc.Format = cdf.decode()
|
||||
vc.EnterpriseID, vc.Format = cdf.decode()
|
||||
*data, vc.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
|
||||
*data, vc.VlanID = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
|
||||
*data, vc.Octets = (*data)[8:], binary.BigEndian.Uint64((*data)[:8])
|
||||
*data, vc.UcastPkts = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
|
||||
*data, vc.MulticastPkts = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
|
||||
*data, vc.BroadcastPkts = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
|
||||
*data, vc.Discards = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
|
||||
return vc, nil
|
||||
}
|
||||
|
||||
//SFLLACPportState : SFlow LACP Port State (All(4) - 32 bit)
|
||||
type SFLLACPPortState struct {
|
||||
PortStateAll uint32
|
||||
}
|
||||
|
||||
//LACPcounters : LACP SFlow Counters ( 64 Bytes )
|
||||
type SFlowLACPCounters struct {
|
||||
SFlowBaseCounterRecord
|
||||
ActorSystemID net.HardwareAddr
|
||||
PartnerSystemID net.HardwareAddr
|
||||
AttachedAggID uint32
|
||||
LacpPortState SFLLACPPortState
|
||||
LACPDUsRx uint32
|
||||
MarkerPDUsRx uint32
|
||||
MarkerResponsePDUsRx uint32
|
||||
UnknownRx uint32
|
||||
IllegalRx uint32
|
||||
LACPDUsTx uint32
|
||||
MarkerPDUsTx uint32
|
||||
MarkerResponsePDUsTx uint32
|
||||
}
|
||||
|
||||
func decodeLACPCounters(data *[]byte) (SFlowLACPCounters, error) {
|
||||
la := SFlowLACPCounters{}
|
||||
var cdf SFlowCounterDataFormat
|
||||
|
||||
*data, cdf = (*data)[4:], SFlowCounterDataFormat(binary.BigEndian.Uint32((*data)[:4]))
|
||||
la.EnterpriseID, la.Format = cdf.decode()
|
||||
*data, la.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
|
||||
*data, la.ActorSystemID = (*data)[6:], (*data)[:6]
|
||||
*data = (*data)[2:] // remove padding
|
||||
*data, la.PartnerSystemID = (*data)[6:], (*data)[:6]
|
||||
*data = (*data)[2:] //remove padding
|
||||
*data, la.AttachedAggID = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
|
||||
*data, la.LacpPortState.PortStateAll = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
|
||||
*data, la.LACPDUsRx = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
|
||||
*data, la.MarkerPDUsRx = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
|
||||
*data, la.MarkerResponsePDUsRx = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
|
||||
*data, la.UnknownRx = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
|
||||
*data, la.IllegalRx = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
|
||||
*data, la.LACPDUsTx = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
|
||||
*data, la.MarkerPDUsTx = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
|
||||
*data, la.MarkerResponsePDUsTx = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
|
||||
|
||||
return la, nil
|
||||
|
||||
}
|
||||
|
||||
// **************************************************
|
||||
// Processor Counter Record
|
||||
// **************************************************
|
||||
@ -2185,3 +2328,144 @@ func decodeProcessorCounters(data *[]byte) (SFlowProcessorCounters, error) {
|
||||
|
||||
return pc, nil
|
||||
}
|
||||
|
||||
// SFlowEthernetFrameFlowRecord give additional information
|
||||
// about the sampled packet if it's available.
|
||||
// An agent may or may not provide this information.
|
||||
type SFlowEthernetFrameFlowRecord struct {
|
||||
SFlowBaseFlowRecord
|
||||
FrameLength uint32
|
||||
SrcMac net.HardwareAddr
|
||||
DstMac net.HardwareAddr
|
||||
Type uint32
|
||||
}
|
||||
|
||||
// Ethernet frame flow records have the following structure:
|
||||
|
||||
// 0 15 31
|
||||
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||
// | 20 bit Interprise (0) |12 bit format |
|
||||
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||
// | record length |
|
||||
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||
// | Source Mac Address |
|
||||
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||
// | Destination Mac Address |
|
||||
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||
// | Ethernet Packet Type |
|
||||
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||
|
||||
func decodeEthernetFrameFlowRecord(data *[]byte) (SFlowEthernetFrameFlowRecord, error) {
|
||||
es := SFlowEthernetFrameFlowRecord{}
|
||||
var fdf SFlowFlowDataFormat
|
||||
|
||||
*data, fdf = (*data)[4:], SFlowFlowDataFormat(binary.BigEndian.Uint32((*data)[:4]))
|
||||
es.EnterpriseID, es.Format = fdf.decode()
|
||||
*data, es.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
|
||||
|
||||
*data, es.FrameLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
|
||||
*data, es.SrcMac = (*data)[8:], net.HardwareAddr((*data)[:6])
|
||||
*data, es.DstMac = (*data)[8:], net.HardwareAddr((*data)[:6])
|
||||
*data, es.Type = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
|
||||
return es, nil
|
||||
}
|
||||
|
||||
//SFlowOpenflowPortCounters : OVS-Sflow OpenFlow Port Counter ( 20 Bytes )
|
||||
type SFlowOpenflowPortCounters struct {
|
||||
SFlowBaseCounterRecord
|
||||
DatapathID uint64
|
||||
PortNo uint32
|
||||
}
|
||||
|
||||
func decodeOpenflowportCounters(data *[]byte) (SFlowOpenflowPortCounters, error) {
|
||||
ofp := SFlowOpenflowPortCounters{}
|
||||
var cdf SFlowCounterDataFormat
|
||||
|
||||
*data, cdf = (*data)[4:], SFlowCounterDataFormat(binary.BigEndian.Uint32((*data)[:4]))
|
||||
ofp.EnterpriseID, ofp.Format = cdf.decode()
|
||||
*data, ofp.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
|
||||
*data, ofp.DatapathID = (*data)[8:], binary.BigEndian.Uint64((*data)[:8])
|
||||
*data, ofp.PortNo = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
|
||||
|
||||
return ofp, nil
|
||||
}
|
||||
|
||||
//SFlowAppresourcesCounters : OVS_Sflow App Resources Counter ( 48 Bytes )
|
||||
type SFlowAppresourcesCounters struct {
|
||||
SFlowBaseCounterRecord
|
||||
UserTime uint32
|
||||
SystemTime uint32
|
||||
MemUsed uint64
|
||||
MemMax uint64
|
||||
FdOpen uint32
|
||||
FdMax uint32
|
||||
ConnOpen uint32
|
||||
ConnMax uint32
|
||||
}
|
||||
|
||||
func decodeAppresourcesCounters(data *[]byte) (SFlowAppresourcesCounters, error) {
|
||||
app := SFlowAppresourcesCounters{}
|
||||
var cdf SFlowCounterDataFormat
|
||||
|
||||
*data, cdf = (*data)[4:], SFlowCounterDataFormat(binary.BigEndian.Uint32((*data)[:4]))
|
||||
app.EnterpriseID, app.Format = cdf.decode()
|
||||
*data, app.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
|
||||
*data, app.UserTime = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
|
||||
*data, app.SystemTime = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
|
||||
*data, app.MemUsed = (*data)[8:], binary.BigEndian.Uint64((*data)[:8])
|
||||
*data, app.MemMax = (*data)[8:], binary.BigEndian.Uint64((*data)[:8])
|
||||
*data, app.FdOpen = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
|
||||
*data, app.FdMax = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
|
||||
*data, app.ConnOpen = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
|
||||
*data, app.ConnMax = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
|
||||
|
||||
return app, nil
|
||||
}
|
||||
|
||||
//SFlowOVSDPCounters : OVS-Sflow DataPath Counter ( 32 Bytes )
|
||||
type SFlowOVSDPCounters struct {
|
||||
SFlowBaseCounterRecord
|
||||
NHit uint32
|
||||
NMissed uint32
|
||||
NLost uint32
|
||||
NMaskHit uint32
|
||||
NFlows uint32
|
||||
NMasks uint32
|
||||
}
|
||||
|
||||
func decodeOVSDPCounters(data *[]byte) (SFlowOVSDPCounters, error) {
|
||||
dp := SFlowOVSDPCounters{}
|
||||
var cdf SFlowCounterDataFormat
|
||||
|
||||
*data, cdf = (*data)[4:], SFlowCounterDataFormat(binary.BigEndian.Uint32((*data)[:4]))
|
||||
dp.EnterpriseID, dp.Format = cdf.decode()
|
||||
*data, dp.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
|
||||
*data, dp.NHit = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
|
||||
*data, dp.NMissed = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
|
||||
*data, dp.NLost = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
|
||||
*data, dp.NMaskHit = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
|
||||
*data, dp.NFlows = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
|
||||
*data, dp.NMasks = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
|
||||
|
||||
return dp, nil
|
||||
}
|
||||
|
||||
//SFlowPORTNAME : OVS-Sflow PORTNAME Counter Sampletype ( 20 Bytes )
|
||||
type SFlowPORTNAME struct {
|
||||
SFlowBaseCounterRecord
|
||||
Len uint32
|
||||
Str string
|
||||
}
|
||||
|
||||
func decodePortnameCounters(data *[]byte) (SFlowPORTNAME, error) {
|
||||
pn := SFlowPORTNAME{}
|
||||
var cdf SFlowCounterDataFormat
|
||||
|
||||
*data, cdf = (*data)[4:], SFlowCounterDataFormat(binary.BigEndian.Uint32((*data)[:4]))
|
||||
pn.EnterpriseID, pn.Format = cdf.decode()
|
||||
*data, pn.FlowDataLength = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
|
||||
*data, pn.Len = (*data)[4:], binary.BigEndian.Uint32((*data)[:4])
|
||||
*data, pn.Str = (*data)[8:], string(binary.BigEndian.Uint64((*data)[:8]))
|
||||
|
||||
return pn, nil
|
||||
}
|
||||
|
5
vendor/github.com/google/gopacket/layers/sip.go
generated
vendored
5
vendor/github.com/google/gopacket/layers/sip.go
generated
vendored
@ -189,6 +189,9 @@ type SIP struct {
|
||||
Method SIPMethod
|
||||
Headers map[string][]string
|
||||
|
||||
// Request
|
||||
RequestURI string
|
||||
|
||||
// Response
|
||||
IsResponse bool
|
||||
ResponseCode int
|
||||
@ -341,6 +344,8 @@ func (s *SIP) ParseFirstLine(firstLine []byte) error {
|
||||
return err
|
||||
}
|
||||
|
||||
s.RequestURI = splits[1]
|
||||
|
||||
// Validate SIP Version
|
||||
s.Version, err = GetSIPVersion(splits[2])
|
||||
if err != nil {
|
||||
|
11
vendor/github.com/google/gopacket/layers/tcp.go
generated
vendored
11
vendor/github.com/google/gopacket/layers/tcp.go
generated
vendored
@ -170,7 +170,7 @@ func (t *TCP) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOpt
|
||||
}
|
||||
bytes[start+1] = o.OptionLength
|
||||
copy(bytes[start+2:start+len(o.OptionData)+2], o.OptionData)
|
||||
start += int(o.OptionLength)
|
||||
start += len(o.OptionData) + 2
|
||||
}
|
||||
}
|
||||
copy(bytes[start:], t.Padding)
|
||||
@ -225,6 +225,10 @@ func (t *TCP) flagsAndOffset() uint16 {
|
||||
}
|
||||
|
||||
func (tcp *TCP) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||||
if len(data) < 20 {
|
||||
df.SetTruncated()
|
||||
return fmt.Errorf("Invalid TCP header. Length %d less than 20", len(data))
|
||||
}
|
||||
tcp.SrcPort = TCPPort(binary.BigEndian.Uint16(data[0:2]))
|
||||
tcp.sPort = data[0:2]
|
||||
tcp.DstPort = TCPPort(binary.BigEndian.Uint16(data[2:4]))
|
||||
@ -275,10 +279,15 @@ func (tcp *TCP) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||||
case TCPOptionKindNop: // 1 byte padding
|
||||
opt.OptionLength = 1
|
||||
default:
|
||||
if len(data) < 2 {
|
||||
df.SetTruncated()
|
||||
return fmt.Errorf("Invalid TCP option length. Length %d less than 2", len(data))
|
||||
}
|
||||
opt.OptionLength = data[1]
|
||||
if opt.OptionLength < 2 {
|
||||
return fmt.Errorf("Invalid TCP option length %d < 2", opt.OptionLength)
|
||||
} else if int(opt.OptionLength) > len(data) {
|
||||
df.SetTruncated()
|
||||
return fmt.Errorf("Invalid TCP option length %d exceeds remaining %d bytes", opt.OptionLength, len(data))
|
||||
}
|
||||
opt.OptionData = data[2:opt.OptionLength]
|
||||
|
4
vendor/github.com/google/gopacket/layers/udp.go
generated
vendored
4
vendor/github.com/google/gopacket/layers/udp.go
generated
vendored
@ -28,6 +28,10 @@ type UDP struct {
|
||||
func (u *UDP) LayerType() gopacket.LayerType { return LayerTypeUDP }
|
||||
|
||||
func (udp *UDP) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||||
if len(data) < 8 {
|
||||
df.SetTruncated()
|
||||
return fmt.Errorf("Invalid UDP header. Length %d less than 8", len(data))
|
||||
}
|
||||
udp.SrcPort = UDPPort(binary.BigEndian.Uint16(data[0:2]))
|
||||
udp.sPort = data[0:2]
|
||||
udp.DstPort = UDPPort(binary.BigEndian.Uint16(data[2:4]))
|
||||
|
3
vendor/github.com/google/gopacket/packet.go
generated
vendored
3
vendor/github.com/google/gopacket/packet.go
generated
vendored
@ -16,6 +16,7 @@ import (
|
||||
"reflect"
|
||||
"runtime/debug"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -814,7 +815,7 @@ func (p *PacketSource) packetsToChannel() {
|
||||
defer close(p.c)
|
||||
for {
|
||||
packet, err := p.NextPacket()
|
||||
if err == io.EOF {
|
||||
if err == io.EOF || err == syscall.EBADF {
|
||||
return
|
||||
} else if err == nil {
|
||||
p.c <- packet
|
||||
|
74
vendor/github.com/google/gopacket/pcap/defs_windows_386.go
generated
vendored
Normal file
74
vendor/github.com/google/gopacket/pcap/defs_windows_386.go
generated
vendored
Normal file
@ -0,0 +1,74 @@
|
||||
// Copyright 2019 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.
|
||||
|
||||
// This file contains necessary structs/constants generated from libpcap headers with cgo -godefs
|
||||
// generated with: generate_defs.exe
|
||||
// DO NOT MODIFY
|
||||
|
||||
package pcap
|
||||
|
||||
import "syscall"
|
||||
|
||||
const errorBufferSize = 0x100
|
||||
|
||||
const (
|
||||
pcapErrorNotActivated = -0x3
|
||||
pcapErrorActivated = -0x4
|
||||
pcapWarningPromisc = 0x2
|
||||
pcapErrorNoSuchDevice = -0x5
|
||||
pcapErrorDenied = -0x8
|
||||
pcapErrorNotUp = -0x9
|
||||
pcapError = -0x1
|
||||
pcapWarning = 0x1
|
||||
pcapDIN = 0x1
|
||||
pcapDOUT = 0x2
|
||||
pcapDINOUT = 0x0
|
||||
pcapNetmaskUnknown = 0xffffffff
|
||||
pcapTstampPrecisionMicro = 0x0
|
||||
pcapTstampPrecisionNano = 0x1
|
||||
)
|
||||
|
||||
type timeval struct {
|
||||
Sec int32
|
||||
Usec int32
|
||||
}
|
||||
type pcapPkthdr struct {
|
||||
Ts timeval
|
||||
Caplen uint32
|
||||
Len uint32
|
||||
}
|
||||
type pcapTPtr uintptr
|
||||
type pcapBpfInstruction struct {
|
||||
Code uint16
|
||||
Jt uint8
|
||||
Jf uint8
|
||||
K uint32
|
||||
}
|
||||
type pcapBpfProgram struct {
|
||||
Len uint32
|
||||
Insns *pcapBpfInstruction
|
||||
}
|
||||
type pcapStats struct {
|
||||
Recv uint32
|
||||
Drop uint32
|
||||
Ifdrop uint32
|
||||
}
|
||||
type pcapCint int32
|
||||
type pcapIf struct {
|
||||
Next *pcapIf
|
||||
Name *int8
|
||||
Description *int8
|
||||
Addresses *pcapAddr
|
||||
Flags uint32
|
||||
}
|
||||
|
||||
type pcapAddr struct {
|
||||
Next *pcapAddr
|
||||
Addr *syscall.RawSockaddr
|
||||
Netmask *syscall.RawSockaddr
|
||||
Broadaddr *syscall.RawSockaddr
|
||||
Dstaddr *syscall.RawSockaddr
|
||||
}
|
76
vendor/github.com/google/gopacket/pcap/defs_windows_amd64.go
generated
vendored
Normal file
76
vendor/github.com/google/gopacket/pcap/defs_windows_amd64.go
generated
vendored
Normal file
@ -0,0 +1,76 @@
|
||||
// Copyright 2019 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.
|
||||
|
||||
// This file contains necessary structs/constants generated from libpcap headers with cgo -godefs
|
||||
// generated with: generate_defs.exe
|
||||
// DO NOT MODIFY
|
||||
|
||||
package pcap
|
||||
|
||||
import "syscall"
|
||||
|
||||
const errorBufferSize = 0x100
|
||||
|
||||
const (
|
||||
pcapErrorNotActivated = -0x3
|
||||
pcapErrorActivated = -0x4
|
||||
pcapWarningPromisc = 0x2
|
||||
pcapErrorNoSuchDevice = -0x5
|
||||
pcapErrorDenied = -0x8
|
||||
pcapErrorNotUp = -0x9
|
||||
pcapError = -0x1
|
||||
pcapWarning = 0x1
|
||||
pcapDIN = 0x1
|
||||
pcapDOUT = 0x2
|
||||
pcapDINOUT = 0x0
|
||||
pcapNetmaskUnknown = 0xffffffff
|
||||
pcapTstampPrecisionMicro = 0x0
|
||||
pcapTstampPrecisionNano = 0x1
|
||||
)
|
||||
|
||||
type timeval struct {
|
||||
Sec int32
|
||||
Usec int32
|
||||
}
|
||||
type pcapPkthdr struct {
|
||||
Ts timeval
|
||||
Caplen uint32
|
||||
Len uint32
|
||||
}
|
||||
type pcapTPtr uintptr
|
||||
type pcapBpfInstruction struct {
|
||||
Code uint16
|
||||
Jt uint8
|
||||
Jf uint8
|
||||
K uint32
|
||||
}
|
||||
type pcapBpfProgram struct {
|
||||
Len uint32
|
||||
Pad_cgo_0 [4]byte
|
||||
Insns *pcapBpfInstruction
|
||||
}
|
||||
type pcapStats struct {
|
||||
Recv uint32
|
||||
Drop uint32
|
||||
Ifdrop uint32
|
||||
}
|
||||
type pcapCint int32
|
||||
type pcapIf struct {
|
||||
Next *pcapIf
|
||||
Name *int8
|
||||
Description *int8
|
||||
Addresses *pcapAddr
|
||||
Flags uint32
|
||||
Pad_cgo_0 [4]byte
|
||||
}
|
||||
|
||||
type pcapAddr struct {
|
||||
Next *pcapAddr
|
||||
Addr *syscall.RawSockaddr
|
||||
Netmask *syscall.RawSockaddr
|
||||
Broadaddr *syscall.RawSockaddr
|
||||
Dstaddr *syscall.RawSockaddr
|
||||
}
|
16
vendor/github.com/google/gopacket/pcap/doc.go
generated
vendored
16
vendor/github.com/google/gopacket/pcap/doc.go
generated
vendored
@ -12,6 +12,12 @@ This package is meant to be used with its parent,
|
||||
http://github.com/google/gopacket, although it can also be used independently
|
||||
if you just want to get packet data from the wire.
|
||||
|
||||
Depending on libpcap version, os support, or file timestamp resolution,
|
||||
nanosecond resolution is used for the internal timestamps. Returned timestamps
|
||||
are always scaled to nanosecond resolution due to the usage of time.Time.
|
||||
libpcap must be at least version 1.5 to support nanosecond timestamps. OpenLive
|
||||
supports only microsecond resolution.
|
||||
|
||||
Reading PCAP Files
|
||||
|
||||
The following code can be used to read in data from a pcap file.
|
||||
@ -28,7 +34,7 @@ The following code can be used to read in data from a pcap file.
|
||||
Reading Live Packets
|
||||
|
||||
The following code can be used to read in data from a live device, in this case
|
||||
"eth0".
|
||||
"eth0". Be aware, that OpenLive only supports microsecond resolution.
|
||||
|
||||
if handle, err := pcap.OpenLive("eth0", 1600, true, pcap.BlockForever); err != nil {
|
||||
panic(err)
|
||||
@ -97,10 +103,10 @@ PCAP File Writing
|
||||
This package does not implement PCAP file writing. However, gopacket/pcapgo
|
||||
does! Look there if you'd like to write PCAP files.
|
||||
|
||||
Note For Windows 10 Users
|
||||
Note For Windows Users
|
||||
|
||||
If you're trying to use 64-bit winpcap on Windows 10, you might have to do
|
||||
the crazy hijinks detailed at
|
||||
http://stackoverflow.com/questions/38047858/compile-gopacket-on-windows-64bit
|
||||
gopacket can use winpcap or npcap. If both are installed at the same time,
|
||||
npcap is preferred. Make sure the right windows service is loaded (npcap for npcap
|
||||
and npf for winpcap).
|
||||
*/
|
||||
package pcap
|
||||
|
157
vendor/github.com/google/gopacket/pcap/generate_defs.go
generated
vendored
Normal file
157
vendor/github.com/google/gopacket/pcap/generate_defs.go
generated
vendored
Normal file
@ -0,0 +1,157 @@
|
||||
// Copyright 2019 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.
|
||||
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
// This file generates the godefs needed for the windows version.
|
||||
// Rebuild is only necessary if additional libpcap functionality is implemented, or a new arch is implemented in golang.
|
||||
// Call with go run generate_windows.go [-I includepath]
|
||||
// Needs npcap sdk, go tool cgo, and gofmt to work. Location of npcap includes can be specified with -I
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const header = `// Copyright 2019 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.
|
||||
|
||||
// This file contains necessary structs/constants generated from libpcap headers with cgo -godefs
|
||||
// generated with: %s
|
||||
// DO NOT MODIFY
|
||||
|
||||
`
|
||||
|
||||
const source = `
|
||||
package pcap
|
||||
|
||||
//#include <pcap.h>
|
||||
import "C"
|
||||
|
||||
import "syscall" // needed for RawSockaddr
|
||||
|
||||
const errorBufferSize = C.PCAP_ERRBUF_SIZE
|
||||
|
||||
const (
|
||||
pcapErrorNotActivated = C.PCAP_ERROR_NOT_ACTIVATED
|
||||
pcapErrorActivated = C.PCAP_ERROR_ACTIVATED
|
||||
pcapWarningPromisc = C.PCAP_WARNING_PROMISC_NOTSUP
|
||||
pcapErrorNoSuchDevice = C.PCAP_ERROR_NO_SUCH_DEVICE
|
||||
pcapErrorDenied = C.PCAP_ERROR_PERM_DENIED
|
||||
pcapErrorNotUp = C.PCAP_ERROR_IFACE_NOT_UP
|
||||
pcapError = C.PCAP_ERROR
|
||||
pcapWarning = C.PCAP_WARNING
|
||||
pcapDIN = C.PCAP_D_IN
|
||||
pcapDOUT = C.PCAP_D_OUT
|
||||
pcapDINOUT = C.PCAP_D_INOUT
|
||||
pcapNetmaskUnknown = C.PCAP_NETMASK_UNKNOWN
|
||||
pcapTstampPrecisionMicro = C.PCAP_TSTAMP_PRECISION_MICRO
|
||||
pcapTstampPrecisionNano = C.PCAP_TSTAMP_PRECISION_NANO
|
||||
)
|
||||
|
||||
type timeval C.struct_timeval
|
||||
type pcapPkthdr C.struct_pcap_pkthdr
|
||||
type pcapTPtr uintptr
|
||||
type pcapBpfInstruction C.struct_bpf_insn
|
||||
type pcapBpfProgram C.struct_bpf_program
|
||||
type pcapStats C.struct_pcap_stat
|
||||
type pcapCint C.int
|
||||
type pcapIf C.struct_pcap_if
|
||||
// +godefs map struct_sockaddr syscall.RawSockaddr
|
||||
type pcapAddr C.struct_pcap_addr
|
||||
`
|
||||
|
||||
var includes = flag.String("I", "C:\\npcap-sdk-1.01\\Include", "Include path containing libpcap headers")
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
infile, err := ioutil.TempFile(".", "defs.*.go")
|
||||
if err != nil {
|
||||
log.Fatal("Couldn't create temporary source file: ", err)
|
||||
}
|
||||
defer infile.Close()
|
||||
defer os.Remove(infile.Name())
|
||||
|
||||
_, err = infile.WriteString(source)
|
||||
if err != nil {
|
||||
log.Fatalf("Couldn't write definitions to temporary file %s: %s", infile.Name(), err)
|
||||
}
|
||||
err = infile.Close()
|
||||
if err != nil {
|
||||
log.Fatalf("Couldn't close temporary source file %s: %s", infile.Name(), err)
|
||||
}
|
||||
|
||||
archs := []string{"386", "amd64"}
|
||||
for _, arch := range archs {
|
||||
env := append(os.Environ(), "GOARCH="+arch)
|
||||
cmd := exec.Command("go", "tool", "cgo", "-godefs", "--", "-I", *includes, infile.Name())
|
||||
cmd.Env = env
|
||||
cmd.Stderr = os.Stderr
|
||||
var generated bytes.Buffer
|
||||
cmd.Stdout = &generated
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
log.Fatalf("Couldn't generated defs for %s: %s\n", arch, err)
|
||||
}
|
||||
|
||||
cmd = exec.Command("gofmt")
|
||||
cmd.Env = env
|
||||
cmd.Stderr = os.Stderr
|
||||
outName := fmt.Sprintf("defs_windows_%s.go", arch)
|
||||
out, err := os.Create(outName)
|
||||
if err != nil {
|
||||
log.Fatalf("Couldn't open file %s: %s", outName, err)
|
||||
}
|
||||
cmd.Stdout = out
|
||||
in, err := cmd.StdinPipe()
|
||||
if err != nil {
|
||||
log.Fatal("Couldn't create input pipe for gofmt: ", err)
|
||||
}
|
||||
err = cmd.Start()
|
||||
if err != nil {
|
||||
log.Fatal("Couldn't start gofmt: ", err)
|
||||
}
|
||||
|
||||
_, err = fmt.Fprintf(in, header, strings.Join(append([]string{filepath.Base(os.Args[0])}, os.Args[1:]...), " "))
|
||||
if err != nil {
|
||||
log.Fatal("Couldn't write header to gofmt: ", err)
|
||||
}
|
||||
|
||||
for {
|
||||
line, err := generated.ReadBytes('\n')
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
// remove godefs comments
|
||||
if bytes.HasPrefix(line, []byte("//")) {
|
||||
continue
|
||||
}
|
||||
_, err = in.Write(line)
|
||||
if err != nil {
|
||||
log.Fatal("Couldn't write line to gofmt: ", err)
|
||||
}
|
||||
}
|
||||
in.Close()
|
||||
err = cmd.Wait()
|
||||
if err != nil {
|
||||
log.Fatal("gofmt failed: ", err)
|
||||
}
|
||||
out.Close()
|
||||
}
|
||||
}
|
622
vendor/github.com/google/gopacket/pcap/pcap.go
generated
vendored
622
vendor/github.com/google/gopacket/pcap/pcap.go
generated
vendored
File diff suppressed because it is too large
Load Diff
5
vendor/github.com/google/gopacket/pcap/pcap_tester.go
generated
vendored
5
vendor/github.com/google/gopacket/pcap/pcap_tester.go
generated
vendored
@ -15,7 +15,6 @@ import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
@ -35,7 +34,7 @@ func generatePackets() {
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
ifaces, err := net.Interfaces()
|
||||
ifaces, err := pcap.FindAllDevs()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
@ -51,7 +50,7 @@ func main() {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func tryCapture(iface net.Interface) error {
|
||||
func tryCapture(iface pcap.Interface) error {
|
||||
if iface.Name[:2] == "lo" {
|
||||
return errors.New("skipping loopback")
|
||||
}
|
||||
|
640
vendor/github.com/google/gopacket/pcap/pcap_unix.go
generated
vendored
640
vendor/github.com/google/gopacket/pcap/pcap_unix.go
generated
vendored
@ -9,9 +9,131 @@
|
||||
|
||||
package pcap
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/google/gopacket"
|
||||
|
||||
"github.com/google/gopacket/layers"
|
||||
)
|
||||
|
||||
/*
|
||||
#cgo solaris LDFLAGS: -L /opt/local/lib -lpcap
|
||||
#cgo linux LDFLAGS: -lpcap
|
||||
#cgo dragonfly LDFLAGS: -lpcap
|
||||
#cgo freebsd LDFLAGS: -lpcap
|
||||
#cgo openbsd LDFLAGS: -lpcap
|
||||
#cgo netbsd LDFLAGS: -lpcap
|
||||
#cgo darwin LDFLAGS: -lpcap
|
||||
#include <stdlib.h>
|
||||
#include <pcap.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// Some old versions of pcap don't define this constant.
|
||||
#ifndef PCAP_NETMASK_UNKNOWN
|
||||
#define PCAP_NETMASK_UNKNOWN 0xffffffff
|
||||
#endif
|
||||
|
||||
// libpcap doesn't actually export its version in a #define-guardable way,
|
||||
// so we have to use other defined things to differentiate versions.
|
||||
// We assume at least libpcap v1.1 at the moment.
|
||||
// See http://upstream-tracker.org/versions/libpcap.html
|
||||
|
||||
#ifndef PCAP_ERROR_TSTAMP_PRECISION_NOTSUP // < v1.5
|
||||
#define PCAP_ERROR_TSTAMP_PRECISION_NOTSUP -12
|
||||
|
||||
int pcap_set_immediate_mode(pcap_t *p, int mode) {
|
||||
return PCAP_ERROR;
|
||||
}
|
||||
|
||||
// libpcap version < v1.5 doesn't have timestamp precision (everything is microsecond)
|
||||
//
|
||||
// This means *_tstamp_* functions and macros are missing. Therefore, we emulate these
|
||||
// functions here and pretend the setting the precision works. This is actually the way
|
||||
// the pcap_open_offline_with_tstamp_precision works, because it doesn't return an error
|
||||
// if it was not possible to set the precision, which depends on support by the given file.
|
||||
// => The rest of the functions always pretend as if they could set nano precision and
|
||||
// verify the actual precision with pcap_get_tstamp_precision, which is emulated for <v1.5
|
||||
// to always return micro resolution.
|
||||
|
||||
#define PCAP_TSTAMP_PRECISION_MICRO 0
|
||||
#define PCAP_TSTAMP_PRECISION_NANO 1
|
||||
|
||||
pcap_t *pcap_open_offline_with_tstamp_precision(const char *fname, u_int precision,
|
||||
char *errbuf) {
|
||||
return pcap_open_offline(fname, errbuf);
|
||||
}
|
||||
|
||||
int pcap_set_tstamp_precision(pcap_t *p, int tstamp_precision) {
|
||||
if (tstamp_precision == PCAP_TSTAMP_PRECISION_MICRO)
|
||||
return 0;
|
||||
return PCAP_ERROR_TSTAMP_PRECISION_NOTSUP;
|
||||
}
|
||||
|
||||
int pcap_get_tstamp_precision(pcap_t *p) {
|
||||
return PCAP_TSTAMP_PRECISION_MICRO
|
||||
}
|
||||
|
||||
#ifndef PCAP_TSTAMP_HOST // < v1.2
|
||||
|
||||
int pcap_set_tstamp_type(pcap_t* p, int t) { return -1; }
|
||||
int pcap_list_tstamp_types(pcap_t* p, int** t) { return 0; }
|
||||
void pcap_free_tstamp_types(int *tstamp_types) {}
|
||||
const char* pcap_tstamp_type_val_to_name(int t) {
|
||||
return "pcap timestamp types not supported";
|
||||
}
|
||||
int pcap_tstamp_type_name_to_val(const char* t) {
|
||||
return PCAP_ERROR;
|
||||
}
|
||||
|
||||
#endif // < v1.2
|
||||
#endif // < v1.5
|
||||
|
||||
#ifndef PCAP_ERROR_PROMISC_PERM_DENIED
|
||||
#define PCAP_ERROR_PROMISC_PERM_DENIED -11
|
||||
#endif
|
||||
|
||||
// Windows, Macs, and Linux all use different time types. Joy.
|
||||
#ifdef __APPLE__
|
||||
#define gopacket_time_secs_t __darwin_time_t
|
||||
#define gopacket_time_usecs_t __darwin_suseconds_t
|
||||
#elif __ANDROID__
|
||||
#define gopacket_time_secs_t __kernel_time_t
|
||||
#define gopacket_time_usecs_t __kernel_suseconds_t
|
||||
#elif __GLIBC__
|
||||
#define gopacket_time_secs_t __time_t
|
||||
#define gopacket_time_usecs_t __suseconds_t
|
||||
#else // Some form of linux/bsd/etc...
|
||||
#include <sys/param.h>
|
||||
#ifdef __OpenBSD__
|
||||
#define gopacket_time_secs_t u_int32_t
|
||||
#define gopacket_time_usecs_t u_int32_t
|
||||
#else
|
||||
#define gopacket_time_secs_t time_t
|
||||
#define gopacket_time_usecs_t suseconds_t
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// The things we do to avoid pointers escaping to the heap...
|
||||
// According to https://github.com/the-tcpdump-group/libpcap/blob/1131a7c26c6f4d4772e4a2beeaf7212f4dea74ac/pcap.c#L398-L406 ,
|
||||
// the return value of pcap_next_ex could be greater than 1 for success.
|
||||
// Let's just make it 1 if it comes bigger than 1.
|
||||
int pcap_next_ex_escaping(pcap_t *p, uintptr_t pkt_hdr, uintptr_t pkt_data) {
|
||||
int ex = pcap_next_ex(p, (struct pcap_pkthdr**)(pkt_hdr), (const u_char**)(pkt_data));
|
||||
if (ex > 1) {
|
||||
ex = 1;
|
||||
}
|
||||
return ex;
|
||||
}
|
||||
|
||||
int pcap_offline_filter_escaping(struct bpf_program *fp, uintptr_t pkt_hdr, uintptr_t pkt) {
|
||||
return pcap_offline_filter(fp, (struct pcap_pkthdr*)(pkt_hdr), (const u_char*)(pkt));
|
||||
}
|
||||
|
||||
// pcap_wait returns when the next packet is available or the timeout expires.
|
||||
// Since it uses pcap_get_selectable_fd, it will not work in Windows.
|
||||
@ -38,22 +160,526 @@ int pcap_wait(pcap_t *p, int usec) {
|
||||
// block indefinitely if no timeout provided
|
||||
return select(fd+1, &fds, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
// libpcap version < v1.5 doesn't have timestamp precision (everything is microsecond)
|
||||
// see pcap.go for an explanation of why precision is ignored
|
||||
#ifndef PCAP_ERROR_TSTAMP_PRECISION_NOTSUP // < v1.5
|
||||
pcap_t *pcap_fopen_offline_with_tstamp_precision(FILE *fp, u_int precision,
|
||||
char *errbuf) {
|
||||
return pcap_fopen_offline(fp, errbuf);
|
||||
}
|
||||
#endif // < v1.5
|
||||
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"unsafe"
|
||||
const errorBufferSize = C.PCAP_ERRBUF_SIZE
|
||||
|
||||
const (
|
||||
pcapErrorNotActivated = C.PCAP_ERROR_NOT_ACTIVATED
|
||||
pcapErrorActivated = C.PCAP_ERROR_ACTIVATED
|
||||
pcapWarningPromisc = C.PCAP_WARNING_PROMISC_NOTSUP
|
||||
pcapErrorNoSuchDevice = C.PCAP_ERROR_NO_SUCH_DEVICE
|
||||
pcapErrorDenied = C.PCAP_ERROR_PERM_DENIED
|
||||
pcapErrorNotUp = C.PCAP_ERROR_IFACE_NOT_UP
|
||||
pcapWarning = C.PCAP_WARNING
|
||||
pcapDIN = C.PCAP_D_IN
|
||||
pcapDOUT = C.PCAP_D_OUT
|
||||
pcapDINOUT = C.PCAP_D_INOUT
|
||||
pcapNetmaskUnknown = C.PCAP_NETMASK_UNKNOWN
|
||||
pcapTstampPrecisionMicro = C.PCAP_TSTAMP_PRECISION_MICRO
|
||||
pcapTstampPrecisionNano = C.PCAP_TSTAMP_PRECISION_NANO
|
||||
)
|
||||
|
||||
type pcapPkthdr C.struct_pcap_pkthdr
|
||||
type pcapTPtr *C.struct_pcap
|
||||
type pcapBpfProgram C.struct_bpf_program
|
||||
|
||||
func (h *pcapPkthdr) getSec() int64 {
|
||||
return int64(h.ts.tv_sec)
|
||||
}
|
||||
|
||||
func (h *pcapPkthdr) getUsec() int64 {
|
||||
return int64(h.ts.tv_usec)
|
||||
}
|
||||
|
||||
func (h *pcapPkthdr) getLen() int {
|
||||
return int(h.len)
|
||||
}
|
||||
|
||||
func (h *pcapPkthdr) getCaplen() int {
|
||||
return int(h.caplen)
|
||||
}
|
||||
|
||||
func pcapGetTstampPrecision(cptr pcapTPtr) int {
|
||||
return int(C.pcap_get_tstamp_precision(cptr))
|
||||
}
|
||||
|
||||
func pcapSetTstampPrecision(cptr pcapTPtr, precision int) error {
|
||||
ret := C.pcap_set_tstamp_precision(cptr, C.int(precision))
|
||||
if ret < 0 {
|
||||
return errors.New(C.GoString(C.pcap_geterr(cptr)))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func statusError(status C.int) error {
|
||||
return errors.New(C.GoString(C.pcap_statustostr(status)))
|
||||
}
|
||||
|
||||
func pcapOpenLive(device string, snaplen int, pro int, timeout int) (*Handle, error) {
|
||||
buf := (*C.char)(C.calloc(errorBufferSize, 1))
|
||||
defer C.free(unsafe.Pointer(buf))
|
||||
|
||||
dev := C.CString(device)
|
||||
defer C.free(unsafe.Pointer(dev))
|
||||
|
||||
cptr := C.pcap_open_live(dev, C.int(snaplen), C.int(pro), C.int(timeout), buf)
|
||||
if cptr == nil {
|
||||
return nil, errors.New(C.GoString(buf))
|
||||
}
|
||||
return &Handle{cptr: cptr}, nil
|
||||
}
|
||||
|
||||
func openOffline(file string) (handle *Handle, err error) {
|
||||
buf := (*C.char)(C.calloc(errorBufferSize, 1))
|
||||
defer C.free(unsafe.Pointer(buf))
|
||||
cf := C.CString(file)
|
||||
defer C.free(unsafe.Pointer(cf))
|
||||
|
||||
cptr := C.pcap_open_offline_with_tstamp_precision(cf, C.PCAP_TSTAMP_PRECISION_NANO, buf)
|
||||
if cptr == nil {
|
||||
return nil, errors.New(C.GoString(buf))
|
||||
}
|
||||
return &Handle{cptr: cptr}, nil
|
||||
}
|
||||
|
||||
func (p *Handle) pcapClose() {
|
||||
if p.cptr != nil {
|
||||
C.pcap_close(p.cptr)
|
||||
}
|
||||
p.cptr = nil
|
||||
}
|
||||
|
||||
func (p *Handle) pcapGeterr() error {
|
||||
return errors.New(C.GoString(C.pcap_geterr(p.cptr)))
|
||||
}
|
||||
|
||||
func (p *Handle) pcapStats() (*Stats, error) {
|
||||
var cstats C.struct_pcap_stat
|
||||
if C.pcap_stats(p.cptr, &cstats) < 0 {
|
||||
return nil, p.pcapGeterr()
|
||||
}
|
||||
return &Stats{
|
||||
PacketsReceived: int(cstats.ps_recv),
|
||||
PacketsDropped: int(cstats.ps_drop),
|
||||
PacketsIfDropped: int(cstats.ps_ifdrop),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// for libpcap < 1.8 pcap_compile is NOT thread-safe, so protect it.
|
||||
var pcapCompileMu sync.Mutex
|
||||
|
||||
func (p *Handle) pcapCompile(expr string, maskp uint32) (pcapBpfProgram, error) {
|
||||
var bpf pcapBpfProgram
|
||||
cexpr := C.CString(expr)
|
||||
defer C.free(unsafe.Pointer(cexpr))
|
||||
|
||||
pcapCompileMu.Lock()
|
||||
defer pcapCompileMu.Unlock()
|
||||
if C.pcap_compile(p.cptr, (*C.struct_bpf_program)(&bpf), cexpr, 1, C.bpf_u_int32(maskp)) < 0 {
|
||||
return bpf, p.pcapGeterr()
|
||||
}
|
||||
return bpf, nil
|
||||
}
|
||||
|
||||
func (p pcapBpfProgram) free() {
|
||||
C.pcap_freecode((*C.struct_bpf_program)(&p))
|
||||
}
|
||||
|
||||
func (p pcapBpfProgram) toBPFInstruction() []BPFInstruction {
|
||||
bpfInsn := (*[bpfInstructionBufferSize]C.struct_bpf_insn)(unsafe.Pointer(p.bf_insns))[0:p.bf_len:p.bf_len]
|
||||
bpfInstruction := make([]BPFInstruction, len(bpfInsn), len(bpfInsn))
|
||||
|
||||
for i, v := range bpfInsn {
|
||||
bpfInstruction[i].Code = uint16(v.code)
|
||||
bpfInstruction[i].Jt = uint8(v.jt)
|
||||
bpfInstruction[i].Jf = uint8(v.jf)
|
||||
bpfInstruction[i].K = uint32(v.k)
|
||||
}
|
||||
return bpfInstruction
|
||||
}
|
||||
|
||||
func pcapBpfProgramFromInstructions(bpfInstructions []BPFInstruction) pcapBpfProgram {
|
||||
var bpf pcapBpfProgram
|
||||
bpf.bf_len = C.u_int(len(bpfInstructions))
|
||||
cbpfInsns := C.calloc(C.size_t(len(bpfInstructions)), C.size_t(unsafe.Sizeof(bpfInstructions[0])))
|
||||
gbpfInsns := (*[bpfInstructionBufferSize]C.struct_bpf_insn)(cbpfInsns)
|
||||
|
||||
for i, v := range bpfInstructions {
|
||||
gbpfInsns[i].code = C.u_short(v.Code)
|
||||
gbpfInsns[i].jt = C.u_char(v.Jt)
|
||||
gbpfInsns[i].jf = C.u_char(v.Jf)
|
||||
gbpfInsns[i].k = C.bpf_u_int32(v.K)
|
||||
}
|
||||
|
||||
bpf.bf_insns = (*C.struct_bpf_insn)(cbpfInsns)
|
||||
return bpf
|
||||
}
|
||||
|
||||
func pcapLookupnet(device string) (netp, maskp uint32, err error) {
|
||||
errorBuf := (*C.char)(C.calloc(errorBufferSize, 1))
|
||||
defer C.free(unsafe.Pointer(errorBuf))
|
||||
dev := C.CString(device)
|
||||
defer C.free(unsafe.Pointer(dev))
|
||||
if C.pcap_lookupnet(
|
||||
dev,
|
||||
(*C.bpf_u_int32)(unsafe.Pointer(&netp)),
|
||||
(*C.bpf_u_int32)(unsafe.Pointer(&maskp)),
|
||||
errorBuf,
|
||||
) < 0 {
|
||||
return 0, 0, errors.New(C.GoString(errorBuf))
|
||||
// We can't lookup the network, but that could be because the interface
|
||||
// doesn't have an IPv4.
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (b *BPF) pcapOfflineFilter(ci gopacket.CaptureInfo, data []byte) bool {
|
||||
hdr := (*C.struct_pcap_pkthdr)(&b.hdr)
|
||||
hdr.ts.tv_sec = C.gopacket_time_secs_t(ci.Timestamp.Unix())
|
||||
hdr.ts.tv_usec = C.gopacket_time_usecs_t(ci.Timestamp.Nanosecond() / 1000)
|
||||
hdr.caplen = C.bpf_u_int32(len(data)) // Trust actual length over ci.Length.
|
||||
hdr.len = C.bpf_u_int32(ci.Length)
|
||||
dataptr := (*C.u_char)(unsafe.Pointer(&data[0]))
|
||||
return C.pcap_offline_filter_escaping((*C.struct_bpf_program)(&b.bpf),
|
||||
C.uintptr_t(uintptr(unsafe.Pointer(hdr))),
|
||||
C.uintptr_t(uintptr(unsafe.Pointer(dataptr)))) != 0
|
||||
}
|
||||
|
||||
func (p *Handle) pcapSetfilter(bpf pcapBpfProgram) error {
|
||||
if C.pcap_setfilter(p.cptr, (*C.struct_bpf_program)(&bpf)) < 0 {
|
||||
return p.pcapGeterr()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Handle) pcapListDatalinks() (datalinks []Datalink, err error) {
|
||||
var dltbuf *C.int
|
||||
|
||||
n := int(C.pcap_list_datalinks(p.cptr, &dltbuf))
|
||||
if n < 0 {
|
||||
return nil, p.pcapGeterr()
|
||||
}
|
||||
|
||||
defer C.pcap_free_datalinks(dltbuf)
|
||||
|
||||
datalinks = make([]Datalink, n)
|
||||
|
||||
dltArray := (*[1 << 28]C.int)(unsafe.Pointer(dltbuf))
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
datalinks[i].Name = pcapDatalinkValToName(int((*dltArray)[i]))
|
||||
datalinks[i].Description = pcapDatalinkValToDescription(int((*dltArray)[i]))
|
||||
}
|
||||
|
||||
return datalinks, nil
|
||||
}
|
||||
|
||||
func pcapOpenDead(linkType layers.LinkType, captureLength int) (*Handle, error) {
|
||||
cptr := C.pcap_open_dead(C.int(linkType), C.int(captureLength))
|
||||
if cptr == nil {
|
||||
return nil, errors.New("error opening dead capture")
|
||||
}
|
||||
|
||||
return &Handle{cptr: cptr}, nil
|
||||
}
|
||||
|
||||
func (p *Handle) pcapNextPacketEx() NextError {
|
||||
// This horrible magic allows us to pass a ptr-to-ptr to pcap_next_ex
|
||||
// without causing that ptr-to-ptr to itself be allocated on the heap.
|
||||
// Since Handle itself survives through the duration of the pcap_next_ex
|
||||
// call, this should be perfectly safe for GC stuff, etc.
|
||||
|
||||
return NextError(C.pcap_next_ex_escaping(p.cptr, C.uintptr_t(uintptr(unsafe.Pointer(&p.pkthdr))), C.uintptr_t(uintptr(unsafe.Pointer(&p.bufptr)))))
|
||||
}
|
||||
|
||||
func (p *Handle) pcapDatalink() layers.LinkType {
|
||||
return layers.LinkType(C.pcap_datalink(p.cptr))
|
||||
}
|
||||
|
||||
func (p *Handle) pcapSetDatalink(dlt layers.LinkType) error {
|
||||
if C.pcap_set_datalink(p.cptr, C.int(dlt)) < 0 {
|
||||
return p.pcapGeterr()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func pcapDatalinkValToName(dlt int) string {
|
||||
return C.GoString(C.pcap_datalink_val_to_name(C.int(dlt)))
|
||||
}
|
||||
|
||||
func pcapDatalinkValToDescription(dlt int) string {
|
||||
return C.GoString(C.pcap_datalink_val_to_description(C.int(dlt)))
|
||||
}
|
||||
|
||||
func pcapDatalinkNameToVal(name string) int {
|
||||
cptr := C.CString(name)
|
||||
defer C.free(unsafe.Pointer(cptr))
|
||||
return int(C.pcap_datalink_name_to_val(cptr))
|
||||
}
|
||||
|
||||
func pcapLibVersion() string {
|
||||
return C.GoString(C.pcap_lib_version())
|
||||
}
|
||||
|
||||
func (p *Handle) isOpen() bool {
|
||||
return p.cptr != nil
|
||||
}
|
||||
|
||||
type pcapDevices struct {
|
||||
all, cur *C.pcap_if_t
|
||||
}
|
||||
|
||||
func (p pcapDevices) free() {
|
||||
C.pcap_freealldevs((*C.pcap_if_t)(p.all))
|
||||
}
|
||||
|
||||
func (p *pcapDevices) next() bool {
|
||||
if p.cur == nil {
|
||||
p.cur = p.all
|
||||
if p.cur == nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
if p.cur.next == nil {
|
||||
return false
|
||||
}
|
||||
p.cur = p.cur.next
|
||||
return true
|
||||
}
|
||||
|
||||
func (p pcapDevices) name() string {
|
||||
return C.GoString(p.cur.name)
|
||||
}
|
||||
|
||||
func (p pcapDevices) description() string {
|
||||
return C.GoString(p.cur.description)
|
||||
}
|
||||
|
||||
func (p pcapDevices) flags() uint32 {
|
||||
return uint32(p.cur.flags)
|
||||
}
|
||||
|
||||
type pcapAddresses struct {
|
||||
all, cur *C.pcap_addr_t
|
||||
}
|
||||
|
||||
func (p *pcapAddresses) next() bool {
|
||||
if p.cur == nil {
|
||||
p.cur = p.all
|
||||
if p.cur == nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
if p.cur.next == nil {
|
||||
return false
|
||||
}
|
||||
p.cur = p.cur.next
|
||||
return true
|
||||
}
|
||||
|
||||
func (p pcapAddresses) addr() *syscall.RawSockaddr {
|
||||
return (*syscall.RawSockaddr)(unsafe.Pointer(p.cur.addr))
|
||||
}
|
||||
|
||||
func (p pcapAddresses) netmask() *syscall.RawSockaddr {
|
||||
return (*syscall.RawSockaddr)(unsafe.Pointer(p.cur.netmask))
|
||||
}
|
||||
|
||||
func (p pcapAddresses) broadaddr() *syscall.RawSockaddr {
|
||||
return (*syscall.RawSockaddr)(unsafe.Pointer(p.cur.broadaddr))
|
||||
}
|
||||
|
||||
func (p pcapAddresses) dstaddr() *syscall.RawSockaddr {
|
||||
return (*syscall.RawSockaddr)(unsafe.Pointer(p.cur.dstaddr))
|
||||
}
|
||||
|
||||
func (p pcapDevices) addresses() pcapAddresses {
|
||||
return pcapAddresses{all: p.cur.addresses}
|
||||
}
|
||||
|
||||
func pcapFindAllDevs() (pcapDevices, error) {
|
||||
var buf *C.char
|
||||
buf = (*C.char)(C.calloc(errorBufferSize, 1))
|
||||
defer C.free(unsafe.Pointer(buf))
|
||||
var alldevsp pcapDevices
|
||||
|
||||
if C.pcap_findalldevs((**C.pcap_if_t)(&alldevsp.all), buf) < 0 {
|
||||
return pcapDevices{}, errors.New(C.GoString(buf))
|
||||
}
|
||||
return alldevsp, nil
|
||||
}
|
||||
|
||||
func (p *Handle) pcapSendpacket(data []byte) error {
|
||||
if C.pcap_sendpacket(p.cptr, (*C.u_char)(&data[0]), (C.int)(len(data))) < 0 {
|
||||
return p.pcapGeterr()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Handle) pcapSetdirection(direction Direction) error {
|
||||
if status := C.pcap_setdirection(p.cptr, (C.pcap_direction_t)(direction)); status < 0 {
|
||||
return statusError(status)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Handle) pcapSnapshot() int {
|
||||
return int(C.pcap_snapshot(p.cptr))
|
||||
}
|
||||
|
||||
func (t TimestampSource) pcapTstampTypeValToName() string {
|
||||
return C.GoString(C.pcap_tstamp_type_val_to_name(C.int(t)))
|
||||
}
|
||||
|
||||
func pcapTstampTypeNameToVal(s string) (TimestampSource, error) {
|
||||
cs := C.CString(s)
|
||||
defer C.free(unsafe.Pointer(cs))
|
||||
t := C.pcap_tstamp_type_name_to_val(cs)
|
||||
if t < 0 {
|
||||
return 0, statusError(t)
|
||||
}
|
||||
return TimestampSource(t), nil
|
||||
}
|
||||
|
||||
func (p *InactiveHandle) pcapGeterr() error {
|
||||
return errors.New(C.GoString(C.pcap_geterr(p.cptr)))
|
||||
}
|
||||
|
||||
func (p *InactiveHandle) pcapActivate() (*Handle, activateError) {
|
||||
ret := activateError(C.pcap_activate(p.cptr))
|
||||
if ret != aeNoError {
|
||||
return nil, ret
|
||||
}
|
||||
h := &Handle{
|
||||
cptr: p.cptr,
|
||||
}
|
||||
p.cptr = nil
|
||||
return h, ret
|
||||
}
|
||||
|
||||
func (p *InactiveHandle) pcapClose() {
|
||||
if p.cptr != nil {
|
||||
C.pcap_close(p.cptr)
|
||||
}
|
||||
}
|
||||
|
||||
func pcapCreate(device string) (*InactiveHandle, error) {
|
||||
buf := (*C.char)(C.calloc(errorBufferSize, 1))
|
||||
defer C.free(unsafe.Pointer(buf))
|
||||
dev := C.CString(device)
|
||||
defer C.free(unsafe.Pointer(dev))
|
||||
|
||||
cptr := C.pcap_create(dev, buf)
|
||||
if cptr == nil {
|
||||
return nil, errors.New(C.GoString(buf))
|
||||
}
|
||||
return &InactiveHandle{cptr: cptr}, nil
|
||||
}
|
||||
|
||||
func (p *InactiveHandle) pcapSetSnaplen(snaplen int) error {
|
||||
if status := C.pcap_set_snaplen(p.cptr, C.int(snaplen)); status < 0 {
|
||||
return statusError(status)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *InactiveHandle) pcapSetPromisc(promisc bool) error {
|
||||
var pro C.int
|
||||
if promisc {
|
||||
pro = 1
|
||||
}
|
||||
if status := C.pcap_set_promisc(p.cptr, pro); status < 0 {
|
||||
return statusError(status)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *InactiveHandle) pcapSetTimeout(timeout time.Duration) error {
|
||||
if status := C.pcap_set_timeout(p.cptr, C.int(timeoutMillis(timeout))); status < 0 {
|
||||
return statusError(status)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *InactiveHandle) pcapListTstampTypes() (out []TimestampSource) {
|
||||
var types *C.int
|
||||
n := int(C.pcap_list_tstamp_types(p.cptr, &types))
|
||||
if n < 0 {
|
||||
return // public interface doesn't have error :(
|
||||
}
|
||||
defer C.pcap_free_tstamp_types(types)
|
||||
typesArray := (*[1 << 28]C.int)(unsafe.Pointer(types))
|
||||
for i := 0; i < n; i++ {
|
||||
out = append(out, TimestampSource((*typesArray)[i]))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (p *InactiveHandle) pcapSetTstampType(t TimestampSource) error {
|
||||
if status := C.pcap_set_tstamp_type(p.cptr, C.int(t)); status < 0 {
|
||||
return statusError(status)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *InactiveHandle) pcapSetRfmon(monitor bool) error {
|
||||
var mon C.int
|
||||
if monitor {
|
||||
mon = 1
|
||||
}
|
||||
switch canset := C.pcap_can_set_rfmon(p.cptr); canset {
|
||||
case 0:
|
||||
return CannotSetRFMon
|
||||
case 1:
|
||||
// success
|
||||
default:
|
||||
return statusError(canset)
|
||||
}
|
||||
if status := C.pcap_set_rfmon(p.cptr, mon); status != 0 {
|
||||
return statusError(status)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *InactiveHandle) pcapSetBufferSize(bufferSize int) error {
|
||||
if status := C.pcap_set_buffer_size(p.cptr, C.int(bufferSize)); status < 0 {
|
||||
return statusError(status)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *InactiveHandle) pcapSetImmediateMode(mode bool) error {
|
||||
var md C.int
|
||||
if mode {
|
||||
md = 1
|
||||
}
|
||||
if status := C.pcap_set_immediate_mode(p.cptr, md); status < 0 {
|
||||
return statusError(status)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Handle) setNonBlocking() error {
|
||||
buf := (*C.char)(C.calloc(errorBufferSize, 1))
|
||||
defer C.free(unsafe.Pointer(buf))
|
||||
|
||||
// Change the device to non-blocking, we'll use pcap_wait to wait until the
|
||||
// handle is ready to read.
|
||||
if v := C.pcap_setnonblock(p.cptr, 1, buf); v == -1 {
|
||||
if v := C.pcap_setnonblock(p.cptr, 1, buf); v < -1 {
|
||||
return errors.New(C.GoString(buf))
|
||||
}
|
||||
|
||||
@ -68,7 +694,7 @@ func (p *Handle) waitForPacket() {
|
||||
usec := timeoutMillis(p.timeout) * 1000
|
||||
usec -= 100
|
||||
|
||||
C.pcap_wait(p.cptr, usec)
|
||||
C.pcap_wait(p.cptr, C.int(usec))
|
||||
}
|
||||
|
||||
// openOfflineFile returns contents of input file as a *Handle.
|
||||
@ -79,7 +705,7 @@ func openOfflineFile(file *os.File) (handle *Handle, err error) {
|
||||
defer C.free(unsafe.Pointer(cmode))
|
||||
cf := C.fdopen(C.int(file.Fd()), cmode)
|
||||
|
||||
cptr := C.pcap_fopen_offline(cf, buf)
|
||||
cptr := C.pcap_fopen_offline_with_tstamp_precision(cf, C.PCAP_TSTAMP_PRECISION_NANO, buf)
|
||||
if cptr == nil {
|
||||
return nil, errors.New(C.GoString(buf))
|
||||
}
|
||||
|
790
vendor/github.com/google/gopacket/pcap/pcap_windows.go
generated
vendored
790
vendor/github.com/google/gopacket/pcap/pcap_windows.go
generated
vendored
@ -7,18 +7,779 @@
|
||||
|
||||
package pcap
|
||||
|
||||
/*
|
||||
#include <pcap.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/google/gopacket"
|
||||
"github.com/google/gopacket/layers"
|
||||
)
|
||||
|
||||
const npcapPath = "\\Npcap"
|
||||
|
||||
func initDllPath(kernel32 syscall.Handle) {
|
||||
setDllDirectory, err := syscall.GetProcAddress(kernel32, "SetDllDirectoryA")
|
||||
if err != nil {
|
||||
// we can't do anything since SetDllDirectoryA is missing - fall back to use first wpcap.dll we encounter
|
||||
return
|
||||
}
|
||||
getSystemDirectory, err := syscall.GetProcAddress(kernel32, "GetSystemDirectoryA")
|
||||
if err != nil {
|
||||
// we can't do anything since SetDllDirectoryA is missing - fall back to use first wpcap.dll we encounter
|
||||
return
|
||||
}
|
||||
buf := make([]byte, 4096)
|
||||
r, _, _ := syscall.Syscall(getSystemDirectory, 2, uintptr(unsafe.Pointer(&buf[0])), uintptr(len(buf)), 0)
|
||||
if r == 0 || r > 4096-uintptr(len(npcapPath))-1 {
|
||||
// we can't do anything since SetDllDirectoryA is missing - fall back to use first wpcap.dll we encounter
|
||||
return
|
||||
}
|
||||
copy(buf[r:], npcapPath)
|
||||
_, _, _ = syscall.Syscall(setDllDirectory, 1, uintptr(unsafe.Pointer(&buf[0])), 0, 0)
|
||||
// ignore errors here - we just fallback to load wpcap.dll from default locations
|
||||
}
|
||||
|
||||
// loadedDllPath will hold the full pathname of the loaded wpcap.dll after init if possible
|
||||
var loadedDllPath = "wpcap.dll"
|
||||
|
||||
func initLoadedDllPath(kernel32 syscall.Handle) {
|
||||
getModuleFileName, err := syscall.GetProcAddress(kernel32, "GetModuleFileNameA")
|
||||
if err != nil {
|
||||
// we can't get the filename of the loaded module in this case - just leave default of wpcap.dll
|
||||
return
|
||||
}
|
||||
buf := make([]byte, 4096)
|
||||
r, _, _ := syscall.Syscall(getModuleFileName, 3, uintptr(wpcapHandle), uintptr(unsafe.Pointer(&buf[0])), uintptr(len(buf)))
|
||||
if r == 0 {
|
||||
// we can't get the filename of the loaded module in this case - just leave default of wpcap.dll
|
||||
return
|
||||
}
|
||||
loadedDllPath = string(buf[:int(r)])
|
||||
}
|
||||
|
||||
func mustLoad(fun string) uintptr {
|
||||
addr, err := syscall.GetProcAddress(wpcapHandle, fun)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Couldn't load function %s from %s", fun, loadedDllPath))
|
||||
}
|
||||
return addr
|
||||
}
|
||||
|
||||
func mightLoad(fun string) uintptr {
|
||||
addr, err := syscall.GetProcAddress(wpcapHandle, fun)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return addr
|
||||
}
|
||||
|
||||
func byteSliceToString(bval []byte) string {
|
||||
for i := range bval {
|
||||
if bval[i] == 0 {
|
||||
return string(bval[:i])
|
||||
}
|
||||
}
|
||||
return string(bval[:])
|
||||
}
|
||||
|
||||
// bytePtrToString returns a string copied from pointer to a null terminated byte array
|
||||
// WARNING: ONLY SAFE WITH IF r POINTS TO C MEMORY!
|
||||
// govet will complain about this function for the reason stated above
|
||||
func bytePtrToString(r uintptr) string {
|
||||
if r == 0 {
|
||||
return ""
|
||||
}
|
||||
bval := (*[1 << 30]byte)(unsafe.Pointer(r))
|
||||
return byteSliceToString(bval[:])
|
||||
}
|
||||
|
||||
var wpcapHandle syscall.Handle
|
||||
var msvcrtHandle syscall.Handle
|
||||
var (
|
||||
callocPtr,
|
||||
pcapStrerrorPtr,
|
||||
pcapStatustostrPtr,
|
||||
pcapOpenLivePtr,
|
||||
pcapOpenOfflinePtr,
|
||||
pcapClosePtr,
|
||||
pcapGeterrPtr,
|
||||
pcapStatsPtr,
|
||||
pcapCompilePtr,
|
||||
pcapFreecodePtr,
|
||||
pcapLookupnetPtr,
|
||||
pcapOfflineFilterPtr,
|
||||
pcapSetfilterPtr,
|
||||
pcapListDatalinksPtr,
|
||||
pcapFreeDatalinksPtr,
|
||||
pcapDatalinkValToNamePtr,
|
||||
pcapDatalinkValToDescriptionPtr,
|
||||
pcapOpenDeadPtr,
|
||||
pcapNextExPtr,
|
||||
pcapDatalinkPtr,
|
||||
pcapSetDatalinkPtr,
|
||||
pcapDatalinkNameToValPtr,
|
||||
pcapLibVersionPtr,
|
||||
pcapFreealldevsPtr,
|
||||
pcapFindalldevsPtr,
|
||||
pcapSendpacketPtr,
|
||||
pcapSetdirectionPtr,
|
||||
pcapSnapshotPtr,
|
||||
pcapTstampTypeValToNamePtr,
|
||||
pcapTstampTypeNameToValPtr,
|
||||
pcapListTstampTypesPtr,
|
||||
pcapFreeTstampTypesPtr,
|
||||
pcapSetTstampTypePtr,
|
||||
pcapGetTstampPrecisionPtr,
|
||||
pcapSetTstampPrecisionPtr,
|
||||
pcapOpenOfflineWithTstampPrecisionPtr,
|
||||
pcapHOpenOfflineWithTstampPrecisionPtr,
|
||||
pcapActivatePtr,
|
||||
pcapCreatePtr,
|
||||
pcapSetSnaplenPtr,
|
||||
pcapSetPromiscPtr,
|
||||
pcapSetTimeoutPtr,
|
||||
pcapCanSetRfmonPtr,
|
||||
pcapSetRfmonPtr,
|
||||
pcapSetBufferSizePtr,
|
||||
pcapSetImmediateModePtr,
|
||||
pcapHopenOfflinePtr uintptr
|
||||
)
|
||||
|
||||
func init() {
|
||||
kernel32, err := syscall.LoadLibrary("kernel32.dll")
|
||||
if err != nil {
|
||||
panic("couldn't load kernel32.dll")
|
||||
}
|
||||
defer syscall.FreeLibrary(kernel32)
|
||||
|
||||
initDllPath(kernel32)
|
||||
|
||||
wpcapHandle, err = syscall.LoadLibrary("wpcap.dll")
|
||||
if err != nil {
|
||||
panic("Couldn't load wpcap.dll")
|
||||
}
|
||||
initLoadedDllPath(kernel32)
|
||||
msvcrtHandle, err = syscall.LoadLibrary("msvcrt.dll")
|
||||
if err != nil {
|
||||
panic("Couldn't load msvcrt.dll")
|
||||
}
|
||||
callocPtr, err = syscall.GetProcAddress(msvcrtHandle, "calloc")
|
||||
if err != nil {
|
||||
panic("Couldn't get calloc function")
|
||||
}
|
||||
|
||||
pcapStrerrorPtr = mustLoad("pcap_strerror")
|
||||
pcapStatustostrPtr = mightLoad("pcap_statustostr") // not available on winpcap
|
||||
pcapOpenLivePtr = mustLoad("pcap_open_live")
|
||||
pcapOpenOfflinePtr = mustLoad("pcap_open_offline")
|
||||
pcapClosePtr = mustLoad("pcap_close")
|
||||
pcapGeterrPtr = mustLoad("pcap_geterr")
|
||||
pcapStatsPtr = mustLoad("pcap_stats")
|
||||
pcapCompilePtr = mustLoad("pcap_compile")
|
||||
pcapFreecodePtr = mustLoad("pcap_freecode")
|
||||
pcapLookupnetPtr = mustLoad("pcap_lookupnet")
|
||||
pcapOfflineFilterPtr = mustLoad("pcap_offline_filter")
|
||||
pcapSetfilterPtr = mustLoad("pcap_setfilter")
|
||||
pcapListDatalinksPtr = mustLoad("pcap_list_datalinks")
|
||||
pcapFreeDatalinksPtr = mustLoad("pcap_free_datalinks")
|
||||
pcapDatalinkValToNamePtr = mustLoad("pcap_datalink_val_to_name")
|
||||
pcapDatalinkValToDescriptionPtr = mustLoad("pcap_datalink_val_to_description")
|
||||
pcapOpenDeadPtr = mustLoad("pcap_open_dead")
|
||||
pcapNextExPtr = mustLoad("pcap_next_ex")
|
||||
pcapDatalinkPtr = mustLoad("pcap_datalink")
|
||||
pcapSetDatalinkPtr = mustLoad("pcap_set_datalink")
|
||||
pcapDatalinkNameToValPtr = mustLoad("pcap_datalink_name_to_val")
|
||||
pcapLibVersionPtr = mustLoad("pcap_lib_version")
|
||||
pcapFreealldevsPtr = mustLoad("pcap_freealldevs")
|
||||
pcapFindalldevsPtr = mustLoad("pcap_findalldevs")
|
||||
pcapSendpacketPtr = mustLoad("pcap_sendpacket")
|
||||
pcapSetdirectionPtr = mustLoad("pcap_setdirection")
|
||||
pcapSnapshotPtr = mustLoad("pcap_snapshot")
|
||||
//libpcap <1.2 doesn't have pcap_*_tstamp_* functions
|
||||
pcapTstampTypeValToNamePtr = mightLoad("pcap_tstamp_type_val_to_name")
|
||||
pcapTstampTypeNameToValPtr = mightLoad("pcap_tstamp_type_name_to_val")
|
||||
pcapListTstampTypesPtr = mightLoad("pcap_list_tstamp_types")
|
||||
pcapFreeTstampTypesPtr = mightLoad("pcap_free_tstamp_types")
|
||||
pcapSetTstampTypePtr = mightLoad("pcap_set_tstamp_type")
|
||||
pcapGetTstampPrecisionPtr = mightLoad("pcap_get_tstamp_precision")
|
||||
pcapSetTstampPrecisionPtr = mightLoad("pcap_set_tstamp_precision")
|
||||
pcapOpenOfflineWithTstampPrecisionPtr = mightLoad("pcap_open_offline_with_tstamp_precision")
|
||||
pcapHOpenOfflineWithTstampPrecisionPtr = mightLoad("pcap_hopen_offline_with_tstamp_precision")
|
||||
pcapActivatePtr = mustLoad("pcap_activate")
|
||||
pcapCreatePtr = mustLoad("pcap_create")
|
||||
pcapSetSnaplenPtr = mustLoad("pcap_set_snaplen")
|
||||
pcapSetPromiscPtr = mustLoad("pcap_set_promisc")
|
||||
pcapSetTimeoutPtr = mustLoad("pcap_set_timeout")
|
||||
//winpcap does not support rfmon
|
||||
pcapCanSetRfmonPtr = mightLoad("pcap_can_set_rfmon")
|
||||
pcapSetRfmonPtr = mightLoad("pcap_set_rfmon")
|
||||
pcapSetBufferSizePtr = mustLoad("pcap_set_buffer_size")
|
||||
//libpcap <1.5 does not have pcap_set_immediate_mode
|
||||
pcapSetImmediateModePtr = mightLoad("pcap_set_immediate_mode")
|
||||
pcapHopenOfflinePtr = mustLoad("pcap_hopen_offline")
|
||||
}
|
||||
|
||||
func (h *pcapPkthdr) getSec() int64 {
|
||||
return int64(h.Ts.Sec)
|
||||
}
|
||||
|
||||
func (h *pcapPkthdr) getUsec() int64 {
|
||||
return int64(h.Ts.Usec)
|
||||
}
|
||||
|
||||
func (h *pcapPkthdr) getLen() int {
|
||||
return int(h.Len)
|
||||
}
|
||||
|
||||
func (h *pcapPkthdr) getCaplen() int {
|
||||
return int(h.Caplen)
|
||||
}
|
||||
|
||||
func statusError(status pcapCint) error {
|
||||
var ret uintptr
|
||||
if pcapStatustostrPtr == 0 {
|
||||
ret, _, _ = syscall.Syscall(pcapStrerrorPtr, 1, uintptr(status), 0, 0)
|
||||
} else {
|
||||
ret, _, _ = syscall.Syscall(pcapStatustostrPtr, 1, uintptr(status), 0, 0)
|
||||
}
|
||||
return errors.New(bytePtrToString(ret))
|
||||
}
|
||||
|
||||
func pcapGetTstampPrecision(cptr pcapTPtr) int {
|
||||
if pcapGetTstampPrecisionPtr == 0 {
|
||||
return pcapTstampPrecisionMicro
|
||||
}
|
||||
ret, _, _ := syscall.Syscall(pcapGetTstampPrecisionPtr, 1, uintptr(cptr), 0, 0)
|
||||
return int(pcapCint(ret))
|
||||
}
|
||||
|
||||
func pcapSetTstampPrecision(cptr pcapTPtr, precision int) error {
|
||||
if pcapSetTstampPrecisionPtr == 0 {
|
||||
return errors.New("Not supported")
|
||||
}
|
||||
ret, _, _ := syscall.Syscall(pcapSetTstampPrecisionPtr, 2, uintptr(cptr), uintptr(precision), 0)
|
||||
if pcapCint(ret) < 0 {
|
||||
return errors.New("Not supported")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func pcapOpenLive(device string, snaplen int, pro int, timeout int) (*Handle, error) {
|
||||
buf := make([]byte, errorBufferSize)
|
||||
dev, err := syscall.BytePtrFromString(device)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cptr, _, _ := syscall.Syscall6(pcapOpenLivePtr, 5, uintptr(unsafe.Pointer(dev)), uintptr(snaplen), uintptr(pro), uintptr(timeout), uintptr(unsafe.Pointer(&buf[0])), 0)
|
||||
|
||||
if cptr == 0 {
|
||||
return nil, errors.New(byteSliceToString(buf))
|
||||
}
|
||||
return &Handle{cptr: pcapTPtr(cptr)}, nil
|
||||
}
|
||||
|
||||
func openOffline(file string) (handle *Handle, err error) {
|
||||
buf := make([]byte, errorBufferSize)
|
||||
f, err := syscall.BytePtrFromString(file)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var cptr uintptr
|
||||
if pcapOpenOfflineWithTstampPrecisionPtr == 0 {
|
||||
cptr, _, _ = syscall.Syscall(pcapOpenOfflinePtr, 2, uintptr(unsafe.Pointer(f)), uintptr(unsafe.Pointer(&buf[0])), 0)
|
||||
} else {
|
||||
cptr, _, _ = syscall.Syscall(pcapOpenOfflineWithTstampPrecisionPtr, 3, uintptr(unsafe.Pointer(f)), uintptr(pcapTstampPrecisionNano), uintptr(unsafe.Pointer(&buf[0])))
|
||||
}
|
||||
|
||||
if cptr == 0 {
|
||||
return nil, errors.New(byteSliceToString(buf))
|
||||
}
|
||||
|
||||
h := &Handle{cptr: pcapTPtr(cptr)}
|
||||
return h, nil
|
||||
}
|
||||
|
||||
func (p *Handle) pcapClose() {
|
||||
if p.cptr != 0 {
|
||||
_, _, _ = syscall.Syscall(pcapClosePtr, 1, uintptr(p.cptr), 0, 0)
|
||||
}
|
||||
p.cptr = 0
|
||||
}
|
||||
|
||||
func (p *Handle) pcapGeterr() error {
|
||||
ret, _, _ := syscall.Syscall(pcapGeterrPtr, 1, uintptr(p.cptr), 0, 0)
|
||||
return errors.New(bytePtrToString(ret))
|
||||
}
|
||||
|
||||
func (p *Handle) pcapStats() (*Stats, error) {
|
||||
var cstats pcapStats
|
||||
ret, _, _ := syscall.Syscall(pcapStatsPtr, 2, uintptr(p.cptr), uintptr(unsafe.Pointer(&cstats)), 0)
|
||||
if pcapCint(ret) < 0 {
|
||||
return nil, p.pcapGeterr()
|
||||
}
|
||||
return &Stats{
|
||||
PacketsReceived: int(cstats.Recv),
|
||||
PacketsDropped: int(cstats.Drop),
|
||||
PacketsIfDropped: int(cstats.Ifdrop),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// for libpcap < 1.8 pcap_compile is NOT thread-safe, so protect it.
|
||||
var pcapCompileMu sync.Mutex
|
||||
|
||||
func (p *Handle) pcapCompile(expr string, maskp uint32) (pcapBpfProgram, error) {
|
||||
var bpf pcapBpfProgram
|
||||
cexpr, err := syscall.BytePtrFromString(expr)
|
||||
if err != nil {
|
||||
return pcapBpfProgram{}, err
|
||||
}
|
||||
pcapCompileMu.Lock()
|
||||
defer pcapCompileMu.Unlock()
|
||||
res, _, _ := syscall.Syscall6(pcapCompilePtr, 5, uintptr(p.cptr), uintptr(unsafe.Pointer(&bpf)), uintptr(unsafe.Pointer(cexpr)), uintptr(1), uintptr(maskp), 0)
|
||||
if pcapCint(res) < 0 {
|
||||
return bpf, p.pcapGeterr()
|
||||
}
|
||||
return bpf, nil
|
||||
}
|
||||
|
||||
func (p pcapBpfProgram) free() {
|
||||
_, _, _ = syscall.Syscall(pcapFreecodePtr, 1, uintptr(unsafe.Pointer(&p)), 0, 0)
|
||||
}
|
||||
|
||||
func (p pcapBpfProgram) toBPFInstruction() []BPFInstruction {
|
||||
bpfInsn := (*[bpfInstructionBufferSize]pcapBpfInstruction)(unsafe.Pointer(p.Insns))[0:p.Len:p.Len]
|
||||
bpfInstruction := make([]BPFInstruction, len(bpfInsn), len(bpfInsn))
|
||||
|
||||
for i, v := range bpfInsn {
|
||||
bpfInstruction[i].Code = v.Code
|
||||
bpfInstruction[i].Jt = v.Jt
|
||||
bpfInstruction[i].Jf = v.Jf
|
||||
bpfInstruction[i].K = v.K
|
||||
}
|
||||
return bpfInstruction
|
||||
}
|
||||
|
||||
func pcapBpfProgramFromInstructions(bpfInstructions []BPFInstruction) pcapBpfProgram {
|
||||
var bpf pcapBpfProgram
|
||||
bpf.Len = uint32(len(bpfInstructions))
|
||||
cbpfInsns, _, _ := syscall.Syscall(callocPtr, 2, uintptr(len(bpfInstructions)), uintptr(unsafe.Sizeof(bpfInstructions[0])), 0)
|
||||
gbpfInsns := (*[bpfInstructionBufferSize]pcapBpfInstruction)(unsafe.Pointer(cbpfInsns))
|
||||
|
||||
for i, v := range bpfInstructions {
|
||||
gbpfInsns[i].Code = v.Code
|
||||
gbpfInsns[i].Jt = v.Jt
|
||||
gbpfInsns[i].Jf = v.Jf
|
||||
gbpfInsns[i].K = v.K
|
||||
}
|
||||
|
||||
bpf.Insns = (*pcapBpfInstruction)(unsafe.Pointer(cbpfInsns))
|
||||
return bpf
|
||||
}
|
||||
|
||||
func pcapLookupnet(device string) (netp, maskp uint32, err error) {
|
||||
buf := make([]byte, errorBufferSize)
|
||||
dev, err := syscall.BytePtrFromString(device)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
e, _, _ := syscall.Syscall6(pcapLookupnetPtr, 4, uintptr(unsafe.Pointer(dev)), uintptr(unsafe.Pointer(&netp)), uintptr(unsafe.Pointer(&maskp)), uintptr(unsafe.Pointer(&buf[0])), 0, 0)
|
||||
if pcapCint(e) < 0 {
|
||||
return 0, 0, errors.New(byteSliceToString(buf))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (b *BPF) pcapOfflineFilter(ci gopacket.CaptureInfo, data []byte) bool {
|
||||
var hdr pcapPkthdr
|
||||
hdr.Ts.Sec = int32(ci.Timestamp.Unix())
|
||||
hdr.Ts.Usec = int32(ci.Timestamp.Nanosecond() / 1000)
|
||||
hdr.Caplen = uint32(len(data)) // Trust actual length over ci.Length.
|
||||
hdr.Len = uint32(ci.Length)
|
||||
e, _, _ := syscall.Syscall(pcapOfflineFilterPtr, 3, uintptr(unsafe.Pointer(&b.bpf)), uintptr(unsafe.Pointer(&hdr)), uintptr(unsafe.Pointer(&data[0])))
|
||||
return e != 0
|
||||
}
|
||||
|
||||
func (p *Handle) pcapSetfilter(bpf pcapBpfProgram) error {
|
||||
e, _, _ := syscall.Syscall(pcapSetfilterPtr, 2, uintptr(p.cptr), uintptr(unsafe.Pointer(&bpf)), 0)
|
||||
if pcapCint(e) < 0 {
|
||||
return p.pcapGeterr()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Handle) pcapListDatalinks() (datalinks []Datalink, err error) {
|
||||
var dltbuf *pcapCint
|
||||
ret, _, _ := syscall.Syscall(pcapListDatalinksPtr, 2, uintptr(p.cptr), uintptr(unsafe.Pointer(&dltbuf)), 0)
|
||||
|
||||
n := int(pcapCint(ret))
|
||||
|
||||
if n < 0 {
|
||||
return nil, p.pcapGeterr()
|
||||
}
|
||||
defer syscall.Syscall(pcapFreeDatalinksPtr, 1, uintptr(unsafe.Pointer(dltbuf)), 0, 0)
|
||||
|
||||
datalinks = make([]Datalink, n)
|
||||
|
||||
dltArray := (*[1 << 28]pcapCint)(unsafe.Pointer(dltbuf))
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
datalinks[i].Name = pcapDatalinkValToName(int((*dltArray)[i]))
|
||||
datalinks[i].Description = pcapDatalinkValToDescription(int((*dltArray)[i]))
|
||||
}
|
||||
|
||||
return datalinks, nil
|
||||
}
|
||||
|
||||
func pcapOpenDead(linkType layers.LinkType, captureLength int) (*Handle, error) {
|
||||
cptr, _, _ := syscall.Syscall(pcapOpenDeadPtr, 2, uintptr(linkType), uintptr(captureLength), 0)
|
||||
if cptr == 0 {
|
||||
return nil, errors.New("error opening dead capture")
|
||||
}
|
||||
|
||||
return &Handle{cptr: pcapTPtr(cptr)}, nil
|
||||
}
|
||||
|
||||
func (p *Handle) pcapNextPacketEx() NextError {
|
||||
r, _, _ := syscall.Syscall(pcapNextExPtr, 3, uintptr(p.cptr), uintptr(unsafe.Pointer(&p.pkthdr)), uintptr(unsafe.Pointer(&p.bufptr)))
|
||||
ret := pcapCint(r)
|
||||
// According to https://github.com/the-tcpdump-group/libpcap/blob/1131a7c26c6f4d4772e4a2beeaf7212f4dea74ac/pcap.c#L398-L406 ,
|
||||
// the return value of pcap_next_ex could be greater than 1 for success.
|
||||
// Let's just make it 1 if it comes bigger than 1.
|
||||
if ret > 1 {
|
||||
ret = 1
|
||||
}
|
||||
return NextError(ret)
|
||||
}
|
||||
|
||||
func (p *Handle) pcapDatalink() layers.LinkType {
|
||||
ret, _, _ := syscall.Syscall(pcapDatalinkPtr, 1, uintptr(p.cptr), 0, 0)
|
||||
return layers.LinkType(ret)
|
||||
}
|
||||
|
||||
func (p *Handle) pcapSetDatalink(dlt layers.LinkType) error {
|
||||
ret, _, _ := syscall.Syscall(pcapSetDatalinkPtr, 2, uintptr(p.cptr), uintptr(dlt), 0)
|
||||
if pcapCint(ret) < 0 {
|
||||
return p.pcapGeterr()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func pcapDatalinkValToName(dlt int) string {
|
||||
ret, _, _ := syscall.Syscall(pcapDatalinkValToNamePtr, 1, uintptr(dlt), 0, 0)
|
||||
return bytePtrToString(ret)
|
||||
}
|
||||
|
||||
func pcapDatalinkValToDescription(dlt int) string {
|
||||
ret, _, _ := syscall.Syscall(pcapDatalinkValToDescriptionPtr, 1, uintptr(dlt), 0, 0)
|
||||
return bytePtrToString(ret)
|
||||
}
|
||||
|
||||
func pcapDatalinkNameToVal(name string) int {
|
||||
cptr, err := syscall.BytePtrFromString(name)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
ret, _, _ := syscall.Syscall(pcapDatalinkNameToValPtr, 1, uintptr(unsafe.Pointer(cptr)), 0, 0)
|
||||
return int(pcapCint(ret))
|
||||
}
|
||||
|
||||
func pcapLibVersion() string {
|
||||
ret, _, _ := syscall.Syscall(pcapLibVersionPtr, 0, 0, 0, 0)
|
||||
return bytePtrToString(ret)
|
||||
}
|
||||
|
||||
func (p *Handle) isOpen() bool {
|
||||
return p.cptr != 0
|
||||
}
|
||||
|
||||
type pcapDevices struct {
|
||||
all, cur *pcapIf
|
||||
}
|
||||
|
||||
func (p pcapDevices) free() {
|
||||
syscall.Syscall(pcapFreealldevsPtr, 1, uintptr(unsafe.Pointer(p.all)), 0, 0)
|
||||
}
|
||||
|
||||
func (p *pcapDevices) next() bool {
|
||||
if p.cur == nil {
|
||||
p.cur = p.all
|
||||
if p.cur == nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
if p.cur.Next == nil {
|
||||
return false
|
||||
}
|
||||
p.cur = p.cur.Next
|
||||
return true
|
||||
}
|
||||
|
||||
func (p pcapDevices) name() string {
|
||||
return bytePtrToString(uintptr(unsafe.Pointer(p.cur.Name)))
|
||||
}
|
||||
|
||||
func (p pcapDevices) description() string {
|
||||
return bytePtrToString(uintptr(unsafe.Pointer(p.cur.Description)))
|
||||
}
|
||||
|
||||
func (p pcapDevices) flags() uint32 {
|
||||
return p.cur.Flags
|
||||
}
|
||||
|
||||
type pcapAddresses struct {
|
||||
all, cur *pcapAddr
|
||||
}
|
||||
|
||||
func (p *pcapAddresses) next() bool {
|
||||
if p.cur == nil {
|
||||
p.cur = p.all
|
||||
if p.cur == nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
if p.cur.Next == nil {
|
||||
return false
|
||||
}
|
||||
p.cur = p.cur.Next
|
||||
return true
|
||||
}
|
||||
|
||||
func (p pcapAddresses) addr() *syscall.RawSockaddr {
|
||||
return p.cur.Addr
|
||||
}
|
||||
|
||||
func (p pcapAddresses) netmask() *syscall.RawSockaddr {
|
||||
return p.cur.Netmask
|
||||
}
|
||||
|
||||
func (p pcapAddresses) broadaddr() *syscall.RawSockaddr {
|
||||
return p.cur.Broadaddr
|
||||
}
|
||||
|
||||
func (p pcapAddresses) dstaddr() *syscall.RawSockaddr {
|
||||
return p.cur.Dstaddr
|
||||
}
|
||||
|
||||
func (p pcapDevices) addresses() pcapAddresses {
|
||||
return pcapAddresses{all: p.cur.Addresses}
|
||||
}
|
||||
|
||||
func pcapFindAllDevs() (pcapDevices, error) {
|
||||
buf := make([]byte, errorBufferSize)
|
||||
var alldevsp pcapDevices
|
||||
|
||||
ret, _, _ := syscall.Syscall(pcapFindalldevsPtr, 2, uintptr(unsafe.Pointer(&alldevsp.all)), uintptr(unsafe.Pointer(&buf[0])), 0)
|
||||
|
||||
if pcapCint(ret) < 0 {
|
||||
return pcapDevices{}, errors.New(byteSliceToString(buf))
|
||||
}
|
||||
return alldevsp, nil
|
||||
}
|
||||
|
||||
func (p *Handle) pcapSendpacket(data []byte) error {
|
||||
ret, _, _ := syscall.Syscall(pcapSendpacketPtr, 3, uintptr(p.cptr), uintptr(unsafe.Pointer(&data[0])), uintptr(len(data)))
|
||||
if pcapCint(ret) < 0 {
|
||||
return p.pcapGeterr()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Handle) pcapSetdirection(direction Direction) error {
|
||||
status, _, _ := syscall.Syscall(pcapSetdirectionPtr, 2, uintptr(p.cptr), uintptr(direction), 0)
|
||||
if pcapCint(status) < 0 {
|
||||
return statusError(pcapCint(status))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Handle) pcapSnapshot() int {
|
||||
ret, _, _ := syscall.Syscall(pcapSnapshotPtr, 1, uintptr(p.cptr), 0, 0)
|
||||
return int(pcapCint(ret))
|
||||
}
|
||||
|
||||
func (t TimestampSource) pcapTstampTypeValToName() string {
|
||||
//libpcap <1.2 doesn't have pcap_*_tstamp_* functions
|
||||
if pcapTstampTypeValToNamePtr == 0 {
|
||||
return "pcap timestamp types not supported"
|
||||
}
|
||||
ret, _, _ := syscall.Syscall(pcapTstampTypeValToNamePtr, 1, uintptr(t), 0, 0)
|
||||
return bytePtrToString(ret)
|
||||
}
|
||||
|
||||
func pcapTstampTypeNameToVal(s string) (TimestampSource, error) {
|
||||
//libpcap <1.2 doesn't have pcap_*_tstamp_* functions
|
||||
if pcapTstampTypeNameToValPtr == 0 {
|
||||
return 0, statusError(pcapCint(pcapError))
|
||||
}
|
||||
cs, err := syscall.BytePtrFromString(s)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
ret, _, _ := syscall.Syscall(pcapTstampTypeNameToValPtr, 1, uintptr(unsafe.Pointer(cs)), 0, 0)
|
||||
t := pcapCint(ret)
|
||||
if t < 0 {
|
||||
return 0, statusError(pcapCint(t))
|
||||
}
|
||||
return TimestampSource(t), nil
|
||||
}
|
||||
|
||||
func (p *InactiveHandle) pcapGeterr() error {
|
||||
ret, _, _ := syscall.Syscall(pcapGeterrPtr, 1, uintptr(p.cptr), 0, 0)
|
||||
return errors.New(bytePtrToString(ret))
|
||||
}
|
||||
|
||||
func (p *InactiveHandle) pcapActivate() (*Handle, activateError) {
|
||||
r, _, _ := syscall.Syscall(pcapActivatePtr, 1, uintptr(p.cptr), 0, 0)
|
||||
ret := activateError(pcapCint(r))
|
||||
if ret != aeNoError {
|
||||
return nil, ret
|
||||
}
|
||||
h := &Handle{
|
||||
cptr: p.cptr,
|
||||
}
|
||||
p.cptr = 0
|
||||
return h, ret
|
||||
}
|
||||
|
||||
func (p *InactiveHandle) pcapClose() {
|
||||
if p.cptr != 0 {
|
||||
_, _, _ = syscall.Syscall(pcapClosePtr, 1, uintptr(p.cptr), 0, 0)
|
||||
}
|
||||
p.cptr = 0
|
||||
}
|
||||
|
||||
func pcapCreate(device string) (*InactiveHandle, error) {
|
||||
buf := make([]byte, errorBufferSize)
|
||||
dev, err := syscall.BytePtrFromString(device)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cptr, _, _ := syscall.Syscall(pcapCreatePtr, 2, uintptr(unsafe.Pointer(dev)), uintptr(unsafe.Pointer(&buf[0])), 0)
|
||||
if cptr == 0 {
|
||||
return nil, errors.New(byteSliceToString(buf))
|
||||
}
|
||||
return &InactiveHandle{cptr: pcapTPtr(cptr)}, nil
|
||||
}
|
||||
|
||||
func (p *InactiveHandle) pcapSetSnaplen(snaplen int) error {
|
||||
status, _, _ := syscall.Syscall(pcapSetSnaplenPtr, 2, uintptr(p.cptr), uintptr(snaplen), 0)
|
||||
if pcapCint(status) < 0 {
|
||||
return statusError(pcapCint(status))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *InactiveHandle) pcapSetPromisc(promisc bool) error {
|
||||
var pro uintptr
|
||||
if promisc {
|
||||
pro = 1
|
||||
}
|
||||
status, _, _ := syscall.Syscall(pcapSetPromiscPtr, 2, uintptr(p.cptr), pro, 0)
|
||||
if pcapCint(status) < 0 {
|
||||
return statusError(pcapCint(status))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *InactiveHandle) pcapSetTimeout(timeout time.Duration) error {
|
||||
status, _, _ := syscall.Syscall(pcapSetTimeoutPtr, 2, uintptr(p.cptr), uintptr(timeoutMillis(timeout)), 0)
|
||||
|
||||
if pcapCint(status) < 0 {
|
||||
return statusError(pcapCint(status))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *InactiveHandle) pcapListTstampTypes() (out []TimestampSource) {
|
||||
//libpcap <1.2 doesn't have pcap_*_tstamp_* functions
|
||||
if pcapListTstampTypesPtr == 0 {
|
||||
return
|
||||
}
|
||||
var types *pcapCint
|
||||
ret, _, _ := syscall.Syscall(pcapListTstampTypesPtr, 2, uintptr(p.cptr), uintptr(unsafe.Pointer(&types)), 0)
|
||||
n := int(pcapCint(ret))
|
||||
if n < 0 {
|
||||
return // public interface doesn't have error :(
|
||||
}
|
||||
defer syscall.Syscall(pcapFreeTstampTypesPtr, 1, uintptr(unsafe.Pointer(types)), 0, 0)
|
||||
typesArray := (*[1 << 28]pcapCint)(unsafe.Pointer(types))
|
||||
for i := 0; i < n; i++ {
|
||||
out = append(out, TimestampSource((*typesArray)[i]))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (p *InactiveHandle) pcapSetTstampType(t TimestampSource) error {
|
||||
//libpcap <1.2 doesn't have pcap_*_tstamp_* functions
|
||||
if pcapSetTstampTypePtr == 0 {
|
||||
return statusError(pcapError)
|
||||
}
|
||||
status, _, _ := syscall.Syscall(pcapSetTstampTypePtr, 2, uintptr(p.cptr), uintptr(t), 0)
|
||||
if pcapCint(status) < 0 {
|
||||
return statusError(pcapCint(status))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *InactiveHandle) pcapSetRfmon(monitor bool) error {
|
||||
//winpcap does not support rfmon
|
||||
if pcapCanSetRfmonPtr == 0 {
|
||||
return CannotSetRFMon
|
||||
}
|
||||
var mon uintptr
|
||||
if monitor {
|
||||
mon = 1
|
||||
}
|
||||
canset, _, _ := syscall.Syscall(pcapCanSetRfmonPtr, 1, uintptr(p.cptr), 0, 0)
|
||||
switch canset {
|
||||
case 0:
|
||||
return CannotSetRFMon
|
||||
case 1:
|
||||
// success
|
||||
default:
|
||||
return statusError(pcapCint(canset))
|
||||
}
|
||||
status, _, _ := syscall.Syscall(pcapSetRfmonPtr, 2, uintptr(p.cptr), mon, 0)
|
||||
if status != 0 {
|
||||
return statusError(pcapCint(status))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *InactiveHandle) pcapSetBufferSize(bufferSize int) error {
|
||||
status, _, _ := syscall.Syscall(pcapSetBufferSizePtr, 2, uintptr(p.cptr), uintptr(bufferSize), 0)
|
||||
if pcapCint(status) < 0 {
|
||||
return statusError(pcapCint(status))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *InactiveHandle) pcapSetImmediateMode(mode bool) error {
|
||||
//libpcap <1.5 does not have pcap_set_immediate_mode
|
||||
if pcapSetImmediateModePtr == 0 {
|
||||
return statusError(pcapError)
|
||||
}
|
||||
var md uintptr
|
||||
if mode {
|
||||
md = 1
|
||||
}
|
||||
status, _, _ := syscall.Syscall(pcapSetImmediateModePtr, 2, uintptr(p.cptr), md, 0)
|
||||
if pcapCint(status) < 0 {
|
||||
return statusError(pcapCint(status))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Handle) setNonBlocking() error {
|
||||
// do nothing
|
||||
return nil
|
||||
@ -32,13 +793,18 @@ func (p *Handle) waitForPacket() {
|
||||
|
||||
// openOfflineFile returns contents of input file as a *Handle.
|
||||
func openOfflineFile(file *os.File) (handle *Handle, err error) {
|
||||
buf := (*C.char)(C.calloc(errorBufferSize, 1))
|
||||
defer C.free(unsafe.Pointer(buf))
|
||||
cf := C.intptr_t(file.Fd())
|
||||
buf := make([]byte, errorBufferSize)
|
||||
cf := file.Fd()
|
||||
|
||||
cptr := C.pcap_hopen_offline(cf, buf)
|
||||
if cptr == nil {
|
||||
return nil, errors.New(C.GoString(buf))
|
||||
var cptr uintptr
|
||||
if pcapOpenOfflineWithTstampPrecisionPtr == 0 {
|
||||
cptr, _, _ = syscall.Syscall(pcapHopenOfflinePtr, 2, cf, uintptr(unsafe.Pointer(&buf[0])), 0)
|
||||
} else {
|
||||
cptr, _, _ = syscall.Syscall(pcapHOpenOfflineWithTstampPrecisionPtr, 3, cf, uintptr(pcapTstampPrecisionNano), uintptr(unsafe.Pointer(&buf[0])))
|
||||
}
|
||||
return &Handle{cptr: cptr}, nil
|
||||
|
||||
if cptr == 0 {
|
||||
return nil, errors.New(byteSliceToString(buf))
|
||||
}
|
||||
return &Handle{cptr: pcapTPtr(cptr)}, nil
|
||||
}
|
||||
|
63
vendor/github.com/google/gopacket/pcapgo/doc.go
generated
vendored
Normal file
63
vendor/github.com/google/gopacket/pcapgo/doc.go
generated
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
// 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 pcapgo provides some native PCAP support, not requiring C libpcap to be installed.
|
||||
|
||||
Overview
|
||||
|
||||
This package contains implementations for native PCAP support. Currently supported are
|
||||
|
||||
* pcap-files read/write: Reader, Writer
|
||||
* pcapng-files read/write: NgReader, NgWriter
|
||||
* raw socket capture (linux only): EthernetHandle
|
||||
|
||||
Basic Usage pcapng
|
||||
|
||||
Pcapng files can be read and written. Reading supports both big and little endian files, packet blocks,
|
||||
simple packet blocks, enhanced packets blocks, interface blocks, and interface statistics blocks. All
|
||||
the options also by Wireshark are supported. The default reader options match libpcap behaviour. Have
|
||||
a look at NgReaderOptions for more advanced usage. Both ReadPacketData and ZeroCopyReadPacketData is
|
||||
supported (which means PacketDataSource and ZeroCopyPacketDataSource is supported).
|
||||
|
||||
f, err := os.Open("somefile.pcapng")
|
||||
if err != nil {
|
||||
...
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
r, err := NewNgReader(f, DefaultNgReaderOptions)
|
||||
if err != nil {
|
||||
...
|
||||
}
|
||||
|
||||
data, ci, err := r.ReadPacketData()
|
||||
...
|
||||
|
||||
Write supports only little endian, enhanced packets blocks, interface blocks, and interface statistics
|
||||
blocks. The same options as with writing are supported. Interface timestamp resolution is fixed to
|
||||
10^-9s to match time.Time. Any other values are ignored. Upon creating a writer, a section, and an
|
||||
interface block is automatically written. Additional interfaces can be added at any time. Since
|
||||
the writer uses a bufio.Writer internally, Flush must be called before closing the file! Have a look
|
||||
at NewNgWriterInterface for more advanced usage.
|
||||
|
||||
f, err := os.Create("somefile.pcapng")
|
||||
if err != nil {
|
||||
...
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
r, err = NewNgWriter(f, layers.LinkTypeEthernet)
|
||||
if err != nil {
|
||||
...
|
||||
}
|
||||
defer r.Flush()
|
||||
|
||||
err = r.WritePacket(ci, data)
|
||||
...
|
||||
|
||||
*/
|
||||
package pcapgo
|
606
vendor/github.com/google/gopacket/pcapgo/ngread.go
generated
vendored
Normal file
606
vendor/github.com/google/gopacket/pcapgo/ngread.go
generated
vendored
Normal file
@ -0,0 +1,606 @@
|
||||
// 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 pcapgo
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/google/gopacket"
|
||||
"github.com/google/gopacket/layers"
|
||||
)
|
||||
|
||||
// NgReaderOptions holds options for reading a pcapng file
|
||||
type NgReaderOptions struct {
|
||||
// WantMixedLinkType enables reading a pcapng file containing multiple interfaces with varying link types. If false all link types must match, which is the libpcap behaviour and LinkType returns the link type of the first interface.
|
||||
// If true the link type of the packet is also exposed via ci.AncillaryData[0].
|
||||
WantMixedLinkType bool
|
||||
// ErrorOnMismatchingLinkType enables returning an error if a packet with a link type not matching the first interface is encountered and WantMixedLinkType == false.
|
||||
// If false packets those packets are just silently ignored, which is the libpcap behaviour.
|
||||
ErrorOnMismatchingLinkType bool
|
||||
// SkipUnknownVersion enables automatically skipping sections with an unknown version, which is recommended by the pcapng standard. Otherwise ErrVersionMismatch is returned.
|
||||
SkipUnknownVersion bool
|
||||
// SectionEndCallback gets called at the end of a section (execept for the last section, which is ends on EOF). The current list of interfaces and additional section information is provided.
|
||||
// This is a good way to read interface statistics.
|
||||
SectionEndCallback func([]NgInterface, NgSectionInfo)
|
||||
// StatisticsCallback is called when a interface statistics block is read. The interface id and the read statistics are provided.
|
||||
StatisticsCallback func(int, NgInterfaceStatistics)
|
||||
}
|
||||
|
||||
// DefaultNgReaderOptions provides sane defaults for a pcapng reader.
|
||||
var DefaultNgReaderOptions = NgReaderOptions{}
|
||||
|
||||
// NgReader wraps an underlying bufio.NgReader to read packet data in pcapng.
|
||||
type NgReader struct {
|
||||
r *bufio.Reader
|
||||
options NgReaderOptions
|
||||
sectionInfo NgSectionInfo
|
||||
linkType layers.LinkType
|
||||
ifaces []NgInterface
|
||||
currentBlock ngBlock
|
||||
currentOption ngOption
|
||||
buf [24]byte
|
||||
packetBuf []byte
|
||||
ci gopacket.CaptureInfo
|
||||
ancil [1]interface{}
|
||||
blen int
|
||||
firstSectionFound bool
|
||||
activeSection bool
|
||||
bigEndian bool
|
||||
}
|
||||
|
||||
// NewNgReader initializes a new writer, reads the first section header, and if necessary according to the options the first interface.
|
||||
func NewNgReader(r io.Reader, options NgReaderOptions) (*NgReader, error) {
|
||||
ret := &NgReader{
|
||||
r: bufio.NewReader(r),
|
||||
currentOption: ngOption{
|
||||
value: make([]byte, 1024),
|
||||
},
|
||||
options: options,
|
||||
}
|
||||
|
||||
//pcapng _must_ start with a section header
|
||||
if err := ret.readBlock(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if ret.currentBlock.typ != ngBlockTypeSectionHeader {
|
||||
return nil, fmt.Errorf("Unknown magic %x", ret.currentBlock.typ)
|
||||
}
|
||||
|
||||
if err := ret.readSectionHeader(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// First a couple of helper functions to speed things up
|
||||
|
||||
// This is way faster than calling io.ReadFull since io.ReadFull needs an itab lookup, does an additional function call into ReadAtLeast, and ReadAtLeast does additional stuff we don't need
|
||||
// Additionally this removes the bounds check compared to io.ReadFull due to the use of uint
|
||||
func (r *NgReader) readBytes(buffer []byte) error {
|
||||
n := uint(0)
|
||||
for n < uint(len(buffer)) {
|
||||
nn, err := r.r.Read(buffer[n:])
|
||||
n += uint(nn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// The following functions make the binary.* functions inlineable (except for getUint64, which is too big, but not in any hot path anyway)
|
||||
// Compared to storing binary.*Endian in a binary.ByteOrder this shaves off about 20% for (ZeroCopy)ReadPacketData, which is caused by the needed itab lookup + indirect go call
|
||||
func (r *NgReader) getUint16(buffer []byte) uint16 {
|
||||
if r.bigEndian {
|
||||
return binary.BigEndian.Uint16(buffer)
|
||||
}
|
||||
return binary.LittleEndian.Uint16(buffer)
|
||||
}
|
||||
|
||||
func (r *NgReader) getUint32(buffer []byte) uint32 {
|
||||
if r.bigEndian {
|
||||
return binary.BigEndian.Uint32(buffer)
|
||||
}
|
||||
return binary.LittleEndian.Uint32(buffer)
|
||||
}
|
||||
|
||||
func (r *NgReader) getUint64(buffer []byte) uint64 {
|
||||
if r.bigEndian {
|
||||
return binary.BigEndian.Uint64(buffer)
|
||||
}
|
||||
return binary.LittleEndian.Uint64(buffer)
|
||||
}
|
||||
|
||||
// Now the pcapng implementation
|
||||
|
||||
// readBlock reads a the blocktype and length from the file. If the type is a section header, endianess is also read.
|
||||
func (r *NgReader) readBlock() error {
|
||||
if err := r.readBytes(r.buf[0:8]); err != nil {
|
||||
return err
|
||||
}
|
||||
r.currentBlock.typ = ngBlockType(r.getUint32(r.buf[0:4]))
|
||||
// The next part is a bit fucked up since a section header could change the endianess...
|
||||
// So first read then length just into a buffer, check if its a section header and then do the endianess part...
|
||||
if r.currentBlock.typ == ngBlockTypeSectionHeader {
|
||||
if err := r.readBytes(r.buf[8:12]); err != nil {
|
||||
return err
|
||||
}
|
||||
if binary.BigEndian.Uint32(r.buf[8:12]) == ngByteOrderMagic {
|
||||
r.bigEndian = true
|
||||
} else if binary.LittleEndian.Uint32(r.buf[8:12]) == ngByteOrderMagic {
|
||||
r.bigEndian = false
|
||||
} else {
|
||||
return errors.New("Wrong byte order value in Section Header")
|
||||
}
|
||||
// Set length to remaining length (length - (type + lengthfield = 8) - 4 for byteOrderMagic)
|
||||
r.currentBlock.length = r.getUint32(r.buf[4:8]) - 8 - 4
|
||||
return nil
|
||||
}
|
||||
// Set length to remaining length (length - (type + lengthfield = 8)
|
||||
r.currentBlock.length = r.getUint32(r.buf[4:8]) - 8
|
||||
return nil
|
||||
}
|
||||
|
||||
// readOption reads a single arbitrary option (type and value). If there is no space left for options and end of options is missing, it is faked.
|
||||
func (r *NgReader) readOption() error {
|
||||
if r.currentBlock.length == 4 {
|
||||
// no more options
|
||||
r.currentOption.code = ngOptionCodeEndOfOptions
|
||||
return nil
|
||||
}
|
||||
if err := r.readBytes(r.buf[:4]); err != nil {
|
||||
return err
|
||||
}
|
||||
r.currentBlock.length -= 4
|
||||
r.currentOption.code = ngOptionCode(r.getUint16(r.buf[:2]))
|
||||
length := r.getUint16(r.buf[2:4])
|
||||
if r.currentOption.code == ngOptionCodeEndOfOptions {
|
||||
if length != 0 {
|
||||
return errors.New("End of Options must be zero length")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if length != 0 {
|
||||
if length < uint16(cap(r.currentOption.value)) {
|
||||
r.currentOption.value = r.currentOption.value[:length]
|
||||
} else {
|
||||
r.currentOption.value = make([]byte, length)
|
||||
}
|
||||
if err := r.readBytes(r.currentOption.value); err != nil {
|
||||
return err
|
||||
}
|
||||
//consume padding
|
||||
padding := length % 4
|
||||
if padding > 0 {
|
||||
padding = 4 - padding
|
||||
if _, err := r.r.Discard(int(padding)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
r.currentBlock.length -= uint32(length + padding)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// readSectionHeader parses the full section header and implements section skipping in case of version mismatch
|
||||
// if needed, the first interface is read
|
||||
func (r *NgReader) readSectionHeader() error {
|
||||
if r.options.SectionEndCallback != nil && r.activeSection {
|
||||
interfaces := make([]NgInterface, len(r.ifaces))
|
||||
for i := range r.ifaces {
|
||||
interfaces[i] = r.ifaces[i]
|
||||
}
|
||||
r.options.SectionEndCallback(interfaces, r.sectionInfo)
|
||||
}
|
||||
// clear the interfaces
|
||||
r.ifaces = r.ifaces[:0]
|
||||
r.activeSection = false
|
||||
|
||||
RESTART:
|
||||
// read major, minor, section length
|
||||
if err := r.readBytes(r.buf[:12]); err != nil {
|
||||
return err
|
||||
}
|
||||
r.currentBlock.length -= 12
|
||||
|
||||
vMajor := r.getUint16(r.buf[0:2])
|
||||
vMinor := r.getUint16(r.buf[2:4])
|
||||
if vMajor != ngVersionMajor || vMinor != ngVersionMinor {
|
||||
if !r.options.SkipUnknownVersion {
|
||||
// Well the standard actually says to skip unknown version section headers,
|
||||
// but this would mean user would be kept in the dark about whats going on...
|
||||
return ErrNgVersionMismatch
|
||||
}
|
||||
if _, err := r.r.Discard(int(r.currentBlock.length)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := r.skipSection(); err != nil {
|
||||
return err
|
||||
}
|
||||
goto RESTART
|
||||
}
|
||||
|
||||
var section NgSectionInfo
|
||||
|
||||
OPTIONS:
|
||||
for {
|
||||
if err := r.readOption(); err != nil {
|
||||
return err
|
||||
}
|
||||
switch r.currentOption.code {
|
||||
case ngOptionCodeEndOfOptions:
|
||||
break OPTIONS
|
||||
case ngOptionCodeComment:
|
||||
section.Comment = string(r.currentOption.value)
|
||||
case ngOptionCodeHardware:
|
||||
section.Hardware = string(r.currentOption.value)
|
||||
case ngOptionCodeOS:
|
||||
section.OS = string(r.currentOption.value)
|
||||
case ngOptionCodeUserApplication:
|
||||
section.Application = string(r.currentOption.value)
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := r.r.Discard(int(r.currentBlock.length)); err != nil {
|
||||
return err
|
||||
}
|
||||
r.activeSection = true
|
||||
r.sectionInfo = section
|
||||
|
||||
if !r.options.WantMixedLinkType {
|
||||
// If we don't want mixed link type, we need the first interface to fill Reader.LinkType()
|
||||
// This handles most of the pcapngs out there, since they start with an IDB
|
||||
if err := r.firstInterface(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// skipSection skips blocks until the next section
|
||||
func (r *NgReader) skipSection() error {
|
||||
for {
|
||||
if err := r.readBlock(); err != nil {
|
||||
return err
|
||||
}
|
||||
if r.currentBlock.typ == ngBlockTypeSectionHeader {
|
||||
return nil
|
||||
}
|
||||
if _, err := r.r.Discard(int(r.currentBlock.length)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SkipSection skips the contents of the rest of the current section and reads the next section header.
|
||||
func (r *NgReader) SkipSection() error {
|
||||
if err := r.skipSection(); err != nil {
|
||||
return err
|
||||
}
|
||||
return r.readSectionHeader()
|
||||
}
|
||||
|
||||
// firstInterface reads the first interface from the section and panics if a packet is encountered.
|
||||
func (r *NgReader) firstInterface() error {
|
||||
for {
|
||||
if err := r.readBlock(); err != nil {
|
||||
return err
|
||||
}
|
||||
switch r.currentBlock.typ {
|
||||
case ngBlockTypeInterfaceDescriptor:
|
||||
if err := r.readInterfaceDescriptor(); err != nil {
|
||||
return err
|
||||
}
|
||||
if !r.firstSectionFound {
|
||||
r.linkType = r.ifaces[0].LinkType
|
||||
r.firstSectionFound = true
|
||||
} else if r.linkType != r.ifaces[0].LinkType {
|
||||
if r.options.ErrorOnMismatchingLinkType {
|
||||
return ErrNgLinkTypeMismatch
|
||||
}
|
||||
continue
|
||||
}
|
||||
return nil
|
||||
case ngBlockTypePacket, ngBlockTypeEnhancedPacket, ngBlockTypeSimplePacket, ngBlockTypeInterfaceStatistics:
|
||||
return errors.New("A section must have an interface before a packet block")
|
||||
}
|
||||
if _, err := r.r.Discard(int(r.currentBlock.length)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// readInterfaceDescriptor parses an interface descriptor, prepares timing calculation, and adds the interface details to the current list
|
||||
func (r *NgReader) readInterfaceDescriptor() error {
|
||||
if err := r.readBytes(r.buf[:8]); err != nil {
|
||||
return err
|
||||
}
|
||||
r.currentBlock.length -= 8
|
||||
var intf NgInterface
|
||||
intf.LinkType = layers.LinkType(r.getUint16(r.buf[:2]))
|
||||
intf.SnapLength = r.getUint32(r.buf[4:8])
|
||||
|
||||
OPTIONS:
|
||||
for {
|
||||
if err := r.readOption(); err != nil {
|
||||
return err
|
||||
}
|
||||
switch r.currentOption.code {
|
||||
case ngOptionCodeEndOfOptions:
|
||||
break OPTIONS
|
||||
case ngOptionCodeInterfaceName:
|
||||
intf.Name = string(r.currentOption.value)
|
||||
case ngOptionCodeComment:
|
||||
intf.Comment = string(r.currentOption.value)
|
||||
case ngOptionCodeInterfaceDescription:
|
||||
intf.Description = string(r.currentOption.value)
|
||||
case ngOptionCodeInterfaceFilter:
|
||||
// ignore filter type (first byte) since it is not specified
|
||||
intf.Filter = string(r.currentOption.value[1:])
|
||||
case ngOptionCodeInterfaceOS:
|
||||
intf.OS = string(r.currentOption.value)
|
||||
case ngOptionCodeInterfaceTimestampOffset:
|
||||
intf.TimestampOffset = r.getUint64(r.currentOption.value[:8])
|
||||
case ngOptionCodeInterfaceTimestampResolution:
|
||||
intf.TimestampResolution = NgResolution(r.currentOption.value[0])
|
||||
}
|
||||
}
|
||||
if _, err := r.r.Discard(int(r.currentBlock.length)); err != nil {
|
||||
return err
|
||||
}
|
||||
if intf.TimestampResolution == 0 {
|
||||
intf.TimestampResolution = 6
|
||||
}
|
||||
|
||||
//parse options
|
||||
if intf.TimestampResolution.Binary() {
|
||||
//negative power of 2
|
||||
intf.secondMask = 1 << intf.TimestampResolution.Exponent()
|
||||
} else {
|
||||
//negative power of 10
|
||||
intf.secondMask = 1
|
||||
for j := uint8(0); j < intf.TimestampResolution.Exponent(); j++ {
|
||||
intf.secondMask *= 10
|
||||
}
|
||||
}
|
||||
intf.scaleDown = 1
|
||||
intf.scaleUp = 1
|
||||
if intf.secondMask < 1e9 {
|
||||
intf.scaleUp = 1e9 / intf.secondMask
|
||||
} else {
|
||||
intf.scaleDown = intf.secondMask / 1e9
|
||||
}
|
||||
r.ifaces = append(r.ifaces, intf)
|
||||
return nil
|
||||
}
|
||||
|
||||
// convertTime adds offset + shifts the given time value according to the given interface
|
||||
func (r *NgReader) convertTime(ifaceID int, ts uint64) (int64, int64) {
|
||||
iface := r.ifaces[ifaceID]
|
||||
return int64(ts/iface.secondMask + iface.TimestampOffset), int64(ts % iface.secondMask * iface.scaleUp / iface.scaleDown)
|
||||
}
|
||||
|
||||
// readInterfaceStatistics updates the statistics of the given interface
|
||||
func (r *NgReader) readInterfaceStatistics() error {
|
||||
if err := r.readBytes(r.buf[:12]); err != nil {
|
||||
return err
|
||||
}
|
||||
r.currentBlock.length -= 12
|
||||
ifaceID := int(r.getUint32(r.buf[:4]))
|
||||
ts := uint64(r.getUint32(r.buf[4:8]))<<32 | uint64(r.getUint32(r.buf[8:12]))
|
||||
if int(ifaceID) >= len(r.ifaces) {
|
||||
return fmt.Errorf("Interface id %d not present in section (have only %d interfaces)", ifaceID, len(r.ifaces))
|
||||
}
|
||||
stats := &r.ifaces[ifaceID].Statistics
|
||||
*stats = ngEmptyStatistics
|
||||
stats.LastUpdate = time.Unix(r.convertTime(ifaceID, ts)).UTC()
|
||||
|
||||
OPTIONS:
|
||||
for {
|
||||
if err := r.readOption(); err != nil {
|
||||
return err
|
||||
}
|
||||
switch r.currentOption.code {
|
||||
case ngOptionCodeEndOfOptions:
|
||||
break OPTIONS
|
||||
case ngOptionCodeComment:
|
||||
stats.Comment = string(r.currentOption.value)
|
||||
case ngOptionCodeInterfaceStatisticsStartTime:
|
||||
ts = uint64(r.getUint32(r.currentOption.value[:4]))<<32 | uint64(r.getUint32(r.currentOption.value[4:8]))
|
||||
stats.StartTime = time.Unix(r.convertTime(ifaceID, ts)).UTC()
|
||||
case ngOptionCodeInterfaceStatisticsEndTime:
|
||||
ts = uint64(r.getUint32(r.currentOption.value[:4]))<<32 | uint64(r.getUint32(r.currentOption.value[4:8]))
|
||||
stats.EndTime = time.Unix(r.convertTime(ifaceID, ts)).UTC()
|
||||
case ngOptionCodeInterfaceStatisticsInterfaceReceived:
|
||||
stats.PacketsReceived = r.getUint64(r.currentOption.value[:8])
|
||||
case ngOptionCodeInterfaceStatisticsInterfaceDropped:
|
||||
stats.PacketsDropped = r.getUint64(r.currentOption.value[:8])
|
||||
}
|
||||
}
|
||||
if _, err := r.r.Discard(int(r.currentBlock.length)); err != nil {
|
||||
return err
|
||||
}
|
||||
if r.options.StatisticsCallback != nil {
|
||||
r.options.StatisticsCallback(ifaceID, *stats)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// readPacketHeader looks for a packet (enhanced, simple, or packet) and parses the header.
|
||||
// If an interface descriptor, an interface statistics block, or a section header is encountered, those are handled accordingly.
|
||||
// All other block types are skipped. New block types must be added here.
|
||||
func (r *NgReader) readPacketHeader() error {
|
||||
RESTART:
|
||||
FIND_PACKET:
|
||||
for {
|
||||
if err := r.readBlock(); err != nil {
|
||||
return err
|
||||
}
|
||||
switch r.currentBlock.typ {
|
||||
case ngBlockTypeEnhancedPacket:
|
||||
if err := r.readBytes(r.buf[:20]); err != nil {
|
||||
return err
|
||||
}
|
||||
r.currentBlock.length -= 20
|
||||
r.ci.InterfaceIndex = int(r.getUint32(r.buf[:4]))
|
||||
if r.ci.InterfaceIndex >= len(r.ifaces) {
|
||||
return fmt.Errorf("Interface id %d not present in section (have only %d interfaces)", r.ci.InterfaceIndex, len(r.ifaces))
|
||||
}
|
||||
r.ci.Timestamp = time.Unix(r.convertTime(r.ci.InterfaceIndex, uint64(r.getUint32(r.buf[4:8]))<<32|uint64(r.getUint32(r.buf[8:12])))).UTC()
|
||||
r.ci.CaptureLength = int(r.getUint32(r.buf[12:16]))
|
||||
r.ci.Length = int(r.getUint32(r.buf[16:20]))
|
||||
break FIND_PACKET
|
||||
case ngBlockTypeSimplePacket:
|
||||
if err := r.readBytes(r.buf[:4]); err != nil {
|
||||
return err
|
||||
}
|
||||
r.currentBlock.length -= 4
|
||||
r.ci.Timestamp = time.Time{}
|
||||
r.ci.InterfaceIndex = 0
|
||||
r.ci.Length = int(r.getUint32(r.buf[:4]))
|
||||
r.ci.CaptureLength = r.ci.Length
|
||||
if len(r.ifaces) == 0 {
|
||||
return errors.New("At least one Interface is needed for a packet")
|
||||
}
|
||||
if r.ifaces[0].SnapLength != 0 && uint32(r.ci.CaptureLength) > r.ifaces[0].SnapLength {
|
||||
r.ci.CaptureLength = int(r.ifaces[0].SnapLength)
|
||||
}
|
||||
break FIND_PACKET
|
||||
case ngBlockTypeInterfaceDescriptor:
|
||||
if err := r.readInterfaceDescriptor(); err != nil {
|
||||
return err
|
||||
}
|
||||
case ngBlockTypeInterfaceStatistics:
|
||||
if err := r.readInterfaceStatistics(); err != nil {
|
||||
return err
|
||||
}
|
||||
case ngBlockTypeSectionHeader:
|
||||
if err := r.readSectionHeader(); err != nil {
|
||||
return err
|
||||
}
|
||||
case ngBlockTypePacket:
|
||||
if err := r.readBytes(r.buf[:20]); err != nil {
|
||||
return err
|
||||
}
|
||||
r.currentBlock.length -= 20
|
||||
r.ci.InterfaceIndex = int(r.getUint16(r.buf[0:2]))
|
||||
if r.ci.InterfaceIndex >= len(r.ifaces) {
|
||||
return fmt.Errorf("Interface id %d not present in section (have only %d interfaces)", r.ci.InterfaceIndex, len(r.ifaces))
|
||||
}
|
||||
r.ci.Timestamp = time.Unix(r.convertTime(r.ci.InterfaceIndex, uint64(r.getUint32(r.buf[4:8]))<<32|uint64(r.getUint32(r.buf[8:12])))).UTC()
|
||||
r.ci.CaptureLength = int(r.getUint32(r.buf[12:16]))
|
||||
r.ci.Length = int(r.getUint32(r.buf[16:20]))
|
||||
break FIND_PACKET
|
||||
default:
|
||||
if _, err := r.r.Discard(int(r.currentBlock.length)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
if !r.options.WantMixedLinkType {
|
||||
if r.ifaces[r.ci.InterfaceIndex].LinkType != r.linkType {
|
||||
if _, err := r.r.Discard(int(r.currentBlock.length)); err != nil {
|
||||
return err
|
||||
}
|
||||
if r.options.ErrorOnMismatchingLinkType {
|
||||
return ErrNgLinkTypeMismatch
|
||||
}
|
||||
goto RESTART
|
||||
}
|
||||
return nil
|
||||
}
|
||||
r.ancil[0] = r.ifaces[r.ci.InterfaceIndex].LinkType
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReadPacketData returns the next packet available from this data source.
|
||||
// If WantMixedLinkType is true, ci.AncillaryData[0] contains the link type.
|
||||
func (r *NgReader) ReadPacketData() (data []byte, ci gopacket.CaptureInfo, err error) {
|
||||
if err = r.readPacketHeader(); err != nil {
|
||||
return
|
||||
}
|
||||
ci = r.ci
|
||||
if r.options.WantMixedLinkType {
|
||||
ci.AncillaryData = make([]interface{}, 1)
|
||||
ci.AncillaryData[0] = r.ancil[0]
|
||||
}
|
||||
data = make([]byte, r.ci.CaptureLength)
|
||||
if err = r.readBytes(data); err != nil {
|
||||
return
|
||||
}
|
||||
// handle options somehow - this would be expensive
|
||||
_, err = r.r.Discard(int(r.currentBlock.length) - r.ci.CaptureLength)
|
||||
return
|
||||
}
|
||||
|
||||
// ZeroCopyReadPacketData returns the next packet available from this data source.
|
||||
// If WantMixedLinkType is true, ci.AncillaryData[0] contains the link type.
|
||||
// Warning: Like data, ci.AncillaryData is also reused and overwritten on the next call to ZeroCopyReadPacketData.
|
||||
//
|
||||
// It is not true zero copy, as data is still copied from the underlying reader. However,
|
||||
// this method avoids allocating heap memory for every packet.
|
||||
func (r *NgReader) ZeroCopyReadPacketData() (data []byte, ci gopacket.CaptureInfo, err error) {
|
||||
if err = r.readPacketHeader(); err != nil {
|
||||
return
|
||||
}
|
||||
ci = r.ci
|
||||
if r.options.WantMixedLinkType {
|
||||
ci.AncillaryData = r.ancil[:]
|
||||
}
|
||||
if cap(r.packetBuf) < ci.CaptureLength {
|
||||
snaplen := int(r.ifaces[ci.InterfaceIndex].SnapLength)
|
||||
if snaplen < ci.CaptureLength {
|
||||
snaplen = ci.CaptureLength
|
||||
}
|
||||
r.packetBuf = make([]byte, snaplen)
|
||||
}
|
||||
data = r.packetBuf[:ci.CaptureLength]
|
||||
if err = r.readBytes(data); err != nil {
|
||||
return
|
||||
}
|
||||
// handle options somehow - this would be expensive
|
||||
_, err = r.r.Discard(int(r.currentBlock.length) - ci.CaptureLength)
|
||||
return
|
||||
}
|
||||
|
||||
// LinkType returns the link type of the first interface, as a layers.LinkType. This is only valid, if WantMixedLinkType is false.
|
||||
func (r *NgReader) LinkType() layers.LinkType {
|
||||
return r.linkType
|
||||
}
|
||||
|
||||
// SectionInfo returns information about the current section.
|
||||
func (r *NgReader) SectionInfo() NgSectionInfo {
|
||||
return r.sectionInfo
|
||||
}
|
||||
|
||||
// Interface returns interface information and statistics of interface with the given id.
|
||||
func (r *NgReader) Interface(i int) (NgInterface, error) {
|
||||
if i >= len(r.ifaces) || i < 0 {
|
||||
return NgInterface{}, fmt.Errorf("Interface %d invalid. There are only %d interfaces", i, len(r.ifaces))
|
||||
}
|
||||
return r.ifaces[i], nil
|
||||
}
|
||||
|
||||
// NInterfaces returns the current number of interfaces.
|
||||
func (r *NgReader) NInterfaces() int {
|
||||
return len(r.ifaces)
|
||||
}
|
||||
|
||||
// Resolution returns the timestamp resolution of acquired timestamps before scaling to NanosecondTimestampResolution.
|
||||
func (r *NgReader) Resolution() gopacket.TimestampResolution {
|
||||
if r.options.WantMixedLinkType {
|
||||
return gopacket.TimestampResolution{}
|
||||
}
|
||||
return r.ifaces[0].Resolution()
|
||||
}
|
397
vendor/github.com/google/gopacket/pcapgo/ngwrite.go
generated
vendored
Normal file
397
vendor/github.com/google/gopacket/pcapgo/ngwrite.go
generated
vendored
Normal file
@ -0,0 +1,397 @@
|
||||
// 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 pcapgo
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/google/gopacket"
|
||||
"github.com/google/gopacket/layers"
|
||||
)
|
||||
|
||||
// NgWriterOptions holds options for creating a pcapng file
|
||||
type NgWriterOptions struct {
|
||||
// SectionInfo will be written to the section header
|
||||
SectionInfo NgSectionInfo
|
||||
}
|
||||
|
||||
// DefaultNgWriterOptions contain defaults for a pcapng writer used by NewWriter
|
||||
var DefaultNgWriterOptions = NgWriterOptions{
|
||||
SectionInfo: NgSectionInfo{
|
||||
Hardware: runtime.GOARCH,
|
||||
OS: runtime.GOOS,
|
||||
Application: "gopacket", //spread the word
|
||||
},
|
||||
}
|
||||
|
||||
// DefaultNgInterface contains default interface options used by NewWriter
|
||||
var DefaultNgInterface = NgInterface{
|
||||
Name: "intf0",
|
||||
OS: runtime.GOOS,
|
||||
SnapLength: 0, //unlimited
|
||||
TimestampResolution: 9,
|
||||
}
|
||||
|
||||
// NgWriter holds the internal state of a pcapng file writer. Internally a bufio.NgWriter is used, therefore Flush must be called before closing the underlying file.
|
||||
type NgWriter struct {
|
||||
w *bufio.Writer
|
||||
options NgWriterOptions
|
||||
intf uint32
|
||||
buf [28]byte
|
||||
}
|
||||
|
||||
// NewNgWriter initializes and returns a new writer. Additionally, one section and one interface (without statistics) is written to the file. Interface and section options are used from DefaultNgInterface and DefaultNgWriterOptions.
|
||||
// Flush must be called before the file is closed, or if eventual unwritten information should be written out to the storage device.
|
||||
//
|
||||
// Written files are in little endian format. Interface timestamp resolution is fixed to 9 (to match time.Time).
|
||||
func NewNgWriter(w io.Writer, linkType layers.LinkType) (*NgWriter, error) {
|
||||
intf := DefaultNgInterface
|
||||
intf.LinkType = linkType
|
||||
return NewNgWriterInterface(w, intf, DefaultNgWriterOptions)
|
||||
}
|
||||
|
||||
// NewNgWriterInterface initializes and returns a new writer. Additionally, one section and one interface (without statistics) is written to the file.
|
||||
// Flush must be called before the file is closed, or if eventual unwritten information should be written out to the storage device.
|
||||
//
|
||||
// Written files are in little endian format. Interface timestamp resolution is fixed to 9 (to match time.Time).
|
||||
func NewNgWriterInterface(w io.Writer, intf NgInterface, options NgWriterOptions) (*NgWriter, error) {
|
||||
ret := &NgWriter{
|
||||
w: bufio.NewWriter(w),
|
||||
options: options,
|
||||
}
|
||||
if err := ret.writeSectionHeader(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if _, err := ret.AddInterface(intf); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// ngOptionLength returns the needed length for one option value (without padding)
|
||||
func ngOptionLength(option ngOption) int {
|
||||
switch val := option.raw.(type) {
|
||||
case []byte:
|
||||
return len(val)
|
||||
case string:
|
||||
return len(val)
|
||||
case time.Time:
|
||||
return 8
|
||||
case uint64:
|
||||
return 8
|
||||
case uint32:
|
||||
return 4
|
||||
case uint8:
|
||||
return 1
|
||||
default:
|
||||
panic("This should never happen")
|
||||
}
|
||||
}
|
||||
|
||||
// prepareNgOptions fills out the length value of the given options and returns the number of octets needed for all the given options including padding.
|
||||
func prepareNgOptions(options []ngOption) uint32 {
|
||||
var ret uint32
|
||||
for i, option := range options {
|
||||
length := ngOptionLength(option)
|
||||
options[i].length = uint16(length)
|
||||
length += (4-length&3)&3 + // padding
|
||||
4 //header
|
||||
ret += uint32(length)
|
||||
}
|
||||
if ret > 0 {
|
||||
ret += 4 // end of options
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// writeOptions writes the given options to the file. prepareOptions must be called beforehand.
|
||||
func (w *NgWriter) writeOptions(options []ngOption) error {
|
||||
if len(options) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var zero [4]byte
|
||||
for _, option := range options {
|
||||
binary.LittleEndian.PutUint16(w.buf[0:2], uint16(option.code))
|
||||
binary.LittleEndian.PutUint16(w.buf[2:4], option.length)
|
||||
if _, err := w.w.Write(w.buf[:4]); err != nil {
|
||||
return err
|
||||
}
|
||||
switch val := option.raw.(type) {
|
||||
case []byte:
|
||||
if _, err := w.w.Write(val); err != nil {
|
||||
return err
|
||||
}
|
||||
padding := uint8((4 - option.length&3) & 3)
|
||||
if padding < 4 {
|
||||
if _, err := w.w.Write(zero[:padding]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
case string:
|
||||
if _, err := w.w.Write([]byte(val)); err != nil {
|
||||
return err
|
||||
}
|
||||
padding := uint8((4 - option.length&3) & 3)
|
||||
if padding < 4 {
|
||||
if _, err := w.w.Write(zero[:padding]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
case time.Time:
|
||||
ts := val.UnixNano()
|
||||
binary.LittleEndian.PutUint32(w.buf[:4], uint32(ts>>32))
|
||||
binary.LittleEndian.PutUint32(w.buf[4:8], uint32(ts))
|
||||
if _, err := w.w.Write(w.buf[:8]); err != nil {
|
||||
return err
|
||||
}
|
||||
case uint64:
|
||||
binary.LittleEndian.PutUint64(w.buf[:8], val)
|
||||
if _, err := w.w.Write(w.buf[:8]); err != nil {
|
||||
return err
|
||||
}
|
||||
case uint32:
|
||||
binary.LittleEndian.PutUint32(w.buf[:4], val)
|
||||
if _, err := w.w.Write(w.buf[:4]); err != nil {
|
||||
return err
|
||||
}
|
||||
case uint8:
|
||||
binary.LittleEndian.PutUint32(w.buf[:4], 0) // padding
|
||||
w.buf[0] = val
|
||||
if _, err := w.w.Write(w.buf[:4]); err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
panic("This should never happen")
|
||||
}
|
||||
}
|
||||
|
||||
// options must be folled by an end of options option
|
||||
binary.LittleEndian.PutUint16(w.buf[0:2], uint16(ngOptionCodeEndOfOptions))
|
||||
binary.LittleEndian.PutUint16(w.buf[2:4], 0)
|
||||
_, err := w.w.Write(w.buf[:4])
|
||||
return err
|
||||
}
|
||||
|
||||
// writeSectionHeader writes a section header to the file
|
||||
func (w *NgWriter) writeSectionHeader() error {
|
||||
var scratch [4]ngOption
|
||||
i := 0
|
||||
info := w.options.SectionInfo
|
||||
if info.Application != "" {
|
||||
scratch[i].code = ngOptionCodeUserApplication
|
||||
scratch[i].raw = info.Application
|
||||
i++
|
||||
}
|
||||
if info.Comment != "" {
|
||||
scratch[i].code = ngOptionCodeComment
|
||||
scratch[i].raw = info.Comment
|
||||
i++
|
||||
}
|
||||
if info.Hardware != "" {
|
||||
scratch[i].code = ngOptionCodeHardware
|
||||
scratch[i].raw = info.Hardware
|
||||
i++
|
||||
}
|
||||
if info.OS != "" {
|
||||
scratch[i].code = ngOptionCodeOS
|
||||
scratch[i].raw = info.OS
|
||||
i++
|
||||
}
|
||||
options := scratch[:i]
|
||||
|
||||
length := prepareNgOptions(options) +
|
||||
24 + // header
|
||||
4 // trailer
|
||||
|
||||
binary.LittleEndian.PutUint32(w.buf[:4], uint32(ngBlockTypeSectionHeader))
|
||||
binary.LittleEndian.PutUint32(w.buf[4:8], length)
|
||||
binary.LittleEndian.PutUint32(w.buf[8:12], ngByteOrderMagic)
|
||||
binary.LittleEndian.PutUint16(w.buf[12:14], ngVersionMajor)
|
||||
binary.LittleEndian.PutUint16(w.buf[14:16], ngVersionMinor)
|
||||
binary.LittleEndian.PutUint64(w.buf[16:24], 0xFFFFFFFFFFFFFFFF) // unspecified
|
||||
if _, err := w.w.Write(w.buf[:24]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := w.writeOptions(options); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
binary.LittleEndian.PutUint32(w.buf[0:4], length)
|
||||
_, err := w.w.Write(w.buf[:4])
|
||||
return err
|
||||
}
|
||||
|
||||
// AddInterface adds the specified interface to the file, excluding statistics. Interface timestamp resolution is fixed to 9 (to match time.Time). Empty values are not written.
|
||||
func (w *NgWriter) AddInterface(intf NgInterface) (id int, err error) {
|
||||
id = int(w.intf)
|
||||
w.intf++
|
||||
|
||||
var scratch [7]ngOption
|
||||
i := 0
|
||||
if intf.Name != "" {
|
||||
scratch[i].code = ngOptionCodeInterfaceName
|
||||
scratch[i].raw = intf.Name
|
||||
i++
|
||||
}
|
||||
if intf.Comment != "" {
|
||||
scratch[i].code = ngOptionCodeComment
|
||||
scratch[i].raw = intf.Comment
|
||||
i++
|
||||
}
|
||||
if intf.Description != "" {
|
||||
scratch[i].code = ngOptionCodeInterfaceDescription
|
||||
scratch[i].raw = intf.Description
|
||||
i++
|
||||
}
|
||||
if intf.Filter != "" {
|
||||
scratch[i].code = ngOptionCodeInterfaceFilter
|
||||
scratch[i].raw = append([]byte{0}, []byte(intf.Filter)...)
|
||||
i++
|
||||
}
|
||||
if intf.OS != "" {
|
||||
scratch[i].code = ngOptionCodeInterfaceOS
|
||||
scratch[i].raw = intf.OS
|
||||
i++
|
||||
}
|
||||
if intf.TimestampOffset != 0 {
|
||||
scratch[i].code = ngOptionCodeInterfaceTimestampOffset
|
||||
scratch[i].raw = intf.TimestampOffset
|
||||
i++
|
||||
}
|
||||
scratch[i].code = ngOptionCodeInterfaceTimestampResolution
|
||||
scratch[i].raw = uint8(9) // fix resolution to nanoseconds (time.Time) in decimal
|
||||
i++
|
||||
options := scratch[:i]
|
||||
|
||||
length := prepareNgOptions(options) +
|
||||
16 + // header
|
||||
4 // trailer
|
||||
|
||||
binary.LittleEndian.PutUint32(w.buf[:4], uint32(ngBlockTypeInterfaceDescriptor))
|
||||
binary.LittleEndian.PutUint32(w.buf[4:8], length)
|
||||
binary.LittleEndian.PutUint16(w.buf[8:10], uint16(intf.LinkType))
|
||||
binary.LittleEndian.PutUint16(w.buf[10:12], 0) // reserved value
|
||||
binary.LittleEndian.PutUint32(w.buf[12:16], intf.SnapLength)
|
||||
if _, err := w.w.Write(w.buf[:16]); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if err := w.writeOptions(options); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
binary.LittleEndian.PutUint32(w.buf[0:4], length)
|
||||
_, err = w.w.Write(w.buf[:4])
|
||||
return id, err
|
||||
}
|
||||
|
||||
// WriteInterfaceStats writes the given interface statistics for the given interface id to the file. Empty values are not written.
|
||||
func (w *NgWriter) WriteInterfaceStats(intf int, stats NgInterfaceStatistics) error {
|
||||
if intf >= int(w.intf) || intf < 0 {
|
||||
return fmt.Errorf("Can't send statistics for non existent interface %d; have only %d interfaces", intf, w.intf)
|
||||
}
|
||||
|
||||
var scratch [4]ngOption
|
||||
i := 0
|
||||
if !stats.StartTime.IsZero() {
|
||||
scratch[i].code = ngOptionCodeInterfaceStatisticsStartTime
|
||||
scratch[i].raw = stats.StartTime
|
||||
i++
|
||||
}
|
||||
if !stats.EndTime.IsZero() {
|
||||
scratch[i].code = ngOptionCodeInterfaceStatisticsEndTime
|
||||
scratch[i].raw = stats.EndTime
|
||||
i++
|
||||
}
|
||||
if stats.PacketsDropped != NgNoValue64 {
|
||||
scratch[i].code = ngOptionCodeInterfaceStatisticsInterfaceDropped
|
||||
scratch[i].raw = stats.PacketsDropped
|
||||
i++
|
||||
}
|
||||
if stats.PacketsReceived != NgNoValue64 {
|
||||
scratch[i].code = ngOptionCodeInterfaceStatisticsInterfaceReceived
|
||||
scratch[i].raw = stats.PacketsReceived
|
||||
i++
|
||||
}
|
||||
options := scratch[:i]
|
||||
|
||||
length := prepareNgOptions(options) + 24
|
||||
|
||||
ts := stats.LastUpdate.UnixNano()
|
||||
if stats.LastUpdate.IsZero() {
|
||||
ts = 0
|
||||
}
|
||||
|
||||
binary.LittleEndian.PutUint32(w.buf[:4], uint32(ngBlockTypeInterfaceStatistics))
|
||||
binary.LittleEndian.PutUint32(w.buf[4:8], length)
|
||||
binary.LittleEndian.PutUint32(w.buf[8:12], uint32(intf))
|
||||
binary.LittleEndian.PutUint32(w.buf[12:16], uint32(ts>>32))
|
||||
binary.LittleEndian.PutUint32(w.buf[16:20], uint32(ts))
|
||||
if _, err := w.w.Write(w.buf[:20]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := w.writeOptions(options); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
binary.LittleEndian.PutUint32(w.buf[0:4], length)
|
||||
_, err := w.w.Write(w.buf[:4])
|
||||
return err
|
||||
}
|
||||
|
||||
// WritePacket writes out packet with the given data and capture info. The given InterfaceIndex must already be added to the file. InterfaceIndex 0 is automatically added by the NewWriter* methods.
|
||||
func (w *NgWriter) WritePacket(ci gopacket.CaptureInfo, data []byte) error {
|
||||
if ci.InterfaceIndex >= int(w.intf) || ci.InterfaceIndex < 0 {
|
||||
return fmt.Errorf("Can't send statistics for non existent interface %d; have only %d interfaces", ci.InterfaceIndex, w.intf)
|
||||
}
|
||||
if ci.CaptureLength != len(data) {
|
||||
return fmt.Errorf("capture length %d does not match data length %d", ci.CaptureLength, len(data))
|
||||
}
|
||||
if ci.CaptureLength > ci.Length {
|
||||
return fmt.Errorf("invalid capture info %+v: capture length > length", ci)
|
||||
}
|
||||
|
||||
length := uint32(len(data)) + 32
|
||||
padding := (4 - length&3) & 3
|
||||
length += padding
|
||||
|
||||
ts := ci.Timestamp.UnixNano()
|
||||
|
||||
binary.LittleEndian.PutUint32(w.buf[:4], uint32(ngBlockTypeEnhancedPacket))
|
||||
binary.LittleEndian.PutUint32(w.buf[4:8], length)
|
||||
binary.LittleEndian.PutUint32(w.buf[8:12], uint32(ci.InterfaceIndex))
|
||||
binary.LittleEndian.PutUint32(w.buf[12:16], uint32(ts>>32))
|
||||
binary.LittleEndian.PutUint32(w.buf[16:20], uint32(ts))
|
||||
binary.LittleEndian.PutUint32(w.buf[20:24], uint32(ci.CaptureLength))
|
||||
binary.LittleEndian.PutUint32(w.buf[24:28], uint32(ci.Length))
|
||||
|
||||
if _, err := w.w.Write(w.buf[:28]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := w.w.Write(data); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
binary.LittleEndian.PutUint32(w.buf[:4], 0)
|
||||
_, err := w.w.Write(w.buf[4-padding : 8]) // padding + length
|
||||
return err
|
||||
}
|
||||
|
||||
// Flush writes out buffered data to the storage media. Must be called before closing the underlying file.
|
||||
func (w *NgWriter) Flush() error {
|
||||
return w.w.Flush()
|
||||
}
|
187
vendor/github.com/google/gopacket/pcapgo/pcapng.go
generated
vendored
Normal file
187
vendor/github.com/google/gopacket/pcapgo/pcapng.go
generated
vendored
Normal file
@ -0,0 +1,187 @@
|
||||
// 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 pcapgo
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"github.com/google/gopacket"
|
||||
"github.com/google/gopacket/layers"
|
||||
)
|
||||
|
||||
// ErrNgVersionMismatch gets returned for unknown pcapng section versions. This can only happen if ReaderOptions.SkipUnknownVersion == false
|
||||
var ErrNgVersionMismatch = errors.New("Unknown pcapng Version in Section Header")
|
||||
|
||||
// ErrNgLinkTypeMismatch gets returned if the link type of an interface is not the same as the link type from the first interface. This can only happen if ReaderOptions.ErrorOnMismatchingLinkType == true && ReaderOptions.WantMixedLinkType == false
|
||||
var ErrNgLinkTypeMismatch = errors.New("Link type of current interface is different from first one")
|
||||
|
||||
const (
|
||||
ngByteOrderMagic = 0x1A2B3C4D
|
||||
|
||||
// We can handle only version 1.0
|
||||
ngVersionMajor = 1
|
||||
ngVersionMinor = 0
|
||||
)
|
||||
|
||||
type ngBlockType uint32
|
||||
|
||||
const (
|
||||
ngBlockTypeInterfaceDescriptor ngBlockType = 1 // Interface description block
|
||||
ngBlockTypePacket ngBlockType = 2 // Packet block (deprecated)
|
||||
ngBlockTypeSimplePacket ngBlockType = 3 // Simple packet block
|
||||
ngBlockTypeInterfaceStatistics ngBlockType = 5 // Interface statistics block
|
||||
ngBlockTypeEnhancedPacket ngBlockType = 6 // Enhanced packet block
|
||||
ngBlockTypeSectionHeader ngBlockType = 0x0A0D0D0A // Section header block (same in both endians)
|
||||
)
|
||||
|
||||
type ngOptionCode uint16
|
||||
|
||||
const (
|
||||
ngOptionCodeEndOfOptions ngOptionCode = iota // end of options. must be at the end of options in a block
|
||||
ngOptionCodeComment // comment
|
||||
ngOptionCodeHardware // description of the hardware
|
||||
ngOptionCodeOS // name of the operating system
|
||||
ngOptionCodeUserApplication // name of the application
|
||||
)
|
||||
|
||||
const (
|
||||
ngOptionCodeInterfaceName ngOptionCode = iota + 2 // interface name
|
||||
ngOptionCodeInterfaceDescription // interface description
|
||||
ngOptionCodeInterfaceIPV4Address // IPv4 network address and netmask for the interface
|
||||
ngOptionCodeInterfaceIPV6Address // IPv6 network address and prefix length for the interface
|
||||
ngOptionCodeInterfaceMACAddress // interface hardware MAC address
|
||||
ngOptionCodeInterfaceEUIAddress // interface hardware EUI address
|
||||
ngOptionCodeInterfaceSpeed // interface speed in bits/s
|
||||
ngOptionCodeInterfaceTimestampResolution // timestamp resolution
|
||||
ngOptionCodeInterfaceTimezone // time zone
|
||||
ngOptionCodeInterfaceFilter // capture filter
|
||||
ngOptionCodeInterfaceOS // operating system
|
||||
ngOptionCodeInterfaceFCSLength // length of the Frame Check Sequence in bits
|
||||
ngOptionCodeInterfaceTimestampOffset // offset (in seconds) that must be added to packet timestamp
|
||||
)
|
||||
|
||||
const (
|
||||
ngOptionCodeInterfaceStatisticsStartTime ngOptionCode = iota + 2 // Start of capture
|
||||
ngOptionCodeInterfaceStatisticsEndTime // End of capture
|
||||
ngOptionCodeInterfaceStatisticsInterfaceReceived // Packets received by physical interface
|
||||
ngOptionCodeInterfaceStatisticsInterfaceDropped // Packets dropped by physical interface
|
||||
ngOptionCodeInterfaceStatisticsFilterAccept // Packets accepted by filter
|
||||
ngOptionCodeInterfaceStatisticsOSDrop // Packets dropped by operating system
|
||||
ngOptionCodeInterfaceStatisticsDelivered // Packets delivered to user
|
||||
)
|
||||
|
||||
// ngOption is a pcapng option
|
||||
type ngOption struct {
|
||||
code ngOptionCode
|
||||
value []byte
|
||||
raw interface{}
|
||||
length uint16
|
||||
}
|
||||
|
||||
// ngBlock is a pcapng block header
|
||||
type ngBlock struct {
|
||||
typ ngBlockType
|
||||
length uint32 // remaining length of block
|
||||
}
|
||||
|
||||
// NgResolution represents a pcapng timestamp resolution
|
||||
type NgResolution uint8
|
||||
|
||||
// Binary returns true if the timestamp resolution is a negative power of two. Otherwise NgResolution is a negative power of 10.
|
||||
func (r NgResolution) Binary() bool {
|
||||
if r&0x80 == 0x80 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Exponent returns the negative exponent of the resolution.
|
||||
func (r NgResolution) Exponent() uint8 {
|
||||
return uint8(r) & 0x7f
|
||||
}
|
||||
|
||||
// ToTimestampResolution converts an NgResolution to a gopaket.TimestampResolution
|
||||
func (r NgResolution) ToTimestampResolution() (ret gopacket.TimestampResolution) {
|
||||
if r.Binary() {
|
||||
ret.Base = 2
|
||||
} else {
|
||||
ret.Base = 10
|
||||
}
|
||||
ret.Exponent = -int(r.Exponent())
|
||||
return
|
||||
}
|
||||
|
||||
// NgNoValue64 is a placeholder for an empty numeric 64 bit value.
|
||||
const NgNoValue64 = math.MaxUint64
|
||||
|
||||
// NgInterfaceStatistics hold the statistic for an interface at a single point in time. These values are already supposed to be accumulated. Most pcapng files contain this information at the end of the file/section.
|
||||
type NgInterfaceStatistics struct {
|
||||
// LastUpdate is the last time the statistics were updated.
|
||||
LastUpdate time.Time
|
||||
// StartTime is the time packet capture started on this interface. This value might be zero if this option is missing.
|
||||
StartTime time.Time
|
||||
// EndTime is the time packet capture ended on this interface This value might be zero if this option is missing.
|
||||
EndTime time.Time
|
||||
// Comment can be an arbitrary comment. This value might be empty if this option is missing.
|
||||
Comment string
|
||||
// PacketsReceived are the number of received packets. This value might be NoValue64 if this option is missing.
|
||||
PacketsReceived uint64
|
||||
// PacketsReceived are the number of received packets. This value might be NoValue64 if this option is missing.
|
||||
PacketsDropped uint64
|
||||
}
|
||||
|
||||
var ngEmptyStatistics = NgInterfaceStatistics{
|
||||
PacketsReceived: NgNoValue64,
|
||||
PacketsDropped: NgNoValue64,
|
||||
}
|
||||
|
||||
// NgInterface holds all the information of a pcapng interface.
|
||||
type NgInterface struct {
|
||||
// Name is the name of the interface. This value might be empty if this option is missing.
|
||||
Name string
|
||||
// Comment can be an arbitrary comment. This value might be empty if this option is missing.
|
||||
Comment string
|
||||
// Description is a description of the interface. This value might be empty if this option is missing.
|
||||
Description string
|
||||
// Filter is the filter used during packet capture. This value might be empty if this option is missing.
|
||||
Filter string
|
||||
// OS is the operating system this interface was controlled by. This value might be empty if this option is missing.
|
||||
OS string
|
||||
// LinkType is the linktype of the interface.
|
||||
LinkType layers.LinkType
|
||||
// TimestampResolution is the timestamp resolution of the packets in the pcapng file belonging to this interface.
|
||||
TimestampResolution NgResolution
|
||||
// TimestampResolution is the timestamp offset in seconds of the packets in the pcapng file belonging to this interface.
|
||||
TimestampOffset uint64
|
||||
// SnapLength is the maximum packet length captured by this interface. 0 for unlimited
|
||||
SnapLength uint32
|
||||
// Statistics holds the interface statistics
|
||||
Statistics NgInterfaceStatistics
|
||||
|
||||
secondMask uint64
|
||||
scaleUp uint64
|
||||
scaleDown uint64
|
||||
}
|
||||
|
||||
// Resolution returns the timestamp resolution of acquired timestamps before scaling to NanosecondTimestampResolution.
|
||||
func (i NgInterface) Resolution() gopacket.TimestampResolution {
|
||||
return i.TimestampResolution.ToTimestampResolution()
|
||||
}
|
||||
|
||||
// NgSectionInfo contains additional information of a pcapng section
|
||||
type NgSectionInfo struct {
|
||||
// Hardware is the hardware this file was generated on. This value might be empty if this option is missing.
|
||||
Hardware string
|
||||
// OS is the operating system this file was generated on. This value might be empty if this option is missing.
|
||||
OS string
|
||||
// Application is the user space application this file was generated with. This value might be empty if this option is missing.
|
||||
Application string
|
||||
// Comment can be an arbitrary comment. This value might be empty if this option is missing.
|
||||
Comment string
|
||||
}
|
47
vendor/github.com/google/gopacket/pcapgo/read.go
generated
vendored
47
vendor/github.com/google/gopacket/pcapgo/read.go
generated
vendored
@ -15,6 +15,7 @@ import (
|
||||
|
||||
"bufio"
|
||||
"compress/gzip"
|
||||
|
||||
"github.com/google/gopacket"
|
||||
"github.com/google/gopacket/layers"
|
||||
)
|
||||
@ -40,6 +41,8 @@ type Reader struct {
|
||||
linkType layers.LinkType
|
||||
// reusable buffer
|
||||
buf [16]byte
|
||||
// buffer for ZeroCopyReadPacketData
|
||||
packetBuf []byte
|
||||
}
|
||||
|
||||
const magicNanoseconds = 0xA1B23C4D
|
||||
@ -121,7 +124,11 @@ func (r *Reader) ReadPacketData() (data []byte, ci gopacket.CaptureInfo, err err
|
||||
return
|
||||
}
|
||||
if ci.CaptureLength > int(r.snaplen) {
|
||||
err = fmt.Errorf("capture length exceeds snap length: %d > %d", 16+ci.CaptureLength, r.snaplen)
|
||||
err = fmt.Errorf("capture length exceeds snap length: %d > %d", ci.CaptureLength, r.snaplen)
|
||||
return
|
||||
}
|
||||
if ci.CaptureLength > ci.Length {
|
||||
err = fmt.Errorf("capture length exceeds original packet length: %d > %d", ci.CaptureLength, ci.Length)
|
||||
return
|
||||
}
|
||||
data = make([]byte, ci.CaptureLength)
|
||||
@ -129,6 +136,36 @@ func (r *Reader) ReadPacketData() (data []byte, ci gopacket.CaptureInfo, err err
|
||||
return data, ci, err
|
||||
}
|
||||
|
||||
// ZeroCopyReadPacketData reads next packet from file. The data buffer is owned by the Reader,
|
||||
// and each call to ZeroCopyReadPacketData invalidates data returned by the previous one.
|
||||
//
|
||||
// It is not true zero copy, as data is still copied from the underlying reader. However,
|
||||
// this method avoids allocating heap memory for every packet.
|
||||
func (r *Reader) ZeroCopyReadPacketData() (data []byte, ci gopacket.CaptureInfo, err error) {
|
||||
if ci, err = r.readPacketHeader(); err != nil {
|
||||
return
|
||||
}
|
||||
if ci.CaptureLength > int(r.snaplen) {
|
||||
err = fmt.Errorf("capture length exceeds snap length: %d > %d", ci.CaptureLength, r.snaplen)
|
||||
return
|
||||
}
|
||||
if ci.CaptureLength > ci.Length {
|
||||
err = fmt.Errorf("capture length exceeds original packet length: %d > %d", ci.CaptureLength, ci.Length)
|
||||
return
|
||||
}
|
||||
|
||||
if cap(r.packetBuf) < ci.CaptureLength {
|
||||
snaplen := int(r.snaplen)
|
||||
if snaplen < ci.CaptureLength {
|
||||
snaplen = ci.CaptureLength
|
||||
}
|
||||
r.packetBuf = make([]byte, snaplen)
|
||||
}
|
||||
data = r.packetBuf[:ci.CaptureLength]
|
||||
_, err = io.ReadFull(r.r, data)
|
||||
return data, ci, err
|
||||
}
|
||||
|
||||
func (r *Reader) readPacketHeader() (ci gopacket.CaptureInfo, err error) {
|
||||
if _, err = io.ReadFull(r.r, r.buf[:]); err != nil {
|
||||
return
|
||||
@ -184,3 +221,11 @@ func (r *Reader) SetSnaplen(newSnaplen uint32) {
|
||||
func (r *Reader) String() string {
|
||||
return fmt.Sprintf("PcapFile maj: %x min: %x snaplen: %d linktype: %s", r.versionMajor, r.versionMinor, r.snaplen, r.linkType)
|
||||
}
|
||||
|
||||
// Resolution returns the timestamp resolution of acquired timestamps before scaling to NanosecondTimestampResolution.
|
||||
func (r *Reader) Resolution() gopacket.TimestampResolution {
|
||||
if r.nanoSecsFactor == 1 {
|
||||
return gopacket.TimestampResolutionMicrosecond
|
||||
}
|
||||
return gopacket.TimestampResolutionNanosecond
|
||||
}
|
||||
|
2
vendor/github.com/google/gopacket/pcapgo/write.go
generated
vendored
2
vendor/github.com/google/gopacket/pcapgo/write.go
generated
vendored
@ -4,8 +4,6 @@
|
||||
// that can be found in the LICENSE file in the root of the source
|
||||
// tree.
|
||||
|
||||
// Package pcapgo provides some native PCAP support, not requiring
|
||||
// C libpcap to be installed.
|
||||
package pcapgo
|
||||
|
||||
import (
|
||||
|
72
vendor/github.com/google/gopacket/time.go
generated
vendored
Normal file
72
vendor/github.com/google/gopacket/time.go
generated
vendored
Normal file
@ -0,0 +1,72 @@
|
||||
// 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 gopacket
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"time"
|
||||
)
|
||||
|
||||
// TimestampResolution represents the resolution of timestamps in Base^Exponent.
|
||||
type TimestampResolution struct {
|
||||
Base, Exponent int
|
||||
}
|
||||
|
||||
func (t TimestampResolution) String() string {
|
||||
return fmt.Sprintf("%d^%d", t.Base, t.Exponent)
|
||||
}
|
||||
|
||||
// ToDuration returns the smallest representable time difference as a time.Duration
|
||||
func (t TimestampResolution) ToDuration() time.Duration {
|
||||
if t.Base == 0 {
|
||||
return 0
|
||||
}
|
||||
if t.Exponent == 0 {
|
||||
return time.Second
|
||||
}
|
||||
switch t.Base {
|
||||
case 10:
|
||||
return time.Duration(math.Pow10(t.Exponent + 9))
|
||||
case 2:
|
||||
if t.Exponent < 0 {
|
||||
return time.Second >> uint(-t.Exponent)
|
||||
}
|
||||
return time.Second << uint(t.Exponent)
|
||||
default:
|
||||
// this might loose precision
|
||||
return time.Duration(float64(time.Second) * math.Pow(float64(t.Base), float64(t.Exponent)))
|
||||
}
|
||||
}
|
||||
|
||||
// TimestampResolutionInvalid represents an invalid timestamp resolution
|
||||
var TimestampResolutionInvalid = TimestampResolution{}
|
||||
|
||||
// TimestampResolutionMillisecond is a resolution of 10^-3s
|
||||
var TimestampResolutionMillisecond = TimestampResolution{10, -3}
|
||||
|
||||
// TimestampResolutionMicrosecond is a resolution of 10^-6s
|
||||
var TimestampResolutionMicrosecond = TimestampResolution{10, -6}
|
||||
|
||||
// TimestampResolutionNanosecond is a resolution of 10^-9s
|
||||
var TimestampResolutionNanosecond = TimestampResolution{10, -9}
|
||||
|
||||
// TimestampResolutionNTP is the resolution of NTP timestamps which is 2^-32 ≈ 233 picoseconds
|
||||
var TimestampResolutionNTP = TimestampResolution{2, -32}
|
||||
|
||||
// TimestampResolutionCaptureInfo is the resolution used in CaptureInfo, which his currently nanosecond
|
||||
var TimestampResolutionCaptureInfo = TimestampResolutionNanosecond
|
||||
|
||||
// PacketSourceResolution is an interface for packet data sources that
|
||||
// support reporting the timestamp resolution of the aqcuired timestamps.
|
||||
// Returned timestamps will always have NanosecondTimestampResolution due
|
||||
// to the use of time.Time, but scaling might have occured if acquired
|
||||
// timestamps have a different resolution.
|
||||
type PacketSourceResolution interface {
|
||||
// Resolution returns the timestamp resolution of acquired timestamps before scaling to NanosecondTimestampResolution.
|
||||
Resolution() TimestampResolution
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user