diff options
Diffstat (limited to 'net/bluetooth/l2cap_sock.c')
-rw-r--r-- | net/bluetooth/l2cap_sock.c | 62 |
1 files changed, 31 insertions, 31 deletions
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index d58f76bcebd1..b247f9d27fed 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c | |||
@@ -36,8 +36,6 @@ | |||
36 | 36 | ||
37 | #include "smp.h" | 37 | #include "smp.h" |
38 | 38 | ||
39 | bool enable_lecoc; | ||
40 | |||
41 | static struct bt_sock_list l2cap_sk_list = { | 39 | static struct bt_sock_list l2cap_sk_list = { |
42 | .lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock) | 40 | .lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock) |
43 | }; | 41 | }; |
@@ -101,9 +99,16 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) | |||
101 | if (!bdaddr_type_is_valid(la.l2_bdaddr_type)) | 99 | if (!bdaddr_type_is_valid(la.l2_bdaddr_type)) |
102 | return -EINVAL; | 100 | return -EINVAL; |
103 | 101 | ||
102 | if (la.l2_cid) { | ||
103 | /* When the socket gets created it defaults to | ||
104 | * CHAN_CONN_ORIENTED, so we need to overwrite the | ||
105 | * default here. | ||
106 | */ | ||
107 | chan->chan_type = L2CAP_CHAN_FIXED; | ||
108 | chan->omtu = L2CAP_DEFAULT_MTU; | ||
109 | } | ||
110 | |||
104 | if (bdaddr_type_is_le(la.l2_bdaddr_type)) { | 111 | if (bdaddr_type_is_le(la.l2_bdaddr_type)) { |
105 | if (!enable_lecoc && la.l2_psm) | ||
106 | return -EINVAL; | ||
107 | /* We only allow ATT user space socket */ | 112 | /* We only allow ATT user space socket */ |
108 | if (la.l2_cid && | 113 | if (la.l2_cid && |
109 | la.l2_cid != __constant_cpu_to_le16(L2CAP_CID_ATT)) | 114 | la.l2_cid != __constant_cpu_to_le16(L2CAP_CID_ATT)) |
@@ -220,8 +225,6 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, | |||
220 | return -EINVAL; | 225 | return -EINVAL; |
221 | 226 | ||
222 | if (bdaddr_type_is_le(la.l2_bdaddr_type)) { | 227 | if (bdaddr_type_is_le(la.l2_bdaddr_type)) { |
223 | if (!enable_lecoc && la.l2_psm) | ||
224 | return -EINVAL; | ||
225 | /* We only allow ATT user space socket */ | 228 | /* We only allow ATT user space socket */ |
226 | if (la.l2_cid && | 229 | if (la.l2_cid && |
227 | la.l2_cid != __constant_cpu_to_le16(L2CAP_CID_ATT)) | 230 | la.l2_cid != __constant_cpu_to_le16(L2CAP_CID_ATT)) |
@@ -357,17 +360,20 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, | |||
357 | 360 | ||
358 | BT_DBG("sock %p, sk %p", sock, sk); | 361 | BT_DBG("sock %p, sk %p", sock, sk); |
359 | 362 | ||
363 | if (peer && sk->sk_state != BT_CONNECTED) | ||
364 | return -ENOTCONN; | ||
365 | |||
360 | memset(la, 0, sizeof(struct sockaddr_l2)); | 366 | memset(la, 0, sizeof(struct sockaddr_l2)); |
361 | addr->sa_family = AF_BLUETOOTH; | 367 | addr->sa_family = AF_BLUETOOTH; |
362 | *len = sizeof(struct sockaddr_l2); | 368 | *len = sizeof(struct sockaddr_l2); |
363 | 369 | ||
370 | la->l2_psm = chan->psm; | ||
371 | |||
364 | if (peer) { | 372 | if (peer) { |
365 | la->l2_psm = chan->psm; | ||
366 | bacpy(&la->l2_bdaddr, &chan->dst); | 373 | bacpy(&la->l2_bdaddr, &chan->dst); |
367 | la->l2_cid = cpu_to_le16(chan->dcid); | 374 | la->l2_cid = cpu_to_le16(chan->dcid); |
368 | la->l2_bdaddr_type = chan->dst_type; | 375 | la->l2_bdaddr_type = chan->dst_type; |
369 | } else { | 376 | } else { |
370 | la->l2_psm = chan->sport; | ||
371 | bacpy(&la->l2_bdaddr, &chan->src); | 377 | bacpy(&la->l2_bdaddr, &chan->src); |
372 | la->l2_cid = cpu_to_le16(chan->scid); | 378 | la->l2_cid = cpu_to_le16(chan->scid); |
373 | la->l2_bdaddr_type = chan->src_type; | 379 | la->l2_bdaddr_type = chan->src_type; |
@@ -432,6 +438,10 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, | |||
432 | opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT | | 438 | opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT | |
433 | L2CAP_LM_SECURE; | 439 | L2CAP_LM_SECURE; |
434 | break; | 440 | break; |
441 | case BT_SECURITY_FIPS: | ||
442 | opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT | | ||
443 | L2CAP_LM_SECURE | L2CAP_LM_FIPS; | ||
444 | break; | ||
435 | default: | 445 | default: |
436 | opt = 0; | 446 | opt = 0; |
437 | break; | 447 | break; |
@@ -445,6 +455,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, | |||
445 | 455 | ||
446 | if (put_user(opt, (u32 __user *) optval)) | 456 | if (put_user(opt, (u32 __user *) optval)) |
447 | err = -EFAULT; | 457 | err = -EFAULT; |
458 | |||
448 | break; | 459 | break; |
449 | 460 | ||
450 | case L2CAP_CONNINFO: | 461 | case L2CAP_CONNINFO: |
@@ -499,6 +510,7 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, | |||
499 | switch (optname) { | 510 | switch (optname) { |
500 | case BT_SECURITY: | 511 | case BT_SECURITY: |
501 | if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED && | 512 | if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED && |
513 | chan->chan_type != L2CAP_CHAN_FIXED && | ||
502 | chan->chan_type != L2CAP_CHAN_RAW) { | 514 | chan->chan_type != L2CAP_CHAN_RAW) { |
503 | err = -EINVAL; | 515 | err = -EINVAL; |
504 | break; | 516 | break; |
@@ -560,11 +572,6 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, | |||
560 | break; | 572 | break; |
561 | 573 | ||
562 | case BT_SNDMTU: | 574 | case BT_SNDMTU: |
563 | if (!enable_lecoc) { | ||
564 | err = -EPROTONOSUPPORT; | ||
565 | break; | ||
566 | } | ||
567 | |||
568 | if (!bdaddr_type_is_le(chan->src_type)) { | 575 | if (!bdaddr_type_is_le(chan->src_type)) { |
569 | err = -EINVAL; | 576 | err = -EINVAL; |
570 | break; | 577 | break; |
@@ -580,11 +587,6 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, | |||
580 | break; | 587 | break; |
581 | 588 | ||
582 | case BT_RCVMTU: | 589 | case BT_RCVMTU: |
583 | if (!enable_lecoc) { | ||
584 | err = -EPROTONOSUPPORT; | ||
585 | break; | ||
586 | } | ||
587 | |||
588 | if (!bdaddr_type_is_le(chan->src_type)) { | 590 | if (!bdaddr_type_is_le(chan->src_type)) { |
589 | err = -EINVAL; | 591 | err = -EINVAL; |
590 | break; | 592 | break; |
@@ -699,6 +701,11 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, | |||
699 | break; | 701 | break; |
700 | } | 702 | } |
701 | 703 | ||
704 | if (opt & L2CAP_LM_FIPS) { | ||
705 | err = -EINVAL; | ||
706 | break; | ||
707 | } | ||
708 | |||
702 | if (opt & L2CAP_LM_AUTH) | 709 | if (opt & L2CAP_LM_AUTH) |
703 | chan->sec_level = BT_SECURITY_LOW; | 710 | chan->sec_level = BT_SECURITY_LOW; |
704 | if (opt & L2CAP_LM_ENCRYPT) | 711 | if (opt & L2CAP_LM_ENCRYPT) |
@@ -750,6 +757,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, | |||
750 | switch (optname) { | 757 | switch (optname) { |
751 | case BT_SECURITY: | 758 | case BT_SECURITY: |
752 | if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED && | 759 | if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED && |
760 | chan->chan_type != L2CAP_CHAN_FIXED && | ||
753 | chan->chan_type != L2CAP_CHAN_RAW) { | 761 | chan->chan_type != L2CAP_CHAN_RAW) { |
754 | err = -EINVAL; | 762 | err = -EINVAL; |
755 | break; | 763 | break; |
@@ -895,11 +903,6 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, | |||
895 | break; | 903 | break; |
896 | 904 | ||
897 | case BT_SNDMTU: | 905 | case BT_SNDMTU: |
898 | if (!enable_lecoc) { | ||
899 | err = -EPROTONOSUPPORT; | ||
900 | break; | ||
901 | } | ||
902 | |||
903 | if (!bdaddr_type_is_le(chan->src_type)) { | 906 | if (!bdaddr_type_is_le(chan->src_type)) { |
904 | err = -EINVAL; | 907 | err = -EINVAL; |
905 | break; | 908 | break; |
@@ -912,11 +915,6 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, | |||
912 | break; | 915 | break; |
913 | 916 | ||
914 | case BT_RCVMTU: | 917 | case BT_RCVMTU: |
915 | if (!enable_lecoc) { | ||
916 | err = -EPROTONOSUPPORT; | ||
917 | break; | ||
918 | } | ||
919 | |||
920 | if (!bdaddr_type_is_le(chan->src_type)) { | 918 | if (!bdaddr_type_is_le(chan->src_type)) { |
921 | err = -EINVAL; | 919 | err = -EINVAL; |
922 | break; | 920 | break; |
@@ -1449,6 +1447,11 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent) | |||
1449 | chan->tx_credits = pchan->tx_credits; | 1447 | chan->tx_credits = pchan->tx_credits; |
1450 | chan->rx_credits = pchan->rx_credits; | 1448 | chan->rx_credits = pchan->rx_credits; |
1451 | 1449 | ||
1450 | if (chan->chan_type == L2CAP_CHAN_FIXED) { | ||
1451 | chan->scid = pchan->scid; | ||
1452 | chan->dcid = pchan->scid; | ||
1453 | } | ||
1454 | |||
1452 | security_sk_clone(parent, sk); | 1455 | security_sk_clone(parent, sk); |
1453 | } else { | 1456 | } else { |
1454 | switch (sk->sk_type) { | 1457 | switch (sk->sk_type) { |
@@ -1614,6 +1617,3 @@ void l2cap_cleanup_sockets(void) | |||
1614 | bt_sock_unregister(BTPROTO_L2CAP); | 1617 | bt_sock_unregister(BTPROTO_L2CAP); |
1615 | proto_unregister(&l2cap_proto); | 1618 | proto_unregister(&l2cap_proto); |
1616 | } | 1619 | } |
1617 | |||
1618 | module_param(enable_lecoc, bool, 0644); | ||
1619 | MODULE_PARM_DESC(enable_lecoc, "Enable support for LE CoC"); | ||