├── .gitignore ├── .travis.yml ├── Dockerfile ├── Dockerfile.build.alpine ├── README.md ├── build ├── build_with_docker ├── driver ├── driver.go ├── driver_test.go └── util.go ├── env ├── log └── log.go ├── main.go ├── test └── vendor ├── github.com ├── Sirupsen │ └── logrus │ │ ├── CHANGELOG.md │ │ ├── LICENSE │ │ ├── README.md │ │ ├── alt_exit.go │ │ ├── doc.go │ │ ├── entry.go │ │ ├── exported.go │ │ ├── formatter.go │ │ ├── hooks.go │ │ ├── json_formatter.go │ │ ├── logger.go │ │ ├── logrus.go │ │ ├── terminal_appengine.go │ │ ├── terminal_bsd.go │ │ ├── terminal_linux.go │ │ ├── terminal_notwindows.go │ │ ├── terminal_solaris.go │ │ ├── terminal_windows.go │ │ ├── text_formatter.go │ │ └── writer.go ├── coreos │ ├── go-systemd │ │ ├── LICENSE │ │ ├── activation │ │ │ ├── files.go │ │ │ ├── listeners.go │ │ │ └── packetconns.go │ │ └── util │ │ │ ├── util.go │ │ │ ├── util_cgo.go │ │ │ └── util_stub.go │ └── pkg │ │ ├── LICENSE │ │ ├── NOTICE │ │ └── dlopen │ │ ├── dlopen.go │ │ └── dlopen_example.go ├── docker │ ├── go-connections │ │ ├── LICENSE │ │ └── sockets │ │ │ ├── README.md │ │ │ ├── inmem_socket.go │ │ │ ├── proxy.go │ │ │ ├── sockets.go │ │ │ ├── sockets_unix.go │ │ │ ├── sockets_windows.go │ │ │ ├── tcp_socket.go │ │ │ └── unix_socket.go │ └── go-plugins-helpers │ │ ├── LICENSE │ │ ├── NOTICE │ │ ├── network │ │ ├── README.md │ │ └── api.go │ │ └── sdk │ │ ├── encoder.go │ │ ├── handler.go │ │ ├── tcp_listener.go │ │ ├── unix_listener.go │ │ └── unix_listener_unsupported.go ├── opencontainers │ └── runc │ │ ├── LICENSE │ │ ├── NOTICE │ │ └── libcontainer │ │ └── user │ │ ├── MAINTAINERS │ │ ├── lookup.go │ │ ├── lookup_unix.go │ │ ├── lookup_unsupported.go │ │ └── user.go ├── urfave │ └── cli │ │ ├── CHANGELOG.md │ │ ├── LICENSE │ │ ├── README.md │ │ ├── app.go │ │ ├── appveyor.yml │ │ ├── category.go │ │ ├── cli.go │ │ ├── command.go │ │ ├── context.go │ │ ├── errors.go │ │ ├── flag.go │ │ ├── funcs.go │ │ ├── help.go │ │ └── runtests └── vishvananda │ ├── netlink │ ├── LICENSE │ ├── Makefile │ ├── README.md │ ├── addr.go │ ├── addr_linux.go │ ├── bpf_linux.go │ ├── class.go │ ├── class_linux.go │ ├── filter.go │ ├── filter_linux.go │ ├── handle_linux.go │ ├── link.go │ ├── link_linux.go │ ├── link_tuntap_linux.go │ ├── neigh.go │ ├── neigh_linux.go │ ├── netlink.go │ ├── netlink_linux.go │ ├── netlink_unspecified.go │ ├── nl │ │ ├── addr_linux.go │ │ ├── link_linux.go │ │ ├── nl_linux.go │ │ ├── route_linux.go │ │ ├── syscall.go │ │ ├── tc_linux.go │ │ ├── xfrm_linux.go │ │ ├── xfrm_policy_linux.go │ │ └── xfrm_state_linux.go │ ├── protinfo.go │ ├── protinfo_linux.go │ ├── qdisc.go │ ├── qdisc_linux.go │ ├── route.go │ ├── route_linux.go │ ├── route_unspecified.go │ ├── rule.go │ ├── rule_linux.go │ ├── xfrm.go │ ├── xfrm_policy.go │ ├── xfrm_policy_linux.go │ ├── xfrm_state.go │ └── xfrm_state_linux.go │ └── netns │ ├── LICENSE │ ├── README.md │ ├── netns.go │ ├── netns_linux.go │ └── netns_unspecified.go ├── golang.org └── x │ └── net │ ├── LICENSE │ ├── PATENTS │ └── proxy │ ├── direct.go │ ├── per_host.go │ ├── proxy.go │ └── socks5.go └── vendor.json /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | docker-plugin-hostnic 3 | bin 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | 3 | language: go 4 | 5 | services: 6 | - docker 7 | 8 | go: 9 | - 1.7 10 | before_install: 11 | install: 12 | - bash ./build_with_docker 13 | script: 14 | - bash ./test 15 | after_success: 16 | - docker login -e="$DOCKER_EMAIL" -u="$DOCKER_USERNAME" -p="$DOCKER_PASSWORD"; 17 | - docker build -t qingcloud/docker-plugin-hostnic . 18 | - if [ "$TRAVIS_BRANCH" == "master" ]; then 19 | docker push qingcloud/docker-plugin-hostnic; 20 | else 21 | echo $TRAVIS_BRANCH; 22 | docker tag qingcloud/docker-plugin-hostnic qingcloud/docker-plugin-hostnic:$TRAVIS_BRANCH; 23 | docker push qingcloud/docker-plugin-hostnic:$TRAVIS_BRANCH; 24 | fi 25 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.4 2 | MAINTAINER jolestar 3 | 4 | COPY bin/alpine/docker-plugin-hostnic /usr/bin/ 5 | 6 | VOLUME /run/docker/plugins 7 | VOLUME /etcd/docker/hostnic 8 | 9 | CMD ["/usr/bin/docker-plugin-hostnic"] 10 | -------------------------------------------------------------------------------- /Dockerfile.build.alpine: -------------------------------------------------------------------------------- 1 | FROM golang:1.7.3-alpine 2 | 3 | ENV GOPATH /go 4 | 5 | RUN mkdir -p "$GOPATH/src/" "$GOPATH/bin" && chmod -R 777 "$GOPATH" && \ 6 | mkdir -p /go/src/github.com/yunify/docker-plugin-hostnic 7 | 8 | RUN apk --update add bash git gcc 9 | RUN apk add --update alpine-sdk 10 | RUN apk add --update linux-headers 11 | RUN ln -s /go/src/github.com/yunify/docker-plugin-hostnic /app 12 | 13 | WORKDIR /app 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # docker-plugin-hostnic 2 | 3 | docker-plugin-hostnic is a docker network plugin which can binding a special host nic to a container. 4 | 5 | ## QuickStart 6 | 7 | 1. Make sure you are using Docker 1.9 or later (test with 1.12) 8 | 2. Build docker-plugin-hostnic and run, or directly run docker-plugin-hostnic docker image. 9 | 10 | docker pull qingcloud/docker-plugin-hostnic 11 | 12 | docker run -v /run/docker/plugins:/run/docker/plugins -v /etc/docker/hostnic:/etc/docker/hostnic --network host --privileged qingcloud/docker-plugin-hostnic docker-plugin-hostnic 13 | 14 | 3. Create hostnic network,the subnet and gateway argument should be same as hostnic. 15 | 16 | docker network create -d hostnic --subnet=192.168.1.0/24 --gateway 192.168.1.1 hostnic 17 | 18 | 4. Run a container and binding a special hostnic. Mac-address argument is for identity the hostnic. Please ensure that the ip argument do not conflict with other hostnic. 19 | 20 | docker run -it --ip 192.168.1.5 --mac-address 52:54:0e:e5:00:f7 --network hostnic ubuntu:14.04 bash 21 | 22 | 23 | ## Additional Notes: 24 | 25 | 1. If the ip argument is not passed when running container, docker will assign a ip to the container, so please pass the ip argument and ensure that the ip do not conflict with other hostnic. 26 | 2. Network config will save to /etc/docker/hostnic/config.json,if plugin container removed and create again, network config can recover from the config. 27 | 3. If your host only have one nic, please not use this plugin. If you binding the only one nic to container, your host will lost network. 28 | -------------------------------------------------------------------------------- /build: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | 4 | OUTPUT=${1:-bin/docker-plugin-hostnic} 5 | 6 | echo "Building docker-plugin-hostnic ..." 7 | mkdir -p bin 8 | go build -o $OUTPUT . 9 | -------------------------------------------------------------------------------- /build_with_docker: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source ./env 4 | 5 | echo "Release docker-plugin-hostnic alpine version ..." 6 | mkdir -p bin/alpine 7 | docker build -t docker_plugin_builder -f Dockerfile.build.alpine . 8 | docker run -ti --rm -v $(pwd):/app docker_plugin_builder ./build bin/alpine/docker-plugin-hostnic 9 | 10 | ls -lh bin/* 11 | -------------------------------------------------------------------------------- /driver/driver_test.go: -------------------------------------------------------------------------------- 1 | package driver 2 | 3 | import ( 4 | "fmt" 5 | "github.com/docker/go-plugins-helpers/network" 6 | "github.com/hashicorp/netlink" 7 | "os" 8 | "path" 9 | "testing" 10 | ) 11 | 12 | func TestLink(t *testing.T) { 13 | links, err := netlink.LinkList() 14 | if err != nil { 15 | print(err) 16 | t.Fatal(err) 17 | } 18 | for _, link := range links { 19 | println(fmt.Sprintf("%+v", link)) 20 | } 21 | } 22 | 23 | func TestConfig(t *testing.T) { 24 | os.Remove(path.Join(configDir, "config.json")) 25 | 26 | driver, err := New() 27 | if err != nil { 28 | t.Fatal(err) 29 | } 30 | 31 | if err != nil { 32 | t.Fatal(err) 33 | } 34 | ipv4data := &network.IPAMData{ 35 | Gateway: "192.168.0.1/24", 36 | Pool: "192.168.0.0/24", 37 | AddressSpace: "LocalDefault", 38 | } 39 | err = driver.RegisterNetwork("0", ipv4data) 40 | if err != nil { 41 | t.Fatal(err) 42 | } 43 | 44 | ipv4data1 := &network.IPAMData{ 45 | Gateway: "192.168.1.1/24", 46 | Pool: "192.168.1.0/24", 47 | AddressSpace: "LocalDefault", 48 | } 49 | err = driver.RegisterNetwork("1", ipv4data1) 50 | if err != nil { 51 | t.Fatal(err) 52 | } 53 | 54 | driver.saveConfig() 55 | 56 | driver2, _ := New() 57 | 58 | if len(driver2.networks) != 2 { 59 | t.Fatal("expect networks len is 2") 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /driver/util.go: -------------------------------------------------------------------------------- 1 | package driver 2 | 3 | import ( 4 | "github.com/yunify/docker-plugin-hostnic/log" 5 | "net" 6 | "os" 7 | ) 8 | 9 | func GetInterfaceIPAddr(ifi net.Interface) string { 10 | addrs, err := ifi.Addrs() 11 | if err != nil { 12 | log.Error("Get interface [%+v] addr error: %s", ifi, err.Error()) 13 | return "" 14 | } 15 | for _, addr := range addrs { 16 | if ipnet, ok := addr.(*net.IPNet); ok { 17 | if ipnet.IP.To4() != nil { 18 | return ipnet.String() 19 | } 20 | } 21 | } 22 | return "" 23 | } 24 | 25 | func FileExists(path string) (bool, error) { 26 | _, err := os.Stat(path) 27 | if err == nil { 28 | return true, nil 29 | } 30 | if os.IsNotExist(err) { 31 | return false, nil 32 | } 33 | return true, err 34 | } 35 | -------------------------------------------------------------------------------- /env: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ORG_PATH="github.com/yunify" 4 | REPO_PATH="${ORG_PATH}/docker-plugin-hostnic" 5 | -------------------------------------------------------------------------------- /log/log.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package log provides support for logging to stdout and stderr. 3 | 4 | Log entries will be logged in the following format: 5 | 6 | timestamp hostname tag[pid]: SEVERITY Message 7 | */ 8 | package log 9 | 10 | import ( 11 | "fmt" 12 | "os" 13 | "strings" 14 | "time" 15 | 16 | log "github.com/Sirupsen/logrus" 17 | ) 18 | 19 | type LogFormatter struct { 20 | } 21 | 22 | func (c *LogFormatter) Format(entry *log.Entry) ([]byte, error) { 23 | timestamp := time.Now().Format(time.RFC3339) 24 | hostname, _ := os.Hostname() 25 | return []byte(fmt.Sprintf("%s %s %s[%d]: %s %s\n", timestamp, hostname, tag, os.Getpid(), strings.ToUpper(entry.Level.String()), entry.Message)), nil 26 | } 27 | 28 | // tag represents the application name generating the log message. The tag 29 | // string will appear in all log entires. 30 | var tag string 31 | 32 | func init() { 33 | tag = os.Args[0] 34 | log.SetFormatter(&LogFormatter{}) 35 | } 36 | 37 | // SetTag sets the tag. 38 | func SetTag(t string) { 39 | tag = t 40 | } 41 | 42 | // SetLevel sets the log level. Valid levels are panic, fatal, error, warn, info and debug. 43 | func SetLevel(level string) { 44 | lvl, err := log.ParseLevel(level) 45 | if err != nil { 46 | Fatal(fmt.Sprintf(`not a valid level: "%s"`, level)) 47 | } 48 | log.SetLevel(lvl) 49 | } 50 | 51 | func IsDebugEnable() bool { 52 | return log.GetLevel() >= log.DebugLevel 53 | } 54 | 55 | // Debug logs a message with severity DEBUG. 56 | func Debug(format string, v ...interface{}) { 57 | log.Debug(fmt.Sprintf(format, v...)) 58 | } 59 | 60 | // Error logs a message with severity ERROR. 61 | func Error(format string, v ...interface{}) { 62 | log.Error(fmt.Sprintf(format, v...)) 63 | } 64 | 65 | // Fatal logs a message with severity ERROR followed by a call to os.Exit(). 66 | func Fatal(format string, v ...interface{}) { 67 | log.Fatal(fmt.Sprintf(format, v...)) 68 | } 69 | 70 | // Info logs a message with severity INFO. 71 | func Info(format string, v ...interface{}) { 72 | log.Info(fmt.Sprintf(format, v...)) 73 | } 74 | 75 | // Warning logs a message with severity WARNING. 76 | func Warning(format string, v ...interface{}) { 77 | log.Warning(fmt.Sprintf(format, v...)) 78 | } 79 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/docker/go-plugins-helpers/network" 5 | "github.com/urfave/cli" 6 | "github.com/yunify/docker-plugin-hostnic/driver" 7 | "github.com/yunify/docker-plugin-hostnic/log" 8 | "os" 9 | ) 10 | 11 | const ( 12 | version = "0.1" 13 | ) 14 | 15 | func main() { 16 | 17 | var flagDebug = cli.BoolFlag{ 18 | Name: "debug, d", 19 | Usage: "enable debugging", 20 | } 21 | app := cli.NewApp() 22 | app.Name = "hostnic" 23 | app.Usage = "Docker Host Nic Network Plugin" 24 | app.Version = version 25 | app.Flags = []cli.Flag{ 26 | flagDebug, 27 | } 28 | app.Action = Run 29 | app.Run(os.Args) 30 | } 31 | 32 | // Run initializes the driver 33 | func Run(ctx *cli.Context) { 34 | if ctx.Bool("debug") { 35 | log.SetLevel("debug") 36 | } 37 | log.Info("Run %s", ctx.App.Name) 38 | d, err := driver.New() 39 | if err == nil { 40 | h := network.NewHandler(d) 41 | err = h.ServeUnix("root", "hostnic") 42 | } 43 | if err != nil { 44 | log.Fatal("Run app error: %s", err.Error()) 45 | os.Exit(1) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /test: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | echo "skip test" 4 | -------------------------------------------------------------------------------- /vendor/github.com/Sirupsen/logrus/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 0.10.0 2 | 3 | * feature: Add a test hook (#180) 4 | * feature: `ParseLevel` is now case-insensitive (#326) 5 | * feature: `FieldLogger` interface that generalizes `Logger` and `Entry` (#308) 6 | * performance: avoid re-allocations on `WithFields` (#335) 7 | 8 | # 0.9.0 9 | 10 | * logrus/text_formatter: don't emit empty msg 11 | * logrus/hooks/airbrake: move out of main repository 12 | * logrus/hooks/sentry: move out of main repository 13 | * logrus/hooks/papertrail: move out of main repository 14 | * logrus/hooks/bugsnag: move out of main repository 15 | * logrus/core: run tests with `-race` 16 | * logrus/core: detect TTY based on `stderr` 17 | * logrus/core: support `WithError` on logger 18 | * logrus/core: Solaris support 19 | 20 | # 0.8.7 21 | 22 | * logrus/core: fix possible race (#216) 23 | * logrus/doc: small typo fixes and doc improvements 24 | 25 | 26 | # 0.8.6 27 | 28 | * hooks/raven: allow passing an initialized client 29 | 30 | # 0.8.5 31 | 32 | * logrus/core: revert #208 33 | 34 | # 0.8.4 35 | 36 | * formatter/text: fix data race (#218) 37 | 38 | # 0.8.3 39 | 40 | * logrus/core: fix entry log level (#208) 41 | * logrus/core: improve performance of text formatter by 40% 42 | * logrus/core: expose `LevelHooks` type 43 | * logrus/core: add support for DragonflyBSD and NetBSD 44 | * formatter/text: print structs more verbosely 45 | 46 | # 0.8.2 47 | 48 | * logrus: fix more Fatal family functions 49 | 50 | # 0.8.1 51 | 52 | * logrus: fix not exiting on `Fatalf` and `Fatalln` 53 | 54 | # 0.8.0 55 | 56 | * logrus: defaults to stderr instead of stdout 57 | * hooks/sentry: add special field for `*http.Request` 58 | * formatter/text: ignore Windows for colors 59 | 60 | # 0.7.3 61 | 62 | * formatter/\*: allow configuration of timestamp layout 63 | 64 | # 0.7.2 65 | 66 | * formatter/text: Add configuration option for time format (#158) 67 | -------------------------------------------------------------------------------- /vendor/github.com/Sirupsen/logrus/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Simon Eskildsen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/github.com/Sirupsen/logrus/alt_exit.go: -------------------------------------------------------------------------------- 1 | package logrus 2 | 3 | // The following code was sourced and modified from the 4 | // https://bitbucket.org/tebeka/atexit package governed by the following license: 5 | // 6 | // Copyright (c) 2012 Miki Tebeka . 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of 9 | // this software and associated documentation files (the "Software"), to deal in 10 | // the Software without restriction, including without limitation the rights to 11 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 12 | // the Software, and to permit persons to whom the Software is furnished to do so, 13 | // subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 20 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 21 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 22 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | 25 | import ( 26 | "fmt" 27 | "os" 28 | ) 29 | 30 | var handlers = []func(){} 31 | 32 | func runHandler(handler func()) { 33 | defer func() { 34 | if err := recover(); err != nil { 35 | fmt.Fprintln(os.Stderr, "Error: Logrus exit handler error:", err) 36 | } 37 | }() 38 | 39 | handler() 40 | } 41 | 42 | func runHandlers() { 43 | for _, handler := range handlers { 44 | runHandler(handler) 45 | } 46 | } 47 | 48 | // Exit runs all the Logrus atexit handlers and then terminates the program using os.Exit(code) 49 | func Exit(code int) { 50 | runHandlers() 51 | os.Exit(code) 52 | } 53 | 54 | // RegisterExitHandler adds a Logrus Exit handler, call logrus.Exit to invoke 55 | // all handlers. The handlers will also be invoked when any Fatal log entry is 56 | // made. 57 | // 58 | // This method is useful when a caller wishes to use logrus to log a fatal 59 | // message but also needs to gracefully shutdown. An example usecase could be 60 | // closing database connections, or sending a alert that the application is 61 | // closing. 62 | func RegisterExitHandler(handler func()) { 63 | handlers = append(handlers, handler) 64 | } 65 | -------------------------------------------------------------------------------- /vendor/github.com/Sirupsen/logrus/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package logrus is a structured logger for Go, completely API compatible with the standard library logger. 3 | 4 | 5 | The simplest way to use Logrus is simply the package-level exported logger: 6 | 7 | package main 8 | 9 | import ( 10 | log "github.com/Sirupsen/logrus" 11 | ) 12 | 13 | func main() { 14 | log.WithFields(log.Fields{ 15 | "animal": "walrus", 16 | "number": 1, 17 | "size": 10, 18 | }).Info("A walrus appears") 19 | } 20 | 21 | Output: 22 | time="2015-09-07T08:48:33Z" level=info msg="A walrus appears" animal=walrus number=1 size=10 23 | 24 | For a full guide visit https://github.com/Sirupsen/logrus 25 | */ 26 | package logrus 27 | -------------------------------------------------------------------------------- /vendor/github.com/Sirupsen/logrus/exported.go: -------------------------------------------------------------------------------- 1 | package logrus 2 | 3 | import ( 4 | "io" 5 | ) 6 | 7 | var ( 8 | // std is the name of the standard logger in stdlib `log` 9 | std = New() 10 | ) 11 | 12 | func StandardLogger() *Logger { 13 | return std 14 | } 15 | 16 | // SetOutput sets the standard logger output. 17 | func SetOutput(out io.Writer) { 18 | std.mu.Lock() 19 | defer std.mu.Unlock() 20 | std.Out = out 21 | } 22 | 23 | // SetFormatter sets the standard logger formatter. 24 | func SetFormatter(formatter Formatter) { 25 | std.mu.Lock() 26 | defer std.mu.Unlock() 27 | std.Formatter = formatter 28 | } 29 | 30 | // SetLevel sets the standard logger level. 31 | func SetLevel(level Level) { 32 | std.mu.Lock() 33 | defer std.mu.Unlock() 34 | std.Level = level 35 | } 36 | 37 | // GetLevel returns the standard logger level. 38 | func GetLevel() Level { 39 | std.mu.Lock() 40 | defer std.mu.Unlock() 41 | return std.Level 42 | } 43 | 44 | // AddHook adds a hook to the standard logger hooks. 45 | func AddHook(hook Hook) { 46 | std.mu.Lock() 47 | defer std.mu.Unlock() 48 | std.Hooks.Add(hook) 49 | } 50 | 51 | // WithError creates an entry from the standard logger and adds an error to it, using the value defined in ErrorKey as key. 52 | func WithError(err error) *Entry { 53 | return std.WithField(ErrorKey, err) 54 | } 55 | 56 | // WithField creates an entry from the standard logger and adds a field to 57 | // it. If you want multiple fields, use `WithFields`. 58 | // 59 | // Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal 60 | // or Panic on the Entry it returns. 61 | func WithField(key string, value interface{}) *Entry { 62 | return std.WithField(key, value) 63 | } 64 | 65 | // WithFields creates an entry from the standard logger and adds multiple 66 | // fields to it. This is simply a helper for `WithField`, invoking it 67 | // once for each field. 68 | // 69 | // Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal 70 | // or Panic on the Entry it returns. 71 | func WithFields(fields Fields) *Entry { 72 | return std.WithFields(fields) 73 | } 74 | 75 | // Debug logs a message at level Debug on the standard logger. 76 | func Debug(args ...interface{}) { 77 | std.Debug(args...) 78 | } 79 | 80 | // Print logs a message at level Info on the standard logger. 81 | func Print(args ...interface{}) { 82 | std.Print(args...) 83 | } 84 | 85 | // Info logs a message at level Info on the standard logger. 86 | func Info(args ...interface{}) { 87 | std.Info(args...) 88 | } 89 | 90 | // Warn logs a message at level Warn on the standard logger. 91 | func Warn(args ...interface{}) { 92 | std.Warn(args...) 93 | } 94 | 95 | // Warning logs a message at level Warn on the standard logger. 96 | func Warning(args ...interface{}) { 97 | std.Warning(args...) 98 | } 99 | 100 | // Error logs a message at level Error on the standard logger. 101 | func Error(args ...interface{}) { 102 | std.Error(args...) 103 | } 104 | 105 | // Panic logs a message at level Panic on the standard logger. 106 | func Panic(args ...interface{}) { 107 | std.Panic(args...) 108 | } 109 | 110 | // Fatal logs a message at level Fatal on the standard logger. 111 | func Fatal(args ...interface{}) { 112 | std.Fatal(args...) 113 | } 114 | 115 | // Debugf logs a message at level Debug on the standard logger. 116 | func Debugf(format string, args ...interface{}) { 117 | std.Debugf(format, args...) 118 | } 119 | 120 | // Printf logs a message at level Info on the standard logger. 121 | func Printf(format string, args ...interface{}) { 122 | std.Printf(format, args...) 123 | } 124 | 125 | // Infof logs a message at level Info on the standard logger. 126 | func Infof(format string, args ...interface{}) { 127 | std.Infof(format, args...) 128 | } 129 | 130 | // Warnf logs a message at level Warn on the standard logger. 131 | func Warnf(format string, args ...interface{}) { 132 | std.Warnf(format, args...) 133 | } 134 | 135 | // Warningf logs a message at level Warn on the standard logger. 136 | func Warningf(format string, args ...interface{}) { 137 | std.Warningf(format, args...) 138 | } 139 | 140 | // Errorf logs a message at level Error on the standard logger. 141 | func Errorf(format string, args ...interface{}) { 142 | std.Errorf(format, args...) 143 | } 144 | 145 | // Panicf logs a message at level Panic on the standard logger. 146 | func Panicf(format string, args ...interface{}) { 147 | std.Panicf(format, args...) 148 | } 149 | 150 | // Fatalf logs a message at level Fatal on the standard logger. 151 | func Fatalf(format string, args ...interface{}) { 152 | std.Fatalf(format, args...) 153 | } 154 | 155 | // Debugln logs a message at level Debug on the standard logger. 156 | func Debugln(args ...interface{}) { 157 | std.Debugln(args...) 158 | } 159 | 160 | // Println logs a message at level Info on the standard logger. 161 | func Println(args ...interface{}) { 162 | std.Println(args...) 163 | } 164 | 165 | // Infoln logs a message at level Info on the standard logger. 166 | func Infoln(args ...interface{}) { 167 | std.Infoln(args...) 168 | } 169 | 170 | // Warnln logs a message at level Warn on the standard logger. 171 | func Warnln(args ...interface{}) { 172 | std.Warnln(args...) 173 | } 174 | 175 | // Warningln logs a message at level Warn on the standard logger. 176 | func Warningln(args ...interface{}) { 177 | std.Warningln(args...) 178 | } 179 | 180 | // Errorln logs a message at level Error on the standard logger. 181 | func Errorln(args ...interface{}) { 182 | std.Errorln(args...) 183 | } 184 | 185 | // Panicln logs a message at level Panic on the standard logger. 186 | func Panicln(args ...interface{}) { 187 | std.Panicln(args...) 188 | } 189 | 190 | // Fatalln logs a message at level Fatal on the standard logger. 191 | func Fatalln(args ...interface{}) { 192 | std.Fatalln(args...) 193 | } 194 | -------------------------------------------------------------------------------- /vendor/github.com/Sirupsen/logrus/formatter.go: -------------------------------------------------------------------------------- 1 | package logrus 2 | 3 | import "time" 4 | 5 | const DefaultTimestampFormat = time.RFC3339 6 | 7 | // The Formatter interface is used to implement a custom Formatter. It takes an 8 | // `Entry`. It exposes all the fields, including the default ones: 9 | // 10 | // * `entry.Data["msg"]`. The message passed from Info, Warn, Error .. 11 | // * `entry.Data["time"]`. The timestamp. 12 | // * `entry.Data["level"]. The level the entry was logged at. 13 | // 14 | // Any additional fields added with `WithField` or `WithFields` are also in 15 | // `entry.Data`. Format is expected to return an array of bytes which are then 16 | // logged to `logger.Out`. 17 | type Formatter interface { 18 | Format(*Entry) ([]byte, error) 19 | } 20 | 21 | // This is to not silently overwrite `time`, `msg` and `level` fields when 22 | // dumping it. If this code wasn't there doing: 23 | // 24 | // logrus.WithField("level", 1).Info("hello") 25 | // 26 | // Would just silently drop the user provided level. Instead with this code 27 | // it'll logged as: 28 | // 29 | // {"level": "info", "fields.level": 1, "msg": "hello", "time": "..."} 30 | // 31 | // It's not exported because it's still using Data in an opinionated way. It's to 32 | // avoid code duplication between the two default formatters. 33 | func prefixFieldClashes(data Fields) { 34 | if t, ok := data["time"]; ok { 35 | data["fields.time"] = t 36 | } 37 | 38 | if m, ok := data["msg"]; ok { 39 | data["fields.msg"] = m 40 | } 41 | 42 | if l, ok := data["level"]; ok { 43 | data["fields.level"] = l 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /vendor/github.com/Sirupsen/logrus/hooks.go: -------------------------------------------------------------------------------- 1 | package logrus 2 | 3 | // A hook to be fired when logging on the logging levels returned from 4 | // `Levels()` on your implementation of the interface. Note that this is not 5 | // fired in a goroutine or a channel with workers, you should handle such 6 | // functionality yourself if your call is non-blocking and you don't wish for 7 | // the logging calls for levels returned from `Levels()` to block. 8 | type Hook interface { 9 | Levels() []Level 10 | Fire(*Entry) error 11 | } 12 | 13 | // Internal type for storing the hooks on a logger instance. 14 | type LevelHooks map[Level][]Hook 15 | 16 | // Add a hook to an instance of logger. This is called with 17 | // `log.Hooks.Add(new(MyHook))` where `MyHook` implements the `Hook` interface. 18 | func (hooks LevelHooks) Add(hook Hook) { 19 | for _, level := range hook.Levels() { 20 | hooks[level] = append(hooks[level], hook) 21 | } 22 | } 23 | 24 | // Fire all the hooks for the passed level. Used by `entry.log` to fire 25 | // appropriate hooks for a log entry. 26 | func (hooks LevelHooks) Fire(level Level, entry *Entry) error { 27 | for _, hook := range hooks[level] { 28 | if err := hook.Fire(entry); err != nil { 29 | return err 30 | } 31 | } 32 | 33 | return nil 34 | } 35 | -------------------------------------------------------------------------------- /vendor/github.com/Sirupsen/logrus/json_formatter.go: -------------------------------------------------------------------------------- 1 | package logrus 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | ) 7 | 8 | type JSONFormatter struct { 9 | // TimestampFormat sets the format used for marshaling timestamps. 10 | TimestampFormat string 11 | } 12 | 13 | func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) { 14 | data := make(Fields, len(entry.Data)+3) 15 | for k, v := range entry.Data { 16 | switch v := v.(type) { 17 | case error: 18 | // Otherwise errors are ignored by `encoding/json` 19 | // https://github.com/Sirupsen/logrus/issues/137 20 | data[k] = v.Error() 21 | default: 22 | data[k] = v 23 | } 24 | } 25 | prefixFieldClashes(data) 26 | 27 | timestampFormat := f.TimestampFormat 28 | if timestampFormat == "" { 29 | timestampFormat = DefaultTimestampFormat 30 | } 31 | 32 | data["time"] = entry.Time.Format(timestampFormat) 33 | data["msg"] = entry.Message 34 | data["level"] = entry.Level.String() 35 | 36 | serialized, err := json.Marshal(data) 37 | if err != nil { 38 | return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err) 39 | } 40 | return append(serialized, '\n'), nil 41 | } 42 | -------------------------------------------------------------------------------- /vendor/github.com/Sirupsen/logrus/logrus.go: -------------------------------------------------------------------------------- 1 | package logrus 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "strings" 7 | ) 8 | 9 | // Fields type, used to pass to `WithFields`. 10 | type Fields map[string]interface{} 11 | 12 | // Level type 13 | type Level uint8 14 | 15 | // Convert the Level to a string. E.g. PanicLevel becomes "panic". 16 | func (level Level) String() string { 17 | switch level { 18 | case DebugLevel: 19 | return "debug" 20 | case InfoLevel: 21 | return "info" 22 | case WarnLevel: 23 | return "warning" 24 | case ErrorLevel: 25 | return "error" 26 | case FatalLevel: 27 | return "fatal" 28 | case PanicLevel: 29 | return "panic" 30 | } 31 | 32 | return "unknown" 33 | } 34 | 35 | // ParseLevel takes a string level and returns the Logrus log level constant. 36 | func ParseLevel(lvl string) (Level, error) { 37 | switch strings.ToLower(lvl) { 38 | case "panic": 39 | return PanicLevel, nil 40 | case "fatal": 41 | return FatalLevel, nil 42 | case "error": 43 | return ErrorLevel, nil 44 | case "warn", "warning": 45 | return WarnLevel, nil 46 | case "info": 47 | return InfoLevel, nil 48 | case "debug": 49 | return DebugLevel, nil 50 | } 51 | 52 | var l Level 53 | return l, fmt.Errorf("not a valid logrus Level: %q", lvl) 54 | } 55 | 56 | // A constant exposing all logging levels 57 | var AllLevels = []Level{ 58 | PanicLevel, 59 | FatalLevel, 60 | ErrorLevel, 61 | WarnLevel, 62 | InfoLevel, 63 | DebugLevel, 64 | } 65 | 66 | // These are the different logging levels. You can set the logging level to log 67 | // on your instance of logger, obtained with `logrus.New()`. 68 | const ( 69 | // PanicLevel level, highest level of severity. Logs and then calls panic with the 70 | // message passed to Debug, Info, ... 71 | PanicLevel Level = iota 72 | // FatalLevel level. Logs and then calls `os.Exit(1)`. It will exit even if the 73 | // logging level is set to Panic. 74 | FatalLevel 75 | // ErrorLevel level. Logs. Used for errors that should definitely be noted. 76 | // Commonly used for hooks to send errors to an error tracking service. 77 | ErrorLevel 78 | // WarnLevel level. Non-critical entries that deserve eyes. 79 | WarnLevel 80 | // InfoLevel level. General operational entries about what's going on inside the 81 | // application. 82 | InfoLevel 83 | // DebugLevel level. Usually only enabled when debugging. Very verbose logging. 84 | DebugLevel 85 | ) 86 | 87 | // Won't compile if StdLogger can't be realized by a log.Logger 88 | var ( 89 | _ StdLogger = &log.Logger{} 90 | _ StdLogger = &Entry{} 91 | _ StdLogger = &Logger{} 92 | ) 93 | 94 | // StdLogger is what your logrus-enabled library should take, that way 95 | // it'll accept a stdlib logger and a logrus logger. There's no standard 96 | // interface, this is the closest we get, unfortunately. 97 | type StdLogger interface { 98 | Print(...interface{}) 99 | Printf(string, ...interface{}) 100 | Println(...interface{}) 101 | 102 | Fatal(...interface{}) 103 | Fatalf(string, ...interface{}) 104 | Fatalln(...interface{}) 105 | 106 | Panic(...interface{}) 107 | Panicf(string, ...interface{}) 108 | Panicln(...interface{}) 109 | } 110 | 111 | // The FieldLogger interface generalizes the Entry and Logger types 112 | type FieldLogger interface { 113 | WithField(key string, value interface{}) *Entry 114 | WithFields(fields Fields) *Entry 115 | WithError(err error) *Entry 116 | 117 | Debugf(format string, args ...interface{}) 118 | Infof(format string, args ...interface{}) 119 | Printf(format string, args ...interface{}) 120 | Warnf(format string, args ...interface{}) 121 | Warningf(format string, args ...interface{}) 122 | Errorf(format string, args ...interface{}) 123 | Fatalf(format string, args ...interface{}) 124 | Panicf(format string, args ...interface{}) 125 | 126 | Debug(args ...interface{}) 127 | Info(args ...interface{}) 128 | Print(args ...interface{}) 129 | Warn(args ...interface{}) 130 | Warning(args ...interface{}) 131 | Error(args ...interface{}) 132 | Fatal(args ...interface{}) 133 | Panic(args ...interface{}) 134 | 135 | Debugln(args ...interface{}) 136 | Infoln(args ...interface{}) 137 | Println(args ...interface{}) 138 | Warnln(args ...interface{}) 139 | Warningln(args ...interface{}) 140 | Errorln(args ...interface{}) 141 | Fatalln(args ...interface{}) 142 | Panicln(args ...interface{}) 143 | } 144 | -------------------------------------------------------------------------------- /vendor/github.com/Sirupsen/logrus/terminal_appengine.go: -------------------------------------------------------------------------------- 1 | // +build appengine 2 | 3 | package logrus 4 | 5 | // IsTerminal returns true if stderr's file descriptor is a terminal. 6 | func IsTerminal() bool { 7 | return true 8 | } 9 | -------------------------------------------------------------------------------- /vendor/github.com/Sirupsen/logrus/terminal_bsd.go: -------------------------------------------------------------------------------- 1 | // +build darwin freebsd openbsd netbsd dragonfly 2 | // +build !appengine 3 | 4 | package logrus 5 | 6 | import "syscall" 7 | 8 | const ioctlReadTermios = syscall.TIOCGETA 9 | 10 | type Termios syscall.Termios 11 | -------------------------------------------------------------------------------- /vendor/github.com/Sirupsen/logrus/terminal_linux.go: -------------------------------------------------------------------------------- 1 | // Based on ssh/terminal: 2 | // Copyright 2013 The Go Authors. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // +build !appengine 7 | 8 | package logrus 9 | 10 | import "syscall" 11 | 12 | const ioctlReadTermios = syscall.TCGETS 13 | 14 | type Termios syscall.Termios 15 | -------------------------------------------------------------------------------- /vendor/github.com/Sirupsen/logrus/terminal_notwindows.go: -------------------------------------------------------------------------------- 1 | // Based on ssh/terminal: 2 | // Copyright 2011 The Go Authors. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // +build linux darwin freebsd openbsd netbsd dragonfly 7 | // +build !appengine 8 | 9 | package logrus 10 | 11 | import ( 12 | "syscall" 13 | "unsafe" 14 | ) 15 | 16 | // IsTerminal returns true if stderr's file descriptor is a terminal. 17 | func IsTerminal() bool { 18 | fd := syscall.Stderr 19 | var termios Termios 20 | _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0) 21 | return err == 0 22 | } 23 | -------------------------------------------------------------------------------- /vendor/github.com/Sirupsen/logrus/terminal_solaris.go: -------------------------------------------------------------------------------- 1 | // +build solaris,!appengine 2 | 3 | package logrus 4 | 5 | import ( 6 | "os" 7 | 8 | "golang.org/x/sys/unix" 9 | ) 10 | 11 | // IsTerminal returns true if the given file descriptor is a terminal. 12 | func IsTerminal() bool { 13 | _, err := unix.IoctlGetTermios(int(os.Stdout.Fd()), unix.TCGETA) 14 | return err == nil 15 | } 16 | -------------------------------------------------------------------------------- /vendor/github.com/Sirupsen/logrus/terminal_windows.go: -------------------------------------------------------------------------------- 1 | // Based on ssh/terminal: 2 | // Copyright 2011 The Go Authors. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // +build windows,!appengine 7 | 8 | package logrus 9 | 10 | import ( 11 | "syscall" 12 | "unsafe" 13 | ) 14 | 15 | var kernel32 = syscall.NewLazyDLL("kernel32.dll") 16 | 17 | var ( 18 | procGetConsoleMode = kernel32.NewProc("GetConsoleMode") 19 | ) 20 | 21 | // IsTerminal returns true if stderr's file descriptor is a terminal. 22 | func IsTerminal() bool { 23 | fd := syscall.Stderr 24 | var st uint32 25 | r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0) 26 | return r != 0 && e == 0 27 | } 28 | -------------------------------------------------------------------------------- /vendor/github.com/Sirupsen/logrus/text_formatter.go: -------------------------------------------------------------------------------- 1 | package logrus 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "runtime" 7 | "sort" 8 | "strings" 9 | "time" 10 | ) 11 | 12 | const ( 13 | nocolor = 0 14 | red = 31 15 | green = 32 16 | yellow = 33 17 | blue = 34 18 | gray = 37 19 | ) 20 | 21 | var ( 22 | baseTimestamp time.Time 23 | isTerminal bool 24 | ) 25 | 26 | func init() { 27 | baseTimestamp = time.Now() 28 | isTerminal = IsTerminal() 29 | } 30 | 31 | func miniTS() int { 32 | return int(time.Since(baseTimestamp) / time.Second) 33 | } 34 | 35 | type TextFormatter struct { 36 | // Set to true to bypass checking for a TTY before outputting colors. 37 | ForceColors bool 38 | 39 | // Force disabling colors. 40 | DisableColors bool 41 | 42 | // Disable timestamp logging. useful when output is redirected to logging 43 | // system that already adds timestamps. 44 | DisableTimestamp bool 45 | 46 | // Enable logging the full timestamp when a TTY is attached instead of just 47 | // the time passed since beginning of execution. 48 | FullTimestamp bool 49 | 50 | // TimestampFormat to use for display when a full timestamp is printed 51 | TimestampFormat string 52 | 53 | // The fields are sorted by default for a consistent output. For applications 54 | // that log extremely frequently and don't use the JSON formatter this may not 55 | // be desired. 56 | DisableSorting bool 57 | } 58 | 59 | func (f *TextFormatter) Format(entry *Entry) ([]byte, error) { 60 | var b *bytes.Buffer 61 | var keys []string = make([]string, 0, len(entry.Data)) 62 | for k := range entry.Data { 63 | keys = append(keys, k) 64 | } 65 | 66 | if !f.DisableSorting { 67 | sort.Strings(keys) 68 | } 69 | if entry.Buffer != nil { 70 | b = entry.Buffer 71 | } else { 72 | b = &bytes.Buffer{} 73 | } 74 | 75 | prefixFieldClashes(entry.Data) 76 | 77 | isColorTerminal := isTerminal && (runtime.GOOS != "windows") 78 | isColored := (f.ForceColors || isColorTerminal) && !f.DisableColors 79 | 80 | timestampFormat := f.TimestampFormat 81 | if timestampFormat == "" { 82 | timestampFormat = DefaultTimestampFormat 83 | } 84 | if isColored { 85 | f.printColored(b, entry, keys, timestampFormat) 86 | } else { 87 | if !f.DisableTimestamp { 88 | f.appendKeyValue(b, "time", entry.Time.Format(timestampFormat)) 89 | } 90 | f.appendKeyValue(b, "level", entry.Level.String()) 91 | if entry.Message != "" { 92 | f.appendKeyValue(b, "msg", entry.Message) 93 | } 94 | for _, key := range keys { 95 | f.appendKeyValue(b, key, entry.Data[key]) 96 | } 97 | } 98 | 99 | b.WriteByte('\n') 100 | return b.Bytes(), nil 101 | } 102 | 103 | func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []string, timestampFormat string) { 104 | var levelColor int 105 | switch entry.Level { 106 | case DebugLevel: 107 | levelColor = gray 108 | case WarnLevel: 109 | levelColor = yellow 110 | case ErrorLevel, FatalLevel, PanicLevel: 111 | levelColor = red 112 | default: 113 | levelColor = blue 114 | } 115 | 116 | levelText := strings.ToUpper(entry.Level.String())[0:4] 117 | 118 | if !f.FullTimestamp { 119 | fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%04d] %-44s ", levelColor, levelText, miniTS(), entry.Message) 120 | } else { 121 | fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s] %-44s ", levelColor, levelText, entry.Time.Format(timestampFormat), entry.Message) 122 | } 123 | for _, k := range keys { 124 | v := entry.Data[k] 125 | fmt.Fprintf(b, " \x1b[%dm%s\x1b[0m=", levelColor, k) 126 | f.appendValue(b, v) 127 | } 128 | } 129 | 130 | func needsQuoting(text string) bool { 131 | for _, ch := range text { 132 | if !((ch >= 'a' && ch <= 'z') || 133 | (ch >= 'A' && ch <= 'Z') || 134 | (ch >= '0' && ch <= '9') || 135 | ch == '-' || ch == '.') { 136 | return true 137 | } 138 | } 139 | return false 140 | } 141 | 142 | func (f *TextFormatter) appendKeyValue(b *bytes.Buffer, key string, value interface{}) { 143 | 144 | b.WriteString(key) 145 | b.WriteByte('=') 146 | f.appendValue(b, value) 147 | b.WriteByte(' ') 148 | } 149 | 150 | func (f *TextFormatter) appendValue(b *bytes.Buffer, value interface{}) { 151 | switch value := value.(type) { 152 | case string: 153 | if !needsQuoting(value) { 154 | b.WriteString(value) 155 | } else { 156 | fmt.Fprintf(b, "%q", value) 157 | } 158 | case error: 159 | errmsg := value.Error() 160 | if !needsQuoting(errmsg) { 161 | b.WriteString(errmsg) 162 | } else { 163 | fmt.Fprintf(b, "%q", errmsg) 164 | } 165 | default: 166 | fmt.Fprint(b, value) 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /vendor/github.com/Sirupsen/logrus/writer.go: -------------------------------------------------------------------------------- 1 | package logrus 2 | 3 | import ( 4 | "bufio" 5 | "io" 6 | "runtime" 7 | ) 8 | 9 | func (logger *Logger) Writer() *io.PipeWriter { 10 | return logger.WriterLevel(InfoLevel) 11 | } 12 | 13 | func (logger *Logger) WriterLevel(level Level) *io.PipeWriter { 14 | reader, writer := io.Pipe() 15 | 16 | var printFunc func(args ...interface{}) 17 | switch level { 18 | case DebugLevel: 19 | printFunc = logger.Debug 20 | case InfoLevel: 21 | printFunc = logger.Info 22 | case WarnLevel: 23 | printFunc = logger.Warn 24 | case ErrorLevel: 25 | printFunc = logger.Error 26 | case FatalLevel: 27 | printFunc = logger.Fatal 28 | case PanicLevel: 29 | printFunc = logger.Panic 30 | default: 31 | printFunc = logger.Print 32 | } 33 | 34 | go logger.writerScanner(reader, printFunc) 35 | runtime.SetFinalizer(writer, writerFinalizer) 36 | 37 | return writer 38 | } 39 | 40 | func (logger *Logger) writerScanner(reader *io.PipeReader, printFunc func(args ...interface{})) { 41 | scanner := bufio.NewScanner(reader) 42 | for scanner.Scan() { 43 | printFunc(scanner.Text()) 44 | } 45 | if err := scanner.Err(); err != nil { 46 | logger.Errorf("Error while reading from Writer: %s", err) 47 | } 48 | reader.Close() 49 | } 50 | 51 | func writerFinalizer(writer *io.PipeWriter) { 52 | writer.Close() 53 | } 54 | -------------------------------------------------------------------------------- /vendor/github.com/coreos/go-systemd/activation/files.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 CoreOS, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package activation implements primitives for systemd socket activation. 16 | package activation 17 | 18 | import ( 19 | "os" 20 | "strconv" 21 | "syscall" 22 | ) 23 | 24 | // based on: https://gist.github.com/alberts/4640792 25 | const ( 26 | listenFdsStart = 3 27 | ) 28 | 29 | func Files(unsetEnv bool) []*os.File { 30 | if unsetEnv { 31 | defer os.Unsetenv("LISTEN_PID") 32 | defer os.Unsetenv("LISTEN_FDS") 33 | } 34 | 35 | pid, err := strconv.Atoi(os.Getenv("LISTEN_PID")) 36 | if err != nil || pid != os.Getpid() { 37 | return nil 38 | } 39 | 40 | nfds, err := strconv.Atoi(os.Getenv("LISTEN_FDS")) 41 | if err != nil || nfds == 0 { 42 | return nil 43 | } 44 | 45 | files := make([]*os.File, 0, nfds) 46 | for fd := listenFdsStart; fd < listenFdsStart+nfds; fd++ { 47 | syscall.CloseOnExec(fd) 48 | files = append(files, os.NewFile(uintptr(fd), "LISTEN_FD_"+strconv.Itoa(fd))) 49 | } 50 | 51 | return files 52 | } 53 | -------------------------------------------------------------------------------- /vendor/github.com/coreos/go-systemd/activation/listeners.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 CoreOS, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package activation 16 | 17 | import ( 18 | "crypto/tls" 19 | "net" 20 | ) 21 | 22 | // Listeners returns a slice containing a net.Listener for each matching socket type 23 | // passed to this process. 24 | // 25 | // The order of the file descriptors is preserved in the returned slice. 26 | // Nil values are used to fill any gaps. For example if systemd were to return file descriptors 27 | // corresponding with "udp, tcp, tcp", then the slice would contain {nil, net.Listener, net.Listener} 28 | func Listeners(unsetEnv bool) ([]net.Listener, error) { 29 | files := Files(unsetEnv) 30 | listeners := make([]net.Listener, len(files)) 31 | 32 | for i, f := range files { 33 | if pc, err := net.FileListener(f); err == nil { 34 | listeners[i] = pc 35 | } 36 | } 37 | return listeners, nil 38 | } 39 | 40 | // TLSListeners returns a slice containing a net.listener for each matching TCP socket type 41 | // passed to this process. 42 | // It uses default Listeners func and forces TCP sockets handlers to use TLS based on tlsConfig. 43 | func TLSListeners(unsetEnv bool, tlsConfig *tls.Config) ([]net.Listener, error) { 44 | listeners, err := Listeners(unsetEnv) 45 | 46 | if listeners == nil || err != nil { 47 | return nil, err 48 | } 49 | 50 | if tlsConfig != nil && err == nil { 51 | for i, l := range listeners { 52 | // Activate TLS only for TCP sockets 53 | if l.Addr().Network() == "tcp" { 54 | listeners[i] = tls.NewListener(l, tlsConfig) 55 | } 56 | } 57 | } 58 | 59 | return listeners, err 60 | } 61 | -------------------------------------------------------------------------------- /vendor/github.com/coreos/go-systemd/activation/packetconns.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 CoreOS, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package activation 16 | 17 | import ( 18 | "net" 19 | ) 20 | 21 | // PacketConns returns a slice containing a net.PacketConn for each matching socket type 22 | // passed to this process. 23 | // 24 | // The order of the file descriptors is preserved in the returned slice. 25 | // Nil values are used to fill any gaps. For example if systemd were to return file descriptors 26 | // corresponding with "udp, tcp, udp", then the slice would contain {net.PacketConn, nil, net.PacketConn} 27 | func PacketConns(unsetEnv bool) ([]net.PacketConn, error) { 28 | files := Files(unsetEnv) 29 | conns := make([]net.PacketConn, len(files)) 30 | 31 | for i, f := range files { 32 | if pc, err := net.FilePacketConn(f); err == nil { 33 | conns[i] = pc 34 | } 35 | } 36 | return conns, nil 37 | } 38 | -------------------------------------------------------------------------------- /vendor/github.com/coreos/go-systemd/util/util.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 CoreOS, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package util contains utility functions related to systemd that applications 16 | // can use to check things like whether systemd is running. Note that some of 17 | // these functions attempt to manually load systemd libraries at runtime rather 18 | // than linking against them. 19 | package util 20 | 21 | import ( 22 | "fmt" 23 | "io/ioutil" 24 | "os" 25 | "strings" 26 | ) 27 | 28 | var ( 29 | ErrNoCGO = fmt.Errorf("go-systemd built with CGO disabled") 30 | ) 31 | 32 | // GetRunningSlice attempts to retrieve the name of the systemd slice in which 33 | // the current process is running. 34 | // This function is a wrapper around the libsystemd C library; if it cannot be 35 | // opened, an error is returned. 36 | func GetRunningSlice() (string, error) { 37 | return getRunningSlice() 38 | } 39 | 40 | // RunningFromSystemService tries to detect whether the current process has 41 | // been invoked from a system service. The condition for this is whether the 42 | // process is _not_ a user process. User processes are those running in session 43 | // scopes or under per-user `systemd --user` instances. 44 | // 45 | // To avoid false positives on systems without `pam_systemd` (which is 46 | // responsible for creating user sessions), this function also uses a heuristic 47 | // to detect whether it's being invoked from a session leader process. This is 48 | // the case if the current process is executed directly from a service file 49 | // (e.g. with `ExecStart=/this/cmd`). Note that this heuristic will fail if the 50 | // command is instead launched in a subshell or similar so that it is not 51 | // session leader (e.g. `ExecStart=/bin/bash -c "/this/cmd"`) 52 | // 53 | // This function is a wrapper around the libsystemd C library; if this is 54 | // unable to successfully open a handle to the library for any reason (e.g. it 55 | // cannot be found), an error will be returned. 56 | func RunningFromSystemService() (bool, error) { 57 | return runningFromSystemService() 58 | } 59 | 60 | // CurrentUnitName attempts to retrieve the name of the systemd system unit 61 | // from which the calling process has been invoked. It wraps the systemd 62 | // `sd_pid_get_unit` call, with the same caveat: for processes not part of a 63 | // systemd system unit, this function will return an error. 64 | func CurrentUnitName() (string, error) { 65 | return currentUnitName() 66 | } 67 | 68 | // IsRunningSystemd checks whether the host was booted with systemd as its init 69 | // system. This functions similarly to systemd's `sd_booted(3)`: internally, it 70 | // checks whether /run/systemd/system/ exists and is a directory. 71 | // http://www.freedesktop.org/software/systemd/man/sd_booted.html 72 | func IsRunningSystemd() bool { 73 | fi, err := os.Lstat("/run/systemd/system") 74 | if err != nil { 75 | return false 76 | } 77 | return fi.IsDir() 78 | } 79 | 80 | // GetMachineID returns a host's 128-bit machine ID as a string. This functions 81 | // similarly to systemd's `sd_id128_get_machine`: internally, it simply reads 82 | // the contents of /etc/machine-id 83 | // http://www.freedesktop.org/software/systemd/man/sd_id128_get_machine.html 84 | func GetMachineID() (string, error) { 85 | machineID, err := ioutil.ReadFile("/etc/machine-id") 86 | if err != nil { 87 | return "", fmt.Errorf("failed to read /etc/machine-id: %v", err) 88 | } 89 | return strings.TrimSpace(string(machineID)), nil 90 | } 91 | -------------------------------------------------------------------------------- /vendor/github.com/coreos/go-systemd/util/util_cgo.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 CoreOS, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // +build cgo 16 | 17 | package util 18 | 19 | // #include 20 | // #include 21 | // #include 22 | // 23 | // int 24 | // my_sd_pid_get_owner_uid(void *f, pid_t pid, uid_t *uid) 25 | // { 26 | // int (*sd_pid_get_owner_uid)(pid_t, uid_t *); 27 | // 28 | // sd_pid_get_owner_uid = (int (*)(pid_t, uid_t *))f; 29 | // return sd_pid_get_owner_uid(pid, uid); 30 | // } 31 | // 32 | // int 33 | // my_sd_pid_get_unit(void *f, pid_t pid, char **unit) 34 | // { 35 | // int (*sd_pid_get_unit)(pid_t, char **); 36 | // 37 | // sd_pid_get_unit = (int (*)(pid_t, char **))f; 38 | // return sd_pid_get_unit(pid, unit); 39 | // } 40 | // 41 | // int 42 | // my_sd_pid_get_slice(void *f, pid_t pid, char **slice) 43 | // { 44 | // int (*sd_pid_get_slice)(pid_t, char **); 45 | // 46 | // sd_pid_get_slice = (int (*)(pid_t, char **))f; 47 | // return sd_pid_get_slice(pid, slice); 48 | // } 49 | // 50 | // int 51 | // am_session_leader() 52 | // { 53 | // return (getsid(0) == getpid()); 54 | // } 55 | import "C" 56 | import ( 57 | "fmt" 58 | "syscall" 59 | "unsafe" 60 | 61 | "github.com/coreos/pkg/dlopen" 62 | ) 63 | 64 | var libsystemdNames = []string{ 65 | // systemd < 209 66 | "libsystemd-login.so.0", 67 | "libsystemd-login.so", 68 | 69 | // systemd >= 209 merged libsystemd-login into libsystemd proper 70 | "libsystemd.so.0", 71 | "libsystemd.so", 72 | } 73 | 74 | func getRunningSlice() (slice string, err error) { 75 | var h *dlopen.LibHandle 76 | h, err = dlopen.GetHandle(libsystemdNames) 77 | if err != nil { 78 | return 79 | } 80 | defer func() { 81 | if err1 := h.Close(); err1 != nil { 82 | err = err1 83 | } 84 | }() 85 | 86 | sd_pid_get_slice, err := h.GetSymbolPointer("sd_pid_get_slice") 87 | if err != nil { 88 | return 89 | } 90 | 91 | var s string 92 | sl := C.CString(s) 93 | defer C.free(unsafe.Pointer(sl)) 94 | 95 | ret := C.my_sd_pid_get_slice(sd_pid_get_slice, 0, &sl) 96 | if ret < 0 { 97 | err = fmt.Errorf("error calling sd_pid_get_slice: %v", syscall.Errno(-ret)) 98 | return 99 | } 100 | 101 | return C.GoString(sl), nil 102 | } 103 | 104 | func runningFromSystemService() (ret bool, err error) { 105 | var h *dlopen.LibHandle 106 | h, err = dlopen.GetHandle(libsystemdNames) 107 | if err != nil { 108 | return 109 | } 110 | defer func() { 111 | if err1 := h.Close(); err1 != nil { 112 | err = err1 113 | } 114 | }() 115 | 116 | sd_pid_get_owner_uid, err := h.GetSymbolPointer("sd_pid_get_owner_uid") 117 | if err != nil { 118 | return 119 | } 120 | 121 | var uid C.uid_t 122 | errno := C.my_sd_pid_get_owner_uid(sd_pid_get_owner_uid, 0, &uid) 123 | serrno := syscall.Errno(-errno) 124 | // when we're running from a unit file, sd_pid_get_owner_uid returns 125 | // ENOENT (systemd <220) or ENXIO (systemd >=220) 126 | switch { 127 | case errno >= 0: 128 | ret = false 129 | case serrno == syscall.ENOENT, serrno == syscall.ENXIO: 130 | // Since the implementation of sessions in systemd relies on 131 | // the `pam_systemd` module, using the sd_pid_get_owner_uid 132 | // heuristic alone can result in false positives if that module 133 | // (or PAM itself) is not present or properly configured on the 134 | // system. As such, we also check if we're the session leader, 135 | // which should be the case if we're invoked from a unit file, 136 | // but not if e.g. we're invoked from the command line from a 137 | // user's login session 138 | ret = C.am_session_leader() == 1 139 | default: 140 | err = fmt.Errorf("error calling sd_pid_get_owner_uid: %v", syscall.Errno(-errno)) 141 | } 142 | return 143 | } 144 | 145 | func currentUnitName() (unit string, err error) { 146 | var h *dlopen.LibHandle 147 | h, err = dlopen.GetHandle(libsystemdNames) 148 | if err != nil { 149 | return 150 | } 151 | defer func() { 152 | if err1 := h.Close(); err1 != nil { 153 | err = err1 154 | } 155 | }() 156 | 157 | sd_pid_get_unit, err := h.GetSymbolPointer("sd_pid_get_unit") 158 | if err != nil { 159 | return 160 | } 161 | 162 | var s string 163 | u := C.CString(s) 164 | defer C.free(unsafe.Pointer(u)) 165 | 166 | ret := C.my_sd_pid_get_unit(sd_pid_get_unit, 0, &u) 167 | if ret < 0 { 168 | err = fmt.Errorf("error calling sd_pid_get_unit: %v", syscall.Errno(-ret)) 169 | return 170 | } 171 | 172 | unit = C.GoString(u) 173 | return 174 | } 175 | -------------------------------------------------------------------------------- /vendor/github.com/coreos/go-systemd/util/util_stub.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 CoreOS, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // +build !cgo 16 | 17 | package util 18 | 19 | func getRunningSlice() (string, error) { return "", ErrNoCGO } 20 | 21 | func runningFromSystemService() (bool, error) { return false, ErrNoCGO } 22 | 23 | func currentUnitName() (string, error) { return "", ErrNoCGO } 24 | -------------------------------------------------------------------------------- /vendor/github.com/coreos/pkg/NOTICE: -------------------------------------------------------------------------------- 1 | CoreOS Project 2 | Copyright 2014 CoreOS, Inc 3 | 4 | This product includes software developed at CoreOS, Inc. 5 | (http://www.coreos.com/). 6 | -------------------------------------------------------------------------------- /vendor/github.com/coreos/pkg/dlopen/dlopen.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 CoreOS, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package dlopen provides some convenience functions to dlopen a library and 16 | // get its symbols. 17 | package dlopen 18 | 19 | // #cgo LDFLAGS: -ldl 20 | // #include 21 | // #include 22 | import "C" 23 | import ( 24 | "errors" 25 | "fmt" 26 | "unsafe" 27 | ) 28 | 29 | var ErrSoNotFound = errors.New("unable to open a handle to the library") 30 | 31 | // LibHandle represents an open handle to a library (.so) 32 | type LibHandle struct { 33 | Handle unsafe.Pointer 34 | Libname string 35 | } 36 | 37 | // GetHandle tries to get a handle to a library (.so), attempting to access it 38 | // by the names specified in libs and returning the first that is successfully 39 | // opened. Callers are responsible for closing the handler. If no library can 40 | // be successfully opened, an error is returned. 41 | func GetHandle(libs []string) (*LibHandle, error) { 42 | for _, name := range libs { 43 | libname := C.CString(name) 44 | defer C.free(unsafe.Pointer(libname)) 45 | handle := C.dlopen(libname, C.RTLD_LAZY) 46 | if handle != nil { 47 | h := &LibHandle{ 48 | Handle: handle, 49 | Libname: name, 50 | } 51 | return h, nil 52 | } 53 | } 54 | return nil, ErrSoNotFound 55 | } 56 | 57 | // GetSymbolPointer takes a symbol name and returns a pointer to the symbol. 58 | func (l *LibHandle) GetSymbolPointer(symbol string) (unsafe.Pointer, error) { 59 | sym := C.CString(symbol) 60 | defer C.free(unsafe.Pointer(sym)) 61 | 62 | C.dlerror() 63 | p := C.dlsym(l.Handle, sym) 64 | e := C.dlerror() 65 | if e != nil { 66 | return nil, fmt.Errorf("error resolving symbol %q: %v", symbol, errors.New(C.GoString(e))) 67 | } 68 | 69 | return p, nil 70 | } 71 | 72 | // Close closes a LibHandle. 73 | func (l *LibHandle) Close() error { 74 | C.dlerror() 75 | C.dlclose(l.Handle) 76 | e := C.dlerror() 77 | if e != nil { 78 | return fmt.Errorf("error closing %v: %v", l.Libname, errors.New(C.GoString(e))) 79 | } 80 | 81 | return nil 82 | } 83 | -------------------------------------------------------------------------------- /vendor/github.com/coreos/pkg/dlopen/dlopen_example.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 CoreOS, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // 15 | // +build linux 16 | 17 | package dlopen 18 | 19 | // #include 20 | // #include 21 | // 22 | // int 23 | // my_strlen(void *f, const char *s) 24 | // { 25 | // size_t (*strlen)(const char *); 26 | // 27 | // strlen = (size_t (*)(const char *))f; 28 | // return strlen(s); 29 | // } 30 | import "C" 31 | 32 | import ( 33 | "fmt" 34 | "unsafe" 35 | ) 36 | 37 | func strlen(libs []string, s string) (int, error) { 38 | h, err := GetHandle(libs) 39 | if err != nil { 40 | return -1, fmt.Errorf(`couldn't get a handle to the library: %v`, err) 41 | } 42 | defer h.Close() 43 | 44 | f := "strlen" 45 | cs := C.CString(s) 46 | defer C.free(unsafe.Pointer(cs)) 47 | 48 | strlen, err := h.GetSymbolPointer(f) 49 | if err != nil { 50 | return -1, fmt.Errorf(`couldn't get symbol %q: %v`, f, err) 51 | } 52 | 53 | len := C.my_strlen(strlen, cs) 54 | 55 | return int(len), nil 56 | } 57 | -------------------------------------------------------------------------------- /vendor/github.com/docker/go-connections/sockets/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yunify/docker-plugin-hostnic/b37aa72af28fcaa3d738bde3405fea6ee209d101/vendor/github.com/docker/go-connections/sockets/README.md -------------------------------------------------------------------------------- /vendor/github.com/docker/go-connections/sockets/inmem_socket.go: -------------------------------------------------------------------------------- 1 | package sockets 2 | 3 | import ( 4 | "errors" 5 | "net" 6 | "sync" 7 | ) 8 | 9 | var errClosed = errors.New("use of closed network connection") 10 | 11 | // InmemSocket implements net.Listener using in-memory only connections. 12 | type InmemSocket struct { 13 | chConn chan net.Conn 14 | chClose chan struct{} 15 | addr string 16 | mu sync.Mutex 17 | } 18 | 19 | // dummyAddr is used to satisfy net.Addr for the in-mem socket 20 | // it is just stored as a string and returns the string for all calls 21 | type dummyAddr string 22 | 23 | // NewInmemSocket creates an in-memory only net.Listener 24 | // The addr argument can be any string, but is used to satisfy the `Addr()` part 25 | // of the net.Listener interface 26 | func NewInmemSocket(addr string, bufSize int) *InmemSocket { 27 | return &InmemSocket{ 28 | chConn: make(chan net.Conn, bufSize), 29 | chClose: make(chan struct{}), 30 | addr: addr, 31 | } 32 | } 33 | 34 | // Addr returns the socket's addr string to satisfy net.Listener 35 | func (s *InmemSocket) Addr() net.Addr { 36 | return dummyAddr(s.addr) 37 | } 38 | 39 | // Accept implements the Accept method in the Listener interface; it waits for the next call and returns a generic Conn. 40 | func (s *InmemSocket) Accept() (net.Conn, error) { 41 | select { 42 | case conn := <-s.chConn: 43 | return conn, nil 44 | case <-s.chClose: 45 | return nil, errClosed 46 | } 47 | } 48 | 49 | // Close closes the listener. It will be unavailable for use once closed. 50 | func (s *InmemSocket) Close() error { 51 | s.mu.Lock() 52 | defer s.mu.Unlock() 53 | select { 54 | case <-s.chClose: 55 | default: 56 | close(s.chClose) 57 | } 58 | return nil 59 | } 60 | 61 | // Dial is used to establish a connection with the in-mem server 62 | func (s *InmemSocket) Dial(network, addr string) (net.Conn, error) { 63 | srvConn, clientConn := net.Pipe() 64 | select { 65 | case s.chConn <- srvConn: 66 | case <-s.chClose: 67 | return nil, errClosed 68 | } 69 | 70 | return clientConn, nil 71 | } 72 | 73 | // Network returns the addr string, satisfies net.Addr 74 | func (a dummyAddr) Network() string { 75 | return string(a) 76 | } 77 | 78 | // String returns the string form 79 | func (a dummyAddr) String() string { 80 | return string(a) 81 | } 82 | -------------------------------------------------------------------------------- /vendor/github.com/docker/go-connections/sockets/proxy.go: -------------------------------------------------------------------------------- 1 | package sockets 2 | 3 | import ( 4 | "net" 5 | "net/url" 6 | "os" 7 | "strings" 8 | 9 | "golang.org/x/net/proxy" 10 | ) 11 | 12 | // GetProxyEnv allows access to the uppercase and the lowercase forms of 13 | // proxy-related variables. See the Go specification for details on these 14 | // variables. https://golang.org/pkg/net/http/ 15 | func GetProxyEnv(key string) string { 16 | proxyValue := os.Getenv(strings.ToUpper(key)) 17 | if proxyValue == "" { 18 | return os.Getenv(strings.ToLower(key)) 19 | } 20 | return proxyValue 21 | } 22 | 23 | // DialerFromEnvironment takes in a "direct" *net.Dialer and returns a 24 | // proxy.Dialer which will route the connections through the proxy using the 25 | // given dialer. 26 | func DialerFromEnvironment(direct *net.Dialer) (proxy.Dialer, error) { 27 | allProxy := GetProxyEnv("all_proxy") 28 | if len(allProxy) == 0 { 29 | return direct, nil 30 | } 31 | 32 | proxyURL, err := url.Parse(allProxy) 33 | if err != nil { 34 | return direct, err 35 | } 36 | 37 | proxyFromURL, err := proxy.FromURL(proxyURL, direct) 38 | if err != nil { 39 | return direct, err 40 | } 41 | 42 | noProxy := GetProxyEnv("no_proxy") 43 | if len(noProxy) == 0 { 44 | return proxyFromURL, nil 45 | } 46 | 47 | perHost := proxy.NewPerHost(proxyFromURL, direct) 48 | perHost.AddFromString(noProxy) 49 | 50 | return perHost, nil 51 | } 52 | -------------------------------------------------------------------------------- /vendor/github.com/docker/go-connections/sockets/sockets.go: -------------------------------------------------------------------------------- 1 | // Package sockets provides helper functions to create and configure Unix or TCP sockets. 2 | package sockets 3 | 4 | import ( 5 | "errors" 6 | "net" 7 | "net/http" 8 | "time" 9 | ) 10 | 11 | // Why 32? See https://github.com/docker/docker/pull/8035. 12 | const defaultTimeout = 32 * time.Second 13 | 14 | // ErrProtocolNotAvailable is returned when a given transport protocol is not provided by the operating system. 15 | var ErrProtocolNotAvailable = errors.New("protocol not available") 16 | 17 | // ConfigureTransport configures the specified Transport according to the 18 | // specified proto and addr. 19 | // If the proto is unix (using a unix socket to communicate) or npipe the 20 | // compression is disabled. 21 | func ConfigureTransport(tr *http.Transport, proto, addr string) error { 22 | switch proto { 23 | case "unix": 24 | return configureUnixTransport(tr, proto, addr) 25 | case "npipe": 26 | return configureNpipeTransport(tr, proto, addr) 27 | default: 28 | tr.Proxy = http.ProxyFromEnvironment 29 | dialer, err := DialerFromEnvironment(&net.Dialer{ 30 | Timeout: defaultTimeout, 31 | }) 32 | if err != nil { 33 | return err 34 | } 35 | tr.Dial = dialer.Dial 36 | } 37 | return nil 38 | } 39 | -------------------------------------------------------------------------------- /vendor/github.com/docker/go-connections/sockets/sockets_unix.go: -------------------------------------------------------------------------------- 1 | // +build !windows 2 | 3 | package sockets 4 | 5 | import ( 6 | "fmt" 7 | "net" 8 | "net/http" 9 | "syscall" 10 | "time" 11 | ) 12 | 13 | const maxUnixSocketPathSize = len(syscall.RawSockaddrUnix{}.Path) 14 | 15 | func configureUnixTransport(tr *http.Transport, proto, addr string) error { 16 | if len(addr) > maxUnixSocketPathSize { 17 | return fmt.Errorf("Unix socket path %q is too long", addr) 18 | } 19 | // No need for compression in local communications. 20 | tr.DisableCompression = true 21 | tr.Dial = func(_, _ string) (net.Conn, error) { 22 | return net.DialTimeout(proto, addr, defaultTimeout) 23 | } 24 | return nil 25 | } 26 | 27 | func configureNpipeTransport(tr *http.Transport, proto, addr string) error { 28 | return ErrProtocolNotAvailable 29 | } 30 | 31 | // DialPipe connects to a Windows named pipe. 32 | // This is not supported on other OSes. 33 | func DialPipe(_ string, _ time.Duration) (net.Conn, error) { 34 | return nil, syscall.EAFNOSUPPORT 35 | } 36 | -------------------------------------------------------------------------------- /vendor/github.com/docker/go-connections/sockets/sockets_windows.go: -------------------------------------------------------------------------------- 1 | package sockets 2 | 3 | import ( 4 | "net" 5 | "net/http" 6 | "time" 7 | 8 | "github.com/Microsoft/go-winio" 9 | ) 10 | 11 | func configureUnixTransport(tr *http.Transport, proto, addr string) error { 12 | return ErrProtocolNotAvailable 13 | } 14 | 15 | func configureNpipeTransport(tr *http.Transport, proto, addr string) error { 16 | // No need for compression in local communications. 17 | tr.DisableCompression = true 18 | tr.Dial = func(_, _ string) (net.Conn, error) { 19 | return DialPipe(addr, defaultTimeout) 20 | } 21 | return nil 22 | } 23 | 24 | // DialPipe connects to a Windows named pipe. 25 | func DialPipe(addr string, timeout time.Duration) (net.Conn, error) { 26 | return winio.DialPipe(addr, &timeout) 27 | } 28 | -------------------------------------------------------------------------------- /vendor/github.com/docker/go-connections/sockets/tcp_socket.go: -------------------------------------------------------------------------------- 1 | // Package sockets provides helper functions to create and configure Unix or TCP sockets. 2 | package sockets 3 | 4 | import ( 5 | "crypto/tls" 6 | "net" 7 | ) 8 | 9 | // NewTCPSocket creates a TCP socket listener with the specified address and 10 | // the specified tls configuration. If TLSConfig is set, will encapsulate the 11 | // TCP listener inside a TLS one. 12 | func NewTCPSocket(addr string, tlsConfig *tls.Config) (net.Listener, error) { 13 | l, err := net.Listen("tcp", addr) 14 | if err != nil { 15 | return nil, err 16 | } 17 | if tlsConfig != nil { 18 | tlsConfig.NextProtos = []string{"http/1.1"} 19 | l = tls.NewListener(l, tlsConfig) 20 | } 21 | return l, nil 22 | } 23 | -------------------------------------------------------------------------------- /vendor/github.com/docker/go-connections/sockets/unix_socket.go: -------------------------------------------------------------------------------- 1 | // +build linux freebsd solaris 2 | 3 | package sockets 4 | 5 | import ( 6 | "fmt" 7 | "net" 8 | "os" 9 | "strconv" 10 | "syscall" 11 | 12 | "github.com/Sirupsen/logrus" 13 | "github.com/opencontainers/runc/libcontainer/user" 14 | ) 15 | 16 | // NewUnixSocket creates a unix socket with the specified path and group. 17 | func NewUnixSocket(path, group string) (net.Listener, error) { 18 | if err := syscall.Unlink(path); err != nil && !os.IsNotExist(err) { 19 | return nil, err 20 | } 21 | mask := syscall.Umask(0777) 22 | defer syscall.Umask(mask) 23 | l, err := net.Listen("unix", path) 24 | if err != nil { 25 | return nil, err 26 | } 27 | if err := setSocketGroup(path, group); err != nil { 28 | l.Close() 29 | return nil, err 30 | } 31 | if err := os.Chmod(path, 0660); err != nil { 32 | l.Close() 33 | return nil, err 34 | } 35 | return l, nil 36 | } 37 | 38 | func setSocketGroup(path, group string) error { 39 | if group == "" { 40 | return nil 41 | } 42 | if err := changeGroup(path, group); err != nil { 43 | if group != "docker" { 44 | return err 45 | } 46 | logrus.Debugf("Warning: could not change group %s to docker: %v", path, err) 47 | } 48 | return nil 49 | } 50 | 51 | func changeGroup(path string, nameOrGid string) error { 52 | gid, err := lookupGidByName(nameOrGid) 53 | if err != nil { 54 | return err 55 | } 56 | logrus.Debugf("%s group found. gid: %d", nameOrGid, gid) 57 | return os.Chown(path, 0, gid) 58 | } 59 | 60 | func lookupGidByName(nameOrGid string) (int, error) { 61 | groupFile, err := user.GetGroupPath() 62 | if err != nil { 63 | return -1, err 64 | } 65 | groups, err := user.ParseGroupFileFilter(groupFile, func(g user.Group) bool { 66 | return g.Name == nameOrGid || strconv.Itoa(g.Gid) == nameOrGid 67 | }) 68 | if err != nil { 69 | return -1, err 70 | } 71 | if groups != nil && len(groups) > 0 { 72 | return groups[0].Gid, nil 73 | } 74 | gid, err := strconv.Atoi(nameOrGid) 75 | if err == nil { 76 | logrus.Warnf("Could not find GID %d", gid) 77 | return gid, nil 78 | } 79 | return -1, fmt.Errorf("Group %s not found", nameOrGid) 80 | } 81 | -------------------------------------------------------------------------------- /vendor/github.com/docker/go-plugins-helpers/NOTICE: -------------------------------------------------------------------------------- 1 | Docker 2 | Copyright 2012-2015 Docker, Inc. 3 | 4 | This product includes software developed at Docker, Inc. (https://www.docker.com). 5 | 6 | This product contains software (https://github.com/kr/pty) developed 7 | by Keith Rarick, licensed under the MIT License. 8 | 9 | The following is courtesy of our legal counsel: 10 | 11 | 12 | Use and transfer of Docker may be subject to certain restrictions by the 13 | United States and other governments. 14 | It is your responsibility to ensure that your use and/or transfer does not 15 | violate applicable laws. 16 | 17 | For more information, please see https://www.bis.doc.gov 18 | 19 | See also https://www.apache.org/dev/crypto.html and/or seek legal counsel. 20 | -------------------------------------------------------------------------------- /vendor/github.com/docker/go-plugins-helpers/network/README.md: -------------------------------------------------------------------------------- 1 | # Docker network extension API 2 | 3 | Go handler to create external network extensions for Docker. 4 | 5 | ## Usage 6 | 7 | This library is designed to be integrated in your program. 8 | 9 | 1. Implement the `network.Driver` interface. 10 | 2. Initialize a `network.Handler` with your implementation. 11 | 3. Call either `ServeTCP` or `ServeUnix` from the `network.Handler`. 12 | 13 | ### Example using TCP sockets: 14 | 15 | ```go 16 | import "github.com/docker/go-plugins-helpers/network" 17 | 18 | d := MyNetworkDriver{} 19 | h := network.NewHandler(d) 20 | h.ServeTCP("test_network", ":8080") 21 | ``` 22 | 23 | ### Example using Unix sockets: 24 | 25 | ```go 26 | import "github.com/docker/go-plugins-helpers/network" 27 | 28 | d := MyNetworkDriver{} 29 | h := network.NewHandler(d) 30 | h.ServeUnix("root", "test_network") 31 | ``` 32 | 33 | ## Full example plugins 34 | 35 | - [docker-ovs-plugin](https://github.com/gopher-net/docker-ovs-plugin) - An Open vSwitch Networking Plugin 36 | -------------------------------------------------------------------------------- /vendor/github.com/docker/go-plugins-helpers/sdk/encoder.go: -------------------------------------------------------------------------------- 1 | package sdk 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io" 7 | "io/ioutil" 8 | "net/http" 9 | ) 10 | 11 | // DefaultContentTypeV1_1 is the default content type accepted and sent by the plugins. 12 | const DefaultContentTypeV1_1 = "application/vnd.docker.plugins.v1.1+json" 13 | 14 | // DecodeRequest decodes an http request into a given structure. 15 | func DecodeRequest(w http.ResponseWriter, r *http.Request, req interface{}) (err error) { 16 | if err = json.NewDecoder(r.Body).Decode(req); err != nil { 17 | http.Error(w, err.Error(), http.StatusBadRequest) 18 | } 19 | return 20 | } 21 | 22 | // EncodeResponse encodes the given structure into an http response. 23 | func EncodeResponse(w http.ResponseWriter, res interface{}, err string) { 24 | w.Header().Set("Content-Type", DefaultContentTypeV1_1) 25 | if err != "" { 26 | w.WriteHeader(http.StatusInternalServerError) 27 | } 28 | json.NewEncoder(w).Encode(res) 29 | } 30 | 31 | // StreamResponse streams a response object to the client 32 | func StreamResponse(w http.ResponseWriter, data io.ReadCloser) { 33 | w.Header().Set("Content-Type", DefaultContentTypeV1_1) 34 | defer data.Close() 35 | byteStream, err := ioutil.ReadAll(data) 36 | if err != nil { 37 | fmt.Printf("ERROR in stream: %v\n", err) 38 | return 39 | } 40 | w.Write(byteStream) 41 | } 42 | -------------------------------------------------------------------------------- /vendor/github.com/docker/go-plugins-helpers/sdk/handler.go: -------------------------------------------------------------------------------- 1 | package sdk 2 | 3 | import ( 4 | "crypto/tls" 5 | "fmt" 6 | "net" 7 | "net/http" 8 | "os" 9 | ) 10 | 11 | const activatePath = "/Plugin.Activate" 12 | 13 | // Handler is the base to create plugin handlers. 14 | // It initializes connections and sockets to listen to. 15 | type Handler struct { 16 | mux *http.ServeMux 17 | } 18 | 19 | // NewHandler creates a new Handler with an http mux. 20 | func NewHandler(manifest string) Handler { 21 | mux := http.NewServeMux() 22 | 23 | mux.HandleFunc(activatePath, func(w http.ResponseWriter, r *http.Request) { 24 | w.Header().Set("Content-Type", DefaultContentTypeV1_1) 25 | fmt.Fprintln(w, manifest) 26 | }) 27 | 28 | return Handler{mux: mux} 29 | } 30 | 31 | // Serve sets up the handler to serve requests on the passed in listener 32 | func (h Handler) Serve(l net.Listener) error { 33 | server := http.Server{ 34 | Addr: l.Addr().String(), 35 | Handler: h.mux, 36 | } 37 | return server.Serve(l) 38 | } 39 | 40 | // ServeTCP makes the handler to listen for request in a given TCP address. 41 | // It also writes the spec file on the right directory for docker to read. 42 | func (h Handler) ServeTCP(pluginName, addr string, tlsConfig *tls.Config) error { 43 | return h.listenAndServe("tcp", addr, pluginName, tlsConfig) 44 | } 45 | 46 | // ServeUnix makes the handler to listen for requests in a unix socket. 47 | // It also creates the socket file on the right directory for docker to read. 48 | func (h Handler) ServeUnix(systemGroup, addr string) error { 49 | return h.listenAndServe("unix", addr, systemGroup, nil) 50 | } 51 | 52 | // HandleFunc registers a function to handle a request path with. 53 | func (h Handler) HandleFunc(path string, fn func(w http.ResponseWriter, r *http.Request)) { 54 | h.mux.HandleFunc(path, fn) 55 | } 56 | 57 | func (h Handler) listenAndServe(proto, addr, group string, tlsConfig *tls.Config) error { 58 | var ( 59 | err error 60 | spec string 61 | l net.Listener 62 | ) 63 | 64 | server := http.Server{ 65 | Addr: addr, 66 | Handler: h.mux, 67 | } 68 | 69 | switch proto { 70 | case "tcp": 71 | l, spec, err = newTCPListener(addr, group, tlsConfig) 72 | case "unix": 73 | l, spec, err = newUnixListener(addr, group) 74 | } 75 | 76 | if spec != "" { 77 | defer os.Remove(spec) 78 | } 79 | if err != nil { 80 | return err 81 | } 82 | 83 | return server.Serve(l) 84 | } 85 | -------------------------------------------------------------------------------- /vendor/github.com/docker/go-plugins-helpers/sdk/tcp_listener.go: -------------------------------------------------------------------------------- 1 | package sdk 2 | 3 | import ( 4 | "crypto/tls" 5 | "io/ioutil" 6 | "net" 7 | "os" 8 | "path/filepath" 9 | 10 | "github.com/docker/go-connections/sockets" 11 | ) 12 | 13 | const ( 14 | pluginSpecDir = "/etc/docker/plugins" 15 | ) 16 | 17 | func newTCPListener(address string, pluginName string, tlsConfig *tls.Config) (net.Listener, string, error) { 18 | listener, err := sockets.NewTCPSocket(address, tlsConfig) 19 | if err != nil { 20 | return nil, "", err 21 | } 22 | spec, err := writeSpec(pluginName, listener.Addr().String()) 23 | if err != nil { 24 | return nil, "", err 25 | } 26 | return listener, spec, nil 27 | } 28 | 29 | func writeSpec(name string, address string) (string, error) { 30 | if err := os.MkdirAll(pluginSpecDir, 0755); err != nil { 31 | return "", err 32 | } 33 | spec := filepath.Join(pluginSpecDir, name+".spec") 34 | url := "tcp://" + address 35 | if err := ioutil.WriteFile(spec, []byte(url), 0644); err != nil { 36 | return "", err 37 | } 38 | return spec, nil 39 | } 40 | -------------------------------------------------------------------------------- /vendor/github.com/docker/go-plugins-helpers/sdk/unix_listener.go: -------------------------------------------------------------------------------- 1 | // +build linux freebsd 2 | 3 | package sdk 4 | 5 | import ( 6 | "fmt" 7 | "net" 8 | "os" 9 | "path/filepath" 10 | 11 | "github.com/coreos/go-systemd/activation" 12 | "github.com/coreos/go-systemd/util" 13 | "github.com/docker/go-connections/sockets" 14 | ) 15 | 16 | const ( 17 | pluginSockDir = "/run/docker/plugins" 18 | ) 19 | 20 | func newUnixListener(pluginName string, group string) (net.Listener, string, error) { 21 | path, err := fullSocketAddress(pluginName) 22 | if err != nil { 23 | return nil, "", err 24 | } 25 | listener, err := setupSocketActivation() 26 | if err != nil { 27 | return nil, "", err 28 | } 29 | if listener == nil { 30 | listener, err = sockets.NewUnixSocket(path, group) 31 | if err != nil { 32 | return nil, "", err 33 | } 34 | } 35 | return listener, path, nil 36 | } 37 | 38 | func fullSocketAddress(address string) (string, error) { 39 | if err := os.MkdirAll(pluginSockDir, 0755); err != nil { 40 | return "", err 41 | } 42 | if filepath.IsAbs(address) { 43 | return address, nil 44 | } 45 | return filepath.Join(pluginSockDir, address+".sock"), nil 46 | } 47 | 48 | func setupSocketActivation() (net.Listener, error) { 49 | if !util.IsRunningSystemd() { 50 | return nil, nil 51 | } 52 | listenFds := activation.Files(false) 53 | if len(listenFds) > 1 { 54 | return nil, fmt.Errorf("expected only one socket from systemd, got %d", len(listenFds)) 55 | } 56 | var listener net.Listener 57 | if len(listenFds) == 1 { 58 | l, err := net.FileListener(listenFds[0]) 59 | if err != nil { 60 | return nil, err 61 | } 62 | listener = l 63 | } 64 | return listener, nil 65 | } 66 | -------------------------------------------------------------------------------- /vendor/github.com/docker/go-plugins-helpers/sdk/unix_listener_unsupported.go: -------------------------------------------------------------------------------- 1 | // +build !linux,!freebsd 2 | 3 | package sdk 4 | 5 | import ( 6 | "errors" 7 | "net" 8 | ) 9 | 10 | var ( 11 | errOnlySupportedOnLinuxAndFreeBSD = errors.New("unix socket creation is only supported on linux and freebsd") 12 | ) 13 | 14 | func newUnixListener(pluginName string, group string) (net.Listener, string, error) { 15 | return nil, "", errOnlySupportedOnLinuxAndFreeBSD 16 | } 17 | -------------------------------------------------------------------------------- /vendor/github.com/opencontainers/runc/NOTICE: -------------------------------------------------------------------------------- 1 | runc 2 | 3 | Copyright 2012-2015 Docker, Inc. 4 | 5 | This product includes software developed at Docker, Inc. (http://www.docker.com). 6 | 7 | The following is courtesy of our legal counsel: 8 | 9 | 10 | Use and transfer of Docker may be subject to certain restrictions by the 11 | United States and other governments. 12 | It is your responsibility to ensure that your use and/or transfer does not 13 | violate applicable laws. 14 | 15 | For more information, please see http://www.bis.doc.gov 16 | 17 | See also http://www.apache.org/dev/crypto.html and/or seek legal counsel. 18 | -------------------------------------------------------------------------------- /vendor/github.com/opencontainers/runc/libcontainer/user/MAINTAINERS: -------------------------------------------------------------------------------- 1 | Tianon Gravi (@tianon) 2 | Aleksa Sarai (@cyphar) 3 | -------------------------------------------------------------------------------- /vendor/github.com/opencontainers/runc/libcontainer/user/lookup.go: -------------------------------------------------------------------------------- 1 | package user 2 | 3 | import ( 4 | "errors" 5 | "syscall" 6 | ) 7 | 8 | var ( 9 | // The current operating system does not provide the required data for user lookups. 10 | ErrUnsupported = errors.New("user lookup: operating system does not provide passwd-formatted data") 11 | // No matching entries found in file. 12 | ErrNoPasswdEntries = errors.New("no matching entries in passwd file") 13 | ErrNoGroupEntries = errors.New("no matching entries in group file") 14 | ) 15 | 16 | func lookupUser(filter func(u User) bool) (User, error) { 17 | // Get operating system-specific passwd reader-closer. 18 | passwd, err := GetPasswd() 19 | if err != nil { 20 | return User{}, err 21 | } 22 | defer passwd.Close() 23 | 24 | // Get the users. 25 | users, err := ParsePasswdFilter(passwd, filter) 26 | if err != nil { 27 | return User{}, err 28 | } 29 | 30 | // No user entries found. 31 | if len(users) == 0 { 32 | return User{}, ErrNoPasswdEntries 33 | } 34 | 35 | // Assume the first entry is the "correct" one. 36 | return users[0], nil 37 | } 38 | 39 | // CurrentUser looks up the current user by their user id in /etc/passwd. If the 40 | // user cannot be found (or there is no /etc/passwd file on the filesystem), 41 | // then CurrentUser returns an error. 42 | func CurrentUser() (User, error) { 43 | return LookupUid(syscall.Getuid()) 44 | } 45 | 46 | // LookupUser looks up a user by their username in /etc/passwd. If the user 47 | // cannot be found (or there is no /etc/passwd file on the filesystem), then 48 | // LookupUser returns an error. 49 | func LookupUser(username string) (User, error) { 50 | return lookupUser(func(u User) bool { 51 | return u.Name == username 52 | }) 53 | } 54 | 55 | // LookupUid looks up a user by their user id in /etc/passwd. If the user cannot 56 | // be found (or there is no /etc/passwd file on the filesystem), then LookupId 57 | // returns an error. 58 | func LookupUid(uid int) (User, error) { 59 | return lookupUser(func(u User) bool { 60 | return u.Uid == uid 61 | }) 62 | } 63 | 64 | func lookupGroup(filter func(g Group) bool) (Group, error) { 65 | // Get operating system-specific group reader-closer. 66 | group, err := GetGroup() 67 | if err != nil { 68 | return Group{}, err 69 | } 70 | defer group.Close() 71 | 72 | // Get the users. 73 | groups, err := ParseGroupFilter(group, filter) 74 | if err != nil { 75 | return Group{}, err 76 | } 77 | 78 | // No user entries found. 79 | if len(groups) == 0 { 80 | return Group{}, ErrNoGroupEntries 81 | } 82 | 83 | // Assume the first entry is the "correct" one. 84 | return groups[0], nil 85 | } 86 | 87 | // CurrentGroup looks up the current user's group by their primary group id's 88 | // entry in /etc/passwd. If the group cannot be found (or there is no 89 | // /etc/group file on the filesystem), then CurrentGroup returns an error. 90 | func CurrentGroup() (Group, error) { 91 | return LookupGid(syscall.Getgid()) 92 | } 93 | 94 | // LookupGroup looks up a group by its name in /etc/group. If the group cannot 95 | // be found (or there is no /etc/group file on the filesystem), then LookupGroup 96 | // returns an error. 97 | func LookupGroup(groupname string) (Group, error) { 98 | return lookupGroup(func(g Group) bool { 99 | return g.Name == groupname 100 | }) 101 | } 102 | 103 | // LookupGid looks up a group by its group id in /etc/group. If the group cannot 104 | // be found (or there is no /etc/group file on the filesystem), then LookupGid 105 | // returns an error. 106 | func LookupGid(gid int) (Group, error) { 107 | return lookupGroup(func(g Group) bool { 108 | return g.Gid == gid 109 | }) 110 | } 111 | -------------------------------------------------------------------------------- /vendor/github.com/opencontainers/runc/libcontainer/user/lookup_unix.go: -------------------------------------------------------------------------------- 1 | // +build darwin dragonfly freebsd linux netbsd openbsd solaris 2 | 3 | package user 4 | 5 | import ( 6 | "io" 7 | "os" 8 | ) 9 | 10 | // Unix-specific path to the passwd and group formatted files. 11 | const ( 12 | unixPasswdPath = "/etc/passwd" 13 | unixGroupPath = "/etc/group" 14 | ) 15 | 16 | func GetPasswdPath() (string, error) { 17 | return unixPasswdPath, nil 18 | } 19 | 20 | func GetPasswd() (io.ReadCloser, error) { 21 | return os.Open(unixPasswdPath) 22 | } 23 | 24 | func GetGroupPath() (string, error) { 25 | return unixGroupPath, nil 26 | } 27 | 28 | func GetGroup() (io.ReadCloser, error) { 29 | return os.Open(unixGroupPath) 30 | } 31 | -------------------------------------------------------------------------------- /vendor/github.com/opencontainers/runc/libcontainer/user/lookup_unsupported.go: -------------------------------------------------------------------------------- 1 | // +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris 2 | 3 | package user 4 | 5 | import "io" 6 | 7 | func GetPasswdPath() (string, error) { 8 | return "", ErrUnsupported 9 | } 10 | 11 | func GetPasswd() (io.ReadCloser, error) { 12 | return nil, ErrUnsupported 13 | } 14 | 15 | func GetGroupPath() (string, error) { 16 | return "", ErrUnsupported 17 | } 18 | 19 | func GetGroup() (io.ReadCloser, error) { 20 | return nil, ErrUnsupported 21 | } 22 | -------------------------------------------------------------------------------- /vendor/github.com/urfave/cli/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Jeremy Saenz & Contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/github.com/urfave/cli/appveyor.yml: -------------------------------------------------------------------------------- 1 | version: "{build}" 2 | 3 | os: Windows Server 2012 R2 4 | 5 | clone_folder: c:\gopath\src\github.com\urfave\cli 6 | 7 | environment: 8 | GOPATH: C:\gopath 9 | GOVERSION: 1.6 10 | PYTHON: C:\Python27-x64 11 | PYTHON_VERSION: 2.7.x 12 | PYTHON_ARCH: 64 13 | GFMXR_DEBUG: 1 14 | 15 | install: 16 | - set PATH=%GOPATH%\bin;C:\go\bin;%PATH% 17 | - go version 18 | - go env 19 | - go get github.com/urfave/gfmxr/... 20 | - go get -v -t ./... 21 | 22 | build_script: 23 | - python runtests vet 24 | - python runtests test 25 | - python runtests gfmxr 26 | -------------------------------------------------------------------------------- /vendor/github.com/urfave/cli/category.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | // CommandCategories is a slice of *CommandCategory. 4 | type CommandCategories []*CommandCategory 5 | 6 | // CommandCategory is a category containing commands. 7 | type CommandCategory struct { 8 | Name string 9 | Commands Commands 10 | } 11 | 12 | func (c CommandCategories) Less(i, j int) bool { 13 | return c[i].Name < c[j].Name 14 | } 15 | 16 | func (c CommandCategories) Len() int { 17 | return len(c) 18 | } 19 | 20 | func (c CommandCategories) Swap(i, j int) { 21 | c[i], c[j] = c[j], c[i] 22 | } 23 | 24 | // AddCommand adds a command to a category. 25 | func (c CommandCategories) AddCommand(category string, command Command) CommandCategories { 26 | for _, commandCategory := range c { 27 | if commandCategory.Name == category { 28 | commandCategory.Commands = append(commandCategory.Commands, command) 29 | return c 30 | } 31 | } 32 | return append(c, &CommandCategory{Name: category, Commands: []Command{command}}) 33 | } 34 | 35 | // VisibleCommands returns a slice of the Commands with Hidden=false 36 | func (c *CommandCategory) VisibleCommands() []Command { 37 | ret := []Command{} 38 | for _, command := range c.Commands { 39 | if !command.Hidden { 40 | ret = append(ret, command) 41 | } 42 | } 43 | return ret 44 | } 45 | -------------------------------------------------------------------------------- /vendor/github.com/urfave/cli/cli.go: -------------------------------------------------------------------------------- 1 | // Package cli provides a minimal framework for creating and organizing command line 2 | // Go applications. cli is designed to be easy to understand and write, the most simple 3 | // cli application can be written as follows: 4 | // func main() { 5 | // cli.NewApp().Run(os.Args) 6 | // } 7 | // 8 | // Of course this application does not do much, so let's make this an actual application: 9 | // func main() { 10 | // app := cli.NewApp() 11 | // app.Name = "greet" 12 | // app.Usage = "say a greeting" 13 | // app.Action = func(c *cli.Context) error { 14 | // println("Greetings") 15 | // } 16 | // 17 | // app.Run(os.Args) 18 | // } 19 | package cli 20 | -------------------------------------------------------------------------------- /vendor/github.com/urfave/cli/errors.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "os" 7 | "strings" 8 | ) 9 | 10 | // OsExiter is the function used when the app exits. If not set defaults to os.Exit. 11 | var OsExiter = os.Exit 12 | 13 | // ErrWriter is used to write errors to the user. This can be anything 14 | // implementing the io.Writer interface and defaults to os.Stderr. 15 | var ErrWriter io.Writer = os.Stderr 16 | 17 | // MultiError is an error that wraps multiple errors. 18 | type MultiError struct { 19 | Errors []error 20 | } 21 | 22 | // NewMultiError creates a new MultiError. Pass in one or more errors. 23 | func NewMultiError(err ...error) MultiError { 24 | return MultiError{Errors: err} 25 | } 26 | 27 | // Error implents the error interface. 28 | func (m MultiError) Error() string { 29 | errs := make([]string, len(m.Errors)) 30 | for i, err := range m.Errors { 31 | errs[i] = err.Error() 32 | } 33 | 34 | return strings.Join(errs, "\n") 35 | } 36 | 37 | // ExitCoder is the interface checked by `App` and `Command` for a custom exit 38 | // code 39 | type ExitCoder interface { 40 | error 41 | ExitCode() int 42 | } 43 | 44 | // ExitError fulfills both the builtin `error` interface and `ExitCoder` 45 | type ExitError struct { 46 | exitCode int 47 | message string 48 | } 49 | 50 | // NewExitError makes a new *ExitError 51 | func NewExitError(message string, exitCode int) *ExitError { 52 | return &ExitError{ 53 | exitCode: exitCode, 54 | message: message, 55 | } 56 | } 57 | 58 | // Error returns the string message, fulfilling the interface required by 59 | // `error` 60 | func (ee *ExitError) Error() string { 61 | return ee.message 62 | } 63 | 64 | // ExitCode returns the exit code, fulfilling the interface required by 65 | // `ExitCoder` 66 | func (ee *ExitError) ExitCode() int { 67 | return ee.exitCode 68 | } 69 | 70 | // HandleExitCoder checks if the error fulfills the ExitCoder interface, and if 71 | // so prints the error to stderr (if it is non-empty) and calls OsExiter with the 72 | // given exit code. If the given error is a MultiError, then this func is 73 | // called on all members of the Errors slice. 74 | func HandleExitCoder(err error) { 75 | if err == nil { 76 | return 77 | } 78 | 79 | if exitErr, ok := err.(ExitCoder); ok { 80 | if err.Error() != "" { 81 | fmt.Fprintln(ErrWriter, err) 82 | } 83 | OsExiter(exitErr.ExitCode()) 84 | return 85 | } 86 | 87 | if multiErr, ok := err.(MultiError); ok { 88 | for _, merr := range multiErr.Errors { 89 | HandleExitCoder(merr) 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /vendor/github.com/urfave/cli/funcs.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | // BashCompleteFunc is an action to execute when the bash-completion flag is set 4 | type BashCompleteFunc func(*Context) 5 | 6 | // BeforeFunc is an action to execute before any subcommands are run, but after 7 | // the context is ready if a non-nil error is returned, no subcommands are run 8 | type BeforeFunc func(*Context) error 9 | 10 | // AfterFunc is an action to execute after any subcommands are run, but after the 11 | // subcommand has finished it is run even if Action() panics 12 | type AfterFunc func(*Context) error 13 | 14 | // ActionFunc is the action to execute when no subcommands are specified 15 | type ActionFunc func(*Context) error 16 | 17 | // CommandNotFoundFunc is executed if the proper command cannot be found 18 | type CommandNotFoundFunc func(*Context, string) 19 | 20 | // OnUsageErrorFunc is executed if an usage error occurs. This is useful for displaying 21 | // customized usage error messages. This function is able to replace the 22 | // original error messages. If this function is not set, the "Incorrect usage" 23 | // is displayed and the execution is interrupted. 24 | type OnUsageErrorFunc func(context *Context, err error, isSubcommand bool) error 25 | 26 | // FlagStringFunc is used by the help generation to display a flag, which is 27 | // expected to be a single line. 28 | type FlagStringFunc func(Flag) string 29 | -------------------------------------------------------------------------------- /vendor/github.com/urfave/cli/runtests: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from __future__ import print_function 3 | 4 | import argparse 5 | import os 6 | import sys 7 | import tempfile 8 | 9 | from subprocess import check_call, check_output 10 | 11 | 12 | PACKAGE_NAME = os.environ.get( 13 | 'CLI_PACKAGE_NAME', 'github.com/urfave/cli' 14 | ) 15 | 16 | 17 | def main(sysargs=sys.argv[:]): 18 | targets = { 19 | 'vet': _vet, 20 | 'test': _test, 21 | 'gfmxr': _gfmxr, 22 | 'toc': _toc, 23 | } 24 | 25 | parser = argparse.ArgumentParser() 26 | parser.add_argument( 27 | 'target', nargs='?', choices=tuple(targets.keys()), default='test' 28 | ) 29 | args = parser.parse_args(sysargs[1:]) 30 | 31 | targets[args.target]() 32 | return 0 33 | 34 | 35 | def _test(): 36 | if check_output('go version'.split()).split()[2] < 'go1.2': 37 | _run('go test -v .'.split()) 38 | return 39 | 40 | coverprofiles = [] 41 | for subpackage in ['', 'altsrc']: 42 | coverprofile = 'cli.coverprofile' 43 | if subpackage != '': 44 | coverprofile = '{}.coverprofile'.format(subpackage) 45 | 46 | coverprofiles.append(coverprofile) 47 | 48 | _run('go test -v'.split() + [ 49 | '-coverprofile={}'.format(coverprofile), 50 | ('{}/{}'.format(PACKAGE_NAME, subpackage)).rstrip('/') 51 | ]) 52 | 53 | combined_name = _combine_coverprofiles(coverprofiles) 54 | _run('go tool cover -func={}'.format(combined_name).split()) 55 | os.remove(combined_name) 56 | 57 | 58 | def _gfmxr(): 59 | _run(['gfmxr', '-c', str(_gfmxr_count()), '-s', 'README.md']) 60 | 61 | 62 | def _vet(): 63 | _run('go vet ./...'.split()) 64 | 65 | 66 | def _toc(): 67 | _run(['node_modules/.bin/markdown-toc', '-i', 'README.md']) 68 | _run(['git', 'diff', '--quiet']) 69 | 70 | 71 | def _run(command): 72 | print('runtests: {}'.format(' '.join(command)), file=sys.stderr) 73 | check_call(command) 74 | 75 | 76 | def _gfmxr_count(): 77 | with open('README.md') as infile: 78 | lines = infile.read().splitlines() 79 | return len(filter(_is_go_runnable, lines)) 80 | 81 | 82 | def _is_go_runnable(line): 83 | return line.startswith('package main') 84 | 85 | 86 | def _combine_coverprofiles(coverprofiles): 87 | combined = tempfile.NamedTemporaryFile( 88 | suffix='.coverprofile', delete=False 89 | ) 90 | combined.write('mode: set\n') 91 | 92 | for coverprofile in coverprofiles: 93 | with open(coverprofile, 'r') as infile: 94 | for line in infile.readlines(): 95 | if not line.startswith('mode: '): 96 | combined.write(line) 97 | 98 | combined.flush() 99 | name = combined.name 100 | combined.close() 101 | return name 102 | 103 | 104 | if __name__ == '__main__': 105 | sys.exit(main()) 106 | -------------------------------------------------------------------------------- /vendor/github.com/vishvananda/netlink/Makefile: -------------------------------------------------------------------------------- 1 | DIRS := \ 2 | . \ 3 | nl 4 | 5 | DEPS = \ 6 | github.com/vishvananda/netns 7 | 8 | uniq = $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1))) 9 | testdirs = $(call uniq,$(foreach d,$(1),$(dir $(wildcard $(d)/*_test.go)))) 10 | goroot = $(addprefix ../../../,$(1)) 11 | unroot = $(subst ../../../,,$(1)) 12 | fmt = $(addprefix fmt-,$(1)) 13 | 14 | all: test 15 | 16 | $(call goroot,$(DEPS)): 17 | go get $(call unroot,$@) 18 | 19 | .PHONY: $(call testdirs,$(DIRS)) 20 | $(call testdirs,$(DIRS)): 21 | sudo -E go test -test.parallel 4 -timeout 60s -v github.com/vishvananda/netlink/$@ 22 | 23 | $(call fmt,$(call testdirs,$(DIRS))): 24 | ! gofmt -l $(subst fmt-,,$@)/*.go | grep '' 25 | 26 | .PHONY: fmt 27 | fmt: $(call fmt,$(call testdirs,$(DIRS))) 28 | 29 | test: fmt $(call goroot,$(DEPS)) $(call testdirs,$(DIRS)) 30 | -------------------------------------------------------------------------------- /vendor/github.com/vishvananda/netlink/README.md: -------------------------------------------------------------------------------- 1 | # netlink - netlink library for go # 2 | 3 | [![Build Status](https://travis-ci.org/vishvananda/netlink.png?branch=master)](https://travis-ci.org/vishvananda/netlink) [![GoDoc](https://godoc.org/github.com/vishvananda/netlink?status.svg)](https://godoc.org/github.com/vishvananda/netlink) 4 | 5 | The netlink package provides a simple netlink library for go. Netlink 6 | is the interface a user-space program in linux uses to communicate with 7 | the kernel. It can be used to add and remove interfaces, set ip addresses 8 | and routes, and configure ipsec. Netlink communication requires elevated 9 | privileges, so in most cases this code needs to be run as root. Since 10 | low-level netlink messages are inscrutable at best, the library attempts 11 | to provide an api that is loosely modeled on the CLI provided by iproute2. 12 | Actions like `ip link add` will be accomplished via a similarly named 13 | function like AddLink(). This library began its life as a fork of the 14 | netlink functionality in 15 | [docker/libcontainer](https://github.com/docker/libcontainer) but was 16 | heavily rewritten to improve testability, performance, and to add new 17 | functionality like ipsec xfrm handling. 18 | 19 | ## Local Build and Test ## 20 | 21 | You can use go get command: 22 | 23 | go get github.com/vishvananda/netlink 24 | 25 | Testing dependencies: 26 | 27 | go get github.com/vishvananda/netns 28 | 29 | Testing (requires root): 30 | 31 | sudo -E go test github.com/vishvananda/netlink 32 | 33 | ## Examples ## 34 | 35 | Add a new bridge and add eth1 into it: 36 | 37 | ```go 38 | package main 39 | 40 | import ( 41 | "net" 42 | "github.com/vishvananda/netlink" 43 | ) 44 | 45 | func main() { 46 | la := netlink.NewLinkAttrs() 47 | la.Name = "foo" 48 | mybridge := &netlink.Bridge{la}} 49 | _ := netlink.LinkAdd(mybridge) 50 | eth1, _ := netlink.LinkByName("eth1") 51 | netlink.LinkSetMaster(eth1, mybridge) 52 | } 53 | 54 | ``` 55 | Note `NewLinkAttrs` constructor, it sets default values in structure. For now 56 | it sets only `TxQLen` to `-1`, so kernel will set default by itself. If you're 57 | using simple initialization(`LinkAttrs{Name: "foo"}`) `TxQLen` will be set to 58 | `0` unless you specify it like `LinkAttrs{Name: "foo", TxQLen: 1000}`. 59 | 60 | Add a new ip address to loopback: 61 | 62 | ```go 63 | package main 64 | 65 | import ( 66 | "net" 67 | "github.com/vishvananda/netlink" 68 | ) 69 | 70 | func main() { 71 | lo, _ := netlink.LinkByName("lo") 72 | addr, _ := netlink.ParseAddr("169.254.169.254/32") 73 | netlink.AddrAdd(lo, addr) 74 | } 75 | 76 | ``` 77 | 78 | ## Future Work ## 79 | 80 | Many pieces of netlink are not yet fully supported in the high-level 81 | interface. Aspects of virtually all of the high-level objects don't exist. 82 | Many of the underlying primitives are there, so its a matter of putting 83 | the right fields into the high-level objects and making sure that they 84 | are serialized and deserialized correctly in the Add and List methods. 85 | 86 | There are also a few pieces of low level netlink functionality that still 87 | need to be implemented. Routing rules are not in place and some of the 88 | more advanced link types. Hopefully there is decent structure and testing 89 | in place to make these fairly straightforward to add. 90 | -------------------------------------------------------------------------------- /vendor/github.com/vishvananda/netlink/addr.go: -------------------------------------------------------------------------------- 1 | package netlink 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | "strings" 7 | ) 8 | 9 | // Addr represents an IP address from netlink. Netlink ip addresses 10 | // include a mask, so it stores the address as a net.IPNet. 11 | type Addr struct { 12 | *net.IPNet 13 | Label string 14 | Flags int 15 | Scope int 16 | Peer *net.IPNet 17 | } 18 | 19 | // String returns $ip/$netmask $label 20 | func (a Addr) String() string { 21 | return strings.TrimSpace(fmt.Sprintf("%s %s", a.IPNet, a.Label)) 22 | } 23 | 24 | // ParseAddr parses the string representation of an address in the 25 | // form $ip/$netmask $label. The label portion is optional 26 | func ParseAddr(s string) (*Addr, error) { 27 | label := "" 28 | parts := strings.Split(s, " ") 29 | if len(parts) > 1 { 30 | s = parts[0] 31 | label = parts[1] 32 | } 33 | m, err := ParseIPNet(s) 34 | if err != nil { 35 | return nil, err 36 | } 37 | return &Addr{IPNet: m, Label: label}, nil 38 | } 39 | 40 | // Equal returns true if both Addrs have the same net.IPNet value. 41 | func (a Addr) Equal(x Addr) bool { 42 | sizea, _ := a.Mask.Size() 43 | sizeb, _ := x.Mask.Size() 44 | // ignore label for comparison 45 | return a.IP.Equal(x.IP) && sizea == sizeb 46 | } 47 | 48 | func (a Addr) PeerEqual(x Addr) bool { 49 | sizea, _ := a.Peer.Mask.Size() 50 | sizeb, _ := x.Peer.Mask.Size() 51 | // ignore label for comparison 52 | return a.Peer.IP.Equal(x.Peer.IP) && sizea == sizeb 53 | } 54 | -------------------------------------------------------------------------------- /vendor/github.com/vishvananda/netlink/addr_linux.go: -------------------------------------------------------------------------------- 1 | package netlink 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "net" 7 | "strings" 8 | "syscall" 9 | 10 | "github.com/vishvananda/netlink/nl" 11 | "github.com/vishvananda/netns" 12 | ) 13 | 14 | // IFA_FLAGS is a u32 attribute. 15 | const IFA_FLAGS = 0x8 16 | 17 | // AddrAdd will add an IP address to a link device. 18 | // Equivalent to: `ip addr add $addr dev $link` 19 | func AddrAdd(link Link, addr *Addr) error { 20 | return pkgHandle.AddrAdd(link, addr) 21 | } 22 | 23 | // AddrAdd will add an IP address to a link device. 24 | // Equivalent to: `ip addr add $addr dev $link` 25 | func (h *Handle) AddrAdd(link Link, addr *Addr) error { 26 | req := h.newNetlinkRequest(syscall.RTM_NEWADDR, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK) 27 | return h.addrHandle(link, addr, req) 28 | } 29 | 30 | // AddrDel will delete an IP address from a link device. 31 | // Equivalent to: `ip addr del $addr dev $link` 32 | func AddrDel(link Link, addr *Addr) error { 33 | return pkgHandle.AddrDel(link, addr) 34 | } 35 | 36 | // AddrDel will delete an IP address from a link device. 37 | // Equivalent to: `ip addr del $addr dev $link` 38 | func (h *Handle) AddrDel(link Link, addr *Addr) error { 39 | req := h.newNetlinkRequest(syscall.RTM_DELADDR, syscall.NLM_F_ACK) 40 | return h.addrHandle(link, addr, req) 41 | } 42 | 43 | func (h *Handle) addrHandle(link Link, addr *Addr, req *nl.NetlinkRequest) error { 44 | base := link.Attrs() 45 | if addr.Label != "" && !strings.HasPrefix(addr.Label, base.Name) { 46 | return fmt.Errorf("label must begin with interface name") 47 | } 48 | h.ensureIndex(base) 49 | 50 | family := nl.GetIPFamily(addr.IP) 51 | 52 | msg := nl.NewIfAddrmsg(family) 53 | msg.Index = uint32(base.Index) 54 | msg.Scope = uint8(addr.Scope) 55 | prefixlen, _ := addr.Mask.Size() 56 | msg.Prefixlen = uint8(prefixlen) 57 | req.AddData(msg) 58 | 59 | var localAddrData []byte 60 | if family == FAMILY_V4 { 61 | localAddrData = addr.IP.To4() 62 | } else { 63 | localAddrData = addr.IP.To16() 64 | } 65 | 66 | localData := nl.NewRtAttr(syscall.IFA_LOCAL, localAddrData) 67 | req.AddData(localData) 68 | var peerAddrData []byte 69 | if addr.Peer != nil { 70 | if family == FAMILY_V4 { 71 | peerAddrData = addr.Peer.IP.To4() 72 | } else { 73 | peerAddrData = addr.Peer.IP.To16() 74 | } 75 | } else { 76 | peerAddrData = localAddrData 77 | } 78 | 79 | addressData := nl.NewRtAttr(syscall.IFA_ADDRESS, peerAddrData) 80 | req.AddData(addressData) 81 | 82 | if addr.Flags != 0 { 83 | if addr.Flags <= 0xff { 84 | msg.IfAddrmsg.Flags = uint8(addr.Flags) 85 | } else { 86 | b := make([]byte, 4) 87 | native.PutUint32(b, uint32(addr.Flags)) 88 | flagsData := nl.NewRtAttr(IFA_FLAGS, b) 89 | req.AddData(flagsData) 90 | } 91 | } 92 | 93 | if addr.Label != "" { 94 | labelData := nl.NewRtAttr(syscall.IFA_LABEL, nl.ZeroTerminated(addr.Label)) 95 | req.AddData(labelData) 96 | } 97 | 98 | _, err := req.Execute(syscall.NETLINK_ROUTE, 0) 99 | return err 100 | } 101 | 102 | // AddrList gets a list of IP addresses in the system. 103 | // Equivalent to: `ip addr show`. 104 | // The list can be filtered by link and ip family. 105 | func AddrList(link Link, family int) ([]Addr, error) { 106 | return pkgHandle.AddrList(link, family) 107 | } 108 | 109 | // AddrList gets a list of IP addresses in the system. 110 | // Equivalent to: `ip addr show`. 111 | // The list can be filtered by link and ip family. 112 | func (h *Handle) AddrList(link Link, family int) ([]Addr, error) { 113 | req := h.newNetlinkRequest(syscall.RTM_GETADDR, syscall.NLM_F_DUMP) 114 | msg := nl.NewIfInfomsg(family) 115 | req.AddData(msg) 116 | 117 | msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWADDR) 118 | if err != nil { 119 | return nil, err 120 | } 121 | 122 | indexFilter := 0 123 | if link != nil { 124 | base := link.Attrs() 125 | h.ensureIndex(base) 126 | indexFilter = base.Index 127 | } 128 | 129 | var res []Addr 130 | for _, m := range msgs { 131 | addr, msgFamily, ifindex, err := parseAddr(m) 132 | if err != nil { 133 | return res, err 134 | } 135 | 136 | if link != nil && ifindex != indexFilter { 137 | // Ignore messages from other interfaces 138 | continue 139 | } 140 | 141 | if family != FAMILY_ALL && msgFamily != family { 142 | continue 143 | } 144 | 145 | res = append(res, addr) 146 | } 147 | 148 | return res, nil 149 | } 150 | 151 | func parseAddr(m []byte) (addr Addr, family, index int, err error) { 152 | msg := nl.DeserializeIfAddrmsg(m) 153 | 154 | family = -1 155 | index = -1 156 | 157 | attrs, err1 := nl.ParseRouteAttr(m[msg.Len():]) 158 | if err1 != nil { 159 | err = err1 160 | return 161 | } 162 | 163 | family = int(msg.Family) 164 | index = int(msg.Index) 165 | 166 | var local, dst *net.IPNet 167 | for _, attr := range attrs { 168 | switch attr.Attr.Type { 169 | case syscall.IFA_ADDRESS: 170 | dst = &net.IPNet{ 171 | IP: attr.Value, 172 | Mask: net.CIDRMask(int(msg.Prefixlen), 8*len(attr.Value)), 173 | } 174 | addr.Peer = dst 175 | case syscall.IFA_LOCAL: 176 | local = &net.IPNet{ 177 | IP: attr.Value, 178 | Mask: net.CIDRMask(int(msg.Prefixlen), 8*len(attr.Value)), 179 | } 180 | addr.IPNet = local 181 | case syscall.IFA_LABEL: 182 | addr.Label = string(attr.Value[:len(attr.Value)-1]) 183 | case IFA_FLAGS: 184 | addr.Flags = int(native.Uint32(attr.Value[0:4])) 185 | } 186 | } 187 | 188 | // IFA_LOCAL should be there but if not, fall back to IFA_ADDRESS 189 | if local != nil { 190 | addr.IPNet = local 191 | } else { 192 | addr.IPNet = dst 193 | } 194 | addr.Scope = int(msg.Scope) 195 | 196 | return 197 | } 198 | 199 | type AddrUpdate struct { 200 | LinkAddress net.IPNet 201 | LinkIndex int 202 | NewAddr bool // true=added false=deleted 203 | } 204 | 205 | // AddrSubscribe takes a chan down which notifications will be sent 206 | // when addresses change. Close the 'done' chan to stop subscription. 207 | func AddrSubscribe(ch chan<- AddrUpdate, done <-chan struct{}) error { 208 | return addrSubscribe(netns.None(), netns.None(), ch, done) 209 | } 210 | 211 | // AddrSubscribeAt works like AddrSubscribe plus it allows the caller 212 | // to choose the network namespace in which to subscribe (ns). 213 | func AddrSubscribeAt(ns netns.NsHandle, ch chan<- AddrUpdate, done <-chan struct{}) error { 214 | return addrSubscribe(ns, netns.None(), ch, done) 215 | } 216 | 217 | func addrSubscribe(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-chan struct{}) error { 218 | s, err := nl.SubscribeAt(newNs, curNs, syscall.NETLINK_ROUTE, syscall.RTNLGRP_IPV4_IFADDR, syscall.RTNLGRP_IPV6_IFADDR) 219 | if err != nil { 220 | return err 221 | } 222 | if done != nil { 223 | go func() { 224 | <-done 225 | s.Close() 226 | }() 227 | } 228 | go func() { 229 | defer close(ch) 230 | for { 231 | msgs, err := s.Receive() 232 | if err != nil { 233 | log.Printf("netlink.AddrSubscribe: Receive() error: %v", err) 234 | return 235 | } 236 | for _, m := range msgs { 237 | msgType := m.Header.Type 238 | if msgType != syscall.RTM_NEWADDR && msgType != syscall.RTM_DELADDR { 239 | log.Printf("netlink.AddrSubscribe: bad message type: %d", msgType) 240 | continue 241 | } 242 | 243 | addr, _, ifindex, err := parseAddr(m.Data) 244 | if err != nil { 245 | log.Printf("netlink.AddrSubscribe: could not parse address: %v", err) 246 | continue 247 | } 248 | 249 | ch <- AddrUpdate{LinkAddress: *addr.IPNet, LinkIndex: ifindex, NewAddr: msgType == syscall.RTM_NEWADDR} 250 | } 251 | } 252 | }() 253 | 254 | return nil 255 | } 256 | -------------------------------------------------------------------------------- /vendor/github.com/vishvananda/netlink/bpf_linux.go: -------------------------------------------------------------------------------- 1 | package netlink 2 | 3 | /* 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | static int load_simple_bpf(int prog_type, int ret) { 12 | #ifdef __NR_bpf 13 | // { return ret; } 14 | __u64 __attribute__((aligned(8))) insns[] = { 15 | 0x00000000000000b7ull | ((__u64)ret<<32), 16 | 0x0000000000000095ull, 17 | }; 18 | __u8 __attribute__((aligned(8))) license[] = "ASL2"; 19 | // Copied from a header file since libc is notoriously slow to update. 20 | // The call will succeed or fail and that will be our indication on 21 | // whether or not it is supported. 22 | struct { 23 | __u32 prog_type; 24 | __u32 insn_cnt; 25 | __u64 insns; 26 | __u64 license; 27 | __u32 log_level; 28 | __u32 log_size; 29 | __u64 log_buf; 30 | __u32 kern_version; 31 | } __attribute__((aligned(8))) attr = { 32 | .prog_type = prog_type, 33 | .insn_cnt = 2, 34 | .insns = (uintptr_t)&insns, 35 | .license = (uintptr_t)&license, 36 | }; 37 | return syscall(__NR_bpf, 5, &attr, sizeof(attr)); 38 | #else 39 | errno = EINVAL; 40 | return -1; 41 | #endif 42 | } 43 | */ 44 | import "C" 45 | 46 | type BpfProgType C.int 47 | 48 | const ( 49 | BPF_PROG_TYPE_UNSPEC BpfProgType = iota 50 | BPF_PROG_TYPE_SOCKET_FILTER 51 | BPF_PROG_TYPE_KPROBE 52 | BPF_PROG_TYPE_SCHED_CLS 53 | BPF_PROG_TYPE_SCHED_ACT 54 | BPF_PROG_TYPE_TRACEPOINT 55 | BPF_PROG_TYPE_XDP 56 | ) 57 | 58 | // loadSimpleBpf loads a trivial bpf program for testing purposes 59 | func loadSimpleBpf(progType BpfProgType, ret int) (int, error) { 60 | fd, err := C.load_simple_bpf(C.int(progType), C.int(ret)) 61 | return int(fd), err 62 | } 63 | -------------------------------------------------------------------------------- /vendor/github.com/vishvananda/netlink/class.go: -------------------------------------------------------------------------------- 1 | package netlink 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | type Class interface { 8 | Attrs() *ClassAttrs 9 | Type() string 10 | } 11 | 12 | // ClassAttrs represents a netlink class. A filter is associated with a link, 13 | // has a handle and a parent. The root filter of a device should have a 14 | // parent == HANDLE_ROOT. 15 | type ClassAttrs struct { 16 | LinkIndex int 17 | Handle uint32 18 | Parent uint32 19 | Leaf uint32 20 | } 21 | 22 | func (q ClassAttrs) String() string { 23 | return fmt.Sprintf("{LinkIndex: %d, Handle: %s, Parent: %s, Leaf: %d}", q.LinkIndex, HandleStr(q.Handle), HandleStr(q.Parent), q.Leaf) 24 | } 25 | 26 | type HtbClassAttrs struct { 27 | // TODO handle all attributes 28 | Rate uint64 29 | Ceil uint64 30 | Buffer uint32 31 | Cbuffer uint32 32 | Quantum uint32 33 | Level uint32 34 | Prio uint32 35 | } 36 | 37 | func (q HtbClassAttrs) String() string { 38 | return fmt.Sprintf("{Rate: %d, Ceil: %d, Buffer: %d, Cbuffer: %d}", q.Rate, q.Ceil, q.Buffer, q.Cbuffer) 39 | } 40 | 41 | // HtbClass represents an Htb class 42 | type HtbClass struct { 43 | ClassAttrs 44 | Rate uint64 45 | Ceil uint64 46 | Buffer uint32 47 | Cbuffer uint32 48 | Quantum uint32 49 | Level uint32 50 | Prio uint32 51 | } 52 | 53 | func (q HtbClass) String() string { 54 | return fmt.Sprintf("{Rate: %d, Ceil: %d, Buffer: %d, Cbuffer: %d}", q.Rate, q.Ceil, q.Buffer, q.Cbuffer) 55 | } 56 | 57 | func (q *HtbClass) Attrs() *ClassAttrs { 58 | return &q.ClassAttrs 59 | } 60 | 61 | func (q *HtbClass) Type() string { 62 | return "htb" 63 | } 64 | 65 | // GenericClass classes represent types that are not currently understood 66 | // by this netlink library. 67 | type GenericClass struct { 68 | ClassAttrs 69 | ClassType string 70 | } 71 | 72 | func (class *GenericClass) Attrs() *ClassAttrs { 73 | return &class.ClassAttrs 74 | } 75 | 76 | func (class *GenericClass) Type() string { 77 | return class.ClassType 78 | } 79 | -------------------------------------------------------------------------------- /vendor/github.com/vishvananda/netlink/class_linux.go: -------------------------------------------------------------------------------- 1 | package netlink 2 | 3 | import ( 4 | "errors" 5 | "syscall" 6 | 7 | "github.com/vishvananda/netlink/nl" 8 | ) 9 | 10 | // NOTE: function is in here because it uses other linux functions 11 | func NewHtbClass(attrs ClassAttrs, cattrs HtbClassAttrs) *HtbClass { 12 | mtu := 1600 13 | rate := cattrs.Rate / 8 14 | ceil := cattrs.Ceil / 8 15 | buffer := cattrs.Buffer 16 | cbuffer := cattrs.Cbuffer 17 | 18 | if ceil == 0 { 19 | ceil = rate 20 | } 21 | 22 | if buffer == 0 { 23 | buffer = uint32(float64(rate)/Hz() + float64(mtu)) 24 | } 25 | buffer = uint32(Xmittime(rate, buffer)) 26 | 27 | if cbuffer == 0 { 28 | cbuffer = uint32(float64(ceil)/Hz() + float64(mtu)) 29 | } 30 | cbuffer = uint32(Xmittime(ceil, cbuffer)) 31 | 32 | return &HtbClass{ 33 | ClassAttrs: attrs, 34 | Rate: rate, 35 | Ceil: ceil, 36 | Buffer: buffer, 37 | Cbuffer: cbuffer, 38 | Quantum: 10, 39 | Level: 0, 40 | Prio: 0, 41 | } 42 | } 43 | 44 | // ClassDel will delete a class from the system. 45 | // Equivalent to: `tc class del $class` 46 | func ClassDel(class Class) error { 47 | return pkgHandle.ClassDel(class) 48 | } 49 | 50 | // ClassDel will delete a class from the system. 51 | // Equivalent to: `tc class del $class` 52 | func (h *Handle) ClassDel(class Class) error { 53 | return h.classModify(syscall.RTM_DELTCLASS, 0, class) 54 | } 55 | 56 | // ClassChange will change a class in place 57 | // Equivalent to: `tc class change $class` 58 | // The parent and handle MUST NOT be changed. 59 | func ClassChange(class Class) error { 60 | return pkgHandle.ClassChange(class) 61 | } 62 | 63 | // ClassChange will change a class in place 64 | // Equivalent to: `tc class change $class` 65 | // The parent and handle MUST NOT be changed. 66 | func (h *Handle) ClassChange(class Class) error { 67 | return h.classModify(syscall.RTM_NEWTCLASS, 0, class) 68 | } 69 | 70 | // ClassReplace will replace a class to the system. 71 | // quivalent to: `tc class replace $class` 72 | // The handle MAY be changed. 73 | // If a class already exist with this parent/handle pair, the class is changed. 74 | // If a class does not already exist with this parent/handle, a new class is created. 75 | func ClassReplace(class Class) error { 76 | return pkgHandle.ClassReplace(class) 77 | } 78 | 79 | // ClassReplace will replace a class to the system. 80 | // quivalent to: `tc class replace $class` 81 | // The handle MAY be changed. 82 | // If a class already exist with this parent/handle pair, the class is changed. 83 | // If a class does not already exist with this parent/handle, a new class is created. 84 | func (h *Handle) ClassReplace(class Class) error { 85 | return h.classModify(syscall.RTM_NEWTCLASS, syscall.NLM_F_CREATE, class) 86 | } 87 | 88 | // ClassAdd will add a class to the system. 89 | // Equivalent to: `tc class add $class` 90 | func ClassAdd(class Class) error { 91 | return pkgHandle.ClassAdd(class) 92 | } 93 | 94 | // ClassAdd will add a class to the system. 95 | // Equivalent to: `tc class add $class` 96 | func (h *Handle) ClassAdd(class Class) error { 97 | return h.classModify( 98 | syscall.RTM_NEWTCLASS, 99 | syscall.NLM_F_CREATE|syscall.NLM_F_EXCL, 100 | class, 101 | ) 102 | } 103 | 104 | func (h *Handle) classModify(cmd, flags int, class Class) error { 105 | req := h.newNetlinkRequest(cmd, flags|syscall.NLM_F_ACK) 106 | base := class.Attrs() 107 | msg := &nl.TcMsg{ 108 | Family: nl.FAMILY_ALL, 109 | Ifindex: int32(base.LinkIndex), 110 | Handle: base.Handle, 111 | Parent: base.Parent, 112 | } 113 | req.AddData(msg) 114 | 115 | if cmd != syscall.RTM_DELTCLASS { 116 | if err := classPayload(req, class); err != nil { 117 | return err 118 | } 119 | } 120 | _, err := req.Execute(syscall.NETLINK_ROUTE, 0) 121 | return err 122 | } 123 | 124 | func classPayload(req *nl.NetlinkRequest, class Class) error { 125 | req.AddData(nl.NewRtAttr(nl.TCA_KIND, nl.ZeroTerminated(class.Type()))) 126 | 127 | options := nl.NewRtAttr(nl.TCA_OPTIONS, nil) 128 | if htb, ok := class.(*HtbClass); ok { 129 | opt := nl.TcHtbCopt{} 130 | opt.Buffer = htb.Buffer 131 | opt.Cbuffer = htb.Cbuffer 132 | opt.Quantum = htb.Quantum 133 | opt.Level = htb.Level 134 | opt.Prio = htb.Prio 135 | // TODO: Handle Debug properly. For now default to 0 136 | /* Calculate {R,C}Tab and set Rate and Ceil */ 137 | cellLog := -1 138 | ccellLog := -1 139 | linklayer := nl.LINKLAYER_ETHERNET 140 | mtu := 1600 141 | var rtab [256]uint32 142 | var ctab [256]uint32 143 | tcrate := nl.TcRateSpec{Rate: uint32(htb.Rate)} 144 | if CalcRtable(&tcrate, rtab, cellLog, uint32(mtu), linklayer) < 0 { 145 | return errors.New("HTB: failed to calculate rate table") 146 | } 147 | opt.Rate = tcrate 148 | tcceil := nl.TcRateSpec{Rate: uint32(htb.Ceil)} 149 | if CalcRtable(&tcceil, ctab, ccellLog, uint32(mtu), linklayer) < 0 { 150 | return errors.New("HTB: failed to calculate ceil rate table") 151 | } 152 | opt.Ceil = tcceil 153 | nl.NewRtAttrChild(options, nl.TCA_HTB_PARMS, opt.Serialize()) 154 | nl.NewRtAttrChild(options, nl.TCA_HTB_RTAB, SerializeRtab(rtab)) 155 | nl.NewRtAttrChild(options, nl.TCA_HTB_CTAB, SerializeRtab(ctab)) 156 | } 157 | req.AddData(options) 158 | return nil 159 | } 160 | 161 | // ClassList gets a list of classes in the system. 162 | // Equivalent to: `tc class show`. 163 | // Generally returns nothing if link and parent are not specified. 164 | func ClassList(link Link, parent uint32) ([]Class, error) { 165 | return pkgHandle.ClassList(link, parent) 166 | } 167 | 168 | // ClassList gets a list of classes in the system. 169 | // Equivalent to: `tc class show`. 170 | // Generally returns nothing if link and parent are not specified. 171 | func (h *Handle) ClassList(link Link, parent uint32) ([]Class, error) { 172 | req := h.newNetlinkRequest(syscall.RTM_GETTCLASS, syscall.NLM_F_DUMP) 173 | msg := &nl.TcMsg{ 174 | Family: nl.FAMILY_ALL, 175 | Parent: parent, 176 | } 177 | if link != nil { 178 | base := link.Attrs() 179 | h.ensureIndex(base) 180 | msg.Ifindex = int32(base.Index) 181 | } 182 | req.AddData(msg) 183 | 184 | msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWTCLASS) 185 | if err != nil { 186 | return nil, err 187 | } 188 | 189 | var res []Class 190 | for _, m := range msgs { 191 | msg := nl.DeserializeTcMsg(m) 192 | 193 | attrs, err := nl.ParseRouteAttr(m[msg.Len():]) 194 | if err != nil { 195 | return nil, err 196 | } 197 | 198 | base := ClassAttrs{ 199 | LinkIndex: int(msg.Ifindex), 200 | Handle: msg.Handle, 201 | Parent: msg.Parent, 202 | } 203 | 204 | var class Class 205 | classType := "" 206 | for _, attr := range attrs { 207 | switch attr.Attr.Type { 208 | case nl.TCA_KIND: 209 | classType = string(attr.Value[:len(attr.Value)-1]) 210 | switch classType { 211 | case "htb": 212 | class = &HtbClass{} 213 | default: 214 | class = &GenericClass{ClassType: classType} 215 | } 216 | case nl.TCA_OPTIONS: 217 | switch classType { 218 | case "htb": 219 | data, err := nl.ParseRouteAttr(attr.Value) 220 | if err != nil { 221 | return nil, err 222 | } 223 | _, err = parseHtbClassData(class, data) 224 | if err != nil { 225 | return nil, err 226 | } 227 | } 228 | } 229 | } 230 | *class.Attrs() = base 231 | res = append(res, class) 232 | } 233 | 234 | return res, nil 235 | } 236 | 237 | func parseHtbClassData(class Class, data []syscall.NetlinkRouteAttr) (bool, error) { 238 | htb := class.(*HtbClass) 239 | detailed := false 240 | for _, datum := range data { 241 | switch datum.Attr.Type { 242 | case nl.TCA_HTB_PARMS: 243 | opt := nl.DeserializeTcHtbCopt(datum.Value) 244 | htb.Rate = uint64(opt.Rate.Rate) 245 | htb.Ceil = uint64(opt.Ceil.Rate) 246 | htb.Buffer = opt.Buffer 247 | htb.Cbuffer = opt.Cbuffer 248 | htb.Quantum = opt.Quantum 249 | htb.Level = opt.Level 250 | htb.Prio = opt.Prio 251 | } 252 | } 253 | return detailed, nil 254 | } 255 | -------------------------------------------------------------------------------- /vendor/github.com/vishvananda/netlink/filter.go: -------------------------------------------------------------------------------- 1 | package netlink 2 | 3 | import "fmt" 4 | 5 | type Filter interface { 6 | Attrs() *FilterAttrs 7 | Type() string 8 | } 9 | 10 | // FilterAttrs represents a netlink filter. A filter is associated with a link, 11 | // has a handle and a parent. The root filter of a device should have a 12 | // parent == HANDLE_ROOT. 13 | type FilterAttrs struct { 14 | LinkIndex int 15 | Handle uint32 16 | Parent uint32 17 | Priority uint16 // lower is higher priority 18 | Protocol uint16 // syscall.ETH_P_* 19 | } 20 | 21 | func (q FilterAttrs) String() string { 22 | return fmt.Sprintf("{LinkIndex: %d, Handle: %s, Parent: %s, Priority: %d, Protocol: %d}", q.LinkIndex, HandleStr(q.Handle), HandleStr(q.Parent), q.Priority, q.Protocol) 23 | } 24 | 25 | type TcAct int32 26 | 27 | const ( 28 | TC_ACT_UNSPEC TcAct = -1 29 | TC_ACT_OK TcAct = 0 30 | TC_ACT_RECLASSIFY TcAct = 1 31 | TC_ACT_SHOT TcAct = 2 32 | TC_ACT_PIPE TcAct = 3 33 | TC_ACT_STOLEN TcAct = 4 34 | TC_ACT_QUEUED TcAct = 5 35 | TC_ACT_REPEAT TcAct = 6 36 | TC_ACT_REDIRECT TcAct = 7 37 | TC_ACT_JUMP TcAct = 0x10000000 38 | ) 39 | 40 | func (a TcAct) String() string { 41 | switch a { 42 | case TC_ACT_UNSPEC: 43 | return "unspec" 44 | case TC_ACT_OK: 45 | return "ok" 46 | case TC_ACT_RECLASSIFY: 47 | return "reclassify" 48 | case TC_ACT_SHOT: 49 | return "shot" 50 | case TC_ACT_PIPE: 51 | return "pipe" 52 | case TC_ACT_STOLEN: 53 | return "stolen" 54 | case TC_ACT_QUEUED: 55 | return "queued" 56 | case TC_ACT_REPEAT: 57 | return "repeat" 58 | case TC_ACT_REDIRECT: 59 | return "redirect" 60 | case TC_ACT_JUMP: 61 | return "jump" 62 | } 63 | return fmt.Sprintf("0x%x", int32(a)) 64 | } 65 | 66 | type TcPolAct int32 67 | 68 | const ( 69 | TC_POLICE_UNSPEC TcPolAct = TcPolAct(TC_ACT_UNSPEC) 70 | TC_POLICE_OK TcPolAct = TcPolAct(TC_ACT_OK) 71 | TC_POLICE_RECLASSIFY TcPolAct = TcPolAct(TC_ACT_RECLASSIFY) 72 | TC_POLICE_SHOT TcPolAct = TcPolAct(TC_ACT_SHOT) 73 | TC_POLICE_PIPE TcPolAct = TcPolAct(TC_ACT_PIPE) 74 | ) 75 | 76 | func (a TcPolAct) String() string { 77 | switch a { 78 | case TC_POLICE_UNSPEC: 79 | return "unspec" 80 | case TC_POLICE_OK: 81 | return "ok" 82 | case TC_POLICE_RECLASSIFY: 83 | return "reclassify" 84 | case TC_POLICE_SHOT: 85 | return "shot" 86 | case TC_POLICE_PIPE: 87 | return "pipe" 88 | } 89 | return fmt.Sprintf("0x%x", int32(a)) 90 | } 91 | 92 | type ActionAttrs struct { 93 | Index int 94 | Capab int 95 | Action TcAct 96 | Refcnt int 97 | Bindcnt int 98 | } 99 | 100 | func (q ActionAttrs) String() string { 101 | return fmt.Sprintf("{Index: %d, Capab: %x, Action: %s, Refcnt: %d, Bindcnt: %d}", q.Index, q.Capab, q.Action.String(), q.Refcnt, q.Bindcnt) 102 | } 103 | 104 | // Action represents an action in any supported filter. 105 | type Action interface { 106 | Attrs() *ActionAttrs 107 | Type() string 108 | } 109 | 110 | type GenericAction struct { 111 | ActionAttrs 112 | } 113 | 114 | func (action *GenericAction) Type() string { 115 | return "generic" 116 | } 117 | 118 | func (action *GenericAction) Attrs() *ActionAttrs { 119 | return &action.ActionAttrs 120 | } 121 | 122 | type BpfAction struct { 123 | ActionAttrs 124 | Fd int 125 | Name string 126 | } 127 | 128 | func (action *BpfAction) Type() string { 129 | return "bpf" 130 | } 131 | 132 | func (action *BpfAction) Attrs() *ActionAttrs { 133 | return &action.ActionAttrs 134 | } 135 | 136 | type MirredAct uint8 137 | 138 | func (a MirredAct) String() string { 139 | switch a { 140 | case TCA_EGRESS_REDIR: 141 | return "egress redir" 142 | case TCA_EGRESS_MIRROR: 143 | return "egress mirror" 144 | case TCA_INGRESS_REDIR: 145 | return "ingress redir" 146 | case TCA_INGRESS_MIRROR: 147 | return "ingress mirror" 148 | } 149 | return "unknown" 150 | } 151 | 152 | const ( 153 | TCA_EGRESS_REDIR MirredAct = 1 /* packet redirect to EGRESS*/ 154 | TCA_EGRESS_MIRROR MirredAct = 2 /* mirror packet to EGRESS */ 155 | TCA_INGRESS_REDIR MirredAct = 3 /* packet redirect to INGRESS*/ 156 | TCA_INGRESS_MIRROR MirredAct = 4 /* mirror packet to INGRESS */ 157 | ) 158 | 159 | type MirredAction struct { 160 | ActionAttrs 161 | MirredAction MirredAct 162 | Ifindex int 163 | } 164 | 165 | func (action *MirredAction) Type() string { 166 | return "mirred" 167 | } 168 | 169 | func (action *MirredAction) Attrs() *ActionAttrs { 170 | return &action.ActionAttrs 171 | } 172 | 173 | func NewMirredAction(redirIndex int) *MirredAction { 174 | return &MirredAction{ 175 | ActionAttrs: ActionAttrs{ 176 | Action: TC_ACT_STOLEN, 177 | }, 178 | MirredAction: TCA_EGRESS_REDIR, 179 | Ifindex: redirIndex, 180 | } 181 | } 182 | 183 | // U32 filters on many packet related properties 184 | type U32 struct { 185 | FilterAttrs 186 | ClassId uint32 187 | RedirIndex int 188 | Actions []Action 189 | } 190 | 191 | func (filter *U32) Attrs() *FilterAttrs { 192 | return &filter.FilterAttrs 193 | } 194 | 195 | func (filter *U32) Type() string { 196 | return "u32" 197 | } 198 | 199 | type FilterFwAttrs struct { 200 | ClassId uint32 201 | InDev string 202 | Mask uint32 203 | Index uint32 204 | Buffer uint32 205 | Mtu uint32 206 | Mpu uint16 207 | Rate uint32 208 | AvRate uint32 209 | PeakRate uint32 210 | Action TcPolAct 211 | Overhead uint16 212 | LinkLayer int 213 | } 214 | 215 | type BpfFilter struct { 216 | FilterAttrs 217 | ClassId uint32 218 | Fd int 219 | Name string 220 | DirectAction bool 221 | } 222 | 223 | func (filter *BpfFilter) Type() string { 224 | return "bpf" 225 | } 226 | 227 | func (filter *BpfFilter) Attrs() *FilterAttrs { 228 | return &filter.FilterAttrs 229 | } 230 | 231 | // GenericFilter filters represent types that are not currently understood 232 | // by this netlink library. 233 | type GenericFilter struct { 234 | FilterAttrs 235 | FilterType string 236 | } 237 | 238 | func (filter *GenericFilter) Attrs() *FilterAttrs { 239 | return &filter.FilterAttrs 240 | } 241 | 242 | func (filter *GenericFilter) Type() string { 243 | return filter.FilterType 244 | } 245 | -------------------------------------------------------------------------------- /vendor/github.com/vishvananda/netlink/handle_linux.go: -------------------------------------------------------------------------------- 1 | package netlink 2 | 3 | import ( 4 | "fmt" 5 | "syscall" 6 | "time" 7 | 8 | "github.com/vishvananda/netlink/nl" 9 | "github.com/vishvananda/netns" 10 | ) 11 | 12 | // Empty handle used by the netlink package methods 13 | var pkgHandle = &Handle{} 14 | 15 | // Handle is an handle for the netlink requests on a 16 | // specific network namespace. All the requests on the 17 | // same netlink family share the same netlink socket, 18 | // which gets released when the handle is deleted. 19 | type Handle struct { 20 | sockets map[int]*nl.SocketHandle 21 | lookupByDump bool 22 | } 23 | 24 | // SupportsNetlinkFamily reports whether the passed netlink family is supported by this Handle 25 | func (h *Handle) SupportsNetlinkFamily(nlFamily int) bool { 26 | _, ok := h.sockets[nlFamily] 27 | return ok 28 | } 29 | 30 | // NewHandle returns a netlink handle on the current network namespace. 31 | // Caller may specify the netlink families the handle should support. 32 | // If no families are specified, all the families the netlink package 33 | // supports will be automatically added. 34 | func NewHandle(nlFamilies ...int) (*Handle, error) { 35 | return newHandle(netns.None(), netns.None(), nlFamilies...) 36 | } 37 | 38 | // SetSocketTimeout sets the send and receive timeout for each socket in the 39 | // netlink handle. Although the socket timeout has granularity of one 40 | // microsecond, the effective granularity is floored by the kernel timer tick, 41 | // which default value is four milliseconds. 42 | func (h *Handle) SetSocketTimeout(to time.Duration) error { 43 | if to < time.Microsecond { 44 | return fmt.Errorf("invalid timeout, minimul value is %s", time.Microsecond) 45 | } 46 | tv := syscall.NsecToTimeval(to.Nanoseconds()) 47 | for _, sh := range h.sockets { 48 | fd := sh.Socket.GetFd() 49 | err := syscall.SetsockoptTimeval(fd, syscall.SOL_SOCKET, syscall.SO_RCVTIMEO, &tv) 50 | if err != nil { 51 | return err 52 | } 53 | err = syscall.SetsockoptTimeval(fd, syscall.SOL_SOCKET, syscall.SO_SNDTIMEO, &tv) 54 | if err != nil { 55 | return err 56 | } 57 | } 58 | return nil 59 | } 60 | 61 | // NewHandle returns a netlink handle on the network namespace 62 | // specified by ns. If ns=netns.None(), current network namespace 63 | // will be assumed 64 | func NewHandleAt(ns netns.NsHandle, nlFamilies ...int) (*Handle, error) { 65 | return newHandle(ns, netns.None(), nlFamilies...) 66 | } 67 | 68 | // NewHandleAtFrom works as NewHandle but allows client to specify the 69 | // new and the origin netns Handle. 70 | func NewHandleAtFrom(newNs, curNs netns.NsHandle) (*Handle, error) { 71 | return newHandle(newNs, curNs) 72 | } 73 | 74 | func newHandle(newNs, curNs netns.NsHandle, nlFamilies ...int) (*Handle, error) { 75 | h := &Handle{sockets: map[int]*nl.SocketHandle{}} 76 | fams := nl.SupportedNlFamilies 77 | if len(nlFamilies) != 0 { 78 | fams = nlFamilies 79 | } 80 | for _, f := range fams { 81 | s, err := nl.GetNetlinkSocketAt(newNs, curNs, f) 82 | if err != nil { 83 | return nil, err 84 | } 85 | h.sockets[f] = &nl.SocketHandle{Socket: s} 86 | } 87 | return h, nil 88 | } 89 | 90 | // Delete releases the resources allocated to this handle 91 | func (h *Handle) Delete() { 92 | for _, sh := range h.sockets { 93 | sh.Close() 94 | } 95 | h.sockets = nil 96 | } 97 | 98 | func (h *Handle) newNetlinkRequest(proto, flags int) *nl.NetlinkRequest { 99 | // Do this so that package API still use nl package variable nextSeqNr 100 | if h.sockets == nil { 101 | return nl.NewNetlinkRequest(proto, flags) 102 | } 103 | return &nl.NetlinkRequest{ 104 | NlMsghdr: syscall.NlMsghdr{ 105 | Len: uint32(syscall.SizeofNlMsghdr), 106 | Type: uint16(proto), 107 | Flags: syscall.NLM_F_REQUEST | uint16(flags), 108 | }, 109 | Sockets: h.sockets, 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /vendor/github.com/vishvananda/netlink/link_tuntap_linux.go: -------------------------------------------------------------------------------- 1 | package netlink 2 | 3 | // ideally golang.org/x/sys/unix would define IfReq but it only has 4 | // IFNAMSIZ, hence this minimalistic implementation 5 | const ( 6 | SizeOfIfReq = 40 7 | IFNAMSIZ = 16 8 | ) 9 | 10 | type ifReq struct { 11 | Name [IFNAMSIZ]byte 12 | Flags uint16 13 | pad [SizeOfIfReq - IFNAMSIZ - 2]byte 14 | } 15 | -------------------------------------------------------------------------------- /vendor/github.com/vishvananda/netlink/neigh.go: -------------------------------------------------------------------------------- 1 | package netlink 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | ) 7 | 8 | // Neigh represents a link layer neighbor from netlink. 9 | type Neigh struct { 10 | LinkIndex int 11 | Family int 12 | State int 13 | Type int 14 | Flags int 15 | IP net.IP 16 | HardwareAddr net.HardwareAddr 17 | } 18 | 19 | // String returns $ip/$hwaddr $label 20 | func (neigh *Neigh) String() string { 21 | return fmt.Sprintf("%s %s", neigh.IP, neigh.HardwareAddr) 22 | } 23 | -------------------------------------------------------------------------------- /vendor/github.com/vishvananda/netlink/neigh_linux.go: -------------------------------------------------------------------------------- 1 | package netlink 2 | 3 | import ( 4 | "net" 5 | "syscall" 6 | "unsafe" 7 | 8 | "github.com/vishvananda/netlink/nl" 9 | ) 10 | 11 | const ( 12 | NDA_UNSPEC = iota 13 | NDA_DST 14 | NDA_LLADDR 15 | NDA_CACHEINFO 16 | NDA_PROBES 17 | NDA_VLAN 18 | NDA_PORT 19 | NDA_VNI 20 | NDA_IFINDEX 21 | NDA_MAX = NDA_IFINDEX 22 | ) 23 | 24 | // Neighbor Cache Entry States. 25 | const ( 26 | NUD_NONE = 0x00 27 | NUD_INCOMPLETE = 0x01 28 | NUD_REACHABLE = 0x02 29 | NUD_STALE = 0x04 30 | NUD_DELAY = 0x08 31 | NUD_PROBE = 0x10 32 | NUD_FAILED = 0x20 33 | NUD_NOARP = 0x40 34 | NUD_PERMANENT = 0x80 35 | ) 36 | 37 | // Neighbor Flags 38 | const ( 39 | NTF_USE = 0x01 40 | NTF_SELF = 0x02 41 | NTF_MASTER = 0x04 42 | NTF_PROXY = 0x08 43 | NTF_ROUTER = 0x80 44 | ) 45 | 46 | type Ndmsg struct { 47 | Family uint8 48 | Index uint32 49 | State uint16 50 | Flags uint8 51 | Type uint8 52 | } 53 | 54 | func deserializeNdmsg(b []byte) *Ndmsg { 55 | var dummy Ndmsg 56 | return (*Ndmsg)(unsafe.Pointer(&b[0:unsafe.Sizeof(dummy)][0])) 57 | } 58 | 59 | func (msg *Ndmsg) Serialize() []byte { 60 | return (*(*[unsafe.Sizeof(*msg)]byte)(unsafe.Pointer(msg)))[:] 61 | } 62 | 63 | func (msg *Ndmsg) Len() int { 64 | return int(unsafe.Sizeof(*msg)) 65 | } 66 | 67 | // NeighAdd will add an IP to MAC mapping to the ARP table 68 | // Equivalent to: `ip neigh add ....` 69 | func NeighAdd(neigh *Neigh) error { 70 | return pkgHandle.NeighAdd(neigh) 71 | } 72 | 73 | // NeighAdd will add an IP to MAC mapping to the ARP table 74 | // Equivalent to: `ip neigh add ....` 75 | func (h *Handle) NeighAdd(neigh *Neigh) error { 76 | return h.neighAdd(neigh, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL) 77 | } 78 | 79 | // NeighSet will add or replace an IP to MAC mapping to the ARP table 80 | // Equivalent to: `ip neigh replace....` 81 | func NeighSet(neigh *Neigh) error { 82 | return pkgHandle.NeighSet(neigh) 83 | } 84 | 85 | // NeighSet will add or replace an IP to MAC mapping to the ARP table 86 | // Equivalent to: `ip neigh replace....` 87 | func (h *Handle) NeighSet(neigh *Neigh) error { 88 | return h.neighAdd(neigh, syscall.NLM_F_CREATE|syscall.NLM_F_REPLACE) 89 | } 90 | 91 | // NeighAppend will append an entry to FDB 92 | // Equivalent to: `bridge fdb append...` 93 | func NeighAppend(neigh *Neigh) error { 94 | return pkgHandle.NeighAppend(neigh) 95 | } 96 | 97 | // NeighAppend will append an entry to FDB 98 | // Equivalent to: `bridge fdb append...` 99 | func (h *Handle) NeighAppend(neigh *Neigh) error { 100 | return h.neighAdd(neigh, syscall.NLM_F_CREATE|syscall.NLM_F_APPEND) 101 | } 102 | 103 | // NeighAppend will append an entry to FDB 104 | // Equivalent to: `bridge fdb append...` 105 | func neighAdd(neigh *Neigh, mode int) error { 106 | return pkgHandle.neighAdd(neigh, mode) 107 | } 108 | 109 | // NeighAppend will append an entry to FDB 110 | // Equivalent to: `bridge fdb append...` 111 | func (h *Handle) neighAdd(neigh *Neigh, mode int) error { 112 | req := h.newNetlinkRequest(syscall.RTM_NEWNEIGH, mode|syscall.NLM_F_ACK) 113 | return neighHandle(neigh, req) 114 | } 115 | 116 | // NeighDel will delete an IP address from a link device. 117 | // Equivalent to: `ip addr del $addr dev $link` 118 | func NeighDel(neigh *Neigh) error { 119 | return pkgHandle.NeighDel(neigh) 120 | } 121 | 122 | // NeighDel will delete an IP address from a link device. 123 | // Equivalent to: `ip addr del $addr dev $link` 124 | func (h *Handle) NeighDel(neigh *Neigh) error { 125 | req := h.newNetlinkRequest(syscall.RTM_DELNEIGH, syscall.NLM_F_ACK) 126 | return neighHandle(neigh, req) 127 | } 128 | 129 | func neighHandle(neigh *Neigh, req *nl.NetlinkRequest) error { 130 | var family int 131 | if neigh.Family > 0 { 132 | family = neigh.Family 133 | } else { 134 | family = nl.GetIPFamily(neigh.IP) 135 | } 136 | 137 | msg := Ndmsg{ 138 | Family: uint8(family), 139 | Index: uint32(neigh.LinkIndex), 140 | State: uint16(neigh.State), 141 | Type: uint8(neigh.Type), 142 | Flags: uint8(neigh.Flags), 143 | } 144 | req.AddData(&msg) 145 | 146 | ipData := neigh.IP.To4() 147 | if ipData == nil { 148 | ipData = neigh.IP.To16() 149 | } 150 | 151 | dstData := nl.NewRtAttr(NDA_DST, ipData) 152 | req.AddData(dstData) 153 | 154 | if neigh.Flags != NTF_PROXY || neigh.HardwareAddr != nil { 155 | hwData := nl.NewRtAttr(NDA_LLADDR, []byte(neigh.HardwareAddr)) 156 | req.AddData(hwData) 157 | } 158 | 159 | _, err := req.Execute(syscall.NETLINK_ROUTE, 0) 160 | return err 161 | } 162 | 163 | // NeighList gets a list of IP-MAC mappings in the system (ARP table). 164 | // Equivalent to: `ip neighbor show`. 165 | // The list can be filtered by link and ip family. 166 | func NeighList(linkIndex, family int) ([]Neigh, error) { 167 | return pkgHandle.NeighList(linkIndex, family) 168 | } 169 | 170 | // NeighProxyList gets a list of neighbor proxies in the system. 171 | // Equivalent to: `ip neighbor show proxy`. 172 | // The list can be filtered by link and ip family. 173 | func NeighProxyList(linkIndex, family int) ([]Neigh, error) { 174 | return pkgHandle.NeighProxyList(linkIndex, family) 175 | } 176 | 177 | // NeighList gets a list of IP-MAC mappings in the system (ARP table). 178 | // Equivalent to: `ip neighbor show`. 179 | // The list can be filtered by link and ip family. 180 | func (h *Handle) NeighList(linkIndex, family int) ([]Neigh, error) { 181 | return h.neighList(linkIndex, family, 0) 182 | } 183 | 184 | // NeighProxyList gets a list of neighbor proxies in the system. 185 | // Equivalent to: `ip neighbor show proxy`. 186 | // The list can be filtered by link, ip family. 187 | func (h *Handle) NeighProxyList(linkIndex, family int) ([]Neigh, error) { 188 | return h.neighList(linkIndex, family, NTF_PROXY) 189 | } 190 | 191 | func (h *Handle) neighList(linkIndex, family, flags int) ([]Neigh, error) { 192 | req := h.newNetlinkRequest(syscall.RTM_GETNEIGH, syscall.NLM_F_DUMP) 193 | msg := Ndmsg{ 194 | Family: uint8(family), 195 | Index: uint32(linkIndex), 196 | Flags: uint8(flags), 197 | } 198 | req.AddData(&msg) 199 | 200 | msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWNEIGH) 201 | if err != nil { 202 | return nil, err 203 | } 204 | 205 | var res []Neigh 206 | for _, m := range msgs { 207 | ndm := deserializeNdmsg(m) 208 | if linkIndex != 0 && int(ndm.Index) != linkIndex { 209 | // Ignore messages from other interfaces 210 | continue 211 | } 212 | 213 | neigh, err := NeighDeserialize(m) 214 | if err != nil { 215 | continue 216 | } 217 | 218 | res = append(res, *neigh) 219 | } 220 | 221 | return res, nil 222 | } 223 | 224 | func NeighDeserialize(m []byte) (*Neigh, error) { 225 | msg := deserializeNdmsg(m) 226 | 227 | neigh := Neigh{ 228 | LinkIndex: int(msg.Index), 229 | Family: int(msg.Family), 230 | State: int(msg.State), 231 | Type: int(msg.Type), 232 | Flags: int(msg.Flags), 233 | } 234 | 235 | attrs, err := nl.ParseRouteAttr(m[msg.Len():]) 236 | if err != nil { 237 | return nil, err 238 | } 239 | 240 | for _, attr := range attrs { 241 | switch attr.Attr.Type { 242 | case NDA_DST: 243 | neigh.IP = net.IP(attr.Value) 244 | case NDA_LLADDR: 245 | neigh.HardwareAddr = net.HardwareAddr(attr.Value) 246 | } 247 | } 248 | 249 | return &neigh, nil 250 | } 251 | -------------------------------------------------------------------------------- /vendor/github.com/vishvananda/netlink/netlink.go: -------------------------------------------------------------------------------- 1 | // Package netlink provides a simple library for netlink. Netlink is 2 | // the interface a user-space program in linux uses to communicate with 3 | // the kernel. It can be used to add and remove interfaces, set up ip 4 | // addresses and routes, and confiugre ipsec. Netlink communication 5 | // requires elevated privileges, so in most cases this code needs to 6 | // be run as root. The low level primitives for netlink are contained 7 | // in the nl subpackage. This package attempts to provide a high-level 8 | // interface that is loosly modeled on the iproute2 cli. 9 | package netlink 10 | 11 | import "net" 12 | 13 | // ParseIPNet parses a string in ip/net format and returns a net.IPNet. 14 | // This is valuable because addresses in netlink are often IPNets and 15 | // ParseCIDR returns an IPNet with the IP part set to the base IP of the 16 | // range. 17 | func ParseIPNet(s string) (*net.IPNet, error) { 18 | ip, ipNet, err := net.ParseCIDR(s) 19 | if err != nil { 20 | return nil, err 21 | } 22 | return &net.IPNet{IP: ip, Mask: ipNet.Mask}, nil 23 | } 24 | 25 | // NewIPNet generates an IPNet from an ip address using a netmask of 32 or 128. 26 | func NewIPNet(ip net.IP) *net.IPNet { 27 | if ip.To4() != nil { 28 | return &net.IPNet{IP: ip, Mask: net.CIDRMask(32, 32)} 29 | } 30 | return &net.IPNet{IP: ip, Mask: net.CIDRMask(128, 128)} 31 | } 32 | -------------------------------------------------------------------------------- /vendor/github.com/vishvananda/netlink/netlink_linux.go: -------------------------------------------------------------------------------- 1 | package netlink 2 | 3 | import "github.com/vishvananda/netlink/nl" 4 | 5 | // Family type definitions 6 | const ( 7 | FAMILY_ALL = nl.FAMILY_ALL 8 | FAMILY_V4 = nl.FAMILY_V4 9 | FAMILY_V6 = nl.FAMILY_V6 10 | ) 11 | -------------------------------------------------------------------------------- /vendor/github.com/vishvananda/netlink/netlink_unspecified.go: -------------------------------------------------------------------------------- 1 | // +build !linux 2 | 3 | package netlink 4 | 5 | import ( 6 | "errors" 7 | ) 8 | 9 | var ( 10 | ErrNotImplemented = errors.New("not implemented") 11 | ) 12 | 13 | func LinkSetUp(link *Link) error { 14 | return ErrNotImplemented 15 | } 16 | 17 | func LinkSetDown(link *Link) error { 18 | return ErrNotImplemented 19 | } 20 | 21 | func LinkSetMTU(link *Link, mtu int) error { 22 | return ErrNotImplemented 23 | } 24 | 25 | func LinkSetMaster(link *Link, master *Link) error { 26 | return ErrNotImplemented 27 | } 28 | 29 | func LinkSetNsPid(link *Link, nspid int) error { 30 | return ErrNotImplemented 31 | } 32 | 33 | func LinkSetNsFd(link *Link, fd int) error { 34 | return ErrNotImplemented 35 | } 36 | 37 | func LinkAdd(link *Link) error { 38 | return ErrNotImplemented 39 | } 40 | 41 | func LinkDel(link *Link) error { 42 | return ErrNotImplemented 43 | } 44 | 45 | func SetHairpin(link Link, mode bool) error { 46 | return ErrNotImplemented 47 | } 48 | 49 | func SetGuard(link Link, mode bool) error { 50 | return ErrNotImplemented 51 | } 52 | 53 | func SetFastLeave(link Link, mode bool) error { 54 | return ErrNotImplemented 55 | } 56 | 57 | func SetLearning(link Link, mode bool) error { 58 | return ErrNotImplemented 59 | } 60 | 61 | func SetRootBlock(link Link, mode bool) error { 62 | return ErrNotImplemented 63 | } 64 | 65 | func SetFlood(link Link, mode bool) error { 66 | return ErrNotImplemented 67 | } 68 | 69 | func LinkList() ([]Link, error) { 70 | return nil, ErrNotImplemented 71 | } 72 | 73 | func AddrAdd(link *Link, addr *Addr) error { 74 | return ErrNotImplemented 75 | } 76 | 77 | func AddrDel(link *Link, addr *Addr) error { 78 | return ErrNotImplemented 79 | } 80 | 81 | func AddrList(link Link, family int) ([]Addr, error) { 82 | return nil, ErrNotImplemented 83 | } 84 | 85 | func RouteAdd(route *Route) error { 86 | return ErrNotImplemented 87 | } 88 | 89 | func RouteDel(route *Route) error { 90 | return ErrNotImplemented 91 | } 92 | 93 | func RouteList(link *Link, family int) ([]Route, error) { 94 | return nil, ErrNotImplemented 95 | } 96 | 97 | func XfrmPolicyAdd(policy *XfrmPolicy) error { 98 | return ErrNotImplemented 99 | } 100 | 101 | func XfrmPolicyDel(policy *XfrmPolicy) error { 102 | return ErrNotImplemented 103 | } 104 | 105 | func XfrmPolicyList(family int) ([]XfrmPolicy, error) { 106 | return nil, ErrNotImplemented 107 | } 108 | 109 | func XfrmStateAdd(policy *XfrmState) error { 110 | return ErrNotImplemented 111 | } 112 | 113 | func XfrmStateDel(policy *XfrmState) error { 114 | return ErrNotImplemented 115 | } 116 | 117 | func XfrmStateList(family int) ([]XfrmState, error) { 118 | return nil, ErrNotImplemented 119 | } 120 | 121 | func NeighAdd(neigh *Neigh) error { 122 | return ErrNotImplemented 123 | } 124 | 125 | func NeighSet(neigh *Neigh) error { 126 | return ErrNotImplemented 127 | } 128 | 129 | func NeighAppend(neigh *Neigh) error { 130 | return ErrNotImplemented 131 | } 132 | 133 | func NeighDel(neigh *Neigh) error { 134 | return ErrNotImplemented 135 | } 136 | 137 | func NeighList(linkIndex, family int) ([]Neigh, error) { 138 | return nil, ErrNotImplemented 139 | } 140 | 141 | func NeighDeserialize(m []byte) (*Neigh, error) { 142 | return nil, ErrNotImplemented 143 | } 144 | -------------------------------------------------------------------------------- /vendor/github.com/vishvananda/netlink/nl/addr_linux.go: -------------------------------------------------------------------------------- 1 | package nl 2 | 3 | import ( 4 | "syscall" 5 | "unsafe" 6 | ) 7 | 8 | type IfAddrmsg struct { 9 | syscall.IfAddrmsg 10 | } 11 | 12 | func NewIfAddrmsg(family int) *IfAddrmsg { 13 | return &IfAddrmsg{ 14 | IfAddrmsg: syscall.IfAddrmsg{ 15 | Family: uint8(family), 16 | }, 17 | } 18 | } 19 | 20 | // struct ifaddrmsg { 21 | // __u8 ifa_family; 22 | // __u8 ifa_prefixlen; /* The prefix length */ 23 | // __u8 ifa_flags; /* Flags */ 24 | // __u8 ifa_scope; /* Address scope */ 25 | // __u32 ifa_index; /* Link index */ 26 | // }; 27 | 28 | // type IfAddrmsg struct { 29 | // Family uint8 30 | // Prefixlen uint8 31 | // Flags uint8 32 | // Scope uint8 33 | // Index uint32 34 | // } 35 | // SizeofIfAddrmsg = 0x8 36 | 37 | func DeserializeIfAddrmsg(b []byte) *IfAddrmsg { 38 | return (*IfAddrmsg)(unsafe.Pointer(&b[0:syscall.SizeofIfAddrmsg][0])) 39 | } 40 | 41 | func (msg *IfAddrmsg) Serialize() []byte { 42 | return (*(*[syscall.SizeofIfAddrmsg]byte)(unsafe.Pointer(msg)))[:] 43 | } 44 | 45 | func (msg *IfAddrmsg) Len() int { 46 | return syscall.SizeofIfAddrmsg 47 | } 48 | -------------------------------------------------------------------------------- /vendor/github.com/vishvananda/netlink/nl/route_linux.go: -------------------------------------------------------------------------------- 1 | package nl 2 | 3 | import ( 4 | "syscall" 5 | "unsafe" 6 | ) 7 | 8 | type RtMsg struct { 9 | syscall.RtMsg 10 | } 11 | 12 | func NewRtMsg() *RtMsg { 13 | return &RtMsg{ 14 | RtMsg: syscall.RtMsg{ 15 | Table: syscall.RT_TABLE_MAIN, 16 | Scope: syscall.RT_SCOPE_UNIVERSE, 17 | Protocol: syscall.RTPROT_BOOT, 18 | Type: syscall.RTN_UNICAST, 19 | }, 20 | } 21 | } 22 | 23 | func NewRtDelMsg() *RtMsg { 24 | return &RtMsg{ 25 | RtMsg: syscall.RtMsg{ 26 | Table: syscall.RT_TABLE_MAIN, 27 | Scope: syscall.RT_SCOPE_NOWHERE, 28 | }, 29 | } 30 | } 31 | 32 | func (msg *RtMsg) Len() int { 33 | return syscall.SizeofRtMsg 34 | } 35 | 36 | func DeserializeRtMsg(b []byte) *RtMsg { 37 | return (*RtMsg)(unsafe.Pointer(&b[0:syscall.SizeofRtMsg][0])) 38 | } 39 | 40 | func (msg *RtMsg) Serialize() []byte { 41 | return (*(*[syscall.SizeofRtMsg]byte)(unsafe.Pointer(msg)))[:] 42 | } 43 | 44 | type RtNexthop struct { 45 | syscall.RtNexthop 46 | } 47 | 48 | func DeserializeRtNexthop(b []byte) *RtNexthop { 49 | return (*RtNexthop)(unsafe.Pointer(&b[0:syscall.SizeofRtNexthop][0])) 50 | } 51 | 52 | func (msg *RtNexthop) Serialize() []byte { 53 | return (*(*[syscall.SizeofRtNexthop]byte)(unsafe.Pointer(msg)))[:] 54 | } 55 | -------------------------------------------------------------------------------- /vendor/github.com/vishvananda/netlink/nl/syscall.go: -------------------------------------------------------------------------------- 1 | package nl 2 | 3 | // syscall package lack of rule atributes type. 4 | // Thus there are defined below 5 | const ( 6 | FRA_UNSPEC = iota 7 | FRA_DST /* destination address */ 8 | FRA_SRC /* source address */ 9 | FRA_IIFNAME /* interface name */ 10 | FRA_GOTO /* target to jump to (FR_ACT_GOTO) */ 11 | FRA_UNUSED2 12 | FRA_PRIORITY /* priority/preference */ 13 | FRA_UNUSED3 14 | FRA_UNUSED4 15 | FRA_UNUSED5 16 | FRA_FWMARK /* mark */ 17 | FRA_FLOW /* flow/class id */ 18 | FRA_TUN_ID 19 | FRA_SUPPRESS_IFGROUP 20 | FRA_SUPPRESS_PREFIXLEN 21 | FRA_TABLE /* Extended table id */ 22 | FRA_FWMASK /* mask for netfilter mark */ 23 | FRA_OIFNAME 24 | ) 25 | 26 | // ip rule netlink request types 27 | const ( 28 | FR_ACT_UNSPEC = iota 29 | FR_ACT_TO_TBL /* Pass to fixed table */ 30 | FR_ACT_GOTO /* Jump to another rule */ 31 | FR_ACT_NOP /* No operation */ 32 | FR_ACT_RES3 33 | FR_ACT_RES4 34 | FR_ACT_BLACKHOLE /* Drop without notification */ 35 | FR_ACT_UNREACHABLE /* Drop with ENETUNREACH */ 36 | FR_ACT_PROHIBIT /* Drop with EACCES */ 37 | ) 38 | -------------------------------------------------------------------------------- /vendor/github.com/vishvananda/netlink/nl/xfrm_policy_linux.go: -------------------------------------------------------------------------------- 1 | package nl 2 | 3 | import ( 4 | "unsafe" 5 | ) 6 | 7 | const ( 8 | SizeofXfrmUserpolicyId = 0x40 9 | SizeofXfrmUserpolicyInfo = 0xa8 10 | SizeofXfrmUserTmpl = 0x40 11 | ) 12 | 13 | // struct xfrm_userpolicy_id { 14 | // struct xfrm_selector sel; 15 | // __u32 index; 16 | // __u8 dir; 17 | // }; 18 | // 19 | 20 | type XfrmUserpolicyId struct { 21 | Sel XfrmSelector 22 | Index uint32 23 | Dir uint8 24 | Pad [3]byte 25 | } 26 | 27 | func (msg *XfrmUserpolicyId) Len() int { 28 | return SizeofXfrmUserpolicyId 29 | } 30 | 31 | func DeserializeXfrmUserpolicyId(b []byte) *XfrmUserpolicyId { 32 | return (*XfrmUserpolicyId)(unsafe.Pointer(&b[0:SizeofXfrmUserpolicyId][0])) 33 | } 34 | 35 | func (msg *XfrmUserpolicyId) Serialize() []byte { 36 | return (*(*[SizeofXfrmUserpolicyId]byte)(unsafe.Pointer(msg)))[:] 37 | } 38 | 39 | // struct xfrm_userpolicy_info { 40 | // struct xfrm_selector sel; 41 | // struct xfrm_lifetime_cfg lft; 42 | // struct xfrm_lifetime_cur curlft; 43 | // __u32 priority; 44 | // __u32 index; 45 | // __u8 dir; 46 | // __u8 action; 47 | // #define XFRM_POLICY_ALLOW 0 48 | // #define XFRM_POLICY_BLOCK 1 49 | // __u8 flags; 50 | // #define XFRM_POLICY_LOCALOK 1 /* Allow user to override global policy */ 51 | // /* Automatically expand selector to include matching ICMP payloads. */ 52 | // #define XFRM_POLICY_ICMP 2 53 | // __u8 share; 54 | // }; 55 | 56 | type XfrmUserpolicyInfo struct { 57 | Sel XfrmSelector 58 | Lft XfrmLifetimeCfg 59 | Curlft XfrmLifetimeCur 60 | Priority uint32 61 | Index uint32 62 | Dir uint8 63 | Action uint8 64 | Flags uint8 65 | Share uint8 66 | Pad [4]byte 67 | } 68 | 69 | func (msg *XfrmUserpolicyInfo) Len() int { 70 | return SizeofXfrmUserpolicyInfo 71 | } 72 | 73 | func DeserializeXfrmUserpolicyInfo(b []byte) *XfrmUserpolicyInfo { 74 | return (*XfrmUserpolicyInfo)(unsafe.Pointer(&b[0:SizeofXfrmUserpolicyInfo][0])) 75 | } 76 | 77 | func (msg *XfrmUserpolicyInfo) Serialize() []byte { 78 | return (*(*[SizeofXfrmUserpolicyInfo]byte)(unsafe.Pointer(msg)))[:] 79 | } 80 | 81 | // struct xfrm_user_tmpl { 82 | // struct xfrm_id id; 83 | // __u16 family; 84 | // xfrm_address_t saddr; 85 | // __u32 reqid; 86 | // __u8 mode; 87 | // __u8 share; 88 | // __u8 optional; 89 | // __u32 aalgos; 90 | // __u32 ealgos; 91 | // __u32 calgos; 92 | // } 93 | 94 | type XfrmUserTmpl struct { 95 | XfrmId XfrmId 96 | Family uint16 97 | Pad1 [2]byte 98 | Saddr XfrmAddress 99 | Reqid uint32 100 | Mode uint8 101 | Share uint8 102 | Optional uint8 103 | Pad2 byte 104 | Aalgos uint32 105 | Ealgos uint32 106 | Calgos uint32 107 | } 108 | 109 | func (msg *XfrmUserTmpl) Len() int { 110 | return SizeofXfrmUserTmpl 111 | } 112 | 113 | func DeserializeXfrmUserTmpl(b []byte) *XfrmUserTmpl { 114 | return (*XfrmUserTmpl)(unsafe.Pointer(&b[0:SizeofXfrmUserTmpl][0])) 115 | } 116 | 117 | func (msg *XfrmUserTmpl) Serialize() []byte { 118 | return (*(*[SizeofXfrmUserTmpl]byte)(unsafe.Pointer(msg)))[:] 119 | } 120 | -------------------------------------------------------------------------------- /vendor/github.com/vishvananda/netlink/nl/xfrm_state_linux.go: -------------------------------------------------------------------------------- 1 | package nl 2 | 3 | import ( 4 | "unsafe" 5 | ) 6 | 7 | const ( 8 | SizeofXfrmUsersaId = 0x18 9 | SizeofXfrmStats = 0x0c 10 | SizeofXfrmUsersaInfo = 0xe0 11 | SizeofXfrmAlgo = 0x44 12 | SizeofXfrmAlgoAuth = 0x48 13 | SizeofXfrmAlgoAEAD = 0x48 14 | SizeofXfrmEncapTmpl = 0x18 15 | SizeofXfrmUsersaFlush = 0x8 16 | ) 17 | 18 | // struct xfrm_usersa_id { 19 | // xfrm_address_t daddr; 20 | // __be32 spi; 21 | // __u16 family; 22 | // __u8 proto; 23 | // }; 24 | 25 | type XfrmUsersaId struct { 26 | Daddr XfrmAddress 27 | Spi uint32 // big endian 28 | Family uint16 29 | Proto uint8 30 | Pad byte 31 | } 32 | 33 | func (msg *XfrmUsersaId) Len() int { 34 | return SizeofXfrmUsersaId 35 | } 36 | 37 | func DeserializeXfrmUsersaId(b []byte) *XfrmUsersaId { 38 | return (*XfrmUsersaId)(unsafe.Pointer(&b[0:SizeofXfrmUsersaId][0])) 39 | } 40 | 41 | func (msg *XfrmUsersaId) Serialize() []byte { 42 | return (*(*[SizeofXfrmUsersaId]byte)(unsafe.Pointer(msg)))[:] 43 | } 44 | 45 | // struct xfrm_stats { 46 | // __u32 replay_window; 47 | // __u32 replay; 48 | // __u32 integrity_failed; 49 | // }; 50 | 51 | type XfrmStats struct { 52 | ReplayWindow uint32 53 | Replay uint32 54 | IntegrityFailed uint32 55 | } 56 | 57 | func (msg *XfrmStats) Len() int { 58 | return SizeofXfrmStats 59 | } 60 | 61 | func DeserializeXfrmStats(b []byte) *XfrmStats { 62 | return (*XfrmStats)(unsafe.Pointer(&b[0:SizeofXfrmStats][0])) 63 | } 64 | 65 | func (msg *XfrmStats) Serialize() []byte { 66 | return (*(*[SizeofXfrmStats]byte)(unsafe.Pointer(msg)))[:] 67 | } 68 | 69 | // struct xfrm_usersa_info { 70 | // struct xfrm_selector sel; 71 | // struct xfrm_id id; 72 | // xfrm_address_t saddr; 73 | // struct xfrm_lifetime_cfg lft; 74 | // struct xfrm_lifetime_cur curlft; 75 | // struct xfrm_stats stats; 76 | // __u32 seq; 77 | // __u32 reqid; 78 | // __u16 family; 79 | // __u8 mode; /* XFRM_MODE_xxx */ 80 | // __u8 replay_window; 81 | // __u8 flags; 82 | // #define XFRM_STATE_NOECN 1 83 | // #define XFRM_STATE_DECAP_DSCP 2 84 | // #define XFRM_STATE_NOPMTUDISC 4 85 | // #define XFRM_STATE_WILDRECV 8 86 | // #define XFRM_STATE_ICMP 16 87 | // #define XFRM_STATE_AF_UNSPEC 32 88 | // #define XFRM_STATE_ALIGN4 64 89 | // #define XFRM_STATE_ESN 128 90 | // }; 91 | // 92 | // #define XFRM_SA_XFLAG_DONT_ENCAP_DSCP 1 93 | // 94 | 95 | type XfrmUsersaInfo struct { 96 | Sel XfrmSelector 97 | Id XfrmId 98 | Saddr XfrmAddress 99 | Lft XfrmLifetimeCfg 100 | Curlft XfrmLifetimeCur 101 | Stats XfrmStats 102 | Seq uint32 103 | Reqid uint32 104 | Family uint16 105 | Mode uint8 106 | ReplayWindow uint8 107 | Flags uint8 108 | Pad [7]byte 109 | } 110 | 111 | func (msg *XfrmUsersaInfo) Len() int { 112 | return SizeofXfrmUsersaInfo 113 | } 114 | 115 | func DeserializeXfrmUsersaInfo(b []byte) *XfrmUsersaInfo { 116 | return (*XfrmUsersaInfo)(unsafe.Pointer(&b[0:SizeofXfrmUsersaInfo][0])) 117 | } 118 | 119 | func (msg *XfrmUsersaInfo) Serialize() []byte { 120 | return (*(*[SizeofXfrmUsersaInfo]byte)(unsafe.Pointer(msg)))[:] 121 | } 122 | 123 | // struct xfrm_algo { 124 | // char alg_name[64]; 125 | // unsigned int alg_key_len; /* in bits */ 126 | // char alg_key[0]; 127 | // }; 128 | 129 | type XfrmAlgo struct { 130 | AlgName [64]byte 131 | AlgKeyLen uint32 132 | AlgKey []byte 133 | } 134 | 135 | func (msg *XfrmAlgo) Len() int { 136 | return SizeofXfrmAlgo + int(msg.AlgKeyLen/8) 137 | } 138 | 139 | func DeserializeXfrmAlgo(b []byte) *XfrmAlgo { 140 | ret := XfrmAlgo{} 141 | copy(ret.AlgName[:], b[0:64]) 142 | ret.AlgKeyLen = *(*uint32)(unsafe.Pointer(&b[64])) 143 | ret.AlgKey = b[68:ret.Len()] 144 | return &ret 145 | } 146 | 147 | func (msg *XfrmAlgo) Serialize() []byte { 148 | b := make([]byte, msg.Len()) 149 | copy(b[0:64], msg.AlgName[:]) 150 | copy(b[64:68], (*(*[4]byte)(unsafe.Pointer(&msg.AlgKeyLen)))[:]) 151 | copy(b[68:msg.Len()], msg.AlgKey[:]) 152 | return b 153 | } 154 | 155 | // struct xfrm_algo_auth { 156 | // char alg_name[64]; 157 | // unsigned int alg_key_len; /* in bits */ 158 | // unsigned int alg_trunc_len; /* in bits */ 159 | // char alg_key[0]; 160 | // }; 161 | 162 | type XfrmAlgoAuth struct { 163 | AlgName [64]byte 164 | AlgKeyLen uint32 165 | AlgTruncLen uint32 166 | AlgKey []byte 167 | } 168 | 169 | func (msg *XfrmAlgoAuth) Len() int { 170 | return SizeofXfrmAlgoAuth + int(msg.AlgKeyLen/8) 171 | } 172 | 173 | func DeserializeXfrmAlgoAuth(b []byte) *XfrmAlgoAuth { 174 | ret := XfrmAlgoAuth{} 175 | copy(ret.AlgName[:], b[0:64]) 176 | ret.AlgKeyLen = *(*uint32)(unsafe.Pointer(&b[64])) 177 | ret.AlgTruncLen = *(*uint32)(unsafe.Pointer(&b[68])) 178 | ret.AlgKey = b[72:ret.Len()] 179 | return &ret 180 | } 181 | 182 | func (msg *XfrmAlgoAuth) Serialize() []byte { 183 | b := make([]byte, msg.Len()) 184 | copy(b[0:64], msg.AlgName[:]) 185 | copy(b[64:68], (*(*[4]byte)(unsafe.Pointer(&msg.AlgKeyLen)))[:]) 186 | copy(b[68:72], (*(*[4]byte)(unsafe.Pointer(&msg.AlgTruncLen)))[:]) 187 | copy(b[72:msg.Len()], msg.AlgKey[:]) 188 | return b 189 | } 190 | 191 | // struct xfrm_algo_aead { 192 | // char alg_name[64]; 193 | // unsigned int alg_key_len; /* in bits */ 194 | // unsigned int alg_icv_len; /* in bits */ 195 | // char alg_key[0]; 196 | // } 197 | 198 | type XfrmAlgoAEAD struct { 199 | AlgName [64]byte 200 | AlgKeyLen uint32 201 | AlgICVLen uint32 202 | AlgKey []byte 203 | } 204 | 205 | func (msg *XfrmAlgoAEAD) Len() int { 206 | return SizeofXfrmAlgoAEAD + int(msg.AlgKeyLen/8) 207 | } 208 | 209 | func DeserializeXfrmAlgoAEAD(b []byte) *XfrmAlgoAEAD { 210 | ret := XfrmAlgoAEAD{} 211 | copy(ret.AlgName[:], b[0:64]) 212 | ret.AlgKeyLen = *(*uint32)(unsafe.Pointer(&b[64])) 213 | ret.AlgICVLen = *(*uint32)(unsafe.Pointer(&b[68])) 214 | ret.AlgKey = b[72:ret.Len()] 215 | return &ret 216 | } 217 | 218 | func (msg *XfrmAlgoAEAD) Serialize() []byte { 219 | b := make([]byte, msg.Len()) 220 | copy(b[0:64], msg.AlgName[:]) 221 | copy(b[64:68], (*(*[4]byte)(unsafe.Pointer(&msg.AlgKeyLen)))[:]) 222 | copy(b[68:72], (*(*[4]byte)(unsafe.Pointer(&msg.AlgICVLen)))[:]) 223 | copy(b[72:msg.Len()], msg.AlgKey[:]) 224 | return b 225 | } 226 | 227 | // struct xfrm_encap_tmpl { 228 | // __u16 encap_type; 229 | // __be16 encap_sport; 230 | // __be16 encap_dport; 231 | // xfrm_address_t encap_oa; 232 | // }; 233 | 234 | type XfrmEncapTmpl struct { 235 | EncapType uint16 236 | EncapSport uint16 // big endian 237 | EncapDport uint16 // big endian 238 | Pad [2]byte 239 | EncapOa XfrmAddress 240 | } 241 | 242 | func (msg *XfrmEncapTmpl) Len() int { 243 | return SizeofXfrmEncapTmpl 244 | } 245 | 246 | func DeserializeXfrmEncapTmpl(b []byte) *XfrmEncapTmpl { 247 | return (*XfrmEncapTmpl)(unsafe.Pointer(&b[0:SizeofXfrmEncapTmpl][0])) 248 | } 249 | 250 | func (msg *XfrmEncapTmpl) Serialize() []byte { 251 | return (*(*[SizeofXfrmEncapTmpl]byte)(unsafe.Pointer(msg)))[:] 252 | } 253 | 254 | // struct xfrm_usersa_flush { 255 | // __u8 proto; 256 | // }; 257 | 258 | type XfrmUsersaFlush struct { 259 | Proto uint8 260 | } 261 | 262 | func (msg *XfrmUsersaFlush) Len() int { 263 | return SizeofXfrmUsersaFlush 264 | } 265 | 266 | func DeserializeXfrmUsersaFlush(b []byte) *XfrmUsersaFlush { 267 | return (*XfrmUsersaFlush)(unsafe.Pointer(&b[0:SizeofXfrmUsersaFlush][0])) 268 | } 269 | 270 | func (msg *XfrmUsersaFlush) Serialize() []byte { 271 | return (*(*[SizeofXfrmUsersaFlush]byte)(unsafe.Pointer(msg)))[:] 272 | } 273 | -------------------------------------------------------------------------------- /vendor/github.com/vishvananda/netlink/protinfo.go: -------------------------------------------------------------------------------- 1 | package netlink 2 | 3 | import ( 4 | "strings" 5 | ) 6 | 7 | // Protinfo represents bridge flags from netlink. 8 | type Protinfo struct { 9 | Hairpin bool 10 | Guard bool 11 | FastLeave bool 12 | RootBlock bool 13 | Learning bool 14 | Flood bool 15 | } 16 | 17 | // String returns a list of enabled flags 18 | func (prot *Protinfo) String() string { 19 | var boolStrings []string 20 | if prot.Hairpin { 21 | boolStrings = append(boolStrings, "Hairpin") 22 | } 23 | if prot.Guard { 24 | boolStrings = append(boolStrings, "Guard") 25 | } 26 | if prot.FastLeave { 27 | boolStrings = append(boolStrings, "FastLeave") 28 | } 29 | if prot.RootBlock { 30 | boolStrings = append(boolStrings, "RootBlock") 31 | } 32 | if prot.Learning { 33 | boolStrings = append(boolStrings, "Learning") 34 | } 35 | if prot.Flood { 36 | boolStrings = append(boolStrings, "Flood") 37 | } 38 | return strings.Join(boolStrings, " ") 39 | } 40 | 41 | func boolToByte(x bool) []byte { 42 | if x { 43 | return []byte{1} 44 | } 45 | return []byte{0} 46 | } 47 | 48 | func byteToBool(x byte) bool { 49 | if uint8(x) != 0 { 50 | return true 51 | } 52 | return false 53 | } 54 | -------------------------------------------------------------------------------- /vendor/github.com/vishvananda/netlink/protinfo_linux.go: -------------------------------------------------------------------------------- 1 | package netlink 2 | 3 | import ( 4 | "fmt" 5 | "syscall" 6 | 7 | "github.com/vishvananda/netlink/nl" 8 | ) 9 | 10 | func LinkGetProtinfo(link Link) (Protinfo, error) { 11 | return pkgHandle.LinkGetProtinfo(link) 12 | } 13 | 14 | func (h *Handle) LinkGetProtinfo(link Link) (Protinfo, error) { 15 | base := link.Attrs() 16 | h.ensureIndex(base) 17 | var pi Protinfo 18 | req := h.newNetlinkRequest(syscall.RTM_GETLINK, syscall.NLM_F_DUMP) 19 | msg := nl.NewIfInfomsg(syscall.AF_BRIDGE) 20 | req.AddData(msg) 21 | msgs, err := req.Execute(syscall.NETLINK_ROUTE, 0) 22 | if err != nil { 23 | return pi, err 24 | } 25 | 26 | for _, m := range msgs { 27 | ans := nl.DeserializeIfInfomsg(m) 28 | if int(ans.Index) != base.Index { 29 | continue 30 | } 31 | attrs, err := nl.ParseRouteAttr(m[ans.Len():]) 32 | if err != nil { 33 | return pi, err 34 | } 35 | for _, attr := range attrs { 36 | if attr.Attr.Type != syscall.IFLA_PROTINFO|syscall.NLA_F_NESTED { 37 | continue 38 | } 39 | infos, err := nl.ParseRouteAttr(attr.Value) 40 | if err != nil { 41 | return pi, err 42 | } 43 | var pi Protinfo 44 | for _, info := range infos { 45 | switch info.Attr.Type { 46 | case nl.IFLA_BRPORT_MODE: 47 | pi.Hairpin = byteToBool(info.Value[0]) 48 | case nl.IFLA_BRPORT_GUARD: 49 | pi.Guard = byteToBool(info.Value[0]) 50 | case nl.IFLA_BRPORT_FAST_LEAVE: 51 | pi.FastLeave = byteToBool(info.Value[0]) 52 | case nl.IFLA_BRPORT_PROTECT: 53 | pi.RootBlock = byteToBool(info.Value[0]) 54 | case nl.IFLA_BRPORT_LEARNING: 55 | pi.Learning = byteToBool(info.Value[0]) 56 | case nl.IFLA_BRPORT_UNICAST_FLOOD: 57 | pi.Flood = byteToBool(info.Value[0]) 58 | } 59 | } 60 | return pi, nil 61 | } 62 | } 63 | return pi, fmt.Errorf("Device with index %d not found", base.Index) 64 | } 65 | -------------------------------------------------------------------------------- /vendor/github.com/vishvananda/netlink/qdisc.go: -------------------------------------------------------------------------------- 1 | package netlink 2 | 3 | import ( 4 | "fmt" 5 | "math" 6 | ) 7 | 8 | const ( 9 | HANDLE_NONE = 0 10 | HANDLE_INGRESS = 0xFFFFFFF1 11 | HANDLE_CLSACT = HANDLE_INGRESS 12 | HANDLE_ROOT = 0xFFFFFFFF 13 | PRIORITY_MAP_LEN = 16 14 | ) 15 | const ( 16 | HANDLE_MIN_INGRESS = 0xFFFFFFF2 17 | HANDLE_MIN_EGRESS = 0xFFFFFFF3 18 | ) 19 | 20 | type Qdisc interface { 21 | Attrs() *QdiscAttrs 22 | Type() string 23 | } 24 | 25 | // QdiscAttrs represents a netlink qdisc. A qdisc is associated with a link, 26 | // has a handle, a parent and a refcnt. The root qdisc of a device should 27 | // have parent == HANDLE_ROOT. 28 | type QdiscAttrs struct { 29 | LinkIndex int 30 | Handle uint32 31 | Parent uint32 32 | Refcnt uint32 // read only 33 | } 34 | 35 | func (q QdiscAttrs) String() string { 36 | return fmt.Sprintf("{LinkIndex: %d, Handle: %s, Parent: %s, Refcnt: %d}", q.LinkIndex, HandleStr(q.Handle), HandleStr(q.Parent), q.Refcnt) 37 | } 38 | 39 | func MakeHandle(major, minor uint16) uint32 { 40 | return (uint32(major) << 16) | uint32(minor) 41 | } 42 | 43 | func MajorMinor(handle uint32) (uint16, uint16) { 44 | return uint16((handle & 0xFFFF0000) >> 16), uint16(handle & 0x0000FFFFF) 45 | } 46 | 47 | func HandleStr(handle uint32) string { 48 | switch handle { 49 | case HANDLE_NONE: 50 | return "none" 51 | case HANDLE_INGRESS: 52 | return "ingress" 53 | case HANDLE_ROOT: 54 | return "root" 55 | default: 56 | major, minor := MajorMinor(handle) 57 | return fmt.Sprintf("%x:%x", major, minor) 58 | } 59 | } 60 | 61 | func Percentage2u32(percentage float32) uint32 { 62 | // FIXME this is most likely not the best way to convert from % to uint32 63 | if percentage == 100 { 64 | return math.MaxUint32 65 | } 66 | return uint32(math.MaxUint32 * (percentage / 100)) 67 | } 68 | 69 | // PfifoFast is the default qdisc created by the kernel if one has not 70 | // been defined for the interface 71 | type PfifoFast struct { 72 | QdiscAttrs 73 | Bands uint8 74 | PriorityMap [PRIORITY_MAP_LEN]uint8 75 | } 76 | 77 | func (qdisc *PfifoFast) Attrs() *QdiscAttrs { 78 | return &qdisc.QdiscAttrs 79 | } 80 | 81 | func (qdisc *PfifoFast) Type() string { 82 | return "pfifo_fast" 83 | } 84 | 85 | // Prio is a basic qdisc that works just like PfifoFast 86 | type Prio struct { 87 | QdiscAttrs 88 | Bands uint8 89 | PriorityMap [PRIORITY_MAP_LEN]uint8 90 | } 91 | 92 | func NewPrio(attrs QdiscAttrs) *Prio { 93 | return &Prio{ 94 | QdiscAttrs: attrs, 95 | Bands: 3, 96 | PriorityMap: [PRIORITY_MAP_LEN]uint8{1, 2, 2, 2, 1, 2, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1}, 97 | } 98 | } 99 | 100 | func (qdisc *Prio) Attrs() *QdiscAttrs { 101 | return &qdisc.QdiscAttrs 102 | } 103 | 104 | func (qdisc *Prio) Type() string { 105 | return "prio" 106 | } 107 | 108 | // Htb is a classful qdisc that rate limits based on tokens 109 | type Htb struct { 110 | QdiscAttrs 111 | Version uint32 112 | Rate2Quantum uint32 113 | Defcls uint32 114 | Debug uint32 115 | DirectPkts uint32 116 | } 117 | 118 | func NewHtb(attrs QdiscAttrs) *Htb { 119 | return &Htb{ 120 | QdiscAttrs: attrs, 121 | Version: 3, 122 | Defcls: 0, 123 | Rate2Quantum: 10, 124 | Debug: 0, 125 | DirectPkts: 0, 126 | } 127 | } 128 | 129 | func (qdisc *Htb) Attrs() *QdiscAttrs { 130 | return &qdisc.QdiscAttrs 131 | } 132 | 133 | func (qdisc *Htb) Type() string { 134 | return "htb" 135 | } 136 | 137 | // Netem is a classless qdisc that rate limits based on tokens 138 | 139 | type NetemQdiscAttrs struct { 140 | Latency uint32 // in us 141 | DelayCorr float32 // in % 142 | Limit uint32 143 | Loss float32 // in % 144 | LossCorr float32 // in % 145 | Gap uint32 146 | Duplicate float32 // in % 147 | DuplicateCorr float32 // in % 148 | Jitter uint32 // in us 149 | ReorderProb float32 // in % 150 | ReorderCorr float32 // in % 151 | CorruptProb float32 // in % 152 | CorruptCorr float32 // in % 153 | } 154 | 155 | func (q NetemQdiscAttrs) String() string { 156 | return fmt.Sprintf( 157 | "{Latency: %d, Limit: %d, Loss: %f, Gap: %d, Duplicate: %f, Jitter: %d}", 158 | q.Latency, q.Limit, q.Loss, q.Gap, q.Duplicate, q.Jitter, 159 | ) 160 | } 161 | 162 | type Netem struct { 163 | QdiscAttrs 164 | Latency uint32 165 | DelayCorr uint32 166 | Limit uint32 167 | Loss uint32 168 | LossCorr uint32 169 | Gap uint32 170 | Duplicate uint32 171 | DuplicateCorr uint32 172 | Jitter uint32 173 | ReorderProb uint32 174 | ReorderCorr uint32 175 | CorruptProb uint32 176 | CorruptCorr uint32 177 | } 178 | 179 | func (qdisc *Netem) Attrs() *QdiscAttrs { 180 | return &qdisc.QdiscAttrs 181 | } 182 | 183 | func (qdisc *Netem) Type() string { 184 | return "netem" 185 | } 186 | 187 | // Tbf is a classless qdisc that rate limits based on tokens 188 | type Tbf struct { 189 | QdiscAttrs 190 | // TODO: handle 64bit rate properly 191 | Rate uint64 192 | Limit uint32 193 | Buffer uint32 194 | // TODO: handle other settings 195 | } 196 | 197 | func (qdisc *Tbf) Attrs() *QdiscAttrs { 198 | return &qdisc.QdiscAttrs 199 | } 200 | 201 | func (qdisc *Tbf) Type() string { 202 | return "tbf" 203 | } 204 | 205 | // Ingress is a qdisc for adding ingress filters 206 | type Ingress struct { 207 | QdiscAttrs 208 | } 209 | 210 | func (qdisc *Ingress) Attrs() *QdiscAttrs { 211 | return &qdisc.QdiscAttrs 212 | } 213 | 214 | func (qdisc *Ingress) Type() string { 215 | return "ingress" 216 | } 217 | 218 | // GenericQdisc qdiscs represent types that are not currently understood 219 | // by this netlink library. 220 | type GenericQdisc struct { 221 | QdiscAttrs 222 | QdiscType string 223 | } 224 | 225 | func (qdisc *GenericQdisc) Attrs() *QdiscAttrs { 226 | return &qdisc.QdiscAttrs 227 | } 228 | 229 | func (qdisc *GenericQdisc) Type() string { 230 | return qdisc.QdiscType 231 | } 232 | -------------------------------------------------------------------------------- /vendor/github.com/vishvananda/netlink/route.go: -------------------------------------------------------------------------------- 1 | package netlink 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | ) 7 | 8 | // Scope is an enum representing a route scope. 9 | type Scope uint8 10 | 11 | type NextHopFlag int 12 | 13 | // Route represents a netlink route. 14 | type Route struct { 15 | LinkIndex int 16 | ILinkIndex int 17 | Scope Scope 18 | Dst *net.IPNet 19 | Src net.IP 20 | Gw net.IP 21 | MultiPath []*NexthopInfo 22 | Protocol int 23 | Priority int 24 | Table int 25 | Type int 26 | Tos int 27 | Flags int 28 | } 29 | 30 | func (r Route) String() string { 31 | if len(r.MultiPath) > 0 { 32 | return fmt.Sprintf("{Dst: %s Src: %s Gw: %s Flags: %s Table: %d}", r.Dst, 33 | r.Src, r.MultiPath, r.ListFlags(), r.Table) 34 | } 35 | return fmt.Sprintf("{Ifindex: %d Dst: %s Src: %s Gw: %s Flags: %s Table: %d}", r.LinkIndex, r.Dst, 36 | r.Src, r.Gw, r.ListFlags(), r.Table) 37 | } 38 | 39 | func (r *Route) SetFlag(flag NextHopFlag) { 40 | r.Flags |= int(flag) 41 | } 42 | 43 | func (r *Route) ClearFlag(flag NextHopFlag) { 44 | r.Flags &^= int(flag) 45 | } 46 | 47 | type flagString struct { 48 | f NextHopFlag 49 | s string 50 | } 51 | 52 | // RouteUpdate is sent when a route changes - type is RTM_NEWROUTE or RTM_DELROUTE 53 | type RouteUpdate struct { 54 | Type uint16 55 | Route 56 | } 57 | 58 | type NexthopInfo struct { 59 | LinkIndex int 60 | Hops int 61 | Gw net.IP 62 | } 63 | 64 | func (n *NexthopInfo) String() string { 65 | return fmt.Sprintf("{Ifindex: %d Weight: %d, Gw: %s}", n.LinkIndex, n.Hops+1, n.Gw) 66 | } 67 | -------------------------------------------------------------------------------- /vendor/github.com/vishvananda/netlink/route_unspecified.go: -------------------------------------------------------------------------------- 1 | // +build !linux 2 | 3 | package netlink 4 | 5 | func (r *Route) ListFlags() []string { 6 | return []string{} 7 | } 8 | -------------------------------------------------------------------------------- /vendor/github.com/vishvananda/netlink/rule.go: -------------------------------------------------------------------------------- 1 | package netlink 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | ) 7 | 8 | // Rule represents a netlink rule. 9 | type Rule struct { 10 | Priority int 11 | Table int 12 | Mark int 13 | Mask int 14 | TunID uint 15 | Goto int 16 | Src *net.IPNet 17 | Dst *net.IPNet 18 | Flow int 19 | IifName string 20 | OifName string 21 | SuppressIfgroup int 22 | SuppressPrefixlen int 23 | } 24 | 25 | func (r Rule) String() string { 26 | return fmt.Sprintf("ip rule %d: from %s table %d", r.Priority, r.Src, r.Table) 27 | } 28 | 29 | // NewRule return empty rules. 30 | func NewRule() *Rule { 31 | return &Rule{ 32 | SuppressIfgroup: -1, 33 | SuppressPrefixlen: -1, 34 | Priority: -1, 35 | Mark: -1, 36 | Mask: -1, 37 | Goto: -1, 38 | Flow: -1, 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /vendor/github.com/vishvananda/netlink/rule_linux.go: -------------------------------------------------------------------------------- 1 | package netlink 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | "syscall" 7 | 8 | "github.com/vishvananda/netlink/nl" 9 | ) 10 | 11 | // RuleAdd adds a rule to the system. 12 | // Equivalent to: ip rule add 13 | func RuleAdd(rule *Rule) error { 14 | return pkgHandle.RuleAdd(rule) 15 | } 16 | 17 | // RuleAdd adds a rule to the system. 18 | // Equivalent to: ip rule add 19 | func (h *Handle) RuleAdd(rule *Rule) error { 20 | req := h.newNetlinkRequest(syscall.RTM_NEWRULE, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK) 21 | return ruleHandle(rule, req) 22 | } 23 | 24 | // RuleDel deletes a rule from the system. 25 | // Equivalent to: ip rule del 26 | func RuleDel(rule *Rule) error { 27 | return pkgHandle.RuleDel(rule) 28 | } 29 | 30 | // RuleDel deletes a rule from the system. 31 | // Equivalent to: ip rule del 32 | func (h *Handle) RuleDel(rule *Rule) error { 33 | req := h.newNetlinkRequest(syscall.RTM_DELRULE, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK) 34 | return ruleHandle(rule, req) 35 | } 36 | 37 | func ruleHandle(rule *Rule, req *nl.NetlinkRequest) error { 38 | msg := nl.NewRtMsg() 39 | msg.Family = syscall.AF_INET 40 | var dstFamily uint8 41 | 42 | var rtAttrs []*nl.RtAttr 43 | if rule.Dst != nil && rule.Dst.IP != nil { 44 | dstLen, _ := rule.Dst.Mask.Size() 45 | msg.Dst_len = uint8(dstLen) 46 | msg.Family = uint8(nl.GetIPFamily(rule.Dst.IP)) 47 | dstFamily = msg.Family 48 | var dstData []byte 49 | if msg.Family == syscall.AF_INET { 50 | dstData = rule.Dst.IP.To4() 51 | } else { 52 | dstData = rule.Dst.IP.To16() 53 | } 54 | rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_DST, dstData)) 55 | } 56 | 57 | if rule.Src != nil && rule.Src.IP != nil { 58 | msg.Family = uint8(nl.GetIPFamily(rule.Src.IP)) 59 | if dstFamily != 0 && dstFamily != msg.Family { 60 | return fmt.Errorf("source and destination ip are not the same IP family") 61 | } 62 | srcLen, _ := rule.Src.Mask.Size() 63 | msg.Src_len = uint8(srcLen) 64 | var srcData []byte 65 | if msg.Family == syscall.AF_INET { 66 | srcData = rule.Src.IP.To4() 67 | } else { 68 | srcData = rule.Src.IP.To16() 69 | } 70 | rtAttrs = append(rtAttrs, nl.NewRtAttr(syscall.RTA_SRC, srcData)) 71 | } 72 | 73 | if rule.Table >= 0 { 74 | msg.Table = uint8(rule.Table) 75 | if rule.Table >= 256 { 76 | msg.Table = syscall.RT_TABLE_UNSPEC 77 | } 78 | } 79 | 80 | req.AddData(msg) 81 | for i := range rtAttrs { 82 | req.AddData(rtAttrs[i]) 83 | } 84 | 85 | native := nl.NativeEndian() 86 | 87 | if rule.Priority >= 0 { 88 | b := make([]byte, 4) 89 | native.PutUint32(b, uint32(rule.Priority)) 90 | req.AddData(nl.NewRtAttr(nl.FRA_PRIORITY, b)) 91 | } 92 | if rule.Mark >= 0 { 93 | b := make([]byte, 4) 94 | native.PutUint32(b, uint32(rule.Mark)) 95 | req.AddData(nl.NewRtAttr(nl.FRA_FWMARK, b)) 96 | } 97 | if rule.Mask >= 0 { 98 | b := make([]byte, 4) 99 | native.PutUint32(b, uint32(rule.Mask)) 100 | req.AddData(nl.NewRtAttr(nl.FRA_FWMASK, b)) 101 | } 102 | if rule.Flow >= 0 { 103 | b := make([]byte, 4) 104 | native.PutUint32(b, uint32(rule.Flow)) 105 | req.AddData(nl.NewRtAttr(nl.FRA_FLOW, b)) 106 | } 107 | if rule.TunID > 0 { 108 | b := make([]byte, 4) 109 | native.PutUint32(b, uint32(rule.TunID)) 110 | req.AddData(nl.NewRtAttr(nl.FRA_TUN_ID, b)) 111 | } 112 | if rule.Table >= 256 { 113 | b := make([]byte, 4) 114 | native.PutUint32(b, uint32(rule.Table)) 115 | req.AddData(nl.NewRtAttr(nl.FRA_TABLE, b)) 116 | } 117 | if msg.Table > 0 { 118 | if rule.SuppressPrefixlen >= 0 { 119 | b := make([]byte, 4) 120 | native.PutUint32(b, uint32(rule.SuppressPrefixlen)) 121 | req.AddData(nl.NewRtAttr(nl.FRA_SUPPRESS_PREFIXLEN, b)) 122 | } 123 | if rule.SuppressIfgroup >= 0 { 124 | b := make([]byte, 4) 125 | native.PutUint32(b, uint32(rule.SuppressIfgroup)) 126 | req.AddData(nl.NewRtAttr(nl.FRA_SUPPRESS_IFGROUP, b)) 127 | } 128 | } 129 | if rule.IifName != "" { 130 | req.AddData(nl.NewRtAttr(nl.FRA_IIFNAME, []byte(rule.IifName))) 131 | } 132 | if rule.OifName != "" { 133 | req.AddData(nl.NewRtAttr(nl.FRA_OIFNAME, []byte(rule.OifName))) 134 | } 135 | if rule.Goto >= 0 { 136 | msg.Type = nl.FR_ACT_NOP 137 | b := make([]byte, 4) 138 | native.PutUint32(b, uint32(rule.Goto)) 139 | req.AddData(nl.NewRtAttr(nl.FRA_GOTO, b)) 140 | } 141 | 142 | _, err := req.Execute(syscall.NETLINK_ROUTE, 0) 143 | return err 144 | } 145 | 146 | // RuleList lists rules in the system. 147 | // Equivalent to: ip rule list 148 | func RuleList(family int) ([]Rule, error) { 149 | return pkgHandle.RuleList(family) 150 | } 151 | 152 | // RuleList lists rules in the system. 153 | // Equivalent to: ip rule list 154 | func (h *Handle) RuleList(family int) ([]Rule, error) { 155 | req := h.newNetlinkRequest(syscall.RTM_GETRULE, syscall.NLM_F_DUMP|syscall.NLM_F_REQUEST) 156 | msg := nl.NewIfInfomsg(family) 157 | req.AddData(msg) 158 | 159 | msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWRULE) 160 | if err != nil { 161 | return nil, err 162 | } 163 | 164 | native := nl.NativeEndian() 165 | var res = make([]Rule, 0) 166 | for i := range msgs { 167 | msg := nl.DeserializeRtMsg(msgs[i]) 168 | attrs, err := nl.ParseRouteAttr(msgs[i][msg.Len():]) 169 | if err != nil { 170 | return nil, err 171 | } 172 | 173 | rule := NewRule() 174 | 175 | for j := range attrs { 176 | switch attrs[j].Attr.Type { 177 | case syscall.RTA_TABLE: 178 | rule.Table = int(native.Uint32(attrs[j].Value[0:4])) 179 | case nl.FRA_SRC: 180 | rule.Src = &net.IPNet{ 181 | IP: attrs[j].Value, 182 | Mask: net.CIDRMask(int(msg.Src_len), 8*len(attrs[j].Value)), 183 | } 184 | case nl.FRA_DST: 185 | rule.Dst = &net.IPNet{ 186 | IP: attrs[j].Value, 187 | Mask: net.CIDRMask(int(msg.Dst_len), 8*len(attrs[j].Value)), 188 | } 189 | case nl.FRA_FWMARK: 190 | rule.Mark = int(native.Uint32(attrs[j].Value[0:4])) 191 | case nl.FRA_FWMASK: 192 | rule.Mask = int(native.Uint32(attrs[j].Value[0:4])) 193 | case nl.FRA_TUN_ID: 194 | rule.TunID = uint(native.Uint64(attrs[j].Value[0:4])) 195 | case nl.FRA_IIFNAME: 196 | rule.IifName = string(attrs[j].Value[:len(attrs[j].Value)-1]) 197 | case nl.FRA_OIFNAME: 198 | rule.OifName = string(attrs[j].Value[:len(attrs[j].Value)-1]) 199 | case nl.FRA_SUPPRESS_PREFIXLEN: 200 | i := native.Uint32(attrs[j].Value[0:4]) 201 | if i != 0xffffffff { 202 | rule.SuppressPrefixlen = int(i) 203 | } 204 | case nl.FRA_SUPPRESS_IFGROUP: 205 | i := native.Uint32(attrs[j].Value[0:4]) 206 | if i != 0xffffffff { 207 | rule.SuppressIfgroup = int(i) 208 | } 209 | case nl.FRA_FLOW: 210 | rule.Flow = int(native.Uint32(attrs[j].Value[0:4])) 211 | case nl.FRA_GOTO: 212 | rule.Goto = int(native.Uint32(attrs[j].Value[0:4])) 213 | case nl.FRA_PRIORITY: 214 | rule.Priority = int(native.Uint32(attrs[j].Value[0:4])) 215 | } 216 | } 217 | res = append(res, *rule) 218 | } 219 | 220 | return res, nil 221 | } 222 | -------------------------------------------------------------------------------- /vendor/github.com/vishvananda/netlink/xfrm.go: -------------------------------------------------------------------------------- 1 | package netlink 2 | 3 | import ( 4 | "fmt" 5 | "syscall" 6 | ) 7 | 8 | // Proto is an enum representing an ipsec protocol. 9 | type Proto uint8 10 | 11 | const ( 12 | XFRM_PROTO_ROUTE2 Proto = syscall.IPPROTO_ROUTING 13 | XFRM_PROTO_ESP Proto = syscall.IPPROTO_ESP 14 | XFRM_PROTO_AH Proto = syscall.IPPROTO_AH 15 | XFRM_PROTO_HAO Proto = syscall.IPPROTO_DSTOPTS 16 | XFRM_PROTO_COMP Proto = 0x6c // NOTE not defined on darwin 17 | XFRM_PROTO_IPSEC_ANY Proto = syscall.IPPROTO_RAW 18 | ) 19 | 20 | func (p Proto) String() string { 21 | switch p { 22 | case XFRM_PROTO_ROUTE2: 23 | return "route2" 24 | case XFRM_PROTO_ESP: 25 | return "esp" 26 | case XFRM_PROTO_AH: 27 | return "ah" 28 | case XFRM_PROTO_HAO: 29 | return "hao" 30 | case XFRM_PROTO_COMP: 31 | return "comp" 32 | case XFRM_PROTO_IPSEC_ANY: 33 | return "ipsec-any" 34 | } 35 | return fmt.Sprintf("%d", p) 36 | } 37 | 38 | // Mode is an enum representing an ipsec transport. 39 | type Mode uint8 40 | 41 | const ( 42 | XFRM_MODE_TRANSPORT Mode = iota 43 | XFRM_MODE_TUNNEL 44 | XFRM_MODE_ROUTEOPTIMIZATION 45 | XFRM_MODE_IN_TRIGGER 46 | XFRM_MODE_BEET 47 | XFRM_MODE_MAX 48 | ) 49 | 50 | func (m Mode) String() string { 51 | switch m { 52 | case XFRM_MODE_TRANSPORT: 53 | return "transport" 54 | case XFRM_MODE_TUNNEL: 55 | return "tunnel" 56 | case XFRM_MODE_ROUTEOPTIMIZATION: 57 | return "ro" 58 | case XFRM_MODE_IN_TRIGGER: 59 | return "in_trigger" 60 | case XFRM_MODE_BEET: 61 | return "beet" 62 | } 63 | return fmt.Sprintf("%d", m) 64 | } 65 | 66 | // XfrmMark represents the mark associated to the state or policy 67 | type XfrmMark struct { 68 | Value uint32 69 | Mask uint32 70 | } 71 | 72 | func (m *XfrmMark) String() string { 73 | return fmt.Sprintf("(0x%x,0x%x)", m.Value, m.Mask) 74 | } 75 | -------------------------------------------------------------------------------- /vendor/github.com/vishvananda/netlink/xfrm_policy.go: -------------------------------------------------------------------------------- 1 | package netlink 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | ) 7 | 8 | // Dir is an enum representing an ipsec template direction. 9 | type Dir uint8 10 | 11 | const ( 12 | XFRM_DIR_IN Dir = iota 13 | XFRM_DIR_OUT 14 | XFRM_DIR_FWD 15 | XFRM_SOCKET_IN 16 | XFRM_SOCKET_OUT 17 | XFRM_SOCKET_FWD 18 | ) 19 | 20 | func (d Dir) String() string { 21 | switch d { 22 | case XFRM_DIR_IN: 23 | return "dir in" 24 | case XFRM_DIR_OUT: 25 | return "dir out" 26 | case XFRM_DIR_FWD: 27 | return "dir fwd" 28 | case XFRM_SOCKET_IN: 29 | return "socket in" 30 | case XFRM_SOCKET_OUT: 31 | return "socket out" 32 | case XFRM_SOCKET_FWD: 33 | return "socket fwd" 34 | } 35 | return fmt.Sprintf("socket %d", d-XFRM_SOCKET_IN) 36 | } 37 | 38 | // XfrmPolicyTmpl encapsulates a rule for the base addresses of an ipsec 39 | // policy. These rules are matched with XfrmState to determine encryption 40 | // and authentication algorithms. 41 | type XfrmPolicyTmpl struct { 42 | Dst net.IP 43 | Src net.IP 44 | Proto Proto 45 | Mode Mode 46 | Spi int 47 | Reqid int 48 | } 49 | 50 | func (t XfrmPolicyTmpl) String() string { 51 | return fmt.Sprintf("{Dst: %v, Src: %v, Proto: %s, Mode: %s, Spi: 0x%x, Reqid: 0x%x}", 52 | t.Dst, t.Src, t.Proto, t.Mode, t.Spi, t.Reqid) 53 | } 54 | 55 | // XfrmPolicy represents an ipsec policy. It represents the overlay network 56 | // and has a list of XfrmPolicyTmpls representing the base addresses of 57 | // the policy. 58 | type XfrmPolicy struct { 59 | Dst *net.IPNet 60 | Src *net.IPNet 61 | Proto Proto 62 | DstPort int 63 | SrcPort int 64 | Dir Dir 65 | Priority int 66 | Index int 67 | Mark *XfrmMark 68 | Tmpls []XfrmPolicyTmpl 69 | } 70 | 71 | func (p XfrmPolicy) String() string { 72 | return fmt.Sprintf("{Dst: %v, Src: %v, Proto: %s, DstPort: %d, SrcPort: %d, Dir: %s, Priority: %d, Index: %d, Mark: %s, Tmpls: %s}", 73 | p.Dst, p.Src, p.Proto, p.DstPort, p.SrcPort, p.Dir, p.Priority, p.Index, p.Mark, p.Tmpls) 74 | } 75 | -------------------------------------------------------------------------------- /vendor/github.com/vishvananda/netlink/xfrm_state.go: -------------------------------------------------------------------------------- 1 | package netlink 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | ) 7 | 8 | // XfrmStateAlgo represents the algorithm to use for the ipsec encryption. 9 | type XfrmStateAlgo struct { 10 | Name string 11 | Key []byte 12 | TruncateLen int // Auth only 13 | ICVLen int // AEAD only 14 | } 15 | 16 | func (a XfrmStateAlgo) String() string { 17 | base := fmt.Sprintf("{Name: %s, Key: 0x%x", a.Name, a.Key) 18 | if a.TruncateLen != 0 { 19 | base = fmt.Sprintf("%s, Truncate length: %d", base, a.TruncateLen) 20 | } 21 | if a.ICVLen != 0 { 22 | base = fmt.Sprintf("%s, ICV length: %d", base, a.ICVLen) 23 | } 24 | return fmt.Sprintf("%s}", base) 25 | } 26 | 27 | // EncapType is an enum representing the optional packet encapsulation. 28 | type EncapType uint8 29 | 30 | const ( 31 | XFRM_ENCAP_ESPINUDP_NONIKE EncapType = iota + 1 32 | XFRM_ENCAP_ESPINUDP 33 | ) 34 | 35 | func (e EncapType) String() string { 36 | switch e { 37 | case XFRM_ENCAP_ESPINUDP_NONIKE: 38 | return "espinudp-non-ike" 39 | case XFRM_ENCAP_ESPINUDP: 40 | return "espinudp" 41 | } 42 | return "unknown" 43 | } 44 | 45 | // XfrmStateEncap represents the encapsulation to use for the ipsec encryption. 46 | type XfrmStateEncap struct { 47 | Type EncapType 48 | SrcPort int 49 | DstPort int 50 | OriginalAddress net.IP 51 | } 52 | 53 | func (e XfrmStateEncap) String() string { 54 | return fmt.Sprintf("{Type: %s, Srcport: %d, DstPort: %d, OriginalAddress: %v}", 55 | e.Type, e.SrcPort, e.DstPort, e.OriginalAddress) 56 | } 57 | 58 | // XfrmStateLimits represents the configured limits for the state. 59 | type XfrmStateLimits struct { 60 | ByteSoft uint64 61 | ByteHard uint64 62 | PacketSoft uint64 63 | PacketHard uint64 64 | TimeSoft uint64 65 | TimeHard uint64 66 | TimeUseSoft uint64 67 | TimeUseHard uint64 68 | } 69 | 70 | // XfrmState represents the state of an ipsec policy. It optionally 71 | // contains an XfrmStateAlgo for encryption and one for authentication. 72 | type XfrmState struct { 73 | Dst net.IP 74 | Src net.IP 75 | Proto Proto 76 | Mode Mode 77 | Spi int 78 | Reqid int 79 | ReplayWindow int 80 | Limits XfrmStateLimits 81 | Mark *XfrmMark 82 | Auth *XfrmStateAlgo 83 | Crypt *XfrmStateAlgo 84 | Aead *XfrmStateAlgo 85 | Encap *XfrmStateEncap 86 | } 87 | 88 | func (sa XfrmState) String() string { 89 | return fmt.Sprintf("Dst: %v, Src: %v, Proto: %s, Mode: %s, SPI: 0x%x, ReqID: 0x%x, ReplayWindow: %d, Mark: %v, Auth: %v, Crypt: %v, Aead: %v,Encap: %v", 90 | sa.Dst, sa.Src, sa.Proto, sa.Mode, sa.Spi, sa.Reqid, sa.ReplayWindow, sa.Mark, sa.Auth, sa.Crypt, sa.Aead, sa.Encap) 91 | } 92 | func (sa XfrmState) Print(stats bool) string { 93 | if !stats { 94 | return sa.String() 95 | } 96 | 97 | return fmt.Sprintf("%s, ByteSoft: %s, ByteHard: %s, PacketSoft: %s, PacketHard: %s, TimeSoft: %d, TimeHard: %d, TimeUseSoft: %d, TimeUseHard: %d", 98 | sa.String(), printLimit(sa.Limits.ByteSoft), printLimit(sa.Limits.ByteHard), printLimit(sa.Limits.PacketSoft), printLimit(sa.Limits.PacketHard), 99 | sa.Limits.TimeSoft, sa.Limits.TimeHard, sa.Limits.TimeUseSoft, sa.Limits.TimeUseHard) 100 | } 101 | 102 | func printLimit(lmt uint64) string { 103 | if lmt == ^uint64(0) { 104 | return "(INF)" 105 | } 106 | return fmt.Sprintf("%d", lmt) 107 | } 108 | -------------------------------------------------------------------------------- /vendor/github.com/vishvananda/netns/README.md: -------------------------------------------------------------------------------- 1 | # netns - network namespaces in go # 2 | 3 | The netns package provides an ultra-simple interface for handling 4 | network namespaces in go. Changing namespaces requires elevated 5 | privileges, so in most cases this code needs to be run as root. 6 | 7 | ## Local Build and Test ## 8 | 9 | You can use go get command: 10 | 11 | go get github.com/vishvananda/netns 12 | 13 | Testing (requires root): 14 | 15 | sudo -E go test github.com/vishvananda/netns 16 | 17 | ## Example ## 18 | 19 | ```go 20 | package main 21 | 22 | import ( 23 | "fmt" 24 | "net" 25 | "runtime" 26 | "github.com/vishvananda/netns" 27 | ) 28 | 29 | func main() { 30 | // Lock the OS Thread so we don't accidentally switch namespaces 31 | runtime.LockOSThread() 32 | defer runtime.UnlockOSThread() 33 | 34 | // Save the current network namespace 35 | origns, _ := netns.Get() 36 | defer origns.Close() 37 | 38 | // Create a new network namespace 39 | newns, _ := netns.New() 40 | defer newns.Close() 41 | 42 | // Do something with the network namespace 43 | ifaces, _ := net.Interfaces() 44 | fmt.Printf("Interfaces: %v\n", ifaces) 45 | 46 | // Switch back to the original namespace 47 | netns.Set(origns) 48 | } 49 | 50 | ``` 51 | -------------------------------------------------------------------------------- /vendor/github.com/vishvananda/netns/netns.go: -------------------------------------------------------------------------------- 1 | // Package netns allows ultra-simple network namespace handling. NsHandles 2 | // can be retrieved and set. Note that the current namespace is thread 3 | // local so actions that set and reset namespaces should use LockOSThread 4 | // to make sure the namespace doesn't change due to a goroutine switch. 5 | // It is best to close NsHandles when you are done with them. This can be 6 | // accomplished via a `defer ns.Close()` on the handle. Changing namespaces 7 | // requires elevated privileges, so in most cases this code needs to be run 8 | // as root. 9 | package netns 10 | 11 | import ( 12 | "fmt" 13 | "syscall" 14 | ) 15 | 16 | // NsHandle is a handle to a network namespace. It can be cast directly 17 | // to an int and used as a file descriptor. 18 | type NsHandle int 19 | 20 | // Equal determines if two network handles refer to the same network 21 | // namespace. This is done by comparing the device and inode that the 22 | // file descripors point to. 23 | func (ns NsHandle) Equal(other NsHandle) bool { 24 | if ns == other { 25 | return true 26 | } 27 | var s1, s2 syscall.Stat_t 28 | if err := syscall.Fstat(int(ns), &s1); err != nil { 29 | return false 30 | } 31 | if err := syscall.Fstat(int(other), &s2); err != nil { 32 | return false 33 | } 34 | return (s1.Dev == s2.Dev) && (s1.Ino == s2.Ino) 35 | } 36 | 37 | // String shows the file descriptor number and its dev and inode. 38 | func (ns NsHandle) String() string { 39 | var s syscall.Stat_t 40 | if ns == -1 { 41 | return "NS(None)" 42 | } 43 | if err := syscall.Fstat(int(ns), &s); err != nil { 44 | return fmt.Sprintf("NS(%d: unknown)", ns) 45 | } 46 | return fmt.Sprintf("NS(%d: %d, %d)", ns, s.Dev, s.Ino) 47 | } 48 | 49 | // UniqueId returns a string which uniquely identifies the namespace 50 | // associated with the network handle. 51 | func (ns NsHandle) UniqueId() string { 52 | var s syscall.Stat_t 53 | if ns == -1 { 54 | return "NS(none)" 55 | } 56 | if err := syscall.Fstat(int(ns), &s); err != nil { 57 | return "NS(unknown)" 58 | } 59 | return fmt.Sprintf("NS(%d:%d)", s.Dev, s.Ino) 60 | } 61 | 62 | // IsOpen returns true if Close() has not been called. 63 | func (ns NsHandle) IsOpen() bool { 64 | return ns != -1 65 | } 66 | 67 | // Close closes the NsHandle and resets its file descriptor to -1. 68 | // It is not safe to use an NsHandle after Close() is called. 69 | func (ns *NsHandle) Close() error { 70 | if err := syscall.Close(int(*ns)); err != nil { 71 | return err 72 | } 73 | (*ns) = -1 74 | return nil 75 | } 76 | 77 | // None gets an empty (closed) NsHandle. 78 | func None() NsHandle { 79 | return NsHandle(-1) 80 | } 81 | -------------------------------------------------------------------------------- /vendor/github.com/vishvananda/netns/netns_linux.go: -------------------------------------------------------------------------------- 1 | // +build linux 2 | 3 | package netns 4 | 5 | import ( 6 | "fmt" 7 | "io/ioutil" 8 | "os" 9 | "path/filepath" 10 | "runtime" 11 | "strconv" 12 | "strings" 13 | "syscall" 14 | ) 15 | 16 | // SYS_SETNS syscall allows changing the namespace of the current process. 17 | var SYS_SETNS = map[string]uintptr{ 18 | "386": 346, 19 | "amd64": 308, 20 | "arm64": 268, 21 | "arm": 375, 22 | "ppc64": 350, 23 | "ppc64le": 350, 24 | "s390x": 339, 25 | }[runtime.GOARCH] 26 | 27 | // Deprecated: use syscall pkg instead (go >= 1.5 needed). 28 | const ( 29 | CLONE_NEWUTS = 0x04000000 /* New utsname group? */ 30 | CLONE_NEWIPC = 0x08000000 /* New ipcs */ 31 | CLONE_NEWUSER = 0x10000000 /* New user namespace */ 32 | CLONE_NEWPID = 0x20000000 /* New pid namespace */ 33 | CLONE_NEWNET = 0x40000000 /* New network namespace */ 34 | CLONE_IO = 0x80000000 /* Get io context */ 35 | ) 36 | 37 | // Setns sets namespace using syscall. Note that this should be a method 38 | // in syscall but it has not been added. 39 | func Setns(ns NsHandle, nstype int) (err error) { 40 | _, _, e1 := syscall.Syscall(SYS_SETNS, uintptr(ns), uintptr(nstype), 0) 41 | if e1 != 0 { 42 | err = e1 43 | } 44 | return 45 | } 46 | 47 | // Set sets the current network namespace to the namespace represented 48 | // by NsHandle. 49 | func Set(ns NsHandle) (err error) { 50 | return Setns(ns, CLONE_NEWNET) 51 | } 52 | 53 | // New creates a new network namespace and returns a handle to it. 54 | func New() (ns NsHandle, err error) { 55 | if err := syscall.Unshare(CLONE_NEWNET); err != nil { 56 | return -1, err 57 | } 58 | return Get() 59 | } 60 | 61 | // Get gets a handle to the current threads network namespace. 62 | func Get() (NsHandle, error) { 63 | return GetFromThread(os.Getpid(), syscall.Gettid()) 64 | } 65 | 66 | // GetFromPath gets a handle to a network namespace 67 | // identified by the path 68 | func GetFromPath(path string) (NsHandle, error) { 69 | fd, err := syscall.Open(path, syscall.O_RDONLY, 0) 70 | if err != nil { 71 | return -1, err 72 | } 73 | return NsHandle(fd), nil 74 | } 75 | 76 | // GetFromName gets a handle to a named network namespace such as one 77 | // created by `ip netns add`. 78 | func GetFromName(name string) (NsHandle, error) { 79 | return GetFromPath(fmt.Sprintf("/var/run/netns/%s", name)) 80 | } 81 | 82 | // GetFromPid gets a handle to the network namespace of a given pid. 83 | func GetFromPid(pid int) (NsHandle, error) { 84 | return GetFromPath(fmt.Sprintf("/proc/%d/ns/net", pid)) 85 | } 86 | 87 | // GetFromThread gets a handle to the network namespace of a given pid and tid. 88 | func GetFromThread(pid, tid int) (NsHandle, error) { 89 | return GetFromPath(fmt.Sprintf("/proc/%d/task/%d/ns/net", pid, tid)) 90 | } 91 | 92 | // GetFromDocker gets a handle to the network namespace of a docker container. 93 | // Id is prefixed matched against the running docker containers, so a short 94 | // identifier can be used as long as it isn't ambiguous. 95 | func GetFromDocker(id string) (NsHandle, error) { 96 | pid, err := getPidForContainer(id) 97 | if err != nil { 98 | return -1, err 99 | } 100 | return GetFromPid(pid) 101 | } 102 | 103 | // borrowed from docker/utils/utils.go 104 | func findCgroupMountpoint(cgroupType string) (string, error) { 105 | output, err := ioutil.ReadFile("/proc/mounts") 106 | if err != nil { 107 | return "", err 108 | } 109 | 110 | // /proc/mounts has 6 fields per line, one mount per line, e.g. 111 | // cgroup /sys/fs/cgroup/devices cgroup rw,relatime,devices 0 0 112 | for _, line := range strings.Split(string(output), "\n") { 113 | parts := strings.Split(line, " ") 114 | if len(parts) == 6 && parts[2] == "cgroup" { 115 | for _, opt := range strings.Split(parts[3], ",") { 116 | if opt == cgroupType { 117 | return parts[1], nil 118 | } 119 | } 120 | } 121 | } 122 | 123 | return "", fmt.Errorf("cgroup mountpoint not found for %s", cgroupType) 124 | } 125 | 126 | // Returns the relative path to the cgroup docker is running in. 127 | // borrowed from docker/utils/utils.go 128 | // modified to get the docker pid instead of using /proc/self 129 | func getThisCgroup(cgroupType string) (string, error) { 130 | dockerpid, err := ioutil.ReadFile("/var/run/docker.pid") 131 | if err != nil { 132 | return "", err 133 | } 134 | result := strings.Split(string(dockerpid), "\n") 135 | if len(result) == 0 || len(result[0]) == 0 { 136 | return "", fmt.Errorf("docker pid not found in /var/run/docker.pid") 137 | } 138 | pid, err := strconv.Atoi(result[0]) 139 | 140 | output, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/cgroup", pid)) 141 | if err != nil { 142 | return "", err 143 | } 144 | for _, line := range strings.Split(string(output), "\n") { 145 | parts := strings.Split(line, ":") 146 | // any type used by docker should work 147 | if parts[1] == cgroupType { 148 | return parts[2], nil 149 | } 150 | } 151 | return "", fmt.Errorf("cgroup '%s' not found in /proc/%d/cgroup", cgroupType, pid) 152 | } 153 | 154 | // Returns the first pid in a container. 155 | // borrowed from docker/utils/utils.go 156 | // modified to only return the first pid 157 | // modified to glob with id 158 | // modified to search for newer docker containers 159 | func getPidForContainer(id string) (int, error) { 160 | pid := 0 161 | 162 | // memory is chosen randomly, any cgroup used by docker works 163 | cgroupType := "memory" 164 | 165 | cgroupRoot, err := findCgroupMountpoint(cgroupType) 166 | if err != nil { 167 | return pid, err 168 | } 169 | 170 | cgroupThis, err := getThisCgroup(cgroupType) 171 | if err != nil { 172 | return pid, err 173 | } 174 | 175 | id += "*" 176 | 177 | attempts := []string{ 178 | filepath.Join(cgroupRoot, cgroupThis, id, "tasks"), 179 | // With more recent lxc versions use, cgroup will be in lxc/ 180 | filepath.Join(cgroupRoot, cgroupThis, "lxc", id, "tasks"), 181 | // With more recent docker, cgroup will be in docker/ 182 | filepath.Join(cgroupRoot, cgroupThis, "docker", id, "tasks"), 183 | // Even more recent docker versions under systemd use docker-.scope/ 184 | filepath.Join(cgroupRoot, "system.slice", "docker-"+id+".scope", "tasks"), 185 | // Even more recent docker versions under cgroup/systemd/docker// 186 | filepath.Join(cgroupRoot, "..", "systemd", "docker", id, "tasks"), 187 | } 188 | 189 | var filename string 190 | for _, attempt := range attempts { 191 | filenames, _ := filepath.Glob(attempt) 192 | if len(filenames) > 1 { 193 | return pid, fmt.Errorf("Ambiguous id supplied: %v", filenames) 194 | } else if len(filenames) == 1 { 195 | filename = filenames[0] 196 | break 197 | } 198 | } 199 | 200 | if filename == "" { 201 | return pid, fmt.Errorf("Unable to find container: %v", id[:len(id)-1]) 202 | } 203 | 204 | output, err := ioutil.ReadFile(filename) 205 | if err != nil { 206 | return pid, err 207 | } 208 | 209 | result := strings.Split(string(output), "\n") 210 | if len(result) == 0 || len(result[0]) == 0 { 211 | return pid, fmt.Errorf("No pid found for container") 212 | } 213 | 214 | pid, err = strconv.Atoi(result[0]) 215 | if err != nil { 216 | return pid, fmt.Errorf("Invalid pid '%s': %s", result[0], err) 217 | } 218 | 219 | return pid, nil 220 | } 221 | -------------------------------------------------------------------------------- /vendor/github.com/vishvananda/netns/netns_unspecified.go: -------------------------------------------------------------------------------- 1 | // +build !linux 2 | 3 | package netns 4 | 5 | import ( 6 | "errors" 7 | ) 8 | 9 | var ( 10 | ErrNotImplemented = errors.New("not implemented") 11 | ) 12 | 13 | func Set(ns NsHandle) (err error) { 14 | return ErrNotImplemented 15 | } 16 | 17 | func New() (ns NsHandle, err error) { 18 | return -1, ErrNotImplemented 19 | } 20 | 21 | func Get() (NsHandle, error) { 22 | return -1, ErrNotImplemented 23 | } 24 | 25 | func GetFromName(name string) (NsHandle, error) { 26 | return -1, ErrNotImplemented 27 | } 28 | 29 | func GetFromPid(pid int) (NsHandle, error) { 30 | return -1, ErrNotImplemented 31 | } 32 | 33 | func GetFromDocker(id string) (NsHandle, error) { 34 | return -1, ErrNotImplemented 35 | } 36 | -------------------------------------------------------------------------------- /vendor/golang.org/x/net/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/golang.org/x/net/PATENTS: -------------------------------------------------------------------------------- 1 | Additional IP Rights Grant (Patents) 2 | 3 | "This implementation" means the copyrightable works distributed by 4 | Google as part of the Go project. 5 | 6 | Google hereby grants to You a perpetual, worldwide, non-exclusive, 7 | no-charge, royalty-free, irrevocable (except as stated in this section) 8 | patent license to make, have made, use, offer to sell, sell, import, 9 | transfer and otherwise run, modify and propagate the contents of this 10 | implementation of Go, where such license applies only to those patent 11 | claims, both currently owned or controlled by Google and acquired in 12 | the future, licensable by Google that are necessarily infringed by this 13 | implementation of Go. This grant does not include claims that would be 14 | infringed only as a consequence of further modification of this 15 | implementation. If you or your agent or exclusive licensee institute or 16 | order or agree to the institution of patent litigation against any 17 | entity (including a cross-claim or counterclaim in a lawsuit) alleging 18 | that this implementation of Go or any code incorporated within this 19 | implementation of Go constitutes direct or contributory patent 20 | infringement, or inducement of patent infringement, then any patent 21 | rights granted to you under this License for this implementation of Go 22 | shall terminate as of the date such litigation is filed. 23 | -------------------------------------------------------------------------------- /vendor/golang.org/x/net/proxy/direct.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package proxy 6 | 7 | import ( 8 | "net" 9 | ) 10 | 11 | type direct struct{} 12 | 13 | // Direct is a direct proxy: one that makes network connections directly. 14 | var Direct = direct{} 15 | 16 | func (direct) Dial(network, addr string) (net.Conn, error) { 17 | return net.Dial(network, addr) 18 | } 19 | -------------------------------------------------------------------------------- /vendor/golang.org/x/net/proxy/per_host.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package proxy 6 | 7 | import ( 8 | "net" 9 | "strings" 10 | ) 11 | 12 | // A PerHost directs connections to a default Dialer unless the hostname 13 | // requested matches one of a number of exceptions. 14 | type PerHost struct { 15 | def, bypass Dialer 16 | 17 | bypassNetworks []*net.IPNet 18 | bypassIPs []net.IP 19 | bypassZones []string 20 | bypassHosts []string 21 | } 22 | 23 | // NewPerHost returns a PerHost Dialer that directs connections to either 24 | // defaultDialer or bypass, depending on whether the connection matches one of 25 | // the configured rules. 26 | func NewPerHost(defaultDialer, bypass Dialer) *PerHost { 27 | return &PerHost{ 28 | def: defaultDialer, 29 | bypass: bypass, 30 | } 31 | } 32 | 33 | // Dial connects to the address addr on the given network through either 34 | // defaultDialer or bypass. 35 | func (p *PerHost) Dial(network, addr string) (c net.Conn, err error) { 36 | host, _, err := net.SplitHostPort(addr) 37 | if err != nil { 38 | return nil, err 39 | } 40 | 41 | return p.dialerForRequest(host).Dial(network, addr) 42 | } 43 | 44 | func (p *PerHost) dialerForRequest(host string) Dialer { 45 | if ip := net.ParseIP(host); ip != nil { 46 | for _, net := range p.bypassNetworks { 47 | if net.Contains(ip) { 48 | return p.bypass 49 | } 50 | } 51 | for _, bypassIP := range p.bypassIPs { 52 | if bypassIP.Equal(ip) { 53 | return p.bypass 54 | } 55 | } 56 | return p.def 57 | } 58 | 59 | for _, zone := range p.bypassZones { 60 | if strings.HasSuffix(host, zone) { 61 | return p.bypass 62 | } 63 | if host == zone[1:] { 64 | // For a zone "example.com", we match "example.com" 65 | // too. 66 | return p.bypass 67 | } 68 | } 69 | for _, bypassHost := range p.bypassHosts { 70 | if bypassHost == host { 71 | return p.bypass 72 | } 73 | } 74 | return p.def 75 | } 76 | 77 | // AddFromString parses a string that contains comma-separated values 78 | // specifying hosts that should use the bypass proxy. Each value is either an 79 | // IP address, a CIDR range, a zone (*.example.com) or a hostname 80 | // (localhost). A best effort is made to parse the string and errors are 81 | // ignored. 82 | func (p *PerHost) AddFromString(s string) { 83 | hosts := strings.Split(s, ",") 84 | for _, host := range hosts { 85 | host = strings.TrimSpace(host) 86 | if len(host) == 0 { 87 | continue 88 | } 89 | if strings.Contains(host, "/") { 90 | // We assume that it's a CIDR address like 127.0.0.0/8 91 | if _, net, err := net.ParseCIDR(host); err == nil { 92 | p.AddNetwork(net) 93 | } 94 | continue 95 | } 96 | if ip := net.ParseIP(host); ip != nil { 97 | p.AddIP(ip) 98 | continue 99 | } 100 | if strings.HasPrefix(host, "*.") { 101 | p.AddZone(host[1:]) 102 | continue 103 | } 104 | p.AddHost(host) 105 | } 106 | } 107 | 108 | // AddIP specifies an IP address that will use the bypass proxy. Note that 109 | // this will only take effect if a literal IP address is dialed. A connection 110 | // to a named host will never match an IP. 111 | func (p *PerHost) AddIP(ip net.IP) { 112 | p.bypassIPs = append(p.bypassIPs, ip) 113 | } 114 | 115 | // AddNetwork specifies an IP range that will use the bypass proxy. Note that 116 | // this will only take effect if a literal IP address is dialed. A connection 117 | // to a named host will never match. 118 | func (p *PerHost) AddNetwork(net *net.IPNet) { 119 | p.bypassNetworks = append(p.bypassNetworks, net) 120 | } 121 | 122 | // AddZone specifies a DNS suffix that will use the bypass proxy. A zone of 123 | // "example.com" matches "example.com" and all of its subdomains. 124 | func (p *PerHost) AddZone(zone string) { 125 | if strings.HasSuffix(zone, ".") { 126 | zone = zone[:len(zone)-1] 127 | } 128 | if !strings.HasPrefix(zone, ".") { 129 | zone = "." + zone 130 | } 131 | p.bypassZones = append(p.bypassZones, zone) 132 | } 133 | 134 | // AddHost specifies a hostname that will use the bypass proxy. 135 | func (p *PerHost) AddHost(host string) { 136 | if strings.HasSuffix(host, ".") { 137 | host = host[:len(host)-1] 138 | } 139 | p.bypassHosts = append(p.bypassHosts, host) 140 | } 141 | -------------------------------------------------------------------------------- /vendor/golang.org/x/net/proxy/proxy.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package proxy provides support for a variety of protocols to proxy network 6 | // data. 7 | package proxy // import "golang.org/x/net/proxy" 8 | 9 | import ( 10 | "errors" 11 | "net" 12 | "net/url" 13 | "os" 14 | ) 15 | 16 | // A Dialer is a means to establish a connection. 17 | type Dialer interface { 18 | // Dial connects to the given address via the proxy. 19 | Dial(network, addr string) (c net.Conn, err error) 20 | } 21 | 22 | // Auth contains authentication parameters that specific Dialers may require. 23 | type Auth struct { 24 | User, Password string 25 | } 26 | 27 | // FromEnvironment returns the dialer specified by the proxy related variables in 28 | // the environment. 29 | func FromEnvironment() Dialer { 30 | allProxy := os.Getenv("all_proxy") 31 | if len(allProxy) == 0 { 32 | return Direct 33 | } 34 | 35 | proxyURL, err := url.Parse(allProxy) 36 | if err != nil { 37 | return Direct 38 | } 39 | proxy, err := FromURL(proxyURL, Direct) 40 | if err != nil { 41 | return Direct 42 | } 43 | 44 | noProxy := os.Getenv("no_proxy") 45 | if len(noProxy) == 0 { 46 | return proxy 47 | } 48 | 49 | perHost := NewPerHost(proxy, Direct) 50 | perHost.AddFromString(noProxy) 51 | return perHost 52 | } 53 | 54 | // proxySchemes is a map from URL schemes to a function that creates a Dialer 55 | // from a URL with such a scheme. 56 | var proxySchemes map[string]func(*url.URL, Dialer) (Dialer, error) 57 | 58 | // RegisterDialerType takes a URL scheme and a function to generate Dialers from 59 | // a URL with that scheme and a forwarding Dialer. Registered schemes are used 60 | // by FromURL. 61 | func RegisterDialerType(scheme string, f func(*url.URL, Dialer) (Dialer, error)) { 62 | if proxySchemes == nil { 63 | proxySchemes = make(map[string]func(*url.URL, Dialer) (Dialer, error)) 64 | } 65 | proxySchemes[scheme] = f 66 | } 67 | 68 | // FromURL returns a Dialer given a URL specification and an underlying 69 | // Dialer for it to make network requests. 70 | func FromURL(u *url.URL, forward Dialer) (Dialer, error) { 71 | var auth *Auth 72 | if u.User != nil { 73 | auth = new(Auth) 74 | auth.User = u.User.Username() 75 | if p, ok := u.User.Password(); ok { 76 | auth.Password = p 77 | } 78 | } 79 | 80 | switch u.Scheme { 81 | case "socks5": 82 | return SOCKS5("tcp", u.Host, auth, forward) 83 | } 84 | 85 | // If the scheme doesn't match any of the built-in schemes, see if it 86 | // was registered by another package. 87 | if proxySchemes != nil { 88 | if f, ok := proxySchemes[u.Scheme]; ok { 89 | return f(u, forward) 90 | } 91 | } 92 | 93 | return nil, errors.New("proxy: unknown scheme: " + u.Scheme) 94 | } 95 | -------------------------------------------------------------------------------- /vendor/golang.org/x/net/proxy/socks5.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package proxy 6 | 7 | import ( 8 | "errors" 9 | "io" 10 | "net" 11 | "strconv" 12 | ) 13 | 14 | // SOCKS5 returns a Dialer that makes SOCKSv5 connections to the given address 15 | // with an optional username and password. See RFC 1928. 16 | func SOCKS5(network, addr string, auth *Auth, forward Dialer) (Dialer, error) { 17 | s := &socks5{ 18 | network: network, 19 | addr: addr, 20 | forward: forward, 21 | } 22 | if auth != nil { 23 | s.user = auth.User 24 | s.password = auth.Password 25 | } 26 | 27 | return s, nil 28 | } 29 | 30 | type socks5 struct { 31 | user, password string 32 | network, addr string 33 | forward Dialer 34 | } 35 | 36 | const socks5Version = 5 37 | 38 | const ( 39 | socks5AuthNone = 0 40 | socks5AuthPassword = 2 41 | ) 42 | 43 | const socks5Connect = 1 44 | 45 | const ( 46 | socks5IP4 = 1 47 | socks5Domain = 3 48 | socks5IP6 = 4 49 | ) 50 | 51 | var socks5Errors = []string{ 52 | "", 53 | "general failure", 54 | "connection forbidden", 55 | "network unreachable", 56 | "host unreachable", 57 | "connection refused", 58 | "TTL expired", 59 | "command not supported", 60 | "address type not supported", 61 | } 62 | 63 | // Dial connects to the address addr on the network net via the SOCKS5 proxy. 64 | func (s *socks5) Dial(network, addr string) (net.Conn, error) { 65 | switch network { 66 | case "tcp", "tcp6", "tcp4": 67 | default: 68 | return nil, errors.New("proxy: no support for SOCKS5 proxy connections of type " + network) 69 | } 70 | 71 | conn, err := s.forward.Dial(s.network, s.addr) 72 | if err != nil { 73 | return nil, err 74 | } 75 | closeConn := &conn 76 | defer func() { 77 | if closeConn != nil { 78 | (*closeConn).Close() 79 | } 80 | }() 81 | 82 | host, portStr, err := net.SplitHostPort(addr) 83 | if err != nil { 84 | return nil, err 85 | } 86 | 87 | port, err := strconv.Atoi(portStr) 88 | if err != nil { 89 | return nil, errors.New("proxy: failed to parse port number: " + portStr) 90 | } 91 | if port < 1 || port > 0xffff { 92 | return nil, errors.New("proxy: port number out of range: " + portStr) 93 | } 94 | 95 | // the size here is just an estimate 96 | buf := make([]byte, 0, 6+len(host)) 97 | 98 | buf = append(buf, socks5Version) 99 | if len(s.user) > 0 && len(s.user) < 256 && len(s.password) < 256 { 100 | buf = append(buf, 2 /* num auth methods */, socks5AuthNone, socks5AuthPassword) 101 | } else { 102 | buf = append(buf, 1 /* num auth methods */, socks5AuthNone) 103 | } 104 | 105 | if _, err := conn.Write(buf); err != nil { 106 | return nil, errors.New("proxy: failed to write greeting to SOCKS5 proxy at " + s.addr + ": " + err.Error()) 107 | } 108 | 109 | if _, err := io.ReadFull(conn, buf[:2]); err != nil { 110 | return nil, errors.New("proxy: failed to read greeting from SOCKS5 proxy at " + s.addr + ": " + err.Error()) 111 | } 112 | if buf[0] != 5 { 113 | return nil, errors.New("proxy: SOCKS5 proxy at " + s.addr + " has unexpected version " + strconv.Itoa(int(buf[0]))) 114 | } 115 | if buf[1] == 0xff { 116 | return nil, errors.New("proxy: SOCKS5 proxy at " + s.addr + " requires authentication") 117 | } 118 | 119 | if buf[1] == socks5AuthPassword { 120 | buf = buf[:0] 121 | buf = append(buf, 1 /* password protocol version */) 122 | buf = append(buf, uint8(len(s.user))) 123 | buf = append(buf, s.user...) 124 | buf = append(buf, uint8(len(s.password))) 125 | buf = append(buf, s.password...) 126 | 127 | if _, err := conn.Write(buf); err != nil { 128 | return nil, errors.New("proxy: failed to write authentication request to SOCKS5 proxy at " + s.addr + ": " + err.Error()) 129 | } 130 | 131 | if _, err := io.ReadFull(conn, buf[:2]); err != nil { 132 | return nil, errors.New("proxy: failed to read authentication reply from SOCKS5 proxy at " + s.addr + ": " + err.Error()) 133 | } 134 | 135 | if buf[1] != 0 { 136 | return nil, errors.New("proxy: SOCKS5 proxy at " + s.addr + " rejected username/password") 137 | } 138 | } 139 | 140 | buf = buf[:0] 141 | buf = append(buf, socks5Version, socks5Connect, 0 /* reserved */) 142 | 143 | if ip := net.ParseIP(host); ip != nil { 144 | if ip4 := ip.To4(); ip4 != nil { 145 | buf = append(buf, socks5IP4) 146 | ip = ip4 147 | } else { 148 | buf = append(buf, socks5IP6) 149 | } 150 | buf = append(buf, ip...) 151 | } else { 152 | if len(host) > 255 { 153 | return nil, errors.New("proxy: destination hostname too long: " + host) 154 | } 155 | buf = append(buf, socks5Domain) 156 | buf = append(buf, byte(len(host))) 157 | buf = append(buf, host...) 158 | } 159 | buf = append(buf, byte(port>>8), byte(port)) 160 | 161 | if _, err := conn.Write(buf); err != nil { 162 | return nil, errors.New("proxy: failed to write connect request to SOCKS5 proxy at " + s.addr + ": " + err.Error()) 163 | } 164 | 165 | if _, err := io.ReadFull(conn, buf[:4]); err != nil { 166 | return nil, errors.New("proxy: failed to read connect reply from SOCKS5 proxy at " + s.addr + ": " + err.Error()) 167 | } 168 | 169 | failure := "unknown error" 170 | if int(buf[1]) < len(socks5Errors) { 171 | failure = socks5Errors[buf[1]] 172 | } 173 | 174 | if len(failure) > 0 { 175 | return nil, errors.New("proxy: SOCKS5 proxy at " + s.addr + " failed to connect: " + failure) 176 | } 177 | 178 | bytesToDiscard := 0 179 | switch buf[3] { 180 | case socks5IP4: 181 | bytesToDiscard = net.IPv4len 182 | case socks5IP6: 183 | bytesToDiscard = net.IPv6len 184 | case socks5Domain: 185 | _, err := io.ReadFull(conn, buf[:1]) 186 | if err != nil { 187 | return nil, errors.New("proxy: failed to read domain length from SOCKS5 proxy at " + s.addr + ": " + err.Error()) 188 | } 189 | bytesToDiscard = int(buf[0]) 190 | default: 191 | return nil, errors.New("proxy: got unknown address type " + strconv.Itoa(int(buf[3])) + " from SOCKS5 proxy at " + s.addr) 192 | } 193 | 194 | if cap(buf) < bytesToDiscard { 195 | buf = make([]byte, bytesToDiscard) 196 | } else { 197 | buf = buf[:bytesToDiscard] 198 | } 199 | if _, err := io.ReadFull(conn, buf); err != nil { 200 | return nil, errors.New("proxy: failed to read address from SOCKS5 proxy at " + s.addr + ": " + err.Error()) 201 | } 202 | 203 | // Also need to discard the port number 204 | if _, err := io.ReadFull(conn, buf[:2]); err != nil { 205 | return nil, errors.New("proxy: failed to read port from SOCKS5 proxy at " + s.addr + ": " + err.Error()) 206 | } 207 | 208 | closeConn = nil 209 | return conn, nil 210 | } 211 | -------------------------------------------------------------------------------- /vendor/vendor.json: -------------------------------------------------------------------------------- 1 | { 2 | "comment": "", 3 | "ignore": "test", 4 | "package": [ 5 | { 6 | "checksumSHA1": "z9ckOyaoHErgXLQDx514AOMxdeo=", 7 | "path": "github.com/Sirupsen/logrus", 8 | "revision": "abc6f20dabf4b10195f233ad21ea6c5ba33acae0", 9 | "revisionTime": "2016-11-11T12:09:51Z" 10 | }, 11 | { 12 | "checksumSHA1": "RBwpnMpfQt7Jo7YWrRph0Vwe+f0=", 13 | "path": "github.com/coreos/go-systemd/activation", 14 | "revision": "48702e0da86bd25e76cfef347e2adeb434a0d0a6", 15 | "revisionTime": "2016-11-14T12:22:54Z" 16 | }, 17 | { 18 | "checksumSHA1": "e8qgBHxXbij3RVspqrkeBzMZ564=", 19 | "path": "github.com/coreos/go-systemd/util", 20 | "revision": "48702e0da86bd25e76cfef347e2adeb434a0d0a6", 21 | "revisionTime": "2016-11-14T12:22:54Z" 22 | }, 23 | { 24 | "checksumSHA1": "O8c/VKtW34XPJNNlyeb/im8vWSI=", 25 | "path": "github.com/coreos/pkg/dlopen", 26 | "revision": "447b7ec906e523386d9c53be15b55a8ae86ea944", 27 | "revisionTime": "2016-10-26T22:29:26Z" 28 | }, 29 | { 30 | "checksumSHA1": "wV/3d0bXQI540Y6lVXgwfxfboys=", 31 | "path": "github.com/docker/go-connections/sockets", 32 | "revision": "4ccf312bf1d35e5dbda654e57a9be4c3f3cd0366", 33 | "revisionTime": "2016-11-15T16:18:49Z" 34 | }, 35 | { 36 | "checksumSHA1": "O8CWhk39rLpO38BIrEa7TKPSIGE=", 37 | "path": "github.com/docker/go-plugins-helpers/network", 38 | "revision": "60d242cfd0fb30e5002fbf76bf6872e81e85adba", 39 | "revisionTime": "2016-10-31T11:46:40Z" 40 | }, 41 | { 42 | "checksumSHA1": "SK1epV582t6zeBtowO7cidLFgRE=", 43 | "path": "github.com/docker/go-plugins-helpers/sdk", 44 | "revision": "60d242cfd0fb30e5002fbf76bf6872e81e85adba", 45 | "revisionTime": "2016-10-31T11:46:40Z" 46 | }, 47 | { 48 | "checksumSHA1": "3AoPMXlmVq2+iWMpsdJZkcUKHB8=", 49 | "path": "github.com/opencontainers/runc/libcontainer/user", 50 | "revision": "43c43004ef0563ceab23bb8f254cd5061a6f607e", 51 | "revisionTime": "2016-11-14T11:01:43Z" 52 | }, 53 | { 54 | "checksumSHA1": "w2mF2cKDob+aDSFxR5n3g2W9Slo=", 55 | "path": "github.com/urfave/cli", 56 | "revision": "a14d7d367bc02b1f57d88de97926727f2d936387", 57 | "revisionTime": "2016-08-29T00:43:50Z", 58 | "version": "v1.18.1", 59 | "versionExact": "v1.18.1" 60 | }, 61 | { 62 | "checksumSHA1": "AbGpMPO4ROPOaLo2SSvZBGGnJp0=", 63 | "path": "github.com/vishvananda/netlink", 64 | "revision": "a4f22d8ad2327663017dbb309b5e3f8b6f348020", 65 | "revisionTime": "2016-11-23T01:07:05Z" 66 | }, 67 | { 68 | "checksumSHA1": "jWu7ylTcopMQHmpV3YdfaLUYikw=", 69 | "path": "github.com/vishvananda/netlink/nl", 70 | "revision": "a4f22d8ad2327663017dbb309b5e3f8b6f348020", 71 | "revisionTime": "2016-11-23T01:07:05Z" 72 | }, 73 | { 74 | "checksumSHA1": "zjfUA3qOv6grhBLpyJ+7EejXWQE=", 75 | "path": "github.com/vishvananda/netns", 76 | "revision": "8ba1072b58e0c2a240eb5f6120165c7776c3e7b8", 77 | "revisionTime": "2016-04-30T05:37:23Z" 78 | }, 79 | { 80 | "checksumSHA1": "LvdVRE0FqdR68SvVpRkHs1rxhcA=", 81 | "path": "golang.org/x/net/proxy", 82 | "revision": "b2ed34f6fc8d65cc6a090fb87692ea6b1162fddd", 83 | "revisionTime": "2016-01-20T20:16:54Z" 84 | }, 85 | { 86 | "checksumSHA1": "KqecwXo3OO+p4N+E9RhlHvl9I+w=", 87 | "path": "golang.org/x/sys/unix", 88 | "revision": "b699b7032584f0953262cb2788a0ca19bb494703", 89 | "revisionTime": "2016-11-10T11:58:56Z" 90 | } 91 | ], 92 | "rootPath": "github.com/yunify/docker-plugin-hostnic" 93 | } 94 | --------------------------------------------------------------------------------