diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/tcp_minisocks.c | 1 | ||||
-rw-r--r-- | net/ipv4/udp.c | 73 | ||||
-rw-r--r-- | net/mac80211/ibss.c | 4 | ||||
-rw-r--r-- | net/mac80211/rx.c | 12 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 2 | ||||
-rw-r--r-- | net/mac80211/tx.c | 3 | ||||
-rw-r--r-- | net/mac80211/util.c | 4 | ||||
-rw-r--r-- | net/sched/act_pedit.c | 2 | ||||
-rw-r--r-- | net/sched/cls_api.c | 2 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 3 |
10 files changed, 66 insertions, 40 deletions
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 624c3c9b3c2..e320afea07f 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -644,6 +644,7 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb, /* If TCP_DEFER_ACCEPT is set, drop bare ACK. */ if (inet_csk(sk)->icsk_accept_queue.rskq_defer_accept && TCP_SKB_CB(skb)->end_seq == tcp_rsk(req)->rcv_isn + 1) { + inet_csk(sk)->icsk_accept_queue.rskq_defer_accept--; inet_rsk(req)->acked = 1; return NULL; } diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 6ec6a8a4a22..d0d436d6216 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -841,6 +841,42 @@ out: return ret; } + +/** + * first_packet_length - return length of first packet in receive queue + * @sk: socket + * + * Drops all bad checksum frames, until a valid one is found. + * Returns the length of found skb, or 0 if none is found. + */ +static unsigned int first_packet_length(struct sock *sk) +{ + struct sk_buff_head list_kill, *rcvq = &sk->sk_receive_queue; + struct sk_buff *skb; + unsigned int res; + + __skb_queue_head_init(&list_kill); + + spin_lock_bh(&rcvq->lock); + while ((skb = skb_peek(rcvq)) != NULL && + udp_lib_checksum_complete(skb)) { + UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS, + IS_UDPLITE(sk)); + __skb_unlink(skb, rcvq); + __skb_queue_tail(&list_kill, skb); + } + res = skb ? skb->len : 0; + spin_unlock_bh(&rcvq->lock); + + if (!skb_queue_empty(&list_kill)) { + lock_sock(sk); + __skb_queue_purge(&list_kill); + sk_mem_reclaim_partial(sk); + release_sock(sk); + } + return res; +} + /* * IOCTL requests applicable to the UDP protocol */ @@ -857,21 +893,16 @@ int udp_ioctl(struct sock *sk, int cmd, unsigned long arg) case SIOCINQ: { - struct sk_buff *skb; - unsigned long amount; + unsigned int amount = first_packet_length(sk); - amount = 0; - spin_lock_bh(&sk->sk_receive_queue.lock); - skb = skb_peek(&sk->sk_receive_queue); - if (skb != NULL) { + if (amount) /* * We will only return the amount * of this packet since that is all * that will be read. */ - amount = skb->len - sizeof(struct udphdr); - } - spin_unlock_bh(&sk->sk_receive_queue.lock); + amount -= sizeof(struct udphdr); + return put_user(amount, (int __user *)arg); } @@ -1540,29 +1571,11 @@ unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait) { unsigned int mask = datagram_poll(file, sock, wait); struct sock *sk = sock->sk; - int is_lite = IS_UDPLITE(sk); /* Check for false positives due to checksum errors */ - if ((mask & POLLRDNORM) && - !(file->f_flags & O_NONBLOCK) && - !(sk->sk_shutdown & RCV_SHUTDOWN)) { - struct sk_buff_head *rcvq = &sk->sk_receive_queue; - struct sk_buff *skb; - - spin_lock_bh(&rcvq->lock); - while ((skb = skb_peek(rcvq)) != NULL && - udp_lib_checksum_complete(skb)) { - UDP_INC_STATS_BH(sock_net(sk), - UDP_MIB_INERRORS, is_lite); - __skb_unlink(skb, rcvq); - kfree_skb(skb); - } - spin_unlock_bh(&rcvq->lock); - - /* nothing to see, move along */ - if (skb == NULL) - mask &= ~(POLLIN | POLLRDNORM); - } + if ((mask & POLLRDNORM) && !(file->f_flags & O_NONBLOCK) && + !(sk->sk_shutdown & RCV_SHUTDOWN) && !first_packet_length(sk)) + mask &= ~(POLLIN | POLLRDNORM); return mask; diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 920ec8792f4..6eaf6982343 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -544,7 +544,7 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) "%pM\n", bss->cbss.bssid, ifibss->bssid); #endif /* CONFIG_MAC80211_IBSS_DEBUG */ - if (bss && memcmp(ifibss->bssid, bss->cbss.bssid, ETH_ALEN)) { + if (bss && !memcmp(ifibss->bssid, bss->cbss.bssid, ETH_ALEN)) { printk(KERN_DEBUG "%s: Selected IBSS BSSID %pM" " based on configured SSID\n", sdata->dev->name, bss->cbss.bssid); @@ -829,7 +829,7 @@ void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local) if (!sdata->u.ibss.ssid_len) continue; sdata->u.ibss.last_scan_completed = jiffies; - ieee80211_sta_find_ibss(sdata); + mod_timer(&sdata->u.ibss.timer, 0); } mutex_unlock(&local->iflist_mtx); } diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index c01588f9d45..7170bf4565a 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -2164,11 +2164,17 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, skb = rx.skb; - list_for_each_entry_rcu(sdata, &local->interfaces, list) { + if (rx.sdata && ieee80211_is_data(hdr->frame_control)) { + rx.flags |= IEEE80211_RX_RA_MATCH; + prepares = prepare_for_handlers(rx.sdata, &rx, hdr); + if (prepares) + prev = rx.sdata; + } else list_for_each_entry_rcu(sdata, &local->interfaces, list) { if (!netif_running(sdata->dev)) continue; - if (sdata->vif.type == NL80211_IFTYPE_MONITOR) + if (sdata->vif.type == NL80211_IFTYPE_MONITOR || + sdata->vif.type == NL80211_IFTYPE_AP_VLAN) continue; rx.flags |= IEEE80211_RX_RA_MATCH; @@ -2447,6 +2453,8 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb) struct ieee80211_supported_band *sband; struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); + WARN_ON_ONCE(softirq_count() == 0); + if (WARN_ON(status->band < 0 || status->band >= IEEE80211_NUM_BANDS)) goto drop; diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index eec001491e6..594f2318c3d 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -361,6 +361,7 @@ int sta_info_insert(struct sta_info *sta) u.ap); drv_sta_notify(local, &sdata->vif, STA_NOTIFY_ADD, &sta->sta); + sdata = sta->sdata; } #ifdef CONFIG_MAC80211_VERBOSE_DEBUG @@ -496,6 +497,7 @@ static void __sta_info_unlink(struct sta_info **sta) drv_sta_notify(local, &sdata->vif, STA_NOTIFY_REMOVE, &(*sta)->sta); + sdata = (*sta)->sdata; } if (ieee80211_vif_is_mesh(&sdata->vif)) { diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index fd402829661..db4bda681ec 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1704,7 +1704,8 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, if (!is_multicast_ether_addr(hdr.addr1)) { rcu_read_lock(); sta = sta_info_get(local, hdr.addr1); - if (sta) + /* XXX: in the future, use sdata to look up the sta */ + if (sta && sta->sdata == sdata) sta_flags = get_sta_flags(sta); rcu_read_unlock(); } diff --git a/net/mac80211/util.c b/net/mac80211/util.c index dd656432136..aeb65b3d229 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -339,7 +339,7 @@ void ieee80211_add_pending_skb(struct ieee80211_local *local, struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); if (WARN_ON(!info->control.vif)) { - kfree(skb); + kfree_skb(skb); return; } @@ -367,7 +367,7 @@ int ieee80211_add_pending_skbs(struct ieee80211_local *local, struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); if (WARN_ON(!info->control.vif)) { - kfree(skb); + kfree_skb(skb); continue; } diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c index 96c0ed115e2..6b0359a500e 100644 --- a/net/sched/act_pedit.c +++ b/net/sched/act_pedit.c @@ -34,7 +34,7 @@ static struct tcf_hashinfo pedit_hash_info = { }; static const struct nla_policy pedit_policy[TCA_PEDIT_MAX + 1] = { - [TCA_PEDIT_PARMS] = { .len = sizeof(struct tcf_pedit) }, + [TCA_PEDIT_PARMS] = { .len = sizeof(struct tc_pedit) }, }; static int tcf_pedit_init(struct nlattr *nla, struct nlattr *est, diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 6a536949cdc..7cf6c0fbc7a 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -350,7 +350,7 @@ static int tcf_fill_node(struct sk_buff *skb, struct tcf_proto *tp, tcm = NLMSG_DATA(nlh); tcm->tcm_family = AF_UNSPEC; tcm->tcm__pad1 = 0; - tcm->tcm__pad1 = 0; + tcm->tcm__pad2 = 0; tcm->tcm_ifindex = qdisc_dev(tp->q)->ifindex; tcm->tcm_parent = tp->classid; tcm->tcm_info = TC_H_MAKE(tp->prio, tp->protocol); diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index eddab097435..ca3c92a0a14 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -4029,7 +4029,7 @@ static int nl80211_wiphy_netns(struct sk_buff *skb, struct genl_info *info) rdev = cfg80211_get_dev_from_info(info); if (IS_ERR(rdev)) { err = PTR_ERR(rdev); - goto out; + goto out_rtnl; } net = get_net_ns_by_pid(pid); @@ -4049,6 +4049,7 @@ static int nl80211_wiphy_netns(struct sk_buff *skb, struct genl_info *info) put_net(net); out: cfg80211_unlock_rdev(rdev); + out_rtnl: rtnl_unlock(); return err; } |