static int testFirewallRemoveRule(const void *opaque) { virBuffer cmdbuf = VIR_BUFFER_INITIALIZER; virFirewallPtr fw = NULL; int ret = -1; const char *actual = NULL; const char *expected = IPTABLES_PATH " -A INPUT --source-host 192.168.122.1 --jump ACCEPT\n" IPTABLES_PATH " -A INPUT --source-host '!192.168.122.1' --jump REJECT\n"; const struct testFirewallData *data = opaque; virFirewallRulePtr fwrule; fwDisabled = data->fwDisabled; if (virFirewallSetBackend(data->tryBackend) < 0) goto cleanup; if (data->expectBackend == VIR_FIREWALL_BACKEND_DIRECT) virCommandSetDryRun(&cmdbuf, NULL, NULL); else fwBuf = &cmdbuf; fw = virFirewallNew(); virFirewallStartTransaction(fw, 0); virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, "-A", "INPUT", "--source-host", "192.168.122.1", "--jump", "ACCEPT", NULL); fwrule = virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, "-A", "INPUT", NULL); virFirewallRuleAddArg(fw, fwrule, "--source-host"); virFirewallRemoveRule(fw, fwrule); fwrule = virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, "-A", "INPUT", NULL); virFirewallRuleAddArg(fw, fwrule, "--source-host"); virFirewallRuleAddArgFormat(fw, fwrule, "%s", "!192.168.122.1"); virFirewallRuleAddArgList(fw, fwrule, "--jump", "REJECT", NULL); if (virFirewallApply(fw) < 0) goto cleanup; if (virBufferError(&cmdbuf)) goto cleanup; actual = virBufferCurrentContent(&cmdbuf); if (STRNEQ_NULLABLE(expected, actual)) { fprintf(stderr, "Unexected command execution\n"); virTestDifference(stderr, expected, actual); goto cleanup; } ret = 0; cleanup: virBufferFreeAndReset(&cmdbuf); fwBuf = NULL; virCommandSetDryRun(NULL, NULL, NULL); virFirewallFree(fw); return ret; }
/* Masquerade all traffic coming from the network associated * with the bridge */ static int iptablesForwardMasquerade(virFirewallPtr fw, virSocketAddr *netaddr, unsigned int prefix, const char *physdev, virSocketAddrRangePtr addr, virPortRangePtr port, const char *protocol, int action) { VIR_AUTOFREE(char *) networkstr = NULL; VIR_AUTOFREE(char *) addrStartStr = NULL; VIR_AUTOFREE(char *) addrEndStr = NULL; VIR_AUTOFREE(char *) portRangeStr = NULL; VIR_AUTOFREE(char *) natRangeStr = NULL; virFirewallRulePtr rule; if (!(networkstr = iptablesFormatNetwork(netaddr, prefix))) return -1; if (!VIR_SOCKET_ADDR_IS_FAMILY(netaddr, AF_INET)) { /* Higher level code *should* guaranteee it's impossible to get here. */ virReportError(VIR_ERR_INTERNAL_ERROR, _("Attempted to NAT '%s'. NAT is only supported for IPv4."), networkstr); return -1; } if (VIR_SOCKET_ADDR_IS_FAMILY(&addr->start, AF_INET)) { if (!(addrStartStr = virSocketAddrFormat(&addr->start))) return -1; if (VIR_SOCKET_ADDR_IS_FAMILY(&addr->end, AF_INET)) { if (!(addrEndStr = virSocketAddrFormat(&addr->end))) return -1; } } if (protocol && protocol[0]) { rule = virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, "--table", "nat", action == ADD ? "--insert" : "--delete", "POSTROUTING", "--source", networkstr, "-p", protocol, "!", "--destination", networkstr, NULL); } else { rule = virFirewallAddRule(fw, VIR_FIREWALL_LAYER_IPV4, "--table", "nat", action == ADD ? "--insert" : "--delete", "POSTROUTING", "--source", networkstr, "!", "--destination", networkstr, NULL); } if (physdev && physdev[0]) virFirewallRuleAddArgList(fw, rule, "--out-interface", physdev, NULL); if (protocol && protocol[0]) { if (port->start == 0 && port->end == 0) { port->start = 1024; port->end = 65535; } if (port->start < port->end && port->end < 65536) { if (virAsprintf(&portRangeStr, ":%u-%u", port->start, port->end) < 0) return -1; } else { virReportError(VIR_ERR_INTERNAL_ERROR, _("Invalid port range '%u-%u'."), port->start, port->end); } } /* Use --jump SNAT if public addr is specified */ if (addrStartStr && addrStartStr[0]) { int r = 0; if (addrEndStr && addrEndStr[0]) { r = virAsprintf(&natRangeStr, "%s-%s%s", addrStartStr, addrEndStr, portRangeStr ? portRangeStr : ""); } else { r = virAsprintf(&natRangeStr, "%s%s", addrStartStr, portRangeStr ? portRangeStr : ""); } if (r < 0) return -1; virFirewallRuleAddArgList(fw, rule, "--jump", "SNAT", "--to-source", natRangeStr, NULL); } else { virFirewallRuleAddArgList(fw, rule, "--jump", "MASQUERADE", NULL); if (portRangeStr && portRangeStr[0]) virFirewallRuleAddArgList(fw, rule, "--to-ports", &portRangeStr[1], NULL); } return 0; }