diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2006-01-05 15:19:05 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2006-01-05 15:19:05 -0500 |
commit | c1d10adb4a521de5760112853f42aaeefcec96eb (patch) | |
tree | c7ba283aa0b9016c8403fa6589b7b3418f71acda /net/ipv4 | |
parent | 205d67c7d942c057648148fefb17e46f77e3efd6 (diff) |
[NETFILTER]: Add ctnetlink port for nf_conntrack
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 47 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_conntrack_proto_icmp.c | 97 |
2 files changed, 126 insertions, 18 deletions
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index 8202c1c0afad..385867efd481 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | |||
@@ -392,6 +392,48 @@ getorigdst(struct sock *sk, int optval, void __user *user, int *len) | |||
392 | return -ENOENT; | 392 | return -ENOENT; |
393 | } | 393 | } |
394 | 394 | ||
395 | #if defined(CONFIG_NF_CT_NETLINK) || \ | ||
396 | defined(CONFIG_NF_CT_NETLINK_MODULE) | ||
397 | |||
398 | #include <linux/netfilter/nfnetlink.h> | ||
399 | #include <linux/netfilter/nfnetlink_conntrack.h> | ||
400 | |||
401 | static int ipv4_tuple_to_nfattr(struct sk_buff *skb, | ||
402 | const struct nf_conntrack_tuple *tuple) | ||
403 | { | ||
404 | NFA_PUT(skb, CTA_IP_V4_SRC, sizeof(u_int32_t), | ||
405 | &tuple->src.u3.ip); | ||
406 | NFA_PUT(skb, CTA_IP_V4_DST, sizeof(u_int32_t), | ||
407 | &tuple->dst.u3.ip); | ||
408 | return 0; | ||
409 | |||
410 | nfattr_failure: | ||
411 | return -1; | ||
412 | } | ||
413 | |||
414 | static const size_t cta_min_ip[CTA_IP_MAX] = { | ||
415 | [CTA_IP_V4_SRC-1] = sizeof(u_int32_t), | ||
416 | [CTA_IP_V4_DST-1] = sizeof(u_int32_t), | ||
417 | }; | ||
418 | |||
419 | static int ipv4_nfattr_to_tuple(struct nfattr *tb[], | ||
420 | struct nf_conntrack_tuple *t) | ||
421 | { | ||
422 | if (!tb[CTA_IP_V4_SRC-1] || !tb[CTA_IP_V4_DST-1]) | ||
423 | return -EINVAL; | ||
424 | |||
425 | if (nfattr_bad_size(tb, CTA_IP_MAX, cta_min_ip)) | ||
426 | return -EINVAL; | ||
427 | |||
428 | t->src.u3.ip = | ||
429 | *(u_int32_t *)NFA_DATA(tb[CTA_IP_V4_SRC-1]); | ||
430 | t->dst.u3.ip = | ||
431 | *(u_int32_t *)NFA_DATA(tb[CTA_IP_V4_DST-1]); | ||
432 | |||
433 | return 0; | ||
434 | } | ||
435 | #endif | ||
436 | |||
395 | static struct nf_sockopt_ops so_getorigdst = { | 437 | static struct nf_sockopt_ops so_getorigdst = { |
396 | .pf = PF_INET, | 438 | .pf = PF_INET, |
397 | .get_optmin = SO_ORIGINAL_DST, | 439 | .get_optmin = SO_ORIGINAL_DST, |
@@ -408,6 +450,11 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 = { | |||
408 | .print_conntrack = ipv4_print_conntrack, | 450 | .print_conntrack = ipv4_print_conntrack, |
409 | .prepare = ipv4_prepare, | 451 | .prepare = ipv4_prepare, |
410 | .get_features = ipv4_get_features, | 452 | .get_features = ipv4_get_features, |
453 | #if defined(CONFIG_NF_CT_NETLINK) || \ | ||
454 | defined(CONFIG_NF_CT_NETLINK_MODULE) | ||
455 | .tuple_to_nfattr = ipv4_tuple_to_nfattr, | ||
456 | .nfattr_to_tuple = ipv4_nfattr_to_tuple, | ||
457 | #endif | ||
411 | .me = THIS_MODULE, | 458 | .me = THIS_MODULE, |
412 | }; | 459 | }; |
413 | 460 | ||
diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c index 7ddb5c08f7b8..52dc175be39a 100644 --- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c | |||
@@ -50,20 +50,21 @@ static int icmp_pkt_to_tuple(const struct sk_buff *skb, | |||
50 | return 1; | 50 | return 1; |
51 | } | 51 | } |
52 | 52 | ||
53 | /* Add 1; spaces filled with 0. */ | ||
54 | static const u_int8_t invmap[] = { | ||
55 | [ICMP_ECHO] = ICMP_ECHOREPLY + 1, | ||
56 | [ICMP_ECHOREPLY] = ICMP_ECHO + 1, | ||
57 | [ICMP_TIMESTAMP] = ICMP_TIMESTAMPREPLY + 1, | ||
58 | [ICMP_TIMESTAMPREPLY] = ICMP_TIMESTAMP + 1, | ||
59 | [ICMP_INFO_REQUEST] = ICMP_INFO_REPLY + 1, | ||
60 | [ICMP_INFO_REPLY] = ICMP_INFO_REQUEST + 1, | ||
61 | [ICMP_ADDRESS] = ICMP_ADDRESSREPLY + 1, | ||
62 | [ICMP_ADDRESSREPLY] = ICMP_ADDRESS + 1 | ||
63 | }; | ||
64 | |||
53 | static int icmp_invert_tuple(struct nf_conntrack_tuple *tuple, | 65 | static int icmp_invert_tuple(struct nf_conntrack_tuple *tuple, |
54 | const struct nf_conntrack_tuple *orig) | 66 | const struct nf_conntrack_tuple *orig) |
55 | { | 67 | { |
56 | /* Add 1; spaces filled with 0. */ | ||
57 | static u_int8_t invmap[] | ||
58 | = { [ICMP_ECHO] = ICMP_ECHOREPLY + 1, | ||
59 | [ICMP_ECHOREPLY] = ICMP_ECHO + 1, | ||
60 | [ICMP_TIMESTAMP] = ICMP_TIMESTAMPREPLY + 1, | ||
61 | [ICMP_TIMESTAMPREPLY] = ICMP_TIMESTAMP + 1, | ||
62 | [ICMP_INFO_REQUEST] = ICMP_INFO_REPLY + 1, | ||
63 | [ICMP_INFO_REPLY] = ICMP_INFO_REQUEST + 1, | ||
64 | [ICMP_ADDRESS] = ICMP_ADDRESSREPLY + 1, | ||
65 | [ICMP_ADDRESSREPLY] = ICMP_ADDRESS + 1}; | ||
66 | |||
67 | if (orig->dst.u.icmp.type >= sizeof(invmap) | 68 | if (orig->dst.u.icmp.type >= sizeof(invmap) |
68 | || !invmap[orig->dst.u.icmp.type]) | 69 | || !invmap[orig->dst.u.icmp.type]) |
69 | return 0; | 70 | return 0; |
@@ -120,11 +121,12 @@ static int icmp_packet(struct nf_conn *ct, | |||
120 | static int icmp_new(struct nf_conn *conntrack, | 121 | static int icmp_new(struct nf_conn *conntrack, |
121 | const struct sk_buff *skb, unsigned int dataoff) | 122 | const struct sk_buff *skb, unsigned int dataoff) |
122 | { | 123 | { |
123 | static u_int8_t valid_new[] | 124 | static const u_int8_t valid_new[] = { |
124 | = { [ICMP_ECHO] = 1, | 125 | [ICMP_ECHO] = 1, |
125 | [ICMP_TIMESTAMP] = 1, | 126 | [ICMP_TIMESTAMP] = 1, |
126 | [ICMP_INFO_REQUEST] = 1, | 127 | [ICMP_INFO_REQUEST] = 1, |
127 | [ICMP_ADDRESS] = 1 }; | 128 | [ICMP_ADDRESS] = 1 |
129 | }; | ||
128 | 130 | ||
129 | if (conntrack->tuplehash[0].tuple.dst.u.icmp.type >= sizeof(valid_new) | 131 | if (conntrack->tuplehash[0].tuple.dst.u.icmp.type >= sizeof(valid_new) |
130 | || !valid_new[conntrack->tuplehash[0].tuple.dst.u.icmp.type]) { | 132 | || !valid_new[conntrack->tuplehash[0].tuple.dst.u.icmp.type]) { |
@@ -168,7 +170,7 @@ icmp_error_message(struct sk_buff *skb, | |||
168 | return -NF_ACCEPT; | 170 | return -NF_ACCEPT; |
169 | } | 171 | } |
170 | 172 | ||
171 | innerproto = nf_ct_find_proto(PF_INET, inside->ip.protocol); | 173 | innerproto = __nf_ct_proto_find(PF_INET, inside->ip.protocol); |
172 | dataoff = skb->nh.iph->ihl*4 + sizeof(inside->icmp); | 174 | dataoff = skb->nh.iph->ihl*4 + sizeof(inside->icmp); |
173 | /* Are they talking about one of our connections? */ | 175 | /* Are they talking about one of our connections? */ |
174 | if (!nf_ct_get_tuple(skb, dataoff, dataoff + inside->ip.ihl*4, PF_INET, | 176 | if (!nf_ct_get_tuple(skb, dataoff, dataoff + inside->ip.ihl*4, PF_INET, |
@@ -281,6 +283,60 @@ checksum_skipped: | |||
281 | return icmp_error_message(skb, ctinfo, hooknum); | 283 | return icmp_error_message(skb, ctinfo, hooknum); |
282 | } | 284 | } |
283 | 285 | ||
286 | #if defined(CONFIG_NF_CT_NETLINK) || \ | ||
287 | defined(CONFIG_NF_CT_NETLINK_MODULE) | ||
288 | |||
289 | #include <linux/netfilter/nfnetlink.h> | ||
290 | #include <linux/netfilter/nfnetlink_conntrack.h> | ||
291 | |||
292 | static int icmp_tuple_to_nfattr(struct sk_buff *skb, | ||
293 | const struct nf_conntrack_tuple *t) | ||
294 | { | ||
295 | NFA_PUT(skb, CTA_PROTO_ICMP_ID, sizeof(u_int16_t), | ||
296 | &t->src.u.icmp.id); | ||
297 | NFA_PUT(skb, CTA_PROTO_ICMP_TYPE, sizeof(u_int8_t), | ||
298 | &t->dst.u.icmp.type); | ||
299 | NFA_PUT(skb, CTA_PROTO_ICMP_CODE, sizeof(u_int8_t), | ||
300 | &t->dst.u.icmp.code); | ||
301 | |||
302 | return 0; | ||
303 | |||
304 | nfattr_failure: | ||
305 | return -1; | ||
306 | } | ||
307 | |||
308 | static const size_t cta_min_proto[CTA_PROTO_MAX] = { | ||
309 | [CTA_PROTO_ICMP_TYPE-1] = sizeof(u_int8_t), | ||
310 | [CTA_PROTO_ICMP_CODE-1] = sizeof(u_int8_t), | ||
311 | [CTA_PROTO_ICMP_ID-1] = sizeof(u_int16_t) | ||
312 | }; | ||
313 | |||
314 | static int icmp_nfattr_to_tuple(struct nfattr *tb[], | ||
315 | struct nf_conntrack_tuple *tuple) | ||
316 | { | ||
317 | if (!tb[CTA_PROTO_ICMP_TYPE-1] | ||
318 | || !tb[CTA_PROTO_ICMP_CODE-1] | ||
319 | || !tb[CTA_PROTO_ICMP_ID-1]) | ||
320 | return -EINVAL; | ||
321 | |||
322 | if (nfattr_bad_size(tb, CTA_PROTO_MAX, cta_min_proto)) | ||
323 | return -EINVAL; | ||
324 | |||
325 | tuple->dst.u.icmp.type = | ||
326 | *(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMP_TYPE-1]); | ||
327 | tuple->dst.u.icmp.code = | ||
328 | *(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMP_CODE-1]); | ||
329 | tuple->src.u.icmp.id = | ||
330 | *(u_int16_t *)NFA_DATA(tb[CTA_PROTO_ICMP_ID-1]); | ||
331 | |||
332 | if (tuple->dst.u.icmp.type >= sizeof(invmap) | ||
333 | || !invmap[tuple->dst.u.icmp.type]) | ||
334 | return -EINVAL; | ||
335 | |||
336 | return 0; | ||
337 | } | ||
338 | #endif | ||
339 | |||
284 | struct nf_conntrack_protocol nf_conntrack_protocol_icmp = | 340 | struct nf_conntrack_protocol nf_conntrack_protocol_icmp = |
285 | { | 341 | { |
286 | .list = { NULL, NULL }, | 342 | .list = { NULL, NULL }, |
@@ -295,7 +351,12 @@ struct nf_conntrack_protocol nf_conntrack_protocol_icmp = | |||
295 | .new = icmp_new, | 351 | .new = icmp_new, |
296 | .error = icmp_error, | 352 | .error = icmp_error, |
297 | .destroy = NULL, | 353 | .destroy = NULL, |
298 | .me = NULL | 354 | .me = NULL, |
355 | #if defined(CONFIG_NF_CT_NETLINK) || \ | ||
356 | defined(CONFIG_NF_CT_NETLINK_MODULE) | ||
357 | .tuple_to_nfattr = icmp_tuple_to_nfattr, | ||
358 | .nfattr_to_tuple = icmp_nfattr_to_tuple, | ||
359 | #endif | ||
299 | }; | 360 | }; |
300 | 361 | ||
301 | EXPORT_SYMBOL(nf_conntrack_protocol_icmp); | 362 | EXPORT_SYMBOL(nf_conntrack_protocol_icmp); |