Commit 2edf870d authored by Marcel Holtmann's avatar Marcel Holtmann Committed by Johan Hedberg

Bluetooth: Provide msg_name callback for L2CAP connectionless channels

The L2CAP connectionless channels use SOCK_DGRAM and recvmsg() and need
to receive the remote BD_ADDR and PSM information via msg_name from
the recvmsg() system call.

So in case the L2CAP socket is for connectionless channels, provide
a msg_name callback that can update the data. Also store the remote
BD_ADDR and PSM in the skb so it can be extracted later on.
Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
Signed-off-by: default avatarJohan Hedberg <johan.hedberg@intel.com>
parent d9763698
...@@ -284,6 +284,8 @@ struct bt_skb_cb { ...@@ -284,6 +284,8 @@ struct bt_skb_cb {
__u8 force_active; __u8 force_active;
struct l2cap_ctrl control; struct l2cap_ctrl control;
struct hci_req_ctrl req; struct hci_req_ctrl req;
bdaddr_t bdaddr;
__le16 psm;
}; };
#define bt_cb(skb) ((struct bt_skb_cb *)((skb)->cb)) #define bt_cb(skb) ((struct bt_skb_cb *)((skb)->cb))
......
...@@ -6459,6 +6459,10 @@ static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, ...@@ -6459,6 +6459,10 @@ static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm,
if (chan->imtu < skb->len) if (chan->imtu < skb->len)
goto drop; goto drop;
/* Store remote BD_ADDR and PSM for msg_name */
bacpy(&bt_cb(skb)->bdaddr, &conn->hcon->dst);
bt_cb(skb)->psm = psm;
if (!chan->ops->recv(chan, skb)) if (!chan->ops->recv(chan, skb))
return; return;
......
...@@ -1137,6 +1137,19 @@ static void l2cap_sock_destruct(struct sock *sk) ...@@ -1137,6 +1137,19 @@ static void l2cap_sock_destruct(struct sock *sk)
skb_queue_purge(&sk->sk_write_queue); skb_queue_purge(&sk->sk_write_queue);
} }
static void l2cap_skb_msg_name(struct sk_buff *skb, void *msg_name,
int *msg_namelen)
{
struct sockaddr_l2 *la = (struct sockaddr_l2 *) msg_name;
memset(la, 0, sizeof(struct sockaddr_l2));
la->l2_family = AF_BLUETOOTH;
la->l2_psm = bt_cb(skb)->psm;
bacpy(&la->l2_bdaddr, &bt_cb(skb)->bdaddr);
*msg_namelen = sizeof(struct sockaddr_l2);
}
static void l2cap_sock_init(struct sock *sk, struct sock *parent) static void l2cap_sock_init(struct sock *sk, struct sock *parent)
{ {
struct l2cap_chan *chan = l2cap_pi(sk)->chan; struct l2cap_chan *chan = l2cap_pi(sk)->chan;
...@@ -1163,13 +1176,13 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent) ...@@ -1163,13 +1176,13 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent)
security_sk_clone(parent, sk); security_sk_clone(parent, sk);
} else { } else {
switch (sk->sk_type) { switch (sk->sk_type) {
case SOCK_RAW: case SOCK_RAW:
chan->chan_type = L2CAP_CHAN_RAW; chan->chan_type = L2CAP_CHAN_RAW;
break; break;
case SOCK_DGRAM: case SOCK_DGRAM:
chan->chan_type = L2CAP_CHAN_CONN_LESS; chan->chan_type = L2CAP_CHAN_CONN_LESS;
bt_sk(sk)->skb_msg_name = l2cap_skb_msg_name;
break; break;
case SOCK_SEQPACKET: case SOCK_SEQPACKET:
case SOCK_STREAM: case SOCK_STREAM:
......
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