1 // SPDX-License-Identifier: GPL-2.0-only
2 /* iptables module for the packet checksum mangling
4 * (C) 2002 by Harald Welte <laforge@netfilter.org>
5 * (C) 2010 Red Hat, Inc.
7 * Author: Michael S. Tsirkin <mst@redhat.com>
9 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
10 #include <linux/module.h>
11 #include <linux/skbuff.h>
13 #include <linux/netfilter/x_tables.h>
14 #include <linux/netfilter/xt_CHECKSUM.h>
16 #include <linux/netfilter_ipv4/ip_tables.h>
17 #include <linux/netfilter_ipv6/ip6_tables.h>
19 MODULE_LICENSE("GPL");
20 MODULE_AUTHOR("Michael S. Tsirkin <mst@redhat.com>");
21 MODULE_DESCRIPTION("Xtables: checksum modification");
22 MODULE_ALIAS("ipt_CHECKSUM");
23 MODULE_ALIAS("ip6t_CHECKSUM");
26 checksum_tg(struct sk_buff
*skb
, const struct xt_action_param
*par
)
28 if (skb
->ip_summed
== CHECKSUM_PARTIAL
&& !skb_is_gso(skb
))
29 skb_checksum_help(skb
);
34 static int checksum_tg_check(const struct xt_tgchk_param
*par
)
36 const struct xt_CHECKSUM_info
*einfo
= par
->targinfo
;
37 const struct ip6t_ip6
*i6
= par
->entryinfo
;
38 const struct ipt_ip
*i4
= par
->entryinfo
;
40 if (einfo
->operation
& ~XT_CHECKSUM_OP_FILL
) {
41 pr_info_ratelimited("unsupported CHECKSUM operation %x\n",
45 if (!einfo
->operation
)
48 switch (par
->family
) {
50 if (i4
->proto
== IPPROTO_UDP
&&
51 (i4
->invflags
& XT_INV_PROTO
) == 0)
55 if ((i6
->flags
& IP6T_F_PROTO
) &&
56 i6
->proto
== IPPROTO_UDP
&&
57 (i6
->invflags
& XT_INV_PROTO
) == 0)
62 pr_warn_once("CHECKSUM should be avoided. If really needed, restrict with \"-p udp\" and only use in OUTPUT\n");
66 static struct xt_target checksum_tg_reg __read_mostly
= {
68 .family
= NFPROTO_UNSPEC
,
69 .target
= checksum_tg
,
70 .targetsize
= sizeof(struct xt_CHECKSUM_info
),
72 .checkentry
= checksum_tg_check
,
76 static int __init
checksum_tg_init(void)
78 return xt_register_target(&checksum_tg_reg
);
81 static void __exit
checksum_tg_exit(void)
83 xt_unregister_target(&checksum_tg_reg
);
86 module_init(checksum_tg_init
);
87 module_exit(checksum_tg_exit
);