diff options
Diffstat (limited to 'net')
| -rw-r--r-- | net/9p/protocol.c | 22 | ||||
| -rw-r--r-- | net/bridge/br_forward.c | 7 | ||||
| -rw-r--r-- | net/core/dev.c | 4 | ||||
| -rw-r--r-- | net/core/neighbour.c | 14 | ||||
| -rw-r--r-- | net/core/skbuff.c | 15 | ||||
| -rw-r--r-- | net/ipv4/ipconfig.c | 6 | ||||
| -rw-r--r-- | net/ipv4/tcp.c | 3 | ||||
| -rw-r--r-- | net/ipv4/tcp_output.c | 12 | ||||
| -rw-r--r-- | net/ipv4/udp.c | 68 | ||||
| -rw-r--r-- | net/ipv6/addrconf.c | 2 | ||||
| -rw-r--r-- | net/ipv6/icmp.c | 4 | ||||
| -rw-r--r-- | net/ipv6/ip6_flowlabel.c | 8 | ||||
| -rw-r--r-- | net/ipv6/ip6_input.c | 2 | ||||
| -rw-r--r-- | net/ipv6/ip6_output.c | 67 | ||||
| -rw-r--r-- | net/ipv6/ip6_tunnel.c | 2 | ||||
| -rw-r--r-- | net/ipv6/ip6mr.c | 24 | ||||
| -rw-r--r-- | net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | 25 | ||||
| -rw-r--r-- | net/ipv6/route.c | 2 | ||||
| -rw-r--r-- | net/netfilter/nf_conntrack_netlink.c | 15 | ||||
| -rw-r--r-- | net/netfilter/xt_sctp.c | 2 | ||||
| -rw-r--r-- | net/packet/af_packet.c | 17 | ||||
| -rw-r--r-- | net/rxrpc/af_rxrpc.c | 5 | ||||
| -rw-r--r-- | net/sunrpc/Kconfig | 2 | ||||
| -rw-r--r-- | net/wimax/debugfs.c | 11 | ||||
| -rw-r--r-- | net/wimax/stack.c | 13 | ||||
| -rw-r--r-- | net/wireless/reg.c | 32 |
26 files changed, 262 insertions, 122 deletions
diff --git a/net/9p/protocol.c b/net/9p/protocol.c index dcd7666824ba..fc70147c771e 100644 --- a/net/9p/protocol.c +++ b/net/9p/protocol.c | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | #include <linux/errno.h> | 29 | #include <linux/errno.h> |
| 30 | #include <linux/uaccess.h> | 30 | #include <linux/uaccess.h> |
| 31 | #include <linux/sched.h> | 31 | #include <linux/sched.h> |
| 32 | #include <linux/types.h> | ||
| 32 | #include <net/9p/9p.h> | 33 | #include <net/9p/9p.h> |
| 33 | #include <net/9p/client.h> | 34 | #include <net/9p/client.h> |
| 34 | #include "protocol.h" | 35 | #include "protocol.h" |
| @@ -160,29 +161,32 @@ p9pdu_vreadf(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap) | |||
| 160 | break; | 161 | break; |
| 161 | case 'w':{ | 162 | case 'w':{ |
| 162 | int16_t *val = va_arg(ap, int16_t *); | 163 | int16_t *val = va_arg(ap, int16_t *); |
| 163 | if (pdu_read(pdu, val, sizeof(*val))) { | 164 | __le16 le_val; |
| 165 | if (pdu_read(pdu, &le_val, sizeof(le_val))) { | ||
| 164 | errcode = -EFAULT; | 166 | errcode = -EFAULT; |
| 165 | break; | 167 | break; |
| 166 | } | 168 | } |
| 167 | *val = cpu_to_le16(*val); | 169 | *val = le16_to_cpu(le_val); |
| 168 | } | 170 | } |
| 169 | break; | 171 | break; |
| 170 | case 'd':{ | 172 | case 'd':{ |
| 171 | int32_t *val = va_arg(ap, int32_t *); | 173 | int32_t *val = va_arg(ap, int32_t *); |
| 172 | if (pdu_read(pdu, val, sizeof(*val))) { | 174 | __le32 le_val; |
| 175 | if (pdu_read(pdu, &le_val, sizeof(le_val))) { | ||
| 173 | errcode = -EFAULT; | 176 | errcode = -EFAULT; |
| 174 | break; | 177 | break; |
| 175 | } | 178 | } |
| 176 | *val = cpu_to_le32(*val); | 179 | *val = le32_to_cpu(le_val); |
| 177 | } | 180 | } |
| 178 | break; | 181 | break; |
| 179 | case 'q':{ | 182 | case 'q':{ |
| 180 | int64_t *val = va_arg(ap, int64_t *); | 183 | int64_t *val = va_arg(ap, int64_t *); |
| 181 | if (pdu_read(pdu, val, sizeof(*val))) { | 184 | __le64 le_val; |
| 185 | if (pdu_read(pdu, &le_val, sizeof(le_val))) { | ||
| 182 | errcode = -EFAULT; | 186 | errcode = -EFAULT; |
| 183 | break; | 187 | break; |
| 184 | } | 188 | } |
| 185 | *val = cpu_to_le64(*val); | 189 | *val = le64_to_cpu(le_val); |
| 186 | } | 190 | } |
| 187 | break; | 191 | break; |
| 188 | case 's':{ | 192 | case 's':{ |
| @@ -362,19 +366,19 @@ p9pdu_vwritef(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap) | |||
| 362 | } | 366 | } |
| 363 | break; | 367 | break; |
| 364 | case 'w':{ | 368 | case 'w':{ |
| 365 | int16_t val = va_arg(ap, int); | 369 | __le16 val = cpu_to_le16(va_arg(ap, int)); |
| 366 | if (pdu_write(pdu, &val, sizeof(val))) | 370 | if (pdu_write(pdu, &val, sizeof(val))) |
| 367 | errcode = -EFAULT; | 371 | errcode = -EFAULT; |
| 368 | } | 372 | } |
| 369 | break; | 373 | break; |
| 370 | case 'd':{ | 374 | case 'd':{ |
| 371 | int32_t val = va_arg(ap, int32_t); | 375 | __le32 val = cpu_to_le32(va_arg(ap, int32_t)); |
| 372 | if (pdu_write(pdu, &val, sizeof(val))) | 376 | if (pdu_write(pdu, &val, sizeof(val))) |
| 373 | errcode = -EFAULT; | 377 | errcode = -EFAULT; |
| 374 | } | 378 | } |
| 375 | break; | 379 | break; |
| 376 | case 'q':{ | 380 | case 'q':{ |
| 377 | int64_t val = va_arg(ap, int64_t); | 381 | __le64 val = cpu_to_le64(va_arg(ap, int64_t)); |
| 378 | if (pdu_write(pdu, &val, sizeof(val))) | 382 | if (pdu_write(pdu, &val, sizeof(val))) |
| 379 | errcode = -EFAULT; | 383 | errcode = -EFAULT; |
| 380 | } | 384 | } |
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index bdd9ccea17ce..d2c27c808d3b 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c | |||
| @@ -67,6 +67,11 @@ static void __br_forward(const struct net_bridge_port *to, struct sk_buff *skb) | |||
| 67 | { | 67 | { |
| 68 | struct net_device *indev; | 68 | struct net_device *indev; |
| 69 | 69 | ||
| 70 | if (skb_warn_if_lro(skb)) { | ||
| 71 | kfree_skb(skb); | ||
| 72 | return; | ||
| 73 | } | ||
| 74 | |||
| 70 | indev = skb->dev; | 75 | indev = skb->dev; |
| 71 | skb->dev = to->dev; | 76 | skb->dev = to->dev; |
| 72 | skb_forward_csum(skb); | 77 | skb_forward_csum(skb); |
| @@ -89,7 +94,7 @@ void br_deliver(const struct net_bridge_port *to, struct sk_buff *skb) | |||
| 89 | /* called with rcu_read_lock */ | 94 | /* called with rcu_read_lock */ |
| 90 | void br_forward(const struct net_bridge_port *to, struct sk_buff *skb) | 95 | void br_forward(const struct net_bridge_port *to, struct sk_buff *skb) |
| 91 | { | 96 | { |
| 92 | if (!skb_warn_if_lro(skb) && should_deliver(to, skb)) { | 97 | if (should_deliver(to, skb)) { |
| 93 | __br_forward(to, skb); | 98 | __br_forward(to, skb); |
| 94 | return; | 99 | return; |
| 95 | } | 100 | } |
diff --git a/net/core/dev.c b/net/core/dev.c index 5379b0c1190a..a17e00662363 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
| @@ -1090,7 +1090,7 @@ int dev_open(struct net_device *dev) | |||
| 1090 | /* | 1090 | /* |
| 1091 | * Enable NET_DMA | 1091 | * Enable NET_DMA |
| 1092 | */ | 1092 | */ |
| 1093 | dmaengine_get(); | 1093 | net_dmaengine_get(); |
| 1094 | 1094 | ||
| 1095 | /* | 1095 | /* |
| 1096 | * Initialize multicasting status | 1096 | * Initialize multicasting status |
| @@ -1172,7 +1172,7 @@ int dev_close(struct net_device *dev) | |||
| 1172 | /* | 1172 | /* |
| 1173 | * Shutdown NET_DMA | 1173 | * Shutdown NET_DMA |
| 1174 | */ | 1174 | */ |
| 1175 | dmaengine_put(); | 1175 | net_dmaengine_put(); |
| 1176 | 1176 | ||
| 1177 | return 0; | 1177 | return 0; |
| 1178 | } | 1178 | } |
diff --git a/net/core/neighbour.c b/net/core/neighbour.c index f66c58df8953..278a142d1047 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c | |||
| @@ -1994,8 +1994,8 @@ static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 1994 | if (!net_eq(neigh_parms_net(p), net)) | 1994 | if (!net_eq(neigh_parms_net(p), net)) |
| 1995 | continue; | 1995 | continue; |
| 1996 | 1996 | ||
| 1997 | if (nidx++ < neigh_skip) | 1997 | if (nidx < neigh_skip) |
| 1998 | continue; | 1998 | goto next; |
| 1999 | 1999 | ||
| 2000 | if (neightbl_fill_param_info(skb, tbl, p, | 2000 | if (neightbl_fill_param_info(skb, tbl, p, |
| 2001 | NETLINK_CB(cb->skb).pid, | 2001 | NETLINK_CB(cb->skb).pid, |
| @@ -2003,6 +2003,8 @@ static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 2003 | RTM_NEWNEIGHTBL, | 2003 | RTM_NEWNEIGHTBL, |
| 2004 | NLM_F_MULTI) <= 0) | 2004 | NLM_F_MULTI) <= 0) |
| 2005 | goto out; | 2005 | goto out; |
| 2006 | next: | ||
| 2007 | nidx++; | ||
| 2006 | } | 2008 | } |
| 2007 | 2009 | ||
| 2008 | neigh_skip = 0; | 2010 | neigh_skip = 0; |
| @@ -2082,12 +2084,10 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, | |||
| 2082 | if (h > s_h) | 2084 | if (h > s_h) |
| 2083 | s_idx = 0; | 2085 | s_idx = 0; |
| 2084 | for (n = tbl->hash_buckets[h], idx = 0; n; n = n->next) { | 2086 | for (n = tbl->hash_buckets[h], idx = 0; n; n = n->next) { |
| 2085 | int lidx; | ||
| 2086 | if (dev_net(n->dev) != net) | 2087 | if (dev_net(n->dev) != net) |
| 2087 | continue; | 2088 | continue; |
| 2088 | lidx = idx++; | 2089 | if (idx < s_idx) |
| 2089 | if (lidx < s_idx) | 2090 | goto next; |
| 2090 | continue; | ||
| 2091 | if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).pid, | 2091 | if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).pid, |
| 2092 | cb->nlh->nlmsg_seq, | 2092 | cb->nlh->nlmsg_seq, |
| 2093 | RTM_NEWNEIGH, | 2093 | RTM_NEWNEIGH, |
| @@ -2096,6 +2096,8 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, | |||
| 2096 | rc = -1; | 2096 | rc = -1; |
| 2097 | goto out; | 2097 | goto out; |
| 2098 | } | 2098 | } |
| 2099 | next: | ||
| 2100 | idx++; | ||
| 2099 | } | 2101 | } |
| 2100 | } | 2102 | } |
| 2101 | read_unlock_bh(&tbl->lock); | 2103 | read_unlock_bh(&tbl->lock); |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 2e5f2ca3bdcd..da74b844f4ea 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
| @@ -2212,10 +2212,10 @@ unsigned int skb_seq_read(unsigned int consumed, const u8 **data, | |||
| 2212 | return 0; | 2212 | return 0; |
| 2213 | 2213 | ||
| 2214 | next_skb: | 2214 | next_skb: |
| 2215 | block_limit = skb_headlen(st->cur_skb); | 2215 | block_limit = skb_headlen(st->cur_skb) + st->stepped_offset; |
| 2216 | 2216 | ||
| 2217 | if (abs_offset < block_limit) { | 2217 | if (abs_offset < block_limit) { |
| 2218 | *data = st->cur_skb->data + abs_offset; | 2218 | *data = st->cur_skb->data + (abs_offset - st->stepped_offset); |
| 2219 | return block_limit - abs_offset; | 2219 | return block_limit - abs_offset; |
| 2220 | } | 2220 | } |
| 2221 | 2221 | ||
| @@ -2250,13 +2250,14 @@ next_skb: | |||
| 2250 | st->frag_data = NULL; | 2250 | st->frag_data = NULL; |
| 2251 | } | 2251 | } |
| 2252 | 2252 | ||
| 2253 | if (st->cur_skb->next) { | 2253 | if (st->root_skb == st->cur_skb && |
| 2254 | st->cur_skb = st->cur_skb->next; | 2254 | skb_shinfo(st->root_skb)->frag_list) { |
| 2255 | st->cur_skb = skb_shinfo(st->root_skb)->frag_list; | ||
| 2255 | st->frag_idx = 0; | 2256 | st->frag_idx = 0; |
| 2256 | goto next_skb; | 2257 | goto next_skb; |
| 2257 | } else if (st->root_skb == st->cur_skb && | 2258 | } else if (st->cur_skb->next) { |
| 2258 | skb_shinfo(st->root_skb)->frag_list) { | 2259 | st->cur_skb = st->cur_skb->next; |
| 2259 | st->cur_skb = skb_shinfo(st->root_skb)->frag_list; | 2260 | st->frag_idx = 0; |
| 2260 | goto next_skb; | 2261 | goto next_skb; |
| 2261 | } | 2262 | } |
| 2262 | 2263 | ||
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c index 42a0f3dd3fd6..d722013c1cae 100644 --- a/net/ipv4/ipconfig.c +++ b/net/ipv4/ipconfig.c | |||
| @@ -1268,6 +1268,9 @@ __be32 __init root_nfs_parse_addr(char *name) | |||
| 1268 | static int __init ip_auto_config(void) | 1268 | static int __init ip_auto_config(void) |
| 1269 | { | 1269 | { |
| 1270 | __be32 addr; | 1270 | __be32 addr; |
| 1271 | #ifdef IPCONFIG_DYNAMIC | ||
| 1272 | int retries = CONF_OPEN_RETRIES; | ||
| 1273 | #endif | ||
| 1271 | 1274 | ||
| 1272 | #ifdef CONFIG_PROC_FS | 1275 | #ifdef CONFIG_PROC_FS |
| 1273 | proc_net_fops_create(&init_net, "pnp", S_IRUGO, &pnp_seq_fops); | 1276 | proc_net_fops_create(&init_net, "pnp", S_IRUGO, &pnp_seq_fops); |
| @@ -1304,9 +1307,6 @@ static int __init ip_auto_config(void) | |||
| 1304 | #endif | 1307 | #endif |
| 1305 | ic_first_dev->next) { | 1308 | ic_first_dev->next) { |
| 1306 | #ifdef IPCONFIG_DYNAMIC | 1309 | #ifdef IPCONFIG_DYNAMIC |
| 1307 | |||
| 1308 | int retries = CONF_OPEN_RETRIES; | ||
| 1309 | |||
| 1310 | if (ic_dynamic() < 0) { | 1310 | if (ic_dynamic() < 0) { |
| 1311 | ic_close_devs(); | 1311 | ic_close_devs(); |
| 1312 | 1312 | ||
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 0cd71b84e483..76b148bcb0dc 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
| @@ -524,7 +524,8 @@ static int tcp_splice_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb, | |||
| 524 | struct tcp_splice_state *tss = rd_desc->arg.data; | 524 | struct tcp_splice_state *tss = rd_desc->arg.data; |
| 525 | int ret; | 525 | int ret; |
| 526 | 526 | ||
| 527 | ret = skb_splice_bits(skb, offset, tss->pipe, rd_desc->count, tss->flags); | 527 | ret = skb_splice_bits(skb, offset, tss->pipe, min(rd_desc->count, len), |
| 528 | tss->flags); | ||
| 528 | if (ret > 0) | 529 | if (ret > 0) |
| 529 | rd_desc->count -= ret; | 530 | rd_desc->count -= ret; |
| 530 | return ret; | 531 | return ret; |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 557fe16cbfb0..dda42f0bd7a3 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
| @@ -663,14 +663,10 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, | |||
| 663 | th->urg_ptr = 0; | 663 | th->urg_ptr = 0; |
| 664 | 664 | ||
| 665 | /* The urg_mode check is necessary during a below snd_una win probe */ | 665 | /* The urg_mode check is necessary during a below snd_una win probe */ |
| 666 | if (unlikely(tcp_urg_mode(tp))) { | 666 | if (unlikely(tcp_urg_mode(tp) && |
| 667 | if (between(tp->snd_up, tcb->seq + 1, tcb->seq + 0xFFFF)) { | 667 | between(tp->snd_up, tcb->seq + 1, tcb->seq + 0xFFFF))) { |
| 668 | th->urg_ptr = htons(tp->snd_up - tcb->seq); | 668 | th->urg_ptr = htons(tp->snd_up - tcb->seq); |
| 669 | th->urg = 1; | 669 | th->urg = 1; |
| 670 | } else if (after(tcb->seq + 0xFFFF, tp->snd_nxt)) { | ||
| 671 | th->urg_ptr = 0xFFFF; | ||
| 672 | th->urg = 1; | ||
| 673 | } | ||
| 674 | } | 670 | } |
| 675 | 671 | ||
| 676 | tcp_options_write((__be32 *)(th + 1), tp, &opts, &md5_hash_location); | 672 | tcp_options_write((__be32 *)(th + 1), tp, &opts, &md5_hash_location); |
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index cf5ab0581eba..c47c989cb1fb 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
| @@ -120,8 +120,11 @@ EXPORT_SYMBOL(sysctl_udp_wmem_min); | |||
| 120 | atomic_t udp_memory_allocated; | 120 | atomic_t udp_memory_allocated; |
| 121 | EXPORT_SYMBOL(udp_memory_allocated); | 121 | EXPORT_SYMBOL(udp_memory_allocated); |
| 122 | 122 | ||
| 123 | #define PORTS_PER_CHAIN (65536 / UDP_HTABLE_SIZE) | ||
| 124 | |||
| 123 | static int udp_lib_lport_inuse(struct net *net, __u16 num, | 125 | static int udp_lib_lport_inuse(struct net *net, __u16 num, |
| 124 | const struct udp_hslot *hslot, | 126 | const struct udp_hslot *hslot, |
| 127 | unsigned long *bitmap, | ||
| 125 | struct sock *sk, | 128 | struct sock *sk, |
| 126 | int (*saddr_comp)(const struct sock *sk1, | 129 | int (*saddr_comp)(const struct sock *sk1, |
| 127 | const struct sock *sk2)) | 130 | const struct sock *sk2)) |
| @@ -132,12 +135,17 @@ static int udp_lib_lport_inuse(struct net *net, __u16 num, | |||
| 132 | sk_nulls_for_each(sk2, node, &hslot->head) | 135 | sk_nulls_for_each(sk2, node, &hslot->head) |
| 133 | if (net_eq(sock_net(sk2), net) && | 136 | if (net_eq(sock_net(sk2), net) && |
| 134 | sk2 != sk && | 137 | sk2 != sk && |
| 135 | sk2->sk_hash == num && | 138 | (bitmap || sk2->sk_hash == num) && |
| 136 | (!sk2->sk_reuse || !sk->sk_reuse) && | 139 | (!sk2->sk_reuse || !sk->sk_reuse) && |
| 137 | (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if | 140 | (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if |
| 138 | || sk2->sk_bound_dev_if == sk->sk_bound_dev_if) && | 141 | || sk2->sk_bound_dev_if == sk->sk_bound_dev_if) && |
| 139 | (*saddr_comp)(sk, sk2)) | 142 | (*saddr_comp)(sk, sk2)) { |
| 140 | return 1; | 143 | if (bitmap) |
| 144 | __set_bit(sk2->sk_hash / UDP_HTABLE_SIZE, | ||
| 145 | bitmap); | ||
| 146 | else | ||
| 147 | return 1; | ||
| 148 | } | ||
| 141 | return 0; | 149 | return 0; |
| 142 | } | 150 | } |
| 143 | 151 | ||
| @@ -160,32 +168,47 @@ int udp_lib_get_port(struct sock *sk, unsigned short snum, | |||
| 160 | if (!snum) { | 168 | if (!snum) { |
| 161 | int low, high, remaining; | 169 | int low, high, remaining; |
| 162 | unsigned rand; | 170 | unsigned rand; |
| 163 | unsigned short first; | 171 | unsigned short first, last; |
| 172 | DECLARE_BITMAP(bitmap, PORTS_PER_CHAIN); | ||
| 164 | 173 | ||
| 165 | inet_get_local_port_range(&low, &high); | 174 | inet_get_local_port_range(&low, &high); |
| 166 | remaining = (high - low) + 1; | 175 | remaining = (high - low) + 1; |
| 167 | 176 | ||
| 168 | rand = net_random(); | 177 | rand = net_random(); |
| 169 | snum = first = rand % remaining + low; | 178 | first = (((u64)rand * remaining) >> 32) + low; |
| 170 | rand |= 1; | 179 | /* |
| 171 | for (;;) { | 180 | * force rand to be an odd multiple of UDP_HTABLE_SIZE |
| 172 | hslot = &udptable->hash[udp_hashfn(net, snum)]; | 181 | */ |
| 182 | rand = (rand | 1) * UDP_HTABLE_SIZE; | ||
| 183 | for (last = first + UDP_HTABLE_SIZE; first != last; first++) { | ||
| 184 | hslot = &udptable->hash[udp_hashfn(net, first)]; | ||
| 185 | bitmap_zero(bitmap, PORTS_PER_CHAIN); | ||
| 173 | spin_lock_bh(&hslot->lock); | 186 | spin_lock_bh(&hslot->lock); |
| 174 | if (!udp_lib_lport_inuse(net, snum, hslot, sk, saddr_comp)) | 187 | udp_lib_lport_inuse(net, snum, hslot, bitmap, sk, |
| 175 | break; | 188 | saddr_comp); |
| 176 | spin_unlock_bh(&hslot->lock); | 189 | |
| 190 | snum = first; | ||
| 191 | /* | ||
| 192 | * Iterate on all possible values of snum for this hash. | ||
| 193 | * Using steps of an odd multiple of UDP_HTABLE_SIZE | ||
| 194 | * give us randomization and full range coverage. | ||
| 195 | */ | ||
| 177 | do { | 196 | do { |
| 178 | snum = snum + rand; | 197 | if (low <= snum && snum <= high && |
| 179 | } while (snum < low || snum > high); | 198 | !test_bit(snum / UDP_HTABLE_SIZE, bitmap)) |
| 180 | if (snum == first) | 199 | goto found; |
| 181 | goto fail; | 200 | snum += rand; |
| 201 | } while (snum != first); | ||
| 202 | spin_unlock_bh(&hslot->lock); | ||
| 182 | } | 203 | } |
| 204 | goto fail; | ||
| 183 | } else { | 205 | } else { |
| 184 | hslot = &udptable->hash[udp_hashfn(net, snum)]; | 206 | hslot = &udptable->hash[udp_hashfn(net, snum)]; |
| 185 | spin_lock_bh(&hslot->lock); | 207 | spin_lock_bh(&hslot->lock); |
| 186 | if (udp_lib_lport_inuse(net, snum, hslot, sk, saddr_comp)) | 208 | if (udp_lib_lport_inuse(net, snum, hslot, NULL, sk, saddr_comp)) |
| 187 | goto fail_unlock; | 209 | goto fail_unlock; |
| 188 | } | 210 | } |
| 211 | found: | ||
| 189 | inet_sk(sk)->num = snum; | 212 | inet_sk(sk)->num = snum; |
| 190 | sk->sk_hash = snum; | 213 | sk->sk_hash = snum; |
| 191 | if (sk_unhashed(sk)) { | 214 | if (sk_unhashed(sk)) { |
| @@ -992,9 +1015,11 @@ static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
| 992 | 1015 | ||
| 993 | if ((rc = sock_queue_rcv_skb(sk, skb)) < 0) { | 1016 | if ((rc = sock_queue_rcv_skb(sk, skb)) < 0) { |
| 994 | /* Note that an ENOMEM error is charged twice */ | 1017 | /* Note that an ENOMEM error is charged twice */ |
| 995 | if (rc == -ENOMEM) | 1018 | if (rc == -ENOMEM) { |
| 996 | UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_RCVBUFERRORS, | 1019 | UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_RCVBUFERRORS, |
| 997 | is_udplite); | 1020 | is_udplite); |
| 1021 | atomic_inc(&sk->sk_drops); | ||
| 1022 | } | ||
| 998 | goto drop; | 1023 | goto drop; |
| 999 | } | 1024 | } |
| 1000 | 1025 | ||
| @@ -1206,11 +1231,10 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, | |||
| 1206 | int proto) | 1231 | int proto) |
| 1207 | { | 1232 | { |
| 1208 | struct sock *sk; | 1233 | struct sock *sk; |
| 1209 | struct udphdr *uh = udp_hdr(skb); | 1234 | struct udphdr *uh; |
| 1210 | unsigned short ulen; | 1235 | unsigned short ulen; |
| 1211 | struct rtable *rt = (struct rtable*)skb->dst; | 1236 | struct rtable *rt = (struct rtable*)skb->dst; |
| 1212 | __be32 saddr = ip_hdr(skb)->saddr; | 1237 | __be32 saddr, daddr; |
| 1213 | __be32 daddr = ip_hdr(skb)->daddr; | ||
| 1214 | struct net *net = dev_net(skb->dev); | 1238 | struct net *net = dev_net(skb->dev); |
| 1215 | 1239 | ||
| 1216 | /* | 1240 | /* |
| @@ -1219,6 +1243,7 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, | |||
| 1219 | if (!pskb_may_pull(skb, sizeof(struct udphdr))) | 1243 | if (!pskb_may_pull(skb, sizeof(struct udphdr))) |
| 1220 | goto drop; /* No space for header. */ | 1244 | goto drop; /* No space for header. */ |
| 1221 | 1245 | ||
| 1246 | uh = udp_hdr(skb); | ||
| 1222 | ulen = ntohs(uh->len); | 1247 | ulen = ntohs(uh->len); |
| 1223 | if (ulen > skb->len) | 1248 | if (ulen > skb->len) |
| 1224 | goto short_packet; | 1249 | goto short_packet; |
| @@ -1233,6 +1258,9 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, | |||
| 1233 | if (udp4_csum_init(skb, uh, proto)) | 1258 | if (udp4_csum_init(skb, uh, proto)) |
| 1234 | goto csum_error; | 1259 | goto csum_error; |
| 1235 | 1260 | ||
| 1261 | saddr = ip_hdr(skb)->saddr; | ||
| 1262 | daddr = ip_hdr(skb)->daddr; | ||
| 1263 | |||
| 1236 | if (rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST)) | 1264 | if (rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST)) |
| 1237 | return __udp4_lib_mcast_deliver(net, skb, uh, | 1265 | return __udp4_lib_mcast_deliver(net, skb, uh, |
| 1238 | saddr, daddr, udptable); | 1266 | saddr, daddr, udptable); |
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index e92ad8455c63..f9afb452249c 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
| @@ -4250,7 +4250,7 @@ static struct addrconf_sysctl_table | |||
| 4250 | .procname = "mc_forwarding", | 4250 | .procname = "mc_forwarding", |
| 4251 | .data = &ipv6_devconf.mc_forwarding, | 4251 | .data = &ipv6_devconf.mc_forwarding, |
| 4252 | .maxlen = sizeof(int), | 4252 | .maxlen = sizeof(int), |
| 4253 | .mode = 0644, | 4253 | .mode = 0444, |
| 4254 | .proc_handler = proc_dointvec, | 4254 | .proc_handler = proc_dointvec, |
| 4255 | }, | 4255 | }, |
| 4256 | #endif | 4256 | #endif |
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 4f433847d95f..36dff8807183 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
| @@ -443,10 +443,10 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, | |||
| 443 | if (xfrm_decode_session_reverse(skb, &fl2, AF_INET6)) | 443 | if (xfrm_decode_session_reverse(skb, &fl2, AF_INET6)) |
| 444 | goto relookup_failed; | 444 | goto relookup_failed; |
| 445 | 445 | ||
| 446 | if (ip6_dst_lookup(sk, &dst2, &fl)) | 446 | if (ip6_dst_lookup(sk, &dst2, &fl2)) |
| 447 | goto relookup_failed; | 447 | goto relookup_failed; |
| 448 | 448 | ||
| 449 | err = xfrm_lookup(net, &dst2, &fl, sk, XFRM_LOOKUP_ICMP); | 449 | err = xfrm_lookup(net, &dst2, &fl2, sk, XFRM_LOOKUP_ICMP); |
| 450 | switch (err) { | 450 | switch (err) { |
| 451 | case 0: | 451 | case 0: |
| 452 | dst_release(dst); | 452 | dst_release(dst); |
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index c62dd247774f..7712578bdc66 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c | |||
| @@ -323,17 +323,21 @@ static struct ip6_flowlabel * | |||
| 323 | fl_create(struct net *net, struct in6_flowlabel_req *freq, char __user *optval, | 323 | fl_create(struct net *net, struct in6_flowlabel_req *freq, char __user *optval, |
| 324 | int optlen, int *err_p) | 324 | int optlen, int *err_p) |
| 325 | { | 325 | { |
| 326 | struct ip6_flowlabel *fl; | 326 | struct ip6_flowlabel *fl = NULL; |
| 327 | int olen; | 327 | int olen; |
| 328 | int addr_type; | 328 | int addr_type; |
| 329 | int err; | 329 | int err; |
| 330 | 330 | ||
| 331 | olen = optlen - CMSG_ALIGN(sizeof(*freq)); | ||
| 332 | err = -EINVAL; | ||
| 333 | if (olen > 64 * 1024) | ||
| 334 | goto done; | ||
| 335 | |||
| 331 | err = -ENOMEM; | 336 | err = -ENOMEM; |
| 332 | fl = kzalloc(sizeof(*fl), GFP_KERNEL); | 337 | fl = kzalloc(sizeof(*fl), GFP_KERNEL); |
| 333 | if (fl == NULL) | 338 | if (fl == NULL) |
| 334 | goto done; | 339 | goto done; |
| 335 | 340 | ||
| 336 | olen = optlen - CMSG_ALIGN(sizeof(*freq)); | ||
| 337 | if (olen > 0) { | 341 | if (olen > 0) { |
| 338 | struct msghdr msg; | 342 | struct msghdr msg; |
| 339 | struct flowi flowi; | 343 | struct flowi flowi; |
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index 936f48946e20..f171e8dbac91 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c | |||
| @@ -255,6 +255,7 @@ int ip6_mc_input(struct sk_buff *skb) | |||
| 255 | * IPv6 multicast router mode is now supported ;) | 255 | * IPv6 multicast router mode is now supported ;) |
| 256 | */ | 256 | */ |
| 257 | if (dev_net(skb->dev)->ipv6.devconf_all->mc_forwarding && | 257 | if (dev_net(skb->dev)->ipv6.devconf_all->mc_forwarding && |
| 258 | !(ipv6_addr_type(&hdr->daddr) & IPV6_ADDR_LINKLOCAL) && | ||
| 258 | likely(!(IP6CB(skb)->flags & IP6SKB_FORWARDED))) { | 259 | likely(!(IP6CB(skb)->flags & IP6SKB_FORWARDED))) { |
| 259 | /* | 260 | /* |
| 260 | * Okay, we try to forward - split and duplicate | 261 | * Okay, we try to forward - split and duplicate |
| @@ -316,7 +317,6 @@ int ip6_mc_input(struct sk_buff *skb) | |||
| 316 | } | 317 | } |
| 317 | 318 | ||
| 318 | if (skb2) { | 319 | if (skb2) { |
| 319 | skb2->dev = skb2->dst->dev; | ||
| 320 | ip6_mr_input(skb2); | 320 | ip6_mr_input(skb2); |
| 321 | } | 321 | } |
| 322 | } | 322 | } |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 4b15938bef4d..9fb49c3b518a 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
| @@ -1105,6 +1105,18 @@ static inline int ip6_ufo_append_data(struct sock *sk, | |||
| 1105 | return err; | 1105 | return err; |
| 1106 | } | 1106 | } |
| 1107 | 1107 | ||
| 1108 | static inline struct ipv6_opt_hdr *ip6_opt_dup(struct ipv6_opt_hdr *src, | ||
| 1109 | gfp_t gfp) | ||
| 1110 | { | ||
| 1111 | return src ? kmemdup(src, (src->hdrlen + 1) * 8, gfp) : NULL; | ||
| 1112 | } | ||
| 1113 | |||
| 1114 | static inline struct ipv6_rt_hdr *ip6_rthdr_dup(struct ipv6_rt_hdr *src, | ||
| 1115 | gfp_t gfp) | ||
| 1116 | { | ||
| 1117 | return src ? kmemdup(src, (src->hdrlen + 1) * 8, gfp) : NULL; | ||
| 1118 | } | ||
| 1119 | |||
| 1108 | int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | 1120 | int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, |
| 1109 | int offset, int len, int odd, struct sk_buff *skb), | 1121 | int offset, int len, int odd, struct sk_buff *skb), |
| 1110 | void *from, int length, int transhdrlen, | 1122 | void *from, int length, int transhdrlen, |
| @@ -1130,17 +1142,37 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
| 1130 | * setup for corking | 1142 | * setup for corking |
| 1131 | */ | 1143 | */ |
| 1132 | if (opt) { | 1144 | if (opt) { |
| 1133 | if (np->cork.opt == NULL) { | 1145 | if (WARN_ON(np->cork.opt)) |
| 1134 | np->cork.opt = kmalloc(opt->tot_len, | ||
| 1135 | sk->sk_allocation); | ||
| 1136 | if (unlikely(np->cork.opt == NULL)) | ||
| 1137 | return -ENOBUFS; | ||
| 1138 | } else if (np->cork.opt->tot_len < opt->tot_len) { | ||
| 1139 | printk(KERN_DEBUG "ip6_append_data: invalid option length\n"); | ||
| 1140 | return -EINVAL; | 1146 | return -EINVAL; |
| 1141 | } | 1147 | |
| 1142 | memcpy(np->cork.opt, opt, opt->tot_len); | 1148 | np->cork.opt = kmalloc(opt->tot_len, sk->sk_allocation); |
| 1143 | inet->cork.flags |= IPCORK_OPT; | 1149 | if (unlikely(np->cork.opt == NULL)) |
| 1150 | return -ENOBUFS; | ||
| 1151 | |||
| 1152 | np->cork.opt->tot_len = opt->tot_len; | ||
| 1153 | np->cork.opt->opt_flen = opt->opt_flen; | ||
| 1154 | np->cork.opt->opt_nflen = opt->opt_nflen; | ||
| 1155 | |||
| 1156 | np->cork.opt->dst0opt = ip6_opt_dup(opt->dst0opt, | ||
| 1157 | sk->sk_allocation); | ||
| 1158 | if (opt->dst0opt && !np->cork.opt->dst0opt) | ||
| 1159 | return -ENOBUFS; | ||
| 1160 | |||
| 1161 | np->cork.opt->dst1opt = ip6_opt_dup(opt->dst1opt, | ||
| 1162 | sk->sk_allocation); | ||
| 1163 | if (opt->dst1opt && !np->cork.opt->dst1opt) | ||
| 1164 | return -ENOBUFS; | ||
| 1165 | |||
| 1166 | np->cork.opt->hopopt = ip6_opt_dup(opt->hopopt, | ||
| 1167 | sk->sk_allocation); | ||
| 1168 | if (opt->hopopt && !np->cork.opt->hopopt) | ||
| 1169 | return -ENOBUFS; | ||
| 1170 | |||
| 1171 | np->cork.opt->srcrt = ip6_rthdr_dup(opt->srcrt, | ||
| 1172 | sk->sk_allocation); | ||
| 1173 | if (opt->srcrt && !np->cork.opt->srcrt) | ||
| 1174 | return -ENOBUFS; | ||
| 1175 | |||
| 1144 | /* need source address above miyazawa*/ | 1176 | /* need source address above miyazawa*/ |
| 1145 | } | 1177 | } |
| 1146 | dst_hold(&rt->u.dst); | 1178 | dst_hold(&rt->u.dst); |
| @@ -1167,8 +1199,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
| 1167 | } else { | 1199 | } else { |
| 1168 | rt = (struct rt6_info *)inet->cork.dst; | 1200 | rt = (struct rt6_info *)inet->cork.dst; |
| 1169 | fl = &inet->cork.fl; | 1201 | fl = &inet->cork.fl; |
| 1170 | if (inet->cork.flags & IPCORK_OPT) | 1202 | opt = np->cork.opt; |
| 1171 | opt = np->cork.opt; | ||
| 1172 | transhdrlen = 0; | 1203 | transhdrlen = 0; |
| 1173 | exthdrlen = 0; | 1204 | exthdrlen = 0; |
| 1174 | mtu = inet->cork.fragsize; | 1205 | mtu = inet->cork.fragsize; |
| @@ -1407,9 +1438,15 @@ error: | |||
| 1407 | 1438 | ||
| 1408 | static void ip6_cork_release(struct inet_sock *inet, struct ipv6_pinfo *np) | 1439 | static void ip6_cork_release(struct inet_sock *inet, struct ipv6_pinfo *np) |
| 1409 | { | 1440 | { |
| 1410 | inet->cork.flags &= ~IPCORK_OPT; | 1441 | if (np->cork.opt) { |
| 1411 | kfree(np->cork.opt); | 1442 | kfree(np->cork.opt->dst0opt); |
| 1412 | np->cork.opt = NULL; | 1443 | kfree(np->cork.opt->dst1opt); |
| 1444 | kfree(np->cork.opt->hopopt); | ||
| 1445 | kfree(np->cork.opt->srcrt); | ||
| 1446 | kfree(np->cork.opt); | ||
| 1447 | np->cork.opt = NULL; | ||
| 1448 | } | ||
| 1449 | |||
| 1413 | if (inet->cork.dst) { | 1450 | if (inet->cork.dst) { |
| 1414 | dst_release(inet->cork.dst); | 1451 | dst_release(inet->cork.dst); |
| 1415 | inet->cork.dst = NULL; | 1452 | inet->cork.dst = NULL; |
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 58e2b0d93758..d994c55a5b16 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
| @@ -249,8 +249,8 @@ static struct ip6_tnl *ip6_tnl_create(struct net *net, struct ip6_tnl_parm *p) | |||
| 249 | } | 249 | } |
| 250 | 250 | ||
| 251 | t = netdev_priv(dev); | 251 | t = netdev_priv(dev); |
| 252 | ip6_tnl_dev_init(dev); | ||
| 253 | t->parms = *p; | 252 | t->parms = *p; |
| 253 | ip6_tnl_dev_init(dev); | ||
| 254 | 254 | ||
| 255 | if ((err = register_netdevice(dev)) < 0) | 255 | if ((err = register_netdevice(dev)) < 0) |
| 256 | goto failed_free; | 256 | goto failed_free; |
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 3c51b2d827f4..228be551e9c1 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c | |||
| @@ -48,6 +48,7 @@ | |||
| 48 | #include <linux/pim.h> | 48 | #include <linux/pim.h> |
| 49 | #include <net/addrconf.h> | 49 | #include <net/addrconf.h> |
| 50 | #include <linux/netfilter_ipv6.h> | 50 | #include <linux/netfilter_ipv6.h> |
| 51 | #include <net/ip6_checksum.h> | ||
| 51 | 52 | ||
| 52 | /* Big lock, protecting vif table, mrt cache and mroute socket state. | 53 | /* Big lock, protecting vif table, mrt cache and mroute socket state. |
| 53 | Note that the changes are semaphored via rtnl_lock. | 54 | Note that the changes are semaphored via rtnl_lock. |
| @@ -365,7 +366,9 @@ static int pim6_rcv(struct sk_buff *skb) | |||
| 365 | pim = (struct pimreghdr *)skb_transport_header(skb); | 366 | pim = (struct pimreghdr *)skb_transport_header(skb); |
| 366 | if (pim->type != ((PIM_VERSION << 4) | PIM_REGISTER) || | 367 | if (pim->type != ((PIM_VERSION << 4) | PIM_REGISTER) || |
| 367 | (pim->flags & PIM_NULL_REGISTER) || | 368 | (pim->flags & PIM_NULL_REGISTER) || |
| 368 | (ip_compute_csum((void *)pim, sizeof(*pim)) != 0 && | 369 | (csum_ipv6_magic(&ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, |
| 370 | sizeof(*pim), IPPROTO_PIM, | ||
| 371 | csum_partial((void *)pim, sizeof(*pim), 0)) && | ||
| 369 | csum_fold(skb_checksum(skb, 0, skb->len, 0)))) | 372 | csum_fold(skb_checksum(skb, 0, skb->len, 0)))) |
| 370 | goto drop; | 373 | goto drop; |
| 371 | 374 | ||
| @@ -392,7 +395,7 @@ static int pim6_rcv(struct sk_buff *skb) | |||
| 392 | skb_pull(skb, (u8 *)encap - skb->data); | 395 | skb_pull(skb, (u8 *)encap - skb->data); |
| 393 | skb_reset_network_header(skb); | 396 | skb_reset_network_header(skb); |
| 394 | skb->dev = reg_dev; | 397 | skb->dev = reg_dev; |
| 395 | skb->protocol = htons(ETH_P_IP); | 398 | skb->protocol = htons(ETH_P_IPV6); |
| 396 | skb->ip_summed = 0; | 399 | skb->ip_summed = 0; |
| 397 | skb->pkt_type = PACKET_HOST; | 400 | skb->pkt_type = PACKET_HOST; |
| 398 | dst_release(skb->dst); | 401 | dst_release(skb->dst); |
| @@ -481,6 +484,7 @@ static int mif6_delete(struct net *net, int vifi) | |||
| 481 | { | 484 | { |
| 482 | struct mif_device *v; | 485 | struct mif_device *v; |
| 483 | struct net_device *dev; | 486 | struct net_device *dev; |
| 487 | struct inet6_dev *in6_dev; | ||
| 484 | if (vifi < 0 || vifi >= net->ipv6.maxvif) | 488 | if (vifi < 0 || vifi >= net->ipv6.maxvif) |
| 485 | return -EADDRNOTAVAIL; | 489 | return -EADDRNOTAVAIL; |
| 486 | 490 | ||
| @@ -513,6 +517,10 @@ static int mif6_delete(struct net *net, int vifi) | |||
| 513 | 517 | ||
| 514 | dev_set_allmulti(dev, -1); | 518 | dev_set_allmulti(dev, -1); |
| 515 | 519 | ||
| 520 | in6_dev = __in6_dev_get(dev); | ||
| 521 | if (in6_dev) | ||
| 522 | in6_dev->cnf.mc_forwarding--; | ||
| 523 | |||
| 516 | if (v->flags & MIFF_REGISTER) | 524 | if (v->flags & MIFF_REGISTER) |
| 517 | unregister_netdevice(dev); | 525 | unregister_netdevice(dev); |
| 518 | 526 | ||
| @@ -622,6 +630,7 @@ static int mif6_add(struct net *net, struct mif6ctl *vifc, int mrtsock) | |||
| 622 | int vifi = vifc->mif6c_mifi; | 630 | int vifi = vifc->mif6c_mifi; |
| 623 | struct mif_device *v = &net->ipv6.vif6_table[vifi]; | 631 | struct mif_device *v = &net->ipv6.vif6_table[vifi]; |
| 624 | struct net_device *dev; | 632 | struct net_device *dev; |
| 633 | struct inet6_dev *in6_dev; | ||
| 625 | int err; | 634 | int err; |
| 626 | 635 | ||
| 627 | /* Is vif busy ? */ | 636 | /* Is vif busy ? */ |
| @@ -662,6 +671,10 @@ static int mif6_add(struct net *net, struct mif6ctl *vifc, int mrtsock) | |||
| 662 | return -EINVAL; | 671 | return -EINVAL; |
| 663 | } | 672 | } |
| 664 | 673 | ||
| 674 | in6_dev = __in6_dev_get(dev); | ||
| 675 | if (in6_dev) | ||
| 676 | in6_dev->cnf.mc_forwarding++; | ||
| 677 | |||
| 665 | /* | 678 | /* |
| 666 | * Fill in the VIF structures | 679 | * Fill in the VIF structures |
| 667 | */ | 680 | */ |
| @@ -838,8 +851,6 @@ static int ip6mr_cache_report(struct net *net, struct sk_buff *pkt, mifi_t mifi, | |||
| 838 | 851 | ||
| 839 | skb->dst = dst_clone(pkt->dst); | 852 | skb->dst = dst_clone(pkt->dst); |
| 840 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 853 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
| 841 | |||
| 842 | skb_pull(skb, sizeof(struct ipv6hdr)); | ||
| 843 | } | 854 | } |
| 844 | 855 | ||
| 845 | if (net->ipv6.mroute6_sk == NULL) { | 856 | if (net->ipv6.mroute6_sk == NULL) { |
| @@ -1222,8 +1233,10 @@ static int ip6mr_sk_init(struct sock *sk) | |||
| 1222 | 1233 | ||
| 1223 | rtnl_lock(); | 1234 | rtnl_lock(); |
| 1224 | write_lock_bh(&mrt_lock); | 1235 | write_lock_bh(&mrt_lock); |
| 1225 | if (likely(net->ipv6.mroute6_sk == NULL)) | 1236 | if (likely(net->ipv6.mroute6_sk == NULL)) { |
| 1226 | net->ipv6.mroute6_sk = sk; | 1237 | net->ipv6.mroute6_sk = sk; |
| 1238 | net->ipv6.devconf_all->mc_forwarding++; | ||
| 1239 | } | ||
| 1227 | else | 1240 | else |
| 1228 | err = -EADDRINUSE; | 1241 | err = -EADDRINUSE; |
| 1229 | write_unlock_bh(&mrt_lock); | 1242 | write_unlock_bh(&mrt_lock); |
| @@ -1242,6 +1255,7 @@ int ip6mr_sk_done(struct sock *sk) | |||
| 1242 | if (sk == net->ipv6.mroute6_sk) { | 1255 | if (sk == net->ipv6.mroute6_sk) { |
| 1243 | write_lock_bh(&mrt_lock); | 1256 | write_lock_bh(&mrt_lock); |
| 1244 | net->ipv6.mroute6_sk = NULL; | 1257 | net->ipv6.mroute6_sk = NULL; |
| 1258 | net->ipv6.devconf_all->mc_forwarding--; | ||
| 1245 | write_unlock_bh(&mrt_lock); | 1259 | write_unlock_bh(&mrt_lock); |
| 1246 | 1260 | ||
| 1247 | mroute_clean_tables(net); | 1261 | mroute_clean_tables(net); |
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index c455cf4ee756..c323643ffcf9 100644 --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | |||
| @@ -49,8 +49,19 @@ static bool icmpv6_pkt_to_tuple(const struct sk_buff *skb, | |||
| 49 | static const u_int8_t invmap[] = { | 49 | static const u_int8_t invmap[] = { |
| 50 | [ICMPV6_ECHO_REQUEST - 128] = ICMPV6_ECHO_REPLY + 1, | 50 | [ICMPV6_ECHO_REQUEST - 128] = ICMPV6_ECHO_REPLY + 1, |
| 51 | [ICMPV6_ECHO_REPLY - 128] = ICMPV6_ECHO_REQUEST + 1, | 51 | [ICMPV6_ECHO_REPLY - 128] = ICMPV6_ECHO_REQUEST + 1, |
| 52 | [ICMPV6_NI_QUERY - 128] = ICMPV6_NI_QUERY + 1, | 52 | [ICMPV6_NI_QUERY - 128] = ICMPV6_NI_REPLY + 1, |
| 53 | [ICMPV6_NI_REPLY - 128] = ICMPV6_NI_REPLY +1 | 53 | [ICMPV6_NI_REPLY - 128] = ICMPV6_NI_QUERY +1 |
| 54 | }; | ||
| 55 | |||
| 56 | static const u_int8_t noct_valid_new[] = { | ||
| 57 | [ICMPV6_MGM_QUERY - 130] = 1, | ||
| 58 | [ICMPV6_MGM_REPORT -130] = 1, | ||
| 59 | [ICMPV6_MGM_REDUCTION - 130] = 1, | ||
| 60 | [NDISC_ROUTER_SOLICITATION - 130] = 1, | ||
| 61 | [NDISC_ROUTER_ADVERTISEMENT - 130] = 1, | ||
| 62 | [NDISC_NEIGHBOUR_SOLICITATION - 130] = 1, | ||
| 63 | [NDISC_NEIGHBOUR_ADVERTISEMENT - 130] = 1, | ||
| 64 | [ICMPV6_MLD2_REPORT - 130] = 1 | ||
| 54 | }; | 65 | }; |
| 55 | 66 | ||
| 56 | static bool icmpv6_invert_tuple(struct nf_conntrack_tuple *tuple, | 67 | static bool icmpv6_invert_tuple(struct nf_conntrack_tuple *tuple, |
| @@ -178,6 +189,7 @@ icmpv6_error(struct net *net, struct sk_buff *skb, unsigned int dataoff, | |||
| 178 | { | 189 | { |
| 179 | const struct icmp6hdr *icmp6h; | 190 | const struct icmp6hdr *icmp6h; |
| 180 | struct icmp6hdr _ih; | 191 | struct icmp6hdr _ih; |
| 192 | int type; | ||
| 181 | 193 | ||
| 182 | icmp6h = skb_header_pointer(skb, dataoff, sizeof(_ih), &_ih); | 194 | icmp6h = skb_header_pointer(skb, dataoff, sizeof(_ih), &_ih); |
| 183 | if (icmp6h == NULL) { | 195 | if (icmp6h == NULL) { |
| @@ -194,6 +206,15 @@ icmpv6_error(struct net *net, struct sk_buff *skb, unsigned int dataoff, | |||
| 194 | return -NF_ACCEPT; | 206 | return -NF_ACCEPT; |
| 195 | } | 207 | } |
| 196 | 208 | ||
| 209 | type = icmp6h->icmp6_type - 130; | ||
| 210 | if (type >= 0 && type < sizeof(noct_valid_new) && | ||
| 211 | noct_valid_new[type]) { | ||
| 212 | skb->nfct = &nf_conntrack_untracked.ct_general; | ||
| 213 | skb->nfctinfo = IP_CT_NEW; | ||
| 214 | nf_conntrack_get(skb->nfct); | ||
| 215 | return NF_ACCEPT; | ||
| 216 | } | ||
| 217 | |||
| 197 | /* is not error message ? */ | 218 | /* is not error message ? */ |
| 198 | if (icmp6h->icmp6_type >= 128) | 219 | if (icmp6h->icmp6_type >= 128) |
| 199 | return NF_ACCEPT; | 220 | return NF_ACCEPT; |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index c4a59824ac2c..9c574235c905 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
| @@ -794,7 +794,7 @@ void ip6_route_input(struct sk_buff *skb) | |||
| 794 | .proto = iph->nexthdr, | 794 | .proto = iph->nexthdr, |
| 795 | }; | 795 | }; |
| 796 | 796 | ||
| 797 | if (rt6_need_strict(&iph->daddr)) | 797 | if (rt6_need_strict(&iph->daddr) && skb->dev->type != ARPHRD_PIMREG) |
| 798 | flags |= RT6_LOOKUP_F_IFACE; | 798 | flags |= RT6_LOOKUP_F_IFACE; |
| 799 | 799 | ||
| 800 | skb->dst = fib6_rule_lookup(net, &fl, flags, ip6_pol_route_input); | 800 | skb->dst = fib6_rule_lookup(net, &fl, flags, ip6_pol_route_input); |
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index c32a7e8e3a1b..cb78aa00399e 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c | |||
| @@ -434,7 +434,7 @@ static int ctnetlink_conntrack_event(struct notifier_block *this, | |||
| 434 | } else | 434 | } else |
| 435 | return NOTIFY_DONE; | 435 | return NOTIFY_DONE; |
| 436 | 436 | ||
| 437 | if (!nfnetlink_has_listeners(group)) | 437 | if (!item->report && !nfnetlink_has_listeners(group)) |
| 438 | return NOTIFY_DONE; | 438 | return NOTIFY_DONE; |
| 439 | 439 | ||
| 440 | skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC); | 440 | skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC); |
| @@ -1215,6 +1215,16 @@ ctnetlink_create_conntrack(struct nlattr *cda[], | |||
| 1215 | } | 1215 | } |
| 1216 | } | 1216 | } |
| 1217 | 1217 | ||
| 1218 | #ifdef CONFIG_NF_NAT_NEEDED | ||
| 1219 | if (cda[CTA_NAT_SEQ_ADJ_ORIG] || cda[CTA_NAT_SEQ_ADJ_REPLY]) { | ||
| 1220 | err = ctnetlink_change_nat_seq_adj(ct, cda); | ||
| 1221 | if (err < 0) { | ||
| 1222 | rcu_read_unlock(); | ||
| 1223 | goto err; | ||
| 1224 | } | ||
| 1225 | } | ||
| 1226 | #endif | ||
| 1227 | |||
| 1218 | if (cda[CTA_PROTOINFO]) { | 1228 | if (cda[CTA_PROTOINFO]) { |
| 1219 | err = ctnetlink_change_protoinfo(ct, cda); | 1229 | err = ctnetlink_change_protoinfo(ct, cda); |
| 1220 | if (err < 0) { | 1230 | if (err < 0) { |
| @@ -1492,7 +1502,8 @@ static int ctnetlink_expect_event(struct notifier_block *this, | |||
| 1492 | } else | 1502 | } else |
| 1493 | return NOTIFY_DONE; | 1503 | return NOTIFY_DONE; |
| 1494 | 1504 | ||
| 1495 | if (!nfnetlink_has_listeners(NFNLGRP_CONNTRACK_EXP_NEW)) | 1505 | if (!item->report && |
| 1506 | !nfnetlink_has_listeners(NFNLGRP_CONNTRACK_EXP_NEW)) | ||
| 1496 | return NOTIFY_DONE; | 1507 | return NOTIFY_DONE; |
| 1497 | 1508 | ||
| 1498 | skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC); | 1509 | skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC); |
diff --git a/net/netfilter/xt_sctp.c b/net/netfilter/xt_sctp.c index e223cb43ae8e..a189ada9128f 100644 --- a/net/netfilter/xt_sctp.c +++ b/net/netfilter/xt_sctp.c | |||
| @@ -105,7 +105,7 @@ match_packet(const struct sk_buff *skb, | |||
| 105 | 105 | ||
| 106 | switch (chunk_match_type) { | 106 | switch (chunk_match_type) { |
| 107 | case SCTP_CHUNK_MATCH_ALL: | 107 | case SCTP_CHUNK_MATCH_ALL: |
| 108 | return SCTP_CHUNKMAP_IS_CLEAR(info->chunkmap); | 108 | return SCTP_CHUNKMAP_IS_CLEAR(chunkmapcopy); |
| 109 | case SCTP_CHUNK_MATCH_ANY: | 109 | case SCTP_CHUNK_MATCH_ANY: |
| 110 | return false; | 110 | return false; |
| 111 | case SCTP_CHUNK_MATCH_ONLY: | 111 | case SCTP_CHUNK_MATCH_ONLY: |
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 5f94db2f3e9e..1fc4a7885c41 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
| @@ -77,6 +77,7 @@ | |||
| 77 | #include <linux/poll.h> | 77 | #include <linux/poll.h> |
| 78 | #include <linux/module.h> | 78 | #include <linux/module.h> |
| 79 | #include <linux/init.h> | 79 | #include <linux/init.h> |
| 80 | #include <linux/mutex.h> | ||
| 80 | 81 | ||
| 81 | #ifdef CONFIG_INET | 82 | #ifdef CONFIG_INET |
| 82 | #include <net/inet_common.h> | 83 | #include <net/inet_common.h> |
| @@ -175,6 +176,7 @@ struct packet_sock { | |||
| 175 | #endif | 176 | #endif |
| 176 | struct packet_type prot_hook; | 177 | struct packet_type prot_hook; |
| 177 | spinlock_t bind_lock; | 178 | spinlock_t bind_lock; |
| 179 | struct mutex pg_vec_lock; | ||
| 178 | unsigned int running:1, /* prot_hook is attached*/ | 180 | unsigned int running:1, /* prot_hook is attached*/ |
| 179 | auxdata:1, | 181 | auxdata:1, |
| 180 | origdev:1; | 182 | origdev:1; |
| @@ -220,13 +222,13 @@ static void *packet_lookup_frame(struct packet_sock *po, unsigned int position, | |||
| 220 | h.raw = po->pg_vec[pg_vec_pos] + (frame_offset * po->frame_size); | 222 | h.raw = po->pg_vec[pg_vec_pos] + (frame_offset * po->frame_size); |
| 221 | switch (po->tp_version) { | 223 | switch (po->tp_version) { |
| 222 | case TPACKET_V1: | 224 | case TPACKET_V1: |
| 223 | if (status != h.h1->tp_status ? TP_STATUS_USER : | 225 | if (status != (h.h1->tp_status ? TP_STATUS_USER : |
| 224 | TP_STATUS_KERNEL) | 226 | TP_STATUS_KERNEL)) |
| 225 | return NULL; | 227 | return NULL; |
| 226 | break; | 228 | break; |
| 227 | case TPACKET_V2: | 229 | case TPACKET_V2: |
| 228 | if (status != h.h2->tp_status ? TP_STATUS_USER : | 230 | if (status != (h.h2->tp_status ? TP_STATUS_USER : |
| 229 | TP_STATUS_KERNEL) | 231 | TP_STATUS_KERNEL)) |
| 230 | return NULL; | 232 | return NULL; |
| 231 | break; | 233 | break; |
| 232 | } | 234 | } |
| @@ -1069,6 +1071,7 @@ static int packet_create(struct net *net, struct socket *sock, int protocol) | |||
| 1069 | */ | 1071 | */ |
| 1070 | 1072 | ||
| 1071 | spin_lock_init(&po->bind_lock); | 1073 | spin_lock_init(&po->bind_lock); |
| 1074 | mutex_init(&po->pg_vec_lock); | ||
| 1072 | po->prot_hook.func = packet_rcv; | 1075 | po->prot_hook.func = packet_rcv; |
| 1073 | 1076 | ||
| 1074 | if (sock->type == SOCK_PACKET) | 1077 | if (sock->type == SOCK_PACKET) |
| @@ -1865,6 +1868,7 @@ static int packet_set_ring(struct sock *sk, struct tpacket_req *req, int closing | |||
| 1865 | synchronize_net(); | 1868 | synchronize_net(); |
| 1866 | 1869 | ||
| 1867 | err = -EBUSY; | 1870 | err = -EBUSY; |
| 1871 | mutex_lock(&po->pg_vec_lock); | ||
| 1868 | if (closing || atomic_read(&po->mapped) == 0) { | 1872 | if (closing || atomic_read(&po->mapped) == 0) { |
| 1869 | err = 0; | 1873 | err = 0; |
| 1870 | #define XC(a, b) ({ __typeof__ ((a)) __t; __t = (a); (a) = (b); __t; }) | 1874 | #define XC(a, b) ({ __typeof__ ((a)) __t; __t = (a); (a) = (b); __t; }) |
| @@ -1886,6 +1890,7 @@ static int packet_set_ring(struct sock *sk, struct tpacket_req *req, int closing | |||
| 1886 | if (atomic_read(&po->mapped)) | 1890 | if (atomic_read(&po->mapped)) |
| 1887 | printk(KERN_DEBUG "packet_mmap: vma is busy: %d\n", atomic_read(&po->mapped)); | 1891 | printk(KERN_DEBUG "packet_mmap: vma is busy: %d\n", atomic_read(&po->mapped)); |
| 1888 | } | 1892 | } |
| 1893 | mutex_unlock(&po->pg_vec_lock); | ||
| 1889 | 1894 | ||
| 1890 | spin_lock(&po->bind_lock); | 1895 | spin_lock(&po->bind_lock); |
| 1891 | if (was_running && !po->running) { | 1896 | if (was_running && !po->running) { |
| @@ -1918,7 +1923,7 @@ static int packet_mmap(struct file *file, struct socket *sock, struct vm_area_st | |||
| 1918 | 1923 | ||
| 1919 | size = vma->vm_end - vma->vm_start; | 1924 | size = vma->vm_end - vma->vm_start; |
| 1920 | 1925 | ||
| 1921 | lock_sock(sk); | 1926 | mutex_lock(&po->pg_vec_lock); |
| 1922 | if (po->pg_vec == NULL) | 1927 | if (po->pg_vec == NULL) |
| 1923 | goto out; | 1928 | goto out; |
| 1924 | if (size != po->pg_vec_len*po->pg_vec_pages*PAGE_SIZE) | 1929 | if (size != po->pg_vec_len*po->pg_vec_pages*PAGE_SIZE) |
| @@ -1941,7 +1946,7 @@ static int packet_mmap(struct file *file, struct socket *sock, struct vm_area_st | |||
| 1941 | err = 0; | 1946 | err = 0; |
| 1942 | 1947 | ||
| 1943 | out: | 1948 | out: |
| 1944 | release_sock(sk); | 1949 | mutex_unlock(&po->pg_vec_lock); |
| 1945 | return err; | 1950 | return err; |
| 1946 | } | 1951 | } |
| 1947 | #endif | 1952 | #endif |
diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c index d7d2bed7a699..eac5e7bb7365 100644 --- a/net/rxrpc/af_rxrpc.c +++ b/net/rxrpc/af_rxrpc.c | |||
| @@ -284,13 +284,13 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock, | |||
| 284 | if (IS_ERR(trans)) { | 284 | if (IS_ERR(trans)) { |
| 285 | call = ERR_CAST(trans); | 285 | call = ERR_CAST(trans); |
| 286 | trans = NULL; | 286 | trans = NULL; |
| 287 | goto out; | 287 | goto out_notrans; |
| 288 | } | 288 | } |
| 289 | } else { | 289 | } else { |
| 290 | trans = rx->trans; | 290 | trans = rx->trans; |
| 291 | if (!trans) { | 291 | if (!trans) { |
| 292 | call = ERR_PTR(-ENOTCONN); | 292 | call = ERR_PTR(-ENOTCONN); |
| 293 | goto out; | 293 | goto out_notrans; |
| 294 | } | 294 | } |
| 295 | atomic_inc(&trans->usage); | 295 | atomic_inc(&trans->usage); |
| 296 | } | 296 | } |
| @@ -315,6 +315,7 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock, | |||
| 315 | rxrpc_put_bundle(trans, bundle); | 315 | rxrpc_put_bundle(trans, bundle); |
| 316 | out: | 316 | out: |
| 317 | rxrpc_put_transport(trans); | 317 | rxrpc_put_transport(trans); |
| 318 | out_notrans: | ||
| 318 | release_sock(&rx->sk); | 319 | release_sock(&rx->sk); |
| 319 | _leave(" = %p", call); | 320 | _leave(" = %p", call); |
| 320 | return call; | 321 | return call; |
diff --git a/net/sunrpc/Kconfig b/net/sunrpc/Kconfig index dcef600d0bf5..5592883e1e4a 100644 --- a/net/sunrpc/Kconfig +++ b/net/sunrpc/Kconfig | |||
| @@ -6,7 +6,7 @@ config SUNRPC_GSS | |||
| 6 | 6 | ||
| 7 | config SUNRPC_XPRT_RDMA | 7 | config SUNRPC_XPRT_RDMA |
| 8 | tristate | 8 | tristate |
| 9 | depends on SUNRPC && INFINIBAND && EXPERIMENTAL | 9 | depends on SUNRPC && INFINIBAND && INFINIBAND_ADDR_TRANS && EXPERIMENTAL |
| 10 | default SUNRPC && INFINIBAND | 10 | default SUNRPC && INFINIBAND |
| 11 | help | 11 | help |
| 12 | This option allows the NFS client and server to support | 12 | This option allows the NFS client and server to support |
diff --git a/net/wimax/debugfs.c b/net/wimax/debugfs.c index 87cf4430079c..94d216a46407 100644 --- a/net/wimax/debugfs.c +++ b/net/wimax/debugfs.c | |||
| @@ -28,17 +28,6 @@ | |||
| 28 | #include "debug-levels.h" | 28 | #include "debug-levels.h" |
| 29 | 29 | ||
| 30 | 30 | ||
| 31 | /* Debug framework control of debug levels */ | ||
| 32 | struct d_level D_LEVEL[] = { | ||
| 33 | D_SUBMODULE_DEFINE(debugfs), | ||
| 34 | D_SUBMODULE_DEFINE(id_table), | ||
| 35 | D_SUBMODULE_DEFINE(op_msg), | ||
| 36 | D_SUBMODULE_DEFINE(op_reset), | ||
| 37 | D_SUBMODULE_DEFINE(op_rfkill), | ||
| 38 | D_SUBMODULE_DEFINE(stack), | ||
| 39 | }; | ||
| 40 | size_t D_LEVEL_SIZE = ARRAY_SIZE(D_LEVEL); | ||
| 41 | |||
| 42 | #define __debugfs_register(prefix, name, parent) \ | 31 | #define __debugfs_register(prefix, name, parent) \ |
| 43 | do { \ | 32 | do { \ |
| 44 | result = d_level_register_debugfs(prefix, name, parent); \ | 33 | result = d_level_register_debugfs(prefix, name, parent); \ |
diff --git a/net/wimax/stack.c b/net/wimax/stack.c index d4da92f8981a..3869c0327882 100644 --- a/net/wimax/stack.c +++ b/net/wimax/stack.c | |||
| @@ -516,6 +516,19 @@ void wimax_dev_rm(struct wimax_dev *wimax_dev) | |||
| 516 | } | 516 | } |
| 517 | EXPORT_SYMBOL_GPL(wimax_dev_rm); | 517 | EXPORT_SYMBOL_GPL(wimax_dev_rm); |
| 518 | 518 | ||
| 519 | |||
| 520 | /* Debug framework control of debug levels */ | ||
| 521 | struct d_level D_LEVEL[] = { | ||
| 522 | D_SUBMODULE_DEFINE(debugfs), | ||
| 523 | D_SUBMODULE_DEFINE(id_table), | ||
| 524 | D_SUBMODULE_DEFINE(op_msg), | ||
| 525 | D_SUBMODULE_DEFINE(op_reset), | ||
| 526 | D_SUBMODULE_DEFINE(op_rfkill), | ||
| 527 | D_SUBMODULE_DEFINE(stack), | ||
| 528 | }; | ||
| 529 | size_t D_LEVEL_SIZE = ARRAY_SIZE(D_LEVEL); | ||
| 530 | |||
| 531 | |||
| 519 | struct genl_family wimax_gnl_family = { | 532 | struct genl_family wimax_gnl_family = { |
| 520 | .id = GENL_ID_GENERATE, | 533 | .id = GENL_ID_GENERATE, |
| 521 | .name = "WiMAX", | 534 | .name = "WiMAX", |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index bc494cef2102..85c9034c59b2 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
| @@ -498,6 +498,7 @@ static struct ieee80211_regdomain *country_ie_2_rd( | |||
| 498 | * calculate the number of reg rules we will need. We will need one | 498 | * calculate the number of reg rules we will need. We will need one |
| 499 | * for each channel subband */ | 499 | * for each channel subband */ |
| 500 | while (country_ie_len >= 3) { | 500 | while (country_ie_len >= 3) { |
| 501 | int end_channel = 0; | ||
| 501 | struct ieee80211_country_ie_triplet *triplet = | 502 | struct ieee80211_country_ie_triplet *triplet = |
| 502 | (struct ieee80211_country_ie_triplet *) country_ie; | 503 | (struct ieee80211_country_ie_triplet *) country_ie; |
| 503 | int cur_sub_max_channel = 0, cur_channel = 0; | 504 | int cur_sub_max_channel = 0, cur_channel = 0; |
| @@ -509,9 +510,25 @@ static struct ieee80211_regdomain *country_ie_2_rd( | |||
| 509 | continue; | 510 | continue; |
| 510 | } | 511 | } |
| 511 | 512 | ||
| 513 | /* 2 GHz */ | ||
| 514 | if (triplet->chans.first_channel <= 14) | ||
| 515 | end_channel = triplet->chans.first_channel + | ||
| 516 | triplet->chans.num_channels; | ||
| 517 | else | ||
| 518 | /* | ||
| 519 | * 5 GHz -- For example in country IEs if the first | ||
| 520 | * channel given is 36 and the number of channels is 4 | ||
| 521 | * then the individual channel numbers defined for the | ||
| 522 | * 5 GHz PHY by these parameters are: 36, 40, 44, and 48 | ||
| 523 | * and not 36, 37, 38, 39. | ||
| 524 | * | ||
| 525 | * See: http://tinyurl.com/11d-clarification | ||
| 526 | */ | ||
| 527 | end_channel = triplet->chans.first_channel + | ||
| 528 | (4 * (triplet->chans.num_channels - 1)); | ||
| 529 | |||
| 512 | cur_channel = triplet->chans.first_channel; | 530 | cur_channel = triplet->chans.first_channel; |
| 513 | cur_sub_max_channel = ieee80211_channel_to_frequency( | 531 | cur_sub_max_channel = end_channel; |
| 514 | cur_channel + triplet->chans.num_channels); | ||
| 515 | 532 | ||
| 516 | /* Basic sanity check */ | 533 | /* Basic sanity check */ |
| 517 | if (cur_sub_max_channel < cur_channel) | 534 | if (cur_sub_max_channel < cur_channel) |
| @@ -590,15 +607,6 @@ static struct ieee80211_regdomain *country_ie_2_rd( | |||
| 590 | end_channel = triplet->chans.first_channel + | 607 | end_channel = triplet->chans.first_channel + |
| 591 | triplet->chans.num_channels; | 608 | triplet->chans.num_channels; |
| 592 | else | 609 | else |
| 593 | /* | ||
| 594 | * 5 GHz -- For example in country IEs if the first | ||
| 595 | * channel given is 36 and the number of channels is 4 | ||
| 596 | * then the individual channel numbers defined for the | ||
| 597 | * 5 GHz PHY by these parameters are: 36, 40, 44, and 48 | ||
| 598 | * and not 36, 37, 38, 39. | ||
| 599 | * | ||
| 600 | * See: http://tinyurl.com/11d-clarification | ||
| 601 | */ | ||
| 602 | end_channel = triplet->chans.first_channel + | 610 | end_channel = triplet->chans.first_channel + |
| 603 | (4 * (triplet->chans.num_channels - 1)); | 611 | (4 * (triplet->chans.num_channels - 1)); |
| 604 | 612 | ||
| @@ -1276,7 +1284,7 @@ static void reg_country_ie_process_debug( | |||
| 1276 | if (intersected_rd) { | 1284 | if (intersected_rd) { |
| 1277 | printk(KERN_DEBUG "cfg80211: We intersect both of these " | 1285 | printk(KERN_DEBUG "cfg80211: We intersect both of these " |
| 1278 | "and get:\n"); | 1286 | "and get:\n"); |
| 1279 | print_regdomain_info(rd); | 1287 | print_regdomain_info(intersected_rd); |
| 1280 | return; | 1288 | return; |
| 1281 | } | 1289 | } |
| 1282 | printk(KERN_DEBUG "cfg80211: Intersection between both failed\n"); | 1290 | printk(KERN_DEBUG "cfg80211: Intersection between both failed\n"); |
