// SPDX-License-Identifier: GPL-2.0-only/* Copyright (c) 2013-2014 Intel Corp.*/#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);module_put(THIS_MODULE);if(atomic_dec_and_test(&dev->peer_count)){BT_DBG("last peer");returntrue;}returnfalse;}