1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28#include <linux/export.h>
29#include <linux/etherdevice.h>
30
31#include <net/bluetooth/bluetooth.h>
32#include <net/bluetooth/hci_core.h>
33#include <net/bluetooth/l2cap.h>
34
35#include "bnep.h"
36
37#define BNEP_TX_QUEUE_LEN 20
38
39static int bnep_net_open(struct net_device *dev)
40{
41 netif_start_queue(dev);
42 return 0;
43}
44
45static int bnep_net_close(struct net_device *dev)
46{
47 netif_stop_queue(dev);
48 return 0;
49}
50
51static void bnep_net_set_mc_list(struct net_device *dev)
52{
53#ifdef CONFIG_BT_BNEP_MC_FILTER
54 struct bnep_session *s = netdev_priv(dev);
55 struct sock *sk = s->sock->sk;
56 struct bnep_set_filter_req *r;
57 struct sk_buff *skb;
58 int size;
59
60 BT_DBG("%s mc_count %d", dev->name, netdev_mc_count(dev));
61
62 size = sizeof(*r) + (BNEP_MAX_MULTICAST_FILTERS + 1) * ETH_ALEN * 2;
63 skb = alloc_skb(size, GFP_ATOMIC);
64 if (!skb) {
65 BT_ERR("%s Multicast list allocation failed", dev->name);
66 return;
67 }
68
69 r = (void *) skb->data;
70 __skb_put(skb, sizeof(*r));
71
72 r->type = BNEP_CONTROL;
73 r->ctrl = BNEP_FILTER_MULTI_ADDR_SET;
74
75 if (dev->flags & (IFF_PROMISC | IFF_ALLMULTI)) {
76 u8 start[ETH_ALEN] = { 0x01 };
77
78
79 memcpy(__skb_put(skb, ETH_ALEN), start, ETH_ALEN);
80 memcpy(__skb_put(skb, ETH_ALEN), dev->broadcast, ETH_ALEN);
81 r->len = htons(ETH_ALEN * 2);
82 } else {
83 struct netdev_hw_addr *ha;
84 int i, len = skb->len;
85
86 if (dev->flags & IFF_BROADCAST) {
87 memcpy(__skb_put(skb, ETH_ALEN), dev->broadcast, ETH_ALEN);
88 memcpy(__skb_put(skb, ETH_ALEN), dev->broadcast, ETH_ALEN);
89 }
90
91
92
93 i = 0;
94 netdev_for_each_mc_addr(ha, dev) {
95 if (i == BNEP_MAX_MULTICAST_FILTERS)
96 break;
97 memcpy(__skb_put(skb, ETH_ALEN), ha->addr, ETH_ALEN);
98 memcpy(__skb_put(skb, ETH_ALEN), ha->addr, ETH_ALEN);
99
100 i++;
101 }
102 r->len = htons(skb->len - len);
103 }
104
105 skb_queue_tail(&sk->sk_write_queue, skb);
106 wake_up_interruptible(sk_sleep(sk));
107#endif
108}
109
110static int bnep_net_set_mac_addr(struct net_device *dev, void *arg)
111{
112 BT_DBG("%s", dev->name);
113 return 0;
114}
115
116static void bnep_net_timeout(struct net_device *dev)
117{
118 BT_DBG("net_timeout");
119 netif_wake_queue(dev);
120}
121
122#ifdef CONFIG_BT_BNEP_MC_FILTER
123static int bnep_net_mc_filter(struct sk_buff *skb, struct bnep_session *s)
124{
125 struct ethhdr *eh = (void *) skb->data;
126
127 if ((eh->h_dest[0] & 1) && !test_bit(bnep_mc_hash(eh->h_dest), (ulong *) &s->mc_filter))
128 return 1;
129 return 0;
130}
131#endif
132
133#ifdef CONFIG_BT_BNEP_PROTO_FILTER
134
135static u16 bnep_net_eth_proto(struct sk_buff *skb)
136{
137 struct ethhdr *eh = (void *) skb->data;
138 u16 proto = ntohs(eh->h_proto);
139
140 if (proto >= 1536)
141 return proto;
142
143 if (get_unaligned((__be16 *) skb->data) == htons(0xFFFF))
144 return ETH_P_802_3;
145
146 return ETH_P_802_2;
147}
148
149static int bnep_net_proto_filter(struct sk_buff *skb, struct bnep_session *s)
150{
151 u16 proto = bnep_net_eth_proto(skb);
152 struct bnep_proto_filter *f = s->proto_filter;
153 int i;
154
155 for (i = 0; i < BNEP_MAX_PROTO_FILTERS && f[i].end; i++) {
156 if (proto >= f[i].start && proto <= f[i].end)
157 return 0;
158 }
159
160 BT_DBG("BNEP: filtered skb %p, proto 0x%.4x", skb, proto);
161 return 1;
162}
163#endif
164
165static netdev_tx_t bnep_net_xmit(struct sk_buff *skb,
166 struct net_device *dev)
167{
168 struct bnep_session *s = netdev_priv(dev);
169 struct sock *sk = s->sock->sk;
170
171 BT_DBG("skb %p, dev %p", skb, dev);
172
173#ifdef CONFIG_BT_BNEP_MC_FILTER
174 if (bnep_net_mc_filter(skb, s)) {
175 kfree_skb(skb);
176 return NETDEV_TX_OK;
177 }
178#endif
179
180#ifdef CONFIG_BT_BNEP_PROTO_FILTER
181 if (bnep_net_proto_filter(skb, s)) {
182 kfree_skb(skb);
183 return NETDEV_TX_OK;
184 }
185#endif
186
187
188
189
190
191
192 dev->trans_start = jiffies;
193 skb_queue_tail(&sk->sk_write_queue, skb);
194 wake_up_interruptible(sk_sleep(sk));
195
196 if (skb_queue_len(&sk->sk_write_queue) >= BNEP_TX_QUEUE_LEN) {
197 BT_DBG("tx queue is full");
198
199
200
201 netif_stop_queue(dev);
202 }
203
204 return NETDEV_TX_OK;
205}
206
207static const struct net_device_ops bnep_netdev_ops = {
208 .ndo_open = bnep_net_open,
209 .ndo_stop = bnep_net_close,
210 .ndo_start_xmit = bnep_net_xmit,
211 .ndo_validate_addr = eth_validate_addr,
212 .ndo_set_rx_mode = bnep_net_set_mc_list,
213 .ndo_set_mac_address = bnep_net_set_mac_addr,
214 .ndo_tx_timeout = bnep_net_timeout,
215 .ndo_change_mtu = eth_change_mtu,
216
217};
218
219void bnep_net_setup(struct net_device *dev)
220{
221
222 memset(dev->broadcast, 0xff, ETH_ALEN);
223 dev->addr_len = ETH_ALEN;
224
225 ether_setup(dev);
226 dev->priv_flags &= ~IFF_TX_SKB_SHARING;
227 dev->netdev_ops = &bnep_netdev_ops;
228
229 dev->watchdog_timeo = HZ * 2;
230}
231