diff options
Diffstat (limited to 'net/bluetooth/l2cap.c')
-rw-r--r-- | net/bluetooth/l2cap.c | 68 |
1 files changed, 47 insertions, 21 deletions
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 1120cf14a548..9753b690a8b3 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)); |
@@ -1368,7 +1371,6 @@ static int l2cap_ertm_send(struct sock *sk) | |||
1368 | 1371 | ||
1369 | while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk)) && | 1372 | while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk)) && |
1370 | !(pi->conn_state & L2CAP_CONN_REMOTE_BUSY)) { | 1373 | !(pi->conn_state & L2CAP_CONN_REMOTE_BUSY)) { |
1371 | tx_skb = skb_clone(skb, GFP_ATOMIC); | ||
1372 | 1374 | ||
1373 | if (pi->remote_max_tx && | 1375 | if (pi->remote_max_tx && |
1374 | bt_cb(skb)->retries == pi->remote_max_tx) { | 1376 | bt_cb(skb)->retries == pi->remote_max_tx) { |
@@ -1376,6 +1378,8 @@ static int l2cap_ertm_send(struct sock *sk) | |||
1376 | break; | 1378 | break; |
1377 | } | 1379 | } |
1378 | 1380 | ||
1381 | tx_skb = skb_clone(skb, GFP_ATOMIC); | ||
1382 | |||
1379 | bt_cb(skb)->retries++; | 1383 | bt_cb(skb)->retries++; |
1380 | 1384 | ||
1381 | control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE); | 1385 | control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE); |
@@ -1622,7 +1626,10 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms | |||
1622 | /* Connectionless channel */ | 1626 | /* Connectionless channel */ |
1623 | if (sk->sk_type == SOCK_DGRAM) { | 1627 | if (sk->sk_type == SOCK_DGRAM) { |
1624 | skb = l2cap_create_connless_pdu(sk, msg, len); | 1628 | skb = l2cap_create_connless_pdu(sk, msg, len); |
1625 | err = l2cap_do_send(sk, skb); | 1629 | if (IS_ERR(skb)) |
1630 | err = PTR_ERR(skb); | ||
1631 | else | ||
1632 | err = l2cap_do_send(sk, skb); | ||
1626 | goto done; | 1633 | goto done; |
1627 | } | 1634 | } |
1628 | 1635 | ||
@@ -2829,6 +2836,11 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr | |||
2829 | int len = cmd->len - sizeof(*rsp); | 2836 | int len = cmd->len - sizeof(*rsp); |
2830 | char req[64]; | 2837 | char req[64]; |
2831 | 2838 | ||
2839 | if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) { | ||
2840 | l2cap_send_disconn_req(conn, sk); | ||
2841 | goto done; | ||
2842 | } | ||
2843 | |||
2832 | /* throw out any old stored conf requests */ | 2844 | /* throw out any old stored conf requests */ |
2833 | result = L2CAP_CONF_SUCCESS; | 2845 | result = L2CAP_CONF_SUCCESS; |
2834 | len = l2cap_parse_conf_rsp(sk, rsp->data, | 2846 | len = l2cap_parse_conf_rsp(sk, rsp->data, |
@@ -3518,7 +3530,6 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk | |||
3518 | struct l2cap_pinfo *pi; | 3530 | struct l2cap_pinfo *pi; |
3519 | u16 control, len; | 3531 | u16 control, len; |
3520 | u8 tx_seq; | 3532 | u8 tx_seq; |
3521 | int err; | ||
3522 | 3533 | ||
3523 | sk = l2cap_get_chan_by_scid(&conn->chan_list, cid); | 3534 | sk = l2cap_get_chan_by_scid(&conn->chan_list, cid); |
3524 | if (!sk) { | 3535 | if (!sk) { |
@@ -3570,13 +3581,11 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk | |||
3570 | goto drop; | 3581 | goto drop; |
3571 | 3582 | ||
3572 | if (__is_iframe(control)) | 3583 | if (__is_iframe(control)) |
3573 | err = l2cap_data_channel_iframe(sk, control, skb); | 3584 | l2cap_data_channel_iframe(sk, control, skb); |
3574 | else | 3585 | else |
3575 | err = l2cap_data_channel_sframe(sk, control, skb); | 3586 | l2cap_data_channel_sframe(sk, control, skb); |
3576 | 3587 | ||
3577 | if (!err) | 3588 | goto done; |
3578 | goto done; | ||
3579 | break; | ||
3580 | 3589 | ||
3581 | case L2CAP_MODE_STREAMING: | 3590 | case L2CAP_MODE_STREAMING: |
3582 | control = get_unaligned_le16(skb->data); | 3591 | control = get_unaligned_le16(skb->data); |
@@ -3602,7 +3611,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk | |||
3602 | else | 3611 | else |
3603 | pi->expected_tx_seq = tx_seq + 1; | 3612 | pi->expected_tx_seq = tx_seq + 1; |
3604 | 3613 | ||
3605 | err = l2cap_sar_reassembly_sdu(sk, skb, control); | 3614 | l2cap_sar_reassembly_sdu(sk, skb, control); |
3606 | 3615 | ||
3607 | goto done; | 3616 | goto done; |
3608 | 3617 | ||
@@ -3939,29 +3948,42 @@ drop: | |||
3939 | return 0; | 3948 | return 0; |
3940 | } | 3949 | } |
3941 | 3950 | ||
3942 | static ssize_t l2cap_sysfs_show(struct class *dev, char *buf) | 3951 | static int l2cap_debugfs_show(struct seq_file *f, void *p) |
3943 | { | 3952 | { |
3944 | struct sock *sk; | 3953 | struct sock *sk; |
3945 | struct hlist_node *node; | 3954 | struct hlist_node *node; |
3946 | char *str = buf; | ||
3947 | 3955 | ||
3948 | read_lock_bh(&l2cap_sk_list.lock); | 3956 | read_lock_bh(&l2cap_sk_list.lock); |
3949 | 3957 | ||
3950 | sk_for_each(sk, node, &l2cap_sk_list.head) { | 3958 | sk_for_each(sk, node, &l2cap_sk_list.head) { |
3951 | struct l2cap_pinfo *pi = l2cap_pi(sk); | 3959 | struct l2cap_pinfo *pi = l2cap_pi(sk); |
3952 | 3960 | ||
3953 | str += sprintf(str, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d\n", | 3961 | 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), | 3962 | batostr(&bt_sk(sk)->src), |
3955 | sk->sk_state, __le16_to_cpu(pi->psm), pi->scid, | 3963 | batostr(&bt_sk(sk)->dst), |
3956 | pi->dcid, pi->imtu, pi->omtu, pi->sec_level); | 3964 | sk->sk_state, __le16_to_cpu(pi->psm), |
3965 | pi->scid, pi->dcid, | ||
3966 | pi->imtu, pi->omtu, pi->sec_level); | ||
3957 | } | 3967 | } |
3958 | 3968 | ||
3959 | read_unlock_bh(&l2cap_sk_list.lock); | 3969 | read_unlock_bh(&l2cap_sk_list.lock); |
3960 | 3970 | ||
3961 | return str - buf; | 3971 | return 0; |
3972 | } | ||
3973 | |||
3974 | static int l2cap_debugfs_open(struct inode *inode, struct file *file) | ||
3975 | { | ||
3976 | return single_open(file, l2cap_debugfs_show, inode->i_private); | ||
3962 | } | 3977 | } |
3963 | 3978 | ||
3964 | static CLASS_ATTR(l2cap, S_IRUGO, l2cap_sysfs_show, NULL); | 3979 | static const struct file_operations l2cap_debugfs_fops = { |
3980 | .open = l2cap_debugfs_open, | ||
3981 | .read = seq_read, | ||
3982 | .llseek = seq_lseek, | ||
3983 | .release = single_release, | ||
3984 | }; | ||
3985 | |||
3986 | static struct dentry *l2cap_debugfs; | ||
3965 | 3987 | ||
3966 | static const struct proto_ops l2cap_sock_ops = { | 3988 | static const struct proto_ops l2cap_sock_ops = { |
3967 | .family = PF_BLUETOOTH, | 3989 | .family = PF_BLUETOOTH, |
@@ -4021,8 +4043,12 @@ static int __init l2cap_init(void) | |||
4021 | goto error; | 4043 | goto error; |
4022 | } | 4044 | } |
4023 | 4045 | ||
4024 | if (class_create_file(bt_class, &class_attr_l2cap) < 0) | 4046 | if (bt_debugfs) { |
4025 | BT_ERR("Failed to create L2CAP info file"); | 4047 | l2cap_debugfs = debugfs_create_file("l2cap", 0444, |
4048 | bt_debugfs, NULL, &l2cap_debugfs_fops); | ||
4049 | if (!l2cap_debugfs) | ||
4050 | BT_ERR("Failed to create L2CAP debug file"); | ||
4051 | } | ||
4026 | 4052 | ||
4027 | BT_INFO("L2CAP ver %s", VERSION); | 4053 | BT_INFO("L2CAP ver %s", VERSION); |
4028 | BT_INFO("L2CAP socket layer initialized"); | 4054 | BT_INFO("L2CAP socket layer initialized"); |
@@ -4036,7 +4062,7 @@ error: | |||
4036 | 4062 | ||
4037 | static void __exit l2cap_exit(void) | 4063 | static void __exit l2cap_exit(void) |
4038 | { | 4064 | { |
4039 | class_remove_file(bt_class, &class_attr_l2cap); | 4065 | debugfs_remove(l2cap_debugfs); |
4040 | 4066 | ||
4041 | if (bt_sock_unregister(BTPROTO_L2CAP) < 0) | 4067 | if (bt_sock_unregister(BTPROTO_L2CAP) < 0) |
4042 | BT_ERR("L2CAP socket unregistration failed"); | 4068 | BT_ERR("L2CAP socket unregistration failed"); |