Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
This commit is contained in:
@@ -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);
|
||||
|
Reference in New Issue
Block a user