diff options
Diffstat (limited to 'net/bluetooth/l2cap.c')
| -rw-r--r-- | net/bluetooth/l2cap.c | 51 |
1 files changed, 37 insertions, 14 deletions
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 4db7ae2fe07d..99d68c34e4f1 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c | |||
| @@ -40,6 +40,8 @@ | |||
| 40 | #include <linux/skbuff.h> | 40 | #include <linux/skbuff.h> |
| 41 | #include <linux/list.h> | 41 | #include <linux/list.h> |
| 42 | #include <linux/device.h> | 42 | #include <linux/device.h> |
| 43 | #include <linux/debugfs.h> | ||
| 44 | #include <linux/seq_file.h> | ||
| 43 | #include <linux/uaccess.h> | 45 | #include <linux/uaccess.h> |
| 44 | #include <linux/crc16.h> | 46 | #include <linux/crc16.h> |
| 45 | #include <net/sock.h> | 47 | #include <net/sock.h> |
| @@ -1000,7 +1002,8 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al | |||
| 1000 | 1002 | ||
| 1001 | BT_DBG("sk %p", sk); | 1003 | BT_DBG("sk %p", sk); |
| 1002 | 1004 | ||
| 1003 | if (!addr || addr->sa_family != AF_BLUETOOTH) | 1005 | if (!addr || alen < sizeof(addr->sa_family) || |
| 1006 | addr->sa_family != AF_BLUETOOTH) | ||
| 1004 | return -EINVAL; | 1007 | return -EINVAL; |
| 1005 | 1008 | ||
| 1006 | memset(&la, 0, sizeof(la)); | 1009 | memset(&la, 0, sizeof(la)); |
| @@ -2830,6 +2833,11 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr | |||
| 2830 | int len = cmd->len - sizeof(*rsp); | 2833 | int len = cmd->len - sizeof(*rsp); |
| 2831 | char req[64]; | 2834 | char req[64]; |
| 2832 | 2835 | ||
| 2836 | if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) { | ||
| 2837 | l2cap_send_disconn_req(conn, sk); | ||
| 2838 | goto done; | ||
| 2839 | } | ||
| 2840 | |||
| 2833 | /* throw out any old stored conf requests */ | 2841 | /* throw out any old stored conf requests */ |
| 2834 | result = L2CAP_CONF_SUCCESS; | 2842 | result = L2CAP_CONF_SUCCESS; |
| 2835 | len = l2cap_parse_conf_rsp(sk, rsp->data, | 2843 | len = l2cap_parse_conf_rsp(sk, rsp->data, |
| @@ -3937,31 +3945,42 @@ drop: | |||
| 3937 | return 0; | 3945 | return 0; |
| 3938 | } | 3946 | } |
| 3939 | 3947 | ||
| 3940 | static ssize_t l2cap_sysfs_show(struct class *dev, | 3948 | static int l2cap_debugfs_show(struct seq_file *f, void *p) |
| 3941 | struct class_attribute *attr, | ||
| 3942 | char *buf) | ||
| 3943 | { | 3949 | { |
| 3944 | struct sock *sk; | 3950 | struct sock *sk; |
| 3945 | struct hlist_node *node; | 3951 | struct hlist_node *node; |
| 3946 | char *str = buf; | ||
| 3947 | 3952 | ||
| 3948 | read_lock_bh(&l2cap_sk_list.lock); | 3953 | read_lock_bh(&l2cap_sk_list.lock); |
| 3949 | 3954 | ||
| 3950 | sk_for_each(sk, node, &l2cap_sk_list.head) { | 3955 | sk_for_each(sk, node, &l2cap_sk_list.head) { |
| 3951 | struct l2cap_pinfo *pi = l2cap_pi(sk); | 3956 | struct l2cap_pinfo *pi = l2cap_pi(sk); |
| 3952 | 3957 | ||
| 3953 | str += sprintf(str, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d\n", | 3958 | seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d\n", |
| 3954 | batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst), | 3959 | batostr(&bt_sk(sk)->src), |
| 3955 | sk->sk_state, __le16_to_cpu(pi->psm), pi->scid, | 3960 | batostr(&bt_sk(sk)->dst), |
| 3956 | pi->dcid, pi->imtu, pi->omtu, pi->sec_level); | 3961 | sk->sk_state, __le16_to_cpu(pi->psm), |
| 3962 | pi->scid, pi->dcid, | ||
| 3963 | pi->imtu, pi->omtu, pi->sec_level); | ||
| 3957 | } | 3964 | } |
| 3958 | 3965 | ||
| 3959 | read_unlock_bh(&l2cap_sk_list.lock); | 3966 | read_unlock_bh(&l2cap_sk_list.lock); |
| 3960 | 3967 | ||
| 3961 | return str - buf; | 3968 | return 0; |
| 3969 | } | ||
| 3970 | |||
| 3971 | static int l2cap_debugfs_open(struct inode *inode, struct file *file) | ||
| 3972 | { | ||
| 3973 | return single_open(file, l2cap_debugfs_show, inode->i_private); | ||
| 3962 | } | 3974 | } |
| 3963 | 3975 | ||
| 3964 | static CLASS_ATTR(l2cap, S_IRUGO, l2cap_sysfs_show, NULL); | 3976 | static const struct file_operations l2cap_debugfs_fops = { |
| 3977 | .open = l2cap_debugfs_open, | ||
| 3978 | .read = seq_read, | ||
| 3979 | .llseek = seq_lseek, | ||
| 3980 | .release = single_release, | ||
| 3981 | }; | ||
| 3982 | |||
| 3983 | static struct dentry *l2cap_debugfs; | ||
| 3965 | 3984 | ||
| 3966 | static const struct proto_ops l2cap_sock_ops = { | 3985 | static const struct proto_ops l2cap_sock_ops = { |
| 3967 | .family = PF_BLUETOOTH, | 3986 | .family = PF_BLUETOOTH, |
| @@ -4021,8 +4040,12 @@ static int __init l2cap_init(void) | |||
| 4021 | goto error; | 4040 | goto error; |
| 4022 | } | 4041 | } |
| 4023 | 4042 | ||
| 4024 | if (class_create_file(bt_class, &class_attr_l2cap) < 0) | 4043 | if (bt_debugfs) { |
| 4025 | BT_ERR("Failed to create L2CAP info file"); | 4044 | l2cap_debugfs = debugfs_create_file("l2cap", 0444, |
| 4045 | bt_debugfs, NULL, &l2cap_debugfs_fops); | ||
| 4046 | if (!l2cap_debugfs) | ||
| 4047 | BT_ERR("Failed to create L2CAP debug file"); | ||
| 4048 | } | ||
| 4026 | 4049 | ||
| 4027 | BT_INFO("L2CAP ver %s", VERSION); | 4050 | BT_INFO("L2CAP ver %s", VERSION); |
| 4028 | BT_INFO("L2CAP socket layer initialized"); | 4051 | BT_INFO("L2CAP socket layer initialized"); |
| @@ -4036,7 +4059,7 @@ error: | |||
| 4036 | 4059 | ||
| 4037 | static void __exit l2cap_exit(void) | 4060 | static void __exit l2cap_exit(void) |
| 4038 | { | 4061 | { |
| 4039 | class_remove_file(bt_class, &class_attr_l2cap); | 4062 | debugfs_remove(l2cap_debugfs); |
| 4040 | 4063 | ||
| 4041 | if (bt_sock_unregister(BTPROTO_L2CAP) < 0) | 4064 | if (bt_sock_unregister(BTPROTO_L2CAP) < 0) |
| 4042 | BT_ERR("L2CAP socket unregistration failed"); | 4065 | BT_ERR("L2CAP socket unregistration failed"); |
