diff options
Diffstat (limited to 'net/ipv6')
34 files changed, 1040 insertions, 638 deletions
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile index b39e04940590..6460eec834b7 100644 --- a/net/ipv6/Makefile +++ b/net/ipv6/Makefile | |||
@@ -8,7 +8,7 @@ ipv6-objs := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o sit.o \ | |||
8 | route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o raw.o \ | 8 | route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o raw.o \ |
9 | protocol.o icmp.o mcast.o reassembly.o tcp_ipv6.o \ | 9 | protocol.o icmp.o mcast.o reassembly.o tcp_ipv6.o \ |
10 | exthdrs.o sysctl_net_ipv6.o datagram.o proc.o \ | 10 | exthdrs.o sysctl_net_ipv6.o datagram.o proc.o \ |
11 | ip6_flowlabel.o ipv6_syms.o | 11 | ip6_flowlabel.o ipv6_syms.o netfilter.o |
12 | 12 | ||
13 | ipv6-$(CONFIG_XFRM) += xfrm6_policy.o xfrm6_state.o xfrm6_input.o \ | 13 | ipv6-$(CONFIG_XFRM) += xfrm6_policy.o xfrm6_state.o xfrm6_input.o \ |
14 | xfrm6_output.o | 14 | xfrm6_output.o |
@@ -23,3 +23,5 @@ obj-$(CONFIG_NETFILTER) += netfilter/ | |||
23 | obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o | 23 | obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o |
24 | 24 | ||
25 | obj-y += exthdrs_core.o | 25 | obj-y += exthdrs_core.o |
26 | |||
27 | obj-$(subst m,y,$(CONFIG_IPV6)) += inet6_hashtables.o | ||
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 77004b9456c0..937ad32db77c 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -1041,9 +1041,9 @@ int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2) | |||
1041 | const struct in6_addr *sk_rcv_saddr6 = &inet6_sk(sk)->rcv_saddr; | 1041 | const struct in6_addr *sk_rcv_saddr6 = &inet6_sk(sk)->rcv_saddr; |
1042 | const struct in6_addr *sk2_rcv_saddr6 = tcp_v6_rcv_saddr(sk2); | 1042 | const struct in6_addr *sk2_rcv_saddr6 = tcp_v6_rcv_saddr(sk2); |
1043 | u32 sk_rcv_saddr = inet_sk(sk)->rcv_saddr; | 1043 | u32 sk_rcv_saddr = inet_sk(sk)->rcv_saddr; |
1044 | u32 sk2_rcv_saddr = tcp_v4_rcv_saddr(sk2); | 1044 | u32 sk2_rcv_saddr = inet_rcv_saddr(sk2); |
1045 | int sk_ipv6only = ipv6_only_sock(sk); | 1045 | int sk_ipv6only = ipv6_only_sock(sk); |
1046 | int sk2_ipv6only = tcp_v6_ipv6only(sk2); | 1046 | int sk2_ipv6only = inet_v6_ipv6only(sk2); |
1047 | int addr_type = ipv6_addr_type(sk_rcv_saddr6); | 1047 | int addr_type = ipv6_addr_type(sk_rcv_saddr6); |
1048 | int addr_type2 = sk2_rcv_saddr6 ? ipv6_addr_type(sk2_rcv_saddr6) : IPV6_ADDR_MAPPED; | 1048 | int addr_type2 = sk2_rcv_saddr6 ? ipv6_addr_type(sk2_rcv_saddr6) : IPV6_ADDR_MAPPED; |
1049 | 1049 | ||
@@ -1126,7 +1126,7 @@ void addrconf_leave_solict(struct inet6_dev *idev, struct in6_addr *addr) | |||
1126 | __ipv6_dev_mc_dec(idev, &maddr); | 1126 | __ipv6_dev_mc_dec(idev, &maddr); |
1127 | } | 1127 | } |
1128 | 1128 | ||
1129 | void addrconf_join_anycast(struct inet6_ifaddr *ifp) | 1129 | static void addrconf_join_anycast(struct inet6_ifaddr *ifp) |
1130 | { | 1130 | { |
1131 | struct in6_addr addr; | 1131 | struct in6_addr addr; |
1132 | ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len); | 1132 | ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len); |
@@ -1135,7 +1135,7 @@ void addrconf_join_anycast(struct inet6_ifaddr *ifp) | |||
1135 | ipv6_dev_ac_inc(ifp->idev->dev, &addr); | 1135 | ipv6_dev_ac_inc(ifp->idev->dev, &addr); |
1136 | } | 1136 | } |
1137 | 1137 | ||
1138 | void addrconf_leave_anycast(struct inet6_ifaddr *ifp) | 1138 | static void addrconf_leave_anycast(struct inet6_ifaddr *ifp) |
1139 | { | 1139 | { |
1140 | struct in6_addr addr; | 1140 | struct in6_addr addr; |
1141 | ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len); | 1141 | ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len); |
@@ -2858,16 +2858,16 @@ static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa) | |||
2858 | 2858 | ||
2859 | skb = alloc_skb(size, GFP_ATOMIC); | 2859 | skb = alloc_skb(size, GFP_ATOMIC); |
2860 | if (!skb) { | 2860 | if (!skb) { |
2861 | netlink_set_err(rtnl, 0, RTMGRP_IPV6_IFADDR, ENOBUFS); | 2861 | netlink_set_err(rtnl, 0, RTNLGRP_IPV6_IFADDR, ENOBUFS); |
2862 | return; | 2862 | return; |
2863 | } | 2863 | } |
2864 | if (inet6_fill_ifaddr(skb, ifa, current->pid, 0, event, 0) < 0) { | 2864 | if (inet6_fill_ifaddr(skb, ifa, current->pid, 0, event, 0) < 0) { |
2865 | kfree_skb(skb); | 2865 | kfree_skb(skb); |
2866 | netlink_set_err(rtnl, 0, RTMGRP_IPV6_IFADDR, EINVAL); | 2866 | netlink_set_err(rtnl, 0, RTNLGRP_IPV6_IFADDR, EINVAL); |
2867 | return; | 2867 | return; |
2868 | } | 2868 | } |
2869 | NETLINK_CB(skb).dst_groups = RTMGRP_IPV6_IFADDR; | 2869 | NETLINK_CB(skb).dst_group = RTNLGRP_IPV6_IFADDR; |
2870 | netlink_broadcast(rtnl, skb, 0, RTMGRP_IPV6_IFADDR, GFP_ATOMIC); | 2870 | netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV6_IFADDR, GFP_ATOMIC); |
2871 | } | 2871 | } |
2872 | 2872 | ||
2873 | static void inline ipv6_store_devconf(struct ipv6_devconf *cnf, | 2873 | static void inline ipv6_store_devconf(struct ipv6_devconf *cnf, |
@@ -2994,16 +2994,16 @@ void inet6_ifinfo_notify(int event, struct inet6_dev *idev) | |||
2994 | 2994 | ||
2995 | skb = alloc_skb(size, GFP_ATOMIC); | 2995 | skb = alloc_skb(size, GFP_ATOMIC); |
2996 | if (!skb) { | 2996 | if (!skb) { |
2997 | netlink_set_err(rtnl, 0, RTMGRP_IPV6_IFINFO, ENOBUFS); | 2997 | netlink_set_err(rtnl, 0, RTNLGRP_IPV6_IFINFO, ENOBUFS); |
2998 | return; | 2998 | return; |
2999 | } | 2999 | } |
3000 | if (inet6_fill_ifinfo(skb, idev, current->pid, 0, event, 0) < 0) { | 3000 | if (inet6_fill_ifinfo(skb, idev, current->pid, 0, event, 0) < 0) { |
3001 | kfree_skb(skb); | 3001 | kfree_skb(skb); |
3002 | netlink_set_err(rtnl, 0, RTMGRP_IPV6_IFINFO, EINVAL); | 3002 | netlink_set_err(rtnl, 0, RTNLGRP_IPV6_IFINFO, EINVAL); |
3003 | return; | 3003 | return; |
3004 | } | 3004 | } |
3005 | NETLINK_CB(skb).dst_groups = RTMGRP_IPV6_IFINFO; | 3005 | NETLINK_CB(skb).dst_group = RTNLGRP_IPV6_IFINFO; |
3006 | netlink_broadcast(rtnl, skb, 0, RTMGRP_IPV6_IFINFO, GFP_ATOMIC); | 3006 | netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV6_IFINFO, GFP_ATOMIC); |
3007 | } | 3007 | } |
3008 | 3008 | ||
3009 | static int inet6_fill_prefix(struct sk_buff *skb, struct inet6_dev *idev, | 3009 | static int inet6_fill_prefix(struct sk_buff *skb, struct inet6_dev *idev, |
@@ -3054,16 +3054,16 @@ static void inet6_prefix_notify(int event, struct inet6_dev *idev, | |||
3054 | 3054 | ||
3055 | skb = alloc_skb(size, GFP_ATOMIC); | 3055 | skb = alloc_skb(size, GFP_ATOMIC); |
3056 | if (!skb) { | 3056 | if (!skb) { |
3057 | netlink_set_err(rtnl, 0, RTMGRP_IPV6_PREFIX, ENOBUFS); | 3057 | netlink_set_err(rtnl, 0, RTNLGRP_IPV6_PREFIX, ENOBUFS); |
3058 | return; | 3058 | return; |
3059 | } | 3059 | } |
3060 | if (inet6_fill_prefix(skb, idev, pinfo, current->pid, 0, event, 0) < 0) { | 3060 | if (inet6_fill_prefix(skb, idev, pinfo, current->pid, 0, event, 0) < 0) { |
3061 | kfree_skb(skb); | 3061 | kfree_skb(skb); |
3062 | netlink_set_err(rtnl, 0, RTMGRP_IPV6_PREFIX, EINVAL); | 3062 | netlink_set_err(rtnl, 0, RTNLGRP_IPV6_PREFIX, EINVAL); |
3063 | return; | 3063 | return; |
3064 | } | 3064 | } |
3065 | NETLINK_CB(skb).dst_groups = RTMGRP_IPV6_PREFIX; | 3065 | NETLINK_CB(skb).dst_group = RTNLGRP_IPV6_PREFIX; |
3066 | netlink_broadcast(rtnl, skb, 0, RTMGRP_IPV6_PREFIX, GFP_ATOMIC); | 3066 | netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV6_PREFIX, GFP_ATOMIC); |
3067 | } | 3067 | } |
3068 | 3068 | ||
3069 | static struct rtnetlink_link inet6_rtnetlink_table[RTM_NR_MSGTYPES] = { | 3069 | static struct rtnetlink_link inet6_rtnetlink_table[RTM_NR_MSGTYPES] = { |
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 28d9bcab0970..4f8795af2edb 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -44,6 +44,7 @@ | |||
44 | #include <linux/netdevice.h> | 44 | #include <linux/netdevice.h> |
45 | #include <linux/icmpv6.h> | 45 | #include <linux/icmpv6.h> |
46 | #include <linux/smp_lock.h> | 46 | #include <linux/smp_lock.h> |
47 | #include <linux/netfilter_ipv6.h> | ||
47 | 48 | ||
48 | #include <net/ip.h> | 49 | #include <net/ip.h> |
49 | #include <net/ipv6.h> | 50 | #include <net/ipv6.h> |
@@ -66,45 +67,14 @@ MODULE_AUTHOR("Cast of dozens"); | |||
66 | MODULE_DESCRIPTION("IPv6 protocol stack for Linux"); | 67 | MODULE_DESCRIPTION("IPv6 protocol stack for Linux"); |
67 | MODULE_LICENSE("GPL"); | 68 | MODULE_LICENSE("GPL"); |
68 | 69 | ||
69 | /* IPv6 procfs goodies... */ | ||
70 | |||
71 | #ifdef CONFIG_PROC_FS | ||
72 | extern int raw6_proc_init(void); | ||
73 | extern void raw6_proc_exit(void); | ||
74 | extern int tcp6_proc_init(void); | ||
75 | extern void tcp6_proc_exit(void); | ||
76 | extern int udp6_proc_init(void); | ||
77 | extern void udp6_proc_exit(void); | ||
78 | extern int ipv6_misc_proc_init(void); | ||
79 | extern void ipv6_misc_proc_exit(void); | ||
80 | extern int ac6_proc_init(void); | ||
81 | extern void ac6_proc_exit(void); | ||
82 | extern int if6_proc_init(void); | ||
83 | extern void if6_proc_exit(void); | ||
84 | #endif | ||
85 | |||
86 | int sysctl_ipv6_bindv6only; | 70 | int sysctl_ipv6_bindv6only; |
87 | 71 | ||
88 | #ifdef INET_REFCNT_DEBUG | ||
89 | atomic_t inet6_sock_nr; | ||
90 | EXPORT_SYMBOL(inet6_sock_nr); | ||
91 | #endif | ||
92 | |||
93 | /* The inetsw table contains everything that inet_create needs to | 72 | /* The inetsw table contains everything that inet_create needs to |
94 | * build a new socket. | 73 | * build a new socket. |
95 | */ | 74 | */ |
96 | static struct list_head inetsw6[SOCK_MAX]; | 75 | static struct list_head inetsw6[SOCK_MAX]; |
97 | static DEFINE_SPINLOCK(inetsw6_lock); | 76 | static DEFINE_SPINLOCK(inetsw6_lock); |
98 | 77 | ||
99 | static void inet6_sock_destruct(struct sock *sk) | ||
100 | { | ||
101 | inet_sock_destruct(sk); | ||
102 | |||
103 | #ifdef INET_REFCNT_DEBUG | ||
104 | atomic_dec(&inet6_sock_nr); | ||
105 | #endif | ||
106 | } | ||
107 | |||
108 | static __inline__ struct ipv6_pinfo *inet6_sk_generic(struct sock *sk) | 78 | static __inline__ struct ipv6_pinfo *inet6_sk_generic(struct sock *sk) |
109 | { | 79 | { |
110 | const int offset = sk->sk_prot->obj_size - sizeof(struct ipv6_pinfo); | 80 | const int offset = sk->sk_prot->obj_size - sizeof(struct ipv6_pinfo); |
@@ -185,7 +155,7 @@ static int inet6_create(struct socket *sock, int protocol) | |||
185 | inet->hdrincl = 1; | 155 | inet->hdrincl = 1; |
186 | } | 156 | } |
187 | 157 | ||
188 | sk->sk_destruct = inet6_sock_destruct; | 158 | sk->sk_destruct = inet_sock_destruct; |
189 | sk->sk_family = PF_INET6; | 159 | sk->sk_family = PF_INET6; |
190 | sk->sk_protocol = protocol; | 160 | sk->sk_protocol = protocol; |
191 | 161 | ||
@@ -212,12 +182,17 @@ static int inet6_create(struct socket *sock, int protocol) | |||
212 | inet->pmtudisc = IP_PMTUDISC_DONT; | 182 | inet->pmtudisc = IP_PMTUDISC_DONT; |
213 | else | 183 | else |
214 | inet->pmtudisc = IP_PMTUDISC_WANT; | 184 | inet->pmtudisc = IP_PMTUDISC_WANT; |
185 | /* | ||
186 | * Increment only the relevant sk_prot->socks debug field, this changes | ||
187 | * the previous behaviour of incrementing both the equivalent to | ||
188 | * answer->prot->socks (inet6_sock_nr) and inet_sock_nr. | ||
189 | * | ||
190 | * This allows better debug granularity as we'll know exactly how many | ||
191 | * UDPv6, TCPv6, etc socks were allocated, not the sum of all IPv6 | ||
192 | * transport protocol socks. -acme | ||
193 | */ | ||
194 | sk_refcnt_debug_inc(sk); | ||
215 | 195 | ||
216 | |||
217 | #ifdef INET_REFCNT_DEBUG | ||
218 | atomic_inc(&inet6_sock_nr); | ||
219 | atomic_inc(&inet_sock_nr); | ||
220 | #endif | ||
221 | if (inet->num) { | 196 | if (inet->num) { |
222 | /* It assumes that any protocol which allows | 197 | /* It assumes that any protocol which allows |
223 | * the user to assign a number at socket | 198 | * the user to assign a number at socket |
@@ -513,11 +488,6 @@ static struct net_proto_family inet6_family_ops = { | |||
513 | .owner = THIS_MODULE, | 488 | .owner = THIS_MODULE, |
514 | }; | 489 | }; |
515 | 490 | ||
516 | #ifdef CONFIG_SYSCTL | ||
517 | extern void ipv6_sysctl_register(void); | ||
518 | extern void ipv6_sysctl_unregister(void); | ||
519 | #endif | ||
520 | |||
521 | /* Same as inet6_dgram_ops, sans udp_poll. */ | 491 | /* Same as inet6_dgram_ops, sans udp_poll. */ |
522 | static struct proto_ops inet6_sockraw_ops = { | 492 | static struct proto_ops inet6_sockraw_ops = { |
523 | .family = PF_INET6, | 493 | .family = PF_INET6, |
@@ -684,8 +654,6 @@ static void cleanup_ipv6_mibs(void) | |||
684 | snmp6_mib_free((void **)udp_stats_in6); | 654 | snmp6_mib_free((void **)udp_stats_in6); |
685 | } | 655 | } |
686 | 656 | ||
687 | extern int ipv6_misc_proc_init(void); | ||
688 | |||
689 | static int __init inet6_init(void) | 657 | static int __init inet6_init(void) |
690 | { | 658 | { |
691 | struct sk_buff *dummy_skb; | 659 | struct sk_buff *dummy_skb; |
@@ -757,6 +725,9 @@ static int __init inet6_init(void) | |||
757 | err = igmp6_init(&inet6_family_ops); | 725 | err = igmp6_init(&inet6_family_ops); |
758 | if (err) | 726 | if (err) |
759 | goto igmp_fail; | 727 | goto igmp_fail; |
728 | err = ipv6_netfilter_init(); | ||
729 | if (err) | ||
730 | goto netfilter_fail; | ||
760 | /* Create /proc/foo6 entries. */ | 731 | /* Create /proc/foo6 entries. */ |
761 | #ifdef CONFIG_PROC_FS | 732 | #ifdef CONFIG_PROC_FS |
762 | err = -ENOMEM; | 733 | err = -ENOMEM; |
@@ -813,6 +784,8 @@ proc_tcp6_fail: | |||
813 | raw6_proc_exit(); | 784 | raw6_proc_exit(); |
814 | proc_raw6_fail: | 785 | proc_raw6_fail: |
815 | #endif | 786 | #endif |
787 | ipv6_netfilter_fini(); | ||
788 | netfilter_fail: | ||
816 | igmp6_cleanup(); | 789 | igmp6_cleanup(); |
817 | igmp_fail: | 790 | igmp_fail: |
818 | ndisc_cleanup(); | 791 | ndisc_cleanup(); |
@@ -852,6 +825,7 @@ static void __exit inet6_exit(void) | |||
852 | ip6_route_cleanup(); | 825 | ip6_route_cleanup(); |
853 | ipv6_packet_cleanup(); | 826 | ipv6_packet_cleanup(); |
854 | igmp6_cleanup(); | 827 | igmp6_cleanup(); |
828 | ipv6_netfilter_fini(); | ||
855 | ndisc_cleanup(); | 829 | ndisc_cleanup(); |
856 | icmpv6_cleanup(); | 830 | icmpv6_cleanup(); |
857 | #ifdef CONFIG_SYSCTL | 831 | #ifdef CONFIG_SYSCTL |
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index 986fdfdccbcd..0ebfad907a03 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c | |||
@@ -131,10 +131,10 @@ static int ipv6_clear_mutable_options(struct ipv6hdr *iph, int len) | |||
131 | case NEXTHDR_HOP: | 131 | case NEXTHDR_HOP: |
132 | case NEXTHDR_DEST: | 132 | case NEXTHDR_DEST: |
133 | if (!zero_out_mutable_opts(exthdr.opth)) { | 133 | if (!zero_out_mutable_opts(exthdr.opth)) { |
134 | LIMIT_NETDEBUG(printk( | 134 | LIMIT_NETDEBUG( |
135 | KERN_WARNING "overrun %sopts\n", | 135 | KERN_WARNING "overrun %sopts\n", |
136 | nexthdr == NEXTHDR_HOP ? | 136 | nexthdr == NEXTHDR_HOP ? |
137 | "hop" : "dest")); | 137 | "hop" : "dest"); |
138 | return -EINVAL; | 138 | return -EINVAL; |
139 | } | 139 | } |
140 | break; | 140 | break; |
@@ -293,8 +293,7 @@ static int ah6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struc | |||
293 | skb_push(skb, skb->data - skb->nh.raw); | 293 | skb_push(skb, skb->data - skb->nh.raw); |
294 | ahp->icv(ahp, skb, ah->auth_data); | 294 | ahp->icv(ahp, skb, ah->auth_data); |
295 | if (memcmp(ah->auth_data, auth_data, ahp->icv_trunc_len)) { | 295 | if (memcmp(ah->auth_data, auth_data, ahp->icv_trunc_len)) { |
296 | LIMIT_NETDEBUG( | 296 | LIMIT_NETDEBUG(KERN_WARNING "ipsec ah authentication error\n"); |
297 | printk(KERN_WARNING "ipsec ah authentication error\n")); | ||
298 | x->stats.integrity_failed++; | 297 | x->stats.integrity_failed++; |
299 | goto free_out; | 298 | goto free_out; |
300 | } | 299 | } |
@@ -332,9 +331,9 @@ static void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
332 | if (!x) | 331 | if (!x) |
333 | return; | 332 | return; |
334 | 333 | ||
335 | NETDEBUG(printk(KERN_DEBUG "pmtu discovery on SA AH/%08x/" | 334 | NETDEBUG(KERN_DEBUG "pmtu discovery on SA AH/%08x/" |
336 | "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", | 335 | "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", |
337 | ntohl(ah->spi), NIP6(iph->daddr))); | 336 | ntohl(ah->spi), NIP6(iph->daddr)); |
338 | 337 | ||
339 | xfrm_state_put(x); | 338 | xfrm_state_put(x); |
340 | } | 339 | } |
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 5229365cd8b4..01468fab3d3d 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <net/addrconf.h> | 29 | #include <net/addrconf.h> |
30 | #include <net/transp_v6.h> | 30 | #include <net/transp_v6.h> |
31 | #include <net/ip6_route.h> | 31 | #include <net/ip6_route.h> |
32 | #include <net/tcp_states.h> | ||
32 | 33 | ||
33 | #include <linux/errqueue.h> | 34 | #include <linux/errqueue.h> |
34 | #include <asm/uaccess.h> | 35 | #include <asm/uaccess.h> |
@@ -588,8 +589,8 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl, | |||
588 | break; | 589 | break; |
589 | 590 | ||
590 | default: | 591 | default: |
591 | LIMIT_NETDEBUG( | 592 | LIMIT_NETDEBUG(KERN_DEBUG "invalid cmsg type: %d\n", |
592 | printk(KERN_DEBUG "invalid cmsg type: %d\n", cmsg->cmsg_type)); | 593 | cmsg->cmsg_type); |
593 | err = -EINVAL; | 594 | err = -EINVAL; |
594 | break; | 595 | break; |
595 | }; | 596 | }; |
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index 324db62515a2..e8bff9d3d96c 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c | |||
@@ -212,8 +212,7 @@ static int esp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, stru | |||
212 | 212 | ||
213 | padlen = nexthdr[0]; | 213 | padlen = nexthdr[0]; |
214 | if (padlen+2 >= elen) { | 214 | if (padlen+2 >= elen) { |
215 | LIMIT_NETDEBUG( | 215 | LIMIT_NETDEBUG(KERN_WARNING "ipsec esp packet is garbage padlen=%d, elen=%d\n", padlen+2, elen); |
216 | printk(KERN_WARNING "ipsec esp packet is garbage padlen=%d, elen=%d\n", padlen+2, elen)); | ||
217 | ret = -EINVAL; | 216 | ret = -EINVAL; |
218 | goto out; | 217 | goto out; |
219 | } | 218 | } |
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index e0839eafc3a9..5be6da2584ee 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c | |||
@@ -424,8 +424,8 @@ static int ipv6_hop_ra(struct sk_buff *skb, int optoff) | |||
424 | IP6CB(skb)->ra = optoff; | 424 | IP6CB(skb)->ra = optoff; |
425 | return 1; | 425 | return 1; |
426 | } | 426 | } |
427 | LIMIT_NETDEBUG( | 427 | LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_ra: wrong RA length %d\n", |
428 | printk(KERN_DEBUG "ipv6_hop_ra: wrong RA length %d\n", skb->nh.raw[optoff+1])); | 428 | skb->nh.raw[optoff+1]); |
429 | kfree_skb(skb); | 429 | kfree_skb(skb); |
430 | return 0; | 430 | return 0; |
431 | } | 431 | } |
@@ -437,8 +437,8 @@ static int ipv6_hop_jumbo(struct sk_buff *skb, int optoff) | |||
437 | u32 pkt_len; | 437 | u32 pkt_len; |
438 | 438 | ||
439 | if (skb->nh.raw[optoff+1] != 4 || (optoff&3) != 2) { | 439 | if (skb->nh.raw[optoff+1] != 4 || (optoff&3) != 2) { |
440 | LIMIT_NETDEBUG( | 440 | LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n", |
441 | printk(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n", skb->nh.raw[optoff+1])); | 441 | skb->nh.raw[optoff+1]); |
442 | IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); | 442 | IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); |
443 | goto drop; | 443 | goto drop; |
444 | } | 444 | } |
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index ff3ec9822e36..5176fc655ea9 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
@@ -67,7 +67,7 @@ | |||
67 | #include <asm/uaccess.h> | 67 | #include <asm/uaccess.h> |
68 | #include <asm/system.h> | 68 | #include <asm/system.h> |
69 | 69 | ||
70 | DEFINE_SNMP_STAT(struct icmpv6_mib, icmpv6_statistics); | 70 | DEFINE_SNMP_STAT(struct icmpv6_mib, icmpv6_statistics) __read_mostly; |
71 | 71 | ||
72 | /* | 72 | /* |
73 | * The ICMP socket(s). This is the most convenient way to flow control | 73 | * The ICMP socket(s). This is the most convenient way to flow control |
@@ -332,8 +332,7 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, | |||
332 | * for now we don't know that. | 332 | * for now we don't know that. |
333 | */ | 333 | */ |
334 | if ((addr_type == IPV6_ADDR_ANY) || (addr_type & IPV6_ADDR_MULTICAST)) { | 334 | if ((addr_type == IPV6_ADDR_ANY) || (addr_type & IPV6_ADDR_MULTICAST)) { |
335 | LIMIT_NETDEBUG( | 335 | LIMIT_NETDEBUG(KERN_DEBUG "icmpv6_send: addr_any/mcast source\n"); |
336 | printk(KERN_DEBUG "icmpv6_send: addr_any/mcast source\n")); | ||
337 | return; | 336 | return; |
338 | } | 337 | } |
339 | 338 | ||
@@ -341,8 +340,7 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, | |||
341 | * Never answer to a ICMP packet. | 340 | * Never answer to a ICMP packet. |
342 | */ | 341 | */ |
343 | if (is_ineligible(skb)) { | 342 | if (is_ineligible(skb)) { |
344 | LIMIT_NETDEBUG( | 343 | LIMIT_NETDEBUG(KERN_DEBUG "icmpv6_send: no reply to icmp error\n"); |
345 | printk(KERN_DEBUG "icmpv6_send: no reply to icmp error\n")); | ||
346 | return; | 344 | return; |
347 | } | 345 | } |
348 | 346 | ||
@@ -393,8 +391,7 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, | |||
393 | len = skb->len - msg.offset; | 391 | len = skb->len - msg.offset; |
394 | len = min_t(unsigned int, len, IPV6_MIN_MTU - sizeof(struct ipv6hdr) -sizeof(struct icmp6hdr)); | 392 | len = min_t(unsigned int, len, IPV6_MIN_MTU - sizeof(struct ipv6hdr) -sizeof(struct icmp6hdr)); |
395 | if (len < 0) { | 393 | if (len < 0) { |
396 | LIMIT_NETDEBUG( | 394 | LIMIT_NETDEBUG(KERN_DEBUG "icmp: len problem\n"); |
397 | printk(KERN_DEBUG "icmp: len problem\n")); | ||
398 | goto out_dst_release; | 395 | goto out_dst_release; |
399 | } | 396 | } |
400 | 397 | ||
@@ -551,7 +548,8 @@ static void icmpv6_notify(struct sk_buff *skb, int type, int code, u32 info) | |||
551 | 548 | ||
552 | read_lock(&raw_v6_lock); | 549 | read_lock(&raw_v6_lock); |
553 | if ((sk = sk_head(&raw_v6_htable[hash])) != NULL) { | 550 | if ((sk = sk_head(&raw_v6_htable[hash])) != NULL) { |
554 | while((sk = __raw_v6_lookup(sk, nexthdr, daddr, saddr))) { | 551 | while((sk = __raw_v6_lookup(sk, nexthdr, daddr, saddr, |
552 | skb->dev->ifindex))) { | ||
555 | rawv6_err(sk, skb, NULL, type, code, inner_offset, info); | 553 | rawv6_err(sk, skb, NULL, type, code, inner_offset, info); |
556 | sk = sk_next(sk); | 554 | sk = sk_next(sk); |
557 | } | 555 | } |
@@ -583,17 +581,15 @@ static int icmpv6_rcv(struct sk_buff **pskb, unsigned int *nhoffp) | |||
583 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 581 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
584 | if (csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_ICMPV6, | 582 | if (csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_ICMPV6, |
585 | skb->csum)) { | 583 | skb->csum)) { |
586 | LIMIT_NETDEBUG( | 584 | LIMIT_NETDEBUG(KERN_DEBUG "ICMPv6 hw checksum failed\n"); |
587 | printk(KERN_DEBUG "ICMPv6 hw checksum failed\n")); | ||
588 | skb->ip_summed = CHECKSUM_NONE; | 585 | skb->ip_summed = CHECKSUM_NONE; |
589 | } | 586 | } |
590 | } | 587 | } |
591 | if (skb->ip_summed == CHECKSUM_NONE) { | 588 | if (skb->ip_summed == CHECKSUM_NONE) { |
592 | if (csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_ICMPV6, | 589 | if (csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_ICMPV6, |
593 | skb_checksum(skb, 0, skb->len, 0))) { | 590 | skb_checksum(skb, 0, skb->len, 0))) { |
594 | LIMIT_NETDEBUG( | 591 | LIMIT_NETDEBUG(KERN_DEBUG "ICMPv6 checksum failed [%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x > %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]\n", |
595 | printk(KERN_DEBUG "ICMPv6 checksum failed [%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x > %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]\n", | 592 | NIP6(*saddr), NIP6(*daddr)); |
596 | NIP6(*saddr), NIP6(*daddr))); | ||
597 | goto discard_it; | 593 | goto discard_it; |
598 | } | 594 | } |
599 | } | 595 | } |
@@ -669,8 +665,7 @@ static int icmpv6_rcv(struct sk_buff **pskb, unsigned int *nhoffp) | |||
669 | break; | 665 | break; |
670 | 666 | ||
671 | default: | 667 | default: |
672 | LIMIT_NETDEBUG( | 668 | LIMIT_NETDEBUG(KERN_DEBUG "icmpv6: msg of unknown type\n"); |
673 | printk(KERN_DEBUG "icmpv6: msg of unknown type\n")); | ||
674 | 669 | ||
675 | /* informational */ | 670 | /* informational */ |
676 | if (type & ICMPV6_INFOMSG_MASK) | 671 | if (type & ICMPV6_INFOMSG_MASK) |
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c new file mode 100644 index 000000000000..01d5f46d4e40 --- /dev/null +++ b/net/ipv6/inet6_hashtables.c | |||
@@ -0,0 +1,81 @@ | |||
1 | /* | ||
2 | * INET An implementation of the TCP/IP protocol suite for the LINUX | ||
3 | * operating system. INET is implemented using the BSD Socket | ||
4 | * interface as the means of communication with the user level. | ||
5 | * | ||
6 | * Generic INET6 transport hashtables | ||
7 | * | ||
8 | * Authors: Lotsa people, from code originally in tcp | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU General Public License | ||
12 | * as published by the Free Software Foundation; either version | ||
13 | * 2 of the License, or (at your option) any later version. | ||
14 | */ | ||
15 | |||
16 | #include <linux/config.h> | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | |||
20 | #include <net/inet_connection_sock.h> | ||
21 | #include <net/inet_hashtables.h> | ||
22 | #include <net/inet6_hashtables.h> | ||
23 | |||
24 | struct sock *inet6_lookup_listener(struct inet_hashinfo *hashinfo, | ||
25 | const struct in6_addr *daddr, | ||
26 | const unsigned short hnum, const int dif) | ||
27 | { | ||
28 | struct sock *sk; | ||
29 | const struct hlist_node *node; | ||
30 | struct sock *result = NULL; | ||
31 | int score, hiscore = 0; | ||
32 | |||
33 | read_lock(&hashinfo->lhash_lock); | ||
34 | sk_for_each(sk, node, &hashinfo->listening_hash[inet_lhashfn(hnum)]) { | ||
35 | if (inet_sk(sk)->num == hnum && sk->sk_family == PF_INET6) { | ||
36 | const struct ipv6_pinfo *np = inet6_sk(sk); | ||
37 | |||
38 | score = 1; | ||
39 | if (!ipv6_addr_any(&np->rcv_saddr)) { | ||
40 | if (!ipv6_addr_equal(&np->rcv_saddr, daddr)) | ||
41 | continue; | ||
42 | score++; | ||
43 | } | ||
44 | if (sk->sk_bound_dev_if) { | ||
45 | if (sk->sk_bound_dev_if != dif) | ||
46 | continue; | ||
47 | score++; | ||
48 | } | ||
49 | if (score == 3) { | ||
50 | result = sk; | ||
51 | break; | ||
52 | } | ||
53 | if (score > hiscore) { | ||
54 | hiscore = score; | ||
55 | result = sk; | ||
56 | } | ||
57 | } | ||
58 | } | ||
59 | if (result) | ||
60 | sock_hold(result); | ||
61 | read_unlock(&hashinfo->lhash_lock); | ||
62 | return result; | ||
63 | } | ||
64 | |||
65 | EXPORT_SYMBOL_GPL(inet6_lookup_listener); | ||
66 | |||
67 | struct sock *inet6_lookup(struct inet_hashinfo *hashinfo, | ||
68 | const struct in6_addr *saddr, const u16 sport, | ||
69 | const struct in6_addr *daddr, const u16 dport, | ||
70 | const int dif) | ||
71 | { | ||
72 | struct sock *sk; | ||
73 | |||
74 | local_bh_disable(); | ||
75 | sk = __inet6_lookup(hashinfo, saddr, sport, daddr, ntohs(dport), dif); | ||
76 | local_bh_enable(); | ||
77 | |||
78 | return sk; | ||
79 | } | ||
80 | |||
81 | EXPORT_SYMBOL_GPL(inet6_lookup); | ||
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 1b354aa97934..16af874c9e8f 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c | |||
@@ -49,7 +49,7 @@ | |||
49 | 49 | ||
50 | struct rt6_statistics rt6_stats; | 50 | struct rt6_statistics rt6_stats; |
51 | 51 | ||
52 | static kmem_cache_t * fib6_node_kmem; | 52 | static kmem_cache_t * fib6_node_kmem __read_mostly; |
53 | 53 | ||
54 | enum fib_walk_state_t | 54 | enum fib_walk_state_t |
55 | { | 55 | { |
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index 10fbb50daea4..6e3480426939 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c | |||
@@ -56,7 +56,7 @@ static inline int ip6_rcv_finish( struct sk_buff *skb) | |||
56 | return dst_input(skb); | 56 | return dst_input(skb); |
57 | } | 57 | } |
58 | 58 | ||
59 | int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt) | 59 | int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev) |
60 | { | 60 | { |
61 | struct ipv6hdr *hdr; | 61 | struct ipv6hdr *hdr; |
62 | u32 pkt_len; | 62 | u32 pkt_len; |
@@ -166,8 +166,8 @@ resubmit: | |||
166 | nexthdr = skb->nh.raw[nhoff]; | 166 | nexthdr = skb->nh.raw[nhoff]; |
167 | 167 | ||
168 | raw_sk = sk_head(&raw_v6_htable[nexthdr & (MAX_INET_PROTOS - 1)]); | 168 | raw_sk = sk_head(&raw_v6_htable[nexthdr & (MAX_INET_PROTOS - 1)]); |
169 | if (raw_sk) | 169 | if (raw_sk && !ipv6_raw_deliver(skb, nexthdr)) |
170 | ipv6_raw_deliver(skb, nexthdr); | 170 | raw_sk = NULL; |
171 | 171 | ||
172 | hash = nexthdr & (MAX_INET_PROTOS - 1); | 172 | hash = nexthdr & (MAX_INET_PROTOS - 1); |
173 | if ((ipprot = rcu_dereference(inet6_protos[hash])) != NULL) { | 173 | if ((ipprot = rcu_dereference(inet6_protos[hash])) != NULL) { |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index ae652ca14bc9..01ef94f7c7f1 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -153,51 +153,6 @@ int ip6_output(struct sk_buff *skb) | |||
153 | return ip6_output2(skb); | 153 | return ip6_output2(skb); |
154 | } | 154 | } |
155 | 155 | ||
156 | #ifdef CONFIG_NETFILTER | ||
157 | int ip6_route_me_harder(struct sk_buff *skb) | ||
158 | { | ||
159 | struct ipv6hdr *iph = skb->nh.ipv6h; | ||
160 | struct dst_entry *dst; | ||
161 | struct flowi fl = { | ||
162 | .oif = skb->sk ? skb->sk->sk_bound_dev_if : 0, | ||
163 | .nl_u = | ||
164 | { .ip6_u = | ||
165 | { .daddr = iph->daddr, | ||
166 | .saddr = iph->saddr, } }, | ||
167 | .proto = iph->nexthdr, | ||
168 | }; | ||
169 | |||
170 | dst = ip6_route_output(skb->sk, &fl); | ||
171 | |||
172 | if (dst->error) { | ||
173 | IP6_INC_STATS(IPSTATS_MIB_OUTNOROUTES); | ||
174 | LIMIT_NETDEBUG( | ||
175 | printk(KERN_DEBUG "ip6_route_me_harder: No more route.\n")); | ||
176 | dst_release(dst); | ||
177 | return -EINVAL; | ||
178 | } | ||
179 | |||
180 | /* Drop old route. */ | ||
181 | dst_release(skb->dst); | ||
182 | |||
183 | skb->dst = dst; | ||
184 | return 0; | ||
185 | } | ||
186 | #endif | ||
187 | |||
188 | static inline int ip6_maybe_reroute(struct sk_buff *skb) | ||
189 | { | ||
190 | #ifdef CONFIG_NETFILTER | ||
191 | if (skb->nfcache & NFC_ALTERED){ | ||
192 | if (ip6_route_me_harder(skb) != 0){ | ||
193 | kfree_skb(skb); | ||
194 | return -EINVAL; | ||
195 | } | ||
196 | } | ||
197 | #endif /* CONFIG_NETFILTER */ | ||
198 | return dst_output(skb); | ||
199 | } | ||
200 | |||
201 | /* | 156 | /* |
202 | * xmit an sk_buff (used by TCP) | 157 | * xmit an sk_buff (used by TCP) |
203 | */ | 158 | */ |
@@ -266,7 +221,8 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, | |||
266 | mtu = dst_mtu(dst); | 221 | mtu = dst_mtu(dst); |
267 | if ((skb->len <= mtu) || ipfragok) { | 222 | if ((skb->len <= mtu) || ipfragok) { |
268 | IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS); | 223 | IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS); |
269 | return NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, ip6_maybe_reroute); | 224 | return NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, |
225 | dst_output); | ||
270 | } | 226 | } |
271 | 227 | ||
272 | if (net_ratelimit()) | 228 | if (net_ratelimit()) |
@@ -321,7 +277,9 @@ static int ip6_call_ra_chain(struct sk_buff *skb, int sel) | |||
321 | read_lock(&ip6_ra_lock); | 277 | read_lock(&ip6_ra_lock); |
322 | for (ra = ip6_ra_chain; ra; ra = ra->next) { | 278 | for (ra = ip6_ra_chain; ra; ra = ra->next) { |
323 | struct sock *sk = ra->sk; | 279 | struct sock *sk = ra->sk; |
324 | if (sk && ra->sel == sel) { | 280 | if (sk && ra->sel == sel && |
281 | (!sk->sk_bound_dev_if || | ||
282 | sk->sk_bound_dev_if == skb->dev->ifindex)) { | ||
325 | if (last) { | 283 | if (last) { |
326 | struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); | 284 | struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); |
327 | if (skb2) | 285 | if (skb2) |
@@ -667,7 +625,7 @@ slow_path: | |||
667 | */ | 625 | */ |
668 | 626 | ||
669 | if ((frag = alloc_skb(len+hlen+sizeof(struct frag_hdr)+LL_RESERVED_SPACE(rt->u.dst.dev), GFP_ATOMIC)) == NULL) { | 627 | if ((frag = alloc_skb(len+hlen+sizeof(struct frag_hdr)+LL_RESERVED_SPACE(rt->u.dst.dev), GFP_ATOMIC)) == NULL) { |
670 | NETDEBUG(printk(KERN_INFO "IPv6: frag: no memory for new fragment!\n")); | 628 | NETDEBUG(KERN_INFO "IPv6: frag: no memory for new fragment!\n"); |
671 | IP6_INC_STATS(IPSTATS_MIB_FRAGFAILS); | 629 | IP6_INC_STATS(IPSTATS_MIB_FRAGFAILS); |
672 | err = -ENOMEM; | 630 | err = -ENOMEM; |
673 | goto fail; | 631 | goto fail; |
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 3bc144a79fa5..76466af8331e 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c | |||
@@ -55,7 +55,7 @@ | |||
55 | 55 | ||
56 | #include <asm/uaccess.h> | 56 | #include <asm/uaccess.h> |
57 | 57 | ||
58 | DEFINE_SNMP_STAT(struct ipstats_mib, ipv6_statistics); | 58 | DEFINE_SNMP_STAT(struct ipstats_mib, ipv6_statistics) __read_mostly; |
59 | 59 | ||
60 | static struct packet_type ipv6_packet_type = { | 60 | static struct packet_type ipv6_packet_type = { |
61 | .type = __constant_htons(ETH_P_IPV6), | 61 | .type = __constant_htons(ETH_P_IPV6), |
@@ -109,13 +109,6 @@ int ip6_ra_control(struct sock *sk, int sel, void (*destructor)(struct sock *)) | |||
109 | return 0; | 109 | return 0; |
110 | } | 110 | } |
111 | 111 | ||
112 | extern int ip6_mc_source(int add, int omode, struct sock *sk, | ||
113 | struct group_source_req *pgsr); | ||
114 | extern int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf); | ||
115 | extern int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf, | ||
116 | struct group_filter __user *optval, int __user *optlen); | ||
117 | |||
118 | |||
119 | int ipv6_setsockopt(struct sock *sk, int level, int optname, | 112 | int ipv6_setsockopt(struct sock *sk, int level, int optname, |
120 | char __user *optval, int optlen) | 113 | char __user *optval, int optlen) |
121 | { | 114 | { |
@@ -163,6 +156,13 @@ int ipv6_setsockopt(struct sock *sk, int level, int optname, | |||
163 | fl6_free_socklist(sk); | 156 | fl6_free_socklist(sk); |
164 | ipv6_sock_mc_close(sk); | 157 | ipv6_sock_mc_close(sk); |
165 | 158 | ||
159 | /* | ||
160 | * Sock is moving from IPv6 to IPv4 (sk_prot), so | ||
161 | * remove it from the refcnt debug socks count in the | ||
162 | * original family... | ||
163 | */ | ||
164 | sk_refcnt_debug_dec(sk); | ||
165 | |||
166 | if (sk->sk_protocol == IPPROTO_TCP) { | 166 | if (sk->sk_protocol == IPPROTO_TCP) { |
167 | struct tcp_sock *tp = tcp_sk(sk); | 167 | struct tcp_sock *tp = tcp_sk(sk); |
168 | 168 | ||
@@ -192,9 +192,11 @@ int ipv6_setsockopt(struct sock *sk, int level, int optname, | |||
192 | kfree_skb(pktopt); | 192 | kfree_skb(pktopt); |
193 | 193 | ||
194 | sk->sk_destruct = inet_sock_destruct; | 194 | sk->sk_destruct = inet_sock_destruct; |
195 | #ifdef INET_REFCNT_DEBUG | 195 | /* |
196 | atomic_dec(&inet6_sock_nr); | 196 | * ... and add it to the refcnt debug socks count |
197 | #endif | 197 | * in the new family. -acme |
198 | */ | ||
199 | sk_refcnt_debug_inc(sk); | ||
198 | module_put(THIS_MODULE); | 200 | module_put(THIS_MODULE); |
199 | retv = 0; | 201 | retv = 0; |
200 | break; | 202 | break; |
@@ -437,7 +439,6 @@ done: | |||
437 | } | 439 | } |
438 | case MCAST_MSFILTER: | 440 | case MCAST_MSFILTER: |
439 | { | 441 | { |
440 | extern int sysctl_optmem_max; | ||
441 | extern int sysctl_mld_max_msf; | 442 | extern int sysctl_mld_max_msf; |
442 | struct group_filter *gsf; | 443 | struct group_filter *gsf; |
443 | 444 | ||
diff --git a/net/ipv6/ipv6_syms.c b/net/ipv6/ipv6_syms.c index 5ade5a5d1990..37a4a99c9fe9 100644 --- a/net/ipv6/ipv6_syms.c +++ b/net/ipv6/ipv6_syms.c | |||
@@ -15,9 +15,6 @@ EXPORT_SYMBOL(ndisc_mc_map); | |||
15 | EXPORT_SYMBOL(register_inet6addr_notifier); | 15 | EXPORT_SYMBOL(register_inet6addr_notifier); |
16 | EXPORT_SYMBOL(unregister_inet6addr_notifier); | 16 | EXPORT_SYMBOL(unregister_inet6addr_notifier); |
17 | EXPORT_SYMBOL(ip6_route_output); | 17 | EXPORT_SYMBOL(ip6_route_output); |
18 | #ifdef CONFIG_NETFILTER | ||
19 | EXPORT_SYMBOL(ip6_route_me_harder); | ||
20 | #endif | ||
21 | EXPORT_SYMBOL(addrconf_lock); | 18 | EXPORT_SYMBOL(addrconf_lock); |
22 | EXPORT_SYMBOL(ipv6_setsockopt); | 19 | EXPORT_SYMBOL(ipv6_setsockopt); |
23 | EXPORT_SYMBOL(ipv6_getsockopt); | 20 | EXPORT_SYMBOL(ipv6_getsockopt); |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 7ae72d4c9bd2..a7eae30f4554 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -812,7 +812,7 @@ static void ndisc_recv_ns(struct sk_buff *skb) | |||
812 | if (ipv6_chk_acast_addr(dev, &msg->target) || | 812 | if (ipv6_chk_acast_addr(dev, &msg->target) || |
813 | (idev->cnf.forwarding && | 813 | (idev->cnf.forwarding && |
814 | pneigh_lookup(&nd_tbl, &msg->target, dev, 0))) { | 814 | pneigh_lookup(&nd_tbl, &msg->target, dev, 0))) { |
815 | if (skb->stamp.tv_sec != LOCALLY_ENQUEUED && | 815 | if (!(NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED) && |
816 | skb->pkt_type != PACKET_HOST && | 816 | skb->pkt_type != PACKET_HOST && |
817 | inc != 0 && | 817 | inc != 0 && |
818 | idev->nd_parms->proxy_delay != 0) { | 818 | idev->nd_parms->proxy_delay != 0) { |
@@ -1487,6 +1487,8 @@ int ndisc_rcv(struct sk_buff *skb) | |||
1487 | return 0; | 1487 | return 0; |
1488 | } | 1488 | } |
1489 | 1489 | ||
1490 | memset(NEIGH_CB(skb), 0, sizeof(struct neighbour_cb)); | ||
1491 | |||
1490 | switch (msg->icmph.icmp6_type) { | 1492 | switch (msg->icmph.icmp6_type) { |
1491 | case NDISC_NEIGHBOUR_SOLICITATION: | 1493 | case NDISC_NEIGHBOUR_SOLICITATION: |
1492 | ndisc_recv_ns(skb); | 1494 | ndisc_recv_ns(skb); |
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c new file mode 100644 index 000000000000..f8626ebf90fd --- /dev/null +++ b/net/ipv6/netfilter.c | |||
@@ -0,0 +1,104 @@ | |||
1 | #include <linux/config.h> | ||
2 | #include <linux/init.h> | ||
3 | |||
4 | #ifdef CONFIG_NETFILTER | ||
5 | |||
6 | #include <linux/kernel.h> | ||
7 | #include <linux/ipv6.h> | ||
8 | #include <linux/netfilter.h> | ||
9 | #include <linux/netfilter_ipv6.h> | ||
10 | #include <net/dst.h> | ||
11 | #include <net/ipv6.h> | ||
12 | #include <net/ip6_route.h> | ||
13 | |||
14 | int ip6_route_me_harder(struct sk_buff *skb) | ||
15 | { | ||
16 | struct ipv6hdr *iph = skb->nh.ipv6h; | ||
17 | struct dst_entry *dst; | ||
18 | struct flowi fl = { | ||
19 | .oif = skb->sk ? skb->sk->sk_bound_dev_if : 0, | ||
20 | .nl_u = | ||
21 | { .ip6_u = | ||
22 | { .daddr = iph->daddr, | ||
23 | .saddr = iph->saddr, } }, | ||
24 | .proto = iph->nexthdr, | ||
25 | }; | ||
26 | |||
27 | dst = ip6_route_output(skb->sk, &fl); | ||
28 | |||
29 | if (dst->error) { | ||
30 | IP6_INC_STATS(IPSTATS_MIB_OUTNOROUTES); | ||
31 | LIMIT_NETDEBUG(KERN_DEBUG "ip6_route_me_harder: No more route.\n"); | ||
32 | dst_release(dst); | ||
33 | return -EINVAL; | ||
34 | } | ||
35 | |||
36 | /* Drop old route. */ | ||
37 | dst_release(skb->dst); | ||
38 | |||
39 | skb->dst = dst; | ||
40 | return 0; | ||
41 | } | ||
42 | EXPORT_SYMBOL(ip6_route_me_harder); | ||
43 | |||
44 | /* | ||
45 | * Extra routing may needed on local out, as the QUEUE target never | ||
46 | * returns control to the table. | ||
47 | */ | ||
48 | |||
49 | struct ip6_rt_info { | ||
50 | struct in6_addr daddr; | ||
51 | struct in6_addr saddr; | ||
52 | }; | ||
53 | |||
54 | static void save(const struct sk_buff *skb, struct nf_info *info) | ||
55 | { | ||
56 | struct ip6_rt_info *rt_info = nf_info_reroute(info); | ||
57 | |||
58 | if (info->hook == NF_IP6_LOCAL_OUT) { | ||
59 | struct ipv6hdr *iph = skb->nh.ipv6h; | ||
60 | |||
61 | rt_info->daddr = iph->daddr; | ||
62 | rt_info->saddr = iph->saddr; | ||
63 | } | ||
64 | } | ||
65 | |||
66 | static int reroute(struct sk_buff **pskb, const struct nf_info *info) | ||
67 | { | ||
68 | struct ip6_rt_info *rt_info = nf_info_reroute(info); | ||
69 | |||
70 | if (info->hook == NF_IP6_LOCAL_OUT) { | ||
71 | struct ipv6hdr *iph = (*pskb)->nh.ipv6h; | ||
72 | if (!ipv6_addr_equal(&iph->daddr, &rt_info->daddr) || | ||
73 | !ipv6_addr_equal(&iph->saddr, &rt_info->saddr)) | ||
74 | return ip6_route_me_harder(*pskb); | ||
75 | } | ||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | static struct nf_queue_rerouter ip6_reroute = { | ||
80 | .rer_size = sizeof(struct ip6_rt_info), | ||
81 | .save = &save, | ||
82 | .reroute = &reroute, | ||
83 | }; | ||
84 | |||
85 | int __init ipv6_netfilter_init(void) | ||
86 | { | ||
87 | return nf_register_queue_rerouter(PF_INET6, &ip6_reroute); | ||
88 | } | ||
89 | |||
90 | void ipv6_netfilter_fini(void) | ||
91 | { | ||
92 | nf_unregister_queue_rerouter(PF_INET6); | ||
93 | } | ||
94 | |||
95 | #else /* CONFIG_NETFILTER */ | ||
96 | int __init ipv6_netfilter_init(void) | ||
97 | { | ||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | void ipv6_netfilter_fini(void) | ||
102 | { | ||
103 | } | ||
104 | #endif /* CONFIG_NETFILTER */ | ||
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig index 77ec704c9ee3..216fbe1ac65c 100644 --- a/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig | |||
@@ -10,13 +10,16 @@ menu "IPv6: Netfilter Configuration (EXPERIMENTAL)" | |||
10 | # dep_tristate ' FTP protocol support' CONFIG_IP6_NF_FTP $CONFIG_IP6_NF_CONNTRACK | 10 | # dep_tristate ' FTP protocol support' CONFIG_IP6_NF_FTP $CONFIG_IP6_NF_CONNTRACK |
11 | #fi | 11 | #fi |
12 | config IP6_NF_QUEUE | 12 | config IP6_NF_QUEUE |
13 | tristate "Userspace queueing via NETLINK" | 13 | tristate "IP6 Userspace queueing via NETLINK (OBSOLETE)" |
14 | ---help--- | 14 | ---help--- |
15 | 15 | ||
16 | This option adds a queue handler to the kernel for IPv6 | 16 | This option adds a queue handler to the kernel for IPv6 |
17 | packets which lets us to receive the filtered packets | 17 | packets which enables users to receive the filtered packets |
18 | with QUEUE target using libiptc as we can do with | 18 | with QUEUE target using libipq. |
19 | the IPv4 now. | 19 | |
20 | THis option enables the old IPv6-only "ip6_queue" implementation | ||
21 | which has been obsoleted by the new "nfnetlink_queue" code (see | ||
22 | CONFIG_NETFILTER_NETLINK_QUEUE). | ||
20 | 23 | ||
21 | (C) Fernando Anton 2001 | 24 | (C) Fernando Anton 2001 |
22 | IPv64 Project - Work based in IPv64 draft by Arturo Azcorra. | 25 | IPv64 Project - Work based in IPv64 draft by Arturo Azcorra. |
@@ -196,6 +199,16 @@ config IP6_NF_TARGET_LOG | |||
196 | 199 | ||
197 | To compile it as a module, choose M here. If unsure, say N. | 200 | To compile it as a module, choose M here. If unsure, say N. |
198 | 201 | ||
202 | config IP6_NF_TARGET_REJECT | ||
203 | tristate "REJECT target support" | ||
204 | depends on IP6_NF_FILTER | ||
205 | help | ||
206 | The REJECT target allows a filtering rule to specify that an ICMPv6 | ||
207 | error should be issued in response to an incoming packet, rather | ||
208 | than silently being dropped. | ||
209 | |||
210 | To compile it as a module, choose M here. If unsure, say N. | ||
211 | |||
199 | # if [ "$CONFIG_IP6_NF_FILTER" != "n" ]; then | 212 | # if [ "$CONFIG_IP6_NF_FILTER" != "n" ]; then |
200 | # dep_tristate ' REJECT target support' CONFIG_IP6_NF_TARGET_REJECT $CONFIG_IP6_NF_FILTER | 213 | # dep_tristate ' REJECT target support' CONFIG_IP6_NF_TARGET_REJECT $CONFIG_IP6_NF_FILTER |
201 | # if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then | 214 | # if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then |
@@ -226,6 +239,22 @@ config IP6_NF_TARGET_MARK | |||
226 | 239 | ||
227 | To compile it as a module, choose M here. If unsure, say N. | 240 | To compile it as a module, choose M here. If unsure, say N. |
228 | 241 | ||
242 | config IP6_NF_TARGET_HL | ||
243 | tristate 'HL (hoplimit) target support' | ||
244 | depends on IP6_NF_MANGLE | ||
245 | help | ||
246 | This option adds a `HL' target, which enables the user to decrement | ||
247 | the hoplimit value of the IPv6 header or set it to a given (lower) | ||
248 | value. | ||
249 | |||
250 | While it is safe to decrement the hoplimit value, this option also | ||
251 | enables functionality to increment and set the hoplimit value of the | ||
252 | IPv6 header to arbitrary values. This is EXTREMELY DANGEROUS since | ||
253 | you can easily create immortal packets that loop forever on the | ||
254 | network. | ||
255 | |||
256 | To compile it as a module, choose M here. If unsure, say N. | ||
257 | |||
229 | #dep_tristate ' LOG target support' CONFIG_IP6_NF_TARGET_LOG $CONFIG_IP6_NF_IPTABLES | 258 | #dep_tristate ' LOG target support' CONFIG_IP6_NF_TARGET_LOG $CONFIG_IP6_NF_IPTABLES |
230 | config IP6_NF_RAW | 259 | config IP6_NF_RAW |
231 | tristate 'raw table support (required for TRACE)' | 260 | tristate 'raw table support (required for TRACE)' |
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile index 2e51714953b6..bd9a16a5cbba 100644 --- a/net/ipv6/netfilter/Makefile +++ b/net/ipv6/netfilter/Makefile | |||
@@ -20,7 +20,10 @@ obj-$(CONFIG_IP6_NF_MATCH_PHYSDEV) += ip6t_physdev.o | |||
20 | obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o | 20 | obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o |
21 | obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o | 21 | obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o |
22 | obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o | 22 | obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o |
23 | obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o | ||
23 | obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o | 24 | obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o |
24 | obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o | 25 | obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o |
25 | obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o | 26 | obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o |
26 | obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o | 27 | obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o |
28 | obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o | ||
29 | obj-$(CONFIG_NETFILTER_NETLINK_QUEUE) += ip6t_NFQUEUE.o | ||
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index a16df5b27c84..aa11cf366efa 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c | |||
@@ -47,16 +47,10 @@ | |||
47 | #define NET_IPQ_QMAX 2088 | 47 | #define NET_IPQ_QMAX 2088 |
48 | #define NET_IPQ_QMAX_NAME "ip6_queue_maxlen" | 48 | #define NET_IPQ_QMAX_NAME "ip6_queue_maxlen" |
49 | 49 | ||
50 | struct ipq_rt_info { | ||
51 | struct in6_addr daddr; | ||
52 | struct in6_addr saddr; | ||
53 | }; | ||
54 | |||
55 | struct ipq_queue_entry { | 50 | struct ipq_queue_entry { |
56 | struct list_head list; | 51 | struct list_head list; |
57 | struct nf_info *info; | 52 | struct nf_info *info; |
58 | struct sk_buff *skb; | 53 | struct sk_buff *skb; |
59 | struct ipq_rt_info rt_info; | ||
60 | }; | 54 | }; |
61 | 55 | ||
62 | typedef int (*ipq_cmpfn)(struct ipq_queue_entry *, unsigned long); | 56 | typedef int (*ipq_cmpfn)(struct ipq_queue_entry *, unsigned long); |
@@ -244,8 +238,8 @@ ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp) | |||
244 | 238 | ||
245 | pmsg->packet_id = (unsigned long )entry; | 239 | pmsg->packet_id = (unsigned long )entry; |
246 | pmsg->data_len = data_len; | 240 | pmsg->data_len = data_len; |
247 | pmsg->timestamp_sec = entry->skb->stamp.tv_sec; | 241 | pmsg->timestamp_sec = skb_tv_base.tv_sec + entry->skb->tstamp.off_sec; |
248 | pmsg->timestamp_usec = entry->skb->stamp.tv_usec; | 242 | pmsg->timestamp_usec = skb_tv_base.tv_usec + entry->skb->tstamp.off_usec; |
249 | pmsg->mark = entry->skb->nfmark; | 243 | pmsg->mark = entry->skb->nfmark; |
250 | pmsg->hook = entry->info->hook; | 244 | pmsg->hook = entry->info->hook; |
251 | pmsg->hw_protocol = entry->skb->protocol; | 245 | pmsg->hw_protocol = entry->skb->protocol; |
@@ -284,7 +278,8 @@ nlmsg_failure: | |||
284 | } | 278 | } |
285 | 279 | ||
286 | static int | 280 | static int |
287 | ipq_enqueue_packet(struct sk_buff *skb, struct nf_info *info, void *data) | 281 | ipq_enqueue_packet(struct sk_buff *skb, struct nf_info *info, |
282 | unsigned int queuenum, void *data) | ||
288 | { | 283 | { |
289 | int status = -EINVAL; | 284 | int status = -EINVAL; |
290 | struct sk_buff *nskb; | 285 | struct sk_buff *nskb; |
@@ -302,13 +297,6 @@ ipq_enqueue_packet(struct sk_buff *skb, struct nf_info *info, void *data) | |||
302 | entry->info = info; | 297 | entry->info = info; |
303 | entry->skb = skb; | 298 | entry->skb = skb; |
304 | 299 | ||
305 | if (entry->info->hook == NF_IP_LOCAL_OUT) { | ||
306 | struct ipv6hdr *iph = skb->nh.ipv6h; | ||
307 | |||
308 | entry->rt_info.daddr = iph->daddr; | ||
309 | entry->rt_info.saddr = iph->saddr; | ||
310 | } | ||
311 | |||
312 | nskb = ipq_build_packet_message(entry, &status); | 300 | nskb = ipq_build_packet_message(entry, &status); |
313 | if (nskb == NULL) | 301 | if (nskb == NULL) |
314 | goto err_out_free; | 302 | goto err_out_free; |
@@ -384,23 +372,11 @@ ipq_mangle_ipv6(ipq_verdict_msg_t *v, struct ipq_queue_entry *e) | |||
384 | } | 372 | } |
385 | skb_put(e->skb, diff); | 373 | skb_put(e->skb, diff); |
386 | } | 374 | } |
387 | if (!skb_ip_make_writable(&e->skb, v->data_len)) | 375 | if (!skb_make_writable(&e->skb, v->data_len)) |
388 | return -ENOMEM; | 376 | return -ENOMEM; |
389 | memcpy(e->skb->data, v->payload, v->data_len); | 377 | memcpy(e->skb->data, v->payload, v->data_len); |
390 | e->skb->ip_summed = CHECKSUM_NONE; | 378 | e->skb->ip_summed = CHECKSUM_NONE; |
391 | e->skb->nfcache |= NFC_ALTERED; | 379 | |
392 | |||
393 | /* | ||
394 | * Extra routing may needed on local out, as the QUEUE target never | ||
395 | * returns control to the table. | ||
396 | * Not a nice way to cmp, but works | ||
397 | */ | ||
398 | if (e->info->hook == NF_IP_LOCAL_OUT) { | ||
399 | struct ipv6hdr *iph = e->skb->nh.ipv6h; | ||
400 | if (!ipv6_addr_equal(&iph->daddr, &e->rt_info.daddr) || | ||
401 | !ipv6_addr_equal(&iph->saddr, &e->rt_info.saddr)) | ||
402 | return ip6_route_me_harder(e->skb); | ||
403 | } | ||
404 | return 0; | 380 | return 0; |
405 | } | 381 | } |
406 | 382 | ||
@@ -676,6 +652,11 @@ ipq_get_info(char *buffer, char **start, off_t offset, int length) | |||
676 | return len; | 652 | return len; |
677 | } | 653 | } |
678 | 654 | ||
655 | static struct nf_queue_handler nfqh = { | ||
656 | .name = "ip6_queue", | ||
657 | .outfn = &ipq_enqueue_packet, | ||
658 | }; | ||
659 | |||
679 | static int | 660 | static int |
680 | init_or_cleanup(int init) | 661 | init_or_cleanup(int init) |
681 | { | 662 | { |
@@ -686,7 +667,8 @@ init_or_cleanup(int init) | |||
686 | goto cleanup; | 667 | goto cleanup; |
687 | 668 | ||
688 | netlink_register_notifier(&ipq_nl_notifier); | 669 | netlink_register_notifier(&ipq_nl_notifier); |
689 | ipqnl = netlink_kernel_create(NETLINK_IP6_FW, ipq_rcv_sk); | 670 | ipqnl = netlink_kernel_create(NETLINK_IP6_FW, 0, ipq_rcv_sk, |
671 | THIS_MODULE); | ||
690 | if (ipqnl == NULL) { | 672 | if (ipqnl == NULL) { |
691 | printk(KERN_ERR "ip6_queue: failed to create netlink socket\n"); | 673 | printk(KERN_ERR "ip6_queue: failed to create netlink socket\n"); |
692 | goto cleanup_netlink_notifier; | 674 | goto cleanup_netlink_notifier; |
@@ -703,7 +685,7 @@ init_or_cleanup(int init) | |||
703 | register_netdevice_notifier(&ipq_dev_notifier); | 685 | register_netdevice_notifier(&ipq_dev_notifier); |
704 | ipq_sysctl_header = register_sysctl_table(ipq_root_table, 0); | 686 | ipq_sysctl_header = register_sysctl_table(ipq_root_table, 0); |
705 | 687 | ||
706 | status = nf_register_queue_handler(PF_INET6, ipq_enqueue_packet, NULL); | 688 | status = nf_register_queue_handler(PF_INET6, &nfqh); |
707 | if (status < 0) { | 689 | if (status < 0) { |
708 | printk(KERN_ERR "ip6_queue: failed to register queue handler\n"); | 690 | printk(KERN_ERR "ip6_queue: failed to register queue handler\n"); |
709 | goto cleanup_sysctl; | 691 | goto cleanup_sysctl; |
@@ -711,7 +693,7 @@ init_or_cleanup(int init) | |||
711 | return status; | 693 | return status; |
712 | 694 | ||
713 | cleanup: | 695 | cleanup: |
714 | nf_unregister_queue_handler(PF_INET6); | 696 | nf_unregister_queue_handlers(&nfqh); |
715 | synchronize_net(); | 697 | synchronize_net(); |
716 | ipq_flush(NF_DROP); | 698 | ipq_flush(NF_DROP); |
717 | 699 | ||
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 73034511c8db..1cb8adb2787f 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
@@ -401,7 +401,6 @@ ip6t_do_table(struct sk_buff **pskb, | |||
401 | do { | 401 | do { |
402 | IP_NF_ASSERT(e); | 402 | IP_NF_ASSERT(e); |
403 | IP_NF_ASSERT(back); | 403 | IP_NF_ASSERT(back); |
404 | (*pskb)->nfcache |= e->nfcache; | ||
405 | if (ip6_packet_match(*pskb, indev, outdev, &e->ipv6, | 404 | if (ip6_packet_match(*pskb, indev, outdev, &e->ipv6, |
406 | &protoff, &offset)) { | 405 | &protoff, &offset)) { |
407 | struct ip6t_entry_target *t; | 406 | struct ip6t_entry_target *t; |
@@ -434,8 +433,8 @@ ip6t_do_table(struct sk_buff **pskb, | |||
434 | back->comefrom); | 433 | back->comefrom); |
435 | continue; | 434 | continue; |
436 | } | 435 | } |
437 | if (table_base + v | 436 | if (table_base + v != (void *)e + e->next_offset |
438 | != (void *)e + e->next_offset) { | 437 | && !(e->ipv6.flags & IP6T_F_GOTO)) { |
439 | /* Save old back ptr in next entry */ | 438 | /* Save old back ptr in next entry */ |
440 | struct ip6t_entry *next | 439 | struct ip6t_entry *next |
441 | = (void *)e + e->next_offset; | 440 | = (void *)e + e->next_offset; |
diff --git a/net/ipv6/netfilter/ip6t_HL.c b/net/ipv6/netfilter/ip6t_HL.c new file mode 100644 index 000000000000..8f5549b72720 --- /dev/null +++ b/net/ipv6/netfilter/ip6t_HL.c | |||
@@ -0,0 +1,118 @@ | |||
1 | /* | ||
2 | * Hop Limit modification target for ip6tables | ||
3 | * Maciej Soltysiak <solt@dns.toxicfilms.tv> | ||
4 | * Based on HW's TTL module | ||
5 | * | ||
6 | * This software is distributed under the terms of GNU GPL | ||
7 | */ | ||
8 | |||
9 | #include <linux/module.h> | ||
10 | #include <linux/skbuff.h> | ||
11 | #include <linux/ip.h> | ||
12 | |||
13 | #include <linux/netfilter_ipv6/ip6_tables.h> | ||
14 | #include <linux/netfilter_ipv6/ip6t_HL.h> | ||
15 | |||
16 | MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>"); | ||
17 | MODULE_DESCRIPTION("IP tables Hop Limit modification module"); | ||
18 | MODULE_LICENSE("GPL"); | ||
19 | |||
20 | static unsigned int ip6t_hl_target(struct sk_buff **pskb, | ||
21 | const struct net_device *in, | ||
22 | const struct net_device *out, | ||
23 | unsigned int hooknum, | ||
24 | const void *targinfo, void *userinfo) | ||
25 | { | ||
26 | struct ipv6hdr *ip6h; | ||
27 | const struct ip6t_HL_info *info = targinfo; | ||
28 | u_int16_t diffs[2]; | ||
29 | int new_hl; | ||
30 | |||
31 | if (!skb_make_writable(pskb, (*pskb)->len)) | ||
32 | return NF_DROP; | ||
33 | |||
34 | ip6h = (*pskb)->nh.ipv6h; | ||
35 | |||
36 | switch (info->mode) { | ||
37 | case IP6T_HL_SET: | ||
38 | new_hl = info->hop_limit; | ||
39 | break; | ||
40 | case IP6T_HL_INC: | ||
41 | new_hl = ip6h->hop_limit + info->hop_limit; | ||
42 | if (new_hl > 255) | ||
43 | new_hl = 255; | ||
44 | break; | ||
45 | case IP6T_HL_DEC: | ||
46 | new_hl = ip6h->hop_limit - info->hop_limit; | ||
47 | if (new_hl < 0) | ||
48 | new_hl = 0; | ||
49 | break; | ||
50 | default: | ||
51 | new_hl = ip6h->hop_limit; | ||
52 | break; | ||
53 | } | ||
54 | |||
55 | if (new_hl != ip6h->hop_limit) { | ||
56 | diffs[0] = htons(((unsigned)ip6h->hop_limit) << 8) ^ 0xFFFF; | ||
57 | ip6h->hop_limit = new_hl; | ||
58 | diffs[1] = htons(((unsigned)ip6h->hop_limit) << 8); | ||
59 | } | ||
60 | |||
61 | return IP6T_CONTINUE; | ||
62 | } | ||
63 | |||
64 | static int ip6t_hl_checkentry(const char *tablename, | ||
65 | const struct ip6t_entry *e, | ||
66 | void *targinfo, | ||
67 | unsigned int targinfosize, | ||
68 | unsigned int hook_mask) | ||
69 | { | ||
70 | struct ip6t_HL_info *info = targinfo; | ||
71 | |||
72 | if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_HL_info))) { | ||
73 | printk(KERN_WARNING "ip6t_HL: targinfosize %u != %Zu\n", | ||
74 | targinfosize, | ||
75 | IP6T_ALIGN(sizeof(struct ip6t_HL_info))); | ||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | if (strcmp(tablename, "mangle")) { | ||
80 | printk(KERN_WARNING "ip6t_HL: can only be called from " | ||
81 | "\"mangle\" table, not \"%s\"\n", tablename); | ||
82 | return 0; | ||
83 | } | ||
84 | |||
85 | if (info->mode > IP6T_HL_MAXMODE) { | ||
86 | printk(KERN_WARNING "ip6t_HL: invalid or unknown Mode %u\n", | ||
87 | info->mode); | ||
88 | return 0; | ||
89 | } | ||
90 | |||
91 | if ((info->mode != IP6T_HL_SET) && (info->hop_limit == 0)) { | ||
92 | printk(KERN_WARNING "ip6t_HL: increment/decrement doesn't " | ||
93 | "make sense with value 0\n"); | ||
94 | return 0; | ||
95 | } | ||
96 | |||
97 | return 1; | ||
98 | } | ||
99 | |||
100 | static struct ip6t_target ip6t_HL = { | ||
101 | .name = "HL", | ||
102 | .target = ip6t_hl_target, | ||
103 | .checkentry = ip6t_hl_checkentry, | ||
104 | .me = THIS_MODULE | ||
105 | }; | ||
106 | |||
107 | static int __init init(void) | ||
108 | { | ||
109 | return ip6t_register_target(&ip6t_HL); | ||
110 | } | ||
111 | |||
112 | static void __exit fini(void) | ||
113 | { | ||
114 | ip6t_unregister_target(&ip6t_HL); | ||
115 | } | ||
116 | |||
117 | module_init(init); | ||
118 | module_exit(fini); | ||
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c index a692e26a4fa3..0cd1d1bd9033 100644 --- a/net/ipv6/netfilter/ip6t_LOG.c +++ b/net/ipv6/netfilter/ip6t_LOG.c | |||
@@ -26,10 +26,6 @@ MODULE_AUTHOR("Jan Rekorajski <baggins@pld.org.pl>"); | |||
26 | MODULE_DESCRIPTION("IP6 tables LOG target module"); | 26 | MODULE_DESCRIPTION("IP6 tables LOG target module"); |
27 | MODULE_LICENSE("GPL"); | 27 | MODULE_LICENSE("GPL"); |
28 | 28 | ||
29 | static unsigned int nflog = 1; | ||
30 | module_param(nflog, int, 0400); | ||
31 | MODULE_PARM_DESC(nflog, "register as internal netfilter logging module"); | ||
32 | |||
33 | struct in_device; | 29 | struct in_device; |
34 | #include <net/route.h> | 30 | #include <net/route.h> |
35 | #include <linux/netfilter_ipv6/ip6t_LOG.h> | 31 | #include <linux/netfilter_ipv6/ip6t_LOG.h> |
@@ -44,7 +40,7 @@ struct in_device; | |||
44 | static DEFINE_SPINLOCK(log_lock); | 40 | static DEFINE_SPINLOCK(log_lock); |
45 | 41 | ||
46 | /* One level of recursion won't kill us */ | 42 | /* One level of recursion won't kill us */ |
47 | static void dump_packet(const struct ip6t_log_info *info, | 43 | static void dump_packet(const struct nf_loginfo *info, |
48 | const struct sk_buff *skb, unsigned int ip6hoff, | 44 | const struct sk_buff *skb, unsigned int ip6hoff, |
49 | int recurse) | 45 | int recurse) |
50 | { | 46 | { |
@@ -53,6 +49,12 @@ static void dump_packet(const struct ip6t_log_info *info, | |||
53 | struct ipv6hdr _ip6h, *ih; | 49 | struct ipv6hdr _ip6h, *ih; |
54 | unsigned int ptr; | 50 | unsigned int ptr; |
55 | unsigned int hdrlen = 0; | 51 | unsigned int hdrlen = 0; |
52 | unsigned int logflags; | ||
53 | |||
54 | if (info->type == NF_LOG_TYPE_LOG) | ||
55 | logflags = info->u.log.logflags; | ||
56 | else | ||
57 | logflags = NF_LOG_MASK; | ||
56 | 58 | ||
57 | ih = skb_header_pointer(skb, ip6hoff, sizeof(_ip6h), &_ip6h); | 59 | ih = skb_header_pointer(skb, ip6hoff, sizeof(_ip6h), &_ip6h); |
58 | if (ih == NULL) { | 60 | if (ih == NULL) { |
@@ -84,7 +86,7 @@ static void dump_packet(const struct ip6t_log_info *info, | |||
84 | } | 86 | } |
85 | 87 | ||
86 | /* Max length: 48 "OPT (...) " */ | 88 | /* Max length: 48 "OPT (...) " */ |
87 | if (info->logflags & IP6T_LOG_IPOPT) | 89 | if (logflags & IP6T_LOG_IPOPT) |
88 | printk("OPT ( "); | 90 | printk("OPT ( "); |
89 | 91 | ||
90 | switch (currenthdr) { | 92 | switch (currenthdr) { |
@@ -119,7 +121,7 @@ static void dump_packet(const struct ip6t_log_info *info, | |||
119 | case IPPROTO_ROUTING: | 121 | case IPPROTO_ROUTING: |
120 | case IPPROTO_HOPOPTS: | 122 | case IPPROTO_HOPOPTS: |
121 | if (fragment) { | 123 | if (fragment) { |
122 | if (info->logflags & IP6T_LOG_IPOPT) | 124 | if (logflags & IP6T_LOG_IPOPT) |
123 | printk(")"); | 125 | printk(")"); |
124 | return; | 126 | return; |
125 | } | 127 | } |
@@ -127,7 +129,7 @@ static void dump_packet(const struct ip6t_log_info *info, | |||
127 | break; | 129 | break; |
128 | /* Max Length */ | 130 | /* Max Length */ |
129 | case IPPROTO_AH: | 131 | case IPPROTO_AH: |
130 | if (info->logflags & IP6T_LOG_IPOPT) { | 132 | if (logflags & IP6T_LOG_IPOPT) { |
131 | struct ip_auth_hdr _ahdr, *ah; | 133 | struct ip_auth_hdr _ahdr, *ah; |
132 | 134 | ||
133 | /* Max length: 3 "AH " */ | 135 | /* Max length: 3 "AH " */ |
@@ -158,7 +160,7 @@ static void dump_packet(const struct ip6t_log_info *info, | |||
158 | hdrlen = (hp->hdrlen+2)<<2; | 160 | hdrlen = (hp->hdrlen+2)<<2; |
159 | break; | 161 | break; |
160 | case IPPROTO_ESP: | 162 | case IPPROTO_ESP: |
161 | if (info->logflags & IP6T_LOG_IPOPT) { | 163 | if (logflags & IP6T_LOG_IPOPT) { |
162 | struct ip_esp_hdr _esph, *eh; | 164 | struct ip_esp_hdr _esph, *eh; |
163 | 165 | ||
164 | /* Max length: 4 "ESP " */ | 166 | /* Max length: 4 "ESP " */ |
@@ -190,7 +192,7 @@ static void dump_packet(const struct ip6t_log_info *info, | |||
190 | printk("Unknown Ext Hdr %u", currenthdr); | 192 | printk("Unknown Ext Hdr %u", currenthdr); |
191 | return; | 193 | return; |
192 | } | 194 | } |
193 | if (info->logflags & IP6T_LOG_IPOPT) | 195 | if (logflags & IP6T_LOG_IPOPT) |
194 | printk(") "); | 196 | printk(") "); |
195 | 197 | ||
196 | currenthdr = hp->nexthdr; | 198 | currenthdr = hp->nexthdr; |
@@ -218,7 +220,7 @@ static void dump_packet(const struct ip6t_log_info *info, | |||
218 | printk("SPT=%u DPT=%u ", | 220 | printk("SPT=%u DPT=%u ", |
219 | ntohs(th->source), ntohs(th->dest)); | 221 | ntohs(th->source), ntohs(th->dest)); |
220 | /* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */ | 222 | /* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */ |
221 | if (info->logflags & IP6T_LOG_TCPSEQ) | 223 | if (logflags & IP6T_LOG_TCPSEQ) |
222 | printk("SEQ=%u ACK=%u ", | 224 | printk("SEQ=%u ACK=%u ", |
223 | ntohl(th->seq), ntohl(th->ack_seq)); | 225 | ntohl(th->seq), ntohl(th->ack_seq)); |
224 | /* Max length: 13 "WINDOW=65535 " */ | 226 | /* Max length: 13 "WINDOW=65535 " */ |
@@ -245,7 +247,7 @@ static void dump_packet(const struct ip6t_log_info *info, | |||
245 | /* Max length: 11 "URGP=65535 " */ | 247 | /* Max length: 11 "URGP=65535 " */ |
246 | printk("URGP=%u ", ntohs(th->urg_ptr)); | 248 | printk("URGP=%u ", ntohs(th->urg_ptr)); |
247 | 249 | ||
248 | if ((info->logflags & IP6T_LOG_TCPOPT) | 250 | if ((logflags & IP6T_LOG_TCPOPT) |
249 | && th->doff * 4 > sizeof(struct tcphdr)) { | 251 | && th->doff * 4 > sizeof(struct tcphdr)) { |
250 | u_int8_t _opt[60 - sizeof(struct tcphdr)], *op; | 252 | u_int8_t _opt[60 - sizeof(struct tcphdr)], *op; |
251 | unsigned int i; | 253 | unsigned int i; |
@@ -349,7 +351,7 @@ static void dump_packet(const struct ip6t_log_info *info, | |||
349 | } | 351 | } |
350 | 352 | ||
351 | /* Max length: 15 "UID=4294967295 " */ | 353 | /* Max length: 15 "UID=4294967295 " */ |
352 | if ((info->logflags & IP6T_LOG_UID) && recurse && skb->sk) { | 354 | if ((logflags & IP6T_LOG_UID) && recurse && skb->sk) { |
353 | read_lock_bh(&skb->sk->sk_callback_lock); | 355 | read_lock_bh(&skb->sk->sk_callback_lock); |
354 | if (skb->sk->sk_socket && skb->sk->sk_socket->file) | 356 | if (skb->sk->sk_socket && skb->sk->sk_socket->file) |
355 | printk("UID=%u ", skb->sk->sk_socket->file->f_uid); | 357 | printk("UID=%u ", skb->sk->sk_socket->file->f_uid); |
@@ -357,19 +359,31 @@ static void dump_packet(const struct ip6t_log_info *info, | |||
357 | } | 359 | } |
358 | } | 360 | } |
359 | 361 | ||
362 | static struct nf_loginfo default_loginfo = { | ||
363 | .type = NF_LOG_TYPE_LOG, | ||
364 | .u = { | ||
365 | .log = { | ||
366 | .level = 0, | ||
367 | .logflags = NF_LOG_MASK, | ||
368 | }, | ||
369 | }, | ||
370 | }; | ||
371 | |||
360 | static void | 372 | static void |
361 | ip6t_log_packet(unsigned int hooknum, | 373 | ip6t_log_packet(unsigned int pf, |
374 | unsigned int hooknum, | ||
362 | const struct sk_buff *skb, | 375 | const struct sk_buff *skb, |
363 | const struct net_device *in, | 376 | const struct net_device *in, |
364 | const struct net_device *out, | 377 | const struct net_device *out, |
365 | const struct ip6t_log_info *loginfo, | 378 | const struct nf_loginfo *loginfo, |
366 | const char *level_string, | ||
367 | const char *prefix) | 379 | const char *prefix) |
368 | { | 380 | { |
381 | if (!loginfo) | ||
382 | loginfo = &default_loginfo; | ||
383 | |||
369 | spin_lock_bh(&log_lock); | 384 | spin_lock_bh(&log_lock); |
370 | printk(level_string); | 385 | printk("<%d>%sIN=%s OUT=%s ", loginfo->u.log.level, |
371 | printk("%sIN=%s OUT=%s ", | 386 | prefix, |
372 | prefix == NULL ? loginfo->prefix : prefix, | ||
373 | in ? in->name : "", | 387 | in ? in->name : "", |
374 | out ? out->name : ""); | 388 | out ? out->name : ""); |
375 | if (in && !out) { | 389 | if (in && !out) { |
@@ -416,29 +430,17 @@ ip6t_log_target(struct sk_buff **pskb, | |||
416 | void *userinfo) | 430 | void *userinfo) |
417 | { | 431 | { |
418 | const struct ip6t_log_info *loginfo = targinfo; | 432 | const struct ip6t_log_info *loginfo = targinfo; |
419 | char level_string[4] = "< >"; | 433 | struct nf_loginfo li; |
434 | |||
435 | li.type = NF_LOG_TYPE_LOG; | ||
436 | li.u.log.level = loginfo->level; | ||
437 | li.u.log.logflags = loginfo->logflags; | ||
420 | 438 | ||
421 | level_string[1] = '0' + (loginfo->level % 8); | 439 | nf_log_packet(PF_INET6, hooknum, *pskb, in, out, &li, loginfo->prefix); |
422 | ip6t_log_packet(hooknum, *pskb, in, out, loginfo, level_string, NULL); | ||
423 | 440 | ||
424 | return IP6T_CONTINUE; | 441 | return IP6T_CONTINUE; |
425 | } | 442 | } |
426 | 443 | ||
427 | static void | ||
428 | ip6t_logfn(unsigned int hooknum, | ||
429 | const struct sk_buff *skb, | ||
430 | const struct net_device *in, | ||
431 | const struct net_device *out, | ||
432 | const char *prefix) | ||
433 | { | ||
434 | struct ip6t_log_info loginfo = { | ||
435 | .level = 0, | ||
436 | .logflags = IP6T_LOG_MASK, | ||
437 | .prefix = "" | ||
438 | }; | ||
439 | |||
440 | ip6t_log_packet(hooknum, skb, in, out, &loginfo, KERN_WARNING, prefix); | ||
441 | } | ||
442 | 444 | ||
443 | static int ip6t_log_checkentry(const char *tablename, | 445 | static int ip6t_log_checkentry(const char *tablename, |
444 | const struct ip6t_entry *e, | 446 | const struct ip6t_entry *e, |
@@ -475,20 +477,29 @@ static struct ip6t_target ip6t_log_reg = { | |||
475 | .me = THIS_MODULE, | 477 | .me = THIS_MODULE, |
476 | }; | 478 | }; |
477 | 479 | ||
480 | static struct nf_logger ip6t_logger = { | ||
481 | .name = "ip6t_LOG", | ||
482 | .logfn = &ip6t_log_packet, | ||
483 | .me = THIS_MODULE, | ||
484 | }; | ||
485 | |||
478 | static int __init init(void) | 486 | static int __init init(void) |
479 | { | 487 | { |
480 | if (ip6t_register_target(&ip6t_log_reg)) | 488 | if (ip6t_register_target(&ip6t_log_reg)) |
481 | return -EINVAL; | 489 | return -EINVAL; |
482 | if (nflog) | 490 | if (nf_log_register(PF_INET6, &ip6t_logger) < 0) { |
483 | nf_log_register(PF_INET6, &ip6t_logfn); | 491 | printk(KERN_WARNING "ip6t_LOG: not logging via system console " |
492 | "since somebody else already registered for PF_INET6\n"); | ||
493 | /* we cannot make module load fail here, since otherwise | ||
494 | * ip6tables userspace would abort */ | ||
495 | } | ||
484 | 496 | ||
485 | return 0; | 497 | return 0; |
486 | } | 498 | } |
487 | 499 | ||
488 | static void __exit fini(void) | 500 | static void __exit fini(void) |
489 | { | 501 | { |
490 | if (nflog) | 502 | nf_log_unregister_logger(&ip6t_logger); |
491 | nf_log_unregister(PF_INET6, &ip6t_logfn); | ||
492 | ip6t_unregister_target(&ip6t_log_reg); | 503 | ip6t_unregister_target(&ip6t_log_reg); |
493 | } | 504 | } |
494 | 505 | ||
diff --git a/net/ipv6/netfilter/ip6t_MARK.c b/net/ipv6/netfilter/ip6t_MARK.c index d09ceb05013a..81924fcc5857 100644 --- a/net/ipv6/netfilter/ip6t_MARK.c +++ b/net/ipv6/netfilter/ip6t_MARK.c | |||
@@ -28,10 +28,9 @@ target(struct sk_buff **pskb, | |||
28 | { | 28 | { |
29 | const struct ip6t_mark_target_info *markinfo = targinfo; | 29 | const struct ip6t_mark_target_info *markinfo = targinfo; |
30 | 30 | ||
31 | if((*pskb)->nfmark != markinfo->mark) { | 31 | if((*pskb)->nfmark != markinfo->mark) |
32 | (*pskb)->nfmark = markinfo->mark; | 32 | (*pskb)->nfmark = markinfo->mark; |
33 | (*pskb)->nfcache |= NFC_ALTERED; | 33 | |
34 | } | ||
35 | return IP6T_CONTINUE; | 34 | return IP6T_CONTINUE; |
36 | } | 35 | } |
37 | 36 | ||
diff --git a/net/ipv6/netfilter/ip6t_NFQUEUE.c b/net/ipv6/netfilter/ip6t_NFQUEUE.c new file mode 100644 index 000000000000..c6e3730e7409 --- /dev/null +++ b/net/ipv6/netfilter/ip6t_NFQUEUE.c | |||
@@ -0,0 +1,70 @@ | |||
1 | /* ip6tables module for using new netfilter netlink queue | ||
2 | * | ||
3 | * (C) 2005 by Harald Welte <laforge@netfilter.org> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | */ | ||
10 | |||
11 | #include <linux/module.h> | ||
12 | #include <linux/skbuff.h> | ||
13 | |||
14 | #include <linux/netfilter.h> | ||
15 | #include <linux/netfilter_ipv6/ip6_tables.h> | ||
16 | #include <linux/netfilter_ipv4/ipt_NFQUEUE.h> | ||
17 | |||
18 | MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); | ||
19 | MODULE_DESCRIPTION("ip6tables NFQUEUE target"); | ||
20 | MODULE_LICENSE("GPL"); | ||
21 | |||
22 | static unsigned int | ||
23 | target(struct sk_buff **pskb, | ||
24 | const struct net_device *in, | ||
25 | const struct net_device *out, | ||
26 | unsigned int hooknum, | ||
27 | const void *targinfo, | ||
28 | void *userinfo) | ||
29 | { | ||
30 | const struct ipt_NFQ_info *tinfo = targinfo; | ||
31 | |||
32 | return NF_QUEUE_NR(tinfo->queuenum); | ||
33 | } | ||
34 | |||
35 | static int | ||
36 | checkentry(const char *tablename, | ||
37 | const struct ip6t_entry *e, | ||
38 | void *targinfo, | ||
39 | unsigned int targinfosize, | ||
40 | unsigned int hook_mask) | ||
41 | { | ||
42 | if (targinfosize != IP6T_ALIGN(sizeof(struct ipt_NFQ_info))) { | ||
43 | printk(KERN_WARNING "NFQUEUE: targinfosize %u != %Zu\n", | ||
44 | targinfosize, | ||
45 | IP6T_ALIGN(sizeof(struct ipt_NFQ_info))); | ||
46 | return 0; | ||
47 | } | ||
48 | |||
49 | return 1; | ||
50 | } | ||
51 | |||
52 | static struct ip6t_target ipt_NFQ_reg = { | ||
53 | .name = "NFQUEUE", | ||
54 | .target = target, | ||
55 | .checkentry = checkentry, | ||
56 | .me = THIS_MODULE, | ||
57 | }; | ||
58 | |||
59 | static int __init init(void) | ||
60 | { | ||
61 | return ip6t_register_target(&ipt_NFQ_reg); | ||
62 | } | ||
63 | |||
64 | static void __exit fini(void) | ||
65 | { | ||
66 | ip6t_unregister_target(&ipt_NFQ_reg); | ||
67 | } | ||
68 | |||
69 | module_init(init); | ||
70 | module_exit(fini); | ||
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c new file mode 100644 index 000000000000..14316c3ebde4 --- /dev/null +++ b/net/ipv6/netfilter/ip6t_REJECT.c | |||
@@ -0,0 +1,284 @@ | |||
1 | /* | ||
2 | * IP6 tables REJECT target module | ||
3 | * Linux INET6 implementation | ||
4 | * | ||
5 | * Copyright (C)2003 USAGI/WIDE Project | ||
6 | * | ||
7 | * Authors: | ||
8 | * Yasuyuki Kozakai <yasuyuki.kozakai@toshiba.co.jp> | ||
9 | * | ||
10 | * Based on net/ipv4/netfilter/ipt_REJECT.c | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version | ||
15 | * 2 of the License, or (at your option) any later version. | ||
16 | */ | ||
17 | |||
18 | #include <linux/config.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/skbuff.h> | ||
21 | #include <linux/icmpv6.h> | ||
22 | #include <linux/netdevice.h> | ||
23 | #include <net/ipv6.h> | ||
24 | #include <net/tcp.h> | ||
25 | #include <net/icmp.h> | ||
26 | #include <net/ip6_checksum.h> | ||
27 | #include <net/ip6_fib.h> | ||
28 | #include <net/ip6_route.h> | ||
29 | #include <net/flow.h> | ||
30 | #include <linux/netfilter_ipv6/ip6_tables.h> | ||
31 | #include <linux/netfilter_ipv6/ip6t_REJECT.h> | ||
32 | |||
33 | MODULE_AUTHOR("Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>"); | ||
34 | MODULE_DESCRIPTION("IP6 tables REJECT target module"); | ||
35 | MODULE_LICENSE("GPL"); | ||
36 | |||
37 | #if 0 | ||
38 | #define DEBUGP printk | ||
39 | #else | ||
40 | #define DEBUGP(format, args...) | ||
41 | #endif | ||
42 | |||
43 | /* Send RST reply */ | ||
44 | static void send_reset(struct sk_buff *oldskb) | ||
45 | { | ||
46 | struct sk_buff *nskb; | ||
47 | struct tcphdr otcph, *tcph; | ||
48 | unsigned int otcplen, hh_len; | ||
49 | int tcphoff, needs_ack; | ||
50 | struct ipv6hdr *oip6h = oldskb->nh.ipv6h, *ip6h; | ||
51 | struct dst_entry *dst = NULL; | ||
52 | u8 proto; | ||
53 | struct flowi fl; | ||
54 | |||
55 | if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) || | ||
56 | (!(ipv6_addr_type(&oip6h->daddr) & IPV6_ADDR_UNICAST))) { | ||
57 | DEBUGP("ip6t_REJECT: addr is not unicast.\n"); | ||
58 | return; | ||
59 | } | ||
60 | |||
61 | proto = oip6h->nexthdr; | ||
62 | tcphoff = ipv6_skip_exthdr(oldskb, ((u8*)(oip6h+1) - oldskb->data), &proto); | ||
63 | |||
64 | if ((tcphoff < 0) || (tcphoff > oldskb->len)) { | ||
65 | DEBUGP("ip6t_REJECT: Can't get TCP header.\n"); | ||
66 | return; | ||
67 | } | ||
68 | |||
69 | otcplen = oldskb->len - tcphoff; | ||
70 | |||
71 | /* IP header checks: fragment, too short. */ | ||
72 | if ((proto != IPPROTO_TCP) || (otcplen < sizeof(struct tcphdr))) { | ||
73 | DEBUGP("ip6t_REJECT: proto(%d) != IPPROTO_TCP, or too short. otcplen = %d\n", | ||
74 | proto, otcplen); | ||
75 | return; | ||
76 | } | ||
77 | |||
78 | if (skb_copy_bits(oldskb, tcphoff, &otcph, sizeof(struct tcphdr))) | ||
79 | BUG(); | ||
80 | |||
81 | /* No RST for RST. */ | ||
82 | if (otcph.rst) { | ||
83 | DEBUGP("ip6t_REJECT: RST is set\n"); | ||
84 | return; | ||
85 | } | ||
86 | |||
87 | /* Check checksum. */ | ||
88 | if (csum_ipv6_magic(&oip6h->saddr, &oip6h->daddr, otcplen, IPPROTO_TCP, | ||
89 | skb_checksum(oldskb, tcphoff, otcplen, 0))) { | ||
90 | DEBUGP("ip6t_REJECT: TCP checksum is invalid\n"); | ||
91 | return; | ||
92 | } | ||
93 | |||
94 | memset(&fl, 0, sizeof(fl)); | ||
95 | fl.proto = IPPROTO_TCP; | ||
96 | ipv6_addr_copy(&fl.fl6_src, &oip6h->daddr); | ||
97 | ipv6_addr_copy(&fl.fl6_dst, &oip6h->saddr); | ||
98 | fl.fl_ip_sport = otcph.dest; | ||
99 | fl.fl_ip_dport = otcph.source; | ||
100 | dst = ip6_route_output(NULL, &fl); | ||
101 | if (dst == NULL) | ||
102 | return; | ||
103 | if (dst->error || | ||
104 | xfrm_lookup(&dst, &fl, NULL, 0)) { | ||
105 | dst_release(dst); | ||
106 | return; | ||
107 | } | ||
108 | |||
109 | hh_len = (dst->dev->hard_header_len + 15)&~15; | ||
110 | nskb = alloc_skb(hh_len + 15 + dst->header_len + sizeof(struct ipv6hdr) | ||
111 | + sizeof(struct tcphdr) + dst->trailer_len, | ||
112 | GFP_ATOMIC); | ||
113 | |||
114 | if (!nskb) { | ||
115 | if (net_ratelimit()) | ||
116 | printk("ip6t_REJECT: Can't alloc skb\n"); | ||
117 | dst_release(dst); | ||
118 | return; | ||
119 | } | ||
120 | |||
121 | nskb->dst = dst; | ||
122 | |||
123 | skb_reserve(nskb, hh_len + dst->header_len); | ||
124 | |||
125 | ip6h = nskb->nh.ipv6h = (struct ipv6hdr *) | ||
126 | skb_put(nskb, sizeof(struct ipv6hdr)); | ||
127 | ip6h->version = 6; | ||
128 | ip6h->hop_limit = dst_metric(dst, RTAX_HOPLIMIT); | ||
129 | ip6h->nexthdr = IPPROTO_TCP; | ||
130 | ip6h->payload_len = htons(sizeof(struct tcphdr)); | ||
131 | ipv6_addr_copy(&ip6h->saddr, &oip6h->daddr); | ||
132 | ipv6_addr_copy(&ip6h->daddr, &oip6h->saddr); | ||
133 | |||
134 | tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr)); | ||
135 | /* Truncate to length (no data) */ | ||
136 | tcph->doff = sizeof(struct tcphdr)/4; | ||
137 | tcph->source = otcph.dest; | ||
138 | tcph->dest = otcph.source; | ||
139 | |||
140 | if (otcph.ack) { | ||
141 | needs_ack = 0; | ||
142 | tcph->seq = otcph.ack_seq; | ||
143 | tcph->ack_seq = 0; | ||
144 | } else { | ||
145 | needs_ack = 1; | ||
146 | tcph->ack_seq = htonl(ntohl(otcph.seq) + otcph.syn + otcph.fin | ||
147 | + otcplen - (otcph.doff<<2)); | ||
148 | tcph->seq = 0; | ||
149 | } | ||
150 | |||
151 | /* Reset flags */ | ||
152 | ((u_int8_t *)tcph)[13] = 0; | ||
153 | tcph->rst = 1; | ||
154 | tcph->ack = needs_ack; | ||
155 | tcph->window = 0; | ||
156 | tcph->urg_ptr = 0; | ||
157 | tcph->check = 0; | ||
158 | |||
159 | /* Adjust TCP checksum */ | ||
160 | tcph->check = csum_ipv6_magic(&nskb->nh.ipv6h->saddr, | ||
161 | &nskb->nh.ipv6h->daddr, | ||
162 | sizeof(struct tcphdr), IPPROTO_TCP, | ||
163 | csum_partial((char *)tcph, | ||
164 | sizeof(struct tcphdr), 0)); | ||
165 | |||
166 | NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, nskb, NULL, nskb->dst->dev, | ||
167 | dst_output); | ||
168 | } | ||
169 | |||
170 | static inline void | ||
171 | send_unreach(struct sk_buff *skb_in, unsigned char code, unsigned int hooknum) | ||
172 | { | ||
173 | if (hooknum == NF_IP6_LOCAL_OUT && skb_in->dev == NULL) | ||
174 | skb_in->dev = &loopback_dev; | ||
175 | |||
176 | icmpv6_send(skb_in, ICMPV6_DEST_UNREACH, code, 0, NULL); | ||
177 | } | ||
178 | |||
179 | static unsigned int reject6_target(struct sk_buff **pskb, | ||
180 | const struct net_device *in, | ||
181 | const struct net_device *out, | ||
182 | unsigned int hooknum, | ||
183 | const void *targinfo, | ||
184 | void *userinfo) | ||
185 | { | ||
186 | const struct ip6t_reject_info *reject = targinfo; | ||
187 | |||
188 | DEBUGP(KERN_DEBUG "%s: medium point\n", __FUNCTION__); | ||
189 | /* WARNING: This code causes reentry within ip6tables. | ||
190 | This means that the ip6tables jump stack is now crap. We | ||
191 | must return an absolute verdict. --RR */ | ||
192 | switch (reject->with) { | ||
193 | case IP6T_ICMP6_NO_ROUTE: | ||
194 | send_unreach(*pskb, ICMPV6_NOROUTE, hooknum); | ||
195 | break; | ||
196 | case IP6T_ICMP6_ADM_PROHIBITED: | ||
197 | send_unreach(*pskb, ICMPV6_ADM_PROHIBITED, hooknum); | ||
198 | break; | ||
199 | case IP6T_ICMP6_NOT_NEIGHBOUR: | ||
200 | send_unreach(*pskb, ICMPV6_NOT_NEIGHBOUR, hooknum); | ||
201 | break; | ||
202 | case IP6T_ICMP6_ADDR_UNREACH: | ||
203 | send_unreach(*pskb, ICMPV6_ADDR_UNREACH, hooknum); | ||
204 | break; | ||
205 | case IP6T_ICMP6_PORT_UNREACH: | ||
206 | send_unreach(*pskb, ICMPV6_PORT_UNREACH, hooknum); | ||
207 | break; | ||
208 | case IP6T_ICMP6_ECHOREPLY: | ||
209 | /* Do nothing */ | ||
210 | break; | ||
211 | case IP6T_TCP_RESET: | ||
212 | send_reset(*pskb); | ||
213 | break; | ||
214 | default: | ||
215 | if (net_ratelimit()) | ||
216 | printk(KERN_WARNING "ip6t_REJECT: case %u not handled yet\n", reject->with); | ||
217 | break; | ||
218 | } | ||
219 | |||
220 | return NF_DROP; | ||
221 | } | ||
222 | |||
223 | static int check(const char *tablename, | ||
224 | const struct ip6t_entry *e, | ||
225 | void *targinfo, | ||
226 | unsigned int targinfosize, | ||
227 | unsigned int hook_mask) | ||
228 | { | ||
229 | const struct ip6t_reject_info *rejinfo = targinfo; | ||
230 | |||
231 | if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_reject_info))) { | ||
232 | DEBUGP("ip6t_REJECT: targinfosize %u != 0\n", targinfosize); | ||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | /* Only allow these for packet filtering. */ | ||
237 | if (strcmp(tablename, "filter") != 0) { | ||
238 | DEBUGP("ip6t_REJECT: bad table `%s'.\n", tablename); | ||
239 | return 0; | ||
240 | } | ||
241 | |||
242 | if ((hook_mask & ~((1 << NF_IP6_LOCAL_IN) | ||
243 | | (1 << NF_IP6_FORWARD) | ||
244 | | (1 << NF_IP6_LOCAL_OUT))) != 0) { | ||
245 | DEBUGP("ip6t_REJECT: bad hook mask %X\n", hook_mask); | ||
246 | return 0; | ||
247 | } | ||
248 | |||
249 | if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) { | ||
250 | printk("ip6t_REJECT: ECHOREPLY is not supported.\n"); | ||
251 | return 0; | ||
252 | } else if (rejinfo->with == IP6T_TCP_RESET) { | ||
253 | /* Must specify that it's a TCP packet */ | ||
254 | if (e->ipv6.proto != IPPROTO_TCP | ||
255 | || (e->ipv6.invflags & IP6T_INV_PROTO)) { | ||
256 | DEBUGP("ip6t_REJECT: TCP_RESET illegal for non-tcp\n"); | ||
257 | return 0; | ||
258 | } | ||
259 | } | ||
260 | |||
261 | return 1; | ||
262 | } | ||
263 | |||
264 | static struct ip6t_target ip6t_reject_reg = { | ||
265 | .name = "REJECT", | ||
266 | .target = reject6_target, | ||
267 | .checkentry = check, | ||
268 | .me = THIS_MODULE | ||
269 | }; | ||
270 | |||
271 | static int __init init(void) | ||
272 | { | ||
273 | if (ip6t_register_target(&ip6t_reject_reg)) | ||
274 | return -EINVAL; | ||
275 | return 0; | ||
276 | } | ||
277 | |||
278 | static void __exit fini(void) | ||
279 | { | ||
280 | ip6t_unregister_target(&ip6t_reject_reg); | ||
281 | } | ||
282 | |||
283 | module_init(init); | ||
284 | module_exit(fini); | ||
diff --git a/net/ipv6/netfilter/ip6t_owner.c b/net/ipv6/netfilter/ip6t_owner.c index ab0e32d3de46..9b91decbfddb 100644 --- a/net/ipv6/netfilter/ip6t_owner.c +++ b/net/ipv6/netfilter/ip6t_owner.c | |||
@@ -20,71 +20,6 @@ MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); | |||
20 | MODULE_DESCRIPTION("IP6 tables owner matching module"); | 20 | MODULE_DESCRIPTION("IP6 tables owner matching module"); |
21 | MODULE_LICENSE("GPL"); | 21 | MODULE_LICENSE("GPL"); |
22 | 22 | ||
23 | static int | ||
24 | match_pid(const struct sk_buff *skb, pid_t pid) | ||
25 | { | ||
26 | struct task_struct *p; | ||
27 | struct files_struct *files; | ||
28 | int i; | ||
29 | |||
30 | read_lock(&tasklist_lock); | ||
31 | p = find_task_by_pid(pid); | ||
32 | if (!p) | ||
33 | goto out; | ||
34 | task_lock(p); | ||
35 | files = p->files; | ||
36 | if(files) { | ||
37 | spin_lock(&files->file_lock); | ||
38 | for (i=0; i < files->max_fds; i++) { | ||
39 | if (fcheck_files(files, i) == skb->sk->sk_socket->file) { | ||
40 | spin_unlock(&files->file_lock); | ||
41 | task_unlock(p); | ||
42 | read_unlock(&tasklist_lock); | ||
43 | return 1; | ||
44 | } | ||
45 | } | ||
46 | spin_unlock(&files->file_lock); | ||
47 | } | ||
48 | task_unlock(p); | ||
49 | out: | ||
50 | read_unlock(&tasklist_lock); | ||
51 | return 0; | ||
52 | } | ||
53 | |||
54 | static int | ||
55 | match_sid(const struct sk_buff *skb, pid_t sid) | ||
56 | { | ||
57 | struct task_struct *g, *p; | ||
58 | struct file *file = skb->sk->sk_socket->file; | ||
59 | int i, found=0; | ||
60 | |||
61 | read_lock(&tasklist_lock); | ||
62 | do_each_thread(g, p) { | ||
63 | struct files_struct *files; | ||
64 | if (p->signal->session != sid) | ||
65 | continue; | ||
66 | |||
67 | task_lock(p); | ||
68 | files = p->files; | ||
69 | if (files) { | ||
70 | spin_lock(&files->file_lock); | ||
71 | for (i=0; i < files->max_fds; i++) { | ||
72 | if (fcheck_files(files, i) == file) { | ||
73 | found = 1; | ||
74 | break; | ||
75 | } | ||
76 | } | ||
77 | spin_unlock(&files->file_lock); | ||
78 | } | ||
79 | task_unlock(p); | ||
80 | if (found) | ||
81 | goto out; | ||
82 | } while_each_thread(g, p); | ||
83 | out: | ||
84 | read_unlock(&tasklist_lock); | ||
85 | |||
86 | return found; | ||
87 | } | ||
88 | 23 | ||
89 | static int | 24 | static int |
90 | match(const struct sk_buff *skb, | 25 | match(const struct sk_buff *skb, |
@@ -112,18 +47,6 @@ match(const struct sk_buff *skb, | |||
112 | return 0; | 47 | return 0; |
113 | } | 48 | } |
114 | 49 | ||
115 | if(info->match & IP6T_OWNER_PID) { | ||
116 | if (!match_pid(skb, info->pid) ^ | ||
117 | !!(info->invert & IP6T_OWNER_PID)) | ||
118 | return 0; | ||
119 | } | ||
120 | |||
121 | if(info->match & IP6T_OWNER_SID) { | ||
122 | if (!match_sid(skb, info->sid) ^ | ||
123 | !!(info->invert & IP6T_OWNER_SID)) | ||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | return 1; | 50 | return 1; |
128 | } | 51 | } |
129 | 52 | ||
@@ -134,6 +57,8 @@ checkentry(const char *tablename, | |||
134 | unsigned int matchsize, | 57 | unsigned int matchsize, |
135 | unsigned int hook_mask) | 58 | unsigned int hook_mask) |
136 | { | 59 | { |
60 | const struct ip6t_owner_info *info = matchinfo; | ||
61 | |||
137 | if (hook_mask | 62 | if (hook_mask |
138 | & ~((1 << NF_IP6_LOCAL_OUT) | (1 << NF_IP6_POST_ROUTING))) { | 63 | & ~((1 << NF_IP6_LOCAL_OUT) | (1 << NF_IP6_POST_ROUTING))) { |
139 | printk("ip6t_owner: only valid for LOCAL_OUT or POST_ROUTING.\n"); | 64 | printk("ip6t_owner: only valid for LOCAL_OUT or POST_ROUTING.\n"); |
@@ -142,14 +67,13 @@ checkentry(const char *tablename, | |||
142 | 67 | ||
143 | if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_owner_info))) | 68 | if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_owner_info))) |
144 | return 0; | 69 | return 0; |
145 | #ifdef CONFIG_SMP | 70 | |
146 | /* files->file_lock can not be used in a BH */ | 71 | if (info->match & (IP6T_OWNER_PID|IP6T_OWNER_SID)) { |
147 | if (((struct ip6t_owner_info *)matchinfo)->match | 72 | printk("ipt_owner: pid and sid matching " |
148 | & (IP6T_OWNER_PID|IP6T_OWNER_SID)) { | 73 | "not supported anymore\n"); |
149 | printk("ip6t_owner: pid and sid matching is broken on SMP.\n"); | ||
150 | return 0; | 74 | return 0; |
151 | } | 75 | } |
152 | #endif | 76 | |
153 | return 1; | 77 | return 1; |
154 | } | 78 | } |
155 | 79 | ||
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 1d4d75b34d32..7a5863298f3f 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -49,6 +49,7 @@ | |||
49 | #include <net/transp_v6.h> | 49 | #include <net/transp_v6.h> |
50 | #include <net/udp.h> | 50 | #include <net/udp.h> |
51 | #include <net/inet_common.h> | 51 | #include <net/inet_common.h> |
52 | #include <net/tcp_states.h> | ||
52 | 53 | ||
53 | #include <net/rawv6.h> | 54 | #include <net/rawv6.h> |
54 | #include <net/xfrm.h> | 55 | #include <net/xfrm.h> |
@@ -81,7 +82,8 @@ static void raw_v6_unhash(struct sock *sk) | |||
81 | 82 | ||
82 | /* Grumble... icmp and ip_input want to get at this... */ | 83 | /* Grumble... icmp and ip_input want to get at this... */ |
83 | struct sock *__raw_v6_lookup(struct sock *sk, unsigned short num, | 84 | struct sock *__raw_v6_lookup(struct sock *sk, unsigned short num, |
84 | struct in6_addr *loc_addr, struct in6_addr *rmt_addr) | 85 | struct in6_addr *loc_addr, struct in6_addr *rmt_addr, |
86 | int dif) | ||
85 | { | 87 | { |
86 | struct hlist_node *node; | 88 | struct hlist_node *node; |
87 | int is_multicast = ipv6_addr_is_multicast(loc_addr); | 89 | int is_multicast = ipv6_addr_is_multicast(loc_addr); |
@@ -94,6 +96,9 @@ struct sock *__raw_v6_lookup(struct sock *sk, unsigned short num, | |||
94 | !ipv6_addr_equal(&np->daddr, rmt_addr)) | 96 | !ipv6_addr_equal(&np->daddr, rmt_addr)) |
95 | continue; | 97 | continue; |
96 | 98 | ||
99 | if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif) | ||
100 | continue; | ||
101 | |||
97 | if (!ipv6_addr_any(&np->rcv_saddr)) { | 102 | if (!ipv6_addr_any(&np->rcv_saddr)) { |
98 | if (ipv6_addr_equal(&np->rcv_saddr, loc_addr)) | 103 | if (ipv6_addr_equal(&np->rcv_saddr, loc_addr)) |
99 | goto found; | 104 | goto found; |
@@ -137,11 +142,12 @@ static __inline__ int icmpv6_filter(struct sock *sk, struct sk_buff *skb) | |||
137 | * | 142 | * |
138 | * Caller owns SKB so we must make clones. | 143 | * Caller owns SKB so we must make clones. |
139 | */ | 144 | */ |
140 | void ipv6_raw_deliver(struct sk_buff *skb, int nexthdr) | 145 | int ipv6_raw_deliver(struct sk_buff *skb, int nexthdr) |
141 | { | 146 | { |
142 | struct in6_addr *saddr; | 147 | struct in6_addr *saddr; |
143 | struct in6_addr *daddr; | 148 | struct in6_addr *daddr; |
144 | struct sock *sk; | 149 | struct sock *sk; |
150 | int delivered = 0; | ||
145 | __u8 hash; | 151 | __u8 hash; |
146 | 152 | ||
147 | saddr = &skb->nh.ipv6h->saddr; | 153 | saddr = &skb->nh.ipv6h->saddr; |
@@ -160,9 +166,10 @@ void ipv6_raw_deliver(struct sk_buff *skb, int nexthdr) | |||
160 | if (sk == NULL) | 166 | if (sk == NULL) |
161 | goto out; | 167 | goto out; |
162 | 168 | ||
163 | sk = __raw_v6_lookup(sk, nexthdr, daddr, saddr); | 169 | sk = __raw_v6_lookup(sk, nexthdr, daddr, saddr, skb->dev->ifindex); |
164 | 170 | ||
165 | while (sk) { | 171 | while (sk) { |
172 | delivered = 1; | ||
166 | if (nexthdr != IPPROTO_ICMPV6 || !icmpv6_filter(sk, skb)) { | 173 | if (nexthdr != IPPROTO_ICMPV6 || !icmpv6_filter(sk, skb)) { |
167 | struct sk_buff *clone = skb_clone(skb, GFP_ATOMIC); | 174 | struct sk_buff *clone = skb_clone(skb, GFP_ATOMIC); |
168 | 175 | ||
@@ -170,10 +177,12 @@ void ipv6_raw_deliver(struct sk_buff *skb, int nexthdr) | |||
170 | if (clone) | 177 | if (clone) |
171 | rawv6_rcv(sk, clone); | 178 | rawv6_rcv(sk, clone); |
172 | } | 179 | } |
173 | sk = __raw_v6_lookup(sk_next(sk), nexthdr, daddr, saddr); | 180 | sk = __raw_v6_lookup(sk_next(sk), nexthdr, daddr, saddr, |
181 | skb->dev->ifindex); | ||
174 | } | 182 | } |
175 | out: | 183 | out: |
176 | read_unlock(&raw_v6_lock); | 184 | read_unlock(&raw_v6_lock); |
185 | return delivered; | ||
177 | } | 186 | } |
178 | 187 | ||
179 | /* This cleans up af_inet6 a bit. -DaveM */ | 188 | /* This cleans up af_inet6 a bit. -DaveM */ |
@@ -334,8 +343,7 @@ int rawv6_rcv(struct sock *sk, struct sk_buff *skb) | |||
334 | if (csum_ipv6_magic(&skb->nh.ipv6h->saddr, | 343 | if (csum_ipv6_magic(&skb->nh.ipv6h->saddr, |
335 | &skb->nh.ipv6h->daddr, | 344 | &skb->nh.ipv6h->daddr, |
336 | skb->len, inet->num, skb->csum)) { | 345 | skb->len, inet->num, skb->csum)) { |
337 | LIMIT_NETDEBUG( | 346 | LIMIT_NETDEBUG(KERN_DEBUG "raw v6 hw csum failure.\n"); |
338 | printk(KERN_DEBUG "raw v6 hw csum failure.\n")); | ||
339 | skb->ip_summed = CHECKSUM_NONE; | 347 | skb->ip_summed = CHECKSUM_NONE; |
340 | } | 348 | } |
341 | } | 349 | } |
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 59e7c6317872..9d9e04344c77 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c | |||
@@ -562,7 +562,7 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
562 | if (skb->dev) | 562 | if (skb->dev) |
563 | fq->iif = skb->dev->ifindex; | 563 | fq->iif = skb->dev->ifindex; |
564 | skb->dev = NULL; | 564 | skb->dev = NULL; |
565 | fq->stamp = skb->stamp; | 565 | skb_get_timestamp(skb, &fq->stamp); |
566 | fq->meat += skb->len; | 566 | fq->meat += skb->len; |
567 | atomic_add(skb->truesize, &ip6_frag_mem); | 567 | atomic_add(skb->truesize, &ip6_frag_mem); |
568 | 568 | ||
@@ -664,7 +664,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in, | |||
664 | 664 | ||
665 | head->next = NULL; | 665 | head->next = NULL; |
666 | head->dev = dev; | 666 | head->dev = dev; |
667 | head->stamp = fq->stamp; | 667 | skb_set_timestamp(head, &fq->stamp); |
668 | head->nh.ipv6h->payload_len = htons(payload_len); | 668 | head->nh.ipv6h->payload_len = htons(payload_len); |
669 | 669 | ||
670 | *skb_in = head; | 670 | *skb_in = head; |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 878789b3122d..5d5bbb49ec78 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -1372,7 +1372,7 @@ int ipv6_route_ioctl(unsigned int cmd, void __user *arg) | |||
1372 | * Drop the packet on the floor | 1372 | * Drop the packet on the floor |
1373 | */ | 1373 | */ |
1374 | 1374 | ||
1375 | int ip6_pkt_discard(struct sk_buff *skb) | 1375 | static int ip6_pkt_discard(struct sk_buff *skb) |
1376 | { | 1376 | { |
1377 | IP6_INC_STATS(IPSTATS_MIB_OUTNOROUTES); | 1377 | IP6_INC_STATS(IPSTATS_MIB_OUTNOROUTES); |
1378 | icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_NOROUTE, 0, skb->dev); | 1378 | icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_NOROUTE, 0, skb->dev); |
@@ -1380,7 +1380,7 @@ int ip6_pkt_discard(struct sk_buff *skb) | |||
1380 | return 0; | 1380 | return 0; |
1381 | } | 1381 | } |
1382 | 1382 | ||
1383 | int ip6_pkt_discard_out(struct sk_buff *skb) | 1383 | static int ip6_pkt_discard_out(struct sk_buff *skb) |
1384 | { | 1384 | { |
1385 | skb->dev = skb->dst->dev; | 1385 | skb->dev = skb->dst->dev; |
1386 | return ip6_pkt_discard(skb); | 1386 | return ip6_pkt_discard(skb); |
@@ -1850,16 +1850,16 @@ void inet6_rt_notify(int event, struct rt6_info *rt, struct nlmsghdr *nlh, | |||
1850 | 1850 | ||
1851 | skb = alloc_skb(size, gfp_any()); | 1851 | skb = alloc_skb(size, gfp_any()); |
1852 | if (!skb) { | 1852 | if (!skb) { |
1853 | netlink_set_err(rtnl, 0, RTMGRP_IPV6_ROUTE, ENOBUFS); | 1853 | netlink_set_err(rtnl, 0, RTNLGRP_IPV6_ROUTE, ENOBUFS); |
1854 | return; | 1854 | return; |
1855 | } | 1855 | } |
1856 | if (rt6_fill_node(skb, rt, NULL, NULL, 0, event, pid, seq, 0, 0) < 0) { | 1856 | if (rt6_fill_node(skb, rt, NULL, NULL, 0, event, pid, seq, 0, 0) < 0) { |
1857 | kfree_skb(skb); | 1857 | kfree_skb(skb); |
1858 | netlink_set_err(rtnl, 0, RTMGRP_IPV6_ROUTE, EINVAL); | 1858 | netlink_set_err(rtnl, 0, RTNLGRP_IPV6_ROUTE, EINVAL); |
1859 | return; | 1859 | return; |
1860 | } | 1860 | } |
1861 | NETLINK_CB(skb).dst_groups = RTMGRP_IPV6_ROUTE; | 1861 | NETLINK_CB(skb).dst_group = RTNLGRP_IPV6_ROUTE; |
1862 | netlink_broadcast(rtnl, skb, 0, RTMGRP_IPV6_ROUTE, gfp_any()); | 1862 | netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV6_ROUTE, gfp_any()); |
1863 | } | 1863 | } |
1864 | 1864 | ||
1865 | /* | 1865 | /* |
@@ -1960,8 +1960,6 @@ static int rt6_proc_info(char *buffer, char **start, off_t offset, int length) | |||
1960 | return arg.len; | 1960 | return arg.len; |
1961 | } | 1961 | } |
1962 | 1962 | ||
1963 | extern struct rt6_statistics rt6_stats; | ||
1964 | |||
1965 | static int rt6_stats_seq_show(struct seq_file *seq, void *v) | 1963 | static int rt6_stats_seq_show(struct seq_file *seq, void *v) |
1966 | { | 1964 | { |
1967 | seq_printf(seq, "%04x %04x %04x %04x %04x %04x %04x\n", | 1965 | seq_printf(seq, "%04x %04x %04x %04x %04x %04x %04x\n", |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index e553e5b80d6e..c3123c9e1a8e 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -770,7 +770,7 @@ static int ipip6_tunnel_init(struct net_device *dev) | |||
770 | return 0; | 770 | return 0; |
771 | } | 771 | } |
772 | 772 | ||
773 | int __init ipip6_fb_tunnel_init(struct net_device *dev) | 773 | static int __init ipip6_fb_tunnel_init(struct net_device *dev) |
774 | { | 774 | { |
775 | struct ip_tunnel *tunnel = dev->priv; | 775 | struct ip_tunnel *tunnel = dev->priv; |
776 | struct iphdr *iph = &tunnel->parms.iph; | 776 | struct iphdr *iph = &tunnel->parms.iph; |
diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c index 3a18e0e6ffed..8eff9fa1e983 100644 --- a/net/ipv6/sysctl_net_ipv6.c +++ b/net/ipv6/sysctl_net_ipv6.c | |||
@@ -14,9 +14,6 @@ | |||
14 | #include <net/ipv6.h> | 14 | #include <net/ipv6.h> |
15 | #include <net/addrconf.h> | 15 | #include <net/addrconf.h> |
16 | 16 | ||
17 | extern ctl_table ipv6_route_table[]; | ||
18 | extern ctl_table ipv6_icmp_table[]; | ||
19 | |||
20 | #ifdef CONFIG_SYSCTL | 17 | #ifdef CONFIG_SYSCTL |
21 | 18 | ||
22 | static ctl_table ipv6_table[] = { | 19 | static ctl_table ipv6_table[] = { |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index ef29cfd936d3..794734f1d230 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -47,6 +47,7 @@ | |||
47 | 47 | ||
48 | #include <net/tcp.h> | 48 | #include <net/tcp.h> |
49 | #include <net/ndisc.h> | 49 | #include <net/ndisc.h> |
50 | #include <net/inet6_hashtables.h> | ||
50 | #include <net/ipv6.h> | 51 | #include <net/ipv6.h> |
51 | #include <net/transp_v6.h> | 52 | #include <net/transp_v6.h> |
52 | #include <net/addrconf.h> | 53 | #include <net/addrconf.h> |
@@ -75,34 +76,11 @@ static int tcp_v6_xmit(struct sk_buff *skb, int ipfragok); | |||
75 | static struct tcp_func ipv6_mapped; | 76 | static struct tcp_func ipv6_mapped; |
76 | static struct tcp_func ipv6_specific; | 77 | static struct tcp_func ipv6_specific; |
77 | 78 | ||
78 | /* I have no idea if this is a good hash for v6 or not. -DaveM */ | 79 | static inline int tcp_v6_bind_conflict(const struct sock *sk, |
79 | static __inline__ int tcp_v6_hashfn(struct in6_addr *laddr, u16 lport, | 80 | const struct inet_bind_bucket *tb) |
80 | struct in6_addr *faddr, u16 fport) | ||
81 | { | 81 | { |
82 | int hashent = (lport ^ fport); | 82 | const struct sock *sk2; |
83 | 83 | const struct hlist_node *node; | |
84 | hashent ^= (laddr->s6_addr32[3] ^ faddr->s6_addr32[3]); | ||
85 | hashent ^= hashent>>16; | ||
86 | hashent ^= hashent>>8; | ||
87 | return (hashent & (tcp_ehash_size - 1)); | ||
88 | } | ||
89 | |||
90 | static __inline__ int tcp_v6_sk_hashfn(struct sock *sk) | ||
91 | { | ||
92 | struct inet_sock *inet = inet_sk(sk); | ||
93 | struct ipv6_pinfo *np = inet6_sk(sk); | ||
94 | struct in6_addr *laddr = &np->rcv_saddr; | ||
95 | struct in6_addr *faddr = &np->daddr; | ||
96 | __u16 lport = inet->num; | ||
97 | __u16 fport = inet->dport; | ||
98 | return tcp_v6_hashfn(laddr, lport, faddr, fport); | ||
99 | } | ||
100 | |||
101 | static inline int tcp_v6_bind_conflict(struct sock *sk, | ||
102 | struct tcp_bind_bucket *tb) | ||
103 | { | ||
104 | struct sock *sk2; | ||
105 | struct hlist_node *node; | ||
106 | 84 | ||
107 | /* We must walk the whole port owner list in this case. -DaveM */ | 85 | /* We must walk the whole port owner list in this case. -DaveM */ |
108 | sk_for_each_bound(sk2, node, &tb->owners) { | 86 | sk_for_each_bound(sk2, node, &tb->owners) { |
@@ -126,8 +104,8 @@ static inline int tcp_v6_bind_conflict(struct sock *sk, | |||
126 | */ | 104 | */ |
127 | static int tcp_v6_get_port(struct sock *sk, unsigned short snum) | 105 | static int tcp_v6_get_port(struct sock *sk, unsigned short snum) |
128 | { | 106 | { |
129 | struct tcp_bind_hashbucket *head; | 107 | struct inet_bind_hashbucket *head; |
130 | struct tcp_bind_bucket *tb; | 108 | struct inet_bind_bucket *tb; |
131 | struct hlist_node *node; | 109 | struct hlist_node *node; |
132 | int ret; | 110 | int ret; |
133 | 111 | ||
@@ -138,25 +116,25 @@ static int tcp_v6_get_port(struct sock *sk, unsigned short snum) | |||
138 | int remaining = (high - low) + 1; | 116 | int remaining = (high - low) + 1; |
139 | int rover; | 117 | int rover; |
140 | 118 | ||
141 | spin_lock(&tcp_portalloc_lock); | 119 | spin_lock(&tcp_hashinfo.portalloc_lock); |
142 | if (tcp_port_rover < low) | 120 | if (tcp_hashinfo.port_rover < low) |
143 | rover = low; | 121 | rover = low; |
144 | else | 122 | else |
145 | rover = tcp_port_rover; | 123 | rover = tcp_hashinfo.port_rover; |
146 | do { rover++; | 124 | do { rover++; |
147 | if (rover > high) | 125 | if (rover > high) |
148 | rover = low; | 126 | rover = low; |
149 | head = &tcp_bhash[tcp_bhashfn(rover)]; | 127 | head = &tcp_hashinfo.bhash[inet_bhashfn(rover, tcp_hashinfo.bhash_size)]; |
150 | spin_lock(&head->lock); | 128 | spin_lock(&head->lock); |
151 | tb_for_each(tb, node, &head->chain) | 129 | inet_bind_bucket_for_each(tb, node, &head->chain) |
152 | if (tb->port == rover) | 130 | if (tb->port == rover) |
153 | goto next; | 131 | goto next; |
154 | break; | 132 | break; |
155 | next: | 133 | next: |
156 | spin_unlock(&head->lock); | 134 | spin_unlock(&head->lock); |
157 | } while (--remaining > 0); | 135 | } while (--remaining > 0); |
158 | tcp_port_rover = rover; | 136 | tcp_hashinfo.port_rover = rover; |
159 | spin_unlock(&tcp_portalloc_lock); | 137 | spin_unlock(&tcp_hashinfo.portalloc_lock); |
160 | 138 | ||
161 | /* Exhausted local port range during search? It is not | 139 | /* Exhausted local port range during search? It is not |
162 | * possible for us to be holding one of the bind hash | 140 | * possible for us to be holding one of the bind hash |
@@ -171,9 +149,9 @@ static int tcp_v6_get_port(struct sock *sk, unsigned short snum) | |||
171 | /* OK, here is the one we will use. */ | 149 | /* OK, here is the one we will use. */ |
172 | snum = rover; | 150 | snum = rover; |
173 | } else { | 151 | } else { |
174 | head = &tcp_bhash[tcp_bhashfn(snum)]; | 152 | head = &tcp_hashinfo.bhash[inet_bhashfn(snum, tcp_hashinfo.bhash_size)]; |
175 | spin_lock(&head->lock); | 153 | spin_lock(&head->lock); |
176 | tb_for_each(tb, node, &head->chain) | 154 | inet_bind_bucket_for_each(tb, node, &head->chain) |
177 | if (tb->port == snum) | 155 | if (tb->port == snum) |
178 | goto tb_found; | 156 | goto tb_found; |
179 | } | 157 | } |
@@ -192,8 +170,11 @@ tb_found: | |||
192 | } | 170 | } |
193 | tb_not_found: | 171 | tb_not_found: |
194 | ret = 1; | 172 | ret = 1; |
195 | if (!tb && (tb = tcp_bucket_create(head, snum)) == NULL) | 173 | if (tb == NULL) { |
196 | goto fail_unlock; | 174 | tb = inet_bind_bucket_create(tcp_hashinfo.bind_bucket_cachep, head, snum); |
175 | if (tb == NULL) | ||
176 | goto fail_unlock; | ||
177 | } | ||
197 | if (hlist_empty(&tb->owners)) { | 178 | if (hlist_empty(&tb->owners)) { |
198 | if (sk->sk_reuse && sk->sk_state != TCP_LISTEN) | 179 | if (sk->sk_reuse && sk->sk_state != TCP_LISTEN) |
199 | tb->fastreuse = 1; | 180 | tb->fastreuse = 1; |
@@ -204,9 +185,9 @@ tb_not_found: | |||
204 | tb->fastreuse = 0; | 185 | tb->fastreuse = 0; |
205 | 186 | ||
206 | success: | 187 | success: |
207 | if (!tcp_sk(sk)->bind_hash) | 188 | if (!inet_csk(sk)->icsk_bind_hash) |
208 | tcp_bind_hash(sk, tb, snum); | 189 | inet_bind_hash(sk, tb, snum); |
209 | BUG_TRAP(tcp_sk(sk)->bind_hash == tb); | 190 | BUG_TRAP(inet_csk(sk)->icsk_bind_hash == tb); |
210 | ret = 0; | 191 | ret = 0; |
211 | 192 | ||
212 | fail_unlock: | 193 | fail_unlock: |
@@ -224,13 +205,13 @@ static __inline__ void __tcp_v6_hash(struct sock *sk) | |||
224 | BUG_TRAP(sk_unhashed(sk)); | 205 | BUG_TRAP(sk_unhashed(sk)); |
225 | 206 | ||
226 | if (sk->sk_state == TCP_LISTEN) { | 207 | if (sk->sk_state == TCP_LISTEN) { |
227 | list = &tcp_listening_hash[tcp_sk_listen_hashfn(sk)]; | 208 | list = &tcp_hashinfo.listening_hash[inet_sk_listen_hashfn(sk)]; |
228 | lock = &tcp_lhash_lock; | 209 | lock = &tcp_hashinfo.lhash_lock; |
229 | tcp_listen_wlock(); | 210 | inet_listen_wlock(&tcp_hashinfo); |
230 | } else { | 211 | } else { |
231 | sk->sk_hashent = tcp_v6_sk_hashfn(sk); | 212 | sk->sk_hashent = inet6_sk_ehashfn(sk, tcp_hashinfo.ehash_size); |
232 | list = &tcp_ehash[sk->sk_hashent].chain; | 213 | list = &tcp_hashinfo.ehash[sk->sk_hashent].chain; |
233 | lock = &tcp_ehash[sk->sk_hashent].lock; | 214 | lock = &tcp_hashinfo.ehash[sk->sk_hashent].lock; |
234 | write_lock(lock); | 215 | write_lock(lock); |
235 | } | 216 | } |
236 | 217 | ||
@@ -255,131 +236,11 @@ static void tcp_v6_hash(struct sock *sk) | |||
255 | } | 236 | } |
256 | } | 237 | } |
257 | 238 | ||
258 | static struct sock *tcp_v6_lookup_listener(struct in6_addr *daddr, unsigned short hnum, int dif) | ||
259 | { | ||
260 | struct sock *sk; | ||
261 | struct hlist_node *node; | ||
262 | struct sock *result = NULL; | ||
263 | int score, hiscore; | ||
264 | |||
265 | hiscore=0; | ||
266 | read_lock(&tcp_lhash_lock); | ||
267 | sk_for_each(sk, node, &tcp_listening_hash[tcp_lhashfn(hnum)]) { | ||
268 | if (inet_sk(sk)->num == hnum && sk->sk_family == PF_INET6) { | ||
269 | struct ipv6_pinfo *np = inet6_sk(sk); | ||
270 | |||
271 | score = 1; | ||
272 | if (!ipv6_addr_any(&np->rcv_saddr)) { | ||
273 | if (!ipv6_addr_equal(&np->rcv_saddr, daddr)) | ||
274 | continue; | ||
275 | score++; | ||
276 | } | ||
277 | if (sk->sk_bound_dev_if) { | ||
278 | if (sk->sk_bound_dev_if != dif) | ||
279 | continue; | ||
280 | score++; | ||
281 | } | ||
282 | if (score == 3) { | ||
283 | result = sk; | ||
284 | break; | ||
285 | } | ||
286 | if (score > hiscore) { | ||
287 | hiscore = score; | ||
288 | result = sk; | ||
289 | } | ||
290 | } | ||
291 | } | ||
292 | if (result) | ||
293 | sock_hold(result); | ||
294 | read_unlock(&tcp_lhash_lock); | ||
295 | return result; | ||
296 | } | ||
297 | |||
298 | /* Sockets in TCP_CLOSE state are _always_ taken out of the hash, so | ||
299 | * we need not check it for TCP lookups anymore, thanks Alexey. -DaveM | ||
300 | * | ||
301 | * The sockhash lock must be held as a reader here. | ||
302 | */ | ||
303 | |||
304 | static inline struct sock *__tcp_v6_lookup_established(struct in6_addr *saddr, u16 sport, | ||
305 | struct in6_addr *daddr, u16 hnum, | ||
306 | int dif) | ||
307 | { | ||
308 | struct tcp_ehash_bucket *head; | ||
309 | struct sock *sk; | ||
310 | struct hlist_node *node; | ||
311 | __u32 ports = TCP_COMBINED_PORTS(sport, hnum); | ||
312 | int hash; | ||
313 | |||
314 | /* Optimize here for direct hit, only listening connections can | ||
315 | * have wildcards anyways. | ||
316 | */ | ||
317 | hash = tcp_v6_hashfn(daddr, hnum, saddr, sport); | ||
318 | head = &tcp_ehash[hash]; | ||
319 | read_lock(&head->lock); | ||
320 | sk_for_each(sk, node, &head->chain) { | ||
321 | /* For IPV6 do the cheaper port and family tests first. */ | ||
322 | if(TCP_IPV6_MATCH(sk, saddr, daddr, ports, dif)) | ||
323 | goto hit; /* You sunk my battleship! */ | ||
324 | } | ||
325 | /* Must check for a TIME_WAIT'er before going to listener hash. */ | ||
326 | sk_for_each(sk, node, &(head + tcp_ehash_size)->chain) { | ||
327 | /* FIXME: acme: check this... */ | ||
328 | struct tcp_tw_bucket *tw = (struct tcp_tw_bucket *)sk; | ||
329 | |||
330 | if(*((__u32 *)&(tw->tw_dport)) == ports && | ||
331 | sk->sk_family == PF_INET6) { | ||
332 | if(ipv6_addr_equal(&tw->tw_v6_daddr, saddr) && | ||
333 | ipv6_addr_equal(&tw->tw_v6_rcv_saddr, daddr) && | ||
334 | (!sk->sk_bound_dev_if || sk->sk_bound_dev_if == dif)) | ||
335 | goto hit; | ||
336 | } | ||
337 | } | ||
338 | read_unlock(&head->lock); | ||
339 | return NULL; | ||
340 | |||
341 | hit: | ||
342 | sock_hold(sk); | ||
343 | read_unlock(&head->lock); | ||
344 | return sk; | ||
345 | } | ||
346 | |||
347 | |||
348 | static inline struct sock *__tcp_v6_lookup(struct in6_addr *saddr, u16 sport, | ||
349 | struct in6_addr *daddr, u16 hnum, | ||
350 | int dif) | ||
351 | { | ||
352 | struct sock *sk; | ||
353 | |||
354 | sk = __tcp_v6_lookup_established(saddr, sport, daddr, hnum, dif); | ||
355 | |||
356 | if (sk) | ||
357 | return sk; | ||
358 | |||
359 | return tcp_v6_lookup_listener(daddr, hnum, dif); | ||
360 | } | ||
361 | |||
362 | inline struct sock *tcp_v6_lookup(struct in6_addr *saddr, u16 sport, | ||
363 | struct in6_addr *daddr, u16 dport, | ||
364 | int dif) | ||
365 | { | ||
366 | struct sock *sk; | ||
367 | |||
368 | local_bh_disable(); | ||
369 | sk = __tcp_v6_lookup(saddr, sport, daddr, ntohs(dport), dif); | ||
370 | local_bh_enable(); | ||
371 | |||
372 | return sk; | ||
373 | } | ||
374 | |||
375 | EXPORT_SYMBOL_GPL(tcp_v6_lookup); | ||
376 | |||
377 | |||
378 | /* | 239 | /* |
379 | * Open request hash tables. | 240 | * Open request hash tables. |
380 | */ | 241 | */ |
381 | 242 | ||
382 | static u32 tcp_v6_synq_hash(struct in6_addr *raddr, u16 rport, u32 rnd) | 243 | static u32 tcp_v6_synq_hash(const struct in6_addr *raddr, const u16 rport, const u32 rnd) |
383 | { | 244 | { |
384 | u32 a, b, c; | 245 | u32 a, b, c; |
385 | 246 | ||
@@ -399,14 +260,15 @@ static u32 tcp_v6_synq_hash(struct in6_addr *raddr, u16 rport, u32 rnd) | |||
399 | return c & (TCP_SYNQ_HSIZE - 1); | 260 | return c & (TCP_SYNQ_HSIZE - 1); |
400 | } | 261 | } |
401 | 262 | ||
402 | static struct request_sock *tcp_v6_search_req(struct tcp_sock *tp, | 263 | static struct request_sock *tcp_v6_search_req(const struct sock *sk, |
403 | struct request_sock ***prevp, | 264 | struct request_sock ***prevp, |
404 | __u16 rport, | 265 | __u16 rport, |
405 | struct in6_addr *raddr, | 266 | struct in6_addr *raddr, |
406 | struct in6_addr *laddr, | 267 | struct in6_addr *laddr, |
407 | int iif) | 268 | int iif) |
408 | { | 269 | { |
409 | struct listen_sock *lopt = tp->accept_queue.listen_opt; | 270 | const struct inet_connection_sock *icsk = inet_csk(sk); |
271 | struct listen_sock *lopt = icsk->icsk_accept_queue.listen_opt; | ||
410 | struct request_sock *req, **prev; | 272 | struct request_sock *req, **prev; |
411 | 273 | ||
412 | for (prev = &lopt->syn_table[tcp_v6_synq_hash(raddr, rport, lopt->hash_rnd)]; | 274 | for (prev = &lopt->syn_table[tcp_v6_synq_hash(raddr, rport, lopt->hash_rnd)]; |
@@ -451,44 +313,48 @@ static __u32 tcp_v6_init_sequence(struct sock *sk, struct sk_buff *skb) | |||
451 | } | 313 | } |
452 | } | 314 | } |
453 | 315 | ||
454 | static int __tcp_v6_check_established(struct sock *sk, __u16 lport, | 316 | static int __tcp_v6_check_established(struct sock *sk, const __u16 lport, |
455 | struct tcp_tw_bucket **twp) | 317 | struct inet_timewait_sock **twp) |
456 | { | 318 | { |
457 | struct inet_sock *inet = inet_sk(sk); | 319 | struct inet_sock *inet = inet_sk(sk); |
458 | struct ipv6_pinfo *np = inet6_sk(sk); | 320 | const struct ipv6_pinfo *np = inet6_sk(sk); |
459 | struct in6_addr *daddr = &np->rcv_saddr; | 321 | const struct in6_addr *daddr = &np->rcv_saddr; |
460 | struct in6_addr *saddr = &np->daddr; | 322 | const struct in6_addr *saddr = &np->daddr; |
461 | int dif = sk->sk_bound_dev_if; | 323 | const int dif = sk->sk_bound_dev_if; |
462 | u32 ports = TCP_COMBINED_PORTS(inet->dport, lport); | 324 | const u32 ports = INET_COMBINED_PORTS(inet->dport, lport); |
463 | int hash = tcp_v6_hashfn(daddr, inet->num, saddr, inet->dport); | 325 | const int hash = inet6_ehashfn(daddr, inet->num, saddr, inet->dport, |
464 | struct tcp_ehash_bucket *head = &tcp_ehash[hash]; | 326 | tcp_hashinfo.ehash_size); |
327 | struct inet_ehash_bucket *head = &tcp_hashinfo.ehash[hash]; | ||
465 | struct sock *sk2; | 328 | struct sock *sk2; |
466 | struct hlist_node *node; | 329 | const struct hlist_node *node; |
467 | struct tcp_tw_bucket *tw; | 330 | struct inet_timewait_sock *tw; |
468 | 331 | ||
469 | write_lock(&head->lock); | 332 | write_lock(&head->lock); |
470 | 333 | ||
471 | /* Check TIME-WAIT sockets first. */ | 334 | /* Check TIME-WAIT sockets first. */ |
472 | sk_for_each(sk2, node, &(head + tcp_ehash_size)->chain) { | 335 | sk_for_each(sk2, node, &(head + tcp_hashinfo.ehash_size)->chain) { |
473 | tw = (struct tcp_tw_bucket*)sk2; | 336 | const struct tcp6_timewait_sock *tcp6tw = tcp6_twsk(sk2); |
337 | |||
338 | tw = inet_twsk(sk2); | ||
474 | 339 | ||
475 | if(*((__u32 *)&(tw->tw_dport)) == ports && | 340 | if(*((__u32 *)&(tw->tw_dport)) == ports && |
476 | sk2->sk_family == PF_INET6 && | 341 | sk2->sk_family == PF_INET6 && |
477 | ipv6_addr_equal(&tw->tw_v6_daddr, saddr) && | 342 | ipv6_addr_equal(&tcp6tw->tw_v6_daddr, saddr) && |
478 | ipv6_addr_equal(&tw->tw_v6_rcv_saddr, daddr) && | 343 | ipv6_addr_equal(&tcp6tw->tw_v6_rcv_saddr, daddr) && |
479 | sk2->sk_bound_dev_if == sk->sk_bound_dev_if) { | 344 | sk2->sk_bound_dev_if == sk->sk_bound_dev_if) { |
345 | const struct tcp_timewait_sock *tcptw = tcp_twsk(sk2); | ||
480 | struct tcp_sock *tp = tcp_sk(sk); | 346 | struct tcp_sock *tp = tcp_sk(sk); |
481 | 347 | ||
482 | if (tw->tw_ts_recent_stamp && | 348 | if (tcptw->tw_ts_recent_stamp && |
483 | (!twp || (sysctl_tcp_tw_reuse && | 349 | (!twp || |
484 | xtime.tv_sec - | 350 | (sysctl_tcp_tw_reuse && |
485 | tw->tw_ts_recent_stamp > 1))) { | 351 | xtime.tv_sec - tcptw->tw_ts_recent_stamp > 1))) { |
486 | /* See comment in tcp_ipv4.c */ | 352 | /* See comment in tcp_ipv4.c */ |
487 | tp->write_seq = tw->tw_snd_nxt + 65535 + 2; | 353 | tp->write_seq = tcptw->tw_snd_nxt + 65535 + 2; |
488 | if (!tp->write_seq) | 354 | if (!tp->write_seq) |
489 | tp->write_seq = 1; | 355 | tp->write_seq = 1; |
490 | tp->rx_opt.ts_recent = tw->tw_ts_recent; | 356 | tp->rx_opt.ts_recent = tcptw->tw_ts_recent; |
491 | tp->rx_opt.ts_recent_stamp = tw->tw_ts_recent_stamp; | 357 | tp->rx_opt.ts_recent_stamp = tcptw->tw_ts_recent_stamp; |
492 | sock_hold(sk2); | 358 | sock_hold(sk2); |
493 | goto unique; | 359 | goto unique; |
494 | } else | 360 | } else |
@@ -499,7 +365,7 @@ static int __tcp_v6_check_established(struct sock *sk, __u16 lport, | |||
499 | 365 | ||
500 | /* And established part... */ | 366 | /* And established part... */ |
501 | sk_for_each(sk2, node, &head->chain) { | 367 | sk_for_each(sk2, node, &head->chain) { |
502 | if(TCP_IPV6_MATCH(sk2, saddr, daddr, ports, dif)) | 368 | if (INET6_MATCH(sk2, saddr, daddr, ports, dif)) |
503 | goto not_unique; | 369 | goto not_unique; |
504 | } | 370 | } |
505 | 371 | ||
@@ -515,10 +381,10 @@ unique: | |||
515 | NET_INC_STATS_BH(LINUX_MIB_TIMEWAITRECYCLED); | 381 | NET_INC_STATS_BH(LINUX_MIB_TIMEWAITRECYCLED); |
516 | } else if (tw) { | 382 | } else if (tw) { |
517 | /* Silly. Should hash-dance instead... */ | 383 | /* Silly. Should hash-dance instead... */ |
518 | tcp_tw_deschedule(tw); | 384 | inet_twsk_deschedule(tw, &tcp_death_row); |
519 | NET_INC_STATS_BH(LINUX_MIB_TIMEWAITRECYCLED); | 385 | NET_INC_STATS_BH(LINUX_MIB_TIMEWAITRECYCLED); |
520 | 386 | ||
521 | tcp_tw_put(tw); | 387 | inet_twsk_put(tw); |
522 | } | 388 | } |
523 | return 0; | 389 | return 0; |
524 | 390 | ||
@@ -540,8 +406,8 @@ static inline u32 tcpv6_port_offset(const struct sock *sk) | |||
540 | static int tcp_v6_hash_connect(struct sock *sk) | 406 | static int tcp_v6_hash_connect(struct sock *sk) |
541 | { | 407 | { |
542 | unsigned short snum = inet_sk(sk)->num; | 408 | unsigned short snum = inet_sk(sk)->num; |
543 | struct tcp_bind_hashbucket *head; | 409 | struct inet_bind_hashbucket *head; |
544 | struct tcp_bind_bucket *tb; | 410 | struct inet_bind_bucket *tb; |
545 | int ret; | 411 | int ret; |
546 | 412 | ||
547 | if (!snum) { | 413 | if (!snum) { |
@@ -553,19 +419,19 @@ static int tcp_v6_hash_connect(struct sock *sk) | |||
553 | static u32 hint; | 419 | static u32 hint; |
554 | u32 offset = hint + tcpv6_port_offset(sk); | 420 | u32 offset = hint + tcpv6_port_offset(sk); |
555 | struct hlist_node *node; | 421 | struct hlist_node *node; |
556 | struct tcp_tw_bucket *tw = NULL; | 422 | struct inet_timewait_sock *tw = NULL; |
557 | 423 | ||
558 | local_bh_disable(); | 424 | local_bh_disable(); |
559 | for (i = 1; i <= range; i++) { | 425 | for (i = 1; i <= range; i++) { |
560 | port = low + (i + offset) % range; | 426 | port = low + (i + offset) % range; |
561 | head = &tcp_bhash[tcp_bhashfn(port)]; | 427 | head = &tcp_hashinfo.bhash[inet_bhashfn(port, tcp_hashinfo.bhash_size)]; |
562 | spin_lock(&head->lock); | 428 | spin_lock(&head->lock); |
563 | 429 | ||
564 | /* Does not bother with rcv_saddr checks, | 430 | /* Does not bother with rcv_saddr checks, |
565 | * because the established check is already | 431 | * because the established check is already |
566 | * unique enough. | 432 | * unique enough. |
567 | */ | 433 | */ |
568 | tb_for_each(tb, node, &head->chain) { | 434 | inet_bind_bucket_for_each(tb, node, &head->chain) { |
569 | if (tb->port == port) { | 435 | if (tb->port == port) { |
570 | BUG_TRAP(!hlist_empty(&tb->owners)); | 436 | BUG_TRAP(!hlist_empty(&tb->owners)); |
571 | if (tb->fastreuse >= 0) | 437 | if (tb->fastreuse >= 0) |
@@ -578,7 +444,7 @@ static int tcp_v6_hash_connect(struct sock *sk) | |||
578 | } | 444 | } |
579 | } | 445 | } |
580 | 446 | ||
581 | tb = tcp_bucket_create(head, port); | 447 | tb = inet_bind_bucket_create(tcp_hashinfo.bind_bucket_cachep, head, port); |
582 | if (!tb) { | 448 | if (!tb) { |
583 | spin_unlock(&head->lock); | 449 | spin_unlock(&head->lock); |
584 | break; | 450 | break; |
@@ -597,7 +463,7 @@ ok: | |||
597 | hint += i; | 463 | hint += i; |
598 | 464 | ||
599 | /* Head lock still held and bh's disabled */ | 465 | /* Head lock still held and bh's disabled */ |
600 | tcp_bind_hash(sk, tb, port); | 466 | inet_bind_hash(sk, tb, port); |
601 | if (sk_unhashed(sk)) { | 467 | if (sk_unhashed(sk)) { |
602 | inet_sk(sk)->sport = htons(port); | 468 | inet_sk(sk)->sport = htons(port); |
603 | __tcp_v6_hash(sk); | 469 | __tcp_v6_hash(sk); |
@@ -605,16 +471,16 @@ ok: | |||
605 | spin_unlock(&head->lock); | 471 | spin_unlock(&head->lock); |
606 | 472 | ||
607 | if (tw) { | 473 | if (tw) { |
608 | tcp_tw_deschedule(tw); | 474 | inet_twsk_deschedule(tw, &tcp_death_row); |
609 | tcp_tw_put(tw); | 475 | inet_twsk_put(tw); |
610 | } | 476 | } |
611 | 477 | ||
612 | ret = 0; | 478 | ret = 0; |
613 | goto out; | 479 | goto out; |
614 | } | 480 | } |
615 | 481 | ||
616 | head = &tcp_bhash[tcp_bhashfn(snum)]; | 482 | head = &tcp_hashinfo.bhash[inet_bhashfn(snum, tcp_hashinfo.bhash_size)]; |
617 | tb = tcp_sk(sk)->bind_hash; | 483 | tb = inet_csk(sk)->icsk_bind_hash; |
618 | spin_lock_bh(&head->lock); | 484 | spin_lock_bh(&head->lock); |
619 | 485 | ||
620 | if (sk_head(&tb->owners) == sk && !sk->sk_bind_node.next) { | 486 | if (sk_head(&tb->owners) == sk && !sk->sk_bind_node.next) { |
@@ -631,11 +497,6 @@ out: | |||
631 | } | 497 | } |
632 | } | 498 | } |
633 | 499 | ||
634 | static __inline__ int tcp_v6_iif(struct sk_buff *skb) | ||
635 | { | ||
636 | return IP6CB(skb)->iif; | ||
637 | } | ||
638 | |||
639 | static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | 500 | static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, |
640 | int addr_len) | 501 | int addr_len) |
641 | { | 502 | { |
@@ -827,14 +688,15 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
827 | int type, int code, int offset, __u32 info) | 688 | int type, int code, int offset, __u32 info) |
828 | { | 689 | { |
829 | struct ipv6hdr *hdr = (struct ipv6hdr*)skb->data; | 690 | struct ipv6hdr *hdr = (struct ipv6hdr*)skb->data; |
830 | struct tcphdr *th = (struct tcphdr *)(skb->data+offset); | 691 | const struct tcphdr *th = (struct tcphdr *)(skb->data+offset); |
831 | struct ipv6_pinfo *np; | 692 | struct ipv6_pinfo *np; |
832 | struct sock *sk; | 693 | struct sock *sk; |
833 | int err; | 694 | int err; |
834 | struct tcp_sock *tp; | 695 | struct tcp_sock *tp; |
835 | __u32 seq; | 696 | __u32 seq; |
836 | 697 | ||
837 | sk = tcp_v6_lookup(&hdr->daddr, th->dest, &hdr->saddr, th->source, skb->dev->ifindex); | 698 | sk = inet6_lookup(&tcp_hashinfo, &hdr->daddr, th->dest, &hdr->saddr, |
699 | th->source, skb->dev->ifindex); | ||
838 | 700 | ||
839 | if (sk == NULL) { | 701 | if (sk == NULL) { |
840 | ICMP6_INC_STATS_BH(__in6_dev_get(skb->dev), ICMP6_MIB_INERRORS); | 702 | ICMP6_INC_STATS_BH(__in6_dev_get(skb->dev), ICMP6_MIB_INERRORS); |
@@ -842,7 +704,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
842 | } | 704 | } |
843 | 705 | ||
844 | if (sk->sk_state == TCP_TIME_WAIT) { | 706 | if (sk->sk_state == TCP_TIME_WAIT) { |
845 | tcp_tw_put((struct tcp_tw_bucket*)sk); | 707 | inet_twsk_put((struct inet_timewait_sock *)sk); |
846 | return; | 708 | return; |
847 | } | 709 | } |
848 | 710 | ||
@@ -920,8 +782,8 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
920 | if (sock_owned_by_user(sk)) | 782 | if (sock_owned_by_user(sk)) |
921 | goto out; | 783 | goto out; |
922 | 784 | ||
923 | req = tcp_v6_search_req(tp, &prev, th->dest, &hdr->daddr, | 785 | req = tcp_v6_search_req(sk, &prev, th->dest, &hdr->daddr, |
924 | &hdr->saddr, tcp_v6_iif(skb)); | 786 | &hdr->saddr, inet6_iif(skb)); |
925 | if (!req) | 787 | if (!req) |
926 | goto out; | 788 | goto out; |
927 | 789 | ||
@@ -935,7 +797,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
935 | goto out; | 797 | goto out; |
936 | } | 798 | } |
937 | 799 | ||
938 | tcp_synq_drop(sk, req, prev); | 800 | inet_csk_reqsk_queue_drop(sk, req, prev); |
939 | goto out; | 801 | goto out; |
940 | 802 | ||
941 | case TCP_SYN_SENT: | 803 | case TCP_SYN_SENT: |
@@ -1132,7 +994,7 @@ static void tcp_v6_send_reset(struct sk_buff *skb) | |||
1132 | buff->csum); | 994 | buff->csum); |
1133 | 995 | ||
1134 | fl.proto = IPPROTO_TCP; | 996 | fl.proto = IPPROTO_TCP; |
1135 | fl.oif = tcp_v6_iif(skb); | 997 | fl.oif = inet6_iif(skb); |
1136 | fl.fl_ip_dport = t1->dest; | 998 | fl.fl_ip_dport = t1->dest; |
1137 | fl.fl_ip_sport = t1->source; | 999 | fl.fl_ip_sport = t1->source; |
1138 | 1000 | ||
@@ -1201,7 +1063,7 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 | |||
1201 | buff->csum); | 1063 | buff->csum); |
1202 | 1064 | ||
1203 | fl.proto = IPPROTO_TCP; | 1065 | fl.proto = IPPROTO_TCP; |
1204 | fl.oif = tcp_v6_iif(skb); | 1066 | fl.oif = inet6_iif(skb); |
1205 | fl.fl_ip_dport = t1->dest; | 1067 | fl.fl_ip_dport = t1->dest; |
1206 | fl.fl_ip_sport = t1->source; | 1068 | fl.fl_ip_sport = t1->source; |
1207 | 1069 | ||
@@ -1220,12 +1082,14 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 | |||
1220 | 1082 | ||
1221 | static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb) | 1083 | static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb) |
1222 | { | 1084 | { |
1223 | struct tcp_tw_bucket *tw = (struct tcp_tw_bucket *)sk; | 1085 | struct inet_timewait_sock *tw = inet_twsk(sk); |
1086 | const struct tcp_timewait_sock *tcptw = tcp_twsk(sk); | ||
1224 | 1087 | ||
1225 | tcp_v6_send_ack(skb, tw->tw_snd_nxt, tw->tw_rcv_nxt, | 1088 | tcp_v6_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, |
1226 | tw->tw_rcv_wnd >> tw->tw_rcv_wscale, tw->tw_ts_recent); | 1089 | tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, |
1090 | tcptw->tw_ts_recent); | ||
1227 | 1091 | ||
1228 | tcp_tw_put(tw); | 1092 | inet_twsk_put(tw); |
1229 | } | 1093 | } |
1230 | 1094 | ||
1231 | static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req) | 1095 | static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req) |
@@ -1237,28 +1101,25 @@ static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req) | |||
1237 | static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb) | 1101 | static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb) |
1238 | { | 1102 | { |
1239 | struct request_sock *req, **prev; | 1103 | struct request_sock *req, **prev; |
1240 | struct tcphdr *th = skb->h.th; | 1104 | const struct tcphdr *th = skb->h.th; |
1241 | struct tcp_sock *tp = tcp_sk(sk); | ||
1242 | struct sock *nsk; | 1105 | struct sock *nsk; |
1243 | 1106 | ||
1244 | /* Find possible connection requests. */ | 1107 | /* Find possible connection requests. */ |
1245 | req = tcp_v6_search_req(tp, &prev, th->source, &skb->nh.ipv6h->saddr, | 1108 | req = tcp_v6_search_req(sk, &prev, th->source, &skb->nh.ipv6h->saddr, |
1246 | &skb->nh.ipv6h->daddr, tcp_v6_iif(skb)); | 1109 | &skb->nh.ipv6h->daddr, inet6_iif(skb)); |
1247 | if (req) | 1110 | if (req) |
1248 | return tcp_check_req(sk, skb, req, prev); | 1111 | return tcp_check_req(sk, skb, req, prev); |
1249 | 1112 | ||
1250 | nsk = __tcp_v6_lookup_established(&skb->nh.ipv6h->saddr, | 1113 | nsk = __inet6_lookup_established(&tcp_hashinfo, &skb->nh.ipv6h->saddr, |
1251 | th->source, | 1114 | th->source, &skb->nh.ipv6h->daddr, |
1252 | &skb->nh.ipv6h->daddr, | 1115 | ntohs(th->dest), inet6_iif(skb)); |
1253 | ntohs(th->dest), | ||
1254 | tcp_v6_iif(skb)); | ||
1255 | 1116 | ||
1256 | if (nsk) { | 1117 | if (nsk) { |
1257 | if (nsk->sk_state != TCP_TIME_WAIT) { | 1118 | if (nsk->sk_state != TCP_TIME_WAIT) { |
1258 | bh_lock_sock(nsk); | 1119 | bh_lock_sock(nsk); |
1259 | return nsk; | 1120 | return nsk; |
1260 | } | 1121 | } |
1261 | tcp_tw_put((struct tcp_tw_bucket*)nsk); | 1122 | inet_twsk_put((struct inet_timewait_sock *)nsk); |
1262 | return NULL; | 1123 | return NULL; |
1263 | } | 1124 | } |
1264 | 1125 | ||
@@ -1271,12 +1132,12 @@ static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb) | |||
1271 | 1132 | ||
1272 | static void tcp_v6_synq_add(struct sock *sk, struct request_sock *req) | 1133 | static void tcp_v6_synq_add(struct sock *sk, struct request_sock *req) |
1273 | { | 1134 | { |
1274 | struct tcp_sock *tp = tcp_sk(sk); | 1135 | struct inet_connection_sock *icsk = inet_csk(sk); |
1275 | struct listen_sock *lopt = tp->accept_queue.listen_opt; | 1136 | struct listen_sock *lopt = icsk->icsk_accept_queue.listen_opt; |
1276 | u32 h = tcp_v6_synq_hash(&tcp6_rsk(req)->rmt_addr, inet_rsk(req)->rmt_port, lopt->hash_rnd); | 1137 | const u32 h = tcp_v6_synq_hash(&tcp6_rsk(req)->rmt_addr, inet_rsk(req)->rmt_port, lopt->hash_rnd); |
1277 | 1138 | ||
1278 | reqsk_queue_hash_req(&tp->accept_queue, h, req, TCP_TIMEOUT_INIT); | 1139 | reqsk_queue_hash_req(&icsk->icsk_accept_queue, h, req, TCP_TIMEOUT_INIT); |
1279 | tcp_synq_added(sk); | 1140 | inet_csk_reqsk_queue_added(sk, TCP_TIMEOUT_INIT); |
1280 | } | 1141 | } |
1281 | 1142 | ||
1282 | 1143 | ||
@@ -1301,13 +1162,13 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1301 | /* | 1162 | /* |
1302 | * There are no SYN attacks on IPv6, yet... | 1163 | * There are no SYN attacks on IPv6, yet... |
1303 | */ | 1164 | */ |
1304 | if (tcp_synq_is_full(sk) && !isn) { | 1165 | if (inet_csk_reqsk_queue_is_full(sk) && !isn) { |
1305 | if (net_ratelimit()) | 1166 | if (net_ratelimit()) |
1306 | printk(KERN_INFO "TCPv6: dropping request, synflood is possible\n"); | 1167 | printk(KERN_INFO "TCPv6: dropping request, synflood is possible\n"); |
1307 | goto drop; | 1168 | goto drop; |
1308 | } | 1169 | } |
1309 | 1170 | ||
1310 | if (sk_acceptq_is_full(sk) && tcp_synq_young(sk) > 1) | 1171 | if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) |
1311 | goto drop; | 1172 | goto drop; |
1312 | 1173 | ||
1313 | req = reqsk_alloc(&tcp6_request_sock_ops); | 1174 | req = reqsk_alloc(&tcp6_request_sock_ops); |
@@ -1339,7 +1200,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1339 | /* So that link locals have meaning */ | 1200 | /* So that link locals have meaning */ |
1340 | if (!sk->sk_bound_dev_if && | 1201 | if (!sk->sk_bound_dev_if && |
1341 | ipv6_addr_type(&treq->rmt_addr) & IPV6_ADDR_LINKLOCAL) | 1202 | ipv6_addr_type(&treq->rmt_addr) & IPV6_ADDR_LINKLOCAL) |
1342 | treq->iif = tcp_v6_iif(skb); | 1203 | treq->iif = inet6_iif(skb); |
1343 | 1204 | ||
1344 | if (isn == 0) | 1205 | if (isn == 0) |
1345 | isn = tcp_v6_init_sequence(sk,skb); | 1206 | isn = tcp_v6_init_sequence(sk,skb); |
@@ -1404,15 +1265,14 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1404 | newsk->sk_backlog_rcv = tcp_v4_do_rcv; | 1265 | newsk->sk_backlog_rcv = tcp_v4_do_rcv; |
1405 | newnp->pktoptions = NULL; | 1266 | newnp->pktoptions = NULL; |
1406 | newnp->opt = NULL; | 1267 | newnp->opt = NULL; |
1407 | newnp->mcast_oif = tcp_v6_iif(skb); | 1268 | newnp->mcast_oif = inet6_iif(skb); |
1408 | newnp->mcast_hops = skb->nh.ipv6h->hop_limit; | 1269 | newnp->mcast_hops = skb->nh.ipv6h->hop_limit; |
1409 | 1270 | ||
1410 | /* Charge newly allocated IPv6 socket. Though it is mapped, | 1271 | /* |
1411 | * it is IPv6 yet. | 1272 | * No need to charge this sock to the relevant IPv6 refcnt debug socks count |
1273 | * here, tcp_create_openreq_child now does this for us, see the comment in | ||
1274 | * that function for the gory details. -acme | ||
1412 | */ | 1275 | */ |
1413 | #ifdef INET_REFCNT_DEBUG | ||
1414 | atomic_inc(&inet6_sock_nr); | ||
1415 | #endif | ||
1416 | 1276 | ||
1417 | /* It is tricky place. Until this moment IPv4 tcp | 1277 | /* It is tricky place. Until this moment IPv4 tcp |
1418 | worked with IPv6 af_tcp.af_specific. | 1278 | worked with IPv6 af_tcp.af_specific. |
@@ -1467,10 +1327,11 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1467 | if (newsk == NULL) | 1327 | if (newsk == NULL) |
1468 | goto out; | 1328 | goto out; |
1469 | 1329 | ||
1470 | /* Charge newly allocated IPv6 socket */ | 1330 | /* |
1471 | #ifdef INET_REFCNT_DEBUG | 1331 | * No need to charge this sock to the relevant IPv6 refcnt debug socks |
1472 | atomic_inc(&inet6_sock_nr); | 1332 | * count here, tcp_create_openreq_child now does this for us, see the |
1473 | #endif | 1333 | * comment in that function for the gory details. -acme |
1334 | */ | ||
1474 | 1335 | ||
1475 | ip6_dst_store(newsk, dst, NULL); | 1336 | ip6_dst_store(newsk, dst, NULL); |
1476 | newsk->sk_route_caps = dst->dev->features & | 1337 | newsk->sk_route_caps = dst->dev->features & |
@@ -1509,7 +1370,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1509 | skb_set_owner_r(newnp->pktoptions, newsk); | 1370 | skb_set_owner_r(newnp->pktoptions, newsk); |
1510 | } | 1371 | } |
1511 | newnp->opt = NULL; | 1372 | newnp->opt = NULL; |
1512 | newnp->mcast_oif = tcp_v6_iif(skb); | 1373 | newnp->mcast_oif = inet6_iif(skb); |
1513 | newnp->mcast_hops = skb->nh.ipv6h->hop_limit; | 1374 | newnp->mcast_hops = skb->nh.ipv6h->hop_limit; |
1514 | 1375 | ||
1515 | /* Clone native IPv6 options from listening socket (if any) | 1376 | /* Clone native IPv6 options from listening socket (if any) |
@@ -1536,7 +1397,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1536 | newinet->daddr = newinet->saddr = newinet->rcv_saddr = LOOPBACK4_IPV6; | 1397 | newinet->daddr = newinet->saddr = newinet->rcv_saddr = LOOPBACK4_IPV6; |
1537 | 1398 | ||
1538 | __tcp_v6_hash(newsk); | 1399 | __tcp_v6_hash(newsk); |
1539 | tcp_inherit_port(sk, newsk); | 1400 | inet_inherit_port(&tcp_hashinfo, sk, newsk); |
1540 | 1401 | ||
1541 | return newsk; | 1402 | return newsk; |
1542 | 1403 | ||
@@ -1557,7 +1418,7 @@ static int tcp_v6_checksum_init(struct sk_buff *skb) | |||
1557 | if (!tcp_v6_check(skb->h.th,skb->len,&skb->nh.ipv6h->saddr, | 1418 | if (!tcp_v6_check(skb->h.th,skb->len,&skb->nh.ipv6h->saddr, |
1558 | &skb->nh.ipv6h->daddr,skb->csum)) | 1419 | &skb->nh.ipv6h->daddr,skb->csum)) |
1559 | return 0; | 1420 | return 0; |
1560 | LIMIT_NETDEBUG(printk(KERN_DEBUG "hw tcp v6 csum failed\n")); | 1421 | LIMIT_NETDEBUG(KERN_DEBUG "hw tcp v6 csum failed\n"); |
1561 | } | 1422 | } |
1562 | if (skb->len <= 76) { | 1423 | if (skb->len <= 76) { |
1563 | if (tcp_v6_check(skb->h.th,skb->len,&skb->nh.ipv6h->saddr, | 1424 | if (tcp_v6_check(skb->h.th,skb->len,&skb->nh.ipv6h->saddr, |
@@ -1684,7 +1545,7 @@ ipv6_pktoptions: | |||
1684 | if (TCP_SKB_CB(opt_skb)->end_seq == tp->rcv_nxt && | 1545 | if (TCP_SKB_CB(opt_skb)->end_seq == tp->rcv_nxt && |
1685 | !((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN))) { | 1546 | !((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN))) { |
1686 | if (np->rxopt.bits.rxinfo) | 1547 | if (np->rxopt.bits.rxinfo) |
1687 | np->mcast_oif = tcp_v6_iif(opt_skb); | 1548 | np->mcast_oif = inet6_iif(opt_skb); |
1688 | if (np->rxopt.bits.rxhlim) | 1549 | if (np->rxopt.bits.rxhlim) |
1689 | np->mcast_hops = opt_skb->nh.ipv6h->hop_limit; | 1550 | np->mcast_hops = opt_skb->nh.ipv6h->hop_limit; |
1690 | if (ipv6_opt_accepted(sk, opt_skb)) { | 1551 | if (ipv6_opt_accepted(sk, opt_skb)) { |
@@ -1739,8 +1600,9 @@ static int tcp_v6_rcv(struct sk_buff **pskb, unsigned int *nhoffp) | |||
1739 | TCP_SKB_CB(skb)->flags = ipv6_get_dsfield(skb->nh.ipv6h); | 1600 | TCP_SKB_CB(skb)->flags = ipv6_get_dsfield(skb->nh.ipv6h); |
1740 | TCP_SKB_CB(skb)->sacked = 0; | 1601 | TCP_SKB_CB(skb)->sacked = 0; |
1741 | 1602 | ||
1742 | sk = __tcp_v6_lookup(&skb->nh.ipv6h->saddr, th->source, | 1603 | sk = __inet6_lookup(&tcp_hashinfo, &skb->nh.ipv6h->saddr, th->source, |
1743 | &skb->nh.ipv6h->daddr, ntohs(th->dest), tcp_v6_iif(skb)); | 1604 | &skb->nh.ipv6h->daddr, ntohs(th->dest), |
1605 | inet6_iif(skb)); | ||
1744 | 1606 | ||
1745 | if (!sk) | 1607 | if (!sk) |
1746 | goto no_tcp_socket; | 1608 | goto no_tcp_socket; |
@@ -1795,26 +1657,29 @@ discard_and_relse: | |||
1795 | 1657 | ||
1796 | do_time_wait: | 1658 | do_time_wait: |
1797 | if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) { | 1659 | if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) { |
1798 | tcp_tw_put((struct tcp_tw_bucket *) sk); | 1660 | inet_twsk_put((struct inet_timewait_sock *)sk); |
1799 | goto discard_it; | 1661 | goto discard_it; |
1800 | } | 1662 | } |
1801 | 1663 | ||
1802 | if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) { | 1664 | if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) { |
1803 | TCP_INC_STATS_BH(TCP_MIB_INERRS); | 1665 | TCP_INC_STATS_BH(TCP_MIB_INERRS); |
1804 | tcp_tw_put((struct tcp_tw_bucket *) sk); | 1666 | inet_twsk_put((struct inet_timewait_sock *)sk); |
1805 | goto discard_it; | 1667 | goto discard_it; |
1806 | } | 1668 | } |
1807 | 1669 | ||
1808 | switch(tcp_timewait_state_process((struct tcp_tw_bucket *)sk, | 1670 | switch (tcp_timewait_state_process((struct inet_timewait_sock *)sk, |
1809 | skb, th, skb->len)) { | 1671 | skb, th)) { |
1810 | case TCP_TW_SYN: | 1672 | case TCP_TW_SYN: |
1811 | { | 1673 | { |
1812 | struct sock *sk2; | 1674 | struct sock *sk2; |
1813 | 1675 | ||
1814 | sk2 = tcp_v6_lookup_listener(&skb->nh.ipv6h->daddr, ntohs(th->dest), tcp_v6_iif(skb)); | 1676 | sk2 = inet6_lookup_listener(&tcp_hashinfo, |
1677 | &skb->nh.ipv6h->daddr, | ||
1678 | ntohs(th->dest), inet6_iif(skb)); | ||
1815 | if (sk2 != NULL) { | 1679 | if (sk2 != NULL) { |
1816 | tcp_tw_deschedule((struct tcp_tw_bucket *)sk); | 1680 | struct inet_timewait_sock *tw = inet_twsk(sk); |
1817 | tcp_tw_put((struct tcp_tw_bucket *)sk); | 1681 | inet_twsk_deschedule(tw, &tcp_death_row); |
1682 | inet_twsk_put(tw); | ||
1818 | sk = sk2; | 1683 | sk = sk2; |
1819 | goto process; | 1684 | goto process; |
1820 | } | 1685 | } |
@@ -1983,7 +1848,7 @@ static struct tcp_func ipv6_specific = { | |||
1983 | static struct tcp_func ipv6_mapped = { | 1848 | static struct tcp_func ipv6_mapped = { |
1984 | .queue_xmit = ip_queue_xmit, | 1849 | .queue_xmit = ip_queue_xmit, |
1985 | .send_check = tcp_v4_send_check, | 1850 | .send_check = tcp_v4_send_check, |
1986 | .rebuild_header = tcp_v4_rebuild_header, | 1851 | .rebuild_header = inet_sk_rebuild_header, |
1987 | .conn_request = tcp_v6_conn_request, | 1852 | .conn_request = tcp_v6_conn_request, |
1988 | .syn_recv_sock = tcp_v6_syn_recv_sock, | 1853 | .syn_recv_sock = tcp_v6_syn_recv_sock, |
1989 | .remember_stamp = tcp_v4_remember_stamp, | 1854 | .remember_stamp = tcp_v4_remember_stamp, |
@@ -2002,13 +1867,14 @@ static struct tcp_func ipv6_mapped = { | |||
2002 | */ | 1867 | */ |
2003 | static int tcp_v6_init_sock(struct sock *sk) | 1868 | static int tcp_v6_init_sock(struct sock *sk) |
2004 | { | 1869 | { |
1870 | struct inet_connection_sock *icsk = inet_csk(sk); | ||
2005 | struct tcp_sock *tp = tcp_sk(sk); | 1871 | struct tcp_sock *tp = tcp_sk(sk); |
2006 | 1872 | ||
2007 | skb_queue_head_init(&tp->out_of_order_queue); | 1873 | skb_queue_head_init(&tp->out_of_order_queue); |
2008 | tcp_init_xmit_timers(sk); | 1874 | tcp_init_xmit_timers(sk); |
2009 | tcp_prequeue_init(tp); | 1875 | tcp_prequeue_init(tp); |
2010 | 1876 | ||
2011 | tp->rto = TCP_TIMEOUT_INIT; | 1877 | icsk->icsk_rto = TCP_TIMEOUT_INIT; |
2012 | tp->mdev = TCP_TIMEOUT_INIT; | 1878 | tp->mdev = TCP_TIMEOUT_INIT; |
2013 | 1879 | ||
2014 | /* So many TCP implementations out there (incorrectly) count the | 1880 | /* So many TCP implementations out there (incorrectly) count the |
@@ -2030,7 +1896,7 @@ static int tcp_v6_init_sock(struct sock *sk) | |||
2030 | sk->sk_state = TCP_CLOSE; | 1896 | sk->sk_state = TCP_CLOSE; |
2031 | 1897 | ||
2032 | tp->af_specific = &ipv6_specific; | 1898 | tp->af_specific = &ipv6_specific; |
2033 | tp->ca_ops = &tcp_init_congestion_ops; | 1899 | icsk->icsk_ca_ops = &tcp_init_congestion_ops; |
2034 | sk->sk_write_space = sk_stream_write_space; | 1900 | sk->sk_write_space = sk_stream_write_space; |
2035 | sock_set_flag(sk, SOCK_USE_WRITE_QUEUE); | 1901 | sock_set_flag(sk, SOCK_USE_WRITE_QUEUE); |
2036 | 1902 | ||
@@ -2044,8 +1910,6 @@ static int tcp_v6_init_sock(struct sock *sk) | |||
2044 | 1910 | ||
2045 | static int tcp_v6_destroy_sock(struct sock *sk) | 1911 | static int tcp_v6_destroy_sock(struct sock *sk) |
2046 | { | 1912 | { |
2047 | extern int tcp_v4_destroy_sock(struct sock *sk); | ||
2048 | |||
2049 | tcp_v4_destroy_sock(sk); | 1913 | tcp_v4_destroy_sock(sk); |
2050 | return inet6_destroy_sock(sk); | 1914 | return inet6_destroy_sock(sk); |
2051 | } | 1915 | } |
@@ -2091,18 +1955,20 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i) | |||
2091 | unsigned long timer_expires; | 1955 | unsigned long timer_expires; |
2092 | struct inet_sock *inet = inet_sk(sp); | 1956 | struct inet_sock *inet = inet_sk(sp); |
2093 | struct tcp_sock *tp = tcp_sk(sp); | 1957 | struct tcp_sock *tp = tcp_sk(sp); |
1958 | const struct inet_connection_sock *icsk = inet_csk(sp); | ||
2094 | struct ipv6_pinfo *np = inet6_sk(sp); | 1959 | struct ipv6_pinfo *np = inet6_sk(sp); |
2095 | 1960 | ||
2096 | dest = &np->daddr; | 1961 | dest = &np->daddr; |
2097 | src = &np->rcv_saddr; | 1962 | src = &np->rcv_saddr; |
2098 | destp = ntohs(inet->dport); | 1963 | destp = ntohs(inet->dport); |
2099 | srcp = ntohs(inet->sport); | 1964 | srcp = ntohs(inet->sport); |
2100 | if (tp->pending == TCP_TIME_RETRANS) { | 1965 | |
1966 | if (icsk->icsk_pending == ICSK_TIME_RETRANS) { | ||
2101 | timer_active = 1; | 1967 | timer_active = 1; |
2102 | timer_expires = tp->timeout; | 1968 | timer_expires = icsk->icsk_timeout; |
2103 | } else if (tp->pending == TCP_TIME_PROBE0) { | 1969 | } else if (icsk->icsk_pending == ICSK_TIME_PROBE0) { |
2104 | timer_active = 4; | 1970 | timer_active = 4; |
2105 | timer_expires = tp->timeout; | 1971 | timer_expires = icsk->icsk_timeout; |
2106 | } else if (timer_pending(&sp->sk_timer)) { | 1972 | } else if (timer_pending(&sp->sk_timer)) { |
2107 | timer_active = 2; | 1973 | timer_active = 2; |
2108 | timer_expires = sp->sk_timer.expires; | 1974 | timer_expires = sp->sk_timer.expires; |
@@ -2123,28 +1989,31 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i) | |||
2123 | tp->write_seq-tp->snd_una, tp->rcv_nxt-tp->copied_seq, | 1989 | tp->write_seq-tp->snd_una, tp->rcv_nxt-tp->copied_seq, |
2124 | timer_active, | 1990 | timer_active, |
2125 | jiffies_to_clock_t(timer_expires - jiffies), | 1991 | jiffies_to_clock_t(timer_expires - jiffies), |
2126 | tp->retransmits, | 1992 | icsk->icsk_retransmits, |
2127 | sock_i_uid(sp), | 1993 | sock_i_uid(sp), |
2128 | tp->probes_out, | 1994 | icsk->icsk_probes_out, |
2129 | sock_i_ino(sp), | 1995 | sock_i_ino(sp), |
2130 | atomic_read(&sp->sk_refcnt), sp, | 1996 | atomic_read(&sp->sk_refcnt), sp, |
2131 | tp->rto, tp->ack.ato, (tp->ack.quick<<1)|tp->ack.pingpong, | 1997 | icsk->icsk_rto, |
1998 | icsk->icsk_ack.ato, | ||
1999 | (icsk->icsk_ack.quick << 1 ) | icsk->icsk_ack.pingpong, | ||
2132 | tp->snd_cwnd, tp->snd_ssthresh>=0xFFFF?-1:tp->snd_ssthresh | 2000 | tp->snd_cwnd, tp->snd_ssthresh>=0xFFFF?-1:tp->snd_ssthresh |
2133 | ); | 2001 | ); |
2134 | } | 2002 | } |
2135 | 2003 | ||
2136 | static void get_timewait6_sock(struct seq_file *seq, | 2004 | static void get_timewait6_sock(struct seq_file *seq, |
2137 | struct tcp_tw_bucket *tw, int i) | 2005 | struct inet_timewait_sock *tw, int i) |
2138 | { | 2006 | { |
2139 | struct in6_addr *dest, *src; | 2007 | struct in6_addr *dest, *src; |
2140 | __u16 destp, srcp; | 2008 | __u16 destp, srcp; |
2009 | struct tcp6_timewait_sock *tcp6tw = tcp6_twsk((struct sock *)tw); | ||
2141 | int ttd = tw->tw_ttd - jiffies; | 2010 | int ttd = tw->tw_ttd - jiffies; |
2142 | 2011 | ||
2143 | if (ttd < 0) | 2012 | if (ttd < 0) |
2144 | ttd = 0; | 2013 | ttd = 0; |
2145 | 2014 | ||
2146 | dest = &tw->tw_v6_daddr; | 2015 | dest = &tcp6tw->tw_v6_daddr; |
2147 | src = &tw->tw_v6_rcv_saddr; | 2016 | src = &tcp6tw->tw_v6_rcv_saddr; |
2148 | destp = ntohs(tw->tw_dport); | 2017 | destp = ntohs(tw->tw_dport); |
2149 | srcp = ntohs(tw->tw_sport); | 2018 | srcp = ntohs(tw->tw_sport); |
2150 | 2019 | ||
@@ -2219,7 +2088,7 @@ struct proto tcpv6_prot = { | |||
2219 | .close = tcp_close, | 2088 | .close = tcp_close, |
2220 | .connect = tcp_v6_connect, | 2089 | .connect = tcp_v6_connect, |
2221 | .disconnect = tcp_disconnect, | 2090 | .disconnect = tcp_disconnect, |
2222 | .accept = tcp_accept, | 2091 | .accept = inet_csk_accept, |
2223 | .ioctl = tcp_ioctl, | 2092 | .ioctl = tcp_ioctl, |
2224 | .init = tcp_v6_init_sock, | 2093 | .init = tcp_v6_init_sock, |
2225 | .destroy = tcp_v6_destroy_sock, | 2094 | .destroy = tcp_v6_destroy_sock, |
@@ -2236,11 +2105,13 @@ struct proto tcpv6_prot = { | |||
2236 | .sockets_allocated = &tcp_sockets_allocated, | 2105 | .sockets_allocated = &tcp_sockets_allocated, |
2237 | .memory_allocated = &tcp_memory_allocated, | 2106 | .memory_allocated = &tcp_memory_allocated, |
2238 | .memory_pressure = &tcp_memory_pressure, | 2107 | .memory_pressure = &tcp_memory_pressure, |
2108 | .orphan_count = &tcp_orphan_count, | ||
2239 | .sysctl_mem = sysctl_tcp_mem, | 2109 | .sysctl_mem = sysctl_tcp_mem, |
2240 | .sysctl_wmem = sysctl_tcp_wmem, | 2110 | .sysctl_wmem = sysctl_tcp_wmem, |
2241 | .sysctl_rmem = sysctl_tcp_rmem, | 2111 | .sysctl_rmem = sysctl_tcp_rmem, |
2242 | .max_header = MAX_TCP_HEADER, | 2112 | .max_header = MAX_TCP_HEADER, |
2243 | .obj_size = sizeof(struct tcp6_sock), | 2113 | .obj_size = sizeof(struct tcp6_sock), |
2114 | .twsk_obj_size = sizeof(struct tcp6_timewait_sock), | ||
2244 | .rsk_prot = &tcp6_request_sock_ops, | 2115 | .rsk_prot = &tcp6_request_sock_ops, |
2245 | }; | 2116 | }; |
2246 | 2117 | ||
@@ -2250,8 +2121,6 @@ static struct inet6_protocol tcpv6_protocol = { | |||
2250 | .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, | 2121 | .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, |
2251 | }; | 2122 | }; |
2252 | 2123 | ||
2253 | extern struct proto_ops inet6_stream_ops; | ||
2254 | |||
2255 | static struct inet_protosw tcpv6_protosw = { | 2124 | static struct inet_protosw tcpv6_protosw = { |
2256 | .type = SOCK_STREAM, | 2125 | .type = SOCK_STREAM, |
2257 | .protocol = IPPROTO_TCP, | 2126 | .protocol = IPPROTO_TCP, |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index eff050ac7049..390d750449ce 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -51,6 +51,7 @@ | |||
51 | #include <net/udp.h> | 51 | #include <net/udp.h> |
52 | #include <net/raw.h> | 52 | #include <net/raw.h> |
53 | #include <net/inet_common.h> | 53 | #include <net/inet_common.h> |
54 | #include <net/tcp_states.h> | ||
54 | 55 | ||
55 | #include <net/ip6_checksum.h> | 56 | #include <net/ip6_checksum.h> |
56 | #include <net/xfrm.h> | 57 | #include <net/xfrm.h> |
@@ -58,7 +59,7 @@ | |||
58 | #include <linux/proc_fs.h> | 59 | #include <linux/proc_fs.h> |
59 | #include <linux/seq_file.h> | 60 | #include <linux/seq_file.h> |
60 | 61 | ||
61 | DEFINE_SNMP_STAT(struct udp_mib, udp_stats_in6); | 62 | DEFINE_SNMP_STAT(struct udp_mib, udp_stats_in6) __read_mostly; |
62 | 63 | ||
63 | /* Grrr, addr_type already calculated by caller, but I don't want | 64 | /* Grrr, addr_type already calculated by caller, but I don't want |
64 | * to add some silly "cookie" argument to this method just for that. | 65 | * to add some silly "cookie" argument to this method just for that. |
@@ -477,8 +478,7 @@ static int udpv6_rcv(struct sk_buff **pskb, unsigned int *nhoffp) | |||
477 | /* RFC 2460 section 8.1 says that we SHOULD log | 478 | /* RFC 2460 section 8.1 says that we SHOULD log |
478 | this error. Well, it is reasonable. | 479 | this error. Well, it is reasonable. |
479 | */ | 480 | */ |
480 | LIMIT_NETDEBUG( | 481 | LIMIT_NETDEBUG(KERN_INFO "IPv6: udp checksum is 0\n"); |
481 | printk(KERN_INFO "IPv6: udp checksum is 0\n")); | ||
482 | goto discard; | 482 | goto discard; |
483 | } | 483 | } |
484 | 484 | ||
@@ -493,7 +493,7 @@ static int udpv6_rcv(struct sk_buff **pskb, unsigned int *nhoffp) | |||
493 | if (skb->ip_summed==CHECKSUM_HW) { | 493 | if (skb->ip_summed==CHECKSUM_HW) { |
494 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 494 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
495 | if (csum_ipv6_magic(saddr, daddr, ulen, IPPROTO_UDP, skb->csum)) { | 495 | if (csum_ipv6_magic(saddr, daddr, ulen, IPPROTO_UDP, skb->csum)) { |
496 | LIMIT_NETDEBUG(printk(KERN_DEBUG "udp v6 hw csum failure.\n")); | 496 | LIMIT_NETDEBUG(KERN_DEBUG "udp v6 hw csum failure.\n"); |
497 | skb->ip_summed = CHECKSUM_NONE; | 497 | skb->ip_summed = CHECKSUM_NONE; |
498 | } | 498 | } |
499 | } | 499 | } |
@@ -825,7 +825,7 @@ back_from_confirm: | |||
825 | /* ... which is an evident application bug. --ANK */ | 825 | /* ... which is an evident application bug. --ANK */ |
826 | release_sock(sk); | 826 | release_sock(sk); |
827 | 827 | ||
828 | LIMIT_NETDEBUG(printk(KERN_DEBUG "udp cork app bug 2\n")); | 828 | LIMIT_NETDEBUG(KERN_DEBUG "udp cork app bug 2\n"); |
829 | err = -EINVAL; | 829 | err = -EINVAL; |
830 | goto out; | 830 | goto out; |
831 | } | 831 | } |
@@ -1054,8 +1054,6 @@ struct proto udpv6_prot = { | |||
1054 | .obj_size = sizeof(struct udp6_sock), | 1054 | .obj_size = sizeof(struct udp6_sock), |
1055 | }; | 1055 | }; |
1056 | 1056 | ||
1057 | extern struct proto_ops inet6_dgram_ops; | ||
1058 | |||
1059 | static struct inet_protosw udpv6_protosw = { | 1057 | static struct inet_protosw udpv6_protosw = { |
1060 | .type = SOCK_DGRAM, | 1058 | .type = SOCK_DGRAM, |
1061 | .protocol = IPPROTO_UDP, | 1059 | .protocol = IPPROTO_UDP, |
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c index 60c26c87277e..fbef7826a74f 100644 --- a/net/ipv6/xfrm6_tunnel.c +++ b/net/ipv6/xfrm6_tunnel.c | |||
@@ -79,7 +79,7 @@ static u32 xfrm6_tunnel_spi; | |||
79 | #define XFRM6_TUNNEL_SPI_MIN 1 | 79 | #define XFRM6_TUNNEL_SPI_MIN 1 |
80 | #define XFRM6_TUNNEL_SPI_MAX 0xffffffff | 80 | #define XFRM6_TUNNEL_SPI_MAX 0xffffffff |
81 | 81 | ||
82 | static kmem_cache_t *xfrm6_tunnel_spi_kmem; | 82 | static kmem_cache_t *xfrm6_tunnel_spi_kmem __read_mostly; |
83 | 83 | ||
84 | #define XFRM6_TUNNEL_SPI_BYADDR_HSIZE 256 | 84 | #define XFRM6_TUNNEL_SPI_BYADDR_HSIZE 256 |
85 | #define XFRM6_TUNNEL_SPI_BYSPI_HSIZE 256 | 85 | #define XFRM6_TUNNEL_SPI_BYSPI_HSIZE 256 |