func DetachContainer(netNSPath, id, ifName string, cidrs []*net.IPNet) error {
	ns, err := netns.GetFromPath(netNSPath)
	if err != nil {
		return err
	}
	defer ns.Close()

	ipt, err := iptables.New()
	if err != nil {
		return err
	}

	return WithNetNSLinkUnsafe(ns, ifName, func(veth netlink.Link) error {
		existingAddrs, err := netlink.AddrList(veth, netlink.FAMILY_V4)
		if err != nil {
			return fmt.Errorf("failed to get IP address for %q: %v", veth.Attrs().Name, err)
		}
		for _, ipnet := range cidrs {
			if !contains(existingAddrs, ipnet) {
				continue
			}
			if err := netlink.AddrDel(veth, &netlink.Addr{IPNet: ipnet}); err != nil {
				return fmt.Errorf("failed to remove IP address from %q: %v", veth.Attrs().Name, err)
			}
		}
		addrs, err := netlink.AddrList(veth, netlink.FAMILY_V4)
		if err != nil {
			return fmt.Errorf("failed to get IP address for %q: %v", veth.Attrs().Name, err)
		}

		// Remove multicast ACCEPT rules for subnets we no longer have addresses in
		subnets := subnets(addrs)
		rules, err := ipt.List("filter", "INPUT")
		if err != nil {
			return err
		}
		for _, rule := range rules {
			ps := strings.Split(rule, " ")
			if len(ps) == 10 &&
				ps[0] == "-A" && ps[2] == "-s" && ps[4] == "-d" && ps[5] == "224.0.0.0/4" &&
				ps[6] == "-i" && ps[7] == ifName && ps[8] == "-j" && ps[9] == "ACCEPT" {

				if _, found := subnets[ps[3]]; !found {
					if err := ipt.Delete("filter", "INPUT", ps[2:]...); err != nil {
						return err
					}
				}
			}
		}

		if len(addrs) == 0 { // all addresses gone: remove the interface
			if err := ipt.Delete("filter", "INPUT", "-i", ifName, "-d", "224.0.0.0/4", "-j", "DROP"); err != nil {
				return err
			}
			if err := netlink.LinkDel(veth); err != nil {
				return err
			}
		}
		return nil
	})
}
// NB: This function can be used only by a process that terminates immediately
//     after calling the function as it changes netns via WithNetNSLinkUnsafe.
This function can be used only by a process that terminates immediately
after calling the function as it changes netns via WithNetNSLinkUnsafe.
// NB : This function can be used only by a process that terminates immediately // after calling the function as it changes netns via WithNetNSLinkUnsafe .
func DetachContainer(netNSPath, id, ifName string, cidrs []*net.IPNet) error {
	ns, err := netns.GetFromPath(netNSPath)
	if err != nil {
		return err
	}
	defer ns.Close()
	ipt, err := iptables.New()
	if err != nil {
		return err
	}
	return WithNetNSLinkUnsafe(ns, ifName, func(veth netlink.Link) error {
		existingAddrs, err := netlink.AddrList(veth, netlink.FAMILY_V4)
		if err != nil {
			return fmt.Errorf("failed to get IP address for %q: %v", veth.Attrs().Name, err)
		}
		for _, ipnet := range cidrs {
			if !contains(existingAddrs, ipnet) {
				continue
			}
			if err := netlink.AddrDel(veth, &netlink.Addr{IPNet: ipnet}); err != nil {
				return fmt.Errorf("failed to remove IP address from %q: %v", veth.Attrs().Name, err)
			}
		}
		addrs, err := netlink.AddrList(veth, netlink.FAMILY_V4)
		if err != nil {
			return fmt.Errorf("failed to get IP address for %q: %v", veth.Attrs().Name, err)
		}
		subnets := subnets(addrs)
		rules, err := ipt.List("filter", "INPUT")
		if err != nil {
			return err
		}
		for _, rule := range rules {
			ps := strings.Split(rule, " ")
			if len(ps) == 10 &&
				ps[0] == "-A" && ps[2] == "-s" && ps[4] == "-d" && ps[5] == "224.0.0.0/4" &&
				ps[6] == "-i" && ps[7] == ifName && ps[8] == "-j" && ps[9] == "ACCEPT" {
				if _, found := subnets[ps[3]]; !found {
					if err := ipt.Delete("filter", "INPUT", ps[2:]...); err != nil {
						return err
					}
				}
			}
		}
		if len(addrs) == 0 { 
			if err := ipt.Delete("filter", "INPUT", "-i", ifName, "-d", "224.0.0.0/4", "-j", "DROP"); err != nil {
				return err
			}
			if err := netlink.LinkDel(veth); err != nil {
				return err
			}
		}
		return nil
	})
}
func DetachContainer ( netNSPath , id , ifName string , cidrs [ ] * net . IPNet ) error { ns , err := netns . GetFromPath ( netNSPath ) if err != nil { return err } defer ns . Close ( ) ipt , err := iptables . New ( ) if err != nil { return err } return WithNetNSLinkUnsafe ( ns , ifName , func ( veth netlink . Link ) error { existingAddrs , err := netlink . AddrList ( veth , netlink . FAMILY_V4 ) if err != nil { return fmt . Errorf ( " " , veth . Attrs ( ) . Name , err ) } for _ , ipnet := range cidrs { if ! contains ( existingAddrs , ipnet ) { continue } if err := netlink . AddrDel ( veth , & netlink . Addr { IPNet : ipnet } ) ; err != nil { return fmt . Errorf ( " " , veth . Attrs ( ) . Name , err ) } } addrs , err := netlink . AddrList ( veth , netlink . FAMILY_V4 ) if err != nil { return fmt . Errorf ( " " , veth . Attrs ( ) . Name , err ) } subnets := subnets ( addrs ) rules , err := ipt . List ( " " , " " ) if err != nil { return err } for _ , rule := range rules { ps := strings . Split ( rule , " " ) if len ( ps ) == 10 && ps [ 0 ] == " " && ps [ 2 ] == " " && ps [ 4 ] == " " && ps [ 5 ] == " " && ps [ 6 ] == " " && ps [ 7 ] == ifName && ps [ 8 ] == " " && ps [ 9 ] == " " { if _ , found := subnets [ ps [ 3 ] ] ; ! found { if err := ipt . Delete ( " " , " " , ps [ 2 : ] ... ) ; err != nil { return err } } } } if len ( addrs ) == 0 { if err := ipt . Delete ( " " , " " , " " , ifName , " " , " " , " " , " " ) ; err != nil { return err } if err := netlink . LinkDel ( veth ) ; err != nil { return err } } return nil } ) }
This function can be used only by a process that terminates immediately
after calling the function as it changes netns via WithNetNSLinkUnsafe.
This function can be used only by a process that terminates immediately after calling the function as it changes netns via WithNetNSLinkUnsafe .
// Remove multicast ACCEPT rules for subnets we no longer have addresses in // all addresses gone: remove the interface