Blame view
net/netfilter/xt_TCPOPTSTRIP.c
3.77 KB
d2912cb15
|
1 |
// SPDX-License-Identifier: GPL-2.0-only |
338e8a792
|
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
|
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
|
30 |
const struct xt_action_param *par, |
fb2eb1c13
|
31 |
unsigned int tcphoff) |
338e8a792
|
32 |
{ |
bc6bcb59d
|
33 |
const struct xt_tcpoptstrip_target_info *info = par->targinfo; |
fb2eb1c13
|
34 |
struct tcphdr *tcph, _th; |
338e8a792
|
35 |
unsigned int optl, i, j; |
338e8a792
|
36 37 |
u_int16_t n, o; u_int8_t *opt; |
fb2eb1c13
|
38 |
int tcp_hdrlen; |
bc6bcb59d
|
39 40 41 42 |
/* This is a fragment, no TCP header is available */ if (par->fragoff != 0) return XT_CONTINUE; |
338e8a792
|
43 |
|
fb2eb1c13
|
44 45 |
tcph = skb_header_pointer(skb, tcphoff, sizeof(_th), &_th); if (!tcph) |
338e8a792
|
46 |
return NF_DROP; |
a206bcb3b
|
47 |
tcp_hdrlen = tcph->doff * 4; |
fb2eb1c13
|
48 49 |
if (tcp_hdrlen < sizeof(struct tcphdr)) return NF_DROP; |
a206bcb3b
|
50 |
|
fb2eb1c13
|
51 |
if (skb_ensure_writable(skb, tcphoff + tcp_hdrlen)) |
ed82c4373
|
52 |
return NF_DROP; |
fb2eb1c13
|
53 54 55 |
/* must reload tcph, might have been moved */ tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff); opt = (u8 *)tcph; |
338e8a792
|
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
|
61 |
for (i = sizeof(struct tcphdr); i < tcp_hdrlen - 1; i += optl) { |
338e8a792
|
62 |
optl = optlen(opt, i); |
a206bcb3b
|
63 |
if (i + optl > tcp_hdrlen) |
338e8a792
|
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
|
77 |
htons(n), false); |
338e8a792
|
78 79 80 81 82 83 84 85 |
} memset(opt + i, TCPOPT_NOP, optl); } return XT_CONTINUE; } static unsigned int |
4b560b447
|
86 |
tcpoptstrip_tg4(struct sk_buff *skb, const struct xt_action_param *par) |
338e8a792
|
87 |
{ |
fb2eb1c13
|
88 |
return tcpoptstrip_mangle_packet(skb, par, ip_hdrlen(skb)); |
338e8a792
|
89 |
} |
c0cd11566
|
90 |
#if IS_ENABLED(CONFIG_IP6_NF_MANGLE) |
338e8a792
|
91 |
static unsigned int |
4b560b447
|
92 |
tcpoptstrip_tg6(struct sk_buff *skb, const struct xt_action_param *par) |
338e8a792
|
93 94 |
{ struct ipv6hdr *ipv6h = ipv6_hdr(skb); |
be8d0d790
|
95 |
int tcphoff; |
338e8a792
|
96 |
u_int8_t nexthdr; |
75f2811c6
|
97 |
__be16 frag_off; |
338e8a792
|
98 99 |
nexthdr = ipv6h->nexthdr; |
75f2811c6
|
100 |
tcphoff = ipv6_skip_exthdr(skb, sizeof(*ipv6h), &nexthdr, &frag_off); |
338e8a792
|
101 102 |
if (tcphoff < 0) return NF_DROP; |
fb2eb1c13
|
103 |
return tcpoptstrip_mangle_packet(skb, par, tcphoff); |
338e8a792
|
104 105 106 107 108 109 |
} #endif static struct xt_target tcpoptstrip_tg_reg[] __read_mostly = { { .name = "TCPOPTSTRIP", |
ee999d8b9
|
110 |
.family = NFPROTO_IPV4, |
338e8a792
|
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
|
117 |
#if IS_ENABLED(CONFIG_IP6_NF_MANGLE) |
338e8a792
|
118 119 |
{ .name = "TCPOPTSTRIP", |
ee999d8b9
|
120 |
.family = NFPROTO_IPV6, |
338e8a792
|
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
|
144 |
MODULE_AUTHOR("Sven Schnelle <svens@bitebene.org>, Jan Engelhardt <jengelh@medozas.de>"); |
2ae15b64e
|
145 |
MODULE_DESCRIPTION("Xtables: TCP option stripping"); |
338e8a792
|
146 147 148 |
MODULE_LICENSE("GPL"); MODULE_ALIAS("ipt_TCPOPTSTRIP"); MODULE_ALIAS("ip6t_TCPOPTSTRIP"); |