/* Allow all traffic coming from the bridge, with a valid network address * to proceed to WAN */ static int iptablesForwardAllowOut(iptablesContext *ctx, virSocketAddr *netaddr, unsigned int prefix, const char *iface, const char *physdev, int action) { int ret; char *networkstr; virCommandPtr cmd = NULL; if (!(networkstr = iptablesFormatNetwork(netaddr, prefix))) return -1; cmd = iptablesCommandNew(ctx->forward_filter, VIR_SOCKET_ADDR_FAMILY(netaddr), action); virCommandAddArgList(cmd, "--source", networkstr, "--in-interface", iface, NULL); if (physdev && physdev[0]) virCommandAddArgList(cmd, "--out-interface", physdev, NULL); virCommandAddArgList(cmd, "--jump", "ACCEPT", NULL); ret = iptablesCommandRunAndFree(cmd); VIR_FREE(networkstr); return ret; }
/* Don't masquerade traffic coming from the network associated with the bridge * if said traffic targets @destaddr. */ static int iptablesForwardDontMasquerade(virSocketAddr *netaddr, unsigned int prefix, const char *physdev, const char *destaddr, int action) { int ret = -1; char *networkstr = NULL; virCommandPtr cmd = NULL; 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); goto cleanup; } cmd = iptablesCommandNew("nat", "POSTROUTING", AF_INET, action); if (physdev && physdev[0]) virCommandAddArgList(cmd, "--out-interface", physdev, NULL); virCommandAddArgList(cmd, "--source", networkstr, "--destination", destaddr, "--jump", "RETURN", NULL); ret = virCommandRun(cmd, NULL); cleanup: virCommandFree(cmd); VIR_FREE(networkstr); return ret; }
static int ATTRIBUTE_SENTINEL iptablesAddRemoveRule(iptRules *rules, int family, int action, const char *arg, ...) { va_list args; virCommandPtr cmd = NULL; const char *s; cmd = iptablesCommandNew(rules, family, action); virCommandAddArg(cmd, arg); va_start(args, arg); while ((s = va_arg(args, const char *))) virCommandAddArg(cmd, s); va_end(args); return iptablesCommandRunAndFree(cmd); }
/* Masquerade all traffic coming from the network associated * with the bridge */ static int iptablesForwardMasquerade(iptablesContext *ctx, virSocketAddr *netaddr, unsigned int prefix, const char *physdev, virSocketAddr *addrStart, virSocketAddr *addrEnd, unsigned int portStart, unsigned int portEnd, const char *protocol, int action) { int ret = -1; char *networkstr = NULL; char *addrStartStr = NULL; char *addrEndStr = NULL; char *portRangeStr = NULL; char *natRangeStr = NULL; virCommandPtr cmd = NULL; 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); goto cleanup; } if (VIR_SOCKET_ADDR_IS_FAMILY(addrStart, AF_INET)) { if (!(addrStartStr = virSocketAddrFormat(addrStart))) goto cleanup; if (VIR_SOCKET_ADDR_IS_FAMILY(addrEnd, AF_INET)) { if (!(addrEndStr = virSocketAddrFormat(addrEnd))) goto cleanup; } } cmd = iptablesCommandNew(ctx->nat_postrouting, AF_INET, action); virCommandAddArgList(cmd, "--source", networkstr, NULL); if (protocol && protocol[0]) virCommandAddArgList(cmd, "-p", protocol, NULL); virCommandAddArgList(cmd, "!", "--destination", networkstr, NULL); if (physdev && physdev[0]) virCommandAddArgList(cmd, "--out-interface", physdev, NULL); if (protocol && protocol[0]) { if (portStart == 0 && portEnd == 0) { portStart = 1024; portEnd = 65535; } if (portStart < portEnd && portEnd < 65536) { if (virAsprintf(&portRangeStr, ":%u-%u", portStart, portEnd) < 0) { virReportOOMError(); goto cleanup; } } else { virReportError(VIR_ERR_INTERNAL_ERROR, _("Invalid port range '%u-%u'."), portStart, portEnd); } } /* 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) { virReportOOMError(); goto cleanup; } virCommandAddArgList(cmd, "--jump", "SNAT", "--to-source", natRangeStr, NULL); } else { virCommandAddArgList(cmd, "--jump", "MASQUERADE", NULL); if (portRangeStr && portRangeStr[0]) virCommandAddArgList(cmd, "--to-ports", &portRangeStr[1], NULL); } ret = virCommandRun(cmd, NULL); cleanup: virCommandFree(cmd); VIR_FREE(networkstr); VIR_FREE(addrStartStr); VIR_FREE(addrEndStr); VIR_FREE(portRangeStr); VIR_FREE(natRangeStr); return ret; }