18e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds RFCOMM implementation for Linux Bluetooth stack (BlueZ). 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Copyright (C) 2002 Maxim Krasnyansky <maxk@qualcomm.com> 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Copyright (C) 2002 Marcel Holtmann <marcel@holtmann.org> 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This program is free software; you can redistribute it and/or modify 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds it under the terms of the GNU General Public License version 2 as 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds published by the Free Software Foundation; 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY 148e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 158e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 168e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 198e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 208e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SOFTWARE IS DISCLAIMED. 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * RFCOMM sockets. 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 288c520a59927a5600973782505dbb750d985057c4Gustavo Padovan#include <linux/export.h> 29aef7d97cc604309b66f6f45cce02cd734934cd4eMarcel Holtmann#include <linux/debugfs.h> 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/bluetooth/bluetooth.h> 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/bluetooth/hci_core.h> 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/bluetooth/l2cap.h> 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/bluetooth/rfcomm.h> 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3690ddc4f0470427df306f308ad03db6b6b21644b8Eric Dumazetstatic const struct proto_ops rfcomm_sock_ops; 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct bt_sock_list rfcomm_sk_list = { 39d5fb2962c6157495e1365e4f30568ed3830d35a7Robert P. J. Day .lock = __RW_LOCK_UNLOCKED(rfcomm_sk_list.lock) 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void rfcomm_sock_close(struct sock *sk); 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void rfcomm_sock_kill(struct sock *sk); 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* ---- DLC callbacks ---- 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * called under rfcomm_dlc_lock() 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void rfcomm_sk_data_ready(struct rfcomm_dlc *d, struct sk_buff *skb) 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sock *sk = d->owner; 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!sk) 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_add(skb->len, &sk->sk_rmem_alloc); 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_queue_tail(&sk->sk_receive_queue, skb); 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sk->sk_data_ready(sk, skb->len); 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf) 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rfcomm_dlc_throttle(d); 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void rfcomm_sk_state_change(struct rfcomm_dlc *d, int err) 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sock *sk = d->owner, *parent; 66fad003b6c8e3d944d4453fd569b0702ef1af82b3Gustavo Padovan unsigned long flags; 67fad003b6c8e3d944d4453fd569b0702ef1af82b3Gustavo Padovan 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!sk) 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BT_DBG("dlc %p state %ld err %d", d, d->state, err); 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 73fad003b6c8e3d944d4453fd569b0702ef1af82b3Gustavo Padovan local_irq_save(flags); 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bh_lock_sock(sk); 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (err) 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sk->sk_err = err; 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sk->sk_state = d->state; 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds parent = bt_sk(sk)->parent; 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (parent) { 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (d->state == BT_CLOSED) { 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sock_set_flag(sk, SOCK_ZAPPED); 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bt_accept_unlink(sk); 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds parent->sk_data_ready(parent, 0); 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (d->state == BT_CONNECTED) 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rfcomm_session_getaddr(d->session, &bt_sk(sk)->src, NULL); 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sk->sk_state_change(sk); 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bh_unlock_sock(sk); 95fad003b6c8e3d944d4453fd569b0702ef1af82b3Gustavo Padovan local_irq_restore(flags); 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (parent && sock_flag(sk, SOCK_ZAPPED)) { 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We have to drop DLC lock here, otherwise 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * rfcomm_sock_destruct() will dead lock. */ 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rfcomm_dlc_unlock(d); 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rfcomm_sock_kill(sk); 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rfcomm_dlc_lock(d); 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* ---- Socket functions ---- */ 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct sock *__rfcomm_get_sock_by_addr(u8 channel, bdaddr_t *src) 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sock *sk = NULL; 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 111b67bfe0d42cac56c512dd5da4b1b347a23f4b70aSasha Levin sk_for_each(sk, &rfcomm_sk_list.head) { 1128e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki if (rfcomm_pi(sk)->channel == channel && 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds !bacmp(&bt_sk(sk)->src, src)) 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 117b67bfe0d42cac56c512dd5da4b1b347a23f4b70aSasha Levin return sk ? sk : NULL; 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Find socket with channel and source bdaddr. 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns closest match. 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 123eeb366564be7c311b31c70821d18a43a8a57f9bcGustavo Padovanstatic struct sock *rfcomm_get_sock_by_channel(int state, u8 channel, bdaddr_t *src) 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sock *sk = NULL, *sk1 = NULL; 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 127eeb366564be7c311b31c70821d18a43a8a57f9bcGustavo Padovan read_lock(&rfcomm_sk_list.lock); 128eeb366564be7c311b31c70821d18a43a8a57f9bcGustavo Padovan 129b67bfe0d42cac56c512dd5da4b1b347a23f4b70aSasha Levin sk_for_each(sk, &rfcomm_sk_list.head) { 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (state && sk->sk_state != state) 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rfcomm_pi(sk)->channel == channel) { 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Exact match. */ 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!bacmp(&bt_sk(sk)->src, src)) 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Closest match */ 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sk1 = sk; 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds read_unlock(&rfcomm_sk_list.lock); 145eeb366564be7c311b31c70821d18a43a8a57f9bcGustavo Padovan 146b67bfe0d42cac56c512dd5da4b1b347a23f4b70aSasha Levin return sk ? sk : sk1; 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void rfcomm_sock_destruct(struct sock *sk) 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct rfcomm_dlc *d = rfcomm_pi(sk)->dlc; 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BT_DBG("sk %p dlc %p", sk, d); 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_queue_purge(&sk->sk_receive_queue); 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_queue_purge(&sk->sk_write_queue); 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rfcomm_dlc_lock(d); 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rfcomm_pi(sk)->dlc = NULL; 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Detach DLC if it's owned by this socket */ 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (d->owner == sk) 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->owner = NULL; 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rfcomm_dlc_unlock(d); 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rfcomm_dlc_put(d); 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void rfcomm_sock_cleanup_listen(struct sock *parent) 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sock *sk; 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BT_DBG("parent %p", parent); 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Close not yet accepted dlcs */ 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while ((sk = bt_accept_dequeue(parent, NULL))) { 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rfcomm_sock_close(sk); 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rfcomm_sock_kill(sk); 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds parent->sk_state = BT_CLOSED; 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sock_set_flag(parent, SOCK_ZAPPED); 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Kill socket (only if zapped and orphan) 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Must be called on unlocked socket. 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void rfcomm_sock_kill(struct sock *sk) 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket) 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BT_DBG("sk %p state %d refcnt %d", sk, sk->sk_state, atomic_read(&sk->sk_refcnt)); 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Kill poor orphan */ 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bt_sock_unlink(&rfcomm_sk_list, sk); 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sock_set_flag(sk, SOCK_DEAD); 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sock_put(sk); 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __rfcomm_sock_close(struct sock *sk) 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct rfcomm_dlc *d = rfcomm_pi(sk)->dlc; 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BT_DBG("sk %p state %d socket %p", sk, sk->sk_state, sk->sk_socket); 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (sk->sk_state) { 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case BT_LISTEN: 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rfcomm_sock_cleanup_listen(sk); 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case BT_CONNECT: 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case BT_CONNECT2: 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case BT_CONFIG: 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case BT_CONNECTED: 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rfcomm_dlc_close(d, 0); 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sock_set_flag(sk, SOCK_ZAPPED); 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Close socket. 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Must be called on unlocked socket. 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void rfcomm_sock_close(struct sock *sk) 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_sock(sk); 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __rfcomm_sock_close(sk); 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_sock(sk); 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void rfcomm_sock_init(struct sock *sk, struct sock *parent) 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct rfcomm_pinfo *pi = rfcomm_pi(sk); 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BT_DBG("sk %p", sk); 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (parent) { 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sk->sk_type = parent->sk_type; 242c5daa683f2d3315cd766f550ef7d88bfca1671f4Gustavo Padovan pi->dlc->defer_setup = test_bit(BT_SK_DEFER_SETUP, 243c5daa683f2d3315cd766f550ef7d88bfca1671f4Gustavo Padovan &bt_sk(parent)->flags); 2449f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann 2459f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann pi->sec_level = rfcomm_pi(parent)->sec_level; 2469f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann pi->role_switch = rfcomm_pi(parent)->role_switch; 2476230c9b4f8957c8938ee4cf2d03166d3c2dc89dePaul Moore 2486230c9b4f8957c8938ee4cf2d03166d3c2dc89dePaul Moore security_sk_clone(parent, sk); 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 250bb23c0ab824653be4aa7dfca15b07b3059717004Marcel Holtmann pi->dlc->defer_setup = 0; 2519f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann 2529f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann pi->sec_level = BT_SECURITY_LOW; 2539f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann pi->role_switch = 0; 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2569f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann pi->dlc->sec_level = pi->sec_level; 2579f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann pi->dlc->role_switch = pi->role_switch; 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct proto rfcomm_proto = { 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "RFCOMM", 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .owner = THIS_MODULE, 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .obj_size = sizeof(struct rfcomm_pinfo) 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2661b8d7ae42d02e483ad94035cca851e4f7fbecb40Eric W. Biedermanstatic struct sock *rfcomm_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio) 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct rfcomm_dlc *d; 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sock *sk; 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2716257ff2177ff02d7f260a7a501876aa41cb9a9f6Pavel Emelyanov sk = sk_alloc(net, PF_BLUETOOTH, prio, &rfcomm_proto); 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!sk) 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sock_init_data(sock, sk); 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INIT_LIST_HEAD(&bt_sk(sk)->accept_q); 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d = rfcomm_dlc_alloc(prio); 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!d) { 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sk_free(sk); 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->data_ready = rfcomm_sk_data_ready; 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->state_change = rfcomm_sk_state_change; 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rfcomm_pi(sk)->dlc = d; 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->owner = sk; 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sk->sk_destruct = rfcomm_sock_destruct; 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sk->sk_sndtimeo = RFCOMM_CONN_TIMEOUT; 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 29377db1980565626471a980f0d2d17299e4bd5e7a5Marcel Holtmann sk->sk_sndbuf = RFCOMM_MAX_CREDITS * RFCOMM_DEFAULT_MTU * 10; 29477db1980565626471a980f0d2d17299e4bd5e7a5Marcel Holtmann sk->sk_rcvbuf = RFCOMM_MAX_CREDITS * RFCOMM_DEFAULT_MTU * 10; 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sock_reset_flag(sk, SOCK_ZAPPED); 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sk->sk_protocol = proto; 29977db1980565626471a980f0d2d17299e4bd5e7a5Marcel Holtmann sk->sk_state = BT_OPEN; 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bt_sock_link(&rfcomm_sk_list, sk); 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BT_DBG("sk %p", sk); 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sk; 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3073f378b684453f2a028eda463ce383370545d9cc9Eric Parisstatic int rfcomm_sock_create(struct net *net, struct socket *sock, 3083f378b684453f2a028eda463ce383370545d9cc9Eric Paris int protocol, int kern) 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sock *sk; 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BT_DBG("sock %p", sock); 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sock->state = SS_UNCONNECTED; 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sock->type != SOCK_STREAM && sock->type != SOCK_RAW) 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ESOCKTNOSUPPORT; 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sock->ops = &rfcomm_sock_ops; 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3211b8d7ae42d02e483ad94035cca851e4f7fbecb40Eric W. Biederman sk = rfcomm_sock_alloc(net, sock, protocol, GFP_ATOMIC); 32274da626a1098640ddc40c0e3481c0cd41e8ec1e9Marcel Holtmann if (!sk) 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rfcomm_sock_init(sk, NULL); 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int rfcomm_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_len) 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sockaddr_rc *sa = (struct sockaddr_rc *) addr; 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sock *sk = sock->sk; 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err = 0; 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3356ed93dc6427d14cdfe0b272cc0a9ee4685ce9ad7Andrei Emeltchenko BT_DBG("sk %p %pMR", sk, &sa->rc_bdaddr); 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!addr || addr->sa_family != AF_BLUETOOTH) 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_sock(sk); 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sk->sk_state != BT_OPEN) { 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = -EBADFD; 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto done; 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 347354d28d5f8546e115ebaae9311897f0bc4b6a8d4Marcel Holtmann if (sk->sk_type != SOCK_STREAM) { 348354d28d5f8546e115ebaae9311897f0bc4b6a8d4Marcel Holtmann err = -EINVAL; 349354d28d5f8546e115ebaae9311897f0bc4b6a8d4Marcel Holtmann goto done; 350354d28d5f8546e115ebaae9311897f0bc4b6a8d4Marcel Holtmann } 351354d28d5f8546e115ebaae9311897f0bc4b6a8d4Marcel Holtmann 35295ca83f42fb5f5bf789b514635f79242afe555d1Gustavo Padovan write_lock(&rfcomm_sk_list.lock); 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sa->rc_channel && __rfcomm_get_sock_by_addr(sa->rc_channel, &sa->rc_bdaddr)) { 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = -EADDRINUSE; 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Save source address */ 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bacpy(&bt_sk(sk)->src, &sa->rc_bdaddr); 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rfcomm_pi(sk)->channel = sa->rc_channel; 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sk->sk_state = BT_BOUND; 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 36395ca83f42fb5f5bf789b514635f79242afe555d1Gustavo Padovan write_unlock(&rfcomm_sk_list.lock); 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdone: 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_sock(sk); 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int rfcomm_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags) 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sockaddr_rc *sa = (struct sockaddr_rc *) addr; 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sock *sk = sock->sk; 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct rfcomm_dlc *d = rfcomm_pi(sk)->dlc; 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err = 0; 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BT_DBG("sk %p", sk); 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3796503d96168f891ffa3b70ae6c9698a1a722025a0Changli Gao if (alen < sizeof(struct sockaddr_rc) || 3806503d96168f891ffa3b70ae6c9698a1a722025a0Changli Gao addr->sa_family != AF_BLUETOOTH) 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 383354d28d5f8546e115ebaae9311897f0bc4b6a8d4Marcel Holtmann lock_sock(sk); 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 385354d28d5f8546e115ebaae9311897f0bc4b6a8d4Marcel Holtmann if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND) { 386354d28d5f8546e115ebaae9311897f0bc4b6a8d4Marcel Holtmann err = -EBADFD; 387354d28d5f8546e115ebaae9311897f0bc4b6a8d4Marcel Holtmann goto done; 388354d28d5f8546e115ebaae9311897f0bc4b6a8d4Marcel Holtmann } 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 390354d28d5f8546e115ebaae9311897f0bc4b6a8d4Marcel Holtmann if (sk->sk_type != SOCK_STREAM) { 391354d28d5f8546e115ebaae9311897f0bc4b6a8d4Marcel Holtmann err = -EINVAL; 392354d28d5f8546e115ebaae9311897f0bc4b6a8d4Marcel Holtmann goto done; 393354d28d5f8546e115ebaae9311897f0bc4b6a8d4Marcel Holtmann } 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sk->sk_state = BT_CONNECT; 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bacpy(&bt_sk(sk)->dst, &sa->rc_bdaddr); 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rfcomm_pi(sk)->channel = sa->rc_channel; 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3999f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann d->sec_level = rfcomm_pi(sk)->sec_level; 4009f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann d->role_switch = rfcomm_pi(sk)->role_switch; 40177db1980565626471a980f0d2d17299e4bd5e7a5Marcel Holtmann 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = rfcomm_dlc_open(d, &bt_sk(sk)->src, &sa->rc_bdaddr, sa->rc_channel); 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!err) 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = bt_sock_wait_state(sk, BT_CONNECTED, 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sock_sndtimeo(sk, flags & O_NONBLOCK)); 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 407354d28d5f8546e115ebaae9311897f0bc4b6a8d4Marcel Holtmanndone: 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_sock(sk); 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int rfcomm_sock_listen(struct socket *sock, int backlog) 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sock *sk = sock->sk; 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err = 0; 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BT_DBG("sk %p backlog %d", sk, backlog); 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_sock(sk); 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sk->sk_state != BT_BOUND) { 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = -EBADFD; 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto done; 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 426354d28d5f8546e115ebaae9311897f0bc4b6a8d4Marcel Holtmann if (sk->sk_type != SOCK_STREAM) { 427354d28d5f8546e115ebaae9311897f0bc4b6a8d4Marcel Holtmann err = -EINVAL; 428354d28d5f8546e115ebaae9311897f0bc4b6a8d4Marcel Holtmann goto done; 429354d28d5f8546e115ebaae9311897f0bc4b6a8d4Marcel Holtmann } 430354d28d5f8546e115ebaae9311897f0bc4b6a8d4Marcel Holtmann 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!rfcomm_pi(sk)->channel) { 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bdaddr_t *src = &bt_sk(sk)->src; 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 channel; 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = -EINVAL; 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 43795ca83f42fb5f5bf789b514635f79242afe555d1Gustavo Padovan write_lock(&rfcomm_sk_list.lock); 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (channel = 1; channel < 31; channel++) 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!__rfcomm_get_sock_by_addr(channel, src)) { 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rfcomm_pi(sk)->channel = channel; 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = 0; 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 44695ca83f42fb5f5bf789b514635f79242afe555d1Gustavo Padovan write_unlock(&rfcomm_sk_list.lock); 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (err < 0) 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto done; 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sk->sk_max_ack_backlog = backlog; 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sk->sk_ack_backlog = 0; 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sk->sk_state = BT_LISTEN; 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdone: 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_sock(sk); 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int flags) 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DECLARE_WAITQUEUE(wait, current); 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sock *sk = sock->sk, *nsk; 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds long timeo; 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err = 0; 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 468dc2a0e20fbc85a71c63aa4330b496fda33f6bf80Gustavo Padovan lock_sock_nested(sk, SINGLE_DEPTH_NESTING); 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 470354d28d5f8546e115ebaae9311897f0bc4b6a8d4Marcel Holtmann if (sk->sk_type != SOCK_STREAM) { 471354d28d5f8546e115ebaae9311897f0bc4b6a8d4Marcel Holtmann err = -EINVAL; 472354d28d5f8546e115ebaae9311897f0bc4b6a8d4Marcel Holtmann goto done; 473354d28d5f8546e115ebaae9311897f0bc4b6a8d4Marcel Holtmann } 474354d28d5f8546e115ebaae9311897f0bc4b6a8d4Marcel Holtmann 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK); 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BT_DBG("sk %p timeo %ld", sk, timeo); 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Wait for an incoming connection. (wake-one). */ 480aa395145165cb06a0d0885221bbe0ce4a564391dEric Dumazet add_wait_queue_exclusive(sk_sleep(sk), &wait); 481950e2d51e866623e4c360280aa63b85ab66d3403Peter Hurley while (1) { 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_current_state(TASK_INTERRUPTIBLE); 483950e2d51e866623e4c360280aa63b85ab66d3403Peter Hurley 484950e2d51e866623e4c360280aa63b85ab66d3403Peter Hurley if (sk->sk_state != BT_LISTEN) { 485950e2d51e866623e4c360280aa63b85ab66d3403Peter Hurley err = -EBADFD; 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 489950e2d51e866623e4c360280aa63b85ab66d3403Peter Hurley nsk = bt_accept_dequeue(sk, newsock); 490950e2d51e866623e4c360280aa63b85ab66d3403Peter Hurley if (nsk) 491950e2d51e866623e4c360280aa63b85ab66d3403Peter Hurley break; 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 493950e2d51e866623e4c360280aa63b85ab66d3403Peter Hurley if (!timeo) { 494950e2d51e866623e4c360280aa63b85ab66d3403Peter Hurley err = -EAGAIN; 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (signal_pending(current)) { 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = sock_intr_errno(timeo); 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 502950e2d51e866623e4c360280aa63b85ab66d3403Peter Hurley 503950e2d51e866623e4c360280aa63b85ab66d3403Peter Hurley release_sock(sk); 504950e2d51e866623e4c360280aa63b85ab66d3403Peter Hurley timeo = schedule_timeout(timeo); 505dc2a0e20fbc85a71c63aa4330b496fda33f6bf80Gustavo Padovan lock_sock_nested(sk, SINGLE_DEPTH_NESTING); 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 507950e2d51e866623e4c360280aa63b85ab66d3403Peter Hurley __set_current_state(TASK_RUNNING); 508aa395145165cb06a0d0885221bbe0ce4a564391dEric Dumazet remove_wait_queue(sk_sleep(sk), &wait); 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (err) 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto done; 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds newsock->state = SS_CONNECTED; 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BT_DBG("new socket %p", nsk); 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdone: 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_sock(sk); 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int rfcomm_sock_getname(struct socket *sock, struct sockaddr *addr, int *len, int peer) 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sockaddr_rc *sa = (struct sockaddr_rc *) addr; 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sock *sk = sock->sk; 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BT_DBG("sock %p, sk %p", sock, sk); 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5299344a972961d1a6d2c04d9008b13617bcb6ec2efMathias Krause memset(sa, 0, sizeof(*sa)); 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sa->rc_family = AF_BLUETOOTH; 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sa->rc_channel = rfcomm_pi(sk)->channel; 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (peer) 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bacpy(&sa->rc_bdaddr, &bt_sk(sk)->dst); 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bacpy(&sa->rc_bdaddr, &bt_sk(sk)->src); 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *len = sizeof(struct sockaddr_rc); 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int rfcomm_sock_sendmsg(struct kiocb *iocb, struct socket *sock, 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct msghdr *msg, size_t len) 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sock *sk = sock->sk; 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct rfcomm_dlc *d = rfcomm_pi(sk)->dlc; 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *skb; 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int sent = 0; 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 549bb23c0ab824653be4aa7dfca15b07b3059717004Marcel Holtmann if (test_bit(RFCOMM_DEFER_SETUP, &d->flags)) 550bb23c0ab824653be4aa7dfca15b07b3059717004Marcel Holtmann return -ENOTCONN; 551bb23c0ab824653be4aa7dfca15b07b3059717004Marcel Holtmann 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (msg->msg_flags & MSG_OOB) 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EOPNOTSUPP; 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sk->sk_shutdown & SEND_SHUTDOWN) 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPIPE; 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BT_DBG("sock %p, sk %p", sock, sk); 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_sock(sk); 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (len) { 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size_t size = min_t(size_t, len, d->mtu); 5644d6a2188bd456969f52c03edf1988de90f08d9f5Marcel Holtmann int err; 5658e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb = sock_alloc_send_skb(sk, size + RFCOMM_SKB_RESERVE, 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds msg->msg_flags & MSG_DONTWAIT, &err); 56891aa35a5aa3540223066bf6b51c935418c63a35dVictor Shcherbatyuk if (!skb) { 56991aa35a5aa3540223066bf6b51c935418c63a35dVictor Shcherbatyuk if (sent == 0) 57091aa35a5aa3540223066bf6b51c935418c63a35dVictor Shcherbatyuk sent = err; 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 57291aa35a5aa3540223066bf6b51c935418c63a35dVictor Shcherbatyuk } 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_reserve(skb, RFCOMM_SKB_HEAD_RESERVE); 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size); 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (err) { 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree_skb(skb); 5784d6a2188bd456969f52c03edf1988de90f08d9f5Marcel Holtmann if (sent == 0) 5794d6a2188bd456969f52c03edf1988de90f08d9f5Marcel Holtmann sent = err; 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 583262038fcb2a50e9b5553243452918fda08cdf83dLuiz Augusto von Dentz skb->priority = sk->sk_priority; 584262038fcb2a50e9b5553243452918fda08cdf83dLuiz Augusto von Dentz 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = rfcomm_dlc_send(d, skb); 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (err < 0) { 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree_skb(skb); 5884d6a2188bd456969f52c03edf1988de90f08d9f5Marcel Holtmann if (sent == 0) 5894d6a2188bd456969f52c03edf1988de90f08d9f5Marcel Holtmann sent = err; 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sent += size; 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len -= size; 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_sock(sk); 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5994d6a2188bd456969f52c03edf1988de90f08d9f5Marcel Holtmann return sent; 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int rfcomm_sock_recvmsg(struct kiocb *iocb, struct socket *sock, 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct msghdr *msg, size_t size, int flags) 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sock *sk = sock->sk; 606bb23c0ab824653be4aa7dfca15b07b3059717004Marcel Holtmann struct rfcomm_dlc *d = rfcomm_pi(sk)->dlc; 6073d7d01dffec4a6757ed1e3182f01c7ef5caa2539Mat Martineau int len; 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 609bb23c0ab824653be4aa7dfca15b07b3059717004Marcel Holtmann if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) { 610bb23c0ab824653be4aa7dfca15b07b3059717004Marcel Holtmann rfcomm_dlc_accept(d); 611e11e0455c0d7d3d62276a0c55d9dfbc16779d691Mathias Krause msg->msg_namelen = 0; 612bb23c0ab824653be4aa7dfca15b07b3059717004Marcel Holtmann return 0; 613bb23c0ab824653be4aa7dfca15b07b3059717004Marcel Holtmann } 614bb23c0ab824653be4aa7dfca15b07b3059717004Marcel Holtmann 6153d7d01dffec4a6757ed1e3182f01c7ef5caa2539Mat Martineau len = bt_sock_stream_recvmsg(iocb, sock, msg, size, flags); 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_sock(sk); 6183d7d01dffec4a6757ed1e3182f01c7ef5caa2539Mat Martineau if (!(flags & MSG_PEEK) && len > 0) 6193d7d01dffec4a6757ed1e3182f01c7ef5caa2539Mat Martineau atomic_sub(len, &sk->sk_rmem_alloc); 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (atomic_read(&sk->sk_rmem_alloc) <= (sk->sk_rcvbuf >> 2)) 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rfcomm_dlc_unthrottle(rfcomm_pi(sk)->dlc); 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_sock(sk); 6243d7d01dffec4a6757ed1e3182f01c7ef5caa2539Mat Martineau 6253d7d01dffec4a6757ed1e3182f01c7ef5caa2539Mat Martineau return len; 6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 628b7058842c940ad2c08dd829b21e5c92ebe3b8758David S. Millerstatic int rfcomm_sock_setsockopt_old(struct socket *sock, int optname, char __user *optval, unsigned int optlen) 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sock *sk = sock->sk; 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err = 0; 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 opt; 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BT_DBG("sk %p", sk); 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_sock(sk); 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (optname) { 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case RFCOMM_LM: 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (get_user(opt, (u32 __user *) optval)) { 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = -EFAULT; 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6459f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann if (opt & RFCOMM_LM_AUTH) 6469f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann rfcomm_pi(sk)->sec_level = BT_SECURITY_LOW; 6479f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann if (opt & RFCOMM_LM_ENCRYPT) 6489f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann rfcomm_pi(sk)->sec_level = BT_SECURITY_MEDIUM; 6499f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann if (opt & RFCOMM_LM_SECURE) 6509f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann rfcomm_pi(sk)->sec_level = BT_SECURITY_HIGH; 6519f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann 6529f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann rfcomm_pi(sk)->role_switch = (opt & RFCOMM_LM_MASTER); 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = -ENOPROTOOPT; 6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_sock(sk); 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 664b7058842c940ad2c08dd829b21e5c92ebe3b8758David S. Millerstatic int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen) 665d58daf42d29a3a4a4d4be46cf47ceee096789680Marcel Holtmann{ 666d58daf42d29a3a4a4d4be46cf47ceee096789680Marcel Holtmann struct sock *sk = sock->sk; 6679f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann struct bt_security sec; 668d0fad89da9801b3945d2ee7243ecbc75b3da6f09Stephen Boyd int err = 0; 669d0fad89da9801b3945d2ee7243ecbc75b3da6f09Stephen Boyd size_t len; 670bb23c0ab824653be4aa7dfca15b07b3059717004Marcel Holtmann u32 opt; 671d58daf42d29a3a4a4d4be46cf47ceee096789680Marcel Holtmann 672d58daf42d29a3a4a4d4be46cf47ceee096789680Marcel Holtmann BT_DBG("sk %p", sk); 673d58daf42d29a3a4a4d4be46cf47ceee096789680Marcel Holtmann 674d58daf42d29a3a4a4d4be46cf47ceee096789680Marcel Holtmann if (level == SOL_RFCOMM) 675d58daf42d29a3a4a4d4be46cf47ceee096789680Marcel Holtmann return rfcomm_sock_setsockopt_old(sock, optname, optval, optlen); 676d58daf42d29a3a4a4d4be46cf47ceee096789680Marcel Holtmann 6770588d94fd7e414367a7ae517569d2222441c255fMarcel Holtmann if (level != SOL_BLUETOOTH) 6780588d94fd7e414367a7ae517569d2222441c255fMarcel Holtmann return -ENOPROTOOPT; 6790588d94fd7e414367a7ae517569d2222441c255fMarcel Holtmann 680d58daf42d29a3a4a4d4be46cf47ceee096789680Marcel Holtmann lock_sock(sk); 681d58daf42d29a3a4a4d4be46cf47ceee096789680Marcel Holtmann 682d58daf42d29a3a4a4d4be46cf47ceee096789680Marcel Holtmann switch (optname) { 6839f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann case BT_SECURITY: 6840588d94fd7e414367a7ae517569d2222441c255fMarcel Holtmann if (sk->sk_type != SOCK_STREAM) { 6850588d94fd7e414367a7ae517569d2222441c255fMarcel Holtmann err = -EINVAL; 6860588d94fd7e414367a7ae517569d2222441c255fMarcel Holtmann break; 6870588d94fd7e414367a7ae517569d2222441c255fMarcel Holtmann } 6880588d94fd7e414367a7ae517569d2222441c255fMarcel Holtmann 6899f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann sec.level = BT_SECURITY_LOW; 6909f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann 6919f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann len = min_t(unsigned int, sizeof(sec), optlen); 6929f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann if (copy_from_user((char *) &sec, optval, len)) { 6939f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann err = -EFAULT; 6949f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann break; 6959f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann } 6969f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann 6979f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann if (sec.level > BT_SECURITY_HIGH) { 6989f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann err = -EINVAL; 6999f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann break; 7009f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann } 7019f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann 7029f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann rfcomm_pi(sk)->sec_level = sec.level; 7039f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann break; 7049f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann 705bb23c0ab824653be4aa7dfca15b07b3059717004Marcel Holtmann case BT_DEFER_SETUP: 706bb23c0ab824653be4aa7dfca15b07b3059717004Marcel Holtmann if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) { 707bb23c0ab824653be4aa7dfca15b07b3059717004Marcel Holtmann err = -EINVAL; 708bb23c0ab824653be4aa7dfca15b07b3059717004Marcel Holtmann break; 709bb23c0ab824653be4aa7dfca15b07b3059717004Marcel Holtmann } 710bb23c0ab824653be4aa7dfca15b07b3059717004Marcel Holtmann 711bb23c0ab824653be4aa7dfca15b07b3059717004Marcel Holtmann if (get_user(opt, (u32 __user *) optval)) { 712bb23c0ab824653be4aa7dfca15b07b3059717004Marcel Holtmann err = -EFAULT; 713bb23c0ab824653be4aa7dfca15b07b3059717004Marcel Holtmann break; 714bb23c0ab824653be4aa7dfca15b07b3059717004Marcel Holtmann } 715bb23c0ab824653be4aa7dfca15b07b3059717004Marcel Holtmann 716c5daa683f2d3315cd766f550ef7d88bfca1671f4Gustavo Padovan if (opt) 717c5daa683f2d3315cd766f550ef7d88bfca1671f4Gustavo Padovan set_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags); 718c5daa683f2d3315cd766f550ef7d88bfca1671f4Gustavo Padovan else 719c5daa683f2d3315cd766f550ef7d88bfca1671f4Gustavo Padovan clear_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags); 720c5daa683f2d3315cd766f550ef7d88bfca1671f4Gustavo Padovan 721bb23c0ab824653be4aa7dfca15b07b3059717004Marcel Holtmann break; 722bb23c0ab824653be4aa7dfca15b07b3059717004Marcel Holtmann 723d58daf42d29a3a4a4d4be46cf47ceee096789680Marcel Holtmann default: 724d58daf42d29a3a4a4d4be46cf47ceee096789680Marcel Holtmann err = -ENOPROTOOPT; 725d58daf42d29a3a4a4d4be46cf47ceee096789680Marcel Holtmann break; 726d58daf42d29a3a4a4d4be46cf47ceee096789680Marcel Holtmann } 727d58daf42d29a3a4a4d4be46cf47ceee096789680Marcel Holtmann 728d58daf42d29a3a4a4d4be46cf47ceee096789680Marcel Holtmann release_sock(sk); 729d58daf42d29a3a4a4d4be46cf47ceee096789680Marcel Holtmann return err; 730d58daf42d29a3a4a4d4be46cf47ceee096789680Marcel Holtmann} 731d58daf42d29a3a4a4d4be46cf47ceee096789680Marcel Holtmann 732d58daf42d29a3a4a4d4be46cf47ceee096789680Marcel Holtmannstatic int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __user *optval, int __user *optlen) 7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sock *sk = sock->sk; 7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct rfcomm_conninfo cinfo; 7368c1d787be4b62d2d1b6f04953eca4bcf7c839d44Gustavo Padovan struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn; 7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int len, err = 0; 7389f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann u32 opt; 7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BT_DBG("sk %p", sk); 7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (get_user(len, optlen)) 7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_sock(sk); 7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (optname) { 7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case RFCOMM_LM: 7499f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann switch (rfcomm_pi(sk)->sec_level) { 7509f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann case BT_SECURITY_LOW: 7519f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann opt = RFCOMM_LM_AUTH; 7529f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann break; 7539f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann case BT_SECURITY_MEDIUM: 7549f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann opt = RFCOMM_LM_AUTH | RFCOMM_LM_ENCRYPT; 7559f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann break; 7569f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann case BT_SECURITY_HIGH: 7579f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann opt = RFCOMM_LM_AUTH | RFCOMM_LM_ENCRYPT | 7589f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann RFCOMM_LM_SECURE; 7599f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann break; 7609f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann default: 7619f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann opt = 0; 7629f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann break; 7639f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann } 7649f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann 7659f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann if (rfcomm_pi(sk)->role_switch) 7669f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann opt |= RFCOMM_LM_MASTER; 7679f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann 7689f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann if (put_user(opt, (u32 __user *) optval)) 7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = -EFAULT; 7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case RFCOMM_CONNINFO: 773bb23c0ab824653be4aa7dfca15b07b3059717004Marcel Holtmann if (sk->sk_state != BT_CONNECTED && 774bb23c0ab824653be4aa7dfca15b07b3059717004Marcel Holtmann !rfcomm_pi(sk)->dlc->defer_setup) { 7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = -ENOTCONN; 7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7798d03e971cf403305217b8e62db3a2e5ad2d6263fFilip Palian memset(&cinfo, 0, sizeof(cinfo)); 7808c1d787be4b62d2d1b6f04953eca4bcf7c839d44Gustavo Padovan cinfo.hci_handle = conn->hcon->handle; 7818c1d787be4b62d2d1b6f04953eca4bcf7c839d44Gustavo Padovan memcpy(cinfo.dev_class, conn->hcon->dev_class, 3); 7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = min_t(unsigned int, len, sizeof(cinfo)); 7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_to_user(optval, (char *) &cinfo, len)) 7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = -EFAULT; 7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = -ENOPROTOOPT; 7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_sock(sk); 795d58daf42d29a3a4a4d4be46cf47ceee096789680Marcel Holtmann return err; 796d58daf42d29a3a4a4d4be46cf47ceee096789680Marcel Holtmann} 797d58daf42d29a3a4a4d4be46cf47ceee096789680Marcel Holtmann 798d58daf42d29a3a4a4d4be46cf47ceee096789680Marcel Holtmannstatic int rfcomm_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen) 799d58daf42d29a3a4a4d4be46cf47ceee096789680Marcel Holtmann{ 800d58daf42d29a3a4a4d4be46cf47ceee096789680Marcel Holtmann struct sock *sk = sock->sk; 8019f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann struct bt_security sec; 802d58daf42d29a3a4a4d4be46cf47ceee096789680Marcel Holtmann int len, err = 0; 803d58daf42d29a3a4a4d4be46cf47ceee096789680Marcel Holtmann 804d58daf42d29a3a4a4d4be46cf47ceee096789680Marcel Holtmann BT_DBG("sk %p", sk); 805d58daf42d29a3a4a4d4be46cf47ceee096789680Marcel Holtmann 806d58daf42d29a3a4a4d4be46cf47ceee096789680Marcel Holtmann if (level == SOL_RFCOMM) 807d58daf42d29a3a4a4d4be46cf47ceee096789680Marcel Holtmann return rfcomm_sock_getsockopt_old(sock, optname, optval, optlen); 808d58daf42d29a3a4a4d4be46cf47ceee096789680Marcel Holtmann 8090588d94fd7e414367a7ae517569d2222441c255fMarcel Holtmann if (level != SOL_BLUETOOTH) 8100588d94fd7e414367a7ae517569d2222441c255fMarcel Holtmann return -ENOPROTOOPT; 8110588d94fd7e414367a7ae517569d2222441c255fMarcel Holtmann 812d58daf42d29a3a4a4d4be46cf47ceee096789680Marcel Holtmann if (get_user(len, optlen)) 813d58daf42d29a3a4a4d4be46cf47ceee096789680Marcel Holtmann return -EFAULT; 814d58daf42d29a3a4a4d4be46cf47ceee096789680Marcel Holtmann 815d58daf42d29a3a4a4d4be46cf47ceee096789680Marcel Holtmann lock_sock(sk); 816d58daf42d29a3a4a4d4be46cf47ceee096789680Marcel Holtmann 817d58daf42d29a3a4a4d4be46cf47ceee096789680Marcel Holtmann switch (optname) { 8189f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann case BT_SECURITY: 8190588d94fd7e414367a7ae517569d2222441c255fMarcel Holtmann if (sk->sk_type != SOCK_STREAM) { 8200588d94fd7e414367a7ae517569d2222441c255fMarcel Holtmann err = -EINVAL; 8210588d94fd7e414367a7ae517569d2222441c255fMarcel Holtmann break; 8220588d94fd7e414367a7ae517569d2222441c255fMarcel Holtmann } 8230588d94fd7e414367a7ae517569d2222441c255fMarcel Holtmann 8249f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann sec.level = rfcomm_pi(sk)->sec_level; 8259ad2de43f1aee7e7274a4e0d41465489299e344bMathias Krause sec.key_size = 0; 8269f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann 8279f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann len = min_t(unsigned int, len, sizeof(sec)); 8289f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann if (copy_to_user(optval, (char *) &sec, len)) 8299f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann err = -EFAULT; 8309f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann 8319f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann break; 8329f2c8a03fbb3048cf38b158f87aa0c3c09bca084Marcel Holtmann 833bb23c0ab824653be4aa7dfca15b07b3059717004Marcel Holtmann case BT_DEFER_SETUP: 834bb23c0ab824653be4aa7dfca15b07b3059717004Marcel Holtmann if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) { 835bb23c0ab824653be4aa7dfca15b07b3059717004Marcel Holtmann err = -EINVAL; 836bb23c0ab824653be4aa7dfca15b07b3059717004Marcel Holtmann break; 837bb23c0ab824653be4aa7dfca15b07b3059717004Marcel Holtmann } 838bb23c0ab824653be4aa7dfca15b07b3059717004Marcel Holtmann 839c5daa683f2d3315cd766f550ef7d88bfca1671f4Gustavo Padovan if (put_user(test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags), 840c5daa683f2d3315cd766f550ef7d88bfca1671f4Gustavo Padovan (u32 __user *) optval)) 841bb23c0ab824653be4aa7dfca15b07b3059717004Marcel Holtmann err = -EFAULT; 842bb23c0ab824653be4aa7dfca15b07b3059717004Marcel Holtmann 843bb23c0ab824653be4aa7dfca15b07b3059717004Marcel Holtmann break; 844bb23c0ab824653be4aa7dfca15b07b3059717004Marcel Holtmann 845d58daf42d29a3a4a4d4be46cf47ceee096789680Marcel Holtmann default: 846d58daf42d29a3a4a4d4be46cf47ceee096789680Marcel Holtmann err = -ENOPROTOOPT; 847d58daf42d29a3a4a4d4be46cf47ceee096789680Marcel Holtmann break; 848d58daf42d29a3a4a4d4be46cf47ceee096789680Marcel Holtmann } 849d58daf42d29a3a4a4d4be46cf47ceee096789680Marcel Holtmann 850d58daf42d29a3a4a4d4be46cf47ceee096789680Marcel Holtmann release_sock(sk); 8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int rfcomm_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) 8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 856e19caae7177fcc732ae1b47135e39f577352adb2David S. Miller struct sock *sk __maybe_unused = sock->sk; 8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err; 8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 859e19caae7177fcc732ae1b47135e39f577352adb2David S. Miller BT_DBG("sk %p cmd %x arg %lx", sk, cmd, arg); 8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8613241ad820dbb172021e0268b5611031991431626Marcel Holtmann err = bt_sock_ioctl(sock, cmd, arg); 8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8633241ad820dbb172021e0268b5611031991431626Marcel Holtmann if (err == -ENOIOCTLCMD) { 8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_BT_RFCOMM_TTY 8653241ad820dbb172021e0268b5611031991431626Marcel Holtmann lock_sock(sk); 8663241ad820dbb172021e0268b5611031991431626Marcel Holtmann err = rfcomm_dev_ioctl(sk, cmd, (void __user *) arg); 8673241ad820dbb172021e0268b5611031991431626Marcel Holtmann release_sock(sk); 8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 8693241ad820dbb172021e0268b5611031991431626Marcel Holtmann err = -EOPNOTSUPP; 8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 8713241ad820dbb172021e0268b5611031991431626Marcel Holtmann } 8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int rfcomm_sock_shutdown(struct socket *sock, int how) 8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sock *sk = sock->sk; 8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err = 0; 8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BT_DBG("sock %p, sk %p", sock, sk); 8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 883285b4e90318dcf421a00b2ac3fe8ab713f3281e3Andrei Emeltchenko if (!sk) 884285b4e90318dcf421a00b2ac3fe8ab713f3281e3Andrei Emeltchenko return 0; 8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_sock(sk); 8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!sk->sk_shutdown) { 8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sk->sk_shutdown = SHUTDOWN_MASK; 8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __rfcomm_sock_close(sk); 8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime) 8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime); 8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_sock(sk); 8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int rfcomm_sock_release(struct socket *sock) 8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sock *sk = sock->sk; 9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err; 9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BT_DBG("sock %p, sk %p", sock, sk); 9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!sk) 9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = rfcomm_sock_shutdown(sock, 2); 9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sock_orphan(sk); 9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rfcomm_sock_kill(sk); 9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9158e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki/* ---- RFCOMM core layer callbacks ---- 9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * called under rfcomm_lock() 9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc **d) 9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sock *sk, *parent; 9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bdaddr_t src, dst; 9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int result = 0; 9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BT_DBG("session %p channel %d", s, channel); 9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rfcomm_session_getaddr(s, &src, &dst); 9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Check if we have socket listening on channel */ 9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds parent = rfcomm_get_sock_by_channel(BT_LISTEN, channel, &src); 9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!parent) 9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 934eeb366564be7c311b31c70821d18a43a8a57f9bcGustavo Padovan bh_lock_sock(parent); 935eeb366564be7c311b31c70821d18a43a8a57f9bcGustavo Padovan 9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Check for backlog size */ 9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sk_acceptq_is_full(parent)) { 9388e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki BT_DBG("backlog full %d", parent->sk_ack_backlog); 9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto done; 9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9423b1e0a655f8eba44ab1ee2a1068d169ccfb853b9YOSHIFUJI Hideaki sk = rfcomm_sock_alloc(sock_net(parent), NULL, BTPROTO_RFCOMM, GFP_ATOMIC); 9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!sk) 9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto done; 9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 946b5a30dda6598af216c070165ece6068f9f00f33aOctavian Purdila bt_sock_reclassify_lock(sk, BTPROTO_RFCOMM); 947b5a30dda6598af216c070165ece6068f9f00f33aOctavian Purdila 9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rfcomm_sock_init(sk, parent); 9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bacpy(&bt_sk(sk)->src, &src); 9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bacpy(&bt_sk(sk)->dst, &dst); 9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rfcomm_pi(sk)->channel = channel; 9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sk->sk_state = BT_CONFIG; 9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bt_accept_enqueue(parent, sk); 9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Accept connection and return socket DLC */ 9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *d = rfcomm_pi(sk)->dlc; 9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = 1; 9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdone: 9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bh_unlock_sock(parent); 962bb23c0ab824653be4aa7dfca15b07b3059717004Marcel Holtmann 963c5daa683f2d3315cd766f550ef7d88bfca1671f4Gustavo Padovan if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags)) 964bb23c0ab824653be4aa7dfca15b07b3059717004Marcel Holtmann parent->sk_state_change(parent); 965bb23c0ab824653be4aa7dfca15b07b3059717004Marcel Holtmann 9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return result; 9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 969aef7d97cc604309b66f6f45cce02cd734934cd4eMarcel Holtmannstatic int rfcomm_sock_debugfs_show(struct seq_file *f, void *p) 9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sock *sk; 9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 97395ca83f42fb5f5bf789b514635f79242afe555d1Gustavo Padovan read_lock(&rfcomm_sk_list.lock); 9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 975b67bfe0d42cac56c512dd5da4b1b347a23f4b70aSasha Levin sk_for_each(sk, &rfcomm_sk_list.head) { 976fcb73338ed531dcc00cb17ca76fe3e05f774e4e9Andrei Emeltchenko seq_printf(f, "%pMR %pMR %d %d\n", 977fcb73338ed531dcc00cb17ca76fe3e05f774e4e9Andrei Emeltchenko &bt_sk(sk)->src, &bt_sk(sk)->dst, 978fcb73338ed531dcc00cb17ca76fe3e05f774e4e9Andrei Emeltchenko sk->sk_state, rfcomm_pi(sk)->channel); 979be9d122730c878baafe11e70d1436faac229f2fcMarcel Holtmann } 9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 98195ca83f42fb5f5bf789b514635f79242afe555d1Gustavo Padovan read_unlock(&rfcomm_sk_list.lock); 9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 983aef7d97cc604309b66f6f45cce02cd734934cd4eMarcel Holtmann return 0; 9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 986aef7d97cc604309b66f6f45cce02cd734934cd4eMarcel Holtmannstatic int rfcomm_sock_debugfs_open(struct inode *inode, struct file *file) 987aef7d97cc604309b66f6f45cce02cd734934cd4eMarcel Holtmann{ 988aef7d97cc604309b66f6f45cce02cd734934cd4eMarcel Holtmann return single_open(file, rfcomm_sock_debugfs_show, inode->i_private); 989aef7d97cc604309b66f6f45cce02cd734934cd4eMarcel Holtmann} 990aef7d97cc604309b66f6f45cce02cd734934cd4eMarcel Holtmann 991aef7d97cc604309b66f6f45cce02cd734934cd4eMarcel Holtmannstatic const struct file_operations rfcomm_sock_debugfs_fops = { 992aef7d97cc604309b66f6f45cce02cd734934cd4eMarcel Holtmann .open = rfcomm_sock_debugfs_open, 993aef7d97cc604309b66f6f45cce02cd734934cd4eMarcel Holtmann .read = seq_read, 994aef7d97cc604309b66f6f45cce02cd734934cd4eMarcel Holtmann .llseek = seq_lseek, 995aef7d97cc604309b66f6f45cce02cd734934cd4eMarcel Holtmann .release = single_release, 996aef7d97cc604309b66f6f45cce02cd734934cd4eMarcel Holtmann}; 997aef7d97cc604309b66f6f45cce02cd734934cd4eMarcel Holtmann 998aef7d97cc604309b66f6f45cce02cd734934cd4eMarcel Holtmannstatic struct dentry *rfcomm_sock_debugfs; 9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 100090ddc4f0470427df306f308ad03db6b6b21644b8Eric Dumazetstatic const struct proto_ops rfcomm_sock_ops = { 10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .family = PF_BLUETOOTH, 10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .owner = THIS_MODULE, 10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .release = rfcomm_sock_release, 10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .bind = rfcomm_sock_bind, 10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .connect = rfcomm_sock_connect, 10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .listen = rfcomm_sock_listen, 10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .accept = rfcomm_sock_accept, 10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .getname = rfcomm_sock_getname, 10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .sendmsg = rfcomm_sock_sendmsg, 10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .recvmsg = rfcomm_sock_recvmsg, 10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .shutdown = rfcomm_sock_shutdown, 10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .setsockopt = rfcomm_sock_setsockopt, 10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .getsockopt = rfcomm_sock_getsockopt, 10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .ioctl = rfcomm_sock_ioctl, 10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .poll = bt_sock_poll, 10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .socketpair = sock_no_socketpair, 10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .mmap = sock_no_mmap 10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1020ec1b4cf74c81bfd0fbe5bf62bafc86c45917e72fStephen Hemmingerstatic const struct net_proto_family rfcomm_sock_family_ops = { 10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .family = PF_BLUETOOTH, 10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .owner = THIS_MODULE, 10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .create = rfcomm_sock_create 10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1026be9d122730c878baafe11e70d1436faac229f2fcMarcel Holtmannint __init rfcomm_init_sockets(void) 10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err; 10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = proto_register(&rfcomm_proto, 0); 10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (err < 0) 10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = bt_sock_register(BTPROTO_RFCOMM, &rfcomm_sock_family_ops); 1035c6f5df16a2710e64090078dfbaa86c54a27c0874Masatake YAMATO if (err < 0) { 1036c6f5df16a2710e64090078dfbaa86c54a27c0874Masatake YAMATO BT_ERR("RFCOMM socket layer registration failed"); 1037c6f5df16a2710e64090078dfbaa86c54a27c0874Masatake YAMATO goto error; 1038c6f5df16a2710e64090078dfbaa86c54a27c0874Masatake YAMATO } 1039c6f5df16a2710e64090078dfbaa86c54a27c0874Masatake YAMATO 1040b03166152f6da91cec8b66837b309dd3923ea536Al Viro err = bt_procfs_init(&init_net, "rfcomm", &rfcomm_sk_list, NULL); 1041c6f5df16a2710e64090078dfbaa86c54a27c0874Masatake YAMATO if (err < 0) { 1042c6f5df16a2710e64090078dfbaa86c54a27c0874Masatake YAMATO BT_ERR("Failed to create RFCOMM proc file"); 1043c6f5df16a2710e64090078dfbaa86c54a27c0874Masatake YAMATO bt_sock_unregister(BTPROTO_RFCOMM); 10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto error; 1045c6f5df16a2710e64090078dfbaa86c54a27c0874Masatake YAMATO } 10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1047aef7d97cc604309b66f6f45cce02cd734934cd4eMarcel Holtmann if (bt_debugfs) { 1048aef7d97cc604309b66f6f45cce02cd734934cd4eMarcel Holtmann rfcomm_sock_debugfs = debugfs_create_file("rfcomm", 0444, 1049aef7d97cc604309b66f6f45cce02cd734934cd4eMarcel Holtmann bt_debugfs, NULL, &rfcomm_sock_debugfs_fops); 1050aef7d97cc604309b66f6f45cce02cd734934cd4eMarcel Holtmann if (!rfcomm_sock_debugfs) 1051aef7d97cc604309b66f6f45cce02cd734934cd4eMarcel Holtmann BT_ERR("Failed to create RFCOMM debug file"); 1052aef7d97cc604309b66f6f45cce02cd734934cd4eMarcel Holtmann } 10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BT_INFO("RFCOMM socket layer initialized"); 10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserror: 10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds proto_unregister(&rfcomm_proto); 10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10632f8362afcd2da8b313ec3cc04a50af19d3592972Gustavo Padovanvoid __exit rfcomm_cleanup_sockets(void) 10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1065c6f5df16a2710e64090078dfbaa86c54a27c0874Masatake YAMATO bt_procfs_cleanup(&init_net, "rfcomm"); 1066c6f5df16a2710e64090078dfbaa86c54a27c0874Masatake YAMATO 1067aef7d97cc604309b66f6f45cce02cd734934cd4eMarcel Holtmann debugfs_remove(rfcomm_sock_debugfs); 10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10695e9d7f868f04106139a58212b860dcdc268ad3afDavid Herrmann bt_sock_unregister(BTPROTO_RFCOMM); 10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds proto_unregister(&rfcomm_proto); 10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1073