summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@intel.com>2014-02-18 21:41:33 +0200
committerMarcel Holtmann <marcel@holtmann.org>2014-02-18 11:48:55 -0800
commit387a33e304caeeabf0c2439607fa6e726666bdf0 (patch)
treeb90a6d87494d36c77489e6c8fe318ab2ce85a67f
parent68d6f6ded5bdaa89f9da0144359a7c5565991f8d (diff)
Bluetooth: Fix updating Identity Address in L2CAP channels
When we receive a remote identity address during SMP key distribution we should ensure that any associated L2CAP channel instances get their address information correspondingly updated (so that e.g. doing getpeername on associated sockets returns the correct address). This patch adds a new L2CAP core function l2cap_conn_update_id_addr() which is used to iterate through all L2CAP channels associated with a connection and update their address information. Signed-off-by: Johan Hedberg <johan.hedberg@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
-rw-r--r--include/net/bluetooth/l2cap.h1
-rw-r--r--net/bluetooth/l2cap_core.c17
-rw-r--r--net/bluetooth/smp.c2
3 files changed, 20 insertions, 0 deletions
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 13bec91785f4..4abdcb220e3a 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -881,6 +881,7 @@ int l2cap_ertm_init(struct l2cap_chan *chan);
void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan);
void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan);
void l2cap_chan_del(struct l2cap_chan *chan, int err);
+void l2cap_conn_update_id_addr(struct hci_conn *hcon);
void l2cap_send_conn_req(struct l2cap_chan *chan);
void l2cap_move_start(struct l2cap_chan *chan);
void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan,
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 6e6b3a9c8e6d..c3bda6445f3d 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -609,6 +609,23 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)
return;
}
+void l2cap_conn_update_id_addr(struct hci_conn *hcon)
+{
+ struct l2cap_conn *conn = hcon->l2cap_data;
+ struct l2cap_chan *chan;
+
+ mutex_lock(&conn->chan_lock);
+
+ list_for_each_entry(chan, &conn->chan_l, list) {
+ l2cap_chan_lock(chan);
+ bacpy(&chan->dst, &hcon->dst);
+ chan->dst_type = bdaddr_type(hcon, hcon->dst_type);
+ l2cap_chan_unlock(chan);
+ }
+
+ mutex_unlock(&conn->chan_lock);
+}
+
static void l2cap_chan_le_connect_reject(struct l2cap_chan *chan)
{
struct l2cap_conn *conn = chan->conn;
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index af29afed0cca..b6a2a8942b2d 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -991,6 +991,8 @@ static int smp_cmd_ident_addr_info(struct l2cap_conn *conn,
bacpy(&hcon->dst, &smp->id_addr);
hcon->dst_type = smp->id_addr_type;
+ l2cap_conn_update_id_addr(hcon);
+
smp_distribute_keys(conn, 1);
return 0;