Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
Johan Hedberg says: ==================== pull request: bluetooth-next 2016-07-13 Here's our main bluetooth-next pull request for the 4.8 kernel: - Fixes and cleanups in 802.15.4 and 6LoWPAN code - Fix out of bounds issue in btmrvl driver - Fixes to Bluetooth socket recvmsg return values - Use crypto_cipher_encrypt_one() instead of crypto_skcipher - Cleanup of Bluetooth connection sysfs interface - New Authentication failure reson code for Disconnected mgmt event - New USB IDs for Atheros, Qualcomm and Intel Bluetooth controllers Please let me know if there are any issues pulling. Thanks. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
0ba3deb346
|
@ -123,6 +123,7 @@ static const struct usb_device_id ath3k_table[] = {
|
|||
{ USB_DEVICE(0x13d3, 0x3472) },
|
||||
{ USB_DEVICE(0x13d3, 0x3474) },
|
||||
{ USB_DEVICE(0x13d3, 0x3487) },
|
||||
{ USB_DEVICE(0x13d3, 0x3490) },
|
||||
|
||||
/* Atheros AR5BBU12 with sflash firmware */
|
||||
{ USB_DEVICE(0x0489, 0xE02C) },
|
||||
|
@ -190,6 +191,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = {
|
|||
{ USB_DEVICE(0x13d3, 0x3472), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3474), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3487), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3490), .driver_info = BTUSB_ATH3012 },
|
||||
|
||||
/* Atheros AR5BBU22 with sflash firmware */
|
||||
{ USB_DEVICE(0x0489, 0xE036), .driver_info = BTUSB_ATH3012 },
|
||||
|
|
|
@ -138,7 +138,7 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb)
|
|||
if (event->length > 3 && event->data[3])
|
||||
priv->btmrvl_dev.dev_type = HCI_AMP;
|
||||
else
|
||||
priv->btmrvl_dev.dev_type = HCI_BREDR;
|
||||
priv->btmrvl_dev.dev_type = HCI_PRIMARY;
|
||||
|
||||
BT_DBG("dev_type: %d", priv->btmrvl_dev.dev_type);
|
||||
} else if (priv->btmrvl_dev.sendcmdflag &&
|
||||
|
|
|
@ -1071,7 +1071,6 @@ static int btmrvl_sdio_host_to_card(struct btmrvl_private *priv,
|
|||
{
|
||||
struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
|
||||
int ret = 0;
|
||||
int buf_block_len;
|
||||
int blksz;
|
||||
int i = 0;
|
||||
u8 *buf = NULL;
|
||||
|
@ -1083,9 +1082,13 @@ static int btmrvl_sdio_host_to_card(struct btmrvl_private *priv,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
blksz = DIV_ROUND_UP(nb, SDIO_BLOCK_SIZE) * SDIO_BLOCK_SIZE;
|
||||
|
||||
buf = payload;
|
||||
if ((unsigned long) payload & (BTSDIO_DMA_ALIGN - 1)) {
|
||||
tmpbufsz = ALIGN_SZ(nb, BTSDIO_DMA_ALIGN);
|
||||
if ((unsigned long) payload & (BTSDIO_DMA_ALIGN - 1) ||
|
||||
nb < blksz) {
|
||||
tmpbufsz = ALIGN_SZ(blksz, BTSDIO_DMA_ALIGN) +
|
||||
BTSDIO_DMA_ALIGN;
|
||||
tmpbuf = kzalloc(tmpbufsz, GFP_KERNEL);
|
||||
if (!tmpbuf)
|
||||
return -ENOMEM;
|
||||
|
@ -1093,15 +1096,12 @@ static int btmrvl_sdio_host_to_card(struct btmrvl_private *priv,
|
|||
memcpy(buf, payload, nb);
|
||||
}
|
||||
|
||||
blksz = SDIO_BLOCK_SIZE;
|
||||
buf_block_len = DIV_ROUND_UP(nb, blksz);
|
||||
|
||||
sdio_claim_host(card->func);
|
||||
|
||||
do {
|
||||
/* Transfer data to card */
|
||||
ret = sdio_writesb(card->func, card->ioport, buf,
|
||||
buf_block_len * blksz);
|
||||
blksz);
|
||||
if (ret < 0) {
|
||||
i++;
|
||||
BT_ERR("i=%d writesb failed: %d", i, ret);
|
||||
|
|
|
@ -311,7 +311,7 @@ static int btsdio_probe(struct sdio_func *func,
|
|||
if (id->class == SDIO_CLASS_BT_AMP)
|
||||
hdev->dev_type = HCI_AMP;
|
||||
else
|
||||
hdev->dev_type = HCI_BREDR;
|
||||
hdev->dev_type = HCI_PRIMARY;
|
||||
|
||||
data->hdev = hdev;
|
||||
|
||||
|
|
|
@ -237,6 +237,7 @@ static const struct usb_device_id blacklist_table[] = {
|
|||
{ USB_DEVICE(0x13d3, 0x3472), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3474), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3487), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3490), .driver_info = BTUSB_ATH3012 },
|
||||
|
||||
/* Atheros AR5BBU12 with sflash firmware */
|
||||
{ USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
|
||||
|
@ -249,6 +250,7 @@ static const struct usb_device_id blacklist_table[] = {
|
|||
{ USB_DEVICE(0x0cf3, 0xe007), .driver_info = BTUSB_QCA_ROME },
|
||||
{ USB_DEVICE(0x0cf3, 0xe300), .driver_info = BTUSB_QCA_ROME },
|
||||
{ USB_DEVICE(0x0cf3, 0xe360), .driver_info = BTUSB_QCA_ROME },
|
||||
{ USB_DEVICE(0x0489, 0xe092), .driver_info = BTUSB_QCA_ROME },
|
||||
|
||||
/* Broadcom BCM2035 */
|
||||
{ USB_DEVICE(0x0a5c, 0x2009), .driver_info = BTUSB_BCM92035 },
|
||||
|
@ -314,6 +316,7 @@ static const struct usb_device_id blacklist_table[] = {
|
|||
{ USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL },
|
||||
{ USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL },
|
||||
{ USB_DEVICE(0x8087, 0x0a2b), .driver_info = BTUSB_INTEL_NEW },
|
||||
{ USB_DEVICE(0x8087, 0x0aa7), .driver_info = BTUSB_INTEL },
|
||||
|
||||
/* Other Intel Bluetooth devices */
|
||||
{ USB_VENDOR_AND_INTERFACE_INFO(0x8087, 0xe0, 0x01, 0x01),
|
||||
|
@ -2103,10 +2106,14 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
|
|||
/* With this Intel bootloader only the hardware variant and device
|
||||
* revision information are used to select the right firmware.
|
||||
*
|
||||
* Currently this bootloader support is limited to hardware variant
|
||||
* iBT 3.0 (LnP/SfP) which is identified by the value 11 (0x0b).
|
||||
* The firmware filename is ibt-<hw_variant>-<dev_revid>.sfi.
|
||||
*
|
||||
* Currently the supported hardware variants are:
|
||||
* 11 (0x0b) for iBT3.0 (LnP/SfP)
|
||||
* 12 (0x0c) for iBT3.5 (WsP)
|
||||
*/
|
||||
snprintf(fwname, sizeof(fwname), "intel/ibt-11-%u.sfi",
|
||||
snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u.sfi",
|
||||
le16_to_cpu(ver.hw_variant),
|
||||
le16_to_cpu(params->dev_revid));
|
||||
|
||||
err = request_firmware(&fw, fwname, &hdev->dev);
|
||||
|
@ -2122,7 +2129,8 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
|
|||
/* Save the DDC file name for later use to apply once the firmware
|
||||
* downloading is done.
|
||||
*/
|
||||
snprintf(fwname, sizeof(fwname), "intel/ibt-11-%u.ddc",
|
||||
snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u.ddc",
|
||||
le16_to_cpu(ver.hw_variant),
|
||||
le16_to_cpu(params->dev_revid));
|
||||
|
||||
kfree_skb(skb);
|
||||
|
@ -2825,7 +2833,7 @@ static int btusb_probe(struct usb_interface *intf,
|
|||
if (id->driver_info & BTUSB_AMP)
|
||||
hdev->dev_type = HCI_AMP;
|
||||
else
|
||||
hdev->dev_type = HCI_BREDR;
|
||||
hdev->dev_type = HCI_PRIMARY;
|
||||
|
||||
data->hdev = hdev;
|
||||
|
||||
|
|
|
@ -537,9 +537,7 @@ static int intel_setup(struct hci_uart *hu)
|
|||
{
|
||||
static const u8 reset_param[] = { 0x00, 0x01, 0x00, 0x01,
|
||||
0x00, 0x08, 0x04, 0x00 };
|
||||
static const u8 lpm_param[] = { 0x03, 0x07, 0x01, 0x0b };
|
||||
struct intel_data *intel = hu->priv;
|
||||
struct intel_device *idev = NULL;
|
||||
struct hci_dev *hdev = hu->hdev;
|
||||
struct sk_buff *skb;
|
||||
struct intel_version ver;
|
||||
|
@ -884,35 +882,23 @@ done:
|
|||
|
||||
bt_dev_info(hdev, "Device booted in %llu usecs", duration);
|
||||
|
||||
/* Enable LPM if matching pdev with wakeup enabled */
|
||||
/* Enable LPM if matching pdev with wakeup enabled, set TX active
|
||||
* until further LPM TX notification.
|
||||
*/
|
||||
mutex_lock(&intel_device_list_lock);
|
||||
list_for_each(p, &intel_device_list) {
|
||||
struct intel_device *dev = list_entry(p, struct intel_device,
|
||||
list);
|
||||
if (hu->tty->dev->parent == dev->pdev->dev.parent) {
|
||||
if (device_may_wakeup(&dev->pdev->dev))
|
||||
idev = dev;
|
||||
if (device_may_wakeup(&dev->pdev->dev)) {
|
||||
set_bit(STATE_LPM_ENABLED, &intel->flags);
|
||||
set_bit(STATE_TX_ACTIVE, &intel->flags);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&intel_device_list_lock);
|
||||
|
||||
if (!idev)
|
||||
goto no_lpm;
|
||||
|
||||
bt_dev_info(hdev, "Enabling LPM");
|
||||
|
||||
skb = __hci_cmd_sync(hdev, 0xfc8b, sizeof(lpm_param), lpm_param,
|
||||
HCI_CMD_TIMEOUT);
|
||||
if (IS_ERR(skb)) {
|
||||
bt_dev_err(hdev, "Failed to enable LPM");
|
||||
goto no_lpm;
|
||||
}
|
||||
kfree_skb(skb);
|
||||
|
||||
set_bit(STATE_LPM_ENABLED, &intel->flags);
|
||||
|
||||
no_lpm:
|
||||
/* Ignore errors, device can work without DDC parameters */
|
||||
btintel_load_ddc_config(hdev, fwname);
|
||||
|
||||
|
|
|
@ -609,7 +609,7 @@ static int hci_uart_register_dev(struct hci_uart *hu)
|
|||
if (test_bit(HCI_UART_CREATE_AMP, &hu->hdev_flags))
|
||||
hdev->dev_type = HCI_AMP;
|
||||
else
|
||||
hdev->dev_type = HCI_BREDR;
|
||||
hdev->dev_type = HCI_PRIMARY;
|
||||
|
||||
if (test_bit(HCI_UART_INIT_PENDING, &hu->hdev_flags))
|
||||
return 0;
|
||||
|
|
|
@ -97,10 +97,10 @@ static int __vhci_create_device(struct vhci_data *data, __u8 opcode)
|
|||
if (data->hdev)
|
||||
return -EBADFD;
|
||||
|
||||
/* bits 0-1 are dev_type (BR/EDR or AMP) */
|
||||
/* bits 0-1 are dev_type (Primary or AMP) */
|
||||
dev_type = opcode & 0x03;
|
||||
|
||||
if (dev_type != HCI_BREDR && dev_type != HCI_AMP)
|
||||
if (dev_type != HCI_PRIMARY && dev_type != HCI_AMP)
|
||||
return -EINVAL;
|
||||
|
||||
/* bits 2-5 are reserved (must be zero) */
|
||||
|
@ -316,7 +316,7 @@ static void vhci_open_timeout(struct work_struct *work)
|
|||
struct vhci_data *data = container_of(work, struct vhci_data,
|
||||
open_timeout.work);
|
||||
|
||||
vhci_create_device(data, amp ? HCI_AMP : HCI_BREDR);
|
||||
vhci_create_device(data, amp ? HCI_AMP : HCI_PRIMARY);
|
||||
}
|
||||
|
||||
static int vhci_open(struct inode *inode, struct file *file)
|
||||
|
|
|
@ -366,11 +366,7 @@ static int atusb_channel(struct ieee802154_hw *hw, u8 page, u8 channel)
|
|||
struct atusb *atusb = hw->priv;
|
||||
int ret;
|
||||
|
||||
/* This implicitly sets the CCA (Clear Channel Assessment) mode to 0,
|
||||
* "Mode 3a, Carrier sense OR energy above threshold".
|
||||
* We should probably make this configurable. @@@
|
||||
*/
|
||||
ret = atusb_write_reg(atusb, RG_PHY_CC_CCA, channel);
|
||||
ret = atusb_write_subreg(atusb, SR_CHANNEL, channel);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
msleep(1); /* @@@ ugly synchronization */
|
||||
|
|
|
@ -112,6 +112,12 @@ static void fakelb_hw_stop(struct ieee802154_hw *hw)
|
|||
write_unlock_bh(&fakelb_ifup_phys_lock);
|
||||
}
|
||||
|
||||
static int
|
||||
fakelb_set_promiscuous_mode(struct ieee802154_hw *hw, const bool on)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct ieee802154_ops fakelb_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.xmit_async = fakelb_hw_xmit,
|
||||
|
@ -119,6 +125,7 @@ static const struct ieee802154_ops fakelb_ops = {
|
|||
.set_channel = fakelb_hw_channel,
|
||||
.start = fakelb_hw_start,
|
||||
.stop = fakelb_hw_stop,
|
||||
.set_promiscuous_mode = fakelb_set_promiscuous_mode,
|
||||
};
|
||||
|
||||
/* Number of dummy devices to be set up by this module. */
|
||||
|
@ -174,6 +181,7 @@ static int fakelb_add_one(struct device *dev)
|
|||
hw->phy->current_channel = 13;
|
||||
phy->channel = hw->phy->current_channel;
|
||||
|
||||
hw->flags = IEEE802154_HW_PROMISCUOUS;
|
||||
hw->parent = dev;
|
||||
|
||||
err = ieee802154_register_hw(hw);
|
||||
|
|
|
@ -1054,6 +1054,8 @@ static irqreturn_t mrf24j40_isr(int irq, void *data)
|
|||
disable_irq_nosync(irq);
|
||||
|
||||
devrec->irq_buf[0] = MRF24J40_READSHORT(REG_INTSTAT);
|
||||
devrec->irq_buf[1] = 0;
|
||||
|
||||
/* Read the interrupt status */
|
||||
ret = spi_async(devrec->spi, &devrec->irq_msg);
|
||||
if (ret) {
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
#define IEEE802154_MIN_PSDU_LEN 9
|
||||
#define IEEE802154_FCS_LEN 2
|
||||
#define IEEE802154_MAX_AUTH_TAG_LEN 16
|
||||
#define IEEE802154_FC_LEN 2
|
||||
#define IEEE802154_SEQ_LEN 1
|
||||
|
||||
/* General MAC frame format:
|
||||
* 2 bytes: Frame Control
|
||||
|
@ -48,6 +50,7 @@
|
|||
|
||||
#define IEEE802154_EXTENDED_ADDR_LEN 8
|
||||
#define IEEE802154_SHORT_ADDR_LEN 2
|
||||
#define IEEE802154_PAN_ID_LEN 2
|
||||
|
||||
#define IEEE802154_LIFS_PERIOD 40
|
||||
#define IEEE802154_SIFS_PERIOD 12
|
||||
|
@ -221,9 +224,17 @@ enum {
|
|||
#define IEEE802154_FCTL_ACKREQ 0x0020
|
||||
#define IEEE802154_FCTL_SECEN 0x0004
|
||||
#define IEEE802154_FCTL_INTRA_PAN 0x0040
|
||||
#define IEEE802154_FCTL_DADDR 0x0c00
|
||||
#define IEEE802154_FCTL_SADDR 0xc000
|
||||
|
||||
#define IEEE802154_FTYPE_DATA 0x0001
|
||||
|
||||
#define IEEE802154_FCTL_ADDR_NONE 0x0000
|
||||
#define IEEE802154_FCTL_DADDR_SHORT 0x0800
|
||||
#define IEEE802154_FCTL_DADDR_EXTENDED 0x0c00
|
||||
#define IEEE802154_FCTL_SADDR_SHORT 0x8000
|
||||
#define IEEE802154_FCTL_SADDR_EXTENDED 0xc000
|
||||
|
||||
/*
|
||||
* ieee802154_is_data - check if type is IEEE802154_FTYPE_DATA
|
||||
* @fc: frame control bytes in little-endian byteorder
|
||||
|
@ -261,6 +272,24 @@ static inline bool ieee802154_is_intra_pan(__le16 fc)
|
|||
return fc & cpu_to_le16(IEEE802154_FCTL_INTRA_PAN);
|
||||
}
|
||||
|
||||
/*
|
||||
* ieee802154_daddr_mode - get daddr mode from fc
|
||||
* @fc: frame control bytes in little-endian byteorder
|
||||
*/
|
||||
static inline __le16 ieee802154_daddr_mode(__le16 fc)
|
||||
{
|
||||
return fc & cpu_to_le16(IEEE802154_FCTL_DADDR);
|
||||
}
|
||||
|
||||
/*
|
||||
* ieee802154_saddr_mode - get saddr mode from fc
|
||||
* @fc: frame control bytes in little-endian byteorder
|
||||
*/
|
||||
static inline __le16 ieee802154_saddr_mode(__le16 fc)
|
||||
{
|
||||
return fc & cpu_to_le16(IEEE802154_FCTL_SADDR);
|
||||
}
|
||||
|
||||
/**
|
||||
* ieee802154_is_valid_psdu_len - check if psdu len is valid
|
||||
* available lengths:
|
||||
|
|
|
@ -65,7 +65,7 @@
|
|||
#define HCI_I2C 8
|
||||
|
||||
/* HCI controller types */
|
||||
#define HCI_BREDR 0x00
|
||||
#define HCI_PRIMARY 0x00
|
||||
#define HCI_AMP 0x01
|
||||
|
||||
/* First BR/EDR Controller shall have ID = 0 */
|
||||
|
@ -445,6 +445,7 @@ enum {
|
|||
/* ---- HCI Error Codes ---- */
|
||||
#define HCI_ERROR_UNKNOWN_CONN_ID 0x02
|
||||
#define HCI_ERROR_AUTH_FAILURE 0x05
|
||||
#define HCI_ERROR_PIN_OR_KEY_MISSING 0x06
|
||||
#define HCI_ERROR_MEMORY_EXCEEDED 0x07
|
||||
#define HCI_ERROR_CONNECTION_TIMEOUT 0x08
|
||||
#define HCI_ERROR_REJ_LIMITED_RESOURCES 0x0d
|
||||
|
|
|
@ -654,6 +654,7 @@ enum {
|
|||
HCI_CONN_PARAM_REMOVAL_PEND,
|
||||
HCI_CONN_NEW_LINK_KEY,
|
||||
HCI_CONN_SCANNING,
|
||||
HCI_CONN_AUTH_FAILURE,
|
||||
};
|
||||
|
||||
static inline bool hci_conn_ssp_enabled(struct hci_conn *conn)
|
||||
|
|
|
@ -645,6 +645,7 @@ struct mgmt_ev_device_connected {
|
|||
#define MGMT_DEV_DISCONN_TIMEOUT 0x01
|
||||
#define MGMT_DEV_DISCONN_LOCAL_HOST 0x02
|
||||
#define MGMT_DEV_DISCONN_REMOTE 0x03
|
||||
#define MGMT_DEV_DISCONN_AUTH_FAILURE 0x04
|
||||
|
||||
#define MGMT_EV_DEVICE_DISCONNECTED 0x000C
|
||||
struct mgmt_ev_device_disconnected {
|
||||
|
|
|
@ -219,9 +219,22 @@ struct wpan_phy {
|
|||
|
||||
struct device dev;
|
||||
|
||||
/* the network namespace this phy lives in currently */
|
||||
possible_net_t _net;
|
||||
|
||||
char priv[0] __aligned(NETDEV_ALIGN);
|
||||
};
|
||||
|
||||
static inline struct net *wpan_phy_net(struct wpan_phy *wpan_phy)
|
||||
{
|
||||
return read_pnet(&wpan_phy->_net);
|
||||
}
|
||||
|
||||
static inline void wpan_phy_net_set(struct wpan_phy *wpan_phy, struct net *net)
|
||||
{
|
||||
write_pnet(&wpan_phy->_net, net);
|
||||
}
|
||||
|
||||
struct ieee802154_addr {
|
||||
u8 mode;
|
||||
__le16 pan_id;
|
||||
|
|
|
@ -247,14 +247,123 @@ struct ieee802154_ops {
|
|||
*/
|
||||
static inline __le16 ieee802154_get_fc_from_skb(const struct sk_buff *skb)
|
||||
{
|
||||
__le16 fc;
|
||||
|
||||
/* check if we can fc at skb_mac_header of sk buffer */
|
||||
if (unlikely(!skb_mac_header_was_set(skb) ||
|
||||
(skb_tail_pointer(skb) - skb_mac_header(skb)) < 2)) {
|
||||
WARN_ON(1);
|
||||
if (WARN_ON(!skb_mac_header_was_set(skb) ||
|
||||
(skb_tail_pointer(skb) -
|
||||
skb_mac_header(skb)) < IEEE802154_FC_LEN))
|
||||
return cpu_to_le16(0);
|
||||
|
||||
memcpy(&fc, skb_mac_header(skb), IEEE802154_FC_LEN);
|
||||
return fc;
|
||||
}
|
||||
|
||||
/**
|
||||
* ieee802154_skb_dst_pan - get the pointer to destination pan field
|
||||
* @fc: mac header frame control field
|
||||
* @skb: skb where the destination pan pointer will be get from
|
||||
*/
|
||||
static inline unsigned char *ieee802154_skb_dst_pan(__le16 fc,
|
||||
const struct sk_buff *skb)
|
||||
{
|
||||
unsigned char *dst_pan;
|
||||
|
||||
switch (ieee802154_daddr_mode(fc)) {
|
||||
case cpu_to_le16(IEEE802154_FCTL_ADDR_NONE):
|
||||
dst_pan = NULL;
|
||||
break;
|
||||
case cpu_to_le16(IEEE802154_FCTL_DADDR_SHORT):
|
||||
case cpu_to_le16(IEEE802154_FCTL_DADDR_EXTENDED):
|
||||
dst_pan = skb_mac_header(skb) +
|
||||
IEEE802154_FC_LEN +
|
||||
IEEE802154_SEQ_LEN;
|
||||
break;
|
||||
default:
|
||||
WARN_ONCE(1, "invalid addr mode detected");
|
||||
dst_pan = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
return get_unaligned_le16(skb_mac_header(skb));
|
||||
return dst_pan;
|
||||
}
|
||||
|
||||
/**
|
||||
* ieee802154_skb_src_pan - get the pointer to source pan field
|
||||
* @fc: mac header frame control field
|
||||
* @skb: skb where the source pan pointer will be get from
|
||||
*/
|
||||
static inline unsigned char *ieee802154_skb_src_pan(__le16 fc,
|
||||
const struct sk_buff *skb)
|
||||
{
|
||||
unsigned char *src_pan;
|
||||
|
||||
switch (ieee802154_saddr_mode(fc)) {
|
||||
case cpu_to_le16(IEEE802154_FCTL_ADDR_NONE):
|
||||
src_pan = NULL;
|
||||
break;
|
||||
case cpu_to_le16(IEEE802154_FCTL_SADDR_SHORT):
|
||||
case cpu_to_le16(IEEE802154_FCTL_SADDR_EXTENDED):
|
||||
/* if intra-pan and source addr mode is non none,
|
||||
* then source pan id is equal destination pan id.
|
||||
*/
|
||||
if (ieee802154_is_intra_pan(fc)) {
|
||||
src_pan = ieee802154_skb_dst_pan(fc, skb);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (ieee802154_daddr_mode(fc)) {
|
||||
case cpu_to_le16(IEEE802154_FCTL_ADDR_NONE):
|
||||
src_pan = skb_mac_header(skb) +
|
||||
IEEE802154_FC_LEN +
|
||||
IEEE802154_SEQ_LEN;
|
||||
break;
|
||||
case cpu_to_le16(IEEE802154_FCTL_DADDR_SHORT):
|
||||
src_pan = skb_mac_header(skb) +
|
||||
IEEE802154_FC_LEN +
|
||||
IEEE802154_SEQ_LEN +
|
||||
IEEE802154_PAN_ID_LEN +
|
||||
IEEE802154_SHORT_ADDR_LEN;
|
||||
break;
|
||||
case cpu_to_le16(IEEE802154_FCTL_DADDR_EXTENDED):
|
||||
src_pan = skb_mac_header(skb) +
|
||||
IEEE802154_FC_LEN +
|
||||
IEEE802154_SEQ_LEN +
|
||||
IEEE802154_PAN_ID_LEN +
|
||||
IEEE802154_EXTENDED_ADDR_LEN;
|
||||
break;
|
||||
default:
|
||||
WARN_ONCE(1, "invalid addr mode detected");
|
||||
src_pan = NULL;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
WARN_ONCE(1, "invalid addr mode detected");
|
||||
src_pan = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
return src_pan;
|
||||
}
|
||||
|
||||
/**
|
||||
* ieee802154_skb_is_intra_pan_addressing - checks whenever the mac addressing
|
||||
* is an intra pan communication
|
||||
* @fc: mac header frame control field
|
||||
* @skb: skb where the source and destination pan should be get from
|
||||
*/
|
||||
static inline bool ieee802154_skb_is_intra_pan_addressing(__le16 fc,
|
||||
const struct sk_buff *skb)
|
||||
{
|
||||
unsigned char *dst_pan = ieee802154_skb_dst_pan(fc, skb),
|
||||
*src_pan = ieee802154_skb_src_pan(fc, skb);
|
||||
|
||||
/* if one is NULL is no intra pan addressing */
|
||||
if (!dst_pan || !src_pan)
|
||||
return false;
|
||||
|
||||
return !memcmp(dst_pan, src_pan, IEEE802154_PAN_ID_LEN);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -54,6 +54,8 @@ enum nl802154_commands {
|
|||
|
||||
NL802154_CMD_SET_ACKREQ_DEFAULT,
|
||||
|
||||
NL802154_CMD_SET_WPAN_PHY_NETNS,
|
||||
|
||||
/* add new commands above here */
|
||||
|
||||
#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
|
||||
|
@ -124,6 +126,11 @@ enum nl802154_attrs {
|
|||
|
||||
NL802154_ATTR_ACKREQ_DEFAULT,
|
||||
|
||||
NL802154_ATTR_PAD,
|
||||
|
||||
NL802154_ATTR_PID,
|
||||
NL802154_ATTR_NETNS_FD,
|
||||
|
||||
/* add attributes here, update the policy in nl802154.c */
|
||||
|
||||
#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
|
||||
|
@ -138,8 +145,6 @@ enum nl802154_attrs {
|
|||
NL802154_ATTR_SEC_KEY,
|
||||
#endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
|
||||
|
||||
NL802154_ATTR_PAD,
|
||||
|
||||
__NL802154_ATTR_AFTER_LAST,
|
||||
NL802154_ATTR_MAX = __NL802154_ATTR_AFTER_LAST - 1
|
||||
};
|
||||
|
|
|
@ -47,6 +47,9 @@ static int lowpan_ndisc_parse_options(const struct net_device *dev,
|
|||
struct nd_opt_hdr *nd_opt,
|
||||
struct ndisc_options *ndopts)
|
||||
{
|
||||
if (!lowpan_is_ll(dev, LOWPAN_LLTYPE_IEEE802154))
|
||||
return 0;
|
||||
|
||||
switch (nd_opt->nd_opt_type) {
|
||||
case ND_OPT_SOURCE_LL_ADDR:
|
||||
case ND_OPT_TARGET_LL_ADDR:
|
||||
|
@ -94,10 +97,13 @@ static void lowpan_ndisc_802154_update(struct neighbour *n, u32 flags,
|
|||
}
|
||||
|
||||
write_lock_bh(&n->lock);
|
||||
if (lladdr_short)
|
||||
if (lladdr_short) {
|
||||
ieee802154_be16_to_le16(&neigh->short_addr, lladdr_short);
|
||||
else
|
||||
if (!lowpan_802154_is_valid_src_short_addr(neigh->short_addr))
|
||||
neigh->short_addr = cpu_to_le16(IEEE802154_ADDR_SHORT_UNSPEC);
|
||||
} else {
|
||||
neigh->short_addr = cpu_to_le16(IEEE802154_ADDR_SHORT_UNSPEC);
|
||||
}
|
||||
write_unlock_bh(&n->lock);
|
||||
}
|
||||
|
||||
|
@ -135,8 +141,9 @@ static int lowpan_ndisc_opt_addr_space(const struct net_device *dev,
|
|||
read_unlock_bh(&neigh->lock);
|
||||
addr_space += __ndisc_opt_addr_space(IEEE802154_SHORT_ADDR_LEN, 0);
|
||||
*ha = ha_buf;
|
||||
} else {
|
||||
read_unlock_bh(&neigh->lock);
|
||||
}
|
||||
read_unlock_bh(&neigh->lock);
|
||||
break;
|
||||
case NDISC_NEIGHBOUR_ADVERTISEMENT:
|
||||
case NDISC_NEIGHBOUR_SOLICITATION:
|
||||
|
|
|
@ -215,6 +215,7 @@ int bt_sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
|
|||
struct sock *sk = sock->sk;
|
||||
struct sk_buff *skb;
|
||||
size_t copied;
|
||||
size_t skblen;
|
||||
int err;
|
||||
|
||||
BT_DBG("sock %p sk %p len %zu", sock, sk, len);
|
||||
|
@ -230,6 +231,7 @@ int bt_sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
|
|||
return err;
|
||||
}
|
||||
|
||||
skblen = skb->len;
|
||||
copied = skb->len;
|
||||
if (len < copied) {
|
||||
msg->msg_flags |= MSG_TRUNC;
|
||||
|
@ -248,6 +250,9 @@ int bt_sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
|
|||
|
||||
skb_free_datagram(sk, skb);
|
||||
|
||||
if (msg->msg_flags & MSG_TRUNC)
|
||||
copied = skblen;
|
||||
|
||||
return err ? : copied;
|
||||
}
|
||||
EXPORT_SYMBOL(bt_sock_recvmsg);
|
||||
|
|
|
@ -625,7 +625,7 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src)
|
|||
list_for_each_entry(d, &hci_dev_list, list) {
|
||||
if (!test_bit(HCI_UP, &d->flags) ||
|
||||
hci_dev_test_flag(d, HCI_USER_CHANNEL) ||
|
||||
d->dev_type != HCI_BREDR)
|
||||
d->dev_type != HCI_PRIMARY)
|
||||
continue;
|
||||
|
||||
/* Simple routing:
|
||||
|
|
|
@ -260,14 +260,12 @@ static int hci_init1_req(struct hci_request *req, unsigned long opt)
|
|||
hci_reset_req(req, 0);
|
||||
|
||||
switch (hdev->dev_type) {
|
||||
case HCI_BREDR:
|
||||
case HCI_PRIMARY:
|
||||
bredr_init(req);
|
||||
break;
|
||||
|
||||
case HCI_AMP:
|
||||
amp_init1(req);
|
||||
break;
|
||||
|
||||
default:
|
||||
BT_ERR("Unknown device type %d", hdev->dev_type);
|
||||
break;
|
||||
|
@ -791,11 +789,11 @@ static int __hci_init(struct hci_dev *hdev)
|
|||
if (err < 0)
|
||||
return err;
|
||||
|
||||
/* HCI_BREDR covers both single-mode LE, BR/EDR and dual-mode
|
||||
/* HCI_PRIMARY covers both single-mode LE, BR/EDR and dual-mode
|
||||
* BR/EDR/LE type controllers. AMP controllers only need the
|
||||
* first two stages of init.
|
||||
*/
|
||||
if (hdev->dev_type != HCI_BREDR)
|
||||
if (hdev->dev_type != HCI_PRIMARY)
|
||||
return 0;
|
||||
|
||||
err = __hci_req_sync(hdev, hci_init3_req, 0, HCI_INIT_TIMEOUT, NULL);
|
||||
|
@ -1202,7 +1200,7 @@ int hci_inquiry(void __user *arg)
|
|||
goto done;
|
||||
}
|
||||
|
||||
if (hdev->dev_type != HCI_BREDR) {
|
||||
if (hdev->dev_type != HCI_PRIMARY) {
|
||||
err = -EOPNOTSUPP;
|
||||
goto done;
|
||||
}
|
||||
|
@ -1307,7 +1305,7 @@ static int hci_dev_do_open(struct hci_dev *hdev)
|
|||
* since AMP controllers do not have an address.
|
||||
*/
|
||||
if (!hci_dev_test_flag(hdev, HCI_USER_CHANNEL) &&
|
||||
hdev->dev_type == HCI_BREDR &&
|
||||
hdev->dev_type == HCI_PRIMARY &&
|
||||
!bacmp(&hdev->bdaddr, BDADDR_ANY) &&
|
||||
!bacmp(&hdev->static_addr, BDADDR_ANY)) {
|
||||
ret = -EADDRNOTAVAIL;
|
||||
|
@ -1402,7 +1400,7 @@ static int hci_dev_do_open(struct hci_dev *hdev)
|
|||
!hci_dev_test_flag(hdev, HCI_UNCONFIGURED) &&
|
||||
!hci_dev_test_flag(hdev, HCI_USER_CHANNEL) &&
|
||||
hci_dev_test_flag(hdev, HCI_MGMT) &&
|
||||
hdev->dev_type == HCI_BREDR) {
|
||||
hdev->dev_type == HCI_PRIMARY) {
|
||||
ret = __hci_req_hci_power_on(hdev);
|
||||
mgmt_power_on(hdev, ret);
|
||||
}
|
||||
|
@ -1563,7 +1561,7 @@ int hci_dev_do_close(struct hci_dev *hdev)
|
|||
|
||||
auto_off = hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF);
|
||||
|
||||
if (!auto_off && hdev->dev_type == HCI_BREDR &&
|
||||
if (!auto_off && hdev->dev_type == HCI_PRIMARY &&
|
||||
hci_dev_test_flag(hdev, HCI_MGMT))
|
||||
__mgmt_power_off(hdev);
|
||||
|
||||
|
@ -1802,7 +1800,7 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg)
|
|||
goto done;
|
||||
}
|
||||
|
||||
if (hdev->dev_type != HCI_BREDR) {
|
||||
if (hdev->dev_type != HCI_PRIMARY) {
|
||||
err = -EOPNOTSUPP;
|
||||
goto done;
|
||||
}
|
||||
|
@ -2043,7 +2041,7 @@ static void hci_power_on(struct work_struct *work)
|
|||
*/
|
||||
if (hci_dev_test_flag(hdev, HCI_RFKILLED) ||
|
||||
hci_dev_test_flag(hdev, HCI_UNCONFIGURED) ||
|
||||
(hdev->dev_type == HCI_BREDR &&
|
||||
(hdev->dev_type == HCI_PRIMARY &&
|
||||
!bacmp(&hdev->bdaddr, BDADDR_ANY) &&
|
||||
!bacmp(&hdev->static_addr, BDADDR_ANY))) {
|
||||
hci_dev_clear_flag(hdev, HCI_AUTO_OFF);
|
||||
|
@ -3030,7 +3028,7 @@ int hci_register_dev(struct hci_dev *hdev)
|
|||
* so the index can be used as the AMP controller ID.
|
||||
*/
|
||||
switch (hdev->dev_type) {
|
||||
case HCI_BREDR:
|
||||
case HCI_PRIMARY:
|
||||
id = ida_simple_get(&hci_index_ida, 0, 0, GFP_KERNEL);
|
||||
break;
|
||||
case HCI_AMP:
|
||||
|
@ -3090,7 +3088,7 @@ int hci_register_dev(struct hci_dev *hdev)
|
|||
hci_dev_set_flag(hdev, HCI_SETUP);
|
||||
hci_dev_set_flag(hdev, HCI_AUTO_OFF);
|
||||
|
||||
if (hdev->dev_type == HCI_BREDR) {
|
||||
if (hdev->dev_type == HCI_PRIMARY) {
|
||||
/* Assume BR/EDR support until proven otherwise (such as
|
||||
* through reading supported features during init.
|
||||
*/
|
||||
|
@ -3415,7 +3413,7 @@ static void hci_queue_acl(struct hci_chan *chan, struct sk_buff_head *queue,
|
|||
hci_skb_pkt_type(skb) = HCI_ACLDATA_PKT;
|
||||
|
||||
switch (hdev->dev_type) {
|
||||
case HCI_BREDR:
|
||||
case HCI_PRIMARY:
|
||||
hci_add_acl_hdr(skb, conn->handle, flags);
|
||||
break;
|
||||
case HCI_AMP:
|
||||
|
@ -3826,7 +3824,7 @@ static void hci_sched_acl(struct hci_dev *hdev)
|
|||
BT_DBG("%s", hdev->name);
|
||||
|
||||
/* No ACL link over BR/EDR controller */
|
||||
if (!hci_conn_num(hdev, ACL_LINK) && hdev->dev_type == HCI_BREDR)
|
||||
if (!hci_conn_num(hdev, ACL_LINK) && hdev->dev_type == HCI_PRIMARY)
|
||||
return;
|
||||
|
||||
/* No AMP link over AMP controller */
|
||||
|
|
|
@ -2332,7 +2332,7 @@ static u8 hci_to_mgmt_reason(u8 err)
|
|||
static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
{
|
||||
struct hci_ev_disconn_complete *ev = (void *) skb->data;
|
||||
u8 reason = hci_to_mgmt_reason(ev->reason);
|
||||
u8 reason;
|
||||
struct hci_conn_params *params;
|
||||
struct hci_conn *conn;
|
||||
bool mgmt_connected;
|
||||
|
@ -2355,6 +2355,12 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
|||
conn->state = BT_CLOSED;
|
||||
|
||||
mgmt_connected = test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags);
|
||||
|
||||
if (test_bit(HCI_CONN_AUTH_FAILURE, &conn->flags))
|
||||
reason = MGMT_DEV_DISCONN_AUTH_FAILURE;
|
||||
else
|
||||
reason = hci_to_mgmt_reason(ev->reason);
|
||||
|
||||
mgmt_device_disconnected(hdev, &conn->dst, conn->type, conn->dst_type,
|
||||
reason, mgmt_connected);
|
||||
|
||||
|
@ -2421,6 +2427,8 @@ static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
|||
goto unlock;
|
||||
|
||||
if (!ev->status) {
|
||||
clear_bit(HCI_CONN_AUTH_FAILURE, &conn->flags);
|
||||
|
||||
if (!hci_conn_ssp_enabled(conn) &&
|
||||
test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
|
||||
BT_INFO("re-auth of legacy device is not possible.");
|
||||
|
@ -2429,6 +2437,9 @@ static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
|||
conn->sec_level = conn->pending_sec_level;
|
||||
}
|
||||
} else {
|
||||
if (ev->status == HCI_ERROR_PIN_OR_KEY_MISSING)
|
||||
set_bit(HCI_CONN_AUTH_FAILURE, &conn->flags);
|
||||
|
||||
mgmt_auth_failed(conn, ev->status);
|
||||
}
|
||||
|
||||
|
@ -2613,6 +2624,9 @@ static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
|||
clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
|
||||
|
||||
if (ev->status && conn->state == BT_CONNECTED) {
|
||||
if (ev->status == HCI_ERROR_PIN_OR_KEY_MISSING)
|
||||
set_bit(HCI_CONN_AUTH_FAILURE, &conn->flags);
|
||||
|
||||
hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
|
||||
hci_conn_drop(conn);
|
||||
goto unlock;
|
||||
|
@ -3249,7 +3263,7 @@ static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev,
|
|||
struct hci_chan *chan;
|
||||
|
||||
switch (hdev->dev_type) {
|
||||
case HCI_BREDR:
|
||||
case HCI_PRIMARY:
|
||||
return hci_conn_hash_lookup_handle(hdev, handle);
|
||||
case HCI_AMP:
|
||||
chan = hci_chan_lookup_handle(hdev, handle);
|
||||
|
|
|
@ -676,7 +676,7 @@ static int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd,
|
|||
if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (hdev->dev_type != HCI_BREDR)
|
||||
if (hdev->dev_type != HCI_PRIMARY)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
switch (cmd) {
|
||||
|
@ -1048,6 +1048,7 @@ static int hci_sock_recvmsg(struct socket *sock, struct msghdr *msg,
|
|||
struct sock *sk = sock->sk;
|
||||
struct sk_buff *skb;
|
||||
int copied, err;
|
||||
unsigned int skblen;
|
||||
|
||||
BT_DBG("sock %p, sk %p", sock, sk);
|
||||
|
||||
|
@ -1064,6 +1065,7 @@ static int hci_sock_recvmsg(struct socket *sock, struct msghdr *msg,
|
|||
if (!skb)
|
||||
return err;
|
||||
|
||||
skblen = skb->len;
|
||||
copied = skb->len;
|
||||
if (len < copied) {
|
||||
msg->msg_flags |= MSG_TRUNC;
|
||||
|
@ -1089,6 +1091,9 @@ static int hci_sock_recvmsg(struct socket *sock, struct msghdr *msg,
|
|||
|
||||
skb_free_datagram(sk, skb);
|
||||
|
||||
if (msg->msg_flags & MSG_TRUNC)
|
||||
copied = skblen;
|
||||
|
||||
return err ? : copied;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,50 +7,6 @@
|
|||
|
||||
static struct class *bt_class;
|
||||
|
||||
static inline char *link_typetostr(int type)
|
||||
{
|
||||
switch (type) {
|
||||
case ACL_LINK:
|
||||
return "ACL";
|
||||
case SCO_LINK:
|
||||
return "SCO";
|
||||
case ESCO_LINK:
|
||||
return "eSCO";
|
||||
case LE_LINK:
|
||||
return "LE";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t show_link_type(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct hci_conn *conn = to_hci_conn(dev);
|
||||
return sprintf(buf, "%s\n", link_typetostr(conn->type));
|
||||
}
|
||||
|
||||
static ssize_t show_link_address(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct hci_conn *conn = to_hci_conn(dev);
|
||||
return sprintf(buf, "%pMR\n", &conn->dst);
|
||||
}
|
||||
|
||||
#define LINK_ATTR(_name, _mode, _show, _store) \
|
||||
struct device_attribute link_attr_##_name = __ATTR(_name, _mode, _show, _store)
|
||||
|
||||
static LINK_ATTR(type, S_IRUGO, show_link_type, NULL);
|
||||
static LINK_ATTR(address, S_IRUGO, show_link_address, NULL);
|
||||
|
||||
static struct attribute *bt_link_attrs[] = {
|
||||
&link_attr_type.attr,
|
||||
&link_attr_address.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
ATTRIBUTE_GROUPS(bt_link);
|
||||
|
||||
static void bt_link_release(struct device *dev)
|
||||
{
|
||||
struct hci_conn *conn = to_hci_conn(dev);
|
||||
|
@ -59,7 +15,6 @@ static void bt_link_release(struct device *dev)
|
|||
|
||||
static struct device_type bt_link = {
|
||||
.name = "link",
|
||||
.groups = bt_link_groups,
|
||||
.release = bt_link_release,
|
||||
};
|
||||
|
||||
|
@ -124,59 +79,6 @@ void hci_conn_del_sysfs(struct hci_conn *conn)
|
|||
hci_dev_put(hdev);
|
||||
}
|
||||
|
||||
static inline char *host_typetostr(int type)
|
||||
{
|
||||
switch (type) {
|
||||
case HCI_BREDR:
|
||||
return "BR/EDR";
|
||||
case HCI_AMP:
|
||||
return "AMP";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t show_type(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct hci_dev *hdev = to_hci_dev(dev);
|
||||
return sprintf(buf, "%s\n", host_typetostr(hdev->dev_type));
|
||||
}
|
||||
|
||||
static ssize_t show_name(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct hci_dev *hdev = to_hci_dev(dev);
|
||||
char name[HCI_MAX_NAME_LENGTH + 1];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < HCI_MAX_NAME_LENGTH; i++)
|
||||
name[i] = hdev->dev_name[i];
|
||||
|
||||
name[HCI_MAX_NAME_LENGTH] = '\0';
|
||||
return sprintf(buf, "%s\n", name);
|
||||
}
|
||||
|
||||
static ssize_t show_address(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct hci_dev *hdev = to_hci_dev(dev);
|
||||
return sprintf(buf, "%pMR\n", &hdev->bdaddr);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(type, S_IRUGO, show_type, NULL);
|
||||
static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
|
||||
static DEVICE_ATTR(address, S_IRUGO, show_address, NULL);
|
||||
|
||||
static struct attribute *bt_host_attrs[] = {
|
||||
&dev_attr_type.attr,
|
||||
&dev_attr_name.attr,
|
||||
&dev_attr_address.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
ATTRIBUTE_GROUPS(bt_host);
|
||||
|
||||
static void bt_host_release(struct device *dev)
|
||||
{
|
||||
struct hci_dev *hdev = to_hci_dev(dev);
|
||||
|
@ -186,7 +88,6 @@ static void bt_host_release(struct device *dev)
|
|||
|
||||
static struct device_type bt_host = {
|
||||
.name = "host",
|
||||
.groups = bt_host_groups,
|
||||
.release = bt_host_release,
|
||||
};
|
||||
|
||||
|
|
|
@ -7468,7 +7468,7 @@ void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
|
|||
int len;
|
||||
|
||||
/* For AMP controller do not create l2cap conn */
|
||||
if (!conn && hcon->hdev->dev_type != HCI_BREDR)
|
||||
if (!conn && hcon->hdev->dev_type != HCI_PRIMARY)
|
||||
goto drop;
|
||||
|
||||
if (!conn)
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
#include "mgmt_util.h"
|
||||
|
||||
#define MGMT_VERSION 1
|
||||
#define MGMT_REVISION 12
|
||||
#define MGMT_REVISION 13
|
||||
|
||||
static const u16 mgmt_commands[] = {
|
||||
MGMT_OP_READ_INDEX_LIST,
|
||||
|
@ -359,7 +359,7 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
|
|||
|
||||
count = 0;
|
||||
list_for_each_entry(d, &hci_dev_list, list) {
|
||||
if (d->dev_type == HCI_BREDR &&
|
||||
if (d->dev_type == HCI_PRIMARY &&
|
||||
!hci_dev_test_flag(d, HCI_UNCONFIGURED))
|
||||
count++;
|
||||
}
|
||||
|
@ -384,7 +384,7 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
|
|||
if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
|
||||
continue;
|
||||
|
||||
if (d->dev_type == HCI_BREDR &&
|
||||
if (d->dev_type == HCI_PRIMARY &&
|
||||
!hci_dev_test_flag(d, HCI_UNCONFIGURED)) {
|
||||
rp->index[count++] = cpu_to_le16(d->id);
|
||||
BT_DBG("Added hci%u", d->id);
|
||||
|
@ -419,7 +419,7 @@ static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
|
|||
|
||||
count = 0;
|
||||
list_for_each_entry(d, &hci_dev_list, list) {
|
||||
if (d->dev_type == HCI_BREDR &&
|
||||
if (d->dev_type == HCI_PRIMARY &&
|
||||
hci_dev_test_flag(d, HCI_UNCONFIGURED))
|
||||
count++;
|
||||
}
|
||||
|
@ -444,7 +444,7 @@ static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
|
|||
if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
|
||||
continue;
|
||||
|
||||
if (d->dev_type == HCI_BREDR &&
|
||||
if (d->dev_type == HCI_PRIMARY &&
|
||||
hci_dev_test_flag(d, HCI_UNCONFIGURED)) {
|
||||
rp->index[count++] = cpu_to_le16(d->id);
|
||||
BT_DBG("Added hci%u", d->id);
|
||||
|
@ -479,7 +479,7 @@ static int read_ext_index_list(struct sock *sk, struct hci_dev *hdev,
|
|||
|
||||
count = 0;
|
||||
list_for_each_entry(d, &hci_dev_list, list) {
|
||||
if (d->dev_type == HCI_BREDR || d->dev_type == HCI_AMP)
|
||||
if (d->dev_type == HCI_PRIMARY || d->dev_type == HCI_AMP)
|
||||
count++;
|
||||
}
|
||||
|
||||
|
@ -503,7 +503,7 @@ static int read_ext_index_list(struct sock *sk, struct hci_dev *hdev,
|
|||
if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
|
||||
continue;
|
||||
|
||||
if (d->dev_type == HCI_BREDR) {
|
||||
if (d->dev_type == HCI_PRIMARY) {
|
||||
if (hci_dev_test_flag(d, HCI_UNCONFIGURED))
|
||||
rp->entry[count].type = 0x01;
|
||||
else
|
||||
|
@ -6366,7 +6366,7 @@ void mgmt_index_added(struct hci_dev *hdev)
|
|||
return;
|
||||
|
||||
switch (hdev->dev_type) {
|
||||
case HCI_BREDR:
|
||||
case HCI_PRIMARY:
|
||||
if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
|
||||
mgmt_index_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev,
|
||||
NULL, 0, HCI_MGMT_UNCONF_INDEX_EVENTS);
|
||||
|
@ -6399,7 +6399,7 @@ void mgmt_index_removed(struct hci_dev *hdev)
|
|||
return;
|
||||
|
||||
switch (hdev->dev_type) {
|
||||
case HCI_BREDR:
|
||||
case HCI_PRIMARY:
|
||||
mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
|
||||
|
||||
if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
|
||||
|
|
|
@ -22,9 +22,9 @@
|
|||
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <linux/crypto.h>
|
||||
#include <crypto/b128ops.h>
|
||||
#include <crypto/hash.h>
|
||||
#include <crypto/skcipher.h>
|
||||
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
#include <net/bluetooth/hci_core.h>
|
||||
|
@ -88,7 +88,7 @@ struct smp_dev {
|
|||
u8 min_key_size;
|
||||
u8 max_key_size;
|
||||
|
||||
struct crypto_skcipher *tfm_aes;
|
||||
struct crypto_cipher *tfm_aes;
|
||||
struct crypto_shash *tfm_cmac;
|
||||
};
|
||||
|
||||
|
@ -127,7 +127,7 @@ struct smp_chan {
|
|||
u8 dhkey[32];
|
||||
u8 mackey[16];
|
||||
|
||||
struct crypto_skcipher *tfm_aes;
|
||||
struct crypto_cipher *tfm_aes;
|
||||
struct crypto_shash *tfm_cmac;
|
||||
};
|
||||
|
||||
|
@ -361,10 +361,8 @@ static int smp_h6(struct crypto_shash *tfm_cmac, const u8 w[16],
|
|||
* s1 and ah.
|
||||
*/
|
||||
|
||||
static int smp_e(struct crypto_skcipher *tfm, const u8 *k, u8 *r)
|
||||
static int smp_e(struct crypto_cipher *tfm, const u8 *k, u8 *r)
|
||||
{
|
||||
SKCIPHER_REQUEST_ON_STACK(req, tfm);
|
||||
struct scatterlist sg;
|
||||
uint8_t tmp[16], data[16];
|
||||
int err;
|
||||
|
||||
|
@ -378,7 +376,7 @@ static int smp_e(struct crypto_skcipher *tfm, const u8 *k, u8 *r)
|
|||
/* The most significant octet of key corresponds to k[0] */
|
||||
swap_buf(k, tmp, 16);
|
||||
|
||||
err = crypto_skcipher_setkey(tfm, tmp, 16);
|
||||
err = crypto_cipher_setkey(tfm, tmp, 16);
|
||||
if (err) {
|
||||
BT_ERR("cipher setkey failed: %d", err);
|
||||
return err;
|
||||
|
@ -387,16 +385,7 @@ static int smp_e(struct crypto_skcipher *tfm, const u8 *k, u8 *r)
|
|||
/* Most significant octet of plaintextData corresponds to data[0] */
|
||||
swap_buf(r, data, 16);
|
||||
|
||||
sg_init_one(&sg, data, 16);
|
||||
|
||||
skcipher_request_set_tfm(req, tfm);
|
||||
skcipher_request_set_callback(req, 0, NULL, NULL);
|
||||
skcipher_request_set_crypt(req, &sg, &sg, 16, NULL);
|
||||
|
||||
err = crypto_skcipher_encrypt(req);
|
||||
skcipher_request_zero(req);
|
||||
if (err)
|
||||
BT_ERR("Encrypt data error %d", err);
|
||||
crypto_cipher_encrypt_one(tfm, data, data);
|
||||
|
||||
/* Most significant octet of encryptedData corresponds to data[0] */
|
||||
swap_buf(data, r, 16);
|
||||
|
@ -406,7 +395,7 @@ static int smp_e(struct crypto_skcipher *tfm, const u8 *k, u8 *r)
|
|||
return err;
|
||||
}
|
||||
|
||||
static int smp_c1(struct crypto_skcipher *tfm_aes, const u8 k[16],
|
||||
static int smp_c1(struct crypto_cipher *tfm_aes, const u8 k[16],
|
||||
const u8 r[16], const u8 preq[7], const u8 pres[7], u8 _iat,
|
||||
const bdaddr_t *ia, u8 _rat, const bdaddr_t *ra, u8 res[16])
|
||||
{
|
||||
|
@ -455,7 +444,7 @@ static int smp_c1(struct crypto_skcipher *tfm_aes, const u8 k[16],
|
|||
return err;
|
||||
}
|
||||
|
||||
static int smp_s1(struct crypto_skcipher *tfm_aes, const u8 k[16],
|
||||
static int smp_s1(struct crypto_cipher *tfm_aes, const u8 k[16],
|
||||
const u8 r1[16], const u8 r2[16], u8 _r[16])
|
||||
{
|
||||
int err;
|
||||
|
@ -471,7 +460,7 @@ static int smp_s1(struct crypto_skcipher *tfm_aes, const u8 k[16],
|
|||
return err;
|
||||
}
|
||||
|
||||
static int smp_ah(struct crypto_skcipher *tfm, const u8 irk[16],
|
||||
static int smp_ah(struct crypto_cipher *tfm, const u8 irk[16],
|
||||
const u8 r[3], u8 res[3])
|
||||
{
|
||||
u8 _res[16];
|
||||
|
@ -759,7 +748,7 @@ static void smp_chan_destroy(struct l2cap_conn *conn)
|
|||
kzfree(smp->slave_csrk);
|
||||
kzfree(smp->link_key);
|
||||
|
||||
crypto_free_skcipher(smp->tfm_aes);
|
||||
crypto_free_cipher(smp->tfm_aes);
|
||||
crypto_free_shash(smp->tfm_cmac);
|
||||
|
||||
/* Ensure that we don't leave any debug key around if debug key
|
||||
|
@ -1359,9 +1348,9 @@ static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
|
|||
if (!smp)
|
||||
return NULL;
|
||||
|
||||
smp->tfm_aes = crypto_alloc_skcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
|
||||
smp->tfm_aes = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
|
||||
if (IS_ERR(smp->tfm_aes)) {
|
||||
BT_ERR("Unable to create ECB crypto context");
|
||||
BT_ERR("Unable to create AES crypto context");
|
||||
kzfree(smp);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1369,7 +1358,7 @@ static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
|
|||
smp->tfm_cmac = crypto_alloc_shash("cmac(aes)", 0, 0);
|
||||
if (IS_ERR(smp->tfm_cmac)) {
|
||||
BT_ERR("Unable to create CMAC crypto context");
|
||||
crypto_free_skcipher(smp->tfm_aes);
|
||||
crypto_free_cipher(smp->tfm_aes);
|
||||
kzfree(smp);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -3120,7 +3109,7 @@ static struct l2cap_chan *smp_add_cid(struct hci_dev *hdev, u16 cid)
|
|||
{
|
||||
struct l2cap_chan *chan;
|
||||
struct smp_dev *smp;
|
||||
struct crypto_skcipher *tfm_aes;
|
||||
struct crypto_cipher *tfm_aes;
|
||||
struct crypto_shash *tfm_cmac;
|
||||
|
||||
if (cid == L2CAP_CID_SMP_BREDR) {
|
||||
|
@ -3132,9 +3121,9 @@ static struct l2cap_chan *smp_add_cid(struct hci_dev *hdev, u16 cid)
|
|||
if (!smp)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
tfm_aes = crypto_alloc_skcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
|
||||
tfm_aes = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
|
||||
if (IS_ERR(tfm_aes)) {
|
||||
BT_ERR("Unable to create ECB crypto context");
|
||||
BT_ERR("Unable to create AES crypto context");
|
||||
kzfree(smp);
|
||||
return ERR_CAST(tfm_aes);
|
||||
}
|
||||
|
@ -3142,7 +3131,7 @@ static struct l2cap_chan *smp_add_cid(struct hci_dev *hdev, u16 cid)
|
|||
tfm_cmac = crypto_alloc_shash("cmac(aes)", 0, 0);
|
||||
if (IS_ERR(tfm_cmac)) {
|
||||
BT_ERR("Unable to create CMAC crypto context");
|
||||
crypto_free_skcipher(tfm_aes);
|
||||
crypto_free_cipher(tfm_aes);
|
||||
kzfree(smp);
|
||||
return ERR_CAST(tfm_cmac);
|
||||
}
|
||||
|
@ -3156,7 +3145,7 @@ create_chan:
|
|||
chan = l2cap_chan_create();
|
||||
if (!chan) {
|
||||
if (smp) {
|
||||
crypto_free_skcipher(smp->tfm_aes);
|
||||
crypto_free_cipher(smp->tfm_aes);
|
||||
crypto_free_shash(smp->tfm_cmac);
|
||||
kzfree(smp);
|
||||
}
|
||||
|
@ -3203,7 +3192,7 @@ static void smp_del_chan(struct l2cap_chan *chan)
|
|||
smp = chan->data;
|
||||
if (smp) {
|
||||
chan->data = NULL;
|
||||
crypto_free_skcipher(smp->tfm_aes);
|
||||
crypto_free_cipher(smp->tfm_aes);
|
||||
crypto_free_shash(smp->tfm_cmac);
|
||||
kzfree(smp);
|
||||
}
|
||||
|
@ -3440,7 +3429,7 @@ void smp_unregister(struct hci_dev *hdev)
|
|||
|
||||
#if IS_ENABLED(CONFIG_BT_SELFTEST_SMP)
|
||||
|
||||
static int __init test_ah(struct crypto_skcipher *tfm_aes)
|
||||
static int __init test_ah(struct crypto_cipher *tfm_aes)
|
||||
{
|
||||
const u8 irk[16] = {
|
||||
0x9b, 0x7d, 0x39, 0x0a, 0xa6, 0x10, 0x10, 0x34,
|
||||
|
@ -3460,7 +3449,7 @@ static int __init test_ah(struct crypto_skcipher *tfm_aes)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int __init test_c1(struct crypto_skcipher *tfm_aes)
|
||||
static int __init test_c1(struct crypto_cipher *tfm_aes)
|
||||
{
|
||||
const u8 k[16] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
|
@ -3490,7 +3479,7 @@ static int __init test_c1(struct crypto_skcipher *tfm_aes)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int __init test_s1(struct crypto_skcipher *tfm_aes)
|
||||
static int __init test_s1(struct crypto_cipher *tfm_aes)
|
||||
{
|
||||
const u8 k[16] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
|
@ -3686,7 +3675,7 @@ static const struct file_operations test_smp_fops = {
|
|||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static int __init run_selftests(struct crypto_skcipher *tfm_aes,
|
||||
static int __init run_selftests(struct crypto_cipher *tfm_aes,
|
||||
struct crypto_shash *tfm_cmac)
|
||||
{
|
||||
ktime_t calltime, delta, rettime;
|
||||
|
@ -3764,27 +3753,27 @@ done:
|
|||
|
||||
int __init bt_selftest_smp(void)
|
||||
{
|
||||
struct crypto_skcipher *tfm_aes;
|
||||
struct crypto_cipher *tfm_aes;
|
||||
struct crypto_shash *tfm_cmac;
|
||||
int err;
|
||||
|
||||
tfm_aes = crypto_alloc_skcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
|
||||
tfm_aes = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
|
||||
if (IS_ERR(tfm_aes)) {
|
||||
BT_ERR("Unable to create ECB crypto context");
|
||||
BT_ERR("Unable to create AES crypto context");
|
||||
return PTR_ERR(tfm_aes);
|
||||
}
|
||||
|
||||
tfm_cmac = crypto_alloc_shash("cmac(aes)", 0, CRYPTO_ALG_ASYNC);
|
||||
if (IS_ERR(tfm_cmac)) {
|
||||
BT_ERR("Unable to create CMAC crypto context");
|
||||
crypto_free_skcipher(tfm_aes);
|
||||
crypto_free_cipher(tfm_aes);
|
||||
return PTR_ERR(tfm_cmac);
|
||||
}
|
||||
|
||||
err = run_selftests(tfm_aes, tfm_cmac);
|
||||
|
||||
crypto_free_shash(tfm_cmac);
|
||||
crypto_free_skcipher(tfm_aes);
|
||||
crypto_free_cipher(tfm_aes);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -130,8 +130,7 @@ static int lowpan_newlink(struct net *src_net, struct net_device *ldev,
|
|||
|
||||
pr_debug("adding new link\n");
|
||||
|
||||
if (!tb[IFLA_LINK] ||
|
||||
!net_eq(dev_net(ldev), &init_net))
|
||||
if (!tb[IFLA_LINK])
|
||||
return -EINVAL;
|
||||
/* find and hold wpan device */
|
||||
wdev = dev_get_by_index(dev_net(ldev), nla_get_u32(tb[IFLA_LINK]));
|
||||
|
|
|
@ -262,7 +262,7 @@ static inline bool lowpan_rx_h_check(struct sk_buff *skb)
|
|||
|
||||
/* check on ieee802154 conform 6LoWPAN header */
|
||||
if (!ieee802154_is_data(fc) ||
|
||||
!ieee802154_is_intra_pan(fc))
|
||||
!ieee802154_skb_is_intra_pan_addressing(fc, skb))
|
||||
return false;
|
||||
|
||||
/* check if we can dereference the dispatch */
|
||||
|
|
|
@ -140,6 +140,8 @@ wpan_phy_new(const struct cfg802154_ops *ops, size_t priv_size)
|
|||
rdev->wpan_phy.dev.class = &wpan_phy_class;
|
||||
rdev->wpan_phy.dev.platform_data = rdev;
|
||||
|
||||
wpan_phy_net_set(&rdev->wpan_phy, &init_net);
|
||||
|
||||
init_waitqueue_head(&rdev->dev_wait);
|
||||
|
||||
return &rdev->wpan_phy;
|
||||
|
@ -207,6 +209,49 @@ void wpan_phy_free(struct wpan_phy *phy)
|
|||
}
|
||||
EXPORT_SYMBOL(wpan_phy_free);
|
||||
|
||||
int cfg802154_switch_netns(struct cfg802154_registered_device *rdev,
|
||||
struct net *net)
|
||||
{
|
||||
struct wpan_dev *wpan_dev;
|
||||
int err = 0;
|
||||
|
||||
list_for_each_entry(wpan_dev, &rdev->wpan_dev_list, list) {
|
||||
if (!wpan_dev->netdev)
|
||||
continue;
|
||||
wpan_dev->netdev->features &= ~NETIF_F_NETNS_LOCAL;
|
||||
err = dev_change_net_namespace(wpan_dev->netdev, net, "wpan%d");
|
||||
if (err)
|
||||
break;
|
||||
wpan_dev->netdev->features |= NETIF_F_NETNS_LOCAL;
|
||||
}
|
||||
|
||||
if (err) {
|
||||
/* failed -- clean up to old netns */
|
||||
net = wpan_phy_net(&rdev->wpan_phy);
|
||||
|
||||
list_for_each_entry_continue_reverse(wpan_dev,
|
||||
&rdev->wpan_dev_list,
|
||||
list) {
|
||||
if (!wpan_dev->netdev)
|
||||
continue;
|
||||
wpan_dev->netdev->features &= ~NETIF_F_NETNS_LOCAL;
|
||||
err = dev_change_net_namespace(wpan_dev->netdev, net,
|
||||
"wpan%d");
|
||||
WARN_ON(err);
|
||||
wpan_dev->netdev->features |= NETIF_F_NETNS_LOCAL;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
wpan_phy_net_set(&rdev->wpan_phy, net);
|
||||
|
||||
err = device_rename(&rdev->wpan_phy.dev, dev_name(&rdev->wpan_phy.dev));
|
||||
WARN_ON(err);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cfg802154_dev_free(struct cfg802154_registered_device *rdev)
|
||||
{
|
||||
kfree(rdev);
|
||||
|
@ -286,14 +331,34 @@ static struct notifier_block cfg802154_netdev_notifier = {
|
|||
.notifier_call = cfg802154_netdev_notifier_call,
|
||||
};
|
||||
|
||||
static void __net_exit cfg802154_pernet_exit(struct net *net)
|
||||
{
|
||||
struct cfg802154_registered_device *rdev;
|
||||
|
||||
rtnl_lock();
|
||||
list_for_each_entry(rdev, &cfg802154_rdev_list, list) {
|
||||
if (net_eq(wpan_phy_net(&rdev->wpan_phy), net))
|
||||
WARN_ON(cfg802154_switch_netns(rdev, &init_net));
|
||||
}
|
||||
rtnl_unlock();
|
||||
}
|
||||
|
||||
static struct pernet_operations cfg802154_pernet_ops = {
|
||||
.exit = cfg802154_pernet_exit,
|
||||
};
|
||||
|
||||
static int __init wpan_phy_class_init(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = wpan_phy_sysfs_init();
|
||||
rc = register_pernet_device(&cfg802154_pernet_ops);
|
||||
if (rc)
|
||||
goto err;
|
||||
|
||||
rc = wpan_phy_sysfs_init();
|
||||
if (rc)
|
||||
goto err_sysfs;
|
||||
|
||||
rc = register_netdevice_notifier(&cfg802154_netdev_notifier);
|
||||
if (rc)
|
||||
goto err_nl;
|
||||
|
@ -315,6 +380,8 @@ err_notifier:
|
|||
unregister_netdevice_notifier(&cfg802154_netdev_notifier);
|
||||
err_nl:
|
||||
wpan_phy_sysfs_exit();
|
||||
err_sysfs:
|
||||
unregister_pernet_device(&cfg802154_pernet_ops);
|
||||
err:
|
||||
return rc;
|
||||
}
|
||||
|
@ -326,6 +393,7 @@ static void __exit wpan_phy_class_exit(void)
|
|||
ieee802154_nl_exit();
|
||||
unregister_netdevice_notifier(&cfg802154_netdev_notifier);
|
||||
wpan_phy_sysfs_exit();
|
||||
unregister_pernet_device(&cfg802154_pernet_ops);
|
||||
}
|
||||
module_exit(wpan_phy_class_exit);
|
||||
|
||||
|
|
|
@ -38,6 +38,8 @@ wpan_phy_to_rdev(struct wpan_phy *wpan_phy)
|
|||
extern struct list_head cfg802154_rdev_list;
|
||||
extern int cfg802154_rdev_list_generation;
|
||||
|
||||
int cfg802154_switch_netns(struct cfg802154_registered_device *rdev,
|
||||
struct net *net);
|
||||
/* free object */
|
||||
void cfg802154_dev_free(struct cfg802154_registered_device *rdev);
|
||||
struct cfg802154_registered_device *
|
||||
|
|
|
@ -80,7 +80,8 @@ __cfg802154_wpan_dev_from_attrs(struct net *netns, struct nlattr **attrs)
|
|||
list_for_each_entry(rdev, &cfg802154_rdev_list, list) {
|
||||
struct wpan_dev *wpan_dev;
|
||||
|
||||
/* TODO netns compare */
|
||||
if (wpan_phy_net(&rdev->wpan_phy) != netns)
|
||||
continue;
|
||||
|
||||
if (have_wpan_dev_id && rdev->wpan_phy_idx != wpan_phy_idx)
|
||||
continue;
|
||||
|
@ -175,7 +176,8 @@ __cfg802154_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
|
|||
if (!rdev)
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
/* TODO netns compare */
|
||||
if (netns != wpan_phy_net(&rdev->wpan_phy))
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
return rdev;
|
||||
}
|
||||
|
@ -233,6 +235,8 @@ static const struct nla_policy nl802154_policy[NL802154_ATTR_MAX+1] = {
|
|||
|
||||
[NL802154_ATTR_ACKREQ_DEFAULT] = { .type = NLA_U8 },
|
||||
|
||||
[NL802154_ATTR_PID] = { .type = NLA_U32 },
|
||||
[NL802154_ATTR_NETNS_FD] = { .type = NLA_U32 },
|
||||
#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
|
||||
[NL802154_ATTR_SEC_ENABLED] = { .type = NLA_U8, },
|
||||
[NL802154_ATTR_SEC_OUT_LEVEL] = { .type = NLA_U32, },
|
||||
|
@ -590,7 +594,6 @@ static int nl802154_dump_wpan_phy_parse(struct sk_buff *skb,
|
|||
struct cfg802154_registered_device *rdev;
|
||||
int ifidx = nla_get_u32(tb[NL802154_ATTR_IFINDEX]);
|
||||
|
||||
/* TODO netns */
|
||||
netdev = __dev_get_by_index(&init_net, ifidx);
|
||||
if (!netdev)
|
||||
return -ENODEV;
|
||||
|
@ -629,7 +632,8 @@ nl802154_dump_wpan_phy(struct sk_buff *skb, struct netlink_callback *cb)
|
|||
}
|
||||
|
||||
list_for_each_entry(rdev, &cfg802154_rdev_list, list) {
|
||||
/* TODO net ns compare */
|
||||
if (!net_eq(wpan_phy_net(&rdev->wpan_phy), sock_net(skb->sk)))
|
||||
continue;
|
||||
if (++idx <= state->start)
|
||||
continue;
|
||||
if (state->filter_wpan_phy != -1 &&
|
||||
|
@ -871,7 +875,8 @@ nl802154_dump_interface(struct sk_buff *skb, struct netlink_callback *cb)
|
|||
|
||||
rtnl_lock();
|
||||
list_for_each_entry(rdev, &cfg802154_rdev_list, list) {
|
||||
/* TODO netns compare */
|
||||
if (!net_eq(wpan_phy_net(&rdev->wpan_phy), sock_net(skb->sk)))
|
||||
continue;
|
||||
if (wp_idx < wp_start) {
|
||||
wp_idx++;
|
||||
continue;
|
||||
|
@ -1271,6 +1276,37 @@ nl802154_set_ackreq_default(struct sk_buff *skb, struct genl_info *info)
|
|||
return rdev_set_ackreq_default(rdev, wpan_dev, ackreq);
|
||||
}
|
||||
|
||||
static int nl802154_wpan_phy_netns(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
struct cfg802154_registered_device *rdev = info->user_ptr[0];
|
||||
struct net *net;
|
||||
int err;
|
||||
|
||||
if (info->attrs[NL802154_ATTR_PID]) {
|
||||
u32 pid = nla_get_u32(info->attrs[NL802154_ATTR_PID]);
|
||||
|
||||
net = get_net_ns_by_pid(pid);
|
||||
} else if (info->attrs[NL802154_ATTR_NETNS_FD]) {
|
||||
u32 fd = nla_get_u32(info->attrs[NL802154_ATTR_NETNS_FD]);
|
||||
|
||||
net = get_net_ns_by_fd(fd);
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (IS_ERR(net))
|
||||
return PTR_ERR(net);
|
||||
|
||||
err = 0;
|
||||
|
||||
/* check if anything to do */
|
||||
if (!net_eq(wpan_phy_net(&rdev->wpan_phy), net))
|
||||
err = cfg802154_switch_netns(rdev, net);
|
||||
|
||||
put_net(net);
|
||||
return err;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
|
||||
static const struct nla_policy nl802154_dev_addr_policy[NL802154_DEV_ADDR_ATTR_MAX + 1] = {
|
||||
[NL802154_DEV_ADDR_ATTR_PAN_ID] = { .type = NLA_U16 },
|
||||
|
@ -2261,6 +2297,14 @@ static const struct genl_ops nl802154_ops[] = {
|
|||
.internal_flags = NL802154_FLAG_NEED_WPAN_PHY |
|
||||
NL802154_FLAG_NEED_RTNL,
|
||||
},
|
||||
{
|
||||
.cmd = NL802154_CMD_SET_WPAN_PHY_NETNS,
|
||||
.doit = nl802154_wpan_phy_netns,
|
||||
.policy = nl802154_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.internal_flags = NL802154_FLAG_NEED_WPAN_PHY |
|
||||
NL802154_FLAG_NEED_RTNL,
|
||||
},
|
||||
{
|
||||
.cmd = NL802154_CMD_SET_PAN_ID,
|
||||
.doit = nl802154_set_pan_id,
|
||||
|
|
Loading…
Reference in New Issue