Blame view

net/netfilter/xt_conntrack.c 9.65 KB
64eb12f99   Jan Engelhardt   [NETFILTER]: xt_c...
1
2
3
  /*
   *	xt_conntrack - Netfilter module to match connection tracking
   *	information. (Superset of Rusty's minimalistic state match.)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4
   *
64eb12f99   Jan Engelhardt   [NETFILTER]: xt_c...
5
   *	(C) 2001  Marc Boucher (marc@mbsi.ca).
f229f6ce4   Patrick McHardy   netfilter: add my...
6
   *	(C) 2006-2012 Patrick McHardy <kaber@trash.net>
64eb12f99   Jan Engelhardt   [NETFILTER]: xt_c...
7
   *	Copyright © CC Computer Consultants GmbH, 2007 - 2008
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
8
   *
64eb12f99   Jan Engelhardt   [NETFILTER]: xt_c...
9
10
11
   *	This program is free software; you can redistribute it and/or modify
   *	it under the terms of the GNU General Public License version 2 as
   *	published by the Free Software Foundation.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
12
   */
8bee4bad0   Jan Engelhardt   netfilter: xt ext...
13
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
14
15
  #include <linux/module.h>
  #include <linux/skbuff.h>
64eb12f99   Jan Engelhardt   [NETFILTER]: xt_c...
16
  #include <net/ipv6.h>
2e4e6a17a   Harald Welte   [NETFILTER] x_tab...
17
18
  #include <linux/netfilter/x_tables.h>
  #include <linux/netfilter/xt_conntrack.h>
587aa6416   Patrick McHardy   [NETFILTER]: Remo...
19
  #include <net/netfilter/nf_conntrack.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
21
22
  
  MODULE_LICENSE("GPL");
  MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
9e05ec4b1   Jan Engelhardt   netfilter: xtable...
23
  MODULE_AUTHOR("Jan Engelhardt <jengelh@medozas.de>");
2ae15b64e   Jan Engelhardt   [NETFILTER]: Upda...
24
  MODULE_DESCRIPTION("Xtables: connection tracking state match");
2e4e6a17a   Harald Welte   [NETFILTER] x_tab...
25
  MODULE_ALIAS("ipt_conntrack");
64eb12f99   Jan Engelhardt   [NETFILTER]: xt_c...
26
  MODULE_ALIAS("ip6t_conntrack");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27

1d93a9cba   Jan Engelhardt   [NETFILTER]: x_ta...
28
  static bool
64eb12f99   Jan Engelhardt   [NETFILTER]: xt_c...
29
30
31
32
  conntrack_addrcmp(const union nf_inet_addr *kaddr,
                    const union nf_inet_addr *uaddr,
                    const union nf_inet_addr *umask, unsigned int l3proto)
  {
ee999d8b9   Jan Engelhardt   netfilter: x_tabl...
33
  	if (l3proto == NFPROTO_IPV4)
6556874dc   Jan Engelhardt   [NETFILTER]: xt_c...
34
  		return ((kaddr->ip ^ uaddr->ip) & umask->ip) == 0;
ee999d8b9   Jan Engelhardt   netfilter: x_tabl...
35
  	else if (l3proto == NFPROTO_IPV6)
64eb12f99   Jan Engelhardt   [NETFILTER]: xt_c...
36
37
38
39
40
41
42
43
  		return ipv6_masked_addr_cmp(&kaddr->in6, &umask->in6,
  		       &uaddr->in6) == 0;
  	else
  		return false;
  }
  
  static inline bool
  conntrack_mt_origsrc(const struct nf_conn *ct,
d6d3f08b0   Jan Engelhardt   netfilter: xtable...
44
                       const struct xt_conntrack_mtinfo2 *info,
76108cea0   Jan Engelhardt   netfilter: Use un...
45
  		     u_int8_t family)
64eb12f99   Jan Engelhardt   [NETFILTER]: xt_c...
46
47
48
49
50
51
52
  {
  	return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3,
  	       &info->origsrc_addr, &info->origsrc_mask, family);
  }
  
  static inline bool
  conntrack_mt_origdst(const struct nf_conn *ct,
d6d3f08b0   Jan Engelhardt   netfilter: xtable...
53
                       const struct xt_conntrack_mtinfo2 *info,
76108cea0   Jan Engelhardt   netfilter: Use un...
54
  		     u_int8_t family)
64eb12f99   Jan Engelhardt   [NETFILTER]: xt_c...
55
56
57
58
59
60
61
  {
  	return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3,
  	       &info->origdst_addr, &info->origdst_mask, family);
  }
  
  static inline bool
  conntrack_mt_replsrc(const struct nf_conn *ct,
d6d3f08b0   Jan Engelhardt   netfilter: xtable...
62
                       const struct xt_conntrack_mtinfo2 *info,
76108cea0   Jan Engelhardt   netfilter: Use un...
63
  		     u_int8_t family)
64eb12f99   Jan Engelhardt   [NETFILTER]: xt_c...
64
65
66
67
68
69
70
  {
  	return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3,
  	       &info->replsrc_addr, &info->replsrc_mask, family);
  }
  
  static inline bool
  conntrack_mt_repldst(const struct nf_conn *ct,
d6d3f08b0   Jan Engelhardt   netfilter: xtable...
71
                       const struct xt_conntrack_mtinfo2 *info,
76108cea0   Jan Engelhardt   netfilter: Use un...
72
  		     u_int8_t family)
64eb12f99   Jan Engelhardt   [NETFILTER]: xt_c...
73
74
75
76
  {
  	return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3,
  	       &info->repldst_addr, &info->repldst_mask, family);
  }
b41649989   Jan Engelhardt   [NETFILTER]: xt_c...
77
  static inline bool
d6d3f08b0   Jan Engelhardt   netfilter: xtable...
78
  ct_proto_port_check(const struct xt_conntrack_mtinfo2 *info,
b41649989   Jan Engelhardt   [NETFILTER]: xt_c...
79
80
81
82
83
84
                      const struct nf_conn *ct)
  {
  	const struct nf_conntrack_tuple *tuple;
  
  	tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
  	if ((info->match_flags & XT_CONNTRACK_PROTO) &&
5e8fbe2ac   Patrick McHardy   [NETFILTER]: nf_c...
85
  	    (nf_ct_protonum(ct) == info->l4proto) ^
b41649989   Jan Engelhardt   [NETFILTER]: xt_c...
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
  	    !(info->invert_flags & XT_CONNTRACK_PROTO))
  		return false;
  
  	/* Shortcut to match all recognized protocols by using ->src.all. */
  	if ((info->match_flags & XT_CONNTRACK_ORIGSRC_PORT) &&
  	    (tuple->src.u.all == info->origsrc_port) ^
  	    !(info->invert_flags & XT_CONNTRACK_ORIGSRC_PORT))
  		return false;
  
  	if ((info->match_flags & XT_CONNTRACK_ORIGDST_PORT) &&
  	    (tuple->dst.u.all == info->origdst_port) ^
  	    !(info->invert_flags & XT_CONNTRACK_ORIGDST_PORT))
  		return false;
  
  	tuple = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;
  
  	if ((info->match_flags & XT_CONNTRACK_REPLSRC_PORT) &&
  	    (tuple->src.u.all == info->replsrc_port) ^
  	    !(info->invert_flags & XT_CONNTRACK_REPLSRC_PORT))
  		return false;
  
  	if ((info->match_flags & XT_CONNTRACK_REPLDST_PORT) &&
  	    (tuple->dst.u.all == info->repldst_port) ^
  	    !(info->invert_flags & XT_CONNTRACK_REPLDST_PORT))
  		return false;
  
  	return true;
  }
b017900aa   Patrick McHardy   netfilter: xt_con...
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
  static inline bool
  port_match(u16 min, u16 max, u16 port, bool invert)
  {
  	return (port >= min && port <= max) ^ invert;
  }
  
  static inline bool
  ct_proto_port_check_v3(const struct xt_conntrack_mtinfo3 *info,
  		       const struct nf_conn *ct)
  {
  	const struct nf_conntrack_tuple *tuple;
  
  	tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
  	if ((info->match_flags & XT_CONNTRACK_PROTO) &&
  	    (nf_ct_protonum(ct) == info->l4proto) ^
  	    !(info->invert_flags & XT_CONNTRACK_PROTO))
  		return false;
  
  	/* Shortcut to match all recognized protocols by using ->src.all. */
  	if ((info->match_flags & XT_CONNTRACK_ORIGSRC_PORT) &&
  	    !port_match(info->origsrc_port, info->origsrc_port_high,
  			ntohs(tuple->src.u.all),
  			info->invert_flags & XT_CONNTRACK_ORIGSRC_PORT))
  		return false;
  
  	if ((info->match_flags & XT_CONNTRACK_ORIGDST_PORT) &&
  	    !port_match(info->origdst_port, info->origdst_port_high,
  			ntohs(tuple->dst.u.all),
  			info->invert_flags & XT_CONNTRACK_ORIGDST_PORT))
  		return false;
  
  	tuple = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;
  
  	if ((info->match_flags & XT_CONNTRACK_REPLSRC_PORT) &&
  	    !port_match(info->replsrc_port, info->replsrc_port_high,
  			ntohs(tuple->src.u.all),
  			info->invert_flags & XT_CONNTRACK_REPLSRC_PORT))
  		return false;
  
  	if ((info->match_flags & XT_CONNTRACK_REPLDST_PORT) &&
  	    !port_match(info->repldst_port, info->repldst_port_high,
  			ntohs(tuple->dst.u.all),
  			info->invert_flags & XT_CONNTRACK_REPLDST_PORT))
  		return false;
  
  	return true;
  }
64eb12f99   Jan Engelhardt   [NETFILTER]: xt_c...
161
  static bool
62fc80510   Jan Engelhardt   netfilter: xtable...
162
  conntrack_mt(const struct sk_buff *skb, struct xt_action_param *par,
3a0429292   Florian Westphal   netfilter: xtable...
163
               u16 state_mask, u16 status_mask)
64eb12f99   Jan Engelhardt   [NETFILTER]: xt_c...
164
  {
d6d3f08b0   Jan Engelhardt   netfilter: xtable...
165
  	const struct xt_conntrack_mtinfo2 *info = par->matchinfo;
64eb12f99   Jan Engelhardt   [NETFILTER]: xt_c...
166
167
168
169
170
  	enum ip_conntrack_info ctinfo;
  	const struct nf_conn *ct;
  	unsigned int statebit;
  
  	ct = nf_ct_get(skb, &ctinfo);
5bfddbd46   Eric Dumazet   netfilter: nf_con...
171
172
173
174
175
176
  	if (ct) {
  		if (nf_ct_is_untracked(ct))
  			statebit = XT_CONNTRACK_STATE_UNTRACKED;
  		else
  			statebit = XT_CONNTRACK_STATE_BIT(ctinfo);
  	} else
64eb12f99   Jan Engelhardt   [NETFILTER]: xt_c...
177
178
179
180
181
182
183
184
185
  		statebit = XT_CONNTRACK_STATE_INVALID;
  
  	if (info->match_flags & XT_CONNTRACK_STATE) {
  		if (ct != NULL) {
  			if (test_bit(IPS_SRC_NAT_BIT, &ct->status))
  				statebit |= XT_CONNTRACK_STATE_SNAT;
  			if (test_bit(IPS_DST_NAT_BIT, &ct->status))
  				statebit |= XT_CONNTRACK_STATE_DNAT;
  		}
3a0429292   Florian Westphal   netfilter: xtable...
186
  		if (!!(state_mask & statebit) ^
64eb12f99   Jan Engelhardt   [NETFILTER]: xt_c...
187
188
189
190
191
192
  		    !(info->invert_flags & XT_CONNTRACK_STATE))
  			return false;
  	}
  
  	if (ct == NULL)
  		return info->match_flags & XT_CONNTRACK_STATE;
b41649989   Jan Engelhardt   [NETFILTER]: xt_c...
193
194
  	if ((info->match_flags & XT_CONNTRACK_DIRECTION) &&
  	    (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL) ^
96120d86f   Florian Westphal   netfilter: xt_con...
195
  	    !(info->invert_flags & XT_CONNTRACK_DIRECTION))
64eb12f99   Jan Engelhardt   [NETFILTER]: xt_c...
196
197
198
  		return false;
  
  	if (info->match_flags & XT_CONNTRACK_ORIGSRC)
92f3b2b1b   Jan Engelhardt   netfilter: xtable...
199
  		if (conntrack_mt_origsrc(ct, info, par->family) ^
64eb12f99   Jan Engelhardt   [NETFILTER]: xt_c...
200
201
202
203
  		    !(info->invert_flags & XT_CONNTRACK_ORIGSRC))
  			return false;
  
  	if (info->match_flags & XT_CONNTRACK_ORIGDST)
92f3b2b1b   Jan Engelhardt   netfilter: xtable...
204
  		if (conntrack_mt_origdst(ct, info, par->family) ^
64eb12f99   Jan Engelhardt   [NETFILTER]: xt_c...
205
206
207
208
  		    !(info->invert_flags & XT_CONNTRACK_ORIGDST))
  			return false;
  
  	if (info->match_flags & XT_CONNTRACK_REPLSRC)
92f3b2b1b   Jan Engelhardt   netfilter: xtable...
209
  		if (conntrack_mt_replsrc(ct, info, par->family) ^
64eb12f99   Jan Engelhardt   [NETFILTER]: xt_c...
210
211
212
213
  		    !(info->invert_flags & XT_CONNTRACK_REPLSRC))
  			return false;
  
  	if (info->match_flags & XT_CONNTRACK_REPLDST)
92f3b2b1b   Jan Engelhardt   netfilter: xtable...
214
  		if (conntrack_mt_repldst(ct, info, par->family) ^
64eb12f99   Jan Engelhardt   [NETFILTER]: xt_c...
215
216
  		    !(info->invert_flags & XT_CONNTRACK_REPLDST))
  			return false;
b017900aa   Patrick McHardy   netfilter: xt_con...
217
218
219
220
221
222
223
  	if (par->match->revision != 3) {
  		if (!ct_proto_port_check(info, ct))
  			return false;
  	} else {
  		if (!ct_proto_port_check_v3(par->matchinfo, ct))
  			return false;
  	}
b41649989   Jan Engelhardt   [NETFILTER]: xt_c...
224

64eb12f99   Jan Engelhardt   [NETFILTER]: xt_c...
225
  	if ((info->match_flags & XT_CONNTRACK_STATUS) &&
3a0429292   Florian Westphal   netfilter: xtable...
226
  	    (!!(status_mask & ct->status) ^
64eb12f99   Jan Engelhardt   [NETFILTER]: xt_c...
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
  	    !(info->invert_flags & XT_CONNTRACK_STATUS)))
  		return false;
  
  	if (info->match_flags & XT_CONNTRACK_EXPIRES) {
  		unsigned long expires = 0;
  
  		if (timer_pending(&ct->timeout))
  			expires = (ct->timeout.expires - jiffies) / HZ;
  		if ((expires >= info->expires_min &&
  		    expires <= info->expires_max) ^
  		    !(info->invert_flags & XT_CONNTRACK_EXPIRES))
  			return false;
  	}
  	return true;
  }
d6d3f08b0   Jan Engelhardt   netfilter: xtable...
242
  static bool
62fc80510   Jan Engelhardt   netfilter: xtable...
243
  conntrack_mt_v1(const struct sk_buff *skb, struct xt_action_param *par)
d6d3f08b0   Jan Engelhardt   netfilter: xtable...
244
  {
3a0429292   Florian Westphal   netfilter: xtable...
245
  	const struct xt_conntrack_mtinfo1 *info = par->matchinfo;
d6d3f08b0   Jan Engelhardt   netfilter: xtable...
246

3a0429292   Florian Westphal   netfilter: xtable...
247
248
249
250
  	return conntrack_mt(skb, par, info->state_mask, info->status_mask);
  }
  
  static bool
62fc80510   Jan Engelhardt   netfilter: xtable...
251
  conntrack_mt_v2(const struct sk_buff *skb, struct xt_action_param *par)
3a0429292   Florian Westphal   netfilter: xtable...
252
253
254
255
  {
  	const struct xt_conntrack_mtinfo2 *info = par->matchinfo;
  
  	return conntrack_mt(skb, par, info->state_mask, info->status_mask);
d6d3f08b0   Jan Engelhardt   netfilter: xtable...
256
  }
b017900aa   Patrick McHardy   netfilter: xt_con...
257
258
259
260
261
262
263
  static bool
  conntrack_mt_v3(const struct sk_buff *skb, struct xt_action_param *par)
  {
  	const struct xt_conntrack_mtinfo3 *info = par->matchinfo;
  
  	return conntrack_mt(skb, par, info->state_mask, info->status_mask);
  }
b0f38452f   Jan Engelhardt   netfilter: xtable...
264
  static int conntrack_mt_check(const struct xt_mtchk_param *par)
b9f78f9fc   Pablo Neira Ayuso   [NETFILTER]: nf_c...
265
  {
4a5a5c73b   Jan Engelhardt   netfilter: xtable...
266
267
268
  	int ret;
  
  	ret = nf_ct_l3proto_try_module_get(par->family);
f95c74e33   Jan Engelhardt   netfilter: xtable...
269
  	if (ret < 0)
8bee4bad0   Jan Engelhardt   netfilter: xt ext...
270
271
272
  		pr_info("cannot load conntrack support for proto=%u
  ",
  			par->family);
f95c74e33   Jan Engelhardt   netfilter: xtable...
273
  	return ret;
b9f78f9fc   Pablo Neira Ayuso   [NETFILTER]: nf_c...
274
  }
6be3d8598   Jan Engelhardt   netfilter: xtable...
275
  static void conntrack_mt_destroy(const struct xt_mtdtor_param *par)
b9f78f9fc   Pablo Neira Ayuso   [NETFILTER]: nf_c...
276
  {
92f3b2b1b   Jan Engelhardt   netfilter: xtable...
277
  	nf_ct_l3proto_module_put(par->family);
b9f78f9fc   Pablo Neira Ayuso   [NETFILTER]: nf_c...
278
  }
64eb12f99   Jan Engelhardt   [NETFILTER]: xt_c...
279
280
281
  static struct xt_match conntrack_mt_reg[] __read_mostly = {
  	{
  		.name       = "conntrack",
64eb12f99   Jan Engelhardt   [NETFILTER]: xt_c...
282
  		.revision   = 1,
92f3b2b1b   Jan Engelhardt   netfilter: xtable...
283
  		.family     = NFPROTO_UNSPEC,
64eb12f99   Jan Engelhardt   [NETFILTER]: xt_c...
284
  		.matchsize  = sizeof(struct xt_conntrack_mtinfo1),
d6d3f08b0   Jan Engelhardt   netfilter: xtable...
285
  		.match      = conntrack_mt_v1,
3a0429292   Florian Westphal   netfilter: xtable...
286
287
  		.checkentry = conntrack_mt_check,
  		.destroy    = conntrack_mt_destroy,
d6d3f08b0   Jan Engelhardt   netfilter: xtable...
288
289
290
291
292
293
294
  		.me         = THIS_MODULE,
  	},
  	{
  		.name       = "conntrack",
  		.revision   = 2,
  		.family     = NFPROTO_UNSPEC,
  		.matchsize  = sizeof(struct xt_conntrack_mtinfo2),
3a0429292   Florian Westphal   netfilter: xtable...
295
  		.match      = conntrack_mt_v2,
64eb12f99   Jan Engelhardt   [NETFILTER]: xt_c...
296
297
298
299
  		.checkentry = conntrack_mt_check,
  		.destroy    = conntrack_mt_destroy,
  		.me         = THIS_MODULE,
  	},
b017900aa   Patrick McHardy   netfilter: xt_con...
300
301
302
303
304
305
306
307
308
309
  	{
  		.name       = "conntrack",
  		.revision   = 3,
  		.family     = NFPROTO_UNSPEC,
  		.matchsize  = sizeof(struct xt_conntrack_mtinfo3),
  		.match      = conntrack_mt_v3,
  		.checkentry = conntrack_mt_check,
  		.destroy    = conntrack_mt_destroy,
  		.me         = THIS_MODULE,
  	},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
310
  };
d3c5ee6d5   Jan Engelhardt   [NETFILTER]: x_ta...
311
  static int __init conntrack_mt_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
312
  {
64eb12f99   Jan Engelhardt   [NETFILTER]: xt_c...
313
314
  	return xt_register_matches(conntrack_mt_reg,
  	       ARRAY_SIZE(conntrack_mt_reg));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
315
  }
d3c5ee6d5   Jan Engelhardt   [NETFILTER]: x_ta...
316
  static void __exit conntrack_mt_exit(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
317
  {
64eb12f99   Jan Engelhardt   [NETFILTER]: xt_c...
318
  	xt_unregister_matches(conntrack_mt_reg, ARRAY_SIZE(conntrack_mt_reg));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
319
  }
d3c5ee6d5   Jan Engelhardt   [NETFILTER]: x_ta...
320
321
  module_init(conntrack_mt_init);
  module_exit(conntrack_mt_exit);