/* Copyright (c) 2013-2014 Intel Corp. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 and only version 2 as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.*/#include<linux/if_arp.h>#include<linux/netdevice.h>#include<linux/etherdevice.h>#include<linux/module.h>#include<linux/debugfs.h>#include<net/ipv6.h>#include<net/ip6_route.h>#include<net/addrconf.h>#include<net/pkt_sched.h>#include<net/bluetooth/bluetooth.h>#include<net/bluetooth/hci_core.h>#include<net/bluetooth/l2cap.h>#include<net/6lowpan.h> /* for the compression support */#define VERSION "0.1"staticstructdentry*lowpan_enable_debugfs;staticstructdentry*lowpan_control_debugfs;#define IFACE_NAME_TEMPLATE "bt%d"structskb_cb{structin6_addraddr;structin6_addrgw;structl2cap_chan*chan;};#define lowpan_cb(skb) ((struct skb_cb *)((skb)->cb))/* The devices list contains those devices that we are acting * as a proxy. The BT 6LoWPAN device is a virtual device that * connects to the Bluetooth LE device. The real connection to * BT device is done via l2cap layer. There exists one * virtual device / one BT 6LoWPAN network (=hciX device). * The list contains struct lowpan_dev elements. */staticLIST_HEAD(bt_6lowpan_devices);staticDEFINE_SPINLOCK(devices_lock);staticboolenable_6lowpan;/* We are listening incoming connections via this channel */staticstructl2cap_chan*listen_chan;structlowpan_peer{structlist_headlist;structrcu_headrcu;structl2cap_chan*chan;/* peer addresses in various formats */unsignedcharlladdr[ETH_ALEN];structin6_addrpeer_addr;};structlowpan_btle_dev{structlist_headlist;structhci_dev*hdev;structnet_device*netdev;structlist_headpeers;atomic_tpeer_count;/* number of items in peers list */structwork_structdelete_netdev;structdelayed_worknotify_peers;};staticinlinestructlowpan_btle_dev*lowpan_btle_dev(conststructnet_device*netdev){return(structlowpan_btle_dev*)lowpan_dev(netdev)->priv;}staticinlinevoidpeer_add(structlowpan_btle_dev*dev,structlowpan_peer*peer){list_add_rcu(&peer->list,&dev->peers);atomic_inc(&dev->peer_count);}staticinlineboolpeer_del(structlowpan_btle_dev*dev,structlowpan_peer*peer){list_del_rcu(&peer->list);kfree_rcu(peer,rcu