Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f78c4dacc5 | ||
|
|
9245b73913 | ||
|
|
6ee961b068 | ||
|
|
1f920513de | ||
|
|
15f21f1899 | ||
|
|
09a204b978 | ||
|
|
77fbb2c12b | ||
|
|
6ad3e69faf | ||
|
|
e2088ef401 | ||
|
|
0f3864968e | ||
|
|
2f235daa1c | ||
|
|
438a5f5fd1 | ||
|
|
b051ef0878 | ||
|
|
48015aa7be | ||
|
|
14730f8572 | ||
|
|
e7a24eaf0a | ||
|
|
15ad210bec | ||
|
|
6bc0e5e71c | ||
|
|
0ca831f50b | ||
|
|
57bca8e955 | ||
|
|
709f820ab6 | ||
|
|
599b99a6c4 | ||
|
|
4e3acfdc02 | ||
|
|
11915948a2 | ||
|
|
bb51a4f36d | ||
|
|
5d0e44bb6f | ||
|
|
6e7a469a62 | ||
|
|
ca0498b860 | ||
|
|
bbfa682083 | ||
|
|
f763c40c10 | ||
|
|
67037b43b0 | ||
|
|
861395011c | ||
|
|
8bdfcd3042 | ||
|
|
83024b946f | ||
|
|
4f48670345 | ||
|
|
4b30d97d4e | ||
|
|
c9e813cfcb | ||
|
|
c97c50b76e | ||
|
|
f919d06e2c | ||
|
|
526538d9d1 | ||
|
|
f43f3fc2e8 | ||
|
|
8b220f6383 | ||
|
|
d44e34584a | ||
|
|
6d2366ca4c | ||
|
|
7c1b615c98 | ||
|
|
390a4099d0 | ||
|
|
01237446eb | ||
|
|
18deb42df1 | ||
|
|
5c508f837e | ||
|
|
e000472af7 | ||
|
|
6d70284c21 | ||
|
|
4529d1587c | ||
|
|
b0d05f5e37 | ||
|
|
4a5d203e58 | ||
|
|
640c5c346c | ||
|
|
3780ce4dfb | ||
|
|
b871c1eecb | ||
|
|
02ecea4576 | ||
|
|
6876507641 | ||
|
|
d2c78d3196 | ||
|
|
5b8365687e | ||
|
|
a43bd88ddd | ||
|
|
e8fcd21baa | ||
|
|
6a48da60ec | ||
|
|
886dea9b10 | ||
|
|
80e9dee9b2 | ||
|
|
5110a604f8 | ||
|
|
404f1bbef3 | ||
|
|
56491b35f1 | ||
|
|
dd70668b89 | ||
|
|
e5441b44e9 | ||
|
|
4da2501d7a | ||
|
|
04680fc52c | ||
|
|
cb4a8769a8 | ||
|
|
62c1d28524 | ||
|
|
92b21ccd44 | ||
|
|
88cd86a5f2 | ||
|
|
b18c88524d | ||
|
|
90e0c43bf2 | ||
|
|
4215618177 | ||
|
|
cb5798f94d | ||
|
|
79e032c984 | ||
|
|
821b787774 | ||
|
|
3ed7894e39 | ||
|
|
30ed34bd2c | ||
|
|
f5c2f51964 | ||
|
|
4d7f0f5014 | ||
|
|
d1ed6c5747 | ||
|
|
44f91950cb | ||
|
|
d2f0287fa3 | ||
|
|
9c09e36135 | ||
|
|
cb8e06c994 | ||
|
|
753c7cce1e | ||
|
|
30b2bada28 | ||
|
|
eeec3833a3 | ||
|
|
ee47f0c3ee | ||
|
|
36a2146ed8 | ||
|
|
6afedb881c | ||
|
|
05ab1139db | ||
|
|
e90cbf290b | ||
|
|
1e0431f6b2 | ||
|
|
9971fc3dac | ||
|
|
7aa7e3c00d | ||
|
|
a4dd7fa198 | ||
|
|
e2157a5d04 | ||
|
|
fc199d0df5 | ||
|
|
cc6d10c9b1 | ||
|
|
ace2c12608 | ||
|
|
57c464d60e | ||
|
|
65b3894a8e | ||
|
|
77bfa6a7e4 | ||
|
|
9d485d0f21 | ||
|
|
991945081a | ||
|
|
123762ec8d | ||
|
|
b07db6479a | ||
|
|
d3f62905b7 | ||
|
|
22b3393cfd | ||
|
|
c8e7dbd600 | ||
|
|
ef26b306e4 | ||
|
|
1588a7259d | ||
|
|
3a92050ebb | ||
|
|
04c63879b8 | ||
|
|
96291d1de4 | ||
|
|
9090fddd9f | ||
|
|
5bcd33c930 | ||
|
|
959d0bf2e2 | ||
|
|
a547d4571c | ||
|
|
b05c5f63c8 | ||
|
|
309a85b29c | ||
|
|
90ccc4a014 | ||
|
|
a6f2ee5ccc | ||
|
|
dcadc0f8cc | ||
|
|
332808c524 | ||
|
|
db006060e6 | ||
|
|
7a6ba40982 | ||
|
|
75e106b667 | ||
|
|
b28e2ee384 | ||
|
|
785b6b4584 | ||
|
|
391613d015 | ||
|
|
7334869134 | ||
|
|
bb4f51499d | ||
|
|
cc88aa2145 | ||
|
|
4b5d827d94 | ||
|
|
802ede1cd3 | ||
|
|
5e69e8a7b4 | ||
|
|
2d912263b1 | ||
|
|
6e78a34a00 | ||
|
|
ac9d72875d | ||
|
|
51d7f455c9 | ||
|
|
89db74338e | ||
|
|
4c6879679d | ||
|
|
d35f2236e1 | ||
|
|
27848992b1 | ||
|
|
690b6ff2cd | ||
|
|
ea2084d871 | ||
|
|
8a4fc9c02a | ||
|
|
760bc10074 | ||
|
|
20d55fe47a | ||
|
|
4a1fbc7c38 | ||
|
|
11c55a3a07 | ||
|
|
a400d43df7 | ||
|
|
189cfa995c | ||
|
|
47d8f24e56 | ||
|
|
4f8fe2c13f | ||
|
|
873781ab58 | ||
|
|
06e0e6ace0 | ||
|
|
eb7ba691ee | ||
|
|
15b9b7416a | ||
|
|
5024270232 | ||
|
|
bd24dd7dae | ||
|
|
2c2a074a83 | ||
|
|
698e1b6d87 | ||
|
|
b248e021ec | ||
|
|
0d481ef0e9 | ||
|
|
0c2e046c86 | ||
|
|
21bc724632 | ||
|
|
16051a89b6 | ||
|
|
6130699ae5 | ||
|
|
e23e364476 | ||
|
|
8a5aa1a6ae | ||
|
|
9654df4d50 | ||
|
|
6f39a15b53 | ||
|
|
e8f35a848e | ||
|
|
43d3339b39 | ||
|
|
13644ee1b0 | ||
|
|
54d24e65ef | ||
|
|
e1e4a7887a | ||
|
|
17b45d9efa | ||
|
|
1bf07d86aa | ||
|
|
bba7b44248 | ||
|
|
d4d9ba1e35 | ||
|
|
d2a9a51296 | ||
|
|
583eea1ec5 | ||
|
|
81b17469f4 | ||
|
|
1c81fcb693 | ||
|
|
4a22dda13f |
No files matched your search
@@ -1,7 +1,7 @@
|
||||
version: 2
|
||||
defaults: &defaults
|
||||
docker:
|
||||
- image: weaveworks/weavebuild:circle20-2e6504d3
|
||||
- image: weaveworks/weavebuild:go-1-13-1-5110a604
|
||||
working_directory: /go/src/github.com/weaveworks/weave
|
||||
|
||||
jobs:
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
2.3.0
|
||||
2.6.2
|
||||
+108
@@ -1,3 +1,111 @@
|
||||
## Release 2.6.3
|
||||
|
||||
This release has a couple of security improvements, and some other fixes.
|
||||
|
||||
* Block non-local traffic to the Weave control port #3805
|
||||
* Tell Linux not to accept router advisory messages #3801
|
||||
* Network Policy Controller: add a metric to show errors while operating #3804
|
||||
* Network Policy Controller: don't treat named port as a fatal error #3790
|
||||
|
||||
## Release 2.6.2
|
||||
|
||||
This release fixes a regression found in 2.6.1 release and removes a possible case
|
||||
of CPU spinning when pcap is used in sleeve mode
|
||||
|
||||
### Bug fixes
|
||||
|
||||
* Weave Net can not be used in fastdp mode and always falls back to sleeve mode #3781, #3783
|
||||
* Restrict timeout value passed to pcap library to a value less than 2^31 microseconds to
|
||||
prevent CPU spinning #3782
|
||||
|
||||
## Release 2.6.1
|
||||
|
||||
This release fixes a bug discovered since the release of Weave Net 2.6.0 and
|
||||
an improvement to support iptables 1.8
|
||||
|
||||
### Bug fixes
|
||||
|
||||
* Weave Net on node restart unable to form connections to peers and connections get stuck in
|
||||
pending state and stops responding to API endpoint #3762 #3763
|
||||
|
||||
### Other improvements
|
||||
|
||||
* Weave Net Kubernetes images by default uses iptables 1.8 with legacy (netfilter) backend with
|
||||
option to choose netfilter as backend #3465, #3747
|
||||
|
||||
|
||||
## Release 2.6.0
|
||||
|
||||
This release reduces CPU and memory usage in larger clusters, by
|
||||
sending notifications to a smaller set of peers and coalescing updates
|
||||
to reduce topology recalculation. #3715, #3732
|
||||
|
||||
The default soft limit on connections has been raised from 100 to 200.
|
||||
|
||||
### Bug fixes
|
||||
|
||||
* Fix a race condition in Kubernetes addon when reclaiming IP
|
||||
addresses after node deletion #3724, #3716
|
||||
* Buffer events so Docker won't drop them, and Weave Net can clean up
|
||||
after dead containers #3432, #3705
|
||||
* Weave reconnect occasionally fails after network interface
|
||||
disconnect #3666, #3669, #3676
|
||||
* Ingress NetworkPolicy would accepts all traffic when specifying both
|
||||
IPBlock and port #3653, #3654
|
||||
|
||||
### Kubernetes improvements
|
||||
|
||||
* Support both podSelector and namespaceSelector in NetworkPolicy #3312, #3647
|
||||
* Only add default-drop egress rule if network policies are in use #3639
|
||||
* Manifests use 'apps/v1' rather than deprecated 'apps/v1beta1' #3660
|
||||
* Avoid Weave Net pods being evicted by setting priorityClassName: system-node-critical #3697
|
||||
* Manifests use recommended DNS policy ClusterFirstWithHostNet #3692
|
||||
* Weave Net now tolerates 'NoExecute' taint #3655
|
||||
* Allow extra arguments to NetworkPolicy controller to be set in an environment variable #3683
|
||||
* Stop reporting a failure to connect to self #3454, #3585
|
||||
* Minor reduction in log noise when reclaiming IPs #3710
|
||||
|
||||
### Other improvements
|
||||
|
||||
* Avoid isolating nodes which have restarted by automatically
|
||||
repairing inconsistencies in IP allocation data #1962, #3637, #3708
|
||||
* Build Weave Net for the s390x architecture #3685
|
||||
* When a IP address is requested that may be in use, make several
|
||||
attempts to claim it before returning an error #3725
|
||||
* Improve logging for IP allocation updates #3627, #3630
|
||||
* Improve 'expecting PMTU update' log message on initial connection #3603
|
||||
|
||||
### Build and test
|
||||
|
||||
* Shut down Kubernetes on node when testing node deletion #3716
|
||||
* Update the base 'Alpine' container image to version 3.8 #3701
|
||||
* Update Go to version 1.13.3 #3712
|
||||
* Update gopacket library #3590
|
||||
* Pin busybox version to 1.28 to avoid CI failure in Python test #3689
|
||||
* Remove obsolete weave-daemonset.yaml file #3674
|
||||
|
||||
Thanks to contributors @christian-2, @hpdvanwyk, @guirish, @kitt1987,
|
||||
@mmerrill3, @Pensu, @scritchley, @sidharthsurana, @tanishq-dubey
|
||||
|
||||
[Full list of changes](https://github.com/weaveworks/weave/milestone/78?closed=1)
|
||||
|
||||
|
||||
## Release 2.5.2
|
||||
|
||||
This release fixes several bugs causing inconsistencies in IPAM and fixes a
|
||||
panic in daemon that reclaims and forgets deleted nodes in Kubernetes clusters.
|
||||
|
||||
### Bug fixes
|
||||
|
||||
* leaking IP addresses in IPAM when weave-net hangs or restarting #3587, #3638
|
||||
* Panic in kube-utils after config map update error resulting in reclaim daemon
|
||||
not performing weave forget on deleted node #3613, #3623
|
||||
* preventing inconsistent IPAM entries and resolving the conflict in case of
|
||||
conflict during IPAM ring merge #3629, #3635, #3632, #3444
|
||||
|
||||
[Full list of changes](https://github.com/weaveworks/weave/milestone/79?closed=1)
|
||||
|
||||
|
||||
## Release 2.5.1
|
||||
|
||||
This release fixes bugs reported for 2.5 release and small improvements.
|
||||
|
||||
Generated
+16
-9
@@ -316,7 +316,7 @@
|
||||
revision = "24818f796faf91cd76ec7bddd72458fbced7a6c1"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:a1b2a09d080e0229db471efc7f030b6d3931cd54989f6a1a4d676e085139cc2d"
|
||||
digest = "1:b23296076e13a960263285b98907623e5d45f12fc405b14da19c6afa2a113deb"
|
||||
name = "github.com/google/gopacket"
|
||||
packages = [
|
||||
".",
|
||||
@@ -325,8 +325,8 @@
|
||||
"pcapgo",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "11c65f1ca9081dfea43b4f9643f5c155583b73ba"
|
||||
version = "v1.1.14"
|
||||
revision = "7f3fc6cbbb499248dca53da7fe3ed6c25a78d22f"
|
||||
version = "v1.1.16"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:5e031a35b76ee001fa9ca9d598298054a123d080e00d13a8dafcfc5e3ecd5b58"
|
||||
@@ -441,6 +441,14 @@
|
||||
revision = "3247c84500bff8d9fb6d579d800f20b3e091582c"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:450f3a64f7a76d3f229ff33a30f0a889629dde46b0f82ece7c53404528316665"
|
||||
name = "github.com/mdlayher/raw"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "fa5ef3332ca961deab5782da07b1616fea8a9dd8"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:2b32af4d2a529083275afc192d1067d8126b578c7a9613b26600e4df9c735155"
|
||||
@@ -678,12 +686,12 @@
|
||||
revision = "6b0aa22550d9325eb8f43418185859e13dc0de1d"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:277e090a58afaeb00fb9fd04e2b2f3466ff8fb327a331e0e531a3399a72697e3"
|
||||
digest = "1:dfa8458da99855b0f0e13f580e6107b46311db15dc7f76cb80c131b937f7f8aa"
|
||||
name = "github.com/weaveworks/mesh"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "38e8100dfbc7b28ae8ffde5a2bbeceec57ffa52a"
|
||||
version = "v0.1"
|
||||
revision = "58dbcc3e8e63eed7dd77f3a6286855ae8c8876c1"
|
||||
version = "v0.4"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
@@ -728,14 +736,14 @@
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:5045bd5ed8083958e27c933e665c38b4de5d7d966146a074d541f691a56d8bc4"
|
||||
digest = "1:653cc9ff57cf744d21f74e811af4f330415284bfc291d28f716833618c02c876"
|
||||
name = "golang.org/x/sys"
|
||||
packages = [
|
||||
"unix",
|
||||
"windows",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "13d03a9a82fba647c21a0ef8fba44a795d0f0835"
|
||||
revision = "afcc84fd7533758f95a6e93ae710aa945a0b7e73"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18"
|
||||
@@ -1100,7 +1108,6 @@
|
||||
"github.com/weaveworks/mesh",
|
||||
"golang.org/x/crypto/hkdf",
|
||||
"golang.org/x/crypto/nacl/secretbox",
|
||||
"golang.org/x/net/context",
|
||||
"golang.org/x/sys/unix",
|
||||
"golang.org/x/tools/cover",
|
||||
"k8s.io/api/core/v1",
|
||||
|
||||
@@ -17,15 +17,15 @@ QEMU_VERSION=v2.7.0
|
||||
|
||||
# A list of all supported architectures here. Should be named as Go is naming platforms
|
||||
# All supported architectures must have an "ifeq" block below that customizes the parameters
|
||||
ALL_ARCHITECTURES=amd64 arm arm64 ppc64le
|
||||
ML_PLATFORMS=linux/amd64,linux/arm,linux/arm64,linux/ppc64le
|
||||
ALL_ARCHITECTURES=amd64 arm arm64 ppc64le s390x
|
||||
ML_PLATFORMS=linux/amd64,linux/arm,linux/arm64,linux/ppc64le,linux/s390x
|
||||
|
||||
ifeq ($(ARCH),amd64)
|
||||
# The architecture to use when downloading the docker binary
|
||||
WEAVEEXEC_DOCKER_ARCH?=x86_64
|
||||
|
||||
# The name of the alpine baseimage to use as the base for weave images
|
||||
ALPINE_BASEIMAGE?=alpine:3.6
|
||||
ALPINE_BASEIMAGE?=alpine:3.10
|
||||
|
||||
# The extension for the made images
|
||||
# Specifying none means for example weaveworks/weave:latest
|
||||
@@ -42,7 +42,7 @@ ifeq ($(ARCH),arm)
|
||||
WEAVEEXEC_DOCKER_ARCH?=armel
|
||||
|
||||
# Using the (semi-)official alpine image
|
||||
ALPINE_BASEIMAGE?=arm32v6/alpine:3.6
|
||||
ALPINE_BASEIMAGE?=arm32v6/alpine:3.8
|
||||
|
||||
# arm images have the -arm suffix, for instance weaveworks/weave-arm:latest
|
||||
ARCH_EXT?=-arm
|
||||
@@ -62,7 +62,7 @@ ifeq ($(ARCH),arm64)
|
||||
WEAVEEXEC_DOCKER_ARCH?=armel
|
||||
|
||||
# Using the (semi-)official alpine image
|
||||
ALPINE_BASEIMAGE?=arm64v8/alpine:3.6
|
||||
ALPINE_BASEIMAGE?=arm64v8/alpine:3.8
|
||||
|
||||
# arm64 images have the -arm64 suffix, for instance weaveworks/weave-arm64:latest
|
||||
ARCH_EXT?=-arm64
|
||||
@@ -82,7 +82,7 @@ ifeq ($(ARCH),ppc64le)
|
||||
WEAVEEXEC_DOCKER_ARCH?=ppc64le
|
||||
|
||||
# Using the (semi-)official alpine image
|
||||
ALPINE_BASEIMAGE?=ppc64le/alpine:3.6
|
||||
ALPINE_BASEIMAGE?=ppc64le/alpine:3.8
|
||||
|
||||
# ppc64le images have the -ppc64le suffix, for instance weaveworks/weave-ppc64le:latest
|
||||
ARCH_EXT?=-ppc64le
|
||||
@@ -97,6 +97,26 @@ ifeq ($(ARCH),ppc64le)
|
||||
# Tell the gcc linker to search for libpcap here
|
||||
CGO_LDFLAGS="-L/usr/local/lib/$(CC)"
|
||||
endif
|
||||
ifeq ($(ARCH),s390x)
|
||||
# The architecture to use when downloading the docker binary
|
||||
WEAVEEXEC_DOCKER_ARCH?=s390x
|
||||
|
||||
# Using the (semi-)official alpine image
|
||||
ALPINE_BASEIMAGE?=s390x/alpine:3.6
|
||||
|
||||
# s390x images have the -s390x suffix, for instance weaveworks/weave-s390x:latest
|
||||
ARCH_EXT?=-s390x
|
||||
|
||||
# The name of the gcc binary
|
||||
CC=s390x-linux-gnu-gcc
|
||||
|
||||
# The architecture name to use when downloading a prebuilt QEMU binary
|
||||
QEMUARCH=s390x
|
||||
|
||||
# In the weaveworks/build image; libpcap libraries for s390x are placed here
|
||||
# Tell the gcc linker to search for libpcap here
|
||||
CGO_LDFLAGS="-L/usr/local/lib/$(CC)"
|
||||
endif
|
||||
|
||||
# The name of the user that this Makefile should produce image artifacts for. Can/should be overridden
|
||||
DOCKERHUB_USER?=weaveworks
|
||||
@@ -156,18 +176,11 @@ PUSH_ML=push_ml_weave push_ml_weaveexec push_ml_weave-kube push_ml_weave-npc
|
||||
|
||||
WEAVE_EXPORT=weave$(ARCH_EXT).tar.gz
|
||||
|
||||
NETGO_CHECK=@strings $@ | grep cgo_stub\\\.go >/dev/null || { \
|
||||
rm $@; \
|
||||
echo "\nYour go standard library was built without the 'netgo' build tag."; \
|
||||
echo "To fix that, run"; \
|
||||
echo " sudo go clean -i net"; \
|
||||
echo " sudo go install -tags netgo std"; \
|
||||
false; \
|
||||
}
|
||||
# The flags we are passing to go build. -extldflags -static for making a static binary,
|
||||
# -linkmode external for linking external C libraries into the binary, -X main.version for telling the
|
||||
# Go binary which version it is, -tags netgo for enforcing the native Go DNS resolver
|
||||
BUILD_FLAGS=-i -ldflags "-linkmode external -extldflags -static -X main.version=$(WEAVE_VERSION)" -tags netgo
|
||||
# -X main.version for telling the Go binary which version it is,
|
||||
# -s -w drop symbol tables used by debuggers (not Go's internal symbol info)
|
||||
# -tags "osusergo netgo" to use native Go UID and DNS implementations
|
||||
BUILD_FLAGS=-ldflags "-extldflags -static -X main.version=$(WEAVE_VERSION) -s -w" -tags "osusergo netgo"
|
||||
|
||||
PACKAGE_BASE=$(shell go list -e ./)
|
||||
|
||||
@@ -196,10 +209,8 @@ ifeq ($(BUILD_IN_CONTAINER),true)
|
||||
# This make target compiles all binaries inside of the weaveworks/build container
|
||||
# It bind-mounts the source into the container and passes all important variables
|
||||
exes $(EXES) tests lint: $(BUILD_UPTODATE)
|
||||
@mkdir -p $(shell pwd)/.pkg
|
||||
$(SUDO) docker run $(RM) $(RUN_FLAGS) \
|
||||
-v $(shell pwd):/go/src/github.com/weaveworks/weave \
|
||||
-v $(shell pwd)/.pkg:/go/pkg \
|
||||
-e GOARCH=$(ARCH) -e CGO_ENABLED=1 -e GOOS=linux -e CIRCLECI -e CIRCLE_BUILD_NUM -e CIRCLE_NODE_TOTAL -e CIRCLE_NODE_INDEX -e COVERDIR -e SLOW -e DEBUG \
|
||||
$(BUILD_IMAGE) COVERAGE=$(COVERAGE) WEAVE_VERSION=$(WEAVE_VERSION) CC=$(CC) QEMUARCH=$(QEMUARCH) CGO_LDFLAGS=$(CGO_LDFLAGS) $@
|
||||
touch $@
|
||||
@@ -215,19 +226,15 @@ ifeq ($(COVERAGE),true)
|
||||
else
|
||||
go build $(BUILD_FLAGS) -o $@ ./$(@D)
|
||||
endif
|
||||
$(NETGO_CHECK)
|
||||
|
||||
$(WEAVEUTIL_EXE) $(KUBEUTILS_EXE) $(WEAVENPC_EXE) $(NETWORKTESTER_EXE):
|
||||
go build $(BUILD_FLAGS) -o $@ ./$(@D)
|
||||
$(NETGO_CHECK)
|
||||
|
||||
$(WEAVEWAIT_EXE):
|
||||
go build $(BUILD_FLAGS) -tags "netgo iface mcast" -o $@ ./$(@D)
|
||||
$(NETGO_CHECK)
|
||||
go build $(BUILD_FLAGS) -tags "osusergo netgo iface mcast" -o $@ ./$(@D)
|
||||
|
||||
$(WEAVEWAIT_NOMCAST_EXE):
|
||||
go build $(BUILD_FLAGS) -tags "netgo iface" -o $@ ./$(@D)
|
||||
$(NETGO_CHECK)
|
||||
go build $(BUILD_FLAGS) -tags "osusergo netgo iface" -o $@ ./$(@D)
|
||||
|
||||
# These programs need a separate rule as they fail the netgo check in
|
||||
# the main build stanza due to not importing net package
|
||||
@@ -392,15 +399,14 @@ clean-bin:
|
||||
-$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker rmi $(IMAGES)
|
||||
find prog -type f -name "Dockerfile.*" -not -name "Dockerfile.template" -print | xargs rm -f
|
||||
find prog -type f -name "*qemu-*" -print | xargs rm -f
|
||||
rm -rf $(EXES) $(IMAGES_UPTODATE) $(WEAVEDB_UPTODATE) weave*.tar.gz .pkg
|
||||
go clean ./...
|
||||
rm -rf $(EXES) $(IMAGES_UPTODATE) $(WEAVEDB_UPTODATE) weave*.tar.gz .cache
|
||||
|
||||
clean: clean-bin clean-work-dir
|
||||
-$(SUDO) DOCKER_HOST=$(DOCKER_HOST) docker rmi $(BUILD_IMAGE)
|
||||
rm -rf test/tls/*.pem test/coverage.* test/coverage $(BUILD_UPTODATE)
|
||||
|
||||
build:
|
||||
$(SUDO) go clean -i net
|
||||
$(SUDO) go install -tags netgo std
|
||||
$(MAKE)
|
||||
|
||||
run-smoketests: all testrunner
|
||||
|
||||
@@ -7,12 +7,11 @@
|
||||
|
||||
# About Weaveworks
|
||||
|
||||
[Weaveworks](https://www.weave.works) is the company that delivers the most productive way for developers to connect, observe and control
|
||||
Docker containers.
|
||||
[Weaveworks](https://www.weave.works) is the company that delivers the most productive way for developers to connect, observe and control Docker containers.
|
||||
|
||||
This repository contains [Weave Net](https://www.weave.works/products/weave-net/), the first product developed by Weaveworks, and with over 8 million downloads to date, enables you to get started with Docker clusters and portable apps in a fraction of the time compared with other solutions.
|
||||
This repository contains [Weave Net](https://www.weave.works/products/weave-net/), the first product developed by Weaveworks, with over 8 million downloads to date. Weave Net enables you to get started with Docker clusters and portable apps in a fraction of the time required by other solutions.
|
||||
|
||||
## Weave Cloud:
|
||||
## Weave Cloud:
|
||||
|
||||
[Weave Cloud](https://www.weave.works/product/cloud/) is software-as-a-service that simplifies deployment, monitoring and management for containers and microservices. It extends and complements popular orchestrators, and enables developers and DevOps to realize faster deployments, insightful monitoring, visualization and networking.
|
||||
|
||||
@@ -29,11 +28,10 @@ Services provided by application containers on the Weave network can be exposed
|
||||
If you have any questions about, feedback for or a problem with Weave Net:
|
||||
|
||||
- Read [the Weave Net docs](https://www.weave.works/docs/net/latest/overview).
|
||||
- Invite yourself to the <a href="https://weaveworks.github.io/community-slack/" target="_blank"> #weave-community </a> slack channel.
|
||||
- Ask a question on the <a href="https://weave-community.slack.com/messages/general/"> #weave-community</a> slack channel.
|
||||
- Invite yourself to the <a href="https://slack.weave.works/" target="_blank">Weave Users Slack</a>.
|
||||
- Ask a question on the [#net-dev](https://weave-community.slack.com/messages/net-dev/) slack channel.
|
||||
- Join the <a href="https://www.meetup.com/pro/Weave/"> Weave User Group </a> and get invited to online talks, hands-on training and meetups in your area.
|
||||
- Send an email to <a href="mailto:weave-users@weave.works">weave-users@weave.works</a>
|
||||
- <a href="https://github.com/weaveworks/weave/issues/new">File an issue.</a>
|
||||
- [File an issue](https://github.com/weaveworks/weave/issues/new).
|
||||
|
||||
Your feedback is always welcome!
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ function signal_failure() {
|
||||
trap signal_failure ERR
|
||||
|
||||
function install_terraform() {
|
||||
curl -fsS https://releases.hashicorp.com/terraform/0.8.5/terraform_0.8.5_linux_amd64.zip | gunzip >terraform && chmod +x terraform && sudo mv terraform /usr/bin
|
||||
curl -fsS https://releases.hashicorp.com/terraform/0.11.14/terraform_0.11.14_linux_amd64.zip | gunzip >terraform && chmod +x terraform && sudo mv terraform /usr/bin
|
||||
}
|
||||
|
||||
function install_ansible() {
|
||||
|
||||
+31
-16
@@ -89,10 +89,11 @@ build() {
|
||||
## Inject the version numbers and build the distributables
|
||||
## (library versions?)
|
||||
sed -i.bak "/SCRIPT_VERSION=/ c\SCRIPT_VERSION=\"$VERSION\"" ./weave
|
||||
sed -i.bak -e "s/:latest/:$VERSION/" -e "/imagePullPolicy: Always/d" ./prog/weave-kube/weave-daemonset.yaml
|
||||
sed -i.bak -e "s/:latest/:$VERSION/" -e "/imagePullPolicy: Always/d" ./prog/weave-kube/weave-daemonset-k8s-1.6.yaml
|
||||
sed -i.bak -e "s/:latest/:$VERSION/" -e "/imagePullPolicy: Always/d" ./prog/weave-kube/weave-daemonset-k8s-1.7.yaml
|
||||
sed -i.bak -e "s/:latest/:$VERSION/" -e "/imagePullPolicy: Always/d" ./prog/weave-kube/weave-daemonset-k8s-1.8.yaml
|
||||
sed -i.bak -e "s/:latest/:$VERSION/" -e "/imagePullPolicy: Always/d" ./prog/weave-kube/weave-daemonset-k8s-1.9.yaml
|
||||
sed -i.bak -e "s/:latest/:$VERSION/" -e "/imagePullPolicy: Always/d" ./prog/weave-kube/weave-daemonset-k8s-1.11.yaml
|
||||
make SUDO=$SUDO WEAVE_VERSION=$VERSION DOCKERHUB_USER=$DOCKERHUB_USER
|
||||
|
||||
if make tests; then
|
||||
@@ -161,13 +162,6 @@ draft() {
|
||||
--name "weave" \
|
||||
--file "./weave"
|
||||
|
||||
github-release upload \
|
||||
--user $GITHUB_USER \
|
||||
--repo weave \
|
||||
--tag $LATEST_TAG \
|
||||
--name "weave-daemonset.yaml" \
|
||||
--file "./prog/weave-kube/weave-daemonset.yaml"
|
||||
|
||||
github-release upload \
|
||||
--user $GITHUB_USER \
|
||||
--repo weave \
|
||||
@@ -188,7 +182,21 @@ draft() {
|
||||
--tag $LATEST_TAG \
|
||||
--name "weave-daemonset-k8s-1.8.yaml" \
|
||||
--file "./prog/weave-kube/weave-daemonset-k8s-1.8.yaml"
|
||||
|
||||
|
||||
github-release upload \
|
||||
--user $GITHUB_USER \
|
||||
--repo weave \
|
||||
--tag $LATEST_TAG \
|
||||
--name "weave-daemonset-k8s-1.9.yaml" \
|
||||
--file "./prog/weave-kube/weave-daemonset-k8s-1.9.yaml"
|
||||
|
||||
github-release upload \
|
||||
--user $GITHUB_USER \
|
||||
--repo weave \
|
||||
--tag $LATEST_TAG \
|
||||
--name "weave-daemonset-k8s-1.11.yaml" \
|
||||
--file "./prog/weave-kube/weave-daemonset-k8s-1.11.yaml"
|
||||
|
||||
echo "** Draft $TYPE $RELEASE_NAME $VERSION created at"
|
||||
echo -e "\thttps://github.com/$GITHUB_USER/weave/releases/$LATEST_TAG"
|
||||
}
|
||||
@@ -276,13 +284,6 @@ publish() {
|
||||
--name "weave" \
|
||||
--file "./weave"
|
||||
|
||||
github-release upload \
|
||||
--user $GITHUB_USER \
|
||||
--repo weave \
|
||||
--tag latest_release \
|
||||
--name "weave-daemonset.yaml" \
|
||||
--file "./prog/weave-kube/weave-daemonset.yaml"
|
||||
|
||||
github-release upload \
|
||||
--user $GITHUB_USER \
|
||||
--repo weave \
|
||||
@@ -304,6 +305,20 @@ publish() {
|
||||
--name "weave-daemonset-k8s-1.8.yaml" \
|
||||
--file "./prog/weave-kube/weave-daemonset-k8s-1.8.yaml"
|
||||
|
||||
github-release upload \
|
||||
--user $GITHUB_USER \
|
||||
--repo weave \
|
||||
--tag latest_release \
|
||||
--name "weave-daemonset-k8s-1.9.yaml" \
|
||||
--file "./prog/weave-kube/weave-daemonset-k8s-1.9.yaml"
|
||||
|
||||
github-release upload \
|
||||
--user $GITHUB_USER \
|
||||
--repo weave \
|
||||
--tag latest_release \
|
||||
--name "weave-daemonset-k8s-1.11.yaml" \
|
||||
--file "./prog/weave-kube/weave-daemonset-k8s-1.11.yaml"
|
||||
|
||||
echo "** Release $RELEASE_NAME $VERSION published at"
|
||||
echo -e "\thttps://github.com/$GITHUB_USER/weave/releases/$LATEST_TAG"
|
||||
echo -e "\thttps://github.com/$GITHUB_USER/weave/releases/latest_release"
|
||||
|
||||
+8
-21
@@ -1,4 +1,4 @@
|
||||
FROM golang:1.10.1-stretch
|
||||
FROM golang:1.13.3-buster
|
||||
|
||||
# Support Raspberry Pi 2 and newer
|
||||
ENV GOARM 7
|
||||
@@ -7,25 +7,25 @@ ENV GOARM 7
|
||||
ENV DEB_CROSSPLATFORMS \
|
||||
armhf \
|
||||
arm64 \
|
||||
ppc64el
|
||||
ppc64el \
|
||||
s390x
|
||||
|
||||
# The go platforms we are supporting to cross-compile
|
||||
ENV GO_CROSSPLATFORMS \
|
||||
linux/arm \
|
||||
linux/arm64 \
|
||||
linux/ppc64le
|
||||
linux/ppc64le \
|
||||
linux/s390x
|
||||
|
||||
# The names of the gcc cross-compilers we have installed
|
||||
ENV GCC_CROSSCOMPILERS \
|
||||
arm-linux-gnueabihf \
|
||||
aarch64-linux-gnu \
|
||||
powerpc64le-linux-gnu
|
||||
powerpc64le-linux-gnu \
|
||||
s390x-linux-gnu
|
||||
|
||||
# Temporarily add the Debian repositories, because we're going to install gcc cross-compilers from there
|
||||
# Install the build-essential and crossbuild-essential-ARCH packages
|
||||
RUN echo "deb http://emdebian.org/tools/debian/ jessie main" > /etc/apt/sources.list.d/cgocrosscompiling.list \
|
||||
&& curl http://emdebian.org/tools/debian/emdebian-toolchain-archive.key | apt-key add - \
|
||||
&& for platform in ${DEB_CROSSPLATFORMS}; do dpkg --add-architecture $platform; done \
|
||||
RUN for platform in ${DEB_CROSSPLATFORMS}; do dpkg --add-architecture $platform; done \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y build-essential \
|
||||
&& for platform in ${DEB_CROSSPLATFORMS}; do apt-get install -y crossbuild-essential-${platform}; done \
|
||||
@@ -57,19 +57,6 @@ RUN go get \
|
||||
github.com/fatih/hclfmt \
|
||||
github.com/client9/misspell/cmd/misspell
|
||||
|
||||
# First clean, because we're gonna rebuild the std both with -race enabled and disabled
|
||||
# Running go install std twice is intentional and required, as content is written in two different directories
|
||||
# (/usr/local/go/pkg/linux_amd64 vs /usr/local/go/pkg/linux_amd64_race)
|
||||
# The other architectures do not have support for -race
|
||||
RUN go clean -i net \
|
||||
&& go install -tags netgo std \
|
||||
&& go install -race -tags netgo std
|
||||
|
||||
# Prebuild std for the other architectures
|
||||
RUN for platform in ${GO_CROSSPLATFORMS}; do \
|
||||
GOOS=${platform%/*} GOARCH=${platform##*/} \
|
||||
go install -tags netgo std; done
|
||||
|
||||
# Allow full write access to the Go folders for anyone
|
||||
RUN chmod -R a+w /usr/local/go
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
bab3b4d04263479b3d9f85cf59bd0cad1f2b434f29856b2204f8288f2f3598e4 qemu-s390x-static
|
||||
@@ -99,7 +99,9 @@ func (c *Client) AddObserver(ob ContainerObserver) error {
|
||||
pending := make(pendingStarts)
|
||||
retryInterval := InitialInterval
|
||||
for {
|
||||
events := make(chan *docker.APIEvents)
|
||||
// Use a buffered chan so the client library can run ahead of the listener
|
||||
// - Docker will drop an event if it is not collected quickly enough.
|
||||
events := make(chan *docker.APIEvents, 1024)
|
||||
if err := c.AddEventListener(events); err != nil {
|
||||
c.errorf("Unable to add listener to Docker API: %s - retrying in %ds", err, retryInterval/time.Second)
|
||||
} else {
|
||||
|
||||
@@ -54,6 +54,12 @@ func SetLogLevel(levelname string) {
|
||||
Log.Level = level
|
||||
}
|
||||
|
||||
func CheckError(e error) {
|
||||
if e != nil {
|
||||
Log.Error(e)
|
||||
}
|
||||
}
|
||||
|
||||
func CheckFatal(e error) {
|
||||
if e != nil {
|
||||
Log.Fatal(e)
|
||||
|
||||
+1
-1
@@ -64,7 +64,7 @@ To add new options to how weave should run with each invocation, you would do th
|
||||
5. Add a command-line option `--option` to `weaveutil` or `weaver` as appropriate.
|
||||
6. If the option can be configured for CNI:
|
||||
* have `prog/weave-kube/launch.sh` read it as an environment variable and set inside
|
||||
* set a default for the environment variable in `prog/weave-kube/weave-daemonset-k8s-1.6.yaml` and `weave-daemonset.yaml`
|
||||
* set a default for the environment variable in `prog/weave-kube/weave-daemonset-k8s-N.N.yaml`
|
||||
* if it should be set via `weaver` globally on its one-time initialization invocation, pass it on in `launch.sh`
|
||||
* if it needs to be set via `weaveutil` on each invocation of `weave-net`, have `launch.sh` save it as an option in the CNI config file `/etc/cni/net.d/10-weave.conflist` and then have the CNI code in `plugin/net/cni.go` in `weaveutil` read it and use where appropriate
|
||||
7. Document it!
|
||||
+2
-2
@@ -4,7 +4,7 @@
|
||||
|
||||
* Weave Net: v2.2.1.
|
||||
* Kubernetes: v1.10.0.
|
||||
* kube-proxy: iptables mode (default kubeadm options).
|
||||
* kube-proxy: iptables/ipvs mode with `--masquerade-all=false` and `--cluster-cidr` unspecified(default kubeadm options).
|
||||
* Hosts: `h1` and `h2`.
|
||||
|
||||
## Source IP
|
||||
@@ -14,7 +14,7 @@
|
||||
1 | Pod_h1 | ip(Pod_h2) | Pod_h2 | ip(Pod_h1) | OK
|
||||
2 | h1 | ClusterIP | Pod_h1 | ip(weave_h1) | **NOK**
|
||||
3 | h1 | ClusterIP | Pod_h2 | ip(weave_h1) | OK
|
||||
4 | Pod_h1 | ClusterIP | Pod_h1 | ip(weave_h1) | **NOK**
|
||||
4 | Pod_h1 | ClusterIP | Pod_h1 | ip(Pod_h1) | OK
|
||||
5 | Pod_h1 | ClusterIP | Pod_h2 | ip(weave_h1) | OK
|
||||
6 | h1 | ip(h1):NodePort | Pod_h1 | ip(weave_h1) | **NOK**
|
||||
7 | h1 | ip(h1):NodePort | Pod_h2 | ip(weave_h1) | OK
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
* Up-to-date versions of `git`, `go` etc
|
||||
* Install GitHub release tool `go get github.com/weaveworks/github-release`
|
||||
* Install manifest tool `go get github.com/estesp/manifest-tool`
|
||||
* Create a [github token for
|
||||
github-release](https://help.github.com/articles/creating-an-access-token-for-command-line-use/); select the `repo` OAuth scope; set and export `$GITHUB_TOKEN` with this value
|
||||
|
||||
@@ -135,7 +136,7 @@ Now, you can validate whether images were published for all platforms:
|
||||
# Published platforms per image:
|
||||
for img in $(grep '^PUBLISH=' Makefile); do
|
||||
img="weaveworks/$(echo $img | cut -d_ -f2):${TAG#v}"
|
||||
platforms=$(vendor/github.com/estesp/manifest-tool/manifest-tool \
|
||||
platforms=$(manifest-tool \
|
||||
inspect --raw "$img" | \
|
||||
jq '.[].Platform | .os + "/" +.architecture' | \
|
||||
tr '\n' ' ')
|
||||
@@ -154,6 +155,7 @@ Weave Net is [available in Docker Store](https://store.docker.com/plugins/weave-
|
||||
* Go to "_Plans & Pricing_" > "_Free Tier_".
|
||||
* Under "_Source Repositories & Tags_", click on "_Add Source_", select "_net-plugin_" under "_Repository_" and the version to release under "_Tag_".
|
||||
* Under "_Resources_" > "_Installation Instructions_", update the lines containing `export NET_VERSION=<version>`.
|
||||
* Click "_Save_"
|
||||
* Click "_Submit For Review_". You should see a message like: "_Your product has been submitted for approval. [...] We'll be in touch with next steps soon!_".
|
||||
* You should receive an email saying:
|
||||
|
||||
@@ -177,6 +179,8 @@ Weave Net is [available in Docker Store](https://store.docker.com/plugins/weave-
|
||||
https://checkpoint-api.weave.works/admin
|
||||
* File a PR to update the version of the daemonset at
|
||||
https://github.com/kubernetes/kops/tree/master/upup/models/cloudup/resources/addons/networking.weave
|
||||
and kops/upup/pkg/fi/cloudup/bootstrapchannelbuilder.go
|
||||
and kops/upup/pkg/fi/cloudup/tests/bootstrapchannelbuilder/weave/manifest.yaml
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
|
||||
+62
-12
@@ -9,7 +9,9 @@ destroyed automatically in response to Pod, Namespace and
|
||||
NetworkPolicy object updates from the k8s API server:
|
||||
|
||||
* A `hash:ip` set per namespace, containing the IP addresses of all
|
||||
pods in that namespace
|
||||
pods in that namespace for which default ingress is allowed
|
||||
* A `hash:ip` set per namespace, containing the IP addresses of all
|
||||
pods in that namespace for which default egress is allowed
|
||||
* A `list:set` per distinct (across all network policies in all
|
||||
namespaces) namespace selector mentioned in a network policy,
|
||||
containing the names of any of the above hash:ip sets whose
|
||||
@@ -18,6 +20,9 @@ NetworkPolicy object updates from the k8s API server:
|
||||
containing network policy's namespace) pod selector mentioned in a
|
||||
network policy, containing the IP addresses of all pods in the
|
||||
namespace whose labels match that selector
|
||||
* A `hash:net` set for each distinct (within the scope of the
|
||||
containing network policy's namespace) `except` list of CIDR's mentioned in
|
||||
the network policies
|
||||
|
||||
IPsets are implemented by the kernel module `xt_set`, without which
|
||||
weave-npc will not work.
|
||||
@@ -38,11 +43,21 @@ hashing to avoid clashes.
|
||||
|
||||
# iptables chains
|
||||
|
||||
The policy controller maintains two iptables chains in response to
|
||||
changes to pods, namespaces and network policies. One chain contains
|
||||
the ingress rules that implement the network policy specifications,
|
||||
and the other is used to bypass the ingress rules for namespaces which
|
||||
have an ingress isolation policy of `DefaultAllow`.
|
||||
The policy controller maintains several iptables chains in response to
|
||||
changes to pods, namespaces and network policies.
|
||||
|
||||
## Static `WEAVE-NPC` chain
|
||||
|
||||
`WEAVE-NPC` chain contains static rules to ACCEPT traffic that is `RELATED,ESTABLISHED`
|
||||
and run `NEW` traffic through `WEAVE-NPC-DEFAULT` followed by `WEAVE-NPC-INGRESS` chains
|
||||
|
||||
Static configuration:
|
||||
|
||||
```
|
||||
iptables -A WEAVE-NPC -m state --state RELATED,ESTABLISHED -j ACCEPT
|
||||
iptables -A WEAVE-NPC -m state --state NEW -j WEAVE-NPC-DEFAULT
|
||||
iptables -A WEAVE-NPC -m state --state NEW -j WEAVE-NPC-INGRESS
|
||||
```
|
||||
|
||||
## Dynamically maintained `WEAVE-NPC-DEFAULT` chain
|
||||
|
||||
@@ -63,23 +78,58 @@ For each namespace network policy ingress rule peer/port combination:
|
||||
iptables -A WEAVE-NPC-INGRESS -p $PROTO [-m set --match-set $SRCSET] -m set --match-set $DSTSET --dport $DPORT -j ACCEPT
|
||||
```
|
||||
|
||||
## Static `WEAVE-NPC` chain
|
||||
## Static `WEAVE-NPC-EGRESS` chain
|
||||
|
||||
`WEAVE-NPC-EGRESS` chain contains static rules to ACCEPT traffic that is `RELATED,ESTABLISHED`
|
||||
and run `NEW` traffic through `WEAVE-NPC-EGRESS-DEFAULT` followed by `WEAVE-NPC-EGRESS-CUSTOM` chains
|
||||
|
||||
Static configuration:
|
||||
|
||||
```
|
||||
iptables -A WEAVE-NPC -m state --state RELATED,ESTABLISHED -j ACCEPT
|
||||
iptables -A WEAVE-NPC -m state --state NEW -j WEAVE-NPC-DEFAULT
|
||||
iptables -A WEAVE-NPC -m state --state NEW -j WEAVE-NPC-INGRESS
|
||||
iptables -A WEAVE-NPC-EGRESS -m state --state RELATED,ESTABLISHED -j ACCEPT
|
||||
iptables -A WEAVE-NPC-EGRESS -m state --state NEW -j WEAVE-NPC-EGRESS-DEFAULT
|
||||
iptables -A WEAVE-NPC-EGRESS -m state --state NEW -m mark ! --mark 0x40000/0x40000 -j WEAVE-NPC-EGRESS-CUSTOM
|
||||
iptables -A WEAVE-NPC-EGRESS -m mark ! --mark 0x40000/0x40000 -j DROP
|
||||
```
|
||||
|
||||
## Dynamically maintained `WEAVE-NPC-EGRESS-DEFAULT` chain
|
||||
|
||||
The policy controller maintains a rule in this chain for every
|
||||
namespace whose egress isolation policy is `DefaultAllow`. The
|
||||
purpose of this rule is simply to ACCEPT any traffic originating from such namespace before it reaches the egress chain.
|
||||
|
||||
```
|
||||
iptables -A WEAVE-NPC-EGRESS-DEFAULT -m set --match-set $NSIPSET src -j WEAVE-NPC-EGRESS-ACCEPT
|
||||
iptables -A WEAVE-NPC-EGRESS-DEFAULT -m set --match-set $NSIPSET src -j RETURN
|
||||
```
|
||||
|
||||
## Static `WEAVE-NPC-EGRESS-ACCEPT` chain
|
||||
|
||||
`WEAVE-NPC-EGRESS-ACCEPTS` chain contains static rules to mark traffic
|
||||
|
||||
Static configuration:
|
||||
|
||||
```
|
||||
iptables -A WEAVE-NPC-EGRESS-ACCEPT -j MARK --set-xmark 0x40000/0x40000
|
||||
```
|
||||
|
||||
## Dynamically maintained `WEAVE-NPC-EGRESS-CUSTOM` chain
|
||||
|
||||
For each namespace network policy egress rule peer/port combination:
|
||||
|
||||
```
|
||||
iptables -A WEAVE-NPC-EGRESS-CUSTOM -p $PROTO [-m set --match-set $SRCSET] -m set --match-set $DSTSET --dport $DPORT -j ACCEPT
|
||||
```
|
||||
|
||||
|
||||
# Steering traffic into the policy engine
|
||||
|
||||
To direct traffic into the policy engine:
|
||||
|
||||
```
|
||||
iptables -A FORWARD -o weave -m physdev ! --physdev-out vethwe-bridge -j WEAVE-NPC
|
||||
iptables -A FORWARD -o weave -m physdev ! --physdev-out vethwe-bridge -j DROP
|
||||
iptables -A INPUT -i weave -j WEAVE-NPC-EGRESS
|
||||
iptables -A FORWARD -i weave -j WEAVE-NPC-EGRESS
|
||||
iptables -A FORWARD -o weave -j WEAVE-NPC
|
||||
```
|
||||
|
||||
Note this only affects traffic which egresses the bridge on a physical
|
||||
|
||||
+13
-2
@@ -275,7 +275,7 @@ func (alloc *Allocator) spaceRequestDenied(sender mesh.PeerName, r address.Range
|
||||
for i := 0; i < len(alloc.pendingClaims); {
|
||||
claim := alloc.pendingClaims[i].(*claim)
|
||||
if r.Contains(claim.cidr.Addr) {
|
||||
claim.deniedBy(alloc, sender)
|
||||
claim.deniedBy(alloc, sender, nil)
|
||||
alloc.pendingClaims = append(alloc.pendingClaims[:i], alloc.pendingClaims[i+1:]...)
|
||||
continue
|
||||
}
|
||||
@@ -814,6 +814,16 @@ func (alloc *Allocator) sendRingUpdate(dest mesh.PeerName) {
|
||||
alloc.gossip.GossipUnicast(dest, msg)
|
||||
}
|
||||
|
||||
func (alloc *Allocator) hasAllocations(rs []address.Range) bool {
|
||||
for _, r := range rs {
|
||||
alloc.debugf("hasAllocations: %v %v vs %v", r, alloc.space.NumFreeAddressesInRange(r), r.Size())
|
||||
if alloc.space.NumFreeAddressesInRange(r) != r.Size() {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (alloc *Allocator) update(sender mesh.PeerName, msg []byte) error {
|
||||
reader := bytes.NewReader(msg)
|
||||
decoder := gob.NewDecoder(reader)
|
||||
@@ -832,7 +842,7 @@ func (alloc *Allocator) update(sender mesh.PeerName, msg []byte) error {
|
||||
// If someone sent us a ring, merge it into ours. Note this will move us
|
||||
// out of the awaiting-consensus state if we didn't have a ring already.
|
||||
case data.Ring != nil:
|
||||
updated, err := alloc.ring.Merge(*data.Ring)
|
||||
updated, err := alloc.ring.Merge(*data.Ring, alloc.hasAllocations)
|
||||
switch err {
|
||||
case nil:
|
||||
if updated {
|
||||
@@ -910,6 +920,7 @@ func (alloc *Allocator) donateSpace(r address.Range, to mesh.PeerName) {
|
||||
alloc.debugln("Giving range", chunk, "to", to)
|
||||
alloc.ring.GrantRangeToHost(chunk.Start, chunk.End, to)
|
||||
alloc.persistRing()
|
||||
alloc.gossip.GossipBroadcast(alloc.Gossip())
|
||||
}
|
||||
|
||||
func (alloc *Allocator) assertInvariants() {
|
||||
|
||||
+15
-4
@@ -12,6 +12,7 @@ import (
|
||||
|
||||
type claim struct {
|
||||
resultChan chan<- error
|
||||
tryCount int
|
||||
ident string // a container ID, something like "weave:expose", or api.NoContainerID
|
||||
cidr address.CIDR // single address being claimed
|
||||
isContainer bool // true if ident is a container ID
|
||||
@@ -19,6 +20,8 @@ type claim struct {
|
||||
hasBeenCancelled func() bool
|
||||
}
|
||||
|
||||
const maxTryCount = 5
|
||||
|
||||
// Send an error (or nil for success) back to caller listening on resultChan
|
||||
func (c *claim) sendResult(result error) {
|
||||
// Make sure we only send a result once, since listener stops listening after that
|
||||
@@ -40,6 +43,8 @@ func (c *claim) Try(alloc *Allocator) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
c.tryCount++
|
||||
|
||||
addOwned := func() {
|
||||
if c.ident == api.NoContainerID {
|
||||
alloc.addOwned(c.cidr.Addr.String(), c.cidr, c.isContainer)
|
||||
@@ -90,8 +95,10 @@ func (c *claim) Try(alloc *Allocator) bool {
|
||||
if c.noErrorOnUnknown {
|
||||
alloc.infof("Claim %s for %s: %s; will try later.", c.cidr, c.ident, err)
|
||||
c.sendResult(nil)
|
||||
} else { // just tell the user they can't do this.
|
||||
c.deniedBy(alloc, owner)
|
||||
} else if c.tryCount > maxTryCount {
|
||||
// give up, tell the user they can't do this
|
||||
c.deniedBy(alloc, owner, err)
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
@@ -128,12 +135,16 @@ func (c *claim) Try(alloc *Allocator) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (c *claim) deniedBy(alloc *Allocator, owner mesh.PeerName) {
|
||||
func (c *claim) deniedBy(alloc *Allocator, owner mesh.PeerName, err error) {
|
||||
name, found := alloc.nicknames[owner]
|
||||
if found {
|
||||
name = " (" + name + ")"
|
||||
}
|
||||
c.sendResult(fmt.Errorf("address %s is owned by other peer %s%s", c.cidr.String(), owner, name))
|
||||
reason := ""
|
||||
if err != nil {
|
||||
reason = fmt.Sprintf(" - %s", err)
|
||||
}
|
||||
c.sendResult(fmt.Errorf("address %s is owned by other peer %s%s%s", c.cidr.String(), owner, name, reason))
|
||||
}
|
||||
|
||||
func (c *claim) Cancel() {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package ring
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
"github.com/weaveworks/mesh"
|
||||
@@ -25,6 +26,7 @@ func (e *entry) Equal(e2 *entry) bool {
|
||||
func (e *entry) update(peername mesh.PeerName, free address.Count) {
|
||||
e.Peer = peername
|
||||
e.Version++
|
||||
common.Log.Debugln(fmt.Sprintf("Updating ring token=%s current peer=%s updated peer=%s new version=%s", e.Token, e.Peer, peername, fmt.Sprint(e.Version)))
|
||||
e.Free = free
|
||||
}
|
||||
|
||||
|
||||
+65
-18
@@ -213,7 +213,7 @@ func (r *Ring) GrantRangeToHost(start, end address.Address, peer mesh.PeerName)
|
||||
|
||||
// Merge the given ring into this ring and indicate whether this ring
|
||||
// got updated as a result.
|
||||
func (r *Ring) Merge(gossip Ring) (bool, error) {
|
||||
func (r *Ring) Merge(gossip Ring, hasAllocations func(r []address.Range) bool) (bool, error) {
|
||||
r.assertInvariants()
|
||||
defer r.trackUpdates()()
|
||||
|
||||
@@ -238,12 +238,22 @@ func (r *Ring) Merge(gossip Ring) (bool, error) {
|
||||
return false, ErrDifferentRange
|
||||
}
|
||||
|
||||
result, updated, err := r.Entries.merge(gossip.Entries, r.Peer)
|
||||
result, updated, err := r.Entries.merge(gossip.Entries, r.Peer, r, hasAllocations)
|
||||
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// reset the free space for entries if there is invalid free space
|
||||
// due to accepting an unexpected update from the peers
|
||||
for i := 0; i < len(result); i++ {
|
||||
distance := r.distance(result.entry(i).Token, result.entry(i+1).Token)
|
||||
if result.entry(i).Peer == r.Peer && result.entry(i).Free > distance {
|
||||
// case that can arise when a range that we own that got split and had no allocations
|
||||
result.entry(i).Free = distance
|
||||
}
|
||||
}
|
||||
|
||||
if err := r.checkEntries(result); err != nil {
|
||||
return false, fmt.Errorf("Merge of incoming data causes: %s", err)
|
||||
}
|
||||
@@ -260,7 +270,7 @@ func (r *Ring) Merge(gossip Ring) (bool, error) {
|
||||
// entries belonging to ourPeer. Returns the merged entries and an
|
||||
// indication whether the merge resulted in any changes, i.e. the
|
||||
// result differs from the original.
|
||||
func (es entries) merge(other entries, ourPeer mesh.PeerName) (result entries, updated bool, err error) {
|
||||
func (es entries) merge(other entries, ourPeer mesh.PeerName, r *Ring, hasAllocations func(r []address.Range) bool) (result entries, updated bool, err error) {
|
||||
var mine, theirs *entry
|
||||
var previousOwner *mesh.PeerName
|
||||
addToResult := func(e entry) { result = append(result, &e) }
|
||||
@@ -274,6 +284,7 @@ func (es entries) merge(other entries, ourPeer mesh.PeerName) (result entries, u
|
||||
var i, j int
|
||||
for i < len(es) && j < len(other) {
|
||||
mine, theirs = es[i], other[j]
|
||||
common.Log.Debugf("[ring %s]: Merge mine.Token=%s theirs.Token=%s mine.Peer=%s theirs.Peer=%s mine.Version=%v theirs.Version=%v", ourPeer, mine.Token, theirs.Token, mine.Peer, theirs.Peer, mine.Version, theirs.Version)
|
||||
switch {
|
||||
case mine.Token < theirs.Token:
|
||||
addToResult(*mine)
|
||||
@@ -282,8 +293,11 @@ func (es entries) merge(other entries, ourPeer mesh.PeerName) (result entries, u
|
||||
case mine.Token > theirs.Token:
|
||||
// insert, checking that a range owned by us hasn't been split
|
||||
if previousOwner != nil && *previousOwner == ourPeer && theirs.Peer != ourPeer {
|
||||
err = errEntryInMyRange(theirs)
|
||||
return
|
||||
// check we have no allocations in the range that got split
|
||||
if hasAllocations(r.makeRanges(theirs.Token, mine.Token)) {
|
||||
err = errEntryInMyRange(theirs)
|
||||
return
|
||||
}
|
||||
}
|
||||
addTheirs(*theirs)
|
||||
j++
|
||||
@@ -292,17 +306,44 @@ func (es entries) merge(other entries, ourPeer mesh.PeerName) (result entries, u
|
||||
switch {
|
||||
case mine.Version >= theirs.Version:
|
||||
if mine.Version == theirs.Version && !mine.Equal(theirs) {
|
||||
err = errInconsistentEntry(mine, theirs)
|
||||
return
|
||||
if mine.Peer == ourPeer {
|
||||
// if we own the entry and has allocations
|
||||
if hasAllocations(r.makeRanges(theirs.Token, es.entry(i+1).Token)) {
|
||||
err = errInconsistentEntry(mine, theirs)
|
||||
return
|
||||
}
|
||||
}
|
||||
// tie-break here, pick the entry with the highest free count
|
||||
if mine.Free >= theirs.Free {
|
||||
addToResult(*mine)
|
||||
previousOwner = &mine.Peer
|
||||
} else {
|
||||
addTheirs(*theirs)
|
||||
}
|
||||
} else {
|
||||
addToResult(*mine)
|
||||
previousOwner = &mine.Peer
|
||||
}
|
||||
addToResult(*mine)
|
||||
previousOwner = &mine.Peer
|
||||
case mine.Version < theirs.Version:
|
||||
if mine.Peer == ourPeer { // We shouldn't receive updates to our own tokens
|
||||
err = errNewerVersion(mine, theirs)
|
||||
return
|
||||
if mine.Peer == ourPeer {
|
||||
// We received update to our own tokens accept the received entry
|
||||
// if either it belongs to a different peer and we do not have allocations
|
||||
// in the range effectively given away, or it belongs to our own peer, in
|
||||
// which case we should set our version to the one received plus one,
|
||||
// effectively imposing our existing entry.
|
||||
if theirs.Peer != ourPeer && !hasAllocations(r.makeRanges(mine.Token, es.entry(i+1).Token)) {
|
||||
common.Log.Infof("ring: repair inconsistent data by accepting token %v from %v - no allocations up to %v", theirs.Token, theirs.Peer, es.entry(i+1).Token)
|
||||
addTheirs(*theirs)
|
||||
} else if theirs.Peer == ourPeer {
|
||||
mine.Version = theirs.Version + 1
|
||||
addToResult(*mine)
|
||||
} else {
|
||||
err = errNewerVersion(mine, theirs)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
addTheirs(*theirs)
|
||||
}
|
||||
addTheirs(*theirs)
|
||||
}
|
||||
i++
|
||||
j++
|
||||
@@ -334,6 +375,11 @@ func (r *Ring) Empty() bool {
|
||||
return len(r.Entries) == 0
|
||||
}
|
||||
|
||||
// convenience function to normalise a single range that may span zero
|
||||
func (r *Ring) makeRanges(start, end address.Address) []address.Range {
|
||||
return r.splitRangesOverZero([]address.Range{{Start: start, End: end}})
|
||||
}
|
||||
|
||||
// Given a slice of ranges which are all in the right order except
|
||||
// possibly the last one spans zero, fix that up and return the slice
|
||||
func (r *Ring) splitRangesOverZero(ranges []address.Range) []address.Range {
|
||||
@@ -384,10 +430,7 @@ type RangeInfo struct {
|
||||
|
||||
func (r *Ring) AllRangeInfo() (result []RangeInfo) {
|
||||
for i, entry := range r.Entries {
|
||||
nextEntry := r.Entries.entry(i + 1)
|
||||
ranges := []address.Range{{Start: entry.Token, End: nextEntry.Token}}
|
||||
ranges = r.splitRangesOverZero(ranges)
|
||||
for _, r := range ranges {
|
||||
for _, r := range r.makeRanges(entry.Token, r.Entries.entry(i+1).Token) {
|
||||
result = append(result, RangeInfo{entry.Peer, r, entry.Version})
|
||||
}
|
||||
}
|
||||
@@ -485,6 +528,7 @@ func (r *Ring) ReportFree(freespace map[address.Address]address.Count) (updated
|
||||
|
||||
entries[i].Free = free
|
||||
entries[i].Version++
|
||||
common.Log.Debugf("[ring %s]: ReportFree token=%s peer=%s version=%v", r.Peer, entries[i].Token, entries[i].Peer, entries[i].Version)
|
||||
updated = true
|
||||
}
|
||||
return
|
||||
@@ -565,7 +609,10 @@ func (r *Ring) Transfer(from, to mesh.PeerName) []address.Range {
|
||||
for i, entry := range r.Entries {
|
||||
if entry.Peer == from {
|
||||
entry.Peer = to
|
||||
entry.Version++
|
||||
// bump version by large value so that transfer of range takes precedence (if there is any conflict in merging entry)
|
||||
// over other opertaions on the entry that increments the version
|
||||
entry.Version = entry.Version + 100
|
||||
common.Log.Debugf("[ring %s]: Transfer token=%s from=%s to=%s version=%v", r.Peer, entry.Token, from, to, entry.Version)
|
||||
newRanges = append(newRanges, address.Range{Start: entry.Token, End: r.Entries.entry(i + 1).Token})
|
||||
}
|
||||
}
|
||||
|
||||
+76
-8
@@ -32,7 +32,27 @@ func ParseIP(s string) address.Address {
|
||||
}
|
||||
|
||||
func merge(r1, r2 *Ring) error {
|
||||
_, err := r1.Merge(*r2)
|
||||
distance := func(start, end address.Address) address.Count {
|
||||
if end > start {
|
||||
return address.Count(end - start)
|
||||
}
|
||||
return address.Count((r1.End - start) + (end - r1.Start))
|
||||
}
|
||||
check := func(rs []address.Range) bool {
|
||||
for _, r := range rs {
|
||||
size := distance(r.Start, r.End)
|
||||
entry, found := r1.Entries.get(r.Start)
|
||||
if !found {
|
||||
continue
|
||||
}
|
||||
if entry.Free < size {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
_, err := r1.Merge(*r2, check)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -219,6 +239,61 @@ func TestMergeSimple(t *testing.T) {
|
||||
require.Equal(t, ring2.Entries, ring1.Entries)
|
||||
}
|
||||
|
||||
func TestMergeWithConflicts(t *testing.T) {
|
||||
|
||||
// received update to entry with a token and version identical to an entry we have
|
||||
// but but holding different content, if there are no allocations, resolve the
|
||||
// conflict by picking entry one with high free count
|
||||
ring1 := NewRing(start, end, peer1name)
|
||||
ring2 := NewRing(start, end, peer2name)
|
||||
ring1.Entries = []*entry{{Token: start, Peer: peer1name, Free: 256, Version: 1}}
|
||||
ring2.Entries = []*entry{{Token: start, Peer: peer2name, Free: 256, Version: 1}}
|
||||
require.NoError(t, merge(ring1, ring2))
|
||||
|
||||
// received update to entry with a token and version identical to an entry we have
|
||||
// but but holding different content, if there are allocations, then reject the received
|
||||
// entry
|
||||
ring1 = NewRing(start, end, peer1name)
|
||||
ring2 = NewRing(start, end, peer2name)
|
||||
ring1.Entries = []*entry{{Token: start, Peer: peer1name, Free: 128, Version: 1}}
|
||||
ring2.Entries = []*entry{{Token: start, Peer: peer2name, Free: 256, Version: 1}}
|
||||
require.Error(t, merge(ring1, ring2), "Expected error")
|
||||
|
||||
// received an entry with update to one of our own tokens and with new version,
|
||||
// accept the received entry if its still going to belong to us
|
||||
ring1 = NewRing(start, end, peer1name)
|
||||
ring2 = NewRing(start, end, peer2name)
|
||||
ring1.Entries = []*entry{{Token: start, Peer: peer1name}}
|
||||
ring2.Entries = []*entry{{Token: start, Peer: peer1name, Version: 1}}
|
||||
require.NoError(t, merge(ring1, ring2))
|
||||
|
||||
// received an entry with update to one of our own tokens and with new version,
|
||||
// but belongs to a different peer, accept the received entry if we do not
|
||||
// have allocations in the range
|
||||
ring1 = NewRing(start, end, peer1name)
|
||||
ring2 = NewRing(start, end, peer2name)
|
||||
ring1.Entries = []*entry{{Token: start, Peer: peer1name, Free: 256}}
|
||||
ring2.Entries = []*entry{{Token: start, Peer: peer2name, Free: 256, Version: 1}}
|
||||
require.NoError(t, merge(ring1, ring2))
|
||||
|
||||
// received an entry with update to one of our own tokens and with new version,
|
||||
// reject received entry if we have allocations in the range
|
||||
ring1 = NewRing(start, end, peer1name)
|
||||
ring2 = NewRing(start, end, peer2name)
|
||||
ring1.Entries = []*entry{{Token: start, Peer: peer1name, Free: 128}}
|
||||
ring2.Entries = []*entry{{Token: start, Peer: peer2name, Version: 1}}
|
||||
require.Error(t, merge(ring1, ring2), "Expected error")
|
||||
|
||||
// we receive an entry that splits one of our ranges, giving some of it
|
||||
// away to another peer. accept the entry provided that we have no allocations
|
||||
// in the range that got given away.
|
||||
ring1 = NewRing(start, end, peer1name)
|
||||
ring2 = NewRing(start, end, peer2name)
|
||||
ring1.Entries = []*entry{{Token: start, Peer: peer1name, Free: 256, Version: 1}}
|
||||
ring2.Entries = []*entry{{Token: start, Peer: peer1name, Free: 128, Version: 2}, {Token: middle, Peer: peer2name, Free: 128}}
|
||||
require.NoError(t, merge(ring1, ring2))
|
||||
}
|
||||
|
||||
func TestMergeErrors(t *testing.T) {
|
||||
// Cannot Merge in an invalid ring
|
||||
ring1 := NewRing(start, end, peer1name)
|
||||
@@ -231,13 +306,6 @@ func TestMergeErrors(t *testing.T) {
|
||||
ring2.Entries = []*entry{}
|
||||
require.True(t, merge(ring1, ring2) == ErrDifferentRange, "Expected ErrDifferentRange")
|
||||
|
||||
// Cannot Merge newer version of entry I own
|
||||
ring2 = NewRing(start, end, peer2name)
|
||||
ring1.Entries = []*entry{{Token: start, Peer: peer1name}}
|
||||
ring2.Entries = []*entry{{Token: start, Peer: peer1name, Version: 1}}
|
||||
fmt.Println(merge(ring1, ring2))
|
||||
require.Error(t, merge(ring1, ring2), "Expected error")
|
||||
|
||||
// Cannot Merge two entries with same version but different hosts
|
||||
ring1.Entries = []*entry{{Token: start, Peer: peer1name}}
|
||||
ring2.Entries = []*entry{{Token: start, Peer: peer2name}}
|
||||
|
||||
@@ -65,6 +65,9 @@ func (m *mockGossipComms) GossipBroadcast(update mesh.GossipData) {
|
||||
}
|
||||
}
|
||||
|
||||
func (m *mockGossipComms) GossipNeighbourSubset(update mesh.GossipData) {
|
||||
m.GossipBroadcast(update)
|
||||
}
|
||||
func equalByteBuffer(a, b []byte) bool {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
|
||||
+20
-11
@@ -63,10 +63,10 @@ const (
|
||||
)
|
||||
|
||||
type Bridge interface {
|
||||
init(config *BridgeConfig) error // create and initialise bridge device(s)
|
||||
attach(veth *netlink.Veth) error // attach veth to bridge
|
||||
IsFastdp() bool // does this bridge use fastdp?
|
||||
String() string // human-readable type string
|
||||
init(procPath string, config *BridgeConfig) error // create and initialise bridge device(s)
|
||||
attach(veth *netlink.Veth) error // attach veth to bridge
|
||||
IsFastdp() bool // does this bridge use fastdp?
|
||||
String() string // human-readable type string
|
||||
}
|
||||
|
||||
// Used to indicate a fallback to the Bridge type
|
||||
@@ -250,7 +250,7 @@ func EnsureBridge(procPath string, config *BridgeConfig, log *logrus.Logger, ips
|
||||
}
|
||||
|
||||
for {
|
||||
if err := bridgeType.init(config); err != nil {
|
||||
if err := bridgeType.init(procPath, config); err != nil {
|
||||
if errors.Cause(err) == errBridgeNotSupported {
|
||||
log.Warnf("Skipping bridge creation of %q due to: %s", bridgeType, err)
|
||||
bridgeType = bridgeImpl{}
|
||||
@@ -279,6 +279,10 @@ func EnsureBridge(procPath string, config *BridgeConfig, log *logrus.Logger, ips
|
||||
return bridgeType, errors.Wrap(err, "setting proxy_arp")
|
||||
}
|
||||
}
|
||||
// No ipv6 router advertisments please
|
||||
if err := sysctl(procPath, "net/ipv6/conf/"+config.WeaveBridgeName+"/accept_ra", "0"); err != nil {
|
||||
return bridgeType, errors.Wrap(err, "setting accept_ra to 0")
|
||||
}
|
||||
|
||||
if err := linkSetUpByName(config.WeaveBridgeName); err != nil {
|
||||
return bridgeType, err
|
||||
@@ -345,11 +349,11 @@ func (b bridgeImpl) initPrep(config *BridgeConfig) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b bridgeImpl) init(config *BridgeConfig) error {
|
||||
func (b bridgeImpl) init(procPath string, config *BridgeConfig) error {
|
||||
if err := b.initPrep(config); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := CreateAndAttachVeth(BridgeIfName, PcapIfName, config.WeaveBridgeName, config.MTU, true, false, func(veth netlink.Link) error {
|
||||
if _, err := CreateAndAttachVeth(procPath, BridgeIfName, PcapIfName, config.WeaveBridgeName, config.MTU, true, false, func(veth netlink.Link) error {
|
||||
return netlink.LinkSetUp(veth)
|
||||
}); err != nil {
|
||||
return errors.Wrap(err, "creating pcap veth pair")
|
||||
@@ -361,7 +365,7 @@ func (b bridgeImpl) init(config *BridgeConfig) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f fastdpImpl) init(config *BridgeConfig) error {
|
||||
func (f fastdpImpl) init(procPath string, config *BridgeConfig) error {
|
||||
odpSupported, err := odp.CreateDatapath(f.datapathName)
|
||||
if !odpSupported {
|
||||
msg := ""
|
||||
@@ -392,14 +396,14 @@ func (f fastdpImpl) init(config *BridgeConfig) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (bf bridgedFastdpImpl) init(config *BridgeConfig) error {
|
||||
if err := bf.fastdpImpl.init(config); err != nil {
|
||||
func (bf bridgedFastdpImpl) init(procPath string, config *BridgeConfig) error {
|
||||
if err := bf.fastdpImpl.init(procPath, config); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := bf.bridgeImpl.initPrep(config); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := CreateAndAttachVeth(BridgeIfName, DatapathIfName, config.WeaveBridgeName, config.MTU, true, false, func(veth netlink.Link) error {
|
||||
if _, err := CreateAndAttachVeth(procPath, BridgeIfName, DatapathIfName, config.WeaveBridgeName, config.MTU, true, false, func(veth netlink.Link) error {
|
||||
if err := netlink.LinkSetUp(veth); err != nil {
|
||||
return errors.Wrapf(err, "setting link up on %q", veth.Attrs().Name)
|
||||
}
|
||||
@@ -465,6 +469,11 @@ func configureIPTables(config *BridgeConfig, ips ipset.Interface) error {
|
||||
}
|
||||
}
|
||||
|
||||
// Block non-local traffic to the Weave control port
|
||||
if err = ipt.AppendUnique("filter", "INPUT", "-p", "tcp", "--dst", "127.0.0.1", "-m", "addrtype", "!", "--src-type", "LOCAL", "-m", "conntrack", "!", "--ctstate", "RELATED,ESTABLISHED", "-j", "DROP"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if config.NPC {
|
||||
// Steer traffic via the NPC.
|
||||
|
||||
|
||||
+22
-16
@@ -85,7 +85,7 @@ func New(log *logrus.Logger) (*IPSec, error) {
|
||||
|
||||
// InitSALocal initializes inbound ipsec from remotePeer and triggers
|
||||
// the initialization on remotePeer.
|
||||
func (ipsec *IPSec) InitSALocal(localPeer, remotePeer mesh.PeerName, connUID uint64, localIP, remoteIP net.IP, udpPort int, sessionKey *[32]byte, initRemote func([]byte) error) error {
|
||||
func (ipsec *IPSec) InitSALocal(localPeer, remotePeer mesh.PeerName, connUID uint64, localIP, remoteIP net.IP, udpPort int, sessionKey *[32]byte) ([]byte, error) {
|
||||
// ID of inbound SPI
|
||||
spiID := getSPIId(remotePeer, localPeer, connUID)
|
||||
|
||||
@@ -95,17 +95,17 @@ func (ipsec *IPSec) InitSALocal(localPeer, remotePeer mesh.PeerName, connUID uin
|
||||
// Derive SA key
|
||||
nonce, err := genNonce()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "generate nonce")
|
||||
return nil, errors.Wrap(err, "generate nonce")
|
||||
}
|
||||
key, err := deriveKey(sessionKey[:], nonce, localPeer)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "derive key")
|
||||
return nil, errors.Wrap(err, "derive key")
|
||||
}
|
||||
|
||||
// Allocate SA
|
||||
sa, err := netlink.XfrmStateAllocSpi(xfrmAllocSpiState(remoteIP, localIP))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, fmt.Sprintf("ip xfrm state allocspi (in, %s, %s)", remoteIP, localIP))
|
||||
return nil, errors.Wrap(err, fmt.Sprintf("ip xfrm state allocspi (in, %s, %s)", remoteIP, localIP))
|
||||
}
|
||||
|
||||
// Use SPI generated by the kernel. The kernel ensures {dstIP, spi} to
|
||||
@@ -117,28 +117,24 @@ func (ipsec *IPSec) InitSALocal(localPeer, remotePeer mesh.PeerName, connUID uin
|
||||
// Create SA
|
||||
if sa, err := xfrmState(remoteIP, localIP, spi, false, key); err == nil {
|
||||
if err := netlink.XfrmStateUpdate(sa); err != nil {
|
||||
return errors.Wrap(err, fmt.Sprintf("xfrm state update (in, %s, %s, 0x%x)", sa.Src, sa.Dst, sa.Spi))
|
||||
return nil, errors.Wrap(err, fmt.Sprintf("xfrm state update (in, %s, %s, 0x%x)", sa.Src, sa.Dst, sa.Spi))
|
||||
}
|
||||
} else {
|
||||
return errors.Wrap(err, "new xfrm state (in)")
|
||||
return nil, errors.Wrap(err, "new xfrm state (in)")
|
||||
}
|
||||
|
||||
// Install iptables rules
|
||||
if err := ipsec.installDropNonEncrypted(localIP, remoteIP, udpPort, spi); err != nil {
|
||||
return errors.Wrap(err, fmt.Sprintf("install protecting rules (%s, %s, %d, 0x%x)", localIP, remoteIP, udpPort, spi))
|
||||
return nil, errors.Wrap(err, fmt.Sprintf("install protecting rules (%s, %s, %d, 0x%x)", localIP, remoteIP, udpPort, spi))
|
||||
}
|
||||
|
||||
si := spiInfo{spi: spi, isDirOut: false}
|
||||
ipsec.spiInfo[spiID] = si
|
||||
ipsec.spis[spi] = &si
|
||||
|
||||
// Trigger the initialization on the remote peer
|
||||
// Generate the message to trigger initialization on the remote peer
|
||||
msg := &msgInitSARemote{nonce, spi}
|
||||
if err := initRemote(msg.serialize()); err != nil {
|
||||
return errors.Wrap(err, "send InitSARemote")
|
||||
}
|
||||
|
||||
return nil
|
||||
return msg.serialize(), nil
|
||||
}
|
||||
|
||||
// InitSARemote initializes outbound ipsec to remotePeer.
|
||||
@@ -223,9 +219,19 @@ func (ipsec *IPSec) Destroy(localPeer, remotePeer mesh.PeerName, connUID uint64,
|
||||
|
||||
if outSPIInfo, ok := ipsec.spiInfo[outSPIID]; ok {
|
||||
ipsec.log.Infof("ipsec: destroy: out %s -> %s 0x%x", localIP, remoteIP, outSPIInfo.spi)
|
||||
|
||||
if err := netlink.XfrmPolicyDel(xfrmPolicy(localIP, remoteIP, outSPIInfo.spi)); err != nil {
|
||||
ipsec.log.Warnf("ipsec: xfrm policy del (%s, %s, 0x%x) failed: %s", localIP, remoteIP, outSPIInfo.spi, err)
|
||||
policy, err := netlink.XfrmPolicyGet(xfrmPolicy(localIP, remoteIP, outSPIInfo.spi))
|
||||
if err != nil {
|
||||
ipsec.log.Warnf("ipsec: xfrm policy get (%s, %s, 0x%x) failed: %s", localIP, remoteIP, outSPIInfo.spi, err)
|
||||
} else {
|
||||
if len(policy.Tmpls) == 1 {
|
||||
if policy.Tmpls[0].Spi == int(outSPIInfo.spi) {
|
||||
if err := netlink.XfrmPolicyDel(xfrmPolicy(localIP, remoteIP, outSPIInfo.spi)); err != nil {
|
||||
ipsec.log.Warnf("ipsec: xfrm policy del (%s, %s, 0x%x) failed: %s", localIP, remoteIP, outSPIInfo.spi, err)
|
||||
}
|
||||
} else {
|
||||
ipsec.log.Debugf("ipsec: xfrm not my policy (%s, %s, 0x%x) got 0x%x ", localIP, remoteIP, outSPIInfo.spi, policy.Tmpls[0].Spi)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
outSA := &netlink.XfrmState{
|
||||
|
||||
+3
-3
@@ -55,9 +55,9 @@ func WithNetNSByPath(path string, work func() error) error {
|
||||
}
|
||||
|
||||
func NSPathByPid(pid int) string {
|
||||
return NSPathByPidWithRoot("/", pid)
|
||||
return NSPathByPidWithProc("/proc", pid)
|
||||
}
|
||||
|
||||
func NSPathByPidWithRoot(root string, pid int) string {
|
||||
return filepath.Join(root, fmt.Sprintf("/proc/%d/ns/net", pid))
|
||||
func NSPathByPidWithProc(procPath string, pid int) string {
|
||||
return filepath.Join(procPath, fmt.Sprint(pid), "/ns/net")
|
||||
}
|
||||
+17
-8
@@ -13,7 +13,7 @@ import (
|
||||
)
|
||||
|
||||
// create and attach a veth to the Weave bridge
|
||||
func CreateAndAttachVeth(name, peerName, bridgeName string, mtu int, keepTXOn bool, errIfLinkExist bool, init func(peer netlink.Link) error) (*netlink.Veth, error) {
|
||||
func CreateAndAttachVeth(procPath, name, peerName, bridgeName string, mtu int, keepTXOn bool, errIfLinkExist bool, init func(peer netlink.Link) error) (*netlink.Veth, error) {
|
||||
bridge, err := netlink.LinkByName(bridgeName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(`bridge "%s" not present; did you launch weave?`, bridgeName)
|
||||
@@ -49,6 +49,13 @@ func CreateAndAttachVeth(name, peerName, bridgeName string, mtu int, keepTXOn bo
|
||||
if err := bridgeType.attach(veth); err != nil {
|
||||
return cleanup("attaching veth %q to %q: %s", name, bridgeName, err)
|
||||
}
|
||||
// No ipv6 router advertisments please
|
||||
if err := sysctl(procPath, "net/ipv6/conf/"+name+"/accept_ra", "0"); err != nil {
|
||||
return cleanup("setting accept_ra to 0: %s", err)
|
||||
}
|
||||
if err := sysctl(procPath, "net/ipv6/conf/"+peerName+"/accept_ra", "0"); err != nil {
|
||||
return cleanup("setting accept_ra to 0: %s", err)
|
||||
}
|
||||
if !bridgeType.IsFastdp() && !keepTXOn {
|
||||
if err := EthtoolTXOff(veth.PeerName); err != nil {
|
||||
return cleanup(`unable to set tx off on %q: %s`, peerName, err)
|
||||
@@ -112,6 +119,9 @@ func interfaceExistsInNamespace(netNSPath string, ifName string) bool {
|
||||
}
|
||||
|
||||
func AttachContainer(netNSPath, id, ifName, bridgeName string, mtu int, withMulticastRoute bool, cidrs []*net.IPNet, keepTXOn bool, hairpinMode bool) error {
|
||||
// AttachContainer expects to be called in host pid namespace
|
||||
const procPath = "/proc"
|
||||
|
||||
ns, err := netns.GetFromPath(netNSPath)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -124,12 +134,12 @@ func AttachContainer(netNSPath, id, ifName, bridgeName string, mtu int, withMult
|
||||
id = id[:maxIDLen] // trim passed ID if too long
|
||||
}
|
||||
name, peerName := vethPrefix+"pl"+id, vethPrefix+"pg"+id
|
||||
veth, err := CreateAndAttachVeth(name, peerName, bridgeName, mtu, keepTXOn, true, func(veth netlink.Link) error {
|
||||
veth, err := CreateAndAttachVeth(procPath, name, peerName, bridgeName, mtu, keepTXOn, true, func(veth netlink.Link) error {
|
||||
if err := netlink.LinkSetNsFd(veth, int(ns)); err != nil {
|
||||
return fmt.Errorf("failed to move veth to container netns: %s", err)
|
||||
}
|
||||
if err := WithNetNS(ns, func() error {
|
||||
return setupIface(peerName, ifName)
|
||||
return setupIface(procPath, peerName, ifName)
|
||||
}); err != nil {
|
||||
return fmt.Errorf("error setting up interface: %s", err)
|
||||
}
|
||||
@@ -206,7 +216,7 @@ func setupIfaceAddrs(veth netlink.Link, withMulticastRoute bool, cidrs []*net.IP
|
||||
}
|
||||
|
||||
// setupIface expects to be called in the container's netns
|
||||
func setupIface(ifaceName, newIfName string) error {
|
||||
func setupIface(procPath, ifaceName, newIfName string) error {
|
||||
ipt, err := iptables.New()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -219,15 +229,14 @@ func setupIface(ifaceName, newIfName string) error {
|
||||
if err := netlink.LinkSetName(link, newIfName); err != nil {
|
||||
return err
|
||||
}
|
||||
// This is only called by AttachContainer which is only called in host pid namespace
|
||||
if err := configureARPCache("/proc", newIfName); err != nil {
|
||||
if err := configureARPCache(procPath, newIfName); err != nil {
|
||||
return err
|
||||
}
|
||||
return ipt.Append("filter", "INPUT", "-i", newIfName, "-d", "224.0.0.0/4", "-j", "DROP")
|
||||
}
|
||||
|
||||
// configureARP is a helper for the Docker plugin which doesn't set the addresses itself
|
||||
func ConfigureARP(prefix, rootPath string) error {
|
||||
func ConfigureARP(prefix, procPath string) error {
|
||||
links, err := netlink.LinkList()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -235,7 +244,7 @@ func ConfigureARP(prefix, rootPath string) error {
|
||||
for _, link := range links {
|
||||
ifName := link.Attrs().Name
|
||||
if strings.HasPrefix(ifName, prefix) {
|
||||
configureARPCache(rootPath+"/proc", ifName)
|
||||
configureARPCache(procPath, ifName)
|
||||
if addrs, err := netlink.AddrList(link, netlink.FAMILY_V4); err == nil {
|
||||
for _, addr := range addrs {
|
||||
arping.GratuitousArpOverIfaceByName(addr.IPNet.IP, ifName)
|
||||
|
||||
+33
-19
@@ -12,12 +12,14 @@ import (
|
||||
|
||||
func (ns *ns) analysePolicy(policy *networkingv1.NetworkPolicy) (
|
||||
rules map[string]*ruleSpec,
|
||||
nsSelectors, podSelectors map[string]*selectorSpec,
|
||||
nsSelectors, podSelectors, namespacedPodSelectors map[string]*selectorSpec,
|
||||
ipBlocks map[string]*ipBlockSpec,
|
||||
err error) {
|
||||
|
||||
nsSelectors = make(map[string]*selectorSpec)
|
||||
podSelectors = make(map[string]*selectorSpec)
|
||||
namespacedPodSelectors = make(map[string]*selectorSpec)
|
||||
|
||||
ipBlocks = make(map[string]*ipBlockSpec)
|
||||
rules = make(map[string]*ruleSpec)
|
||||
policyTypes := make([]policyType, 0)
|
||||
@@ -31,9 +33,9 @@ func (ns *ns) analysePolicy(policy *networkingv1.NetworkPolicy) (
|
||||
}
|
||||
}
|
||||
// If empty, matches all pods in a namespace
|
||||
targetSelector, err := newSelectorSpec(&policy.Spec.PodSelector, policyTypes, ns.name, ipset.HashIP)
|
||||
targetSelector, err := newSelectorSpec(&policy.Spec.PodSelector, nil, policyTypes, ns.name, ipset.HashIP)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
return nil, nil, nil, nil, nil, err
|
||||
}
|
||||
|
||||
// To prevent targetSelector being overwritten by a subsequent selector with
|
||||
@@ -52,7 +54,7 @@ func (ns *ns) analysePolicy(policy *networkingv1.NetworkPolicy) (
|
||||
|
||||
if !allPorts {
|
||||
if err = checkForNamedPorts(ingressRule.Ports); err != nil {
|
||||
return nil, nil, nil, nil, fmt.Errorf("named ports in network policies is not supported yet. "+
|
||||
return nil, nil, nil, nil, nil, fmt.Errorf("named ports in network policies is not supported yet. "+
|
||||
"Rejecting network policy: %s from further processing. "+err.Error(), policy.Name)
|
||||
}
|
||||
}
|
||||
@@ -72,18 +74,24 @@ func (ns *ns) analysePolicy(policy *networkingv1.NetworkPolicy) (
|
||||
var srcRuleHost ruleHost
|
||||
|
||||
// NetworkPolicyPeer describes a peer to allow traffic from.
|
||||
// Exactly one of its fields must be specified.
|
||||
if peer.PodSelector != nil {
|
||||
srcSelector, err = newSelectorSpec(peer.PodSelector, nil, ns.name, ipset.HashIP)
|
||||
if peer.PodSelector != nil && peer.NamespaceSelector != nil {
|
||||
srcSelector, err = newSelectorSpec(peer.PodSelector, peer.NamespaceSelector, nil, "", ipset.HashIP)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
return nil, nil, nil, nil, nil, err
|
||||
}
|
||||
addIfNotExist(srcSelector, namespacedPodSelectors)
|
||||
srcRuleHost = srcSelector
|
||||
} else if peer.PodSelector != nil {
|
||||
srcSelector, err = newSelectorSpec(peer.PodSelector, nil, nil, ns.name, ipset.HashIP)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, nil, err
|
||||
}
|
||||
addIfNotExist(srcSelector, podSelectors)
|
||||
srcRuleHost = srcSelector
|
||||
} else if peer.NamespaceSelector != nil {
|
||||
srcSelector, err = newSelectorSpec(peer.NamespaceSelector, nil, "", ipset.ListSet)
|
||||
srcSelector, err = newSelectorSpec(nil, peer.NamespaceSelector, nil, "", ipset.ListSet)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
return nil, nil, nil, nil, nil, err
|
||||
}
|
||||
nsSelectors[srcSelector.key] = srcSelector
|
||||
srcRuleHost = srcSelector
|
||||
@@ -98,7 +106,7 @@ func (ns *ns) analysePolicy(policy *networkingv1.NetworkPolicy) (
|
||||
rules[rule.key] = rule
|
||||
} else {
|
||||
withNormalisedProtoAndPort(ingressRule.Ports, func(proto, port string) {
|
||||
rule := newRuleSpec(policyTypeIngress, &proto, srcSelector, targetSelector, &port)
|
||||
rule := newRuleSpec(policyTypeIngress, &proto, srcRuleHost, targetSelector, &port)
|
||||
rules[rule.key] = rule
|
||||
})
|
||||
}
|
||||
@@ -117,7 +125,7 @@ func (ns *ns) analysePolicy(policy *networkingv1.NetworkPolicy) (
|
||||
|
||||
if !allPorts {
|
||||
if err = checkForNamedPorts(egressRule.Ports); err != nil {
|
||||
return nil, nil, nil, nil, fmt.Errorf("named ports in network policies is not supported yet. "+
|
||||
return nil, nil, nil, nil, nil, fmt.Errorf("named ports in network policies is not supported yet. "+
|
||||
"Rejecting network policy: %s from further processing. "+err.Error(), policy.Name)
|
||||
}
|
||||
}
|
||||
@@ -137,19 +145,25 @@ func (ns *ns) analysePolicy(policy *networkingv1.NetworkPolicy) (
|
||||
var dstRuleHost ruleHost
|
||||
|
||||
// NetworkPolicyPeer describes a peer to allow traffic to.
|
||||
// Exactly one of its fields must be specified.
|
||||
if peer.PodSelector != nil {
|
||||
dstSelector, err = newSelectorSpec(peer.PodSelector, nil, ns.name, ipset.HashIP)
|
||||
if peer.PodSelector != nil && peer.NamespaceSelector != nil {
|
||||
dstSelector, err = newSelectorSpec(peer.PodSelector, peer.NamespaceSelector, nil, "", ipset.HashIP)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
return nil, nil, nil, nil, nil, err
|
||||
}
|
||||
addIfNotExist(dstSelector, namespacedPodSelectors)
|
||||
dstRuleHost = dstSelector
|
||||
} else if peer.PodSelector != nil {
|
||||
dstSelector, err = newSelectorSpec(peer.PodSelector, nil, nil, ns.name, ipset.HashIP)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, nil, err
|
||||
}
|
||||
addIfNotExist(dstSelector, podSelectors)
|
||||
dstRuleHost = dstSelector
|
||||
|
||||
} else if peer.NamespaceSelector != nil {
|
||||
dstSelector, err = newSelectorSpec(peer.NamespaceSelector, nil, "", ipset.ListSet)
|
||||
dstSelector, err = newSelectorSpec(nil, peer.NamespaceSelector, nil, "", ipset.ListSet)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
return nil, nil, nil, nil, nil, err
|
||||
}
|
||||
nsSelectors[dstSelector.key] = dstSelector
|
||||
dstRuleHost = dstSelector
|
||||
@@ -173,7 +187,7 @@ func (ns *ns) analysePolicy(policy *networkingv1.NetworkPolicy) (
|
||||
}
|
||||
}
|
||||
|
||||
return rules, nsSelectors, podSelectors, ipBlocks, nil
|
||||
return rules, nsSelectors, podSelectors, namespacedPodSelectors, ipBlocks, nil
|
||||
}
|
||||
|
||||
func addIfNotExist(s *selectorSpec, ss map[string]*selectorSpec) {
|
||||
|
||||
+74
-14
@@ -1,12 +1,15 @@
|
||||
package npc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
coreapi "k8s.io/api/core/v1"
|
||||
extnapi "k8s.io/api/extensions/v1beta1"
|
||||
networkingv1 "k8s.io/api/networking/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
|
||||
"github.com/weaveworks/weave/common"
|
||||
"github.com/weaveworks/weave/net/ipset"
|
||||
@@ -32,30 +35,33 @@ type controller struct {
|
||||
|
||||
nodeName string // my node name
|
||||
|
||||
ipt iptables.Interface
|
||||
ips ipset.Interface
|
||||
|
||||
nss map[string]*ns // ns name -> ns struct
|
||||
nsSelectors *selectorSet // selector string -> nsSelector
|
||||
ipt iptables.Interface
|
||||
ips ipset.Interface
|
||||
clientset kubernetes.Interface
|
||||
nss map[string]*ns // ns name -> ns struct
|
||||
nsSelectors *selectorSet // selector string -> nsSelector
|
||||
namespacedPodSelectors *selectorSet
|
||||
defaultEgressDrop bool // flag to track if base iptable rule to drop egress traffic is added or not
|
||||
}
|
||||
|
||||
func New(nodeName string, ipt iptables.Interface, ips ipset.Interface) NetworkPolicyController {
|
||||
func New(nodeName string, ipt iptables.Interface, ips ipset.Interface, clientset kubernetes.Interface) NetworkPolicyController {
|
||||
c := &controller{
|
||||
nodeName: nodeName,
|
||||
ipt: ipt,
|
||||
ips: ips,
|
||||
nss: make(map[string]*ns)}
|
||||
nodeName: nodeName,
|
||||
ipt: ipt,
|
||||
ips: ips,
|
||||
clientset: clientset,
|
||||
nss: make(map[string]*ns)}
|
||||
|
||||
doNothing := func(*selector, policyType) error { return nil }
|
||||
c.nsSelectors = newSelectorSet(ips, c.onNewNsSelector, doNothing, doNothing)
|
||||
|
||||
c.namespacedPodSelectors = newSelectorSet(ips, c.onNewNamespacePodsSelector, doNothing, doNothing)
|
||||
return c
|
||||
}
|
||||
|
||||
func (npc *controller) onNewNsSelector(selector *selector) error {
|
||||
for _, ns := range npc.nss {
|
||||
if ns.namespace != nil {
|
||||
if selector.matches(ns.namespace.ObjectMeta.Labels) {
|
||||
if selector.matchesNamespaceSelector(ns.namespace.ObjectMeta.Labels) {
|
||||
if err := selector.addEntry(ns.namespace.ObjectMeta.UID, string(ns.allPods.ipsetName), namespaceComment(ns)); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -65,10 +71,32 @@ func (npc *controller) onNewNsSelector(selector *selector) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (npc *controller) onNewNamespacePodsSelector(selector *selector) error {
|
||||
for _, ns := range npc.nss {
|
||||
if ns.namespace != nil && len(ns.pods) > 0 {
|
||||
for _, pod := range ns.pods {
|
||||
if hasIP(pod) {
|
||||
if selector.matchesNamespacedPodSelector(pod.ObjectMeta.Labels, ns.namespace.ObjectMeta.Labels) {
|
||||
if err := selector.addEntry(pod.ObjectMeta.UID, pod.Status.PodIP, podComment(pod)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (npc *controller) withNS(name string, f func(ns *ns) error) error {
|
||||
ns, found := npc.nss[name]
|
||||
if !found {
|
||||
newNs, err := newNS(name, npc.nodeName, npc.ipt, npc.ips, npc.nsSelectors)
|
||||
namespace, err := npc.clientset.CoreV1().Namespaces().Get(name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
newNs, err := newNS(name, npc.nodeName, npc.ipt, npc.ips, npc.nsSelectors, npc.namespacedPodSelectors, namespace)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -121,11 +149,26 @@ func (npc *controller) AddNetworkPolicy(obj interface{}) error {
|
||||
npc.Lock()
|
||||
defer npc.Unlock()
|
||||
|
||||
// lazily add default rule to drop egress traffic only when network policies are applied
|
||||
if !npc.defaultEgressDrop {
|
||||
egressNetworkPolicy, err := isEgressNetworkPolicy(obj)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if egressNetworkPolicy {
|
||||
npc.defaultEgressDrop = true
|
||||
if err := npc.ipt.Append(TableFilter, EgressChain,
|
||||
"-m", "mark", "!", "--mark", EgressMark, "-j", "DROP"); err != nil {
|
||||
npc.defaultEgressDrop = false
|
||||
return fmt.Errorf("Failed to add iptable rule to drop egress traffic from the pods by default due to %s", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsName, err := nsName(obj)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
common.Log.Infof("EVENT AddNetworkPolicy %s", js(obj))
|
||||
return npc.withNS(nsName, func(ns *ns) error {
|
||||
return errors.Wrap(ns.addNetworkPolicy(obj), "add network policy")
|
||||
@@ -202,3 +245,20 @@ func nsName(obj interface{}) (string, error) {
|
||||
|
||||
return "", errInvalidNetworkPolicyObjType
|
||||
}
|
||||
|
||||
func isEgressNetworkPolicy(obj interface{}) (bool, error) {
|
||||
if policy, ok := obj.(*networkingv1.NetworkPolicy); ok {
|
||||
if len(policy.Spec.PolicyTypes) > 0 {
|
||||
for _, policyType := range policy.Spec.PolicyTypes {
|
||||
if policyType == networkingv1.PolicyTypeEgress {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
if policy.Spec.Egress != nil {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
return false, errInvalidNetworkPolicyObjType
|
||||
}
|
||||
+104
-6
@@ -14,6 +14,7 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
)
|
||||
|
||||
type mockSet struct {
|
||||
@@ -198,7 +199,10 @@ func TestRegressionPolicyNamespaceOrdering3059(t *testing.T) {
|
||||
|
||||
// Namespaces first
|
||||
m := newMockIPSet()
|
||||
controller := New("foo", newMockIPTables(), &m)
|
||||
client := fake.NewSimpleClientset()
|
||||
controller := New("foo", newMockIPTables(), &m, client)
|
||||
client.CoreV1().Namespaces().Create(sourceNamespace)
|
||||
client.CoreV1().Namespaces().Create(destinationNamespace)
|
||||
|
||||
const (
|
||||
selectorIPSetName = "weave-I239Zp%sCvoVt*D6u=A!2]YEk"
|
||||
@@ -214,7 +218,7 @@ func TestRegressionPolicyNamespaceOrdering3059(t *testing.T) {
|
||||
|
||||
// NetworkPolicy first
|
||||
m = newMockIPSet()
|
||||
controller = New("foo", newMockIPTables(), &m)
|
||||
controller = New("foo", newMockIPTables(), &m, &fake.Clientset{})
|
||||
|
||||
controller.AddNetworkPolicy(networkPolicy)
|
||||
|
||||
@@ -235,7 +239,7 @@ func TestDefaultAllow(t *testing.T) {
|
||||
)
|
||||
|
||||
m := newMockIPSet()
|
||||
controller := New("bar", newMockIPTables(), &m)
|
||||
controller := New("bar", newMockIPTables(), &m, &fake.Clientset{})
|
||||
|
||||
defaultNamespace := &coreapi.Namespace{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@@ -363,13 +367,15 @@ func TestOutOfOrderPodEvents(t *testing.T) {
|
||||
)
|
||||
|
||||
m := newMockIPSet()
|
||||
controller := New("qux", newMockIPTables(), &m)
|
||||
client := fake.NewSimpleClientset()
|
||||
controller := New("qux", newMockIPTables(), &m, client)
|
||||
|
||||
defaultNamespace := &coreapi.Namespace{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "default",
|
||||
},
|
||||
}
|
||||
client.CoreV1().Namespaces().Create(defaultNamespace)
|
||||
controller.AddNamespace(defaultNamespace)
|
||||
|
||||
podFoo := &coreapi.Pod{
|
||||
@@ -445,13 +451,15 @@ func TestNewTargetSelector(t *testing.T) {
|
||||
)
|
||||
|
||||
m := newMockIPSet()
|
||||
controller := New("baz", newMockIPTables(), &m)
|
||||
client := fake.NewSimpleClientset()
|
||||
controller := New("baz", newMockIPTables(), &m, client)
|
||||
|
||||
defaultNamespace := &coreapi.Namespace{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "default",
|
||||
},
|
||||
}
|
||||
client.CoreV1().Namespaces().Create(defaultNamespace)
|
||||
controller.AddNamespace(defaultNamespace)
|
||||
|
||||
podFoo := &coreapi.Pod{
|
||||
@@ -521,7 +529,21 @@ func TestEgressPolicyWithIPBlock(t *testing.T) {
|
||||
|
||||
m := newMockIPSet()
|
||||
ipt := newMockIPTables()
|
||||
controller := New("foo", ipt, &m)
|
||||
client := fake.NewSimpleClientset()
|
||||
controller := New("foo", ipt, &m, client)
|
||||
|
||||
defaultNamespace := &coreapi.Namespace{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "default",
|
||||
},
|
||||
}
|
||||
nonDefaultNamespace := &coreapi.Namespace{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "non-default",
|
||||
},
|
||||
}
|
||||
client.CoreV1().Namespaces().Create(defaultNamespace)
|
||||
client.CoreV1().Namespaces().Create(nonDefaultNamespace)
|
||||
|
||||
netpolFoo := &networkingv1.NetworkPolicy{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@@ -592,3 +614,79 @@ func TestEgressPolicyWithIPBlock(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 2, len(m.sets[exceptIPSetNameInNonDefault].subSets))
|
||||
}
|
||||
|
||||
// Test case for https://github.com/weaveworks/weave/issues/3653
|
||||
func TestIngressPolicyWithIPBlockAndPortSpecified(t *testing.T) {
|
||||
const (
|
||||
barPodIP = "10.32.0.11"
|
||||
runBarIPSetName = "weave-bZ~x=yBgzH)Ht()K*Uv3z{M]Y"
|
||||
)
|
||||
|
||||
m := newMockIPSet()
|
||||
ipt := newMockIPTables()
|
||||
client := fake.NewSimpleClientset()
|
||||
controller := New("any", ipt, &m, client)
|
||||
|
||||
defaultNamespace := &coreapi.Namespace{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "default",
|
||||
},
|
||||
}
|
||||
|
||||
client.CoreV1().Namespaces().Create(defaultNamespace)
|
||||
|
||||
podBar := &coreapi.Pod{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
UID: "bar",
|
||||
Namespace: "default",
|
||||
Name: "bar",
|
||||
Labels: map[string]string{"run": "bar"}},
|
||||
Status: coreapi.PodStatus{PodIP: barPodIP}}
|
||||
controller.AddPod(podBar)
|
||||
defer controller.DeletePod(podBar)
|
||||
|
||||
portProtocol := coreapi.ProtocolTCP
|
||||
port := intstr.FromInt(80)
|
||||
netpolicty := &networkingv1.NetworkPolicy{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
UID: "ipblock-bar",
|
||||
Name: "allow-ipblock-to-bar",
|
||||
Namespace: "default",
|
||||
},
|
||||
Spec: networkingv1.NetworkPolicySpec{
|
||||
PolicyTypes: []networkingv1.PolicyType{
|
||||
networkingv1.PolicyTypeIngress,
|
||||
},
|
||||
PodSelector: metav1.LabelSelector{MatchLabels: podBar.Labels},
|
||||
Ingress: []networkingv1.NetworkPolicyIngressRule{
|
||||
{
|
||||
Ports: []networkingv1.NetworkPolicyPort{
|
||||
{
|
||||
Protocol: &portProtocol,
|
||||
Port: &port,
|
||||
},
|
||||
},
|
||||
From: []networkingv1.NetworkPolicyPeer{
|
||||
{
|
||||
IPBlock: &networkingv1.IPBlock{
|
||||
CIDR: "192.168.48.4/32",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
err := controller.AddNetworkPolicy(netpolicty)
|
||||
require.NoError(t, err)
|
||||
defer controller.DeleteNetworkPolicy(netpolicty)
|
||||
|
||||
require.Equal(t, 1, len(m.sets[runBarIPSetName].subSets))
|
||||
require.True(t, m.entryExists(runBarIPSetName, barPodIP))
|
||||
|
||||
require.Equal(t, 1, len(ipt.rules[IngressChain]))
|
||||
for rule := range ipt.rules[IngressChain] {
|
||||
require.Contains(t, rule, "-s 192.168.48.4/32 -m set --match-set "+runBarIPSetName+" dst --dport 80")
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,12 @@ var (
|
||||
},
|
||||
[]string{"protocol", "dport"},
|
||||
)
|
||||
PolicyEnforcementErrors = prometheus.NewCounter(
|
||||
prometheus.CounterOpts{
|
||||
Name: "weavenpc_policy_enforcement_errors",
|
||||
Help: "Errors occured in enforcing the network policies.",
|
||||
},
|
||||
)
|
||||
)
|
||||
|
||||
func gatherMetrics() {
|
||||
@@ -95,6 +101,9 @@ func Start(addr string) error {
|
||||
if err := prometheus.Register(blockedConnections); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := prometheus.Register(PolicyEnforcementErrors); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
http.Handle("/metrics", promhttp.Handler())
|
||||
|
||||
|
||||
+87
-38
@@ -37,30 +37,33 @@ type ns struct {
|
||||
ingressDefaultAllowIPSet ipset.Name
|
||||
egressDefaultAllowIPSet ipset.Name
|
||||
|
||||
nsSelectors *selectorSet
|
||||
podSelectors *selectorSet
|
||||
ipBlocks *ipBlockSet
|
||||
rules *ruleSet
|
||||
nsSelectors *selectorSet // reference to global selectorSet that is shared across the `ns`. Used to represent all pods in the matching namespaces
|
||||
podSelectors *selectorSet // used to represent the matching pods in namespace respresented by this `ns`
|
||||
namespacedPodsSelectors *selectorSet // reference to global selectorSet that is shared across the `ns`. Used to represent matching pods in matching namespace
|
||||
ipBlocks *ipBlockSet
|
||||
rules *ruleSet
|
||||
}
|
||||
|
||||
func newNS(name, nodeName string, ipt iptables.Interface, ips ipset.Interface, nsSelectors *selectorSet) (*ns, error) {
|
||||
allPods, err := newSelectorSpec(&metav1.LabelSelector{}, nil, name, ipset.HashIP)
|
||||
func newNS(name, nodeName string, ipt iptables.Interface, ips ipset.Interface, nsSelectors *selectorSet, namespacedPodsSelectors *selectorSet, namespaceObj *coreapi.Namespace) (*ns, error) {
|
||||
allPods, err := newSelectorSpec(&metav1.LabelSelector{}, nil, nil, name, ipset.HashIP)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ns := &ns{
|
||||
ipt: ipt,
|
||||
ips: ips,
|
||||
name: name,
|
||||
nodeName: nodeName,
|
||||
pods: make(map[types.UID]*coreapi.Pod),
|
||||
policies: make(map[types.UID]interface{}),
|
||||
uid: uuid.NewUUID(),
|
||||
allPods: allPods,
|
||||
nsSelectors: nsSelectors,
|
||||
ipBlocks: newIPBlockSet(ips),
|
||||
rules: newRuleSet(ipt),
|
||||
ipt: ipt,
|
||||
ips: ips,
|
||||
name: name,
|
||||
namespace: namespaceObj,
|
||||
nodeName: nodeName,
|
||||
pods: make(map[types.UID]*coreapi.Pod),
|
||||
policies: make(map[types.UID]interface{}),
|
||||
uid: uuid.NewUUID(),
|
||||
allPods: allPods,
|
||||
nsSelectors: nsSelectors,
|
||||
namespacedPodsSelectors: namespacedPodsSelectors,
|
||||
ipBlocks: newIPBlockSet(ips),
|
||||
rules: newRuleSet(ipt),
|
||||
}
|
||||
|
||||
ns.podSelectors = newSelectorSet(ips, ns.onNewPodSelector, ns.onNewTargetPodSelector, ns.onDestroyTargetPodSelector)
|
||||
@@ -95,7 +98,7 @@ func (ns *ns) destroy() error {
|
||||
func (ns *ns) onNewPodSelector(selector *selector) error {
|
||||
for _, pod := range ns.pods {
|
||||
if hasIP(pod) {
|
||||
if selector.matches(pod.ObjectMeta.Labels) {
|
||||
if selector.matchesPodSelector(pod.ObjectMeta.Labels) {
|
||||
if err := selector.addEntry(pod.ObjectMeta.UID, pod.Status.PodIP, podComment(pod)); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -111,7 +114,7 @@ func (ns *ns) onNewTargetPodSelector(selector *selector, policyType policyType)
|
||||
if hasIP(pod) {
|
||||
// Remove the pod from default-allow if dst podselector matches the pod
|
||||
ipset := ns.defaultAllowIPSetName(policyType)
|
||||
if selector.matches(pod.ObjectMeta.Labels) {
|
||||
if selector.matchesPodSelector(pod.ObjectMeta.Labels) {
|
||||
if err := ns.ips.DelEntry(pod.ObjectMeta.UID, ipset, pod.Status.PodIP); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -125,7 +128,7 @@ func (ns *ns) onNewTargetPodSelector(selector *selector, policyType policyType)
|
||||
func (ns *ns) onDestroyTargetPodSelector(selector *selector, policyType policyType) error {
|
||||
for _, pod := range ns.pods {
|
||||
if hasIP(pod) {
|
||||
if selector.matches(pod.ObjectMeta.Labels) {
|
||||
if selector.matchesPodSelector(pod.ObjectMeta.Labels) {
|
||||
if err := ns.addToDefaultAllowIfNoMatching(pod, policyType); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -141,7 +144,7 @@ func (ns *ns) addToDefaultAllowIfNoMatching(pod *coreapi.Pod, policyType policyT
|
||||
found := false
|
||||
// TODO(mp) optimize (avoid iterating over selectors) by ref counting IP addrs.
|
||||
for _, s := range ns.podSelectors.entries {
|
||||
if ns.podSelectors.targetSelectorExist(s, policyType) && s.matches(pod.ObjectMeta.Labels) {
|
||||
if ns.podSelectors.targetSelectorExist(s, policyType) && s.matchesPodSelector(pod.ObjectMeta.Labels) {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
@@ -169,7 +172,7 @@ func (ns *ns) addPod(obj *coreapi.Pod) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
foundIngress, foundEgress, err := ns.podSelectors.addToMatching(obj.ObjectMeta.UID, obj.ObjectMeta.Labels, obj.Status.PodIP, podComment(obj))
|
||||
foundIngress, foundEgress, err := ns.podSelectors.addToMatchingPodSelector(obj.ObjectMeta.UID, obj.ObjectMeta.Labels, obj.Status.PodIP, podComment(obj))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -185,6 +188,11 @@ func (ns *ns) addPod(obj *coreapi.Pod) error {
|
||||
}
|
||||
}
|
||||
|
||||
err = ns.namespacedPodsSelectors.addToMatchingNamespacedPodSelector(obj.ObjectMeta.UID, obj.ObjectMeta.Labels, ns.namespace.ObjectMeta.Labels, obj.Status.PodIP, podComment(obj))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -203,12 +211,15 @@ func (ns *ns) updatePod(oldObj, newObj *coreapi.Pod) error {
|
||||
if err := ns.ips.DelEntry(oldObj.ObjectMeta.UID, ns.egressDefaultAllowIPSet, oldObj.Status.PodIP); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ns.namespacedPodsSelectors.delFromMatchingNamespacedPodSelector(oldObj.ObjectMeta.UID, oldObj.ObjectMeta.Labels, ns.namespace.ObjectMeta.Labels, oldObj.Status.PodIP); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return ns.podSelectors.delFromMatching(oldObj.ObjectMeta.UID, oldObj.ObjectMeta.Labels, oldObj.Status.PodIP)
|
||||
return ns.podSelectors.delFromMatchingPodSelector(oldObj.ObjectMeta.UID, oldObj.ObjectMeta.Labels, oldObj.Status.PodIP)
|
||||
}
|
||||
|
||||
if !hasIP(oldObj) && hasIP(newObj) {
|
||||
foundIngress, foundEgress, err := ns.podSelectors.addToMatching(newObj.ObjectMeta.UID, newObj.ObjectMeta.Labels, newObj.Status.PodIP, podComment(newObj))
|
||||
foundIngress, foundEgress, err := ns.podSelectors.addToMatchingPodSelector(newObj.ObjectMeta.UID, newObj.ObjectMeta.Labels, newObj.Status.PodIP, podComment(newObj))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -223,6 +234,10 @@ func (ns *ns) updatePod(oldObj, newObj *coreapi.Pod) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
err = ns.namespacedPodsSelectors.addToMatchingNamespacedPodSelector(newObj.ObjectMeta.UID, newObj.ObjectMeta.Labels, ns.namespace.ObjectMeta.Labels, newObj.Status.PodIP, podComment(newObj))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -240,8 +255,8 @@ func (ns *ns) updatePod(oldObj, newObj *coreapi.Pod) error {
|
||||
oldObj.Status.PodIP != newObj.Status.PodIP {
|
||||
|
||||
for _, ps := range ns.podSelectors.entries {
|
||||
oldMatch := ps.matches(oldObj.ObjectMeta.Labels)
|
||||
newMatch := ps.matches(newObj.ObjectMeta.Labels)
|
||||
oldMatch := ps.matchesPodSelector(oldObj.ObjectMeta.Labels)
|
||||
newMatch := ps.matchesPodSelector(newObj.ObjectMeta.Labels)
|
||||
if oldMatch == newMatch && oldObj.Status.PodIP == newObj.Status.PodIP {
|
||||
continue
|
||||
}
|
||||
@@ -263,6 +278,23 @@ func (ns *ns) updatePod(oldObj, newObj *coreapi.Pod) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
for _, ps := range ns.namespacedPodsSelectors.entries {
|
||||
oldMatch := ps.matchesNamespacedPodSelector(oldObj.ObjectMeta.Labels, ns.namespace.ObjectMeta.Labels)
|
||||
newMatch := ps.matchesNamespacedPodSelector(newObj.ObjectMeta.Labels, ns.namespace.ObjectMeta.Labels)
|
||||
if oldMatch == newMatch && oldObj.Status.PodIP == newObj.Status.PodIP {
|
||||
continue
|
||||
}
|
||||
if oldMatch {
|
||||
if err := ps.delEntry(oldObj.ObjectMeta.UID, oldObj.Status.PodIP); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if newMatch {
|
||||
if err := ps.addEntry(newObj.ObjectMeta.UID, newObj.Status.PodIP, podComment(newObj)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -298,14 +330,19 @@ func (ns *ns) deletePod(obj *coreapi.Pod) error {
|
||||
if err := ns.ips.DelEntry(obj.ObjectMeta.UID, ns.egressDefaultAllowIPSet, obj.Status.PodIP); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return ns.podSelectors.delFromMatching(obj.ObjectMeta.UID, obj.ObjectMeta.Labels, obj.Status.PodIP)
|
||||
if err := ns.podSelectors.delFromMatchingPodSelector(obj.ObjectMeta.UID, obj.ObjectMeta.Labels, obj.Status.PodIP); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ns.namespacedPodsSelectors.delFromMatchingNamespacedPodSelector(obj.ObjectMeta.UID, obj.ObjectMeta.Labels, ns.namespace.ObjectMeta.Labels, obj.Status.PodIP); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ns *ns) addNetworkPolicy(obj interface{}) error {
|
||||
// Analyse policy, determine which rules and ipsets are required
|
||||
|
||||
uid, rules, nsSelectors, podSelectors, ipBlocks, err := ns.analyse(obj)
|
||||
uid, rules, nsSelectors, podSelectors, namespacedPodsSelectors, ipBlocks, err := ns.analyse(obj)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -317,6 +354,9 @@ func (ns *ns) addNetworkPolicy(obj interface{}) error {
|
||||
if err := ns.podSelectors.provision(uid, nil, podSelectors); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ns.namespacedPodsSelectors.provision(uid, nil, namespacedPodsSelectors); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ns.ipBlocks.provision(uid, nil, ipBlocks); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -325,11 +365,11 @@ func (ns *ns) addNetworkPolicy(obj interface{}) error {
|
||||
|
||||
func (ns *ns) updateNetworkPolicy(oldObj, newObj interface{}) error {
|
||||
// Analyse the old and the new policy so we can determine differences
|
||||
oldUID, oldRules, oldNsSelectors, oldPodSelectors, oldIPBlocks, err := ns.analyse(oldObj)
|
||||
oldUID, oldRules, oldNsSelectors, oldPodSelectors, oldNamespacedPodsSelectors, oldIPBlocks, err := ns.analyse(oldObj)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
newUID, newRules, newNsSelectors, newPodSelectors, newIPBlocks, err := ns.analyse(newObj)
|
||||
newUID, newRules, newNsSelectors, newPodSelectors, newNamespacedPodsSelectors, newIPBlocks, err := ns.analyse(newObj)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -347,6 +387,9 @@ func (ns *ns) updateNetworkPolicy(oldObj, newObj interface{}) error {
|
||||
if err := ns.podSelectors.deprovision(oldUID, oldPodSelectors, newPodSelectors); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ns.namespacedPodsSelectors.deprovision(oldUID, oldNamespacedPodsSelectors, newNamespacedPodsSelectors); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ns.ipBlocks.deprovision(oldUID, oldIPBlocks, newIPBlocks); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -356,6 +399,9 @@ func (ns *ns) updateNetworkPolicy(oldObj, newObj interface{}) error {
|
||||
if err := ns.podSelectors.provision(oldUID, oldPodSelectors, newPodSelectors); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ns.namespacedPodsSelectors.provision(oldUID, oldNamespacedPodsSelectors, newNamespacedPodsSelectors); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ns.ipBlocks.provision(oldUID, oldIPBlocks, newIPBlocks); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -364,7 +410,7 @@ func (ns *ns) updateNetworkPolicy(oldObj, newObj interface{}) error {
|
||||
|
||||
func (ns *ns) deleteNetworkPolicy(obj interface{}) error {
|
||||
// Analyse network policy to free resources
|
||||
uid, rules, nsSelectors, podSelectors, ipBlocks, err := ns.analyse(obj)
|
||||
uid, rules, nsSelectors, podSelectors, namespacedPodsSelectors, ipBlocks, err := ns.analyse(obj)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -381,6 +427,9 @@ func (ns *ns) deleteNetworkPolicy(obj interface{}) error {
|
||||
if err := ns.podSelectors.deprovision(uid, podSelectors, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ns.namespacedPodsSelectors.deprovision(uid, namespacedPodsSelectors, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ns.ipBlocks.deprovision(uid, ipBlocks, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -454,7 +503,7 @@ func (ns *ns) addNamespace(obj *coreapi.Namespace) error {
|
||||
}
|
||||
|
||||
// Add namespace ipset to matching namespace selectors
|
||||
_, _, err := ns.nsSelectors.addToMatching(obj.ObjectMeta.UID, obj.ObjectMeta.Labels, string(ns.allPods.ipsetName), namespaceComment(ns))
|
||||
err := ns.nsSelectors.addToMatchingNamespaceSelector(obj.ObjectMeta.UID, obj.ObjectMeta.Labels, string(ns.allPods.ipsetName), namespaceComment(ns))
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -464,8 +513,8 @@ func (ns *ns) updateNamespace(oldObj, newObj *coreapi.Namespace) error {
|
||||
// Re-evaluate namespace selector membership if labels have changed
|
||||
if !equals(oldObj.ObjectMeta.Labels, newObj.ObjectMeta.Labels) {
|
||||
for _, selector := range ns.nsSelectors.entries {
|
||||
oldMatch := selector.matches(oldObj.ObjectMeta.Labels)
|
||||
newMatch := selector.matches(newObj.ObjectMeta.Labels)
|
||||
oldMatch := selector.matchesNamespaceSelector(oldObj.ObjectMeta.Labels)
|
||||
newMatch := selector.matchesNamespaceSelector(newObj.ObjectMeta.Labels)
|
||||
if oldMatch == newMatch {
|
||||
continue
|
||||
}
|
||||
@@ -494,7 +543,7 @@ func (ns *ns) deleteNamespace(obj *coreapi.Namespace) error {
|
||||
}
|
||||
|
||||
// Remove namespace ipset from any matching namespace selectors
|
||||
err := ns.nsSelectors.delFromMatching(obj.ObjectMeta.UID, obj.ObjectMeta.Labels, string(ns.allPods.ipsetName))
|
||||
err := ns.nsSelectors.delFromMatchingNamespaceSelector(obj.ObjectMeta.UID, obj.ObjectMeta.Labels, string(ns.allPods.ipsetName))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -546,7 +595,7 @@ func (ns *ns) defaultAllowIPSetName(pt policyType) ipset.Name {
|
||||
func (ns *ns) analyse(obj interface{}) (
|
||||
uid types.UID,
|
||||
rules map[string]*ruleSpec,
|
||||
nsSelectors, podSelectors map[string]*selectorSpec,
|
||||
nsSelectors, podSelectors, namespacedPodsSelectors map[string]*selectorSpec,
|
||||
ipBlocks map[string]*ipBlockSpec,
|
||||
err error) {
|
||||
|
||||
@@ -562,7 +611,7 @@ func (ns *ns) analyse(obj interface{}) (
|
||||
ns.policies[uid] = obj
|
||||
|
||||
// Analyse policy, determine which rules and ipsets are required
|
||||
rules, nsSelectors, podSelectors, ipBlocks, err = ns.analysePolicy(obj.(*networkingv1.NetworkPolicy))
|
||||
rules, nsSelectors, podSelectors, namespacedPodsSelectors, ipBlocks, err = ns.analysePolicy(obj.(*networkingv1.NetworkPolicy))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
+83
-17
@@ -12,25 +12,39 @@ import (
|
||||
)
|
||||
|
||||
type selectorSpec struct {
|
||||
key string // string representation (for hash keying/equality comparison)
|
||||
selector labels.Selector // k8s Selector object (for matching)
|
||||
policyTypes []policyType // If non-empty, then selectorSpec is a target selector for given policyTypes.
|
||||
key string // string representation (for hash keying/equality comparison)
|
||||
podSelector labels.Selector // k8s Selector object (for matching pods)
|
||||
namespaceSelector labels.Selector // k8s Selector object (for matching namespaces)
|
||||
policyTypes []policyType // If non-empty, then selectorSpec is a target selector for given policyTypes.
|
||||
|
||||
ipsetType ipset.Type // type of ipset to provision
|
||||
ipsetName ipset.Name // generated ipset name
|
||||
nsName string // Namespace name
|
||||
}
|
||||
|
||||
func newSelectorSpec(json *metav1.LabelSelector, policyType []policyType, nsName string, ipsetType ipset.Type) (*selectorSpec, error) {
|
||||
selector, err := metav1.LabelSelectorAsSelector(json)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
func newSelectorSpec(podJSON *metav1.LabelSelector, namespaceJSON *metav1.LabelSelector, policyType []policyType, nsName string, ipsetType ipset.Type) (*selectorSpec, error) {
|
||||
var podSelector, namespaceSelector labels.Selector
|
||||
var err error
|
||||
var key string
|
||||
if namespaceJSON != nil {
|
||||
namespaceSelector, err = metav1.LabelSelectorAsSelector(namespaceJSON)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
key = namespaceSelector.String()
|
||||
}
|
||||
if podJSON != nil {
|
||||
podSelector, err = metav1.LabelSelectorAsSelector(podJSON)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
key = key + podSelector.String()
|
||||
}
|
||||
key := selector.String()
|
||||
return &selectorSpec{
|
||||
key: key,
|
||||
selector: selector,
|
||||
policyTypes: policyType,
|
||||
key: key,
|
||||
podSelector: podSelector,
|
||||
namespaceSelector: namespaceSelector,
|
||||
policyTypes: policyType,
|
||||
// We prefix the selector string with the namespace name when generating
|
||||
// the shortname because you can specify the same selector in multiple
|
||||
// namespaces - we need those to map to distinct ipsets
|
||||
@@ -61,8 +75,16 @@ type selector struct {
|
||||
spec *selectorSpec
|
||||
}
|
||||
|
||||
func (s *selector) matches(labelMap map[string]string) bool {
|
||||
return s.spec.selector.Matches(labels.Set(labelMap))
|
||||
func (s *selector) matchesPodSelector(podsLabelMap map[string]string) bool {
|
||||
return s.spec.podSelector.Matches(labels.Set(podsLabelMap))
|
||||
}
|
||||
|
||||
func (s *selector) matchesNamespaceSelector(namespaceLabelMap map[string]string) bool {
|
||||
return s.spec.namespaceSelector.Matches(labels.Set(namespaceLabelMap))
|
||||
}
|
||||
|
||||
func (s *selector) matchesNamespacedPodSelector(podsLabelMap, namespaceLabelMap map[string]string) bool {
|
||||
return s.spec.podSelector.Matches(labels.Set(podsLabelMap)) && s.spec.namespaceSelector.Matches(labels.Set(namespaceLabelMap))
|
||||
}
|
||||
|
||||
func (s *selector) addEntry(user types.UID, entry string, comment string) error {
|
||||
@@ -105,11 +127,11 @@ func newSelectorSet(ips ipset.Interface, onNewSelector selectorFn, onNewTargetSe
|
||||
targetSelectorsCount: make(map[string]map[policyType]int)}
|
||||
}
|
||||
|
||||
func (ss *selectorSet) addToMatching(user types.UID, labelMap map[string]string, entry string, comment string) (bool, bool, error) {
|
||||
func (ss *selectorSet) addToMatchingPodSelector(user types.UID, podLabelsMap map[string]string, entry string, comment string) (bool, bool, error) {
|
||||
foundIngress := false
|
||||
foundEgress := false
|
||||
for _, s := range ss.entries {
|
||||
if s.matches(labelMap) {
|
||||
if s.matchesPodSelector(podLabelsMap) {
|
||||
if ss.targetSelectorExist(s, policyTypeIngress) {
|
||||
foundIngress = true
|
||||
}
|
||||
@@ -124,9 +146,53 @@ func (ss *selectorSet) addToMatching(user types.UID, labelMap map[string]string,
|
||||
return foundIngress, foundEgress, nil
|
||||
}
|
||||
|
||||
func (ss *selectorSet) delFromMatching(user types.UID, labelMap map[string]string, entry string) error {
|
||||
func (ss *selectorSet) addToMatchingNamespaceSelector(user types.UID, namespaceLabelsMap map[string]string, entry string, comment string) error {
|
||||
for _, s := range ss.entries {
|
||||
if s.matches(labelMap) {
|
||||
if s.matchesNamespaceSelector(namespaceLabelsMap) {
|
||||
if err := s.addEntry(user, entry, comment); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ss *selectorSet) addToMatchingNamespacedPodSelector(user types.UID, podLabelsMap map[string]string, namespaceLabelsMap map[string]string, entry string, comment string) error {
|
||||
for _, s := range ss.entries {
|
||||
if s.matchesNamespacedPodSelector(podLabelsMap, namespaceLabelsMap) {
|
||||
if err := s.addEntry(user, entry, comment); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ss *selectorSet) delFromMatchingPodSelector(user types.UID, podLabelsMap map[string]string, entry string) error {
|
||||
for _, s := range ss.entries {
|
||||
if s.matchesPodSelector(podLabelsMap) {
|
||||
if err := s.delEntry(user, entry); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ss *selectorSet) delFromMatchingNamespaceSelector(user types.UID, namespaceLabelsMap map[string]string, entry string) error {
|
||||
for _, s := range ss.entries {
|
||||
if s.matchesNamespaceSelector(namespaceLabelsMap) {
|
||||
if err := s.delEntry(user, entry); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ss *selectorSet) delFromMatchingNamespacedPodSelector(user types.UID, podLabelsMap map[string]string, namespaceLabelsMap map[string]string, entry string) error {
|
||||
for _, s := range ss.entries {
|
||||
if s.matchesNamespacedPodSelector(podLabelsMap, namespaceLabelsMap) {
|
||||
if err := s.delEntry(user, entry); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/ipam"
|
||||
"github.com/containernetworking/cni/pkg/skel"
|
||||
@@ -206,7 +207,13 @@ func (c *CNIPlugin) CmdDel(args *skel.CmdArgs) error {
|
||||
err = ipam.ExecDel(conf.IPAM.Type, args.StdinData)
|
||||
}
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), fmt.Sprintf("Delete: no addresses for %s", args.ContainerID)) {
|
||||
// ignore the error in the case where there are no IP addresses associated with container
|
||||
fmt.Fprintln(os.Stderr, "weave-cni:", fmt.Sprintf("Delete: no addresses for %s", args.ContainerID))
|
||||
return nil
|
||||
}
|
||||
logOnStderr(fmt.Errorf("unable to release IP address: %s", err))
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -39,9 +39,10 @@ type driver struct {
|
||||
// used only by plugin-v2
|
||||
forceMulticast bool
|
||||
networks map[string]network
|
||||
procPath string
|
||||
}
|
||||
|
||||
func New(client *docker.Client, weave *weaveapi.Client, name, scope string, dns, isPluginV2, forceMulticast bool) (skel.Driver, error) {
|
||||
func New(client *docker.Client, weave *weaveapi.Client, name, scope string, dns, isPluginV2, forceMulticast bool, procPath string) (skel.Driver, error) {
|
||||
driver := &driver{
|
||||
name: name,
|
||||
scope: scope,
|
||||
@@ -51,6 +52,7 @@ func New(client *docker.Client, weave *weaveapi.Client, name, scope string, dns,
|
||||
// make sure that it's used only by plugin-v2
|
||||
forceMulticast: isPluginV2 && forceMulticast,
|
||||
networks: make(map[string]network),
|
||||
procPath: procPath,
|
||||
}
|
||||
|
||||
// Do not start watcher in the case of plugin v2, which prevents us from
|
||||
@@ -134,7 +136,7 @@ func (driver *driver) CreateEndpoint(create *api.CreateEndpointRequest) (*api.Cr
|
||||
|
||||
// create veths. note we assume endpoint IDs are unique in the first 9 chars
|
||||
name, peerName := vethPair(create.EndpointID)
|
||||
if _, err := weavenet.CreateAndAttachVeth(name, peerName, weavenet.WeaveBridgeName, 0, false, true, nil); err != nil {
|
||||
if _, err := weavenet.CreateAndAttachVeth(driver.procPath, name, peerName, weavenet.WeaveBridgeName, 0, false, true, nil); err != nil {
|
||||
return nil, driver.error("JoinEndpoint", "%s", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -43,14 +43,9 @@ func (w *watcher) ContainerStarted(id string) {
|
||||
w.driver.warn("ContainerStarted", "unable to register %s with weaveDNS: %s", id, err)
|
||||
}
|
||||
}
|
||||
rootDir := "/"
|
||||
if w.driver.isPluginV2 {
|
||||
// We bind mount host's /proc to /host/proc for plugin-v2
|
||||
rootDir = "/host"
|
||||
}
|
||||
netNSPath := weavenet.NSPathByPidWithRoot(rootDir, info.State.Pid)
|
||||
netNSPath := weavenet.NSPathByPidWithProc(w.driver.procPath, info.State.Pid)
|
||||
if err := weavenet.WithNetNSByPath(netNSPath, func() error {
|
||||
return weavenet.ConfigureARP(weavenet.VethName, rootDir)
|
||||
return weavenet.ConfigureARP(weavenet.VethName, w.driver.procPath)
|
||||
}); err != nil {
|
||||
w.driver.warn("ContainerStarted", "unable to configure interfaces: %s", err)
|
||||
}
|
||||
|
||||
+5
-4
@@ -32,6 +32,7 @@ type Config struct {
|
||||
EnableV2Multicast bool
|
||||
DNS bool
|
||||
DefaultSubnet string
|
||||
ProcPath string // path to reach host /proc filesystem
|
||||
}
|
||||
|
||||
type Plugin struct {
|
||||
@@ -62,7 +63,7 @@ func (plugin *Plugin) run(dockerClient *docker.Client, weave *weaveapi.Client, r
|
||||
endChan := make(chan error, 1)
|
||||
|
||||
if plugin.Socket != "" {
|
||||
globalListener, err := listenAndServe(dockerClient, weave, plugin.Socket, endChan, "global", false, plugin.DNS, plugin.EnableV2, plugin.EnableV2Multicast)
|
||||
globalListener, err := listenAndServe(dockerClient, weave, plugin.Socket, endChan, "global", false, plugin.DNS, plugin.EnableV2, plugin.EnableV2Multicast, plugin.ProcPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -70,7 +71,7 @@ func (plugin *Plugin) run(dockerClient *docker.Client, weave *weaveapi.Client, r
|
||||
defer globalListener.Close()
|
||||
}
|
||||
if plugin.MeshSocket != "" {
|
||||
meshListener, err := listenAndServe(dockerClient, weave, plugin.MeshSocket, endChan, "local", true, plugin.DNS, plugin.EnableV2, plugin.EnableV2Multicast)
|
||||
meshListener, err := listenAndServe(dockerClient, weave, plugin.MeshSocket, endChan, "local", true, plugin.DNS, plugin.EnableV2, plugin.EnableV2Multicast, plugin.ProcPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -87,7 +88,7 @@ func (plugin *Plugin) run(dockerClient *docker.Client, weave *weaveapi.Client, r
|
||||
return <-endChan
|
||||
}
|
||||
|
||||
func listenAndServe(dockerClient *docker.Client, weave *weaveapi.Client, address string, endChan chan<- error, scope string, withIpam, dns bool, isPluginV2, forceMulticast bool) (net.Listener, error) {
|
||||
func listenAndServe(dockerClient *docker.Client, weave *weaveapi.Client, address string, endChan chan<- error, scope string, withIpam, dns bool, isPluginV2, forceMulticast bool, procPath string) (net.Listener, error) {
|
||||
var name string
|
||||
if isPluginV2 {
|
||||
name = pluginV2Name
|
||||
@@ -95,7 +96,7 @@ func listenAndServe(dockerClient *docker.Client, weave *weaveapi.Client, address
|
||||
name = pluginNameFromAddress(address)
|
||||
}
|
||||
|
||||
d, err := netplugin.New(dockerClient, weave, name, scope, dns, isPluginV2, forceMulticast)
|
||||
d, err := netplugin.New(dockerClient, weave, name, scope, dns, isPluginV2, forceMulticast, procPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -96,33 +96,33 @@ func (cml *configMapAnnotations) GetAnnotation(key string) (string, bool) {
|
||||
}
|
||||
|
||||
func (cml *configMapAnnotations) UpdateAnnotation(key, value string) (err error) {
|
||||
if cml.cm == nil {
|
||||
if cml.cm == nil || cml.cm.Annotations == nil {
|
||||
return errors.New("endpoint not initialized, call Init first")
|
||||
}
|
||||
// speculatively change the state, then replace with whatever comes back
|
||||
// from Update(), which will be the latest on the server whatever happened
|
||||
// from Update(), which will be the latest on the server, or nil if error
|
||||
cml.cm.Annotations[cleanKey(key)] = value
|
||||
cml.cm, err = cml.Client.ConfigMaps(cml.Namespace).Update(cml.cm)
|
||||
return err
|
||||
}
|
||||
|
||||
func (cml *configMapAnnotations) RemoveAnnotation(key string) (err error) {
|
||||
if cml.cm == nil {
|
||||
if cml.cm == nil || cml.cm.Annotations == nil {
|
||||
return errors.New("endpoint not initialized, call Init first")
|
||||
}
|
||||
// speculatively change the state, then replace with whatever comes back
|
||||
// from Update(), which will be the latest on the server whatever happened
|
||||
// from Update(), which will be the latest on the server, or nil if error
|
||||
delete(cml.cm.Annotations, cleanKey(key))
|
||||
cml.cm, err = cml.Client.ConfigMaps(cml.Namespace).Update(cml.cm)
|
||||
return err
|
||||
}
|
||||
|
||||
func (cml *configMapAnnotations) RemoveAnnotationsWithValue(valueToRemove string) (err error) {
|
||||
if cml.cm == nil {
|
||||
if cml.cm == nil || cml.cm.Annotations == nil {
|
||||
return errors.New("endpoint not initialized, call Init first")
|
||||
}
|
||||
// speculatively change the state, then replace with whatever comes back
|
||||
// from Update(), which will be the latest on the server whatever happened
|
||||
// from Update(), which will be the latest on the server, or nil if error
|
||||
for key, value := range cml.cm.Annotations {
|
||||
if value == valueToRemove {
|
||||
delete(cml.cm.Annotations, key) // don't need to clean this key as it came from the map
|
||||
|
||||
+82
-24
@@ -15,6 +15,8 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/vishvananda/netlink"
|
||||
"golang.org/x/sys/unix"
|
||||
api "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
@@ -54,6 +56,10 @@ func getKubePeers(c kubernetes.Interface, includeWithNoIPAddr bool) ([]nodeInfo,
|
||||
|
||||
// Fallback for cases where a Node has an ExternalIP but no InternalIP
|
||||
if internalIP != "" {
|
||||
// exclude self from the list of peers this node will peer with
|
||||
if isLocalNodeIP(internalIP) {
|
||||
continue
|
||||
}
|
||||
addresses = append(addresses, nodeInfo{name: peer.Name, addr: internalIP})
|
||||
} else if externalIP != "" {
|
||||
addresses = append(addresses, nodeInfo{name: peer.Name, addr: externalIP})
|
||||
@@ -64,6 +70,20 @@ func getKubePeers(c kubernetes.Interface, includeWithNoIPAddr bool) ([]nodeInfo,
|
||||
return addresses, nil
|
||||
}
|
||||
|
||||
// returns true if given IP matches with one of the local IP's
|
||||
func isLocalNodeIP(ip string) bool {
|
||||
addrs, err := netlink.AddrList(nil, unix.AF_INET)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
for _, addr := range addrs {
|
||||
if addr.Peer.IP.String() == ip {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// (minimal, incomplete) interface so weaver can be mocked for testing.
|
||||
type weaveClient interface {
|
||||
RmPeer(peerName string) (string, error)
|
||||
@@ -74,11 +94,8 @@ type weaveClient interface {
|
||||
func reclaimRemovedPeers(kube kubernetes.Interface, cml *configMapAnnotations, myPeerName, myNodeName string) error {
|
||||
weave := weaveapi.NewClient(os.Getenv("WEAVE_HTTP_ADDR"), common.Log)
|
||||
for loopsWhenNothingChanged := 0; loopsWhenNothingChanged < 3; loopsWhenNothingChanged++ {
|
||||
if err := cml.Init(); err != nil {
|
||||
return err
|
||||
}
|
||||
// 1. Compare peers stored in the peerList against all peers reported by k8s now.
|
||||
storedPeerList, err := cml.GetPeerList()
|
||||
storedPeerList, err := getRefreshedPeerList(cml)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -92,7 +109,9 @@ func reclaimRemovedPeers(kube kubernetes.Interface, cml *configMapAnnotations, m
|
||||
}
|
||||
peerMap := make(map[string]peerInfo, len(storedPeerList.Peers))
|
||||
for _, peer := range storedPeerList.Peers {
|
||||
peerMap[peer.PeerName] = peer
|
||||
if peer.PeerName != myPeerName {
|
||||
peerMap[peer.PeerName] = peer
|
||||
}
|
||||
}
|
||||
// remove entries from the peer map that are current nodes
|
||||
for key, peer := range peerMap {
|
||||
@@ -115,7 +134,7 @@ func reclaimRemovedPeers(kube kubernetes.Interface, cml *configMapAnnotations, m
|
||||
common.Log.Warnln("[kube-peers] not removing myself", peer)
|
||||
continue
|
||||
}
|
||||
changed, err := reclaimPeer(weave, cml, storedPeerList, peer.PeerName, myPeerName)
|
||||
changed, err := reclaimPeer(weave, cml, peer.PeerName, myPeerName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -135,11 +154,16 @@ func reclaimRemovedPeers(kube kubernetes.Interface, cml *configMapAnnotations, m
|
||||
// actions the reclaim.
|
||||
// Return a bool to show whether we attempted to change anything,
|
||||
// and an error if something went wrong.
|
||||
func reclaimPeer(weave weaveClient, cml *configMapAnnotations, storedPeerList *peerList, peerName string, myPeerName string) (changed bool, err error) {
|
||||
func reclaimPeer(weave weaveClient, cml *configMapAnnotations, peerName string, myPeerName string) (changed bool, err error) {
|
||||
common.Log.Debugln("[kube-peers] Preparing to remove disappeared peer", peerName)
|
||||
okToRemove := false
|
||||
nonExistentPeer := false
|
||||
|
||||
// Re-read status from Kubernetes; speculative updates may leave it un-set
|
||||
if err := cml.Init(); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// 3. Check if there is an existing annotation with key X
|
||||
existingAnnotation, found := cml.GetAnnotation(KubePeersPrefix + peerName)
|
||||
if found {
|
||||
@@ -148,6 +172,10 @@ func reclaimPeer(weave weaveClient, cml *configMapAnnotations, storedPeerList *p
|
||||
if existingAnnotation == myPeerName {
|
||||
okToRemove = true
|
||||
} else {
|
||||
storedPeerList, err := cml.GetPeerList()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
// handle an edge case where peer claimed to own the action to reclaim but no longer
|
||||
// exists hence lock persists foever
|
||||
if !storedPeerList.contains(existingAnnotation) {
|
||||
@@ -169,10 +197,15 @@ func reclaimPeer(weave weaveClient, cml *configMapAnnotations, storedPeerList *p
|
||||
return false, nil
|
||||
}
|
||||
// 6. If step 4 or 5 succeeded, rmpeer X
|
||||
result, err := weave.RmPeer(peerName)
|
||||
common.Log.Infof("[kube-peers] rmpeer of %s: %s", peerName, result)
|
||||
if err != nil {
|
||||
return false, err
|
||||
// we will try once more to see if the peerName has been removed from the annotation
|
||||
// by another weave pod
|
||||
storedPeerList, err := getRefreshedPeerList(cml)
|
||||
if storedPeerList.contains(peerName) {
|
||||
result, err := weave.RmPeer(peerName)
|
||||
common.Log.Infof("[kube-peers] rmpeer of %s: %s", peerName, result)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
err = cml.LoopUpdate(func() error {
|
||||
// 7aa. Remove any annotations Z* that have contents X
|
||||
@@ -184,9 +217,13 @@ func reclaimPeer(weave weaveClient, cml *configMapAnnotations, storedPeerList *p
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
storedPeerList.remove(peerName)
|
||||
if err := cml.UpdatePeerList(*storedPeerList); err != nil {
|
||||
return err
|
||||
if storedPeerList.contains(peerName) {
|
||||
storedPeerList.remove(peerName)
|
||||
if err := cml.UpdatePeerList(*storedPeerList); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
common.Log.Infof("[kube-peers] annotation was removed already for %s", peerName)
|
||||
}
|
||||
// 7b. Remove annotation with key X
|
||||
return cml.RemoveAnnotation(KubePeersPrefix + peerName)
|
||||
@@ -230,6 +267,13 @@ func registerForNodeUpdates(client *kubernetes.Clientset, stopCh <-chan struct{}
|
||||
common.Log.Debugln("registering for updates for node delete events")
|
||||
nodeInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
DeleteFunc: func(obj interface{}) {
|
||||
var name string
|
||||
if apiObj, ok := obj.(api.Object); ok {
|
||||
name = apiObj.GetName()
|
||||
} else {
|
||||
name = fmt.Sprintf("%#v", obj)
|
||||
}
|
||||
common.Log.Debugln("Delete event for", name)
|
||||
// add random delay to avoid all nodes acting on node delete event at the same
|
||||
// time leading to contention to use `weave-net` configmap
|
||||
r := rand.Intn(5000)
|
||||
@@ -250,6 +294,18 @@ func registerForNodeUpdates(client *kubernetes.Clientset, stopCh <-chan struct{}
|
||||
informerFactory.Start(stopCh)
|
||||
}
|
||||
|
||||
// getRefreshedPeerList will fetch the latest peer list from the config map annotation
|
||||
func getRefreshedPeerList(cml *configMapAnnotations) (*peerList, error) {
|
||||
if err := cml.Init(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
storedPeerList, err := cml.GetPeerList()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return storedPeerList, nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
var (
|
||||
justReclaim bool
|
||||
@@ -312,6 +368,18 @@ func main() {
|
||||
}
|
||||
return
|
||||
}
|
||||
if runReclaimDaemon {
|
||||
// Handle SIGINT and SIGTERM
|
||||
ch := make(chan os.Signal)
|
||||
signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
|
||||
stopCh := make(chan struct{})
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
registerForNodeUpdates(c, stopCh, nodeName, peerName)
|
||||
<-ch
|
||||
close(stopCh)
|
||||
return
|
||||
}
|
||||
|
||||
peers, err := getKubePeers(c, false)
|
||||
if err != nil {
|
||||
common.Log.Fatalf("[kube-peers] Could not get peers: %v", err)
|
||||
@@ -319,14 +387,4 @@ func main() {
|
||||
for _, node := range peers {
|
||||
fmt.Println(node.addr)
|
||||
}
|
||||
|
||||
if runReclaimDaemon {
|
||||
// Handle SIGINT and SIGTERM
|
||||
ch := make(chan os.Signal)
|
||||
signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
|
||||
stopCh := make(chan struct{})
|
||||
registerForNodeUpdates(c, stopCh, nodeName, peerName)
|
||||
<-ch
|
||||
close(stopCh)
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"math/rand"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
@@ -71,6 +72,7 @@ func doConcurrentIterations(iterations, concurrency int, f func(int)) {
|
||||
}
|
||||
|
||||
func TestPeerListFuzz(t *testing.T) {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
const (
|
||||
testIters = 1000
|
||||
maxNodes = 100
|
||||
@@ -137,9 +139,10 @@ func TestPeerListFuzz(t *testing.T) {
|
||||
found := storedPeerList.contains(peerName(i))
|
||||
require.True(t, found, "peer %d not found in stored list", i)
|
||||
|
||||
_, err = reclaimPeer(mockWeave{}, cml, storedPeerList, peerName(i), fmt.Sprintf("deleter-%d", i))
|
||||
_, err = reclaimPeer(mockWeave{}, cml, peerName(i), fmt.Sprintf("deleter-%d", i))
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, cml.Init())
|
||||
storedPeerList, err = cml.GetPeerList()
|
||||
require.NoError(t, err)
|
||||
stateLock.Lock()
|
||||
|
||||
@@ -6,6 +6,34 @@ modprobe_safe() {
|
||||
modprobe $1 || echo "Ignore the error if \"$1\" is built-in in the kernel" >&2
|
||||
}
|
||||
|
||||
# Setup iptables backend to be legacy or nftable
|
||||
setup_iptables_backend() {
|
||||
if [ -n "${IPTABLES_BACKEND}" ]; then
|
||||
mode=$IPTABLES_BACKEND
|
||||
else
|
||||
# auto-detect if iptables backend mode to use if not specified explicitly
|
||||
num_legacy_lines=$( (iptables-legacy-save || true) 2>/dev/null | grep '^-' | wc -l)
|
||||
num_nft_lines=$( (iptables-nft-save || true) 2>/dev/null | grep '^-' | wc -l)
|
||||
if [ "${num_legacy_lines}" -ge 10 ]; then
|
||||
mode="legacy"
|
||||
else
|
||||
if [ "${num_legacy_lines}" -ge "${num_nft_lines}" ]; then
|
||||
mode="legacy"
|
||||
else
|
||||
mode="nft"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if [ $mode = "nft" ]; then
|
||||
rm /sbin/iptables
|
||||
rm /sbin/iptables-save
|
||||
rm /sbin/iptables-restore
|
||||
ln -s /sbin/iptables-nft /sbin/iptables
|
||||
ln -s /sbin/iptables-nft-save /sbin/iptables-save
|
||||
ln -s /sbin/iptables-nft-restore /sbin/iptables-restore
|
||||
fi
|
||||
}
|
||||
|
||||
# Check whether xt_set actually exists
|
||||
xt_set_exists() {
|
||||
# Clean everything up in advance, in case there's leftovers
|
||||
@@ -24,12 +52,14 @@ xt_set_exists() {
|
||||
[ -z "$NOT_EXIST" ] || (echo "\"xt_set\" does not exist" >&2 && return 1)
|
||||
}
|
||||
|
||||
setup_iptables_backend
|
||||
|
||||
# Default if not supplied - same as weave net default
|
||||
IPALLOC_RANGE=${IPALLOC_RANGE:-10.32.0.0/12}
|
||||
HTTP_ADDR=${WEAVE_HTTP_ADDR:-127.0.0.1:6784}
|
||||
METRICS_ADDR=${WEAVE_METRICS_ADDR:-0.0.0.0:6782}
|
||||
HOST_ROOT=${HOST_ROOT:-/host}
|
||||
CONN_LIMIT=${CONN_LIMIT:-100}
|
||||
CONN_LIMIT=${CONN_LIMIT:-200}
|
||||
DB_PREFIX=${DB_PREFIX:-/weavedb/weave-net}
|
||||
|
||||
# Check if the IP range overlaps anything existing on the host
|
||||
@@ -85,7 +115,7 @@ router_bridge_opts() {
|
||||
}
|
||||
|
||||
if [ -z "$KUBE_PEERS" ]; then
|
||||
if ! KUBE_PEERS=$(/home/weave/kube-utils) || [ -z "$KUBE_PEERS" ]; then
|
||||
if ! KUBE_PEERS=$(/home/weave/kube-utils); then
|
||||
echo Failed to get peers >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -0,0 +1,215 @@
|
||||
apiVersion: v1
|
||||
kind: List
|
||||
items:
|
||||
- apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: weave-net
|
||||
labels:
|
||||
name: weave-net
|
||||
namespace: kube-system
|
||||
- apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: weave-net
|
||||
labels:
|
||||
name: weave-net
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ''
|
||||
resources:
|
||||
- pods
|
||||
- namespaces
|
||||
- nodes
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- extensions
|
||||
resources:
|
||||
- networkpolicies
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- 'networking.k8s.io'
|
||||
resources:
|
||||
- networkpolicies
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- ''
|
||||
resources:
|
||||
- nodes/status
|
||||
verbs:
|
||||
- patch
|
||||
- update
|
||||
- apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: weave-net
|
||||
labels:
|
||||
name: weave-net
|
||||
roleRef:
|
||||
kind: ClusterRole
|
||||
name: weave-net
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: weave-net
|
||||
namespace: kube-system
|
||||
- apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: weave-net
|
||||
namespace: kube-system
|
||||
labels:
|
||||
name: weave-net
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ''
|
||||
resources:
|
||||
- configmaps
|
||||
resourceNames:
|
||||
- weave-net
|
||||
verbs:
|
||||
- get
|
||||
- update
|
||||
- apiGroups:
|
||||
- ''
|
||||
resources:
|
||||
- configmaps
|
||||
verbs:
|
||||
- create
|
||||
- apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: weave-net
|
||||
namespace: kube-system
|
||||
labels:
|
||||
name: weave-net
|
||||
roleRef:
|
||||
kind: Role
|
||||
name: weave-net
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: weave-net
|
||||
namespace: kube-system
|
||||
- apiVersion: apps/v1
|
||||
kind: DaemonSet
|
||||
metadata:
|
||||
name: weave-net
|
||||
labels:
|
||||
name: weave-net
|
||||
namespace: kube-system
|
||||
spec:
|
||||
# Wait 5 seconds to let pod connect before rolling next pod
|
||||
selector:
|
||||
matchLabels:
|
||||
name: weave-net
|
||||
minReadySeconds: 5
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
name: weave-net
|
||||
spec:
|
||||
containers:
|
||||
- name: weave
|
||||
command:
|
||||
- /home/weave/launch.sh
|
||||
env:
|
||||
- name: HOSTNAME
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
apiVersion: v1
|
||||
fieldPath: spec.nodeName
|
||||
image: 'weaveworks/weave-kube:latest'
|
||||
imagePullPolicy: Always
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
host: 127.0.0.1
|
||||
path: /status
|
||||
port: 6784
|
||||
resources:
|
||||
requests:
|
||||
cpu: 50m
|
||||
securityContext:
|
||||
privileged: true
|
||||
volumeMounts:
|
||||
- name: weavedb
|
||||
mountPath: /weavedb
|
||||
- name: cni-bin
|
||||
mountPath: /host/opt
|
||||
- name: cni-bin2
|
||||
mountPath: /host/home
|
||||
- name: cni-conf
|
||||
mountPath: /host/etc
|
||||
- name: dbus
|
||||
mountPath: /host/var/lib/dbus
|
||||
- name: lib-modules
|
||||
mountPath: /lib/modules
|
||||
- name: xtables-lock
|
||||
mountPath: /run/xtables.lock
|
||||
readOnly: false
|
||||
- name: weave-npc
|
||||
env:
|
||||
- name: HOSTNAME
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
apiVersion: v1
|
||||
fieldPath: spec.nodeName
|
||||
image: 'weaveworks/weave-npc:latest'
|
||||
imagePullPolicy: Always
|
||||
#npc-args
|
||||
resources:
|
||||
requests:
|
||||
cpu: 50m
|
||||
securityContext:
|
||||
privileged: true
|
||||
volumeMounts:
|
||||
- name: xtables-lock
|
||||
mountPath: /run/xtables.lock
|
||||
readOnly: false
|
||||
hostNetwork: true
|
||||
dnsPolicy: ClusterFirstWithHostNet
|
||||
hostPID: true
|
||||
restartPolicy: Always
|
||||
securityContext:
|
||||
seLinuxOptions: {}
|
||||
serviceAccountName: weave-net
|
||||
tolerations:
|
||||
- effect: NoSchedule
|
||||
operator: Exists
|
||||
- effect: NoExecute
|
||||
operator: Exists
|
||||
volumes:
|
||||
- name: weavedb
|
||||
hostPath:
|
||||
path: /var/lib/weave
|
||||
- name: cni-bin
|
||||
hostPath:
|
||||
path: /opt
|
||||
- name: cni-bin2
|
||||
hostPath:
|
||||
path: /home
|
||||
- name: cni-conf
|
||||
hostPath:
|
||||
path: /etc
|
||||
- name: dbus
|
||||
hostPath:
|
||||
path: /var/lib/dbus
|
||||
- name: lib-modules
|
||||
hostPath:
|
||||
path: /lib/modules
|
||||
- name: xtables-lock
|
||||
hostPath:
|
||||
path: /run/xtables.lock
|
||||
type: FileOrCreate
|
||||
priorityClassName: system-node-critical
|
||||
updateStrategy:
|
||||
type: RollingUpdate
|
||||
@@ -117,7 +117,7 @@ items:
|
||||
port: 6784
|
||||
resources:
|
||||
requests:
|
||||
cpu: 10m
|
||||
cpu: 50m
|
||||
securityContext:
|
||||
privileged: true
|
||||
volumeMounts:
|
||||
@@ -144,7 +144,7 @@ items:
|
||||
imagePullPolicy: Always
|
||||
resources:
|
||||
requests:
|
||||
cpu: 10m
|
||||
cpu: 50m
|
||||
securityContext:
|
||||
privileged: true
|
||||
hostNetwork: true
|
||||
@@ -156,6 +156,8 @@ items:
|
||||
tolerations:
|
||||
- effect: NoSchedule
|
||||
operator: Exists
|
||||
- effect: NoExecute
|
||||
operator: Exists
|
||||
volumes:
|
||||
- name: weavedb
|
||||
hostPath:
|
||||
|
||||
@@ -126,7 +126,7 @@ items:
|
||||
port: 6784
|
||||
resources:
|
||||
requests:
|
||||
cpu: 10m
|
||||
cpu: 50m
|
||||
securityContext:
|
||||
privileged: true
|
||||
volumeMounts:
|
||||
@@ -156,7 +156,7 @@ items:
|
||||
imagePullPolicy: Always
|
||||
resources:
|
||||
requests:
|
||||
cpu: 10m
|
||||
cpu: 50m
|
||||
securityContext:
|
||||
privileged: true
|
||||
volumeMounts:
|
||||
@@ -172,6 +172,8 @@ items:
|
||||
tolerations:
|
||||
- effect: NoSchedule
|
||||
operator: Exists
|
||||
- effect: NoExecute
|
||||
operator: Exists
|
||||
volumes:
|
||||
- name: weavedb
|
||||
hostPath:
|
||||
|
||||
@@ -8,7 +8,7 @@ items:
|
||||
labels:
|
||||
name: weave-net
|
||||
namespace: kube-system
|
||||
- apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||
- apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: weave-net
|
||||
@@ -48,7 +48,7 @@ items:
|
||||
verbs:
|
||||
- patch
|
||||
- update
|
||||
- apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||
- apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: weave-net
|
||||
@@ -62,7 +62,7 @@ items:
|
||||
- kind: ServiceAccount
|
||||
name: weave-net
|
||||
namespace: kube-system
|
||||
- apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||
- apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: weave-net
|
||||
@@ -85,7 +85,7 @@ items:
|
||||
- configmaps
|
||||
verbs:
|
||||
- create
|
||||
- apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||
- apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: weave-net
|
||||
@@ -134,7 +134,7 @@ items:
|
||||
port: 6784
|
||||
resources:
|
||||
requests:
|
||||
cpu: 10m
|
||||
cpu: 50m
|
||||
securityContext:
|
||||
privileged: true
|
||||
volumeMounts:
|
||||
@@ -165,7 +165,7 @@ items:
|
||||
#npc-args
|
||||
resources:
|
||||
requests:
|
||||
cpu: 10m
|
||||
cpu: 50m
|
||||
securityContext:
|
||||
privileged: true
|
||||
volumeMounts:
|
||||
@@ -181,6 +181,8 @@ items:
|
||||
tolerations:
|
||||
- effect: NoSchedule
|
||||
operator: Exists
|
||||
- effect: NoExecute
|
||||
operator: Exists
|
||||
volumes:
|
||||
- name: weavedb
|
||||
hostPath:
|
||||
|
||||
@@ -0,0 +1,214 @@
|
||||
apiVersion: v1
|
||||
kind: List
|
||||
items:
|
||||
- apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: weave-net
|
||||
labels:
|
||||
name: weave-net
|
||||
namespace: kube-system
|
||||
- apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: weave-net
|
||||
labels:
|
||||
name: weave-net
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ''
|
||||
resources:
|
||||
- pods
|
||||
- namespaces
|
||||
- nodes
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- extensions
|
||||
resources:
|
||||
- networkpolicies
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- 'networking.k8s.io'
|
||||
resources:
|
||||
- networkpolicies
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- ''
|
||||
resources:
|
||||
- nodes/status
|
||||
verbs:
|
||||
- patch
|
||||
- update
|
||||
- apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: weave-net
|
||||
labels:
|
||||
name: weave-net
|
||||
roleRef:
|
||||
kind: ClusterRole
|
||||
name: weave-net
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: weave-net
|
||||
namespace: kube-system
|
||||
- apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: weave-net
|
||||
namespace: kube-system
|
||||
labels:
|
||||
name: weave-net
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ''
|
||||
resources:
|
||||
- configmaps
|
||||
resourceNames:
|
||||
- weave-net
|
||||
verbs:
|
||||
- get
|
||||
- update
|
||||
- apiGroups:
|
||||
- ''
|
||||
resources:
|
||||
- configmaps
|
||||
verbs:
|
||||
- create
|
||||
- apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: weave-net
|
||||
namespace: kube-system
|
||||
labels:
|
||||
name: weave-net
|
||||
roleRef:
|
||||
kind: Role
|
||||
name: weave-net
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: weave-net
|
||||
namespace: kube-system
|
||||
- apiVersion: apps/v1
|
||||
kind: DaemonSet
|
||||
metadata:
|
||||
name: weave-net
|
||||
labels:
|
||||
name: weave-net
|
||||
namespace: kube-system
|
||||
spec:
|
||||
# Wait 5 seconds to let pod connect before rolling next pod
|
||||
selector:
|
||||
matchLabels:
|
||||
name: weave-net
|
||||
minReadySeconds: 5
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
name: weave-net
|
||||
spec:
|
||||
containers:
|
||||
- name: weave
|
||||
command:
|
||||
- /home/weave/launch.sh
|
||||
env:
|
||||
- name: HOSTNAME
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
apiVersion: v1
|
||||
fieldPath: spec.nodeName
|
||||
image: 'weaveworks/weave-kube:latest'
|
||||
imagePullPolicy: Always
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
host: 127.0.0.1
|
||||
path: /status
|
||||
port: 6784
|
||||
resources:
|
||||
requests:
|
||||
cpu: 50m
|
||||
securityContext:
|
||||
privileged: true
|
||||
volumeMounts:
|
||||
- name: weavedb
|
||||
mountPath: /weavedb
|
||||
- name: cni-bin
|
||||
mountPath: /host/opt
|
||||
- name: cni-bin2
|
||||
mountPath: /host/home
|
||||
- name: cni-conf
|
||||
mountPath: /host/etc
|
||||
- name: dbus
|
||||
mountPath: /host/var/lib/dbus
|
||||
- name: lib-modules
|
||||
mountPath: /lib/modules
|
||||
- name: xtables-lock
|
||||
mountPath: /run/xtables.lock
|
||||
readOnly: false
|
||||
- name: weave-npc
|
||||
env:
|
||||
- name: HOSTNAME
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
apiVersion: v1
|
||||
fieldPath: spec.nodeName
|
||||
image: 'weaveworks/weave-npc:latest'
|
||||
imagePullPolicy: Always
|
||||
#npc-args
|
||||
resources:
|
||||
requests:
|
||||
cpu: 50m
|
||||
securityContext:
|
||||
privileged: true
|
||||
volumeMounts:
|
||||
- name: xtables-lock
|
||||
mountPath: /run/xtables.lock
|
||||
readOnly: false
|
||||
hostNetwork: true
|
||||
dnsPolicy: ClusterFirstWithHostNet
|
||||
hostPID: true
|
||||
restartPolicy: Always
|
||||
securityContext:
|
||||
seLinuxOptions: {}
|
||||
serviceAccountName: weave-net
|
||||
tolerations:
|
||||
- effect: NoSchedule
|
||||
operator: Exists
|
||||
- effect: NoExecute
|
||||
operator: Exists
|
||||
volumes:
|
||||
- name: weavedb
|
||||
hostPath:
|
||||
path: /var/lib/weave
|
||||
- name: cni-bin
|
||||
hostPath:
|
||||
path: /opt
|
||||
- name: cni-bin2
|
||||
hostPath:
|
||||
path: /home
|
||||
- name: cni-conf
|
||||
hostPath:
|
||||
path: /etc
|
||||
- name: dbus
|
||||
hostPath:
|
||||
path: /var/lib/dbus
|
||||
- name: lib-modules
|
||||
hostPath:
|
||||
path: /lib/modules
|
||||
- name: xtables-lock
|
||||
hostPath:
|
||||
path: /run/xtables.lock
|
||||
type: FileOrCreate
|
||||
updateStrategy:
|
||||
type: RollingUpdate
|
||||
@@ -1,100 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: List
|
||||
items:
|
||||
- apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: weave-net
|
||||
labels:
|
||||
name: weave-net
|
||||
namespace: kube-system
|
||||
- apiVersion: extensions/v1beta1
|
||||
kind: DaemonSet
|
||||
metadata:
|
||||
name: weave-net
|
||||
labels:
|
||||
name: weave-net
|
||||
namespace: kube-system
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
scheduler.alpha.kubernetes.io/tolerations: >-
|
||||
[{"key":"dedicated","operator":"Equal","value":"master","effect":"NoSchedule"}]
|
||||
labels:
|
||||
name: weave-net
|
||||
spec:
|
||||
containers:
|
||||
- name: weave
|
||||
command:
|
||||
- /home/weave/launch.sh
|
||||
env:
|
||||
- name: HOSTNAME
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
apiVersion: v1
|
||||
fieldPath: spec.nodeName
|
||||
image: 'weaveworks/weave-kube:latest'
|
||||
imagePullPolicy: Always
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
host: 127.0.0.1
|
||||
path: /status
|
||||
port: 6784
|
||||
resources:
|
||||
requests:
|
||||
cpu: 10m
|
||||
securityContext:
|
||||
privileged: true
|
||||
volumeMounts:
|
||||
- name: weavedb
|
||||
mountPath: /weavedb
|
||||
- name: cni-bin
|
||||
mountPath: /host/opt
|
||||
- name: cni-bin2
|
||||
mountPath: /host/home
|
||||
- name: cni-conf
|
||||
mountPath: /host/etc
|
||||
- name: dbus
|
||||
mountPath: /host/var/lib/dbus
|
||||
- name: lib-modules
|
||||
mountPath: /lib/modules
|
||||
- name: weave-npc
|
||||
env:
|
||||
- name: HOSTNAME
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
apiVersion: v1
|
||||
fieldPath: spec.nodeName
|
||||
image: 'weaveworks/weave-npc:latest'
|
||||
imagePullPolicy: Always
|
||||
resources:
|
||||
requests:
|
||||
cpu: 10m
|
||||
securityContext:
|
||||
privileged: true
|
||||
hostNetwork: true
|
||||
hostPID: true
|
||||
restartPolicy: Always
|
||||
securityContext:
|
||||
seLinuxOptions: {}
|
||||
serviceAccountName: weave-net
|
||||
volumes:
|
||||
- name: weavedb
|
||||
hostPath:
|
||||
path: /var/lib/weave
|
||||
- name: cni-bin
|
||||
hostPath:
|
||||
path: /opt
|
||||
- name: cni-bin2
|
||||
hostPath:
|
||||
path: /home
|
||||
- name: cni-conf
|
||||
hostPath:
|
||||
path: /etc
|
||||
- name: dbus
|
||||
hostPath:
|
||||
path: /var/lib/dbus
|
||||
- name: lib-modules
|
||||
hostPath:
|
||||
path: /lib/modules
|
||||
@@ -27,7 +27,8 @@ RUN apk add --update \
|
||||
&& mknod /var/log/ulogd.pcap p
|
||||
COPY ./weave-npc /usr/bin/weave-npc
|
||||
COPY ./ulogd.conf /etc/ulogd.conf
|
||||
ENTRYPOINT ["/usr/bin/weave-npc"]
|
||||
COPY ./launch.sh /usr/bin/
|
||||
ENTRYPOINT ["/usr/bin/launch.sh"]
|
||||
|
||||
# These labels will change for every build, and should therefore be the last layer of the image:
|
||||
ARG revision
|
||||
|
||||
Executable
+36
@@ -0,0 +1,36 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
# Setup iptables backend to be legacy or nftable
|
||||
setup_iptables_backend() {
|
||||
if [ -n "${IPTABLES_BACKEND}" ]; then
|
||||
mode=$IPTABLES_BACKEND
|
||||
else
|
||||
# auto-detect if iptables backend mode to use if not specified explicitly
|
||||
num_legacy_lines=$( (iptables-legacy-save || true) 2>/dev/null | grep '^-' | wc -l)
|
||||
num_nft_lines=$( (iptables-nft-save || true) 2>/dev/null | grep '^-' | wc -l)
|
||||
if [ "${num_legacy_lines}" -ge 10 ]; then
|
||||
mode="legacy"
|
||||
else
|
||||
if [ "${num_legacy_lines}" -ge "${num_nft_lines}" ]; then
|
||||
mode="legacy"
|
||||
else
|
||||
mode="nft"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if [ $mode = "nft" ]; then
|
||||
rm /sbin/iptables
|
||||
rm /sbin/iptables-save
|
||||
rm /sbin/iptables-restore
|
||||
ln -s /sbin/iptables-nft /sbin/iptables
|
||||
ln -s /sbin/iptables-nft-save /sbin/iptables-save
|
||||
ln -s /sbin/iptables-nft-restore /sbin/iptables-restore
|
||||
fi
|
||||
}
|
||||
|
||||
setup_iptables_backend
|
||||
|
||||
# Start weave-npc with any flags specified in $EXTRA_ARGS as well as any flags passed to this container (for backwards compatibility)
|
||||
exec /usr/bin/weave-npc $EXTRA_ARGS $@
|
||||
+16
-10
@@ -34,7 +34,14 @@ var (
|
||||
bridgePortName string
|
||||
)
|
||||
|
||||
func handleError(err error) { common.CheckFatal(err) }
|
||||
func handleError(err error) {
|
||||
if err != nil {
|
||||
metrics.PolicyEnforcementErrors.Inc()
|
||||
common.Log.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func handleFatal(err error) { common.CheckFatal(err) }
|
||||
|
||||
func makeController(getter cache.Getter, resource string,
|
||||
objType runtime.Object, handlers cache.ResourceEventHandlerFuncs) cache.Controller {
|
||||
@@ -183,7 +190,6 @@ func createBaseRules(ipt *iptables.IPTables, ips ipset.Interface) error {
|
||||
{"-m", "state", "--state", "NEW", "-j", string(npc.EgressDefaultChain)},
|
||||
{"-m", "state", "--state", "NEW", "-m", "mark", "!", "--mark", npc.EgressMark, "-j", string(npc.EgressCustomChain)},
|
||||
{"-m", "state", "--state", "NEW", "-m", "mark", "!", "--mark", npc.EgressMark, "-j", "NFLOG", "--nflog-group", "86"},
|
||||
{"-m", "mark", "!", "--mark", npc.EgressMark, "-j", "DROP"},
|
||||
}...)
|
||||
if err := net.AddChainWithRules(ipt, npc.TableFilter, npc.EgressChain, ruleSpecs); err != nil {
|
||||
return err
|
||||
@@ -241,21 +247,21 @@ func root(cmd *cobra.Command, args []string) {
|
||||
}
|
||||
|
||||
config, err := rest.InClusterConfig()
|
||||
handleError(err)
|
||||
handleFatal(err)
|
||||
|
||||
client, err := kubernetes.NewForConfig(config)
|
||||
handleError(err)
|
||||
handleFatal(err)
|
||||
|
||||
ipt, err := iptables.New()
|
||||
handleError(err)
|
||||
handleFatal(err)
|
||||
|
||||
ips := ipset.New(common.LogLogger(), maxList)
|
||||
|
||||
handleError(resetIPTables(ipt))
|
||||
handleError(resetIPSets(ips))
|
||||
handleError(createBaseRules(ipt, ips))
|
||||
handleFatal(resetIPTables(ipt))
|
||||
handleFatal(resetIPSets(ips))
|
||||
handleFatal(createBaseRules(ipt, ips))
|
||||
|
||||
npc := npc.New(nodeName, ipt, ips)
|
||||
npc := npc.New(nodeName, ipt, ips, client)
|
||||
|
||||
nsController := makeController(client.Core().RESTClient(), "namespaces", &coreapi.Namespace{},
|
||||
cache.ResourceEventHandlerFuncs{
|
||||
@@ -340,5 +346,5 @@ func main() {
|
||||
rootCmd.PersistentFlags().IntVar(&maxList, "max-list-size", 1024, "maximum size of ipset list (for namespaces)")
|
||||
rootCmd.PersistentFlags().StringVar(&bridgePortName, "bridge-port-name", "vethwe-bridge", "name of the brige port on which packets are received and sent")
|
||||
|
||||
handleError(rootCmd.Execute())
|
||||
handleFatal(rootCmd.Execute())
|
||||
}
|
||||
+2
-1
@@ -188,7 +188,7 @@ func main() {
|
||||
mflag.StringVar(&logLevel, []string{"-log-level"}, "info", "logging level (debug, info, warning, error)")
|
||||
mflag.BoolVar(&pktdebug, []string{"-pkt-debug"}, false, "enable per-packet debug logging")
|
||||
mflag.StringVar(&prof, []string{"-profile"}, "", "enable profiling and write profiles to given path")
|
||||
mflag.IntVar(&config.ConnLimit, []string{"-conn-limit"}, 100, "connection limit (0 for unlimited)")
|
||||
mflag.IntVar(&config.ConnLimit, []string{"-conn-limit"}, 200, "connection limit (0 for unlimited)")
|
||||
mflag.BoolVar(&noDiscovery, []string{"-no-discovery"}, false, "disable peer discovery")
|
||||
mflag.IntVar(&bufSzMB, []string{"-bufsz"}, 8, "capture buffer size in MB")
|
||||
mflag.IntVar(&bridgeConfig.MTU, []string{"-mtu"}, 0, "MTU size")
|
||||
@@ -453,6 +453,7 @@ func main() {
|
||||
|
||||
pluginConfig.DNS = !noDNS
|
||||
pluginConfig.DefaultSubnet = defaultSubnet.String()
|
||||
pluginConfig.ProcPath = procPath
|
||||
plugin := plugin.NewPlugin(pluginConfig)
|
||||
|
||||
// The weave script always waits for a status call to succeed,
|
||||
|
||||
+21
-6
@@ -482,7 +482,7 @@ func (fastdp *FastDatapath) getVxlanVportID(udpPort int) (odp.VportID, error) {
|
||||
// The netdev interface is down, so most likely bringing it up
|
||||
// has failed due to the UDP port being in use.
|
||||
if err := fastdp.dp.DeleteVport(vxlanVportID); err != nil {
|
||||
log.Warning("Unable to remove vxlan vport %d: %s", vxlanVportID, err)
|
||||
log.Warningf("Unable to remove vxlan vport %d: %s", vxlanVportID, err)
|
||||
}
|
||||
return 0, odp.NetlinkError(syscall.EADDRINUSE)
|
||||
}
|
||||
@@ -654,27 +654,26 @@ func (fwd *fastDatapathForwarder) logPrefix() string {
|
||||
|
||||
func (fwd *fastDatapathForwarder) Confirm() {
|
||||
fwd.lock.Lock()
|
||||
defer fwd.lock.Unlock()
|
||||
|
||||
if fwd.confirmed {
|
||||
log.Fatal(fwd.logPrefix(), "already confirmed")
|
||||
}
|
||||
|
||||
var controlMsg []byte
|
||||
if fwd.fastdp.ipsec != nil && fwd.sessionKey != nil {
|
||||
fwd.isEncrypted = true
|
||||
log.Info("Setting up IPsec between ", fwd.fastdp.localPeer, " and ", fwd.remotePeer)
|
||||
err := fwd.fastdp.ipsec.InitSALocal(
|
||||
var err error
|
||||
controlMsg, err = fwd.fastdp.ipsec.InitSALocal(
|
||||
fwd.fastdp.localPeer.Name, fwd.remotePeer.Name, fwd.connUID,
|
||||
net.IP(fwd.localIP[:]), fwd.remoteAddr.IP,
|
||||
fwd.remoteAddr.Port,
|
||||
fwd.sessionKey,
|
||||
func(msg []byte) error {
|
||||
return fwd.sendControlMsg(FastDatapathCryptoInitSARemote, msg)
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
log.Error(fwd.logPrefix(), "ipsec init SA local failed: ", err)
|
||||
fwd.handleError(err)
|
||||
fwd.lock.Unlock()
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -692,6 +691,17 @@ func (fwd *fastDatapathForwarder) Confirm() {
|
||||
}
|
||||
|
||||
fwd.heartbeatTimeout = time.NewTimer(HeartbeatTimeout)
|
||||
|
||||
fwd.lock.Unlock() // unlock before calling send() which may block
|
||||
|
||||
if len(controlMsg) > 0 {
|
||||
if err := fwd.sendControlMsg(FastDatapathCryptoInitSARemote, controlMsg); err != nil {
|
||||
log.Error(fwd.logPrefix(), "ipsec send InitSARemote failed: ", err)
|
||||
fwd.handleError(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
go fwd.doHeartbeats()
|
||||
}
|
||||
|
||||
@@ -881,6 +891,11 @@ func (fwd *fastDatapathForwarder) handleHeartbeatAck() {
|
||||
}
|
||||
|
||||
func (fwd *fastDatapathForwarder) handleCryptoInitSARemote(msg []byte) {
|
||||
if fwd.stopped {
|
||||
log.Info(fwd.logPrefix(), "IPSec init SA remote failed: forwarder has already been stopped")
|
||||
return
|
||||
}
|
||||
|
||||
log.Info(fwd.logPrefix(), "IPSec init SA remote")
|
||||
err := fwd.fastdp.ipsec.InitSARemote(
|
||||
msg,
|
||||
|
||||
+5
-1
@@ -4,10 +4,14 @@ import (
|
||||
"fmt"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/google/gopacket/pcap"
|
||||
)
|
||||
|
||||
// Must be less than 2^31 usec - see https://github.com/google/gopacket/issues/708
|
||||
const longTimeout = time.Duration(30 * time.Minute)
|
||||
|
||||
type Pcap struct {
|
||||
NonDiscardingFlowOp
|
||||
|
||||
@@ -77,7 +81,7 @@ func newPcapHandle(ifName string, promisc bool, snaplen int, bufSz int) (handle
|
||||
if err = inactive.SetSnapLen(snaplen); err != nil {
|
||||
return
|
||||
}
|
||||
if err = inactive.SetTimeout(MaxDuration); err != nil {
|
||||
if err = inactive.SetTimeout(longTimeout); err != nil {
|
||||
return
|
||||
}
|
||||
if err = inactive.SetImmediateMode(true); err != nil {
|
||||
|
||||
+1
-1
@@ -1092,7 +1092,7 @@ func (sender *udpSenderDF) send(msg []byte, raddr *net.UDPAddr) error {
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
log.Print("EMSGSIZE on send, expecting PMTU update (IP packet was ", len(packet), " bytes, payload was ", len(msg), " bytes)")
|
||||
log.Debug("sleeve ->[", sender, "] expecting PMTU update (IP packet was ", len(packet), " bytes, payload was ", len(msg), " bytes)")
|
||||
pmtu, err := syscall.GetsockoptInt(int(f.Fd()), syscall.IPPROTO_IP, syscall.IP_MTU)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -7,6 +7,8 @@ search_type: Documentation
|
||||
The following topics are discussed:
|
||||
|
||||
* [Installation](#install)
|
||||
* [Installing on GKE](#gke)
|
||||
* [Installing on EKS](#eks)
|
||||
* [Upgrading the Daemon Sets](#daemon-sets)
|
||||
* [CPU and Memory Requirements](#resources)
|
||||
* [Pod Eviction](#eviction)
|
||||
@@ -18,6 +20,7 @@ The following topics are discussed:
|
||||
* [Troubleshooting Blocked Connections](#blocked-connections)
|
||||
* [Things to watch out for](#key-points)
|
||||
* [Changing Configuration Options](#configuration-options)
|
||||
* [Securing The Setup](#securing-the-setup)
|
||||
|
||||
|
||||
## <a name="install"></a> Installation
|
||||
@@ -33,6 +36,8 @@ with a single command:
|
||||
$ kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"
|
||||
```
|
||||
|
||||
**Important:** this configuration won't enable encryption by default. If your data plane traffic isn't secured that could allow malicious actors to access your pod network. Read on to see the alternatives.
|
||||
|
||||
After a few seconds, a Weave Net pod should be running on each
|
||||
Node and any further pods you create will be automatically attached to the Weave
|
||||
network.
|
||||
@@ -68,10 +73,26 @@ Shut down Kubernetes, and _on all nodes_ perform the following:
|
||||
Then relaunch Kubernetes and install the addon as described
|
||||
above.
|
||||
|
||||
**Note:** Installing on GKE
|
||||
### <a name="gke"></a> Installing on GKE
|
||||
Please note that you must grant the user the ability to create roles in Kubernetes before launching Weave Net.
|
||||
This is a prerequisite to use use role-based access control on GKE. Please see the GKE [instructions](https://cloud.google.com/kubernetes-engine/docs/how-to/role-based-access-control).
|
||||
|
||||
### <a name="gke"></a> Installing on EKS
|
||||
|
||||
EKS by default installs `amazon-vpc-cni-k8s` CNI. Please follow below steps to use Weave-net as CNI
|
||||
|
||||
- create EKS cluster in any of [prescribed](https://docs.aws.amazon.com/eks/latest/userguide/create-cluster.html) way
|
||||
- delete `amazon-vpc-cni-k8s` deamonset by running `kubectl delete ds aws-node -n kube-system` command
|
||||
- delete `/etc/cni/net.d/10-aws.conflist` on each of the node
|
||||
- edit instance security group to allow TCP 6783 and UDP 6783/6784 ports
|
||||
- flush iptables nat, mangle, filter tables to clear any iptables configurations done by `amazon-vpc-cni-k8s`
|
||||
- restart kube-proxy pods to reconfigure iptables
|
||||
- apply weave-net daemoset by following above installation steps
|
||||
- delete existing pods so they get recreated in Weave pod CIDR's address-space.
|
||||
|
||||
Please note that while pods can connect to the Kubernetes API server for your cluser, API server will not be able to connect to the pods as API server nodes are not connected to Weave Net (they run on network managed by EKS).
|
||||
|
||||
|
||||
### <a name="daemon-sets"></a> Upgrading the Daemon Sets
|
||||
|
||||
The DaemonSet definition specifies [Rolling
|
||||
@@ -86,23 +107,18 @@ Kubernetes manages
|
||||
on each node, and only schedules pods to run on nodes that have enough
|
||||
free resources.
|
||||
|
||||
The components of a typical Kubernetes installation (with the master
|
||||
node running etcd, scheduler, api-server, etc.) take up about 95% of a
|
||||
CPU, which leaves little room to run anything else. For all of Weave
|
||||
Net's features to work, it must run on every node, including the
|
||||
master.
|
||||
In the example manifests we request 10% of a CPU, which will be enough
|
||||
for small installations, but you should monitor how much it uses in
|
||||
your production clusters and adjust the requests to suit.
|
||||
|
||||
The best way to resolve this issue is to use machines with at least
|
||||
two CPU cores. However if you are installing Kubernetes and Weave Net
|
||||
for the first time, you may not be aware of this requirement. For this
|
||||
reason, Weave Net launches as a DaemonSet with a specification that
|
||||
reserves at least 1% CPU for each container. This enables Weave Net to
|
||||
start up seamlessly on a single-CPU node.
|
||||
We do not recommend that you set a CPU or memory _limit_ unless you
|
||||
are very experienced in such matters, because the implementation of
|
||||
limits in the Linux kernel sometimes behaves in a surprising way.
|
||||
|
||||
Depending on the workload, Weave Net may need more than 1% of the
|
||||
CPU. The percentage set in the DaemonSet is the minimum and not a
|
||||
limit. This minimum setting allows Weave Net to take advantage of
|
||||
available CPU and "burst" above that limit if it needs to.
|
||||
On a 1-node single-CPU cluster you may find Weave Net does not install
|
||||
at all, because other Kubernetes components already take 95% of the
|
||||
CPU. The best way to resolve this issue is to use machines with at
|
||||
least two CPU cores.
|
||||
|
||||
## <a name="eviction"></a>Pod Eviction
|
||||
|
||||
@@ -209,10 +225,10 @@ ask for the logs like this:
|
||||
$ kubectl logs -n kube-system weave-net-1jkl6 weave
|
||||
```
|
||||
|
||||
For easier viewing, pipe the output into a file , especially if
|
||||
For easier viewing, pipe the output into a file, especially if
|
||||
it is long.
|
||||
|
||||
By default log level of `weave` container is set to `info` level. If you wish to see more detailed logs you can set the desired log level for the `-log-level` flag through the `EXTRA_ARGS` environment variable for the `weave` container in the weave-net daemon set. Add environment variable as below.
|
||||
By default log level of `weave` container is set to `info` level. If you wish to see more detailed logs you can set the desired log level for the `--log-level` flag through the `EXTRA_ARGS` environment variable for the `weave` container in the weave-net daemon set. Add environment variable as below.
|
||||
|
||||
```yaml
|
||||
containers:
|
||||
@@ -224,9 +240,11 @@ By default log level of `weave` container is set to `info` level. If you wish to
|
||||
value: --log-level=debug
|
||||
```
|
||||
|
||||
You may also set the `--log-level` flag to `warning` or `error` if you
|
||||
prefer to only log exceptional conditions.
|
||||
|
||||
Many Kubernetes network issues occur at a higher level than Weave Net.
|
||||
The [Kubernetes Service Debugging Guide]
|
||||
(https://kubernetes.io/docs/tasks/debug-application-cluster/debug-service/)
|
||||
The [Kubernetes Service Debugging Guide](https://kubernetes.io/docs/tasks/debug-application-cluster/debug-service/)
|
||||
has a detailed step-by-step guide.
|
||||
|
||||
Once it is up and running, the status of Weave Net can be checked by
|
||||
@@ -336,6 +354,8 @@ UDP connection from 10.32.0.7:56648 to 10.32.0.11:80 blocked by Weave NPC.
|
||||
|
||||
### <a name="key-points"></a> Things to watch out for
|
||||
|
||||
- Weave Net does not work on hosts running iptables 1.8 or above, only with 1.6.
|
||||
Track this via issue [#3465](https://github.com/weaveworks/weave/issues/3465)
|
||||
- Don't turn on `--masquerade-all` on kube-proxy: this will change the
|
||||
source address of every pod-to-pod conversation which will make it
|
||||
impossible to correctly enforce network policies that restrict which
|
||||
@@ -376,7 +396,7 @@ The list of variables you can set is:
|
||||
* `CHECKPOINT_DISABLE` - if set to 1, disable checking for new Weave Net
|
||||
versions (default is blank, i.e. check is enabled)
|
||||
* `CONN_LIMIT` - soft limit on the number of connections between
|
||||
peers. Defaults to 100.
|
||||
peers. Defaults to 200.
|
||||
* `HAIRPIN_MODE` - Weave Net defaults to enabling hairpin on the bridge side of
|
||||
the `veth` pair for containers attached. If you need to disable hairpin, e.g. your
|
||||
kernel is one of those that can panic if hairpin is enabled, then you can disable it
|
||||
@@ -404,6 +424,7 @@ The list of variables you can set is:
|
||||
* `NO_MASQ_LOCAL` - set to 1 to preserve the client source IP address when
|
||||
accessing Service annotated with `service.spec.externalTrafficPolicy=Local`.
|
||||
The feature works only with Weave IPAM (default).
|
||||
* `IPTABLES_BACKEND` - set to `nft` to use `nftables` backend for `iptables` (default is `iptables`)
|
||||
|
||||
Example:
|
||||
```
|
||||
@@ -442,3 +463,19 @@ For example,
|
||||
- name: IPALLOC_RANGE
|
||||
value: 10.0.0.0/16
|
||||
```
|
||||
|
||||
## <a name="securing-the-setup"></a> Securing the Setup
|
||||
|
||||
You must pass the `password-secret` option as noted in the previous section to enable the data plane encryption; this is a recommended option in case you cannot be sure about the security of the fabric between your nodes.
|
||||
|
||||
A different option is to use `trusted-subnets` and whitelist only the subnets that host your k8s nodes. Mind that depending on your circumstances that might allow a malicious container running in your cluster to access the weave dataplane, still.
|
||||
|
||||
Read on the [Securing Connections Across Untrusted Networks](/site/tasks/manage/security-untrusted-networks/) document to see the alternatives.
|
||||
|
||||
To improve security drop `CAP_NET_RAW` from pod capabilities: by default pods can forge packets from anywhere on the network, which enables attacks such as DNS spoofing.
|
||||
|
||||
```
|
||||
securityContext:
|
||||
capabilities:
|
||||
drop: ["NET_RAW"]
|
||||
```
|
||||
@@ -9,6 +9,9 @@ Weave Net creates a virtual network that connects Docker containers across multi
|
||||
|
||||
Services provided by application containers on the weave network can be exposed to the outside world, regardless of where they are running. Similarly, existing internal systems can be opened to accept connections from application containers irrespective of their location.
|
||||
|
||||
### How does it work?
|
||||
|
||||
Weave Net creates a new Layer 2 network using Linux kernel features; one daemon sets up that network and manages routing between machines and there are various ways to attach to that network (e.g. a CNI plugin which runs as a separate process). Also one more daemon if you are using Kubernetes Network Policy.
|
||||
|
||||
## Why Weave?
|
||||
|
||||
|
||||
@@ -13,7 +13,22 @@ Weave Net detects when a container has exited and releases its allocated address
|
||||
|
||||
See the [Automatic IP Address Management](/site/tasks/ipam/ipam.md) and also an explanation of [the basics of IP addressing](/site/concepts/ip-addresses.md) for further details.
|
||||
|
||||
Instead of allowing Weave Net to allocate IP addresses automatically (using IPAM), there may be instances where you need to control a particular container or a cluster by setting an IP address for it.
|
||||
Instead of allowing Weave Net to allocate IP addresses automatically (using IPAM), there may be instances where you need to control a particular container or a cluster by setting an IP address for it. The way to do this varies according to how containers are attached to Weave Net.
|
||||
|
||||
## Manually specifying an IP address when using CNI
|
||||
|
||||
The software making a call to CNI has to specify an allocator that allows static IPs.
|
||||
For instance the [static allocator](https://github.com/containernetworking/plugins/tree/master/plugins/ipam/static)
|
||||
|
||||
(At the time of writing there is no straightforward way to ask Kubernetes to do this.)
|
||||
|
||||
## Manually specifying an IP address when using the Weave Net Docker Plugin
|
||||
|
||||
Docker has a flag `--ip` to specify an address, e.g.:
|
||||
|
||||
$ docker run --network=mynetwork --ip=172.18.0.22 ...
|
||||
|
||||
## Manually specifying an IP address when using the Weave Net Docker Proxy
|
||||
|
||||
You can specify an IP address and a network explicitly, using Classless Inter-Domain Routing or [CIDR notation](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing).
|
||||
|
||||
|
||||
@@ -26,10 +26,15 @@ start_container $HOST2 $C2/24 --name=c2
|
||||
assert_raises "weave_on $HOST2 connect 10.2.2.1 10.2.2.2"
|
||||
assert_peers $HOST2 "10.2.2.1\n10.2.2.2"
|
||||
|
||||
sleep 2 # Allow topology to propagate
|
||||
|
||||
# Replace bogus hosts with real hosts
|
||||
assert_raises "exec_on $HOST1 c1 sh -c '! $PING $C2'"
|
||||
assert_raises "weave_on $HOST2 connect --replace $HOST1 $HOST2"
|
||||
assert_peers $HOST2 "$HOST1\n$HOST2"
|
||||
|
||||
sleep 2 # Allow topology to propagate
|
||||
|
||||
assert_raises "exec_on $HOST1 c1 $PING $C2"
|
||||
|
||||
# Forget everyone and disconnect
|
||||
@@ -37,6 +42,9 @@ assert_raises "weave_on $HOST2 forget $HOST1 $HOST2"
|
||||
assert_raises "stop_weave_on $HOST1"
|
||||
assert_raises "weave_on $HOST1 launch"
|
||||
assert_peers $HOST2 ""
|
||||
|
||||
sleep 2 # Allow topology to propagate
|
||||
|
||||
assert_raises "exec_on $HOST1 c1 sh -c '! $PING $C2'"
|
||||
|
||||
end_suite
|
||||
@@ -9,7 +9,7 @@ kill_weaver() {
|
||||
run_on $HOST1 sudo ip link set weave down
|
||||
WEAVER_PID=$(container_pid $HOST1 weave)
|
||||
run_on $HOST1 sudo kill -9 $WEAVER_PID
|
||||
sleep 3
|
||||
sleep 5
|
||||
}
|
||||
|
||||
start_suite "Re-create bridge after restart"
|
||||
@@ -20,6 +20,7 @@ WEAVE_NO_FASTDP=1 weave_on $HOST2 launch $HOST1
|
||||
|
||||
start_container $HOST1 $C1/24 --name=c1
|
||||
start_container $HOST2 $C2/24 --name=c2
|
||||
sleep 2 # give topology gossip some time to propagate
|
||||
assert_raises "exec_on $HOST1 c1 $PING $C2"
|
||||
|
||||
kill_weaver # should re-create the bridge
|
||||
@@ -30,6 +31,7 @@ assert_raises "exec_on $HOST1 c1 $PING $C2"
|
||||
weave_on $HOST1 reset
|
||||
weave_on $HOST1 launch $HOST2
|
||||
weave_on $HOST1 attach $C1/24 c1
|
||||
sleep 2 # give topology gossip some time to propagate
|
||||
assert_raises "exec_on $HOST1 c1 $PING $C2"
|
||||
|
||||
kill_weaver # should re-create the bridge
|
||||
|
||||
@@ -16,6 +16,8 @@ for host in $HOSTS; do
|
||||
weave_on $host launch --ipalloc-range $UNIVERSE $HOSTS
|
||||
done
|
||||
|
||||
sleep 2 # Allow topology updates to propagate
|
||||
|
||||
# Basic test
|
||||
start_container $HOST2 $C2/24 --name=c2 -h $NAME2
|
||||
start_container_with_dns $HOST1 $C1/24 --name=c1
|
||||
|
||||
@@ -8,6 +8,8 @@ weave_on $HOST1 launch --no-discovery
|
||||
weave_on $HOST2 launch --no-discovery $HOST1
|
||||
weave_on $HOST3 launch --no-discovery $HOST2
|
||||
|
||||
sleep 2 # Allow topology updates to propagate
|
||||
|
||||
start_container $HOST1 --name=c1
|
||||
C1=$(container_ip $HOST1 c1)
|
||||
start_container_with_dns $HOST3 --name=c3
|
||||
@@ -25,7 +27,7 @@ weave_on $HOST1 launch --no-discovery $HOST3
|
||||
# Now re-enable gossip from host2 to host3
|
||||
run_on $HOST3 "sudo iptables -D INPUT -s $HOST2 -j DROP"
|
||||
|
||||
sleep 1
|
||||
sleep 2 # allow some time for connections to reform and updates to propagate
|
||||
|
||||
assert_no_dns_record $HOST3 c3 c1.weave.local
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ weave_on $HOST1 launch --ipalloc-range $UNIVERSE $HOST2
|
||||
# Start another container on host1. The starting should block, because host1 is
|
||||
# not able to establish the ring due to host2 being offline.
|
||||
CMD="proxy_start_container $HOST1 --name c4 -e WEAVE_CIDR=$C4/12"
|
||||
assert_raises "timeout 5 cat <( $CMD )" 124
|
||||
assert_raises "timeout --signal=9 5 cat <( $CMD )" 137
|
||||
|
||||
# However, allocation for an external subnet should not block.
|
||||
assert_raises "proxy_start_container $HOST1 -e WEAVE_CIDR=10.3.0.1/12"
|
||||
|
||||
@@ -15,6 +15,9 @@ assert_raises "timeout 10 cat <( start_container $HOST2 --name c2)"
|
||||
# Connect routers
|
||||
weave_on $HOST2 connect $HOST1
|
||||
|
||||
# Allow topology to propagate
|
||||
sleep 2
|
||||
|
||||
# Check connectivity
|
||||
assert_raises "exec_on $HOST1 c1 $PING c2"
|
||||
assert_raises "exec_on $HOST2 c2 $PING c1"
|
||||
|
||||
@@ -13,6 +13,9 @@ docker_py_test() {
|
||||
|
||||
# Work round https://github.com/docker/docker-py/issues/852
|
||||
docker_on $HOST1 pull busybox:buildroot-2014.02 >/dev/null
|
||||
# Work round https://github.com/weaveworks/weave/issues/3680 - pin busybox version to 1.28
|
||||
docker_on $HOST1 pull busybox:1.28 >/dev/null
|
||||
docker_on $HOST1 tag busybox:1.28 busybox:latest >/dev/null
|
||||
# Get a list of the tests for use to shard
|
||||
docker_on $HOST1 pull $IMAGE >/dev/null
|
||||
CANDIDATES=$(docker_on $HOST1 run \
|
||||
|
||||
@@ -15,6 +15,8 @@ weave_on $HOST2 launch $HOST1
|
||||
start_container_local_plugin $HOST1 --name=c1 --hostname=$C1_NAME --dns=$DNS_IP
|
||||
start_container_local_plugin $HOST2 --name=c2 --hostname=$C2_NAME --dns=$DNS_IP
|
||||
|
||||
sleep 2 # Allow topology to propagate
|
||||
|
||||
assert_raises "exec_on $HOST1 c1 $PING $C2_NAME"
|
||||
assert_raises "exec_on $HOST2 c2 $PING $C1_NAME"
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ fi
|
||||
# Ensure Kubernetes uses locally built container images and inject code coverage environment variable (or do nothing depending on $COVERAGE):
|
||||
sed -e "s%imagePullPolicy: Always%imagePullPolicy: Never%" \
|
||||
-e "s%env:%$WEAVE_ENV_VARS%" \
|
||||
"$(dirname "$0")/../prog/weave-kube/weave-daemonset-k8s-1.8.yaml" | run_on "$HOST1" "$KUBECTL apply -n kube-system -f -"
|
||||
"$(dirname "$0")/../prog/weave-kube/weave-daemonset-k8s-1.9.yaml" | run_on "$HOST1" "$KUBECTL apply -n kube-system -f -"
|
||||
|
||||
sleep 5
|
||||
|
||||
@@ -357,7 +357,7 @@ WEAVE_ENV_VARS="${WEAVE_ENV_VARS}\\n - name: NO_MASQ_LOCAL\\n
|
||||
$SSH $HOST1 "$KUBECTL delete ds weave-net -n=kube-system"
|
||||
sed -e "s%imagePullPolicy: Always%imagePullPolicy: Never%" \
|
||||
-e "s%env:%$WEAVE_ENV_VARS%" \
|
||||
"$(dirname "$0")/../prog/weave-kube/weave-daemonset-k8s-1.8.yaml" | run_on "$HOST1" "$KUBECTL apply -n kube-system -f -"
|
||||
"$(dirname "$0")/../prog/weave-kube/weave-daemonset-k8s-1.9.yaml" | run_on "$HOST1" "$KUBECTL apply -n kube-system -f -"
|
||||
|
||||
sleep 5
|
||||
|
||||
|
||||
@@ -54,6 +54,8 @@ function setup_kubernetes_cluster {
|
||||
}
|
||||
|
||||
function force_drop_node {
|
||||
greyly echo "Shutting down Kubernetes on node $1"
|
||||
run_on $1 "sudo kubeadm reset --force"
|
||||
greyly echo "Dropping node $1 with 'sudo kubectl delete node'"
|
||||
local target=$(echo "$1" | awk -F"." '{print $1}')
|
||||
run_on $HOST1 "$KUBECTL delete node $target"
|
||||
@@ -84,7 +86,7 @@ function relaunch_weave_pod {
|
||||
# Suite
|
||||
#
|
||||
function main {
|
||||
local IPAM_RECOVER_DELAY=90
|
||||
local IPAM_RECOVER_DELAY=10
|
||||
|
||||
start_suite "Test weave-net deallocates from IPAM on node failure";
|
||||
|
||||
|
||||
Binary file not shown.
@@ -206,7 +206,8 @@ function set_hosts() {
|
||||
function provision_remotely() {
|
||||
case "$1" in
|
||||
on)
|
||||
terraform apply -input=false -parallelism="$NUM_HOSTS" -var "app=$APP" -var "name=$NAME" -var "num_hosts=$NUM_HOSTS" "$DIR/../tools/provisioning/$2"
|
||||
terraform init "$DIR/../tools/provisioning/gcp"
|
||||
terraform apply -auto-approve -input=false -parallelism="$NUM_HOSTS" -var "app=$APP" -var "name=$NAME" -var "num_hosts=$NUM_HOSTS" "$DIR/../tools/provisioning/$2"
|
||||
local status=$?
|
||||
ssh_user=$(terraform output username)
|
||||
ssh_id_file=$(terraform output private_key_path)
|
||||
|
||||
@@ -199,3 +199,7 @@ func (client TestRouterClient) GossipUnicast(dstPeerName mesh.PeerName, buf []by
|
||||
func (client TestRouterClient) GossipBroadcast(update mesh.GossipData) {
|
||||
client.router.gossipBroadcast(client.sender, update)
|
||||
}
|
||||
|
||||
func (client TestRouterClient) GossipNeighbourSubset(update mesh.GossipData) {
|
||||
client.router.gossip(client.sender, update)
|
||||
}
|
||||
@@ -110,10 +110,6 @@ func ObjectReaction(tracker ObjectTracker) testing.ReactionFunc {
|
||||
}
|
||||
err = tracker.Update(gvr, action.GetObject(), ns)
|
||||
if err != nil {
|
||||
if errors.IsConflict(err) { // return the currently-stored version of the object
|
||||
obj, _ := tracker.Get(gvr, ns, objMeta.GetName())
|
||||
return true, obj, err
|
||||
}
|
||||
return true, nil, err
|
||||
}
|
||||
obj, err := tracker.Get(gvr, ns, objMeta.GetName())
|
||||
|
||||
+1
-1
Submodule tools updated: ca69607f79...2a2df52789.
+7
-4
@@ -2,8 +2,8 @@
|
||||
|
||||
cd "$(dirname $0)"
|
||||
|
||||
go get github.com/golang/lint/golint
|
||||
DIRS=". tcpassembly tcpassembly/tcpreader ip4defrag reassembly macs pcapgo pcap afpacket pfring routing"
|
||||
go get golang.org/x/lint/golint
|
||||
DIRS=". tcpassembly tcpassembly/tcpreader ip4defrag reassembly macs pcapgo pcap afpacket pfring routing defrag/lcmdefrag"
|
||||
# Add subdirectories here as we clean up golint on each.
|
||||
for subdir in $DIRS; do
|
||||
pushd $subdir
|
||||
@@ -17,8 +17,11 @@ for subdir in $DIRS; do
|
||||
done
|
||||
|
||||
pushd layers
|
||||
for file in $(cat .linted); do
|
||||
if golint $file | grep .; then
|
||||
for file in *.go; do
|
||||
if cat .lint_blacklist | grep -q $file; then
|
||||
echo "Skipping lint of $file due to .lint_blacklist"
|
||||
elif golint $file | grep .; then
|
||||
echo "Lint error in file $file"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
cd "$(dirname $0)"
|
||||
DIRS=". layers pcap pcapgo pfring tcpassembly tcpassembly/tcpreader routing ip4defrag bytediff macs"
|
||||
DIRS=". layers pcap pcapgo tcpassembly tcpassembly/tcpreader routing ip4defrag bytediff macs defrag/lcmdefrag"
|
||||
set -e
|
||||
for subdir in $DIRS; do
|
||||
pushd $subdir
|
||||
|
||||
+4
@@ -1,12 +1,16 @@
|
||||
language: go
|
||||
before_install:
|
||||
- sudo apt-get install libpcap-dev
|
||||
install:
|
||||
- go get github.com/google/gopacket
|
||||
- go get github.com/google/gopacket/layers
|
||||
- go get github.com/google/gopacket/pcapgo
|
||||
- go get github.com/google/gopacket/tcpassembly
|
||||
- go get github.com/google/gopacket/reassembly
|
||||
script:
|
||||
- go test github.com/google/gopacket
|
||||
- go test github.com/google/gopacket/layers
|
||||
- go test github.com/google/gopacket/pcapgo
|
||||
- go test github.com/google/gopacket/tcpassembly
|
||||
- go test github.com/google/gopacket/reassembly
|
||||
- ./.travis.gofmt.sh
|
||||
|
||||
+5
@@ -13,6 +13,9 @@ Hiroaki Kawai <Hiroaki.Kawai@gmail.com>
|
||||
Lukas Lueg <lukas.lueg@gmail.com>
|
||||
Laurent Hausermann <laurent.hausermann@gmail.com>
|
||||
Bill Green <bgreen@newrelic.com>
|
||||
Christian Mäder <christian.maeder@nine.ch>
|
||||
Gernot Vormayr <gvormayr@gmail.com>
|
||||
Vitor Garcia Graveto <victor.graveto@gmail.com>
|
||||
|
||||
CONTRIBUTORS:
|
||||
Attila Oláh <attila@attilaolah.eu>
|
||||
@@ -26,6 +29,8 @@ Satoshi Matsumoto <kaorimatz@gmail.com>
|
||||
David Stainton <dstainton415@gmail.com>
|
||||
Jesse Ward <jesse@jesseward.com>
|
||||
Kane Mathers <kane@kanemathers.name>
|
||||
Jose Selvi <jselvi@pentester.es>
|
||||
Yerden Zhumabekov <yerden.zhumabekov@gmail.com>
|
||||
|
||||
-----------------------------------------------
|
||||
FORKED FROM github.com/akrennmair/gopcap
|
||||
|
||||
+2
@@ -6,5 +6,7 @@ See [godoc](https://godoc.org/github.com/google/gopacket) for more details.
|
||||
[](https://travis-ci.org/google/gopacket)
|
||||
[](https://godoc.org/github.com/google/gopacket)
|
||||
|
||||
Minimum Go version required is 1.5.
|
||||
|
||||
Originally forked from the gopcap project written by Andreas
|
||||
Krennmair <ak@synflood.at> (http://github.com/akrennmair/gopcap).
|
||||
+7
-2
@@ -22,6 +22,8 @@ useful, including:
|
||||
Also, if you're looking to dive right into code, see the examples subdirectory
|
||||
for numerous simple binaries built using gopacket libraries.
|
||||
|
||||
Minimum go version required is 1.5.
|
||||
|
||||
Basic Usage
|
||||
|
||||
gopacket takes in packet data as a []byte and decodes it into a packet with
|
||||
@@ -288,7 +290,10 @@ the packet's information. A quick example:
|
||||
parser := gopacket.NewDecodingLayerParser(layers.LayerTypeEthernet, ð, &ip4, &ip6, &tcp)
|
||||
decoded := []gopacket.LayerType{}
|
||||
for packetData := range somehowGetPacketData() {
|
||||
err := parser.DecodeLayers(packetData, &decoded)
|
||||
if err := parser.DecodeLayers(packetData, &decoded); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Could not decode layers: %v\n", err)
|
||||
continue
|
||||
}
|
||||
for _, layerType := range decoded {
|
||||
switch layerType {
|
||||
case layers.LayerTypeIPv6:
|
||||
@@ -329,7 +334,7 @@ the following manner:
|
||||
}
|
||||
buf := gopacket.NewSerializeBuffer()
|
||||
opts := gopacket.SerializeOptions{} // See SerializeOptions for more details.
|
||||
err := ip.SerializeTo(&buf, opts)
|
||||
err := ip.SerializeTo(buf, opts)
|
||||
if err != nil { panic(err) }
|
||||
fmt.Println(buf.Bytes()) // prints out a byte slice containing the serialized IPv4 layer.
|
||||
|
||||
|
||||
+10
@@ -106,6 +106,7 @@ if [ ! -z "$GEN" ]; then
|
||||
popd
|
||||
pushd layers
|
||||
go run gen.go | gofmt > iana_ports.go
|
||||
go run gen2.go | gofmt > enums_generated.go
|
||||
popd
|
||||
fi
|
||||
|
||||
@@ -126,6 +127,9 @@ if [ -f /usr/include/pcap.h ]; then
|
||||
Root pcap_tester --mode=filtered
|
||||
Root pcap_tester --mode=timestamp || echo "You might not support timestamp sources"
|
||||
popd
|
||||
pushd examples/afpacket
|
||||
go build
|
||||
popd
|
||||
pushd examples/pcapdump
|
||||
go build
|
||||
popd
|
||||
@@ -182,6 +186,12 @@ if [ -f /usr/include/pfring.h ]; then
|
||||
go build
|
||||
popd
|
||||
fi
|
||||
pushd ip4defrag
|
||||
go test ./...
|
||||
popd
|
||||
pushd defrag
|
||||
go test ./...
|
||||
popd
|
||||
|
||||
for travis_script in `ls .travis.*.sh`; do
|
||||
./$travis_script
|
||||
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
dot11.go
|
||||
eap.go
|
||||
endpoints.go
|
||||
enums_generated.go
|
||||
enums.go
|
||||
ethernet.go
|
||||
geneve.go
|
||||
icmp4.go
|
||||
icmp6.go
|
||||
igmp.go
|
||||
ip4.go
|
||||
ip6.go
|
||||
layertypes.go
|
||||
linux_sll.go
|
||||
llc.go
|
||||
lldp.go
|
||||
mpls.go
|
||||
ndp.go
|
||||
ntp.go
|
||||
ospf.go
|
||||
pflog.go
|
||||
pppoe.go
|
||||
prism.go
|
||||
radiotap.go
|
||||
rudp.go
|
||||
sctp.go
|
||||
sflow.go
|
||||
tcp.go
|
||||
tcpip.go
|
||||
tls.go
|
||||
tls_alert.go
|
||||
tls_appdata.go
|
||||
tls_cipherspec.go
|
||||
tls_hanshake.go
|
||||
tls_test.go
|
||||
udp.go
|
||||
udplite.go
|
||||
usb.go
|
||||
vrrp.go
|
||||
-40
@@ -1,40 +0,0 @@
|
||||
arp.go
|
||||
base.go
|
||||
base_test.go
|
||||
cdp.go
|
||||
ctp.go
|
||||
decode_test.go
|
||||
dhcp_test.go
|
||||
dhcpv4.go
|
||||
dns.go
|
||||
dns_test.go
|
||||
doc.go
|
||||
dot11_test.go
|
||||
dot1q.go
|
||||
dot1q_test.go
|
||||
eapol.go
|
||||
etherip.go
|
||||
fddi.go
|
||||
gen.go
|
||||
gre.go
|
||||
gre_test.go
|
||||
iana_ports.go
|
||||
icmp6_test.go
|
||||
igmp_test.go
|
||||
ip4_test.go
|
||||
ipsec.go
|
||||
ipsec_test.go
|
||||
loopback.go
|
||||
mpls_test.go
|
||||
ntp_test.go
|
||||
ports.go
|
||||
ppp.go
|
||||
prism_test.go
|
||||
radiotap_test.go
|
||||
sflow_test.go
|
||||
tcp_test.go
|
||||
udp_test.go
|
||||
usb_test.go
|
||||
vrrp_test.go
|
||||
vxlan.go
|
||||
vxlan_test.go
|
||||
+481
@@ -0,0 +1,481 @@
|
||||
// Copyright 2017 Google, Inc. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the LICENSE file in the root of the source
|
||||
// tree.
|
||||
//
|
||||
|
||||
package layers
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
|
||||
"github.com/google/gopacket"
|
||||
)
|
||||
|
||||
// BFD Control Packet Format
|
||||
// -------------------------
|
||||
// The current version of BFD's RFC (RFC 5880) contains the following
|
||||
// diagram for the BFD Control packet format:
|
||||
//
|
||||
// 0 1 2 3
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// |Vers | Diag |Sta|P|F|C|A|D|M| Detect Mult | Length |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | My Discriminator |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | Your Discriminator |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | Desired Min TX Interval |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | Required Min RX Interval |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | Required Min Echo RX Interval |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
//
|
||||
// An optional Authentication Section MAY be present:
|
||||
//
|
||||
// 0 1 2 3
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | Auth Type | Auth Len | Authentication Data... |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
//
|
||||
//
|
||||
// Simple Password Authentication Section Format
|
||||
// ---------------------------------------------
|
||||
// 0 1 2 3
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | Auth Type | Auth Len | Auth Key ID | Password... |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | ... |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
//
|
||||
//
|
||||
// Keyed MD5 and Meticulous Keyed MD5 Authentication Section Format
|
||||
// ----------------------------------------------------------------
|
||||
// 0 1 2 3
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | Auth Type | Auth Len | Auth Key ID | Reserved |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | Sequence Number |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | Auth Key/Digest... |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | ... |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
//
|
||||
//
|
||||
// Keyed SHA1 and Meticulous Keyed SHA1 Authentication Section Format
|
||||
// ------------------------------------------------------------------
|
||||
// 0 1 2 3
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | Auth Type | Auth Len | Auth Key ID | Reserved |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | Sequence Number |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | Auth Key/Hash... |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | ... |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
//
|
||||
// From https://tools.ietf.org/rfc/rfc5880.txt
|
||||
const bfdMinimumRecordSizeInBytes int = 24
|
||||
|
||||
// BFDVersion represents the version as decoded from the BFD control message
|
||||
type BFDVersion uint8
|
||||
|
||||
// BFDDiagnostic represents diagnostic infomation about a BFD session
|
||||
type BFDDiagnostic uint8
|
||||
|
||||
// constants that define BFDDiagnostic flags
|
||||
const (
|
||||
BFDDiagnosticNone BFDDiagnostic = 0 // No Diagnostic
|
||||
BFDDiagnosticTimeExpired BFDDiagnostic = 1 // Control Detection Time Expired
|
||||
BFDDiagnosticEchoFailed BFDDiagnostic = 2 // Echo Function Failed
|
||||
BFDDiagnosticNeighborSignalDown BFDDiagnostic = 3 // Neighbor Signaled Session Down
|
||||
BFDDiagnosticForwardPlaneReset BFDDiagnostic = 4 // Forwarding Plane Reset
|
||||
BFDDiagnosticPathDown BFDDiagnostic = 5 // Path Down
|
||||
BFDDiagnosticConcatPathDown BFDDiagnostic = 6 // Concatenated Path Down
|
||||
BFDDiagnosticAdminDown BFDDiagnostic = 7 // Administratively Down
|
||||
BFDDiagnosticRevConcatPathDown BFDDiagnostic = 8 // Reverse Concatenated Path Dow
|
||||
)
|
||||
|
||||
// String returns a string version of BFDDiagnostic
|
||||
func (bd BFDDiagnostic) String() string {
|
||||
switch bd {
|
||||
default:
|
||||
return "Unknown"
|
||||
case BFDDiagnosticNone:
|
||||
return "None"
|
||||
case BFDDiagnosticTimeExpired:
|
||||
return "Control Detection Time Expired"
|
||||
case BFDDiagnosticEchoFailed:
|
||||
return "Echo Function Failed"
|
||||
case BFDDiagnosticNeighborSignalDown:
|
||||
return "Neighbor Signaled Session Down"
|
||||
case BFDDiagnosticForwardPlaneReset:
|
||||
return "Forwarding Plane Reset"
|
||||
case BFDDiagnosticPathDown:
|
||||
return "Path Down"
|
||||
case BFDDiagnosticConcatPathDown:
|
||||
return "Concatenated Path Down"
|
||||
case BFDDiagnosticAdminDown:
|
||||
return "Administratively Down"
|
||||
case BFDDiagnosticRevConcatPathDown:
|
||||
return "Reverse Concatenated Path Down"
|
||||
}
|
||||
}
|
||||
|
||||
// BFDState represents the state of a BFD session
|
||||
type BFDState uint8
|
||||
|
||||
// constants that define BFDState
|
||||
const (
|
||||
BFDStateAdminDown BFDState = 0
|
||||
BFDStateDown BFDState = 1
|
||||
BFDStateInit BFDState = 2
|
||||
BFDStateUp BFDState = 3
|
||||
)
|
||||
|
||||
// String returns a string version of BFDState
|
||||
func (s BFDState) String() string {
|
||||
switch s {
|
||||
default:
|
||||
return "Unknown"
|
||||
case BFDStateAdminDown:
|
||||
return "Admin Down"
|
||||
case BFDStateDown:
|
||||
return "Down"
|
||||
case BFDStateInit:
|
||||
return "Init"
|
||||
case BFDStateUp:
|
||||
return "Up"
|
||||
}
|
||||
}
|
||||
|
||||
// BFDDetectMultiplier represents the negotiated transmit interval,
|
||||
// multiplied by this value, provides the Detection Time for the
|
||||
// receiving system in Asynchronous mode.
|
||||
type BFDDetectMultiplier uint8
|
||||
|
||||
// BFDDiscriminator is a unique, nonzero discriminator value used
|
||||
// to demultiplex multiple BFD sessions between the same pair of systems.
|
||||
type BFDDiscriminator uint32
|
||||
|
||||
// BFDTimeInterval represents a time interval in microseconds
|
||||
type BFDTimeInterval uint32
|
||||
|
||||
// BFDAuthType represents the authentication used in the BFD session
|
||||
type BFDAuthType uint8
|
||||
|
||||
// constants that define the BFDAuthType
|
||||
const (
|
||||
BFDAuthTypeNone BFDAuthType = 0 // No Auth
|
||||
BFDAuthTypePassword BFDAuthType = 1 // Simple Password
|
||||
BFDAuthTypeKeyedMD5 BFDAuthType = 2 // Keyed MD5
|
||||
BFDAuthTypeMeticulousKeyedMD5 BFDAuthType = 3 // Meticulous Keyed MD5
|
||||
BFDAuthTypeKeyedSHA1 BFDAuthType = 4 // Keyed SHA1
|
||||
BFDAuthTypeMeticulousKeyedSHA1 BFDAuthType = 5 // Meticulous Keyed SHA1
|
||||
)
|
||||
|
||||
// String returns a string version of BFDAuthType
|
||||
func (at BFDAuthType) String() string {
|
||||
switch at {
|
||||
default:
|
||||
return "Unknown"
|
||||
case BFDAuthTypeNone:
|
||||
return "No Authentication"
|
||||
case BFDAuthTypePassword:
|
||||
return "Simple Password"
|
||||
case BFDAuthTypeKeyedMD5:
|
||||
return "Keyed MD5"
|
||||
case BFDAuthTypeMeticulousKeyedMD5:
|
||||
return "Meticulous Keyed MD5"
|
||||
case BFDAuthTypeKeyedSHA1:
|
||||
return "Keyed SHA1"
|
||||
case BFDAuthTypeMeticulousKeyedSHA1:
|
||||
return "Meticulous Keyed SHA1"
|
||||
}
|
||||
}
|
||||
|
||||
// BFDAuthKeyID represents the authentication key ID in use for
|
||||
// this packet. This allows multiple keys to be active simultaneously.
|
||||
type BFDAuthKeyID uint8
|
||||
|
||||
// BFDAuthSequenceNumber represents the sequence number for this packet.
|
||||
// For Keyed Authentication, this value is incremented occasionally. For
|
||||
// Meticulous Keyed Authentication, this value is incremented for each
|
||||
// successive packet transmitted for a session. This provides protection
|
||||
// against replay attacks.
|
||||
type BFDAuthSequenceNumber uint32
|
||||
|
||||
// BFDAuthData represents the authentication key or digest
|
||||
type BFDAuthData []byte
|
||||
|
||||
// BFDAuthHeader represents authentication data used in the BFD session
|
||||
type BFDAuthHeader struct {
|
||||
AuthType BFDAuthType
|
||||
KeyID BFDAuthKeyID
|
||||
SequenceNumber BFDAuthSequenceNumber
|
||||
Data BFDAuthData
|
||||
}
|
||||
|
||||
// Length returns the data length of the BFDAuthHeader based on the
|
||||
// authentication type
|
||||
func (h *BFDAuthHeader) Length() int {
|
||||
switch h.AuthType {
|
||||
case BFDAuthTypePassword:
|
||||
return 3 + len(h.Data)
|
||||
case BFDAuthTypeKeyedMD5, BFDAuthTypeMeticulousKeyedMD5:
|
||||
return 8 + len(h.Data)
|
||||
case BFDAuthTypeKeyedSHA1, BFDAuthTypeMeticulousKeyedSHA1:
|
||||
return 8 + len(h.Data)
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
// BFD represents a BFD control message packet whose payload contains
|
||||
// the control information required to for a BFD session.
|
||||
//
|
||||
// References
|
||||
// ----------
|
||||
//
|
||||
// Wikipedia's BFD entry:
|
||||
// https://en.wikipedia.org/wiki/Bidirectional_Forwarding_Detection
|
||||
// This is the best place to get an overview of BFD.
|
||||
//
|
||||
// RFC 5880 "Bidirectional Forwarding Detection (BFD)" (2010)
|
||||
// https://tools.ietf.org/html/rfc5880
|
||||
// This is the original BFD specification.
|
||||
//
|
||||
// RFC 5881 "Bidirectional Forwarding Detection (BFD) for IPv4 and IPv6 (Single Hop)" (2010)
|
||||
// https://tools.ietf.org/html/rfc5881
|
||||
// Describes the use of the Bidirectional Forwarding Detection (BFD)
|
||||
// protocol over IPv4 and IPv6 for single IP hops.
|
||||
type BFD struct {
|
||||
BaseLayer // Stores the packet bytes and payload bytes.
|
||||
|
||||
Version BFDVersion // Version of the BFD protocol.
|
||||
Diagnostic BFDDiagnostic // Diagnostic code for last state change
|
||||
State BFDState // Current state
|
||||
Poll bool // Requesting verification
|
||||
Final bool // Responding to a received BFD Control packet that had the Poll (P) bit set.
|
||||
ControlPlaneIndependent bool // BFD implementation does not share fate with its control plane
|
||||
AuthPresent bool // Authentication Section is present and the session is to be authenticated
|
||||
Demand bool // Demand mode is active
|
||||
Multipoint bool // For future point-to-multipoint extensions. Must always be zero
|
||||
DetectMultiplier BFDDetectMultiplier // Detection time multiplier
|
||||
MyDiscriminator BFDDiscriminator // A unique, nonzero discriminator value
|
||||
YourDiscriminator BFDDiscriminator // discriminator received from the remote system.
|
||||
DesiredMinTxInterval BFDTimeInterval // Minimum interval, in microseconds, the local system would like to use when transmitting BFD Control packets
|
||||
RequiredMinRxInterval BFDTimeInterval // Minimum interval, in microseconds, between received BFD Control packets that this system is capable of supporting
|
||||
RequiredMinEchoRxInterval BFDTimeInterval // Minimum interval, in microseconds, between received BFD Echo packets that this system is capable of supporting
|
||||
AuthHeader *BFDAuthHeader // Authentication data, variable length.
|
||||
}
|
||||
|
||||
// Length returns the data length of a BFD Control message which
|
||||
// changes based on the presence and type of authentication
|
||||
// contained in the message
|
||||
func (d *BFD) Length() int {
|
||||
if d.AuthPresent && (d.AuthHeader != nil) {
|
||||
return bfdMinimumRecordSizeInBytes + d.AuthHeader.Length()
|
||||
}
|
||||
|
||||
return bfdMinimumRecordSizeInBytes
|
||||
}
|
||||
|
||||
// LayerType returns the layer type of the BFD object, which is LayerTypeBFD.
|
||||
func (d *BFD) LayerType() gopacket.LayerType {
|
||||
return LayerTypeBFD
|
||||
}
|
||||
|
||||
// decodeBFD analyses a byte slice and attempts to decode it as a BFD
|
||||
// control packet
|
||||
//
|
||||
// If it succeeds, it loads p with information about the packet and returns nil.
|
||||
// If it fails, it returns an error (non nil).
|
||||
//
|
||||
// This function is employed in layertypes.go to register the BFD layer.
|
||||
func decodeBFD(data []byte, p gopacket.PacketBuilder) error {
|
||||
|
||||
// Attempt to decode the byte slice.
|
||||
d := &BFD{}
|
||||
err := d.DecodeFromBytes(data, p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If the decoding worked, add the layer to the packet and set it
|
||||
// as the application layer too, if there isn't already one.
|
||||
p.AddLayer(d)
|
||||
p.SetApplicationLayer(d)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DecodeFromBytes analyses a byte slice and attempts to decode it as a BFD
|
||||
// control packet.
|
||||
//
|
||||
// Upon succeeds, it loads the BFD object with information about the packet
|
||||
// and returns nil.
|
||||
// Upon failure, it returns an error (non nil).
|
||||
func (d *BFD) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||||
|
||||
// If the data block is too short to be a BFD record, then return an error.
|
||||
if len(data) < bfdMinimumRecordSizeInBytes {
|
||||
df.SetTruncated()
|
||||
return errors.New("BFD packet too short")
|
||||
}
|
||||
|
||||
pLen := uint8(data[3])
|
||||
if len(data) != int(pLen) {
|
||||
return errors.New("BFD packet length does not match")
|
||||
}
|
||||
|
||||
// BFD type embeds type BaseLayer which contains two fields:
|
||||
// Contents is supposed to contain the bytes of the data at this level.
|
||||
// Payload is supposed to contain the payload of this level.
|
||||
// Here we set the baselayer to be the bytes of the BFD record.
|
||||
d.BaseLayer = BaseLayer{Contents: data[:len(data)]}
|
||||
|
||||
// Extract the fields from the block of bytes.
|
||||
// To make sense of this, refer to the packet diagram
|
||||
// above and the section on endian conventions.
|
||||
|
||||
// The first few fields are all packed into the first 32 bits. Unpack them.
|
||||
d.Version = BFDVersion(((data[0] & 0xE0) >> 5))
|
||||
d.Diagnostic = BFDDiagnostic(data[0] & 0x1F)
|
||||
data = data[1:]
|
||||
|
||||
d.State = BFDState((data[0] & 0xC0) >> 6)
|
||||
d.Poll = data[0]&0x20 != 0
|
||||
d.Final = data[0]&0x10 != 0
|
||||
d.ControlPlaneIndependent = data[0]&0x08 != 0
|
||||
d.AuthPresent = data[0]&0x04 != 0
|
||||
d.Demand = data[0]&0x02 != 0
|
||||
d.Multipoint = data[0]&0x01 != 0
|
||||
data = data[1:]
|
||||
|
||||
data, d.DetectMultiplier = data[1:], BFDDetectMultiplier(data[0])
|
||||
data, _ = data[1:], uint8(data[0]) // Consume length
|
||||
|
||||
// The remaining fields can just be copied in big endian order.
|
||||
data, d.MyDiscriminator = data[4:], BFDDiscriminator(binary.BigEndian.Uint32(data[:4]))
|
||||
data, d.YourDiscriminator = data[4:], BFDDiscriminator(binary.BigEndian.Uint32(data[:4]))
|
||||
data, d.DesiredMinTxInterval = data[4:], BFDTimeInterval(binary.BigEndian.Uint32(data[:4]))
|
||||
data, d.RequiredMinRxInterval = data[4:], BFDTimeInterval(binary.BigEndian.Uint32(data[:4]))
|
||||
data, d.RequiredMinEchoRxInterval = data[4:], BFDTimeInterval(binary.BigEndian.Uint32(data[:4]))
|
||||
|
||||
if d.AuthPresent && (len(data) > 2) {
|
||||
d.AuthHeader = &BFDAuthHeader{}
|
||||
data, d.AuthHeader.AuthType = data[1:], BFDAuthType(data[0])
|
||||
data, _ = data[1:], uint8(data[0]) // Consume length
|
||||
data, d.AuthHeader.KeyID = data[1:], BFDAuthKeyID(data[0])
|
||||
|
||||
switch d.AuthHeader.AuthType {
|
||||
case BFDAuthTypePassword:
|
||||
d.AuthHeader.Data = BFDAuthData(data)
|
||||
case BFDAuthTypeKeyedMD5, BFDAuthTypeMeticulousKeyedMD5:
|
||||
// Skipped reserved byte
|
||||
data, d.AuthHeader.SequenceNumber = data[5:], BFDAuthSequenceNumber(binary.BigEndian.Uint32(data[1:5]))
|
||||
d.AuthHeader.Data = BFDAuthData(data)
|
||||
case BFDAuthTypeKeyedSHA1, BFDAuthTypeMeticulousKeyedSHA1:
|
||||
// Skipped reserved byte
|
||||
data, d.AuthHeader.SequenceNumber = data[5:], BFDAuthSequenceNumber(binary.BigEndian.Uint32(data[1:5]))
|
||||
d.AuthHeader.Data = BFDAuthData(data)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SerializeTo writes the serialized form of this layer into the
|
||||
// SerializationBuffer, implementing gopacket.SerializableLayer.
|
||||
// See the docs for gopacket.SerializableLayer for more info.
|
||||
func (d *BFD) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
|
||||
data, err := b.PrependBytes(bfdMinimumRecordSizeInBytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Pack the first few fields into the first 32 bits.
|
||||
data[0] = byte(byte(d.Version<<5) | byte(d.Diagnostic))
|
||||
h := uint8(0)
|
||||
h |= (uint8(d.State) << 6)
|
||||
h |= (uint8(bool2uint8(d.Poll)) << 5)
|
||||
h |= (uint8(bool2uint8(d.Final)) << 4)
|
||||
h |= (uint8(bool2uint8(d.ControlPlaneIndependent)) << 3)
|
||||
h |= (uint8(bool2uint8(d.AuthPresent)) << 2)
|
||||
h |= (uint8(bool2uint8(d.Demand)) << 1)
|
||||
h |= uint8(bool2uint8(d.Multipoint))
|
||||
data[1] = byte(h)
|
||||
data[2] = byte(d.DetectMultiplier)
|
||||
data[3] = byte(d.Length())
|
||||
|
||||
// The remaining fields can just be copied in big endian order.
|
||||
binary.BigEndian.PutUint32(data[4:], uint32(d.MyDiscriminator))
|
||||
binary.BigEndian.PutUint32(data[8:], uint32(d.YourDiscriminator))
|
||||
binary.BigEndian.PutUint32(data[12:], uint32(d.DesiredMinTxInterval))
|
||||
binary.BigEndian.PutUint32(data[16:], uint32(d.RequiredMinRxInterval))
|
||||
binary.BigEndian.PutUint32(data[20:], uint32(d.RequiredMinEchoRxInterval))
|
||||
|
||||
if d.AuthPresent && (d.AuthHeader != nil) {
|
||||
auth, err := b.AppendBytes(int(d.AuthHeader.Length()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
auth[0] = byte(d.AuthHeader.AuthType)
|
||||
auth[1] = byte(d.AuthHeader.Length())
|
||||
auth[2] = byte(d.AuthHeader.KeyID)
|
||||
|
||||
switch d.AuthHeader.AuthType {
|
||||
case BFDAuthTypePassword:
|
||||
copy(auth[3:], d.AuthHeader.Data)
|
||||
case BFDAuthTypeKeyedMD5, BFDAuthTypeMeticulousKeyedMD5:
|
||||
auth[3] = byte(0)
|
||||
binary.BigEndian.PutUint32(auth[4:], uint32(d.AuthHeader.SequenceNumber))
|
||||
copy(auth[8:], d.AuthHeader.Data)
|
||||
case BFDAuthTypeKeyedSHA1, BFDAuthTypeMeticulousKeyedSHA1:
|
||||
auth[3] = byte(0)
|
||||
binary.BigEndian.PutUint32(auth[4:], uint32(d.AuthHeader.SequenceNumber))
|
||||
copy(auth[8:], d.AuthHeader.Data)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CanDecode returns a set of layers that BFD objects can decode.
|
||||
// As BFD objects can only decide the BFD layer, we can return just that layer.
|
||||
// Apparently a single layer type implements LayerClass.
|
||||
func (d *BFD) CanDecode() gopacket.LayerClass {
|
||||
return LayerTypeBFD
|
||||
}
|
||||
|
||||
// NextLayerType specifies the next layer that GoPacket should attempt to
|
||||
// analyse after this (BFD) layer. As BFD packets do not contain any payload
|
||||
// bytes, there are no further layers to analyse.
|
||||
func (d *BFD) NextLayerType() gopacket.LayerType {
|
||||
return gopacket.LayerTypeZero
|
||||
}
|
||||
|
||||
// Payload returns an empty byte slice as BFD packets do not carry a payload
|
||||
func (d *BFD) Payload() []byte {
|
||||
return nil
|
||||
}
|
||||
|
||||
// bool2uint8 converts a bool to uint8
|
||||
func bool2uint8(b bool) uint8 {
|
||||
if b {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
+25
-11
@@ -9,7 +9,6 @@ package layers
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
@@ -125,6 +124,7 @@ func (d *DHCPv4) LayerType() gopacket.LayerType { return LayerTypeDHCPv4 }
|
||||
|
||||
// DecodeFromBytes decodes the given bytes into this layer.
|
||||
func (d *DHCPv4) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||||
d.Options = d.Options[:0]
|
||||
d.Operation = DHCPOp(data[0])
|
||||
d.HardwareType = LinkType(data[1])
|
||||
d.HardwareLen = data[2]
|
||||
@@ -140,7 +140,7 @@ func (d *DHCPv4) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error
|
||||
d.ServerName = data[44:108]
|
||||
d.File = data[108:236]
|
||||
if binary.BigEndian.Uint32(data[236:240]) != DHCPMagic {
|
||||
return errors.New("Bad DHCP header")
|
||||
return InvalidMagicCookie
|
||||
}
|
||||
|
||||
if len(data) <= 240 {
|
||||
@@ -538,9 +538,6 @@ func (o *DHCPOption) encode(b []byte) error {
|
||||
case DHCPOptPad, DHCPOptEnd:
|
||||
b[0] = byte(o.Type)
|
||||
default:
|
||||
if o.Length > 253 {
|
||||
return errors.New("data too long to encode")
|
||||
}
|
||||
b[0] = byte(o.Type)
|
||||
b[1] = o.Length
|
||||
copy(b[2:], o.Data)
|
||||
@@ -551,21 +548,38 @@ func (o *DHCPOption) encode(b []byte) error {
|
||||
func (o *DHCPOption) decode(data []byte) error {
|
||||
if len(data) < 1 {
|
||||
// Pad/End have a length of 1
|
||||
return errors.New("Not enough data to decode")
|
||||
return DecOptionNotEnoughData
|
||||
}
|
||||
o.Type = DHCPOpt(data[0])
|
||||
switch o.Type {
|
||||
case DHCPOptPad, DHCPOptEnd:
|
||||
o.Data = nil
|
||||
default:
|
||||
if len(data) < 3 {
|
||||
return errors.New("Not enough data to decode")
|
||||
if len(data) < 2 {
|
||||
return DecOptionNotEnoughData
|
||||
}
|
||||
o.Length = data[1]
|
||||
if o.Length > 253 {
|
||||
return errors.New("data too long to decode")
|
||||
if int(o.Length) > len(data[2:]) {
|
||||
return DecOptionMalformed
|
||||
}
|
||||
o.Data = data[2 : 2+o.Length]
|
||||
o.Data = data[2 : 2+int(o.Length)]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DHCPv4Error is used for constant errors for DHCPv4. It is needed for test asserts.
|
||||
type DHCPv4Error string
|
||||
|
||||
// DHCPv4Error implements error interface.
|
||||
func (d DHCPv4Error) Error() string {
|
||||
return string(d)
|
||||
}
|
||||
|
||||
const (
|
||||
// DecOptionNotEnoughData is returned when there is not enough data during option's decode process
|
||||
DecOptionNotEnoughData = DHCPv4Error("Not enough data to decode")
|
||||
// DecOptionMalformed is returned when the option is malformed
|
||||
DecOptionMalformed = DHCPv4Error("Option is malformed")
|
||||
// InvalidMagicCookie is returned when Magic cookie is missing into BOOTP header
|
||||
InvalidMagicCookie = DHCPv4Error("Bad DHCP header")
|
||||
)
|
||||
+341
@@ -0,0 +1,341 @@
|
||||
// Copyright 2018 Google, Inc. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the LICENSE file in the root of the source
|
||||
// tree.
|
||||
|
||||
package layers
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/google/gopacket"
|
||||
)
|
||||
|
||||
// DHCPv6MsgType represents a DHCPv6 operation
|
||||
type DHCPv6MsgType byte
|
||||
|
||||
// Constants that represent DHCP operations
|
||||
const (
|
||||
DHCPv6MsgTypeUnspecified DHCPv6MsgType = iota
|
||||
DHCPv6MsgTypeSolicit
|
||||
DHCPv6MsgTypeAdverstise
|
||||
DHCPv6MsgTypeRequest
|
||||
DHCPv6MsgTypeConfirm
|
||||
DHCPv6MsgTypeRenew
|
||||
DHCPv6MsgTypeRebind
|
||||
DHCPv6MsgTypeReply
|
||||
DHCPv6MsgTypeRelease
|
||||
DHCPv6MsgTypeDecline
|
||||
DHCPv6MsgTypeReconfigure
|
||||
DHCPv6MsgTypeInformationRequest
|
||||
DHCPv6MsgTypeRelayForward
|
||||
DHCPv6MsgTypeRelayReply
|
||||
)
|
||||
|
||||
// String returns a string version of a DHCPv6MsgType.
|
||||
func (o DHCPv6MsgType) String() string {
|
||||
switch o {
|
||||
case DHCPv6MsgTypeUnspecified:
|
||||
return "Unspecified"
|
||||
case DHCPv6MsgTypeSolicit:
|
||||
return "Solicit"
|
||||
case DHCPv6MsgTypeAdverstise:
|
||||
return "Adverstise"
|
||||
case DHCPv6MsgTypeRequest:
|
||||
return "Request"
|
||||
case DHCPv6MsgTypeConfirm:
|
||||
return "Confirm"
|
||||
case DHCPv6MsgTypeRenew:
|
||||
return "Renew"
|
||||
case DHCPv6MsgTypeRebind:
|
||||
return "Rebind"
|
||||
case DHCPv6MsgTypeReply:
|
||||
return "Reply"
|
||||
case DHCPv6MsgTypeRelease:
|
||||
return "Release"
|
||||
case DHCPv6MsgTypeDecline:
|
||||
return "Decline"
|
||||
case DHCPv6MsgTypeReconfigure:
|
||||
return "Reconfigure"
|
||||
case DHCPv6MsgTypeInformationRequest:
|
||||
return "InformationRequest"
|
||||
case DHCPv6MsgTypeRelayForward:
|
||||
return "RelayForward"
|
||||
case DHCPv6MsgTypeRelayReply:
|
||||
return "RelayReply"
|
||||
default:
|
||||
return "Unknown"
|
||||
}
|
||||
}
|
||||
|
||||
// DHCPv6 contains data for a single DHCP packet.
|
||||
type DHCPv6 struct {
|
||||
BaseLayer
|
||||
MsgType DHCPv6MsgType
|
||||
HopCount uint8
|
||||
LinkAddr net.IP
|
||||
PeerAddr net.IP
|
||||
TransactionID []byte
|
||||
Options DHCPv6Options
|
||||
}
|
||||
|
||||
// LayerType returns gopacket.LayerTypeDHCPv6
|
||||
func (d *DHCPv6) LayerType() gopacket.LayerType { return LayerTypeDHCPv6 }
|
||||
|
||||
// DecodeFromBytes decodes the given bytes into this layer.
|
||||
func (d *DHCPv6) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||||
d.BaseLayer = BaseLayer{Contents: data}
|
||||
d.Options = d.Options[:0]
|
||||
d.MsgType = DHCPv6MsgType(data[0])
|
||||
|
||||
offset := 0
|
||||
if d.MsgType == DHCPv6MsgTypeRelayForward || d.MsgType == DHCPv6MsgTypeRelayReply {
|
||||
d.HopCount = data[1]
|
||||
d.LinkAddr = net.IP(data[2:18])
|
||||
d.PeerAddr = net.IP(data[18:34])
|
||||
offset = 34
|
||||
} else {
|
||||
d.TransactionID = data[1:4]
|
||||
offset = 4
|
||||
}
|
||||
|
||||
stop := len(data)
|
||||
for offset < stop {
|
||||
o := DHCPv6Option{}
|
||||
if err := o.decode(data[offset:]); err != nil {
|
||||
return err
|
||||
}
|
||||
d.Options = append(d.Options, o)
|
||||
offset += int(o.Length) + 4 // 2 from option code, 2 from option length
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Len returns the length of a DHCPv6 packet.
|
||||
func (d *DHCPv6) Len() int {
|
||||
n := 1
|
||||
if d.MsgType == DHCPv6MsgTypeRelayForward || d.MsgType == DHCPv6MsgTypeRelayReply {
|
||||
n += 33
|
||||
} else {
|
||||
n += 3
|
||||
}
|
||||
|
||||
for _, o := range d.Options {
|
||||
n += int(o.Length) + 4 // 2 from option code, 2 from option length
|
||||
}
|
||||
|
||||
return n
|
||||
}
|
||||
|
||||
// SerializeTo writes the serialized form of this layer into the
|
||||
// SerializationBuffer, implementing gopacket.SerializableLayer.
|
||||
// See the docs for gopacket.SerializableLayer for more info.
|
||||
func (d *DHCPv6) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
|
||||
plen := int(d.Len())
|
||||
|
||||
data, err := b.PrependBytes(plen)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
offset := 0
|
||||
data[0] = byte(d.MsgType)
|
||||
if d.MsgType == DHCPv6MsgTypeRelayForward || d.MsgType == DHCPv6MsgTypeRelayReply {
|
||||
data[1] = byte(d.HopCount)
|
||||
copy(data[2:18], d.LinkAddr.To16())
|
||||
copy(data[18:34], d.PeerAddr.To16())
|
||||
offset = 34
|
||||
} else {
|
||||
copy(data[1:4], d.TransactionID)
|
||||
offset = 4
|
||||
}
|
||||
|
||||
if len(d.Options) > 0 {
|
||||
for _, o := range d.Options {
|
||||
if err := o.encode(data[offset:], opts); err != nil {
|
||||
return err
|
||||
}
|
||||
offset += int(o.Length) + 4 // 2 from option code, 2 from option length
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CanDecode returns the set of layer types that this DecodingLayer can decode.
|
||||
func (d *DHCPv6) CanDecode() gopacket.LayerClass {
|
||||
return LayerTypeDHCPv6
|
||||
}
|
||||
|
||||
// NextLayerType returns the layer type contained by this DecodingLayer.
|
||||
func (d *DHCPv6) NextLayerType() gopacket.LayerType {
|
||||
return gopacket.LayerTypePayload
|
||||
}
|
||||
|
||||
func decodeDHCPv6(data []byte, p gopacket.PacketBuilder) error {
|
||||
dhcp := &DHCPv6{}
|
||||
err := dhcp.DecodeFromBytes(data, p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.AddLayer(dhcp)
|
||||
return p.NextDecoder(gopacket.LayerTypePayload)
|
||||
}
|
||||
|
||||
// DHCPv6StatusCode represents a DHCP status code - RFC-3315
|
||||
type DHCPv6StatusCode uint16
|
||||
|
||||
// Constants for the DHCPv6StatusCode.
|
||||
const (
|
||||
DHCPv6StatusCodeSuccess DHCPv6StatusCode = iota
|
||||
DHCPv6StatusCodeUnspecFail
|
||||
DHCPv6StatusCodeNoAddrsAvail
|
||||
DHCPv6StatusCodeNoBinding
|
||||
DHCPv6StatusCodeNotOnLink
|
||||
DHCPv6StatusCodeUseMulticast
|
||||
)
|
||||
|
||||
// String returns a string version of a DHCPv6StatusCode.
|
||||
func (o DHCPv6StatusCode) String() string {
|
||||
switch o {
|
||||
case DHCPv6StatusCodeSuccess:
|
||||
return "Success"
|
||||
case DHCPv6StatusCodeUnspecFail:
|
||||
return "UnspecifiedFailure"
|
||||
case DHCPv6StatusCodeNoAddrsAvail:
|
||||
return "NoAddressAvailable"
|
||||
case DHCPv6StatusCodeNoBinding:
|
||||
return "NoBinding"
|
||||
case DHCPv6StatusCodeNotOnLink:
|
||||
return "NotOnLink"
|
||||
case DHCPv6StatusCodeUseMulticast:
|
||||
return "UseMulticast"
|
||||
default:
|
||||
return "Unknown"
|
||||
}
|
||||
}
|
||||
|
||||
// DHCPv6DUIDType represents a DHCP DUID - RFC-3315
|
||||
type DHCPv6DUIDType uint16
|
||||
|
||||
// Constants for the DHCPv6DUIDType.
|
||||
const (
|
||||
DHCPv6DUIDTypeLLT DHCPv6DUIDType = iota + 1
|
||||
DHCPv6DUIDTypeEN
|
||||
DHCPv6DUIDTypeLL
|
||||
)
|
||||
|
||||
// String returns a string version of a DHCPv6DUIDType.
|
||||
func (o DHCPv6DUIDType) String() string {
|
||||
switch o {
|
||||
case DHCPv6DUIDTypeLLT:
|
||||
return "LLT"
|
||||
case DHCPv6DUIDTypeEN:
|
||||
return "EN"
|
||||
case DHCPv6DUIDTypeLL:
|
||||
return "LL"
|
||||
default:
|
||||
return "Unknown"
|
||||
}
|
||||
}
|
||||
|
||||
// DHCPv6DUID means DHCP Unique Identifier as stated in RFC 3315, section 9 (https://tools.ietf.org/html/rfc3315#page-19)
|
||||
type DHCPv6DUID struct {
|
||||
Type DHCPv6DUIDType
|
||||
// LLT, LL
|
||||
HardwareType []byte
|
||||
// EN
|
||||
EnterpriseNumber []byte
|
||||
// LLT
|
||||
Time []byte
|
||||
// LLT, LL
|
||||
LinkLayerAddress net.HardwareAddr
|
||||
// EN
|
||||
Identifier []byte
|
||||
}
|
||||
|
||||
// DecodeFromBytes decodes the given bytes into a DHCPv6DUID
|
||||
func (d *DHCPv6DUID) DecodeFromBytes(data []byte) error {
|
||||
if len(data) < 2 {
|
||||
return errors.New("Not enough bytes to decode: " + string(len(data)))
|
||||
}
|
||||
|
||||
d.Type = DHCPv6DUIDType(binary.BigEndian.Uint16(data[:2]))
|
||||
if d.Type == DHCPv6DUIDTypeLLT || d.Type == DHCPv6DUIDTypeLL {
|
||||
d.HardwareType = data[2:4]
|
||||
}
|
||||
|
||||
if d.Type == DHCPv6DUIDTypeLLT {
|
||||
d.Time = data[4:8]
|
||||
d.LinkLayerAddress = net.HardwareAddr(data[8:])
|
||||
} else if d.Type == DHCPv6DUIDTypeEN {
|
||||
d.EnterpriseNumber = data[2:6]
|
||||
d.Identifier = data[6:]
|
||||
} else { // DHCPv6DUIDTypeLL
|
||||
d.LinkLayerAddress = net.HardwareAddr(data[4:])
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Encode encodes the DHCPv6DUID in a slice of bytes
|
||||
func (d *DHCPv6DUID) Encode() []byte {
|
||||
length := d.Len()
|
||||
data := make([]byte, length)
|
||||
binary.BigEndian.PutUint16(data[0:2], uint16(d.Type))
|
||||
|
||||
if d.Type == DHCPv6DUIDTypeLLT || d.Type == DHCPv6DUIDTypeLL {
|
||||
copy(data[2:4], d.HardwareType)
|
||||
}
|
||||
|
||||
if d.Type == DHCPv6DUIDTypeLLT {
|
||||
copy(data[4:8], d.Time)
|
||||
copy(data[8:], d.LinkLayerAddress)
|
||||
} else if d.Type == DHCPv6DUIDTypeEN {
|
||||
copy(data[2:6], d.EnterpriseNumber)
|
||||
copy(data[6:], d.Identifier)
|
||||
} else {
|
||||
copy(data[4:], d.LinkLayerAddress)
|
||||
}
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
// Len returns the length of the DHCPv6DUID, respecting the type
|
||||
func (d *DHCPv6DUID) Len() int {
|
||||
length := 2 // d.Type
|
||||
if d.Type == DHCPv6DUIDTypeLLT {
|
||||
length += 2 /*HardwareType*/ + 4 /*d.Time*/ + len(d.LinkLayerAddress)
|
||||
} else if d.Type == DHCPv6DUIDTypeEN {
|
||||
length += 4 /*d.EnterpriseNumber*/ + len(d.Identifier)
|
||||
} else { // LL
|
||||
length += 2 /*d.HardwareType*/ + len(d.LinkLayerAddress)
|
||||
}
|
||||
|
||||
return length
|
||||
}
|
||||
|
||||
func (d *DHCPv6DUID) String() string {
|
||||
duid := "Type: " + d.Type.String() + ", "
|
||||
if d.Type == DHCPv6DUIDTypeLLT {
|
||||
duid += fmt.Sprintf("HardwareType: %v, Time: %v, LinkLayerAddress: %v", d.HardwareType, d.Time, d.LinkLayerAddress)
|
||||
} else if d.Type == DHCPv6DUIDTypeEN {
|
||||
duid += fmt.Sprintf("EnterpriseNumber: %v, Identifier: %v", d.EnterpriseNumber, d.Identifier)
|
||||
} else { // DHCPv6DUIDTypeLL
|
||||
duid += fmt.Sprintf("HardwareType: %v, LinkLayerAddress: %v", d.HardwareType, d.LinkLayerAddress)
|
||||
}
|
||||
return duid
|
||||
}
|
||||
|
||||
func decodeDHCPv6DUID(data []byte) (*DHCPv6DUID, error) {
|
||||
duid := &DHCPv6DUID{}
|
||||
err := duid.DecodeFromBytes(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return duid, nil
|
||||
}
|
||||
+621
@@ -0,0 +1,621 @@
|
||||
// Copyright 2018 The GoPacket Authors. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the LICENSE file in the root of the source
|
||||
// tree.
|
||||
|
||||
package layers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/google/gopacket"
|
||||
)
|
||||
|
||||
// DHCPv6Opt represents a DHCP option or parameter from RFC-3315
|
||||
type DHCPv6Opt uint16
|
||||
|
||||
// Constants for the DHCPv6Opt options.
|
||||
const (
|
||||
DHCPv6OptClientID DHCPv6Opt = 1
|
||||
DHCPv6OptServerID DHCPv6Opt = 2
|
||||
DHCPv6OptIANA DHCPv6Opt = 3
|
||||
DHCPv6OptIATA DHCPv6Opt = 4
|
||||
DHCPv6OptIAAddr DHCPv6Opt = 5
|
||||
DHCPv6OptOro DHCPv6Opt = 6
|
||||
DHCPv6OptPreference DHCPv6Opt = 7
|
||||
DHCPv6OptElapsedTime DHCPv6Opt = 8
|
||||
DHCPv6OptRelayMessage DHCPv6Opt = 9
|
||||
DHCPv6OptAuth DHCPv6Opt = 11
|
||||
DHCPv6OptUnicast DHCPv6Opt = 12
|
||||
DHCPv6OptStatusCode DHCPv6Opt = 13
|
||||
DHCPv6OptRapidCommit DHCPv6Opt = 14
|
||||
DHCPv6OptUserClass DHCPv6Opt = 15
|
||||
DHCPv6OptVendorClass DHCPv6Opt = 16
|
||||
DHCPv6OptVendorOpts DHCPv6Opt = 17
|
||||
DHCPv6OptInterfaceID DHCPv6Opt = 18
|
||||
DHCPv6OptReconfigureMessage DHCPv6Opt = 19
|
||||
DHCPv6OptReconfigureAccept DHCPv6Opt = 20
|
||||
|
||||
// RFC 3319 Session Initiation Protocol (SIP)
|
||||
DHCPv6OptSIPServersDomainList DHCPv6Opt = 21
|
||||
DHCPv6OptSIPServersAddressList DHCPv6Opt = 22
|
||||
|
||||
// RFC 3646 DNS Configuration
|
||||
DHCPv6OptDNSServers DHCPv6Opt = 23
|
||||
DHCPv6OptDomainList DHCPv6Opt = 24
|
||||
|
||||
// RFC 3633 Prefix Delegation
|
||||
DHCPv6OptIAPD DHCPv6Opt = 25
|
||||
DHCPv6OptIAPrefix DHCPv6Opt = 26
|
||||
|
||||
// RFC 3898 Network Information Service (NIS)
|
||||
DHCPv6OptNISServers DHCPv6Opt = 27
|
||||
DHCPv6OptNISPServers DHCPv6Opt = 28
|
||||
DHCPv6OptNISDomainName DHCPv6Opt = 29
|
||||
DHCPv6OptNISPDomainName DHCPv6Opt = 30
|
||||
|
||||
// RFC 4075 Simple Network Time Protocol (SNTP)
|
||||
DHCPv6OptSNTPServers DHCPv6Opt = 31
|
||||
|
||||
// RFC 4242 Information Refresh Time Option
|
||||
DHCPv6OptInformationRefreshTime DHCPv6Opt = 32
|
||||
|
||||
// RFC 4280 Broadcast and Multicast Control Servers
|
||||
DHCPv6OptBCMCSServerDomainNameList DHCPv6Opt = 33
|
||||
DHCPv6OptBCMCSServerAddressList DHCPv6Opt = 34
|
||||
|
||||
// RFC 4776 Civic Address ConfigurationOption
|
||||
DHCPv6OptGeoconfCivic DHCPv6Opt = 36
|
||||
|
||||
// RFC 4649 Relay Agent Remote-ID
|
||||
DHCPv6OptRemoteID DHCPv6Opt = 37
|
||||
|
||||
// RFC 4580 Relay Agent Subscriber-ID
|
||||
DHCPv6OptSubscriberID DHCPv6Opt = 38
|
||||
|
||||
// RFC 4704 Client Full Qualified Domain Name (FQDN)
|
||||
DHCPv6OptClientFQDN DHCPv6Opt = 39
|
||||
|
||||
// RFC 5192 Protocol for Carrying Authentication for Network Access (PANA)
|
||||
DHCPv6OptPanaAgent DHCPv6Opt = 40
|
||||
|
||||
// RFC 4833 Timezone Options
|
||||
DHCPv6OptNewPOSIXTimezone DHCPv6Opt = 41
|
||||
DHCPv6OptNewTZDBTimezone DHCPv6Opt = 42
|
||||
|
||||
// RFC 4994 Relay Agent Echo Request
|
||||
DHCPv6OptEchoRequestOption DHCPv6Opt = 43
|
||||
|
||||
// RFC 5007 Leasequery
|
||||
DHCPv6OptLQQuery DHCPv6Opt = 44
|
||||
DHCPv6OptCLTTime DHCPv6Opt = 45
|
||||
DHCPv6OptClientData DHCPv6Opt = 46
|
||||
DHCPv6OptLQRelayData DHCPv6Opt = 47
|
||||
DHCPv6OptLQClientLink DHCPv6Opt = 48
|
||||
|
||||
// RFC 6610 Home Information Discovery in Mobile IPv6 (MIPv6)
|
||||
DHCPv6OptMIP6HNIDF DHCPv6Opt = 49
|
||||
DHCPv6OptMIP6VDINF DHCPv6Opt = 50
|
||||
DHCPv6OptMIP6IDINF DHCPv6Opt = 69
|
||||
DHCPv6OptMIP6UDINF DHCPv6Opt = 70
|
||||
DHCPv6OptMIP6HNP DHCPv6Opt = 71
|
||||
DHCPv6OptMIP6HAA DHCPv6Opt = 72
|
||||
DHCPv6OptMIP6HAF DHCPv6Opt = 73
|
||||
|
||||
// RFC 5223 Discovering Location-to-Service Translation (LoST) Servers
|
||||
DHCPv6OptV6LOST DHCPv6Opt = 51
|
||||
|
||||
// RFC 5417 Control And Provisioning of Wireless Access Points (CAPWAP)
|
||||
DHCPv6OptCAPWAPACV6 DHCPv6Opt = 52
|
||||
|
||||
// RFC 5460 Bulk Leasequery
|
||||
DHCPv6OptRelayID DHCPv6Opt = 53
|
||||
|
||||
// RFC 5678 IEEE 802.21 Mobility Services (MoS) Discovery
|
||||
DHCPv6OptIPv6AddressMoS DHCPv6Opt = 54
|
||||
DHCPv6OptIPv6FQDNMoS DHCPv6Opt = 55
|
||||
|
||||
// RFC 5908 NTP Server Option
|
||||
DHCPv6OptNTPServer DHCPv6Opt = 56
|
||||
|
||||
// RFC 5986 Discovering the Local Location Information Server (LIS)
|
||||
DHCPv6OptV6AccessDomain DHCPv6Opt = 57
|
||||
|
||||
// RFC 5986 SIP User Agent
|
||||
DHCPv6OptSIPUACSList DHCPv6Opt = 58
|
||||
|
||||
// RFC 5970 Options for Network Boot
|
||||
DHCPv6OptBootFileURL DHCPv6Opt = 59
|
||||
DHCPv6OptBootFileParam DHCPv6Opt = 60
|
||||
DHCPv6OptClientArchType DHCPv6Opt = 61
|
||||
DHCPv6OptNII DHCPv6Opt = 62
|
||||
|
||||
// RFC 6225 Coordinate-Based Location Configuration Information
|
||||
DHCPv6OptGeolocation DHCPv6Opt = 63
|
||||
|
||||
// RFC 6334 Dual-Stack Lite
|
||||
DHCPv6OptAFTRName DHCPv6Opt = 64
|
||||
|
||||
// RFC 6440 EAP Re-authentication Protocol (ERP)
|
||||
DHCPv6OptERPLocalDomainName DHCPv6Opt = 65
|
||||
|
||||
// RFC 6422 Relay-Supplied DHCP Options
|
||||
DHCPv6OptRSOO DHCPv6Opt = 66
|
||||
|
||||
// RFC 6603 Prefix Exclude Option for DHCPv6-based Prefix Delegation
|
||||
DHCPv6OptPDExclude DHCPv6Opt = 67
|
||||
|
||||
// RFC 6607 Virtual Subnet Selection
|
||||
DHCPv6OptVSS DHCPv6Opt = 68
|
||||
|
||||
// RFC 6731 Improved Recursive DNS Server Selection for Multi-Interfaced Nodes
|
||||
DHCPv6OptRDNSSSelection DHCPv6Opt = 74
|
||||
|
||||
// RFC 6784 Kerberos Options for DHCPv6
|
||||
DHCPv6OptKRBPrincipalName DHCPv6Opt = 75
|
||||
DHCPv6OptKRBRealmName DHCPv6Opt = 76
|
||||
DHCPv6OptKRBKDC DHCPv6Opt = 77
|
||||
|
||||
// RFC 6939 Client Link-Layer Address Option
|
||||
DHCPv6OptClientLinkLayerAddress DHCPv6Opt = 79
|
||||
|
||||
// RFC 6977 Triggering DHCPv6 Reconfiguration from Relay Agents
|
||||
DHCPv6OptLinkAddress DHCPv6Opt = 80
|
||||
|
||||
// RFC 7037 RADIUS Option for the DHCPv6 Relay Agent
|
||||
DHCPv6OptRADIUS DHCPv6Opt = 81
|
||||
|
||||
// RFC 7083 Modification to Default Values of SOL_MAX_RT and INF_MAX_RT
|
||||
DHCPv6OptSolMaxRt DHCPv6Opt = 82
|
||||
DHCPv6OptInfMaxRt DHCPv6Opt = 83
|
||||
|
||||
// RFC 7078 Distributing Address Selection Policy
|
||||
DHCPv6OptAddrSel DHCPv6Opt = 84
|
||||
DHCPv6OptAddrSelTable DHCPv6Opt = 85
|
||||
|
||||
// RFC 7291 DHCP Options for the Port Control Protocol (PCP)
|
||||
DHCPv6OptV6PCPServer DHCPv6Opt = 86
|
||||
|
||||
// RFC 7341 DHCPv4-over-DHCPv6 (DHCP 4o6) Transport
|
||||
DHCPv6OptDHCPv4Message DHCPv6Opt = 87
|
||||
DHCPv6OptDHCPv4OverDHCPv6Server DHCPv6Opt = 88
|
||||
|
||||
// RFC 7598 Configuration of Softwire Address and Port-Mapped Clients
|
||||
DHCPv6OptS46Rule DHCPv6Opt = 89
|
||||
DHCPv6OptS46BR DHCPv6Opt = 90
|
||||
DHCPv6OptS46DMR DHCPv6Opt = 91
|
||||
DHCPv6OptS46V4V4Bind DHCPv6Opt = 92
|
||||
DHCPv6OptS46PortParameters DHCPv6Opt = 93
|
||||
DHCPv6OptS46ContMAPE DHCPv6Opt = 94
|
||||
DHCPv6OptS46ContMAPT DHCPv6Opt = 95
|
||||
DHCPv6OptS46ContLW DHCPv6Opt = 96
|
||||
|
||||
// RFC 7600 IPv4 Residual Deployment via IPv6
|
||||
DHCPv6Opt4RD DHCPv6Opt = 97
|
||||
DHCPv6Opt4RDMapRule DHCPv6Opt = 98
|
||||
DHCPv6Opt4RDNonMapRule DHCPv6Opt = 99
|
||||
|
||||
// RFC 7653 Active Leasequery
|
||||
DHCPv6OptLQBaseTime DHCPv6Opt = 100
|
||||
DHCPv6OptLQStartTime DHCPv6Opt = 101
|
||||
DHCPv6OptLQEndTime DHCPv6Opt = 102
|
||||
|
||||
// RFC 7710 Captive-Portal Identification
|
||||
DHCPv6OptCaptivePortal DHCPv6Opt = 103
|
||||
|
||||
// RFC 7774 Multicast Protocol for Low-Power and Lossy Networks (MPL) Parameter Configuration
|
||||
DHCPv6OptMPLParameters DHCPv6Opt = 104
|
||||
|
||||
// RFC 7839 Access-Network-Identifier (ANI)
|
||||
DHCPv6OptANIATT DHCPv6Opt = 105
|
||||
DHCPv6OptANINetworkName DHCPv6Opt = 106
|
||||
DHCPv6OptANIAPName DHCPv6Opt = 107
|
||||
DHCPv6OptANIAPBSSID DHCPv6Opt = 108
|
||||
DHCPv6OptANIOperatorID DHCPv6Opt = 109
|
||||
DHCPv6OptANIOperatorRealm DHCPv6Opt = 110
|
||||
|
||||
// RFC 8026 Unified IPv4-in-IPv6 Softwire Customer Premises Equipment (CPE)
|
||||
DHCPv6OptS46Priority DHCPv6Opt = 111
|
||||
|
||||
// draft-ietf-opsawg-mud-25 Manufacturer Usage Description (MUD)
|
||||
DHCPv6OptMUDURLV6 DHCPv6Opt = 112
|
||||
|
||||
// RFC 8115 IPv4-Embedded Multicast and Unicast IPv6 Prefixes
|
||||
DHCPv6OptV6Prefix64 DHCPv6Opt = 113
|
||||
|
||||
// RFC 8156 DHCPv6 Failover Protocol
|
||||
DHCPv6OptFBindingStatus DHCPv6Opt = 114
|
||||
DHCPv6OptFConnectFlags DHCPv6Opt = 115
|
||||
DHCPv6OptFDNSRemovalInfo DHCPv6Opt = 116
|
||||
DHCPv6OptFDNSHostName DHCPv6Opt = 117
|
||||
DHCPv6OptFDNSZoneName DHCPv6Opt = 118
|
||||
DHCPv6OptFDNSFlags DHCPv6Opt = 119
|
||||
DHCPv6OptFExpirationTime DHCPv6Opt = 120
|
||||
DHCPv6OptFMaxUnacknowledgedBNDUPD DHCPv6Opt = 121
|
||||
DHCPv6OptFMCLT DHCPv6Opt = 122
|
||||
DHCPv6OptFPartnerLifetime DHCPv6Opt = 123
|
||||
DHCPv6OptFPartnerLifetimeSent DHCPv6Opt = 124
|
||||
DHCPv6OptFPartnerDownTime DHCPv6Opt = 125
|
||||
DHCPv6OptFPartnerRawCltTime DHCPv6Opt = 126
|
||||
DHCPv6OptFProtocolVersion DHCPv6Opt = 127
|
||||
DHCPv6OptFKeepaliveTime DHCPv6Opt = 128
|
||||
DHCPv6OptFReconfigureData DHCPv6Opt = 129
|
||||
DHCPv6OptFRelationshipName DHCPv6Opt = 130
|
||||
DHCPv6OptFServerFlags DHCPv6Opt = 131
|
||||
DHCPv6OptFServerState DHCPv6Opt = 132
|
||||
DHCPv6OptFStartTimeOfState DHCPv6Opt = 133
|
||||
DHCPv6OptFStateExpirationTime DHCPv6Opt = 134
|
||||
|
||||
// RFC 8357 Generalized UDP Source Port for DHCP Relay
|
||||
DHCPv6OptRelayPort DHCPv6Opt = 135
|
||||
|
||||
// draft-ietf-netconf-zerotouch-25 Zero Touch Provisioning for Networking Devices
|
||||
DHCPv6OptV6ZeroTouchRedirect DHCPv6Opt = 136
|
||||
|
||||
// RFC 6153 Access Network Discovery and Selection Function (ANDSF) Discovery
|
||||
DHCPv6OptIPV6AddressANDSF DHCPv6Opt = 143
|
||||
)
|
||||
|
||||
// String returns a string version of a DHCPv6Opt.
|
||||
func (o DHCPv6Opt) String() string {
|
||||
switch o {
|
||||
case DHCPv6OptClientID:
|
||||
return "ClientID"
|
||||
case DHCPv6OptServerID:
|
||||
return "ServerID"
|
||||
case DHCPv6OptIANA:
|
||||
return "IA_NA"
|
||||
case DHCPv6OptIATA:
|
||||
return "IA_TA"
|
||||
case DHCPv6OptIAAddr:
|
||||
return "IAAddr"
|
||||
case DHCPv6OptOro:
|
||||
return "Oro"
|
||||
case DHCPv6OptPreference:
|
||||
return "Preference"
|
||||
case DHCPv6OptElapsedTime:
|
||||
return "ElapsedTime"
|
||||
case DHCPv6OptRelayMessage:
|
||||
return "RelayMessage"
|
||||
case DHCPv6OptAuth:
|
||||
return "Auth"
|
||||
case DHCPv6OptUnicast:
|
||||
return "Unicast"
|
||||
case DHCPv6OptStatusCode:
|
||||
return "StatusCode"
|
||||
case DHCPv6OptRapidCommit:
|
||||
return "RapidCommit"
|
||||
case DHCPv6OptUserClass:
|
||||
return "UserClass"
|
||||
case DHCPv6OptVendorClass:
|
||||
return "VendorClass"
|
||||
case DHCPv6OptVendorOpts:
|
||||
return "VendorOpts"
|
||||
case DHCPv6OptInterfaceID:
|
||||
return "InterfaceID"
|
||||
case DHCPv6OptReconfigureMessage:
|
||||
return "ReconfigureMessage"
|
||||
case DHCPv6OptReconfigureAccept:
|
||||
return "ReconfigureAccept"
|
||||
case DHCPv6OptSIPServersDomainList:
|
||||
return "SIPServersDomainList"
|
||||
case DHCPv6OptSIPServersAddressList:
|
||||
return "SIPServersAddressList"
|
||||
case DHCPv6OptDNSServers:
|
||||
return "DNSRecursiveNameServer"
|
||||
case DHCPv6OptDomainList:
|
||||
return "DomainSearchList"
|
||||
case DHCPv6OptIAPD:
|
||||
return "IdentityAssociationPrefixDelegation"
|
||||
case DHCPv6OptIAPrefix:
|
||||
return "IAPDPrefix"
|
||||
case DHCPv6OptNISServers:
|
||||
return "NISServers"
|
||||
case DHCPv6OptNISPServers:
|
||||
return "NISv2Servers"
|
||||
case DHCPv6OptNISDomainName:
|
||||
return "NISDomainName"
|
||||
case DHCPv6OptNISPDomainName:
|
||||
return "NISv2DomainName"
|
||||
case DHCPv6OptSNTPServers:
|
||||
return "SNTPServers"
|
||||
case DHCPv6OptInformationRefreshTime:
|
||||
return "InformationRefreshTime"
|
||||
case DHCPv6OptBCMCSServerDomainNameList:
|
||||
return "BCMCSControlServersDomainNameList"
|
||||
case DHCPv6OptBCMCSServerAddressList:
|
||||
return "BCMCSControlServersAddressList"
|
||||
case DHCPv6OptGeoconfCivic:
|
||||
return "CivicAddress"
|
||||
case DHCPv6OptRemoteID:
|
||||
return "RelayAgentRemoteID"
|
||||
case DHCPv6OptSubscriberID:
|
||||
return "RelayAgentSubscriberID"
|
||||
case DHCPv6OptClientFQDN:
|
||||
return "ClientFQDN"
|
||||
case DHCPv6OptPanaAgent:
|
||||
return "PANAAuthenticationAgent"
|
||||
case DHCPv6OptNewPOSIXTimezone:
|
||||
return "NewPOSIXTimezone"
|
||||
case DHCPv6OptNewTZDBTimezone:
|
||||
return "NewTZDBTimezone"
|
||||
case DHCPv6OptEchoRequestOption:
|
||||
return "EchoRequest"
|
||||
case DHCPv6OptLQQuery:
|
||||
return "LeasequeryQuery"
|
||||
case DHCPv6OptClientData:
|
||||
return "LeasequeryClientData"
|
||||
case DHCPv6OptCLTTime:
|
||||
return "LeasequeryClientLastTransactionTime"
|
||||
case DHCPv6OptLQRelayData:
|
||||
return "LeasequeryRelayData"
|
||||
case DHCPv6OptLQClientLink:
|
||||
return "LeasequeryClientLink"
|
||||
case DHCPv6OptMIP6HNIDF:
|
||||
return "MIPv6HomeNetworkIDFQDN"
|
||||
case DHCPv6OptMIP6VDINF:
|
||||
return "MIPv6VisitedHomeNetworkInformation"
|
||||
case DHCPv6OptMIP6IDINF:
|
||||
return "MIPv6IdentifiedHomeNetworkInformation"
|
||||
case DHCPv6OptMIP6UDINF:
|
||||
return "MIPv6UnrestrictedHomeNetworkInformation"
|
||||
case DHCPv6OptMIP6HNP:
|
||||
return "MIPv6HomeNetworkPrefix"
|
||||
case DHCPv6OptMIP6HAA:
|
||||
return "MIPv6HomeAgentAddress"
|
||||
case DHCPv6OptMIP6HAF:
|
||||
return "MIPv6HomeAgentFQDN"
|
||||
case DHCPv6OptV6LOST:
|
||||
return "LoST Server"
|
||||
case DHCPv6OptCAPWAPACV6:
|
||||
return "CAPWAPAccessControllerV6"
|
||||
case DHCPv6OptRelayID:
|
||||
return "LeasequeryRelayID"
|
||||
case DHCPv6OptIPv6AddressMoS:
|
||||
return "MoSIPv6Address"
|
||||
case DHCPv6OptIPv6FQDNMoS:
|
||||
return "MoSDomainNameList"
|
||||
case DHCPv6OptNTPServer:
|
||||
return "NTPServer"
|
||||
case DHCPv6OptV6AccessDomain:
|
||||
return "AccessNetworkDomainName"
|
||||
case DHCPv6OptSIPUACSList:
|
||||
return "SIPUserAgentConfigurationServiceDomains"
|
||||
case DHCPv6OptBootFileURL:
|
||||
return "BootFileURL"
|
||||
case DHCPv6OptBootFileParam:
|
||||
return "BootFileParameters"
|
||||
case DHCPv6OptClientArchType:
|
||||
return "ClientSystemArchitectureType"
|
||||
case DHCPv6OptNII:
|
||||
return "ClientNetworkInterfaceIdentifier"
|
||||
case DHCPv6OptGeolocation:
|
||||
return "Geolocation"
|
||||
case DHCPv6OptAFTRName:
|
||||
return "AFTRName"
|
||||
case DHCPv6OptERPLocalDomainName:
|
||||
return "AFTRName"
|
||||
case DHCPv6OptRSOO:
|
||||
return "RSOOption"
|
||||
case DHCPv6OptPDExclude:
|
||||
return "PrefixExclude"
|
||||
case DHCPv6OptVSS:
|
||||
return "VirtualSubnetSelection"
|
||||
case DHCPv6OptRDNSSSelection:
|
||||
return "RDNSSSelection"
|
||||
case DHCPv6OptKRBPrincipalName:
|
||||
return "KerberosPrincipalName"
|
||||
case DHCPv6OptKRBRealmName:
|
||||
return "KerberosRealmName"
|
||||
case DHCPv6OptKRBKDC:
|
||||
return "KerberosKDC"
|
||||
case DHCPv6OptClientLinkLayerAddress:
|
||||
return "ClientLinkLayerAddress"
|
||||
case DHCPv6OptLinkAddress:
|
||||
return "LinkAddress"
|
||||
case DHCPv6OptRADIUS:
|
||||
return "RADIUS"
|
||||
case DHCPv6OptSolMaxRt:
|
||||
return "SolMaxRt"
|
||||
case DHCPv6OptInfMaxRt:
|
||||
return "InfMaxRt"
|
||||
case DHCPv6OptAddrSel:
|
||||
return "AddressSelection"
|
||||
case DHCPv6OptAddrSelTable:
|
||||
return "AddressSelectionTable"
|
||||
case DHCPv6OptV6PCPServer:
|
||||
return "PCPServer"
|
||||
case DHCPv6OptDHCPv4Message:
|
||||
return "DHCPv4Message"
|
||||
case DHCPv6OptDHCPv4OverDHCPv6Server:
|
||||
return "DHCP4o6ServerAddress"
|
||||
case DHCPv6OptS46Rule:
|
||||
return "S46Rule"
|
||||
case DHCPv6OptS46BR:
|
||||
return "S46BR"
|
||||
case DHCPv6OptS46DMR:
|
||||
return "S46DMR"
|
||||
case DHCPv6OptS46V4V4Bind:
|
||||
return "S46IPv4IPv6AddressBinding"
|
||||
case DHCPv6OptS46PortParameters:
|
||||
return "S46PortParameters"
|
||||
case DHCPv6OptS46ContMAPE:
|
||||
return "S46MAPEContainer"
|
||||
case DHCPv6OptS46ContMAPT:
|
||||
return "S46MAPTContainer"
|
||||
case DHCPv6OptS46ContLW:
|
||||
return "S46Lightweight4Over6Container"
|
||||
case DHCPv6Opt4RD:
|
||||
return "4RD"
|
||||
case DHCPv6Opt4RDMapRule:
|
||||
return "4RDMapRule"
|
||||
case DHCPv6Opt4RDNonMapRule:
|
||||
return "4RDNonMapRule"
|
||||
case DHCPv6OptLQBaseTime:
|
||||
return "LQBaseTime"
|
||||
case DHCPv6OptLQStartTime:
|
||||
return "LQStartTime"
|
||||
case DHCPv6OptLQEndTime:
|
||||
return "LQEndTime"
|
||||
case DHCPv6OptCaptivePortal:
|
||||
return "CaptivePortal"
|
||||
case DHCPv6OptMPLParameters:
|
||||
return "MPLParameterConfiguration"
|
||||
case DHCPv6OptANIATT:
|
||||
return "ANIAccessTechnologyType"
|
||||
case DHCPv6OptANINetworkName:
|
||||
return "ANINetworkName"
|
||||
case DHCPv6OptANIAPName:
|
||||
return "ANIAccessPointName"
|
||||
case DHCPv6OptANIAPBSSID:
|
||||
return "ANIAccessPointBSSID"
|
||||
case DHCPv6OptANIOperatorID:
|
||||
return "ANIOperatorIdentifier"
|
||||
case DHCPv6OptANIOperatorRealm:
|
||||
return "ANIOperatorRealm"
|
||||
case DHCPv6OptS46Priority:
|
||||
return "S64Priority"
|
||||
case DHCPv6OptMUDURLV6:
|
||||
return "ManufacturerUsageDescriptionURL"
|
||||
case DHCPv6OptV6Prefix64:
|
||||
return "V6Prefix64"
|
||||
case DHCPv6OptFBindingStatus:
|
||||
return "FailoverBindingStatus"
|
||||
case DHCPv6OptFConnectFlags:
|
||||
return "FailoverConnectFlags"
|
||||
case DHCPv6OptFDNSRemovalInfo:
|
||||
return "FailoverDNSRemovalInfo"
|
||||
case DHCPv6OptFDNSHostName:
|
||||
return "FailoverDNSHostName"
|
||||
case DHCPv6OptFDNSZoneName:
|
||||
return "FailoverDNSZoneName"
|
||||
case DHCPv6OptFDNSFlags:
|
||||
return "FailoverDNSFlags"
|
||||
case DHCPv6OptFExpirationTime:
|
||||
return "FailoverExpirationTime"
|
||||
case DHCPv6OptFMaxUnacknowledgedBNDUPD:
|
||||
return "FailoverMaxUnacknowledgedBNDUPDMessages"
|
||||
case DHCPv6OptFMCLT:
|
||||
return "FailoverMaximumClientLeadTime"
|
||||
case DHCPv6OptFPartnerLifetime:
|
||||
return "FailoverPartnerLifetime"
|
||||
case DHCPv6OptFPartnerLifetimeSent:
|
||||
return "FailoverPartnerLifetimeSent"
|
||||
case DHCPv6OptFPartnerDownTime:
|
||||
return "FailoverPartnerDownTime"
|
||||
case DHCPv6OptFPartnerRawCltTime:
|
||||
return "FailoverPartnerRawClientLeadTime"
|
||||
case DHCPv6OptFProtocolVersion:
|
||||
return "FailoverProtocolVersion"
|
||||
case DHCPv6OptFKeepaliveTime:
|
||||
return "FailoverKeepaliveTime"
|
||||
case DHCPv6OptFReconfigureData:
|
||||
return "FailoverReconfigureData"
|
||||
case DHCPv6OptFRelationshipName:
|
||||
return "FailoverRelationshipName"
|
||||
case DHCPv6OptFServerFlags:
|
||||
return "FailoverServerFlags"
|
||||
case DHCPv6OptFServerState:
|
||||
return "FailoverServerState"
|
||||
case DHCPv6OptFStartTimeOfState:
|
||||
return "FailoverStartTimeOfState"
|
||||
case DHCPv6OptFStateExpirationTime:
|
||||
return "FailoverStateExpirationTime"
|
||||
case DHCPv6OptRelayPort:
|
||||
return "RelayPort"
|
||||
case DHCPv6OptV6ZeroTouchRedirect:
|
||||
return "ZeroTouch"
|
||||
case DHCPv6OptIPV6AddressANDSF:
|
||||
return "ANDSFIPv6Address"
|
||||
default:
|
||||
return fmt.Sprintf("Unknown(%d)", uint16(o))
|
||||
}
|
||||
}
|
||||
|
||||
// DHCPv6Options is used to get nicely printed option lists which would normally
|
||||
// be cut off after 5 options.
|
||||
type DHCPv6Options []DHCPv6Option
|
||||
|
||||
// String returns a string version of the options list.
|
||||
func (o DHCPv6Options) String() string {
|
||||
buf := &bytes.Buffer{}
|
||||
buf.WriteByte('[')
|
||||
for i, opt := range o {
|
||||
buf.WriteString(opt.String())
|
||||
if i+1 != len(o) {
|
||||
buf.WriteString(", ")
|
||||
}
|
||||
}
|
||||
buf.WriteByte(']')
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// DHCPv6Option rerpresents a DHCP option.
|
||||
type DHCPv6Option struct {
|
||||
Code DHCPv6Opt
|
||||
Length uint16
|
||||
Data []byte
|
||||
}
|
||||
|
||||
// String returns a string version of a DHCP Option.
|
||||
func (o DHCPv6Option) String() string {
|
||||
switch o.Code {
|
||||
case DHCPv6OptClientID, DHCPv6OptServerID:
|
||||
duid, err := decodeDHCPv6DUID(o.Data)
|
||||
if err != nil {
|
||||
return fmt.Sprintf("Option(%s:INVALID)", o.Code)
|
||||
}
|
||||
return fmt.Sprintf("Option(%s:[%s])", o.Code, duid.String())
|
||||
case DHCPv6OptOro:
|
||||
options := ""
|
||||
for i := 0; i < int(o.Length); i += 2 {
|
||||
if options != "" {
|
||||
options += ","
|
||||
}
|
||||
option := DHCPv6Opt(binary.BigEndian.Uint16(o.Data[i : i+2]))
|
||||
options += option.String()
|
||||
}
|
||||
return fmt.Sprintf("Option(%s:[%s])", o.Code, options)
|
||||
default:
|
||||
return fmt.Sprintf("Option(%s:%v)", o.Code, o.Data)
|
||||
}
|
||||
}
|
||||
|
||||
// NewDHCPv6Option constructs a new DHCPv6Option with a given type and data.
|
||||
func NewDHCPv6Option(code DHCPv6Opt, data []byte) DHCPv6Option {
|
||||
o := DHCPv6Option{Code: code}
|
||||
if data != nil {
|
||||
o.Data = data
|
||||
o.Length = uint16(len(data))
|
||||
}
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
func (o *DHCPv6Option) encode(b []byte, opts gopacket.SerializeOptions) error {
|
||||
binary.BigEndian.PutUint16(b[0:2], uint16(o.Code))
|
||||
if opts.FixLengths {
|
||||
binary.BigEndian.PutUint16(b[2:4], uint16(len(o.Data)))
|
||||
} else {
|
||||
binary.BigEndian.PutUint16(b[2:4], o.Length)
|
||||
}
|
||||
copy(b[4:], o.Data)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *DHCPv6Option) decode(data []byte) error {
|
||||
if len(data) < 2 {
|
||||
return errors.New("not enough data to decode")
|
||||
}
|
||||
o.Code = DHCPv6Opt(binary.BigEndian.Uint16(data[0:2]))
|
||||
if len(data) < 3 {
|
||||
return errors.New("not enough data to decode")
|
||||
}
|
||||
o.Length = binary.BigEndian.Uint16(data[2:4])
|
||||
o.Data = data[4 : 4+o.Length]
|
||||
return nil
|
||||
}
|
||||
+39
-19
@@ -254,7 +254,7 @@ type DNS struct {
|
||||
TC bool // Truncated
|
||||
RD bool // Recursion desired
|
||||
RA bool // Recursion available
|
||||
Z uint8 // Resrved for future use
|
||||
Z uint8 // Reserved for future use
|
||||
|
||||
ResponseCode DNSResponseCode
|
||||
QDCount uint16 // Number of questions to expect
|
||||
@@ -296,7 +296,7 @@ func (d *DNS) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||||
|
||||
if len(data) < 12 {
|
||||
df.SetTruncated()
|
||||
return errors.New("DNS packet too short")
|
||||
return errDNSPacketTooShort
|
||||
}
|
||||
|
||||
// since there are no further layers, the baselayer's content is
|
||||
@@ -366,13 +366,13 @@ func (d *DNS) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||||
}
|
||||
|
||||
if uint16(len(d.Questions)) != d.QDCount {
|
||||
return errors.New("Invalid query decoding, not the right number of questions")
|
||||
return errDecodeQueryBadQDCount
|
||||
} else if uint16(len(d.Answers)) != d.ANCount {
|
||||
return errors.New("Invalid query decoding, not the right number of answers")
|
||||
return errDecodeQueryBadANCount
|
||||
} else if uint16(len(d.Authorities)) != d.NSCount {
|
||||
return errors.New("Invalid query decoding, not the right number of authorities")
|
||||
return errDecodeQueryBadNSCount
|
||||
} else if uint16(len(d.Additionals)) != d.ARCount {
|
||||
return errors.New("Invalid query decoding, not the right number of additionals info")
|
||||
return errDecodeQueryBadARCount
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -431,7 +431,7 @@ func recSize(rr *DNSResourceRecord) int {
|
||||
func computeSize(recs []DNSResourceRecord) int {
|
||||
sz := 0
|
||||
for _, rr := range recs {
|
||||
sz += len(rr.Name) + 14
|
||||
sz += len(rr.Name) + 12
|
||||
sz += recSize(&rr)
|
||||
}
|
||||
return sz
|
||||
@@ -504,17 +504,15 @@ func (d *DNS) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOpt
|
||||
return nil
|
||||
}
|
||||
|
||||
var errMaxRecursion = errors.New("max DNS recursion level hit")
|
||||
|
||||
const maxRecursionLevel = 255
|
||||
|
||||
func decodeName(data []byte, offset int, buffer *[]byte, level int) ([]byte, int, error) {
|
||||
if level > maxRecursionLevel {
|
||||
return nil, 0, errMaxRecursion
|
||||
} else if offset >= len(data) {
|
||||
return nil, 0, errors.New("dns name offset too high")
|
||||
return nil, 0, errDNSNameOffsetTooHigh
|
||||
} else if offset < 0 {
|
||||
return nil, 0, errors.New("dns name offset is negative")
|
||||
return nil, 0, errDNSNameOffsetNegative
|
||||
}
|
||||
start := len(*buffer)
|
||||
index := offset
|
||||
@@ -535,9 +533,9 @@ loop:
|
||||
*/
|
||||
index2 := index + int(data[index]) + 1
|
||||
if index2-offset > 255 {
|
||||
return nil, 0, errors.New("dns name is too long")
|
||||
return nil, 0, errDNSNameTooLong
|
||||
} else if index2 < index+1 || index2 > len(data) {
|
||||
return nil, 0, errors.New("dns name uncomputable: invalid index")
|
||||
return nil, 0, errDNSNameInvalidIndex
|
||||
}
|
||||
*buffer = append(*buffer, '.')
|
||||
*buffer = append(*buffer, data[index+1:index2]...)
|
||||
@@ -564,11 +562,11 @@ loop:
|
||||
- a sequence of labels ending with a pointer
|
||||
*/
|
||||
if index+2 > len(data) {
|
||||
return nil, 0, errors.New("dns offset pointer too high")
|
||||
return nil, 0, errDNSPointerOffsetTooHigh
|
||||
}
|
||||
offsetp := int(binary.BigEndian.Uint16(data[index:index+2]) & 0x3fff)
|
||||
if offsetp > len(data) {
|
||||
return nil, 0, errors.New("dns offset pointer too high")
|
||||
return nil, 0, errDNSPointerOffsetTooHigh
|
||||
}
|
||||
// This looks a little tricky, but actually isn't. Because of how
|
||||
// decodeName is written, calling it appends the decoded name to the
|
||||
@@ -590,11 +588,11 @@ loop:
|
||||
data[index], index)
|
||||
}
|
||||
if index >= len(data) {
|
||||
return nil, 0, errors.New("dns index walked out of range")
|
||||
return nil, 0, errDNSIndexOutOfRange
|
||||
}
|
||||
}
|
||||
if len(*buffer) <= start {
|
||||
return nil, 0, errors.New("no dns data found for name")
|
||||
return nil, 0, errDNSNameHasNoData
|
||||
}
|
||||
return (*buffer)[start+1:], index + 1, nil
|
||||
}
|
||||
@@ -686,7 +684,7 @@ func (rr *DNSResourceRecord) decode(data []byte, offset int, df gopacket.DecodeF
|
||||
rr.DataLength = binary.BigEndian.Uint16(data[endq+8 : endq+10])
|
||||
end := endq + 10 + int(rr.DataLength)
|
||||
if end > len(data) {
|
||||
return 0, fmt.Errorf("resource record length exceeds data")
|
||||
return 0, errDecodeRecordLength
|
||||
}
|
||||
rr.Data = data[endq+10 : end]
|
||||
|
||||
@@ -798,7 +796,7 @@ func decodeCharacterStrings(data []byte) ([][]byte, error) {
|
||||
for index, index2 := 0, 0; index != end; index = index2 {
|
||||
index2 = index + 1 + int(data[index]) // index increases by 1..256 and does not overflow
|
||||
if index2 > end {
|
||||
return nil, errors.New("Insufficient data for a <character-string>")
|
||||
return nil, errCharStringMissData
|
||||
}
|
||||
strings = append(strings, data[index+1:index2])
|
||||
}
|
||||
@@ -892,3 +890,25 @@ type DNSMX struct {
|
||||
Preference uint16
|
||||
Name []byte
|
||||
}
|
||||
|
||||
var (
|
||||
errMaxRecursion = errors.New("max DNS recursion level hit")
|
||||
|
||||
errDNSNameOffsetTooHigh = errors.New("dns name offset too high")
|
||||
errDNSNameOffsetNegative = errors.New("dns name offset is negative")
|
||||
errDNSPacketTooShort = errors.New("DNS packet too short")
|
||||
errDNSNameTooLong = errors.New("dns name is too long")
|
||||
errDNSNameInvalidIndex = errors.New("dns name uncomputable: invalid index")
|
||||
errDNSPointerOffsetTooHigh = errors.New("dns offset pointer too high")
|
||||
errDNSIndexOutOfRange = errors.New("dns index walked out of range")
|
||||
errDNSNameHasNoData = errors.New("no dns data found for name")
|
||||
|
||||
errCharStringMissData = errors.New("Insufficient data for a <character-string>")
|
||||
|
||||
errDecodeRecordLength = errors.New("resource record length exceeds data")
|
||||
|
||||
errDecodeQueryBadQDCount = errors.New("Invalid query decoding, not the right number of questions")
|
||||
errDecodeQueryBadANCount = errors.New("Invalid query decoding, not the right number of answers")
|
||||
errDecodeQueryBadNSCount = errors.New("Invalid query decoding, not the right number of authorities")
|
||||
errDecodeQueryBadARCount = errors.New("Invalid query decoding, not the right number of additionals info")
|
||||
)
|
||||
+732
-57
@@ -240,24 +240,178 @@ func (a Dot11Algorithm) String() string {
|
||||
|
||||
type Dot11InformationElementID uint8
|
||||
|
||||
// TODO: Verify these element ids, and append more ids if more.
|
||||
|
||||
const (
|
||||
Dot11InformationElementIDSSID Dot11InformationElementID = 0
|
||||
Dot11InformationElementIDRates Dot11InformationElementID = 1
|
||||
Dot11InformationElementIDFHSet Dot11InformationElementID = 2
|
||||
Dot11InformationElementIDDSSet Dot11InformationElementID = 3
|
||||
Dot11InformationElementIDCFSet Dot11InformationElementID = 4
|
||||
Dot11InformationElementIDTIM Dot11InformationElementID = 5
|
||||
Dot11InformationElementIDIBSSSet Dot11InformationElementID = 6
|
||||
Dot11InformationElementIDChallenge Dot11InformationElementID = 16
|
||||
Dot11InformationElementIDERPInfo Dot11InformationElementID = 42
|
||||
Dot11InformationElementIDQOSCapability Dot11InformationElementID = 46
|
||||
Dot11InformationElementIDERPInfo2 Dot11InformationElementID = 47
|
||||
Dot11InformationElementIDRSNInfo Dot11InformationElementID = 48
|
||||
Dot11InformationElementIDESRates Dot11InformationElementID = 50
|
||||
Dot11InformationElementIDVendor Dot11InformationElementID = 221
|
||||
Dot11InformationElementIDReserved Dot11InformationElementID = 68
|
||||
Dot11InformationElementIDSSID Dot11InformationElementID = 0
|
||||
Dot11InformationElementIDRates Dot11InformationElementID = 1
|
||||
Dot11InformationElementIDFHSet Dot11InformationElementID = 2
|
||||
Dot11InformationElementIDDSSet Dot11InformationElementID = 3
|
||||
Dot11InformationElementIDCFSet Dot11InformationElementID = 4
|
||||
Dot11InformationElementIDTIM Dot11InformationElementID = 5
|
||||
Dot11InformationElementIDIBSSSet Dot11InformationElementID = 6
|
||||
Dot11InformationElementIDCountryInfo Dot11InformationElementID = 7
|
||||
Dot11InformationElementIDHoppingPatternParam Dot11InformationElementID = 8
|
||||
Dot11InformationElementIDHoppingPatternTable Dot11InformationElementID = 9
|
||||
Dot11InformationElementIDRequest Dot11InformationElementID = 10
|
||||
Dot11InformationElementIDQBSSLoadElem Dot11InformationElementID = 11
|
||||
Dot11InformationElementIDEDCAParamSet Dot11InformationElementID = 12
|
||||
Dot11InformationElementIDTrafficSpec Dot11InformationElementID = 13
|
||||
Dot11InformationElementIDTrafficClass Dot11InformationElementID = 14
|
||||
Dot11InformationElementIDSchedule Dot11InformationElementID = 15
|
||||
Dot11InformationElementIDChallenge Dot11InformationElementID = 16
|
||||
Dot11InformationElementIDPowerConst Dot11InformationElementID = 32
|
||||
Dot11InformationElementIDPowerCapability Dot11InformationElementID = 33
|
||||
Dot11InformationElementIDTPCRequest Dot11InformationElementID = 34
|
||||
Dot11InformationElementIDTPCReport Dot11InformationElementID = 35
|
||||
Dot11InformationElementIDSupportedChannels Dot11InformationElementID = 36
|
||||
Dot11InformationElementIDSwitchChannelAnnounce Dot11InformationElementID = 37
|
||||
Dot11InformationElementIDMeasureRequest Dot11InformationElementID = 38
|
||||
Dot11InformationElementIDMeasureReport Dot11InformationElementID = 39
|
||||
Dot11InformationElementIDQuiet Dot11InformationElementID = 40
|
||||
Dot11InformationElementIDIBSSDFS Dot11InformationElementID = 41
|
||||
Dot11InformationElementIDERPInfo Dot11InformationElementID = 42
|
||||
Dot11InformationElementIDTSDelay Dot11InformationElementID = 43
|
||||
Dot11InformationElementIDTCLASProcessing Dot11InformationElementID = 44
|
||||
Dot11InformationElementIDHTCapabilities Dot11InformationElementID = 45
|
||||
Dot11InformationElementIDQOSCapability Dot11InformationElementID = 46
|
||||
Dot11InformationElementIDERPInfo2 Dot11InformationElementID = 47
|
||||
Dot11InformationElementIDRSNInfo Dot11InformationElementID = 48
|
||||
Dot11InformationElementIDESRates Dot11InformationElementID = 50
|
||||
Dot11InformationElementIDAPChannelReport Dot11InformationElementID = 51
|
||||
Dot11InformationElementIDNeighborReport Dot11InformationElementID = 52
|
||||
Dot11InformationElementIDRCPI Dot11InformationElementID = 53
|
||||
Dot11InformationElementIDMobilityDomain Dot11InformationElementID = 54
|
||||
Dot11InformationElementIDFastBSSTrans Dot11InformationElementID = 55
|
||||
Dot11InformationElementIDTimeoutInt Dot11InformationElementID = 56
|
||||
Dot11InformationElementIDRICData Dot11InformationElementID = 57
|
||||
Dot11InformationElementIDDSERegisteredLoc Dot11InformationElementID = 58
|
||||
Dot11InformationElementIDSuppOperatingClass Dot11InformationElementID = 59
|
||||
Dot11InformationElementIDExtChanSwitchAnnounce Dot11InformationElementID = 60
|
||||
Dot11InformationElementIDHTInfo Dot11InformationElementID = 61
|
||||
Dot11InformationElementIDSecChanOffset Dot11InformationElementID = 62
|
||||
Dot11InformationElementIDBSSAverageAccessDelay Dot11InformationElementID = 63
|
||||
Dot11InformationElementIDAntenna Dot11InformationElementID = 64
|
||||
Dot11InformationElementIDRSNI Dot11InformationElementID = 65
|
||||
Dot11InformationElementIDMeasurePilotTrans Dot11InformationElementID = 66
|
||||
Dot11InformationElementIDBSSAvailAdmCapacity Dot11InformationElementID = 67
|
||||
Dot11InformationElementIDBSSACAccDelayWAPIParam Dot11InformationElementID = 68
|
||||
Dot11InformationElementIDTimeAdvertisement Dot11InformationElementID = 69
|
||||
Dot11InformationElementIDRMEnabledCapabilities Dot11InformationElementID = 70
|
||||
Dot11InformationElementIDMultipleBSSID Dot11InformationElementID = 71
|
||||
Dot11InformationElementID2040BSSCoExist Dot11InformationElementID = 72
|
||||
Dot11InformationElementID2040BSSIntChanReport Dot11InformationElementID = 73
|
||||
Dot11InformationElementIDOverlapBSSScanParam Dot11InformationElementID = 74
|
||||
Dot11InformationElementIDRICDescriptor Dot11InformationElementID = 75
|
||||
Dot11InformationElementIDManagementMIC Dot11InformationElementID = 76
|
||||
Dot11InformationElementIDEventRequest Dot11InformationElementID = 78
|
||||
Dot11InformationElementIDEventReport Dot11InformationElementID = 79
|
||||
Dot11InformationElementIDDiagnosticRequest Dot11InformationElementID = 80
|
||||
Dot11InformationElementIDDiagnosticReport Dot11InformationElementID = 81
|
||||
Dot11InformationElementIDLocationParam Dot11InformationElementID = 82
|
||||
Dot11InformationElementIDNonTransBSSIDCapability Dot11InformationElementID = 83
|
||||
Dot11InformationElementIDSSIDList Dot11InformationElementID = 84
|
||||
Dot11InformationElementIDMultipleBSSIDIndex Dot11InformationElementID = 85
|
||||
Dot11InformationElementIDFMSDescriptor Dot11InformationElementID = 86
|
||||
Dot11InformationElementIDFMSRequest Dot11InformationElementID = 87
|
||||
Dot11InformationElementIDFMSResponse Dot11InformationElementID = 88
|
||||
Dot11InformationElementIDQOSTrafficCapability Dot11InformationElementID = 89
|
||||
Dot11InformationElementIDBSSMaxIdlePeriod Dot11InformationElementID = 90
|
||||
Dot11InformationElementIDTFSRequest Dot11InformationElementID = 91
|
||||
Dot11InformationElementIDTFSResponse Dot11InformationElementID = 92
|
||||
Dot11InformationElementIDWNMSleepMode Dot11InformationElementID = 93
|
||||
Dot11InformationElementIDTIMBroadcastRequest Dot11InformationElementID = 94
|
||||
Dot11InformationElementIDTIMBroadcastResponse Dot11InformationElementID = 95
|
||||
Dot11InformationElementIDCollInterferenceReport Dot11InformationElementID = 96
|
||||
Dot11InformationElementIDChannelUsage Dot11InformationElementID = 97
|
||||
Dot11InformationElementIDTimeZone Dot11InformationElementID = 98
|
||||
Dot11InformationElementIDDMSRequest Dot11InformationElementID = 99
|
||||
Dot11InformationElementIDDMSResponse Dot11InformationElementID = 100
|
||||
Dot11InformationElementIDLinkIdentifier Dot11InformationElementID = 101
|
||||
Dot11InformationElementIDWakeupSchedule Dot11InformationElementID = 102
|
||||
Dot11InformationElementIDChannelSwitchTiming Dot11InformationElementID = 104
|
||||
Dot11InformationElementIDPTIControl Dot11InformationElementID = 105
|
||||
Dot11InformationElementIDPUBufferStatus Dot11InformationElementID = 106
|
||||
Dot11InformationElementIDInterworking Dot11InformationElementID = 107
|
||||
Dot11InformationElementIDAdvertisementProtocol Dot11InformationElementID = 108
|
||||
Dot11InformationElementIDExpBWRequest Dot11InformationElementID = 109
|
||||
Dot11InformationElementIDQOSMapSet Dot11InformationElementID = 110
|
||||
Dot11InformationElementIDRoamingConsortium Dot11InformationElementID = 111
|
||||
Dot11InformationElementIDEmergencyAlertIdentifier Dot11InformationElementID = 112
|
||||
Dot11InformationElementIDMeshConfiguration Dot11InformationElementID = 113
|
||||
Dot11InformationElementIDMeshID Dot11InformationElementID = 114
|
||||
Dot11InformationElementIDMeshLinkMetricReport Dot11InformationElementID = 115
|
||||
Dot11InformationElementIDCongestionNotification Dot11InformationElementID = 116
|
||||
Dot11InformationElementIDMeshPeeringManagement Dot11InformationElementID = 117
|
||||
Dot11InformationElementIDMeshChannelSwitchParam Dot11InformationElementID = 118
|
||||
Dot11InformationElementIDMeshAwakeWindows Dot11InformationElementID = 119
|
||||
Dot11InformationElementIDBeaconTiming Dot11InformationElementID = 120
|
||||
Dot11InformationElementIDMCCAOPSetupRequest Dot11InformationElementID = 121
|
||||
Dot11InformationElementIDMCCAOPSetupReply Dot11InformationElementID = 122
|
||||
Dot11InformationElementIDMCCAOPAdvertisement Dot11InformationElementID = 123
|
||||
Dot11InformationElementIDMCCAOPTeardown Dot11InformationElementID = 124
|
||||
Dot11InformationElementIDGateAnnouncement Dot11InformationElementID = 125
|
||||
Dot11InformationElementIDRootAnnouncement Dot11InformationElementID = 126
|
||||
Dot11InformationElementIDExtCapability Dot11InformationElementID = 127
|
||||
Dot11InformationElementIDAgereProprietary Dot11InformationElementID = 128
|
||||
Dot11InformationElementIDPathRequest Dot11InformationElementID = 130
|
||||
Dot11InformationElementIDPathReply Dot11InformationElementID = 131
|
||||
Dot11InformationElementIDPathError Dot11InformationElementID = 132
|
||||
Dot11InformationElementIDCiscoCCX1CKIPDeviceName Dot11InformationElementID = 133
|
||||
Dot11InformationElementIDCiscoCCX2 Dot11InformationElementID = 136
|
||||
Dot11InformationElementIDProxyUpdate Dot11InformationElementID = 137
|
||||
Dot11InformationElementIDProxyUpdateConfirmation Dot11InformationElementID = 138
|
||||
Dot11InformationElementIDAuthMeshPerringExch Dot11InformationElementID = 139
|
||||
Dot11InformationElementIDMIC Dot11InformationElementID = 140
|
||||
Dot11InformationElementIDDestinationURI Dot11InformationElementID = 141
|
||||
Dot11InformationElementIDUAPSDCoexistence Dot11InformationElementID = 142
|
||||
Dot11InformationElementIDWakeupSchedule80211ad Dot11InformationElementID = 143
|
||||
Dot11InformationElementIDExtendedSchedule Dot11InformationElementID = 144
|
||||
Dot11InformationElementIDSTAAvailability Dot11InformationElementID = 145
|
||||
Dot11InformationElementIDDMGTSPEC Dot11InformationElementID = 146
|
||||
Dot11InformationElementIDNextDMGATI Dot11InformationElementID = 147
|
||||
Dot11InformationElementIDDMSCapabilities Dot11InformationElementID = 148
|
||||
Dot11InformationElementIDCiscoUnknown95 Dot11InformationElementID = 149
|
||||
Dot11InformationElementIDVendor2 Dot11InformationElementID = 150
|
||||
Dot11InformationElementIDDMGOperating Dot11InformationElementID = 151
|
||||
Dot11InformationElementIDDMGBSSParamChange Dot11InformationElementID = 152
|
||||
Dot11InformationElementIDDMGBeamRefinement Dot11InformationElementID = 153
|
||||
Dot11InformationElementIDChannelMeasFeedback Dot11InformationElementID = 154
|
||||
Dot11InformationElementIDAwakeWindow Dot11InformationElementID = 157
|
||||
Dot11InformationElementIDMultiBand Dot11InformationElementID = 158
|
||||
Dot11InformationElementIDADDBAExtension Dot11InformationElementID = 159
|
||||
Dot11InformationElementIDNEXTPCPList Dot11InformationElementID = 160
|
||||
Dot11InformationElementIDPCPHandover Dot11InformationElementID = 161
|
||||
Dot11InformationElementIDDMGLinkMargin Dot11InformationElementID = 162
|
||||
Dot11InformationElementIDSwitchingStream Dot11InformationElementID = 163
|
||||
Dot11InformationElementIDSessionTransmission Dot11InformationElementID = 164
|
||||
Dot11InformationElementIDDynamicTonePairReport Dot11InformationElementID = 165
|
||||
Dot11InformationElementIDClusterReport Dot11InformationElementID = 166
|
||||
Dot11InformationElementIDRelayCapabilities Dot11InformationElementID = 167
|
||||
Dot11InformationElementIDRelayTransferParameter Dot11InformationElementID = 168
|
||||
Dot11InformationElementIDBeamlinkMaintenance Dot11InformationElementID = 169
|
||||
Dot11InformationElementIDMultipleMacSublayers Dot11InformationElementID = 170
|
||||
Dot11InformationElementIDUPID Dot11InformationElementID = 171
|
||||
Dot11InformationElementIDDMGLinkAdaptionAck Dot11InformationElementID = 172
|
||||
Dot11InformationElementIDSymbolProprietary Dot11InformationElementID = 173
|
||||
Dot11InformationElementIDMCCAOPAdvertOverview Dot11InformationElementID = 174
|
||||
Dot11InformationElementIDQuietPeriodRequest Dot11InformationElementID = 175
|
||||
Dot11InformationElementIDQuietPeriodResponse Dot11InformationElementID = 177
|
||||
Dot11InformationElementIDECPACPolicy Dot11InformationElementID = 182
|
||||
Dot11InformationElementIDClusterTimeOffset Dot11InformationElementID = 183
|
||||
Dot11InformationElementIDAntennaSectorID Dot11InformationElementID = 190
|
||||
Dot11InformationElementIDVHTCapabilities Dot11InformationElementID = 191
|
||||
Dot11InformationElementIDVHTOperation Dot11InformationElementID = 192
|
||||
Dot11InformationElementIDExtendedBSSLoad Dot11InformationElementID = 193
|
||||
Dot11InformationElementIDWideBWChannelSwitch Dot11InformationElementID = 194
|
||||
Dot11InformationElementIDVHTTxPowerEnvelope Dot11InformationElementID = 195
|
||||
Dot11InformationElementIDChannelSwitchWrapper Dot11InformationElementID = 196
|
||||
Dot11InformationElementIDOperatingModeNotification Dot11InformationElementID = 199
|
||||
Dot11InformationElementIDUPSIM Dot11InformationElementID = 200
|
||||
Dot11InformationElementIDReducedNeighborReport Dot11InformationElementID = 201
|
||||
Dot11InformationElementIDTVHTOperation Dot11InformationElementID = 202
|
||||
Dot11InformationElementIDDeviceLocation Dot11InformationElementID = 204
|
||||
Dot11InformationElementIDWhiteSpaceMap Dot11InformationElementID = 205
|
||||
Dot11InformationElementIDFineTuningMeasureParams Dot11InformationElementID = 206
|
||||
Dot11InformationElementIDVendor Dot11InformationElementID = 221
|
||||
)
|
||||
|
||||
// String provides a human readable string for Dot11InformationElementID.
|
||||
@@ -267,35 +421,347 @@ const (
|
||||
func (a Dot11InformationElementID) String() string {
|
||||
switch a {
|
||||
case Dot11InformationElementIDSSID:
|
||||
return "SSID"
|
||||
return "SSID parameter set"
|
||||
case Dot11InformationElementIDRates:
|
||||
return "Rates"
|
||||
return "Supported Rates"
|
||||
case Dot11InformationElementIDFHSet:
|
||||
return "FHset"
|
||||
return "FH Parameter set"
|
||||
case Dot11InformationElementIDDSSet:
|
||||
return "DSset"
|
||||
return "DS Parameter set"
|
||||
case Dot11InformationElementIDCFSet:
|
||||
return "CFset"
|
||||
return "CF Parameter set"
|
||||
case Dot11InformationElementIDTIM:
|
||||
return "TIM"
|
||||
return "Traffic Indication Map (TIM)"
|
||||
case Dot11InformationElementIDIBSSSet:
|
||||
return "IBSSset"
|
||||
return "IBSS Parameter set"
|
||||
case Dot11InformationElementIDCountryInfo:
|
||||
return "Country Information"
|
||||
case Dot11InformationElementIDHoppingPatternParam:
|
||||
return "Hopping Pattern Parameters"
|
||||
case Dot11InformationElementIDHoppingPatternTable:
|
||||
return "Hopping Pattern Table"
|
||||
case Dot11InformationElementIDRequest:
|
||||
return "Request"
|
||||
case Dot11InformationElementIDQBSSLoadElem:
|
||||
return "QBSS Load Element"
|
||||
case Dot11InformationElementIDEDCAParamSet:
|
||||
return "EDCA Parameter Set"
|
||||
case Dot11InformationElementIDTrafficSpec:
|
||||
return "Traffic Specification"
|
||||
case Dot11InformationElementIDTrafficClass:
|
||||
return "Traffic Classification"
|
||||
case Dot11InformationElementIDSchedule:
|
||||
return "Schedule"
|
||||
case Dot11InformationElementIDChallenge:
|
||||
return "Challenge"
|
||||
return "Challenge text"
|
||||
case Dot11InformationElementIDPowerConst:
|
||||
return "Power Constraint"
|
||||
case Dot11InformationElementIDPowerCapability:
|
||||
return "Power Capability"
|
||||
case Dot11InformationElementIDTPCRequest:
|
||||
return "TPC Request"
|
||||
case Dot11InformationElementIDTPCReport:
|
||||
return "TPC Report"
|
||||
case Dot11InformationElementIDSupportedChannels:
|
||||
return "Supported Channels"
|
||||
case Dot11InformationElementIDSwitchChannelAnnounce:
|
||||
return "Channel Switch Announcement"
|
||||
case Dot11InformationElementIDMeasureRequest:
|
||||
return "Measurement Request"
|
||||
case Dot11InformationElementIDMeasureReport:
|
||||
return "Measurement Report"
|
||||
case Dot11InformationElementIDQuiet:
|
||||
return "Quiet"
|
||||
case Dot11InformationElementIDIBSSDFS:
|
||||
return "IBSS DFS"
|
||||
case Dot11InformationElementIDERPInfo:
|
||||
return "ERPinfo"
|
||||
return "ERP Information"
|
||||
case Dot11InformationElementIDTSDelay:
|
||||
return "TS Delay"
|
||||
case Dot11InformationElementIDTCLASProcessing:
|
||||
return "TCLAS Processing"
|
||||
case Dot11InformationElementIDHTCapabilities:
|
||||
return "HT Capabilities (802.11n D1.10)"
|
||||
case Dot11InformationElementIDQOSCapability:
|
||||
return "QOS capability"
|
||||
return "QOS Capability"
|
||||
case Dot11InformationElementIDERPInfo2:
|
||||
return "ERPinfo2"
|
||||
return "ERP Information-2"
|
||||
case Dot11InformationElementIDRSNInfo:
|
||||
return "RSNinfo"
|
||||
return "RSN Information"
|
||||
case Dot11InformationElementIDESRates:
|
||||
return "ESrates"
|
||||
return "Extended Supported Rates"
|
||||
case Dot11InformationElementIDAPChannelReport:
|
||||
return "AP Channel Report"
|
||||
case Dot11InformationElementIDNeighborReport:
|
||||
return "Neighbor Report"
|
||||
case Dot11InformationElementIDRCPI:
|
||||
return "RCPI"
|
||||
case Dot11InformationElementIDMobilityDomain:
|
||||
return "Mobility Domain"
|
||||
case Dot11InformationElementIDFastBSSTrans:
|
||||
return "Fast BSS Transition"
|
||||
case Dot11InformationElementIDTimeoutInt:
|
||||
return "Timeout Interval"
|
||||
case Dot11InformationElementIDRICData:
|
||||
return "RIC Data"
|
||||
case Dot11InformationElementIDDSERegisteredLoc:
|
||||
return "DSE Registered Location"
|
||||
case Dot11InformationElementIDSuppOperatingClass:
|
||||
return "Supported Operating Classes"
|
||||
case Dot11InformationElementIDExtChanSwitchAnnounce:
|
||||
return "Extended Channel Switch Announcement"
|
||||
case Dot11InformationElementIDHTInfo:
|
||||
return "HT Information (802.11n D1.10)"
|
||||
case Dot11InformationElementIDSecChanOffset:
|
||||
return "Secondary Channel Offset (802.11n D1.10)"
|
||||
case Dot11InformationElementIDBSSAverageAccessDelay:
|
||||
return "BSS Average Access Delay"
|
||||
case Dot11InformationElementIDAntenna:
|
||||
return "Antenna"
|
||||
case Dot11InformationElementIDRSNI:
|
||||
return "RSNI"
|
||||
case Dot11InformationElementIDMeasurePilotTrans:
|
||||
return "Measurement Pilot Transmission"
|
||||
case Dot11InformationElementIDBSSAvailAdmCapacity:
|
||||
return "BSS Available Admission Capacity"
|
||||
case Dot11InformationElementIDBSSACAccDelayWAPIParam:
|
||||
return "BSS AC Access Delay/WAPI Parameter Set"
|
||||
case Dot11InformationElementIDTimeAdvertisement:
|
||||
return "Time Advertisement"
|
||||
case Dot11InformationElementIDRMEnabledCapabilities:
|
||||
return "RM Enabled Capabilities"
|
||||
case Dot11InformationElementIDMultipleBSSID:
|
||||
return "Multiple BSSID"
|
||||
case Dot11InformationElementID2040BSSCoExist:
|
||||
return "20/40 BSS Coexistence"
|
||||
case Dot11InformationElementID2040BSSIntChanReport:
|
||||
return "20/40 BSS Intolerant Channel Report"
|
||||
case Dot11InformationElementIDOverlapBSSScanParam:
|
||||
return "Overlapping BSS Scan Parameters"
|
||||
case Dot11InformationElementIDRICDescriptor:
|
||||
return "RIC Descriptor"
|
||||
case Dot11InformationElementIDManagementMIC:
|
||||
return "Management MIC"
|
||||
case Dot11InformationElementIDEventRequest:
|
||||
return "Event Request"
|
||||
case Dot11InformationElementIDEventReport:
|
||||
return "Event Report"
|
||||
case Dot11InformationElementIDDiagnosticRequest:
|
||||
return "Diagnostic Request"
|
||||
case Dot11InformationElementIDDiagnosticReport:
|
||||
return "Diagnostic Report"
|
||||
case Dot11InformationElementIDLocationParam:
|
||||
return "Location Parameters"
|
||||
case Dot11InformationElementIDNonTransBSSIDCapability:
|
||||
return "Non Transmitted BSSID Capability"
|
||||
case Dot11InformationElementIDSSIDList:
|
||||
return "SSID List"
|
||||
case Dot11InformationElementIDMultipleBSSIDIndex:
|
||||
return "Multiple BSSID Index"
|
||||
case Dot11InformationElementIDFMSDescriptor:
|
||||
return "FMS Descriptor"
|
||||
case Dot11InformationElementIDFMSRequest:
|
||||
return "FMS Request"
|
||||
case Dot11InformationElementIDFMSResponse:
|
||||
return "FMS Response"
|
||||
case Dot11InformationElementIDQOSTrafficCapability:
|
||||
return "QoS Traffic Capability"
|
||||
case Dot11InformationElementIDBSSMaxIdlePeriod:
|
||||
return "BSS Max Idle Period"
|
||||
case Dot11InformationElementIDTFSRequest:
|
||||
return "TFS Request"
|
||||
case Dot11InformationElementIDTFSResponse:
|
||||
return "TFS Response"
|
||||
case Dot11InformationElementIDWNMSleepMode:
|
||||
return "WNM-Sleep Mode"
|
||||
case Dot11InformationElementIDTIMBroadcastRequest:
|
||||
return "TIM Broadcast Request"
|
||||
case Dot11InformationElementIDTIMBroadcastResponse:
|
||||
return "TIM Broadcast Response"
|
||||
case Dot11InformationElementIDCollInterferenceReport:
|
||||
return "Collocated Interference Report"
|
||||
case Dot11InformationElementIDChannelUsage:
|
||||
return "Channel Usage"
|
||||
case Dot11InformationElementIDTimeZone:
|
||||
return "Time Zone"
|
||||
case Dot11InformationElementIDDMSRequest:
|
||||
return "DMS Request"
|
||||
case Dot11InformationElementIDDMSResponse:
|
||||
return "DMS Response"
|
||||
case Dot11InformationElementIDLinkIdentifier:
|
||||
return "Link Identifier"
|
||||
case Dot11InformationElementIDWakeupSchedule:
|
||||
return "Wakeup Schedule"
|
||||
case Dot11InformationElementIDChannelSwitchTiming:
|
||||
return "Channel Switch Timing"
|
||||
case Dot11InformationElementIDPTIControl:
|
||||
return "PTI Control"
|
||||
case Dot11InformationElementIDPUBufferStatus:
|
||||
return "PU Buffer Status"
|
||||
case Dot11InformationElementIDInterworking:
|
||||
return "Interworking"
|
||||
case Dot11InformationElementIDAdvertisementProtocol:
|
||||
return "Advertisement Protocol"
|
||||
case Dot11InformationElementIDExpBWRequest:
|
||||
return "Expedited Bandwidth Request"
|
||||
case Dot11InformationElementIDQOSMapSet:
|
||||
return "QoS Map Set"
|
||||
case Dot11InformationElementIDRoamingConsortium:
|
||||
return "Roaming Consortium"
|
||||
case Dot11InformationElementIDEmergencyAlertIdentifier:
|
||||
return "Emergency Alert Identifier"
|
||||
case Dot11InformationElementIDMeshConfiguration:
|
||||
return "Mesh Configuration"
|
||||
case Dot11InformationElementIDMeshID:
|
||||
return "Mesh ID"
|
||||
case Dot11InformationElementIDMeshLinkMetricReport:
|
||||
return "Mesh Link Metric Report"
|
||||
case Dot11InformationElementIDCongestionNotification:
|
||||
return "Congestion Notification"
|
||||
case Dot11InformationElementIDMeshPeeringManagement:
|
||||
return "Mesh Peering Management"
|
||||
case Dot11InformationElementIDMeshChannelSwitchParam:
|
||||
return "Mesh Channel Switch Parameters"
|
||||
case Dot11InformationElementIDMeshAwakeWindows:
|
||||
return "Mesh Awake Windows"
|
||||
case Dot11InformationElementIDBeaconTiming:
|
||||
return "Beacon Timing"
|
||||
case Dot11InformationElementIDMCCAOPSetupRequest:
|
||||
return "MCCAOP Setup Request"
|
||||
case Dot11InformationElementIDMCCAOPSetupReply:
|
||||
return "MCCAOP SETUP Reply"
|
||||
case Dot11InformationElementIDMCCAOPAdvertisement:
|
||||
return "MCCAOP Advertisement"
|
||||
case Dot11InformationElementIDMCCAOPTeardown:
|
||||
return "MCCAOP Teardown"
|
||||
case Dot11InformationElementIDGateAnnouncement:
|
||||
return "Gate Announcement"
|
||||
case Dot11InformationElementIDRootAnnouncement:
|
||||
return "Root Announcement"
|
||||
case Dot11InformationElementIDExtCapability:
|
||||
return "Extended Capabilities"
|
||||
case Dot11InformationElementIDAgereProprietary:
|
||||
return "Agere Proprietary"
|
||||
case Dot11InformationElementIDPathRequest:
|
||||
return "Path Request"
|
||||
case Dot11InformationElementIDPathReply:
|
||||
return "Path Reply"
|
||||
case Dot11InformationElementIDPathError:
|
||||
return "Path Error"
|
||||
case Dot11InformationElementIDCiscoCCX1CKIPDeviceName:
|
||||
return "Cisco CCX1 CKIP + Device Name"
|
||||
case Dot11InformationElementIDCiscoCCX2:
|
||||
return "Cisco CCX2"
|
||||
case Dot11InformationElementIDProxyUpdate:
|
||||
return "Proxy Update"
|
||||
case Dot11InformationElementIDProxyUpdateConfirmation:
|
||||
return "Proxy Update Confirmation"
|
||||
case Dot11InformationElementIDAuthMeshPerringExch:
|
||||
return "Auhenticated Mesh Perring Exchange"
|
||||
case Dot11InformationElementIDMIC:
|
||||
return "MIC (Message Integrity Code)"
|
||||
case Dot11InformationElementIDDestinationURI:
|
||||
return "Destination URI"
|
||||
case Dot11InformationElementIDUAPSDCoexistence:
|
||||
return "U-APSD Coexistence"
|
||||
case Dot11InformationElementIDWakeupSchedule80211ad:
|
||||
return "Wakeup Schedule 802.11ad"
|
||||
case Dot11InformationElementIDExtendedSchedule:
|
||||
return "Extended Schedule"
|
||||
case Dot11InformationElementIDSTAAvailability:
|
||||
return "STA Availability"
|
||||
case Dot11InformationElementIDDMGTSPEC:
|
||||
return "DMG TSPEC"
|
||||
case Dot11InformationElementIDNextDMGATI:
|
||||
return "Next DMG ATI"
|
||||
case Dot11InformationElementIDDMSCapabilities:
|
||||
return "DMG Capabilities"
|
||||
case Dot11InformationElementIDCiscoUnknown95:
|
||||
return "Cisco Unknown 95"
|
||||
case Dot11InformationElementIDVendor2:
|
||||
return "Vendor Specific"
|
||||
case Dot11InformationElementIDDMGOperating:
|
||||
return "DMG Operating"
|
||||
case Dot11InformationElementIDDMGBSSParamChange:
|
||||
return "DMG BSS Parameter Change"
|
||||
case Dot11InformationElementIDDMGBeamRefinement:
|
||||
return "DMG Beam Refinement"
|
||||
case Dot11InformationElementIDChannelMeasFeedback:
|
||||
return "Channel Measurement Feedback"
|
||||
case Dot11InformationElementIDAwakeWindow:
|
||||
return "Awake Window"
|
||||
case Dot11InformationElementIDMultiBand:
|
||||
return "Multi Band"
|
||||
case Dot11InformationElementIDADDBAExtension:
|
||||
return "ADDBA Extension"
|
||||
case Dot11InformationElementIDNEXTPCPList:
|
||||
return "NEXTPCP List"
|
||||
case Dot11InformationElementIDPCPHandover:
|
||||
return "PCP Handover"
|
||||
case Dot11InformationElementIDDMGLinkMargin:
|
||||
return "DMG Link Margin"
|
||||
case Dot11InformationElementIDSwitchingStream:
|
||||
return "Switching Stream"
|
||||
case Dot11InformationElementIDSessionTransmission:
|
||||
return "Session Transmission"
|
||||
case Dot11InformationElementIDDynamicTonePairReport:
|
||||
return "Dynamic Tone Pairing Report"
|
||||
case Dot11InformationElementIDClusterReport:
|
||||
return "Cluster Report"
|
||||
case Dot11InformationElementIDRelayCapabilities:
|
||||
return "Relay Capabilities"
|
||||
case Dot11InformationElementIDRelayTransferParameter:
|
||||
return "Relay Transfer Parameter"
|
||||
case Dot11InformationElementIDBeamlinkMaintenance:
|
||||
return "Beamlink Maintenance"
|
||||
case Dot11InformationElementIDMultipleMacSublayers:
|
||||
return "Multiple MAC Sublayers"
|
||||
case Dot11InformationElementIDUPID:
|
||||
return "U-PID"
|
||||
case Dot11InformationElementIDDMGLinkAdaptionAck:
|
||||
return "DMG Link Adaption Acknowledgment"
|
||||
case Dot11InformationElementIDSymbolProprietary:
|
||||
return "Symbol Proprietary"
|
||||
case Dot11InformationElementIDMCCAOPAdvertOverview:
|
||||
return "MCCAOP Advertisement Overview"
|
||||
case Dot11InformationElementIDQuietPeriodRequest:
|
||||
return "Quiet Period Request"
|
||||
case Dot11InformationElementIDQuietPeriodResponse:
|
||||
return "Quiet Period Response"
|
||||
case Dot11InformationElementIDECPACPolicy:
|
||||
return "ECPAC Policy"
|
||||
case Dot11InformationElementIDClusterTimeOffset:
|
||||
return "Cluster Time Offset"
|
||||
case Dot11InformationElementIDAntennaSectorID:
|
||||
return "Antenna Sector ID"
|
||||
case Dot11InformationElementIDVHTCapabilities:
|
||||
return "VHT Capabilities (IEEE Std 802.11ac/D3.1)"
|
||||
case Dot11InformationElementIDVHTOperation:
|
||||
return "VHT Operation (IEEE Std 802.11ac/D3.1)"
|
||||
case Dot11InformationElementIDExtendedBSSLoad:
|
||||
return "Extended BSS Load"
|
||||
case Dot11InformationElementIDWideBWChannelSwitch:
|
||||
return "Wide Bandwidth Channel Switch"
|
||||
case Dot11InformationElementIDVHTTxPowerEnvelope:
|
||||
return "VHT Tx Power Envelope (IEEE Std 802.11ac/D5.0)"
|
||||
case Dot11InformationElementIDChannelSwitchWrapper:
|
||||
return "Channel Switch Wrapper"
|
||||
case Dot11InformationElementIDOperatingModeNotification:
|
||||
return "Operating Mode Notification"
|
||||
case Dot11InformationElementIDUPSIM:
|
||||
return "UP SIM"
|
||||
case Dot11InformationElementIDReducedNeighborReport:
|
||||
return "Reduced Neighbor Report"
|
||||
case Dot11InformationElementIDTVHTOperation:
|
||||
return "TVHT Op"
|
||||
case Dot11InformationElementIDDeviceLocation:
|
||||
return "Device Location"
|
||||
case Dot11InformationElementIDWhiteSpaceMap:
|
||||
return "White Space Map"
|
||||
case Dot11InformationElementIDFineTuningMeasureParams:
|
||||
return "Fine Tuning Measure Parameters"
|
||||
case Dot11InformationElementIDVendor:
|
||||
return "Vendor"
|
||||
case Dot11InformationElementIDReserved:
|
||||
return "Reserved"
|
||||
default:
|
||||
return "Unknown information element id"
|
||||
}
|
||||
@@ -303,7 +769,7 @@ func (a Dot11InformationElementID) String() string {
|
||||
|
||||
// Dot11 provides an IEEE 802.11 base packet header.
|
||||
// See http://standards.ieee.org/findstds/standard/802.11-2012.html
|
||||
// for excrutiating detail.
|
||||
// for excruciating detail.
|
||||
type Dot11 struct {
|
||||
BaseLayer
|
||||
Type Dot11Type
|
||||
@@ -317,23 +783,138 @@ type Dot11 struct {
|
||||
SequenceNumber uint16
|
||||
FragmentNumber uint16
|
||||
Checksum uint32
|
||||
QOS *Dot11QOS
|
||||
HTControl *Dot11HTControl
|
||||
DataLayer gopacket.Layer
|
||||
}
|
||||
|
||||
type Dot11QOS struct {
|
||||
TID uint8 /* Traffic IDentifier */
|
||||
EOSP bool /* End of service period */
|
||||
AckPolicy Dot11AckPolicy
|
||||
TXOP uint8
|
||||
}
|
||||
|
||||
type Dot11HTControl struct {
|
||||
ACConstraint bool
|
||||
RDGMorePPDU bool
|
||||
|
||||
VHT *Dot11HTControlVHT
|
||||
HT *Dot11HTControlHT
|
||||
}
|
||||
|
||||
type Dot11HTControlHT struct {
|
||||
LinkAdapationControl *Dot11LinkAdapationControl
|
||||
CalibrationPosition uint8
|
||||
CalibrationSequence uint8
|
||||
CSISteering uint8
|
||||
NDPAnnouncement bool
|
||||
DEI bool
|
||||
}
|
||||
|
||||
type Dot11HTControlVHT struct {
|
||||
MRQ bool
|
||||
UnsolicitedMFB bool
|
||||
MSI *uint8
|
||||
MFB Dot11HTControlMFB
|
||||
CompressedMSI *uint8
|
||||
STBCIndication bool
|
||||
MFSI *uint8
|
||||
GID *uint8
|
||||
CodingType *Dot11CodingType
|
||||
FbTXBeamformed bool
|
||||
}
|
||||
|
||||
type Dot11HTControlMFB struct {
|
||||
NumSTS uint8
|
||||
VHTMCS uint8
|
||||
BW uint8
|
||||
SNR int8
|
||||
}
|
||||
|
||||
type Dot11LinkAdapationControl struct {
|
||||
TRQ bool
|
||||
MRQ bool
|
||||
MSI uint8
|
||||
MFSI uint8
|
||||
ASEL *Dot11ASEL
|
||||
MFB *uint8
|
||||
}
|
||||
|
||||
type Dot11ASEL struct {
|
||||
Command uint8
|
||||
Data uint8
|
||||
}
|
||||
|
||||
type Dot11CodingType uint8
|
||||
|
||||
const (
|
||||
Dot11CodingTypeBCC = 0
|
||||
Dot11CodingTypeLDPC = 1
|
||||
)
|
||||
|
||||
func (a Dot11CodingType) String() string {
|
||||
switch a {
|
||||
case Dot11CodingTypeBCC:
|
||||
return "BCC"
|
||||
case Dot11CodingTypeLDPC:
|
||||
return "LDPC"
|
||||
default:
|
||||
return "Unknown coding type"
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Dot11HTControlMFB) NoFeedBackPresent() bool {
|
||||
return m.VHTMCS == 15 && m.NumSTS == 7
|
||||
}
|
||||
|
||||
func decodeDot11(data []byte, p gopacket.PacketBuilder) error {
|
||||
d := &Dot11{}
|
||||
return decodingLayerDecoder(d, data, p)
|
||||
err := d.DecodeFromBytes(data, p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.AddLayer(d)
|
||||
if d.DataLayer != nil {
|
||||
p.AddLayer(d.DataLayer)
|
||||
}
|
||||
return p.NextDecoder(d.NextLayerType())
|
||||
}
|
||||
|
||||
func (m *Dot11) LayerType() gopacket.LayerType { return LayerTypeDot11 }
|
||||
func (m *Dot11) CanDecode() gopacket.LayerClass { return LayerTypeDot11 }
|
||||
func (m *Dot11) NextLayerType() gopacket.LayerType {
|
||||
if m.Flags.WEP() {
|
||||
return (LayerTypeDot11WEP)
|
||||
if m.DataLayer != nil {
|
||||
if m.Flags.WEP() {
|
||||
return LayerTypeDot11WEP
|
||||
}
|
||||
return m.DataLayer.(gopacket.DecodingLayer).NextLayerType()
|
||||
}
|
||||
|
||||
return m.Type.LayerType()
|
||||
}
|
||||
|
||||
func createU8(x uint8) *uint8 {
|
||||
return &x
|
||||
}
|
||||
|
||||
var dataDecodeMap = map[Dot11Type]func() gopacket.DecodingLayer{
|
||||
Dot11TypeData: func() gopacket.DecodingLayer { return &Dot11Data{} },
|
||||
Dot11TypeDataCFAck: func() gopacket.DecodingLayer { return &Dot11DataCFAck{} },
|
||||
Dot11TypeDataCFPoll: func() gopacket.DecodingLayer { return &Dot11DataCFPoll{} },
|
||||
Dot11TypeDataCFAckPoll: func() gopacket.DecodingLayer { return &Dot11DataCFAckPoll{} },
|
||||
Dot11TypeDataNull: func() gopacket.DecodingLayer { return &Dot11DataNull{} },
|
||||
Dot11TypeDataCFAckNoData: func() gopacket.DecodingLayer { return &Dot11DataCFAckNoData{} },
|
||||
Dot11TypeDataCFPollNoData: func() gopacket.DecodingLayer { return &Dot11DataCFPollNoData{} },
|
||||
Dot11TypeDataCFAckPollNoData: func() gopacket.DecodingLayer { return &Dot11DataCFAckPollNoData{} },
|
||||
Dot11TypeDataQOSData: func() gopacket.DecodingLayer { return &Dot11DataQOSData{} },
|
||||
Dot11TypeDataQOSDataCFAck: func() gopacket.DecodingLayer { return &Dot11DataQOSDataCFAck{} },
|
||||
Dot11TypeDataQOSDataCFPoll: func() gopacket.DecodingLayer { return &Dot11DataQOSDataCFPoll{} },
|
||||
Dot11TypeDataQOSDataCFAckPoll: func() gopacket.DecodingLayer { return &Dot11DataQOSDataCFAckPoll{} },
|
||||
Dot11TypeDataQOSNull: func() gopacket.DecodingLayer { return &Dot11DataQOSNull{} },
|
||||
Dot11TypeDataQOSCFPollNoData: func() gopacket.DecodingLayer { return &Dot11DataQOSCFPollNoData{} },
|
||||
Dot11TypeDataQOSCFAckPollNoData: func() gopacket.DecodingLayer { return &Dot11DataQOSCFAckPollNoData{} },
|
||||
}
|
||||
|
||||
func (m *Dot11) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||||
if len(data) < 10 {
|
||||
df.SetTruncated()
|
||||
@@ -385,7 +966,112 @@ func (m *Dot11) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||||
offset += 6
|
||||
}
|
||||
|
||||
m.BaseLayer = BaseLayer{Contents: data[0:offset], Payload: data[offset : len(data)-4]}
|
||||
if m.Type.QOS() {
|
||||
if len(data) < offset+2 {
|
||||
df.SetTruncated()
|
||||
return fmt.Errorf("Dot11 length %v too short, %v required", len(data), offset+6)
|
||||
}
|
||||
m.QOS = &Dot11QOS{
|
||||
TID: (uint8(data[offset]) & 0x0F),
|
||||
EOSP: (uint8(data[offset]) & 0x10) == 0x10,
|
||||
AckPolicy: Dot11AckPolicy((uint8(data[offset]) & 0x60) >> 5),
|
||||
TXOP: uint8(data[offset+1]),
|
||||
}
|
||||
offset += 2
|
||||
}
|
||||
if m.Flags.Order() && (m.Type.QOS() || mainType == Dot11TypeMgmt) {
|
||||
if len(data) < offset+4 {
|
||||
df.SetTruncated()
|
||||
return fmt.Errorf("Dot11 length %v too short, %v required", len(data), offset+6)
|
||||
}
|
||||
|
||||
htc := &Dot11HTControl{
|
||||
ACConstraint: data[offset+3]&0x40 != 0,
|
||||
RDGMorePPDU: data[offset+3]&0x80 != 0,
|
||||
}
|
||||
m.HTControl = htc
|
||||
|
||||
if data[offset]&0x1 != 0 { // VHT Variant
|
||||
vht := &Dot11HTControlVHT{}
|
||||
htc.VHT = vht
|
||||
vht.MRQ = data[offset]&0x4 != 0
|
||||
vht.UnsolicitedMFB = data[offset+3]&0x20 != 0
|
||||
vht.MFB = Dot11HTControlMFB{
|
||||
NumSTS: uint8(data[offset+1] >> 1 & 0x7),
|
||||
VHTMCS: uint8(data[offset+1] >> 4 & 0xF),
|
||||
BW: uint8(data[offset+2] & 0x3),
|
||||
SNR: int8((-(data[offset+2] >> 2 & 0x20))+data[offset+2]>>2&0x1F) + 22,
|
||||
}
|
||||
|
||||
if vht.UnsolicitedMFB {
|
||||
if !vht.MFB.NoFeedBackPresent() {
|
||||
vht.CompressedMSI = createU8(data[offset] >> 3 & 0x3)
|
||||
vht.STBCIndication = data[offset]&0x20 != 0
|
||||
vht.CodingType = (*Dot11CodingType)(createU8(data[offset+3] >> 3 & 0x1))
|
||||
vht.FbTXBeamformed = data[offset+3]&0x10 != 0
|
||||
vht.GID = createU8(
|
||||
data[offset]>>6 +
|
||||
(data[offset+1] & 0x1 << 2) +
|
||||
data[offset+3]&0x7<<3)
|
||||
}
|
||||
} else {
|
||||
if vht.MRQ {
|
||||
vht.MSI = createU8((data[offset] >> 3) & 0x07)
|
||||
}
|
||||
vht.MFSI = createU8(data[offset]>>6 + (data[offset+1] & 0x1 << 2))
|
||||
}
|
||||
|
||||
} else { // HT Variant
|
||||
ht := &Dot11HTControlHT{}
|
||||
htc.HT = ht
|
||||
|
||||
lac := &Dot11LinkAdapationControl{}
|
||||
ht.LinkAdapationControl = lac
|
||||
lac.TRQ = data[offset]&0x2 != 0
|
||||
lac.MFSI = data[offset]>>6&0x3 + data[offset+1]&0x1<<3
|
||||
if data[offset]&0x3C == 0x38 { // ASEL
|
||||
lac.ASEL = &Dot11ASEL{
|
||||
Command: data[offset+1] >> 1 & 0x7,
|
||||
Data: data[offset+1] >> 4 & 0xF,
|
||||
}
|
||||
} else {
|
||||
lac.MRQ = data[offset]&0x4 != 0
|
||||
if lac.MRQ {
|
||||
lac.MSI = data[offset] >> 3 & 0x7
|
||||
}
|
||||
lac.MFB = createU8(data[offset+1] >> 1)
|
||||
}
|
||||
ht.CalibrationPosition = data[offset+2] & 0x3
|
||||
ht.CalibrationSequence = data[offset+2] >> 2 & 0x3
|
||||
ht.CSISteering = data[offset+2] >> 6 & 0x3
|
||||
ht.NDPAnnouncement = data[offset+3]&0x1 != 0
|
||||
if mainType != Dot11TypeMgmt {
|
||||
ht.DEI = data[offset+3]&0x20 != 0
|
||||
}
|
||||
}
|
||||
|
||||
offset += 4
|
||||
}
|
||||
|
||||
if len(data) < offset+4 {
|
||||
df.SetTruncated()
|
||||
return fmt.Errorf("Dot11 length %v too short, %v required", len(data), offset+4)
|
||||
}
|
||||
|
||||
m.BaseLayer = BaseLayer{
|
||||
Contents: data[0:offset],
|
||||
Payload: data[offset : len(data)-4],
|
||||
}
|
||||
|
||||
if mainType == Dot11TypeData {
|
||||
l := dataDecodeMap[m.Type]()
|
||||
err := l.DecodeFromBytes(m.BaseLayer.Payload, df)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m.DataLayer = l.(gopacket.Layer)
|
||||
}
|
||||
|
||||
m.Checksum = binary.LittleEndian.Uint32(data[len(data)-4 : len(data)])
|
||||
return nil
|
||||
}
|
||||
@@ -474,7 +1160,7 @@ type Dot11WEP struct {
|
||||
BaseLayer
|
||||
}
|
||||
|
||||
func (m *Dot11WEP) NextLayerType() gopacket.LayerType { return LayerTypeLLC }
|
||||
func (m *Dot11WEP) NextLayerType() gopacket.LayerType { return gopacket.LayerTypePayload }
|
||||
|
||||
func (m *Dot11WEP) LayerType() gopacket.LayerType { return LayerTypeDot11WEP }
|
||||
func (m *Dot11WEP) CanDecode() gopacket.LayerClass { return LayerTypeDot11WEP }
|
||||
@@ -493,7 +1179,9 @@ type Dot11Data struct {
|
||||
BaseLayer
|
||||
}
|
||||
|
||||
func (m *Dot11Data) NextLayerType() gopacket.LayerType { return LayerTypeLLC }
|
||||
func (m *Dot11Data) NextLayerType() gopacket.LayerType {
|
||||
return LayerTypeLLC
|
||||
}
|
||||
|
||||
func (m *Dot11Data) LayerType() gopacket.LayerType { return LayerTypeDot11Data }
|
||||
func (m *Dot11Data) CanDecode() gopacket.LayerClass { return LayerTypeDot11Data }
|
||||
@@ -618,23 +1306,10 @@ func (m *Dot11DataCFAckPollNoData) DecodeFromBytes(data []byte, df gopacket.Deco
|
||||
|
||||
type Dot11DataQOS struct {
|
||||
Dot11Ctrl
|
||||
TID uint8 /* Traffic IDentifier */
|
||||
EOSP bool /* End of service period */
|
||||
AckPolicy Dot11AckPolicy
|
||||
TXOP uint8
|
||||
}
|
||||
|
||||
func (m *Dot11DataQOS) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||||
if len(data) < 4 {
|
||||
df.SetTruncated()
|
||||
return fmt.Errorf("Dot11DataQOS length %v too short, %v required", len(data), 4)
|
||||
}
|
||||
m.TID = (uint8(data[0]) & 0x0F)
|
||||
m.EOSP = (uint8(data[0]) & 0x10) == 0x10
|
||||
m.AckPolicy = Dot11AckPolicy((uint8(data[0]) & 0x60) >> 5)
|
||||
m.TXOP = uint8(data[1])
|
||||
// TODO: Mesh Control bytes 2:4
|
||||
m.BaseLayer = BaseLayer{Contents: data[0:4], Payload: data[4:]}
|
||||
m.BaseLayer = BaseLayer{Payload: data}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -802,7 +1477,7 @@ func (m *Dot11InformationElement) DecodeFromBytes(data []byte, df gopacket.Decod
|
||||
|
||||
func (d *Dot11InformationElement) String() string {
|
||||
if d.ID == 0 {
|
||||
return fmt.Sprintf("802.11 Information Element (SSID: %v)", string(d.Info))
|
||||
return fmt.Sprintf("802.11 Information Element (ID: %v, Length: %v, SSID: %v)", d.ID, d.Length, string(d.Info))
|
||||
} else if d.ID == 1 {
|
||||
rates := ""
|
||||
for i := 0; i < len(d.Info); i++ {
|
||||
@@ -812,9 +1487,9 @@ func (d *Dot11InformationElement) String() string {
|
||||
rates += fmt.Sprintf("%.1f* ", float32(d.Info[i]&0x7F)*0.5)
|
||||
}
|
||||
}
|
||||
return fmt.Sprintf("802.11 Information Element (Rates: %s Mbit)", rates)
|
||||
return fmt.Sprintf("802.11 Information Element (ID: %v, Length: %v, Rates: %s Mbit)", d.ID, d.Length, rates)
|
||||
} else if d.ID == 221 {
|
||||
return fmt.Sprintf("802.11 Information Element (Vendor: ID: %v, Length: %v, OUI: %X, Info: %X)", d.ID, d.Length, d.OUI, d.Info)
|
||||
return fmt.Sprintf("802.11 Information Element (ID: %v, Length: %v, OUI: %X, Info: %X)", d.ID, d.Length, d.OUI, d.Info)
|
||||
} else {
|
||||
return fmt.Sprintf("802.11 Information Element (ID: %v, Length: %v, Info: %X)", d.ID, d.Length, d.Info)
|
||||
}
|
||||
|
||||
+236
@@ -8,6 +8,7 @@ package layers
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"github.com/google/gopacket"
|
||||
)
|
||||
|
||||
@@ -55,3 +56,238 @@ func decodeEAPOL(data []byte, p gopacket.PacketBuilder) error {
|
||||
e := &EAPOL{}
|
||||
return decodingLayerDecoder(e, data, p)
|
||||
}
|
||||
|
||||
// EAPOLKeyDescriptorType is an enumeration of key descriptor types
|
||||
// as specified by 802.1x in the EAPOL-Key frame
|
||||
type EAPOLKeyDescriptorType uint8
|
||||
|
||||
// Enumeration of EAPOLKeyDescriptorType
|
||||
const (
|
||||
EAPOLKeyDescriptorTypeRC4 EAPOLKeyDescriptorType = 1
|
||||
EAPOLKeyDescriptorTypeDot11 EAPOLKeyDescriptorType = 2
|
||||
EAPOLKeyDescriptorTypeWPA EAPOLKeyDescriptorType = 254
|
||||
)
|
||||
|
||||
func (kdt EAPOLKeyDescriptorType) String() string {
|
||||
switch kdt {
|
||||
case EAPOLKeyDescriptorTypeRC4:
|
||||
return "RC4"
|
||||
case EAPOLKeyDescriptorTypeDot11:
|
||||
return "802.11"
|
||||
case EAPOLKeyDescriptorTypeWPA:
|
||||
return "WPA"
|
||||
default:
|
||||
return fmt.Sprintf("unknown descriptor type %d", kdt)
|
||||
}
|
||||
}
|
||||
|
||||
// EAPOLKeyDescriptorVersion is an enumeration of versions specifying the
|
||||
// encryption algorithm for the key data and the authentication for the
|
||||
// message integrity code (MIC)
|
||||
type EAPOLKeyDescriptorVersion uint8
|
||||
|
||||
// Enumeration of EAPOLKeyDescriptorVersion
|
||||
const (
|
||||
EAPOLKeyDescriptorVersionOther EAPOLKeyDescriptorVersion = 0
|
||||
EAPOLKeyDescriptorVersionRC4HMACMD5 EAPOLKeyDescriptorVersion = 1
|
||||
EAPOLKeyDescriptorVersionAESHMACSHA1 EAPOLKeyDescriptorVersion = 2
|
||||
EAPOLKeyDescriptorVersionAES128CMAC EAPOLKeyDescriptorVersion = 3
|
||||
)
|
||||
|
||||
func (v EAPOLKeyDescriptorVersion) String() string {
|
||||
switch v {
|
||||
case EAPOLKeyDescriptorVersionOther:
|
||||
return "Other"
|
||||
case EAPOLKeyDescriptorVersionRC4HMACMD5:
|
||||
return "RC4-HMAC-MD5"
|
||||
case EAPOLKeyDescriptorVersionAESHMACSHA1:
|
||||
return "AES-HMAC-SHA1-128"
|
||||
case EAPOLKeyDescriptorVersionAES128CMAC:
|
||||
return "AES-128-CMAC"
|
||||
default:
|
||||
return fmt.Sprintf("unknown version %d", v)
|
||||
}
|
||||
}
|
||||
|
||||
// EAPOLKeyType is an enumeration of key derivation types describing
|
||||
// the purpose of the keys being derived.
|
||||
type EAPOLKeyType uint8
|
||||
|
||||
// Enumeration of EAPOLKeyType
|
||||
const (
|
||||
EAPOLKeyTypeGroupSMK EAPOLKeyType = 0
|
||||
EAPOLKeyTypePairwise EAPOLKeyType = 1
|
||||
)
|
||||
|
||||
func (kt EAPOLKeyType) String() string {
|
||||
switch kt {
|
||||
case EAPOLKeyTypeGroupSMK:
|
||||
return "Group/SMK"
|
||||
case EAPOLKeyTypePairwise:
|
||||
return "Pairwise"
|
||||
default:
|
||||
return fmt.Sprintf("unknown key type %d", kt)
|
||||
}
|
||||
}
|
||||
|
||||
// EAPOLKey defines an EAPOL-Key frame for 802.1x authentication
|
||||
type EAPOLKey struct {
|
||||
BaseLayer
|
||||
KeyDescriptorType EAPOLKeyDescriptorType
|
||||
KeyDescriptorVersion EAPOLKeyDescriptorVersion
|
||||
KeyType EAPOLKeyType
|
||||
KeyIndex uint8
|
||||
Install bool
|
||||
KeyACK bool
|
||||
KeyMIC bool
|
||||
Secure bool
|
||||
MICError bool
|
||||
Request bool
|
||||
HasEncryptedKeyData bool
|
||||
SMKMessage bool
|
||||
KeyLength uint16
|
||||
ReplayCounter uint64
|
||||
Nonce []byte
|
||||
IV []byte
|
||||
RSC uint64
|
||||
ID uint64
|
||||
MIC []byte
|
||||
KeyDataLength uint16
|
||||
EncryptedKeyData []byte
|
||||
}
|
||||
|
||||
// LayerType returns LayerTypeEAPOLKey.
|
||||
func (ek *EAPOLKey) LayerType() gopacket.LayerType {
|
||||
return LayerTypeEAPOLKey
|
||||
}
|
||||
|
||||
// NextLayerType returns layers.LayerTypeDot11InformationElement if the key
|
||||
// data exists and is unencrypted, otherwise it does not expect a next layer.
|
||||
func (ek *EAPOLKey) NextLayerType() gopacket.LayerType {
|
||||
if !ek.HasEncryptedKeyData && ek.KeyDataLength > 0 {
|
||||
return LayerTypeDot11InformationElement
|
||||
}
|
||||
return gopacket.LayerTypePayload
|
||||
}
|
||||
|
||||
const eapolKeyFrameLen = 95
|
||||
|
||||
// DecodeFromBytes decodes the given bytes into this layer.
|
||||
func (ek *EAPOLKey) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||||
if len(data) < eapolKeyFrameLen {
|
||||
df.SetTruncated()
|
||||
return fmt.Errorf("EAPOLKey length %v too short, %v required",
|
||||
len(data), eapolKeyFrameLen)
|
||||
}
|
||||
|
||||
ek.KeyDescriptorType = EAPOLKeyDescriptorType(data[0])
|
||||
|
||||
info := binary.BigEndian.Uint16(data[1:3])
|
||||
ek.KeyDescriptorVersion = EAPOLKeyDescriptorVersion(info & 0x0007)
|
||||
ek.KeyType = EAPOLKeyType((info & 0x0008) >> 3)
|
||||
ek.KeyIndex = uint8((info & 0x0030) >> 4)
|
||||
ek.Install = (info & 0x0040) != 0
|
||||
ek.KeyACK = (info & 0x0080) != 0
|
||||
ek.KeyMIC = (info & 0x0100) != 0
|
||||
ek.Secure = (info & 0x0200) != 0
|
||||
ek.MICError = (info & 0x0400) != 0
|
||||
ek.Request = (info & 0x0800) != 0
|
||||
ek.HasEncryptedKeyData = (info & 0x1000) != 0
|
||||
ek.SMKMessage = (info & 0x2000) != 0
|
||||
|
||||
ek.KeyLength = binary.BigEndian.Uint16(data[3:5])
|
||||
ek.ReplayCounter = binary.BigEndian.Uint64(data[5:13])
|
||||
|
||||
ek.Nonce = data[13:45]
|
||||
ek.IV = data[45:61]
|
||||
ek.RSC = binary.BigEndian.Uint64(data[61:69])
|
||||
ek.ID = binary.BigEndian.Uint64(data[69:77])
|
||||
ek.MIC = data[77:93]
|
||||
|
||||
ek.KeyDataLength = binary.BigEndian.Uint16(data[93:95])
|
||||
|
||||
totalLength := eapolKeyFrameLen + int(ek.KeyDataLength)
|
||||
if len(data) < totalLength {
|
||||
df.SetTruncated()
|
||||
return fmt.Errorf("EAPOLKey data length %d too short, %d required",
|
||||
len(data)-eapolKeyFrameLen, ek.KeyDataLength)
|
||||
}
|
||||
|
||||
if ek.HasEncryptedKeyData {
|
||||
ek.EncryptedKeyData = data[eapolKeyFrameLen:totalLength]
|
||||
ek.BaseLayer = BaseLayer{
|
||||
Contents: data[:totalLength],
|
||||
Payload: data[totalLength:],
|
||||
}
|
||||
} else {
|
||||
ek.BaseLayer = BaseLayer{
|
||||
Contents: data[:eapolKeyFrameLen],
|
||||
Payload: data[eapolKeyFrameLen:],
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SerializeTo writes the serialized form of this layer into the
|
||||
// SerializationBuffer, implementing gopacket.SerializableLayer.
|
||||
// See the docs for gopacket.SerializableLayer for more info.
|
||||
func (ek *EAPOLKey) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
|
||||
buf, err := b.PrependBytes(eapolKeyFrameLen + len(ek.EncryptedKeyData))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
buf[0] = byte(ek.KeyDescriptorType)
|
||||
|
||||
var info uint16
|
||||
info |= uint16(ek.KeyDescriptorVersion)
|
||||
info |= uint16(ek.KeyType) << 3
|
||||
info |= uint16(ek.KeyIndex) << 4
|
||||
if ek.Install {
|
||||
info |= 0x0040
|
||||
}
|
||||
if ek.KeyACK {
|
||||
info |= 0x0080
|
||||
}
|
||||
if ek.KeyMIC {
|
||||
info |= 0x0100
|
||||
}
|
||||
if ek.Secure {
|
||||
info |= 0x0200
|
||||
}
|
||||
if ek.MICError {
|
||||
info |= 0x0400
|
||||
}
|
||||
if ek.Request {
|
||||
info |= 0x0800
|
||||
}
|
||||
if ek.HasEncryptedKeyData {
|
||||
info |= 0x1000
|
||||
}
|
||||
if ek.SMKMessage {
|
||||
info |= 0x2000
|
||||
}
|
||||
binary.BigEndian.PutUint16(buf[1:3], info)
|
||||
|
||||
binary.BigEndian.PutUint16(buf[3:5], ek.KeyLength)
|
||||
binary.BigEndian.PutUint64(buf[5:13], ek.ReplayCounter)
|
||||
|
||||
copy(buf[13:45], ek.Nonce)
|
||||
copy(buf[45:61], ek.IV)
|
||||
binary.BigEndian.PutUint64(buf[61:69], ek.RSC)
|
||||
binary.BigEndian.PutUint64(buf[69:77], ek.ID)
|
||||
copy(buf[77:93], ek.MIC)
|
||||
|
||||
binary.BigEndian.PutUint16(buf[93:95], ek.KeyDataLength)
|
||||
if len(ek.EncryptedKeyData) > 0 {
|
||||
copy(buf[95:95+len(ek.EncryptedKeyData)], ek.EncryptedKeyData)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func decodeEAPOLKey(data []byte, p gopacket.PacketBuilder) error {
|
||||
ek := &EAPOLKey{}
|
||||
return decodingLayerDecoder(ek, data, p)
|
||||
}
|
||||
+36
-150
@@ -10,6 +10,7 @@ package layers
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"runtime"
|
||||
|
||||
"github.com/google/gopacket"
|
||||
)
|
||||
@@ -49,6 +50,7 @@ const (
|
||||
EthernetTypeNortelDiscovery EthernetType = 0x01a2
|
||||
EthernetTypeTransparentEthernetBridging EthernetType = 0x6558
|
||||
EthernetTypeDot1Q EthernetType = 0x8100
|
||||
EthernetTypePPP EthernetType = 0x880b
|
||||
EthernetTypePPPoEDiscovery EthernetType = 0x8863
|
||||
EthernetTypePPPoESession EthernetType = 0x8864
|
||||
EthernetTypeMPLSUnicast EthernetType = 0x8847
|
||||
@@ -80,6 +82,7 @@ const (
|
||||
IPProtocolICMPv6 IPProtocol = 58
|
||||
IPProtocolNoNextHeader IPProtocol = 59
|
||||
IPProtocolIPv6Destination IPProtocol = 60
|
||||
IPProtocolOSPF IPProtocol = 89
|
||||
IPProtocolIPIP IPProtocol = 94
|
||||
IPProtocolEtherIP IPProtocol = 97
|
||||
IPProtocolVRRP IPProtocol = 112
|
||||
@@ -218,12 +221,17 @@ func (d Dot11Type) MainType() Dot11Type {
|
||||
return d & dot11TypeMask
|
||||
}
|
||||
|
||||
func (d Dot11Type) QOS() bool {
|
||||
return d&dot11QOSMask == Dot11TypeDataQOSData
|
||||
}
|
||||
|
||||
const (
|
||||
Dot11TypeMgmt Dot11Type = 0x00
|
||||
Dot11TypeCtrl Dot11Type = 0x01
|
||||
Dot11TypeData Dot11Type = 0x02
|
||||
Dot11TypeReserved Dot11Type = 0x03
|
||||
dot11TypeMask = 0x03
|
||||
dot11QOSMask = 0x23
|
||||
|
||||
// The following are type/subtype conglomerations.
|
||||
|
||||
@@ -271,107 +279,6 @@ const (
|
||||
Dot11TypeDataQOSCFAckPollNoData Dot11Type = 0x3e
|
||||
)
|
||||
|
||||
var (
|
||||
// Each of the following arrays contains mappings of how to handle enum
|
||||
// values for various enum types in gopacket/layers.
|
||||
//
|
||||
// So, EthernetTypeMetadata[2] contains information on how to handle EthernetType
|
||||
// 2, including which name to give it and which decoder to use to decode
|
||||
// packet data of that type. These arrays are filled by default with all of the
|
||||
// protocols gopacket/layers knows how to handle, but users of the library can
|
||||
// add new decoders or override existing ones. For example, if you write a better
|
||||
// TCP decoder, you can override IPProtocolMetadata[IPProtocolTCP].DecodeWith
|
||||
// with your new decoder, and all gopacket/layers decoding will use your new
|
||||
// decoder whenever they encounter that IPProtocol.
|
||||
EthernetTypeMetadata [65536]EnumMetadata
|
||||
IPProtocolMetadata [256]EnumMetadata
|
||||
SCTPChunkTypeMetadata [256]EnumMetadata
|
||||
PPPTypeMetadata [65536]EnumMetadata
|
||||
PPPoECodeMetadata [256]EnumMetadata
|
||||
LinkTypeMetadata [256]EnumMetadata
|
||||
FDDIFrameControlMetadata [256]EnumMetadata
|
||||
EAPOLTypeMetadata [256]EnumMetadata
|
||||
ProtocolFamilyMetadata [256]EnumMetadata
|
||||
Dot11TypeMetadata [256]EnumMetadata
|
||||
USBTypeMetadata [256]EnumMetadata
|
||||
)
|
||||
|
||||
func (a EthernetType) Decode(data []byte, p gopacket.PacketBuilder) error {
|
||||
return EthernetTypeMetadata[a].DecodeWith.Decode(data, p)
|
||||
}
|
||||
func (a EthernetType) String() string {
|
||||
return EthernetTypeMetadata[a].Name
|
||||
}
|
||||
func (a EthernetType) LayerType() gopacket.LayerType {
|
||||
return EthernetTypeMetadata[a].LayerType
|
||||
}
|
||||
func (a IPProtocol) Decode(data []byte, p gopacket.PacketBuilder) error {
|
||||
return IPProtocolMetadata[a].DecodeWith.Decode(data, p)
|
||||
}
|
||||
func (a IPProtocol) String() string {
|
||||
return IPProtocolMetadata[a].Name
|
||||
}
|
||||
func (a IPProtocol) LayerType() gopacket.LayerType {
|
||||
return IPProtocolMetadata[a].LayerType
|
||||
}
|
||||
func (a SCTPChunkType) Decode(data []byte, p gopacket.PacketBuilder) error {
|
||||
return SCTPChunkTypeMetadata[a].DecodeWith.Decode(data, p)
|
||||
}
|
||||
func (a SCTPChunkType) String() string {
|
||||
return SCTPChunkTypeMetadata[a].Name
|
||||
}
|
||||
func (a PPPType) Decode(data []byte, p gopacket.PacketBuilder) error {
|
||||
return PPPTypeMetadata[a].DecodeWith.Decode(data, p)
|
||||
}
|
||||
func (a PPPType) String() string {
|
||||
return PPPTypeMetadata[a].Name
|
||||
}
|
||||
func (a LinkType) Decode(data []byte, p gopacket.PacketBuilder) error {
|
||||
return LinkTypeMetadata[a].DecodeWith.Decode(data, p)
|
||||
}
|
||||
func (a LinkType) String() string {
|
||||
return LinkTypeMetadata[a].Name
|
||||
}
|
||||
func (a PPPoECode) Decode(data []byte, p gopacket.PacketBuilder) error {
|
||||
return PPPoECodeMetadata[a].DecodeWith.Decode(data, p)
|
||||
}
|
||||
func (a PPPoECode) String() string {
|
||||
return PPPoECodeMetadata[a].Name
|
||||
}
|
||||
func (a FDDIFrameControl) Decode(data []byte, p gopacket.PacketBuilder) error {
|
||||
return FDDIFrameControlMetadata[a].DecodeWith.Decode(data, p)
|
||||
}
|
||||
func (a FDDIFrameControl) String() string {
|
||||
return FDDIFrameControlMetadata[a].Name
|
||||
}
|
||||
func (a EAPOLType) Decode(data []byte, p gopacket.PacketBuilder) error {
|
||||
return EAPOLTypeMetadata[a].DecodeWith.Decode(data, p)
|
||||
}
|
||||
func (a EAPOLType) String() string {
|
||||
return EAPOLTypeMetadata[a].Name
|
||||
}
|
||||
func (a EAPOLType) LayerType() gopacket.LayerType {
|
||||
return EAPOLTypeMetadata[a].LayerType
|
||||
}
|
||||
func (a ProtocolFamily) Decode(data []byte, p gopacket.PacketBuilder) error {
|
||||
return ProtocolFamilyMetadata[a].DecodeWith.Decode(data, p)
|
||||
}
|
||||
func (a ProtocolFamily) String() string {
|
||||
return ProtocolFamilyMetadata[a].Name
|
||||
}
|
||||
func (a ProtocolFamily) LayerType() gopacket.LayerType {
|
||||
return ProtocolFamilyMetadata[a].LayerType
|
||||
}
|
||||
func (a Dot11Type) Decode(data []byte, p gopacket.PacketBuilder) error {
|
||||
return Dot11TypeMetadata[a].DecodeWith.Decode(data, p)
|
||||
}
|
||||
func (a Dot11Type) String() string {
|
||||
return Dot11TypeMetadata[a].Name
|
||||
}
|
||||
func (a Dot11Type) LayerType() gopacket.LayerType {
|
||||
return Dot11TypeMetadata[a].LayerType
|
||||
}
|
||||
|
||||
// Decode a raw v4 or v6 IP packet.
|
||||
func decodeIPv4or6(data []byte, p gopacket.PacketBuilder) error {
|
||||
version := data[0] >> 4
|
||||
@@ -384,58 +291,28 @@ func decodeIPv4or6(data []byte, p gopacket.PacketBuilder) error {
|
||||
return fmt.Errorf("Invalid IP packet version %v", version)
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Here we link up all enumerations with their respective names and decoders.
|
||||
for i := 0; i < 65536; i++ {
|
||||
EthernetTypeMetadata[i] = EnumMetadata{
|
||||
DecodeWith: errorFunc(fmt.Sprintf("Unable to decode ethernet type %d", i)),
|
||||
Name: fmt.Sprintf("UnknownEthernetType(%d)", i),
|
||||
}
|
||||
PPPTypeMetadata[i] = EnumMetadata{
|
||||
DecodeWith: errorFunc(fmt.Sprintf("Unable to decode PPP type %d", i)),
|
||||
Name: fmt.Sprintf("UnknownPPPType(%d)", i),
|
||||
}
|
||||
}
|
||||
for i := 0; i < 256; i++ {
|
||||
IPProtocolMetadata[i] = EnumMetadata{
|
||||
DecodeWith: errorFunc(fmt.Sprintf("Unable to decode IP protocol %d", i)),
|
||||
Name: fmt.Sprintf("UnknownIPProtocol(%d)", i),
|
||||
}
|
||||
SCTPChunkTypeMetadata[i] = EnumMetadata{
|
||||
DecodeWith: errorFunc(fmt.Sprintf("Unable to decode SCTP chunk type %d", i)),
|
||||
Name: fmt.Sprintf("UnknownSCTPChunkType(%d)", i),
|
||||
}
|
||||
PPPoECodeMetadata[i] = EnumMetadata{
|
||||
DecodeWith: errorFunc(fmt.Sprintf("Unable to decode PPPoE code %d", i)),
|
||||
Name: fmt.Sprintf("UnknownPPPoECode(%d)", i),
|
||||
}
|
||||
LinkTypeMetadata[i] = EnumMetadata{
|
||||
DecodeWith: errorFunc(fmt.Sprintf("Unable to decode link type %d", i)),
|
||||
Name: fmt.Sprintf("UnknownLinkType(%d)", i),
|
||||
}
|
||||
FDDIFrameControlMetadata[i] = EnumMetadata{
|
||||
DecodeWith: errorFunc(fmt.Sprintf("Unable to decode FDDI frame control %d", i)),
|
||||
Name: fmt.Sprintf("UnknownFDDIFrameControl(%d)", i),
|
||||
}
|
||||
EAPOLTypeMetadata[i] = EnumMetadata{
|
||||
DecodeWith: errorFunc(fmt.Sprintf("Unable to decode EAPOL type %d", i)),
|
||||
Name: fmt.Sprintf("UnknownEAPOLType(%d)", i),
|
||||
}
|
||||
ProtocolFamilyMetadata[i] = EnumMetadata{
|
||||
DecodeWith: errorFunc(fmt.Sprintf("Unable to decode protocol family %d", i)),
|
||||
Name: fmt.Sprintf("UnknownProtocolFamily(%d)", i),
|
||||
}
|
||||
Dot11TypeMetadata[i] = EnumMetadata{
|
||||
DecodeWith: errorFunc(fmt.Sprintf("Unable to decode Dot11 type %d", i)),
|
||||
Name: fmt.Sprintf("UnknownDot11Type(%d)", i),
|
||||
}
|
||||
}
|
||||
func initActualTypeData() {
|
||||
// Each of the XXXTypeMetadata arrays contains mappings of how to handle enum
|
||||
// values for various enum types in gopacket/layers.
|
||||
// These arrays are actually created by gen2.go and stored in
|
||||
// enums_generated.go.
|
||||
//
|
||||
// So, EthernetTypeMetadata[2] contains information on how to handle EthernetType
|
||||
// 2, including which name to give it and which decoder to use to decode
|
||||
// packet data of that type. These arrays are filled by default with all of the
|
||||
// protocols gopacket/layers knows how to handle, but users of the library can
|
||||
// add new decoders or override existing ones. For example, if you write a better
|
||||
// TCP decoder, you can override IPProtocolMetadata[IPProtocolTCP].DecodeWith
|
||||
// with your new decoder, and all gopacket/layers decoding will use your new
|
||||
// decoder whenever they encounter that IPProtocol.
|
||||
|
||||
// Here we link up all enumerations with their respective names and decoders.
|
||||
EthernetTypeMetadata[EthernetTypeLLC] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeLLC), Name: "LLC", LayerType: LayerTypeLLC}
|
||||
EthernetTypeMetadata[EthernetTypeIPv4] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeIPv4), Name: "IPv4", LayerType: LayerTypeIPv4}
|
||||
EthernetTypeMetadata[EthernetTypeIPv6] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeIPv6), Name: "IPv6", LayerType: LayerTypeIPv6}
|
||||
EthernetTypeMetadata[EthernetTypeARP] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeARP), Name: "ARP", LayerType: LayerTypeARP}
|
||||
EthernetTypeMetadata[EthernetTypeDot1Q] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeDot1Q), Name: "Dot1Q", LayerType: LayerTypeDot1Q}
|
||||
EthernetTypeMetadata[EthernetTypePPP] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodePPP), Name: "PPP", LayerType: LayerTypePPP}
|
||||
EthernetTypeMetadata[EthernetTypePPPoEDiscovery] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodePPPoE), Name: "PPPoEDiscovery", LayerType: LayerTypePPPoE}
|
||||
EthernetTypeMetadata[EthernetTypePPPoESession] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodePPPoE), Name: "PPPoESession", LayerType: LayerTypePPPoE}
|
||||
EthernetTypeMetadata[EthernetTypeEthernetCTP] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeEthernetCTP), Name: "EthernetCTP", LayerType: LayerTypeEthernetCTP}
|
||||
@@ -463,6 +340,7 @@ func init() {
|
||||
IPProtocolMetadata[IPProtocolIPv6Routing] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeIPv6Routing), Name: "IPv6Routing", LayerType: LayerTypeIPv6Routing}
|
||||
IPProtocolMetadata[IPProtocolIPv6Fragment] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeIPv6Fragment), Name: "IPv6Fragment", LayerType: LayerTypeIPv6Fragment}
|
||||
IPProtocolMetadata[IPProtocolIPv6Destination] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeIPv6Destination), Name: "IPv6Destination", LayerType: LayerTypeIPv6Destination}
|
||||
IPProtocolMetadata[IPProtocolOSPF] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeOSPF), Name: "OSPF", LayerType: LayerTypeOSPF}
|
||||
IPProtocolMetadata[IPProtocolAH] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeIPSecAH), Name: "IPSecAH", LayerType: LayerTypeIPSecAH}
|
||||
IPProtocolMetadata[IPProtocolESP] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeIPSecESP), Name: "IPSecESP", LayerType: LayerTypeIPSecESP}
|
||||
IPProtocolMetadata[IPProtocolUDPLite] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeUDPLite), Name: "UDPLite", LayerType: LayerTypeUDPLite}
|
||||
@@ -500,6 +378,13 @@ func init() {
|
||||
LinkTypeMetadata[LinkTypeLoop] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeLoopback), Name: "Loop"}
|
||||
LinkTypeMetadata[LinkTypeIEEE802_11] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeDot11), Name: "802.11"}
|
||||
LinkTypeMetadata[LinkTypeRaw] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeIPv4or6), Name: "Raw"}
|
||||
// See https://github.com/the-tcpdump-group/libpcap/blob/170f717e6e818cdc4bcbbfd906b63088eaa88fa0/pcap/dlt.h#L85
|
||||
// Or https://github.com/wireshark/wireshark/blob/854cfe53efe44080609c78053ecfb2342ad84a08/wiretap/pcap-common.c#L508
|
||||
if runtime.GOOS == "openbsd" {
|
||||
LinkTypeMetadata[14] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeIPv4or6), Name: "Raw"}
|
||||
} else {
|
||||
LinkTypeMetadata[12] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeIPv4or6), Name: "Raw"}
|
||||
}
|
||||
LinkTypeMetadata[LinkTypePFLog] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodePFLog), Name: "PFLog"}
|
||||
LinkTypeMetadata[LinkTypeIEEE80211Radio] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeRadioTap), Name: "RadioTap"}
|
||||
LinkTypeMetadata[LinkTypeLinuxUSB] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeUSB), Name: "USB"}
|
||||
@@ -509,6 +394,7 @@ func init() {
|
||||
FDDIFrameControlMetadata[FDDIFrameControlLLC] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeLLC), Name: "LLC"}
|
||||
|
||||
EAPOLTypeMetadata[EAPOLTypeEAP] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeEAP), Name: "EAP", LayerType: LayerTypeEAP}
|
||||
EAPOLTypeMetadata[EAPOLTypeKey] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeEAPOLKey), Name: "EAPOLKey", LayerType: LayerTypeEAPOLKey}
|
||||
|
||||
ProtocolFamilyMetadata[ProtocolFamilyIPv4] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeIPv4), Name: "IPv4", LayerType: LayerTypeIPv4}
|
||||
ProtocolFamilyMetadata[ProtocolFamilyIPv6BSD] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeIPv6), Name: "IPv6", LayerType: LayerTypeIPv6}
|
||||
@@ -556,7 +442,7 @@ func init() {
|
||||
Dot11TypeMetadata[Dot11TypeDataQOSCFPollNoData] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeDot11DataQOSCFPollNoData), Name: "DataQOSCFPollNoData", LayerType: LayerTypeDot11DataQOSCFPollNoData}
|
||||
Dot11TypeMetadata[Dot11TypeDataQOSCFAckPollNoData] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeDot11DataQOSCFAckPollNoData), Name: "DataQOSCFAckPollNoData", LayerType: LayerTypeDot11DataQOSCFAckPollNoData}
|
||||
|
||||
USBTypeMetadata[USBTransportTypeInterrupt] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeUSBInterrupt), Name: "Interrupt", LayerType: LayerTypeUSBInterrupt}
|
||||
USBTypeMetadata[USBTransportTypeControl] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeUSBControl), Name: "Control", LayerType: LayerTypeUSBControl}
|
||||
USBTypeMetadata[USBTransportTypeBulk] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeUSBBulk), Name: "Bulk", LayerType: LayerTypeUSBBulk}
|
||||
USBTransportTypeMetadata[USBTransportTypeInterrupt] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeUSBInterrupt), Name: "Interrupt", LayerType: LayerTypeUSBInterrupt}
|
||||
USBTransportTypeMetadata[USBTransportTypeControl] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeUSBControl), Name: "Control", LayerType: LayerTypeUSBControl}
|
||||
USBTransportTypeMetadata[USBTransportTypeBulk] = EnumMetadata{DecodeWith: gopacket.DecodeFunc(decodeUSBBulk), Name: "Bulk", LayerType: LayerTypeUSBBulk}
|
||||
}
|
||||
+434
@@ -0,0 +1,434 @@
|
||||
// Copyright 2012 Google, Inc. All rights reserved.
|
||||
|
||||
package layers
|
||||
|
||||
// Created by gen2.go, don't edit manually
|
||||
// Generated at 2017-10-23 10:20:24.458771856 -0600 MDT m=+0.001159033
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/google/gopacket"
|
||||
)
|
||||
|
||||
func init() {
|
||||
initUnknownTypesForLinkType()
|
||||
initUnknownTypesForEthernetType()
|
||||
initUnknownTypesForPPPType()
|
||||
initUnknownTypesForIPProtocol()
|
||||
initUnknownTypesForSCTPChunkType()
|
||||
initUnknownTypesForPPPoECode()
|
||||
initUnknownTypesForFDDIFrameControl()
|
||||
initUnknownTypesForEAPOLType()
|
||||
initUnknownTypesForProtocolFamily()
|
||||
initUnknownTypesForDot11Type()
|
||||
initUnknownTypesForUSBTransportType()
|
||||
initActualTypeData()
|
||||
}
|
||||
|
||||
// Decoder calls LinkTypeMetadata.DecodeWith's decoder.
|
||||
func (a LinkType) Decode(data []byte, p gopacket.PacketBuilder) error {
|
||||
return LinkTypeMetadata[a].DecodeWith.Decode(data, p)
|
||||
}
|
||||
|
||||
// String returns LinkTypeMetadata.Name.
|
||||
func (a LinkType) String() string {
|
||||
return LinkTypeMetadata[a].Name
|
||||
}
|
||||
|
||||
// LayerType returns LinkTypeMetadata.LayerType.
|
||||
func (a LinkType) LayerType() gopacket.LayerType {
|
||||
return LinkTypeMetadata[a].LayerType
|
||||
}
|
||||
|
||||
type errorDecoderForLinkType int
|
||||
|
||||
func (a *errorDecoderForLinkType) Decode(data []byte, p gopacket.PacketBuilder) error {
|
||||
return a
|
||||
}
|
||||
func (a *errorDecoderForLinkType) Error() string {
|
||||
return fmt.Sprintf("Unable to decode LinkType %d", int(*a))
|
||||
}
|
||||
|
||||
var errorDecodersForLinkType [256]errorDecoderForLinkType
|
||||
var LinkTypeMetadata [256]EnumMetadata
|
||||
|
||||
func initUnknownTypesForLinkType() {
|
||||
for i := 0; i < 256; i++ {
|
||||
errorDecodersForLinkType[i] = errorDecoderForLinkType(i)
|
||||
LinkTypeMetadata[i] = EnumMetadata{
|
||||
DecodeWith: &errorDecodersForLinkType[i],
|
||||
Name: "UnknownLinkType",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Decoder calls EthernetTypeMetadata.DecodeWith's decoder.
|
||||
func (a EthernetType) Decode(data []byte, p gopacket.PacketBuilder) error {
|
||||
return EthernetTypeMetadata[a].DecodeWith.Decode(data, p)
|
||||
}
|
||||
|
||||
// String returns EthernetTypeMetadata.Name.
|
||||
func (a EthernetType) String() string {
|
||||
return EthernetTypeMetadata[a].Name
|
||||
}
|
||||
|
||||
// LayerType returns EthernetTypeMetadata.LayerType.
|
||||
func (a EthernetType) LayerType() gopacket.LayerType {
|
||||
return EthernetTypeMetadata[a].LayerType
|
||||
}
|
||||
|
||||
type errorDecoderForEthernetType int
|
||||
|
||||
func (a *errorDecoderForEthernetType) Decode(data []byte, p gopacket.PacketBuilder) error {
|
||||
return a
|
||||
}
|
||||
func (a *errorDecoderForEthernetType) Error() string {
|
||||
return fmt.Sprintf("Unable to decode EthernetType %d", int(*a))
|
||||
}
|
||||
|
||||
var errorDecodersForEthernetType [65536]errorDecoderForEthernetType
|
||||
var EthernetTypeMetadata [65536]EnumMetadata
|
||||
|
||||
func initUnknownTypesForEthernetType() {
|
||||
for i := 0; i < 65536; i++ {
|
||||
errorDecodersForEthernetType[i] = errorDecoderForEthernetType(i)
|
||||
EthernetTypeMetadata[i] = EnumMetadata{
|
||||
DecodeWith: &errorDecodersForEthernetType[i],
|
||||
Name: "UnknownEthernetType",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Decoder calls PPPTypeMetadata.DecodeWith's decoder.
|
||||
func (a PPPType) Decode(data []byte, p gopacket.PacketBuilder) error {
|
||||
return PPPTypeMetadata[a].DecodeWith.Decode(data, p)
|
||||
}
|
||||
|
||||
// String returns PPPTypeMetadata.Name.
|
||||
func (a PPPType) String() string {
|
||||
return PPPTypeMetadata[a].Name
|
||||
}
|
||||
|
||||
// LayerType returns PPPTypeMetadata.LayerType.
|
||||
func (a PPPType) LayerType() gopacket.LayerType {
|
||||
return PPPTypeMetadata[a].LayerType
|
||||
}
|
||||
|
||||
type errorDecoderForPPPType int
|
||||
|
||||
func (a *errorDecoderForPPPType) Decode(data []byte, p gopacket.PacketBuilder) error {
|
||||
return a
|
||||
}
|
||||
func (a *errorDecoderForPPPType) Error() string {
|
||||
return fmt.Sprintf("Unable to decode PPPType %d", int(*a))
|
||||
}
|
||||
|
||||
var errorDecodersForPPPType [65536]errorDecoderForPPPType
|
||||
var PPPTypeMetadata [65536]EnumMetadata
|
||||
|
||||
func initUnknownTypesForPPPType() {
|
||||
for i := 0; i < 65536; i++ {
|
||||
errorDecodersForPPPType[i] = errorDecoderForPPPType(i)
|
||||
PPPTypeMetadata[i] = EnumMetadata{
|
||||
DecodeWith: &errorDecodersForPPPType[i],
|
||||
Name: "UnknownPPPType",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Decoder calls IPProtocolMetadata.DecodeWith's decoder.
|
||||
func (a IPProtocol) Decode(data []byte, p gopacket.PacketBuilder) error {
|
||||
return IPProtocolMetadata[a].DecodeWith.Decode(data, p)
|
||||
}
|
||||
|
||||
// String returns IPProtocolMetadata.Name.
|
||||
func (a IPProtocol) String() string {
|
||||
return IPProtocolMetadata[a].Name
|
||||
}
|
||||
|
||||
// LayerType returns IPProtocolMetadata.LayerType.
|
||||
func (a IPProtocol) LayerType() gopacket.LayerType {
|
||||
return IPProtocolMetadata[a].LayerType
|
||||
}
|
||||
|
||||
type errorDecoderForIPProtocol int
|
||||
|
||||
func (a *errorDecoderForIPProtocol) Decode(data []byte, p gopacket.PacketBuilder) error {
|
||||
return a
|
||||
}
|
||||
func (a *errorDecoderForIPProtocol) Error() string {
|
||||
return fmt.Sprintf("Unable to decode IPProtocol %d", int(*a))
|
||||
}
|
||||
|
||||
var errorDecodersForIPProtocol [256]errorDecoderForIPProtocol
|
||||
var IPProtocolMetadata [256]EnumMetadata
|
||||
|
||||
func initUnknownTypesForIPProtocol() {
|
||||
for i := 0; i < 256; i++ {
|
||||
errorDecodersForIPProtocol[i] = errorDecoderForIPProtocol(i)
|
||||
IPProtocolMetadata[i] = EnumMetadata{
|
||||
DecodeWith: &errorDecodersForIPProtocol[i],
|
||||
Name: "UnknownIPProtocol",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Decoder calls SCTPChunkTypeMetadata.DecodeWith's decoder.
|
||||
func (a SCTPChunkType) Decode(data []byte, p gopacket.PacketBuilder) error {
|
||||
return SCTPChunkTypeMetadata[a].DecodeWith.Decode(data, p)
|
||||
}
|
||||
|
||||
// String returns SCTPChunkTypeMetadata.Name.
|
||||
func (a SCTPChunkType) String() string {
|
||||
return SCTPChunkTypeMetadata[a].Name
|
||||
}
|
||||
|
||||
// LayerType returns SCTPChunkTypeMetadata.LayerType.
|
||||
func (a SCTPChunkType) LayerType() gopacket.LayerType {
|
||||
return SCTPChunkTypeMetadata[a].LayerType
|
||||
}
|
||||
|
||||
type errorDecoderForSCTPChunkType int
|
||||
|
||||
func (a *errorDecoderForSCTPChunkType) Decode(data []byte, p gopacket.PacketBuilder) error {
|
||||
return a
|
||||
}
|
||||
func (a *errorDecoderForSCTPChunkType) Error() string {
|
||||
return fmt.Sprintf("Unable to decode SCTPChunkType %d", int(*a))
|
||||
}
|
||||
|
||||
var errorDecodersForSCTPChunkType [256]errorDecoderForSCTPChunkType
|
||||
var SCTPChunkTypeMetadata [256]EnumMetadata
|
||||
|
||||
func initUnknownTypesForSCTPChunkType() {
|
||||
for i := 0; i < 256; i++ {
|
||||
errorDecodersForSCTPChunkType[i] = errorDecoderForSCTPChunkType(i)
|
||||
SCTPChunkTypeMetadata[i] = EnumMetadata{
|
||||
DecodeWith: &errorDecodersForSCTPChunkType[i],
|
||||
Name: "UnknownSCTPChunkType",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Decoder calls PPPoECodeMetadata.DecodeWith's decoder.
|
||||
func (a PPPoECode) Decode(data []byte, p gopacket.PacketBuilder) error {
|
||||
return PPPoECodeMetadata[a].DecodeWith.Decode(data, p)
|
||||
}
|
||||
|
||||
// String returns PPPoECodeMetadata.Name.
|
||||
func (a PPPoECode) String() string {
|
||||
return PPPoECodeMetadata[a].Name
|
||||
}
|
||||
|
||||
// LayerType returns PPPoECodeMetadata.LayerType.
|
||||
func (a PPPoECode) LayerType() gopacket.LayerType {
|
||||
return PPPoECodeMetadata[a].LayerType
|
||||
}
|
||||
|
||||
type errorDecoderForPPPoECode int
|
||||
|
||||
func (a *errorDecoderForPPPoECode) Decode(data []byte, p gopacket.PacketBuilder) error {
|
||||
return a
|
||||
}
|
||||
func (a *errorDecoderForPPPoECode) Error() string {
|
||||
return fmt.Sprintf("Unable to decode PPPoECode %d", int(*a))
|
||||
}
|
||||
|
||||
var errorDecodersForPPPoECode [256]errorDecoderForPPPoECode
|
||||
var PPPoECodeMetadata [256]EnumMetadata
|
||||
|
||||
func initUnknownTypesForPPPoECode() {
|
||||
for i := 0; i < 256; i++ {
|
||||
errorDecodersForPPPoECode[i] = errorDecoderForPPPoECode(i)
|
||||
PPPoECodeMetadata[i] = EnumMetadata{
|
||||
DecodeWith: &errorDecodersForPPPoECode[i],
|
||||
Name: "UnknownPPPoECode",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Decoder calls FDDIFrameControlMetadata.DecodeWith's decoder.
|
||||
func (a FDDIFrameControl) Decode(data []byte, p gopacket.PacketBuilder) error {
|
||||
return FDDIFrameControlMetadata[a].DecodeWith.Decode(data, p)
|
||||
}
|
||||
|
||||
// String returns FDDIFrameControlMetadata.Name.
|
||||
func (a FDDIFrameControl) String() string {
|
||||
return FDDIFrameControlMetadata[a].Name
|
||||
}
|
||||
|
||||
// LayerType returns FDDIFrameControlMetadata.LayerType.
|
||||
func (a FDDIFrameControl) LayerType() gopacket.LayerType {
|
||||
return FDDIFrameControlMetadata[a].LayerType
|
||||
}
|
||||
|
||||
type errorDecoderForFDDIFrameControl int
|
||||
|
||||
func (a *errorDecoderForFDDIFrameControl) Decode(data []byte, p gopacket.PacketBuilder) error {
|
||||
return a
|
||||
}
|
||||
func (a *errorDecoderForFDDIFrameControl) Error() string {
|
||||
return fmt.Sprintf("Unable to decode FDDIFrameControl %d", int(*a))
|
||||
}
|
||||
|
||||
var errorDecodersForFDDIFrameControl [256]errorDecoderForFDDIFrameControl
|
||||
var FDDIFrameControlMetadata [256]EnumMetadata
|
||||
|
||||
func initUnknownTypesForFDDIFrameControl() {
|
||||
for i := 0; i < 256; i++ {
|
||||
errorDecodersForFDDIFrameControl[i] = errorDecoderForFDDIFrameControl(i)
|
||||
FDDIFrameControlMetadata[i] = EnumMetadata{
|
||||
DecodeWith: &errorDecodersForFDDIFrameControl[i],
|
||||
Name: "UnknownFDDIFrameControl",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Decoder calls EAPOLTypeMetadata.DecodeWith's decoder.
|
||||
func (a EAPOLType) Decode(data []byte, p gopacket.PacketBuilder) error {
|
||||
return EAPOLTypeMetadata[a].DecodeWith.Decode(data, p)
|
||||
}
|
||||
|
||||
// String returns EAPOLTypeMetadata.Name.
|
||||
func (a EAPOLType) String() string {
|
||||
return EAPOLTypeMetadata[a].Name
|
||||
}
|
||||
|
||||
// LayerType returns EAPOLTypeMetadata.LayerType.
|
||||
func (a EAPOLType) LayerType() gopacket.LayerType {
|
||||
return EAPOLTypeMetadata[a].LayerType
|
||||
}
|
||||
|
||||
type errorDecoderForEAPOLType int
|
||||
|
||||
func (a *errorDecoderForEAPOLType) Decode(data []byte, p gopacket.PacketBuilder) error {
|
||||
return a
|
||||
}
|
||||
func (a *errorDecoderForEAPOLType) Error() string {
|
||||
return fmt.Sprintf("Unable to decode EAPOLType %d", int(*a))
|
||||
}
|
||||
|
||||
var errorDecodersForEAPOLType [256]errorDecoderForEAPOLType
|
||||
var EAPOLTypeMetadata [256]EnumMetadata
|
||||
|
||||
func initUnknownTypesForEAPOLType() {
|
||||
for i := 0; i < 256; i++ {
|
||||
errorDecodersForEAPOLType[i] = errorDecoderForEAPOLType(i)
|
||||
EAPOLTypeMetadata[i] = EnumMetadata{
|
||||
DecodeWith: &errorDecodersForEAPOLType[i],
|
||||
Name: "UnknownEAPOLType",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Decoder calls ProtocolFamilyMetadata.DecodeWith's decoder.
|
||||
func (a ProtocolFamily) Decode(data []byte, p gopacket.PacketBuilder) error {
|
||||
return ProtocolFamilyMetadata[a].DecodeWith.Decode(data, p)
|
||||
}
|
||||
|
||||
// String returns ProtocolFamilyMetadata.Name.
|
||||
func (a ProtocolFamily) String() string {
|
||||
return ProtocolFamilyMetadata[a].Name
|
||||
}
|
||||
|
||||
// LayerType returns ProtocolFamilyMetadata.LayerType.
|
||||
func (a ProtocolFamily) LayerType() gopacket.LayerType {
|
||||
return ProtocolFamilyMetadata[a].LayerType
|
||||
}
|
||||
|
||||
type errorDecoderForProtocolFamily int
|
||||
|
||||
func (a *errorDecoderForProtocolFamily) Decode(data []byte, p gopacket.PacketBuilder) error {
|
||||
return a
|
||||
}
|
||||
func (a *errorDecoderForProtocolFamily) Error() string {
|
||||
return fmt.Sprintf("Unable to decode ProtocolFamily %d", int(*a))
|
||||
}
|
||||
|
||||
var errorDecodersForProtocolFamily [256]errorDecoderForProtocolFamily
|
||||
var ProtocolFamilyMetadata [256]EnumMetadata
|
||||
|
||||
func initUnknownTypesForProtocolFamily() {
|
||||
for i := 0; i < 256; i++ {
|
||||
errorDecodersForProtocolFamily[i] = errorDecoderForProtocolFamily(i)
|
||||
ProtocolFamilyMetadata[i] = EnumMetadata{
|
||||
DecodeWith: &errorDecodersForProtocolFamily[i],
|
||||
Name: "UnknownProtocolFamily",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Decoder calls Dot11TypeMetadata.DecodeWith's decoder.
|
||||
func (a Dot11Type) Decode(data []byte, p gopacket.PacketBuilder) error {
|
||||
return Dot11TypeMetadata[a].DecodeWith.Decode(data, p)
|
||||
}
|
||||
|
||||
// String returns Dot11TypeMetadata.Name.
|
||||
func (a Dot11Type) String() string {
|
||||
return Dot11TypeMetadata[a].Name
|
||||
}
|
||||
|
||||
// LayerType returns Dot11TypeMetadata.LayerType.
|
||||
func (a Dot11Type) LayerType() gopacket.LayerType {
|
||||
return Dot11TypeMetadata[a].LayerType
|
||||
}
|
||||
|
||||
type errorDecoderForDot11Type int
|
||||
|
||||
func (a *errorDecoderForDot11Type) Decode(data []byte, p gopacket.PacketBuilder) error {
|
||||
return a
|
||||
}
|
||||
func (a *errorDecoderForDot11Type) Error() string {
|
||||
return fmt.Sprintf("Unable to decode Dot11Type %d", int(*a))
|
||||
}
|
||||
|
||||
var errorDecodersForDot11Type [256]errorDecoderForDot11Type
|
||||
var Dot11TypeMetadata [256]EnumMetadata
|
||||
|
||||
func initUnknownTypesForDot11Type() {
|
||||
for i := 0; i < 256; i++ {
|
||||
errorDecodersForDot11Type[i] = errorDecoderForDot11Type(i)
|
||||
Dot11TypeMetadata[i] = EnumMetadata{
|
||||
DecodeWith: &errorDecodersForDot11Type[i],
|
||||
Name: "UnknownDot11Type",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Decoder calls USBTransportTypeMetadata.DecodeWith's decoder.
|
||||
func (a USBTransportType) Decode(data []byte, p gopacket.PacketBuilder) error {
|
||||
return USBTransportTypeMetadata[a].DecodeWith.Decode(data, p)
|
||||
}
|
||||
|
||||
// String returns USBTransportTypeMetadata.Name.
|
||||
func (a USBTransportType) String() string {
|
||||
return USBTransportTypeMetadata[a].Name
|
||||
}
|
||||
|
||||
// LayerType returns USBTransportTypeMetadata.LayerType.
|
||||
func (a USBTransportType) LayerType() gopacket.LayerType {
|
||||
return USBTransportTypeMetadata[a].LayerType
|
||||
}
|
||||
|
||||
type errorDecoderForUSBTransportType int
|
||||
|
||||
func (a *errorDecoderForUSBTransportType) Decode(data []byte, p gopacket.PacketBuilder) error {
|
||||
return a
|
||||
}
|
||||
func (a *errorDecoderForUSBTransportType) Error() string {
|
||||
return fmt.Sprintf("Unable to decode USBTransportType %d", int(*a))
|
||||
}
|
||||
|
||||
var errorDecodersForUSBTransportType [256]errorDecoderForUSBTransportType
|
||||
var USBTransportTypeMetadata [256]EnumMetadata
|
||||
|
||||
func initUnknownTypesForUSBTransportType() {
|
||||
for i := 0; i < 256; i++ {
|
||||
errorDecodersForUSBTransportType[i] = errorDecoderForUSBTransportType(i)
|
||||
USBTransportTypeMetadata[i] = EnumMetadata{
|
||||
DecodeWith: &errorDecodersForUSBTransportType[i],
|
||||
Name: "UnknownUSBTransportType",
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
@@ -46,6 +46,7 @@ func (eth *Ethernet) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) er
|
||||
eth.SrcMAC = net.HardwareAddr(data[6:12])
|
||||
eth.EthernetType = EthernetType(binary.BigEndian.Uint16(data[12:14]))
|
||||
eth.BaseLayer = BaseLayer{data[:14], data[14:]}
|
||||
eth.Length = 0
|
||||
if eth.EthernetType < 0x0600 {
|
||||
eth.Length = uint16(eth.EthernetType)
|
||||
eth.EthernetType = EthernetTypeLLC
|
||||
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
// Copyright 2012 Google, Inc. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the LICENSE file in the root of the source
|
||||
// tree.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// This binary handles creating string constants and function templates for enums.
|
||||
//
|
||||
// go run gen.go | gofmt > enums_generated.go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"text/template"
|
||||
"time"
|
||||
)
|
||||
|
||||
const fmtString = `// Copyright 2012 Google, Inc. All rights reserved.
|
||||
|
||||
package layers
|
||||
|
||||
// Created by gen2.go, don't edit manually
|
||||
// Generated at %s
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/google/gopacket"
|
||||
)
|
||||
|
||||
`
|
||||
|
||||
var funcsTmpl = template.Must(template.New("foo").Parse(`
|
||||
// Decoder calls {{.Name}}Metadata.DecodeWith's decoder.
|
||||
func (a {{.Name}}) Decode(data []byte, p gopacket.PacketBuilder) error {
|
||||
return {{.Name}}Metadata[a].DecodeWith.Decode(data, p)
|
||||
}
|
||||
// String returns {{.Name}}Metadata.Name.
|
||||
func (a {{.Name}}) String() string {
|
||||
return {{.Name}}Metadata[a].Name
|
||||
}
|
||||
// LayerType returns {{.Name}}Metadata.LayerType.
|
||||
func (a {{.Name}}) LayerType() gopacket.LayerType {
|
||||
return {{.Name}}Metadata[a].LayerType
|
||||
}
|
||||
|
||||
type errorDecoderFor{{.Name}} int
|
||||
func (a *errorDecoderFor{{.Name}}) Decode(data []byte, p gopacket.PacketBuilder) error {
|
||||
return a
|
||||
}
|
||||
func (a *errorDecoderFor{{.Name}}) Error() string {
|
||||
return fmt.Sprintf("Unable to decode {{.Name}} %d", int(*a))
|
||||
}
|
||||
|
||||
var errorDecodersFor{{.Name}} [{{.Num}}]errorDecoderFor{{.Name}}
|
||||
var {{.Name}}Metadata [{{.Num}}]EnumMetadata
|
||||
|
||||
func initUnknownTypesFor{{.Name}}() {
|
||||
for i := 0; i < {{.Num}}; i++ {
|
||||
errorDecodersFor{{.Name}}[i] = errorDecoderFor{{.Name}}(i)
|
||||
{{.Name}}Metadata[i] = EnumMetadata{
|
||||
DecodeWith: &errorDecodersFor{{.Name}}[i],
|
||||
Name: "Unknown{{.Name}}",
|
||||
}
|
||||
}
|
||||
}
|
||||
`))
|
||||
|
||||
func main() {
|
||||
fmt.Fprintf(os.Stderr, "Writing results to stdout\n")
|
||||
fmt.Printf(fmtString, time.Now())
|
||||
types := []struct {
|
||||
Name string
|
||||
Num int
|
||||
}{
|
||||
{"LinkType", 256},
|
||||
{"EthernetType", 65536},
|
||||
{"PPPType", 65536},
|
||||
{"IPProtocol", 256},
|
||||
{"SCTPChunkType", 256},
|
||||
{"PPPoECode", 256},
|
||||
{"FDDIFrameControl", 256},
|
||||
{"EAPOLType", 256},
|
||||
{"ProtocolFamily", 256},
|
||||
{"Dot11Type", 256},
|
||||
{"USBTransportType", 256},
|
||||
}
|
||||
|
||||
fmt.Println("func init() {")
|
||||
for _, t := range types {
|
||||
fmt.Printf("initUnknownTypesFor%s()\n", t.Name)
|
||||
}
|
||||
fmt.Println("initActualTypeData()")
|
||||
fmt.Println("}")
|
||||
for _, t := range types {
|
||||
if err := funcsTmpl.Execute(os.Stdout, t); err != nil {
|
||||
log.Fatalf("Failed to execute template %s: %v", t.Name, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
-6
@@ -8,6 +8,7 @@ package layers
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
|
||||
"github.com/google/gopacket"
|
||||
)
|
||||
@@ -52,19 +53,25 @@ func (gn *Geneve) LayerType() gopacket.LayerType { return LayerTypeGeneve }
|
||||
func decodeGeneveOption(data []byte, gn *Geneve) (*GeneveOption, uint8) {
|
||||
opt := &GeneveOption{}
|
||||
|
||||
opt.Class = binary.BigEndian.Uint16(data[0:1])
|
||||
opt.Class = binary.BigEndian.Uint16(data[0:2])
|
||||
opt.Type = data[2]
|
||||
opt.Flags = data[3] >> 4
|
||||
opt.Length = data[3] & 0xf
|
||||
opt.Length = (data[3]&0xf)*4 + 4
|
||||
|
||||
opt.Data = make([]byte, opt.Length-4)
|
||||
copy(opt.Data, data[4:opt.Length])
|
||||
|
||||
return opt, 4 + opt.Length
|
||||
return opt, opt.Length
|
||||
}
|
||||
|
||||
func (gn *Geneve) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||||
if len(data) < 7 {
|
||||
df.SetTruncated()
|
||||
return errors.New("geneve packet too short")
|
||||
}
|
||||
|
||||
gn.Version = data[0] >> 7
|
||||
gn.OptionsLength = data[0] & 0x3f
|
||||
gn.OptionsLength = (data[0] & 0x3f) * 4
|
||||
|
||||
gn.OAMPacket = data[1]&0x80 > 0
|
||||
gn.CriticalOption = data[1]&0x40 > 0
|
||||
@@ -74,12 +81,17 @@ func (gn *Geneve) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error
|
||||
copy(buf[1:], data[4:7])
|
||||
gn.VNI = binary.BigEndian.Uint32(buf[:])
|
||||
|
||||
offset, length := uint8(8), gn.OptionsLength
|
||||
offset, length := uint8(8), int32(gn.OptionsLength)
|
||||
if len(data) < int(length+7) {
|
||||
df.SetTruncated()
|
||||
return errors.New("geneve packet too short")
|
||||
}
|
||||
|
||||
for length > 0 {
|
||||
opt, len := decodeGeneveOption(data[offset:], gn)
|
||||
gn.Options = append(gn.Options, opt)
|
||||
|
||||
length -= len
|
||||
length -= int32(len)
|
||||
offset += len
|
||||
}
|
||||
|
||||
|
||||
+20
-5
@@ -15,11 +15,11 @@ import (
|
||||
// GRE is a Generic Routing Encapsulation header.
|
||||
type GRE struct {
|
||||
BaseLayer
|
||||
ChecksumPresent, RoutingPresent, KeyPresent, SeqPresent, StrictSourceRoute bool
|
||||
RecursionControl, Flags, Version uint8
|
||||
Protocol EthernetType
|
||||
Checksum, Offset uint16
|
||||
Key, Seq uint32
|
||||
ChecksumPresent, RoutingPresent, KeyPresent, SeqPresent, StrictSourceRoute, AckPresent bool
|
||||
RecursionControl, Flags, Version uint8
|
||||
Protocol EthernetType
|
||||
Checksum, Offset uint16
|
||||
Key, Seq, Ack uint32
|
||||
*GRERouting
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ func (g *GRE) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||||
g.KeyPresent = data[0]&0x20 != 0
|
||||
g.SeqPresent = data[0]&0x10 != 0
|
||||
g.StrictSourceRoute = data[0]&0x08 != 0
|
||||
g.AckPresent = data[1]&0x80 != 0
|
||||
g.RecursionControl = data[0] & 0x7
|
||||
g.Flags = data[1] >> 3
|
||||
g.Version = data[1] & 0x7
|
||||
@@ -77,6 +78,10 @@ func (g *GRE) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||||
tail = &sre.Next
|
||||
}
|
||||
}
|
||||
if g.AckPresent {
|
||||
g.Ack = binary.BigEndian.Uint32(data[offset : offset+4])
|
||||
offset += 4
|
||||
}
|
||||
g.BaseLayer = BaseLayer{data[:offset], data[offset:]}
|
||||
return nil
|
||||
}
|
||||
@@ -102,6 +107,9 @@ func (g *GRE) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOpt
|
||||
}
|
||||
size += 4
|
||||
}
|
||||
if g.AckPresent {
|
||||
size += 4
|
||||
}
|
||||
buf, err := b.PrependBytes(size)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -124,6 +132,9 @@ func (g *GRE) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOpt
|
||||
if g.StrictSourceRoute {
|
||||
buf[0] |= 0x08
|
||||
}
|
||||
if g.AckPresent {
|
||||
buf[1] |= 0x80
|
||||
}
|
||||
buf[0] |= g.RecursionControl
|
||||
buf[1] |= g.Flags << 3
|
||||
buf[1] |= g.Version
|
||||
@@ -159,6 +170,10 @@ func (g *GRE) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOpt
|
||||
// Terminate routing field with a "NULL" SRE.
|
||||
binary.BigEndian.PutUint32(buf[offset:offset+4], 0)
|
||||
}
|
||||
if g.AckPresent {
|
||||
binary.BigEndian.PutUint32(buf[offset:offset+4], g.Ack)
|
||||
offset += 4
|
||||
}
|
||||
if g.ChecksumPresent {
|
||||
if opts.ComputeChecksums {
|
||||
g.Checksum = tcpipChecksum(b.Bytes(), 0)
|
||||
|
||||
+181
@@ -0,0 +1,181 @@
|
||||
// Copyright 2017 Google, Inc. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the LICENSE file in the root of the source
|
||||
// tree.
|
||||
//
|
||||
|
||||
package layers
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"github.com/google/gopacket"
|
||||
)
|
||||
|
||||
const gtpMinimumSizeInBytes int = 8
|
||||
|
||||
// GTPExtensionHeader is used to carry extra data and enable future extensions of the GTP without the need to use another version number.
|
||||
type GTPExtensionHeader struct {
|
||||
Type uint8
|
||||
Content []byte
|
||||
}
|
||||
|
||||
// GTPv1U protocol is used to exchange user data over GTP tunnels across the Sx interfaces.
|
||||
// Defined in https://portal.3gpp.org/desktopmodules/Specifications/SpecificationDetails.aspx?specificationId=1595
|
||||
type GTPv1U struct {
|
||||
BaseLayer
|
||||
Version uint8
|
||||
ProtocolType uint8
|
||||
Reserved uint8
|
||||
ExtensionHeaderFlag bool
|
||||
SequenceNumberFlag bool
|
||||
NPDUFlag bool
|
||||
MessageType uint8
|
||||
MessageLength uint16
|
||||
TEID uint32
|
||||
SequenceNumber uint16
|
||||
NPDU uint8
|
||||
GTPExtensionHeaders []GTPExtensionHeader
|
||||
}
|
||||
|
||||
// LayerType returns LayerTypeGTPV1U
|
||||
func (g *GTPv1U) LayerType() gopacket.LayerType { return LayerTypeGTPv1U }
|
||||
|
||||
// DecodeFromBytes analyses a byte slice and attempts to decode it as a GTPv1U packet
|
||||
func (g *GTPv1U) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||||
hLen := gtpMinimumSizeInBytes
|
||||
dLen := len(data)
|
||||
if dLen < hLen {
|
||||
return fmt.Errorf("GTP packet too small: %d bytes", dLen)
|
||||
}
|
||||
g.Version = (data[0] >> 5) & 0x07
|
||||
g.ProtocolType = (data[0] >> 4) & 0x01
|
||||
g.Reserved = (data[0] >> 3) & 0x01
|
||||
g.SequenceNumberFlag = ((data[0] >> 1) & 0x01) == 1
|
||||
g.NPDUFlag = (data[0] & 0x01) == 1
|
||||
g.ExtensionHeaderFlag = ((data[0] >> 2) & 0x01) == 1
|
||||
g.MessageType = data[1]
|
||||
g.MessageLength = binary.BigEndian.Uint16(data[2:4])
|
||||
pLen := 8 + g.MessageLength
|
||||
if uint16(dLen) < pLen {
|
||||
return fmt.Errorf("GTP packet too small: %d bytes", dLen)
|
||||
}
|
||||
// Field used to multiplex different connections in the same GTP tunnel.
|
||||
g.TEID = binary.BigEndian.Uint32(data[4:8])
|
||||
cIndex := uint16(hLen)
|
||||
if g.SequenceNumberFlag || g.NPDUFlag || g.ExtensionHeaderFlag {
|
||||
hLen += 4
|
||||
cIndex += 4
|
||||
if dLen < hLen {
|
||||
return fmt.Errorf("GTP packet too small: %d bytes", dLen)
|
||||
}
|
||||
if g.SequenceNumberFlag {
|
||||
g.SequenceNumber = binary.BigEndian.Uint16(data[8:10])
|
||||
}
|
||||
if g.NPDUFlag {
|
||||
g.NPDU = data[10]
|
||||
}
|
||||
if g.ExtensionHeaderFlag {
|
||||
extensionFlag := true
|
||||
for extensionFlag {
|
||||
extensionType := uint8(data[cIndex-1])
|
||||
extensionLength := uint(data[cIndex])
|
||||
if extensionLength == 0 {
|
||||
return fmt.Errorf("GTP packet with invalid extension header")
|
||||
}
|
||||
// extensionLength is in 4-octet units
|
||||
lIndex := cIndex + (uint16(extensionLength) * 4)
|
||||
if uint16(dLen) < lIndex {
|
||||
fmt.Println(dLen, lIndex)
|
||||
return fmt.Errorf("GTP packet with small extension header: %d bytes", dLen)
|
||||
}
|
||||
content := data[cIndex+1 : lIndex-1]
|
||||
eh := GTPExtensionHeader{Type: extensionType, Content: content}
|
||||
g.GTPExtensionHeaders = append(g.GTPExtensionHeaders, eh)
|
||||
cIndex = lIndex
|
||||
// Check if coming bytes are from an extension header
|
||||
extensionFlag = data[cIndex-1] != 0
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
g.BaseLayer = BaseLayer{Contents: data[:cIndex], Payload: data[cIndex:]}
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
// SerializeTo writes the serialized form of this layer into the
|
||||
// SerializationBuffer, implementing gopacket.SerializableLayer.
|
||||
// See the docs for gopacket.SerializableLayer for more info.
|
||||
func (g *GTPv1U) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
|
||||
data, err := b.PrependBytes(gtpMinimumSizeInBytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data[0] |= (g.Version << 5)
|
||||
data[0] |= (1 << 4)
|
||||
if len(g.GTPExtensionHeaders) > 0 {
|
||||
data[0] |= 0x04
|
||||
g.ExtensionHeaderFlag = true
|
||||
}
|
||||
if g.SequenceNumberFlag {
|
||||
data[0] |= 0x02
|
||||
}
|
||||
if g.NPDUFlag {
|
||||
data[0] |= 0x01
|
||||
}
|
||||
data[1] = g.MessageType
|
||||
binary.BigEndian.PutUint16(data[2:4], g.MessageLength)
|
||||
binary.BigEndian.PutUint32(data[4:8], g.TEID)
|
||||
if g.ExtensionHeaderFlag || g.SequenceNumberFlag || g.NPDUFlag {
|
||||
data, err := b.AppendBytes(4)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
binary.BigEndian.PutUint16(data[:2], g.SequenceNumber)
|
||||
data[2] = g.NPDU
|
||||
for _, eh := range g.GTPExtensionHeaders {
|
||||
data[len(data)-1] = eh.Type
|
||||
lContent := len(eh.Content)
|
||||
// extensionLength is in 4-octet units
|
||||
extensionLength := (lContent + 2) / 4
|
||||
// Get two extra byte for the next extension header type and length
|
||||
data, err = b.AppendBytes(lContent + 2)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data[0] = byte(extensionLength)
|
||||
copy(data[1:lContent+1], eh.Content)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
// CanDecode returns a set of layers that GTP objects can decode.
|
||||
func (g *GTPv1U) CanDecode() gopacket.LayerClass {
|
||||
return LayerTypeGTPv1U
|
||||
}
|
||||
|
||||
// NextLayerType specifies the next layer that GoPacket should attempt to
|
||||
func (g *GTPv1U) NextLayerType() gopacket.LayerType {
|
||||
version := uint8(g.LayerPayload()[0]) >> 4
|
||||
if version == 4 {
|
||||
return LayerTypeIPv4
|
||||
} else if version == 6 {
|
||||
return LayerTypeIPv6
|
||||
} else {
|
||||
return LayerTypePPP
|
||||
}
|
||||
}
|
||||
|
||||
func decodeGTPv1u(data []byte, p gopacket.PacketBuilder) error {
|
||||
gtp := >Pv1U{}
|
||||
err := gtp.DecodeFromBytes(data, p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.AddLayer(gtp)
|
||||
return p.NextDecoder(gtp.NextLayerType())
|
||||
}
|
||||
+46
-9
@@ -3,7 +3,7 @@
|
||||
package layers
|
||||
|
||||
// Created by gen.go, don't edit manually
|
||||
// Generated at 2017-01-04 15:05:26.649794815 -0700 MST
|
||||
// Generated at 2017-10-23 09:57:28.214859163 -0600 MDT m=+1.011679290
|
||||
// Fetched from "http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xml"
|
||||
|
||||
// TCPPortNames contains the port names for all TCP ports.
|
||||
@@ -45,7 +45,6 @@ var tcpPortNames = map[TCPPort]string{
|
||||
44: "mpm-flags",
|
||||
45: "mpm",
|
||||
46: "mpm-snd",
|
||||
47: "ni-ftp",
|
||||
48: "auditd",
|
||||
49: "tacacs",
|
||||
50: "re-mail-ck",
|
||||
@@ -55,7 +54,6 @@ var tcpPortNames = map[TCPPort]string{
|
||||
55: "isi-gl",
|
||||
56: "xns-auth",
|
||||
58: "xns-mail",
|
||||
61: "ni-mail",
|
||||
62: "acas",
|
||||
63: "whoispp",
|
||||
64: "covia",
|
||||
@@ -673,6 +671,7 @@ var tcpPortNames = map[TCPPort]string{
|
||||
847: "dhcp-failover2",
|
||||
848: "gdoi",
|
||||
853: "domain-s",
|
||||
854: "dlep",
|
||||
860: "iscsi",
|
||||
861: "owamp-control",
|
||||
862: "twamp-control",
|
||||
@@ -688,6 +687,7 @@ var tcpPortNames = map[TCPPort]string{
|
||||
911: "xact-backup",
|
||||
912: "apex-mesh",
|
||||
913: "apex-edge",
|
||||
953: "rndc",
|
||||
989: "ftps-data",
|
||||
990: "ftps",
|
||||
991: "nas",
|
||||
@@ -2726,7 +2726,7 @@ var tcpPortNames = map[TCPPort]string{
|
||||
3068: "ls3bcast",
|
||||
3069: "ls3",
|
||||
3070: "mgxswitch",
|
||||
3071: "csd-mgmt-port",
|
||||
3071: "xplat-replicate",
|
||||
3072: "csd-monitor",
|
||||
3073: "vcrp",
|
||||
3074: "xbox",
|
||||
@@ -3753,6 +3753,7 @@ var tcpPortNames = map[TCPPort]string{
|
||||
4117: "hillrserv",
|
||||
4118: "netscript",
|
||||
4119: "assuria-slm",
|
||||
4120: "minirem",
|
||||
4121: "e-builder",
|
||||
4122: "fprams",
|
||||
4123: "z-wave",
|
||||
@@ -3823,6 +3824,7 @@ var tcpPortNames = map[TCPPort]string{
|
||||
4190: "sieve",
|
||||
4192: "azeti",
|
||||
4193: "pvxplusio",
|
||||
4197: "hctl",
|
||||
4199: "eims-admin",
|
||||
4300: "corelccam",
|
||||
4301: "d-data",
|
||||
@@ -3831,7 +3833,7 @@ var tcpPortNames = map[TCPPort]string{
|
||||
4304: "owserver",
|
||||
4305: "batman",
|
||||
4306: "pinghgl",
|
||||
4307: "visicron-vs",
|
||||
4307: "trueconf",
|
||||
4308: "compx-lockview",
|
||||
4309: "dserver",
|
||||
4310: "mirrtex",
|
||||
@@ -4028,6 +4030,7 @@ var tcpPortNames = map[TCPPort]string{
|
||||
4702: "netxms-sync",
|
||||
4703: "npqes-test",
|
||||
4704: "assuria-ins",
|
||||
4711: "trinity-dist",
|
||||
4725: "truckstar",
|
||||
4727: "fcis",
|
||||
4728: "capmux",
|
||||
@@ -4105,6 +4108,7 @@ var tcpPortNames = map[TCPPort]string{
|
||||
4953: "dbsyncarbiter",
|
||||
4969: "ccss-qmm",
|
||||
4970: "ccss-qsm",
|
||||
4971: "burp",
|
||||
4984: "webyast",
|
||||
4985: "gerhcs",
|
||||
4986: "mrip",
|
||||
@@ -4415,6 +4419,7 @@ var tcpPortNames = map[TCPPort]string{
|
||||
5638: "flcrs",
|
||||
5639: "ics",
|
||||
5646: "vfmobile",
|
||||
5666: "nrpe",
|
||||
5670: "filemq",
|
||||
5671: "amqps",
|
||||
5672: "amqp",
|
||||
@@ -4432,6 +4437,7 @@ var tcpPortNames = map[TCPPort]string{
|
||||
5693: "rbsystem",
|
||||
5696: "kmip",
|
||||
5700: "supportassist",
|
||||
5705: "storageos",
|
||||
5713: "proshareaudio",
|
||||
5714: "prosharevideo",
|
||||
5715: "prosharedata",
|
||||
@@ -4609,6 +4615,7 @@ var tcpPortNames = map[TCPPort]string{
|
||||
6446: "mysql-proxy",
|
||||
6455: "skip-cert-recv",
|
||||
6456: "skip-cert-send",
|
||||
6464: "ieee11073-20701",
|
||||
6471: "lvision-lm",
|
||||
6480: "sun-sr-http",
|
||||
6481: "servicetags",
|
||||
@@ -4739,6 +4746,8 @@ var tcpPortNames = map[TCPPort]string{
|
||||
7013: "microtalon-dis",
|
||||
7014: "microtalon-com",
|
||||
7015: "talon-webserver",
|
||||
7016: "spg",
|
||||
7017: "grasp",
|
||||
7018: "fisa-svc",
|
||||
7019: "doceri-ctl",
|
||||
7020: "dpserve",
|
||||
@@ -4776,6 +4785,7 @@ var tcpPortNames = map[TCPPort]string{
|
||||
7174: "clutild",
|
||||
7200: "fodms",
|
||||
7201: "dlip",
|
||||
7202: "pon-ictp",
|
||||
7215: "PS-Server",
|
||||
7216: "PS-Capture-Pro",
|
||||
7227: "ramp",
|
||||
@@ -4926,6 +4936,8 @@ var tcpPortNames = map[TCPPort]string{
|
||||
8002: "teradataordbms",
|
||||
8003: "mcreport",
|
||||
8005: "mxi",
|
||||
8006: "wpl-analytics",
|
||||
8007: "warppipe",
|
||||
8008: "http-alt",
|
||||
8019: "qbdb",
|
||||
8020: "intu-ec-svcdisc",
|
||||
@@ -4937,6 +4949,7 @@ var tcpPortNames = map[TCPPort]string{
|
||||
8033: "mindprint",
|
||||
8034: "vantronix-mgmt",
|
||||
8040: "ampify",
|
||||
8041: "enguity-xccetp",
|
||||
8042: "fs-agent",
|
||||
8043: "fs-server",
|
||||
8044: "fs-mgmt",
|
||||
@@ -4951,7 +4964,9 @@ var tcpPortNames = map[TCPPort]string{
|
||||
8059: "senomix08",
|
||||
8066: "toad-bi-appsrvr",
|
||||
8067: "infi-async",
|
||||
8070: "ucs-isc",
|
||||
8074: "gadugadu",
|
||||
8077: "mles",
|
||||
8080: "http-alt",
|
||||
8081: "sunproxyadmin",
|
||||
8082: "us-cli",
|
||||
@@ -4959,6 +4974,7 @@ var tcpPortNames = map[TCPPort]string{
|
||||
8086: "d-s-n",
|
||||
8087: "simplifymedia",
|
||||
8088: "radan-http",
|
||||
8090: "opsmessaging",
|
||||
8091: "jamlink",
|
||||
8097: "sac",
|
||||
8100: "xprint-server",
|
||||
@@ -5000,6 +5016,7 @@ var tcpPortNames = map[TCPPort]string{
|
||||
8208: "lm-webwatcher",
|
||||
8230: "rexecj",
|
||||
8243: "synapse-nhttps",
|
||||
8270: "robot-remote",
|
||||
8276: "pando-sec",
|
||||
8280: "synapse-nhttp",
|
||||
8282: "libelle",
|
||||
@@ -5028,6 +5045,7 @@ var tcpPortNames = map[TCPPort]string{
|
||||
8415: "dlpx-sp",
|
||||
8416: "espeech",
|
||||
8417: "espeech-rtp",
|
||||
8423: "aritts",
|
||||
8442: "cybro-a-bus",
|
||||
8443: "pcsync-https",
|
||||
8444: "pcsync-http",
|
||||
@@ -5258,6 +5276,8 @@ var tcpPortNames = map[TCPPort]string{
|
||||
9955: "alljoyn-stm",
|
||||
9966: "odnsp",
|
||||
9978: "xybrid-rt",
|
||||
9979: "visweather",
|
||||
9981: "pumpkindb",
|
||||
9987: "dsm-scm-target",
|
||||
9988: "nsesrvr",
|
||||
9990: "osm-appsrvr",
|
||||
@@ -5281,6 +5301,7 @@ var tcpPortNames = map[TCPPort]string{
|
||||
10008: "octopus",
|
||||
10009: "swdtp-sv",
|
||||
10010: "rxapi",
|
||||
10020: "abb-hw",
|
||||
10050: "zabbix-agent",
|
||||
10051: "zabbix-trapper",
|
||||
10055: "qptlmd",
|
||||
@@ -5535,6 +5556,7 @@ var tcpPortNames = map[TCPPort]string{
|
||||
20999: "athand-mmp",
|
||||
21000: "irtrans",
|
||||
21010: "notezilla-lan",
|
||||
21221: "aigairserver",
|
||||
21553: "rdm-tfs",
|
||||
21554: "dfserver",
|
||||
21590: "vofr-gateway",
|
||||
@@ -5648,6 +5670,7 @@ var tcpPortNames = map[TCPPort]string{
|
||||
30003: "amicon-fpsu-ra",
|
||||
30100: "rwp",
|
||||
30260: "kingdomsonline",
|
||||
30400: "gs-realtime",
|
||||
30999: "ovobs",
|
||||
31016: "ka-sddp",
|
||||
31020: "autotrac-acp",
|
||||
@@ -5789,6 +5812,7 @@ var tcpPortNames = map[TCPPort]string{
|
||||
48619: "iqobject",
|
||||
48653: "robotraconteur",
|
||||
49000: "matahari",
|
||||
49001: "nusrp",
|
||||
}
|
||||
var udpPortNames = map[UDPPort]string{
|
||||
1: "tcpmux",
|
||||
@@ -5820,7 +5844,6 @@ var udpPortNames = map[UDPPort]string{
|
||||
44: "mpm-flags",
|
||||
45: "mpm",
|
||||
46: "mpm-snd",
|
||||
47: "ni-ftp",
|
||||
48: "auditd",
|
||||
49: "tacacs",
|
||||
50: "re-mail-ck",
|
||||
@@ -5830,7 +5853,6 @@ var udpPortNames = map[UDPPort]string{
|
||||
55: "isi-gl",
|
||||
56: "xns-auth",
|
||||
58: "xns-mail",
|
||||
61: "ni-mail",
|
||||
62: "acas",
|
||||
63: "whoispp",
|
||||
64: "covia",
|
||||
@@ -6447,6 +6469,7 @@ var udpPortNames = map[UDPPort]string{
|
||||
847: "dhcp-failover2",
|
||||
848: "gdoi",
|
||||
853: "domain-s",
|
||||
854: "dlep",
|
||||
860: "iscsi",
|
||||
861: "owamp-control",
|
||||
862: "twamp-control",
|
||||
@@ -8483,7 +8506,6 @@ var udpPortNames = map[UDPPort]string{
|
||||
3068: "ls3bcast",
|
||||
3069: "ls3",
|
||||
3070: "mgxswitch",
|
||||
3071: "csd-mgmt-port",
|
||||
3072: "csd-monitor",
|
||||
3073: "vcrp",
|
||||
3074: "xbox",
|
||||
@@ -9562,6 +9584,7 @@ var udpPortNames = map[UDPPort]string{
|
||||
4188: "vatata",
|
||||
4191: "dsmipv6",
|
||||
4192: "azeti-bd",
|
||||
4197: "hctl",
|
||||
4199: "eims-admin",
|
||||
4300: "corelccam",
|
||||
4301: "d-data",
|
||||
@@ -9570,7 +9593,7 @@ var udpPortNames = map[UDPPort]string{
|
||||
4304: "owserver",
|
||||
4305: "batman",
|
||||
4306: "pinghgl",
|
||||
4307: "visicron-vs",
|
||||
4307: "trueconf",
|
||||
4308: "compx-lockview",
|
||||
4309: "dserver",
|
||||
4310: "mirrtex",
|
||||
@@ -9732,6 +9755,7 @@ var udpPortNames = map[UDPPort]string{
|
||||
4700: "netxms-agent",
|
||||
4701: "netxms-mgmt",
|
||||
4702: "netxms-sync",
|
||||
4711: "trinity-dist",
|
||||
4725: "truckstar",
|
||||
4726: "a26-fap-fgw",
|
||||
4727: "fcis-disc",
|
||||
@@ -10239,6 +10263,7 @@ var udpPortNames = map[UDPPort]string{
|
||||
6446: "mysql-proxy",
|
||||
6455: "skip-cert-recv",
|
||||
6456: "skip-cert-send",
|
||||
6464: "ieee11073-20701",
|
||||
6471: "lvision-lm",
|
||||
6480: "sun-sr-http",
|
||||
6481: "servicetags",
|
||||
@@ -10355,6 +10380,8 @@ var udpPortNames = map[UDPPort]string{
|
||||
7013: "microtalon-dis",
|
||||
7014: "microtalon-com",
|
||||
7015: "talon-webserver",
|
||||
7016: "spg",
|
||||
7017: "grasp",
|
||||
7019: "doceri-view",
|
||||
7020: "dpserve",
|
||||
7021: "dpserveadmin",
|
||||
@@ -10513,6 +10540,8 @@ var udpPortNames = map[UDPPort]string{
|
||||
8002: "teradataordbms",
|
||||
8003: "mcreport",
|
||||
8005: "mxi",
|
||||
8006: "wpl-disc",
|
||||
8007: "warppipe",
|
||||
8008: "http-alt",
|
||||
8019: "qbdb",
|
||||
8020: "intu-ec-svcdisc",
|
||||
@@ -10524,6 +10553,7 @@ var udpPortNames = map[UDPPort]string{
|
||||
8033: "mindprint",
|
||||
8034: "vantronix-mgmt",
|
||||
8040: "ampify",
|
||||
8041: "enguity-xccetp",
|
||||
8052: "senomix01",
|
||||
8053: "senomix02",
|
||||
8054: "senomix03",
|
||||
@@ -10634,6 +10664,7 @@ var udpPortNames = map[UDPPort]string{
|
||||
8793: "acd-pm",
|
||||
8800: "sunwebadmin",
|
||||
8804: "truecm",
|
||||
8805: "pfcp",
|
||||
8808: "ssports-bcast",
|
||||
8873: "dxspider",
|
||||
8880: "cddbp-alt",
|
||||
@@ -11241,6 +11272,7 @@ var udpPortNames = map[UDPPort]string{
|
||||
48556: "com-bardac-dw",
|
||||
48619: "iqobject",
|
||||
48653: "robotraconteur",
|
||||
49001: "nusdp-disc",
|
||||
}
|
||||
var sctpPortNames = map[SCTPPort]string{
|
||||
9: "discard",
|
||||
@@ -11267,6 +11299,7 @@ var sctpPortNames = map[SCTPPort]string{
|
||||
3868: "diameter",
|
||||
4333: "ahsp",
|
||||
4502: "a25-fap-fgw",
|
||||
4711: "trinity-dist",
|
||||
4739: "ipfix",
|
||||
4740: "ipfixs",
|
||||
5060: "sip",
|
||||
@@ -11287,6 +11320,7 @@ var sctpPortNames = map[SCTPPort]string{
|
||||
6706: "frc-lp",
|
||||
6970: "conductor-mpx",
|
||||
7626: "simco",
|
||||
7701: "nfapi",
|
||||
7728: "osvr",
|
||||
8471: "pim-port",
|
||||
9082: "lcs-ap",
|
||||
@@ -11311,4 +11345,7 @@ var sctpPortNames = map[SCTPPort]string{
|
||||
36443: "m2ap",
|
||||
36444: "m3ap",
|
||||
36462: "xw-control",
|
||||
38412: "ng-control",
|
||||
38422: "xn-control",
|
||||
38472: "f1-control",
|
||||
}
|
||||
+48
-13
@@ -24,12 +24,21 @@ const (
|
||||
ICMPv6TypeParameterProblem = 4
|
||||
ICMPv6TypeEchoRequest = 128
|
||||
ICMPv6TypeEchoReply = 129
|
||||
|
||||
// The following are from RFC 4861
|
||||
ICMPv6TypeRouterSolicitation = 133
|
||||
ICMPv6TypeRouterAdvertisement = 134
|
||||
ICMPv6TypeNeighborSolicitation = 135
|
||||
ICMPv6TypeNeighborAdvertisement = 136
|
||||
ICMPv6TypeRedirect = 137
|
||||
|
||||
// The following are from RFC 2710
|
||||
ICMPv6TypeMLDv1MulticastListenerQueryMessage = 130
|
||||
ICMPv6TypeMLDv1MulticastListenerReportMessage = 131
|
||||
ICMPv6TypeMLDv1MulticastListenerDoneMessage = 132
|
||||
|
||||
// The following are from RFC 3810
|
||||
ICMPv6TypeMLDv2MulticastListenerReportMessageV2 = 143
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -165,8 +174,10 @@ func CreateICMPv6TypeCode(typ uint8, code uint8) ICMPv6TypeCode {
|
||||
// ICMPv6 is the layer for IPv6 ICMP packet data
|
||||
type ICMPv6 struct {
|
||||
BaseLayer
|
||||
TypeCode ICMPv6TypeCode
|
||||
Checksum uint16
|
||||
TypeCode ICMPv6TypeCode
|
||||
Checksum uint16
|
||||
// TypeBytes is deprecated and always nil. See the different ICMPv6 message types
|
||||
// instead (e.g. ICMPv6TypeRouterSolicitation).
|
||||
TypeBytes []byte
|
||||
tcpipchecksum
|
||||
}
|
||||
@@ -176,14 +187,13 @@ func (i *ICMPv6) LayerType() gopacket.LayerType { return LayerTypeICMPv6 }
|
||||
|
||||
// DecodeFromBytes decodes the given bytes into this layer.
|
||||
func (i *ICMPv6) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||||
if len(data) < 8 {
|
||||
if len(data) < 4 {
|
||||
df.SetTruncated()
|
||||
return errors.New("ICMP layer less then 8 bytes for ICMPv6 packet")
|
||||
return errors.New("ICMP layer less then 4 bytes for ICMPv6 packet")
|
||||
}
|
||||
i.TypeCode = CreateICMPv6TypeCode(data[0], data[1])
|
||||
i.Checksum = binary.BigEndian.Uint16(data[2:4])
|
||||
i.TypeBytes = data[4:8]
|
||||
i.BaseLayer = BaseLayer{data[:8], data[8:]}
|
||||
i.BaseLayer = BaseLayer{data[:4], data[4:]}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -191,17 +201,12 @@ func (i *ICMPv6) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error
|
||||
// SerializationBuffer, implementing gopacket.SerializableLayer.
|
||||
// See the docs for gopacket.SerializableLayer for more info.
|
||||
func (i *ICMPv6) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
|
||||
if i.TypeBytes == nil {
|
||||
i.TypeBytes = lotsOfZeros[:4]
|
||||
} else if len(i.TypeBytes) != 4 {
|
||||
return fmt.Errorf("invalid type bytes for ICMPv6 packet: %v", i.TypeBytes)
|
||||
}
|
||||
bytes, err := b.PrependBytes(8)
|
||||
bytes, err := b.PrependBytes(4)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
i.TypeCode.SerializeTo(bytes)
|
||||
copy(bytes[4:8], i.TypeBytes)
|
||||
|
||||
if opts.ComputeChecksums {
|
||||
bytes[2] = 0
|
||||
bytes[3] = 0
|
||||
@@ -212,6 +217,7 @@ func (i *ICMPv6) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.Serialize
|
||||
i.Checksum = csum
|
||||
}
|
||||
binary.BigEndian.PutUint16(bytes[2:], i.Checksum)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -222,6 +228,35 @@ func (i *ICMPv6) CanDecode() gopacket.LayerClass {
|
||||
|
||||
// NextLayerType returns the layer type contained by this DecodingLayer.
|
||||
func (i *ICMPv6) NextLayerType() gopacket.LayerType {
|
||||
switch i.TypeCode.Type() {
|
||||
case ICMPv6TypeEchoRequest:
|
||||
return LayerTypeICMPv6Echo
|
||||
case ICMPv6TypeEchoReply:
|
||||
return LayerTypeICMPv6Echo
|
||||
case ICMPv6TypeRouterSolicitation:
|
||||
return LayerTypeICMPv6RouterSolicitation
|
||||
case ICMPv6TypeRouterAdvertisement:
|
||||
return LayerTypeICMPv6RouterAdvertisement
|
||||
case ICMPv6TypeNeighborSolicitation:
|
||||
return LayerTypeICMPv6NeighborSolicitation
|
||||
case ICMPv6TypeNeighborAdvertisement:
|
||||
return LayerTypeICMPv6NeighborAdvertisement
|
||||
case ICMPv6TypeRedirect:
|
||||
return LayerTypeICMPv6Redirect
|
||||
case ICMPv6TypeMLDv1MulticastListenerQueryMessage: // Same Code for MLDv1 Query and MLDv2 Query
|
||||
if len(i.Payload) > 20 { // Only payload size differs
|
||||
return LayerTypeMLDv2MulticastListenerQuery
|
||||
} else {
|
||||
return LayerTypeMLDv1MulticastListenerQuery
|
||||
}
|
||||
case ICMPv6TypeMLDv1MulticastListenerDoneMessage:
|
||||
return LayerTypeMLDv1MulticastListenerDone
|
||||
case ICMPv6TypeMLDv1MulticastListenerReportMessage:
|
||||
return LayerTypeMLDv1MulticastListenerReport
|
||||
case ICMPv6TypeMLDv2MulticastListenerReportMessageV2:
|
||||
return LayerTypeMLDv2MulticastListenerReport
|
||||
}
|
||||
|
||||
return gopacket.LayerTypePayload
|
||||
}
|
||||
|
||||
|
||||
+578
@@ -0,0 +1,578 @@
|
||||
// Copyright 2012 Google, Inc. All rights reserved.
|
||||
// Copyright 2009-2011 Andreas Krennmair. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the LICENSE file in the root of the source
|
||||
// tree.
|
||||
|
||||
package layers
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/google/gopacket"
|
||||
)
|
||||
|
||||
// Based on RFC 4861
|
||||
|
||||
// ICMPv6Opt indicate how to decode the data associated with each ICMPv6Option.
|
||||
type ICMPv6Opt uint8
|
||||
|
||||
const (
|
||||
_ ICMPv6Opt = iota
|
||||
|
||||
// ICMPv6OptSourceAddress contains the link-layer address of the sender of
|
||||
// the packet. It is used in the Neighbor Solicitation, Router
|
||||
// Solicitation, and Router Advertisement packets. Must be ignored for other
|
||||
// Neighbor discovery messages.
|
||||
ICMPv6OptSourceAddress
|
||||
|
||||
// ICMPv6OptTargetAddress contains the link-layer address of the target. It
|
||||
// is used in Neighbor Advertisement and Redirect packets. Must be ignored
|
||||
// for other Neighbor discovery messages.
|
||||
ICMPv6OptTargetAddress
|
||||
|
||||
// ICMPv6OptPrefixInfo provides hosts with on-link prefixes and prefixes
|
||||
// for Address Autoconfiguration. The Prefix Information option appears in
|
||||
// Router Advertisement packets and MUST be silently ignored for other
|
||||
// messages.
|
||||
ICMPv6OptPrefixInfo
|
||||
|
||||
// ICMPv6OptRedirectedHeader is used in Redirect messages and contains all
|
||||
// or part of the packet that is being redirected.
|
||||
ICMPv6OptRedirectedHeader
|
||||
|
||||
// ICMPv6OptMTU is used in Router Advertisement messages to ensure that all
|
||||
// nodes on a link use the same MTU value in those cases where the link MTU
|
||||
// is not well known. This option MUST be silently ignored for other
|
||||
// Neighbor Discovery messages.
|
||||
ICMPv6OptMTU
|
||||
)
|
||||
|
||||
// ICMPv6Echo represents the structure of a ping.
|
||||
type ICMPv6Echo struct {
|
||||
BaseLayer
|
||||
Identifier uint16
|
||||
SeqNumber uint16
|
||||
}
|
||||
|
||||
// ICMPv6RouterSolicitation is sent by hosts to find routers.
|
||||
type ICMPv6RouterSolicitation struct {
|
||||
BaseLayer
|
||||
Options ICMPv6Options
|
||||
}
|
||||
|
||||
// ICMPv6RouterAdvertisement is sent by routers in response to Solicitation.
|
||||
type ICMPv6RouterAdvertisement struct {
|
||||
BaseLayer
|
||||
HopLimit uint8
|
||||
Flags uint8
|
||||
RouterLifetime uint16
|
||||
ReachableTime uint32
|
||||
RetransTimer uint32
|
||||
Options ICMPv6Options
|
||||
}
|
||||
|
||||
// ICMPv6NeighborSolicitation is sent to request the link-layer address of a
|
||||
// target node.
|
||||
type ICMPv6NeighborSolicitation struct {
|
||||
BaseLayer
|
||||
TargetAddress net.IP
|
||||
Options ICMPv6Options
|
||||
}
|
||||
|
||||
// ICMPv6NeighborAdvertisement is sent by nodes in response to Solicitation.
|
||||
type ICMPv6NeighborAdvertisement struct {
|
||||
BaseLayer
|
||||
Flags uint8
|
||||
TargetAddress net.IP
|
||||
Options ICMPv6Options
|
||||
}
|
||||
|
||||
// ICMPv6Redirect is sent by routers to inform hosts of a better first-hop node
|
||||
// on the path to a destination.
|
||||
type ICMPv6Redirect struct {
|
||||
BaseLayer
|
||||
TargetAddress net.IP
|
||||
DestinationAddress net.IP
|
||||
Options ICMPv6Options
|
||||
}
|
||||
|
||||
// ICMPv6Option contains the type and data for a single option.
|
||||
type ICMPv6Option struct {
|
||||
Type ICMPv6Opt
|
||||
Data []byte
|
||||
}
|
||||
|
||||
// ICMPv6Options is a slice of ICMPv6Option.
|
||||
type ICMPv6Options []ICMPv6Option
|
||||
|
||||
func (i ICMPv6Opt) String() string {
|
||||
switch i {
|
||||
case ICMPv6OptSourceAddress:
|
||||
return "SourceAddress"
|
||||
case ICMPv6OptTargetAddress:
|
||||
return "TargetAddress"
|
||||
case ICMPv6OptPrefixInfo:
|
||||
return "PrefixInfo"
|
||||
case ICMPv6OptRedirectedHeader:
|
||||
return "RedirectedHeader"
|
||||
case ICMPv6OptMTU:
|
||||
return "MTU"
|
||||
default:
|
||||
return fmt.Sprintf("Unknown(%d)", i)
|
||||
}
|
||||
}
|
||||
|
||||
// CanDecode returns the set of layer types that this DecodingLayer can decode.
|
||||
func (i *ICMPv6Echo) CanDecode() gopacket.LayerClass {
|
||||
return LayerTypeICMPv6Echo
|
||||
}
|
||||
|
||||
// LayerType returns LayerTypeICMPv6Echo.
|
||||
func (i *ICMPv6Echo) LayerType() gopacket.LayerType {
|
||||
return LayerTypeICMPv6Echo
|
||||
}
|
||||
|
||||
// NextLayerType returns the layer type contained by this DecodingLayer.
|
||||
func (i *ICMPv6Echo) NextLayerType() gopacket.LayerType {
|
||||
return gopacket.LayerTypePayload
|
||||
}
|
||||
|
||||
// DecodeFromBytes decodes the given bytes into this layer.
|
||||
func (i *ICMPv6Echo) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||||
if len(data) < 4 {
|
||||
df.SetTruncated()
|
||||
return errors.New("ICMP layer less then 4 bytes for ICMPv6 Echo")
|
||||
}
|
||||
i.Identifier = binary.BigEndian.Uint16(data[0:2])
|
||||
i.SeqNumber = binary.BigEndian.Uint16(data[2:4])
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SerializeTo writes the serialized form of this layer into the
|
||||
// SerializationBuffer, implementing gopacket.SerializableLayer.
|
||||
// See the docs for gopacket.SerializableLayer for more info.
|
||||
func (i *ICMPv6Echo) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
|
||||
buf, err := b.PrependBytes(4)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
binary.BigEndian.PutUint16(buf, i.Identifier)
|
||||
binary.BigEndian.PutUint16(buf[2:], i.SeqNumber)
|
||||
return nil
|
||||
}
|
||||
|
||||
// LayerType returns LayerTypeICMPv6.
|
||||
func (i *ICMPv6RouterSolicitation) LayerType() gopacket.LayerType {
|
||||
return LayerTypeICMPv6RouterSolicitation
|
||||
}
|
||||
|
||||
// NextLayerType returns the layer type contained by this DecodingLayer.
|
||||
func (i *ICMPv6RouterSolicitation) NextLayerType() gopacket.LayerType {
|
||||
return gopacket.LayerTypePayload
|
||||
}
|
||||
|
||||
// DecodeFromBytes decodes the given bytes into this layer.
|
||||
func (i *ICMPv6RouterSolicitation) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||||
// first 4 bytes are reserved followed by options
|
||||
if len(data) < 4 {
|
||||
df.SetTruncated()
|
||||
return errors.New("ICMP layer less then 4 bytes for ICMPv6 router solicitation")
|
||||
}
|
||||
|
||||
// truncate old options
|
||||
i.Options = i.Options[:0]
|
||||
|
||||
return i.Options.DecodeFromBytes(data[4:], df)
|
||||
}
|
||||
|
||||
// SerializeTo writes the serialized form of this layer into the
|
||||
// SerializationBuffer, implementing gopacket.SerializableLayer.
|
||||
// See the docs for gopacket.SerializableLayer for more info.
|
||||
func (i *ICMPv6RouterSolicitation) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
|
||||
if err := i.Options.SerializeTo(b, opts); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
buf, err := b.PrependBytes(4)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
copy(buf, lotsOfZeros[:4])
|
||||
return nil
|
||||
}
|
||||
|
||||
// CanDecode returns the set of layer types that this DecodingLayer can decode.
|
||||
func (i *ICMPv6RouterSolicitation) CanDecode() gopacket.LayerClass {
|
||||
return LayerTypeICMPv6RouterSolicitation
|
||||
}
|
||||
|
||||
// LayerType returns LayerTypeICMPv6RouterAdvertisement.
|
||||
func (i *ICMPv6RouterAdvertisement) LayerType() gopacket.LayerType {
|
||||
return LayerTypeICMPv6RouterAdvertisement
|
||||
}
|
||||
|
||||
// NextLayerType returns the layer type contained by this DecodingLayer.
|
||||
func (i *ICMPv6RouterAdvertisement) NextLayerType() gopacket.LayerType {
|
||||
return gopacket.LayerTypePayload
|
||||
}
|
||||
|
||||
// DecodeFromBytes decodes the given bytes into this layer.
|
||||
func (i *ICMPv6RouterAdvertisement) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||||
if len(data) < 12 {
|
||||
df.SetTruncated()
|
||||
return errors.New("ICMP layer less then 12 bytes for ICMPv6 router advertisement")
|
||||
}
|
||||
|
||||
i.HopLimit = uint8(data[0])
|
||||
// M, O bit followed by 6 reserved bits
|
||||
i.Flags = uint8(data[1])
|
||||
i.RouterLifetime = binary.BigEndian.Uint16(data[2:4])
|
||||
i.ReachableTime = binary.BigEndian.Uint32(data[4:8])
|
||||
i.RetransTimer = binary.BigEndian.Uint32(data[8:12])
|
||||
i.BaseLayer = BaseLayer{data, nil} // assume no payload
|
||||
|
||||
// truncate old options
|
||||
i.Options = i.Options[:0]
|
||||
|
||||
return i.Options.DecodeFromBytes(data[12:], df)
|
||||
}
|
||||
|
||||
// SerializeTo writes the serialized form of this layer into the
|
||||
// SerializationBuffer, implementing gopacket.SerializableLayer.
|
||||
// See the docs for gopacket.SerializableLayer for more info.
|
||||
func (i *ICMPv6RouterAdvertisement) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
|
||||
if err := i.Options.SerializeTo(b, opts); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
buf, err := b.PrependBytes(12)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
buf[0] = byte(i.HopLimit)
|
||||
buf[1] = byte(i.Flags)
|
||||
binary.BigEndian.PutUint16(buf[2:], i.RouterLifetime)
|
||||
binary.BigEndian.PutUint32(buf[4:], i.ReachableTime)
|
||||
binary.BigEndian.PutUint32(buf[8:], i.RetransTimer)
|
||||
return nil
|
||||
}
|
||||
|
||||
// CanDecode returns the set of layer types that this DecodingLayer can decode.
|
||||
func (i *ICMPv6RouterAdvertisement) CanDecode() gopacket.LayerClass {
|
||||
return LayerTypeICMPv6RouterAdvertisement
|
||||
}
|
||||
|
||||
// ManagedAddressConfig is true when addresses are available via DHCPv6. If
|
||||
// set, the OtherConfig flag is redundant.
|
||||
func (i *ICMPv6RouterAdvertisement) ManagedAddressConfig() bool {
|
||||
return i.Flags&0x80 != 0
|
||||
}
|
||||
|
||||
// OtherConfig is true when there is other configuration information available
|
||||
// via DHCPv6. For example, DNS-related information.
|
||||
func (i *ICMPv6RouterAdvertisement) OtherConfig() bool {
|
||||
return i.Flags&0x40 != 0
|
||||
}
|
||||
|
||||
// LayerType returns LayerTypeICMPv6NeighborSolicitation.
|
||||
func (i *ICMPv6NeighborSolicitation) LayerType() gopacket.LayerType {
|
||||
return LayerTypeICMPv6NeighborSolicitation
|
||||
}
|
||||
|
||||
// NextLayerType returns the layer type contained by this DecodingLayer.
|
||||
func (i *ICMPv6NeighborSolicitation) NextLayerType() gopacket.LayerType {
|
||||
return gopacket.LayerTypePayload
|
||||
}
|
||||
|
||||
// DecodeFromBytes decodes the given bytes into this layer.
|
||||
func (i *ICMPv6NeighborSolicitation) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||||
if len(data) < 20 {
|
||||
df.SetTruncated()
|
||||
return errors.New("ICMP layer less then 20 bytes for ICMPv6 neighbor solicitation")
|
||||
}
|
||||
|
||||
i.TargetAddress = net.IP(data[4:20])
|
||||
i.BaseLayer = BaseLayer{data, nil} // assume no payload
|
||||
|
||||
// truncate old options
|
||||
i.Options = i.Options[:0]
|
||||
|
||||
return i.Options.DecodeFromBytes(data[20:], df)
|
||||
}
|
||||
|
||||
// SerializeTo writes the serialized form of this layer into the
|
||||
// SerializationBuffer, implementing gopacket.SerializableLayer.
|
||||
// See the docs for gopacket.SerializableLayer for more info.
|
||||
func (i *ICMPv6NeighborSolicitation) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
|
||||
if err := i.Options.SerializeTo(b, opts); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
buf, err := b.PrependBytes(20)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
copy(buf, lotsOfZeros[:4])
|
||||
copy(buf[4:], i.TargetAddress)
|
||||
return nil
|
||||
}
|
||||
|
||||
// CanDecode returns the set of layer types that this DecodingLayer can decode.
|
||||
func (i *ICMPv6NeighborSolicitation) CanDecode() gopacket.LayerClass {
|
||||
return LayerTypeICMPv6NeighborSolicitation
|
||||
}
|
||||
|
||||
// LayerType returns LayerTypeICMPv6NeighborAdvertisement.
|
||||
func (i *ICMPv6NeighborAdvertisement) LayerType() gopacket.LayerType {
|
||||
return LayerTypeICMPv6NeighborAdvertisement
|
||||
}
|
||||
|
||||
// NextLayerType returns the layer type contained by this DecodingLayer.
|
||||
func (i *ICMPv6NeighborAdvertisement) NextLayerType() gopacket.LayerType {
|
||||
return gopacket.LayerTypePayload
|
||||
}
|
||||
|
||||
// DecodeFromBytes decodes the given bytes into this layer.
|
||||
func (i *ICMPv6NeighborAdvertisement) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||||
if len(data) < 20 {
|
||||
df.SetTruncated()
|
||||
return errors.New("ICMP layer less then 20 bytes for ICMPv6 neighbor advertisement")
|
||||
}
|
||||
|
||||
i.Flags = uint8(data[0])
|
||||
i.TargetAddress = net.IP(data[4:20])
|
||||
i.BaseLayer = BaseLayer{data, nil} // assume no payload
|
||||
|
||||
// truncate old options
|
||||
i.Options = i.Options[:0]
|
||||
|
||||
return i.Options.DecodeFromBytes(data[20:], df)
|
||||
}
|
||||
|
||||
// SerializeTo writes the serialized form of this layer into the
|
||||
// SerializationBuffer, implementing gopacket.SerializableLayer.
|
||||
// See the docs for gopacket.SerializableLayer for more info.
|
||||
func (i *ICMPv6NeighborAdvertisement) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
|
||||
if err := i.Options.SerializeTo(b, opts); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
buf, err := b.PrependBytes(20)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
buf[0] = byte(i.Flags)
|
||||
copy(buf[1:], lotsOfZeros[:3])
|
||||
copy(buf[4:], i.TargetAddress)
|
||||
return nil
|
||||
}
|
||||
|
||||
// CanDecode returns the set of layer types that this DecodingLayer can decode.
|
||||
func (i *ICMPv6NeighborAdvertisement) CanDecode() gopacket.LayerClass {
|
||||
return LayerTypeICMPv6NeighborAdvertisement
|
||||
}
|
||||
|
||||
// Router indicates whether the sender is a router or not.
|
||||
func (i *ICMPv6NeighborAdvertisement) Router() bool {
|
||||
return i.Flags&0x80 != 0
|
||||
}
|
||||
|
||||
// Solicited indicates whether the advertisement was solicited or not.
|
||||
func (i *ICMPv6NeighborAdvertisement) Solicited() bool {
|
||||
return i.Flags&0x40 != 0
|
||||
}
|
||||
|
||||
// Override indicates whether the advertisement should Override an existing
|
||||
// cache entry.
|
||||
func (i *ICMPv6NeighborAdvertisement) Override() bool {
|
||||
return i.Flags&0x20 != 0
|
||||
}
|
||||
|
||||
// LayerType returns LayerTypeICMPv6Redirect.
|
||||
func (i *ICMPv6Redirect) LayerType() gopacket.LayerType {
|
||||
return LayerTypeICMPv6Redirect
|
||||
}
|
||||
|
||||
// NextLayerType returns the layer type contained by this DecodingLayer.
|
||||
func (i *ICMPv6Redirect) NextLayerType() gopacket.LayerType {
|
||||
return gopacket.LayerTypePayload
|
||||
}
|
||||
|
||||
// DecodeFromBytes decodes the given bytes into this layer.
|
||||
func (i *ICMPv6Redirect) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||||
if len(data) < 36 {
|
||||
df.SetTruncated()
|
||||
return errors.New("ICMP layer less then 36 bytes for ICMPv6 redirect")
|
||||
}
|
||||
|
||||
i.TargetAddress = net.IP(data[4:20])
|
||||
i.DestinationAddress = net.IP(data[20:36])
|
||||
i.BaseLayer = BaseLayer{data, nil} // assume no payload
|
||||
|
||||
// truncate old options
|
||||
i.Options = i.Options[:0]
|
||||
|
||||
return i.Options.DecodeFromBytes(data[36:], df)
|
||||
}
|
||||
|
||||
// SerializeTo writes the serialized form of this layer into the
|
||||
// SerializationBuffer, implementing gopacket.SerializableLayer.
|
||||
// See the docs for gopacket.SerializableLayer for more info.
|
||||
func (i *ICMPv6Redirect) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
|
||||
if err := i.Options.SerializeTo(b, opts); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
buf, err := b.PrependBytes(36)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
copy(buf, lotsOfZeros[:4])
|
||||
copy(buf[4:], i.TargetAddress)
|
||||
copy(buf[20:], i.DestinationAddress)
|
||||
return nil
|
||||
}
|
||||
|
||||
// CanDecode returns the set of layer types that this DecodingLayer can decode.
|
||||
func (i *ICMPv6Redirect) CanDecode() gopacket.LayerClass {
|
||||
return LayerTypeICMPv6Redirect
|
||||
}
|
||||
|
||||
func (i ICMPv6Option) String() string {
|
||||
hd := hex.EncodeToString(i.Data)
|
||||
if len(hd) > 0 {
|
||||
hd = " 0x" + hd
|
||||
}
|
||||
|
||||
switch i.Type {
|
||||
case ICMPv6OptSourceAddress, ICMPv6OptTargetAddress:
|
||||
return fmt.Sprintf("ICMPv6Option(%s:%v)",
|
||||
i.Type,
|
||||
net.HardwareAddr(i.Data))
|
||||
case ICMPv6OptPrefixInfo:
|
||||
if len(i.Data) == 30 {
|
||||
prefixLen := uint8(i.Data[0])
|
||||
onLink := (i.Data[1]&0x80 != 0)
|
||||
autonomous := (i.Data[1]&0x40 != 0)
|
||||
validLifetime := time.Duration(binary.BigEndian.Uint32(i.Data[2:6])) * time.Second
|
||||
preferredLifetime := time.Duration(binary.BigEndian.Uint32(i.Data[6:10])) * time.Second
|
||||
|
||||
prefix := net.IP(i.Data[14:])
|
||||
|
||||
return fmt.Sprintf("ICMPv6Option(%s:%v/%v:%t:%t:%v:%v)",
|
||||
i.Type,
|
||||
prefix, prefixLen,
|
||||
onLink, autonomous,
|
||||
validLifetime, preferredLifetime)
|
||||
}
|
||||
case ICMPv6OptRedirectedHeader:
|
||||
// could invoke IP decoder on data... probably best not to
|
||||
break
|
||||
case ICMPv6OptMTU:
|
||||
if len(i.Data) == 6 {
|
||||
return fmt.Sprintf("ICMPv6Option(%s:%v)",
|
||||
i.Type,
|
||||
binary.BigEndian.Uint32(i.Data[2:]))
|
||||
}
|
||||
|
||||
}
|
||||
return fmt.Sprintf("ICMPv6Option(%s:%s)", i.Type, hd)
|
||||
}
|
||||
|
||||
// DecodeFromBytes decodes the given bytes into this layer.
|
||||
func (i *ICMPv6Options) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||||
for len(data) > 0 {
|
||||
if len(data) < 2 {
|
||||
df.SetTruncated()
|
||||
return errors.New("ICMP layer less then 2 bytes for ICMPv6 message option")
|
||||
}
|
||||
|
||||
// unit is 8 octets, convert to bytes
|
||||
length := int(data[1]) * 8
|
||||
|
||||
if length == 0 {
|
||||
df.SetTruncated()
|
||||
return errors.New("ICMPv6 message option with length 0")
|
||||
}
|
||||
|
||||
if len(data) < length {
|
||||
df.SetTruncated()
|
||||
return fmt.Errorf("ICMP layer only %v bytes for ICMPv6 message option with length %v", len(data), length)
|
||||
}
|
||||
|
||||
o := ICMPv6Option{
|
||||
Type: ICMPv6Opt(data[0]),
|
||||
Data: data[2:length],
|
||||
}
|
||||
|
||||
// chop off option we just consumed
|
||||
data = data[length:]
|
||||
|
||||
*i = append(*i, o)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SerializeTo writes the serialized form of this layer into the
|
||||
// SerializationBuffer, implementing gopacket.SerializableLayer.
|
||||
// See the docs for gopacket.SerializableLayer for more info.
|
||||
func (i *ICMPv6Options) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
|
||||
for _, opt := range []ICMPv6Option(*i) {
|
||||
length := len(opt.Data) + 2
|
||||
buf, err := b.PrependBytes(length)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
buf[0] = byte(opt.Type)
|
||||
buf[1] = byte(length / 8)
|
||||
copy(buf[2:], opt.Data)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func decodeICMPv6Echo(data []byte, p gopacket.PacketBuilder) error {
|
||||
i := &ICMPv6Echo{}
|
||||
return decodingLayerDecoder(i, data, p)
|
||||
}
|
||||
|
||||
func decodeICMPv6RouterSolicitation(data []byte, p gopacket.PacketBuilder) error {
|
||||
i := &ICMPv6RouterSolicitation{}
|
||||
return decodingLayerDecoder(i, data, p)
|
||||
}
|
||||
|
||||
func decodeICMPv6RouterAdvertisement(data []byte, p gopacket.PacketBuilder) error {
|
||||
i := &ICMPv6RouterAdvertisement{}
|
||||
return decodingLayerDecoder(i, data, p)
|
||||
}
|
||||
|
||||
func decodeICMPv6NeighborSolicitation(data []byte, p gopacket.PacketBuilder) error {
|
||||
i := &ICMPv6NeighborSolicitation{}
|
||||
return decodingLayerDecoder(i, data, p)
|
||||
}
|
||||
|
||||
func decodeICMPv6NeighborAdvertisement(data []byte, p gopacket.PacketBuilder) error {
|
||||
i := &ICMPv6NeighborAdvertisement{}
|
||||
return decodingLayerDecoder(i, data, p)
|
||||
}
|
||||
|
||||
func decodeICMPv6Redirect(data []byte, p gopacket.PacketBuilder) error {
|
||||
i := &ICMPv6Redirect{}
|
||||
return decodingLayerDecoder(i, data, p)
|
||||
}
|
||||
+20
-6
@@ -186,6 +186,10 @@ func (ip *IPv4) flagsfrags() (ff uint16) {
|
||||
|
||||
// DecodeFromBytes decodes the given bytes into this layer.
|
||||
func (ip *IPv4) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||||
if len(data) < 20 {
|
||||
df.SetTruncated()
|
||||
return fmt.Errorf("Invalid ip4 header. Length %d less than 20", len(data))
|
||||
}
|
||||
flagsfrags := binary.BigEndian.Uint16(data[6:8])
|
||||
|
||||
ip.Version = uint8(data[0]) >> 4
|
||||
@@ -201,6 +205,7 @@ func (ip *IPv4) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||||
ip.SrcIP = data[12:16]
|
||||
ip.DstIP = data[16:20]
|
||||
ip.Options = ip.Options[:0]
|
||||
ip.Padding = nil
|
||||
// Set up an initial guess for contents/payload... we'll reset these soon.
|
||||
ip.BaseLayer = BaseLayer{Contents: data}
|
||||
|
||||
@@ -243,19 +248,28 @@ func (ip *IPv4) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||||
opt.OptionLength = 1
|
||||
ip.Options = append(ip.Options, opt)
|
||||
ip.Padding = data[1:]
|
||||
break
|
||||
return nil
|
||||
case 1: // 1 byte padding
|
||||
opt.OptionLength = 1
|
||||
data = data[1:]
|
||||
ip.Options = append(ip.Options, opt)
|
||||
default:
|
||||
if len(data) < 2 {
|
||||
df.SetTruncated()
|
||||
return fmt.Errorf("Invalid ip4 option length. Length %d less than 2", len(data))
|
||||
}
|
||||
opt.OptionLength = data[1]
|
||||
if len(data) < int(opt.OptionLength) {
|
||||
df.SetTruncated()
|
||||
return fmt.Errorf("IP option length exceeds remaining IP header size, option type %v length %v", opt.OptionType, opt.OptionLength)
|
||||
}
|
||||
if opt.OptionLength <= 2 {
|
||||
return fmt.Errorf("Invalid IP option type %v length %d. Must be greater than 2", opt.OptionType, opt.OptionLength)
|
||||
}
|
||||
opt.OptionData = data[2:opt.OptionLength]
|
||||
}
|
||||
if len(data) >= int(opt.OptionLength) {
|
||||
data = data[opt.OptionLength:]
|
||||
} else {
|
||||
return fmt.Errorf("IP option length exceeds remaining IP header size, option type %v length %v", opt.OptionType, opt.OptionLength)
|
||||
ip.Options = append(ip.Options, opt)
|
||||
}
|
||||
ip.Options = append(ip.Options, opt)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
+125
-68
@@ -17,7 +17,8 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
IPv6HopByHopOptionJumbogram = 0xC2 // RFC 2675
|
||||
// IPv6HopByHopOptionJumbogram code as defined in RFC 2675
|
||||
IPv6HopByHopOptionJumbogram = 0xC2
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -42,10 +43,11 @@ type IPv6 struct {
|
||||
}
|
||||
|
||||
// LayerType returns LayerTypeIPv6
|
||||
func (i *IPv6) LayerType() gopacket.LayerType { return LayerTypeIPv6 }
|
||||
func (ipv6 *IPv6) LayerType() gopacket.LayerType { return LayerTypeIPv6 }
|
||||
|
||||
func (i *IPv6) NetworkFlow() gopacket.Flow {
|
||||
return gopacket.NewFlow(EndpointIPv6, i.SrcIP, i.DstIP)
|
||||
// NetworkFlow returns this new Flow (EndpointIPv6, SrcIP, DstIP)
|
||||
func (ipv6 *IPv6) NetworkFlow() gopacket.Flow {
|
||||
return gopacket.NewFlow(EndpointIPv6, ipv6.SrcIP, ipv6.DstIP)
|
||||
}
|
||||
|
||||
// Search for Jumbo Payload TLV in IPv6HopByHop and return (length, true) if found
|
||||
@@ -115,7 +117,7 @@ func setIPv6PayloadJumboLength(hbh []byte) error {
|
||||
opt := hbh[offset]
|
||||
if opt == 0 {
|
||||
//Pad1
|
||||
offset += 1
|
||||
offset++
|
||||
continue
|
||||
}
|
||||
optLen := int(hbh[offset+1])
|
||||
@@ -134,7 +136,7 @@ func setIPv6PayloadJumboLength(hbh []byte) error {
|
||||
// SerializeTo writes the serialized form of this layer into the
|
||||
// SerializationBuffer, implementing gopacket.SerializableLayer.
|
||||
// See the docs for gopacket.SerializableLayer for more info.
|
||||
func (ip6 *IPv6) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
|
||||
func (ipv6 *IPv6) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
|
||||
var jumbo bool
|
||||
var err error
|
||||
|
||||
@@ -145,11 +147,11 @@ func (ip6 *IPv6) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.Serialize
|
||||
if opts.FixLengths {
|
||||
// We need to set the length later because the hop-by-hop header may
|
||||
// not exist or else need padding, so pLen may yet change
|
||||
addIPv6JumboOption(ip6)
|
||||
} else if ip6.HopByHop == nil {
|
||||
addIPv6JumboOption(ipv6)
|
||||
} else if ipv6.HopByHop == nil {
|
||||
return fmt.Errorf("Cannot fit payload length of %d into IPv6 packet", pLen)
|
||||
} else {
|
||||
_, ok, err := getIPv6HopByHopJumboLength(ip6.HopByHop)
|
||||
_, ok, err := getIPv6HopByHopJumboLength(ipv6.HopByHop)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -158,12 +160,22 @@ func (ip6 *IPv6) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.Serialize
|
||||
}
|
||||
}
|
||||
}
|
||||
if ip6.HopByHop != nil {
|
||||
if ip6.NextHeader != IPProtocolIPv6HopByHop {
|
||||
// Just fix it instead of throwing an error
|
||||
ip6.NextHeader = IPProtocolIPv6HopByHop
|
||||
|
||||
hbhAlreadySerialized := false
|
||||
if ipv6.HopByHop != nil {
|
||||
for _, l := range b.Layers() {
|
||||
if l == LayerTypeIPv6HopByHop {
|
||||
hbhAlreadySerialized = true
|
||||
break
|
||||
}
|
||||
}
|
||||
err = ip6.HopByHop.SerializeTo(b, opts)
|
||||
}
|
||||
if ipv6.HopByHop != nil && !hbhAlreadySerialized {
|
||||
if ipv6.NextHeader != IPProtocolIPv6HopByHop {
|
||||
// Just fix it instead of throwing an error
|
||||
ipv6.NextHeader = IPProtocolIPv6HopByHop
|
||||
}
|
||||
err = ipv6.HopByHop.SerializeTo(b, opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -176,6 +188,7 @@ func (ip6 *IPv6) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.Serialize
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !jumbo && pLen > ipv6MaxPayloadLength {
|
||||
return errors.New("Cannot fit payload into IPv6 header")
|
||||
}
|
||||
@@ -183,88 +196,98 @@ func (ip6 *IPv6) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.Serialize
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
bytes[0] = (ip6.Version << 4) | (ip6.TrafficClass >> 4)
|
||||
bytes[1] = (ip6.TrafficClass << 4) | uint8(ip6.FlowLabel>>16)
|
||||
binary.BigEndian.PutUint16(bytes[2:], uint16(ip6.FlowLabel))
|
||||
bytes[0] = (ipv6.Version << 4) | (ipv6.TrafficClass >> 4)
|
||||
bytes[1] = (ipv6.TrafficClass << 4) | uint8(ipv6.FlowLabel>>16)
|
||||
binary.BigEndian.PutUint16(bytes[2:], uint16(ipv6.FlowLabel))
|
||||
if opts.FixLengths {
|
||||
if jumbo {
|
||||
ip6.Length = 0
|
||||
ipv6.Length = 0
|
||||
} else {
|
||||
ip6.Length = uint16(pLen)
|
||||
ipv6.Length = uint16(pLen)
|
||||
}
|
||||
}
|
||||
binary.BigEndian.PutUint16(bytes[4:], ip6.Length)
|
||||
bytes[6] = byte(ip6.NextHeader)
|
||||
bytes[7] = byte(ip6.HopLimit)
|
||||
if err := ip6.AddressTo16(); err != nil {
|
||||
binary.BigEndian.PutUint16(bytes[4:], ipv6.Length)
|
||||
bytes[6] = byte(ipv6.NextHeader)
|
||||
bytes[7] = byte(ipv6.HopLimit)
|
||||
if err := ipv6.AddressTo16(); err != nil {
|
||||
return err
|
||||
}
|
||||
copy(bytes[8:], ip6.SrcIP)
|
||||
copy(bytes[24:], ip6.DstIP)
|
||||
copy(bytes[8:], ipv6.SrcIP)
|
||||
copy(bytes[24:], ipv6.DstIP)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ip6 *IPv6) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||||
ip6.Version = uint8(data[0]) >> 4
|
||||
ip6.TrafficClass = uint8((binary.BigEndian.Uint16(data[0:2]) >> 4) & 0x00FF)
|
||||
ip6.FlowLabel = binary.BigEndian.Uint32(data[0:4]) & 0x000FFFFF
|
||||
ip6.Length = binary.BigEndian.Uint16(data[4:6])
|
||||
ip6.NextHeader = IPProtocol(data[6])
|
||||
ip6.HopLimit = data[7]
|
||||
ip6.SrcIP = data[8:24]
|
||||
ip6.DstIP = data[24:40]
|
||||
ip6.HopByHop = nil
|
||||
ip6.BaseLayer = BaseLayer{data[:40], data[40:]}
|
||||
// DecodeFromBytes implementation according to gopacket.DecodingLayer
|
||||
func (ipv6 *IPv6) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||||
if len(data) < 40 {
|
||||
df.SetTruncated()
|
||||
return fmt.Errorf("Invalid ip6 header. Length %d less than 40", len(data))
|
||||
}
|
||||
ipv6.Version = uint8(data[0]) >> 4
|
||||
ipv6.TrafficClass = uint8((binary.BigEndian.Uint16(data[0:2]) >> 4) & 0x00FF)
|
||||
ipv6.FlowLabel = binary.BigEndian.Uint32(data[0:4]) & 0x000FFFFF
|
||||
ipv6.Length = binary.BigEndian.Uint16(data[4:6])
|
||||
ipv6.NextHeader = IPProtocol(data[6])
|
||||
ipv6.HopLimit = data[7]
|
||||
ipv6.SrcIP = data[8:24]
|
||||
ipv6.DstIP = data[24:40]
|
||||
ipv6.HopByHop = nil
|
||||
ipv6.BaseLayer = BaseLayer{data[:40], data[40:]}
|
||||
|
||||
// We treat a HopByHop IPv6 option as part of the IPv6 packet, since its
|
||||
// options are crucial for understanding what's actually happening per packet.
|
||||
if ip6.NextHeader == IPProtocolIPv6HopByHop {
|
||||
err := ip6.hbh.DecodeFromBytes(ip6.Payload, df)
|
||||
if ipv6.NextHeader == IPProtocolIPv6HopByHop {
|
||||
err := ipv6.hbh.DecodeFromBytes(ipv6.Payload, df)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ip6.HopByHop = &ip6.hbh
|
||||
pEnd, jumbo, err := getIPv6HopByHopJumboLength(ip6.HopByHop)
|
||||
ipv6.HopByHop = &ipv6.hbh
|
||||
pEnd, jumbo, err := getIPv6HopByHopJumboLength(ipv6.HopByHop)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if jumbo && ip6.Length == 0 {
|
||||
if jumbo && ipv6.Length == 0 {
|
||||
pEnd := int(pEnd)
|
||||
if pEnd > len(ip6.Payload) {
|
||||
if pEnd > len(ipv6.Payload) {
|
||||
df.SetTruncated()
|
||||
pEnd = len(ip6.Payload)
|
||||
pEnd = len(ipv6.Payload)
|
||||
}
|
||||
ip6.Payload = ip6.Payload[:pEnd]
|
||||
ipv6.Payload = ipv6.Payload[:pEnd]
|
||||
return nil
|
||||
} else if jumbo && ip6.Length != 0 {
|
||||
} else if jumbo && ipv6.Length != 0 {
|
||||
return errors.New("IPv6 has jumbo length and IPv6 length is not 0")
|
||||
} else if !jumbo && ip6.Length == 0 {
|
||||
} else if !jumbo && ipv6.Length == 0 {
|
||||
return errors.New("IPv6 length 0, but HopByHop header does not have jumbogram option")
|
||||
} else {
|
||||
ipv6.Payload = ipv6.Payload[ipv6.hbh.ActualLength:]
|
||||
}
|
||||
}
|
||||
|
||||
if ip6.Length == 0 {
|
||||
return fmt.Errorf("IPv6 length 0, but next header is %v, not HopByHop", ip6.NextHeader)
|
||||
} else {
|
||||
pEnd := int(ip6.Length)
|
||||
if pEnd > len(ip6.Payload) {
|
||||
df.SetTruncated()
|
||||
pEnd = len(ip6.Payload)
|
||||
}
|
||||
ip6.Payload = ip6.Payload[:pEnd]
|
||||
if ipv6.Length == 0 {
|
||||
return fmt.Errorf("IPv6 length 0, but next header is %v, not HopByHop", ipv6.NextHeader)
|
||||
}
|
||||
|
||||
pEnd := int(ipv6.Length)
|
||||
if pEnd > len(ipv6.Payload) {
|
||||
df.SetTruncated()
|
||||
pEnd = len(ipv6.Payload)
|
||||
}
|
||||
ipv6.Payload = ipv6.Payload[:pEnd]
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *IPv6) CanDecode() gopacket.LayerClass {
|
||||
// CanDecode implementation according to gopacket.DecodingLayer
|
||||
func (ipv6 *IPv6) CanDecode() gopacket.LayerClass {
|
||||
return LayerTypeIPv6
|
||||
}
|
||||
|
||||
func (i *IPv6) NextLayerType() gopacket.LayerType {
|
||||
if i.HopByHop != nil {
|
||||
return i.HopByHop.NextHeader.LayerType()
|
||||
// NextLayerType implementation according to gopacket.DecodingLayer
|
||||
func (ipv6 *IPv6) NextLayerType() gopacket.LayerType {
|
||||
if ipv6.HopByHop != nil {
|
||||
return ipv6.HopByHop.NextHeader.LayerType()
|
||||
}
|
||||
return i.NextHeader.LayerType()
|
||||
return ipv6.NextHeader.LayerType()
|
||||
}
|
||||
|
||||
func decodeIPv6(data []byte, p gopacket.PacketBuilder) error {
|
||||
@@ -384,10 +407,17 @@ type ipv6ExtensionBase struct {
|
||||
ActualLength int
|
||||
}
|
||||
|
||||
func decodeIPv6ExtensionBase(data []byte) (i ipv6ExtensionBase) {
|
||||
func decodeIPv6ExtensionBase(data []byte, df gopacket.DecodeFeedback) (i ipv6ExtensionBase, returnedErr error) {
|
||||
if len(data) < 2 {
|
||||
df.SetTruncated()
|
||||
return ipv6ExtensionBase{}, fmt.Errorf("Invalid ip6-extension header. Length %d less than 2", len(data))
|
||||
}
|
||||
i.NextHeader = IPProtocol(data[0])
|
||||
i.HeaderLength = data[1]
|
||||
i.ActualLength = int(i.HeaderLength)*8 + 8
|
||||
if len(data) < i.ActualLength {
|
||||
return ipv6ExtensionBase{}, fmt.Errorf("Invalid ip6-extension header. Length %d less than specified length %d", len(data), i.ActualLength)
|
||||
}
|
||||
i.Contents = data[:i.ActualLength]
|
||||
i.Payload = data[i.ActualLength:]
|
||||
return
|
||||
@@ -401,17 +431,23 @@ type IPv6ExtensionSkipper struct {
|
||||
BaseLayer
|
||||
}
|
||||
|
||||
// DecodeFromBytes implementation according to gopacket.DecodingLayer
|
||||
func (i *IPv6ExtensionSkipper) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||||
extension := decodeIPv6ExtensionBase(data)
|
||||
extension, err := decodeIPv6ExtensionBase(data, df)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
i.BaseLayer = BaseLayer{data[:extension.ActualLength], data[extension.ActualLength:]}
|
||||
i.NextHeader = extension.NextHeader
|
||||
return nil
|
||||
}
|
||||
|
||||
// CanDecode implementation according to gopacket.DecodingLayer
|
||||
func (i *IPv6ExtensionSkipper) CanDecode() gopacket.LayerClass {
|
||||
return LayerClassIPv6Extension
|
||||
}
|
||||
|
||||
// NextLayerType implementation according to gopacket.DecodingLayer
|
||||
func (i *IPv6ExtensionSkipper) NextLayerType() gopacket.LayerType {
|
||||
return i.NextHeader.LayerType()
|
||||
}
|
||||
@@ -428,6 +464,7 @@ type IPv6HopByHop struct {
|
||||
// LayerType returns LayerTypeIPv6HopByHop.
|
||||
func (i *IPv6HopByHop) LayerType() gopacket.LayerType { return LayerTypeIPv6HopByHop }
|
||||
|
||||
// SerializeTo implementation according to gopacket.SerializableLayer
|
||||
func (i *IPv6HopByHop) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
|
||||
var bytes []byte
|
||||
var err error
|
||||
@@ -460,8 +497,13 @@ func (i *IPv6HopByHop) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.Ser
|
||||
return nil
|
||||
}
|
||||
|
||||
// DecodeFromBytes implementation according to gopacket.DecodingLayer
|
||||
func (i *IPv6HopByHop) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||||
i.ipv6ExtensionBase = decodeIPv6ExtensionBase(data)
|
||||
var err error
|
||||
i.ipv6ExtensionBase, err = decodeIPv6ExtensionBase(data, df)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
offset := 2
|
||||
for offset < i.ActualLength {
|
||||
opt := decodeIPv6HeaderTLVOption(data[offset:])
|
||||
@@ -481,6 +523,7 @@ func decodeIPv6HopByHop(data []byte, p gopacket.PacketBuilder) error {
|
||||
return p.NextDecoder(i.NextHeader)
|
||||
}
|
||||
|
||||
// SetJumboLength adds the IPv6HopByHopOptionJumbogram with the given length
|
||||
func (o *IPv6HopByHopOption) SetJumboLength(len uint32) {
|
||||
o.OptionType = IPv6HopByHopOptionJumbogram
|
||||
o.OptionLength = 4
|
||||
@@ -509,8 +552,12 @@ type IPv6Routing struct {
|
||||
func (i *IPv6Routing) LayerType() gopacket.LayerType { return LayerTypeIPv6Routing }
|
||||
|
||||
func decodeIPv6Routing(data []byte, p gopacket.PacketBuilder) error {
|
||||
base, err := decodeIPv6ExtensionBase(data, p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
i := &IPv6Routing{
|
||||
ipv6ExtensionBase: decodeIPv6ExtensionBase(data),
|
||||
ipv6ExtensionBase: base,
|
||||
RoutingType: data[2],
|
||||
SegmentsLeft: data[3],
|
||||
Reserved: data[4:8],
|
||||
@@ -548,6 +595,10 @@ type IPv6Fragment struct {
|
||||
func (i *IPv6Fragment) LayerType() gopacket.LayerType { return LayerTypeIPv6Fragment }
|
||||
|
||||
func decodeIPv6Fragment(data []byte, p gopacket.PacketBuilder) error {
|
||||
if len(data) < 8 {
|
||||
p.SetTruncated()
|
||||
return fmt.Errorf("Invalid ip6-fragment header. Length %d less than 8", len(data))
|
||||
}
|
||||
i := &IPv6Fragment{
|
||||
BaseLayer: BaseLayer{data[:8], data[8:]},
|
||||
NextHeader: IPProtocol(data[0]),
|
||||
@@ -573,8 +624,13 @@ type IPv6Destination struct {
|
||||
// LayerType returns LayerTypeIPv6Destination.
|
||||
func (i *IPv6Destination) LayerType() gopacket.LayerType { return LayerTypeIPv6Destination }
|
||||
|
||||
// DecodeFromBytes implementation according to gopacket.DecodingLayer
|
||||
func (i *IPv6Destination) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
|
||||
i.ipv6ExtensionBase = decodeIPv6ExtensionBase(data)
|
||||
var err error
|
||||
i.ipv6ExtensionBase, err = decodeIPv6ExtensionBase(data, df)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
offset := 2
|
||||
for offset < i.ActualLength {
|
||||
opt := decodeIPv6HeaderTLVOption(data[offset:])
|
||||
@@ -639,11 +695,12 @@ func checkIPv6Address(addr net.IP) error {
|
||||
return fmt.Errorf("wrong length of %d bytes instead of %d", len(addr), net.IPv6len)
|
||||
}
|
||||
|
||||
func (ip *IPv6) AddressTo16() error {
|
||||
if err := checkIPv6Address(ip.SrcIP); err != nil {
|
||||
// AddressTo16 ensures IPv6.SrcIP and IPv6.DstIP are actually IPv6 addresses (i.e. 16 byte addresses)
|
||||
func (ipv6 *IPv6) AddressTo16() error {
|
||||
if err := checkIPv6Address(ipv6.SrcIP); err != nil {
|
||||
return fmt.Errorf("Invalid source IPv6 address (%s)", err)
|
||||
}
|
||||
if err := checkIPv6Address(ip.DstIP); err != nil {
|
||||
if err := checkIPv6Address(ipv6.DstIP); err != nil {
|
||||
return fmt.Errorf("Invalid destination IPv6 address (%s)", err)
|
||||
}
|
||||
return nil
|
||||
|
||||
+155
-112
@@ -11,118 +11,138 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
LayerTypeARP = gopacket.RegisterLayerType(10, gopacket.LayerTypeMetadata{Name: "ARP", Decoder: gopacket.DecodeFunc(decodeARP)})
|
||||
LayerTypeCiscoDiscovery = gopacket.RegisterLayerType(11, gopacket.LayerTypeMetadata{Name: "CiscoDiscovery", Decoder: gopacket.DecodeFunc(decodeCiscoDiscovery)})
|
||||
LayerTypeEthernetCTP = gopacket.RegisterLayerType(12, gopacket.LayerTypeMetadata{Name: "EthernetCTP", Decoder: gopacket.DecodeFunc(decodeEthernetCTP)})
|
||||
LayerTypeEthernetCTPForwardData = gopacket.RegisterLayerType(13, gopacket.LayerTypeMetadata{Name: "EthernetCTPForwardData", Decoder: nil})
|
||||
LayerTypeEthernetCTPReply = gopacket.RegisterLayerType(14, gopacket.LayerTypeMetadata{Name: "EthernetCTPReply", Decoder: nil})
|
||||
LayerTypeDot1Q = gopacket.RegisterLayerType(15, gopacket.LayerTypeMetadata{Name: "Dot1Q", Decoder: gopacket.DecodeFunc(decodeDot1Q)})
|
||||
LayerTypeEtherIP = gopacket.RegisterLayerType(16, gopacket.LayerTypeMetadata{Name: "EtherIP", Decoder: gopacket.DecodeFunc(decodeEtherIP)})
|
||||
LayerTypeEthernet = gopacket.RegisterLayerType(17, gopacket.LayerTypeMetadata{Name: "Ethernet", Decoder: gopacket.DecodeFunc(decodeEthernet)})
|
||||
LayerTypeGRE = gopacket.RegisterLayerType(18, gopacket.LayerTypeMetadata{Name: "GRE", Decoder: gopacket.DecodeFunc(decodeGRE)})
|
||||
LayerTypeICMPv4 = gopacket.RegisterLayerType(19, gopacket.LayerTypeMetadata{Name: "ICMPv4", Decoder: gopacket.DecodeFunc(decodeICMPv4)})
|
||||
LayerTypeIPv4 = gopacket.RegisterLayerType(20, gopacket.LayerTypeMetadata{Name: "IPv4", Decoder: gopacket.DecodeFunc(decodeIPv4)})
|
||||
LayerTypeIPv6 = gopacket.RegisterLayerType(21, gopacket.LayerTypeMetadata{Name: "IPv6", Decoder: gopacket.DecodeFunc(decodeIPv6)})
|
||||
LayerTypeLLC = gopacket.RegisterLayerType(22, gopacket.LayerTypeMetadata{Name: "LLC", Decoder: gopacket.DecodeFunc(decodeLLC)})
|
||||
LayerTypeSNAP = gopacket.RegisterLayerType(23, gopacket.LayerTypeMetadata{Name: "SNAP", Decoder: gopacket.DecodeFunc(decodeSNAP)})
|
||||
LayerTypeMPLS = gopacket.RegisterLayerType(24, gopacket.LayerTypeMetadata{Name: "MPLS", Decoder: gopacket.DecodeFunc(decodeMPLS)})
|
||||
LayerTypePPP = gopacket.RegisterLayerType(25, gopacket.LayerTypeMetadata{Name: "PPP", Decoder: gopacket.DecodeFunc(decodePPP)})
|
||||
LayerTypePPPoE = gopacket.RegisterLayerType(26, gopacket.LayerTypeMetadata{Name: "PPPoE", Decoder: gopacket.DecodeFunc(decodePPPoE)})
|
||||
LayerTypeRUDP = gopacket.RegisterLayerType(27, gopacket.LayerTypeMetadata{Name: "RUDP", Decoder: gopacket.DecodeFunc(decodeRUDP)})
|
||||
LayerTypeSCTP = gopacket.RegisterLayerType(28, gopacket.LayerTypeMetadata{Name: "SCTP", Decoder: gopacket.DecodeFunc(decodeSCTP)})
|
||||
LayerTypeSCTPUnknownChunkType = gopacket.RegisterLayerType(29, gopacket.LayerTypeMetadata{Name: "SCTPUnknownChunkType", Decoder: nil})
|
||||
LayerTypeSCTPData = gopacket.RegisterLayerType(30, gopacket.LayerTypeMetadata{Name: "SCTPData", Decoder: nil})
|
||||
LayerTypeSCTPInit = gopacket.RegisterLayerType(31, gopacket.LayerTypeMetadata{Name: "SCTPInit", Decoder: nil})
|
||||
LayerTypeSCTPSack = gopacket.RegisterLayerType(32, gopacket.LayerTypeMetadata{Name: "SCTPSack", Decoder: nil})
|
||||
LayerTypeSCTPHeartbeat = gopacket.RegisterLayerType(33, gopacket.LayerTypeMetadata{Name: "SCTPHeartbeat", Decoder: nil})
|
||||
LayerTypeSCTPError = gopacket.RegisterLayerType(34, gopacket.LayerTypeMetadata{Name: "SCTPError", Decoder: nil})
|
||||
LayerTypeSCTPShutdown = gopacket.RegisterLayerType(35, gopacket.LayerTypeMetadata{Name: "SCTPShutdown", Decoder: nil})
|
||||
LayerTypeSCTPShutdownAck = gopacket.RegisterLayerType(36, gopacket.LayerTypeMetadata{Name: "SCTPShutdownAck", Decoder: nil})
|
||||
LayerTypeSCTPCookieEcho = gopacket.RegisterLayerType(37, gopacket.LayerTypeMetadata{Name: "SCTPCookieEcho", Decoder: nil})
|
||||
LayerTypeSCTPEmptyLayer = gopacket.RegisterLayerType(38, gopacket.LayerTypeMetadata{Name: "SCTPEmptyLayer", Decoder: nil})
|
||||
LayerTypeSCTPInitAck = gopacket.RegisterLayerType(39, gopacket.LayerTypeMetadata{Name: "SCTPInitAck", Decoder: nil})
|
||||
LayerTypeSCTPHeartbeatAck = gopacket.RegisterLayerType(40, gopacket.LayerTypeMetadata{Name: "SCTPHeartbeatAck", Decoder: nil})
|
||||
LayerTypeSCTPAbort = gopacket.RegisterLayerType(41, gopacket.LayerTypeMetadata{Name: "SCTPAbort", Decoder: nil})
|
||||
LayerTypeSCTPShutdownComplete = gopacket.RegisterLayerType(42, gopacket.LayerTypeMetadata{Name: "SCTPShutdownComplete", Decoder: nil})
|
||||
LayerTypeSCTPCookieAck = gopacket.RegisterLayerType(43, gopacket.LayerTypeMetadata{Name: "SCTPCookieAck", Decoder: nil})
|
||||
LayerTypeTCP = gopacket.RegisterLayerType(44, gopacket.LayerTypeMetadata{Name: "TCP", Decoder: gopacket.DecodeFunc(decodeTCP)})
|
||||
LayerTypeUDP = gopacket.RegisterLayerType(45, gopacket.LayerTypeMetadata{Name: "UDP", Decoder: gopacket.DecodeFunc(decodeUDP)})
|
||||
LayerTypeIPv6HopByHop = gopacket.RegisterLayerType(46, gopacket.LayerTypeMetadata{Name: "IPv6HopByHop", Decoder: gopacket.DecodeFunc(decodeIPv6HopByHop)})
|
||||
LayerTypeIPv6Routing = gopacket.RegisterLayerType(47, gopacket.LayerTypeMetadata{Name: "IPv6Routing", Decoder: gopacket.DecodeFunc(decodeIPv6Routing)})
|
||||
LayerTypeIPv6Fragment = gopacket.RegisterLayerType(48, gopacket.LayerTypeMetadata{Name: "IPv6Fragment", Decoder: gopacket.DecodeFunc(decodeIPv6Fragment)})
|
||||
LayerTypeIPv6Destination = gopacket.RegisterLayerType(49, gopacket.LayerTypeMetadata{Name: "IPv6Destination", Decoder: gopacket.DecodeFunc(decodeIPv6Destination)})
|
||||
LayerTypeIPSecAH = gopacket.RegisterLayerType(50, gopacket.LayerTypeMetadata{Name: "IPSecAH", Decoder: gopacket.DecodeFunc(decodeIPSecAH)})
|
||||
LayerTypeIPSecESP = gopacket.RegisterLayerType(51, gopacket.LayerTypeMetadata{Name: "IPSecESP", Decoder: gopacket.DecodeFunc(decodeIPSecESP)})
|
||||
LayerTypeUDPLite = gopacket.RegisterLayerType(52, gopacket.LayerTypeMetadata{Name: "UDPLite", Decoder: gopacket.DecodeFunc(decodeUDPLite)})
|
||||
LayerTypeFDDI = gopacket.RegisterLayerType(53, gopacket.LayerTypeMetadata{Name: "FDDI", Decoder: gopacket.DecodeFunc(decodeFDDI)})
|
||||
LayerTypeLoopback = gopacket.RegisterLayerType(54, gopacket.LayerTypeMetadata{Name: "Loopback", Decoder: gopacket.DecodeFunc(decodeLoopback)})
|
||||
LayerTypeEAP = gopacket.RegisterLayerType(55, gopacket.LayerTypeMetadata{Name: "EAP", Decoder: gopacket.DecodeFunc(decodeEAP)})
|
||||
LayerTypeEAPOL = gopacket.RegisterLayerType(56, gopacket.LayerTypeMetadata{Name: "EAPOL", Decoder: gopacket.DecodeFunc(decodeEAPOL)})
|
||||
LayerTypeICMPv6 = gopacket.RegisterLayerType(57, gopacket.LayerTypeMetadata{Name: "ICMPv6", Decoder: gopacket.DecodeFunc(decodeICMPv6)})
|
||||
LayerTypeLinkLayerDiscovery = gopacket.RegisterLayerType(58, gopacket.LayerTypeMetadata{Name: "LinkLayerDiscovery", Decoder: gopacket.DecodeFunc(decodeLinkLayerDiscovery)})
|
||||
LayerTypeCiscoDiscoveryInfo = gopacket.RegisterLayerType(59, gopacket.LayerTypeMetadata{Name: "CiscoDiscoveryInfo", Decoder: gopacket.DecodeFunc(decodeCiscoDiscoveryInfo)})
|
||||
LayerTypeLinkLayerDiscoveryInfo = gopacket.RegisterLayerType(60, gopacket.LayerTypeMetadata{Name: "LinkLayerDiscoveryInfo", Decoder: nil})
|
||||
LayerTypeNortelDiscovery = gopacket.RegisterLayerType(61, gopacket.LayerTypeMetadata{Name: "NortelDiscovery", Decoder: gopacket.DecodeFunc(decodeNortelDiscovery)})
|
||||
LayerTypeIGMP = gopacket.RegisterLayerType(62, gopacket.LayerTypeMetadata{Name: "IGMP", Decoder: gopacket.DecodeFunc(decodeIGMP)})
|
||||
LayerTypePFLog = gopacket.RegisterLayerType(63, gopacket.LayerTypeMetadata{Name: "PFLog", Decoder: gopacket.DecodeFunc(decodePFLog)})
|
||||
LayerTypeRadioTap = gopacket.RegisterLayerType(64, gopacket.LayerTypeMetadata{Name: "RadioTap", Decoder: gopacket.DecodeFunc(decodeRadioTap)})
|
||||
LayerTypeDot11 = gopacket.RegisterLayerType(65, gopacket.LayerTypeMetadata{Name: "Dot11", Decoder: gopacket.DecodeFunc(decodeDot11)})
|
||||
LayerTypeDot11Ctrl = gopacket.RegisterLayerType(66, gopacket.LayerTypeMetadata{Name: "Dot11Ctrl", Decoder: gopacket.DecodeFunc(decodeDot11Ctrl)})
|
||||
LayerTypeDot11Data = gopacket.RegisterLayerType(67, gopacket.LayerTypeMetadata{Name: "Dot11Data", Decoder: gopacket.DecodeFunc(decodeDot11Data)})
|
||||
LayerTypeDot11DataCFAck = gopacket.RegisterLayerType(68, gopacket.LayerTypeMetadata{Name: "Dot11DataCFAck", Decoder: gopacket.DecodeFunc(decodeDot11DataCFAck)})
|
||||
LayerTypeDot11DataCFPoll = gopacket.RegisterLayerType(69, gopacket.LayerTypeMetadata{Name: "Dot11DataCFPoll", Decoder: gopacket.DecodeFunc(decodeDot11DataCFPoll)})
|
||||
LayerTypeDot11DataCFAckPoll = gopacket.RegisterLayerType(70, gopacket.LayerTypeMetadata{Name: "Dot11DataCFAckPoll", Decoder: gopacket.DecodeFunc(decodeDot11DataCFAckPoll)})
|
||||
LayerTypeDot11DataNull = gopacket.RegisterLayerType(71, gopacket.LayerTypeMetadata{Name: "Dot11DataNull", Decoder: gopacket.DecodeFunc(decodeDot11DataNull)})
|
||||
LayerTypeDot11DataCFAckNoData = gopacket.RegisterLayerType(72, gopacket.LayerTypeMetadata{Name: "Dot11DataCFAck", Decoder: gopacket.DecodeFunc(decodeDot11DataCFAck)})
|
||||
LayerTypeDot11DataCFPollNoData = gopacket.RegisterLayerType(73, gopacket.LayerTypeMetadata{Name: "Dot11DataCFPoll", Decoder: gopacket.DecodeFunc(decodeDot11DataCFPoll)})
|
||||
LayerTypeDot11DataCFAckPollNoData = gopacket.RegisterLayerType(74, gopacket.LayerTypeMetadata{Name: "Dot11DataCFAckPoll", Decoder: gopacket.DecodeFunc(decodeDot11DataCFAckPoll)})
|
||||
LayerTypeDot11DataQOSData = gopacket.RegisterLayerType(75, gopacket.LayerTypeMetadata{Name: "Dot11DataQOSData", Decoder: gopacket.DecodeFunc(decodeDot11DataQOSData)})
|
||||
LayerTypeDot11DataQOSDataCFAck = gopacket.RegisterLayerType(76, gopacket.LayerTypeMetadata{Name: "Dot11DataQOSDataCFAck", Decoder: gopacket.DecodeFunc(decodeDot11DataQOSDataCFAck)})
|
||||
LayerTypeDot11DataQOSDataCFPoll = gopacket.RegisterLayerType(77, gopacket.LayerTypeMetadata{Name: "Dot11DataQOSDataCFPoll", Decoder: gopacket.DecodeFunc(decodeDot11DataQOSDataCFPoll)})
|
||||
LayerTypeDot11DataQOSDataCFAckPoll = gopacket.RegisterLayerType(78, gopacket.LayerTypeMetadata{Name: "Dot11DataQOSDataCFAckPoll", Decoder: gopacket.DecodeFunc(decodeDot11DataQOSDataCFAckPoll)})
|
||||
LayerTypeDot11DataQOSNull = gopacket.RegisterLayerType(79, gopacket.LayerTypeMetadata{Name: "Dot11DataQOSNull", Decoder: gopacket.DecodeFunc(decodeDot11DataQOSNull)})
|
||||
LayerTypeDot11DataQOSCFPollNoData = gopacket.RegisterLayerType(80, gopacket.LayerTypeMetadata{Name: "Dot11DataQOSCFPoll", Decoder: gopacket.DecodeFunc(decodeDot11DataQOSCFPollNoData)})
|
||||
LayerTypeDot11DataQOSCFAckPollNoData = gopacket.RegisterLayerType(81, gopacket.LayerTypeMetadata{Name: "Dot11DataQOSCFAckPoll", Decoder: gopacket.DecodeFunc(decodeDot11DataQOSCFAckPollNoData)})
|
||||
LayerTypeDot11InformationElement = gopacket.RegisterLayerType(82, gopacket.LayerTypeMetadata{Name: "Dot11InformationElement", Decoder: gopacket.DecodeFunc(decodeDot11InformationElement)})
|
||||
LayerTypeDot11CtrlCTS = gopacket.RegisterLayerType(83, gopacket.LayerTypeMetadata{Name: "Dot11CtrlCTS", Decoder: gopacket.DecodeFunc(decodeDot11CtrlCTS)})
|
||||
LayerTypeDot11CtrlRTS = gopacket.RegisterLayerType(84, gopacket.LayerTypeMetadata{Name: "Dot11CtrlRTS", Decoder: gopacket.DecodeFunc(decodeDot11CtrlRTS)})
|
||||
LayerTypeDot11CtrlBlockAckReq = gopacket.RegisterLayerType(85, gopacket.LayerTypeMetadata{Name: "Dot11CtrlBlockAckReq", Decoder: gopacket.DecodeFunc(decodeDot11CtrlBlockAckReq)})
|
||||
LayerTypeDot11CtrlBlockAck = gopacket.RegisterLayerType(86, gopacket.LayerTypeMetadata{Name: "Dot11CtrlBlockAck", Decoder: gopacket.DecodeFunc(decodeDot11CtrlBlockAck)})
|
||||
LayerTypeDot11CtrlPowersavePoll = gopacket.RegisterLayerType(87, gopacket.LayerTypeMetadata{Name: "Dot11CtrlPowersavePoll", Decoder: gopacket.DecodeFunc(decodeDot11CtrlPowersavePoll)})
|
||||
LayerTypeDot11CtrlAck = gopacket.RegisterLayerType(88, gopacket.LayerTypeMetadata{Name: "Dot11CtrlAck", Decoder: gopacket.DecodeFunc(decodeDot11CtrlAck)})
|
||||
LayerTypeDot11CtrlCFEnd = gopacket.RegisterLayerType(89, gopacket.LayerTypeMetadata{Name: "Dot11CtrlCFEnd", Decoder: gopacket.DecodeFunc(decodeDot11CtrlCFEnd)})
|
||||
LayerTypeDot11CtrlCFEndAck = gopacket.RegisterLayerType(90, gopacket.LayerTypeMetadata{Name: "Dot11CtrlCFEndAck", Decoder: gopacket.DecodeFunc(decodeDot11CtrlCFEndAck)})
|
||||
LayerTypeDot11MgmtAssociationReq = gopacket.RegisterLayerType(91, gopacket.LayerTypeMetadata{Name: "Dot11MgmtAssociationReq", Decoder: gopacket.DecodeFunc(decodeDot11MgmtAssociationReq)})
|
||||
LayerTypeDot11MgmtAssociationResp = gopacket.RegisterLayerType(92, gopacket.LayerTypeMetadata{Name: "Dot11MgmtAssociationResp", Decoder: gopacket.DecodeFunc(decodeDot11MgmtAssociationResp)})
|
||||
LayerTypeDot11MgmtReassociationReq = gopacket.RegisterLayerType(93, gopacket.LayerTypeMetadata{Name: "Dot11MgmtReassociationReq", Decoder: gopacket.DecodeFunc(decodeDot11MgmtReassociationReq)})
|
||||
LayerTypeDot11MgmtReassociationResp = gopacket.RegisterLayerType(94, gopacket.LayerTypeMetadata{Name: "Dot11MgmtReassociationResp", Decoder: gopacket.DecodeFunc(decodeDot11MgmtReassociationResp)})
|
||||
LayerTypeDot11MgmtProbeReq = gopacket.RegisterLayerType(95, gopacket.LayerTypeMetadata{Name: "Dot11MgmtProbeReq", Decoder: gopacket.DecodeFunc(decodeDot11MgmtProbeReq)})
|
||||
LayerTypeDot11MgmtProbeResp = gopacket.RegisterLayerType(96, gopacket.LayerTypeMetadata{Name: "Dot11MgmtProbeResp", Decoder: gopacket.DecodeFunc(decodeDot11MgmtProbeResp)})
|
||||
LayerTypeDot11MgmtMeasurementPilot = gopacket.RegisterLayerType(97, gopacket.LayerTypeMetadata{Name: "Dot11MgmtMeasurementPilot", Decoder: gopacket.DecodeFunc(decodeDot11MgmtMeasurementPilot)})
|
||||
LayerTypeDot11MgmtBeacon = gopacket.RegisterLayerType(98, gopacket.LayerTypeMetadata{Name: "Dot11MgmtBeacon", Decoder: gopacket.DecodeFunc(decodeDot11MgmtBeacon)})
|
||||
LayerTypeDot11MgmtATIM = gopacket.RegisterLayerType(99, gopacket.LayerTypeMetadata{Name: "Dot11MgmtATIM", Decoder: gopacket.DecodeFunc(decodeDot11MgmtATIM)})
|
||||
LayerTypeDot11MgmtDisassociation = gopacket.RegisterLayerType(100, gopacket.LayerTypeMetadata{Name: "Dot11MgmtDisassociation", Decoder: gopacket.DecodeFunc(decodeDot11MgmtDisassociation)})
|
||||
LayerTypeDot11MgmtAuthentication = gopacket.RegisterLayerType(101, gopacket.LayerTypeMetadata{Name: "Dot11MgmtAuthentication", Decoder: gopacket.DecodeFunc(decodeDot11MgmtAuthentication)})
|
||||
LayerTypeDot11MgmtDeauthentication = gopacket.RegisterLayerType(102, gopacket.LayerTypeMetadata{Name: "Dot11MgmtDeauthentication", Decoder: gopacket.DecodeFunc(decodeDot11MgmtDeauthentication)})
|
||||
LayerTypeDot11MgmtAction = gopacket.RegisterLayerType(103, gopacket.LayerTypeMetadata{Name: "Dot11MgmtAction", Decoder: gopacket.DecodeFunc(decodeDot11MgmtAction)})
|
||||
LayerTypeDot11MgmtActionNoAck = gopacket.RegisterLayerType(104, gopacket.LayerTypeMetadata{Name: "Dot11MgmtActionNoAck", Decoder: gopacket.DecodeFunc(decodeDot11MgmtActionNoAck)})
|
||||
LayerTypeDot11MgmtArubaWLAN = gopacket.RegisterLayerType(105, gopacket.LayerTypeMetadata{Name: "Dot11MgmtArubaWLAN", Decoder: gopacket.DecodeFunc(decodeDot11MgmtArubaWLAN)})
|
||||
LayerTypeDot11WEP = gopacket.RegisterLayerType(106, gopacket.LayerTypeMetadata{Name: "Dot11WEP", Decoder: gopacket.DecodeFunc(decodeDot11WEP)})
|
||||
LayerTypeDNS = gopacket.RegisterLayerType(107, gopacket.LayerTypeMetadata{Name: "DNS", Decoder: gopacket.DecodeFunc(decodeDNS)})
|
||||
LayerTypeUSB = gopacket.RegisterLayerType(108, gopacket.LayerTypeMetadata{Name: "USB", Decoder: gopacket.DecodeFunc(decodeUSB)})
|
||||
LayerTypeUSBRequestBlockSetup = gopacket.RegisterLayerType(109, gopacket.LayerTypeMetadata{Name: "USBRequestBlockSetup", Decoder: gopacket.DecodeFunc(decodeUSBRequestBlockSetup)})
|
||||
LayerTypeUSBControl = gopacket.RegisterLayerType(110, gopacket.LayerTypeMetadata{Name: "USBControl", Decoder: gopacket.DecodeFunc(decodeUSBControl)})
|
||||
LayerTypeUSBInterrupt = gopacket.RegisterLayerType(111, gopacket.LayerTypeMetadata{Name: "USBInterrupt", Decoder: gopacket.DecodeFunc(decodeUSBInterrupt)})
|
||||
LayerTypeUSBBulk = gopacket.RegisterLayerType(112, gopacket.LayerTypeMetadata{Name: "USBBulk", Decoder: gopacket.DecodeFunc(decodeUSBBulk)})
|
||||
LayerTypeLinuxSLL = gopacket.RegisterLayerType(113, gopacket.LayerTypeMetadata{Name: "Linux SLL", Decoder: gopacket.DecodeFunc(decodeLinuxSLL)})
|
||||
LayerTypeSFlow = gopacket.RegisterLayerType(114, gopacket.LayerTypeMetadata{Name: "SFlow", Decoder: gopacket.DecodeFunc(decodeSFlow)})
|
||||
LayerTypePrismHeader = gopacket.RegisterLayerType(115, gopacket.LayerTypeMetadata{Name: "Prism monitor mode header", Decoder: gopacket.DecodeFunc(decodePrismHeader)})
|
||||
LayerTypeVXLAN = gopacket.RegisterLayerType(116, gopacket.LayerTypeMetadata{Name: "VXLAN", Decoder: gopacket.DecodeFunc(decodeVXLAN)})
|
||||
LayerTypeNTP = gopacket.RegisterLayerType(117, gopacket.LayerTypeMetadata{Name: "NTP", Decoder: gopacket.DecodeFunc(decodeNTP)})
|
||||
LayerTypeDHCPv4 = gopacket.RegisterLayerType(118, gopacket.LayerTypeMetadata{Name: "DHCPv4", Decoder: gopacket.DecodeFunc(decodeDHCPv4)})
|
||||
LayerTypeVRRP = gopacket.RegisterLayerType(119, gopacket.LayerTypeMetadata{Name: "VRRP", Decoder: gopacket.DecodeFunc(decodeVRRP)})
|
||||
LayerTypeGeneve = gopacket.RegisterLayerType(120, gopacket.LayerTypeMetadata{Name: "Geneve", Decoder: gopacket.DecodeFunc(decodeGeneve)})
|
||||
LayerTypeSTP = gopacket.RegisterLayerType(121, gopacket.LayerTypeMetadata{Name: "STP", Decoder: gopacket.DecodeFunc(decodeSTP)})
|
||||
LayerTypeARP = gopacket.RegisterLayerType(10, gopacket.LayerTypeMetadata{Name: "ARP", Decoder: gopacket.DecodeFunc(decodeARP)})
|
||||
LayerTypeCiscoDiscovery = gopacket.RegisterLayerType(11, gopacket.LayerTypeMetadata{Name: "CiscoDiscovery", Decoder: gopacket.DecodeFunc(decodeCiscoDiscovery)})
|
||||
LayerTypeEthernetCTP = gopacket.RegisterLayerType(12, gopacket.LayerTypeMetadata{Name: "EthernetCTP", Decoder: gopacket.DecodeFunc(decodeEthernetCTP)})
|
||||
LayerTypeEthernetCTPForwardData = gopacket.RegisterLayerType(13, gopacket.LayerTypeMetadata{Name: "EthernetCTPForwardData", Decoder: nil})
|
||||
LayerTypeEthernetCTPReply = gopacket.RegisterLayerType(14, gopacket.LayerTypeMetadata{Name: "EthernetCTPReply", Decoder: nil})
|
||||
LayerTypeDot1Q = gopacket.RegisterLayerType(15, gopacket.LayerTypeMetadata{Name: "Dot1Q", Decoder: gopacket.DecodeFunc(decodeDot1Q)})
|
||||
LayerTypeEtherIP = gopacket.RegisterLayerType(16, gopacket.LayerTypeMetadata{Name: "EtherIP", Decoder: gopacket.DecodeFunc(decodeEtherIP)})
|
||||
LayerTypeEthernet = gopacket.RegisterLayerType(17, gopacket.LayerTypeMetadata{Name: "Ethernet", Decoder: gopacket.DecodeFunc(decodeEthernet)})
|
||||
LayerTypeGRE = gopacket.RegisterLayerType(18, gopacket.LayerTypeMetadata{Name: "GRE", Decoder: gopacket.DecodeFunc(decodeGRE)})
|
||||
LayerTypeICMPv4 = gopacket.RegisterLayerType(19, gopacket.LayerTypeMetadata{Name: "ICMPv4", Decoder: gopacket.DecodeFunc(decodeICMPv4)})
|
||||
LayerTypeIPv4 = gopacket.RegisterLayerType(20, gopacket.LayerTypeMetadata{Name: "IPv4", Decoder: gopacket.DecodeFunc(decodeIPv4)})
|
||||
LayerTypeIPv6 = gopacket.RegisterLayerType(21, gopacket.LayerTypeMetadata{Name: "IPv6", Decoder: gopacket.DecodeFunc(decodeIPv6)})
|
||||
LayerTypeLLC = gopacket.RegisterLayerType(22, gopacket.LayerTypeMetadata{Name: "LLC", Decoder: gopacket.DecodeFunc(decodeLLC)})
|
||||
LayerTypeSNAP = gopacket.RegisterLayerType(23, gopacket.LayerTypeMetadata{Name: "SNAP", Decoder: gopacket.DecodeFunc(decodeSNAP)})
|
||||
LayerTypeMPLS = gopacket.RegisterLayerType(24, gopacket.LayerTypeMetadata{Name: "MPLS", Decoder: gopacket.DecodeFunc(decodeMPLS)})
|
||||
LayerTypePPP = gopacket.RegisterLayerType(25, gopacket.LayerTypeMetadata{Name: "PPP", Decoder: gopacket.DecodeFunc(decodePPP)})
|
||||
LayerTypePPPoE = gopacket.RegisterLayerType(26, gopacket.LayerTypeMetadata{Name: "PPPoE", Decoder: gopacket.DecodeFunc(decodePPPoE)})
|
||||
LayerTypeRUDP = gopacket.RegisterLayerType(27, gopacket.LayerTypeMetadata{Name: "RUDP", Decoder: gopacket.DecodeFunc(decodeRUDP)})
|
||||
LayerTypeSCTP = gopacket.RegisterLayerType(28, gopacket.LayerTypeMetadata{Name: "SCTP", Decoder: gopacket.DecodeFunc(decodeSCTP)})
|
||||
LayerTypeSCTPUnknownChunkType = gopacket.RegisterLayerType(29, gopacket.LayerTypeMetadata{Name: "SCTPUnknownChunkType", Decoder: nil})
|
||||
LayerTypeSCTPData = gopacket.RegisterLayerType(30, gopacket.LayerTypeMetadata{Name: "SCTPData", Decoder: nil})
|
||||
LayerTypeSCTPInit = gopacket.RegisterLayerType(31, gopacket.LayerTypeMetadata{Name: "SCTPInit", Decoder: nil})
|
||||
LayerTypeSCTPSack = gopacket.RegisterLayerType(32, gopacket.LayerTypeMetadata{Name: "SCTPSack", Decoder: nil})
|
||||
LayerTypeSCTPHeartbeat = gopacket.RegisterLayerType(33, gopacket.LayerTypeMetadata{Name: "SCTPHeartbeat", Decoder: nil})
|
||||
LayerTypeSCTPError = gopacket.RegisterLayerType(34, gopacket.LayerTypeMetadata{Name: "SCTPError", Decoder: nil})
|
||||
LayerTypeSCTPShutdown = gopacket.RegisterLayerType(35, gopacket.LayerTypeMetadata{Name: "SCTPShutdown", Decoder: nil})
|
||||
LayerTypeSCTPShutdownAck = gopacket.RegisterLayerType(36, gopacket.LayerTypeMetadata{Name: "SCTPShutdownAck", Decoder: nil})
|
||||
LayerTypeSCTPCookieEcho = gopacket.RegisterLayerType(37, gopacket.LayerTypeMetadata{Name: "SCTPCookieEcho", Decoder: nil})
|
||||
LayerTypeSCTPEmptyLayer = gopacket.RegisterLayerType(38, gopacket.LayerTypeMetadata{Name: "SCTPEmptyLayer", Decoder: nil})
|
||||
LayerTypeSCTPInitAck = gopacket.RegisterLayerType(39, gopacket.LayerTypeMetadata{Name: "SCTPInitAck", Decoder: nil})
|
||||
LayerTypeSCTPHeartbeatAck = gopacket.RegisterLayerType(40, gopacket.LayerTypeMetadata{Name: "SCTPHeartbeatAck", Decoder: nil})
|
||||
LayerTypeSCTPAbort = gopacket.RegisterLayerType(41, gopacket.LayerTypeMetadata{Name: "SCTPAbort", Decoder: nil})
|
||||
LayerTypeSCTPShutdownComplete = gopacket.RegisterLayerType(42, gopacket.LayerTypeMetadata{Name: "SCTPShutdownComplete", Decoder: nil})
|
||||
LayerTypeSCTPCookieAck = gopacket.RegisterLayerType(43, gopacket.LayerTypeMetadata{Name: "SCTPCookieAck", Decoder: nil})
|
||||
LayerTypeTCP = gopacket.RegisterLayerType(44, gopacket.LayerTypeMetadata{Name: "TCP", Decoder: gopacket.DecodeFunc(decodeTCP)})
|
||||
LayerTypeUDP = gopacket.RegisterLayerType(45, gopacket.LayerTypeMetadata{Name: "UDP", Decoder: gopacket.DecodeFunc(decodeUDP)})
|
||||
LayerTypeIPv6HopByHop = gopacket.RegisterLayerType(46, gopacket.LayerTypeMetadata{Name: "IPv6HopByHop", Decoder: gopacket.DecodeFunc(decodeIPv6HopByHop)})
|
||||
LayerTypeIPv6Routing = gopacket.RegisterLayerType(47, gopacket.LayerTypeMetadata{Name: "IPv6Routing", Decoder: gopacket.DecodeFunc(decodeIPv6Routing)})
|
||||
LayerTypeIPv6Fragment = gopacket.RegisterLayerType(48, gopacket.LayerTypeMetadata{Name: "IPv6Fragment", Decoder: gopacket.DecodeFunc(decodeIPv6Fragment)})
|
||||
LayerTypeIPv6Destination = gopacket.RegisterLayerType(49, gopacket.LayerTypeMetadata{Name: "IPv6Destination", Decoder: gopacket.DecodeFunc(decodeIPv6Destination)})
|
||||
LayerTypeIPSecAH = gopacket.RegisterLayerType(50, gopacket.LayerTypeMetadata{Name: "IPSecAH", Decoder: gopacket.DecodeFunc(decodeIPSecAH)})
|
||||
LayerTypeIPSecESP = gopacket.RegisterLayerType(51, gopacket.LayerTypeMetadata{Name: "IPSecESP", Decoder: gopacket.DecodeFunc(decodeIPSecESP)})
|
||||
LayerTypeUDPLite = gopacket.RegisterLayerType(52, gopacket.LayerTypeMetadata{Name: "UDPLite", Decoder: gopacket.DecodeFunc(decodeUDPLite)})
|
||||
LayerTypeFDDI = gopacket.RegisterLayerType(53, gopacket.LayerTypeMetadata{Name: "FDDI", Decoder: gopacket.DecodeFunc(decodeFDDI)})
|
||||
LayerTypeLoopback = gopacket.RegisterLayerType(54, gopacket.LayerTypeMetadata{Name: "Loopback", Decoder: gopacket.DecodeFunc(decodeLoopback)})
|
||||
LayerTypeEAP = gopacket.RegisterLayerType(55, gopacket.LayerTypeMetadata{Name: "EAP", Decoder: gopacket.DecodeFunc(decodeEAP)})
|
||||
LayerTypeEAPOL = gopacket.RegisterLayerType(56, gopacket.LayerTypeMetadata{Name: "EAPOL", Decoder: gopacket.DecodeFunc(decodeEAPOL)})
|
||||
LayerTypeICMPv6 = gopacket.RegisterLayerType(57, gopacket.LayerTypeMetadata{Name: "ICMPv6", Decoder: gopacket.DecodeFunc(decodeICMPv6)})
|
||||
LayerTypeLinkLayerDiscovery = gopacket.RegisterLayerType(58, gopacket.LayerTypeMetadata{Name: "LinkLayerDiscovery", Decoder: gopacket.DecodeFunc(decodeLinkLayerDiscovery)})
|
||||
LayerTypeCiscoDiscoveryInfo = gopacket.RegisterLayerType(59, gopacket.LayerTypeMetadata{Name: "CiscoDiscoveryInfo", Decoder: gopacket.DecodeFunc(decodeCiscoDiscoveryInfo)})
|
||||
LayerTypeLinkLayerDiscoveryInfo = gopacket.RegisterLayerType(60, gopacket.LayerTypeMetadata{Name: "LinkLayerDiscoveryInfo", Decoder: nil})
|
||||
LayerTypeNortelDiscovery = gopacket.RegisterLayerType(61, gopacket.LayerTypeMetadata{Name: "NortelDiscovery", Decoder: gopacket.DecodeFunc(decodeNortelDiscovery)})
|
||||
LayerTypeIGMP = gopacket.RegisterLayerType(62, gopacket.LayerTypeMetadata{Name: "IGMP", Decoder: gopacket.DecodeFunc(decodeIGMP)})
|
||||
LayerTypePFLog = gopacket.RegisterLayerType(63, gopacket.LayerTypeMetadata{Name: "PFLog", Decoder: gopacket.DecodeFunc(decodePFLog)})
|
||||
LayerTypeRadioTap = gopacket.RegisterLayerType(64, gopacket.LayerTypeMetadata{Name: "RadioTap", Decoder: gopacket.DecodeFunc(decodeRadioTap)})
|
||||
LayerTypeDot11 = gopacket.RegisterLayerType(65, gopacket.LayerTypeMetadata{Name: "Dot11", Decoder: gopacket.DecodeFunc(decodeDot11)})
|
||||
LayerTypeDot11Ctrl = gopacket.RegisterLayerType(66, gopacket.LayerTypeMetadata{Name: "Dot11Ctrl", Decoder: gopacket.DecodeFunc(decodeDot11Ctrl)})
|
||||
LayerTypeDot11Data = gopacket.RegisterLayerType(67, gopacket.LayerTypeMetadata{Name: "Dot11Data", Decoder: gopacket.DecodeFunc(decodeDot11Data)})
|
||||
LayerTypeDot11DataCFAck = gopacket.RegisterLayerType(68, gopacket.LayerTypeMetadata{Name: "Dot11DataCFAck", Decoder: gopacket.DecodeFunc(decodeDot11DataCFAck)})
|
||||
LayerTypeDot11DataCFPoll = gopacket.RegisterLayerType(69, gopacket.LayerTypeMetadata{Name: "Dot11DataCFPoll", Decoder: gopacket.DecodeFunc(decodeDot11DataCFPoll)})
|
||||
LayerTypeDot11DataCFAckPoll = gopacket.RegisterLayerType(70, gopacket.LayerTypeMetadata{Name: "Dot11DataCFAckPoll", Decoder: gopacket.DecodeFunc(decodeDot11DataCFAckPoll)})
|
||||
LayerTypeDot11DataNull = gopacket.RegisterLayerType(71, gopacket.LayerTypeMetadata{Name: "Dot11DataNull", Decoder: gopacket.DecodeFunc(decodeDot11DataNull)})
|
||||
LayerTypeDot11DataCFAckNoData = gopacket.RegisterLayerType(72, gopacket.LayerTypeMetadata{Name: "Dot11DataCFAck", Decoder: gopacket.DecodeFunc(decodeDot11DataCFAck)})
|
||||
LayerTypeDot11DataCFPollNoData = gopacket.RegisterLayerType(73, gopacket.LayerTypeMetadata{Name: "Dot11DataCFPoll", Decoder: gopacket.DecodeFunc(decodeDot11DataCFPoll)})
|
||||
LayerTypeDot11DataCFAckPollNoData = gopacket.RegisterLayerType(74, gopacket.LayerTypeMetadata{Name: "Dot11DataCFAckPoll", Decoder: gopacket.DecodeFunc(decodeDot11DataCFAckPoll)})
|
||||
LayerTypeDot11DataQOSData = gopacket.RegisterLayerType(75, gopacket.LayerTypeMetadata{Name: "Dot11DataQOSData", Decoder: gopacket.DecodeFunc(decodeDot11DataQOSData)})
|
||||
LayerTypeDot11DataQOSDataCFAck = gopacket.RegisterLayerType(76, gopacket.LayerTypeMetadata{Name: "Dot11DataQOSDataCFAck", Decoder: gopacket.DecodeFunc(decodeDot11DataQOSDataCFAck)})
|
||||
LayerTypeDot11DataQOSDataCFPoll = gopacket.RegisterLayerType(77, gopacket.LayerTypeMetadata{Name: "Dot11DataQOSDataCFPoll", Decoder: gopacket.DecodeFunc(decodeDot11DataQOSDataCFPoll)})
|
||||
LayerTypeDot11DataQOSDataCFAckPoll = gopacket.RegisterLayerType(78, gopacket.LayerTypeMetadata{Name: "Dot11DataQOSDataCFAckPoll", Decoder: gopacket.DecodeFunc(decodeDot11DataQOSDataCFAckPoll)})
|
||||
LayerTypeDot11DataQOSNull = gopacket.RegisterLayerType(79, gopacket.LayerTypeMetadata{Name: "Dot11DataQOSNull", Decoder: gopacket.DecodeFunc(decodeDot11DataQOSNull)})
|
||||
LayerTypeDot11DataQOSCFPollNoData = gopacket.RegisterLayerType(80, gopacket.LayerTypeMetadata{Name: "Dot11DataQOSCFPoll", Decoder: gopacket.DecodeFunc(decodeDot11DataQOSCFPollNoData)})
|
||||
LayerTypeDot11DataQOSCFAckPollNoData = gopacket.RegisterLayerType(81, gopacket.LayerTypeMetadata{Name: "Dot11DataQOSCFAckPoll", Decoder: gopacket.DecodeFunc(decodeDot11DataQOSCFAckPollNoData)})
|
||||
LayerTypeDot11InformationElement = gopacket.RegisterLayerType(82, gopacket.LayerTypeMetadata{Name: "Dot11InformationElement", Decoder: gopacket.DecodeFunc(decodeDot11InformationElement)})
|
||||
LayerTypeDot11CtrlCTS = gopacket.RegisterLayerType(83, gopacket.LayerTypeMetadata{Name: "Dot11CtrlCTS", Decoder: gopacket.DecodeFunc(decodeDot11CtrlCTS)})
|
||||
LayerTypeDot11CtrlRTS = gopacket.RegisterLayerType(84, gopacket.LayerTypeMetadata{Name: "Dot11CtrlRTS", Decoder: gopacket.DecodeFunc(decodeDot11CtrlRTS)})
|
||||
LayerTypeDot11CtrlBlockAckReq = gopacket.RegisterLayerType(85, gopacket.LayerTypeMetadata{Name: "Dot11CtrlBlockAckReq", Decoder: gopacket.DecodeFunc(decodeDot11CtrlBlockAckReq)})
|
||||
LayerTypeDot11CtrlBlockAck = gopacket.RegisterLayerType(86, gopacket.LayerTypeMetadata{Name: "Dot11CtrlBlockAck", Decoder: gopacket.DecodeFunc(decodeDot11CtrlBlockAck)})
|
||||
LayerTypeDot11CtrlPowersavePoll = gopacket.RegisterLayerType(87, gopacket.LayerTypeMetadata{Name: "Dot11CtrlPowersavePoll", Decoder: gopacket.DecodeFunc(decodeDot11CtrlPowersavePoll)})
|
||||
LayerTypeDot11CtrlAck = gopacket.RegisterLayerType(88, gopacket.LayerTypeMetadata{Name: "Dot11CtrlAck", Decoder: gopacket.DecodeFunc(decodeDot11CtrlAck)})
|
||||
LayerTypeDot11CtrlCFEnd = gopacket.RegisterLayerType(89, gopacket.LayerTypeMetadata{Name: "Dot11CtrlCFEnd", Decoder: gopacket.DecodeFunc(decodeDot11CtrlCFEnd)})
|
||||
LayerTypeDot11CtrlCFEndAck = gopacket.RegisterLayerType(90, gopacket.LayerTypeMetadata{Name: "Dot11CtrlCFEndAck", Decoder: gopacket.DecodeFunc(decodeDot11CtrlCFEndAck)})
|
||||
LayerTypeDot11MgmtAssociationReq = gopacket.RegisterLayerType(91, gopacket.LayerTypeMetadata{Name: "Dot11MgmtAssociationReq", Decoder: gopacket.DecodeFunc(decodeDot11MgmtAssociationReq)})
|
||||
LayerTypeDot11MgmtAssociationResp = gopacket.RegisterLayerType(92, gopacket.LayerTypeMetadata{Name: "Dot11MgmtAssociationResp", Decoder: gopacket.DecodeFunc(decodeDot11MgmtAssociationResp)})
|
||||
LayerTypeDot11MgmtReassociationReq = gopacket.RegisterLayerType(93, gopacket.LayerTypeMetadata{Name: "Dot11MgmtReassociationReq", Decoder: gopacket.DecodeFunc(decodeDot11MgmtReassociationReq)})
|
||||
LayerTypeDot11MgmtReassociationResp = gopacket.RegisterLayerType(94, gopacket.LayerTypeMetadata{Name: "Dot11MgmtReassociationResp", Decoder: gopacket.DecodeFunc(decodeDot11MgmtReassociationResp)})
|
||||
LayerTypeDot11MgmtProbeReq = gopacket.RegisterLayerType(95, gopacket.LayerTypeMetadata{Name: "Dot11MgmtProbeReq", Decoder: gopacket.DecodeFunc(decodeDot11MgmtProbeReq)})
|
||||
LayerTypeDot11MgmtProbeResp = gopacket.RegisterLayerType(96, gopacket.LayerTypeMetadata{Name: "Dot11MgmtProbeResp", Decoder: gopacket.DecodeFunc(decodeDot11MgmtProbeResp)})
|
||||
LayerTypeDot11MgmtMeasurementPilot = gopacket.RegisterLayerType(97, gopacket.LayerTypeMetadata{Name: "Dot11MgmtMeasurementPilot", Decoder: gopacket.DecodeFunc(decodeDot11MgmtMeasurementPilot)})
|
||||
LayerTypeDot11MgmtBeacon = gopacket.RegisterLayerType(98, gopacket.LayerTypeMetadata{Name: "Dot11MgmtBeacon", Decoder: gopacket.DecodeFunc(decodeDot11MgmtBeacon)})
|
||||
LayerTypeDot11MgmtATIM = gopacket.RegisterLayerType(99, gopacket.LayerTypeMetadata{Name: "Dot11MgmtATIM", Decoder: gopacket.DecodeFunc(decodeDot11MgmtATIM)})
|
||||
LayerTypeDot11MgmtDisassociation = gopacket.RegisterLayerType(100, gopacket.LayerTypeMetadata{Name: "Dot11MgmtDisassociation", Decoder: gopacket.DecodeFunc(decodeDot11MgmtDisassociation)})
|
||||
LayerTypeDot11MgmtAuthentication = gopacket.RegisterLayerType(101, gopacket.LayerTypeMetadata{Name: "Dot11MgmtAuthentication", Decoder: gopacket.DecodeFunc(decodeDot11MgmtAuthentication)})
|
||||
LayerTypeDot11MgmtDeauthentication = gopacket.RegisterLayerType(102, gopacket.LayerTypeMetadata{Name: "Dot11MgmtDeauthentication", Decoder: gopacket.DecodeFunc(decodeDot11MgmtDeauthentication)})
|
||||
LayerTypeDot11MgmtAction = gopacket.RegisterLayerType(103, gopacket.LayerTypeMetadata{Name: "Dot11MgmtAction", Decoder: gopacket.DecodeFunc(decodeDot11MgmtAction)})
|
||||
LayerTypeDot11MgmtActionNoAck = gopacket.RegisterLayerType(104, gopacket.LayerTypeMetadata{Name: "Dot11MgmtActionNoAck", Decoder: gopacket.DecodeFunc(decodeDot11MgmtActionNoAck)})
|
||||
LayerTypeDot11MgmtArubaWLAN = gopacket.RegisterLayerType(105, gopacket.LayerTypeMetadata{Name: "Dot11MgmtArubaWLAN", Decoder: gopacket.DecodeFunc(decodeDot11MgmtArubaWLAN)})
|
||||
LayerTypeDot11WEP = gopacket.RegisterLayerType(106, gopacket.LayerTypeMetadata{Name: "Dot11WEP", Decoder: gopacket.DecodeFunc(decodeDot11WEP)})
|
||||
LayerTypeDNS = gopacket.RegisterLayerType(107, gopacket.LayerTypeMetadata{Name: "DNS", Decoder: gopacket.DecodeFunc(decodeDNS)})
|
||||
LayerTypeUSB = gopacket.RegisterLayerType(108, gopacket.LayerTypeMetadata{Name: "USB", Decoder: gopacket.DecodeFunc(decodeUSB)})
|
||||
LayerTypeUSBRequestBlockSetup = gopacket.RegisterLayerType(109, gopacket.LayerTypeMetadata{Name: "USBRequestBlockSetup", Decoder: gopacket.DecodeFunc(decodeUSBRequestBlockSetup)})
|
||||
LayerTypeUSBControl = gopacket.RegisterLayerType(110, gopacket.LayerTypeMetadata{Name: "USBControl", Decoder: gopacket.DecodeFunc(decodeUSBControl)})
|
||||
LayerTypeUSBInterrupt = gopacket.RegisterLayerType(111, gopacket.LayerTypeMetadata{Name: "USBInterrupt", Decoder: gopacket.DecodeFunc(decodeUSBInterrupt)})
|
||||
LayerTypeUSBBulk = gopacket.RegisterLayerType(112, gopacket.LayerTypeMetadata{Name: "USBBulk", Decoder: gopacket.DecodeFunc(decodeUSBBulk)})
|
||||
LayerTypeLinuxSLL = gopacket.RegisterLayerType(113, gopacket.LayerTypeMetadata{Name: "Linux SLL", Decoder: gopacket.DecodeFunc(decodeLinuxSLL)})
|
||||
LayerTypeSFlow = gopacket.RegisterLayerType(114, gopacket.LayerTypeMetadata{Name: "SFlow", Decoder: gopacket.DecodeFunc(decodeSFlow)})
|
||||
LayerTypePrismHeader = gopacket.RegisterLayerType(115, gopacket.LayerTypeMetadata{Name: "Prism monitor mode header", Decoder: gopacket.DecodeFunc(decodePrismHeader)})
|
||||
LayerTypeVXLAN = gopacket.RegisterLayerType(116, gopacket.LayerTypeMetadata{Name: "VXLAN", Decoder: gopacket.DecodeFunc(decodeVXLAN)})
|
||||
LayerTypeNTP = gopacket.RegisterLayerType(117, gopacket.LayerTypeMetadata{Name: "NTP", Decoder: gopacket.DecodeFunc(decodeNTP)})
|
||||
LayerTypeDHCPv4 = gopacket.RegisterLayerType(118, gopacket.LayerTypeMetadata{Name: "DHCPv4", Decoder: gopacket.DecodeFunc(decodeDHCPv4)})
|
||||
LayerTypeVRRP = gopacket.RegisterLayerType(119, gopacket.LayerTypeMetadata{Name: "VRRP", Decoder: gopacket.DecodeFunc(decodeVRRP)})
|
||||
LayerTypeGeneve = gopacket.RegisterLayerType(120, gopacket.LayerTypeMetadata{Name: "Geneve", Decoder: gopacket.DecodeFunc(decodeGeneve)})
|
||||
LayerTypeSTP = gopacket.RegisterLayerType(121, gopacket.LayerTypeMetadata{Name: "STP", Decoder: gopacket.DecodeFunc(decodeSTP)})
|
||||
LayerTypeBFD = gopacket.RegisterLayerType(122, gopacket.LayerTypeMetadata{Name: "BFD", Decoder: gopacket.DecodeFunc(decodeBFD)})
|
||||
LayerTypeOSPF = gopacket.RegisterLayerType(123, gopacket.LayerTypeMetadata{Name: "OSPF", Decoder: gopacket.DecodeFunc(decodeOSPF)})
|
||||
LayerTypeICMPv6RouterSolicitation = gopacket.RegisterLayerType(124, gopacket.LayerTypeMetadata{Name: "ICMPv6RouterSolicitation", Decoder: gopacket.DecodeFunc(decodeICMPv6RouterSolicitation)})
|
||||
LayerTypeICMPv6RouterAdvertisement = gopacket.RegisterLayerType(125, gopacket.LayerTypeMetadata{Name: "ICMPv6RouterAdvertisement", Decoder: gopacket.DecodeFunc(decodeICMPv6RouterAdvertisement)})
|
||||
LayerTypeICMPv6NeighborSolicitation = gopacket.RegisterLayerType(126, gopacket.LayerTypeMetadata{Name: "ICMPv6NeighborSolicitation", Decoder: gopacket.DecodeFunc(decodeICMPv6NeighborSolicitation)})
|
||||
LayerTypeICMPv6NeighborAdvertisement = gopacket.RegisterLayerType(127, gopacket.LayerTypeMetadata{Name: "ICMPv6NeighborAdvertisement", Decoder: gopacket.DecodeFunc(decodeICMPv6NeighborAdvertisement)})
|
||||
LayerTypeICMPv6Redirect = gopacket.RegisterLayerType(128, gopacket.LayerTypeMetadata{Name: "ICMPv6Redirect", Decoder: gopacket.DecodeFunc(decodeICMPv6Redirect)})
|
||||
LayerTypeGTPv1U = gopacket.RegisterLayerType(129, gopacket.LayerTypeMetadata{Name: "GTPv1U", Decoder: gopacket.DecodeFunc(decodeGTPv1u)})
|
||||
LayerTypeEAPOLKey = gopacket.RegisterLayerType(130, gopacket.LayerTypeMetadata{Name: "EAPOLKey", Decoder: gopacket.DecodeFunc(decodeEAPOLKey)})
|
||||
LayerTypeLCM = gopacket.RegisterLayerType(131, gopacket.LayerTypeMetadata{Name: "LCM", Decoder: gopacket.DecodeFunc(decodeLCM)})
|
||||
LayerTypeICMPv6Echo = gopacket.RegisterLayerType(132, gopacket.LayerTypeMetadata{Name: "ICMPv6Echo", Decoder: gopacket.DecodeFunc(decodeICMPv6Echo)})
|
||||
LayerTypeSIP = gopacket.RegisterLayerType(133, gopacket.LayerTypeMetadata{Name: "SIP", Decoder: gopacket.DecodeFunc(decodeSIP)})
|
||||
LayerTypeDHCPv6 = gopacket.RegisterLayerType(134, gopacket.LayerTypeMetadata{Name: "DHCPv6", Decoder: gopacket.DecodeFunc(decodeDHCPv6)})
|
||||
LayerTypeMLDv1MulticastListenerReport = gopacket.RegisterLayerType(135, gopacket.LayerTypeMetadata{Name: "MLDv1MulticastListenerReport", Decoder: gopacket.DecodeFunc(decodeMLDv1MulticastListenerReport)})
|
||||
LayerTypeMLDv1MulticastListenerDone = gopacket.RegisterLayerType(136, gopacket.LayerTypeMetadata{Name: "MLDv1MulticastListenerDone", Decoder: gopacket.DecodeFunc(decodeMLDv1MulticastListenerDone)})
|
||||
LayerTypeMLDv1MulticastListenerQuery = gopacket.RegisterLayerType(137, gopacket.LayerTypeMetadata{Name: "MLDv1MulticastListenerQuery", Decoder: gopacket.DecodeFunc(decodeMLDv1MulticastListenerQuery)})
|
||||
LayerTypeMLDv2MulticastListenerReport = gopacket.RegisterLayerType(138, gopacket.LayerTypeMetadata{Name: "MLDv2MulticastListenerReport", Decoder: gopacket.DecodeFunc(decodeMLDv2MulticastListenerReport)})
|
||||
LayerTypeMLDv2MulticastListenerQuery = gopacket.RegisterLayerType(139, gopacket.LayerTypeMetadata{Name: "MLDv2MulticastListenerQuery", Decoder: gopacket.DecodeFunc(decodeMLDv2MulticastListenerQuery)})
|
||||
LayerTypeTLS = gopacket.RegisterLayerType(140, gopacket.LayerTypeMetadata{Name: "TLS", Decoder: gopacket.DecodeFunc(decodeTLS)})
|
||||
LayerTypeModbusTCP = gopacket.RegisterLayerType(141, gopacket.LayerTypeMetadata{Name: "ModbusTCP", Decoder: gopacket.DecodeFunc(decodeModbusTCP)})
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -172,4 +192,27 @@ var (
|
||||
LayerTypeIPSecAH,
|
||||
LayerTypeIPSecESP,
|
||||
})
|
||||
// LayerClassICMPv6NDP contains ICMPv6 neighbor discovery protocol
|
||||
// messages.
|
||||
LayerClassICMPv6NDP = gopacket.NewLayerClass([]gopacket.LayerType{
|
||||
LayerTypeICMPv6RouterSolicitation,
|
||||
LayerTypeICMPv6RouterAdvertisement,
|
||||
LayerTypeICMPv6NeighborSolicitation,
|
||||
LayerTypeICMPv6NeighborAdvertisement,
|
||||
LayerTypeICMPv6Redirect,
|
||||
})
|
||||
// LayerClassMLDv1 contains multicast listener discovery protocol
|
||||
LayerClassMLDv1 = gopacket.NewLayerClass([]gopacket.LayerType{
|
||||
LayerTypeMLDv1MulticastListenerQuery,
|
||||
LayerTypeMLDv1MulticastListenerReport,
|
||||
LayerTypeMLDv1MulticastListenerDone,
|
||||
})
|
||||
// LayerClassMLDv2 contains multicast listener discovery protocol v2
|
||||
LayerClassMLDv2 = gopacket.NewLayerClass([]gopacket.LayerType{
|
||||
LayerTypeMLDv1MulticastListenerReport,
|
||||
LayerTypeMLDv1MulticastListenerDone,
|
||||
LayerTypeMLDv2MulticastListenerReport,
|
||||
LayerTypeMLDv1MulticastListenerQuery,
|
||||
LayerTypeMLDv2MulticastListenerQuery,
|
||||
})
|
||||
)
|
||||
Loaded 100 of 405 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user