Update netlink vendoring (#1471)
* github.com/ema/qdisc * github.com/mdlayher/genetlink * github.com/mdlayher/wifi Signed-off-by: Ben Kochie <superq@gmail.com>
This commit is contained in:
parent
8c3de12c22
commit
0e77317955
245 changed files with 6515 additions and 1699 deletions
1
vendor/github.com/mdlayher/netlink/.gitignore
generated
vendored
1
vendor/github.com/mdlayher/netlink/.gitignore
generated
vendored
|
|
@ -1 +1,2 @@
|
|||
cmd/nlstress/nlstress
|
||||
netlink.test
|
||||
|
|
|
|||
17
vendor/github.com/mdlayher/netlink/.travis.yml
generated
vendored
17
vendor/github.com/mdlayher/netlink/.travis.yml
generated
vendored
|
|
@ -1,17 +0,0 @@
|
|||
language: go
|
||||
go:
|
||||
- "1.x"
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
sudo: required
|
||||
before_install:
|
||||
- go get golang.org/x/lint/golint
|
||||
- go get honnef.co/go/tools/cmd/staticcheck
|
||||
- go get -d ./...
|
||||
script:
|
||||
- go build -tags=gofuzz ./...
|
||||
- go vet ./...
|
||||
- staticcheck ./...
|
||||
- golint -set_exit_status ./...
|
||||
- go test -v -race -tags=integration ./...
|
||||
2
vendor/github.com/mdlayher/netlink/LICENSE.md
generated
vendored
2
vendor/github.com/mdlayher/netlink/LICENSE.md
generated
vendored
|
|
@ -1,7 +1,7 @@
|
|||
MIT License
|
||||
===========
|
||||
|
||||
Copyright (C) 2016-2017 Matt Layher
|
||||
Copyright (C) 2016-2019 Matt Layher
|
||||
|
||||
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:
|
||||
|
||||
|
|
|
|||
42
vendor/github.com/mdlayher/netlink/README.md
generated
vendored
42
vendor/github.com/mdlayher/netlink/README.md
generated
vendored
|
|
@ -1,27 +1,49 @@
|
|||
netlink [](https://travis-ci.org/mdlayher/netlink) [](https://godoc.org/github.com/mdlayher/netlink) [](https://goreportcard.com/report/github.com/mdlayher/netlink)
|
||||
=======
|
||||
# netlink [](https://builds.sr.ht/~mdlayher/netlink?) [](https://godoc.org/github.com/mdlayher/netlink) [](https://goreportcard.com/report/github.com/mdlayher/netlink)
|
||||
|
||||
Package `netlink` provides low-level access to Linux netlink sockets.
|
||||
MIT Licensed.
|
||||
|
||||
For more information about how netlink works, check out my blog series
|
||||
on [Linux, Netlink, and Go](https://medium.com/@mdlayher/linux-netlink-and-go-part-1-netlink-4781aaeeaca8).
|
||||
on [Linux, Netlink, and Go](https://mdlayher.com/blog/linux-netlink-and-go-part-1-netlink/).
|
||||
|
||||
If you're looking for package `genetlink`, it's been moved to its own
|
||||
repository at [`github.com/mdlayher/genetlink`](https://github.com/mdlayher/genetlink).
|
||||
If you have any questions or you'd like some guidance, please join us on
|
||||
[Gophers Slack](https://invite.slack.golangbridge.org) in the `#networking`
|
||||
channel!
|
||||
|
||||
Why?
|
||||
----
|
||||
## Stability
|
||||
|
||||
At this time, package `netlink` is in a pre-v1.0.0 state. Changes are being made
|
||||
which may impact the exported API of this package and others in its ecosystem.
|
||||
To follow along on the status of a v1.0.0 release, [see the associated issue](https://github.com/mdlayher/netlink/issues/123).
|
||||
|
||||
The general policy of this package is to only support the latest, stable version
|
||||
of Go. Compatibility shims may be added for prior versions of Go on an as-needed
|
||||
basis. If you would like to raise a concern, please [file an issue](https://github.com/mdlayher/netlink/issues/new).
|
||||
|
||||
**If you depend on this package in your applications, please vendor it or use Go
|
||||
modules when building your application.**
|
||||
|
||||
## Design
|
||||
|
||||
A [number of netlink packages](https://godoc.org/?q=netlink) are already
|
||||
available for Go, but I wasn't able to find one that aligned with what
|
||||
I wanted in a netlink package:
|
||||
|
||||
- Simple, idiomatic API
|
||||
- Straightforward, idiomatic API
|
||||
- Well tested
|
||||
- Well documented
|
||||
- Makes use of Go best practices
|
||||
- Doesn't need root to work
|
||||
- Doesn't use package/global variables or state
|
||||
- Doesn't necessarily need root to work
|
||||
|
||||
My goal for this package is to use it as a building block for the creation
|
||||
of other netlink family packages.
|
||||
|
||||
## Ecosystem
|
||||
|
||||
Over time, an ecosystem of Go packages has developed around package `netlink`.
|
||||
Many of these packages provide building blocks for further interactions with
|
||||
various netlink families, such as `NETLINK_GENERIC` or `NETLINK_ROUTE`.
|
||||
|
||||
To have your package included in this diagram, please send a pull request!
|
||||
|
||||

|
||||
|
|
|
|||
4
vendor/github.com/mdlayher/netlink/align.go
generated
vendored
4
vendor/github.com/mdlayher/netlink/align.go
generated
vendored
|
|
@ -1,8 +1,6 @@
|
|||
package netlink
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
import "unsafe"
|
||||
|
||||
// Functions and values used to properly align netlink messages, headers,
|
||||
// and attributes. Definitions taken from Linux kernel source.
|
||||
|
|
|
|||
14
vendor/github.com/mdlayher/netlink/attribute.go
generated
vendored
14
vendor/github.com/mdlayher/netlink/attribute.go
generated
vendored
|
|
@ -8,10 +8,8 @@ import (
|
|||
"github.com/mdlayher/netlink/nlenc"
|
||||
)
|
||||
|
||||
var (
|
||||
// errInvalidAttribute specifies if an Attribute's length is incorrect.
|
||||
errInvalidAttribute = errors.New("invalid attribute; length too short or too large")
|
||||
)
|
||||
// errInvalidAttribute specifies if an Attribute's length is incorrect.
|
||||
var errInvalidAttribute = errors.New("invalid attribute; length too short or too large")
|
||||
|
||||
// An Attribute is a netlink attribute. Attributes are packed and unpacked
|
||||
// to and from the Data field of Message for some netlink families.
|
||||
|
|
@ -180,12 +178,8 @@ func (ad *AttributeDecoder) Next() bool {
|
|||
|
||||
ad.i++
|
||||
|
||||
if len(ad.attrs) < ad.i {
|
||||
// No more attributes, stop iteration.
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
// More attributes?
|
||||
return len(ad.attrs) >= ad.i
|
||||
}
|
||||
|
||||
// Type returns the Attribute.Type field of the current netlink attribute
|
||||
|
|
|
|||
317
vendor/github.com/mdlayher/netlink/conn.go
generated
vendored
317
vendor/github.com/mdlayher/netlink/conn.go
generated
vendored
|
|
@ -2,9 +2,9 @@ package netlink
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"math/rand"
|
||||
"os"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"syscall"
|
||||
"time"
|
||||
|
|
@ -12,30 +12,16 @@ import (
|
|||
"golang.org/x/net/bpf"
|
||||
)
|
||||
|
||||
// Error messages which can be returned by Validate.
|
||||
var (
|
||||
errMismatchedSequence = errors.New("mismatched sequence in netlink reply")
|
||||
errMismatchedPID = errors.New("mismatched PID in netlink reply")
|
||||
errShortErrorMessage = errors.New("not enough data for netlink error code")
|
||||
)
|
||||
|
||||
// Errors which can be returned by a Socket that does not implement
|
||||
// all exposed methods of Conn.
|
||||
var (
|
||||
errReadWriteCloserNotSupported = errors.New("raw read/write/closer not supported")
|
||||
errMulticastGroupsNotSupported = errors.New("multicast groups not supported")
|
||||
errBPFFiltersNotSupported = errors.New("BPF filters not supported")
|
||||
errOptionsNotSupported = errors.New("options not supported")
|
||||
errSetBufferNotSupported = errors.New("setting buffer sizes not supported")
|
||||
errSyscallConnNotSupported = errors.New("syscall.RawConn operation not supported")
|
||||
)
|
||||
|
||||
// A Conn is a connection to netlink. A Conn can be used to send and
|
||||
// receives messages to and from netlink.
|
||||
//
|
||||
// A Conn is safe for concurrent use, but to avoid contention in
|
||||
// high-throughput applications, the caller should almost certainly create a
|
||||
// pool of Conns and distribute them among workers.
|
||||
//
|
||||
// A Conn is capable of manipulating netlink subsystems from within a specific
|
||||
// Linux network namespace, but special care must be taken when doing so. See
|
||||
// the documentation of Config for details.
|
||||
type Conn struct {
|
||||
// sock is the operating system-specific implementation of
|
||||
// a netlink sockets connection.
|
||||
|
|
@ -50,6 +36,10 @@ type Conn struct {
|
|||
|
||||
// d provides debugging capabilities for a Conn if not nil.
|
||||
d *debugger
|
||||
|
||||
// mu serializes access to the netlink socket for the request/response
|
||||
// transaction within Execute.
|
||||
mu sync.RWMutex
|
||||
}
|
||||
|
||||
// A Socket is an operating-system specific implementation of netlink
|
||||
|
|
@ -107,24 +97,40 @@ func (c *Conn) debug(fn func(d *debugger)) {
|
|||
fn(c.d)
|
||||
}
|
||||
|
||||
// Close closes the connection.
|
||||
// Close closes the connection. Close will unblock any concurrent calls to
|
||||
// Receive which are waiting on a response from the kernel.
|
||||
func (c *Conn) Close() error {
|
||||
return c.sock.Close()
|
||||
// Close does not acquire a lock because it must be able to interrupt any
|
||||
// blocked system calls, such as when Receive is waiting on a multicast
|
||||
// group message.
|
||||
//
|
||||
// We rely on the kernel to deal with concurrent operations to the netlink
|
||||
// socket itself.
|
||||
return newOpError("close", c.sock.Close())
|
||||
}
|
||||
|
||||
// Execute sends a single Message to netlink using Conn.Send, receives one or more
|
||||
// replies using Conn.Receive, and then checks the validity of the replies against
|
||||
// Execute sends a single Message to netlink using Send, receives one or more
|
||||
// replies using Receive, and then checks the validity of the replies against
|
||||
// the request using Validate.
|
||||
//
|
||||
// See the documentation of Conn.Send, Conn.Receive, and Validate for details about
|
||||
// Execute acquires a lock for the duration of the function call which blocks
|
||||
// concurrent calls to Send, SendMessages, and Receive, in order to ensure
|
||||
// consistency between netlink request/reply messages.
|
||||
//
|
||||
// See the documentation of Send, Receive, and Validate for details about
|
||||
// each function.
|
||||
func (c *Conn) Execute(message Message) ([]Message, error) {
|
||||
req, err := c.Send(message)
|
||||
// Acquire the write lock and invoke the internal implementations of Send
|
||||
// and Receive which require the lock already be held.
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
req, err := c.lockedSend(message)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
replies, err := c.Receive()
|
||||
replies, err := c.lockedReceive()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -136,24 +142,14 @@ func (c *Conn) Execute(message Message) ([]Message, error) {
|
|||
return replies, nil
|
||||
}
|
||||
|
||||
func (c *Conn) fixMsg(m *Message, ml int) {
|
||||
if m.Header.Length == 0 {
|
||||
m.Header.Length = uint32(nlmsgAlign(ml))
|
||||
}
|
||||
|
||||
if m.Header.Sequence == 0 {
|
||||
m.Header.Sequence = c.nextSequence()
|
||||
}
|
||||
|
||||
if m.Header.PID == 0 {
|
||||
m.Header.PID = c.pid
|
||||
}
|
||||
}
|
||||
|
||||
// SendMessages sends multiple Messages to netlink. The handling of
|
||||
// a Header's Length, Sequence and PID fields is the same as when
|
||||
// calling Send.
|
||||
func (c *Conn) SendMessages(messages []Message) ([]Message, error) {
|
||||
// Wait for any concurrent calls to Execute to finish before proceeding.
|
||||
c.mu.RLock()
|
||||
defer c.mu.RUnlock()
|
||||
|
||||
for idx, m := range messages {
|
||||
ml := nlmsgLength(len(m.Data))
|
||||
|
||||
|
|
@ -176,7 +172,7 @@ func (c *Conn) SendMessages(messages []Message) ([]Message, error) {
|
|||
d.debugf(1, "send msgs: err: %v", err)
|
||||
})
|
||||
|
||||
return nil, err
|
||||
return nil, newOpError("send-messages", err)
|
||||
}
|
||||
|
||||
return messages, nil
|
||||
|
|
@ -196,6 +192,17 @@ func (c *Conn) SendMessages(messages []Message) ([]Message, error) {
|
|||
// If Header.PID is 0, it will be automatically populated using a PID
|
||||
// assigned by netlink.
|
||||
func (c *Conn) Send(message Message) (Message, error) {
|
||||
// Wait for any concurrent calls to Execute to finish before proceeding.
|
||||
c.mu.RLock()
|
||||
defer c.mu.RUnlock()
|
||||
|
||||
return c.lockedSend(message)
|
||||
}
|
||||
|
||||
// lockedSend implements Send, but must be called with c.mu acquired for reading.
|
||||
// We rely on the kernel to deal with concurrent reads and writes to the netlink
|
||||
// socket itself.
|
||||
func (c *Conn) lockedSend(message Message) (Message, error) {
|
||||
ml := nlmsgLength(len(message.Data))
|
||||
|
||||
// TODO(mdlayher): fine-tune this limit.
|
||||
|
|
@ -214,7 +221,7 @@ func (c *Conn) Send(message Message) (Message, error) {
|
|||
d.debugf(1, "send: err: %v", err)
|
||||
})
|
||||
|
||||
return Message{}, err
|
||||
return Message{}, newOpError("send", err)
|
||||
}
|
||||
|
||||
return message, nil
|
||||
|
|
@ -226,6 +233,17 @@ func (c *Conn) Send(message Message) (Message, error) {
|
|||
//
|
||||
// If any of the messages indicate a netlink error, that error will be returned.
|
||||
func (c *Conn) Receive() ([]Message, error) {
|
||||
// Wait for any concurrent calls to Execute to finish before proceeding.
|
||||
c.mu.RLock()
|
||||
defer c.mu.RUnlock()
|
||||
|
||||
return c.lockedReceive()
|
||||
}
|
||||
|
||||
// lockedReceive implements Receive, but must be called with c.mu acquired for reading.
|
||||
// We rely on the kernel to deal with concurrent reads and writes to the netlink
|
||||
// socket itself.
|
||||
func (c *Conn) lockedReceive() ([]Message, error) {
|
||||
msgs, err := c.receive()
|
||||
if err != nil {
|
||||
c.debug(func(d *debugger) {
|
||||
|
|
@ -248,7 +266,7 @@ func (c *Conn) Receive() ([]Message, error) {
|
|||
|
||||
// Trim the final message with multi-part done indicator if
|
||||
// present.
|
||||
if m := msgs[len(msgs)-1]; m.Header.Flags&HeaderFlagsMulti != 0 && m.Header.Type == HeaderTypeDone {
|
||||
if m := msgs[len(msgs)-1]; m.Header.Flags&Multi != 0 && m.Header.Type == Done {
|
||||
return msgs[:len(msgs)-1], nil
|
||||
}
|
||||
|
||||
|
|
@ -258,11 +276,18 @@ func (c *Conn) Receive() ([]Message, error) {
|
|||
// receive is the internal implementation of Conn.Receive, which can be called
|
||||
// recursively to handle multi-part messages.
|
||||
func (c *Conn) receive() ([]Message, error) {
|
||||
// NB: All non-nil errors returned from this function *must* be of type
|
||||
// OpError in order to maintain the appropriate contract with callers of
|
||||
// this package.
|
||||
//
|
||||
// This contract also applies to functions called within this function,
|
||||
// such as checkMessage.
|
||||
|
||||
var res []Message
|
||||
for {
|
||||
msgs, err := c.sock.Receive()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, newOpError("receive", err)
|
||||
}
|
||||
|
||||
// If this message is multi-part, we will need to perform an recursive call
|
||||
|
|
@ -275,14 +300,14 @@ func (c *Conn) receive() ([]Message, error) {
|
|||
}
|
||||
|
||||
// Does this message indicate a multi-part message?
|
||||
if m.Header.Flags&HeaderFlagsMulti == 0 {
|
||||
if m.Header.Flags&Multi == 0 {
|
||||
// No, check the next messages.
|
||||
continue
|
||||
}
|
||||
|
||||
// Does this message indicate the last message in a series of
|
||||
// multi-part messages from a single read?
|
||||
multi = m.Header.Type != HeaderTypeDone
|
||||
multi = m.Header.Type != Done
|
||||
}
|
||||
|
||||
res = append(res, msgs...)
|
||||
|
|
@ -294,51 +319,6 @@ func (c *Conn) receive() ([]Message, error) {
|
|||
}
|
||||
}
|
||||
|
||||
// An fder is a Socket that supports retrieving its raw file descriptor.
|
||||
type fder interface {
|
||||
Socket
|
||||
FD() int
|
||||
}
|
||||
|
||||
var _ io.ReadWriteCloser = &fileReadWriteCloser{}
|
||||
|
||||
// A fileReadWriteCloser is a limited *os.File which only allows access to its
|
||||
// Read and Write methods.
|
||||
type fileReadWriteCloser struct {
|
||||
f *os.File
|
||||
}
|
||||
|
||||
// Read implements io.ReadWriteCloser.
|
||||
func (rwc *fileReadWriteCloser) Read(b []byte) (int, error) { return rwc.f.Read(b) }
|
||||
|
||||
// Write implements io.ReadWriteCloser.
|
||||
func (rwc *fileReadWriteCloser) Write(b []byte) (int, error) { return rwc.f.Write(b) }
|
||||
|
||||
// Close implements io.ReadWriteCloser.
|
||||
func (rwc *fileReadWriteCloser) Close() error { return rwc.f.Close() }
|
||||
|
||||
// ReadWriteCloser returns a raw io.ReadWriteCloser backed by the connection
|
||||
// of the Conn.
|
||||
//
|
||||
// ReadWriteCloser is intended for advanced use cases, such as those that do
|
||||
// not involve standard netlink message passing.
|
||||
//
|
||||
// Once invoked, it is the caller's responsibility to ensure that operations
|
||||
// performed using Conn and the raw io.ReadWriteCloser do not conflict with
|
||||
// each other. In almost all scenarios, only one of the two should be used.
|
||||
func (c *Conn) ReadWriteCloser() (io.ReadWriteCloser, error) {
|
||||
fc, ok := c.sock.(fder)
|
||||
if !ok {
|
||||
return nil, errReadWriteCloserNotSupported
|
||||
}
|
||||
|
||||
return &fileReadWriteCloser{
|
||||
// Backing the io.ReadWriteCloser with an *os.File enables easy reading
|
||||
// and writing without more system call boilerplate.
|
||||
f: os.NewFile(uintptr(fc.FD()), "netlink"),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// A groupJoinLeaver is a Socket that supports joining and leaving
|
||||
// netlink multicast groups.
|
||||
type groupJoinLeaver interface {
|
||||
|
|
@ -349,22 +329,22 @@ type groupJoinLeaver interface {
|
|||
|
||||
// JoinGroup joins a netlink multicast group by its ID.
|
||||
func (c *Conn) JoinGroup(group uint32) error {
|
||||
gc, ok := c.sock.(groupJoinLeaver)
|
||||
conn, ok := c.sock.(groupJoinLeaver)
|
||||
if !ok {
|
||||
return errMulticastGroupsNotSupported
|
||||
return notSupported("join-group")
|
||||
}
|
||||
|
||||
return gc.JoinGroup(group)
|
||||
return newOpError("join-group", conn.JoinGroup(group))
|
||||
}
|
||||
|
||||
// LeaveGroup leaves a netlink multicast group by its ID.
|
||||
func (c *Conn) LeaveGroup(group uint32) error {
|
||||
gc, ok := c.sock.(groupJoinLeaver)
|
||||
conn, ok := c.sock.(groupJoinLeaver)
|
||||
if !ok {
|
||||
return errMulticastGroupsNotSupported
|
||||
return notSupported("leave-group")
|
||||
}
|
||||
|
||||
return gc.LeaveGroup(group)
|
||||
return newOpError("leave-group", conn.LeaveGroup(group))
|
||||
}
|
||||
|
||||
// A bpfSetter is a Socket that supports setting and removing BPF filters.
|
||||
|
|
@ -376,22 +356,69 @@ type bpfSetter interface {
|
|||
|
||||
// SetBPF attaches an assembled BPF program to a Conn.
|
||||
func (c *Conn) SetBPF(filter []bpf.RawInstruction) error {
|
||||
bc, ok := c.sock.(bpfSetter)
|
||||
conn, ok := c.sock.(bpfSetter)
|
||||
if !ok {
|
||||
return errBPFFiltersNotSupported
|
||||
return notSupported("set-bpf")
|
||||
}
|
||||
|
||||
return bc.SetBPF(filter)
|
||||
return newOpError("set-bpf", conn.SetBPF(filter))
|
||||
}
|
||||
|
||||
// RemoveBPF removes a BPF filter from a Conn.
|
||||
func (c *Conn) RemoveBPF() error {
|
||||
s, ok := c.sock.(bpfSetter)
|
||||
conn, ok := c.sock.(bpfSetter)
|
||||
if !ok {
|
||||
return errBPFFiltersNotSupported
|
||||
return notSupported("remove-bpf")
|
||||
}
|
||||
|
||||
return s.RemoveBPF()
|
||||
return newOpError("remove-bpf", conn.RemoveBPF())
|
||||
}
|
||||
|
||||
// A deadlineSetter is a Socket that supports setting deadlines.
|
||||
type deadlineSetter interface {
|
||||
Socket
|
||||
SetDeadline(time.Time) error
|
||||
SetReadDeadline(time.Time) error
|
||||
SetWriteDeadline(time.Time) error
|
||||
}
|
||||
|
||||
// SetDeadline sets the read and write deadlines associated with the connection.
|
||||
//
|
||||
// Deadline functionality is only supported on Go 1.12+. Calling this function
|
||||
// on older versions of Go will result in an error.
|
||||
func (c *Conn) SetDeadline(t time.Time) error {
|
||||
conn, ok := c.sock.(deadlineSetter)
|
||||
if !ok {
|
||||
return notSupported("set-deadline")
|
||||
}
|
||||
|
||||
return newOpError("set-deadline", conn.SetDeadline(t))
|
||||
}
|
||||
|
||||
// SetReadDeadline sets the read deadline associated with the connection.
|
||||
//
|
||||
// Deadline functionality is only supported on Go 1.12+. Calling this function
|
||||
// on older versions of Go will result in an error.
|
||||
func (c *Conn) SetReadDeadline(t time.Time) error {
|
||||
conn, ok := c.sock.(deadlineSetter)
|
||||
if !ok {
|
||||
return notSupported("set-read-deadline")
|
||||
}
|
||||
|
||||
return newOpError("set-read-deadline", conn.SetReadDeadline(t))
|
||||
}
|
||||
|
||||
// SetWriteDeadline sets the write deadline associated with the connection.
|
||||
//
|
||||
// Deadline functionality is only supported on Go 1.12+. Calling this function
|
||||
// on older versions of Go will result in an error.
|
||||
func (c *Conn) SetWriteDeadline(t time.Time) error {
|
||||
conn, ok := c.sock.(deadlineSetter)
|
||||
if !ok {
|
||||
return notSupported("set-write-deadline")
|
||||
}
|
||||
|
||||
return newOpError("set-write-deadline", conn.SetWriteDeadline(t))
|
||||
}
|
||||
|
||||
// A ConnOption is a boolean option that may be set for a Conn.
|
||||
|
|
@ -405,6 +432,7 @@ const (
|
|||
NoENOBUFS
|
||||
ListenAllNSID
|
||||
CapAcknowledge
|
||||
ExtendedAcknowledge
|
||||
)
|
||||
|
||||
// An optionSetter is a Socket that supports setting netlink options.
|
||||
|
|
@ -415,12 +443,12 @@ type optionSetter interface {
|
|||
|
||||
// SetOption enables or disables a netlink socket option for the Conn.
|
||||
func (c *Conn) SetOption(option ConnOption, enable bool) error {
|
||||
fc, ok := c.sock.(optionSetter)
|
||||
conn, ok := c.sock.(optionSetter)
|
||||
if !ok {
|
||||
return errOptionsNotSupported
|
||||
return notSupported("set-option")
|
||||
}
|
||||
|
||||
return fc.SetOption(option, enable)
|
||||
return newOpError("set-option", conn.SetOption(option, enable))
|
||||
}
|
||||
|
||||
// A bufferSetter is a Socket that supports setting connection buffer sizes.
|
||||
|
|
@ -435,10 +463,10 @@ type bufferSetter interface {
|
|||
func (c *Conn) SetReadBuffer(bytes int) error {
|
||||
conn, ok := c.sock.(bufferSetter)
|
||||
if !ok {
|
||||
return errSetBufferNotSupported
|
||||
return notSupported("set-read-buffer")
|
||||
}
|
||||
|
||||
return conn.SetReadBuffer(bytes)
|
||||
return newOpError("set-read-buffer", conn.SetReadBuffer(bytes))
|
||||
}
|
||||
|
||||
// SetWriteBuffer sets the size of the operating system's transmit buffer
|
||||
|
|
@ -446,10 +474,16 @@ func (c *Conn) SetReadBuffer(bytes int) error {
|
|||
func (c *Conn) SetWriteBuffer(bytes int) error {
|
||||
conn, ok := c.sock.(bufferSetter)
|
||||
if !ok {
|
||||
return errSetBufferNotSupported
|
||||
return notSupported("set-write-buffer")
|
||||
}
|
||||
|
||||
return conn.SetWriteBuffer(bytes)
|
||||
return newOpError("set-write-buffer", conn.SetWriteBuffer(bytes))
|
||||
}
|
||||
|
||||
// A filer is a Socket that supports retrieving its associated *os.File.
|
||||
type filer interface {
|
||||
Socket
|
||||
File() *os.File
|
||||
}
|
||||
|
||||
var _ syscall.Conn = &Conn{}
|
||||
|
|
@ -460,8 +494,10 @@ var _ syscall.Conn = &Conn{}
|
|||
// SyscallConn returns a raw network connection. This implements the
|
||||
// syscall.Conn interface.
|
||||
//
|
||||
// Only the Control method of the returned syscall.RawConn is currently
|
||||
// implemented.
|
||||
// On Go 1.12+, all methods of the returned syscall.RawConn are supported and
|
||||
// the Conn is integrated with the runtime network poller. On versions of Go
|
||||
// prior to Go 1.12, only the Control method of the returned syscall.RawConn
|
||||
// is implemented.
|
||||
//
|
||||
// SyscallConn is intended for advanced use cases, such as getting and setting
|
||||
// arbitrary socket options using the netlink socket's file descriptor.
|
||||
|
|
@ -470,33 +506,29 @@ var _ syscall.Conn = &Conn{}
|
|||
// performed using Conn and the syscall.RawConn do not conflict with
|
||||
// each other.
|
||||
func (c *Conn) SyscallConn() (syscall.RawConn, error) {
|
||||
conn, ok := c.sock.(fder)
|
||||
fc, ok := c.sock.(filer)
|
||||
if !ok {
|
||||
return nil, errSyscallConnNotSupported
|
||||
return nil, notSupported("syscall-conn")
|
||||
}
|
||||
|
||||
return &rawConn{
|
||||
fd: uintptr(conn.FD()),
|
||||
}, nil
|
||||
return newRawConn(fc.File())
|
||||
}
|
||||
|
||||
var _ syscall.RawConn = &rawConn{}
|
||||
// fixMsg updates the fields of m using the logic specified in Send.
|
||||
func (c *Conn) fixMsg(m *Message, ml int) {
|
||||
if m.Header.Length == 0 {
|
||||
m.Header.Length = uint32(nlmsgAlign(ml))
|
||||
}
|
||||
|
||||
// A rawConn is a syscall.RawConn.
|
||||
type rawConn struct {
|
||||
fd uintptr
|
||||
if m.Header.Sequence == 0 {
|
||||
m.Header.Sequence = c.nextSequence()
|
||||
}
|
||||
|
||||
if m.Header.PID == 0 {
|
||||
m.Header.PID = c.pid
|
||||
}
|
||||
}
|
||||
|
||||
func (rc *rawConn) Control(f func(fd uintptr)) error {
|
||||
f(rc.fd)
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO(mdlayher): implement Read and Write?
|
||||
|
||||
func (rc *rawConn) Read(_ func(fd uintptr) (done bool)) error { return errSyscallConnNotSupported }
|
||||
func (rc *rawConn) Write(_ func(fd uintptr) (done bool)) error { return errSyscallConnNotSupported }
|
||||
|
||||
// nextSequence atomically increments Conn's sequence number and returns
|
||||
// the incremented value.
|
||||
func (c *Conn) nextSequence() uint32 {
|
||||
|
|
@ -511,7 +543,7 @@ func Validate(request Message, replies []Message) error {
|
|||
// - request had no sequence, meaning we are probably validating
|
||||
// a multicast reply
|
||||
if m.Header.Sequence != request.Header.Sequence && request.Header.Sequence != 0 {
|
||||
return errMismatchedSequence
|
||||
return newOpError("validate", errMismatchedSequence)
|
||||
}
|
||||
|
||||
// Check for mismatched PID, unless:
|
||||
|
|
@ -520,7 +552,7 @@ func Validate(request Message, replies []Message) error {
|
|||
// - netlink has not yet assigned us a PID
|
||||
// - response had no PID, meaning it's from the kernel as a multicast reply
|
||||
if m.Header.PID != request.Header.PID && request.Header.PID != 0 && m.Header.PID != 0 {
|
||||
return errMismatchedPID
|
||||
return newOpError("validate", errMismatchedPID)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -533,7 +565,22 @@ type Config struct {
|
|||
// no multicast group subscriptions will be made.
|
||||
Groups uint32
|
||||
|
||||
// Network namespace the Conn needs to operate in. If set to 0,
|
||||
// no network namespace will be entered.
|
||||
// NetNS specifies the network namespace the Conn will operate in.
|
||||
//
|
||||
// If set (non-zero), Conn will enter the specified network namespace and
|
||||
// an error will occur in Dial if the operation fails.
|
||||
//
|
||||
// If not set (zero), a best-effort attempt will be made to enter the
|
||||
// network namespace of the calling thread: this means that any changes made
|
||||
// to the calling thread's network namespace will also be reflected in Conn.
|
||||
// If this operation fails (due to lack of permissions or because network
|
||||
// namespaces are disabled by kernel configuration), Dial will not return
|
||||
// an error, and the Conn will operate in the default network namespace of
|
||||
// the process. This enables non-privileged use of Conn in applications
|
||||
// which do not require elevated privileges.
|
||||
//
|
||||
// Entering a network namespace is a privileged operation (root or
|
||||
// CAP_SYS_ADMIN are required), and most applications should leave this set
|
||||
// to 0.
|
||||
NetNS int
|
||||
}
|
||||
|
|
|
|||
533
vendor/github.com/mdlayher/netlink/conn_linux.go
generated
vendored
533
vendor/github.com/mdlayher/netlink/conn_linux.go
generated
vendored
|
|
@ -3,25 +3,26 @@
|
|||
package netlink
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math"
|
||||
"os"
|
||||
"runtime"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/net/bpf"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
var (
|
||||
errInvalidSockaddr = errors.New("expected unix.SockaddrNetlink but received different unix.Sockaddr")
|
||||
errInvalidFamily = errors.New("received invalid netlink family")
|
||||
)
|
||||
|
||||
var _ Socket = &conn{}
|
||||
|
||||
var _ deadlineSetter = &conn{}
|
||||
|
||||
// A conn is the Linux implementation of a netlink sockets connection.
|
||||
//
|
||||
// All conn methods must wrap system call errors with os.NewSyscallError to
|
||||
// enable more intelligible error messages in OpError.
|
||||
type conn struct {
|
||||
s socket
|
||||
sa *unix.SockaddrNetlink
|
||||
|
|
@ -32,10 +33,15 @@ type socket interface {
|
|||
Bind(sa unix.Sockaddr) error
|
||||
Close() error
|
||||
FD() int
|
||||
File() *os.File
|
||||
Getsockname() (unix.Sockaddr, error)
|
||||
Recvmsg(p, oob []byte, flags int) (n int, oobn int, recvflags int, from unix.Sockaddr, err error)
|
||||
Sendmsg(p, oob []byte, to unix.Sockaddr, flags int) error
|
||||
SetSockopt(level, name int, v unsafe.Pointer, l uint32) error
|
||||
SetDeadline(t time.Time) error
|
||||
SetReadDeadline(t time.Time) error
|
||||
SetWriteDeadline(t time.Time) error
|
||||
SetSockoptSockFprog(level, opt int, fprog *unix.SockFprog) error
|
||||
SetSockoptInt(level, opt, value int) error
|
||||
}
|
||||
|
||||
// dial is the entry point for Dial. dial opens a netlink socket using
|
||||
|
|
@ -56,7 +62,7 @@ func dial(family int, config *Config) (*conn, uint32, error) {
|
|||
}
|
||||
|
||||
if err := sock.Socket(family); err != nil {
|
||||
return nil, 0, err
|
||||
return nil, 0, os.NewSyscallError("socket", err)
|
||||
}
|
||||
|
||||
return bind(sock, config)
|
||||
|
|
@ -79,13 +85,13 @@ func bind(s socket, config *Config) (*conn, uint32, error) {
|
|||
|
||||
if err := s.Bind(addr); err != nil {
|
||||
_ = s.Close()
|
||||
return nil, 0, err
|
||||
return nil, 0, os.NewSyscallError("bind", err)
|
||||
}
|
||||
|
||||
sa, err := s.Getsockname()
|
||||
if err != nil {
|
||||
_ = s.Close()
|
||||
return nil, 0, err
|
||||
return nil, 0, os.NewSyscallError("getsockname", err)
|
||||
}
|
||||
|
||||
pid := sa.(*unix.SockaddrNetlink).Pid
|
||||
|
|
@ -112,7 +118,7 @@ func (c *conn) SendMessages(messages []Message) error {
|
|||
Family: unix.AF_NETLINK,
|
||||
}
|
||||
|
||||
return c.s.Sendmsg(buf, nil, addr, 0)
|
||||
return os.NewSyscallError("sendmsg", c.s.Sendmsg(buf, nil, addr, 0))
|
||||
}
|
||||
|
||||
// Send sends a single Message to netlink.
|
||||
|
|
@ -126,7 +132,7 @@ func (c *conn) Send(m Message) error {
|
|||
Family: unix.AF_NETLINK,
|
||||
}
|
||||
|
||||
return c.s.Sendmsg(b, nil, addr, 0)
|
||||
return os.NewSyscallError("sendmsg", c.s.Sendmsg(b, nil, addr, 0))
|
||||
}
|
||||
|
||||
// Receive receives one or more Messages from netlink.
|
||||
|
|
@ -139,7 +145,7 @@ func (c *conn) Receive() ([]Message, error) {
|
|||
// when PacketInfo ConnOption is true.
|
||||
n, _, _, _, err := c.s.Recvmsg(b, nil, unix.MSG_PEEK)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, os.NewSyscallError("recvmsg", err)
|
||||
}
|
||||
|
||||
// Break when we can read all messages
|
||||
|
|
@ -152,17 +158,9 @@ func (c *conn) Receive() ([]Message, error) {
|
|||
}
|
||||
|
||||
// Read out all available messages
|
||||
n, _, _, from, err := c.s.Recvmsg(b, nil, 0)
|
||||
n, _, _, _, err := c.s.Recvmsg(b, nil, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
addr, ok := from.(*unix.SockaddrNetlink)
|
||||
if !ok {
|
||||
return nil, errInvalidSockaddr
|
||||
}
|
||||
if addr.Family != unix.AF_NETLINK {
|
||||
return nil, errInvalidFamily
|
||||
return nil, os.NewSyscallError("recvmsg", err)
|
||||
}
|
||||
|
||||
n = nlmsgAlign(n)
|
||||
|
|
@ -187,7 +185,7 @@ func (c *conn) Receive() ([]Message, error) {
|
|||
|
||||
// Close closes the connection.
|
||||
func (c *conn) Close() error {
|
||||
return c.s.Close()
|
||||
return os.NewSyscallError("close", c.s.Close())
|
||||
}
|
||||
|
||||
// FD retrieves the file descriptor of the Conn.
|
||||
|
|
@ -195,24 +193,27 @@ func (c *conn) FD() int {
|
|||
return c.s.FD()
|
||||
}
|
||||
|
||||
// File retrieves the *os.File associated with the Conn.
|
||||
func (c *conn) File() *os.File {
|
||||
return c.s.File()
|
||||
}
|
||||
|
||||
// JoinGroup joins a multicast group by ID.
|
||||
func (c *conn) JoinGroup(group uint32) error {
|
||||
return c.s.SetSockopt(
|
||||
return os.NewSyscallError("setsockopt", c.s.SetSockoptInt(
|
||||
unix.SOL_NETLINK,
|
||||
unix.NETLINK_ADD_MEMBERSHIP,
|
||||
unsafe.Pointer(&group),
|
||||
uint32(unsafe.Sizeof(group)),
|
||||
)
|
||||
int(group),
|
||||
))
|
||||
}
|
||||
|
||||
// LeaveGroup leaves a multicast group by ID.
|
||||
func (c *conn) LeaveGroup(group uint32) error {
|
||||
return c.s.SetSockopt(
|
||||
return os.NewSyscallError("setsockopt", c.s.SetSockoptInt(
|
||||
unix.SOL_NETLINK,
|
||||
unix.NETLINK_DROP_MEMBERSHIP,
|
||||
unsafe.Pointer(&group),
|
||||
uint32(unsafe.Sizeof(group)),
|
||||
)
|
||||
int(group),
|
||||
))
|
||||
}
|
||||
|
||||
// SetBPF attaches an assembled BPF program to a conn.
|
||||
|
|
@ -222,25 +223,21 @@ func (c *conn) SetBPF(filter []bpf.RawInstruction) error {
|
|||
Filter: (*unix.SockFilter)(unsafe.Pointer(&filter[0])),
|
||||
}
|
||||
|
||||
return c.s.SetSockopt(
|
||||
return os.NewSyscallError("setsockopt", c.s.SetSockoptSockFprog(
|
||||
unix.SOL_SOCKET,
|
||||
unix.SO_ATTACH_FILTER,
|
||||
unsafe.Pointer(&prog),
|
||||
uint32(unsafe.Sizeof(prog)),
|
||||
)
|
||||
&prog,
|
||||
))
|
||||
}
|
||||
|
||||
// RemoveBPF removes a BPF filter from a conn.
|
||||
func (c *conn) RemoveBPF() error {
|
||||
// dummy is ignored as argument to SO_DETACH_FILTER
|
||||
// but SetSockopt requires it as an argument
|
||||
var dummy uint32
|
||||
return c.s.SetSockopt(
|
||||
// 0 argument is ignored by SO_DETACH_FILTER.
|
||||
return os.NewSyscallError("setsockopt", c.s.SetSockoptInt(
|
||||
unix.SOL_SOCKET,
|
||||
unix.SO_DETACH_FILTER,
|
||||
unsafe.Pointer(&dummy),
|
||||
uint32(unsafe.Sizeof(dummy)),
|
||||
)
|
||||
0,
|
||||
))
|
||||
}
|
||||
|
||||
// SetOption enables or disables a netlink socket option for the Conn.
|
||||
|
|
@ -248,46 +245,51 @@ func (c *conn) SetOption(option ConnOption, enable bool) error {
|
|||
o, ok := linuxOption(option)
|
||||
if !ok {
|
||||
// Return the typical Linux error for an unknown ConnOption.
|
||||
return unix.ENOPROTOOPT
|
||||
return os.NewSyscallError("setsockopt", unix.ENOPROTOOPT)
|
||||
}
|
||||
|
||||
var v uint32
|
||||
var v int
|
||||
if enable {
|
||||
v = 1
|
||||
}
|
||||
|
||||
return c.s.SetSockopt(
|
||||
return os.NewSyscallError("setsockopt", c.s.SetSockoptInt(
|
||||
unix.SOL_NETLINK,
|
||||
o,
|
||||
unsafe.Pointer(&v),
|
||||
uint32(unsafe.Sizeof(v)),
|
||||
)
|
||||
v,
|
||||
))
|
||||
}
|
||||
|
||||
func (c *conn) SetDeadline(t time.Time) error {
|
||||
return c.s.SetDeadline(t)
|
||||
}
|
||||
|
||||
func (c *conn) SetReadDeadline(t time.Time) error {
|
||||
return c.s.SetReadDeadline(t)
|
||||
}
|
||||
|
||||
func (c *conn) SetWriteDeadline(t time.Time) error {
|
||||
return c.s.SetWriteDeadline(t)
|
||||
}
|
||||
|
||||
// SetReadBuffer sets the size of the operating system's receive buffer
|
||||
// associated with the Conn.
|
||||
func (c *conn) SetReadBuffer(bytes int) error {
|
||||
v := uint32(bytes)
|
||||
|
||||
return c.s.SetSockopt(
|
||||
return os.NewSyscallError("setsockopt", c.s.SetSockoptInt(
|
||||
unix.SOL_SOCKET,
|
||||
unix.SO_RCVBUF,
|
||||
unsafe.Pointer(&v),
|
||||
uint32(unsafe.Sizeof(v)),
|
||||
)
|
||||
bytes,
|
||||
))
|
||||
}
|
||||
|
||||
// SetReadBuffer sets the size of the operating system's transmit buffer
|
||||
// associated with the Conn.
|
||||
func (c *conn) SetWriteBuffer(bytes int) error {
|
||||
v := uint32(bytes)
|
||||
|
||||
return c.s.SetSockopt(
|
||||
return os.NewSyscallError("setsockopt", c.s.SetSockoptInt(
|
||||
unix.SOL_SOCKET,
|
||||
unix.SO_SNDBUF,
|
||||
unsafe.Pointer(&v),
|
||||
uint32(unsafe.Sizeof(v)),
|
||||
)
|
||||
bytes,
|
||||
))
|
||||
}
|
||||
|
||||
// linuxOption converts a ConnOption to its Linux value.
|
||||
|
|
@ -303,6 +305,8 @@ func linuxOption(o ConnOption) (int, bool) {
|
|||
return unix.NETLINK_LISTEN_ALL_NSID, true
|
||||
case CapAcknowledge:
|
||||
return unix.NETLINK_CAP_ACK, true
|
||||
case ExtendedAcknowledge:
|
||||
return unix.NETLINK_EXT_ACK, true
|
||||
default:
|
||||
return 0, false
|
||||
}
|
||||
|
|
@ -325,122 +329,88 @@ var _ socket = &sysSocket{}
|
|||
|
||||
// A sysSocket is a socket which uses system calls for socket operations.
|
||||
type sysSocket struct {
|
||||
fd int
|
||||
|
||||
wg *sync.WaitGroup
|
||||
funcC chan<- func()
|
||||
|
||||
mu sync.RWMutex
|
||||
|
||||
done bool
|
||||
doneC chan<- bool
|
||||
mu sync.RWMutex
|
||||
fd *os.File
|
||||
closed bool
|
||||
g *lockedNetNSGoroutine
|
||||
}
|
||||
|
||||
// newSysSocket creates a sysSocket that optionally locks its internal goroutine
|
||||
// to a single thread.
|
||||
func newSysSocket(config *Config) (*sysSocket, error) {
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
|
||||
// This system call loop strategy was inspired by:
|
||||
// https://github.com/golang/go/wiki/LockOSThread. Thanks to squeed on
|
||||
// Gophers Slack for providing this useful link.
|
||||
|
||||
funcC := make(chan func())
|
||||
doneC := make(chan bool)
|
||||
errC := make(chan error)
|
||||
|
||||
go func() {
|
||||
// It is important to lock this goroutine to its OS thread for the duration
|
||||
// of the netlink socket being used, or else the kernel may end up routing
|
||||
// messages to the wrong places.
|
||||
// See: http://lists.infradead.org/pipermail/libnl/2017-February/002293.html.
|
||||
//
|
||||
// The intent is to never unlock the OS thread, so that the thread
|
||||
// will terminate when the goroutine exits starting in Go 1.10:
|
||||
// https://go-review.googlesource.com/c/go/+/46038.
|
||||
//
|
||||
// However, due to recent instability and a potential bad interaction
|
||||
// with the Go runtime for threads which are not unlocked, we have
|
||||
// elected to temporarily unlock the thread when the goroutine terminates:
|
||||
// https://github.com/golang/go/issues/25128#issuecomment-410764489.
|
||||
|
||||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
defer wg.Done()
|
||||
|
||||
// The user requested the Conn to operate in a non-default network namespace.
|
||||
if config.NetNS != 0 {
|
||||
|
||||
// Get the current namespace of the thread the goroutine is locked to.
|
||||
origNetNS, err := getThreadNetNS()
|
||||
if err != nil {
|
||||
errC <- err
|
||||
return
|
||||
}
|
||||
|
||||
// Set the network namespace of the current thread using
|
||||
// the file descriptor provided by the user.
|
||||
err = setThreadNetNS(config.NetNS)
|
||||
if err != nil {
|
||||
errC <- err
|
||||
return
|
||||
}
|
||||
|
||||
// Once the thread's namespace has been successfully manipulated,
|
||||
// make sure we change it back when the goroutine returns.
|
||||
defer setThreadNetNS(origNetNS)
|
||||
}
|
||||
|
||||
// Signal to caller that initialization was successful.
|
||||
errC <- nil
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-doneC:
|
||||
return
|
||||
case f := <-funcC:
|
||||
f()
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// Wait for the goroutine to return err or nil.
|
||||
if err := <-errC; err != nil {
|
||||
// Determine network namespaces using the threadNetNS function.
|
||||
g, err := newLockedNetNSGoroutine(config.NetNS, threadNetNS)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &sysSocket{
|
||||
wg: &wg,
|
||||
funcC: funcC,
|
||||
doneC: doneC,
|
||||
g: g,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// do runs f in a worker goroutine which can be locked to one thread.
|
||||
func (s *sysSocket) do(f func()) error {
|
||||
done := make(chan bool, 1)
|
||||
|
||||
// All operations handled by this function are assumed to only
|
||||
// read from s.done.
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
|
||||
if s.done {
|
||||
s.mu.RUnlock()
|
||||
if s.closed {
|
||||
return syscall.EBADF
|
||||
}
|
||||
|
||||
s.funcC <- func() {
|
||||
f()
|
||||
done <- true
|
||||
}
|
||||
<-done
|
||||
|
||||
s.mu.RUnlock()
|
||||
|
||||
s.g.run(f)
|
||||
return nil
|
||||
}
|
||||
|
||||
// read executes f, a read function, against the associated file descriptor.
|
||||
func (s *sysSocket) read(f func(fd int) bool) error {
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
|
||||
if s.closed {
|
||||
return syscall.EBADF
|
||||
}
|
||||
|
||||
var err error
|
||||
s.g.run(func() {
|
||||
err = fdread(s.fd, f)
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// write executes f, a write function, against the associated file descriptor.
|
||||
func (s *sysSocket) write(f func(fd int) bool) error {
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
|
||||
if s.closed {
|
||||
return syscall.EBADF
|
||||
}
|
||||
|
||||
var err error
|
||||
s.g.run(func() {
|
||||
err = fdwrite(s.fd, f)
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// control executes f, a control function, against the associated file descriptor.
|
||||
func (s *sysSocket) control(f func(fd int)) error {
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
|
||||
if s.closed {
|
||||
return syscall.EBADF
|
||||
}
|
||||
|
||||
var err error
|
||||
s.g.run(func() {
|
||||
err = fdcontrol(s.fd, f)
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *sysSocket) Socket(family int) error {
|
||||
var (
|
||||
fd int
|
||||
|
|
@ -448,11 +418,47 @@ func (s *sysSocket) Socket(family int) error {
|
|||
)
|
||||
|
||||
doErr := s.do(func() {
|
||||
// Mirror what the standard library does when creating file
|
||||
// descriptors: avoid racing a fork/exec with the creation
|
||||
// of new file descriptors, so that child processes do not
|
||||
// inherit netlink socket file descriptors unexpectedly.
|
||||
//
|
||||
// On Linux, SOCK_CLOEXEC was introduced in 2.6.27. OTOH,
|
||||
// Go supports Linux 2.6.23 and above. If we get EINVAL on
|
||||
// the first try, it may be that we are running on a kernel
|
||||
// older than 2.6.27. In that case, take syscall.ForkLock
|
||||
// and try again without SOCK_CLOEXEC.
|
||||
//
|
||||
// SOCK_NONBLOCK was also added in 2.6.27, but we don't
|
||||
// use SOCK_NONBLOCK here for now, not until we remove support
|
||||
// for Go 1.11, since we still support the old blocking file
|
||||
// descriptor behavior.
|
||||
//
|
||||
// For a more thorough explanation, see similar work in the
|
||||
// Go tree: func sysSocket in net/sock_cloexec.go, as well
|
||||
// as the detailed comment in syscall/exec_unix.go.
|
||||
//
|
||||
// TODO(acln): update this to mirror net.sysSocket completely:
|
||||
// use SOCK_NONBLOCK as well, and remove the separate
|
||||
// setBlockingMode step once Go 1.11 support is removed and
|
||||
// we switch to using entirely non-blocking file descriptors.
|
||||
fd, err = unix.Socket(
|
||||
unix.AF_NETLINK,
|
||||
unix.SOCK_RAW,
|
||||
unix.SOCK_RAW|unix.SOCK_CLOEXEC,
|
||||
family,
|
||||
)
|
||||
if err == unix.EINVAL {
|
||||
syscall.ForkLock.RLock()
|
||||
fd, err = unix.Socket(
|
||||
unix.AF_NETLINK,
|
||||
unix.SOCK_RAW,
|
||||
family,
|
||||
)
|
||||
if err == nil {
|
||||
unix.CloseOnExec(fd)
|
||||
}
|
||||
syscall.ForkLock.RUnlock()
|
||||
}
|
||||
})
|
||||
if doErr != nil {
|
||||
return doErr
|
||||
|
|
@ -461,14 +467,24 @@ func (s *sysSocket) Socket(family int) error {
|
|||
return err
|
||||
}
|
||||
|
||||
s.fd = fd
|
||||
if err := setBlockingMode(fd); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// When using Go 1.12+, the setBlockingMode call we just did puts the
|
||||
// file descriptor into non-blocking mode. In that case, os.NewFile
|
||||
// registers the file descriptor with the runtime poller, which is
|
||||
// then used for all subsequent operations.
|
||||
//
|
||||
// See also: https://golang.org/pkg/os/#NewFile
|
||||
s.fd = os.NewFile(uintptr(fd), "netlink")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *sysSocket) Bind(sa unix.Sockaddr) error {
|
||||
var err error
|
||||
doErr := s.do(func() {
|
||||
err = unix.Bind(s.fd, sa)
|
||||
doErr := s.control(func(fd int) {
|
||||
err = unix.Bind(fd, sa)
|
||||
})
|
||||
if doErr != nil {
|
||||
return doErr
|
||||
|
|
@ -478,7 +494,6 @@ func (s *sysSocket) Bind(sa unix.Sockaddr) error {
|
|||
}
|
||||
|
||||
func (s *sysSocket) Close() error {
|
||||
|
||||
// Be sure to acquire a write lock because we need to stop any other
|
||||
// goroutines from sending system call requests after close.
|
||||
// Any invocation of do() after this write lock unlocks is guaranteed
|
||||
|
|
@ -488,19 +503,18 @@ func (s *sysSocket) Close() error {
|
|||
|
||||
// Close the socket from the main thread, this operation has no risk
|
||||
// of routing data to the wrong socket.
|
||||
err := unix.Close(s.fd)
|
||||
s.done = true
|
||||
err := s.fd.Close()
|
||||
s.closed = true
|
||||
|
||||
// Signal the syscall worker to exit, wait for the WaitGroup to join,
|
||||
// and close the job channel only when the worker is guaranteed to have stopped.
|
||||
close(s.doneC)
|
||||
s.wg.Wait()
|
||||
close(s.funcC)
|
||||
// Stop the associated goroutine and wait for it to return.
|
||||
s.g.stop()
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *sysSocket) FD() int { return s.fd }
|
||||
func (s *sysSocket) FD() int { return int(s.fd.Fd()) }
|
||||
|
||||
func (s *sysSocket) File() *os.File { return s.fd }
|
||||
|
||||
func (s *sysSocket) Getsockname() (unix.Sockaddr, error) {
|
||||
var (
|
||||
|
|
@ -508,8 +522,8 @@ func (s *sysSocket) Getsockname() (unix.Sockaddr, error) {
|
|||
err error
|
||||
)
|
||||
|
||||
doErr := s.do(func() {
|
||||
sa, err = unix.Getsockname(s.fd)
|
||||
doErr := s.control(func(fd int) {
|
||||
sa, err = unix.Getsockname(fd)
|
||||
})
|
||||
if doErr != nil {
|
||||
return nil, doErr
|
||||
|
|
@ -525,8 +539,16 @@ func (s *sysSocket) Recvmsg(p, oob []byte, flags int) (int, int, int, unix.Socka
|
|||
err error
|
||||
)
|
||||
|
||||
doErr := s.do(func() {
|
||||
n, oobn, recvflags, from, err = unix.Recvmsg(s.fd, p, oob, flags)
|
||||
doErr := s.read(func(fd int) bool {
|
||||
n, oobn, recvflags, from, err = unix.Recvmsg(fd, p, oob, flags)
|
||||
|
||||
// When the socket is in non-blocking mode, we might see
|
||||
// EAGAIN and end up here. In that case, return false to
|
||||
// let the poller wait for readiness. See the source code
|
||||
// for internal/poll.FD.RawRead for more details.
|
||||
//
|
||||
// If the socket is in blocking mode, EAGAIN should never occur.
|
||||
return err != syscall.EAGAIN
|
||||
})
|
||||
if doErr != nil {
|
||||
return 0, 0, 0, nil, doErr
|
||||
|
|
@ -537,8 +559,11 @@ func (s *sysSocket) Recvmsg(p, oob []byte, flags int) (int, int, int, unix.Socka
|
|||
|
||||
func (s *sysSocket) Sendmsg(p, oob []byte, to unix.Sockaddr, flags int) error {
|
||||
var err error
|
||||
doErr := s.do(func() {
|
||||
err = unix.Sendmsg(s.fd, p, oob, to, flags)
|
||||
doErr := s.write(func(fd int) bool {
|
||||
err = unix.Sendmsg(fd, p, oob, to, flags)
|
||||
|
||||
// Analogous to Recvmsg. See the comments there.
|
||||
return err != syscall.EAGAIN
|
||||
})
|
||||
if doErr != nil {
|
||||
return doErr
|
||||
|
|
@ -547,10 +572,27 @@ func (s *sysSocket) Sendmsg(p, oob []byte, to unix.Sockaddr, flags int) error {
|
|||
return err
|
||||
}
|
||||
|
||||
func (s *sysSocket) SetSockopt(level, name int, v unsafe.Pointer, l uint32) error {
|
||||
func (s *sysSocket) SetDeadline(t time.Time) error {
|
||||
return s.fd.SetDeadline(t)
|
||||
}
|
||||
|
||||
func (s *sysSocket) SetReadDeadline(t time.Time) error {
|
||||
return s.fd.SetReadDeadline(t)
|
||||
}
|
||||
|
||||
func (s *sysSocket) SetWriteDeadline(t time.Time) error {
|
||||
return s.fd.SetWriteDeadline(t)
|
||||
}
|
||||
|
||||
func (s *sysSocket) SetSockoptInt(level, opt, value int) error {
|
||||
// Value must be in range of a C integer.
|
||||
if value < math.MinInt32 || value > math.MaxInt32 {
|
||||
return unix.EINVAL
|
||||
}
|
||||
|
||||
var err error
|
||||
doErr := s.do(func() {
|
||||
err = setsockopt(s.fd, level, name, v, l)
|
||||
doErr := s.control(func(fd int) {
|
||||
err = unix.SetsockoptInt(fd, level, opt, value)
|
||||
})
|
||||
if doErr != nil {
|
||||
return doErr
|
||||
|
|
@ -558,3 +600,142 @@ func (s *sysSocket) SetSockopt(level, name int, v unsafe.Pointer, l uint32) erro
|
|||
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *sysSocket) SetSockoptSockFprog(level, opt int, fprog *unix.SockFprog) error {
|
||||
var err error
|
||||
doErr := s.control(func(fd int) {
|
||||
err = unix.SetsockoptSockFprog(fd, level, opt, fprog)
|
||||
})
|
||||
if doErr != nil {
|
||||
return doErr
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// lockedNetNSGoroutine is a worker goroutine locked to an operating system
|
||||
// thread, optionally configured to run in a non-default network namespace.
|
||||
type lockedNetNSGoroutine struct {
|
||||
wg sync.WaitGroup
|
||||
doneC chan struct{}
|
||||
funcC chan func()
|
||||
}
|
||||
|
||||
// newLockedNetNSGoroutine creates a lockedNetNSGoroutine that will enter the
|
||||
// specified network namespace netNS (by file descriptor), and will use the
|
||||
// getNS function to produce netNS handles.
|
||||
func newLockedNetNSGoroutine(netNS int, getNS func() (*netNS, error)) (*lockedNetNSGoroutine, error) {
|
||||
// Any bare syscall errors (e.g. setns) should be wrapped with
|
||||
// os.NewSyscallError for the remainder of this function.
|
||||
|
||||
callerNS, err := getNS()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer callerNS.Close()
|
||||
|
||||
g := &lockedNetNSGoroutine{
|
||||
doneC: make(chan struct{}),
|
||||
funcC: make(chan func()),
|
||||
}
|
||||
|
||||
errC := make(chan error)
|
||||
g.wg.Add(1)
|
||||
|
||||
go func() {
|
||||
// It is important to lock this goroutine to its OS thread for the duration
|
||||
// of the netlink socket being used, or else the kernel may end up routing
|
||||
// messages to the wrong places.
|
||||
// See: http://lists.infradead.org/pipermail/libnl/2017-February/002293.html.
|
||||
//
|
||||
//
|
||||
// In addition, the OS thread must also remain locked because we attempt
|
||||
// to manipulate the network namespace of the thread within this goroutine.
|
||||
//
|
||||
// The intent is to never unlock the OS thread, so that the thread
|
||||
// will terminate when the goroutine exits starting in Go 1.10:
|
||||
// https://go-review.googlesource.com/c/go/+/46038.
|
||||
//
|
||||
// However, due to recent instability and a potential bad interaction
|
||||
// with the Go runtime for threads which are not unlocked, we have
|
||||
// elected to temporarily unlock the thread when the goroutine terminates:
|
||||
// https://github.com/golang/go/issues/25128#issuecomment-410764489.
|
||||
|
||||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
defer g.wg.Done()
|
||||
|
||||
// Get the current namespace of the thread the goroutine is locked to.
|
||||
threadNS, err := getNS()
|
||||
if err != nil {
|
||||
errC <- err
|
||||
return
|
||||
}
|
||||
defer threadNS.Close()
|
||||
|
||||
// Attempt to set the network namespace of the current thread to either:
|
||||
// - the namespace referred to by the provided file descriptor from config
|
||||
// - the calling thread's namespace
|
||||
//
|
||||
// See the rules specified in the Config.NetNS documentation.
|
||||
explicitNS := true
|
||||
if netNS == 0 {
|
||||
explicitNS = false
|
||||
netNS = int(callerNS.FD())
|
||||
}
|
||||
|
||||
// Only return an error if the network namespace was explicitly
|
||||
// configured; implicit configuration by zero value should be ignored.
|
||||
err = threadNS.Set(netNS)
|
||||
switch {
|
||||
case err != nil && explicitNS:
|
||||
errC <- err
|
||||
return
|
||||
case err == nil:
|
||||
// If the thread's namespace has been successfully manipulated,
|
||||
// make sure we change it back when the goroutine returns.
|
||||
defer threadNS.Restore()
|
||||
default:
|
||||
// We couldn't successfully set the namespace, but the caller didn't
|
||||
// explicitly ask for it to be set either. Continue.
|
||||
}
|
||||
|
||||
// Signal to caller that initialization was successful.
|
||||
errC <- nil
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-g.doneC:
|
||||
return
|
||||
case f := <-g.funcC:
|
||||
f()
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// Wait for the goroutine to return err or nil.
|
||||
if err := <-errC; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return g, nil
|
||||
}
|
||||
|
||||
// stop signals the goroutine to stop and blocks until it does.
|
||||
//
|
||||
// It is invalid to call run concurrently with stop. It is also invalid to
|
||||
// call run after stop has returned.
|
||||
func (g *lockedNetNSGoroutine) stop() {
|
||||
close(g.doneC)
|
||||
g.wg.Wait()
|
||||
}
|
||||
|
||||
// run runs f on the worker goroutine.
|
||||
func (g *lockedNetNSGoroutine) run(f func()) {
|
||||
done := make(chan struct{})
|
||||
g.funcC <- func() {
|
||||
defer close(done)
|
||||
f()
|
||||
}
|
||||
<-done
|
||||
}
|
||||
|
|
|
|||
10
vendor/github.com/mdlayher/netlink/conn_others.go
generated
vendored
10
vendor/github.com/mdlayher/netlink/conn_others.go
generated
vendored
|
|
@ -7,12 +7,10 @@ import (
|
|||
"runtime"
|
||||
)
|
||||
|
||||
var (
|
||||
// errUnimplemented is returned by all functions on platforms that
|
||||
// cannot make use of netlink sockets.
|
||||
errUnimplemented = fmt.Errorf("netlink: not implemented on %s/%s",
|
||||
runtime.GOOS, runtime.GOARCH)
|
||||
)
|
||||
// errUnimplemented is returned by all functions on platforms that
|
||||
// cannot make use of netlink sockets.
|
||||
var errUnimplemented = fmt.Errorf("netlink: not implemented on %s/%s",
|
||||
runtime.GOOS, runtime.GOARCH)
|
||||
|
||||
var _ Socket = &conn{}
|
||||
|
||||
|
|
|
|||
6
vendor/github.com/mdlayher/netlink/debug.go
generated
vendored
6
vendor/github.com/mdlayher/netlink/debug.go
generated
vendored
|
|
@ -8,10 +8,8 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
// Arguments used to create a debugger.
|
||||
debugArgs []string
|
||||
)
|
||||
// Arguments used to create a debugger.
|
||||
var debugArgs []string
|
||||
|
||||
func init() {
|
||||
// Is netlink debugging enabled?
|
||||
|
|
|
|||
14
vendor/github.com/mdlayher/netlink/doc.go
generated
vendored
14
vendor/github.com/mdlayher/netlink/doc.go
generated
vendored
|
|
@ -1,5 +1,17 @@
|
|||
// Package netlink provides low-level access to Linux netlink sockets.
|
||||
//
|
||||
// If you have any questions or you'd like some guidance, please join us on
|
||||
// Gophers Slack (https://invite.slack.golangbridge.org) in the #networking
|
||||
// channel!
|
||||
//
|
||||
//
|
||||
// Network namespaces
|
||||
//
|
||||
// This package is aware of Linux network namespaces, and can enter different
|
||||
// network namespaces either implicitly or explicitly, depending on
|
||||
// configuration. The Config structure passed to Dial to create a Conn controls
|
||||
// these behaviors. See the documentation of Config.NetNS for details.
|
||||
//
|
||||
//
|
||||
// Debugging
|
||||
//
|
||||
|
|
@ -20,3 +32,5 @@
|
|||
//
|
||||
// level=N: specify the debugging level (only "1" is currently supported)
|
||||
package netlink
|
||||
|
||||
//go:generate dot netlink.dot -T svg -o netlink.svg
|
||||
|
|
|
|||
119
vendor/github.com/mdlayher/netlink/errors.go
generated
vendored
Normal file
119
vendor/github.com/mdlayher/netlink/errors.go
generated
vendored
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
package netlink
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
)
|
||||
|
||||
// Error messages which can be returned by Validate.
|
||||
var (
|
||||
errMismatchedSequence = errors.New("mismatched sequence in netlink reply")
|
||||
errMismatchedPID = errors.New("mismatched PID in netlink reply")
|
||||
errShortErrorMessage = errors.New("not enough data for netlink error code")
|
||||
)
|
||||
|
||||
// Errors which can be returned by a Socket that does not implement
|
||||
// all exposed methods of Conn.
|
||||
|
||||
var errNotSupported = errors.New("operation not supported")
|
||||
|
||||
// notSupported provides a concise constructor for "not supported" errors.
|
||||
func notSupported(op string) error {
|
||||
return newOpError(op, errNotSupported)
|
||||
}
|
||||
|
||||
// IsNotExist determines if an error is produced as the result of querying some
|
||||
// file, object, resource, etc. which does not exist. Users of this package
|
||||
// should always use netlink.IsNotExist, rather than os.IsNotExist, when
|
||||
// checking for specific netlink-related errors.
|
||||
//
|
||||
// Errors types created by this package, such as OpError, can be used with
|
||||
// IsNotExist, but this function also defers to the behavior of os.IsNotExist
|
||||
// for unrecognized error types.
|
||||
func IsNotExist(err error) bool {
|
||||
switch err := err.(type) {
|
||||
case *OpError:
|
||||
// TODO(mdlayher): more error handling logic?
|
||||
|
||||
// Unwrap the inner error and use the stdlib's logic.
|
||||
return os.IsNotExist(err.Err)
|
||||
default:
|
||||
return os.IsNotExist(err)
|
||||
}
|
||||
}
|
||||
|
||||
var _ error = &OpError{}
|
||||
var _ net.Error = &OpError{}
|
||||
|
||||
// An OpError is an error produced as the result of a failed netlink operation.
|
||||
type OpError struct {
|
||||
// Op is the operation which caused this OpError, such as "send"
|
||||
// or "receive".
|
||||
Op string
|
||||
|
||||
// Err is the underlying error which caused this OpError.
|
||||
//
|
||||
// If Err was produced by a system call error, Err will be of type
|
||||
// *os.SyscallError. If Err was produced by an error code in a netlink
|
||||
// message, Err will contain a raw error value type such as a unix.Errno.
|
||||
//
|
||||
// Most callers should inspect Err using a helper such as IsNotExist.
|
||||
Err error
|
||||
}
|
||||
|
||||
// newOpError is a small wrapper for creating an OpError. As a convenience, it
|
||||
// returns nil if the input err is nil: akin to os.NewSyscallError.
|
||||
func newOpError(op string, err error) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &OpError{
|
||||
Op: op,
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
|
||||
func (e *OpError) Error() string {
|
||||
if e == nil {
|
||||
return "<nil>"
|
||||
}
|
||||
|
||||
return fmt.Sprintf("netlink %s: %v", e.Op, e.Err)
|
||||
}
|
||||
|
||||
// Portions of this code taken from the Go standard library:
|
||||
//
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
type timeout interface {
|
||||
Timeout() bool
|
||||
}
|
||||
|
||||
// Timeout reports whether the error was caused by an I/O timeout.
|
||||
func (e *OpError) Timeout() bool {
|
||||
if ne, ok := e.Err.(*os.SyscallError); ok {
|
||||
t, ok := ne.Err.(timeout)
|
||||
return ok && t.Timeout()
|
||||
}
|
||||
t, ok := e.Err.(timeout)
|
||||
return ok && t.Timeout()
|
||||
}
|
||||
|
||||
type temporary interface {
|
||||
Temporary() bool
|
||||
}
|
||||
|
||||
// Temporary reports whether an operation may succeed if retried.
|
||||
func (e *OpError) Temporary() bool {
|
||||
if ne, ok := e.Err.(*os.SyscallError); ok {
|
||||
t, ok := ne.Err.(temporary)
|
||||
return ok && t.Temporary()
|
||||
}
|
||||
t, ok := e.Err.(temporary)
|
||||
return ok && t.Temporary()
|
||||
}
|
||||
44
vendor/github.com/mdlayher/netlink/fdcall_gteq_1.12.go
generated
vendored
Normal file
44
vendor/github.com/mdlayher/netlink/fdcall_gteq_1.12.go
generated
vendored
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
//+build go1.12,linux
|
||||
|
||||
package netlink
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// setBlockingMode puts the file descriptor into non-blocking mode.
|
||||
func setBlockingMode(sysfd int) error {
|
||||
return unix.SetNonblock(sysfd, true)
|
||||
}
|
||||
|
||||
func fdread(fd *os.File, f func(int) (done bool)) error {
|
||||
rc, err := fd.SyscallConn()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return rc.Read(func(sysfd uintptr) bool {
|
||||
return f(int(sysfd))
|
||||
})
|
||||
}
|
||||
|
||||
func fdwrite(fd *os.File, f func(int) (done bool)) error {
|
||||
rc, err := fd.SyscallConn()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return rc.Write(func(sysfd uintptr) bool {
|
||||
return f(int(sysfd))
|
||||
})
|
||||
}
|
||||
|
||||
func fdcontrol(fd *os.File, f func(int)) error {
|
||||
rc, err := fd.SyscallConn()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return rc.Control(func(sysfd uintptr) {
|
||||
f(int(sysfd))
|
||||
})
|
||||
}
|
||||
29
vendor/github.com/mdlayher/netlink/fdcall_lt_1.12.go
generated
vendored
Normal file
29
vendor/github.com/mdlayher/netlink/fdcall_lt_1.12.go
generated
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
//+build !go1.12,linux
|
||||
|
||||
package netlink
|
||||
|
||||
import "os"
|
||||
|
||||
// setBlockingMode exists for compatibility reasons: prior to Go 1.12,
|
||||
// package netlink used blocking file descriptors, and did not support
|
||||
// deadlines. This variant of setBlockingMode, which does nothing (i.e.
|
||||
// it leaves the file descriptor in blocking mode), maintains compatibility
|
||||
// for users up to and including Go 1.11.
|
||||
func setBlockingMode(sysfd int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func fdread(fd *os.File, f func(int) (done bool)) error {
|
||||
f(int(fd.Fd()))
|
||||
return nil
|
||||
}
|
||||
|
||||
func fdwrite(fd *os.File, f func(int) (done bool)) error {
|
||||
f(int(fd.Fd()))
|
||||
return nil
|
||||
}
|
||||
|
||||
func fdcontrol(fd *os.File, f func(int)) error {
|
||||
f(int(fd.Fd()))
|
||||
return nil
|
||||
}
|
||||
2
vendor/github.com/mdlayher/netlink/fuzz.go
generated
vendored
2
vendor/github.com/mdlayher/netlink/fuzz.go
generated
vendored
|
|
@ -4,7 +4,7 @@ package netlink
|
|||
|
||||
func Fuzz(data []byte) int {
|
||||
return fuzzAttributes(data)
|
||||
//return fuzzMessage(data)
|
||||
// return fuzzMessage(data)
|
||||
}
|
||||
|
||||
func fuzzAttributes(data []byte) int {
|
||||
|
|
|
|||
10
vendor/github.com/mdlayher/netlink/go.mod
generated
vendored
Normal file
10
vendor/github.com/mdlayher/netlink/go.mod
generated
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
module github.com/mdlayher/netlink
|
||||
|
||||
go 1.12
|
||||
|
||||
require (
|
||||
github.com/google/go-cmp v0.3.1
|
||||
github.com/jsimonetti/rtnetlink v0.0.0-20190606172950-9527aa82566a
|
||||
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297
|
||||
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456
|
||||
)
|
||||
16
vendor/github.com/mdlayher/netlink/go.sum
generated
vendored
Normal file
16
vendor/github.com/mdlayher/netlink/go.sum
generated
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/jsimonetti/rtnetlink v0.0.0-20190606172950-9527aa82566a h1:84IpUNXj4mCR9CuCEvSiCArMbzr/TMbuPIadKDwypkI=
|
||||
github.com/jsimonetti/rtnetlink v0.0.0-20190606172950-9527aa82566a/go.mod h1:Oz+70psSo5OFh8DBl0Zv2ACw7Esh6pPUphlvZG9x7uw=
|
||||
github.com/mdlayher/netlink v0.0.0-20190409211403-11939a169225/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 h1:k7pJ2yAPLPgbskkFdhRCsA77k2fySZ1zf2zCjvQCiIM=
|
||||
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190411185658-b44545bcd369/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456 h1:ng0gs1AKnRRuEMZoTLLlbOd+C17zUDepwGQBb/n+JVg=
|
||||
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
112
vendor/github.com/mdlayher/netlink/message.go
generated
vendored
112
vendor/github.com/mdlayher/netlink/message.go
generated
vendored
|
|
@ -21,61 +21,56 @@ type HeaderFlags uint16
|
|||
const (
|
||||
// General netlink communication flags.
|
||||
|
||||
// HeaderFlagsRequest indicates a request to netlink.
|
||||
HeaderFlagsRequest HeaderFlags = 1
|
||||
// Request indicates a request to netlink.
|
||||
Request HeaderFlags = 1
|
||||
|
||||
// HeaderFlagsMulti indicates a multi-part message, terminated
|
||||
// by HeaderTypeDone on the last message.
|
||||
HeaderFlagsMulti HeaderFlags = 2
|
||||
// Multi indicates a multi-part message, terminated by Done on the
|
||||
// last message.
|
||||
Multi HeaderFlags = 2
|
||||
|
||||
// HeaderFlagsAcknowledge requests that netlink reply with
|
||||
// an acknowledgement using HeaderTypeError and, if needed,
|
||||
// an error code.
|
||||
HeaderFlagsAcknowledge HeaderFlags = 4
|
||||
// Acknowledge requests that netlink reply with an acknowledgement
|
||||
// using Error and, if needed, an error code.
|
||||
Acknowledge HeaderFlags = 4
|
||||
|
||||
// HeaderFlagsEcho requests that netlink echo this request
|
||||
// back to the sender.
|
||||
HeaderFlagsEcho HeaderFlags = 8
|
||||
// Echo requests that netlink echo this request back to the sender.
|
||||
Echo HeaderFlags = 8
|
||||
|
||||
// HeaderFlagsDumpInterrupted indicates that a dump was
|
||||
// inconsistent due to a sequence change.
|
||||
HeaderFlagsDumpInterrupted HeaderFlags = 16
|
||||
// DumpInterrupted indicates that a dump was inconsistent due to a
|
||||
// sequence change.
|
||||
DumpInterrupted HeaderFlags = 16
|
||||
|
||||
// HeaderFlagsDumpFiltered indicates that a dump was filtered
|
||||
// as requested.
|
||||
HeaderFlagsDumpFiltered HeaderFlags = 32
|
||||
// DumpFiltered indicates that a dump was filtered as requested.
|
||||
DumpFiltered HeaderFlags = 32
|
||||
|
||||
// Flags used to retrieve data from netlink.
|
||||
|
||||
// HeaderFlagsRoot requests that netlink return a complete table instead
|
||||
// of a single entry.
|
||||
HeaderFlagsRoot HeaderFlags = 0x100
|
||||
// Root requests that netlink return a complete table instead of a
|
||||
// single entry.
|
||||
Root HeaderFlags = 0x100
|
||||
|
||||
// HeaderFlagsMatch requests that netlink return a list of all matching
|
||||
// entries.
|
||||
HeaderFlagsMatch HeaderFlags = 0x200
|
||||
// Match requests that netlink return a list of all matching entries.
|
||||
Match HeaderFlags = 0x200
|
||||
|
||||
// HeaderFlagsAtomic requests that netlink send an atomic snapshot of
|
||||
// its entries. Requires CAP_NET_ADMIN or an effective UID of 0.
|
||||
HeaderFlagsAtomic HeaderFlags = 0x400
|
||||
// Atomic requests that netlink send an atomic snapshot of its entries.
|
||||
// Requires CAP_NET_ADMIN or an effective UID of 0.
|
||||
Atomic HeaderFlags = 0x400
|
||||
|
||||
// HeaderFlagsDump requests that netlink return a complete list of
|
||||
// all entries.
|
||||
HeaderFlagsDump HeaderFlags = HeaderFlagsRoot | HeaderFlagsMatch
|
||||
// Dump requests that netlink return a complete list of all entries.
|
||||
Dump HeaderFlags = Root | Match
|
||||
|
||||
// Flags used to create objects.
|
||||
|
||||
// HeaderFlagsReplace indicates request replaces an existing matching object.
|
||||
HeaderFlagsReplace HeaderFlags = 0x100
|
||||
// Replace indicates request replaces an existing matching object.
|
||||
Replace HeaderFlags = 0x100
|
||||
|
||||
// HeaderFlagsExcl indicates request does not replace the object if it already exists.
|
||||
HeaderFlagsExcl HeaderFlags = 0x200
|
||||
// Excl indicates request does not replace the object if it already exists.
|
||||
Excl HeaderFlags = 0x200
|
||||
|
||||
// HeaderFlagsCreate indicates request creates an object if it doesn't already exist.
|
||||
HeaderFlagsCreate HeaderFlags = 0x400
|
||||
// Create indicates request creates an object if it doesn't already exist.
|
||||
Create HeaderFlags = 0x400
|
||||
|
||||
// HeaderFlagsAppend indicates request adds to the end of the object list.
|
||||
HeaderFlagsAppend HeaderFlags = 0x800
|
||||
// Append indicates request adds to the end of the object list.
|
||||
Append HeaderFlags = 0x800
|
||||
)
|
||||
|
||||
// String returns the string representation of a HeaderFlags.
|
||||
|
|
@ -123,30 +118,30 @@ func (f HeaderFlags) String() string {
|
|||
type HeaderType uint16
|
||||
|
||||
const (
|
||||
// HeaderTypeNoop indicates that no action was taken.
|
||||
HeaderTypeNoop HeaderType = 0x1
|
||||
// Noop indicates that no action was taken.
|
||||
Noop HeaderType = 0x1
|
||||
|
||||
// HeaderTypeError indicates an error code is present, which is also
|
||||
// used to indicate success when the code is 0.
|
||||
HeaderTypeError HeaderType = 0x2
|
||||
// Error indicates an error code is present, which is also used to indicate
|
||||
// success when the code is 0.
|
||||
Error HeaderType = 0x2
|
||||
|
||||
// HeaderTypeDone indicates the end of a multi-part message.
|
||||
HeaderTypeDone HeaderType = 0x3
|
||||
// Done indicates the end of a multi-part message.
|
||||
Done HeaderType = 0x3
|
||||
|
||||
// HeaderTypeOverrun indicates that data was lost from this message.
|
||||
HeaderTypeOverrun HeaderType = 0x4
|
||||
// Overrun indicates that data was lost from this message.
|
||||
Overrun HeaderType = 0x4
|
||||
)
|
||||
|
||||
// String returns the string representation of a HeaderType.
|
||||
func (t HeaderType) String() string {
|
||||
switch t {
|
||||
case HeaderTypeNoop:
|
||||
case Noop:
|
||||
return "noop"
|
||||
case HeaderTypeError:
|
||||
case Error:
|
||||
return "error"
|
||||
case HeaderTypeDone:
|
||||
case Done:
|
||||
return "done"
|
||||
case HeaderTypeOverrun:
|
||||
case Overrun:
|
||||
return "overrun"
|
||||
default:
|
||||
return fmt.Sprintf("unknown(%d)", t)
|
||||
|
|
@ -231,6 +226,10 @@ func (m *Message) UnmarshalBinary(b []byte) error {
|
|||
|
||||
// checkMessage checks a single Message for netlink errors.
|
||||
func checkMessage(m Message) error {
|
||||
// NB: All non-nil errors returned from this function *must* be of type
|
||||
// OpError in order to maintain the appropriate contract with callers of
|
||||
// this package.
|
||||
|
||||
const success = 0
|
||||
|
||||
// Per libnl documentation, only messages that indicate type error can
|
||||
|
|
@ -242,18 +241,19 @@ func checkMessage(m Message) error {
|
|||
// it is unknown whether this change was correct or not. If you run into
|
||||
// a problem with your application because of this change, please file
|
||||
// an issue.
|
||||
if m.Header.Type != HeaderTypeError {
|
||||
if m.Header.Type != Error {
|
||||
return nil
|
||||
}
|
||||
|
||||
if len(m.Data) < 4 {
|
||||
return errShortErrorMessage
|
||||
return newOpError("receive", errShortErrorMessage)
|
||||
}
|
||||
|
||||
if c := nlenc.Int32(m.Data[0:4]); c != success {
|
||||
// Error code is a negative integer, convert it into
|
||||
// an OS-specific system call error
|
||||
return newError(-1 * int(c))
|
||||
// Error code is a negative integer, convert it into an OS-specific raw
|
||||
// system call error, but do not wrap with os.NewSyscallError to signify
|
||||
// that this error was produced by a netlink message; not a system call.
|
||||
return newOpError("receive", newError(-1*int(c)))
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
|||
86
vendor/github.com/mdlayher/netlink/netlink.dot
generated
vendored
Normal file
86
vendor/github.com/mdlayher/netlink/netlink.dot
generated
vendored
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
digraph {
|
||||
rankdir = LR
|
||||
|
||||
subgraph cluster_netlink {
|
||||
"github.com/mdlayher/netlink" [URL="https://github.com/mdlayher/netlink"]
|
||||
}
|
||||
|
||||
subgraph cluster_connector {
|
||||
label = "NETLINK_CONNECTOR";
|
||||
|
||||
{
|
||||
"github.com/fearful-symmetry/garlic" [URL="https://github.com/fearful-symmetry/garlic"]
|
||||
} -> "github.com/mdlayher/netlink"
|
||||
}
|
||||
|
||||
subgraph cluster_crypto {
|
||||
label = "NETLINK_CRYPTO";
|
||||
|
||||
{
|
||||
"github.com/mdlayher/cryptonl" [URL="https://github.com/mdlayher/cryptonl"]
|
||||
} -> "github.com/mdlayher/netlink"
|
||||
}
|
||||
|
||||
subgraph cluster_generic {
|
||||
label = "NETLINK_GENERIC (genetlink)";
|
||||
"github.com/mdlayher/genetlink" [URL="https://github.com/mdlayher/genetlink"]
|
||||
"github.com/mdlayher/genetlink" -> "github.com/mdlayher/netlink"
|
||||
|
||||
{
|
||||
"github.com/axatrax/l2tp" [URL="https://github.com/axatrax/l2tp"]
|
||||
"github.com/digitalocean/go-openvswitch" [URL="https://github.com/digitalocean/go-openvswitch"]
|
||||
"github.com/mdlayher/devlink" [URL="https://github.com/mdlayher/devlink"]
|
||||
"github.com/mdlayher/quota" [URL="https://github.com/mdlayher/quota"]
|
||||
"github.com/mdlayher/taskstats" [URL="https://github.com/mdlayher/taskstats"]
|
||||
"github.com/mdlayher/wifi" [URL="https://github.com/mdlayher/wifi"]
|
||||
"github.com/Merovius/nbd" [URL="https://github.com/Merovius/nbd"]
|
||||
"github.com/rtr7/router7" [URL="https://github.com/rtr7/router7"]
|
||||
"github.com/u-root/u-bmc" [URL="https://github.com/u-root/u-bmc"]
|
||||
"golang.zx2c4.com/wireguard/wgctrl" [URL="https://golang.zx2c4.com/wireguard/wgctrl"]
|
||||
} -> "github.com/mdlayher/genetlink"
|
||||
}
|
||||
|
||||
subgraph cluster_kobject_uevent {
|
||||
label = "NETLINK_KOBJECT_UEVENT";
|
||||
|
||||
{
|
||||
"github.com/mdlayher/kobject" [URL="https://github.com/mdlayher/kobject"]
|
||||
} -> "github.com/mdlayher/netlink"
|
||||
}
|
||||
|
||||
subgraph cluster_netfilter {
|
||||
label = "NETLINK_NETFILTER (nfnetlink)";
|
||||
|
||||
{
|
||||
"github.com/florianl/go-conntrack" [URL="https://github.com/florianl/go-conntrack"]
|
||||
"github.com/florianl/go-nflog" [URL="https://github.com/florianl/go-nflog"]
|
||||
"github.com/florianl/go-nfqueue" [URL="https://github.com/florianl/go-nfqueue"]
|
||||
"github.com/google/nftables" [URL="https://github.com/google/nftables"]
|
||||
"github.com/ti-mo/netfilter" [URL="https://github.com/ti-mo/netfilter"]
|
||||
} -> "github.com/mdlayher/netlink"
|
||||
|
||||
{
|
||||
"github.com/ti-mo/conntrack" [URL="https://github.com/ti-mo/conntrack"]
|
||||
} -> "github.com/ti-mo/netfilter"
|
||||
}
|
||||
|
||||
subgraph cluster_route {
|
||||
label = "NETLINK_ROUTE (rtnetlink)";
|
||||
|
||||
{
|
||||
"github.com/ema/qdisc" [URL="https://github.com/ema/qdisc"]
|
||||
"github.com/florianl/go-tc" [URL="https://github.com/florianl/go-tc"]
|
||||
"github.com/jsimonetti/rtnetlink" [URL="https://github.com/jsimonetti/rtnetlink"]
|
||||
"gitlab.com/mergetb/tech/rtnl" [URL="https://gitlab.com/mergetb/tech/rtnl"]
|
||||
} -> "github.com/mdlayher/netlink"
|
||||
}
|
||||
|
||||
subgraph cluster_w1 {
|
||||
label = "NETLINK_W1";
|
||||
|
||||
{
|
||||
"github.com/SpComb/go-onewire" [URL="https://github.com/SpComb/go-onewire"]
|
||||
} -> "github.com/mdlayher/netlink"
|
||||
}
|
||||
}
|
||||
|
||||
436
vendor/github.com/mdlayher/netlink/netlink.svg
generated
vendored
Normal file
436
vendor/github.com/mdlayher/netlink/netlink.svg
generated
vendored
Normal file
|
|
@ -0,0 +1,436 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Generated by graphviz version 2.40.1 (20161225.0304)
|
||||
-->
|
||||
<!-- Title: %3 Pages: 1 -->
|
||||
<svg width="928pt" height="1461pt"
|
||||
viewBox="0.00 0.00 928.33 1461.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 1457)">
|
||||
<title>%3</title>
|
||||
<polygon fill="#ffffff" stroke="transparent" points="-4,4 -4,-1457 924.3276,-1457 924.3276,4 -4,4"/>
|
||||
<g id="clust1" class="cluster">
|
||||
<title>cluster_netlink</title>
|
||||
<polygon fill="none" stroke="#000000" points="667.5479,-417 667.5479,-469 912.3276,-469 912.3276,-417 667.5479,-417"/>
|
||||
</g>
|
||||
<g id="clust2" class="cluster">
|
||||
<title>cluster_connector</title>
|
||||
<polygon fill="none" stroke="#000000" points="354.6724,-1370 354.6724,-1445 647.5479,-1445 647.5479,-1370 354.6724,-1370"/>
|
||||
<text text-anchor="middle" x="501.1102" y="-1429.8" font-family="Times,serif" font-size="14.00" fill="#000000">NETLINK_CONNECTOR</text>
|
||||
</g>
|
||||
<g id="clust4" class="cluster">
|
||||
<title>cluster_crypto</title>
|
||||
<polygon fill="none" stroke="#000000" points="374.1707,-1287 374.1707,-1362 628.0496,-1362 628.0496,-1287 374.1707,-1287"/>
|
||||
<text text-anchor="middle" x="501.1102" y="-1346.8" font-family="Times,serif" font-size="14.00" fill="#000000">NETLINK_CRYPTO</text>
|
||||
</g>
|
||||
<g id="clust6" class="cluster">
|
||||
<title>cluster_generic</title>
|
||||
<polygon fill="none" stroke="#000000" points="8,-718 8,-1279 631.2993,-1279 631.2993,-718 8,-718"/>
|
||||
<text text-anchor="middle" x="319.6497" y="-1263.8" font-family="Times,serif" font-size="14.00" fill="#000000">NETLINK_GENERIC (genetlink)</text>
|
||||
</g>
|
||||
<g id="clust8" class="cluster">
|
||||
<title>cluster_kobject_uevent</title>
|
||||
<polygon fill="none" stroke="#000000" points="377.4204,-635 377.4204,-710 624.7999,-710 624.7999,-635 377.4204,-635"/>
|
||||
<text text-anchor="middle" x="501.1102" y="-694.8" font-family="Times,serif" font-size="14.00" fill="#000000">NETLINK_KOBJECT_UEVENT</text>
|
||||
</g>
|
||||
<g id="clust10" class="cluster">
|
||||
<title>cluster_netfilter</title>
|
||||
<polygon fill="none" stroke="#000000" points="35.2976,-336 35.2976,-627 612.451,-627 612.451,-336 35.2976,-336"/>
|
||||
<text text-anchor="middle" x="323.8743" y="-611.8" font-family="Times,serif" font-size="14.00" fill="#000000">NETLINK_NETFILTER (nfnetlink)</text>
|
||||
</g>
|
||||
<g id="clust13" class="cluster">
|
||||
<title>cluster_route</title>
|
||||
<polygon fill="none" stroke="#000000" points="371.5709,-91 371.5709,-328 630.6494,-328 630.6494,-91 371.5709,-91"/>
|
||||
<text text-anchor="middle" x="501.1102" y="-312.8" font-family="Times,serif" font-size="14.00" fill="#000000">NETLINK_ROUTE (rtnetlink)</text>
|
||||
</g>
|
||||
<g id="clust15" class="cluster">
|
||||
<title>cluster_w1</title>
|
||||
<polygon fill="none" stroke="#000000" points="365.7215,-8 365.7215,-83 636.4988,-83 636.4988,-8 365.7215,-8"/>
|
||||
<text text-anchor="middle" x="501.1102" y="-67.8" font-family="Times,serif" font-size="14.00" fill="#000000">NETLINK_W1</text>
|
||||
</g>
|
||||
<!-- github.com/mdlayher/netlink -->
|
||||
<g id="node1" class="node">
|
||||
<title>github.com/mdlayher/netlink</title>
|
||||
<g id="a_node1"><a xlink:href="https://github.com/mdlayher/netlink" xlink:title="github.com/mdlayher/netlink">
|
||||
<ellipse fill="none" stroke="#000000" cx="789.9377" cy="-443" rx="114.2798" ry="18"/>
|
||||
<text text-anchor="middle" x="789.9377" y="-439.3" font-family="Times,serif" font-size="14.00" fill="#000000">github.com/mdlayher/netlink</text>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- github.com/fearful-symmetry/garlic -->
|
||||
<g id="node2" class="node">
|
||||
<title>github.com/fearful-symmetry/garlic</title>
|
||||
<g id="a_node2"><a xlink:href="https://github.com/fearful-symmetry/garlic" xlink:title="github.com/fearful-symmetry/garlic">
|
||||
<ellipse fill="none" stroke="#000000" cx="501.1102" cy="-1396" rx="138.3755" ry="18"/>
|
||||
<text text-anchor="middle" x="501.1102" y="-1392.3" font-family="Times,serif" font-size="14.00" fill="#000000">github.com/fearful-symmetry/garlic</text>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- github.com/fearful-symmetry/garlic->github.com/mdlayher/netlink -->
|
||||
<g id="edge1" class="edge">
|
||||
<title>github.com/fearful-symmetry/garlic->github.com/mdlayher/netlink</title>
|
||||
<path fill="none" stroke="#000000" d="M618.0901,-1386.1685C629.0968,-1381.2937 639.2266,-1374.7394 647.5479,-1366 711.2893,-1299.0557 774.4581,-618.9655 787.4947,-471.2237"/>
|
||||
<polygon fill="#000000" stroke="#000000" points="790.9911,-471.4178 788.3785,-461.1501 784.0178,-470.8059 790.9911,-471.4178"/>
|
||||
</g>
|
||||
<!-- github.com/mdlayher/cryptonl -->
|
||||
<g id="node3" class="node">
|
||||
<title>github.com/mdlayher/cryptonl</title>
|
||||
<g id="a_node3"><a xlink:href="https://github.com/mdlayher/cryptonl" xlink:title="github.com/mdlayher/cryptonl">
|
||||
<ellipse fill="none" stroke="#000000" cx="501.1102" cy="-1313" rx="118.8789" ry="18"/>
|
||||
<text text-anchor="middle" x="501.1102" y="-1309.3" font-family="Times,serif" font-size="14.00" fill="#000000">github.com/mdlayher/cryptonl</text>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- github.com/mdlayher/cryptonl->github.com/mdlayher/netlink -->
|
||||
<g id="edge2" class="edge">
|
||||
<title>github.com/mdlayher/cryptonl->github.com/mdlayher/netlink</title>
|
||||
<path fill="none" stroke="#000000" d="M610.7334,-1305.9481C624.5338,-1300.8942 637.3585,-1293.5434 647.5479,-1283 763.2734,-1163.2529 785.5805,-604.2973 789.275,-471.404"/>
|
||||
<polygon fill="#000000" stroke="#000000" points="792.7785,-471.3145 789.5441,-461.2255 785.7809,-471.1294 792.7785,-471.3145"/>
|
||||
</g>
|
||||
<!-- github.com/mdlayher/genetlink -->
|
||||
<g id="node4" class="node">
|
||||
<title>github.com/mdlayher/genetlink</title>
|
||||
<g id="a_node4"><a xlink:href="https://github.com/mdlayher/genetlink" xlink:title="github.com/mdlayher/genetlink">
|
||||
<ellipse fill="none" stroke="#000000" cx="501.1102" cy="-960" rx="122.3786" ry="18"/>
|
||||
<text text-anchor="middle" x="501.1102" y="-956.3" font-family="Times,serif" font-size="14.00" fill="#000000">github.com/mdlayher/genetlink</text>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- github.com/mdlayher/genetlink->github.com/mdlayher/netlink -->
|
||||
<g id="edge3" class="edge">
|
||||
<title>github.com/mdlayher/genetlink->github.com/mdlayher/netlink</title>
|
||||
<path fill="none" stroke="#000000" d="M512.2824,-941.9846C537.2353,-901.5876 599.1109,-800.521 647.5479,-714 696.8353,-625.9599 751.3273,-519.464 776.1997,-470.3016"/>
|
||||
<polygon fill="#000000" stroke="#000000" points="779.3841,-471.76 780.7689,-461.256 773.136,-468.6038 779.3841,-471.76"/>
|
||||
</g>
|
||||
<!-- github.com/axatrax/l2tp -->
|
||||
<g id="node5" class="node">
|
||||
<title>github.com/axatrax/l2tp</title>
|
||||
<g id="a_node5"><a xlink:href="https://github.com/axatrax/l2tp" xlink:title="github.com/axatrax/l2tp">
|
||||
<ellipse fill="none" stroke="#000000" cx="171.3362" cy="-1230" rx="95.5831" ry="18"/>
|
||||
<text text-anchor="middle" x="171.3362" y="-1226.3" font-family="Times,serif" font-size="14.00" fill="#000000">github.com/axatrax/l2tp</text>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- github.com/axatrax/l2tp->github.com/mdlayher/genetlink -->
|
||||
<g id="edge4" class="edge">
|
||||
<title>github.com/axatrax/l2tp->github.com/mdlayher/genetlink</title>
|
||||
<path fill="none" stroke="#000000" d="M264.3393,-1225.7596C285.9946,-1221.6342 308.121,-1214.6346 326.6724,-1203 411.4328,-1149.8426 467.4112,-1039.0703 489.9239,-987.5067"/>
|
||||
<polygon fill="#000000" stroke="#000000" points="493.2676,-988.589 493.9789,-978.018 486.8307,-985.8382 493.2676,-988.589"/>
|
||||
</g>
|
||||
<!-- github.com/digitalocean/go-openvswitch -->
|
||||
<g id="node6" class="node">
|
||||
<title>github.com/digitalocean/go-openvswitch</title>
|
||||
<g id="a_node6"><a xlink:href="https://github.com/digitalocean/go-openvswitch" xlink:title="github.com/digitalocean/go-openvswitch">
|
||||
<ellipse fill="none" stroke="#000000" cx="171.3362" cy="-1176" rx="155.1726" ry="18"/>
|
||||
<text text-anchor="middle" x="171.3362" y="-1172.3" font-family="Times,serif" font-size="14.00" fill="#000000">github.com/digitalocean/go-openvswitch</text>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- github.com/digitalocean/go-openvswitch->github.com/mdlayher/genetlink -->
|
||||
<g id="edge5" class="edge">
|
||||
<title>github.com/digitalocean/go-openvswitch->github.com/mdlayher/genetlink</title>
|
||||
<path fill="none" stroke="#000000" d="M288.675,-1164.1733C301.9335,-1160.3648 314.894,-1155.4158 326.6724,-1149 399.005,-1109.5999 457.6675,-1028.8489 484.8041,-986.7962"/>
|
||||
<polygon fill="#000000" stroke="#000000" points="487.8588,-988.5148 490.2614,-978.196 481.9483,-984.7643 487.8588,-988.5148"/>
|
||||
</g>
|
||||
<!-- github.com/mdlayher/devlink -->
|
||||
<g id="node7" class="node">
|
||||
<title>github.com/mdlayher/devlink</title>
|
||||
<g id="a_node7"><a xlink:href="https://github.com/mdlayher/devlink" xlink:title="github.com/mdlayher/devlink">
|
||||
<ellipse fill="none" stroke="#000000" cx="171.3362" cy="-1122" rx="116.1796" ry="18"/>
|
||||
<text text-anchor="middle" x="171.3362" y="-1118.3" font-family="Times,serif" font-size="14.00" fill="#000000">github.com/mdlayher/devlink</text>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- github.com/mdlayher/devlink->github.com/mdlayher/genetlink -->
|
||||
<g id="edge6" class="edge">
|
||||
<title>github.com/mdlayher/devlink->github.com/mdlayher/genetlink</title>
|
||||
<path fill="none" stroke="#000000" d="M270.0065,-1112.2812C289.3033,-1108.3328 309.0157,-1102.787 326.6724,-1095 387.0749,-1068.361 445.2293,-1016.3812 476.7727,-985.2696"/>
|
||||
<polygon fill="#000000" stroke="#000000" points="479.6082,-987.3837 484.204,-977.8376 474.6582,-982.4342 479.6082,-987.3837"/>
|
||||
</g>
|
||||
<!-- github.com/mdlayher/quota -->
|
||||
<g id="node8" class="node">
|
||||
<title>github.com/mdlayher/quota</title>
|
||||
<g id="a_node8"><a xlink:href="https://github.com/mdlayher/quota" xlink:title="github.com/mdlayher/quota">
|
||||
<ellipse fill="none" stroke="#000000" cx="171.3362" cy="-1068" rx="109.381" ry="18"/>
|
||||
<text text-anchor="middle" x="171.3362" y="-1064.3" font-family="Times,serif" font-size="14.00" fill="#000000">github.com/mdlayher/quota</text>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- github.com/mdlayher/quota->github.com/mdlayher/genetlink -->
|
||||
<g id="edge7" class="edge">
|
||||
<title>github.com/mdlayher/quota->github.com/mdlayher/genetlink</title>
|
||||
<path fill="none" stroke="#000000" d="M258.1644,-1057.0454C280.7514,-1053.0754 304.8604,-1047.8288 326.6724,-1041 374.644,-1025.9812 426.5199,-1000.6145 461.1179,-982.2644"/>
|
||||
<polygon fill="#000000" stroke="#000000" points="462.802,-985.3329 469.9641,-977.5255 459.4965,-979.1625 462.802,-985.3329"/>
|
||||
</g>
|
||||
<!-- github.com/mdlayher/taskstats -->
|
||||
<g id="node9" class="node">
|
||||
<title>github.com/mdlayher/taskstats</title>
|
||||
<g id="a_node9"><a xlink:href="https://github.com/mdlayher/taskstats" xlink:title="github.com/mdlayher/taskstats">
|
||||
<ellipse fill="none" stroke="#000000" cx="171.3362" cy="-1014" rx="119.6788" ry="18"/>
|
||||
<text text-anchor="middle" x="171.3362" y="-1010.3" font-family="Times,serif" font-size="14.00" fill="#000000">github.com/mdlayher/taskstats</text>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- github.com/mdlayher/taskstats->github.com/mdlayher/genetlink -->
|
||||
<g id="edge8" class="edge">
|
||||
<title>github.com/mdlayher/taskstats->github.com/mdlayher/genetlink</title>
|
||||
<path fill="none" stroke="#000000" d="M252.4304,-1000.721C299.8893,-992.9496 359.9621,-983.1128 409.1751,-975.0542"/>
|
||||
<polygon fill="#000000" stroke="#000000" points="409.8812,-978.4853 419.1842,-973.4153 408.75,-971.5773 409.8812,-978.4853"/>
|
||||
</g>
|
||||
<!-- github.com/mdlayher/wifi -->
|
||||
<g id="node10" class="node">
|
||||
<title>github.com/mdlayher/wifi</title>
|
||||
<g id="a_node10"><a xlink:href="https://github.com/mdlayher/wifi" xlink:title="github.com/mdlayher/wifi">
|
||||
<ellipse fill="none" stroke="#000000" cx="171.3362" cy="-960" rx="103.9815" ry="18"/>
|
||||
<text text-anchor="middle" x="171.3362" y="-956.3" font-family="Times,serif" font-size="14.00" fill="#000000">github.com/mdlayher/wifi</text>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- github.com/mdlayher/wifi->github.com/mdlayher/genetlink -->
|
||||
<g id="edge9" class="edge">
|
||||
<title>github.com/mdlayher/wifi->github.com/mdlayher/genetlink</title>
|
||||
<path fill="none" stroke="#000000" d="M275.6788,-960C305.0928,-960 337.4919,-960 368.3321,-960"/>
|
||||
<polygon fill="#000000" stroke="#000000" points="368.7246,-963.5001 378.7246,-960 368.7245,-956.5001 368.7246,-963.5001"/>
|
||||
</g>
|
||||
<!-- github.com/Merovius/nbd -->
|
||||
<g id="node11" class="node">
|
||||
<title>github.com/Merovius/nbd</title>
|
||||
<g id="a_node11"><a xlink:href="https://github.com/Merovius/nbd" xlink:title="github.com/Merovius/nbd">
|
||||
<ellipse fill="none" stroke="#000000" cx="171.3362" cy="-906" rx="103.1819" ry="18"/>
|
||||
<text text-anchor="middle" x="171.3362" y="-902.3" font-family="Times,serif" font-size="14.00" fill="#000000">github.com/Merovius/nbd</text>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- github.com/Merovius/nbd->github.com/mdlayher/genetlink -->
|
||||
<g id="edge10" class="edge">
|
||||
<title>github.com/Merovius/nbd->github.com/mdlayher/genetlink</title>
|
||||
<path fill="none" stroke="#000000" d="M246.993,-918.3887C295.2157,-926.2851 358.0096,-936.5675 409.1103,-944.9352"/>
|
||||
<polygon fill="#000000" stroke="#000000" points="408.7326,-948.4198 419.1668,-946.5819 409.8638,-941.5119 408.7326,-948.4198"/>
|
||||
</g>
|
||||
<!-- github.com/rtr7/router7 -->
|
||||
<g id="node12" class="node">
|
||||
<title>github.com/rtr7/router7</title>
|
||||
<g id="a_node12"><a xlink:href="https://github.com/rtr7/router7" xlink:title="github.com/rtr7/router7">
|
||||
<ellipse fill="none" stroke="#000000" cx="171.3362" cy="-852" rx="94.4839" ry="18"/>
|
||||
<text text-anchor="middle" x="171.3362" y="-848.3" font-family="Times,serif" font-size="14.00" fill="#000000">github.com/rtr7/router7</text>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- github.com/rtr7/router7->github.com/mdlayher/genetlink -->
|
||||
<g id="edge11" class="edge">
|
||||
<title>github.com/rtr7/router7->github.com/mdlayher/genetlink</title>
|
||||
<path fill="none" stroke="#000000" d="M250.9186,-861.7151C275.5276,-865.812 302.5094,-871.4351 326.6724,-879 374.644,-894.0188 426.5199,-919.3855 461.1179,-937.7356"/>
|
||||
<polygon fill="#000000" stroke="#000000" points="459.4965,-940.8375 469.9641,-942.4745 462.802,-934.6671 459.4965,-940.8375"/>
|
||||
</g>
|
||||
<!-- github.com/u-root/u-bmc -->
|
||||
<g id="node13" class="node">
|
||||
<title>github.com/u-root/u-bmc</title>
|
||||
<g id="a_node13"><a xlink:href="https://github.com/u-root/u-bmc" xlink:title="github.com/u-root/u-bmc">
|
||||
<ellipse fill="none" stroke="#000000" cx="171.3362" cy="-798" rx="100.9827" ry="18"/>
|
||||
<text text-anchor="middle" x="171.3362" y="-794.3" font-family="Times,serif" font-size="14.00" fill="#000000">github.com/u-root/u-bmc</text>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- github.com/u-root/u-bmc->github.com/mdlayher/genetlink -->
|
||||
<g id="edge12" class="edge">
|
||||
<title>github.com/u-root/u-bmc->github.com/mdlayher/genetlink</title>
|
||||
<path fill="none" stroke="#000000" d="M261.4204,-806.0589C283.386,-810.065 306.386,-816.0532 326.6724,-825 387.0749,-851.639 445.2293,-903.6188 476.7727,-934.7304"/>
|
||||
<polygon fill="#000000" stroke="#000000" points="474.6582,-937.5658 484.204,-942.1624 479.6082,-932.6163 474.6582,-937.5658"/>
|
||||
</g>
|
||||
<!-- golang.zx2c4.com/wireguard/wgctrl -->
|
||||
<g id="node14" class="node">
|
||||
<title>golang.zx2c4.com/wireguard/wgctrl</title>
|
||||
<g id="a_node14"><a xlink:href="https://golang.zx2c4.com/wireguard/wgctrl" xlink:title="golang.zx2c4.com/wireguard/wgctrl">
|
||||
<ellipse fill="none" stroke="#000000" cx="171.3362" cy="-744" rx="139.1754" ry="18"/>
|
||||
<text text-anchor="middle" x="171.3362" y="-740.3" font-family="Times,serif" font-size="14.00" fill="#000000">golang.zx2c4.com/wireguard/wgctrl</text>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- golang.zx2c4.com/wireguard/wgctrl->github.com/mdlayher/genetlink -->
|
||||
<g id="edge13" class="edge">
|
||||
<title>golang.zx2c4.com/wireguard/wgctrl->github.com/mdlayher/genetlink</title>
|
||||
<path fill="none" stroke="#000000" d="M284.2004,-754.5868C299.0091,-758.5427 313.5719,-763.864 326.6724,-771 399.005,-810.4001 457.6675,-891.1511 484.8041,-933.2038"/>
|
||||
<polygon fill="#000000" stroke="#000000" points="481.9483,-935.2357 490.2614,-941.804 487.8588,-931.4852 481.9483,-935.2357"/>
|
||||
</g>
|
||||
<!-- github.com/mdlayher/kobject -->
|
||||
<g id="node15" class="node">
|
||||
<title>github.com/mdlayher/kobject</title>
|
||||
<g id="a_node15"><a xlink:href="https://github.com/mdlayher/kobject" xlink:title="github.com/mdlayher/kobject">
|
||||
<ellipse fill="none" stroke="#000000" cx="501.1102" cy="-661" rx="115.8798" ry="18"/>
|
||||
<text text-anchor="middle" x="501.1102" y="-657.3" font-family="Times,serif" font-size="14.00" fill="#000000">github.com/mdlayher/kobject</text>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- github.com/mdlayher/kobject->github.com/mdlayher/netlink -->
|
||||
<g id="edge14" class="edge">
|
||||
<title>github.com/mdlayher/kobject->github.com/mdlayher/netlink</title>
|
||||
<path fill="none" stroke="#000000" d="M598.6533,-651.2474C615.7971,-646.7428 632.8379,-640.2701 647.5479,-631 711.0165,-591.0025 756.5745,-511.9527 777.347,-470.2422"/>
|
||||
<polygon fill="#000000" stroke="#000000" points="780.5136,-471.7338 781.7468,-461.2109 774.2206,-468.668 780.5136,-471.7338"/>
|
||||
</g>
|
||||
<!-- github.com/florianl/go-conntrack -->
|
||||
<g id="node16" class="node">
|
||||
<title>github.com/florianl/go-conntrack</title>
|
||||
<g id="a_node16"><a xlink:href="https://github.com/florianl/go-conntrack" xlink:title="github.com/florianl/go-conntrack">
|
||||
<ellipse fill="none" stroke="#000000" cx="171.3362" cy="-524" rx="128.0773" ry="18"/>
|
||||
<text text-anchor="middle" x="171.3362" y="-520.3" font-family="Times,serif" font-size="14.00" fill="#000000">github.com/florianl/go-conntrack</text>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- github.com/florianl/go-conntrack->github.com/mdlayher/netlink -->
|
||||
<g id="edge15" class="edge">
|
||||
<title>github.com/florianl/go-conntrack->github.com/mdlayher/netlink</title>
|
||||
<path fill="none" stroke="#000000" d="M277.0466,-513.8001C373.7222,-503.9954 520.5725,-487.9044 647.5479,-469 667.216,-466.0718 688.3299,-462.4696 708.1165,-458.8899"/>
|
||||
<polygon fill="#000000" stroke="#000000" points="708.8102,-462.3212 718.0183,-457.0808 707.5521,-455.4352 708.8102,-462.3212"/>
|
||||
</g>
|
||||
<!-- github.com/florianl/go-nflog -->
|
||||
<g id="node17" class="node">
|
||||
<title>github.com/florianl/go-nflog</title>
|
||||
<g id="a_node17"><a xlink:href="https://github.com/florianl/go-nflog" xlink:title="github.com/florianl/go-nflog">
|
||||
<ellipse fill="none" stroke="#000000" cx="171.3362" cy="-470" rx="112.3801" ry="18"/>
|
||||
<text text-anchor="middle" x="171.3362" y="-466.3" font-family="Times,serif" font-size="14.00" fill="#000000">github.com/florianl/go-nflog</text>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- github.com/florianl/go-nflog->github.com/mdlayher/netlink -->
|
||||
<g id="edge16" class="edge">
|
||||
<title>github.com/florianl/go-nflog->github.com/mdlayher/netlink</title>
|
||||
<path fill="none" stroke="#000000" d="M280.1508,-465.2506C389.1846,-460.4916 556.624,-453.1834 669.5731,-448.2535"/>
|
||||
<polygon fill="#000000" stroke="#000000" points="669.81,-451.7466 679.6479,-447.8138 669.5047,-444.7533 669.81,-451.7466"/>
|
||||
</g>
|
||||
<!-- github.com/florianl/go-nfqueue -->
|
||||
<g id="node18" class="node">
|
||||
<title>github.com/florianl/go-nfqueue</title>
|
||||
<g id="a_node18"><a xlink:href="https://github.com/florianl/go-nfqueue" xlink:title="github.com/florianl/go-nfqueue">
|
||||
<ellipse fill="none" stroke="#000000" cx="171.3362" cy="-416" rx="122.3786" ry="18"/>
|
||||
<text text-anchor="middle" x="171.3362" y="-412.3" font-family="Times,serif" font-size="14.00" fill="#000000">github.com/florianl/go-nfqueue</text>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- github.com/florianl/go-nfqueue->github.com/mdlayher/netlink -->
|
||||
<g id="edge17" class="edge">
|
||||
<title>github.com/florianl/go-nfqueue->github.com/mdlayher/netlink</title>
|
||||
<path fill="none" stroke="#000000" d="M288.7819,-421.1261C397.8587,-425.887 559.5469,-432.9442 669.5556,-437.7457"/>
|
||||
<polygon fill="#000000" stroke="#000000" points="669.5611,-441.2492 679.7043,-438.1887 669.8664,-434.2558 669.5611,-441.2492"/>
|
||||
</g>
|
||||
<!-- github.com/google/nftables -->
|
||||
<g id="node19" class="node">
|
||||
<title>github.com/google/nftables</title>
|
||||
<g id="a_node19"><a xlink:href="https://github.com/google/nftables" xlink:title="github.com/google/nftables">
|
||||
<ellipse fill="none" stroke="#000000" cx="171.3362" cy="-362" rx="107.781" ry="18"/>
|
||||
<text text-anchor="middle" x="171.3362" y="-358.3" font-family="Times,serif" font-size="14.00" fill="#000000">github.com/google/nftables</text>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- github.com/google/nftables->github.com/mdlayher/netlink -->
|
||||
<g id="edge18" class="edge">
|
||||
<title>github.com/google/nftables->github.com/mdlayher/netlink</title>
|
||||
<path fill="none" stroke="#000000" d="M261.4388,-371.9156C357.3042,-382.7128 513.3379,-400.995 647.5479,-420 664.9576,-422.4653 683.5294,-425.3087 701.3161,-428.1371"/>
|
||||
<polygon fill="#000000" stroke="#000000" points="701.2554,-431.6719 711.6832,-429.7978 702.3627,-424.7601 701.2554,-431.6719"/>
|
||||
</g>
|
||||
<!-- github.com/ti-mo/netfilter -->
|
||||
<g id="node20" class="node">
|
||||
<title>github.com/ti-mo/netfilter</title>
|
||||
<g id="a_node20"><a xlink:href="https://github.com/ti-mo/netfilter" xlink:title="github.com/ti-mo/netfilter">
|
||||
<ellipse fill="none" stroke="#000000" cx="501.1102" cy="-572" rx="103.1819" ry="18"/>
|
||||
<text text-anchor="middle" x="501.1102" y="-568.3" font-family="Times,serif" font-size="14.00" fill="#000000">github.com/ti-mo/netfilter</text>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- github.com/ti-mo/netfilter->github.com/mdlayher/netlink -->
|
||||
<g id="edge19" class="edge">
|
||||
<title>github.com/ti-mo/netfilter->github.com/mdlayher/netlink</title>
|
||||
<path fill="none" stroke="#000000" d="M564.7651,-557.7322C590.9674,-550.8436 621.2746,-541.5409 647.5479,-530 687.2088,-512.5784 729.1179,-485.8262 757.1173,-466.5875"/>
|
||||
<polygon fill="#000000" stroke="#000000" points="759.1243,-469.455 765.3424,-460.8767 755.132,-463.7051 759.1243,-469.455"/>
|
||||
</g>
|
||||
<!-- github.com/ti-mo/conntrack -->
|
||||
<g id="node21" class="node">
|
||||
<title>github.com/ti-mo/conntrack</title>
|
||||
<g id="a_node21"><a xlink:href="https://github.com/ti-mo/conntrack" xlink:title="github.com/ti-mo/conntrack">
|
||||
<ellipse fill="none" stroke="#000000" cx="171.3362" cy="-578" rx="110.4804" ry="18"/>
|
||||
<text text-anchor="middle" x="171.3362" y="-574.3" font-family="Times,serif" font-size="14.00" fill="#000000">github.com/ti-mo/conntrack</text>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- github.com/ti-mo/conntrack->github.com/ti-mo/netfilter -->
|
||||
<g id="edge20" class="edge">
|
||||
<title>github.com/ti-mo/conntrack->github.com/ti-mo/netfilter</title>
|
||||
<path fill="none" stroke="#000000" d="M281.1462,-576.0021C315.5084,-575.3769 353.4762,-574.6861 388.0577,-574.0569"/>
|
||||
<polygon fill="#000000" stroke="#000000" points="388.2582,-577.5539 398.1929,-573.8725 388.1308,-570.5551 388.2582,-577.5539"/>
|
||||
</g>
|
||||
<!-- github.com/ema/qdisc -->
|
||||
<g id="node22" class="node">
|
||||
<title>github.com/ema/qdisc</title>
|
||||
<g id="a_node22"><a xlink:href="https://github.com/ema/qdisc" xlink:title="github.com/ema/qdisc">
|
||||
<ellipse fill="none" stroke="#000000" cx="501.1102" cy="-279" rx="89.8845" ry="18"/>
|
||||
<text text-anchor="middle" x="501.1102" y="-275.3" font-family="Times,serif" font-size="14.00" fill="#000000">github.com/ema/qdisc</text>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- github.com/ema/qdisc->github.com/mdlayher/netlink -->
|
||||
<g id="edge21" class="edge">
|
||||
<title>github.com/ema/qdisc->github.com/mdlayher/netlink</title>
|
||||
<path fill="none" stroke="#000000" d="M553.6635,-293.5936C582.3585,-302.6386 617.9653,-315.6578 647.5479,-332 691.4973,-356.2788 736.197,-393.6346 763.5001,-418.1958"/>
|
||||
<polygon fill="#000000" stroke="#000000" points="761.3065,-420.9318 771.0595,-425.0704 766.0161,-415.753 761.3065,-420.9318"/>
|
||||
</g>
|
||||
<!-- github.com/florianl/go-tc -->
|
||||
<g id="node23" class="node">
|
||||
<title>github.com/florianl/go-tc</title>
|
||||
<g id="a_node23"><a xlink:href="https://github.com/florianl/go-tc" xlink:title="github.com/florianl/go-tc">
|
||||
<ellipse fill="none" stroke="#000000" cx="501.1102" cy="-225" rx="100.1823" ry="18"/>
|
||||
<text text-anchor="middle" x="501.1102" y="-221.3" font-family="Times,serif" font-size="14.00" fill="#000000">github.com/florianl/go-tc</text>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- github.com/florianl/go-tc->github.com/mdlayher/netlink -->
|
||||
<g id="edge22" class="edge">
|
||||
<title>github.com/florianl/go-tc->github.com/mdlayher/netlink</title>
|
||||
<path fill="none" stroke="#000000" d="M594.8153,-231.5626C613.2418,-235.7365 631.7408,-242.172 647.5479,-252 712.2318,-292.2171 757.5371,-373.4108 777.8719,-415.8163"/>
|
||||
<polygon fill="#000000" stroke="#000000" points="774.7542,-417.4118 782.1666,-424.982 781.0929,-414.4417 774.7542,-417.4118"/>
|
||||
</g>
|
||||
<!-- github.com/jsimonetti/rtnetlink -->
|
||||
<g id="node24" class="node">
|
||||
<title>github.com/jsimonetti/rtnetlink</title>
|
||||
<g id="a_node24"><a xlink:href="https://github.com/jsimonetti/rtnetlink" xlink:title="github.com/jsimonetti/rtnetlink">
|
||||
<ellipse fill="none" stroke="#000000" cx="501.1102" cy="-171" rx="121.5784" ry="18"/>
|
||||
<text text-anchor="middle" x="501.1102" y="-167.3" font-family="Times,serif" font-size="14.00" fill="#000000">github.com/jsimonetti/rtnetlink</text>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- github.com/jsimonetti/rtnetlink->github.com/mdlayher/netlink -->
|
||||
<g id="edge23" class="edge">
|
||||
<title>github.com/jsimonetti/rtnetlink->github.com/mdlayher/netlink</title>
|
||||
<path fill="none" stroke="#000000" d="M608.2934,-179.5458C622.2871,-183.7949 635.8152,-189.7416 647.5479,-198 724.8917,-252.4412 766.3728,-363.2908 782.2353,-415.1194"/>
|
||||
<polygon fill="#000000" stroke="#000000" points="778.9529,-416.3615 785.1523,-424.9532 785.6639,-414.3707 778.9529,-416.3615"/>
|
||||
</g>
|
||||
<!-- gitlab.com/mergetb/tech/rtnl -->
|
||||
<g id="node25" class="node">
|
||||
<title>gitlab.com/mergetb/tech/rtnl</title>
|
||||
<g id="a_node25"><a xlink:href="https://gitlab.com/mergetb/tech/rtnl" xlink:title="gitlab.com/mergetb/tech/rtnl">
|
||||
<ellipse fill="none" stroke="#000000" cx="501.1102" cy="-117" rx="112.3801" ry="18"/>
|
||||
<text text-anchor="middle" x="501.1102" y="-113.3" font-family="Times,serif" font-size="14.00" fill="#000000">gitlab.com/mergetb/tech/rtnl</text>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- gitlab.com/mergetb/tech/rtnl->github.com/mdlayher/netlink -->
|
||||
<g id="edge24" class="edge">
|
||||
<title>gitlab.com/mergetb/tech/rtnl->github.com/mdlayher/netlink</title>
|
||||
<path fill="none" stroke="#000000" d="M605.9213,-123.7549C620.9013,-128.1694 635.3432,-134.6381 647.5479,-144 738.1381,-213.4898 773.8638,-355.0819 785.3329,-415.1061"/>
|
||||
<polygon fill="#000000" stroke="#000000" points="781.9009,-415.7955 787.1431,-425.0025 788.7866,-414.536 781.9009,-415.7955"/>
|
||||
</g>
|
||||
<!-- github.com/SpComb/go-onewire -->
|
||||
<g id="node26" class="node">
|
||||
<title>github.com/SpComb/go-onewire</title>
|
||||
<g id="a_node26"><a xlink:href="https://github.com/SpComb/go-onewire" xlink:title="github.com/SpComb/go-onewire">
|
||||
<ellipse fill="none" stroke="#000000" cx="501.1102" cy="-34" rx="127.2775" ry="18"/>
|
||||
<text text-anchor="middle" x="501.1102" y="-30.3" font-family="Times,serif" font-size="14.00" fill="#000000">github.com/SpComb/go-onewire</text>
|
||||
</a>
|
||||
</g>
|
||||
</g>
|
||||
<!-- github.com/SpComb/go-onewire->github.com/mdlayher/netlink -->
|
||||
<g id="edge25" class="edge">
|
||||
<title>github.com/SpComb/go-onewire->github.com/mdlayher/netlink</title>
|
||||
<path fill="none" stroke="#000000" d="M577.4569,-48.4733C602.3155,-56.3703 628.4063,-68.484 647.5479,-87 744.3092,-180.5992 777.0533,-348.493 786.5385,-414.8793"/>
|
||||
<polygon fill="#000000" stroke="#000000" points="783.0981,-415.5551 787.9134,-424.9924 790.0343,-414.612 783.0981,-415.5551"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 27 KiB |
92
vendor/github.com/mdlayher/netlink/netns_linux.go
generated
vendored
92
vendor/github.com/mdlayher/netlink/netns_linux.go
generated
vendored
|
|
@ -3,25 +3,91 @@
|
|||
package netlink
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// getThreadNetNS gets the network namespace file descriptor of the thread the current goroutine
|
||||
// is running on. Make sure to call runtime.LockOSThread() before this so the goroutine does not
|
||||
// get scheduled on another thread in the meantime.
|
||||
func getThreadNetNS() (int, error) {
|
||||
file, err := os.Open(fmt.Sprintf("/proc/%d/task/%d/ns/net", unix.Getpid(), unix.Gettid()))
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
return int(file.Fd()), nil
|
||||
// errNetNSDisabled is returned when network namespaces are unavailable on
|
||||
// a given system.
|
||||
var errNetNSDisabled = errors.New("netlink: network namespaces are not enabled on this system")
|
||||
|
||||
// A netNS is a handle that can manipulate network namespaces.
|
||||
//
|
||||
// Operations performed on a netNS must use runtime.LockOSThread before
|
||||
// manipulating any network namespaces.
|
||||
type netNS struct {
|
||||
// The handle to a network namespace.
|
||||
f *os.File
|
||||
|
||||
// Indicates if network namespaces are disabled on this system, and thus
|
||||
// operations should become a no-op or return errors.
|
||||
disabled bool
|
||||
}
|
||||
|
||||
// setThreadNetNS sets the network namespace of the thread of the current goroutine to
|
||||
// the namespace described by the user-provided file descriptor.
|
||||
func setThreadNetNS(fd int) error {
|
||||
return unix.Setns(fd, unix.CLONE_NEWNET)
|
||||
// threadNetNS constructs a netNS using the network namespace of the calling
|
||||
// thread. If the namespace is not the default namespace, runtime.LockOSThread
|
||||
// should be invoked first.
|
||||
func threadNetNS() (*netNS, error) {
|
||||
return fileNetNS(fmt.Sprintf("/proc/self/task/%d/ns/net", unix.Gettid()))
|
||||
}
|
||||
|
||||
// fileNetNS opens file and creates a netNS. fileNetNS should only be called
|
||||
// directly in tests.
|
||||
func fileNetNS(file string) (*netNS, error) {
|
||||
f, err := os.Open(file)
|
||||
switch {
|
||||
case err == nil:
|
||||
return &netNS{f: f}, nil
|
||||
case os.IsNotExist(err):
|
||||
// Network namespaces are not enabled on this system. Use this signal
|
||||
// to return errors elsewhere if the caller explicitly asks for a
|
||||
// network namespace to be set.
|
||||
return &netNS{disabled: true}, nil
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Close releases the handle to a network namespace.
|
||||
func (n *netNS) Close() error {
|
||||
return n.do(func() error {
|
||||
return n.f.Close()
|
||||
})
|
||||
}
|
||||
|
||||
// FD returns a file descriptor which represents the network namespace.
|
||||
func (n *netNS) FD() int {
|
||||
if n.disabled {
|
||||
// No reasonable file descriptor value in this case, so specify a
|
||||
// non-existent one.
|
||||
return -1
|
||||
}
|
||||
|
||||
return int(n.f.Fd())
|
||||
}
|
||||
|
||||
// Restore restores the original network namespace for the calling thread.
|
||||
func (n *netNS) Restore() error {
|
||||
return n.do(func() error {
|
||||
return n.Set(n.FD())
|
||||
})
|
||||
}
|
||||
|
||||
// Set sets a new network namespace for the current thread using fd.
|
||||
func (n *netNS) Set(fd int) error {
|
||||
return n.do(func() error {
|
||||
return os.NewSyscallError("setns", unix.Setns(fd, unix.CLONE_NEWNET))
|
||||
})
|
||||
}
|
||||
|
||||
// do runs fn if network namespaces are enabled on this system.
|
||||
func (n *netNS) do(fn func() error) error {
|
||||
if n.disabled {
|
||||
return errNetNSDisabled
|
||||
}
|
||||
|
||||
return fn()
|
||||
}
|
||||
|
|
|
|||
4
vendor/github.com/mdlayher/netlink/nlenc/endian.go
generated
vendored
4
vendor/github.com/mdlayher/netlink/nlenc/endian.go
generated
vendored
|
|
@ -1,8 +1,6 @@
|
|||
package nlenc
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
)
|
||||
import "encoding/binary"
|
||||
|
||||
// NativeEndian returns the native byte order of this system.
|
||||
func NativeEndian() binary.ByteOrder {
|
||||
|
|
|
|||
6
vendor/github.com/mdlayher/netlink/nlenc/string.go
generated
vendored
6
vendor/github.com/mdlayher/netlink/nlenc/string.go
generated
vendored
|
|
@ -10,5 +10,9 @@ func Bytes(s string) []byte {
|
|||
// String returns a string with the contents of b from a null-terminated
|
||||
// byte slice.
|
||||
func String(b []byte) string {
|
||||
return string(bytes.TrimSuffix(b, []byte{0x00}))
|
||||
// If the string has more than one NULL terminator byte, we want to remove
|
||||
// all of them before returning the string to the caller; hence the use of
|
||||
// strings.TrimRight instead of strings.TrimSuffix (which previously only
|
||||
// removed a single NULL).
|
||||
return string(bytes.TrimRight(b, "\x00"))
|
||||
}
|
||||
|
|
|
|||
12
vendor/github.com/mdlayher/netlink/rawconn_gteq_1.12.go
generated
vendored
Normal file
12
vendor/github.com/mdlayher/netlink/rawconn_gteq_1.12.go
generated
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
//+build go1.12
|
||||
|
||||
package netlink
|
||||
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func newRawConn(fd *os.File) (syscall.RawConn, error) {
|
||||
return fd.SyscallConn()
|
||||
}
|
||||
32
vendor/github.com/mdlayher/netlink/rawconn_lt_1.12.go
generated
vendored
Normal file
32
vendor/github.com/mdlayher/netlink/rawconn_lt_1.12.go
generated
vendored
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
//+build !go1.12
|
||||
|
||||
package netlink
|
||||
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func newRawConn(fd *os.File) (syscall.RawConn, error) {
|
||||
return &rawConn{fd: fd.Fd()}, nil
|
||||
}
|
||||
|
||||
var _ syscall.RawConn = &rawConn{}
|
||||
|
||||
// A rawConn is a syscall.RawConn.
|
||||
type rawConn struct {
|
||||
fd uintptr
|
||||
}
|
||||
|
||||
func (rc *rawConn) Control(f func(fd uintptr)) error {
|
||||
f(rc.fd)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rc *rawConn) Read(_ func(fd uintptr) (done bool)) error {
|
||||
return notSupported("syscall-conn-read")
|
||||
}
|
||||
|
||||
func (rc *rawConn) Write(_ func(fd uintptr) (done bool)) error {
|
||||
return notSupported("syscall-conn-write")
|
||||
}
|
||||
27
vendor/github.com/mdlayher/netlink/sockopt_linux.go
generated
vendored
27
vendor/github.com/mdlayher/netlink/sockopt_linux.go
generated
vendored
|
|
@ -1,27 +0,0 @@
|
|||
// +build linux,!386
|
||||
|
||||
package netlink
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// setsockopt provides access to the setsockopt syscall.
|
||||
func setsockopt(fd, level, name int, v unsafe.Pointer, l uint32) error {
|
||||
_, _, errno := unix.Syscall6(
|
||||
unix.SYS_SETSOCKOPT,
|
||||
uintptr(fd),
|
||||
uintptr(level),
|
||||
uintptr(name),
|
||||
uintptr(v),
|
||||
uintptr(l),
|
||||
0,
|
||||
)
|
||||
if errno != 0 {
|
||||
return error(errno)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
36
vendor/github.com/mdlayher/netlink/sockopt_linux_386.go
generated
vendored
36
vendor/github.com/mdlayher/netlink/sockopt_linux_386.go
generated
vendored
|
|
@ -1,36 +0,0 @@
|
|||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build linux,386
|
||||
|
||||
package netlink
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
sysSETSOCKOPT = 0xe
|
||||
)
|
||||
|
||||
func socketcall(call int, a0, a1, a2, a3, a4, a5 uintptr) (int, syscall.Errno)
|
||||
|
||||
// setsockopt provides access to the setsockopt syscall.
|
||||
func setsockopt(fd, level, name int, v unsafe.Pointer, l uint32) error {
|
||||
_, errno := socketcall(
|
||||
sysSETSOCKOPT,
|
||||
uintptr(fd),
|
||||
uintptr(level),
|
||||
uintptr(name),
|
||||
uintptr(v),
|
||||
uintptr(l),
|
||||
0,
|
||||
)
|
||||
if errno != 0 {
|
||||
return error(errno)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
6
vendor/github.com/mdlayher/netlink/sockopt_linux_386.s
generated
vendored
6
vendor/github.com/mdlayher/netlink/sockopt_linux_386.s
generated
vendored
|
|
@ -1,6 +0,0 @@
|
|||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
TEXT ·socketcall(SB),4,$0-36
|
||||
JMP syscall·socketcall(SB)
|
||||
Loading…
Add table
Add a link
Reference in a new issue