├── .gitignore ├── .travis.gofmt.sh ├── .travis.golint.sh ├── .travis.govet.sh ├── .travis.install.sh ├── .travis.script.sh ├── .travis.yml ├── AUTHORS ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── afpacket ├── afpacket.go ├── afpacket_test.go ├── header.go ├── options.go └── sockopt_linux.go ├── base.go ├── benchmark_test.go ├── bsdbpf └── bsd_bpf_sniffer.go ├── bytediff ├── bytediff.go └── bytediff_test.go ├── decode.go ├── defrag └── lcmdefrag │ ├── lcmdefrag.go │ └── lcmdefrag_test.go ├── doc.go ├── dumpcommand └── tcpdump.go ├── examples ├── afpacket │ └── afpacket.go ├── arpscan │ └── arpscan.go ├── bidirectional │ └── main.go ├── bytediff │ ├── bytediff.png │ └── main.go ├── httpassembly │ └── main.go ├── pcapdump │ └── main.go ├── pcaplay │ └── main.go ├── pfdump │ └── main.go ├── reassemblydump │ ├── compare.sh │ └── main.go ├── snoopread │ └── main.go ├── statsassembly │ └── main.go ├── synscan │ └── main.go └── util │ └── util.go ├── flows.go ├── gc ├── gen.go ├── go.mod ├── go.sum ├── ip4defrag ├── defrag.go └── defrag_test.go ├── layerclass.go ├── layers ├── .lint_blacklist ├── ague_var0.go ├── ague_var0_test.go ├── ague_var1.go ├── ague_var1_test.go ├── apsp.go ├── apsp_test.go ├── arp.go ├── asf.go ├── asf_presencepong.go ├── asf_presencepong_test.go ├── asf_test.go ├── base.go ├── base_test.go ├── bfd.go ├── bfd_test.go ├── bitfield.go ├── bitfield_test.go ├── cdp.go ├── ctp.go ├── decode_test.go ├── dhcp_test.go ├── dhcpv4.go ├── dhcpv6.go ├── dhcpv6_options.go ├── dhcpv6_test.go ├── dns.go ├── dns_test.go ├── doc.go ├── dot11.go ├── dot11_test.go ├── dot1q.go ├── dot1q_test.go ├── eap.go ├── eapol.go ├── eapol_test.go ├── endpoints.go ├── endpoints_test.go ├── enums.go ├── enums_generated.go ├── erspan2.go ├── erspan2_test.go ├── etherip.go ├── ethernet.go ├── fddi.go ├── fuzz_layer.go ├── gen.go ├── gen2.go ├── gen_linted.sh ├── geneve.go ├── geneve_test.go ├── gre.go ├── gre_test.go ├── gtp.go ├── gtp_test.go ├── iana_ports.go ├── icmp4.go ├── icmp6.go ├── icmp6NDflags_test.go ├── icmp6_test.go ├── icmp6hopbyhop_test.go ├── icmp6msg.go ├── icmp6msg_test.go ├── igmp.go ├── igmp_test.go ├── ip4.go ├── ip4_test.go ├── ip6.go ├── ip6_test.go ├── ipsec.go ├── ipsec_test.go ├── layertypes.go ├── lcm.go ├── lcm_test.go ├── linux_sll.go ├── llc.go ├── lldp.go ├── lldp_test.go ├── loopback.go ├── mldv1.go ├── mldv1_test.go ├── mldv2.go ├── mldv2_test.go ├── modbustcp.go ├── mpls.go ├── mpls_test.go ├── ndp.go ├── ntp.go ├── ntp_test.go ├── ospf.go ├── ospf_test.go ├── pflog.go ├── ports.go ├── ppp.go ├── pppoe.go ├── prism.go ├── prism_test.go ├── radiotap.go ├── radiotap_test.go ├── radius.go ├── radius_test.go ├── rmcp.go ├── rmcp_test.go ├── rudp.go ├── sctp.go ├── sflow.go ├── sflow_test.go ├── sip.go ├── sip_test.go ├── stp.go ├── stp_test.go ├── tcp.go ├── tcp_test.go ├── tcpip.go ├── tcpip_test.go ├── test_creator.py ├── testdata │ └── fuzz │ │ └── FuzzDecodeFromBytes │ │ ├── 27d23183d8ce7b719228870c23869cf21bf8829d7160c82da88f80aeff2d861c │ │ ├── 3b53f220d321f20980b59f64e1617d6b334b152a90b141a7407c3c8fa4837a31 │ │ ├── f539b7a397cf68c2129abd63d4c7cfb1979c489ad9bad6898510a4d4759bb85f │ │ └── fe20300d6b2057b406a06ec4f04065f6d0dda6b2b362c0a89192c1933e927adf ├── tls.go ├── tls_alert.go ├── tls_appdata.go ├── tls_cipherspec.go ├── tls_handshake.go ├── tls_test.go ├── udp.go ├── udp_test.go ├── udplite.go ├── usb.go ├── usb_test.go ├── vrrp.go ├── vrrp_test.go ├── vxlan.go └── vxlan_test.go ├── layers_decoder.go ├── layertype.go ├── macs ├── benchmark_test.go ├── doc.go ├── gen.go └── valid_mac_prefixes.go ├── packet.go ├── packet_test.go ├── parser.go ├── pcap ├── bpf_test.go ├── defs_windows_386.go ├── defs_windows_amd64.go ├── doc.go ├── generate_defs.go ├── gopacket_benchmark │ └── benchmark.go ├── pcap.go ├── pcap_test.go ├── pcap_tester.go ├── pcap_unix.go ├── pcap_windows.go ├── pcapgo_test.go ├── pcapnggo_test.go ├── test_dns.pcap ├── test_ethernet.pcap └── test_loopback.pcap ├── pcapgo ├── capture.go ├── capture_test.go ├── doc.go ├── ngread.go ├── ngread_test.go ├── ngwrite.go ├── ngwrite_test.go ├── pcapng.go ├── read.go ├── read_test.go ├── snoop.go ├── snoop_test.go ├── tests │ ├── README.md │ ├── be │ │ ├── test001.pcapng │ │ ├── test002.pcapng │ │ ├── test003.pcapng │ │ ├── test004.pcapng │ │ ├── test005.pcapng │ │ ├── test006.pcapng │ │ ├── test007.pcapng │ │ ├── test008.pcapng │ │ ├── test009.pcapng │ │ ├── test010.pcapng │ │ ├── test011.pcapng │ │ ├── test012.pcapng │ │ ├── test013.pcapng │ │ ├── test014.pcapng │ │ ├── test015.pcapng │ │ ├── test016.pcapng │ │ ├── test017.pcapng │ │ ├── test018.pcapng │ │ ├── test100.pcapng │ │ ├── test101.pcapng │ │ ├── test102.pcapng │ │ ├── test200.pcapng │ │ ├── test201.pcapng │ │ ├── test202.pcapng │ │ ├── test901.pcapng │ │ └── test902.pcapng │ ├── le │ │ ├── test001.pcapng │ │ ├── test002.pcapng │ │ ├── test003.pcapng │ │ ├── test004.pcapng │ │ ├── test005.pcapng │ │ ├── test006.pcapng │ │ ├── test007.pcapng │ │ ├── test008.pcapng │ │ ├── test009.pcapng │ │ ├── test010.pcapng │ │ ├── test011.pcapng │ │ ├── test012.pcapng │ │ ├── test013.pcapng │ │ ├── test014.pcapng │ │ ├── test015.pcapng │ │ ├── test016.pcapng │ │ ├── test017.pcapng │ │ ├── test018.pcapng │ │ ├── test100.pcapng │ │ ├── test101.pcapng │ │ ├── test102.pcapng │ │ ├── test200.pcapng │ │ ├── test201.pcapng │ │ ├── test202.pcapng │ │ ├── test901.pcapng │ │ └── test902.pcapng │ ├── test901.lua │ └── test902.lua ├── write.go └── write_test.go ├── pfring ├── doc.go ├── pfring.go └── pfring_test.go ├── reassembly ├── cap2test.go ├── memory.go ├── tcpassembly.go ├── tcpassembly_test.go ├── tcpcheck.go └── tcpcheck_test.go ├── routing ├── common.go ├── other.go ├── routing.go └── routing_test.go ├── tcpassembly ├── assembly.go ├── assembly_test.go └── tcpreader │ ├── reader.go │ └── reader_test.go ├── time.go ├── time_test.go ├── writer.go └── writer_test.go /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | #* 24 | *~ 25 | 26 | # examples binaries 27 | examples/synscan/synscan 28 | examples/pfdump/pfdump 29 | examples/pcapdump/pcapdump 30 | examples/httpassembly/httpassembly 31 | examples/statsassembly/statsassembly 32 | examples/arpscan/arpscan 33 | examples/bidirectional/bidirectional 34 | examples/bytediff/bytediff 35 | examples/reassemblydump/reassemblydump 36 | layers/gen 37 | macs/gen 38 | pcap/pcap_tester 39 | -------------------------------------------------------------------------------- /.travis.gofmt.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd "$(dirname $0)" 4 | if [ -n "$(go fmt ./...)" ]; then 5 | echo "Go code is not formatted, run 'go fmt github.com/google/stenographer/...'" >&2 6 | exit 1 7 | fi 8 | -------------------------------------------------------------------------------- /.travis.golint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd "$(dirname $0)" 4 | 5 | go get golang.org/x/lint/golint 6 | DIRS=". tcpassembly tcpassembly/tcpreader ip4defrag reassembly macs pcapgo pcap afpacket pfring routing defrag/lcmdefrag" 7 | # Add subdirectories here as we clean up golint on each. 8 | for subdir in $DIRS; do 9 | pushd $subdir 10 | if golint | 11 | grep -v CannotSetRFMon | # pcap exported error name 12 | grep -v DataLost | # tcpassembly/tcpreader exported error name 13 | grep .; then 14 | exit 1 15 | fi 16 | popd 17 | done 18 | 19 | pushd layers 20 | for file in *.go; do 21 | if cat .lint_blacklist | grep -q $file; then 22 | echo "Skipping lint of $file due to .lint_blacklist" 23 | elif golint $file | grep .; then 24 | echo "Lint error in file $file" 25 | exit 1 26 | fi 27 | done 28 | popd 29 | -------------------------------------------------------------------------------- /.travis.govet.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd "$(dirname $0)" 4 | DIRS=". layers pcap pcapgo tcpassembly tcpassembly/tcpreader routing ip4defrag bytediff macs defrag/lcmdefrag" 5 | set -e 6 | for subdir in $DIRS; do 7 | pushd $subdir 8 | go vet 9 | popd 10 | done 11 | -------------------------------------------------------------------------------- /.travis.install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -ev 4 | 5 | go get github.com/google/gopacket 6 | go get github.com/google/gopacket/layers 7 | go get github.com/google/gopacket/tcpassembly 8 | go get github.com/google/gopacket/reassembly 9 | go get github.com/google/gopacket/pcapgo 10 | -------------------------------------------------------------------------------- /.travis.script.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -ev 4 | 5 | go test github.com/google/gopacket 6 | go test github.com/google/gopacket/layers 7 | go test github.com/google/gopacket/tcpassembly 8 | go test github.com/google/gopacket/reassembly 9 | go test github.com/google/gopacket/pcapgo 10 | go test github.com/google/gopacket/pcap 11 | sudo $(which go) test github.com/google/gopacket/routing 12 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go: 3 | - 1.11.x 4 | - 1.12.x 5 | - 1.13.x 6 | - master 7 | 8 | addons: 9 | apt: 10 | packages: 11 | libpcap-dev 12 | 13 | # use modules except for older versions (see below) 14 | install: true 15 | 16 | env: 17 | - GO111MODULE=on 18 | 19 | script: ./.travis.script.sh 20 | 21 | matrix: 22 | fast_finish: true 23 | allow_failures: 24 | - go: master 25 | 26 | jobs: 27 | include: 28 | - go: 1.5.x 29 | install: ./.travis.install.sh 30 | - go: 1.6.x 31 | install: ./.travis.install.sh 32 | - go: 1.7.x 33 | install: ./.travis.install.sh 34 | - go: 1.8.x 35 | install: ./.travis.install.sh 36 | - go: 1.9.x 37 | install: ./.travis.install.sh 38 | - go: 1.10.x 39 | install: ./.travis.install.sh 40 | - os: osx 41 | go: 1.x 42 | # windows doesn't work on travis (package installation just hangs and then errors out) 43 | # - os: windows 44 | # go: 1.x 45 | # # We don't need nmap - but that's the only way to get npcap: 46 | # before_install: choco install npcap --version 0.86 -y 47 | - stage: style 48 | name: "fmt/vet/lint" 49 | go: 1.x 50 | script: 51 | - ./.travis.gofmt.sh 52 | - ./.travis.govet.sh 53 | - ./.travis.golint.sh 54 | 55 | stages: 56 | - style 57 | - test 58 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | AUTHORS AND MAINTAINERS: 2 | 3 | MAIN DEVELOPERS: 4 | Graeme Connell 5 | 6 | AUTHORS: 7 | Nigel Tao 8 | Cole Mickens 9 | Ben Daglish 10 | Luis Martinez 11 | Remco Verhoef 12 | Hiroaki Kawai 13 | Lukas Lueg 14 | Laurent Hausermann 15 | Bill Green 16 | Christian Mäder 17 | Gernot Vormayr 18 | Vitor Garcia Graveto 19 | Elias Chavarria Reyes 20 | Daniel Rittweiler 21 | 22 | CONTRIBUTORS: 23 | Attila Oláh 24 | Vittus Mikiassen 25 | Matthias Radestock 26 | Matthew Sackman 27 | Loic Prylli 28 | Alexandre Fiori 29 | Adrian Tam 30 | Satoshi Matsumoto 31 | David Stainton 32 | Jesse Ward 33 | Kane Mathers 34 | Jose Selvi 35 | Yerden Zhumabekov 36 | Jensen Hwa 37 | 38 | ----------------------------------------------- 39 | FORKED FROM github.com/akrennmair/gopcap 40 | ALL THE FOLLOWING ARE FOR THAT PROJECT 41 | 42 | MAIN DEVELOPERS: 43 | Andreas Krennmair 44 | 45 | CONTRIBUTORS: 46 | Andrea Nall 47 | Daniel Arndt 48 | Dustin Sallings 49 | Graeme Connell 50 | Guillaume Savary 51 | Mark Smith 52 | Miek Gieben 53 | Mike Bell 54 | Trevor Strohman 55 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Google, Inc. All rights reserved. 2 | Copyright (c) 2009-2011 Andreas Krennmair. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above 11 | copyright notice, this list of conditions and the following disclaimer 12 | in the documentation and/or other materials provided with the 13 | distribution. 14 | * Neither the name of Andreas Krennmair, Google, nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GoPacket 2 | 3 | This library provides packet decoding capabilities for Go. 4 | See [godoc](https://godoc.org/github.com/google/gopacket) for more details. 5 | 6 | [![Build Status](https://travis-ci.org/google/gopacket.svg?branch=master)](https://travis-ci.org/google/gopacket) 7 | [![GoDoc](https://godoc.org/github.com/google/gopacket?status.svg)](https://godoc.org/github.com/google/gopacket) 8 | 9 | Minimum Go version required is 1.5 except for pcapgo/EthernetHandle, afpacket, and bsdbpf which need at least 1.9 due to x/sys/unix dependencies. 10 | 11 | Originally forked from the gopcap project written by Andreas 12 | Krennmair (http://github.com/akrennmair/gopcap). 13 | -------------------------------------------------------------------------------- /afpacket/afpacket_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | // +build linux 8 | 9 | package afpacket 10 | 11 | import ( 12 | "reflect" 13 | "testing" 14 | ) 15 | 16 | func TestParseOptions(t *testing.T) { 17 | wanted1 := defaultOpts 18 | wanted1.frameSize = 1 << 10 19 | wanted1.framesPerBlock = wanted1.blockSize / wanted1.frameSize 20 | for i, test := range []struct { 21 | opts []interface{} 22 | want options 23 | err bool 24 | }{ 25 | {opts: []interface{}{OptBlockSize(2)}, err: true}, 26 | {opts: []interface{}{OptFrameSize(333)}, err: true}, 27 | {opts: []interface{}{OptTPacketVersion(-3)}, err: true}, 28 | {opts: []interface{}{OptTPacketVersion(5)}, err: true}, 29 | {opts: []interface{}{OptFrameSize(1 << 10)}, want: wanted1}, 30 | } { 31 | got, err := parseOptions(test.opts...) 32 | t.Logf("got: %#v\nerr: %v", got, err) 33 | if test.err && err == nil || !test.err && err != nil { 34 | t.Errorf("%d error mismatch, want error? %v. error: %v", i, test.err, err) 35 | } 36 | if !test.err && !reflect.DeepEqual(test.want, got) { 37 | t.Errorf("%d opts mismatch, want\n%#v", i, test.want) 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /afpacket/sockopt_linux.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | // +build linux 8 | 9 | package afpacket 10 | 11 | import ( 12 | "unsafe" 13 | 14 | "golang.org/x/sys/unix" 15 | ) 16 | 17 | // setsockopt provides access to the setsockopt syscall. 18 | func setsockopt(fd, level, name int, val unsafe.Pointer, vallen uintptr) error { 19 | _, _, errno := unix.Syscall6( 20 | unix.SYS_SETSOCKOPT, 21 | uintptr(fd), 22 | uintptr(level), 23 | uintptr(name), 24 | uintptr(val), 25 | vallen, 26 | 0, 27 | ) 28 | if errno != 0 { 29 | return error(errno) 30 | } 31 | 32 | return nil 33 | } 34 | 35 | // getsockopt provides access to the getsockopt syscall. 36 | func getsockopt(fd, level, name int, val unsafe.Pointer, vallen uintptr) error { 37 | _, _, errno := unix.Syscall6( 38 | unix.SYS_GETSOCKOPT, 39 | uintptr(fd), 40 | uintptr(level), 41 | uintptr(name), 42 | uintptr(val), 43 | vallen, 44 | 0, 45 | ) 46 | if errno != 0 { 47 | return error(errno) 48 | } 49 | 50 | return nil 51 | } 52 | 53 | // htons converts a short (uint16) from host-to-network byte order. 54 | // Thanks to mikioh for this neat trick: 55 | // https://github.com/mikioh/-stdyng/blob/master/afpacket.go 56 | func htons(i uint16) uint16 { 57 | return (i<<8)&0xff00 | i>>8 58 | } 59 | -------------------------------------------------------------------------------- /bytediff/bytediff_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | package bytediff 8 | 9 | import ( 10 | "reflect" 11 | "testing" 12 | ) 13 | 14 | func TestLCS(t *testing.T) { 15 | for i, test := range []struct { 16 | a, b []byte 17 | indexA, indexB, length int 18 | }{ 19 | {[]byte{1, 2, 3}, []byte{1, 2, 3}, 0, 0, 3}, 20 | {[]byte{0, 1, 2, 3}, []byte{1, 2, 3, 4}, 1, 0, 3}, 21 | {[]byte{0, 1, 2, 3, 1, 2, 3, 4, 1, 2, 3}, []byte{1, 2, 3, 4}, 4, 0, 4}, 22 | {[]byte{1, 2, 2, 3, 4}, []byte{1, 2, 3, 4}, 2, 1, 3}, 23 | {[]byte{0, 1, 2, 3, 4}, []byte{1, 1, 2, 2, 3, 4}, 2, 3, 3}, 24 | } { 25 | ia, ib, l := longestCommonSubstring(test.a, test.b) 26 | if ia != test.indexA || ib != test.indexB || l != test.length { 27 | t.Errorf("%d: want (%d %d %d) got (%d %d %d)", i, test.indexA, test.indexB, test.length, ia, ib, l) 28 | } 29 | } 30 | } 31 | 32 | func TestDiff(t *testing.T) { 33 | for i, test := range []struct { 34 | a, b []byte 35 | d Differences 36 | }{ 37 | { 38 | []byte{0, 1, 2, 3, 4}, 39 | []byte{1, 1, 2, 2, 3, 4}, 40 | Differences{ 41 | Difference{true, []byte{0}, []byte{}}, 42 | Difference{false, []byte{1}, []byte{1}}, 43 | Difference{true, []byte{}, []byte{1, 2}}, 44 | Difference{false, []byte{2, 3, 4}, []byte{2, 3, 4}}, 45 | }, 46 | }, 47 | } { 48 | diffs := Diff(test.a, test.b) 49 | if !reflect.DeepEqual(diffs, test.d) { 50 | t.Errorf("%d want %v got %v", i, test.d, diffs) 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /defrag/lcmdefrag/lcmdefrag_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | package lcmdefrag 8 | 9 | import ( 10 | "testing" 11 | 12 | "github.com/google/gopacket" 13 | "github.com/google/gopacket/layers" 14 | ) 15 | 16 | var ( 17 | fragmentOne = []byte{ 18 | 0x4c, 0x43, 0x30, 0x33, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0d, 19 | 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x02, 0x4c, 0x43, 0x4d, 0x5f, 20 | 0x53, 0x45, 0x4c, 0x46, 0x5f, 0x54, 0x45, 0x53, 0x54, 0x00, 0x6c, 0x63, 21 | 0x6d, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x20, 0x74, 0x65, 0x73, 0x74, 22 | } 23 | 24 | fragmentTwo = []byte{ 25 | 0x4c, 0x43, 0x30, 0x33, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0d, 26 | 0x00, 0x00, 0x00, 0x2d, 0x00, 0x01, 0x00, 0x02, 0x6c, 0x63, 0x6d, 0x20, 27 | 0x73, 0x65, 0x6c, 0x66, 0x20, 0x74, 0x65, 0x73, 0x74, 28 | } 29 | 30 | completePacket = []byte{ 31 | 0x4c, 0x43, 0x30, 0x32, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x43, 0x4d, 0x5f, 32 | 0x53, 0x45, 0x4c, 0x46, 0x5f, 0x54, 0x45, 0x53, 0x54, 0x00, 0x6c, 0x63, 33 | 0x6d, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x20, 0x74, 0x65, 0x73, 0x74, 34 | } 35 | ) 36 | 37 | func TestOrderedLCMDefrag(t *testing.T) { 38 | defragmenter := NewLCMDefragmenter() 39 | var err error 40 | 41 | packet := gopacket.NewPacket(fragmentOne, layers.LayerTypeLCM, gopacket.NoCopy) 42 | lcm := packet.Layer(layers.LayerTypeLCM).(*layers.LCM) 43 | 44 | lcm, err = defragmenter.Defrag(lcm) 45 | if lcm != nil { 46 | t.Fatal("Returned incomplete LCM message.") 47 | } 48 | if err != nil { 49 | t.Fatal(err) 50 | } 51 | 52 | packet = gopacket.NewPacket(fragmentTwo, layers.LayerTypeLCM, gopacket.NoCopy) 53 | lcm = packet.Layer(layers.LayerTypeLCM).(*layers.LCM) 54 | 55 | lcm, err = defragmenter.Defrag(lcm) 56 | if lcm == nil { 57 | t.Fatal("Did not receive defragmented LCM message.") 58 | } 59 | if err != nil { 60 | t.Fatal(err) 61 | } 62 | } 63 | 64 | func TestUnorderedLCMDefrag(t *testing.T) { 65 | defragmenter := NewLCMDefragmenter() 66 | var err error 67 | 68 | packet := gopacket.NewPacket(fragmentTwo, layers.LayerTypeLCM, gopacket.NoCopy) 69 | lcm := packet.Layer(layers.LayerTypeLCM).(*layers.LCM) 70 | 71 | lcm, err = defragmenter.Defrag(lcm) 72 | if lcm != nil { 73 | t.Fatal("Returned incomplete LCM message.") 74 | } 75 | if err != nil { 76 | t.Fatal(err) 77 | } 78 | 79 | packet = gopacket.NewPacket(fragmentOne, layers.LayerTypeLCM, gopacket.NoCopy) 80 | lcm = packet.Layer(layers.LayerTypeLCM).(*layers.LCM) 81 | 82 | lcm, err = defragmenter.Defrag(lcm) 83 | if lcm == nil { 84 | t.Fatal("Did not receive defragmented LCM message.") 85 | } 86 | if err != nil { 87 | t.Fatal(err) 88 | } 89 | } 90 | 91 | func TestNonLCMDefrag(t *testing.T) { 92 | defragmenter := NewLCMDefragmenter() 93 | var err error 94 | 95 | packet := gopacket.NewPacket(completePacket, layers.LayerTypeLCM, gopacket.NoCopy) 96 | lcm := packet.Layer(layers.LayerTypeLCM).(*layers.LCM) 97 | 98 | lcm, err = defragmenter.Defrag(lcm) 99 | if lcm == nil { 100 | t.Fatal("Did not receive complete LCM message.") 101 | } 102 | if err != nil { 103 | t.Fatal(err) 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /examples/bytediff/bytediff.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/examples/bytediff/bytediff.png -------------------------------------------------------------------------------- /examples/pcapdump/main.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | // The pcapdump binary implements a tcpdump-like command line tool with gopacket 8 | // using pcap as a backend data collection mechanism. 9 | package main 10 | 11 | import ( 12 | "flag" 13 | "fmt" 14 | "github.com/google/gopacket/dumpcommand" 15 | "github.com/google/gopacket/examples/util" 16 | "github.com/google/gopacket/pcap" 17 | "log" 18 | "os" 19 | "strings" 20 | "time" 21 | ) 22 | 23 | var iface = flag.String("i", "eth0", "Interface to read packets from") 24 | var fname = flag.String("r", "", "Filename to read from, overrides -i") 25 | var snaplen = flag.Int("s", 65536, "Snap length (number of bytes max to read per packet") 26 | var tstype = flag.String("timestamp_type", "", "Type of timestamps to use") 27 | var promisc = flag.Bool("promisc", true, "Set promiscuous mode") 28 | 29 | func main() { 30 | defer util.Run()() 31 | var handle *pcap.Handle 32 | var err error 33 | if *fname != "" { 34 | if handle, err = pcap.OpenOffline(*fname); err != nil { 35 | log.Fatal("PCAP OpenOffline error:", err) 36 | } 37 | } else { 38 | // This is a little complicated because we want to allow all possible options 39 | // for creating the packet capture handle... instead of all this you can 40 | // just call pcap.OpenLive if you want a simple handle. 41 | inactive, err := pcap.NewInactiveHandle(*iface) 42 | if err != nil { 43 | log.Fatalf("could not create: %v", err) 44 | } 45 | defer inactive.CleanUp() 46 | if err = inactive.SetSnapLen(*snaplen); err != nil { 47 | log.Fatalf("could not set snap length: %v", err) 48 | } else if err = inactive.SetPromisc(*promisc); err != nil { 49 | log.Fatalf("could not set promisc mode: %v", err) 50 | } else if err = inactive.SetTimeout(time.Second); err != nil { 51 | log.Fatalf("could not set timeout: %v", err) 52 | } 53 | if *tstype != "" { 54 | if t, err := pcap.TimestampSourceFromString(*tstype); err != nil { 55 | log.Fatalf("Supported timestamp types: %v", inactive.SupportedTimestamps()) 56 | } else if err := inactive.SetTimestampSource(t); err != nil { 57 | log.Fatalf("Supported timestamp types: %v", inactive.SupportedTimestamps()) 58 | } 59 | } 60 | if handle, err = inactive.Activate(); err != nil { 61 | log.Fatal("PCAP Activate error:", err) 62 | } 63 | defer handle.Close() 64 | } 65 | if len(flag.Args()) > 0 { 66 | bpffilter := strings.Join(flag.Args(), " ") 67 | fmt.Fprintf(os.Stderr, "Using BPF filter %q\n", bpffilter) 68 | if err = handle.SetBPFFilter(bpffilter); err != nil { 69 | log.Fatal("BPF filter error:", err) 70 | } 71 | } 72 | dumpcommand.Run(handle) 73 | } 74 | -------------------------------------------------------------------------------- /examples/pfdump/main.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | // The pfdump binary implements a tcpdump-like command line tool with gopacket 8 | // using pfring as a backend data collection mechanism. 9 | package main 10 | 11 | import ( 12 | "flag" 13 | "fmt" 14 | "github.com/google/gopacket/dumpcommand" 15 | "github.com/google/gopacket/examples/util" 16 | "github.com/google/gopacket/pfring" 17 | "log" 18 | "os" 19 | "strings" 20 | ) 21 | 22 | var iface = flag.String("i", "eth0", "Interface to read packets from") 23 | var snaplen = flag.Int("s", 65536, "Snap length (number of bytes max to read per packet") 24 | var cluster = flag.Int("cluster", -1, "If >= 0, sets the pfring cluster to this value") 25 | var clustertype = flag.Int("clustertype", int(pfring.ClusterPerFlow), "Cluster type") 26 | 27 | func main() { 28 | defer util.Run()() 29 | var ring *pfring.Ring 30 | var err error 31 | if ring, err = pfring.NewRing(*iface, uint32(*snaplen), pfring.FlagPromisc); err != nil { 32 | log.Fatalln("pfring ring creation error:", err) 33 | } 34 | if len(flag.Args()) > 0 { 35 | bpffilter := strings.Join(flag.Args(), " ") 36 | fmt.Fprintf(os.Stderr, "Using BPF filter %q\n", bpffilter) 37 | if err = ring.SetBPFFilter(bpffilter); err != nil { 38 | log.Fatalln("BPF filter error:", err) 39 | } 40 | } 41 | if *cluster >= 0 { 42 | if err = ring.SetCluster(*cluster, pfring.ClusterType(*clustertype)); err != nil { 43 | log.Fatalln("pfring SetCluster error:", err) 44 | } 45 | } 46 | if err = ring.SetSocketMode(pfring.ReadOnly); err != nil { 47 | log.Fatalln("pfring SetSocketMode error:", err) 48 | } else if err = ring.Enable(); err != nil { 49 | log.Fatalln("pfring Enable error:", err) 50 | } 51 | dumpcommand.Run(ring) 52 | } 53 | -------------------------------------------------------------------------------- /examples/reassemblydump/compare.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Limitations: if the number extracted files in too big, finding identical 4 | # files might fail due to '*' in cmdline 5 | # This would require to split sha256sum symlinks in xx/yyyyy 6 | 7 | usage() 8 | { 9 | echo "Usage: $0 " 10 | echo "Compares tcpreassembly against tcpflow" 11 | echo "" 12 | echo "$@" 13 | exit 1 14 | } 15 | 16 | debug() { 17 | return # comment me for debug 18 | echo "$@" 19 | } 20 | 21 | die() 22 | { 23 | ( 24 | echo "$@" 25 | echo 26 | ) >&2 27 | exit 1 28 | } 29 | 30 | rename() 31 | { 32 | local path="$1" 33 | local filter="$2" 34 | find "$path" -type f -name "$filter" -print0 | 35 | while IFS= read -r -d $'\0' f; do 36 | local sha256="$(sha256sum "$f" | cut -d ' ' -f 1)" 37 | local target="$(dirname $f)/../sha256/$sha256" 38 | debug "$target → $f" 39 | mkdir -p "$(dirname "$target")" || return 1 40 | if [ ! -f "$target" ]; then 41 | ln -sr "$f" "$target" || return 1 42 | fi 43 | done 44 | return $? 45 | } 46 | 47 | main() 48 | { 49 | local src="$1" 50 | local out="$2" 51 | 52 | # TODO: make options 53 | local extra="" 54 | extra="$extra -debug" 55 | extra="$extra -cpuprofile "$out/gopacket/cpu.prof"" 56 | extra="$extra -memprofile "$out/gopacket/mem.prof"" 57 | 58 | [ ! -f "$src" ] && usage "Missing pcap" 59 | [ ! -d "$out" ] && ( mkdir "$out" || die "Failed to create $out" ) 60 | 61 | mkdir -p "$out/gopacket/all" || die "Failed to create $out/gopacket/all" 62 | mkdir -p "$out/tcpflow/all" || die "Faield to create $out/tcpflow/all" 63 | 64 | echo " * Running go reassembly" 65 | time ./reassemblydump -r "$src" $debug -output "$out/gopacket/all" $extra -writeincomplete -ignorefsmerr -nooptcheck -allowmissinginit port 80 &> "$out/gopacket.txt" || die "Failed to run reassmbly. Check $out/gopacket.txt" 66 | echo " * Running tcpflow" 67 | time tcpflow -e http -r "$src" -o "$out/tcpflow/all" port 80 &> "$out/tcpflow.txt" || die "Failed to run tcpflow. Check $out/tcpflow.txt" 68 | 69 | echo " * Creating sha256sum symlinks for gopacket" 70 | rename "$out/gopacket/all" '*' || die "Failed to rename in $out/gopacket" 71 | echo " * Creating sha256sum symlinks for tcpflow" 72 | rename "$out/tcpflow/all" '*HTTPBODY*' || die "Failed to rename in $out/tcpflow" 73 | 74 | # Remove identical files 75 | echo " * Finding identical files" 76 | local nb=0 77 | mkdir -p "$out/gopacket/sha256-equal" 78 | mkdir -p "$out/tcpflow/sha256-equal" 79 | for f in "$out/gopacket/sha256/"*; do 80 | local f="$(basename "$f")" 81 | [ -f "$out/tcpflow/sha256/$f" ] && { 82 | debug " $f" 83 | mv "$out/gopacket/sha256/$f" "$out/gopacket/sha256-equal" 84 | mv "$out/tcpflow/sha256/$f" "$out/tcpflow/sha256-equal" 85 | nb=$((nb+1)) 86 | } 87 | done 88 | echo " → found $nb files" 89 | 90 | echo " * Diffing {gopacket,tcpflow}/sha256" 91 | local rc=0 92 | for p in "gopacket" "tcpflow"; do 93 | local nb=$(ls -1 "$out/$p/sha256/" | wc -l) 94 | if [ $nb -ne 0 ]; then 95 | rc=$((rc+1)) 96 | echo " → $nb files in $out/$p/sha256" 97 | fi 98 | done 99 | return $rc 100 | } 101 | 102 | main "$@" 103 | exit $? 104 | -------------------------------------------------------------------------------- /examples/snoopread/main.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The GoPacket Authors. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | // snoopread is a example for read a snoop file using 8 | // gopacket and its subpackages and output the decoded data with a package count 9 | package main 10 | 11 | import ( 12 | "fmt" 13 | "log" 14 | "os" 15 | 16 | "github.com/google/gopacket" 17 | "github.com/google/gopacket/pcapgo" 18 | ) 19 | 20 | func main() { 21 | //download snoop from https://wiki.wireshark.org/SampleCaptures 22 | f, err := os.Open("example.snoop") 23 | if err != nil { 24 | log.Fatal(err) 25 | return 26 | } 27 | defer f.Close() 28 | handle, err := pcapgo.NewSnoopReader(f) 29 | if err != nil { 30 | log.Fatal(err) 31 | return 32 | } 33 | 34 | lt, err := handle.LinkType() 35 | if err != nil { 36 | log.Fatal(err) 37 | return 38 | } 39 | packetSource := gopacket.NewPacketSource(handle, lt) 40 | 41 | cnt := 0 42 | for packet := range packetSource.Packets() { 43 | fmt.Println(packet) 44 | cnt++ 45 | } 46 | fmt.Printf("Packet count: %d\n", cnt) 47 | } 48 | -------------------------------------------------------------------------------- /examples/util/util.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | // Package util provides shared utilities for all gopacket examples. 8 | package util 9 | 10 | import ( 11 | "flag" 12 | "log" 13 | "os" 14 | "runtime/pprof" 15 | ) 16 | 17 | var cpuprofile = flag.String("cpuprofile", "", "Where to write CPU profile") 18 | 19 | // Run starts up stuff at the beginning of a main function, and returns a 20 | // function to defer until the function completes. It should be used like this: 21 | // 22 | // func main() { 23 | // defer util.Run()() 24 | // ... stuff ... 25 | // } 26 | func Run() func() { 27 | flag.Parse() 28 | if *cpuprofile != "" { 29 | f, err := os.Create(*cpuprofile) 30 | if err != nil { 31 | log.Fatalf("could not open cpu profile file %q", *cpuprofile) 32 | } 33 | pprof.StartCPUProfile(f) 34 | return func() { 35 | pprof.StopCPUProfile() 36 | f.Close() 37 | } 38 | } 39 | return func() {} 40 | } 41 | -------------------------------------------------------------------------------- /gen.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The GoPacket Authors. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | // +build ignore 8 | 9 | // This file generates LayersDecoder function for DecodingLayerContainer 10 | // go run gen.go | gofmt > layers_decoder.go 11 | package main 12 | 13 | import ( 14 | "fmt" 15 | "os" 16 | "time" 17 | ) 18 | 19 | const headerFmt = `// Copyright 2019 The GoPacket Authors. All rights reserved. 20 | 21 | package gopacket 22 | 23 | // Created by gen.go, don't edit manually 24 | // Generated at %s 25 | 26 | // LayersDecoder returns DecodingLayerFunc for specified 27 | // DecodingLayerContainer, LayerType value to start decoding with and 28 | // some DecodeFeedback. 29 | func LayersDecoder(dl DecodingLayerContainer, first LayerType, df DecodeFeedback) DecodingLayerFunc { 30 | firstDec, ok := dl.Decoder(first) 31 | if !ok { 32 | return func([]byte, *[]LayerType) (LayerType, error) { 33 | return first, nil 34 | } 35 | } 36 | ` 37 | 38 | var funcBody = `return func(data []byte, decoded *[]LayerType) (LayerType, error) { 39 | *decoded = (*decoded)[:0] // Truncated decoded layers. 40 | typ := first 41 | decoder := firstDec 42 | for { 43 | if err := decoder.DecodeFromBytes(data, df); err != nil { 44 | return LayerTypeZero, err 45 | } 46 | *decoded = append(*decoded, typ) 47 | typ = decoder.NextLayerType() 48 | if data = decoder.LayerPayload(); len(data) == 0 { 49 | break 50 | } 51 | if decoder, ok = dlc.Decoder(typ); !ok { 52 | return typ, nil 53 | } 54 | } 55 | return LayerTypeZero, nil 56 | }` 57 | 58 | func main() { 59 | fmt.Fprintf(os.Stderr, "Writing results to stdout\n") 60 | types := []string{ 61 | "DecodingLayerSparse", 62 | "DecodingLayerArray", 63 | "DecodingLayerMap", 64 | } 65 | 66 | fmt.Printf(headerFmt, time.Now()) 67 | for _, t := range types { 68 | fmt.Printf("if dlc, ok := dl.(%s); ok {", t) 69 | fmt.Println(funcBody) 70 | fmt.Println("}") 71 | } 72 | fmt.Println("dlc := dl") 73 | fmt.Println(funcBody) 74 | fmt.Println("}") 75 | } 76 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/google/gopacket 2 | 3 | go 1.12 4 | 5 | require ( 6 | github.com/vishvananda/netlink v1.1.0 7 | github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f 8 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859 9 | golang.org/x/sys v0.0.0-20200217220822-9197077df867 10 | ) 11 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0= 2 | github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= 3 | github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= 4 | github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f h1:p4VB7kIXpOQvVn1ZaTIVp+3vuYAXFe3OJEvjbUYJLaA= 5 | github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= 6 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 7 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI= 8 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 9 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 10 | golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 11 | golang.org/x/sys v0.0.0-20200217220822-9197077df867 h1:JoRuNIf+rpHl+VhScRQQvzbHed86tKkqwPMV34T8myw= 12 | golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 13 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 14 | -------------------------------------------------------------------------------- /layerclass.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | package gopacket 8 | 9 | // LayerClass is a set of LayerTypes, used for grabbing one of a number of 10 | // different types from a packet. 11 | type LayerClass interface { 12 | // Contains returns true if the given layer type should be considered part 13 | // of this layer class. 14 | Contains(LayerType) bool 15 | // LayerTypes returns the set of all layer types in this layer class. 16 | // Note that this may not be a fast operation on all LayerClass 17 | // implementations. 18 | LayerTypes() []LayerType 19 | } 20 | 21 | // Contains implements LayerClass. 22 | func (l LayerType) Contains(a LayerType) bool { 23 | return l == a 24 | } 25 | 26 | // LayerTypes implements LayerClass. 27 | func (l LayerType) LayerTypes() []LayerType { 28 | return []LayerType{l} 29 | } 30 | 31 | // LayerClassSlice implements a LayerClass with a slice. 32 | type LayerClassSlice []bool 33 | 34 | // Contains returns true if the given layer type should be considered part 35 | // of this layer class. 36 | func (s LayerClassSlice) Contains(t LayerType) bool { 37 | return int(t) < len(s) && s[t] 38 | } 39 | 40 | // LayerTypes returns all layer types in this LayerClassSlice. 41 | // Because of LayerClassSlice's implementation, this could be quite slow. 42 | func (s LayerClassSlice) LayerTypes() (all []LayerType) { 43 | for i := 0; i < len(s); i++ { 44 | if s[i] { 45 | all = append(all, LayerType(i)) 46 | } 47 | } 48 | return 49 | } 50 | 51 | // NewLayerClassSlice creates a new LayerClassSlice by creating a slice of 52 | // size max(types) and setting slice[t] to true for each type t. Note, if 53 | // you implement your own LayerType and give it a high value, this WILL create 54 | // a very large slice. 55 | func NewLayerClassSlice(types []LayerType) LayerClassSlice { 56 | var max LayerType 57 | for _, typ := range types { 58 | if typ > max { 59 | max = typ 60 | } 61 | } 62 | t := make([]bool, int(max+1)) 63 | for _, typ := range types { 64 | t[typ] = true 65 | } 66 | return t 67 | } 68 | 69 | // LayerClassMap implements a LayerClass with a map. 70 | type LayerClassMap map[LayerType]bool 71 | 72 | // Contains returns true if the given layer type should be considered part 73 | // of this layer class. 74 | func (m LayerClassMap) Contains(t LayerType) bool { 75 | return m[t] 76 | } 77 | 78 | // LayerTypes returns all layer types in this LayerClassMap. 79 | func (m LayerClassMap) LayerTypes() (all []LayerType) { 80 | for t := range m { 81 | all = append(all, t) 82 | } 83 | return 84 | } 85 | 86 | // NewLayerClassMap creates a LayerClassMap and sets map[t] to true for each 87 | // type in types. 88 | func NewLayerClassMap(types []LayerType) LayerClassMap { 89 | m := LayerClassMap{} 90 | for _, typ := range types { 91 | m[typ] = true 92 | } 93 | return m 94 | } 95 | 96 | // NewLayerClass creates a LayerClass, attempting to be smart about which type 97 | // it creates based on which types are passed in. 98 | func NewLayerClass(types []LayerType) LayerClass { 99 | for _, typ := range types { 100 | if typ > maxLayerType { 101 | // NewLayerClassSlice could create a very large object, so instead create 102 | // a map. 103 | return NewLayerClassMap(types) 104 | } 105 | } 106 | return NewLayerClassSlice(types) 107 | } 108 | -------------------------------------------------------------------------------- /layers/.lint_blacklist: -------------------------------------------------------------------------------- 1 | dot11.go 2 | eap.go 3 | endpoints.go 4 | enums_generated.go 5 | enums.go 6 | ethernet.go 7 | geneve.go 8 | icmp4.go 9 | icmp6.go 10 | igmp.go 11 | ip4.go 12 | ip6.go 13 | layertypes.go 14 | linux_sll.go 15 | llc.go 16 | lldp.go 17 | mpls.go 18 | ndp.go 19 | ntp.go 20 | ospf.go 21 | pflog.go 22 | pppoe.go 23 | prism.go 24 | radiotap.go 25 | rudp.go 26 | sctp.go 27 | sflow.go 28 | tcp.go 29 | tcpip.go 30 | tls.go 31 | tls_alert.go 32 | tls_appdata.go 33 | tls_cipherspec.go 34 | tls_hanshake.go 35 | tls_test.go 36 | udp.go 37 | udplite.go 38 | usb.go 39 | vrrp.go 40 | -------------------------------------------------------------------------------- /layers/ague_var0.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | package layers 8 | 9 | import ( 10 | "errors" 11 | 12 | "github.com/google/gopacket" 13 | ) 14 | 15 | // AGUEVar0 represents a packet encoded with Generic UDP Encapsulation. 16 | // It should sit "under" a UDP layer with dest port 666. 17 | // 18 | // For more information about the meaning of the fields, see 19 | // https://tools.ietf.org/html/draft-ietf-intarea-gue-04#section-3.1 20 | type AGUEVar0 struct { 21 | Version uint8 22 | C bool 23 | Protocol IPProtocol 24 | Flags uint16 25 | Extensions []byte 26 | Data []byte 27 | } 28 | 29 | // LayerType returns this pseudo-header's type as defined in layertypes.go 30 | func (l AGUEVar0) LayerType() gopacket.LayerType { 31 | return LayerTypeAGUEVar0 32 | } 33 | 34 | // LayerContents returns a byte array containing our serialized header. 35 | func (l AGUEVar0) LayerContents() []byte { 36 | b := make([]byte, 4, 4+len(l.Extensions)) 37 | hlen := uint8(len(l.Extensions)) 38 | b[0] = l.Version<<6 | hlen 39 | if l.C { 40 | b[0] |= 0x20 41 | } 42 | b[0] |= hlen 43 | b[1] = byte(l.Protocol) 44 | b[2] = byte(l.Flags >> 8) 45 | b[3] = byte(l.Flags & 0xff) 46 | b = append(b, l.Extensions...) 47 | return b 48 | } 49 | 50 | // LayerPayload returns an IPv4 or IPv6 packet in serialized form. 51 | func (l AGUEVar0) LayerPayload() []byte { 52 | return l.Data 53 | } 54 | 55 | // SerializeTo writes our header into SerializeBuffer. 56 | func (l AGUEVar0) SerializeTo(buf gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error { 57 | b := l.LayerContents() 58 | writeTo, err := buf.PrependBytes(len(b)) 59 | if err != nil { 60 | return err 61 | } 62 | copy(writeTo, b) 63 | return nil 64 | } 65 | 66 | // CanDecode returns the type of layer we can decode. 67 | func (l AGUEVar0) CanDecode() gopacket.LayerClass { 68 | return LayerTypeAGUEVar0 69 | } 70 | 71 | // DecodeFromBytes extracts our header data from a serialized packet. 72 | func (l *AGUEVar0) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error { 73 | l.Version = data[0] >> 6 74 | l.C = data[0]&0x20 != 0 75 | l.Protocol = IPProtocol(data[1]) 76 | l.Flags = (uint16(data[2]) << 8) | uint16(data[3]) 77 | hlen := data[0] & 0x1f 78 | l.Extensions = data[4 : 4+hlen] 79 | l.Data = data[4+hlen:] 80 | return nil 81 | } 82 | 83 | // NextLayerType returns the next layer type, e.g. LayerTypeIPv4 84 | func (l AGUEVar0) NextLayerType() gopacket.LayerType { 85 | return l.Protocol.LayerType() 86 | } 87 | 88 | // decodeAGUE decodes AGUEVar0 or AGUEVar1, depending on the first data byte. 89 | // If AGUEVar1, it refers the packet to AGUEVar1 for decoding. 90 | // Else it adds AGUEVar0 layer info to the packet object, recursively decodes 91 | // remaining layers, and returns the next-layer type (IPv4 or IPv6). 92 | func decodeAGUE(data []byte, p gopacket.PacketBuilder) error { 93 | if len(data) == 0 { 94 | return errors.New("decodeAGUE() failed, no data") 95 | } 96 | if data[0]>>6 == 1 { 97 | return decodeAGUEVar1(data, p) 98 | } 99 | l := AGUEVar0{} 100 | if err := l.DecodeFromBytes(data, gopacket.NilDecodeFeedback); err != nil { 101 | return err 102 | } 103 | p.AddLayer(l) 104 | return p.NextDecoder(l.NextLayerType()) 105 | } 106 | -------------------------------------------------------------------------------- /layers/ague_var0_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | package layers 8 | 9 | import ( 10 | "encoding/hex" 11 | "net" 12 | "testing" 13 | 14 | "github.com/google/gopacket" 15 | ) 16 | 17 | func TestGueDecoding(t *testing.T) { 18 | // This is a packet generated by the Linux kernel GUE implementation, captured 19 | // by pcap. It includes: 20 | // - Ethernet 21 | // - IPv4 22 | // - UDP 23 | // - AGueVar0 (port 666) 24 | // - IPv4 25 | // - ICMP (ping) 26 | // TODO: build a test packet using port 666 (0x029a) 27 | ph := `02427b2522f502420ae0d90608004500007451ea4000ff119d050ae0d9060afa9da88c0f029a00608cfa000400004500005459f240004001e2cd0ae0d9060afd0f0608000a7e005f000cea811f59000000005daa080000000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021222324252627` 28 | pr, err := hex.DecodeString(ph) 29 | if err != nil { 30 | t.Errorf("Error decoding hex packet: %v", err) 31 | } 32 | 33 | p := gopacket.NewPacket(pr, LayerTypeEthernet, gopacket.Default) 34 | // require.Nil(t, p.ErrorLayer()) 35 | if p.ErrorLayer() != nil { 36 | t.Errorf("AGUEVar0 layer is nil") 37 | } 38 | t.Logf("%v", p) 39 | 40 | gue := p.Layer(LayerTypeAGUEVar0).(AGUEVar0) 41 | // require.NotNil(t, gue) 42 | if uint8(0) != gue.Version { 43 | t.Errorf("gue.Version is not 0") 44 | } 45 | } 46 | 47 | var testIPv4OverAGUEVar0 = []gopacket.SerializableLayer{ 48 | &Ethernet{ 49 | SrcMAC: net.HardwareAddr{142, 122, 18, 195, 169, 113}, 50 | DstMAC: net.HardwareAddr{58, 86, 107, 105, 89, 94}, 51 | EthernetType: EthernetTypeIPv4, 52 | }, 53 | &IPv4{ 54 | Version: 4, 55 | SrcIP: net.IP{192, 168, 1, 1}, 56 | DstIP: net.IP{192, 168, 1, 2}, 57 | Protocol: IPProtocolUDP, 58 | Flags: IPv4DontFragment, 59 | TTL: 64, 60 | Id: 33852, 61 | IHL: 5, 62 | }, 63 | &UDP{ 64 | SrcPort: 8, 65 | DstPort: 666, 66 | }, 67 | &AGUEVar0{ 68 | Protocol: IPProtocolIPv4, 69 | }, 70 | &IPv4{ 71 | Version: 4, 72 | SrcIP: net.IP{172, 16, 1, 1}, 73 | DstIP: net.IP{172, 16, 2, 1}, 74 | Protocol: IPProtocolICMPv4, 75 | Flags: IPv4DontFragment, 76 | TTL: 64, 77 | IHL: 5, 78 | Id: 1160, 79 | }, 80 | &ICMPv4{ 81 | TypeCode: CreateICMPv4TypeCode(ICMPv4TypeEchoRequest, 0), 82 | Id: 4724, 83 | Seq: 1, 84 | }, 85 | gopacket.Payload{ 86 | 0xc8, 0x92, 0xa3, 0x54, 0x00, 0x00, 0x00, 0x00, 0x38, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 87 | 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 88 | 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 89 | 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 90 | }, 91 | } 92 | 93 | func TestIPv4OverAGUEVar0Encode(t *testing.T) { 94 | b := gopacket.NewSerializeBuffer() 95 | opts := gopacket.SerializeOptions{ 96 | ComputeChecksums: false, // if desired, see gre_test:setNetworkLayer() 97 | FixLengths: true, 98 | } 99 | if err := gopacket.SerializeLayers(b, opts, testIPv4OverAGUEVar0...); err != nil { 100 | t.Errorf("Unable to serialize: %v", err) 101 | } 102 | p := gopacket.NewPacket(b.Bytes(), LinkTypeEthernet, gopacket.Default) 103 | if p.ErrorLayer() != nil { 104 | t.Error("Failed to decode packet:", p.ErrorLayer().Error()) 105 | } 106 | checkLayers(p, []gopacket.LayerType{LayerTypeEthernet, LayerTypeIPv4, LayerTypeUDP, LayerTypeAGUEVar0, LayerTypeIPv4, LayerTypeICMPv4, gopacket.LayerTypePayload}, t) 107 | 108 | // We don't have a corresponding sample packet capture, but if we did, the verify would look like this: 109 | // if got, want := b.Bytes(), testPacketAGUEVar0``; !reflect.DeepEqual(want, got) { 110 | // t.Errorf("Encoding mismatch, \nwant: %v\ngot %v\n", want, got) 111 | // } 112 | } 113 | -------------------------------------------------------------------------------- /layers/ague_var1.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | package layers 8 | 9 | import ( 10 | "errors" 11 | 12 | "github.com/google/gopacket" 13 | ) 14 | 15 | // An AGUEVar1 header is mostly imaginary, having a length of 0 in its serialized form. 16 | // IPProtocol value is either IPProtocolIPv4 or IPProtocolIPv6, depending on the encapped 17 | // IP header contained in Data, which must begin with the high-order bits 01. 18 | type AGUEVar1 struct { 19 | Protocol IPProtocol 20 | Data []byte 21 | } 22 | 23 | // LayerType returns this pseudo-header's type as defined in layertypes.go 24 | func (l AGUEVar1) LayerType() gopacket.LayerType { 25 | return LayerTypeAGUEVar1 26 | } 27 | 28 | // LayerContents returns an empty byte array, because this header has no length. 29 | func (l AGUEVar1) LayerContents() []byte { 30 | b := make([]byte, 0, 0) 31 | return b 32 | } 33 | 34 | // LayerPayload returns an IPv4 or IPv6 packet in serialized form. 35 | func (l AGUEVar1) LayerPayload() []byte { 36 | return l.Data 37 | } 38 | 39 | // SerializeTo writes our imaginary header into SerializeBuffer. This amount to a noop. 40 | func (l AGUEVar1) SerializeTo(buf gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error { 41 | return nil 42 | } 43 | 44 | // CanDecode returns the type of layer we can decode. 45 | func (l AGUEVar1) CanDecode() gopacket.LayerClass { 46 | return LayerTypeAGUEVar1 47 | } 48 | 49 | // DecodeFromBytes extracts our pseudo-header data from a serialized packet. 50 | // There's only one thing, the next header type, which is either IPv4 or IPv6. 51 | // They are crafted to keep their own header type in the first nibble. 52 | // So we peek into the IP header to get the next-layer protocol type. 53 | func (l *AGUEVar1) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error { 54 | if len(data) < 1 { 55 | return errors.New("DecodeFromBytes() failed, no data") 56 | } 57 | ipVersion := data[0] >> 4 58 | if ipVersion == 4 { 59 | l.Protocol = IPProtocolIPv4 60 | } else if ipVersion == 6 { 61 | l.Protocol = IPProtocolIPv6 62 | } else { 63 | return errors.New("DecodeFromBytes() failed, unknown IP version") 64 | } 65 | l.Data = data 66 | return nil 67 | } 68 | 69 | // NextLayerType returns the next layer type, e.g. LayerTypeIPv4 70 | func (l AGUEVar1) NextLayerType() gopacket.LayerType { 71 | return l.Protocol.LayerType() 72 | } 73 | 74 | // decodeAGUEVar1 decodes packet data to figure out the next-layer IP type, 75 | // then adds AGUEVar1 layer info to the packet object, recursively decodes 76 | // remaining layers, and returns the next-layer type. 77 | func decodeAGUEVar1(data []byte, p gopacket.PacketBuilder) error { 78 | l := AGUEVar1{} 79 | if err := l.DecodeFromBytes(data, gopacket.NilDecodeFeedback); err != nil { 80 | return err 81 | } 82 | p.AddLayer(l) 83 | return p.NextDecoder(l.NextLayerType()) 84 | } 85 | -------------------------------------------------------------------------------- /layers/asf_presencepong_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The GoPacket Authors. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license that can be found 4 | // in the LICENSE file in the root of the source tree. 5 | 6 | package layers 7 | 8 | import ( 9 | "bytes" 10 | "encoding/hex" 11 | "testing" 12 | 13 | "github.com/google/gopacket" 14 | ) 15 | 16 | func TestASFPresencePongDecodeFromBytes(t *testing.T) { 17 | b, err := hex.DecodeString("000011be000000008100000000000000") 18 | if err != nil { 19 | t.Fatalf("Failed to decode ASF Presence Pong message") 20 | } 21 | 22 | pp := &ASFPresencePong{} 23 | if err := pp.DecodeFromBytes(b, gopacket.NilDecodeFeedback); err != nil { 24 | t.Fatalf("Unexpected error: %v", err) 25 | } 26 | if !bytes.Equal(pp.BaseLayer.Payload, []byte{}) { 27 | t.Errorf("payload is %v, want %v", pp.BaseLayer.Payload, b) 28 | } 29 | if !bytes.Equal(pp.BaseLayer.Contents, b) { 30 | t.Errorf("contents is %v, want %v", pp.BaseLayer.Contents, b) 31 | } 32 | if pp.Enterprise != ASFRMCPEnterprise { 33 | t.Errorf("want enterprise %v, got %v", ASFRMCPEnterprise, pp.Enterprise) 34 | } 35 | if !bytes.Equal(pp.OEM[:], make([]byte, 4)) { 36 | t.Errorf("want null OEM, got %v", pp.OEM[:]) 37 | } 38 | if !pp.IPMI { 39 | t.Errorf("want IPMI, got false") 40 | } 41 | if !pp.ASFv1 { 42 | t.Errorf("want ASFv1, got false") 43 | } 44 | if pp.SecurityExtensions { 45 | t.Errorf("do not want security extensions, got true") 46 | } 47 | if pp.DASH { 48 | t.Errorf("do not want DASH, got true") 49 | } 50 | } 51 | 52 | func TestASFPresencePongSupportsDCMI(t *testing.T) { 53 | table := []struct { 54 | layer *ASFPresencePong 55 | want bool 56 | }{ 57 | { 58 | &ASFPresencePong{ 59 | Enterprise: ASFRMCPEnterprise, 60 | IPMI: true, 61 | ASFv1: true, 62 | }, 63 | false, 64 | }, 65 | { 66 | &ASFPresencePong{ 67 | Enterprise: ASFDCMIEnterprise, 68 | IPMI: false, 69 | ASFv1: true, 70 | }, 71 | false, 72 | }, 73 | { 74 | &ASFPresencePong{ 75 | Enterprise: ASFDCMIEnterprise, 76 | IPMI: true, 77 | ASFv1: false, 78 | }, 79 | false, 80 | }, 81 | { 82 | &ASFPresencePong{ 83 | Enterprise: ASFDCMIEnterprise, 84 | IPMI: true, 85 | ASFv1: true, 86 | }, 87 | true, 88 | }, 89 | } 90 | for _, test := range table { 91 | got := test.layer.SupportsDCMI() 92 | if got != test.want { 93 | t.Errorf("%v SupportsDCMI() = %v, want %v", test.layer, got, test.want) 94 | } 95 | } 96 | } 97 | 98 | func serializeASFPresencePong(pp *ASFPresencePong) ([]byte, error) { 99 | sb := gopacket.NewSerializeBuffer() 100 | err := pp.SerializeTo(sb, gopacket.SerializeOptions{}) 101 | return sb.Bytes(), err 102 | } 103 | 104 | func TestASFPresencePongSerializeTo(t *testing.T) { 105 | table := []struct { 106 | layer *ASFPresencePong 107 | want []byte 108 | }{ 109 | { 110 | &ASFPresencePong{ 111 | Enterprise: ASFRMCPEnterprise, 112 | IPMI: true, 113 | ASFv1: true, 114 | }, 115 | []byte{0, 0, 0x11, 0xbe, 0, 0, 0, 0, 0x81, 0, 0, 0, 0, 0, 0, 0}, 116 | }, 117 | { 118 | &ASFPresencePong{ 119 | Enterprise: 1234, 120 | OEM: [4]byte{1, 2, 3, 4}, 121 | ASFv1: true, 122 | SecurityExtensions: true, 123 | DASH: true, 124 | }, 125 | []byte{0, 0, 0x4, 0xd2, 1, 2, 3, 4, 0x01, 0xa0, 0, 0, 0, 0, 0, 0}, 126 | }, 127 | } 128 | for _, test := range table { 129 | b, err := serializeASFPresencePong(test.layer) 130 | switch { 131 | case err != nil && test.want != nil: 132 | t.Errorf("serialize %v failed with %v, wanted %v", test.layer, 133 | err, test.want) 134 | case err == nil && !bytes.Equal(b, test.want): 135 | t.Errorf("serialize %v = %v, want %v", test.layer, b, test.want) 136 | } 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /layers/asf_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The GoPacket Authors. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license that can be found 4 | // in the LICENSE file in the root of the source tree. 5 | 6 | package layers 7 | 8 | import ( 9 | "bytes" 10 | "encoding/hex" 11 | "testing" 12 | 13 | "github.com/google/gopacket" 14 | ) 15 | 16 | func TestASFDecodeFromBytes(t *testing.T) { 17 | b, err := hex.DecodeString("000011be4000001000000000000000") 18 | if err != nil { 19 | t.Fatalf("Failed to decode ASF message") 20 | } 21 | 22 | asf := &ASF{} 23 | if err := asf.DecodeFromBytes(b, gopacket.NilDecodeFeedback); err != nil { 24 | t.Fatalf("Unexpected error: %v", err) 25 | } 26 | if !bytes.Equal(asf.BaseLayer.Contents, b[:8]) { 27 | t.Errorf("contents is %v, want %v", asf.BaseLayer.Contents, b[:8]) 28 | } 29 | if !bytes.Equal(asf.BaseLayer.Payload, b[8:]) { 30 | t.Errorf("payload is %v, want %v", asf.BaseLayer.Payload, b[8:]) 31 | } 32 | if asf.Enterprise != ASFRMCPEnterprise { 33 | t.Errorf("enterprise is %v, want %v", asf.Enterprise, ASFRMCPEnterprise) 34 | } 35 | if asf.Type != ASFDataIdentifierPresencePong.Type { 36 | t.Errorf("type is %v, want %v", asf.Type, ASFDataIdentifierPresencePong) 37 | } 38 | if asf.Tag != 0 { 39 | t.Errorf("tag is %v, want 0", asf.Tag) 40 | } 41 | if asf.Length != 16 { 42 | t.Errorf("length is %v, want 16", asf.Length) 43 | } 44 | } 45 | 46 | func serializeASF(asf *ASF) ([]byte, error) { 47 | sb := gopacket.NewSerializeBuffer() 48 | err := asf.SerializeTo(sb, gopacket.SerializeOptions{ 49 | FixLengths: true, 50 | }) 51 | return sb.Bytes(), err 52 | } 53 | 54 | func TestASFSerializeTo(t *testing.T) { 55 | table := []struct { 56 | layer *ASF 57 | want []byte 58 | }{ 59 | { 60 | &ASF{ 61 | ASFDataIdentifier: ASFDataIdentifierPresencePing, 62 | }, 63 | []byte{0, 0, 0x11, 0xbe, 0x80, 0, 0, 0}, 64 | }, 65 | { 66 | &ASF{ 67 | ASFDataIdentifier: ASFDataIdentifierPresencePong, 68 | // ensures length is being overridden - should be encoded to 0 69 | // as there is no payload 70 | Length: 1, 71 | }, 72 | []byte{0, 0, 0x11, 0xbe, 0x40, 0, 0, 0}, 73 | }, 74 | } 75 | for _, test := range table { 76 | b, err := serializeASF(test.layer) 77 | switch { 78 | case err != nil && test.want != nil: 79 | t.Errorf("serialize %v failed with %v, wanted %v", test.layer, 80 | err, test.want) 81 | case err == nil && !bytes.Equal(b, test.want): 82 | t.Errorf("serialize %v = %v, want %v", test.layer, b, test.want) 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /layers/base.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | package layers 8 | 9 | import ( 10 | "github.com/google/gopacket" 11 | ) 12 | 13 | // BaseLayer is a convenience struct which implements the LayerData and 14 | // LayerPayload functions of the Layer interface. 15 | type BaseLayer struct { 16 | // Contents is the set of bytes that make up this layer. IE: for an 17 | // Ethernet packet, this would be the set of bytes making up the 18 | // Ethernet frame. 19 | Contents []byte 20 | // Payload is the set of bytes contained by (but not part of) this 21 | // Layer. Again, to take Ethernet as an example, this would be the 22 | // set of bytes encapsulated by the Ethernet protocol. 23 | Payload []byte 24 | } 25 | 26 | // LayerContents returns the bytes of the packet layer. 27 | func (b *BaseLayer) LayerContents() []byte { return b.Contents } 28 | 29 | // LayerPayload returns the bytes contained within the packet layer. 30 | func (b *BaseLayer) LayerPayload() []byte { return b.Payload } 31 | 32 | type layerDecodingLayer interface { 33 | gopacket.Layer 34 | DecodeFromBytes([]byte, gopacket.DecodeFeedback) error 35 | NextLayerType() gopacket.LayerType 36 | } 37 | 38 | func decodingLayerDecoder(d layerDecodingLayer, data []byte, p gopacket.PacketBuilder) error { 39 | err := d.DecodeFromBytes(data, p) 40 | if err != nil { 41 | return err 42 | } 43 | p.AddLayer(d) 44 | next := d.NextLayerType() 45 | if next == gopacket.LayerTypeZero { 46 | return nil 47 | } 48 | return p.NextDecoder(next) 49 | } 50 | 51 | // hacky way to zero out memory... there must be a better way? 52 | var lotsOfZeros [1024]byte 53 | -------------------------------------------------------------------------------- /layers/base_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012, Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | // This file contains some test helper functions. 8 | 9 | package layers 10 | 11 | import ( 12 | "testing" 13 | 14 | "github.com/google/gopacket" 15 | ) 16 | 17 | func checkLayers(p gopacket.Packet, want []gopacket.LayerType, t *testing.T) { 18 | layers := p.Layers() 19 | t.Log("Checking packet layers, want", want) 20 | for _, l := range layers { 21 | t.Logf(" Got layer %v, %d bytes, payload of %d bytes", l.LayerType(), 22 | len(l.LayerContents()), len(l.LayerPayload())) 23 | } 24 | t.Log(p) 25 | if len(layers) < len(want) { 26 | t.Errorf(" Number of layers mismatch: got %d want %d", len(layers), 27 | len(want)) 28 | return 29 | } 30 | for i, l := range want { 31 | if l == gopacket.LayerTypePayload { 32 | // done matching layers 33 | return 34 | } 35 | 36 | if layers[i].LayerType() != l { 37 | t.Errorf(" Layer %d mismatch: got %v want %v", i, 38 | layers[i].LayerType(), l) 39 | } 40 | } 41 | } 42 | 43 | // Checks that when a serialized version of p is decoded, p and the serialized version of p are the same. 44 | // Does not work for packets where the order of options can change, like icmpv6 router advertisements, dhcpv6, etc. 45 | func checkSerialization(p gopacket.Packet, t *testing.T) { 46 | buf := gopacket.NewSerializeBuffer() 47 | opts := gopacket.SerializeOptions{ 48 | ComputeChecksums: false, 49 | FixLengths: false, 50 | } 51 | if err := gopacket.SerializePacket(buf, opts, p); err != nil { 52 | t.Error("Failed to encode packet:", err) 53 | } 54 | 55 | p2 := gopacket.NewPacket(buf.Bytes(), LinkTypeEthernet, gopacket.Default) 56 | if p2.ErrorLayer() != nil { 57 | t.Error("Failed to decode the re-encoded packet:", p2.ErrorLayer().Error()) 58 | } 59 | 60 | if p2.Dump() != p.Dump() { 61 | t.Errorf("The decoded and the re-encoded packet are different!\nDecoded:\n%s\n Re-Encoded:\n%s", p.Dump(), p2.Dump()) 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /layers/bitfield.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 The GoPacket Authors. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license that can be found 4 | // in the LICENSE file in the root of the source tree. 5 | 6 | package layers 7 | 8 | type bitfield [1024]uint64 9 | 10 | // set sets bit i in bitfield b to 1. 11 | func (b *bitfield) set(i uint16) { 12 | b[i>>6] |= (1 << (i & 0x3f)) 13 | } 14 | 15 | // has reports whether bit i is set to 1 in bitfield b. 16 | func (b *bitfield) has(i uint16) bool { 17 | return b[i>>6]&(1<<(i&0x3f)) != 0 18 | } 19 | -------------------------------------------------------------------------------- /layers/bitfield_test.go: -------------------------------------------------------------------------------- 1 | package layers 2 | 3 | import "testing" 4 | 5 | func TestBitfield(t *testing.T) { 6 | var b bitfield 7 | 8 | const uint16Max = ^uint16(0) 9 | 10 | for i := uint16(0); i < uint16Max; i++ { 11 | if b.has(i) { 12 | t.Errorf("b.has(%d) expected false, got true", i) 13 | } 14 | } 15 | 16 | b.set(0) 17 | if !b.has(0) { 18 | t.Error("b.has(0) expected true, got false") 19 | } 20 | 21 | for i := uint16(1); i < uint16Max; i++ { 22 | if b.has(i) { 23 | t.Errorf("b.has(%d) expected false, got true", i) 24 | } 25 | } 26 | } 27 | 28 | func TestBitfieldStressTest(t *testing.T) { 29 | for i := 0; i < 7; i++ { 30 | var b bitfield 31 | for j := i; j < 64*1024; j += 7 { 32 | b.set(uint16(j)) 33 | } 34 | for j := 0; j < 64&1024; j++ { 35 | want := j%7 == i 36 | if got := b.has(uint16(j)); got != want { 37 | t.Errorf("Test %d bit %d: got %v want %v", i, j, got, want) 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /layers/ctp.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | package layers 8 | 9 | import ( 10 | "encoding/binary" 11 | "fmt" 12 | "github.com/google/gopacket" 13 | ) 14 | 15 | // EthernetCTPFunction is the function code used by the EthernetCTP protocol to identify each 16 | // EthernetCTP layer. 17 | type EthernetCTPFunction uint16 18 | 19 | // EthernetCTPFunction values. 20 | const ( 21 | EthernetCTPFunctionReply EthernetCTPFunction = 1 22 | EthernetCTPFunctionForwardData EthernetCTPFunction = 2 23 | ) 24 | 25 | // EthernetCTP implements the EthernetCTP protocol, see http://www.mit.edu/people/jhawk/ctp.html. 26 | // We split EthernetCTP up into the top-level EthernetCTP layer, followed by zero or more 27 | // EthernetCTPForwardData layers, followed by a final EthernetCTPReply layer. 28 | type EthernetCTP struct { 29 | BaseLayer 30 | SkipCount uint16 31 | } 32 | 33 | // LayerType returns gopacket.LayerTypeEthernetCTP. 34 | func (c *EthernetCTP) LayerType() gopacket.LayerType { 35 | return LayerTypeEthernetCTP 36 | } 37 | 38 | // EthernetCTPForwardData is the ForwardData layer inside EthernetCTP. See EthernetCTP's docs for more 39 | // details. 40 | type EthernetCTPForwardData struct { 41 | BaseLayer 42 | Function EthernetCTPFunction 43 | ForwardAddress []byte 44 | } 45 | 46 | // LayerType returns gopacket.LayerTypeEthernetCTPForwardData. 47 | func (c *EthernetCTPForwardData) LayerType() gopacket.LayerType { 48 | return LayerTypeEthernetCTPForwardData 49 | } 50 | 51 | // ForwardEndpoint returns the EthernetCTPForwardData ForwardAddress as an endpoint. 52 | func (c *EthernetCTPForwardData) ForwardEndpoint() gopacket.Endpoint { 53 | return gopacket.NewEndpoint(EndpointMAC, c.ForwardAddress) 54 | } 55 | 56 | // EthernetCTPReply is the Reply layer inside EthernetCTP. See EthernetCTP's docs for more details. 57 | type EthernetCTPReply struct { 58 | BaseLayer 59 | Function EthernetCTPFunction 60 | ReceiptNumber uint16 61 | Data []byte 62 | } 63 | 64 | // LayerType returns gopacket.LayerTypeEthernetCTPReply. 65 | func (c *EthernetCTPReply) LayerType() gopacket.LayerType { 66 | return LayerTypeEthernetCTPReply 67 | } 68 | 69 | // Payload returns the EthernetCTP reply's Data bytes. 70 | func (c *EthernetCTPReply) Payload() []byte { return c.Data } 71 | 72 | func decodeEthernetCTP(data []byte, p gopacket.PacketBuilder) error { 73 | c := &EthernetCTP{ 74 | SkipCount: binary.LittleEndian.Uint16(data[:2]), 75 | BaseLayer: BaseLayer{data[:2], data[2:]}, 76 | } 77 | if c.SkipCount%2 != 0 { 78 | return fmt.Errorf("EthernetCTP skip count is odd: %d", c.SkipCount) 79 | } 80 | p.AddLayer(c) 81 | return p.NextDecoder(gopacket.DecodeFunc(decodeEthernetCTPFromFunctionType)) 82 | } 83 | 84 | // decodeEthernetCTPFromFunctionType reads in the first 2 bytes to determine the EthernetCTP 85 | // layer type to decode next, then decodes based on that. 86 | func decodeEthernetCTPFromFunctionType(data []byte, p gopacket.PacketBuilder) error { 87 | function := EthernetCTPFunction(binary.LittleEndian.Uint16(data[:2])) 88 | switch function { 89 | case EthernetCTPFunctionReply: 90 | reply := &EthernetCTPReply{ 91 | Function: function, 92 | ReceiptNumber: binary.LittleEndian.Uint16(data[2:4]), 93 | Data: data[4:], 94 | BaseLayer: BaseLayer{data, nil}, 95 | } 96 | p.AddLayer(reply) 97 | p.SetApplicationLayer(reply) 98 | return nil 99 | case EthernetCTPFunctionForwardData: 100 | forward := &EthernetCTPForwardData{ 101 | Function: function, 102 | ForwardAddress: data[2:8], 103 | BaseLayer: BaseLayer{data[:8], data[8:]}, 104 | } 105 | p.AddLayer(forward) 106 | return p.NextDecoder(gopacket.DecodeFunc(decodeEthernetCTPFromFunctionType)) 107 | } 108 | return fmt.Errorf("Unknown EthernetCTP function type %v", function) 109 | } 110 | -------------------------------------------------------------------------------- /layers/dhcpv6_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018, Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | package layers 8 | 9 | import ( 10 | "bytes" 11 | "testing" 12 | 13 | "github.com/google/gopacket" 14 | ) 15 | 16 | func TestDHCPv6EncodeRequest(t *testing.T) { 17 | dhcpv6 := &DHCPv6{MsgType: DHCPv6MsgTypeRequest, HopCount: 0, TransactionID: []byte{87, 25, 88}} 18 | 19 | client := &DHCPv6DUID{Type: DHCPv6DUIDTypeLLT, HardwareType: []byte{0, 1}, Time: []byte{28, 56, 38, 45}, LinkLayerAddress: []byte{8, 0, 39, 254, 143, 149}} 20 | dhcpv6.Options = append(dhcpv6.Options, NewDHCPv6Option(DHCPv6OptClientID, client.Encode())) 21 | 22 | server := &DHCPv6DUID{Type: DHCPv6DUIDTypeLLT, HardwareType: []byte{0, 1}, Time: []byte{28, 56, 37, 232}, LinkLayerAddress: []byte{8, 0, 39, 212, 16, 187}} 23 | dhcpv6.Options = append(dhcpv6.Options, NewDHCPv6Option(DHCPv6OptServerID, server.Encode())) 24 | 25 | buf := gopacket.NewSerializeBuffer() 26 | opts := gopacket.SerializeOptions{FixLengths: true} 27 | err := gopacket.SerializeLayers(buf, opts, dhcpv6) 28 | if err != nil { 29 | t.Fatal(err) 30 | } 31 | 32 | p2 := gopacket.NewPacket(buf.Bytes(), LayerTypeDHCPv6, testDecodeOptions) 33 | dhcpv62 := p2.Layer(LayerTypeDHCPv6).(*DHCPv6) 34 | testDHCPv6Equal(t, dhcpv6, dhcpv62) 35 | } 36 | 37 | func TestDHCPv6EncodeReply(t *testing.T) { 38 | dhcpv6 := &DHCPv6{MsgType: DHCPv6MsgTypeReply, HopCount: 0, TransactionID: []byte{87, 25, 88}} 39 | 40 | client := &DHCPv6DUID{Type: DHCPv6DUIDTypeLLT, HardwareType: []byte{0, 1}, Time: []byte{28, 56, 38, 45}, LinkLayerAddress: []byte{8, 0, 39, 254, 143, 149}} 41 | dhcpv6.Options = append(dhcpv6.Options, NewDHCPv6Option(DHCPv6OptClientID, client.Encode())) 42 | 43 | server := &DHCPv6DUID{Type: DHCPv6DUIDTypeLLT, HardwareType: []byte{0, 1}, Time: []byte{28, 56, 37, 232}, LinkLayerAddress: []byte{8, 0, 39, 212, 16, 187}} 44 | dhcpv6.Options = append(dhcpv6.Options, NewDHCPv6Option(DHCPv6OptServerID, server.Encode())) 45 | 46 | buf := gopacket.NewSerializeBuffer() 47 | opts := gopacket.SerializeOptions{FixLengths: true} 48 | err := gopacket.SerializeLayers(buf, opts, dhcpv6) 49 | if err != nil { 50 | t.Fatal(err) 51 | } 52 | 53 | p2 := gopacket.NewPacket(buf.Bytes(), LayerTypeDHCPv6, testDecodeOptions) 54 | dhcpv62 := p2.Layer(LayerTypeDHCPv6).(*DHCPv6) 55 | testDHCPv6Equal(t, dhcpv6, dhcpv62) 56 | } 57 | 58 | func testDHCPv6Equal(t *testing.T, d1, d2 *DHCPv6) { 59 | if d1.MsgType != d2.MsgType { 60 | t.Errorf("expected MsgType=%s, got %s", d1.MsgType, d2.MsgType) 61 | } 62 | if d1.HopCount != d2.HopCount { 63 | t.Errorf("expected HopCount=%d, got %d", d1.HopCount, d2.HopCount) 64 | } 65 | if !d1.LinkAddr.Equal(d2.LinkAddr) { 66 | t.Errorf("expected LinkAddr=%v, got %v", d1.LinkAddr, d2.LinkAddr) 67 | } 68 | if !d1.PeerAddr.Equal(d2.PeerAddr) { 69 | t.Errorf("expected PeerAddr=%v, got %v", d1.PeerAddr, d2.PeerAddr) 70 | } 71 | if !bytes.Equal(d1.TransactionID, d2.TransactionID) { 72 | t.Errorf("expected TransactionID=%v, got %v", d1.TransactionID, d2.TransactionID) 73 | } 74 | if len(d1.Options) != len(d2.Options) { 75 | t.Errorf("expected %d options, got %d", len(d1.Options), len(d2.Options)) 76 | } 77 | 78 | for i, o := range d1.Options { 79 | testDHCPv6OptionEqual(t, i, o, d2.Options[i]) 80 | } 81 | } 82 | 83 | func testDHCPv6OptionEqual(t *testing.T, idx int, d1, d2 DHCPv6Option) { 84 | if d1.Code != d2.Code { 85 | t.Errorf("expection Options[%d].Code = %s, got %s", idx, d1.Code, d2.Code) 86 | } 87 | if d1.Length != d2.Length { 88 | t.Errorf("expection Options[%d].Length = %d, got %d", idx, d1.Length, d2.Length) 89 | } 90 | if !bytes.Equal(d1.Data, d2.Data) { 91 | t.Errorf("expection Options[%d].Data to be = %v, got %v", idx, d1.Data, d2.Data) 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /layers/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | /* 8 | Package layers provides decoding layers for many common protocols. 9 | 10 | The layers package contains decode implementations for a number of different 11 | types of packet layers. Users of gopacket will almost always want to also use 12 | layers to actually decode packet data into useful pieces. To see the set of 13 | protocols that gopacket/layers is currently able to decode, 14 | look at the set of LayerTypes defined in the Variables sections. The 15 | layers package also defines endpoints for many of the common packet layers 16 | that have source/destination addresses associated with them, for example IPv4/6 17 | (IPs) and TCP/UDP (ports). 18 | Finally, layers contains a number of useful enumerations (IPProtocol, 19 | EthernetType, LinkType, PPPType, etc...). Many of these implement the 20 | gopacket.Decoder interface, so they can be passed into gopacket as decoders. 21 | 22 | Most common protocol layers are named using acronyms or other industry-common 23 | names (IPv4, TCP, PPP). Some of the less common ones have their names expanded 24 | (CiscoDiscoveryProtocol). 25 | For certain protocols, sub-parts of the protocol are split out into their own 26 | layers (SCTP, for example). This is done mostly in cases where portions of the 27 | protocol may fulfill the capabilities of interesting layers (SCTPData implements 28 | ApplicationLayer, while base SCTP implements TransportLayer), or possibly 29 | because splitting a protocol into a few layers makes decoding easier. 30 | 31 | This package is meant to be used with its parent, 32 | http://github.com/google/gopacket. 33 | 34 | Port Types 35 | 36 | Instead of using raw uint16 or uint8 values for ports, we use a different port 37 | type for every protocol, for example TCPPort and UDPPort. This allows us to 38 | override string behavior for each port, which we do by setting up port name 39 | maps (TCPPortNames, UDPPortNames, etc...). Well-known ports are annotated with 40 | their protocol names, and their String function displays these names: 41 | 42 | p := TCPPort(80) 43 | fmt.Printf("Number: %d String: %v", p, p) 44 | // Prints: "Number: 80 String: 80(http)" 45 | 46 | Modifying Decode Behavior 47 | 48 | layers links together decoding through its enumerations. For example, after 49 | decoding layer type Ethernet, it uses Ethernet.EthernetType as its next decoder. 50 | All enumerations that act as decoders, like EthernetType, can be modified by 51 | users depending on their preferences. For example, if you have a spiffy new 52 | IPv4 decoder that works way better than the one built into layers, you can do 53 | this: 54 | 55 | var mySpiffyIPv4Decoder gopacket.Decoder = ... 56 | layers.EthernetTypeMetadata[EthernetTypeIPv4].DecodeWith = mySpiffyIPv4Decoder 57 | 58 | This will make all future ethernet packets use your new decoder to decode IPv4 59 | packets, instead of the built-in decoder used by gopacket. 60 | */ 61 | package layers 62 | -------------------------------------------------------------------------------- /layers/dot1q.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google, Inc. All rights reserved. 2 | // Copyright 2009-2011 Andreas Krennmair. All rights reserved. 3 | // 4 | // Use of this source code is governed by a BSD-style license 5 | // that can be found in the LICENSE file in the root of the source 6 | // tree. 7 | 8 | package layers 9 | 10 | import ( 11 | "encoding/binary" 12 | "fmt" 13 | "github.com/google/gopacket" 14 | ) 15 | 16 | // Dot1Q is the packet layer for 802.1Q VLAN headers. 17 | type Dot1Q struct { 18 | BaseLayer 19 | Priority uint8 20 | DropEligible bool 21 | VLANIdentifier uint16 22 | Type EthernetType 23 | } 24 | 25 | // LayerType returns gopacket.LayerTypeDot1Q 26 | func (d *Dot1Q) LayerType() gopacket.LayerType { return LayerTypeDot1Q } 27 | 28 | // DecodeFromBytes decodes the given bytes into this layer. 29 | func (d *Dot1Q) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error { 30 | if len(data) < 4 { 31 | df.SetTruncated() 32 | return fmt.Errorf("802.1Q tag length %d too short", len(data)) 33 | } 34 | d.Priority = (data[0] & 0xE0) >> 5 35 | d.DropEligible = data[0]&0x10 != 0 36 | d.VLANIdentifier = binary.BigEndian.Uint16(data[:2]) & 0x0FFF 37 | d.Type = EthernetType(binary.BigEndian.Uint16(data[2:4])) 38 | d.BaseLayer = BaseLayer{Contents: data[:4], Payload: data[4:]} 39 | return nil 40 | } 41 | 42 | // CanDecode returns the set of layer types that this DecodingLayer can decode. 43 | func (d *Dot1Q) CanDecode() gopacket.LayerClass { 44 | return LayerTypeDot1Q 45 | } 46 | 47 | // NextLayerType returns the layer type contained by this DecodingLayer. 48 | func (d *Dot1Q) NextLayerType() gopacket.LayerType { 49 | return d.Type.LayerType() 50 | } 51 | 52 | func decodeDot1Q(data []byte, p gopacket.PacketBuilder) error { 53 | d := &Dot1Q{} 54 | return decodingLayerDecoder(d, data, p) 55 | } 56 | 57 | // SerializeTo writes the serialized form of this layer into the 58 | // SerializationBuffer, implementing gopacket.SerializableLayer. 59 | // See the docs for gopacket.SerializableLayer for more info. 60 | func (d *Dot1Q) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error { 61 | bytes, err := b.PrependBytes(4) 62 | if err != nil { 63 | return err 64 | } 65 | if d.VLANIdentifier > 0xFFF { 66 | return fmt.Errorf("vlan identifier %v is too high", d.VLANIdentifier) 67 | } 68 | firstBytes := uint16(d.Priority)<<13 | d.VLANIdentifier 69 | if d.DropEligible { 70 | firstBytes |= 0x1000 71 | } 72 | binary.BigEndian.PutUint16(bytes, firstBytes) 73 | binary.BigEndian.PutUint16(bytes[2:], uint16(d.Type)) 74 | return nil 75 | } 76 | -------------------------------------------------------------------------------- /layers/dot1q_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | package layers 7 | 8 | import ( 9 | "fmt" 10 | "reflect" 11 | "testing" 12 | 13 | "github.com/google/gopacket" 14 | ) 15 | 16 | // test harness to ensure the dot1q layer can be encoded/decoded properly 17 | // return error if decoded data not match. 18 | func testEncodeDecodeDot1Q(dot1Q *Dot1Q) error { 19 | buf := gopacket.NewSerializeBuffer() 20 | opts := gopacket.SerializeOptions{} 21 | expectedDot1Q := dot1Q 22 | 23 | err := dot1Q.SerializeTo(buf, opts) 24 | if err != nil { 25 | return err 26 | } 27 | 28 | newDot1q := &Dot1Q{} 29 | err = newDot1q.DecodeFromBytes(buf.Bytes(), gopacket.NilDecodeFeedback) 30 | if err != nil { 31 | return err 32 | } 33 | newDot1q.BaseLayer = BaseLayer{} 34 | 35 | if !reflect.DeepEqual(expectedDot1Q, newDot1q) { 36 | return fmt.Errorf("Expect %v actual %v", expectedDot1Q, newDot1q) 37 | } 38 | return nil 39 | 40 | } 41 | 42 | // Test to ensure what has been encode can be decoded 43 | func TestEncodeDecodeDot1Q(t *testing.T) { 44 | dot1Qs := []*Dot1Q{ 45 | &Dot1Q{ 46 | Priority: uint8(3), 47 | VLANIdentifier: uint16(30), 48 | }, 49 | &Dot1Q{ 50 | Priority: uint8(0x07), 51 | DropEligible: true, 52 | VLANIdentifier: uint16(0xFFF), 53 | }, 54 | } 55 | 56 | for i, curTest := range dot1Qs { 57 | err := testEncodeDecodeDot1Q(curTest) 58 | if err != nil { 59 | t.Error("Error with item ", i, " with error message :", err) 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /layers/eap.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | package layers 8 | 9 | import ( 10 | "encoding/binary" 11 | "fmt" 12 | "github.com/google/gopacket" 13 | ) 14 | 15 | type EAPCode uint8 16 | type EAPType uint8 17 | 18 | const ( 19 | EAPCodeRequest EAPCode = 1 20 | EAPCodeResponse EAPCode = 2 21 | EAPCodeSuccess EAPCode = 3 22 | EAPCodeFailure EAPCode = 4 23 | 24 | // EAPTypeNone means that this EAP layer has no Type or TypeData. 25 | // Success and Failure EAPs will have this set. 26 | EAPTypeNone EAPType = 0 27 | 28 | EAPTypeIdentity EAPType = 1 29 | EAPTypeNotification EAPType = 2 30 | EAPTypeNACK EAPType = 3 31 | EAPTypeOTP EAPType = 4 32 | EAPTypeTokenCard EAPType = 5 33 | ) 34 | 35 | // EAP defines an Extensible Authentication Protocol (rfc 3748) layer. 36 | type EAP struct { 37 | BaseLayer 38 | Code EAPCode 39 | Id uint8 40 | Length uint16 41 | Type EAPType 42 | TypeData []byte 43 | } 44 | 45 | // LayerType returns LayerTypeEAP. 46 | func (e *EAP) LayerType() gopacket.LayerType { return LayerTypeEAP } 47 | 48 | // DecodeFromBytes decodes the given bytes into this layer. 49 | func (e *EAP) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error { 50 | if len(data) < 4 { 51 | df.SetTruncated() 52 | return fmt.Errorf("EAP length %d too short", len(data)) 53 | } 54 | e.Code = EAPCode(data[0]) 55 | e.Id = data[1] 56 | e.Length = binary.BigEndian.Uint16(data[2:4]) 57 | if len(data) < int(e.Length) { 58 | df.SetTruncated() 59 | return fmt.Errorf("EAP length %d too short, %d expected", len(data), e.Length) 60 | } 61 | switch { 62 | case e.Length > 4: 63 | e.Type = EAPType(data[4]) 64 | e.TypeData = data[5:] 65 | case e.Length == 4: 66 | e.Type = 0 67 | e.TypeData = nil 68 | default: 69 | return fmt.Errorf("invalid EAP length %d", e.Length) 70 | } 71 | e.BaseLayer.Contents = data[:e.Length] 72 | e.BaseLayer.Payload = data[e.Length:] // Should be 0 bytes 73 | return nil 74 | } 75 | 76 | // SerializeTo writes the serialized form of this layer into the 77 | // SerializationBuffer, implementing gopacket.SerializableLayer. 78 | // See the docs for gopacket.SerializableLayer for more info. 79 | func (e *EAP) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error { 80 | if opts.FixLengths { 81 | e.Length = uint16(len(e.TypeData) + 1) 82 | } 83 | size := len(e.TypeData) + 4 84 | if size > 4 { 85 | size++ 86 | } 87 | bytes, err := b.PrependBytes(size) 88 | if err != nil { 89 | return err 90 | } 91 | bytes[0] = byte(e.Code) 92 | bytes[1] = e.Id 93 | binary.BigEndian.PutUint16(bytes[2:], e.Length) 94 | if size > 4 { 95 | bytes[4] = byte(e.Type) 96 | copy(bytes[5:], e.TypeData) 97 | } 98 | return nil 99 | } 100 | 101 | // CanDecode returns the set of layer types that this DecodingLayer can decode. 102 | func (e *EAP) CanDecode() gopacket.LayerClass { 103 | return LayerTypeEAP 104 | } 105 | 106 | // NextLayerType returns the layer type contained by this DecodingLayer. 107 | func (e *EAP) NextLayerType() gopacket.LayerType { 108 | return gopacket.LayerTypeZero 109 | } 110 | 111 | func decodeEAP(data []byte, p gopacket.PacketBuilder) error { 112 | e := &EAP{} 113 | return decodingLayerDecoder(e, data, p) 114 | } 115 | -------------------------------------------------------------------------------- /layers/endpoints.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | package layers 8 | 9 | import ( 10 | "encoding/binary" 11 | "github.com/google/gopacket" 12 | "net" 13 | "strconv" 14 | ) 15 | 16 | var ( 17 | // We use two different endpoint types for IPv4 vs IPv6 addresses, so that 18 | // ordering with endpointA.LessThan(endpointB) sanely groups all IPv4 19 | // addresses and all IPv6 addresses, such that IPv6 > IPv4 for all addresses. 20 | EndpointIPv4 = gopacket.RegisterEndpointType(1, gopacket.EndpointTypeMetadata{Name: "IPv4", Formatter: func(b []byte) string { 21 | return net.IP(b).String() 22 | }}) 23 | EndpointIPv6 = gopacket.RegisterEndpointType(2, gopacket.EndpointTypeMetadata{Name: "IPv6", Formatter: func(b []byte) string { 24 | return net.IP(b).String() 25 | }}) 26 | 27 | EndpointMAC = gopacket.RegisterEndpointType(3, gopacket.EndpointTypeMetadata{Name: "MAC", Formatter: func(b []byte) string { 28 | return net.HardwareAddr(b).String() 29 | }}) 30 | EndpointTCPPort = gopacket.RegisterEndpointType(4, gopacket.EndpointTypeMetadata{Name: "TCP", Formatter: func(b []byte) string { 31 | return strconv.Itoa(int(binary.BigEndian.Uint16(b))) 32 | }}) 33 | EndpointUDPPort = gopacket.RegisterEndpointType(5, gopacket.EndpointTypeMetadata{Name: "UDP", Formatter: func(b []byte) string { 34 | return strconv.Itoa(int(binary.BigEndian.Uint16(b))) 35 | }}) 36 | EndpointSCTPPort = gopacket.RegisterEndpointType(6, gopacket.EndpointTypeMetadata{Name: "SCTP", Formatter: func(b []byte) string { 37 | return strconv.Itoa(int(binary.BigEndian.Uint16(b))) 38 | }}) 39 | EndpointRUDPPort = gopacket.RegisterEndpointType(7, gopacket.EndpointTypeMetadata{Name: "RUDP", Formatter: func(b []byte) string { 40 | return strconv.Itoa(int(b[0])) 41 | }}) 42 | EndpointUDPLitePort = gopacket.RegisterEndpointType(8, gopacket.EndpointTypeMetadata{Name: "UDPLite", Formatter: func(b []byte) string { 43 | return strconv.Itoa(int(binary.BigEndian.Uint16(b))) 44 | }}) 45 | EndpointPPP = gopacket.RegisterEndpointType(9, gopacket.EndpointTypeMetadata{Name: "PPP", Formatter: func([]byte) string { 46 | return "point" 47 | }}) 48 | ) 49 | 50 | // NewIPEndpoint creates a new IP (v4 or v6) endpoint from a net.IP address. 51 | // It returns gopacket.InvalidEndpoint if the IP address is invalid. 52 | func NewIPEndpoint(a net.IP) gopacket.Endpoint { 53 | ipv4 := a.To4() 54 | if ipv4 != nil { 55 | return gopacket.NewEndpoint(EndpointIPv4, []byte(ipv4)) 56 | } 57 | 58 | ipv6 := a.To16() 59 | if ipv6 != nil { 60 | return gopacket.NewEndpoint(EndpointIPv6, []byte(ipv6)) 61 | } 62 | 63 | return gopacket.InvalidEndpoint 64 | } 65 | 66 | // NewMACEndpoint returns a new MAC address endpoint. 67 | func NewMACEndpoint(a net.HardwareAddr) gopacket.Endpoint { 68 | return gopacket.NewEndpoint(EndpointMAC, []byte(a)) 69 | } 70 | func newPortEndpoint(t gopacket.EndpointType, p uint16) gopacket.Endpoint { 71 | return gopacket.NewEndpoint(t, []byte{byte(p >> 8), byte(p)}) 72 | } 73 | 74 | // NewTCPPortEndpoint returns an endpoint based on a TCP port. 75 | func NewTCPPortEndpoint(p TCPPort) gopacket.Endpoint { 76 | return newPortEndpoint(EndpointTCPPort, uint16(p)) 77 | } 78 | 79 | // NewUDPPortEndpoint returns an endpoint based on a UDP port. 80 | func NewUDPPortEndpoint(p UDPPort) gopacket.Endpoint { 81 | return newPortEndpoint(EndpointUDPPort, uint16(p)) 82 | } 83 | 84 | // NewSCTPPortEndpoint returns an endpoint based on a SCTP port. 85 | func NewSCTPPortEndpoint(p SCTPPort) gopacket.Endpoint { 86 | return newPortEndpoint(EndpointSCTPPort, uint16(p)) 87 | } 88 | 89 | // NewRUDPPortEndpoint returns an endpoint based on a RUDP port. 90 | func NewRUDPPortEndpoint(p RUDPPort) gopacket.Endpoint { 91 | return gopacket.NewEndpoint(EndpointRUDPPort, []byte{byte(p)}) 92 | } 93 | 94 | // NewUDPLitePortEndpoint returns an endpoint based on a UDPLite port. 95 | func NewUDPLitePortEndpoint(p UDPLitePort) gopacket.Endpoint { 96 | return newPortEndpoint(EndpointUDPLitePort, uint16(p)) 97 | } 98 | -------------------------------------------------------------------------------- /layers/endpoints_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017, Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | package layers 8 | 9 | import ( 10 | "net" 11 | "testing" 12 | 13 | "github.com/google/gopacket" 14 | ) 15 | 16 | func TestNewIPEndpoint(t *testing.T) { 17 | cases := []struct { 18 | ip net.IP 19 | endpointType gopacket.EndpointType 20 | }{ 21 | {net.ParseIP("192.168.0.1").To4(), EndpointIPv4}, 22 | {net.ParseIP("192.168.0.1").To16(), EndpointIPv4}, 23 | {net.ParseIP("2001:0db8:85a3:0000:0000:8a2e:0370:7334"), EndpointIPv6}, 24 | } 25 | 26 | for _, c := range cases { 27 | endpoint := NewIPEndpoint(c.ip) 28 | if endpoint == gopacket.InvalidEndpoint { 29 | t.Errorf("Failed to create an IP endpoint for %s (%d-bytes)", 30 | c.ip, len(c.ip)) 31 | } 32 | if endpoint.EndpointType() != c.endpointType { 33 | t.Errorf("Wrong endpoint type created for %s (%d-bytes): expected %s, got %s", 34 | c.ip, len(c.ip), c.endpointType, endpoint.EndpointType()) 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /layers/erspan2.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | package layers 8 | 9 | import ( 10 | "encoding/binary" 11 | 12 | "github.com/google/gopacket" 13 | ) 14 | 15 | const ( 16 | //ERSPANIIVersionObsolete - The obsolete value for the version field 17 | ERSPANIIVersionObsolete = 0x0 18 | // ERSPANIIVersion - The current value for the version field 19 | ERSPANIIVersion = 0x1 20 | ) 21 | 22 | // ERSPANII contains all of the fields found in an ERSPAN Type II header 23 | // https://tools.ietf.org/html/draft-foschiano-erspan-03 24 | type ERSPANII struct { 25 | BaseLayer 26 | IsTruncated bool 27 | Version, CoS, TrunkEncap uint8 28 | VLANIdentifier, SessionID, Reserved uint16 29 | Index uint32 30 | } 31 | 32 | func (erspan2 *ERSPANII) LayerType() gopacket.LayerType { return LayerTypeERSPANII } 33 | 34 | // DecodeFromBytes decodes the given bytes into this layer. 35 | func (erspan2 *ERSPANII) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error { 36 | erspan2Length := 8 37 | erspan2.Version = data[0] & 0xF0 >> 4 38 | erspan2.VLANIdentifier = binary.BigEndian.Uint16(data[:2]) & 0x0FFF 39 | erspan2.CoS = data[2] & 0xE0 >> 5 40 | erspan2.TrunkEncap = data[2] & 0x18 >> 3 41 | erspan2.IsTruncated = data[2]&0x4>>2 != 0 42 | erspan2.SessionID = binary.BigEndian.Uint16(data[2:4]) & 0x03FF 43 | erspan2.Reserved = binary.BigEndian.Uint16(data[4:6]) & 0xFFF0 >> 4 44 | erspan2.Index = binary.BigEndian.Uint32(data[4:8]) & 0x000FFFFF 45 | erspan2.Contents = data[:erspan2Length] 46 | erspan2.Payload = data[erspan2Length:] 47 | return nil 48 | } 49 | 50 | // SerializeTo writes the serialized form of this layer into the 51 | // SerializationBuffer, implementing gopacket.SerializableLayer. 52 | // See the docs for gopacket.SerializableLayer for more info. 53 | func (erspan2 *ERSPANII) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error { 54 | bytes, err := b.PrependBytes(8) 55 | if err != nil { 56 | return err 57 | } 58 | 59 | twoByteInt := uint16(erspan2.Version&0xF)<<12 | erspan2.VLANIdentifier&0x0FFF 60 | binary.BigEndian.PutUint16(bytes, twoByteInt) 61 | 62 | twoByteInt = uint16(erspan2.CoS&0x7)<<13 | uint16(erspan2.TrunkEncap&0x3)<<11 | erspan2.SessionID&0x03FF 63 | if erspan2.IsTruncated { 64 | twoByteInt |= 0x400 65 | } 66 | binary.BigEndian.PutUint16(bytes[2:], twoByteInt) 67 | 68 | fourByteInt := uint32(erspan2.Reserved&0x0FFF)<<20 | erspan2.Index&0x000FFFFF 69 | binary.BigEndian.PutUint32(bytes[4:], fourByteInt) 70 | return nil 71 | } 72 | 73 | // CanDecode returns the set of layer types that this DecodingLayer can decode. 74 | func (erspan2 *ERSPANII) CanDecode() gopacket.LayerClass { 75 | return LayerTypeERSPANII 76 | } 77 | 78 | // NextLayerType returns the layer type contained by this DecodingLayer. 79 | func (erspan2 *ERSPANII) NextLayerType() gopacket.LayerType { 80 | return LayerTypeEthernet 81 | } 82 | 83 | func decodeERSPANII(data []byte, p gopacket.PacketBuilder) error { 84 | erspan2 := &ERSPANII{} 85 | return decodingLayerDecoder(erspan2, data, p) 86 | } 87 | -------------------------------------------------------------------------------- /layers/erspan2_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | package layers 7 | 8 | import ( 9 | "reflect" 10 | "testing" 11 | 12 | "github.com/google/gopacket" 13 | ) 14 | 15 | func TestDecodeAndEncode(t *testing.T) { 16 | erspan := &ERSPANII{ 17 | Version: ERSPANIIVersion, 18 | VLANIdentifier: 0x2aa, 19 | CoS: 0x4, 20 | TrunkEncap: 0x2, 21 | IsTruncated: true, 22 | SessionID: 0x2aa, 23 | Reserved: 0x155, 24 | Index: 0xF0F0F, 25 | } 26 | expectedBytes := []byte{0x12, 0xaa, 0x96, 0xaa, 0x15, 0x5F, 0x0F, 0x0F} 27 | 28 | buf := gopacket.NewSerializeBuffer() 29 | opts := gopacket.SerializeOptions{} 30 | erspan.SerializeTo(buf, opts) 31 | 32 | if !reflect.DeepEqual(buf.Bytes(), expectedBytes) { 33 | t.Fatalf("Got %+v, expected %+v\n", buf.Bytes(), expectedBytes) 34 | } 35 | 36 | erspan2 := &ERSPANII{} 37 | erspan2.DecodeFromBytes(buf.Bytes(), gopacket.NilDecodeFeedback) 38 | if erspan.Version != erspan2.Version { 39 | t.Fatalf("Got %+v, expected %+v\n", erspan2.Version, erspan.Version) 40 | } 41 | if erspan.VLANIdentifier != erspan2.VLANIdentifier { 42 | t.Fatalf("Got %+v, expected %+v\n", erspan2.VLANIdentifier, erspan.VLANIdentifier) 43 | } 44 | if erspan.CoS != erspan2.CoS { 45 | t.Fatalf("Got %+v, expected %+v\n", erspan2.CoS, erspan.CoS) 46 | } 47 | if erspan.TrunkEncap != erspan2.TrunkEncap { 48 | t.Fatalf("Got %+v, expected %+v\n", erspan2.TrunkEncap, erspan.TrunkEncap) 49 | } 50 | if erspan.IsTruncated != erspan2.IsTruncated { 51 | t.Fatalf("Got %+v, expected %+v\n", erspan2.IsTruncated, erspan.IsTruncated) 52 | } 53 | if erspan.SessionID != erspan2.SessionID { 54 | t.Fatalf("Got %+v, expected %+v\n", erspan2.SessionID, erspan.SessionID) 55 | } 56 | if erspan.Reserved != erspan2.Reserved { 57 | t.Fatalf("Got %+v, expected %+v\n", erspan2.Reserved, erspan.Reserved) 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /layers/etherip.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | package layers 8 | 9 | import ( 10 | "encoding/binary" 11 | "github.com/google/gopacket" 12 | ) 13 | 14 | // EtherIP is the struct for storing RFC 3378 EtherIP packet headers. 15 | type EtherIP struct { 16 | BaseLayer 17 | Version uint8 18 | Reserved uint16 19 | } 20 | 21 | // LayerType returns gopacket.LayerTypeEtherIP. 22 | func (e *EtherIP) LayerType() gopacket.LayerType { return LayerTypeEtherIP } 23 | 24 | // DecodeFromBytes decodes the given bytes into this layer. 25 | func (e *EtherIP) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error { 26 | e.Version = data[0] >> 4 27 | e.Reserved = binary.BigEndian.Uint16(data[:2]) & 0x0fff 28 | e.BaseLayer = BaseLayer{data[:2], data[2:]} 29 | return nil 30 | } 31 | 32 | // CanDecode returns the set of layer types that this DecodingLayer can decode. 33 | func (e *EtherIP) CanDecode() gopacket.LayerClass { 34 | return LayerTypeEtherIP 35 | } 36 | 37 | // NextLayerType returns the layer type contained by this DecodingLayer. 38 | func (e *EtherIP) NextLayerType() gopacket.LayerType { 39 | return LayerTypeEthernet 40 | } 41 | 42 | func decodeEtherIP(data []byte, p gopacket.PacketBuilder) error { 43 | e := &EtherIP{} 44 | return decodingLayerDecoder(e, data, p) 45 | } 46 | -------------------------------------------------------------------------------- /layers/fddi.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | package layers 8 | 9 | import ( 10 | "github.com/google/gopacket" 11 | "net" 12 | ) 13 | 14 | // FDDI contains the header for FDDI frames. 15 | type FDDI struct { 16 | BaseLayer 17 | FrameControl FDDIFrameControl 18 | Priority uint8 19 | SrcMAC, DstMAC net.HardwareAddr 20 | } 21 | 22 | // LayerType returns LayerTypeFDDI. 23 | func (f *FDDI) LayerType() gopacket.LayerType { return LayerTypeFDDI } 24 | 25 | // LinkFlow returns a new flow of type EndpointMAC. 26 | func (f *FDDI) LinkFlow() gopacket.Flow { 27 | return gopacket.NewFlow(EndpointMAC, f.SrcMAC, f.DstMAC) 28 | } 29 | 30 | func decodeFDDI(data []byte, p gopacket.PacketBuilder) error { 31 | f := &FDDI{ 32 | FrameControl: FDDIFrameControl(data[0] & 0xF8), 33 | Priority: data[0] & 0x07, 34 | SrcMAC: net.HardwareAddr(data[1:7]), 35 | DstMAC: net.HardwareAddr(data[7:13]), 36 | BaseLayer: BaseLayer{data[:13], data[13:]}, 37 | } 38 | p.SetLinkLayer(f) 39 | p.AddLayer(f) 40 | return p.NextDecoder(f.FrameControl) 41 | } 42 | -------------------------------------------------------------------------------- /layers/fuzz_layer.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The GoPacket Authors. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license that can be found 4 | // in the LICENSE file in the root of the source tree. 5 | 6 | package layers 7 | 8 | import ( 9 | "encoding/binary" 10 | 11 | "github.com/google/gopacket" 12 | ) 13 | 14 | // FuzzLayer is a fuzz target for the layers package of gopacket 15 | // A fuzz target is a function processing a binary blob (byte slice) 16 | // The process here is to interpret this data as a packet, and print the layers contents. 17 | // The decoding options and the starting layer are encoded in the first bytes. 18 | // The function returns 1 if this is a valid packet (no error layer) 19 | func FuzzLayer(data []byte) int { 20 | if len(data) < 3 { 21 | return 0 22 | } 23 | // use the first two bytes to choose the top level layer 24 | startLayer := binary.BigEndian.Uint16(data[:2]) 25 | var fuzzOpts = gopacket.DecodeOptions{ 26 | Lazy: data[2]&0x1 != 0, 27 | NoCopy: data[2]&0x2 != 0, 28 | SkipDecodeRecovery: data[2]&0x4 != 0, 29 | DecodeStreamsAsDatagrams: data[2]&0x8 != 0, 30 | } 31 | p := gopacket.NewPacket(data[3:], gopacket.LayerType(startLayer), fuzzOpts) 32 | for _, l := range p.Layers() { 33 | gopacket.LayerString(l) 34 | } 35 | if p.ErrorLayer() != nil { 36 | return 0 37 | } 38 | return 1 39 | } 40 | -------------------------------------------------------------------------------- /layers/gen.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | // +build ignore 8 | 9 | // This binary pulls known ports from IANA, and uses them to populate 10 | // iana_ports.go's TCPPortNames and UDPPortNames maps. 11 | // 12 | // go run gen.go | gofmt > iana_ports.go 13 | package main 14 | 15 | import ( 16 | "bytes" 17 | "encoding/xml" 18 | "flag" 19 | "fmt" 20 | "io/ioutil" 21 | "net/http" 22 | "os" 23 | "strconv" 24 | "time" 25 | ) 26 | 27 | const fmtString = `// Copyright 2012 Google, Inc. All rights reserved. 28 | 29 | package layers 30 | 31 | // Created by gen.go, don't edit manually 32 | // Generated at %s 33 | // Fetched from %q 34 | 35 | // TCPPortNames contains the port names for all TCP ports. 36 | var TCPPortNames = tcpPortNames 37 | 38 | // UDPPortNames contains the port names for all UDP ports. 39 | var UDPPortNames = udpPortNames 40 | 41 | // SCTPPortNames contains the port names for all SCTP ports. 42 | var SCTPPortNames = sctpPortNames 43 | 44 | var tcpPortNames = map[TCPPort]string{ 45 | %s} 46 | var udpPortNames = map[UDPPort]string{ 47 | %s} 48 | var sctpPortNames = map[SCTPPort]string{ 49 | %s} 50 | ` 51 | 52 | var url = flag.String("url", "http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xml", "URL to grab port numbers from") 53 | 54 | func main() { 55 | fmt.Fprintf(os.Stderr, "Fetching ports from %q\n", *url) 56 | resp, err := http.Get(*url) 57 | if err != nil { 58 | panic(err) 59 | } 60 | defer resp.Body.Close() 61 | body, err := ioutil.ReadAll(resp.Body) 62 | if err != nil { 63 | panic(err) 64 | } 65 | fmt.Fprintln(os.Stderr, "Parsing XML") 66 | var registry struct { 67 | Records []struct { 68 | Protocol string `xml:"protocol"` 69 | Number string `xml:"number"` 70 | Name string `xml:"name"` 71 | } `xml:"record"` 72 | } 73 | xml.Unmarshal(body, ®istry) 74 | var tcpPorts bytes.Buffer 75 | var udpPorts bytes.Buffer 76 | var sctpPorts bytes.Buffer 77 | done := map[string]map[int]bool{ 78 | "tcp": map[int]bool{}, 79 | "udp": map[int]bool{}, 80 | "sctp": map[int]bool{}, 81 | } 82 | for _, r := range registry.Records { 83 | port, err := strconv.Atoi(r.Number) 84 | if err != nil { 85 | continue 86 | } 87 | if r.Name == "" { 88 | continue 89 | } 90 | var b *bytes.Buffer 91 | switch r.Protocol { 92 | case "tcp": 93 | b = &tcpPorts 94 | case "udp": 95 | b = &udpPorts 96 | case "sctp": 97 | b = &sctpPorts 98 | default: 99 | continue 100 | } 101 | if done[r.Protocol][port] { 102 | continue 103 | } 104 | done[r.Protocol][port] = true 105 | fmt.Fprintf(b, "\t%d: %q,\n", port, r.Name) 106 | } 107 | fmt.Fprintln(os.Stderr, "Writing results to stdout") 108 | fmt.Printf(fmtString, time.Now(), *url, tcpPorts.String(), udpPorts.String(), sctpPorts.String()) 109 | } 110 | -------------------------------------------------------------------------------- /layers/gen2.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | // +build ignore 8 | 9 | // This binary handles creating string constants and function templates for enums. 10 | // 11 | // go run gen.go | gofmt > enums_generated.go 12 | package main 13 | 14 | import ( 15 | "fmt" 16 | "log" 17 | "os" 18 | "text/template" 19 | "time" 20 | ) 21 | 22 | const fmtString = `// Copyright 2012 Google, Inc. All rights reserved. 23 | 24 | package layers 25 | 26 | // Created by gen2.go, don't edit manually 27 | // Generated at %s 28 | 29 | import ( 30 | "fmt" 31 | 32 | "github.com/google/gopacket" 33 | ) 34 | 35 | ` 36 | 37 | var funcsTmpl = template.Must(template.New("foo").Parse(` 38 | // Decoder calls {{.Name}}Metadata.DecodeWith's decoder. 39 | func (a {{.Name}}) Decode(data []byte, p gopacket.PacketBuilder) error { 40 | return {{.Name}}Metadata[a].DecodeWith.Decode(data, p) 41 | } 42 | // String returns {{.Name}}Metadata.Name. 43 | func (a {{.Name}}) String() string { 44 | return {{.Name}}Metadata[a].Name 45 | } 46 | // LayerType returns {{.Name}}Metadata.LayerType. 47 | func (a {{.Name}}) LayerType() gopacket.LayerType { 48 | return {{.Name}}Metadata[a].LayerType 49 | } 50 | 51 | type errorDecoderFor{{.Name}} int 52 | func (a *errorDecoderFor{{.Name}}) Decode(data []byte, p gopacket.PacketBuilder) error { 53 | return a 54 | } 55 | func (a *errorDecoderFor{{.Name}}) Error() string { 56 | return fmt.Sprintf("Unable to decode {{.Name}} %d", int(*a)) 57 | } 58 | 59 | var errorDecodersFor{{.Name}} [{{.Num}}]errorDecoderFor{{.Name}} 60 | var {{.Name}}Metadata [{{.Num}}]EnumMetadata 61 | 62 | func initUnknownTypesFor{{.Name}}() { 63 | for i := 0; i < {{.Num}}; i++ { 64 | errorDecodersFor{{.Name}}[i] = errorDecoderFor{{.Name}}(i) 65 | {{.Name}}Metadata[i] = EnumMetadata{ 66 | DecodeWith: &errorDecodersFor{{.Name}}[i], 67 | Name: "Unknown{{.Name}}", 68 | } 69 | } 70 | } 71 | `)) 72 | 73 | func main() { 74 | fmt.Fprintf(os.Stderr, "Writing results to stdout\n") 75 | fmt.Printf(fmtString, time.Now()) 76 | types := []struct { 77 | Name string 78 | Num int 79 | }{ 80 | {"LinkType", 256}, 81 | {"EthernetType", 65536}, 82 | {"PPPType", 65536}, 83 | {"IPProtocol", 256}, 84 | {"SCTPChunkType", 256}, 85 | {"PPPoECode", 256}, 86 | {"FDDIFrameControl", 256}, 87 | {"EAPOLType", 256}, 88 | {"ProtocolFamily", 256}, 89 | {"Dot11Type", 256}, 90 | {"USBTransportType", 256}, 91 | } 92 | 93 | fmt.Println("func init() {") 94 | for _, t := range types { 95 | fmt.Printf("initUnknownTypesFor%s()\n", t.Name) 96 | } 97 | fmt.Println("initActualTypeData()") 98 | fmt.Println("}") 99 | for _, t := range types { 100 | if err := funcsTmpl.Execute(os.Stdout, t); err != nil { 101 | log.Fatalf("Failed to execute template %s: %v", t.Name, err) 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /layers/gen_linted.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | for i in *.go; do golint $i | grep -q . || echo $i; done > .linted 4 | -------------------------------------------------------------------------------- /layers/icmp6_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012, Google, Inc. All rights reserved. 2 | // Copyright 2009-2011 Andreas Krennmair. All rights reserved. 3 | // 4 | // Use of this source code is governed by a BSD-style license 5 | // that can be found in the LICENSE file in the root of the source 6 | // tree. 7 | 8 | package layers 9 | 10 | import ( 11 | "github.com/google/gopacket" 12 | "net" 13 | "reflect" 14 | "testing" 15 | ) 16 | 17 | // testPacketICMPv6 is the packet: 18 | // 10:48:30.088384 IP6 2620:0:1005:0:26be:5ff:fe27:b17 > fe80::21f:caff:feb3:7640: ICMP6, neighbor advertisement, tgt is 2620:0:1005:0:26be:5ff:fe27:b17, length 24 19 | // 0x0000: 001f cab3 7640 24be 0527 0b17 86dd 6000 ....v@$..'....`. 20 | // 0x0010: 0000 0018 3aff 2620 0000 1005 0000 26be ....:.&.......&. 21 | // 0x0020: 05ff fe27 0b17 fe80 0000 0000 0000 021f ...'............ 22 | // 0x0030: caff feb3 7640 8800 1ed6 4000 0000 2620 ....v@....@...&. 23 | // 0x0040: 0000 1005 0000 26be 05ff fe27 0b17 ......&....'.. 24 | var testPacketICMPv6 = []byte{ 25 | 0x00, 0x1f, 0xca, 0xb3, 0x76, 0x40, 0x24, 0xbe, 0x05, 0x27, 0x0b, 0x17, 0x86, 0xdd, 0x60, 0x00, 26 | 0x00, 0x00, 0x00, 0x18, 0x3a, 0xff, 0x26, 0x20, 0x00, 0x00, 0x10, 0x05, 0x00, 0x00, 0x26, 0xbe, 27 | 0x05, 0xff, 0xfe, 0x27, 0x0b, 0x17, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x1f, 28 | 0xca, 0xff, 0xfe, 0xb3, 0x76, 0x40, 0x88, 0x00, 0x1e, 0xd6, 0x40, 0x00, 0x00, 0x00, 0x26, 0x20, 29 | 0x00, 0x00, 0x10, 0x05, 0x00, 0x00, 0x26, 0xbe, 0x05, 0xff, 0xfe, 0x27, 0x0b, 0x17, 30 | } 31 | 32 | func TestPacketICMPv6(t *testing.T) { 33 | p := gopacket.NewPacket(testPacketICMPv6, LinkTypeEthernet, gopacket.Default) 34 | if p.ErrorLayer() != nil { 35 | t.Error("Failed to decode packet:", p.ErrorLayer().Error()) 36 | } 37 | checkLayers(p, []gopacket.LayerType{LayerTypeEthernet, LayerTypeIPv6, LayerTypeICMPv6, gopacket.LayerTypePayload}, t) 38 | checkSerialization(p, t) 39 | 40 | if got, ok := p.Layer(LayerTypeIPv6).(*IPv6); ok { 41 | want := &IPv6{ 42 | BaseLayer: BaseLayer{ 43 | Contents: []byte{0x60, 0x0, 0x0, 0x0, 0x0, 0x18, 44 | 0x3a, 0xff, 0x26, 0x20, 0x0, 0x0, 0x10, 0x5, 0x0, 0x0, 0x26, 0xbe, 0x5, 45 | 0xff, 0xfe, 0x27, 0xb, 0x17, 0xfe, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 46 | 0x2, 0x1f, 0xca, 0xff, 0xfe, 0xb3, 0x76, 0x40}, 47 | Payload: []byte{0x88, 0x0, 0x1e, 0xd6, 0x40, 0x0, 0x0, 0x0, 0x26, 0x20, 48 | 0x0, 0x0, 0x10, 0x5, 0x0, 0x0, 0x26, 0xbe, 0x5, 0xff, 0xfe, 0x27, 0xb, 49 | 0x17}, 50 | }, 51 | Version: 6, 52 | TrafficClass: 0, 53 | FlowLabel: 0, 54 | Length: 24, 55 | NextHeader: IPProtocolICMPv6, 56 | HopLimit: 255, 57 | SrcIP: net.IP{0x26, 0x20, 0x0, 0x0, 0x10, 0x5, 0x0, 0x0, 0x26, 0xbe, 0x5, 0xff, 0xfe, 0x27, 0xb, 0x17}, 58 | DstIP: net.IP{0xfe, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x1f, 0xca, 0xff, 0xfe, 0xb3, 0x76, 0x40}, 59 | } 60 | if !reflect.DeepEqual(got, want) { 61 | t.Errorf("IPv6 packet processing failed:\ngot :\n%#v\n\nwant :\n%#v\n\n", got, want) 62 | } 63 | } else { 64 | t.Error("No IPv6 layer type found in packet") 65 | } 66 | if got, ok := p.Layer(LayerTypeICMPv6).(*ICMPv6); ok { 67 | want := &ICMPv6{ 68 | BaseLayer: BaseLayer{ 69 | Contents: []byte{0x88, 0x0, 0x1e, 0xd6}, 70 | Payload: []byte{0x40, 0x0, 0x0, 0x0, 0x26, 0x20, 0x0, 0x0, 0x10, 71 | 0x5, 0x0, 0x0, 0x26, 0xbe, 0x5, 0xff, 0xfe, 0x27, 0xb, 0x17}, 72 | }, 73 | TypeCode: 0x8800, 74 | Checksum: 0x1ed6, 75 | } 76 | if !reflect.DeepEqual(got, want) { 77 | t.Errorf("ICMPv6 packet processing failed:\ngot :\n%#v\n\nwant :\n%#v\n\n", got, want) 78 | } 79 | if got.TypeCode.String() != "NeighborAdvertisement" { 80 | t.Errorf("ICMPv6 type code, got %q want 'NeighborAdvertisement'", got.TypeCode.String()) 81 | } 82 | } else { 83 | t.Error("No ICMPv6 layer type found in packet") 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /layers/icmp6hopbyhop_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012, Google, Inc. All rights reserved. 2 | // Copyright 2009-2011 Andreas Krennmair. All rights reserved. 3 | // 4 | // Use of this source code is governed by a BSD-style license 5 | // that can be found in the LICENSE file in the root of the source 6 | // tree. 7 | 8 | package layers 9 | 10 | import ( 11 | "github.com/google/gopacket" 12 | "testing" 13 | ) 14 | 15 | var icmp6HopByHopData = []byte{ 16 | // Ethernet layer 17 | 0x33, 0x33, 0x00, 0x00, 0x00, 0x16, // destination 18 | 0x1e, 0xc3, 0xe3, 0xb7, 0xc4, 0xd5, // source 19 | 0x86, 0xdd, // type IPv6 20 | 21 | // IPv6 layer 22 | 0x60, 0x00, 0x00, 0x00, // version; traffic class; flow label 23 | 0x00, 0x88, // payload length? 24 | 0x00, // Next Header 25 | 0x01, // Hop Limit 26 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // source 27 | 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, // destination 28 | 29 | // IPv6 Hop-by-hop option 30 | 0x3a, // Next Header - IPv6-ICMP 31 | 0x00, // Hdr Ext Len 32 | 0x05, 0x02, 0x00, 0x00, 0x01, 0x00, // Options and Padding 33 | 34 | // ICMPv6 layer 35 | 0x8f, 0x00, // ICMP type 143, code 0 36 | 37 | 0x9e, 0xed, 0x00, 0x00, 0x00, 0x06, 0x03, 0x00, 38 | 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 39 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xb7, 40 | 0xc4, 0xd5, 0x03, 0x00, 0x00, 0x00, 0xff, 0x02, 41 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 42 | 0x00, 0x01, 0xff, 0x00, 0x00, 0x00, 0x04, 0x00, 43 | 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 44 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0x11, 45 | 0x00, 0x79, 0x04, 0x00, 0x00, 0x00, 0xff, 0x02, 46 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 47 | 0x00, 0x01, 0xff, 0x00, 0x00, 0x01, 0x04, 0x00, 48 | 0x00, 0x00, 0xff, 0x05, 0x00, 0x00, 0x00, 0x00, 49 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 50 | 0x00, 0x02, 0x04, 0x00, 0x00, 0x00, 0xff, 0x02, 51 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 52 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 53 | } 54 | 55 | func TestPacketICMPv6WithHopByHop(t *testing.T) { 56 | var ethLayerResp Ethernet 57 | var ipV6LayerResp IPv6 58 | var icmpLayerResp ICMPv6 59 | var payload gopacket.Payload 60 | 61 | parser := gopacket.NewDecodingLayerParser(LayerTypeEthernet, ðLayerResp, &ipV6LayerResp, &icmpLayerResp, &payload) 62 | parser.IgnoreUnsupported = true // avoid `No decoder for layer type ICMPv6RouterAdvertisement` error 63 | 64 | respLayers := make([]gopacket.LayerType, 0) 65 | err := parser.DecodeLayers(icmp6HopByHopData, &respLayers) 66 | 67 | if err != nil { 68 | t.Errorf("error decoding layers %s", err) 69 | return 70 | } 71 | 72 | expectedType := uint8(icmp6HopByHopData[62]) 73 | actualType := uint8(icmpLayerResp.TypeCode.Type()) 74 | if expectedType != actualType { 75 | t.Errorf("expected ICMP layer's TypeCode to be %d but was %d", expectedType, actualType) 76 | } 77 | 78 | p := gopacket.NewPacket(icmp6HopByHopData, LinkTypeEthernet, gopacket.Default) 79 | if p.ErrorLayer() != nil { 80 | t.Error("Failed to decode packet:", p.ErrorLayer().Error()) 81 | } 82 | checkLayers(p, []gopacket.LayerType{LayerTypeEthernet, LayerTypeIPv6, LayerTypeIPv6HopByHop, LayerTypeICMPv6}, t) 83 | // See https://github.com/google/gopacket/issues/517 84 | // checkSerialization(p, t) 85 | } 86 | -------------------------------------------------------------------------------- /layers/ipsec.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | package layers 8 | 9 | import ( 10 | "encoding/binary" 11 | "errors" 12 | "github.com/google/gopacket" 13 | ) 14 | 15 | // IPSecAH is the authentication header for IPv4/6 defined in 16 | // http://tools.ietf.org/html/rfc2402 17 | type IPSecAH struct { 18 | // While the auth header can be used for both IPv4 and v6, its format is that of 19 | // an IPv6 extension (NextHeader, PayloadLength, etc...), so we use ipv6ExtensionBase 20 | // to build it. 21 | ipv6ExtensionBase 22 | Reserved uint16 23 | SPI, Seq uint32 24 | AuthenticationData []byte 25 | } 26 | 27 | // LayerType returns LayerTypeIPSecAH. 28 | func (i *IPSecAH) LayerType() gopacket.LayerType { return LayerTypeIPSecAH } 29 | 30 | func decodeIPSecAH(data []byte, p gopacket.PacketBuilder) error { 31 | if len(data) < 12 { 32 | p.SetTruncated() 33 | return errors.New("IPSec AH packet less than 12 bytes") 34 | } 35 | i := &IPSecAH{ 36 | ipv6ExtensionBase: ipv6ExtensionBase{ 37 | NextHeader: IPProtocol(data[0]), 38 | HeaderLength: data[1], 39 | }, 40 | Reserved: binary.BigEndian.Uint16(data[2:4]), 41 | SPI: binary.BigEndian.Uint32(data[4:8]), 42 | Seq: binary.BigEndian.Uint32(data[8:12]), 43 | } 44 | i.ActualLength = (int(i.HeaderLength) + 2) * 4 45 | if len(data) < i.ActualLength { 46 | p.SetTruncated() 47 | return errors.New("Truncated AH packet < ActualLength") 48 | } 49 | i.AuthenticationData = data[12:i.ActualLength] 50 | i.Contents = data[:i.ActualLength] 51 | i.Payload = data[i.ActualLength:] 52 | p.AddLayer(i) 53 | return p.NextDecoder(i.NextHeader) 54 | } 55 | 56 | // IPSecESP is the encapsulating security payload defined in 57 | // http://tools.ietf.org/html/rfc2406 58 | type IPSecESP struct { 59 | BaseLayer 60 | SPI, Seq uint32 61 | // Encrypted contains the encrypted set of bytes sent in an ESP 62 | Encrypted []byte 63 | } 64 | 65 | // LayerType returns LayerTypeIPSecESP. 66 | func (i *IPSecESP) LayerType() gopacket.LayerType { return LayerTypeIPSecESP } 67 | 68 | func decodeIPSecESP(data []byte, p gopacket.PacketBuilder) error { 69 | i := &IPSecESP{ 70 | BaseLayer: BaseLayer{data, nil}, 71 | SPI: binary.BigEndian.Uint32(data[:4]), 72 | Seq: binary.BigEndian.Uint32(data[4:8]), 73 | Encrypted: data[8:], 74 | } 75 | p.AddLayer(i) 76 | return nil 77 | } 78 | -------------------------------------------------------------------------------- /layers/linux_sll.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | package layers 8 | 9 | import ( 10 | "encoding/binary" 11 | "errors" 12 | "fmt" 13 | "net" 14 | 15 | "github.com/google/gopacket" 16 | ) 17 | 18 | type LinuxSLLPacketType uint16 19 | 20 | const ( 21 | LinuxSLLPacketTypeHost LinuxSLLPacketType = 0 // To us 22 | LinuxSLLPacketTypeBroadcast LinuxSLLPacketType = 1 // To all 23 | LinuxSLLPacketTypeMulticast LinuxSLLPacketType = 2 // To group 24 | LinuxSLLPacketTypeOtherhost LinuxSLLPacketType = 3 // To someone else 25 | LinuxSLLPacketTypeOutgoing LinuxSLLPacketType = 4 // Outgoing of any type 26 | // These ones are invisible by user level 27 | LinuxSLLPacketTypeLoopback LinuxSLLPacketType = 5 // MC/BRD frame looped back 28 | LinuxSLLPacketTypeFastroute LinuxSLLPacketType = 6 // Fastrouted frame 29 | ) 30 | 31 | func (l LinuxSLLPacketType) String() string { 32 | switch l { 33 | case LinuxSLLPacketTypeHost: 34 | return "host" 35 | case LinuxSLLPacketTypeBroadcast: 36 | return "broadcast" 37 | case LinuxSLLPacketTypeMulticast: 38 | return "multicast" 39 | case LinuxSLLPacketTypeOtherhost: 40 | return "otherhost" 41 | case LinuxSLLPacketTypeOutgoing: 42 | return "outgoing" 43 | case LinuxSLLPacketTypeLoopback: 44 | return "loopback" 45 | case LinuxSLLPacketTypeFastroute: 46 | return "fastroute" 47 | } 48 | return fmt.Sprintf("Unknown(%d)", int(l)) 49 | } 50 | 51 | type LinuxSLL struct { 52 | BaseLayer 53 | PacketType LinuxSLLPacketType 54 | AddrLen uint16 55 | Addr net.HardwareAddr 56 | EthernetType EthernetType 57 | AddrType uint16 58 | } 59 | 60 | // LayerType returns LayerTypeLinuxSLL. 61 | func (sll *LinuxSLL) LayerType() gopacket.LayerType { return LayerTypeLinuxSLL } 62 | 63 | func (sll *LinuxSLL) CanDecode() gopacket.LayerClass { 64 | return LayerTypeLinuxSLL 65 | } 66 | 67 | func (sll *LinuxSLL) LinkFlow() gopacket.Flow { 68 | return gopacket.NewFlow(EndpointMAC, sll.Addr, nil) 69 | } 70 | 71 | func (sll *LinuxSLL) NextLayerType() gopacket.LayerType { 72 | return sll.EthernetType.LayerType() 73 | } 74 | 75 | func (sll *LinuxSLL) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error { 76 | if len(data) < 16 { 77 | return errors.New("Linux SLL packet too small") 78 | } 79 | sll.PacketType = LinuxSLLPacketType(binary.BigEndian.Uint16(data[0:2])) 80 | sll.AddrType = binary.BigEndian.Uint16(data[2:4]) 81 | sll.AddrLen = binary.BigEndian.Uint16(data[4:6]) 82 | 83 | sll.Addr = net.HardwareAddr(data[6 : sll.AddrLen+6]) 84 | sll.EthernetType = EthernetType(binary.BigEndian.Uint16(data[14:16])) 85 | sll.BaseLayer = BaseLayer{data[:16], data[16:]} 86 | 87 | return nil 88 | } 89 | 90 | func decodeLinuxSLL(data []byte, p gopacket.PacketBuilder) error { 91 | sll := &LinuxSLL{} 92 | if err := sll.DecodeFromBytes(data, p); err != nil { 93 | return err 94 | } 95 | p.AddLayer(sll) 96 | p.SetLinkLayer(sll) 97 | return p.NextDecoder(sll.EthernetType) 98 | } 99 | -------------------------------------------------------------------------------- /layers/loopback.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | package layers 8 | 9 | import ( 10 | "encoding/binary" 11 | "errors" 12 | "fmt" 13 | 14 | "github.com/google/gopacket" 15 | ) 16 | 17 | // Loopback contains the header for loopback encapsulation. This header is 18 | // used by both BSD and OpenBSD style loopback decoding (pcap's DLT_NULL 19 | // and DLT_LOOP, respectively). 20 | type Loopback struct { 21 | BaseLayer 22 | Family ProtocolFamily 23 | } 24 | 25 | // LayerType returns LayerTypeLoopback. 26 | func (l *Loopback) LayerType() gopacket.LayerType { return LayerTypeLoopback } 27 | 28 | // DecodeFromBytes decodes the given bytes into this layer. 29 | func (l *Loopback) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error { 30 | if len(data) < 4 { 31 | return errors.New("Loopback packet too small") 32 | } 33 | 34 | // The protocol could be either big-endian or little-endian, we're 35 | // not sure. But we're PRETTY sure that the value is less than 36 | // 256, so we can check the first two bytes. 37 | var prot uint32 38 | if data[0] == 0 && data[1] == 0 { 39 | prot = binary.BigEndian.Uint32(data[:4]) 40 | } else { 41 | prot = binary.LittleEndian.Uint32(data[:4]) 42 | } 43 | if prot > 0xFF { 44 | return fmt.Errorf("Invalid loopback protocol %q", data[:4]) 45 | } 46 | 47 | l.Family = ProtocolFamily(prot) 48 | l.BaseLayer = BaseLayer{data[:4], data[4:]} 49 | return nil 50 | } 51 | 52 | // CanDecode returns the set of layer types that this DecodingLayer can decode. 53 | func (l *Loopback) CanDecode() gopacket.LayerClass { 54 | return LayerTypeLoopback 55 | } 56 | 57 | // NextLayerType returns the layer type contained by this DecodingLayer. 58 | func (l *Loopback) NextLayerType() gopacket.LayerType { 59 | return l.Family.LayerType() 60 | } 61 | 62 | // SerializeTo writes the serialized form of this layer into the 63 | // SerializationBuffer, implementing gopacket.SerializableLayer. 64 | func (l *Loopback) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error { 65 | bytes, err := b.PrependBytes(4) 66 | if err != nil { 67 | return err 68 | } 69 | binary.LittleEndian.PutUint32(bytes, uint32(l.Family)) 70 | return nil 71 | } 72 | 73 | func decodeLoopback(data []byte, p gopacket.PacketBuilder) error { 74 | l := Loopback{} 75 | if err := l.DecodeFromBytes(data, gopacket.NilDecodeFeedback); err != nil { 76 | return err 77 | } 78 | p.AddLayer(&l) 79 | return p.NextDecoder(l.Family) 80 | } 81 | -------------------------------------------------------------------------------- /layers/mpls.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | package layers 8 | 9 | import ( 10 | "encoding/binary" 11 | "errors" 12 | "github.com/google/gopacket" 13 | ) 14 | 15 | // MPLS is the MPLS packet header. 16 | type MPLS struct { 17 | BaseLayer 18 | Label uint32 19 | TrafficClass uint8 20 | StackBottom bool 21 | TTL uint8 22 | } 23 | 24 | // LayerType returns gopacket.LayerTypeMPLS. 25 | func (m *MPLS) LayerType() gopacket.LayerType { return LayerTypeMPLS } 26 | 27 | // ProtocolGuessingDecoder attempts to guess the protocol of the bytes it's 28 | // given, then decode the packet accordingly. Its algorithm for guessing is: 29 | // If the packet starts with byte 0x45-0x4F: IPv4 30 | // If the packet starts with byte 0x60-0x6F: IPv6 31 | // Otherwise: Error 32 | // See draft-hsmit-isis-aal5mux-00.txt for more detail on this approach. 33 | type ProtocolGuessingDecoder struct{} 34 | 35 | func (ProtocolGuessingDecoder) Decode(data []byte, p gopacket.PacketBuilder) error { 36 | switch data[0] { 37 | // 0x40 | header_len, where header_len is at least 5. 38 | case 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f: 39 | return decodeIPv4(data, p) 40 | // IPv6 can start with any byte whose first 4 bits are 0x6. 41 | case 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f: 42 | return decodeIPv6(data, p) 43 | } 44 | return errors.New("Unable to guess protocol of packet data") 45 | } 46 | 47 | // MPLSPayloadDecoder is the decoder used to data encapsulated by each MPLS 48 | // layer. MPLS contains no type information, so we have to explicitly decide 49 | // which decoder to use. This is initially set to ProtocolGuessingDecoder, our 50 | // simple attempt at guessing protocols based on the first few bytes of data 51 | // available to us. However, if you know that in your environment MPLS always 52 | // encapsulates a specific protocol, you may reset this. 53 | var MPLSPayloadDecoder gopacket.Decoder = ProtocolGuessingDecoder{} 54 | 55 | func decodeMPLS(data []byte, p gopacket.PacketBuilder) error { 56 | decoded := binary.BigEndian.Uint32(data[:4]) 57 | mpls := &MPLS{ 58 | Label: decoded >> 12, 59 | TrafficClass: uint8(decoded>>9) & 0x7, 60 | StackBottom: decoded&0x100 != 0, 61 | TTL: uint8(decoded), 62 | BaseLayer: BaseLayer{data[:4], data[4:]}, 63 | } 64 | p.AddLayer(mpls) 65 | if mpls.StackBottom { 66 | return p.NextDecoder(MPLSPayloadDecoder) 67 | } 68 | return p.NextDecoder(gopacket.DecodeFunc(decodeMPLS)) 69 | } 70 | 71 | // SerializeTo writes the serialized form of this layer into the 72 | // SerializationBuffer, implementing gopacket.SerializableLayer. 73 | // See the docs for gopacket.SerializableLayer for more info. 74 | func (m *MPLS) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error { 75 | bytes, err := b.PrependBytes(4) 76 | if err != nil { 77 | return err 78 | } 79 | encoded := m.Label << 12 80 | encoded |= uint32(m.TrafficClass) << 9 81 | encoded |= uint32(m.TTL) 82 | if m.StackBottom { 83 | encoded |= 0x100 84 | } 85 | binary.BigEndian.PutUint32(bytes, encoded) 86 | return nil 87 | } 88 | -------------------------------------------------------------------------------- /layers/pflog.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | package layers 8 | 9 | import ( 10 | "encoding/binary" 11 | "errors" 12 | "fmt" 13 | 14 | "github.com/google/gopacket" 15 | ) 16 | 17 | type PFDirection uint8 18 | 19 | const ( 20 | PFDirectionInOut PFDirection = 0 21 | PFDirectionIn PFDirection = 1 22 | PFDirectionOut PFDirection = 2 23 | ) 24 | 25 | // PFLog provides the layer for 'pf' packet-filter logging, as described at 26 | // http://www.freebsd.org/cgi/man.cgi?query=pflog&sektion=4 27 | type PFLog struct { 28 | BaseLayer 29 | Length uint8 30 | Family ProtocolFamily 31 | Action, Reason uint8 32 | IFName, Ruleset []byte 33 | RuleNum, SubruleNum uint32 34 | UID uint32 35 | PID int32 36 | RuleUID uint32 37 | RulePID int32 38 | Direction PFDirection 39 | // The remainder is padding 40 | } 41 | 42 | func (pf *PFLog) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error { 43 | if len(data) < 60 { 44 | df.SetTruncated() 45 | return errors.New("PFLog data less than 60 bytes") 46 | } 47 | pf.Length = data[0] 48 | pf.Family = ProtocolFamily(data[1]) 49 | pf.Action = data[2] 50 | pf.Reason = data[3] 51 | pf.IFName = data[4:20] 52 | pf.Ruleset = data[20:36] 53 | pf.RuleNum = binary.BigEndian.Uint32(data[36:40]) 54 | pf.SubruleNum = binary.BigEndian.Uint32(data[40:44]) 55 | pf.UID = binary.BigEndian.Uint32(data[44:48]) 56 | pf.PID = int32(binary.BigEndian.Uint32(data[48:52])) 57 | pf.RuleUID = binary.BigEndian.Uint32(data[52:56]) 58 | pf.RulePID = int32(binary.BigEndian.Uint32(data[56:60])) 59 | pf.Direction = PFDirection(data[60]) 60 | if pf.Length%4 != 1 { 61 | return errors.New("PFLog header length should be 3 less than multiple of 4") 62 | } 63 | actualLength := int(pf.Length) + 3 64 | if len(data) < actualLength { 65 | return fmt.Errorf("PFLog data size < %d", actualLength) 66 | } 67 | pf.Contents = data[:actualLength] 68 | pf.Payload = data[actualLength:] 69 | return nil 70 | } 71 | 72 | // LayerType returns layers.LayerTypePFLog 73 | func (pf *PFLog) LayerType() gopacket.LayerType { return LayerTypePFLog } 74 | 75 | func (pf *PFLog) CanDecode() gopacket.LayerClass { return LayerTypePFLog } 76 | 77 | func (pf *PFLog) NextLayerType() gopacket.LayerType { 78 | return pf.Family.LayerType() 79 | } 80 | 81 | func decodePFLog(data []byte, p gopacket.PacketBuilder) error { 82 | pf := &PFLog{} 83 | return decodingLayerDecoder(pf, data, p) 84 | } 85 | -------------------------------------------------------------------------------- /layers/ppp.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | package layers 8 | 9 | import ( 10 | "encoding/binary" 11 | "errors" 12 | "github.com/google/gopacket" 13 | ) 14 | 15 | // PPP is the layer for PPP encapsulation headers. 16 | type PPP struct { 17 | BaseLayer 18 | PPPType PPPType 19 | HasPPTPHeader bool 20 | } 21 | 22 | // PPPEndpoint is a singleton endpoint for PPP. Since there is no actual 23 | // addressing for the two ends of a PPP connection, we use a singleton value 24 | // named 'point' for each endpoint. 25 | var PPPEndpoint = gopacket.NewEndpoint(EndpointPPP, nil) 26 | 27 | // PPPFlow is a singleton flow for PPP. Since there is no actual addressing for 28 | // the two ends of a PPP connection, we use a singleton value to represent the 29 | // flow for all PPP connections. 30 | var PPPFlow = gopacket.NewFlow(EndpointPPP, nil, nil) 31 | 32 | // LayerType returns LayerTypePPP 33 | func (p *PPP) LayerType() gopacket.LayerType { return LayerTypePPP } 34 | 35 | // LinkFlow returns PPPFlow. 36 | func (p *PPP) LinkFlow() gopacket.Flow { return PPPFlow } 37 | 38 | func decodePPP(data []byte, p gopacket.PacketBuilder) error { 39 | ppp := &PPP{} 40 | offset := 0 41 | if data[0] == 0xff && data[1] == 0x03 { 42 | offset = 2 43 | ppp.HasPPTPHeader = true 44 | } 45 | if data[offset]&0x1 == 0 { 46 | if data[offset+1]&0x1 == 0 { 47 | return errors.New("PPP has invalid type") 48 | } 49 | ppp.PPPType = PPPType(binary.BigEndian.Uint16(data[offset : offset+2])) 50 | ppp.Contents = data[offset : offset+2] 51 | ppp.Payload = data[offset+2:] 52 | } else { 53 | ppp.PPPType = PPPType(data[offset]) 54 | ppp.Contents = data[offset : offset+1] 55 | ppp.Payload = data[offset+1:] 56 | } 57 | p.AddLayer(ppp) 58 | p.SetLinkLayer(ppp) 59 | return p.NextDecoder(ppp.PPPType) 60 | } 61 | 62 | // SerializeTo writes the serialized form of this layer into the 63 | // SerializationBuffer, implementing gopacket.SerializableLayer. 64 | // See the docs for gopacket.SerializableLayer for more info. 65 | func (p *PPP) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error { 66 | if p.PPPType&0x100 == 0 { 67 | bytes, err := b.PrependBytes(2) 68 | if err != nil { 69 | return err 70 | } 71 | binary.BigEndian.PutUint16(bytes, uint16(p.PPPType)) 72 | } else { 73 | bytes, err := b.PrependBytes(1) 74 | if err != nil { 75 | return err 76 | } 77 | bytes[0] = uint8(p.PPPType) 78 | } 79 | if p.HasPPTPHeader { 80 | bytes, err := b.PrependBytes(2) 81 | if err != nil { 82 | return err 83 | } 84 | bytes[0] = 0xff 85 | bytes[1] = 0x03 86 | } 87 | return nil 88 | } 89 | -------------------------------------------------------------------------------- /layers/pppoe.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | package layers 8 | 9 | import ( 10 | "encoding/binary" 11 | "github.com/google/gopacket" 12 | ) 13 | 14 | // PPPoE is the layer for PPPoE encapsulation headers. 15 | type PPPoE struct { 16 | BaseLayer 17 | Version uint8 18 | Type uint8 19 | Code PPPoECode 20 | SessionId uint16 21 | Length uint16 22 | } 23 | 24 | // LayerType returns gopacket.LayerTypePPPoE. 25 | func (p *PPPoE) LayerType() gopacket.LayerType { 26 | return LayerTypePPPoE 27 | } 28 | 29 | // decodePPPoE decodes the PPPoE header (see http://tools.ietf.org/html/rfc2516). 30 | func decodePPPoE(data []byte, p gopacket.PacketBuilder) error { 31 | pppoe := &PPPoE{ 32 | Version: data[0] >> 4, 33 | Type: data[0] & 0x0F, 34 | Code: PPPoECode(data[1]), 35 | SessionId: binary.BigEndian.Uint16(data[2:4]), 36 | Length: binary.BigEndian.Uint16(data[4:6]), 37 | } 38 | pppoe.BaseLayer = BaseLayer{data[:6], data[6 : 6+pppoe.Length]} 39 | p.AddLayer(pppoe) 40 | return p.NextDecoder(pppoe.Code) 41 | } 42 | 43 | // SerializeTo writes the serialized form of this layer into the 44 | // SerializationBuffer, implementing gopacket.SerializableLayer. 45 | // See the docs for gopacket.SerializableLayer for more info. 46 | func (p *PPPoE) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error { 47 | payload := b.Bytes() 48 | bytes, err := b.PrependBytes(6) 49 | if err != nil { 50 | return err 51 | } 52 | bytes[0] = (p.Version << 4) | p.Type 53 | bytes[1] = byte(p.Code) 54 | binary.BigEndian.PutUint16(bytes[2:], p.SessionId) 55 | if opts.FixLengths { 56 | p.Length = uint16(len(payload)) 57 | } 58 | binary.BigEndian.PutUint16(bytes[4:], p.Length) 59 | return nil 60 | } 61 | -------------------------------------------------------------------------------- /layers/radiotap_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | package layers 7 | 8 | import ( 9 | "github.com/google/gopacket" 10 | "testing" 11 | ) 12 | 13 | // testPacketRadiotap0 is the packet: 14 | // 09:34:34.799438 1.0 Mb/s 2412 MHz 11b -58dB signal antenna 7 Acknowledgment RA:88:1f:a1:ae:9d:cb 15 | // 0x0000: 0000 1200 2e48 0000 1002 6c09 a000 c607 .....H....l..... 16 | // 0x0010: 0000 d400 0000 881f a1ae 9dcb c630 4b4b .............0KK 17 | var testPacketRadiotap0 = []byte{ 18 | 0x00, 0x00, 0x12, 0x00, 0x2e, 0x48, 0x00, 0x00, 0x10, 0x02, 0x6c, 0x09, 0xa0, 0x00, 0xc6, 0x07, 19 | 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00, 0x88, 0x1f, 0xa1, 0xae, 0x9d, 0xcb, 0xc6, 0x30, 0x4b, 0x4b, 20 | } 21 | 22 | func TestPacketRadiotap0(t *testing.T) { 23 | p := gopacket.NewPacket(testPacketRadiotap0, LayerTypeRadioTap, gopacket.Default) 24 | if p.ErrorLayer() != nil { 25 | t.Error("Failed to decode packet:", p.ErrorLayer().Error()) 26 | } 27 | checkLayers(p, []gopacket.LayerType{LayerTypeRadioTap, LayerTypeDot11}, t) 28 | rt := p.Layer(LayerTypeRadioTap).(*RadioTap) 29 | if rt.ChannelFrequency != 2412 || rt.DBMAntennaSignal != -58 || rt.Antenna != 7 { 30 | t.Error("Radiotap decode error") 31 | } 32 | if rt.Rate != 2 { // 500Kbps unit 33 | t.Error("Radiotap Rate decode error") 34 | } 35 | } 36 | func BenchmarkDecodePacketRadiotap0(b *testing.B) { 37 | for i := 0; i < b.N; i++ { 38 | gopacket.NewPacket(testPacketRadiotap0, LayerTypeRadioTap, gopacket.NoCopy) 39 | } 40 | } 41 | 42 | // testPacketRadiotap1 is the packet: 43 | // 05:24:21.380948 2412 MHz 11g -36dB signal antenna 5 65.0 Mb/s MCS 7 20 MHz lon GI 44 | // 0x0000: 0000 1500 2a48 0800 1000 6c09 8004 dc05 ....*H....l..... 45 | // 0x0010: 0000 0700 0748 112c 0000 3a9d aaf0 191c .....H.,..:..... 46 | // 0x0020: aba7 f213 9d00 3a9d aaf0 1970 b2ee a9f1 ......:....p.... 47 | // 0x0030: 16 . 48 | var testPacketRadiotap1 = []byte{ 49 | 0x00, 0x00, 0x15, 0x00, 0x2a, 0x48, 0x08, 0x00, 0x10, 0x00, 0x6c, 0x09, 0x80, 0x04, 0xdc, 0x05, 50 | 0x00, 0x00, 0x07, 0x00, 0x07, 0x48, 0x11, 0x2c, 0x00, 0x00, 0x3a, 0x9d, 0xaa, 0xf0, 0x19, 0x1c, 51 | 0xab, 0xa7, 0xf2, 0x13, 0x9d, 0x00, 0x3a, 0x9d, 0xaa, 0xf0, 0x19, 0x70, 0xb2, 0xee, 0xa9, 0xf1, 52 | 0x16, 53 | } 54 | 55 | func TestPacketRadiotap1(t *testing.T) { 56 | p := gopacket.NewPacket(testPacketRadiotap1, LayerTypeRadioTap, gopacket.Default) 57 | if p.ErrorLayer() != nil { 58 | t.Error("Failed to decode packet:", p.ErrorLayer().Error()) 59 | } 60 | checkLayers(p, []gopacket.LayerType{LayerTypeRadioTap, LayerTypeDot11}, t) 61 | rt := p.Layer(LayerTypeRadioTap).(*RadioTap) 62 | if rt.ChannelFrequency != 2412 || rt.DBMAntennaSignal != -36 || rt.Antenna != 5 { 63 | t.Error("Radiotap decode error") 64 | } 65 | if !rt.MCS.Known.MCSIndex() || rt.MCS.MCS != 7 { 66 | t.Error("Radiotap MCS error") 67 | } 68 | if !rt.MCS.Known.Bandwidth() || rt.MCS.Flags.Bandwidth() != 0 { 69 | t.Error("Radiotap bandwidth error") 70 | } 71 | if !rt.MCS.Known.GuardInterval() || rt.MCS.Flags.ShortGI() { 72 | t.Error("Radiotap GI error") 73 | } 74 | } 75 | func BenchmarkDecodePacketRadiotap1(b *testing.B) { 76 | for i := 0; i < b.N; i++ { 77 | gopacket.NewPacket(testPacketRadiotap1, LayerTypeRadioTap, gopacket.NoCopy) 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /layers/rmcp_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The GoPacket Authors. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license that can be found 4 | // in the LICENSE file in the root of the source tree. 5 | 6 | package layers 7 | 8 | import ( 9 | "bytes" 10 | "encoding/hex" 11 | "testing" 12 | 13 | "github.com/google/gopacket" 14 | ) 15 | 16 | func TestRMCPDecodeFromBytes(t *testing.T) { 17 | b, err := hex.DecodeString("0600ff06") 18 | if err != nil { 19 | t.Fatalf("Failed to decode RMCP message") 20 | } 21 | 22 | rmcp := &RMCP{} 23 | if err := rmcp.DecodeFromBytes(b, gopacket.NilDecodeFeedback); err != nil { 24 | t.Fatalf("Unexpected error: %v", err) 25 | } 26 | if !bytes.Equal(rmcp.BaseLayer.Payload, []byte{}) { 27 | t.Errorf("payload is %v, want %v", rmcp.BaseLayer.Payload, b) 28 | } 29 | if !bytes.Equal(rmcp.BaseLayer.Contents, b) { 30 | t.Errorf("contents is %v, want %v", rmcp.BaseLayer.Contents, b) 31 | } 32 | if rmcp.Version != RMCPVersion1 { 33 | t.Errorf("version is %v, want %v", rmcp.Version, RMCPVersion1) 34 | } 35 | if rmcp.Sequence != 0xFF { 36 | t.Errorf("sequence is %v, want %v", rmcp.Sequence, 0xFF) 37 | } 38 | if rmcp.Ack { 39 | t.Errorf("ack is true, want false") 40 | } 41 | if rmcp.Class != RMCPClassASF { 42 | t.Errorf("class is %v, want %v", rmcp.Class, RMCPClassASF) 43 | } 44 | } 45 | 46 | func serializeRMCP(rmcp *RMCP) ([]byte, error) { 47 | sb := gopacket.NewSerializeBuffer() 48 | err := rmcp.SerializeTo(sb, gopacket.SerializeOptions{}) 49 | return sb.Bytes(), err 50 | } 51 | 52 | func TestRMCPTestSerializeTo(t *testing.T) { 53 | table := []struct { 54 | layer *RMCP 55 | want []byte 56 | }{ 57 | { 58 | &RMCP{ 59 | Version: RMCPVersion1, 60 | Sequence: 1, 61 | Ack: false, 62 | Class: RMCPClassASF, 63 | }, 64 | []byte{0x6, 0x0, 0x1, 0x6}, 65 | }, 66 | { 67 | &RMCP{ 68 | Version: RMCPVersion1, 69 | Sequence: 0xFF, 70 | Ack: true, 71 | Class: RMCPClassIPMI, 72 | }, 73 | []byte{0x6, 0x0, 0xFF, 0x87}, 74 | }, 75 | } 76 | for _, test := range table { 77 | b, err := serializeRMCP(test.layer) 78 | switch { 79 | case err != nil && test.want != nil: 80 | t.Errorf("serialize %v failed with %v, wanted %v", test.layer, 81 | err, test.want) 82 | case err == nil && !bytes.Equal(b, test.want): 83 | t.Errorf("serialize %v = %v, want %v", test.layer, b, test.want) 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /layers/rudp.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | package layers 8 | 9 | import ( 10 | "encoding/binary" 11 | "fmt" 12 | "github.com/google/gopacket" 13 | ) 14 | 15 | type RUDP struct { 16 | BaseLayer 17 | SYN, ACK, EACK, RST, NUL bool 18 | Version uint8 19 | HeaderLength uint8 20 | SrcPort, DstPort RUDPPort 21 | DataLength uint16 22 | Seq, Ack, Checksum uint32 23 | VariableHeaderArea []byte 24 | // RUDPHeaderSyn contains SYN information for the RUDP packet, 25 | // if the SYN flag is set 26 | *RUDPHeaderSYN 27 | // RUDPHeaderEack contains EACK information for the RUDP packet, 28 | // if the EACK flag is set. 29 | *RUDPHeaderEACK 30 | } 31 | 32 | type RUDPHeaderSYN struct { 33 | MaxOutstandingSegments, MaxSegmentSize, OptionFlags uint16 34 | } 35 | 36 | type RUDPHeaderEACK struct { 37 | SeqsReceivedOK []uint32 38 | } 39 | 40 | // LayerType returns gopacket.LayerTypeRUDP. 41 | func (r *RUDP) LayerType() gopacket.LayerType { return LayerTypeRUDP } 42 | 43 | func decodeRUDP(data []byte, p gopacket.PacketBuilder) error { 44 | r := &RUDP{ 45 | SYN: data[0]&0x80 != 0, 46 | ACK: data[0]&0x40 != 0, 47 | EACK: data[0]&0x20 != 0, 48 | RST: data[0]&0x10 != 0, 49 | NUL: data[0]&0x08 != 0, 50 | Version: data[0] & 0x3, 51 | HeaderLength: data[1], 52 | SrcPort: RUDPPort(data[2]), 53 | DstPort: RUDPPort(data[3]), 54 | DataLength: binary.BigEndian.Uint16(data[4:6]), 55 | Seq: binary.BigEndian.Uint32(data[6:10]), 56 | Ack: binary.BigEndian.Uint32(data[10:14]), 57 | Checksum: binary.BigEndian.Uint32(data[14:18]), 58 | } 59 | if r.HeaderLength < 9 { 60 | return fmt.Errorf("RUDP packet with too-short header length %d", r.HeaderLength) 61 | } 62 | hlen := int(r.HeaderLength) * 2 63 | r.Contents = data[:hlen] 64 | r.Payload = data[hlen : hlen+int(r.DataLength)] 65 | r.VariableHeaderArea = data[18:hlen] 66 | headerData := r.VariableHeaderArea 67 | switch { 68 | case r.SYN: 69 | if len(headerData) != 6 { 70 | return fmt.Errorf("RUDP packet invalid SYN header length: %d", len(headerData)) 71 | } 72 | r.RUDPHeaderSYN = &RUDPHeaderSYN{ 73 | MaxOutstandingSegments: binary.BigEndian.Uint16(headerData[:2]), 74 | MaxSegmentSize: binary.BigEndian.Uint16(headerData[2:4]), 75 | OptionFlags: binary.BigEndian.Uint16(headerData[4:6]), 76 | } 77 | case r.EACK: 78 | if len(headerData)%4 != 0 { 79 | return fmt.Errorf("RUDP packet invalid EACK header length: %d", len(headerData)) 80 | } 81 | r.RUDPHeaderEACK = &RUDPHeaderEACK{make([]uint32, len(headerData)/4)} 82 | for i := 0; i < len(headerData); i += 4 { 83 | r.SeqsReceivedOK[i/4] = binary.BigEndian.Uint32(headerData[i : i+4]) 84 | } 85 | } 86 | p.AddLayer(r) 87 | p.SetTransportLayer(r) 88 | return p.NextDecoder(gopacket.LayerTypePayload) 89 | } 90 | 91 | func (r *RUDP) TransportFlow() gopacket.Flow { 92 | return gopacket.NewFlow(EndpointRUDPPort, []byte{byte(r.SrcPort)}, []byte{byte(r.DstPort)}) 93 | } 94 | -------------------------------------------------------------------------------- /layers/tcp_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016, Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | package layers 8 | 9 | import ( 10 | "reflect" 11 | "testing" 12 | 13 | "github.com/google/gopacket" 14 | ) 15 | 16 | func TestTCPOptionKindString(t *testing.T) { 17 | testData := []struct { 18 | o *TCPOption 19 | s string 20 | }{ 21 | {&TCPOption{ 22 | OptionType: TCPOptionKindNop, 23 | OptionLength: 1, 24 | }, 25 | "TCPOption(NOP:)"}, 26 | {&TCPOption{ 27 | OptionType: TCPOptionKindMSS, 28 | OptionLength: 4, 29 | OptionData: []byte{0x12, 0x34}, 30 | }, 31 | "TCPOption(MSS:4660 0x1234)"}, 32 | {&TCPOption{ 33 | OptionType: TCPOptionKindTimestamps, 34 | OptionLength: 10, 35 | OptionData: []byte{0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01}, 36 | }, 37 | "TCPOption(Timestamps:2/1 0x0000000200000001)"}} 38 | 39 | for _, tc := range testData { 40 | if s := tc.o.String(); s != tc.s { 41 | t.Errorf("expected %#v string to be %s, got %s", tc.o, tc.s, s) 42 | } 43 | } 44 | } 45 | 46 | func TestTCPSerializePadding(t *testing.T) { 47 | tcp := &TCP{} 48 | tcp.Options = append(tcp.Options, TCPOption{ 49 | OptionType: TCPOptionKindNop, 50 | OptionLength: 1, 51 | }) 52 | buf := gopacket.NewSerializeBuffer() 53 | opts := gopacket.SerializeOptions{FixLengths: true} 54 | err := gopacket.SerializeLayers(buf, opts, tcp) 55 | if err != nil { 56 | t.Fatal(err) 57 | } 58 | if len(buf.Bytes())%4 != 0 { 59 | t.Errorf("TCP data of len %d not padding to 32 bit boundary", len(buf.Bytes())) 60 | } 61 | } 62 | 63 | // testPacketTCPOptionDecode is the packet: 64 | // 16:17:26.239051 IP 192.168.0.1.12345 > 192.168.0.2.54321: Flags [S], seq 3735928559:3735928563, win 0, options [mss 8192,eol], length 4 65 | // 0x0000: 0000 0000 0001 0000 0000 0001 0800 4500 ..............E. 66 | // 0x0010: 0034 0000 0000 8006 b970 c0a8 0001 c0a8 .4.......p...... 67 | // 0x0020: 0002 3039 d431 dead beef 0000 0000 7002 ..09.1........p. 68 | // 0x0030: 0000 829c 0000 0204 2000 0000 0000 5465 ..............Te 69 | // 0x0040: 7374 st 70 | var testPacketTCPOptionDecode = []byte{ 71 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x45, 0x00, 72 | 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x80, 0x06, 0xb9, 0x70, 0xc0, 0xa8, 0x00, 0x01, 0xc0, 0xa8, 73 | 0x00, 0x02, 0x30, 0x39, 0xd4, 0x31, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00, 0x70, 0x02, 74 | 0x00, 0x00, 0x82, 0x9c, 0x00, 0x00, 0x02, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x65, 75 | 0x73, 0x74, 76 | } 77 | 78 | func TestPacketTCPOptionDecode(t *testing.T) { 79 | p := gopacket.NewPacket(testPacketTCPOptionDecode, LinkTypeEthernet, gopacket.Default) 80 | if p.ErrorLayer() != nil { 81 | t.Error("Failed to decode packet:", p.ErrorLayer().Error()) 82 | } 83 | tcp := p.Layer(LayerTypeTCP).(*TCP) 84 | if tcp == nil { 85 | t.Error("Expected TCP layer, but got none") 86 | } 87 | 88 | expected := []TCPOption{ 89 | { 90 | OptionType: TCPOptionKindMSS, 91 | OptionLength: 4, 92 | OptionData: []byte{32, 00}, 93 | }, 94 | { 95 | OptionType: TCPOptionKindEndList, 96 | OptionLength: 1, 97 | }, 98 | } 99 | 100 | if !reflect.DeepEqual(expected, tcp.Options) { 101 | t.Errorf("expected options to be %#v, but got %#v", expected, tcp.Options) 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /layers/tcpip.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google, Inc. All rights reserved. 2 | // Copyright 2009-2011 Andreas Krennmair. All rights reserved. 3 | // 4 | // Use of this source code is governed by a BSD-style license 5 | // that can be found in the LICENSE file in the root of the source 6 | // tree. 7 | 8 | package layers 9 | 10 | import ( 11 | "errors" 12 | "fmt" 13 | 14 | "github.com/google/gopacket" 15 | ) 16 | 17 | // Checksum computation for TCP/UDP. 18 | type tcpipchecksum struct { 19 | pseudoheader tcpipPseudoHeader 20 | } 21 | 22 | type tcpipPseudoHeader interface { 23 | pseudoheaderChecksum() (uint32, error) 24 | } 25 | 26 | func (ip *IPv4) pseudoheaderChecksum() (csum uint32, err error) { 27 | if err := ip.AddressTo4(); err != nil { 28 | return 0, err 29 | } 30 | csum += (uint32(ip.SrcIP[0]) + uint32(ip.SrcIP[2])) << 8 31 | csum += uint32(ip.SrcIP[1]) + uint32(ip.SrcIP[3]) 32 | csum += (uint32(ip.DstIP[0]) + uint32(ip.DstIP[2])) << 8 33 | csum += uint32(ip.DstIP[1]) + uint32(ip.DstIP[3]) 34 | return csum, nil 35 | } 36 | 37 | func (ip *IPv6) pseudoheaderChecksum() (csum uint32, err error) { 38 | if err := ip.AddressTo16(); err != nil { 39 | return 0, err 40 | } 41 | for i := 0; i < 16; i += 2 { 42 | csum += uint32(ip.SrcIP[i]) << 8 43 | csum += uint32(ip.SrcIP[i+1]) 44 | csum += uint32(ip.DstIP[i]) << 8 45 | csum += uint32(ip.DstIP[i+1]) 46 | } 47 | return csum, nil 48 | } 49 | 50 | // Calculate the TCP/IP checksum defined in rfc1071. The passed-in csum is any 51 | // initial checksum data that's already been computed. 52 | func tcpipChecksum(data []byte, csum uint32) uint16 { 53 | // to handle odd lengths, we loop to length - 1, incrementing by 2, then 54 | // handle the last byte specifically by checking against the original 55 | // length. 56 | length := len(data) - 1 57 | for i := 0; i < length; i += 2 { 58 | // For our test packet, doing this manually is about 25% faster 59 | // (740 ns vs. 1000ns) than doing it by calling binary.BigEndian.Uint16. 60 | csum += uint32(data[i]) << 8 61 | csum += uint32(data[i+1]) 62 | } 63 | if len(data)%2 == 1 { 64 | csum += uint32(data[length]) << 8 65 | } 66 | for csum > 0xffff { 67 | csum = (csum >> 16) + (csum & 0xffff) 68 | } 69 | return ^uint16(csum) 70 | } 71 | 72 | // computeChecksum computes a TCP or UDP checksum. headerAndPayload is the 73 | // serialized TCP or UDP header plus its payload, with the checksum zero'd 74 | // out. headerProtocol is the IP protocol number of the upper-layer header. 75 | func (c *tcpipchecksum) computeChecksum(headerAndPayload []byte, headerProtocol IPProtocol) (uint16, error) { 76 | if c.pseudoheader == nil { 77 | return 0, errors.New("TCP/IP layer 4 checksum cannot be computed without network layer... call SetNetworkLayerForChecksum to set which layer to use") 78 | } 79 | length := uint32(len(headerAndPayload)) 80 | csum, err := c.pseudoheader.pseudoheaderChecksum() 81 | if err != nil { 82 | return 0, err 83 | } 84 | csum += uint32(headerProtocol) 85 | csum += length & 0xffff 86 | csum += length >> 16 87 | return tcpipChecksum(headerAndPayload, csum), nil 88 | } 89 | 90 | // SetNetworkLayerForChecksum tells this layer which network layer is wrapping it. 91 | // This is needed for computing the checksum when serializing, since TCP/IP transport 92 | // layer checksums depends on fields in the IPv4 or IPv6 layer that contains it. 93 | // The passed in layer must be an *IPv4 or *IPv6. 94 | func (i *tcpipchecksum) SetNetworkLayerForChecksum(l gopacket.NetworkLayer) error { 95 | switch v := l.(type) { 96 | case *IPv4: 97 | i.pseudoheader = v 98 | case *IPv6: 99 | i.pseudoheader = v 100 | default: 101 | return fmt.Errorf("cannot use layer type %v for tcp checksum network layer", l.LayerType()) 102 | } 103 | return nil 104 | } 105 | -------------------------------------------------------------------------------- /layers/testdata/fuzz/FuzzDecodeFromBytes/27d23183d8ce7b719228870c23869cf21bf8829d7160c82da88f80aeff2d861c: -------------------------------------------------------------------------------- 1 | go test fuzz v1 2 | []byte("0000000\x10\x10\x00\x01\x01\x01\x01\x01\x01\x00") 3 | -------------------------------------------------------------------------------- /layers/testdata/fuzz/FuzzDecodeFromBytes/3b53f220d321f20980b59f64e1617d6b334b152a90b141a7407c3c8fa4837a31: -------------------------------------------------------------------------------- 1 | go test fuzz v1 2 | []byte("000000000000\x00") 3 | -------------------------------------------------------------------------------- /layers/testdata/fuzz/FuzzDecodeFromBytes/f539b7a397cf68c2129abd63d4c7cfb1979c489ad9bad6898510a4d4759bb85f: -------------------------------------------------------------------------------- 1 | go test fuzz v1 2 | []byte("01000\x10\x10\xdfd\x01\x01\x01\x00d\x01\x01\x01\x00") 3 | -------------------------------------------------------------------------------- /layers/testdata/fuzz/FuzzDecodeFromBytes/fe20300d6b2057b406a06ec4f04065f6d0dda6b2b362c0a89192c1933e927adf: -------------------------------------------------------------------------------- 1 | go test fuzz v1 2 | []byte("0000\x00\x00000000\x010\x000") 3 | -------------------------------------------------------------------------------- /layers/tls_appdata.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The GoPacket Authors. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | package layers 8 | 9 | import ( 10 | "errors" 11 | 12 | "github.com/google/gopacket" 13 | ) 14 | 15 | // TLSAppDataRecord contains all the information that each AppData Record types should have 16 | type TLSAppDataRecord struct { 17 | TLSRecordHeader 18 | Payload []byte 19 | } 20 | 21 | // DecodeFromBytes decodes the slice into the TLS struct. 22 | func (t *TLSAppDataRecord) decodeFromBytes(h TLSRecordHeader, data []byte, df gopacket.DecodeFeedback) error { 23 | // TLS Record Header 24 | t.ContentType = h.ContentType 25 | t.Version = h.Version 26 | t.Length = h.Length 27 | 28 | if len(data) != int(t.Length) { 29 | return errors.New("TLS Application Data length mismatch") 30 | } 31 | 32 | t.Payload = data 33 | return nil 34 | } 35 | -------------------------------------------------------------------------------- /layers/tls_cipherspec.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The GoPacket Authors. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | package layers 8 | 9 | import ( 10 | "errors" 11 | 12 | "github.com/google/gopacket" 13 | ) 14 | 15 | // TLSchangeCipherSpec defines the message value inside ChangeCipherSpec Record 16 | type TLSchangeCipherSpec uint8 17 | 18 | const ( 19 | TLSChangecipherspecMessage TLSchangeCipherSpec = 1 20 | TLSChangecipherspecUnknown TLSchangeCipherSpec = 255 21 | ) 22 | 23 | // TLS Change Cipher Spec 24 | // 0 1 2 3 4 5 6 7 8 25 | // +--+--+--+--+--+--+--+--+ 26 | // | Message | 27 | // +--+--+--+--+--+--+--+--+ 28 | 29 | // TLSChangeCipherSpecRecord defines the type of data inside ChangeCipherSpec Record 30 | type TLSChangeCipherSpecRecord struct { 31 | TLSRecordHeader 32 | 33 | Message TLSchangeCipherSpec 34 | } 35 | 36 | // DecodeFromBytes decodes the slice into the TLS struct. 37 | func (t *TLSChangeCipherSpecRecord) decodeFromBytes(h TLSRecordHeader, data []byte, df gopacket.DecodeFeedback) error { 38 | // TLS Record Header 39 | t.ContentType = h.ContentType 40 | t.Version = h.Version 41 | t.Length = h.Length 42 | 43 | if len(data) != 1 { 44 | df.SetTruncated() 45 | return errors.New("TLS Change Cipher Spec record incorrect length") 46 | } 47 | 48 | t.Message = TLSchangeCipherSpec(data[0]) 49 | if t.Message != TLSChangecipherspecMessage { 50 | t.Message = TLSChangecipherspecUnknown 51 | } 52 | 53 | return nil 54 | } 55 | 56 | // String shows the message value nicely formatted 57 | func (ccs TLSchangeCipherSpec) String() string { 58 | switch ccs { 59 | default: 60 | return "Unknown" 61 | case TLSChangecipherspecMessage: 62 | return "Change Cipher Spec Message" 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /layers/tls_handshake.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The GoPacket Authors. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | package layers 8 | 9 | import ( 10 | "github.com/google/gopacket" 11 | ) 12 | 13 | // TLSHandshakeRecord defines the structure of a Handshare Record 14 | type TLSHandshakeRecord struct { 15 | TLSRecordHeader 16 | } 17 | 18 | // DecodeFromBytes decodes the slice into the TLS struct. 19 | func (t *TLSHandshakeRecord) decodeFromBytes(h TLSRecordHeader, data []byte, df gopacket.DecodeFeedback) error { 20 | // TLS Record Header 21 | t.ContentType = h.ContentType 22 | t.Version = h.Version 23 | t.Length = h.Length 24 | 25 | // TODO 26 | 27 | return nil 28 | } 29 | -------------------------------------------------------------------------------- /layers/udplite.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google, Inc. All rights reserved. 2 | // Copyright 2009-2011 Andreas Krennmair. All rights reserved. 3 | // 4 | // Use of this source code is governed by a BSD-style license 5 | // that can be found in the LICENSE file in the root of the source 6 | // tree. 7 | 8 | package layers 9 | 10 | import ( 11 | "encoding/binary" 12 | "github.com/google/gopacket" 13 | ) 14 | 15 | // UDPLite is the layer for UDP-Lite headers (rfc 3828). 16 | type UDPLite struct { 17 | BaseLayer 18 | SrcPort, DstPort UDPLitePort 19 | ChecksumCoverage uint16 20 | Checksum uint16 21 | sPort, dPort []byte 22 | } 23 | 24 | // LayerType returns gopacket.LayerTypeUDPLite 25 | func (u *UDPLite) LayerType() gopacket.LayerType { return LayerTypeUDPLite } 26 | 27 | func decodeUDPLite(data []byte, p gopacket.PacketBuilder) error { 28 | udp := &UDPLite{ 29 | SrcPort: UDPLitePort(binary.BigEndian.Uint16(data[0:2])), 30 | sPort: data[0:2], 31 | DstPort: UDPLitePort(binary.BigEndian.Uint16(data[2:4])), 32 | dPort: data[2:4], 33 | ChecksumCoverage: binary.BigEndian.Uint16(data[4:6]), 34 | Checksum: binary.BigEndian.Uint16(data[6:8]), 35 | BaseLayer: BaseLayer{data[:8], data[8:]}, 36 | } 37 | p.AddLayer(udp) 38 | p.SetTransportLayer(udp) 39 | return p.NextDecoder(gopacket.LayerTypePayload) 40 | } 41 | 42 | func (u *UDPLite) TransportFlow() gopacket.Flow { 43 | return gopacket.NewFlow(EndpointUDPLitePort, u.sPort, u.dPort) 44 | } 45 | -------------------------------------------------------------------------------- /layers/usb_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014, Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | package layers 8 | 9 | import ( 10 | _ "fmt" 11 | "github.com/google/gopacket" 12 | "reflect" 13 | "testing" 14 | ) 15 | 16 | // Generator python layers/test_creator.py --link_type USB --name USB dongle.pcap 17 | // http://wiki.wireshark.org/SampleCaptures#Sample_Captures 18 | 19 | // testPacketUSB0 is the packet: 20 | // 02:41:04.689546 INTERRUPT COMPLETE to 2:1:1 21 | // 0x0000: 0038 4a3b 0088 ffff 4301 8101 0200 2d00 .8J;....C.....-. 22 | // 0x0010: c0d3 5b50 0000 0000 8a85 0a00 0000 0000 ..[P............ 23 | // 0x0020: 0100 0000 0100 0000 0000 0000 0000 0000 ................ 24 | // 0x0030: 8000 0000 0000 0000 0002 0000 0000 0000 ................ 25 | // 0x0040: 04 . 26 | var testPacketUSB0 = []byte{ 27 | 0x00, 0x38, 0x4a, 0x3b, 0x00, 0x88, 0xff, 0xff, 0x43, 0x01, 0x81, 0x01, 0x02, 0x00, 0x2d, 0x00, 28 | 0xc0, 0xd3, 0x5b, 0x50, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x85, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 29 | 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 30 | 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 31 | 0x04, 32 | } 33 | 34 | func TestPacketUSB0(t *testing.T) { 35 | p := gopacket.NewPacket(testPacketUSB0, LinkTypeLinuxUSB, gopacket.Default) 36 | if p.ErrorLayer() != nil { 37 | t.Error("Failed to decode packet:", p.ErrorLayer().Error()) 38 | } 39 | checkLayers(p, []gopacket.LayerType{LayerTypeUSB, LayerTypeUSBInterrupt}, t) 40 | 41 | if got, ok := p.Layer(LayerTypeUSB).(*USB); ok { 42 | want := &USB{ 43 | BaseLayer: BaseLayer{ 44 | Contents: []uint8{0x0, 0x38, 0x4a, 0x3b, 0x0, 0x88, 0xff, 0xff, 0x43, 0x1, 0x81, 0x1, 0x2, 0x0, 0x2d, 0x0, 0xc0, 0xd3, 0x5b, 0x50, 0x0, 0x0, 0x0, 0x0, 0x8a, 0x85, 0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0}, 45 | Payload: []uint8{0x4}, 46 | }, 47 | ID: 0xffff88003b4a3800, 48 | EventType: USBEventTypeComplete, 49 | TransferType: USBTransportTypeInterrupt, 50 | Direction: 0x1, 51 | EndpointNumber: 0x1, 52 | DeviceAddress: 0x1, 53 | BusID: 0x2, 54 | TimestampSec: 1348195264, 55 | TimestampUsec: 689546, 56 | Setup: false, 57 | Data: true, 58 | Status: 0, 59 | UrbLength: 0x1, 60 | UrbDataLength: 0x1, 61 | } 62 | 63 | if !reflect.DeepEqual(got, want) { 64 | t.Errorf("USB packet processing failed:\ngot :\n%#v\n\nwant :\n%#v\n\n", got, want) 65 | } 66 | } 67 | 68 | } 69 | func BenchmarkDecodePacketUSB0(b *testing.B) { 70 | for i := 0; i < b.N; i++ { 71 | gopacket.NewPacket(testPacketUSB0, LinkTypeLinuxUSB, gopacket.NoCopy) 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /layers/vrrp_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | package layers 7 | 8 | import ( 9 | "github.com/google/gopacket" 10 | "testing" 11 | ) 12 | 13 | // vrrpPacketPriority100 is the packet: 14 | // 06:12:21.813317 IP 192.168.0.30 > 224.0.0.18: VRRPv2, Advertisement, vrid 1, prio 100, authtype none, intvl 1s, length 20 15 | // 0x0000: 0100 5e00 0012 0000 5e00 0101 0800 45c0 ..^.....^.....E. 16 | // 0x0010: 0028 0000 0000 ff70 19cd c0a8 001e e000 .(.....p........ 17 | // 0x0020: 0012 2101 6401 0001 ba52 c0a8 0001 0000 ..!.d....R...... 18 | // 0x0030: 0000 0000 0000 0000 0000 0000 ............ 19 | var vrrpPacketPriority100 = []byte{ 20 | 0x01, 0x00, 0x5e, 0x00, 0x00, 0x12, 0x00, 0x00, 0x5e, 0x00, 0x01, 0x01, 0x08, 0x00, 0x45, 0xc0, 21 | 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0xff, 0x70, 0x19, 0xcd, 0xc0, 0xa8, 0x00, 0x1e, 0xe0, 0x00, 22 | 0x00, 0x12, 0x21, 0x01, 0x64, 0x01, 0x00, 0x01, 0xba, 0x52, 0xc0, 0xa8, 0x00, 0x01, 0x00, 0x00, 23 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 24 | } 25 | 26 | func TestVRRPPacketPacket0(t *testing.T) { 27 | p := gopacket.NewPacket(vrrpPacketPriority100, LinkTypeEthernet, gopacket.Default) 28 | if p.ErrorLayer() != nil { 29 | t.Error("Failed to decode packet", p.ErrorLayer().Error()) 30 | } 31 | checkLayers(p, []gopacket.LayerType{LayerTypeEthernet, LayerTypeIPv4, LayerTypeVRRP}, t) 32 | 33 | // Version=2 Type=VRRPv2 Advertisement VirtualRtrID=1 Priority=100 34 | vrrp := p.Layer(LayerTypeVRRP).(*VRRPv2) 35 | if vrrp.Version != 2 { 36 | t.Fatalf("Unable to decode VRRPv2 version. Received %d, expected %d", vrrp.Version, 2) 37 | } 38 | 39 | if vrrp.Type != 1 { 40 | t.Fatalf("Unable to decode VRRPv2 type. Received %d, expected %d", vrrp.Type, 1) 41 | } 42 | 43 | if vrrp.Priority != 100 { 44 | t.Fatalf("Unable to decode VRRPv2 priority. Received %d, expected %d", vrrp.Priority, 100) 45 | } 46 | 47 | if vrrp.Checksum != 47698 { 48 | t.Fatalf("Unable to decode VRRPv2 checksum. Received %d, expected %d", vrrp.Checksum, 47698) 49 | } 50 | } 51 | func BenchmarkDecodeVRRPPacket0(b *testing.B) { 52 | for i := 0; i < b.N; i++ { 53 | gopacket.NewPacket(vrrpPacketPriority100, LayerTypeEthernet, gopacket.NoCopy) 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /layers_decoder.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The GoPacket Authors. All rights reserved. 2 | 3 | package gopacket 4 | 5 | // Created by gen.go, don't edit manually 6 | // Generated at 2019-06-18 11:37:31.308731293 +0600 +06 m=+0.000842599 7 | 8 | // LayersDecoder returns DecodingLayerFunc for specified 9 | // DecodingLayerContainer, LayerType value to start decoding with and 10 | // some DecodeFeedback. 11 | func LayersDecoder(dl DecodingLayerContainer, first LayerType, df DecodeFeedback) DecodingLayerFunc { 12 | firstDec, ok := dl.Decoder(first) 13 | if !ok { 14 | return func([]byte, *[]LayerType) (LayerType, error) { 15 | return first, nil 16 | } 17 | } 18 | if dlc, ok := dl.(DecodingLayerSparse); ok { 19 | return func(data []byte, decoded *[]LayerType) (LayerType, error) { 20 | *decoded = (*decoded)[:0] // Truncated decoded layers. 21 | typ := first 22 | decoder := firstDec 23 | for { 24 | if err := decoder.DecodeFromBytes(data, df); err != nil { 25 | return LayerTypeZero, err 26 | } 27 | *decoded = append(*decoded, typ) 28 | typ = decoder.NextLayerType() 29 | if data = decoder.LayerPayload(); len(data) == 0 { 30 | break 31 | } 32 | if decoder, ok = dlc.Decoder(typ); !ok { 33 | return typ, nil 34 | } 35 | } 36 | return LayerTypeZero, nil 37 | } 38 | } 39 | if dlc, ok := dl.(DecodingLayerArray); ok { 40 | return func(data []byte, decoded *[]LayerType) (LayerType, error) { 41 | *decoded = (*decoded)[:0] // Truncated decoded layers. 42 | typ := first 43 | decoder := firstDec 44 | for { 45 | if err := decoder.DecodeFromBytes(data, df); err != nil { 46 | return LayerTypeZero, err 47 | } 48 | *decoded = append(*decoded, typ) 49 | typ = decoder.NextLayerType() 50 | if data = decoder.LayerPayload(); len(data) == 0 { 51 | break 52 | } 53 | if decoder, ok = dlc.Decoder(typ); !ok { 54 | return typ, nil 55 | } 56 | } 57 | return LayerTypeZero, nil 58 | } 59 | } 60 | if dlc, ok := dl.(DecodingLayerMap); ok { 61 | return func(data []byte, decoded *[]LayerType) (LayerType, error) { 62 | *decoded = (*decoded)[:0] // Truncated decoded layers. 63 | typ := first 64 | decoder := firstDec 65 | for { 66 | if err := decoder.DecodeFromBytes(data, df); err != nil { 67 | return LayerTypeZero, err 68 | } 69 | *decoded = append(*decoded, typ) 70 | typ = decoder.NextLayerType() 71 | if data = decoder.LayerPayload(); len(data) == 0 { 72 | break 73 | } 74 | if decoder, ok = dlc.Decoder(typ); !ok { 75 | return typ, nil 76 | } 77 | } 78 | return LayerTypeZero, nil 79 | } 80 | } 81 | dlc := dl 82 | return func(data []byte, decoded *[]LayerType) (LayerType, error) { 83 | *decoded = (*decoded)[:0] // Truncated decoded layers. 84 | typ := first 85 | decoder := firstDec 86 | for { 87 | if err := decoder.DecodeFromBytes(data, df); err != nil { 88 | return LayerTypeZero, err 89 | } 90 | *decoded = append(*decoded, typ) 91 | typ = decoder.NextLayerType() 92 | if data = decoder.LayerPayload(); len(data) == 0 { 93 | break 94 | } 95 | if decoder, ok = dlc.Decoder(typ); !ok { 96 | return typ, nil 97 | } 98 | } 99 | return LayerTypeZero, nil 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /layertype.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | package gopacket 8 | 9 | import ( 10 | "fmt" 11 | "strconv" 12 | ) 13 | 14 | // LayerType is a unique identifier for each type of layer. This enumeration 15 | // does not match with any externally available numbering scheme... it's solely 16 | // usable/useful within this library as a means for requesting layer types 17 | // (see Packet.Layer) and determining which types of layers have been decoded. 18 | // 19 | // New LayerTypes may be created by calling gopacket.RegisterLayerType. 20 | type LayerType int64 21 | 22 | // LayerTypeMetadata contains metadata associated with each LayerType. 23 | type LayerTypeMetadata struct { 24 | // Name is the string returned by each layer type's String method. 25 | Name string 26 | // Decoder is the decoder to use when the layer type is passed in as a 27 | // Decoder. 28 | Decoder Decoder 29 | } 30 | 31 | type layerTypeMetadata struct { 32 | inUse bool 33 | LayerTypeMetadata 34 | } 35 | 36 | // DecodersByLayerName maps layer names to decoders for those layers. 37 | // This allows users to specify decoders by name to a program and have that 38 | // program pick the correct decoder accordingly. 39 | var DecodersByLayerName = map[string]Decoder{} 40 | 41 | const maxLayerType = 2000 42 | 43 | var ltMeta [maxLayerType]layerTypeMetadata 44 | var ltMetaMap = map[LayerType]layerTypeMetadata{} 45 | 46 | // RegisterLayerType creates a new layer type and registers it globally. 47 | // The number passed in must be unique, or a runtime panic will occur. Numbers 48 | // 0-999 are reserved for the gopacket library. Numbers 1000-1999 should be 49 | // used for common application-specific types, and are very fast. Any other 50 | // number (negative or >= 2000) may be used for uncommon application-specific 51 | // types, and are somewhat slower (they require a map lookup over an array 52 | // index). 53 | func RegisterLayerType(num int, meta LayerTypeMetadata) LayerType { 54 | if 0 <= num && num < maxLayerType { 55 | if ltMeta[num].inUse { 56 | panic("Layer type already exists") 57 | } 58 | } else { 59 | if ltMetaMap[LayerType(num)].inUse { 60 | panic("Layer type already exists") 61 | } 62 | } 63 | return OverrideLayerType(num, meta) 64 | } 65 | 66 | // OverrideLayerType acts like RegisterLayerType, except that if the layer type 67 | // has already been registered, it overrides the metadata with the passed-in 68 | // metadata intead of panicing. 69 | func OverrideLayerType(num int, meta LayerTypeMetadata) LayerType { 70 | if 0 <= num && num < maxLayerType { 71 | ltMeta[num] = layerTypeMetadata{ 72 | inUse: true, 73 | LayerTypeMetadata: meta, 74 | } 75 | } else { 76 | ltMetaMap[LayerType(num)] = layerTypeMetadata{ 77 | inUse: true, 78 | LayerTypeMetadata: meta, 79 | } 80 | } 81 | DecodersByLayerName[meta.Name] = meta.Decoder 82 | return LayerType(num) 83 | } 84 | 85 | // Decode decodes the given data using the decoder registered with the layer 86 | // type. 87 | func (t LayerType) Decode(data []byte, c PacketBuilder) error { 88 | var d Decoder 89 | if 0 <= int(t) && int(t) < maxLayerType { 90 | d = ltMeta[int(t)].Decoder 91 | } else { 92 | d = ltMetaMap[t].Decoder 93 | } 94 | if d != nil { 95 | return d.Decode(data, c) 96 | } 97 | return fmt.Errorf("Layer type %v has no associated decoder", t) 98 | } 99 | 100 | // String returns the string associated with this layer type. 101 | func (t LayerType) String() (s string) { 102 | if 0 <= int(t) && int(t) < maxLayerType { 103 | s = ltMeta[int(t)].Name 104 | } else { 105 | s = ltMetaMap[t].Name 106 | } 107 | if s == "" { 108 | s = strconv.Itoa(int(t)) 109 | } 110 | return 111 | } 112 | -------------------------------------------------------------------------------- /macs/benchmark_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | package macs 8 | 9 | import ( 10 | "testing" 11 | ) 12 | 13 | func BenchmarkCheckEthernetPrefix(b *testing.B) { 14 | key := [3]byte{5, 5, 5} 15 | for i := 0; i < b.N; i++ { 16 | _ = ValidMACPrefixMap[key] 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /macs/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | // Package macs provides an in-memory mapping of all valid Ethernet MAC address 8 | // prefixes to their associated organization. 9 | // 10 | // The ValidMACPrefixMap map maps 3-byte prefixes to organization strings. It 11 | // can be updated using 'go run gen.go' in this directory. 12 | package macs 13 | -------------------------------------------------------------------------------- /macs/gen.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | // +build ignore 8 | 9 | // This binary pulls the list of known MAC 10 | // prefixes from IEEE and writes them out to a go file which is compiled 11 | // into gopacket. It should be run as follows: 12 | // 13 | // go run gen.go | gofmt > valid_mac_prefixes.go 14 | package main 15 | 16 | import ( 17 | "bufio" 18 | "bytes" 19 | "encoding/hex" 20 | "flag" 21 | "fmt" 22 | "io" 23 | "net/http" 24 | "os" 25 | "regexp" 26 | "sort" 27 | "time" 28 | ) 29 | 30 | const header = `// Copyright 2012 Google, Inc. All rights reserved. 31 | // 32 | // Use of this source code is governed by a BSD-style license 33 | // that can be found in the LICENSE file in the root of the source 34 | // tree. 35 | 36 | package macs 37 | 38 | // Created by gen.go, don't edit manually 39 | // Generated at %s 40 | // Fetched from %q 41 | 42 | // ValidMACPrefixMap maps a valid MAC address prefix to the name of the 43 | // organization that owns the rights to use it. We map it to a hidden 44 | // variable so it won't show up in godoc, since it's a very large map. 45 | var ValidMACPrefixMap = validMACPrefixMap 46 | var validMACPrefixMap = map[[3]byte]string{ 47 | ` 48 | 49 | var url = flag.String("url", "http://standards-oui.ieee.org/oui/oui.txt", "URL to fetch MACs from") 50 | 51 | type mac struct { 52 | prefix [3]byte 53 | company string 54 | } 55 | 56 | type macs []mac 57 | 58 | func (m macs) Len() int { return len(m) } 59 | func (m macs) Less(i, j int) bool { return bytes.Compare(m[i].prefix[:], m[j].prefix[:]) < 0 } 60 | func (m macs) Swap(i, j int) { m[i], m[j] = m[j], m[i] } 61 | 62 | func main() { 63 | flag.Parse() 64 | fmt.Fprintf(os.Stderr, "Fetching MACs from %q\n", *url) 65 | resp, err := http.Get(*url) 66 | if err != nil { 67 | panic(err) 68 | } 69 | defer resp.Body.Close() 70 | buffered := bufio.NewReader(resp.Body) 71 | finder := regexp.MustCompile(`^\s*([0-9A-F]{6})\s+\(base 16\)\s+(.*\S)`) 72 | got := macs{} 73 | for { 74 | line, err := buffered.ReadString('\n') 75 | if err == io.EOF { 76 | break 77 | } else if err != nil { 78 | panic(err) 79 | } 80 | if matches := finder.FindStringSubmatch(line); matches != nil { 81 | var prefix [3]byte 82 | hex.Decode(prefix[:], []byte(matches[1])) 83 | company := matches[2] 84 | if company == "" { 85 | company = "PRIVATE" 86 | } 87 | fmt.Fprint(os.Stderr, "*") 88 | got = append(got, mac{prefix: prefix, company: company}) 89 | } 90 | } 91 | fmt.Fprintln(os.Stderr, "\nSorting macs") 92 | sort.Sort(got) 93 | fmt.Fprintln(os.Stderr, "Starting write to standard output") 94 | fmt.Printf(header, time.Now(), *url) 95 | for _, m := range got { 96 | fmt.Printf("\t[3]byte{%d, %d, %d}: %q,\n", m.prefix[0], m.prefix[1], m.prefix[2], m.company) 97 | } 98 | fmt.Println("}") 99 | } 100 | -------------------------------------------------------------------------------- /packet_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | package gopacket 8 | 9 | import ( 10 | "io" 11 | "reflect" 12 | "testing" 13 | ) 14 | 15 | type embedded struct { 16 | A, B int 17 | } 18 | 19 | type embedding struct { 20 | embedded 21 | C, D int 22 | } 23 | 24 | func TestDumpEmbedded(t *testing.T) { 25 | e := embedding{embedded: embedded{A: 1, B: 2}, C: 3, D: 4} 26 | if got, want := layerString(reflect.ValueOf(e), false, false), "{A=1 B=2 C=3 D=4}"; got != want { 27 | t.Errorf("embedded dump mismatch:\n got: %v\n want: %v", got, want) 28 | } 29 | } 30 | 31 | type singlePacketSource [1][]byte 32 | 33 | func (s *singlePacketSource) ReadPacketData() ([]byte, CaptureInfo, error) { 34 | if (*s)[0] == nil { 35 | return nil, CaptureInfo{}, io.EOF 36 | } 37 | out := (*s)[0] 38 | (*s)[0] = nil 39 | return out, CaptureInfo{}, nil 40 | } 41 | 42 | func TestConcatPacketSources(t *testing.T) { 43 | sourceA := &singlePacketSource{[]byte{1}} 44 | sourceB := &singlePacketSource{[]byte{2}} 45 | sourceC := &singlePacketSource{[]byte{3}} 46 | concat := ConcatFinitePacketDataSources(sourceA, sourceB, sourceC) 47 | a, _, err := concat.ReadPacketData() 48 | if err != nil || len(a) != 1 || a[0] != 1 { 49 | t.Errorf("expected [1], got %v/%v", a, err) 50 | } 51 | b, _, err := concat.ReadPacketData() 52 | if err != nil || len(b) != 1 || b[0] != 2 { 53 | t.Errorf("expected [2], got %v/%v", b, err) 54 | } 55 | c, _, err := concat.ReadPacketData() 56 | if err != nil || len(c) != 1 || c[0] != 3 { 57 | t.Errorf("expected [3], got %v/%v", c, err) 58 | } 59 | if _, _, err := concat.ReadPacketData(); err != io.EOF { 60 | t.Errorf("expected io.EOF, got %v", err) 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /pcap/bpf_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The GoPacket Authors. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | package pcap 7 | 8 | import ( 9 | "testing" 10 | "time" 11 | 12 | "github.com/google/gopacket" 13 | "github.com/google/gopacket/layers" 14 | ) 15 | 16 | var ( 17 | snaplen = 65535 18 | packet = [...]byte{ 19 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // dst mac 20 | 0x0, 0x11, 0x22, 0x33, 0x44, 0x55, // src mac 21 | 0x08, 0x0, // ether type 22 | 0x45, 0x0, 0x0, 0x3c, 0xa6, 0xc3, 0x40, 0x0, 0x40, 0x06, 0x3d, 0xd8, // ip header 23 | 0xc0, 0xa8, 0x50, 0x2f, // src ip 24 | 0xc0, 0xa8, 0x50, 0x2c, // dst ip 25 | 0xaf, 0x14, // src port 26 | 0x0, 0x50, // dst port 27 | } 28 | matchingBPFFilter = "ip and tcp and port 80" 29 | nonmatchingBPFFilter = "udp and port 80" 30 | ) 31 | 32 | func BenchmarkPcapNonmatchingBPFFilter(b *testing.B) { 33 | bpf, err := NewBPF(layers.LinkTypeEthernet, snaplen, nonmatchingBPFFilter) 34 | if err != nil { 35 | b.Fatal("incorrect filter") 36 | } 37 | 38 | ci := gopacket.CaptureInfo{ 39 | InterfaceIndex: 0, 40 | CaptureLength: len(packet), 41 | Length: len(packet), 42 | Timestamp: time.Now(), 43 | } 44 | 45 | for i := 0; i < b.N; i++ { 46 | if bpf.Matches(ci, packet[:]) { 47 | b.Fatal("filter must not match the packet") 48 | } 49 | } 50 | } 51 | 52 | func BenchmarkPcapMatchingBPFFilter(b *testing.B) { 53 | bpf, err := NewBPF(layers.LinkTypeEthernet, snaplen, matchingBPFFilter) 54 | if err != nil { 55 | b.Fatal("incorrect filter") 56 | } 57 | 58 | ci := gopacket.CaptureInfo{ 59 | InterfaceIndex: 0, 60 | CaptureLength: len(packet), 61 | Length: len(packet), 62 | Timestamp: time.Now(), 63 | } 64 | 65 | for i := 0; i < b.N; i++ { 66 | if !bpf.Matches(ci, packet[:]) { 67 | b.Fatal("filter must match the packet") 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /pcap/defs_windows_386.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The GoPacket Authors. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | // This file contains necessary structs/constants generated from libpcap headers with cgo -godefs 8 | // generated with: generate_defs.exe 9 | // DO NOT MODIFY 10 | 11 | package pcap 12 | 13 | import "syscall" 14 | 15 | const errorBufferSize = 0x100 16 | 17 | const ( 18 | pcapErrorNotActivated = -0x3 19 | pcapErrorActivated = -0x4 20 | pcapWarningPromisc = 0x2 21 | pcapErrorNoSuchDevice = -0x5 22 | pcapErrorDenied = -0x8 23 | pcapErrorNotUp = -0x9 24 | pcapError = -0x1 25 | pcapWarning = 0x1 26 | pcapDIN = 0x1 27 | pcapDOUT = 0x2 28 | pcapDINOUT = 0x0 29 | pcapNetmaskUnknown = 0xffffffff 30 | pcapTstampPrecisionMicro = 0x0 31 | pcapTstampPrecisionNano = 0x1 32 | ) 33 | 34 | type timeval struct { 35 | Sec int32 36 | Usec int32 37 | } 38 | type pcapPkthdr struct { 39 | Ts timeval 40 | Caplen uint32 41 | Len uint32 42 | } 43 | type pcapTPtr uintptr 44 | type pcapBpfInstruction struct { 45 | Code uint16 46 | Jt uint8 47 | Jf uint8 48 | K uint32 49 | } 50 | type pcapBpfProgram struct { 51 | Len uint32 52 | Insns *pcapBpfInstruction 53 | } 54 | type pcapStats struct { 55 | Recv uint32 56 | Drop uint32 57 | Ifdrop uint32 58 | } 59 | type pcapCint int32 60 | type pcapIf struct { 61 | Next *pcapIf 62 | Name *int8 63 | Description *int8 64 | Addresses *pcapAddr 65 | Flags uint32 66 | } 67 | 68 | type pcapAddr struct { 69 | Next *pcapAddr 70 | Addr *syscall.RawSockaddr 71 | Netmask *syscall.RawSockaddr 72 | Broadaddr *syscall.RawSockaddr 73 | Dstaddr *syscall.RawSockaddr 74 | } 75 | -------------------------------------------------------------------------------- /pcap/defs_windows_amd64.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The GoPacket Authors. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | // This file contains necessary structs/constants generated from libpcap headers with cgo -godefs 8 | // generated with: generate_defs.exe 9 | // DO NOT MODIFY 10 | 11 | package pcap 12 | 13 | import "syscall" 14 | 15 | const errorBufferSize = 0x100 16 | 17 | const ( 18 | pcapErrorNotActivated = -0x3 19 | pcapErrorActivated = -0x4 20 | pcapWarningPromisc = 0x2 21 | pcapErrorNoSuchDevice = -0x5 22 | pcapErrorDenied = -0x8 23 | pcapErrorNotUp = -0x9 24 | pcapError = -0x1 25 | pcapWarning = 0x1 26 | pcapDIN = 0x1 27 | pcapDOUT = 0x2 28 | pcapDINOUT = 0x0 29 | pcapNetmaskUnknown = 0xffffffff 30 | pcapTstampPrecisionMicro = 0x0 31 | pcapTstampPrecisionNano = 0x1 32 | ) 33 | 34 | type timeval struct { 35 | Sec int32 36 | Usec int32 37 | } 38 | type pcapPkthdr struct { 39 | Ts timeval 40 | Caplen uint32 41 | Len uint32 42 | } 43 | type pcapTPtr uintptr 44 | type pcapBpfInstruction struct { 45 | Code uint16 46 | Jt uint8 47 | Jf uint8 48 | K uint32 49 | } 50 | type pcapBpfProgram struct { 51 | Len uint32 52 | Pad_cgo_0 [4]byte 53 | Insns *pcapBpfInstruction 54 | } 55 | type pcapStats struct { 56 | Recv uint32 57 | Drop uint32 58 | Ifdrop uint32 59 | } 60 | type pcapCint int32 61 | type pcapIf struct { 62 | Next *pcapIf 63 | Name *int8 64 | Description *int8 65 | Addresses *pcapAddr 66 | Flags uint32 67 | Pad_cgo_0 [4]byte 68 | } 69 | 70 | type pcapAddr struct { 71 | Next *pcapAddr 72 | Addr *syscall.RawSockaddr 73 | Netmask *syscall.RawSockaddr 74 | Broadaddr *syscall.RawSockaddr 75 | Dstaddr *syscall.RawSockaddr 76 | } 77 | -------------------------------------------------------------------------------- /pcap/pcap_tester.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | // +build ignore 8 | 9 | // This binary tests that PCAP packet capture is working correctly by issuing 10 | // HTTP requests, then making sure we actually capture data off the wire. 11 | package main 12 | 13 | import ( 14 | "errors" 15 | "flag" 16 | "fmt" 17 | "log" 18 | "net/http" 19 | "os" 20 | "time" 21 | 22 | "github.com/google/gopacket/pcap" 23 | ) 24 | 25 | var mode = flag.String("mode", "basic", "One of: basic,filtered,timestamp") 26 | 27 | func generatePackets() { 28 | if resp, err := http.Get("http://code.google.com"); err != nil { 29 | log.Printf("Could not get HTTP: %v", err) 30 | } else { 31 | resp.Body.Close() 32 | } 33 | } 34 | 35 | func main() { 36 | flag.Parse() 37 | ifaces, err := pcap.FindAllDevs() 38 | if err != nil { 39 | log.Fatal(err) 40 | } 41 | for _, iface := range ifaces { 42 | log.Printf("Trying capture on %q", iface.Name) 43 | if err := tryCapture(iface); err != nil { 44 | log.Printf("Error capturing on %q: %v", iface.Name, err) 45 | } else { 46 | log.Printf("Successfully captured on %q", iface.Name) 47 | return 48 | } 49 | } 50 | os.Exit(1) 51 | } 52 | 53 | func tryCapture(iface pcap.Interface) error { 54 | if iface.Name[:2] == "lo" { 55 | return errors.New("skipping loopback") 56 | } 57 | var h *pcap.Handle 58 | var err error 59 | switch *mode { 60 | case "basic": 61 | h, err = pcap.OpenLive(iface.Name, 65536, false, time.Second*3) 62 | if err != nil { 63 | return fmt.Errorf("openlive: %v", err) 64 | } 65 | defer h.Close() 66 | case "filtered": 67 | h, err = pcap.OpenLive(iface.Name, 65536, false, time.Second*3) 68 | if err != nil { 69 | return fmt.Errorf("openlive: %v", err) 70 | } 71 | defer h.Close() 72 | if err := h.SetBPFFilter("port 80 or port 443"); err != nil { 73 | return fmt.Errorf("setbpf: %v", err) 74 | } 75 | case "timestamp": 76 | u, err := pcap.NewInactiveHandle(iface.Name) 77 | if err != nil { 78 | return err 79 | } 80 | defer u.CleanUp() 81 | if err = u.SetSnapLen(65536); err != nil { 82 | return err 83 | } else if err = u.SetPromisc(false); err != nil { 84 | return err 85 | } else if err = u.SetTimeout(time.Second * 3); err != nil { 86 | return err 87 | } 88 | sources := u.SupportedTimestamps() 89 | if len(sources) == 0 { 90 | return errors.New("no supported timestamp sources") 91 | } else if err := u.SetTimestampSource(sources[0]); err != nil { 92 | return fmt.Errorf("settimestampsource(%v): %v", sources[0], err) 93 | } else if h, err = u.Activate(); err != nil { 94 | return fmt.Errorf("could not activate: %v", err) 95 | } 96 | defer h.Close() 97 | default: 98 | panic("Invalid --mode: " + *mode) 99 | } 100 | go generatePackets() 101 | h.ReadPacketData() // Do one dummy read to clear any timeouts. 102 | data, ci, err := h.ReadPacketData() 103 | if err != nil { 104 | return fmt.Errorf("readpacketdata: %v", err) 105 | } 106 | log.Printf("Read packet, %v bytes, CI: %+v", len(data), ci) 107 | return nil 108 | } 109 | -------------------------------------------------------------------------------- /pcap/pcapgo_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | package pcap 8 | 9 | import ( 10 | "bytes" 11 | "github.com/google/gopacket" 12 | "github.com/google/gopacket/layers" 13 | "github.com/google/gopacket/pcapgo" 14 | "io/ioutil" 15 | "reflect" 16 | "testing" 17 | "time" 18 | ) 19 | 20 | func TestPCAPGoWrite(t *testing.T) { 21 | f, err := ioutil.TempFile("", "pcapgo") 22 | if err != nil { 23 | t.Fatal(err) 24 | } 25 | data := []byte{0xab, 0xcd, 0xef, 0x01, 0x02, 0x03, 0x04} 26 | ci := gopacket.CaptureInfo{ 27 | Timestamp: time.Unix(12345667, 1234567000), 28 | Length: 700, 29 | CaptureLength: len(data), 30 | } 31 | func() { 32 | defer f.Close() 33 | w := pcapgo.NewWriter(f) 34 | if err := w.WriteFileHeader(65536, layers.LinkTypeEthernet); err != nil { 35 | t.Fatal(err) 36 | } 37 | if err := w.WritePacket(ci, data); err != nil { 38 | t.Fatal(err) 39 | } 40 | }() 41 | h, err := OpenOffline(f.Name()) 42 | if err != nil { 43 | t.Fatal(err) 44 | } 45 | defer h.Close() 46 | gotData, gotCI, err := h.ReadPacketData() 47 | if err != nil { 48 | t.Fatal("could not read first packet:", err) 49 | } 50 | if !bytes.Equal(gotData, data) { 51 | t.Errorf("byte mismatch:\nwant: %v\n got: %v", data, gotData) 52 | } 53 | if !reflect.DeepEqual(ci, gotCI) { 54 | t.Errorf("CI mismatch:\nwant: %v\n got: %v", ci, gotCI) 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /pcap/pcapnggo_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The GoPacket Authors. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | package pcap 8 | 9 | import ( 10 | "bytes" 11 | "io/ioutil" 12 | "reflect" 13 | "testing" 14 | "time" 15 | 16 | "github.com/google/gopacket" 17 | "github.com/google/gopacket/layers" 18 | "github.com/google/gopacket/pcapgo" 19 | ) 20 | 21 | func TestPCAPGoNgWrite(t *testing.T) { 22 | f, err := ioutil.TempFile("", "pcapnggo") 23 | if err != nil { 24 | t.Fatal(err) 25 | } 26 | data := []byte{0xab, 0xcd, 0xef, 0x01, 0x02, 0x03, 0x04} 27 | ci := gopacket.CaptureInfo{ 28 | Timestamp: time.Unix(12345667, 1234567123), 29 | Length: 700, 30 | CaptureLength: len(data), 31 | } 32 | func() { 33 | defer f.Close() 34 | w, err := pcapgo.NewNgWriter(f, layers.LinkTypeEthernet) 35 | if err != nil { 36 | t.Fatal(err) 37 | } 38 | if err := w.WritePacket(ci, data); err != nil { 39 | t.Fatal(err) 40 | } 41 | if err := w.Flush(); err != nil { 42 | t.Fatal(err) 43 | } 44 | }() 45 | h, err := OpenOffline(f.Name()) 46 | if err != nil { 47 | t.Fatal(err) 48 | } 49 | defer h.Close() 50 | gotData, gotCI, err := h.ReadPacketData() 51 | if err != nil { 52 | t.Fatal("could not read first packet:", err) 53 | } 54 | if !bytes.Equal(gotData, data) { 55 | t.Errorf("byte mismatch:\nwant: %v\n got: %v", data, gotData) 56 | } 57 | if !reflect.DeepEqual(ci, gotCI) { 58 | t.Errorf("CI mismatch:\nwant: %v\n got: %v", ci, gotCI) 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /pcap/test_dns.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcap/test_dns.pcap -------------------------------------------------------------------------------- /pcap/test_ethernet.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcap/test_ethernet.pcap -------------------------------------------------------------------------------- /pcap/test_loopback.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcap/test_loopback.pcap -------------------------------------------------------------------------------- /pcapgo/capture_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | // +build linux,go1.9 7 | 8 | package pcapgo_test 9 | 10 | import ( 11 | "log" 12 | "os" 13 | 14 | "github.com/google/gopacket" 15 | "github.com/google/gopacket/layers" 16 | "github.com/google/gopacket/pcapgo" 17 | ) 18 | 19 | func Example_captureEthernet() { 20 | f, err := os.Create("/tmp/lo.pcap") 21 | if err != nil { 22 | log.Fatal(err) 23 | } 24 | defer f.Close() 25 | pcapw := pcapgo.NewWriter(f) 26 | if err := pcapw.WriteFileHeader(1600, layers.LinkTypeEthernet); err != nil { 27 | log.Fatalf("WriteFileHeader: %v", err) 28 | } 29 | 30 | handle, err := pcapgo.NewEthernetHandle("lo") 31 | if err != nil { 32 | log.Fatalf("OpenEthernet: %v", err) 33 | } 34 | 35 | pkgsrc := gopacket.NewPacketSource(handle, layers.LayerTypeEthernet) 36 | for packet := range pkgsrc.Packets() { 37 | if err := pcapw.WritePacket(packet.Metadata().CaptureInfo, packet.Data()); err != nil { 38 | log.Fatalf("pcap.WritePacket(): %v", err) 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /pcapgo/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The GoPacket Authors. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | /* 8 | Package pcapgo provides some native PCAP support, not requiring C libpcap to be installed. 9 | 10 | Overview 11 | 12 | This package contains implementations for native PCAP support. Currently supported are 13 | 14 | * pcap-files read/write: Reader, Writer 15 | * pcapng-files read/write: NgReader, NgWriter 16 | * raw socket capture (linux only): EthernetHandle 17 | 18 | Basic Usage pcapng 19 | 20 | Pcapng files can be read and written. Reading supports both big and little endian files, packet blocks, 21 | simple packet blocks, enhanced packets blocks, interface blocks, and interface statistics blocks. All 22 | the options also by Wireshark are supported. The default reader options match libpcap behaviour. Have 23 | a look at NgReaderOptions for more advanced usage. Both ReadPacketData and ZeroCopyReadPacketData is 24 | supported (which means PacketDataSource and ZeroCopyPacketDataSource is supported). 25 | 26 | f, err := os.Open("somefile.pcapng") 27 | if err != nil { 28 | ... 29 | } 30 | defer f.Close() 31 | 32 | r, err := NewNgReader(f, DefaultNgReaderOptions) 33 | if err != nil { 34 | ... 35 | } 36 | 37 | data, ci, err := r.ReadPacketData() 38 | ... 39 | 40 | Write supports only little endian, enhanced packets blocks, interface blocks, and interface statistics 41 | blocks. The same options as with writing are supported. Interface timestamp resolution is fixed to 42 | 10^-9s to match time.Time. Any other values are ignored. Upon creating a writer, a section, and an 43 | interface block is automatically written. Additional interfaces can be added at any time. Since 44 | the writer uses a bufio.Writer internally, Flush must be called before closing the file! Have a look 45 | at NewNgWriterInterface for more advanced usage. 46 | 47 | f, err := os.Create("somefile.pcapng") 48 | if err != nil { 49 | ... 50 | } 51 | defer f.Close() 52 | 53 | r, err = NewNgWriter(f, layers.LinkTypeEthernet) 54 | if err != nil { 55 | ... 56 | } 57 | defer r.Flush() 58 | 59 | err = r.WritePacket(ci, data) 60 | ... 61 | 62 | */ 63 | package pcapgo 64 | -------------------------------------------------------------------------------- /pcapgo/tests/README.md: -------------------------------------------------------------------------------- 1 | This directory contains the test data generated with https://github.com/hadrielk/pcapng-test-generator and two additional tests. -------------------------------------------------------------------------------- /pcapgo/tests/be/test001.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/be/test001.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/be/test002.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/be/test002.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/be/test003.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/be/test003.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/be/test004.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/be/test004.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/be/test005.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/be/test005.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/be/test006.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/be/test006.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/be/test007.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/be/test007.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/be/test008.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/be/test008.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/be/test009.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/be/test009.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/be/test010.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/be/test010.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/be/test011.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/be/test011.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/be/test012.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/be/test012.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/be/test013.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/be/test013.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/be/test014.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/be/test014.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/be/test015.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/be/test015.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/be/test016.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/be/test016.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/be/test017.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/be/test017.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/be/test018.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/be/test018.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/be/test100.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/be/test100.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/be/test101.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/be/test101.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/be/test102.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/be/test102.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/be/test200.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/be/test200.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/be/test201.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/be/test201.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/be/test202.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/be/test202.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/be/test901.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/be/test901.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/be/test902.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/be/test902.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/le/test001.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/le/test001.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/le/test002.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/le/test002.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/le/test003.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/le/test003.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/le/test004.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/le/test004.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/le/test005.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/le/test005.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/le/test006.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/le/test006.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/le/test007.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/le/test007.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/le/test008.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/le/test008.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/le/test009.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/le/test009.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/le/test010.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/le/test010.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/le/test011.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/le/test011.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/le/test012.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/le/test012.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/le/test013.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/le/test013.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/le/test014.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/le/test014.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/le/test015.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/le/test015.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/le/test016.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/le/test016.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/le/test017.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/le/test017.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/le/test018.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/le/test018.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/le/test100.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/le/test100.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/le/test101.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/le/test101.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/le/test102.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/le/test102.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/le/test200.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/le/test200.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/le/test201.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/le/test201.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/le/test202.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/le/test202.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/le/test901.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/le/test901.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/le/test902.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/gopacket/b7d9dbd15ae4c4621a62119b0c682dc23061a8bc/pcapgo/tests/le/test902.pcapng -------------------------------------------------------------------------------- /pcapgo/tests/test901.lua: -------------------------------------------------------------------------------- 1 | -- prevent wireshark loading this file as a plugin 2 | if not _G['pcapng_test_gen'] then return end 3 | 4 | 5 | local block = require "blocks" 6 | local input = require "input" 7 | 8 | 9 | local test = { 10 | category = 'difficult', 11 | description = "Multible SHB sections, one with invalid version number", 12 | } 13 | 14 | 15 | local timestamp = UInt64(0x64ca47aa, 0x0004c397) 16 | 17 | function test:compile() 18 | local idb0 = block.IDB(0, input.linktype.ETHERNET, 0, "eth0") 19 | 20 | self.blocks = { 21 | block.SHB("my computer", "linux", "pcap_writer.lua") 22 | :addOption('comment', self.testname .. " SHB-0"), 23 | idb0, 24 | 25 | block.EPB( idb0, input:getData(1), timestamp ), 26 | 27 | block.SHB("my computer", "linux", "pcap_writer.lua") 28 | :addOption('comment', self.testname .. " SHB-1") 29 | :setVersion(2, 0), 30 | idb0, 31 | 32 | block.EPB( idb0, input:getData(2), timestamp ), 33 | 34 | block.SHB("my computer", "linux", "pcap_writer.lua") 35 | :addOption('comment', self.testname .. " SHB-2"), 36 | idb0, 37 | 38 | block.EPB( idb0, input:getData(3), timestamp ), 39 | } 40 | end 41 | 42 | 43 | return test 44 | -------------------------------------------------------------------------------- /pcapgo/tests/test902.lua: -------------------------------------------------------------------------------- 1 | -- prevent wireshark loading this file as a plugin 2 | if not _G['pcapng_test_gen'] then return end 3 | 4 | 5 | local block = require "blocks" 6 | local input = require "input" 7 | 8 | 9 | local test = { 10 | category = 'difficult', 11 | description = "idb with binary resolution", 12 | } 13 | 14 | 15 | local timestamp = UInt64(0x8c0dc032, 0x0000005a) 16 | 17 | function test:compile() 18 | local idb0 = block.IDB(0, input.linktype.ETHERNET, 0, "eth0") 19 | :addOption( block.OptionFormat ('if_tsresol', "B", 0x88) ) 20 | 21 | self.blocks = { 22 | block.SHB("my computer", "linux", "pcap_writer.lua") 23 | :addOption('comment', self.testname), 24 | idb0, 25 | block.EPB( idb0, input:getData(1), timestamp ), 26 | } 27 | end 28 | 29 | 30 | return test 31 | -------------------------------------------------------------------------------- /pcapgo/write_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | package pcapgo 8 | 9 | import ( 10 | "bytes" 11 | "testing" 12 | "time" 13 | 14 | "github.com/google/gopacket" 15 | ) 16 | 17 | func TestWriteHeaderNanos(t *testing.T) { 18 | var buf bytes.Buffer 19 | w := NewWriterNanos(&buf) 20 | w.WriteFileHeader(0x1234, 0x56) 21 | want := []byte{ 22 | 0x4d, 0x3c, 0xb2, 0xa1, 0x02, 0x00, 0x04, 0x00, 23 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 24 | 0x34, 0x12, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 25 | } 26 | if got := buf.Bytes(); !bytes.Equal(got, want) { 27 | t.Errorf("buf mismatch:\nwant: %+v\ngot: %+v", want, got) 28 | } 29 | } 30 | 31 | func TestWriteHeader(t *testing.T) { 32 | var buf bytes.Buffer 33 | w := NewWriter(&buf) 34 | w.WriteFileHeader(0x1234, 0x56) 35 | want := []byte{ 36 | 0xd4, 0xc3, 0xb2, 0xa1, 0x02, 0x00, 0x04, 0x00, 37 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 38 | 0x34, 0x12, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 39 | } 40 | if got := buf.Bytes(); !bytes.Equal(got, want) { 41 | t.Errorf("buf mismatch:\nwant: %+v\ngot: %+v", want, got) 42 | } 43 | } 44 | 45 | func TestWritePacket(t *testing.T) { 46 | ci := gopacket.CaptureInfo{ 47 | Timestamp: time.Unix(0x01020304, 0xAA*1000), 48 | Length: 0xABCD, 49 | CaptureLength: 10, 50 | } 51 | data := []byte{9, 8, 7, 6, 5, 4, 3, 2, 1, 0} 52 | var buf bytes.Buffer 53 | w := NewWriter(&buf) 54 | w.WritePacket(ci, data) 55 | want := []byte{ 56 | 0x04, 0x03, 0x02, 0x01, 0xAA, 0x00, 0x00, 0x00, 57 | 0x0A, 0x00, 0x00, 0x00, 0xCD, 0xAB, 0x00, 0x00, 58 | 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 59 | } 60 | if got := buf.Bytes(); !bytes.Equal(got, want) { 61 | t.Errorf("buf mismatch:\nwant: %+v\ngot: %+v", want, got) 62 | } 63 | } 64 | 65 | func BenchmarkWritePacket(b *testing.B) { 66 | b.StopTimer() 67 | ci := gopacket.CaptureInfo{ 68 | Timestamp: time.Unix(0x01020304, 0xAA*1000), 69 | Length: 0xABCD, 70 | CaptureLength: 10, 71 | } 72 | data := []byte{9, 8, 7, 6, 5, 4, 3, 2, 1, 0} 73 | var buf bytes.Buffer 74 | w := NewWriter(&buf) 75 | b.StartTimer() 76 | 77 | for i := 0; i < b.N; i++ { 78 | w.WritePacket(ci, data) 79 | } 80 | } 81 | 82 | func TestCaptureInfoErrors(t *testing.T) { 83 | data := []byte{1, 2, 3, 4} 84 | ts := time.Unix(0, 0) 85 | for _, test := range []gopacket.CaptureInfo{ 86 | gopacket.CaptureInfo{ 87 | Timestamp: ts, 88 | Length: 5, 89 | CaptureLength: 5, 90 | }, 91 | gopacket.CaptureInfo{ 92 | Timestamp: ts, 93 | Length: 3, 94 | CaptureLength: 4, 95 | }, 96 | } { 97 | var buf bytes.Buffer 98 | w := NewWriter(&buf) 99 | if err := w.WritePacket(test, data); err == nil { 100 | t.Errorf("CaptureInfo %+v should have error", test) 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /pfring/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | /*Package pfring wraps the PF_RING C library for Go. 8 | 9 | PF_RING is a high-performance packet capture library written by ntop.org (see 10 | http://www.ntop.org/products/pf_ring/). This library allows you to utilize the 11 | PF_RING library with gopacket to read packet data and decode it. 12 | 13 | This package is meant to be used with its parent, 14 | http://github.com/google/gopacket, although it can also be used independently 15 | if you just want to get packet data from the wire. 16 | 17 | Simple Example 18 | 19 | This is probably the simplest code you can use to start getting packets through 20 | pfring: 21 | 22 | if ring, err := pfring.NewRing("eth0", 65536, pfring.FlagPromisc); err != nil { 23 | panic(err) 24 | } else if err := ring.SetBPFFilter("tcp and port 80"); err != nil { // optional 25 | panic(err) 26 | } else if err := ring.Enable(); err != nil { // Must do this!, or you get no packets! 27 | panic(err) 28 | } else { 29 | packetSource := gopacket.NewPacketSource(ring, layers.LinkTypeEthernet) 30 | for packet := range packetSource.Packets() { 31 | handlePacket(packet) // Do something with a packet here. 32 | } 33 | } 34 | 35 | Pfring Tweaks 36 | 37 | PF_RING has a ton of optimizations and tweaks to make sure you get just the 38 | packets you want. For example, if you're only using pfring to read packets, 39 | consider running: 40 | 41 | ring.SetSocketMode(pfring.ReadOnly) 42 | 43 | If you only care about packets received on your interface (not those transmitted 44 | by the interface), you can run: 45 | 46 | ring.SetDirection(pfring.ReceiveOnly) 47 | 48 | Pfring Clusters 49 | 50 | PF_RING has an idea of 'clusters', where multiple applications can all read from 51 | the same cluster, and PF_RING will multiplex packets over that cluster such that 52 | only one application receives each packet. We won't discuss this mechanism in 53 | too much more detail (see the ntop.org docs for more info), but here's how to 54 | utilize this with the pfring go library: 55 | 56 | ring.SetCluster(1, pfring.ClusterPerFlow5Tuple) 57 | */ 58 | package pfring 59 | -------------------------------------------------------------------------------- /pfring/pfring_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The GoPacket Authors. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | package pfring 8 | 9 | import ( 10 | "flag" 11 | "log" 12 | "testing" 13 | ) 14 | 15 | var iface = flag.String("i", "eth0", "Interface to read packets from") 16 | 17 | func BenchmarkPfringRead(b *testing.B) { 18 | var ring *Ring 19 | var err error 20 | if ring, err = NewRing(*iface, 65536, FlagPromisc); err != nil { 21 | log.Fatalln("pfring ring creation error:", err) 22 | } 23 | if err = ring.SetSocketMode(ReadOnly); err != nil { 24 | log.Fatalln("pfring SetSocketMode error:", err) 25 | } else if err = ring.Enable(); err != nil { 26 | log.Fatalln("pfring Enable error:", err) 27 | } 28 | b.ResetTimer() 29 | for i := 0; i < b.N; i++ { 30 | _, ci, _ := ring.ReadPacketData() 31 | b.SetBytes(int64(ci.CaptureLength)) 32 | } 33 | } 34 | 35 | func BenchmarkPfringReadZero(b *testing.B) { 36 | var ring *Ring 37 | var err error 38 | if ring, err = NewRing(*iface, 65536, FlagPromisc); err != nil { 39 | log.Fatalln("pfring ring creation error:", err) 40 | } 41 | if err = ring.SetSocketMode(ReadOnly); err != nil { 42 | log.Fatalln("pfring SetSocketMode error:", err) 43 | } else if err = ring.Enable(); err != nil { 44 | log.Fatalln("pfring Enable error:", err) 45 | } 46 | b.ResetTimer() 47 | for i := 0; i < b.N; i++ { 48 | _, ci, _ := ring.ZeroCopyReadPacketData() 49 | b.SetBytes(int64(ci.CaptureLength)) 50 | } 51 | } 52 | 53 | func BenchmarkPfringReadTo(b *testing.B) { 54 | var ring *Ring 55 | var err error 56 | if ring, err = NewRing(*iface, 65536, FlagPromisc); err != nil { 57 | log.Fatalln("pfring ring creation error:", err) 58 | } 59 | if err = ring.SetSocketMode(ReadOnly); err != nil { 60 | log.Fatalln("pfring SetSocketMode error:", err) 61 | } else if err = ring.Enable(); err != nil { 62 | log.Fatalln("pfring Enable error:", err) 63 | } 64 | buffer := make([]byte, 65536*2) 65 | b.ResetTimer() 66 | for i := 0; i < b.N; i++ { 67 | ci, _ := ring.ReadPacketDataTo(buffer) 68 | b.SetBytes(int64(ci.CaptureLength)) 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /reassembly/cap2test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | // +build ignore 8 | 9 | package main 10 | 11 | import ( 12 | "bytes" 13 | "flag" 14 | "fmt" 15 | "log" 16 | "os" 17 | "strings" 18 | 19 | "github.com/google/gopacket" 20 | "github.com/google/gopacket/layers" 21 | "github.com/google/gopacket/pcap" 22 | ) 23 | 24 | var input = flag.String("i", "", "Input filename") 25 | 26 | func main() { 27 | var handler *pcap.Handle 28 | var err error 29 | flag.Parse() 30 | if *input == "" { 31 | log.Fatalf("Please specify input filename") 32 | } 33 | if handler, err = pcap.OpenOffline(*input); err != nil { 34 | log.Fatalf("Failed to open: %s: %s", *input, err) 35 | } 36 | args := flag.Args() 37 | if len(args) > 0 { 38 | filter := strings.Join(args, " ") 39 | if err := handler.SetBPFFilter(filter); err != nil { 40 | log.Fatalf("Failed to set BPF filter \"%s\": %s", filter, err) 41 | } 42 | handler.Stats() 43 | } 44 | var decoder gopacket.Decoder 45 | var ok bool 46 | linkType := fmt.Sprintf("%s", handler.LinkType()) 47 | if decoder, ok = gopacket.DecodersByLayerName[linkType]; !ok { 48 | log.Fatalf("Failed to find decoder to pcap's linktype %s", linkType) 49 | } 50 | source := gopacket.NewPacketSource(handler, decoder) 51 | count := uint64(0) 52 | pktNonTcp := uint64(0) 53 | pktTcp := uint64(0) 54 | fmt.Println("test([]testSequence{") 55 | for packet := range source.Packets() { 56 | count++ 57 | tcp := packet.Layer(layers.LayerTypeTCP) 58 | if tcp == nil { 59 | pktNonTcp++ 60 | continue 61 | } else { 62 | pktTcp++ 63 | tcp := tcp.(*layers.TCP) 64 | //fmt.Printf("packet: %s\n", tcp) 65 | var b bytes.Buffer 66 | b.WriteString("{\n") 67 | // TCP 68 | b.WriteString("tcp: layers.TCP{\n") 69 | if tcp.SYN { 70 | b.WriteString(" SYN: true,\n") 71 | } 72 | if tcp.ACK { 73 | b.WriteString(" ACK: true,\n") 74 | } 75 | if tcp.RST { 76 | b.WriteString(" RST: true,\n") 77 | } 78 | if tcp.FIN { 79 | b.WriteString(" FIN: true,\n") 80 | } 81 | b.WriteString(fmt.Sprintf(" SrcPort: %d,\n", tcp.SrcPort)) 82 | b.WriteString(fmt.Sprintf(" DstPort: %d,\n", tcp.DstPort)) 83 | b.WriteString(fmt.Sprintf(" Seq: %d,\n", tcp.Seq)) 84 | b.WriteString(fmt.Sprintf(" Ack: %d,\n", tcp.Ack)) 85 | b.WriteString(" BaseLayer: layers.BaseLayer{Payload: []byte{") 86 | for _, p := range tcp.Payload { 87 | b.WriteString(fmt.Sprintf("%d,", p)) 88 | } 89 | b.WriteString("}},\n") 90 | b.WriteString("},\n") 91 | // CaptureInfo 92 | b.WriteString("ci: gopacket.CaptureInfo{\n") 93 | ts := packet.Metadata().CaptureInfo.Timestamp 94 | b.WriteString(fmt.Sprintf(" Timestamp: time.Unix(%d,%d),\n", ts.Unix(), ts.Nanosecond())) 95 | b.WriteString("},\n") 96 | // Struct 97 | b.WriteString("},\n") 98 | fmt.Print(b.String()) 99 | } 100 | 101 | } 102 | fmt.Println("})") 103 | 104 | fmt.Fprintf(os.Stderr, "Total: %d, TCP: %d, non-TCP: %d\n", count, pktTcp, pktNonTcp) 105 | } 106 | -------------------------------------------------------------------------------- /routing/common.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | package routing 8 | 9 | import ( 10 | "net" 11 | ) 12 | 13 | // Router implements simple IPv4/IPv6 routing based on the kernel's routing 14 | // table. This routing library has very few features and may actually route 15 | // incorrectly in some cases, but it should work the majority of the time. 16 | type Router interface { 17 | // Route returns where to route a packet based on the packet's source 18 | // and destination IP address. 19 | // 20 | // Callers may pass in nil for src, in which case the src is treated as 21 | // either 0.0.0.0 or ::, depending on whether dst is a v4 or v6 address. 22 | // 23 | // It returns the interface on which to send the packet, the gateway IP 24 | // to send the packet to (if necessary), the preferred src IP to use (if 25 | // available). If the preferred src address is not given in the routing 26 | // table, the first IP address of the interface is provided. 27 | // 28 | // If an error is encountered, iface, geteway, and 29 | // preferredSrc will be nil, and err will be set. 30 | Route(dst net.IP) (iface *net.Interface, gateway, preferredSrc net.IP, err error) 31 | 32 | // RouteWithSrc routes based on source information as well as destination 33 | // information. Either or both of input/src can be nil. If both are, this 34 | // should behave exactly like Route(dst) 35 | RouteWithSrc(input net.HardwareAddr, src, dst net.IP) (iface *net.Interface, gateway, preferredSrc net.IP, err error) 36 | } 37 | -------------------------------------------------------------------------------- /routing/other.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | // +build !linux 8 | 9 | // Package routing is currently only supported in Linux, but the build system requires a valid go file for all architectures. 10 | 11 | package routing 12 | 13 | func New() (Router, error) { 14 | panic("router only implemented in linux") 15 | } 16 | -------------------------------------------------------------------------------- /tcpassembly/tcpreader/reader_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | package tcpreader 8 | 9 | import ( 10 | "bytes" 11 | "fmt" 12 | "github.com/google/gopacket" 13 | "github.com/google/gopacket/layers" 14 | "github.com/google/gopacket/tcpassembly" 15 | "io" 16 | "net" 17 | "testing" 18 | ) 19 | 20 | var netFlow gopacket.Flow 21 | 22 | func init() { 23 | netFlow, _ = gopacket.FlowFromEndpoints( 24 | layers.NewIPEndpoint(net.IP{1, 2, 3, 4}), 25 | layers.NewIPEndpoint(net.IP{5, 6, 7, 8})) 26 | } 27 | 28 | type readReturn struct { 29 | data []byte 30 | err error 31 | } 32 | type readSequence struct { 33 | in []layers.TCP 34 | want []readReturn 35 | } 36 | type testReaderFactory struct { 37 | lossErrors bool 38 | readSize int 39 | ReaderStream 40 | output chan []byte 41 | } 42 | 43 | func (t *testReaderFactory) New(a, b gopacket.Flow) tcpassembly.Stream { 44 | return &t.ReaderStream 45 | } 46 | 47 | func testReadSequence(t *testing.T, lossErrors bool, readSize int, seq readSequence) { 48 | f := &testReaderFactory{ReaderStream: NewReaderStream()} 49 | f.ReaderStream.LossErrors = lossErrors 50 | p := tcpassembly.NewStreamPool(f) 51 | a := tcpassembly.NewAssembler(p) 52 | buf := make([]byte, readSize) 53 | go func() { 54 | for i, test := range seq.in { 55 | fmt.Println("Assembling", i) 56 | a.Assemble(netFlow, &test) 57 | fmt.Println("Assembly done") 58 | } 59 | }() 60 | for i, test := range seq.want { 61 | fmt.Println("Waiting for read", i) 62 | n, err := f.Read(buf[:]) 63 | fmt.Println("Got read") 64 | if n != len(test.data) { 65 | t.Errorf("test %d want %d bytes, got %d bytes", i, len(test.data), n) 66 | } else if err != test.err { 67 | t.Errorf("test %d want err %v, got err %v", i, test.err, err) 68 | } else if !bytes.Equal(buf[:n], test.data) { 69 | t.Errorf("test %d\nwant: %v\n got: %v\n", i, test.data, buf[:n]) 70 | } 71 | } 72 | fmt.Println("All done reads") 73 | } 74 | 75 | func TestRead(t *testing.T) { 76 | testReadSequence(t, false, 10, readSequence{ 77 | in: []layers.TCP{ 78 | { 79 | SYN: true, 80 | SrcPort: 1, 81 | DstPort: 2, 82 | Seq: 1000, 83 | BaseLayer: layers.BaseLayer{Payload: []byte{1, 2, 3}}, 84 | }, 85 | { 86 | FIN: true, 87 | SrcPort: 1, 88 | DstPort: 2, 89 | Seq: 1004, 90 | }, 91 | }, 92 | want: []readReturn{ 93 | {data: []byte{1, 2, 3}}, 94 | {err: io.EOF}, 95 | }, 96 | }) 97 | } 98 | 99 | func TestReadSmallChunks(t *testing.T) { 100 | testReadSequence(t, false, 2, readSequence{ 101 | in: []layers.TCP{ 102 | { 103 | SYN: true, 104 | SrcPort: 1, 105 | DstPort: 2, 106 | Seq: 1000, 107 | BaseLayer: layers.BaseLayer{Payload: []byte{1, 2, 3}}, 108 | }, 109 | { 110 | FIN: true, 111 | SrcPort: 1, 112 | DstPort: 2, 113 | Seq: 1004, 114 | }, 115 | }, 116 | want: []readReturn{ 117 | {data: []byte{1, 2}}, 118 | {data: []byte{3}}, 119 | {err: io.EOF}, 120 | }, 121 | }) 122 | } 123 | 124 | func ExampleDiscardBytesToEOF() { 125 | b := bytes.NewBuffer([]byte{1, 2, 3, 4, 5}) 126 | fmt.Println(DiscardBytesToEOF(b)) 127 | // Output: 128 | // 5 129 | } 130 | -------------------------------------------------------------------------------- /time.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The GoPacket Authors. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | package gopacket 8 | 9 | import ( 10 | "fmt" 11 | "math" 12 | "time" 13 | ) 14 | 15 | // TimestampResolution represents the resolution of timestamps in Base^Exponent. 16 | type TimestampResolution struct { 17 | Base, Exponent int 18 | } 19 | 20 | func (t TimestampResolution) String() string { 21 | return fmt.Sprintf("%d^%d", t.Base, t.Exponent) 22 | } 23 | 24 | // ToDuration returns the smallest representable time difference as a time.Duration 25 | func (t TimestampResolution) ToDuration() time.Duration { 26 | if t.Base == 0 { 27 | return 0 28 | } 29 | if t.Exponent == 0 { 30 | return time.Second 31 | } 32 | switch t.Base { 33 | case 10: 34 | return time.Duration(math.Pow10(t.Exponent + 9)) 35 | case 2: 36 | if t.Exponent < 0 { 37 | return time.Second >> uint(-t.Exponent) 38 | } 39 | return time.Second << uint(t.Exponent) 40 | default: 41 | // this might loose precision 42 | return time.Duration(float64(time.Second) * math.Pow(float64(t.Base), float64(t.Exponent))) 43 | } 44 | } 45 | 46 | // TimestampResolutionInvalid represents an invalid timestamp resolution 47 | var TimestampResolutionInvalid = TimestampResolution{} 48 | 49 | // TimestampResolutionMillisecond is a resolution of 10^-3s 50 | var TimestampResolutionMillisecond = TimestampResolution{10, -3} 51 | 52 | // TimestampResolutionMicrosecond is a resolution of 10^-6s 53 | var TimestampResolutionMicrosecond = TimestampResolution{10, -6} 54 | 55 | // TimestampResolutionNanosecond is a resolution of 10^-9s 56 | var TimestampResolutionNanosecond = TimestampResolution{10, -9} 57 | 58 | // TimestampResolutionNTP is the resolution of NTP timestamps which is 2^-32 ≈ 233 picoseconds 59 | var TimestampResolutionNTP = TimestampResolution{2, -32} 60 | 61 | // TimestampResolutionCaptureInfo is the resolution used in CaptureInfo, which his currently nanosecond 62 | var TimestampResolutionCaptureInfo = TimestampResolutionNanosecond 63 | 64 | // PacketSourceResolution is an interface for packet data sources that 65 | // support reporting the timestamp resolution of the aqcuired timestamps. 66 | // Returned timestamps will always have NanosecondTimestampResolution due 67 | // to the use of time.Time, but scaling might have occured if acquired 68 | // timestamps have a different resolution. 69 | type PacketSourceResolution interface { 70 | // Resolution returns the timestamp resolution of acquired timestamps before scaling to NanosecondTimestampResolution. 71 | Resolution() TimestampResolution 72 | } 73 | -------------------------------------------------------------------------------- /time_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The GoPacket Authors. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | package gopacket 8 | 9 | import ( 10 | "testing" 11 | "time" 12 | ) 13 | 14 | func TestToDuration(t *testing.T) { 15 | for i, test := range []struct { 16 | r TimestampResolution 17 | d time.Duration 18 | }{ 19 | { 20 | TimestampResolutionMillisecond, 21 | time.Millisecond, 22 | }, 23 | { 24 | TimestampResolutionMicrosecond, 25 | time.Microsecond, 26 | }, 27 | { 28 | TimestampResolutionNanosecond, 29 | time.Nanosecond, 30 | }, 31 | { 32 | TimestampResolutionNTP, 33 | 0, // this is not representable since it's ~0.233 nanoseconds 34 | }, 35 | { 36 | TimestampResolution{2, -16}, 37 | 15258, 38 | }, 39 | { 40 | TimestampResolution{2, 1}, 41 | 2 * time.Second, 42 | }, 43 | { 44 | TimestampResolution{10, 1}, 45 | 10 * time.Second, 46 | }, 47 | { 48 | TimestampResolution{10, 0}, 49 | time.Second, 50 | }, 51 | { 52 | TimestampResolution{2, 0}, 53 | time.Second, 54 | }, 55 | { 56 | TimestampResolution{0, 0}, 57 | 0, 58 | }, 59 | { 60 | TimestampResolution{3, 2}, 61 | 9 * time.Second, 62 | }, 63 | { 64 | TimestampResolution{3, -2}, 65 | 111111111, 66 | }, 67 | } { 68 | d := test.r.ToDuration() 69 | if d != test.d { 70 | t.Errorf("%d: resolution: %s want: %d got: %d", i, test.r, test.d, d) 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /writer_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google, Inc. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the LICENSE file in the root of the source 5 | // tree. 6 | 7 | package gopacket 8 | 9 | import ( 10 | "fmt" 11 | "testing" 12 | ) 13 | 14 | func TestExponentialSizeIncreasePrepend(t *testing.T) { 15 | var b serializeBuffer 16 | for i, test := range []struct { 17 | prepend, size int 18 | }{ 19 | {2, 2}, 20 | {2, 4}, 21 | {2, 8}, 22 | {2, 8}, 23 | {2, 16}, 24 | {2, 16}, 25 | {2, 16}, 26 | {2, 16}, 27 | {2, 32}, 28 | } { 29 | b.PrependBytes(test.prepend) 30 | if test.size != cap(b.data) { 31 | t.Error(i, "size want", test.size, "got", cap(b.data)) 32 | } 33 | } 34 | b.Clear() 35 | if b.start != 32 { 36 | t.Error(b.start) 37 | } 38 | } 39 | 40 | func TestExponentialSizeIncreaseAppend(t *testing.T) { 41 | var b serializeBuffer 42 | for i, test := range []struct { 43 | appnd, size int 44 | }{ 45 | {2, 2}, 46 | {2, 4}, 47 | {2, 8}, 48 | {2, 8}, 49 | {2, 16}, 50 | {2, 16}, 51 | {2, 16}, 52 | {2, 16}, 53 | {2, 32}, 54 | } { 55 | b.AppendBytes(test.appnd) 56 | if test.size != cap(b.data) { 57 | t.Error(i, "size want", test.size, "got", cap(b.data)) 58 | } 59 | } 60 | b.Clear() 61 | if b.start != 0 { 62 | t.Error(b.start) 63 | } 64 | } 65 | 66 | func ExampleSerializeBuffer() { 67 | b := NewSerializeBuffer() 68 | fmt.Println("1:", b.Bytes()) 69 | bytes, _ := b.PrependBytes(3) 70 | copy(bytes, []byte{1, 2, 3}) 71 | fmt.Println("2:", b.Bytes()) 72 | bytes, _ = b.AppendBytes(2) 73 | copy(bytes, []byte{4, 5}) 74 | fmt.Println("3:", b.Bytes()) 75 | bytes, _ = b.PrependBytes(1) 76 | copy(bytes, []byte{0}) 77 | fmt.Println("4:", b.Bytes()) 78 | bytes, _ = b.AppendBytes(3) 79 | copy(bytes, []byte{6, 7, 8}) 80 | fmt.Println("5:", b.Bytes()) 81 | b.Clear() 82 | fmt.Println("6:", b.Bytes()) 83 | bytes, _ = b.PrependBytes(2) 84 | copy(bytes, []byte{9, 9}) 85 | fmt.Println("7:", b.Bytes()) 86 | // Output: 87 | // 1: [] 88 | // 2: [1 2 3] 89 | // 3: [1 2 3 4 5] 90 | // 4: [0 1 2 3 4 5] 91 | // 5: [0 1 2 3 4 5 6 7 8] 92 | // 6: [] 93 | // 7: [9 9] 94 | } 95 | --------------------------------------------------------------------------------