aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJan Engelhardt <jengelh@computergmbh.de>2008-01-15 02:40:53 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 18:02:23 -0500
commit64eb12f9972d45f3b9b0f0a33a966e311c3d5275 (patch)
tree0a598500b8ec1bb62dd71909f1c907e121e4a4bf /net
parent2e3075a2c4364c0e8726ac2a0f3b1708da781bac (diff)
[NETFILTER]: xt_conntrack match, revision 1
Introduces the xt_conntrack match revision 1. It uses fixed types, the new nf_inet_addr and comes with IPv6 support, thereby completely superseding xt_state. Signed-off-by: Jan Engelhardt <jengelh@computergmbh.de> Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/netfilter/xt_conntrack.c207
1 files changed, 182 insertions, 25 deletions
diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c
index 3f8bfbaa9b19..dc9e73786864 100644
--- a/net/netfilter/xt_conntrack.c
+++ b/net/netfilter/xt_conntrack.c
@@ -1,15 +1,19 @@
1/* Kernel module to match connection tracking information. 1/*
2 * Superset of Rusty's minimalistic state match. 2 * xt_conntrack - Netfilter module to match connection tracking
3 * information. (Superset of Rusty's minimalistic state match.)
3 * 4 *
4 * (C) 2001 Marc Boucher (marc@mbsi.ca). 5 * (C) 2001 Marc Boucher (marc@mbsi.ca).
6 * Copyright © CC Computer Consultants GmbH, 2007 - 2008
7 * Jan Engelhardt <jengelh@computergmbh.de>
5 * 8 *
6 * This program is free software; you can redistribute it and/or modify 9 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as 10 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation. 11 * published by the Free Software Foundation.
9 */ 12 */
10 13
11#include <linux/module.h> 14#include <linux/module.h>
12#include <linux/skbuff.h> 15#include <linux/skbuff.h>
16#include <net/ipv6.h>
13#include <linux/netfilter/x_tables.h> 17#include <linux/netfilter/x_tables.h>
14#include <linux/netfilter/xt_conntrack.h> 18#include <linux/netfilter/xt_conntrack.h>
15#include <net/netfilter/nf_conntrack.h> 19#include <net/netfilter/nf_conntrack.h>
@@ -18,12 +22,13 @@ MODULE_LICENSE("GPL");
18MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); 22MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
19MODULE_DESCRIPTION("iptables connection tracking match module"); 23MODULE_DESCRIPTION("iptables connection tracking match module");
20MODULE_ALIAS("ipt_conntrack"); 24MODULE_ALIAS("ipt_conntrack");
25MODULE_ALIAS("ip6t_conntrack");
21 26
22static bool 27static bool
23conntrack_mt(const struct sk_buff *skb, const struct net_device *in, 28conntrack_mt_v0(const struct sk_buff *skb, const struct net_device *in,
24 const struct net_device *out, const struct xt_match *match, 29 const struct net_device *out, const struct xt_match *match,
25 const void *matchinfo, int offset, unsigned int protoff, 30 const void *matchinfo, int offset, unsigned int protoff,
26 bool *hotdrop) 31 bool *hotdrop)
27{ 32{
28 const struct xt_conntrack_info *sinfo = matchinfo; 33 const struct xt_conntrack_info *sinfo = matchinfo;
29 const struct nf_conn *ct; 34 const struct nf_conn *ct;
@@ -112,6 +117,134 @@ conntrack_mt(const struct sk_buff *skb, const struct net_device *in,
112} 117}
113 118
114static bool 119static bool
120conntrack_addrcmp(const union nf_inet_addr *kaddr,
121 const union nf_inet_addr *uaddr,
122 const union nf_inet_addr *umask, unsigned int l3proto)
123{
124 if (l3proto == AF_INET)
125 return (kaddr->ip & umask->ip) == uaddr->ip;
126 else if (l3proto == AF_INET6)
127 return ipv6_masked_addr_cmp(&kaddr->in6, &umask->in6,
128 &uaddr->in6) == 0;
129 else
130 return false;
131}
132
133static inline bool
134conntrack_mt_origsrc(const struct nf_conn *ct,
135 const struct xt_conntrack_mtinfo1 *info,
136 unsigned int family)
137{
138 return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3,
139 &info->origsrc_addr, &info->origsrc_mask, family);
140}
141
142static inline bool
143conntrack_mt_origdst(const struct nf_conn *ct,
144 const struct xt_conntrack_mtinfo1 *info,
145 unsigned int family)
146{
147 return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3,
148 &info->origdst_addr, &info->origdst_mask, family);
149}
150
151static inline bool
152conntrack_mt_replsrc(const struct nf_conn *ct,
153 const struct xt_conntrack_mtinfo1 *info,
154 unsigned int family)
155{
156 return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3,
157 &info->replsrc_addr, &info->replsrc_mask, family);
158}
159
160static inline bool
161conntrack_mt_repldst(const struct nf_conn *ct,
162 const struct xt_conntrack_mtinfo1 *info,
163 unsigned int family)
164{
165 return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3,
166 &info->repldst_addr, &info->repldst_mask, family);
167}
168
169static bool
170conntrack_mt(const struct sk_buff *skb, const struct net_device *in,
171 const struct net_device *out, const struct xt_match *match,
172 const void *matchinfo, int offset, unsigned int protoff,
173 bool *hotdrop)
174{
175 const struct xt_conntrack_mtinfo1 *info = matchinfo;
176 enum ip_conntrack_info ctinfo;
177 const struct nf_conn *ct;
178 unsigned int statebit;
179
180 ct = nf_ct_get(skb, &ctinfo);
181
182 if (ct == &nf_conntrack_untracked)
183 statebit = XT_CONNTRACK_STATE_UNTRACKED;
184 else if (ct != NULL)
185 statebit = XT_CONNTRACK_STATE_BIT(ctinfo);
186 else
187 statebit = XT_CONNTRACK_STATE_INVALID;
188
189 if (info->match_flags & XT_CONNTRACK_STATE) {
190 if (ct != NULL) {
191 if (test_bit(IPS_SRC_NAT_BIT, &ct->status))
192 statebit |= XT_CONNTRACK_STATE_SNAT;
193 if (test_bit(IPS_DST_NAT_BIT, &ct->status))
194 statebit |= XT_CONNTRACK_STATE_DNAT;
195 }
196 if ((info->state_mask & statebit) ^
197 !(info->invert_flags & XT_CONNTRACK_STATE))
198 return false;
199 }
200
201 if (ct == NULL)
202 return info->match_flags & XT_CONNTRACK_STATE;
203
204 if ((info->match_flags & XT_CONNTRACK_PROTO) &&
205 ((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum ==
206 info->l4proto) ^ !(info->invert_flags & XT_CONNTRACK_PROTO)))
207 return false;
208
209 if (info->match_flags & XT_CONNTRACK_ORIGSRC)
210 if (conntrack_mt_origsrc(ct, info, match->family) ^
211 !(info->invert_flags & XT_CONNTRACK_ORIGSRC))
212 return false;
213
214 if (info->match_flags & XT_CONNTRACK_ORIGDST)
215 if (conntrack_mt_origdst(ct, info, match->family) ^
216 !(info->invert_flags & XT_CONNTRACK_ORIGDST))
217 return false;
218
219 if (info->match_flags & XT_CONNTRACK_REPLSRC)
220 if (conntrack_mt_replsrc(ct, info, match->family) ^
221 !(info->invert_flags & XT_CONNTRACK_REPLSRC))
222 return false;
223
224 if (info->match_flags & XT_CONNTRACK_REPLDST)
225 if (conntrack_mt_repldst(ct, info, match->family) ^
226 !(info->invert_flags & XT_CONNTRACK_REPLDST))
227 return false;
228
229 if ((info->match_flags & XT_CONNTRACK_STATUS) &&
230 (!!(info->status_mask & ct->status) ^
231 !(info->invert_flags & XT_CONNTRACK_STATUS)))
232 return false;
233
234 if (info->match_flags & XT_CONNTRACK_EXPIRES) {
235 unsigned long expires = 0;
236
237 if (timer_pending(&ct->timeout))
238 expires = (ct->timeout.expires - jiffies) / HZ;
239 if ((expires >= info->expires_min &&
240 expires <= info->expires_max) ^
241 !(info->invert_flags & XT_CONNTRACK_EXPIRES))
242 return false;
243 }
244 return true;
245}
246
247static bool
115conntrack_mt_check(const char *tablename, const void *ip, 248conntrack_mt_check(const char *tablename, const void *ip,
116 const struct xt_match *match, void *matchinfo, 249 const struct xt_match *match, void *matchinfo,
117 unsigned int hook_mask) 250 unsigned int hook_mask)
@@ -144,7 +277,7 @@ struct compat_xt_conntrack_info
144 u_int8_t invflags; 277 u_int8_t invflags;
145}; 278};
146 279
147static void conntrack_mt_compat_from_user(void *dst, void *src) 280static void conntrack_mt_compat_from_user_v0(void *dst, void *src)
148{ 281{
149 const struct compat_xt_conntrack_info *cm = src; 282 const struct compat_xt_conntrack_info *cm = src;
150 struct xt_conntrack_info m = { 283 struct xt_conntrack_info m = {
@@ -161,7 +294,7 @@ static void conntrack_mt_compat_from_user(void *dst, void *src)
161 memcpy(dst, &m, sizeof(m)); 294 memcpy(dst, &m, sizeof(m));
162} 295}
163 296
164static int conntrack_mt_compat_to_user(void __user *dst, void *src) 297static int conntrack_mt_compat_to_user_v0(void __user *dst, void *src)
165{ 298{
166 const struct xt_conntrack_info *m = src; 299 const struct xt_conntrack_info *m = src;
167 struct compat_xt_conntrack_info cm = { 300 struct compat_xt_conntrack_info cm = {
@@ -179,29 +312,53 @@ static int conntrack_mt_compat_to_user(void __user *dst, void *src)
179} 312}
180#endif 313#endif
181 314
182static struct xt_match conntrack_mt_reg __read_mostly = { 315static struct xt_match conntrack_mt_reg[] __read_mostly = {
183 .name = "conntrack", 316 {
184 .match = conntrack_mt, 317 .name = "conntrack",
185 .checkentry = conntrack_mt_check, 318 .revision = 0,
186 .destroy = conntrack_mt_destroy, 319 .family = AF_INET,
187 .matchsize = sizeof(struct xt_conntrack_info), 320 .match = conntrack_mt_v0,
321 .checkentry = conntrack_mt_check,
322 .destroy = conntrack_mt_destroy,
323 .matchsize = sizeof(struct xt_conntrack_info),
324 .me = THIS_MODULE,
188#ifdef CONFIG_COMPAT 325#ifdef CONFIG_COMPAT
189 .compatsize = sizeof(struct compat_xt_conntrack_info), 326 .compatsize = sizeof(struct compat_xt_conntrack_info),
190 .compat_from_user = conntrack_mt_compat_from_user, 327 .compat_from_user = conntrack_mt_compat_from_user_v0,
191 .compat_to_user = conntrack_mt_compat_to_user, 328 .compat_to_user = conntrack_mt_compat_to_user_v0,
192#endif 329#endif
193 .family = AF_INET, 330 },
194 .me = THIS_MODULE, 331 {
332 .name = "conntrack",
333 .revision = 1,
334 .family = AF_INET,
335 .matchsize = sizeof(struct xt_conntrack_mtinfo1),
336 .match = conntrack_mt,
337 .checkentry = conntrack_mt_check,
338 .destroy = conntrack_mt_destroy,
339 .me = THIS_MODULE,
340 },
341 {
342 .name = "conntrack",
343 .revision = 1,
344 .family = AF_INET6,
345 .matchsize = sizeof(struct xt_conntrack_mtinfo1),
346 .match = conntrack_mt,
347 .checkentry = conntrack_mt_check,
348 .destroy = conntrack_mt_destroy,
349 .me = THIS_MODULE,
350 },
195}; 351};
196 352
197static int __init conntrack_mt_init(void) 353static int __init conntrack_mt_init(void)
198{ 354{
199 return xt_register_match(&conntrack_mt_reg); 355 return xt_register_matches(conntrack_mt_reg,
356 ARRAY_SIZE(conntrack_mt_reg));
200} 357}
201 358
202static void __exit conntrack_mt_exit(void) 359static void __exit conntrack_mt_exit(void)
203{ 360{
204 xt_unregister_match(&conntrack_mt_reg); 361 xt_unregister_matches(conntrack_mt_reg, ARRAY_SIZE(conntrack_mt_reg));
205} 362}
206 363
207module_init(conntrack_mt_init); 364module_init(conntrack_mt_init);