diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/8021q/vlan.c | 20 | ||||
-rw-r--r-- | net/8021q/vlan.h | 5 | ||||
-rw-r--r-- | net/8021q/vlanproc.c | 5 | ||||
-rw-r--r-- | net/bluetooth/af_bluetooth.c | 40 | ||||
-rw-r--r-- | net/bluetooth/hci_sock.c | 2 | ||||
-rw-r--r-- | net/bluetooth/l2cap.c | 2 | ||||
-rw-r--r-- | net/bluetooth/rfcomm/core.c | 2 | ||||
-rw-r--r-- | net/bluetooth/rfcomm/sock.c | 2 | ||||
-rw-r--r-- | net/bluetooth/rfcomm/tty.c | 5 | ||||
-rw-r--r-- | net/bluetooth/sco.c | 2 | ||||
-rw-r--r-- | net/ipv4/inet_fragment.c | 3 | ||||
-rw-r--r-- | net/ipv4/ip_forward.c | 2 | ||||
-rw-r--r-- | net/ipv4/udp.c | 4 | ||||
-rw-r--r-- | net/ipv6/addrconf.c | 19 | ||||
-rw-r--r-- | net/ipv6/icmp.c | 4 | ||||
-rw-r--r-- | net/ipv6/ip6_input.c | 3 | ||||
-rw-r--r-- | net/ipv6/netfilter/nf_conntrack_reasm.c | 2 | ||||
-rw-r--r-- | net/llc/af_llc.c | 3 | ||||
-rw-r--r-- | net/llc/llc_c_ac.c | 47 | ||||
-rw-r--r-- | net/llc/llc_core.c | 9 | ||||
-rw-r--r-- | net/llc/llc_input.c | 6 | ||||
-rw-r--r-- | net/llc/llc_pdu.c | 2 | ||||
-rw-r--r-- | net/llc/llc_s_ac.c | 9 | ||||
-rw-r--r-- | net/llc/llc_sap.c | 27 | ||||
-rw-r--r-- | net/llc/llc_station.c | 19 | ||||
-rw-r--r-- | net/mac80211/ieee80211.c | 12 | ||||
-rw-r--r-- | net/mac80211/ieee80211_sta.c | 9 | ||||
-rw-r--r-- | net/rose/af_rose.c | 9 | ||||
-rw-r--r-- | net/sched/sch_generic.c | 18 |
29 files changed, 218 insertions, 74 deletions
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index 694be86e449..5975ec3be7f 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c @@ -384,17 +384,35 @@ static void vlan_sync_address(struct net_device *dev, memcpy(vlan->real_dev_addr, dev->dev_addr, ETH_ALEN); } +static void __vlan_device_event(struct net_device *dev, unsigned long event) +{ + switch (event) { + case NETDEV_CHANGENAME: + vlan_proc_rem_dev(dev); + if (vlan_proc_add_dev(dev) < 0) + pr_warning("8021q: failed to change proc name for %s\n", + dev->name); + break; + } +} + static int vlan_device_event(struct notifier_block *unused, unsigned long event, void *ptr) { struct net_device *dev = ptr; - struct vlan_group *grp = __vlan_find_group(dev->ifindex); + struct vlan_group *grp; int i, flgs; struct net_device *vlandev; if (dev_net(dev) != &init_net) return NOTIFY_DONE; + if (is_vlan_dev(dev)) { + __vlan_device_event(dev, event); + goto out; + } + + grp = __vlan_find_group(dev->ifindex); if (!grp) goto out; diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h index 73efcc715cc..51271aea402 100644 --- a/net/8021q/vlan.h +++ b/net/8021q/vlan.h @@ -45,4 +45,9 @@ void vlan_netlink_fini(void); extern struct rtnl_link_ops vlan_link_ops; +static inline int is_vlan_dev(struct net_device *dev) +{ + return dev->priv_flags & IFF_802_1Q_VLAN; +} + #endif /* !(__BEN_VLAN_802_1Q_INC__) */ diff --git a/net/8021q/vlanproc.c b/net/8021q/vlanproc.c index 3b8657a0b83..24cd96ee810 100644 --- a/net/8021q/vlanproc.c +++ b/net/8021q/vlanproc.c @@ -210,11 +210,6 @@ int vlan_proc_rem_dev(struct net_device *vlandev) * The following few functions build the content of /proc/net/vlan/config */ -static inline int is_vlan_dev(struct net_device *dev) -{ - return dev->priv_flags & IFF_802_1Q_VLAN; -} - /* start read of /proc/net/vlan/config */ static void *vlan_seq_start(struct seq_file *seq, loff_t *pos) __acquires(dev_base_lock) diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 1220d8a41eb..d366423c839 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -53,6 +53,30 @@ /* Bluetooth sockets */ #define BT_MAX_PROTO 8 static struct net_proto_family *bt_proto[BT_MAX_PROTO]; + +static struct lock_class_key bt_slock_key[BT_MAX_PROTO]; +static struct lock_class_key bt_lock_key[BT_MAX_PROTO]; +static const char *bt_key_strings[BT_MAX_PROTO] = { + "sk_lock-AF_BLUETOOTH-BTPROTO_L2CAP", + "sk_lock-AF_BLUETOOTH-BTPROTO_HCI", + "sk_lock-AF_BLUETOOTH-BTPROTO_SCO", + "sk_lock-AF_BLUETOOTH-BTPROTO_RFCOMM", + "sk_lock-AF_BLUETOOTH-BTPROTO_BNEP", + "sk_lock-AF_BLUETOOTH-BTPROTO_CMTP", + "sk_lock-AF_BLUETOOTH-BTPROTO_HIDP", + "sk_lock-AF_BLUETOOTH-BTPROTO_AVDTP", +}; + +static const char *bt_slock_key_strings[BT_MAX_PROTO] = { + "slock-AF_BLUETOOTH-BTPROTO_L2CAP", + "slock-AF_BLUETOOTH-BTPROTO_HCI", + "slock-AF_BLUETOOTH-BTPROTO_SCO", + "slock-AF_BLUETOOTH-BTPROTO_RFCOMM", + "slock-AF_BLUETOOTH-BTPROTO_BNEP", + "slock-AF_BLUETOOTH-BTPROTO_CMTP", + "slock-AF_BLUETOOTH-BTPROTO_HIDP", + "slock-AF_BLUETOOTH-BTPROTO_AVDTP", +}; static DEFINE_RWLOCK(bt_proto_lock); int bt_sock_register(int proto, struct net_proto_family *ops) @@ -95,6 +119,21 @@ int bt_sock_unregister(int proto) } EXPORT_SYMBOL(bt_sock_unregister); +static void bt_reclassify_sock_lock(struct socket *sock, int proto) +{ + struct sock *sk = sock->sk; + + if (!sk) + return; + BUG_ON(sock_owned_by_user(sk)); + + sock_lock_init_class_and_name(sk, + bt_slock_key_strings[proto], + &bt_slock_key[proto], + bt_key_strings[proto], + &bt_lock_key[proto]); +} + static int bt_sock_create(struct net *net, struct socket *sock, int proto) { int err; @@ -117,6 +156,7 @@ static int bt_sock_create(struct net *net, struct socket *sock, int proto) if (bt_proto[proto] && try_module_get(bt_proto[proto]->owner)) { err = bt_proto[proto]->create(net, sock, proto); + bt_reclassify_sock_lock(sock, proto); module_put(bt_proto[proto]->owner); } diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index b5d4019d357..1d36c093523 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -84,7 +84,7 @@ static struct hci_sec_filter hci_sec_filter = { }; static struct bt_sock_list hci_sk_list = { - .lock = RW_LOCK_UNLOCKED + .lock = __RW_LOCK_UNLOCKED(hci_sk_list.lock) }; /* Send frame to RAW socket */ diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 6b995ac832f..a4849f2c1d8 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -62,7 +62,7 @@ static u32 l2cap_feat_mask = 0x0000; static const struct proto_ops l2cap_sock_ops; static struct bt_sock_list l2cap_sk_list = { - .lock = RW_LOCK_UNLOCKED + .lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock) }; static void __l2cap_sock_close(struct sock *sk, int reason); diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 0c2c93735e9..eb62558e9b0 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -423,8 +423,8 @@ static int __rfcomm_dlc_close(struct rfcomm_dlc *d, int err) rfcomm_dlc_lock(d); d->state = BT_CLOSED; - d->state_change(d, err); rfcomm_dlc_unlock(d); + d->state_change(d, err); skb_queue_purge(&d->tx_queue); rfcomm_dlc_unlink(d); diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index c103fa02893..5083adcbfae 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -60,7 +60,7 @@ static const struct proto_ops rfcomm_sock_ops; static struct bt_sock_list rfcomm_sk_list = { - .lock = RW_LOCK_UNLOCKED + .lock = __RW_LOCK_UNLOCKED(rfcomm_sk_list.lock) }; static void rfcomm_sock_close(struct sock *sk); diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index e4c779bb8d7..c3f749abb2d 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c @@ -570,12 +570,7 @@ static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err) return; rfcomm_dev_del(dev); - /* We have to drop DLC lock here, otherwise - rfcomm_dev_put() will dead lock if it's - the last reference. */ - rfcomm_dlc_unlock(dlc); rfcomm_dev_put(dev); - rfcomm_dlc_lock(dlc); } } else tty_hangup(dev->tty); diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 2a5953b4405..b0d487e2db2 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -58,7 +58,7 @@ static const struct proto_ops sco_sock_ops; static struct bt_sock_list sco_sk_list = { - .lock = RW_LOCK_UNLOCKED + .lock = __RW_LOCK_UNLOCKED(sco_sk_list.lock) }; static void __sco_chan_add(struct sco_conn *conn, struct sock *sk, struct sock *parent); diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c index 93170bfcc22..4ed429bd595 100644 --- a/net/ipv4/inet_fragment.c +++ b/net/ipv4/inet_fragment.c @@ -86,7 +86,10 @@ EXPORT_SYMBOL(inet_frags_fini); void inet_frags_exit_net(struct netns_frags *nf, struct inet_frags *f) { nf->low_thresh = 0; + + local_bh_disable(); inet_frag_evictor(nf, f); + local_bh_enable(); } EXPORT_SYMBOL(inet_frags_exit_net); diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c index 9d6d3befd85..4813c39b438 100644 --- a/net/ipv4/ip_forward.c +++ b/net/ipv4/ip_forward.c @@ -85,7 +85,7 @@ int ip_forward(struct sk_buff *skb) if (opt->is_strictroute && rt->rt_dst != rt->rt_gateway) goto sr_failed; - if (unlikely(skb->len > dst_mtu(&rt->u.dst) && + if (unlikely(skb->len > dst_mtu(&rt->u.dst) && !skb_is_gso(skb) && (ip_hdr(skb)->frag_off & htons(IP_DF))) && !skb->local_df) { IP_INC_STATS(IPSTATS_MIB_FRAGFAILS); icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 03bd7069748..7b7fcacec4a 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1551,14 +1551,14 @@ static void *udp_seq_start(struct seq_file *seq, loff_t *pos) __acquires(udp_hash_lock) { read_lock(&udp_hash_lock); - return *pos ? udp_get_idx(seq, *pos-1) : (void *)1; + return *pos ? udp_get_idx(seq, *pos-1) : SEQ_START_TOKEN; } static void *udp_seq_next(struct seq_file *seq, void *v, loff_t *pos) { struct sock *sk; - if (v == (void *)1) + if (v == SEQ_START_TOKEN) sk = udp_get_idx(seq, 0); else sk = udp_get_next(seq, v); diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 5ab9973571e..87f688857ad 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -776,6 +776,7 @@ static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, struct inet6_ifaddr *i struct inet6_dev *idev = ifp->idev; struct in6_addr addr, *tmpaddr; unsigned long tmp_prefered_lft, tmp_valid_lft, tmp_cstamp, tmp_tstamp; + unsigned long regen_advance; int tmp_plen; int ret = 0; int max_addresses; @@ -836,8 +837,23 @@ retry: tmp_tstamp = ifp->tstamp; spin_unlock_bh(&ifp->lock); + regen_advance = idev->cnf.regen_max_retry * + idev->cnf.dad_transmits * + idev->nd_parms->retrans_time / HZ; write_unlock(&idev->lock); + /* A temporary address is created only if this calculated Preferred + * Lifetime is greater than REGEN_ADVANCE time units. In particular, + * an implementation must not create a temporary address with a zero + * Preferred Lifetime. + */ + if (tmp_prefered_lft <= regen_advance) { + in6_ifa_put(ifp); + in6_dev_put(idev); + ret = -1; + goto out; + } + addr_flags = IFA_F_TEMPORARY; /* set in addrconf_prefix_rcv() */ if (ifp->flags & IFA_F_OPTIMISTIC) @@ -1834,6 +1850,9 @@ ok: * lifetimes of an existing temporary address * when processing a Prefix Information Option. */ + if (ifp != ift->ifpub) + continue; + spin_lock(&ift->lock); flags = ift->flags; if (ift->valid_lft > valid_lft && diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 63309d10df3..227ce3d2339 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -440,10 +440,10 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, } if (xfrm_decode_session_reverse(skb, &fl2, AF_INET6)) - goto out; + goto out_dst_release; if (ip6_dst_lookup(sk, &dst2, &fl)) - goto out; + goto out_dst_release; err = xfrm_lookup(&dst2, &fl, sk, XFRM_LOOKUP_ICMP); if (err == -ENOENT) { diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index 7e36269826b..43a617e2268 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c @@ -234,8 +234,7 @@ int ip6_mc_input(struct sk_buff *skb) IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INMCASTPKTS); hdr = ipv6_hdr(skb); - deliver = unlikely(skb->dev->flags & (IFF_PROMISC|IFF_ALLMULTI)) || - ipv6_chk_mcast_addr(skb->dev, &hdr->daddr, NULL); + deliver = ipv6_chk_mcast_addr(skb->dev, &hdr->daddr, NULL); /* * IPv6 multicast router mode isnt currently supported. diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index ad8066200f9..9e5f305b202 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c @@ -171,7 +171,9 @@ static __inline__ void fq_kill(struct nf_ct_frag6_queue *fq) static void nf_ct_frag6_evictor(void) { + local_bh_disable(); inet_frag_evictor(&nf_init_frags, &nf_frags); + local_bh_enable(); } static void nf_ct_frag6_expire(unsigned long data) diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index f93b5761858..97101dcde4c 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -155,6 +155,9 @@ static int llc_ui_create(struct net *net, struct socket *sock, int protocol) struct sock *sk; int rc = -ESOCKTNOSUPPORT; + if (!capable(CAP_NET_RAW)) + return -EPERM; + if (net != &init_net) return -EAFNOSUPPORT; diff --git a/net/llc/llc_c_ac.c b/net/llc/llc_c_ac.c index f728ffe288a..019c780512e 100644 --- a/net/llc/llc_c_ac.c +++ b/net/llc/llc_c_ac.c @@ -198,7 +198,7 @@ int llc_conn_ac_send_disc_cmd_p_set_x(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; struct llc_sock *llc = llc_sk(sk); - struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_U, 0); if (nskb) { struct llc_sap *sap = llc->sap; @@ -223,7 +223,7 @@ int llc_conn_ac_send_dm_rsp_f_set_p(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; struct llc_sock *llc = llc_sk(sk); - struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_U, 0); if (nskb) { struct llc_sap *sap = llc->sap; @@ -249,7 +249,7 @@ int llc_conn_ac_send_dm_rsp_f_set_1(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; struct llc_sock *llc = llc_sk(sk); - struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_U, 0); if (nskb) { struct llc_sap *sap = llc->sap; @@ -282,7 +282,8 @@ int llc_conn_ac_send_frmr_rsp_f_set_x(struct sock *sk, struct sk_buff *skb) llc_pdu_decode_pf_bit(skb, &f_bit); else f_bit = 0; - nskb = llc_alloc_frame(sk, llc->dev); + nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_U, + sizeof(struct llc_frmr_info)); if (nskb) { struct llc_sap *sap = llc->sap; @@ -306,7 +307,8 @@ int llc_conn_ac_resend_frmr_rsp_f_set_0(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; struct llc_sock *llc = llc_sk(sk); - struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_U, + sizeof(struct llc_frmr_info)); if (nskb) { struct llc_sap *sap = llc->sap; @@ -336,7 +338,8 @@ int llc_conn_ac_resend_frmr_rsp_f_set_p(struct sock *sk, struct sk_buff *skb) struct llc_sock *llc = llc_sk(sk); llc_pdu_decode_pf_bit(skb, &f_bit); - nskb = llc_alloc_frame(sk, llc->dev); + nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_U, + sizeof(struct llc_frmr_info)); if (nskb) { struct llc_sap *sap = llc->sap; struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); @@ -424,7 +427,7 @@ int llc_conn_ac_resend_i_xxx_x_set_0_or_send_rr(struct sock *sk, struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); int rc = -ENOBUFS; struct llc_sock *llc = llc_sk(sk); - struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_U, 0); if (nskb) { struct llc_sap *sap = llc->sap; @@ -459,7 +462,7 @@ int llc_conn_ac_send_rej_cmd_p_set_1(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; struct llc_sock *llc = llc_sk(sk); - struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_S, 0); if (nskb) { struct llc_sap *sap = llc->sap; @@ -483,7 +486,7 @@ int llc_conn_ac_send_rej_rsp_f_set_1(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; struct llc_sock *llc = llc_sk(sk); - struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_S, 0); if (nskb) { struct llc_sap *sap = llc->sap; @@ -507,7 +510,7 @@ int llc_conn_ac_send_rej_xxx_x_set_0(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; struct llc_sock *llc = llc_sk(sk); - struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_S, 0); if (nskb) { struct llc_sap *sap = llc->sap; @@ -531,7 +534,7 @@ int llc_conn_ac_send_rnr_cmd_p_set_1(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; struct llc_sock *llc = llc_sk(sk); - struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_S, 0); if (nskb) { struct llc_sap *sap = llc->sap; @@ -555,7 +558,7 @@ int llc_conn_ac_send_rnr_rsp_f_set_1(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; struct llc_sock *llc = llc_sk(sk); - struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_S, 0); if (nskb) { struct llc_sap *sap = llc->sap; @@ -579,7 +582,7 @@ int llc_conn_ac_send_rnr_xxx_x_set_0(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; struct llc_sock *llc = llc_sk(sk); - struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_S, 0); if (nskb) { struct llc_sap *sap = llc->sap; @@ -615,7 +618,7 @@ int llc_conn_ac_opt_send_rnr_xxx_x_set_0(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; struct llc_sock *llc = llc_sk(sk); - struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_S, 0); if (nskb) { struct llc_sap *sap = llc->sap; @@ -639,7 +642,7 @@ int llc_conn_ac_send_rr_cmd_p_set_1(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; struct llc_sock *llc = llc_sk(sk); - struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_S, 0); if (nskb) { struct llc_sap *sap = llc->sap; @@ -663,7 +666,7 @@ int llc_conn_ac_send_rr_rsp_f_set_1(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; struct llc_sock *llc = llc_sk(sk); - struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_S, 0); if (nskb) { struct llc_sap *sap = llc->sap; @@ -688,7 +691,7 @@ int llc_conn_ac_send_ack_rsp_f_set_1(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; struct llc_sock *llc = llc_sk(sk); - struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_S, 0); if (nskb) { struct llc_sap *sap = llc->sap; @@ -712,7 +715,7 @@ int llc_conn_ac_send_rr_xxx_x_set_0(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; struct llc_sock *llc = llc_sk(sk); - struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_S, 0); if (nskb) { struct llc_sap *sap = llc->sap; @@ -736,7 +739,7 @@ int llc_conn_ac_send_ack_xxx_x_set_0(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; struct llc_sock *llc = llc_sk(sk); - struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_S, 0); if (nskb) { struct llc_sap *sap = llc->sap; @@ -770,7 +773,7 @@ int llc_conn_ac_send_sabme_cmd_p_set_x(struct sock *sk, struct sk_buff *skb) { int rc = -ENOBUFS; struct llc_sock *llc = llc_sk(sk); - struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_U, 0); if (nskb) { struct llc_sap *sap = llc->sap; @@ -799,7 +802,7 @@ int llc_conn_ac_send_ua_rsp_f_set_p(struct sock *sk, struct sk_buff *skb) u8 f_bit; int rc = -ENOBUFS; struct llc_sock *llc = llc_sk(sk); - struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_U, 0); llc_pdu_decode_pf_bit(skb, &f_bit); if (nskb) { @@ -956,7 +959,7 @@ static int llc_conn_ac_send_rr_rsp_f_set_ackpf(struct sock *sk, { int rc = -ENOBUFS; struct llc_sock *llc = llc_sk(sk); - struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_S, 0); if (nskb) { struct llc_sap *sap = llc->sap; diff --git a/net/llc/llc_core.c b/net/llc/llc_core.c index 248b5903bb1..50d5b10e23a 100644 --- a/net/llc/llc_core.c +++ b/net/llc/llc_core.c @@ -25,8 +25,6 @@ LIST_HEAD(llc_sap_list); DEFINE_RWLOCK(llc_sap_list_lock); -unsigned char llc_station_mac_sa[ETH_ALEN]; - /** * llc_sap_alloc - allocates and initializes sap. * @@ -37,8 +35,8 @@ static struct llc_sap *llc_sap_alloc(void) struct llc_sap *sap = kzalloc(sizeof(*sap), GFP_ATOMIC); if (sap) { + /* sap->laddr.mac - leave as a null, it's filled by bind */ sap->state = LLC_SAP_STATE_ACTIVE; - memcpy(sap->laddr.mac, llc_station_mac_sa, ETH_ALEN); rwlock_init(&sap->sk_list.lock); atomic_set(&sap->refcnt, 1); } @@ -167,10 +165,6 @@ static int __init llc_init(void) if (dev != NULL) dev = next_net_device(dev); - if (dev != NULL) - memcpy(llc_station_mac_sa, dev->dev_addr, ETH_ALEN); - else - memset(llc_station_mac_sa, 0, ETH_ALEN); dev_add_pack(&llc_packet_type); dev_add_pack(&llc_tr_packet_type); return 0; @@ -185,7 +179,6 @@ static void __exit llc_exit(void) module_init(llc_init); module_exit(llc_exit); -EXPORT_SYMBOL(llc_station_mac_sa); EXPORT_SYMBOL(llc_sap_list); EXPORT_SYMBOL(llc_sap_list_lock); EXPORT_SYMBOL(llc_sap_find); diff --git a/net/llc/llc_input.c b/net/llc/llc_input.c index a69c5c427fe..1c45f172991 100644 --- a/net/llc/llc_input.c +++ b/net/llc/llc_input.c @@ -117,8 +117,12 @@ static inline int llc_fixup_skb(struct sk_buff *skb) skb_pull(skb, llc_len); if (skb->protocol == htons(ETH_P_802_2)) { __be16 pdulen = eth_hdr(skb)->h_proto; - u16 data_size = ntohs(pdulen) - llc_len; + s32 data_size = ntohs(pdulen) - llc_len; + if (data_size < 0 || + ((skb_tail_pointer(skb) - + (u8 *)pdu) - llc_len) < data_size) + return 0; if (unlikely(pskb_trim_rcsum(skb, data_size))) return 0; } diff --git a/net/llc/llc_pdu.c b/net/llc/llc_pdu.c index fa8324396db..2e6cb79196b 100644 --- a/net/llc/llc_pdu.c +++ b/net/llc/llc_pdu.c @@ -241,7 +241,7 @@ void llc_pdu_init_as_frmr_rsp(struct sk_buff *skb, struct llc_pdu_sn *prev_pdu, FRMR_INFO_SET_PDU_INFO_2LONG_IND(frmr_info, vzyxw); FRMR_INFO_SET_PDU_INVALID_Nr_IND(frmr_info, vzyxw); FRMR_INFO_SET_PDU_INVALID_Ns_IND(frmr_info, vzyxw); - skb_put(skb, 5); + skb_put(skb, sizeof(struct llc_frmr_info)); } /** diff --git a/net/llc/llc_s_ac.c b/net/llc/llc_s_ac.c index ac3d93b210d..a94bd56bcac 100644 --- a/net/llc/llc_s_ac.c +++ b/net/llc/llc_s_ac.c @@ -103,7 +103,8 @@ int llc_sap_action_send_xid_r(struct llc_sap *sap, struct sk_buff *skb) llc_pdu_decode_sa(skb, mac_da); llc_pdu_decode_da(skb, mac_sa); llc_pdu_decode_ssap(skb, &dsap); - nskb = llc_alloc_frame(NULL, skb->dev); + nskb = llc_alloc_frame(NULL, skb->dev, LLC_PDU_TYPE_U, + sizeof(struct llc_xid_info)); if (!nskb) goto out; llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, dsap, @@ -144,11 +145,15 @@ int llc_sap_action_send_test_r(struct llc_sap *sap, struct sk_buff *skb) u8 mac_da[ETH_ALEN], mac_sa[ETH_ALEN], dsap; struct sk_buff *nskb; int rc = 1; + u32 data_size; llc_pdu_decode_sa(skb, mac_da); llc_pdu_decode_da(skb, mac_sa); llc_pdu_decode_ssap(skb, &dsap); - nskb = llc_alloc_frame(NULL, skb->dev); + + /* The test request command is type U (llc_len = 3) */ + data_size = ntohs(eth_hdr(skb)->h_proto) - 3; + nskb = llc_alloc_frame(NULL, skb->dev, LLC_PDU_TYPE_U, data_size); if (!nskb) goto out; llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, dsap, diff --git a/net/llc/llc_sap.c b/net/llc/llc_sap.c index 2525165e2e8..e2ddde75501 100644 --- a/net/llc/llc_sap.c +++ b/net/llc/llc_sap.c @@ -24,20 +24,41 @@ #include <net/tcp_states.h> #include <linux/llc.h> +static int llc_mac_header_len(unsigned short devtype) +{ + switch (devtype) { + case ARPHRD_ETHER: + case ARPHRD_LOOPBACK: + return sizeof(struct ethhdr); +#ifdef CONFIG_TR + case ARPHRD_IEEE802_TR: + return sizeof(struct trh_hdr); +#endif + } + return 0; +} + /** * llc_alloc_frame - allocates sk_buff for frame * @dev: network device this skb will be sent over + * @type: pdu type to allocate + * @data_size: data size to allocate * * Allocates an sk_buff for frame and initializes sk_buff fields. * Returns allocated skb or %NULL when out of memory. */ -struct sk_buff *llc_alloc_frame(struct sock *sk, struct net_device *dev) +struct sk_buff *llc_alloc_frame(struct sock *sk, struct net_device *dev, + u8 type, u32 data_size) { - struct sk_buff *skb = alloc_skb(128, GFP_ATOMIC); + int hlen = type == LLC_PDU_TYPE_U ? 3 : 4; + struct sk_buff *skb; + + hlen += llc_mac_header_len(dev->type); + skb = alloc_skb(hlen + data_size, GFP_ATOMIC); if (skb) { skb_reset_mac_header(skb); - skb_reserve(skb, 50); + skb_reserve(skb, hlen); skb_reset_network_header(skb); skb_reset_transport_header(skb); skb->protocol = htons(ETH_P_802_2); diff --git a/net/llc/llc_station.c b/net/llc/llc_station.c index 6f2ea209032..83da1333949 100644 --- a/net/llc/llc_station.c +++ b/net/llc/llc_station.c @@ -253,13 +253,14 @@ static int llc_station_ac_inc_xid_r_cnt_by_1(struct sk_buff *skb) static int llc_station_ac_send_null_dsap_xid_c(struct sk_buff *skb) { int rc = 1; - struct sk_buff *nskb = llc_alloc_frame(NULL, skb->dev); + struct sk_buff *nskb = llc_alloc_frame(NULL, skb->dev, LLC_PDU_TYPE_U, + sizeof(struct llc_xid_info)); if (!nskb) goto out; llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, 0, 0, LLC_PDU_CMD); llc_pdu_init_as_xid_cmd(nskb, LLC_XID_NULL_CLASS_2, 127); - rc = llc_mac_hdr_init(nskb, llc_station_mac_sa, llc_station_mac_sa); + rc = llc_mac_hdr_init(nskb, skb->dev->dev_addr, skb->dev->dev_addr); if (unlikely(rc)) goto free; llc_station_send_pdu(nskb); @@ -274,7 +275,8 @@ static int llc_station_ac_send_xid_r(struct sk_buff *skb) { u8 mac_da[ETH_ALEN], dsap; int rc = 1; - struct sk_buff* nskb = llc_alloc_frame(NULL, skb->dev); + struct sk_buff *nskb = llc_alloc_frame(NULL, skb->dev, LLC_PDU_TYPE_U, + sizeof(struct llc_xid_info)); if (!nskb) goto out; @@ -283,7 +285,7 @@ static int llc_station_ac_send_xid_r(struct sk_buff *skb) llc_pdu_decode_ssap(skb, &dsap); llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, 0, dsap, LLC_PDU_RSP); llc_pdu_init_as_xid_rsp(nskb, LLC_XID_NULL_CLASS_2, 127); - rc = llc_mac_hdr_init(nskb, llc_station_mac_sa, mac_da); + rc = llc_mac_hdr_init(nskb, skb->dev->dev_addr, mac_da); if (unlikely(rc)) goto free; llc_station_send_pdu(nskb); @@ -298,7 +300,12 @@ static int llc_station_ac_send_test_r(struct sk_buff *skb) { u8 mac_da[ETH_ALEN], dsap; int rc = 1; - struct sk_buff *nskb = llc_alloc_frame(NULL, skb->dev); + u32 data_size; + struct sk_buff *nskb; + + /* The test request command is type U (llc_len = 3) */ + data_size = ntohs(eth_hdr(skb)->h_proto) - 3; + nskb = llc_alloc_frame(NULL, skb->dev, LLC_PDU_TYPE_U, data_size); if (!nskb) goto out; @@ -307,7 +314,7 @@ static int llc_station_ac_send_test_r(struct sk_buff *skb) llc_pdu_decode_ssap(skb, &dsap); llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, 0, dsap, LLC_PDU_RSP); llc_pdu_init_as_test_rsp(nskb, skb); - rc = llc_mac_hdr_init(nskb, llc_station_mac_sa, mac_da); + rc = llc_mac_hdr_init(nskb, skb->dev->dev_addr, mac_da); if (unlikely(rc)) goto free; llc_station_send_pdu(nskb); diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c index 5ee431b6256..aaa5480e204 100644 --- a/net/mac80211/ieee80211.c +++ b/net/mac80211/ieee80211.c @@ -375,6 +375,18 @@ static int ieee80211_open(struct net_device *dev) if (need_hw_reconfig) ieee80211_hw_config(local); + /* + * ieee80211_sta_work is disabled while network interface + * is down. Therefore, some configuration changes may not + * yet be effective. Trigger execution of ieee80211_sta_work + * to fix this. + */ + if(sdata->vif.type == IEEE80211_IF_TYPE_STA || + sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { + struct ieee80211_if_sta *ifsta = &sdata->u.sta; + queue_work(local->hw.workqueue, &ifsta->work); + } + netif_start_queue(dev); return 0; diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c index 110eaf3ab58..c20ef89acad 100644 --- a/net/mac80211/ieee80211_sta.c +++ b/net/mac80211/ieee80211_sta.c @@ -360,7 +360,7 @@ static u32 ieee80211_handle_erp_ie(struct ieee80211_sub_if_data *sdata, struct ieee80211_bss_conf *bss_conf = &sdata->bss_conf; struct ieee80211_if_sta *ifsta = &sdata->u.sta; bool use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0; - bool preamble_mode = (erp_value & WLAN_ERP_BARKER_PREAMBLE) != 0; + bool use_short_preamble = (erp_value & WLAN_ERP_BARKER_PREAMBLE) == 0; DECLARE_MAC_BUF(mac); u32 changed = 0; @@ -376,16 +376,15 @@ static u32 ieee80211_handle_erp_ie(struct ieee80211_sub_if_data *sdata, changed |= BSS_CHANGED_ERP_CTS_PROT; } - if (preamble_mode != bss_conf->use_short_preamble) { + if (use_short_preamble != bss_conf->use_short_preamble) { if (net_ratelimit()) { printk(KERN_DEBUG "%s: switched to %s barker preamble" " (BSSID=%s)\n", sdata->dev->name, - (preamble_mode == WLAN_ERP_PREAMBLE_SHORT) ? - "short" : "long", + use_short_preamble ? "short" : "long", print_mac(mac, ifsta->bssid)); } - bss_conf->use_short_preamble = preamble_mode; + bss_conf->use_short_preamble = use_short_preamble; changed |= BSS_CHANGED_ERP_PREAMBLE; } diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index 92d85c38e4d..d1ff3f885c5 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c @@ -598,17 +598,24 @@ static int rose_release(struct socket *sock) if (sk == NULL) return 0; + sock_hold(sk); + sock_orphan(sk); + lock_sock(sk); rose = rose_sk(sk); switch (rose->state) { case ROSE_STATE_0: + release_sock(sk); rose_disconnect(sk, 0, -1, -1); + lock_sock(sk); rose_destroy_socket(sk); break; case ROSE_STATE_2: rose->neighbour->use--; + release_sock(sk); rose_disconnect(sk, 0, -1, -1); + lock_sock(sk); rose_destroy_socket(sk); break; @@ -633,6 +640,8 @@ static int rose_release(struct socket *sock) } sock->sk = NULL; + release_sock(sk); + sock_put(sk); return 0; } diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 10b5c0887ff..b741618e4d5 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -184,10 +184,22 @@ static inline int qdisc_restart(struct net_device *dev) void __qdisc_run(struct net_device *dev) { - do { - if (!qdisc_restart(dev)) + unsigned long start_time = jiffies; + + while (qdisc_restart(dev)) { + if (netif_queue_stopped(dev)) + break; + + /* + * Postpone processing if + * 1. another process needs the CPU; + * 2. we've been doing it for too long. + */ + if (need_resched() || jiffies != start_time) { + netif_schedule(dev); break; - } while (!netif_queue_stopped(dev)); + } + } clear_bit(__LINK_STATE_QDISC_RUNNING, &dev->state); } |