// Control Inter Network Communication. Install/remove only if it is not/is present.
func setINC(iface1, iface2 string, enable bool) error {
	var (
		table = iptables.Filter
		chain = IsolationChain
		args  = [2][]string{{"-i", iface1, "-o", iface2, "-j", "DROP"}, {"-i", iface2, "-o", iface1, "-j", "DROP"}}
	)

	if enable {
		for i := 0; i < 2; i++ {
			if iptables.Exists(iptables.Iptables, table, chain, args[i]...) {
				continue
			}
			if err := iptables.RawCombinedOutput(iptables.Iptables, append([]string{"-I", chain}, args[i]...)...); err != nil {
				return fmt.Errorf("unable to add inter-network communication rule: %v", err)
			}
		}
	} else {
		for i := 0; i < 2; i++ {
			if !iptables.Exists(iptables.Iptables, table, chain, args[i]...) {
				continue
			}
			if err := iptables.RawCombinedOutput(iptables.Iptables, append([]string{"-D", chain}, args[i]...)...); err != nil {
				return fmt.Errorf("unable to remove inter-network communication rule: %v", err)
			}
		}
	}

	return nil
}
func programChainRule(rule iptRule, ruleDescr string, insert bool) error {
	var (
		prefix    []string
		operation string
		condition bool
		doesExist = iptables.Exists(rule.ipv, rule.table, rule.chain, rule.args...)
	)

	if insert {
		condition = !doesExist
		prefix = []string{"-I", rule.chain}
		operation = "enable"
	} else {
		condition = doesExist
		prefix = []string{"-D", rule.chain}
		operation = "disable"
	}
	if rule.preArgs != nil {
		prefix = append(rule.preArgs, prefix...)
	}

	if condition {
		if err := iptables.RawCombinedOutput(rule.ipv, append(prefix, rule.args...)...); err != nil {
			return fmt.Errorf("Unable to %s %s rule: %s", operation, ruleDescr, err.Error())
		}
	}

	return nil
}
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
}
// Ensure the jump rule is on top
func ensureJumpRule(ipv iptables.IPV, fromChain, toChain string) error {
	var (
		table = iptables.Filter
		args  = []string{"-j", toChain}
	)

	if iptables.Exists(ipv, table, fromChain, args...) {
		err := iptables.RawCombinedOutput(ipv, append([]string{"-D", fromChain}, args...)...)
		if err != nil {
			return fmt.Errorf("unable to remove jump to %s rule in %s chain: %s", toChain, fromChain, err.Error())
		}
	}

	err := iptables.RawCombinedOutput(ipv, append([]string{"-I", fromChain}, args...)...)
	if err != nil {
		return fmt.Errorf("unable to insert jump to %s rule in %s chain: %s", toChain, fromChain, err.Error())
	}

	return nil
}
func addReturnRule(ipv iptables.IPV, chain string) error {
	var (
		table = iptables.Filter
		args  = []string{"-j", "RETURN"}
	)

	if iptables.Exists(ipv, table, chain, args...) {
		return nil
	}

	err := iptables.RawCombinedOutput(ipv, append([]string{"-I", chain}, args...)...)
	if err != nil {
		return fmt.Errorf("unable to add return rule in %s chain: %s", chain, err.Error())
	}

	return nil
}