Bluetooth: Disallow usage of L2CAP CID setting for now
[pandora-kernel.git] / net / bluetooth / l2cap.c
index 7bba469..7c6768c 100644 (file)
@@ -206,6 +206,8 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct so
 
        BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn, l2cap_pi(sk)->psm, l2cap_pi(sk)->dcid);
 
+       conn->disc_reason = 0x13;
+
        l2cap_pi(sk)->conn = conn;
 
        if (sk->sk_type == SOCK_SEQPACKET) {
@@ -266,16 +268,26 @@ static inline int l2cap_check_security(struct sock *sk)
        struct l2cap_conn *conn = l2cap_pi(sk)->conn;
        __u8 auth_type;
 
-       switch (l2cap_pi(sk)->sec_level) {
-       case BT_SECURITY_HIGH:
-               auth_type = HCI_AT_GENERAL_BONDING_MITM;
-               break;
-       case BT_SECURITY_MEDIUM:
-               auth_type = HCI_AT_GENERAL_BONDING;
-               break;
-       default:
-               auth_type = HCI_AT_NO_BONDING;
-               break;
+       if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) {
+               if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
+                       auth_type = HCI_AT_NO_BONDING_MITM;
+               else
+                        auth_type = HCI_AT_NO_BONDING;
+
+               if (l2cap_pi(sk)->sec_level == BT_SECURITY_LOW)
+                       l2cap_pi(sk)->sec_level = BT_SECURITY_SDP;
+       } else {
+               switch (l2cap_pi(sk)->sec_level) {
+               case BT_SECURITY_HIGH:
+                       auth_type = HCI_AT_GENERAL_BONDING_MITM;
+                       break;
+               case BT_SECURITY_MEDIUM:
+                       auth_type = HCI_AT_GENERAL_BONDING;
+                       break;
+               default:
+                       auth_type = HCI_AT_NO_BONDING;
+                       break;
+               }
        }
 
        return hci_conn_security(conn->hcon, l2cap_pi(sk)->sec_level,
@@ -491,6 +503,8 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
        spin_lock_init(&conn->lock);
        rwlock_init(&conn->chan_list.lock);
 
+       conn->disc_reason = 0x13;
+
        return conn;
 }
 
@@ -785,6 +799,9 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
        len = min_t(unsigned int, sizeof(la), alen);
        memcpy(&la, addr, len);
 
+       if (la.l2_cid)
+               return -EINVAL;
+
        lock_sock(sk);
 
        if (sk->sk_state != BT_OPEN) {
@@ -915,19 +932,20 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al
        struct sockaddr_l2 la;
        int len, err = 0;
 
-       lock_sock(sk);
-
        BT_DBG("sk %p", sk);
 
-       if (!addr || addr->sa_family != AF_BLUETOOTH) {
-               err = -EINVAL;
-               goto done;
-       }
+       if (!addr || addr->sa_family != AF_BLUETOOTH)
+               return -EINVAL;
 
        memset(&la, 0, sizeof(la));
        len = min_t(unsigned int, sizeof(la), alen);
        memcpy(&la, addr, len);
 
+       if (la.l2_cid)
+               return -EINVAL;
+
+       lock_sock(sk);
+
        if (sk->sk_type == SOCK_SEQPACKET && !la.l2_psm) {
                err = -EINVAL;
                goto done;
@@ -1840,6 +1858,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
        /* Check if the ACL is secure enough (if not SDP) */
        if (psm != cpu_to_le16(0x0001) &&
                                !hci_conn_check_link_mode(conn->hcon)) {
+               conn->disc_reason = 0x05;
                result = L2CAP_CR_SEC_BLOCK;
                goto response;
        }
@@ -2472,7 +2491,19 @@ static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
        return 0;
 }
 
-static int l2cap_disconn_ind(struct hci_conn *hcon, u8 reason)
+static int l2cap_disconn_ind(struct hci_conn *hcon)
+{
+       struct l2cap_conn *conn = hcon->l2cap_data;
+
+       BT_DBG("hcon %p", hcon);
+
+       if (hcon->type != ACL_LINK || !conn)
+               return 0x13;
+
+       return conn->disc_reason;
+}
+
+static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
 {
        BT_DBG("hcon %p reason %d", hcon, reason);
 
@@ -2717,6 +2748,7 @@ static struct hci_proto l2cap_hci_proto = {
        .connect_ind    = l2cap_connect_ind,
        .connect_cfm    = l2cap_connect_cfm,
        .disconn_ind    = l2cap_disconn_ind,
+       .disconn_cfm    = l2cap_disconn_cfm,
        .security_cfm   = l2cap_security_cfm,
        .recv_acldata   = l2cap_recv_acldata
 };