diff --git a/libnetwork/bridge/bridge.go b/libnetwork/bridge/bridge.go index 3599735988..a7c5215b76 100644 --- a/libnetwork/bridge/bridge.go +++ b/libnetwork/bridge/bridge.go @@ -212,46 +212,6 @@ func createBridge(config *Configuration) (netlink.Addr, []netlink.Addr, error) { return getInterfaceAddrByName(config.BridgeName) } - -func checkBridgeConfig(iface netlink.Link, config *Configuration) (netlink.Addr, []netlink.Addr, error) { - addrv4, addrsv6, err := getInterfaceAddr(iface) - if err != nil { - return netlink.Addr{}, nil, err - } - - // If config dictates a specific IP for the bridge, we have to check if it - // corresponds to reality. - if config.AddressIPv4 != "" { - bridgeIP, _, err := net.ParseCIDR(config.AddressIPv4) - if err != nil { - return netlink.Addr{}, nil, err - } - if !addrv4.IP.Equal(bridgeIP) { - return netlink.Addr{}, nil, fmt.Errorf("bridge ip (%s) does not match existing configuration %s", addrv4.IP, bridgeIP) - } - } - - return addrv4, addrsv6, nil -} - -func setupIPv6Bridge(iface netlink.Link, config *Configuration) error { - procFile := "/proc/sys/net/ipv6/conf/" + config.BridgeName + "/disable_ipv6" - if err := ioutil.WriteFile(procFile, []byte{'0', '\n'}, 0644); err != nil { - return fmt.Errorf("Unable to enable IPv6 addresses on bridge: %v", err) - } - - ip, net, err := net.ParseCIDR(config.AddressIPv6) - if err != nil { - return fmt.Errorf("Invalid bridge IPv6 address %q: %v", config.AddressIPv6, err) - } - - net.IP = ip - if err := netlink.AddrAdd(iface, &netlink.Addr{net, ""}); err != nil { - return fmt.Errorf("Failed to add address %s to bridge: %v", net, err) - } - - return nil -} */ type bridgeNetwork struct { diff --git a/libnetwork/bridge/setup.go b/libnetwork/bridge/setup.go index 3ba81106a3..2d17f7a7f2 100644 --- a/libnetwork/bridge/setup.go +++ b/libnetwork/bridge/setup.go @@ -7,8 +7,8 @@ type BridgeSetup struct { steps []SetupStep } -func NewBridgeSetup(b *Interface) *BridgeSetup { - return &BridgeSetup{bridge: b} +func NewBridgeSetup(i *Interface) *BridgeSetup { + return &BridgeSetup{bridge: i} } func (b *BridgeSetup) Apply() error { @@ -26,18 +26,18 @@ func (b *BridgeSetup) QueueStep(step SetupStep) { //---------------------------------------------------------------------------// -func SetupFixedCIDRv4(b *Interface) error { +func SetupFixedCIDRv4(i *Interface) error { return nil } -func SetupFixedCIDRv6(b *Interface) error { +func SetupFixedCIDRv6(i *Interface) error { return nil } -func SetupIPTables(b *Interface) error { +func SetupIPTables(i *Interface) error { return nil } -func SetupIPForwarding(b *Interface) error { +func SetupIPForwarding(i *Interface) error { return nil } diff --git a/libnetwork/bridge/setup_device.go b/libnetwork/bridge/setup_device.go index 8256f1fbbf..d2e285b77f 100644 --- a/libnetwork/bridge/setup_device.go +++ b/libnetwork/bridge/setup_device.go @@ -10,6 +10,7 @@ import ( "github.com/vishvananda/netlink" ) +// SetupDevice create a new bridge interface/ func SetupDevice(i *Interface) error { // We only attempt to create the bridge when the requested device name is // the default one. @@ -32,9 +33,11 @@ func SetupDevice(i *Interface) error { log.Debugf("Setting bridge mac address to %s", i.Link.Attrs().HardwareAddr) } + // Call out to netlink to create the device. return netlink.LinkAdd(i.Link) } +// SetupDeviceUp ups the given bridge interface. func SetupDeviceUp(i *Interface) error { return netlink.LinkSetUp(i.Link) } diff --git a/libnetwork/bridge/setup_ipv4.go b/libnetwork/bridge/setup_ipv4.go index 5c4bb748f2..974e7e2032 100644 --- a/libnetwork/bridge/setup_ipv4.go +++ b/libnetwork/bridge/setup_ipv4.go @@ -5,6 +5,7 @@ import ( "net" log "github.com/Sirupsen/logrus" + "github.com/docker/docker/pkg/networkfs/resolvconf" "github.com/vishvananda/netlink" ) @@ -56,12 +57,80 @@ func electBridgeIPv4(config *Configuration) (*net.IPNet, error) { return config.AddressIPv4, nil } + // We don't check for an error here, because we don't really care if we + // can't read /etc/resolv.conf. So instead we skip the append if resolvConf + // is nil. It either doesn't exist, or we can't read it for some reason. + nameservers := []string{} + if resolvConf, _ := resolvconf.Get(); resolvConf != nil { + nameservers = append(nameservers, resolvconf.GetNameserversAsCIDR(resolvConf)...) + } + // Try to automatically elect appropriate brige IPv4 settings. for _, n := range bridgeNetworks { - // TODO CheckNameserverOverlaps - // TODO CheckRouteOverlaps - return n, nil + if err := checkNameserverOverlaps(nameservers, n); err == nil { + if err := checkRouteOverlaps(n); err == nil { + return n, nil + } + } } return nil, fmt.Errorf("Couldn't find an address range for interface %q", config.BridgeName) } + +func checkNameserverOverlaps(nameservers []string, toCheck *net.IPNet) error { + for _, ns := range nameservers { + _, nsNetwork, err := net.ParseCIDR(ns) + if err != nil { + return err + } + if networkOverlaps(toCheck, nsNetwork) { + return fmt.Errorf("Requested network %s overlaps with name server") + } + } + return nil +} + +func checkRouteOverlaps(toCheck *net.IPNet) error { + networks, err := netlink.RouteList(nil, netlink.FAMILY_V4) + if err != nil { + return err + } + + for _, network := range networks { + // TODO Is that right? + if network.Dst != nil && networkOverlaps(toCheck, network.Dst) { + return fmt.Errorf("Requested network %s overlaps with an existing network") + } + } + return nil +} + +func networkOverlaps(netX *net.IPNet, netY *net.IPNet) bool { + if len(netX.IP) == len(netY.IP) { + if firstIP, _ := networkRange(netX); netY.Contains(firstIP) { + return true + } + if firstIP, _ := networkRange(netY); netX.Contains(firstIP) { + return true + } + } + return false +} + +func networkRange(network *net.IPNet) (net.IP, net.IP) { + var netIP net.IP + if network.IP.To4() != nil { + netIP = network.IP.To4() + } else if network.IP.To16() != nil { + netIP = network.IP.To16() + } else { + return nil, nil + } + + lastIP := make([]byte, len(netIP), len(netIP)) + + for i := 0; i < len(netIP); i++ { + lastIP[i] = netIP[i] | ^network.Mask[i] + } + return netIP.Mask(network.Mask), net.IP(lastIP) +} diff --git a/libnetwork/cmd/test/main.go b/libnetwork/cmd/test/main.go index 020e49e4b0..bb2d041068 100644 --- a/libnetwork/cmd/test/main.go +++ b/libnetwork/cmd/test/main.go @@ -10,7 +10,8 @@ import ( ) func main() { - _, net, _ := net.ParseCIDR("192.168.100.1/24") + ip, net, _ := net.ParseCIDR("192.168.100.1/24") + net.IP = ip options := libnetwork.DriverParams{"AddressIPv4": net} netw, err := libnetwork.NewNetwork("simplebridge", options)