예제 #1
0
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;
}
예제 #2
0
/* 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;
}