blob: cd24290f3b2fdbff20088a0ffd2692fb6240a9ce [file] [log] [blame]
Patrick McHardycdd289a2007-02-07 15:09:46 -08001/*
2 * This is a module which is used for setting the MSS option in TCP packets.
3 *
4 * Copyright (C) 2000 Marc Boucher <marc@mbsi.ca>
Patrick McHardyf229f6c2013-04-06 15:24:29 +02005 * Copyright (C) 2007 Patrick McHardy <kaber@trash.net>
Patrick McHardycdd289a2007-02-07 15:09:46 -08006 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
Jan Engelhardt8bee4ba2010-03-17 16:04:40 +010011#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
Patrick McHardycdd289a2007-02-07 15:09:46 -080012#include <linux/module.h>
13#include <linux/skbuff.h>
14#include <linux/ip.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090015#include <linux/gfp.h>
Patrick McHardycdd289a2007-02-07 15:09:46 -080016#include <linux/ipv6.h>
17#include <linux/tcp.h>
Jan Engelhardt37c08382008-01-31 04:06:10 -080018#include <net/dst.h>
19#include <net/flow.h>
Patrick McHardycdd289a2007-02-07 15:09:46 -080020#include <net/ipv6.h>
Jan Engelhardt37c08382008-01-31 04:06:10 -080021#include <net/route.h>
Patrick McHardycdd289a2007-02-07 15:09:46 -080022#include <net/tcp.h>
23
24#include <linux/netfilter_ipv4/ip_tables.h>
25#include <linux/netfilter_ipv6/ip6_tables.h>
26#include <linux/netfilter/x_tables.h>
27#include <linux/netfilter/xt_tcpudp.h>
28#include <linux/netfilter/xt_TCPMSS.h>
29
30MODULE_LICENSE("GPL");
31MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
Jan Engelhardt2ae15b62008-01-14 23:42:28 -080032MODULE_DESCRIPTION("Xtables: TCP Maximum Segment Size (MSS) adjustment");
Patrick McHardycdd289a2007-02-07 15:09:46 -080033MODULE_ALIAS("ipt_TCPMSS");
34MODULE_ALIAS("ip6t_TCPMSS");
35
36static inline unsigned int
37optlen(const u_int8_t *opt, unsigned int offset)
38{
39 /* Beware zero-length options: make finite progress */
40 if (opt[offset] <= TCPOPT_NOP || opt[offset+1] == 0)
41 return 1;
42 else
43 return opt[offset+1];
44}
45
46static int
Herbert Xu3db05fe2007-10-15 00:53:15 -070047tcpmss_mangle_packet(struct sk_buff *skb,
Phil Oester70d19f82013-06-12 10:44:51 +020048 const struct xt_action_param *par,
Jan Engelhardt37c08382008-01-31 04:06:10 -080049 unsigned int in_mtu,
Patrick McHardycdd289a2007-02-07 15:09:46 -080050 unsigned int tcphoff,
51 unsigned int minlen)
52{
Phil Oester70d19f82013-06-12 10:44:51 +020053 const struct xt_tcpmss_info *info = par->targinfo;
Patrick McHardycdd289a2007-02-07 15:09:46 -080054 struct tcphdr *tcph;
Pablo Neira Ayuso71ffe9c2013-07-25 10:37:49 +020055 int len, tcp_hdrlen;
56 unsigned int i;
Patrick McHardycdd289a2007-02-07 15:09:46 -080057 __be16 oldval;
58 u16 newmss;
59 u8 *opt;
60
Phil Oesterb3969662013-06-12 10:58:20 +020061 /* This is a fragment, no TCP header is available */
62 if (par->fragoff != 0)
Phil Oester1205e1f2013-09-01 08:32:21 -070063 return 0;
Phil Oesterb3969662013-06-12 10:58:20 +020064
Herbert Xu3db05fe2007-10-15 00:53:15 -070065 if (!skb_make_writable(skb, skb->len))
Patrick McHardycdd289a2007-02-07 15:09:46 -080066 return -1;
67
Pablo Neira Ayuso71ffe9c2013-07-25 10:37:49 +020068 len = skb->len - tcphoff;
69 if (len < (int)sizeof(struct tcphdr))
70 return -1;
Patrick McHardycdd289a2007-02-07 15:09:46 -080071
Pablo Neira Ayuso71ffe9c2013-07-25 10:37:49 +020072 tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff);
73 tcp_hdrlen = tcph->doff * 4;
74
75 if (len < tcp_hdrlen)
Patrick McHardycdd289a2007-02-07 15:09:46 -080076 return -1;
Patrick McHardycdd289a2007-02-07 15:09:46 -080077
78 if (info->mss == XT_TCPMSS_CLAMP_PMTU) {
Eric Dumazetadf30902009-06-02 05:19:30 +000079 if (dst_mtu(skb_dst(skb)) <= minlen) {
Joe Perchese87cc472012-05-13 21:56:26 +000080 net_err_ratelimited("unknown or invalid path-MTU (%u)\n",
81 dst_mtu(skb_dst(skb)));
Patrick McHardycdd289a2007-02-07 15:09:46 -080082 return -1;
83 }
Jan Engelhardt37c08382008-01-31 04:06:10 -080084 if (in_mtu <= minlen) {
Joe Perchese87cc472012-05-13 21:56:26 +000085 net_err_ratelimited("unknown or invalid path-MTU (%u)\n",
86 in_mtu);
Jan Engelhardt37c08382008-01-31 04:06:10 -080087 return -1;
88 }
Eric Dumazetadf30902009-06-02 05:19:30 +000089 newmss = min(dst_mtu(skb_dst(skb)), in_mtu) - minlen;
Patrick McHardycdd289a2007-02-07 15:09:46 -080090 } else
91 newmss = info->mss;
92
93 opt = (u_int8_t *)tcph;
Pablo Neira Ayuso71ffe9c2013-07-25 10:37:49 +020094 for (i = sizeof(struct tcphdr); i <= tcp_hdrlen - TCPOLEN_MSS; i += optlen(opt, i)) {
95 if (opt[i] == TCPOPT_MSS && opt[i+1] == TCPOLEN_MSS) {
Patrick McHardycdd289a2007-02-07 15:09:46 -080096 u_int16_t oldmss;
97
98 oldmss = (opt[i+2] << 8) | opt[i+3];
99
Benjamin LaHaise17008062007-12-17 22:27:36 -0800100 /* Never increase MSS, even when setting it, as
101 * doing so results in problems for hosts that rely
102 * on MSS being set correctly.
103 */
104 if (oldmss <= newmss)
Patrick McHardycdd289a2007-02-07 15:09:46 -0800105 return 0;
106
107 opt[i+2] = (newmss & 0xff00) >> 8;
Jan Engelhardt7c4e36b2007-07-07 22:19:08 -0700108 opt[i+3] = newmss & 0x00ff;
Patrick McHardycdd289a2007-02-07 15:09:46 -0800109
Patrick McHardybe0ea7d2007-11-30 01:17:11 +1100110 inet_proto_csum_replace2(&tcph->check, skb,
111 htons(oldmss), htons(newmss),
112 0);
Patrick McHardycdd289a2007-02-07 15:09:46 -0800113 return 0;
114 }
115 }
116
Simon Arlott10a19932010-02-02 15:33:38 +0100117 /* There is data after the header so the option can't be added
Pablo Neira Ayuso71ffe9c2013-07-25 10:37:49 +0200118 * without moving it, and doing so may make the SYN packet
119 * itself too large. Accept the packet unmodified instead.
120 */
121 if (len > tcp_hdrlen)
Simon Arlott10a19932010-02-02 15:33:38 +0100122 return 0;
123
Patrick McHardycdd289a2007-02-07 15:09:46 -0800124 /*
125 * MSS Option not found ?! add it..
126 */
Herbert Xu3db05fe2007-10-15 00:53:15 -0700127 if (skb_tailroom(skb) < TCPOLEN_MSS) {
128 if (pskb_expand_head(skb, 0,
129 TCPOLEN_MSS - skb_tailroom(skb),
Herbert Xu2ca7b0a2007-10-14 00:39:55 -0700130 GFP_ATOMIC))
Patrick McHardycdd289a2007-02-07 15:09:46 -0800131 return -1;
Herbert Xu3db05fe2007-10-15 00:53:15 -0700132 tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff);
Patrick McHardycdd289a2007-02-07 15:09:46 -0800133 }
134
Herbert Xu3db05fe2007-10-15 00:53:15 -0700135 skb_put(skb, TCPOLEN_MSS);
Patrick McHardycdd289a2007-02-07 15:09:46 -0800136
Phil Oester70d19f82013-06-12 10:44:51 +0200137 /*
138 * IPv4: RFC 1122 states "If an MSS option is not received at
139 * connection setup, TCP MUST assume a default send MSS of 536".
140 * IPv6: RFC 2460 states IPv6 has a minimum MTU of 1280 and a minimum
141 * length IPv6 header of 60, ergo the default MSS value is 1220
142 * Since no MSS was provided, we must use the default values
Phil Oester409b5452013-06-04 05:09:27 +0000143 */
Phil Oester70d19f82013-06-12 10:44:51 +0200144 if (par->family == NFPROTO_IPV4)
145 newmss = min(newmss, (u16)536);
146 else
147 newmss = min(newmss, (u16)1220);
Phil Oester409b5452013-06-04 05:09:27 +0000148
Patrick McHardycdd289a2007-02-07 15:09:46 -0800149 opt = (u_int8_t *)tcph + sizeof(struct tcphdr);
Pablo Neira Ayuso71ffe9c2013-07-25 10:37:49 +0200150 memmove(opt + TCPOLEN_MSS, opt, len - sizeof(struct tcphdr));
Patrick McHardycdd289a2007-02-07 15:09:46 -0800151
Patrick McHardybe0ea7d2007-11-30 01:17:11 +1100152 inet_proto_csum_replace2(&tcph->check, skb,
Pablo Neira Ayuso71ffe9c2013-07-25 10:37:49 +0200153 htons(len), htons(len + TCPOLEN_MSS), 1);
Patrick McHardycdd289a2007-02-07 15:09:46 -0800154 opt[0] = TCPOPT_MSS;
155 opt[1] = TCPOLEN_MSS;
156 opt[2] = (newmss & 0xff00) >> 8;
Jan Engelhardt7c4e36b2007-07-07 22:19:08 -0700157 opt[3] = newmss & 0x00ff;
Patrick McHardycdd289a2007-02-07 15:09:46 -0800158
Patrick McHardybe0ea7d2007-11-30 01:17:11 +1100159 inet_proto_csum_replace4(&tcph->check, skb, 0, *((__be32 *)opt), 0);
Patrick McHardycdd289a2007-02-07 15:09:46 -0800160
161 oldval = ((__be16 *)tcph)[6];
162 tcph->doff += TCPOLEN_MSS/4;
Patrick McHardybe0ea7d2007-11-30 01:17:11 +1100163 inet_proto_csum_replace2(&tcph->check, skb,
164 oldval, ((__be16 *)tcph)[6], 0);
Patrick McHardycdd289a2007-02-07 15:09:46 -0800165 return TCPOLEN_MSS;
166}
167
Jan Engelhardtdb1a75b2008-07-21 10:02:59 -0700168static u_int32_t tcpmss_reverse_mtu(const struct sk_buff *skb,
169 unsigned int family)
Jan Engelhardt37c08382008-01-31 04:06:10 -0800170{
David S. Millera1bbb0e2011-03-12 02:16:48 -0500171 struct flowi fl;
Jan Engelhardt37c08382008-01-31 04:06:10 -0800172 const struct nf_afinfo *ai;
173 struct rtable *rt = NULL;
174 u_int32_t mtu = ~0U;
175
David S. Millera1bbb0e2011-03-12 02:16:48 -0500176 if (family == PF_INET) {
177 struct flowi4 *fl4 = &fl.u.ip4;
178 memset(fl4, 0, sizeof(*fl4));
179 fl4->daddr = ip_hdr(skb)->saddr;
180 } else {
181 struct flowi6 *fl6 = &fl.u.ip6;
Jan Engelhardtdb1a75b2008-07-21 10:02:59 -0700182
David S. Millera1bbb0e2011-03-12 02:16:48 -0500183 memset(fl6, 0, sizeof(*fl6));
Alexey Dobriyan4e3fd7a2011-11-21 03:39:03 +0000184 fl6->daddr = ipv6_hdr(skb)->saddr;
David S. Millera1bbb0e2011-03-12 02:16:48 -0500185 }
Jan Engelhardt37c08382008-01-31 04:06:10 -0800186 rcu_read_lock();
Jan Engelhardtdb1a75b2008-07-21 10:02:59 -0700187 ai = nf_get_afinfo(family);
Jan Engelhardt37c08382008-01-31 04:06:10 -0800188 if (ai != NULL)
Florian Westphal0fae2e72011-04-04 17:00:54 +0200189 ai->route(&init_net, (struct dst_entry **)&rt, &fl, false);
Jan Engelhardt37c08382008-01-31 04:06:10 -0800190 rcu_read_unlock();
191
192 if (rt != NULL) {
Changli Gaod8d1f302010-06-10 23:31:35 -0700193 mtu = dst_mtu(&rt->dst);
194 dst_release(&rt->dst);
Jan Engelhardt37c08382008-01-31 04:06:10 -0800195 }
196 return mtu;
197}
198
Patrick McHardycdd289a2007-02-07 15:09:46 -0800199static unsigned int
Jan Engelhardt4b560b42009-07-05 19:43:26 +0200200tcpmss_tg4(struct sk_buff *skb, const struct xt_action_param *par)
Patrick McHardycdd289a2007-02-07 15:09:46 -0800201{
Herbert Xu3db05fe2007-10-15 00:53:15 -0700202 struct iphdr *iph = ip_hdr(skb);
Patrick McHardycdd289a2007-02-07 15:09:46 -0800203 __be16 newlen;
204 int ret;
205
Phil Oester70d19f82013-06-12 10:44:51 +0200206 ret = tcpmss_mangle_packet(skb, par,
Jan Engelhardtdb1a75b2008-07-21 10:02:59 -0700207 tcpmss_reverse_mtu(skb, PF_INET),
Jan Engelhardt37c08382008-01-31 04:06:10 -0800208 iph->ihl * 4,
Patrick McHardycdd289a2007-02-07 15:09:46 -0800209 sizeof(*iph) + sizeof(struct tcphdr));
210 if (ret < 0)
211 return NF_DROP;
212 if (ret > 0) {
Herbert Xu3db05fe2007-10-15 00:53:15 -0700213 iph = ip_hdr(skb);
Patrick McHardycdd289a2007-02-07 15:09:46 -0800214 newlen = htons(ntohs(iph->tot_len) + ret);
Patrick McHardybe0ea7d2007-11-30 01:17:11 +1100215 csum_replace2(&iph->check, iph->tot_len, newlen);
Patrick McHardycdd289a2007-02-07 15:09:46 -0800216 iph->tot_len = newlen;
217 }
218 return XT_CONTINUE;
219}
220
Igor Maravićc0cd1152011-12-12 02:58:24 +0000221#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
Patrick McHardycdd289a2007-02-07 15:09:46 -0800222static unsigned int
Jan Engelhardt4b560b42009-07-05 19:43:26 +0200223tcpmss_tg6(struct sk_buff *skb, const struct xt_action_param *par)
Patrick McHardycdd289a2007-02-07 15:09:46 -0800224{
Herbert Xu3db05fe2007-10-15 00:53:15 -0700225 struct ipv6hdr *ipv6h = ipv6_hdr(skb);
Patrick McHardycdd289a2007-02-07 15:09:46 -0800226 u8 nexthdr;
Jesse Gross75f28112011-11-30 17:05:51 -0800227 __be16 frag_off;
Patrick McHardycdd289a2007-02-07 15:09:46 -0800228 int tcphoff;
229 int ret;
230
231 nexthdr = ipv6h->nexthdr;
Jesse Gross75f28112011-11-30 17:05:51 -0800232 tcphoff = ipv6_skip_exthdr(skb, sizeof(*ipv6h), &nexthdr, &frag_off);
Patrick McHardy9dc05642007-11-30 23:58:03 +1100233 if (tcphoff < 0)
Patrick McHardycdd289a2007-02-07 15:09:46 -0800234 return NF_DROP;
Phil Oester70d19f82013-06-12 10:44:51 +0200235 ret = tcpmss_mangle_packet(skb, par,
Jan Engelhardtdb1a75b2008-07-21 10:02:59 -0700236 tcpmss_reverse_mtu(skb, PF_INET6),
Jan Engelhardt37c08382008-01-31 04:06:10 -0800237 tcphoff,
Patrick McHardycdd289a2007-02-07 15:09:46 -0800238 sizeof(*ipv6h) + sizeof(struct tcphdr));
239 if (ret < 0)
240 return NF_DROP;
241 if (ret > 0) {
Herbert Xu3db05fe2007-10-15 00:53:15 -0700242 ipv6h = ipv6_hdr(skb);
Patrick McHardycdd289a2007-02-07 15:09:46 -0800243 ipv6h->payload_len = htons(ntohs(ipv6h->payload_len) + ret);
244 }
245 return XT_CONTINUE;
246}
247#endif
248
Patrick McHardycdd289a2007-02-07 15:09:46 -0800249/* Must specify -p tcp --syn */
Jan Engelhardte1931b72007-07-07 22:16:26 -0700250static inline bool find_syn_match(const struct xt_entry_match *m)
Patrick McHardycdd289a2007-02-07 15:09:46 -0800251{
252 const struct xt_tcp *tcpinfo = (const struct xt_tcp *)m->data;
253
254 if (strcmp(m->u.kernel.match->name, "tcp") == 0 &&
Changli Gaoa3433f32010-06-12 14:01:43 +0000255 tcpinfo->flg_cmp & TCPHDR_SYN &&
Patrick McHardycdd289a2007-02-07 15:09:46 -0800256 !(tcpinfo->invflags & XT_TCP_INV_FLAGS))
Jan Engelhardte1931b72007-07-07 22:16:26 -0700257 return true;
Patrick McHardycdd289a2007-02-07 15:09:46 -0800258
Jan Engelhardte1931b72007-07-07 22:16:26 -0700259 return false;
Patrick McHardycdd289a2007-02-07 15:09:46 -0800260}
261
Jan Engelhardt135367b2010-03-19 17:16:42 +0100262static int tcpmss_tg4_check(const struct xt_tgchk_param *par)
Patrick McHardycdd289a2007-02-07 15:09:46 -0800263{
Jan Engelhardtaf5d6dc2008-10-08 11:35:19 +0200264 const struct xt_tcpmss_info *info = par->targinfo;
265 const struct ipt_entry *e = par->entryinfo;
Jan Engelhardtdcea9922010-02-24 18:34:48 +0100266 const struct xt_entry_match *ematch;
Patrick McHardycdd289a2007-02-07 15:09:46 -0800267
268 if (info->mss == XT_TCPMSS_CLAMP_PMTU &&
Jan Engelhardtaf5d6dc2008-10-08 11:35:19 +0200269 (par->hook_mask & ~((1 << NF_INET_FORWARD) |
Patrick McHardy6e23ae22007-11-19 18:53:30 -0800270 (1 << NF_INET_LOCAL_OUT) |
271 (1 << NF_INET_POST_ROUTING))) != 0) {
Jan Engelhardt8bee4ba2010-03-17 16:04:40 +0100272 pr_info("path-MTU clamping only supported in "
273 "FORWARD, OUTPUT and POSTROUTING hooks\n");
Jan Engelhardtd6b00a52010-03-25 16:34:45 +0100274 return -EINVAL;
Patrick McHardycdd289a2007-02-07 15:09:46 -0800275 }
Jan Engelhardtdcea9922010-02-24 18:34:48 +0100276 xt_ematch_foreach(ematch, e)
277 if (find_syn_match(ematch))
Jan Engelhardtd6b00a52010-03-25 16:34:45 +0100278 return 0;
Jan Engelhardt8bee4ba2010-03-17 16:04:40 +0100279 pr_info("Only works on TCP SYN packets\n");
Jan Engelhardtd6b00a52010-03-25 16:34:45 +0100280 return -EINVAL;
Patrick McHardycdd289a2007-02-07 15:09:46 -0800281}
282
Igor Maravićc0cd1152011-12-12 02:58:24 +0000283#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
Jan Engelhardt135367b2010-03-19 17:16:42 +0100284static int tcpmss_tg6_check(const struct xt_tgchk_param *par)
Patrick McHardycdd289a2007-02-07 15:09:46 -0800285{
Jan Engelhardtaf5d6dc2008-10-08 11:35:19 +0200286 const struct xt_tcpmss_info *info = par->targinfo;
287 const struct ip6t_entry *e = par->entryinfo;
Jan Engelhardtdcea9922010-02-24 18:34:48 +0100288 const struct xt_entry_match *ematch;
Patrick McHardycdd289a2007-02-07 15:09:46 -0800289
290 if (info->mss == XT_TCPMSS_CLAMP_PMTU &&
Jan Engelhardtaf5d6dc2008-10-08 11:35:19 +0200291 (par->hook_mask & ~((1 << NF_INET_FORWARD) |
Patrick McHardy6e23ae22007-11-19 18:53:30 -0800292 (1 << NF_INET_LOCAL_OUT) |
293 (1 << NF_INET_POST_ROUTING))) != 0) {
Jan Engelhardt8bee4ba2010-03-17 16:04:40 +0100294 pr_info("path-MTU clamping only supported in "
295 "FORWARD, OUTPUT and POSTROUTING hooks\n");
Jan Engelhardtd6b00a52010-03-25 16:34:45 +0100296 return -EINVAL;
Patrick McHardycdd289a2007-02-07 15:09:46 -0800297 }
Jan Engelhardtdcea9922010-02-24 18:34:48 +0100298 xt_ematch_foreach(ematch, e)
299 if (find_syn_match(ematch))
Jan Engelhardtd6b00a52010-03-25 16:34:45 +0100300 return 0;
Jan Engelhardt8bee4ba2010-03-17 16:04:40 +0100301 pr_info("Only works on TCP SYN packets\n");
Jan Engelhardtd6b00a52010-03-25 16:34:45 +0100302 return -EINVAL;
Patrick McHardycdd289a2007-02-07 15:09:46 -0800303}
304#endif
305
Jan Engelhardtd3c5ee62007-12-04 23:24:03 -0800306static struct xt_target tcpmss_tg_reg[] __read_mostly = {
Patrick McHardycdd289a2007-02-07 15:09:46 -0800307 {
Jan Engelhardtee999d82008-10-08 11:35:01 +0200308 .family = NFPROTO_IPV4,
Patrick McHardycdd289a2007-02-07 15:09:46 -0800309 .name = "TCPMSS",
Jan Engelhardtd3c5ee62007-12-04 23:24:03 -0800310 .checkentry = tcpmss_tg4_check,
311 .target = tcpmss_tg4,
Patrick McHardycdd289a2007-02-07 15:09:46 -0800312 .targetsize = sizeof(struct xt_tcpmss_info),
313 .proto = IPPROTO_TCP,
314 .me = THIS_MODULE,
315 },
Igor Maravićc0cd1152011-12-12 02:58:24 +0000316#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
Patrick McHardycdd289a2007-02-07 15:09:46 -0800317 {
Jan Engelhardtee999d82008-10-08 11:35:01 +0200318 .family = NFPROTO_IPV6,
Patrick McHardycdd289a2007-02-07 15:09:46 -0800319 .name = "TCPMSS",
Jan Engelhardtd3c5ee62007-12-04 23:24:03 -0800320 .checkentry = tcpmss_tg6_check,
321 .target = tcpmss_tg6,
Patrick McHardycdd289a2007-02-07 15:09:46 -0800322 .targetsize = sizeof(struct xt_tcpmss_info),
323 .proto = IPPROTO_TCP,
324 .me = THIS_MODULE,
325 },
326#endif
327};
328
Jan Engelhardtd3c5ee62007-12-04 23:24:03 -0800329static int __init tcpmss_tg_init(void)
Patrick McHardycdd289a2007-02-07 15:09:46 -0800330{
Jan Engelhardtd3c5ee62007-12-04 23:24:03 -0800331 return xt_register_targets(tcpmss_tg_reg, ARRAY_SIZE(tcpmss_tg_reg));
Patrick McHardycdd289a2007-02-07 15:09:46 -0800332}
333
Jan Engelhardtd3c5ee62007-12-04 23:24:03 -0800334static void __exit tcpmss_tg_exit(void)
Patrick McHardycdd289a2007-02-07 15:09:46 -0800335{
Jan Engelhardtd3c5ee62007-12-04 23:24:03 -0800336 xt_unregister_targets(tcpmss_tg_reg, ARRAY_SIZE(tcpmss_tg_reg));
Patrick McHardycdd289a2007-02-07 15:09:46 -0800337}
338
Jan Engelhardtd3c5ee62007-12-04 23:24:03 -0800339module_init(tcpmss_tg_init);
340module_exit(tcpmss_tg_exit);