2011-02-04 01:50:35 +03:00
/*
BlueZ - Bluetooth protocol stack for Linux
Copyright ( C ) 2000 - 2001 Qualcomm Incorporated
Copyright ( C ) 2009 - 2010 Gustavo F . Padovan < gustavo @ padovan . org >
Copyright ( C ) 2010 Google Inc .
Written 2000 , 2001 by Maxim Krasnyansky < maxk @ qualcomm . com >
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation ;
THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS
OR IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS .
IN NO EVENT SHALL THE COPYRIGHT HOLDER ( S ) AND AUTHOR ( S ) BE LIABLE FOR ANY
CLAIM , OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES , OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE , DATA OR PROFITS , WHETHER IN AN
ACTION OF CONTRACT , NEGLIGENCE OR OTHER TORTIOUS ACTION , ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE .
ALL LIABILITY , INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS ,
COPYRIGHTS , TRADEMARKS OR OTHER RIGHTS , RELATING TO USE OF THIS
SOFTWARE IS DISCLAIMED .
*/
/* Bluetooth L2CAP sockets. */
# include <net/bluetooth/bluetooth.h>
2011-02-04 07:48:48 +03:00
# include <net/bluetooth/hci_core.h>
2011-02-04 01:50:35 +03:00
# include <net/bluetooth/l2cap.h>
2011-02-04 08:23:31 +03:00
/* ---- L2CAP timers ---- */
2011-02-04 01:50:35 +03:00
static void l2cap_sock_timeout ( unsigned long arg )
{
struct sock * sk = ( struct sock * ) arg ;
int reason ;
BT_DBG ( " sock %p state %d " , sk , sk - > sk_state ) ;
bh_lock_sock ( sk ) ;
if ( sock_owned_by_user ( sk ) ) {
/* sk is owned by user. Try again later */
l2cap_sock_set_timer ( sk , HZ / 5 ) ;
bh_unlock_sock ( sk ) ;
sock_put ( sk ) ;
return ;
}
if ( sk - > sk_state = = BT_CONNECTED | | sk - > sk_state = = BT_CONFIG )
reason = ECONNREFUSED ;
else if ( sk - > sk_state = = BT_CONNECT & &
l2cap_pi ( sk ) - > sec_level ! = BT_SECURITY_SDP )
reason = ECONNREFUSED ;
else
reason = ETIMEDOUT ;
__l2cap_sock_close ( sk , reason ) ;
bh_unlock_sock ( sk ) ;
l2cap_sock_kill ( sk ) ;
sock_put ( sk ) ;
}
2011-02-04 08:23:31 +03:00
void l2cap_sock_set_timer ( struct sock * sk , long timeout )
{
BT_DBG ( " sk %p state %d timeout %ld " , sk , sk - > sk_state , timeout ) ;
sk_reset_timer ( sk , & sk - > sk_timer , jiffies + timeout ) ;
}
void l2cap_sock_clear_timer ( struct sock * sk )
{
BT_DBG ( " sock %p state %d " , sk , sk - > sk_state ) ;
sk_stop_timer ( sk , & sk - > sk_timer ) ;
}
2011-02-04 07:40:28 +03:00
static struct sock * __l2cap_get_sock_by_addr ( __le16 psm , bdaddr_t * src )
{
struct sock * sk ;
struct hlist_node * node ;
sk_for_each ( sk , node , & l2cap_sk_list . head )
if ( l2cap_pi ( sk ) - > sport = = psm & & ! bacmp ( & bt_sk ( sk ) - > src , src ) )
goto found ;
sk = NULL ;
found :
return sk ;
}
static int l2cap_sock_bind ( struct socket * sock , struct sockaddr * addr , int alen )
{
struct sock * sk = sock - > sk ;
struct sockaddr_l2 la ;
int len , err = 0 ;
BT_DBG ( " sk %p " , sk ) ;
if ( ! addr | | addr - > sa_family ! = AF_BLUETOOTH )
return - EINVAL ;
memset ( & la , 0 , sizeof ( la ) ) ;
len = min_t ( unsigned int , sizeof ( la ) , alen ) ;
memcpy ( & la , addr , len ) ;
2011-02-11 04:38:50 +03:00
if ( la . l2_cid & & la . l2_psm )
2011-02-04 07:40:28 +03:00
return - EINVAL ;
lock_sock ( sk ) ;
if ( sk - > sk_state ! = BT_OPEN ) {
err = - EBADFD ;
goto done ;
}
if ( la . l2_psm ) {
__u16 psm = __le16_to_cpu ( la . l2_psm ) ;
/* PSM must be odd and lsb of upper byte must be 0 */
if ( ( psm & 0x0101 ) ! = 0x0001 ) {
err = - EINVAL ;
goto done ;
}
/* Restrict usage of well-known PSMs */
if ( psm < 0x1001 & & ! capable ( CAP_NET_BIND_SERVICE ) ) {
err = - EACCES ;
goto done ;
}
}
write_lock_bh ( & l2cap_sk_list . lock ) ;
if ( la . l2_psm & & __l2cap_get_sock_by_addr ( la . l2_psm , & la . l2_bdaddr ) ) {
err = - EADDRINUSE ;
} else {
/* Save source address */
bacpy ( & bt_sk ( sk ) - > src , & la . l2_bdaddr ) ;
l2cap_pi ( sk ) - > psm = la . l2_psm ;
l2cap_pi ( sk ) - > sport = la . l2_psm ;
sk - > sk_state = BT_BOUND ;
if ( __le16_to_cpu ( la . l2_psm ) = = 0x0001 | |
__le16_to_cpu ( la . l2_psm ) = = 0x0003 )
l2cap_pi ( sk ) - > sec_level = BT_SECURITY_SDP ;
}
2011-02-11 04:38:50 +03:00
if ( la . l2_cid )
l2cap_pi ( sk ) - > scid = la . l2_cid ;
2011-02-04 07:40:28 +03:00
write_unlock_bh ( & l2cap_sk_list . lock ) ;
done :
release_sock ( sk ) ;
return err ;
}
2011-02-04 07:56:13 +03:00
static int l2cap_sock_connect ( struct socket * sock , struct sockaddr * addr , int alen , int flags )
{
struct sock * sk = sock - > sk ;
struct sockaddr_l2 la ;
int len , err = 0 ;
BT_DBG ( " sk %p " , sk ) ;
if ( ! addr | | alen < sizeof ( addr - > sa_family ) | |
addr - > sa_family ! = AF_BLUETOOTH )
return - EINVAL ;
memset ( & la , 0 , sizeof ( la ) ) ;
len = min_t ( unsigned int , sizeof ( la ) , alen ) ;
memcpy ( & la , addr , len ) ;
2011-02-11 04:38:49 +03:00
if ( la . l2_cid & & la . l2_psm )
2011-02-04 07:56:13 +03:00
return - EINVAL ;
lock_sock ( sk ) ;
if ( ( sk - > sk_type = = SOCK_SEQPACKET | | sk - > sk_type = = SOCK_STREAM )
2011-02-11 04:38:49 +03:00
& & ! ( la . l2_psm | | la . l2_cid ) ) {
2011-02-04 07:56:13 +03:00
err = - EINVAL ;
goto done ;
}
switch ( l2cap_pi ( sk ) - > mode ) {
case L2CAP_MODE_BASIC :
break ;
case L2CAP_MODE_ERTM :
case L2CAP_MODE_STREAMING :
if ( ! disable_ertm )
break ;
/* fall through */
default :
err = - ENOTSUPP ;
goto done ;
}
switch ( sk - > sk_state ) {
case BT_CONNECT :
case BT_CONNECT2 :
case BT_CONFIG :
/* Already connecting */
goto wait ;
case BT_CONNECTED :
/* Already connected */
err = - EISCONN ;
goto done ;
case BT_OPEN :
case BT_BOUND :
/* Can connect */
break ;
default :
err = - EBADFD ;
goto done ;
}
/* PSM must be odd and lsb of upper byte must be 0 */
if ( ( __le16_to_cpu ( la . l2_psm ) & 0x0101 ) ! = 0x0001 & &
2011-02-11 04:38:49 +03:00
sk - > sk_type ! = SOCK_RAW & & ! la . l2_cid ) {
2011-02-04 07:56:13 +03:00
err = - EINVAL ;
goto done ;
}
/* Set destination address and psm */
bacpy ( & bt_sk ( sk ) - > dst , & la . l2_bdaddr ) ;
l2cap_pi ( sk ) - > psm = la . l2_psm ;
2011-02-11 04:38:49 +03:00
l2cap_pi ( sk ) - > dcid = la . l2_cid ;
2011-02-04 07:56:13 +03:00
err = l2cap_do_connect ( sk ) ;
if ( err )
goto done ;
wait :
err = bt_sock_wait_state ( sk , BT_CONNECTED ,
sock_sndtimeo ( sk , flags & O_NONBLOCK ) ) ;
done :
release_sock ( sk ) ;
return err ;
}
2011-02-04 07:40:28 +03:00
static int l2cap_sock_listen ( struct socket * sock , int backlog )
{
struct sock * sk = sock - > sk ;
int err = 0 ;
BT_DBG ( " sk %p backlog %d " , sk , backlog ) ;
lock_sock ( sk ) ;
if ( ( sock - > type ! = SOCK_SEQPACKET & & sock - > type ! = SOCK_STREAM )
| | sk - > sk_state ! = BT_BOUND ) {
err = - EBADFD ;
goto done ;
}
switch ( l2cap_pi ( sk ) - > mode ) {
case L2CAP_MODE_BASIC :
break ;
case L2CAP_MODE_ERTM :
case L2CAP_MODE_STREAMING :
if ( ! disable_ertm )
break ;
/* fall through */
default :
err = - ENOTSUPP ;
goto done ;
}
2011-02-11 04:38:50 +03:00
if ( ! l2cap_pi ( sk ) - > psm & & ! l2cap_pi ( sk ) - > dcid ) {
2011-02-04 07:40:28 +03:00
bdaddr_t * src = & bt_sk ( sk ) - > src ;
u16 psm ;
err = - EINVAL ;
write_lock_bh ( & l2cap_sk_list . lock ) ;
for ( psm = 0x1001 ; psm < 0x1100 ; psm + = 2 )
if ( ! __l2cap_get_sock_by_addr ( cpu_to_le16 ( psm ) , src ) ) {
l2cap_pi ( sk ) - > psm = cpu_to_le16 ( psm ) ;
l2cap_pi ( sk ) - > sport = cpu_to_le16 ( psm ) ;
err = 0 ;
break ;
}
write_unlock_bh ( & l2cap_sk_list . lock ) ;
if ( err < 0 )
goto done ;
}
sk - > sk_max_ack_backlog = backlog ;
sk - > sk_ack_backlog = 0 ;
sk - > sk_state = BT_LISTEN ;
done :
release_sock ( sk ) ;
return err ;
}
2011-02-04 07:42:23 +03:00
static int l2cap_sock_accept ( struct socket * sock , struct socket * newsock , int flags )
{
DECLARE_WAITQUEUE ( wait , current ) ;
struct sock * sk = sock - > sk , * nsk ;
long timeo ;
int err = 0 ;
lock_sock_nested ( sk , SINGLE_DEPTH_NESTING ) ;
if ( sk - > sk_state ! = BT_LISTEN ) {
err = - EBADFD ;
goto done ;
}
timeo = sock_rcvtimeo ( sk , flags & O_NONBLOCK ) ;
BT_DBG ( " sk %p timeo %ld " , sk , timeo ) ;
/* Wait for an incoming connection. (wake-one). */
add_wait_queue_exclusive ( sk_sleep ( sk ) , & wait ) ;
while ( ! ( nsk = bt_accept_dequeue ( sk , newsock ) ) ) {
set_current_state ( TASK_INTERRUPTIBLE ) ;
if ( ! timeo ) {
err = - EAGAIN ;
break ;
}
release_sock ( sk ) ;
timeo = schedule_timeout ( timeo ) ;
lock_sock_nested ( sk , SINGLE_DEPTH_NESTING ) ;
if ( sk - > sk_state ! = BT_LISTEN ) {
err = - EBADFD ;
break ;
}
if ( signal_pending ( current ) ) {
err = sock_intr_errno ( timeo ) ;
break ;
}
}
set_current_state ( TASK_RUNNING ) ;
remove_wait_queue ( sk_sleep ( sk ) , & wait ) ;
if ( err )
goto done ;
newsock - > state = SS_CONNECTED ;
BT_DBG ( " new socket %p " , nsk ) ;
done :
release_sock ( sk ) ;
return err ;
}
2011-02-04 07:43:46 +03:00
static int l2cap_sock_getname ( struct socket * sock , struct sockaddr * addr , int * len , int peer )
{
struct sockaddr_l2 * la = ( struct sockaddr_l2 * ) addr ;
struct sock * sk = sock - > sk ;
BT_DBG ( " sock %p, sk %p " , sock , sk ) ;
addr - > sa_family = AF_BLUETOOTH ;
* len = sizeof ( struct sockaddr_l2 ) ;
if ( peer ) {
la - > l2_psm = l2cap_pi ( sk ) - > psm ;
bacpy ( & la - > l2_bdaddr , & bt_sk ( sk ) - > dst ) ;
la - > l2_cid = cpu_to_le16 ( l2cap_pi ( sk ) - > dcid ) ;
} else {
la - > l2_psm = l2cap_pi ( sk ) - > sport ;
bacpy ( & la - > l2_bdaddr , & bt_sk ( sk ) - > src ) ;
la - > l2_cid = cpu_to_le16 ( l2cap_pi ( sk ) - > scid ) ;
}
return 0 ;
}
2011-02-04 07:52:55 +03:00
static int l2cap_sock_getsockopt_old ( struct socket * sock , int optname , char __user * optval , int __user * optlen )
{
struct sock * sk = sock - > sk ;
struct l2cap_options opts ;
struct l2cap_conninfo cinfo ;
int len , err = 0 ;
u32 opt ;
BT_DBG ( " sk %p " , sk ) ;
if ( get_user ( len , optlen ) )
return - EFAULT ;
lock_sock ( sk ) ;
switch ( optname ) {
case L2CAP_OPTIONS :
2011-02-10 20:59:42 +03:00
memset ( & opts , 0 , sizeof ( opts ) ) ;
2011-02-04 07:52:55 +03:00
opts . imtu = l2cap_pi ( sk ) - > imtu ;
opts . omtu = l2cap_pi ( sk ) - > omtu ;
opts . flush_to = l2cap_pi ( sk ) - > flush_to ;
opts . mode = l2cap_pi ( sk ) - > mode ;
opts . fcs = l2cap_pi ( sk ) - > fcs ;
opts . max_tx = l2cap_pi ( sk ) - > max_tx ;
opts . txwin_size = ( __u16 ) l2cap_pi ( sk ) - > tx_win ;
len = min_t ( unsigned int , len , sizeof ( opts ) ) ;
if ( copy_to_user ( optval , ( char * ) & opts , len ) )
err = - EFAULT ;
break ;
case L2CAP_LM :
switch ( l2cap_pi ( sk ) - > sec_level ) {
case BT_SECURITY_LOW :
opt = L2CAP_LM_AUTH ;
break ;
case BT_SECURITY_MEDIUM :
opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT ;
break ;
case BT_SECURITY_HIGH :
opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT |
L2CAP_LM_SECURE ;
break ;
default :
opt = 0 ;
break ;
}
if ( l2cap_pi ( sk ) - > role_switch )
opt | = L2CAP_LM_MASTER ;
if ( l2cap_pi ( sk ) - > force_reliable )
opt | = L2CAP_LM_RELIABLE ;
if ( put_user ( opt , ( u32 __user * ) optval ) )
err = - EFAULT ;
break ;
case L2CAP_CONNINFO :
if ( sk - > sk_state ! = BT_CONNECTED & &
! ( sk - > sk_state = = BT_CONNECT2 & &
bt_sk ( sk ) - > defer_setup ) ) {
err = - ENOTCONN ;
break ;
}
cinfo . hci_handle = l2cap_pi ( sk ) - > conn - > hcon - > handle ;
memcpy ( cinfo . dev_class , l2cap_pi ( sk ) - > conn - > hcon - > dev_class , 3 ) ;
len = min_t ( unsigned int , len , sizeof ( cinfo ) ) ;
if ( copy_to_user ( optval , ( char * ) & cinfo , len ) )
err = - EFAULT ;
break ;
default :
err = - ENOPROTOOPT ;
break ;
}
release_sock ( sk ) ;
return err ;
}
static int l2cap_sock_getsockopt ( struct socket * sock , int level , int optname , char __user * optval , int __user * optlen )
{
struct sock * sk = sock - > sk ;
struct bt_security sec ;
int len , err = 0 ;
BT_DBG ( " sk %p " , sk ) ;
if ( level = = SOL_L2CAP )
return l2cap_sock_getsockopt_old ( sock , optname , optval , optlen ) ;
if ( level ! = SOL_BLUETOOTH )
return - ENOPROTOOPT ;
if ( get_user ( len , optlen ) )
return - EFAULT ;
lock_sock ( sk ) ;
switch ( optname ) {
case BT_SECURITY :
if ( sk - > sk_type ! = SOCK_SEQPACKET & & sk - > sk_type ! = SOCK_STREAM
& & sk - > sk_type ! = SOCK_RAW ) {
err = - EINVAL ;
break ;
}
sec . level = l2cap_pi ( sk ) - > sec_level ;
len = min_t ( unsigned int , len , sizeof ( sec ) ) ;
if ( copy_to_user ( optval , ( char * ) & sec , len ) )
err = - EFAULT ;
break ;
case BT_DEFER_SETUP :
if ( sk - > sk_state ! = BT_BOUND & & sk - > sk_state ! = BT_LISTEN ) {
err = - EINVAL ;
break ;
}
if ( put_user ( bt_sk ( sk ) - > defer_setup , ( u32 __user * ) optval ) )
err = - EFAULT ;
break ;
case BT_FLUSHABLE :
if ( put_user ( l2cap_pi ( sk ) - > flushable , ( u32 __user * ) optval ) )
err = - EFAULT ;
break ;
default :
err = - ENOPROTOOPT ;
break ;
}
release_sock ( sk ) ;
return err ;
}
2011-02-04 07:48:48 +03:00
static int l2cap_sock_setsockopt_old ( struct socket * sock , int optname , char __user * optval , unsigned int optlen )
{
struct sock * sk = sock - > sk ;
struct l2cap_options opts ;
int len , err = 0 ;
u32 opt ;
BT_DBG ( " sk %p " , sk ) ;
lock_sock ( sk ) ;
switch ( optname ) {
case L2CAP_OPTIONS :
if ( sk - > sk_state = = BT_CONNECTED ) {
err = - EINVAL ;
break ;
}
opts . imtu = l2cap_pi ( sk ) - > imtu ;
opts . omtu = l2cap_pi ( sk ) - > omtu ;
opts . flush_to = l2cap_pi ( sk ) - > flush_to ;
opts . mode = l2cap_pi ( sk ) - > mode ;
opts . fcs = l2cap_pi ( sk ) - > fcs ;
opts . max_tx = l2cap_pi ( sk ) - > max_tx ;
opts . txwin_size = ( __u16 ) l2cap_pi ( sk ) - > tx_win ;
len = min_t ( unsigned int , sizeof ( opts ) , optlen ) ;
if ( copy_from_user ( ( char * ) & opts , optval , len ) ) {
err = - EFAULT ;
break ;
}
if ( opts . txwin_size > L2CAP_DEFAULT_TX_WINDOW ) {
err = - EINVAL ;
break ;
}
l2cap_pi ( sk ) - > mode = opts . mode ;
switch ( l2cap_pi ( sk ) - > mode ) {
case L2CAP_MODE_BASIC :
l2cap_pi ( sk ) - > conf_state & = ~ L2CAP_CONF_STATE2_DEVICE ;
break ;
case L2CAP_MODE_ERTM :
case L2CAP_MODE_STREAMING :
if ( ! disable_ertm )
break ;
/* fall through */
default :
err = - EINVAL ;
break ;
}
l2cap_pi ( sk ) - > imtu = opts . imtu ;
l2cap_pi ( sk ) - > omtu = opts . omtu ;
l2cap_pi ( sk ) - > fcs = opts . fcs ;
l2cap_pi ( sk ) - > max_tx = opts . max_tx ;
l2cap_pi ( sk ) - > tx_win = ( __u8 ) opts . txwin_size ;
break ;
case L2CAP_LM :
if ( get_user ( opt , ( u32 __user * ) optval ) ) {
err = - EFAULT ;
break ;
}
if ( opt & L2CAP_LM_AUTH )
l2cap_pi ( sk ) - > sec_level = BT_SECURITY_LOW ;
if ( opt & L2CAP_LM_ENCRYPT )
l2cap_pi ( sk ) - > sec_level = BT_SECURITY_MEDIUM ;
if ( opt & L2CAP_LM_SECURE )
l2cap_pi ( sk ) - > sec_level = BT_SECURITY_HIGH ;
l2cap_pi ( sk ) - > role_switch = ( opt & L2CAP_LM_MASTER ) ;
l2cap_pi ( sk ) - > force_reliable = ( opt & L2CAP_LM_RELIABLE ) ;
break ;
default :
err = - ENOPROTOOPT ;
break ;
}
release_sock ( sk ) ;
return err ;
}
static int l2cap_sock_setsockopt ( struct socket * sock , int level , int optname , char __user * optval , unsigned int optlen )
{
struct sock * sk = sock - > sk ;
struct bt_security sec ;
int len , err = 0 ;
u32 opt ;
BT_DBG ( " sk %p " , sk ) ;
if ( level = = SOL_L2CAP )
return l2cap_sock_setsockopt_old ( sock , optname , optval , optlen ) ;
if ( level ! = SOL_BLUETOOTH )
return - ENOPROTOOPT ;
lock_sock ( sk ) ;
switch ( optname ) {
case BT_SECURITY :
if ( sk - > sk_type ! = SOCK_SEQPACKET & & sk - > sk_type ! = SOCK_STREAM
& & sk - > sk_type ! = SOCK_RAW ) {
err = - EINVAL ;
break ;
}
sec . level = BT_SECURITY_LOW ;
len = min_t ( unsigned int , sizeof ( sec ) , optlen ) ;
if ( copy_from_user ( ( char * ) & sec , optval , len ) ) {
err = - EFAULT ;
break ;
}
if ( sec . level < BT_SECURITY_LOW | |
sec . level > BT_SECURITY_HIGH ) {
err = - EINVAL ;
break ;
}
l2cap_pi ( sk ) - > sec_level = sec . level ;
break ;
case BT_DEFER_SETUP :
if ( sk - > sk_state ! = BT_BOUND & & sk - > sk_state ! = BT_LISTEN ) {
err = - EINVAL ;
break ;
}
if ( get_user ( opt , ( u32 __user * ) optval ) ) {
err = - EFAULT ;
break ;
}
bt_sk ( sk ) - > defer_setup = opt ;
break ;
case BT_FLUSHABLE :
if ( get_user ( opt , ( u32 __user * ) optval ) ) {
err = - EFAULT ;
break ;
}
if ( opt > BT_FLUSHABLE_ON ) {
err = - EINVAL ;
break ;
}
if ( opt = = BT_FLUSHABLE_OFF ) {
struct l2cap_conn * conn = l2cap_pi ( sk ) - > conn ;
/* proceed futher only when we have l2cap_conn and
No Flush support in the LM */
if ( ! conn | | ! lmp_no_flush_capable ( conn - > hcon - > hdev ) ) {
err = - EINVAL ;
break ;
}
}
l2cap_pi ( sk ) - > flushable = opt ;
break ;
default :
err = - ENOPROTOOPT ;
break ;
}
release_sock ( sk ) ;
return err ;
}
2011-02-04 08:20:52 +03:00
static int l2cap_sock_sendmsg ( struct kiocb * iocb , struct socket * sock , struct msghdr * msg , size_t len )
{
struct sock * sk = sock - > sk ;
struct l2cap_pinfo * pi = l2cap_pi ( sk ) ;
struct sk_buff * skb ;
u16 control ;
int err ;
BT_DBG ( " sock %p, sk %p " , sock , sk ) ;
err = sock_error ( sk ) ;
if ( err )
return err ;
if ( msg - > msg_flags & MSG_OOB )
return - EOPNOTSUPP ;
lock_sock ( sk ) ;
if ( sk - > sk_state ! = BT_CONNECTED ) {
err = - ENOTCONN ;
goto done ;
}
/* Connectionless channel */
if ( sk - > sk_type = = SOCK_DGRAM ) {
skb = l2cap_create_connless_pdu ( sk , msg , len ) ;
if ( IS_ERR ( skb ) ) {
err = PTR_ERR ( skb ) ;
} else {
l2cap_do_send ( sk , skb ) ;
err = len ;
}
goto done ;
}
switch ( pi - > mode ) {
case L2CAP_MODE_BASIC :
/* Check outgoing MTU */
if ( len > pi - > omtu ) {
err = - EMSGSIZE ;
goto done ;
}
/* Create a basic PDU */
skb = l2cap_create_basic_pdu ( sk , msg , len ) ;
if ( IS_ERR ( skb ) ) {
err = PTR_ERR ( skb ) ;
goto done ;
}
l2cap_do_send ( sk , skb ) ;
err = len ;
break ;
case L2CAP_MODE_ERTM :
case L2CAP_MODE_STREAMING :
/* Entire SDU fits into one PDU */
if ( len < = pi - > remote_mps ) {
control = L2CAP_SDU_UNSEGMENTED ;
skb = l2cap_create_iframe_pdu ( sk , msg , len , control , 0 ) ;
if ( IS_ERR ( skb ) ) {
err = PTR_ERR ( skb ) ;
goto done ;
}
__skb_queue_tail ( TX_QUEUE ( sk ) , skb ) ;
if ( sk - > sk_send_head = = NULL )
sk - > sk_send_head = skb ;
} else {
/* Segment SDU into multiples PDUs */
err = l2cap_sar_segment_sdu ( sk , msg , len ) ;
if ( err < 0 )
goto done ;
}
if ( pi - > mode = = L2CAP_MODE_STREAMING ) {
l2cap_streaming_send ( sk ) ;
} else {
if ( ( pi - > conn_state & L2CAP_CONN_REMOTE_BUSY ) & &
( pi - > conn_state & L2CAP_CONN_WAIT_F ) ) {
err = len ;
break ;
}
err = l2cap_ertm_send ( sk ) ;
}
if ( err > = 0 )
err = len ;
break ;
default :
BT_DBG ( " bad state %1.1x " , pi - > mode ) ;
err = - EBADFD ;
}
done :
release_sock ( sk ) ;
return err ;
}
2011-02-04 07:48:48 +03:00
2011-02-04 08:02:31 +03:00
static int l2cap_sock_recvmsg ( struct kiocb * iocb , struct socket * sock , struct msghdr * msg , size_t len , int flags )
{
struct sock * sk = sock - > sk ;
lock_sock ( sk ) ;
if ( sk - > sk_state = = BT_CONNECT2 & & bt_sk ( sk ) - > defer_setup ) {
struct l2cap_conn_rsp rsp ;
struct l2cap_conn * conn = l2cap_pi ( sk ) - > conn ;
u8 buf [ 128 ] ;
sk - > sk_state = BT_CONFIG ;
rsp . scid = cpu_to_le16 ( l2cap_pi ( sk ) - > dcid ) ;
rsp . dcid = cpu_to_le16 ( l2cap_pi ( sk ) - > scid ) ;
rsp . result = cpu_to_le16 ( L2CAP_CR_SUCCESS ) ;
rsp . status = cpu_to_le16 ( L2CAP_CS_NO_INFO ) ;
l2cap_send_cmd ( l2cap_pi ( sk ) - > conn , l2cap_pi ( sk ) - > ident ,
L2CAP_CONN_RSP , sizeof ( rsp ) , & rsp ) ;
if ( l2cap_pi ( sk ) - > conf_state & L2CAP_CONF_REQ_SENT ) {
release_sock ( sk ) ;
return 0 ;
}
l2cap_pi ( sk ) - > conf_state | = L2CAP_CONF_REQ_SENT ;
l2cap_send_cmd ( conn , l2cap_get_ident ( conn ) , L2CAP_CONF_REQ ,
l2cap_build_conf_req ( sk , buf ) , buf ) ;
l2cap_pi ( sk ) - > num_conf_req + + ;
release_sock ( sk ) ;
return 0 ;
}
release_sock ( sk ) ;
if ( sock - > type = = SOCK_STREAM )
return bt_sock_stream_recvmsg ( iocb , sock , msg , len , flags ) ;
return bt_sock_recvmsg ( iocb , sock , msg , len , flags ) ;
}
2011-02-04 08:26:01 +03:00
/* Kill socket (only if zapped and orphan)
* Must be called on unlocked socket .
*/
void l2cap_sock_kill ( struct sock * sk )
{
if ( ! sock_flag ( sk , SOCK_ZAPPED ) | | sk - > sk_socket )
return ;
BT_DBG ( " sk %p state %d " , sk , sk - > sk_state ) ;
/* Kill poor orphan */
bt_sock_unlink ( & l2cap_sk_list , sk ) ;
sock_set_flag ( sk , SOCK_DEAD ) ;
sock_put ( sk ) ;
}
2011-02-04 08:35:20 +03:00
/* Must be called on unlocked socket. */
static void l2cap_sock_close ( struct sock * sk )
{
l2cap_sock_clear_timer ( sk ) ;
lock_sock ( sk ) ;
__l2cap_sock_close ( sk , ECONNRESET ) ;
release_sock ( sk ) ;
l2cap_sock_kill ( sk ) ;
}
static void l2cap_sock_cleanup_listen ( struct sock * parent )
{
struct sock * sk ;
BT_DBG ( " parent %p " , parent ) ;
/* Close not yet accepted channels */
while ( ( sk = bt_accept_dequeue ( parent , NULL ) ) )
l2cap_sock_close ( sk ) ;
parent - > sk_state = BT_CLOSED ;
sock_set_flag ( parent , SOCK_ZAPPED ) ;
}
void __l2cap_sock_close ( struct sock * sk , int reason )
{
2011-02-11 04:38:51 +03:00
struct l2cap_conn * conn = l2cap_pi ( sk ) - > conn ;
2011-02-04 08:35:20 +03:00
BT_DBG ( " sk %p state %d socket %p " , sk , sk - > sk_state , sk - > sk_socket ) ;
switch ( sk - > sk_state ) {
case BT_LISTEN :
l2cap_sock_cleanup_listen ( sk ) ;
break ;
case BT_CONNECTED :
case BT_CONFIG :
2011-02-11 04:38:51 +03:00
if ( ( sk - > sk_type = = SOCK_SEQPACKET | |
sk - > sk_type = = SOCK_STREAM ) & &
conn - > hcon - > type = = ACL_LINK ) {
2011-02-04 08:35:20 +03:00
l2cap_sock_set_timer ( sk , sk - > sk_sndtimeo ) ;
l2cap_send_disconn_req ( conn , sk , reason ) ;
} else
l2cap_chan_del ( sk , reason ) ;
break ;
case BT_CONNECT2 :
2011-02-11 04:38:51 +03:00
if ( ( sk - > sk_type = = SOCK_SEQPACKET | |
sk - > sk_type = = SOCK_STREAM ) & &
conn - > hcon - > type = = ACL_LINK ) {
2011-02-04 08:35:20 +03:00
struct l2cap_conn_rsp rsp ;
__u16 result ;
if ( bt_sk ( sk ) - > defer_setup )
result = L2CAP_CR_SEC_BLOCK ;
else
result = L2CAP_CR_BAD_PSM ;
rsp . scid = cpu_to_le16 ( l2cap_pi ( sk ) - > dcid ) ;
rsp . dcid = cpu_to_le16 ( l2cap_pi ( sk ) - > scid ) ;
rsp . result = cpu_to_le16 ( result ) ;
rsp . status = cpu_to_le16 ( L2CAP_CS_NO_INFO ) ;
l2cap_send_cmd ( conn , l2cap_pi ( sk ) - > ident ,
L2CAP_CONN_RSP , sizeof ( rsp ) , & rsp ) ;
} else
l2cap_chan_del ( sk , reason ) ;
break ;
case BT_CONNECT :
case BT_DISCONN :
l2cap_chan_del ( sk , reason ) ;
break ;
default :
sock_set_flag ( sk , SOCK_ZAPPED ) ;
break ;
}
}
2011-02-04 08:08:36 +03:00
static int l2cap_sock_shutdown ( struct socket * sock , int how )
{
struct sock * sk = sock - > sk ;
int err = 0 ;
BT_DBG ( " sock %p, sk %p " , sock , sk ) ;
if ( ! sk )
return 0 ;
lock_sock ( sk ) ;
if ( ! sk - > sk_shutdown ) {
if ( l2cap_pi ( sk ) - > mode = = L2CAP_MODE_ERTM )
err = __l2cap_wait_ack ( sk ) ;
sk - > sk_shutdown = SHUTDOWN_MASK ;
l2cap_sock_clear_timer ( sk ) ;
__l2cap_sock_close ( sk , 0 ) ;
if ( sock_flag ( sk , SOCK_LINGER ) & & sk - > sk_lingertime )
err = bt_sock_wait_state ( sk , BT_CLOSED ,
sk - > sk_lingertime ) ;
}
if ( ! err & & sk - > sk_err )
err = - sk - > sk_err ;
release_sock ( sk ) ;
return err ;
}
2011-02-04 07:36:42 +03:00
static int l2cap_sock_release ( struct socket * sock )
{
struct sock * sk = sock - > sk ;
int err ;
BT_DBG ( " sock %p, sk %p " , sock , sk ) ;
if ( ! sk )
return 0 ;
err = l2cap_sock_shutdown ( sock , 2 ) ;
sock_orphan ( sk ) ;
l2cap_sock_kill ( sk ) ;
return err ;
}
2011-02-04 01:50:35 +03:00
static void l2cap_sock_destruct ( struct sock * sk )
{
BT_DBG ( " sk %p " , sk ) ;
skb_queue_purge ( & sk - > sk_receive_queue ) ;
skb_queue_purge ( & sk - > sk_write_queue ) ;
}
void l2cap_sock_init ( struct sock * sk , struct sock * parent )
{
struct l2cap_pinfo * pi = l2cap_pi ( sk ) ;
BT_DBG ( " sk %p " , sk ) ;
if ( parent ) {
sk - > sk_type = parent - > sk_type ;
bt_sk ( sk ) - > defer_setup = bt_sk ( parent ) - > defer_setup ;
pi - > imtu = l2cap_pi ( parent ) - > imtu ;
pi - > omtu = l2cap_pi ( parent ) - > omtu ;
pi - > conf_state = l2cap_pi ( parent ) - > conf_state ;
pi - > mode = l2cap_pi ( parent ) - > mode ;
pi - > fcs = l2cap_pi ( parent ) - > fcs ;
pi - > max_tx = l2cap_pi ( parent ) - > max_tx ;
pi - > tx_win = l2cap_pi ( parent ) - > tx_win ;
pi - > sec_level = l2cap_pi ( parent ) - > sec_level ;
pi - > role_switch = l2cap_pi ( parent ) - > role_switch ;
pi - > force_reliable = l2cap_pi ( parent ) - > force_reliable ;
pi - > flushable = l2cap_pi ( parent ) - > flushable ;
} else {
pi - > imtu = L2CAP_DEFAULT_MTU ;
pi - > omtu = 0 ;
if ( ! disable_ertm & & sk - > sk_type = = SOCK_STREAM ) {
pi - > mode = L2CAP_MODE_ERTM ;
pi - > conf_state | = L2CAP_CONF_STATE2_DEVICE ;
} else {
pi - > mode = L2CAP_MODE_BASIC ;
}
pi - > max_tx = L2CAP_DEFAULT_MAX_TX ;
pi - > fcs = L2CAP_FCS_CRC16 ;
pi - > tx_win = L2CAP_DEFAULT_TX_WINDOW ;
pi - > sec_level = BT_SECURITY_LOW ;
pi - > role_switch = 0 ;
pi - > force_reliable = 0 ;
pi - > flushable = BT_FLUSHABLE_OFF ;
}
/* Default config options */
pi - > conf_len = 0 ;
pi - > flush_to = L2CAP_DEFAULT_FLUSH_TO ;
skb_queue_head_init ( TX_QUEUE ( sk ) ) ;
skb_queue_head_init ( SREJ_QUEUE ( sk ) ) ;
skb_queue_head_init ( BUSY_QUEUE ( sk ) ) ;
INIT_LIST_HEAD ( SREJ_LIST ( sk ) ) ;
}
static struct proto l2cap_proto = {
. name = " L2CAP " ,
. owner = THIS_MODULE ,
. obj_size = sizeof ( struct l2cap_pinfo )
} ;
struct sock * l2cap_sock_alloc ( struct net * net , struct socket * sock , int proto , gfp_t prio )
{
struct sock * sk ;
sk = sk_alloc ( net , PF_BLUETOOTH , prio , & l2cap_proto ) ;
if ( ! sk )
return NULL ;
sock_init_data ( sock , sk ) ;
INIT_LIST_HEAD ( & bt_sk ( sk ) - > accept_q ) ;
sk - > sk_destruct = l2cap_sock_destruct ;
sk - > sk_sndtimeo = msecs_to_jiffies ( L2CAP_CONN_TIMEOUT ) ;
sock_reset_flag ( sk , SOCK_ZAPPED ) ;
sk - > sk_protocol = proto ;
sk - > sk_state = BT_OPEN ;
setup_timer ( & sk - > sk_timer , l2cap_sock_timeout , ( unsigned long ) sk ) ;
bt_sock_link ( & l2cap_sk_list , sk ) ;
return sk ;
}
static int l2cap_sock_create ( struct net * net , struct socket * sock , int protocol ,
int kern )
{
struct sock * sk ;
BT_DBG ( " sock %p " , sock ) ;
sock - > state = SS_UNCONNECTED ;
if ( sock - > type ! = SOCK_SEQPACKET & & sock - > type ! = SOCK_STREAM & &
sock - > type ! = SOCK_DGRAM & & sock - > type ! = SOCK_RAW )
return - ESOCKTNOSUPPORT ;
if ( sock - > type = = SOCK_RAW & & ! kern & & ! capable ( CAP_NET_RAW ) )
return - EPERM ;
sock - > ops = & l2cap_sock_ops ;
sk = l2cap_sock_alloc ( net , sock , protocol , GFP_ATOMIC ) ;
if ( ! sk )
return - ENOMEM ;
l2cap_sock_init ( sk , NULL ) ;
return 0 ;
}
2011-02-04 07:33:56 +03:00
const struct proto_ops l2cap_sock_ops = {
. family = PF_BLUETOOTH ,
. owner = THIS_MODULE ,
. release = l2cap_sock_release ,
. bind = l2cap_sock_bind ,
. connect = l2cap_sock_connect ,
. listen = l2cap_sock_listen ,
. accept = l2cap_sock_accept ,
. getname = l2cap_sock_getname ,
. sendmsg = l2cap_sock_sendmsg ,
. recvmsg = l2cap_sock_recvmsg ,
. poll = bt_sock_poll ,
. ioctl = bt_sock_ioctl ,
. mmap = sock_no_mmap ,
. socketpair = sock_no_socketpair ,
. shutdown = l2cap_sock_shutdown ,
. setsockopt = l2cap_sock_setsockopt ,
. getsockopt = l2cap_sock_getsockopt
} ;
2011-02-04 01:50:35 +03:00
static const struct net_proto_family l2cap_sock_family_ops = {
. family = PF_BLUETOOTH ,
. owner = THIS_MODULE ,
. create = l2cap_sock_create ,
} ;
int __init l2cap_init_sockets ( void )
{
2011-02-18 01:16:55 +03:00
int err ;
2011-02-04 01:50:35 +03:00
2011-02-18 01:16:55 +03:00
err = proto_register ( & l2cap_proto , 0 ) ;
if ( err < 0 )
return err ;
2011-02-04 01:50:35 +03:00
2011-02-18 01:16:55 +03:00
err = bt_sock_register ( BTPROTO_L2CAP , & l2cap_sock_family_ops ) ;
if ( err < 0 )
goto error ;
2011-02-04 01:50:35 +03:00
2011-02-18 01:16:55 +03:00
BT_INFO ( " L2CAP socket layer initialized " ) ;
2011-02-04 01:50:35 +03:00
2011-02-18 01:16:55 +03:00
return 0 ;
2011-02-04 01:50:35 +03:00
error :
2011-02-18 01:16:55 +03:00
BT_ERR ( " L2CAP socket registration failed " ) ;
proto_unregister ( & l2cap_proto ) ;
return err ;
2011-02-04 01:50:35 +03:00
}
void l2cap_cleanup_sockets ( void )
{
2011-02-18 01:16:55 +03:00
if ( bt_sock_unregister ( BTPROTO_L2CAP ) < 0 )
BT_ERR ( " L2CAP socket unregistration failed " ) ;
2011-02-04 01:50:35 +03:00
2011-02-18 01:16:55 +03:00
proto_unregister ( & l2cap_proto ) ;
2011-02-04 01:50:35 +03:00
}