|
|
|
@ -50,52 +50,54 @@ func (p *Plugin) CreateNetwork(r CreateNetworkRequest) error {
|
|
|
|
|
return util.ErrNotBridge
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
v4Addrs, err := netlink.AddrList(link, unix.AF_INET)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("failed to retrieve IPv4 addresses for %v: %w", opts.Bridge, err)
|
|
|
|
|
}
|
|
|
|
|
v6Addrs, err := netlink.AddrList(link, unix.AF_INET6)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("failed to retrieve IPv6 addresses for %v: %w", opts.Bridge, err)
|
|
|
|
|
}
|
|
|
|
|
bridgeAddrs := append(v4Addrs, v6Addrs...)
|
|
|
|
|
|
|
|
|
|
nets, err := p.docker.NetworkList(context.Background(), dTypes.NetworkListOptions{})
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("failed to retrieve list of networks from Docker: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Make sure the addresses on this bridge aren't used by another network
|
|
|
|
|
for _, n := range nets {
|
|
|
|
|
if IsDHCPPlugin(n.Driver) {
|
|
|
|
|
otherOpts, err := decodeOpts(n.Options)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.
|
|
|
|
|
WithField("network", n.Name).
|
|
|
|
|
WithError(err).
|
|
|
|
|
Warn("Failed to parse other DHCP network's options")
|
|
|
|
|
} else if otherOpts.Bridge == opts.Bridge {
|
|
|
|
|
return util.ErrBridgeUsed
|
|
|
|
|
}
|
|
|
|
|
if !opts.IgnoreConflicts {
|
|
|
|
|
v4Addrs, err := netlink.AddrList(link, unix.AF_INET)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("failed to retrieve IPv4 addresses for %v: %w", opts.Bridge, err)
|
|
|
|
|
}
|
|
|
|
|
if n.IPAM.Driver == "null" {
|
|
|
|
|
// Null driver networks will have 0.0.0.0/0 which covers any address range!
|
|
|
|
|
continue
|
|
|
|
|
v6Addrs, err := netlink.AddrList(link, unix.AF_INET6)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("failed to retrieve IPv6 addresses for %v: %w", opts.Bridge, err)
|
|
|
|
|
}
|
|
|
|
|
bridgeAddrs := append(v4Addrs, v6Addrs...)
|
|
|
|
|
|
|
|
|
|
for _, c := range n.IPAM.Config {
|
|
|
|
|
_, dockerCIDR, err := net.ParseCIDR(c.Subnet)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("failed to parse subnet %v on Docker network %v: %w", c.Subnet, n.ID, err)
|
|
|
|
|
nets, err := p.docker.NetworkList(context.Background(), dTypes.NetworkListOptions{})
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("failed to retrieve list of networks from Docker: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Make sure the addresses on this bridge aren't used by another network
|
|
|
|
|
for _, n := range nets {
|
|
|
|
|
if IsDHCPPlugin(n.Driver) {
|
|
|
|
|
otherOpts, err := decodeOpts(n.Options)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.
|
|
|
|
|
WithField("network", n.Name).
|
|
|
|
|
WithError(err).
|
|
|
|
|
Warn("Failed to parse other DHCP network's options")
|
|
|
|
|
} else if otherOpts.Bridge == opts.Bridge {
|
|
|
|
|
return util.ErrBridgeUsed
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if bytes.Equal(dockerCIDR.Mask, net.CIDRMask(0, 32)) || bytes.Equal(dockerCIDR.Mask, net.CIDRMask(0, 128)) {
|
|
|
|
|
// Last check to make sure the network isn't 0.0.0.0/0 or ::/0 (which would always pass the check below)
|
|
|
|
|
if n.IPAM.Driver == "null" {
|
|
|
|
|
// Null driver networks will have 0.0.0.0/0 which covers any address range!
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, bridgeAddr := range bridgeAddrs {
|
|
|
|
|
if bridgeAddr.IPNet.Contains(dockerCIDR.IP) || dockerCIDR.Contains(bridgeAddr.IP) {
|
|
|
|
|
return util.ErrBridgeUsed
|
|
|
|
|
for _, c := range n.IPAM.Config {
|
|
|
|
|
_, dockerCIDR, err := net.ParseCIDR(c.Subnet)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("failed to parse subnet %v on Docker network %v: %w", c.Subnet, n.ID, err)
|
|
|
|
|
}
|
|
|
|
|
if bytes.Equal(dockerCIDR.Mask, net.CIDRMask(0, 32)) || bytes.Equal(dockerCIDR.Mask, net.CIDRMask(0, 128)) {
|
|
|
|
|
// Last check to make sure the network isn't 0.0.0.0/0 or ::/0 (which would always pass the check below)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, bridgeAddr := range bridgeAddrs {
|
|
|
|
|
if bridgeAddr.IPNet.Contains(dockerCIDR.IP) || dockerCIDR.Contains(bridgeAddr.IP) {
|
|
|
|
|
return util.ErrBridgeUsed
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|