18e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BNEP implementation for Linux Bluetooth stack (BlueZ). 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Copyright (C) 2001-2002 Inventel Systemes 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Written 2001-2002 by 596de0e252cedffad61b3cb5e05662c591898e69aJan Engelhardt Clément Moreau <clement.moreau@inventel.fr> 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds David Libault <david.libault@inventel.fr> 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Copyright (C) 2002 Maxim Krasnyansky <maxk@qualcomm.com> 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This program is free software; you can redistribute it and/or modify 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds it under the terms of the GNU General Public License version 2 as 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds published by the Free Software Foundation; 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY 188e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 198e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 208e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 238e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 248e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SOFTWARE IS DISCLAIMED. 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 29f4d7cd4a4c25cb4a5c30a675d4cc0052c93b925aSzymon Janc#include <linux/kthread.h> 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/file.h> 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/etherdevice.h> 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/unaligned.h> 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/bluetooth/bluetooth.h> 350a85b964e141a4b8db6eaf500ceace12f8f52f93Marcel Holtmann#include <net/bluetooth/hci_core.h> 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "bnep.h" 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3928111eb2f5087c5aa5ec3697388f6c7d354b2ad8Marcel Holtmann#define VERSION "1.3" 4028111eb2f5087c5aa5ec3697388f6c7d354b2ad8Marcel Holtmann 41eb93992207dadb946a3b5cf4544957dc924a6f58Rusty Russellstatic bool compress_src = true; 42eb93992207dadb946a3b5cf4544957dc924a6f58Rusty Russellstatic bool compress_dst = true; 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic LIST_HEAD(bnep_session_list); 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DECLARE_RWSEM(bnep_session_sem); 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct bnep_session *__bnep_get_session(u8 *dst) 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct bnep_session *s; 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BT_DBG(""); 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 538035ded466049ca2fe8c04564a0fa00f222abe3fLuiz Augusto von Dentz list_for_each_entry(s, &bnep_session_list, list) 54c47fc9814ca15cc075f1f09e8c069b041f2ea397Joe Perches if (ether_addr_equal(dst, s->eh.h_source)) 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return s; 568035ded466049ca2fe8c04564a0fa00f222abe3fLuiz Augusto von Dentz 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __bnep_link_session(struct bnep_session *s) 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 628e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki list_add(&s->list, &bnep_session_list); 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __bnep_unlink_session(struct bnep_session *s) 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_del(&s->list); 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int bnep_send(struct bnep_session *s, void *data, size_t len) 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct socket *sock = s->sock; 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct kvec iv = { data, len }; 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return kernel_sendmsg(sock, &s->msg, &iv, 1, len); 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int bnep_send_rsp(struct bnep_session *s, u8 ctrl, u16 resp) 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct bnep_control_rsp rsp; 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rsp.type = BNEP_CONTROL; 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rsp.ctrl = ctrl; 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rsp.resp = htons(resp); 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return bnep_send(s, &rsp, sizeof(rsp)); 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_BT_BNEP_PROTO_FILTER 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void bnep_set_default_proto_filter(struct bnep_session *s) 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* (IPv4, ARP) */ 91e41d21697326a38a0a871c515db88fa310177e24Al Viro s->proto_filter[0].start = ETH_P_IP; 92e41d21697326a38a0a871c515db88fa310177e24Al Viro s->proto_filter[0].end = ETH_P_ARP; 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* (RARP, AppleTalk) */ 94e41d21697326a38a0a871c515db88fa310177e24Al Viro s->proto_filter[1].start = ETH_P_RARP; 95e41d21697326a38a0a871c515db88fa310177e24Al Viro s->proto_filter[1].end = ETH_P_AARP; 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* (IPX, IPv6) */ 97e41d21697326a38a0a871c515db88fa310177e24Al Viro s->proto_filter[2].start = ETH_P_IPX; 98e41d21697326a38a0a871c515db88fa310177e24Al Viro s->proto_filter[2].end = ETH_P_IPV6; 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1021bc5d4483a83349f143e2bbf23ec144cd7e21e89Al Virostatic int bnep_ctrl_set_netfilter(struct bnep_session *s, __be16 *data, int len) 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int n; 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (len < 2) 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EILSEQ; 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10983985319393973f280ca2a797047780a7955cf19Harvey Harrison n = get_unaligned_be16(data); 1103aad75a128e2f2b8da31de1df4b9b9b4a8f65c66Szymon Janc data++; 1113aad75a128e2f2b8da31de1df4b9b9b4a8f65c66Szymon Janc len -= 2; 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (len < n) 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EILSEQ; 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BT_DBG("filter len %d", n); 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_BT_BNEP_PROTO_FILTER 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds n /= 4; 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (n <= BNEP_MAX_PROTO_FILTERS) { 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct bnep_proto_filter *f = s->proto_filter; 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < n; i++) { 12583985319393973f280ca2a797047780a7955cf19Harvey Harrison f[i].start = get_unaligned_be16(data++); 12683985319393973f280ca2a797047780a7955cf19Harvey Harrison f[i].end = get_unaligned_be16(data++); 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BT_DBG("proto filter start %d end %d", 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds f[i].start, f[i].end); 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i < BNEP_MAX_PROTO_FILTERS) 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(f + i, 0, sizeof(*f)); 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (n == 0) 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bnep_set_default_proto_filter(s); 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bnep_send_rsp(s, BNEP_FILTER_NET_TYPE_RSP, BNEP_SUCCESS); 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bnep_send_rsp(s, BNEP_FILTER_NET_TYPE_RSP, BNEP_FILTER_LIMIT_REACHED); 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bnep_send_rsp(s, BNEP_FILTER_NET_TYPE_RSP, BNEP_FILTER_UNSUPPORTED_REQ); 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int bnep_ctrl_set_mcfilter(struct bnep_session *s, u8 *data, int len) 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int n; 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (len < 2) 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EILSEQ; 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15583985319393973f280ca2a797047780a7955cf19Harvey Harrison n = get_unaligned_be16(data); 1563aad75a128e2f2b8da31de1df4b9b9b4a8f65c66Szymon Janc data += 2; 1573aad75a128e2f2b8da31de1df4b9b9b4a8f65c66Szymon Janc len -= 2; 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (len < n) 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EILSEQ; 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BT_DBG("filter len %d", n); 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_BT_BNEP_MC_FILTER 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds n /= (ETH_ALEN * 2); 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (n > 0) { 168a3d9bd4c00f13defd4c0fdcf8b47f8764a69e54dSzymon Janc int i; 169a3d9bd4c00f13defd4c0fdcf8b47f8764a69e54dSzymon Janc 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->mc_filter = 0; 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Always send broadcast */ 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_bit(bnep_mc_hash(s->dev->broadcast), (ulong *) &s->mc_filter); 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Add address ranges to the multicast hash */ 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (; n > 0; n--) { 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 a1[6], *a2; 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1793aad75a128e2f2b8da31de1df4b9b9b4a8f65c66Szymon Janc memcpy(a1, data, ETH_ALEN); 1803aad75a128e2f2b8da31de1df4b9b9b4a8f65c66Szymon Janc data += ETH_ALEN; 1813aad75a128e2f2b8da31de1df4b9b9b4a8f65c66Szymon Janc a2 = data; 1823aad75a128e2f2b8da31de1df4b9b9b4a8f65c66Szymon Janc data += ETH_ALEN; 1838e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki 1846ed93dc6427d14cdfe0b272cc0a9ee4685ce9ad7Andrei Emeltchenko BT_DBG("mc filter %pMR -> %pMR", a1, a2); 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Iterate from a1 to a2 */ 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_bit(bnep_mc_hash(a1), (ulong *) &s->mc_filter); 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (memcmp(a1, a2, 6) < 0 && s->mc_filter != ~0LL) { 189a3d9bd4c00f13defd4c0fdcf8b47f8764a69e54dSzymon Janc /* Increment a1 */ 190a3d9bd4c00f13defd4c0fdcf8b47f8764a69e54dSzymon Janc i = 5; 191a3d9bd4c00f13defd4c0fdcf8b47f8764a69e54dSzymon Janc while (i >= 0 && ++a1[i--] == 0) 192a3d9bd4c00f13defd4c0fdcf8b47f8764a69e54dSzymon Janc ; 193a3d9bd4c00f13defd4c0fdcf8b47f8764a69e54dSzymon Janc 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_bit(bnep_mc_hash(a1), (ulong *) &s->mc_filter); 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BT_DBG("mc filter hash 0x%llx", s->mc_filter); 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bnep_send_rsp(s, BNEP_FILTER_MULTI_ADDR_RSP, BNEP_SUCCESS); 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bnep_send_rsp(s, BNEP_FILTER_MULTI_ADDR_RSP, BNEP_FILTER_UNSUPPORTED_REQ); 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int bnep_rx_control(struct bnep_session *s, void *data, int len) 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 cmd = *(u8 *)data; 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err = 0; 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2133aad75a128e2f2b8da31de1df4b9b9b4a8f65c66Szymon Janc data++; 2143aad75a128e2f2b8da31de1df4b9b9b4a8f65c66Szymon Janc len--; 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cmd) { 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case BNEP_CMD_NOT_UNDERSTOOD: 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case BNEP_SETUP_CONN_RSP: 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case BNEP_FILTER_NET_TYPE_RSP: 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case BNEP_FILTER_MULTI_ADDR_RSP: 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Ignore these for now */ 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case BNEP_FILTER_NET_TYPE_SET: 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = bnep_ctrl_set_netfilter(s, data, len); 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case BNEP_FILTER_MULTI_ADDR_SET: 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = bnep_ctrl_set_mcfilter(s, data, len); 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 232cde9f807f003676862178a6f28b52c7d431511edVikram Kandukuri case BNEP_SETUP_CONN_REQ: 233cde9f807f003676862178a6f28b52c7d431511edVikram Kandukuri err = bnep_send_rsp(s, BNEP_SETUP_CONN_RSP, BNEP_CONN_NOT_ALLOWED); 234cde9f807f003676862178a6f28b52c7d431511edVikram Kandukuri break; 235cde9f807f003676862178a6f28b52c7d431511edVikram Kandukuri 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: { 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 pkt[3]; 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pkt[0] = BNEP_CONTROL; 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pkt[1] = BNEP_CMD_NOT_UNDERSTOOD; 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pkt[2] = cmd; 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bnep_send(s, pkt, sizeof(pkt)); 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int bnep_rx_extension(struct bnep_session *s, struct sk_buff *skb) 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct bnep_ext_hdr *h; 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err = 0; 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do { 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds h = (void *) skb->data; 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!skb_pull(skb, sizeof(*h))) { 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = -EILSEQ; 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BT_DBG("type 0x%x len %d", h->type, h->len); 2628e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (h->type & BNEP_TYPE_MASK) { 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case BNEP_EXT_CONTROL: 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bnep_rx_control(s, skb->data, skb->len); 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Unknown extension, skip it. */ 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!skb_pull(skb, h->len)) { 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = -EILSEQ; 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } while (!err && (h->type & BNEP_EXT_HEADER)); 2788e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u8 __bnep_rx_hlen[] = { 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ETH_HLEN, /* BNEP_GENERAL */ 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0, /* BNEP_CONTROL */ 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2, /* BNEP_COMPRESSED */ 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ETH_ALEN + 2, /* BNEP_COMPRESSED_SRC_ONLY */ 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ETH_ALEN + 2 /* BNEP_COMPRESSED_DST_ONLY */ 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2906039aa73a1323edc2d6d93a22505d4dc28f38e3fGustavo Padovanstatic int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb) 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct net_device *dev = s->dev; 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *nskb; 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 type; 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 296b4d7f0a46bc0e30514b1779caff0fce6e424c4b5Stephen Hemminger dev->stats.rx_bytes += skb->len; 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2983aad75a128e2f2b8da31de1df4b9b9b4a8f65c66Szymon Janc type = *(u8 *) skb->data; 2993aad75a128e2f2b8da31de1df4b9b9b4a8f65c66Szymon Janc skb_pull(skb, 1); 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 301a3d9bd4c00f13defd4c0fdcf8b47f8764a69e54dSzymon Janc if ((type & BNEP_TYPE_MASK) >= sizeof(__bnep_rx_hlen)) 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto badframe; 3038e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((type & BNEP_TYPE_MASK) == BNEP_CONTROL) { 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bnep_rx_control(s, skb->data, skb->len); 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree_skb(skb); 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 310459a98ed881802dee55897441bc7f77af614368eArnaldo Carvalho de Melo skb_reset_mac_header(skb); 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Verify and pull out header */ 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!skb_pull(skb, __bnep_rx_hlen[type & BNEP_TYPE_MASK])) 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto badframe; 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3161bc5d4483a83349f143e2bbf23ec144cd7e21e89Al Viro s->eh.h_proto = get_unaligned((__be16 *) (skb->data - 2)); 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (type & BNEP_EXT_HEADER) { 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bnep_rx_extension(s, skb) < 0) 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto badframe; 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Strip 802.1p header */ 324000092b0b4793caf831f6016fa69d25abba31e51Eldad Zack if (ntohs(s->eh.h_proto) == ETH_P_8021Q) { 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!skb_pull(skb, 4)) 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto badframe; 3271bc5d4483a83349f143e2bbf23ec144cd7e21e89Al Viro s->eh.h_proto = get_unaligned((__be16 *) (skb->data - 2)); 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3298e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We have to alloc new skb and copy data here :(. Because original skb 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * may not be modified and because of the alignment requirements. */ 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nskb = alloc_skb(2 + ETH_HLEN + skb->len, GFP_KERNEL); 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!nskb) { 334b4d7f0a46bc0e30514b1779caff0fce6e424c4b5Stephen Hemminger dev->stats.rx_dropped++; 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree_skb(skb); 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_reserve(nskb, 2); 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Decompress header and construct ether frame */ 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (type & BNEP_TYPE_MASK) { 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case BNEP_COMPRESSED: 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(__skb_put(nskb, ETH_HLEN), &s->eh, ETH_HLEN); 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3458e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case BNEP_COMPRESSED_SRC_ONLY: 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(__skb_put(nskb, ETH_ALEN), s->eh.h_dest, ETH_ALEN); 34898e399f82ab3a6d863d1d4a7ea48925cc91c830eArnaldo Carvalho de Melo memcpy(__skb_put(nskb, ETH_ALEN), skb_mac_header(skb), ETH_ALEN); 3491bc5d4483a83349f143e2bbf23ec144cd7e21e89Al Viro put_unaligned(s->eh.h_proto, (__be16 *) __skb_put(nskb, 2)); 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case BNEP_COMPRESSED_DST_ONLY: 35398e399f82ab3a6d863d1d4a7ea48925cc91c830eArnaldo Carvalho de Melo memcpy(__skb_put(nskb, ETH_ALEN), skb_mac_header(skb), 3543aad75a128e2f2b8da31de1df4b9b9b4a8f65c66Szymon Janc ETH_ALEN); 35598e399f82ab3a6d863d1d4a7ea48925cc91c830eArnaldo Carvalho de Melo memcpy(__skb_put(nskb, ETH_ALEN + 2), s->eh.h_source, 3563aad75a128e2f2b8da31de1df4b9b9b4a8f65c66Szymon Janc ETH_ALEN + 2); 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case BNEP_GENERAL: 36098e399f82ab3a6d863d1d4a7ea48925cc91c830eArnaldo Carvalho de Melo memcpy(__skb_put(nskb, ETH_ALEN * 2), skb_mac_header(skb), 3613aad75a128e2f2b8da31de1df4b9b9b4a8f65c66Szymon Janc ETH_ALEN * 2); 3621bc5d4483a83349f143e2bbf23ec144cd7e21e89Al Viro put_unaligned(s->eh.h_proto, (__be16 *) __skb_put(nskb, 2)); 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 366d626f62b11e00c16e81e4308ab93d3f13551812aArnaldo Carvalho de Melo skb_copy_from_linear_data(skb, __skb_put(nskb, skb->len), skb->len); 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree_skb(skb); 3688e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki 369b4d7f0a46bc0e30514b1779caff0fce6e424c4b5Stephen Hemminger dev->stats.rx_packets++; 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nskb->ip_summed = CHECKSUM_NONE; 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nskb->protocol = eth_type_trans(nskb, dev); 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_rx_ni(nskb); 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsbadframe: 376b4d7f0a46bc0e30514b1779caff0fce6e424c4b5Stephen Hemminger dev->stats.rx_errors++; 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree_skb(skb); 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u8 __bnep_tx_types[] = { 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BNEP_GENERAL, 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BNEP_COMPRESSED_SRC_ONLY, 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BNEP_COMPRESSED_DST_ONLY, 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BNEP_COMPRESSED 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3886039aa73a1323edc2d6d93a22505d4dc28f38e3fGustavo Padovanstatic int bnep_tx_frame(struct bnep_session *s, struct sk_buff *skb) 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ethhdr *eh = (void *) skb->data; 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct socket *sock = s->sock; 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct kvec iv[3]; 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int len = 0, il = 0; 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 type = 0; 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BT_DBG("skb %p dev %p type %d", skb, skb->dev, skb->pkt_type); 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!skb->dev) { 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Control frame sent by us */ 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto send; 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iv[il++] = (struct kvec) { &type, 1 }; 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len++; 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 406c47fc9814ca15cc075f1f09e8c069b041f2ea397Joe Perches if (compress_src && ether_addr_equal(eh->h_dest, s->eh.h_source)) 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds type |= 0x01; 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 409c47fc9814ca15cc075f1f09e8c069b041f2ea397Joe Perches if (compress_dst && ether_addr_equal(eh->h_source, s->eh.h_dest)) 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds type |= 0x02; 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (type) 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_pull(skb, ETH_ALEN * 2); 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds type = __bnep_tx_types[type]; 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (type) { 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case BNEP_COMPRESSED_SRC_ONLY: 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iv[il++] = (struct kvec) { eh->h_source, ETH_ALEN }; 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len += ETH_ALEN; 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4218e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case BNEP_COMPRESSED_DST_ONLY: 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iv[il++] = (struct kvec) { eh->h_dest, ETH_ALEN }; 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len += ETH_ALEN; 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssend: 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iv[il++] = (struct kvec) { skb->data, skb->len }; 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len += skb->len; 4318e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* FIXME: linearize skb */ 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = kernel_sendmsg(sock, &s->msg, iv, il, len); 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree_skb(skb); 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (len > 0) { 439b4d7f0a46bc0e30514b1779caff0fce6e424c4b5Stephen Hemminger s->dev->stats.tx_bytes += len; 440b4d7f0a46bc0e30514b1779caff0fce6e424c4b5Stephen Hemminger s->dev->stats.tx_packets++; 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return len; 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int bnep_session(void *arg) 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct bnep_session *s = arg; 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct net_device *dev = s->dev; 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sock *sk = s->sock->sk; 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *skb; 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wait_queue_t wait; 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BT_DBG(""); 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_user_nice(current, -15); 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds init_waitqueue_entry(&wait, current); 460aa395145165cb06a0d0885221bbe0ce4a564391dEric Dumazet add_wait_queue(sk_sleep(sk), &wait); 46138d57555616afcdad7381b02b523d494327494cdPeter Hurley while (1) { 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_current_state(TASK_INTERRUPTIBLE); 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 464751c10a56802513a6b057c8cf1552cecc1c9afdePeter Hurley if (atomic_read(&s->terminate)) 46538d57555616afcdad7381b02b523d494327494cdPeter Hurley break; 4663aad75a128e2f2b8da31de1df4b9b9b4a8f65c66Szymon Janc /* RX */ 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while ((skb = skb_dequeue(&sk->sk_receive_queue))) { 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_orphan(skb); 469449357200c5d73d80a9c42dee5dafed684b3cd17Mat Martineau if (!skb_linearize(skb)) 470449357200c5d73d80a9c42dee5dafed684b3cd17Mat Martineau bnep_rx_frame(s, skb); 471449357200c5d73d80a9c42dee5dafed684b3cd17Mat Martineau else 472449357200c5d73d80a9c42dee5dafed684b3cd17Mat Martineau kfree_skb(skb); 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sk->sk_state != BT_CONNECTED) 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4778e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki 4783aad75a128e2f2b8da31de1df4b9b9b4a8f65c66Szymon Janc /* TX */ 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while ((skb = skb_dequeue(&sk->sk_write_queue))) 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bnep_tx_frame(s, skb)) 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_wake_queue(dev); 4838e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds schedule(); 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 48638d57555616afcdad7381b02b523d494327494cdPeter Hurley __set_current_state(TASK_RUNNING); 487aa395145165cb06a0d0885221bbe0ce4a564391dEric Dumazet remove_wait_queue(sk_sleep(sk), &wait); 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Cleanup session */ 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds down_write(&bnep_session_sem); 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Delete network device */ 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unregister_netdev(dev); 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 495ec8dab36e0738d3059980d144e34f16a26bbda7dMarcel Holtmann /* Wakeup user-space polling for socket errors */ 496ec8dab36e0738d3059980d144e34f16a26bbda7dMarcel Holtmann s->sock->sk->sk_err = EUNATCH; 497ec8dab36e0738d3059980d144e34f16a26bbda7dMarcel Holtmann 498aa395145165cb06a0d0885221bbe0ce4a564391dEric Dumazet wake_up_interruptible(sk_sleep(s->sock->sk)); 499ec8dab36e0738d3059980d144e34f16a26bbda7dMarcel Holtmann 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Release the socket */ 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fput(s->sock->file); 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __bnep_unlink_session(s); 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up_write(&bnep_session_sem); 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_netdev(dev); 5079b338c3dd12918f7f7df2b882f63f71e9efbcb41David Herrmann module_put_and_exit(0); 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5110a85b964e141a4b8db6eaf500ceace12f8f52f93Marcel Holtmannstatic struct device *bnep_get_device(struct bnep_session *session) 5120a85b964e141a4b8db6eaf500ceace12f8f52f93Marcel Holtmann{ 5130a85b964e141a4b8db6eaf500ceace12f8f52f93Marcel Holtmann bdaddr_t *src = &bt_sk(session->sock->sk)->src; 5140a85b964e141a4b8db6eaf500ceace12f8f52f93Marcel Holtmann bdaddr_t *dst = &bt_sk(session->sock->sk)->dst; 5150a85b964e141a4b8db6eaf500ceace12f8f52f93Marcel Holtmann struct hci_dev *hdev; 5160a85b964e141a4b8db6eaf500ceace12f8f52f93Marcel Holtmann struct hci_conn *conn; 5170a85b964e141a4b8db6eaf500ceace12f8f52f93Marcel Holtmann 5180a85b964e141a4b8db6eaf500ceace12f8f52f93Marcel Holtmann hdev = hci_get_route(dst, src); 5190a85b964e141a4b8db6eaf500ceace12f8f52f93Marcel Holtmann if (!hdev) 5200a85b964e141a4b8db6eaf500ceace12f8f52f93Marcel Holtmann return NULL; 5210a85b964e141a4b8db6eaf500ceace12f8f52f93Marcel Holtmann 5220a85b964e141a4b8db6eaf500ceace12f8f52f93Marcel Holtmann conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst); 5230a85b964e141a4b8db6eaf500ceace12f8f52f93Marcel Holtmann 5240a85b964e141a4b8db6eaf500ceace12f8f52f93Marcel Holtmann hci_dev_put(hdev); 5250a85b964e141a4b8db6eaf500ceace12f8f52f93Marcel Holtmann 526b2cfcd75df77b80d9cc3fa84190a350dfa79eb93Marcel Holtmann return conn ? &conn->dev : NULL; 5270a85b964e141a4b8db6eaf500ceace12f8f52f93Marcel Holtmann} 5280a85b964e141a4b8db6eaf500ceace12f8f52f93Marcel Holtmann 529384912ed194e43c03ad1cdaa09b0b1e488c34d46Marcel Holtmannstatic struct device_type bnep_type = { 530384912ed194e43c03ad1cdaa09b0b1e488c34d46Marcel Holtmann .name = "bluetooth", 531384912ed194e43c03ad1cdaa09b0b1e488c34d46Marcel Holtmann}; 532384912ed194e43c03ad1cdaa09b0b1e488c34d46Marcel Holtmann 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock) 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct net_device *dev; 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct bnep_session *s, *ss; 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 dst[ETH_ALEN], src[ETH_ALEN]; 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err; 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BT_DBG(""); 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds baswap((void *) dst, &bt_sk(sock->sk)->dst); 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds baswap((void *) src, &bt_sk(sock->sk)->src); 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* session struct allocated as private part of net_device */ 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev = alloc_netdev(sizeof(struct bnep_session), 5473aad75a128e2f2b8da31de1df4b9b9b4a8f65c66Szymon Janc (*req->device) ? req->device : "bnep%d", 5483aad75a128e2f2b8da31de1df4b9b9b4a8f65c66Szymon Janc bnep_net_setup); 54967b52e554ba973947704fcb4fc284d7bab9ab931Tobias Klauser if (!dev) 55067b52e554ba973947704fcb4fc284d7bab9ab931Tobias Klauser return -ENOMEM; 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds down_write(&bnep_session_sem); 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ss = __bnep_get_session(dst); 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ss && ss->state == BT_CONNECTED) { 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = -EEXIST; 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed; 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 560524ad0a79126efabf58d0a49eace6155ab5b4549Wang Chen s = netdev_priv(dev); 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* This is rx header therefore addresses are swapped. 5633aad75a128e2f2b8da31de1df4b9b9b4a8f65c66Szymon Janc * ie. eh.h_dest is our local address. */ 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(s->eh.h_dest, &src, ETH_ALEN); 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(s->eh.h_source, &dst, ETH_ALEN); 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(dev->dev_addr, s->eh.h_dest, ETH_ALEN); 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5680a85b964e141a4b8db6eaf500ceace12f8f52f93Marcel Holtmann s->dev = dev; 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->sock = sock; 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->role = req->role; 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->state = BT_CONNECTED; 5728e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->msg.msg_flags = MSG_NOSIGNAL; 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_BT_BNEP_MC_FILTER 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Set default mc filter */ 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_bit(bnep_mc_hash(dev->broadcast), (ulong *) &s->mc_filter); 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_BT_BNEP_PROTO_FILTER 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Set default protocol filter */ 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bnep_set_default_proto_filter(s); 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5850a85b964e141a4b8db6eaf500ceace12f8f52f93Marcel Holtmann SET_NETDEV_DEV(dev, bnep_get_device(s)); 586384912ed194e43c03ad1cdaa09b0b1e488c34d46Marcel Holtmann SET_NETDEV_DEVTYPE(dev, &bnep_type); 5870a85b964e141a4b8db6eaf500ceace12f8f52f93Marcel Holtmann 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = register_netdev(dev); 5893aad75a128e2f2b8da31de1df4b9b9b4a8f65c66Szymon Janc if (err) 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed; 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __bnep_link_session(s); 5938e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki 5949b338c3dd12918f7f7df2b882f63f71e9efbcb41David Herrmann __module_get(THIS_MODULE); 595f4d7cd4a4c25cb4a5c30a675d4cc0052c93b925aSzymon Janc s->task = kthread_run(bnep_session, s, "kbnepd %s", dev->name); 596f4d7cd4a4c25cb4a5c30a675d4cc0052c93b925aSzymon Janc if (IS_ERR(s->task)) { 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Session thread start failed, gotta cleanup. */ 5989b338c3dd12918f7f7df2b882f63f71e9efbcb41David Herrmann module_put(THIS_MODULE); 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unregister_netdev(dev); 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __bnep_unlink_session(s); 601f4d7cd4a4c25cb4a5c30a675d4cc0052c93b925aSzymon Janc err = PTR_ERR(s->task); 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed; 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up_write(&bnep_session_sem); 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcpy(req->device, dev->name); 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfailed: 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up_write(&bnep_session_sem); 6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_netdev(dev); 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint bnep_del_connection(struct bnep_conndel_req *req) 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct bnep_session *s; 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err = 0; 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BT_DBG(""); 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds down_read(&bnep_session_sem); 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s = __bnep_get_session(req->dst); 625751c10a56802513a6b057c8cf1552cecc1c9afdePeter Hurley if (s) { 626751c10a56802513a6b057c8cf1552cecc1c9afdePeter Hurley atomic_inc(&s->terminate); 627751c10a56802513a6b057c8cf1552cecc1c9afdePeter Hurley wake_up_process(s->task); 628751c10a56802513a6b057c8cf1552cecc1c9afdePeter Hurley } else 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = -ENOENT; 6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up_read(&bnep_session_sem); 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __bnep_copy_ci(struct bnep_conninfo *ci, struct bnep_session *s) 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6375520d20f68310fc158dcbbecfd5eac5cdfc5a241Vasiliy Kulikov memset(ci, 0, sizeof(*ci)); 6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(ci->dst, s->eh.h_source, ETH_ALEN); 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcpy(ci->device, s->dev->name); 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ci->flags = s->flags; 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ci->state = s->state; 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ci->role = s->role; 6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint bnep_get_connlist(struct bnep_connlist_req *req) 6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6478035ded466049ca2fe8c04564a0fa00f222abe3fLuiz Augusto von Dentz struct bnep_session *s; 6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err = 0, n = 0; 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds down_read(&bnep_session_sem); 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6528035ded466049ca2fe8c04564a0fa00f222abe3fLuiz Augusto von Dentz list_for_each_entry(s, &bnep_session_list, list) { 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct bnep_conninfo ci; 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __bnep_copy_ci(&ci, s); 6568e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki 6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_to_user(req->ci, &ci, sizeof(ci))) { 6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = -EFAULT; 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (++n >= req->cnum) 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req->ci++; 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds req->cnum = n; 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up_read(&bnep_session_sem); 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint bnep_get_conninfo(struct bnep_conninfo *ci) 6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct bnep_session *s; 6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err = 0; 6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds down_read(&bnep_session_sem); 6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s = __bnep_get_session(ci->dst); 6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (s) 6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __bnep_copy_ci(ci, s); 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = -ENOENT; 6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up_read(&bnep_session_sem); 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init bnep_init(void) 6918e87d14255acffeee36873de226dc25c11b5f46dYOSHIFUJI Hideaki{ 6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char flt[50] = ""; 6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_BT_BNEP_PROTO_FILTER 6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcat(flt, "protocol "); 6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_BT_BNEP_MC_FILTER 6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcat(flt, "multicast"); 7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BT_INFO("BNEP (Ethernet Emulation) ver %s", VERSION); 7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (flt[0]) 7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BT_INFO("BNEP filters: %s", flt); 7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bnep_sock_init(); 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit bnep_exit(void) 7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bnep_sock_cleanup(); 7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(bnep_init); 7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(bnep_exit); 7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 71828111eb2f5087c5aa5ec3697388f6c7d354b2ad8Marcel Holtmannmodule_param(compress_src, bool, 0644); 71928111eb2f5087c5aa5ec3697388f6c7d354b2ad8Marcel HoltmannMODULE_PARM_DESC(compress_src, "Compress sources headers"); 72028111eb2f5087c5aa5ec3697388f6c7d354b2ad8Marcel Holtmann 72128111eb2f5087c5aa5ec3697388f6c7d354b2ad8Marcel Holtmannmodule_param(compress_dst, bool, 0644); 72228111eb2f5087c5aa5ec3697388f6c7d354b2ad8Marcel HoltmannMODULE_PARM_DESC(compress_dst, "Compress destination headers"); 72328111eb2f5087c5aa5ec3697388f6c7d354b2ad8Marcel Holtmann 72463fbd24e5102eecfc9d049ed7f4be7f9a25f814fMarcel HoltmannMODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); 7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("Bluetooth BNEP ver " VERSION); 7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_VERSION(VERSION); 7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_ALIAS("bt-proto-4"); 729