aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2009-01-15 15:56:48 -0500
committerMarcel Holtmann <marcel@holtmann.org>2009-02-27 00:14:23 -0500
commitbb23c0ab824653be4aa7dfca15b07b3059717004 (patch)
treebd0390c67d129e8b5ddc2a70a1b12e383db6fa16
parentc4f912e155504e94dd4f3d63c378dab0ff03dbda (diff)
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>
-rw-r--r--include/net/bluetooth/rfcomm.h6
-rw-r--r--net/bluetooth/rfcomm/core.c56
-rw-r--r--net/bluetooth/rfcomm/sock.c44
3 files changed, 88 insertions, 18 deletions
diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h
index 4dc8d92a4638..71b45f459687 100644
--- a/include/net/bluetooth/rfcomm.h
+++ b/include/net/bluetooth/rfcomm.h
@@ -185,6 +185,7 @@ struct rfcomm_dlc {
185 u8 out; 185 u8 out;
186 186
187 u32 link_mode; 187 u32 link_mode;
188 u32 defer_setup;
188 189
189 uint mtu; 190 uint mtu;
190 uint cfc; 191 uint cfc;
@@ -202,10 +203,11 @@ struct rfcomm_dlc {
202#define RFCOMM_RX_THROTTLED 0 203#define RFCOMM_RX_THROTTLED 0
203#define RFCOMM_TX_THROTTLED 1 204#define RFCOMM_TX_THROTTLED 1
204#define RFCOMM_TIMED_OUT 2 205#define RFCOMM_TIMED_OUT 2
205#define RFCOMM_MSC_PENDING 3 206#define RFCOMM_MSC_PENDING 3
206#define RFCOMM_AUTH_PENDING 4 207#define RFCOMM_AUTH_PENDING 4
207#define RFCOMM_AUTH_ACCEPT 5 208#define RFCOMM_AUTH_ACCEPT 5
208#define RFCOMM_AUTH_REJECT 6 209#define RFCOMM_AUTH_REJECT 6
210#define RFCOMM_DEFER_SETUP 7
209 211
210/* Scheduling flags and events */ 212/* Scheduling flags and events */
211#define RFCOMM_SCHED_STATE 0 213#define RFCOMM_SCHED_STATE 0
@@ -239,6 +241,7 @@ int rfcomm_dlc_close(struct rfcomm_dlc *d, int reason);
239int rfcomm_dlc_send(struct rfcomm_dlc *d, struct sk_buff *skb); 241int rfcomm_dlc_send(struct rfcomm_dlc *d, struct sk_buff *skb);
240int rfcomm_dlc_set_modem_status(struct rfcomm_dlc *d, u8 v24_sig); 242int rfcomm_dlc_set_modem_status(struct rfcomm_dlc *d, u8 v24_sig);
241int rfcomm_dlc_get_modem_status(struct rfcomm_dlc *d, u8 *v24_sig); 243int rfcomm_dlc_get_modem_status(struct rfcomm_dlc *d, u8 *v24_sig);
244void rfcomm_dlc_accept(struct rfcomm_dlc *d);
242 245
243#define rfcomm_dlc_lock(d) spin_lock(&d->lock) 246#define rfcomm_dlc_lock(d) spin_lock(&d->lock)
244#define rfcomm_dlc_unlock(d) spin_unlock(&d->lock) 247#define rfcomm_dlc_unlock(d) spin_unlock(&d->lock)
@@ -333,7 +336,6 @@ struct rfcomm_dev_req {
333 bdaddr_t src; 336 bdaddr_t src;
334 bdaddr_t dst; 337 bdaddr_t dst;
335 u8 channel; 338 u8 channel;
336
337}; 339};
338 340
339struct rfcomm_dev_info { 341struct rfcomm_dev_info {
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index acd84fd524b8..edee49e00fbf 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -421,9 +421,16 @@ static int __rfcomm_dlc_close(struct rfcomm_dlc *d, int err)
421 d, d->state, d->dlci, err, s); 421 d, d->state, d->dlci, err, s);
422 422
423 switch (d->state) { 423 switch (d->state) {
424 case BT_CONNECTED:
425 case BT_CONFIG:
426 case BT_CONNECT: 424 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:
427 d->state = BT_DISCONN; 434 d->state = BT_DISCONN;
428 if (skb_queue_empty(&d->tx_queue)) { 435 if (skb_queue_empty(&d->tx_queue)) {
429 rfcomm_send_disc(s, d->dlci); 436 rfcomm_send_disc(s, d->dlci);
@@ -434,6 +441,14 @@ static int __rfcomm_dlc_close(struct rfcomm_dlc *d, int err)
434 } 441 }
435 break; 442 break;
436 443
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
437 default: 452 default:
438 rfcomm_dlc_clear_timer(d); 453 rfcomm_dlc_clear_timer(d);
439 454
@@ -1162,7 +1177,7 @@ static int rfcomm_recv_disc(struct rfcomm_session *s, u8 dlci)
1162 return 0; 1177 return 0;
1163} 1178}
1164 1179
1165static void rfcomm_dlc_accept(struct rfcomm_dlc *d) 1180void rfcomm_dlc_accept(struct rfcomm_dlc *d)
1166{ 1181{
1167 struct sock *sk = d->session->sock->sk; 1182 struct sock *sk = d->session->sock->sk;
1168 1183
@@ -1181,6 +1196,20 @@ static void rfcomm_dlc_accept(struct rfcomm_dlc *d)
1181 rfcomm_send_msc(d->session, 1, d->dlci, d->v24_sig); 1196 rfcomm_send_msc(d->session, 1, d->dlci, d->v24_sig);
1182} 1197}
1183 1198
1199static 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
1184static int rfcomm_recv_sabm(struct rfcomm_session *s, u8 dlci) 1213static int rfcomm_recv_sabm(struct rfcomm_session *s, u8 dlci)
1185{ 1214{
1186 struct rfcomm_dlc *d; 1215 struct rfcomm_dlc *d;
@@ -1203,11 +1232,7 @@ static int rfcomm_recv_sabm(struct rfcomm_session *s, u8 dlci)
1203 if (d) { 1232 if (d) {
1204 if (d->state == BT_OPEN) { 1233 if (d->state == BT_OPEN) {
1205 /* DLC was previously opened by PN request */ 1234 /* DLC was previously opened by PN request */
1206 if (rfcomm_check_link_mode(d)) { 1235 rfcomm_check_accept(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);
1211 } 1236 }
1212 return 0; 1237 return 0;
1213 } 1238 }
@@ -1219,11 +1244,7 @@ static int rfcomm_recv_sabm(struct rfcomm_session *s, u8 dlci)
1219 d->addr = __addr(s->initiator, dlci); 1244 d->addr = __addr(s->initiator, dlci);
1220 rfcomm_dlc_link(s, d); 1245 rfcomm_dlc_link(s, d);
1221 1246
1222 if (rfcomm_check_link_mode(d)) { 1247 rfcomm_check_accept(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);
1227 } else { 1248 } else {
1228 rfcomm_send_dm(s, dlci); 1249 rfcomm_send_dm(s, dlci);
1229 } 1250 }
@@ -1717,8 +1738,13 @@ static inline void rfcomm_process_dlcs(struct rfcomm_session *s)
1717 if (d->out) { 1738 if (d->out) {
1718 rfcomm_send_pn(s, 1, d); 1739 rfcomm_send_pn(s, 1, d);
1719 rfcomm_dlc_set_timer(d, RFCOMM_CONN_TIMEOUT); 1740 rfcomm_dlc_set_timer(d, RFCOMM_CONN_TIMEOUT);
1720 } else 1741 } else {
1721 rfcomm_dlc_accept(d); 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 }
1722 if (d->link_mode & RFCOMM_LM_SECURE) { 1748 if (d->link_mode & RFCOMM_LM_SECURE) {
1723 struct sock *sk = s->sock->sk; 1749 struct sock *sk = s->sock->sk;
1724 hci_conn_change_link_key(l2cap_pi(sk)->conn->hcon); 1750 hci_conn_change_link_key(l2cap_pi(sk)->conn->hcon);
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index 65dd7133d72b..d37a829a81e4 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -262,8 +262,10 @@ static void rfcomm_sock_init(struct sock *sk, struct sock *parent)
262 if (parent) { 262 if (parent) {
263 sk->sk_type = parent->sk_type; 263 sk->sk_type = parent->sk_type;
264 pi->link_mode = rfcomm_pi(parent)->link_mode; 264 pi->link_mode = rfcomm_pi(parent)->link_mode;
265 pi->dlc->defer_setup = bt_sk(parent)->defer_setup;
265 } else { 266 } else {
266 pi->link_mode = 0; 267 pi->link_mode = 0;
268 pi->dlc->defer_setup = 0;
267 } 269 }
268 270
269 pi->dlc->link_mode = pi->link_mode; 271 pi->dlc->link_mode = pi->link_mode;
@@ -554,6 +556,9 @@ static int rfcomm_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
554 struct sk_buff *skb; 556 struct sk_buff *skb;
555 int sent = 0; 557 int sent = 0;
556 558
559 if (test_bit(RFCOMM_DEFER_SETUP, &d->flags))
560 return -ENOTCONN;
561
557 if (msg->msg_flags & MSG_OOB) 562 if (msg->msg_flags & MSG_OOB)
558 return -EOPNOTSUPP; 563 return -EOPNOTSUPP;
559 564
@@ -633,10 +638,16 @@ static int rfcomm_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
633 struct msghdr *msg, size_t size, int flags) 638 struct msghdr *msg, size_t size, int flags)
634{ 639{
635 struct sock *sk = sock->sk; 640 struct sock *sk = sock->sk;
641 struct rfcomm_dlc *d = rfcomm_pi(sk)->dlc;
636 int err = 0; 642 int err = 0;
637 size_t target, copied = 0; 643 size_t target, copied = 0;
638 long timeo; 644 long timeo;
639 645
646 if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) {
647 rfcomm_dlc_accept(d);
648 return 0;
649 }
650
640 if (flags & MSG_OOB) 651 if (flags & MSG_OOB)
641 return -EOPNOTSUPP; 652 return -EOPNOTSUPP;
642 653
@@ -746,6 +757,7 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, c
746{ 757{
747 struct sock *sk = sock->sk; 758 struct sock *sk = sock->sk;
748 int err = 0; 759 int err = 0;
760 u32 opt;
749 761
750 BT_DBG("sk %p", sk); 762 BT_DBG("sk %p", sk);
751 763
@@ -755,6 +767,20 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, c
755 lock_sock(sk); 767 lock_sock(sk);
756 768
757 switch (optname) { 769 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
758 default: 784 default:
759 err = -ENOPROTOOPT; 785 err = -ENOPROTOOPT;
760 break; 786 break;
@@ -785,7 +811,8 @@ static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __u
785 break; 811 break;
786 812
787 case RFCOMM_CONNINFO: 813 case RFCOMM_CONNINFO:
788 if (sk->sk_state != BT_CONNECTED) { 814 if (sk->sk_state != BT_CONNECTED &&
815 !rfcomm_pi(sk)->dlc->defer_setup) {
789 err = -ENOTCONN; 816 err = -ENOTCONN;
790 break; 817 break;
791 } 818 }
@@ -826,6 +853,17 @@ static int rfcomm_sock_getsockopt(struct socket *sock, int level, int optname, c
826 lock_sock(sk); 853 lock_sock(sk);
827 854
828 switch (optname) { 855 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
829 default: 867 default:
830 err = -ENOPROTOOPT; 868 err = -ENOPROTOOPT;
831 break; 869 break;
@@ -938,6 +976,10 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc *
938 976
939done: 977done:
940 bh_unlock_sock(parent); 978 bh_unlock_sock(parent);
979
980 if (bt_sk(parent)->defer_setup)
981 parent->sk_state_change(parent);
982
941 return result; 983 return result;
942} 984}
943 985