Vendoring libnetwork @9ab6e13
| ... | ... |
@@ -71,7 +71,7 @@ clone git github.com/RackSec/srslog 365bf33cd9acc21ae1c355209865f17228ca534e |
| 71 | 71 |
clone git github.com/imdario/mergo 0.2.1 |
| 72 | 72 |
|
| 73 | 73 |
#get libnetwork packages |
| 74 |
-clone git github.com/docker/libnetwork f4338b6f1085ccfe5972e655cca8a1d15d73439d |
|
| 74 |
+clone git github.com/docker/libnetwork 9ab6e136fa628b5bb4af4a75f76609ef2c21c024 |
|
| 75 | 75 |
clone git github.com/docker/go-events 18b43f1bc85d9cdd42c05a6cd2d444c7a200a894 |
| 76 | 76 |
clone git github.com/armon/go-radix e39d623f12e8e41c7b5529e9a9dd67a1e2261f80 |
| 77 | 77 |
clone git github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec |
| ... | ... |
@@ -1655,17 +1655,16 @@ func (s *DockerSuite) TestDockerNetworkInternalMode(c *check.C) {
|
| 1655 | 1655 |
c.Assert(err, check.IsNil) |
| 1656 | 1656 |
} |
| 1657 | 1657 |
|
| 1658 |
-// Test for #21401 |
|
| 1658 |
+// Test for special characters in network names. only [a-zA-Z0-9][a-zA-Z0-9_.-] are |
|
| 1659 |
+// valid characters |
|
| 1659 | 1660 |
func (s *DockerNetworkSuite) TestDockerNetworkCreateDeleteSpecialCharacters(c *check.C) {
|
| 1660 |
- dockerCmd(c, "network", "create", "test@#$") |
|
| 1661 |
- assertNwIsAvailable(c, "test@#$") |
|
| 1662 |
- dockerCmd(c, "network", "rm", "test@#$") |
|
| 1663 |
- assertNwNotAvailable(c, "test@#$") |
|
| 1664 |
- |
|
| 1665 |
- dockerCmd(c, "network", "create", "kiwl$%^") |
|
| 1666 |
- assertNwIsAvailable(c, "kiwl$%^") |
|
| 1667 |
- dockerCmd(c, "network", "rm", "kiwl$%^") |
|
| 1668 |
- assertNwNotAvailable(c, "kiwl$%^") |
|
| 1661 |
+ _, _, err := dockerCmdWithError("network", "create", "test@#$")
|
|
| 1662 |
+ c.Assert(err, check.NotNil) |
|
| 1663 |
+ |
|
| 1664 |
+ dockerCmd(c, "network", "create", "test-1_0.net") |
|
| 1665 |
+ assertNwIsAvailable(c, "test-1_0.net") |
|
| 1666 |
+ dockerCmd(c, "network", "rm", "test-1_0.net") |
|
| 1667 |
+ assertNwNotAvailable(c, "test-1_0.net") |
|
| 1669 | 1668 |
} |
| 1670 | 1669 |
|
| 1671 | 1670 |
func (s *DockerDaemonSuite) TestDaemonRestartRestoreBridgeNetwork(t *check.C) {
|
| ... | ... |
@@ -328,22 +328,26 @@ func (c *controller) agentDriverNotify(d driverapi.Driver) {
|
| 328 | 328 |
} |
| 329 | 329 |
|
| 330 | 330 |
func (c *controller) agentClose() {
|
| 331 |
- if c.agent == nil {
|
|
| 331 |
+ // Acquire current agent instance and reset its pointer |
|
| 332 |
+ // then run closing functions |
|
| 333 |
+ c.Lock() |
|
| 334 |
+ agent := c.agent |
|
| 335 |
+ c.agent = nil |
|
| 336 |
+ c.Unlock() |
|
| 337 |
+ |
|
| 338 |
+ if agent == nil {
|
|
| 332 | 339 |
return |
| 333 | 340 |
} |
| 334 | 341 |
|
| 335 |
- for _, cancelFuncs := range c.agent.driverCancelFuncs {
|
|
| 342 |
+ for _, cancelFuncs := range agent.driverCancelFuncs {
|
|
| 336 | 343 |
for _, cancel := range cancelFuncs {
|
| 337 | 344 |
cancel() |
| 338 | 345 |
} |
| 339 | 346 |
} |
| 340 |
- c.agent.epTblCancel() |
|
| 341 | 347 |
|
| 342 |
- c.agent.networkDB.Close() |
|
| 348 |
+ agent.epTblCancel() |
|
| 343 | 349 |
|
| 344 |
- c.Lock() |
|
| 345 |
- c.agent = nil |
|
| 346 |
- c.Unlock() |
|
| 350 |
+ agent.networkDB.Close() |
|
| 347 | 351 |
} |
| 348 | 352 |
|
| 349 | 353 |
func (n *network) isClusterEligible() bool {
|
| ... | ... |
@@ -1,6 +1,8 @@ |
| 1 | 1 |
package config |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
+ "fmt" |
|
| 5 |
+ "regexp" |
|
| 4 | 6 |
"strings" |
| 5 | 7 |
|
| 6 | 8 |
"github.com/BurntSushi/toml" |
| ... | ... |
@@ -15,6 +17,12 @@ import ( |
| 15 | 15 |
"github.com/docker/libnetwork/osl" |
| 16 | 16 |
) |
| 17 | 17 |
|
| 18 |
+// RestrictedNameChars collects the characters allowed to represent a network or endpoint name. |
|
| 19 |
+const restrictedNameChars = `[a-zA-Z0-9][a-zA-Z0-9_.-]` |
|
| 20 |
+ |
|
| 21 |
+// RestrictedNamePattern is a regular expression to validate names against the collection of restricted characters. |
|
| 22 |
+var restrictedNamePattern = regexp.MustCompile(`^/?` + restrictedNameChars + `+$`) |
|
| 23 |
+ |
|
| 18 | 24 |
// Config encapsulates configurations of various Libnetwork components |
| 19 | 25 |
type Config struct {
|
| 20 | 26 |
Daemon DaemonCfg |
| ... | ... |
@@ -223,12 +231,12 @@ func (c *Config) ProcessOptions(options ...Option) {
|
| 223 | 223 |
} |
| 224 | 224 |
} |
| 225 | 225 |
|
| 226 |
-// IsValidName validates configuration objects supported by libnetwork |
|
| 227 |
-func IsValidName(name string) bool {
|
|
| 228 |
- if strings.TrimSpace(name) == "" {
|
|
| 229 |
- return false |
|
| 226 |
+// ValidateName validates configuration objects supported by libnetwork |
|
| 227 |
+func ValidateName(name string) error {
|
|
| 228 |
+ if !restrictedNamePattern.MatchString(name) {
|
|
| 229 |
+ return fmt.Errorf("%s includes invalid characters, only %q are allowed", name, restrictedNameChars)
|
|
| 230 | 230 |
} |
| 231 |
- return true |
|
| 231 |
+ return nil |
|
| 232 | 232 |
} |
| 233 | 233 |
|
| 234 | 234 |
// OptionLocalKVProvider function returns an option setter for kvstore provider |
| ... | ... |
@@ -626,8 +626,8 @@ func (c *controller) NewNetwork(networkType, name string, id string, options ... |
| 626 | 626 |
} |
| 627 | 627 |
} |
| 628 | 628 |
|
| 629 |
- if !config.IsValidName(name) {
|
|
| 630 |
- return nil, ErrInvalidName(name) |
|
| 629 |
+ if err := config.ValidateName(name); err != nil {
|
|
| 630 |
+ return nil, ErrInvalidName(err.Error()) |
|
| 631 | 631 |
} |
| 632 | 632 |
|
| 633 | 633 |
if id == "" {
|
| ... | ... |
@@ -145,7 +145,7 @@ func makeDefaultScopes() map[string]*ScopeCfg {
|
| 145 | 145 |
var defaultRootChain = []string{"docker", "network", "v1.0"}
|
| 146 | 146 |
var rootChain = defaultRootChain |
| 147 | 147 |
|
| 148 |
-// DefaultScopes returns a map of default scopes and it's config for clients to use. |
|
| 148 |
+// DefaultScopes returns a map of default scopes and its config for clients to use. |
|
| 149 | 149 |
func DefaultScopes(dataDir string) map[string]*ScopeCfg {
|
| 150 | 150 |
if dataDir != "" {
|
| 151 | 151 |
defaultScopes[LocalScope].Client.Address = dataDir + "/network/files/local-kv.db" |
| ... | ... |
@@ -1,6 +1,6 @@ |
| 1 | 1 |
package discoverapi |
| 2 | 2 |
|
| 3 |
-// Discover is an interface to be implemented by the componenet interested in receiving discover events |
|
| 3 |
+// Discover is an interface to be implemented by the component interested in receiving discover events |
|
| 4 | 4 |
// like new node joining the cluster or datastore updates |
| 5 | 5 |
type Discover interface {
|
| 6 | 6 |
// DiscoverNew is a notification for a new discovery event, Example:a new node joining a cluster |
| ... | ... |
@@ -79,11 +79,11 @@ func (n *bridgeNetwork) setupIPTables(config *networkConfiguration, i *bridgeInt |
| 79 | 79 |
Mask: i.bridgeIPv4.Mask, |
| 80 | 80 |
} |
| 81 | 81 |
if config.Internal {
|
| 82 |
- if err = setupInternalNetworkRules(config.BridgeName, maskedAddrv4, true); err != nil {
|
|
| 82 |
+ if err = setupInternalNetworkRules(config.BridgeName, maskedAddrv4, config.EnableICC, true); err != nil {
|
|
| 83 | 83 |
return fmt.Errorf("Failed to Setup IP tables: %s", err.Error())
|
| 84 | 84 |
} |
| 85 | 85 |
n.registerIptCleanFunc(func() error {
|
| 86 |
- return setupInternalNetworkRules(config.BridgeName, maskedAddrv4, false) |
|
| 86 |
+ return setupInternalNetworkRules(config.BridgeName, maskedAddrv4, config.EnableICC, false) |
|
| 87 | 87 |
}) |
| 88 | 88 |
} else {
|
| 89 | 89 |
if err = setupIPTablesInternal(config.BridgeName, maskedAddrv4, config.EnableICC, config.EnableIPMasquerade, hairpinMode, true); err != nil {
|
| ... | ... |
@@ -333,7 +333,7 @@ func removeIPChains() {
|
| 333 | 333 |
} |
| 334 | 334 |
} |
| 335 | 335 |
|
| 336 |
-func setupInternalNetworkRules(bridgeIface string, addr net.Addr, insert bool) error {
|
|
| 336 |
+func setupInternalNetworkRules(bridgeIface string, addr net.Addr, icc, insert bool) error {
|
|
| 337 | 337 |
var ( |
| 338 | 338 |
inDropRule = iptRule{table: iptables.Filter, chain: IsolationChain, args: []string{"-i", bridgeIface, "!", "-d", addr.String(), "-j", "DROP"}}
|
| 339 | 339 |
outDropRule = iptRule{table: iptables.Filter, chain: IsolationChain, args: []string{"-o", bridgeIface, "!", "-s", addr.String(), "-j", "DROP"}}
|
| ... | ... |
@@ -344,5 +344,9 @@ func setupInternalNetworkRules(bridgeIface string, addr net.Addr, insert bool) e |
| 344 | 344 |
if err := programChainRule(outDropRule, "DROP OUTGOING", insert); err != nil {
|
| 345 | 345 |
return err |
| 346 | 346 |
} |
| 347 |
+ // Set Inter Container Communication. |
|
| 348 |
+ if err := setIcc(bridgeIface, icc, insert); err != nil {
|
|
| 349 |
+ return err |
|
| 350 |
+ } |
|
| 347 | 351 |
return nil |
| 348 | 352 |
} |
| ... | ... |
@@ -66,7 +66,7 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, |
| 66 | 66 |
return nil |
| 67 | 67 |
} |
| 68 | 68 |
|
| 69 |
-// DeleteEndpoint remove the endpoint and associated netlink interface |
|
| 69 |
+// DeleteEndpoint removes the endpoint and associated netlink interface |
|
| 70 | 70 |
func (d *driver) DeleteEndpoint(nid, eid string) error {
|
| 71 | 71 |
defer osl.InitOSContext()() |
| 72 | 72 |
if err := validateID(nid, eid); err != nil {
|
| ... | ... |
@@ -124,7 +124,7 @@ func (d *driver) createNetwork(config *configuration) error {
|
| 124 | 124 |
return nil |
| 125 | 125 |
} |
| 126 | 126 |
|
| 127 |
-// DeleteNetwork the network for the specified driver type |
|
| 127 |
+// DeleteNetwork deletes the network for the specified driver type |
|
| 128 | 128 |
func (d *driver) DeleteNetwork(nid string) error {
|
| 129 | 129 |
defer osl.InitOSContext()() |
| 130 | 130 |
n := d.network(nid) |
| ... | ... |
@@ -171,7 +171,7 @@ func (d *driver) DeleteNetwork(nid string) error {
|
| 171 | 171 |
return nil |
| 172 | 172 |
} |
| 173 | 173 |
|
| 174 |
-// parseNetworkOptions parse docker network options |
|
| 174 |
+// parseNetworkOptions parses docker network options |
|
| 175 | 175 |
func parseNetworkOptions(id string, option options.Generic) (*configuration, error) {
|
| 176 | 176 |
var ( |
| 177 | 177 |
err error |
| ... | ... |
@@ -193,7 +193,7 @@ func parseNetworkOptions(id string, option options.Generic) (*configuration, err |
| 193 | 193 |
return config, nil |
| 194 | 194 |
} |
| 195 | 195 |
|
| 196 |
-// parseNetworkGenericOptions parse generic driver docker network options |
|
| 196 |
+// parseNetworkGenericOptions parses generic driver docker network options |
|
| 197 | 197 |
func parseNetworkGenericOptions(data interface{}) (*configuration, error) {
|
| 198 | 198 |
var ( |
| 199 | 199 |
err error |
| ... | ... |
@@ -64,7 +64,7 @@ func setMacVlanMode(mode string) (netlink.MacvlanMode, error) {
|
| 64 | 64 |
} |
| 65 | 65 |
} |
| 66 | 66 |
|
| 67 |
-// parentExists check if the specified interface exists in the default namespace |
|
| 67 |
+// parentExists checks if the specified interface exists in the default namespace |
|
| 68 | 68 |
func parentExists(ifaceStr string) bool {
|
| 69 | 69 |
_, err := ns.NlHandle().LinkByName(ifaceStr) |
| 70 | 70 |
if err != nil {
|
| ... | ... |
@@ -469,12 +469,14 @@ func (ep *endpoint) sbJoin(sb *sandbox, options ...EndpointOption) error {
|
| 469 | 469 |
n.getController().watchSvcRecord(ep) |
| 470 | 470 |
} |
| 471 | 471 |
|
| 472 |
- address := "" |
|
| 473 |
- if ip := ep.getFirstInterfaceAddress(); ip != nil {
|
|
| 474 |
- address = ip.String() |
|
| 475 |
- } |
|
| 476 |
- if err = sb.updateHostsFile(address); err != nil {
|
|
| 477 |
- return err |
|
| 472 |
+ if doUpdateHostsFile(n, sb) {
|
|
| 473 |
+ address := "" |
|
| 474 |
+ if ip := ep.getFirstInterfaceAddress(); ip != nil {
|
|
| 475 |
+ address = ip.String() |
|
| 476 |
+ } |
|
| 477 |
+ if err = sb.updateHostsFile(address); err != nil {
|
|
| 478 |
+ return err |
|
| 479 |
+ } |
|
| 478 | 480 |
} |
| 479 | 481 |
if err = sb.updateDNS(n.enableIPv6); err != nil {
|
| 480 | 482 |
return err |
| ... | ... |
@@ -556,6 +558,10 @@ func (ep *endpoint) sbJoin(sb *sandbox, options ...EndpointOption) error {
|
| 556 | 556 |
return nil |
| 557 | 557 |
} |
| 558 | 558 |
|
| 559 |
+func doUpdateHostsFile(n *network, sb *sandbox) bool {
|
|
| 560 |
+ return !n.ingress && n.Name() != libnGWNetwork |
|
| 561 |
+} |
|
| 562 |
+ |
|
| 559 | 563 |
func (ep *endpoint) rename(name string) error {
|
| 560 | 564 |
var err error |
| 561 | 565 |
n := ep.getNetwork() |
| ... | ... |
@@ -783,7 +789,7 @@ func (ep *endpoint) Delete(force bool) error {
|
| 783 | 783 |
ep.releaseAddress() |
| 784 | 784 |
|
| 785 | 785 |
if err := n.getEpCnt().DecEndpointCnt(); err != nil {
|
| 786 |
- log.Warnf("failed to decrement endpoint coint for ep %s: %v", ep.ID(), err)
|
|
| 786 |
+ log.Warnf("failed to decrement endpoint count for ep %s: %v", ep.ID(), err)
|
|
| 787 | 787 |
} |
| 788 | 788 |
|
| 789 | 789 |
return nil |
| ... | ... |
@@ -1125,3 +1131,20 @@ func (c *controller) cleanupLocalEndpoints() {
|
| 1125 | 1125 |
} |
| 1126 | 1126 |
} |
| 1127 | 1127 |
} |
| 1128 |
+ |
|
| 1129 |
+func (ep *endpoint) setAliasIP(sb *sandbox, ip net.IP, add bool) error {
|
|
| 1130 |
+ sb.Lock() |
|
| 1131 |
+ sbox := sb.osSbox |
|
| 1132 |
+ sb.Unlock() |
|
| 1133 |
+ |
|
| 1134 |
+ for _, i := range sbox.Info().Interfaces() {
|
|
| 1135 |
+ if ep.hasInterface(i.SrcName()) {
|
|
| 1136 |
+ ipNet := &net.IPNet{IP: ip, Mask: []byte{255, 255, 255, 255}}
|
|
| 1137 |
+ if err := i.SetAliasIP(ipNet, add); err != nil {
|
|
| 1138 |
+ return err |
|
| 1139 |
+ } |
|
| 1140 |
+ break |
|
| 1141 |
+ } |
|
| 1142 |
+ } |
|
| 1143 |
+ return nil |
|
| 1144 |
+} |
| ... | ... |
@@ -69,7 +69,7 @@ func (ii ErrInvalidID) Error() string {
|
| 69 | 69 |
func (ii ErrInvalidID) BadRequest() {}
|
| 70 | 70 |
|
| 71 | 71 |
// ErrInvalidName is returned when a query-by-name or resource create method is |
| 72 |
-// invoked with an empty name parameter |
|
| 72 |
+// invoked with an invalid name parameter |
|
| 73 | 73 |
type ErrInvalidName string |
| 74 | 74 |
|
| 75 | 75 |
func (in ErrInvalidName) Error() string {
|
| ... | ... |
@@ -107,7 +107,7 @@ func (nnr NetworkNameError) Error() string {
|
| 107 | 107 |
// Forbidden denotes the type of this error |
| 108 | 108 |
func (nnr NetworkNameError) Forbidden() {}
|
| 109 | 109 |
|
| 110 |
-// UnknownNetworkError is returned when libnetwork could not find in it's database |
|
| 110 |
+// UnknownNetworkError is returned when libnetwork could not find in its database |
|
| 111 | 111 |
// a network with the same name and id. |
| 112 | 112 |
type UnknownNetworkError struct {
|
| 113 | 113 |
name string |
| ... | ... |
@@ -135,7 +135,7 @@ func (aee *ActiveEndpointsError) Error() string {
|
| 135 | 135 |
// Forbidden denotes the type of this error |
| 136 | 136 |
func (aee *ActiveEndpointsError) Forbidden() {}
|
| 137 | 137 |
|
| 138 |
-// UnknownEndpointError is returned when libnetwork could not find in it's database |
|
| 138 |
+// UnknownEndpointError is returned when libnetwork could not find in its database |
|
| 139 | 139 |
// an endpoint with the same name and id. |
| 140 | 140 |
type UnknownEndpointError struct {
|
| 141 | 141 |
name string |
| ... | ... |
@@ -326,6 +326,21 @@ func (c *ChainInfo) Remove() error {
|
| 326 | 326 |
|
| 327 | 327 |
// Exists checks if a rule exists |
| 328 | 328 |
func Exists(table Table, chain string, rule ...string) bool {
|
| 329 |
+ return exists(false, table, chain, rule...) |
|
| 330 |
+} |
|
| 331 |
+ |
|
| 332 |
+// ExistsNative behaves as Exists with the difference it |
|
| 333 |
+// will always invoke `iptables` binary. |
|
| 334 |
+func ExistsNative(table Table, chain string, rule ...string) bool {
|
|
| 335 |
+ return exists(true, table, chain, rule...) |
|
| 336 |
+} |
|
| 337 |
+ |
|
| 338 |
+func exists(native bool, table Table, chain string, rule ...string) bool {
|
|
| 339 |
+ f := Raw |
|
| 340 |
+ if native {
|
|
| 341 |
+ f = raw |
|
| 342 |
+ } |
|
| 343 |
+ |
|
| 329 | 344 |
if string(table) == "" {
|
| 330 | 345 |
table = Filter |
| 331 | 346 |
} |
| ... | ... |
@@ -334,7 +349,7 @@ func Exists(table Table, chain string, rule ...string) bool {
|
| 334 | 334 |
|
| 335 | 335 |
if supportsCOpt {
|
| 336 | 336 |
// if exit status is 0 then return true, the rule exists |
| 337 |
- _, err := Raw(append([]string{"-t", string(table), "-C", chain}, rule...)...)
|
|
| 337 |
+ _, err := f(append([]string{"-t", string(table), "-C", chain}, rule...)...)
|
|
| 338 | 338 |
return err == nil |
| 339 | 339 |
} |
| 340 | 340 |
|
| ... | ... |
@@ -17,6 +17,7 @@ import ( |
| 17 | 17 |
"github.com/docker/libnetwork/ipamapi" |
| 18 | 18 |
"github.com/docker/libnetwork/netlabel" |
| 19 | 19 |
"github.com/docker/libnetwork/netutils" |
| 20 |
+ "github.com/docker/libnetwork/networkdb" |
|
| 20 | 21 |
"github.com/docker/libnetwork/options" |
| 21 | 22 |
"github.com/docker/libnetwork/types" |
| 22 | 23 |
) |
| ... | ... |
@@ -34,7 +35,7 @@ type Network interface {
|
| 34 | 34 |
Type() string |
| 35 | 35 |
|
| 36 | 36 |
// Create a new endpoint to this network symbolically identified by the |
| 37 |
- // specified unique name. The options parameter carry driver specific options. |
|
| 37 |
+ // specified unique name. The options parameter carries driver specific options. |
|
| 38 | 38 |
CreateEndpoint(name string, options ...EndpointOption) (Endpoint, error) |
| 39 | 39 |
|
| 40 | 40 |
// Delete the network. |
| ... | ... |
@@ -67,6 +68,11 @@ type NetworkInfo interface {
|
| 67 | 67 |
Labels() map[string]string |
| 68 | 68 |
Dynamic() bool |
| 69 | 69 |
Created() time.Time |
| 70 |
+ // Peers returns a slice of PeerInfo structures which has the information about the peer |
|
| 71 |
+ // nodes participating in the same overlay network. This is currently the per-network |
|
| 72 |
+ // gossip cluster. For non-dynamic overlay networks and bridge networks it returns an |
|
| 73 |
+ // empty slice |
|
| 74 |
+ Peers() []networkdb.PeerInfo |
|
| 70 | 75 |
} |
| 71 | 76 |
|
| 72 | 77 |
// EndpointWalker is a client provided function which will be used to walk the Endpoints. |
| ... | ... |
@@ -848,8 +854,9 @@ func (n *network) addEndpoint(ep *endpoint) error {
|
| 848 | 848 |
|
| 849 | 849 |
func (n *network) CreateEndpoint(name string, options ...EndpointOption) (Endpoint, error) {
|
| 850 | 850 |
var err error |
| 851 |
- if !config.IsValidName(name) {
|
|
| 852 |
- return nil, ErrInvalidName(name) |
|
| 851 |
+ |
|
| 852 |
+ if err = config.ValidateName(name); err != nil {
|
|
| 853 |
+ return nil, ErrInvalidName(err.Error()) |
|
| 853 | 854 |
} |
| 854 | 855 |
|
| 855 | 856 |
if _, err = n.EndpointByName(name); err == nil {
|
| ... | ... |
@@ -1459,6 +1466,24 @@ func (n *network) Info() NetworkInfo {
|
| 1459 | 1459 |
return n |
| 1460 | 1460 |
} |
| 1461 | 1461 |
|
| 1462 |
+func (n *network) Peers() []networkdb.PeerInfo {
|
|
| 1463 |
+ if !n.Dynamic() {
|
|
| 1464 |
+ return []networkdb.PeerInfo{}
|
|
| 1465 |
+ } |
|
| 1466 |
+ |
|
| 1467 |
+ var nDB *networkdb.NetworkDB |
|
| 1468 |
+ n.ctrlr.Lock() |
|
| 1469 |
+ if n.ctrlr.agentInitDone == nil && n.ctrlr.agent != nil {
|
|
| 1470 |
+ nDB = n.ctrlr.agent.networkDB |
|
| 1471 |
+ } |
|
| 1472 |
+ n.ctrlr.Unlock() |
|
| 1473 |
+ |
|
| 1474 |
+ if nDB != nil {
|
|
| 1475 |
+ return n.ctrlr.agent.networkDB.Peers(n.id) |
|
| 1476 |
+ } |
|
| 1477 |
+ return []networkdb.PeerInfo{}
|
|
| 1478 |
+} |
|
| 1479 |
+ |
|
| 1462 | 1480 |
func (n *network) DriverOptions() map[string]string {
|
| 1463 | 1481 |
n.Lock() |
| 1464 | 1482 |
defer n.Unlock() |
| ... | ... |
@@ -30,6 +30,10 @@ func (n *network) startResolver() {
|
| 30 | 30 |
options := n.Info().DriverOptions() |
| 31 | 31 |
hnsid := options[windows.HNSID] |
| 32 | 32 |
|
| 33 |
+ if hnsid == "" {
|
|
| 34 |
+ return |
|
| 35 |
+ } |
|
| 36 |
+ |
|
| 33 | 37 |
hnsresponse, err := hcsshim.HNSNetworkRequest("GET", hnsid, "")
|
| 34 | 38 |
if err != nil {
|
| 35 | 39 |
log.Errorf("Resolver Setup/Start failed for container %s, %q", n.Name(), err)
|
| ... | ... |
@@ -91,6 +91,12 @@ type NetworkDB struct {
|
| 91 | 91 |
keyring *memberlist.Keyring |
| 92 | 92 |
} |
| 93 | 93 |
|
| 94 |
+// PeerInfo represents the peer (gossip cluster) nodes of a network |
|
| 95 |
+type PeerInfo struct {
|
|
| 96 |
+ Name string |
|
| 97 |
+ IP string |
|
| 98 |
+} |
|
| 99 |
+ |
|
| 94 | 100 |
type node struct {
|
| 95 | 101 |
memberlist.Node |
| 96 | 102 |
ltime serf.LamportTime |
| ... | ... |
@@ -200,6 +206,20 @@ func (nDB *NetworkDB) Close() {
|
| 200 | 200 |
} |
| 201 | 201 |
} |
| 202 | 202 |
|
| 203 |
+// Peers returns the gossip peers for a given network. |
|
| 204 |
+func (nDB *NetworkDB) Peers(nid string) []PeerInfo {
|
|
| 205 |
+ nDB.RLock() |
|
| 206 |
+ defer nDB.RUnlock() |
|
| 207 |
+ peers := make([]PeerInfo, 0, len(nDB.networkNodes[nid])) |
|
| 208 |
+ for _, nodeName := range nDB.networkNodes[nid] {
|
|
| 209 |
+ peers = append(peers, PeerInfo{
|
|
| 210 |
+ Name: nDB.nodes[nodeName].Name, |
|
| 211 |
+ IP: nDB.nodes[nodeName].Addr.String(), |
|
| 212 |
+ }) |
|
| 213 |
+ } |
|
| 214 |
+ return peers |
|
| 215 |
+} |
|
| 216 |
+ |
|
| 203 | 217 |
// GetEntry retrieves the value of a table entry in a given (network, |
| 204 | 218 |
// table, key) tuple |
| 205 | 219 |
func (nDB *NetworkDB) GetEntry(tname, nid, key string) ([]byte, error) {
|
| ... | ... |
@@ -26,7 +26,6 @@ type nwIface struct {
|
| 26 | 26 |
mac net.HardwareAddr |
| 27 | 27 |
address *net.IPNet |
| 28 | 28 |
addressIPv6 *net.IPNet |
| 29 |
- ipAliases []*net.IPNet |
|
| 30 | 29 |
llAddrs []*net.IPNet |
| 31 | 30 |
routes []*net.IPNet |
| 32 | 31 |
bridge bool |
| ... | ... |
@@ -97,13 +96,6 @@ func (i *nwIface) LinkLocalAddresses() []*net.IPNet {
|
| 97 | 97 |
return i.llAddrs |
| 98 | 98 |
} |
| 99 | 99 |
|
| 100 |
-func (i *nwIface) IPAliases() []*net.IPNet {
|
|
| 101 |
- i.Lock() |
|
| 102 |
- defer i.Unlock() |
|
| 103 |
- |
|
| 104 |
- return i.ipAliases |
|
| 105 |
-} |
|
| 106 |
- |
|
| 107 | 100 |
func (i *nwIface) Routes() []*net.IPNet {
|
| 108 | 101 |
i.Lock() |
| 109 | 102 |
defer i.Unlock() |
| ... | ... |
@@ -130,6 +122,28 @@ func (n *networkNamespace) Interfaces() []Interface {
|
| 130 | 130 |
return ifaces |
| 131 | 131 |
} |
| 132 | 132 |
|
| 133 |
+func (i *nwIface) SetAliasIP(ip *net.IPNet, add bool) error {
|
|
| 134 |
+ i.Lock() |
|
| 135 |
+ n := i.ns |
|
| 136 |
+ i.Unlock() |
|
| 137 |
+ |
|
| 138 |
+ n.Lock() |
|
| 139 |
+ nlh := n.nlHandle |
|
| 140 |
+ n.Unlock() |
|
| 141 |
+ |
|
| 142 |
+ // Find the network interface identified by the DstName attribute. |
|
| 143 |
+ iface, err := nlh.LinkByName(i.DstName()) |
|
| 144 |
+ if err != nil {
|
|
| 145 |
+ return err |
|
| 146 |
+ } |
|
| 147 |
+ |
|
| 148 |
+ ipAddr := &netlink.Addr{IPNet: ip, Label: ""}
|
|
| 149 |
+ if add {
|
|
| 150 |
+ return nlh.AddrAdd(iface, ipAddr) |
|
| 151 |
+ } |
|
| 152 |
+ return nlh.AddrDel(iface, ipAddr) |
|
| 153 |
+} |
|
| 154 |
+ |
|
| 133 | 155 |
func (i *nwIface) Remove() error {
|
| 134 | 156 |
i.Lock() |
| 135 | 157 |
n := i.ns |
| ... | ... |
@@ -333,7 +347,6 @@ func configureInterface(nlh *netlink.Handle, iface netlink.Link, i *nwIface) err |
| 333 | 333 |
{setInterfaceIPv6, fmt.Sprintf("error setting interface %q IPv6 to %v", ifaceName, i.AddressIPv6())},
|
| 334 | 334 |
{setInterfaceMaster, fmt.Sprintf("error setting interface %q master to %q", ifaceName, i.DstMaster())},
|
| 335 | 335 |
{setInterfaceLinkLocalIPs, fmt.Sprintf("error setting interface %q link local IPs to %v", ifaceName, i.LinkLocalAddresses())},
|
| 336 |
- {setInterfaceIPAliases, fmt.Sprintf("error setting interface %q IP Aliases to %v", ifaceName, i.IPAliases())},
|
|
| 337 | 336 |
} |
| 338 | 337 |
|
| 339 | 338 |
for _, config := range ifaceConfigurators {
|
| ... | ... |
@@ -387,16 +400,6 @@ func setInterfaceLinkLocalIPs(nlh *netlink.Handle, iface netlink.Link, i *nwIfac |
| 387 | 387 |
return nil |
| 388 | 388 |
} |
| 389 | 389 |
|
| 390 |
-func setInterfaceIPAliases(nlh *netlink.Handle, iface netlink.Link, i *nwIface) error {
|
|
| 391 |
- for _, si := range i.IPAliases() {
|
|
| 392 |
- ipAddr := &netlink.Addr{IPNet: si}
|
|
| 393 |
- if err := nlh.AddrAdd(iface, ipAddr); err != nil {
|
|
| 394 |
- return err |
|
| 395 |
- } |
|
| 396 |
- } |
|
| 397 |
- return nil |
|
| 398 |
-} |
|
| 399 |
- |
|
| 400 | 390 |
func setInterfaceName(nlh *netlink.Handle, iface netlink.Link, i *nwIface) error {
|
| 401 | 391 |
return nlh.LinkSetName(iface, i.DstName()) |
| 402 | 392 |
} |
| ... | ... |
@@ -66,12 +66,6 @@ func (n *networkNamespace) LinkLocalAddresses(list []*net.IPNet) IfaceOption {
|
| 66 | 66 |
} |
| 67 | 67 |
} |
| 68 | 68 |
|
| 69 |
-func (n *networkNamespace) IPAliases(list []*net.IPNet) IfaceOption {
|
|
| 70 |
- return func(i *nwIface) {
|
|
| 71 |
- i.ipAliases = list |
|
| 72 |
- } |
|
| 73 |
-} |
|
| 74 |
- |
|
| 75 | 69 |
func (n *networkNamespace) Routes(routes []*net.IPNet) IfaceOption {
|
| 76 | 70 |
return func(i *nwIface) {
|
| 77 | 71 |
i.routes = routes |
| ... | ... |
@@ -91,9 +91,6 @@ type IfaceOptionSetter interface {
|
| 91 | 91 |
// LinkLocalAddresses returns an option setter to set the link-local IP addresses. |
| 92 | 92 |
LinkLocalAddresses([]*net.IPNet) IfaceOption |
| 93 | 93 |
|
| 94 |
- // IPAliases returns an option setter to set IP address Aliases |
|
| 95 |
- IPAliases([]*net.IPNet) IfaceOption |
|
| 96 |
- |
|
| 97 | 94 |
// Master returns an option setter to set the master interface if any for this |
| 98 | 95 |
// interface. The master interface name should refer to the srcname of a |
| 99 | 96 |
// previously added interface of type bridge. |
| ... | ... |
@@ -150,9 +147,6 @@ type Interface interface {
|
| 150 | 150 |
// LinkLocalAddresses returns the link-local IP addresses assigned to the interface. |
| 151 | 151 |
LinkLocalAddresses() []*net.IPNet |
| 152 | 152 |
|
| 153 |
- // IPAliases returns the IP address aliases assigned to the interface. |
|
| 154 |
- IPAliases() []*net.IPNet |
|
| 155 |
- |
|
| 156 | 153 |
// IP routes for the interface. |
| 157 | 154 |
Routes() []*net.IPNet |
| 158 | 155 |
|
| ... | ... |
@@ -166,6 +160,10 @@ type Interface interface {
|
| 166 | 166 |
// and moving it out of the sandbox. |
| 167 | 167 |
Remove() error |
| 168 | 168 |
|
| 169 |
+ // SetAliasIP adds or deletes the passed IP as an alias on the interface. |
|
| 170 |
+ // ex: set the vip of services in the same network as secondary IP. |
|
| 171 |
+ SetAliasIP(ip *net.IPNet, add bool) error |
|
| 172 |
+ |
|
| 169 | 173 |
// Statistics returns the statistics for this interface |
| 170 | 174 |
Statistics() (*types.InterfaceStatistics, error) |
| 171 | 175 |
} |
| ... | ... |
@@ -123,10 +123,10 @@ func FilterResolvDNS(resolvConf []byte, ipv6Enabled bool) (*File, error) {
|
| 123 | 123 |
// if the resulting resolvConf has no more nameservers defined, add appropriate |
| 124 | 124 |
// default DNS servers for IPv4 and (optionally) IPv6 |
| 125 | 125 |
if len(GetNameservers(cleanedResolvConf, types.IP)) == 0 {
|
| 126 |
- logrus.Infof("No non-localhost DNS nameservers are left in resolv.conf. Using default external servers : %v", defaultIPv4Dns)
|
|
| 126 |
+ logrus.Infof("No non-localhost DNS nameservers are left in resolv.conf. Using default external servers: %v", defaultIPv4Dns)
|
|
| 127 | 127 |
dns := defaultIPv4Dns |
| 128 | 128 |
if ipv6Enabled {
|
| 129 |
- logrus.Infof("IPv6 enabled; Adding default IPv6 external servers : %v", defaultIPv6Dns)
|
|
| 129 |
+ logrus.Infof("IPv6 enabled; Adding default IPv6 external servers: %v", defaultIPv6Dns)
|
|
| 130 | 130 |
dns = append(dns, defaultIPv6Dns...) |
| 131 | 131 |
} |
| 132 | 132 |
cleanedResolvConf = append(cleanedResolvConf, []byte("\n"+strings.Join(dns, "\n"))...)
|
| ... | ... |
@@ -725,10 +725,6 @@ func (sb *sandbox) restoreOslSandbox() error {
|
| 725 | 725 |
if len(i.llAddrs) != 0 {
|
| 726 | 726 |
ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().LinkLocalAddresses(i.llAddrs)) |
| 727 | 727 |
} |
| 728 |
- if len(ep.virtualIP) != 0 {
|
|
| 729 |
- vipAlias := &net.IPNet{IP: ep.virtualIP, Mask: net.CIDRMask(32, 32)}
|
|
| 730 |
- ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().IPAliases([]*net.IPNet{vipAlias}))
|
|
| 731 |
- } |
|
| 732 | 728 |
Ifaces[fmt.Sprintf("%s+%s", i.srcName, i.dstPrefix)] = ifaceOptions
|
| 733 | 729 |
if joinInfo != nil {
|
| 734 | 730 |
for _, r := range joinInfo.StaticRoutes {
|
| ... | ... |
@@ -782,10 +778,6 @@ func (sb *sandbox) populateNetworkResources(ep *endpoint) error {
|
| 782 | 782 |
if len(i.llAddrs) != 0 {
|
| 783 | 783 |
ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().LinkLocalAddresses(i.llAddrs)) |
| 784 | 784 |
} |
| 785 |
- if len(ep.virtualIP) != 0 {
|
|
| 786 |
- vipAlias := &net.IPNet{IP: ep.virtualIP, Mask: net.CIDRMask(32, 32)}
|
|
| 787 |
- ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().IPAliases([]*net.IPNet{vipAlias}))
|
|
| 788 |
- } |
|
| 789 | 785 |
if i.mac != nil {
|
| 790 | 786 |
ifaceOptions = append(ifaceOptions, sb.osSbox.InterfaceOptions().MacAddress(i.mac)) |
| 791 | 787 |
} |
| ... | ... |
@@ -317,6 +317,14 @@ func (sb *sandbox) populateLoadbalancers(ep *endpoint) {
|
| 317 | 317 |
for _, ip := range lb.backEnds {
|
| 318 | 318 |
sb.addLBBackend(ip, lb.vip, lb.fwMark, lb.service.ingressPorts, |
| 319 | 319 |
eIP, gwIP, addService, n.ingress) |
| 320 |
+ // For a new service program the vip as an alias on the task's sandbox interface |
|
| 321 |
+ // connected to this network. |
|
| 322 |
+ if !addService {
|
|
| 323 |
+ continue |
|
| 324 |
+ } |
|
| 325 |
+ if err := ep.setAliasIP(sb, lb.vip, true); err != nil {
|
|
| 326 |
+ logrus.Errorf("Adding Service VIP %v to ep %v(%v) failed: %v", lb.vip, ep.ID(), ep.Name(), err)
|
|
| 327 |
+ } |
|
| 320 | 328 |
addService = false |
| 321 | 329 |
} |
| 322 | 330 |
lb.service.Unlock() |
| ... | ... |
@@ -340,8 +348,16 @@ func (n *network) addLBBackend(ip, vip net.IP, fwMark uint32, ingressPorts []*Po |
| 340 | 340 |
} |
| 341 | 341 |
|
| 342 | 342 |
sb.addLBBackend(ip, vip, fwMark, ingressPorts, ep.Iface().Address(), gwIP, addService, n.ingress) |
| 343 |
- } |
|
| 344 | 343 |
|
| 344 |
+ // For a new service program the vip as an alias on the task's sandbox interface |
|
| 345 |
+ // connected to this network. |
|
| 346 |
+ if !addService {
|
|
| 347 |
+ return false |
|
| 348 |
+ } |
|
| 349 |
+ if err := ep.setAliasIP(sb, vip, true); err != nil {
|
|
| 350 |
+ logrus.Errorf("Adding Service VIP %v to ep %v(%v) failed: %v", vip, ep.ID(), ep.Name(), err)
|
|
| 351 |
+ } |
|
| 352 |
+ } |
|
| 345 | 353 |
return false |
| 346 | 354 |
}) |
| 347 | 355 |
} |
| ... | ... |
@@ -363,8 +379,16 @@ func (n *network) rmLBBackend(ip, vip net.IP, fwMark uint32, ingressPorts []*Por |
| 363 | 363 |
} |
| 364 | 364 |
|
| 365 | 365 |
sb.rmLBBackend(ip, vip, fwMark, ingressPorts, ep.Iface().Address(), gwIP, rmService, n.ingress) |
| 366 |
- } |
|
| 367 | 366 |
|
| 367 |
+ // If the service is being remove its vip alias on on the task's sandbox interface |
|
| 368 |
+ // has to be removed as well. |
|
| 369 |
+ if !rmService {
|
|
| 370 |
+ return false |
|
| 371 |
+ } |
|
| 372 |
+ if err := ep.setAliasIP(sb, vip, false); err != nil {
|
|
| 373 |
+ logrus.Errorf("Removing Service VIP %v from ep %v(%v) failed: %v", vip, ep.ID(), ep.Name(), err)
|
|
| 374 |
+ } |
|
| 375 |
+ } |
|
| 368 | 376 |
return false |
| 369 | 377 |
}) |
| 370 | 378 |
} |
| ... | ... |
@@ -935,6 +959,14 @@ func redirecter() {
|
| 935 | 935 |
rule := strings.Fields(fmt.Sprintf("-t nat -A PREROUTING -d %s -p %s --dport %d -j REDIRECT --to-port %d",
|
| 936 | 936 |
eIP.String(), strings.ToLower(PortConfig_Protocol_name[int32(iPort.Protocol)]), iPort.PublishedPort, iPort.TargetPort)) |
| 937 | 937 |
rules = append(rules, rule) |
| 938 |
+ // Allow only incoming connections to exposed ports |
|
| 939 |
+ iRule := strings.Fields(fmt.Sprintf("-I INPUT -d %s -p %s --dport %d -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT",
|
|
| 940 |
+ eIP.String(), strings.ToLower(PortConfig_Protocol_name[int32(iPort.Protocol)]), iPort.TargetPort)) |
|
| 941 |
+ rules = append(rules, iRule) |
|
| 942 |
+ // Allow only outgoing connections from exposed ports |
|
| 943 |
+ oRule := strings.Fields(fmt.Sprintf("-I OUTPUT -s %s -p %s --sport %d -m conntrack --ctstate ESTABLISHED -j ACCEPT",
|
|
| 944 |
+ eIP.String(), strings.ToLower(PortConfig_Protocol_name[int32(iPort.Protocol)]), iPort.TargetPort)) |
|
| 945 |
+ rules = append(rules, oRule) |
|
| 938 | 946 |
} |
| 939 | 947 |
|
| 940 | 948 |
ns, err := netns.GetFromPath(os.Args[1]) |
| ... | ... |
@@ -952,7 +984,31 @@ func redirecter() {
|
| 952 | 952 |
for _, rule := range rules {
|
| 953 | 953 |
if err := iptables.RawCombinedOutputNative(rule...); err != nil {
|
| 954 | 954 |
logrus.Errorf("setting up rule failed, %v: %v", rule, err)
|
| 955 |
- os.Exit(5) |
|
| 955 |
+ os.Exit(6) |
|
| 956 |
+ } |
|
| 957 |
+ } |
|
| 958 |
+ |
|
| 959 |
+ if len(ingressPorts) == 0 {
|
|
| 960 |
+ return |
|
| 961 |
+ } |
|
| 962 |
+ |
|
| 963 |
+ // Ensure blocking rules for anything else in/to ingress network |
|
| 964 |
+ for _, rule := range [][]string{
|
|
| 965 |
+ {"-d", eIP.String(), "-p", "udp", "-j", "DROP"},
|
|
| 966 |
+ {"-d", eIP.String(), "-p", "tcp", "-j", "DROP"},
|
|
| 967 |
+ } {
|
|
| 968 |
+ if !iptables.ExistsNative(iptables.Filter, "INPUT", rule...) {
|
|
| 969 |
+ if err := iptables.RawCombinedOutputNative(append([]string{"-A", "INPUT"}, rule...)...); err != nil {
|
|
| 970 |
+ logrus.Errorf("setting up rule failed, %v: %v", rule, err)
|
|
| 971 |
+ os.Exit(7) |
|
| 972 |
+ } |
|
| 973 |
+ } |
|
| 974 |
+ rule[0] = "-s" |
|
| 975 |
+ if !iptables.ExistsNative(iptables.Filter, "OUTPUT", rule...) {
|
|
| 976 |
+ if err := iptables.RawCombinedOutputNative(append([]string{"-A", "OUTPUT"}, rule...)...); err != nil {
|
|
| 977 |
+ logrus.Errorf("setting up rule failed, %v: %v", rule, err)
|
|
| 978 |
+ os.Exit(8) |
|
| 979 |
+ } |
|
| 956 | 980 |
} |
| 957 | 981 |
} |
| 958 | 982 |
} |