1 /* iptables module for the packet checksum mangling
2  *
3  * (C) 2002 by Harald Welte <laforge@netfilter.org>
4  * (C) 2010 Red Hat, Inc.
5  *
6  * Author: Michael S. Tsirkin <mst@redhat.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11 */
12 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
13 #include <linux/module.h>
14 #include <linux/skbuff.h>
15 
16 #include <linux/netfilter/x_tables.h>
17 #include <linux/netfilter/xt_CHECKSUM.h>
18 
19 #include <linux/netfilter_ipv4/ip_tables.h>
20 #include <linux/netfilter_ipv6/ip6_tables.h>
21 
22 MODULE_LICENSE("GPL");
23 MODULE_AUTHOR("Michael S. Tsirkin <mst@redhat.com>");
24 MODULE_DESCRIPTION("Xtables: checksum modification");
25 MODULE_ALIAS("ipt_CHECKSUM");
26 MODULE_ALIAS("ip6t_CHECKSUM");
27 
28 static unsigned int
checksum_tg(struct sk_buff * skb,const struct xt_action_param * par)29 checksum_tg(struct sk_buff *skb, const struct xt_action_param *par)
30 {
31 	if (skb->ip_summed == CHECKSUM_PARTIAL && !skb_is_gso(skb))
32 		skb_checksum_help(skb);
33 
34 	return XT_CONTINUE;
35 }
36 
checksum_tg_check(const struct xt_tgchk_param * par)37 static int checksum_tg_check(const struct xt_tgchk_param *par)
38 {
39 	const struct xt_CHECKSUM_info *einfo = par->targinfo;
40 	const struct ip6t_ip6 *i6 = par->entryinfo;
41 	const struct ipt_ip *i4 = par->entryinfo;
42 
43 	if (einfo->operation & ~XT_CHECKSUM_OP_FILL) {
44 		pr_info_ratelimited("unsupported CHECKSUM operation %x\n",
45 				    einfo->operation);
46 		return -EINVAL;
47 	}
48 	if (!einfo->operation)
49 		return -EINVAL;
50 
51 	switch (par->family) {
52 	case NFPROTO_IPV4:
53 		if (i4->proto == IPPROTO_UDP &&
54 		    (i4->invflags & XT_INV_PROTO) == 0)
55 			return 0;
56 		break;
57 	case NFPROTO_IPV6:
58 		if ((i6->flags & IP6T_F_PROTO) &&
59 		    i6->proto == IPPROTO_UDP &&
60 		    (i6->invflags & XT_INV_PROTO) == 0)
61 			return 0;
62 		break;
63 	}
64 
65 	pr_warn_once("CHECKSUM should be avoided.  If really needed, restrict with \"-p udp\" and only use in OUTPUT\n");
66 	return 0;
67 }
68 
69 static struct xt_target checksum_tg_reg __read_mostly = {
70 	.name		= "CHECKSUM",
71 	.family		= NFPROTO_UNSPEC,
72 	.target		= checksum_tg,
73 	.targetsize	= sizeof(struct xt_CHECKSUM_info),
74 	.table		= "mangle",
75 	.checkentry	= checksum_tg_check,
76 	.me		= THIS_MODULE,
77 };
78 
checksum_tg_init(void)79 static int __init checksum_tg_init(void)
80 {
81 	return xt_register_target(&checksum_tg_reg);
82 }
83 
checksum_tg_exit(void)84 static void __exit checksum_tg_exit(void)
85 {
86 	xt_unregister_target(&checksum_tg_reg);
87 }
88 
89 module_init(checksum_tg_init);
90 module_exit(checksum_tg_exit);
91