diff options
author | Jeff Garzik <jgarzik@pobox.com> | 2005-10-06 05:51:07 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-10-06 05:51:07 -0400 |
commit | 012e060c95e547eceea4a12c6f58592473bf4011 (patch) | |
tree | b57d3eafb50ce517577d2cf366c9ef0b4b286589 /net/ipv6 | |
parent | 923f122573851d18a3832ca808269fa2d5046fb1 (diff) | |
parent | ed39f731ab2e77e58122232f6e27333331d7793d (diff) |
Merge branch 'master'
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/addrconf.c | 4 | ||||
-rw-r--r-- | net/ipv6/ip6_output.c | 2 | ||||
-rw-r--r-- | net/ipv6/mcast.c | 2 | ||||
-rw-r--r-- | net/ipv6/netfilter/Kconfig | 11 | ||||
-rw-r--r-- | net/ipv6/netfilter/Makefile | 2 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6_queue.c | 4 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6_tables.c | 52 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6t_ah.c | 81 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6t_dst.c | 88 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6t_esp.c | 73 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6t_frag.c | 90 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6t_hbh.c | 88 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6t_rt.c | 83 | ||||
-rw-r--r-- | net/ipv6/raw.c | 2 | ||||
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 18 | ||||
-rw-r--r-- | net/ipv6/udp.c | 27 |
16 files changed, 140 insertions, 487 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 2fea3f4402a0..a970b4727ce8 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -1806,7 +1806,7 @@ static void sit_add_v4_addrs(struct inet6_dev *idev) | |||
1806 | } | 1806 | } |
1807 | 1807 | ||
1808 | for (dev = dev_base; dev != NULL; dev = dev->next) { | 1808 | for (dev = dev_base; dev != NULL; dev = dev->next) { |
1809 | struct in_device * in_dev = __in_dev_get(dev); | 1809 | struct in_device * in_dev = __in_dev_get_rtnl(dev); |
1810 | if (in_dev && (dev->flags & IFF_UP)) { | 1810 | if (in_dev && (dev->flags & IFF_UP)) { |
1811 | struct in_ifaddr * ifa; | 1811 | struct in_ifaddr * ifa; |
1812 | 1812 | ||
@@ -3520,6 +3520,8 @@ int __init addrconf_init(void) | |||
3520 | if (err) | 3520 | if (err) |
3521 | return err; | 3521 | return err; |
3522 | 3522 | ||
3523 | ip6_null_entry.rt6i_idev = in6_dev_get(&loopback_dev); | ||
3524 | |||
3523 | register_netdevice_notifier(&ipv6_dev_notf); | 3525 | register_netdevice_notifier(&ipv6_dev_notf); |
3524 | 3526 | ||
3525 | #ifdef CONFIG_IPV6_PRIVACY | 3527 | #ifdef CONFIG_IPV6_PRIVACY |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 2f589f24c093..563b442ffab8 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -666,7 +666,7 @@ slow_path: | |||
666 | */ | 666 | */ |
667 | fh->nexthdr = nexthdr; | 667 | fh->nexthdr = nexthdr; |
668 | fh->reserved = 0; | 668 | fh->reserved = 0; |
669 | if (frag_id) { | 669 | if (!frag_id) { |
670 | ipv6_select_ident(skb, fh); | 670 | ipv6_select_ident(skb, fh); |
671 | frag_id = fh->identification; | 671 | frag_id = fh->identification; |
672 | } else | 672 | } else |
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 29fed6e58d0a..519899fb11d5 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c | |||
@@ -1968,7 +1968,7 @@ static void ip6_mc_clear_src(struct ifmcaddr6 *pmc) | |||
1968 | } | 1968 | } |
1969 | pmc->mca_sources = NULL; | 1969 | pmc->mca_sources = NULL; |
1970 | pmc->mca_sfmode = MCAST_EXCLUDE; | 1970 | pmc->mca_sfmode = MCAST_EXCLUDE; |
1971 | pmc->mca_sfcount[MCAST_EXCLUDE] = 0; | 1971 | pmc->mca_sfcount[MCAST_INCLUDE] = 0; |
1972 | pmc->mca_sfcount[MCAST_EXCLUDE] = 1; | 1972 | pmc->mca_sfcount[MCAST_EXCLUDE] = 1; |
1973 | } | 1973 | } |
1974 | 1974 | ||
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig index 216fbe1ac65c..bb7ccfe33f23 100644 --- a/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig | |||
@@ -209,6 +209,17 @@ config IP6_NF_TARGET_REJECT | |||
209 | 209 | ||
210 | To compile it as a module, choose M here. If unsure, say N. | 210 | To compile it as a module, choose M here. If unsure, say N. |
211 | 211 | ||
212 | config IP6_NF_TARGET_NFQUEUE | ||
213 | tristate "NFQUEUE Target Support" | ||
214 | depends on IP_NF_IPTABLES | ||
215 | help | ||
216 | This Target replaced the old obsolete QUEUE target. | ||
217 | |||
218 | As opposed to QUEUE, it supports 65535 different queues, | ||
219 | not just one. | ||
220 | |||
221 | To compile it as a module, choose M here. If unsure, say N. | ||
222 | |||
212 | # if [ "$CONFIG_IP6_NF_FILTER" != "n" ]; then | 223 | # if [ "$CONFIG_IP6_NF_FILTER" != "n" ]; then |
213 | # dep_tristate ' REJECT target support' CONFIG_IP6_NF_TARGET_REJECT $CONFIG_IP6_NF_FILTER | 224 | # dep_tristate ' REJECT target support' CONFIG_IP6_NF_TARGET_REJECT $CONFIG_IP6_NF_FILTER |
214 | # if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then | 225 | # if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then |
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile index bd9a16a5cbba..2b2c370e8b1c 100644 --- a/net/ipv6/netfilter/Makefile +++ b/net/ipv6/netfilter/Makefile | |||
@@ -21,9 +21,9 @@ 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_TARGET_HL) += ip6t_HL.o |
24 | obj-$(CONFIG_IP6_NF_TARGET_NFQUEUE) += ip6t_NFQUEUE.o | ||
24 | obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o | 25 | obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o |
25 | obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o | 26 | obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o |
26 | obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o | 27 | obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o |
27 | obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o | 28 | obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o |
28 | obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o | 29 | 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 aa11cf366efa..5027bbe6415e 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c | |||
@@ -238,8 +238,8 @@ ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp) | |||
238 | 238 | ||
239 | pmsg->packet_id = (unsigned long )entry; | 239 | pmsg->packet_id = (unsigned long )entry; |
240 | pmsg->data_len = data_len; | 240 | pmsg->data_len = data_len; |
241 | pmsg->timestamp_sec = skb_tv_base.tv_sec + entry->skb->tstamp.off_sec; | 241 | pmsg->timestamp_sec = entry->skb->tstamp.off_sec; |
242 | pmsg->timestamp_usec = skb_tv_base.tv_usec + entry->skb->tstamp.off_usec; | 242 | pmsg->timestamp_usec = entry->skb->tstamp.off_usec; |
243 | pmsg->mark = entry->skb->nfmark; | 243 | pmsg->mark = entry->skb->nfmark; |
244 | pmsg->hook = entry->info->hook; | 244 | pmsg->hook = entry->info->hook; |
245 | pmsg->hw_protocol = entry->skb->protocol; | 245 | pmsg->hw_protocol = entry->skb->protocol; |
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 1cb8adb2787f..2da514b16d95 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
@@ -1955,6 +1955,57 @@ static void __exit fini(void) | |||
1955 | #endif | 1955 | #endif |
1956 | } | 1956 | } |
1957 | 1957 | ||
1958 | /* | ||
1959 | * find specified header up to transport protocol header. | ||
1960 | * If found target header, the offset to the header is set to *offset | ||
1961 | * and return 0. otherwise, return -1. | ||
1962 | * | ||
1963 | * Notes: - non-1st Fragment Header isn't skipped. | ||
1964 | * - ESP header isn't skipped. | ||
1965 | * - The target header may be trancated. | ||
1966 | */ | ||
1967 | int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, u8 target) | ||
1968 | { | ||
1969 | unsigned int start = (u8*)(skb->nh.ipv6h + 1) - skb->data; | ||
1970 | u8 nexthdr = skb->nh.ipv6h->nexthdr; | ||
1971 | unsigned int len = skb->len - start; | ||
1972 | |||
1973 | while (nexthdr != target) { | ||
1974 | struct ipv6_opt_hdr _hdr, *hp; | ||
1975 | unsigned int hdrlen; | ||
1976 | |||
1977 | if ((!ipv6_ext_hdr(nexthdr)) || nexthdr == NEXTHDR_NONE) | ||
1978 | return -1; | ||
1979 | hp = skb_header_pointer(skb, start, sizeof(_hdr), &_hdr); | ||
1980 | if (hp == NULL) | ||
1981 | return -1; | ||
1982 | if (nexthdr == NEXTHDR_FRAGMENT) { | ||
1983 | unsigned short _frag_off, *fp; | ||
1984 | fp = skb_header_pointer(skb, | ||
1985 | start+offsetof(struct frag_hdr, | ||
1986 | frag_off), | ||
1987 | sizeof(_frag_off), | ||
1988 | &_frag_off); | ||
1989 | if (fp == NULL) | ||
1990 | return -1; | ||
1991 | |||
1992 | if (ntohs(*fp) & ~0x7) | ||
1993 | return -1; | ||
1994 | hdrlen = 8; | ||
1995 | } else if (nexthdr == NEXTHDR_AUTH) | ||
1996 | hdrlen = (hp->hdrlen + 2) << 2; | ||
1997 | else | ||
1998 | hdrlen = ipv6_optlen(hp); | ||
1999 | |||
2000 | nexthdr = hp->nexthdr; | ||
2001 | len -= hdrlen; | ||
2002 | start += hdrlen; | ||
2003 | } | ||
2004 | |||
2005 | *offset = start; | ||
2006 | return 0; | ||
2007 | } | ||
2008 | |||
1958 | EXPORT_SYMBOL(ip6t_register_table); | 2009 | EXPORT_SYMBOL(ip6t_register_table); |
1959 | EXPORT_SYMBOL(ip6t_unregister_table); | 2010 | EXPORT_SYMBOL(ip6t_unregister_table); |
1960 | EXPORT_SYMBOL(ip6t_do_table); | 2011 | EXPORT_SYMBOL(ip6t_do_table); |
@@ -1963,6 +2014,7 @@ EXPORT_SYMBOL(ip6t_unregister_match); | |||
1963 | EXPORT_SYMBOL(ip6t_register_target); | 2014 | EXPORT_SYMBOL(ip6t_register_target); |
1964 | EXPORT_SYMBOL(ip6t_unregister_target); | 2015 | EXPORT_SYMBOL(ip6t_unregister_target); |
1965 | EXPORT_SYMBOL(ip6t_ext_hdr); | 2016 | EXPORT_SYMBOL(ip6t_ext_hdr); |
2017 | EXPORT_SYMBOL(ipv6_find_hdr); | ||
1966 | 2018 | ||
1967 | module_init(init); | 2019 | module_init(init); |
1968 | module_exit(fini); | 2020 | module_exit(fini); |
diff --git a/net/ipv6/netfilter/ip6t_ah.c b/net/ipv6/netfilter/ip6t_ah.c index d5b94f142bba..dde37793d20b 100644 --- a/net/ipv6/netfilter/ip6t_ah.c +++ b/net/ipv6/netfilter/ip6t_ah.c | |||
@@ -48,92 +48,21 @@ match(const struct sk_buff *skb, | |||
48 | unsigned int protoff, | 48 | unsigned int protoff, |
49 | int *hotdrop) | 49 | int *hotdrop) |
50 | { | 50 | { |
51 | struct ip_auth_hdr *ah = NULL, _ah; | 51 | struct ip_auth_hdr *ah, _ah; |
52 | const struct ip6t_ah *ahinfo = matchinfo; | 52 | const struct ip6t_ah *ahinfo = matchinfo; |
53 | unsigned int temp; | ||
54 | int len; | ||
55 | u8 nexthdr; | ||
56 | unsigned int ptr; | 53 | unsigned int ptr; |
57 | unsigned int hdrlen = 0; | 54 | unsigned int hdrlen = 0; |
58 | 55 | ||
59 | /*DEBUGP("IPv6 AH entered\n");*/ | 56 | if (ipv6_find_hdr(skb, &ptr, NEXTHDR_AUTH) < 0) |
60 | /* if (opt->auth == 0) return 0; | ||
61 | * It does not filled on output */ | ||
62 | |||
63 | /* type of the 1st exthdr */ | ||
64 | nexthdr = skb->nh.ipv6h->nexthdr; | ||
65 | /* pointer to the 1st exthdr */ | ||
66 | ptr = sizeof(struct ipv6hdr); | ||
67 | /* available length */ | ||
68 | len = skb->len - ptr; | ||
69 | temp = 0; | ||
70 | |||
71 | while (ip6t_ext_hdr(nexthdr)) { | ||
72 | struct ipv6_opt_hdr _hdr, *hp; | ||
73 | |||
74 | DEBUGP("ipv6_ah header iteration \n"); | ||
75 | |||
76 | /* Is there enough space for the next ext header? */ | ||
77 | if (len < sizeof(struct ipv6_opt_hdr)) | ||
78 | return 0; | ||
79 | /* No more exthdr -> evaluate */ | ||
80 | if (nexthdr == NEXTHDR_NONE) | ||
81 | break; | ||
82 | /* ESP -> evaluate */ | ||
83 | if (nexthdr == NEXTHDR_ESP) | ||
84 | break; | ||
85 | |||
86 | hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr); | ||
87 | BUG_ON(hp == NULL); | ||
88 | |||
89 | /* Calculate the header length */ | ||
90 | if (nexthdr == NEXTHDR_FRAGMENT) | ||
91 | hdrlen = 8; | ||
92 | else if (nexthdr == NEXTHDR_AUTH) | ||
93 | hdrlen = (hp->hdrlen+2)<<2; | ||
94 | else | ||
95 | hdrlen = ipv6_optlen(hp); | ||
96 | |||
97 | /* AH -> evaluate */ | ||
98 | if (nexthdr == NEXTHDR_AUTH) { | ||
99 | temp |= MASK_AH; | ||
100 | break; | ||
101 | } | ||
102 | |||
103 | |||
104 | /* set the flag */ | ||
105 | switch (nexthdr) { | ||
106 | case NEXTHDR_HOP: | ||
107 | case NEXTHDR_ROUTING: | ||
108 | case NEXTHDR_FRAGMENT: | ||
109 | case NEXTHDR_AUTH: | ||
110 | case NEXTHDR_DEST: | ||
111 | break; | ||
112 | default: | ||
113 | DEBUGP("ipv6_ah match: unknown nextheader %u\n",nexthdr); | ||
114 | return 0; | ||
115 | } | ||
116 | |||
117 | nexthdr = hp->nexthdr; | ||
118 | len -= hdrlen; | ||
119 | ptr += hdrlen; | ||
120 | if (ptr > skb->len) { | ||
121 | DEBUGP("ipv6_ah: new pointer too large! \n"); | ||
122 | break; | ||
123 | } | ||
124 | } | ||
125 | |||
126 | /* AH header not found */ | ||
127 | if (temp != MASK_AH) | ||
128 | return 0; | 57 | return 0; |
129 | 58 | ||
130 | if (len < sizeof(struct ip_auth_hdr)){ | 59 | ah = skb_header_pointer(skb, ptr, sizeof(_ah), &_ah); |
60 | if (ah == NULL) { | ||
131 | *hotdrop = 1; | 61 | *hotdrop = 1; |
132 | return 0; | 62 | return 0; |
133 | } | 63 | } |
134 | 64 | ||
135 | ah = skb_header_pointer(skb, ptr, sizeof(_ah), &_ah); | 65 | hdrlen = (ah->hdrlen + 2) << 2; |
136 | BUG_ON(ah == NULL); | ||
137 | 66 | ||
138 | DEBUGP("IPv6 AH LEN %u %u ", hdrlen, ah->hdrlen); | 67 | DEBUGP("IPv6 AH LEN %u %u ", hdrlen, ah->hdrlen); |
139 | DEBUGP("RES %04X ", ah->reserved); | 68 | DEBUGP("RES %04X ", ah->reserved); |
diff --git a/net/ipv6/netfilter/ip6t_dst.c b/net/ipv6/netfilter/ip6t_dst.c index 540925e4a7a8..c450a635e54b 100644 --- a/net/ipv6/netfilter/ip6t_dst.c +++ b/net/ipv6/netfilter/ip6t_dst.c | |||
@@ -63,8 +63,6 @@ match(const struct sk_buff *skb, | |||
63 | struct ipv6_opt_hdr _optsh, *oh; | 63 | struct ipv6_opt_hdr _optsh, *oh; |
64 | const struct ip6t_opts *optinfo = matchinfo; | 64 | const struct ip6t_opts *optinfo = matchinfo; |
65 | unsigned int temp; | 65 | unsigned int temp; |
66 | unsigned int len; | ||
67 | u8 nexthdr; | ||
68 | unsigned int ptr; | 66 | unsigned int ptr; |
69 | unsigned int hdrlen = 0; | 67 | unsigned int hdrlen = 0; |
70 | unsigned int ret = 0; | 68 | unsigned int ret = 0; |
@@ -72,97 +70,25 @@ match(const struct sk_buff *skb, | |||
72 | u8 _optlen, *lp = NULL; | 70 | u8 _optlen, *lp = NULL; |
73 | unsigned int optlen; | 71 | unsigned int optlen; |
74 | 72 | ||
75 | /* type of the 1st exthdr */ | ||
76 | nexthdr = skb->nh.ipv6h->nexthdr; | ||
77 | /* pointer to the 1st exthdr */ | ||
78 | ptr = sizeof(struct ipv6hdr); | ||
79 | /* available length */ | ||
80 | len = skb->len - ptr; | ||
81 | temp = 0; | ||
82 | |||
83 | while (ip6t_ext_hdr(nexthdr)) { | ||
84 | struct ipv6_opt_hdr _hdr, *hp; | ||
85 | |||
86 | DEBUGP("ipv6_opts header iteration \n"); | ||
87 | |||
88 | /* Is there enough space for the next ext header? */ | ||
89 | if (len < (int)sizeof(struct ipv6_opt_hdr)) | ||
90 | return 0; | ||
91 | /* No more exthdr -> evaluate */ | ||
92 | if (nexthdr == NEXTHDR_NONE) { | ||
93 | break; | ||
94 | } | ||
95 | /* ESP -> evaluate */ | ||
96 | if (nexthdr == NEXTHDR_ESP) { | ||
97 | break; | ||
98 | } | ||
99 | |||
100 | hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr); | ||
101 | BUG_ON(hp == NULL); | ||
102 | |||
103 | /* Calculate the header length */ | ||
104 | if (nexthdr == NEXTHDR_FRAGMENT) { | ||
105 | hdrlen = 8; | ||
106 | } else if (nexthdr == NEXTHDR_AUTH) | ||
107 | hdrlen = (hp->hdrlen+2)<<2; | ||
108 | else | ||
109 | hdrlen = ipv6_optlen(hp); | ||
110 | |||
111 | /* OPTS -> evaluate */ | ||
112 | #if HOPBYHOP | 73 | #if HOPBYHOP |
113 | if (nexthdr == NEXTHDR_HOP) { | 74 | if (ipv6_find_hdr(skb, &ptr, NEXTHDR_HOP) < 0) |
114 | temp |= MASK_HOPOPTS; | ||
115 | #else | 75 | #else |
116 | if (nexthdr == NEXTHDR_DEST) { | 76 | if (ipv6_find_hdr(skb, &ptr, NEXTHDR_DEST) < 0) |
117 | temp |= MASK_DSTOPTS; | ||
118 | #endif | 77 | #endif |
119 | break; | 78 | return 0; |
120 | } | ||
121 | |||
122 | 79 | ||
123 | /* set the flag */ | 80 | oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh); |
124 | switch (nexthdr){ | 81 | if (oh == NULL){ |
125 | case NEXTHDR_HOP: | ||
126 | case NEXTHDR_ROUTING: | ||
127 | case NEXTHDR_FRAGMENT: | ||
128 | case NEXTHDR_AUTH: | ||
129 | case NEXTHDR_DEST: | ||
130 | break; | ||
131 | default: | ||
132 | DEBUGP("ipv6_opts match: unknown nextheader %u\n",nexthdr); | ||
133 | return 0; | ||
134 | break; | ||
135 | } | ||
136 | |||
137 | nexthdr = hp->nexthdr; | ||
138 | len -= hdrlen; | ||
139 | ptr += hdrlen; | ||
140 | if ( ptr > skb->len ) { | ||
141 | DEBUGP("ipv6_opts: new pointer is too large! \n"); | ||
142 | break; | ||
143 | } | ||
144 | } | ||
145 | |||
146 | /* OPTIONS header not found */ | ||
147 | #if HOPBYHOP | ||
148 | if ( temp != MASK_HOPOPTS ) return 0; | ||
149 | #else | ||
150 | if ( temp != MASK_DSTOPTS ) return 0; | ||
151 | #endif | ||
152 | |||
153 | if (len < (int)sizeof(struct ipv6_opt_hdr)){ | ||
154 | *hotdrop = 1; | 82 | *hotdrop = 1; |
155 | return 0; | 83 | return 0; |
156 | } | 84 | } |
157 | 85 | ||
158 | if (len < hdrlen){ | 86 | hdrlen = ipv6_optlen(oh); |
87 | if (skb->len - ptr < hdrlen){ | ||
159 | /* Packet smaller than it's length field */ | 88 | /* Packet smaller than it's length field */ |
160 | return 0; | 89 | return 0; |
161 | } | 90 | } |
162 | 91 | ||
163 | oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh); | ||
164 | BUG_ON(oh == NULL); | ||
165 | |||
166 | DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen); | 92 | DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen); |
167 | 93 | ||
168 | DEBUGP("len %02X %04X %02X ", | 94 | DEBUGP("len %02X %04X %02X ", |
diff --git a/net/ipv6/netfilter/ip6t_esp.c b/net/ipv6/netfilter/ip6t_esp.c index e39dd236fd8e..24bc0cde43a1 100644 --- a/net/ipv6/netfilter/ip6t_esp.c +++ b/net/ipv6/netfilter/ip6t_esp.c | |||
@@ -48,87 +48,22 @@ match(const struct sk_buff *skb, | |||
48 | unsigned int protoff, | 48 | unsigned int protoff, |
49 | int *hotdrop) | 49 | int *hotdrop) |
50 | { | 50 | { |
51 | struct ip_esp_hdr _esp, *eh = NULL; | 51 | struct ip_esp_hdr _esp, *eh; |
52 | const struct ip6t_esp *espinfo = matchinfo; | 52 | const struct ip6t_esp *espinfo = matchinfo; |
53 | unsigned int temp; | ||
54 | int len; | ||
55 | u8 nexthdr; | ||
56 | unsigned int ptr; | 53 | unsigned int ptr; |
57 | 54 | ||
58 | /* Make sure this isn't an evil packet */ | 55 | /* Make sure this isn't an evil packet */ |
59 | /*DEBUGP("ipv6_esp entered \n");*/ | 56 | /*DEBUGP("ipv6_esp entered \n");*/ |
60 | 57 | ||
61 | /* type of the 1st exthdr */ | 58 | if (ipv6_find_hdr(skb, &ptr, NEXTHDR_ESP) < 0) |
62 | nexthdr = skb->nh.ipv6h->nexthdr; | ||
63 | /* pointer to the 1st exthdr */ | ||
64 | ptr = sizeof(struct ipv6hdr); | ||
65 | /* available length */ | ||
66 | len = skb->len - ptr; | ||
67 | temp = 0; | ||
68 | |||
69 | while (ip6t_ext_hdr(nexthdr)) { | ||
70 | struct ipv6_opt_hdr _hdr, *hp; | ||
71 | int hdrlen; | ||
72 | |||
73 | DEBUGP("ipv6_esp header iteration \n"); | ||
74 | |||
75 | /* Is there enough space for the next ext header? */ | ||
76 | if (len < sizeof(struct ipv6_opt_hdr)) | ||
77 | return 0; | ||
78 | /* No more exthdr -> evaluate */ | ||
79 | if (nexthdr == NEXTHDR_NONE) | ||
80 | break; | ||
81 | /* ESP -> evaluate */ | ||
82 | if (nexthdr == NEXTHDR_ESP) { | ||
83 | temp |= MASK_ESP; | ||
84 | break; | ||
85 | } | ||
86 | |||
87 | hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr); | ||
88 | BUG_ON(hp == NULL); | ||
89 | |||
90 | /* Calculate the header length */ | ||
91 | if (nexthdr == NEXTHDR_FRAGMENT) | ||
92 | hdrlen = 8; | ||
93 | else if (nexthdr == NEXTHDR_AUTH) | ||
94 | hdrlen = (hp->hdrlen+2)<<2; | ||
95 | else | ||
96 | hdrlen = ipv6_optlen(hp); | ||
97 | |||
98 | /* set the flag */ | ||
99 | switch (nexthdr) { | ||
100 | case NEXTHDR_HOP: | ||
101 | case NEXTHDR_ROUTING: | ||
102 | case NEXTHDR_FRAGMENT: | ||
103 | case NEXTHDR_AUTH: | ||
104 | case NEXTHDR_DEST: | ||
105 | break; | ||
106 | default: | ||
107 | DEBUGP("ipv6_esp match: unknown nextheader %u\n",nexthdr); | ||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | nexthdr = hp->nexthdr; | ||
112 | len -= hdrlen; | ||
113 | ptr += hdrlen; | ||
114 | if (ptr > skb->len) { | ||
115 | DEBUGP("ipv6_esp: new pointer too large! \n"); | ||
116 | break; | ||
117 | } | ||
118 | } | ||
119 | |||
120 | /* ESP header not found */ | ||
121 | if (temp != MASK_ESP) | ||
122 | return 0; | 59 | return 0; |
123 | 60 | ||
124 | if (len < sizeof(struct ip_esp_hdr)) { | 61 | eh = skb_header_pointer(skb, ptr, sizeof(_esp), &_esp); |
62 | if (eh == NULL) { | ||
125 | *hotdrop = 1; | 63 | *hotdrop = 1; |
126 | return 0; | 64 | return 0; |
127 | } | 65 | } |
128 | 66 | ||
129 | eh = skb_header_pointer(skb, ptr, sizeof(_esp), &_esp); | ||
130 | BUG_ON(eh == NULL); | ||
131 | |||
132 | DEBUGP("IPv6 ESP SPI %u %08X\n", ntohl(eh->spi), ntohl(eh->spi)); | 67 | DEBUGP("IPv6 ESP SPI %u %08X\n", ntohl(eh->spi), ntohl(eh->spi)); |
133 | 68 | ||
134 | return (eh != NULL) | 69 | return (eh != NULL) |
diff --git a/net/ipv6/netfilter/ip6t_frag.c b/net/ipv6/netfilter/ip6t_frag.c index 4bfa30a9bc80..085d5f8eea29 100644 --- a/net/ipv6/netfilter/ip6t_frag.c +++ b/net/ipv6/netfilter/ip6t_frag.c | |||
@@ -48,90 +48,18 @@ match(const struct sk_buff *skb, | |||
48 | unsigned int protoff, | 48 | unsigned int protoff, |
49 | int *hotdrop) | 49 | int *hotdrop) |
50 | { | 50 | { |
51 | struct frag_hdr _frag, *fh = NULL; | 51 | struct frag_hdr _frag, *fh; |
52 | const struct ip6t_frag *fraginfo = matchinfo; | 52 | const struct ip6t_frag *fraginfo = matchinfo; |
53 | unsigned int temp; | ||
54 | int len; | ||
55 | u8 nexthdr; | ||
56 | unsigned int ptr; | 53 | unsigned int ptr; |
57 | unsigned int hdrlen = 0; | ||
58 | |||
59 | /* type of the 1st exthdr */ | ||
60 | nexthdr = skb->nh.ipv6h->nexthdr; | ||
61 | /* pointer to the 1st exthdr */ | ||
62 | ptr = sizeof(struct ipv6hdr); | ||
63 | /* available length */ | ||
64 | len = skb->len - ptr; | ||
65 | temp = 0; | ||
66 | |||
67 | while (ip6t_ext_hdr(nexthdr)) { | ||
68 | struct ipv6_opt_hdr _hdr, *hp; | ||
69 | |||
70 | DEBUGP("ipv6_frag header iteration \n"); | ||
71 | |||
72 | /* Is there enough space for the next ext header? */ | ||
73 | if (len < (int)sizeof(struct ipv6_opt_hdr)) | ||
74 | return 0; | ||
75 | /* No more exthdr -> evaluate */ | ||
76 | if (nexthdr == NEXTHDR_NONE) { | ||
77 | break; | ||
78 | } | ||
79 | /* ESP -> evaluate */ | ||
80 | if (nexthdr == NEXTHDR_ESP) { | ||
81 | break; | ||
82 | } | ||
83 | |||
84 | hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr); | ||
85 | BUG_ON(hp == NULL); | ||
86 | |||
87 | /* Calculate the header length */ | ||
88 | if (nexthdr == NEXTHDR_FRAGMENT) { | ||
89 | hdrlen = 8; | ||
90 | } else if (nexthdr == NEXTHDR_AUTH) | ||
91 | hdrlen = (hp->hdrlen+2)<<2; | ||
92 | else | ||
93 | hdrlen = ipv6_optlen(hp); | ||
94 | |||
95 | /* FRAG -> evaluate */ | ||
96 | if (nexthdr == NEXTHDR_FRAGMENT) { | ||
97 | temp |= MASK_FRAGMENT; | ||
98 | break; | ||
99 | } | ||
100 | |||
101 | |||
102 | /* set the flag */ | ||
103 | switch (nexthdr){ | ||
104 | case NEXTHDR_HOP: | ||
105 | case NEXTHDR_ROUTING: | ||
106 | case NEXTHDR_FRAGMENT: | ||
107 | case NEXTHDR_AUTH: | ||
108 | case NEXTHDR_DEST: | ||
109 | break; | ||
110 | default: | ||
111 | DEBUGP("ipv6_frag match: unknown nextheader %u\n",nexthdr); | ||
112 | return 0; | ||
113 | break; | ||
114 | } | ||
115 | |||
116 | nexthdr = hp->nexthdr; | ||
117 | len -= hdrlen; | ||
118 | ptr += hdrlen; | ||
119 | if ( ptr > skb->len ) { | ||
120 | DEBUGP("ipv6_frag: new pointer too large! \n"); | ||
121 | break; | ||
122 | } | ||
123 | } | ||
124 | |||
125 | /* FRAG header not found */ | ||
126 | if ( temp != MASK_FRAGMENT ) return 0; | ||
127 | |||
128 | if (len < sizeof(struct frag_hdr)){ | ||
129 | *hotdrop = 1; | ||
130 | return 0; | ||
131 | } | ||
132 | 54 | ||
133 | fh = skb_header_pointer(skb, ptr, sizeof(_frag), &_frag); | 55 | if (ipv6_find_hdr(skb, &ptr, NEXTHDR_FRAGMENT) < 0) |
134 | BUG_ON(fh == NULL); | 56 | return 0; |
57 | |||
58 | fh = skb_header_pointer(skb, ptr, sizeof(_frag), &_frag); | ||
59 | if (fh == NULL){ | ||
60 | *hotdrop = 1; | ||
61 | return 0; | ||
62 | } | ||
135 | 63 | ||
136 | DEBUGP("INFO %04X ", fh->frag_off); | 64 | DEBUGP("INFO %04X ", fh->frag_off); |
137 | DEBUGP("OFFSET %04X ", ntohs(fh->frag_off) & ~0x7); | 65 | DEBUGP("OFFSET %04X ", ntohs(fh->frag_off) & ~0x7); |
diff --git a/net/ipv6/netfilter/ip6t_hbh.c b/net/ipv6/netfilter/ip6t_hbh.c index 27f3650d127e..1d09485111d0 100644 --- a/net/ipv6/netfilter/ip6t_hbh.c +++ b/net/ipv6/netfilter/ip6t_hbh.c | |||
@@ -63,8 +63,6 @@ match(const struct sk_buff *skb, | |||
63 | struct ipv6_opt_hdr _optsh, *oh; | 63 | struct ipv6_opt_hdr _optsh, *oh; |
64 | const struct ip6t_opts *optinfo = matchinfo; | 64 | const struct ip6t_opts *optinfo = matchinfo; |
65 | unsigned int temp; | 65 | unsigned int temp; |
66 | unsigned int len; | ||
67 | u8 nexthdr; | ||
68 | unsigned int ptr; | 66 | unsigned int ptr; |
69 | unsigned int hdrlen = 0; | 67 | unsigned int hdrlen = 0; |
70 | unsigned int ret = 0; | 68 | unsigned int ret = 0; |
@@ -72,97 +70,25 @@ match(const struct sk_buff *skb, | |||
72 | u8 _optlen, *lp = NULL; | 70 | u8 _optlen, *lp = NULL; |
73 | unsigned int optlen; | 71 | unsigned int optlen; |
74 | 72 | ||
75 | /* type of the 1st exthdr */ | ||
76 | nexthdr = skb->nh.ipv6h->nexthdr; | ||
77 | /* pointer to the 1st exthdr */ | ||
78 | ptr = sizeof(struct ipv6hdr); | ||
79 | /* available length */ | ||
80 | len = skb->len - ptr; | ||
81 | temp = 0; | ||
82 | |||
83 | while (ip6t_ext_hdr(nexthdr)) { | ||
84 | struct ipv6_opt_hdr _hdr, *hp; | ||
85 | |||
86 | DEBUGP("ipv6_opts header iteration \n"); | ||
87 | |||
88 | /* Is there enough space for the next ext header? */ | ||
89 | if (len < (int)sizeof(struct ipv6_opt_hdr)) | ||
90 | return 0; | ||
91 | /* No more exthdr -> evaluate */ | ||
92 | if (nexthdr == NEXTHDR_NONE) { | ||
93 | break; | ||
94 | } | ||
95 | /* ESP -> evaluate */ | ||
96 | if (nexthdr == NEXTHDR_ESP) { | ||
97 | break; | ||
98 | } | ||
99 | |||
100 | hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr); | ||
101 | BUG_ON(hp == NULL); | ||
102 | |||
103 | /* Calculate the header length */ | ||
104 | if (nexthdr == NEXTHDR_FRAGMENT) { | ||
105 | hdrlen = 8; | ||
106 | } else if (nexthdr == NEXTHDR_AUTH) | ||
107 | hdrlen = (hp->hdrlen+2)<<2; | ||
108 | else | ||
109 | hdrlen = ipv6_optlen(hp); | ||
110 | |||
111 | /* OPTS -> evaluate */ | ||
112 | #if HOPBYHOP | 73 | #if HOPBYHOP |
113 | if (nexthdr == NEXTHDR_HOP) { | 74 | if (ipv6_find_hdr(skb, &ptr, NEXTHDR_HOP) < 0) |
114 | temp |= MASK_HOPOPTS; | ||
115 | #else | 75 | #else |
116 | if (nexthdr == NEXTHDR_DEST) { | 76 | if (ipv6_find_hdr(skb, &ptr, NEXTHDR_DEST) < 0) |
117 | temp |= MASK_DSTOPTS; | ||
118 | #endif | 77 | #endif |
119 | break; | 78 | return 0; |
120 | } | ||
121 | |||
122 | 79 | ||
123 | /* set the flag */ | 80 | oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh); |
124 | switch (nexthdr){ | 81 | if (oh == NULL){ |
125 | case NEXTHDR_HOP: | ||
126 | case NEXTHDR_ROUTING: | ||
127 | case NEXTHDR_FRAGMENT: | ||
128 | case NEXTHDR_AUTH: | ||
129 | case NEXTHDR_DEST: | ||
130 | break; | ||
131 | default: | ||
132 | DEBUGP("ipv6_opts match: unknown nextheader %u\n",nexthdr); | ||
133 | return 0; | ||
134 | break; | ||
135 | } | ||
136 | |||
137 | nexthdr = hp->nexthdr; | ||
138 | len -= hdrlen; | ||
139 | ptr += hdrlen; | ||
140 | if ( ptr > skb->len ) { | ||
141 | DEBUGP("ipv6_opts: new pointer is too large! \n"); | ||
142 | break; | ||
143 | } | ||
144 | } | ||
145 | |||
146 | /* OPTIONS header not found */ | ||
147 | #if HOPBYHOP | ||
148 | if ( temp != MASK_HOPOPTS ) return 0; | ||
149 | #else | ||
150 | if ( temp != MASK_DSTOPTS ) return 0; | ||
151 | #endif | ||
152 | |||
153 | if (len < (int)sizeof(struct ipv6_opt_hdr)){ | ||
154 | *hotdrop = 1; | 82 | *hotdrop = 1; |
155 | return 0; | 83 | return 0; |
156 | } | 84 | } |
157 | 85 | ||
158 | if (len < hdrlen){ | 86 | hdrlen = ipv6_optlen(oh); |
87 | if (skb->len - ptr < hdrlen){ | ||
159 | /* Packet smaller than it's length field */ | 88 | /* Packet smaller than it's length field */ |
160 | return 0; | 89 | return 0; |
161 | } | 90 | } |
162 | 91 | ||
163 | oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh); | ||
164 | BUG_ON(oh == NULL); | ||
165 | |||
166 | DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen); | 92 | DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen); |
167 | 93 | ||
168 | DEBUGP("len %02X %04X %02X ", | 94 | DEBUGP("len %02X %04X %02X ", |
diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c index 2bb670037df3..beb2fd5cebbb 100644 --- a/net/ipv6/netfilter/ip6t_rt.c +++ b/net/ipv6/netfilter/ip6t_rt.c | |||
@@ -50,98 +50,29 @@ match(const struct sk_buff *skb, | |||
50 | unsigned int protoff, | 50 | unsigned int protoff, |
51 | int *hotdrop) | 51 | int *hotdrop) |
52 | { | 52 | { |
53 | struct ipv6_rt_hdr _route, *rh = NULL; | 53 | struct ipv6_rt_hdr _route, *rh; |
54 | const struct ip6t_rt *rtinfo = matchinfo; | 54 | const struct ip6t_rt *rtinfo = matchinfo; |
55 | unsigned int temp; | 55 | unsigned int temp; |
56 | unsigned int len; | ||
57 | u8 nexthdr; | ||
58 | unsigned int ptr; | 56 | unsigned int ptr; |
59 | unsigned int hdrlen = 0; | 57 | unsigned int hdrlen = 0; |
60 | unsigned int ret = 0; | 58 | unsigned int ret = 0; |
61 | struct in6_addr *ap, _addr; | 59 | struct in6_addr *ap, _addr; |
62 | 60 | ||
63 | /* type of the 1st exthdr */ | 61 | if (ipv6_find_hdr(skb, &ptr, NEXTHDR_ROUTING) < 0) |
64 | nexthdr = skb->nh.ipv6h->nexthdr; | 62 | return 0; |
65 | /* pointer to the 1st exthdr */ | ||
66 | ptr = sizeof(struct ipv6hdr); | ||
67 | /* available length */ | ||
68 | len = skb->len - ptr; | ||
69 | temp = 0; | ||
70 | 63 | ||
71 | while (ip6t_ext_hdr(nexthdr)) { | 64 | rh = skb_header_pointer(skb, ptr, sizeof(_route), &_route); |
72 | struct ipv6_opt_hdr _hdr, *hp; | 65 | if (rh == NULL){ |
73 | |||
74 | DEBUGP("ipv6_rt header iteration \n"); | ||
75 | |||
76 | /* Is there enough space for the next ext header? */ | ||
77 | if (len < (int)sizeof(struct ipv6_opt_hdr)) | ||
78 | return 0; | ||
79 | /* No more exthdr -> evaluate */ | ||
80 | if (nexthdr == NEXTHDR_NONE) { | ||
81 | break; | ||
82 | } | ||
83 | /* ESP -> evaluate */ | ||
84 | if (nexthdr == NEXTHDR_ESP) { | ||
85 | break; | ||
86 | } | ||
87 | |||
88 | hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr); | ||
89 | BUG_ON(hp == NULL); | ||
90 | |||
91 | /* Calculate the header length */ | ||
92 | if (nexthdr == NEXTHDR_FRAGMENT) { | ||
93 | hdrlen = 8; | ||
94 | } else if (nexthdr == NEXTHDR_AUTH) | ||
95 | hdrlen = (hp->hdrlen+2)<<2; | ||
96 | else | ||
97 | hdrlen = ipv6_optlen(hp); | ||
98 | |||
99 | /* ROUTING -> evaluate */ | ||
100 | if (nexthdr == NEXTHDR_ROUTING) { | ||
101 | temp |= MASK_ROUTING; | ||
102 | break; | ||
103 | } | ||
104 | |||
105 | |||
106 | /* set the flag */ | ||
107 | switch (nexthdr){ | ||
108 | case NEXTHDR_HOP: | ||
109 | case NEXTHDR_ROUTING: | ||
110 | case NEXTHDR_FRAGMENT: | ||
111 | case NEXTHDR_AUTH: | ||
112 | case NEXTHDR_DEST: | ||
113 | break; | ||
114 | default: | ||
115 | DEBUGP("ipv6_rt match: unknown nextheader %u\n",nexthdr); | ||
116 | return 0; | ||
117 | break; | ||
118 | } | ||
119 | |||
120 | nexthdr = hp->nexthdr; | ||
121 | len -= hdrlen; | ||
122 | ptr += hdrlen; | ||
123 | if ( ptr > skb->len ) { | ||
124 | DEBUGP("ipv6_rt: new pointer is too large! \n"); | ||
125 | break; | ||
126 | } | ||
127 | } | ||
128 | |||
129 | /* ROUTING header not found */ | ||
130 | if ( temp != MASK_ROUTING ) return 0; | ||
131 | |||
132 | if (len < (int)sizeof(struct ipv6_rt_hdr)){ | ||
133 | *hotdrop = 1; | 66 | *hotdrop = 1; |
134 | return 0; | 67 | return 0; |
135 | } | 68 | } |
136 | 69 | ||
137 | if (len < hdrlen){ | 70 | hdrlen = ipv6_optlen(rh); |
71 | if (skb->len - ptr < hdrlen){ | ||
138 | /* Pcket smaller than its length field */ | 72 | /* Pcket smaller than its length field */ |
139 | return 0; | 73 | return 0; |
140 | } | 74 | } |
141 | 75 | ||
142 | rh = skb_header_pointer(skb, ptr, sizeof(_route), &_route); | ||
143 | BUG_ON(rh == NULL); | ||
144 | |||
145 | DEBUGP("IPv6 RT LEN %u %u ", hdrlen, rh->hdrlen); | 76 | DEBUGP("IPv6 RT LEN %u %u ", hdrlen, rh->hdrlen); |
146 | DEBUGP("TYPE %04X ", rh->type); | 77 | DEBUGP("TYPE %04X ", rh->type); |
147 | DEBUGP("SGS_LEFT %u %02X\n", rh->segments_left, rh->segments_left); | 78 | DEBUGP("SGS_LEFT %u %02X\n", rh->segments_left, rh->segments_left); |
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 5aa3691c578d..a1265a320b11 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -627,7 +627,7 @@ static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg) | |||
627 | 627 | ||
628 | if (type && code) { | 628 | if (type && code) { |
629 | get_user(fl->fl_icmp_type, type); | 629 | get_user(fl->fl_icmp_type, type); |
630 | __get_user(fl->fl_icmp_code, code); | 630 | get_user(fl->fl_icmp_code, code); |
631 | probed = 1; | 631 | probed = 1; |
632 | } | 632 | } |
633 | break; | 633 | break; |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 80643e6b346b..d693cb988b78 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -209,9 +209,11 @@ static __inline__ void __tcp_v6_hash(struct sock *sk) | |||
209 | lock = &tcp_hashinfo.lhash_lock; | 209 | lock = &tcp_hashinfo.lhash_lock; |
210 | inet_listen_wlock(&tcp_hashinfo); | 210 | inet_listen_wlock(&tcp_hashinfo); |
211 | } else { | 211 | } else { |
212 | sk->sk_hashent = inet6_sk_ehashfn(sk, tcp_hashinfo.ehash_size); | 212 | unsigned int hash; |
213 | list = &tcp_hashinfo.ehash[sk->sk_hashent].chain; | 213 | sk->sk_hash = hash = inet6_sk_ehashfn(sk); |
214 | lock = &tcp_hashinfo.ehash[sk->sk_hashent].lock; | 214 | hash &= (tcp_hashinfo.ehash_size - 1); |
215 | list = &tcp_hashinfo.ehash[hash].chain; | ||
216 | lock = &tcp_hashinfo.ehash[hash].lock; | ||
215 | write_lock(lock); | 217 | write_lock(lock); |
216 | } | 218 | } |
217 | 219 | ||
@@ -322,13 +324,13 @@ static int __tcp_v6_check_established(struct sock *sk, const __u16 lport, | |||
322 | const struct in6_addr *saddr = &np->daddr; | 324 | const struct in6_addr *saddr = &np->daddr; |
323 | const int dif = sk->sk_bound_dev_if; | 325 | const int dif = sk->sk_bound_dev_if; |
324 | const u32 ports = INET_COMBINED_PORTS(inet->dport, lport); | 326 | const u32 ports = INET_COMBINED_PORTS(inet->dport, lport); |
325 | const int hash = inet6_ehashfn(daddr, inet->num, saddr, inet->dport, | 327 | unsigned int hash = inet6_ehashfn(daddr, inet->num, saddr, inet->dport); |
326 | tcp_hashinfo.ehash_size); | 328 | struct inet_ehash_bucket *head = inet_ehash_bucket(&tcp_hashinfo, hash); |
327 | struct inet_ehash_bucket *head = &tcp_hashinfo.ehash[hash]; | ||
328 | struct sock *sk2; | 329 | struct sock *sk2; |
329 | const struct hlist_node *node; | 330 | const struct hlist_node *node; |
330 | struct inet_timewait_sock *tw; | 331 | struct inet_timewait_sock *tw; |
331 | 332 | ||
333 | prefetch(head->chain.first); | ||
332 | write_lock(&head->lock); | 334 | write_lock(&head->lock); |
333 | 335 | ||
334 | /* Check TIME-WAIT sockets first. */ | 336 | /* Check TIME-WAIT sockets first. */ |
@@ -365,14 +367,14 @@ static int __tcp_v6_check_established(struct sock *sk, const __u16 lport, | |||
365 | 367 | ||
366 | /* And established part... */ | 368 | /* And established part... */ |
367 | sk_for_each(sk2, node, &head->chain) { | 369 | sk_for_each(sk2, node, &head->chain) { |
368 | if (INET6_MATCH(sk2, saddr, daddr, ports, dif)) | 370 | if (INET6_MATCH(sk2, hash, saddr, daddr, ports, dif)) |
369 | goto not_unique; | 371 | goto not_unique; |
370 | } | 372 | } |
371 | 373 | ||
372 | unique: | 374 | unique: |
373 | BUG_TRAP(sk_unhashed(sk)); | 375 | BUG_TRAP(sk_unhashed(sk)); |
374 | __sk_add_node(sk, &head->chain); | 376 | __sk_add_node(sk, &head->chain); |
375 | sk->sk_hashent = hash; | 377 | sk->sk_hash = hash; |
376 | sock_prot_inc_use(sk->sk_prot); | 378 | sock_prot_inc_use(sk->sk_prot); |
377 | write_unlock(&head->lock); | 379 | write_unlock(&head->lock); |
378 | 380 | ||
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 69b146843a20..e4cad11f284a 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -405,9 +405,8 @@ static struct sock *udp_v6_mcast_next(struct sock *sk, | |||
405 | continue; | 405 | continue; |
406 | 406 | ||
407 | if (!ipv6_addr_any(&np->rcv_saddr)) { | 407 | if (!ipv6_addr_any(&np->rcv_saddr)) { |
408 | if (ipv6_addr_equal(&np->rcv_saddr, loc_addr)) | 408 | if (!ipv6_addr_equal(&np->rcv_saddr, loc_addr)) |
409 | return s; | 409 | continue; |
410 | continue; | ||
411 | } | 410 | } |
412 | if(!inet6_mc_check(s, loc_addr, rmt_addr)) | 411 | if(!inet6_mc_check(s, loc_addr, rmt_addr)) |
413 | continue; | 412 | continue; |
@@ -640,6 +639,7 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
640 | int tclass = -1; | 639 | int tclass = -1; |
641 | int corkreq = up->corkflag || msg->msg_flags&MSG_MORE; | 640 | int corkreq = up->corkflag || msg->msg_flags&MSG_MORE; |
642 | int err; | 641 | int err; |
642 | int connected = 0; | ||
643 | 643 | ||
644 | /* destination address check */ | 644 | /* destination address check */ |
645 | if (sin6) { | 645 | if (sin6) { |
@@ -749,6 +749,7 @@ do_udp_sendmsg: | |||
749 | fl->fl_ip_dport = inet->dport; | 749 | fl->fl_ip_dport = inet->dport; |
750 | daddr = &np->daddr; | 750 | daddr = &np->daddr; |
751 | fl->fl6_flowlabel = np->flow_label; | 751 | fl->fl6_flowlabel = np->flow_label; |
752 | connected = 1; | ||
752 | } | 753 | } |
753 | 754 | ||
754 | if (!fl->oif) | 755 | if (!fl->oif) |
@@ -771,6 +772,7 @@ do_udp_sendmsg: | |||
771 | } | 772 | } |
772 | if (!(opt->opt_nflen|opt->opt_flen)) | 773 | if (!(opt->opt_nflen|opt->opt_flen)) |
773 | opt = NULL; | 774 | opt = NULL; |
775 | connected = 0; | ||
774 | } | 776 | } |
775 | if (opt == NULL) | 777 | if (opt == NULL) |
776 | opt = np->opt; | 778 | opt = np->opt; |
@@ -788,10 +790,13 @@ do_udp_sendmsg: | |||
788 | ipv6_addr_copy(&final, &fl->fl6_dst); | 790 | ipv6_addr_copy(&final, &fl->fl6_dst); |
789 | ipv6_addr_copy(&fl->fl6_dst, rt0->addr); | 791 | ipv6_addr_copy(&fl->fl6_dst, rt0->addr); |
790 | final_p = &final; | 792 | final_p = &final; |
793 | connected = 0; | ||
791 | } | 794 | } |
792 | 795 | ||
793 | if (!fl->oif && ipv6_addr_is_multicast(&fl->fl6_dst)) | 796 | if (!fl->oif && ipv6_addr_is_multicast(&fl->fl6_dst)) { |
794 | fl->oif = np->mcast_oif; | 797 | fl->oif = np->mcast_oif; |
798 | connected = 0; | ||
799 | } | ||
795 | 800 | ||
796 | err = ip6_dst_lookup(sk, &dst, fl); | 801 | err = ip6_dst_lookup(sk, &dst, fl); |
797 | if (err) | 802 | if (err) |
@@ -847,10 +852,16 @@ do_append_data: | |||
847 | else if (!corkreq) | 852 | else if (!corkreq) |
848 | err = udp_v6_push_pending_frames(sk, up); | 853 | err = udp_v6_push_pending_frames(sk, up); |
849 | 854 | ||
850 | if (dst) | 855 | if (dst) { |
851 | ip6_dst_store(sk, dst, | 856 | if (connected) { |
852 | ipv6_addr_equal(&fl->fl6_dst, &np->daddr) ? | 857 | ip6_dst_store(sk, dst, |
853 | &np->daddr : NULL); | 858 | ipv6_addr_equal(&fl->fl6_dst, &np->daddr) ? |
859 | &np->daddr : NULL); | ||
860 | } else { | ||
861 | dst_release(dst); | ||
862 | } | ||
863 | } | ||
864 | |||
854 | if (err > 0) | 865 | if (err > 0) |
855 | err = np->recverr ? net_xmit_errno(err) : 0; | 866 | err = np->recverr ? net_xmit_errno(err) : 0; |
856 | release_sock(sk); | 867 | release_sock(sk); |