Commit 9363d05d authored by Marcel Holtmann's avatar Marcel Holtmann

[Bluetooth] Update socket option handling

This patch unifies the socket option handling across the L2CAP,
SCO and RFCOMM socket layers.
Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
parent 133ffc83
......@@ -38,17 +38,19 @@ struct sockaddr_l2 {
bdaddr_t l2_bdaddr;
};
/* Socket options */
/* L2CAP socket options */
#define L2CAP_OPTIONS 0x01
struct l2cap_options {
__u16 omtu;
__u16 imtu;
__u16 flush_to;
__u8 mode;
};
#define L2CAP_CONNINFO 0x02
#define L2CAP_CONNINFO 0x02
struct l2cap_conninfo {
__u16 hci_handle;
__u8 dev_class[3];
};
#define L2CAP_LM 0x03
......@@ -59,20 +61,6 @@ struct l2cap_conninfo {
#define L2CAP_LM_RELIABLE 0x0010
#define L2CAP_LM_SECURE 0x0020
#define L2CAP_QOS 0x04
struct l2cap_qos {
__u16 service_type;
__u32 token_rate;
__u32 token_bucket_size;
__u32 peak_bandwidth;
__u32 latency;
__u32 delay_variation;
};
#define L2CAP_SERV_NO_TRAFFIC 0x00
#define L2CAP_SERV_BEST_EFFORT 0x01
#define L2CAP_SERV_GUARANTEED 0x02
/* L2CAP command codes */
#define L2CAP_COMMAND_REJ 0x01
#define L2CAP_CONN_REQ 0x02
......@@ -154,6 +142,7 @@ struct l2cap_conf_opt {
#define L2CAP_CONF_MTU 0x01
#define L2CAP_CONF_FLUSH_TO 0x02
#define L2CAP_CONF_QOS 0x03
#define L2CAP_CONF_RFC 0x04
#define L2CAP_CONF_MAX_SIZE 22
......@@ -198,11 +187,11 @@ struct l2cap_conn {
bdaddr_t *dst;
bdaddr_t *src;
unsigned int mtu;
spinlock_t lock;
struct sk_buff *rx_skb;
__u32 rx_len;
__u8 rx_ident;
......@@ -222,7 +211,7 @@ struct l2cap_pinfo {
__u16 imtu;
__u16 omtu;
__u16 flush_to;
__u32 link_mode;
__u8 conf_state;
......
......@@ -181,6 +181,8 @@ struct rfcomm_dlc {
u8 v24_sig;
u8 mscex;
u32 link_mode;
uint mtu;
uint cfc;
uint rx_credits;
......@@ -267,16 +269,31 @@ extern u8 rfcomm_crc_table[];
/* ---- RFCOMM sockets ---- */
struct sockaddr_rc {
sa_family_t rc_family;
bdaddr_t rc_bdaddr;
u8 rc_channel;
sa_family_t rc_family;
bdaddr_t rc_bdaddr;
u8 rc_channel;
};
#define RFCOMM_CONNINFO 0x02
struct rfcomm_conninfo {
__u16 hci_handle;
__u8 dev_class[3];
};
#define RFCOMM_LM 0x03
#define RFCOMM_LM_MASTER 0x0001
#define RFCOMM_LM_AUTH 0x0002
#define RFCOMM_LM_ENCRYPT 0x0004
#define RFCOMM_LM_TRUSTED 0x0008
#define RFCOMM_LM_RELIABLE 0x0010
#define RFCOMM_LM_SECURE 0x0020
#define rfcomm_pi(sk) ((struct rfcomm_pinfo *)sk->sk_protinfo)
struct rfcomm_pinfo {
struct rfcomm_dlc *dlc;
u8 channel;
u32 link_mode;
};
int rfcomm_init_sockets(void);
......
......@@ -39,15 +39,16 @@ struct sockaddr_sco {
bdaddr_t sco_bdaddr;
};
/* set/get sockopt defines */
#define SCO_OPTIONS 0x01
/* SCO socket options */
#define SCO_OPTIONS 0x01
struct sco_options {
__u16 mtu;
};
#define SCO_CONNINFO 0x02
#define SCO_CONNINFO 0x02
struct sco_conninfo {
__u16 hci_handle;
__u8 dev_class[3];
};
/* ---- SCO connections ---- */
......
......@@ -57,7 +57,7 @@
#define BT_DBG(D...)
#endif
#define VERSION "2.6"
#define VERSION "2.7"
static struct proto_ops l2cap_sock_ops;
......@@ -798,7 +798,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
switch (optname) {
case L2CAP_OPTIONS:
len = min_t(unsigned int, sizeof(opts), optlen);
if (copy_from_user((char *)&opts, optval, len)) {
if (copy_from_user((char *) &opts, optval, len)) {
err = -EFAULT;
break;
}
......@@ -807,7 +807,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
break;
case L2CAP_LM:
if (get_user(opt, (u32 __user *)optval)) {
if (get_user(opt, (u32 __user *) optval)) {
err = -EFAULT;
break;
}
......@@ -829,7 +829,9 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
struct sock *sk = sock->sk;
struct l2cap_options opts;
struct l2cap_conninfo cinfo;
int len, err = 0;
int len, err = 0;
BT_DBG("sk %p", sk);
if (get_user(len, optlen))
return -EFAULT;
......@@ -841,15 +843,16 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
opts.imtu = l2cap_pi(sk)->imtu;
opts.omtu = l2cap_pi(sk)->omtu;
opts.flush_to = l2cap_pi(sk)->flush_to;
opts.mode = 0x00;
len = min_t(unsigned int, len, sizeof(opts));
if (copy_to_user(optval, (char *)&opts, len))
if (copy_to_user(optval, (char *) &opts, len))
err = -EFAULT;
break;
case L2CAP_LM:
if (put_user(l2cap_pi(sk)->link_mode, (u32 __user *)optval))
if (put_user(l2cap_pi(sk)->link_mode, (u32 __user *) optval))
err = -EFAULT;
break;
......@@ -860,9 +863,10 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
}
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))
if (copy_to_user(optval, (char *) &cinfo, len))
err = -EFAULT;
break;
......
......@@ -50,7 +50,7 @@
#include <net/bluetooth/l2cap.h>
#include <net/bluetooth/rfcomm.h>
#define VERSION "1.3"
#define VERSION "1.4"
#ifndef CONFIG_BT_RFCOMM_DEBUG
#undef BT_DBG
......
......@@ -51,6 +51,8 @@
#include <asm/uaccess.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
#include <net/bluetooth/l2cap.h>
#include <net/bluetooth/rfcomm.h>
#ifndef CONFIG_BT_RFCOMM_DEBUG
......@@ -261,10 +263,18 @@ static void rfcomm_sock_close(struct sock *sk)
static void rfcomm_sock_init(struct sock *sk, struct sock *parent)
{
struct rfcomm_pinfo *pi = rfcomm_pi(sk);
BT_DBG("sk %p", sk);
if (parent)
if (parent) {
sk->sk_type = parent->sk_type;
pi->link_mode = rfcomm_pi(parent)->link_mode;
} else {
pi->link_mode = 0;
}
pi->dlc->link_mode = pi->link_mode;
}
static struct sock *rfcomm_sock_alloc(struct socket *sock, int proto, int prio)
......@@ -671,12 +681,22 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, c
{
struct sock *sk = sock->sk;
int err = 0;
u32 opt;
BT_DBG("sk %p", sk);
lock_sock(sk);
switch (optname) {
case RFCOMM_LM:
if (get_user(opt, (u32 __user *) optval)) {
err = -EFAULT;
break;
}
rfcomm_pi(sk)->link_mode = opt;
break;
default:
err = -ENOPROTOOPT;
break;
......@@ -689,7 +709,9 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, c
static int rfcomm_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen)
{
struct sock *sk = sock->sk;
int len, err = 0;
struct sock *l2cap_sk;
struct rfcomm_conninfo cinfo;
int len, err = 0;
BT_DBG("sk %p", sk);
......@@ -699,10 +721,32 @@ static int rfcomm_sock_getsockopt(struct socket *sock, int level, int optname, c
lock_sock(sk);
switch (optname) {
case RFCOMM_LM:
if (put_user(rfcomm_pi(sk)->link_mode, (u32 __user *) optval))
err = -EFAULT;
break;
case RFCOMM_CONNINFO:
if (sk->sk_state != BT_CONNECTED) {
err = -ENOTCONN;
break;
}
l2cap_sk = rfcomm_pi(sk)->dlc->session->sock->sk;
cinfo.hci_handle = l2cap_pi(l2cap_sk)->conn->hcon->handle;
memcpy(cinfo.dev_class, l2cap_pi(l2cap_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;
......
......@@ -56,7 +56,7 @@
#define BT_DBG(D...)
#endif
#define VERSION "0.3"
#define VERSION "0.4"
static struct proto_ops sco_sock_ops;
......@@ -705,6 +705,7 @@ static int sco_sock_getsockopt(struct socket *sock, int level, int optname, char
}
cinfo.hci_handle = sco_pi(sk)->conn->hcon->handle;
memcpy(cinfo.dev_class, sco_pi(sk)->conn->hcon->dev_class, 3);
len = min_t(unsigned int, len, sizeof(cinfo));
if (copy_to_user(optval, (char *)&cinfo, len))
......@@ -1045,7 +1046,7 @@ static void __exit sco_exit(void)
module_init(sco_init);
module_exit(sco_exit);
MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>");
MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>");
MODULE_DESCRIPTION("Bluetooth SCO ver " VERSION);
MODULE_VERSION(VERSION);
MODULE_LICENSE("GPL");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment