summaryrefslogtreecommitdiff
path: root/vendor/github.com
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com')
-rw-r--r--vendor/github.com/buger/goterm/.gitignore1
-rw-r--r--vendor/github.com/buger/goterm/box.go66
-rw-r--r--vendor/github.com/buger/goterm/go.mod5
-rw-r--r--vendor/github.com/buger/goterm/go.sum2
-rw-r--r--vendor/github.com/buger/goterm/plot.go3
-rw-r--r--vendor/github.com/buger/goterm/terminal.go10
-rw-r--r--vendor/github.com/buger/goterm/terminal_nosysioctl.go2
-rw-r--r--vendor/github.com/buger/goterm/terminal_sysioctl.go1
-rw-r--r--vendor/github.com/buger/goterm/terminal_windows.go23
-rw-r--r--vendor/github.com/docker/go-plugins-helpers/volume/api.go9
-rw-r--r--vendor/github.com/felixge/httpsnoop/.gitignore0
-rw-r--r--vendor/github.com/felixge/httpsnoop/.travis.yml6
-rw-r--r--vendor/github.com/felixge/httpsnoop/LICENSE.txt19
-rw-r--r--vendor/github.com/felixge/httpsnoop/Makefile10
-rw-r--r--vendor/github.com/felixge/httpsnoop/README.md94
-rw-r--r--vendor/github.com/felixge/httpsnoop/capture_metrics.go84
-rw-r--r--vendor/github.com/felixge/httpsnoop/docs.go10
-rw-r--r--vendor/github.com/felixge/httpsnoop/go.mod3
-rw-r--r--vendor/github.com/felixge/httpsnoop/wrap_generated_gteq_1.8.go385
-rw-r--r--vendor/github.com/felixge/httpsnoop/wrap_generated_lt_1.8.go243
-rw-r--r--vendor/github.com/google/shlex/go.mod3
-rw-r--r--vendor/github.com/gorilla/handlers/.travis.yml8
-rw-r--r--vendor/github.com/gorilla/handlers/README.md22
-rw-r--r--vendor/github.com/gorilla/handlers/canonical.go5
-rw-r--r--vendor/github.com/gorilla/handlers/compress.go157
-rw-r--r--vendor/github.com/gorilla/handlers/cors.go355
-rw-r--r--vendor/github.com/gorilla/handlers/go.mod5
-rw-r--r--vendor/github.com/gorilla/handlers/go.sum2
-rw-r--r--vendor/github.com/gorilla/handlers/handlers.go287
-rw-r--r--vendor/github.com/gorilla/handlers/logging.go244
-rw-r--r--vendor/github.com/gorilla/handlers/proxy_headers.go23
-rw-r--r--vendor/github.com/gorilla/handlers/recovery.go96
-rw-r--r--vendor/github.com/opencontainers/runc/libcontainer/apparmor/apparmor_linux.go5
-rw-r--r--vendor/github.com/opencontainers/runc/libcontainer/apparmor/apparmor_unsupported.go1
-rw-r--r--vendor/github.com/opencontainers/runc/libcontainer/cgroups/cgroups.go2
-rw-r--r--vendor/github.com/opencontainers/runc/libcontainer/cgroups/cgroups_unsupported.go3
-rw-r--r--vendor/github.com/opencontainers/runc/libcontainer/cgroups/file.go60
-rw-r--r--vendor/github.com/opencontainers/runc/libcontainer/cgroups/getallpids.go27
-rw-r--r--vendor/github.com/opencontainers/runc/libcontainer/cgroups/stats.go16
-rw-r--r--vendor/github.com/opencontainers/runc/libcontainer/cgroups/utils.go115
-rw-r--r--vendor/github.com/opencontainers/runc/libcontainer/cgroups/v1_utils.go19
-rw-r--r--vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_linux.go20
-rw-r--r--vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_unsupported.go1
-rw-r--r--vendor/github.com/opencontainers/runc/libcontainer/configs/config.go34
-rw-r--r--vendor/github.com/opencontainers/runc/libcontainer/configs/config_linux.go17
-rw-r--r--vendor/github.com/opencontainers/runc/libcontainer/configs/configs_fuzzer.go1
-rw-r--r--vendor/github.com/opencontainers/runc/libcontainer/configs/intelrdt.go3
-rw-r--r--vendor/github.com/opencontainers/runc/libcontainer/configs/mount.go9
-rw-r--r--vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_syscall.go1
-rw-r--r--vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_syscall_unsupported.go1
-rw-r--r--vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_unsupported.go1
-rw-r--r--vendor/github.com/opencontainers/runc/libcontainer/configs/rdma.go9
-rw-r--r--vendor/github.com/opencontainers/runc/libcontainer/devices/device_unix.go12
-rw-r--r--vendor/github.com/opencontainers/runc/libcontainer/user/lookup_unix.go1
-rw-r--r--vendor/github.com/opencontainers/runc/libcontainer/user/user.go21
-rw-r--r--vendor/github.com/opencontainers/runc/libcontainer/user/user_fuzzer.go1
-rw-r--r--vendor/github.com/opencontainers/runc/libcontainer/userns/userns_fuzzer.go1
-rw-r--r--vendor/github.com/opencontainers/runc/libcontainer/userns/userns_unsupported.go1
-rw-r--r--vendor/github.com/opencontainers/runc/libcontainer/utils/cmsg.go11
-rw-r--r--vendor/github.com/opencontainers/runc/libcontainer/utils/utils.go14
-rw-r--r--vendor/github.com/opencontainers/runc/libcontainer/utils/utils_unix.go5
-rw-r--r--vendor/github.com/opencontainers/runtime-spec/specs-go/config.go53
-rw-r--r--vendor/github.com/opencontainers/runtime-tools/generate/config.go28
-rw-r--r--vendor/github.com/opencontainers/runtime-tools/generate/generate.go55
-rw-r--r--vendor/github.com/opencontainers/runtime-tools/generate/seccomp/consts.go5
-rw-r--r--vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default_linux.go1
-rw-r--r--vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default_unsupported.go1
-rw-r--r--vendor/github.com/opencontainers/runtime-tools/generate/seccomp/syscall_compare.go16
-rw-r--r--vendor/github.com/opencontainers/runtime-tools/validate/validate.go5
-rw-r--r--vendor/github.com/opencontainers/runtime-tools/validate/validate_linux.go1
-rw-r--r--vendor/github.com/opencontainers/runtime-tools/validate/validate_unsupported.go1
-rw-r--r--vendor/github.com/seccomp/libseccomp-golang/.travis.yml28
-rw-r--r--vendor/github.com/seccomp/libseccomp-golang/Makefile8
-rw-r--r--vendor/github.com/seccomp/libseccomp-golang/README.md2
-rw-r--r--vendor/github.com/seccomp/libseccomp-golang/seccomp.go225
-rw-r--r--vendor/github.com/seccomp/libseccomp-golang/seccomp_internal.go260
-rw-r--r--vendor/github.com/vishvananda/netlink/.travis.yml20
-rw-r--r--vendor/github.com/vishvananda/netlink/README.md2
-rw-r--r--vendor/github.com/vishvananda/netlink/addr_linux.go6
-rw-r--r--vendor/github.com/vishvananda/netlink/bpf_linux.go24
-rw-r--r--vendor/github.com/vishvananda/netlink/class_linux.go8
-rw-r--r--vendor/github.com/vishvananda/netlink/conntrack_linux.go143
-rw-r--r--vendor/github.com/vishvananda/netlink/devlink_linux.go353
-rw-r--r--vendor/github.com/vishvananda/netlink/filter.go62
-rw-r--r--vendor/github.com/vishvananda/netlink/filter_linux.go306
-rw-r--r--vendor/github.com/vishvananda/netlink/handle_linux.go14
-rw-r--r--vendor/github.com/vishvananda/netlink/handle_unspecified.go2
-rw-r--r--vendor/github.com/vishvananda/netlink/ipset_linux.go167
-rw-r--r--vendor/github.com/vishvananda/netlink/link.go73
-rw-r--r--vendor/github.com/vishvananda/netlink/link_linux.go182
-rw-r--r--vendor/github.com/vishvananda/netlink/neigh.go1
-rw-r--r--vendor/github.com/vishvananda/netlink/neigh_linux.go34
-rw-r--r--vendor/github.com/vishvananda/netlink/netlink_unspecified.go16
-rw-r--r--vendor/github.com/vishvananda/netlink/netns_linux.go6
-rw-r--r--vendor/github.com/vishvananda/netlink/nl/conntrack_linux.go1
-rw-r--r--vendor/github.com/vishvananda/netlink/nl/devlink_linux.go55
-rw-r--r--vendor/github.com/vishvananda/netlink/nl/link_linux.go9
-rw-r--r--vendor/github.com/vishvananda/netlink/nl/lwt_linux.go29
-rw-r--r--vendor/github.com/vishvananda/netlink/nl/nl_linux.go53
-rw-r--r--vendor/github.com/vishvananda/netlink/nl/rdma_link_linux.go4
-rw-r--r--vendor/github.com/vishvananda/netlink/nl/seg6_linux.go4
-rw-r--r--vendor/github.com/vishvananda/netlink/nl/syscall.go2
-rw-r--r--vendor/github.com/vishvananda/netlink/nl/tc_linux.go105
-rw-r--r--vendor/github.com/vishvananda/netlink/proc_event.go217
-rw-r--r--vendor/github.com/vishvananda/netlink/qdisc_linux.go9
-rw-r--r--vendor/github.com/vishvananda/netlink/rdma_link_linux.go51
-rw-r--r--vendor/github.com/vishvananda/netlink/route.go4
-rw-r--r--vendor/github.com/vishvananda/netlink/route_linux.go237
-rw-r--r--vendor/github.com/vishvananda/netlink/rule.go13
-rw-r--r--vendor/github.com/vishvananda/netlink/rule_linux.go5
-rw-r--r--vendor/github.com/vishvananda/netlink/socket_linux.go76
-rw-r--r--vendor/github.com/vishvananda/netlink/xfrm_state_linux.go2
112 files changed, 4096 insertions, 1483 deletions
diff --git a/vendor/github.com/buger/goterm/.gitignore b/vendor/github.com/buger/goterm/.gitignore
new file mode 100644
index 000000000..1377554eb
--- /dev/null
+++ b/vendor/github.com/buger/goterm/.gitignore
@@ -0,0 +1 @@
+*.swp
diff --git a/vendor/github.com/buger/goterm/box.go b/vendor/github.com/buger/goterm/box.go
index 7df929d7d..4a119c552 100644
--- a/vendor/github.com/buger/goterm/box.go
+++ b/vendor/github.com/buger/goterm/box.go
@@ -2,7 +2,9 @@ package goterm
import (
"bytes"
+ "regexp"
"strings"
+ _ "unicode/utf8"
)
const DEFAULT_BORDER = "- │ ┌ ┐ └ ┘"
@@ -61,7 +63,9 @@ func (b *Box) Write(p []byte) (int, error) {
return b.Buf.Write(p)
}
-// Render Box
+var ANSI_RE = regexp.MustCompile(`\\0\d+\[\d+(?:;\d+)?m`)
+
+// String renders Box
func (b *Box) String() (out string) {
borders := strings.Split(b.Border, " ")
lines := strings.Split(b.Buf.String(), "\n")
@@ -74,7 +78,6 @@ func (b *Box) String() (out string) {
// Content width without borders and padding
contentWidth := b.Width - (b.PaddingX+1)*2
-
for y := 0; y < b.Height; y++ {
var line string
@@ -99,12 +102,63 @@ func (b *Box) String() (out string) {
line = ""
}
- if len(line) > contentWidth-1 {
+ r := []rune(line)
+
+ lastAnsii := ""
+ withoutAnsii := []rune{}
+ withOffset := []rune{}
+ i := 0
+
+ for {
+ if i >= len(r) {
+ break
+ }
+
+ if r[i] == 27 {
+ lastAnsii = ""
+ withOffset = append(withOffset, r[i])
+ lastAnsii += string(r[i])
+ i++
+ for {
+
+ i++
+ if i > len(r) {
+ break
+ }
+
+ withOffset = append(withOffset, r[i])
+ lastAnsii += string(r[i])
+
+ if r[i] == 'm' {
+ i++
+ break
+ }
+ }
+ }
+
+ if i >= len(r) {
+ break
+ }
+
+ withoutAnsii = append(withoutAnsii, r[i])
+
+ if len(withoutAnsii) <= contentWidth {
+ withOffset = append(withOffset, r[i])
+ }
+
+ i++
+ }
+
+ if len(withoutAnsii) > contentWidth {
// If line is too large limit it
- line = line[0:contentWidth]
+ line = string(withOffset)
} else {
// If line is too small enlarge it by adding spaces
- line = line + strings.Repeat(" ", contentWidth-len(line))
+ line += strings.Repeat(" ", contentWidth-len(withoutAnsii))
+ }
+
+ if lastAnsii != "" {
+ line += RESET
}
line = prefix + line + suffix
@@ -112,7 +166,7 @@ func (b *Box) String() (out string) {
// Don't add newline for last element
if y != b.Height-1 {
- line = line + "\n"
+ line += "\n"
}
out += line
diff --git a/vendor/github.com/buger/goterm/go.mod b/vendor/github.com/buger/goterm/go.mod
new file mode 100644
index 000000000..47f0e68b9
--- /dev/null
+++ b/vendor/github.com/buger/goterm/go.mod
@@ -0,0 +1,5 @@
+module github.com/buger/goterm
+
+go 1.15
+
+require golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54
diff --git a/vendor/github.com/buger/goterm/go.sum b/vendor/github.com/buger/goterm/go.sum
new file mode 100644
index 000000000..a9c9b7f42
--- /dev/null
+++ b/vendor/github.com/buger/goterm/go.sum
@@ -0,0 +1,2 @@
+golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54 h1:rF3Ohx8DRyl8h2zw9qojyLHLhrJpEMgyPOImREEryf0=
+golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
diff --git a/vendor/github.com/buger/goterm/plot.go b/vendor/github.com/buger/goterm/plot.go
index 120147623..504358cbe 100644
--- a/vendor/github.com/buger/goterm/plot.go
+++ b/vendor/github.com/buger/goterm/plot.go
@@ -4,6 +4,7 @@ import (
"fmt"
"math"
"strings"
+ "unicode/utf8"
)
const (
@@ -119,7 +120,7 @@ func (c *LineChart) DrawAxes(maxX, minX, maxY, minY float64, index int) {
c.writeText(ff(minX), c.paddingX, 0)
x_col := c.data.columns[0]
- c.writeText(c.data.columns[0], c.Width/2-len(x_col)/2, 1)
+ c.writeText(c.data.columns[0], c.Width/2-utf8.RuneCountInString(x_col)/2, 1)
if c.Flags&DRAW_INDEPENDENT != 0 || len(c.data.columns) < 3 {
col := c.data.columns[index]
diff --git a/vendor/github.com/buger/goterm/terminal.go b/vendor/github.com/buger/goterm/terminal.go
index 7c4dfa70f..1ba6493ad 100644
--- a/vendor/github.com/buger/goterm/terminal.go
+++ b/vendor/github.com/buger/goterm/terminal.go
@@ -71,7 +71,7 @@ type winsize struct {
// Its not recommended write to buffer dirrectly, use package Print,Printf,Println fucntions instead.
var Screen *bytes.Buffer = new(bytes.Buffer)
-// Get relative or absolute coordinates
+// GetXY gets relative or absolute coordinates
// To get relative, set PCT flag to number:
//
// // Get 10% of total width to `x` and 20 to y
@@ -145,7 +145,7 @@ func MoveTo(str string, x int, y int) (out string) {
})
}
-// Return carrier to start of line
+// ResetLine returns carrier to start of line
func ResetLine(str string) (out string) {
return applyTransform(str, func(idx int, line string) string {
return fmt.Sprintf("%s%s", RESET_LINE, line)
@@ -188,7 +188,7 @@ func Background(str string, color int) string {
})
}
-// Get console width
+// Width gets console width
func Width() int {
ws, err := getWinsize()
@@ -199,7 +199,7 @@ func Width() int {
return int(ws.Col)
}
-// Get console height
+// Height gets console height
func Height() int {
ws, err := getWinsize()
if err != nil {
@@ -208,7 +208,7 @@ func Height() int {
return int(ws.Row)
}
-// Get current height. Line count in Screen buffer.
+// CurrentHeight gets current height. Line count in Screen buffer.
func CurrentHeight() int {
return strings.Count(Screen.String(), "\n")
}
diff --git a/vendor/github.com/buger/goterm/terminal_nosysioctl.go b/vendor/github.com/buger/goterm/terminal_nosysioctl.go
index 690615008..9b988ffd5 100644
--- a/vendor/github.com/buger/goterm/terminal_nosysioctl.go
+++ b/vendor/github.com/buger/goterm/terminal_nosysioctl.go
@@ -1,4 +1,4 @@
-// +build windows plan9 solaris
+// +build plan9 solaris
package goterm
diff --git a/vendor/github.com/buger/goterm/terminal_sysioctl.go b/vendor/github.com/buger/goterm/terminal_sysioctl.go
index 5a61cd52b..33148ede0 100644
--- a/vendor/github.com/buger/goterm/terminal_sysioctl.go
+++ b/vendor/github.com/buger/goterm/terminal_sysioctl.go
@@ -4,6 +4,7 @@ package goterm
import (
"os"
+
"golang.org/x/sys/unix"
)
diff --git a/vendor/github.com/buger/goterm/terminal_windows.go b/vendor/github.com/buger/goterm/terminal_windows.go
new file mode 100644
index 000000000..37c56ae69
--- /dev/null
+++ b/vendor/github.com/buger/goterm/terminal_windows.go
@@ -0,0 +1,23 @@
+// +build windows
+
+package goterm
+
+import (
+ "os"
+
+ "golang.org/x/sys/windows"
+)
+
+func getWinsize() (*winsize, error) {
+ ws := new(winsize)
+ fd := os.Stdout.Fd()
+ var info windows.ConsoleScreenBufferInfo
+ if err := windows.GetConsoleScreenBufferInfo(windows.Handle(fd), &info); err != nil {
+ return nil, err
+ }
+
+ ws.Col = uint16(info.Window.Right - info.Window.Left + 1)
+ ws.Row = uint16(info.Window.Bottom - info.Window.Top + 1)
+
+ return ws, nil
+}
diff --git a/vendor/github.com/docker/go-plugins-helpers/volume/api.go b/vendor/github.com/docker/go-plugins-helpers/volume/api.go
index dcc2f3abf..387e82ac5 100644
--- a/vendor/github.com/docker/go-plugins-helpers/volume/api.go
+++ b/vendor/github.com/docker/go-plugins-helpers/volume/api.go
@@ -1,7 +1,6 @@
package volume
import (
- "log"
"net/http"
"github.com/docker/go-plugins-helpers/sdk"
@@ -130,7 +129,6 @@ func NewHandler(driver Driver) *Handler {
func (h *Handler) initMux() {
h.HandleFunc(createPath, func(w http.ResponseWriter, r *http.Request) {
- log.Println("Entering go-plugins-helpers createPath")
req := &CreateRequest{}
err := sdk.DecodeRequest(w, r, req)
if err != nil {
@@ -144,7 +142,6 @@ func (h *Handler) initMux() {
sdk.EncodeResponse(w, struct{}{}, false)
})
h.HandleFunc(removePath, func(w http.ResponseWriter, r *http.Request) {
- log.Println("Entering go-plugins-helpers removePath")
req := &RemoveRequest{}
err := sdk.DecodeRequest(w, r, req)
if err != nil {
@@ -158,7 +155,6 @@ func (h *Handler) initMux() {
sdk.EncodeResponse(w, struct{}{}, false)
})
h.HandleFunc(mountPath, func(w http.ResponseWriter, r *http.Request) {
- log.Println("Entering go-plugins-helpers mountPath")
req := &MountRequest{}
err := sdk.DecodeRequest(w, r, req)
if err != nil {
@@ -172,7 +168,6 @@ func (h *Handler) initMux() {
sdk.EncodeResponse(w, res, false)
})
h.HandleFunc(hostVirtualPath, func(w http.ResponseWriter, r *http.Request) {
- log.Println("Entering go-plugins-helpers hostVirtualPath")
req := &PathRequest{}
err := sdk.DecodeRequest(w, r, req)
if err != nil {
@@ -186,7 +181,6 @@ func (h *Handler) initMux() {
sdk.EncodeResponse(w, res, false)
})
h.HandleFunc(getPath, func(w http.ResponseWriter, r *http.Request) {
- log.Println("Entering go-plugins-helpers getPath")
req := &GetRequest{}
err := sdk.DecodeRequest(w, r, req)
if err != nil {
@@ -200,7 +194,6 @@ func (h *Handler) initMux() {
sdk.EncodeResponse(w, res, false)
})
h.HandleFunc(unmountPath, func(w http.ResponseWriter, r *http.Request) {
- log.Println("Entering go-plugins-helpers unmountPath")
req := &UnmountRequest{}
err := sdk.DecodeRequest(w, r, req)
if err != nil {
@@ -214,7 +207,6 @@ func (h *Handler) initMux() {
sdk.EncodeResponse(w, struct{}{}, false)
})
h.HandleFunc(listPath, func(w http.ResponseWriter, r *http.Request) {
- log.Println("Entering go-plugins-helpers listPath")
res, err := h.driver.List()
if err != nil {
sdk.EncodeResponse(w, NewErrorResponse(err.Error()), true)
@@ -224,7 +216,6 @@ func (h *Handler) initMux() {
})
h.HandleFunc(capabilitiesPath, func(w http.ResponseWriter, r *http.Request) {
- log.Println("Entering go-plugins-helpers capabilitiesPath")
sdk.EncodeResponse(w, h.driver.Capabilities(), false)
})
}
diff --git a/vendor/github.com/felixge/httpsnoop/.gitignore b/vendor/github.com/felixge/httpsnoop/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/vendor/github.com/felixge/httpsnoop/.gitignore
diff --git a/vendor/github.com/felixge/httpsnoop/.travis.yml b/vendor/github.com/felixge/httpsnoop/.travis.yml
new file mode 100644
index 000000000..bfc421200
--- /dev/null
+++ b/vendor/github.com/felixge/httpsnoop/.travis.yml
@@ -0,0 +1,6 @@
+language: go
+
+go:
+ - 1.6
+ - 1.7
+ - 1.8
diff --git a/vendor/github.com/felixge/httpsnoop/LICENSE.txt b/vendor/github.com/felixge/httpsnoop/LICENSE.txt
new file mode 100644
index 000000000..e028b46a9
--- /dev/null
+++ b/vendor/github.com/felixge/httpsnoop/LICENSE.txt
@@ -0,0 +1,19 @@
+Copyright (c) 2016 Felix Geisendörfer (felix@debuggable.com)
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
diff --git a/vendor/github.com/felixge/httpsnoop/Makefile b/vendor/github.com/felixge/httpsnoop/Makefile
new file mode 100644
index 000000000..2d84889ae
--- /dev/null
+++ b/vendor/github.com/felixge/httpsnoop/Makefile
@@ -0,0 +1,10 @@
+.PHONY: ci generate clean
+
+ci: clean generate
+ go test -v ./...
+
+generate:
+ go generate .
+
+clean:
+ rm -rf *_generated*.go
diff --git a/vendor/github.com/felixge/httpsnoop/README.md b/vendor/github.com/felixge/httpsnoop/README.md
new file mode 100644
index 000000000..ae44137e9
--- /dev/null
+++ b/vendor/github.com/felixge/httpsnoop/README.md
@@ -0,0 +1,94 @@
+# httpsnoop
+
+Package httpsnoop provides an easy way to capture http related metrics (i.e.
+response time, bytes written, and http status code) from your application's
+http.Handlers.
+
+Doing this requires non-trivial wrapping of the http.ResponseWriter interface,
+which is also exposed for users interested in a more low-level API.
+
+[![GoDoc](https://godoc.org/github.com/felixge/httpsnoop?status.svg)](https://godoc.org/github.com/felixge/httpsnoop)
+[![Build Status](https://travis-ci.org/felixge/httpsnoop.svg?branch=master)](https://travis-ci.org/felixge/httpsnoop)
+
+## Usage Example
+
+```go
+// myH is your app's http handler, perhaps a http.ServeMux or similar.
+var myH http.Handler
+// wrappedH wraps myH in order to log every request.
+wrappedH := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ m := httpsnoop.CaptureMetrics(myH, w, r)
+ log.Printf(
+ "%s %s (code=%d dt=%s written=%d)",
+ r.Method,
+ r.URL,
+ m.Code,
+ m.Duration,
+ m.Written,
+ )
+})
+http.ListenAndServe(":8080", wrappedH)
+```
+
+## Why this package exists
+
+Instrumenting an application's http.Handler is surprisingly difficult.
+
+However if you google for e.g. "capture ResponseWriter status code" you'll find
+lots of advise and code examples that suggest it to be a fairly trivial
+undertaking. Unfortunately everything I've seen so far has a high chance of
+breaking your application.
+
+The main problem is that a `http.ResponseWriter` often implements additional
+interfaces such as `http.Flusher`, `http.CloseNotifier`, `http.Hijacker`, `http.Pusher`, and
+`io.ReaderFrom`. So the naive approach of just wrapping `http.ResponseWriter`
+in your own struct that also implements the `http.ResponseWriter` interface
+will hide the additional interfaces mentioned above. This has a high change of
+introducing subtle bugs into any non-trivial application.
+
+Another approach I've seen people take is to return a struct that implements
+all of the interfaces above. However, that's also problematic, because it's
+difficult to fake some of these interfaces behaviors when the underlying
+`http.ResponseWriter` doesn't have an implementation. It's also dangerous,
+because an application may choose to operate differently, merely because it
+detects the presence of these additional interfaces.
+
+This package solves this problem by checking which additional interfaces a
+`http.ResponseWriter` implements, returning a wrapped version implementing the
+exact same set of interfaces.
+
+Additionally this package properly handles edge cases such as `WriteHeader` not
+being called, or called more than once, as well as concurrent calls to
+`http.ResponseWriter` methods, and even calls happening after the wrapped
+`ServeHTTP` has already returned.
+
+Unfortunately this package is not perfect either. It's possible that it is
+still missing some interfaces provided by the go core (let me know if you find
+one), and it won't work for applications adding their own interfaces into the
+mix.
+
+However, hopefully the explanation above has sufficiently scared you of rolling
+your own solution to this problem. httpsnoop may still break your application,
+but at least it tries to avoid it as much as possible.
+
+Anyway, the real problem here is that smuggling additional interfaces inside
+`http.ResponseWriter` is a problematic design choice, but it probably goes as
+deep as the Go language specification itself. But that's okay, I still prefer
+Go over the alternatives ;).
+
+## Performance
+
+```
+BenchmarkBaseline-8 20000 94912 ns/op
+BenchmarkCaptureMetrics-8 20000 95461 ns/op
+```
+
+As you can see, using `CaptureMetrics` on a vanilla http.Handler introduces an
+overhead of ~500 ns per http request on my machine. However, the margin of
+error appears to be larger than that, therefor it should be reasonable to
+assume that the overhead introduced by `CaptureMetrics` is absolutely
+negligible.
+
+## License
+
+MIT
diff --git a/vendor/github.com/felixge/httpsnoop/capture_metrics.go b/vendor/github.com/felixge/httpsnoop/capture_metrics.go
new file mode 100644
index 000000000..4c45b1a8c
--- /dev/null
+++ b/vendor/github.com/felixge/httpsnoop/capture_metrics.go
@@ -0,0 +1,84 @@
+package httpsnoop
+
+import (
+ "io"
+ "net/http"
+ "sync"
+ "time"
+)
+
+// Metrics holds metrics captured from CaptureMetrics.
+type Metrics struct {
+ // Code is the first http response code passed to the WriteHeader func of
+ // the ResponseWriter. If no such call is made, a default code of 200 is
+ // assumed instead.
+ Code int
+ // Duration is the time it took to execute the handler.
+ Duration time.Duration
+ // Written is the number of bytes successfully written by the Write or
+ // ReadFrom function of the ResponseWriter. ResponseWriters may also write
+ // data to their underlaying connection directly (e.g. headers), but those
+ // are not tracked. Therefor the number of Written bytes will usually match
+ // the size of the response body.
+ Written int64
+}
+
+// CaptureMetrics wraps the given hnd, executes it with the given w and r, and
+// returns the metrics it captured from it.
+func CaptureMetrics(hnd http.Handler, w http.ResponseWriter, r *http.Request) Metrics {
+ return CaptureMetricsFn(w, func(ww http.ResponseWriter) {
+ hnd.ServeHTTP(ww, r)
+ })
+}
+
+// CaptureMetricsFn wraps w and calls fn with the wrapped w and returns the
+// resulting metrics. This is very similar to CaptureMetrics (which is just
+// sugar on top of this func), but is a more usable interface if your
+// application doesn't use the Go http.Handler interface.
+func CaptureMetricsFn(w http.ResponseWriter, fn func(http.ResponseWriter)) Metrics {
+ var (
+ start = time.Now()
+ m = Metrics{Code: http.StatusOK}
+ headerWritten bool
+ lock sync.Mutex
+ hooks = Hooks{
+ WriteHeader: func(next WriteHeaderFunc) WriteHeaderFunc {
+ return func(code int) {
+ next(code)
+ lock.Lock()
+ defer lock.Unlock()
+ if !headerWritten {
+ m.Code = code
+ headerWritten = true
+ }
+ }
+ },
+
+ Write: func(next WriteFunc) WriteFunc {
+ return func(p []byte) (int, error) {
+ n, err := next(p)
+ lock.Lock()
+ defer lock.Unlock()
+ m.Written += int64(n)
+ headerWritten = true
+ return n, err
+ }
+ },
+
+ ReadFrom: func(next ReadFromFunc) ReadFromFunc {
+ return func(src io.Reader) (int64, error) {
+ n, err := next(src)
+ lock.Lock()
+ defer lock.Unlock()
+ headerWritten = true
+ m.Written += n
+ return n, err
+ }
+ },
+ }
+ )
+
+ fn(Wrap(w, hooks))
+ m.Duration = time.Since(start)
+ return m
+}
diff --git a/vendor/github.com/felixge/httpsnoop/docs.go b/vendor/github.com/felixge/httpsnoop/docs.go
new file mode 100644
index 000000000..203c35b3c
--- /dev/null
+++ b/vendor/github.com/felixge/httpsnoop/docs.go
@@ -0,0 +1,10 @@
+// Package httpsnoop provides an easy way to capture http related metrics (i.e.
+// response time, bytes written, and http status code) from your application's
+// http.Handlers.
+//
+// Doing this requires non-trivial wrapping of the http.ResponseWriter
+// interface, which is also exposed for users interested in a more low-level
+// API.
+package httpsnoop
+
+//go:generate go run codegen/main.go
diff --git a/vendor/github.com/felixge/httpsnoop/go.mod b/vendor/github.com/felixge/httpsnoop/go.mod
new file mode 100644
index 000000000..73b394690
--- /dev/null
+++ b/vendor/github.com/felixge/httpsnoop/go.mod
@@ -0,0 +1,3 @@
+module github.com/felixge/httpsnoop
+
+go 1.13
diff --git a/vendor/github.com/felixge/httpsnoop/wrap_generated_gteq_1.8.go b/vendor/github.com/felixge/httpsnoop/wrap_generated_gteq_1.8.go
new file mode 100644
index 000000000..41a20da9e
--- /dev/null
+++ b/vendor/github.com/felixge/httpsnoop/wrap_generated_gteq_1.8.go
@@ -0,0 +1,385 @@
+// +build go1.8
+// Code generated by "httpsnoop/codegen"; DO NOT EDIT
+
+package httpsnoop
+
+import (
+ "bufio"
+ "io"
+ "net"
+ "net/http"
+)
+
+// HeaderFunc is part of the http.ResponseWriter interface.
+type HeaderFunc func() http.Header
+
+// WriteHeaderFunc is part of the http.ResponseWriter interface.
+type WriteHeaderFunc func(code int)
+
+// WriteFunc is part of the http.ResponseWriter interface.
+type WriteFunc func(b []byte) (int, error)
+
+// FlushFunc is part of the http.Flusher interface.
+type FlushFunc func()
+
+// CloseNotifyFunc is part of the http.CloseNotifier interface.
+type CloseNotifyFunc func() <-chan bool
+
+// HijackFunc is part of the http.Hijacker interface.
+type HijackFunc func() (net.Conn, *bufio.ReadWriter, error)
+
+// ReadFromFunc is part of the io.ReaderFrom interface.
+type ReadFromFunc func(src io.Reader) (int64, error)
+
+// PushFunc is part of the http.Pusher interface.
+type PushFunc func(target string, opts *http.PushOptions) error
+
+// Hooks defines a set of method interceptors for methods included in
+// http.ResponseWriter as well as some others. You can think of them as
+// middleware for the function calls they target. See Wrap for more details.
+type Hooks struct {
+ Header func(HeaderFunc) HeaderFunc
+ WriteHeader func(WriteHeaderFunc) WriteHeaderFunc
+ Write func(WriteFunc) WriteFunc
+ Flush func(FlushFunc) FlushFunc
+ CloseNotify func(CloseNotifyFunc) CloseNotifyFunc
+ Hijack func(HijackFunc) HijackFunc
+ ReadFrom func(ReadFromFunc) ReadFromFunc
+ Push func(PushFunc) PushFunc
+}
+
+// Wrap returns a wrapped version of w that provides the exact same interface
+// as w. Specifically if w implements any combination of:
+//
+// - http.Flusher
+// - http.CloseNotifier
+// - http.Hijacker
+// - io.ReaderFrom
+// - http.Pusher
+//
+// The wrapped version will implement the exact same combination. If no hooks
+// are set, the wrapped version also behaves exactly as w. Hooks targeting
+// methods not supported by w are ignored. Any other hooks will intercept the
+// method they target and may modify the call's arguments and/or return values.
+// The CaptureMetrics implementation serves as a working example for how the
+// hooks can be used.
+func Wrap(w http.ResponseWriter, hooks Hooks) http.ResponseWriter {
+ rw := &rw{w: w, h: hooks}
+ _, i0 := w.(http.Flusher)
+ _, i1 := w.(http.CloseNotifier)
+ _, i2 := w.(http.Hijacker)
+ _, i3 := w.(io.ReaderFrom)
+ _, i4 := w.(http.Pusher)
+ switch {
+ // combination 1/32
+ case !i0 && !i1 && !i2 && !i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ }{rw}
+ // combination 2/32
+ case !i0 && !i1 && !i2 && !i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.Pusher
+ }{rw, rw}
+ // combination 3/32
+ case !i0 && !i1 && !i2 && i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ io.ReaderFrom
+ }{rw, rw}
+ // combination 4/32
+ case !i0 && !i1 && !i2 && i3 && i4:
+ return struct {
+ http.ResponseWriter
+ io.ReaderFrom
+ http.Pusher
+ }{rw, rw, rw}
+ // combination 5/32
+ case !i0 && !i1 && i2 && !i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.Hijacker
+ }{rw, rw}
+ // combination 6/32
+ case !i0 && !i1 && i2 && !i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.Hijacker
+ http.Pusher
+ }{rw, rw, rw}
+ // combination 7/32
+ case !i0 && !i1 && i2 && i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.Hijacker
+ io.ReaderFrom
+ }{rw, rw, rw}
+ // combination 8/32
+ case !i0 && !i1 && i2 && i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.Hijacker
+ io.ReaderFrom
+ http.Pusher
+ }{rw, rw, rw, rw}
+ // combination 9/32
+ case !i0 && i1 && !i2 && !i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.CloseNotifier
+ }{rw, rw}
+ // combination 10/32
+ case !i0 && i1 && !i2 && !i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.CloseNotifier
+ http.Pusher
+ }{rw, rw, rw}
+ // combination 11/32
+ case !i0 && i1 && !i2 && i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.CloseNotifier
+ io.ReaderFrom
+ }{rw, rw, rw}
+ // combination 12/32
+ case !i0 && i1 && !i2 && i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.CloseNotifier
+ io.ReaderFrom
+ http.Pusher
+ }{rw, rw, rw, rw}
+ // combination 13/32
+ case !i0 && i1 && i2 && !i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.CloseNotifier
+ http.Hijacker
+ }{rw, rw, rw}
+ // combination 14/32
+ case !i0 && i1 && i2 && !i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.CloseNotifier
+ http.Hijacker
+ http.Pusher
+ }{rw, rw, rw, rw}
+ // combination 15/32
+ case !i0 && i1 && i2 && i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.CloseNotifier
+ http.Hijacker
+ io.ReaderFrom
+ }{rw, rw, rw, rw}
+ // combination 16/32
+ case !i0 && i1 && i2 && i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.CloseNotifier
+ http.Hijacker
+ io.ReaderFrom
+ http.Pusher
+ }{rw, rw, rw, rw, rw}
+ // combination 17/32
+ case i0 && !i1 && !i2 && !i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ }{rw, rw}
+ // combination 18/32
+ case i0 && !i1 && !i2 && !i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ http.Pusher
+ }{rw, rw, rw}
+ // combination 19/32
+ case i0 && !i1 && !i2 && i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ io.ReaderFrom
+ }{rw, rw, rw}
+ // combination 20/32
+ case i0 && !i1 && !i2 && i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ io.ReaderFrom
+ http.Pusher
+ }{rw, rw, rw, rw}
+ // combination 21/32
+ case i0 && !i1 && i2 && !i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ http.Hijacker
+ }{rw, rw, rw}
+ // combination 22/32
+ case i0 && !i1 && i2 && !i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ http.Hijacker
+ http.Pusher
+ }{rw, rw, rw, rw}
+ // combination 23/32
+ case i0 && !i1 && i2 && i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ http.Hijacker
+ io.ReaderFrom
+ }{rw, rw, rw, rw}
+ // combination 24/32
+ case i0 && !i1 && i2 && i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ http.Hijacker
+ io.ReaderFrom
+ http.Pusher
+ }{rw, rw, rw, rw, rw}
+ // combination 25/32
+ case i0 && i1 && !i2 && !i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ http.CloseNotifier
+ }{rw, rw, rw}
+ // combination 26/32
+ case i0 && i1 && !i2 && !i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ http.CloseNotifier
+ http.Pusher
+ }{rw, rw, rw, rw}
+ // combination 27/32
+ case i0 && i1 && !i2 && i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ http.CloseNotifier
+ io.ReaderFrom
+ }{rw, rw, rw, rw}
+ // combination 28/32
+ case i0 && i1 && !i2 && i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ http.CloseNotifier
+ io.ReaderFrom
+ http.Pusher
+ }{rw, rw, rw, rw, rw}
+ // combination 29/32
+ case i0 && i1 && i2 && !i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ http.CloseNotifier
+ http.Hijacker
+ }{rw, rw, rw, rw}
+ // combination 30/32
+ case i0 && i1 && i2 && !i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ http.CloseNotifier
+ http.Hijacker
+ http.Pusher
+ }{rw, rw, rw, rw, rw}
+ // combination 31/32
+ case i0 && i1 && i2 && i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ http.CloseNotifier
+ http.Hijacker
+ io.ReaderFrom
+ }{rw, rw, rw, rw, rw}
+ // combination 32/32
+ case i0 && i1 && i2 && i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ http.CloseNotifier
+ http.Hijacker
+ io.ReaderFrom
+ http.Pusher
+ }{rw, rw, rw, rw, rw, rw}
+ }
+ panic("unreachable")
+}
+
+type rw struct {
+ w http.ResponseWriter
+ h Hooks
+}
+
+func (w *rw) Header() http.Header {
+ f := w.w.(http.ResponseWriter).Header
+ if w.h.Header != nil {
+ f = w.h.Header(f)
+ }
+ return f()
+}
+
+func (w *rw) WriteHeader(code int) {
+ f := w.w.(http.ResponseWriter).WriteHeader
+ if w.h.WriteHeader != nil {
+ f = w.h.WriteHeader(f)
+ }
+ f(code)
+}
+
+func (w *rw) Write(b []byte) (int, error) {
+ f := w.w.(http.ResponseWriter).Write
+ if w.h.Write != nil {
+ f = w.h.Write(f)
+ }
+ return f(b)
+}
+
+func (w *rw) Flush() {
+ f := w.w.(http.Flusher).Flush
+ if w.h.Flush != nil {
+ f = w.h.Flush(f)
+ }
+ f()
+}
+
+func (w *rw) CloseNotify() <-chan bool {
+ f := w.w.(http.CloseNotifier).CloseNotify
+ if w.h.CloseNotify != nil {
+ f = w.h.CloseNotify(f)
+ }
+ return f()
+}
+
+func (w *rw) Hijack() (net.Conn, *bufio.ReadWriter, error) {
+ f := w.w.(http.Hijacker).Hijack
+ if w.h.Hijack != nil {
+ f = w.h.Hijack(f)
+ }
+ return f()
+}
+
+func (w *rw) ReadFrom(src io.Reader) (int64, error) {
+ f := w.w.(io.ReaderFrom).ReadFrom
+ if w.h.ReadFrom != nil {
+ f = w.h.ReadFrom(f)
+ }
+ return f(src)
+}
+
+func (w *rw) Push(target string, opts *http.PushOptions) error {
+ f := w.w.(http.Pusher).Push
+ if w.h.Push != nil {
+ f = w.h.Push(f)
+ }
+ return f(target, opts)
+}
diff --git a/vendor/github.com/felixge/httpsnoop/wrap_generated_lt_1.8.go b/vendor/github.com/felixge/httpsnoop/wrap_generated_lt_1.8.go
new file mode 100644
index 000000000..36bb59b83
--- /dev/null
+++ b/vendor/github.com/felixge/httpsnoop/wrap_generated_lt_1.8.go
@@ -0,0 +1,243 @@
+// +build !go1.8
+// Code generated by "httpsnoop/codegen"; DO NOT EDIT
+
+package httpsnoop
+
+import (
+ "bufio"
+ "io"
+ "net"
+ "net/http"
+)
+
+// HeaderFunc is part of the http.ResponseWriter interface.
+type HeaderFunc func() http.Header
+
+// WriteHeaderFunc is part of the http.ResponseWriter interface.
+type WriteHeaderFunc func(code int)
+
+// WriteFunc is part of the http.ResponseWriter interface.
+type WriteFunc func(b []byte) (int, error)
+
+// FlushFunc is part of the http.Flusher interface.
+type FlushFunc func()
+
+// CloseNotifyFunc is part of the http.CloseNotifier interface.
+type CloseNotifyFunc func() <-chan bool
+
+// HijackFunc is part of the http.Hijacker interface.
+type HijackFunc func() (net.Conn, *bufio.ReadWriter, error)
+
+// ReadFromFunc is part of the io.ReaderFrom interface.
+type ReadFromFunc func(src io.Reader) (int64, error)
+
+// Hooks defines a set of method interceptors for methods included in
+// http.ResponseWriter as well as some others. You can think of them as
+// middleware for the function calls they target. See Wrap for more details.
+type Hooks struct {
+ Header func(HeaderFunc) HeaderFunc
+ WriteHeader func(WriteHeaderFunc) WriteHeaderFunc
+ Write func(WriteFunc) WriteFunc
+ Flush func(FlushFunc) FlushFunc
+ CloseNotify func(CloseNotifyFunc) CloseNotifyFunc
+ Hijack func(HijackFunc) HijackFunc
+ ReadFrom func(ReadFromFunc) ReadFromFunc
+}
+
+// Wrap returns a wrapped version of w that provides the exact same interface
+// as w. Specifically if w implements any combination of:
+//
+// - http.Flusher
+// - http.CloseNotifier
+// - http.Hijacker
+// - io.ReaderFrom
+//
+// The wrapped version will implement the exact same combination. If no hooks
+// are set, the wrapped version also behaves exactly as w. Hooks targeting
+// methods not supported by w are ignored. Any other hooks will intercept the
+// method they target and may modify the call's arguments and/or return values.
+// The CaptureMetrics implementation serves as a working example for how the
+// hooks can be used.
+func Wrap(w http.ResponseWriter, hooks Hooks) http.ResponseWriter {
+ rw := &rw{w: w, h: hooks}
+ _, i0 := w.(http.Flusher)
+ _, i1 := w.(http.CloseNotifier)
+ _, i2 := w.(http.Hijacker)
+ _, i3 := w.(io.ReaderFrom)
+ switch {
+ // combination 1/16
+ case !i0 && !i1 && !i2 && !i3:
+ return struct {
+ http.ResponseWriter
+ }{rw}
+ // combination 2/16
+ case !i0 && !i1 && !i2 && i3:
+ return struct {
+ http.ResponseWriter
+ io.ReaderFrom
+ }{rw, rw}
+ // combination 3/16
+ case !i0 && !i1 && i2 && !i3:
+ return struct {
+ http.ResponseWriter
+ http.Hijacker
+ }{rw, rw}
+ // combination 4/16
+ case !i0 && !i1 && i2 && i3:
+ return struct {
+ http.ResponseWriter
+ http.Hijacker
+ io.ReaderFrom
+ }{rw, rw, rw}
+ // combination 5/16
+ case !i0 && i1 && !i2 && !i3:
+ return struct {
+ http.ResponseWriter
+ http.CloseNotifier
+ }{rw, rw}
+ // combination 6/16
+ case !i0 && i1 && !i2 && i3:
+ return struct {
+ http.ResponseWriter
+ http.CloseNotifier
+ io.ReaderFrom
+ }{rw, rw, rw}
+ // combination 7/16
+ case !i0 && i1 && i2 && !i3:
+ return struct {
+ http.ResponseWriter
+ http.CloseNotifier
+ http.Hijacker
+ }{rw, rw, rw}
+ // combination 8/16
+ case !i0 && i1 && i2 && i3:
+ return struct {
+ http.ResponseWriter
+ http.CloseNotifier
+ http.Hijacker
+ io.ReaderFrom
+ }{rw, rw, rw, rw}
+ // combination 9/16
+ case i0 && !i1 && !i2 && !i3:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ }{rw, rw}
+ // combination 10/16
+ case i0 && !i1 && !i2 && i3:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ io.ReaderFrom
+ }{rw, rw, rw}
+ // combination 11/16
+ case i0 && !i1 && i2 && !i3:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ http.Hijacker
+ }{rw, rw, rw}
+ // combination 12/16
+ case i0 && !i1 && i2 && i3:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ http.Hijacker
+ io.ReaderFrom
+ }{rw, rw, rw, rw}
+ // combination 13/16
+ case i0 && i1 && !i2 && !i3:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ http.CloseNotifier
+ }{rw, rw, rw}
+ // combination 14/16
+ case i0 && i1 && !i2 && i3:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ http.CloseNotifier
+ io.ReaderFrom
+ }{rw, rw, rw, rw}
+ // combination 15/16
+ case i0 && i1 && i2 && !i3:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ http.CloseNotifier
+ http.Hijacker
+ }{rw, rw, rw, rw}
+ // combination 16/16
+ case i0 && i1 && i2 && i3:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ http.CloseNotifier
+ http.Hijacker
+ io.ReaderFrom
+ }{rw, rw, rw, rw, rw}
+ }
+ panic("unreachable")
+}
+
+type rw struct {
+ w http.ResponseWriter
+ h Hooks
+}
+
+func (w *rw) Header() http.Header {
+ f := w.w.(http.ResponseWriter).Header
+ if w.h.Header != nil {
+ f = w.h.Header(f)
+ }
+ return f()
+}
+
+func (w *rw) WriteHeader(code int) {
+ f := w.w.(http.ResponseWriter).WriteHeader
+ if w.h.WriteHeader != nil {
+ f = w.h.WriteHeader(f)
+ }
+ f(code)
+}
+
+func (w *rw) Write(b []byte) (int, error) {
+ f := w.w.(http.ResponseWriter).Write
+ if w.h.Write != nil {
+ f = w.h.Write(f)
+ }
+ return f(b)
+}
+
+func (w *rw) Flush() {
+ f := w.w.(http.Flusher).Flush
+ if w.h.Flush != nil {
+ f = w.h.Flush(f)
+ }
+ f()
+}
+
+func (w *rw) CloseNotify() <-chan bool {
+ f := w.w.(http.CloseNotifier).CloseNotify
+ if w.h.CloseNotify != nil {
+ f = w.h.CloseNotify(f)
+ }
+ return f()
+}
+
+func (w *rw) Hijack() (net.Conn, *bufio.ReadWriter, error) {
+ f := w.w.(http.Hijacker).Hijack
+ if w.h.Hijack != nil {
+ f = w.h.Hijack(f)
+ }
+ return f()
+}
+
+func (w *rw) ReadFrom(src io.Reader) (int64, error) {
+ f := w.w.(io.ReaderFrom).ReadFrom
+ if w.h.ReadFrom != nil {
+ f = w.h.ReadFrom(f)
+ }
+ return f(src)
+}
diff --git a/vendor/github.com/google/shlex/go.mod b/vendor/github.com/google/shlex/go.mod
new file mode 100644
index 000000000..0ab3bce7f
--- /dev/null
+++ b/vendor/github.com/google/shlex/go.mod
@@ -0,0 +1,3 @@
+module github.com/google/shlex
+
+go 1.13
diff --git a/vendor/github.com/gorilla/handlers/.travis.yml b/vendor/github.com/gorilla/handlers/.travis.yml
deleted file mode 100644
index 354b7f8b2..000000000
--- a/vendor/github.com/gorilla/handlers/.travis.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-language: go
-
-go:
- - 1.1
- - 1.2
- - 1.3
- - 1.4
- - tip
diff --git a/vendor/github.com/gorilla/handlers/README.md b/vendor/github.com/gorilla/handlers/README.md
index a340abe08..6eba66bf3 100644
--- a/vendor/github.com/gorilla/handlers/README.md
+++ b/vendor/github.com/gorilla/handlers/README.md
@@ -1,28 +1,32 @@
gorilla/handlers
================
-[![GoDoc](https://godoc.org/github.com/gorilla/handlers?status.svg)](https://godoc.org/github.com/gorilla/handlers) [![Build Status](https://travis-ci.org/gorilla/handlers.svg?branch=master)](https://travis-ci.org/gorilla/handlers)
+[![GoDoc](https://godoc.org/github.com/gorilla/handlers?status.svg)](https://godoc.org/github.com/gorilla/handlers)
+[![CircleCI](https://circleci.com/gh/gorilla/handlers.svg?style=svg)](https://circleci.com/gh/gorilla/handlers)
+[![Sourcegraph](https://sourcegraph.com/github.com/gorilla/handlers/-/badge.svg)](https://sourcegraph.com/github.com/gorilla/handlers?badge)
+
Package handlers is a collection of handlers (aka "HTTP middleware") for use
with Go's `net/http` package (or any framework supporting `http.Handler`), including:
-* `LoggingHandler` for logging HTTP requests in the Apache [Common Log
+* [**LoggingHandler**](https://godoc.org/github.com/gorilla/handlers#LoggingHandler) for logging HTTP requests in the Apache [Common Log
Format](http://httpd.apache.org/docs/2.2/logs.html#common).
-* `CombinedLoggingHandler` for logging HTTP requests in the Apache [Combined Log
+* [**CombinedLoggingHandler**](https://godoc.org/github.com/gorilla/handlers#CombinedLoggingHandler) for logging HTTP requests in the Apache [Combined Log
Format](http://httpd.apache.org/docs/2.2/logs.html#combined) commonly used by
both Apache and nginx.
-* `CompressHandler` for gzipping responses.
-* `ContentTypeHandler` for validating requests against a list of accepted
+* [**CompressHandler**](https://godoc.org/github.com/gorilla/handlers#CompressHandler) for gzipping responses.
+* [**ContentTypeHandler**](https://godoc.org/github.com/gorilla/handlers#ContentTypeHandler) for validating requests against a list of accepted
content types.
-* `MethodHandler` for matching HTTP methods against handlers in a
+* [**MethodHandler**](https://godoc.org/github.com/gorilla/handlers#MethodHandler) for matching HTTP methods against handlers in a
`map[string]http.Handler`
-* `ProxyHeaders` for populating `r.RemoteAddr` and `r.URL.Scheme` based on the
+* [**ProxyHeaders**](https://godoc.org/github.com/gorilla/handlers#ProxyHeaders) for populating `r.RemoteAddr` and `r.URL.Scheme` based on the
`X-Forwarded-For`, `X-Real-IP`, `X-Forwarded-Proto` and RFC7239 `Forwarded`
headers when running a Go server behind a HTTP reverse proxy.
-* `CanonicalHost` for re-directing to the preferred host when handling multiple
+* [**CanonicalHost**](https://godoc.org/github.com/gorilla/handlers#CanonicalHost) for re-directing to the preferred host when handling multiple
domains (i.e. multiple CNAME aliases).
+* [**RecoveryHandler**](https://godoc.org/github.com/gorilla/handlers#RecoveryHandler) for recovering from unexpected panics.
Other handlers are documented [on the Gorilla
-website](http://www.gorillatoolkit.org/pkg/handlers).
+website](https://www.gorillatoolkit.org/pkg/handlers).
## Example
diff --git a/vendor/github.com/gorilla/handlers/canonical.go b/vendor/github.com/gorilla/handlers/canonical.go
index 3961695c4..8437fefc1 100644
--- a/vendor/github.com/gorilla/handlers/canonical.go
+++ b/vendor/github.com/gorilla/handlers/canonical.go
@@ -18,7 +18,6 @@ type canonical struct {
//
// Note: If the provided domain is considered invalid by url.Parse or otherwise
// returns an empty scheme or host, clients are not re-directed.
-// not re-directed.
//
// Example:
//
@@ -54,7 +53,11 @@ func (c canonical) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if !strings.EqualFold(cleanHost(r.Host), dest.Host) {
// Re-build the destination URL
dest := dest.Scheme + "://" + dest.Host + r.URL.Path
+ if r.URL.RawQuery != "" {
+ dest += "?" + r.URL.RawQuery
+ }
http.Redirect(w, r, dest, c.code)
+ return
}
c.h.ServeHTTP(w, r)
diff --git a/vendor/github.com/gorilla/handlers/compress.go b/vendor/github.com/gorilla/handlers/compress.go
index 3d90e1914..1e95f1ccb 100644
--- a/vendor/github.com/gorilla/handlers/compress.go
+++ b/vendor/github.com/gorilla/handlers/compress.go
@@ -10,75 +10,134 @@ import (
"io"
"net/http"
"strings"
+
+ "github.com/felixge/httpsnoop"
)
+const acceptEncoding string = "Accept-Encoding"
+
type compressResponseWriter struct {
- io.Writer
- http.ResponseWriter
- http.Hijacker
+ compressor io.Writer
+ w http.ResponseWriter
}
-func (w *compressResponseWriter) Header() http.Header {
- return w.ResponseWriter.Header()
+func (cw *compressResponseWriter) WriteHeader(c int) {
+ cw.w.Header().Del("Content-Length")
+ cw.w.WriteHeader(c)
}
-func (w *compressResponseWriter) Write(b []byte) (int, error) {
- h := w.ResponseWriter.Header()
+func (cw *compressResponseWriter) Write(b []byte) (int, error) {
+ h := cw.w.Header()
if h.Get("Content-Type") == "" {
h.Set("Content-Type", http.DetectContentType(b))
}
+ h.Del("Content-Length")
+
+ return cw.compressor.Write(b)
+}
- return w.Writer.Write(b)
+func (cw *compressResponseWriter) ReadFrom(r io.Reader) (int64, error) {
+ return io.Copy(cw.compressor, r)
+}
+
+type flusher interface {
+ Flush() error
+}
+
+func (w *compressResponseWriter) Flush() {
+ // Flush compressed data if compressor supports it.
+ if f, ok := w.compressor.(flusher); ok {
+ f.Flush()
+ }
+ // Flush HTTP response.
+ if f, ok := w.w.(http.Flusher); ok {
+ f.Flush()
+ }
}
// CompressHandler gzip compresses HTTP responses for clients that support it
// via the 'Accept-Encoding' header.
+//
+// Compressing TLS traffic may leak the page contents to an attacker if the
+// page contains user input: http://security.stackexchange.com/a/102015/12208
func CompressHandler(h http.Handler) http.Handler {
+ return CompressHandlerLevel(h, gzip.DefaultCompression)
+}
+
+// CompressHandlerLevel gzip compresses HTTP responses with specified compression level
+// for clients that support it via the 'Accept-Encoding' header.
+//
+// The compression level should be gzip.DefaultCompression, gzip.NoCompression,
+// or any integer value between gzip.BestSpeed and gzip.BestCompression inclusive.
+// gzip.DefaultCompression is used in case of invalid compression level.
+func CompressHandlerLevel(h http.Handler, level int) http.Handler {
+ if level < gzip.DefaultCompression || level > gzip.BestCompression {
+ level = gzip.DefaultCompression
+ }
+
+ const (
+ gzipEncoding = "gzip"
+ flateEncoding = "deflate"
+ )
+
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- L:
- for _, enc := range strings.Split(r.Header.Get("Accept-Encoding"), ",") {
- switch strings.TrimSpace(enc) {
- case "gzip":
- w.Header().Set("Content-Encoding", "gzip")
- w.Header().Add("Vary", "Accept-Encoding")
-
- gw := gzip.NewWriter(w)
- defer gw.Close()
-
- h, hok := w.(http.Hijacker)
- if !hok { /* w is not Hijacker... oh well... */
- h = nil
- }
-
- w = &compressResponseWriter{
- Writer: gw,
- ResponseWriter: w,
- Hijacker: h,
- }
-
- break L
- case "deflate":
- w.Header().Set("Content-Encoding", "deflate")
- w.Header().Add("Vary", "Accept-Encoding")
-
- fw, _ := flate.NewWriter(w, flate.DefaultCompression)
- defer fw.Close()
-
- h, hok := w.(http.Hijacker)
- if !hok { /* w is not Hijacker... oh well... */
- h = nil
- }
-
- w = &compressResponseWriter{
- Writer: fw,
- ResponseWriter: w,
- Hijacker: h,
- }
-
- break L
+ // detect what encoding to use
+ var encoding string
+ for _, curEnc := range strings.Split(r.Header.Get(acceptEncoding), ",") {
+ curEnc = strings.TrimSpace(curEnc)
+ if curEnc == gzipEncoding || curEnc == flateEncoding {
+ encoding = curEnc
+ break
}
}
+ // always add Accept-Encoding to Vary to prevent intermediate caches corruption
+ w.Header().Add("Vary", acceptEncoding)
+
+ // if we weren't able to identify an encoding we're familiar with, pass on the
+ // request to the handler and return
+ if encoding == "" {
+ h.ServeHTTP(w, r)
+ return
+ }
+
+ if r.Header.Get("Upgrade") != "" {
+ h.ServeHTTP(w, r)
+ return
+ }
+
+ // wrap the ResponseWriter with the writer for the chosen encoding
+ var encWriter io.WriteCloser
+ if encoding == gzipEncoding {
+ encWriter, _ = gzip.NewWriterLevel(w, level)
+ } else if encoding == flateEncoding {
+ encWriter, _ = flate.NewWriter(w, level)
+ }
+ defer encWriter.Close()
+
+ w.Header().Set("Content-Encoding", encoding)
+ r.Header.Del(acceptEncoding)
+
+ cw := &compressResponseWriter{
+ w: w,
+ compressor: encWriter,
+ }
+
+ w = httpsnoop.Wrap(w, httpsnoop.Hooks{
+ Write: func(httpsnoop.WriteFunc) httpsnoop.WriteFunc {
+ return cw.Write
+ },
+ WriteHeader: func(httpsnoop.WriteHeaderFunc) httpsnoop.WriteHeaderFunc {
+ return cw.WriteHeader
+ },
+ Flush: func(httpsnoop.FlushFunc) httpsnoop.FlushFunc {
+ return cw.Flush
+ },
+ ReadFrom: func(rff httpsnoop.ReadFromFunc) httpsnoop.ReadFromFunc {
+ return cw.ReadFrom
+ },
+ })
+
h.ServeHTTP(w, r)
})
}
diff --git a/vendor/github.com/gorilla/handlers/cors.go b/vendor/github.com/gorilla/handlers/cors.go
new file mode 100644
index 000000000..0dcdffb3d
--- /dev/null
+++ b/vendor/github.com/gorilla/handlers/cors.go
@@ -0,0 +1,355 @@
+package handlers
+
+import (
+ "net/http"
+ "strconv"
+ "strings"
+)
+
+// CORSOption represents a functional option for configuring the CORS middleware.
+type CORSOption func(*cors) error
+
+type cors struct {
+ h http.Handler
+ allowedHeaders []string
+ allowedMethods []string
+ allowedOrigins []string
+ allowedOriginValidator OriginValidator
+ exposedHeaders []string
+ maxAge int
+ ignoreOptions bool
+ allowCredentials bool
+ optionStatusCode int
+}
+
+// OriginValidator takes an origin string and returns whether or not that origin is allowed.
+type OriginValidator func(string) bool
+
+var (
+ defaultCorsOptionStatusCode = 200
+ defaultCorsMethods = []string{"GET", "HEAD", "POST"}
+ defaultCorsHeaders = []string{"Accept", "Accept-Language", "Content-Language", "Origin"}
+ // (WebKit/Safari v9 sends the Origin header by default in AJAX requests)
+)
+
+const (
+ corsOptionMethod string = "OPTIONS"
+ corsAllowOriginHeader string = "Access-Control-Allow-Origin"
+ corsExposeHeadersHeader string = "Access-Control-Expose-Headers"
+ corsMaxAgeHeader string = "Access-Control-Max-Age"
+ corsAllowMethodsHeader string = "Access-Control-Allow-Methods"
+ corsAllowHeadersHeader string = "Access-Control-Allow-Headers"
+ corsAllowCredentialsHeader string = "Access-Control-Allow-Credentials"
+ corsRequestMethodHeader string = "Access-Control-Request-Method"
+ corsRequestHeadersHeader string = "Access-Control-Request-Headers"
+ corsOriginHeader string = "Origin"
+ corsVaryHeader string = "Vary"
+ corsOriginMatchAll string = "*"
+)
+
+func (ch *cors) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ origin := r.Header.Get(corsOriginHeader)
+ if !ch.isOriginAllowed(origin) {
+ if r.Method != corsOptionMethod || ch.ignoreOptions {
+ ch.h.ServeHTTP(w, r)
+ }
+
+ return
+ }
+
+ if r.Method == corsOptionMethod {
+ if ch.ignoreOptions {
+ ch.h.ServeHTTP(w, r)
+ return
+ }
+
+ if _, ok := r.Header[corsRequestMethodHeader]; !ok {
+ w.WriteHeader(http.StatusBadRequest)
+ return
+ }
+
+ method := r.Header.Get(corsRequestMethodHeader)
+ if !ch.isMatch(method, ch.allowedMethods) {
+ w.WriteHeader(http.StatusMethodNotAllowed)
+ return
+ }
+
+ requestHeaders := strings.Split(r.Header.Get(corsRequestHeadersHeader), ",")
+ allowedHeaders := []string{}
+ for _, v := range requestHeaders {
+ canonicalHeader := http.CanonicalHeaderKey(strings.TrimSpace(v))
+ if canonicalHeader == "" || ch.isMatch(canonicalHeader, defaultCorsHeaders) {
+ continue
+ }
+
+ if !ch.isMatch(canonicalHeader, ch.allowedHeaders) {
+ w.WriteHeader(http.StatusForbidden)
+ return
+ }
+
+ allowedHeaders = append(allowedHeaders, canonicalHeader)
+ }
+
+ if len(allowedHeaders) > 0 {
+ w.Header().Set(corsAllowHeadersHeader, strings.Join(allowedHeaders, ","))
+ }
+
+ if ch.maxAge > 0 {
+ w.Header().Set(corsMaxAgeHeader, strconv.Itoa(ch.maxAge))
+ }
+
+ if !ch.isMatch(method, defaultCorsMethods) {
+ w.Header().Set(corsAllowMethodsHeader, method)
+ }
+ } else {
+ if len(ch.exposedHeaders) > 0 {
+ w.Header().Set(corsExposeHeadersHeader, strings.Join(ch.exposedHeaders, ","))
+ }
+ }
+
+ if ch.allowCredentials {
+ w.Header().Set(corsAllowCredentialsHeader, "true")
+ }
+
+ if len(ch.allowedOrigins) > 1 {
+ w.Header().Set(corsVaryHeader, corsOriginHeader)
+ }
+
+ returnOrigin := origin
+ if ch.allowedOriginValidator == nil && len(ch.allowedOrigins) == 0 {
+ returnOrigin = "*"
+ } else {
+ for _, o := range ch.allowedOrigins {
+ // A configuration of * is different than explicitly setting an allowed
+ // origin. Returning arbitrary origin headers in an access control allow
+ // origin header is unsafe and is not required by any use case.
+ if o == corsOriginMatchAll {
+ returnOrigin = "*"
+ break
+ }
+ }
+ }
+ w.Header().Set(corsAllowOriginHeader, returnOrigin)
+
+ if r.Method == corsOptionMethod {
+ w.WriteHeader(ch.optionStatusCode)
+ return
+ }
+ ch.h.ServeHTTP(w, r)
+}
+
+// CORS provides Cross-Origin Resource Sharing middleware.
+// Example:
+//
+// import (
+// "net/http"
+//
+// "github.com/gorilla/handlers"
+// "github.com/gorilla/mux"
+// )
+//
+// func main() {
+// r := mux.NewRouter()
+// r.HandleFunc("/users", UserEndpoint)
+// r.HandleFunc("/projects", ProjectEndpoint)
+//
+// // Apply the CORS middleware to our top-level router, with the defaults.
+// http.ListenAndServe(":8000", handlers.CORS()(r))
+// }
+//
+func CORS(opts ...CORSOption) func(http.Handler) http.Handler {
+ return func(h http.Handler) http.Handler {
+ ch := parseCORSOptions(opts...)
+ ch.h = h
+ return ch
+ }
+}
+
+func parseCORSOptions(opts ...CORSOption) *cors {
+ ch := &cors{
+ allowedMethods: defaultCorsMethods,
+ allowedHeaders: defaultCorsHeaders,
+ allowedOrigins: []string{},
+ optionStatusCode: defaultCorsOptionStatusCode,
+ }
+
+ for _, option := range opts {
+ option(ch)
+ }
+
+ return ch
+}
+
+//
+// Functional options for configuring CORS.
+//
+
+// AllowedHeaders adds the provided headers to the list of allowed headers in a
+// CORS request.
+// This is an append operation so the headers Accept, Accept-Language,
+// and Content-Language are always allowed.
+// Content-Type must be explicitly declared if accepting Content-Types other than
+// application/x-www-form-urlencoded, multipart/form-data, or text/plain.
+func AllowedHeaders(headers []string) CORSOption {
+ return func(ch *cors) error {
+ for _, v := range headers {
+ normalizedHeader := http.CanonicalHeaderKey(strings.TrimSpace(v))
+ if normalizedHeader == "" {
+ continue
+ }
+
+ if !ch.isMatch(normalizedHeader, ch.allowedHeaders) {
+ ch.allowedHeaders = append(ch.allowedHeaders, normalizedHeader)
+ }
+ }
+
+ return nil
+ }
+}
+
+// AllowedMethods can be used to explicitly allow methods in the
+// Access-Control-Allow-Methods header.
+// This is a replacement operation so you must also
+// pass GET, HEAD, and POST if you wish to support those methods.
+func AllowedMethods(methods []string) CORSOption {
+ return func(ch *cors) error {
+ ch.allowedMethods = []string{}
+ for _, v := range methods {
+ normalizedMethod := strings.ToUpper(strings.TrimSpace(v))
+ if normalizedMethod == "" {
+ continue
+ }
+
+ if !ch.isMatch(normalizedMethod, ch.allowedMethods) {
+ ch.allowedMethods = append(ch.allowedMethods, normalizedMethod)
+ }
+ }
+
+ return nil
+ }
+}
+
+// AllowedOrigins sets the allowed origins for CORS requests, as used in the
+// 'Allow-Access-Control-Origin' HTTP header.
+// Note: Passing in a []string{"*"} will allow any domain.
+func AllowedOrigins(origins []string) CORSOption {
+ return func(ch *cors) error {
+ for _, v := range origins {
+ if v == corsOriginMatchAll {
+ ch.allowedOrigins = []string{corsOriginMatchAll}
+ return nil
+ }
+ }
+
+ ch.allowedOrigins = origins
+ return nil
+ }
+}
+
+// AllowedOriginValidator sets a function for evaluating allowed origins in CORS requests, represented by the
+// 'Allow-Access-Control-Origin' HTTP header.
+func AllowedOriginValidator(fn OriginValidator) CORSOption {
+ return func(ch *cors) error {
+ ch.allowedOriginValidator = fn
+ return nil
+ }
+}
+
+// OptionStatusCode sets a custom status code on the OPTIONS requests.
+// Default behaviour sets it to 200 to reflect best practices. This is option is not mandatory
+// and can be used if you need a custom status code (i.e 204).
+//
+// More informations on the spec:
+// https://fetch.spec.whatwg.org/#cors-preflight-fetch
+func OptionStatusCode(code int) CORSOption {
+ return func(ch *cors) error {
+ ch.optionStatusCode = code
+ return nil
+ }
+}
+
+// ExposedHeaders can be used to specify headers that are available
+// and will not be stripped out by the user-agent.
+func ExposedHeaders(headers []string) CORSOption {
+ return func(ch *cors) error {
+ ch.exposedHeaders = []string{}
+ for _, v := range headers {
+ normalizedHeader := http.CanonicalHeaderKey(strings.TrimSpace(v))
+ if normalizedHeader == "" {
+ continue
+ }
+
+ if !ch.isMatch(normalizedHeader, ch.exposedHeaders) {
+ ch.exposedHeaders = append(ch.exposedHeaders, normalizedHeader)
+ }
+ }
+
+ return nil
+ }
+}
+
+// MaxAge determines the maximum age (in seconds) between preflight requests. A
+// maximum of 10 minutes is allowed. An age above this value will default to 10
+// minutes.
+func MaxAge(age int) CORSOption {
+ return func(ch *cors) error {
+ // Maximum of 10 minutes.
+ if age > 600 {
+ age = 600
+ }
+
+ ch.maxAge = age
+ return nil
+ }
+}
+
+// IgnoreOptions causes the CORS middleware to ignore OPTIONS requests, instead
+// passing them through to the next handler. This is useful when your application
+// or framework has a pre-existing mechanism for responding to OPTIONS requests.
+func IgnoreOptions() CORSOption {
+ return func(ch *cors) error {
+ ch.ignoreOptions = true
+ return nil
+ }
+}
+
+// AllowCredentials can be used to specify that the user agent may pass
+// authentication details along with the request.
+func AllowCredentials() CORSOption {
+ return func(ch *cors) error {
+ ch.allowCredentials = true
+ return nil
+ }
+}
+
+func (ch *cors) isOriginAllowed(origin string) bool {
+ if origin == "" {
+ return false
+ }
+
+ if ch.allowedOriginValidator != nil {
+ return ch.allowedOriginValidator(origin)
+ }
+
+ if len(ch.allowedOrigins) == 0 {
+ return true
+ }
+
+ for _, allowedOrigin := range ch.allowedOrigins {
+ if allowedOrigin == origin || allowedOrigin == corsOriginMatchAll {
+ return true
+ }
+ }
+
+ return false
+}
+
+func (ch *cors) isMatch(needle string, haystack []string) bool {
+ for _, v := range haystack {
+ if v == needle {
+ return true
+ }
+ }
+
+ return false
+}
diff --git a/vendor/github.com/gorilla/handlers/go.mod b/vendor/github.com/gorilla/handlers/go.mod
new file mode 100644
index 000000000..58e6a85ec
--- /dev/null
+++ b/vendor/github.com/gorilla/handlers/go.mod
@@ -0,0 +1,5 @@
+module github.com/gorilla/handlers
+
+go 1.14
+
+require github.com/felixge/httpsnoop v1.0.1
diff --git a/vendor/github.com/gorilla/handlers/go.sum b/vendor/github.com/gorilla/handlers/go.sum
new file mode 100644
index 000000000..8c2645804
--- /dev/null
+++ b/vendor/github.com/gorilla/handlers/go.sum
@@ -0,0 +1,2 @@
+github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ=
+github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
diff --git a/vendor/github.com/gorilla/handlers/handlers.go b/vendor/github.com/gorilla/handlers/handlers.go
index c3c20e5b9..0509482ad 100644
--- a/vendor/github.com/gorilla/handlers/handlers.go
+++ b/vendor/github.com/gorilla/handlers/handlers.go
@@ -7,27 +7,22 @@ package handlers
import (
"bufio"
"fmt"
- "io"
"net"
"net/http"
- "net/url"
"sort"
- "strconv"
"strings"
- "time"
- "unicode/utf8"
)
-// MethodHandler is an http.Handler that dispatches to a handler whose key in the MethodHandler's
-// map matches the name of the HTTP request's method, eg: GET
+// MethodHandler is an http.Handler that dispatches to a handler whose key in the
+// MethodHandler's map matches the name of the HTTP request's method, eg: GET
//
-// If the request's method is OPTIONS and OPTIONS is not a key in the map then the handler
-// responds with a status of 200 and sets the Allow header to a comma-separated list of
-// available methods.
+// If the request's method is OPTIONS and OPTIONS is not a key in the map then
+// the handler responds with a status of 200 and sets the Allow header to a
+// comma-separated list of available methods.
//
-// If the request's method doesn't match any of its keys the handler responds with
-// a status of 405, Method not allowed and sets the Allow header to a comma-separated list
-// of available methods.
+// If the request's method doesn't match any of its keys the handler responds
+// with a status of HTTP 405 "Method Not Allowed" and sets the Allow header to a
+// comma-separated list of available methods.
type MethodHandler map[string]http.Handler
func (h MethodHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
@@ -48,74 +43,15 @@ func (h MethodHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
}
}
-// loggingHandler is the http.Handler implementation for LoggingHandlerTo and its friends
-type loggingHandler struct {
- writer io.Writer
- handler http.Handler
-}
-
-// combinedLoggingHandler is the http.Handler implementation for LoggingHandlerTo and its friends
-type combinedLoggingHandler struct {
- writer io.Writer
- handler http.Handler
-}
-
-func (h loggingHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
- t := time.Now()
- logger := makeLogger(w)
- url := *req.URL
- h.handler.ServeHTTP(logger, req)
- writeLog(h.writer, req, url, t, logger.Status(), logger.Size())
-}
-
-func (h combinedLoggingHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
- t := time.Now()
- logger := makeLogger(w)
- url := *req.URL
- h.handler.ServeHTTP(logger, req)
- writeCombinedLog(h.writer, req, url, t, logger.Status(), logger.Size())
-}
-
-func makeLogger(w http.ResponseWriter) loggingResponseWriter {
- var logger loggingResponseWriter = &responseLogger{w: w}
- if _, ok := w.(http.Hijacker); ok {
- logger = &hijackLogger{responseLogger{w: w}}
- }
- h, ok1 := logger.(http.Hijacker)
- c, ok2 := w.(http.CloseNotifier)
- if ok1 && ok2 {
- return hijackCloseNotifier{logger, h, c}
- }
- if ok2 {
- return &closeNotifyWriter{logger, c}
- }
- return logger
-}
-
-type loggingResponseWriter interface {
- http.ResponseWriter
- http.Flusher
- Status() int
- Size() int
-}
-
-// responseLogger is wrapper of http.ResponseWriter that keeps track of its HTTP status
-// code and body size
+// responseLogger is wrapper of http.ResponseWriter that keeps track of its HTTP
+// status code and body size
type responseLogger struct {
w http.ResponseWriter
status int
size int
}
-func (l *responseLogger) Header() http.Header {
- return l.w.Header()
-}
-
func (l *responseLogger) Write(b []byte) (int, error) {
- if l.status == 0 {
- // The status will be StatusOK if WriteHeader has not been called yet
- l.status = http.StatusOK
- }
size, err := l.w.Write(b)
l.size += size
return size, err
@@ -134,187 +70,18 @@ func (l *responseLogger) Size() int {
return l.size
}
-func (l *responseLogger) Flush() {
- f, ok := l.w.(http.Flusher)
- if ok {
- f.Flush()
- }
-}
-
-type hijackLogger struct {
- responseLogger
-}
-
-func (l *hijackLogger) Hijack() (net.Conn, *bufio.ReadWriter, error) {
- h := l.responseLogger.w.(http.Hijacker)
- conn, rw, err := h.Hijack()
- if err == nil && l.responseLogger.status == 0 {
- // The status will be StatusSwitchingProtocols if there was no error and WriteHeader has not been called yet
- l.responseLogger.status = http.StatusSwitchingProtocols
+func (l *responseLogger) Hijack() (net.Conn, *bufio.ReadWriter, error) {
+ conn, rw, err := l.w.(http.Hijacker).Hijack()
+ if err == nil && l.status == 0 {
+ // The status will be StatusSwitchingProtocols if there was no error and
+ // WriteHeader has not been called yet
+ l.status = http.StatusSwitchingProtocols
}
return conn, rw, err
}
-type closeNotifyWriter struct {
- loggingResponseWriter
- http.CloseNotifier
-}
-
-type hijackCloseNotifier struct {
- loggingResponseWriter
- http.Hijacker
- http.CloseNotifier
-}
-
-const lowerhex = "0123456789abcdef"
-
-func appendQuoted(buf []byte, s string) []byte {
- var runeTmp [utf8.UTFMax]byte
- for width := 0; len(s) > 0; s = s[width:] {
- r := rune(s[0])
- width = 1
- if r >= utf8.RuneSelf {
- r, width = utf8.DecodeRuneInString(s)
- }
- if width == 1 && r == utf8.RuneError {
- buf = append(buf, `\x`...)
- buf = append(buf, lowerhex[s[0]>>4])
- buf = append(buf, lowerhex[s[0]&0xF])
- continue
- }
- if r == rune('"') || r == '\\' { // always backslashed
- buf = append(buf, '\\')
- buf = append(buf, byte(r))
- continue
- }
- if strconv.IsPrint(r) {
- n := utf8.EncodeRune(runeTmp[:], r)
- buf = append(buf, runeTmp[:n]...)
- continue
- }
- switch r {
- case '\a':
- buf = append(buf, `\a`...)
- case '\b':
- buf = append(buf, `\b`...)
- case '\f':
- buf = append(buf, `\f`...)
- case '\n':
- buf = append(buf, `\n`...)
- case '\r':
- buf = append(buf, `\r`...)
- case '\t':
- buf = append(buf, `\t`...)
- case '\v':
- buf = append(buf, `\v`...)
- default:
- switch {
- case r < ' ':
- buf = append(buf, `\x`...)
- buf = append(buf, lowerhex[s[0]>>4])
- buf = append(buf, lowerhex[s[0]&0xF])
- case r > utf8.MaxRune:
- r = 0xFFFD
- fallthrough
- case r < 0x10000:
- buf = append(buf, `\u`...)
- for s := 12; s >= 0; s -= 4 {
- buf = append(buf, lowerhex[r>>uint(s)&0xF])
- }
- default:
- buf = append(buf, `\U`...)
- for s := 28; s >= 0; s -= 4 {
- buf = append(buf, lowerhex[r>>uint(s)&0xF])
- }
- }
- }
- }
- return buf
-
-}
-
-// buildCommonLogLine builds a log entry for req in Apache Common Log Format.
-// ts is the timestamp with which the entry should be logged.
-// status and size are used to provide the response HTTP status and size.
-func buildCommonLogLine(req *http.Request, url url.URL, ts time.Time, status int, size int) []byte {
- username := "-"
- if url.User != nil {
- if name := url.User.Username(); name != "" {
- username = name
- }
- }
-
- host, _, err := net.SplitHostPort(req.RemoteAddr)
-
- if err != nil {
- host = req.RemoteAddr
- }
-
- uri := url.RequestURI()
-
- buf := make([]byte, 0, 3*(len(host)+len(username)+len(req.Method)+len(uri)+len(req.Proto)+50)/2)
- buf = append(buf, host...)
- buf = append(buf, " - "...)
- buf = append(buf, username...)
- buf = append(buf, " ["...)
- buf = append(buf, ts.Format("02/Jan/2006:15:04:05 -0700")...)
- buf = append(buf, `] "`...)
- buf = append(buf, req.Method...)
- buf = append(buf, " "...)
- buf = appendQuoted(buf, uri)
- buf = append(buf, " "...)
- buf = append(buf, req.Proto...)
- buf = append(buf, `" `...)
- buf = append(buf, strconv.Itoa(status)...)
- buf = append(buf, " "...)
- buf = append(buf, strconv.Itoa(size)...)
- return buf
-}
-
-// writeLog writes a log entry for req to w in Apache Common Log Format.
-// ts is the timestamp with which the entry should be logged.
-// status and size are used to provide the response HTTP status and size.
-func writeLog(w io.Writer, req *http.Request, url url.URL, ts time.Time, status, size int) {
- buf := buildCommonLogLine(req, url, ts, status, size)
- buf = append(buf, '\n')
- w.Write(buf)
-}
-
-// writeCombinedLog writes a log entry for req to w in Apache Combined Log Format.
-// ts is the timestamp with which the entry should be logged.
-// status and size are used to provide the response HTTP status and size.
-func writeCombinedLog(w io.Writer, req *http.Request, url url.URL, ts time.Time, status, size int) {
- buf := buildCommonLogLine(req, url, ts, status, size)
- buf = append(buf, ` "`...)
- buf = appendQuoted(buf, req.Referer())
- buf = append(buf, `" "`...)
- buf = appendQuoted(buf, req.UserAgent())
- buf = append(buf, '"', '\n')
- w.Write(buf)
-}
-
-// CombinedLoggingHandler return a http.Handler that wraps h and logs requests to out in
-// Apache Combined Log Format.
-//
-// See http://httpd.apache.org/docs/2.2/logs.html#combined for a description of this format.
-//
-// LoggingHandler always sets the ident field of the log to -
-func CombinedLoggingHandler(out io.Writer, h http.Handler) http.Handler {
- return combinedLoggingHandler{out, h}
-}
-
-// LoggingHandler return a http.Handler that wraps h and logs requests to out in
-// Apache Common Log Format (CLF).
-//
-// See http://httpd.apache.org/docs/2.2/logs.html#common for a description of this format.
-//
-// LoggingHandler always sets the ident field of the log to -
-func LoggingHandler(out io.Writer, h http.Handler) http.Handler {
- return loggingHandler{out, h}
-}
-
-// isContentType validates the Content-Type header
-// is contentType. That is, its type and subtype match.
+// isContentType validates the Content-Type header matches the supplied
+// contentType. That is, its type and subtype match.
func isContentType(h http.Header, contentType string) bool {
ct := h.Get("Content-Type")
if i := strings.IndexRune(ct, ';'); i != -1 {
@@ -323,9 +90,9 @@ func isContentType(h http.Header, contentType string) bool {
return ct == contentType
}
-// ContentTypeHandler wraps and returns a http.Handler, validating the request content type
-// is acompatible with the contentTypes list.
-// It writes a HTTP 415 error if that fails.
+// ContentTypeHandler wraps and returns a http.Handler, validating the request
+// content type is compatible with the contentTypes list. It writes a HTTP 415
+// error if that fails.
//
// Only PUT, POST, and PATCH requests are considered.
func ContentTypeHandler(h http.Handler, contentTypes ...string) http.Handler {
@@ -354,12 +121,14 @@ const (
HTTPMethodOverrideFormKey = "_method"
)
-// HTTPMethodOverrideHandler wraps and returns a http.Handler which checks for the X-HTTP-Method-Override header
-// or the _method form key, and overrides (if valid) request.Method with its value.
+// HTTPMethodOverrideHandler wraps and returns a http.Handler which checks for
+// the X-HTTP-Method-Override header or the _method form key, and overrides (if
+// valid) request.Method with its value.
//
-// This is especially useful for http clients that don't support many http verbs.
-// It isn't secure to override e.g a GET to a POST, so only POST requests are considered.
-// Likewise, the override method can only be a "write" method: PUT, PATCH or DELETE.
+// This is especially useful for HTTP clients that don't support many http verbs.
+// It isn't secure to override e.g a GET to a POST, so only POST requests are
+// considered. Likewise, the override method can only be a "write" method: PUT,
+// PATCH or DELETE.
//
// Form method takes precedence over header method.
func HTTPMethodOverrideHandler(h http.Handler) http.Handler {
diff --git a/vendor/github.com/gorilla/handlers/logging.go b/vendor/github.com/gorilla/handlers/logging.go
new file mode 100644
index 000000000..228465eba
--- /dev/null
+++ b/vendor/github.com/gorilla/handlers/logging.go
@@ -0,0 +1,244 @@
+// Copyright 2013 The Gorilla Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package handlers
+
+import (
+ "io"
+ "net"
+ "net/http"
+ "net/url"
+ "strconv"
+ "time"
+ "unicode/utf8"
+
+ "github.com/felixge/httpsnoop"
+)
+
+// Logging
+
+// LogFormatterParams is the structure any formatter will be handed when time to log comes
+type LogFormatterParams struct {
+ Request *http.Request
+ URL url.URL
+ TimeStamp time.Time
+ StatusCode int
+ Size int
+}
+
+// LogFormatter gives the signature of the formatter function passed to CustomLoggingHandler
+type LogFormatter func(writer io.Writer, params LogFormatterParams)
+
+// loggingHandler is the http.Handler implementation for LoggingHandlerTo and its
+// friends
+
+type loggingHandler struct {
+ writer io.Writer
+ handler http.Handler
+ formatter LogFormatter
+}
+
+func (h loggingHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+ t := time.Now()
+ logger, w := makeLogger(w)
+ url := *req.URL
+
+ h.handler.ServeHTTP(w, req)
+ if req.MultipartForm != nil {
+ req.MultipartForm.RemoveAll()
+ }
+
+ params := LogFormatterParams{
+ Request: req,
+ URL: url,
+ TimeStamp: t,
+ StatusCode: logger.Status(),
+ Size: logger.Size(),
+ }
+
+ h.formatter(h.writer, params)
+}
+
+func makeLogger(w http.ResponseWriter) (*responseLogger, http.ResponseWriter) {
+ logger := &responseLogger{w: w, status: http.StatusOK}
+ return logger, httpsnoop.Wrap(w, httpsnoop.Hooks{
+ Write: func(httpsnoop.WriteFunc) httpsnoop.WriteFunc {
+ return logger.Write
+ },
+ WriteHeader: func(httpsnoop.WriteHeaderFunc) httpsnoop.WriteHeaderFunc {
+ return logger.WriteHeader
+ },
+ })
+}
+
+const lowerhex = "0123456789abcdef"
+
+func appendQuoted(buf []byte, s string) []byte {
+ var runeTmp [utf8.UTFMax]byte
+ for width := 0; len(s) > 0; s = s[width:] {
+ r := rune(s[0])
+ width = 1
+ if r >= utf8.RuneSelf {
+ r, width = utf8.DecodeRuneInString(s)
+ }
+ if width == 1 && r == utf8.RuneError {
+ buf = append(buf, `\x`...)
+ buf = append(buf, lowerhex[s[0]>>4])
+ buf = append(buf, lowerhex[s[0]&0xF])
+ continue
+ }
+ if r == rune('"') || r == '\\' { // always backslashed
+ buf = append(buf, '\\')
+ buf = append(buf, byte(r))
+ continue
+ }
+ if strconv.IsPrint(r) {
+ n := utf8.EncodeRune(runeTmp[:], r)
+ buf = append(buf, runeTmp[:n]...)
+ continue
+ }
+ switch r {
+ case '\a':
+ buf = append(buf, `\a`...)
+ case '\b':
+ buf = append(buf, `\b`...)
+ case '\f':
+ buf = append(buf, `\f`...)
+ case '\n':
+ buf = append(buf, `\n`...)
+ case '\r':
+ buf = append(buf, `\r`...)
+ case '\t':
+ buf = append(buf, `\t`...)
+ case '\v':
+ buf = append(buf, `\v`...)
+ default:
+ switch {
+ case r < ' ':
+ buf = append(buf, `\x`...)
+ buf = append(buf, lowerhex[s[0]>>4])
+ buf = append(buf, lowerhex[s[0]&0xF])
+ case r > utf8.MaxRune:
+ r = 0xFFFD
+ fallthrough
+ case r < 0x10000:
+ buf = append(buf, `\u`...)
+ for s := 12; s >= 0; s -= 4 {
+ buf = append(buf, lowerhex[r>>uint(s)&0xF])
+ }
+ default:
+ buf = append(buf, `\U`...)
+ for s := 28; s >= 0; s -= 4 {
+ buf = append(buf, lowerhex[r>>uint(s)&0xF])
+ }
+ }
+ }
+ }
+ return buf
+}
+
+// buildCommonLogLine builds a log entry for req in Apache Common Log Format.
+// ts is the timestamp with which the entry should be logged.
+// status and size are used to provide the response HTTP status and size.
+func buildCommonLogLine(req *http.Request, url url.URL, ts time.Time, status int, size int) []byte {
+ username := "-"
+ if url.User != nil {
+ if name := url.User.Username(); name != "" {
+ username = name
+ }
+ }
+
+ host, _, err := net.SplitHostPort(req.RemoteAddr)
+ if err != nil {
+ host = req.RemoteAddr
+ }
+
+ uri := req.RequestURI
+
+ // Requests using the CONNECT method over HTTP/2.0 must use
+ // the authority field (aka r.Host) to identify the target.
+ // Refer: https://httpwg.github.io/specs/rfc7540.html#CONNECT
+ if req.ProtoMajor == 2 && req.Method == "CONNECT" {
+ uri = req.Host
+ }
+ if uri == "" {
+ uri = url.RequestURI()
+ }
+
+ buf := make([]byte, 0, 3*(len(host)+len(username)+len(req.Method)+len(uri)+len(req.Proto)+50)/2)
+ buf = append(buf, host...)
+ buf = append(buf, " - "...)
+ buf = append(buf, username...)
+ buf = append(buf, " ["...)
+ buf = append(buf, ts.Format("02/Jan/2006:15:04:05 -0700")...)
+ buf = append(buf, `] "`...)
+ buf = append(buf, req.Method...)
+ buf = append(buf, " "...)
+ buf = appendQuoted(buf, uri)
+ buf = append(buf, " "...)
+ buf = append(buf, req.Proto...)
+ buf = append(buf, `" `...)
+ buf = append(buf, strconv.Itoa(status)...)
+ buf = append(buf, " "...)
+ buf = append(buf, strconv.Itoa(size)...)
+ return buf
+}
+
+// writeLog writes a log entry for req to w in Apache Common Log Format.
+// ts is the timestamp with which the entry should be logged.
+// status and size are used to provide the response HTTP status and size.
+func writeLog(writer io.Writer, params LogFormatterParams) {
+ buf := buildCommonLogLine(params.Request, params.URL, params.TimeStamp, params.StatusCode, params.Size)
+ buf = append(buf, '\n')
+ writer.Write(buf)
+}
+
+// writeCombinedLog writes a log entry for req to w in Apache Combined Log Format.
+// ts is the timestamp with which the entry should be logged.
+// status and size are used to provide the response HTTP status and size.
+func writeCombinedLog(writer io.Writer, params LogFormatterParams) {
+ buf := buildCommonLogLine(params.Request, params.URL, params.TimeStamp, params.StatusCode, params.Size)
+ buf = append(buf, ` "`...)
+ buf = appendQuoted(buf, params.Request.Referer())
+ buf = append(buf, `" "`...)
+ buf = appendQuoted(buf, params.Request.UserAgent())
+ buf = append(buf, '"', '\n')
+ writer.Write(buf)
+}
+
+// CombinedLoggingHandler return a http.Handler that wraps h and logs requests to out in
+// Apache Combined Log Format.
+//
+// See http://httpd.apache.org/docs/2.2/logs.html#combined for a description of this format.
+//
+// LoggingHandler always sets the ident field of the log to -
+func CombinedLoggingHandler(out io.Writer, h http.Handler) http.Handler {
+ return loggingHandler{out, h, writeCombinedLog}
+}
+
+// LoggingHandler return a http.Handler that wraps h and logs requests to out in
+// Apache Common Log Format (CLF).
+//
+// See http://httpd.apache.org/docs/2.2/logs.html#common for a description of this format.
+//
+// LoggingHandler always sets the ident field of the log to -
+//
+// Example:
+//
+// r := mux.NewRouter()
+// r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+// w.Write([]byte("This is a catch-all route"))
+// })
+// loggedRouter := handlers.LoggingHandler(os.Stdout, r)
+// http.ListenAndServe(":1123", loggedRouter)
+//
+func LoggingHandler(out io.Writer, h http.Handler) http.Handler {
+ return loggingHandler{out, h, writeLog}
+}
+
+// CustomLoggingHandler provides a way to supply a custom log formatter
+// while taking advantage of the mechanisms in this package
+func CustomLoggingHandler(out io.Writer, h http.Handler, f LogFormatter) http.Handler {
+ return loggingHandler{out, h, f}
+}
diff --git a/vendor/github.com/gorilla/handlers/proxy_headers.go b/vendor/github.com/gorilla/handlers/proxy_headers.go
index 268de9c6a..ed939dcef 100644
--- a/vendor/github.com/gorilla/handlers/proxy_headers.go
+++ b/vendor/github.com/gorilla/handlers/proxy_headers.go
@@ -8,9 +8,11 @@ import (
var (
// De-facto standard header keys.
- xForwardedFor = http.CanonicalHeaderKey("X-Forwarded-For")
- xRealIP = http.CanonicalHeaderKey("X-Real-IP")
- xForwardedProto = http.CanonicalHeaderKey("X-Forwarded-Scheme")
+ xForwardedFor = http.CanonicalHeaderKey("X-Forwarded-For")
+ xForwardedHost = http.CanonicalHeaderKey("X-Forwarded-Host")
+ xForwardedProto = http.CanonicalHeaderKey("X-Forwarded-Proto")
+ xForwardedScheme = http.CanonicalHeaderKey("X-Forwarded-Scheme")
+ xRealIP = http.CanonicalHeaderKey("X-Real-IP")
)
var (
@@ -28,9 +30,9 @@ var (
// ProxyHeaders inspects common reverse proxy headers and sets the corresponding
// fields in the HTTP request struct. These are X-Forwarded-For and X-Real-IP
-// for the remote (client) IP address, X-Forwarded-Proto for the scheme
-// (http|https) and the RFC7239 Forwarded header, which may include both client
-// IPs and schemes.
+// for the remote (client) IP address, X-Forwarded-Proto or X-Forwarded-Scheme
+// for the scheme (http|https), X-Forwarded-Host for the host and the RFC7239
+// Forwarded header, which may include both client IPs and schemes.
//
// NOTE: This middleware should only be used when behind a reverse
// proxy like nginx, HAProxy or Apache. Reverse proxies that don't (or are
@@ -49,7 +51,10 @@ func ProxyHeaders(h http.Handler) http.Handler {
if scheme := getScheme(r); scheme != "" {
r.URL.Scheme = scheme
}
-
+ // Set the host with the value passed by the proxy
+ if r.Header.Get(xForwardedHost) != "" {
+ r.Host = r.Header.Get(xForwardedHost)
+ }
// Call the next handler in the chain.
h.ServeHTTP(w, r)
}
@@ -99,7 +104,9 @@ func getScheme(r *http.Request) string {
// Retrieve the scheme from X-Forwarded-Proto.
if proto := r.Header.Get(xForwardedProto); proto != "" {
scheme = strings.ToLower(proto)
- } else if proto := r.Header.Get(forwarded); proto != "" {
+ } else if proto = r.Header.Get(xForwardedScheme); proto != "" {
+ scheme = strings.ToLower(proto)
+ } else if proto = r.Header.Get(forwarded); proto != "" {
// match should contain at least two elements if the protocol was
// specified in the Forwarded header. The first element will always be
// the 'proto=' capture, which we ignore. In the case of multiple proto
diff --git a/vendor/github.com/gorilla/handlers/recovery.go b/vendor/github.com/gorilla/handlers/recovery.go
new file mode 100644
index 000000000..4c4c1d9c6
--- /dev/null
+++ b/vendor/github.com/gorilla/handlers/recovery.go
@@ -0,0 +1,96 @@
+package handlers
+
+import (
+ "log"
+ "net/http"
+ "runtime/debug"
+)
+
+// RecoveryHandlerLogger is an interface used by the recovering handler to print logs.
+type RecoveryHandlerLogger interface {
+ Println(...interface{})
+}
+
+type recoveryHandler struct {
+ handler http.Handler
+ logger RecoveryHandlerLogger
+ printStack bool
+}
+
+// RecoveryOption provides a functional approach to define
+// configuration for a handler; such as setting the logging
+// whether or not to print stack traces on panic.
+type RecoveryOption func(http.Handler)
+
+func parseRecoveryOptions(h http.Handler, opts ...RecoveryOption) http.Handler {
+ for _, option := range opts {
+ option(h)
+ }
+
+ return h
+}
+
+// RecoveryHandler is HTTP middleware that recovers from a panic,
+// logs the panic, writes http.StatusInternalServerError, and
+// continues to the next handler.
+//
+// Example:
+//
+// r := mux.NewRouter()
+// r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+// panic("Unexpected error!")
+// })
+//
+// http.ListenAndServe(":1123", handlers.RecoveryHandler()(r))
+func RecoveryHandler(opts ...RecoveryOption) func(h http.Handler) http.Handler {
+ return func(h http.Handler) http.Handler {
+ r := &recoveryHandler{handler: h}
+ return parseRecoveryOptions(r, opts...)
+ }
+}
+
+// RecoveryLogger is a functional option to override
+// the default logger
+func RecoveryLogger(logger RecoveryHandlerLogger) RecoveryOption {
+ return func(h http.Handler) {
+ r := h.(*recoveryHandler)
+ r.logger = logger
+ }
+}
+
+// PrintRecoveryStack is a functional option to enable
+// or disable printing stack traces on panic.
+func PrintRecoveryStack(print bool) RecoveryOption {
+ return func(h http.Handler) {
+ r := h.(*recoveryHandler)
+ r.printStack = print
+ }
+}
+
+func (h recoveryHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+ defer func() {
+ if err := recover(); err != nil {
+ w.WriteHeader(http.StatusInternalServerError)
+ h.log(err)
+ }
+ }()
+
+ h.handler.ServeHTTP(w, req)
+}
+
+func (h recoveryHandler) log(v ...interface{}) {
+ if h.logger != nil {
+ h.logger.Println(v...)
+ } else {
+ log.Println(v...)
+ }
+
+ if h.printStack {
+ stack := string(debug.Stack())
+ if h.logger != nil {
+ h.logger.Println(stack)
+ } else {
+ log.Println(stack)
+ }
+ }
+}
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/apparmor/apparmor_linux.go b/vendor/github.com/opencontainers/runc/libcontainer/apparmor/apparmor_linux.go
index 8b1483c7d..744d4e570 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/apparmor/apparmor_linux.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/apparmor/apparmor_linux.go
@@ -3,6 +3,7 @@ package apparmor
import (
"errors"
"fmt"
+ "io/ioutil"
"os"
"sync"
@@ -18,7 +19,7 @@ var (
func isEnabled() bool {
checkAppArmor.Do(func() {
if _, err := os.Stat("/sys/kernel/security/apparmor"); err == nil {
- buf, err := os.ReadFile("/sys/module/apparmor/parameters/enabled")
+ buf, err := ioutil.ReadFile("/sys/module/apparmor/parameters/enabled")
appArmorEnabled = err == nil && len(buf) > 1 && buf[0] == 'Y'
}
})
@@ -51,7 +52,7 @@ func setProcAttr(attr, value string) error {
// changeOnExec reimplements aa_change_onexec from libapparmor in Go
func changeOnExec(name string) error {
if err := setProcAttr("exec", "exec "+name); err != nil {
- return fmt.Errorf("apparmor failed to apply profile: %w", err)
+ return fmt.Errorf("apparmor failed to apply profile: %s", err)
}
return nil
}
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/apparmor/apparmor_unsupported.go b/vendor/github.com/opencontainers/runc/libcontainer/apparmor/apparmor_unsupported.go
index 684248f25..1adadafec 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/apparmor/apparmor_unsupported.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/apparmor/apparmor_unsupported.go
@@ -1,4 +1,3 @@
-//go:build !linux
// +build !linux
package apparmor
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/cgroups.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/cgroups.go
index ba2b2266c..68a346ca5 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/cgroups.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/cgroups.go
@@ -1,3 +1,5 @@
+// +build linux
+
package cgroups
import (
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/cgroups_unsupported.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/cgroups_unsupported.go
new file mode 100644
index 000000000..278d507e2
--- /dev/null
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/cgroups_unsupported.go
@@ -0,0 +1,3 @@
+// +build !linux
+
+package cgroups
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/file.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/file.go
index 0cdaf7478..5f6ab9fd6 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/file.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/file.go
@@ -2,27 +2,20 @@ package cgroups
import (
"bytes"
- "errors"
- "fmt"
"os"
- "path"
- "strconv"
"strings"
"sync"
+ "github.com/pkg/errors"
"github.com/sirupsen/logrus"
"golang.org/x/sys/unix"
)
// OpenFile opens a cgroup file in a given dir with given flags.
-// It is supposed to be used for cgroup files only, and returns
-// an error if the file is not a cgroup file.
-//
-// Arguments dir and file are joined together to form an absolute path
-// to a file being opened.
+// It is supposed to be used for cgroup files only.
func OpenFile(dir, file string, flags int) (*os.File, error) {
if dir == "" {
- return nil, fmt.Errorf("no directory specified for %s", file)
+ return nil, errors.Errorf("no directory specified for %s", file)
}
return openFile(dir, file, flags)
}
@@ -50,8 +43,7 @@ func WriteFile(dir, file, data string) error {
}
defer fd.Close()
if err := retryingWriteFile(fd, data); err != nil {
- // Having data in the error message helps in debugging.
- return fmt.Errorf("failed to write %q: %w", data, err)
+ return errors.Wrapf(err, "failed to write %q", data)
}
return nil
}
@@ -89,7 +81,7 @@ func prepareOpenat2() error {
})
if err != nil {
prepErr = &os.PathError{Op: "openat2", Path: cgroupfsDir, Err: err}
- if err != unix.ENOSYS { //nolint:errorlint // unix errors are bare
+ if err != unix.ENOSYS {
logrus.Warnf("falling back to securejoin: %s", prepErr)
} else {
logrus.Debug("openat2 not available, falling back to securejoin")
@@ -115,6 +107,8 @@ func prepareOpenat2() error {
return prepErr
}
+// OpenFile opens a cgroup file in a given dir with given flags.
+// It is supposed to be used for cgroup files only.
func openFile(dir, file string, flags int) (*os.File, error) {
mode := os.FileMode(0)
if TestMode && flags&os.O_WRONLY != 0 {
@@ -122,52 +116,34 @@ func openFile(dir, file string, flags int) (*os.File, error) {
flags |= os.O_TRUNC | os.O_CREATE
mode = 0o600
}
- path := path.Join(dir, file)
if prepareOpenat2() != nil {
- return openFallback(path, flags, mode)
+ return openFallback(dir, file, flags, mode)
}
- relPath := strings.TrimPrefix(path, cgroupfsPrefix)
- if len(relPath) == len(path) { // non-standard path, old system?
- return openFallback(path, flags, mode)
+ reldir := strings.TrimPrefix(dir, cgroupfsPrefix)
+ if len(reldir) == len(dir) { // non-standard path, old system?
+ return openFallback(dir, file, flags, mode)
}
- fd, err := unix.Openat2(cgroupFd, relPath,
+ relname := reldir + "/" + file
+ fd, err := unix.Openat2(cgroupFd, relname,
&unix.OpenHow{
Resolve: resolveFlags,
Flags: uint64(flags) | unix.O_CLOEXEC,
Mode: uint64(mode),
})
if err != nil {
- err = &os.PathError{Op: "openat2", Path: path, Err: err}
- // Check if cgroupFd is still opened to cgroupfsDir
- // (happens when this package is incorrectly used
- // across the chroot/pivot_root/mntns boundary, or
- // when /sys/fs/cgroup is remounted).
- //
- // TODO: if such usage will ever be common, amend this
- // to reopen cgroupFd and retry openat2.
- fdStr := strconv.Itoa(cgroupFd)
- fdDest, _ := os.Readlink("/proc/self/fd/" + fdStr)
- if fdDest != cgroupfsDir {
- // Wrap the error so it is clear that cgroupFd
- // is opened to an unexpected/wrong directory.
- err = fmt.Errorf("cgroupFd %s unexpectedly opened to %s != %s: %w",
- fdStr, fdDest, cgroupfsDir, err)
- }
- return nil, err
+ return nil, &os.PathError{Op: "openat2", Path: dir + "/" + file, Err: err}
}
- return os.NewFile(uintptr(fd), path), nil
+ return os.NewFile(uintptr(fd), cgroupfsPrefix+relname), nil
}
var errNotCgroupfs = errors.New("not a cgroup file")
-// Can be changed by unit tests.
-var openFallback = openAndCheck
-
-// openAndCheck is used when openat2(2) is not available. It checks the opened
+// openFallback is used when openat2(2) is not available. It checks the opened
// file is on cgroupfs, returning an error otherwise.
-func openAndCheck(path string, flags int, mode os.FileMode) (*os.File, error) {
+func openFallback(dir, file string, flags int, mode os.FileMode) (*os.File, error) {
+ path := dir + "/" + file
fd, err := os.OpenFile(path, flags, mode)
if err != nil {
return nil, err
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/getallpids.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/getallpids.go
deleted file mode 100644
index 1355a5101..000000000
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/getallpids.go
+++ /dev/null
@@ -1,27 +0,0 @@
-package cgroups
-
-import (
- "io/fs"
- "path/filepath"
-)
-
-// GetAllPids returns all pids from the cgroup identified by path, and all its
-// sub-cgroups.
-func GetAllPids(path string) ([]int, error) {
- var pids []int
- err := filepath.WalkDir(path, func(p string, d fs.DirEntry, iErr error) error {
- if iErr != nil {
- return iErr
- }
- if !d.IsDir() {
- return nil
- }
- cPids, err := readProcsFile(p)
- if err != nil {
- return err
- }
- pids = append(pids, cPids...)
- return nil
- })
- return pids, err
-}
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/stats.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/stats.go
index 40a81dd5a..e7f9c4626 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/stats.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/stats.go
@@ -1,3 +1,5 @@
+// +build linux
+
package cgroups
type ThrottlingData struct {
@@ -124,7 +126,7 @@ type BlkioStatEntry struct {
}
type BlkioStats struct {
- // number of bytes transferred to and from the block device
+ // number of bytes tranferred to and from the block device
IoServiceBytesRecursive []BlkioStatEntry `json:"io_service_bytes_recursive,omitempty"`
IoServicedRecursive []BlkioStatEntry `json:"io_serviced_recursive,omitempty"`
IoQueuedRecursive []BlkioStatEntry `json:"io_queue_recursive,omitempty"`
@@ -144,17 +146,6 @@ type HugetlbStats struct {
Failcnt uint64 `json:"failcnt"`
}
-type RdmaEntry struct {
- Device string `json:"device,omitempty"`
- HcaHandles uint32 `json:"hca_handles,omitempty"`
- HcaObjects uint32 `json:"hca_objects,omitempty"`
-}
-
-type RdmaStats struct {
- RdmaLimit []RdmaEntry `json:"rdma_limit,omitempty"`
- RdmaCurrent []RdmaEntry `json:"rdma_current,omitempty"`
-}
-
type Stats struct {
CpuStats CpuStats `json:"cpu_stats,omitempty"`
CPUSetStats CPUSetStats `json:"cpuset_stats,omitempty"`
@@ -163,7 +154,6 @@ type Stats struct {
BlkioStats BlkioStats `json:"blkio_stats,omitempty"`
// the map is in the format "size of hugepage: stats of the hugepage"
HugetlbStats map[string]HugetlbStats `json:"hugetlb_stats,omitempty"`
- RdmaStats RdmaStats `json:"rdma_stats,omitempty"`
}
func NewStats() *Stats {
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/utils.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/utils.go
index 13ebf52ab..92606525b 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/utils.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/utils.go
@@ -1,3 +1,5 @@
+// +build linux
+
package cgroups
import (
@@ -5,6 +7,7 @@ import (
"errors"
"fmt"
"io"
+ "io/ioutil"
"os"
"path/filepath"
"strconv"
@@ -20,14 +23,11 @@ import (
const (
CgroupProcesses = "cgroup.procs"
unifiedMountpoint = "/sys/fs/cgroup"
- hybridMountpoint = "/sys/fs/cgroup/unified"
)
var (
isUnifiedOnce sync.Once
isUnified bool
- isHybridOnce sync.Once
- isHybrid bool
)
// IsCgroup2UnifiedMode returns whether we are running in cgroup v2 unified mode.
@@ -49,24 +49,6 @@ func IsCgroup2UnifiedMode() bool {
return isUnified
}
-// IsCgroup2HybridMode returns whether we are running in cgroup v2 hybrid mode.
-func IsCgroup2HybridMode() bool {
- isHybridOnce.Do(func() {
- var st unix.Statfs_t
- err := unix.Statfs(hybridMountpoint, &st)
- if err != nil {
- if os.IsNotExist(err) {
- // ignore the "not found" error
- isHybrid = false
- return
- }
- panic(fmt.Sprintf("cannot statfs cgroup root: %s", err))
- }
- isHybrid = st.Type == unix.CGROUP2_SUPER_MAGIC
- })
- return isHybrid
-}
-
type Mount struct {
Mountpoint string
Root string
@@ -136,8 +118,8 @@ func GetAllSubsystems() ([]string, error) {
return subsystems, nil
}
-func readProcsFile(dir string) ([]int, error) {
- f, err := OpenFile(dir, CgroupProcesses, os.O_RDONLY)
+func readProcsFile(file string) ([]int, error) {
+ f, err := os.Open(file)
if err != nil {
return nil, err
}
@@ -228,7 +210,7 @@ func EnterPid(cgroupPaths map[string]string, pid int) error {
func rmdir(path string) error {
err := unix.Rmdir(path)
- if err == nil || err == unix.ENOENT { //nolint:errorlint // unix errors are bare
+ if err == nil || err == unix.ENOENT {
return nil
}
return &os.PathError{Op: "rmdir", Path: path, Err: err}
@@ -242,7 +224,7 @@ func RemovePath(path string) error {
return nil
}
- infos, err := os.ReadDir(path)
+ infos, err := ioutil.ReadDir(path)
if err != nil {
if os.IsNotExist(err) {
err = nil
@@ -302,61 +284,40 @@ func RemovePaths(paths map[string]string) (err error) {
return fmt.Errorf("Failed to remove paths: %v", paths)
}
-var (
- hugePageSizes []string
- initHPSOnce sync.Once
-)
-
-func HugePageSizes() []string {
- initHPSOnce.Do(func() {
- dir, err := os.OpenFile("/sys/kernel/mm/hugepages", unix.O_DIRECTORY|unix.O_RDONLY, 0)
- if err != nil {
- return
- }
- files, err := dir.Readdirnames(0)
- dir.Close()
- if err != nil {
- return
- }
-
- hugePageSizes, err = getHugePageSizeFromFilenames(files)
- if err != nil {
- logrus.Warn("HugePageSizes: ", err)
- }
- })
+func GetHugePageSize() ([]string, error) {
+ dir, err := os.OpenFile("/sys/kernel/mm/hugepages", unix.O_DIRECTORY|unix.O_RDONLY, 0)
+ if err != nil {
+ return nil, err
+ }
+ files, err := dir.Readdirnames(0)
+ dir.Close()
+ if err != nil {
+ return nil, err
+ }
- return hugePageSizes
+ return getHugePageSizeFromFilenames(files)
}
func getHugePageSizeFromFilenames(fileNames []string) ([]string, error) {
pageSizes := make([]string, 0, len(fileNames))
- var warn error
for _, file := range fileNames {
// example: hugepages-1048576kB
val := strings.TrimPrefix(file, "hugepages-")
if len(val) == len(file) {
- // Unexpected file name: no prefix found, ignore it.
+ // unexpected file name: no prefix found
continue
}
- // The suffix is always "kB" (as of Linux 5.13). If we find
- // something else, produce an error but keep going.
+ // The suffix is always "kB" (as of Linux 5.9)
eLen := len(val) - 2
val = strings.TrimSuffix(val, "kB")
if len(val) != eLen {
- // Highly unlikely.
- if warn == nil {
- warn = errors.New(file + `: invalid suffix (expected "kB")`)
- }
+ logrus.Warnf("GetHugePageSize: %s: invalid filename suffix (expected \"kB\")", file)
continue
}
size, err := strconv.Atoi(val)
if err != nil {
- // Highly unlikely.
- if warn == nil {
- warn = fmt.Errorf("%s: %w", file, err)
- }
- continue
+ return nil, err
}
// Model after https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/mm/hugetlb_cgroup.c?id=eff48ddeab782e35e58ccc8853f7386bbae9dec4#n574
// but in our case the size is in KB already.
@@ -370,12 +331,34 @@ func getHugePageSizeFromFilenames(fileNames []string) ([]string, error) {
pageSizes = append(pageSizes, val)
}
- return pageSizes, warn
+ return pageSizes, nil
}
// GetPids returns all pids, that were added to cgroup at path.
func GetPids(dir string) ([]int, error) {
- return readProcsFile(dir)
+ return readProcsFile(filepath.Join(dir, CgroupProcesses))
+}
+
+// GetAllPids returns all pids, that were added to cgroup at path and to all its
+// subcgroups.
+func GetAllPids(path string) ([]int, error) {
+ var pids []int
+ // collect pids from all sub-cgroups
+ err := filepath.Walk(path, func(p string, info os.FileInfo, iErr error) error {
+ if iErr != nil {
+ return iErr
+ }
+ if info.IsDir() || info.Name() != CgroupProcesses {
+ return nil
+ }
+ cPids, err := readProcsFile(p)
+ if err != nil {
+ return err
+ }
+ pids = append(pids, cPids...)
+ return nil
+ })
+ return pids, err
}
// WriteCgroupProc writes the specified pid into the cgroup's cgroup.procs file
@@ -393,7 +376,7 @@ func WriteCgroupProc(dir string, pid int) error {
file, err := OpenFile(dir, CgroupProcesses, os.O_WRONLY)
if err != nil {
- return fmt.Errorf("failed to write %v: %w", pid, err)
+ return fmt.Errorf("failed to write %v to %v: %v", pid, CgroupProcesses, err)
}
defer file.Close()
@@ -410,7 +393,7 @@ func WriteCgroupProc(dir string, pid int) error {
continue
}
- return fmt.Errorf("failed to write %v: %w", pid, err)
+ return fmt.Errorf("failed to write %v to %v: %v", pid, CgroupProcesses, err)
}
return err
}
@@ -463,5 +446,5 @@ func ConvertBlkIOToIOWeightValue(blkIoWeight uint16) uint64 {
if blkIoWeight == 0 {
return 0
}
- return 1 + (uint64(blkIoWeight)-10)*9999/990
+ return uint64(1 + (uint64(blkIoWeight)-10)*9999/990)
}
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/v1_utils.go b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/v1_utils.go
index 47c75f22b..95ec9dff0 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/cgroups/v1_utils.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/cgroups/v1_utils.go
@@ -46,8 +46,11 @@ func NewNotFoundError(sub string) error {
}
func IsNotFound(err error) bool {
- var nfErr *NotFoundError
- return errors.As(err, &nfErr)
+ if err == nil {
+ return false
+ }
+ _, ok := err.(*NotFoundError)
+ return ok
}
func tryDefaultPath(cgroupPath, subsystem string) string {
@@ -113,11 +116,6 @@ func FindCgroupMountpoint(cgroupPath, subsystem string) (string, error) {
return "", errUnified
}
- // If subsystem is empty, we look for the cgroupv2 hybrid path.
- if len(subsystem) == 0 {
- return hybridMountpoint, nil
- }
-
// Avoid parsing mountinfo by trying the default path first, if possible.
if path := tryDefaultPath(cgroupPath, subsystem); path != "" {
return path, nil
@@ -156,7 +154,7 @@ func findCgroupMountpointAndRootFromMI(mounts []*mountinfo.Info, cgroupPath, sub
func (m Mount) GetOwnCgroup(cgroups map[string]string) (string, error) {
if len(m.Subsystems) == 0 {
- return "", errors.New("no subsystem for mount")
+ return "", fmt.Errorf("no subsystem for mount")
}
return getControllerPath(m.Subsystems[0], cgroups)
@@ -228,11 +226,6 @@ func GetOwnCgroupPath(subsystem string) (string, error) {
return "", err
}
- // If subsystem is empty, we look for the cgroupv2 hybrid path.
- if len(subsystem) == 0 {
- return hybridMountpoint, nil
- }
-
return getCgroupPathHelper(subsystem, cgroup)
}
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_linux.go b/vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_linux.go
index 2d4a89871..5ea9d940c 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_linux.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_linux.go
@@ -28,26 +28,17 @@ type Cgroup struct {
// ScopePrefix describes prefix for the scope name
ScopePrefix string `json:"scope_prefix"`
+ // Paths represent the absolute cgroups paths to join.
+ // This takes precedence over Path.
+ Paths map[string]string
+
// Resources contains various cgroups settings to apply
*Resources
- // Systemd tells if systemd should be used to manage cgroups.
- Systemd bool
-
// SystemdProps are any additional properties for systemd,
// derived from org.systemd.property.xxx annotations.
// Ignored unless systemd is used for managing cgroups.
SystemdProps []systemdDbus.Property `json:"-"`
-
- // Rootless tells if rootless cgroups should be used.
- Rootless bool
-
- // The host UID that should own the cgroup, or nil to accept
- // the default ownership. This should only be set when the
- // cgroupfs is to be mounted read/write.
- // Not all cgroup manager implementations support changing
- // the ownership.
- OwnerUID *int `json:"owner_uid,omitempty"`
}
type Resources struct {
@@ -126,9 +117,6 @@ type Resources struct {
// Set class identifier for container's network packets
NetClsClassid uint32 `json:"net_cls_classid_u"`
- // Rdma resource restriction configuration
- Rdma map[string]LinuxRdma `json:"rdma"`
-
// Used on cgroups v2:
// CpuWeight sets a proportional bandwidth limit.
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_unsupported.go b/vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_unsupported.go
index 7e383020f..2a519f582 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_unsupported.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_unsupported.go
@@ -1,4 +1,3 @@
-//go:build !linux
// +build !linux
package configs
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/configs/config.go b/vendor/github.com/opencontainers/runc/libcontainer/configs/config.go
index c1b4a0041..4281593f0 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/configs/config.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/configs/config.go
@@ -7,10 +7,10 @@ import (
"os/exec"
"time"
- "github.com/sirupsen/logrus"
-
"github.com/opencontainers/runc/libcontainer/devices"
"github.com/opencontainers/runtime-spec/specs-go"
+ "github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
)
type Rlimit struct {
@@ -31,12 +31,10 @@ type IDMap struct {
// for syscalls. Additional architectures can be added by specifying them in
// Architectures.
type Seccomp struct {
- DefaultAction Action `json:"default_action"`
- Architectures []string `json:"architectures"`
- Syscalls []*Syscall `json:"syscalls"`
- DefaultErrnoRet *uint `json:"default_errno_ret"`
- ListenerPath string `json:"listener_path,omitempty"`
- ListenerMetadata string `json:"listener_metadata,omitempty"`
+ DefaultAction Action `json:"default_action"`
+ Architectures []string `json:"architectures"`
+ Syscalls []*Syscall `json:"syscalls"`
+ DefaultErrnoRet *uint `json:"default_errno_ret"`
}
// Action is taken upon rule match in Seccomp
@@ -49,9 +47,6 @@ const (
Allow
Trace
Log
- Notify
- KillThread
- KillProcess
)
// Operator is a comparison operator to be used when matching syscall arguments in Seccomp
@@ -251,19 +246,6 @@ const (
Poststop HookName = "poststop"
)
-// KnownHookNames returns the known hook names.
-// Used by `runc features`.
-func KnownHookNames() []string {
- return []string{
- string(Prestart), // deprecated
- string(CreateRuntime),
- string(CreateContainer),
- string(StartContainer),
- string(Poststart),
- string(Poststop),
- }
-}
-
type Capabilities struct {
// Bounding is the set of capabilities checked by the kernel.
Bounding []string
@@ -280,7 +262,7 @@ type Capabilities struct {
func (hooks HookList) RunHooks(state *specs.State) error {
for i, h := range hooks {
if err := h.Run(state); err != nil {
- return fmt.Errorf("error running hook #%d: %w", i, err)
+ return errors.Wrapf(err, "Running hook #%d:", i)
}
}
@@ -393,7 +375,7 @@ func (c Command) Run(s *specs.State) error {
go func() {
err := cmd.Wait()
if err != nil {
- err = fmt.Errorf("error running hook: %w, stdout: %s, stderr: %s", err, stdout.String(), stderr.String())
+ err = fmt.Errorf("error running hook: %v, stdout: %s, stderr: %s", err, stdout.String(), stderr.String())
}
errC <- err
}()
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/configs/config_linux.go b/vendor/github.com/opencontainers/runc/libcontainer/configs/config_linux.go
index 8c02848b7..07da10804 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/configs/config_linux.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/configs/config_linux.go
@@ -1,24 +1,17 @@
package configs
-import "errors"
-
-var (
- errNoUIDMap = errors.New("User namespaces enabled, but no uid mappings found.")
- errNoUserMap = errors.New("User namespaces enabled, but no user mapping found.")
- errNoGIDMap = errors.New("User namespaces enabled, but no gid mappings found.")
- errNoGroupMap = errors.New("User namespaces enabled, but no group mapping found.")
-)
+import "fmt"
// HostUID gets the translated uid for the process on host which could be
// different when user namespaces are enabled.
func (c Config) HostUID(containerId int) (int, error) {
if c.Namespaces.Contains(NEWUSER) {
if c.UidMappings == nil {
- return -1, errNoUIDMap
+ return -1, fmt.Errorf("User namespaces enabled, but no uid mappings found.")
}
id, found := c.hostIDFromMapping(containerId, c.UidMappings)
if !found {
- return -1, errNoUserMap
+ return -1, fmt.Errorf("User namespaces enabled, but no user mapping found.")
}
return id, nil
}
@@ -37,11 +30,11 @@ func (c Config) HostRootUID() (int, error) {
func (c Config) HostGID(containerId int) (int, error) {
if c.Namespaces.Contains(NEWUSER) {
if c.GidMappings == nil {
- return -1, errNoGIDMap
+ return -1, fmt.Errorf("User namespaces enabled, but no gid mappings found.")
}
id, found := c.hostIDFromMapping(containerId, c.GidMappings)
if !found {
- return -1, errNoGroupMap
+ return -1, fmt.Errorf("User namespaces enabled, but no group mapping found.")
}
return id, nil
}
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/configs/configs_fuzzer.go b/vendor/github.com/opencontainers/runc/libcontainer/configs/configs_fuzzer.go
index bce829e29..93bf41c8d 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/configs/configs_fuzzer.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/configs/configs_fuzzer.go
@@ -1,4 +1,3 @@
-//go:build gofuzz
// +build gofuzz
package configs
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/configs/intelrdt.go b/vendor/github.com/opencontainers/runc/libcontainer/configs/intelrdt.go
index f8d951ab8..57e9f037d 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/configs/intelrdt.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/configs/intelrdt.go
@@ -1,9 +1,6 @@
package configs
type IntelRdt struct {
- // The identity for RDT Class of Service
- ClosID string `json:"closID,omitempty"`
-
// The schema for L3 cache id and capacity bitmask (CBM)
// Format: "L3:<cache_id0>=<cbm0>;<cache_id1>=<cbm1>;..."
L3CacheSchema string `json:"l3_cache_schema,omitempty"`
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/configs/mount.go b/vendor/github.com/opencontainers/runc/libcontainer/configs/mount.go
index 784c61820..a75ff10ec 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/configs/mount.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/configs/mount.go
@@ -1,7 +1,5 @@
package configs
-import "golang.org/x/sys/unix"
-
const (
// EXT_COPYUP is a directive to copy up the contents of a directory when
// a tmpfs is mounted over it.
@@ -30,9 +28,6 @@ type Mount struct {
// Relabel source if set, "z" indicates shared, "Z" indicates unshared.
Relabel string `json:"relabel"`
- // RecAttr represents mount properties to be applied recursively (AT_RECURSIVE), see mount_setattr(2).
- RecAttr *unix.MountAttr `json:"rec_attr"`
-
// Extensions are additional flags that are specific to runc.
Extensions int `json:"extensions"`
@@ -42,7 +37,3 @@ type Mount struct {
// Optional Command to be run after Source is mounted.
PostmountCmds []Command `json:"postmount_cmds"`
}
-
-func (m *Mount) IsBind() bool {
- return m.Flags&unix.MS_BIND != 0
-}
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_syscall.go b/vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_syscall.go
index 0516dba8d..2dc7adfc9 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_syscall.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_syscall.go
@@ -1,4 +1,3 @@
-//go:build linux
// +build linux
package configs
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_syscall_unsupported.go b/vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_syscall_unsupported.go
index fbb0d4907..5d9a5c81f 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_syscall_unsupported.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_syscall_unsupported.go
@@ -1,4 +1,3 @@
-//go:build !linux && !windows
// +build !linux,!windows
package configs
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_unsupported.go b/vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_unsupported.go
index 946db30a5..cc76e2f58 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_unsupported.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_unsupported.go
@@ -1,4 +1,3 @@
-//go:build !linux
// +build !linux
package configs
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/configs/rdma.go b/vendor/github.com/opencontainers/runc/libcontainer/configs/rdma.go
deleted file mode 100644
index c69f2c802..000000000
--- a/vendor/github.com/opencontainers/runc/libcontainer/configs/rdma.go
+++ /dev/null
@@ -1,9 +0,0 @@
-package configs
-
-// LinuxRdma for Linux cgroup 'rdma' resource management (Linux 4.11)
-type LinuxRdma struct {
- // Maximum number of HCA handles that can be opened. Default is "no limit".
- HcaHandles *uint32 `json:"hca_handles,omitempty"`
- // Maximum number of HCA objects that can be created. Default is "no limit".
- HcaObjects *uint32 `json:"hca_objects,omitempty"`
-}
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/devices/device_unix.go b/vendor/github.com/opencontainers/runc/libcontainer/devices/device_unix.go
index 7d8e9fc31..6d5b3d09d 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/devices/device_unix.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/devices/device_unix.go
@@ -1,10 +1,10 @@
-//go:build !windows
// +build !windows
package devices
import (
"errors"
+ "io/ioutil"
"os"
"path/filepath"
@@ -16,8 +16,8 @@ var ErrNotADevice = errors.New("not a device node")
// Testing dependencies
var (
- unixLstat = unix.Lstat
- osReadDir = os.ReadDir
+ unixLstat = unix.Lstat
+ ioutilReadDir = ioutil.ReadDir
)
func mkDev(d *Rule) (uint64, error) {
@@ -40,7 +40,7 @@ func DeviceFromPath(path, permissions string) (*Device, error) {
var (
devType Type
mode = stat.Mode
- devNumber = uint64(stat.Rdev) //nolint:unconvert // Rdev is uint32 on e.g. MIPS.
+ devNumber = uint64(stat.Rdev)
major = unix.Major(devNumber)
minor = unix.Minor(devNumber)
)
@@ -76,7 +76,7 @@ func HostDevices() ([]*Device, error) {
// GetDevices recursively traverses a directory specified by path
// and returns all devices found there.
func GetDevices(path string) ([]*Device, error) {
- files, err := osReadDir(path)
+ files, err := ioutilReadDir(path)
if err != nil {
return nil, err
}
@@ -103,7 +103,7 @@ func GetDevices(path string) ([]*Device, error) {
}
device, err := DeviceFromPath(filepath.Join(path, f.Name()), "rwm")
if err != nil {
- if errors.Is(err, ErrNotADevice) {
+ if err == ErrNotADevice {
continue
}
if os.IsNotExist(err) {
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/user/lookup_unix.go b/vendor/github.com/opencontainers/runc/libcontainer/user/lookup_unix.go
index f95c1409f..967717a1b 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/user/lookup_unix.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/user/lookup_unix.go
@@ -1,4 +1,3 @@
-//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
package user
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/user/user.go b/vendor/github.com/opencontainers/runc/libcontainer/user/user.go
index 2473c5ead..cc7a106be 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/user/user.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/user/user.go
@@ -120,7 +120,7 @@ func ParsePasswdFileFilter(path string, filter func(User) bool) ([]User, error)
func ParsePasswdFilter(r io.Reader, filter func(User) bool) ([]User, error) {
if r == nil {
- return nil, errors.New("nil source for passwd-formatted data")
+ return nil, fmt.Errorf("nil source for passwd-formatted data")
}
var (
@@ -178,7 +178,7 @@ func ParseGroupFileFilter(path string, filter func(Group) bool) ([]Group, error)
func ParseGroupFilter(r io.Reader, filter func(Group) bool) ([]Group, error) {
if r == nil {
- return nil, errors.New("nil source for group-formatted data")
+ return nil, fmt.Errorf("nil source for group-formatted data")
}
rd := bufio.NewReader(r)
out := []Group{}
@@ -339,7 +339,7 @@ func GetExecUser(userSpec string, defaults *ExecUser, passwd, group io.Reader) (
if userArg == "" {
userArg = strconv.Itoa(user.Uid)
}
- return nil, fmt.Errorf("unable to find user %s: %w", userArg, err)
+ return nil, fmt.Errorf("unable to find user %s: %v", userArg, err)
}
var matchedUserName string
@@ -355,7 +355,7 @@ func GetExecUser(userSpec string, defaults *ExecUser, passwd, group io.Reader) (
if uidErr != nil {
// Not numeric.
- return nil, fmt.Errorf("unable to find user %s: %w", userArg, ErrNoPasswdEntries)
+ return nil, fmt.Errorf("unable to find user %s: %v", userArg, ErrNoPasswdEntries)
}
user.Uid = uidArg
@@ -390,7 +390,7 @@ func GetExecUser(userSpec string, defaults *ExecUser, passwd, group io.Reader) (
return g.Name == groupArg
})
if err != nil && group != nil {
- return nil, fmt.Errorf("unable to find groups for spec %v: %w", matchedUserName, err)
+ return nil, fmt.Errorf("unable to find groups for spec %v: %v", matchedUserName, err)
}
// Only start modifying user.Gid if it is in explicit form.
@@ -404,7 +404,7 @@ func GetExecUser(userSpec string, defaults *ExecUser, passwd, group io.Reader) (
if gidErr != nil {
// Not numeric.
- return nil, fmt.Errorf("unable to find group %s: %w", groupArg, ErrNoGroupEntries)
+ return nil, fmt.Errorf("unable to find group %s: %v", groupArg, ErrNoGroupEntries)
}
user.Gid = gidArg
@@ -445,7 +445,7 @@ func GetAdditionalGroups(additionalGroups []string, group io.Reader) ([]int, err
return false
})
if err != nil {
- return nil, fmt.Errorf("Unable to find additional groups %v: %w", additionalGroups, err)
+ return nil, fmt.Errorf("Unable to find additional groups %v: %v", additionalGroups, err)
}
}
@@ -468,8 +468,7 @@ func GetAdditionalGroups(additionalGroups []string, group io.Reader) ([]int, err
if !found {
gid, err := strconv.ParseInt(ag, 10, 64)
if err != nil {
- // Not a numeric ID either.
- return nil, fmt.Errorf("Unable to find group %s: %w", ag, ErrNoGroupEntries)
+ return nil, fmt.Errorf("Unable to find group %s", ag)
}
// Ensure gid is inside gid range.
if gid < minID || gid > maxID {
@@ -522,7 +521,7 @@ func ParseSubIDFileFilter(path string, filter func(SubID) bool) ([]SubID, error)
func ParseSubIDFilter(r io.Reader, filter func(SubID) bool) ([]SubID, error) {
if r == nil {
- return nil, errors.New("nil source for subid-formatted data")
+ return nil, fmt.Errorf("nil source for subid-formatted data")
}
var (
@@ -575,7 +574,7 @@ func ParseIDMapFileFilter(path string, filter func(IDMap) bool) ([]IDMap, error)
func ParseIDMapFilter(r io.Reader, filter func(IDMap) bool) ([]IDMap, error) {
if r == nil {
- return nil, errors.New("nil source for idmap-formatted data")
+ return nil, fmt.Errorf("nil source for idmap-formatted data")
}
var (
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/user/user_fuzzer.go b/vendor/github.com/opencontainers/runc/libcontainer/user/user_fuzzer.go
index e018eae61..8c9bb5df3 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/user/user_fuzzer.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/user/user_fuzzer.go
@@ -1,4 +1,3 @@
-//go:build gofuzz
// +build gofuzz
package user
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/userns/userns_fuzzer.go b/vendor/github.com/opencontainers/runc/libcontainer/userns/userns_fuzzer.go
index 1e00ab8b5..529f8eaea 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/userns/userns_fuzzer.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/userns/userns_fuzzer.go
@@ -1,4 +1,3 @@
-//go:build gofuzz
// +build gofuzz
package userns
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/userns/userns_unsupported.go b/vendor/github.com/opencontainers/runc/libcontainer/userns/userns_unsupported.go
index f35c13a10..f45bb0c31 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/userns/userns_unsupported.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/userns/userns_unsupported.go
@@ -1,4 +1,3 @@
-//go:build !linux
// +build !linux
package userns
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/utils/cmsg.go b/vendor/github.com/opencontainers/runc/libcontainer/utils/cmsg.go
index 7ef9da21f..c8a9364d5 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/utils/cmsg.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/utils/cmsg.go
@@ -1,3 +1,5 @@
+// +build linux
+
package utils
/*
@@ -86,11 +88,6 @@ func SendFd(socket *os.File, name string, fd uintptr) error {
if len(name) >= MaxNameLen {
return fmt.Errorf("sendfd: filename too long: %s", name)
}
- return SendFds(socket, []byte(name), int(fd))
-}
-
-// SendFds sends a list of files descriptor and msg over the given AF_UNIX socket.
-func SendFds(socket *os.File, msg []byte, fds ...int) error {
- oob := unix.UnixRights(fds...)
- return unix.Sendmsg(int(socket.Fd()), msg, oob, nil, 0)
+ oob := unix.UnixRights(int(fd))
+ return unix.Sendmsg(int(socket.Fd()), []byte(name), oob, nil, 0)
}
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/utils/utils.go b/vendor/github.com/opencontainers/runc/libcontainer/utils/utils.go
index 6b9fc3435..cd78f23e1 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/utils/utils.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/utils/utils.go
@@ -11,7 +11,7 @@ import (
"strings"
"unsafe"
- securejoin "github.com/cyphar/filepath-securejoin"
+ "github.com/cyphar/filepath-securejoin"
"golang.org/x/sys/unix"
)
@@ -33,6 +33,16 @@ func init() {
}
}
+// ResolveRootfs ensures that the current working directory is
+// not a symlink and returns the absolute path to the rootfs
+func ResolveRootfs(uncleanRootfs string) (string, error) {
+ rootfs, err := filepath.Abs(uncleanRootfs)
+ if err != nil {
+ return "", err
+ }
+ return filepath.EvalSymlinks(rootfs)
+}
+
// ExitStatus returns the correct exit status for a process based on if it
// was signaled or exited cleanly
func ExitStatus(status unix.WaitStatus) int {
@@ -110,7 +120,7 @@ func WithProcfd(root, unsafePath string, fn func(procfd string) error) error {
unsafePath = stripRoot(root, unsafePath)
path, err := securejoin.SecureJoin(root, unsafePath)
if err != nil {
- return fmt.Errorf("resolving path inside rootfs failed: %w", err)
+ return fmt.Errorf("resolving path inside rootfs failed: %v", err)
}
// Open the target path.
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/utils/utils_unix.go b/vendor/github.com/opencontainers/runc/libcontainer/utils/utils_unix.go
index 220d0b439..1576f2d4a 100644
--- a/vendor/github.com/opencontainers/runc/libcontainer/utils/utils_unix.go
+++ b/vendor/github.com/opencontainers/runc/libcontainer/utils/utils_unix.go
@@ -1,4 +1,3 @@
-//go:build !windows
// +build !windows
package utils
@@ -15,7 +14,7 @@ import (
func EnsureProcHandle(fh *os.File) error {
var buf unix.Statfs_t
if err := unix.Fstatfs(int(fh.Fd()), &buf); err != nil {
- return fmt.Errorf("ensure %s is on procfs: %w", fh.Name(), err)
+ return fmt.Errorf("ensure %s is on procfs: %v", fh.Name(), err)
}
if buf.Type != unix.PROC_SUPER_MAGIC {
return fmt.Errorf("%s is not on procfs", fh.Name())
@@ -53,7 +52,7 @@ func CloseExecFrom(minFd int) error {
// Intentionally ignore errors from unix.CloseOnExec -- the cases where
// this might fail are basically file descriptors that have already
// been closed (including and especially the one that was created when
- // os.ReadDir did the "opendir" syscall).
+ // ioutil.ReadDir did the "opendir" syscall).
unix.CloseOnExec(fd)
}
return nil
diff --git a/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go b/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go
index 6a7a91e55..c0e879448 100644
--- a/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go
+++ b/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go
@@ -15,7 +15,7 @@ type Spec struct {
// Mounts configures additional mounts (on top of Root).
Mounts []Mount `json:"mounts,omitempty"`
// Hooks configures callbacks for container lifecycle events.
- Hooks *Hooks `json:"hooks,omitempty" platform:"linux,solaris"`
+ Hooks *Hooks `json:"hooks,omitempty" platform:"linux,solaris,zos"`
// Annotations contains arbitrary metadata for the container.
Annotations map[string]string `json:"annotations,omitempty"`
@@ -27,6 +27,8 @@ type Spec struct {
Windows *Windows `json:"windows,omitempty" platform:"windows"`
// VM specifies configuration for virtual-machine-based containers.
VM *VM `json:"vm,omitempty" platform:"vm"`
+ // ZOS is platform-specific configuration for z/OS based containers.
+ ZOS *ZOS `json:"zos,omitempty" platform:"zos"`
}
// Process contains information to start a specific application inside the container.
@@ -49,7 +51,7 @@ type Process struct {
// Capabilities are Linux capabilities that are kept for the process.
Capabilities *LinuxCapabilities `json:"capabilities,omitempty" platform:"linux"`
// Rlimits specifies rlimit options to apply to the process.
- Rlimits []POSIXRlimit `json:"rlimits,omitempty" platform:"linux,solaris"`
+ Rlimits []POSIXRlimit `json:"rlimits,omitempty" platform:"linux,solaris,zos"`
// NoNewPrivileges controls whether additional privileges could be gained by processes in the container.
NoNewPrivileges bool `json:"noNewPrivileges,omitempty" platform:"linux"`
// ApparmorProfile specifies the apparmor profile for the container.
@@ -86,11 +88,11 @@ type Box struct {
// User specifies specific user (and group) information for the container process.
type User struct {
// UID is the user id.
- UID uint32 `json:"uid" platform:"linux,solaris"`
+ UID uint32 `json:"uid" platform:"linux,solaris,zos"`
// GID is the group id.
- GID uint32 `json:"gid" platform:"linux,solaris"`
+ GID uint32 `json:"gid" platform:"linux,solaris,zos"`
// Umask is the umask for the init process.
- Umask *uint32 `json:"umask,omitempty" platform:"linux,solaris"`
+ Umask *uint32 `json:"umask,omitempty" platform:"linux,solaris,zos"`
// AdditionalGids are additional group ids set for the container's process.
AdditionalGids []uint32 `json:"additionalGids,omitempty" platform:"linux,solaris"`
// Username is the user name.
@@ -110,7 +112,7 @@ type Mount struct {
// Destination is the absolute path where the mount will be placed in the container.
Destination string `json:"destination"`
// Type specifies the mount kind.
- Type string `json:"type,omitempty" platform:"linux,solaris"`
+ Type string `json:"type,omitempty" platform:"linux,solaris,zos"`
// Source specifies the source path of the mount.
Source string `json:"source,omitempty"`
// Options are fstab style mount options.
@@ -178,7 +180,7 @@ type Linux struct {
// MountLabel specifies the selinux context for the mounts in the container.
MountLabel string `json:"mountLabel,omitempty"`
// IntelRdt contains Intel Resource Director Technology (RDT) information for
- // handling resource constraints (e.g., L3 cache, memory bandwidth) for the container
+ // handling resource constraints and monitoring metrics (e.g., L3 cache, memory bandwidth) for the container
IntelRdt *LinuxIntelRdt `json:"intelRdt,omitempty"`
// Personality contains configuration for the Linux personality syscall
Personality *LinuxPersonality `json:"personality,omitempty"`
@@ -683,8 +685,9 @@ type LinuxSyscall struct {
Args []LinuxSeccompArg `json:"args,omitempty"`
}
-// LinuxIntelRdt has container runtime resource constraints for Intel RDT
-// CAT and MBA features which introduced in Linux 4.10 and 4.12 kernel
+// LinuxIntelRdt has container runtime resource constraints for Intel RDT CAT and MBA
+// features and flags enabling Intel RDT CMT and MBM features.
+// Intel RDT features are available in Linux 4.14 and newer kernel versions.
type LinuxIntelRdt struct {
// The identity for RDT Class of Service
ClosID string `json:"closID,omitempty"`
@@ -697,4 +700,36 @@ type LinuxIntelRdt struct {
// The unit of memory bandwidth is specified in "percentages" by
// default, and in "MBps" if MBA Software Controller is enabled.
MemBwSchema string `json:"memBwSchema,omitempty"`
+
+ // EnableCMT is the flag to indicate if the Intel RDT CMT is enabled. CMT (Cache Monitoring Technology) supports monitoring of
+ // the last-level cache (LLC) occupancy for the container.
+ EnableCMT bool `json:"enableCMT,omitempty"`
+
+ // EnableMBM is the flag to indicate if the Intel RDT MBM is enabled. MBM (Memory Bandwidth Monitoring) supports monitoring of
+ // total and local memory bandwidth for the container.
+ EnableMBM bool `json:"enableMBM,omitempty"`
+}
+
+// ZOS contains platform-specific configuration for z/OS based containers.
+type ZOS struct {
+ // Devices are a list of device nodes that are created for the container
+ Devices []ZOSDevice `json:"devices,omitempty"`
+}
+
+// ZOSDevice represents the mknod information for a z/OS special device file
+type ZOSDevice struct {
+ // Path to the device.
+ Path string `json:"path"`
+ // Device type, block, char, etc.
+ Type string `json:"type"`
+ // Major is the device's major number.
+ Major int64 `json:"major"`
+ // Minor is the device's minor number.
+ Minor int64 `json:"minor"`
+ // FileMode permission bits for the device.
+ FileMode *os.FileMode `json:"fileMode,omitempty"`
+ // UID of the device.
+ UID *uint32 `json:"uid,omitempty"`
+ // Gid of the device.
+ GID *uint32 `json:"gid,omitempty"`
}
diff --git a/vendor/github.com/opencontainers/runtime-tools/generate/config.go b/vendor/github.com/opencontainers/runtime-tools/generate/config.go
index f68bdde37..48f281d28 100644
--- a/vendor/github.com/opencontainers/runtime-tools/generate/config.go
+++ b/vendor/github.com/opencontainers/runtime-tools/generate/config.go
@@ -123,6 +123,13 @@ func (g *Generator) initConfigLinuxResourcesPids() {
}
}
+func (g *Generator) initConfigLinuxResourcesUnified() {
+ g.initConfigLinuxResources()
+ if g.Config.Linux.Resources.Unified == nil {
+ g.Config.Linux.Resources.Unified = map[string]string{}
+ }
+}
+
func (g *Generator) initConfigSolaris() {
g.initConfig()
if g.Config.Solaris == nil {
@@ -185,24 +192,3 @@ func (g *Generator) initConfigVM() {
g.Config.VM = &rspec.VM{}
}
}
-
-func (g *Generator) initConfigVMHypervisor() {
- g.initConfigVM()
- if &g.Config.VM.Hypervisor == nil {
- g.Config.VM.Hypervisor = rspec.VMHypervisor{}
- }
-}
-
-func (g *Generator) initConfigVMKernel() {
- g.initConfigVM()
- if &g.Config.VM.Kernel == nil {
- g.Config.VM.Kernel = rspec.VMKernel{}
- }
-}
-
-func (g *Generator) initConfigVMImage() {
- g.initConfigVM()
- if &g.Config.VM.Image == nil {
- g.Config.VM.Image = rspec.VMImage{}
- }
-}
diff --git a/vendor/github.com/opencontainers/runtime-tools/generate/generate.go b/vendor/github.com/opencontainers/runtime-tools/generate/generate.go
index 70b175362..be1f027bf 100644
--- a/vendor/github.com/opencontainers/runtime-tools/generate/generate.go
+++ b/vendor/github.com/opencontainers/runtime-tools/generate/generate.go
@@ -604,6 +604,12 @@ func (g *Generator) SetLinuxCgroupsPath(path string) {
g.Config.Linux.CgroupsPath = path
}
+// SetLinuxIntelRdtClosID sets g.Config.Linux.IntelRdt.ClosID
+func (g *Generator) SetLinuxIntelRdtClosID(clos string) {
+ g.initConfigLinuxIntelRdt()
+ g.Config.Linux.IntelRdt.ClosID = clos
+}
+
// SetLinuxIntelRdtL3CacheSchema sets g.Config.Linux.IntelRdt.L3CacheSchema
func (g *Generator) SetLinuxIntelRdtL3CacheSchema(schema string) {
g.initConfigLinuxIntelRdt()
@@ -851,6 +857,28 @@ func (g *Generator) DropLinuxResourcesHugepageLimit(pageSize string) {
}
}
+// AddLinuxResourcesUnified sets the g.Config.Linux.Resources.Unified
+func (g *Generator) SetLinuxResourcesUnified(unified map[string]string) {
+ g.initConfigLinuxResourcesUnified()
+ for k, v := range unified {
+ g.Config.Linux.Resources.Unified[k] = v
+ }
+}
+
+// AddLinuxResourcesUnified adds or updates the key-value pair from g.Config.Linux.Resources.Unified
+func (g *Generator) AddLinuxResourcesUnified(key, val string) {
+ g.initConfigLinuxResourcesUnified()
+ g.Config.Linux.Resources.Unified[key] = val
+}
+
+// DropLinuxResourcesUnified drops a key-value pair from g.Config.Linux.Resources.Unified
+func (g *Generator) DropLinuxResourcesUnified(key string) {
+ if g.Config == nil || g.Config.Linux == nil || g.Config.Linux.Resources == nil || g.Config.Linux.Resources.Unified == nil {
+ return
+ }
+ delete(g.Config.Linux.Resources.Unified, key)
+}
+
// SetLinuxResourcesMemoryLimit sets g.Config.Linux.Resources.Memory.Limit.
func (g *Generator) SetLinuxResourcesMemoryLimit(limit int64) {
g.initConfigLinuxResourcesMemory()
@@ -1025,10 +1053,9 @@ func (g *Generator) ClearPreStartHooks() {
}
// AddPreStartHook add a prestart hook into g.Config.Hooks.Prestart.
-func (g *Generator) AddPreStartHook(preStartHook rspec.Hook) error {
+func (g *Generator) AddPreStartHook(preStartHook rspec.Hook) {
g.initConfigHooks()
g.Config.Hooks.Prestart = append(g.Config.Hooks.Prestart, preStartHook)
- return nil
}
// ClearPostStopHooks clear g.Config.Hooks.Poststop.
@@ -1040,10 +1067,9 @@ func (g *Generator) ClearPostStopHooks() {
}
// AddPostStopHook adds a poststop hook into g.Config.Hooks.Poststop.
-func (g *Generator) AddPostStopHook(postStopHook rspec.Hook) error {
+func (g *Generator) AddPostStopHook(postStopHook rspec.Hook) {
g.initConfigHooks()
g.Config.Hooks.Poststop = append(g.Config.Hooks.Poststop, postStopHook)
- return nil
}
// ClearPostStartHooks clear g.Config.Hooks.Poststart.
@@ -1055,10 +1081,9 @@ func (g *Generator) ClearPostStartHooks() {
}
// AddPostStartHook adds a poststart hook into g.Config.Hooks.Poststart.
-func (g *Generator) AddPostStartHook(postStartHook rspec.Hook) error {
+func (g *Generator) AddPostStartHook(postStartHook rspec.Hook) {
g.initConfigHooks()
g.Config.Hooks.Poststart = append(g.Config.Hooks.Poststart, postStartHook)
- return nil
}
// AddMount adds a mount into g.Config.Mounts.
@@ -1560,12 +1585,8 @@ func (g *Generator) RemoveLinuxResourcesDevice(allow bool, devType string, major
return
}
}
- return
}
-// strPtr returns the pointer pointing to the string s.
-func strPtr(s string) *string { return &s }
-
// SetSyscallAction adds rules for syscalls with the specified action
func (g *Generator) SetSyscallAction(arguments seccomp.SyscallOpts) error {
g.initConfigLinuxSeccomp()
@@ -1691,14 +1712,14 @@ func (g *Generator) SetVMHypervisorPath(path string) error {
if !strings.HasPrefix(path, "/") {
return fmt.Errorf("hypervisorPath %v is not an absolute path", path)
}
- g.initConfigVMHypervisor()
+ g.initConfigVM()
g.Config.VM.Hypervisor.Path = path
return nil
}
// SetVMHypervisorParameters sets g.Config.VM.Hypervisor.Parameters
func (g *Generator) SetVMHypervisorParameters(parameters []string) {
- g.initConfigVMHypervisor()
+ g.initConfigVM()
g.Config.VM.Hypervisor.Parameters = parameters
}
@@ -1707,14 +1728,14 @@ func (g *Generator) SetVMKernelPath(path string) error {
if !strings.HasPrefix(path, "/") {
return fmt.Errorf("kernelPath %v is not an absolute path", path)
}
- g.initConfigVMKernel()
+ g.initConfigVM()
g.Config.VM.Kernel.Path = path
return nil
}
// SetVMKernelParameters sets g.Config.VM.Kernel.Parameters
func (g *Generator) SetVMKernelParameters(parameters []string) {
- g.initConfigVMKernel()
+ g.initConfigVM()
g.Config.VM.Kernel.Parameters = parameters
}
@@ -1723,7 +1744,7 @@ func (g *Generator) SetVMKernelInitRD(initrd string) error {
if !strings.HasPrefix(initrd, "/") {
return fmt.Errorf("kernelInitrd %v is not an absolute path", initrd)
}
- g.initConfigVMKernel()
+ g.initConfigVM()
g.Config.VM.Kernel.InitRD = initrd
return nil
}
@@ -1733,7 +1754,7 @@ func (g *Generator) SetVMImagePath(path string) error {
if !strings.HasPrefix(path, "/") {
return fmt.Errorf("imagePath %v is not an absolute path", path)
}
- g.initConfigVMImage()
+ g.initConfigVM()
g.Config.VM.Image.Path = path
return nil
}
@@ -1749,7 +1770,7 @@ func (g *Generator) SetVMImageFormat(format string) error {
default:
return fmt.Errorf("Commonly supported formats are: raw, qcow2, vdi, vmdk, vhd")
}
- g.initConfigVMImage()
+ g.initConfigVM()
g.Config.VM.Image.Format = format
return nil
}
diff --git a/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/consts.go b/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/consts.go
index eade5718e..f28d8f587 100644
--- a/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/consts.go
+++ b/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/consts.go
@@ -4,9 +4,4 @@ const (
seccompOverwrite = "overwrite"
seccompAppend = "append"
nothing = "nothing"
- kill = "kill"
- trap = "trap"
- trace = "trace"
- allow = "allow"
- errno = "errno"
)
diff --git a/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default_linux.go b/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default_linux.go
index 311587437..93472fba0 100644
--- a/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default_linux.go
+++ b/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default_linux.go
@@ -1,3 +1,4 @@
+//go:build linux
// +build linux
package seccomp
diff --git a/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default_unsupported.go b/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default_unsupported.go
index 589b81c16..b8c1bc26e 100644
--- a/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default_unsupported.go
+++ b/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default_unsupported.go
@@ -1,3 +1,4 @@
+//go:build !linux
// +build !linux
package seccomp
diff --git a/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/syscall_compare.go b/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/syscall_compare.go
index dbf2aec1c..5e84653a9 100644
--- a/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/syscall_compare.go
+++ b/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/syscall_compare.go
@@ -92,22 +92,6 @@ func identical(config1, config2 *rspec.LinuxSyscall) bool {
return reflect.DeepEqual(config1, config2)
}
-func identicalExceptAction(config1, config2 *rspec.LinuxSyscall) bool {
- samename := sameName(config1, config2)
- sameAction := sameAction(config1, config2)
- sameArgs := sameArgs(config1, config2)
-
- return samename && !sameAction && sameArgs
-}
-
-func identicalExceptArgs(config1, config2 *rspec.LinuxSyscall) bool {
- samename := sameName(config1, config2)
- sameAction := sameAction(config1, config2)
- sameArgs := sameArgs(config1, config2)
-
- return samename && sameAction && !sameArgs
-}
-
func sameName(config1, config2 *rspec.LinuxSyscall) bool {
return reflect.DeepEqual(config1.Names, config2.Names)
}
diff --git a/vendor/github.com/opencontainers/runtime-tools/validate/validate.go b/vendor/github.com/opencontainers/runtime-tools/validate/validate.go
index 9c3710529..2d3d42bce 100644
--- a/vendor/github.com/opencontainers/runtime-tools/validate/validate.go
+++ b/vendor/github.com/opencontainers/runtime-tools/validate/validate.go
@@ -131,9 +131,8 @@ func JSONSchemaURL(version string) (url string, err error) {
if err != nil {
return "", specerror.NewError(specerror.SpecVersionInSemVer, err, rspec.Version)
}
- configRenamedToConfigSchemaVersion, err := semver.Parse("1.0.0-rc2") // config.json became config-schema.json in 1.0.0-rc2
- if ver.Compare(configRenamedToConfigSchemaVersion) == -1 {
- return "", fmt.Errorf("unsupported configuration version (older than %s)", configRenamedToConfigSchemaVersion)
+ if ver.LT(semver.Version{Major: 1, Minor: 0, Patch: 2}) {
+ return "", errors.New("unsupported configuration version (older than 1.0.2)")
}
return fmt.Sprintf(configSchemaTemplate, version), nil
}
diff --git a/vendor/github.com/opencontainers/runtime-tools/validate/validate_linux.go b/vendor/github.com/opencontainers/runtime-tools/validate/validate_linux.go
index dcefafae7..6f1b28218 100644
--- a/vendor/github.com/opencontainers/runtime-tools/validate/validate_linux.go
+++ b/vendor/github.com/opencontainers/runtime-tools/validate/validate_linux.go
@@ -1,3 +1,4 @@
+//go:build linux
// +build linux
package validate
diff --git a/vendor/github.com/opencontainers/runtime-tools/validate/validate_unsupported.go b/vendor/github.com/opencontainers/runtime-tools/validate/validate_unsupported.go
index f150c326c..313ec3995 100644
--- a/vendor/github.com/opencontainers/runtime-tools/validate/validate_unsupported.go
+++ b/vendor/github.com/opencontainers/runtime-tools/validate/validate_unsupported.go
@@ -1,3 +1,4 @@
+//go:build !linux
// +build !linux
package validate
diff --git a/vendor/github.com/seccomp/libseccomp-golang/.travis.yml b/vendor/github.com/seccomp/libseccomp-golang/.travis.yml
index 5240d4622..feef144d1 100644
--- a/vendor/github.com/seccomp/libseccomp-golang/.travis.yml
+++ b/vendor/github.com/seccomp/libseccomp-golang/.travis.yml
@@ -19,39 +19,19 @@ os:
language: go
-jobs:
- include:
- - name: "last libseccomp 2.5.0"
- env:
- - SECCOMP_VER=2.5.0
- - SECCOMP_SHA256SUM=1ffa7038d2720ad191919816db3479295a4bcca1ec14e02f672539f4983014f3
- - name: "compat libseccomp 2.4.4"
- env:
- - SECCOMP_VER=2.4.4
- - SECCOMP_SHA256SUM=4e79738d1ef3c9b7ca9769f1f8b8d84fc17143c2c1c432e53b9c64787e0ff3eb
- - name: "compat libseccomp 2.2.1"
- env:
- - SECCOMP_VER=2.2.1
- - SECCOMP_SHA256SUM=0ba1789f54786c644af54cdffc9fd0dd0a8bb2b2ee153933f658855d2851a740
-
addons:
apt:
packages:
- build-essential
- - astyle
- - golint
- - gperf
+ # TODO: use the main libseccomp git repo instead of a distro package
+ - libseccomp2
+ - libseccomp-dev
install:
- go get -u golang.org/x/lint/golint
# run all of the tests independently, fail if any of the tests error
script:
- - wget https://github.com/seccomp/libseccomp/releases/download/v$SECCOMP_VER/libseccomp-$SECCOMP_VER.tar.gz
- - echo $SECCOMP_SHA256SUM libseccomp-$SECCOMP_VER.tar.gz | sha256sum -c
- - tar xf libseccomp-$SECCOMP_VER.tar.gz
- - pushd libseccomp-$SECCOMP_VER && ./configure --prefix=/opt/libseccomp-$SECCOMP_VER && make && sudo make install && popd
- make check-syntax
- make lint
- - PKG_CONFIG_PATH=/opt/libseccomp-$SECCOMP_VER/lib/pkgconfig LD_LIBRARY_PATH=/opt/libseccomp-$SECCOMP_VER/lib make vet
- - PKG_CONFIG_PATH=/opt/libseccomp-$SECCOMP_VER/lib/pkgconfig LD_LIBRARY_PATH=/opt/libseccomp-$SECCOMP_VER/lib make test
+ - make check
diff --git a/vendor/github.com/seccomp/libseccomp-golang/Makefile b/vendor/github.com/seccomp/libseccomp-golang/Makefile
index 38cfa852c..1ff4cc898 100644
--- a/vendor/github.com/seccomp/libseccomp-golang/Makefile
+++ b/vendor/github.com/seccomp/libseccomp-golang/Makefile
@@ -18,14 +18,8 @@ fix-syntax:
vet:
go vet -v
-# Previous bugs have made the tests freeze until the timeout. Golang default
-# timeout for tests is 10 minutes, which is too long, considering current tests
-# can be executed in less than 1 second. Reduce the timeout, so problems can
-# be noticed earlier in the CI.
-TEST_TIMEOUT=10s
-
test:
- go test -v -timeout $(TEST_TIMEOUT)
+ go test -v
lint:
@$(if $(shell which golint),true,$(error "install golint and include it in your PATH"))
diff --git a/vendor/github.com/seccomp/libseccomp-golang/README.md b/vendor/github.com/seccomp/libseccomp-golang/README.md
index 806a5ddf2..27423f2d9 100644
--- a/vendor/github.com/seccomp/libseccomp-golang/README.md
+++ b/vendor/github.com/seccomp/libseccomp-golang/README.md
@@ -2,7 +2,7 @@
===============================================================================
https://github.com/seccomp/libseccomp-golang
-[![Build Status](https://img.shields.io/travis/seccomp/libseccomp-golang/main.svg)](https://travis-ci.org/seccomp/libseccomp-golang)
+[![Build Status](https://img.shields.io/travis/seccomp/libseccomp-golang/master.svg)](https://travis-ci.org/seccomp/libseccomp-golang)
The libseccomp library provides an easy to use, platform independent, interface
to the Linux Kernel's syscall filtering mechanism. The libseccomp API is
diff --git a/vendor/github.com/seccomp/libseccomp-golang/seccomp.go b/vendor/github.com/seccomp/libseccomp-golang/seccomp.go
index e9b92e221..e489b9ebd 100644
--- a/vendor/github.com/seccomp/libseccomp-golang/seccomp.go
+++ b/vendor/github.com/seccomp/libseccomp-golang/seccomp.go
@@ -20,13 +20,6 @@ import (
// C wrapping code
-// To compile libseccomp-golang against a specific version of libseccomp:
-// cd ../libseccomp && mkdir -p prefix
-// ./configure --prefix=$PWD/prefix && make && make install
-// cd ../libseccomp-golang
-// PKG_CONFIG_PATH=$PWD/../libseccomp/prefix/lib/pkgconfig/ make
-// LD_PRELOAD=$PWD/../libseccomp/prefix/lib/libseccomp.so.2.5.0 PKG_CONFIG_PATH=$PWD/../libseccomp/prefix/lib/pkgconfig/ make test
-
// #cgo pkg-config: libseccomp
// #include <stdlib.h>
// #include <seccomp.h>
@@ -41,25 +34,19 @@ type VersionError struct {
minimum string
}
-func init() {
- // This forces the cgo libseccomp to initialize its internal API support state,
- // which is necessary on older versions of libseccomp in order to work
- // correctly.
- GetAPI()
-}
-
func (e VersionError) Error() string {
- messageStr := ""
+ format := "Libseccomp version too low: "
if e.message != "" {
- messageStr = e.message + ": "
+ format += e.message + ": "
}
- minimumStr := ""
+ format += "minimum supported is "
if e.minimum != "" {
- minimumStr = e.minimum
+ format += e.minimum + ": "
} else {
- minimumStr = "2.2.0"
+ format += "2.2.0: "
}
- return fmt.Sprintf("Libseccomp version too low: %sminimum supported is %s: detected %d.%d.%d", messageStr, minimumStr, verMajor, verMinor, verMicro)
+ format += "detected %d.%d.%d"
+ return fmt.Sprintf(format, verMajor, verMinor, verMicro)
}
// ScmpArch represents a CPU architecture. Seccomp can restrict syscalls on a
@@ -82,61 +69,9 @@ type ScmpCondition struct {
Operand2 uint64 `json:"operand_two,omitempty"`
}
-// Seccomp userspace notification structures associated with filters that use the ActNotify action.
-
-// ScmpSyscall identifies a Linux System Call by its number.
+// ScmpSyscall represents a Linux System Call
type ScmpSyscall int32
-// ScmpFd represents a file-descriptor used for seccomp userspace notifications.
-type ScmpFd int32
-
-// ScmpNotifData describes the system call context that triggered a notification.
-//
-// Syscall: the syscall number
-// Arch: the filter architecture
-// InstrPointer: address of the instruction that triggered a notification
-// Args: arguments (up to 6) for the syscall
-//
-type ScmpNotifData struct {
- Syscall ScmpSyscall `json:"syscall,omitempty"`
- Arch ScmpArch `json:"arch,omitempty"`
- InstrPointer uint64 `json:"instr_pointer,omitempty"`
- Args []uint64 `json:"args,omitempty"`
-}
-
-// ScmpNotifReq represents a seccomp userspace notification. See NotifReceive() for
-// info on how to pull such a notification.
-//
-// ID: notification ID
-// Pid: process that triggered the notification event
-// Flags: filter flags (see seccomp(2))
-// Data: system call context that triggered the notification
-//
-type ScmpNotifReq struct {
- ID uint64 `json:"id,omitempty"`
- Pid uint32 `json:"pid,omitempty"`
- Flags uint32 `json:"flags,omitempty"`
- Data ScmpNotifData `json:"data,omitempty"`
-}
-
-// ScmpNotifResp represents a seccomp userspace notification response. See NotifRespond()
-// for info on how to push such a response.
-//
-// ID: notification ID (must match the corresponding ScmpNotifReq ID)
-// Error: must be 0 if no error occurred, or an error constant from package
-// syscall (e.g., syscall.EPERM, etc). In the latter case, it's used
-// as an error return from the syscall that created the notification.
-// Val: return value for the syscall that created the notification. Only
-// relevant if Error is 0.
-// Flags: userspace notification response flag (e.g., NotifRespFlagContinue)
-//
-type ScmpNotifResp struct {
- ID uint64 `json:"id,omitempty"`
- Error int32 `json:"error,omitempty"`
- Val uint64 `json:"val,omitempty"`
- Flags uint32 `json:"flags,omitempty"`
-}
-
// Exported Constants
const (
@@ -182,10 +117,6 @@ const (
ArchS390 ScmpArch = iota
// ArchS390X represents 64-bit System z/390 syscalls
ArchS390X ScmpArch = iota
- // ArchPARISC represents 32-bit PA-RISC
- ArchPARISC ScmpArch = iota
- // ArchPARISC64 represents 64-bit PA-RISC
- ArchPARISC64 ScmpArch = iota
)
const (
@@ -199,9 +130,6 @@ const (
ActKill ScmpAction = iota
// ActTrap throws SIGSYS
ActTrap ScmpAction = iota
- // ActNotify triggers a userspace notification. This action is only usable when
- // libseccomp API level 6 or higher is supported.
- ActNotify ScmpAction = iota
// ActErrno causes the syscall to return a negative error code. This
// code can be set with the SetReturnCode method
ActErrno ScmpAction = iota
@@ -253,21 +181,6 @@ const (
CompareMaskedEqual ScmpCompareOp = iota
)
-var (
- // ErrSyscallDoesNotExist represents an error condition where
- // libseccomp is unable to resolve the syscall
- ErrSyscallDoesNotExist = fmt.Errorf("could not resolve syscall name")
-)
-
-const (
- // Userspace notification response flags
-
- // NotifRespFlagContinue tells the kernel to continue executing the system
- // call that triggered the notification. Must only be used when the notication
- // response's error is 0.
- NotifRespFlagContinue uint32 = 1
-)
-
// Helpers for types
// GetArchFromString returns an ScmpArch constant from a string representing an
@@ -310,10 +223,6 @@ func GetArchFromString(arch string) (ScmpArch, error) {
return ArchS390, nil
case "s390x":
return ArchS390X, nil
- case "parisc":
- return ArchPARISC, nil
- case "parisc64":
- return ArchPARISC64, nil
default:
return ArchInvalid, fmt.Errorf("cannot convert unrecognized string %q", arch)
}
@@ -354,10 +263,6 @@ func (a ScmpArch) String() string {
return "s390"
case ArchS390X:
return "s390x"
- case ArchPARISC:
- return "parisc"
- case ArchPARISC64:
- return "parisc64"
case ArchNative:
return "native"
case ArchInvalid:
@@ -405,8 +310,6 @@ func (a ScmpAction) String() string {
case ActTrace:
return fmt.Sprintf("Action: Notify tracing processes with code %d",
(a >> 16))
- case ActNotify:
- return "Action: Notify userspace"
case ActLog:
return "Action: Log system call"
case ActAllow:
@@ -446,7 +349,7 @@ func GetLibraryVersion() (major, minor, micro uint) {
// Returns a positive int containing the API level, or 0 with an error if the
// API level could not be detected due to the library being older than v2.4.0.
// See the seccomp_api_get(3) man page for details on available API levels:
-// https://github.com/seccomp/libseccomp/blob/main/doc/man/man3/seccomp_api_get.3
+// https://github.com/seccomp/libseccomp/blob/master/doc/man/man3/seccomp_api_get.3
func GetAPI() (uint, error) {
return getAPI()
}
@@ -456,7 +359,7 @@ func GetAPI() (uint, error) {
// Returns an error if the API level could not be set. An error is always
// returned if the library is older than v2.4.0
// See the seccomp_api_get(3) man page for details on available API levels:
-// https://github.com/seccomp/libseccomp/blob/main/doc/man/man3/seccomp_api_get.3
+// https://github.com/seccomp/libseccomp/blob/master/doc/man/man3/seccomp_api_get.3
func SetAPI(api uint) error {
return setAPI(api)
}
@@ -483,7 +386,7 @@ func (s ScmpSyscall) GetNameByArch(arch ScmpArch) (string, error) {
cString := C.seccomp_syscall_resolve_num_arch(arch.toNative(), C.int(s))
if cString == nil {
- return "", ErrSyscallDoesNotExist
+ return "", fmt.Errorf("could not resolve syscall name for %#x", int32(s))
}
defer C.free(unsafe.Pointer(cString))
@@ -506,7 +409,7 @@ func GetSyscallFromName(name string) (ScmpSyscall, error) {
result := C.seccomp_syscall_resolve_name(cString)
if result == scmpError {
- return 0, ErrSyscallDoesNotExist
+ return 0, fmt.Errorf("could not resolve name to syscall: %q", name)
}
return ScmpSyscall(result), nil
@@ -530,7 +433,7 @@ func GetSyscallFromNameByArch(name string, arch ScmpArch) (ScmpSyscall, error) {
result := C.seccomp_syscall_resolve_name_arch(arch.toNative(), cString)
if result == scmpError {
- return 0, ErrSyscallDoesNotExist
+ return 0, fmt.Errorf("could not resolve name to syscall: %q on %v", name, arch)
}
return ScmpSyscall(result), nil
@@ -603,10 +506,11 @@ type ScmpFilter struct {
lock sync.Mutex
}
-// NewFilter creates and returns a new filter context. Accepts a default action to be
-// taken for syscalls which match no rules in the filter.
-// Returns a reference to a valid filter context, or nil and an error
-// if the filter context could not be created or an invalid default action was given.
+// NewFilter creates and returns a new filter context.
+// Accepts a default action to be taken for syscalls which match no rules in
+// the filter.
+// Returns a reference to a valid filter context, or nil and an error if the
+// filter context could not be created or an invalid default action was given.
func NewFilter(defaultAction ScmpAction) (*ScmpFilter, error) {
if err := ensureSupportedVersion(); err != nil {
return nil, err
@@ -626,8 +530,8 @@ func NewFilter(defaultAction ScmpAction) (*ScmpFilter, error) {
filter.valid = true
runtime.SetFinalizer(filter, filterFinalizer)
- // Enable TSync so all goroutines will receive the same rules.
- // If the kernel does not support TSYNC, allow us to continue without error.
+ // Enable TSync so all goroutines will receive the same rules
+ // If the kernel does not support TSYNC, allow us to continue without error
if err := filter.setFilterAttr(filterAttrTsync, 0x1); err != nil && err != syscall.ENOTSUP {
filter.Release()
return nil, fmt.Errorf("could not create filter - error setting tsync bit: %v", err)
@@ -874,9 +778,8 @@ func (f *ScmpFilter) GetNoNewPrivsBit() (bool, error) {
func (f *ScmpFilter) GetLogBit() (bool, error) {
log, err := f.getFilterAttr(filterAttrLog)
if err != nil {
- // Ignore error, if not supported returns apiLevel == 0
- apiLevel, _ := GetAPI()
- if apiLevel < 3 {
+ api, apiErr := getAPI()
+ if (apiErr != nil && api == 0) || (apiErr == nil && api < 3) {
return false, fmt.Errorf("getting the log bit is only supported in libseccomp 2.4.0 and newer with API level 3 or higher")
}
@@ -890,30 +793,6 @@ func (f *ScmpFilter) GetLogBit() (bool, error) {
return true, nil
}
-// GetSSB returns the current state the SSB bit will be set to on the filter
-// being loaded, or an error if an issue was encountered retrieving the value.
-// The SSB bit tells the kernel that a seccomp user is not interested in enabling
-// Speculative Store Bypass mitigation.
-// The SSB bit is only usable when libseccomp API level 4 or higher is
-// supported.
-func (f *ScmpFilter) GetSSB() (bool, error) {
- ssb, err := f.getFilterAttr(filterAttrSSB)
- if err != nil {
- api, apiErr := getAPI()
- if (apiErr != nil && api == 0) || (apiErr == nil && api < 4) {
- return false, fmt.Errorf("getting the SSB flag is only supported in libseccomp 2.5.0 and newer with API level 4 or higher")
- }
-
- return false, err
- }
-
- if ssb == 0 {
- return false, nil
- }
-
- return true, nil
-}
-
// SetBadArchAction sets the default action taken on a syscall for an
// architecture not in the filter, or an error if an issue was encountered
// setting the value.
@@ -953,32 +832,9 @@ func (f *ScmpFilter) SetLogBit(state bool) error {
err := f.setFilterAttr(filterAttrLog, toSet)
if err != nil {
- // Ignore error, if not supported returns apiLevel == 0
- apiLevel, _ := GetAPI()
- if apiLevel < 3 {
- return fmt.Errorf("setting the log bit is only supported in libseccomp 2.4.0 and newer with API level 3 or higher")
- }
- }
-
- return err
-}
-
-// SetSSB sets the state of the SSB bit, which will be applied on filter
-// load, or an error if an issue was encountered setting the value.
-// The SSB bit is only usable when libseccomp API level 4 or higher is
-// supported.
-func (f *ScmpFilter) SetSSB(state bool) error {
- var toSet C.uint32_t = 0x0
-
- if state {
- toSet = 0x1
- }
-
- err := f.setFilterAttr(filterAttrSSB, toSet)
- if err != nil {
api, apiErr := getAPI()
- if (apiErr != nil && api == 0) || (apiErr == nil && api < 4) {
- return fmt.Errorf("setting the SSB flag is only supported in libseccomp 2.5.0 and newer with API level 4 or higher")
+ if (apiErr != nil && api == 0) || (apiErr == nil && api < 3) {
+ return fmt.Errorf("setting the log bit is only supported in libseccomp 2.4.0 and newer with API level 3 or higher")
}
}
@@ -1091,36 +947,3 @@ func (f *ScmpFilter) ExportBPF(file *os.File) error {
return nil
}
-
-// Userspace Notification API
-
-// GetNotifFd returns the userspace notification file descriptor associated with the given
-// filter context. Such a file descriptor is only valid after the filter has been loaded
-// and only when the filter uses the ActNotify action. The file descriptor can be used to
-// retrieve and respond to notifications associated with the filter (see NotifReceive(),
-// NotifRespond(), and NotifIDValid()).
-func (f *ScmpFilter) GetNotifFd() (ScmpFd, error) {
- return f.getNotifFd()
-}
-
-// NotifReceive retrieves a seccomp userspace notification from a filter whose ActNotify
-// action has triggered. The caller is expected to process the notification and return a
-// response via NotifRespond(). Each invocation of this function returns one
-// notification. As multiple notifications may be pending at any time, this function is
-// normally called within a polling loop.
-func NotifReceive(fd ScmpFd) (*ScmpNotifReq, error) {
- return notifReceive(fd)
-}
-
-// NotifRespond responds to a notification retrieved via NotifReceive(). The response Id
-// must match that of the corresponding notification retrieved via NotifReceive().
-func NotifRespond(fd ScmpFd, scmpResp *ScmpNotifResp) error {
- return notifRespond(fd, scmpResp)
-}
-
-// NotifIDValid checks if a notification is still valid. An return value of nil means the
-// notification is still valid. Otherwise the notification is not valid. This can be used
-// to mitigate time-of-check-time-of-use (TOCTOU) attacks as described in seccomp_notify_id_valid(2).
-func NotifIDValid(fd ScmpFd, id uint64) error {
- return notifIDValid(fd, id)
-}
diff --git a/vendor/github.com/seccomp/libseccomp-golang/seccomp_internal.go b/vendor/github.com/seccomp/libseccomp-golang/seccomp_internal.go
index 8dc7b296f..0982e930f 100644
--- a/vendor/github.com/seccomp/libseccomp-golang/seccomp_internal.go
+++ b/vendor/github.com/seccomp/libseccomp-golang/seccomp_internal.go
@@ -14,13 +14,6 @@ import (
// Get the seccomp header in scope
// Need stdlib.h for free() on cstrings
-// To compile libseccomp-golang against a specific version of libseccomp:
-// cd ../libseccomp && mkdir -p prefix
-// ./configure --prefix=$PWD/prefix && make && make install
-// cd ../libseccomp-golang
-// PKG_CONFIG_PATH=$PWD/../libseccomp/prefix/lib/pkgconfig/ make
-// LD_PRELOAD=$PWD/../libseccomp/prefix/lib/libseccomp.so.2.5.0 PKG_CONFIG_PATH=$PWD/../libseccomp/prefix/lib/pkgconfig/ make test
-
// #cgo pkg-config: libseccomp
/*
#include <errno.h>
@@ -57,14 +50,6 @@ const uint32_t C_ARCH_BAD = ARCH_BAD;
#define SCMP_ARCH_S390X ARCH_BAD
#endif
-#ifndef SCMP_ARCH_PARISC
-#define SCMP_ARCH_PARISC ARCH_BAD
-#endif
-
-#ifndef SCMP_ARCH_PARISC64
-#define SCMP_ARCH_PARISC64 ARCH_BAD
-#endif
-
const uint32_t C_ARCH_NATIVE = SCMP_ARCH_NATIVE;
const uint32_t C_ARCH_X86 = SCMP_ARCH_X86;
const uint32_t C_ARCH_X86_64 = SCMP_ARCH_X86_64;
@@ -82,8 +67,6 @@ const uint32_t C_ARCH_PPC64 = SCMP_ARCH_PPC64;
const uint32_t C_ARCH_PPC64LE = SCMP_ARCH_PPC64LE;
const uint32_t C_ARCH_S390 = SCMP_ARCH_S390;
const uint32_t C_ARCH_S390X = SCMP_ARCH_S390X;
-const uint32_t C_ARCH_PARISC = SCMP_ARCH_PARISC;
-const uint32_t C_ARCH_PARISC64 = SCMP_ARCH_PARISC64;
#ifndef SCMP_ACT_LOG
#define SCMP_ACT_LOG 0x7ffc0000U
@@ -97,10 +80,6 @@ const uint32_t C_ARCH_PARISC64 = SCMP_ARCH_PARISC64;
#define SCMP_ACT_KILL_THREAD 0x00000000U
#endif
-#ifndef SCMP_ACT_NOTIFY
-#define SCMP_ACT_NOTIFY 0x7fc00000U
-#endif
-
const uint32_t C_ACT_KILL = SCMP_ACT_KILL;
const uint32_t C_ACT_KILL_PROCESS = SCMP_ACT_KILL_PROCESS;
const uint32_t C_ACT_KILL_THREAD = SCMP_ACT_KILL_THREAD;
@@ -109,7 +88,6 @@ const uint32_t C_ACT_ERRNO = SCMP_ACT_ERRNO(0);
const uint32_t C_ACT_TRACE = SCMP_ACT_TRACE(0);
const uint32_t C_ACT_LOG = SCMP_ACT_LOG;
const uint32_t C_ACT_ALLOW = SCMP_ACT_ALLOW;
-const uint32_t C_ACT_NOTIFY = SCMP_ACT_NOTIFY;
// The libseccomp SCMP_FLTATR_CTL_LOG member of the scmp_filter_attr enum was
// added in v2.4.0
@@ -117,16 +95,12 @@ const uint32_t C_ACT_NOTIFY = SCMP_ACT_NOTIFY;
(SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 4)
#define SCMP_FLTATR_CTL_LOG _SCMP_FLTATR_MIN
#endif
-#if SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 5
-#define SCMP_FLTATR_CTL_SSB _SCMP_FLTATR_MIN
-#endif
const uint32_t C_ATTRIBUTE_DEFAULT = (uint32_t)SCMP_FLTATR_ACT_DEFAULT;
const uint32_t C_ATTRIBUTE_BADARCH = (uint32_t)SCMP_FLTATR_ACT_BADARCH;
const uint32_t C_ATTRIBUTE_NNP = (uint32_t)SCMP_FLTATR_CTL_NNP;
const uint32_t C_ATTRIBUTE_TSYNC = (uint32_t)SCMP_FLTATR_CTL_TSYNC;
const uint32_t C_ATTRIBUTE_LOG = (uint32_t)SCMP_FLTATR_CTL_LOG;
-const uint32_t C_ATTRIBUTE_SSB = (uint32_t)SCMP_FLTATR_CTL_SSB;
const int C_CMP_NE = (int)SCMP_CMP_NE;
const int C_CMP_LT = (int)SCMP_CMP_LT;
@@ -215,51 +189,6 @@ void add_struct_arg_cmp(
return;
}
-
-// The seccomp notify API functions were added in v2.5.0
-#if (SCMP_VER_MAJOR < 2) || \
- (SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 5)
-
-struct seccomp_data {
- int nr;
- __u32 arch;
- __u64 instruction_pointer;
- __u64 args[6];
-};
-
-struct seccomp_notif {
- __u64 id;
- __u32 pid;
- __u32 flags;
- struct seccomp_data data;
-};
-
-struct seccomp_notif_resp {
- __u64 id;
- __s64 val;
- __s32 error;
- __u32 flags;
-};
-
-int seccomp_notify_alloc(struct seccomp_notif **req, struct seccomp_notif_resp **resp) {
- return -EOPNOTSUPP;
-}
-int seccomp_notify_fd(const scmp_filter_ctx ctx) {
- return -EOPNOTSUPP;
-}
-void seccomp_notify_free(struct seccomp_notif *req, struct seccomp_notif_resp *resp) {
-}
-int seccomp_notify_id_valid(int fd, uint64_t id) {
- return -EOPNOTSUPP;
-}
-int seccomp_notify_receive(int fd, struct seccomp_notif *req) {
- return -EOPNOTSUPP;
-}
-int seccomp_notify_respond(int fd, struct seccomp_notif_resp *resp) {
- return -EOPNOTSUPP;
-}
-
-#endif
*/
import "C"
@@ -274,7 +203,6 @@ const (
filterAttrNNP scmpFilterAttr = iota
filterAttrTsync scmpFilterAttr = iota
filterAttrLog scmpFilterAttr = iota
- filterAttrSSB scmpFilterAttr = iota
)
const (
@@ -282,7 +210,7 @@ const (
scmpError C.int = -1
// Comparison boundaries to check for architecture validity
archStart ScmpArch = ArchNative
- archEnd ScmpArch = ArchPARISC64
+ archEnd ScmpArch = ArchS390X
// Comparison boundaries to check for action validity
actionStart ScmpAction = ActKill
actionEnd ScmpAction = ActKillProcess
@@ -532,10 +460,6 @@ func archFromNative(a C.uint32_t) (ScmpArch, error) {
return ArchS390, nil
case C.C_ARCH_S390X:
return ArchS390X, nil
- case C.C_ARCH_PARISC:
- return ArchPARISC, nil
- case C.C_ARCH_PARISC64:
- return ArchPARISC64, nil
default:
return 0x0, fmt.Errorf("unrecognized architecture %#x", uint32(a))
}
@@ -576,10 +500,6 @@ func (a ScmpArch) toNative() C.uint32_t {
return C.C_ARCH_S390
case ArchS390X:
return C.C_ARCH_S390X
- case ArchPARISC:
- return C.C_ARCH_PARISC
- case ArchPARISC64:
- return C.C_ARCH_PARISC64
case ArchNative:
return C.C_ARCH_NATIVE
default:
@@ -628,8 +548,6 @@ func actionFromNative(a C.uint32_t) (ScmpAction, error) {
return ActLog, nil
case C.C_ACT_ALLOW:
return ActAllow, nil
- case C.C_ACT_NOTIFY:
- return ActNotify, nil
default:
return 0x0, fmt.Errorf("unrecognized action %#x", uint32(a))
}
@@ -654,8 +572,6 @@ func (a ScmpAction) toNative() C.uint32_t {
return C.C_ACT_LOG
case ActAllow:
return C.C_ACT_ALLOW
- case ActNotify:
- return C.C_ACT_NOTIFY
default:
return 0x0
}
@@ -674,181 +590,7 @@ func (a scmpFilterAttr) toNative() uint32 {
return uint32(C.C_ATTRIBUTE_TSYNC)
case filterAttrLog:
return uint32(C.C_ATTRIBUTE_LOG)
- case filterAttrSSB:
- return uint32(C.C_ATTRIBUTE_SSB)
default:
return 0x0
}
}
-
-func (a ScmpSyscall) toNative() C.uint32_t {
- return C.uint32_t(a)
-}
-
-func syscallFromNative(a C.int) ScmpSyscall {
- return ScmpSyscall(a)
-}
-
-func notifReqFromNative(req *C.struct_seccomp_notif) (*ScmpNotifReq, error) {
- scmpArgs := make([]uint64, 6)
- for i := 0; i < len(scmpArgs); i++ {
- scmpArgs[i] = uint64(req.data.args[i])
- }
-
- arch, err := archFromNative(req.data.arch)
- if err != nil {
- return nil, err
- }
-
- scmpData := ScmpNotifData{
- Syscall: syscallFromNative(req.data.nr),
- Arch: arch,
- InstrPointer: uint64(req.data.instruction_pointer),
- Args: scmpArgs,
- }
-
- scmpReq := &ScmpNotifReq{
- ID: uint64(req.id),
- Pid: uint32(req.pid),
- Flags: uint32(req.flags),
- Data: scmpData,
- }
-
- return scmpReq, nil
-}
-
-func (scmpResp *ScmpNotifResp) toNative(resp *C.struct_seccomp_notif_resp) {
- resp.id = C.__u64(scmpResp.ID)
- resp.val = C.__s64(scmpResp.Val)
- resp.error = (C.__s32(scmpResp.Error) * -1) // kernel requires a negated value
- resp.flags = C.__u32(scmpResp.Flags)
-}
-
-// Userspace Notification API
-// Calls to C.seccomp_notify* hidden from seccomp.go
-
-func (f *ScmpFilter) getNotifFd() (ScmpFd, error) {
- f.lock.Lock()
- defer f.lock.Unlock()
-
- if !f.valid {
- return -1, errBadFilter
- }
-
- // Ignore error, if not supported returns apiLevel == 0
- apiLevel, _ := GetAPI()
- if apiLevel < 6 {
- return -1, fmt.Errorf("seccomp notification requires API level >= 6; current level = %d", apiLevel)
- }
-
- fd := C.seccomp_notify_fd(f.filterCtx)
-
- return ScmpFd(fd), nil
-}
-
-func notifReceive(fd ScmpFd) (*ScmpNotifReq, error) {
- var req *C.struct_seccomp_notif
- var resp *C.struct_seccomp_notif_resp
-
- // Ignore error, if not supported returns apiLevel == 0
- apiLevel, _ := GetAPI()
- if apiLevel < 6 {
- return nil, fmt.Errorf("seccomp notification requires API level >= 6; current level = %d", apiLevel)
- }
-
- // we only use the request here; the response is unused
- if retCode := C.seccomp_notify_alloc(&req, &resp); retCode != 0 {
- return nil, errRc(retCode)
- }
-
- defer func() {
- C.seccomp_notify_free(req, resp)
- }()
-
- for {
- retCode, errno := C.seccomp_notify_receive(C.int(fd), req)
- if retCode == 0 {
- break
- }
-
- if errno == syscall.EINTR {
- continue
- }
-
- if errno == syscall.ENOENT {
- return nil, errno
- }
-
- return nil, errRc(retCode)
- }
-
- return notifReqFromNative(req)
-}
-
-func notifRespond(fd ScmpFd, scmpResp *ScmpNotifResp) error {
- var req *C.struct_seccomp_notif
- var resp *C.struct_seccomp_notif_resp
-
- // Ignore error, if not supported returns apiLevel == 0
- apiLevel, _ := GetAPI()
- if apiLevel < 6 {
- return fmt.Errorf("seccomp notification requires API level >= 6; current level = %d", apiLevel)
- }
-
- // we only use the reponse here; the request is discarded
- if retCode := C.seccomp_notify_alloc(&req, &resp); retCode != 0 {
- return errRc(retCode)
- }
-
- defer func() {
- C.seccomp_notify_free(req, resp)
- }()
-
- scmpResp.toNative(resp)
-
- for {
- retCode, errno := C.seccomp_notify_respond(C.int(fd), resp)
- if retCode == 0 {
- break
- }
-
- if errno == syscall.EINTR {
- continue
- }
-
- if errno == syscall.ENOENT {
- return errno
- }
-
- return errRc(retCode)
- }
-
- return nil
-}
-
-func notifIDValid(fd ScmpFd, id uint64) error {
- // Ignore error, if not supported returns apiLevel == 0
- apiLevel, _ := GetAPI()
- if apiLevel < 6 {
- return fmt.Errorf("seccomp notification requires API level >= 6; current level = %d", apiLevel)
- }
-
- for {
- retCode, errno := C.seccomp_notify_id_valid(C.int(fd), C.uint64_t(id))
- if retCode == 0 {
- break
- }
-
- if errno == syscall.EINTR {
- continue
- }
-
- if errno == syscall.ENOENT {
- return errno
- }
-
- return errRc(retCode)
- }
-
- return nil
-}
diff --git a/vendor/github.com/vishvananda/netlink/.travis.yml b/vendor/github.com/vishvananda/netlink/.travis.yml
deleted file mode 100644
index 80219c69d..000000000
--- a/vendor/github.com/vishvananda/netlink/.travis.yml
+++ /dev/null
@@ -1,20 +0,0 @@
-language: go
-go:
- - "1.12.x"
- - "1.13.x"
- - "1.14.x"
-before_script:
- # make sure we keep path in tact when we sudo
- - sudo sed -i -e 's/^Defaults\tsecure_path.*$//' /etc/sudoers
- # modprobe ip_gre or else the first gre device can't be deleted
- - sudo modprobe ip_gre
- # modprobe nf_conntrack for the conntrack testing
- - sudo modprobe nf_conntrack
- - sudo modprobe nf_conntrack_netlink
- - sudo modprobe nf_conntrack_ipv4
- - sudo modprobe nf_conntrack_ipv6
- - sudo modprobe sch_hfsc
- - sudo modprobe sch_sfq
-install:
- - go get -v -t ./...
-go_import_path: github.com/vishvananda/netlink
diff --git a/vendor/github.com/vishvananda/netlink/README.md b/vendor/github.com/vishvananda/netlink/README.md
index a88e2f418..0128bc67d 100644
--- a/vendor/github.com/vishvananda/netlink/README.md
+++ b/vendor/github.com/vishvananda/netlink/README.md
@@ -1,6 +1,6 @@
# netlink - netlink library for go #
-[![Build Status](https://travis-ci.org/vishvananda/netlink.png?branch=master)](https://travis-ci.org/vishvananda/netlink) [![GoDoc](https://godoc.org/github.com/vishvananda/netlink?status.svg)](https://godoc.org/github.com/vishvananda/netlink)
+![Build Status](https://github.com/vishvananda/netlink/actions/workflows/main.yml/badge.svg) [![GoDoc](https://godoc.org/github.com/vishvananda/netlink?status.svg)](https://godoc.org/github.com/vishvananda/netlink)
The netlink package provides a simple netlink library for go. Netlink
is the interface a user-space program in linux uses to communicate with
diff --git a/vendor/github.com/vishvananda/netlink/addr_linux.go b/vendor/github.com/vishvananda/netlink/addr_linux.go
index 71da251ca..e4a167dda 100644
--- a/vendor/github.com/vishvananda/netlink/addr_linux.go
+++ b/vendor/github.com/vishvananda/netlink/addr_linux.go
@@ -268,7 +268,7 @@ func parseAddr(m []byte) (addr Addr, family int, err error) {
// But obviously, as there are IPv6 PtP addresses, too,
// IFA_LOCAL should also be handled for IPv6.
if local != nil {
- if family == FAMILY_V4 && local.IP.Equal(dst.IP) {
+ if family == FAMILY_V4 && dst != nil && local.IP.Equal(dst.IP) {
addr.IPNet = dst
} else {
addr.IPNet = local
@@ -357,7 +357,8 @@ func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-c
msgs, from, err := s.Receive()
if err != nil {
if cberr != nil {
- cberr(err)
+ cberr(fmt.Errorf("Receive failed: %v",
+ err))
}
return
}
@@ -372,7 +373,6 @@ func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-c
continue
}
if m.Header.Type == unix.NLMSG_ERROR {
- native := nl.NativeEndian()
error := int32(native.Uint32(m.Data[0:4]))
if error == 0 {
continue
diff --git a/vendor/github.com/vishvananda/netlink/bpf_linux.go b/vendor/github.com/vishvananda/netlink/bpf_linux.go
index 6631626bf..96befbfe0 100644
--- a/vendor/github.com/vishvananda/netlink/bpf_linux.go
+++ b/vendor/github.com/vishvananda/netlink/bpf_linux.go
@@ -16,6 +16,30 @@ const (
BPF_PROG_TYPE_SCHED_ACT
BPF_PROG_TYPE_TRACEPOINT
BPF_PROG_TYPE_XDP
+ BPF_PROG_TYPE_PERF_EVENT
+ BPF_PROG_TYPE_CGROUP_SKB
+ BPF_PROG_TYPE_CGROUP_SOCK
+ BPF_PROG_TYPE_LWT_IN
+ BPF_PROG_TYPE_LWT_OUT
+ BPF_PROG_TYPE_LWT_XMIT
+ BPF_PROG_TYPE_SOCK_OPS
+ BPF_PROG_TYPE_SK_SKB
+ BPF_PROG_TYPE_CGROUP_DEVICE
+ BPF_PROG_TYPE_SK_MSG
+ BPF_PROG_TYPE_RAW_TRACEPOINT
+ BPF_PROG_TYPE_CGROUP_SOCK_ADDR
+ BPF_PROG_TYPE_LWT_SEG6LOCAL
+ BPF_PROG_TYPE_LIRC_MODE2
+ BPF_PROG_TYPE_SK_REUSEPORT
+ BPF_PROG_TYPE_FLOW_DISSECTOR
+ BPF_PROG_TYPE_CGROUP_SYSCTL
+ BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE
+ BPF_PROG_TYPE_CGROUP_SOCKOPT
+ BPF_PROG_TYPE_TRACING
+ BPF_PROG_TYPE_STRUCT_OPS
+ BPF_PROG_TYPE_EXT
+ BPF_PROG_TYPE_LSM
+ BPF_PROG_TYPE_SK_LOOKUP
)
type BPFAttr struct {
diff --git a/vendor/github.com/vishvananda/netlink/class_linux.go b/vendor/github.com/vishvananda/netlink/class_linux.go
index 029568a3f..6f542ba4e 100644
--- a/vendor/github.com/vishvananda/netlink/class_linux.go
+++ b/vendor/github.com/vishvananda/netlink/class_linux.go
@@ -191,9 +191,9 @@ func classPayload(req *nl.NetlinkRequest, class Class) error {
opt.Fsc.Set(fm1/8, fd, fm2/8)
um1, ud, um2 := hfsc.Usc.Attrs()
opt.Usc.Set(um1/8, ud, um2/8)
- nl.NewRtAttrChild(options, nl.TCA_HFSC_RSC, nl.SerializeHfscCurve(&opt.Rsc))
- nl.NewRtAttrChild(options, nl.TCA_HFSC_FSC, nl.SerializeHfscCurve(&opt.Fsc))
- nl.NewRtAttrChild(options, nl.TCA_HFSC_USC, nl.SerializeHfscCurve(&opt.Usc))
+ options.AddRtAttr(nl.TCA_HFSC_RSC, nl.SerializeHfscCurve(&opt.Rsc))
+ options.AddRtAttr(nl.TCA_HFSC_FSC, nl.SerializeHfscCurve(&opt.Fsc))
+ options.AddRtAttr(nl.TCA_HFSC_USC, nl.SerializeHfscCurve(&opt.Usc))
}
req.AddData(options)
return nil
@@ -341,7 +341,6 @@ func parseHfscClassData(class Class, data []syscall.NetlinkRouteAttr) (bool, err
func parseTcStats(data []byte) (*ClassStatistics, error) {
buf := &bytes.Buffer{}
buf.Write(data)
- native := nl.NativeEndian()
tcStats := &tcStats{}
if err := binary.Read(buf, native, tcStats); err != nil {
return nil, err
@@ -363,7 +362,6 @@ func parseTcStats(data []byte) (*ClassStatistics, error) {
func parseGnetStats(data []byte, gnetStats interface{}) error {
buf := &bytes.Buffer{}
buf.Write(data)
- native := nl.NativeEndian()
return binary.Read(buf, native, gnetStats)
}
diff --git a/vendor/github.com/vishvananda/netlink/conntrack_linux.go b/vendor/github.com/vishvananda/netlink/conntrack_linux.go
index ab91f4e55..03ea1b98f 100644
--- a/vendor/github.com/vishvananda/netlink/conntrack_linux.go
+++ b/vendor/github.com/vishvananda/netlink/conntrack_linux.go
@@ -6,6 +6,7 @@ import (
"errors"
"fmt"
"net"
+ "time"
"github.com/vishvananda/netlink/nl"
"golang.org/x/sys/unix"
@@ -145,16 +146,23 @@ type ConntrackFlow struct {
Forward ipTuple
Reverse ipTuple
Mark uint32
+ TimeStart uint64
+ TimeStop uint64
+ TimeOut uint32
}
func (s *ConntrackFlow) String() string {
// conntrack cmd output:
// udp 17 src=127.0.0.1 dst=127.0.0.1 sport=4001 dport=1234 packets=5 bytes=532 [UNREPLIED] src=127.0.0.1 dst=127.0.0.1 sport=1234 dport=4001 packets=10 bytes=1078 mark=0
- return fmt.Sprintf("%s\t%d src=%s dst=%s sport=%d dport=%d packets=%d bytes=%d\tsrc=%s dst=%s sport=%d dport=%d packets=%d bytes=%d mark=%d",
+ // start=2019-07-26 01:26:21.557800506 +0000 UTC stop=1970-01-01 00:00:00 +0000 UTC timeout=30(sec)
+ start := time.Unix(0, int64(s.TimeStart))
+ stop := time.Unix(0, int64(s.TimeStop))
+ timeout := int32(s.TimeOut)
+ return fmt.Sprintf("%s\t%d src=%s dst=%s sport=%d dport=%d packets=%d bytes=%d\tsrc=%s dst=%s sport=%d dport=%d packets=%d bytes=%d mark=0x%x start=%v stop=%v timeout=%d(sec)",
nl.L4ProtoMap[s.Forward.Protocol], s.Forward.Protocol,
s.Forward.SrcIP.String(), s.Forward.DstIP.String(), s.Forward.SrcPort, s.Forward.DstPort, s.Forward.Packets, s.Forward.Bytes,
s.Reverse.SrcIP.String(), s.Reverse.DstIP.String(), s.Reverse.SrcPort, s.Reverse.DstPort, s.Reverse.Packets, s.Reverse.Bytes,
- s.Mark)
+ s.Mark, start, stop, timeout)
}
// This method parse the ip tuple structure
@@ -174,25 +182,43 @@ func parseIpTuple(reader *bytes.Reader, tpl *ipTuple) uint8 {
tpl.DstIP = v
}
}
- // Skip the next 4 bytes nl.NLA_F_NESTED|nl.CTA_TUPLE_PROTO
- reader.Seek(4, seekCurrent)
- _, t, _, v := parseNfAttrTLV(reader)
+ // Get total length of nested protocol-specific info.
+ _, _, protoInfoTotalLen := parseNfAttrTL(reader)
+ _, t, l, v := parseNfAttrTLV(reader)
+ // Track the number of bytes read.
+ protoInfoBytesRead := uint16(nl.SizeofNfattr) + l
if t == nl.CTA_PROTO_NUM {
tpl.Protocol = uint8(v[0])
}
- // Skip some padding 3 bytes
+ // We only parse TCP & UDP headers. Skip the others.
+ if tpl.Protocol != 6 && tpl.Protocol != 17 {
+ // skip the rest
+ bytesRemaining := protoInfoTotalLen - protoInfoBytesRead
+ reader.Seek(int64(bytesRemaining), seekCurrent)
+ return tpl.Protocol
+ }
+ // Skip 3 bytes of padding
reader.Seek(3, seekCurrent)
+ protoInfoBytesRead += 3
for i := 0; i < 2; i++ {
_, t, _ := parseNfAttrTL(reader)
+ protoInfoBytesRead += uint16(nl.SizeofNfattr)
switch t {
case nl.CTA_PROTO_SRC_PORT:
parseBERaw16(reader, &tpl.SrcPort)
+ protoInfoBytesRead += 2
case nl.CTA_PROTO_DST_PORT:
parseBERaw16(reader, &tpl.DstPort)
+ protoInfoBytesRead += 2
}
- // Skip some padding 2 byte
+ // Skip 2 bytes of padding
reader.Seek(2, seekCurrent)
+ protoInfoBytesRead += 2
}
+ // Skip any remaining/unknown parts of the message
+ bytesRemaining := protoInfoTotalLen - protoInfoBytesRead
+ reader.Seek(int64(bytesRemaining), seekCurrent)
+
return tpl.Protocol
}
@@ -211,10 +237,14 @@ func parseNfAttrTL(r *bytes.Reader) (isNested bool, attrType, len uint16) {
binary.Read(r, nl.NativeEndian(), &attrType)
isNested = (attrType & nl.NLA_F_NESTED) == nl.NLA_F_NESTED
attrType = attrType & (nl.NLA_F_NESTED - 1)
-
return isNested, attrType, len
}
+func skipNfAttrValue(r *bytes.Reader, len uint16) {
+ len = (len + nl.NLA_ALIGNTO - 1) & ^(nl.NLA_ALIGNTO - 1)
+ r.Seek(int64(len), seekCurrent)
+}
+
func parseBERaw16(r *bytes.Reader, v *uint16) {
binary.Read(r, binary.BigEndian, v)
}
@@ -241,6 +271,36 @@ func parseByteAndPacketCounters(r *bytes.Reader) (bytes, packets uint64) {
return
}
+// when the flow is alive, only the timestamp_start is returned in structure
+func parseTimeStamp(r *bytes.Reader, readSize uint16) (tstart, tstop uint64) {
+ var numTimeStamps int
+ oneItem := nl.SizeofNfattr + 8 // 4 bytes attr header + 8 bytes timestamp
+ if readSize == uint16(oneItem) {
+ numTimeStamps = 1
+ } else if readSize == 2*uint16(oneItem) {
+ numTimeStamps = 2
+ } else {
+ return
+ }
+ for i := 0; i < numTimeStamps; i++ {
+ switch _, t, _ := parseNfAttrTL(r); t {
+ case nl.CTA_TIMESTAMP_START:
+ parseBERaw64(r, &tstart)
+ case nl.CTA_TIMESTAMP_STOP:
+ parseBERaw64(r, &tstop)
+ default:
+ return
+ }
+ }
+ return
+
+}
+
+func parseTimeOut(r *bytes.Reader) (ttimeout uint32) {
+ parseBERaw32(r, &ttimeout)
+ return
+}
+
func parseConnectionMark(r *bytes.Reader) (mark uint32) {
parseBERaw32(r, &mark)
return
@@ -266,25 +326,37 @@ func parseRawData(data []byte) *ConntrackFlow {
if nested, t, l := parseNfAttrTL(reader); nested {
switch t {
case nl.CTA_TUPLE_ORIG:
- if nested, t, _ = parseNfAttrTL(reader); nested && t == nl.CTA_TUPLE_IP {
+ if nested, t, l = parseNfAttrTL(reader); nested && t == nl.CTA_TUPLE_IP {
parseIpTuple(reader, &s.Forward)
}
case nl.CTA_TUPLE_REPLY:
- if nested, t, _ = parseNfAttrTL(reader); nested && t == nl.CTA_TUPLE_IP {
+ if nested, t, l = parseNfAttrTL(reader); nested && t == nl.CTA_TUPLE_IP {
parseIpTuple(reader, &s.Reverse)
} else {
// Header not recognized skip it
- reader.Seek(int64(l), seekCurrent)
+ skipNfAttrValue(reader, l)
}
case nl.CTA_COUNTERS_ORIG:
s.Forward.Bytes, s.Forward.Packets = parseByteAndPacketCounters(reader)
case nl.CTA_COUNTERS_REPLY:
s.Reverse.Bytes, s.Reverse.Packets = parseByteAndPacketCounters(reader)
+ case nl.CTA_TIMESTAMP:
+ s.TimeStart, s.TimeStop = parseTimeStamp(reader, l)
+ case nl.CTA_PROTOINFO:
+ skipNfAttrValue(reader, l)
+ default:
+ skipNfAttrValue(reader, l)
}
} else {
switch t {
case nl.CTA_MARK:
s.Mark = parseConnectionMark(reader)
+ case nl.CTA_TIMEOUT:
+ s.TimeOut = parseTimeOut(reader)
+ case nl.CTA_STATUS, nl.CTA_USE, nl.CTA_ID:
+ skipNfAttrValue(reader, l)
+ default:
+ skipNfAttrValue(reader, l)
}
}
}
@@ -346,23 +418,34 @@ type CustomConntrackFilter interface {
}
type ConntrackFilter struct {
- ipFilter map[ConntrackFilterType]net.IP
+ ipNetFilter map[ConntrackFilterType]*net.IPNet
portFilter map[ConntrackFilterType]uint16
protoFilter uint8
}
-// AddIP adds an IP to the conntrack filter
-func (f *ConntrackFilter) AddIP(tp ConntrackFilterType, ip net.IP) error {
- if f.ipFilter == nil {
- f.ipFilter = make(map[ConntrackFilterType]net.IP)
+// AddIPNet adds a IP subnet to the conntrack filter
+func (f *ConntrackFilter) AddIPNet(tp ConntrackFilterType, ipNet *net.IPNet) error {
+ if ipNet == nil {
+ return fmt.Errorf("Filter attribute empty")
}
- if _, ok := f.ipFilter[tp]; ok {
+ if f.ipNetFilter == nil {
+ f.ipNetFilter = make(map[ConntrackFilterType]*net.IPNet)
+ }
+ if _, ok := f.ipNetFilter[tp]; ok {
return errors.New("Filter attribute already present")
}
- f.ipFilter[tp] = ip
+ f.ipNetFilter[tp] = ipNet
return nil
}
+// AddIP adds an IP to the conntrack filter
+func (f *ConntrackFilter) AddIP(tp ConntrackFilterType, ip net.IP) error {
+ if ip == nil {
+ return fmt.Errorf("Filter attribute empty")
+ }
+ return f.AddIPNet(tp, NewIPNet(ip))
+}
+
// AddPort adds a Port to the conntrack filter if the Layer 4 protocol allows it
func (f *ConntrackFilter) AddPort(tp ConntrackFilterType, port uint16) error {
switch f.protoFilter {
@@ -394,7 +477,7 @@ func (f *ConntrackFilter) AddProtocol(proto uint8) error {
// MatchConntrackFlow applies the filter to the flow and returns true if the flow matches the filter
// false otherwise
func (f *ConntrackFilter) MatchConntrackFlow(flow *ConntrackFlow) bool {
- if len(f.ipFilter) == 0 && len(f.portFilter) == 0 && f.protoFilter == 0 {
+ if len(f.ipNetFilter) == 0 && len(f.portFilter) == 0 && f.protoFilter == 0 {
// empty filter always not match
return false
}
@@ -408,30 +491,30 @@ func (f *ConntrackFilter) MatchConntrackFlow(flow *ConntrackFlow) bool {
match := true
// IP conntrack filter
- if len(f.ipFilter) > 0 {
+ if len(f.ipNetFilter) > 0 {
// -orig-src ip Source address from original direction
- if elem, found := f.ipFilter[ConntrackOrigSrcIP]; found {
- match = match && elem.Equal(flow.Forward.SrcIP)
+ if elem, found := f.ipNetFilter[ConntrackOrigSrcIP]; found {
+ match = match && elem.Contains(flow.Forward.SrcIP)
}
// -orig-dst ip Destination address from original direction
- if elem, found := f.ipFilter[ConntrackOrigDstIP]; match && found {
- match = match && elem.Equal(flow.Forward.DstIP)
+ if elem, found := f.ipNetFilter[ConntrackOrigDstIP]; match && found {
+ match = match && elem.Contains(flow.Forward.DstIP)
}
// -src-nat ip Source NAT ip
- if elem, found := f.ipFilter[ConntrackReplySrcIP]; match && found {
- match = match && elem.Equal(flow.Reverse.SrcIP)
+ if elem, found := f.ipNetFilter[ConntrackReplySrcIP]; match && found {
+ match = match && elem.Contains(flow.Reverse.SrcIP)
}
// -dst-nat ip Destination NAT ip
- if elem, found := f.ipFilter[ConntrackReplyDstIP]; match && found {
- match = match && elem.Equal(flow.Reverse.DstIP)
+ if elem, found := f.ipNetFilter[ConntrackReplyDstIP]; match && found {
+ match = match && elem.Contains(flow.Reverse.DstIP)
}
// Match source or destination reply IP
- if elem, found := f.ipFilter[ConntrackReplyAnyIP]; match && found {
- match = match && (elem.Equal(flow.Reverse.SrcIP) || elem.Equal(flow.Reverse.DstIP))
+ if elem, found := f.ipNetFilter[ConntrackReplyAnyIP]; match && found {
+ match = match && (elem.Contains(flow.Reverse.SrcIP) || elem.Contains(flow.Reverse.DstIP))
}
}
diff --git a/vendor/github.com/vishvananda/netlink/devlink_linux.go b/vendor/github.com/vishvananda/netlink/devlink_linux.go
index 7d57080e8..358b232c6 100644
--- a/vendor/github.com/vishvananda/netlink/devlink_linux.go
+++ b/vendor/github.com/vishvananda/netlink/devlink_linux.go
@@ -1,9 +1,11 @@
package netlink
import (
+ "fmt"
+ "net"
+ "strings"
"syscall"
- "fmt"
"github.com/vishvananda/netlink/nl"
"golang.org/x/sys/unix"
)
@@ -27,6 +29,20 @@ type DevlinkDevice struct {
Attrs DevlinkDevAttrs
}
+// DevlinkPortFn represents port function and its attributes
+type DevlinkPortFn struct {
+ HwAddr net.HardwareAddr
+ State uint8
+ OpState uint8
+}
+
+// DevlinkPortFnSetAttrs represents attributes to set
+type DevlinkPortFnSetAttrs struct {
+ FnAttrs DevlinkPortFn
+ HwAddrValid bool
+ StateValid bool
+}
+
// DevlinkPort represents port and its attributes
type DevlinkPort struct {
BusName string
@@ -37,6 +53,35 @@ type DevlinkPort struct {
NetdevIfIndex uint32
RdmaDeviceName string
PortFlavour uint16
+ Fn *DevlinkPortFn
+}
+
+type DevLinkPortAddAttrs struct {
+ Controller uint32
+ SfNumber uint32
+ PortIndex uint32
+ PfNumber uint16
+ SfNumberValid bool
+ PortIndexValid bool
+ ControllerValid bool
+}
+
+// DevlinkDeviceInfo represents devlink info
+type DevlinkDeviceInfo struct {
+ Driver string
+ SerialNumber string
+ BoardID string
+ FwApp string
+ FwAppBoundleID string
+ FwAppName string
+ FwBoundleID string
+ FwMgmt string
+ FwMgmtAPI string
+ FwMgmtBuild string
+ FwNetlist string
+ FwNetlistBuild string
+ FwPsidAPI string
+ FwUndi string
}
func parseDevLinkDeviceList(msgs [][]byte) ([]*DevlinkDevice, error) {
@@ -107,9 +152,9 @@ func (d *DevlinkDevice) parseAttributes(attrs []syscall.NetlinkRouteAttr) error
for _, a := range attrs {
switch a.Attr.Type {
case nl.DEVLINK_ATTR_BUS_NAME:
- d.BusName = string(a.Value)
+ d.BusName = string(a.Value[:len(a.Value)-1])
case nl.DEVLINK_ATTR_DEV_NAME:
- d.DeviceName = string(a.Value)
+ d.DeviceName = string(a.Value[:len(a.Value)-1])
case nl.DEVLINK_ATTR_ESWITCH_MODE:
d.Attrs.Eswitch.Mode = parseEswitchMode(native.Uint16(a.Value))
case nl.DEVLINK_ATTR_ESWITCH_INLINE_MODE:
@@ -138,12 +183,12 @@ func (h *Handle) getEswitchAttrs(family *GenlFamily, dev *DevlinkDevice) {
req := h.newNetlinkRequest(int(family.ID), unix.NLM_F_REQUEST|unix.NLM_F_ACK)
req.AddData(msg)
- b := make([]byte, len(dev.BusName))
+ b := make([]byte, len(dev.BusName)+1)
copy(b, dev.BusName)
data := nl.NewRtAttr(nl.DEVLINK_ATTR_BUS_NAME, b)
req.AddData(data)
- b = make([]byte, len(dev.DeviceName))
+ b = make([]byte, len(dev.DeviceName)+1)
copy(b, dev.DeviceName)
data = nl.NewRtAttr(nl.DEVLINK_ATTR_DEV_NAME, b)
req.AddData(data)
@@ -287,21 +332,33 @@ func (port *DevlinkPort) parseAttributes(attrs []syscall.NetlinkRouteAttr) error
for _, a := range attrs {
switch a.Attr.Type {
case nl.DEVLINK_ATTR_BUS_NAME:
- port.BusName = string(a.Value)
+ port.BusName = string(a.Value[:len(a.Value)-1])
case nl.DEVLINK_ATTR_DEV_NAME:
- port.DeviceName = string(a.Value)
+ port.DeviceName = string(a.Value[:len(a.Value)-1])
case nl.DEVLINK_ATTR_PORT_INDEX:
port.PortIndex = native.Uint32(a.Value)
case nl.DEVLINK_ATTR_PORT_TYPE:
port.PortType = native.Uint16(a.Value)
case nl.DEVLINK_ATTR_PORT_NETDEV_NAME:
- port.NetdeviceName = string(a.Value)
+ port.NetdeviceName = string(a.Value[:len(a.Value)-1])
case nl.DEVLINK_ATTR_PORT_NETDEV_IFINDEX:
port.NetdevIfIndex = native.Uint32(a.Value)
case nl.DEVLINK_ATTR_PORT_IBDEV_NAME:
- port.RdmaDeviceName = string(a.Value)
+ port.RdmaDeviceName = string(a.Value[:len(a.Value)-1])
case nl.DEVLINK_ATTR_PORT_FLAVOUR:
port.PortFlavour = native.Uint16(a.Value)
+ case nl.DEVLINK_ATTR_PORT_FUNCTION:
+ port.Fn = &DevlinkPortFn{}
+ for nested := range nl.ParseAttributes(a.Value) {
+ switch nested.Type {
+ case nl.DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR:
+ port.Fn.HwAddr = nested.Value[:]
+ case nl.DEVLINK_PORT_FN_ATTR_STATE:
+ port.Fn.State = uint8(nested.Value[0])
+ case nl.DEVLINK_PORT_FN_ATTR_OPSTATE:
+ port.Fn.OpState = uint8(nested.Value[0])
+ }
+ }
}
}
return nil
@@ -391,3 +448,281 @@ func (h *Handle) DevLinkGetPortByIndex(Bus string, Device string, PortIndex uint
func DevLinkGetPortByIndex(Bus string, Device string, PortIndex uint32) (*DevlinkPort, error) {
return pkgHandle.DevLinkGetPortByIndex(Bus, Device, PortIndex)
}
+
+// DevLinkPortAdd adds a devlink port and returns a port on success
+// otherwise returns nil port and an error code.
+func (h *Handle) DevLinkPortAdd(Bus string, Device string, Flavour uint16, Attrs DevLinkPortAddAttrs) (*DevlinkPort, error) {
+ _, req, err := h.createCmdReq(nl.DEVLINK_CMD_PORT_NEW, Bus, Device)
+ if err != nil {
+ return nil, err
+ }
+
+ req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PORT_FLAVOUR, nl.Uint16Attr(Flavour)))
+
+ req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PORT_PCI_PF_NUMBER, nl.Uint16Attr(Attrs.PfNumber)))
+ if Flavour == nl.DEVLINK_PORT_FLAVOUR_PCI_SF && Attrs.SfNumberValid {
+ req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PORT_PCI_SF_NUMBER, nl.Uint32Attr(Attrs.SfNumber)))
+ }
+ if Attrs.PortIndexValid {
+ req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PORT_INDEX, nl.Uint32Attr(Attrs.PortIndex)))
+ }
+ if Attrs.ControllerValid {
+ req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PORT_CONTROLLER_NUMBER, nl.Uint32Attr(Attrs.Controller)))
+ }
+ respmsg, err := req.Execute(unix.NETLINK_GENERIC, 0)
+ if err != nil {
+ return nil, err
+ }
+ port, err := parseDevlinkPortMsg(respmsg)
+ return port, err
+}
+
+// DevLinkPortAdd adds a devlink port and returns a port on success
+// otherwise returns nil port and an error code.
+func DevLinkPortAdd(Bus string, Device string, Flavour uint16, Attrs DevLinkPortAddAttrs) (*DevlinkPort, error) {
+ return pkgHandle.DevLinkPortAdd(Bus, Device, Flavour, Attrs)
+}
+
+// DevLinkPortDel deletes a devlink port and returns success or error code.
+func (h *Handle) DevLinkPortDel(Bus string, Device string, PortIndex uint32) error {
+ _, req, err := h.createCmdReq(nl.DEVLINK_CMD_PORT_DEL, Bus, Device)
+ if err != nil {
+ return err
+ }
+
+ req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PORT_INDEX, nl.Uint32Attr(PortIndex)))
+ _, err = req.Execute(unix.NETLINK_GENERIC, 0)
+ return err
+}
+
+// DevLinkPortDel deletes a devlink port and returns success or error code.
+func DevLinkPortDel(Bus string, Device string, PortIndex uint32) error {
+ return pkgHandle.DevLinkPortDel(Bus, Device, PortIndex)
+}
+
+// DevlinkPortFnSet sets one or more port function attributes specified by the attribute mask.
+// It returns 0 on success or error code.
+func (h *Handle) DevlinkPortFnSet(Bus string, Device string, PortIndex uint32, FnAttrs DevlinkPortFnSetAttrs) error {
+ _, req, err := h.createCmdReq(nl.DEVLINK_CMD_PORT_SET, Bus, Device)
+ if err != nil {
+ return err
+ }
+
+ req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PORT_INDEX, nl.Uint32Attr(PortIndex)))
+
+ fnAttr := nl.NewRtAttr(nl.DEVLINK_ATTR_PORT_FUNCTION|unix.NLA_F_NESTED, nil)
+
+ if FnAttrs.HwAddrValid {
+ fnAttr.AddRtAttr(nl.DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR, []byte(FnAttrs.FnAttrs.HwAddr))
+ }
+
+ if FnAttrs.StateValid {
+ fnAttr.AddRtAttr(nl.DEVLINK_PORT_FN_ATTR_STATE, nl.Uint8Attr(FnAttrs.FnAttrs.State))
+ }
+ req.AddData(fnAttr)
+
+ _, err = req.Execute(unix.NETLINK_GENERIC, 0)
+ return err
+}
+
+// DevlinkPortFnSet sets one or more port function attributes specified by the attribute mask.
+// It returns 0 on success or error code.
+func DevlinkPortFnSet(Bus string, Device string, PortIndex uint32, FnAttrs DevlinkPortFnSetAttrs) error {
+ return pkgHandle.DevlinkPortFnSet(Bus, Device, PortIndex, FnAttrs)
+}
+
+// devlinkInfoGetter is function that is responsible for getting devlink info message
+// this is introduced for test purpose
+type devlinkInfoGetter func(bus, device string) ([]byte, error)
+
+// DevlinkGetDeviceInfoByName returns devlink info for selected device,
+// otherwise returns an error code.
+// Equivalent to: `devlink dev info $dev`
+func (h *Handle) DevlinkGetDeviceInfoByName(Bus string, Device string, getInfoMsg devlinkInfoGetter) (*DevlinkDeviceInfo, error) {
+ info, err := h.DevlinkGetDeviceInfoByNameAsMap(Bus, Device, getInfoMsg)
+ if err != nil {
+ return nil, err
+ }
+
+ return parseInfoData(info), nil
+}
+
+// DevlinkGetDeviceInfoByName returns devlink info for selected device,
+// otherwise returns an error code.
+// Equivalent to: `devlink dev info $dev`
+func DevlinkGetDeviceInfoByName(Bus string, Device string) (*DevlinkDeviceInfo, error) {
+ return pkgHandle.DevlinkGetDeviceInfoByName(Bus, Device, pkgHandle.getDevlinkInfoMsg)
+}
+
+// DevlinkGetDeviceInfoByNameAsMap returns devlink info for selected device as a map,
+// otherwise returns an error code.
+// Equivalent to: `devlink dev info $dev`
+func (h *Handle) DevlinkGetDeviceInfoByNameAsMap(Bus string, Device string, getInfoMsg devlinkInfoGetter) (map[string]string, error) {
+ response, err := getInfoMsg(Bus, Device)
+ if err != nil {
+ return nil, err
+ }
+
+ info, err := parseInfoMsg(response)
+ if err != nil {
+ return nil, err
+ }
+
+ return info, nil
+}
+
+// DevlinkGetDeviceInfoByNameAsMap returns devlink info for selected device as a map,
+// otherwise returns an error code.
+// Equivalent to: `devlink dev info $dev`
+func DevlinkGetDeviceInfoByNameAsMap(Bus string, Device string) (map[string]string, error) {
+ return pkgHandle.DevlinkGetDeviceInfoByNameAsMap(Bus, Device, pkgHandle.getDevlinkInfoMsg)
+}
+
+// GetDevlinkInfo returns devlink info for target device,
+// otherwise returns an error code.
+func (d *DevlinkDevice) GetDevlinkInfo() (*DevlinkDeviceInfo, error) {
+ return pkgHandle.DevlinkGetDeviceInfoByName(d.BusName, d.DeviceName, pkgHandle.getDevlinkInfoMsg)
+}
+
+// GetDevlinkInfoAsMap returns devlink info for target device as a map,
+// otherwise returns an error code.
+func (d *DevlinkDevice) GetDevlinkInfoAsMap() (map[string]string, error) {
+ return pkgHandle.DevlinkGetDeviceInfoByNameAsMap(d.BusName, d.DeviceName, pkgHandle.getDevlinkInfoMsg)
+}
+
+func (h *Handle) getDevlinkInfoMsg(bus, device string) ([]byte, error) {
+ _, req, err := h.createCmdReq(nl.DEVLINK_CMD_INFO_GET, bus, device)
+ if err != nil {
+ return nil, err
+ }
+
+ response, err := req.Execute(unix.NETLINK_GENERIC, 0)
+ if err != nil {
+ return nil, err
+ }
+
+ if len(response) < 1 {
+ return nil, fmt.Errorf("getDevlinkInfoMsg: message too short")
+ }
+
+ return response[0], nil
+}
+
+func parseInfoMsg(msg []byte) (map[string]string, error) {
+ if len(msg) < nl.SizeofGenlmsg {
+ return nil, fmt.Errorf("parseInfoMsg: message too short")
+ }
+
+ info := make(map[string]string)
+ err := collectInfoData(msg[nl.SizeofGenlmsg:], info)
+
+ if err != nil {
+ return nil, err
+ }
+
+ return info, nil
+}
+
+func collectInfoData(msg []byte, data map[string]string) error {
+ attrs, err := nl.ParseRouteAttr(msg)
+ if err != nil {
+ return err
+ }
+
+ for _, attr := range attrs {
+ switch attr.Attr.Type {
+ case nl.DEVLINK_ATTR_INFO_DRIVER_NAME:
+ data["driver"] = parseInfoValue(attr.Value)
+ case nl.DEVLINK_ATTR_INFO_SERIAL_NUMBER:
+ data["serialNumber"] = parseInfoValue(attr.Value)
+ case nl.DEVLINK_ATTR_INFO_VERSION_RUNNING, nl.DEVLINK_ATTR_INFO_VERSION_FIXED,
+ nl.DEVLINK_ATTR_INFO_VERSION_STORED:
+ key, value, err := getNestedInfoData(attr.Value)
+ if err != nil {
+ return err
+ }
+ data[key] = value
+ }
+ }
+
+ if len(data) == 0 {
+ return fmt.Errorf("collectInfoData: could not read attributes")
+ }
+
+ return nil
+}
+
+func getNestedInfoData(msg []byte) (string, string, error) {
+ nestedAttrs, err := nl.ParseRouteAttr(msg)
+
+ var key, value string
+
+ if err != nil {
+ return "", "", err
+ }
+
+ if len(nestedAttrs) != 2 {
+ return "", "", fmt.Errorf("getNestedInfoData: too few attributes in nested structure")
+ }
+
+ for _, nestedAttr := range nestedAttrs {
+ switch nestedAttr.Attr.Type {
+ case nl.DEVLINK_ATTR_INFO_VERSION_NAME:
+ key = parseInfoValue(nestedAttr.Value)
+ case nl.DEVLINK_ATTR_INFO_VERSION_VALUE:
+ value = parseInfoValue(nestedAttr.Value)
+ }
+ }
+
+ if key == "" {
+ return "", "", fmt.Errorf("getNestedInfoData: key not found")
+ }
+
+ if value == "" {
+ return "", "", fmt.Errorf("getNestedInfoData: value not found")
+ }
+
+ return key, value, nil
+}
+
+func parseInfoData(data map[string]string) *DevlinkDeviceInfo {
+ info := new(DevlinkDeviceInfo)
+ for key, value := range data {
+ switch key {
+ case "driver":
+ info.Driver = value
+ case "serialNumber":
+ info.SerialNumber = value
+ case "board.id":
+ info.BoardID = value
+ case "fw.app":
+ info.FwApp = value
+ case "fw.app.bundle_id":
+ info.FwAppBoundleID = value
+ case "fw.app.name":
+ info.FwAppName = value
+ case "fw.bundle_id":
+ info.FwBoundleID = value
+ case "fw.mgmt":
+ info.FwMgmt = value
+ case "fw.mgmt.api":
+ info.FwMgmtAPI = value
+ case "fw.mgmt.build":
+ info.FwMgmtBuild = value
+ case "fw.netlist":
+ info.FwNetlist = value
+ case "fw.netlist.build":
+ info.FwNetlistBuild = value
+ case "fw.psid.api":
+ info.FwPsidAPI = value
+ case "fw.undi":
+ info.FwUndi = value
+ }
+ }
+ return info
+}
+
+func parseInfoValue(value []byte) string {
+ v := strings.ReplaceAll(string(value), "\x00", "")
+ return strings.TrimSpace(v)
+}
diff --git a/vendor/github.com/vishvananda/netlink/filter.go b/vendor/github.com/vishvananda/netlink/filter.go
index 2dc34b995..413abdb47 100644
--- a/vendor/github.com/vishvananda/netlink/filter.go
+++ b/vendor/github.com/vishvananda/netlink/filter.go
@@ -260,6 +260,40 @@ func NewSkbEditAction() *SkbEditAction {
}
}
+type PoliceAction struct {
+ ActionAttrs
+ Rate uint32 // in byte per second
+ Burst uint32 // in byte
+ RCellLog int
+ Mtu uint32
+ Mpu uint16 // in byte
+ PeakRate uint32 // in byte per second
+ PCellLog int
+ AvRate uint32 // in byte per second
+ Overhead uint16
+ LinkLayer int
+ ExceedAction TcPolAct
+ NotExceedAction TcPolAct
+}
+
+func (action *PoliceAction) Type() string {
+ return "police"
+}
+
+func (action *PoliceAction) Attrs() *ActionAttrs {
+ return &action.ActionAttrs
+}
+
+func NewPoliceAction() *PoliceAction {
+ return &PoliceAction{
+ RCellLog: -1,
+ PCellLog: -1,
+ LinkLayer: 1, // ETHERNET
+ ExceedAction: TC_POLICE_RECLASSIFY,
+ NotExceedAction: TC_POLICE_OK,
+ }
+}
+
// MatchAll filters match all packets
type MatchAll struct {
FilterAttrs
@@ -275,20 +309,20 @@ func (filter *MatchAll) Type() string {
return "matchall"
}
-type FilterFwAttrs struct {
- ClassId uint32
- InDev string
- Mask uint32
- Index uint32
- Buffer uint32
- Mtu uint32
- Mpu uint16
- Rate uint32
- AvRate uint32
- PeakRate uint32
- Action TcPolAct
- Overhead uint16
- LinkLayer int
+type FwFilter struct {
+ FilterAttrs
+ ClassId uint32
+ InDev string
+ Mask uint32
+ Police *PoliceAction
+}
+
+func (filter *FwFilter) Attrs() *FilterAttrs {
+ return &filter.FilterAttrs
+}
+
+func (filter *FwFilter) Type() string {
+ return "fw"
}
type BpfFilter struct {
diff --git a/vendor/github.com/vishvananda/netlink/filter_linux.go b/vendor/github.com/vishvananda/netlink/filter_linux.go
index 2cd46266c..3cfea4586 100644
--- a/vendor/github.com/vishvananda/netlink/filter_linux.go
+++ b/vendor/github.com/vishvananda/netlink/filter_linux.go
@@ -6,6 +6,7 @@ import (
"encoding/hex"
"errors"
"fmt"
+ "net"
"syscall"
"github.com/vishvananda/netlink/nl"
@@ -50,74 +51,129 @@ func (filter *U32) Type() string {
return "u32"
}
-// Fw filter filters on firewall marks
-// NOTE: this is in filter_linux because it refers to nl.TcPolice which
-// is defined in nl/tc_linux.go
-type Fw struct {
+type Flower struct {
FilterAttrs
- ClassId uint32
- // TODO remove nl type from interface
- Police nl.TcPolice
- InDev string
- // TODO Action
- Mask uint32
- AvRate uint32
- Rtab [256]uint32
- Ptab [256]uint32
-}
-
-func NewFw(attrs FilterAttrs, fattrs FilterFwAttrs) (*Fw, error) {
- var rtab [256]uint32
- var ptab [256]uint32
- rcellLog := -1
- pcellLog := -1
- avrate := fattrs.AvRate / 8
- police := nl.TcPolice{}
- police.Rate.Rate = fattrs.Rate / 8
- police.PeakRate.Rate = fattrs.PeakRate / 8
- buffer := fattrs.Buffer
- linklayer := nl.LINKLAYER_ETHERNET
+ DestIP net.IP
+ DestIPMask net.IPMask
+ SrcIP net.IP
+ SrcIPMask net.IPMask
+ EthType uint16
+ EncDestIP net.IP
+ EncDestIPMask net.IPMask
+ EncSrcIP net.IP
+ EncSrcIPMask net.IPMask
+ EncDestPort uint16
+ EncKeyId uint32
+
+ Actions []Action
+}
- if fattrs.LinkLayer != nl.LINKLAYER_UNSPEC {
- linklayer = fattrs.LinkLayer
- }
+func (filter *Flower) Attrs() *FilterAttrs {
+ return &filter.FilterAttrs
+}
- police.Action = int32(fattrs.Action)
- if police.Rate.Rate != 0 {
- police.Rate.Mpu = fattrs.Mpu
- police.Rate.Overhead = fattrs.Overhead
- if CalcRtable(&police.Rate, rtab[:], rcellLog, fattrs.Mtu, linklayer) < 0 {
- return nil, errors.New("TBF: failed to calculate rate table")
- }
- police.Burst = Xmittime(uint64(police.Rate.Rate), uint32(buffer))
+func (filter *Flower) Type() string {
+ return "flower"
+}
+
+func (filter *Flower) encodeIP(parent *nl.RtAttr, ip net.IP, mask net.IPMask, v4Type, v6Type int, v4MaskType, v6MaskType int) {
+ ipType := v4Type
+ maskType := v4MaskType
+
+ encodeMask := mask
+ if mask == nil {
+ encodeMask = net.CIDRMask(32, 32)
}
- police.Mtu = fattrs.Mtu
- if police.PeakRate.Rate != 0 {
- police.PeakRate.Mpu = fattrs.Mpu
- police.PeakRate.Overhead = fattrs.Overhead
- if CalcRtable(&police.PeakRate, ptab[:], pcellLog, fattrs.Mtu, linklayer) < 0 {
- return nil, errors.New("POLICE: failed to calculate peak rate table")
- }
+ v4IP := ip.To4()
+ if v4IP == nil {
+ ipType = v6Type
+ maskType = v6MaskType
+ if mask == nil {
+ encodeMask = net.CIDRMask(128, 128)
+ }
+ } else {
+ ip = v4IP
}
- return &Fw{
- FilterAttrs: attrs,
- ClassId: fattrs.ClassId,
- InDev: fattrs.InDev,
- Mask: fattrs.Mask,
- Police: police,
- AvRate: avrate,
- Rtab: rtab,
- Ptab: ptab,
- }, nil
+ parent.AddRtAttr(ipType, ip)
+ parent.AddRtAttr(maskType, encodeMask)
}
-func (filter *Fw) Attrs() *FilterAttrs {
- return &filter.FilterAttrs
+func (filter *Flower) encode(parent *nl.RtAttr) error {
+ if filter.EthType != 0 {
+ parent.AddRtAttr(nl.TCA_FLOWER_KEY_ETH_TYPE, htons(filter.EthType))
+ }
+ if filter.SrcIP != nil {
+ filter.encodeIP(parent, filter.SrcIP, filter.SrcIPMask,
+ nl.TCA_FLOWER_KEY_IPV4_SRC, nl.TCA_FLOWER_KEY_IPV6_SRC,
+ nl.TCA_FLOWER_KEY_IPV4_SRC_MASK, nl.TCA_FLOWER_KEY_IPV6_SRC_MASK)
+ }
+ if filter.DestIP != nil {
+ filter.encodeIP(parent, filter.DestIP, filter.DestIPMask,
+ nl.TCA_FLOWER_KEY_IPV4_DST, nl.TCA_FLOWER_KEY_IPV6_DST,
+ nl.TCA_FLOWER_KEY_IPV4_DST_MASK, nl.TCA_FLOWER_KEY_IPV6_DST_MASK)
+ }
+ if filter.EncSrcIP != nil {
+ filter.encodeIP(parent, filter.EncSrcIP, filter.EncSrcIPMask,
+ nl.TCA_FLOWER_KEY_ENC_IPV4_SRC, nl.TCA_FLOWER_KEY_ENC_IPV6_SRC,
+ nl.TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK, nl.TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK)
+ }
+ if filter.EncDestIP != nil {
+ filter.encodeIP(parent, filter.EncDestIP, filter.EncSrcIPMask,
+ nl.TCA_FLOWER_KEY_ENC_IPV4_DST, nl.TCA_FLOWER_KEY_ENC_IPV6_DST,
+ nl.TCA_FLOWER_KEY_ENC_IPV4_DST_MASK, nl.TCA_FLOWER_KEY_ENC_IPV6_DST_MASK)
+ }
+ if filter.EncDestPort != 0 {
+ parent.AddRtAttr(nl.TCA_FLOWER_KEY_ENC_UDP_DST_PORT, htons(filter.EncDestPort))
+ }
+ if filter.EncKeyId != 0 {
+ parent.AddRtAttr(nl.TCA_FLOWER_KEY_ENC_KEY_ID, htonl(filter.EncKeyId))
+ }
+
+ actionsAttr := parent.AddRtAttr(nl.TCA_FLOWER_ACT, nil)
+ if err := EncodeActions(actionsAttr, filter.Actions); err != nil {
+ return err
+ }
+ return nil
}
-func (filter *Fw) Type() string {
- return "fw"
+func (filter *Flower) decode(data []syscall.NetlinkRouteAttr) error {
+ for _, datum := range data {
+ switch datum.Attr.Type {
+ case nl.TCA_FLOWER_KEY_ETH_TYPE:
+ filter.EthType = ntohs(datum.Value)
+ case nl.TCA_FLOWER_KEY_IPV4_SRC, nl.TCA_FLOWER_KEY_IPV6_SRC:
+ filter.SrcIP = datum.Value
+ case nl.TCA_FLOWER_KEY_IPV4_SRC_MASK, nl.TCA_FLOWER_KEY_IPV6_SRC_MASK:
+ filter.SrcIPMask = datum.Value
+ case nl.TCA_FLOWER_KEY_IPV4_DST, nl.TCA_FLOWER_KEY_IPV6_DST:
+ filter.DestIP = datum.Value
+ case nl.TCA_FLOWER_KEY_IPV4_DST_MASK, nl.TCA_FLOWER_KEY_IPV6_DST_MASK:
+ filter.DestIPMask = datum.Value
+ case nl.TCA_FLOWER_KEY_ENC_IPV4_SRC, nl.TCA_FLOWER_KEY_ENC_IPV6_SRC:
+ filter.EncSrcIP = datum.Value
+ case nl.TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK, nl.TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK:
+ filter.EncSrcIPMask = datum.Value
+ case nl.TCA_FLOWER_KEY_ENC_IPV4_DST, nl.TCA_FLOWER_KEY_ENC_IPV6_DST:
+ filter.EncDestIP = datum.Value
+ case nl.TCA_FLOWER_KEY_ENC_IPV4_DST_MASK, nl.TCA_FLOWER_KEY_ENC_IPV6_DST_MASK:
+ filter.EncDestIPMask = datum.Value
+ case nl.TCA_FLOWER_KEY_ENC_UDP_DST_PORT:
+ filter.EncDestPort = ntohs(datum.Value)
+ case nl.TCA_FLOWER_KEY_ENC_KEY_ID:
+ filter.EncKeyId = ntohl(datum.Value)
+ case nl.TCA_FLOWER_ACT:
+ tables, err := nl.ParseRouteAttr(datum.Value)
+ if err != nil {
+ return err
+ }
+ filter.Actions, err = parseActions(tables)
+ if err != nil {
+ return err
+ }
+ }
+ }
+ return nil
}
// FilterDel will delete a filter from the system.
@@ -169,7 +225,6 @@ func (h *Handle) FilterReplace(filter Filter) error {
}
func (h *Handle) filterModify(filter Filter, flags int) error {
- native = nl.NativeEndian()
req := h.newNetlinkRequest(unix.RTM_NEWTFILTER, flags|unix.NLM_F_ACK)
base := filter.Attrs()
msg := &nl.TcMsg{
@@ -237,7 +292,7 @@ func (h *Handle) filterModify(filter Filter, flags int) error {
if err := EncodeActions(actionsAttr, filter.Actions); err != nil {
return err
}
- case *Fw:
+ case *FwFilter:
if filter.Mask != 0 {
b := make([]byte, 4)
native.PutUint32(b, filter.Mask)
@@ -246,17 +301,10 @@ func (h *Handle) filterModify(filter Filter, flags int) error {
if filter.InDev != "" {
options.AddRtAttr(nl.TCA_FW_INDEV, nl.ZeroTerminated(filter.InDev))
}
- if (filter.Police != nl.TcPolice{}) {
-
+ if filter.Police != nil {
police := options.AddRtAttr(nl.TCA_FW_POLICE, nil)
- police.AddRtAttr(nl.TCA_POLICE_TBF, filter.Police.Serialize())
- if (filter.Police.Rate != nl.TcRateSpec{}) {
- payload := SerializeRtab(filter.Rtab)
- police.AddRtAttr(nl.TCA_POLICE_RATE, payload)
- }
- if (filter.Police.PeakRate != nl.TcRateSpec{}) {
- payload := SerializeRtab(filter.Ptab)
- police.AddRtAttr(nl.TCA_POLICE_PEAKRATE, payload)
+ if err := encodePolice(police, filter.Police); err != nil {
+ return err
}
}
if filter.ClassId != 0 {
@@ -287,6 +335,10 @@ func (h *Handle) filterModify(filter Filter, flags int) error {
if filter.ClassId != 0 {
options.AddRtAttr(nl.TCA_MATCHALL_CLASSID, nl.Uint32Attr(filter.ClassId))
}
+ case *Flower:
+ if err := filter.encode(options); err != nil {
+ return err
+ }
}
req.AddData(options)
@@ -350,11 +402,13 @@ func (h *Handle) FilterList(link Link, parent uint32) ([]Filter, error) {
case "u32":
filter = &U32{}
case "fw":
- filter = &Fw{}
+ filter = &FwFilter{}
case "bpf":
filter = &BpfFilter{}
case "matchall":
filter = &MatchAll{}
+ case "flower":
+ filter = &Flower{}
default:
filter = &GenericFilter{FilterType: filterType}
}
@@ -384,6 +438,11 @@ func (h *Handle) FilterList(link Link, parent uint32) ([]Filter, error) {
if err != nil {
return nil, err
}
+ case "flower":
+ detailed, err = parseFlowerData(filter, data)
+ if err != nil {
+ return nil, err
+ }
default:
detailed = true
}
@@ -415,6 +474,53 @@ func toAttrs(tcgen *nl.TcGen, attrs *ActionAttrs) {
attrs.Bindcnt = int(tcgen.Bindcnt)
}
+func encodePolice(attr *nl.RtAttr, action *PoliceAction) error {
+ var rtab [256]uint32
+ var ptab [256]uint32
+ police := nl.TcPolice{}
+ police.Index = uint32(action.Attrs().Index)
+ police.Bindcnt = int32(action.Attrs().Bindcnt)
+ police.Capab = uint32(action.Attrs().Capab)
+ police.Refcnt = int32(action.Attrs().Refcnt)
+ police.Rate.Rate = action.Rate
+ police.PeakRate.Rate = action.PeakRate
+ police.Action = int32(action.ExceedAction)
+
+ if police.Rate.Rate != 0 {
+ police.Rate.Mpu = action.Mpu
+ police.Rate.Overhead = action.Overhead
+ if CalcRtable(&police.Rate, rtab[:], action.RCellLog, action.Mtu, action.LinkLayer) < 0 {
+ return errors.New("TBF: failed to calculate rate table")
+ }
+ police.Burst = Xmittime(uint64(police.Rate.Rate), action.Burst)
+ }
+
+ police.Mtu = action.Mtu
+ if police.PeakRate.Rate != 0 {
+ police.PeakRate.Mpu = action.Mpu
+ police.PeakRate.Overhead = action.Overhead
+ if CalcRtable(&police.PeakRate, ptab[:], action.PCellLog, action.Mtu, action.LinkLayer) < 0 {
+ return errors.New("POLICE: failed to calculate peak rate table")
+ }
+ }
+
+ attr.AddRtAttr(nl.TCA_POLICE_TBF, police.Serialize())
+ if police.Rate.Rate != 0 {
+ attr.AddRtAttr(nl.TCA_POLICE_RATE, SerializeRtab(rtab))
+ }
+ if police.PeakRate.Rate != 0 {
+ attr.AddRtAttr(nl.TCA_POLICE_PEAKRATE, SerializeRtab(ptab))
+ }
+ if action.AvRate != 0 {
+ attr.AddRtAttr(nl.TCA_POLICE_AVRATE, nl.Uint32Attr(action.AvRate))
+ }
+ if action.NotExceedAction != 0 {
+ attr.AddRtAttr(nl.TCA_POLICE_RESULT, nl.Uint32Attr(uint32(action.NotExceedAction)))
+ }
+
+ return nil
+}
+
func EncodeActions(attr *nl.RtAttr, actions []Action) error {
tabIndex := int(nl.TCA_ACT_TAB)
@@ -422,6 +528,14 @@ func EncodeActions(attr *nl.RtAttr, actions []Action) error {
switch action := action.(type) {
default:
return fmt.Errorf("unknown action type %s", action.Type())
+ case *PoliceAction:
+ table := attr.AddRtAttr(tabIndex, nil)
+ tabIndex++
+ table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("police"))
+ aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil)
+ if err := encodePolice(aopts, action); err != nil {
+ return err
+ }
case *MirredAction:
table := attr.AddRtAttr(tabIndex, nil)
tabIndex++
@@ -516,6 +630,29 @@ func EncodeActions(attr *nl.RtAttr, actions []Action) error {
return nil
}
+func parsePolice(data syscall.NetlinkRouteAttr, police *PoliceAction) {
+ switch data.Attr.Type {
+ case nl.TCA_POLICE_RESULT:
+ police.NotExceedAction = TcPolAct(native.Uint32(data.Value[0:4]))
+ case nl.TCA_POLICE_AVRATE:
+ police.AvRate = native.Uint32(data.Value[0:4])
+ case nl.TCA_POLICE_TBF:
+ p := *nl.DeserializeTcPolice(data.Value)
+ police.ActionAttrs = ActionAttrs{}
+ police.Attrs().Index = int(p.Index)
+ police.Attrs().Bindcnt = int(p.Bindcnt)
+ police.Attrs().Capab = int(p.Capab)
+ police.Attrs().Refcnt = int(p.Refcnt)
+ police.ExceedAction = TcPolAct(p.Action)
+ police.Rate = p.Rate.Rate
+ police.PeakRate = p.PeakRate.Rate
+ police.Burst = Xmitsize(uint64(p.Rate.Rate), p.Burst)
+ police.Mtu = p.Mtu
+ police.LinkLayer = int(p.Rate.Linklayer) & nl.TC_LINKLAYER_MASK
+ police.Overhead = p.Rate.Overhead
+ }
+}
+
func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
var actions []Action
for _, table := range tables {
@@ -544,6 +681,8 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
action = &TunnelKeyAction{}
case "skbedit":
action = &SkbEditAction{}
+ case "police":
+ action = &PoliceAction{}
default:
break nextattr
}
@@ -622,6 +761,8 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
gen := *nl.DeserializeTcGen(adatum.Value)
toAttrs(&gen, action.Attrs())
}
+ case "police":
+ parsePolice(adatum, action.(*PoliceAction))
}
}
}
@@ -632,7 +773,6 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) {
}
func parseU32Data(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
- native = nl.NativeEndian()
u32 := filter.(*U32)
detailed := false
for _, datum := range data {
@@ -678,8 +818,7 @@ func parseU32Data(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error)
}
func parseFwData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
- native = nl.NativeEndian()
- fw := filter.(*Fw)
+ fw := filter.(*FwFilter)
detailed := true
for _, datum := range data {
switch datum.Attr.Type {
@@ -690,24 +829,18 @@ func parseFwData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
case nl.TCA_FW_INDEV:
fw.InDev = string(datum.Value[:len(datum.Value)-1])
case nl.TCA_FW_POLICE:
+ var police PoliceAction
adata, _ := nl.ParseRouteAttr(datum.Value)
for _, aattr := range adata {
- switch aattr.Attr.Type {
- case nl.TCA_POLICE_TBF:
- fw.Police = *nl.DeserializeTcPolice(aattr.Value)
- case nl.TCA_POLICE_RATE:
- fw.Rtab = DeserializeRtab(aattr.Value)
- case nl.TCA_POLICE_PEAKRATE:
- fw.Ptab = DeserializeRtab(aattr.Value)
- }
+ parsePolice(aattr, &police)
}
+ fw.Police = &police
}
}
return detailed, nil
}
func parseBpfData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
- native = nl.NativeEndian()
bpf := filter.(*BpfFilter)
detailed := true
for _, datum := range data {
@@ -733,7 +866,6 @@ func parseBpfData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error)
}
func parseMatchAllData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
- native = nl.NativeEndian()
matchall := filter.(*MatchAll)
detailed := true
for _, datum := range data {
@@ -754,6 +886,10 @@ func parseMatchAllData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, er
return detailed, nil
}
+func parseFlowerData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) {
+ return true, filter.(*Flower).decode(data)
+}
+
func AlignToAtm(size uint) uint {
var linksize, cells int
cells = int(size / nl.ATM_CELL_PAYLOAD)
@@ -801,14 +937,12 @@ func CalcRtable(rate *nl.TcRateSpec, rtab []uint32, cellLog int, mtu uint32, lin
func DeserializeRtab(b []byte) [256]uint32 {
var rtab [256]uint32
- native := nl.NativeEndian()
r := bytes.NewReader(b)
_ = binary.Read(r, native, &rtab)
return rtab
}
func SerializeRtab(rtab [256]uint32) []byte {
- native := nl.NativeEndian()
var w bytes.Buffer
_ = binary.Write(&w, native, rtab)
return w.Bytes()
diff --git a/vendor/github.com/vishvananda/netlink/handle_linux.go b/vendor/github.com/vishvananda/netlink/handle_linux.go
index 65356679d..c02bfb7e6 100644
--- a/vendor/github.com/vishvananda/netlink/handle_linux.go
+++ b/vendor/github.com/vishvananda/netlink/handle_linux.go
@@ -15,7 +15,7 @@ var pkgHandle = &Handle{}
// Handle is an handle for the netlink requests on a
// specific network namespace. All the requests on the
// same netlink family share the same netlink socket,
-// which gets released when the handle is deleted.
+// which gets released when the handle is Close'd.
type Handle struct {
sockets map[int]*nl.SocketHandle
lookupByDump bool
@@ -136,14 +136,22 @@ func newHandle(newNs, curNs netns.NsHandle, nlFamilies ...int) (*Handle, error)
return h, nil
}
-// Delete releases the resources allocated to this handle
-func (h *Handle) Delete() {
+// Close releases the resources allocated to this handle
+func (h *Handle) Close() {
for _, sh := range h.sockets {
sh.Close()
}
h.sockets = nil
}
+// Delete releases the resources allocated to this handle
+//
+// Deprecated: use Close instead which is in line with typical resource release
+// patterns for files and other resources.
+func (h *Handle) Delete() {
+ h.Close()
+}
+
func (h *Handle) newNetlinkRequest(proto, flags int) *nl.NetlinkRequest {
// Do this so that package API still use nl package variable nextSeqNr
if h.sockets == nil {
diff --git a/vendor/github.com/vishvananda/netlink/handle_unspecified.go b/vendor/github.com/vishvananda/netlink/handle_unspecified.go
index 3a6db8137..cc94a4e00 100644
--- a/vendor/github.com/vishvananda/netlink/handle_unspecified.go
+++ b/vendor/github.com/vishvananda/netlink/handle_unspecified.go
@@ -23,6 +23,8 @@ func NewHandleAtFrom(newNs, curNs netns.NsHandle) (*Handle, error) {
return nil, ErrNotImplemented
}
+func (h *Handle) Close() {}
+
func (h *Handle) Delete() {}
func (h *Handle) SupportsNetlinkFamily(nlFamily int) bool {
diff --git a/vendor/github.com/vishvananda/netlink/ipset_linux.go b/vendor/github.com/vishvananda/netlink/ipset_linux.go
index 2adc2440a..1f4eae81c 100644
--- a/vendor/github.com/vishvananda/netlink/ipset_linux.go
+++ b/vendor/github.com/vishvananda/netlink/ipset_linux.go
@@ -1,6 +1,7 @@
package netlink
import (
+ "encoding/binary"
"log"
"net"
"syscall"
@@ -11,12 +12,19 @@ import (
// IPSetEntry is used for adding, updating, retreiving and deleting entries
type IPSetEntry struct {
- Comment string
- MAC net.HardwareAddr
- IP net.IP
- Timeout *uint32
- Packets *uint64
- Bytes *uint64
+ Comment string
+ MAC net.HardwareAddr
+ IP net.IP
+ CIDR uint8
+ Timeout *uint32
+ Packets *uint64
+ Bytes *uint64
+ Protocol *uint8
+ Port *uint16
+ IP2 net.IP
+ CIDR2 uint8
+ IFace string
+ Mark *uint32
Replace bool // replace existing entry
}
@@ -32,6 +40,12 @@ type IPSetResult struct {
SetName string
TypeName string
Comment string
+ MarkMask uint32
+
+ IPFrom net.IP
+ IPTo net.IP
+ PortFrom uint16
+ PortTo uint16
HashSize uint32
NumEntries uint32
@@ -52,6 +66,12 @@ type IpsetCreateOptions struct {
Counters bool
Comments bool
Skbinfo bool
+
+ Revision uint8
+ IPFrom net.IP
+ IPTo net.IP
+ PortFrom uint16
+ PortTo uint16
}
// IpsetProtocol returns the ipset protocol version from the kernel
@@ -86,12 +106,12 @@ func IpsetListAll() ([]IPSetResult, error) {
// IpsetAdd adds an entry to an existing ipset.
func IpsetAdd(setname string, entry *IPSetEntry) error {
- return pkgHandle.ipsetAddDel(nl.IPSET_CMD_ADD, setname, entry)
+ return pkgHandle.IpsetAdd(setname, entry)
}
// IpsetDel deletes an entry from an existing ipset.
func IpsetDel(setname string, entry *IPSetEntry) error {
- return pkgHandle.ipsetAddDel(nl.IPSET_CMD_DEL, setname, entry)
+ return pkgHandle.IpsetDel(setname, entry)
}
func (h *Handle) IpsetProtocol() (protocol uint8, minVersion uint8, err error) {
@@ -114,11 +134,30 @@ func (h *Handle) IpsetCreate(setname, typename string, options IpsetCreateOption
req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_SETNAME, nl.ZeroTerminated(setname)))
req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_TYPENAME, nl.ZeroTerminated(typename)))
- req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_REVISION, nl.Uint8Attr(0)))
- req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_FAMILY, nl.Uint8Attr(2))) // 2 == inet
+
+ revision := options.Revision
+ if revision == 0 {
+ revision = getIpsetDefaultWithTypeName(typename)
+ }
+ req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_REVISION, nl.Uint8Attr(revision)))
data := nl.NewRtAttr(nl.IPSET_ATTR_DATA|int(nl.NLA_F_NESTED), nil)
+ var family uint8
+ switch typename {
+ case "hash:mac":
+ case "bitmap:port":
+ buf := make([]byte, 4)
+ binary.BigEndian.PutUint16(buf, options.PortFrom)
+ binary.BigEndian.PutUint16(buf[2:], options.PortTo)
+ data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_PORT_FROM|int(nl.NLA_F_NET_BYTEORDER), buf[:2]))
+ data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_PORT_TO|int(nl.NLA_F_NET_BYTEORDER), buf[2:]))
+ default:
+ family = unix.AF_INET
+ }
+
+ req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_FAMILY, nl.Uint8Attr(family)))
+
if timeout := options.Timeout; timeout != nil {
data.AddChild(&nl.Uint32Attribute{Type: nl.IPSET_ATTR_TIMEOUT | nl.NLA_F_NET_BYTEORDER, Value: *timeout})
}
@@ -187,6 +226,16 @@ func (h *Handle) IpsetListAll() ([]IPSetResult, error) {
return result, nil
}
+// IpsetAdd adds an entry to an existing ipset.
+func (h *Handle) IpsetAdd(setname string, entry *IPSetEntry) error {
+ return h.ipsetAddDel(nl.IPSET_CMD_ADD, setname, entry)
+}
+
+// IpsetDel deletes an entry from an existing ipset.
+func (h *Handle) IpsetDel(setname string, entry *IPSetEntry) error {
+ return h.ipsetAddDel(nl.IPSET_CMD_DEL, setname, entry)
+}
+
func (h *Handle) ipsetAddDel(nlCmd int, setname string, entry *IPSetEntry) error {
req := h.newIpsetRequest(nlCmd)
req.AddData(nl.NewRtAttr(nl.IPSET_ATTR_SETNAME, nl.ZeroTerminated(setname)))
@@ -204,15 +253,49 @@ func (h *Handle) ipsetAddDel(nlCmd int, setname string, entry *IPSetEntry) error
if entry.Timeout != nil {
data.AddChild(&nl.Uint32Attribute{Type: nl.IPSET_ATTR_TIMEOUT | nl.NLA_F_NET_BYTEORDER, Value: *entry.Timeout})
}
- if entry.MAC != nil {
- nestedData := nl.NewRtAttr(nl.IPSET_ATTR_ETHER|int(nl.NLA_F_NET_BYTEORDER), entry.MAC)
- data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_ETHER|int(nl.NLA_F_NESTED), nestedData.Serialize()))
- }
+
if entry.IP != nil {
nestedData := nl.NewRtAttr(nl.IPSET_ATTR_IP|int(nl.NLA_F_NET_BYTEORDER), entry.IP)
data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_IP|int(nl.NLA_F_NESTED), nestedData.Serialize()))
}
+ if entry.MAC != nil {
+ data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_ETHER, entry.MAC))
+ }
+
+ if entry.CIDR != 0 {
+ data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_CIDR, nl.Uint8Attr(entry.CIDR)))
+ }
+
+ if entry.IP2 != nil {
+ nestedData := nl.NewRtAttr(nl.IPSET_ATTR_IP|int(nl.NLA_F_NET_BYTEORDER), entry.IP2)
+ data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_IP2|int(nl.NLA_F_NESTED), nestedData.Serialize()))
+ }
+
+ if entry.CIDR2 != 0 {
+ data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_CIDR2, nl.Uint8Attr(entry.CIDR2)))
+ }
+
+ if entry.Port != nil {
+ if entry.Protocol == nil {
+ // use tcp protocol as default
+ val := uint8(unix.IPPROTO_TCP)
+ entry.Protocol = &val
+ }
+ data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_PROTO, nl.Uint8Attr(*entry.Protocol)))
+ buf := make([]byte, 2)
+ binary.BigEndian.PutUint16(buf, *entry.Port)
+ data.AddChild(nl.NewRtAttr(int(nl.IPSET_ATTR_PORT|nl.NLA_F_NET_BYTEORDER), buf))
+ }
+
+ if entry.IFace != "" {
+ data.AddChild(nl.NewRtAttr(nl.IPSET_ATTR_IFACE, nl.ZeroTerminated(entry.IFace)))
+ }
+
+ if entry.Mark != nil {
+ data.AddChild(&nl.Uint32Attribute{Type: nl.IPSET_ATTR_MARK | nl.NLA_F_NET_BYTEORDER, Value: *entry.Mark})
+ }
+
data.AddChild(&nl.Uint32Attribute{Type: nl.IPSET_ATTR_LINENO | nl.NLA_F_NET_BYTEORDER, Value: 0})
req.AddData(data)
@@ -235,6 +318,17 @@ func (h *Handle) newIpsetRequest(cmd int) *nl.NetlinkRequest {
return req
}
+func getIpsetDefaultWithTypeName(typename string) uint8 {
+ switch typename {
+ case "hash:ip,port",
+ "hash:ip,port,ip",
+ "hash:ip,port,net",
+ "hash:net,port":
+ return 1
+ }
+ return 0
+}
+
func ipsetExecute(req *nl.NetlinkRequest) (msgs [][]byte, err error) {
msgs, err = req.Execute(unix.NETLINK_NETFILTER, 0)
@@ -278,6 +372,8 @@ func (result *IPSetResult) unserialize(msg []byte) {
result.parseAttrADT(attr.Value)
case nl.IPSET_ATTR_PROTOCOL_MIN:
result.ProtocolMinVersion = attr.Value[0]
+ case nl.IPSET_ATTR_MARKMASK:
+ result.MarkMask = attr.Uint32()
default:
log.Printf("unknown ipset attribute from kernel: %+v %v", attr, attr.Type&nl.NLA_TYPE_MASK)
}
@@ -307,12 +403,31 @@ func (result *IPSetResult) parseAttrData(data []byte) {
switch nested.Type {
case nl.IPSET_ATTR_IP | nl.NLA_F_NET_BYTEORDER:
result.Entries = append(result.Entries, IPSetEntry{IP: nested.Value})
+ case nl.IPSET_ATTR_IP:
+ result.IPFrom = nested.Value
+ default:
+ log.Printf("unknown nested ipset data attribute from kernel: %+v %v", nested, nested.Type&nl.NLA_TYPE_MASK)
+ }
+ }
+ case nl.IPSET_ATTR_IP_TO | nl.NLA_F_NESTED:
+ for nested := range nl.ParseAttributes(attr.Value) {
+ switch nested.Type {
+ case nl.IPSET_ATTR_IP:
+ result.IPTo = nested.Value
+ default:
+ log.Printf("unknown nested ipset data attribute from kernel: %+v %v", nested, nested.Type&nl.NLA_TYPE_MASK)
}
}
+ case nl.IPSET_ATTR_PORT_FROM | nl.NLA_F_NET_BYTEORDER:
+ result.PortFrom = networkOrder.Uint16(attr.Value)
+ case nl.IPSET_ATTR_PORT_TO | nl.NLA_F_NET_BYTEORDER:
+ result.PortTo = networkOrder.Uint16(attr.Value)
case nl.IPSET_ATTR_CADT_LINENO | nl.NLA_F_NET_BYTEORDER:
result.LineNo = attr.Uint32()
case nl.IPSET_ATTR_COMMENT:
result.Comment = nl.BytesToString(attr.Value)
+ case nl.IPSET_ATTR_MARKMASK:
+ result.MarkMask = attr.Uint32()
default:
log.Printf("unknown ipset data attribute from kernel: %+v %v", attr, attr.Type&nl.NLA_TYPE_MASK)
}
@@ -357,6 +472,30 @@ func parseIPSetEntry(data []byte) (entry IPSetEntry) {
log.Printf("unknown nested ADT attribute from kernel: %+v", attr)
}
}
+ case nl.IPSET_ATTR_IP2 | nl.NLA_F_NESTED:
+ for attr := range nl.ParseAttributes(attr.Value) {
+ switch attr.Type {
+ case nl.IPSET_ATTR_IP:
+ entry.IP2 = net.IP(attr.Value)
+ default:
+ log.Printf("unknown nested ADT attribute from kernel: %+v", attr)
+ }
+ }
+ case nl.IPSET_ATTR_CIDR:
+ entry.CIDR = attr.Value[0]
+ case nl.IPSET_ATTR_CIDR2:
+ entry.CIDR2 = attr.Value[0]
+ case nl.IPSET_ATTR_PORT | nl.NLA_F_NET_BYTEORDER:
+ val := networkOrder.Uint16(attr.Value)
+ entry.Port = &val
+ case nl.IPSET_ATTR_PROTO:
+ val := attr.Value[0]
+ entry.Protocol = &val
+ case nl.IPSET_ATTR_IFACE:
+ entry.IFace = nl.BytesToString(attr.Value)
+ case nl.IPSET_ATTR_MARK | nl.NLA_F_NET_BYTEORDER:
+ val := attr.Uint32()
+ entry.Mark = &val
default:
log.Printf("unknown ADT attribute from kernel: %+v", attr)
}
diff --git a/vendor/github.com/vishvananda/netlink/link.go b/vendor/github.com/vishvananda/netlink/link.go
index 32ca7cd64..82d0360eb 100644
--- a/vendor/github.com/vishvananda/netlink/link.go
+++ b/vendor/github.com/vishvananda/netlink/link.go
@@ -35,10 +35,13 @@ type LinkAttrs struct {
Alias string
Statistics *LinkStatistics
Promisc int
+ Allmulti int
+ Multi int
Xdp *LinkXdp
EncapType string
Protinfo *Protinfo
OperState LinkOperState
+ PhysSwitchID int
NetNsID int
NumTxQueues int
NumRxQueues int
@@ -456,6 +459,19 @@ func (ipvlan *IPVlan) Type() string {
return "ipvlan"
}
+// IPVtap - IPVtap is a virtual interfaces based on ipvlan
+type IPVtap struct {
+ IPVlan
+}
+
+func (ipvtap *IPVtap) Attrs() *LinkAttrs {
+ return &ipvtap.LinkAttrs
+}
+
+func (ipvtap IPVtap) Type() string {
+ return "ipvtap"
+}
+
// VlanProtocol type
type VlanProtocol int
@@ -946,6 +962,14 @@ func (b *BondSlave) SlaveType() string {
return "bond"
}
+type VrfSlave struct {
+ Table uint32
+}
+
+func (v *VrfSlave) SlaveType() string {
+ return "vrf"
+}
+
// Geneve devices must specify RemoteIP and ID (VNI) on create
// https://github.com/torvalds/linux/blob/47ec5303d73ea344e84f46660fff693c57641386/drivers/net/geneve.c#L1209-L1223
type Geneve struct {
@@ -1049,6 +1073,37 @@ func (ip6tnl *Ip6tnl) Type() string {
return "ip6tnl"
}
+// from https://elixir.bootlin.com/linux/v5.15.4/source/include/uapi/linux/if_tunnel.h#L84
+type TunnelEncapType uint16
+
+const (
+ None TunnelEncapType = iota
+ FOU
+ GUE
+)
+
+// from https://elixir.bootlin.com/linux/v5.15.4/source/include/uapi/linux/if_tunnel.h#L91
+type TunnelEncapFlag uint16
+
+const (
+ CSum TunnelEncapFlag = 1 << 0
+ CSum6 = 1 << 1
+ RemCSum = 1 << 2
+)
+
+// from https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/ip6_tunnel.h#L12
+type IP6TunnelFlag uint16
+
+const (
+ IP6_TNL_F_IGN_ENCAP_LIMIT IP6TunnelFlag = 1 // don't add encapsulation limit if one isn't present in inner packet
+ IP6_TNL_F_USE_ORIG_TCLASS = 2 // copy the traffic class field from the inner packet
+ IP6_TNL_F_USE_ORIG_FLOWLABEL = 4 // copy the flowlabel from the inner packet
+ IP6_TNL_F_MIP6_DEV = 8 // being used for Mobile IPv6
+ IP6_TNL_F_RCV_DSCP_COPY = 10 // copy DSCP from the outer packet
+ IP6_TNL_F_USE_ORIG_FWMARK = 20 // copy fwmark from inner packet
+ IP6_TNL_F_ALLOW_LOCAL_REMOTE = 40 // allow remote endpoint on the local node
+)
+
type Sittun struct {
LinkAttrs
Link uint32
@@ -1260,11 +1315,27 @@ func (ipoib *IPoIB) Type() string {
return "ipoib"
}
+type BareUDP struct {
+ LinkAttrs
+ Port uint16
+ EtherType uint16
+ SrcPortMin uint16
+ MultiProto bool
+}
+
+func (bareudp *BareUDP) Attrs() *LinkAttrs {
+ return &bareudp.LinkAttrs
+}
+
+func (bareudp *BareUDP) Type() string {
+ return "bareudp"
+}
+
// iproute2 supported devices;
// vlan | veth | vcan | dummy | ifb | macvlan | macvtap |
// bridge | bond | ipoib | ip6tnl | ipip | sit | vxlan |
// gre | gretap | ip6gre | ip6gretap | vti | vti6 | nlmon |
-// bond_slave | ipvlan | xfrm
+// bond_slave | ipvlan | xfrm | bareudp
// LinkNotFoundError wraps the various not found errors when
// getting/reading links. This is intended for better error
diff --git a/vendor/github.com/vishvananda/netlink/link_linux.go b/vendor/github.com/vishvananda/netlink/link_linux.go
index 3b959299c..aa998e311 100644
--- a/vendor/github.com/vishvananda/netlink/link_linux.go
+++ b/vendor/github.com/vishvananda/netlink/link_linux.go
@@ -55,8 +55,6 @@ const (
VF_LINK_STATE_DISABLE uint32 = 2
)
-var lookupByDump = false
-
var macvlanModes = [...]uint32{
0,
nl.MACVLAN_MODE_PRIVATE,
@@ -153,7 +151,6 @@ func (h *Handle) LinkSetAllmulticastOn(link Link) error {
msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
msg.Change = unix.IFF_ALLMULTI
msg.Flags = unix.IFF_ALLMULTI
-
msg.Index = int32(base.Index)
req.AddData(msg)
@@ -183,6 +180,51 @@ func (h *Handle) LinkSetAllmulticastOff(link Link) error {
return err
}
+// LinkSetMulticastOn enables the reception of multicast packets for the link device.
+// Equivalent to: `ip link set $link multicast on`
+func LinkSetMulticastOn(link Link) error {
+ return pkgHandle.LinkSetMulticastOn(link)
+}
+
+// LinkSetMulticastOn enables the reception of multicast packets for the link device.
+// Equivalent to: `ip link set $link multicast on`
+func (h *Handle) LinkSetMulticastOn(link Link) error {
+ base := link.Attrs()
+ h.ensureIndex(base)
+ req := h.newNetlinkRequest(unix.RTM_NEWLINK, unix.NLM_F_ACK)
+
+ msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
+ msg.Change = unix.IFF_MULTICAST
+ msg.Flags = unix.IFF_MULTICAST
+ msg.Index = int32(base.Index)
+ req.AddData(msg)
+
+ _, err := req.Execute(unix.NETLINK_ROUTE, 0)
+ return err
+}
+
+// LinkSetAllmulticastOff disables the reception of multicast packets for the link device.
+// Equivalent to: `ip link set $link multicast off`
+func LinkSetMulticastOff(link Link) error {
+ return pkgHandle.LinkSetMulticastOff(link)
+}
+
+// LinkSetAllmulticastOff disables the reception of multicast packets for the link device.
+// Equivalent to: `ip link set $link multicast off`
+func (h *Handle) LinkSetMulticastOff(link Link) error {
+ base := link.Attrs()
+ h.ensureIndex(base)
+ req := h.newNetlinkRequest(unix.RTM_NEWLINK, unix.NLM_F_ACK)
+
+ msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
+ msg.Change = unix.IFF_MULTICAST
+ msg.Index = int32(base.Index)
+ req.AddData(msg)
+
+ _, err := req.Execute(unix.NETLINK_ROUTE, 0)
+ return err
+}
+
func MacvlanMACAddrAdd(link Link, addr net.HardwareAddr) error {
return pkgHandle.MacvlanMACAddrAdd(link, addr)
}
@@ -547,13 +589,13 @@ func (h *Handle) LinkSetVfVlanQos(link Link, vf, vlan, qos int) error {
req.AddData(msg)
data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil)
- info := nl.NewRtAttrChild(data, nl.IFLA_VF_INFO, nil)
+ info := data.AddRtAttr(nl.IFLA_VF_INFO, nil)
vfmsg := nl.VfVlan{
Vf: uint32(vf),
Vlan: uint32(vlan),
Qos: uint32(qos),
}
- nl.NewRtAttrChild(info, nl.IFLA_VF_VLAN, vfmsg.Serialize())
+ info.AddRtAttr(nl.IFLA_VF_VLAN, vfmsg.Serialize())
req.AddData(data)
_, err := req.Execute(unix.NETLINK_ROUTE, 0)
@@ -1104,6 +1146,10 @@ func (h *Handle) LinkAdd(link Link) error {
return h.linkModify(link, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK)
}
+func LinkModify(link Link) error {
+ return pkgHandle.LinkModify(link)
+}
+
func (h *Handle) LinkModify(link Link) error {
return h.linkModify(link, unix.NLM_F_REQUEST|unix.NLM_F_ACK)
}
@@ -1218,9 +1264,26 @@ func (h *Handle) linkModify(link Link, flags int) error {
}
+ control := func(file *os.File, f func(fd uintptr)) error {
+ name := file.Name()
+ conn, err := file.SyscallConn()
+ if err != nil {
+ return fmt.Errorf("SyscallConn() failed on %s: %v", name, err)
+ }
+ if err := conn.Control(f); err != nil {
+ return fmt.Errorf("Failed to get file descriptor for %s: %v", name, err)
+ }
+ return nil
+ }
+
// only persist interface if NonPersist is NOT set
if !tuntap.NonPersist {
- _, _, errno := unix.Syscall(unix.SYS_IOCTL, fds[0].Fd(), uintptr(unix.TUNSETPERSIST), 1)
+ var errno syscall.Errno
+ if err := control(fds[0], func(fd uintptr) {
+ _, _, errno = unix.Syscall(unix.SYS_IOCTL, fd, uintptr(unix.TUNSETPERSIST), 1)
+ }); err != nil {
+ return err
+ }
if errno != 0 {
cleanupFds(fds)
return fmt.Errorf("Tuntap IOCTL TUNSETPERSIST failed, errno %v", errno)
@@ -1237,7 +1300,10 @@ func (h *Handle) linkModify(link Link, flags int) error {
// un-persist (e.g. allow the interface to be removed) the tuntap
// should not hurt if not set prior, condition might be not needed
if !tuntap.NonPersist {
- _, _, _ = unix.Syscall(unix.SYS_IOCTL, fds[0].Fd(), uintptr(unix.TUNSETPERSIST), 0)
+ // ignore error
+ _ = control(fds[0], func(fd uintptr) {
+ _, _, _ = unix.Syscall(unix.SYS_IOCTL, fd, uintptr(unix.TUNSETPERSIST), 0)
+ })
}
cleanupFds(fds)
return err
@@ -1409,6 +1475,10 @@ func (h *Handle) linkModify(link Link, flags int) error {
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
data.AddRtAttr(nl.IFLA_IPVLAN_MODE, nl.Uint16Attr(uint16(link.Mode)))
data.AddRtAttr(nl.IFLA_IPVLAN_FLAG, nl.Uint16Attr(uint16(link.Flag)))
+ case *IPVtap:
+ data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
+ data.AddRtAttr(nl.IFLA_IPVLAN_MODE, nl.Uint16Attr(uint16(link.Mode)))
+ data.AddRtAttr(nl.IFLA_IPVLAN_FLAG, nl.Uint16Attr(uint16(link.Flag)))
case *Macvlan:
if link.Mode != MACVLAN_MODE_DEFAULT {
data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
@@ -1443,6 +1513,8 @@ func (h *Handle) linkModify(link Link, flags int) error {
addXfrmiAttrs(link, linkInfo)
case *IPoIB:
addIPoIBAttrs(link, linkInfo)
+ case *BareUDP:
+ addBareUDPAttrs(link, linkInfo)
}
req.AddData(linkInfo)
@@ -1624,7 +1696,7 @@ func execGetLink(req *nl.NetlinkRequest) (Link, error) {
}
}
-// linkDeserialize deserializes a raw message received from netlink into
+// LinkDeserialize deserializes a raw message received from netlink into
// a link object.
func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
msg := nl.DeserializeIfInfomsg(m)
@@ -1639,9 +1711,17 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
base.RawFlags = msg.Flags
base.Flags = linkFlags(msg.Flags)
base.EncapType = msg.EncapType()
+ base.NetNsID = -1
if msg.Flags&unix.IFF_PROMISC != 0 {
base.Promisc = 1
}
+ if msg.Flags&unix.IFF_ALLMULTI != 0 {
+ base.Allmulti = 1
+ }
+ if msg.Flags&unix.IFF_MULTICAST != 0 {
+ base.Multi = 1
+ }
+
var (
link Link
stats32 *LinkStatistics32
@@ -1680,6 +1760,8 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
link = &Bond{}
case "ipvlan":
link = &IPVlan{}
+ case "ipvtap":
+ link = &IPVtap{}
case "macvlan":
link = &Macvlan{}
case "macvtap":
@@ -1714,6 +1796,8 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
link = &IPoIB{}
case "can":
link = &Can{}
+ case "bareudp":
+ link = &BareUDP{}
default:
link = &GenericLink{LinkType: linkType}
}
@@ -1731,6 +1815,8 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
parseBondData(link, data)
case "ipvlan":
parseIPVlanData(link, data)
+ case "ipvtap":
+ parseIPVtapData(link, data)
case "macvlan":
parseMacvlanData(link, data)
case "macvtap":
@@ -1767,13 +1853,19 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
parseIPoIBData(link, data)
case "can":
parseCanData(link, data)
+ case "bareudp":
+ parseBareUDPData(link, data)
}
+
case nl.IFLA_INFO_SLAVE_KIND:
slaveType = string(info.Value[:len(info.Value)-1])
switch slaveType {
case "bond":
linkSlave = &BondSlave{}
+ case "vrf":
+ linkSlave = &VrfSlave{}
}
+
case nl.IFLA_INFO_SLAVE_DATA:
switch slaveType {
case "bond":
@@ -1782,6 +1874,12 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
return nil, err
}
parseBondSlaveData(linkSlave, data)
+ case "vrf":
+ data, err := nl.ParseRouteAttr(info.Value)
+ if err != nil {
+ return nil, err
+ }
+ parseVrfSlaveData(linkSlave, data)
}
}
}
@@ -1835,6 +1933,8 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
}
case unix.IFLA_OPERSTATE:
base.OperState = LinkOperState(uint8(attr.Value[0]))
+ case unix.IFLA_PHYS_SWITCH_ID:
+ base.PhysSwitchID = int(native.Uint32(attr.Value[0:4]))
case unix.IFLA_LINK_NETNSID:
base.NetNsID = int(native.Uint32(attr.Value[0:4]))
case unix.IFLA_GSO_MAX_SIZE:
@@ -2023,7 +2123,8 @@ func linkSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- LinkUpdate, done <-c
msgs, from, err := s.Receive()
if err != nil {
if cberr != nil {
- cberr(err)
+ cberr(fmt.Errorf("Receive failed: %v",
+ err))
}
return
}
@@ -2038,15 +2139,15 @@ func linkSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- LinkUpdate, done <-c
continue
}
if m.Header.Type == unix.NLMSG_ERROR {
- native := nl.NativeEndian()
error := int32(native.Uint32(m.Data[0:4]))
if error == 0 {
continue
}
if cberr != nil {
- cberr(syscall.Errno(-error))
+ cberr(fmt.Errorf("error message: %v",
+ syscall.Errno(-error)))
}
- return
+ continue
}
ifmsg := nl.DeserializeIfInfomsg(m.Data)
header := unix.NlMsghdr(m.Header)
@@ -2055,7 +2156,7 @@ func linkSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- LinkUpdate, done <-c
if cberr != nil {
cberr(err)
}
- return
+ continue
}
ch <- LinkUpdate{IfInfomsg: *ifmsg, Header: header, Link: link}
}
@@ -2404,6 +2505,16 @@ func parseBondSlaveData(slave LinkSlave, data []syscall.NetlinkRouteAttr) {
}
}
+func parseVrfSlaveData(slave LinkSlave, data []syscall.NetlinkRouteAttr) {
+ vrfSlave := slave.(*VrfSlave)
+ for i := range data {
+ switch data[i].Attr.Type {
+ case nl.IFLA_BOND_SLAVE_STATE:
+ vrfSlave.Table = native.Uint32(data[i].Value[0:4])
+ }
+ }
+}
+
func parseIPVlanData(link Link, data []syscall.NetlinkRouteAttr) {
ipv := link.(*IPVlan)
for _, datum := range data {
@@ -2416,6 +2527,18 @@ func parseIPVlanData(link Link, data []syscall.NetlinkRouteAttr) {
}
}
+func parseIPVtapData(link Link, data []syscall.NetlinkRouteAttr) {
+ ipv := link.(*IPVtap)
+ for _, datum := range data {
+ switch datum.Attr.Type {
+ case nl.IFLA_IPVLAN_MODE:
+ ipv.Mode = IPVlanMode(native.Uint32(datum.Value[0:4]))
+ case nl.IFLA_IPVLAN_FLAG:
+ ipv.Flag = IPVlanFlag(native.Uint32(datum.Value[0:4]))
+ }
+ }
+}
+
func parseMacvtapData(link Link, data []syscall.NetlinkRouteAttr) {
macv := link.(*Macvtap)
parseMacvlanData(&macv.Macvlan, data)
@@ -2756,6 +2879,10 @@ func addIptunAttrs(iptun *Iptun, linkInfo *nl.RtAttr) {
func parseIptunData(link Link, data []syscall.NetlinkRouteAttr) {
iptun := link.(*Iptun)
for _, datum := range data {
+ // NOTE: same with vxlan, ip tunnel may also has null datum.Value
+ if len(datum.Value) == 0 {
+ continue
+ }
switch datum.Attr.Type {
case nl.IFLA_IPTUN_LOCAL:
iptun.Local = net.IP(datum.Value[0:4])
@@ -3303,3 +3430,32 @@ func addIPoIBAttrs(ipoib *IPoIB, linkInfo *nl.RtAttr) {
data.AddRtAttr(nl.IFLA_IPOIB_MODE, nl.Uint16Attr(uint16(ipoib.Mode)))
data.AddRtAttr(nl.IFLA_IPOIB_UMCAST, nl.Uint16Attr(uint16(ipoib.Umcast)))
}
+
+func addBareUDPAttrs(bareudp *BareUDP, linkInfo *nl.RtAttr) {
+ data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
+
+ data.AddRtAttr(nl.IFLA_BAREUDP_PORT, nl.Uint16Attr(nl.Swap16(bareudp.Port)))
+ data.AddRtAttr(nl.IFLA_BAREUDP_ETHERTYPE, nl.Uint16Attr(nl.Swap16(bareudp.EtherType)))
+ if bareudp.SrcPortMin != 0 {
+ data.AddRtAttr(nl.IFLA_BAREUDP_SRCPORT_MIN, nl.Uint16Attr(bareudp.SrcPortMin))
+ }
+ if bareudp.MultiProto {
+ data.AddRtAttr(nl.IFLA_BAREUDP_MULTIPROTO_MODE, []byte{})
+ }
+}
+
+func parseBareUDPData(link Link, data []syscall.NetlinkRouteAttr) {
+ bareudp := link.(*BareUDP)
+ for _, attr := range data {
+ switch attr.Attr.Type {
+ case nl.IFLA_BAREUDP_PORT:
+ bareudp.Port = binary.BigEndian.Uint16(attr.Value)
+ case nl.IFLA_BAREUDP_ETHERTYPE:
+ bareudp.EtherType = binary.BigEndian.Uint16(attr.Value)
+ case nl.IFLA_BAREUDP_SRCPORT_MIN:
+ bareudp.SrcPortMin = native.Uint16(attr.Value)
+ case nl.IFLA_BAREUDP_MULTIPROTO_MODE:
+ bareudp.MultiProto = true
+ }
+ }
+}
diff --git a/vendor/github.com/vishvananda/netlink/neigh.go b/vendor/github.com/vishvananda/netlink/neigh.go
index 379e5655f..32d722e88 100644
--- a/vendor/github.com/vishvananda/netlink/neigh.go
+++ b/vendor/github.com/vishvananda/netlink/neigh.go
@@ -12,6 +12,7 @@ type Neigh struct {
State int
Type int
Flags int
+ FlagsExt int
IP net.IP
HardwareAddr net.HardwareAddr
LLIPAddr net.IP //Used in the case of NHRP
diff --git a/vendor/github.com/vishvananda/netlink/neigh_linux.go b/vendor/github.com/vishvananda/netlink/neigh_linux.go
index fb220d141..4c1e76635 100644
--- a/vendor/github.com/vishvananda/netlink/neigh_linux.go
+++ b/vendor/github.com/vishvananda/netlink/neigh_linux.go
@@ -24,7 +24,11 @@ const (
NDA_MASTER
NDA_LINK_NETNSID
NDA_SRC_VNI
- NDA_MAX = NDA_SRC_VNI
+ NDA_PROTOCOL
+ NDA_NH_ID
+ NDA_FDB_EXT_ATTRS
+ NDA_FLAGS_EXT
+ NDA_MAX = NDA_FLAGS_EXT
)
// Neighbor Cache Entry States.
@@ -42,11 +46,19 @@ const (
// Neighbor Flags
const (
- NTF_USE = 0x01
- NTF_SELF = 0x02
- NTF_MASTER = 0x04
- NTF_PROXY = 0x08
- NTF_ROUTER = 0x80
+ NTF_USE = 0x01
+ NTF_SELF = 0x02
+ NTF_MASTER = 0x04
+ NTF_PROXY = 0x08
+ NTF_EXT_LEARNED = 0x10
+ NTF_OFFLOADED = 0x20
+ NTF_STICKY = 0x40
+ NTF_ROUTER = 0x80
+)
+
+// Extended Neighbor Flags
+const (
+ NTF_EXT_MANAGED = 0x00000001
)
// Ndmsg is for adding, removing or receiving information about a neighbor table entry
@@ -162,11 +174,16 @@ func neighHandle(neigh *Neigh, req *nl.NetlinkRequest) error {
if neigh.LLIPAddr != nil {
llIPData := nl.NewRtAttr(NDA_LLADDR, neigh.LLIPAddr.To4())
req.AddData(llIPData)
- } else if neigh.Flags != NTF_PROXY || neigh.HardwareAddr != nil {
+ } else if neigh.HardwareAddr != nil {
hwData := nl.NewRtAttr(NDA_LLADDR, []byte(neigh.HardwareAddr))
req.AddData(hwData)
}
+ if neigh.FlagsExt != 0 {
+ flagsExtData := nl.NewRtAttr(NDA_FLAGS_EXT, nl.Uint32Attr(uint32(neigh.FlagsExt)))
+ req.AddData(flagsExtData)
+ }
+
if neigh.Vlan != 0 {
vlanData := nl.NewRtAttr(NDA_VLAN, nl.Uint16Attr(uint16(neigh.Vlan)))
req.AddData(vlanData)
@@ -305,6 +322,8 @@ func NeighDeserialize(m []byte) (*Neigh, error) {
} else {
neigh.HardwareAddr = net.HardwareAddr(attr.Value)
}
+ case NDA_FLAGS_EXT:
+ neigh.FlagsExt = int(native.Uint32(attr.Value[0:4]))
case NDA_VLAN:
neigh.Vlan = int(native.Uint16(attr.Value[0:2]))
case NDA_VNI:
@@ -408,7 +427,6 @@ func neighSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- NeighUpdate, done <
continue
}
if m.Header.Type == unix.NLMSG_ERROR {
- native := nl.NativeEndian()
error := int32(native.Uint32(m.Data[0:4]))
if error == 0 {
continue
diff --git a/vendor/github.com/vishvananda/netlink/netlink_unspecified.go b/vendor/github.com/vishvananda/netlink/netlink_unspecified.go
index 71436f25c..98d2c0dbf 100644
--- a/vendor/github.com/vishvananda/netlink/netlink_unspecified.go
+++ b/vendor/github.com/vishvananda/netlink/netlink_unspecified.go
@@ -180,14 +180,30 @@ func RouteAdd(route *Route) error {
return ErrNotImplemented
}
+func RouteAppend(route *Route) error {
+ return ErrNotImplemented
+}
+
func RouteDel(route *Route) error {
return ErrNotImplemented
}
+func RouteGet(destination net.IP) ([]Route, error) {
+ return nil, ErrNotImplemented
+}
+
func RouteList(link Link, family int) ([]Route, error) {
return nil, ErrNotImplemented
}
+func RouteListFiltered(family int, filter *Route, filterMask uint64) ([]Route, error) {
+ return nil, ErrNotImplemented
+}
+
+func RouteReplace(route *Route) error {
+ return ErrNotImplemented
+}
+
func XfrmPolicyAdd(policy *XfrmPolicy) error {
return ErrNotImplemented
}
diff --git a/vendor/github.com/vishvananda/netlink/netns_linux.go b/vendor/github.com/vishvananda/netlink/netns_linux.go
index 77cf6f469..2eb29c7ce 100644
--- a/vendor/github.com/vishvananda/netlink/netns_linux.go
+++ b/vendor/github.com/vishvananda/netlink/netns_linux.go
@@ -87,7 +87,7 @@ func (h *Handle) getNetNsId(attrType int, val uint32) (int, error) {
rtgen := nl.NewRtGenMsg()
req.AddData(rtgen)
- b := make([]byte, 4, 4)
+ b := make([]byte, 4)
native.PutUint32(b, val)
attr := nl.NewRtAttr(attrType, b)
req.AddData(attr)
@@ -126,12 +126,12 @@ func (h *Handle) setNetNsId(attrType int, val uint32, newnsid uint32) error {
rtgen := nl.NewRtGenMsg()
req.AddData(rtgen)
- b := make([]byte, 4, 4)
+ b := make([]byte, 4)
native.PutUint32(b, val)
attr := nl.NewRtAttr(attrType, b)
req.AddData(attr)
- b1 := make([]byte, 4, 4)
+ b1 := make([]byte, 4)
native.PutUint32(b1, newnsid)
attr1 := nl.NewRtAttr(NETNSA_NSID, b1)
req.AddData(attr1)
diff --git a/vendor/github.com/vishvananda/netlink/nl/conntrack_linux.go b/vendor/github.com/vishvananda/netlink/nl/conntrack_linux.go
index 14924027e..183601803 100644
--- a/vendor/github.com/vishvananda/netlink/nl/conntrack_linux.go
+++ b/vendor/github.com/vishvananda/netlink/nl/conntrack_linux.go
@@ -44,6 +44,7 @@ const (
NLA_F_NESTED uint16 = (1 << 15) // #define NLA_F_NESTED (1 << 15)
NLA_F_NET_BYTEORDER uint16 = (1 << 14) // #define NLA_F_NESTED (1 << 14)
NLA_TYPE_MASK = ^(NLA_F_NESTED | NLA_F_NET_BYTEORDER)
+ NLA_ALIGNTO uint16 = 4 // #define NLA_ALIGNTO 4
)
// enum ctattr_type {
diff --git a/vendor/github.com/vishvananda/netlink/nl/devlink_linux.go b/vendor/github.com/vishvananda/netlink/nl/devlink_linux.go
index aa6155e21..2995da492 100644
--- a/vendor/github.com/vishvananda/netlink/nl/devlink_linux.go
+++ b/vendor/github.com/vishvananda/netlink/nl/devlink_linux.go
@@ -11,22 +11,37 @@ const (
const (
DEVLINK_CMD_GET = 1
DEVLINK_CMD_PORT_GET = 5
+ DEVLINK_CMD_PORT_SET = 6
+ DEVLINK_CMD_PORT_NEW = 7
+ DEVLINK_CMD_PORT_DEL = 8
DEVLINK_CMD_ESWITCH_GET = 29
DEVLINK_CMD_ESWITCH_SET = 30
+ DEVLINK_CMD_INFO_GET = 51
)
const (
- DEVLINK_ATTR_BUS_NAME = 1
- DEVLINK_ATTR_DEV_NAME = 2
- DEVLINK_ATTR_PORT_INDEX = 3
- DEVLINK_ATTR_PORT_TYPE = 4
- DEVLINK_ATTR_PORT_NETDEV_IFINDEX = 6
- DEVLINK_ATTR_PORT_NETDEV_NAME = 7
- DEVLINK_ATTR_PORT_IBDEV_NAME = 8
- DEVLINK_ATTR_ESWITCH_MODE = 25
- DEVLINK_ATTR_ESWITCH_INLINE_MODE = 26
- DEVLINK_ATTR_ESWITCH_ENCAP_MODE = 62
- DEVLINK_ATTR_PORT_FLAVOUR = 77
+ DEVLINK_ATTR_BUS_NAME = 1
+ DEVLINK_ATTR_DEV_NAME = 2
+ DEVLINK_ATTR_PORT_INDEX = 3
+ DEVLINK_ATTR_PORT_TYPE = 4
+ DEVLINK_ATTR_PORT_NETDEV_IFINDEX = 6
+ DEVLINK_ATTR_PORT_NETDEV_NAME = 7
+ DEVLINK_ATTR_PORT_IBDEV_NAME = 8
+ DEVLINK_ATTR_ESWITCH_MODE = 25
+ DEVLINK_ATTR_ESWITCH_INLINE_MODE = 26
+ DEVLINK_ATTR_ESWITCH_ENCAP_MODE = 62
+ DEVLINK_ATTR_PORT_FLAVOUR = 77
+ DEVLINK_ATTR_INFO_DRIVER_NAME = 98
+ DEVLINK_ATTR_INFO_SERIAL_NUMBER = 99
+ DEVLINK_ATTR_INFO_VERSION_FIXED = 100
+ DEVLINK_ATTR_INFO_VERSION_RUNNING = 101
+ DEVLINK_ATTR_INFO_VERSION_STORED = 102
+ DEVLINK_ATTR_INFO_VERSION_NAME = 103
+ DEVLINK_ATTR_INFO_VERSION_VALUE = 104
+ DEVLINK_ATTR_PORT_PCI_PF_NUMBER = 127
+ DEVLINK_ATTR_PORT_FUNCTION = 145
+ DEVLINK_ATTR_PORT_CONTROLLER_NUMBER = 150
+ DEVLINK_ATTR_PORT_PCI_SF_NUMBER = 164
)
const (
@@ -53,6 +68,8 @@ const (
DEVLINK_PORT_FLAVOUR_PCI_PF = 3
DEVLINK_PORT_FLAVOUR_PCI_VF = 4
DEVLINK_PORT_FLAVOUR_VIRTUAL = 5
+ DEVLINK_PORT_FLAVOUR_UNUSED = 6
+ DEVLINK_PORT_FLAVOUR_PCI_SF = 7
)
const (
@@ -61,3 +78,19 @@ const (
DEVLINK_PORT_TYPE_ETH = 2
DEVLINK_PORT_TYPE_IB = 3
)
+
+const (
+ DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR = 1
+ DEVLINK_PORT_FN_ATTR_STATE = 2
+ DEVLINK_PORT_FN_ATTR_OPSTATE = 3
+)
+
+const (
+ DEVLINK_PORT_FN_STATE_INACTIVE = 0
+ DEVLINK_PORT_FN_STATE_ACTIVE = 1
+)
+
+const (
+ DEVLINK_PORT_FN_OPSTATE_DETACHED = 0
+ DEVLINK_PORT_FN_OPSTATE_ATTACHED = 1
+)
diff --git a/vendor/github.com/vishvananda/netlink/nl/link_linux.go b/vendor/github.com/vishvananda/netlink/nl/link_linux.go
index c72cc436e..e10edbc09 100644
--- a/vendor/github.com/vishvananda/netlink/nl/link_linux.go
+++ b/vendor/github.com/vishvananda/netlink/nl/link_linux.go
@@ -709,3 +709,12 @@ const (
IFLA_CAN_BITRATE_MAX
IFLA_CAN_MAX = IFLA_CAN_BITRATE_MAX
)
+
+const (
+ IFLA_BAREUDP_UNSPEC = iota
+ IFLA_BAREUDP_PORT
+ IFLA_BAREUDP_ETHERTYPE
+ IFLA_BAREUDP_SRCPORT_MIN
+ IFLA_BAREUDP_MULTIPROTO_MODE
+ IFLA_BAREUDP_MAX = IFLA_BAREUDP_MULTIPROTO_MODE
+)
diff --git a/vendor/github.com/vishvananda/netlink/nl/lwt_linux.go b/vendor/github.com/vishvananda/netlink/nl/lwt_linux.go
new file mode 100644
index 000000000..bafd593c4
--- /dev/null
+++ b/vendor/github.com/vishvananda/netlink/nl/lwt_linux.go
@@ -0,0 +1,29 @@
+package nl
+
+const (
+ LWT_BPF_PROG_UNSPEC = iota
+ LWT_BPF_PROG_FD
+ LWT_BPF_PROG_NAME
+ __LWT_BPF_PROG_MAX
+)
+
+const (
+ LWT_BPF_PROG_MAX = __LWT_BPF_PROG_MAX - 1
+)
+
+const (
+ LWT_BPF_UNSPEC = iota
+ LWT_BPF_IN
+ LWT_BPF_OUT
+ LWT_BPF_XMIT
+ LWT_BPF_XMIT_HEADROOM
+ __LWT_BPF_MAX
+)
+
+const (
+ LWT_BPF_MAX = __LWT_BPF_MAX - 1
+)
+
+const (
+ LWT_BPF_MAX_HEADROOM = 256
+)
diff --git a/vendor/github.com/vishvananda/netlink/nl/nl_linux.go b/vendor/github.com/vishvananda/netlink/nl/nl_linux.go
index dcd4b9469..a49f67570 100644
--- a/vendor/github.com/vishvananda/netlink/nl/nl_linux.go
+++ b/vendor/github.com/vishvananda/netlink/nl/nl_linux.go
@@ -27,7 +27,8 @@ const (
// tc rules or filters, or other more memory requiring data.
RECEIVE_BUFFER_SIZE = 65536
// Kernel netlink pid
- PidKernel uint32 = 0
+ PidKernel uint32 = 0
+ SizeofCnMsgOp = 0x18
)
// SupportedNlFamilies contains the list of netlink families this netlink package supports
@@ -85,6 +86,56 @@ type NetlinkRequestData interface {
Serialize() []byte
}
+const (
+ PROC_CN_MCAST_LISTEN = 1
+ PROC_CN_MCAST_IGNORE
+)
+
+type CbID struct {
+ Idx uint32
+ Val uint32
+}
+
+type CnMsg struct {
+ ID CbID
+ Seq uint32
+ Ack uint32
+ Length uint16
+ Flags uint16
+}
+
+type CnMsgOp struct {
+ CnMsg
+ // here we differ from the C header
+ Op uint32
+}
+
+func NewCnMsg(idx, val, op uint32) *CnMsgOp {
+ var cm CnMsgOp
+
+ cm.ID.Idx = idx
+ cm.ID.Val = val
+
+ cm.Ack = 0
+ cm.Seq = 1
+ cm.Length = uint16(binary.Size(op))
+ cm.Op = op
+
+ return &cm
+}
+
+func (msg *CnMsgOp) Serialize() []byte {
+ return (*(*[SizeofCnMsgOp]byte)(unsafe.Pointer(msg)))[:]
+}
+
+func DeserializeCnMsgOp(b []byte) *CnMsgOp {
+ return (*CnMsgOp)(unsafe.Pointer(&b[0:SizeofCnMsgOp][0]))
+}
+
+func (msg *CnMsgOp) Len() int {
+ return SizeofCnMsgOp
+}
+
// IfInfomsg is related to links, but it is used for list requests as well
type IfInfomsg struct {
unix.IfInfomsg
diff --git a/vendor/github.com/vishvananda/netlink/nl/rdma_link_linux.go b/vendor/github.com/vishvananda/netlink/nl/rdma_link_linux.go
index 1224b747d..ce43ee155 100644
--- a/vendor/github.com/vishvananda/netlink/nl/rdma_link_linux.go
+++ b/vendor/github.com/vishvananda/netlink/nl/rdma_link_linux.go
@@ -11,6 +11,8 @@ const (
const (
RDMA_NLDEV_CMD_GET = 1
RDMA_NLDEV_CMD_SET = 2
+ RDMA_NLDEV_CMD_NEWLINK = 3
+ RDMA_NLDEV_CMD_DELLINK = 4
RDMA_NLDEV_CMD_SYS_GET = 6
RDMA_NLDEV_CMD_SYS_SET = 7
)
@@ -30,6 +32,8 @@ const (
RDMA_NLDEV_ATTR_PORT_STATE = 12
RDMA_NLDEV_ATTR_PORT_PHYS_STATE = 13
RDMA_NLDEV_ATTR_DEV_NODE_TYPE = 14
+ RDMA_NLDEV_ATTR_NDEV_NAME = 51
+ RDMA_NLDEV_ATTR_LINK_TYPE = 65
RDMA_NLDEV_SYS_ATTR_NETNS_MODE = 66
RDMA_NLDEV_NET_NS_FD = 68
)
diff --git a/vendor/github.com/vishvananda/netlink/nl/seg6_linux.go b/vendor/github.com/vishvananda/netlink/nl/seg6_linux.go
index 5774cbb15..fe88285f2 100644
--- a/vendor/github.com/vishvananda/netlink/nl/seg6_linux.go
+++ b/vendor/github.com/vishvananda/netlink/nl/seg6_linux.go
@@ -23,7 +23,7 @@ func (s1 *IPv6SrHdr) Equal(s2 IPv6SrHdr) bool {
return false
}
for i := range s1.Segments {
- if s1.Segments[i].Equal(s2.Segments[i]) != true {
+ if !s1.Segments[i].Equal(s2.Segments[i]) {
return false
}
}
@@ -89,7 +89,7 @@ func DecodeSEG6Encap(buf []byte) (int, []net.IP, error) {
}
buf = buf[12:]
if len(buf)%16 != 0 {
- err := fmt.Errorf("DecodeSEG6Encap: error parsing Segment List (buf len: %d)\n", len(buf))
+ err := fmt.Errorf("DecodeSEG6Encap: error parsing Segment List (buf len: %d)", len(buf))
return mode, nil, err
}
for len(buf) > 0 {
diff --git a/vendor/github.com/vishvananda/netlink/nl/syscall.go b/vendor/github.com/vishvananda/netlink/nl/syscall.go
index 4a01e6e59..bdf6ba639 100644
--- a/vendor/github.com/vishvananda/netlink/nl/syscall.go
+++ b/vendor/github.com/vishvananda/netlink/nl/syscall.go
@@ -1,6 +1,6 @@
package nl
-// syscall package lack of rule atributes type.
+// syscall package lack of rule attributes type.
// Thus there are defined below
const (
FRA_UNSPEC = iota
diff --git a/vendor/github.com/vishvananda/netlink/nl/tc_linux.go b/vendor/github.com/vishvananda/netlink/nl/tc_linux.go
index c24d53eb7..002beda92 100644
--- a/vendor/github.com/vishvananda/netlink/nl/tc_linux.go
+++ b/vendor/github.com/vishvananda/netlink/nl/tc_linux.go
@@ -882,6 +882,111 @@ const (
TCA_HFSC_USC
)
+const (
+ TCA_FLOWER_UNSPEC = iota
+ TCA_FLOWER_CLASSID
+ TCA_FLOWER_INDEV
+ TCA_FLOWER_ACT
+ TCA_FLOWER_KEY_ETH_DST /* ETH_ALEN */
+ TCA_FLOWER_KEY_ETH_DST_MASK /* ETH_ALEN */
+ TCA_FLOWER_KEY_ETH_SRC /* ETH_ALEN */
+ TCA_FLOWER_KEY_ETH_SRC_MASK /* ETH_ALEN */
+ TCA_FLOWER_KEY_ETH_TYPE /* be16 */
+ TCA_FLOWER_KEY_IP_PROTO /* u8 */
+ TCA_FLOWER_KEY_IPV4_SRC /* be32 */
+ TCA_FLOWER_KEY_IPV4_SRC_MASK /* be32 */
+ TCA_FLOWER_KEY_IPV4_DST /* be32 */
+ TCA_FLOWER_KEY_IPV4_DST_MASK /* be32 */
+ TCA_FLOWER_KEY_IPV6_SRC /* struct in6_addr */
+ TCA_FLOWER_KEY_IPV6_SRC_MASK /* struct in6_addr */
+ TCA_FLOWER_KEY_IPV6_DST /* struct in6_addr */
+ TCA_FLOWER_KEY_IPV6_DST_MASK /* struct in6_addr */
+ TCA_FLOWER_KEY_TCP_SRC /* be16 */
+ TCA_FLOWER_KEY_TCP_DST /* be16 */
+ TCA_FLOWER_KEY_UDP_SRC /* be16 */
+ TCA_FLOWER_KEY_UDP_DST /* be16 */
+
+ TCA_FLOWER_FLAGS
+ TCA_FLOWER_KEY_VLAN_ID /* be16 */
+ TCA_FLOWER_KEY_VLAN_PRIO /* u8 */
+ TCA_FLOWER_KEY_VLAN_ETH_TYPE /* be16 */
+
+ TCA_FLOWER_KEY_ENC_KEY_ID /* be32 */
+ TCA_FLOWER_KEY_ENC_IPV4_SRC /* be32 */
+ TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK /* be32 */
+ TCA_FLOWER_KEY_ENC_IPV4_DST /* be32 */
+ TCA_FLOWER_KEY_ENC_IPV4_DST_MASK /* be32 */
+ TCA_FLOWER_KEY_ENC_IPV6_SRC /* struct in6_addr */
+ TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK /* struct in6_addr */
+ TCA_FLOWER_KEY_ENC_IPV6_DST /* struct in6_addr */
+ TCA_FLOWER_KEY_ENC_IPV6_DST_MASK /* struct in6_addr */
+
+ TCA_FLOWER_KEY_TCP_SRC_MASK /* be16 */
+ TCA_FLOWER_KEY_TCP_DST_MASK /* be16 */
+ TCA_FLOWER_KEY_UDP_SRC_MASK /* be16 */
+ TCA_FLOWER_KEY_UDP_DST_MASK /* be16 */
+ TCA_FLOWER_KEY_SCTP_SRC_MASK /* be16 */
+ TCA_FLOWER_KEY_SCTP_DST_MASK /* be16 */
+
+ TCA_FLOWER_KEY_SCTP_SRC /* be16 */
+ TCA_FLOWER_KEY_SCTP_DST /* be16 */
+
+ TCA_FLOWER_KEY_ENC_UDP_SRC_PORT /* be16 */
+ TCA_FLOWER_KEY_ENC_UDP_SRC_PORT_MASK /* be16 */
+ TCA_FLOWER_KEY_ENC_UDP_DST_PORT /* be16 */
+ TCA_FLOWER_KEY_ENC_UDP_DST_PORT_MASK /* be16 */
+
+ TCA_FLOWER_KEY_FLAGS /* be32 */
+ TCA_FLOWER_KEY_FLAGS_MASK /* be32 */
+
+ TCA_FLOWER_KEY_ICMPV4_CODE /* u8 */
+ TCA_FLOWER_KEY_ICMPV4_CODE_MASK /* u8 */
+ TCA_FLOWER_KEY_ICMPV4_TYPE /* u8 */
+ TCA_FLOWER_KEY_ICMPV4_TYPE_MASK /* u8 */
+ TCA_FLOWER_KEY_ICMPV6_CODE /* u8 */
+ TCA_FLOWER_KEY_ICMPV6_CODE_MASK /* u8 */
+ TCA_FLOWER_KEY_ICMPV6_TYPE /* u8 */
+ TCA_FLOWER_KEY_ICMPV6_TYPE_MASK /* u8 */
+
+ TCA_FLOWER_KEY_ARP_SIP /* be32 */
+ TCA_FLOWER_KEY_ARP_SIP_MASK /* be32 */
+ TCA_FLOWER_KEY_ARP_TIP /* be32 */
+ TCA_FLOWER_KEY_ARP_TIP_MASK /* be32 */
+ TCA_FLOWER_KEY_ARP_OP /* u8 */
+ TCA_FLOWER_KEY_ARP_OP_MASK /* u8 */
+ TCA_FLOWER_KEY_ARP_SHA /* ETH_ALEN */
+ TCA_FLOWER_KEY_ARP_SHA_MASK /* ETH_ALEN */
+ TCA_FLOWER_KEY_ARP_THA /* ETH_ALEN */
+ TCA_FLOWER_KEY_ARP_THA_MASK /* ETH_ALEN */
+
+ TCA_FLOWER_KEY_MPLS_TTL /* u8 - 8 bits */
+ TCA_FLOWER_KEY_MPLS_BOS /* u8 - 1 bit */
+ TCA_FLOWER_KEY_MPLS_TC /* u8 - 3 bits */
+ TCA_FLOWER_KEY_MPLS_LABEL /* be32 - 20 bits */
+
+ TCA_FLOWER_KEY_TCP_FLAGS /* be16 */
+ TCA_FLOWER_KEY_TCP_FLAGS_MASK /* be16 */
+
+ TCA_FLOWER_KEY_IP_TOS /* u8 */
+ TCA_FLOWER_KEY_IP_TOS_MASK /* u8 */
+ TCA_FLOWER_KEY_IP_TTL /* u8 */
+ TCA_FLOWER_KEY_IP_TTL_MASK /* u8 */
+
+ TCA_FLOWER_KEY_CVLAN_ID /* be16 */
+ TCA_FLOWER_KEY_CVLAN_PRIO /* u8 */
+ TCA_FLOWER_KEY_CVLAN_ETH_TYPE /* be16 */
+
+ TCA_FLOWER_KEY_ENC_IP_TOS /* u8 */
+ TCA_FLOWER_KEY_ENC_IP_TOS_MASK /* u8 */
+ TCA_FLOWER_KEY_ENC_IP_TTL /* u8 */
+ TCA_FLOWER_KEY_ENC_IP_TTL_MASK /* u8 */
+
+ TCA_FLOWER_KEY_ENC_OPTS
+ TCA_FLOWER_KEY_ENC_OPTS_MASK
+
+ __TCA_FLOWER_MAX
+)
+
// struct tc_sfq_qopt {
// unsigned quantum; /* Bytes per round allocated to flow */
// int perturb_period; /* Period of hash perturbation */
diff --git a/vendor/github.com/vishvananda/netlink/proc_event.go b/vendor/github.com/vishvananda/netlink/proc_event.go
new file mode 100644
index 000000000..53bc59a6e
--- /dev/null
+++ b/vendor/github.com/vishvananda/netlink/proc_event.go
@@ -0,0 +1,217 @@
+package netlink
+
+import (
+ "bytes"
+ "encoding/binary"
+ "fmt"
+ "os"
+ "syscall"
+
+ "github.com/vishvananda/netlink/nl"
+ "github.com/vishvananda/netns"
+ "golang.org/x/sys/unix"
+)
+
+const CN_IDX_PROC = 0x1
+
+const (
+ PROC_EVENT_NONE = 0x00000000
+ PROC_EVENT_FORK = 0x00000001
+ PROC_EVENT_EXEC = 0x00000002
+ PROC_EVENT_UID = 0x00000004
+ PROC_EVENT_GID = 0x00000040
+ PROC_EVENT_SID = 0x00000080
+ PROC_EVENT_PTRACE = 0x00000100
+ PROC_EVENT_COMM = 0x00000200
+ PROC_EVENT_COREDUMP = 0x40000000
+ PROC_EVENT_EXIT = 0x80000000
+)
+
+const (
+ CN_VAL_PROC = 0x1
+ PROC_CN_MCAST_LISTEN = 0x1
+)
+
+type ProcEventMsg interface {
+ Pid() uint32
+ Tgid() uint32
+}
+
+type ProcEventHeader struct {
+ What uint32
+ CPU uint32
+ Timestamp uint64
+}
+
+type ProcEvent struct {
+ ProcEventHeader
+ Msg ProcEventMsg
+}
+
+func (pe *ProcEvent) setHeader(h ProcEventHeader) {
+ pe.What = h.What
+ pe.CPU = h.CPU
+ pe.Timestamp = h.Timestamp
+}
+
+type ExitProcEvent struct {
+ ProcessPid uint32
+ ProcessTgid uint32
+ ExitCode uint32
+ ExitSignal uint32
+ ParentPid uint32
+ ParentTgid uint32
+}
+
+type ExitProcEvent2 struct {
+ ProcessPid uint32
+ ProcessTgid uint32
+ ExitCode uint32
+ ExitSignal uint32
+ ParentPid uint32
+ ParentTgid uint32
+}
+
+func (e *ExitProcEvent) Pid() uint32 {
+ return e.ProcessPid
+}
+
+func (e *ExitProcEvent) Tgid() uint32 {
+ return e.ProcessTgid
+}
+
+type ExecProcEvent struct {
+ ProcessPid uint32
+ ProcessTgid uint32
+}
+
+func (e *ExecProcEvent) Pid() uint32 {
+ return e.ProcessPid
+}
+
+func (e *ExecProcEvent) Tgid() uint32 {
+ return e.ProcessTgid
+}
+
+type ForkProcEvent struct {
+ ParentPid uint32
+ ParentTgid uint32
+ ChildPid uint32
+ ChildTgid uint32
+}
+
+func (e *ForkProcEvent) Pid() uint32 {
+ return e.ParentPid
+}
+
+func (e *ForkProcEvent) Tgid() uint32 {
+ return e.ParentTgid
+}
+
+type CommProcEvent struct {
+ ProcessPid uint32
+ ProcessTgid uint32
+ Comm [16]byte
+}
+
+func (e *CommProcEvent) Pid() uint32 {
+ return e.ProcessPid
+}
+
+func (e *CommProcEvent) Tgid() uint32 {
+ return e.ProcessTgid
+}
+
+func ProcEventMonitor(ch chan<- ProcEvent, done <-chan struct{}, errorChan chan<- error) error {
+ h, err := NewHandle()
+ if err != nil {
+ return err
+ }
+ defer h.Delete()
+
+ s, err := nl.SubscribeAt(netns.None(), netns.None(), unix.NETLINK_CONNECTOR, CN_IDX_PROC)
+ if err != nil {
+ return err
+ }
+
+ var nlmsg nl.NetlinkRequest
+
+ nlmsg.Pid = uint32(os.Getpid())
+ nlmsg.Type = unix.NLMSG_DONE
+ nlmsg.Len = uint32(unix.SizeofNlMsghdr)
+
+ cm := nl.NewCnMsg(CN_IDX_PROC, CN_VAL_PROC, PROC_CN_MCAST_LISTEN)
+ nlmsg.AddData(cm)
+
+ s.Send(&nlmsg)
+
+ if done != nil {
+ go func() {
+ <-done
+ s.Close()
+ }()
+ }
+
+ go func() {
+ defer close(ch)
+ for {
+ msgs, from, err := s.Receive()
+ if err != nil {
+ errorChan <- err
+ return
+ }
+ if from.Pid != nl.PidKernel {
+ errorChan <- fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel)
+ return
+ }
+
+ for _, m := range msgs {
+ e := parseNetlinkMessage(m)
+ if e != nil {
+ ch <- *e
+ }
+ }
+
+ }
+ }()
+
+ return nil
+}
+
+func parseNetlinkMessage(m syscall.NetlinkMessage) *ProcEvent {
+ if m.Header.Type == unix.NLMSG_DONE {
+ buf := bytes.NewBuffer(m.Data)
+ msg := &nl.CnMsg{}
+ hdr := &ProcEventHeader{}
+ binary.Read(buf, nl.NativeEndian(), msg)
+ binary.Read(buf, nl.NativeEndian(), hdr)
+
+ pe := &ProcEvent{}
+ pe.setHeader(*hdr)
+ switch hdr.What {
+ case PROC_EVENT_EXIT:
+ event := &ExitProcEvent{}
+ binary.Read(buf, nl.NativeEndian(), event)
+ pe.Msg = event
+ return pe
+ case PROC_EVENT_FORK:
+ event := &ForkProcEvent{}
+ binary.Read(buf, nl.NativeEndian(), event)
+ pe.Msg = event
+ return pe
+ case PROC_EVENT_EXEC:
+ event := &ExecProcEvent{}
+ binary.Read(buf, nl.NativeEndian(), event)
+ pe.Msg = event
+ return pe
+ case PROC_EVENT_COMM:
+ event := &CommProcEvent{}
+ binary.Read(buf, nl.NativeEndian(), event)
+ pe.Msg = event
+ return pe
+ }
+ return nil
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/vishvananda/netlink/qdisc_linux.go b/vendor/github.com/vishvananda/netlink/qdisc_linux.go
index edc4b726a..e182e1cfe 100644
--- a/vendor/github.com/vishvananda/netlink/qdisc_linux.go
+++ b/vendor/github.com/vishvananda/netlink/qdisc_linux.go
@@ -468,7 +468,6 @@ func parsePrioData(qdisc Qdisc, value []byte) error {
}
func parseHtbData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error {
- native = nl.NativeEndian()
htb := qdisc.(*Htb)
for _, datum := range data {
switch datum.Attr.Type {
@@ -488,7 +487,6 @@ func parseHtbData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error {
}
func parseFqCodelData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error {
- native = nl.NativeEndian()
fqCodel := qdisc.(*FqCodel)
for _, datum := range data {
@@ -518,13 +516,11 @@ func parseFqCodelData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error {
func parseHfscData(qdisc Qdisc, data []byte) error {
Hfsc := qdisc.(*Hfsc)
- native = nl.NativeEndian()
Hfsc.Defcls = native.Uint16(data)
return nil
}
func parseFqData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error {
- native = nl.NativeEndian()
fq := qdisc.(*Fq)
for _, datum := range data {
switch datum.Attr.Type {
@@ -589,7 +585,6 @@ func parseNetemData(qdisc Qdisc, value []byte) error {
}
func parseTbfData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error {
- native = nl.NativeEndian()
tbf := qdisc.(*Tbf)
for _, datum := range data {
switch datum.Attr.Type {
@@ -711,3 +706,7 @@ func Xmittime(rate uint64, size uint32) uint32 {
// https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/tc/tc_core.c#n62
return time2Tick(uint32(TIME_UNITS_PER_SEC * (float64(size) / float64(rate))))
}
+
+func Xmitsize(rate uint64, ticks uint32) uint32 {
+ return uint32((float64(rate) * float64(tick2Time(ticks))) / TIME_UNITS_PER_SEC)
+}
diff --git a/vendor/github.com/vishvananda/netlink/rdma_link_linux.go b/vendor/github.com/vishvananda/netlink/rdma_link_linux.go
index ff014ca4c..036399db6 100644
--- a/vendor/github.com/vishvananda/netlink/rdma_link_linux.go
+++ b/vendor/github.com/vishvananda/netlink/rdma_link_linux.go
@@ -278,3 +278,54 @@ func (h *Handle) RdmaLinkSetNsFd(link *RdmaLink, fd uint32) error {
return execRdmaSetLink(req)
}
+
+// RdmaLinkDel deletes an rdma link
+//
+// Similar to: rdma link delete NAME
+// REF: https://man7.org/linux/man-pages/man8/rdma-link.8.html
+func RdmaLinkDel(name string) error {
+ return pkgHandle.RdmaLinkDel(name)
+}
+
+// RdmaLinkDel deletes an rdma link.
+func (h *Handle) RdmaLinkDel(name string) error {
+ link, err := h.RdmaLinkByName(name)
+ if err != nil {
+ return err
+ }
+
+ proto := getProtoField(nl.RDMA_NL_NLDEV, nl.RDMA_NLDEV_CMD_DELLINK)
+ req := h.newNetlinkRequest(proto, unix.NLM_F_ACK)
+
+ b := make([]byte, 4)
+ native.PutUint32(b, link.Attrs.Index)
+ req.AddData(nl.NewRtAttr(nl.RDMA_NLDEV_ATTR_DEV_INDEX, b))
+
+ _, err = req.Execute(unix.NETLINK_RDMA, 0)
+ return err
+}
+
+// RdmaLinkAdd adds an rdma link for the specified type to the network device.
+// Similar to: rdma link add NAME type TYPE netdev NETDEV
+// NAME - specifies the new name of the rdma link to add
+// TYPE - specifies which rdma type to use. Link types:
+// rxe - Soft RoCE driver
+// siw - Soft iWARP driver
+// NETDEV - specifies the network device to which the link is bound
+//
+// REF: https://man7.org/linux/man-pages/man8/rdma-link.8.html
+func RdmaLinkAdd(linkName, linkType, netdev string) error {
+ return pkgHandle.RdmaLinkAdd(linkName, linkType, netdev)
+}
+
+// RdmaLinkAdd adds an rdma link for the specified type to the network device.
+func (h *Handle) RdmaLinkAdd(linkName string, linkType string, netdev string) error {
+ proto := getProtoField(nl.RDMA_NL_NLDEV, nl.RDMA_NLDEV_CMD_NEWLINK)
+ req := h.newNetlinkRequest(proto, unix.NLM_F_ACK)
+
+ req.AddData(nl.NewRtAttr(nl.RDMA_NLDEV_ATTR_DEV_NAME, nl.ZeroTerminated(linkName)))
+ req.AddData(nl.NewRtAttr(nl.RDMA_NLDEV_ATTR_LINK_TYPE, nl.ZeroTerminated(linkType)))
+ req.AddData(nl.NewRtAttr(nl.RDMA_NLDEV_ATTR_NDEV_NAME, nl.ZeroTerminated(netdev)))
+ _, err := req.Execute(unix.NETLINK_RDMA, 0)
+ return err
+}
diff --git a/vendor/github.com/vishvananda/netlink/route.go b/vendor/github.com/vishvananda/netlink/route.go
index 845f41808..ffad5d398 100644
--- a/vendor/github.com/vishvananda/netlink/route.go
+++ b/vendor/github.com/vishvananda/netlink/route.go
@@ -41,6 +41,7 @@ type Route struct {
MultiPath []*NexthopInfo
Protocol RouteProtocol
Priority int
+ Family int
Table int
Type int
Tos int
@@ -49,6 +50,7 @@ type Route struct {
NewDst Destination
Encap Encap
Via Destination
+ Realm int
MTU int
Window int
Rtt int
@@ -94,6 +96,7 @@ func (r Route) String() string {
}
elems = append(elems, fmt.Sprintf("Flags: %s", r.ListFlags()))
elems = append(elems, fmt.Sprintf("Table: %d", r.Table))
+ elems = append(elems, fmt.Sprintf("Realm: %d", r.Realm))
return fmt.Sprintf("{%s}", strings.Join(elems, " "))
}
@@ -107,6 +110,7 @@ func (r Route) Equal(x Route) bool {
nexthopInfoSlice(r.MultiPath).Equal(x.MultiPath) &&
r.Protocol == x.Protocol &&
r.Priority == x.Priority &&
+ r.Realm == x.Realm &&
r.Table == x.Table &&
r.Type == x.Type &&
r.Tos == x.Tos &&
diff --git a/vendor/github.com/vishvananda/netlink/route_linux.go b/vendor/github.com/vishvananda/netlink/route_linux.go
index 32641cb0d..b059d4a9e 100644
--- a/vendor/github.com/vishvananda/netlink/route_linux.go
+++ b/vendor/github.com/vishvananda/netlink/route_linux.go
@@ -56,6 +56,7 @@ const (
RT_FILTER_PRIORITY
RT_FILTER_MARK
RT_FILTER_MASK
+ RT_FILTER_REALM
)
const (
@@ -151,7 +152,6 @@ func (e *MPLSEncap) Decode(buf []byte) error {
if len(buf) < 4 {
return fmt.Errorf("lack of bytes")
}
- native := nl.NativeEndian()
l := native.Uint16(buf)
if len(buf) < int(l) {
return fmt.Errorf("lack of bytes")
@@ -167,7 +167,6 @@ func (e *MPLSEncap) Decode(buf []byte) error {
func (e *MPLSEncap) Encode() ([]byte, error) {
s := nl.EncodeMPLSStack(e.Labels...)
- native := nl.NativeEndian()
hdr := make([]byte, 4)
native.PutUint16(hdr, uint16(len(s)+4))
native.PutUint16(hdr[2:], nl.MPLS_IPTUNNEL_DST)
@@ -223,7 +222,6 @@ func (e *SEG6Encap) Decode(buf []byte) error {
if len(buf) < 4 {
return fmt.Errorf("lack of bytes")
}
- native := nl.NativeEndian()
// Get Length(l) & Type(typ) : 2 + 2 bytes
l := native.Uint16(buf)
if len(buf) < int(l) {
@@ -243,7 +241,6 @@ func (e *SEG6Encap) Decode(buf []byte) error {
}
func (e *SEG6Encap) Encode() ([]byte, error) {
s, err := nl.EncodeSEG6Encap(e.Mode, e.Segments)
- native := nl.NativeEndian()
hdr := make([]byte, 4)
native.PutUint16(hdr, uint16(len(s)+4))
native.PutUint16(hdr[2:], nl.SEG6_IPTUNNEL_SRH)
@@ -253,7 +250,7 @@ func (e *SEG6Encap) String() string {
segs := make([]string, 0, len(e.Segments))
// append segment backwards (from n to 0) since seg#0 is the last segment.
for i := len(e.Segments); i > 0; i-- {
- segs = append(segs, fmt.Sprintf("%s", e.Segments[i-1]))
+ segs = append(segs, e.Segments[i-1].String())
}
str := fmt.Sprintf("mode %s segs %d [ %s ]", nl.SEG6EncapModeString(e.Mode),
len(e.Segments), strings.Join(segs, " "))
@@ -304,7 +301,6 @@ func (e *SEG6LocalEncap) Decode(buf []byte) error {
if err != nil {
return err
}
- native := nl.NativeEndian()
for _, attr := range attrs {
switch attr.Attr.Type {
case nl.SEG6_LOCAL_ACTION:
@@ -334,7 +330,6 @@ func (e *SEG6LocalEncap) Decode(buf []byte) error {
}
func (e *SEG6LocalEncap) Encode() ([]byte, error) {
var err error
- native := nl.NativeEndian()
res := make([]byte, 8)
native.PutUint16(res, 8) // length
native.PutUint16(res[2:], nl.SEG6_LOCAL_ACTION)
@@ -425,7 +420,7 @@ func (e *SEG6LocalEncap) String() string {
segs := make([]string, 0, len(e.Segments))
//append segment backwards (from n to 0) since seg#0 is the last segment.
for i := len(e.Segments); i > 0; i-- {
- segs = append(segs, fmt.Sprintf("%s", e.Segments[i-1]))
+ segs = append(segs, e.Segments[i-1].String())
}
strs = append(strs, fmt.Sprintf("segs %d [ %s ]", len(e.Segments), strings.Join(segs, " ")))
}
@@ -466,6 +461,152 @@ func (e *SEG6LocalEncap) Equal(x Encap) bool {
return true
}
+// Encap BPF definitions
+type bpfObj struct {
+ progFd int
+ progName string
+}
+type BpfEncap struct {
+ progs [nl.LWT_BPF_MAX]bpfObj
+ headroom int
+}
+
+// SetProg adds a bpf function to the route via netlink RTA_ENCAP. The fd must be a bpf
+// program loaded with bpf(type=BPF_PROG_TYPE_LWT_*) matching the direction the program should
+// be applied to (LWT_BPF_IN, LWT_BPF_OUT, LWT_BPF_XMIT).
+func (e *BpfEncap) SetProg(mode, progFd int, progName string) error {
+ if progFd <= 0 {
+ return fmt.Errorf("lwt bpf SetProg: invalid fd")
+ }
+ if mode <= nl.LWT_BPF_UNSPEC || mode >= nl.LWT_BPF_XMIT_HEADROOM {
+ return fmt.Errorf("lwt bpf SetProg:invalid mode")
+ }
+ e.progs[mode].progFd = progFd
+ e.progs[mode].progName = fmt.Sprintf("%s[fd:%d]", progName, progFd)
+ return nil
+}
+
+// SetXmitHeadroom sets the xmit headroom (LWT_BPF_MAX_HEADROOM) via netlink RTA_ENCAP.
+// maximum headroom is LWT_BPF_MAX_HEADROOM
+func (e *BpfEncap) SetXmitHeadroom(headroom int) error {
+ if headroom > nl.LWT_BPF_MAX_HEADROOM || headroom < 0 {
+ return fmt.Errorf("invalid headroom size. range is 0 - %d", nl.LWT_BPF_MAX_HEADROOM)
+ }
+ e.headroom = headroom
+ return nil
+}
+
+func (e *BpfEncap) Type() int {
+ return nl.LWTUNNEL_ENCAP_BPF
+}
+func (e *BpfEncap) Decode(buf []byte) error {
+ if len(buf) < 4 {
+ return fmt.Errorf("lwt bpf decode: lack of bytes")
+ }
+ native := nl.NativeEndian()
+ attrs, err := nl.ParseRouteAttr(buf)
+ if err != nil {
+ return fmt.Errorf("lwt bpf decode: failed parsing attribute. err: %v", err)
+ }
+ for _, attr := range attrs {
+ if int(attr.Attr.Type) < 1 {
+ // nl.LWT_BPF_UNSPEC
+ continue
+ }
+ if int(attr.Attr.Type) > nl.LWT_BPF_MAX {
+ return fmt.Errorf("lwt bpf decode: received unknown attribute type: %d", attr.Attr.Type)
+ }
+ switch int(attr.Attr.Type) {
+ case nl.LWT_BPF_MAX_HEADROOM:
+ e.headroom = int(native.Uint32(attr.Value))
+ default:
+ bpfO := bpfObj{}
+ parsedAttrs, err := nl.ParseRouteAttr(attr.Value)
+ if err != nil {
+ return fmt.Errorf("lwt bpf decode: failed parsing route attribute")
+ }
+ for _, parsedAttr := range parsedAttrs {
+ switch int(parsedAttr.Attr.Type) {
+ case nl.LWT_BPF_PROG_FD:
+ bpfO.progFd = int(native.Uint32(parsedAttr.Value))
+ case nl.LWT_BPF_PROG_NAME:
+ bpfO.progName = string(parsedAttr.Value)
+ default:
+ return fmt.Errorf("lwt bpf decode: received unknown attribute: type: %d, len: %d", parsedAttr.Attr.Type, parsedAttr.Attr.Len)
+ }
+ }
+ e.progs[attr.Attr.Type] = bpfO
+ }
+ }
+ return nil
+}
+
+func (e *BpfEncap) Encode() ([]byte, error) {
+ buf := make([]byte, 0)
+ native = nl.NativeEndian()
+ for index, attr := range e.progs {
+ nlMsg := nl.NewRtAttr(index, []byte{})
+ if attr.progFd != 0 {
+ nlMsg.AddRtAttr(nl.LWT_BPF_PROG_FD, nl.Uint32Attr(uint32(attr.progFd)))
+ }
+ if attr.progName != "" {
+ nlMsg.AddRtAttr(nl.LWT_BPF_PROG_NAME, nl.ZeroTerminated(attr.progName))
+ }
+ if nlMsg.Len() > 4 {
+ buf = append(buf, nlMsg.Serialize()...)
+ }
+ }
+ if len(buf) <= 4 {
+ return nil, fmt.Errorf("lwt bpf encode: bpf obj definitions returned empty buffer")
+ }
+ if e.headroom > 0 {
+ hRoom := nl.NewRtAttr(nl.LWT_BPF_XMIT_HEADROOM, nl.Uint32Attr(uint32(e.headroom)))
+ buf = append(buf, hRoom.Serialize()...)
+ }
+ return buf, nil
+}
+
+func (e *BpfEncap) String() string {
+ progs := make([]string, 0)
+ for index, obj := range e.progs {
+ empty := bpfObj{}
+ switch index {
+ case nl.LWT_BPF_IN:
+ if obj != empty {
+ progs = append(progs, fmt.Sprintf("in: %s", obj.progName))
+ }
+ case nl.LWT_BPF_OUT:
+ if obj != empty {
+ progs = append(progs, fmt.Sprintf("out: %s", obj.progName))
+ }
+ case nl.LWT_BPF_XMIT:
+ if obj != empty {
+ progs = append(progs, fmt.Sprintf("xmit: %s", obj.progName))
+ }
+ }
+ }
+ if e.headroom > 0 {
+ progs = append(progs, fmt.Sprintf("xmit headroom: %d", e.headroom))
+ }
+ return strings.Join(progs, " ")
+}
+
+func (e *BpfEncap) Equal(x Encap) bool {
+ o, ok := x.(*BpfEncap)
+ if !ok {
+ return false
+ }
+ if e.headroom != o.headroom {
+ return false
+ }
+ for i := range o.progs {
+ if o.progs[i] != e.progs[i] {
+ return false
+ }
+ }
+ return true
+}
+
type Via struct {
AddrFamily int
Addr net.IP
@@ -504,7 +645,6 @@ func (v *Via) Encode() ([]byte, error) {
}
func (v *Via) Decode(b []byte) error {
- native := nl.NativeEndian()
if len(b) < 6 {
return fmt.Errorf("decoding failed: buffer too small (%d bytes)", len(b))
}
@@ -552,14 +692,14 @@ func (h *Handle) RouteAppend(route *Route) error {
// RouteAddEcmp will add a route to the system.
func RouteAddEcmp(route *Route) error {
- return pkgHandle.RouteAddEcmp(route)
+ return pkgHandle.RouteAddEcmp(route)
}
// RouteAddEcmp will add a route to the system.
func (h *Handle) RouteAddEcmp(route *Route) error {
- flags := unix.NLM_F_CREATE | unix.NLM_F_ACK
- req := h.newNetlinkRequest(unix.RTM_NEWROUTE, flags)
- return h.routeHandle(route, req, nl.NewRtMsg())
+ flags := unix.NLM_F_CREATE | unix.NLM_F_ACK
+ req := h.newNetlinkRequest(unix.RTM_NEWROUTE, flags)
+ return h.routeHandle(route, req, nl.NewRtMsg())
}
// RouteReplace will add a route to the system.
@@ -635,7 +775,13 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
if err != nil {
return err
}
- rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_ENCAP, buf))
+ switch route.Encap.Type() {
+ case nl.LWTUNNEL_ENCAP_BPF:
+ rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_ENCAP|unix.NLA_F_NESTED, buf))
+ default:
+ rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_ENCAP, buf))
+ }
+
}
if route.Src != nil {
@@ -748,6 +894,11 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
native.PutUint32(b, uint32(route.Priority))
rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_PRIORITY, b))
}
+ if route.Realm > 0 {
+ b := make([]byte, 4)
+ native.PutUint32(b, uint32(route.Realm))
+ rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_FLOW, b))
+ }
if route.Tos > 0 {
msg.Tos = uint8(route.Tos)
}
@@ -840,10 +991,7 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg
req.AddData(attr)
}
- var (
- b = make([]byte, 4)
- native = nl.NativeEndian()
- )
+ b := make([]byte, 4)
native.PutUint32(b, uint32(route.LinkIndex))
req.AddData(nl.NewRtAttr(unix.RTA_OIF, b))
@@ -919,6 +1067,8 @@ func (h *Handle) RouteListFiltered(family int, filter *Route, filterMask uint64)
continue
case filterMask&RT_FILTER_TOS != 0 && route.Tos != filter.Tos:
continue
+ case filterMask&RT_FILTER_REALM != 0 && route.Realm != filter.Realm:
+ continue
case filterMask&RT_FILTER_OIF != 0 && route.LinkIndex != filter.LinkIndex:
continue
case filterMask&RT_FILTER_IIF != 0 && route.ILinkIndex != filter.ILinkIndex:
@@ -956,9 +1106,9 @@ func deserializeRoute(m []byte) (Route, error) {
Type: int(msg.Type),
Tos: int(msg.Tos),
Flags: int(msg.Flags),
+ Family: int(msg.Family),
}
- native := nl.NativeEndian()
var encap, encapType syscall.NetlinkRouteAttr
for _, attr := range attrs {
switch attr.Attr.Type {
@@ -985,6 +1135,8 @@ func deserializeRoute(m []byte) (Route, error) {
route.ILinkIndex = int(native.Uint32(attr.Value[0:4]))
case unix.RTA_PRIORITY:
route.Priority = int(native.Uint32(attr.Value[0:4]))
+ case unix.RTA_FLOW:
+ route.Realm = int(native.Uint32(attr.Value[0:4]))
case unix.RTA_TABLE:
route.Table = int(native.Uint32(attr.Value[0:4]))
case unix.RTA_MULTIPATH:
@@ -1140,6 +1292,11 @@ func deserializeRoute(m []byte) (Route, error) {
if err := e.Decode(encap.Value); err != nil {
return route, err
}
+ case nl.LWTUNNEL_ENCAP_BPF:
+ e = &BpfEncap{}
+ if err := e.Decode(encap.Value); err != nil {
+ return route, err
+ }
}
route.Encap = e
}
@@ -1150,6 +1307,8 @@ func deserializeRoute(m []byte) (Route, error) {
// RouteGetOptions contains a set of options to use with
// RouteGetWithOptions
type RouteGetOptions struct {
+ Iif string
+ Oif string
VrfName string
SrcAddr net.IP
}
@@ -1198,10 +1357,31 @@ func (h *Handle) RouteGetWithOptions(destination net.IP, options *RouteGetOption
if err != nil {
return nil, err
}
- var (
- b = make([]byte, 4)
- native = nl.NativeEndian()
- )
+ b := make([]byte, 4)
+ native.PutUint32(b, uint32(link.Attrs().Index))
+
+ req.AddData(nl.NewRtAttr(unix.RTA_OIF, b))
+ }
+
+ if len(options.Iif) > 0 {
+ link, err := LinkByName(options.Iif)
+ if err != nil {
+ return nil, err
+ }
+
+ b := make([]byte, 4)
+ native.PutUint32(b, uint32(link.Attrs().Index))
+
+ req.AddData(nl.NewRtAttr(unix.RTA_IIF, b))
+ }
+
+ if len(options.Oif) > 0 {
+ link, err := LinkByName(options.Oif)
+ if err != nil {
+ return nil, err
+ }
+
+ b := make([]byte, 4)
native.PutUint32(b, uint32(link.Attrs().Index))
req.AddData(nl.NewRtAttr(unix.RTA_OIF, b))
@@ -1298,7 +1478,8 @@ func routeSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- RouteUpdate, done <
msgs, from, err := s.Receive()
if err != nil {
if cberr != nil {
- cberr(err)
+ cberr(fmt.Errorf("Receive failed: %v",
+ err))
}
return
}
@@ -1313,22 +1494,22 @@ func routeSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- RouteUpdate, done <
continue
}
if m.Header.Type == unix.NLMSG_ERROR {
- native := nl.NativeEndian()
error := int32(native.Uint32(m.Data[0:4]))
if error == 0 {
continue
}
if cberr != nil {
- cberr(syscall.Errno(-error))
+ cberr(fmt.Errorf("error message: %v",
+ syscall.Errno(-error)))
}
- return
+ continue
}
route, err := deserializeRoute(m.Data)
if err != nil {
if cberr != nil {
cberr(err)
}
- return
+ continue
}
ch <- RouteUpdate{Type: m.Header.Type, Route: route}
}
diff --git a/vendor/github.com/vishvananda/netlink/rule.go b/vendor/github.com/vishvananda/netlink/rule.go
index 95f2facfb..9b7b0af49 100644
--- a/vendor/github.com/vishvananda/netlink/rule.go
+++ b/vendor/github.com/vishvananda/netlink/rule.go
@@ -28,7 +28,18 @@ type Rule struct {
}
func (r Rule) String() string {
- return fmt.Sprintf("ip rule %d: from %s table %d", r.Priority, r.Src, r.Table)
+ from := "all"
+ if r.Src != nil && r.Src.String() != "<nil>" {
+ from = r.Src.String()
+ }
+
+ to := "all"
+ if r.Dst != nil && r.Dst.String() != "<nil>" {
+ to = r.Dst.String()
+ }
+
+ return fmt.Sprintf("ip rule %d: from %s to %s table %d",
+ r.Priority, from, to, r.Table)
}
// NewRule return empty rules.
diff --git a/vendor/github.com/vishvananda/netlink/rule_linux.go b/vendor/github.com/vishvananda/netlink/rule_linux.go
index 40474f30e..9c426cbd3 100644
--- a/vendor/github.com/vishvananda/netlink/rule_linux.go
+++ b/vendor/github.com/vishvananda/netlink/rule_linux.go
@@ -97,8 +97,6 @@ func ruleHandle(rule *Rule, req *nl.NetlinkRequest) error {
req.AddData(rtAttrs[i])
}
- native := nl.NativeEndian()
-
if rule.Priority >= 0 {
b := make([]byte, 4)
native.PutUint32(b, uint32(rule.Priority))
@@ -199,7 +197,6 @@ func (h *Handle) RuleListFiltered(family int, filter *Rule, filterMask uint64) (
return nil, err
}
- native := nl.NativeEndian()
var res = make([]Rule, 0)
for i := range msgs {
msg := nl.DeserializeRtMsg(msgs[i])
@@ -232,7 +229,7 @@ func (h *Handle) RuleListFiltered(family int, filter *Rule, filterMask uint64) (
case nl.FRA_FWMASK:
rule.Mask = int(native.Uint32(attrs[j].Value[0:4]))
case nl.FRA_TUN_ID:
- rule.TunID = uint(native.Uint64(attrs[j].Value[0:4]))
+ rule.TunID = uint(native.Uint64(attrs[j].Value[0:8]))
case nl.FRA_IIFNAME:
rule.IifName = string(attrs[j].Value[:len(attrs[j].Value)-1])
case nl.FRA_OIFNAME:
diff --git a/vendor/github.com/vishvananda/netlink/socket_linux.go b/vendor/github.com/vishvananda/netlink/socket_linux.go
index 9b0f4a081..b881fe496 100644
--- a/vendor/github.com/vishvananda/netlink/socket_linux.go
+++ b/vendor/github.com/vishvananda/netlink/socket_linux.go
@@ -172,12 +172,56 @@ func SocketGet(local, remote net.Addr) (*Socket, error) {
return sock, nil
}
-// SocketDiagTCPInfo requests INET_DIAG_INFO for TCP protocol for specified family type.
+// SocketDiagTCPInfo requests INET_DIAG_INFO for TCP protocol for specified family type and return with extension TCP info.
func SocketDiagTCPInfo(family uint8) ([]*InetDiagTCPInfoResp, error) {
- s, err := nl.Subscribe(unix.NETLINK_INET_DIAG)
+ var result []*InetDiagTCPInfoResp
+ err := socketDiagTCPExecutor(family, func(m syscall.NetlinkMessage) error {
+ sockInfo := &Socket{}
+ if err := sockInfo.deserialize(m.Data); err != nil {
+ return err
+ }
+ attrs, err := nl.ParseRouteAttr(m.Data[sizeofSocket:])
+ if err != nil {
+ return err
+ }
+
+ res, err := attrsToInetDiagTCPInfoResp(attrs, sockInfo)
+ if err != nil {
+ return err
+ }
+
+ result = append(result, res)
+ return nil
+ })
+ if err != nil {
+ return nil, err
+ }
+ return result, nil
+}
+
+// SocketDiagTCP requests INET_DIAG_INFO for TCP protocol for specified family type and return related socket.
+func SocketDiagTCP(family uint8) ([]*Socket, error) {
+ var result []*Socket
+ err := socketDiagTCPExecutor(family, func(m syscall.NetlinkMessage) error {
+ sockInfo := &Socket{}
+ if err := sockInfo.deserialize(m.Data); err != nil {
+ return err
+ }
+ result = append(result, sockInfo)
+ return nil
+ })
if err != nil {
return nil, err
}
+ return result, nil
+}
+
+// socketDiagTCPExecutor requests INET_DIAG_INFO for TCP protocol for specified family type.
+func socketDiagTCPExecutor(family uint8, receiver func(syscall.NetlinkMessage) error) error {
+ s, err := nl.Subscribe(unix.NETLINK_INET_DIAG)
+ if err != nil {
+ return err
+ }
defer s.Close()
req := nl.NewNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP)
@@ -189,18 +233,17 @@ func SocketDiagTCPInfo(family uint8) ([]*InetDiagTCPInfoResp, error) {
})
s.Send(req)
- var result []*InetDiagTCPInfoResp
loop:
for {
msgs, from, err := s.Receive()
if err != nil {
- return nil, err
+ return err
}
if from.Pid != nl.PidKernel {
- return nil, fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel)
+ return fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel)
}
if len(msgs) == 0 {
- return nil, errors.New("no message nor error from netlink")
+ return errors.New("no message nor error from netlink")
}
for _, m := range msgs {
@@ -208,28 +251,15 @@ loop:
case unix.NLMSG_DONE:
break loop
case unix.NLMSG_ERROR:
- native := nl.NativeEndian()
error := int32(native.Uint32(m.Data[0:4]))
- return nil, syscall.Errno(-error)
+ return syscall.Errno(-error)
}
- sockInfo := &Socket{}
- if err := sockInfo.deserialize(m.Data); err != nil {
- return nil, err
+ if err := receiver(m); err != nil {
+ return err
}
- attrs, err := nl.ParseRouteAttr(m.Data[sizeofSocket:])
- if err != nil {
- return nil, err
- }
-
- res, err := attrsToInetDiagTCPInfoResp(attrs, sockInfo)
- if err != nil {
- return nil, err
- }
-
- result = append(result, res)
}
}
- return result, nil
+ return nil
}
func attrsToInetDiagTCPInfoResp(attrs []syscall.NetlinkRouteAttr, sockInfo *Socket) (*InetDiagTCPInfoResp, error) {
diff --git a/vendor/github.com/vishvananda/netlink/xfrm_state_linux.go b/vendor/github.com/vishvananda/netlink/xfrm_state_linux.go
index 5b1b6c31a..3b37b87d3 100644
--- a/vendor/github.com/vishvananda/netlink/xfrm_state_linux.go
+++ b/vendor/github.com/vishvananda/netlink/xfrm_state_linux.go
@@ -111,7 +111,7 @@ func (h *Handle) xfrmStateAddOrUpdate(state *XfrmState, nlProto int) error {
// A state with spi 0 can't be deleted so don't allow it to be set
if state.Spi == 0 {
- return fmt.Errorf("Spi must be set when adding xfrm state.")
+ return fmt.Errorf("Spi must be set when adding xfrm state")
}
req := h.newNetlinkRequest(nlProto, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK)