Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /* iptables module for the packet checksum mangling
0003  *
0004  * (C) 2002 by Harald Welte <laforge@netfilter.org>
0005  * (C) 2010 Red Hat, Inc.
0006  *
0007  * Author: Michael S. Tsirkin <mst@redhat.com>
0008 */
0009 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0010 #include <linux/module.h>
0011 #include <linux/skbuff.h>
0012 
0013 #include <linux/netfilter/x_tables.h>
0014 #include <linux/netfilter/xt_CHECKSUM.h>
0015 
0016 #include <linux/netfilter_ipv4/ip_tables.h>
0017 #include <linux/netfilter_ipv6/ip6_tables.h>
0018 
0019 MODULE_LICENSE("GPL");
0020 MODULE_AUTHOR("Michael S. Tsirkin <mst@redhat.com>");
0021 MODULE_DESCRIPTION("Xtables: checksum modification");
0022 MODULE_ALIAS("ipt_CHECKSUM");
0023 MODULE_ALIAS("ip6t_CHECKSUM");
0024 
0025 static unsigned int
0026 checksum_tg(struct sk_buff *skb, const struct xt_action_param *par)
0027 {
0028     if (skb->ip_summed == CHECKSUM_PARTIAL && !skb_is_gso(skb))
0029         skb_checksum_help(skb);
0030 
0031     return XT_CONTINUE;
0032 }
0033 
0034 static int checksum_tg_check(const struct xt_tgchk_param *par)
0035 {
0036     const struct xt_CHECKSUM_info *einfo = par->targinfo;
0037     const struct ip6t_ip6 *i6 = par->entryinfo;
0038     const struct ipt_ip *i4 = par->entryinfo;
0039 
0040     if (einfo->operation & ~XT_CHECKSUM_OP_FILL) {
0041         pr_info_ratelimited("unsupported CHECKSUM operation %x\n",
0042                     einfo->operation);
0043         return -EINVAL;
0044     }
0045     if (!einfo->operation)
0046         return -EINVAL;
0047 
0048     switch (par->family) {
0049     case NFPROTO_IPV4:
0050         if (i4->proto == IPPROTO_UDP &&
0051             (i4->invflags & XT_INV_PROTO) == 0)
0052             return 0;
0053         break;
0054     case NFPROTO_IPV6:
0055         if ((i6->flags & IP6T_F_PROTO) &&
0056             i6->proto == IPPROTO_UDP &&
0057             (i6->invflags & XT_INV_PROTO) == 0)
0058             return 0;
0059         break;
0060     }
0061 
0062     pr_warn_once("CHECKSUM should be avoided.  If really needed, restrict with \"-p udp\" and only use in OUTPUT\n");
0063     return 0;
0064 }
0065 
0066 static struct xt_target checksum_tg_reg __read_mostly = {
0067     .name       = "CHECKSUM",
0068     .family     = NFPROTO_UNSPEC,
0069     .target     = checksum_tg,
0070     .targetsize = sizeof(struct xt_CHECKSUM_info),
0071     .table      = "mangle",
0072     .checkentry = checksum_tg_check,
0073     .me     = THIS_MODULE,
0074 };
0075 
0076 static int __init checksum_tg_init(void)
0077 {
0078     return xt_register_target(&checksum_tg_reg);
0079 }
0080 
0081 static void __exit checksum_tg_exit(void)
0082 {
0083     xt_unregister_target(&checksum_tg_reg);
0084 }
0085 
0086 module_init(checksum_tg_init);
0087 module_exit(checksum_tg_exit);