Blame view

net/netfilter/xt_TCPOPTSTRIP.c 3.77 KB
d2912cb15   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
338e8a792   Sven Schnelle   [NETFILTER]: x_ta...
2
3
4
5
6
  /*
   * A module for stripping a specific TCP option from TCP packets.
   *
   * Copyright (C) 2007 Sven Schnelle <svens@bitebene.org>
   * Copyright © CC Computer Consultants GmbH, 2007
338e8a792   Sven Schnelle   [NETFILTER]: x_ta...
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
   */
  
  #include <linux/module.h>
  #include <linux/skbuff.h>
  #include <linux/ip.h>
  #include <linux/ipv6.h>
  #include <linux/tcp.h>
  #include <net/ipv6.h>
  #include <net/tcp.h>
  #include <linux/netfilter/x_tables.h>
  #include <linux/netfilter/xt_TCPOPTSTRIP.h>
  
  static inline unsigned int optlen(const u_int8_t *opt, unsigned int offset)
  {
  	/* Beware zero-length options: make finite progress */
  	if (opt[offset] <= TCPOPT_NOP || opt[offset+1] == 0)
  		return 1;
  	else
  		return opt[offset+1];
  }
  
  static unsigned int
  tcpoptstrip_mangle_packet(struct sk_buff *skb,
bc6bcb59d   Pablo Neira Ayuso   netfilter: xt_TCP...
30
  			  const struct xt_action_param *par,
fb2eb1c13   Florian Westphal   netfilter: tcpmss...
31
  			  unsigned int tcphoff)
338e8a792   Sven Schnelle   [NETFILTER]: x_ta...
32
  {
bc6bcb59d   Pablo Neira Ayuso   netfilter: xt_TCP...
33
  	const struct xt_tcpoptstrip_target_info *info = par->targinfo;
fb2eb1c13   Florian Westphal   netfilter: tcpmss...
34
  	struct tcphdr *tcph, _th;
338e8a792   Sven Schnelle   [NETFILTER]: x_ta...
35
  	unsigned int optl, i, j;
338e8a792   Sven Schnelle   [NETFILTER]: x_ta...
36
37
  	u_int16_t n, o;
  	u_int8_t *opt;
fb2eb1c13   Florian Westphal   netfilter: tcpmss...
38
  	int tcp_hdrlen;
bc6bcb59d   Pablo Neira Ayuso   netfilter: xt_TCP...
39
40
41
42
  
  	/* This is a fragment, no TCP header is available */
  	if (par->fragoff != 0)
  		return XT_CONTINUE;
338e8a792   Sven Schnelle   [NETFILTER]: x_ta...
43

fb2eb1c13   Florian Westphal   netfilter: tcpmss...
44
45
  	tcph = skb_header_pointer(skb, tcphoff, sizeof(_th), &_th);
  	if (!tcph)
338e8a792   Sven Schnelle   [NETFILTER]: x_ta...
46
  		return NF_DROP;
a206bcb3b   Pablo Neira Ayuso   netfilter: xt_TCP...
47
  	tcp_hdrlen = tcph->doff * 4;
fb2eb1c13   Florian Westphal   netfilter: tcpmss...
48
49
  	if (tcp_hdrlen < sizeof(struct tcphdr))
  		return NF_DROP;
a206bcb3b   Pablo Neira Ayuso   netfilter: xt_TCP...
50

fb2eb1c13   Florian Westphal   netfilter: tcpmss...
51
  	if (skb_ensure_writable(skb, tcphoff + tcp_hdrlen))
ed82c4373   Pablo Neira Ayuso   netfilter: xt_TCP...
52
  		return NF_DROP;
fb2eb1c13   Florian Westphal   netfilter: tcpmss...
53
54
55
  	/* must reload tcph, might have been moved */
  	tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff);
  	opt  = (u8 *)tcph;
338e8a792   Sven Schnelle   [NETFILTER]: x_ta...
56
57
58
59
60
  
  	/*
  	 * Walk through all TCP options - if we find some option to remove,
  	 * set all octets to %TCPOPT_NOP and adjust checksum.
  	 */
a206bcb3b   Pablo Neira Ayuso   netfilter: xt_TCP...
61
  	for (i = sizeof(struct tcphdr); i < tcp_hdrlen - 1; i += optl) {
338e8a792   Sven Schnelle   [NETFILTER]: x_ta...
62
  		optl = optlen(opt, i);
a206bcb3b   Pablo Neira Ayuso   netfilter: xt_TCP...
63
  		if (i + optl > tcp_hdrlen)
338e8a792   Sven Schnelle   [NETFILTER]: x_ta...
64
65
66
67
68
69
70
71
72
73
74
75
76
  			break;
  
  		if (!tcpoptstrip_test_bit(info->strip_bmap, opt[i]))
  			continue;
  
  		for (j = 0; j < optl; ++j) {
  			o = opt[i+j];
  			n = TCPOPT_NOP;
  			if ((i + j) % 2 == 0) {
  				o <<= 8;
  				n <<= 8;
  			}
  			inet_proto_csum_replace2(&tcph->check, skb, htons(o),
4b048d6d9   Tom Herbert   net: Change pseud...
77
  						 htons(n), false);
338e8a792   Sven Schnelle   [NETFILTER]: x_ta...
78
79
80
81
82
83
84
85
  		}
  		memset(opt + i, TCPOPT_NOP, optl);
  	}
  
  	return XT_CONTINUE;
  }
  
  static unsigned int
4b560b447   Jan Engelhardt   netfilter: xtable...
86
  tcpoptstrip_tg4(struct sk_buff *skb, const struct xt_action_param *par)
338e8a792   Sven Schnelle   [NETFILTER]: x_ta...
87
  {
fb2eb1c13   Florian Westphal   netfilter: tcpmss...
88
  	return tcpoptstrip_mangle_packet(skb, par, ip_hdrlen(skb));
338e8a792   Sven Schnelle   [NETFILTER]: x_ta...
89
  }
c0cd11566   Igor Maravić   net:netfilter: us...
90
  #if IS_ENABLED(CONFIG_IP6_NF_MANGLE)
338e8a792   Sven Schnelle   [NETFILTER]: x_ta...
91
  static unsigned int
4b560b447   Jan Engelhardt   netfilter: xtable...
92
  tcpoptstrip_tg6(struct sk_buff *skb, const struct xt_action_param *par)
338e8a792   Sven Schnelle   [NETFILTER]: x_ta...
93
94
  {
  	struct ipv6hdr *ipv6h = ipv6_hdr(skb);
be8d0d790   Roel Kluin   netfilter: xt_TCP...
95
  	int tcphoff;
338e8a792   Sven Schnelle   [NETFILTER]: x_ta...
96
  	u_int8_t nexthdr;
75f2811c6   Jesse Gross   ipv6: Add fragmen...
97
  	__be16 frag_off;
338e8a792   Sven Schnelle   [NETFILTER]: x_ta...
98
99
  
  	nexthdr = ipv6h->nexthdr;
75f2811c6   Jesse Gross   ipv6: Add fragmen...
100
  	tcphoff = ipv6_skip_exthdr(skb, sizeof(*ipv6h), &nexthdr, &frag_off);
338e8a792   Sven Schnelle   [NETFILTER]: x_ta...
101
102
  	if (tcphoff < 0)
  		return NF_DROP;
fb2eb1c13   Florian Westphal   netfilter: tcpmss...
103
  	return tcpoptstrip_mangle_packet(skb, par, tcphoff);
338e8a792   Sven Schnelle   [NETFILTER]: x_ta...
104
105
106
107
108
109
  }
  #endif
  
  static struct xt_target tcpoptstrip_tg_reg[] __read_mostly = {
  	{
  		.name       = "TCPOPTSTRIP",
ee999d8b9   Jan Engelhardt   netfilter: x_tabl...
110
  		.family     = NFPROTO_IPV4,
338e8a792   Sven Schnelle   [NETFILTER]: x_ta...
111
112
113
114
115
116
  		.table      = "mangle",
  		.proto      = IPPROTO_TCP,
  		.target     = tcpoptstrip_tg4,
  		.targetsize = sizeof(struct xt_tcpoptstrip_target_info),
  		.me         = THIS_MODULE,
  	},
c0cd11566   Igor Maravić   net:netfilter: us...
117
  #if IS_ENABLED(CONFIG_IP6_NF_MANGLE)
338e8a792   Sven Schnelle   [NETFILTER]: x_ta...
118
119
  	{
  		.name       = "TCPOPTSTRIP",
ee999d8b9   Jan Engelhardt   netfilter: x_tabl...
120
  		.family     = NFPROTO_IPV6,
338e8a792   Sven Schnelle   [NETFILTER]: x_ta...
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
  		.table      = "mangle",
  		.proto      = IPPROTO_TCP,
  		.target     = tcpoptstrip_tg6,
  		.targetsize = sizeof(struct xt_tcpoptstrip_target_info),
  		.me         = THIS_MODULE,
  	},
  #endif
  };
  
  static int __init tcpoptstrip_tg_init(void)
  {
  	return xt_register_targets(tcpoptstrip_tg_reg,
  				   ARRAY_SIZE(tcpoptstrip_tg_reg));
  }
  
  static void __exit tcpoptstrip_tg_exit(void)
  {
  	xt_unregister_targets(tcpoptstrip_tg_reg,
  			      ARRAY_SIZE(tcpoptstrip_tg_reg));
  }
  
  module_init(tcpoptstrip_tg_init);
  module_exit(tcpoptstrip_tg_exit);
408ffaa4a   Jan Engelhardt   netfilter: update...
144
  MODULE_AUTHOR("Sven Schnelle <svens@bitebene.org>, Jan Engelhardt <jengelh@medozas.de>");
2ae15b64e   Jan Engelhardt   [NETFILTER]: Upda...
145
  MODULE_DESCRIPTION("Xtables: TCP option stripping");
338e8a792   Sven Schnelle   [NETFILTER]: x_ta...
146
147
148
  MODULE_LICENSE("GPL");
  MODULE_ALIAS("ipt_TCPOPTSTRIP");
  MODULE_ALIAS("ip6t_TCPOPTSTRIP");