!networkAddRoutingIptablesRules(driver, network))
goto err8;
+ /* If we are doing local DHCP service on this network, attempt to
+ * add a rule that will fixup the checksum of DHCP response
+ * packets back to the guests (but report failure without
+ * aborting, since not all iptables implementations support it).
+ */
+
+ if ((network->def->ipAddress || network->def->nranges) &&
+ (iptablesAddOutputFixUdpChecksum(driver->iptables,
+ network->def->bridge, 68) != 0)) {
+ VIR_WARN("Could not add rule to fixup DHCP response checksums "
+ "on network '%s'.", network->def->name);
+ VIR_WARN0("May need to update iptables package & kernel to support CHECKSUM rule.");
+ }
+
return 1;
err8:
static void
networkRemoveIptablesRules(struct network_driver *driver,
virNetworkObjPtr network) {
+ if (network->def->ipAddress || network->def->nranges) {
+ iptablesRemoveOutputFixUdpChecksum(driver->iptables,
+ network->def->bridge, 68);
+ }
if (network->def->forwardType != VIR_NETWORK_FORWARD_NONE) {
if (network->def->forwardType == VIR_NETWORK_FORWARD_NAT) {
iptablesRemoveForwardMasquerade(driver->iptables,
iptRules *input_filter;
iptRules *forward_filter;
iptRules *nat_postrouting;
+ iptRules *mangle_postrouting;
};
static void
if (!(ctx->nat_postrouting = iptRulesNew("nat", "POSTROUTING")))
goto error;
+ if (!(ctx->mangle_postrouting = iptRulesNew("mangle", "POSTROUTING")))
+ goto error;
+
return ctx;
error:
iptRulesFree(ctx->forward_filter);
if (ctx->nat_postrouting)
iptRulesFree(ctx->nat_postrouting);
+ if (ctx->mangle_postrouting)
+ iptRulesFree(ctx->mangle_postrouting);
VIR_FREE(ctx);
}
{
return iptablesForwardMasquerade(ctx, network, physdev, protocol, REMOVE);
}
+
+
+static int
+iptablesOutputFixUdpChecksum(iptablesContext *ctx,
+ const char *iface,
+ int port,
+ int action)
+{
+ char portstr[32];
+
+ snprintf(portstr, sizeof(portstr), "%d", port);
+ portstr[sizeof(portstr) - 1] = '\0';
+
+ return iptablesAddRemoveRule(ctx->mangle_postrouting,
+ action,
+ "--out-interface", iface,
+ "--protocol", "udp",
+ "--destination-port", portstr,
+ "--jump", "CHECKSUM", "--checksum-fill",
+ NULL);
+}
+
+/**
+ * iptablesAddOutputFixUdpChecksum:
+ * @ctx: pointer to the IP table context
+ * @iface: the interface name
+ * @port: the UDP port to match
+ *
+ * Add an rule to the mangle table's POSTROUTING chain that fixes up the
+ * checksum of packets with the given destination @port.
+ * the given @iface interface for TCP packets.
+ *
+ * Returns 0 in case of success or an error code in case of error.
+ * (NB: if the system's iptables does not support checksum mangling,
+ * this will return an error, which should be ignored.)
+ */
+
+int
+iptablesAddOutputFixUdpChecksum(iptablesContext *ctx,
+ const char *iface,
+ int port)
+{
+ return iptablesOutputFixUdpChecksum(ctx, iface, port, ADD);
+}
+
+/**
+ * iptablesRemoveOutputFixUdpChecksum:
+ * @ctx: pointer to the IP table context
+ * @iface: the interface name
+ * @port: the UDP port of the rule to remove
+ *
+ * Removes the checksum fixup rule that was previous added with
+ * iptablesAddOutputFixUdpChecksum.
+ *
+ * Returns 0 in case of success or an error code in case of error
+ * (again, if iptables doesn't support checksum fixup, this will
+ * return an error, which should be ignored)
+ */
+int
+iptablesRemoveOutputFixUdpChecksum(iptablesContext *ctx,
+ const char *iface,
+ int port)
+{
+ return iptablesOutputFixUdpChecksum(ctx, iface, port, REMOVE);
+}