mm: create the new vm_fault_t type
[linux-2.6-microblaze.git] / net / netfilter / xt_CHECKSUM.c
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
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
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
79 static int __init checksum_tg_init(void)
80 {
81         return xt_register_target(&checksum_tg_reg);
82 }
83
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);