Explorar o código

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem

John W. Linville %!s(int64=11) %!d(string=hai) anos
pai
achega
c6ac68a612

+ 2 - 1
drivers/bluetooth/ath3k.c

@@ -193,9 +193,10 @@ static int ath3k_load_firmware(struct usb_device *udev,
 	sent += 20;
 	sent += 20;
 	count -= 20;
 	count -= 20;
 
 
+	pipe = usb_sndbulkpipe(udev, 0x02);
+
 	while (count) {
 	while (count) {
 		size = min_t(uint, count, BULK_SIZE);
 		size = min_t(uint, count, BULK_SIZE);
-		pipe = usb_sndbulkpipe(udev, 0x02);
 		memcpy(send_buf, firmware->data + sent, size);
 		memcpy(send_buf, firmware->data + sent, size);
 
 
 		err = usb_bulk_msg(udev, pipe, send_buf, size,
 		err = usb_bulk_msg(udev, pipe, send_buf, size,

+ 53 - 0
drivers/net/wireless/at76c50x-usb.c

@@ -1429,6 +1429,8 @@ static int at76_startup_device(struct at76_priv *priv)
 	/* remove BSSID from previous run */
 	/* remove BSSID from previous run */
 	memset(priv->bssid, 0, ETH_ALEN);
 	memset(priv->bssid, 0, ETH_ALEN);
 
 
+	priv->scanning = false;
+
 	if (at76_set_radio(priv, 1) == 1)
 	if (at76_set_radio(priv, 1) == 1)
 		at76_wait_completion(priv, CMD_RADIO_ON);
 		at76_wait_completion(priv, CMD_RADIO_ON);
 
 
@@ -1502,6 +1504,52 @@ static void at76_work_submit_rx(struct work_struct *work)
 	mutex_unlock(&priv->mtx);
 	mutex_unlock(&priv->mtx);
 }
 }
 
 
+/* This is a workaround to make scan working:
+ * currently mac80211 does not process frames with no frequency
+ * information.
+ * However during scan the HW performs a sweep by itself, and we
+ * are unable to know where the radio is actually tuned.
+ * This function tries to do its best to guess this information..
+ * During scan, If the current frame is a beacon or a probe response,
+ * the channel information is extracted from it.
+ * When not scanning, for other frames, or if it happens that for
+ * whatever reason we fail to parse beacons and probe responses, this
+ * function returns the priv->channel information, that should be correct
+ * at least when we are not scanning.
+ */
+static inline int at76_guess_freq(struct at76_priv *priv)
+{
+	size_t el_off;
+	const u8 *el;
+	int channel = priv->channel;
+	int len = priv->rx_skb->len;
+	struct ieee80211_hdr *hdr = (void *)priv->rx_skb->data;
+
+	if (!priv->scanning)
+		goto exit;
+
+	if (len < 24)
+		goto exit;
+
+	if (ieee80211_is_probe_resp(hdr->frame_control)) {
+		el_off = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
+		el = ((struct ieee80211_mgmt *)hdr)->u.probe_resp.variable;
+	} else if (ieee80211_is_beacon(hdr->frame_control)) {
+		el_off = offsetof(struct ieee80211_mgmt, u.beacon.variable);
+		el = ((struct ieee80211_mgmt *)hdr)->u.beacon.variable;
+	} else {
+		goto exit;
+	}
+	len -= el_off;
+
+	el = cfg80211_find_ie(WLAN_EID_DS_PARAMS, el, len);
+	if (el && el[1] > 0)
+		channel = el[2];
+
+exit:
+	return ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ);
+}
+
 static void at76_rx_tasklet(unsigned long param)
 static void at76_rx_tasklet(unsigned long param)
 {
 {
 	struct urb *urb = (struct urb *)param;
 	struct urb *urb = (struct urb *)param;
@@ -1542,6 +1590,8 @@ static void at76_rx_tasklet(unsigned long param)
 	rx_status.signal = buf->rssi;
 	rx_status.signal = buf->rssi;
 	rx_status.flag |= RX_FLAG_DECRYPTED;
 	rx_status.flag |= RX_FLAG_DECRYPTED;
 	rx_status.flag |= RX_FLAG_IV_STRIPPED;
 	rx_status.flag |= RX_FLAG_IV_STRIPPED;
+	rx_status.band = IEEE80211_BAND_2GHZ;
+	rx_status.freq = at76_guess_freq(priv);
 
 
 	at76_dbg(DBG_MAC80211, "calling ieee80211_rx_irqsafe(): %d/%d",
 	at76_dbg(DBG_MAC80211, "calling ieee80211_rx_irqsafe(): %d/%d",
 		 priv->rx_skb->len, priv->rx_skb->data_len);
 		 priv->rx_skb->len, priv->rx_skb->data_len);
@@ -1894,6 +1944,8 @@ static void at76_dwork_hw_scan(struct work_struct *work)
 	if (is_valid_ether_addr(priv->bssid))
 	if (is_valid_ether_addr(priv->bssid))
 		at76_join(priv);
 		at76_join(priv);
 
 
+	priv->scanning = false;
+
 	mutex_unlock(&priv->mtx);
 	mutex_unlock(&priv->mtx);
 
 
 	ieee80211_scan_completed(priv->hw, false);
 	ieee80211_scan_completed(priv->hw, false);
@@ -1948,6 +2000,7 @@ static int at76_hw_scan(struct ieee80211_hw *hw,
 		goto exit;
 		goto exit;
 	}
 	}
 
 
+	priv->scanning = true;
 	ieee80211_queue_delayed_work(priv->hw, &priv->dwork_hw_scan,
 	ieee80211_queue_delayed_work(priv->hw, &priv->dwork_hw_scan,
 				     SCAN_POLL_INTERVAL);
 				     SCAN_POLL_INTERVAL);
 
 

+ 1 - 0
drivers/net/wireless/at76c50x-usb.h

@@ -418,6 +418,7 @@ struct at76_priv {
 	int scan_max_time;	/* scan max channel time */
 	int scan_max_time;	/* scan max channel time */
 	int scan_mode;		/* SCAN_TYPE_ACTIVE, SCAN_TYPE_PASSIVE */
 	int scan_mode;		/* SCAN_TYPE_ACTIVE, SCAN_TYPE_PASSIVE */
 	int scan_need_any;	/* if set, need to scan for any ESSID */
 	int scan_need_any;	/* if set, need to scan for any ESSID */
+	bool scanning;		/* if set, the scan is running */
 
 
 	u16 assoc_id;		/* current association ID, if associated */
 	u16 assoc_id;		/* current association ID, if associated */
 
 

+ 35 - 30
net/bluetooth/6lowpan.c

@@ -420,12 +420,18 @@ static int conn_send(struct l2cap_conn *conn,
 	return 0;
 	return 0;
 }
 }
 
 
-static void get_dest_bdaddr(struct in6_addr *ip6_daddr,
-			    bdaddr_t *addr, u8 *addr_type)
+static u8 get_addr_type_from_eui64(u8 byte)
 {
 {
-	u8 *eui64;
+	/* Is universal(0) or local(1) bit,  */
+	if (byte & 0x02)
+		return ADDR_LE_DEV_RANDOM;
 
 
-	eui64 = ip6_daddr->s6_addr + 8;
+	return ADDR_LE_DEV_PUBLIC;
+}
+
+static void copy_to_bdaddr(struct in6_addr *ip6_daddr, bdaddr_t *addr)
+{
+	u8 *eui64 = ip6_daddr->s6_addr + 8;
 
 
 	addr->b[0] = eui64[7];
 	addr->b[0] = eui64[7];
 	addr->b[1] = eui64[6];
 	addr->b[1] = eui64[6];
@@ -433,16 +439,19 @@ static void get_dest_bdaddr(struct in6_addr *ip6_daddr,
 	addr->b[3] = eui64[2];
 	addr->b[3] = eui64[2];
 	addr->b[4] = eui64[1];
 	addr->b[4] = eui64[1];
 	addr->b[5] = eui64[0];
 	addr->b[5] = eui64[0];
+}
 
 
-	addr->b[5] ^= 2;
+static void convert_dest_bdaddr(struct in6_addr *ip6_daddr,
+				bdaddr_t *addr, u8 *addr_type)
+{
+	copy_to_bdaddr(ip6_daddr, addr);
 
 
-	/* Set universal/local bit to 0 */
-	if (addr->b[5] & 1) {
-		addr->b[5] &= ~1;
-		*addr_type = ADDR_LE_DEV_PUBLIC;
-	} else {
-		*addr_type = ADDR_LE_DEV_RANDOM;
-	}
+	/* We need to toggle the U/L bit that we got from IPv6 address
+	 * so that we get the proper address and type of the BD address.
+	 */
+	addr->b[5] ^= 0x02;
+
+	*addr_type = get_addr_type_from_eui64(addr->b[5]);
 }
 }
 
 
 static int header_create(struct sk_buff *skb, struct net_device *netdev,
 static int header_create(struct sk_buff *skb, struct net_device *netdev,
@@ -473,9 +482,11 @@ static int header_create(struct sk_buff *skb, struct net_device *netdev,
 		/* Get destination BT device from skb.
 		/* Get destination BT device from skb.
 		 * If there is no such peer then discard the packet.
 		 * If there is no such peer then discard the packet.
 		 */
 		 */
-		get_dest_bdaddr(&hdr->daddr, &addr, &addr_type);
+		convert_dest_bdaddr(&hdr->daddr, &addr, &addr_type);
 
 
-		BT_DBG("dest addr %pMR type %d", &addr, addr_type);
+		BT_DBG("dest addr %pMR type %s IP %pI6c", &addr,
+		       addr_type == ADDR_LE_DEV_PUBLIC ? "PUBLIC" : "RANDOM",
+		       &hdr->daddr);
 
 
 		read_lock_irqsave(&devices_lock, flags);
 		read_lock_irqsave(&devices_lock, flags);
 		peer = peer_lookup_ba(dev, &addr, addr_type);
 		peer = peer_lookup_ba(dev, &addr, addr_type);
@@ -556,7 +567,7 @@ static netdev_tx_t bt_xmit(struct sk_buff *skb, struct net_device *netdev)
 	} else {
 	} else {
 		unsigned long flags;
 		unsigned long flags;
 
 
-		get_dest_bdaddr(&lowpan_cb(skb)->addr, &addr, &addr_type);
+		convert_dest_bdaddr(&lowpan_cb(skb)->addr, &addr, &addr_type);
 		eui64_addr = lowpan_cb(skb)->addr.s6_addr + 8;
 		eui64_addr = lowpan_cb(skb)->addr.s6_addr + 8;
 		dev = lowpan_dev(netdev);
 		dev = lowpan_dev(netdev);
 
 
@@ -564,8 +575,10 @@ static netdev_tx_t bt_xmit(struct sk_buff *skb, struct net_device *netdev)
 		peer = peer_lookup_ba(dev, &addr, addr_type);
 		peer = peer_lookup_ba(dev, &addr, addr_type);
 		read_unlock_irqrestore(&devices_lock, flags);
 		read_unlock_irqrestore(&devices_lock, flags);
 
 
-		BT_DBG("xmit from %s to %pMR (%pI6c) peer %p", netdev->name,
-		       &addr, &lowpan_cb(skb)->addr, peer);
+		BT_DBG("xmit %s to %pMR type %s IP %pI6c peer %p",
+		       netdev->name, &addr,
+		       addr_type == ADDR_LE_DEV_PUBLIC ? "PUBLIC" : "RANDOM",
+		       &lowpan_cb(skb)->addr, peer);
 
 
 		if (peer && peer->conn)
 		if (peer && peer->conn)
 			err = send_pkt(peer->conn, netdev->dev_addr,
 			err = send_pkt(peer->conn, netdev->dev_addr,
@@ -620,13 +633,13 @@ static void set_addr(u8 *eui, u8 *addr, u8 addr_type)
 	eui[6] = addr[1];
 	eui[6] = addr[1];
 	eui[7] = addr[0];
 	eui[7] = addr[0];
 
 
-	eui[0] ^= 2;
-
-	/* Universal/local bit set, RFC 4291 */
+	/* Universal/local bit set, BT 6lowpan draft ch. 3.2.1 */
 	if (addr_type == ADDR_LE_DEV_PUBLIC)
 	if (addr_type == ADDR_LE_DEV_PUBLIC)
-		eui[0] |= 1;
+		eui[0] &= ~0x02;
 	else
 	else
-		eui[0] &= ~1;
+		eui[0] |= 0x02;
+
+	BT_DBG("type %d addr %*phC", addr_type, 8, eui);
 }
 }
 
 
 static void set_dev_addr(struct net_device *netdev, bdaddr_t *addr,
 static void set_dev_addr(struct net_device *netdev, bdaddr_t *addr,
@@ -634,7 +647,6 @@ static void set_dev_addr(struct net_device *netdev, bdaddr_t *addr,
 {
 {
 	netdev->addr_assign_type = NET_ADDR_PERM;
 	netdev->addr_assign_type = NET_ADDR_PERM;
 	set_addr(netdev->dev_addr, addr->b, addr_type);
 	set_addr(netdev->dev_addr, addr->b, addr_type);
-	netdev->dev_addr[0] ^= 2;
 }
 }
 
 
 static void ifup(struct net_device *netdev)
 static void ifup(struct net_device *netdev)
@@ -684,13 +696,6 @@ static int add_peer_conn(struct l2cap_conn *conn, struct lowpan_dev *dev)
 
 
 	memcpy(&peer->eui64_addr, (u8 *)&peer->peer_addr.s6_addr + 8,
 	memcpy(&peer->eui64_addr, (u8 *)&peer->peer_addr.s6_addr + 8,
 	       EUI64_ADDR_LEN);
 	       EUI64_ADDR_LEN);
-	peer->eui64_addr[0] ^= 2; /* second bit-flip (Universe/Local)
-				   * is done according RFC2464
-				   */
-
-	raw_dump_inline(__func__, "peer IPv6 address",
-			(unsigned char *)&peer->peer_addr, 16);
-	raw_dump_inline(__func__, "peer EUI64 address", peer->eui64_addr, 8);
 
 
 	write_lock_irqsave(&devices_lock, flags);
 	write_lock_irqsave(&devices_lock, flags);
 	INIT_LIST_HEAD(&peer->list);
 	INIT_LIST_HEAD(&peer->list);

+ 3 - 1
net/bluetooth/hci_event.c

@@ -1453,6 +1453,7 @@ static int hci_outgoing_auth_needed(struct hci_dev *hdev,
 	 * is requested.
 	 * is requested.
 	 */
 	 */
 	if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) &&
 	if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) &&
+	    conn->pending_sec_level != BT_SECURITY_FIPS &&
 	    conn->pending_sec_level != BT_SECURITY_HIGH &&
 	    conn->pending_sec_level != BT_SECURITY_HIGH &&
 	    conn->pending_sec_level != BT_SECURITY_MEDIUM)
 	    conn->pending_sec_level != BT_SECURITY_MEDIUM)
 		return 0;
 		return 0;
@@ -3076,7 +3077,8 @@ static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
 		}
 		}
 
 
 		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
 		if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
-		    conn->pending_sec_level == BT_SECURITY_HIGH) {
+		    (conn->pending_sec_level == BT_SECURITY_HIGH ||
+		     conn->pending_sec_level == BT_SECURITY_FIPS)) {
 			BT_DBG("%s ignoring key unauthenticated for high security",
 			BT_DBG("%s ignoring key unauthenticated for high security",
 			       hdev->name);
 			       hdev->name);
 			goto not_found;
 			goto not_found;

+ 6 - 0
net/bluetooth/l2cap_core.c

@@ -471,8 +471,14 @@ void l2cap_chan_set_defaults(struct l2cap_chan *chan)
 	chan->max_tx = L2CAP_DEFAULT_MAX_TX;
 	chan->max_tx = L2CAP_DEFAULT_MAX_TX;
 	chan->tx_win = L2CAP_DEFAULT_TX_WINDOW;
 	chan->tx_win = L2CAP_DEFAULT_TX_WINDOW;
 	chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
 	chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW;
+	chan->remote_max_tx = chan->max_tx;
+	chan->remote_tx_win = chan->tx_win;
 	chan->ack_win = L2CAP_DEFAULT_TX_WINDOW;
 	chan->ack_win = L2CAP_DEFAULT_TX_WINDOW;
 	chan->sec_level = BT_SECURITY_LOW;
 	chan->sec_level = BT_SECURITY_LOW;
+	chan->flush_to = L2CAP_DEFAULT_FLUSH_TO;
+	chan->retrans_timeout = L2CAP_DEFAULT_RETRANS_TO;
+	chan->monitor_timeout = L2CAP_DEFAULT_MONITOR_TO;
+	chan->conf_state = 0;
 
 
 	set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
 	set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
 }
 }

+ 4 - 1
net/bluetooth/l2cap_sock.c

@@ -1180,13 +1180,16 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan)
 	/* Check for backlog size */
 	/* Check for backlog size */
 	if (sk_acceptq_is_full(parent)) {
 	if (sk_acceptq_is_full(parent)) {
 		BT_DBG("backlog full %d", parent->sk_ack_backlog);
 		BT_DBG("backlog full %d", parent->sk_ack_backlog);
+		release_sock(parent);
 		return NULL;
 		return NULL;
 	}
 	}
 
 
 	sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP,
 	sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP,
 			      GFP_ATOMIC);
 			      GFP_ATOMIC);
-	if (!sk)
+	if (!sk) {
+		release_sock(parent);
 		return NULL;
 		return NULL;
+        }
 
 
 	bt_sock_reclassify_lock(sk, BTPROTO_L2CAP);
 	bt_sock_reclassify_lock(sk, BTPROTO_L2CAP);
 
 

+ 8 - 2
net/bluetooth/mgmt.c

@@ -4546,10 +4546,16 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
 		else
 		else
 			type = HCI_SMP_LTK_SLAVE;
 			type = HCI_SMP_LTK_SLAVE;
 
 
-		if (key->type == MGMT_LTK_UNAUTHENTICATED)
+		switch (key->type) {
+		case MGMT_LTK_UNAUTHENTICATED:
 			authenticated = 0x00;
 			authenticated = 0x00;
-		else
+			break;
+		case MGMT_LTK_AUTHENTICATED:
 			authenticated = 0x01;
 			authenticated = 0x01;
+			break;
+		default:
+			continue;
+		}
 
 
 		hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
 		hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
 			    authenticated, key->val, key->enc_size, key->ediv,
 			    authenticated, key->val, key->enc_size, key->ediv,

+ 4 - 3
net/bluetooth/smp.c

@@ -909,10 +909,11 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
 
 
 	authreq = seclevel_to_authreq(sec_level);
 	authreq = seclevel_to_authreq(sec_level);
 
 
-	/* hcon->auth_type is set by pair_device in mgmt.c. If the MITM
-	 * flag is set we should also set it for the SMP request.
+	/* Require MITM if IO Capability allows or the security level
+	 * requires it.
 	 */
 	 */
-	if ((hcon->auth_type & 0x01))
+	if (hcon->io_capability != HCI_IO_NO_INPUT_OUTPUT ||
+	    sec_level > BT_SECURITY_MEDIUM)
 		authreq |= SMP_AUTH_MITM;
 		authreq |= SMP_AUTH_MITM;
 
 
 	if (hcon->link_mode & HCI_LM_MASTER) {
 	if (hcon->link_mode & HCI_LM_MASTER) {