github.com/guilhermebr/docker@v1.4.2-0.20150428121140-67da055cebca/daemon/networkdriver/bridge/driver.go (about)

     1  package bridge
     2  
     3  import (
     4  	"encoding/hex"
     5  	"errors"
     6  	"fmt"
     7  	"io/ioutil"
     8  	"net"
     9  	"os"
    10  	"os/exec"
    11  	"strconv"
    12  	"strings"
    13  	"sync"
    14  
    15  	"github.com/Sirupsen/logrus"
    16  	"github.com/docker/docker/daemon/network"
    17  	"github.com/docker/docker/daemon/networkdriver"
    18  	"github.com/docker/docker/daemon/networkdriver/ipallocator"
    19  	"github.com/docker/docker/daemon/networkdriver/portmapper"
    20  	"github.com/docker/docker/nat"
    21  	"github.com/docker/docker/pkg/iptables"
    22  	"github.com/docker/docker/pkg/parsers/kernel"
    23  	"github.com/docker/docker/pkg/resolvconf"
    24  	"github.com/docker/libcontainer/netlink"
    25  )
    26  
    27  const (
    28  	DefaultNetworkBridge     = "docker0"
    29  	MaxAllocatedPortAttempts = 10
    30  )
    31  
    32  // Network interface represents the networking stack of a container
    33  type networkInterface struct {
    34  	IP           net.IP
    35  	IPv6         net.IP
    36  	PortMappings []net.Addr // There are mappings to the host interfaces
    37  }
    38  
    39  type ifaces struct {
    40  	c map[string]*networkInterface
    41  	sync.Mutex
    42  }
    43  
    44  func (i *ifaces) Set(key string, n *networkInterface) {
    45  	i.Lock()
    46  	i.c[key] = n
    47  	i.Unlock()
    48  }
    49  
    50  func (i *ifaces) Get(key string) *networkInterface {
    51  	i.Lock()
    52  	res := i.c[key]
    53  	i.Unlock()
    54  	return res
    55  }
    56  
    57  var (
    58  	addrs = []string{
    59  		// Here we don't follow the convention of using the 1st IP of the range for the gateway.
    60  		// This is to use the same gateway IPs as the /24 ranges, which predate the /16 ranges.
    61  		// In theory this shouldn't matter - in practice there's bound to be a few scripts relying
    62  		// on the internal addressing or other things like that.
    63  		// They shouldn't, but hey, let's not break them unless we really have to.
    64  		"172.17.42.1/16", // Don't use 172.16.0.0/16, it conflicts with EC2 DNS 172.16.0.23
    65  		"10.0.42.1/16",   // Don't even try using the entire /8, that's too intrusive
    66  		"10.1.42.1/16",
    67  		"10.42.42.1/16",
    68  		"172.16.42.1/24",
    69  		"172.16.43.1/24",
    70  		"172.16.44.1/24",
    71  		"10.0.42.1/24",
    72  		"10.0.43.1/24",
    73  		"192.168.42.1/24",
    74  		"192.168.43.1/24",
    75  		"192.168.44.1/24",
    76  	}
    77  
    78  	bridgeIface       string
    79  	bridgeIPv4Network *net.IPNet
    80  	gatewayIPv4       net.IP
    81  	bridgeIPv6Addr    net.IP
    82  	globalIPv6Network *net.IPNet
    83  	gatewayIPv6       net.IP
    84  	portMapper        *portmapper.PortMapper
    85  	once              sync.Once
    86  
    87  	defaultBindingIP  = net.ParseIP("0.0.0.0")
    88  	currentInterfaces = ifaces{c: make(map[string]*networkInterface)}
    89  	ipAllocator       = ipallocator.New()
    90  )
    91  
    92  func initPortMapper() {
    93  	once.Do(func() {
    94  		portMapper = portmapper.New()
    95  	})
    96  }
    97  
    98  type Config struct {
    99  	EnableIPv6                  bool
   100  	EnableIptables              bool
   101  	EnableIpForward             bool
   102  	EnableIpMasq                bool
   103  	DefaultIp                   net.IP
   104  	Iface                       string
   105  	IP                          string
   106  	FixedCIDR                   string
   107  	FixedCIDRv6                 string
   108  	DefaultGatewayIPv4          string
   109  	DefaultGatewayIPv6          string
   110  	InterContainerCommunication bool
   111  }
   112  
   113  func InitDriver(config *Config) error {
   114  	var (
   115  		networkv4  *net.IPNet
   116  		networkv6  *net.IPNet
   117  		addrv4     net.Addr
   118  		addrsv6    []net.Addr
   119  		bridgeIPv6 = "fe80::1/64"
   120  	)
   121  
   122  	// try to modprobe bridge first
   123  	// see gh#12177
   124  	if out, err := exec.Command("modprobe", "-va", "bridge", "nf_nat").Output(); err != nil {
   125  		logrus.Warnf("Running modprobe bridge nf_nat failed with message: %s, error: %v", out, err)
   126  	}
   127  
   128  	initPortMapper()
   129  
   130  	if config.DefaultIp != nil {
   131  		defaultBindingIP = config.DefaultIp
   132  	}
   133  
   134  	bridgeIface = config.Iface
   135  	usingDefaultBridge := false
   136  	if bridgeIface == "" {
   137  		usingDefaultBridge = true
   138  		bridgeIface = DefaultNetworkBridge
   139  	}
   140  
   141  	addrv4, addrsv6, err := networkdriver.GetIfaceAddr(bridgeIface)
   142  
   143  	if err != nil {
   144  		// No Bridge existent, create one
   145  		// If we're not using the default bridge, fail without trying to create it
   146  		if !usingDefaultBridge {
   147  			return err
   148  		}
   149  
   150  		logrus.Info("Bridge interface not found, trying to create it")
   151  
   152  		// If the iface is not found, try to create it
   153  		if err := configureBridge(config.IP, bridgeIPv6, config.EnableIPv6); err != nil {
   154  			logrus.Errorf("Could not configure Bridge: %s", err)
   155  			return err
   156  		}
   157  
   158  		addrv4, addrsv6, err = networkdriver.GetIfaceAddr(bridgeIface)
   159  		if err != nil {
   160  			return err
   161  		}
   162  
   163  		if config.FixedCIDRv6 != "" {
   164  			// Setting route to global IPv6 subnet
   165  			logrus.Infof("Adding route to IPv6 network %q via device %q", config.FixedCIDRv6, bridgeIface)
   166  			if err := netlink.AddRoute(config.FixedCIDRv6, "", "", bridgeIface); err != nil {
   167  				logrus.Fatalf("Could not add route to IPv6 network %q via device %q", config.FixedCIDRv6, bridgeIface)
   168  			}
   169  		}
   170  	} else {
   171  		// Bridge exists already, getting info...
   172  		// Validate that the bridge ip matches the ip specified by BridgeIP
   173  		if config.IP != "" {
   174  			networkv4 = addrv4.(*net.IPNet)
   175  			bip, _, err := net.ParseCIDR(config.IP)
   176  			if err != nil {
   177  				return err
   178  			}
   179  			if !networkv4.IP.Equal(bip) {
   180  				return fmt.Errorf("Bridge ip (%s) does not match existing bridge configuration %s", networkv4.IP, bip)
   181  			}
   182  		}
   183  
   184  		// A bridge might exist but not have any IPv6 addr associated with it yet
   185  		// (for example, an existing Docker installation that has only been used
   186  		// with IPv4 and docker0 already is set up) In that case, we can perform
   187  		// the bridge init for IPv6 here, else we will error out below if --ipv6=true
   188  		if len(addrsv6) == 0 && config.EnableIPv6 {
   189  			if err := setupIPv6Bridge(bridgeIPv6); err != nil {
   190  				return err
   191  			}
   192  			// Recheck addresses now that IPv6 is setup on the bridge
   193  			addrv4, addrsv6, err = networkdriver.GetIfaceAddr(bridgeIface)
   194  			if err != nil {
   195  				return err
   196  			}
   197  		}
   198  
   199  		// TODO: Check if route to config.FixedCIDRv6 is set
   200  	}
   201  
   202  	if config.EnableIPv6 {
   203  		bip6, _, err := net.ParseCIDR(bridgeIPv6)
   204  		if err != nil {
   205  			return err
   206  		}
   207  		found := false
   208  		for _, addrv6 := range addrsv6 {
   209  			networkv6 = addrv6.(*net.IPNet)
   210  			if networkv6.IP.Equal(bip6) {
   211  				found = true
   212  				break
   213  			}
   214  		}
   215  		if !found {
   216  			return fmt.Errorf("Bridge IPv6 does not match existing bridge configuration %s", bip6)
   217  		}
   218  	}
   219  
   220  	networkv4 = addrv4.(*net.IPNet)
   221  
   222  	if config.EnableIPv6 {
   223  		if len(addrsv6) == 0 {
   224  			return errors.New("IPv6 enabled but no IPv6 detected")
   225  		}
   226  		bridgeIPv6Addr = networkv6.IP
   227  	}
   228  
   229  	if config.EnableIptables {
   230  		iptables.FirewalldInit()
   231  	}
   232  
   233  	// Configure iptables for link support
   234  	if config.EnableIptables {
   235  		if err := setupIPTables(addrv4, config.InterContainerCommunication, config.EnableIpMasq); err != nil {
   236  			logrus.Errorf("Error configuring iptables: %s", err)
   237  			return err
   238  		}
   239  		// call this on Firewalld reload
   240  		iptables.OnReloaded(func() { setupIPTables(addrv4, config.InterContainerCommunication, config.EnableIpMasq) })
   241  	}
   242  
   243  	if config.EnableIpForward {
   244  		// Enable IPv4 forwarding
   245  		if err := ioutil.WriteFile("/proc/sys/net/ipv4/ip_forward", []byte{'1', '\n'}, 0644); err != nil {
   246  			logrus.Warnf("WARNING: unable to enable IPv4 forwarding: %s\n", err)
   247  		}
   248  
   249  		if config.FixedCIDRv6 != "" {
   250  			// Enable IPv6 forwarding
   251  			if err := ioutil.WriteFile("/proc/sys/net/ipv6/conf/default/forwarding", []byte{'1', '\n'}, 0644); err != nil {
   252  				logrus.Warnf("WARNING: unable to enable IPv6 default forwarding: %s\n", err)
   253  			}
   254  			if err := ioutil.WriteFile("/proc/sys/net/ipv6/conf/all/forwarding", []byte{'1', '\n'}, 0644); err != nil {
   255  				logrus.Warnf("WARNING: unable to enable IPv6 all forwarding: %s\n", err)
   256  			}
   257  		}
   258  	}
   259  
   260  	// We can always try removing the iptables
   261  	if err := iptables.RemoveExistingChain("DOCKER", iptables.Nat); err != nil {
   262  		return err
   263  	}
   264  
   265  	if config.EnableIptables {
   266  		_, err := iptables.NewChain("DOCKER", bridgeIface, iptables.Nat)
   267  		if err != nil {
   268  			return err
   269  		}
   270  		// call this on Firewalld reload
   271  		iptables.OnReloaded(func() { iptables.NewChain("DOCKER", bridgeIface, iptables.Nat) })
   272  
   273  		chain, err := iptables.NewChain("DOCKER", bridgeIface, iptables.Filter)
   274  		if err != nil {
   275  			return err
   276  		}
   277  		// call this on Firewalld reload
   278  		iptables.OnReloaded(func() { iptables.NewChain("DOCKER", bridgeIface, iptables.Filter) })
   279  
   280  		portMapper.SetIptablesChain(chain)
   281  	}
   282  
   283  	bridgeIPv4Network = networkv4
   284  	if config.FixedCIDR != "" {
   285  		_, subnet, err := net.ParseCIDR(config.FixedCIDR)
   286  		if err != nil {
   287  			return err
   288  		}
   289  		logrus.Debugf("Subnet: %v", subnet)
   290  		if err := ipAllocator.RegisterSubnet(bridgeIPv4Network, subnet); err != nil {
   291  			logrus.Errorf("Error registering subnet for IPv4 bridge network: %s", err)
   292  			return err
   293  		}
   294  	}
   295  
   296  	if gateway, err := requestDefaultGateway(config.DefaultGatewayIPv4, bridgeIPv4Network); err != nil {
   297  		return err
   298  	} else {
   299  		gatewayIPv4 = gateway
   300  	}
   301  
   302  	if config.FixedCIDRv6 != "" {
   303  		_, subnet, err := net.ParseCIDR(config.FixedCIDRv6)
   304  		if err != nil {
   305  			return err
   306  		}
   307  		logrus.Debugf("Subnet: %v", subnet)
   308  		if err := ipAllocator.RegisterSubnet(subnet, subnet); err != nil {
   309  			logrus.Errorf("Error registering subnet for IPv6 bridge network: %s", err)
   310  			return err
   311  		}
   312  		globalIPv6Network = subnet
   313  
   314  		if gateway, err := requestDefaultGateway(config.DefaultGatewayIPv6, globalIPv6Network); err != nil {
   315  			return err
   316  		} else {
   317  			gatewayIPv6 = gateway
   318  		}
   319  	}
   320  
   321  	// Block BridgeIP in IP allocator
   322  	ipAllocator.RequestIP(bridgeIPv4Network, bridgeIPv4Network.IP)
   323  
   324  	if config.EnableIptables {
   325  		iptables.OnReloaded(portMapper.ReMapAll) // call this on Firewalld reload
   326  	}
   327  
   328  	return nil
   329  }
   330  
   331  func setupIPTables(addr net.Addr, icc, ipmasq bool) error {
   332  	// Enable NAT
   333  
   334  	if ipmasq {
   335  		natArgs := []string{"-s", addr.String(), "!", "-o", bridgeIface, "-j", "MASQUERADE"}
   336  
   337  		if !iptables.Exists(iptables.Nat, "POSTROUTING", natArgs...) {
   338  			if output, err := iptables.Raw(append([]string{
   339  				"-t", string(iptables.Nat), "-I", "POSTROUTING"}, natArgs...)...); err != nil {
   340  				return fmt.Errorf("Unable to enable network bridge NAT: %s", err)
   341  			} else if len(output) != 0 {
   342  				return iptables.ChainError{Chain: "POSTROUTING", Output: output}
   343  			}
   344  		}
   345  	}
   346  
   347  	var (
   348  		args       = []string{"-i", bridgeIface, "-o", bridgeIface, "-j"}
   349  		acceptArgs = append(args, "ACCEPT")
   350  		dropArgs   = append(args, "DROP")
   351  	)
   352  
   353  	if !icc {
   354  		iptables.Raw(append([]string{"-D", "FORWARD"}, acceptArgs...)...)
   355  
   356  		if !iptables.Exists(iptables.Filter, "FORWARD", dropArgs...) {
   357  			logrus.Debugf("Disable inter-container communication")
   358  			if output, err := iptables.Raw(append([]string{"-I", "FORWARD"}, dropArgs...)...); err != nil {
   359  				return fmt.Errorf("Unable to prevent intercontainer communication: %s", err)
   360  			} else if len(output) != 0 {
   361  				return fmt.Errorf("Error disabling intercontainer communication: %s", output)
   362  			}
   363  		}
   364  	} else {
   365  		iptables.Raw(append([]string{"-D", "FORWARD"}, dropArgs...)...)
   366  
   367  		if !iptables.Exists(iptables.Filter, "FORWARD", acceptArgs...) {
   368  			logrus.Debugf("Enable inter-container communication")
   369  			if output, err := iptables.Raw(append([]string{"-I", "FORWARD"}, acceptArgs...)...); err != nil {
   370  				return fmt.Errorf("Unable to allow intercontainer communication: %s", err)
   371  			} else if len(output) != 0 {
   372  				return fmt.Errorf("Error enabling intercontainer communication: %s", output)
   373  			}
   374  		}
   375  	}
   376  
   377  	// Accept all non-intercontainer outgoing packets
   378  	outgoingArgs := []string{"-i", bridgeIface, "!", "-o", bridgeIface, "-j", "ACCEPT"}
   379  	if !iptables.Exists(iptables.Filter, "FORWARD", outgoingArgs...) {
   380  		if output, err := iptables.Raw(append([]string{"-I", "FORWARD"}, outgoingArgs...)...); err != nil {
   381  			return fmt.Errorf("Unable to allow outgoing packets: %s", err)
   382  		} else if len(output) != 0 {
   383  			return iptables.ChainError{Chain: "FORWARD outgoing", Output: output}
   384  		}
   385  	}
   386  
   387  	// Accept incoming packets for existing connections
   388  	existingArgs := []string{"-o", bridgeIface, "-m", "conntrack", "--ctstate", "RELATED,ESTABLISHED", "-j", "ACCEPT"}
   389  
   390  	if !iptables.Exists(iptables.Filter, "FORWARD", existingArgs...) {
   391  		if output, err := iptables.Raw(append([]string{"-I", "FORWARD"}, existingArgs...)...); err != nil {
   392  			return fmt.Errorf("Unable to allow incoming packets: %s", err)
   393  		} else if len(output) != 0 {
   394  			return iptables.ChainError{Chain: "FORWARD incoming", Output: output}
   395  		}
   396  	}
   397  	return nil
   398  }
   399  
   400  func RequestPort(ip net.IP, proto string, port int) (int, error) {
   401  	initPortMapper()
   402  	return portMapper.Allocator.RequestPort(ip, proto, port)
   403  }
   404  
   405  // configureBridge attempts to create and configure a network bridge interface named `bridgeIface` on the host
   406  // If bridgeIP is empty, it will try to find a non-conflicting IP from the Docker-specified private ranges
   407  // If the bridge `bridgeIface` already exists, it will only perform the IP address association with the existing
   408  // bridge (fixes issue #8444)
   409  // If an address which doesn't conflict with existing interfaces can't be found, an error is returned.
   410  func configureBridge(bridgeIP string, bridgeIPv6 string, enableIPv6 bool) error {
   411  	nameservers := []string{}
   412  	resolvConf, _ := resolvconf.Get()
   413  	// We don't check for an error here, because we don't really care
   414  	// if we can't read /etc/resolv.conf. So instead we skip the append
   415  	// if resolvConf is nil. It either doesn't exist, or we can't read it
   416  	// for some reason.
   417  	if resolvConf != nil {
   418  		nameservers = append(nameservers, resolvconf.GetNameserversAsCIDR(resolvConf)...)
   419  	}
   420  
   421  	var ifaceAddr string
   422  	if len(bridgeIP) != 0 {
   423  		_, _, err := net.ParseCIDR(bridgeIP)
   424  		if err != nil {
   425  			return err
   426  		}
   427  		ifaceAddr = bridgeIP
   428  	} else {
   429  		for _, addr := range addrs {
   430  			_, dockerNetwork, err := net.ParseCIDR(addr)
   431  			if err != nil {
   432  				return err
   433  			}
   434  			if err := networkdriver.CheckNameserverOverlaps(nameservers, dockerNetwork); err == nil {
   435  				if err := networkdriver.CheckRouteOverlaps(dockerNetwork); err == nil {
   436  					ifaceAddr = addr
   437  					break
   438  				} else {
   439  					logrus.Debugf("%s %s", addr, err)
   440  				}
   441  			}
   442  		}
   443  	}
   444  
   445  	if ifaceAddr == "" {
   446  		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)
   447  	}
   448  	logrus.Debugf("Creating bridge %s with network %s", bridgeIface, ifaceAddr)
   449  
   450  	if err := createBridgeIface(bridgeIface); err != nil {
   451  		// The bridge may already exist, therefore we can ignore an "exists" error
   452  		if !os.IsExist(err) {
   453  			return err
   454  		}
   455  	}
   456  
   457  	iface, err := net.InterfaceByName(bridgeIface)
   458  	if err != nil {
   459  		return err
   460  	}
   461  
   462  	ipAddr, ipNet, err := net.ParseCIDR(ifaceAddr)
   463  	if err != nil {
   464  		return err
   465  	}
   466  
   467  	if err := netlink.NetworkLinkAddIp(iface, ipAddr, ipNet); err != nil {
   468  		return fmt.Errorf("Unable to add private network: %s", err)
   469  	}
   470  
   471  	if enableIPv6 {
   472  		if err := setupIPv6Bridge(bridgeIPv6); err != nil {
   473  			return err
   474  		}
   475  	}
   476  
   477  	if err := netlink.NetworkLinkUp(iface); err != nil {
   478  		return fmt.Errorf("Unable to start network bridge: %s", err)
   479  	}
   480  	return nil
   481  }
   482  
   483  func setupIPv6Bridge(bridgeIPv6 string) error {
   484  
   485  	iface, err := net.InterfaceByName(bridgeIface)
   486  	if err != nil {
   487  		return err
   488  	}
   489  	// Enable IPv6 on the bridge
   490  	procFile := "/proc/sys/net/ipv6/conf/" + iface.Name + "/disable_ipv6"
   491  	if err := ioutil.WriteFile(procFile, []byte{'0', '\n'}, 0644); err != nil {
   492  		return fmt.Errorf("Unable to enable IPv6 addresses on bridge: %v", err)
   493  	}
   494  
   495  	ipAddr6, ipNet6, err := net.ParseCIDR(bridgeIPv6)
   496  	if err != nil {
   497  		return fmt.Errorf("Unable to parse bridge IPv6 address: %q, error: %v", bridgeIPv6, err)
   498  	}
   499  
   500  	if err := netlink.NetworkLinkAddIp(iface, ipAddr6, ipNet6); err != nil {
   501  		return fmt.Errorf("Unable to add private IPv6 network: %v", err)
   502  	}
   503  
   504  	return nil
   505  }
   506  
   507  func requestDefaultGateway(requestedGateway string, network *net.IPNet) (gateway net.IP, err error) {
   508  	if requestedGateway != "" {
   509  		gateway = net.ParseIP(requestedGateway)
   510  
   511  		if gateway == nil {
   512  			return nil, fmt.Errorf("Bad parameter: invalid gateway ip %s", requestedGateway)
   513  		}
   514  
   515  		if !network.Contains(gateway) {
   516  			return nil, fmt.Errorf("Gateway ip %s must be part of the network %s", requestedGateway, network.String())
   517  		}
   518  
   519  		ipAllocator.RequestIP(network, gateway)
   520  	}
   521  
   522  	return gateway, nil
   523  }
   524  
   525  func createBridgeIface(name string) error {
   526  	kv, err := kernel.GetKernelVersion()
   527  	// Only set the bridge's mac address if the kernel version is > 3.3
   528  	// before that it was not supported
   529  	setBridgeMacAddr := err == nil && (kv.Kernel >= 3 && kv.Major >= 3)
   530  	logrus.Debugf("setting bridge mac address = %v", setBridgeMacAddr)
   531  	return netlink.CreateBridge(name, setBridgeMacAddr)
   532  }
   533  
   534  // Generate a IEEE802 compliant MAC address from the given IP address.
   535  //
   536  // The generator is guaranteed to be consistent: the same IP will always yield the same
   537  // MAC address. This is to avoid ARP cache issues.
   538  func generateMacAddr(ip net.IP) net.HardwareAddr {
   539  	hw := make(net.HardwareAddr, 6)
   540  
   541  	// The first byte of the MAC address has to comply with these rules:
   542  	// 1. Unicast: Set the least-significant bit to 0.
   543  	// 2. Address is locally administered: Set the second-least-significant bit (U/L) to 1.
   544  	// 3. As "small" as possible: The veth address has to be "smaller" than the bridge address.
   545  	hw[0] = 0x02
   546  
   547  	// The first 24 bits of the MAC represent the Organizationally Unique Identifier (OUI).
   548  	// Since this address is locally administered, we can do whatever we want as long as
   549  	// it doesn't conflict with other addresses.
   550  	hw[1] = 0x42
   551  
   552  	// Insert the IP address into the last 32 bits of the MAC address.
   553  	// This is a simple way to guarantee the address will be consistent and unique.
   554  	copy(hw[2:], ip.To4())
   555  
   556  	return hw
   557  }
   558  
   559  func linkLocalIPv6FromMac(mac string) (string, error) {
   560  	hx := strings.Replace(mac, ":", "", -1)
   561  	hw, err := hex.DecodeString(hx)
   562  	if err != nil {
   563  		return "", errors.New("Could not parse MAC address " + mac)
   564  	}
   565  
   566  	hw[0] ^= 0x2
   567  
   568  	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
   569  }
   570  
   571  // Allocate a network interface
   572  func Allocate(id, requestedMac, requestedIP, requestedIPv6 string) (*network.Settings, error) {
   573  	var (
   574  		ip            net.IP
   575  		mac           net.HardwareAddr
   576  		err           error
   577  		globalIPv6    net.IP
   578  		defaultGWIPv4 net.IP
   579  		defaultGWIPv6 net.IP
   580  	)
   581  
   582  	ip, err = ipAllocator.RequestIP(bridgeIPv4Network, net.ParseIP(requestedIP))
   583  	if err != nil {
   584  		return nil, err
   585  	}
   586  
   587  	// If no explicit mac address was given, generate a random one.
   588  	if mac, err = net.ParseMAC(requestedMac); err != nil {
   589  		mac = generateMacAddr(ip)
   590  	}
   591  
   592  	if globalIPv6Network != nil {
   593  		// If globalIPv6Network Size is at least a /80 subnet generate IPv6 address from MAC address
   594  		netmaskOnes, _ := globalIPv6Network.Mask.Size()
   595  		ipv6 := net.ParseIP(requestedIPv6)
   596  		if ipv6 == nil && netmaskOnes <= 80 {
   597  			ipv6 = make(net.IP, len(globalIPv6Network.IP))
   598  			copy(ipv6, globalIPv6Network.IP)
   599  			for i, h := range mac {
   600  				ipv6[i+10] = h
   601  			}
   602  		}
   603  
   604  		globalIPv6, err = ipAllocator.RequestIP(globalIPv6Network, ipv6)
   605  		if err != nil {
   606  			logrus.Errorf("Allocator: RequestIP v6: %v", err)
   607  			return nil, err
   608  		}
   609  		logrus.Infof("Allocated IPv6 %s", globalIPv6)
   610  	}
   611  
   612  	maskSize, _ := bridgeIPv4Network.Mask.Size()
   613  
   614  	if gatewayIPv4 != nil {
   615  		defaultGWIPv4 = gatewayIPv4
   616  	} else {
   617  		defaultGWIPv4 = bridgeIPv4Network.IP
   618  	}
   619  
   620  	if gatewayIPv6 != nil {
   621  		defaultGWIPv6 = gatewayIPv6
   622  	} else {
   623  		defaultGWIPv6 = bridgeIPv6Addr
   624  	}
   625  
   626  	// If linklocal IPv6
   627  	localIPv6Net, err := linkLocalIPv6FromMac(mac.String())
   628  	if err != nil {
   629  		return nil, err
   630  	}
   631  	localIPv6, _, _ := net.ParseCIDR(localIPv6Net)
   632  
   633  	networkSettings := &network.Settings{
   634  		IPAddress:            ip.String(),
   635  		Gateway:              defaultGWIPv4.String(),
   636  		MacAddress:           mac.String(),
   637  		Bridge:               bridgeIface,
   638  		IPPrefixLen:          maskSize,
   639  		LinkLocalIPv6Address: localIPv6.String(),
   640  	}
   641  
   642  	if globalIPv6Network != nil {
   643  		networkSettings.GlobalIPv6Address = globalIPv6.String()
   644  		maskV6Size, _ := globalIPv6Network.Mask.Size()
   645  		networkSettings.GlobalIPv6PrefixLen = maskV6Size
   646  		networkSettings.IPv6Gateway = defaultGWIPv6.String()
   647  	}
   648  
   649  	currentInterfaces.Set(id, &networkInterface{
   650  		IP:   ip,
   651  		IPv6: globalIPv6,
   652  	})
   653  
   654  	return networkSettings, nil
   655  }
   656  
   657  // Release an interface for a select ip
   658  func Release(id string) {
   659  	var containerInterface = currentInterfaces.Get(id)
   660  
   661  	if containerInterface == nil {
   662  		logrus.Warnf("No network information to release for %s", id)
   663  		return
   664  	}
   665  
   666  	for _, nat := range containerInterface.PortMappings {
   667  		if err := portMapper.Unmap(nat); err != nil {
   668  			logrus.Infof("Unable to unmap port %s: %s", nat, err)
   669  		}
   670  	}
   671  
   672  	if err := ipAllocator.ReleaseIP(bridgeIPv4Network, containerInterface.IP); err != nil {
   673  		logrus.Infof("Unable to release IPv4 %s", err)
   674  	}
   675  	if globalIPv6Network != nil {
   676  		if err := ipAllocator.ReleaseIP(globalIPv6Network, containerInterface.IPv6); err != nil {
   677  			logrus.Infof("Unable to release IPv6 %s", err)
   678  		}
   679  	}
   680  }
   681  
   682  // Allocate an external port and map it to the interface
   683  func AllocatePort(id string, port nat.Port, binding nat.PortBinding) (nat.PortBinding, error) {
   684  	var (
   685  		ip            = defaultBindingIP
   686  		proto         = port.Proto()
   687  		containerPort = port.Int()
   688  		network       = currentInterfaces.Get(id)
   689  	)
   690  
   691  	if binding.HostIp != "" {
   692  		ip = net.ParseIP(binding.HostIp)
   693  		if ip == nil {
   694  			return nat.PortBinding{}, fmt.Errorf("Bad parameter: invalid host ip %s", binding.HostIp)
   695  		}
   696  	}
   697  
   698  	// host ip, proto, and host port
   699  	var container net.Addr
   700  	switch proto {
   701  	case "tcp":
   702  		container = &net.TCPAddr{IP: network.IP, Port: containerPort}
   703  	case "udp":
   704  		container = &net.UDPAddr{IP: network.IP, Port: containerPort}
   705  	default:
   706  		return nat.PortBinding{}, fmt.Errorf("unsupported address type %s", proto)
   707  	}
   708  
   709  	//
   710  	// Try up to 10 times to get a port that's not already allocated.
   711  	//
   712  	// In the event of failure to bind, return the error that portmapper.Map
   713  	// yields.
   714  	//
   715  
   716  	var (
   717  		host net.Addr
   718  		err  error
   719  	)
   720  	hostPort, err := nat.ParsePort(binding.HostPort)
   721  	if err != nil {
   722  		return nat.PortBinding{}, err
   723  	}
   724  	for i := 0; i < MaxAllocatedPortAttempts; i++ {
   725  		if host, err = portMapper.Map(container, ip, hostPort); err == nil {
   726  			break
   727  		}
   728  		// There is no point in immediately retrying to map an explicitly
   729  		// chosen port.
   730  		if hostPort != 0 {
   731  			logrus.Warnf("Failed to allocate and map port %d: %s", hostPort, err)
   732  			break
   733  		}
   734  		logrus.Warnf("Failed to allocate and map port: %s, retry: %d", err, i+1)
   735  	}
   736  
   737  	if err != nil {
   738  		return nat.PortBinding{}, err
   739  	}
   740  
   741  	network.PortMappings = append(network.PortMappings, host)
   742  
   743  	switch netAddr := host.(type) {
   744  	case *net.TCPAddr:
   745  		return nat.PortBinding{HostIp: netAddr.IP.String(), HostPort: strconv.Itoa(netAddr.Port)}, nil
   746  	case *net.UDPAddr:
   747  		return nat.PortBinding{HostIp: netAddr.IP.String(), HostPort: strconv.Itoa(netAddr.Port)}, nil
   748  	default:
   749  		return nat.PortBinding{}, fmt.Errorf("unsupported address type %T", netAddr)
   750  	}
   751  }
   752  
   753  //TODO: should it return something more than just an error?
   754  func LinkContainers(action, parentIP, childIP string, ports []nat.Port, ignoreErrors bool) error {
   755  	var nfAction iptables.Action
   756  
   757  	switch action {
   758  	case "-A":
   759  		nfAction = iptables.Append
   760  	case "-I":
   761  		nfAction = iptables.Insert
   762  	case "-D":
   763  		nfAction = iptables.Delete
   764  	default:
   765  		return fmt.Errorf("Invalid action '%s' specified", action)
   766  	}
   767  
   768  	ip1 := net.ParseIP(parentIP)
   769  	if ip1 == nil {
   770  		return fmt.Errorf("Parent IP '%s' is invalid", parentIP)
   771  	}
   772  	ip2 := net.ParseIP(childIP)
   773  	if ip2 == nil {
   774  		return fmt.Errorf("Child IP '%s' is invalid", childIP)
   775  	}
   776  
   777  	chain := iptables.Chain{Name: "DOCKER", Bridge: bridgeIface}
   778  	for _, port := range ports {
   779  		if err := chain.Link(nfAction, ip1, ip2, port.Int(), port.Proto()); !ignoreErrors && err != nil {
   780  			return err
   781  		}
   782  	}
   783  	return nil
   784  }