x86: Annotate section mismatch warnings in kernel/apic/x2apic_uv_x.c
[safe/jmp/linux-2.6] / net / bluetooth / rfcomm / core.c
index fcd2caf..94b3388 100644 (file)
@@ -23,8 +23,6 @@
 
 /*
  * Bluetooth RFCOMM core.
- *
- * $Id: core.c,v 1.42 2002/10/01 23:26:25 maxk Exp $
  */
 
 #include <linux/module.h>
 #include <net/bluetooth/l2cap.h>
 #include <net/bluetooth/rfcomm.h>
 
-#ifndef CONFIG_BT_RFCOMM_DEBUG
-#undef  BT_DBG
-#define BT_DBG(D...)
-#endif
-
-#define VERSION "1.9"
+#define VERSION "1.11"
 
 static int disable_cfc = 0;
 static int channel_mtu = -1;
@@ -230,19 +223,25 @@ static int rfcomm_l2sock_create(struct socket **sock)
        return err;
 }
 
-static inline int rfcomm_check_link_mode(struct rfcomm_dlc *d)
+static inline int rfcomm_check_security(struct rfcomm_dlc *d)
 {
        struct sock *sk = d->session->sock->sk;
+       __u8 auth_type;
 
-       if (d->link_mode & (RFCOMM_LM_ENCRYPT | RFCOMM_LM_SECURE)) {
-               if (!hci_conn_encrypt(l2cap_pi(sk)->conn->hcon))
-                       return 1;
-       } else if (d->link_mode & RFCOMM_LM_AUTH) {
-               if (!hci_conn_auth(l2cap_pi(sk)->conn->hcon))
-                       return 1;
+       switch (d->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 0;
+       return hci_conn_security(l2cap_pi(sk)->conn->hcon, d->sec_level,
+                                                               auth_type);
 }
 
 /* ---- RFCOMM DLCs ---- */
@@ -395,10 +394,10 @@ static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst,
        d->cfc = (s->cfc == RFCOMM_CFC_UNKNOWN) ? 0 : s->cfc;
 
        if (s->state == BT_CONNECTED) {
-               if (rfcomm_check_link_mode(d))
-                       set_bit(RFCOMM_AUTH_PENDING, &d->flags);
-               else
+               if (rfcomm_check_security(d))
                        rfcomm_send_pn(s, 1, d);
+               else
+                       set_bit(RFCOMM_AUTH_PENDING, &d->flags);
        }
 
        rfcomm_dlc_set_timer(d, RFCOMM_CONN_TIMEOUT);
@@ -428,9 +427,16 @@ static int __rfcomm_dlc_close(struct rfcomm_dlc *d, int err)
                        d, d->state, d->dlci, err, s);
 
        switch (d->state) {
-       case BT_CONNECTED:
-       case BT_CONFIG:
        case BT_CONNECT:
+       case BT_CONFIG:
+               if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) {
+                       set_bit(RFCOMM_AUTH_REJECT, &d->flags);
+                       rfcomm_schedule(RFCOMM_SCHED_AUTH);
+                       break;
+               }
+               /* Fall through */
+
+       case BT_CONNECTED:
                d->state = BT_DISCONN;
                if (skb_queue_empty(&d->tx_queue)) {
                        rfcomm_send_disc(s, d->dlci);
@@ -441,6 +447,15 @@ static int __rfcomm_dlc_close(struct rfcomm_dlc *d, int err)
                }
                break;
 
+       case BT_OPEN:
+       case BT_CONNECT2:
+               if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) {
+                       set_bit(RFCOMM_AUTH_REJECT, &d->flags);
+                       rfcomm_schedule(RFCOMM_SCHED_AUTH);
+                       break;
+               }
+               /* Fall through */
+
        default:
                rfcomm_dlc_clear_timer(d);
 
@@ -643,6 +658,7 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, bdaddr_t *dst
        bacpy(&addr.l2_bdaddr, src);
        addr.l2_family = AF_BLUETOOTH;
        addr.l2_psm    = 0;
+       addr.l2_cid    = 0;
        *err = kernel_bind(sock, (struct sockaddr *) &addr, sizeof(addr));
        if (*err < 0)
                goto failed;
@@ -663,7 +679,8 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, bdaddr_t *dst
 
        bacpy(&addr.l2_bdaddr, dst);
        addr.l2_family = AF_BLUETOOTH;
-       addr.l2_psm    = htobs(RFCOMM_PSM);
+       addr.l2_psm    = cpu_to_le16(RFCOMM_PSM);
+       addr.l2_cid    = 0;
        *err = kernel_connect(sock, (struct sockaddr *) &addr, sizeof(addr), O_NONBLOCK);
        if (*err == 0 || *err == -EINPROGRESS)
                return s;
@@ -835,9 +852,9 @@ static int rfcomm_send_pn(struct rfcomm_session *s, int cr, struct rfcomm_dlc *d
        }
 
        if (cr && channel_mtu >= 0)
-               pn->mtu = htobs(channel_mtu);
+               pn->mtu = cpu_to_le16(channel_mtu);
        else
-               pn->mtu = htobs(d->mtu);
+               pn->mtu = cpu_to_le16(d->mtu);
 
        *ptr = __fcs(buf); ptr++;
 
@@ -1039,7 +1056,7 @@ static void rfcomm_make_uih(struct sk_buff *skb, u8 addr)
 
        if (len > 127) {
                hdr = (void *) skb_push(skb, 4);
-               put_unaligned(htobs(__len16(len)), (__le16 *) &hdr->len);
+               put_unaligned(cpu_to_le16(__len16(len)), (__le16 *) &hdr->len);
        } else {
                hdr = (void *) skb_push(skb, 3);
                hdr->len = __len8(len);
@@ -1169,7 +1186,7 @@ static int rfcomm_recv_disc(struct rfcomm_session *s, u8 dlci)
        return 0;
 }
 
-static void rfcomm_dlc_accept(struct rfcomm_dlc *d)
+void rfcomm_dlc_accept(struct rfcomm_dlc *d)
 {
        struct sock *sk = d->session->sock->sk;
 
@@ -1177,17 +1194,38 @@ static void rfcomm_dlc_accept(struct rfcomm_dlc *d)
 
        rfcomm_send_ua(d->session, d->dlci);
 
+       rfcomm_dlc_clear_timer(d);
+
        rfcomm_dlc_lock(d);
        d->state = BT_CONNECTED;
        d->state_change(d, 0);
        rfcomm_dlc_unlock(d);
 
-       if (d->link_mode & RFCOMM_LM_MASTER)
+       if (d->role_switch)
                hci_conn_switch_role(l2cap_pi(sk)->conn->hcon, 0x00);
 
        rfcomm_send_msc(d->session, 1, d->dlci, d->v24_sig);
 }
 
+static void rfcomm_check_accept(struct rfcomm_dlc *d)
+{
+       if (rfcomm_check_security(d)) {
+               if (d->defer_setup) {
+                       set_bit(RFCOMM_DEFER_SETUP, &d->flags);
+                       rfcomm_dlc_set_timer(d, RFCOMM_AUTH_TIMEOUT);
+
+                       rfcomm_dlc_lock(d);
+                       d->state = BT_CONNECT2;
+                       d->state_change(d, 0);
+                       rfcomm_dlc_unlock(d);
+               } else
+                       rfcomm_dlc_accept(d);
+       } else {
+               set_bit(RFCOMM_AUTH_PENDING, &d->flags);
+               rfcomm_dlc_set_timer(d, RFCOMM_AUTH_TIMEOUT);
+       }
+}
+
 static int rfcomm_recv_sabm(struct rfcomm_session *s, u8 dlci)
 {
        struct rfcomm_dlc *d;
@@ -1210,11 +1248,7 @@ static int rfcomm_recv_sabm(struct rfcomm_session *s, u8 dlci)
        if (d) {
                if (d->state == BT_OPEN) {
                        /* DLC was previously opened by PN request */
-                       if (rfcomm_check_link_mode(d)) {
-                               set_bit(RFCOMM_AUTH_PENDING, &d->flags);
-                               rfcomm_dlc_set_timer(d, RFCOMM_AUTH_TIMEOUT);
-                       } else
-                               rfcomm_dlc_accept(d);
+                       rfcomm_check_accept(d);
                }
                return 0;
        }
@@ -1226,11 +1260,7 @@ static int rfcomm_recv_sabm(struct rfcomm_session *s, u8 dlci)
                d->addr = __addr(s->initiator, dlci);
                rfcomm_dlc_link(s, d);
 
-               if (rfcomm_check_link_mode(d)) {
-                       set_bit(RFCOMM_AUTH_PENDING, &d->flags);
-                       rfcomm_dlc_set_timer(d, RFCOMM_AUTH_TIMEOUT);
-               } else
-                       rfcomm_dlc_accept(d);
+               rfcomm_check_accept(d);
        } else {
                rfcomm_send_dm(s, dlci);
        }
@@ -1259,7 +1289,7 @@ static int rfcomm_apply_pn(struct rfcomm_dlc *d, int cr, struct rfcomm_pn *pn)
 
        d->priority = pn->priority;
 
-       d->mtu = btohs(pn->mtu);
+       d->mtu = __le16_to_cpu(pn->mtu);
 
        if (cr && d->mtu > s->mtu)
                d->mtu = s->mtu;
@@ -1644,11 +1674,12 @@ static void rfcomm_process_connect(struct rfcomm_session *s)
                d = list_entry(p, struct rfcomm_dlc, list);
                if (d->state == BT_CONFIG) {
                        d->mtu = s->mtu;
-                       if (rfcomm_check_link_mode(d)) {
+                       if (rfcomm_check_security(d)) {
+                               rfcomm_send_pn(s, 1, d);
+                       } else {
                                set_bit(RFCOMM_AUTH_PENDING, &d->flags);
                                rfcomm_dlc_set_timer(d, RFCOMM_AUTH_TIMEOUT);
-                       } else
-                               rfcomm_send_pn(s, 1, d);
+                       }
                }
        }
 }
@@ -1724,11 +1755,17 @@ static inline void rfcomm_process_dlcs(struct rfcomm_session *s)
                        if (d->out) {
                                rfcomm_send_pn(s, 1, d);
                                rfcomm_dlc_set_timer(d, RFCOMM_CONN_TIMEOUT);
-                       } else
-                               rfcomm_dlc_accept(d);
-                       if (d->link_mode & RFCOMM_LM_SECURE) {
-                               struct sock *sk = s->sock->sk;
-                               hci_conn_change_link_key(l2cap_pi(sk)->conn->hcon);
+                       } else {
+                               if (d->defer_setup) {
+                                       set_bit(RFCOMM_DEFER_SETUP, &d->flags);
+                                       rfcomm_dlc_set_timer(d, RFCOMM_AUTH_TIMEOUT);
+
+                                       rfcomm_dlc_lock(d);
+                                       d->state = BT_CONNECT2;
+                                       d->state_change(d, 0);
+                                       rfcomm_dlc_unlock(d);
+                               } else
+                                       rfcomm_dlc_accept(d);
                        }
                        continue;
                } else if (test_and_clear_bit(RFCOMM_AUTH_REJECT, &d->flags)) {
@@ -1741,6 +1778,9 @@ static inline void rfcomm_process_dlcs(struct rfcomm_session *s)
                        continue;
                }
 
+               if (test_bit(RFCOMM_SEC_PENDING, &d->flags))
+                       continue;
+
                if (test_bit(RFCOMM_TX_THROTTLED, &s->flags))
                        continue;
 
@@ -1788,8 +1828,6 @@ static inline void rfcomm_accept_connection(struct rfcomm_session *s)
        if (err < 0)
                return;
 
-       __module_get(nsock->ops->owner);
-
        /* Set our callbacks */
        nsock->sk->sk_data_ready   = rfcomm_l2data_ready;
        nsock->sk->sk_state_change = rfcomm_l2state_change;
@@ -1884,7 +1922,8 @@ static int rfcomm_add_listener(bdaddr_t *ba)
        /* Bind socket */
        bacpy(&addr.l2_bdaddr, ba);
        addr.l2_family = AF_BLUETOOTH;
-       addr.l2_psm    = htobs(RFCOMM_PSM);
+       addr.l2_psm    = cpu_to_le16(RFCOMM_PSM);
+       addr.l2_cid    = 0;
        err = kernel_bind(sock, (struct sockaddr *) &addr, sizeof(addr));
        if (err < 0) {
                BT_ERR("Bind failed %d", err);
@@ -1956,42 +1995,7 @@ static int rfcomm_run(void *unused)
        return 0;
 }
 
-static void rfcomm_auth_cfm(struct hci_conn *conn, u8 status)
-{
-       struct rfcomm_session *s;
-       struct rfcomm_dlc *d;
-       struct list_head *p, *n;
-
-       BT_DBG("conn %p status 0x%02x", conn, status);
-
-       s = rfcomm_session_get(&conn->hdev->bdaddr, &conn->dst);
-       if (!s)
-               return;
-
-       rfcomm_session_hold(s);
-
-       list_for_each_safe(p, n, &s->dlcs) {
-               d = list_entry(p, struct rfcomm_dlc, list);
-
-               if ((d->link_mode & (RFCOMM_LM_ENCRYPT | RFCOMM_LM_SECURE)) &&
-                               !(conn->link_mode & HCI_LM_ENCRYPT) && !status)
-                       continue;
-
-               if (!test_and_clear_bit(RFCOMM_AUTH_PENDING, &d->flags))
-                       continue;
-
-               if (!status)
-                       set_bit(RFCOMM_AUTH_ACCEPT, &d->flags);
-               else
-                       set_bit(RFCOMM_AUTH_REJECT, &d->flags);
-       }
-
-       rfcomm_session_put(s);
-
-       rfcomm_schedule(RFCOMM_SCHED_AUTH);
-}
-
-static void rfcomm_encrypt_cfm(struct hci_conn *conn, u8 status, u8 encrypt)
+static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt)
 {
        struct rfcomm_session *s;
        struct rfcomm_dlc *d;
@@ -2008,18 +2012,29 @@ static void rfcomm_encrypt_cfm(struct hci_conn *conn, u8 status, u8 encrypt)
        list_for_each_safe(p, n, &s->dlcs) {
                d = list_entry(p, struct rfcomm_dlc, list);
 
-               if ((d->link_mode & (RFCOMM_LM_ENCRYPT | RFCOMM_LM_SECURE)) &&
-                                       (d->state == BT_CONNECTED ||
-                                               d->state == BT_CONFIG) &&
-                                               !status && encrypt == 0x00) {
-                       __rfcomm_dlc_close(d, ECONNREFUSED);
-                       continue;
+               if (test_and_clear_bit(RFCOMM_SEC_PENDING, &d->flags)) {
+                       rfcomm_dlc_clear_timer(d);
+                       if (status || encrypt == 0x00) {
+                               __rfcomm_dlc_close(d, ECONNREFUSED);
+                               continue;
+                       }
+               }
+
+               if (d->state == BT_CONNECTED && !status && encrypt == 0x00) {
+                       if (d->sec_level == BT_SECURITY_MEDIUM) {
+                               set_bit(RFCOMM_SEC_PENDING, &d->flags);
+                               rfcomm_dlc_set_timer(d, RFCOMM_AUTH_TIMEOUT);
+                               continue;
+                       } else if (d->sec_level == BT_SECURITY_HIGH) {
+                               __rfcomm_dlc_close(d, ECONNREFUSED);
+                               continue;
+                       }
                }
 
                if (!test_and_clear_bit(RFCOMM_AUTH_PENDING, &d->flags))
                        continue;
 
-               if (!status && encrypt)
+               if (!status)
                        set_bit(RFCOMM_AUTH_ACCEPT, &d->flags);
                else
                        set_bit(RFCOMM_AUTH_REJECT, &d->flags);
@@ -2032,8 +2047,7 @@ static void rfcomm_encrypt_cfm(struct hci_conn *conn, u8 status, u8 encrypt)
 
 static struct hci_cb rfcomm_cb = {
        .name           = "RFCOMM",
-       .auth_cfm       = rfcomm_auth_cfm,
-       .encrypt_cfm    = rfcomm_encrypt_cfm
+       .security_cfm   = rfcomm_security_cfm
 };
 
 static ssize_t rfcomm_dlc_sysfs_show(struct class *dev, char *buf)
@@ -2066,28 +2080,41 @@ static CLASS_ATTR(rfcomm_dlc, S_IRUGO, rfcomm_dlc_sysfs_show, NULL);
 /* ---- Initialization ---- */
 static int __init rfcomm_init(void)
 {
+       int ret;
+
        l2cap_load();
 
        hci_register_cb(&rfcomm_cb);
 
        rfcomm_thread = kthread_run(rfcomm_run, NULL, "krfcommd");
        if (IS_ERR(rfcomm_thread)) {
-               hci_unregister_cb(&rfcomm_cb);
-               return PTR_ERR(rfcomm_thread);
+               ret = PTR_ERR(rfcomm_thread);
+               goto out_thread;
        }
 
        if (class_create_file(bt_class, &class_attr_rfcomm_dlc) < 0)
                BT_ERR("Failed to create RFCOMM info file");
 
-       rfcomm_init_sockets();
+       ret = rfcomm_init_ttys();
+       if (ret)
+               goto out_tty;
 
-#ifdef CONFIG_BT_RFCOMM_TTY
-       rfcomm_init_ttys();
-#endif
+       ret = rfcomm_init_sockets();
+       if (ret)
+               goto out_sock;
 
        BT_INFO("RFCOMM ver %s", VERSION);
 
        return 0;
+
+out_sock:
+       rfcomm_cleanup_ttys();
+out_tty:
+       kthread_stop(rfcomm_thread);
+out_thread:
+       hci_unregister_cb(&rfcomm_cb);
+
+       return ret;
 }
 
 static void __exit rfcomm_exit(void)
@@ -2098,9 +2125,7 @@ static void __exit rfcomm_exit(void)
 
        kthread_stop(rfcomm_thread);
 
-#ifdef CONFIG_BT_RFCOMM_TTY
        rfcomm_cleanup_ttys();
-#endif
 
        rfcomm_cleanup_sockets();
 }
@@ -2117,7 +2142,7 @@ MODULE_PARM_DESC(channel_mtu, "Default MTU for the RFCOMM channel");
 module_param(l2cap_mtu, uint, 0644);
 MODULE_PARM_DESC(l2cap_mtu, "Default MTU for the L2CAP connection");
 
-MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>, Marcel Holtmann <marcel@holtmann.org>");
+MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
 MODULE_DESCRIPTION("Bluetooth RFCOMM ver " VERSION);
 MODULE_VERSION(VERSION);
 MODULE_LICENSE("GPL");