|
@@ -16,6 +16,9 @@
|
|
|
#include <linux/netfilter/x_tables.h>
|
|
|
#include <linux/netfilter/xt_CHECKSUM.h>
|
|
|
|
|
|
+#include <linux/netfilter_ipv4/ip_tables.h>
|
|
|
+#include <linux/netfilter_ipv6/ip6_tables.h>
|
|
|
+
|
|
|
MODULE_LICENSE("GPL");
|
|
|
MODULE_AUTHOR("Michael S. Tsirkin <mst@redhat.com>");
|
|
|
MODULE_DESCRIPTION("Xtables: checksum modification");
|
|
@@ -25,7 +28,7 @@ MODULE_ALIAS("ip6t_CHECKSUM");
|
|
|
static unsigned int
|
|
|
checksum_tg(struct sk_buff *skb, const struct xt_action_param *par)
|
|
|
{
|
|
|
- if (skb->ip_summed == CHECKSUM_PARTIAL)
|
|
|
+ if (skb->ip_summed == CHECKSUM_PARTIAL && !skb_is_gso(skb))
|
|
|
skb_checksum_help(skb);
|
|
|
|
|
|
return XT_CONTINUE;
|
|
@@ -34,6 +37,8 @@ checksum_tg(struct sk_buff *skb, const struct xt_action_param *par)
|
|
|
static int checksum_tg_check(const struct xt_tgchk_param *par)
|
|
|
{
|
|
|
const struct xt_CHECKSUM_info *einfo = par->targinfo;
|
|
|
+ const struct ip6t_ip6 *i6 = par->entryinfo;
|
|
|
+ const struct ipt_ip *i4 = par->entryinfo;
|
|
|
|
|
|
if (einfo->operation & ~XT_CHECKSUM_OP_FILL) {
|
|
|
pr_info_ratelimited("unsupported CHECKSUM operation %x\n",
|
|
@@ -43,6 +48,21 @@ static int checksum_tg_check(const struct xt_tgchk_param *par)
|
|
|
if (!einfo->operation)
|
|
|
return -EINVAL;
|
|
|
|
|
|
+ switch (par->family) {
|
|
|
+ case NFPROTO_IPV4:
|
|
|
+ if (i4->proto == IPPROTO_UDP &&
|
|
|
+ (i4->invflags & XT_INV_PROTO) == 0)
|
|
|
+ return 0;
|
|
|
+ break;
|
|
|
+ case NFPROTO_IPV6:
|
|
|
+ if ((i6->flags & IP6T_F_PROTO) &&
|
|
|
+ i6->proto == IPPROTO_UDP &&
|
|
|
+ (i6->invflags & XT_INV_PROTO) == 0)
|
|
|
+ return 0;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ pr_warn_once("CHECKSUM should be avoided. If really needed, restrict with \"-p udp\" and only use in OUTPUT\n");
|
|
|
return 0;
|
|
|
}
|
|
|
|