Commit 0fdcaa59 authored by John W. Linville's avatar John W. Linville
parents 47e4df94 f161dd41
...@@ -464,6 +464,8 @@ struct hci_conn_params { ...@@ -464,6 +464,8 @@ struct hci_conn_params {
HCI_AUTO_CONN_ALWAYS, HCI_AUTO_CONN_ALWAYS,
HCI_AUTO_CONN_LINK_LOSS, HCI_AUTO_CONN_LINK_LOSS,
} auto_connect; } auto_connect;
struct hci_conn *conn;
}; };
extern struct list_head hci_dev_list; extern struct list_head hci_dev_list;
......
...@@ -16,7 +16,6 @@ struct netns_sysctl_lowpan { ...@@ -16,7 +16,6 @@ struct netns_sysctl_lowpan {
struct netns_ieee802154_lowpan { struct netns_ieee802154_lowpan {
struct netns_sysctl_lowpan sysctl; struct netns_sysctl_lowpan sysctl;
struct netns_frags frags; struct netns_frags frags;
int max_dsize;
}; };
#endif #endif
...@@ -589,6 +589,14 @@ EXPORT_SYMBOL(hci_get_route); ...@@ -589,6 +589,14 @@ EXPORT_SYMBOL(hci_get_route);
void hci_le_conn_failed(struct hci_conn *conn, u8 status) void hci_le_conn_failed(struct hci_conn *conn, u8 status)
{ {
struct hci_dev *hdev = conn->hdev; struct hci_dev *hdev = conn->hdev;
struct hci_conn_params *params;
params = hci_pend_le_action_lookup(&hdev->pend_le_conns, &conn->dst,
conn->dst_type);
if (params && params->conn) {
hci_conn_drop(params->conn);
params->conn = NULL;
}
conn->state = BT_CLOSED; conn->state = BT_CLOSED;
......
...@@ -2536,8 +2536,13 @@ static void hci_pend_le_actions_clear(struct hci_dev *hdev) ...@@ -2536,8 +2536,13 @@ static void hci_pend_le_actions_clear(struct hci_dev *hdev)
{ {
struct hci_conn_params *p; struct hci_conn_params *p;
list_for_each_entry(p, &hdev->le_conn_params, list) list_for_each_entry(p, &hdev->le_conn_params, list) {
if (p->conn) {
hci_conn_drop(p->conn);
p->conn = NULL;
}
list_del_init(&p->action); list_del_init(&p->action);
}
BT_DBG("All LE pending actions cleared"); BT_DBG("All LE pending actions cleared");
} }
...@@ -2578,8 +2583,8 @@ static int hci_dev_do_close(struct hci_dev *hdev) ...@@ -2578,8 +2583,8 @@ static int hci_dev_do_close(struct hci_dev *hdev)
hci_dev_lock(hdev); hci_dev_lock(hdev);
hci_inquiry_cache_flush(hdev); hci_inquiry_cache_flush(hdev);
hci_conn_hash_flush(hdev);
hci_pend_le_actions_clear(hdev); hci_pend_le_actions_clear(hdev);
hci_conn_hash_flush(hdev);
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
hci_notify(hdev, HCI_DEV_DOWN); hci_notify(hdev, HCI_DEV_DOWN);
...@@ -3727,6 +3732,9 @@ void hci_conn_params_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type) ...@@ -3727,6 +3732,9 @@ void hci_conn_params_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type)
if (!params) if (!params)
return; return;
if (params->conn)
hci_conn_drop(params->conn);
list_del(&params->action); list_del(&params->action);
list_del(&params->list); list_del(&params->list);
kfree(params); kfree(params);
...@@ -3757,6 +3765,8 @@ void hci_conn_params_clear_all(struct hci_dev *hdev) ...@@ -3757,6 +3765,8 @@ void hci_conn_params_clear_all(struct hci_dev *hdev)
struct hci_conn_params *params, *tmp; struct hci_conn_params *params, *tmp;
list_for_each_entry_safe(params, tmp, &hdev->le_conn_params, list) { list_for_each_entry_safe(params, tmp, &hdev->le_conn_params, list) {
if (params->conn)
hci_conn_drop(params->conn);
list_del(&params->action); list_del(&params->action);
list_del(&params->list); list_del(&params->list);
kfree(params); kfree(params);
......
...@@ -4221,8 +4221,13 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -4221,8 +4221,13 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
hci_proto_connect_cfm(conn, ev->status); hci_proto_connect_cfm(conn, ev->status);
params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type); params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type);
if (params) if (params) {
list_del_init(&params->action); list_del_init(&params->action);
if (params->conn) {
hci_conn_drop(params->conn);
params->conn = NULL;
}
}
unlock: unlock:
hci_update_background_scan(hdev); hci_update_background_scan(hdev);
...@@ -4304,8 +4309,16 @@ static void check_pending_le_conn(struct hci_dev *hdev, bdaddr_t *addr, ...@@ -4304,8 +4309,16 @@ static void check_pending_le_conn(struct hci_dev *hdev, bdaddr_t *addr,
conn = hci_connect_le(hdev, addr, addr_type, BT_SECURITY_LOW, conn = hci_connect_le(hdev, addr, addr_type, BT_SECURITY_LOW,
HCI_LE_AUTOCONN_TIMEOUT, HCI_ROLE_MASTER); HCI_LE_AUTOCONN_TIMEOUT, HCI_ROLE_MASTER);
if (!IS_ERR(conn)) if (!IS_ERR(conn)) {
/* Store the pointer since we don't really have any
* other owner of the object besides the params that
* triggered it. This way we can abort the connection if
* the parameters get removed and keep the reference
* count consistent once the connection is established.
*/
params->conn = conn;
return; return;
}
switch (PTR_ERR(conn)) { switch (PTR_ERR(conn)) {
case -EBUSY: case -EBUSY:
......
...@@ -246,7 +246,7 @@ lowpan_alloc_frag(struct sk_buff *skb, int size, ...@@ -246,7 +246,7 @@ lowpan_alloc_frag(struct sk_buff *skb, int size,
return ERR_PTR(-rc); return ERR_PTR(-rc);
} }
} else { } else {
frag = ERR_PTR(ENOMEM); frag = ERR_PTR(-ENOMEM);
} }
return frag; return frag;
...@@ -437,7 +437,7 @@ static void lowpan_setup(struct net_device *dev) ...@@ -437,7 +437,7 @@ static void lowpan_setup(struct net_device *dev)
/* Frame Control + Sequence Number + Address fields + Security Header */ /* Frame Control + Sequence Number + Address fields + Security Header */
dev->hard_header_len = 2 + 1 + 20 + 14; dev->hard_header_len = 2 + 1 + 20 + 14;
dev->needed_tailroom = 2; /* FCS */ dev->needed_tailroom = 2; /* FCS */
dev->mtu = 1281; dev->mtu = IPV6_MIN_MTU;
dev->tx_queue_len = 0; dev->tx_queue_len = 0;
dev->flags = IFF_BROADCAST | IFF_MULTICAST; dev->flags = IFF_BROADCAST | IFF_MULTICAST;
dev->watchdog_timeo = 0; dev->watchdog_timeo = 0;
......
...@@ -355,8 +355,6 @@ int lowpan_frag_rcv(struct sk_buff *skb, const u8 frag_type) ...@@ -355,8 +355,6 @@ int lowpan_frag_rcv(struct sk_buff *skb, const u8 frag_type)
struct net *net = dev_net(skb->dev); struct net *net = dev_net(skb->dev);
struct lowpan_frag_info *frag_info = lowpan_cb(skb); struct lowpan_frag_info *frag_info = lowpan_cb(skb);
struct ieee802154_addr source, dest; struct ieee802154_addr source, dest;
struct netns_ieee802154_lowpan *ieee802154_lowpan =
net_ieee802154_lowpan(net);
int err; int err;
source = mac_cb(skb)->source; source = mac_cb(skb)->source;
...@@ -366,8 +364,10 @@ int lowpan_frag_rcv(struct sk_buff *skb, const u8 frag_type) ...@@ -366,8 +364,10 @@ int lowpan_frag_rcv(struct sk_buff *skb, const u8 frag_type)
if (err < 0) if (err < 0)
goto err; goto err;
if (frag_info->d_size > ieee802154_lowpan->max_dsize) if (frag_info->d_size > IPV6_MIN_MTU) {
net_warn_ratelimited("lowpan_frag_rcv: datagram size exceeds MTU\n");
goto err; goto err;
}
fq = fq_find(net, frag_info, &source, &dest); fq = fq_find(net, frag_info, &source, &dest);
if (fq != NULL) { if (fq != NULL) {
...@@ -415,13 +415,6 @@ static struct ctl_table lowpan_frags_ns_ctl_table[] = { ...@@ -415,13 +415,6 @@ static struct ctl_table lowpan_frags_ns_ctl_table[] = {
.mode = 0644, .mode = 0644,
.proc_handler = proc_dointvec_jiffies, .proc_handler = proc_dointvec_jiffies,
}, },
{
.procname = "6lowpanfrag_max_datagram_size",
.data = &init_net.ieee802154_lowpan.max_dsize,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec
},
{ } { }
}; };
...@@ -458,7 +451,6 @@ static int __net_init lowpan_frags_ns_sysctl_register(struct net *net) ...@@ -458,7 +451,6 @@ static int __net_init lowpan_frags_ns_sysctl_register(struct net *net)
table[1].data = &ieee802154_lowpan->frags.low_thresh; table[1].data = &ieee802154_lowpan->frags.low_thresh;
table[1].extra2 = &ieee802154_lowpan->frags.high_thresh; table[1].extra2 = &ieee802154_lowpan->frags.high_thresh;
table[2].data = &ieee802154_lowpan->frags.timeout; table[2].data = &ieee802154_lowpan->frags.timeout;
table[3].data = &ieee802154_lowpan->max_dsize;
/* Don't export sysctls to unprivileged users */ /* Don't export sysctls to unprivileged users */
if (net->user_ns != &init_user_ns) if (net->user_ns != &init_user_ns)
...@@ -533,7 +525,6 @@ static int __net_init lowpan_frags_init_net(struct net *net) ...@@ -533,7 +525,6 @@ static int __net_init lowpan_frags_init_net(struct net *net)
ieee802154_lowpan->frags.high_thresh = IPV6_FRAG_HIGH_THRESH; ieee802154_lowpan->frags.high_thresh = IPV6_FRAG_HIGH_THRESH;
ieee802154_lowpan->frags.low_thresh = IPV6_FRAG_LOW_THRESH; ieee802154_lowpan->frags.low_thresh = IPV6_FRAG_LOW_THRESH;
ieee802154_lowpan->frags.timeout = IPV6_FRAG_TIMEOUT; ieee802154_lowpan->frags.timeout = IPV6_FRAG_TIMEOUT;
ieee802154_lowpan->max_dsize = 0xFFFF;
inet_frags_init_net(&ieee802154_lowpan->frags); inet_frags_init_net(&ieee802154_lowpan->frags);
......
...@@ -462,7 +462,10 @@ mac802154_subif_frame(struct mac802154_sub_if_data *sdata, struct sk_buff *skb, ...@@ -462,7 +462,10 @@ mac802154_subif_frame(struct mac802154_sub_if_data *sdata, struct sk_buff *skb,
skb->pkt_type = PACKET_OTHERHOST; skb->pkt_type = PACKET_OTHERHOST;
break; break;
default: default:
break; spin_unlock_bh(&sdata->mib_lock);
pr_debug("invalid dest mode\n");
kfree_skb(skb);
return NET_RX_DROP;
} }
spin_unlock_bh(&sdata->mib_lock); spin_unlock_bh(&sdata->mib_lock);
...@@ -573,6 +576,7 @@ void mac802154_wpans_rx(struct mac802154_priv *priv, struct sk_buff *skb) ...@@ -573,6 +576,7 @@ void mac802154_wpans_rx(struct mac802154_priv *priv, struct sk_buff *skb)
ret = mac802154_parse_frame_start(skb, &hdr); ret = mac802154_parse_frame_start(skb, &hdr);
if (ret) { if (ret) {
pr_debug("got invalid frame\n"); pr_debug("got invalid frame\n");
kfree_skb(skb);
return; return;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment