Skip to content

Commit bb23c0a

Browse files
committed
Bluetooth: Add support for deferring RFCOMM connection setup
In order to decide if listening RFCOMM sockets should be accept()ed the BD_ADDR of the remote device needs to be known. This patch adds a socket option which defines a timeout for deferring the actual connection setup. The connection setup is done after reading from the socket for the first time. Until then writing to the socket returns ENOTCONN. Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
1 parent c4f912e commit bb23c0a

File tree

3 files changed

+88
-18
lines changed

3 files changed

+88
-18
lines changed

include/net/bluetooth/rfcomm.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ struct rfcomm_dlc {
185185
u8 out;
186186

187187
u32 link_mode;
188+
u32 defer_setup;
188189

189190
uint mtu;
190191
uint cfc;
@@ -202,10 +203,11 @@ struct rfcomm_dlc {
202203
#define RFCOMM_RX_THROTTLED 0
203204
#define RFCOMM_TX_THROTTLED 1
204205
#define RFCOMM_TIMED_OUT 2
205-
#define RFCOMM_MSC_PENDING 3
206+
#define RFCOMM_MSC_PENDING 3
206207
#define RFCOMM_AUTH_PENDING 4
207208
#define RFCOMM_AUTH_ACCEPT 5
208209
#define RFCOMM_AUTH_REJECT 6
210+
#define RFCOMM_DEFER_SETUP 7
209211

210212
/* Scheduling flags and events */
211213
#define RFCOMM_SCHED_STATE 0
@@ -239,6 +241,7 @@ int rfcomm_dlc_close(struct rfcomm_dlc *d, int reason);
239241
int rfcomm_dlc_send(struct rfcomm_dlc *d, struct sk_buff *skb);
240242
int rfcomm_dlc_set_modem_status(struct rfcomm_dlc *d, u8 v24_sig);
241243
int rfcomm_dlc_get_modem_status(struct rfcomm_dlc *d, u8 *v24_sig);
244+
void rfcomm_dlc_accept(struct rfcomm_dlc *d);
242245

243246
#define rfcomm_dlc_lock(d) spin_lock(&d->lock)
244247
#define rfcomm_dlc_unlock(d) spin_unlock(&d->lock)
@@ -333,7 +336,6 @@ struct rfcomm_dev_req {
333336
bdaddr_t src;
334337
bdaddr_t dst;
335338
u8 channel;
336-
337339
};
338340

339341
struct rfcomm_dev_info {

net/bluetooth/rfcomm/core.c

Lines changed: 41 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -421,9 +421,16 @@ static int __rfcomm_dlc_close(struct rfcomm_dlc *d, int err)
421421
d, d->state, d->dlci, err, s);
422422

423423
switch (d->state) {
424-
case BT_CONNECTED:
425-
case BT_CONFIG:
426424
case BT_CONNECT:
425+
case BT_CONFIG:
426+
if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) {
427+
set_bit(RFCOMM_AUTH_REJECT, &d->flags);
428+
rfcomm_schedule(RFCOMM_SCHED_AUTH);
429+
break;
430+
}
431+
/* Fall through */
432+
433+
case BT_CONNECTED:
427434
d->state = BT_DISCONN;
428435
if (skb_queue_empty(&d->tx_queue)) {
429436
rfcomm_send_disc(s, d->dlci);
@@ -434,6 +441,14 @@ static int __rfcomm_dlc_close(struct rfcomm_dlc *d, int err)
434441
}
435442
break;
436443

444+
case BT_OPEN:
445+
if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) {
446+
set_bit(RFCOMM_AUTH_REJECT, &d->flags);
447+
rfcomm_schedule(RFCOMM_SCHED_AUTH);
448+
break;
449+
}
450+
/* Fall through */
451+
437452
default:
438453
rfcomm_dlc_clear_timer(d);
439454

@@ -1162,7 +1177,7 @@ static int rfcomm_recv_disc(struct rfcomm_session *s, u8 dlci)
11621177
return 0;
11631178
}
11641179

1165-
static void rfcomm_dlc_accept(struct rfcomm_dlc *d)
1180+
void rfcomm_dlc_accept(struct rfcomm_dlc *d)
11661181
{
11671182
struct sock *sk = d->session->sock->sk;
11681183

@@ -1181,6 +1196,20 @@ static void rfcomm_dlc_accept(struct rfcomm_dlc *d)
11811196
rfcomm_send_msc(d->session, 1, d->dlci, d->v24_sig);
11821197
}
11831198

1199+
static void rfcomm_check_accept(struct rfcomm_dlc *d)
1200+
{
1201+
if (rfcomm_check_link_mode(d)) {
1202+
set_bit(RFCOMM_AUTH_PENDING, &d->flags);
1203+
rfcomm_dlc_set_timer(d, RFCOMM_AUTH_TIMEOUT);
1204+
} else {
1205+
if (d->defer_setup) {
1206+
set_bit(RFCOMM_DEFER_SETUP, &d->flags);
1207+
rfcomm_dlc_set_timer(d, RFCOMM_AUTH_TIMEOUT);
1208+
} else
1209+
rfcomm_dlc_accept(d);
1210+
}
1211+
}
1212+
11841213
static int rfcomm_recv_sabm(struct rfcomm_session *s, u8 dlci)
11851214
{
11861215
struct rfcomm_dlc *d;
@@ -1203,11 +1232,7 @@ static int rfcomm_recv_sabm(struct rfcomm_session *s, u8 dlci)
12031232
if (d) {
12041233
if (d->state == BT_OPEN) {
12051234
/* DLC was previously opened by PN request */
1206-
if (rfcomm_check_link_mode(d)) {
1207-
set_bit(RFCOMM_AUTH_PENDING, &d->flags);
1208-
rfcomm_dlc_set_timer(d, RFCOMM_AUTH_TIMEOUT);
1209-
} else
1210-
rfcomm_dlc_accept(d);
1235+
rfcomm_check_accept(d);
12111236
}
12121237
return 0;
12131238
}
@@ -1219,11 +1244,7 @@ static int rfcomm_recv_sabm(struct rfcomm_session *s, u8 dlci)
12191244
d->addr = __addr(s->initiator, dlci);
12201245
rfcomm_dlc_link(s, d);
12211246

1222-
if (rfcomm_check_link_mode(d)) {
1223-
set_bit(RFCOMM_AUTH_PENDING, &d->flags);
1224-
rfcomm_dlc_set_timer(d, RFCOMM_AUTH_TIMEOUT);
1225-
} else
1226-
rfcomm_dlc_accept(d);
1247+
rfcomm_check_accept(d);
12271248
} else {
12281249
rfcomm_send_dm(s, dlci);
12291250
}
@@ -1717,8 +1738,13 @@ static inline void rfcomm_process_dlcs(struct rfcomm_session *s)
17171738
if (d->out) {
17181739
rfcomm_send_pn(s, 1, d);
17191740
rfcomm_dlc_set_timer(d, RFCOMM_CONN_TIMEOUT);
1720-
} else
1721-
rfcomm_dlc_accept(d);
1741+
} else {
1742+
if (d->defer_setup) {
1743+
set_bit(RFCOMM_DEFER_SETUP, &d->flags);
1744+
rfcomm_dlc_set_timer(d, RFCOMM_AUTH_TIMEOUT);
1745+
} else
1746+
rfcomm_dlc_accept(d);
1747+
}
17221748
if (d->link_mode & RFCOMM_LM_SECURE) {
17231749
struct sock *sk = s->sock->sk;
17241750
hci_conn_change_link_key(l2cap_pi(sk)->conn->hcon);

net/bluetooth/rfcomm/sock.c

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,8 +262,10 @@ static void rfcomm_sock_init(struct sock *sk, struct sock *parent)
262262
if (parent) {
263263
sk->sk_type = parent->sk_type;
264264
pi->link_mode = rfcomm_pi(parent)->link_mode;
265+
pi->dlc->defer_setup = bt_sk(parent)->defer_setup;
265266
} else {
266267
pi->link_mode = 0;
268+
pi->dlc->defer_setup = 0;
267269
}
268270

269271
pi->dlc->link_mode = pi->link_mode;
@@ -554,6 +556,9 @@ static int rfcomm_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
554556
struct sk_buff *skb;
555557
int sent = 0;
556558

559+
if (test_bit(RFCOMM_DEFER_SETUP, &d->flags))
560+
return -ENOTCONN;
561+
557562
if (msg->msg_flags & MSG_OOB)
558563
return -EOPNOTSUPP;
559564

@@ -633,10 +638,16 @@ static int rfcomm_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
633638
struct msghdr *msg, size_t size, int flags)
634639
{
635640
struct sock *sk = sock->sk;
641+
struct rfcomm_dlc *d = rfcomm_pi(sk)->dlc;
636642
int err = 0;
637643
size_t target, copied = 0;
638644
long timeo;
639645

646+
if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) {
647+
rfcomm_dlc_accept(d);
648+
return 0;
649+
}
650+
640651
if (flags & MSG_OOB)
641652
return -EOPNOTSUPP;
642653

@@ -746,6 +757,7 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, c
746757
{
747758
struct sock *sk = sock->sk;
748759
int err = 0;
760+
u32 opt;
749761

750762
BT_DBG("sk %p", sk);
751763

@@ -755,6 +767,20 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, c
755767
lock_sock(sk);
756768

757769
switch (optname) {
770+
case BT_DEFER_SETUP:
771+
if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
772+
err = -EINVAL;
773+
break;
774+
}
775+
776+
if (get_user(opt, (u32 __user *) optval)) {
777+
err = -EFAULT;
778+
break;
779+
}
780+
781+
bt_sk(sk)->defer_setup = opt;
782+
break;
783+
758784
default:
759785
err = -ENOPROTOOPT;
760786
break;
@@ -785,7 +811,8 @@ static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __u
785811
break;
786812

787813
case RFCOMM_CONNINFO:
788-
if (sk->sk_state != BT_CONNECTED) {
814+
if (sk->sk_state != BT_CONNECTED &&
815+
!rfcomm_pi(sk)->dlc->defer_setup) {
789816
err = -ENOTCONN;
790817
break;
791818
}
@@ -826,6 +853,17 @@ static int rfcomm_sock_getsockopt(struct socket *sock, int level, int optname, c
826853
lock_sock(sk);
827854

828855
switch (optname) {
856+
case BT_DEFER_SETUP:
857+
if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
858+
err = -EINVAL;
859+
break;
860+
}
861+
862+
if (put_user(bt_sk(sk)->defer_setup, (u32 __user *) optval))
863+
err = -EFAULT;
864+
865+
break;
866+
829867
default:
830868
err = -ENOPROTOOPT;
831869
break;
@@ -938,6 +976,10 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc *
938976

939977
done:
940978
bh_unlock_sock(parent);
979+
980+
if (bt_sk(parent)->defer_setup)
981+
parent->sk_state_change(parent);
982+
941983
return result;
942984
}
943985

0 commit comments

Comments
 (0)