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