#include <net/bluetooth/l2cap.h>
#include <net/bluetooth/rfcomm.h>
-#define VERSION "1.10"
+#define VERSION "1.11"
static int disable_cfc = 0;
static int channel_mtu = -1;
static inline int rfcomm_check_security(struct rfcomm_dlc *d)
{
struct sock *sk = d->session->sock->sk;
+ __u8 auth_type;
- return hci_conn_security(l2cap_pi(sk)->conn->hcon, d->sec_level);
+ 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 hci_conn_security(l2cap_pi(sk)->conn->hcon, d->sec_level,
+ auth_type);
}
/* ---- RFCOMM DLCs ---- */
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);
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;
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;
}
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++;
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);
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);
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 {
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;
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;
}
+ if (test_bit(RFCOMM_SEC_PENDING, &d->flags))
+ continue;
+
if (test_bit(RFCOMM_TX_THROTTLED, &s->flags))
continue;
/* 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);
list_for_each_safe(p, n, &s->dlcs) {
d = list_entry(p, struct rfcomm_dlc, list);
- if (!status && encrypt == 0x00 &&
- d->sec_level == BT_SECURITY_HIGH &&
- (d->state == BT_CONNECTED ||
- d->state == BT_CONFIG)) {
- __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))
/* ---- 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)
kthread_stop(rfcomm_thread);
-#ifdef CONFIG_BT_RFCOMM_TTY
rfcomm_cleanup_ttys();
-#endif
rfcomm_cleanup_sockets();
}