~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/netfilter/xt_TCPOPTSTRIP.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-only
  2 /*
  3  * A module for stripping a specific TCP option from TCP packets.
  4  *
  5  * Copyright (C) 2007 Sven Schnelle <svens@bitebene.org>
  6  * Copyright © CC Computer Consultants GmbH, 2007
  7  */
  8 
  9 #include <linux/module.h>
 10 #include <linux/skbuff.h>
 11 #include <linux/ip.h>
 12 #include <linux/ipv6.h>
 13 #include <linux/tcp.h>
 14 #include <net/ipv6.h>
 15 #include <net/tcp.h>
 16 #include <linux/netfilter/x_tables.h>
 17 #include <linux/netfilter/xt_TCPOPTSTRIP.h>
 18 
 19 static inline unsigned int optlen(const u_int8_t *opt, unsigned int offset)
 20 {
 21         /* Beware zero-length options: make finite progress */
 22         if (opt[offset] <= TCPOPT_NOP || opt[offset+1] == 0)
 23                 return 1;
 24         else
 25                 return opt[offset+1];
 26 }
 27 
 28 static unsigned int
 29 tcpoptstrip_mangle_packet(struct sk_buff *skb,
 30                           const struct xt_action_param *par,
 31                           unsigned int tcphoff)
 32 {
 33         const struct xt_tcpoptstrip_target_info *info = par->targinfo;
 34         struct tcphdr *tcph, _th;
 35         unsigned int optl, i, j;
 36         u_int16_t n, o;
 37         u_int8_t *opt;
 38         int tcp_hdrlen;
 39 
 40         /* This is a fragment, no TCP header is available */
 41         if (par->fragoff != 0)
 42                 return XT_CONTINUE;
 43 
 44         tcph = skb_header_pointer(skb, tcphoff, sizeof(_th), &_th);
 45         if (!tcph)
 46                 return NF_DROP;
 47 
 48         tcp_hdrlen = tcph->doff * 4;
 49         if (tcp_hdrlen < sizeof(struct tcphdr))
 50                 return NF_DROP;
 51 
 52         if (skb_ensure_writable(skb, tcphoff + tcp_hdrlen))
 53                 return NF_DROP;
 54 
 55         /* must reload tcph, might have been moved */
 56         tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff);
 57         opt  = (u8 *)tcph;
 58 
 59         /*
 60          * Walk through all TCP options - if we find some option to remove,
 61          * set all octets to %TCPOPT_NOP and adjust checksum.
 62          */
 63         for (i = sizeof(struct tcphdr); i < tcp_hdrlen - 1; i += optl) {
 64                 optl = optlen(opt, i);
 65 
 66                 if (i + optl > tcp_hdrlen)
 67                         break;
 68 
 69                 if (!tcpoptstrip_test_bit(info->strip_bmap, opt[i]))
 70                         continue;
 71 
 72                 for (j = 0; j < optl; ++j) {
 73                         o = opt[i+j];
 74                         n = TCPOPT_NOP;
 75                         if ((i + j) % 2 == 0) {
 76                                 o <<= 8;
 77                                 n <<= 8;
 78                         }
 79                         inet_proto_csum_replace2(&tcph->check, skb, htons(o),
 80                                                  htons(n), false);
 81                 }
 82                 memset(opt + i, TCPOPT_NOP, optl);
 83         }
 84 
 85         return XT_CONTINUE;
 86 }
 87 
 88 static unsigned int
 89 tcpoptstrip_tg4(struct sk_buff *skb, const struct xt_action_param *par)
 90 {
 91         return tcpoptstrip_mangle_packet(skb, par, ip_hdrlen(skb));
 92 }
 93 
 94 #if IS_ENABLED(CONFIG_IP6_NF_MANGLE)
 95 static unsigned int
 96 tcpoptstrip_tg6(struct sk_buff *skb, const struct xt_action_param *par)
 97 {
 98         struct ipv6hdr *ipv6h = ipv6_hdr(skb);
 99         int tcphoff;
100         u_int8_t nexthdr;
101         __be16 frag_off;
102 
103         nexthdr = ipv6h->nexthdr;
104         tcphoff = ipv6_skip_exthdr(skb, sizeof(*ipv6h), &nexthdr, &frag_off);
105         if (tcphoff < 0)
106                 return NF_DROP;
107 
108         return tcpoptstrip_mangle_packet(skb, par, tcphoff);
109 }
110 #endif
111 
112 static struct xt_target tcpoptstrip_tg_reg[] __read_mostly = {
113         {
114                 .name       = "TCPOPTSTRIP",
115                 .family     = NFPROTO_IPV4,
116                 .table      = "mangle",
117                 .proto      = IPPROTO_TCP,
118                 .target     = tcpoptstrip_tg4,
119                 .targetsize = sizeof(struct xt_tcpoptstrip_target_info),
120                 .me         = THIS_MODULE,
121         },
122 #if IS_ENABLED(CONFIG_IP6_NF_MANGLE)
123         {
124                 .name       = "TCPOPTSTRIP",
125                 .family     = NFPROTO_IPV6,
126                 .table      = "mangle",
127                 .proto      = IPPROTO_TCP,
128                 .target     = tcpoptstrip_tg6,
129                 .targetsize = sizeof(struct xt_tcpoptstrip_target_info),
130                 .me         = THIS_MODULE,
131         },
132 #endif
133 };
134 
135 static int __init tcpoptstrip_tg_init(void)
136 {
137         return xt_register_targets(tcpoptstrip_tg_reg,
138                                    ARRAY_SIZE(tcpoptstrip_tg_reg));
139 }
140 
141 static void __exit tcpoptstrip_tg_exit(void)
142 {
143         xt_unregister_targets(tcpoptstrip_tg_reg,
144                               ARRAY_SIZE(tcpoptstrip_tg_reg));
145 }
146 
147 module_init(tcpoptstrip_tg_init);
148 module_exit(tcpoptstrip_tg_exit);
149 MODULE_AUTHOR("Sven Schnelle <svens@bitebene.org>, Jan Engelhardt <jengelh@medozas.de>");
150 MODULE_DESCRIPTION("Xtables: TCP option stripping");
151 MODULE_LICENSE("GPL");
152 MODULE_ALIAS("ipt_TCPOPTSTRIP");
153 MODULE_ALIAS("ip6t_TCPOPTSTRIP");
154 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php