blob: c8a639f561684107cdab4332b6c3aff30e81fdb1 [file] [log] [blame]
Thomas Gleixnerd2912cb2019-06-04 10:11:33 +02001// SPDX-License-Identifier: GPL-2.0-only
Michael S. Tsirkinedf0e1f2010-07-15 17:20:46 +02002/* iptables module for the packet checksum mangling
3 *
4 * (C) 2002 by Harald Welte <laforge@netfilter.org>
5 * (C) 2010 Red Hat, Inc.
6 *
7 * Author: Michael S. Tsirkin <mst@redhat.com>
Michael S. Tsirkinedf0e1f2010-07-15 17:20:46 +02008*/
9#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
10#include <linux/module.h>
11#include <linux/skbuff.h>
12
13#include <linux/netfilter/x_tables.h>
14#include <linux/netfilter/xt_CHECKSUM.h>
15
Florian Westphal10568f62018-08-22 11:33:27 +020016#include <linux/netfilter_ipv4/ip_tables.h>
17#include <linux/netfilter_ipv6/ip6_tables.h>
18
Michael S. Tsirkinedf0e1f2010-07-15 17:20:46 +020019MODULE_LICENSE("GPL");
20MODULE_AUTHOR("Michael S. Tsirkin <mst@redhat.com>");
21MODULE_DESCRIPTION("Xtables: checksum modification");
22MODULE_ALIAS("ipt_CHECKSUM");
23MODULE_ALIAS("ip6t_CHECKSUM");
24
25static unsigned int
26checksum_tg(struct sk_buff *skb, const struct xt_action_param *par)
27{
Florian Westphal10568f62018-08-22 11:33:27 +020028 if (skb->ip_summed == CHECKSUM_PARTIAL && !skb_is_gso(skb))
Michael S. Tsirkinedf0e1f2010-07-15 17:20:46 +020029 skb_checksum_help(skb);
30
31 return XT_CONTINUE;
32}
33
34static int checksum_tg_check(const struct xt_tgchk_param *par)
35{
36 const struct xt_CHECKSUM_info *einfo = par->targinfo;
Florian Westphal10568f62018-08-22 11:33:27 +020037 const struct ip6t_ip6 *i6 = par->entryinfo;
38 const struct ipt_ip *i4 = par->entryinfo;
Michael S. Tsirkinedf0e1f2010-07-15 17:20:46 +020039
40 if (einfo->operation & ~XT_CHECKSUM_OP_FILL) {
Florian Westphalb2606642018-02-09 15:52:07 +010041 pr_info_ratelimited("unsupported CHECKSUM operation %x\n",
42 einfo->operation);
Michael S. Tsirkinedf0e1f2010-07-15 17:20:46 +020043 return -EINVAL;
44 }
Florian Westphal0cc95012018-02-09 15:51:59 +010045 if (!einfo->operation)
Michael S. Tsirkinedf0e1f2010-07-15 17:20:46 +020046 return -EINVAL;
Florian Westphal0cc95012018-02-09 15:51:59 +010047
Florian Westphal10568f62018-08-22 11:33:27 +020048 switch (par->family) {
49 case NFPROTO_IPV4:
50 if (i4->proto == IPPROTO_UDP &&
51 (i4->invflags & XT_INV_PROTO) == 0)
52 return 0;
53 break;
54 case NFPROTO_IPV6:
55 if ((i6->flags & IP6T_F_PROTO) &&
56 i6->proto == IPPROTO_UDP &&
57 (i6->invflags & XT_INV_PROTO) == 0)
58 return 0;
59 break;
60 }
61
62 pr_warn_once("CHECKSUM should be avoided. If really needed, restrict with \"-p udp\" and only use in OUTPUT\n");
Michael S. Tsirkinedf0e1f2010-07-15 17:20:46 +020063 return 0;
64}
65
66static struct xt_target checksum_tg_reg __read_mostly = {
67 .name = "CHECKSUM",
68 .family = NFPROTO_UNSPEC,
69 .target = checksum_tg,
70 .targetsize = sizeof(struct xt_CHECKSUM_info),
71 .table = "mangle",
72 .checkentry = checksum_tg_check,
73 .me = THIS_MODULE,
74};
75
76static int __init checksum_tg_init(void)
77{
78 return xt_register_target(&checksum_tg_reg);
79}
80
81static void __exit checksum_tg_exit(void)
82{
83 xt_unregister_target(&checksum_tg_reg);
84}
85
86module_init(checksum_tg_init);
87module_exit(checksum_tg_exit);