diff options
author | David S. Miller <davem@davemloft.net> | 2015-01-27 19:59:56 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-01-27 19:59:56 -0500 |
commit | 95f873f2fff96c592c5d863e2a39825bd8bf0500 (patch) | |
tree | 0d2dd664964ba2c701aefea5b4d1e85b481045e1 /net | |
parent | 8ea65f4a2dfaaf494ef42a16cbf2fea39b07450f (diff) | |
parent | 59343cd7c4809cf7598789e1cd14563780ae4239 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Conflicts:
arch/arm/boot/dts/imx6sx-sdb.dts
net/sched/cls_bpf.c
Two simple sets of overlapping changes.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/core/dev.c | 20 | ||||
-rw-r--r-- | net/dsa/slave.c | 1 | ||||
-rw-r--r-- | net/ipv4/ip_forward.c | 3 | ||||
-rw-r--r-- | net/ipv4/ip_sockglue.c | 8 | ||||
-rw-r--r-- | net/ipv4/ping.c | 5 | ||||
-rw-r--r-- | net/ipv4/route.c | 9 | ||||
-rw-r--r-- | net/ipv4/udp_diag.c | 4 | ||||
-rw-r--r-- | net/ipv6/datagram.c | 10 | ||||
-rw-r--r-- | net/ipv6/ip6_fib.c | 45 | ||||
-rw-r--r-- | net/ipv6/route.c | 13 | ||||
-rw-r--r-- | net/ipv6/xfrm6_policy.c | 10 | ||||
-rw-r--r-- | net/llc/sysctl_net_llc.c | 8 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 2 | ||||
-rw-r--r-- | net/mac80211/pm.c | 29 | ||||
-rw-r--r-- | net/mac80211/rx.c | 2 | ||||
-rw-r--r-- | net/netlink/af_netlink.c | 24 | ||||
-rw-r--r-- | net/netlink/af_netlink.h | 1 | ||||
-rw-r--r-- | net/netlink/genetlink.c | 18 | ||||
-rw-r--r-- | net/sched/cls_bpf.c | 15 | ||||
-rw-r--r-- | net/sctp/associola.c | 1 | ||||
-rw-r--r-- | net/sctp/socket.c | 8 | ||||
-rw-r--r-- | net/socket.c | 3 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 9 | ||||
-rw-r--r-- | net/wireless/reg.c | 56 | ||||
-rw-r--r-- | net/wireless/util.c | 6 |
25 files changed, 189 insertions, 121 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 1e325adc4367..7f028d441e98 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -7075,10 +7075,20 @@ static int dev_cpu_callback(struct notifier_block *nfb, | |||
7075 | oldsd->output_queue = NULL; | 7075 | oldsd->output_queue = NULL; |
7076 | oldsd->output_queue_tailp = &oldsd->output_queue; | 7076 | oldsd->output_queue_tailp = &oldsd->output_queue; |
7077 | } | 7077 | } |
7078 | /* Append NAPI poll list from offline CPU. */ | 7078 | /* Append NAPI poll list from offline CPU, with one exception : |
7079 | if (!list_empty(&oldsd->poll_list)) { | 7079 | * process_backlog() must be called by cpu owning percpu backlog. |
7080 | list_splice_init(&oldsd->poll_list, &sd->poll_list); | 7080 | * We properly handle process_queue & input_pkt_queue later. |
7081 | raise_softirq_irqoff(NET_RX_SOFTIRQ); | 7081 | */ |
7082 | while (!list_empty(&oldsd->poll_list)) { | ||
7083 | struct napi_struct *napi = list_first_entry(&oldsd->poll_list, | ||
7084 | struct napi_struct, | ||
7085 | poll_list); | ||
7086 | |||
7087 | list_del_init(&napi->poll_list); | ||
7088 | if (napi->poll == process_backlog) | ||
7089 | napi->state = 0; | ||
7090 | else | ||
7091 | ____napi_schedule(sd, napi); | ||
7082 | } | 7092 | } |
7083 | 7093 | ||
7084 | raise_softirq_irqoff(NET_TX_SOFTIRQ); | 7094 | raise_softirq_irqoff(NET_TX_SOFTIRQ); |
@@ -7089,7 +7099,7 @@ static int dev_cpu_callback(struct notifier_block *nfb, | |||
7089 | netif_rx_internal(skb); | 7099 | netif_rx_internal(skb); |
7090 | input_queue_head_incr(oldsd); | 7100 | input_queue_head_incr(oldsd); |
7091 | } | 7101 | } |
7092 | while ((skb = __skb_dequeue(&oldsd->input_pkt_queue))) { | 7102 | while ((skb = skb_dequeue(&oldsd->input_pkt_queue))) { |
7093 | netif_rx_internal(skb); | 7103 | netif_rx_internal(skb); |
7094 | input_queue_head_incr(oldsd); | 7104 | input_queue_head_incr(oldsd); |
7095 | } | 7105 | } |
diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 515569ffde8a..589aafd01fc5 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c | |||
@@ -46,6 +46,7 @@ void dsa_slave_mii_bus_init(struct dsa_switch *ds) | |||
46 | snprintf(ds->slave_mii_bus->id, MII_BUS_ID_SIZE, "dsa-%d:%.2x", | 46 | snprintf(ds->slave_mii_bus->id, MII_BUS_ID_SIZE, "dsa-%d:%.2x", |
47 | ds->index, ds->pd->sw_addr); | 47 | ds->index, ds->pd->sw_addr); |
48 | ds->slave_mii_bus->parent = ds->master_dev; | 48 | ds->slave_mii_bus->parent = ds->master_dev; |
49 | ds->slave_mii_bus->phy_mask = ~ds->phys_mii_mask; | ||
49 | } | 50 | } |
50 | 51 | ||
51 | 52 | ||
diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c index 3a83ce5efa80..787b3c294ce6 100644 --- a/net/ipv4/ip_forward.c +++ b/net/ipv4/ip_forward.c | |||
@@ -129,7 +129,8 @@ int ip_forward(struct sk_buff *skb) | |||
129 | * We now generate an ICMP HOST REDIRECT giving the route | 129 | * We now generate an ICMP HOST REDIRECT giving the route |
130 | * we calculated. | 130 | * we calculated. |
131 | */ | 131 | */ |
132 | if (rt->rt_flags&RTCF_DOREDIRECT && !opt->srr && !skb_sec_path(skb)) | 132 | if (IPCB(skb)->flags & IPSKB_DOREDIRECT && !opt->srr && |
133 | !skb_sec_path(skb)) | ||
133 | ip_rt_send_redirect(skb); | 134 | ip_rt_send_redirect(skb); |
134 | 135 | ||
135 | skb->priority = rt_tos2priority(iph->tos); | 136 | skb->priority = rt_tos2priority(iph->tos); |
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index a317797b3cd0..db5e0f81ce0a 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c | |||
@@ -494,17 +494,13 @@ int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) | |||
494 | 494 | ||
495 | memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err)); | 495 | memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err)); |
496 | sin = &errhdr.offender; | 496 | sin = &errhdr.offender; |
497 | sin->sin_family = AF_UNSPEC; | 497 | memset(sin, 0, sizeof(*sin)); |
498 | 498 | ||
499 | if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP || | 499 | if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP || |
500 | ipv4_pktinfo_prepare_errqueue(sk, skb, serr->ee.ee_origin)) { | 500 | ipv4_pktinfo_prepare_errqueue(sk, skb, serr->ee.ee_origin)) { |
501 | struct inet_sock *inet = inet_sk(sk); | ||
502 | |||
503 | sin->sin_family = AF_INET; | 501 | sin->sin_family = AF_INET; |
504 | sin->sin_addr.s_addr = ip_hdr(skb)->saddr; | 502 | sin->sin_addr.s_addr = ip_hdr(skb)->saddr; |
505 | sin->sin_port = 0; | 503 | if (inet_sk(sk)->cmsg_flags) |
506 | memset(&sin->sin_zero, 0, sizeof(sin->sin_zero)); | ||
507 | if (inet->cmsg_flags) | ||
508 | ip_cmsg_recv(msg, skb); | 504 | ip_cmsg_recv(msg, skb); |
509 | } | 505 | } |
510 | 506 | ||
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index c0d82f78d364..2a3720fb5a5f 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c | |||
@@ -966,8 +966,11 @@ bool ping_rcv(struct sk_buff *skb) | |||
966 | 966 | ||
967 | sk = ping_lookup(net, skb, ntohs(icmph->un.echo.id)); | 967 | sk = ping_lookup(net, skb, ntohs(icmph->un.echo.id)); |
968 | if (sk != NULL) { | 968 | if (sk != NULL) { |
969 | struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); | ||
970 | |||
969 | pr_debug("rcv on socket %p\n", sk); | 971 | pr_debug("rcv on socket %p\n", sk); |
970 | ping_queue_rcv_skb(sk, skb_get(skb)); | 972 | if (skb2) |
973 | ping_queue_rcv_skb(sk, skb2); | ||
971 | sock_put(sk); | 974 | sock_put(sk); |
972 | return true; | 975 | return true; |
973 | } | 976 | } |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 2000110c75f0..0c63b2abd873 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -1567,11 +1567,10 @@ static int __mkroute_input(struct sk_buff *skb, | |||
1567 | 1567 | ||
1568 | do_cache = res->fi && !itag; | 1568 | do_cache = res->fi && !itag; |
1569 | if (out_dev == in_dev && err && IN_DEV_TX_REDIRECTS(out_dev) && | 1569 | if (out_dev == in_dev && err && IN_DEV_TX_REDIRECTS(out_dev) && |
1570 | skb->protocol == htons(ETH_P_IP) && | ||
1570 | (IN_DEV_SHARED_MEDIA(out_dev) || | 1571 | (IN_DEV_SHARED_MEDIA(out_dev) || |
1571 | inet_addr_onlink(out_dev, saddr, FIB_RES_GW(*res)))) { | 1572 | inet_addr_onlink(out_dev, saddr, FIB_RES_GW(*res)))) |
1572 | flags |= RTCF_DOREDIRECT; | 1573 | IPCB(skb)->flags |= IPSKB_DOREDIRECT; |
1573 | do_cache = false; | ||
1574 | } | ||
1575 | 1574 | ||
1576 | if (skb->protocol != htons(ETH_P_IP)) { | 1575 | if (skb->protocol != htons(ETH_P_IP)) { |
1577 | /* Not IP (i.e. ARP). Do not create route, if it is | 1576 | /* Not IP (i.e. ARP). Do not create route, if it is |
@@ -2316,6 +2315,8 @@ static int rt_fill_info(struct net *net, __be32 dst, __be32 src, | |||
2316 | r->rtm_flags = (rt->rt_flags & ~0xFFFF) | RTM_F_CLONED; | 2315 | r->rtm_flags = (rt->rt_flags & ~0xFFFF) | RTM_F_CLONED; |
2317 | if (rt->rt_flags & RTCF_NOTIFY) | 2316 | if (rt->rt_flags & RTCF_NOTIFY) |
2318 | r->rtm_flags |= RTM_F_NOTIFY; | 2317 | r->rtm_flags |= RTM_F_NOTIFY; |
2318 | if (IPCB(skb)->flags & IPSKB_DOREDIRECT) | ||
2319 | r->rtm_flags |= RTCF_DOREDIRECT; | ||
2319 | 2320 | ||
2320 | if (nla_put_be32(skb, RTA_DST, dst)) | 2321 | if (nla_put_be32(skb, RTA_DST, dst)) |
2321 | goto nla_put_failure; | 2322 | goto nla_put_failure; |
diff --git a/net/ipv4/udp_diag.c b/net/ipv4/udp_diag.c index 7927db0a9279..4a000f1dd757 100644 --- a/net/ipv4/udp_diag.c +++ b/net/ipv4/udp_diag.c | |||
@@ -99,11 +99,13 @@ static void udp_dump(struct udp_table *table, struct sk_buff *skb, struct netlin | |||
99 | s_slot = cb->args[0]; | 99 | s_slot = cb->args[0]; |
100 | num = s_num = cb->args[1]; | 100 | num = s_num = cb->args[1]; |
101 | 101 | ||
102 | for (slot = s_slot; slot <= table->mask; num = s_num = 0, slot++) { | 102 | for (slot = s_slot; slot <= table->mask; s_num = 0, slot++) { |
103 | struct sock *sk; | 103 | struct sock *sk; |
104 | struct hlist_nulls_node *node; | 104 | struct hlist_nulls_node *node; |
105 | struct udp_hslot *hslot = &table->hash[slot]; | 105 | struct udp_hslot *hslot = &table->hash[slot]; |
106 | 106 | ||
107 | num = 0; | ||
108 | |||
107 | if (hlist_nulls_empty(&hslot->head)) | 109 | if (hlist_nulls_empty(&hslot->head)) |
108 | continue; | 110 | continue; |
109 | 111 | ||
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 100c589a2a6c..49f5e73db122 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c | |||
@@ -393,11 +393,10 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) | |||
393 | 393 | ||
394 | memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err)); | 394 | memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err)); |
395 | sin = &errhdr.offender; | 395 | sin = &errhdr.offender; |
396 | sin->sin6_family = AF_UNSPEC; | 396 | memset(sin, 0, sizeof(*sin)); |
397 | |||
397 | if (serr->ee.ee_origin != SO_EE_ORIGIN_LOCAL) { | 398 | if (serr->ee.ee_origin != SO_EE_ORIGIN_LOCAL) { |
398 | sin->sin6_family = AF_INET6; | 399 | sin->sin6_family = AF_INET6; |
399 | sin->sin6_flowinfo = 0; | ||
400 | sin->sin6_port = 0; | ||
401 | if (np->rxopt.all) { | 400 | if (np->rxopt.all) { |
402 | if (serr->ee.ee_origin != SO_EE_ORIGIN_ICMP && | 401 | if (serr->ee.ee_origin != SO_EE_ORIGIN_ICMP && |
403 | serr->ee.ee_origin != SO_EE_ORIGIN_ICMP6) | 402 | serr->ee.ee_origin != SO_EE_ORIGIN_ICMP6) |
@@ -412,12 +411,9 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) | |||
412 | ipv6_iface_scope_id(&sin->sin6_addr, | 411 | ipv6_iface_scope_id(&sin->sin6_addr, |
413 | IP6CB(skb)->iif); | 412 | IP6CB(skb)->iif); |
414 | } else { | 413 | } else { |
415 | struct inet_sock *inet = inet_sk(sk); | ||
416 | |||
417 | ipv6_addr_set_v4mapped(ip_hdr(skb)->saddr, | 414 | ipv6_addr_set_v4mapped(ip_hdr(skb)->saddr, |
418 | &sin->sin6_addr); | 415 | &sin->sin6_addr); |
419 | sin->sin6_scope_id = 0; | 416 | if (inet_sk(sk)->cmsg_flags) |
420 | if (inet->cmsg_flags) | ||
421 | ip_cmsg_recv(msg, skb); | 417 | ip_cmsg_recv(msg, skb); |
422 | } | 418 | } |
423 | } | 419 | } |
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 53775ee7d376..263ef4143bff 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c | |||
@@ -661,6 +661,29 @@ static int fib6_commit_metrics(struct dst_entry *dst, struct mx6_config *mxc) | |||
661 | return 0; | 661 | return 0; |
662 | } | 662 | } |
663 | 663 | ||
664 | static void fib6_purge_rt(struct rt6_info *rt, struct fib6_node *fn, | ||
665 | struct net *net) | ||
666 | { | ||
667 | if (atomic_read(&rt->rt6i_ref) != 1) { | ||
668 | /* This route is used as dummy address holder in some split | ||
669 | * nodes. It is not leaked, but it still holds other resources, | ||
670 | * which must be released in time. So, scan ascendant nodes | ||
671 | * and replace dummy references to this route with references | ||
672 | * to still alive ones. | ||
673 | */ | ||
674 | while (fn) { | ||
675 | if (!(fn->fn_flags & RTN_RTINFO) && fn->leaf == rt) { | ||
676 | fn->leaf = fib6_find_prefix(net, fn); | ||
677 | atomic_inc(&fn->leaf->rt6i_ref); | ||
678 | rt6_release(rt); | ||
679 | } | ||
680 | fn = fn->parent; | ||
681 | } | ||
682 | /* No more references are possible at this point. */ | ||
683 | BUG_ON(atomic_read(&rt->rt6i_ref) != 1); | ||
684 | } | ||
685 | } | ||
686 | |||
664 | /* | 687 | /* |
665 | * Insert routing information in a node. | 688 | * Insert routing information in a node. |
666 | */ | 689 | */ |
@@ -808,11 +831,12 @@ add: | |||
808 | rt->dst.rt6_next = iter->dst.rt6_next; | 831 | rt->dst.rt6_next = iter->dst.rt6_next; |
809 | atomic_inc(&rt->rt6i_ref); | 832 | atomic_inc(&rt->rt6i_ref); |
810 | inet6_rt_notify(RTM_NEWROUTE, rt, info); | 833 | inet6_rt_notify(RTM_NEWROUTE, rt, info); |
811 | rt6_release(iter); | ||
812 | if (!(fn->fn_flags & RTN_RTINFO)) { | 834 | if (!(fn->fn_flags & RTN_RTINFO)) { |
813 | info->nl_net->ipv6.rt6_stats->fib_route_nodes++; | 835 | info->nl_net->ipv6.rt6_stats->fib_route_nodes++; |
814 | fn->fn_flags |= RTN_RTINFO; | 836 | fn->fn_flags |= RTN_RTINFO; |
815 | } | 837 | } |
838 | fib6_purge_rt(iter, fn, info->nl_net); | ||
839 | rt6_release(iter); | ||
816 | } | 840 | } |
817 | 841 | ||
818 | return 0; | 842 | return 0; |
@@ -1323,24 +1347,7 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp, | |||
1323 | fn = fib6_repair_tree(net, fn); | 1347 | fn = fib6_repair_tree(net, fn); |
1324 | } | 1348 | } |
1325 | 1349 | ||
1326 | if (atomic_read(&rt->rt6i_ref) != 1) { | 1350 | fib6_purge_rt(rt, fn, net); |
1327 | /* This route is used as dummy address holder in some split | ||
1328 | * nodes. It is not leaked, but it still holds other resources, | ||
1329 | * which must be released in time. So, scan ascendant nodes | ||
1330 | * and replace dummy references to this route with references | ||
1331 | * to still alive ones. | ||
1332 | */ | ||
1333 | while (fn) { | ||
1334 | if (!(fn->fn_flags & RTN_RTINFO) && fn->leaf == rt) { | ||
1335 | fn->leaf = fib6_find_prefix(net, fn); | ||
1336 | atomic_inc(&fn->leaf->rt6i_ref); | ||
1337 | rt6_release(rt); | ||
1338 | } | ||
1339 | fn = fn->parent; | ||
1340 | } | ||
1341 | /* No more references are possible at this point. */ | ||
1342 | BUG_ON(atomic_read(&rt->rt6i_ref) != 1); | ||
1343 | } | ||
1344 | 1351 | ||
1345 | inet6_rt_notify(RTM_DELROUTE, rt, info); | 1352 | inet6_rt_notify(RTM_DELROUTE, rt, info); |
1346 | rt6_release(rt); | 1353 | rt6_release(rt); |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index c60f15775c53..7622951e5fbb 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -1160,12 +1160,9 @@ static void ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, | |||
1160 | struct net *net = dev_net(dst->dev); | 1160 | struct net *net = dev_net(dst->dev); |
1161 | 1161 | ||
1162 | rt6->rt6i_flags |= RTF_MODIFIED; | 1162 | rt6->rt6i_flags |= RTF_MODIFIED; |
1163 | if (mtu < IPV6_MIN_MTU) { | 1163 | if (mtu < IPV6_MIN_MTU) |
1164 | u32 features = dst_metric(dst, RTAX_FEATURES); | ||
1165 | mtu = IPV6_MIN_MTU; | 1164 | mtu = IPV6_MIN_MTU; |
1166 | features |= RTAX_FEATURE_ALLFRAG; | 1165 | |
1167 | dst_metric_set(dst, RTAX_FEATURES, features); | ||
1168 | } | ||
1169 | dst_metric_set(dst, RTAX_MTU, mtu); | 1166 | dst_metric_set(dst, RTAX_MTU, mtu); |
1170 | rt6_update_expires(rt6, net->ipv6.sysctl.ip6_rt_mtu_expires); | 1167 | rt6_update_expires(rt6, net->ipv6.sysctl.ip6_rt_mtu_expires); |
1171 | } | 1168 | } |
@@ -1245,12 +1242,16 @@ restart: | |||
1245 | rt = net->ipv6.ip6_null_entry; | 1242 | rt = net->ipv6.ip6_null_entry; |
1246 | else if (rt->dst.error) { | 1243 | else if (rt->dst.error) { |
1247 | rt = net->ipv6.ip6_null_entry; | 1244 | rt = net->ipv6.ip6_null_entry; |
1248 | } else if (rt == net->ipv6.ip6_null_entry) { | 1245 | goto out; |
1246 | } | ||
1247 | |||
1248 | if (rt == net->ipv6.ip6_null_entry) { | ||
1249 | fn = fib6_backtrack(fn, &fl6->saddr); | 1249 | fn = fib6_backtrack(fn, &fl6->saddr); |
1250 | if (fn) | 1250 | if (fn) |
1251 | goto restart; | 1251 | goto restart; |
1252 | } | 1252 | } |
1253 | 1253 | ||
1254 | out: | ||
1254 | dst_hold(&rt->dst); | 1255 | dst_hold(&rt->dst); |
1255 | 1256 | ||
1256 | read_unlock_bh(&table->tb6_lock); | 1257 | read_unlock_bh(&table->tb6_lock); |
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index 5f983644373a..48bf5a06847b 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c | |||
@@ -130,12 +130,18 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) | |||
130 | { | 130 | { |
131 | struct flowi6 *fl6 = &fl->u.ip6; | 131 | struct flowi6 *fl6 = &fl->u.ip6; |
132 | int onlyproto = 0; | 132 | int onlyproto = 0; |
133 | u16 offset = skb_network_header_len(skb); | ||
134 | const struct ipv6hdr *hdr = ipv6_hdr(skb); | 133 | const struct ipv6hdr *hdr = ipv6_hdr(skb); |
134 | u16 offset = sizeof(*hdr); | ||
135 | struct ipv6_opt_hdr *exthdr; | 135 | struct ipv6_opt_hdr *exthdr; |
136 | const unsigned char *nh = skb_network_header(skb); | 136 | const unsigned char *nh = skb_network_header(skb); |
137 | u8 nexthdr = nh[IP6CB(skb)->nhoff]; | 137 | u16 nhoff = IP6CB(skb)->nhoff; |
138 | int oif = 0; | 138 | int oif = 0; |
139 | u8 nexthdr; | ||
140 | |||
141 | if (!nhoff) | ||
142 | nhoff = offsetof(struct ipv6hdr, nexthdr); | ||
143 | |||
144 | nexthdr = nh[nhoff]; | ||
139 | 145 | ||
140 | if (skb_dst(skb)) | 146 | if (skb_dst(skb)) |
141 | oif = skb_dst(skb)->dev->ifindex; | 147 | oif = skb_dst(skb)->dev->ifindex; |
diff --git a/net/llc/sysctl_net_llc.c b/net/llc/sysctl_net_llc.c index 612a5ddaf93b..799bafc2af39 100644 --- a/net/llc/sysctl_net_llc.c +++ b/net/llc/sysctl_net_llc.c | |||
@@ -18,28 +18,28 @@ static struct ctl_table llc2_timeout_table[] = { | |||
18 | { | 18 | { |
19 | .procname = "ack", | 19 | .procname = "ack", |
20 | .data = &sysctl_llc2_ack_timeout, | 20 | .data = &sysctl_llc2_ack_timeout, |
21 | .maxlen = sizeof(long), | 21 | .maxlen = sizeof(sysctl_llc2_ack_timeout), |
22 | .mode = 0644, | 22 | .mode = 0644, |
23 | .proc_handler = proc_dointvec_jiffies, | 23 | .proc_handler = proc_dointvec_jiffies, |
24 | }, | 24 | }, |
25 | { | 25 | { |
26 | .procname = "busy", | 26 | .procname = "busy", |
27 | .data = &sysctl_llc2_busy_timeout, | 27 | .data = &sysctl_llc2_busy_timeout, |
28 | .maxlen = sizeof(long), | 28 | .maxlen = sizeof(sysctl_llc2_busy_timeout), |
29 | .mode = 0644, | 29 | .mode = 0644, |
30 | .proc_handler = proc_dointvec_jiffies, | 30 | .proc_handler = proc_dointvec_jiffies, |
31 | }, | 31 | }, |
32 | { | 32 | { |
33 | .procname = "p", | 33 | .procname = "p", |
34 | .data = &sysctl_llc2_p_timeout, | 34 | .data = &sysctl_llc2_p_timeout, |
35 | .maxlen = sizeof(long), | 35 | .maxlen = sizeof(sysctl_llc2_p_timeout), |
36 | .mode = 0644, | 36 | .mode = 0644, |
37 | .proc_handler = proc_dointvec_jiffies, | 37 | .proc_handler = proc_dointvec_jiffies, |
38 | }, | 38 | }, |
39 | { | 39 | { |
40 | .procname = "rej", | 40 | .procname = "rej", |
41 | .data = &sysctl_llc2_rej_timeout, | 41 | .data = &sysctl_llc2_rej_timeout, |
42 | .maxlen = sizeof(long), | 42 | .maxlen = sizeof(sysctl_llc2_rej_timeout), |
43 | .mode = 0644, | 43 | .mode = 0644, |
44 | .proc_handler = proc_dointvec_jiffies, | 44 | .proc_handler = proc_dointvec_jiffies, |
45 | }, | 45 | }, |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 1875181ebd94..c1460e635c7f 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -1651,7 +1651,7 @@ __ieee80211_sta_handle_tspec_ac_params(struct ieee80211_sub_if_data *sdata) | |||
1651 | { | 1651 | { |
1652 | struct ieee80211_local *local = sdata->local; | 1652 | struct ieee80211_local *local = sdata->local; |
1653 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 1653 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
1654 | bool ret; | 1654 | bool ret = false; |
1655 | int ac; | 1655 | int ac; |
1656 | 1656 | ||
1657 | if (local->hw.queues < IEEE80211_NUM_ACS) | 1657 | if (local->hw.queues < IEEE80211_NUM_ACS) |
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 8c8c67819072..ca405b6b686d 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c | |||
@@ -86,20 +86,6 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
86 | } | 86 | } |
87 | } | 87 | } |
88 | 88 | ||
89 | /* tear down aggregation sessions and remove STAs */ | ||
90 | mutex_lock(&local->sta_mtx); | ||
91 | list_for_each_entry(sta, &local->sta_list, list) { | ||
92 | if (sta->uploaded) { | ||
93 | enum ieee80211_sta_state state; | ||
94 | |||
95 | state = sta->sta_state; | ||
96 | for (; state > IEEE80211_STA_NOTEXIST; state--) | ||
97 | WARN_ON(drv_sta_state(local, sta->sdata, sta, | ||
98 | state, state - 1)); | ||
99 | } | ||
100 | } | ||
101 | mutex_unlock(&local->sta_mtx); | ||
102 | |||
103 | /* remove all interfaces that were created in the driver */ | 89 | /* remove all interfaces that were created in the driver */ |
104 | list_for_each_entry(sdata, &local->interfaces, list) { | 90 | list_for_each_entry(sdata, &local->interfaces, list) { |
105 | if (!ieee80211_sdata_running(sdata)) | 91 | if (!ieee80211_sdata_running(sdata)) |
@@ -111,6 +97,21 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
111 | case NL80211_IFTYPE_STATION: | 97 | case NL80211_IFTYPE_STATION: |
112 | ieee80211_mgd_quiesce(sdata); | 98 | ieee80211_mgd_quiesce(sdata); |
113 | break; | 99 | break; |
100 | case NL80211_IFTYPE_WDS: | ||
101 | /* tear down aggregation sessions and remove STAs */ | ||
102 | mutex_lock(&local->sta_mtx); | ||
103 | sta = sdata->u.wds.sta; | ||
104 | if (sta && sta->uploaded) { | ||
105 | enum ieee80211_sta_state state; | ||
106 | |||
107 | state = sta->sta_state; | ||
108 | for (; state > IEEE80211_STA_NOTEXIST; state--) | ||
109 | WARN_ON(drv_sta_state(local, sta->sdata, | ||
110 | sta, state, | ||
111 | state - 1)); | ||
112 | } | ||
113 | mutex_unlock(&local->sta_mtx); | ||
114 | break; | ||
114 | default: | 115 | default: |
115 | break; | 116 | break; |
116 | } | 117 | } |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 3d79d498e7f6..9491e8689a9d 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -272,7 +272,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
272 | else if (rate && rate->flags & IEEE80211_RATE_ERP_G) | 272 | else if (rate && rate->flags & IEEE80211_RATE_ERP_G) |
273 | channel_flags |= IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ; | 273 | channel_flags |= IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ; |
274 | else if (rate) | 274 | else if (rate) |
275 | channel_flags |= IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ; | 275 | channel_flags |= IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ; |
276 | else | 276 | else |
277 | channel_flags |= IEEE80211_CHAN_2GHZ; | 277 | channel_flags |= IEEE80211_CHAN_2GHZ; |
278 | put_unaligned_le16(channel_flags, pos); | 278 | put_unaligned_le16(channel_flags, pos); |
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index d77b3467b1d4..2197af00673a 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
@@ -61,6 +61,7 @@ | |||
61 | #include <linux/rhashtable.h> | 61 | #include <linux/rhashtable.h> |
62 | #include <asm/cacheflush.h> | 62 | #include <asm/cacheflush.h> |
63 | #include <linux/hash.h> | 63 | #include <linux/hash.h> |
64 | #include <linux/genetlink.h> | ||
64 | 65 | ||
65 | #include <net/net_namespace.h> | 66 | #include <net/net_namespace.h> |
66 | #include <net/sock.h> | 67 | #include <net/sock.h> |
@@ -1091,6 +1092,8 @@ static void netlink_remove(struct sock *sk) | |||
1091 | __sk_del_bind_node(sk); | 1092 | __sk_del_bind_node(sk); |
1092 | netlink_update_listeners(sk); | 1093 | netlink_update_listeners(sk); |
1093 | } | 1094 | } |
1095 | if (sk->sk_protocol == NETLINK_GENERIC) | ||
1096 | atomic_inc(&genl_sk_destructing_cnt); | ||
1094 | netlink_table_ungrab(); | 1097 | netlink_table_ungrab(); |
1095 | } | 1098 | } |
1096 | 1099 | ||
@@ -1214,6 +1217,20 @@ static int netlink_release(struct socket *sock) | |||
1214 | * will be purged. | 1217 | * will be purged. |
1215 | */ | 1218 | */ |
1216 | 1219 | ||
1220 | /* must not acquire netlink_table_lock in any way again before unbind | ||
1221 | * and notifying genetlink is done as otherwise it might deadlock | ||
1222 | */ | ||
1223 | if (nlk->netlink_unbind) { | ||
1224 | int i; | ||
1225 | |||
1226 | for (i = 0; i < nlk->ngroups; i++) | ||
1227 | if (test_bit(i, nlk->groups)) | ||
1228 | nlk->netlink_unbind(sock_net(sk), i + 1); | ||
1229 | } | ||
1230 | if (sk->sk_protocol == NETLINK_GENERIC && | ||
1231 | atomic_dec_return(&genl_sk_destructing_cnt) == 0) | ||
1232 | wake_up(&genl_sk_destructing_waitq); | ||
1233 | |||
1217 | sock->sk = NULL; | 1234 | sock->sk = NULL; |
1218 | wake_up_interruptible_all(&nlk->wait); | 1235 | wake_up_interruptible_all(&nlk->wait); |
1219 | 1236 | ||
@@ -1249,13 +1266,6 @@ static int netlink_release(struct socket *sock) | |||
1249 | netlink_table_ungrab(); | 1266 | netlink_table_ungrab(); |
1250 | } | 1267 | } |
1251 | 1268 | ||
1252 | if (nlk->netlink_unbind) { | ||
1253 | int i; | ||
1254 | |||
1255 | for (i = 0; i < nlk->ngroups; i++) | ||
1256 | if (test_bit(i, nlk->groups)) | ||
1257 | nlk->netlink_unbind(sock_net(sk), i + 1); | ||
1258 | } | ||
1259 | kfree(nlk->groups); | 1269 | kfree(nlk->groups); |
1260 | nlk->groups = NULL; | 1270 | nlk->groups = NULL; |
1261 | 1271 | ||
diff --git a/net/netlink/af_netlink.h b/net/netlink/af_netlink.h index 7518375782f5..89008405d6b4 100644 --- a/net/netlink/af_netlink.h +++ b/net/netlink/af_netlink.h | |||
@@ -2,6 +2,7 @@ | |||
2 | #define _AF_NETLINK_H | 2 | #define _AF_NETLINK_H |
3 | 3 | ||
4 | #include <linux/rhashtable.h> | 4 | #include <linux/rhashtable.h> |
5 | #include <linux/atomic.h> | ||
5 | #include <net/sock.h> | 6 | #include <net/sock.h> |
6 | 7 | ||
7 | #define NLGRPSZ(x) (ALIGN(x, sizeof(unsigned long) * 8) / 8) | 8 | #define NLGRPSZ(x) (ALIGN(x, sizeof(unsigned long) * 8) / 8) |
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index f52a7d5734cd..2ed5f964772e 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c | |||
@@ -23,6 +23,9 @@ | |||
23 | static DEFINE_MUTEX(genl_mutex); /* serialization of message processing */ | 23 | static DEFINE_MUTEX(genl_mutex); /* serialization of message processing */ |
24 | static DECLARE_RWSEM(cb_lock); | 24 | static DECLARE_RWSEM(cb_lock); |
25 | 25 | ||
26 | atomic_t genl_sk_destructing_cnt = ATOMIC_INIT(0); | ||
27 | DECLARE_WAIT_QUEUE_HEAD(genl_sk_destructing_waitq); | ||
28 | |||
26 | void genl_lock(void) | 29 | void genl_lock(void) |
27 | { | 30 | { |
28 | mutex_lock(&genl_mutex); | 31 | mutex_lock(&genl_mutex); |
@@ -435,15 +438,18 @@ int genl_unregister_family(struct genl_family *family) | |||
435 | 438 | ||
436 | genl_lock_all(); | 439 | genl_lock_all(); |
437 | 440 | ||
438 | genl_unregister_mc_groups(family); | ||
439 | |||
440 | list_for_each_entry(rc, genl_family_chain(family->id), family_list) { | 441 | list_for_each_entry(rc, genl_family_chain(family->id), family_list) { |
441 | if (family->id != rc->id || strcmp(rc->name, family->name)) | 442 | if (family->id != rc->id || strcmp(rc->name, family->name)) |
442 | continue; | 443 | continue; |
443 | 444 | ||
445 | genl_unregister_mc_groups(family); | ||
446 | |||
444 | list_del(&rc->family_list); | 447 | list_del(&rc->family_list); |
445 | family->n_ops = 0; | 448 | family->n_ops = 0; |
446 | genl_unlock_all(); | 449 | up_write(&cb_lock); |
450 | wait_event(genl_sk_destructing_waitq, | ||
451 | atomic_read(&genl_sk_destructing_cnt) == 0); | ||
452 | genl_unlock(); | ||
447 | 453 | ||
448 | kfree(family->attrbuf); | 454 | kfree(family->attrbuf); |
449 | genl_ctrl_event(CTRL_CMD_DELFAMILY, family, NULL, 0); | 455 | genl_ctrl_event(CTRL_CMD_DELFAMILY, family, NULL, 0); |
@@ -987,7 +993,7 @@ static struct genl_multicast_group genl_ctrl_groups[] = { | |||
987 | 993 | ||
988 | static int genl_bind(struct net *net, int group) | 994 | static int genl_bind(struct net *net, int group) |
989 | { | 995 | { |
990 | int i, err = 0; | 996 | int i, err = -ENOENT; |
991 | 997 | ||
992 | down_read(&cb_lock); | 998 | down_read(&cb_lock); |
993 | for (i = 0; i < GENL_FAM_TAB_SIZE; i++) { | 999 | for (i = 0; i < GENL_FAM_TAB_SIZE; i++) { |
@@ -1016,7 +1022,6 @@ static int genl_bind(struct net *net, int group) | |||
1016 | static void genl_unbind(struct net *net, int group) | 1022 | static void genl_unbind(struct net *net, int group) |
1017 | { | 1023 | { |
1018 | int i; | 1024 | int i; |
1019 | bool found = false; | ||
1020 | 1025 | ||
1021 | down_read(&cb_lock); | 1026 | down_read(&cb_lock); |
1022 | for (i = 0; i < GENL_FAM_TAB_SIZE; i++) { | 1027 | for (i = 0; i < GENL_FAM_TAB_SIZE; i++) { |
@@ -1029,14 +1034,11 @@ static void genl_unbind(struct net *net, int group) | |||
1029 | 1034 | ||
1030 | if (f->mcast_unbind) | 1035 | if (f->mcast_unbind) |
1031 | f->mcast_unbind(net, fam_grp); | 1036 | f->mcast_unbind(net, fam_grp); |
1032 | found = true; | ||
1033 | break; | 1037 | break; |
1034 | } | 1038 | } |
1035 | } | 1039 | } |
1036 | } | 1040 | } |
1037 | up_read(&cb_lock); | 1041 | up_read(&cb_lock); |
1038 | |||
1039 | WARN_ON(!found); | ||
1040 | } | 1042 | } |
1041 | 1043 | ||
1042 | static int __net_init genl_pernet_init(struct net *net) | 1044 | static int __net_init genl_pernet_init(struct net *net) |
diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c index 1029923f9e86..5f3ee9e4b5bf 100644 --- a/net/sched/cls_bpf.c +++ b/net/sched/cls_bpf.c | |||
@@ -180,6 +180,11 @@ static int cls_bpf_modify_existing(struct net *net, struct tcf_proto *tp, | |||
180 | } | 180 | } |
181 | 181 | ||
182 | bpf_size = bpf_num_ops * sizeof(*bpf_ops); | 182 | bpf_size = bpf_num_ops * sizeof(*bpf_ops); |
183 | if (bpf_size != nla_len(tb[TCA_BPF_OPS])) { | ||
184 | ret = -EINVAL; | ||
185 | goto errout; | ||
186 | } | ||
187 | |||
183 | bpf_ops = kzalloc(bpf_size, GFP_KERNEL); | 188 | bpf_ops = kzalloc(bpf_size, GFP_KERNEL); |
184 | if (bpf_ops == NULL) { | 189 | if (bpf_ops == NULL) { |
185 | ret = -ENOMEM; | 190 | ret = -ENOMEM; |
@@ -215,15 +220,21 @@ static u32 cls_bpf_grab_new_handle(struct tcf_proto *tp, | |||
215 | struct cls_bpf_head *head) | 220 | struct cls_bpf_head *head) |
216 | { | 221 | { |
217 | unsigned int i = 0x80000000; | 222 | unsigned int i = 0x80000000; |
223 | u32 handle; | ||
218 | 224 | ||
219 | do { | 225 | do { |
220 | if (++head->hgen == 0x7FFFFFFF) | 226 | if (++head->hgen == 0x7FFFFFFF) |
221 | head->hgen = 1; | 227 | head->hgen = 1; |
222 | } while (--i > 0 && cls_bpf_get(tp, head->hgen)); | 228 | } while (--i > 0 && cls_bpf_get(tp, head->hgen)); |
223 | if (i == 0) | 229 | |
230 | if (unlikely(i == 0)) { | ||
224 | pr_err("Insufficient number of handles\n"); | 231 | pr_err("Insufficient number of handles\n"); |
232 | handle = 0; | ||
233 | } else { | ||
234 | handle = head->hgen; | ||
235 | } | ||
225 | 236 | ||
226 | return i; | 237 | return handle; |
227 | } | 238 | } |
228 | 239 | ||
229 | static int cls_bpf_change(struct net *net, struct sk_buff *in_skb, | 240 | static int cls_bpf_change(struct net *net, struct sk_buff *in_skb, |
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index f791edd64d6c..26d06dbcc1c8 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c | |||
@@ -1182,7 +1182,6 @@ void sctp_assoc_update(struct sctp_association *asoc, | |||
1182 | asoc->peer.peer_hmacs = new->peer.peer_hmacs; | 1182 | asoc->peer.peer_hmacs = new->peer.peer_hmacs; |
1183 | new->peer.peer_hmacs = NULL; | 1183 | new->peer.peer_hmacs = NULL; |
1184 | 1184 | ||
1185 | sctp_auth_key_put(asoc->asoc_shared_key); | ||
1186 | sctp_auth_asoc_init_active_key(asoc, GFP_ATOMIC); | 1185 | sctp_auth_asoc_init_active_key(asoc, GFP_ATOMIC); |
1187 | } | 1186 | } |
1188 | 1187 | ||
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 2625eccb77d5..aafe94bf292e 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -1603,7 +1603,7 @@ static int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
1603 | sctp_assoc_t associd = 0; | 1603 | sctp_assoc_t associd = 0; |
1604 | sctp_cmsgs_t cmsgs = { NULL }; | 1604 | sctp_cmsgs_t cmsgs = { NULL }; |
1605 | sctp_scope_t scope; | 1605 | sctp_scope_t scope; |
1606 | bool fill_sinfo_ttl = false; | 1606 | bool fill_sinfo_ttl = false, wait_connect = false; |
1607 | struct sctp_datamsg *datamsg; | 1607 | struct sctp_datamsg *datamsg; |
1608 | int msg_flags = msg->msg_flags; | 1608 | int msg_flags = msg->msg_flags; |
1609 | __u16 sinfo_flags = 0; | 1609 | __u16 sinfo_flags = 0; |
@@ -1943,6 +1943,7 @@ static int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
1943 | if (err < 0) | 1943 | if (err < 0) |
1944 | goto out_free; | 1944 | goto out_free; |
1945 | 1945 | ||
1946 | wait_connect = true; | ||
1946 | pr_debug("%s: we associated primitively\n", __func__); | 1947 | pr_debug("%s: we associated primitively\n", __func__); |
1947 | } | 1948 | } |
1948 | 1949 | ||
@@ -1980,6 +1981,11 @@ static int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
1980 | sctp_datamsg_put(datamsg); | 1981 | sctp_datamsg_put(datamsg); |
1981 | err = msg_len; | 1982 | err = msg_len; |
1982 | 1983 | ||
1984 | if (unlikely(wait_connect)) { | ||
1985 | timeo = sock_sndtimeo(sk, msg_flags & MSG_DONTWAIT); | ||
1986 | sctp_wait_for_connect(asoc, &timeo); | ||
1987 | } | ||
1988 | |||
1983 | /* If we are already past ASSOCIATE, the lower | 1989 | /* If we are already past ASSOCIATE, the lower |
1984 | * layers are responsible for association cleanup. | 1990 | * layers are responsible for association cleanup. |
1985 | */ | 1991 | */ |
diff --git a/net/socket.c b/net/socket.c index 9fcf15b61009..3acd35f144d6 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -869,9 +869,6 @@ static ssize_t sock_splice_read(struct file *file, loff_t *ppos, | |||
869 | static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb, | 869 | static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb, |
870 | struct sock_iocb *siocb) | 870 | struct sock_iocb *siocb) |
871 | { | 871 | { |
872 | if (!is_sync_kiocb(iocb)) | ||
873 | BUG(); | ||
874 | |||
875 | siocb->kiocb = iocb; | 872 | siocb->kiocb = iocb; |
876 | iocb->private = siocb; | 873 | iocb->private = siocb; |
877 | return siocb; | 874 | return siocb; |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 4fc812f2b583..7d60f4bf95d2 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -2871,6 +2871,9 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info) | |||
2871 | if (!rdev->ops->get_key) | 2871 | if (!rdev->ops->get_key) |
2872 | return -EOPNOTSUPP; | 2872 | return -EOPNOTSUPP; |
2873 | 2873 | ||
2874 | if (!pairwise && mac_addr && !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN)) | ||
2875 | return -ENOENT; | ||
2876 | |||
2874 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | 2877 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); |
2875 | if (!msg) | 2878 | if (!msg) |
2876 | return -ENOMEM; | 2879 | return -ENOMEM; |
@@ -2890,10 +2893,6 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info) | |||
2890 | nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr)) | 2893 | nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr)) |
2891 | goto nla_put_failure; | 2894 | goto nla_put_failure; |
2892 | 2895 | ||
2893 | if (pairwise && mac_addr && | ||
2894 | !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN)) | ||
2895 | return -ENOENT; | ||
2896 | |||
2897 | err = rdev_get_key(rdev, dev, key_idx, pairwise, mac_addr, &cookie, | 2896 | err = rdev_get_key(rdev, dev, key_idx, pairwise, mac_addr, &cookie, |
2898 | get_key_callback); | 2897 | get_key_callback); |
2899 | 2898 | ||
@@ -3064,7 +3063,7 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info) | |||
3064 | wdev_lock(dev->ieee80211_ptr); | 3063 | wdev_lock(dev->ieee80211_ptr); |
3065 | err = nl80211_key_allowed(dev->ieee80211_ptr); | 3064 | err = nl80211_key_allowed(dev->ieee80211_ptr); |
3066 | 3065 | ||
3067 | if (key.type == NL80211_KEYTYPE_PAIRWISE && mac_addr && | 3066 | if (key.type == NL80211_KEYTYPE_GROUP && mac_addr && |
3068 | !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN)) | 3067 | !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN)) |
3069 | err = -ENOENT; | 3068 | err = -ENOENT; |
3070 | 3069 | ||
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 886cc7cb5566..b586d0dcb09e 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -1533,45 +1533,40 @@ static void reg_call_notifier(struct wiphy *wiphy, | |||
1533 | 1533 | ||
1534 | static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev) | 1534 | static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev) |
1535 | { | 1535 | { |
1536 | struct ieee80211_channel *ch; | ||
1537 | struct cfg80211_chan_def chandef; | 1536 | struct cfg80211_chan_def chandef; |
1538 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); | 1537 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); |
1539 | bool ret = true; | 1538 | enum nl80211_iftype iftype; |
1540 | 1539 | ||
1541 | wdev_lock(wdev); | 1540 | wdev_lock(wdev); |
1541 | iftype = wdev->iftype; | ||
1542 | 1542 | ||
1543 | /* make sure the interface is active */ | ||
1543 | if (!wdev->netdev || !netif_running(wdev->netdev)) | 1544 | if (!wdev->netdev || !netif_running(wdev->netdev)) |
1544 | goto out; | 1545 | goto wdev_inactive_unlock; |
1545 | 1546 | ||
1546 | switch (wdev->iftype) { | 1547 | switch (iftype) { |
1547 | case NL80211_IFTYPE_AP: | 1548 | case NL80211_IFTYPE_AP: |
1548 | case NL80211_IFTYPE_P2P_GO: | 1549 | case NL80211_IFTYPE_P2P_GO: |
1549 | if (!wdev->beacon_interval) | 1550 | if (!wdev->beacon_interval) |
1550 | goto out; | 1551 | goto wdev_inactive_unlock; |
1551 | 1552 | chandef = wdev->chandef; | |
1552 | ret = cfg80211_reg_can_beacon(wiphy, | ||
1553 | &wdev->chandef, wdev->iftype); | ||
1554 | break; | 1553 | break; |
1555 | case NL80211_IFTYPE_ADHOC: | 1554 | case NL80211_IFTYPE_ADHOC: |
1556 | if (!wdev->ssid_len) | 1555 | if (!wdev->ssid_len) |
1557 | goto out; | 1556 | goto wdev_inactive_unlock; |
1558 | 1557 | chandef = wdev->chandef; | |
1559 | ret = cfg80211_reg_can_beacon(wiphy, | ||
1560 | &wdev->chandef, wdev->iftype); | ||
1561 | break; | 1558 | break; |
1562 | case NL80211_IFTYPE_STATION: | 1559 | case NL80211_IFTYPE_STATION: |
1563 | case NL80211_IFTYPE_P2P_CLIENT: | 1560 | case NL80211_IFTYPE_P2P_CLIENT: |
1564 | if (!wdev->current_bss || | 1561 | if (!wdev->current_bss || |
1565 | !wdev->current_bss->pub.channel) | 1562 | !wdev->current_bss->pub.channel) |
1566 | goto out; | 1563 | goto wdev_inactive_unlock; |
1567 | 1564 | ||
1568 | ch = wdev->current_bss->pub.channel; | 1565 | if (!rdev->ops->get_channel || |
1569 | if (rdev->ops->get_channel && | 1566 | rdev_get_channel(rdev, wdev, &chandef)) |
1570 | !rdev_get_channel(rdev, wdev, &chandef)) | 1567 | cfg80211_chandef_create(&chandef, |
1571 | ret = cfg80211_chandef_usable(wiphy, &chandef, | 1568 | wdev->current_bss->pub.channel, |
1572 | IEEE80211_CHAN_DISABLED); | 1569 | NL80211_CHAN_NO_HT); |
1573 | else | ||
1574 | ret = !(ch->flags & IEEE80211_CHAN_DISABLED); | ||
1575 | break; | 1570 | break; |
1576 | case NL80211_IFTYPE_MONITOR: | 1571 | case NL80211_IFTYPE_MONITOR: |
1577 | case NL80211_IFTYPE_AP_VLAN: | 1572 | case NL80211_IFTYPE_AP_VLAN: |
@@ -1584,9 +1579,26 @@ static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev) | |||
1584 | break; | 1579 | break; |
1585 | } | 1580 | } |
1586 | 1581 | ||
1587 | out: | ||
1588 | wdev_unlock(wdev); | 1582 | wdev_unlock(wdev); |
1589 | return ret; | 1583 | |
1584 | switch (iftype) { | ||
1585 | case NL80211_IFTYPE_AP: | ||
1586 | case NL80211_IFTYPE_P2P_GO: | ||
1587 | case NL80211_IFTYPE_ADHOC: | ||
1588 | return cfg80211_reg_can_beacon(wiphy, &chandef, iftype); | ||
1589 | case NL80211_IFTYPE_STATION: | ||
1590 | case NL80211_IFTYPE_P2P_CLIENT: | ||
1591 | return cfg80211_chandef_usable(wiphy, &chandef, | ||
1592 | IEEE80211_CHAN_DISABLED); | ||
1593 | default: | ||
1594 | break; | ||
1595 | } | ||
1596 | |||
1597 | return true; | ||
1598 | |||
1599 | wdev_inactive_unlock: | ||
1600 | wdev_unlock(wdev); | ||
1601 | return true; | ||
1590 | } | 1602 | } |
1591 | 1603 | ||
1592 | static void reg_leave_invalid_chans(struct wiphy *wiphy) | 1604 | static void reg_leave_invalid_chans(struct wiphy *wiphy) |
diff --git a/net/wireless/util.c b/net/wireless/util.c index 97c744eeac4f..0d1966d54aaa 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -308,6 +308,12 @@ unsigned int __attribute_const__ ieee80211_hdrlen(__le16 fc) | |||
308 | goto out; | 308 | goto out; |
309 | } | 309 | } |
310 | 310 | ||
311 | if (ieee80211_is_mgmt(fc)) { | ||
312 | if (ieee80211_has_order(fc)) | ||
313 | hdrlen += IEEE80211_HT_CTL_LEN; | ||
314 | goto out; | ||
315 | } | ||
316 | |||
311 | if (ieee80211_is_ctl(fc)) { | 317 | if (ieee80211_is_ctl(fc)) { |
312 | /* | 318 | /* |
313 | * ACK and CTS are 10 bytes, all others 16. To see how | 319 | * ACK and CTS are 10 bytes, all others 16. To see how |