diff options
author | David S. Miller <davem@davemloft.net> | 2010-10-21 11:21:34 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-10-21 11:21:34 -0400 |
commit | 9941fb62762253774cc6177d0b9172ece5133fe1 (patch) | |
tree | 641fc2b376e2f84c7023aa0cd8b9d76f954cc3a1 /net/ipv6 | |
parent | a5190b4eea1f1c53ee26b3d1176441cafa8e7f79 (diff) | |
parent | 3b1a1ce6f418cb7ab35eb55c8a6575987a524e30 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/kaber/nf-next-2.6
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/af_inet6.c | 3 | ||||
-rw-r--r-- | net/ipv6/datagram.c | 19 | ||||
-rw-r--r-- | net/ipv6/ipv6_sockglue.c | 23 | ||||
-rw-r--r-- | net/ipv6/netfilter/Kconfig | 4 | ||||
-rw-r--r-- | net/ipv6/netfilter/Makefile | 5 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6_tables.c | 84 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6t_LOG.c | 157 | ||||
-rw-r--r-- | net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 78 | ||||
-rw-r--r-- | net/ipv6/netfilter/nf_conntrack_reasm.c | 14 | ||||
-rw-r--r-- | net/ipv6/netfilter/nf_defrag_ipv6_hooks.c | 131 | ||||
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 12 | ||||
-rw-r--r-- | net/ipv6/udp.c | 16 |
12 files changed, 337 insertions, 209 deletions
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 60220985bb80..54e8e42f7a88 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -343,7 +343,8 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
343 | */ | 343 | */ |
344 | v4addr = LOOPBACK4_IPV6; | 344 | v4addr = LOOPBACK4_IPV6; |
345 | if (!(addr_type & IPV6_ADDR_MULTICAST)) { | 345 | if (!(addr_type & IPV6_ADDR_MULTICAST)) { |
346 | if (!ipv6_chk_addr(net, &addr->sin6_addr, | 346 | if (!inet->transparent && |
347 | !ipv6_chk_addr(net, &addr->sin6_addr, | ||
347 | dev, 0)) { | 348 | dev, 0)) { |
348 | err = -EADDRNOTAVAIL; | 349 | err = -EADDRNOTAVAIL; |
349 | goto out_unlock; | 350 | goto out_unlock; |
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index ef371aa01ac5..320bdb877eed 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c | |||
@@ -577,6 +577,25 @@ int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb) | |||
577 | u8 *ptr = nh + opt->dst1; | 577 | u8 *ptr = nh + opt->dst1; |
578 | put_cmsg(msg, SOL_IPV6, IPV6_2292DSTOPTS, (ptr[1]+1)<<3, ptr); | 578 | put_cmsg(msg, SOL_IPV6, IPV6_2292DSTOPTS, (ptr[1]+1)<<3, ptr); |
579 | } | 579 | } |
580 | if (np->rxopt.bits.rxorigdstaddr) { | ||
581 | struct sockaddr_in6 sin6; | ||
582 | u16 *ports = (u16 *) skb_transport_header(skb); | ||
583 | |||
584 | if (skb_transport_offset(skb) + 4 <= skb->len) { | ||
585 | /* All current transport protocols have the port numbers in the | ||
586 | * first four bytes of the transport header and this function is | ||
587 | * written with this assumption in mind. | ||
588 | */ | ||
589 | |||
590 | sin6.sin6_family = AF_INET6; | ||
591 | ipv6_addr_copy(&sin6.sin6_addr, &ipv6_hdr(skb)->daddr); | ||
592 | sin6.sin6_port = ports[1]; | ||
593 | sin6.sin6_flowinfo = 0; | ||
594 | sin6.sin6_scope_id = 0; | ||
595 | |||
596 | put_cmsg(msg, SOL_IPV6, IPV6_ORIGDSTADDR, sizeof(sin6), &sin6); | ||
597 | } | ||
598 | } | ||
580 | return 0; | 599 | return 0; |
581 | } | 600 | } |
582 | 601 | ||
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index a7f66bc8f0b0..0553867a317f 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c | |||
@@ -342,6 +342,21 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, | |||
342 | retv = 0; | 342 | retv = 0; |
343 | break; | 343 | break; |
344 | 344 | ||
345 | case IPV6_TRANSPARENT: | ||
346 | if (optlen < sizeof(int)) | ||
347 | goto e_inval; | ||
348 | /* we don't have a separate transparent bit for IPV6 we use the one in the IPv4 socket */ | ||
349 | inet_sk(sk)->transparent = valbool; | ||
350 | retv = 0; | ||
351 | break; | ||
352 | |||
353 | case IPV6_RECVORIGDSTADDR: | ||
354 | if (optlen < sizeof(int)) | ||
355 | goto e_inval; | ||
356 | np->rxopt.bits.rxorigdstaddr = valbool; | ||
357 | retv = 0; | ||
358 | break; | ||
359 | |||
345 | case IPV6_HOPOPTS: | 360 | case IPV6_HOPOPTS: |
346 | case IPV6_RTHDRDSTOPTS: | 361 | case IPV6_RTHDRDSTOPTS: |
347 | case IPV6_RTHDR: | 362 | case IPV6_RTHDR: |
@@ -1104,6 +1119,14 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
1104 | break; | 1119 | break; |
1105 | } | 1120 | } |
1106 | 1121 | ||
1122 | case IPV6_TRANSPARENT: | ||
1123 | val = inet_sk(sk)->transparent; | ||
1124 | break; | ||
1125 | |||
1126 | case IPV6_RECVORIGDSTADDR: | ||
1127 | val = np->rxopt.bits.rxorigdstaddr; | ||
1128 | break; | ||
1129 | |||
1107 | case IPV6_UNICAST_HOPS: | 1130 | case IPV6_UNICAST_HOPS: |
1108 | case IPV6_MULTICAST_HOPS: | 1131 | case IPV6_MULTICAST_HOPS: |
1109 | { | 1132 | { |
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig index 29d643bcafa4..44d2eeac089b 100644 --- a/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig | |||
@@ -132,10 +132,10 @@ config IP6_NF_MATCH_RT | |||
132 | # The targets | 132 | # The targets |
133 | config IP6_NF_TARGET_HL | 133 | config IP6_NF_TARGET_HL |
134 | tristate '"HL" hoplimit target support' | 134 | tristate '"HL" hoplimit target support' |
135 | depends on NETFILTER_ADVANCED | 135 | depends on NETFILTER_ADVANCED && IP6_NF_MANGLE |
136 | select NETFILTER_XT_TARGET_HL | 136 | select NETFILTER_XT_TARGET_HL |
137 | ---help--- | 137 | ---help--- |
138 | This is a backwards-compat option for the user's convenience | 138 | This is a backwards-compatible option for the user's convenience |
139 | (e.g. when running oldconfig). It selects | 139 | (e.g. when running oldconfig). It selects |
140 | CONFIG_NETFILTER_XT_TARGET_HL. | 140 | CONFIG_NETFILTER_XT_TARGET_HL. |
141 | 141 | ||
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile index aafbba30c899..3f8e4a3d83ce 100644 --- a/net/ipv6/netfilter/Makefile +++ b/net/ipv6/netfilter/Makefile | |||
@@ -11,10 +11,11 @@ obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o | |||
11 | obj-$(CONFIG_IP6_NF_SECURITY) += ip6table_security.o | 11 | obj-$(CONFIG_IP6_NF_SECURITY) += ip6table_security.o |
12 | 12 | ||
13 | # objects for l3 independent conntrack | 13 | # objects for l3 independent conntrack |
14 | nf_conntrack_ipv6-objs := nf_conntrack_l3proto_ipv6.o nf_conntrack_proto_icmpv6.o nf_conntrack_reasm.o | 14 | nf_conntrack_ipv6-objs := nf_conntrack_l3proto_ipv6.o nf_conntrack_proto_icmpv6.o |
15 | nf_defrag_ipv6-objs := nf_defrag_ipv6_hooks.o nf_conntrack_reasm.o | ||
15 | 16 | ||
16 | # l3 independent conntrack | 17 | # l3 independent conntrack |
17 | obj-$(CONFIG_NF_CONNTRACK_IPV6) += nf_conntrack_ipv6.o | 18 | obj-$(CONFIG_NF_CONNTRACK_IPV6) += nf_conntrack_ipv6.o nf_defrag_ipv6.o |
18 | 19 | ||
19 | # matches | 20 | # matches |
20 | obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o | 21 | obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o |
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 6b331e9b5706..51df035897e7 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
@@ -215,7 +215,7 @@ static inline bool unconditional(const struct ip6t_ip6 *ipv6) | |||
215 | return memcmp(ipv6, &uncond, sizeof(uncond)) == 0; | 215 | return memcmp(ipv6, &uncond, sizeof(uncond)) == 0; |
216 | } | 216 | } |
217 | 217 | ||
218 | static inline const struct ip6t_entry_target * | 218 | static inline const struct xt_entry_target * |
219 | ip6t_get_target_c(const struct ip6t_entry *e) | 219 | ip6t_get_target_c(const struct ip6t_entry *e) |
220 | { | 220 | { |
221 | return ip6t_get_target((struct ip6t_entry *)e); | 221 | return ip6t_get_target((struct ip6t_entry *)e); |
@@ -260,9 +260,9 @@ get_chainname_rulenum(const struct ip6t_entry *s, const struct ip6t_entry *e, | |||
260 | const char *hookname, const char **chainname, | 260 | const char *hookname, const char **chainname, |
261 | const char **comment, unsigned int *rulenum) | 261 | const char **comment, unsigned int *rulenum) |
262 | { | 262 | { |
263 | const struct ip6t_standard_target *t = (void *)ip6t_get_target_c(s); | 263 | const struct xt_standard_target *t = (void *)ip6t_get_target_c(s); |
264 | 264 | ||
265 | if (strcmp(t->target.u.kernel.target->name, IP6T_ERROR_TARGET) == 0) { | 265 | if (strcmp(t->target.u.kernel.target->name, XT_ERROR_TARGET) == 0) { |
266 | /* Head of user chain: ERROR target with chainname */ | 266 | /* Head of user chain: ERROR target with chainname */ |
267 | *chainname = t->target.data; | 267 | *chainname = t->target.data; |
268 | (*rulenum) = 0; | 268 | (*rulenum) = 0; |
@@ -271,7 +271,7 @@ get_chainname_rulenum(const struct ip6t_entry *s, const struct ip6t_entry *e, | |||
271 | 271 | ||
272 | if (s->target_offset == sizeof(struct ip6t_entry) && | 272 | if (s->target_offset == sizeof(struct ip6t_entry) && |
273 | strcmp(t->target.u.kernel.target->name, | 273 | strcmp(t->target.u.kernel.target->name, |
274 | IP6T_STANDARD_TARGET) == 0 && | 274 | XT_STANDARD_TARGET) == 0 && |
275 | t->verdict < 0 && | 275 | t->verdict < 0 && |
276 | unconditional(&s->ipv6)) { | 276 | unconditional(&s->ipv6)) { |
277 | /* Tail of chains: STANDARD target (return/policy) */ | 277 | /* Tail of chains: STANDARD target (return/policy) */ |
@@ -369,7 +369,7 @@ ip6t_do_table(struct sk_buff *skb, | |||
369 | e = get_entry(table_base, private->hook_entry[hook]); | 369 | e = get_entry(table_base, private->hook_entry[hook]); |
370 | 370 | ||
371 | do { | 371 | do { |
372 | const struct ip6t_entry_target *t; | 372 | const struct xt_entry_target *t; |
373 | const struct xt_entry_match *ematch; | 373 | const struct xt_entry_match *ematch; |
374 | 374 | ||
375 | IP_NF_ASSERT(e); | 375 | IP_NF_ASSERT(e); |
@@ -403,10 +403,10 @@ ip6t_do_table(struct sk_buff *skb, | |||
403 | if (!t->u.kernel.target->target) { | 403 | if (!t->u.kernel.target->target) { |
404 | int v; | 404 | int v; |
405 | 405 | ||
406 | v = ((struct ip6t_standard_target *)t)->verdict; | 406 | v = ((struct xt_standard_target *)t)->verdict; |
407 | if (v < 0) { | 407 | if (v < 0) { |
408 | /* Pop from stack? */ | 408 | /* Pop from stack? */ |
409 | if (v != IP6T_RETURN) { | 409 | if (v != XT_RETURN) { |
410 | verdict = (unsigned)(-v) - 1; | 410 | verdict = (unsigned)(-v) - 1; |
411 | break; | 411 | break; |
412 | } | 412 | } |
@@ -434,7 +434,7 @@ ip6t_do_table(struct sk_buff *skb, | |||
434 | acpar.targinfo = t->data; | 434 | acpar.targinfo = t->data; |
435 | 435 | ||
436 | verdict = t->u.kernel.target->target(skb, &acpar); | 436 | verdict = t->u.kernel.target->target(skb, &acpar); |
437 | if (verdict == IP6T_CONTINUE) | 437 | if (verdict == XT_CONTINUE) |
438 | e = ip6t_next_entry(e); | 438 | e = ip6t_next_entry(e); |
439 | else | 439 | else |
440 | /* Verdict */ | 440 | /* Verdict */ |
@@ -474,7 +474,7 @@ mark_source_chains(const struct xt_table_info *newinfo, | |||
474 | e->counters.pcnt = pos; | 474 | e->counters.pcnt = pos; |
475 | 475 | ||
476 | for (;;) { | 476 | for (;;) { |
477 | const struct ip6t_standard_target *t | 477 | const struct xt_standard_target *t |
478 | = (void *)ip6t_get_target_c(e); | 478 | = (void *)ip6t_get_target_c(e); |
479 | int visited = e->comefrom & (1 << hook); | 479 | int visited = e->comefrom & (1 << hook); |
480 | 480 | ||
@@ -488,13 +488,13 @@ mark_source_chains(const struct xt_table_info *newinfo, | |||
488 | /* Unconditional return/END. */ | 488 | /* Unconditional return/END. */ |
489 | if ((e->target_offset == sizeof(struct ip6t_entry) && | 489 | if ((e->target_offset == sizeof(struct ip6t_entry) && |
490 | (strcmp(t->target.u.user.name, | 490 | (strcmp(t->target.u.user.name, |
491 | IP6T_STANDARD_TARGET) == 0) && | 491 | XT_STANDARD_TARGET) == 0) && |
492 | t->verdict < 0 && | 492 | t->verdict < 0 && |
493 | unconditional(&e->ipv6)) || visited) { | 493 | unconditional(&e->ipv6)) || visited) { |
494 | unsigned int oldpos, size; | 494 | unsigned int oldpos, size; |
495 | 495 | ||
496 | if ((strcmp(t->target.u.user.name, | 496 | if ((strcmp(t->target.u.user.name, |
497 | IP6T_STANDARD_TARGET) == 0) && | 497 | XT_STANDARD_TARGET) == 0) && |
498 | t->verdict < -NF_MAX_VERDICT - 1) { | 498 | t->verdict < -NF_MAX_VERDICT - 1) { |
499 | duprintf("mark_source_chains: bad " | 499 | duprintf("mark_source_chains: bad " |
500 | "negative verdict (%i)\n", | 500 | "negative verdict (%i)\n", |
@@ -537,7 +537,7 @@ mark_source_chains(const struct xt_table_info *newinfo, | |||
537 | int newpos = t->verdict; | 537 | int newpos = t->verdict; |
538 | 538 | ||
539 | if (strcmp(t->target.u.user.name, | 539 | if (strcmp(t->target.u.user.name, |
540 | IP6T_STANDARD_TARGET) == 0 && | 540 | XT_STANDARD_TARGET) == 0 && |
541 | newpos >= 0) { | 541 | newpos >= 0) { |
542 | if (newpos > newinfo->size - | 542 | if (newpos > newinfo->size - |
543 | sizeof(struct ip6t_entry)) { | 543 | sizeof(struct ip6t_entry)) { |
@@ -565,7 +565,7 @@ mark_source_chains(const struct xt_table_info *newinfo, | |||
565 | return 1; | 565 | return 1; |
566 | } | 566 | } |
567 | 567 | ||
568 | static void cleanup_match(struct ip6t_entry_match *m, struct net *net) | 568 | static void cleanup_match(struct xt_entry_match *m, struct net *net) |
569 | { | 569 | { |
570 | struct xt_mtdtor_param par; | 570 | struct xt_mtdtor_param par; |
571 | 571 | ||
@@ -581,14 +581,14 @@ static void cleanup_match(struct ip6t_entry_match *m, struct net *net) | |||
581 | static int | 581 | static int |
582 | check_entry(const struct ip6t_entry *e, const char *name) | 582 | check_entry(const struct ip6t_entry *e, const char *name) |
583 | { | 583 | { |
584 | const struct ip6t_entry_target *t; | 584 | const struct xt_entry_target *t; |
585 | 585 | ||
586 | if (!ip6_checkentry(&e->ipv6)) { | 586 | if (!ip6_checkentry(&e->ipv6)) { |
587 | duprintf("ip_tables: ip check failed %p %s.\n", e, name); | 587 | duprintf("ip_tables: ip check failed %p %s.\n", e, name); |
588 | return -EINVAL; | 588 | return -EINVAL; |
589 | } | 589 | } |
590 | 590 | ||
591 | if (e->target_offset + sizeof(struct ip6t_entry_target) > | 591 | if (e->target_offset + sizeof(struct xt_entry_target) > |
592 | e->next_offset) | 592 | e->next_offset) |
593 | return -EINVAL; | 593 | return -EINVAL; |
594 | 594 | ||
@@ -599,7 +599,7 @@ check_entry(const struct ip6t_entry *e, const char *name) | |||
599 | return 0; | 599 | return 0; |
600 | } | 600 | } |
601 | 601 | ||
602 | static int check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par) | 602 | static int check_match(struct xt_entry_match *m, struct xt_mtchk_param *par) |
603 | { | 603 | { |
604 | const struct ip6t_ip6 *ipv6 = par->entryinfo; | 604 | const struct ip6t_ip6 *ipv6 = par->entryinfo; |
605 | int ret; | 605 | int ret; |
@@ -618,7 +618,7 @@ static int check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par) | |||
618 | } | 618 | } |
619 | 619 | ||
620 | static int | 620 | static int |
621 | find_check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par) | 621 | find_check_match(struct xt_entry_match *m, struct xt_mtchk_param *par) |
622 | { | 622 | { |
623 | struct xt_match *match; | 623 | struct xt_match *match; |
624 | int ret; | 624 | int ret; |
@@ -643,7 +643,7 @@ err: | |||
643 | 643 | ||
644 | static int check_target(struct ip6t_entry *e, struct net *net, const char *name) | 644 | static int check_target(struct ip6t_entry *e, struct net *net, const char *name) |
645 | { | 645 | { |
646 | struct ip6t_entry_target *t = ip6t_get_target(e); | 646 | struct xt_entry_target *t = ip6t_get_target(e); |
647 | struct xt_tgchk_param par = { | 647 | struct xt_tgchk_param par = { |
648 | .net = net, | 648 | .net = net, |
649 | .table = name, | 649 | .table = name, |
@@ -670,7 +670,7 @@ static int | |||
670 | find_check_entry(struct ip6t_entry *e, struct net *net, const char *name, | 670 | find_check_entry(struct ip6t_entry *e, struct net *net, const char *name, |
671 | unsigned int size) | 671 | unsigned int size) |
672 | { | 672 | { |
673 | struct ip6t_entry_target *t; | 673 | struct xt_entry_target *t; |
674 | struct xt_target *target; | 674 | struct xt_target *target; |
675 | int ret; | 675 | int ret; |
676 | unsigned int j; | 676 | unsigned int j; |
@@ -721,7 +721,7 @@ find_check_entry(struct ip6t_entry *e, struct net *net, const char *name, | |||
721 | 721 | ||
722 | static bool check_underflow(const struct ip6t_entry *e) | 722 | static bool check_underflow(const struct ip6t_entry *e) |
723 | { | 723 | { |
724 | const struct ip6t_entry_target *t; | 724 | const struct xt_entry_target *t; |
725 | unsigned int verdict; | 725 | unsigned int verdict; |
726 | 726 | ||
727 | if (!unconditional(&e->ipv6)) | 727 | if (!unconditional(&e->ipv6)) |
@@ -729,7 +729,7 @@ static bool check_underflow(const struct ip6t_entry *e) | |||
729 | t = ip6t_get_target_c(e); | 729 | t = ip6t_get_target_c(e); |
730 | if (strcmp(t->u.user.name, XT_STANDARD_TARGET) != 0) | 730 | if (strcmp(t->u.user.name, XT_STANDARD_TARGET) != 0) |
731 | return false; | 731 | return false; |
732 | verdict = ((struct ip6t_standard_target *)t)->verdict; | 732 | verdict = ((struct xt_standard_target *)t)->verdict; |
733 | verdict = -verdict - 1; | 733 | verdict = -verdict - 1; |
734 | return verdict == NF_DROP || verdict == NF_ACCEPT; | 734 | return verdict == NF_DROP || verdict == NF_ACCEPT; |
735 | } | 735 | } |
@@ -752,7 +752,7 @@ check_entry_size_and_hooks(struct ip6t_entry *e, | |||
752 | } | 752 | } |
753 | 753 | ||
754 | if (e->next_offset | 754 | if (e->next_offset |
755 | < sizeof(struct ip6t_entry) + sizeof(struct ip6t_entry_target)) { | 755 | < sizeof(struct ip6t_entry) + sizeof(struct xt_entry_target)) { |
756 | duprintf("checking: element %p size %u\n", | 756 | duprintf("checking: element %p size %u\n", |
757 | e, e->next_offset); | 757 | e, e->next_offset); |
758 | return -EINVAL; | 758 | return -EINVAL; |
@@ -784,7 +784,7 @@ check_entry_size_and_hooks(struct ip6t_entry *e, | |||
784 | static void cleanup_entry(struct ip6t_entry *e, struct net *net) | 784 | static void cleanup_entry(struct ip6t_entry *e, struct net *net) |
785 | { | 785 | { |
786 | struct xt_tgdtor_param par; | 786 | struct xt_tgdtor_param par; |
787 | struct ip6t_entry_target *t; | 787 | struct xt_entry_target *t; |
788 | struct xt_entry_match *ematch; | 788 | struct xt_entry_match *ematch; |
789 | 789 | ||
790 | /* Cleanup all matches */ | 790 | /* Cleanup all matches */ |
@@ -985,8 +985,8 @@ copy_entries_to_user(unsigned int total_size, | |||
985 | /* ... then go back and fix counters and names */ | 985 | /* ... then go back and fix counters and names */ |
986 | for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){ | 986 | for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){ |
987 | unsigned int i; | 987 | unsigned int i; |
988 | const struct ip6t_entry_match *m; | 988 | const struct xt_entry_match *m; |
989 | const struct ip6t_entry_target *t; | 989 | const struct xt_entry_target *t; |
990 | 990 | ||
991 | e = (struct ip6t_entry *)(loc_cpu_entry + off); | 991 | e = (struct ip6t_entry *)(loc_cpu_entry + off); |
992 | if (copy_to_user(userptr + off | 992 | if (copy_to_user(userptr + off |
@@ -1003,7 +1003,7 @@ copy_entries_to_user(unsigned int total_size, | |||
1003 | m = (void *)e + i; | 1003 | m = (void *)e + i; |
1004 | 1004 | ||
1005 | if (copy_to_user(userptr + off + i | 1005 | if (copy_to_user(userptr + off + i |
1006 | + offsetof(struct ip6t_entry_match, | 1006 | + offsetof(struct xt_entry_match, |
1007 | u.user.name), | 1007 | u.user.name), |
1008 | m->u.kernel.match->name, | 1008 | m->u.kernel.match->name, |
1009 | strlen(m->u.kernel.match->name)+1) | 1009 | strlen(m->u.kernel.match->name)+1) |
@@ -1015,7 +1015,7 @@ copy_entries_to_user(unsigned int total_size, | |||
1015 | 1015 | ||
1016 | t = ip6t_get_target_c(e); | 1016 | t = ip6t_get_target_c(e); |
1017 | if (copy_to_user(userptr + off + e->target_offset | 1017 | if (copy_to_user(userptr + off + e->target_offset |
1018 | + offsetof(struct ip6t_entry_target, | 1018 | + offsetof(struct xt_entry_target, |
1019 | u.user.name), | 1019 | u.user.name), |
1020 | t->u.kernel.target->name, | 1020 | t->u.kernel.target->name, |
1021 | strlen(t->u.kernel.target->name)+1) != 0) { | 1021 | strlen(t->u.kernel.target->name)+1) != 0) { |
@@ -1053,7 +1053,7 @@ static int compat_calc_entry(const struct ip6t_entry *e, | |||
1053 | const void *base, struct xt_table_info *newinfo) | 1053 | const void *base, struct xt_table_info *newinfo) |
1054 | { | 1054 | { |
1055 | const struct xt_entry_match *ematch; | 1055 | const struct xt_entry_match *ematch; |
1056 | const struct ip6t_entry_target *t; | 1056 | const struct xt_entry_target *t; |
1057 | unsigned int entry_offset; | 1057 | unsigned int entry_offset; |
1058 | int off, i, ret; | 1058 | int off, i, ret; |
1059 | 1059 | ||
@@ -1105,7 +1105,7 @@ static int compat_table_info(const struct xt_table_info *info, | |||
1105 | static int get_info(struct net *net, void __user *user, | 1105 | static int get_info(struct net *net, void __user *user, |
1106 | const int *len, int compat) | 1106 | const int *len, int compat) |
1107 | { | 1107 | { |
1108 | char name[IP6T_TABLE_MAXNAMELEN]; | 1108 | char name[XT_TABLE_MAXNAMELEN]; |
1109 | struct xt_table *t; | 1109 | struct xt_table *t; |
1110 | int ret; | 1110 | int ret; |
1111 | 1111 | ||
@@ -1118,7 +1118,7 @@ static int get_info(struct net *net, void __user *user, | |||
1118 | if (copy_from_user(name, user, sizeof(name)) != 0) | 1118 | if (copy_from_user(name, user, sizeof(name)) != 0) |
1119 | return -EFAULT; | 1119 | return -EFAULT; |
1120 | 1120 | ||
1121 | name[IP6T_TABLE_MAXNAMELEN-1] = '\0'; | 1121 | name[XT_TABLE_MAXNAMELEN-1] = '\0'; |
1122 | #ifdef CONFIG_COMPAT | 1122 | #ifdef CONFIG_COMPAT |
1123 | if (compat) | 1123 | if (compat) |
1124 | xt_compat_lock(AF_INET6); | 1124 | xt_compat_lock(AF_INET6); |
@@ -1415,14 +1415,14 @@ do_add_counters(struct net *net, const void __user *user, unsigned int len, | |||
1415 | 1415 | ||
1416 | #ifdef CONFIG_COMPAT | 1416 | #ifdef CONFIG_COMPAT |
1417 | struct compat_ip6t_replace { | 1417 | struct compat_ip6t_replace { |
1418 | char name[IP6T_TABLE_MAXNAMELEN]; | 1418 | char name[XT_TABLE_MAXNAMELEN]; |
1419 | u32 valid_hooks; | 1419 | u32 valid_hooks; |
1420 | u32 num_entries; | 1420 | u32 num_entries; |
1421 | u32 size; | 1421 | u32 size; |
1422 | u32 hook_entry[NF_INET_NUMHOOKS]; | 1422 | u32 hook_entry[NF_INET_NUMHOOKS]; |
1423 | u32 underflow[NF_INET_NUMHOOKS]; | 1423 | u32 underflow[NF_INET_NUMHOOKS]; |
1424 | u32 num_counters; | 1424 | u32 num_counters; |
1425 | compat_uptr_t counters; /* struct ip6t_counters * */ | 1425 | compat_uptr_t counters; /* struct xt_counters * */ |
1426 | struct compat_ip6t_entry entries[0]; | 1426 | struct compat_ip6t_entry entries[0]; |
1427 | }; | 1427 | }; |
1428 | 1428 | ||
@@ -1431,7 +1431,7 @@ compat_copy_entry_to_user(struct ip6t_entry *e, void __user **dstptr, | |||
1431 | unsigned int *size, struct xt_counters *counters, | 1431 | unsigned int *size, struct xt_counters *counters, |
1432 | unsigned int i) | 1432 | unsigned int i) |
1433 | { | 1433 | { |
1434 | struct ip6t_entry_target *t; | 1434 | struct xt_entry_target *t; |
1435 | struct compat_ip6t_entry __user *ce; | 1435 | struct compat_ip6t_entry __user *ce; |
1436 | u_int16_t target_offset, next_offset; | 1436 | u_int16_t target_offset, next_offset; |
1437 | compat_uint_t origsize; | 1437 | compat_uint_t origsize; |
@@ -1466,7 +1466,7 @@ compat_copy_entry_to_user(struct ip6t_entry *e, void __user **dstptr, | |||
1466 | } | 1466 | } |
1467 | 1467 | ||
1468 | static int | 1468 | static int |
1469 | compat_find_calc_match(struct ip6t_entry_match *m, | 1469 | compat_find_calc_match(struct xt_entry_match *m, |
1470 | const char *name, | 1470 | const char *name, |
1471 | const struct ip6t_ip6 *ipv6, | 1471 | const struct ip6t_ip6 *ipv6, |
1472 | unsigned int hookmask, | 1472 | unsigned int hookmask, |
@@ -1488,7 +1488,7 @@ compat_find_calc_match(struct ip6t_entry_match *m, | |||
1488 | 1488 | ||
1489 | static void compat_release_entry(struct compat_ip6t_entry *e) | 1489 | static void compat_release_entry(struct compat_ip6t_entry *e) |
1490 | { | 1490 | { |
1491 | struct ip6t_entry_target *t; | 1491 | struct xt_entry_target *t; |
1492 | struct xt_entry_match *ematch; | 1492 | struct xt_entry_match *ematch; |
1493 | 1493 | ||
1494 | /* Cleanup all matches */ | 1494 | /* Cleanup all matches */ |
@@ -1509,7 +1509,7 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e, | |||
1509 | const char *name) | 1509 | const char *name) |
1510 | { | 1510 | { |
1511 | struct xt_entry_match *ematch; | 1511 | struct xt_entry_match *ematch; |
1512 | struct ip6t_entry_target *t; | 1512 | struct xt_entry_target *t; |
1513 | struct xt_target *target; | 1513 | struct xt_target *target; |
1514 | unsigned int entry_offset; | 1514 | unsigned int entry_offset; |
1515 | unsigned int j; | 1515 | unsigned int j; |
@@ -1591,7 +1591,7 @@ compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr, | |||
1591 | unsigned int *size, const char *name, | 1591 | unsigned int *size, const char *name, |
1592 | struct xt_table_info *newinfo, unsigned char *base) | 1592 | struct xt_table_info *newinfo, unsigned char *base) |
1593 | { | 1593 | { |
1594 | struct ip6t_entry_target *t; | 1594 | struct xt_entry_target *t; |
1595 | struct xt_target *target; | 1595 | struct xt_target *target; |
1596 | struct ip6t_entry *de; | 1596 | struct ip6t_entry *de; |
1597 | unsigned int origsize; | 1597 | unsigned int origsize; |
@@ -1899,7 +1899,7 @@ compat_do_ip6t_set_ctl(struct sock *sk, int cmd, void __user *user, | |||
1899 | } | 1899 | } |
1900 | 1900 | ||
1901 | struct compat_ip6t_get_entries { | 1901 | struct compat_ip6t_get_entries { |
1902 | char name[IP6T_TABLE_MAXNAMELEN]; | 1902 | char name[XT_TABLE_MAXNAMELEN]; |
1903 | compat_uint_t size; | 1903 | compat_uint_t size; |
1904 | struct compat_ip6t_entry entrytable[0]; | 1904 | struct compat_ip6t_entry entrytable[0]; |
1905 | }; | 1905 | }; |
@@ -2054,7 +2054,7 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
2054 | 2054 | ||
2055 | case IP6T_SO_GET_REVISION_MATCH: | 2055 | case IP6T_SO_GET_REVISION_MATCH: |
2056 | case IP6T_SO_GET_REVISION_TARGET: { | 2056 | case IP6T_SO_GET_REVISION_TARGET: { |
2057 | struct ip6t_get_revision rev; | 2057 | struct xt_get_revision rev; |
2058 | int target; | 2058 | int target; |
2059 | 2059 | ||
2060 | if (*len != sizeof(rev)) { | 2060 | if (*len != sizeof(rev)) { |
@@ -2191,7 +2191,7 @@ static int icmp6_checkentry(const struct xt_mtchk_param *par) | |||
2191 | /* The built-in targets: standard (NULL) and error. */ | 2191 | /* The built-in targets: standard (NULL) and error. */ |
2192 | static struct xt_target ip6t_builtin_tg[] __read_mostly = { | 2192 | static struct xt_target ip6t_builtin_tg[] __read_mostly = { |
2193 | { | 2193 | { |
2194 | .name = IP6T_STANDARD_TARGET, | 2194 | .name = XT_STANDARD_TARGET, |
2195 | .targetsize = sizeof(int), | 2195 | .targetsize = sizeof(int), |
2196 | .family = NFPROTO_IPV6, | 2196 | .family = NFPROTO_IPV6, |
2197 | #ifdef CONFIG_COMPAT | 2197 | #ifdef CONFIG_COMPAT |
@@ -2201,9 +2201,9 @@ static struct xt_target ip6t_builtin_tg[] __read_mostly = { | |||
2201 | #endif | 2201 | #endif |
2202 | }, | 2202 | }, |
2203 | { | 2203 | { |
2204 | .name = IP6T_ERROR_TARGET, | 2204 | .name = XT_ERROR_TARGET, |
2205 | .target = ip6t_error, | 2205 | .target = ip6t_error, |
2206 | .targetsize = IP6T_FUNCTION_MAXNAMELEN, | 2206 | .targetsize = XT_FUNCTION_MAXNAMELEN, |
2207 | .family = NFPROTO_IPV6, | 2207 | .family = NFPROTO_IPV6, |
2208 | }, | 2208 | }, |
2209 | }; | 2209 | }; |
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c index 0a07ae7b933f..09c88891a753 100644 --- a/net/ipv6/netfilter/ip6t_LOG.c +++ b/net/ipv6/netfilter/ip6t_LOG.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/netfilter/x_tables.h> | 23 | #include <linux/netfilter/x_tables.h> |
24 | #include <linux/netfilter_ipv6/ip6_tables.h> | 24 | #include <linux/netfilter_ipv6/ip6_tables.h> |
25 | #include <net/netfilter/nf_log.h> | 25 | #include <net/netfilter/nf_log.h> |
26 | #include <net/netfilter/xt_log.h> | ||
26 | 27 | ||
27 | MODULE_AUTHOR("Jan Rekorajski <baggins@pld.org.pl>"); | 28 | MODULE_AUTHOR("Jan Rekorajski <baggins@pld.org.pl>"); |
28 | MODULE_DESCRIPTION("Xtables: IPv6 packet logging to syslog"); | 29 | MODULE_DESCRIPTION("Xtables: IPv6 packet logging to syslog"); |
@@ -32,11 +33,9 @@ struct in_device; | |||
32 | #include <net/route.h> | 33 | #include <net/route.h> |
33 | #include <linux/netfilter_ipv6/ip6t_LOG.h> | 34 | #include <linux/netfilter_ipv6/ip6t_LOG.h> |
34 | 35 | ||
35 | /* Use lock to serialize, so printks don't overlap */ | ||
36 | static DEFINE_SPINLOCK(log_lock); | ||
37 | |||
38 | /* One level of recursion won't kill us */ | 36 | /* One level of recursion won't kill us */ |
39 | static void dump_packet(const struct nf_loginfo *info, | 37 | static void dump_packet(struct sbuff *m, |
38 | const struct nf_loginfo *info, | ||
40 | const struct sk_buff *skb, unsigned int ip6hoff, | 39 | const struct sk_buff *skb, unsigned int ip6hoff, |
41 | int recurse) | 40 | int recurse) |
42 | { | 41 | { |
@@ -55,15 +54,15 @@ static void dump_packet(const struct nf_loginfo *info, | |||
55 | 54 | ||
56 | ih = skb_header_pointer(skb, ip6hoff, sizeof(_ip6h), &_ip6h); | 55 | ih = skb_header_pointer(skb, ip6hoff, sizeof(_ip6h), &_ip6h); |
57 | if (ih == NULL) { | 56 | if (ih == NULL) { |
58 | printk("TRUNCATED"); | 57 | sb_add(m, "TRUNCATED"); |
59 | return; | 58 | return; |
60 | } | 59 | } |
61 | 60 | ||
62 | /* Max length: 88 "SRC=0000.0000.0000.0000.0000.0000.0000.0000 DST=0000.0000.0000.0000.0000.0000.0000.0000 " */ | 61 | /* Max length: 88 "SRC=0000.0000.0000.0000.0000.0000.0000.0000 DST=0000.0000.0000.0000.0000.0000.0000.0000 " */ |
63 | printk("SRC=%pI6 DST=%pI6 ", &ih->saddr, &ih->daddr); | 62 | sb_add(m, "SRC=%pI6 DST=%pI6 ", &ih->saddr, &ih->daddr); |
64 | 63 | ||
65 | /* Max length: 44 "LEN=65535 TC=255 HOPLIMIT=255 FLOWLBL=FFFFF " */ | 64 | /* Max length: 44 "LEN=65535 TC=255 HOPLIMIT=255 FLOWLBL=FFFFF " */ |
66 | printk("LEN=%Zu TC=%u HOPLIMIT=%u FLOWLBL=%u ", | 65 | sb_add(m, "LEN=%Zu TC=%u HOPLIMIT=%u FLOWLBL=%u ", |
67 | ntohs(ih->payload_len) + sizeof(struct ipv6hdr), | 66 | ntohs(ih->payload_len) + sizeof(struct ipv6hdr), |
68 | (ntohl(*(__be32 *)ih) & 0x0ff00000) >> 20, | 67 | (ntohl(*(__be32 *)ih) & 0x0ff00000) >> 20, |
69 | ih->hop_limit, | 68 | ih->hop_limit, |
@@ -78,35 +77,35 @@ static void dump_packet(const struct nf_loginfo *info, | |||
78 | 77 | ||
79 | hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr); | 78 | hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr); |
80 | if (hp == NULL) { | 79 | if (hp == NULL) { |
81 | printk("TRUNCATED"); | 80 | sb_add(m, "TRUNCATED"); |
82 | return; | 81 | return; |
83 | } | 82 | } |
84 | 83 | ||
85 | /* Max length: 48 "OPT (...) " */ | 84 | /* Max length: 48 "OPT (...) " */ |
86 | if (logflags & IP6T_LOG_IPOPT) | 85 | if (logflags & IP6T_LOG_IPOPT) |
87 | printk("OPT ( "); | 86 | sb_add(m, "OPT ( "); |
88 | 87 | ||
89 | switch (currenthdr) { | 88 | switch (currenthdr) { |
90 | case IPPROTO_FRAGMENT: { | 89 | case IPPROTO_FRAGMENT: { |
91 | struct frag_hdr _fhdr; | 90 | struct frag_hdr _fhdr; |
92 | const struct frag_hdr *fh; | 91 | const struct frag_hdr *fh; |
93 | 92 | ||
94 | printk("FRAG:"); | 93 | sb_add(m, "FRAG:"); |
95 | fh = skb_header_pointer(skb, ptr, sizeof(_fhdr), | 94 | fh = skb_header_pointer(skb, ptr, sizeof(_fhdr), |
96 | &_fhdr); | 95 | &_fhdr); |
97 | if (fh == NULL) { | 96 | if (fh == NULL) { |
98 | printk("TRUNCATED "); | 97 | sb_add(m, "TRUNCATED "); |
99 | return; | 98 | return; |
100 | } | 99 | } |
101 | 100 | ||
102 | /* Max length: 6 "65535 " */ | 101 | /* Max length: 6 "65535 " */ |
103 | printk("%u ", ntohs(fh->frag_off) & 0xFFF8); | 102 | sb_add(m, "%u ", ntohs(fh->frag_off) & 0xFFF8); |
104 | 103 | ||
105 | /* Max length: 11 "INCOMPLETE " */ | 104 | /* Max length: 11 "INCOMPLETE " */ |
106 | if (fh->frag_off & htons(0x0001)) | 105 | if (fh->frag_off & htons(0x0001)) |
107 | printk("INCOMPLETE "); | 106 | sb_add(m, "INCOMPLETE "); |
108 | 107 | ||
109 | printk("ID:%08x ", ntohl(fh->identification)); | 108 | sb_add(m, "ID:%08x ", ntohl(fh->identification)); |
110 | 109 | ||
111 | if (ntohs(fh->frag_off) & 0xFFF8) | 110 | if (ntohs(fh->frag_off) & 0xFFF8) |
112 | fragment = 1; | 111 | fragment = 1; |
@@ -120,7 +119,7 @@ static void dump_packet(const struct nf_loginfo *info, | |||
120 | case IPPROTO_HOPOPTS: | 119 | case IPPROTO_HOPOPTS: |
121 | if (fragment) { | 120 | if (fragment) { |
122 | if (logflags & IP6T_LOG_IPOPT) | 121 | if (logflags & IP6T_LOG_IPOPT) |
123 | printk(")"); | 122 | sb_add(m, ")"); |
124 | return; | 123 | return; |
125 | } | 124 | } |
126 | hdrlen = ipv6_optlen(hp); | 125 | hdrlen = ipv6_optlen(hp); |
@@ -132,10 +131,10 @@ static void dump_packet(const struct nf_loginfo *info, | |||
132 | const struct ip_auth_hdr *ah; | 131 | const struct ip_auth_hdr *ah; |
133 | 132 | ||
134 | /* Max length: 3 "AH " */ | 133 | /* Max length: 3 "AH " */ |
135 | printk("AH "); | 134 | sb_add(m, "AH "); |
136 | 135 | ||
137 | if (fragment) { | 136 | if (fragment) { |
138 | printk(")"); | 137 | sb_add(m, ")"); |
139 | return; | 138 | return; |
140 | } | 139 | } |
141 | 140 | ||
@@ -146,13 +145,13 @@ static void dump_packet(const struct nf_loginfo *info, | |||
146 | * Max length: 26 "INCOMPLETE [65535 | 145 | * Max length: 26 "INCOMPLETE [65535 |
147 | * bytes] )" | 146 | * bytes] )" |
148 | */ | 147 | */ |
149 | printk("INCOMPLETE [%u bytes] )", | 148 | sb_add(m, "INCOMPLETE [%u bytes] )", |
150 | skb->len - ptr); | 149 | skb->len - ptr); |
151 | return; | 150 | return; |
152 | } | 151 | } |
153 | 152 | ||
154 | /* Length: 15 "SPI=0xF1234567 */ | 153 | /* Length: 15 "SPI=0xF1234567 */ |
155 | printk("SPI=0x%x ", ntohl(ah->spi)); | 154 | sb_add(m, "SPI=0x%x ", ntohl(ah->spi)); |
156 | 155 | ||
157 | } | 156 | } |
158 | 157 | ||
@@ -164,10 +163,10 @@ static void dump_packet(const struct nf_loginfo *info, | |||
164 | const struct ip_esp_hdr *eh; | 163 | const struct ip_esp_hdr *eh; |
165 | 164 | ||
166 | /* Max length: 4 "ESP " */ | 165 | /* Max length: 4 "ESP " */ |
167 | printk("ESP "); | 166 | sb_add(m, "ESP "); |
168 | 167 | ||
169 | if (fragment) { | 168 | if (fragment) { |
170 | printk(")"); | 169 | sb_add(m, ")"); |
171 | return; | 170 | return; |
172 | } | 171 | } |
173 | 172 | ||
@@ -177,23 +176,23 @@ static void dump_packet(const struct nf_loginfo *info, | |||
177 | eh = skb_header_pointer(skb, ptr, sizeof(_esph), | 176 | eh = skb_header_pointer(skb, ptr, sizeof(_esph), |
178 | &_esph); | 177 | &_esph); |
179 | if (eh == NULL) { | 178 | if (eh == NULL) { |
180 | printk("INCOMPLETE [%u bytes] )", | 179 | sb_add(m, "INCOMPLETE [%u bytes] )", |
181 | skb->len - ptr); | 180 | skb->len - ptr); |
182 | return; | 181 | return; |
183 | } | 182 | } |
184 | 183 | ||
185 | /* Length: 16 "SPI=0xF1234567 )" */ | 184 | /* Length: 16 "SPI=0xF1234567 )" */ |
186 | printk("SPI=0x%x )", ntohl(eh->spi) ); | 185 | sb_add(m, "SPI=0x%x )", ntohl(eh->spi) ); |
187 | 186 | ||
188 | } | 187 | } |
189 | return; | 188 | return; |
190 | default: | 189 | default: |
191 | /* Max length: 20 "Unknown Ext Hdr 255" */ | 190 | /* Max length: 20 "Unknown Ext Hdr 255" */ |
192 | printk("Unknown Ext Hdr %u", currenthdr); | 191 | sb_add(m, "Unknown Ext Hdr %u", currenthdr); |
193 | return; | 192 | return; |
194 | } | 193 | } |
195 | if (logflags & IP6T_LOG_IPOPT) | 194 | if (logflags & IP6T_LOG_IPOPT) |
196 | printk(") "); | 195 | sb_add(m, ") "); |
197 | 196 | ||
198 | currenthdr = hp->nexthdr; | 197 | currenthdr = hp->nexthdr; |
199 | ptr += hdrlen; | 198 | ptr += hdrlen; |
@@ -205,7 +204,7 @@ static void dump_packet(const struct nf_loginfo *info, | |||
205 | const struct tcphdr *th; | 204 | const struct tcphdr *th; |
206 | 205 | ||
207 | /* Max length: 10 "PROTO=TCP " */ | 206 | /* Max length: 10 "PROTO=TCP " */ |
208 | printk("PROTO=TCP "); | 207 | sb_add(m, "PROTO=TCP "); |
209 | 208 | ||
210 | if (fragment) | 209 | if (fragment) |
211 | break; | 210 | break; |
@@ -213,40 +212,40 @@ static void dump_packet(const struct nf_loginfo *info, | |||
213 | /* Max length: 25 "INCOMPLETE [65535 bytes] " */ | 212 | /* Max length: 25 "INCOMPLETE [65535 bytes] " */ |
214 | th = skb_header_pointer(skb, ptr, sizeof(_tcph), &_tcph); | 213 | th = skb_header_pointer(skb, ptr, sizeof(_tcph), &_tcph); |
215 | if (th == NULL) { | 214 | if (th == NULL) { |
216 | printk("INCOMPLETE [%u bytes] ", skb->len - ptr); | 215 | sb_add(m, "INCOMPLETE [%u bytes] ", skb->len - ptr); |
217 | return; | 216 | return; |
218 | } | 217 | } |
219 | 218 | ||
220 | /* Max length: 20 "SPT=65535 DPT=65535 " */ | 219 | /* Max length: 20 "SPT=65535 DPT=65535 " */ |
221 | printk("SPT=%u DPT=%u ", | 220 | sb_add(m, "SPT=%u DPT=%u ", |
222 | ntohs(th->source), ntohs(th->dest)); | 221 | ntohs(th->source), ntohs(th->dest)); |
223 | /* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */ | 222 | /* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */ |
224 | if (logflags & IP6T_LOG_TCPSEQ) | 223 | if (logflags & IP6T_LOG_TCPSEQ) |
225 | printk("SEQ=%u ACK=%u ", | 224 | sb_add(m, "SEQ=%u ACK=%u ", |
226 | ntohl(th->seq), ntohl(th->ack_seq)); | 225 | ntohl(th->seq), ntohl(th->ack_seq)); |
227 | /* Max length: 13 "WINDOW=65535 " */ | 226 | /* Max length: 13 "WINDOW=65535 " */ |
228 | printk("WINDOW=%u ", ntohs(th->window)); | 227 | sb_add(m, "WINDOW=%u ", ntohs(th->window)); |
229 | /* Max length: 9 "RES=0x3C " */ | 228 | /* Max length: 9 "RES=0x3C " */ |
230 | printk("RES=0x%02x ", (u_int8_t)(ntohl(tcp_flag_word(th) & TCP_RESERVED_BITS) >> 22)); | 229 | sb_add(m, "RES=0x%02x ", (u_int8_t)(ntohl(tcp_flag_word(th) & TCP_RESERVED_BITS) >> 22)); |
231 | /* Max length: 32 "CWR ECE URG ACK PSH RST SYN FIN " */ | 230 | /* Max length: 32 "CWR ECE URG ACK PSH RST SYN FIN " */ |
232 | if (th->cwr) | 231 | if (th->cwr) |
233 | printk("CWR "); | 232 | sb_add(m, "CWR "); |
234 | if (th->ece) | 233 | if (th->ece) |
235 | printk("ECE "); | 234 | sb_add(m, "ECE "); |
236 | if (th->urg) | 235 | if (th->urg) |
237 | printk("URG "); | 236 | sb_add(m, "URG "); |
238 | if (th->ack) | 237 | if (th->ack) |
239 | printk("ACK "); | 238 | sb_add(m, "ACK "); |
240 | if (th->psh) | 239 | if (th->psh) |
241 | printk("PSH "); | 240 | sb_add(m, "PSH "); |
242 | if (th->rst) | 241 | if (th->rst) |
243 | printk("RST "); | 242 | sb_add(m, "RST "); |
244 | if (th->syn) | 243 | if (th->syn) |
245 | printk("SYN "); | 244 | sb_add(m, "SYN "); |
246 | if (th->fin) | 245 | if (th->fin) |
247 | printk("FIN "); | 246 | sb_add(m, "FIN "); |
248 | /* Max length: 11 "URGP=65535 " */ | 247 | /* Max length: 11 "URGP=65535 " */ |
249 | printk("URGP=%u ", ntohs(th->urg_ptr)); | 248 | sb_add(m, "URGP=%u ", ntohs(th->urg_ptr)); |
250 | 249 | ||
251 | if ((logflags & IP6T_LOG_TCPOPT) && | 250 | if ((logflags & IP6T_LOG_TCPOPT) && |
252 | th->doff * 4 > sizeof(struct tcphdr)) { | 251 | th->doff * 4 > sizeof(struct tcphdr)) { |
@@ -260,15 +259,15 @@ static void dump_packet(const struct nf_loginfo *info, | |||
260 | ptr + sizeof(struct tcphdr), | 259 | ptr + sizeof(struct tcphdr), |
261 | optsize, _opt); | 260 | optsize, _opt); |
262 | if (op == NULL) { | 261 | if (op == NULL) { |
263 | printk("OPT (TRUNCATED)"); | 262 | sb_add(m, "OPT (TRUNCATED)"); |
264 | return; | 263 | return; |
265 | } | 264 | } |
266 | 265 | ||
267 | /* Max length: 127 "OPT (" 15*4*2chars ") " */ | 266 | /* Max length: 127 "OPT (" 15*4*2chars ") " */ |
268 | printk("OPT ("); | 267 | sb_add(m, "OPT ("); |
269 | for (i =0; i < optsize; i++) | 268 | for (i =0; i < optsize; i++) |
270 | printk("%02X", op[i]); | 269 | sb_add(m, "%02X", op[i]); |
271 | printk(") "); | 270 | sb_add(m, ") "); |
272 | } | 271 | } |
273 | break; | 272 | break; |
274 | } | 273 | } |
@@ -279,9 +278,9 @@ static void dump_packet(const struct nf_loginfo *info, | |||
279 | 278 | ||
280 | if (currenthdr == IPPROTO_UDP) | 279 | if (currenthdr == IPPROTO_UDP) |
281 | /* Max length: 10 "PROTO=UDP " */ | 280 | /* Max length: 10 "PROTO=UDP " */ |
282 | printk("PROTO=UDP " ); | 281 | sb_add(m, "PROTO=UDP " ); |
283 | else /* Max length: 14 "PROTO=UDPLITE " */ | 282 | else /* Max length: 14 "PROTO=UDPLITE " */ |
284 | printk("PROTO=UDPLITE "); | 283 | sb_add(m, "PROTO=UDPLITE "); |
285 | 284 | ||
286 | if (fragment) | 285 | if (fragment) |
287 | break; | 286 | break; |
@@ -289,12 +288,12 @@ static void dump_packet(const struct nf_loginfo *info, | |||
289 | /* Max length: 25 "INCOMPLETE [65535 bytes] " */ | 288 | /* Max length: 25 "INCOMPLETE [65535 bytes] " */ |
290 | uh = skb_header_pointer(skb, ptr, sizeof(_udph), &_udph); | 289 | uh = skb_header_pointer(skb, ptr, sizeof(_udph), &_udph); |
291 | if (uh == NULL) { | 290 | if (uh == NULL) { |
292 | printk("INCOMPLETE [%u bytes] ", skb->len - ptr); | 291 | sb_add(m, "INCOMPLETE [%u bytes] ", skb->len - ptr); |
293 | return; | 292 | return; |
294 | } | 293 | } |
295 | 294 | ||
296 | /* Max length: 20 "SPT=65535 DPT=65535 " */ | 295 | /* Max length: 20 "SPT=65535 DPT=65535 " */ |
297 | printk("SPT=%u DPT=%u LEN=%u ", | 296 | sb_add(m, "SPT=%u DPT=%u LEN=%u ", |
298 | ntohs(uh->source), ntohs(uh->dest), | 297 | ntohs(uh->source), ntohs(uh->dest), |
299 | ntohs(uh->len)); | 298 | ntohs(uh->len)); |
300 | break; | 299 | break; |
@@ -304,7 +303,7 @@ static void dump_packet(const struct nf_loginfo *info, | |||
304 | const struct icmp6hdr *ic; | 303 | const struct icmp6hdr *ic; |
305 | 304 | ||
306 | /* Max length: 13 "PROTO=ICMPv6 " */ | 305 | /* Max length: 13 "PROTO=ICMPv6 " */ |
307 | printk("PROTO=ICMPv6 "); | 306 | sb_add(m, "PROTO=ICMPv6 "); |
308 | 307 | ||
309 | if (fragment) | 308 | if (fragment) |
310 | break; | 309 | break; |
@@ -312,18 +311,18 @@ static void dump_packet(const struct nf_loginfo *info, | |||
312 | /* Max length: 25 "INCOMPLETE [65535 bytes] " */ | 311 | /* Max length: 25 "INCOMPLETE [65535 bytes] " */ |
313 | ic = skb_header_pointer(skb, ptr, sizeof(_icmp6h), &_icmp6h); | 312 | ic = skb_header_pointer(skb, ptr, sizeof(_icmp6h), &_icmp6h); |
314 | if (ic == NULL) { | 313 | if (ic == NULL) { |
315 | printk("INCOMPLETE [%u bytes] ", skb->len - ptr); | 314 | sb_add(m, "INCOMPLETE [%u bytes] ", skb->len - ptr); |
316 | return; | 315 | return; |
317 | } | 316 | } |
318 | 317 | ||
319 | /* Max length: 18 "TYPE=255 CODE=255 " */ | 318 | /* Max length: 18 "TYPE=255 CODE=255 " */ |
320 | printk("TYPE=%u CODE=%u ", ic->icmp6_type, ic->icmp6_code); | 319 | sb_add(m, "TYPE=%u CODE=%u ", ic->icmp6_type, ic->icmp6_code); |
321 | 320 | ||
322 | switch (ic->icmp6_type) { | 321 | switch (ic->icmp6_type) { |
323 | case ICMPV6_ECHO_REQUEST: | 322 | case ICMPV6_ECHO_REQUEST: |
324 | case ICMPV6_ECHO_REPLY: | 323 | case ICMPV6_ECHO_REPLY: |
325 | /* Max length: 19 "ID=65535 SEQ=65535 " */ | 324 | /* Max length: 19 "ID=65535 SEQ=65535 " */ |
326 | printk("ID=%u SEQ=%u ", | 325 | sb_add(m, "ID=%u SEQ=%u ", |
327 | ntohs(ic->icmp6_identifier), | 326 | ntohs(ic->icmp6_identifier), |
328 | ntohs(ic->icmp6_sequence)); | 327 | ntohs(ic->icmp6_sequence)); |
329 | break; | 328 | break; |
@@ -334,35 +333,35 @@ static void dump_packet(const struct nf_loginfo *info, | |||
334 | 333 | ||
335 | case ICMPV6_PARAMPROB: | 334 | case ICMPV6_PARAMPROB: |
336 | /* Max length: 17 "POINTER=ffffffff " */ | 335 | /* Max length: 17 "POINTER=ffffffff " */ |
337 | printk("POINTER=%08x ", ntohl(ic->icmp6_pointer)); | 336 | sb_add(m, "POINTER=%08x ", ntohl(ic->icmp6_pointer)); |
338 | /* Fall through */ | 337 | /* Fall through */ |
339 | case ICMPV6_DEST_UNREACH: | 338 | case ICMPV6_DEST_UNREACH: |
340 | case ICMPV6_PKT_TOOBIG: | 339 | case ICMPV6_PKT_TOOBIG: |
341 | case ICMPV6_TIME_EXCEED: | 340 | case ICMPV6_TIME_EXCEED: |
342 | /* Max length: 3+maxlen */ | 341 | /* Max length: 3+maxlen */ |
343 | if (recurse) { | 342 | if (recurse) { |
344 | printk("["); | 343 | sb_add(m, "["); |
345 | dump_packet(info, skb, ptr + sizeof(_icmp6h), | 344 | dump_packet(m, info, skb, |
346 | 0); | 345 | ptr + sizeof(_icmp6h), 0); |
347 | printk("] "); | 346 | sb_add(m, "] "); |
348 | } | 347 | } |
349 | 348 | ||
350 | /* Max length: 10 "MTU=65535 " */ | 349 | /* Max length: 10 "MTU=65535 " */ |
351 | if (ic->icmp6_type == ICMPV6_PKT_TOOBIG) | 350 | if (ic->icmp6_type == ICMPV6_PKT_TOOBIG) |
352 | printk("MTU=%u ", ntohl(ic->icmp6_mtu)); | 351 | sb_add(m, "MTU=%u ", ntohl(ic->icmp6_mtu)); |
353 | } | 352 | } |
354 | break; | 353 | break; |
355 | } | 354 | } |
356 | /* Max length: 10 "PROTO=255 " */ | 355 | /* Max length: 10 "PROTO=255 " */ |
357 | default: | 356 | default: |
358 | printk("PROTO=%u ", currenthdr); | 357 | sb_add(m, "PROTO=%u ", currenthdr); |
359 | } | 358 | } |
360 | 359 | ||
361 | /* Max length: 15 "UID=4294967295 " */ | 360 | /* Max length: 15 "UID=4294967295 " */ |
362 | if ((logflags & IP6T_LOG_UID) && recurse && skb->sk) { | 361 | if ((logflags & IP6T_LOG_UID) && recurse && skb->sk) { |
363 | read_lock_bh(&skb->sk->sk_callback_lock); | 362 | read_lock_bh(&skb->sk->sk_callback_lock); |
364 | if (skb->sk->sk_socket && skb->sk->sk_socket->file) | 363 | if (skb->sk->sk_socket && skb->sk->sk_socket->file) |
365 | printk("UID=%u GID=%u ", | 364 | sb_add(m, "UID=%u GID=%u ", |
366 | skb->sk->sk_socket->file->f_cred->fsuid, | 365 | skb->sk->sk_socket->file->f_cred->fsuid, |
367 | skb->sk->sk_socket->file->f_cred->fsgid); | 366 | skb->sk->sk_socket->file->f_cred->fsgid); |
368 | read_unlock_bh(&skb->sk->sk_callback_lock); | 367 | read_unlock_bh(&skb->sk->sk_callback_lock); |
@@ -370,10 +369,11 @@ static void dump_packet(const struct nf_loginfo *info, | |||
370 | 369 | ||
371 | /* Max length: 16 "MARK=0xFFFFFFFF " */ | 370 | /* Max length: 16 "MARK=0xFFFFFFFF " */ |
372 | if (!recurse && skb->mark) | 371 | if (!recurse && skb->mark) |
373 | printk("MARK=0x%x ", skb->mark); | 372 | sb_add(m, "MARK=0x%x ", skb->mark); |
374 | } | 373 | } |
375 | 374 | ||
376 | static void dump_mac_header(const struct nf_loginfo *info, | 375 | static void dump_mac_header(struct sbuff *m, |
376 | const struct nf_loginfo *info, | ||
377 | const struct sk_buff *skb) | 377 | const struct sk_buff *skb) |
378 | { | 378 | { |
379 | struct net_device *dev = skb->dev; | 379 | struct net_device *dev = skb->dev; |
@@ -387,7 +387,7 @@ static void dump_mac_header(const struct nf_loginfo *info, | |||
387 | 387 | ||
388 | switch (dev->type) { | 388 | switch (dev->type) { |
389 | case ARPHRD_ETHER: | 389 | case ARPHRD_ETHER: |
390 | printk("MACSRC=%pM MACDST=%pM MACPROTO=%04x ", | 390 | sb_add(m, "MACSRC=%pM MACDST=%pM MACPROTO=%04x ", |
391 | eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest, | 391 | eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest, |
392 | ntohs(eth_hdr(skb)->h_proto)); | 392 | ntohs(eth_hdr(skb)->h_proto)); |
393 | return; | 393 | return; |
@@ -396,7 +396,7 @@ static void dump_mac_header(const struct nf_loginfo *info, | |||
396 | } | 396 | } |
397 | 397 | ||
398 | fallback: | 398 | fallback: |
399 | printk("MAC="); | 399 | sb_add(m, "MAC="); |
400 | if (dev->hard_header_len && | 400 | if (dev->hard_header_len && |
401 | skb->mac_header != skb->network_header) { | 401 | skb->mac_header != skb->network_header) { |
402 | const unsigned char *p = skb_mac_header(skb); | 402 | const unsigned char *p = skb_mac_header(skb); |
@@ -408,19 +408,19 @@ fallback: | |||
408 | p = NULL; | 408 | p = NULL; |
409 | 409 | ||
410 | if (p != NULL) { | 410 | if (p != NULL) { |
411 | printk("%02x", *p++); | 411 | sb_add(m, "%02x", *p++); |
412 | for (i = 1; i < len; i++) | 412 | for (i = 1; i < len; i++) |
413 | printk(":%02x", p[i]); | 413 | sb_add(m, ":%02x", p[i]); |
414 | } | 414 | } |
415 | printk(" "); | 415 | sb_add(m, " "); |
416 | 416 | ||
417 | if (dev->type == ARPHRD_SIT) { | 417 | if (dev->type == ARPHRD_SIT) { |
418 | const struct iphdr *iph = | 418 | const struct iphdr *iph = |
419 | (struct iphdr *)skb_mac_header(skb); | 419 | (struct iphdr *)skb_mac_header(skb); |
420 | printk("TUNNEL=%pI4->%pI4 ", &iph->saddr, &iph->daddr); | 420 | sb_add(m, "TUNNEL=%pI4->%pI4 ", &iph->saddr, &iph->daddr); |
421 | } | 421 | } |
422 | } else | 422 | } else |
423 | printk(" "); | 423 | sb_add(m, " "); |
424 | } | 424 | } |
425 | 425 | ||
426 | static struct nf_loginfo default_loginfo = { | 426 | static struct nf_loginfo default_loginfo = { |
@@ -442,22 +442,23 @@ ip6t_log_packet(u_int8_t pf, | |||
442 | const struct nf_loginfo *loginfo, | 442 | const struct nf_loginfo *loginfo, |
443 | const char *prefix) | 443 | const char *prefix) |
444 | { | 444 | { |
445 | struct sbuff *m = sb_open(); | ||
446 | |||
445 | if (!loginfo) | 447 | if (!loginfo) |
446 | loginfo = &default_loginfo; | 448 | loginfo = &default_loginfo; |
447 | 449 | ||
448 | spin_lock_bh(&log_lock); | 450 | sb_add(m, "<%d>%sIN=%s OUT=%s ", loginfo->u.log.level, |
449 | printk("<%d>%sIN=%s OUT=%s ", loginfo->u.log.level, | 451 | prefix, |
450 | prefix, | 452 | in ? in->name : "", |
451 | in ? in->name : "", | 453 | out ? out->name : ""); |
452 | out ? out->name : ""); | ||
453 | 454 | ||
454 | /* MAC logging for input path only. */ | 455 | /* MAC logging for input path only. */ |
455 | if (in && !out) | 456 | if (in && !out) |
456 | dump_mac_header(loginfo, skb); | 457 | dump_mac_header(m, loginfo, skb); |
458 | |||
459 | dump_packet(m, loginfo, skb, skb_network_offset(skb), 1); | ||
457 | 460 | ||
458 | dump_packet(loginfo, skb, skb_network_offset(skb), 1); | 461 | sb_close(m); |
459 | printk("\n"); | ||
460 | spin_unlock_bh(&log_lock); | ||
461 | } | 462 | } |
462 | 463 | ||
463 | static unsigned int | 464 | static unsigned int |
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index ff43461704be..c8af58b22562 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | |||
@@ -16,7 +16,6 @@ | |||
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/skbuff.h> | 17 | #include <linux/skbuff.h> |
18 | #include <linux/icmp.h> | 18 | #include <linux/icmp.h> |
19 | #include <linux/sysctl.h> | ||
20 | #include <net/ipv6.h> | 19 | #include <net/ipv6.h> |
21 | #include <net/inet_frag.h> | 20 | #include <net/inet_frag.h> |
22 | 21 | ||
@@ -29,6 +28,7 @@ | |||
29 | #include <net/netfilter/nf_conntrack_core.h> | 28 | #include <net/netfilter/nf_conntrack_core.h> |
30 | #include <net/netfilter/nf_conntrack_zones.h> | 29 | #include <net/netfilter/nf_conntrack_zones.h> |
31 | #include <net/netfilter/ipv6/nf_conntrack_ipv6.h> | 30 | #include <net/netfilter/ipv6/nf_conntrack_ipv6.h> |
31 | #include <net/netfilter/ipv6/nf_defrag_ipv6.h> | ||
32 | #include <net/netfilter/nf_log.h> | 32 | #include <net/netfilter/nf_log.h> |
33 | 33 | ||
34 | static bool ipv6_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff, | 34 | static bool ipv6_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff, |
@@ -189,53 +189,6 @@ out: | |||
189 | return nf_conntrack_confirm(skb); | 189 | return nf_conntrack_confirm(skb); |
190 | } | 190 | } |
191 | 191 | ||
192 | static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum, | ||
193 | struct sk_buff *skb) | ||
194 | { | ||
195 | u16 zone = NF_CT_DEFAULT_ZONE; | ||
196 | |||
197 | if (skb->nfct) | ||
198 | zone = nf_ct_zone((struct nf_conn *)skb->nfct); | ||
199 | |||
200 | #ifdef CONFIG_BRIDGE_NETFILTER | ||
201 | if (skb->nf_bridge && | ||
202 | skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING) | ||
203 | return IP6_DEFRAG_CONNTRACK_BRIDGE_IN + zone; | ||
204 | #endif | ||
205 | if (hooknum == NF_INET_PRE_ROUTING) | ||
206 | return IP6_DEFRAG_CONNTRACK_IN + zone; | ||
207 | else | ||
208 | return IP6_DEFRAG_CONNTRACK_OUT + zone; | ||
209 | |||
210 | } | ||
211 | |||
212 | static unsigned int ipv6_defrag(unsigned int hooknum, | ||
213 | struct sk_buff *skb, | ||
214 | const struct net_device *in, | ||
215 | const struct net_device *out, | ||
216 | int (*okfn)(struct sk_buff *)) | ||
217 | { | ||
218 | struct sk_buff *reasm; | ||
219 | |||
220 | /* Previously seen (loopback)? */ | ||
221 | if (skb->nfct && !nf_ct_is_template((struct nf_conn *)skb->nfct)) | ||
222 | return NF_ACCEPT; | ||
223 | |||
224 | reasm = nf_ct_frag6_gather(skb, nf_ct6_defrag_user(hooknum, skb)); | ||
225 | /* queued */ | ||
226 | if (reasm == NULL) | ||
227 | return NF_STOLEN; | ||
228 | |||
229 | /* error occured or not fragmented */ | ||
230 | if (reasm == skb) | ||
231 | return NF_ACCEPT; | ||
232 | |||
233 | nf_ct_frag6_output(hooknum, reasm, (struct net_device *)in, | ||
234 | (struct net_device *)out, okfn); | ||
235 | |||
236 | return NF_STOLEN; | ||
237 | } | ||
238 | |||
239 | static unsigned int __ipv6_conntrack_in(struct net *net, | 192 | static unsigned int __ipv6_conntrack_in(struct net *net, |
240 | unsigned int hooknum, | 193 | unsigned int hooknum, |
241 | struct sk_buff *skb, | 194 | struct sk_buff *skb, |
@@ -288,13 +241,6 @@ static unsigned int ipv6_conntrack_local(unsigned int hooknum, | |||
288 | 241 | ||
289 | static struct nf_hook_ops ipv6_conntrack_ops[] __read_mostly = { | 242 | static struct nf_hook_ops ipv6_conntrack_ops[] __read_mostly = { |
290 | { | 243 | { |
291 | .hook = ipv6_defrag, | ||
292 | .owner = THIS_MODULE, | ||
293 | .pf = NFPROTO_IPV6, | ||
294 | .hooknum = NF_INET_PRE_ROUTING, | ||
295 | .priority = NF_IP6_PRI_CONNTRACK_DEFRAG, | ||
296 | }, | ||
297 | { | ||
298 | .hook = ipv6_conntrack_in, | 244 | .hook = ipv6_conntrack_in, |
299 | .owner = THIS_MODULE, | 245 | .owner = THIS_MODULE, |
300 | .pf = NFPROTO_IPV6, | 246 | .pf = NFPROTO_IPV6, |
@@ -309,13 +255,6 @@ static struct nf_hook_ops ipv6_conntrack_ops[] __read_mostly = { | |||
309 | .priority = NF_IP6_PRI_CONNTRACK, | 255 | .priority = NF_IP6_PRI_CONNTRACK, |
310 | }, | 256 | }, |
311 | { | 257 | { |
312 | .hook = ipv6_defrag, | ||
313 | .owner = THIS_MODULE, | ||
314 | .pf = NFPROTO_IPV6, | ||
315 | .hooknum = NF_INET_LOCAL_OUT, | ||
316 | .priority = NF_IP6_PRI_CONNTRACK_DEFRAG, | ||
317 | }, | ||
318 | { | ||
319 | .hook = ipv6_confirm, | 258 | .hook = ipv6_confirm, |
320 | .owner = THIS_MODULE, | 259 | .owner = THIS_MODULE, |
321 | .pf = NFPROTO_IPV6, | 260 | .pf = NFPROTO_IPV6, |
@@ -387,10 +326,6 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6 __read_mostly = { | |||
387 | .nlattr_to_tuple = ipv6_nlattr_to_tuple, | 326 | .nlattr_to_tuple = ipv6_nlattr_to_tuple, |
388 | .nla_policy = ipv6_nla_policy, | 327 | .nla_policy = ipv6_nla_policy, |
389 | #endif | 328 | #endif |
390 | #ifdef CONFIG_SYSCTL | ||
391 | .ctl_table_path = nf_net_netfilter_sysctl_path, | ||
392 | .ctl_table = nf_ct_ipv6_sysctl_table, | ||
393 | #endif | ||
394 | .me = THIS_MODULE, | 329 | .me = THIS_MODULE, |
395 | }; | 330 | }; |
396 | 331 | ||
@@ -403,16 +338,12 @@ static int __init nf_conntrack_l3proto_ipv6_init(void) | |||
403 | int ret = 0; | 338 | int ret = 0; |
404 | 339 | ||
405 | need_conntrack(); | 340 | need_conntrack(); |
341 | nf_defrag_ipv6_enable(); | ||
406 | 342 | ||
407 | ret = nf_ct_frag6_init(); | ||
408 | if (ret < 0) { | ||
409 | pr_err("nf_conntrack_ipv6: can't initialize frag6.\n"); | ||
410 | return ret; | ||
411 | } | ||
412 | ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_tcp6); | 343 | ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_tcp6); |
413 | if (ret < 0) { | 344 | if (ret < 0) { |
414 | pr_err("nf_conntrack_ipv6: can't register tcp.\n"); | 345 | pr_err("nf_conntrack_ipv6: can't register tcp.\n"); |
415 | goto cleanup_frag6; | 346 | return ret; |
416 | } | 347 | } |
417 | 348 | ||
418 | ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udp6); | 349 | ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udp6); |
@@ -450,8 +381,6 @@ static int __init nf_conntrack_l3proto_ipv6_init(void) | |||
450 | nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp6); | 381 | nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp6); |
451 | cleanup_tcp: | 382 | cleanup_tcp: |
452 | nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp6); | 383 | nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp6); |
453 | cleanup_frag6: | ||
454 | nf_ct_frag6_cleanup(); | ||
455 | return ret; | 384 | return ret; |
456 | } | 385 | } |
457 | 386 | ||
@@ -463,7 +392,6 @@ static void __exit nf_conntrack_l3proto_ipv6_fini(void) | |||
463 | nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmpv6); | 392 | nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmpv6); |
464 | nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp6); | 393 | nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp6); |
465 | nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp6); | 394 | nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp6); |
466 | nf_ct_frag6_cleanup(); | ||
467 | } | 395 | } |
468 | 396 | ||
469 | module_init(nf_conntrack_l3proto_ipv6_init); | 397 | module_init(nf_conntrack_l3proto_ipv6_init); |
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 138a8b362706..489d71b844ac 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c | |||
@@ -73,7 +73,7 @@ static struct inet_frags nf_frags; | |||
73 | static struct netns_frags nf_init_frags; | 73 | static struct netns_frags nf_init_frags; |
74 | 74 | ||
75 | #ifdef CONFIG_SYSCTL | 75 | #ifdef CONFIG_SYSCTL |
76 | struct ctl_table nf_ct_ipv6_sysctl_table[] = { | 76 | struct ctl_table nf_ct_frag6_sysctl_table[] = { |
77 | { | 77 | { |
78 | .procname = "nf_conntrack_frag6_timeout", | 78 | .procname = "nf_conntrack_frag6_timeout", |
79 | .data = &nf_init_frags.timeout, | 79 | .data = &nf_init_frags.timeout, |
@@ -97,6 +97,8 @@ struct ctl_table nf_ct_ipv6_sysctl_table[] = { | |||
97 | }, | 97 | }, |
98 | { } | 98 | { } |
99 | }; | 99 | }; |
100 | |||
101 | static struct ctl_table_header *nf_ct_frag6_sysctl_header; | ||
100 | #endif | 102 | #endif |
101 | 103 | ||
102 | static unsigned int nf_hashfn(struct inet_frag_queue *q) | 104 | static unsigned int nf_hashfn(struct inet_frag_queue *q) |
@@ -623,11 +625,21 @@ int nf_ct_frag6_init(void) | |||
623 | inet_frags_init_net(&nf_init_frags); | 625 | inet_frags_init_net(&nf_init_frags); |
624 | inet_frags_init(&nf_frags); | 626 | inet_frags_init(&nf_frags); |
625 | 627 | ||
628 | nf_ct_frag6_sysctl_header = register_sysctl_paths(nf_net_netfilter_sysctl_path, | ||
629 | nf_ct_frag6_sysctl_table); | ||
630 | if (!nf_ct_frag6_sysctl_header) { | ||
631 | inet_frags_fini(&nf_frags); | ||
632 | return -ENOMEM; | ||
633 | } | ||
634 | |||
626 | return 0; | 635 | return 0; |
627 | } | 636 | } |
628 | 637 | ||
629 | void nf_ct_frag6_cleanup(void) | 638 | void nf_ct_frag6_cleanup(void) |
630 | { | 639 | { |
640 | unregister_sysctl_table(nf_ct_frag6_sysctl_header); | ||
641 | nf_ct_frag6_sysctl_header = NULL; | ||
642 | |||
631 | inet_frags_fini(&nf_frags); | 643 | inet_frags_fini(&nf_frags); |
632 | 644 | ||
633 | nf_init_frags.low_thresh = 0; | 645 | nf_init_frags.low_thresh = 0; |
diff --git a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c new file mode 100644 index 000000000000..99abfb53bab9 --- /dev/null +++ b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c | |||
@@ -0,0 +1,131 @@ | |||
1 | /* (C) 1999-2001 Paul `Rusty' Russell | ||
2 | * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #include <linux/types.h> | ||
10 | #include <linux/ipv6.h> | ||
11 | #include <linux/in6.h> | ||
12 | #include <linux/netfilter.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/skbuff.h> | ||
15 | #include <linux/icmp.h> | ||
16 | #include <linux/sysctl.h> | ||
17 | #include <net/ipv6.h> | ||
18 | #include <net/inet_frag.h> | ||
19 | |||
20 | #include <linux/netfilter_ipv6.h> | ||
21 | #include <linux/netfilter_bridge.h> | ||
22 | #include <net/netfilter/nf_conntrack.h> | ||
23 | #include <net/netfilter/nf_conntrack_helper.h> | ||
24 | #include <net/netfilter/nf_conntrack_l4proto.h> | ||
25 | #include <net/netfilter/nf_conntrack_l3proto.h> | ||
26 | #include <net/netfilter/nf_conntrack_core.h> | ||
27 | #include <net/netfilter/nf_conntrack_zones.h> | ||
28 | #include <net/netfilter/ipv6/nf_conntrack_ipv6.h> | ||
29 | #include <net/netfilter/ipv6/nf_defrag_ipv6.h> | ||
30 | |||
31 | static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum, | ||
32 | struct sk_buff *skb) | ||
33 | { | ||
34 | u16 zone = NF_CT_DEFAULT_ZONE; | ||
35 | |||
36 | if (skb->nfct) | ||
37 | zone = nf_ct_zone((struct nf_conn *)skb->nfct); | ||
38 | |||
39 | #ifdef CONFIG_BRIDGE_NETFILTER | ||
40 | if (skb->nf_bridge && | ||
41 | skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING) | ||
42 | return IP6_DEFRAG_CONNTRACK_BRIDGE_IN + zone; | ||
43 | #endif | ||
44 | if (hooknum == NF_INET_PRE_ROUTING) | ||
45 | return IP6_DEFRAG_CONNTRACK_IN + zone; | ||
46 | else | ||
47 | return IP6_DEFRAG_CONNTRACK_OUT + zone; | ||
48 | |||
49 | } | ||
50 | |||
51 | static unsigned int ipv6_defrag(unsigned int hooknum, | ||
52 | struct sk_buff *skb, | ||
53 | const struct net_device *in, | ||
54 | const struct net_device *out, | ||
55 | int (*okfn)(struct sk_buff *)) | ||
56 | { | ||
57 | struct sk_buff *reasm; | ||
58 | |||
59 | /* Previously seen (loopback)? */ | ||
60 | if (skb->nfct && !nf_ct_is_template((struct nf_conn *)skb->nfct)) | ||
61 | return NF_ACCEPT; | ||
62 | |||
63 | reasm = nf_ct_frag6_gather(skb, nf_ct6_defrag_user(hooknum, skb)); | ||
64 | /* queued */ | ||
65 | if (reasm == NULL) | ||
66 | return NF_STOLEN; | ||
67 | |||
68 | /* error occured or not fragmented */ | ||
69 | if (reasm == skb) | ||
70 | return NF_ACCEPT; | ||
71 | |||
72 | nf_ct_frag6_output(hooknum, reasm, (struct net_device *)in, | ||
73 | (struct net_device *)out, okfn); | ||
74 | |||
75 | return NF_STOLEN; | ||
76 | } | ||
77 | |||
78 | static struct nf_hook_ops ipv6_defrag_ops[] = { | ||
79 | { | ||
80 | .hook = ipv6_defrag, | ||
81 | .owner = THIS_MODULE, | ||
82 | .pf = NFPROTO_IPV6, | ||
83 | .hooknum = NF_INET_PRE_ROUTING, | ||
84 | .priority = NF_IP6_PRI_CONNTRACK_DEFRAG, | ||
85 | }, | ||
86 | { | ||
87 | .hook = ipv6_defrag, | ||
88 | .owner = THIS_MODULE, | ||
89 | .pf = NFPROTO_IPV6, | ||
90 | .hooknum = NF_INET_LOCAL_OUT, | ||
91 | .priority = NF_IP6_PRI_CONNTRACK_DEFRAG, | ||
92 | }, | ||
93 | }; | ||
94 | |||
95 | static int __init nf_defrag_init(void) | ||
96 | { | ||
97 | int ret = 0; | ||
98 | |||
99 | ret = nf_ct_frag6_init(); | ||
100 | if (ret < 0) { | ||
101 | pr_err("nf_defrag_ipv6: can't initialize frag6.\n"); | ||
102 | return ret; | ||
103 | } | ||
104 | ret = nf_register_hooks(ipv6_defrag_ops, ARRAY_SIZE(ipv6_defrag_ops)); | ||
105 | if (ret < 0) { | ||
106 | pr_err("nf_defrag_ipv6: can't register hooks\n"); | ||
107 | goto cleanup_frag6; | ||
108 | } | ||
109 | return ret; | ||
110 | |||
111 | cleanup_frag6: | ||
112 | nf_ct_frag6_cleanup(); | ||
113 | return ret; | ||
114 | |||
115 | } | ||
116 | |||
117 | static void __exit nf_defrag_fini(void) | ||
118 | { | ||
119 | nf_unregister_hooks(ipv6_defrag_ops, ARRAY_SIZE(ipv6_defrag_ops)); | ||
120 | nf_ct_frag6_cleanup(); | ||
121 | } | ||
122 | |||
123 | void nf_defrag_ipv6_enable(void) | ||
124 | { | ||
125 | } | ||
126 | EXPORT_SYMBOL_GPL(nf_defrag_ipv6_enable); | ||
127 | |||
128 | module_init(nf_defrag_init); | ||
129 | module_exit(nf_defrag_fini); | ||
130 | |||
131 | MODULE_LICENSE("GPL"); | ||
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 8d93f6d81979..7e41e2cbb85e 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -1409,7 +1409,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1409 | 1409 | ||
1410 | newsk = tcp_create_openreq_child(sk, req, skb); | 1410 | newsk = tcp_create_openreq_child(sk, req, skb); |
1411 | if (newsk == NULL) | 1411 | if (newsk == NULL) |
1412 | goto out; | 1412 | goto out_nonewsk; |
1413 | 1413 | ||
1414 | /* | 1414 | /* |
1415 | * No need to charge this sock to the relevant IPv6 refcnt debug socks | 1415 | * No need to charge this sock to the relevant IPv6 refcnt debug socks |
@@ -1497,18 +1497,22 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1497 | } | 1497 | } |
1498 | #endif | 1498 | #endif |
1499 | 1499 | ||
1500 | if (__inet_inherit_port(sk, newsk) < 0) { | ||
1501 | sock_put(newsk); | ||
1502 | goto out; | ||
1503 | } | ||
1500 | __inet6_hash(newsk, NULL); | 1504 | __inet6_hash(newsk, NULL); |
1501 | __inet_inherit_port(sk, newsk); | ||
1502 | 1505 | ||
1503 | return newsk; | 1506 | return newsk; |
1504 | 1507 | ||
1505 | out_overflow: | 1508 | out_overflow: |
1506 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS); | 1509 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS); |
1507 | out: | 1510 | out_nonewsk: |
1508 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); | ||
1509 | if (opt && opt != np->opt) | 1511 | if (opt && opt != np->opt) |
1510 | sock_kfree_s(sk, opt, opt->tot_len); | 1512 | sock_kfree_s(sk, opt, opt->tot_len); |
1511 | dst_release(dst); | 1513 | dst_release(dst); |
1514 | out: | ||
1515 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); | ||
1512 | return NULL; | 1516 | return NULL; |
1513 | } | 1517 | } |
1514 | 1518 | ||
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 5acb3560ff15..c84dad432114 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -122,8 +122,8 @@ static void udp_v6_rehash(struct sock *sk) | |||
122 | 122 | ||
123 | static inline int compute_score(struct sock *sk, struct net *net, | 123 | static inline int compute_score(struct sock *sk, struct net *net, |
124 | unsigned short hnum, | 124 | unsigned short hnum, |
125 | struct in6_addr *saddr, __be16 sport, | 125 | const struct in6_addr *saddr, __be16 sport, |
126 | struct in6_addr *daddr, __be16 dport, | 126 | const struct in6_addr *daddr, __be16 dport, |
127 | int dif) | 127 | int dif) |
128 | { | 128 | { |
129 | int score = -1; | 129 | int score = -1; |
@@ -239,8 +239,8 @@ exact_match: | |||
239 | } | 239 | } |
240 | 240 | ||
241 | static struct sock *__udp6_lib_lookup(struct net *net, | 241 | static struct sock *__udp6_lib_lookup(struct net *net, |
242 | struct in6_addr *saddr, __be16 sport, | 242 | const struct in6_addr *saddr, __be16 sport, |
243 | struct in6_addr *daddr, __be16 dport, | 243 | const struct in6_addr *daddr, __be16 dport, |
244 | int dif, struct udp_table *udptable) | 244 | int dif, struct udp_table *udptable) |
245 | { | 245 | { |
246 | struct sock *sk, *result; | 246 | struct sock *sk, *result; |
@@ -320,6 +320,14 @@ static struct sock *__udp6_lib_lookup_skb(struct sk_buff *skb, | |||
320 | udptable); | 320 | udptable); |
321 | } | 321 | } |
322 | 322 | ||
323 | struct sock *udp6_lib_lookup(struct net *net, const struct in6_addr *saddr, __be16 sport, | ||
324 | const struct in6_addr *daddr, __be16 dport, int dif) | ||
325 | { | ||
326 | return __udp6_lib_lookup(net, saddr, sport, daddr, dport, dif, &udp_table); | ||
327 | } | ||
328 | EXPORT_SYMBOL_GPL(udp6_lib_lookup); | ||
329 | |||
330 | |||
323 | /* | 331 | /* |
324 | * This should be easy, if there is something there we | 332 | * This should be easy, if there is something there we |
325 | * return it, otherwise we block. | 333 | * return it, otherwise we block. |