1*1da177e4SLinus Torvalds /* 2*1da177e4SLinus Torvalds BNEP implementation for Linux Bluetooth stack (BlueZ). 3*1da177e4SLinus Torvalds Copyright (C) 2001-2002 Inventel Systemes 4*1da177e4SLinus Torvalds Written 2001-2002 by 5*1da177e4SLinus Torvalds Cl�ment Moreau <clement.moreau@inventel.fr> 6*1da177e4SLinus Torvalds David Libault <david.libault@inventel.fr> 7*1da177e4SLinus Torvalds 8*1da177e4SLinus Torvalds Copyright (C) 2002 Maxim Krasnyansky <maxk@qualcomm.com> 9*1da177e4SLinus Torvalds 10*1da177e4SLinus Torvalds This program is free software; you can redistribute it and/or modify 11*1da177e4SLinus Torvalds it under the terms of the GNU General Public License version 2 as 12*1da177e4SLinus Torvalds published by the Free Software Foundation; 13*1da177e4SLinus Torvalds 14*1da177e4SLinus Torvalds THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15*1da177e4SLinus Torvalds OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16*1da177e4SLinus Torvalds FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. 17*1da177e4SLinus Torvalds IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY 18*1da177e4SLinus Torvalds CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 19*1da177e4SLinus Torvalds WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 20*1da177e4SLinus Torvalds ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 21*1da177e4SLinus Torvalds OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 22*1da177e4SLinus Torvalds 23*1da177e4SLinus Torvalds ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 24*1da177e4SLinus Torvalds COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 25*1da177e4SLinus Torvalds SOFTWARE IS DISCLAIMED. 26*1da177e4SLinus Torvalds */ 27*1da177e4SLinus Torvalds 28*1da177e4SLinus Torvalds /* 29*1da177e4SLinus Torvalds * $Id: netdev.c,v 1.8 2002/08/04 21:23:58 maxk Exp $ 30*1da177e4SLinus Torvalds */ 31*1da177e4SLinus Torvalds 32*1da177e4SLinus Torvalds #include <linux/config.h> 33*1da177e4SLinus Torvalds #include <linux/module.h> 34*1da177e4SLinus Torvalds 35*1da177e4SLinus Torvalds #include <linux/socket.h> 36*1da177e4SLinus Torvalds #include <linux/netdevice.h> 37*1da177e4SLinus Torvalds #include <linux/etherdevice.h> 38*1da177e4SLinus Torvalds #include <linux/skbuff.h> 39*1da177e4SLinus Torvalds #include <linux/wait.h> 40*1da177e4SLinus Torvalds 41*1da177e4SLinus Torvalds #include <asm/unaligned.h> 42*1da177e4SLinus Torvalds 43*1da177e4SLinus Torvalds #include <net/bluetooth/bluetooth.h> 44*1da177e4SLinus Torvalds #include <net/bluetooth/hci_core.h> 45*1da177e4SLinus Torvalds #include <net/bluetooth/l2cap.h> 46*1da177e4SLinus Torvalds 47*1da177e4SLinus Torvalds #include "bnep.h" 48*1da177e4SLinus Torvalds 49*1da177e4SLinus Torvalds #ifndef CONFIG_BT_BNEP_DEBUG 50*1da177e4SLinus Torvalds #undef BT_DBG 51*1da177e4SLinus Torvalds #define BT_DBG( A... ) 52*1da177e4SLinus Torvalds #endif 53*1da177e4SLinus Torvalds 54*1da177e4SLinus Torvalds #define BNEP_TX_QUEUE_LEN 20 55*1da177e4SLinus Torvalds 56*1da177e4SLinus Torvalds static int bnep_net_open(struct net_device *dev) 57*1da177e4SLinus Torvalds { 58*1da177e4SLinus Torvalds netif_start_queue(dev); 59*1da177e4SLinus Torvalds return 0; 60*1da177e4SLinus Torvalds } 61*1da177e4SLinus Torvalds 62*1da177e4SLinus Torvalds static int bnep_net_close(struct net_device *dev) 63*1da177e4SLinus Torvalds { 64*1da177e4SLinus Torvalds netif_stop_queue(dev); 65*1da177e4SLinus Torvalds return 0; 66*1da177e4SLinus Torvalds } 67*1da177e4SLinus Torvalds 68*1da177e4SLinus Torvalds static struct net_device_stats *bnep_net_get_stats(struct net_device *dev) 69*1da177e4SLinus Torvalds { 70*1da177e4SLinus Torvalds struct bnep_session *s = dev->priv; 71*1da177e4SLinus Torvalds return &s->stats; 72*1da177e4SLinus Torvalds } 73*1da177e4SLinus Torvalds 74*1da177e4SLinus Torvalds static void bnep_net_set_mc_list(struct net_device *dev) 75*1da177e4SLinus Torvalds { 76*1da177e4SLinus Torvalds #ifdef CONFIG_BT_BNEP_MC_FILTER 77*1da177e4SLinus Torvalds struct bnep_session *s = dev->priv; 78*1da177e4SLinus Torvalds struct sock *sk = s->sock->sk; 79*1da177e4SLinus Torvalds struct bnep_set_filter_req *r; 80*1da177e4SLinus Torvalds struct sk_buff *skb; 81*1da177e4SLinus Torvalds int size; 82*1da177e4SLinus Torvalds 83*1da177e4SLinus Torvalds BT_DBG("%s mc_count %d", dev->name, dev->mc_count); 84*1da177e4SLinus Torvalds 85*1da177e4SLinus Torvalds size = sizeof(*r) + (BNEP_MAX_MULTICAST_FILTERS + 1) * ETH_ALEN * 2; 86*1da177e4SLinus Torvalds skb = alloc_skb(size, GFP_ATOMIC); 87*1da177e4SLinus Torvalds if (!skb) { 88*1da177e4SLinus Torvalds BT_ERR("%s Multicast list allocation failed", dev->name); 89*1da177e4SLinus Torvalds return; 90*1da177e4SLinus Torvalds } 91*1da177e4SLinus Torvalds 92*1da177e4SLinus Torvalds r = (void *) skb->data; 93*1da177e4SLinus Torvalds __skb_put(skb, sizeof(*r)); 94*1da177e4SLinus Torvalds 95*1da177e4SLinus Torvalds r->type = BNEP_CONTROL; 96*1da177e4SLinus Torvalds r->ctrl = BNEP_FILTER_MULTI_ADDR_SET; 97*1da177e4SLinus Torvalds 98*1da177e4SLinus Torvalds if (dev->flags & (IFF_PROMISC | IFF_ALLMULTI)) { 99*1da177e4SLinus Torvalds u8 start[ETH_ALEN] = { 0x01 }; 100*1da177e4SLinus Torvalds 101*1da177e4SLinus Torvalds /* Request all addresses */ 102*1da177e4SLinus Torvalds memcpy(__skb_put(skb, ETH_ALEN), start, ETH_ALEN); 103*1da177e4SLinus Torvalds memcpy(__skb_put(skb, ETH_ALEN), dev->broadcast, ETH_ALEN); 104*1da177e4SLinus Torvalds r->len = htons(ETH_ALEN * 2); 105*1da177e4SLinus Torvalds } else { 106*1da177e4SLinus Torvalds struct dev_mc_list *dmi = dev->mc_list; 107*1da177e4SLinus Torvalds int i, len = skb->len; 108*1da177e4SLinus Torvalds 109*1da177e4SLinus Torvalds if (dev->flags & IFF_BROADCAST) { 110*1da177e4SLinus Torvalds memcpy(__skb_put(skb, ETH_ALEN), dev->broadcast, ETH_ALEN); 111*1da177e4SLinus Torvalds memcpy(__skb_put(skb, ETH_ALEN), dev->broadcast, ETH_ALEN); 112*1da177e4SLinus Torvalds } 113*1da177e4SLinus Torvalds 114*1da177e4SLinus Torvalds /* FIXME: We should group addresses here. */ 115*1da177e4SLinus Torvalds 116*1da177e4SLinus Torvalds for (i = 0; i < dev->mc_count && i < BNEP_MAX_MULTICAST_FILTERS; i++) { 117*1da177e4SLinus Torvalds memcpy(__skb_put(skb, ETH_ALEN), dmi->dmi_addr, ETH_ALEN); 118*1da177e4SLinus Torvalds memcpy(__skb_put(skb, ETH_ALEN), dmi->dmi_addr, ETH_ALEN); 119*1da177e4SLinus Torvalds dmi = dmi->next; 120*1da177e4SLinus Torvalds } 121*1da177e4SLinus Torvalds r->len = htons(skb->len - len); 122*1da177e4SLinus Torvalds } 123*1da177e4SLinus Torvalds 124*1da177e4SLinus Torvalds skb_queue_tail(&sk->sk_write_queue, skb); 125*1da177e4SLinus Torvalds wake_up_interruptible(sk->sk_sleep); 126*1da177e4SLinus Torvalds #endif 127*1da177e4SLinus Torvalds } 128*1da177e4SLinus Torvalds 129*1da177e4SLinus Torvalds static int bnep_net_set_mac_addr(struct net_device *dev, void *arg) 130*1da177e4SLinus Torvalds { 131*1da177e4SLinus Torvalds BT_DBG("%s", dev->name); 132*1da177e4SLinus Torvalds return 0; 133*1da177e4SLinus Torvalds } 134*1da177e4SLinus Torvalds 135*1da177e4SLinus Torvalds static void bnep_net_timeout(struct net_device *dev) 136*1da177e4SLinus Torvalds { 137*1da177e4SLinus Torvalds BT_DBG("net_timeout"); 138*1da177e4SLinus Torvalds netif_wake_queue(dev); 139*1da177e4SLinus Torvalds } 140*1da177e4SLinus Torvalds 141*1da177e4SLinus Torvalds static int bnep_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) 142*1da177e4SLinus Torvalds { 143*1da177e4SLinus Torvalds return -EINVAL; 144*1da177e4SLinus Torvalds } 145*1da177e4SLinus Torvalds 146*1da177e4SLinus Torvalds #ifdef CONFIG_BT_BNEP_MC_FILTER 147*1da177e4SLinus Torvalds static inline int bnep_net_mc_filter(struct sk_buff *skb, struct bnep_session *s) 148*1da177e4SLinus Torvalds { 149*1da177e4SLinus Torvalds struct ethhdr *eh = (void *) skb->data; 150*1da177e4SLinus Torvalds 151*1da177e4SLinus Torvalds if ((eh->h_dest[0] & 1) && !test_bit(bnep_mc_hash(eh->h_dest), (ulong *) &s->mc_filter)) 152*1da177e4SLinus Torvalds return 1; 153*1da177e4SLinus Torvalds return 0; 154*1da177e4SLinus Torvalds } 155*1da177e4SLinus Torvalds #endif 156*1da177e4SLinus Torvalds 157*1da177e4SLinus Torvalds #ifdef CONFIG_BT_BNEP_PROTO_FILTER 158*1da177e4SLinus Torvalds /* Determine ether protocol. Based on eth_type_trans. */ 159*1da177e4SLinus Torvalds static inline u16 bnep_net_eth_proto(struct sk_buff *skb) 160*1da177e4SLinus Torvalds { 161*1da177e4SLinus Torvalds struct ethhdr *eh = (void *) skb->data; 162*1da177e4SLinus Torvalds 163*1da177e4SLinus Torvalds if (ntohs(eh->h_proto) >= 1536) 164*1da177e4SLinus Torvalds return eh->h_proto; 165*1da177e4SLinus Torvalds 166*1da177e4SLinus Torvalds if (get_unaligned((u16 *) skb->data) == 0xFFFF) 167*1da177e4SLinus Torvalds return htons(ETH_P_802_3); 168*1da177e4SLinus Torvalds 169*1da177e4SLinus Torvalds return htons(ETH_P_802_2); 170*1da177e4SLinus Torvalds } 171*1da177e4SLinus Torvalds 172*1da177e4SLinus Torvalds static inline int bnep_net_proto_filter(struct sk_buff *skb, struct bnep_session *s) 173*1da177e4SLinus Torvalds { 174*1da177e4SLinus Torvalds u16 proto = bnep_net_eth_proto(skb); 175*1da177e4SLinus Torvalds struct bnep_proto_filter *f = s->proto_filter; 176*1da177e4SLinus Torvalds int i; 177*1da177e4SLinus Torvalds 178*1da177e4SLinus Torvalds for (i = 0; i < BNEP_MAX_PROTO_FILTERS && f[i].end; i++) { 179*1da177e4SLinus Torvalds if (proto >= f[i].start && proto <= f[i].end) 180*1da177e4SLinus Torvalds return 0; 181*1da177e4SLinus Torvalds } 182*1da177e4SLinus Torvalds 183*1da177e4SLinus Torvalds BT_DBG("BNEP: filtered skb %p, proto 0x%.4x", skb, proto); 184*1da177e4SLinus Torvalds return 1; 185*1da177e4SLinus Torvalds } 186*1da177e4SLinus Torvalds #endif 187*1da177e4SLinus Torvalds 188*1da177e4SLinus Torvalds static int bnep_net_xmit(struct sk_buff *skb, struct net_device *dev) 189*1da177e4SLinus Torvalds { 190*1da177e4SLinus Torvalds struct bnep_session *s = dev->priv; 191*1da177e4SLinus Torvalds struct sock *sk = s->sock->sk; 192*1da177e4SLinus Torvalds 193*1da177e4SLinus Torvalds BT_DBG("skb %p, dev %p", skb, dev); 194*1da177e4SLinus Torvalds 195*1da177e4SLinus Torvalds #ifdef CONFIG_BT_BNEP_MC_FILTER 196*1da177e4SLinus Torvalds if (bnep_net_mc_filter(skb, s)) { 197*1da177e4SLinus Torvalds kfree_skb(skb); 198*1da177e4SLinus Torvalds return 0; 199*1da177e4SLinus Torvalds } 200*1da177e4SLinus Torvalds #endif 201*1da177e4SLinus Torvalds 202*1da177e4SLinus Torvalds #ifdef CONFIG_BT_BNEP_PROTO_FILTER 203*1da177e4SLinus Torvalds if (bnep_net_proto_filter(skb, s)) { 204*1da177e4SLinus Torvalds kfree_skb(skb); 205*1da177e4SLinus Torvalds return 0; 206*1da177e4SLinus Torvalds } 207*1da177e4SLinus Torvalds #endif 208*1da177e4SLinus Torvalds 209*1da177e4SLinus Torvalds /* 210*1da177e4SLinus Torvalds * We cannot send L2CAP packets from here as we are potentially in a bh. 211*1da177e4SLinus Torvalds * So we have to queue them and wake up session thread which is sleeping 212*1da177e4SLinus Torvalds * on the sk->sk_sleep. 213*1da177e4SLinus Torvalds */ 214*1da177e4SLinus Torvalds dev->trans_start = jiffies; 215*1da177e4SLinus Torvalds skb_queue_tail(&sk->sk_write_queue, skb); 216*1da177e4SLinus Torvalds wake_up_interruptible(sk->sk_sleep); 217*1da177e4SLinus Torvalds 218*1da177e4SLinus Torvalds if (skb_queue_len(&sk->sk_write_queue) >= BNEP_TX_QUEUE_LEN) { 219*1da177e4SLinus Torvalds BT_DBG("tx queue is full"); 220*1da177e4SLinus Torvalds 221*1da177e4SLinus Torvalds /* Stop queuing. 222*1da177e4SLinus Torvalds * Session thread will do netif_wake_queue() */ 223*1da177e4SLinus Torvalds netif_stop_queue(dev); 224*1da177e4SLinus Torvalds } 225*1da177e4SLinus Torvalds 226*1da177e4SLinus Torvalds return 0; 227*1da177e4SLinus Torvalds } 228*1da177e4SLinus Torvalds 229*1da177e4SLinus Torvalds void bnep_net_setup(struct net_device *dev) 230*1da177e4SLinus Torvalds { 231*1da177e4SLinus Torvalds 232*1da177e4SLinus Torvalds memset(dev->broadcast, 0xff, ETH_ALEN); 233*1da177e4SLinus Torvalds dev->addr_len = ETH_ALEN; 234*1da177e4SLinus Torvalds 235*1da177e4SLinus Torvalds ether_setup(dev); 236*1da177e4SLinus Torvalds 237*1da177e4SLinus Torvalds dev->open = bnep_net_open; 238*1da177e4SLinus Torvalds dev->stop = bnep_net_close; 239*1da177e4SLinus Torvalds dev->hard_start_xmit = bnep_net_xmit; 240*1da177e4SLinus Torvalds dev->get_stats = bnep_net_get_stats; 241*1da177e4SLinus Torvalds dev->do_ioctl = bnep_net_ioctl; 242*1da177e4SLinus Torvalds dev->set_mac_address = bnep_net_set_mac_addr; 243*1da177e4SLinus Torvalds dev->set_multicast_list = bnep_net_set_mc_list; 244*1da177e4SLinus Torvalds 245*1da177e4SLinus Torvalds dev->watchdog_timeo = HZ * 2; 246*1da177e4SLinus Torvalds dev->tx_timeout = bnep_net_timeout; 247*1da177e4SLinus Torvalds } 248