1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 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> 8 */ 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 16 #include <linux/netfilter_ipv4/ip_tables.h> 17 #include <linux/netfilter_ipv6/ip6_tables.h> 18 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"); 24 25 static unsigned int checksum_tg(struct sk_buff * skb,const struct xt_action_param * par)26 checksum_tg(struct sk_buff *skb, const struct xt_action_param *par) 27 { 28 if (skb->ip_summed == CHECKSUM_PARTIAL && !skb_is_gso(skb)) 29 skb_checksum_help(skb); 30 31 return XT_CONTINUE; 32 } 33 checksum_tg_check(const struct xt_tgchk_param * par)34 static int checksum_tg_check(const struct xt_tgchk_param *par) 35 { 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; 39 40 if (einfo->operation & ~XT_CHECKSUM_OP_FILL) { 41 pr_info_ratelimited("unsupported CHECKSUM operation %x\n", 42 einfo->operation); 43 return -EINVAL; 44 } 45 if (!einfo->operation) 46 return -EINVAL; 47 48 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"); 63 return 0; 64 } 65 66 static struct xt_target checksum_tg_reg[] __read_mostly = { 67 { 68 .name = "CHECKSUM", 69 .family = NFPROTO_IPV4, 70 .target = checksum_tg, 71 .targetsize = sizeof(struct xt_CHECKSUM_info), 72 .table = "mangle", 73 .checkentry = checksum_tg_check, 74 .me = THIS_MODULE, 75 }, 76 #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) 77 { 78 .name = "CHECKSUM", 79 .family = NFPROTO_IPV6, 80 .target = checksum_tg, 81 .targetsize = sizeof(struct xt_CHECKSUM_info), 82 .table = "mangle", 83 .checkentry = checksum_tg_check, 84 .me = THIS_MODULE, 85 }, 86 #endif 87 }; 88 checksum_tg_init(void)89 static int __init checksum_tg_init(void) 90 { 91 return xt_register_targets(checksum_tg_reg, ARRAY_SIZE(checksum_tg_reg)); 92 } 93 checksum_tg_exit(void)94 static void __exit checksum_tg_exit(void) 95 { 96 xt_unregister_targets(checksum_tg_reg, ARRAY_SIZE(checksum_tg_reg)); 97 } 98 99 module_init(checksum_tg_init); 100 module_exit(checksum_tg_exit); 101