mirror of
https://github.com/weaveworks/scope.git
synced 2026-08-18 11:56:39 +00:00
No op gvt restore
This commit is contained in:
-44
@@ -1,44 +0,0 @@
|
||||
AUTHORS AND MAINTAINERS:
|
||||
|
||||
MAIN DEVELOPERS:
|
||||
Graeme Connell <gconnell@google.com, gsconnell@gmail.com>
|
||||
|
||||
AUTHORS:
|
||||
Nigel Tao <nigeltao@google.com>
|
||||
Cole Mickens <cole.mickens@gmail.com>
|
||||
Ben Daglish <bdaglish@restorepoint.com>
|
||||
Luis Martinez <martinezlc99@gmail.com>
|
||||
Remco Verhoef <remco@dutchcoders.io>
|
||||
Hiroaki Kawai <Hiroaki.Kawai@gmail.com>
|
||||
Lukas Lueg <lukas.lueg@gmail.com>
|
||||
Laurent Hausermann <laurent.hausermann@gmail.com>
|
||||
Bill Green <bgreen@newrelic.com>
|
||||
|
||||
CONTRIBUTORS:
|
||||
Attila Oláh <attila@attilaolah.eu>
|
||||
Vittus Mikiassen <matt.miki.vimik@gmail.com>
|
||||
Matthias Radestock <matthias.radestock@gmail.com>
|
||||
Matthew Sackman <matthew@wellquite.org>
|
||||
Loic Prylli <loicp@google.com>
|
||||
Alexandre Fiori <fiorix@gmail.com>
|
||||
Adrian Tam <adrian.c.m.tam@gmail.com>
|
||||
Satoshi Matsumoto <kaorimatz@gmail.com>
|
||||
David Stainton <dstainton415@gmail.com>
|
||||
|
||||
-----------------------------------------------
|
||||
FORKED FROM github.com/akrennmair/gopcap
|
||||
ALL THE FOLLOWING ARE FOR THAT PROJECT
|
||||
|
||||
MAIN DEVELOPERS:
|
||||
Andreas Krennmair <ak@synflood.at>
|
||||
|
||||
CONTRIBUTORS:
|
||||
Andrea Nall <anall@andreanall.com>
|
||||
Daniel Arndt <danielarndt@gmail.com>
|
||||
Dustin Sallings <dustin@spy.net>
|
||||
Graeme Connell <gconnell@google.com, gsconnell@gmail.com>
|
||||
Guillaume Savary <guillaume@savary.name>
|
||||
Mark Smith <mark@qq.is>
|
||||
Miek Gieben <miek@miek.nl>
|
||||
Mike Bell <mike@mikebell.org>
|
||||
Trevor Strohman <strohman@google.com>
|
||||
-1
@@ -1 +0,0 @@
|
||||
See https://code.google.com/p/gopacket/wiki/ChangeLog
|
||||
-233
@@ -1,233 +0,0 @@
|
||||
Contributing To gopacket
|
||||
========================
|
||||
|
||||
So you've got some code and you'd like it to be part of gopacket... wonderful!
|
||||
We're happy to accept contributions, whether they're fixes to old protocols, new
|
||||
protocols entirely, or anything else you think would improve the gopacket
|
||||
library. This document is designed to help you to do just that.
|
||||
|
||||
The first section deals with the plumbing: how to actually get a change
|
||||
submitted.
|
||||
|
||||
The second section deals with coding style... Go is great in that it
|
||||
has a uniform style implemented by 'go fmt', but there's still some decisions
|
||||
we've made that go above and beyond, and if you follow them, they won't come up
|
||||
in your code review.
|
||||
|
||||
The third section deals with some of the implementation decisions we've made,
|
||||
which may help you to understand the current code and which we may ask you to
|
||||
conform to (or provide compelling reasons for ignoring).
|
||||
|
||||
Overall, we hope this document will help you to understand our system and write
|
||||
great code which fits in, and help us to turn around on your code review quickly
|
||||
so the code can make it into the master branch as quickly as possible.
|
||||
|
||||
|
||||
How To Submit Code
|
||||
------------------
|
||||
|
||||
gopacket uses the code.google.com Git version control system. If you want to
|
||||
make a new change, you'll first have to get our code:
|
||||
|
||||
go get code.google.com/p/gopacket
|
||||
cd $GOROOT/src/pkg/code.google.com/p/gopacket
|
||||
git checkout -b <mynewfeature> # create a new branch to work from
|
||||
... code code code ...
|
||||
./gc # Run this to do local commits, it performs a number of checks
|
||||
... code code code ...
|
||||
./gc --benchmark # Run this whenever your commit could affect performance
|
||||
|
||||
Nw that you're in the gopacket code directory, you can start making your initial
|
||||
change. PLEASE make sure you're using a new branch to develop whatever feature
|
||||
you're working on.
|
||||
|
||||
Once you've got your code to a place where you're ready to have us look at it,
|
||||
send an email to gopacket@googlegroups.com, detailing your change. We'll add
|
||||
you as a committer, and you can upload your feature branch to code.google.com.
|
||||
From there, the other folks working on gopacket can give you code reviews with
|
||||
the code.google.com code review functionality.
|
||||
|
||||
The code review will generally be either emails or line-by-line reviews via
|
||||
code.google.com. One or more folks might review your code. The review should
|
||||
be considered "complete" when at least one of the project Owners (see
|
||||
https://code.google.com/p/gopacket/people/list) gives you permission to merge to
|
||||
master. At that point, you can merge to master yourself, or you can have one of
|
||||
the other committers/owners do it for you.
|
||||
|
||||
When doing the final merge, please try to capture any interesting comments or
|
||||
discussions that came up in code review. This will help future contributors be
|
||||
able to find and reference those discussions later on.
|
||||
|
||||
To sum up:
|
||||
|
||||
* DO
|
||||
+ Pull down the latest version.
|
||||
+ Make a feature-specific branch.
|
||||
+ Code using the style and methods discussed in the rest of this document.
|
||||
+ Use the ./gc command to do local commits.
|
||||
+ Send an email asking us to make you a committer (if you're new).
|
||||
+ Push your new feature branch up to code.google.com.
|
||||
+ Handle comments and requests from reviewers, pushing new commits up to
|
||||
your feature branch as problems are addressed.
|
||||
+ Get approval from a project Owner to merge to master.
|
||||
+ Merge yourself, or have another Committer/Owner do it for you.
|
||||
+ Put interesting comments and discussions into commit comments.
|
||||
* DON'T
|
||||
+ Push directly to master.
|
||||
+ Push to someone else's branch without their permission.
|
||||
+ Merge your own code to master without sign-off from others on the project.
|
||||
+ Rebase (please merge)
|
||||
* OPTIONAL
|
||||
+ Review others' code as it comes in (politely :)
|
||||
+ Keep contributing!
|
||||
|
||||
|
||||
Coding Style
|
||||
------------
|
||||
|
||||
* Go code must be run through 'go fmt'.
|
||||
* Follow http://golang.org/doc/effective_go.html as much as possible.
|
||||
+ In particular, http://golang.org/doc/effective_go.html#mixed-caps. Enums
|
||||
should be be CamelCase, with acronyms capitalized (TCPSourcePort, vs.
|
||||
TcpSourcePort or TCP_SOURCE_PORT).
|
||||
* Bonus points for giving enum types a String() field.
|
||||
* Any exported types or functions should have commentary
|
||||
(http://golang.org/doc/effective_go.html#commentary)
|
||||
|
||||
|
||||
Coding Methods And Implementation Notes
|
||||
---------------------------------------
|
||||
|
||||
### Error Handling
|
||||
|
||||
Many times, you'll be decoding a protocol and run across something bad, a packet
|
||||
corruption or the like. How do you handle this? First off, ALWAYS report the
|
||||
error. You can do this either by returning the error from the decode() function
|
||||
(most common), or if you're up for it you can implement and add an ErrorLayer
|
||||
through the packet builder (the first method is a simple shortcut that does
|
||||
exactly this, then stops any future decoding).
|
||||
|
||||
Often, you'll already have decode some part of your protocol by the time you hit
|
||||
your error. Use your own discretion to determine whether the stuff you've
|
||||
already decoded should be returned to the caller or not:
|
||||
|
||||
func decodeMyProtocol(data []byte, p gopacket.PacketBuilder) error {
|
||||
prot := &MyProtocol{}
|
||||
if len(data) < 10 {
|
||||
// This error occurred before we did ANYTHING, so there's nothing in my
|
||||
// protocol that the caller could possibly want. Just return the error.
|
||||
return fmt.Errorf("Length %d less than 10", len(data))
|
||||
}
|
||||
prot.ImportantField1 = data[:5]
|
||||
prot.ImportantField2 = data[5:10]
|
||||
// At this point, we've already got enough information in 'prot' to
|
||||
// warrant returning it to the caller, so we'll add it now.
|
||||
p.AddLayer(prot)
|
||||
if len(data) < 15 {
|
||||
// We encountered an error later in the packet, but the caller already
|
||||
// has the important info we've gleaned so far.
|
||||
return fmt.Errorf("Length %d less than 15", len(data))
|
||||
}
|
||||
prot.ImportantField3 = data[10:15]
|
||||
return nil // We've already added the layer, we can just return success.
|
||||
}
|
||||
|
||||
In general, our code follows the approach of returning the first error it
|
||||
encounters. In general, we don't trust any bytes after the first error we see.
|
||||
|
||||
### What Is A Layer?
|
||||
|
||||
The definition of a layer is up to the discretion of the coder. It should be
|
||||
something important enough that it's actually useful to the caller (IE: every
|
||||
TLV value should probably NOT be a layer). However, it can be more granular
|
||||
than a single protocol... IPv6 and SCTP both implement many layers to handle the
|
||||
various parts of the protocol. Use your best judgement, and prepare to defend
|
||||
your decisions during code review. ;)
|
||||
|
||||
### Performance
|
||||
|
||||
We strive to make gopacket as fast as possible while still providing lots of
|
||||
features. In general, this means:
|
||||
|
||||
* Focus performance tuning on common protocols (IP4/6, TCP, etc), and optimize
|
||||
others on an as-needed basis (tons of MPLS on your network? Time to optimize
|
||||
MPLS!)
|
||||
* Use fast operations. See the toplevel benchmark_test for benchmarks of some
|
||||
of Go's underlying features and types.
|
||||
* Test your performance changes! You should use the ./gc script's --benchmark
|
||||
flag to submit any performance-related changes. Use pcap/gopacket_benchmark
|
||||
to test your change against a PCAP file based on your traffic patterns.
|
||||
* Don't be TOO hacky. Sometimes, removing an unused struct from a field causes
|
||||
a huge performance hit, due to the way that Go currently handles its segmented
|
||||
stack... don't be afraid to clean it up anyway. We'll trust the Go compiler
|
||||
to get good enough over time to handle this. Also, this type of
|
||||
compiler-specific optimization is very fragile; someone adding a field to an
|
||||
entirely different struct elsewhere in the codebase could reverse any gains
|
||||
you might achieve by aligning your allocations.
|
||||
* Try to minimize memory allocations. If possible, use []byte to reference
|
||||
pieces of the input, instead of using string, which requires copying the bytes
|
||||
into a new memory allocation.
|
||||
* Think hard about what should be evaluated lazily vs. not. In general, a
|
||||
layer's struct should almost exactly mirror the layer's frame. Anything
|
||||
that's more interesting should be a function. This may not always be
|
||||
possible, but it's a good rule of thumb.
|
||||
* Don't fear micro-optimizations. With the above in mind, we welcome
|
||||
micro-optimizations that we think will have positive/neutral impacts on the
|
||||
majority of workloads. A prime example of this is pre-allocating certain
|
||||
structs within a larger one:
|
||||
|
||||
type MyProtocol struct {
|
||||
// Most packets have 1-4 of VeryCommon, so we preallocate it here.
|
||||
initialAllocation [4]uint32
|
||||
VeryCommon []uint32
|
||||
}
|
||||
|
||||
func decodeMyProtocol(data []byte, p gopacket.PacketBuilder) error {
|
||||
prot := &MyProtocol{}
|
||||
prot.VeryCommon = proto.initialAllocation[:0]
|
||||
for len(data) > 4 {
|
||||
field := binary.BigEndian.Uint32(data[:4])
|
||||
data = data[4:]
|
||||
// Since we're using the underlying initialAllocation, we won't need to
|
||||
// allocate new memory for the following append unless we more than 16
|
||||
// bytes of data, which should be the uncommon case.
|
||||
prot.VeryCommon = append(prot.VeryCommon, field)
|
||||
}
|
||||
p.AddLayer(prot)
|
||||
if len(data) > 0 {
|
||||
return fmt.Errorf("MyProtocol packet has %d bytes left after decoding", len(data))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
### Slices And Data
|
||||
|
||||
If you're pulling a slice from the data you're decoding, don't copy it. Just
|
||||
use the slice itself.
|
||||
|
||||
type MyProtocol struct {
|
||||
A, B net.IP
|
||||
}
|
||||
func decodeMyProtocol(data []byte, p gopacket.PacketBuilder) error {
|
||||
p.AddLayer(&MyProtocol{
|
||||
A: data[:4],
|
||||
B: data[4:8],
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
The caller has already agreed, by using this library, that they won't modify the
|
||||
set of bytes they pass in to the decoder, or the library has already copied the
|
||||
set of bytes to a read-only location. See DecodeOptions.NoCopy for more
|
||||
information.
|
||||
|
||||
### Enums/Types
|
||||
|
||||
If a protocol has an integer field (uint8, uint16, etc) with a couple of known
|
||||
values that mean something special, make it a type. This allows us to do really
|
||||
nice things like adding a String() function to them, so we can more easily
|
||||
display those to users. Check out layers/enums.go for one example, as well as
|
||||
layers/icmp.go for layer-specific enums.
|
||||
|
||||
When naming things, try for descriptiveness over suscinctness. For example,
|
||||
choose DNSResponseRecord over DNSRR.
|
||||
-10
@@ -1,10 +0,0 @@
|
||||
# GoPacket
|
||||
|
||||
This library provides packet decoding capabilities for Go.
|
||||
See [godoc](https://godoc.org/github.com/google/gopacket) for more details.
|
||||
|
||||
[](https://travis-ci.org/google/gopacket)
|
||||
[](https://godoc.org/github.com/google/gopacket)
|
||||
|
||||
Originally forked from the gopcap project written by Andreas
|
||||
Krennmair <ak@synflood.at> (http://github.com/akrennmair/gopcap).
|
||||
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 46 KiB |
-271
@@ -1,271 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Copyright 2012 Google, Inc. All rights reserved.
|
||||
|
||||
# This script provides a simple way to run benchmarks against previous code and
|
||||
# keep a log of how benchmarks change over time. When used with the --benchmark
|
||||
# flag, it runs benchmarks from the current code and from the last commit run
|
||||
# with --benchmark, then stores the results in the git commit description. We
|
||||
# rerun the old benchmarks along with the new ones, since there's no guarantee
|
||||
# that git commits will happen on the same machine, so machine differences could
|
||||
# cause wildly inaccurate results.
|
||||
#
|
||||
# If you're making changes to 'gopacket' which could cause performance changes,
|
||||
# you may be requested to use this commit script to make sure your changes don't
|
||||
# have large detrimental effects (or to show off how awesome your performance
|
||||
# improvements are).
|
||||
#
|
||||
# If not run with the --benchmark flag, this script is still very useful... it
|
||||
# makes sure all the correct go formatting, building, and testing work as
|
||||
# expected.
|
||||
|
||||
function Usage {
|
||||
cat <<EOF
|
||||
USAGE: $0 [--benchmark regexp] [--root] [--gen] <git commit flags...>
|
||||
|
||||
--benchmark: Run benchmark comparisons against last benchmark'd commit
|
||||
--root: Run tests that require root priviledges
|
||||
--gen: Generate code for MACs/ports by pulling down external data
|
||||
|
||||
Note, some 'git commit' flags are necessary, if all else fails, pass in -a
|
||||
EOF
|
||||
exit 1
|
||||
}
|
||||
|
||||
BENCH=""
|
||||
GEN=""
|
||||
ROOT=""
|
||||
while [ ! -z "$1" ]; do
|
||||
case "$1" in
|
||||
"--benchmark")
|
||||
BENCH="$2"
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
"--gen")
|
||||
GEN="yes"
|
||||
shift
|
||||
;;
|
||||
"--root")
|
||||
ROOT="yes"
|
||||
shift
|
||||
;;
|
||||
"--help")
|
||||
Usage
|
||||
;;
|
||||
"-h")
|
||||
Usage
|
||||
;;
|
||||
"help")
|
||||
Usage
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
function Root {
|
||||
if [ ! -z "$ROOT" ]; then
|
||||
local exec="$1"
|
||||
# Some folks (like me) keep source code in places inaccessible by root (like
|
||||
# NFS), so to make sure things run smoothly we copy them to a /tmp location.
|
||||
local tmpfile="$(mktemp -t gopacket_XXXXXXXX)"
|
||||
echo "Running root test executable $exec as $tmpfile"
|
||||
cp "$exec" "$tmpfile"
|
||||
chmod a+x "$tmpfile"
|
||||
shift
|
||||
sudo "$tmpfile" "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
if [ "$#" -eq "0" ]; then
|
||||
Usage
|
||||
fi
|
||||
|
||||
cd $(dirname $0)
|
||||
|
||||
# Check for copyright notices.
|
||||
for filename in $(find ./ -type f -name '*.go'); do
|
||||
if ! head -n 1 "$filename" | grep -q Copyright; then
|
||||
echo "File '$filename' may not have copyright notice"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
set -e
|
||||
set -x
|
||||
|
||||
if [ ! -z "$ROOT" ]; then
|
||||
echo "Running SUDO to get root priviledges for root tests"
|
||||
sudo echo "have root"
|
||||
fi
|
||||
|
||||
if [ ! -z "$GEN" ]; then
|
||||
pushd macs
|
||||
go run gen.go | gofmt > valid_mac_prefixes.go
|
||||
popd
|
||||
pushd layers
|
||||
go run gen.go | gofmt > iana_ports.go
|
||||
popd
|
||||
fi
|
||||
|
||||
# Make sure everything is formatted, compiles, and tests pass.
|
||||
go fmt ./...
|
||||
go test -i ./... 2>/dev/null >/dev/null || true
|
||||
go test
|
||||
go build
|
||||
pushd examples/bytediff
|
||||
go build
|
||||
popd
|
||||
if [ -f /usr/include/pcap.h ]; then
|
||||
pushd pcap
|
||||
go test ./...
|
||||
go build ./...
|
||||
go build pcap_tester.go
|
||||
Root pcap_tester --mode=basic
|
||||
Root pcap_tester --mode=filtered
|
||||
Root pcap_tester --mode=timestamp || echo "You might not support timestamp sources"
|
||||
popd
|
||||
pushd examples/pcapdump
|
||||
go build
|
||||
popd
|
||||
pushd examples/arpscan
|
||||
go build
|
||||
popd
|
||||
pushd examples/bidirectional
|
||||
go build
|
||||
popd
|
||||
pushd examples/synscan
|
||||
go build
|
||||
popd
|
||||
pushd examples/httpassembly
|
||||
go build
|
||||
popd
|
||||
pushd examples/statsassembly
|
||||
go build
|
||||
popd
|
||||
fi
|
||||
pushd macs
|
||||
go test ./...
|
||||
gofmt -w gen.go
|
||||
go build gen.go
|
||||
popd
|
||||
pushd tcpassembly
|
||||
go test ./...
|
||||
popd
|
||||
pushd layers
|
||||
gofmt -w gen.go
|
||||
go build gen.go
|
||||
go test ./...
|
||||
popd
|
||||
pushd pcapgo
|
||||
go test ./...
|
||||
go build ./...
|
||||
popd
|
||||
if [ -f /usr/include/linux/if_packet.h ]; then
|
||||
if grep -q TPACKET_V3 /usr/include/linux/if_packet.h; then
|
||||
pushd afpacket
|
||||
go build ./...
|
||||
go test ./...
|
||||
popd
|
||||
fi
|
||||
fi
|
||||
if [ -f /usr/include/pfring.h ]; then
|
||||
pushd pfring
|
||||
go test ./...
|
||||
go build ./...
|
||||
popd
|
||||
pushd examples/pfdump
|
||||
go build
|
||||
popd
|
||||
fi
|
||||
|
||||
# Run our initial commit
|
||||
git commit "$@"
|
||||
|
||||
if [ -z "$BENCH" ]; then
|
||||
set +x
|
||||
echo "We're not benchmarking and we've committed... we're done!"
|
||||
exit
|
||||
fi
|
||||
|
||||
### If we get here, we want to run benchmarks from current commit, and compare
|
||||
### then to benchmarks from the last --benchmark commit.
|
||||
|
||||
# Get our current branch.
|
||||
BRANCH="$(git branch | grep '^*' | awk '{print $2}')"
|
||||
|
||||
# File we're going to build our commit description in.
|
||||
COMMIT_FILE="$(mktemp /tmp/tmp.XXXXXXXX)"
|
||||
|
||||
# Add the word "BENCH" to the start of the git commit.
|
||||
echo -n "BENCH " > $COMMIT_FILE
|
||||
|
||||
# Get the current description... there must be an easier way.
|
||||
git log -n 1 | grep '^ ' | sed 's/^ //' >> $COMMIT_FILE
|
||||
|
||||
# Get the commit sha for the last benchmark commit
|
||||
PREV=$(git log -n 1 --grep='BENCHMARK_MARKER_DO_NOT_CHANGE' | head -n 1 | awk '{print $2}')
|
||||
|
||||
## Run current benchmarks
|
||||
|
||||
cat >> $COMMIT_FILE <<EOF
|
||||
|
||||
|
||||
----------------------------------------------------------
|
||||
BENCHMARK_MARKER_DO_NOT_CHANGE
|
||||
----------------------------------------------------------
|
||||
|
||||
Go version $(go version)
|
||||
|
||||
|
||||
TEST BENCHMARKS "$BENCH"
|
||||
EOF
|
||||
# go seems to have trouble with 'go test --bench=. ./...'
|
||||
go test --test.bench="$BENCH" 2>&1 | tee -a $COMMIT_FILE
|
||||
pushd layers
|
||||
go test --test.bench="$BENCH" 2>&1 | tee -a $COMMIT_FILE
|
||||
popd
|
||||
cat >> $COMMIT_FILE <<EOF
|
||||
|
||||
|
||||
PCAP BENCHMARK
|
||||
EOF
|
||||
if [ "$BENCH" -eq ".*" ]; then
|
||||
go run pcap/gopacket_benchmark/*.go 2>&1 | tee -a $COMMIT_FILE
|
||||
fi
|
||||
|
||||
|
||||
|
||||
## Reset to last benchmark commit, run benchmarks
|
||||
|
||||
git checkout $PREV
|
||||
|
||||
cat >> $COMMIT_FILE <<EOF
|
||||
----------------------------------------------------------
|
||||
BENCHMARKING AGAINST COMMIT $PREV
|
||||
----------------------------------------------------------
|
||||
|
||||
|
||||
OLD TEST BENCHMARKS
|
||||
EOF
|
||||
# go seems to have trouble with 'go test --bench=. ./...'
|
||||
go test --test.bench="$BENCH" 2>&1 | tee -a $COMMIT_FILE
|
||||
pushd layers
|
||||
go test --test.bench="$BENCH" 2>&1 | tee -a $COMMIT_FILE
|
||||
popd
|
||||
cat >> $COMMIT_FILE <<EOF
|
||||
|
||||
|
||||
OLD PCAP BENCHMARK
|
||||
EOF
|
||||
if [ "$BENCH" -eq ".*" ]; then
|
||||
go run pcap/gopacket_benchmark/*.go 2>&1 | tee -a $COMMIT_FILE
|
||||
fi
|
||||
|
||||
|
||||
|
||||
## Reset back to the most recent commit, edit the commit message by appending
|
||||
## benchmark results.
|
||||
git checkout $BRANCH
|
||||
git commit --amend -F $COMMIT_FILE
|
||||
-103
@@ -1,103 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
# Copyright 2012 Google, Inc. All rights reserved.
|
||||
|
||||
"""TestCreator creates test templates from pcap files."""
|
||||
|
||||
import argparse
|
||||
import base64
|
||||
import glob
|
||||
import re
|
||||
import string
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
|
||||
class Packet(object):
|
||||
"""Helper class encapsulating packet from a pcap file."""
|
||||
|
||||
def __init__(self, packet_lines):
|
||||
self.packet_lines = packet_lines
|
||||
self.data = self._DecodeText(packet_lines)
|
||||
|
||||
@classmethod
|
||||
def _DecodeText(cls, packet_lines):
|
||||
packet_bytes = []
|
||||
# First line is timestamp and stuff, skip it.
|
||||
# Format: 0x0010: 0000 0020 3aff 3ffe 0000 0000 0000 0000 ....:.?.........
|
||||
|
||||
for line in packet_lines[1:]:
|
||||
m = re.match(r'\s+0x[a-f\d]+:\s+((?:[\da-f]{2,4}\s)*)', line, re.IGNORECASE)
|
||||
if m is None: continue
|
||||
for hexpart in m.group(1).split():
|
||||
packet_bytes.append(base64.b16decode(hexpart.upper()))
|
||||
return ''.join(packet_bytes)
|
||||
|
||||
def Test(self, name, link_type):
|
||||
"""Yields a test using this packet, as a set of lines."""
|
||||
yield '// testPacket%s is the packet:' % name
|
||||
for line in self.packet_lines:
|
||||
yield '// ' + line
|
||||
yield 'var testPacket%s = []byte{' % name
|
||||
data = list(self.data)
|
||||
while data:
|
||||
linebytes, data = data[:16], data[16:]
|
||||
yield ''.join(['\t'] + ['0x%02x, ' % ord(c) for c in linebytes])
|
||||
yield '}'
|
||||
yield 'func TestPacket%s(t *testing.T) {' % name
|
||||
yield '\tp := gopacket.NewPacket(testPacket%s, LinkType%s, gopacket.Default)' % (name, link_type)
|
||||
yield '\tif p.ErrorLayer() != nil {'
|
||||
yield '\t\tt.Error("Failed to decode packet:", p.ErrorLayer().Error())'
|
||||
yield '\t}'
|
||||
yield '\tcheckLayers(p, []gopacket.LayerType{LayerType%s, FILL_ME_IN_WITH_ACTUAL_LAYERS}, t)' % link_type
|
||||
yield '}'
|
||||
yield 'func BenchmarkDecodePacket%s(b *testing.B) {' % name
|
||||
yield '\tfor i := 0; i < b.N; i++ {'
|
||||
yield '\t\tgopacket.NewPacket(testPacket%s, LinkType%s, gopacket.NoCopy)' % (name, link_type)
|
||||
yield '\t}'
|
||||
yield '}'
|
||||
|
||||
|
||||
|
||||
def GetTcpdumpOutput(filename):
|
||||
"""Runs tcpdump on the given file, returning output as string."""
|
||||
return subprocess.check_output(
|
||||
['tcpdump', '-XX', '-s', '0', '-n', '-r', filename])
|
||||
|
||||
|
||||
def TcpdumpOutputToPackets(output):
|
||||
"""Reads a pcap file with TCPDump, yielding Packet objects."""
|
||||
pdata = []
|
||||
for line in output.splitlines():
|
||||
if line[0] not in string.whitespace and pdata:
|
||||
yield Packet(pdata)
|
||||
pdata = []
|
||||
pdata.append(line)
|
||||
if pdata:
|
||||
yield Packet(pdata)
|
||||
|
||||
|
||||
def main():
|
||||
class CustomHelpFormatter(argparse.ArgumentDefaultsHelpFormatter):
|
||||
def _format_usage(self, usage, actions, groups, prefix=None):
|
||||
header =('TestCreator creates gopacket tests using a pcap file.\n\n'
|
||||
'Tests are written to standard out... they can then be \n'
|
||||
'copied into the file of your choice and modified as \n'
|
||||
'you see.\n\n')
|
||||
return header + argparse.ArgumentDefaultsHelpFormatter._format_usage(
|
||||
self, usage, actions, groups, prefix)
|
||||
|
||||
parser = argparse.ArgumentParser(formatter_class=CustomHelpFormatter)
|
||||
parser.add_argument('--link_type', default='Ethernet', help='the link type (default: %(default)s)')
|
||||
parser.add_argument('--name', default='Packet%d', help='the layer type, must have "%d" inside it')
|
||||
parser.add_argument('files', metavar='file.pcap', type=str, nargs='+', help='the files to process')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
for arg in args.files:
|
||||
for path in glob.glob(arg):
|
||||
for i, packet in enumerate(TcpdumpOutputToPackets(GetTcpdumpOutput(path))):
|
||||
print '\n'.join(packet.Test(
|
||||
args.name % i, args.link_type))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Reference in New Issue
Block a user