Skip to content

Commit

Permalink
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/gi…
Browse files Browse the repository at this point in the history
…t/linville/wireless-next into for-davem
  • Loading branch information
John W. Linville committed Jun 6, 2014
2 parents 9e89fd8 + c678de5 commit c6ac68a
Show file tree
Hide file tree
Showing 9 changed files with 116 additions and 38 deletions.
3 changes: 2 additions & 1 deletion drivers/bluetooth/ath3k.c
Original file line number Diff line number Diff line change
Expand Up @@ -193,9 +193,10 @@ static int ath3k_load_firmware(struct usb_device *udev,
sent += 20;
count -= 20;

pipe = usb_sndbulkpipe(udev, 0x02);

while (count) {
size = min_t(uint, count, BULK_SIZE);
pipe = usb_sndbulkpipe(udev, 0x02);
memcpy(send_buf, firmware->data + sent, size);

err = usb_bulk_msg(udev, pipe, send_buf, size,
Expand Down
53 changes: 53 additions & 0 deletions drivers/net/wireless/at76c50x-usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -1429,6 +1429,8 @@ static int at76_startup_device(struct at76_priv *priv)
/* remove BSSID from previous run */
memset(priv->bssid, 0, ETH_ALEN);

priv->scanning = false;

if (at76_set_radio(priv, 1) == 1)
at76_wait_completion(priv, CMD_RADIO_ON);

Expand Down Expand Up @@ -1502,6 +1504,52 @@ static void at76_work_submit_rx(struct work_struct *work)
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)
{
struct urb *urb = (struct urb *)param;
Expand Down Expand Up @@ -1542,6 +1590,8 @@ static void at76_rx_tasklet(unsigned long param)
rx_status.signal = buf->rssi;
rx_status.flag |= RX_FLAG_DECRYPTED;
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",
priv->rx_skb->len, priv->rx_skb->data_len);
Expand Down Expand Up @@ -1894,6 +1944,8 @@ static void at76_dwork_hw_scan(struct work_struct *work)
if (is_valid_ether_addr(priv->bssid))
at76_join(priv);

priv->scanning = false;

mutex_unlock(&priv->mtx);

ieee80211_scan_completed(priv->hw, false);
Expand Down Expand Up @@ -1948,6 +2000,7 @@ static int at76_hw_scan(struct ieee80211_hw *hw,
goto exit;
}

priv->scanning = true;
ieee80211_queue_delayed_work(priv->hw, &priv->dwork_hw_scan,
SCAN_POLL_INTERVAL);

Expand Down
1 change: 1 addition & 0 deletions drivers/net/wireless/at76c50x-usb.h
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,7 @@ struct at76_priv {
int scan_max_time; /* scan max channel time */
int scan_mode; /* SCAN_TYPE_ACTIVE, SCAN_TYPE_PASSIVE */
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 */

Expand Down
65 changes: 35 additions & 30 deletions net/bluetooth/6lowpan.c
Original file line number Diff line number Diff line change
Expand Up @@ -420,29 +420,38 @@ static int conn_send(struct l2cap_conn *conn,
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[1] = eui64[6];
addr->b[2] = eui64[5];
addr->b[3] = eui64[2];
addr->b[4] = eui64[1];
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,
Expand Down Expand Up @@ -473,9 +482,11 @@ static int header_create(struct sk_buff *skb, struct net_device *netdev,
/* Get destination BT device from skb.
* 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);
peer = peer_lookup_ba(dev, &addr, addr_type);
Expand Down Expand Up @@ -556,16 +567,18 @@ static netdev_tx_t bt_xmit(struct sk_buff *skb, struct net_device *netdev)
} else {
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;
dev = lowpan_dev(netdev);

read_lock_irqsave(&devices_lock, flags);
peer = peer_lookup_ba(dev, &addr, addr_type);
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)
err = send_pkt(peer->conn, netdev->dev_addr,
Expand Down Expand Up @@ -620,21 +633,20 @@ static void set_addr(u8 *eui, u8 *addr, u8 addr_type)
eui[6] = addr[1];
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)
eui[0] |= 1;
eui[0] &= ~0x02;
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,
u8 addr_type)
{
netdev->addr_assign_type = NET_ADDR_PERM;
set_addr(netdev->dev_addr, addr->b, addr_type);
netdev->dev_addr[0] ^= 2;
}

static void ifup(struct net_device *netdev)
Expand Down Expand Up @@ -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,
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);
INIT_LIST_HEAD(&peer->list);
Expand Down
4 changes: 3 additions & 1 deletion net/bluetooth/hci_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -1453,6 +1453,7 @@ static int hci_outgoing_auth_needed(struct hci_dev *hdev,
* is requested.
*/
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_MEDIUM)
return 0;
Expand Down Expand Up @@ -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 &&
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",
hdev->name);
goto not_found;
Expand Down
6 changes: 6 additions & 0 deletions net/bluetooth/l2cap_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -471,8 +471,14 @@ void l2cap_chan_set_defaults(struct l2cap_chan *chan)
chan->max_tx = L2CAP_DEFAULT_MAX_TX;
chan->tx_win = 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->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);
}
Expand Down
5 changes: 4 additions & 1 deletion net/bluetooth/l2cap_sock.c
Original file line number Diff line number Diff line change
Expand Up @@ -1180,13 +1180,16 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan)
/* Check for backlog size */
if (sk_acceptq_is_full(parent)) {
BT_DBG("backlog full %d", parent->sk_ack_backlog);
release_sock(parent);
return NULL;
}

sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP,
GFP_ATOMIC);
if (!sk)
if (!sk) {
release_sock(parent);
return NULL;
}

bt_sock_reclassify_lock(sk, BTPROTO_L2CAP);

Expand Down
10 changes: 8 additions & 2 deletions net/bluetooth/mgmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -4546,10 +4546,16 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
else
type = HCI_SMP_LTK_SLAVE;

if (key->type == MGMT_LTK_UNAUTHENTICATED)
switch (key->type) {
case MGMT_LTK_UNAUTHENTICATED:
authenticated = 0x00;
else
break;
case MGMT_LTK_AUTHENTICATED:
authenticated = 0x01;
break;
default:
continue;
}

hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
authenticated, key->val, key->enc_size, key->ediv,
Expand Down
7 changes: 4 additions & 3 deletions net/bluetooth/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -909,10 +909,11 @@ int smp_conn_security(struct hci_conn *hcon, __u8 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;

if (hcon->link_mode & HCI_LM_MASTER) {
Expand Down

0 comments on commit c6ac68a

Please sign in to comment.