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. |
