func setIcc(bridgeIface string, iccEnable, insert bool) error { var ( table = iptables.Filter chain = "FORWARD" args = []string{"-i", bridgeIface, "-o", bridgeIface, "-j"} acceptArgs = append(args, "ACCEPT") dropArgs = append(args, "DROP") ) if insert { if !iccEnable { iptables.Raw(iptables.Iptables, append([]string{"-D", chain}, acceptArgs...)...) if !iptables.Exists(iptables.Iptables, table, chain, dropArgs...) { if err := iptables.RawCombinedOutput(iptables.Iptables, append([]string{"-A", chain}, dropArgs...)...); err != nil { return fmt.Errorf("Unable to prevent intercontainer communication: %s", err.Error()) } } } else { iptables.Raw(iptables.Iptables, append([]string{"-D", chain}, dropArgs...)...) if !iptables.Exists(iptables.Iptables, table, chain, acceptArgs...) { if err := iptables.RawCombinedOutput(iptables.Iptables, append([]string{"-I", chain}, acceptArgs...)...); err != nil { return fmt.Errorf("Unable to allow intercontainer communication: %s", err.Error()) } } } } else { // Remove any ICC rule. if !iccEnable { if iptables.Exists(iptables.Iptables, table, chain, dropArgs...) { iptables.Raw(iptables.Iptables, append([]string{"-D", chain}, dropArgs...)...) } } else { if iptables.Exists(iptables.Iptables, table, chain, acceptArgs...) { iptables.Raw(iptables.Iptables, append([]string{"-D", chain}, acceptArgs...)...) } } } return nil }
func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]interface{}) error { defer osl.InitOSContext()() if ifInfo == nil { return errors.New("invalid interface info passed") } // Get the network handler and make sure it exists d.Lock() n, ok := d.networks[nid] dconfig := d.config d.Unlock() if !ok { return types.NotFoundErrorf("network %s does not exist", nid) } if n == nil { return driverapi.ErrNoNetwork(nid) } // Sanity check n.Lock() if n.id != nid { n.Unlock() return InvalidNetworkIDError(nid) } n.Unlock() // Check if endpoint id is good and retrieve correspondent endpoint ep, err := n.getEndpoint(eid) if err != nil { return err } // Endpoint with that id exists either on desired or other sandbox if ep != nil { return driverapi.ErrEndpointExists(eid) } // Try to convert the options to endpoint configuration epConfig, err := parseEndpointOptions(epOptions) if err != nil { return err } // Create and add the endpoint n.Lock() endpoint := &bridgeEndpoint{id: eid, config: epConfig} n.endpoints[eid] = endpoint n.Unlock() // On failure make sure to remove the endpoint defer func() { if err != nil { n.Lock() delete(n.endpoints, eid) n.Unlock() } }() // Generate a name for what will be the host side pipe interface hostIfName, err := netutils.GenerateIfaceName(vethPrefix, vethLen) if err != nil { return err } // Generate a name for what will be the sandbox side pipe interface containerIfName, err := netutils.GenerateIfaceName(vethPrefix, vethLen) if err != nil { return err } // Generate and add the interface pipe host <-> sandbox veth := &netlink.Veth{ LinkAttrs: netlink.LinkAttrs{Name: hostIfName, TxQLen: 0}, PeerName: containerIfName} if err = netlink.LinkAdd(veth); err != nil { return types.InternalErrorf("failed to add the host (%s) <=> sandbox (%s) pair interfaces: %v", hostIfName, containerIfName, err) } // Get the host side pipe interface handler host, err := netlink.LinkByName(hostIfName) if err != nil { return types.InternalErrorf("failed to find host side interface %s: %v", hostIfName, err) } defer func() { if err != nil { netlink.LinkDel(host) } }() // Get the sandbox side pipe interface handler sbox, err := netlink.LinkByName(containerIfName) if err != nil { return types.InternalErrorf("failed to find sandbox side interface %s: %v", containerIfName, err) } defer func() { if err != nil { netlink.LinkDel(sbox) } }() n.Lock() config := n.config n.Unlock() // Add bridge inherited attributes to pipe interfaces if config.Mtu != 0 { err = netlink.LinkSetMTU(host, config.Mtu) if err != nil { return types.InternalErrorf("failed to set MTU on host interface %s: %v", hostIfName, err) } err = netlink.LinkSetMTU(sbox, config.Mtu) if err != nil { return types.InternalErrorf("failed to set MTU on sandbox interface %s: %v", containerIfName, err) } } // Attach host side pipe interface into the bridge if err = addToBridge(hostIfName, config.BridgeName); err != nil { return fmt.Errorf("adding interface %s to bridge %s failed: %v", hostIfName, config.BridgeName, err) } if !dconfig.EnableUserlandProxy { err = setHairpinMode(host, true) if err != nil { return err } } // Create the sandbox side pipe interface endpoint.srcName = containerIfName endpoint.macAddress = ifInfo.MacAddress() endpoint.addr = ifInfo.Address() endpoint.addrv6 = ifInfo.AddressIPv6() // Down the interface before configuring mac address. if err = netlink.LinkSetDown(sbox); err != nil { return fmt.Errorf("could not set link down for container interface %s: %v", containerIfName, err) } // Set the sbox's MAC. If specified, use the one configured by user, otherwise generate one based on IP. if endpoint.macAddress == nil { endpoint.macAddress = electMacAddress(epConfig, endpoint.addr.IP) if err := ifInfo.SetMacAddress(endpoint.macAddress); err != nil { return err } } err = netlink.LinkSetHardwareAddr(sbox, endpoint.macAddress) if err != nil { return fmt.Errorf("could not set mac address for container interface %s: %v", containerIfName, err) } // Up the host interface after finishing all netlink configuration if err = netlink.LinkSetUp(host); err != nil { return fmt.Errorf("could not set link up for host interface %s: %v", hostIfName, err) } if endpoint.addrv6 == nil && config.EnableIPv6 { var ip6 net.IP network := n.bridge.bridgeIPv6 if config.AddressIPv6 != nil { network = config.AddressIPv6 } ones, _ := network.Mask.Size() if ones > 80 { err = types.ForbiddenErrorf("Cannot self generate an IPv6 address on network %v: At least 48 host bits are needed.", network) return err } ip6 = make(net.IP, len(network.IP)) copy(ip6, network.IP) for i, h := range endpoint.macAddress { ip6[i+10] = h } endpoint.addrv6 = &net.IPNet{IP: ip6, Mask: network.Mask} if err := ifInfo.SetIPAddress(endpoint.addrv6); err != nil { return err } } // Add a neighbor proxy if using NDP proxying if config.NDPProxyInterface != "" && config.EnableIPv6 { link, err := netlink.LinkByName(config.NDPProxyInterface) if err != nil { return err } neighbor := netlink.Neigh{ LinkIndex: link.Attrs().Index, Family: netlink.FAMILY_V6, State: netlink.NUD_PERMANENT, Type: netlink.NDA_UNSPEC, Flags: netlink.NTF_PROXY, IP: endpoint.addrv6.IP, HardwareAddr: endpoint.macAddress, } if err := netlink.NeighAdd(&neighbor); err != nil { logrus.Warnf("could not add the neighbor proxy: %v", err) return err } if endpoint.config != nil { for _, port := range endpoint.config.ExposedPorts { insert := []string{ string(iptables.Insert), DockerChain, "-p", port.Proto.String(), "-d", endpoint.addrv6.String(), "--dport", strconv.Itoa(int(port.Port)), "-j", "ACCEPT", } iptables.Raw(iptables.IP6Tables, insert...) } } } // Program any required port mapping and store them in the endpoint endpoint.portMapping, err = n.allocatePorts(epConfig, endpoint, config.DefaultBindingIP, d.config.EnableUserlandProxy) if err != nil { return err } return nil }
func (d *driver) DeleteEndpoint(nid, eid string) error { var err error defer osl.InitOSContext()() // Get the network handler and make sure it exists d.Lock() n, ok := d.networks[nid] d.Unlock() if !ok { return types.InternalMaskableErrorf("network %s does not exist", nid) } if n == nil { return driverapi.ErrNoNetwork(nid) } // Sanity Check n.Lock() if n.id != nid { n.Unlock() return InvalidNetworkIDError(nid) } n.Unlock() // Check endpoint id and if an endpoint is actually there ep, err := n.getEndpoint(eid) if err != nil { return err } if ep == nil { return EndpointNotFoundError(eid) } // Remove it n.Lock() delete(n.endpoints, eid) n.Unlock() // On failure make sure to set back ep in n.endpoints, but only // if it hasn't been taken over already by some other thread. defer func() { if err != nil { n.Lock() if _, ok := n.endpoints[eid]; !ok { n.endpoints[eid] = ep } n.Unlock() } }() // Remove port mappings. Do not stop endpoint delete on unmap failure n.releasePorts(ep) if ep.config != nil { for _, port := range ep.config.ExposedPorts { rule := []string{ "-p", port.Proto.String(), "-d", ep.addrv6.String(), "--dport", strconv.Itoa(int(port.Port)), "-j", "ACCEPT", } if iptables.Exists(iptables.IP6Tables, iptables.Filter, DockerChain, rule...) { delete := append( []string{ string(iptables.Delete), DockerChain, }, rule..., ) iptables.Raw(iptables.IP6Tables, delete...) } } } // Try removal of neighbor proxy. Discard error: it is a best effort. // Also make sure defer does not see this error either. if n.config.NDPProxyInterface != "" && n.config.EnableIPv6 { link, err := netlink.LinkByName(n.config.NDPProxyInterface) if err == nil { neighbor := netlink.Neigh{ LinkIndex: link.Attrs().Index, Family: netlink.FAMILY_V6, State: netlink.NUD_PERMANENT, Type: netlink.NDA_UNSPEC, Flags: netlink.NTF_PROXY, IP: ep.addrv6.IP, HardwareAddr: ep.macAddress, } netlink.NeighDel(&neighbor) } } // Try removal of link. Discard error: it is a best effort. // Also make sure defer does not see this error either. if link, err := netlink.LinkByName(ep.srcName); err == nil { netlink.LinkDel(link) } return nil }