aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2009-01-15 15:57:00 -0500
committerMarcel Holtmann <marcel@holtmann.org>2009-02-27 00:14:24 -0500
commitf66dc81f44d918ee1aa1a9d821bb2f25c7592bc0 (patch)
treefe9030b58a7fac0d85dbed2da9f33702aab2e9b5 /net
parentbb23c0ab824653be4aa7dfca15b07b3059717004 (diff)
Bluetooth: Add support for deferring L2CAP connection setup
In order to decide if listening L2CAP 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. Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net')
-rw-r--r--net/bluetooth/l2cap.c110
1 files changed, 101 insertions, 9 deletions
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index df1a95e185c6..123efb46d3f5 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -372,9 +372,17 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
372 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); 372 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
373 373
374 if (l2cap_check_link_mode(sk)) { 374 if (l2cap_check_link_mode(sk)) {
375 sk->sk_state = BT_CONFIG; 375 if (bt_sk(sk)->defer_setup) {
376 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); 376 struct sock *parent = bt_sk(sk)->parent;
377 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); 377 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
378 rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
379 parent->sk_data_ready(parent, 0);
380
381 } else {
382 sk->sk_state = BT_CONFIG;
383 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
384 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
385 }
378 } else { 386 } else {
379 rsp.result = cpu_to_le16(L2CAP_CR_PEND); 387 rsp.result = cpu_to_le16(L2CAP_CR_PEND);
380 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND); 388 rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
@@ -608,7 +616,6 @@ static void __l2cap_sock_close(struct sock *sk, int reason)
608 616
609 case BT_CONNECTED: 617 case BT_CONNECTED:
610 case BT_CONFIG: 618 case BT_CONFIG:
611 case BT_CONNECT2:
612 if (sk->sk_type == SOCK_SEQPACKET) { 619 if (sk->sk_type == SOCK_SEQPACKET) {
613 struct l2cap_conn *conn = l2cap_pi(sk)->conn; 620 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
614 struct l2cap_disconn_req req; 621 struct l2cap_disconn_req req;
@@ -624,6 +631,27 @@ static void __l2cap_sock_close(struct sock *sk, int reason)
624 l2cap_chan_del(sk, reason); 631 l2cap_chan_del(sk, reason);
625 break; 632 break;
626 633
634 case BT_CONNECT2:
635 if (sk->sk_type == SOCK_SEQPACKET) {
636 struct l2cap_conn *conn = l2cap_pi(sk)->conn;
637 struct l2cap_conn_rsp rsp;
638 __u16 result;
639
640 if (bt_sk(sk)->defer_setup)
641 result = L2CAP_CR_SEC_BLOCK;
642 else
643 result = L2CAP_CR_BAD_PSM;
644
645 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
646 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
647 rsp.result = cpu_to_le16(result);
648 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
649 l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
650 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
651 } else
652 l2cap_chan_del(sk, reason);
653 break;
654
627 case BT_CONNECT: 655 case BT_CONNECT:
628 case BT_DISCONN: 656 case BT_DISCONN:
629 l2cap_chan_del(sk, reason); 657 l2cap_chan_del(sk, reason);
@@ -653,6 +681,8 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent)
653 681
654 if (parent) { 682 if (parent) {
655 sk->sk_type = parent->sk_type; 683 sk->sk_type = parent->sk_type;
684 bt_sk(sk)->defer_setup = bt_sk(parent)->defer_setup;
685
656 pi->imtu = l2cap_pi(parent)->imtu; 686 pi->imtu = l2cap_pi(parent)->imtu;
657 pi->omtu = l2cap_pi(parent)->omtu; 687 pi->omtu = l2cap_pi(parent)->omtu;
658 pi->link_mode = l2cap_pi(parent)->link_mode; 688 pi->link_mode = l2cap_pi(parent)->link_mode;
@@ -1106,6 +1136,33 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
1106 return err; 1136 return err;
1107} 1137}
1108 1138
1139static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len, int flags)
1140{
1141 struct sock *sk = sock->sk;
1142
1143 lock_sock(sk);
1144
1145 if (sk->sk_state == BT_CONNECT2 && bt_sk(sk)->defer_setup) {
1146 struct l2cap_conn_rsp rsp;
1147
1148 sk->sk_state = BT_CONFIG;
1149
1150 rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
1151 rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
1152 rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
1153 rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
1154 l2cap_send_cmd(l2cap_pi(sk)->conn, l2cap_pi(sk)->ident,
1155 L2CAP_CONN_RSP, sizeof(rsp), &rsp);
1156
1157 release_sock(sk);
1158 return 0;
1159 }
1160
1161 release_sock(sk);
1162
1163 return bt_sock_recvmsg(iocb, sock, msg, len, flags);
1164}
1165
1109static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __user *optval, int optlen) 1166static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __user *optval, int optlen)
1110{ 1167{
1111 struct sock *sk = sock->sk; 1168 struct sock *sk = sock->sk;
@@ -1156,6 +1213,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
1156{ 1213{
1157 struct sock *sk = sock->sk; 1214 struct sock *sk = sock->sk;
1158 int err = 0; 1215 int err = 0;
1216 u32 opt;
1159 1217
1160 BT_DBG("sk %p", sk); 1218 BT_DBG("sk %p", sk);
1161 1219
@@ -1165,6 +1223,20 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
1165 lock_sock(sk); 1223 lock_sock(sk);
1166 1224
1167 switch (optname) { 1225 switch (optname) {
1226 case BT_DEFER_SETUP:
1227 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
1228 err = -EINVAL;
1229 break;
1230 }
1231
1232 if (get_user(opt, (u32 __user *) optval)) {
1233 err = -EFAULT;
1234 break;
1235 }
1236
1237 bt_sk(sk)->defer_setup = opt;
1238 break;
1239
1168 default: 1240 default:
1169 err = -ENOPROTOOPT; 1241 err = -ENOPROTOOPT;
1170 break; 1242 break;
@@ -1207,7 +1279,9 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us
1207 break; 1279 break;
1208 1280
1209 case L2CAP_CONNINFO: 1281 case L2CAP_CONNINFO:
1210 if (sk->sk_state != BT_CONNECTED) { 1282 if (sk->sk_state != BT_CONNECTED &&
1283 !(sk->sk_state == BT_CONNECT2 &&
1284 bt_sk(sk)->defer_setup)) {
1211 err = -ENOTCONN; 1285 err = -ENOTCONN;
1212 break; 1286 break;
1213 } 1287 }
@@ -1246,6 +1320,17 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
1246 lock_sock(sk); 1320 lock_sock(sk);
1247 1321
1248 switch (optname) { 1322 switch (optname) {
1323 case BT_DEFER_SETUP:
1324 if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
1325 err = -EINVAL;
1326 break;
1327 }
1328
1329 if (put_user(bt_sk(sk)->defer_setup, (u32 __user *) optval))
1330 err = -EFAULT;
1331
1332 break;
1333
1249 default: 1334 default:
1250 err = -ENOPROTOOPT; 1335 err = -ENOPROTOOPT;
1251 break; 1336 break;
@@ -1670,9 +1755,16 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
1670 1755
1671 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) { 1756 if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
1672 if (l2cap_check_link_mode(sk)) { 1757 if (l2cap_check_link_mode(sk)) {
1673 sk->sk_state = BT_CONFIG; 1758 if (bt_sk(sk)->defer_setup) {
1674 result = L2CAP_CR_SUCCESS; 1759 sk->sk_state = BT_CONNECT2;
1675 status = L2CAP_CS_NO_INFO; 1760 result = L2CAP_CR_PEND;
1761 status = L2CAP_CS_AUTHOR_PEND;
1762 parent->sk_data_ready(parent, 0);
1763 } else {
1764 sk->sk_state = BT_CONFIG;
1765 result = L2CAP_CR_SUCCESS;
1766 status = L2CAP_CS_NO_INFO;
1767 }
1676 } else { 1768 } else {
1677 sk->sk_state = BT_CONNECT2; 1769 sk->sk_state = BT_CONNECT2;
1678 result = L2CAP_CR_PEND; 1770 result = L2CAP_CR_PEND;
@@ -2494,7 +2586,7 @@ static const struct proto_ops l2cap_sock_ops = {
2494 .accept = l2cap_sock_accept, 2586 .accept = l2cap_sock_accept,
2495 .getname = l2cap_sock_getname, 2587 .getname = l2cap_sock_getname,
2496 .sendmsg = l2cap_sock_sendmsg, 2588 .sendmsg = l2cap_sock_sendmsg,
2497 .recvmsg = bt_sock_recvmsg, 2589 .recvmsg = l2cap_sock_recvmsg,
2498 .poll = bt_sock_poll, 2590 .poll = bt_sock_poll,
2499 .ioctl = bt_sock_ioctl, 2591 .ioctl = bt_sock_ioctl,
2500 .mmap = sock_no_mmap, 2592 .mmap = sock_no_mmap,