Переглянути джерело

Merge with docker/libnetwork

Signed-off-by: Jana Radhakrishnan <mrjana@socketplane.io>
Jana Radhakrishnan 10 роки тому
батько
коміт
91589f4948
100 змінених файлів з 12169 додано та 0 видалено
  1. 38 0
      libnetwork/Godeps/Godeps.json
  2. 5 0
      libnetwork/Godeps/Readme
  3. 2 0
      libnetwork/Godeps/_workspace/.gitignore
  4. 1 0
      libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/.gitignore
  5. 8 0
      libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/.travis.yml
  6. 21 0
      libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/LICENSE
  7. 373 0
      libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/README.md
  8. 252 0
      libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/entry.go
  9. 53 0
      libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/entry_test.go
  10. 40 0
      libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/examples/basic/basic.go
  11. 35 0
      libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/examples/hook/hook.go
  12. 186 0
      libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/exported.go
  13. 44 0
      libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/formatter.go
  14. 88 0
      libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/formatter_bench_test.go
  15. 122 0
      libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/hook_test.go
  16. 34 0
      libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks.go
  17. 54 0
      libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/airbrake/airbrake.go
  18. 28 0
      libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/papertrail/README.md
  19. 55 0
      libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/papertrail/papertrail.go
  20. 26 0
      libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/papertrail/papertrail_test.go
  21. 61 0
      libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/sentry/README.md
  22. 100 0
      libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/sentry/sentry.go
  23. 97 0
      libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/sentry/sentry_test.go
  24. 20 0
      libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/syslog/README.md
  25. 59 0
      libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/syslog/syslog.go
  26. 26 0
      libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/syslog/syslog_test.go
  27. 26 0
      libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/json_formatter.go
  28. 161 0
      libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/logger.go
  29. 94 0
      libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/logrus.go
  30. 283 0
      libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/logrus_test.go
  31. 12 0
      libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/terminal_darwin.go
  32. 20 0
      libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/terminal_freebsd.go
  33. 12 0
      libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/terminal_linux.go
  34. 21 0
      libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/terminal_notwindows.go
  35. 8 0
      libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/terminal_openbsd.go
  36. 27 0
      libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/terminal_windows.go
  37. 124 0
      libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/text_formatter.go
  38. 33 0
      libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/text_formatter_test.go
  39. 31 0
      libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/writer.go
  40. 720 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/bridge/driver.go
  41. 161 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/bridge/driver_test.go
  42. 160 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/ipallocator/allocator.go
  43. 681 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/ipallocator/allocator_test.go
  44. 10 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/network.go
  45. 175 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/network_test.go
  46. 153 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/portallocator/portallocator.go
  47. 245 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/portallocator/portallocator_test.go
  48. 176 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/portmapper/mapper.go
  49. 152 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/portmapper/mapper_test.go
  50. 18 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/portmapper/mock_proxy.go
  51. 161 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/portmapper/proxy.go
  52. 118 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/utils.go
  53. 93 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/parsers/kernel/kernel.go
  54. 61 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/parsers/kernel/kernel_test.go
  55. 16 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/parsers/kernel/uname_linux.go
  56. 15 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/parsers/kernel/uname_unsupported.go
  57. 1 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/reexec/MAINTAINERS
  58. 5 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/reexec/README.md
  59. 18 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/reexec/command_linux.go
  60. 11 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/reexec/command_unsupported.go
  61. 42 0
      libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/reexec/reexec.go
  62. 2 0
      libnetwork/Godeps/_workspace/src/github.com/docker/libcontainer/netlink/MAINTAINERS
  63. 31 0
      libnetwork/Godeps/_workspace/src/github.com/docker/libcontainer/netlink/netlink.go
  64. 1307 0
      libnetwork/Godeps/_workspace/src/github.com/docker/libcontainer/netlink/netlink_linux.go
  65. 5 0
      libnetwork/Godeps/_workspace/src/github.com/docker/libcontainer/netlink/netlink_linux_arm.go
  66. 7 0
      libnetwork/Godeps/_workspace/src/github.com/docker/libcontainer/netlink/netlink_linux_notarm.go
  67. 408 0
      libnetwork/Godeps/_workspace/src/github.com/docker/libcontainer/netlink/netlink_linux_test.go
  68. 88 0
      libnetwork/Godeps/_workspace/src/github.com/docker/libcontainer/netlink/netlink_unsupported.go
  69. 3 0
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/.travis.yml
  70. 192 0
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/LICENSE
  71. 29 0
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/Makefile
  72. 83 0
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/README.md
  73. 43 0
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/addr.go
  74. 114 0
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/addr_linux.go
  75. 45 0
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/addr_test.go
  76. 175 0
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/link.go
  77. 696 0
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/link_linux.go
  78. 531 0
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/link_test.go
  79. 22 0
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/neigh.go
  80. 189 0
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/neigh_linux.go
  81. 104 0
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/neigh_test.go
  82. 39 0
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/netlink.go
  83. 34 0
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/netlink_test.go
  84. 143 0
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/netlink_unspecified.go
  85. 47 0
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/addr_linux.go
  86. 39 0
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/addr_linux_test.go
  87. 81 0
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/link_linux.go
  88. 417 0
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/nl_linux.go
  89. 60 0
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/nl_linux_test.go
  90. 33 0
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/route_linux.go
  91. 43 0
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/route_linux_test.go
  92. 259 0
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/xfrm_linux.go
  93. 161 0
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/xfrm_linux_test.go
  94. 119 0
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/xfrm_policy_linux.go
  95. 109 0
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/xfrm_policy_linux_test.go
  96. 221 0
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/xfrm_state_linux.go
  97. 207 0
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/xfrm_state_linux_test.go
  98. 53 0
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/protinfo.go
  99. 60 0
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/protinfo_linux.go
  100. 98 0
      libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/protinfo_test.go

+ 38 - 0
libnetwork/Godeps/Godeps.json

@@ -0,0 +1,38 @@
+{
+	"ImportPath": "github.com/docker/libnetwork",
+	"GoVersion": "go1.4.2",
+	"Packages": [
+		"./..."
+	],
+	"Deps": [
+		{
+			"ImportPath": "github.com/Sirupsen/logrus",
+			"Comment": "v0.6.4-12-g467d9d5",
+			"Rev": "467d9d55c2d2c17248441a8fc661561161f40d5e"
+		},
+		{
+			"ImportPath": "github.com/docker/docker/daemon/networkdriver",
+			"Comment": "v1.4.1-1379-g8e107a9",
+			"Rev": "8e107a93210c54f22ec1354d969c771b1abfbe05"
+		},
+		{
+			"ImportPath": "github.com/docker/docker/pkg/parsers/kernel",
+			"Comment": "v1.4.1-1379-g8e107a9",
+			"Rev": "8e107a93210c54f22ec1354d969c771b1abfbe05"
+		},
+		{
+			"ImportPath": "github.com/docker/docker/pkg/reexec",
+			"Comment": "v1.4.1-1379-g8e107a9",
+			"Rev": "8e107a93210c54f22ec1354d969c771b1abfbe05"
+		},
+		{
+			"ImportPath": "github.com/docker/libcontainer/netlink",
+			"Comment": "v1.4.0-324-g88989e6",
+			"Rev": "88989e66d3a1ab960deb37f3dd7f824d85e1b9bc"
+		},
+		{
+			"ImportPath": "github.com/vishvananda/netlink",
+			"Rev": "8eb64238879fed52fd51c5b30ad20b928fb4c36c"
+		}
+	]
+}

+ 5 - 0
libnetwork/Godeps/Readme

@@ -0,0 +1,5 @@
+This directory tree is generated automatically by godep.
+
+Please do not edit.
+
+See https://github.com/tools/godep for more information.

+ 2 - 0
libnetwork/Godeps/_workspace/.gitignore

@@ -0,0 +1,2 @@
+/pkg
+/bin

+ 1 - 0
libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/.gitignore

@@ -0,0 +1 @@
+logrus

+ 8 - 0
libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/.travis.yml

@@ -0,0 +1,8 @@
+language: go
+go:
+  - 1.2
+  - 1.3
+  - 1.4
+  - tip
+install:
+  - go get -t ./...

+ 21 - 0
libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/LICENSE

@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Simon Eskildsen
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.

+ 373 - 0
libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/README.md

@@ -0,0 +1,373 @@
+# Logrus <img src="http://i.imgur.com/hTeVwmJ.png" width="40" height="40" alt=":walrus:" class="emoji" title=":walrus:"/>&nbsp;[![Build Status](https://travis-ci.org/Sirupsen/logrus.svg?branch=master)](https://travis-ci.org/Sirupsen/logrus)&nbsp;[![godoc reference](https://godoc.org/github.com/Sirupsen/logrus?status.png)][godoc]
+
+Logrus is a structured logger for Go (golang), completely API compatible with
+the standard library logger. [Godoc][godoc]. **Please note the Logrus API is not
+yet stable (pre 1.0), the core API is unlikely to change much but please version
+control your Logrus to make sure you aren't fetching latest `master` on every
+build.**
+
+Nicely color-coded in development (when a TTY is attached, otherwise just
+plain text):
+
+![Colored](http://i.imgur.com/PY7qMwd.png)
+
+With `log.Formatter = new(logrus.JSONFormatter)`, for easy parsing by logstash
+or Splunk:
+
+```json
+{"animal":"walrus","level":"info","msg":"A group of walrus emerges from the
+ocean","size":10,"time":"2014-03-10 19:57:38.562264131 -0400 EDT"}
+
+{"level":"warning","msg":"The group's number increased tremendously!",
+"number":122,"omg":true,"time":"2014-03-10 19:57:38.562471297 -0400 EDT"}
+
+{"animal":"walrus","level":"info","msg":"A giant walrus appears!",
+"size":10,"time":"2014-03-10 19:57:38.562500591 -0400 EDT"}
+
+{"animal":"walrus","level":"info","msg":"Tremendously sized cow enters the ocean.",
+"size":9,"time":"2014-03-10 19:57:38.562527896 -0400 EDT"}
+
+{"level":"fatal","msg":"The ice breaks!","number":100,"omg":true,
+"time":"2014-03-10 19:57:38.562543128 -0400 EDT"}
+```
+
+With the default `log.Formatter = new(logrus.TextFormatter)` when a TTY is not
+attached, the output is compatible with the
+[logfmt](http://godoc.org/github.com/kr/logfmt) format:
+
+```text
+time="2014-04-20 15:36:23.830442383 -0400 EDT" level="info" msg="A group of walrus emerges from the ocean" animal="walrus" size=10
+time="2014-04-20 15:36:23.830584199 -0400 EDT" level="warning" msg="The group's number increased tremendously!" omg=true number=122
+time="2014-04-20 15:36:23.830596521 -0400 EDT" level="info" msg="A giant walrus appears!" animal="walrus" size=10
+time="2014-04-20 15:36:23.830611837 -0400 EDT" level="info" msg="Tremendously sized cow enters the ocean." animal="walrus" size=9
+time="2014-04-20 15:36:23.830626464 -0400 EDT" level="fatal" msg="The ice breaks!" omg=true number=100
+```
+
+#### Example
+
+The simplest way to use Logrus is simply the package-level exported logger:
+
+```go
+package main
+
+import (
+  log "github.com/Sirupsen/logrus"
+)
+
+func main() {
+  log.WithFields(log.Fields{
+    "animal": "walrus",
+  }).Info("A walrus appears")
+}
+```
+
+Note that it's completely api-compatible with the stdlib logger, so you can
+replace your `log` imports everywhere with `log "github.com/Sirupsen/logrus"`
+and you'll now have the flexibility of Logrus. You can customize it all you
+want:
+
+```go
+package main
+
+import (
+  "os"
+  log "github.com/Sirupsen/logrus"
+  "github.com/Sirupsen/logrus/hooks/airbrake"
+)
+
+func init() {
+  // Log as JSON instead of the default ASCII formatter.
+  log.SetFormatter(&log.JSONFormatter{})
+
+  // Use the Airbrake hook to report errors that have Error severity or above to
+  // an exception tracker. You can create custom hooks, see the Hooks section.
+  log.AddHook(&logrus_airbrake.AirbrakeHook{})
+
+  // Output to stderr instead of stdout, could also be a file.
+  log.SetOutput(os.Stderr)
+
+  // Only log the warning severity or above.
+  log.SetLevel(log.WarnLevel)
+}
+
+func main() {
+  log.WithFields(log.Fields{
+    "animal": "walrus",
+    "size":   10,
+  }).Info("A group of walrus emerges from the ocean")
+
+  log.WithFields(log.Fields{
+    "omg":    true,
+    "number": 122,
+  }).Warn("The group's number increased tremendously!")
+
+  log.WithFields(log.Fields{
+    "omg":    true,
+    "number": 100,
+  }).Fatal("The ice breaks!")
+}
+```
+
+For more advanced usage such as logging to multiple locations from the same
+application, you can also create an instance of the `logrus` Logger:
+
+```go
+package main
+
+import (
+  "github.com/Sirupsen/logrus"
+)
+
+// Create a new instance of the logger. You can have any number of instances.
+var log = logrus.New()
+
+func main() {
+  // The API for setting attributes is a little different than the package level
+  // exported logger. See Godoc.
+  log.Out = os.Stderr
+
+  log.WithFields(logrus.Fields{
+    "animal": "walrus",
+    "size":   10,
+  }).Info("A group of walrus emerges from the ocean")
+}
+```
+
+#### Fields
+
+Logrus encourages careful, structured logging though logging fields instead of
+long, unparseable error messages. For example, instead of: `log.Fatalf("Failed
+to send event %s to topic %s with key %d")`, you should log the much more
+discoverable:
+
+```go
+log.WithFields(log.Fields{
+  "event": event,
+  "topic": topic,
+  "key": key,
+}).Fatal("Failed to send event")
+```
+
+We've found this API forces you to think about logging in a way that produces
+much more useful logging messages. We've been in countless situations where just
+a single added field to a log statement that was already there would've saved us
+hours. The `WithFields` call is optional.
+
+In general, with Logrus using any of the `printf`-family functions should be
+seen as a hint you should add a field, however, you can still use the
+`printf`-family functions with Logrus.
+
+#### Hooks
+
+You can add hooks for logging levels. For example to send errors to an exception
+tracking service on `Error`, `Fatal` and `Panic`, info to StatsD or log to
+multiple places simultaneously, e.g. syslog.
+
+```go
+// Not the real implementation of the Airbrake hook. Just a simple sample.
+import (
+  log "github.com/Sirupsen/logrus"
+)
+
+func init() {
+  log.AddHook(new(AirbrakeHook))
+}
+
+type AirbrakeHook struct{}
+
+// `Fire()` takes the entry that the hook is fired for. `entry.Data[]` contains
+// the fields for the entry. See the Fields section of the README.
+func (hook *AirbrakeHook) Fire(entry *logrus.Entry) error {
+  err := airbrake.Notify(entry.Data["error"].(error))
+  if err != nil {
+    log.WithFields(log.Fields{
+      "source":   "airbrake",
+      "endpoint": airbrake.Endpoint,
+    }).Info("Failed to send error to Airbrake")
+  }
+
+  return nil
+}
+
+// `Levels()` returns a slice of `Levels` the hook is fired for.
+func (hook *AirbrakeHook) Levels() []log.Level {
+  return []log.Level{
+    log.ErrorLevel,
+    log.FatalLevel,
+    log.PanicLevel,
+  }
+}
+```
+
+Logrus comes with built-in hooks. Add those, or your custom hook, in `init`:
+
+```go
+import (
+  log "github.com/Sirupsen/logrus"
+  "github.com/Sirupsen/logrus/hooks/airbrake"
+  "github.com/Sirupsen/logrus/hooks/syslog"
+  "log/syslog"
+)
+
+func init() {
+  log.AddHook(new(logrus_airbrake.AirbrakeHook))
+
+  hook, err := logrus_syslog.NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, "")
+  if err != nil {
+    log.Error("Unable to connect to local syslog daemon")
+  } else {
+    log.AddHook(hook)
+  }
+}
+```
+
+* [`github.com/Sirupsen/logrus/hooks/airbrake`](https://github.com/Sirupsen/logrus/blob/master/hooks/airbrake/airbrake.go)
+  Send errors to an exception tracking service compatible with the Airbrake API.
+  Uses [`airbrake-go`](https://github.com/tobi/airbrake-go) behind the scenes.
+
+* [`github.com/Sirupsen/logrus/hooks/papertrail`](https://github.com/Sirupsen/logrus/blob/master/hooks/papertrail/papertrail.go)
+  Send errors to the Papertrail hosted logging service via UDP.
+
+* [`github.com/Sirupsen/logrus/hooks/syslog`](https://github.com/Sirupsen/logrus/blob/master/hooks/syslog/syslog.go)
+  Send errors to remote syslog server.
+  Uses standard library `log/syslog` behind the scenes.
+
+* [`github.com/nubo/hiprus`](https://github.com/nubo/hiprus)
+  Send errors to a channel in hipchat.
+
+* [`github.com/sebest/logrusly`](https://github.com/sebest/logrusly)
+  Send logs to Loggly (https://www.loggly.com/)
+
+* [`github.com/johntdyer/slackrus`](https://github.com/johntdyer/slackrus)
+  Hook for Slack chat.
+
+#### Level logging
+
+Logrus has six logging levels: Debug, Info, Warning, Error, Fatal and Panic.
+
+```go
+log.Debug("Useful debugging information.")
+log.Info("Something noteworthy happened!")
+log.Warn("You should probably take a look at this.")
+log.Error("Something failed but I'm not quitting.")
+// Calls os.Exit(1) after logging
+log.Fatal("Bye.")
+// Calls panic() after logging
+log.Panic("I'm bailing.")
+```
+
+You can set the logging level on a `Logger`, then it will only log entries with
+that severity or anything above it:
+
+```go
+// Will log anything that is info or above (warn, error, fatal, panic). Default.
+log.SetLevel(log.InfoLevel)
+```
+
+It may be useful to set `log.Level = logrus.DebugLevel` in a debug or verbose
+environment if your application has that.
+
+#### Entries
+
+Besides the fields added with `WithField` or `WithFields` some fields are
+automatically added to all logging events:
+
+1. `time`. The timestamp when the entry was created.
+2. `msg`. The logging message passed to `{Info,Warn,Error,Fatal,Panic}` after
+   the `AddFields` call. E.g. `Failed to send event.`
+3. `level`. The logging level. E.g. `info`.
+
+#### Environments
+
+Logrus has no notion of environment.
+
+If you wish for hooks and formatters to only be used in specific environments,
+you should handle that yourself. For example, if your application has a global
+variable `Environment`, which is a string representation of the environment you
+could do:
+
+```go
+import (
+  log "github.com/Sirupsen/logrus"
+)
+
+init() {
+  // do something here to set environment depending on an environment variable
+  // or command-line flag
+  if Environment == "production" {
+    log.SetFormatter(logrus.JSONFormatter)
+  } else {
+    // The TextFormatter is default, you don't actually have to do this.
+    log.SetFormatter(logrus.TextFormatter)
+  }
+}
+```
+
+This configuration is how `logrus` was intended to be used, but JSON in
+production is mostly only useful if you do log aggregation with tools like
+Splunk or Logstash.
+
+#### Formatters
+
+The built-in logging formatters are:
+
+* `logrus.TextFormatter`. Logs the event in colors if stdout is a tty, otherwise
+  without colors.
+  * *Note:* to force colored output when there is no TTY, set the `ForceColors`
+    field to `true`.  To force no colored output even if there is a TTY  set the
+    `DisableColors` field to `true`
+* `logrus.JSONFormatter`. Logs fields as JSON.
+
+Third party logging formatters:
+
+* [`zalgo`](https://github.com/aybabtme/logzalgo): invoking the P͉̫o̳̼̊w̖͈̰͎e̬͔̭͂r͚̼̹̲ ̫͓͉̳͈ō̠͕͖̚f̝͍̠ ͕̲̞͖͑Z̖̫̤̫ͪa͉̬͈̗l͖͎g̳̥o̰̥̅!̣͔̲̻͊̄ ̙̘̦̹̦.
+
+You can define your formatter by implementing the `Formatter` interface,
+requiring a `Format` method. `Format` takes an `*Entry`. `entry.Data` is a
+`Fields` type (`map[string]interface{}`) with all your fields as well as the
+default ones (see Entries section above):
+
+```go
+type MyJSONFormatter struct {
+}
+
+log.SetFormatter(new(MyJSONFormatter))
+
+func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
+  // Note this doesn't include Time, Level and Message which are available on
+  // the Entry. Consult `godoc` on information about those fields or read the
+  // source of the official loggers.
+  serialized, err := json.Marshal(entry.Data)
+    if err != nil {
+      return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err)
+    }
+  return append(serialized, '\n'), nil
+}
+```
+
+#### Logger as an `io.Writer`
+
+Logrus can be transormed into an `io.Writer`. That writer is the end of an `io.Pipe` and it is your responsability to close it.
+
+```go
+w := logger.Writer()
+defer w.Close()
+
+srv := http.Server{
+    // create a stdlib log.Logger that writes to
+    // logrus.Logger.
+    ErrorLog: log.New(w, "", 0),
+}
+```
+
+Each line written to that writer will be printed the usual way, using formatters
+and hooks. The level for those entries is `info`.
+
+#### Rotation
+
+Log rotation is not provided with Logrus. Log rotation should be done by an
+external program (like `logrotated(8)`) that can compress and delete old log
+entries. It should not be a feature of the application-level logger.
+
+
+[godoc]: https://godoc.org/github.com/Sirupsen/logrus

+ 252 - 0
libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/entry.go

@@ -0,0 +1,252 @@
+package logrus
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"os"
+	"time"
+)
+
+// An entry is the final or intermediate Logrus logging entry. It contains all
+// the fields passed with WithField{,s}. It's finally logged when Debug, Info,
+// Warn, Error, Fatal or Panic is called on it. These objects can be reused and
+// passed around as much as you wish to avoid field duplication.
+type Entry struct {
+	Logger *Logger
+
+	// Contains all the fields set by the user.
+	Data Fields
+
+	// Time at which the log entry was created
+	Time time.Time
+
+	// Level the log entry was logged at: Debug, Info, Warn, Error, Fatal or Panic
+	Level Level
+
+	// Message passed to Debug, Info, Warn, Error, Fatal or Panic
+	Message string
+}
+
+func NewEntry(logger *Logger) *Entry {
+	return &Entry{
+		Logger: logger,
+		// Default is three fields, give a little extra room
+		Data: make(Fields, 5),
+	}
+}
+
+// Returns a reader for the entry, which is a proxy to the formatter.
+func (entry *Entry) Reader() (*bytes.Buffer, error) {
+	serialized, err := entry.Logger.Formatter.Format(entry)
+	return bytes.NewBuffer(serialized), err
+}
+
+// Returns the string representation from the reader and ultimately the
+// formatter.
+func (entry *Entry) String() (string, error) {
+	reader, err := entry.Reader()
+	if err != nil {
+		return "", err
+	}
+
+	return reader.String(), err
+}
+
+// Add a single field to the Entry.
+func (entry *Entry) WithField(key string, value interface{}) *Entry {
+	return entry.WithFields(Fields{key: value})
+}
+
+// Add a map of fields to the Entry.
+func (entry *Entry) WithFields(fields Fields) *Entry {
+	data := Fields{}
+	for k, v := range entry.Data {
+		data[k] = v
+	}
+	for k, v := range fields {
+		data[k] = v
+	}
+	return &Entry{Logger: entry.Logger, Data: data}
+}
+
+func (entry *Entry) log(level Level, msg string) {
+	entry.Time = time.Now()
+	entry.Level = level
+	entry.Message = msg
+
+	if err := entry.Logger.Hooks.Fire(level, entry); err != nil {
+		entry.Logger.mu.Lock()
+		fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err)
+		entry.Logger.mu.Unlock()
+	}
+
+	reader, err := entry.Reader()
+	if err != nil {
+		entry.Logger.mu.Lock()
+		fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err)
+		entry.Logger.mu.Unlock()
+	}
+
+	entry.Logger.mu.Lock()
+	defer entry.Logger.mu.Unlock()
+
+	_, err = io.Copy(entry.Logger.Out, reader)
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err)
+	}
+
+	// To avoid Entry#log() returning a value that only would make sense for
+	// panic() to use in Entry#Panic(), we avoid the allocation by checking
+	// directly here.
+	if level <= PanicLevel {
+		panic(entry)
+	}
+}
+
+func (entry *Entry) Debug(args ...interface{}) {
+	if entry.Logger.Level >= DebugLevel {
+		entry.log(DebugLevel, fmt.Sprint(args...))
+	}
+}
+
+func (entry *Entry) Print(args ...interface{}) {
+	entry.Info(args...)
+}
+
+func (entry *Entry) Info(args ...interface{}) {
+	if entry.Logger.Level >= InfoLevel {
+		entry.log(InfoLevel, fmt.Sprint(args...))
+	}
+}
+
+func (entry *Entry) Warn(args ...interface{}) {
+	if entry.Logger.Level >= WarnLevel {
+		entry.log(WarnLevel, fmt.Sprint(args...))
+	}
+}
+
+func (entry *Entry) Warning(args ...interface{}) {
+	entry.Warn(args...)
+}
+
+func (entry *Entry) Error(args ...interface{}) {
+	if entry.Logger.Level >= ErrorLevel {
+		entry.log(ErrorLevel, fmt.Sprint(args...))
+	}
+}
+
+func (entry *Entry) Fatal(args ...interface{}) {
+	if entry.Logger.Level >= FatalLevel {
+		entry.log(FatalLevel, fmt.Sprint(args...))
+	}
+	os.Exit(1)
+}
+
+func (entry *Entry) Panic(args ...interface{}) {
+	if entry.Logger.Level >= PanicLevel {
+		entry.log(PanicLevel, fmt.Sprint(args...))
+	}
+	panic(fmt.Sprint(args...))
+}
+
+// Entry Printf family functions
+
+func (entry *Entry) Debugf(format string, args ...interface{}) {
+	if entry.Logger.Level >= DebugLevel {
+		entry.Debug(fmt.Sprintf(format, args...))
+	}
+}
+
+func (entry *Entry) Infof(format string, args ...interface{}) {
+	if entry.Logger.Level >= InfoLevel {
+		entry.Info(fmt.Sprintf(format, args...))
+	}
+}
+
+func (entry *Entry) Printf(format string, args ...interface{}) {
+	entry.Infof(format, args...)
+}
+
+func (entry *Entry) Warnf(format string, args ...interface{}) {
+	if entry.Logger.Level >= WarnLevel {
+		entry.Warn(fmt.Sprintf(format, args...))
+	}
+}
+
+func (entry *Entry) Warningf(format string, args ...interface{}) {
+	entry.Warnf(format, args...)
+}
+
+func (entry *Entry) Errorf(format string, args ...interface{}) {
+	if entry.Logger.Level >= ErrorLevel {
+		entry.Error(fmt.Sprintf(format, args...))
+	}
+}
+
+func (entry *Entry) Fatalf(format string, args ...interface{}) {
+	if entry.Logger.Level >= FatalLevel {
+		entry.Fatal(fmt.Sprintf(format, args...))
+	}
+}
+
+func (entry *Entry) Panicf(format string, args ...interface{}) {
+	if entry.Logger.Level >= PanicLevel {
+		entry.Panic(fmt.Sprintf(format, args...))
+	}
+}
+
+// Entry Println family functions
+
+func (entry *Entry) Debugln(args ...interface{}) {
+	if entry.Logger.Level >= DebugLevel {
+		entry.Debug(entry.sprintlnn(args...))
+	}
+}
+
+func (entry *Entry) Infoln(args ...interface{}) {
+	if entry.Logger.Level >= InfoLevel {
+		entry.Info(entry.sprintlnn(args...))
+	}
+}
+
+func (entry *Entry) Println(args ...interface{}) {
+	entry.Infoln(args...)
+}
+
+func (entry *Entry) Warnln(args ...interface{}) {
+	if entry.Logger.Level >= WarnLevel {
+		entry.Warn(entry.sprintlnn(args...))
+	}
+}
+
+func (entry *Entry) Warningln(args ...interface{}) {
+	entry.Warnln(args...)
+}
+
+func (entry *Entry) Errorln(args ...interface{}) {
+	if entry.Logger.Level >= ErrorLevel {
+		entry.Error(entry.sprintlnn(args...))
+	}
+}
+
+func (entry *Entry) Fatalln(args ...interface{}) {
+	if entry.Logger.Level >= FatalLevel {
+		entry.Fatal(entry.sprintlnn(args...))
+	}
+}
+
+func (entry *Entry) Panicln(args ...interface{}) {
+	if entry.Logger.Level >= PanicLevel {
+		entry.Panic(entry.sprintlnn(args...))
+	}
+}
+
+// Sprintlnn => Sprint no newline. This is to get the behavior of how
+// fmt.Sprintln where spaces are always added between operands, regardless of
+// their type. Instead of vendoring the Sprintln implementation to spare a
+// string allocation, we do the simplest thing.
+func (entry *Entry) sprintlnn(args ...interface{}) string {
+	msg := fmt.Sprintln(args...)
+	return msg[:len(msg)-1]
+}

+ 53 - 0
libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/entry_test.go

@@ -0,0 +1,53 @@
+package logrus
+
+import (
+	"bytes"
+	"fmt"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestEntryPanicln(t *testing.T) {
+	errBoom := fmt.Errorf("boom time")
+
+	defer func() {
+		p := recover()
+		assert.NotNil(t, p)
+
+		switch pVal := p.(type) {
+		case *Entry:
+			assert.Equal(t, "kaboom", pVal.Message)
+			assert.Equal(t, errBoom, pVal.Data["err"])
+		default:
+			t.Fatalf("want type *Entry, got %T: %#v", pVal, pVal)
+		}
+	}()
+
+	logger := New()
+	logger.Out = &bytes.Buffer{}
+	entry := NewEntry(logger)
+	entry.WithField("err", errBoom).Panicln("kaboom")
+}
+
+func TestEntryPanicf(t *testing.T) {
+	errBoom := fmt.Errorf("boom again")
+
+	defer func() {
+		p := recover()
+		assert.NotNil(t, p)
+
+		switch pVal := p.(type) {
+		case *Entry:
+			assert.Equal(t, "kaboom true", pVal.Message)
+			assert.Equal(t, errBoom, pVal.Data["err"])
+		default:
+			t.Fatalf("want type *Entry, got %T: %#v", pVal, pVal)
+		}
+	}()
+
+	logger := New()
+	logger.Out = &bytes.Buffer{}
+	entry := NewEntry(logger)
+	entry.WithField("err", errBoom).Panicf("kaboom %v", true)
+}

+ 40 - 0
libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/examples/basic/basic.go

@@ -0,0 +1,40 @@
+package main
+
+import (
+	"github.com/Sirupsen/logrus"
+)
+
+var log = logrus.New()
+
+func init() {
+	log.Formatter = new(logrus.JSONFormatter)
+	log.Formatter = new(logrus.TextFormatter) // default
+}
+
+func main() {
+	defer func() {
+		err := recover()
+		if err != nil {
+			log.WithFields(logrus.Fields{
+				"omg":    true,
+				"err":    err,
+				"number": 100,
+			}).Fatal("The ice breaks!")
+		}
+	}()
+
+	log.WithFields(logrus.Fields{
+		"animal": "walrus",
+		"size":   10,
+	}).Info("A group of walrus emerges from the ocean")
+
+	log.WithFields(logrus.Fields{
+		"omg":    true,
+		"number": 122,
+	}).Warn("The group's number increased tremendously!")
+
+	log.WithFields(logrus.Fields{
+		"animal": "orca",
+		"size":   9009,
+	}).Panic("It's over 9000!")
+}

+ 35 - 0
libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/examples/hook/hook.go

@@ -0,0 +1,35 @@
+package main
+
+import (
+	"github.com/Sirupsen/logrus"
+	"github.com/Sirupsen/logrus/hooks/airbrake"
+	"github.com/tobi/airbrake-go"
+)
+
+var log = logrus.New()
+
+func init() {
+	log.Formatter = new(logrus.TextFormatter) // default
+	log.Hooks.Add(new(logrus_airbrake.AirbrakeHook))
+}
+
+func main() {
+	airbrake.Endpoint = "https://exceptions.whatever.com/notifier_api/v2/notices.xml"
+	airbrake.ApiKey = "whatever"
+	airbrake.Environment = "production"
+
+	log.WithFields(logrus.Fields{
+		"animal": "walrus",
+		"size":   10,
+	}).Info("A group of walrus emerges from the ocean")
+
+	log.WithFields(logrus.Fields{
+		"omg":    true,
+		"number": 122,
+	}).Warn("The group's number increased tremendously!")
+
+	log.WithFields(logrus.Fields{
+		"omg":    true,
+		"number": 100,
+	}).Fatal("The ice breaks!")
+}

+ 186 - 0
libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/exported.go

@@ -0,0 +1,186 @@
+package logrus
+
+import (
+	"io"
+)
+
+var (
+	// std is the name of the standard logger in stdlib `log`
+	std = New()
+)
+
+func StandardLogger() *Logger {
+	return std
+}
+
+// SetOutput sets the standard logger output.
+func SetOutput(out io.Writer) {
+	std.mu.Lock()
+	defer std.mu.Unlock()
+	std.Out = out
+}
+
+// SetFormatter sets the standard logger formatter.
+func SetFormatter(formatter Formatter) {
+	std.mu.Lock()
+	defer std.mu.Unlock()
+	std.Formatter = formatter
+}
+
+// SetLevel sets the standard logger level.
+func SetLevel(level Level) {
+	std.mu.Lock()
+	defer std.mu.Unlock()
+	std.Level = level
+}
+
+// GetLevel returns the standard logger level.
+func GetLevel() Level {
+	return std.Level
+}
+
+// AddHook adds a hook to the standard logger hooks.
+func AddHook(hook Hook) {
+	std.mu.Lock()
+	defer std.mu.Unlock()
+	std.Hooks.Add(hook)
+}
+
+// WithField creates an entry from the standard logger and adds a field to
+// it. If you want multiple fields, use `WithFields`.
+//
+// Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal
+// or Panic on the Entry it returns.
+func WithField(key string, value interface{}) *Entry {
+	return std.WithField(key, value)
+}
+
+// WithFields creates an entry from the standard logger and adds multiple
+// fields to it. This is simply a helper for `WithField`, invoking it
+// once for each field.
+//
+// Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal
+// or Panic on the Entry it returns.
+func WithFields(fields Fields) *Entry {
+	return std.WithFields(fields)
+}
+
+// Debug logs a message at level Debug on the standard logger.
+func Debug(args ...interface{}) {
+	std.Debug(args...)
+}
+
+// Print logs a message at level Info on the standard logger.
+func Print(args ...interface{}) {
+	std.Print(args...)
+}
+
+// Info logs a message at level Info on the standard logger.
+func Info(args ...interface{}) {
+	std.Info(args...)
+}
+
+// Warn logs a message at level Warn on the standard logger.
+func Warn(args ...interface{}) {
+	std.Warn(args...)
+}
+
+// Warning logs a message at level Warn on the standard logger.
+func Warning(args ...interface{}) {
+	std.Warning(args...)
+}
+
+// Error logs a message at level Error on the standard logger.
+func Error(args ...interface{}) {
+	std.Error(args...)
+}
+
+// Panic logs a message at level Panic on the standard logger.
+func Panic(args ...interface{}) {
+	std.Panic(args...)
+}
+
+// Fatal logs a message at level Fatal on the standard logger.
+func Fatal(args ...interface{}) {
+	std.Fatal(args...)
+}
+
+// Debugf logs a message at level Debug on the standard logger.
+func Debugf(format string, args ...interface{}) {
+	std.Debugf(format, args...)
+}
+
+// Printf logs a message at level Info on the standard logger.
+func Printf(format string, args ...interface{}) {
+	std.Printf(format, args...)
+}
+
+// Infof logs a message at level Info on the standard logger.
+func Infof(format string, args ...interface{}) {
+	std.Infof(format, args...)
+}
+
+// Warnf logs a message at level Warn on the standard logger.
+func Warnf(format string, args ...interface{}) {
+	std.Warnf(format, args...)
+}
+
+// Warningf logs a message at level Warn on the standard logger.
+func Warningf(format string, args ...interface{}) {
+	std.Warningf(format, args...)
+}
+
+// Errorf logs a message at level Error on the standard logger.
+func Errorf(format string, args ...interface{}) {
+	std.Errorf(format, args...)
+}
+
+// Panicf logs a message at level Panic on the standard logger.
+func Panicf(format string, args ...interface{}) {
+	std.Panicf(format, args...)
+}
+
+// Fatalf logs a message at level Fatal on the standard logger.
+func Fatalf(format string, args ...interface{}) {
+	std.Fatalf(format, args...)
+}
+
+// Debugln logs a message at level Debug on the standard logger.
+func Debugln(args ...interface{}) {
+	std.Debugln(args...)
+}
+
+// Println logs a message at level Info on the standard logger.
+func Println(args ...interface{}) {
+	std.Println(args...)
+}
+
+// Infoln logs a message at level Info on the standard logger.
+func Infoln(args ...interface{}) {
+	std.Infoln(args...)
+}
+
+// Warnln logs a message at level Warn on the standard logger.
+func Warnln(args ...interface{}) {
+	std.Warnln(args...)
+}
+
+// Warningln logs a message at level Warn on the standard logger.
+func Warningln(args ...interface{}) {
+	std.Warningln(args...)
+}
+
+// Errorln logs a message at level Error on the standard logger.
+func Errorln(args ...interface{}) {
+	std.Errorln(args...)
+}
+
+// Panicln logs a message at level Panic on the standard logger.
+func Panicln(args ...interface{}) {
+	std.Panicln(args...)
+}
+
+// Fatalln logs a message at level Fatal on the standard logger.
+func Fatalln(args ...interface{}) {
+	std.Fatalln(args...)
+}

+ 44 - 0
libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/formatter.go

@@ -0,0 +1,44 @@
+package logrus
+
+// The Formatter interface is used to implement a custom Formatter. It takes an
+// `Entry`. It exposes all the fields, including the default ones:
+//
+// * `entry.Data["msg"]`. The message passed from Info, Warn, Error ..
+// * `entry.Data["time"]`. The timestamp.
+// * `entry.Data["level"]. The level the entry was logged at.
+//
+// Any additional fields added with `WithField` or `WithFields` are also in
+// `entry.Data`. Format is expected to return an array of bytes which are then
+// logged to `logger.Out`.
+type Formatter interface {
+	Format(*Entry) ([]byte, error)
+}
+
+// This is to not silently overwrite `time`, `msg` and `level` fields when
+// dumping it. If this code wasn't there doing:
+//
+//  logrus.WithField("level", 1).Info("hello")
+//
+// Would just silently drop the user provided level. Instead with this code
+// it'll logged as:
+//
+//  {"level": "info", "fields.level": 1, "msg": "hello", "time": "..."}
+//
+// It's not exported because it's still using Data in an opinionated way. It's to
+// avoid code duplication between the two default formatters.
+func prefixFieldClashes(data Fields) {
+	_, ok := data["time"]
+	if ok {
+		data["fields.time"] = data["time"]
+	}
+
+	_, ok = data["msg"]
+	if ok {
+		data["fields.msg"] = data["msg"]
+	}
+
+	_, ok = data["level"]
+	if ok {
+		data["fields.level"] = data["level"]
+	}
+}

+ 88 - 0
libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/formatter_bench_test.go

@@ -0,0 +1,88 @@
+package logrus
+
+import (
+	"testing"
+	"time"
+)
+
+// smallFields is a small size data set for benchmarking
+var smallFields = Fields{
+	"foo":   "bar",
+	"baz":   "qux",
+	"one":   "two",
+	"three": "four",
+}
+
+// largeFields is a large size data set for benchmarking
+var largeFields = Fields{
+	"foo":       "bar",
+	"baz":       "qux",
+	"one":       "two",
+	"three":     "four",
+	"five":      "six",
+	"seven":     "eight",
+	"nine":      "ten",
+	"eleven":    "twelve",
+	"thirteen":  "fourteen",
+	"fifteen":   "sixteen",
+	"seventeen": "eighteen",
+	"nineteen":  "twenty",
+	"a":         "b",
+	"c":         "d",
+	"e":         "f",
+	"g":         "h",
+	"i":         "j",
+	"k":         "l",
+	"m":         "n",
+	"o":         "p",
+	"q":         "r",
+	"s":         "t",
+	"u":         "v",
+	"w":         "x",
+	"y":         "z",
+	"this":      "will",
+	"make":      "thirty",
+	"entries":   "yeah",
+}
+
+func BenchmarkSmallTextFormatter(b *testing.B) {
+	doBenchmark(b, &TextFormatter{DisableColors: true}, smallFields)
+}
+
+func BenchmarkLargeTextFormatter(b *testing.B) {
+	doBenchmark(b, &TextFormatter{DisableColors: true}, largeFields)
+}
+
+func BenchmarkSmallColoredTextFormatter(b *testing.B) {
+	doBenchmark(b, &TextFormatter{ForceColors: true}, smallFields)
+}
+
+func BenchmarkLargeColoredTextFormatter(b *testing.B) {
+	doBenchmark(b, &TextFormatter{ForceColors: true}, largeFields)
+}
+
+func BenchmarkSmallJSONFormatter(b *testing.B) {
+	doBenchmark(b, &JSONFormatter{}, smallFields)
+}
+
+func BenchmarkLargeJSONFormatter(b *testing.B) {
+	doBenchmark(b, &JSONFormatter{}, largeFields)
+}
+
+func doBenchmark(b *testing.B, formatter Formatter, fields Fields) {
+	entry := &Entry{
+		Time:    time.Time{},
+		Level:   InfoLevel,
+		Message: "message",
+		Data:    fields,
+	}
+	var d []byte
+	var err error
+	for i := 0; i < b.N; i++ {
+		d, err = formatter.Format(entry)
+		if err != nil {
+			b.Fatal(err)
+		}
+		b.SetBytes(int64(len(d)))
+	}
+}

+ 122 - 0
libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/hook_test.go

@@ -0,0 +1,122 @@
+package logrus
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+type TestHook struct {
+	Fired bool
+}
+
+func (hook *TestHook) Fire(entry *Entry) error {
+	hook.Fired = true
+	return nil
+}
+
+func (hook *TestHook) Levels() []Level {
+	return []Level{
+		DebugLevel,
+		InfoLevel,
+		WarnLevel,
+		ErrorLevel,
+		FatalLevel,
+		PanicLevel,
+	}
+}
+
+func TestHookFires(t *testing.T) {
+	hook := new(TestHook)
+
+	LogAndAssertJSON(t, func(log *Logger) {
+		log.Hooks.Add(hook)
+		assert.Equal(t, hook.Fired, false)
+
+		log.Print("test")
+	}, func(fields Fields) {
+		assert.Equal(t, hook.Fired, true)
+	})
+}
+
+type ModifyHook struct {
+}
+
+func (hook *ModifyHook) Fire(entry *Entry) error {
+	entry.Data["wow"] = "whale"
+	return nil
+}
+
+func (hook *ModifyHook) Levels() []Level {
+	return []Level{
+		DebugLevel,
+		InfoLevel,
+		WarnLevel,
+		ErrorLevel,
+		FatalLevel,
+		PanicLevel,
+	}
+}
+
+func TestHookCanModifyEntry(t *testing.T) {
+	hook := new(ModifyHook)
+
+	LogAndAssertJSON(t, func(log *Logger) {
+		log.Hooks.Add(hook)
+		log.WithField("wow", "elephant").Print("test")
+	}, func(fields Fields) {
+		assert.Equal(t, fields["wow"], "whale")
+	})
+}
+
+func TestCanFireMultipleHooks(t *testing.T) {
+	hook1 := new(ModifyHook)
+	hook2 := new(TestHook)
+
+	LogAndAssertJSON(t, func(log *Logger) {
+		log.Hooks.Add(hook1)
+		log.Hooks.Add(hook2)
+
+		log.WithField("wow", "elephant").Print("test")
+	}, func(fields Fields) {
+		assert.Equal(t, fields["wow"], "whale")
+		assert.Equal(t, hook2.Fired, true)
+	})
+}
+
+type ErrorHook struct {
+	Fired bool
+}
+
+func (hook *ErrorHook) Fire(entry *Entry) error {
+	hook.Fired = true
+	return nil
+}
+
+func (hook *ErrorHook) Levels() []Level {
+	return []Level{
+		ErrorLevel,
+	}
+}
+
+func TestErrorHookShouldntFireOnInfo(t *testing.T) {
+	hook := new(ErrorHook)
+
+	LogAndAssertJSON(t, func(log *Logger) {
+		log.Hooks.Add(hook)
+		log.Info("test")
+	}, func(fields Fields) {
+		assert.Equal(t, hook.Fired, false)
+	})
+}
+
+func TestErrorHookShouldFireOnError(t *testing.T) {
+	hook := new(ErrorHook)
+
+	LogAndAssertJSON(t, func(log *Logger) {
+		log.Hooks.Add(hook)
+		log.Error("test")
+	}, func(fields Fields) {
+		assert.Equal(t, hook.Fired, true)
+	})
+}

+ 34 - 0
libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks.go

@@ -0,0 +1,34 @@
+package logrus
+
+// A hook to be fired when logging on the logging levels returned from
+// `Levels()` on your implementation of the interface. Note that this is not
+// fired in a goroutine or a channel with workers, you should handle such
+// functionality yourself if your call is non-blocking and you don't wish for
+// the logging calls for levels returned from `Levels()` to block.
+type Hook interface {
+	Levels() []Level
+	Fire(*Entry) error
+}
+
+// Internal type for storing the hooks on a logger instance.
+type levelHooks map[Level][]Hook
+
+// Add a hook to an instance of logger. This is called with
+// `log.Hooks.Add(new(MyHook))` where `MyHook` implements the `Hook` interface.
+func (hooks levelHooks) Add(hook Hook) {
+	for _, level := range hook.Levels() {
+		hooks[level] = append(hooks[level], hook)
+	}
+}
+
+// Fire all the hooks for the passed level. Used by `entry.log` to fire
+// appropriate hooks for a log entry.
+func (hooks levelHooks) Fire(level Level, entry *Entry) error {
+	for _, hook := range hooks[level] {
+		if err := hook.Fire(entry); err != nil {
+			return err
+		}
+	}
+
+	return nil
+}

+ 54 - 0
libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/airbrake/airbrake.go

@@ -0,0 +1,54 @@
+package logrus_airbrake
+
+import (
+	"github.com/Sirupsen/logrus"
+	"github.com/tobi/airbrake-go"
+)
+
+// AirbrakeHook to send exceptions to an exception-tracking service compatible
+// with the Airbrake API. You must set:
+// * airbrake.Endpoint
+// * airbrake.ApiKey
+// * airbrake.Environment (only sends exceptions when set to "production")
+//
+// Before using this hook, to send an error. Entries that trigger an Error,
+// Fatal or Panic should now include an "error" field to send to Airbrake.
+type AirbrakeHook struct{}
+
+func (hook *AirbrakeHook) Fire(entry *logrus.Entry) error {
+	if entry.Data["error"] == nil {
+		entry.Logger.WithFields(logrus.Fields{
+			"source":   "airbrake",
+			"endpoint": airbrake.Endpoint,
+		}).Warn("Exceptions sent to Airbrake must have an 'error' key with the error")
+		return nil
+	}
+
+	err, ok := entry.Data["error"].(error)
+	if !ok {
+		entry.Logger.WithFields(logrus.Fields{
+			"source":   "airbrake",
+			"endpoint": airbrake.Endpoint,
+		}).Warn("Exceptions sent to Airbrake must have an `error` key of type `error`")
+		return nil
+	}
+
+	airErr := airbrake.Notify(err)
+	if airErr != nil {
+		entry.Logger.WithFields(logrus.Fields{
+			"source":   "airbrake",
+			"endpoint": airbrake.Endpoint,
+			"error":    airErr,
+		}).Warn("Failed to send error to Airbrake")
+	}
+
+	return nil
+}
+
+func (hook *AirbrakeHook) Levels() []logrus.Level {
+	return []logrus.Level{
+		logrus.ErrorLevel,
+		logrus.FatalLevel,
+		logrus.PanicLevel,
+	}
+}

+ 28 - 0
libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/papertrail/README.md

@@ -0,0 +1,28 @@
+# Papertrail Hook for Logrus <img src="http://i.imgur.com/hTeVwmJ.png" width="40" height="40" alt=":walrus:" class="emoji" title=":walrus:" />
+
+[Papertrail](https://papertrailapp.com) provides hosted log management. Once stored in Papertrail, you can [group](http://help.papertrailapp.com/kb/how-it-works/groups/) your logs on various dimensions, [search](http://help.papertrailapp.com/kb/how-it-works/search-syntax) them, and trigger [alerts](http://help.papertrailapp.com/kb/how-it-works/alerts).
+
+In most deployments, you'll want to send logs to Papertrail via their [remote_syslog](http://help.papertrailapp.com/kb/configuration/configuring-centralized-logging-from-text-log-files-in-unix/) daemon, which requires no application-specific configuration. This hook is intended for relatively low-volume logging, likely in managed cloud hosting deployments where installing `remote_syslog` is not possible.
+
+## Usage
+
+You can find your Papertrail UDP port on your [Papertrail account page](https://papertrailapp.com/account/destinations). Substitute it below for `YOUR_PAPERTRAIL_UDP_PORT`.
+
+For `YOUR_APP_NAME`, substitute a short string that will readily identify your application or service in the logs.
+
+```go
+import (
+  "log/syslog"
+  "github.com/Sirupsen/logrus"
+  "github.com/Sirupsen/logrus/hooks/papertrail"
+)
+
+func main() {
+  log       := logrus.New()
+  hook, err := logrus_papertrail.NewPapertrailHook("logs.papertrailapp.com", YOUR_PAPERTRAIL_UDP_PORT, YOUR_APP_NAME)
+
+  if err == nil {
+    log.Hooks.Add(hook)
+  }
+}
+```

+ 55 - 0
libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/papertrail/papertrail.go

@@ -0,0 +1,55 @@
+package logrus_papertrail
+
+import (
+	"fmt"
+	"net"
+	"os"
+	"time"
+
+	"github.com/Sirupsen/logrus"
+)
+
+const (
+	format = "Jan 2 15:04:05"
+)
+
+// PapertrailHook to send logs to a logging service compatible with the Papertrail API.
+type PapertrailHook struct {
+	Host    string
+	Port    int
+	AppName string
+	UDPConn net.Conn
+}
+
+// NewPapertrailHook creates a hook to be added to an instance of logger.
+func NewPapertrailHook(host string, port int, appName string) (*PapertrailHook, error) {
+	conn, err := net.Dial("udp", fmt.Sprintf("%s:%d", host, port))
+	return &PapertrailHook{host, port, appName, conn}, err
+}
+
+// Fire is called when a log event is fired.
+func (hook *PapertrailHook) Fire(entry *logrus.Entry) error {
+	date := time.Now().Format(format)
+	msg, _ := entry.String()
+	payload := fmt.Sprintf("<22> %s %s: %s", date, hook.AppName, msg)
+
+	bytesWritten, err := hook.UDPConn.Write([]byte(payload))
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "Unable to send log line to Papertrail via UDP. Wrote %d bytes before error: %v", bytesWritten, err)
+		return err
+	}
+
+	return nil
+}
+
+// Levels returns the available logging levels.
+func (hook *PapertrailHook) Levels() []logrus.Level {
+	return []logrus.Level{
+		logrus.PanicLevel,
+		logrus.FatalLevel,
+		logrus.ErrorLevel,
+		logrus.WarnLevel,
+		logrus.InfoLevel,
+		logrus.DebugLevel,
+	}
+}

+ 26 - 0
libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/papertrail/papertrail_test.go

@@ -0,0 +1,26 @@
+package logrus_papertrail
+
+import (
+	"fmt"
+	"testing"
+
+	"github.com/Sirupsen/logrus"
+	"github.com/stvp/go-udp-testing"
+)
+
+func TestWritingToUDP(t *testing.T) {
+	port := 16661
+	udp.SetAddr(fmt.Sprintf(":%d", port))
+
+	hook, err := NewPapertrailHook("localhost", port, "test")
+	if err != nil {
+		t.Errorf("Unable to connect to local UDP server.")
+	}
+
+	log := logrus.New()
+	log.Hooks.Add(hook)
+
+	udp.ShouldReceive(t, "foo", func() {
+		log.Info("foo")
+	})
+}

+ 61 - 0
libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/sentry/README.md

@@ -0,0 +1,61 @@
+# Sentry Hook for Logrus <img src="http://i.imgur.com/hTeVwmJ.png" width="40" height="40" alt=":walrus:" class="emoji" title=":walrus:" />
+
+[Sentry](https://getsentry.com) provides both self-hosted and hosted
+solutions for exception tracking.
+Both client and server are
+[open source](https://github.com/getsentry/sentry).
+
+## Usage
+
+Every sentry application defined on the server gets a different
+[DSN](https://www.getsentry.com/docs/). In the example below replace
+`YOUR_DSN` with the one created for your application.
+
+```go
+import (
+  "github.com/Sirupsen/logrus"
+  "github.com/Sirupsen/logrus/hooks/sentry"
+)
+
+func main() {
+  log       := logrus.New()
+  hook, err := logrus_sentry.NewSentryHook(YOUR_DSN, []logrus.Level{
+    logrus.PanicLevel,
+    logrus.FatalLevel,
+    logrus.ErrorLevel,
+  })
+
+  if err == nil {
+    log.Hooks.Add(hook)
+  }
+}
+```
+
+## Special fields
+
+Some logrus fields have a special meaning in this hook,
+these are server_name and logger.
+When logs are sent to sentry these fields are treated differently.
+- server_name (also known as hostname) is the name of the server which
+is logging the event (hostname.example.com)
+- logger is the part of the application which is logging the event.
+In go this usually means setting it to the name of the package.
+
+## Timeout
+
+`Timeout` is the time the sentry hook will wait for a response
+from the sentry server.
+
+If this time elapses with no response from
+the server an error will be returned.
+
+If `Timeout` is set to 0 the SentryHook will not wait for a reply
+and will assume a correct delivery.
+
+The SentryHook has a default timeout of `100 milliseconds` when created
+with a call to `NewSentryHook`. This can be changed by assigning a value to the `Timeout` field:
+
+```go
+hook, _ := logrus_sentry.NewSentryHook(...)
+hook.Timeout = 20*time.Seconds
+```

+ 100 - 0
libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/sentry/sentry.go

@@ -0,0 +1,100 @@
+package logrus_sentry
+
+import (
+	"fmt"
+	"time"
+
+	"github.com/Sirupsen/logrus"
+	"github.com/getsentry/raven-go"
+)
+
+var (
+	severityMap = map[logrus.Level]raven.Severity{
+		logrus.DebugLevel: raven.DEBUG,
+		logrus.InfoLevel:  raven.INFO,
+		logrus.WarnLevel:  raven.WARNING,
+		logrus.ErrorLevel: raven.ERROR,
+		logrus.FatalLevel: raven.FATAL,
+		logrus.PanicLevel: raven.FATAL,
+	}
+)
+
+func getAndDel(d logrus.Fields, key string) (string, bool) {
+	var (
+		ok  bool
+		v   interface{}
+		val string
+	)
+	if v, ok = d[key]; !ok {
+		return "", false
+	}
+
+	if val, ok = v.(string); !ok {
+		return "", false
+	}
+	delete(d, key)
+	return val, true
+}
+
+// SentryHook delivers logs to a sentry server.
+type SentryHook struct {
+	// Timeout sets the time to wait for a delivery error from the sentry server.
+	// If this is set to zero the server will not wait for any response and will
+	// consider the message correctly sent
+	Timeout time.Duration
+
+	client *raven.Client
+	levels []logrus.Level
+}
+
+// NewSentryHook creates a hook to be added to an instance of logger
+// and initializes the raven client.
+// This method sets the timeout to 100 milliseconds.
+func NewSentryHook(DSN string, levels []logrus.Level) (*SentryHook, error) {
+	client, err := raven.NewClient(DSN, nil)
+	if err != nil {
+		return nil, err
+	}
+	return &SentryHook{100 * time.Millisecond, client, levels}, nil
+}
+
+// Called when an event should be sent to sentry
+// Special fields that sentry uses to give more information to the server
+// are extracted from entry.Data (if they are found)
+// These fields are: logger and server_name
+func (hook *SentryHook) Fire(entry *logrus.Entry) error {
+	packet := &raven.Packet{
+		Message:   entry.Message,
+		Timestamp: raven.Timestamp(entry.Time),
+		Level:     severityMap[entry.Level],
+		Platform:  "go",
+	}
+
+	d := entry.Data
+
+	if logger, ok := getAndDel(d, "logger"); ok {
+		packet.Logger = logger
+	}
+	if serverName, ok := getAndDel(d, "server_name"); ok {
+		packet.ServerName = serverName
+	}
+	packet.Extra = map[string]interface{}(d)
+
+	_, errCh := hook.client.Capture(packet, nil)
+	timeout := hook.Timeout
+	if timeout != 0 {
+		timeoutCh := time.After(timeout)
+		select {
+		case err := <-errCh:
+			return err
+		case <-timeoutCh:
+			return fmt.Errorf("no response from sentry server in %s", timeout)
+		}
+	}
+	return nil
+}
+
+// Levels returns the available logging levels.
+func (hook *SentryHook) Levels() []logrus.Level {
+	return hook.levels
+}

+ 97 - 0
libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/sentry/sentry_test.go

@@ -0,0 +1,97 @@
+package logrus_sentry
+
+import (
+	"encoding/json"
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"net/http/httptest"
+	"strings"
+	"testing"
+
+	"github.com/Sirupsen/logrus"
+	"github.com/getsentry/raven-go"
+)
+
+const (
+	message     = "error message"
+	server_name = "testserver.internal"
+	logger_name = "test.logger"
+)
+
+func getTestLogger() *logrus.Logger {
+	l := logrus.New()
+	l.Out = ioutil.Discard
+	return l
+}
+
+func WithTestDSN(t *testing.T, tf func(string, <-chan *raven.Packet)) {
+	pch := make(chan *raven.Packet, 1)
+	s := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
+		defer req.Body.Close()
+		d := json.NewDecoder(req.Body)
+		p := &raven.Packet{}
+		err := d.Decode(p)
+		if err != nil {
+			t.Fatal(err.Error())
+		}
+
+		pch <- p
+	}))
+	defer s.Close()
+
+	fragments := strings.SplitN(s.URL, "://", 2)
+	dsn := fmt.Sprintf(
+		"%s://public:secret@%s/sentry/project-id",
+		fragments[0],
+		fragments[1],
+	)
+	tf(dsn, pch)
+}
+
+func TestSpecialFields(t *testing.T) {
+	WithTestDSN(t, func(dsn string, pch <-chan *raven.Packet) {
+		logger := getTestLogger()
+
+		hook, err := NewSentryHook(dsn, []logrus.Level{
+			logrus.ErrorLevel,
+		})
+
+		if err != nil {
+			t.Fatal(err.Error())
+		}
+		logger.Hooks.Add(hook)
+		logger.WithFields(logrus.Fields{
+			"server_name": server_name,
+			"logger":      logger_name,
+		}).Error(message)
+
+		packet := <-pch
+		if packet.Logger != logger_name {
+			t.Errorf("logger should have been %s, was %s", logger_name, packet.Logger)
+		}
+
+		if packet.ServerName != server_name {
+			t.Errorf("server_name should have been %s, was %s", server_name, packet.ServerName)
+		}
+	})
+}
+
+func TestSentryHandler(t *testing.T) {
+	WithTestDSN(t, func(dsn string, pch <-chan *raven.Packet) {
+		logger := getTestLogger()
+		hook, err := NewSentryHook(dsn, []logrus.Level{
+			logrus.ErrorLevel,
+		})
+		if err != nil {
+			t.Fatal(err.Error())
+		}
+		logger.Hooks.Add(hook)
+
+		logger.Error(message)
+		packet := <-pch
+		if packet.Message != message {
+			t.Errorf("message should have been %s, was %s", message, packet.Message)
+		}
+	})
+}

+ 20 - 0
libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/syslog/README.md

@@ -0,0 +1,20 @@
+# Syslog Hooks for Logrus <img src="http://i.imgur.com/hTeVwmJ.png" width="40" height="40" alt=":walrus:" class="emoji" title=":walrus:"/>
+
+## Usage
+
+```go
+import (
+  "log/syslog"
+  "github.com/Sirupsen/logrus"
+  logrus_syslog "github.com/Sirupsen/logrus/hooks/syslog"
+)
+
+func main() {
+  log       := logrus.New()
+  hook, err := logrus_syslog.NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, "")
+
+  if err == nil {
+    log.Hooks.Add(hook)
+  }
+}
+```

+ 59 - 0
libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/syslog/syslog.go

@@ -0,0 +1,59 @@
+package logrus_syslog
+
+import (
+	"fmt"
+	"github.com/Sirupsen/logrus"
+	"log/syslog"
+	"os"
+)
+
+// SyslogHook to send logs via syslog.
+type SyslogHook struct {
+	Writer        *syslog.Writer
+	SyslogNetwork string
+	SyslogRaddr   string
+}
+
+// Creates a hook to be added to an instance of logger. This is called with
+// `hook, err := NewSyslogHook("udp", "localhost:514", syslog.LOG_DEBUG, "")`
+// `if err == nil { log.Hooks.Add(hook) }`
+func NewSyslogHook(network, raddr string, priority syslog.Priority, tag string) (*SyslogHook, error) {
+	w, err := syslog.Dial(network, raddr, priority, tag)
+	return &SyslogHook{w, network, raddr}, err
+}
+
+func (hook *SyslogHook) Fire(entry *logrus.Entry) error {
+	line, err := entry.String()
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "Unable to read entry, %v", err)
+		return err
+	}
+
+	switch entry.Level {
+	case logrus.PanicLevel:
+		return hook.Writer.Crit(line)
+	case logrus.FatalLevel:
+		return hook.Writer.Crit(line)
+	case logrus.ErrorLevel:
+		return hook.Writer.Err(line)
+	case logrus.WarnLevel:
+		return hook.Writer.Warning(line)
+	case logrus.InfoLevel:
+		return hook.Writer.Info(line)
+	case logrus.DebugLevel:
+		return hook.Writer.Debug(line)
+	default:
+		return nil
+	}
+}
+
+func (hook *SyslogHook) Levels() []logrus.Level {
+	return []logrus.Level{
+		logrus.PanicLevel,
+		logrus.FatalLevel,
+		logrus.ErrorLevel,
+		logrus.WarnLevel,
+		logrus.InfoLevel,
+		logrus.DebugLevel,
+	}
+}

+ 26 - 0
libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/hooks/syslog/syslog_test.go

@@ -0,0 +1,26 @@
+package logrus_syslog
+
+import (
+	"github.com/Sirupsen/logrus"
+	"log/syslog"
+	"testing"
+)
+
+func TestLocalhostAddAndPrint(t *testing.T) {
+	log := logrus.New()
+	hook, err := NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, "")
+
+	if err != nil {
+		t.Errorf("Unable to connect to local syslog.")
+	}
+
+	log.Hooks.Add(hook)
+
+	for _, level := range hook.Levels() {
+		if len(log.Hooks[level]) != 1 {
+			t.Errorf("SyslogHook was not added. The length of log.Hooks[%v]: %v", level, len(log.Hooks[level]))
+		}
+	}
+
+	log.Info("Congratulations!")
+}

+ 26 - 0
libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/json_formatter.go

@@ -0,0 +1,26 @@
+package logrus
+
+import (
+	"encoding/json"
+	"fmt"
+	"time"
+)
+
+type JSONFormatter struct{}
+
+func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
+	data := make(Fields, len(entry.Data)+3)
+	for k, v := range entry.Data {
+		data[k] = v
+	}
+	prefixFieldClashes(data)
+	data["time"] = entry.Time.Format(time.RFC3339)
+	data["msg"] = entry.Message
+	data["level"] = entry.Level.String()
+
+	serialized, err := json.Marshal(data)
+	if err != nil {
+		return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err)
+	}
+	return append(serialized, '\n'), nil
+}

+ 161 - 0
libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/logger.go

@@ -0,0 +1,161 @@
+package logrus
+
+import (
+	"io"
+	"os"
+	"sync"
+)
+
+type Logger struct {
+	// The logs are `io.Copy`'d to this in a mutex. It's common to set this to a
+	// file, or leave it default which is `os.Stdout`. You can also set this to
+	// something more adventorous, such as logging to Kafka.
+	Out io.Writer
+	// Hooks for the logger instance. These allow firing events based on logging
+	// levels and log entries. For example, to send errors to an error tracking
+	// service, log to StatsD or dump the core on fatal errors.
+	Hooks levelHooks
+	// All log entries pass through the formatter before logged to Out. The
+	// included formatters are `TextFormatter` and `JSONFormatter` for which
+	// TextFormatter is the default. In development (when a TTY is attached) it
+	// logs with colors, but to a file it wouldn't. You can easily implement your
+	// own that implements the `Formatter` interface, see the `README` or included
+	// formatters for examples.
+	Formatter Formatter
+	// The logging level the logger should log at. This is typically (and defaults
+	// to) `logrus.Info`, which allows Info(), Warn(), Error() and Fatal() to be
+	// logged. `logrus.Debug` is useful in
+	Level Level
+	// Used to sync writing to the log.
+	mu sync.Mutex
+}
+
+// Creates a new logger. Configuration should be set by changing `Formatter`,
+// `Out` and `Hooks` directly on the default logger instance. You can also just
+// instantiate your own:
+//
+//    var log = &Logger{
+//      Out: os.Stderr,
+//      Formatter: new(JSONFormatter),
+//      Hooks: make(levelHooks),
+//      Level: logrus.DebugLevel,
+//    }
+//
+// It's recommended to make this a global instance called `log`.
+func New() *Logger {
+	return &Logger{
+		Out:       os.Stdout,
+		Formatter: new(TextFormatter),
+		Hooks:     make(levelHooks),
+		Level:     InfoLevel,
+	}
+}
+
+// Adds a field to the log entry, note that you it doesn't log until you call
+// Debug, Print, Info, Warn, Fatal or Panic. It only creates a log entry.
+// Ff you want multiple fields, use `WithFields`.
+func (logger *Logger) WithField(key string, value interface{}) *Entry {
+	return NewEntry(logger).WithField(key, value)
+}
+
+// Adds a struct of fields to the log entry. All it does is call `WithField` for
+// each `Field`.
+func (logger *Logger) WithFields(fields Fields) *Entry {
+	return NewEntry(logger).WithFields(fields)
+}
+
+func (logger *Logger) Debugf(format string, args ...interface{}) {
+	NewEntry(logger).Debugf(format, args...)
+}
+
+func (logger *Logger) Infof(format string, args ...interface{}) {
+	NewEntry(logger).Infof(format, args...)
+}
+
+func (logger *Logger) Printf(format string, args ...interface{}) {
+	NewEntry(logger).Printf(format, args...)
+}
+
+func (logger *Logger) Warnf(format string, args ...interface{}) {
+	NewEntry(logger).Warnf(format, args...)
+}
+
+func (logger *Logger) Warningf(format string, args ...interface{}) {
+	NewEntry(logger).Warnf(format, args...)
+}
+
+func (logger *Logger) Errorf(format string, args ...interface{}) {
+	NewEntry(logger).Errorf(format, args...)
+}
+
+func (logger *Logger) Fatalf(format string, args ...interface{}) {
+	NewEntry(logger).Fatalf(format, args...)
+}
+
+func (logger *Logger) Panicf(format string, args ...interface{}) {
+	NewEntry(logger).Panicf(format, args...)
+}
+
+func (logger *Logger) Debug(args ...interface{}) {
+	NewEntry(logger).Debug(args...)
+}
+
+func (logger *Logger) Info(args ...interface{}) {
+	NewEntry(logger).Info(args...)
+}
+
+func (logger *Logger) Print(args ...interface{}) {
+	NewEntry(logger).Info(args...)
+}
+
+func (logger *Logger) Warn(args ...interface{}) {
+	NewEntry(logger).Warn(args...)
+}
+
+func (logger *Logger) Warning(args ...interface{}) {
+	NewEntry(logger).Warn(args...)
+}
+
+func (logger *Logger) Error(args ...interface{}) {
+	NewEntry(logger).Error(args...)
+}
+
+func (logger *Logger) Fatal(args ...interface{}) {
+	NewEntry(logger).Fatal(args...)
+}
+
+func (logger *Logger) Panic(args ...interface{}) {
+	NewEntry(logger).Panic(args...)
+}
+
+func (logger *Logger) Debugln(args ...interface{}) {
+	NewEntry(logger).Debugln(args...)
+}
+
+func (logger *Logger) Infoln(args ...interface{}) {
+	NewEntry(logger).Infoln(args...)
+}
+
+func (logger *Logger) Println(args ...interface{}) {
+	NewEntry(logger).Println(args...)
+}
+
+func (logger *Logger) Warnln(args ...interface{}) {
+	NewEntry(logger).Warnln(args...)
+}
+
+func (logger *Logger) Warningln(args ...interface{}) {
+	NewEntry(logger).Warnln(args...)
+}
+
+func (logger *Logger) Errorln(args ...interface{}) {
+	NewEntry(logger).Errorln(args...)
+}
+
+func (logger *Logger) Fatalln(args ...interface{}) {
+	NewEntry(logger).Fatalln(args...)
+}
+
+func (logger *Logger) Panicln(args ...interface{}) {
+	NewEntry(logger).Panicln(args...)
+}

+ 94 - 0
libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/logrus.go

@@ -0,0 +1,94 @@
+package logrus
+
+import (
+	"fmt"
+	"log"
+)
+
+// Fields type, used to pass to `WithFields`.
+type Fields map[string]interface{}
+
+// Level type
+type Level uint8
+
+// Convert the Level to a string. E.g. PanicLevel becomes "panic".
+func (level Level) String() string {
+	switch level {
+	case DebugLevel:
+		return "debug"
+	case InfoLevel:
+		return "info"
+	case WarnLevel:
+		return "warning"
+	case ErrorLevel:
+		return "error"
+	case FatalLevel:
+		return "fatal"
+	case PanicLevel:
+		return "panic"
+	}
+
+	return "unknown"
+}
+
+// ParseLevel takes a string level and returns the Logrus log level constant.
+func ParseLevel(lvl string) (Level, error) {
+	switch lvl {
+	case "panic":
+		return PanicLevel, nil
+	case "fatal":
+		return FatalLevel, nil
+	case "error":
+		return ErrorLevel, nil
+	case "warn", "warning":
+		return WarnLevel, nil
+	case "info":
+		return InfoLevel, nil
+	case "debug":
+		return DebugLevel, nil
+	}
+
+	var l Level
+	return l, fmt.Errorf("not a valid logrus Level: %q", lvl)
+}
+
+// These are the different logging levels. You can set the logging level to log
+// on your instance of logger, obtained with `logrus.New()`.
+const (
+	// PanicLevel level, highest level of severity. Logs and then calls panic with the
+	// message passed to Debug, Info, ...
+	PanicLevel Level = iota
+	// FatalLevel level. Logs and then calls `os.Exit(1)`. It will exit even if the
+	// logging level is set to Panic.
+	FatalLevel
+	// ErrorLevel level. Logs. Used for errors that should definitely be noted.
+	// Commonly used for hooks to send errors to an error tracking service.
+	ErrorLevel
+	// WarnLevel level. Non-critical entries that deserve eyes.
+	WarnLevel
+	// InfoLevel level. General operational entries about what's going on inside the
+	// application.
+	InfoLevel
+	// DebugLevel level. Usually only enabled when debugging. Very verbose logging.
+	DebugLevel
+)
+
+// Won't compile if StdLogger can't be realized by a log.Logger
+var _ StdLogger = &log.Logger{}
+
+// StdLogger is what your logrus-enabled library should take, that way
+// it'll accept a stdlib logger and a logrus logger. There's no standard
+// interface, this is the closest we get, unfortunately.
+type StdLogger interface {
+	Print(...interface{})
+	Printf(string, ...interface{})
+	Println(...interface{})
+
+	Fatal(...interface{})
+	Fatalf(string, ...interface{})
+	Fatalln(...interface{})
+
+	Panic(...interface{})
+	Panicf(string, ...interface{})
+	Panicln(...interface{})
+}

+ 283 - 0
libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/logrus_test.go

@@ -0,0 +1,283 @@
+package logrus
+
+import (
+	"bytes"
+	"encoding/json"
+	"strconv"
+	"strings"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func LogAndAssertJSON(t *testing.T, log func(*Logger), assertions func(fields Fields)) {
+	var buffer bytes.Buffer
+	var fields Fields
+
+	logger := New()
+	logger.Out = &buffer
+	logger.Formatter = new(JSONFormatter)
+
+	log(logger)
+
+	err := json.Unmarshal(buffer.Bytes(), &fields)
+	assert.Nil(t, err)
+
+	assertions(fields)
+}
+
+func LogAndAssertText(t *testing.T, log func(*Logger), assertions func(fields map[string]string)) {
+	var buffer bytes.Buffer
+
+	logger := New()
+	logger.Out = &buffer
+	logger.Formatter = &TextFormatter{
+		DisableColors: true,
+	}
+
+	log(logger)
+
+	fields := make(map[string]string)
+	for _, kv := range strings.Split(buffer.String(), " ") {
+		if !strings.Contains(kv, "=") {
+			continue
+		}
+		kvArr := strings.Split(kv, "=")
+		key := strings.TrimSpace(kvArr[0])
+		val := kvArr[1]
+		if kvArr[1][0] == '"' {
+			var err error
+			val, err = strconv.Unquote(val)
+			assert.NoError(t, err)
+		}
+		fields[key] = val
+	}
+	assertions(fields)
+}
+
+func TestPrint(t *testing.T) {
+	LogAndAssertJSON(t, func(log *Logger) {
+		log.Print("test")
+	}, func(fields Fields) {
+		assert.Equal(t, fields["msg"], "test")
+		assert.Equal(t, fields["level"], "info")
+	})
+}
+
+func TestInfo(t *testing.T) {
+	LogAndAssertJSON(t, func(log *Logger) {
+		log.Info("test")
+	}, func(fields Fields) {
+		assert.Equal(t, fields["msg"], "test")
+		assert.Equal(t, fields["level"], "info")
+	})
+}
+
+func TestWarn(t *testing.T) {
+	LogAndAssertJSON(t, func(log *Logger) {
+		log.Warn("test")
+	}, func(fields Fields) {
+		assert.Equal(t, fields["msg"], "test")
+		assert.Equal(t, fields["level"], "warning")
+	})
+}
+
+func TestInfolnShouldAddSpacesBetweenStrings(t *testing.T) {
+	LogAndAssertJSON(t, func(log *Logger) {
+		log.Infoln("test", "test")
+	}, func(fields Fields) {
+		assert.Equal(t, fields["msg"], "test test")
+	})
+}
+
+func TestInfolnShouldAddSpacesBetweenStringAndNonstring(t *testing.T) {
+	LogAndAssertJSON(t, func(log *Logger) {
+		log.Infoln("test", 10)
+	}, func(fields Fields) {
+		assert.Equal(t, fields["msg"], "test 10")
+	})
+}
+
+func TestInfolnShouldAddSpacesBetweenTwoNonStrings(t *testing.T) {
+	LogAndAssertJSON(t, func(log *Logger) {
+		log.Infoln(10, 10)
+	}, func(fields Fields) {
+		assert.Equal(t, fields["msg"], "10 10")
+	})
+}
+
+func TestInfoShouldAddSpacesBetweenTwoNonStrings(t *testing.T) {
+	LogAndAssertJSON(t, func(log *Logger) {
+		log.Infoln(10, 10)
+	}, func(fields Fields) {
+		assert.Equal(t, fields["msg"], "10 10")
+	})
+}
+
+func TestInfoShouldNotAddSpacesBetweenStringAndNonstring(t *testing.T) {
+	LogAndAssertJSON(t, func(log *Logger) {
+		log.Info("test", 10)
+	}, func(fields Fields) {
+		assert.Equal(t, fields["msg"], "test10")
+	})
+}
+
+func TestInfoShouldNotAddSpacesBetweenStrings(t *testing.T) {
+	LogAndAssertJSON(t, func(log *Logger) {
+		log.Info("test", "test")
+	}, func(fields Fields) {
+		assert.Equal(t, fields["msg"], "testtest")
+	})
+}
+
+func TestWithFieldsShouldAllowAssignments(t *testing.T) {
+	var buffer bytes.Buffer
+	var fields Fields
+
+	logger := New()
+	logger.Out = &buffer
+	logger.Formatter = new(JSONFormatter)
+
+	localLog := logger.WithFields(Fields{
+		"key1": "value1",
+	})
+
+	localLog.WithField("key2", "value2").Info("test")
+	err := json.Unmarshal(buffer.Bytes(), &fields)
+	assert.Nil(t, err)
+
+	assert.Equal(t, "value2", fields["key2"])
+	assert.Equal(t, "value1", fields["key1"])
+
+	buffer = bytes.Buffer{}
+	fields = Fields{}
+	localLog.Info("test")
+	err = json.Unmarshal(buffer.Bytes(), &fields)
+	assert.Nil(t, err)
+
+	_, ok := fields["key2"]
+	assert.Equal(t, false, ok)
+	assert.Equal(t, "value1", fields["key1"])
+}
+
+func TestUserSuppliedFieldDoesNotOverwriteDefaults(t *testing.T) {
+	LogAndAssertJSON(t, func(log *Logger) {
+		log.WithField("msg", "hello").Info("test")
+	}, func(fields Fields) {
+		assert.Equal(t, fields["msg"], "test")
+	})
+}
+
+func TestUserSuppliedMsgFieldHasPrefix(t *testing.T) {
+	LogAndAssertJSON(t, func(log *Logger) {
+		log.WithField("msg", "hello").Info("test")
+	}, func(fields Fields) {
+		assert.Equal(t, fields["msg"], "test")
+		assert.Equal(t, fields["fields.msg"], "hello")
+	})
+}
+
+func TestUserSuppliedTimeFieldHasPrefix(t *testing.T) {
+	LogAndAssertJSON(t, func(log *Logger) {
+		log.WithField("time", "hello").Info("test")
+	}, func(fields Fields) {
+		assert.Equal(t, fields["fields.time"], "hello")
+	})
+}
+
+func TestUserSuppliedLevelFieldHasPrefix(t *testing.T) {
+	LogAndAssertJSON(t, func(log *Logger) {
+		log.WithField("level", 1).Info("test")
+	}, func(fields Fields) {
+		assert.Equal(t, fields["level"], "info")
+		assert.Equal(t, fields["fields.level"], 1)
+	})
+}
+
+func TestDefaultFieldsAreNotPrefixed(t *testing.T) {
+	LogAndAssertText(t, func(log *Logger) {
+		ll := log.WithField("herp", "derp")
+		ll.Info("hello")
+		ll.Info("bye")
+	}, func(fields map[string]string) {
+		for _, fieldName := range []string{"fields.level", "fields.time", "fields.msg"} {
+			if _, ok := fields[fieldName]; ok {
+				t.Fatalf("should not have prefixed %q: %v", fieldName, fields)
+			}
+		}
+	})
+}
+
+func TestDoubleLoggingDoesntPrefixPreviousFields(t *testing.T) {
+
+	var buffer bytes.Buffer
+	var fields Fields
+
+	logger := New()
+	logger.Out = &buffer
+	logger.Formatter = new(JSONFormatter)
+
+	llog := logger.WithField("context", "eating raw fish")
+
+	llog.Info("looks delicious")
+
+	err := json.Unmarshal(buffer.Bytes(), &fields)
+	assert.NoError(t, err, "should have decoded first message")
+	assert.Equal(t, len(fields), 4, "should only have msg/time/level/context fields")
+	assert.Equal(t, fields["msg"], "looks delicious")
+	assert.Equal(t, fields["context"], "eating raw fish")
+
+	buffer.Reset()
+
+	llog.Warn("omg it is!")
+
+	err = json.Unmarshal(buffer.Bytes(), &fields)
+	assert.NoError(t, err, "should have decoded second message")
+	assert.Equal(t, len(fields), 4, "should only have msg/time/level/context fields")
+	assert.Equal(t, fields["msg"], "omg it is!")
+	assert.Equal(t, fields["context"], "eating raw fish")
+	assert.Nil(t, fields["fields.msg"], "should not have prefixed previous `msg` entry")
+
+}
+
+func TestConvertLevelToString(t *testing.T) {
+	assert.Equal(t, "debug", DebugLevel.String())
+	assert.Equal(t, "info", InfoLevel.String())
+	assert.Equal(t, "warning", WarnLevel.String())
+	assert.Equal(t, "error", ErrorLevel.String())
+	assert.Equal(t, "fatal", FatalLevel.String())
+	assert.Equal(t, "panic", PanicLevel.String())
+}
+
+func TestParseLevel(t *testing.T) {
+	l, err := ParseLevel("panic")
+	assert.Nil(t, err)
+	assert.Equal(t, PanicLevel, l)
+
+	l, err = ParseLevel("fatal")
+	assert.Nil(t, err)
+	assert.Equal(t, FatalLevel, l)
+
+	l, err = ParseLevel("error")
+	assert.Nil(t, err)
+	assert.Equal(t, ErrorLevel, l)
+
+	l, err = ParseLevel("warn")
+	assert.Nil(t, err)
+	assert.Equal(t, WarnLevel, l)
+
+	l, err = ParseLevel("warning")
+	assert.Nil(t, err)
+	assert.Equal(t, WarnLevel, l)
+
+	l, err = ParseLevel("info")
+	assert.Nil(t, err)
+	assert.Equal(t, InfoLevel, l)
+
+	l, err = ParseLevel("debug")
+	assert.Nil(t, err)
+	assert.Equal(t, DebugLevel, l)
+
+	l, err = ParseLevel("invalid")
+	assert.Equal(t, "not a valid logrus Level: \"invalid\"", err.Error())
+}

+ 12 - 0
libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/terminal_darwin.go

@@ -0,0 +1,12 @@
+// Based on ssh/terminal:
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package logrus
+
+import "syscall"
+
+const ioctlReadTermios = syscall.TIOCGETA
+
+type Termios syscall.Termios

+ 20 - 0
libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/terminal_freebsd.go

@@ -0,0 +1,20 @@
+/*
+  Go 1.2 doesn't include Termios for FreeBSD. This should be added in 1.3 and this could be merged with terminal_darwin.
+*/
+package logrus
+
+import (
+	"syscall"
+)
+
+const ioctlReadTermios = syscall.TIOCGETA
+
+type Termios struct {
+	Iflag  uint32
+	Oflag  uint32
+	Cflag  uint32
+	Lflag  uint32
+	Cc     [20]uint8
+	Ispeed uint32
+	Ospeed uint32
+}

+ 12 - 0
libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/terminal_linux.go

@@ -0,0 +1,12 @@
+// Based on ssh/terminal:
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package logrus
+
+import "syscall"
+
+const ioctlReadTermios = syscall.TCGETS
+
+type Termios syscall.Termios

+ 21 - 0
libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/terminal_notwindows.go

@@ -0,0 +1,21 @@
+// Based on ssh/terminal:
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux,!appengine darwin freebsd openbsd
+
+package logrus
+
+import (
+	"syscall"
+	"unsafe"
+)
+
+// IsTerminal returns true if the given file descriptor is a terminal.
+func IsTerminal() bool {
+	fd := syscall.Stdout
+	var termios Termios
+	_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
+	return err == 0
+}

+ 8 - 0
libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/terminal_openbsd.go

@@ -0,0 +1,8 @@
+
+package logrus
+
+import "syscall"
+
+const ioctlReadTermios = syscall.TIOCGETA
+
+type Termios syscall.Termios

+ 27 - 0
libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/terminal_windows.go

@@ -0,0 +1,27 @@
+// Based on ssh/terminal:
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build windows
+
+package logrus
+
+import (
+	"syscall"
+	"unsafe"
+)
+
+var kernel32 = syscall.NewLazyDLL("kernel32.dll")
+
+var (
+	procGetConsoleMode = kernel32.NewProc("GetConsoleMode")
+)
+
+// IsTerminal returns true if the given file descriptor is a terminal.
+func IsTerminal() bool {
+	fd := syscall.Stdout
+	var st uint32
+	r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0)
+	return r != 0 && e == 0
+}

+ 124 - 0
libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/text_formatter.go

@@ -0,0 +1,124 @@
+package logrus
+
+import (
+	"bytes"
+	"fmt"
+	"regexp"
+	"sort"
+	"strings"
+	"time"
+)
+
+const (
+	nocolor = 0
+	red     = 31
+	green   = 32
+	yellow  = 33
+	blue    = 34
+)
+
+var (
+	baseTimestamp time.Time
+	isTerminal    bool
+	noQuoteNeeded *regexp.Regexp
+)
+
+func init() {
+	baseTimestamp = time.Now()
+	isTerminal = IsTerminal()
+}
+
+func miniTS() int {
+	return int(time.Since(baseTimestamp) / time.Second)
+}
+
+type TextFormatter struct {
+	// Set to true to bypass checking for a TTY before outputting colors.
+	ForceColors   bool
+	DisableColors bool
+	// Set to true to disable timestamp logging (useful when the output
+	// is redirected to a logging system already adding a timestamp)
+	DisableTimestamp bool
+}
+
+func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
+
+	var keys []string
+	for k := range entry.Data {
+		keys = append(keys, k)
+	}
+	sort.Strings(keys)
+
+	b := &bytes.Buffer{}
+
+	prefixFieldClashes(entry.Data)
+
+	isColored := (f.ForceColors || isTerminal) && !f.DisableColors
+
+	if isColored {
+		printColored(b, entry, keys)
+	} else {
+		if !f.DisableTimestamp {
+			f.appendKeyValue(b, "time", entry.Time.Format(time.RFC3339))
+		}
+		f.appendKeyValue(b, "level", entry.Level.String())
+		f.appendKeyValue(b, "msg", entry.Message)
+		for _, key := range keys {
+			f.appendKeyValue(b, key, entry.Data[key])
+		}
+	}
+
+	b.WriteByte('\n')
+	return b.Bytes(), nil
+}
+
+func printColored(b *bytes.Buffer, entry *Entry, keys []string) {
+	var levelColor int
+	switch entry.Level {
+	case WarnLevel:
+		levelColor = yellow
+	case ErrorLevel, FatalLevel, PanicLevel:
+		levelColor = red
+	default:
+		levelColor = blue
+	}
+
+	levelText := strings.ToUpper(entry.Level.String())[0:4]
+
+	fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%04d] %-44s ", levelColor, levelText, miniTS(), entry.Message)
+	for _, k := range keys {
+		v := entry.Data[k]
+		fmt.Fprintf(b, " \x1b[%dm%s\x1b[0m=%v", levelColor, k, v)
+	}
+}
+
+func needsQuoting(text string) bool {
+	for _, ch := range text {
+		if !((ch >= 'a' && ch <= 'z') ||
+			(ch >= 'A' && ch <= 'Z') ||
+			(ch >= '0' && ch < '9') ||
+			ch == '-' || ch == '.') {
+			return false
+		}
+	}
+	return true
+}
+
+func (f *TextFormatter) appendKeyValue(b *bytes.Buffer, key, value interface{}) {
+	switch value.(type) {
+	case string:
+		if needsQuoting(value.(string)) {
+			fmt.Fprintf(b, "%v=%s ", key, value)
+		} else {
+			fmt.Fprintf(b, "%v=%q ", key, value)
+		}
+	case error:
+		if needsQuoting(value.(error).Error()) {
+			fmt.Fprintf(b, "%v=%s ", key, value)
+		} else {
+			fmt.Fprintf(b, "%v=%q ", key, value)
+		}
+	default:
+		fmt.Fprintf(b, "%v=%v ", key, value)
+	}
+}

+ 33 - 0
libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/text_formatter_test.go

@@ -0,0 +1,33 @@
+package logrus
+
+import (
+	"bytes"
+	"errors"
+
+	"testing"
+)
+
+func TestQuoting(t *testing.T) {
+	tf := &TextFormatter{DisableColors: true}
+
+	checkQuoting := func(q bool, value interface{}) {
+		b, _ := tf.Format(WithField("test", value))
+		idx := bytes.Index(b, ([]byte)("test="))
+		cont := bytes.Contains(b[idx+5:], []byte{'"'})
+		if cont != q {
+			if q {
+				t.Errorf("quoting expected for: %#v", value)
+			} else {
+				t.Errorf("quoting not expected for: %#v", value)
+			}
+		}
+	}
+
+	checkQuoting(false, "abcd")
+	checkQuoting(false, "v1.0")
+	checkQuoting(true, "/foobar")
+	checkQuoting(true, "x y")
+	checkQuoting(true, "x,y")
+	checkQuoting(false, errors.New("invalid"))
+	checkQuoting(true, errors.New("invalid argument"))
+}

+ 31 - 0
libnetwork/Godeps/_workspace/src/github.com/Sirupsen/logrus/writer.go

@@ -0,0 +1,31 @@
+package logrus
+
+import (
+	"bufio"
+	"io"
+	"runtime"
+)
+
+func (logger *Logger) Writer() (*io.PipeWriter) {
+	reader, writer := io.Pipe()
+
+	go logger.writerScanner(reader)
+	runtime.SetFinalizer(writer, writerFinalizer)
+
+	return writer
+}
+
+func (logger *Logger) writerScanner(reader *io.PipeReader) {
+	scanner := bufio.NewScanner(reader)
+	for scanner.Scan() {
+		logger.Print(scanner.Text())
+	}
+	if err := scanner.Err(); err != nil {
+		logger.Errorf("Error while reading from Writer: %s", err)
+	}
+	reader.Close()
+}
+
+func writerFinalizer(writer *io.PipeWriter) {
+	writer.Close()
+}

+ 720 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/bridge/driver.go

@@ -0,0 +1,720 @@
+package bridge
+
+import (
+	"encoding/hex"
+	"errors"
+	"fmt"
+	"io/ioutil"
+	"net"
+	"os"
+	"strings"
+	"sync"
+
+	log "github.com/Sirupsen/logrus"
+	"github.com/docker/docker/daemon/networkdriver"
+	"github.com/docker/docker/daemon/networkdriver/ipallocator"
+	"github.com/docker/docker/daemon/networkdriver/portmapper"
+	"github.com/docker/docker/engine"
+	"github.com/docker/docker/nat"
+	"github.com/docker/docker/pkg/iptables"
+	"github.com/docker/docker/pkg/networkfs/resolvconf"
+	"github.com/docker/docker/pkg/parsers/kernel"
+	"github.com/docker/libcontainer/netlink"
+)
+
+const (
+	DefaultNetworkBridge     = "docker0"
+	MaxAllocatedPortAttempts = 10
+)
+
+// Network interface represents the networking stack of a container
+type networkInterface struct {
+	IP           net.IP
+	IPv6         net.IP
+	PortMappings []net.Addr // there are mappings to the host interfaces
+}
+
+type ifaces struct {
+	c map[string]*networkInterface
+	sync.Mutex
+}
+
+func (i *ifaces) Set(key string, n *networkInterface) {
+	i.Lock()
+	i.c[key] = n
+	i.Unlock()
+}
+
+func (i *ifaces) Get(key string) *networkInterface {
+	i.Lock()
+	res := i.c[key]
+	i.Unlock()
+	return res
+}
+
+var (
+	addrs = []string{
+		// Here we don't follow the convention of using the 1st IP of the range for the gateway.
+		// This is to use the same gateway IPs as the /24 ranges, which predate the /16 ranges.
+		// In theory this shouldn't matter - in practice there's bound to be a few scripts relying
+		// on the internal addressing or other stupid things like that.
+		// They shouldn't, but hey, let's not break them unless we really have to.
+		"172.17.42.1/16", // Don't use 172.16.0.0/16, it conflicts with EC2 DNS 172.16.0.23
+		"10.0.42.1/16",   // Don't even try using the entire /8, that's too intrusive
+		"10.1.42.1/16",
+		"10.42.42.1/16",
+		"172.16.42.1/24",
+		"172.16.43.1/24",
+		"172.16.44.1/24",
+		"10.0.42.1/24",
+		"10.0.43.1/24",
+		"192.168.42.1/24",
+		"192.168.43.1/24",
+		"192.168.44.1/24",
+	}
+
+	bridgeIface       string
+	bridgeIPv4Network *net.IPNet
+	bridgeIPv6Addr    net.IP
+	globalIPv6Network *net.IPNet
+
+	defaultBindingIP  = net.ParseIP("0.0.0.0")
+	currentInterfaces = ifaces{c: make(map[string]*networkInterface)}
+)
+
+func InitDriver(job *engine.Job) engine.Status {
+	var (
+		networkv4      *net.IPNet
+		networkv6      *net.IPNet
+		addrv4         net.Addr
+		addrsv6        []net.Addr
+		enableIPTables = job.GetenvBool("EnableIptables")
+		enableIPv6     = job.GetenvBool("EnableIPv6")
+		icc            = job.GetenvBool("InterContainerCommunication")
+		ipMasq         = job.GetenvBool("EnableIpMasq")
+		ipForward      = job.GetenvBool("EnableIpForward")
+		bridgeIP       = job.Getenv("BridgeIP")
+		bridgeIPv6     = "fe80::1/64"
+		fixedCIDR      = job.Getenv("FixedCIDR")
+		fixedCIDRv6    = job.Getenv("FixedCIDRv6")
+	)
+
+	if defaultIP := job.Getenv("DefaultBindingIP"); defaultIP != "" {
+		defaultBindingIP = net.ParseIP(defaultIP)
+	}
+
+	bridgeIface = job.Getenv("BridgeIface")
+	usingDefaultBridge := false
+	if bridgeIface == "" {
+		usingDefaultBridge = true
+		bridgeIface = DefaultNetworkBridge
+	}
+
+	addrv4, addrsv6, err := networkdriver.GetIfaceAddr(bridgeIface)
+
+	if err != nil {
+		// No Bridge existent, create one
+		// If we're not using the default bridge, fail without trying to create it
+		if !usingDefaultBridge {
+			return job.Error(err)
+		}
+
+		// If the iface is not found, try to create it
+		if err := configureBridge(bridgeIP, bridgeIPv6, enableIPv6); err != nil {
+			return job.Error(err)
+		}
+
+		addrv4, addrsv6, err = networkdriver.GetIfaceAddr(bridgeIface)
+		if err != nil {
+			return job.Error(err)
+		}
+
+		if fixedCIDRv6 != "" {
+			// Setting route to global IPv6 subnet
+			log.Infof("Adding route to IPv6 network %q via device %q", fixedCIDRv6, bridgeIface)
+			if err := netlink.AddRoute(fixedCIDRv6, "", "", bridgeIface); err != nil {
+				log.Fatalf("Could not add route to IPv6 network %q via device %q", fixedCIDRv6, bridgeIface)
+			}
+		}
+	} else {
+		// Bridge exists already, getting info...
+		// validate that the bridge ip matches the ip specified by BridgeIP
+		if bridgeIP != "" {
+			networkv4 = addrv4.(*net.IPNet)
+			bip, _, err := net.ParseCIDR(bridgeIP)
+			if err != nil {
+				return job.Error(err)
+			}
+			if !networkv4.IP.Equal(bip) {
+				return job.Errorf("bridge ip (%s) does not match existing bridge configuration %s", networkv4.IP, bip)
+			}
+		}
+
+		// a bridge might exist but not have any IPv6 addr associated with it yet
+		// (for example, an existing Docker installation that has only been used
+		// with IPv4 and docker0 already is set up) In that case, we can perform
+		// the bridge init for IPv6 here, else we will error out below if --ipv6=true
+		if len(addrsv6) == 0 && enableIPv6 {
+			if err := setupIPv6Bridge(bridgeIPv6); err != nil {
+				return job.Error(err)
+			}
+			// recheck addresses now that IPv6 is setup on the bridge
+			addrv4, addrsv6, err = networkdriver.GetIfaceAddr(bridgeIface)
+			if err != nil {
+				return job.Error(err)
+			}
+		}
+
+		// TODO: Check if route to fixedCIDRv6 is set
+	}
+
+	if enableIPv6 {
+		bip6, _, err := net.ParseCIDR(bridgeIPv6)
+		if err != nil {
+			return job.Error(err)
+		}
+		found := false
+		for _, addrv6 := range addrsv6 {
+			networkv6 = addrv6.(*net.IPNet)
+			if networkv6.IP.Equal(bip6) {
+				found = true
+				break
+			}
+		}
+		if !found {
+			return job.Errorf("bridge IPv6 does not match existing bridge configuration %s", bip6)
+		}
+	}
+
+	networkv4 = addrv4.(*net.IPNet)
+
+	if enableIPv6 {
+		if len(addrsv6) == 0 {
+			return job.Error(errors.New("IPv6 enabled but no IPv6 detected"))
+		}
+		bridgeIPv6Addr = networkv6.IP
+	}
+
+	// Configure iptables for link support
+	if enableIPTables {
+		if err := setupIPTables(addrv4, icc, ipMasq); err != nil {
+			return job.Error(err)
+		}
+
+	}
+
+	if ipForward {
+		// Enable IPv4 forwarding
+		if err := ioutil.WriteFile("/proc/sys/net/ipv4/ip_forward", []byte{'1', '\n'}, 0644); err != nil {
+			job.Logf("WARNING: unable to enable IPv4 forwarding: %s\n", err)
+		}
+
+		if fixedCIDRv6 != "" {
+			// Enable IPv6 forwarding
+			if err := ioutil.WriteFile("/proc/sys/net/ipv6/conf/default/forwarding", []byte{'1', '\n'}, 0644); err != nil {
+				job.Logf("WARNING: unable to enable IPv6 default forwarding: %s\n", err)
+			}
+			if err := ioutil.WriteFile("/proc/sys/net/ipv6/conf/all/forwarding", []byte{'1', '\n'}, 0644); err != nil {
+				job.Logf("WARNING: unable to enable IPv6 all forwarding: %s\n", err)
+			}
+		}
+	}
+
+	// We can always try removing the iptables
+	if err := iptables.RemoveExistingChain("DOCKER", iptables.Nat); err != nil {
+		return job.Error(err)
+	}
+
+	if enableIPTables {
+		_, err := iptables.NewChain("DOCKER", bridgeIface, iptables.Nat)
+		if err != nil {
+			return job.Error(err)
+		}
+		chain, err := iptables.NewChain("DOCKER", bridgeIface, iptables.Filter)
+		if err != nil {
+			return job.Error(err)
+		}
+		portmapper.SetIptablesChain(chain)
+	}
+
+	bridgeIPv4Network = networkv4
+	if fixedCIDR != "" {
+		_, subnet, err := net.ParseCIDR(fixedCIDR)
+		if err != nil {
+			return job.Error(err)
+		}
+		log.Debugf("Subnet: %v", subnet)
+		if err := ipallocator.RegisterSubnet(bridgeIPv4Network, subnet); err != nil {
+			return job.Error(err)
+		}
+	}
+
+	if fixedCIDRv6 != "" {
+		_, subnet, err := net.ParseCIDR(fixedCIDRv6)
+		if err != nil {
+			return job.Error(err)
+		}
+		log.Debugf("Subnet: %v", subnet)
+		if err := ipallocator.RegisterSubnet(subnet, subnet); err != nil {
+			return job.Error(err)
+		}
+		globalIPv6Network = subnet
+	}
+
+	// Block BridgeIP in IP allocator
+	ipallocator.RequestIP(bridgeIPv4Network, bridgeIPv4Network.IP)
+
+	// https://github.com/docker/docker/issues/2768
+	job.Eng.Hack_SetGlobalVar("httpapi.bridgeIP", bridgeIPv4Network.IP)
+
+	for name, f := range map[string]engine.Handler{
+		"allocate_interface": Allocate,
+		"release_interface":  Release,
+		"allocate_port":      AllocatePort,
+		"link":               LinkContainers,
+	} {
+		if err := job.Eng.Register(name, f); err != nil {
+			return job.Error(err)
+		}
+	}
+	return engine.StatusOK
+}
+
+func setupIPTables(addr net.Addr, icc, ipmasq bool) error {
+	// Enable NAT
+
+	if ipmasq {
+		natArgs := []string{"POSTROUTING", "-t", "nat", "-s", addr.String(), "!", "-o", bridgeIface, "-j", "MASQUERADE"}
+
+		if !iptables.Exists(natArgs...) {
+			if output, err := iptables.Raw(append([]string{"-I"}, natArgs...)...); err != nil {
+				return fmt.Errorf("Unable to enable network bridge NAT: %s", err)
+			} else if len(output) != 0 {
+				return &iptables.ChainError{Chain: "POSTROUTING", Output: output}
+			}
+		}
+	}
+
+	var (
+		args       = []string{"FORWARD", "-i", bridgeIface, "-o", bridgeIface, "-j"}
+		acceptArgs = append(args, "ACCEPT")
+		dropArgs   = append(args, "DROP")
+	)
+
+	if !icc {
+		iptables.Raw(append([]string{"-D"}, acceptArgs...)...)
+
+		if !iptables.Exists(dropArgs...) {
+			log.Debugf("Disable inter-container communication")
+			if output, err := iptables.Raw(append([]string{"-I"}, dropArgs...)...); err != nil {
+				return fmt.Errorf("Unable to prevent intercontainer communication: %s", err)
+			} else if len(output) != 0 {
+				return fmt.Errorf("Error disabling intercontainer communication: %s", output)
+			}
+		}
+	} else {
+		iptables.Raw(append([]string{"-D"}, dropArgs...)...)
+
+		if !iptables.Exists(acceptArgs...) {
+			log.Debugf("Enable inter-container communication")
+			if output, err := iptables.Raw(append([]string{"-I"}, acceptArgs...)...); err != nil {
+				return fmt.Errorf("Unable to allow intercontainer communication: %s", err)
+			} else if len(output) != 0 {
+				return fmt.Errorf("Error enabling intercontainer communication: %s", output)
+			}
+		}
+	}
+
+	// Accept all non-intercontainer outgoing packets
+	outgoingArgs := []string{"FORWARD", "-i", bridgeIface, "!", "-o", bridgeIface, "-j", "ACCEPT"}
+	if !iptables.Exists(outgoingArgs...) {
+		if output, err := iptables.Raw(append([]string{"-I"}, outgoingArgs...)...); err != nil {
+			return fmt.Errorf("Unable to allow outgoing packets: %s", err)
+		} else if len(output) != 0 {
+			return &iptables.ChainError{Chain: "FORWARD outgoing", Output: output}
+		}
+	}
+
+	// Accept incoming packets for existing connections
+	existingArgs := []string{"FORWARD", "-o", bridgeIface, "-m", "conntrack", "--ctstate", "RELATED,ESTABLISHED", "-j", "ACCEPT"}
+
+	if !iptables.Exists(existingArgs...) {
+		if output, err := iptables.Raw(append([]string{"-I"}, existingArgs...)...); err != nil {
+			return fmt.Errorf("Unable to allow incoming packets: %s", err)
+		} else if len(output) != 0 {
+			return &iptables.ChainError{Chain: "FORWARD incoming", Output: output}
+		}
+	}
+	return nil
+}
+
+// configureBridge attempts to create and configure a network bridge interface named `bridgeIface` on the host
+// If bridgeIP is empty, it will try to find a non-conflicting IP from the Docker-specified private ranges
+// If the bridge `bridgeIface` already exists, it will only perform the IP address association with the existing
+// bridge (fixes issue #8444)
+// If an address which doesn't conflict with existing interfaces can't be found, an error is returned.
+func configureBridge(bridgeIP string, bridgeIPv6 string, enableIPv6 bool) error {
+	nameservers := []string{}
+	resolvConf, _ := resolvconf.Get()
+	// we don't check for an error here, because we don't really care
+	// if we can't read /etc/resolv.conf. So instead we skip the append
+	// if resolvConf is nil. It either doesn't exist, or we can't read it
+	// for some reason.
+	if resolvConf != nil {
+		nameservers = append(nameservers, resolvconf.GetNameserversAsCIDR(resolvConf)...)
+	}
+
+	var ifaceAddr string
+	if len(bridgeIP) != 0 {
+		_, _, err := net.ParseCIDR(bridgeIP)
+		if err != nil {
+			return err
+		}
+		ifaceAddr = bridgeIP
+	} else {
+		for _, addr := range addrs {
+			_, dockerNetwork, err := net.ParseCIDR(addr)
+			if err != nil {
+				return err
+			}
+			if err := networkdriver.CheckNameserverOverlaps(nameservers, dockerNetwork); err == nil {
+				if err := networkdriver.CheckRouteOverlaps(dockerNetwork); err == nil {
+					ifaceAddr = addr
+					break
+				} else {
+					log.Debugf("%s %s", addr, err)
+				}
+			}
+		}
+	}
+
+	if ifaceAddr == "" {
+		return fmt.Errorf("Could not find a free IP address range for interface '%s'. Please configure its address manually and run 'docker -b %s'", bridgeIface, bridgeIface)
+	}
+	log.Debugf("Creating bridge %s with network %s", bridgeIface, ifaceAddr)
+
+	if err := createBridgeIface(bridgeIface); err != nil {
+		// the bridge may already exist, therefore we can ignore an "exists" error
+		if !os.IsExist(err) {
+			return err
+		}
+	}
+
+	iface, err := net.InterfaceByName(bridgeIface)
+	if err != nil {
+		return err
+	}
+
+	ipAddr, ipNet, err := net.ParseCIDR(ifaceAddr)
+	if err != nil {
+		return err
+	}
+
+	if err := netlink.NetworkLinkAddIp(iface, ipAddr, ipNet); err != nil {
+		return fmt.Errorf("Unable to add private network: %s", err)
+	}
+
+	if enableIPv6 {
+		if err := setupIPv6Bridge(bridgeIPv6); err != nil {
+			return err
+		}
+	}
+
+	if err := netlink.NetworkLinkUp(iface); err != nil {
+		return fmt.Errorf("Unable to start network bridge: %s", err)
+	}
+	return nil
+}
+
+func setupIPv6Bridge(bridgeIPv6 string) error {
+
+	iface, err := net.InterfaceByName(bridgeIface)
+	if err != nil {
+		return err
+	}
+	// Enable IPv6 on the bridge
+	procFile := "/proc/sys/net/ipv6/conf/" + iface.Name + "/disable_ipv6"
+	if err := ioutil.WriteFile(procFile, []byte{'0', '\n'}, 0644); err != nil {
+		return fmt.Errorf("Unable to enable IPv6 addresses on bridge: %v", err)
+	}
+
+	ipAddr6, ipNet6, err := net.ParseCIDR(bridgeIPv6)
+	if err != nil {
+		return fmt.Errorf("Unable to parse bridge IPv6 address: %q, error: %v", bridgeIPv6, err)
+	}
+
+	if err := netlink.NetworkLinkAddIp(iface, ipAddr6, ipNet6); err != nil {
+		return fmt.Errorf("Unable to add private IPv6 network: %v", err)
+	}
+
+	return nil
+}
+
+func createBridgeIface(name string) error {
+	kv, err := kernel.GetKernelVersion()
+	// only set the bridge's mac address if the kernel version is > 3.3
+	// before that it was not supported
+	setBridgeMacAddr := err == nil && (kv.Kernel >= 3 && kv.Major >= 3)
+	log.Debugf("setting bridge mac address = %v", setBridgeMacAddr)
+	return netlink.CreateBridge(name, setBridgeMacAddr)
+}
+
+// Generate a IEEE802 compliant MAC address from the given IP address.
+//
+// The generator is guaranteed to be consistent: the same IP will always yield the same
+// MAC address. This is to avoid ARP cache issues.
+func generateMacAddr(ip net.IP) net.HardwareAddr {
+	hw := make(net.HardwareAddr, 6)
+
+	// The first byte of the MAC address has to comply with these rules:
+	// 1. Unicast: Set the least-significant bit to 0.
+	// 2. Address is locally administered: Set the second-least-significant bit (U/L) to 1.
+	// 3. As "small" as possible: The veth address has to be "smaller" than the bridge address.
+	hw[0] = 0x02
+
+	// The first 24 bits of the MAC represent the Organizationally Unique Identifier (OUI).
+	// Since this address is locally administered, we can do whatever we want as long as
+	// it doesn't conflict with other addresses.
+	hw[1] = 0x42
+
+	// Insert the IP address into the last 32 bits of the MAC address.
+	// This is a simple way to guarantee the address will be consistent and unique.
+	copy(hw[2:], ip.To4())
+
+	return hw
+}
+
+func linkLocalIPv6FromMac(mac string) (string, error) {
+	hx := strings.Replace(mac, ":", "", -1)
+	hw, err := hex.DecodeString(hx)
+	if err != nil {
+		return "", errors.New("Could not parse MAC address " + mac)
+	}
+
+	hw[0] ^= 0x2
+
+	return fmt.Sprintf("fe80::%x%x:%xff:fe%x:%x%x/64", hw[0], hw[1], hw[2], hw[3], hw[4], hw[5]), nil
+}
+
+// Allocate a network interface
+func Allocate(job *engine.Job) engine.Status {
+	var (
+		ip            net.IP
+		mac           net.HardwareAddr
+		err           error
+		id            = job.Args[0]
+		requestedIP   = net.ParseIP(job.Getenv("RequestedIP"))
+		requestedIPv6 = net.ParseIP(job.Getenv("RequestedIPv6"))
+		globalIPv6    net.IP
+	)
+
+	if requestedIP != nil {
+		ip, err = ipallocator.RequestIP(bridgeIPv4Network, requestedIP)
+	} else {
+		ip, err = ipallocator.RequestIP(bridgeIPv4Network, nil)
+	}
+	if err != nil {
+		return job.Error(err)
+	}
+
+	// If no explicit mac address was given, generate a random one.
+	if mac, err = net.ParseMAC(job.Getenv("RequestedMac")); err != nil {
+		mac = generateMacAddr(ip)
+	}
+
+	if globalIPv6Network != nil {
+		// if globalIPv6Network Size is at least a /80 subnet generate IPv6 address from MAC address
+		netmask_ones, _ := globalIPv6Network.Mask.Size()
+		if requestedIPv6 == nil && netmask_ones <= 80 {
+			requestedIPv6 = globalIPv6Network.IP
+			for i, h := range mac {
+				requestedIPv6[i+10] = h
+			}
+		}
+
+		globalIPv6, err = ipallocator.RequestIP(globalIPv6Network, requestedIPv6)
+		if err != nil {
+			log.Errorf("Allocator: RequestIP v6: %s", err.Error())
+			return job.Error(err)
+		}
+		log.Infof("Allocated IPv6 %s", globalIPv6)
+	}
+
+	out := engine.Env{}
+	out.Set("IP", ip.String())
+	out.Set("Mask", bridgeIPv4Network.Mask.String())
+	out.Set("Gateway", bridgeIPv4Network.IP.String())
+	out.Set("MacAddress", mac.String())
+	out.Set("Bridge", bridgeIface)
+
+	size, _ := bridgeIPv4Network.Mask.Size()
+	out.SetInt("IPPrefixLen", size)
+
+	// if linklocal IPv6
+	localIPv6Net, err := linkLocalIPv6FromMac(mac.String())
+	if err != nil {
+		return job.Error(err)
+	}
+	localIPv6, _, _ := net.ParseCIDR(localIPv6Net)
+	out.Set("LinkLocalIPv6", localIPv6.String())
+	out.Set("MacAddress", mac.String())
+
+	if globalIPv6Network != nil {
+		out.Set("GlobalIPv6", globalIPv6.String())
+		sizev6, _ := globalIPv6Network.Mask.Size()
+		out.SetInt("GlobalIPv6PrefixLen", sizev6)
+		out.Set("IPv6Gateway", bridgeIPv6Addr.String())
+	}
+
+	currentInterfaces.Set(id, &networkInterface{
+		IP:   ip,
+		IPv6: globalIPv6,
+	})
+
+	out.WriteTo(job.Stdout)
+
+	return engine.StatusOK
+}
+
+// release an interface for a select ip
+func Release(job *engine.Job) engine.Status {
+	var (
+		id                 = job.Args[0]
+		containerInterface = currentInterfaces.Get(id)
+	)
+
+	if containerInterface == nil {
+		return job.Errorf("No network information to release for %s", id)
+	}
+
+	for _, nat := range containerInterface.PortMappings {
+		if err := portmapper.Unmap(nat); err != nil {
+			log.Infof("Unable to unmap port %s: %s", nat, err)
+		}
+	}
+
+	if err := ipallocator.ReleaseIP(bridgeIPv4Network, containerInterface.IP); err != nil {
+		log.Infof("Unable to release IPv4 %s", err)
+	}
+	if globalIPv6Network != nil {
+		if err := ipallocator.ReleaseIP(globalIPv6Network, containerInterface.IPv6); err != nil {
+			log.Infof("Unable to release IPv6 %s", err)
+		}
+	}
+	return engine.StatusOK
+}
+
+// Allocate an external port and map it to the interface
+func AllocatePort(job *engine.Job) engine.Status {
+	var (
+		err error
+
+		ip            = defaultBindingIP
+		id            = job.Args[0]
+		hostIP        = job.Getenv("HostIP")
+		hostPort      = job.GetenvInt("HostPort")
+		containerPort = job.GetenvInt("ContainerPort")
+		proto         = job.Getenv("Proto")
+		network       = currentInterfaces.Get(id)
+	)
+
+	if hostIP != "" {
+		ip = net.ParseIP(hostIP)
+		if ip == nil {
+			return job.Errorf("Bad parameter: invalid host ip %s", hostIP)
+		}
+	}
+
+	// host ip, proto, and host port
+	var container net.Addr
+	switch proto {
+	case "tcp":
+		container = &net.TCPAddr{IP: network.IP, Port: containerPort}
+	case "udp":
+		container = &net.UDPAddr{IP: network.IP, Port: containerPort}
+	default:
+		return job.Errorf("unsupported address type %s", proto)
+	}
+
+	//
+	// Try up to 10 times to get a port that's not already allocated.
+	//
+	// In the event of failure to bind, return the error that portmapper.Map
+	// yields.
+	//
+
+	var host net.Addr
+	for i := 0; i < MaxAllocatedPortAttempts; i++ {
+		if host, err = portmapper.Map(container, ip, hostPort); err == nil {
+			break
+		}
+		// There is no point in immediately retrying to map an explicitly
+		// chosen port.
+		if hostPort != 0 {
+			job.Logf("Failed to allocate and map port %d: %s", hostPort, err)
+			break
+		}
+		job.Logf("Failed to allocate and map port: %s, retry: %d", err, i+1)
+	}
+
+	if err != nil {
+		return job.Error(err)
+	}
+
+	network.PortMappings = append(network.PortMappings, host)
+
+	out := engine.Env{}
+	switch netAddr := host.(type) {
+	case *net.TCPAddr:
+		out.Set("HostIP", netAddr.IP.String())
+		out.SetInt("HostPort", netAddr.Port)
+	case *net.UDPAddr:
+		out.Set("HostIP", netAddr.IP.String())
+		out.SetInt("HostPort", netAddr.Port)
+	}
+	if _, err := out.WriteTo(job.Stdout); err != nil {
+		return job.Error(err)
+	}
+
+	return engine.StatusOK
+}
+
+func LinkContainers(job *engine.Job) engine.Status {
+	var (
+		action       = job.Args[0]
+		nfAction     iptables.Action
+		childIP      = job.Getenv("ChildIP")
+		parentIP     = job.Getenv("ParentIP")
+		ignoreErrors = job.GetenvBool("IgnoreErrors")
+		ports        = job.GetenvList("Ports")
+	)
+
+	switch action {
+	case "-A":
+		nfAction = iptables.Append
+	case "-I":
+		nfAction = iptables.Insert
+	case "-D":
+		nfAction = iptables.Delete
+	default:
+		return job.Errorf("Invalid action '%s' specified", action)
+	}
+
+	ip1 := net.ParseIP(parentIP)
+	if ip1 == nil {
+		return job.Errorf("parent IP '%s' is invalid", parentIP)
+	}
+	ip2 := net.ParseIP(childIP)
+	if ip2 == nil {
+		return job.Errorf("child IP '%s' is invalid", childIP)
+	}
+
+	chain := iptables.Chain{Name: "DOCKER", Bridge: bridgeIface}
+	for _, p := range ports {
+		port := nat.Port(p)
+		if err := chain.Link(nfAction, ip1, ip2, port.Int(), port.Proto()); !ignoreErrors && err != nil {
+			return job.Error(err)
+		}
+	}
+	return engine.StatusOK
+}

+ 161 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/bridge/driver_test.go

@@ -0,0 +1,161 @@
+package bridge
+
+import (
+	"net"
+	"strconv"
+	"testing"
+
+	"github.com/docker/docker/daemon/networkdriver/portmapper"
+	"github.com/docker/docker/engine"
+	"github.com/docker/docker/pkg/iptables"
+)
+
+func init() {
+	// reset the new proxy command for mocking out the userland proxy in tests
+	portmapper.NewProxy = portmapper.NewMockProxyCommand
+}
+
+func findFreePort(t *testing.T) int {
+	l, err := net.Listen("tcp", ":0")
+	if err != nil {
+		t.Fatal("Failed to find a free port")
+	}
+	defer l.Close()
+
+	result, err := net.ResolveTCPAddr("tcp", l.Addr().String())
+	if err != nil {
+		t.Fatal("Failed to resolve address to identify free port")
+	}
+	return result.Port
+}
+
+func newPortAllocationJob(eng *engine.Engine, port int) (job *engine.Job) {
+	strPort := strconv.Itoa(port)
+
+	job = eng.Job("allocate_port", "container_id")
+	job.Setenv("HostIP", "127.0.0.1")
+	job.Setenv("HostPort", strPort)
+	job.Setenv("Proto", "tcp")
+	job.Setenv("ContainerPort", strPort)
+	return
+}
+
+func newPortAllocationJobWithInvalidHostIP(eng *engine.Engine, port int) (job *engine.Job) {
+	strPort := strconv.Itoa(port)
+
+	job = eng.Job("allocate_port", "container_id")
+	job.Setenv("HostIP", "localhost")
+	job.Setenv("HostPort", strPort)
+	job.Setenv("Proto", "tcp")
+	job.Setenv("ContainerPort", strPort)
+	return
+}
+
+func TestAllocatePortDetection(t *testing.T) {
+	eng := engine.New()
+	eng.Logging = false
+
+	freePort := findFreePort(t)
+
+	// Init driver
+	job := eng.Job("initdriver")
+	if res := InitDriver(job); res != engine.StatusOK {
+		t.Fatal("Failed to initialize network driver")
+	}
+
+	// Allocate interface
+	job = eng.Job("allocate_interface", "container_id")
+	if res := Allocate(job); res != engine.StatusOK {
+		t.Fatal("Failed to allocate network interface")
+	}
+
+	// Allocate same port twice, expect failure on second call
+	job = newPortAllocationJob(eng, freePort)
+	if res := AllocatePort(job); res != engine.StatusOK {
+		t.Fatal("Failed to find a free port to allocate")
+	}
+	if res := AllocatePort(job); res == engine.StatusOK {
+		t.Fatal("Duplicate port allocation granted by AllocatePort")
+	}
+}
+
+func TestHostnameFormatChecking(t *testing.T) {
+	eng := engine.New()
+	eng.Logging = false
+
+	freePort := findFreePort(t)
+
+	// Init driver
+	job := eng.Job("initdriver")
+	if res := InitDriver(job); res != engine.StatusOK {
+		t.Fatal("Failed to initialize network driver")
+	}
+
+	// Allocate interface
+	job = eng.Job("allocate_interface", "container_id")
+	if res := Allocate(job); res != engine.StatusOK {
+		t.Fatal("Failed to allocate network interface")
+	}
+
+	// Allocate port with invalid HostIP, expect failure with Bad Request http status
+	job = newPortAllocationJobWithInvalidHostIP(eng, freePort)
+	if res := AllocatePort(job); res == engine.StatusOK {
+		t.Fatal("Failed to check invalid HostIP")
+	}
+}
+
+func TestMacAddrGeneration(t *testing.T) {
+	ip := net.ParseIP("192.168.0.1")
+	mac := generateMacAddr(ip).String()
+
+	// Should be consistent.
+	if generateMacAddr(ip).String() != mac {
+		t.Fatal("Inconsistent MAC address")
+	}
+
+	// Should be unique.
+	ip2 := net.ParseIP("192.168.0.2")
+	if generateMacAddr(ip2).String() == mac {
+		t.Fatal("Non-unique MAC address")
+	}
+}
+
+func TestLinkContainers(t *testing.T) {
+	eng := engine.New()
+	eng.Logging = false
+
+	// Init driver
+	job := eng.Job("initdriver")
+	if res := InitDriver(job); res != engine.StatusOK {
+		t.Fatal("Failed to initialize network driver")
+	}
+
+	// Allocate interface
+	job = eng.Job("allocate_interface", "container_id")
+	if res := Allocate(job); res != engine.StatusOK {
+		t.Fatal("Failed to allocate network interface")
+	}
+
+	job.Args[0] = "-I"
+
+	job.Setenv("ChildIP", "172.17.0.2")
+	job.Setenv("ParentIP", "172.17.0.1")
+	job.SetenvBool("IgnoreErrors", false)
+	job.SetenvList("Ports", []string{"1234"})
+
+	bridgeIface = "lo"
+	_, err := iptables.NewChain("DOCKER", bridgeIface, iptables.Filter)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if res := LinkContainers(job); res != engine.StatusOK {
+		t.Fatalf("LinkContainers failed")
+	}
+
+	// flush rules
+	if _, err = iptables.Raw([]string{"-F", "DOCKER"}...); err != nil {
+		t.Fatal(err)
+	}
+
+}

+ 160 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/ipallocator/allocator.go

@@ -0,0 +1,160 @@
+package ipallocator
+
+import (
+	"errors"
+	"math/big"
+	"net"
+	"sync"
+
+	log "github.com/Sirupsen/logrus"
+	"github.com/docker/docker/daemon/networkdriver"
+)
+
+// allocatedMap is thread-unsafe set of allocated IP
+type allocatedMap struct {
+	p     map[string]struct{}
+	last  *big.Int
+	begin *big.Int
+	end   *big.Int
+}
+
+func newAllocatedMap(network *net.IPNet) *allocatedMap {
+	firstIP, lastIP := networkdriver.NetworkRange(network)
+	begin := big.NewInt(0).Add(ipToBigInt(firstIP), big.NewInt(1))
+	end := big.NewInt(0).Sub(ipToBigInt(lastIP), big.NewInt(1))
+
+	return &allocatedMap{
+		p:     make(map[string]struct{}),
+		begin: begin,
+		end:   end,
+		last:  big.NewInt(0).Sub(begin, big.NewInt(1)), // so first allocated will be begin
+	}
+}
+
+type networkSet map[string]*allocatedMap
+
+var (
+	ErrNoAvailableIPs           = errors.New("no available ip addresses on network")
+	ErrIPAlreadyAllocated       = errors.New("ip already allocated")
+	ErrIPOutOfRange             = errors.New("requested ip is out of range")
+	ErrNetworkAlreadyRegistered = errors.New("network already registered")
+	ErrBadSubnet                = errors.New("network does not contain specified subnet")
+)
+
+var (
+	lock         = sync.Mutex{}
+	allocatedIPs = networkSet{}
+)
+
+// RegisterSubnet registers network in global allocator with bounds
+// defined by subnet. If you want to use network range you must call
+// this method before first RequestIP, otherwise full network range will be used
+func RegisterSubnet(network *net.IPNet, subnet *net.IPNet) error {
+	lock.Lock()
+	defer lock.Unlock()
+	key := network.String()
+	if _, ok := allocatedIPs[key]; ok {
+		return ErrNetworkAlreadyRegistered
+	}
+	n := newAllocatedMap(network)
+	beginIP, endIP := networkdriver.NetworkRange(subnet)
+	begin := big.NewInt(0).Add(ipToBigInt(beginIP), big.NewInt(1))
+	end := big.NewInt(0).Sub(ipToBigInt(endIP), big.NewInt(1))
+
+	// Check that subnet is within network
+	if !(begin.Cmp(n.begin) >= 0 && end.Cmp(n.end) <= 0 && begin.Cmp(end) == -1) {
+		return ErrBadSubnet
+	}
+	n.begin.Set(begin)
+	n.end.Set(end)
+	n.last.Sub(begin, big.NewInt(1))
+	allocatedIPs[key] = n
+	return nil
+}
+
+// RequestIP requests an available ip from the given network.  It
+// will return the next available ip if the ip provided is nil.  If the
+// ip provided is not nil it will validate that the provided ip is available
+// for use or return an error
+func RequestIP(network *net.IPNet, ip net.IP) (net.IP, error) {
+	lock.Lock()
+	defer lock.Unlock()
+	key := network.String()
+	allocated, ok := allocatedIPs[key]
+	if !ok {
+		allocated = newAllocatedMap(network)
+		allocatedIPs[key] = allocated
+	}
+
+	if ip == nil {
+		return allocated.getNextIP()
+	}
+	return allocated.checkIP(ip)
+}
+
+// ReleaseIP adds the provided ip back into the pool of
+// available ips to be returned for use.
+func ReleaseIP(network *net.IPNet, ip net.IP) error {
+	lock.Lock()
+	defer lock.Unlock()
+	if allocated, exists := allocatedIPs[network.String()]; exists {
+		delete(allocated.p, ip.String())
+	}
+	return nil
+}
+
+func (allocated *allocatedMap) checkIP(ip net.IP) (net.IP, error) {
+	if _, ok := allocated.p[ip.String()]; ok {
+		return nil, ErrIPAlreadyAllocated
+	}
+
+	pos := ipToBigInt(ip)
+	// Verify that the IP address is within our network range.
+	if pos.Cmp(allocated.begin) == -1 || pos.Cmp(allocated.end) == 1 {
+		return nil, ErrIPOutOfRange
+	}
+
+	// Register the IP.
+	allocated.p[ip.String()] = struct{}{}
+
+	return ip, nil
+}
+
+// return an available ip if one is currently available.  If not,
+// return the next available ip for the nextwork
+func (allocated *allocatedMap) getNextIP() (net.IP, error) {
+	pos := big.NewInt(0).Set(allocated.last)
+	allRange := big.NewInt(0).Sub(allocated.end, allocated.begin)
+	for i := big.NewInt(0); i.Cmp(allRange) <= 0; i.Add(i, big.NewInt(1)) {
+		pos.Add(pos, big.NewInt(1))
+		if pos.Cmp(allocated.end) == 1 {
+			pos.Set(allocated.begin)
+		}
+		if _, ok := allocated.p[bigIntToIP(pos).String()]; ok {
+			continue
+		}
+		allocated.p[bigIntToIP(pos).String()] = struct{}{}
+		allocated.last.Set(pos)
+		return bigIntToIP(pos), nil
+	}
+	return nil, ErrNoAvailableIPs
+}
+
+// Converts a 4 bytes IP into a 128 bit integer
+func ipToBigInt(ip net.IP) *big.Int {
+	x := big.NewInt(0)
+	if ip4 := ip.To4(); ip4 != nil {
+		return x.SetBytes(ip4)
+	}
+	if ip6 := ip.To16(); ip6 != nil {
+		return x.SetBytes(ip6)
+	}
+
+	log.Errorf("ipToBigInt: Wrong IP length! %s", ip)
+	return nil
+}
+
+// Converts 128 bit integer into a 4 bytes IP address
+func bigIntToIP(v *big.Int) net.IP {
+	return net.IP(v.Bytes())
+}

+ 681 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/ipallocator/allocator_test.go

@@ -0,0 +1,681 @@
+package ipallocator
+
+import (
+	"fmt"
+	"math/big"
+	"net"
+	"testing"
+)
+
+func reset() {
+	allocatedIPs = networkSet{}
+}
+
+func TestConversion(t *testing.T) {
+	ip := net.ParseIP("127.0.0.1")
+	i := ipToBigInt(ip)
+	if i.Cmp(big.NewInt(0x7f000001)) != 0 {
+		t.Fatal("incorrect conversion")
+	}
+	conv := bigIntToIP(i)
+	if !ip.Equal(conv) {
+		t.Error(conv.String())
+	}
+}
+
+func TestConversionIPv6(t *testing.T) {
+	ip := net.ParseIP("2a00:1450::1")
+	ip2 := net.ParseIP("2a00:1450::2")
+	ip3 := net.ParseIP("2a00:1450::1:1")
+	i := ipToBigInt(ip)
+	val, success := big.NewInt(0).SetString("2a001450000000000000000000000001", 16)
+	if !success {
+		t.Fatal("Hex-String to BigInt conversion failed.")
+	}
+	if i.Cmp(val) != 0 {
+		t.Fatal("incorrent conversion")
+	}
+
+	conv := bigIntToIP(i)
+	conv2 := bigIntToIP(big.NewInt(0).Add(i, big.NewInt(1)))
+	conv3 := bigIntToIP(big.NewInt(0).Add(i, big.NewInt(0x10000)))
+
+	if !ip.Equal(conv) {
+		t.Error("2a00:1450::1 should be equal to " + conv.String())
+	}
+	if !ip2.Equal(conv2) {
+		t.Error("2a00:1450::2 should be equal to " + conv2.String())
+	}
+	if !ip3.Equal(conv3) {
+		t.Error("2a00:1450::1:1 should be equal to " + conv3.String())
+	}
+}
+
+func TestRequestNewIps(t *testing.T) {
+	defer reset()
+	network := &net.IPNet{
+		IP:   []byte{192, 168, 0, 1},
+		Mask: []byte{255, 255, 255, 0},
+	}
+
+	var ip net.IP
+	var err error
+
+	for i := 1; i < 10; i++ {
+		ip, err = RequestIP(network, nil)
+		if err != nil {
+			t.Fatal(err)
+		}
+
+		if expected := fmt.Sprintf("192.168.0.%d", i); ip.String() != expected {
+			t.Fatalf("Expected ip %s got %s", expected, ip.String())
+		}
+	}
+	value := bigIntToIP(big.NewInt(0).Add(ipToBigInt(ip), big.NewInt(1))).String()
+	if err := ReleaseIP(network, ip); err != nil {
+		t.Fatal(err)
+	}
+	ip, err = RequestIP(network, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if ip.String() != value {
+		t.Fatalf("Expected to receive the next ip %s got %s", value, ip.String())
+	}
+}
+
+func TestRequestNewIpV6(t *testing.T) {
+	defer reset()
+	network := &net.IPNet{
+		IP:   []byte{0x2a, 0x00, 0x14, 0x50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
+		Mask: []byte{255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0}, // /64 netmask
+	}
+
+	var ip net.IP
+	var err error
+	for i := 1; i < 10; i++ {
+		ip, err = RequestIP(network, nil)
+		if err != nil {
+			t.Fatal(err)
+		}
+
+		if expected := fmt.Sprintf("2a00:1450::%d", i); ip.String() != expected {
+			t.Fatalf("Expected ip %s got %s", expected, ip.String())
+		}
+	}
+	value := bigIntToIP(big.NewInt(0).Add(ipToBigInt(ip), big.NewInt(1))).String()
+	if err := ReleaseIP(network, ip); err != nil {
+		t.Fatal(err)
+	}
+	ip, err = RequestIP(network, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if ip.String() != value {
+		t.Fatalf("Expected to receive the next ip %s got %s", value, ip.String())
+	}
+}
+
+func TestReleaseIp(t *testing.T) {
+	defer reset()
+	network := &net.IPNet{
+		IP:   []byte{192, 168, 0, 1},
+		Mask: []byte{255, 255, 255, 0},
+	}
+
+	ip, err := RequestIP(network, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if err := ReleaseIP(network, ip); err != nil {
+		t.Fatal(err)
+	}
+}
+
+func TestReleaseIpV6(t *testing.T) {
+	defer reset()
+	network := &net.IPNet{
+		IP:   []byte{0x2a, 0x00, 0x14, 0x50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
+		Mask: []byte{255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0}, // /64 netmask
+	}
+
+	ip, err := RequestIP(network, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if err := ReleaseIP(network, ip); err != nil {
+		t.Fatal(err)
+	}
+}
+
+func TestGetReleasedIp(t *testing.T) {
+	defer reset()
+	network := &net.IPNet{
+		IP:   []byte{192, 168, 0, 1},
+		Mask: []byte{255, 255, 255, 0},
+	}
+
+	ip, err := RequestIP(network, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	value := ip.String()
+	if err := ReleaseIP(network, ip); err != nil {
+		t.Fatal(err)
+	}
+
+	for i := 0; i < 253; i++ {
+		_, err = RequestIP(network, nil)
+		if err != nil {
+			t.Fatal(err)
+		}
+		err = ReleaseIP(network, ip)
+		if err != nil {
+			t.Fatal(err)
+		}
+	}
+
+	ip, err = RequestIP(network, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if ip.String() != value {
+		t.Fatalf("Expected to receive same ip %s got %s", value, ip.String())
+	}
+}
+
+func TestGetReleasedIpV6(t *testing.T) {
+	defer reset()
+	network := &net.IPNet{
+		IP:   []byte{0x2a, 0x00, 0x14, 0x50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
+		Mask: []byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0},
+	}
+
+	ip, err := RequestIP(network, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	value := ip.String()
+	if err := ReleaseIP(network, ip); err != nil {
+		t.Fatal(err)
+	}
+
+	for i := 0; i < 253; i++ {
+		_, err = RequestIP(network, nil)
+		if err != nil {
+			t.Fatal(err)
+		}
+		err = ReleaseIP(network, ip)
+		if err != nil {
+			t.Fatal(err)
+		}
+	}
+
+	ip, err = RequestIP(network, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if ip.String() != value {
+		t.Fatalf("Expected to receive same ip %s got %s", value, ip.String())
+	}
+}
+
+func TestRequestSpecificIp(t *testing.T) {
+	defer reset()
+	network := &net.IPNet{
+		IP:   []byte{192, 168, 0, 1},
+		Mask: []byte{255, 255, 255, 224},
+	}
+
+	ip := net.ParseIP("192.168.0.5")
+
+	// Request a "good" IP.
+	if _, err := RequestIP(network, ip); err != nil {
+		t.Fatal(err)
+	}
+
+	// Request the same IP again.
+	if _, err := RequestIP(network, ip); err != ErrIPAlreadyAllocated {
+		t.Fatalf("Got the same IP twice: %#v", err)
+	}
+
+	// Request an out of range IP.
+	if _, err := RequestIP(network, net.ParseIP("192.168.0.42")); err != ErrIPOutOfRange {
+		t.Fatalf("Got an out of range IP: %#v", err)
+	}
+}
+
+func TestRequestSpecificIpV6(t *testing.T) {
+	defer reset()
+	network := &net.IPNet{
+		IP:   []byte{0x2a, 0x00, 0x14, 0x50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
+		Mask: []byte{255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0}, // /64 netmask
+	}
+
+	ip := net.ParseIP("2a00:1450::5")
+
+	// Request a "good" IP.
+	if _, err := RequestIP(network, ip); err != nil {
+		t.Fatal(err)
+	}
+
+	// Request the same IP again.
+	if _, err := RequestIP(network, ip); err != ErrIPAlreadyAllocated {
+		t.Fatalf("Got the same IP twice: %#v", err)
+	}
+
+	// Request an out of range IP.
+	if _, err := RequestIP(network, net.ParseIP("2a00:1500::1")); err != ErrIPOutOfRange {
+		t.Fatalf("Got an out of range IP: %#v", err)
+	}
+}
+
+func TestIPAllocator(t *testing.T) {
+	expectedIPs := []net.IP{
+		0: net.IPv4(127, 0, 0, 1),
+		1: net.IPv4(127, 0, 0, 2),
+		2: net.IPv4(127, 0, 0, 3),
+		3: net.IPv4(127, 0, 0, 4),
+		4: net.IPv4(127, 0, 0, 5),
+		5: net.IPv4(127, 0, 0, 6),
+	}
+
+	gwIP, n, _ := net.ParseCIDR("127.0.0.1/29")
+
+	network := &net.IPNet{IP: gwIP, Mask: n.Mask}
+	// Pool after initialisation (f = free, u = used)
+	// 1(f) - 2(f) - 3(f) - 4(f) - 5(f) - 6(f)
+	//  ↑
+
+	// Check that we get 6 IPs, from 127.0.0.1–127.0.0.6, in that
+	// order.
+	for i := 0; i < 6; i++ {
+		ip, err := RequestIP(network, nil)
+		if err != nil {
+			t.Fatal(err)
+		}
+
+		assertIPEquals(t, expectedIPs[i], ip)
+	}
+	// Before loop begin
+	// 1(f) - 2(f) - 3(f) - 4(f) - 5(f) - 6(f)
+	//  ↑
+
+	// After i = 0
+	// 1(u) - 2(f) - 3(f) - 4(f) - 5(f) - 6(f)
+	//         ↑
+
+	// After i = 1
+	// 1(u) - 2(u) - 3(f) - 4(f) - 5(f) - 6(f)
+	//                ↑
+
+	// After i = 2
+	// 1(u) - 2(u) - 3(u) - 4(f) - 5(f) - 6(f)
+	//                       ↑
+
+	// After i = 3
+	// 1(u) - 2(u) - 3(u) - 4(u) - 5(f) - 6(f)
+	//                              ↑
+
+	// After i = 4
+	// 1(u) - 2(u) - 3(u) - 4(u) - 5(u) - 6(f)
+	//                                     ↑
+
+	// After i = 5
+	// 1(u) - 2(u) - 3(u) - 4(u) - 5(u) - 6(u)
+	//  ↑
+
+	// Check that there are no more IPs
+	ip, err := RequestIP(network, nil)
+	if err == nil {
+		t.Fatalf("There shouldn't be any IP addresses at this point, got %s\n", ip)
+	}
+
+	// Release some IPs in non-sequential order
+	if err := ReleaseIP(network, expectedIPs[3]); err != nil {
+		t.Fatal(err)
+	}
+	// 1(u) - 2(u) - 3(u) - 4(f) - 5(u) - 6(u)
+	//                       ↑
+
+	if err := ReleaseIP(network, expectedIPs[2]); err != nil {
+		t.Fatal(err)
+	}
+	// 1(u) - 2(u) - 3(f) - 4(f) - 5(u) - 6(u)
+	//                ↑
+
+	if err := ReleaseIP(network, expectedIPs[4]); err != nil {
+		t.Fatal(err)
+	}
+	// 1(u) - 2(u) - 3(f) - 4(f) - 5(f) - 6(u)
+	//                              ↑
+
+	// Make sure that IPs are reused in sequential order, starting
+	// with the first released IP
+	newIPs := make([]net.IP, 3)
+	for i := 0; i < 3; i++ {
+		ip, err := RequestIP(network, nil)
+		if err != nil {
+			t.Fatal(err)
+		}
+
+		newIPs[i] = ip
+	}
+	assertIPEquals(t, expectedIPs[2], newIPs[0])
+	assertIPEquals(t, expectedIPs[3], newIPs[1])
+	assertIPEquals(t, expectedIPs[4], newIPs[2])
+
+	_, err = RequestIP(network, nil)
+	if err == nil {
+		t.Fatal("There shouldn't be any IP addresses at this point")
+	}
+}
+
+func TestAllocateFirstIP(t *testing.T) {
+	defer reset()
+	network := &net.IPNet{
+		IP:   []byte{192, 168, 0, 0},
+		Mask: []byte{255, 255, 255, 0},
+	}
+
+	firstIP := network.IP.To4().Mask(network.Mask)
+	first := big.NewInt(0).Add(ipToBigInt(firstIP), big.NewInt(1))
+
+	ip, err := RequestIP(network, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+	allocated := ipToBigInt(ip)
+
+	if allocated == first {
+		t.Fatalf("allocated ip should not equal first ip: %d == %d", first, allocated)
+	}
+}
+
+func TestAllocateAllIps(t *testing.T) {
+	defer reset()
+	network := &net.IPNet{
+		IP:   []byte{192, 168, 0, 1},
+		Mask: []byte{255, 255, 255, 0},
+	}
+
+	var (
+		current, first net.IP
+		err            error
+		isFirst        = true
+	)
+
+	for err == nil {
+		current, err = RequestIP(network, nil)
+		if isFirst {
+			first = current
+			isFirst = false
+		}
+	}
+
+	if err != ErrNoAvailableIPs {
+		t.Fatal(err)
+	}
+
+	if _, err := RequestIP(network, nil); err != ErrNoAvailableIPs {
+		t.Fatal(err)
+	}
+
+	if err := ReleaseIP(network, first); err != nil {
+		t.Fatal(err)
+	}
+
+	again, err := RequestIP(network, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	assertIPEquals(t, first, again)
+
+	// ensure that alloc.last == alloc.begin won't result in dead loop
+	if _, err := RequestIP(network, nil); err != ErrNoAvailableIPs {
+		t.Fatal(err)
+	}
+
+	// Test by making alloc.last the only free ip and ensure we get it back
+	// #1. first of the range, (alloc.last == ipToInt(first) already)
+	if err := ReleaseIP(network, first); err != nil {
+		t.Fatal(err)
+	}
+
+	ret, err := RequestIP(network, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	assertIPEquals(t, first, ret)
+
+	// #2. last of the range, note that current is the last one
+	last := net.IPv4(192, 168, 0, 254)
+	setLastTo(t, network, last)
+
+	ret, err = RequestIP(network, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	assertIPEquals(t, last, ret)
+
+	// #3. middle of the range
+	mid := net.IPv4(192, 168, 0, 7)
+	setLastTo(t, network, mid)
+
+	ret, err = RequestIP(network, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	assertIPEquals(t, mid, ret)
+}
+
+// make sure the pool is full when calling setLastTo.
+// we don't cheat here
+func setLastTo(t *testing.T, network *net.IPNet, ip net.IP) {
+	if err := ReleaseIP(network, ip); err != nil {
+		t.Fatal(err)
+	}
+
+	ret, err := RequestIP(network, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	assertIPEquals(t, ip, ret)
+
+	if err := ReleaseIP(network, ip); err != nil {
+		t.Fatal(err)
+	}
+}
+
+func TestAllocateDifferentSubnets(t *testing.T) {
+	defer reset()
+	network1 := &net.IPNet{
+		IP:   []byte{192, 168, 0, 1},
+		Mask: []byte{255, 255, 255, 0},
+	}
+	network2 := &net.IPNet{
+		IP:   []byte{127, 0, 0, 1},
+		Mask: []byte{255, 255, 255, 0},
+	}
+	network3 := &net.IPNet{
+		IP:   []byte{0x2a, 0x00, 0x14, 0x50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
+		Mask: []byte{255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0}, // /64 netmask
+	}
+	network4 := &net.IPNet{
+		IP:   []byte{0x2a, 0x00, 0x16, 0x32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
+		Mask: []byte{255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0}, // /64 netmask
+	}
+	expectedIPs := []net.IP{
+		0: net.IPv4(192, 168, 0, 1),
+		1: net.IPv4(192, 168, 0, 2),
+		2: net.IPv4(127, 0, 0, 1),
+		3: net.IPv4(127, 0, 0, 2),
+		4: net.ParseIP("2a00:1450::1"),
+		5: net.ParseIP("2a00:1450::2"),
+		6: net.ParseIP("2a00:1450::3"),
+		7: net.ParseIP("2a00:1632::1"),
+		8: net.ParseIP("2a00:1632::2"),
+	}
+
+	ip11, err := RequestIP(network1, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+	ip12, err := RequestIP(network1, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+	ip21, err := RequestIP(network2, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+	ip22, err := RequestIP(network2, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+	ip31, err := RequestIP(network3, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+	ip32, err := RequestIP(network3, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+	ip33, err := RequestIP(network3, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+	ip41, err := RequestIP(network4, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+	ip42, err := RequestIP(network4, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+	assertIPEquals(t, expectedIPs[0], ip11)
+	assertIPEquals(t, expectedIPs[1], ip12)
+	assertIPEquals(t, expectedIPs[2], ip21)
+	assertIPEquals(t, expectedIPs[3], ip22)
+	assertIPEquals(t, expectedIPs[4], ip31)
+	assertIPEquals(t, expectedIPs[5], ip32)
+	assertIPEquals(t, expectedIPs[6], ip33)
+	assertIPEquals(t, expectedIPs[7], ip41)
+	assertIPEquals(t, expectedIPs[8], ip42)
+}
+
+func TestRegisterBadTwice(t *testing.T) {
+	defer reset()
+	network := &net.IPNet{
+		IP:   []byte{192, 168, 1, 1},
+		Mask: []byte{255, 255, 255, 0},
+	}
+	subnet := &net.IPNet{
+		IP:   []byte{192, 168, 1, 8},
+		Mask: []byte{255, 255, 255, 248},
+	}
+
+	if err := RegisterSubnet(network, subnet); err != nil {
+		t.Fatal(err)
+	}
+	subnet = &net.IPNet{
+		IP:   []byte{192, 168, 1, 16},
+		Mask: []byte{255, 255, 255, 248},
+	}
+	if err := RegisterSubnet(network, subnet); err != ErrNetworkAlreadyRegistered {
+		t.Fatalf("Expecteded ErrNetworkAlreadyRegistered error, got %v", err)
+	}
+}
+
+func TestRegisterBadRange(t *testing.T) {
+	defer reset()
+	network := &net.IPNet{
+		IP:   []byte{192, 168, 1, 1},
+		Mask: []byte{255, 255, 255, 0},
+	}
+	subnet := &net.IPNet{
+		IP:   []byte{192, 168, 1, 1},
+		Mask: []byte{255, 255, 0, 0},
+	}
+	if err := RegisterSubnet(network, subnet); err != ErrBadSubnet {
+		t.Fatalf("Expected ErrBadSubnet error, got %v", err)
+	}
+}
+
+func TestAllocateFromRange(t *testing.T) {
+	defer reset()
+	network := &net.IPNet{
+		IP:   []byte{192, 168, 0, 1},
+		Mask: []byte{255, 255, 255, 0},
+	}
+	// 192.168.1.9 - 192.168.1.14
+	subnet := &net.IPNet{
+		IP:   []byte{192, 168, 0, 8},
+		Mask: []byte{255, 255, 255, 248},
+	}
+
+	if err := RegisterSubnet(network, subnet); err != nil {
+		t.Fatal(err)
+	}
+	expectedIPs := []net.IP{
+		0: net.IPv4(192, 168, 0, 9),
+		1: net.IPv4(192, 168, 0, 10),
+		2: net.IPv4(192, 168, 0, 11),
+		3: net.IPv4(192, 168, 0, 12),
+		4: net.IPv4(192, 168, 0, 13),
+		5: net.IPv4(192, 168, 0, 14),
+	}
+	for _, ip := range expectedIPs {
+		rip, err := RequestIP(network, nil)
+		if err != nil {
+			t.Fatal(err)
+		}
+		assertIPEquals(t, ip, rip)
+	}
+
+	if _, err := RequestIP(network, nil); err != ErrNoAvailableIPs {
+		t.Fatalf("Expected ErrNoAvailableIPs error, got %v", err)
+	}
+	for _, ip := range expectedIPs {
+		ReleaseIP(network, ip)
+		rip, err := RequestIP(network, nil)
+		if err != nil {
+			t.Fatal(err)
+		}
+		assertIPEquals(t, ip, rip)
+	}
+}
+
+func assertIPEquals(t *testing.T, ip1, ip2 net.IP) {
+	if !ip1.Equal(ip2) {
+		t.Fatalf("Expected IP %s, got %s", ip1, ip2)
+	}
+}
+
+func BenchmarkRequestIP(b *testing.B) {
+	network := &net.IPNet{
+		IP:   []byte{192, 168, 0, 1},
+		Mask: []byte{255, 255, 255, 0},
+	}
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		for j := 0; j < 253; j++ {
+			_, err := RequestIP(network, nil)
+			if err != nil {
+				b.Fatal(err)
+			}
+		}
+		reset()
+	}
+}

+ 10 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/network.go

@@ -0,0 +1,10 @@
+package networkdriver
+
+import (
+	"errors"
+)
+
+var (
+	ErrNetworkOverlapsWithNameservers = errors.New("requested network overlaps with nameserver")
+	ErrNetworkOverlaps                = errors.New("requested network overlaps with existing network")
+)

+ 175 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/network_test.go

@@ -0,0 +1,175 @@
+package networkdriver
+
+import (
+	"github.com/docker/libcontainer/netlink"
+	"net"
+	"testing"
+)
+
+func TestNonOverlapingNameservers(t *testing.T) {
+	network := &net.IPNet{
+		IP:   []byte{192, 168, 0, 1},
+		Mask: []byte{255, 255, 255, 0},
+	}
+	nameservers := []string{
+		"127.0.0.1/32",
+	}
+
+	if err := CheckNameserverOverlaps(nameservers, network); err != nil {
+		t.Fatal(err)
+	}
+}
+
+func TestOverlapingNameservers(t *testing.T) {
+	network := &net.IPNet{
+		IP:   []byte{192, 168, 0, 1},
+		Mask: []byte{255, 255, 255, 0},
+	}
+	nameservers := []string{
+		"192.168.0.1/32",
+	}
+
+	if err := CheckNameserverOverlaps(nameservers, network); err == nil {
+		t.Fatalf("Expected error %s got %s", ErrNetworkOverlapsWithNameservers, err)
+	}
+}
+
+func TestCheckRouteOverlaps(t *testing.T) {
+	orig := networkGetRoutesFct
+	defer func() {
+		networkGetRoutesFct = orig
+	}()
+	networkGetRoutesFct = func() ([]netlink.Route, error) {
+		routesData := []string{"10.0.2.0/32", "10.0.3.0/24", "10.0.42.0/24", "172.16.42.0/24", "192.168.142.0/24"}
+
+		routes := []netlink.Route{}
+		for _, addr := range routesData {
+			_, netX, _ := net.ParseCIDR(addr)
+			routes = append(routes, netlink.Route{IPNet: netX})
+		}
+		return routes, nil
+	}
+
+	_, netX, _ := net.ParseCIDR("172.16.0.1/24")
+	if err := CheckRouteOverlaps(netX); err != nil {
+		t.Fatal(err)
+	}
+
+	_, netX, _ = net.ParseCIDR("10.0.2.0/24")
+	if err := CheckRouteOverlaps(netX); err == nil {
+		t.Fatalf("10.0.2.0/24 and 10.0.2.0 should overlap but it doesn't")
+	}
+}
+
+func TestCheckNameserverOverlaps(t *testing.T) {
+	nameservers := []string{"10.0.2.3/32", "192.168.102.1/32"}
+
+	_, netX, _ := net.ParseCIDR("10.0.2.3/32")
+
+	if err := CheckNameserverOverlaps(nameservers, netX); err == nil {
+		t.Fatalf("%s should overlap 10.0.2.3/32 but doesn't", netX)
+	}
+
+	_, netX, _ = net.ParseCIDR("192.168.102.2/32")
+
+	if err := CheckNameserverOverlaps(nameservers, netX); err != nil {
+		t.Fatalf("%s should not overlap %v but it does", netX, nameservers)
+	}
+}
+
+func AssertOverlap(CIDRx string, CIDRy string, t *testing.T) {
+	_, netX, _ := net.ParseCIDR(CIDRx)
+	_, netY, _ := net.ParseCIDR(CIDRy)
+	if !NetworkOverlaps(netX, netY) {
+		t.Errorf("%v and %v should overlap", netX, netY)
+	}
+}
+
+func AssertNoOverlap(CIDRx string, CIDRy string, t *testing.T) {
+	_, netX, _ := net.ParseCIDR(CIDRx)
+	_, netY, _ := net.ParseCIDR(CIDRy)
+	if NetworkOverlaps(netX, netY) {
+		t.Errorf("%v and %v should not overlap", netX, netY)
+	}
+}
+
+func TestNetworkOverlaps(t *testing.T) {
+	//netY starts at same IP and ends within netX
+	AssertOverlap("172.16.0.1/24", "172.16.0.1/25", t)
+	//netY starts within netX and ends at same IP
+	AssertOverlap("172.16.0.1/24", "172.16.0.128/25", t)
+	//netY starts and ends within netX
+	AssertOverlap("172.16.0.1/24", "172.16.0.64/25", t)
+	//netY starts at same IP and ends outside of netX
+	AssertOverlap("172.16.0.1/24", "172.16.0.1/23", t)
+	//netY starts before and ends at same IP of netX
+	AssertOverlap("172.16.1.1/24", "172.16.0.1/23", t)
+	//netY starts before and ends outside of netX
+	AssertOverlap("172.16.1.1/24", "172.16.0.1/22", t)
+	//netY starts and ends before netX
+	AssertNoOverlap("172.16.1.1/25", "172.16.0.1/24", t)
+	//netX starts and ends before netY
+	AssertNoOverlap("172.16.1.1/25", "172.16.2.1/24", t)
+}
+
+func TestNetworkRange(t *testing.T) {
+	// Simple class C test
+	_, network, _ := net.ParseCIDR("192.168.0.1/24")
+	first, last := NetworkRange(network)
+	if !first.Equal(net.ParseIP("192.168.0.0")) {
+		t.Error(first.String())
+	}
+	if !last.Equal(net.ParseIP("192.168.0.255")) {
+		t.Error(last.String())
+	}
+
+	// Class A test
+	_, network, _ = net.ParseCIDR("10.0.0.1/8")
+	first, last = NetworkRange(network)
+	if !first.Equal(net.ParseIP("10.0.0.0")) {
+		t.Error(first.String())
+	}
+	if !last.Equal(net.ParseIP("10.255.255.255")) {
+		t.Error(last.String())
+	}
+
+	// Class A, random IP address
+	_, network, _ = net.ParseCIDR("10.1.2.3/8")
+	first, last = NetworkRange(network)
+	if !first.Equal(net.ParseIP("10.0.0.0")) {
+		t.Error(first.String())
+	}
+	if !last.Equal(net.ParseIP("10.255.255.255")) {
+		t.Error(last.String())
+	}
+
+	// 32bit mask
+	_, network, _ = net.ParseCIDR("10.1.2.3/32")
+	first, last = NetworkRange(network)
+	if !first.Equal(net.ParseIP("10.1.2.3")) {
+		t.Error(first.String())
+	}
+	if !last.Equal(net.ParseIP("10.1.2.3")) {
+		t.Error(last.String())
+	}
+
+	// 31bit mask
+	_, network, _ = net.ParseCIDR("10.1.2.3/31")
+	first, last = NetworkRange(network)
+	if !first.Equal(net.ParseIP("10.1.2.2")) {
+		t.Error(first.String())
+	}
+	if !last.Equal(net.ParseIP("10.1.2.3")) {
+		t.Error(last.String())
+	}
+
+	// 26bit mask
+	_, network, _ = net.ParseCIDR("10.1.2.3/26")
+	first, last = NetworkRange(network)
+	if !first.Equal(net.ParseIP("10.1.2.0")) {
+		t.Error(first.String())
+	}
+	if !last.Equal(net.ParseIP("10.1.2.63")) {
+		t.Error(last.String())
+	}
+}

+ 153 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/portallocator/portallocator.go

@@ -0,0 +1,153 @@
+package portallocator
+
+import (
+	"errors"
+	"fmt"
+	"net"
+	"sync"
+)
+
+type portMap struct {
+	p    map[int]struct{}
+	last int
+}
+
+func newPortMap() *portMap {
+	return &portMap{
+		p:    map[int]struct{}{},
+		last: EndPortRange,
+	}
+}
+
+type protoMap map[string]*portMap
+
+func newProtoMap() protoMap {
+	return protoMap{
+		"tcp": newPortMap(),
+		"udp": newPortMap(),
+	}
+}
+
+type ipMapping map[string]protoMap
+
+const (
+	BeginPortRange = 49153
+	EndPortRange   = 65535
+)
+
+var (
+	ErrAllPortsAllocated = errors.New("all ports are allocated")
+	ErrUnknownProtocol   = errors.New("unknown protocol")
+)
+
+var (
+	mutex sync.Mutex
+
+	defaultIP = net.ParseIP("0.0.0.0")
+	globalMap = ipMapping{}
+)
+
+type ErrPortAlreadyAllocated struct {
+	ip   string
+	port int
+}
+
+func NewErrPortAlreadyAllocated(ip string, port int) ErrPortAlreadyAllocated {
+	return ErrPortAlreadyAllocated{
+		ip:   ip,
+		port: port,
+	}
+}
+
+func (e ErrPortAlreadyAllocated) IP() string {
+	return e.ip
+}
+
+func (e ErrPortAlreadyAllocated) Port() int {
+	return e.port
+}
+
+func (e ErrPortAlreadyAllocated) IPPort() string {
+	return fmt.Sprintf("%s:%d", e.ip, e.port)
+}
+
+func (e ErrPortAlreadyAllocated) Error() string {
+	return fmt.Sprintf("Bind for %s:%d failed: port is already allocated", e.ip, e.port)
+}
+
+// RequestPort requests new port from global ports pool for specified ip and proto.
+// If port is 0 it returns first free port. Otherwise it cheks port availability
+// in pool and return that port or error if port is already busy.
+func RequestPort(ip net.IP, proto string, port int) (int, error) {
+	mutex.Lock()
+	defer mutex.Unlock()
+
+	if proto != "tcp" && proto != "udp" {
+		return 0, ErrUnknownProtocol
+	}
+
+	if ip == nil {
+		ip = defaultIP
+	}
+	ipstr := ip.String()
+	protomap, ok := globalMap[ipstr]
+	if !ok {
+		protomap = newProtoMap()
+		globalMap[ipstr] = protomap
+	}
+	mapping := protomap[proto]
+	if port > 0 {
+		if _, ok := mapping.p[port]; !ok {
+			mapping.p[port] = struct{}{}
+			return port, nil
+		}
+		return 0, NewErrPortAlreadyAllocated(ipstr, port)
+	}
+
+	port, err := mapping.findPort()
+	if err != nil {
+		return 0, err
+	}
+	return port, nil
+}
+
+// ReleasePort releases port from global ports pool for specified ip and proto.
+func ReleasePort(ip net.IP, proto string, port int) error {
+	mutex.Lock()
+	defer mutex.Unlock()
+
+	if ip == nil {
+		ip = defaultIP
+	}
+	protomap, ok := globalMap[ip.String()]
+	if !ok {
+		return nil
+	}
+	delete(protomap[proto].p, port)
+	return nil
+}
+
+// ReleaseAll releases all ports for all ips.
+func ReleaseAll() error {
+	mutex.Lock()
+	globalMap = ipMapping{}
+	mutex.Unlock()
+	return nil
+}
+
+func (pm *portMap) findPort() (int, error) {
+	port := pm.last
+	for i := 0; i <= EndPortRange-BeginPortRange; i++ {
+		port++
+		if port > EndPortRange {
+			port = BeginPortRange
+		}
+
+		if _, ok := pm.p[port]; !ok {
+			pm.p[port] = struct{}{}
+			pm.last = port
+			return port, nil
+		}
+	}
+	return 0, ErrAllPortsAllocated
+}

+ 245 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/portallocator/portallocator_test.go

@@ -0,0 +1,245 @@
+package portallocator
+
+import (
+	"net"
+	"testing"
+)
+
+func reset() {
+	ReleaseAll()
+}
+
+func TestRequestNewPort(t *testing.T) {
+	defer reset()
+
+	port, err := RequestPort(defaultIP, "tcp", 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if expected := BeginPortRange; port != expected {
+		t.Fatalf("Expected port %d got %d", expected, port)
+	}
+}
+
+func TestRequestSpecificPort(t *testing.T) {
+	defer reset()
+
+	port, err := RequestPort(defaultIP, "tcp", 5000)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if port != 5000 {
+		t.Fatalf("Expected port 5000 got %d", port)
+	}
+}
+
+func TestReleasePort(t *testing.T) {
+	defer reset()
+
+	port, err := RequestPort(defaultIP, "tcp", 5000)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if port != 5000 {
+		t.Fatalf("Expected port 5000 got %d", port)
+	}
+
+	if err := ReleasePort(defaultIP, "tcp", 5000); err != nil {
+		t.Fatal(err)
+	}
+}
+
+func TestReuseReleasedPort(t *testing.T) {
+	defer reset()
+
+	port, err := RequestPort(defaultIP, "tcp", 5000)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if port != 5000 {
+		t.Fatalf("Expected port 5000 got %d", port)
+	}
+
+	if err := ReleasePort(defaultIP, "tcp", 5000); err != nil {
+		t.Fatal(err)
+	}
+
+	port, err = RequestPort(defaultIP, "tcp", 5000)
+	if err != nil {
+		t.Fatal(err)
+	}
+}
+
+func TestReleaseUnreadledPort(t *testing.T) {
+	defer reset()
+
+	port, err := RequestPort(defaultIP, "tcp", 5000)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if port != 5000 {
+		t.Fatalf("Expected port 5000 got %d", port)
+	}
+
+	port, err = RequestPort(defaultIP, "tcp", 5000)
+
+	switch err.(type) {
+	case ErrPortAlreadyAllocated:
+	default:
+		t.Fatalf("Expected port allocation error got %s", err)
+	}
+}
+
+func TestUnknowProtocol(t *testing.T) {
+	defer reset()
+
+	if _, err := RequestPort(defaultIP, "tcpp", 0); err != ErrUnknownProtocol {
+		t.Fatalf("Expected error %s got %s", ErrUnknownProtocol, err)
+	}
+}
+
+func TestAllocateAllPorts(t *testing.T) {
+	defer reset()
+
+	for i := 0; i <= EndPortRange-BeginPortRange; i++ {
+		port, err := RequestPort(defaultIP, "tcp", 0)
+		if err != nil {
+			t.Fatal(err)
+		}
+
+		if expected := BeginPortRange + i; port != expected {
+			t.Fatalf("Expected port %d got %d", expected, port)
+		}
+	}
+
+	if _, err := RequestPort(defaultIP, "tcp", 0); err != ErrAllPortsAllocated {
+		t.Fatalf("Expected error %s got %s", ErrAllPortsAllocated, err)
+	}
+
+	_, err := RequestPort(defaultIP, "udp", 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// release a port in the middle and ensure we get another tcp port
+	port := BeginPortRange + 5
+	if err := ReleasePort(defaultIP, "tcp", port); err != nil {
+		t.Fatal(err)
+	}
+	newPort, err := RequestPort(defaultIP, "tcp", 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if newPort != port {
+		t.Fatalf("Expected port %d got %d", port, newPort)
+	}
+
+	// now pm.last == newPort, release it so that it's the only free port of
+	// the range, and ensure we get it back
+	if err := ReleasePort(defaultIP, "tcp", newPort); err != nil {
+		t.Fatal(err)
+	}
+	port, err = RequestPort(defaultIP, "tcp", 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if newPort != port {
+		t.Fatalf("Expected port %d got %d", newPort, port)
+	}
+}
+
+func BenchmarkAllocatePorts(b *testing.B) {
+	defer reset()
+
+	for i := 0; i < b.N; i++ {
+		for i := 0; i <= EndPortRange-BeginPortRange; i++ {
+			port, err := RequestPort(defaultIP, "tcp", 0)
+			if err != nil {
+				b.Fatal(err)
+			}
+
+			if expected := BeginPortRange + i; port != expected {
+				b.Fatalf("Expected port %d got %d", expected, port)
+			}
+		}
+		reset()
+	}
+}
+
+func TestPortAllocation(t *testing.T) {
+	defer reset()
+
+	ip := net.ParseIP("192.168.0.1")
+	ip2 := net.ParseIP("192.168.0.2")
+	if port, err := RequestPort(ip, "tcp", 80); err != nil {
+		t.Fatal(err)
+	} else if port != 80 {
+		t.Fatalf("Acquire(80) should return 80, not %d", port)
+	}
+	port, err := RequestPort(ip, "tcp", 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if port <= 0 {
+		t.Fatalf("Acquire(0) should return a non-zero port")
+	}
+
+	if _, err := RequestPort(ip, "tcp", port); err == nil {
+		t.Fatalf("Acquiring a port already in use should return an error")
+	}
+
+	if newPort, err := RequestPort(ip, "tcp", 0); err != nil {
+		t.Fatal(err)
+	} else if newPort == port {
+		t.Fatalf("Acquire(0) allocated the same port twice: %d", port)
+	}
+
+	if _, err := RequestPort(ip, "tcp", 80); err == nil {
+		t.Fatalf("Acquiring a port already in use should return an error")
+	}
+	if _, err := RequestPort(ip2, "tcp", 80); err != nil {
+		t.Fatalf("It should be possible to allocate the same port on a different interface")
+	}
+	if _, err := RequestPort(ip2, "tcp", 80); err == nil {
+		t.Fatalf("Acquiring a port already in use should return an error")
+	}
+	if err := ReleasePort(ip, "tcp", 80); err != nil {
+		t.Fatal(err)
+	}
+	if _, err := RequestPort(ip, "tcp", 80); err != nil {
+		t.Fatal(err)
+	}
+
+	port, err = RequestPort(ip, "tcp", 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+	port2, err := RequestPort(ip, "tcp", port+1)
+	if err != nil {
+		t.Fatal(err)
+	}
+	port3, err := RequestPort(ip, "tcp", 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if port3 == port2 {
+		t.Fatal("Requesting a dynamic port should never allocate a used port")
+	}
+}
+
+func TestNoDuplicateBPR(t *testing.T) {
+	defer reset()
+
+	if port, err := RequestPort(defaultIP, "tcp", BeginPortRange); err != nil {
+		t.Fatal(err)
+	} else if port != BeginPortRange {
+		t.Fatalf("Expected port %d got %d", BeginPortRange, port)
+	}
+
+	if port, err := RequestPort(defaultIP, "tcp", 0); err != nil {
+		t.Fatal(err)
+	} else if port == BeginPortRange {
+		t.Fatalf("Acquire(0) allocated the same port twice: %d", port)
+	}
+}

+ 176 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/portmapper/mapper.go

@@ -0,0 +1,176 @@
+package portmapper
+
+import (
+	"errors"
+	"fmt"
+	"net"
+	"sync"
+
+	log "github.com/Sirupsen/logrus"
+	"github.com/docker/docker/daemon/networkdriver/portallocator"
+	"github.com/docker/docker/pkg/iptables"
+)
+
+type mapping struct {
+	proto         string
+	userlandProxy UserlandProxy
+	host          net.Addr
+	container     net.Addr
+}
+
+var (
+	chain *iptables.Chain
+	lock  sync.Mutex
+
+	// udp:ip:port
+	currentMappings = make(map[string]*mapping)
+
+	NewProxy = NewProxyCommand
+)
+
+var (
+	ErrUnknownBackendAddressType = errors.New("unknown container address type not supported")
+	ErrPortMappedForIP           = errors.New("port is already mapped to ip")
+	ErrPortNotMapped             = errors.New("port is not mapped")
+)
+
+func SetIptablesChain(c *iptables.Chain) {
+	chain = c
+}
+
+func Map(container net.Addr, hostIP net.IP, hostPort int) (host net.Addr, err error) {
+	lock.Lock()
+	defer lock.Unlock()
+
+	var (
+		m                 *mapping
+		proto             string
+		allocatedHostPort int
+		proxy             UserlandProxy
+	)
+
+	switch container.(type) {
+	case *net.TCPAddr:
+		proto = "tcp"
+		if allocatedHostPort, err = portallocator.RequestPort(hostIP, proto, hostPort); err != nil {
+			return nil, err
+		}
+
+		m = &mapping{
+			proto:     proto,
+			host:      &net.TCPAddr{IP: hostIP, Port: allocatedHostPort},
+			container: container,
+		}
+
+		proxy = NewProxy(proto, hostIP, allocatedHostPort, container.(*net.TCPAddr).IP, container.(*net.TCPAddr).Port)
+	case *net.UDPAddr:
+		proto = "udp"
+		if allocatedHostPort, err = portallocator.RequestPort(hostIP, proto, hostPort); err != nil {
+			return nil, err
+		}
+
+		m = &mapping{
+			proto:     proto,
+			host:      &net.UDPAddr{IP: hostIP, Port: allocatedHostPort},
+			container: container,
+		}
+
+		proxy = NewProxy(proto, hostIP, allocatedHostPort, container.(*net.UDPAddr).IP, container.(*net.UDPAddr).Port)
+	default:
+		return nil, ErrUnknownBackendAddressType
+	}
+
+	// release the allocated port on any further error during return.
+	defer func() {
+		if err != nil {
+			portallocator.ReleasePort(hostIP, proto, allocatedHostPort)
+		}
+	}()
+
+	key := getKey(m.host)
+	if _, exists := currentMappings[key]; exists {
+		return nil, ErrPortMappedForIP
+	}
+
+	containerIP, containerPort := getIPAndPort(m.container)
+	if err := forward(iptables.Append, m.proto, hostIP, allocatedHostPort, containerIP.String(), containerPort); err != nil {
+		return nil, err
+	}
+
+	cleanup := func() error {
+		// need to undo the iptables rules before we return
+		proxy.Stop()
+		forward(iptables.Delete, m.proto, hostIP, allocatedHostPort, containerIP.String(), containerPort)
+		if err := portallocator.ReleasePort(hostIP, m.proto, allocatedHostPort); err != nil {
+			return err
+		}
+
+		return nil
+	}
+
+	if err := proxy.Start(); err != nil {
+		if err := cleanup(); err != nil {
+			return nil, fmt.Errorf("Error during port allocation cleanup: %v", err)
+		}
+		return nil, err
+	}
+	m.userlandProxy = proxy
+	currentMappings[key] = m
+	return m.host, nil
+}
+
+func Unmap(host net.Addr) error {
+	lock.Lock()
+	defer lock.Unlock()
+
+	key := getKey(host)
+	data, exists := currentMappings[key]
+	if !exists {
+		return ErrPortNotMapped
+	}
+
+	data.userlandProxy.Stop()
+
+	delete(currentMappings, key)
+
+	containerIP, containerPort := getIPAndPort(data.container)
+	hostIP, hostPort := getIPAndPort(data.host)
+	if err := forward(iptables.Delete, data.proto, hostIP, hostPort, containerIP.String(), containerPort); err != nil {
+		log.Errorf("Error on iptables delete: %s", err)
+	}
+
+	switch a := host.(type) {
+	case *net.TCPAddr:
+		return portallocator.ReleasePort(a.IP, "tcp", a.Port)
+	case *net.UDPAddr:
+		return portallocator.ReleasePort(a.IP, "udp", a.Port)
+	}
+	return nil
+}
+
+func getKey(a net.Addr) string {
+	switch t := a.(type) {
+	case *net.TCPAddr:
+		return fmt.Sprintf("%s:%d/%s", t.IP.String(), t.Port, "tcp")
+	case *net.UDPAddr:
+		return fmt.Sprintf("%s:%d/%s", t.IP.String(), t.Port, "udp")
+	}
+	return ""
+}
+
+func getIPAndPort(a net.Addr) (net.IP, int) {
+	switch t := a.(type) {
+	case *net.TCPAddr:
+		return t.IP, t.Port
+	case *net.UDPAddr:
+		return t.IP, t.Port
+	}
+	return nil, 0
+}
+
+func forward(action iptables.Action, proto string, sourceIP net.IP, sourcePort int, containerIP string, containerPort int) error {
+	if chain == nil {
+		return nil
+	}
+	return chain.Forward(action, sourceIP, sourcePort, proto, containerIP, containerPort)
+}

+ 152 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/portmapper/mapper_test.go

@@ -0,0 +1,152 @@
+package portmapper
+
+import (
+	"net"
+	"testing"
+
+	"github.com/docker/docker/daemon/networkdriver/portallocator"
+	"github.com/docker/docker/pkg/iptables"
+)
+
+func init() {
+	// override this func to mock out the proxy server
+	NewProxy = NewMockProxyCommand
+}
+
+func reset() {
+	chain = nil
+	currentMappings = make(map[string]*mapping)
+}
+
+func TestSetIptablesChain(t *testing.T) {
+	defer reset()
+
+	c := &iptables.Chain{
+		Name:   "TEST",
+		Bridge: "192.168.1.1",
+	}
+
+	if chain != nil {
+		t.Fatal("chain should be nil at init")
+	}
+
+	SetIptablesChain(c)
+	if chain == nil {
+		t.Fatal("chain should not be nil after set")
+	}
+}
+
+func TestMapPorts(t *testing.T) {
+	dstIp1 := net.ParseIP("192.168.0.1")
+	dstIp2 := net.ParseIP("192.168.0.2")
+	dstAddr1 := &net.TCPAddr{IP: dstIp1, Port: 80}
+	dstAddr2 := &net.TCPAddr{IP: dstIp2, Port: 80}
+
+	srcAddr1 := &net.TCPAddr{Port: 1080, IP: net.ParseIP("172.16.0.1")}
+	srcAddr2 := &net.TCPAddr{Port: 1080, IP: net.ParseIP("172.16.0.2")}
+
+	addrEqual := func(addr1, addr2 net.Addr) bool {
+		return (addr1.Network() == addr2.Network()) && (addr1.String() == addr2.String())
+	}
+
+	if host, err := Map(srcAddr1, dstIp1, 80); err != nil {
+		t.Fatalf("Failed to allocate port: %s", err)
+	} else if !addrEqual(dstAddr1, host) {
+		t.Fatalf("Incorrect mapping result: expected %s:%s, got %s:%s",
+			dstAddr1.String(), dstAddr1.Network(), host.String(), host.Network())
+	}
+
+	if _, err := Map(srcAddr1, dstIp1, 80); err == nil {
+		t.Fatalf("Port is in use - mapping should have failed")
+	}
+
+	if _, err := Map(srcAddr2, dstIp1, 80); err == nil {
+		t.Fatalf("Port is in use - mapping should have failed")
+	}
+
+	if _, err := Map(srcAddr2, dstIp2, 80); err != nil {
+		t.Fatalf("Failed to allocate port: %s", err)
+	}
+
+	if Unmap(dstAddr1) != nil {
+		t.Fatalf("Failed to release port")
+	}
+
+	if Unmap(dstAddr2) != nil {
+		t.Fatalf("Failed to release port")
+	}
+
+	if Unmap(dstAddr2) == nil {
+		t.Fatalf("Port already released, but no error reported")
+	}
+}
+
+func TestGetUDPKey(t *testing.T) {
+	addr := &net.UDPAddr{IP: net.ParseIP("192.168.1.5"), Port: 53}
+
+	key := getKey(addr)
+
+	if expected := "192.168.1.5:53/udp"; key != expected {
+		t.Fatalf("expected key %s got %s", expected, key)
+	}
+}
+
+func TestGetTCPKey(t *testing.T) {
+	addr := &net.TCPAddr{IP: net.ParseIP("192.168.1.5"), Port: 80}
+
+	key := getKey(addr)
+
+	if expected := "192.168.1.5:80/tcp"; key != expected {
+		t.Fatalf("expected key %s got %s", expected, key)
+	}
+}
+
+func TestGetUDPIPAndPort(t *testing.T) {
+	addr := &net.UDPAddr{IP: net.ParseIP("192.168.1.5"), Port: 53}
+
+	ip, port := getIPAndPort(addr)
+	if expected := "192.168.1.5"; ip.String() != expected {
+		t.Fatalf("expected ip %s got %s", expected, ip)
+	}
+
+	if ep := 53; port != ep {
+		t.Fatalf("expected port %d got %d", ep, port)
+	}
+}
+
+func TestMapAllPortsSingleInterface(t *testing.T) {
+	dstIp1 := net.ParseIP("0.0.0.0")
+	srcAddr1 := &net.TCPAddr{Port: 1080, IP: net.ParseIP("172.16.0.1")}
+
+	hosts := []net.Addr{}
+	var host net.Addr
+	var err error
+
+	defer func() {
+		for _, val := range hosts {
+			Unmap(val)
+		}
+	}()
+
+	for i := 0; i < 10; i++ {
+		for i := portallocator.BeginPortRange; i < portallocator.EndPortRange; i++ {
+			if host, err = Map(srcAddr1, dstIp1, 0); err != nil {
+				t.Fatal(err)
+			}
+
+			hosts = append(hosts, host)
+		}
+
+		if _, err := Map(srcAddr1, dstIp1, portallocator.BeginPortRange); err == nil {
+			t.Fatalf("Port %d should be bound but is not", portallocator.BeginPortRange)
+		}
+
+		for _, val := range hosts {
+			if err := Unmap(val); err != nil {
+				t.Fatal(err)
+			}
+		}
+
+		hosts = []net.Addr{}
+	}
+}

+ 18 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/portmapper/mock_proxy.go

@@ -0,0 +1,18 @@
+package portmapper
+
+import "net"
+
+func NewMockProxyCommand(proto string, hostIP net.IP, hostPort int, containerIP net.IP, containerPort int) UserlandProxy {
+	return &mockProxyCommand{}
+}
+
+type mockProxyCommand struct {
+}
+
+func (p *mockProxyCommand) Start() error {
+	return nil
+}
+
+func (p *mockProxyCommand) Stop() error {
+	return nil
+}

+ 161 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/portmapper/proxy.go

@@ -0,0 +1,161 @@
+package portmapper
+
+import (
+	"flag"
+	"fmt"
+	"io/ioutil"
+	"log"
+	"net"
+	"os"
+	"os/exec"
+	"os/signal"
+	"strconv"
+	"syscall"
+	"time"
+
+	"github.com/docker/docker/pkg/proxy"
+	"github.com/docker/docker/pkg/reexec"
+)
+
+const userlandProxyCommandName = "docker-proxy"
+
+func init() {
+	reexec.Register(userlandProxyCommandName, execProxy)
+}
+
+type UserlandProxy interface {
+	Start() error
+	Stop() error
+}
+
+// proxyCommand wraps an exec.Cmd to run the userland TCP and UDP
+// proxies as separate processes.
+type proxyCommand struct {
+	cmd *exec.Cmd
+}
+
+// execProxy is the reexec function that is registered to start the userland proxies
+func execProxy() {
+	f := os.NewFile(3, "signal-parent")
+	host, container := parseHostContainerAddrs()
+
+	p, err := proxy.NewProxy(host, container)
+	if err != nil {
+		fmt.Fprintf(f, "1\n%s", err)
+		f.Close()
+		os.Exit(1)
+	}
+	go handleStopSignals(p)
+	fmt.Fprint(f, "0\n")
+	f.Close()
+
+	// Run will block until the proxy stops
+	p.Run()
+}
+
+// parseHostContainerAddrs parses the flags passed on reexec to create the TCP or UDP
+// net.Addrs to map the host and container ports
+func parseHostContainerAddrs() (host net.Addr, container net.Addr) {
+	var (
+		proto         = flag.String("proto", "tcp", "proxy protocol")
+		hostIP        = flag.String("host-ip", "", "host ip")
+		hostPort      = flag.Int("host-port", -1, "host port")
+		containerIP   = flag.String("container-ip", "", "container ip")
+		containerPort = flag.Int("container-port", -1, "container port")
+	)
+
+	flag.Parse()
+
+	switch *proto {
+	case "tcp":
+		host = &net.TCPAddr{IP: net.ParseIP(*hostIP), Port: *hostPort}
+		container = &net.TCPAddr{IP: net.ParseIP(*containerIP), Port: *containerPort}
+	case "udp":
+		host = &net.UDPAddr{IP: net.ParseIP(*hostIP), Port: *hostPort}
+		container = &net.UDPAddr{IP: net.ParseIP(*containerIP), Port: *containerPort}
+	default:
+		log.Fatalf("unsupported protocol %s", *proto)
+	}
+
+	return host, container
+}
+
+func handleStopSignals(p proxy.Proxy) {
+	s := make(chan os.Signal, 10)
+	signal.Notify(s, os.Interrupt, syscall.SIGTERM, syscall.SIGSTOP)
+
+	for _ = range s {
+		p.Close()
+
+		os.Exit(0)
+	}
+}
+
+func NewProxyCommand(proto string, hostIP net.IP, hostPort int, containerIP net.IP, containerPort int) UserlandProxy {
+	args := []string{
+		userlandProxyCommandName,
+		"-proto", proto,
+		"-host-ip", hostIP.String(),
+		"-host-port", strconv.Itoa(hostPort),
+		"-container-ip", containerIP.String(),
+		"-container-port", strconv.Itoa(containerPort),
+	}
+
+	return &proxyCommand{
+		cmd: &exec.Cmd{
+			Path: reexec.Self(),
+			Args: args,
+			SysProcAttr: &syscall.SysProcAttr{
+				Pdeathsig: syscall.SIGTERM, // send a sigterm to the proxy if the daemon process dies
+			},
+		},
+	}
+}
+
+func (p *proxyCommand) Start() error {
+	r, w, err := os.Pipe()
+	if err != nil {
+		return fmt.Errorf("proxy unable to open os.Pipe %s", err)
+	}
+	defer r.Close()
+	p.cmd.ExtraFiles = []*os.File{w}
+	if err := p.cmd.Start(); err != nil {
+		return err
+	}
+	w.Close()
+
+	errchan := make(chan error, 1)
+	go func() {
+		buf := make([]byte, 2)
+		r.Read(buf)
+
+		if string(buf) != "0\n" {
+			errStr, err := ioutil.ReadAll(r)
+			if err != nil {
+				errchan <- fmt.Errorf("Error reading exit status from userland proxy: %v", err)
+				return
+			}
+
+			errchan <- fmt.Errorf("Error starting userland proxy: %s", errStr)
+			return
+		}
+		errchan <- nil
+	}()
+
+	select {
+	case err := <-errchan:
+		return err
+	case <-time.After(16 * time.Second):
+		return fmt.Errorf("Timed out proxy starting the userland proxy")
+	}
+}
+
+func (p *proxyCommand) Stop() error {
+	if p.cmd.Process != nil {
+		if err := p.cmd.Process.Signal(os.Interrupt); err != nil {
+			return err
+		}
+		return p.cmd.Wait()
+	}
+	return nil
+}

+ 118 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/daemon/networkdriver/utils.go

@@ -0,0 +1,118 @@
+package networkdriver
+
+import (
+	"errors"
+	"fmt"
+	"net"
+
+	"github.com/docker/libcontainer/netlink"
+)
+
+var (
+	networkGetRoutesFct = netlink.NetworkGetRoutes
+	ErrNoDefaultRoute   = errors.New("no default route")
+)
+
+func CheckNameserverOverlaps(nameservers []string, toCheck *net.IPNet) error {
+	if len(nameservers) > 0 {
+		for _, ns := range nameservers {
+			_, nsNetwork, err := net.ParseCIDR(ns)
+			if err != nil {
+				return err
+			}
+			if NetworkOverlaps(toCheck, nsNetwork) {
+				return ErrNetworkOverlapsWithNameservers
+			}
+		}
+	}
+	return nil
+}
+
+func CheckRouteOverlaps(toCheck *net.IPNet) error {
+	networks, err := networkGetRoutesFct()
+	if err != nil {
+		return err
+	}
+
+	for _, network := range networks {
+		if network.IPNet != nil && NetworkOverlaps(toCheck, network.IPNet) {
+			return ErrNetworkOverlaps
+		}
+	}
+	return nil
+}
+
+// Detects overlap between one IPNet and another
+func NetworkOverlaps(netX *net.IPNet, netY *net.IPNet) bool {
+	if len(netX.IP) == len(netY.IP) {
+		if firstIP, _ := NetworkRange(netX); netY.Contains(firstIP) {
+			return true
+		}
+		if firstIP, _ := NetworkRange(netY); netX.Contains(firstIP) {
+			return true
+		}
+	}
+	return false
+}
+
+// Calculates the first and last IP addresses in an IPNet
+func NetworkRange(network *net.IPNet) (net.IP, net.IP) {
+	var netIP net.IP
+	if network.IP.To4() != nil {
+		netIP = network.IP.To4()
+	} else if network.IP.To16() != nil {
+		netIP = network.IP.To16()
+	} else {
+		return nil, nil
+	}
+
+	lastIP := make([]byte, len(netIP), len(netIP))
+
+	for i := 0; i < len(netIP); i++ {
+		lastIP[i] = netIP[i] | ^network.Mask[i]
+	}
+	return netIP.Mask(network.Mask), net.IP(lastIP)
+}
+
+// Return the first IPv4 address and slice of IPv6 addresses for the specified network interface
+func GetIfaceAddr(name string) (net.Addr, []net.Addr, error) {
+	iface, err := net.InterfaceByName(name)
+	if err != nil {
+		return nil, nil, err
+	}
+	addrs, err := iface.Addrs()
+	if err != nil {
+		return nil, nil, err
+	}
+	var addrs4 []net.Addr
+	var addrs6 []net.Addr
+	for _, addr := range addrs {
+		ip := (addr.(*net.IPNet)).IP
+		if ip4 := ip.To4(); ip4 != nil {
+			addrs4 = append(addrs4, addr)
+		} else if ip6 := ip.To16(); len(ip6) == net.IPv6len {
+			addrs6 = append(addrs6, addr)
+		}
+	}
+	switch {
+	case len(addrs4) == 0:
+		return nil, nil, fmt.Errorf("Interface %v has no IPv4 addresses", name)
+	case len(addrs4) > 1:
+		fmt.Printf("Interface %v has more than 1 IPv4 address. Defaulting to using %v\n",
+			name, (addrs4[0].(*net.IPNet)).IP)
+	}
+	return addrs4[0], addrs6, nil
+}
+
+func GetDefaultRouteIface() (*net.Interface, error) {
+	rs, err := networkGetRoutesFct()
+	if err != nil {
+		return nil, fmt.Errorf("unable to get routes: %v", err)
+	}
+	for _, r := range rs {
+		if r.Default {
+			return r.Iface, nil
+		}
+	}
+	return nil, ErrNoDefaultRoute
+}

+ 93 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/parsers/kernel/kernel.go

@@ -0,0 +1,93 @@
+package kernel
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+)
+
+type KernelVersionInfo struct {
+	Kernel int
+	Major  int
+	Minor  int
+	Flavor string
+}
+
+func (k *KernelVersionInfo) String() string {
+	return fmt.Sprintf("%d.%d.%d%s", k.Kernel, k.Major, k.Minor, k.Flavor)
+}
+
+// Compare two KernelVersionInfo struct.
+// Returns -1 if a < b, 0 if a == b, 1 it a > b
+func CompareKernelVersion(a, b *KernelVersionInfo) int {
+	if a.Kernel < b.Kernel {
+		return -1
+	} else if a.Kernel > b.Kernel {
+		return 1
+	}
+
+	if a.Major < b.Major {
+		return -1
+	} else if a.Major > b.Major {
+		return 1
+	}
+
+	if a.Minor < b.Minor {
+		return -1
+	} else if a.Minor > b.Minor {
+		return 1
+	}
+
+	return 0
+}
+
+func GetKernelVersion() (*KernelVersionInfo, error) {
+	var (
+		err error
+	)
+
+	uts, err := uname()
+	if err != nil {
+		return nil, err
+	}
+
+	release := make([]byte, len(uts.Release))
+
+	i := 0
+	for _, c := range uts.Release {
+		release[i] = byte(c)
+		i++
+	}
+
+	// Remove the \x00 from the release for Atoi to parse correctly
+	release = release[:bytes.IndexByte(release, 0)]
+
+	return ParseRelease(string(release))
+}
+
+func ParseRelease(release string) (*KernelVersionInfo, error) {
+	var (
+		kernel, major, minor, parsed int
+		flavor, partial              string
+	)
+
+	// Ignore error from Sscanf to allow an empty flavor.  Instead, just
+	// make sure we got all the version numbers.
+	parsed, _ = fmt.Sscanf(release, "%d.%d%s", &kernel, &major, &partial)
+	if parsed < 2 {
+		return nil, errors.New("Can't parse kernel version " + release)
+	}
+
+	// sometimes we have 3.12.25-gentoo, but sometimes we just have 3.12-1-amd64
+	parsed, _ = fmt.Sscanf(partial, ".%d%s", &minor, &flavor)
+	if parsed < 1 {
+		flavor = partial
+	}
+
+	return &KernelVersionInfo{
+		Kernel: kernel,
+		Major:  major,
+		Minor:  minor,
+		Flavor: flavor,
+	}, nil
+}

+ 61 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/parsers/kernel/kernel_test.go

@@ -0,0 +1,61 @@
+package kernel
+
+import (
+	"testing"
+)
+
+func assertParseRelease(t *testing.T, release string, b *KernelVersionInfo, result int) {
+	var (
+		a *KernelVersionInfo
+	)
+	a, _ = ParseRelease(release)
+
+	if r := CompareKernelVersion(a, b); r != result {
+		t.Fatalf("Unexpected kernel version comparison result. Found %d, expected %d", r, result)
+	}
+	if a.Flavor != b.Flavor {
+		t.Fatalf("Unexpected parsed kernel flavor.  Found %s, expected %s", a.Flavor, b.Flavor)
+	}
+}
+
+func TestParseRelease(t *testing.T) {
+	assertParseRelease(t, "3.8.0", &KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0}, 0)
+	assertParseRelease(t, "3.4.54.longterm-1", &KernelVersionInfo{Kernel: 3, Major: 4, Minor: 54, Flavor: ".longterm-1"}, 0)
+	assertParseRelease(t, "3.4.54.longterm-1", &KernelVersionInfo{Kernel: 3, Major: 4, Minor: 54, Flavor: ".longterm-1"}, 0)
+	assertParseRelease(t, "3.8.0-19-generic", &KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0, Flavor: "-19-generic"}, 0)
+	assertParseRelease(t, "3.12.8tag", &KernelVersionInfo{Kernel: 3, Major: 12, Minor: 8, Flavor: "tag"}, 0)
+	assertParseRelease(t, "3.12-1-amd64", &KernelVersionInfo{Kernel: 3, Major: 12, Minor: 0, Flavor: "-1-amd64"}, 0)
+}
+
+func assertKernelVersion(t *testing.T, a, b *KernelVersionInfo, result int) {
+	if r := CompareKernelVersion(a, b); r != result {
+		t.Fatalf("Unexpected kernel version comparison result. Found %d, expected %d", r, result)
+	}
+}
+
+func TestCompareKernelVersion(t *testing.T) {
+	assertKernelVersion(t,
+		&KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0},
+		&KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0},
+		0)
+	assertKernelVersion(t,
+		&KernelVersionInfo{Kernel: 2, Major: 6, Minor: 0},
+		&KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0},
+		-1)
+	assertKernelVersion(t,
+		&KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0},
+		&KernelVersionInfo{Kernel: 2, Major: 6, Minor: 0},
+		1)
+	assertKernelVersion(t,
+		&KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0},
+		&KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0},
+		0)
+	assertKernelVersion(t,
+		&KernelVersionInfo{Kernel: 3, Major: 8, Minor: 5},
+		&KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0},
+		1)
+	assertKernelVersion(t,
+		&KernelVersionInfo{Kernel: 3, Major: 0, Minor: 20},
+		&KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0},
+		-1)
+}

+ 16 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/parsers/kernel/uname_linux.go

@@ -0,0 +1,16 @@
+package kernel
+
+import (
+	"syscall"
+)
+
+type Utsname syscall.Utsname
+
+func uname() (*syscall.Utsname, error) {
+	uts := &syscall.Utsname{}
+
+	if err := syscall.Uname(uts); err != nil {
+		return nil, err
+	}
+	return uts, nil
+}

+ 15 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/parsers/kernel/uname_unsupported.go

@@ -0,0 +1,15 @@
+// +build !linux
+
+package kernel
+
+import (
+	"errors"
+)
+
+type Utsname struct {
+	Release [65]byte
+}
+
+func uname() (*Utsname, error) {
+	return nil, errors.New("Kernel version detection is available only on linux")
+}

+ 1 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/reexec/MAINTAINERS

@@ -0,0 +1 @@
+Michael Crosby <michael@docker.com> (@crosbymichael)

+ 5 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/reexec/README.md

@@ -0,0 +1,5 @@
+## reexec
+
+The `reexec` package facilitates the busybox style reexec of the docker binary that we require because 
+of the forking limitations of using Go.  Handlers can be registered with a name and the argv 0 of 
+the exec of the binary will be used to find and execute custom init paths.

+ 18 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/reexec/command_linux.go

@@ -0,0 +1,18 @@
+// +build linux
+
+package reexec
+
+import (
+	"os/exec"
+	"syscall"
+)
+
+func Command(args ...string) *exec.Cmd {
+	return &exec.Cmd{
+		Path: Self(),
+		Args: args,
+		SysProcAttr: &syscall.SysProcAttr{
+			Pdeathsig: syscall.SIGTERM,
+		},
+	}
+}

+ 11 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/reexec/command_unsupported.go

@@ -0,0 +1,11 @@
+// +build !linux
+
+package reexec
+
+import (
+	"os/exec"
+)
+
+func Command(args ...string) *exec.Cmd {
+	return nil
+}

+ 42 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/reexec/reexec.go

@@ -0,0 +1,42 @@
+package reexec
+
+import (
+	"fmt"
+	"os"
+	"os/exec"
+	"path/filepath"
+)
+
+var registeredInitializers = make(map[string]func())
+
+// Register adds an initialization func under the specified name
+func Register(name string, initializer func()) {
+	if _, exists := registeredInitializers[name]; exists {
+		panic(fmt.Sprintf("reexec func already registred under name %q", name))
+	}
+
+	registeredInitializers[name] = initializer
+}
+
+// Init is called as the first part of the exec process and returns true if an
+// initialization function was called.
+func Init() bool {
+	initializer, exists := registeredInitializers[os.Args[0]]
+	if exists {
+		initializer()
+
+		return true
+	}
+	return false
+}
+
+// Self returns the path to the current processes binary
+func Self() string {
+	name := os.Args[0]
+	if filepath.Base(name) == name {
+		if lp, err := exec.LookPath(name); err == nil {
+			name = lp
+		}
+	}
+	return name
+}

+ 2 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/libcontainer/netlink/MAINTAINERS

@@ -0,0 +1,2 @@
+Michael Crosby <michael@crosbymichael.com> (@crosbymichael)
+Guillaume J. Charmes <guillaume@docker.com> (@creack)

+ 31 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/libcontainer/netlink/netlink.go

@@ -0,0 +1,31 @@
+// Packet netlink provide access to low level Netlink sockets and messages.
+//
+// Actual implementations are in:
+// netlink_linux.go
+// netlink_darwin.go
+package netlink
+
+import (
+	"errors"
+	"net"
+)
+
+var (
+	ErrWrongSockType   = errors.New("Wrong socket type")
+	ErrShortResponse   = errors.New("Got short response from netlink")
+	ErrInterfaceExists = errors.New("Network interface already exists")
+)
+
+// A Route is a subnet associated with the interface to reach it.
+type Route struct {
+	*net.IPNet
+	Iface   *net.Interface
+	Default bool
+}
+
+// An IfAddr defines IP network settings for a given network interface
+type IfAddr struct {
+	Iface *net.Interface
+	IP    net.IP
+	IPNet *net.IPNet
+}

+ 1307 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/libcontainer/netlink/netlink_linux.go

@@ -0,0 +1,1307 @@
+package netlink
+
+import (
+	"encoding/binary"
+	"fmt"
+	"io"
+	"math/rand"
+	"net"
+	"os"
+	"sync/atomic"
+	"syscall"
+	"unsafe"
+)
+
+const (
+	IFNAMSIZ          = 16
+	DEFAULT_CHANGE    = 0xFFFFFFFF
+	IFLA_INFO_KIND    = 1
+	IFLA_INFO_DATA    = 2
+	VETH_INFO_PEER    = 1
+	IFLA_MACVLAN_MODE = 1
+	IFLA_VLAN_ID      = 1
+	IFLA_NET_NS_FD    = 28
+	IFLA_ADDRESS      = 1
+	IFLA_BRPORT_MODE  = 4
+	SIOC_BRADDBR      = 0x89a0
+	SIOC_BRDELBR      = 0x89a1
+	SIOC_BRADDIF      = 0x89a2
+)
+
+const (
+	MACVLAN_MODE_PRIVATE = 1 << iota
+	MACVLAN_MODE_VEPA
+	MACVLAN_MODE_BRIDGE
+	MACVLAN_MODE_PASSTHRU
+)
+
+var nextSeqNr uint32
+
+type ifreqHwaddr struct {
+	IfrnName   [IFNAMSIZ]byte
+	IfruHwaddr syscall.RawSockaddr
+}
+
+type ifreqIndex struct {
+	IfrnName  [IFNAMSIZ]byte
+	IfruIndex int32
+}
+
+type ifreqFlags struct {
+	IfrnName  [IFNAMSIZ]byte
+	Ifruflags uint16
+}
+
+var native binary.ByteOrder
+
+func init() {
+	var x uint32 = 0x01020304
+	if *(*byte)(unsafe.Pointer(&x)) == 0x01 {
+		native = binary.BigEndian
+	} else {
+		native = binary.LittleEndian
+	}
+}
+
+func getIpFamily(ip net.IP) int {
+	if len(ip) <= net.IPv4len {
+		return syscall.AF_INET
+	}
+	if ip.To4() != nil {
+		return syscall.AF_INET
+	}
+	return syscall.AF_INET6
+}
+
+type NetlinkRequestData interface {
+	Len() int
+	ToWireFormat() []byte
+}
+
+type IfInfomsg struct {
+	syscall.IfInfomsg
+}
+
+func newIfInfomsg(family int) *IfInfomsg {
+	return &IfInfomsg{
+		IfInfomsg: syscall.IfInfomsg{
+			Family: uint8(family),
+		},
+	}
+}
+
+func newIfInfomsgChild(parent *RtAttr, family int) *IfInfomsg {
+	msg := newIfInfomsg(family)
+	parent.children = append(parent.children, msg)
+	return msg
+}
+
+func (msg *IfInfomsg) ToWireFormat() []byte {
+	length := syscall.SizeofIfInfomsg
+	b := make([]byte, length)
+	b[0] = msg.Family
+	b[1] = 0
+	native.PutUint16(b[2:4], msg.Type)
+	native.PutUint32(b[4:8], uint32(msg.Index))
+	native.PutUint32(b[8:12], msg.Flags)
+	native.PutUint32(b[12:16], msg.Change)
+	return b
+}
+
+func (msg *IfInfomsg) Len() int {
+	return syscall.SizeofIfInfomsg
+}
+
+type IfAddrmsg struct {
+	syscall.IfAddrmsg
+}
+
+func newIfAddrmsg(family int) *IfAddrmsg {
+	return &IfAddrmsg{
+		IfAddrmsg: syscall.IfAddrmsg{
+			Family: uint8(family),
+		},
+	}
+}
+
+func (msg *IfAddrmsg) ToWireFormat() []byte {
+	length := syscall.SizeofIfAddrmsg
+	b := make([]byte, length)
+	b[0] = msg.Family
+	b[1] = msg.Prefixlen
+	b[2] = msg.Flags
+	b[3] = msg.Scope
+	native.PutUint32(b[4:8], msg.Index)
+	return b
+}
+
+func (msg *IfAddrmsg) Len() int {
+	return syscall.SizeofIfAddrmsg
+}
+
+type RtMsg struct {
+	syscall.RtMsg
+}
+
+func newRtMsg() *RtMsg {
+	return &RtMsg{
+		RtMsg: syscall.RtMsg{
+			Table:    syscall.RT_TABLE_MAIN,
+			Scope:    syscall.RT_SCOPE_UNIVERSE,
+			Protocol: syscall.RTPROT_BOOT,
+			Type:     syscall.RTN_UNICAST,
+		},
+	}
+}
+
+func (msg *RtMsg) ToWireFormat() []byte {
+	length := syscall.SizeofRtMsg
+	b := make([]byte, length)
+	b[0] = msg.Family
+	b[1] = msg.Dst_len
+	b[2] = msg.Src_len
+	b[3] = msg.Tos
+	b[4] = msg.Table
+	b[5] = msg.Protocol
+	b[6] = msg.Scope
+	b[7] = msg.Type
+	native.PutUint32(b[8:12], msg.Flags)
+	return b
+}
+
+func (msg *RtMsg) Len() int {
+	return syscall.SizeofRtMsg
+}
+
+func rtaAlignOf(attrlen int) int {
+	return (attrlen + syscall.RTA_ALIGNTO - 1) & ^(syscall.RTA_ALIGNTO - 1)
+}
+
+type RtAttr struct {
+	syscall.RtAttr
+	Data     []byte
+	children []NetlinkRequestData
+}
+
+func newRtAttr(attrType int, data []byte) *RtAttr {
+	return &RtAttr{
+		RtAttr: syscall.RtAttr{
+			Type: uint16(attrType),
+		},
+		children: []NetlinkRequestData{},
+		Data:     data,
+	}
+}
+
+func newRtAttrChild(parent *RtAttr, attrType int, data []byte) *RtAttr {
+	attr := newRtAttr(attrType, data)
+	parent.children = append(parent.children, attr)
+	return attr
+}
+
+func (a *RtAttr) Len() int {
+	if len(a.children) == 0 {
+		return (syscall.SizeofRtAttr + len(a.Data))
+	}
+
+	l := 0
+	for _, child := range a.children {
+		l += child.Len()
+	}
+	l += syscall.SizeofRtAttr
+	return rtaAlignOf(l + len(a.Data))
+}
+
+func (a *RtAttr) ToWireFormat() []byte {
+	length := a.Len()
+	buf := make([]byte, rtaAlignOf(length))
+
+	if a.Data != nil {
+		copy(buf[4:], a.Data)
+	} else {
+		next := 4
+		for _, child := range a.children {
+			childBuf := child.ToWireFormat()
+			copy(buf[next:], childBuf)
+			next += rtaAlignOf(len(childBuf))
+		}
+	}
+
+	if l := uint16(length); l != 0 {
+		native.PutUint16(buf[0:2], l)
+	}
+	native.PutUint16(buf[2:4], a.Type)
+	return buf
+}
+
+func uint32Attr(t int, n uint32) *RtAttr {
+	buf := make([]byte, 4)
+	native.PutUint32(buf, n)
+	return newRtAttr(t, buf)
+}
+
+type NetlinkRequest struct {
+	syscall.NlMsghdr
+	Data []NetlinkRequestData
+}
+
+func (rr *NetlinkRequest) ToWireFormat() []byte {
+	length := rr.Len
+	dataBytes := make([][]byte, len(rr.Data))
+	for i, data := range rr.Data {
+		dataBytes[i] = data.ToWireFormat()
+		length += uint32(len(dataBytes[i]))
+	}
+	b := make([]byte, length)
+	native.PutUint32(b[0:4], length)
+	native.PutUint16(b[4:6], rr.Type)
+	native.PutUint16(b[6:8], rr.Flags)
+	native.PutUint32(b[8:12], rr.Seq)
+	native.PutUint32(b[12:16], rr.Pid)
+
+	next := 16
+	for _, data := range dataBytes {
+		copy(b[next:], data)
+		next += len(data)
+	}
+	return b
+}
+
+func (rr *NetlinkRequest) AddData(data NetlinkRequestData) {
+	if data != nil {
+		rr.Data = append(rr.Data, data)
+	}
+}
+
+func newNetlinkRequest(proto, flags int) *NetlinkRequest {
+	return &NetlinkRequest{
+		NlMsghdr: syscall.NlMsghdr{
+			Len:   uint32(syscall.NLMSG_HDRLEN),
+			Type:  uint16(proto),
+			Flags: syscall.NLM_F_REQUEST | uint16(flags),
+			Seq:   atomic.AddUint32(&nextSeqNr, 1),
+		},
+	}
+}
+
+type NetlinkSocket struct {
+	fd  int
+	lsa syscall.SockaddrNetlink
+}
+
+func getNetlinkSocket() (*NetlinkSocket, error) {
+	fd, err := syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_RAW, syscall.NETLINK_ROUTE)
+	if err != nil {
+		return nil, err
+	}
+	s := &NetlinkSocket{
+		fd: fd,
+	}
+	s.lsa.Family = syscall.AF_NETLINK
+	if err := syscall.Bind(fd, &s.lsa); err != nil {
+		syscall.Close(fd)
+		return nil, err
+	}
+
+	return s, nil
+}
+
+func (s *NetlinkSocket) Close() {
+	syscall.Close(s.fd)
+}
+
+func (s *NetlinkSocket) Send(request *NetlinkRequest) error {
+	if err := syscall.Sendto(s.fd, request.ToWireFormat(), 0, &s.lsa); err != nil {
+		return err
+	}
+	return nil
+}
+
+func (s *NetlinkSocket) Receive() ([]syscall.NetlinkMessage, error) {
+	rb := make([]byte, syscall.Getpagesize())
+	nr, _, err := syscall.Recvfrom(s.fd, rb, 0)
+	if err != nil {
+		return nil, err
+	}
+	if nr < syscall.NLMSG_HDRLEN {
+		return nil, ErrShortResponse
+	}
+	rb = rb[:nr]
+	return syscall.ParseNetlinkMessage(rb)
+}
+
+func (s *NetlinkSocket) GetPid() (uint32, error) {
+	lsa, err := syscall.Getsockname(s.fd)
+	if err != nil {
+		return 0, err
+	}
+	switch v := lsa.(type) {
+	case *syscall.SockaddrNetlink:
+		return v.Pid, nil
+	}
+	return 0, ErrWrongSockType
+}
+
+func (s *NetlinkSocket) CheckMessage(m syscall.NetlinkMessage, seq, pid uint32) error {
+	if m.Header.Seq != seq {
+		return fmt.Errorf("netlink: invalid seq %d, expected %d", m.Header.Seq, seq)
+	}
+	if m.Header.Pid != pid {
+		return fmt.Errorf("netlink: wrong pid %d, expected %d", m.Header.Pid, pid)
+	}
+	if m.Header.Type == syscall.NLMSG_DONE {
+		return io.EOF
+	}
+	if m.Header.Type == syscall.NLMSG_ERROR {
+		e := int32(native.Uint32(m.Data[0:4]))
+		if e == 0 {
+			return io.EOF
+		}
+		return syscall.Errno(-e)
+	}
+	return nil
+}
+
+func (s *NetlinkSocket) HandleAck(seq uint32) error {
+	pid, err := s.GetPid()
+	if err != nil {
+		return err
+	}
+
+outer:
+	for {
+		msgs, err := s.Receive()
+		if err != nil {
+			return err
+		}
+		for _, m := range msgs {
+			if err := s.CheckMessage(m, seq, pid); err != nil {
+				if err == io.EOF {
+					break outer
+				}
+				return err
+			}
+		}
+	}
+
+	return nil
+}
+
+func zeroTerminated(s string) []byte {
+	return []byte(s + "\000")
+}
+
+func nonZeroTerminated(s string) []byte {
+	return []byte(s)
+}
+
+// Add a new network link of a specified type.
+// This is identical to running: ip link add $name type $linkType
+func NetworkLinkAdd(name string, linkType string) error {
+	if name == "" || linkType == "" {
+		return fmt.Errorf("Neither link name nor link type can be empty!")
+	}
+
+	s, err := getNetlinkSocket()
+	if err != nil {
+		return err
+	}
+	defer s.Close()
+
+	wb := newNetlinkRequest(syscall.RTM_NEWLINK, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
+
+	msg := newIfInfomsg(syscall.AF_UNSPEC)
+	wb.AddData(msg)
+
+	linkInfo := newRtAttr(syscall.IFLA_LINKINFO, nil)
+	newRtAttrChild(linkInfo, IFLA_INFO_KIND, nonZeroTerminated(linkType))
+	wb.AddData(linkInfo)
+
+	nameData := newRtAttr(syscall.IFLA_IFNAME, zeroTerminated(name))
+	wb.AddData(nameData)
+
+	if err := s.Send(wb); err != nil {
+		return err
+	}
+
+	return s.HandleAck(wb.Seq)
+}
+
+// Delete a network link.
+// This is identical to running: ip link del $name
+func NetworkLinkDel(name string) error {
+	if name == "" {
+		return fmt.Errorf("Network link name can not be empty!")
+	}
+
+	s, err := getNetlinkSocket()
+	if err != nil {
+		return err
+	}
+	defer s.Close()
+
+	iface, err := net.InterfaceByName(name)
+	if err != nil {
+		return err
+	}
+
+	wb := newNetlinkRequest(syscall.RTM_DELLINK, syscall.NLM_F_ACK)
+
+	msg := newIfInfomsg(syscall.AF_UNSPEC)
+	msg.Index = int32(iface.Index)
+	wb.AddData(msg)
+
+	if err := s.Send(wb); err != nil {
+		return err
+	}
+
+	return s.HandleAck(wb.Seq)
+}
+
+// Bring up a particular network interface.
+// This is identical to running: ip link set dev $name up
+func NetworkLinkUp(iface *net.Interface) error {
+	s, err := getNetlinkSocket()
+	if err != nil {
+		return err
+	}
+	defer s.Close()
+
+	wb := newNetlinkRequest(syscall.RTM_NEWLINK, syscall.NLM_F_ACK)
+
+	msg := newIfInfomsg(syscall.AF_UNSPEC)
+	msg.Index = int32(iface.Index)
+	msg.Flags = syscall.IFF_UP
+	msg.Change = syscall.IFF_UP
+	wb.AddData(msg)
+
+	if err := s.Send(wb); err != nil {
+		return err
+	}
+
+	return s.HandleAck(wb.Seq)
+}
+
+// Bring down a particular network interface.
+// This is identical to running: ip link set $name down
+func NetworkLinkDown(iface *net.Interface) error {
+	s, err := getNetlinkSocket()
+	if err != nil {
+		return err
+	}
+	defer s.Close()
+
+	wb := newNetlinkRequest(syscall.RTM_NEWLINK, syscall.NLM_F_ACK)
+
+	msg := newIfInfomsg(syscall.AF_UNSPEC)
+	msg.Index = int32(iface.Index)
+	msg.Flags = 0 & ^syscall.IFF_UP
+	msg.Change = DEFAULT_CHANGE
+	wb.AddData(msg)
+
+	if err := s.Send(wb); err != nil {
+		return err
+	}
+
+	return s.HandleAck(wb.Seq)
+}
+
+// Set link layer address ie. MAC Address.
+// This is identical to running: ip link set dev $name address $macaddress
+func NetworkSetMacAddress(iface *net.Interface, macaddr string) error {
+	s, err := getNetlinkSocket()
+	if err != nil {
+		return err
+	}
+	defer s.Close()
+
+	hwaddr, err := net.ParseMAC(macaddr)
+	if err != nil {
+		return err
+	}
+
+	var (
+		MULTICAST byte = 0x1
+	)
+
+	if hwaddr[0]&0x1 == MULTICAST {
+		return fmt.Errorf("Multicast MAC Address is not supported: %s", macaddr)
+	}
+
+	wb := newNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
+
+	msg := newIfInfomsg(syscall.AF_UNSPEC)
+	msg.Index = int32(iface.Index)
+	msg.Change = DEFAULT_CHANGE
+	wb.AddData(msg)
+
+	macdata := make([]byte, 6)
+	copy(macdata, hwaddr)
+	data := newRtAttr(IFLA_ADDRESS, macdata)
+	wb.AddData(data)
+
+	if err := s.Send(wb); err != nil {
+		return err
+	}
+	return s.HandleAck(wb.Seq)
+}
+
+// Set link Maximum Transmission Unit
+// This is identical to running: ip link set dev $name mtu $MTU
+// bridge is a bitch here https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=292088
+// https://bugzilla.redhat.com/show_bug.cgi?id=697021
+// There is a discussion about how to deal with ifcs joining bridge with MTU > 1500
+// Regular network nterfaces do seem to work though!
+func NetworkSetMTU(iface *net.Interface, mtu int) error {
+	s, err := getNetlinkSocket()
+	if err != nil {
+		return err
+	}
+	defer s.Close()
+
+	wb := newNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
+
+	msg := newIfInfomsg(syscall.AF_UNSPEC)
+	msg.Type = syscall.RTM_SETLINK
+	msg.Flags = syscall.NLM_F_REQUEST
+	msg.Index = int32(iface.Index)
+	msg.Change = DEFAULT_CHANGE
+	wb.AddData(msg)
+	wb.AddData(uint32Attr(syscall.IFLA_MTU, uint32(mtu)))
+
+	if err := s.Send(wb); err != nil {
+		return err
+	}
+	return s.HandleAck(wb.Seq)
+}
+
+// Set link queue length
+// This is identical to running: ip link set dev $name txqueuelen $QLEN
+func NetworkSetTxQueueLen(iface *net.Interface, txQueueLen int) error {
+	s, err := getNetlinkSocket()
+	if err != nil {
+		return err
+	}
+	defer s.Close()
+
+	wb := newNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
+
+	msg := newIfInfomsg(syscall.AF_UNSPEC)
+	msg.Type = syscall.RTM_SETLINK
+	msg.Flags = syscall.NLM_F_REQUEST
+	msg.Index = int32(iface.Index)
+	msg.Change = DEFAULT_CHANGE
+	wb.AddData(msg)
+	wb.AddData(uint32Attr(syscall.IFLA_TXQLEN, uint32(txQueueLen)))
+
+	if err := s.Send(wb); err != nil {
+		return err
+	}
+	return s.HandleAck(wb.Seq)
+}
+
+func networkMasterAction(iface *net.Interface, rtattr *RtAttr) error {
+	s, err := getNetlinkSocket()
+	if err != nil {
+		return err
+	}
+	defer s.Close()
+
+	wb := newNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
+
+	msg := newIfInfomsg(syscall.AF_UNSPEC)
+	msg.Type = syscall.RTM_SETLINK
+	msg.Flags = syscall.NLM_F_REQUEST
+	msg.Index = int32(iface.Index)
+	msg.Change = DEFAULT_CHANGE
+	wb.AddData(msg)
+	wb.AddData(rtattr)
+
+	if err := s.Send(wb); err != nil {
+		return err
+	}
+
+	return s.HandleAck(wb.Seq)
+}
+
+// Add an interface to bridge.
+// This is identical to running: ip link set $name master $master
+func NetworkSetMaster(iface, master *net.Interface) error {
+	data := uint32Attr(syscall.IFLA_MASTER, uint32(master.Index))
+	return networkMasterAction(iface, data)
+}
+
+// Remove an interface from the bridge
+// This is is identical to to running: ip link $name set nomaster
+func NetworkSetNoMaster(iface *net.Interface) error {
+	data := uint32Attr(syscall.IFLA_MASTER, 0)
+	return networkMasterAction(iface, data)
+}
+
+func networkSetNsAction(iface *net.Interface, rtattr *RtAttr) error {
+	s, err := getNetlinkSocket()
+	if err != nil {
+		return err
+	}
+	defer s.Close()
+
+	wb := newNetlinkRequest(syscall.RTM_NEWLINK, syscall.NLM_F_ACK)
+	msg := newIfInfomsg(syscall.AF_UNSPEC)
+	msg.Index = int32(iface.Index)
+	wb.AddData(msg)
+	wb.AddData(rtattr)
+
+	if err := s.Send(wb); err != nil {
+		return err
+	}
+
+	return s.HandleAck(wb.Seq)
+}
+
+// Move a particular network interface to a particular network namespace
+// specified by PID. This is idential to running: ip link set dev $name netns $pid
+func NetworkSetNsPid(iface *net.Interface, nspid int) error {
+	data := uint32Attr(syscall.IFLA_NET_NS_PID, uint32(nspid))
+	return networkSetNsAction(iface, data)
+}
+
+// Move a particular network interface to a particular mounted
+// network namespace specified by file descriptor.
+// This is idential to running: ip link set dev $name netns $fd
+func NetworkSetNsFd(iface *net.Interface, fd int) error {
+	data := uint32Attr(IFLA_NET_NS_FD, uint32(fd))
+	return networkSetNsAction(iface, data)
+}
+
+// Rname a particular interface to a different name
+// !!! Note that you can't rename an active interface. You need to bring it down before renaming it.
+// This is identical to running: ip link set dev ${oldName} name ${newName}
+func NetworkChangeName(iface *net.Interface, newName string) error {
+	if len(newName) >= IFNAMSIZ {
+		return fmt.Errorf("Interface name %s too long", newName)
+	}
+
+	s, err := getNetlinkSocket()
+	if err != nil {
+		return err
+	}
+	defer s.Close()
+
+	wb := newNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
+
+	msg := newIfInfomsg(syscall.AF_UNSPEC)
+	msg.Index = int32(iface.Index)
+	msg.Change = DEFAULT_CHANGE
+	wb.AddData(msg)
+
+	nameData := newRtAttr(syscall.IFLA_IFNAME, zeroTerminated(newName))
+	wb.AddData(nameData)
+
+	if err := s.Send(wb); err != nil {
+		return err
+	}
+
+	return s.HandleAck(wb.Seq)
+}
+
+// Add a new VETH pair link on the host
+// This is identical to running: ip link add name $name type veth peer name $peername
+func NetworkCreateVethPair(name1, name2 string, txQueueLen int) error {
+	s, err := getNetlinkSocket()
+	if err != nil {
+		return err
+	}
+	defer s.Close()
+
+	wb := newNetlinkRequest(syscall.RTM_NEWLINK, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
+
+	msg := newIfInfomsg(syscall.AF_UNSPEC)
+	wb.AddData(msg)
+
+	nameData := newRtAttr(syscall.IFLA_IFNAME, zeroTerminated(name1))
+	wb.AddData(nameData)
+
+	txqLen := make([]byte, 4)
+	native.PutUint32(txqLen, uint32(txQueueLen))
+	txqData := newRtAttr(syscall.IFLA_TXQLEN, txqLen)
+	wb.AddData(txqData)
+
+	nest1 := newRtAttr(syscall.IFLA_LINKINFO, nil)
+	newRtAttrChild(nest1, IFLA_INFO_KIND, zeroTerminated("veth"))
+	nest2 := newRtAttrChild(nest1, IFLA_INFO_DATA, nil)
+	nest3 := newRtAttrChild(nest2, VETH_INFO_PEER, nil)
+
+	newIfInfomsgChild(nest3, syscall.AF_UNSPEC)
+	newRtAttrChild(nest3, syscall.IFLA_IFNAME, zeroTerminated(name2))
+
+	txqLen2 := make([]byte, 4)
+	native.PutUint32(txqLen2, uint32(txQueueLen))
+	newRtAttrChild(nest3, syscall.IFLA_TXQLEN, txqLen2)
+
+	wb.AddData(nest1)
+
+	if err := s.Send(wb); err != nil {
+		return err
+	}
+
+	if err := s.HandleAck(wb.Seq); err != nil {
+		if os.IsExist(err) {
+			return ErrInterfaceExists
+		}
+
+		return err
+	}
+
+	return nil
+}
+
+// Add a new VLAN interface with masterDev as its upper device
+// This is identical to running:
+// ip link add name $name link $masterdev type vlan id $id
+func NetworkLinkAddVlan(masterDev, vlanDev string, vlanId uint16) error {
+	s, err := getNetlinkSocket()
+	if err != nil {
+		return err
+	}
+	defer s.Close()
+
+	wb := newNetlinkRequest(syscall.RTM_NEWLINK, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
+
+	masterDevIfc, err := net.InterfaceByName(masterDev)
+	if err != nil {
+		return err
+	}
+
+	msg := newIfInfomsg(syscall.AF_UNSPEC)
+	wb.AddData(msg)
+
+	nest1 := newRtAttr(syscall.IFLA_LINKINFO, nil)
+	newRtAttrChild(nest1, IFLA_INFO_KIND, nonZeroTerminated("vlan"))
+
+	nest2 := newRtAttrChild(nest1, IFLA_INFO_DATA, nil)
+	vlanData := make([]byte, 2)
+	native.PutUint16(vlanData, vlanId)
+	newRtAttrChild(nest2, IFLA_VLAN_ID, vlanData)
+	wb.AddData(nest1)
+
+	wb.AddData(uint32Attr(syscall.IFLA_LINK, uint32(masterDevIfc.Index)))
+	wb.AddData(newRtAttr(syscall.IFLA_IFNAME, zeroTerminated(vlanDev)))
+
+	if err := s.Send(wb); err != nil {
+		return err
+	}
+	return s.HandleAck(wb.Seq)
+}
+
+// MacVlan link has LowerDev, UpperDev and operates in Mode mode
+// This simplifies the code when creating MacVlan or MacVtap interface
+type MacVlanLink struct {
+	MasterDev string
+	SlaveDev  string
+	mode      string
+}
+
+func (m MacVlanLink) Mode() uint32 {
+	modeMap := map[string]uint32{
+		"private":  MACVLAN_MODE_PRIVATE,
+		"vepa":     MACVLAN_MODE_VEPA,
+		"bridge":   MACVLAN_MODE_BRIDGE,
+		"passthru": MACVLAN_MODE_PASSTHRU,
+	}
+
+	return modeMap[m.mode]
+}
+
+// Add MAC VLAN network interface with masterDev as its upper device
+// This is identical to running:
+// ip link add name $name link $masterdev type macvlan mode $mode
+func networkLinkMacVlan(dev_type string, mcvln *MacVlanLink) error {
+	s, err := getNetlinkSocket()
+	if err != nil {
+		return err
+	}
+	defer s.Close()
+
+	wb := newNetlinkRequest(syscall.RTM_NEWLINK, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
+
+	masterDevIfc, err := net.InterfaceByName(mcvln.MasterDev)
+	if err != nil {
+		return err
+	}
+
+	msg := newIfInfomsg(syscall.AF_UNSPEC)
+	wb.AddData(msg)
+
+	nest1 := newRtAttr(syscall.IFLA_LINKINFO, nil)
+	newRtAttrChild(nest1, IFLA_INFO_KIND, nonZeroTerminated(dev_type))
+
+	nest2 := newRtAttrChild(nest1, IFLA_INFO_DATA, nil)
+	macVlanData := make([]byte, 4)
+	native.PutUint32(macVlanData, mcvln.Mode())
+	newRtAttrChild(nest2, IFLA_MACVLAN_MODE, macVlanData)
+	wb.AddData(nest1)
+
+	wb.AddData(uint32Attr(syscall.IFLA_LINK, uint32(masterDevIfc.Index)))
+	wb.AddData(newRtAttr(syscall.IFLA_IFNAME, zeroTerminated(mcvln.SlaveDev)))
+
+	if err := s.Send(wb); err != nil {
+		return err
+	}
+	return s.HandleAck(wb.Seq)
+}
+
+func NetworkLinkAddMacVlan(masterDev, macVlanDev string, mode string) error {
+	return networkLinkMacVlan("macvlan", &MacVlanLink{
+		MasterDev: masterDev,
+		SlaveDev:  macVlanDev,
+		mode:      mode,
+	})
+}
+
+func NetworkLinkAddMacVtap(masterDev, macVlanDev string, mode string) error {
+	return networkLinkMacVlan("macvtap", &MacVlanLink{
+		MasterDev: masterDev,
+		SlaveDev:  macVlanDev,
+		mode:      mode,
+	})
+}
+
+func networkLinkIpAction(action, flags int, ifa IfAddr) error {
+	s, err := getNetlinkSocket()
+	if err != nil {
+		return err
+	}
+	defer s.Close()
+
+	family := getIpFamily(ifa.IP)
+
+	wb := newNetlinkRequest(action, flags)
+
+	msg := newIfAddrmsg(family)
+	msg.Index = uint32(ifa.Iface.Index)
+	prefixLen, _ := ifa.IPNet.Mask.Size()
+	msg.Prefixlen = uint8(prefixLen)
+	wb.AddData(msg)
+
+	var ipData []byte
+	if family == syscall.AF_INET {
+		ipData = ifa.IP.To4()
+	} else {
+		ipData = ifa.IP.To16()
+	}
+
+	localData := newRtAttr(syscall.IFA_LOCAL, ipData)
+	wb.AddData(localData)
+
+	addrData := newRtAttr(syscall.IFA_ADDRESS, ipData)
+	wb.AddData(addrData)
+
+	if err := s.Send(wb); err != nil {
+		return err
+	}
+
+	return s.HandleAck(wb.Seq)
+}
+
+// Delete an IP address from an interface. This is identical to:
+// ip addr del $ip/$ipNet dev $iface
+func NetworkLinkDelIp(iface *net.Interface, ip net.IP, ipNet *net.IPNet) error {
+	return networkLinkIpAction(
+		syscall.RTM_DELADDR,
+		syscall.NLM_F_ACK,
+		IfAddr{iface, ip, ipNet},
+	)
+}
+
+// Add an Ip address to an interface. This is identical to:
+// ip addr add $ip/$ipNet dev $iface
+func NetworkLinkAddIp(iface *net.Interface, ip net.IP, ipNet *net.IPNet) error {
+	return networkLinkIpAction(
+		syscall.RTM_NEWADDR,
+		syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK,
+		IfAddr{iface, ip, ipNet},
+	)
+}
+
+// Returns an array of IPNet for all the currently routed subnets on ipv4
+// This is similar to the first column of "ip route" output
+func NetworkGetRoutes() ([]Route, error) {
+	s, err := getNetlinkSocket()
+	if err != nil {
+		return nil, err
+	}
+	defer s.Close()
+
+	wb := newNetlinkRequest(syscall.RTM_GETROUTE, syscall.NLM_F_DUMP)
+
+	msg := newIfInfomsg(syscall.AF_UNSPEC)
+	wb.AddData(msg)
+
+	if err := s.Send(wb); err != nil {
+		return nil, err
+	}
+
+	pid, err := s.GetPid()
+	if err != nil {
+		return nil, err
+	}
+
+	res := make([]Route, 0)
+
+outer:
+	for {
+		msgs, err := s.Receive()
+		if err != nil {
+			return nil, err
+		}
+		for _, m := range msgs {
+			if err := s.CheckMessage(m, wb.Seq, pid); err != nil {
+				if err == io.EOF {
+					break outer
+				}
+				return nil, err
+			}
+			if m.Header.Type != syscall.RTM_NEWROUTE {
+				continue
+			}
+
+			var r Route
+
+			msg := (*RtMsg)(unsafe.Pointer(&m.Data[0:syscall.SizeofRtMsg][0]))
+
+			if msg.Flags&syscall.RTM_F_CLONED != 0 {
+				// Ignore cloned routes
+				continue
+			}
+
+			if msg.Table != syscall.RT_TABLE_MAIN {
+				// Ignore non-main tables
+				continue
+			}
+
+			if msg.Family != syscall.AF_INET {
+				// Ignore non-ipv4 routes
+				continue
+			}
+
+			if msg.Dst_len == 0 {
+				// Default routes
+				r.Default = true
+			}
+
+			attrs, err := syscall.ParseNetlinkRouteAttr(&m)
+			if err != nil {
+				return nil, err
+			}
+			for _, attr := range attrs {
+				switch attr.Attr.Type {
+				case syscall.RTA_DST:
+					ip := attr.Value
+					r.IPNet = &net.IPNet{
+						IP:   ip,
+						Mask: net.CIDRMask(int(msg.Dst_len), 8*len(ip)),
+					}
+				case syscall.RTA_OIF:
+					index := int(native.Uint32(attr.Value[0:4]))
+					r.Iface, _ = net.InterfaceByIndex(index)
+				}
+			}
+			if r.Default || r.IPNet != nil {
+				res = append(res, r)
+			}
+		}
+	}
+
+	return res, nil
+}
+
+// Add a new route table entry.
+func AddRoute(destination, source, gateway, device string) error {
+	if destination == "" && source == "" && gateway == "" {
+		return fmt.Errorf("one of destination, source or gateway must not be blank")
+	}
+
+	s, err := getNetlinkSocket()
+	if err != nil {
+		return err
+	}
+	defer s.Close()
+
+	wb := newNetlinkRequest(syscall.RTM_NEWROUTE, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
+	msg := newRtMsg()
+	currentFamily := -1
+	var rtAttrs []*RtAttr
+
+	if destination != "" {
+		destIP, destNet, err := net.ParseCIDR(destination)
+		if err != nil {
+			return fmt.Errorf("destination CIDR %s couldn't be parsed", destination)
+		}
+		destFamily := getIpFamily(destIP)
+		currentFamily = destFamily
+		destLen, bits := destNet.Mask.Size()
+		if destLen == 0 && bits == 0 {
+			return fmt.Errorf("destination CIDR %s generated a non-canonical Mask", destination)
+		}
+		msg.Family = uint8(destFamily)
+		msg.Dst_len = uint8(destLen)
+		var destData []byte
+		if destFamily == syscall.AF_INET {
+			destData = destIP.To4()
+		} else {
+			destData = destIP.To16()
+		}
+		rtAttrs = append(rtAttrs, newRtAttr(syscall.RTA_DST, destData))
+	}
+
+	if source != "" {
+		srcIP := net.ParseIP(source)
+		if srcIP == nil {
+			return fmt.Errorf("source IP %s couldn't be parsed", source)
+		}
+		srcFamily := getIpFamily(srcIP)
+		if currentFamily != -1 && currentFamily != srcFamily {
+			return fmt.Errorf("source and destination ip were not the same IP family")
+		}
+		currentFamily = srcFamily
+		msg.Family = uint8(srcFamily)
+		var srcData []byte
+		if srcFamily == syscall.AF_INET {
+			srcData = srcIP.To4()
+		} else {
+			srcData = srcIP.To16()
+		}
+		rtAttrs = append(rtAttrs, newRtAttr(syscall.RTA_PREFSRC, srcData))
+	}
+
+	if gateway != "" {
+		gwIP := net.ParseIP(gateway)
+		if gwIP == nil {
+			return fmt.Errorf("gateway IP %s couldn't be parsed", gateway)
+		}
+		gwFamily := getIpFamily(gwIP)
+		if currentFamily != -1 && currentFamily != gwFamily {
+			return fmt.Errorf("gateway, source, and destination ip were not the same IP family")
+		}
+		msg.Family = uint8(gwFamily)
+		var gwData []byte
+		if gwFamily == syscall.AF_INET {
+			gwData = gwIP.To4()
+		} else {
+			gwData = gwIP.To16()
+		}
+		rtAttrs = append(rtAttrs, newRtAttr(syscall.RTA_GATEWAY, gwData))
+	}
+
+	wb.AddData(msg)
+	for _, attr := range rtAttrs {
+		wb.AddData(attr)
+	}
+
+	iface, err := net.InterfaceByName(device)
+	if err != nil {
+		return err
+	}
+	wb.AddData(uint32Attr(syscall.RTA_OIF, uint32(iface.Index)))
+
+	if err := s.Send(wb); err != nil {
+		return err
+	}
+	return s.HandleAck(wb.Seq)
+}
+
+// Add a new default gateway. Identical to:
+// ip route add default via $ip
+func AddDefaultGw(ip, device string) error {
+	return AddRoute("", "", ip, device)
+}
+
+// THIS CODE DOES NOT COMMUNICATE WITH KERNEL VIA RTNETLINK INTERFACE
+// IT IS HERE FOR BACKWARDS COMPATIBILITY WITH OLDER LINUX KERNELS
+// WHICH SHIP WITH OLDER NOT ENTIRELY FUNCTIONAL VERSION OF NETLINK
+func getIfSocket() (fd int, err error) {
+	for _, socket := range []int{
+		syscall.AF_INET,
+		syscall.AF_PACKET,
+		syscall.AF_INET6,
+	} {
+		if fd, err = syscall.Socket(socket, syscall.SOCK_DGRAM, 0); err == nil {
+			break
+		}
+	}
+	if err == nil {
+		return fd, nil
+	}
+	return -1, err
+}
+
+// Create the actual bridge device.  This is more backward-compatible than
+// netlink.NetworkLinkAdd and works on RHEL 6.
+func CreateBridge(name string, setMacAddr bool) error {
+	if len(name) >= IFNAMSIZ {
+		return fmt.Errorf("Interface name %s too long", name)
+	}
+
+	s, err := getIfSocket()
+	if err != nil {
+		return err
+	}
+	defer syscall.Close(s)
+
+	nameBytePtr, err := syscall.BytePtrFromString(name)
+	if err != nil {
+		return err
+	}
+	if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(s), SIOC_BRADDBR, uintptr(unsafe.Pointer(nameBytePtr))); err != 0 {
+		return err
+	}
+	if setMacAddr {
+		return SetMacAddress(name, randMacAddr())
+	}
+	return nil
+}
+
+// Delete the actual bridge device.
+func DeleteBridge(name string) error {
+	s, err := getIfSocket()
+	if err != nil {
+		return err
+	}
+	defer syscall.Close(s)
+
+	nameBytePtr, err := syscall.BytePtrFromString(name)
+	if err != nil {
+		return err
+	}
+
+	var ifr ifreqFlags
+	copy(ifr.IfrnName[:len(ifr.IfrnName)-1], []byte(name))
+	if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(s),
+		syscall.SIOCSIFFLAGS, uintptr(unsafe.Pointer(&ifr))); err != 0 {
+		return err
+	}
+
+	if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(s),
+		SIOC_BRDELBR, uintptr(unsafe.Pointer(nameBytePtr))); err != 0 {
+		return err
+	}
+	return nil
+}
+
+// Add a slave to abridge device.  This is more backward-compatible than
+// netlink.NetworkSetMaster and works on RHEL 6.
+func AddToBridge(iface, master *net.Interface) error {
+	if len(master.Name) >= IFNAMSIZ {
+		return fmt.Errorf("Interface name %s too long", master.Name)
+	}
+
+	s, err := getIfSocket()
+	if err != nil {
+		return err
+	}
+	defer syscall.Close(s)
+
+	ifr := ifreqIndex{}
+	copy(ifr.IfrnName[:len(ifr.IfrnName)-1], master.Name)
+	ifr.IfruIndex = int32(iface.Index)
+
+	if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(s), SIOC_BRADDIF, uintptr(unsafe.Pointer(&ifr))); err != 0 {
+		return err
+	}
+
+	return nil
+}
+
+func randMacAddr() string {
+	hw := make(net.HardwareAddr, 6)
+	for i := 0; i < 6; i++ {
+		hw[i] = byte(rand.Intn(255))
+	}
+	hw[0] &^= 0x1 // clear multicast bit
+	hw[0] |= 0x2  // set local assignment bit (IEEE802)
+	return hw.String()
+}
+
+func SetMacAddress(name, addr string) error {
+	if len(name) >= IFNAMSIZ {
+		return fmt.Errorf("Interface name %s too long", name)
+	}
+
+	hw, err := net.ParseMAC(addr)
+	if err != nil {
+		return err
+	}
+
+	s, err := getIfSocket()
+	if err != nil {
+		return err
+	}
+	defer syscall.Close(s)
+
+	ifr := ifreqHwaddr{}
+	ifr.IfruHwaddr.Family = syscall.ARPHRD_ETHER
+	copy(ifr.IfrnName[:len(ifr.IfrnName)-1], name)
+
+	for i := 0; i < 6; i++ {
+		ifr.IfruHwaddr.Data[i] = ifrDataByte(hw[i])
+	}
+
+	if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(s), syscall.SIOCSIFHWADDR, uintptr(unsafe.Pointer(&ifr))); err != 0 {
+		return err
+	}
+	return nil
+}
+
+func SetHairpinMode(iface *net.Interface, enabled bool) error {
+	s, err := getNetlinkSocket()
+	if err != nil {
+		return err
+	}
+	defer s.Close()
+	req := newNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
+
+	msg := newIfInfomsg(syscall.AF_BRIDGE)
+	msg.Type = syscall.RTM_SETLINK
+	msg.Flags = syscall.NLM_F_REQUEST
+	msg.Index = int32(iface.Index)
+	msg.Change = DEFAULT_CHANGE
+	req.AddData(msg)
+
+	mode := []byte{0}
+	if enabled {
+		mode[0] = byte(1)
+	}
+
+	br := newRtAttr(syscall.IFLA_PROTINFO|syscall.NLA_F_NESTED, nil)
+	newRtAttrChild(br, IFLA_BRPORT_MODE, mode)
+	req.AddData(br)
+	if err := s.Send(req); err != nil {
+		return err
+	}
+
+	return s.HandleAck(req.Seq)
+}
+
+func ChangeName(iface *net.Interface, newName string) error {
+	if len(newName) >= IFNAMSIZ {
+		return fmt.Errorf("Interface name %s too long", newName)
+	}
+
+	fd, err := getIfSocket()
+	if err != nil {
+		return err
+	}
+	defer syscall.Close(fd)
+
+	data := [IFNAMSIZ * 2]byte{}
+	// the "-1"s here are very important for ensuring we get proper null
+	// termination of our new C strings
+	copy(data[:IFNAMSIZ-1], iface.Name)
+	copy(data[IFNAMSIZ:IFNAMSIZ*2-1], newName)
+
+	if _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), syscall.SIOCSIFNAME, uintptr(unsafe.Pointer(&data[0]))); errno != 0 {
+		return errno
+	}
+
+	return nil
+}

+ 5 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/libcontainer/netlink/netlink_linux_arm.go

@@ -0,0 +1,5 @@
+package netlink
+
+func ifrDataByte(b byte) uint8 {
+	return uint8(b)
+}

+ 7 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/libcontainer/netlink/netlink_linux_notarm.go

@@ -0,0 +1,7 @@
+// +build !arm
+
+package netlink
+
+func ifrDataByte(b byte) int8 {
+	return int8(b)
+}

+ 408 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/libcontainer/netlink/netlink_linux_test.go

@@ -0,0 +1,408 @@
+package netlink
+
+import (
+	"net"
+	"strings"
+	"syscall"
+	"testing"
+)
+
+type testLink struct {
+	name     string
+	linkType string
+}
+
+func addLink(t *testing.T, name string, linkType string) {
+	if err := NetworkLinkAdd(name, linkType); err != nil {
+		t.Fatalf("Unable to create %s link: %s", name, err)
+	}
+}
+
+func readLink(t *testing.T, name string) *net.Interface {
+	iface, err := net.InterfaceByName(name)
+	if err != nil {
+		t.Fatalf("Could not find %s interface: %s", name, err)
+	}
+
+	return iface
+}
+
+func deleteLink(t *testing.T, name string) {
+	if err := NetworkLinkDel(name); err != nil {
+		t.Fatalf("Unable to delete %s link: %s", name, err)
+	}
+}
+
+func upLink(t *testing.T, name string) {
+	iface := readLink(t, name)
+	if err := NetworkLinkUp(iface); err != nil {
+		t.Fatalf("Could not bring UP %#v interface: %s", iface, err)
+	}
+}
+
+func downLink(t *testing.T, name string) {
+	iface := readLink(t, name)
+	if err := NetworkLinkDown(iface); err != nil {
+		t.Fatalf("Could not bring DOWN %#v interface: %s", iface, err)
+	}
+}
+
+func ipAssigned(iface *net.Interface, ip net.IP) bool {
+	addrs, _ := iface.Addrs()
+
+	for _, addr := range addrs {
+		args := strings.SplitN(addr.String(), "/", 2)
+		if args[0] == ip.String() {
+			return true
+		}
+	}
+
+	return false
+}
+
+func TestNetworkLinkAddDel(t *testing.T) {
+	if testing.Short() {
+		return
+	}
+
+	testLinks := []testLink{
+		{"tstEth", "dummy"},
+		{"tstBr", "bridge"},
+	}
+
+	for _, tl := range testLinks {
+		addLink(t, tl.name, tl.linkType)
+		defer deleteLink(t, tl.name)
+		readLink(t, tl.name)
+	}
+}
+
+func TestNetworkLinkUpDown(t *testing.T) {
+	if testing.Short() {
+		return
+	}
+
+	tl := testLink{name: "tstEth", linkType: "dummy"}
+
+	addLink(t, tl.name, tl.linkType)
+	defer deleteLink(t, tl.name)
+
+	upLink(t, tl.name)
+	ifcAfterUp := readLink(t, tl.name)
+
+	if (ifcAfterUp.Flags & syscall.IFF_UP) != syscall.IFF_UP {
+		t.Fatalf("Could not bring UP %#v initerface", tl)
+	}
+
+	downLink(t, tl.name)
+	ifcAfterDown := readLink(t, tl.name)
+
+	if (ifcAfterDown.Flags & syscall.IFF_UP) == syscall.IFF_UP {
+		t.Fatalf("Could not bring DOWN %#v initerface", tl)
+	}
+}
+
+func TestNetworkSetMacAddress(t *testing.T) {
+	if testing.Short() {
+		return
+	}
+
+	tl := testLink{name: "tstEth", linkType: "dummy"}
+	macaddr := "22:ce:e0:99:63:6f"
+
+	addLink(t, tl.name, tl.linkType)
+	defer deleteLink(t, tl.name)
+
+	ifcBeforeSet := readLink(t, tl.name)
+
+	if err := NetworkSetMacAddress(ifcBeforeSet, macaddr); err != nil {
+		t.Fatalf("Could not set %s MAC address on %#v interface: %s", macaddr, tl, err)
+	}
+
+	ifcAfterSet := readLink(t, tl.name)
+
+	if ifcAfterSet.HardwareAddr.String() != macaddr {
+		t.Fatalf("Could not set %s MAC address on %#v interface", macaddr, tl)
+	}
+}
+
+func TestNetworkSetMTU(t *testing.T) {
+	if testing.Short() {
+		return
+	}
+
+	tl := testLink{name: "tstEth", linkType: "dummy"}
+	mtu := 1400
+
+	addLink(t, tl.name, tl.linkType)
+	defer deleteLink(t, tl.name)
+
+	ifcBeforeSet := readLink(t, tl.name)
+
+	if err := NetworkSetMTU(ifcBeforeSet, mtu); err != nil {
+		t.Fatalf("Could not set %d MTU on %#v interface: %s", mtu, tl, err)
+	}
+
+	ifcAfterSet := readLink(t, tl.name)
+
+	if ifcAfterSet.MTU != mtu {
+		t.Fatalf("Could not set %d MTU on %#v interface", mtu, tl)
+	}
+}
+
+func TestNetworkSetMasterNoMaster(t *testing.T) {
+	if testing.Short() {
+		return
+	}
+
+	master := testLink{"tstBr", "bridge"}
+	slave := testLink{"tstEth", "dummy"}
+	testLinks := []testLink{master, slave}
+
+	for _, tl := range testLinks {
+		addLink(t, tl.name, tl.linkType)
+		defer deleteLink(t, tl.name)
+		upLink(t, tl.name)
+	}
+
+	masterIfc := readLink(t, master.name)
+	slaveIfc := readLink(t, slave.name)
+	if err := NetworkSetMaster(slaveIfc, masterIfc); err != nil {
+		t.Fatalf("Could not set %#v to be the master of %#v: %s", master, slave, err)
+	}
+
+	// Trying to figure out a way to test which will not break on RHEL6.
+	// We could check for existence of /sys/class/net/tstEth/upper_tstBr
+	// which should point to the ../tstBr which is the UPPER device i.e. network bridge
+
+	if err := NetworkSetNoMaster(slaveIfc); err != nil {
+		t.Fatalf("Could not UNset %#v master of %#v: %s", master, slave, err)
+	}
+}
+
+func TestNetworkChangeName(t *testing.T) {
+	if testing.Short() {
+		return
+	}
+
+	tl := testLink{"tstEth", "dummy"}
+	newName := "newTst"
+
+	addLink(t, tl.name, tl.linkType)
+
+	linkIfc := readLink(t, tl.name)
+	if err := NetworkChangeName(linkIfc, newName); err != nil {
+		deleteLink(t, tl.name)
+		t.Fatalf("Could not change %#v interface name to %s: %s", tl, newName, err)
+	}
+
+	readLink(t, newName)
+	deleteLink(t, newName)
+}
+
+func TestNetworkLinkAddVlan(t *testing.T) {
+	if testing.Short() {
+		return
+	}
+
+	tl := struct {
+		name string
+		id   uint16
+	}{
+		name: "tstVlan",
+		id:   32,
+	}
+	masterLink := testLink{"tstEth", "dummy"}
+
+	addLink(t, masterLink.name, masterLink.linkType)
+	defer deleteLink(t, masterLink.name)
+
+	if err := NetworkLinkAddVlan(masterLink.name, tl.name, tl.id); err != nil {
+		t.Fatalf("Unable to create %#v VLAN interface: %s", tl, err)
+	}
+
+	readLink(t, tl.name)
+}
+
+func TestNetworkLinkAddMacVlan(t *testing.T) {
+	if testing.Short() {
+		return
+	}
+
+	tl := struct {
+		name string
+		mode string
+	}{
+		name: "tstVlan",
+		mode: "private",
+	}
+	masterLink := testLink{"tstEth", "dummy"}
+
+	addLink(t, masterLink.name, masterLink.linkType)
+	defer deleteLink(t, masterLink.name)
+
+	if err := NetworkLinkAddMacVlan(masterLink.name, tl.name, tl.mode); err != nil {
+		t.Fatalf("Unable to create %#v MAC VLAN interface: %s", tl, err)
+	}
+
+	readLink(t, tl.name)
+}
+
+func TestNetworkLinkAddMacVtap(t *testing.T) {
+	if testing.Short() {
+		return
+	}
+
+	tl := struct {
+		name string
+		mode string
+	}{
+		name: "tstVtap",
+		mode: "private",
+	}
+	masterLink := testLink{"tstEth", "dummy"}
+
+	addLink(t, masterLink.name, masterLink.linkType)
+	defer deleteLink(t, masterLink.name)
+
+	if err := NetworkLinkAddMacVtap(masterLink.name, tl.name, tl.mode); err != nil {
+		t.Fatalf("Unable to create %#v MAC VTAP interface: %s", tl, err)
+	}
+
+	readLink(t, tl.name)
+}
+
+func TestAddDelNetworkIp(t *testing.T) {
+	if testing.Short() {
+		return
+	}
+
+	ifaceName := "lo"
+	ip := net.ParseIP("127.0.1.1")
+	mask := net.IPv4Mask(255, 255, 255, 255)
+	ipNet := &net.IPNet{IP: ip, Mask: mask}
+
+	iface, err := net.InterfaceByName(ifaceName)
+	if err != nil {
+		t.Skip("No 'lo' interface; skipping tests")
+	}
+
+	if err := NetworkLinkAddIp(iface, ip, ipNet); err != nil {
+		t.Fatalf("Could not add IP address %s to interface %#v: %s", ip.String(), iface, err)
+	}
+
+	if !ipAssigned(iface, ip) {
+		t.Fatalf("Could not locate address '%s' in lo address list.", ip.String())
+	}
+
+	if err := NetworkLinkDelIp(iface, ip, ipNet); err != nil {
+		t.Fatalf("Could not delete IP address %s from interface %#v: %s", ip.String(), iface, err)
+	}
+
+	if ipAssigned(iface, ip) {
+		t.Fatalf("Located address '%s' in lo address list after removal.", ip.String())
+	}
+}
+
+func TestAddRouteSourceSelection(t *testing.T) {
+	tstIp := "127.1.1.1"
+	tl := testLink{name: "tstEth", linkType: "dummy"}
+
+	addLink(t, tl.name, tl.linkType)
+	defer deleteLink(t, tl.name)
+
+	ip := net.ParseIP(tstIp)
+	mask := net.IPv4Mask(255, 255, 255, 255)
+	ipNet := &net.IPNet{IP: ip, Mask: mask}
+
+	iface, err := net.InterfaceByName(tl.name)
+	if err != nil {
+		t.Fatalf("Lost created link %#v", tl)
+	}
+
+	if err := NetworkLinkAddIp(iface, ip, ipNet); err != nil {
+		t.Fatalf("Could not add IP address %s to interface %#v: %s", ip.String(), iface, err)
+	}
+
+	upLink(t, tl.name)
+	defer downLink(t, tl.name)
+
+	if err := AddRoute("127.0.0.0/8", tstIp, "", tl.name); err != nil {
+		t.Fatalf("Failed to add route with source address")
+	}
+}
+
+func TestCreateVethPair(t *testing.T) {
+	if testing.Short() {
+		return
+	}
+
+	var (
+		name1 = "veth1"
+		name2 = "veth2"
+	)
+
+	if err := NetworkCreateVethPair(name1, name2, 0); err != nil {
+		t.Fatalf("Could not create veth pair %s %s: %s", name1, name2, err)
+	}
+	defer NetworkLinkDel(name1)
+
+	readLink(t, name1)
+	readLink(t, name2)
+}
+
+//
+// netlink package tests which do not use RTNETLINK
+//
+func TestCreateBridgeWithMac(t *testing.T) {
+	if testing.Short() {
+		return
+	}
+
+	name := "testbridge"
+
+	if err := CreateBridge(name, true); err != nil {
+		t.Fatal(err)
+	}
+
+	if _, err := net.InterfaceByName(name); err != nil {
+		t.Fatal(err)
+	}
+
+	// cleanup and tests
+
+	if err := DeleteBridge(name); err != nil {
+		t.Fatal(err)
+	}
+
+	if _, err := net.InterfaceByName(name); err == nil {
+		t.Fatalf("expected error getting interface because %s bridge was deleted", name)
+	}
+}
+
+func TestSetMacAddress(t *testing.T) {
+	if testing.Short() {
+		return
+	}
+
+	name := "testmac"
+	mac := randMacAddr()
+
+	if err := NetworkLinkAdd(name, "bridge"); err != nil {
+		t.Fatal(err)
+	}
+	defer NetworkLinkDel(name)
+
+	if err := SetMacAddress(name, mac); err != nil {
+		t.Fatal(err)
+	}
+
+	iface, err := net.InterfaceByName(name)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if iface.HardwareAddr.String() != mac {
+		t.Fatalf("mac address %q does not match %q", iface.HardwareAddr, mac)
+	}
+}

+ 88 - 0
libnetwork/Godeps/_workspace/src/github.com/docker/libcontainer/netlink/netlink_unsupported.go

@@ -0,0 +1,88 @@
+// +build !linux
+
+package netlink
+
+import (
+	"errors"
+	"net"
+)
+
+var (
+	ErrNotImplemented = errors.New("not implemented")
+)
+
+func NetworkGetRoutes() ([]Route, error) {
+	return nil, ErrNotImplemented
+}
+
+func NetworkLinkAdd(name string, linkType string) error {
+	return ErrNotImplemented
+}
+
+func NetworkLinkDel(name string) error {
+	return ErrNotImplemented
+}
+
+func NetworkLinkUp(iface *net.Interface) error {
+	return ErrNotImplemented
+}
+
+func NetworkLinkAddIp(iface *net.Interface, ip net.IP, ipNet *net.IPNet) error {
+	return ErrNotImplemented
+}
+
+func NetworkLinkDelIp(iface *net.Interface, ip net.IP, ipNet *net.IPNet) error {
+	return ErrNotImplemented
+}
+
+func AddRoute(destination, source, gateway, device string) error {
+	return ErrNotImplemented
+}
+
+func AddDefaultGw(ip, device string) error {
+	return ErrNotImplemented
+}
+
+func NetworkSetMTU(iface *net.Interface, mtu int) error {
+	return ErrNotImplemented
+}
+
+func NetworkSetTxQueueLen(iface *net.Interface, txQueueLen int) error {
+	return ErrNotImplemented
+}
+
+func NetworkCreateVethPair(name1, name2 string, txQueueLen int) error {
+	return ErrNotImplemented
+}
+
+func NetworkChangeName(iface *net.Interface, newName string) error {
+	return ErrNotImplemented
+}
+
+func NetworkSetNsFd(iface *net.Interface, fd int) error {
+	return ErrNotImplemented
+}
+
+func NetworkSetNsPid(iface *net.Interface, nspid int) error {
+	return ErrNotImplemented
+}
+
+func NetworkSetMaster(iface, master *net.Interface) error {
+	return ErrNotImplemented
+}
+
+func NetworkLinkDown(iface *net.Interface) error {
+	return ErrNotImplemented
+}
+
+func CreateBridge(name string, setMacAddr bool) error {
+	return ErrNotImplemented
+}
+
+func DeleteBridge(name string) error {
+	return ErrNotImplemented
+}
+
+func AddToBridge(iface, master *net.Interface) error {
+	return ErrNotImplemented
+}

+ 3 - 0
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/.travis.yml

@@ -0,0 +1,3 @@
+language: go
+install:
+      - go get github.com/vishvananda/netns

+ 192 - 0
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/LICENSE

@@ -0,0 +1,192 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   Copyright 2014 Vishvananda Ishaya.
+   Copyright 2014 Docker, Inc.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.

+ 29 - 0
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/Makefile

@@ -0,0 +1,29 @@
+DIRS := \
+	. \
+	nl
+
+DEPS = \
+	github.com/vishvananda/netns
+
+uniq = $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1)))
+testdirs = $(call uniq,$(foreach d,$(1),$(dir $(wildcard $(d)/*_test.go))))
+goroot = $(addprefix ../../../,$(1))
+unroot = $(subst ../../../,,$(1))
+fmt = $(addprefix fmt-,$(1))
+
+all: fmt
+
+$(call goroot,$(DEPS)):
+	go get $(call unroot,$@)
+
+.PHONY: $(call testdirs,$(DIRS))
+$(call testdirs,$(DIRS)):
+	sudo -E go test -v github.com/vishvananda/netlink/$@
+
+$(call fmt,$(call testdirs,$(DIRS))):
+	! gofmt -l $(subst fmt-,,$@)/*.go | grep ''
+
+.PHONY: fmt
+fmt: $(call fmt,$(call testdirs,$(DIRS)))
+
+test: fmt $(call goroot,$(DEPS)) $(call testdirs,$(DIRS))

+ 83 - 0
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/README.md

@@ -0,0 +1,83 @@
+# netlink - netlink library for go #
+
+[![Build Status](https://travis-ci.org/vishvananda/netlink.png?branch=master)](https://travis-ci.org/vishvananda/netlink) [![GoDoc](https://godoc.org/github.com/vishvananda/netlink?status.svg)](https://godoc.org/github.com/vishvananda/netlink)
+
+The netlink package provides a simple netlink library for go. Netlink
+is the interface a user-space program in linux uses to communicate with
+the kernel. It can be used to add and remove interfaces, set ip addresses
+and routes, and configure ipsec. Netlink communication requires elevated
+privileges, so in most cases this code needs to be run as root. Since
+low-level netlink messages are inscrutable at best, the library attempts
+to provide an api that is loosely modeled on the CLI provied by iproute2.
+Actions like `ip link add` will be accomplished via a similarly named
+function like AddLink(). This library began its life as a fork of the
+netlink functionality in
+[docker/libcontainer](https://github.com/docker/libcontainer) but was
+heavily rewritten to improve testability, performance, and to add new
+functionality like ipsec xfrm handling.
+
+## Local Build and Test ##
+
+You can use go get command:
+
+    go get github.com/vishvananda/netlink
+
+Testing dependencies:
+
+    go get github.com/vishvananda/netns
+
+Testing (requires root):
+
+    sudo -E go test github.com/vishvananda/netlink
+
+## Examples ##
+
+Add a new bridge and add eth1 into it:
+
+```go
+package main
+
+import (
+    "net"
+    "github.com/vishvananda/netlink"
+)
+
+func main() {
+    mybridge := &netlink.Bridge{netlink.LinkAttrs{Name: "foo"}}
+    _ := netlink.LinkAdd(mybridge)
+    eth1, _ := netlink.LinkByName("eth1")
+    netlink.LinkSetMaster(eth1, mybridge)
+}
+
+```
+
+Add a new ip address to loopback:
+
+```go
+package main
+
+import (
+    "net"
+    "github.com/vishvananda/netlink"
+)
+
+func main() {
+    lo, _ := netlink.LinkByName("lo")
+    addr, _ := netlink.ParseAddr("169.254.169.254/32")
+    netlink.AddrAdd(lo, addr)
+}
+
+```
+
+## Future Work ##
+
+Many pieces of netlink are not yet fully supported in the high-level
+interface. Aspects of virtually all of the high-level objects don't exist.
+Many of the underlying primitives are there, so its a matter of putting
+the right fields into the high-level objects and making sure that they
+are serialized and deserialized correctly in the Add and List methods.
+
+There are also a few pieces of low level netlink functionality that still
+need to be implemented. Routing rules are not in place and some of the
+more advanced link types. Hopefully there is decent structure and testing
+in place to make these fairly straightforward to add.

+ 43 - 0
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/addr.go

@@ -0,0 +1,43 @@
+package netlink
+
+import (
+	"fmt"
+	"net"
+	"strings"
+)
+
+// Addr represents an IP address from netlink. Netlink ip addresses
+// include a mask, so it stores the address as a net.IPNet.
+type Addr struct {
+	*net.IPNet
+	Label string
+}
+
+// String returns $ip/$netmask $label
+func (addr Addr) String() string {
+	return fmt.Sprintf("%s %s", addr.IPNet, addr.Label)
+}
+
+// ParseAddr parses the string representation of an address in the
+// form $ip/$netmask $label. The label portion is optional
+func ParseAddr(s string) (*Addr, error) {
+	label := ""
+	parts := strings.Split(s, " ")
+	if len(parts) > 1 {
+		s = parts[0]
+		label = parts[1]
+	}
+	m, err := ParseIPNet(s)
+	if err != nil {
+		return nil, err
+	}
+	return &Addr{IPNet: m, Label: label}, nil
+}
+
+// Equal returns true if both Addrs have the same net.IPNet value.
+func (a Addr) Equal(x Addr) bool {
+	sizea, _ := a.Mask.Size()
+	sizeb, _ := x.Mask.Size()
+	// ignore label for comparison
+	return a.IP.Equal(x.IP) && sizea == sizeb
+}

+ 114 - 0
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/addr_linux.go

@@ -0,0 +1,114 @@
+package netlink
+
+import (
+	"fmt"
+	"net"
+	"strings"
+	"syscall"
+
+	"github.com/vishvananda/netlink/nl"
+)
+
+// AddrAdd will add an IP address to a link device.
+// Equivalent to: `ip addr add $addr dev $link`
+func AddrAdd(link Link, addr *Addr) error {
+
+	req := nl.NewNetlinkRequest(syscall.RTM_NEWADDR, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
+	return addrHandle(link, addr, req)
+}
+
+// AddrDel will delete an IP address from a link device.
+// Equivalent to: `ip addr del $addr dev $link`
+func AddrDel(link Link, addr *Addr) error {
+	req := nl.NewNetlinkRequest(syscall.RTM_DELADDR, syscall.NLM_F_ACK)
+	return addrHandle(link, addr, req)
+}
+
+func addrHandle(link Link, addr *Addr, req *nl.NetlinkRequest) error {
+	base := link.Attrs()
+	if addr.Label != "" && !strings.HasPrefix(addr.Label, base.Name) {
+		return fmt.Errorf("label must begin with interface name")
+	}
+	ensureIndex(base)
+
+	family := nl.GetIPFamily(addr.IP)
+
+	msg := nl.NewIfAddrmsg(family)
+	msg.Index = uint32(base.Index)
+	prefixlen, _ := addr.Mask.Size()
+	msg.Prefixlen = uint8(prefixlen)
+	req.AddData(msg)
+
+	var addrData []byte
+	if family == FAMILY_V4 {
+		addrData = addr.IP.To4()
+	} else {
+		addrData = addr.IP.To16()
+	}
+
+	localData := nl.NewRtAttr(syscall.IFA_LOCAL, addrData)
+	req.AddData(localData)
+
+	addressData := nl.NewRtAttr(syscall.IFA_ADDRESS, addrData)
+	req.AddData(addressData)
+
+	if addr.Label != "" {
+		labelData := nl.NewRtAttr(syscall.IFA_LABEL, nl.ZeroTerminated(addr.Label))
+		req.AddData(labelData)
+	}
+
+	_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
+	return err
+}
+
+// AddrList gets a list of IP addresses in the system.
+// Equivalent to: `ip addr show`.
+// The list can be filtered by link and ip family.
+func AddrList(link Link, family int) ([]Addr, error) {
+	req := nl.NewNetlinkRequest(syscall.RTM_GETADDR, syscall.NLM_F_DUMP)
+	msg := nl.NewIfInfomsg(family)
+	req.AddData(msg)
+
+	msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWADDR)
+	if err != nil {
+		return nil, err
+	}
+
+	index := 0
+	if link != nil {
+		base := link.Attrs()
+		ensureIndex(base)
+		index = base.Index
+	}
+
+	res := make([]Addr, 0)
+	for _, m := range msgs {
+		msg := nl.DeserializeIfAddrmsg(m)
+
+		if link != nil && msg.Index != uint32(index) {
+			// Ignore messages from other interfaces
+			continue
+		}
+
+		attrs, err := nl.ParseRouteAttr(m[msg.Len():])
+		if err != nil {
+			return nil, err
+		}
+
+		var addr Addr
+		for _, attr := range attrs {
+			switch attr.Attr.Type {
+			case syscall.IFA_ADDRESS:
+				addr.IPNet = &net.IPNet{
+					IP:   attr.Value,
+					Mask: net.CIDRMask(int(msg.Prefixlen), 8*len(attr.Value)),
+				}
+			case syscall.IFA_LABEL:
+				addr.Label = string(attr.Value[:len(attr.Value)-1])
+			}
+		}
+		res = append(res, addr)
+	}
+
+	return res, nil
+}

+ 45 - 0
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/addr_test.go

@@ -0,0 +1,45 @@
+package netlink
+
+import (
+	"testing"
+)
+
+func TestAddrAddDel(t *testing.T) {
+	tearDown := setUpNetlinkTest(t)
+	defer tearDown()
+
+	link, err := LinkByName("lo")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	addr, err := ParseAddr("127.1.1.1/24 local")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if err = AddrAdd(link, addr); err != nil {
+		t.Fatal(err)
+	}
+
+	addrs, err := AddrList(link, FAMILY_ALL)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if len(addrs) != 1 || !addr.Equal(addrs[0]) || addrs[0].Label != addr.Label {
+		t.Fatal("Address not added properly")
+	}
+
+	if err = AddrDel(link, addr); err != nil {
+		t.Fatal(err)
+	}
+	addrs, err = AddrList(link, FAMILY_ALL)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if len(addrs) != 0 {
+		t.Fatal("Address not removed properly")
+	}
+}

+ 175 - 0
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/link.go

@@ -0,0 +1,175 @@
+package netlink
+
+import "net"
+
+// Link represents a link device from netlink. Shared link attributes
+// like name may be retrieved using the Attrs() method. Unique data
+// can be retrieved by casting the object to the proper type.
+type Link interface {
+	Attrs() *LinkAttrs
+	Type() string
+}
+
+// LinkAttrs represents data shared by most link types
+type LinkAttrs struct {
+	Index        int
+	MTU          int
+	TxQLen       uint32 // Transmit Queue Length
+	Name         string
+	HardwareAddr net.HardwareAddr
+	Flags        net.Flags
+	ParentIndex  int // index of the parent link device
+	MasterIndex  int // must be the index of a bridge
+}
+
+// Device links cannot be created via netlink. These links
+// are links created by udev like 'lo' and 'etho0'
+type Device struct {
+	LinkAttrs
+}
+
+func (device *Device) Attrs() *LinkAttrs {
+	return &device.LinkAttrs
+}
+
+func (device *Device) Type() string {
+	return "device"
+}
+
+// Dummy links are dummy ethernet devices
+type Dummy struct {
+	LinkAttrs
+}
+
+func (dummy *Dummy) Attrs() *LinkAttrs {
+	return &dummy.LinkAttrs
+}
+
+func (dummy *Dummy) Type() string {
+	return "dummy"
+}
+
+// Bridge links are simple linux bridges
+type Bridge struct {
+	LinkAttrs
+}
+
+func (bridge *Bridge) Attrs() *LinkAttrs {
+	return &bridge.LinkAttrs
+}
+
+func (bridge *Bridge) Type() string {
+	return "bridge"
+}
+
+// Vlan links have ParentIndex set in their Attrs()
+type Vlan struct {
+	LinkAttrs
+	VlanId int
+}
+
+func (vlan *Vlan) Attrs() *LinkAttrs {
+	return &vlan.LinkAttrs
+}
+
+func (vlan *Vlan) Type() string {
+	return "vlan"
+}
+
+// Macvlan links have ParentIndex set in their Attrs()
+type Macvlan struct {
+	LinkAttrs
+}
+
+func (macvlan *Macvlan) Attrs() *LinkAttrs {
+	return &macvlan.LinkAttrs
+}
+
+func (macvlan *Macvlan) Type() string {
+	return "macvlan"
+}
+
+// Veth devices must specify PeerName on create
+type Veth struct {
+	LinkAttrs
+	PeerName string // veth on create only
+}
+
+func (veth *Veth) Attrs() *LinkAttrs {
+	return &veth.LinkAttrs
+}
+
+func (veth *Veth) Type() string {
+	return "veth"
+}
+
+// Generic links represent types that are not currently understood
+// by this netlink library.
+type Generic struct {
+	LinkAttrs
+	LinkType string
+}
+
+func (generic *Generic) Attrs() *LinkAttrs {
+	return &generic.LinkAttrs
+}
+
+func (generic *Generic) Type() string {
+	return generic.LinkType
+}
+
+type Vxlan struct {
+	LinkAttrs
+	VxlanId      int
+	VtepDevIndex int
+	SrcAddr      net.IP
+	Group        net.IP
+	TTL          int
+	TOS          int
+	Learning     bool
+	Proxy        bool
+	RSC          bool
+	L2miss       bool
+	L3miss       bool
+	NoAge        bool
+	Age          int
+	Limit        int
+	Port         int
+	PortLow      int
+	PortHigh     int
+}
+
+func (vxlan *Vxlan) Attrs() *LinkAttrs {
+	return &vxlan.LinkAttrs
+}
+
+func (vxlan *Vxlan) Type() string {
+	return "vxlan"
+}
+
+type IPVlanMode uint16
+
+const (
+	IPVLAN_MODE_L2 IPVlanMode = iota
+	IPVLAN_MODE_L3
+	IPVLAN_MODE_MAX
+)
+
+type IPVlan struct {
+	LinkAttrs
+	Mode IPVlanMode
+}
+
+func (ipvlan *IPVlan) Attrs() *LinkAttrs {
+	return &ipvlan.LinkAttrs
+}
+
+func (ipvlan *IPVlan) Type() string {
+	return "ipvlan"
+}
+
+// iproute2 supported devices;
+// vlan | veth | vcan | dummy | ifb | macvlan | macvtap |
+// bridge | bond | ipoib | ip6tnl | ipip | sit | vxlan |
+// gre | gretap | ip6gre | ip6gretap | vti | nlmon |
+// bond_slave | ipvlan

+ 696 - 0
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/link_linux.go

@@ -0,0 +1,696 @@
+package netlink
+
+import (
+	"bytes"
+	"encoding/binary"
+	"fmt"
+	"net"
+	"syscall"
+
+	"github.com/vishvananda/netlink/nl"
+)
+
+var native = nl.NativeEndian()
+var lookupByDump = false
+
+func ensureIndex(link *LinkAttrs) {
+	if link != nil && link.Index == 0 {
+		newlink, _ := LinkByName(link.Name)
+		if newlink != nil {
+			link.Index = newlink.Attrs().Index
+		}
+	}
+}
+
+// LinkSetUp enables the link device.
+// Equivalent to: `ip link set $link up`
+func LinkSetUp(link Link) error {
+	base := link.Attrs()
+	ensureIndex(base)
+	req := nl.NewNetlinkRequest(syscall.RTM_NEWLINK, syscall.NLM_F_ACK)
+
+	msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
+	msg.Change = syscall.IFF_UP
+	msg.Flags = syscall.IFF_UP
+	msg.Index = int32(base.Index)
+	req.AddData(msg)
+
+	_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
+	return err
+}
+
+// LinkSetUp disables link device.
+// Equivalent to: `ip link set $link down`
+func LinkSetDown(link Link) error {
+	base := link.Attrs()
+	ensureIndex(base)
+	req := nl.NewNetlinkRequest(syscall.RTM_NEWLINK, syscall.NLM_F_ACK)
+
+	msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
+	msg.Change = syscall.IFF_UP
+	msg.Flags = 0 & ^syscall.IFF_UP
+	msg.Index = int32(base.Index)
+	req.AddData(msg)
+
+	_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
+	return err
+}
+
+// LinkSetMTU sets the mtu of the link device.
+// Equivalent to: `ip link set $link mtu $mtu`
+func LinkSetMTU(link Link, mtu int) error {
+	base := link.Attrs()
+	ensureIndex(base)
+	req := nl.NewNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
+
+	msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
+	msg.Type = syscall.RTM_SETLINK
+	msg.Flags = syscall.NLM_F_REQUEST
+	msg.Index = int32(base.Index)
+	msg.Change = nl.DEFAULT_CHANGE
+	req.AddData(msg)
+
+	b := make([]byte, 4)
+	native.PutUint32(b, uint32(mtu))
+
+	data := nl.NewRtAttr(syscall.IFLA_MTU, b)
+	req.AddData(data)
+
+	_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
+	return err
+}
+
+// LinkSetName sets the name of the link device.
+// Equivalent to: `ip link set $link name $name`
+func LinkSetName(link Link, name string) error {
+	base := link.Attrs()
+	ensureIndex(base)
+	req := nl.NewNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
+
+	msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
+	msg.Type = syscall.RTM_SETLINK
+	msg.Flags = syscall.NLM_F_REQUEST
+	msg.Index = int32(base.Index)
+	msg.Change = nl.DEFAULT_CHANGE
+	req.AddData(msg)
+
+	data := nl.NewRtAttr(syscall.IFLA_IFNAME, []byte(name))
+	req.AddData(data)
+
+	_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
+	return err
+}
+
+// LinkSetHardwareAddr sets the hardware address of the link device.
+// Equivalent to: `ip link set $link address $hwaddr`
+func LinkSetHardwareAddr(link Link, hwaddr net.HardwareAddr) error {
+	base := link.Attrs()
+	ensureIndex(base)
+	req := nl.NewNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
+
+	msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
+	msg.Type = syscall.RTM_SETLINK
+	msg.Flags = syscall.NLM_F_REQUEST
+	msg.Index = int32(base.Index)
+	msg.Change = nl.DEFAULT_CHANGE
+	req.AddData(msg)
+
+	data := nl.NewRtAttr(syscall.IFLA_ADDRESS, []byte(hwaddr))
+	req.AddData(data)
+
+	_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
+	return err
+}
+
+// LinkSetMaster sets the master of the link device.
+// Equivalent to: `ip link set $link master $master`
+func LinkSetMaster(link Link, master *Bridge) error {
+	index := 0
+	if master != nil {
+		masterBase := master.Attrs()
+		ensureIndex(masterBase)
+		index = masterBase.Index
+	}
+	return LinkSetMasterByIndex(link, index)
+}
+
+// LinkSetMasterByIndex sets the master of the link device.
+// Equivalent to: `ip link set $link master $master`
+func LinkSetMasterByIndex(link Link, masterIndex int) error {
+	base := link.Attrs()
+	ensureIndex(base)
+	req := nl.NewNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
+
+	msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
+	msg.Type = syscall.RTM_SETLINK
+	msg.Flags = syscall.NLM_F_REQUEST
+	msg.Index = int32(base.Index)
+	msg.Change = nl.DEFAULT_CHANGE
+	req.AddData(msg)
+
+	b := make([]byte, 4)
+	native.PutUint32(b, uint32(masterIndex))
+
+	data := nl.NewRtAttr(syscall.IFLA_MASTER, b)
+	req.AddData(data)
+
+	_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
+	return err
+}
+
+// LinkSetNsPid puts the device into a new network namespace. The
+// pid must be a pid of a running process.
+// Equivalent to: `ip link set $link netns $pid`
+func LinkSetNsPid(link Link, nspid int) error {
+	base := link.Attrs()
+	ensureIndex(base)
+	req := nl.NewNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
+
+	msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
+	msg.Type = syscall.RTM_SETLINK
+	msg.Flags = syscall.NLM_F_REQUEST
+	msg.Index = int32(base.Index)
+	msg.Change = nl.DEFAULT_CHANGE
+	req.AddData(msg)
+
+	b := make([]byte, 4)
+	native.PutUint32(b, uint32(nspid))
+
+	data := nl.NewRtAttr(syscall.IFLA_NET_NS_PID, b)
+	req.AddData(data)
+
+	_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
+	return err
+}
+
+// LinkSetNsPid puts the device into a new network namespace. The
+// fd must be an open file descriptor to a network namespace.
+// Similar to: `ip link set $link netns $ns`
+func LinkSetNsFd(link Link, fd int) error {
+	base := link.Attrs()
+	ensureIndex(base)
+	req := nl.NewNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
+
+	msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
+	msg.Type = syscall.RTM_SETLINK
+	msg.Flags = syscall.NLM_F_REQUEST
+	msg.Index = int32(base.Index)
+	msg.Change = nl.DEFAULT_CHANGE
+	req.AddData(msg)
+
+	b := make([]byte, 4)
+	native.PutUint32(b, uint32(fd))
+
+	data := nl.NewRtAttr(nl.IFLA_NET_NS_FD, b)
+	req.AddData(data)
+
+	_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
+	return err
+}
+
+func boolAttr(val bool) []byte {
+	var v uint8
+	if val {
+		v = 1
+	}
+	return nl.Uint8Attr(v)
+}
+
+type vxlanPortRange struct {
+	Lo, Hi uint16
+}
+
+func addVxlanAttrs(vxlan *Vxlan, linkInfo *nl.RtAttr) {
+	data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil)
+	nl.NewRtAttrChild(data, nl.IFLA_VXLAN_ID, nl.Uint32Attr(uint32(vxlan.VxlanId)))
+	if vxlan.VtepDevIndex != 0 {
+		nl.NewRtAttrChild(data, nl.IFLA_VXLAN_LINK, nl.Uint32Attr(uint32(vxlan.VtepDevIndex)))
+	}
+	if vxlan.SrcAddr != nil {
+		ip := vxlan.SrcAddr.To4()
+		if ip != nil {
+			nl.NewRtAttrChild(data, nl.IFLA_VXLAN_LOCAL, []byte(ip))
+		} else {
+			ip = vxlan.SrcAddr.To16()
+			if ip != nil {
+				nl.NewRtAttrChild(data, nl.IFLA_VXLAN_LOCAL6, []byte(ip))
+			}
+		}
+	}
+	if vxlan.Group != nil {
+		group := vxlan.Group.To4()
+		if group != nil {
+			nl.NewRtAttrChild(data, nl.IFLA_VXLAN_GROUP, []byte(group))
+		} else {
+			group = vxlan.Group.To16()
+			if group != nil {
+				nl.NewRtAttrChild(data, nl.IFLA_VXLAN_GROUP6, []byte(group))
+			}
+		}
+	}
+
+	nl.NewRtAttrChild(data, nl.IFLA_VXLAN_TTL, nl.Uint8Attr(uint8(vxlan.TTL)))
+	nl.NewRtAttrChild(data, nl.IFLA_VXLAN_TOS, nl.Uint8Attr(uint8(vxlan.TOS)))
+	nl.NewRtAttrChild(data, nl.IFLA_VXLAN_LEARNING, boolAttr(vxlan.Learning))
+	nl.NewRtAttrChild(data, nl.IFLA_VXLAN_PROXY, boolAttr(vxlan.Proxy))
+	nl.NewRtAttrChild(data, nl.IFLA_VXLAN_RSC, boolAttr(vxlan.RSC))
+	nl.NewRtAttrChild(data, nl.IFLA_VXLAN_L2MISS, boolAttr(vxlan.L2miss))
+	nl.NewRtAttrChild(data, nl.IFLA_VXLAN_L3MISS, boolAttr(vxlan.L3miss))
+
+	if vxlan.NoAge {
+		nl.NewRtAttrChild(data, nl.IFLA_VXLAN_AGEING, nl.Uint32Attr(0))
+	} else if vxlan.Age > 0 {
+		nl.NewRtAttrChild(data, nl.IFLA_VXLAN_AGEING, nl.Uint32Attr(uint32(vxlan.Age)))
+	}
+	if vxlan.Limit > 0 {
+		nl.NewRtAttrChild(data, nl.IFLA_VXLAN_LIMIT, nl.Uint32Attr(uint32(vxlan.Limit)))
+	}
+	if vxlan.Port > 0 {
+		nl.NewRtAttrChild(data, nl.IFLA_VXLAN_PORT, nl.Uint16Attr(uint16(vxlan.Port)))
+	}
+	if vxlan.PortLow > 0 || vxlan.PortHigh > 0 {
+		pr := vxlanPortRange{uint16(vxlan.PortLow), uint16(vxlan.PortHigh)}
+
+		buf := new(bytes.Buffer)
+		binary.Write(buf, binary.BigEndian, &pr)
+
+		nl.NewRtAttrChild(data, nl.IFLA_VXLAN_PORT_RANGE, buf.Bytes())
+	}
+}
+
+// LinkAdd adds a new link device. The type and features of the device
+// are taken fromt the parameters in the link object.
+// Equivalent to: `ip link add $link`
+func LinkAdd(link Link) error {
+	// TODO: set mtu and hardware address
+	// TODO: support extra data for macvlan
+	base := link.Attrs()
+
+	if base.Name == "" {
+		return fmt.Errorf("LinkAttrs.Name cannot be empty!")
+	}
+
+	req := nl.NewNetlinkRequest(syscall.RTM_NEWLINK, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
+
+	msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
+	req.AddData(msg)
+
+	if base.ParentIndex != 0 {
+		b := make([]byte, 4)
+		native.PutUint32(b, uint32(base.ParentIndex))
+		data := nl.NewRtAttr(syscall.IFLA_LINK, b)
+		req.AddData(data)
+	} else if link.Type() == "ipvlan" {
+		return fmt.Errorf("Can't create ipvlan link without ParentIndex")
+	}
+
+	nameData := nl.NewRtAttr(syscall.IFLA_IFNAME, nl.ZeroTerminated(base.Name))
+	req.AddData(nameData)
+
+	if base.MTU > 0 {
+		mtu := nl.NewRtAttr(syscall.IFLA_MTU, nl.Uint32Attr(uint32(base.MTU)))
+		req.AddData(mtu)
+	}
+
+	linkInfo := nl.NewRtAttr(syscall.IFLA_LINKINFO, nil)
+	nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_KIND, nl.NonZeroTerminated(link.Type()))
+
+	nl.NewRtAttrChild(linkInfo, syscall.IFLA_TXQLEN, nl.Uint32Attr(base.TxQLen))
+
+	if vlan, ok := link.(*Vlan); ok {
+		b := make([]byte, 2)
+		native.PutUint16(b, uint16(vlan.VlanId))
+		data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil)
+		nl.NewRtAttrChild(data, nl.IFLA_VLAN_ID, b)
+	} else if veth, ok := link.(*Veth); ok {
+		data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil)
+		peer := nl.NewRtAttrChild(data, nl.VETH_INFO_PEER, nil)
+		nl.NewIfInfomsgChild(peer, syscall.AF_UNSPEC)
+		nl.NewRtAttrChild(peer, syscall.IFLA_IFNAME, nl.ZeroTerminated(veth.PeerName))
+		nl.NewRtAttrChild(peer, syscall.IFLA_TXQLEN, nl.Uint32Attr(base.TxQLen))
+		if base.MTU > 0 {
+			nl.NewRtAttrChild(peer, syscall.IFLA_MTU, nl.Uint32Attr(uint32(base.MTU)))
+		}
+	} else if vxlan, ok := link.(*Vxlan); ok {
+		addVxlanAttrs(vxlan, linkInfo)
+	} else if ipv, ok := link.(*IPVlan); ok {
+		data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil)
+		nl.NewRtAttrChild(data, nl.IFLA_IPVLAN_MODE, nl.Uint16Attr(uint16(ipv.Mode)))
+	}
+
+	req.AddData(linkInfo)
+
+	_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
+	if err != nil {
+		return err
+	}
+
+	ensureIndex(base)
+
+	// can't set master during create, so set it afterwards
+	if base.MasterIndex != 0 {
+		// TODO: verify MasterIndex is actually a bridge?
+		return LinkSetMasterByIndex(link, base.MasterIndex)
+	}
+	return nil
+}
+
+// LinkDel deletes link device. Either Index or Name must be set in
+// the link object for it to be deleted. The other values are ignored.
+// Equivalent to: `ip link del $link`
+func LinkDel(link Link) error {
+	base := link.Attrs()
+
+	ensureIndex(base)
+
+	req := nl.NewNetlinkRequest(syscall.RTM_DELLINK, syscall.NLM_F_ACK)
+
+	msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
+	msg.Index = int32(base.Index)
+	req.AddData(msg)
+
+	_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
+	return err
+}
+
+func linkByNameDump(name string) (Link, error) {
+	links, err := LinkList()
+	if err != nil {
+		return nil, err
+	}
+
+	for _, link := range links {
+		if link.Attrs().Name == name {
+			return link, nil
+		}
+	}
+	return nil, fmt.Errorf("Link %s not found", name)
+}
+
+// LinkByName finds a link by name and returns a pointer to the object.
+func LinkByName(name string) (Link, error) {
+	if lookupByDump {
+		return linkByNameDump(name)
+	}
+
+	req := nl.NewNetlinkRequest(syscall.RTM_GETLINK, syscall.NLM_F_ACK)
+
+	msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
+	req.AddData(msg)
+
+	nameData := nl.NewRtAttr(syscall.IFLA_IFNAME, nl.ZeroTerminated(name))
+	req.AddData(nameData)
+
+	link, err := execGetLink(req)
+	if err == syscall.EINVAL {
+		// older kernels don't support looking up via IFLA_IFNAME
+		// so fall back to dumping all links
+		lookupByDump = true
+		return linkByNameDump(name)
+	}
+
+	return link, err
+}
+
+// LinkByIndex finds a link by index and returns a pointer to the object.
+func LinkByIndex(index int) (Link, error) {
+	req := nl.NewNetlinkRequest(syscall.RTM_GETLINK, syscall.NLM_F_ACK)
+
+	msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
+	msg.Index = int32(index)
+	req.AddData(msg)
+
+	return execGetLink(req)
+}
+
+func execGetLink(req *nl.NetlinkRequest) (Link, error) {
+	msgs, err := req.Execute(syscall.NETLINK_ROUTE, 0)
+	if err != nil {
+		if errno, ok := err.(syscall.Errno); ok {
+			if errno == syscall.ENODEV {
+				return nil, fmt.Errorf("Link not found")
+			}
+		}
+		return nil, err
+	}
+
+	switch {
+	case len(msgs) == 0:
+		return nil, fmt.Errorf("Link not found")
+
+	case len(msgs) == 1:
+		return linkDeserialize(msgs[0])
+
+	default:
+		return nil, fmt.Errorf("More than one link found")
+	}
+}
+
+// linkDeserialize deserializes a raw message received from netlink into
+// a link object.
+func linkDeserialize(m []byte) (Link, error) {
+	msg := nl.DeserializeIfInfomsg(m)
+
+	attrs, err := nl.ParseRouteAttr(m[msg.Len():])
+	if err != nil {
+		return nil, err
+	}
+
+	base := LinkAttrs{Index: int(msg.Index), Flags: linkFlags(msg.Flags)}
+	var link Link
+	linkType := ""
+	for _, attr := range attrs {
+		switch attr.Attr.Type {
+		case syscall.IFLA_LINKINFO:
+			infos, err := nl.ParseRouteAttr(attr.Value)
+			if err != nil {
+				return nil, err
+			}
+			for _, info := range infos {
+				switch info.Attr.Type {
+				case nl.IFLA_INFO_KIND:
+					linkType = string(info.Value[:len(info.Value)-1])
+					switch linkType {
+					case "dummy":
+						link = &Dummy{}
+					case "bridge":
+						link = &Bridge{}
+					case "vlan":
+						link = &Vlan{}
+					case "veth":
+						link = &Veth{}
+					case "vxlan":
+						link = &Vxlan{}
+					case "ipvlan":
+						link = &IPVlan{}
+					default:
+						link = &Generic{LinkType: linkType}
+					}
+				case nl.IFLA_INFO_DATA:
+					data, err := nl.ParseRouteAttr(info.Value)
+					if err != nil {
+						return nil, err
+					}
+					switch linkType {
+					case "vlan":
+						parseVlanData(link, data)
+					case "vxlan":
+						parseVxlanData(link, data)
+					case "ipvlan":
+						parseIPVlanData(link, data)
+					}
+				}
+			}
+		case syscall.IFLA_ADDRESS:
+			var nonzero bool
+			for _, b := range attr.Value {
+				if b != 0 {
+					nonzero = true
+				}
+			}
+			if nonzero {
+				base.HardwareAddr = attr.Value[:]
+			}
+		case syscall.IFLA_IFNAME:
+			base.Name = string(attr.Value[:len(attr.Value)-1])
+		case syscall.IFLA_MTU:
+			base.MTU = int(native.Uint32(attr.Value[0:4]))
+		case syscall.IFLA_LINK:
+			base.ParentIndex = int(native.Uint32(attr.Value[0:4]))
+		case syscall.IFLA_MASTER:
+			base.MasterIndex = int(native.Uint32(attr.Value[0:4]))
+		case syscall.IFLA_TXQLEN:
+			base.TxQLen = native.Uint32(attr.Value[0:4])
+		}
+	}
+	// Links that don't have IFLA_INFO_KIND are hardware devices
+	if link == nil {
+		link = &Device{}
+	}
+	*link.Attrs() = base
+
+	return link, nil
+}
+
+// LinkList gets a list of link devices.
+// Equivalent to: `ip link show`
+func LinkList() ([]Link, error) {
+	// NOTE(vish): This duplicates functionality in net/iface_linux.go, but we need
+	//             to get the message ourselves to parse link type.
+	req := nl.NewNetlinkRequest(syscall.RTM_GETLINK, syscall.NLM_F_DUMP)
+
+	msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
+	req.AddData(msg)
+
+	msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWLINK)
+	if err != nil {
+		return nil, err
+	}
+
+	res := make([]Link, 0)
+
+	for _, m := range msgs {
+		link, err := linkDeserialize(m)
+		if err != nil {
+			return nil, err
+		}
+		res = append(res, link)
+	}
+
+	return res, nil
+}
+
+func LinkSetHairpin(link Link, mode bool) error {
+	return setProtinfoAttr(link, mode, nl.IFLA_BRPORT_MODE)
+}
+
+func LinkSetGuard(link Link, mode bool) error {
+	return setProtinfoAttr(link, mode, nl.IFLA_BRPORT_GUARD)
+}
+
+func LinkSetFastLeave(link Link, mode bool) error {
+	return setProtinfoAttr(link, mode, nl.IFLA_BRPORT_FAST_LEAVE)
+}
+
+func LinkSetLearning(link Link, mode bool) error {
+	return setProtinfoAttr(link, mode, nl.IFLA_BRPORT_LEARNING)
+}
+
+func LinkSetRootBlock(link Link, mode bool) error {
+	return setProtinfoAttr(link, mode, nl.IFLA_BRPORT_PROTECT)
+}
+
+func LinkSetFlood(link Link, mode bool) error {
+	return setProtinfoAttr(link, mode, nl.IFLA_BRPORT_UNICAST_FLOOD)
+}
+
+func setProtinfoAttr(link Link, mode bool, attr int) error {
+	base := link.Attrs()
+	ensureIndex(base)
+	req := nl.NewNetlinkRequest(syscall.RTM_SETLINK, syscall.NLM_F_ACK)
+
+	msg := nl.NewIfInfomsg(syscall.AF_BRIDGE)
+	msg.Type = syscall.RTM_SETLINK
+	msg.Flags = syscall.NLM_F_REQUEST
+	msg.Index = int32(base.Index)
+	msg.Change = nl.DEFAULT_CHANGE
+	req.AddData(msg)
+
+	br := nl.NewRtAttr(syscall.IFLA_PROTINFO|syscall.NLA_F_NESTED, nil)
+	nl.NewRtAttrChild(br, attr, boolToByte(mode))
+	req.AddData(br)
+	_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func parseVlanData(link Link, data []syscall.NetlinkRouteAttr) {
+	vlan := link.(*Vlan)
+	for _, datum := range data {
+		switch datum.Attr.Type {
+		case nl.IFLA_VLAN_ID:
+			vlan.VlanId = int(native.Uint16(datum.Value[0:2]))
+		}
+	}
+}
+
+func parseVxlanData(link Link, data []syscall.NetlinkRouteAttr) {
+	vxlan := link.(*Vxlan)
+	for _, datum := range data {
+		switch datum.Attr.Type {
+		case nl.IFLA_VXLAN_ID:
+			vxlan.VxlanId = int(native.Uint32(datum.Value[0:4]))
+		case nl.IFLA_VXLAN_LINK:
+			vxlan.VtepDevIndex = int(native.Uint32(datum.Value[0:4]))
+		case nl.IFLA_VXLAN_LOCAL:
+			vxlan.SrcAddr = net.IP(datum.Value[0:4])
+		case nl.IFLA_VXLAN_LOCAL6:
+			vxlan.SrcAddr = net.IP(datum.Value[0:16])
+		case nl.IFLA_VXLAN_GROUP:
+			vxlan.Group = net.IP(datum.Value[0:4])
+		case nl.IFLA_VXLAN_GROUP6:
+			vxlan.Group = net.IP(datum.Value[0:16])
+		case nl.IFLA_VXLAN_TTL:
+			vxlan.TTL = int(datum.Value[0])
+		case nl.IFLA_VXLAN_TOS:
+			vxlan.TOS = int(datum.Value[0])
+		case nl.IFLA_VXLAN_LEARNING:
+			vxlan.Learning = int8(datum.Value[0]) != 0
+		case nl.IFLA_VXLAN_PROXY:
+			vxlan.Proxy = int8(datum.Value[0]) != 0
+		case nl.IFLA_VXLAN_RSC:
+			vxlan.RSC = int8(datum.Value[0]) != 0
+		case nl.IFLA_VXLAN_L2MISS:
+			vxlan.L2miss = int8(datum.Value[0]) != 0
+		case nl.IFLA_VXLAN_L3MISS:
+			vxlan.L3miss = int8(datum.Value[0]) != 0
+		case nl.IFLA_VXLAN_AGEING:
+			vxlan.Age = int(native.Uint32(datum.Value[0:4]))
+			vxlan.NoAge = vxlan.Age == 0
+		case nl.IFLA_VXLAN_LIMIT:
+			vxlan.Limit = int(native.Uint32(datum.Value[0:4]))
+		case nl.IFLA_VXLAN_PORT:
+			vxlan.Port = int(native.Uint16(datum.Value[0:2]))
+		case nl.IFLA_VXLAN_PORT_RANGE:
+			buf := bytes.NewBuffer(datum.Value[0:4])
+			var pr vxlanPortRange
+			if binary.Read(buf, binary.BigEndian, &pr) != nil {
+				vxlan.PortLow = int(pr.Lo)
+				vxlan.PortHigh = int(pr.Hi)
+			}
+		}
+	}
+}
+
+func parseIPVlanData(link Link, data []syscall.NetlinkRouteAttr) {
+	ipv := link.(*IPVlan)
+	for _, datum := range data {
+		if datum.Attr.Type == nl.IFLA_IPVLAN_MODE {
+			ipv.Mode = IPVlanMode(native.Uint32(datum.Value[0:4]))
+			return
+		}
+	}
+}
+
+// copied from pkg/net_linux.go
+func linkFlags(rawFlags uint32) net.Flags {
+	var f net.Flags
+	if rawFlags&syscall.IFF_UP != 0 {
+		f |= net.FlagUp
+	}
+	if rawFlags&syscall.IFF_BROADCAST != 0 {
+		f |= net.FlagBroadcast
+	}
+	if rawFlags&syscall.IFF_LOOPBACK != 0 {
+		f |= net.FlagLoopback
+	}
+	if rawFlags&syscall.IFF_POINTOPOINT != 0 {
+		f |= net.FlagPointToPoint
+	}
+	if rawFlags&syscall.IFF_MULTICAST != 0 {
+		f |= net.FlagMulticast
+	}
+	return f
+}

+ 531 - 0
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/link_test.go

@@ -0,0 +1,531 @@
+package netlink
+
+import (
+	"bytes"
+	"net"
+	"testing"
+
+	"github.com/vishvananda/netns"
+)
+
+const testTxQLen uint32 = 100
+
+func testLinkAddDel(t *testing.T, link Link) {
+	links, err := LinkList()
+	if err != nil {
+		t.Fatal(err)
+	}
+	num := len(links)
+
+	if err := LinkAdd(link); err != nil {
+		t.Fatal(err)
+	}
+
+	base := link.Attrs()
+
+	result, err := LinkByName(base.Name)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	rBase := result.Attrs()
+
+	if vlan, ok := link.(*Vlan); ok {
+		other, ok := result.(*Vlan)
+		if !ok {
+			t.Fatal("Result of create is not a vlan")
+		}
+		if vlan.VlanId != other.VlanId {
+			t.Fatal("Link.VlanId id doesn't match")
+		}
+	}
+
+	if rBase.ParentIndex == 0 && base.ParentIndex != 0 {
+		t.Fatal("Created link doesn't have a Parent but it should")
+	} else if rBase.ParentIndex != 0 && base.ParentIndex == 0 {
+		t.Fatal("Created link has a Parent but it shouldn't")
+	} else if rBase.ParentIndex != 0 && base.ParentIndex != 0 {
+		if rBase.ParentIndex != base.ParentIndex {
+			t.Fatal("Link.ParentIndex doesn't match")
+		}
+	}
+
+	if veth, ok := link.(*Veth); ok {
+		if veth.TxQLen != testTxQLen {
+			t.Fatalf("TxQLen is %d, should be %d", veth.TxQLen, testTxQLen)
+		}
+		if rBase.MTU != base.MTU {
+			t.Fatalf("MTU is %d, should be %d", rBase.MTU, base.MTU)
+		}
+
+		if veth.PeerName != "" {
+			var peer *Veth
+			other, err := LinkByName(veth.PeerName)
+			if err != nil {
+				t.Fatalf("Peer %s not created", veth.PeerName)
+			}
+			if peer, ok = other.(*Veth); !ok {
+				t.Fatalf("Peer %s is incorrect type", veth.PeerName)
+			}
+			if peer.TxQLen != testTxQLen {
+				t.Fatalf("TxQLen of peer is %d, should be %d", peer.TxQLen, testTxQLen)
+			}
+		}
+	}
+
+	if vxlan, ok := link.(*Vxlan); ok {
+		other, ok := result.(*Vxlan)
+		if !ok {
+			t.Fatal("Result of create is not a vxlan")
+		}
+		compareVxlan(t, vxlan, other)
+	}
+
+	if ipv, ok := link.(*IPVlan); ok {
+		other, ok := result.(*IPVlan)
+		if !ok {
+			t.Fatal("Result of create is not a ipvlan")
+		}
+		if ipv.Mode != other.Mode {
+			t.Fatalf("Got unexpected mode: %d, expected: %d", other.Mode, ipv.Mode)
+		}
+	}
+
+	if err = LinkDel(link); err != nil {
+		t.Fatal(err)
+	}
+
+	links, err = LinkList()
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if len(links) != num {
+		t.Fatal("Link not removed properly")
+	}
+}
+
+func compareVxlan(t *testing.T, expected, actual *Vxlan) {
+
+	if actual.VxlanId != expected.VxlanId {
+		t.Fatal("Vxlan.VxlanId doesn't match")
+	}
+	if expected.SrcAddr != nil && !actual.SrcAddr.Equal(expected.SrcAddr) {
+		t.Fatal("Vxlan.SrcAddr doesn't match")
+	}
+	if expected.Group != nil && !actual.Group.Equal(expected.Group) {
+		t.Fatal("Vxlan.Group doesn't match")
+	}
+	if expected.TTL != -1 && actual.TTL != expected.TTL {
+		t.Fatal("Vxlan.TTL doesn't match")
+	}
+	if expected.TOS != -1 && actual.TOS != expected.TOS {
+		t.Fatal("Vxlan.TOS doesn't match")
+	}
+	if actual.Learning != expected.Learning {
+		t.Fatal("Vxlan.Learning doesn't match")
+	}
+	if actual.Proxy != expected.Proxy {
+		t.Fatal("Vxlan.Proxy doesn't match")
+	}
+	if actual.RSC != expected.RSC {
+		t.Fatal("Vxlan.RSC doesn't match")
+	}
+	if actual.L2miss != expected.L2miss {
+		t.Fatal("Vxlan.L2miss doesn't match")
+	}
+	if actual.L3miss != expected.L3miss {
+		t.Fatal("Vxlan.L3miss doesn't match")
+	}
+	if expected.NoAge {
+		if !actual.NoAge {
+			t.Fatal("Vxlan.NoAge doesn't match")
+		}
+	} else if expected.Age > 0 && actual.Age != expected.Age {
+		t.Fatal("Vxlan.Age doesn't match")
+	}
+	if expected.Limit > 0 && actual.Limit != expected.Limit {
+		t.Fatal("Vxlan.Limit doesn't match")
+	}
+	if expected.Port > 0 && actual.Port != expected.Port {
+		t.Fatal("Vxlan.Port doesn't match")
+	}
+	if expected.PortLow > 0 || expected.PortHigh > 0 {
+		if actual.PortLow != expected.PortLow {
+			t.Fatal("Vxlan.PortLow doesn't match")
+		}
+		if actual.PortHigh != expected.PortHigh {
+			t.Fatal("Vxlan.PortHigh doesn't match")
+		}
+	}
+}
+
+func TestLinkAddDelDummy(t *testing.T) {
+	tearDown := setUpNetlinkTest(t)
+	defer tearDown()
+
+	testLinkAddDel(t, &Dummy{LinkAttrs{Name: "foo"}})
+}
+
+func TestLinkAddDelBridge(t *testing.T) {
+	tearDown := setUpNetlinkTest(t)
+	defer tearDown()
+
+	testLinkAddDel(t, &Bridge{LinkAttrs{Name: "foo", MTU: 1400}})
+}
+
+func TestLinkAddDelVlan(t *testing.T) {
+	tearDown := setUpNetlinkTest(t)
+	defer tearDown()
+
+	parent := &Dummy{LinkAttrs{Name: "foo"}}
+	if err := LinkAdd(parent); err != nil {
+		t.Fatal(err)
+	}
+
+	testLinkAddDel(t, &Vlan{LinkAttrs{Name: "bar", ParentIndex: parent.Attrs().Index}, 900})
+
+	if err := LinkDel(parent); err != nil {
+		t.Fatal(err)
+	}
+}
+
+func TestLinkAddDelMacvlan(t *testing.T) {
+	tearDown := setUpNetlinkTest(t)
+	defer tearDown()
+
+	parent := &Dummy{LinkAttrs{Name: "foo"}}
+	if err := LinkAdd(parent); err != nil {
+		t.Fatal(err)
+	}
+
+	testLinkAddDel(t, &Macvlan{LinkAttrs{Name: "bar", ParentIndex: parent.Attrs().Index}})
+
+	if err := LinkDel(parent); err != nil {
+		t.Fatal(err)
+	}
+}
+
+func TestLinkAddDelVeth(t *testing.T) {
+	tearDown := setUpNetlinkTest(t)
+	defer tearDown()
+
+	testLinkAddDel(t, &Veth{LinkAttrs{Name: "foo", TxQLen: testTxQLen, MTU: 1400}, "bar"})
+}
+
+func TestLinkAddDelBridgeMaster(t *testing.T) {
+	tearDown := setUpNetlinkTest(t)
+	defer tearDown()
+
+	master := &Bridge{LinkAttrs{Name: "foo"}}
+	if err := LinkAdd(master); err != nil {
+		t.Fatal(err)
+	}
+	testLinkAddDel(t, &Dummy{LinkAttrs{Name: "bar", MasterIndex: master.Attrs().Index}})
+
+	if err := LinkDel(master); err != nil {
+		t.Fatal(err)
+	}
+}
+
+func TestLinkSetUnsetResetMaster(t *testing.T) {
+	tearDown := setUpNetlinkTest(t)
+	defer tearDown()
+
+	master := &Bridge{LinkAttrs{Name: "foo"}}
+	if err := LinkAdd(master); err != nil {
+		t.Fatal(err)
+	}
+
+	newmaster := &Bridge{LinkAttrs{Name: "bar"}}
+	if err := LinkAdd(newmaster); err != nil {
+		t.Fatal(err)
+	}
+
+	slave := &Dummy{LinkAttrs{Name: "baz"}}
+	if err := LinkAdd(slave); err != nil {
+		t.Fatal(err)
+	}
+
+	if err := LinkSetMaster(slave, master); err != nil {
+		t.Fatal(err)
+	}
+
+	link, err := LinkByName("baz")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if link.Attrs().MasterIndex != master.Attrs().Index {
+		t.Fatal("Master not set properly")
+	}
+
+	if err := LinkSetMaster(slave, newmaster); err != nil {
+		t.Fatal(err)
+	}
+
+	link, err = LinkByName("baz")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if link.Attrs().MasterIndex != newmaster.Attrs().Index {
+		t.Fatal("Master not reset properly")
+	}
+
+	if err := LinkSetMaster(slave, nil); err != nil {
+		t.Fatal(err)
+	}
+
+	link, err = LinkByName("baz")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if link.Attrs().MasterIndex != 0 {
+		t.Fatal("Master not unset properly")
+	}
+	if err := LinkDel(slave); err != nil {
+		t.Fatal(err)
+	}
+
+	if err := LinkDel(newmaster); err != nil {
+		t.Fatal(err)
+	}
+
+	if err := LinkDel(master); err != nil {
+		t.Fatal(err)
+	}
+}
+
+func TestLinkSetNs(t *testing.T) {
+	tearDown := setUpNetlinkTest(t)
+	defer tearDown()
+
+	basens, err := netns.Get()
+	if err != nil {
+		t.Fatal("Failed to get basens")
+	}
+	defer basens.Close()
+
+	newns, err := netns.New()
+	if err != nil {
+		t.Fatal("Failed to create newns")
+	}
+	defer newns.Close()
+
+	link := &Veth{LinkAttrs{Name: "foo"}, "bar"}
+	if err := LinkAdd(link); err != nil {
+		t.Fatal(err)
+	}
+
+	peer, err := LinkByName("bar")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	LinkSetNsFd(peer, int(basens))
+	if err != nil {
+		t.Fatal("Failed to set newns for link")
+	}
+
+	_, err = LinkByName("bar")
+	if err == nil {
+		t.Fatal("Link bar is still in newns")
+	}
+
+	err = netns.Set(basens)
+	if err != nil {
+		t.Fatal("Failed to set basens")
+	}
+
+	peer, err = LinkByName("bar")
+	if err != nil {
+		t.Fatal("Link is not in basens")
+	}
+
+	if err := LinkDel(peer); err != nil {
+		t.Fatal(err)
+	}
+
+	err = netns.Set(newns)
+	if err != nil {
+		t.Fatal("Failed to set newns")
+	}
+
+	_, err = LinkByName("foo")
+	if err == nil {
+		t.Fatal("Other half of veth pair not deleted")
+	}
+
+}
+
+func TestLinkAddDelVxlan(t *testing.T) {
+	tearDown := setUpNetlinkTest(t)
+	defer tearDown()
+
+	parent := &Dummy{
+		LinkAttrs{Name: "foo"},
+	}
+	if err := LinkAdd(parent); err != nil {
+		t.Fatal(err)
+	}
+
+	vxlan := Vxlan{
+		LinkAttrs: LinkAttrs{
+			Name: "bar",
+		},
+		VxlanId:      10,
+		VtepDevIndex: parent.Index,
+		Learning:     true,
+		L2miss:       true,
+		L3miss:       true,
+	}
+
+	testLinkAddDel(t, &vxlan)
+	if err := LinkDel(parent); err != nil {
+		t.Fatal(err)
+	}
+}
+
+func TestLinkAddDelIPVlanL2(t *testing.T) {
+	tearDown := setUpNetlinkTest(t)
+	defer tearDown()
+	parent := &Dummy{LinkAttrs{Name: "foo"}}
+	if err := LinkAdd(parent); err != nil {
+		t.Fatal(err)
+	}
+
+	ipv := IPVlan{
+		LinkAttrs: LinkAttrs{
+			Name:        "bar",
+			ParentIndex: parent.Index,
+		},
+		Mode: IPVLAN_MODE_L2,
+	}
+
+	testLinkAddDel(t, &ipv)
+}
+
+func TestLinkAddDelIPVlanL3(t *testing.T) {
+	tearDown := setUpNetlinkTest(t)
+	defer tearDown()
+	parent := &Dummy{LinkAttrs{Name: "foo"}}
+	if err := LinkAdd(parent); err != nil {
+		t.Fatal(err)
+	}
+
+	ipv := IPVlan{
+		LinkAttrs: LinkAttrs{
+			Name:        "bar",
+			ParentIndex: parent.Index,
+		},
+		Mode: IPVLAN_MODE_L3,
+	}
+
+	testLinkAddDel(t, &ipv)
+}
+
+func TestLinkAddDelIPVlanNoParent(t *testing.T) {
+	tearDown := setUpNetlinkTest(t)
+	defer tearDown()
+
+	ipv := IPVlan{
+		LinkAttrs: LinkAttrs{
+			Name: "bar",
+		},
+		Mode: IPVLAN_MODE_L3,
+	}
+	err := LinkAdd(&ipv)
+	if err == nil {
+		t.Fatal("Add should fail if ipvlan creating without ParentIndex")
+	}
+	if err.Error() != "Can't create ipvlan link without ParentIndex" {
+		t.Fatalf("Error should be about missing ParentIndex, got %q", err)
+	}
+}
+
+func TestLinkByIndex(t *testing.T) {
+	tearDown := setUpNetlinkTest(t)
+	defer tearDown()
+
+	dummy := &Dummy{LinkAttrs{Name: "dummy"}}
+	if err := LinkAdd(dummy); err != nil {
+		t.Fatal(err)
+	}
+
+	found, err := LinkByIndex(dummy.Index)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if found.Attrs().Index != dummy.Attrs().Index {
+		t.Fatalf("Indices don't match: %v != %v", found.Attrs().Index, dummy.Attrs().Index)
+	}
+
+	LinkDel(dummy)
+
+	// test not found
+	_, err = LinkByIndex(dummy.Attrs().Index)
+	if err == nil {
+		t.Fatalf("LinkByIndex(%v) found deleted link", err)
+	}
+}
+
+func TestLinkSet(t *testing.T) {
+	tearDown := setUpNetlinkTest(t)
+	defer tearDown()
+
+	iface := &Dummy{LinkAttrs{Name: "foo"}}
+	if err := LinkAdd(iface); err != nil {
+		t.Fatal(err)
+	}
+
+	link, err := LinkByName("foo")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	err = LinkSetName(link, "bar")
+	if err != nil {
+		t.Fatalf("Could not change interface name: %v", err)
+	}
+
+	link, err = LinkByName("bar")
+	if err != nil {
+		t.Fatalf("Interface name not changed: %v", err)
+	}
+
+	err = LinkSetMTU(link, 1400)
+	if err != nil {
+		t.Fatalf("Could not set MTU: %v", err)
+	}
+
+	link, err = LinkByName("bar")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if link.Attrs().MTU != 1400 {
+		t.Fatal("MTU not changed!")
+	}
+
+	addr, err := net.ParseMAC("00:12:34:56:78:AB")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	err = LinkSetHardwareAddr(link, addr)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	link, err = LinkByName("bar")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if !bytes.Equal(link.Attrs().HardwareAddr, addr) {
+		t.Fatalf("hardware address not changed!")
+	}
+}

+ 22 - 0
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/neigh.go

@@ -0,0 +1,22 @@
+package netlink
+
+import (
+	"fmt"
+	"net"
+)
+
+// Neigh represents a link layer neighbor from netlink.
+type Neigh struct {
+	LinkIndex    int
+	Family       int
+	State        int
+	Type         int
+	Flags        int
+	IP           net.IP
+	HardwareAddr net.HardwareAddr
+}
+
+// String returns $ip/$hwaddr $label
+func (neigh *Neigh) String() string {
+	return fmt.Sprintf("%s %s", neigh.IP, neigh.HardwareAddr)
+}

+ 189 - 0
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/neigh_linux.go

@@ -0,0 +1,189 @@
+package netlink
+
+import (
+	"net"
+	"syscall"
+	"unsafe"
+
+	"github.com/vishvananda/netlink/nl"
+)
+
+const (
+	NDA_UNSPEC = iota
+	NDA_DST
+	NDA_LLADDR
+	NDA_CACHEINFO
+	NDA_PROBES
+	NDA_VLAN
+	NDA_PORT
+	NDA_VNI
+	NDA_IFINDEX
+	NDA_MAX = NDA_IFINDEX
+)
+
+// Neighbor Cache Entry States.
+const (
+	NUD_NONE       = 0x00
+	NUD_INCOMPLETE = 0x01
+	NUD_REACHABLE  = 0x02
+	NUD_STALE      = 0x04
+	NUD_DELAY      = 0x08
+	NUD_PROBE      = 0x10
+	NUD_FAILED     = 0x20
+	NUD_NOARP      = 0x40
+	NUD_PERMANENT  = 0x80
+)
+
+// Neighbor Flags
+const (
+	NTF_USE    = 0x01
+	NTF_SELF   = 0x02
+	NTF_MASTER = 0x04
+	NTF_PROXY  = 0x08
+	NTF_ROUTER = 0x80
+)
+
+type Ndmsg struct {
+	Family uint8
+	Index  uint32
+	State  uint16
+	Flags  uint8
+	Type   uint8
+}
+
+func deserializeNdmsg(b []byte) *Ndmsg {
+	var dummy Ndmsg
+	return (*Ndmsg)(unsafe.Pointer(&b[0:unsafe.Sizeof(dummy)][0]))
+}
+
+func (msg *Ndmsg) Serialize() []byte {
+	return (*(*[unsafe.Sizeof(*msg)]byte)(unsafe.Pointer(msg)))[:]
+}
+
+func (msg *Ndmsg) Len() int {
+	return int(unsafe.Sizeof(*msg))
+}
+
+// NeighAdd will add an IP to MAC mapping to the ARP table
+// Equivalent to: `ip neigh add ....`
+func NeighAdd(neigh *Neigh) error {
+	return neighAdd(neigh, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL)
+}
+
+// NeighAdd will add or replace an IP to MAC mapping to the ARP table
+// Equivalent to: `ip neigh replace....`
+func NeighSet(neigh *Neigh) error {
+	return neighAdd(neigh, syscall.NLM_F_CREATE)
+}
+
+// NeighAppend will append an entry to FDB
+// Equivalent to: `bridge fdb append...`
+func NeighAppend(neigh *Neigh) error {
+	return neighAdd(neigh, syscall.NLM_F_CREATE|syscall.NLM_F_APPEND)
+}
+
+func neighAdd(neigh *Neigh, mode int) error {
+	req := nl.NewNetlinkRequest(syscall.RTM_NEWNEIGH, mode|syscall.NLM_F_ACK)
+	return neighHandle(neigh, req)
+}
+
+// NeighDel will delete an IP address from a link device.
+// Equivalent to: `ip addr del $addr dev $link`
+func NeighDel(neigh *Neigh) error {
+	req := nl.NewNetlinkRequest(syscall.RTM_DELNEIGH, syscall.NLM_F_ACK)
+	return neighHandle(neigh, req)
+}
+
+func neighHandle(neigh *Neigh, req *nl.NetlinkRequest) error {
+	var family int
+	if neigh.Family > 0 {
+		family = neigh.Family
+	} else {
+		family = nl.GetIPFamily(neigh.IP)
+	}
+
+	msg := Ndmsg{
+		Family: uint8(family),
+		Index:  uint32(neigh.LinkIndex),
+		State:  uint16(neigh.State),
+		Type:   uint8(neigh.Type),
+		Flags:  uint8(neigh.Flags),
+	}
+	req.AddData(&msg)
+
+	ipData := neigh.IP.To4()
+	if ipData == nil {
+		ipData = neigh.IP.To16()
+	}
+
+	dstData := nl.NewRtAttr(NDA_DST, ipData)
+	req.AddData(dstData)
+
+	hwData := nl.NewRtAttr(NDA_LLADDR, []byte(neigh.HardwareAddr))
+	req.AddData(hwData)
+
+	_, err := req.Execute(syscall.NETLINK_ROUTE, 0)
+	return err
+}
+
+// NeighList gets a list of IP-MAC mappings in the system (ARP table).
+// Equivalent to: `ip neighbor show`.
+// The list can be filtered by link and ip family.
+func NeighList(linkIndex, family int) ([]Neigh, error) {
+	req := nl.NewNetlinkRequest(syscall.RTM_GETNEIGH, syscall.NLM_F_DUMP)
+	msg := Ndmsg{
+		Family: uint8(family),
+	}
+	req.AddData(&msg)
+
+	msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWNEIGH)
+	if err != nil {
+		return nil, err
+	}
+
+	res := make([]Neigh, 0)
+	for _, m := range msgs {
+		ndm := deserializeNdmsg(m)
+		if linkIndex != 0 && int(ndm.Index) != linkIndex {
+			// Ignore messages from other interfaces
+			continue
+		}
+
+		neigh, err := NeighDeserialize(m)
+		if err != nil {
+			continue
+		}
+
+		res = append(res, *neigh)
+	}
+
+	return res, nil
+}
+
+func NeighDeserialize(m []byte) (*Neigh, error) {
+	msg := deserializeNdmsg(m)
+
+	neigh := Neigh{
+		LinkIndex: int(msg.Index),
+		Family:    int(msg.Family),
+		State:     int(msg.State),
+		Type:      int(msg.Type),
+		Flags:     int(msg.Flags),
+	}
+
+	attrs, err := nl.ParseRouteAttr(m[msg.Len():])
+	if err != nil {
+		return nil, err
+	}
+
+	for _, attr := range attrs {
+		switch attr.Attr.Type {
+		case NDA_DST:
+			neigh.IP = net.IP(attr.Value)
+		case NDA_LLADDR:
+			neigh.HardwareAddr = net.HardwareAddr(attr.Value)
+		}
+	}
+
+	return &neigh, nil
+}

+ 104 - 0
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/neigh_test.go

@@ -0,0 +1,104 @@
+package netlink
+
+import (
+	"net"
+	"testing"
+)
+
+type arpEntry struct {
+	ip  net.IP
+	mac net.HardwareAddr
+}
+
+func parseMAC(s string) net.HardwareAddr {
+	m, err := net.ParseMAC(s)
+	if err != nil {
+		panic(err)
+	}
+	return m
+}
+
+func dumpContains(dump []Neigh, e arpEntry) bool {
+	for _, n := range dump {
+		if n.IP.Equal(e.ip) && (n.State&NUD_INCOMPLETE) == 0 {
+			return true
+		}
+	}
+	return false
+}
+
+func TestNeighAddDel(t *testing.T) {
+	tearDown := setUpNetlinkTest(t)
+	defer tearDown()
+
+	dummy := Dummy{LinkAttrs{Name: "neigh0"}}
+	if err := LinkAdd(&dummy); err != nil {
+		t.Fatal(err)
+	}
+
+	ensureIndex(dummy.Attrs())
+
+	arpTable := []arpEntry{
+		{net.ParseIP("10.99.0.1"), parseMAC("aa:bb:cc:dd:00:01")},
+		{net.ParseIP("10.99.0.2"), parseMAC("aa:bb:cc:dd:00:02")},
+		{net.ParseIP("10.99.0.3"), parseMAC("aa:bb:cc:dd:00:03")},
+		{net.ParseIP("10.99.0.4"), parseMAC("aa:bb:cc:dd:00:04")},
+		{net.ParseIP("10.99.0.5"), parseMAC("aa:bb:cc:dd:00:05")},
+	}
+
+	// Add the arpTable
+	for _, entry := range arpTable {
+		err := NeighAdd(&Neigh{
+			LinkIndex:    dummy.Index,
+			State:        NUD_REACHABLE,
+			IP:           entry.ip,
+			HardwareAddr: entry.mac,
+		})
+
+		if err != nil {
+			t.Errorf("Failed to NeighAdd: %v", err)
+		}
+	}
+
+	// Dump and see that all added entries are there
+	dump, err := NeighList(dummy.Index, 0)
+	if err != nil {
+		t.Errorf("Failed to NeighList: %v", err)
+	}
+
+	for _, entry := range arpTable {
+		if !dumpContains(dump, entry) {
+			t.Errorf("Dump does not contain: %v", entry)
+		}
+	}
+
+	// Delete the arpTable
+	for _, entry := range arpTable {
+		err := NeighDel(&Neigh{
+			LinkIndex:    dummy.Index,
+			IP:           entry.ip,
+			HardwareAddr: entry.mac,
+		})
+
+		if err != nil {
+			t.Errorf("Failed to NeighDel: %v", err)
+		}
+	}
+
+	// TODO: seems not working because of cache
+	//// Dump and see that none of deleted entries are there
+	//dump, err = NeighList(dummy.Index, 0)
+	//if err != nil {
+	//t.Errorf("Failed to NeighList: %v", err)
+	//}
+
+	//for _, entry := range arpTable {
+	//if dumpContains(dump, entry) {
+	//t.Errorf("Dump contains: %v", entry)
+	//}
+	//}
+
+	if err := LinkDel(&dummy); err != nil {
+		t.Fatal(err)
+	}
+}

+ 39 - 0
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/netlink.go

@@ -0,0 +1,39 @@
+// Package netlink provides a simple library for netlink. Netlink is
+// the interface a user-space program in linux uses to communicate with
+// the kernel. It can be used to add and remove interfaces, set up ip
+// addresses and routes, and confiugre ipsec. Netlink communication
+// requires elevated privileges, so in most cases this code needs to
+// be run as root. The low level primitives for netlink are contained
+// in the nl subpackage. This package attempts to provide a high-level
+// interface that is loosly modeled on the iproute2 cli.
+package netlink
+
+import (
+	"net"
+
+	"github.com/vishvananda/netlink/nl"
+)
+
+const (
+	// Family type definitions
+	FAMILY_ALL = nl.FAMILY_ALL
+	FAMILY_V4  = nl.FAMILY_V4
+	FAMILY_V6  = nl.FAMILY_V6
+)
+
+// ParseIPNet parses a string in ip/net format and returns a net.IPNet.
+// This is valuable because addresses in netlink are often IPNets and
+// ParseCIDR returns an IPNet with the IP part set to the base IP of the
+// range.
+func ParseIPNet(s string) (*net.IPNet, error) {
+	ip, ipNet, err := net.ParseCIDR(s)
+	if err != nil {
+		return nil, err
+	}
+	return &net.IPNet{IP: ip, Mask: ipNet.Mask}, nil
+}
+
+// NewIPNet generates an IPNet from an ip address using a netmask of 32.
+func NewIPNet(ip net.IP) *net.IPNet {
+	return &net.IPNet{IP: ip, Mask: net.CIDRMask(32, 32)}
+}

+ 34 - 0
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/netlink_test.go

@@ -0,0 +1,34 @@
+package netlink
+
+import (
+	"log"
+	"os"
+	"runtime"
+	"testing"
+
+	"github.com/vishvananda/netns"
+)
+
+type tearDownNetlinkTest func()
+
+func setUpNetlinkTest(t *testing.T) tearDownNetlinkTest {
+	if os.Getuid() != 0 {
+		msg := "Skipped test because it requires root privileges."
+		log.Printf(msg)
+		t.Skip(msg)
+	}
+
+	// new temporary namespace so we don't pollute the host
+	// lock thread since the namespace is thread local
+	runtime.LockOSThread()
+	var err error
+	ns, err := netns.New()
+	if err != nil {
+		t.Fatal("Failed to create newns", ns)
+	}
+
+	return func() {
+		ns.Close()
+		runtime.UnlockOSThread()
+	}
+}

+ 143 - 0
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/netlink_unspecified.go

@@ -0,0 +1,143 @@
+// +build !linux
+
+package netlink
+
+import (
+	"errors"
+)
+
+var (
+	ErrNotImplemented = errors.New("not implemented")
+)
+
+func LinkSetUp(link *Link) error {
+	return ErrNotImplemented
+}
+
+func LinkSetDown(link *Link) error {
+	return ErrNotImplemented
+}
+
+func LinkSetMTU(link *Link, mtu int) error {
+	return ErrNotImplemented
+}
+
+func LinkSetMaster(link *Link, master *Link) error {
+	return ErrNotImplemented
+}
+
+func LinkSetNsPid(link *Link, nspid int) error {
+	return ErrNotImplemented
+}
+
+func LinkSetNsFd(link *Link, fd int) error {
+	return ErrNotImplemented
+}
+
+func LinkAdd(link *Link) error {
+	return ErrNotImplemented
+}
+
+func LinkDel(link *Link) error {
+	return ErrNotImplemented
+}
+
+func SetHairpin(link Link, mode bool) error {
+	return ErrNotImplemented
+}
+
+func SetGuard(link Link, mode bool) error {
+	return ErrNotImplemented
+}
+
+func SetFastLeave(link Link, mode bool) error {
+	return ErrNotImplemented
+}
+
+func SetLearning(link Link, mode bool) error {
+	return ErrNotImplemented
+}
+
+func SetRootBlock(link Link, mode bool) error {
+	return ErrNotImplemented
+}
+
+func SetFlood(link Link, mode bool) error {
+	return ErrNotImplemented
+}
+
+func LinkList() ([]Link, error) {
+	return nil, ErrNotImplemented
+}
+
+func AddrAdd(link *Link, addr *Addr) error {
+	return ErrNotImplemented
+}
+
+func AddrDel(link *Link, addr *Addr) error {
+	return ErrNotImplemented
+}
+
+func AddrList(link *Link, family int) ([]Addr, error) {
+	return nil, ErrNotImplemented
+}
+
+func RouteAdd(route *Route) error {
+	return ErrNotImplemented
+}
+
+func RouteDel(route *Route) error {
+	return ErrNotImplemented
+}
+
+func RouteList(link *Link, family int) ([]Route, error) {
+	return nil, ErrNotImplemented
+}
+
+func XfrmPolicyAdd(policy *XfrmPolicy) error {
+	return ErrNotImplemented
+}
+
+func XfrmPolicyDel(policy *XfrmPolicy) error {
+	return ErrNotImplemented
+}
+
+func XfrmPolicyList(family int) ([]XfrmPolicy, error) {
+	return nil, ErrNotImplemented
+}
+
+func XfrmStateAdd(policy *XfrmState) error {
+	return ErrNotImplemented
+}
+
+func XfrmStateDel(policy *XfrmState) error {
+	return ErrNotImplemented
+}
+
+func XfrmStateList(family int) ([]XfrmState, error) {
+	return nil, ErrNotImplemented
+}
+
+func NeighAdd(neigh *Neigh) error {
+	return ErrNotImplemented
+}
+
+func NeighSet(neigh *Neigh) error {
+	return ErrNotImplemented
+}
+
+func NeighAppend(neigh *Neigh) error {
+	return ErrNotImplemented
+}
+
+func NeighDel(neigh *Neigh) error {
+	return ErrNotImplemented
+}
+
+func NeighList(linkIndex, family int) ([]Neigh, error) {
+	return nil, ErrNotImplemented
+}
+
+func NeighDeserialize(m []byte) (*Ndmsg, *Neigh, error) {
+	return nil, nil, ErrNotImplemented
+}

+ 47 - 0
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/addr_linux.go

@@ -0,0 +1,47 @@
+package nl
+
+import (
+	"syscall"
+	"unsafe"
+)
+
+type IfAddrmsg struct {
+	syscall.IfAddrmsg
+}
+
+func NewIfAddrmsg(family int) *IfAddrmsg {
+	return &IfAddrmsg{
+		IfAddrmsg: syscall.IfAddrmsg{
+			Family: uint8(family),
+		},
+	}
+}
+
+// struct ifaddrmsg {
+//   __u8    ifa_family;
+//   __u8    ifa_prefixlen;  /* The prefix length    */
+//   __u8    ifa_flags;  /* Flags      */
+//   __u8    ifa_scope;  /* Address scope    */
+//   __u32   ifa_index;  /* Link index     */
+// };
+
+// type IfAddrmsg struct {
+// 	Family    uint8
+// 	Prefixlen uint8
+// 	Flags     uint8
+// 	Scope     uint8
+// 	Index     uint32
+// }
+// SizeofIfAddrmsg     = 0x8
+
+func DeserializeIfAddrmsg(b []byte) *IfAddrmsg {
+	return (*IfAddrmsg)(unsafe.Pointer(&b[0:syscall.SizeofIfAddrmsg][0]))
+}
+
+func (msg *IfAddrmsg) Serialize() []byte {
+	return (*(*[syscall.SizeofIfAddrmsg]byte)(unsafe.Pointer(msg)))[:]
+}
+
+func (msg *IfAddrmsg) Len() int {
+	return syscall.SizeofIfAddrmsg
+}

+ 39 - 0
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/addr_linux_test.go

@@ -0,0 +1,39 @@
+package nl
+
+import (
+	"bytes"
+	"crypto/rand"
+	"encoding/binary"
+	"syscall"
+	"testing"
+)
+
+func (msg *IfAddrmsg) write(b []byte) {
+	native := NativeEndian()
+	b[0] = msg.Family
+	b[1] = msg.Prefixlen
+	b[2] = msg.Flags
+	b[3] = msg.Scope
+	native.PutUint32(b[4:8], msg.Index)
+}
+
+func (msg *IfAddrmsg) serializeSafe() []byte {
+	len := syscall.SizeofIfAddrmsg
+	b := make([]byte, len)
+	msg.write(b)
+	return b
+}
+
+func deserializeIfAddrmsgSafe(b []byte) *IfAddrmsg {
+	var msg = IfAddrmsg{}
+	binary.Read(bytes.NewReader(b[0:syscall.SizeofIfAddrmsg]), NativeEndian(), &msg)
+	return &msg
+}
+
+func TestIfAddrmsgDeserializeSerialize(t *testing.T) {
+	var orig = make([]byte, syscall.SizeofIfAddrmsg)
+	rand.Read(orig)
+	safemsg := deserializeIfAddrmsgSafe(orig)
+	msg := DeserializeIfAddrmsg(orig)
+	testDeserializeSerialize(t, orig, safemsg, msg)
+}

+ 81 - 0
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/link_linux.go

@@ -0,0 +1,81 @@
+package nl
+
+const (
+	DEFAULT_CHANGE = 0xFFFFFFFF
+)
+
+const (
+	IFLA_INFO_UNSPEC = iota
+	IFLA_INFO_KIND
+	IFLA_INFO_DATA
+	IFLA_INFO_XSTATS
+	IFLA_INFO_MAX = IFLA_INFO_XSTATS
+)
+
+const (
+	IFLA_VLAN_UNSPEC = iota
+	IFLA_VLAN_ID
+	IFLA_VLAN_FLAGS
+	IFLA_VLAN_EGRESS_QOS
+	IFLA_VLAN_INGRESS_QOS
+	IFLA_VLAN_PROTOCOL
+	IFLA_VLAN_MAX = IFLA_VLAN_PROTOCOL
+)
+
+const (
+	VETH_INFO_UNSPEC = iota
+	VETH_INFO_PEER
+	VETH_INFO_MAX = VETH_INFO_PEER
+)
+
+const (
+	IFLA_VXLAN_UNSPEC = iota
+	IFLA_VXLAN_ID
+	IFLA_VXLAN_GROUP
+	IFLA_VXLAN_LINK
+	IFLA_VXLAN_LOCAL
+	IFLA_VXLAN_TTL
+	IFLA_VXLAN_TOS
+	IFLA_VXLAN_LEARNING
+	IFLA_VXLAN_AGEING
+	IFLA_VXLAN_LIMIT
+	IFLA_VXLAN_PORT_RANGE
+	IFLA_VXLAN_PROXY
+	IFLA_VXLAN_RSC
+	IFLA_VXLAN_L2MISS
+	IFLA_VXLAN_L3MISS
+	IFLA_VXLAN_PORT
+	IFLA_VXLAN_GROUP6
+	IFLA_VXLAN_LOCAL6
+	IFLA_VXLAN_MAX = IFLA_VXLAN_LOCAL6
+)
+
+const (
+	BRIDGE_MODE_UNSPEC = iota
+	BRIDGE_MODE_HAIRPIN
+)
+
+const (
+	IFLA_BRPORT_UNSPEC = iota
+	IFLA_BRPORT_STATE
+	IFLA_BRPORT_PRIORITY
+	IFLA_BRPORT_COST
+	IFLA_BRPORT_MODE
+	IFLA_BRPORT_GUARD
+	IFLA_BRPORT_PROTECT
+	IFLA_BRPORT_FAST_LEAVE
+	IFLA_BRPORT_LEARNING
+	IFLA_BRPORT_UNICAST_FLOOD
+	IFLA_BRPORT_MAX = IFLA_BRPORT_UNICAST_FLOOD
+)
+
+const (
+	IFLA_IPVLAN_UNSPEC = iota
+	IFLA_IPVLAN_MODE
+	IFLA_IPVLAN_MAX = IFLA_IPVLAN_MODE
+)
+
+const (
+	// not defined in syscall
+	IFLA_NET_NS_FD = 28
+)

+ 417 - 0
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/nl_linux.go

@@ -0,0 +1,417 @@
+// Package nl has low level primitives for making Netlink calls.
+package nl
+
+import (
+	"bytes"
+	"encoding/binary"
+	"fmt"
+	"net"
+	"sync/atomic"
+	"syscall"
+	"unsafe"
+)
+
+const (
+	// Family type definitions
+	FAMILY_ALL = syscall.AF_UNSPEC
+	FAMILY_V4  = syscall.AF_INET
+	FAMILY_V6  = syscall.AF_INET6
+)
+
+var nextSeqNr uint32
+
+// GetIPFamily returns the family type of a net.IP.
+func GetIPFamily(ip net.IP) int {
+	if len(ip) <= net.IPv4len {
+		return FAMILY_V4
+	}
+	if ip.To4() != nil {
+		return FAMILY_V4
+	}
+	return FAMILY_V6
+}
+
+var nativeEndian binary.ByteOrder
+
+// Get native endianness for the system
+func NativeEndian() binary.ByteOrder {
+	if nativeEndian == nil {
+		var x uint32 = 0x01020304
+		if *(*byte)(unsafe.Pointer(&x)) == 0x01 {
+			nativeEndian = binary.BigEndian
+		}
+		nativeEndian = binary.LittleEndian
+	}
+	return nativeEndian
+}
+
+// Byte swap a 16 bit value if we aren't big endian
+func Swap16(i uint16) uint16 {
+	if NativeEndian() == binary.BigEndian {
+		return i
+	}
+	return (i&0xff00)>>8 | (i&0xff)<<8
+}
+
+// Byte swap a 32 bit value if aren't big endian
+func Swap32(i uint32) uint32 {
+	if NativeEndian() == binary.BigEndian {
+		return i
+	}
+	return (i&0xff000000)>>24 | (i&0xff0000)>>8 | (i&0xff00)<<8 | (i&0xff)<<24
+}
+
+type NetlinkRequestData interface {
+	Len() int
+	Serialize() []byte
+}
+
+// IfInfomsg is related to links, but it is used for list requests as well
+type IfInfomsg struct {
+	syscall.IfInfomsg
+}
+
+// Create an IfInfomsg with family specified
+func NewIfInfomsg(family int) *IfInfomsg {
+	return &IfInfomsg{
+		IfInfomsg: syscall.IfInfomsg{
+			Family: uint8(family),
+		},
+	}
+}
+
+func DeserializeIfInfomsg(b []byte) *IfInfomsg {
+	return (*IfInfomsg)(unsafe.Pointer(&b[0:syscall.SizeofIfInfomsg][0]))
+}
+
+func (msg *IfInfomsg) Serialize() []byte {
+	return (*(*[syscall.SizeofIfInfomsg]byte)(unsafe.Pointer(msg)))[:]
+}
+
+func (msg *IfInfomsg) Len() int {
+	return syscall.SizeofIfInfomsg
+}
+
+func rtaAlignOf(attrlen int) int {
+	return (attrlen + syscall.RTA_ALIGNTO - 1) & ^(syscall.RTA_ALIGNTO - 1)
+}
+
+func NewIfInfomsgChild(parent *RtAttr, family int) *IfInfomsg {
+	msg := NewIfInfomsg(family)
+	parent.children = append(parent.children, msg)
+	return msg
+}
+
+// Extend RtAttr to handle data and children
+type RtAttr struct {
+	syscall.RtAttr
+	Data     []byte
+	children []NetlinkRequestData
+}
+
+// Create a new Extended RtAttr object
+func NewRtAttr(attrType int, data []byte) *RtAttr {
+	return &RtAttr{
+		RtAttr: syscall.RtAttr{
+			Type: uint16(attrType),
+		},
+		children: []NetlinkRequestData{},
+		Data:     data,
+	}
+}
+
+// Create a new RtAttr obj anc add it as a child of an existing object
+func NewRtAttrChild(parent *RtAttr, attrType int, data []byte) *RtAttr {
+	attr := NewRtAttr(attrType, data)
+	parent.children = append(parent.children, attr)
+	return attr
+}
+
+func (a *RtAttr) Len() int {
+	if len(a.children) == 0 {
+		return (syscall.SizeofRtAttr + len(a.Data))
+	}
+
+	l := 0
+	for _, child := range a.children {
+		l += rtaAlignOf(child.Len())
+	}
+	l += syscall.SizeofRtAttr
+	return rtaAlignOf(l + len(a.Data))
+}
+
+// Serialize the RtAttr into a byte array
+// This can't ust unsafe.cast because it must iterate through children.
+func (a *RtAttr) Serialize() []byte {
+	native := NativeEndian()
+
+	length := a.Len()
+	buf := make([]byte, rtaAlignOf(length))
+
+	if a.Data != nil {
+		copy(buf[4:], a.Data)
+	} else {
+		next := 4
+		for _, child := range a.children {
+			childBuf := child.Serialize()
+			copy(buf[next:], childBuf)
+			next += rtaAlignOf(len(childBuf))
+		}
+	}
+
+	if l := uint16(length); l != 0 {
+		native.PutUint16(buf[0:2], l)
+	}
+	native.PutUint16(buf[2:4], a.Type)
+	return buf
+}
+
+type NetlinkRequest struct {
+	syscall.NlMsghdr
+	Data []NetlinkRequestData
+}
+
+// Serialize the Netlink Request into a byte array
+func (msg *NetlinkRequest) Serialize() []byte {
+	length := syscall.SizeofNlMsghdr
+	dataBytes := make([][]byte, len(msg.Data))
+	for i, data := range msg.Data {
+		dataBytes[i] = data.Serialize()
+		length = length + len(dataBytes[i])
+	}
+	msg.Len = uint32(length)
+	b := make([]byte, length)
+	hdr := (*(*[syscall.SizeofNlMsghdr]byte)(unsafe.Pointer(msg)))[:]
+	next := syscall.SizeofNlMsghdr
+	copy(b[0:next], hdr)
+	for _, data := range dataBytes {
+		for _, dataByte := range data {
+			b[next] = dataByte
+			next = next + 1
+		}
+	}
+	return b
+}
+
+func (msg *NetlinkRequest) AddData(data NetlinkRequestData) {
+	if data != nil {
+		msg.Data = append(msg.Data, data)
+	}
+}
+
+// Execute the request against a the given sockType.
+// Returns a list of netlink messages in seriaized format, optionally filtered
+// by resType.
+func (req *NetlinkRequest) Execute(sockType int, resType uint16) ([][]byte, error) {
+	s, err := getNetlinkSocket(sockType)
+	if err != nil {
+		return nil, err
+	}
+	defer s.Close()
+
+	if err := s.Send(req); err != nil {
+		return nil, err
+	}
+
+	pid, err := s.GetPid()
+	if err != nil {
+		return nil, err
+	}
+
+	res := make([][]byte, 0)
+
+done:
+	for {
+		msgs, err := s.Recieve()
+		if err != nil {
+			return nil, err
+		}
+		for _, m := range msgs {
+			if m.Header.Seq != req.Seq {
+				return nil, fmt.Errorf("Wrong Seq nr %d, expected 1", m.Header.Seq)
+			}
+			if m.Header.Pid != pid {
+				return nil, fmt.Errorf("Wrong pid %d, expected %d", m.Header.Pid, pid)
+			}
+			if m.Header.Type == syscall.NLMSG_DONE {
+				break done
+			}
+			if m.Header.Type == syscall.NLMSG_ERROR {
+				native := NativeEndian()
+				error := int32(native.Uint32(m.Data[0:4]))
+				if error == 0 {
+					break done
+				}
+				return nil, syscall.Errno(-error)
+			}
+			if resType != 0 && m.Header.Type != resType {
+				continue
+			}
+			res = append(res, m.Data)
+			if m.Header.Flags&syscall.NLM_F_MULTI == 0 {
+				break done
+			}
+		}
+	}
+	return res, nil
+}
+
+// Create a new netlink request from proto and flags
+// Note the Len value will be inaccurate once data is added until
+// the message is serialized
+func NewNetlinkRequest(proto, flags int) *NetlinkRequest {
+	return &NetlinkRequest{
+		NlMsghdr: syscall.NlMsghdr{
+			Len:   uint32(syscall.SizeofNlMsghdr),
+			Type:  uint16(proto),
+			Flags: syscall.NLM_F_REQUEST | uint16(flags),
+			Seq:   atomic.AddUint32(&nextSeqNr, 1),
+		},
+	}
+}
+
+type NetlinkSocket struct {
+	fd  int
+	lsa syscall.SockaddrNetlink
+}
+
+func getNetlinkSocket(protocol int) (*NetlinkSocket, error) {
+	fd, err := syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_RAW, protocol)
+	if err != nil {
+		return nil, err
+	}
+	s := &NetlinkSocket{
+		fd: fd,
+	}
+	s.lsa.Family = syscall.AF_NETLINK
+	if err := syscall.Bind(fd, &s.lsa); err != nil {
+		syscall.Close(fd)
+		return nil, err
+	}
+
+	return s, nil
+}
+
+// Create a netlink socket with a given protocol (e.g. NETLINK_ROUTE)
+// and subscribe it to multicast groups passed in variable argument list.
+// Returns the netlink socket on whic hReceive() method can be called
+// to retrieve the messages from the kernel.
+func Subscribe(protocol int, groups ...uint) (*NetlinkSocket, error) {
+	fd, err := syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_RAW, protocol)
+	if err != nil {
+		return nil, err
+	}
+	s := &NetlinkSocket{
+		fd: fd,
+	}
+	s.lsa.Family = syscall.AF_NETLINK
+
+	for _, g := range groups {
+		s.lsa.Groups |= (1 << (g - 1))
+	}
+
+	if err := syscall.Bind(fd, &s.lsa); err != nil {
+		syscall.Close(fd)
+		return nil, err
+	}
+
+	return s, nil
+}
+
+func (s *NetlinkSocket) Close() {
+	syscall.Close(s.fd)
+}
+
+func (s *NetlinkSocket) Send(request *NetlinkRequest) error {
+	if err := syscall.Sendto(s.fd, request.Serialize(), 0, &s.lsa); err != nil {
+		return err
+	}
+	return nil
+}
+
+func (s *NetlinkSocket) Recieve() ([]syscall.NetlinkMessage, error) {
+	rb := make([]byte, syscall.Getpagesize())
+	nr, _, err := syscall.Recvfrom(s.fd, rb, 0)
+	if err != nil {
+		return nil, err
+	}
+	if nr < syscall.NLMSG_HDRLEN {
+		return nil, fmt.Errorf("Got short response from netlink")
+	}
+	rb = rb[:nr]
+	return syscall.ParseNetlinkMessage(rb)
+}
+
+func (s *NetlinkSocket) GetPid() (uint32, error) {
+	lsa, err := syscall.Getsockname(s.fd)
+	if err != nil {
+		return 0, err
+	}
+	switch v := lsa.(type) {
+	case *syscall.SockaddrNetlink:
+		return v.Pid, nil
+	}
+	return 0, fmt.Errorf("Wrong socket type")
+}
+
+func ZeroTerminated(s string) []byte {
+	bytes := make([]byte, len(s)+1)
+	for i := 0; i < len(s); i++ {
+		bytes[i] = s[i]
+	}
+	bytes[len(s)] = 0
+	return bytes
+}
+
+func NonZeroTerminated(s string) []byte {
+	bytes := make([]byte, len(s))
+	for i := 0; i < len(s); i++ {
+		bytes[i] = s[i]
+	}
+	return bytes
+}
+
+func BytesToString(b []byte) string {
+	n := bytes.Index(b, []byte{0})
+	return string(b[:n])
+}
+
+func Uint8Attr(v uint8) []byte {
+	return []byte{byte(v)}
+}
+
+func Uint16Attr(v uint16) []byte {
+	native := NativeEndian()
+	bytes := make([]byte, 2)
+	native.PutUint16(bytes, v)
+	return bytes
+}
+
+func Uint32Attr(v uint32) []byte {
+	native := NativeEndian()
+	bytes := make([]byte, 4)
+	native.PutUint32(bytes, v)
+	return bytes
+}
+
+func ParseRouteAttr(b []byte) ([]syscall.NetlinkRouteAttr, error) {
+	var attrs []syscall.NetlinkRouteAttr
+	for len(b) >= syscall.SizeofRtAttr {
+		a, vbuf, alen, err := netlinkRouteAttrAndValue(b)
+		if err != nil {
+			return nil, err
+		}
+		ra := syscall.NetlinkRouteAttr{Attr: *a, Value: vbuf[:int(a.Len)-syscall.SizeofRtAttr]}
+		attrs = append(attrs, ra)
+		b = b[alen:]
+	}
+	return attrs, nil
+}
+
+func netlinkRouteAttrAndValue(b []byte) (*syscall.RtAttr, []byte, int, error) {
+	a := (*syscall.RtAttr)(unsafe.Pointer(&b[0]))
+	if int(a.Len) < syscall.SizeofRtAttr || int(a.Len) > len(b) {
+		return nil, nil, 0, syscall.EINVAL
+	}
+	return a, b[syscall.SizeofRtAttr:], rtaAlignOf(int(a.Len)), nil
+}

+ 60 - 0
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/nl_linux_test.go

@@ -0,0 +1,60 @@
+package nl
+
+import (
+	"bytes"
+	"crypto/rand"
+	"encoding/binary"
+	"reflect"
+	"syscall"
+	"testing"
+)
+
+type testSerializer interface {
+	serializeSafe() []byte
+	Serialize() []byte
+}
+
+func testDeserializeSerialize(t *testing.T, orig []byte, safemsg testSerializer, msg testSerializer) {
+	if !reflect.DeepEqual(safemsg, msg) {
+		t.Fatal("Deserialization failed.\n", safemsg, "\n", msg)
+	}
+	safe := msg.serializeSafe()
+	if !bytes.Equal(safe, orig) {
+		t.Fatal("Safe serialization failed.\n", safe, "\n", orig)
+	}
+	b := msg.Serialize()
+	if !bytes.Equal(b, safe) {
+		t.Fatal("Serialization failed.\n", b, "\n", safe)
+	}
+}
+
+func (msg *IfInfomsg) write(b []byte) {
+	native := NativeEndian()
+	b[0] = msg.Family
+	b[1] = msg.X__ifi_pad
+	native.PutUint16(b[2:4], msg.Type)
+	native.PutUint32(b[4:8], uint32(msg.Index))
+	native.PutUint32(b[8:12], msg.Flags)
+	native.PutUint32(b[12:16], msg.Change)
+}
+
+func (msg *IfInfomsg) serializeSafe() []byte {
+	length := syscall.SizeofIfInfomsg
+	b := make([]byte, length)
+	msg.write(b)
+	return b
+}
+
+func deserializeIfInfomsgSafe(b []byte) *IfInfomsg {
+	var msg = IfInfomsg{}
+	binary.Read(bytes.NewReader(b[0:syscall.SizeofIfInfomsg]), NativeEndian(), &msg)
+	return &msg
+}
+
+func TestIfInfomsgDeserializeSerialize(t *testing.T) {
+	var orig = make([]byte, syscall.SizeofIfInfomsg)
+	rand.Read(orig)
+	safemsg := deserializeIfInfomsgSafe(orig)
+	msg := DeserializeIfInfomsg(orig)
+	testDeserializeSerialize(t, orig, safemsg, msg)
+}

+ 33 - 0
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/route_linux.go

@@ -0,0 +1,33 @@
+package nl
+
+import (
+	"syscall"
+	"unsafe"
+)
+
+type RtMsg struct {
+	syscall.RtMsg
+}
+
+func NewRtMsg() *RtMsg {
+	return &RtMsg{
+		RtMsg: syscall.RtMsg{
+			Table:    syscall.RT_TABLE_MAIN,
+			Scope:    syscall.RT_SCOPE_UNIVERSE,
+			Protocol: syscall.RTPROT_BOOT,
+			Type:     syscall.RTN_UNICAST,
+		},
+	}
+}
+
+func (msg *RtMsg) Len() int {
+	return syscall.SizeofRtMsg
+}
+
+func DeserializeRtMsg(b []byte) *RtMsg {
+	return (*RtMsg)(unsafe.Pointer(&b[0:syscall.SizeofRtMsg][0]))
+}
+
+func (msg *RtMsg) Serialize() []byte {
+	return (*(*[syscall.SizeofRtMsg]byte)(unsafe.Pointer(msg)))[:]
+}

+ 43 - 0
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/route_linux_test.go

@@ -0,0 +1,43 @@
+package nl
+
+import (
+	"bytes"
+	"crypto/rand"
+	"encoding/binary"
+	"syscall"
+	"testing"
+)
+
+func (msg *RtMsg) write(b []byte) {
+	native := NativeEndian()
+	b[0] = msg.Family
+	b[1] = msg.Dst_len
+	b[2] = msg.Src_len
+	b[3] = msg.Tos
+	b[4] = msg.Table
+	b[5] = msg.Protocol
+	b[6] = msg.Scope
+	b[7] = msg.Type
+	native.PutUint32(b[8:12], msg.Flags)
+}
+
+func (msg *RtMsg) serializeSafe() []byte {
+	len := syscall.SizeofRtMsg
+	b := make([]byte, len)
+	msg.write(b)
+	return b
+}
+
+func deserializeRtMsgSafe(b []byte) *RtMsg {
+	var msg = RtMsg{}
+	binary.Read(bytes.NewReader(b[0:syscall.SizeofRtMsg]), NativeEndian(), &msg)
+	return &msg
+}
+
+func TestRtMsgDeserializeSerialize(t *testing.T) {
+	var orig = make([]byte, syscall.SizeofRtMsg)
+	rand.Read(orig)
+	safemsg := deserializeRtMsgSafe(orig)
+	msg := DeserializeRtMsg(orig)
+	testDeserializeSerialize(t, orig, safemsg, msg)
+}

+ 259 - 0
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/xfrm_linux.go

@@ -0,0 +1,259 @@
+package nl
+
+import (
+	"bytes"
+	"net"
+	"unsafe"
+)
+
+// Infinity for packet and byte counts
+const (
+	XFRM_INF = ^uint64(0)
+)
+
+// Message Types
+const (
+	XFRM_MSG_BASE        = 0x10
+	XFRM_MSG_NEWSA       = 0x10
+	XFRM_MSG_DELSA       = 0x11
+	XFRM_MSG_GETSA       = 0x12
+	XFRM_MSG_NEWPOLICY   = 0x13
+	XFRM_MSG_DELPOLICY   = 0x14
+	XFRM_MSG_GETPOLICY   = 0x15
+	XFRM_MSG_ALLOCSPI    = 0x16
+	XFRM_MSG_ACQUIRE     = 0x17
+	XFRM_MSG_EXPIRE      = 0x18
+	XFRM_MSG_UPDPOLICY   = 0x19
+	XFRM_MSG_UPDSA       = 0x1a
+	XFRM_MSG_POLEXPIRE   = 0x1b
+	XFRM_MSG_FLUSHSA     = 0x1c
+	XFRM_MSG_FLUSHPOLICY = 0x1d
+	XFRM_MSG_NEWAE       = 0x1e
+	XFRM_MSG_GETAE       = 0x1f
+	XFRM_MSG_REPORT      = 0x20
+	XFRM_MSG_MIGRATE     = 0x21
+	XFRM_MSG_NEWSADINFO  = 0x22
+	XFRM_MSG_GETSADINFO  = 0x23
+	XFRM_MSG_NEWSPDINFO  = 0x24
+	XFRM_MSG_GETSPDINFO  = 0x25
+	XFRM_MSG_MAPPING     = 0x26
+	XFRM_MSG_MAX         = 0x26
+	XFRM_NR_MSGTYPES     = 0x17
+)
+
+// Attribute types
+const (
+	/* Netlink message attributes.  */
+	XFRMA_UNSPEC         = 0x00
+	XFRMA_ALG_AUTH       = 0x01 /* struct xfrm_algo */
+	XFRMA_ALG_CRYPT      = 0x02 /* struct xfrm_algo */
+	XFRMA_ALG_COMP       = 0x03 /* struct xfrm_algo */
+	XFRMA_ENCAP          = 0x04 /* struct xfrm_algo + struct xfrm_encap_tmpl */
+	XFRMA_TMPL           = 0x05 /* 1 or more struct xfrm_user_tmpl */
+	XFRMA_SA             = 0x06 /* struct xfrm_usersa_info  */
+	XFRMA_POLICY         = 0x07 /* struct xfrm_userpolicy_info */
+	XFRMA_SEC_CTX        = 0x08 /* struct xfrm_sec_ctx */
+	XFRMA_LTIME_VAL      = 0x09
+	XFRMA_REPLAY_VAL     = 0x0a
+	XFRMA_REPLAY_THRESH  = 0x0b
+	XFRMA_ETIMER_THRESH  = 0x0c
+	XFRMA_SRCADDR        = 0x0d /* xfrm_address_t */
+	XFRMA_COADDR         = 0x0e /* xfrm_address_t */
+	XFRMA_LASTUSED       = 0x0f /* unsigned long  */
+	XFRMA_POLICY_TYPE    = 0x10 /* struct xfrm_userpolicy_type */
+	XFRMA_MIGRATE        = 0x11
+	XFRMA_ALG_AEAD       = 0x12 /* struct xfrm_algo_aead */
+	XFRMA_KMADDRESS      = 0x13 /* struct xfrm_user_kmaddress */
+	XFRMA_ALG_AUTH_TRUNC = 0x14 /* struct xfrm_algo_auth */
+	XFRMA_MARK           = 0x15 /* struct xfrm_mark */
+	XFRMA_TFCPAD         = 0x16 /* __u32 */
+	XFRMA_REPLAY_ESN_VAL = 0x17 /* struct xfrm_replay_esn */
+	XFRMA_SA_EXTRA_FLAGS = 0x18 /* __u32 */
+	XFRMA_MAX            = 0x18
+)
+
+const (
+	SizeofXfrmAddress     = 0x10
+	SizeofXfrmSelector    = 0x38
+	SizeofXfrmLifetimeCfg = 0x40
+	SizeofXfrmLifetimeCur = 0x20
+	SizeofXfrmId          = 0x18
+)
+
+// typedef union {
+//   __be32    a4;
+//   __be32    a6[4];
+// } xfrm_address_t;
+
+type XfrmAddress [SizeofXfrmAddress]byte
+
+func (x *XfrmAddress) ToIP() net.IP {
+	var empty = [12]byte{}
+	ip := make(net.IP, net.IPv6len)
+	if bytes.Equal(x[4:16], empty[:]) {
+		ip[10] = 0xff
+		ip[11] = 0xff
+		copy(ip[12:16], x[0:4])
+	} else {
+		copy(ip[:], x[:])
+	}
+	return ip
+}
+
+func (x *XfrmAddress) ToIPNet(prefixlen uint8) *net.IPNet {
+	ip := x.ToIP()
+	if GetIPFamily(ip) == FAMILY_V4 {
+		return &net.IPNet{IP: ip, Mask: net.CIDRMask(int(prefixlen), 32)}
+	} else {
+		return &net.IPNet{IP: ip, Mask: net.CIDRMask(int(prefixlen), 128)}
+	}
+}
+
+func (x *XfrmAddress) FromIP(ip net.IP) {
+	var empty = [16]byte{}
+	if len(ip) < net.IPv4len {
+		copy(x[4:16], empty[:])
+	} else if GetIPFamily(ip) == FAMILY_V4 {
+		copy(x[0:4], ip.To4()[0:4])
+		copy(x[4:16], empty[:12])
+	} else {
+		copy(x[0:16], ip.To16()[0:16])
+	}
+}
+
+func DeserializeXfrmAddress(b []byte) *XfrmAddress {
+	return (*XfrmAddress)(unsafe.Pointer(&b[0:SizeofXfrmAddress][0]))
+}
+
+func (msg *XfrmAddress) Serialize() []byte {
+	return (*(*[SizeofXfrmAddress]byte)(unsafe.Pointer(msg)))[:]
+}
+
+// struct xfrm_selector {
+//   xfrm_address_t  daddr;
+//   xfrm_address_t  saddr;
+//   __be16  dport;
+//   __be16  dport_mask;
+//   __be16  sport;
+//   __be16  sport_mask;
+//   __u16 family;
+//   __u8  prefixlen_d;
+//   __u8  prefixlen_s;
+//   __u8  proto;
+//   int ifindex;
+//   __kernel_uid32_t  user;
+// };
+
+type XfrmSelector struct {
+	Daddr      XfrmAddress
+	Saddr      XfrmAddress
+	Dport      uint16 // big endian
+	DportMask  uint16 // big endian
+	Sport      uint16 // big endian
+	SportMask  uint16 // big endian
+	Family     uint16
+	PrefixlenD uint8
+	PrefixlenS uint8
+	Proto      uint8
+	Pad        [3]byte
+	Ifindex    int32
+	User       uint32
+}
+
+func (msg *XfrmSelector) Len() int {
+	return SizeofXfrmSelector
+}
+
+func DeserializeXfrmSelector(b []byte) *XfrmSelector {
+	return (*XfrmSelector)(unsafe.Pointer(&b[0:SizeofXfrmSelector][0]))
+}
+
+func (msg *XfrmSelector) Serialize() []byte {
+	return (*(*[SizeofXfrmSelector]byte)(unsafe.Pointer(msg)))[:]
+}
+
+// struct xfrm_lifetime_cfg {
+//   __u64 soft_byte_limit;
+//   __u64 hard_byte_limit;
+//   __u64 soft_packet_limit;
+//   __u64 hard_packet_limit;
+//   __u64 soft_add_expires_seconds;
+//   __u64 hard_add_expires_seconds;
+//   __u64 soft_use_expires_seconds;
+//   __u64 hard_use_expires_seconds;
+// };
+//
+
+type XfrmLifetimeCfg struct {
+	SoftByteLimit         uint64
+	HardByteLimit         uint64
+	SoftPacketLimit       uint64
+	HardPacketLimit       uint64
+	SoftAddExpiresSeconds uint64
+	HardAddExpiresSeconds uint64
+	SoftUseExpiresSeconds uint64
+	HardUseExpiresSeconds uint64
+}
+
+func (msg *XfrmLifetimeCfg) Len() int {
+	return SizeofXfrmLifetimeCfg
+}
+
+func DeserializeXfrmLifetimeCfg(b []byte) *XfrmLifetimeCfg {
+	return (*XfrmLifetimeCfg)(unsafe.Pointer(&b[0:SizeofXfrmLifetimeCfg][0]))
+}
+
+func (msg *XfrmLifetimeCfg) Serialize() []byte {
+	return (*(*[SizeofXfrmLifetimeCfg]byte)(unsafe.Pointer(msg)))[:]
+}
+
+// struct xfrm_lifetime_cur {
+//   __u64 bytes;
+//   __u64 packets;
+//   __u64 add_time;
+//   __u64 use_time;
+// };
+
+type XfrmLifetimeCur struct {
+	Bytes   uint64
+	Packets uint64
+	AddTime uint64
+	UseTime uint64
+}
+
+func (msg *XfrmLifetimeCur) Len() int {
+	return SizeofXfrmLifetimeCur
+}
+
+func DeserializeXfrmLifetimeCur(b []byte) *XfrmLifetimeCur {
+	return (*XfrmLifetimeCur)(unsafe.Pointer(&b[0:SizeofXfrmLifetimeCur][0]))
+}
+
+func (msg *XfrmLifetimeCur) Serialize() []byte {
+	return (*(*[SizeofXfrmLifetimeCur]byte)(unsafe.Pointer(msg)))[:]
+}
+
+// struct xfrm_id {
+//   xfrm_address_t  daddr;
+//   __be32    spi;
+//   __u8    proto;
+// };
+
+type XfrmId struct {
+	Daddr XfrmAddress
+	Spi   uint32 // big endian
+	Proto uint8
+	Pad   [3]byte
+}
+
+func (msg *XfrmId) Len() int {
+	return SizeofXfrmId
+}
+
+func DeserializeXfrmId(b []byte) *XfrmId {
+	return (*XfrmId)(unsafe.Pointer(&b[0:SizeofXfrmId][0]))
+}
+
+func (msg *XfrmId) Serialize() []byte {
+	return (*(*[SizeofXfrmId]byte)(unsafe.Pointer(msg)))[:]
+}

+ 161 - 0
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/xfrm_linux_test.go

@@ -0,0 +1,161 @@
+package nl
+
+import (
+	"bytes"
+	"crypto/rand"
+	"encoding/binary"
+	"testing"
+)
+
+func (msg *XfrmAddress) write(b []byte) {
+	copy(b[0:SizeofXfrmAddress], msg[:])
+}
+
+func (msg *XfrmAddress) serializeSafe() []byte {
+	b := make([]byte, SizeofXfrmAddress)
+	msg.write(b)
+	return b
+}
+
+func deserializeXfrmAddressSafe(b []byte) *XfrmAddress {
+	var msg = XfrmAddress{}
+	binary.Read(bytes.NewReader(b[0:SizeofXfrmAddress]), NativeEndian(), &msg)
+	return &msg
+}
+
+func TestXfrmAddressDeserializeSerialize(t *testing.T) {
+	var orig = make([]byte, SizeofXfrmAddress)
+	rand.Read(orig)
+	safemsg := deserializeXfrmAddressSafe(orig)
+	msg := DeserializeXfrmAddress(orig)
+	testDeserializeSerialize(t, orig, safemsg, msg)
+}
+
+func (msg *XfrmSelector) write(b []byte) {
+	const AddrEnd = SizeofXfrmAddress * 2
+	native := NativeEndian()
+	msg.Daddr.write(b[0:SizeofXfrmAddress])
+	msg.Saddr.write(b[SizeofXfrmAddress:AddrEnd])
+	native.PutUint16(b[AddrEnd:AddrEnd+2], msg.Dport)
+	native.PutUint16(b[AddrEnd+2:AddrEnd+4], msg.DportMask)
+	native.PutUint16(b[AddrEnd+4:AddrEnd+6], msg.Sport)
+	native.PutUint16(b[AddrEnd+6:AddrEnd+8], msg.SportMask)
+	native.PutUint16(b[AddrEnd+8:AddrEnd+10], msg.Family)
+	b[AddrEnd+10] = msg.PrefixlenD
+	b[AddrEnd+11] = msg.PrefixlenS
+	b[AddrEnd+12] = msg.Proto
+	copy(b[AddrEnd+13:AddrEnd+16], msg.Pad[:])
+	native.PutUint32(b[AddrEnd+16:AddrEnd+20], uint32(msg.Ifindex))
+	native.PutUint32(b[AddrEnd+20:AddrEnd+24], msg.User)
+}
+
+func (msg *XfrmSelector) serializeSafe() []byte {
+	length := SizeofXfrmSelector
+	b := make([]byte, length)
+	msg.write(b)
+	return b
+}
+
+func deserializeXfrmSelectorSafe(b []byte) *XfrmSelector {
+	var msg = XfrmSelector{}
+	binary.Read(bytes.NewReader(b[0:SizeofXfrmSelector]), NativeEndian(), &msg)
+	return &msg
+}
+
+func TestXfrmSelectorDeserializeSerialize(t *testing.T) {
+	var orig = make([]byte, SizeofXfrmSelector)
+	rand.Read(orig)
+	safemsg := deserializeXfrmSelectorSafe(orig)
+	msg := DeserializeXfrmSelector(orig)
+	testDeserializeSerialize(t, orig, safemsg, msg)
+}
+
+func (msg *XfrmLifetimeCfg) write(b []byte) {
+	native := NativeEndian()
+	native.PutUint64(b[0:8], msg.SoftByteLimit)
+	native.PutUint64(b[8:16], msg.HardByteLimit)
+	native.PutUint64(b[16:24], msg.SoftPacketLimit)
+	native.PutUint64(b[24:32], msg.HardPacketLimit)
+	native.PutUint64(b[32:40], msg.SoftAddExpiresSeconds)
+	native.PutUint64(b[40:48], msg.HardAddExpiresSeconds)
+	native.PutUint64(b[48:56], msg.SoftUseExpiresSeconds)
+	native.PutUint64(b[56:64], msg.HardUseExpiresSeconds)
+}
+
+func (msg *XfrmLifetimeCfg) serializeSafe() []byte {
+	length := SizeofXfrmLifetimeCfg
+	b := make([]byte, length)
+	msg.write(b)
+	return b
+}
+
+func deserializeXfrmLifetimeCfgSafe(b []byte) *XfrmLifetimeCfg {
+	var msg = XfrmLifetimeCfg{}
+	binary.Read(bytes.NewReader(b[0:SizeofXfrmLifetimeCfg]), NativeEndian(), &msg)
+	return &msg
+}
+
+func TestXfrmLifetimeCfgDeserializeSerialize(t *testing.T) {
+	var orig = make([]byte, SizeofXfrmLifetimeCfg)
+	rand.Read(orig)
+	safemsg := deserializeXfrmLifetimeCfgSafe(orig)
+	msg := DeserializeXfrmLifetimeCfg(orig)
+	testDeserializeSerialize(t, orig, safemsg, msg)
+}
+
+func (msg *XfrmLifetimeCur) write(b []byte) {
+	native := NativeEndian()
+	native.PutUint64(b[0:8], msg.Bytes)
+	native.PutUint64(b[8:16], msg.Packets)
+	native.PutUint64(b[16:24], msg.AddTime)
+	native.PutUint64(b[24:32], msg.UseTime)
+}
+
+func (msg *XfrmLifetimeCur) serializeSafe() []byte {
+	length := SizeofXfrmLifetimeCur
+	b := make([]byte, length)
+	msg.write(b)
+	return b
+}
+
+func deserializeXfrmLifetimeCurSafe(b []byte) *XfrmLifetimeCur {
+	var msg = XfrmLifetimeCur{}
+	binary.Read(bytes.NewReader(b[0:SizeofXfrmLifetimeCur]), NativeEndian(), &msg)
+	return &msg
+}
+
+func TestXfrmLifetimeCurDeserializeSerialize(t *testing.T) {
+	var orig = make([]byte, SizeofXfrmLifetimeCur)
+	rand.Read(orig)
+	safemsg := deserializeXfrmLifetimeCurSafe(orig)
+	msg := DeserializeXfrmLifetimeCur(orig)
+	testDeserializeSerialize(t, orig, safemsg, msg)
+}
+
+func (msg *XfrmId) write(b []byte) {
+	native := NativeEndian()
+	msg.Daddr.write(b[0:SizeofXfrmAddress])
+	native.PutUint32(b[SizeofXfrmAddress:SizeofXfrmAddress+4], msg.Spi)
+	b[SizeofXfrmAddress+4] = msg.Proto
+	copy(b[SizeofXfrmAddress+5:SizeofXfrmAddress+8], msg.Pad[:])
+}
+
+func (msg *XfrmId) serializeSafe() []byte {
+	b := make([]byte, SizeofXfrmId)
+	msg.write(b)
+	return b
+}
+
+func deserializeXfrmIdSafe(b []byte) *XfrmId {
+	var msg = XfrmId{}
+	binary.Read(bytes.NewReader(b[0:SizeofXfrmId]), NativeEndian(), &msg)
+	return &msg
+}
+
+func TestXfrmIdDeserializeSerialize(t *testing.T) {
+	var orig = make([]byte, SizeofXfrmId)
+	rand.Read(orig)
+	safemsg := deserializeXfrmIdSafe(orig)
+	msg := DeserializeXfrmId(orig)
+	testDeserializeSerialize(t, orig, safemsg, msg)
+}

+ 119 - 0
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/xfrm_policy_linux.go

@@ -0,0 +1,119 @@
+package nl
+
+import (
+	"unsafe"
+)
+
+const (
+	SizeofXfrmUserpolicyId   = 0x40
+	SizeofXfrmUserpolicyInfo = 0xa8
+	SizeofXfrmUserTmpl       = 0x40
+)
+
+// struct xfrm_userpolicy_id {
+//   struct xfrm_selector    sel;
+//   __u32       index;
+//   __u8        dir;
+// };
+//
+
+type XfrmUserpolicyId struct {
+	Sel   XfrmSelector
+	Index uint32
+	Dir   uint8
+	Pad   [3]byte
+}
+
+func (msg *XfrmUserpolicyId) Len() int {
+	return SizeofXfrmUserpolicyId
+}
+
+func DeserializeXfrmUserpolicyId(b []byte) *XfrmUserpolicyId {
+	return (*XfrmUserpolicyId)(unsafe.Pointer(&b[0:SizeofXfrmUserpolicyId][0]))
+}
+
+func (msg *XfrmUserpolicyId) Serialize() []byte {
+	return (*(*[SizeofXfrmUserpolicyId]byte)(unsafe.Pointer(msg)))[:]
+}
+
+// struct xfrm_userpolicy_info {
+//   struct xfrm_selector    sel;
+//   struct xfrm_lifetime_cfg  lft;
+//   struct xfrm_lifetime_cur  curlft;
+//   __u32       priority;
+//   __u32       index;
+//   __u8        dir;
+//   __u8        action;
+// #define XFRM_POLICY_ALLOW 0
+// #define XFRM_POLICY_BLOCK 1
+//   __u8        flags;
+// #define XFRM_POLICY_LOCALOK 1 /* Allow user to override global policy */
+//   /* Automatically expand selector to include matching ICMP payloads. */
+// #define XFRM_POLICY_ICMP  2
+//   __u8        share;
+// };
+
+type XfrmUserpolicyInfo struct {
+	Sel      XfrmSelector
+	Lft      XfrmLifetimeCfg
+	Curlft   XfrmLifetimeCur
+	Priority uint32
+	Index    uint32
+	Dir      uint8
+	Action   uint8
+	Flags    uint8
+	Share    uint8
+	Pad      [4]byte
+}
+
+func (msg *XfrmUserpolicyInfo) Len() int {
+	return SizeofXfrmUserpolicyInfo
+}
+
+func DeserializeXfrmUserpolicyInfo(b []byte) *XfrmUserpolicyInfo {
+	return (*XfrmUserpolicyInfo)(unsafe.Pointer(&b[0:SizeofXfrmUserpolicyInfo][0]))
+}
+
+func (msg *XfrmUserpolicyInfo) Serialize() []byte {
+	return (*(*[SizeofXfrmUserpolicyInfo]byte)(unsafe.Pointer(msg)))[:]
+}
+
+// struct xfrm_user_tmpl {
+//   struct xfrm_id    id;
+//   __u16     family;
+//   xfrm_address_t    saddr;
+//   __u32     reqid;
+//   __u8      mode;
+//   __u8      share;
+//   __u8      optional;
+//   __u32     aalgos;
+//   __u32     ealgos;
+//   __u32     calgos;
+// }
+
+type XfrmUserTmpl struct {
+	XfrmId   XfrmId
+	Family   uint16
+	Pad1     [2]byte
+	Saddr    XfrmAddress
+	Reqid    uint32
+	Mode     uint8
+	Share    uint8
+	Optional uint8
+	Pad2     byte
+	Aalgos   uint32
+	Ealgos   uint32
+	Calgos   uint32
+}
+
+func (msg *XfrmUserTmpl) Len() int {
+	return SizeofXfrmUserTmpl
+}
+
+func DeserializeXfrmUserTmpl(b []byte) *XfrmUserTmpl {
+	return (*XfrmUserTmpl)(unsafe.Pointer(&b[0:SizeofXfrmUserTmpl][0]))
+}
+
+func (msg *XfrmUserTmpl) Serialize() []byte {
+	return (*(*[SizeofXfrmUserTmpl]byte)(unsafe.Pointer(msg)))[:]
+}

+ 109 - 0
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/xfrm_policy_linux_test.go

@@ -0,0 +1,109 @@
+package nl
+
+import (
+	"bytes"
+	"crypto/rand"
+	"encoding/binary"
+	"testing"
+)
+
+func (msg *XfrmUserpolicyId) write(b []byte) {
+	native := NativeEndian()
+	msg.Sel.write(b[0:SizeofXfrmSelector])
+	native.PutUint32(b[SizeofXfrmSelector:SizeofXfrmSelector+4], msg.Index)
+	b[SizeofXfrmSelector+4] = msg.Dir
+	copy(b[SizeofXfrmSelector+5:SizeofXfrmSelector+8], msg.Pad[:])
+}
+
+func (msg *XfrmUserpolicyId) serializeSafe() []byte {
+	b := make([]byte, SizeofXfrmUserpolicyId)
+	msg.write(b)
+	return b
+}
+
+func deserializeXfrmUserpolicyIdSafe(b []byte) *XfrmUserpolicyId {
+	var msg = XfrmUserpolicyId{}
+	binary.Read(bytes.NewReader(b[0:SizeofXfrmUserpolicyId]), NativeEndian(), &msg)
+	return &msg
+}
+
+func TestXfrmUserpolicyIdDeserializeSerialize(t *testing.T) {
+	var orig = make([]byte, SizeofXfrmUserpolicyId)
+	rand.Read(orig)
+	safemsg := deserializeXfrmUserpolicyIdSafe(orig)
+	msg := DeserializeXfrmUserpolicyId(orig)
+	testDeserializeSerialize(t, orig, safemsg, msg)
+}
+
+func (msg *XfrmUserpolicyInfo) write(b []byte) {
+	const CfgEnd = SizeofXfrmSelector + SizeofXfrmLifetimeCfg
+	const CurEnd = CfgEnd + SizeofXfrmLifetimeCur
+	native := NativeEndian()
+	msg.Sel.write(b[0:SizeofXfrmSelector])
+	msg.Lft.write(b[SizeofXfrmSelector:CfgEnd])
+	msg.Curlft.write(b[CfgEnd:CurEnd])
+	native.PutUint32(b[CurEnd:CurEnd+4], msg.Priority)
+	native.PutUint32(b[CurEnd+4:CurEnd+8], msg.Index)
+	b[CurEnd+8] = msg.Dir
+	b[CurEnd+9] = msg.Action
+	b[CurEnd+10] = msg.Flags
+	b[CurEnd+11] = msg.Share
+	copy(b[CurEnd+12:CurEnd+16], msg.Pad[:])
+}
+
+func (msg *XfrmUserpolicyInfo) serializeSafe() []byte {
+	b := make([]byte, SizeofXfrmUserpolicyInfo)
+	msg.write(b)
+	return b
+}
+
+func deserializeXfrmUserpolicyInfoSafe(b []byte) *XfrmUserpolicyInfo {
+	var msg = XfrmUserpolicyInfo{}
+	binary.Read(bytes.NewReader(b[0:SizeofXfrmUserpolicyInfo]), NativeEndian(), &msg)
+	return &msg
+}
+
+func TestXfrmUserpolicyInfoDeserializeSerialize(t *testing.T) {
+	var orig = make([]byte, SizeofXfrmUserpolicyInfo)
+	rand.Read(orig)
+	safemsg := deserializeXfrmUserpolicyInfoSafe(orig)
+	msg := DeserializeXfrmUserpolicyInfo(orig)
+	testDeserializeSerialize(t, orig, safemsg, msg)
+}
+
+func (msg *XfrmUserTmpl) write(b []byte) {
+	const AddrEnd = SizeofXfrmId + 4 + SizeofXfrmAddress
+	native := NativeEndian()
+	msg.XfrmId.write(b[0:SizeofXfrmId])
+	native.PutUint16(b[SizeofXfrmId:SizeofXfrmId+2], msg.Family)
+	copy(b[SizeofXfrmId+2:SizeofXfrmId+4], msg.Pad1[:])
+	msg.Saddr.write(b[SizeofXfrmId+4 : AddrEnd])
+	native.PutUint32(b[AddrEnd:AddrEnd+4], msg.Reqid)
+	b[AddrEnd+4] = msg.Mode
+	b[AddrEnd+5] = msg.Share
+	b[AddrEnd+6] = msg.Optional
+	b[AddrEnd+7] = msg.Pad2
+	native.PutUint32(b[AddrEnd+8:AddrEnd+12], msg.Aalgos)
+	native.PutUint32(b[AddrEnd+12:AddrEnd+16], msg.Ealgos)
+	native.PutUint32(b[AddrEnd+16:AddrEnd+20], msg.Calgos)
+}
+
+func (msg *XfrmUserTmpl) serializeSafe() []byte {
+	b := make([]byte, SizeofXfrmUserTmpl)
+	msg.write(b)
+	return b
+}
+
+func deserializeXfrmUserTmplSafe(b []byte) *XfrmUserTmpl {
+	var msg = XfrmUserTmpl{}
+	binary.Read(bytes.NewReader(b[0:SizeofXfrmUserTmpl]), NativeEndian(), &msg)
+	return &msg
+}
+
+func TestXfrmUserTmplDeserializeSerialize(t *testing.T) {
+	var orig = make([]byte, SizeofXfrmUserTmpl)
+	rand.Read(orig)
+	safemsg := deserializeXfrmUserTmplSafe(orig)
+	msg := DeserializeXfrmUserTmpl(orig)
+	testDeserializeSerialize(t, orig, safemsg, msg)
+}

+ 221 - 0
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/xfrm_state_linux.go

@@ -0,0 +1,221 @@
+package nl
+
+import (
+	"unsafe"
+)
+
+const (
+	SizeofXfrmUsersaId   = 0x18
+	SizeofXfrmStats      = 0x0c
+	SizeofXfrmUsersaInfo = 0xe0
+	SizeofXfrmAlgo       = 0x44
+	SizeofXfrmAlgoAuth   = 0x48
+	SizeofXfrmEncapTmpl  = 0x18
+)
+
+// struct xfrm_usersa_id {
+//   xfrm_address_t      daddr;
+//   __be32        spi;
+//   __u16       family;
+//   __u8        proto;
+// };
+
+type XfrmUsersaId struct {
+	Daddr  XfrmAddress
+	Spi    uint32 // big endian
+	Family uint16
+	Proto  uint8
+	Pad    byte
+}
+
+func (msg *XfrmUsersaId) Len() int {
+	return SizeofXfrmUsersaId
+}
+
+func DeserializeXfrmUsersaId(b []byte) *XfrmUsersaId {
+	return (*XfrmUsersaId)(unsafe.Pointer(&b[0:SizeofXfrmUsersaId][0]))
+}
+
+func (msg *XfrmUsersaId) Serialize() []byte {
+	return (*(*[SizeofXfrmUsersaId]byte)(unsafe.Pointer(msg)))[:]
+}
+
+// struct xfrm_stats {
+//   __u32 replay_window;
+//   __u32 replay;
+//   __u32 integrity_failed;
+// };
+
+type XfrmStats struct {
+	ReplayWindow    uint32
+	Replay          uint32
+	IntegrityFailed uint32
+}
+
+func (msg *XfrmStats) Len() int {
+	return SizeofXfrmStats
+}
+
+func DeserializeXfrmStats(b []byte) *XfrmStats {
+	return (*XfrmStats)(unsafe.Pointer(&b[0:SizeofXfrmStats][0]))
+}
+
+func (msg *XfrmStats) Serialize() []byte {
+	return (*(*[SizeofXfrmStats]byte)(unsafe.Pointer(msg)))[:]
+}
+
+// struct xfrm_usersa_info {
+//   struct xfrm_selector    sel;
+//   struct xfrm_id      id;
+//   xfrm_address_t      saddr;
+//   struct xfrm_lifetime_cfg  lft;
+//   struct xfrm_lifetime_cur  curlft;
+//   struct xfrm_stats   stats;
+//   __u32       seq;
+//   __u32       reqid;
+//   __u16       family;
+//   __u8        mode;   /* XFRM_MODE_xxx */
+//   __u8        replay_window;
+//   __u8        flags;
+// #define XFRM_STATE_NOECN  1
+// #define XFRM_STATE_DECAP_DSCP 2
+// #define XFRM_STATE_NOPMTUDISC 4
+// #define XFRM_STATE_WILDRECV 8
+// #define XFRM_STATE_ICMP   16
+// #define XFRM_STATE_AF_UNSPEC  32
+// #define XFRM_STATE_ALIGN4 64
+// #define XFRM_STATE_ESN    128
+// };
+//
+// #define XFRM_SA_XFLAG_DONT_ENCAP_DSCP 1
+//
+
+type XfrmUsersaInfo struct {
+	Sel          XfrmSelector
+	Id           XfrmId
+	Saddr        XfrmAddress
+	Lft          XfrmLifetimeCfg
+	Curlft       XfrmLifetimeCur
+	Stats        XfrmStats
+	Seq          uint32
+	Reqid        uint32
+	Family       uint16
+	Mode         uint8
+	ReplayWindow uint8
+	Flags        uint8
+	Pad          [7]byte
+}
+
+func (msg *XfrmUsersaInfo) Len() int {
+	return SizeofXfrmUsersaInfo
+}
+
+func DeserializeXfrmUsersaInfo(b []byte) *XfrmUsersaInfo {
+	return (*XfrmUsersaInfo)(unsafe.Pointer(&b[0:SizeofXfrmUsersaInfo][0]))
+}
+
+func (msg *XfrmUsersaInfo) Serialize() []byte {
+	return (*(*[SizeofXfrmUsersaInfo]byte)(unsafe.Pointer(msg)))[:]
+}
+
+// struct xfrm_algo {
+//   char    alg_name[64];
+//   unsigned int  alg_key_len;    /* in bits */
+//   char    alg_key[0];
+// };
+
+type XfrmAlgo struct {
+	AlgName   [64]byte
+	AlgKeyLen uint32
+	AlgKey    []byte
+}
+
+func (msg *XfrmAlgo) Len() int {
+	return SizeofXfrmAlgo + int(msg.AlgKeyLen/8)
+}
+
+func DeserializeXfrmAlgo(b []byte) *XfrmAlgo {
+	ret := XfrmAlgo{}
+	copy(ret.AlgName[:], b[0:64])
+	ret.AlgKeyLen = *(*uint32)(unsafe.Pointer(&b[64]))
+	ret.AlgKey = b[68:ret.Len()]
+	return &ret
+}
+
+func (msg *XfrmAlgo) Serialize() []byte {
+	b := make([]byte, msg.Len())
+	copy(b[0:64], msg.AlgName[:])
+	copy(b[64:68], (*(*[4]byte)(unsafe.Pointer(&msg.AlgKeyLen)))[:])
+	copy(b[68:msg.Len()], msg.AlgKey[:])
+	return b
+}
+
+// struct xfrm_algo_auth {
+//   char    alg_name[64];
+//   unsigned int  alg_key_len;    /* in bits */
+//   unsigned int  alg_trunc_len;  /* in bits */
+//   char    alg_key[0];
+// };
+
+type XfrmAlgoAuth struct {
+	AlgName     [64]byte
+	AlgKeyLen   uint32
+	AlgTruncLen uint32
+	AlgKey      []byte
+}
+
+func (msg *XfrmAlgoAuth) Len() int {
+	return SizeofXfrmAlgoAuth + int(msg.AlgKeyLen/8)
+}
+
+func DeserializeXfrmAlgoAuth(b []byte) *XfrmAlgoAuth {
+	ret := XfrmAlgoAuth{}
+	copy(ret.AlgName[:], b[0:64])
+	ret.AlgKeyLen = *(*uint32)(unsafe.Pointer(&b[64]))
+	ret.AlgTruncLen = *(*uint32)(unsafe.Pointer(&b[68]))
+	ret.AlgKey = b[72:ret.Len()]
+	return &ret
+}
+
+func (msg *XfrmAlgoAuth) Serialize() []byte {
+	b := make([]byte, msg.Len())
+	copy(b[0:64], msg.AlgName[:])
+	copy(b[64:68], (*(*[4]byte)(unsafe.Pointer(&msg.AlgKeyLen)))[:])
+	copy(b[68:72], (*(*[4]byte)(unsafe.Pointer(&msg.AlgTruncLen)))[:])
+	copy(b[72:msg.Len()], msg.AlgKey[:])
+	return b
+}
+
+// struct xfrm_algo_aead {
+//   char    alg_name[64];
+//   unsigned int  alg_key_len;  /* in bits */
+//   unsigned int  alg_icv_len;  /* in bits */
+//   char    alg_key[0];
+// }
+
+// struct xfrm_encap_tmpl {
+//   __u16   encap_type;
+//   __be16    encap_sport;
+//   __be16    encap_dport;
+//   xfrm_address_t  encap_oa;
+// };
+
+type XfrmEncapTmpl struct {
+	EncapType  uint16
+	EncapSport uint16 // big endian
+	EncapDport uint16 // big endian
+	Pad        [2]byte
+	EncapOa    XfrmAddress
+}
+
+func (msg *XfrmEncapTmpl) Len() int {
+	return SizeofXfrmEncapTmpl
+}
+
+func DeserializeXfrmEncapTmpl(b []byte) *XfrmEncapTmpl {
+	return (*XfrmEncapTmpl)(unsafe.Pointer(&b[0:SizeofXfrmEncapTmpl][0]))
+}
+
+func (msg *XfrmEncapTmpl) Serialize() []byte {
+	return (*(*[SizeofXfrmEncapTmpl]byte)(unsafe.Pointer(msg)))[:]
+}

+ 207 - 0
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/nl/xfrm_state_linux_test.go

@@ -0,0 +1,207 @@
+package nl
+
+import (
+	"bytes"
+	"crypto/rand"
+	"encoding/binary"
+	"testing"
+)
+
+func (msg *XfrmUsersaId) write(b []byte) {
+	native := NativeEndian()
+	msg.Daddr.write(b[0:SizeofXfrmAddress])
+	native.PutUint32(b[SizeofXfrmAddress:SizeofXfrmAddress+4], msg.Spi)
+	native.PutUint16(b[SizeofXfrmAddress+4:SizeofXfrmAddress+6], msg.Family)
+	b[SizeofXfrmAddress+6] = msg.Proto
+	b[SizeofXfrmAddress+7] = msg.Pad
+}
+
+func (msg *XfrmUsersaId) serializeSafe() []byte {
+	b := make([]byte, SizeofXfrmUsersaId)
+	msg.write(b)
+	return b
+}
+
+func deserializeXfrmUsersaIdSafe(b []byte) *XfrmUsersaId {
+	var msg = XfrmUsersaId{}
+	binary.Read(bytes.NewReader(b[0:SizeofXfrmUsersaId]), NativeEndian(), &msg)
+	return &msg
+}
+
+func TestXfrmUsersaIdDeserializeSerialize(t *testing.T) {
+	var orig = make([]byte, SizeofXfrmUsersaId)
+	rand.Read(orig)
+	safemsg := deserializeXfrmUsersaIdSafe(orig)
+	msg := DeserializeXfrmUsersaId(orig)
+	testDeserializeSerialize(t, orig, safemsg, msg)
+}
+
+func (msg *XfrmStats) write(b []byte) {
+	native := NativeEndian()
+	native.PutUint32(b[0:4], msg.ReplayWindow)
+	native.PutUint32(b[4:8], msg.Replay)
+	native.PutUint32(b[8:12], msg.IntegrityFailed)
+}
+
+func (msg *XfrmStats) serializeSafe() []byte {
+	b := make([]byte, SizeofXfrmStats)
+	msg.write(b)
+	return b
+}
+
+func deserializeXfrmStatsSafe(b []byte) *XfrmStats {
+	var msg = XfrmStats{}
+	binary.Read(bytes.NewReader(b[0:SizeofXfrmStats]), NativeEndian(), &msg)
+	return &msg
+}
+
+func TestXfrmStatsDeserializeSerialize(t *testing.T) {
+	var orig = make([]byte, SizeofXfrmStats)
+	rand.Read(orig)
+	safemsg := deserializeXfrmStatsSafe(orig)
+	msg := DeserializeXfrmStats(orig)
+	testDeserializeSerialize(t, orig, safemsg, msg)
+}
+
+func (msg *XfrmUsersaInfo) write(b []byte) {
+	const IdEnd = SizeofXfrmSelector + SizeofXfrmId
+	const AddressEnd = IdEnd + SizeofXfrmAddress
+	const CfgEnd = AddressEnd + SizeofXfrmLifetimeCfg
+	const CurEnd = CfgEnd + SizeofXfrmLifetimeCur
+	const StatsEnd = CurEnd + SizeofXfrmStats
+	native := NativeEndian()
+	msg.Sel.write(b[0:SizeofXfrmSelector])
+	msg.Id.write(b[SizeofXfrmSelector:IdEnd])
+	msg.Saddr.write(b[IdEnd:AddressEnd])
+	msg.Lft.write(b[AddressEnd:CfgEnd])
+	msg.Curlft.write(b[CfgEnd:CurEnd])
+	msg.Stats.write(b[CurEnd:StatsEnd])
+	native.PutUint32(b[StatsEnd:StatsEnd+4], msg.Seq)
+	native.PutUint32(b[StatsEnd+4:StatsEnd+8], msg.Reqid)
+	native.PutUint16(b[StatsEnd+8:StatsEnd+10], msg.Family)
+	b[StatsEnd+10] = msg.Mode
+	b[StatsEnd+11] = msg.ReplayWindow
+	b[StatsEnd+12] = msg.Flags
+	copy(b[StatsEnd+13:StatsEnd+20], msg.Pad[:])
+}
+
+func (msg *XfrmUsersaInfo) serializeSafe() []byte {
+	b := make([]byte, SizeofXfrmUsersaInfo)
+	msg.write(b)
+	return b
+}
+
+func deserializeXfrmUsersaInfoSafe(b []byte) *XfrmUsersaInfo {
+	var msg = XfrmUsersaInfo{}
+	binary.Read(bytes.NewReader(b[0:SizeofXfrmUsersaInfo]), NativeEndian(), &msg)
+	return &msg
+}
+
+func TestXfrmUsersaInfoDeserializeSerialize(t *testing.T) {
+	var orig = make([]byte, SizeofXfrmUsersaInfo)
+	rand.Read(orig)
+	safemsg := deserializeXfrmUsersaInfoSafe(orig)
+	msg := DeserializeXfrmUsersaInfo(orig)
+	testDeserializeSerialize(t, orig, safemsg, msg)
+}
+
+func (msg *XfrmAlgo) write(b []byte) {
+	native := NativeEndian()
+	copy(b[0:64], msg.AlgName[:])
+	native.PutUint32(b[64:68], msg.AlgKeyLen)
+	copy(b[68:msg.Len()], msg.AlgKey[:])
+}
+
+func (msg *XfrmAlgo) serializeSafe() []byte {
+	b := make([]byte, msg.Len())
+	msg.write(b)
+	return b
+}
+
+func deserializeXfrmAlgoSafe(b []byte) *XfrmAlgo {
+	var msg = XfrmAlgo{}
+	copy(msg.AlgName[:], b[0:64])
+	binary.Read(bytes.NewReader(b[64:68]), NativeEndian(), &msg.AlgKeyLen)
+	msg.AlgKey = b[68:msg.Len()]
+	return &msg
+}
+
+func TestXfrmAlgoDeserializeSerialize(t *testing.T) {
+	// use a 32 byte key len
+	var orig = make([]byte, SizeofXfrmAlgo+32)
+	rand.Read(orig)
+	// set the key len to 256 bits
+	orig[64] = 0
+	orig[65] = 1
+	orig[66] = 0
+	orig[67] = 0
+	safemsg := deserializeXfrmAlgoSafe(orig)
+	msg := DeserializeXfrmAlgo(orig)
+	testDeserializeSerialize(t, orig, safemsg, msg)
+}
+
+func (msg *XfrmAlgoAuth) write(b []byte) {
+	native := NativeEndian()
+	copy(b[0:64], msg.AlgName[:])
+	native.PutUint32(b[64:68], msg.AlgKeyLen)
+	native.PutUint32(b[68:72], msg.AlgTruncLen)
+	copy(b[72:msg.Len()], msg.AlgKey[:])
+}
+
+func (msg *XfrmAlgoAuth) serializeSafe() []byte {
+	b := make([]byte, msg.Len())
+	msg.write(b)
+	return b
+}
+
+func deserializeXfrmAlgoAuthSafe(b []byte) *XfrmAlgoAuth {
+	var msg = XfrmAlgoAuth{}
+	copy(msg.AlgName[:], b[0:64])
+	binary.Read(bytes.NewReader(b[64:68]), NativeEndian(), &msg.AlgKeyLen)
+	binary.Read(bytes.NewReader(b[68:72]), NativeEndian(), &msg.AlgTruncLen)
+	msg.AlgKey = b[72:msg.Len()]
+	return &msg
+}
+
+func TestXfrmAlgoAuthDeserializeSerialize(t *testing.T) {
+	// use a 32 byte key len
+	var orig = make([]byte, SizeofXfrmAlgoAuth+32)
+	rand.Read(orig)
+	// set the key len to 256 bits
+	orig[64] = 0
+	orig[65] = 1
+	orig[66] = 0
+	orig[67] = 0
+	safemsg := deserializeXfrmAlgoAuthSafe(orig)
+	msg := DeserializeXfrmAlgoAuth(orig)
+	testDeserializeSerialize(t, orig, safemsg, msg)
+}
+
+func (msg *XfrmEncapTmpl) write(b []byte) {
+	native := NativeEndian()
+	native.PutUint16(b[0:2], msg.EncapType)
+	native.PutUint16(b[2:4], msg.EncapSport)
+	native.PutUint16(b[4:6], msg.EncapDport)
+	copy(b[6:8], msg.Pad[:])
+	msg.EncapOa.write(b[8:SizeofXfrmAddress])
+}
+
+func (msg *XfrmEncapTmpl) serializeSafe() []byte {
+	b := make([]byte, SizeofXfrmEncapTmpl)
+	msg.write(b)
+	return b
+}
+
+func deserializeXfrmEncapTmplSafe(b []byte) *XfrmEncapTmpl {
+	var msg = XfrmEncapTmpl{}
+	binary.Read(bytes.NewReader(b[0:SizeofXfrmEncapTmpl]), NativeEndian(), &msg)
+	return &msg
+}
+
+func TestXfrmEncapTmplDeserializeSerialize(t *testing.T) {
+	var orig = make([]byte, SizeofXfrmEncapTmpl)
+	rand.Read(orig)
+	safemsg := deserializeXfrmEncapTmplSafe(orig)
+	msg := DeserializeXfrmEncapTmpl(orig)
+	testDeserializeSerialize(t, orig, safemsg, msg)
+}

+ 53 - 0
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/protinfo.go

@@ -0,0 +1,53 @@
+package netlink
+
+import (
+	"strings"
+)
+
+// Protinfo represents bridge flags from netlink.
+type Protinfo struct {
+	Hairpin   bool
+	Guard     bool
+	FastLeave bool
+	RootBlock bool
+	Learning  bool
+	Flood     bool
+}
+
+// String returns a list of enabled flags
+func (prot *Protinfo) String() string {
+	boolStrings := make([]string, 0)
+	if prot.Hairpin {
+		boolStrings = append(boolStrings, "Hairpin")
+	}
+	if prot.Guard {
+		boolStrings = append(boolStrings, "Guard")
+	}
+	if prot.FastLeave {
+		boolStrings = append(boolStrings, "FastLeave")
+	}
+	if prot.RootBlock {
+		boolStrings = append(boolStrings, "RootBlock")
+	}
+	if prot.Learning {
+		boolStrings = append(boolStrings, "Learning")
+	}
+	if prot.Flood {
+		boolStrings = append(boolStrings, "Flood")
+	}
+	return strings.Join(boolStrings, " ")
+}
+
+func boolToByte(x bool) []byte {
+	if x {
+		return []byte{1}
+	}
+	return []byte{0}
+}
+
+func byteToBool(x byte) bool {
+	if uint8(x) != 0 {
+		return true
+	}
+	return false
+}

+ 60 - 0
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/protinfo_linux.go

@@ -0,0 +1,60 @@
+package netlink
+
+import (
+	"fmt"
+	"syscall"
+
+	"github.com/vishvananda/netlink/nl"
+)
+
+func LinkGetProtinfo(link Link) (Protinfo, error) {
+	base := link.Attrs()
+	ensureIndex(base)
+	var pi Protinfo
+	req := nl.NewNetlinkRequest(syscall.RTM_GETLINK, syscall.NLM_F_DUMP)
+	msg := nl.NewIfInfomsg(syscall.AF_BRIDGE)
+	req.AddData(msg)
+	msgs, err := req.Execute(syscall.NETLINK_ROUTE, 0)
+	if err != nil {
+		return pi, err
+	}
+
+	for _, m := range msgs {
+		ans := nl.DeserializeIfInfomsg(m)
+		if int(ans.Index) != base.Index {
+			continue
+		}
+		attrs, err := nl.ParseRouteAttr(m[ans.Len():])
+		if err != nil {
+			return pi, err
+		}
+		for _, attr := range attrs {
+			if attr.Attr.Type != syscall.IFLA_PROTINFO|syscall.NLA_F_NESTED {
+				continue
+			}
+			infos, err := nl.ParseRouteAttr(attr.Value)
+			if err != nil {
+				return pi, err
+			}
+			var pi Protinfo
+			for _, info := range infos {
+				switch info.Attr.Type {
+				case nl.IFLA_BRPORT_MODE:
+					pi.Hairpin = byteToBool(info.Value[0])
+				case nl.IFLA_BRPORT_GUARD:
+					pi.Guard = byteToBool(info.Value[0])
+				case nl.IFLA_BRPORT_FAST_LEAVE:
+					pi.FastLeave = byteToBool(info.Value[0])
+				case nl.IFLA_BRPORT_PROTECT:
+					pi.RootBlock = byteToBool(info.Value[0])
+				case nl.IFLA_BRPORT_LEARNING:
+					pi.Learning = byteToBool(info.Value[0])
+				case nl.IFLA_BRPORT_UNICAST_FLOOD:
+					pi.Flood = byteToBool(info.Value[0])
+				}
+			}
+			return pi, nil
+		}
+	}
+	return pi, fmt.Errorf("Device with index %d not found", base.Index)
+}

+ 98 - 0
libnetwork/Godeps/_workspace/src/github.com/vishvananda/netlink/protinfo_test.go

@@ -0,0 +1,98 @@
+package netlink
+
+import "testing"
+
+func TestProtinfo(t *testing.T) {
+	tearDown := setUpNetlinkTest(t)
+	defer tearDown()
+	master := &Bridge{LinkAttrs{Name: "foo"}}
+	if err := LinkAdd(master); err != nil {
+		t.Fatal(err)
+	}
+	iface1 := &Dummy{LinkAttrs{Name: "bar1", MasterIndex: master.Index}}
+	iface2 := &Dummy{LinkAttrs{Name: "bar2", MasterIndex: master.Index}}
+	iface3 := &Dummy{LinkAttrs{Name: "bar3"}}
+
+	if err := LinkAdd(iface1); err != nil {
+		t.Fatal(err)
+	}
+	if err := LinkAdd(iface2); err != nil {
+		t.Fatal(err)
+	}
+	if err := LinkAdd(iface3); err != nil {
+		t.Fatal(err)
+	}
+
+	oldpi1, err := LinkGetProtinfo(iface1)
+	if err != nil {
+		t.Fatal(err)
+	}
+	oldpi2, err := LinkGetProtinfo(iface2)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if err := LinkSetHairpin(iface1, true); err != nil {
+		t.Fatal(err)
+	}
+
+	if err := LinkSetRootBlock(iface1, true); err != nil {
+		t.Fatal(err)
+	}
+
+	pi1, err := LinkGetProtinfo(iface1)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if !pi1.Hairpin {
+		t.Fatalf("Hairpin mode is not enabled for %s, but should", iface1.Name)
+	}
+	if !pi1.RootBlock {
+		t.Fatalf("RootBlock is not enabled for %s, but should", iface1.Name)
+	}
+	if pi1.Guard != oldpi1.Guard {
+		t.Fatalf("Guard field was changed for %s but shouldn't", iface1.Name)
+	}
+	if pi1.FastLeave != oldpi1.FastLeave {
+		t.Fatalf("FastLeave field was changed for %s but shouldn't", iface1.Name)
+	}
+	if pi1.Learning != oldpi1.Learning {
+		t.Fatalf("Learning field was changed for %s but shouldn't", iface1.Name)
+	}
+	if pi1.Flood != oldpi1.Flood {
+		t.Fatalf("Flood field was changed for %s but shouldn't", iface1.Name)
+	}
+
+	if err := LinkSetGuard(iface2, true); err != nil {
+		t.Fatal(err)
+	}
+	if err := LinkSetLearning(iface2, false); err != nil {
+		t.Fatal(err)
+	}
+	pi2, err := LinkGetProtinfo(iface2)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if pi2.Hairpin {
+		t.Fatalf("Hairpin mode is enabled for %s, but shouldn't", iface2.Name)
+	}
+	if !pi2.Guard {
+		t.Fatalf("Guard is not enabled for %s, but should", iface2.Name)
+	}
+	if pi2.Learning {
+		t.Fatalf("Learning is enabled for %s, but shouldn't", iface2.Name)
+	}
+	if pi2.RootBlock != oldpi2.RootBlock {
+		t.Fatalf("RootBlock field was changed for %s but shouldn't", iface2.Name)
+	}
+	if pi2.FastLeave != oldpi2.FastLeave {
+		t.Fatalf("FastLeave field was changed for %s but shouldn't", iface2.Name)
+	}
+	if pi2.Flood != oldpi2.Flood {
+		t.Fatalf("Flood field was changed for %s but shouldn't", iface2.Name)
+	}
+
+	if err := LinkSetHairpin(iface3, true); err == nil || err.Error() != "operation not supported" {
+		t.Fatalf("Set protinfo attrs for link without master is not supported, but err: %s", err)
+	}
+}

Деякі файли не було показано, через те що забагато файлів було змінено