diff options
Diffstat (limited to 'net/bluetooth/l2cap_sock.c')
| -rw-r--r-- | net/bluetooth/l2cap_sock.c | 89 | 
1 files changed, 58 insertions, 31 deletions
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 083f2bf065d..89f1472939e 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -40,7 +40,8 @@ static struct bt_sock_list l2cap_sk_list = {  static const struct proto_ops l2cap_sock_ops;  static void l2cap_sock_init(struct sock *sk, struct sock *parent); -static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio); +static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, +				     int proto, gfp_t prio);  static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)  { @@ -106,7 +107,8 @@ done:  	return err;  } -static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags) +static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, +			      int alen, int flags)  {  	struct sock *sk = sock->sk;  	struct l2cap_chan *chan = l2cap_pi(sk)->chan; @@ -134,7 +136,7 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al  	lock_sock(sk);  	err = bt_sock_wait_state(sk, BT_CONNECTED, -			sock_sndtimeo(sk, flags & O_NONBLOCK)); +				 sock_sndtimeo(sk, flags & O_NONBLOCK));  	release_sock(sk); @@ -185,7 +187,8 @@ done:  	return err;  } -static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int flags) +static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, +			     int flags)  {  	DECLARE_WAITQUEUE(wait, current);  	struct sock *sk = sock->sk, *nsk; @@ -241,7 +244,8 @@ done:  	return err;  } -static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *len, int peer) +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; @@ -266,7 +270,8 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *l  	return 0;  } -static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __user *optval, int __user *optlen) +static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, +				     char __user *optval, int __user *optlen)  {  	struct sock *sk = sock->sk;  	struct l2cap_chan *chan = l2cap_pi(sk)->chan; @@ -309,7 +314,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us  			break;  		case BT_SECURITY_HIGH:  			opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT | -							L2CAP_LM_SECURE; +			      L2CAP_LM_SECURE;  			break;  		default:  			opt = 0; @@ -353,7 +358,8 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us  	return err;  } -static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen) +static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, +				 char __user *optval, int __user *optlen)  {  	struct sock *sk = sock->sk;  	struct l2cap_chan *chan = l2cap_pi(sk)->chan; @@ -377,19 +383,20 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch  	switch (optname) {  	case BT_SECURITY:  		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED && -					chan->chan_type != L2CAP_CHAN_RAW) { +		    chan->chan_type != L2CAP_CHAN_RAW) {  			err = -EINVAL;  			break;  		}  		memset(&sec, 0, sizeof(sec)); -		if (chan->conn) +		if (chan->conn) {  			sec.level = chan->conn->hcon->sec_level; -		else -			sec.level = chan->sec_level; -		if (sk->sk_state == BT_CONNECTED) -			sec.key_size = chan->conn->hcon->enc_key_size; +			if (sk->sk_state == BT_CONNECTED) +				sec.key_size = chan->conn->hcon->enc_key_size; +		} else { +			sec.level = chan->sec_level; +		}  		len = min_t(unsigned int, len, sizeof(sec));  		if (copy_to_user(optval, (char *) &sec, len)) @@ -411,14 +418,14 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch  	case BT_FLUSHABLE:  		if (put_user(test_bit(FLAG_FLUSHABLE, &chan->flags), -						(u32 __user *) optval)) +			     (u32 __user *) optval))  			err = -EFAULT;  		break;  	case BT_POWER:  		if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM -				&& sk->sk_type != SOCK_RAW) { +		    && sk->sk_type != SOCK_RAW) {  			err = -EINVAL;  			break;  		} @@ -466,7 +473,8 @@ static bool l2cap_valid_mtu(struct l2cap_chan *chan, u16 mtu)  	return true;  } -static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __user *optval, unsigned int optlen) +static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, +				     char __user *optval, unsigned int optlen)  {  	struct sock *sk = sock->sk;  	struct l2cap_chan *chan = l2cap_pi(sk)->chan; @@ -529,6 +537,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us  		chan->fcs  = opts.fcs;  		chan->max_tx = opts.max_tx;  		chan->tx_win = opts.txwin_size; +		chan->flush_to = opts.flush_to;  		break;  	case L2CAP_LM: @@ -564,7 +573,8 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us  	return err;  } -static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen) +static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, +				 char __user *optval, unsigned int optlen)  {  	struct sock *sk = sock->sk;  	struct l2cap_chan *chan = l2cap_pi(sk)->chan; @@ -587,7 +597,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch  	switch (optname) {  	case BT_SECURITY:  		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED && -					chan->chan_type != L2CAP_CHAN_RAW) { +		    chan->chan_type != L2CAP_CHAN_RAW) {  			err = -EINVAL;  			break;  		} @@ -601,7 +611,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch  		}  		if (sec.level < BT_SECURITY_LOW || -					sec.level > BT_SECURITY_HIGH) { +		    sec.level > BT_SECURITY_HIGH) {  			err = -EINVAL;  			break;  		} @@ -627,7 +637,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch  		/* or for ACL link */  		} else if ((sk->sk_state == BT_CONNECT2 && -			   test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) || +			    test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) ||  			   sk->sk_state == BT_CONNECTED) {  			if (!l2cap_chan_check_security(chan))  				set_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags); @@ -684,7 +694,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch  	case BT_POWER:  		if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED && -					chan->chan_type != L2CAP_CHAN_RAW) { +		    chan->chan_type != L2CAP_CHAN_RAW) {  			err = -EINVAL;  			break;  		} @@ -720,7 +730,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch  		}  		if (chan->mode != L2CAP_MODE_ERTM && -				chan->mode != L2CAP_MODE_STREAMING) { +		    chan->mode != L2CAP_MODE_STREAMING) {  			err = -EOPNOTSUPP;  			break;  		} @@ -737,7 +747,8 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch  	return err;  } -static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len) +static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, +			      struct msghdr *msg, size_t len)  {  	struct sock *sk = sock->sk;  	struct l2cap_chan *chan = l2cap_pi(sk)->chan; @@ -762,7 +773,8 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms  	return err;  } -static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len, int flags) +static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, +			      struct msghdr *msg, size_t len, int flags)  {  	struct sock *sk = sock->sk;  	struct l2cap_pinfo *pi = l2cap_pi(sk); @@ -866,7 +878,7 @@ static int l2cap_sock_shutdown(struct socket *sock, int how)  		if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime)  			err = bt_sock_wait_state(sk, BT_CLOSED, -							sk->sk_lingertime); +						 sk->sk_lingertime);  	}  	if (!err && sk->sk_err) @@ -930,7 +942,7 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan)  	}  	sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, -								GFP_ATOMIC); +			      GFP_ATOMIC);  	if (!sk)  		return NULL; @@ -938,6 +950,8 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan)  	l2cap_sock_init(sk, parent); +	bt_accept_enqueue(parent, sk); +  	return l2cap_pi(sk)->chan;  } @@ -1068,6 +1082,15 @@ static void l2cap_sock_ready_cb(struct l2cap_chan *chan)  	release_sock(sk);  } +static void l2cap_sock_defer_cb(struct l2cap_chan *chan) +{ +	struct sock *sk = chan->data; +	struct sock *parent = bt_sk(sk)->parent; + +	if (parent) +		parent->sk_data_ready(parent, 0); +} +  static struct l2cap_ops l2cap_chan_ops = {  	.name		= "L2CAP Socket Interface",  	.new_connection	= l2cap_sock_new_connection_cb, @@ -1076,6 +1099,7 @@ static struct l2cap_ops l2cap_chan_ops = {  	.teardown	= l2cap_sock_teardown_cb,  	.state_change	= l2cap_sock_state_change_cb,  	.ready		= l2cap_sock_ready_cb, +	.defer		= l2cap_sock_defer_cb,  	.alloc_skb	= l2cap_sock_alloc_skb_cb,  }; @@ -1083,7 +1107,8 @@ static void l2cap_sock_destruct(struct sock *sk)  {  	BT_DBG("sk %p", sk); -	l2cap_chan_put(l2cap_pi(sk)->chan); +	if (l2cap_pi(sk)->chan) +		l2cap_chan_put(l2cap_pi(sk)->chan);  	if (l2cap_pi(sk)->rx_busy_skb) {  		kfree_skb(l2cap_pi(sk)->rx_busy_skb);  		l2cap_pi(sk)->rx_busy_skb = NULL; @@ -1159,7 +1184,8 @@ static struct proto l2cap_proto = {  	.obj_size	= sizeof(struct l2cap_pinfo)  }; -static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio) +static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, +				     int proto, gfp_t prio)  {  	struct sock *sk;  	struct l2cap_chan *chan; @@ -1204,7 +1230,7 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol,  	sock->state = SS_UNCONNECTED;  	if (sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM && -			sock->type != SOCK_DGRAM && sock->type != SOCK_RAW) +	    sock->type != SOCK_DGRAM && sock->type != SOCK_RAW)  		return -ESOCKTNOSUPPORT;  	if (sock->type == SOCK_RAW && !kern && !capable(CAP_NET_RAW)) @@ -1261,7 +1287,8 @@ int __init l2cap_init_sockets(void)  		goto error;  	} -	err = bt_procfs_init(THIS_MODULE, &init_net, "l2cap", &l2cap_sk_list, NULL); +	err = bt_procfs_init(THIS_MODULE, &init_net, "l2cap", &l2cap_sk_list, +			     NULL);  	if (err < 0) {  		BT_ERR("Failed to create L2CAP proc file");  		bt_sock_unregister(BTPROTO_L2CAP);  |