diff options
author | Jan Engelhardt <jengelh@computergmbh.de> | 2008-01-15 02:40:53 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 18:02:23 -0500 |
commit | 64eb12f9972d45f3b9b0f0a33a966e311c3d5275 (patch) | |
tree | 0a598500b8ec1bb62dd71909f1c907e121e4a4bf /net | |
parent | 2e3075a2c4364c0e8726ac2a0f3b1708da781bac (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.c | 207 |
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"); | |||
18 | MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); | 22 | MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); |
19 | MODULE_DESCRIPTION("iptables connection tracking match module"); | 23 | MODULE_DESCRIPTION("iptables connection tracking match module"); |
20 | MODULE_ALIAS("ipt_conntrack"); | 24 | MODULE_ALIAS("ipt_conntrack"); |
25 | MODULE_ALIAS("ip6t_conntrack"); | ||
21 | 26 | ||
22 | static bool | 27 | static bool |
23 | conntrack_mt(const struct sk_buff *skb, const struct net_device *in, | 28 | conntrack_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 | ||
114 | static bool | 119 | static bool |
120 | conntrack_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 | |||
133 | static inline bool | ||
134 | conntrack_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 | |||
142 | static inline bool | ||
143 | conntrack_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 | |||
151 | static inline bool | ||
152 | conntrack_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 | |||
160 | static inline bool | ||
161 | conntrack_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 | |||
169 | static bool | ||
170 | conntrack_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 | |||
247 | static bool | ||
115 | conntrack_mt_check(const char *tablename, const void *ip, | 248 | conntrack_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 | ||
147 | static void conntrack_mt_compat_from_user(void *dst, void *src) | 280 | static 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 | ||
164 | static int conntrack_mt_compat_to_user(void __user *dst, void *src) | 297 | static 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 | ||
182 | static struct xt_match conntrack_mt_reg __read_mostly = { | 315 | static 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 | ||
197 | static int __init conntrack_mt_init(void) | 353 | static 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 | ||
202 | static void __exit conntrack_mt_exit(void) | 359 | static 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 | ||
207 | module_init(conntrack_mt_init); | 364 | module_init(conntrack_mt_init); |