/* 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/af_ieee802154.h> /* to get the address type */#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_psm_debugfs;staticstructdentry*lowpan_control_debugfs;#define IFACE_NAME_TEMPLATE "bt%d"#define EUI64_ADDR_LEN 8structskb_cb{structin6_addraddr;structl2cap_chan*chan;intstatus;};#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_RWLOCK(devices_lock);/* If psm is set to 0 (default value), then 6lowpan is disabled. * Other values are used to indicate a Protocol Service Multiplexer * value for 6lowpan. */staticu16psm_6lowpan;/* We are listening incoming connections via this channel */staticstructl2cap_chan*listen_chan;structlowpan_peer{structlist_headlist;structl2cap_chan*chan;/* peer addresses in various formats */unsignedchareui64_addr[EUI64_ADDR_LEN];structin6_addrpeer_addr;};structlowpan_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_dev*lowpan_dev(conststructnet_device*netdev){returnnetdev_priv(netdev);}staticinlinevoidpeer_add(structlowpan_dev*dev,structlowpan_peer*peer){list_add(&peer->list,&dev->peers);atomic_inc(&dev->peer_count);}staticinlineboolpeer_del(structlowpan_dev*dev,structlowpan_peer*peer){list_del(&peer->list);module_put(THIS_MODULE);if(atomic_dec_and_test(&dev->peer_count)){