1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Ethernet netdevice using ATM AAL5 as underlying carrier |
4 | * (RFC1483 obsoleted by RFC2684) for Linux |
5 | * |
6 | * Authors: Marcell GAL, 2000, XDSL Ltd, Hungary |
7 | * Eric Kinzie, 2006-2007, US Naval Research Laboratory |
8 | */ |
9 | |
10 | #define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__ |
11 | |
12 | #include <linux/module.h> |
13 | #include <linux/init.h> |
14 | #include <linux/kernel.h> |
15 | #include <linux/list.h> |
16 | #include <linux/netdevice.h> |
17 | #include <linux/skbuff.h> |
18 | #include <linux/etherdevice.h> |
19 | #include <linux/rtnetlink.h> |
20 | #include <linux/ip.h> |
21 | #include <linux/uaccess.h> |
22 | #include <linux/slab.h> |
23 | #include <net/arp.h> |
24 | #include <linux/atm.h> |
25 | #include <linux/atmdev.h> |
26 | #include <linux/capability.h> |
27 | #include <linux/seq_file.h> |
28 | |
29 | #include <linux/atmbr2684.h> |
30 | |
31 | #include "common.h" |
32 | |
33 | static void skb_debug(const struct sk_buff *skb) |
34 | { |
35 | #ifdef SKB_DEBUG |
36 | #define NUM2PRINT 50 |
37 | print_hex_dump(KERN_DEBUG, "br2684: skb: " , DUMP_OFFSET, |
38 | 16, 1, skb->data, min(NUM2PRINT, skb->len), true); |
39 | #endif |
40 | } |
41 | |
42 | #define BR2684_ETHERTYPE_LEN 2 |
43 | #define BR2684_PAD_LEN 2 |
44 | |
45 | #define LLC 0xaa, 0xaa, 0x03 |
46 | #define SNAP_BRIDGED 0x00, 0x80, 0xc2 |
47 | #define SNAP_ROUTED 0x00, 0x00, 0x00 |
48 | #define PID_ETHERNET 0x00, 0x07 |
49 | #define ETHERTYPE_IPV4 0x08, 0x00 |
50 | #define ETHERTYPE_IPV6 0x86, 0xdd |
51 | #define PAD_BRIDGED 0x00, 0x00 |
52 | |
53 | static const unsigned char ethertype_ipv4[] = { ETHERTYPE_IPV4 }; |
54 | static const unsigned char ethertype_ipv6[] = { ETHERTYPE_IPV6 }; |
55 | static const unsigned char llc_oui_pid_pad[] = |
56 | { LLC, SNAP_BRIDGED, PID_ETHERNET, PAD_BRIDGED }; |
57 | static const unsigned char pad[] = { PAD_BRIDGED }; |
58 | static const unsigned char llc_oui_ipv4[] = { LLC, SNAP_ROUTED, ETHERTYPE_IPV4 }; |
59 | static const unsigned char llc_oui_ipv6[] = { LLC, SNAP_ROUTED, ETHERTYPE_IPV6 }; |
60 | |
61 | enum br2684_encaps { |
62 | e_vc = BR2684_ENCAPS_VC, |
63 | e_llc = BR2684_ENCAPS_LLC, |
64 | }; |
65 | |
66 | struct br2684_vcc { |
67 | struct atm_vcc *atmvcc; |
68 | struct net_device *device; |
69 | /* keep old push, pop functions for chaining */ |
70 | void (*old_push)(struct atm_vcc *vcc, struct sk_buff *skb); |
71 | void (*old_pop)(struct atm_vcc *vcc, struct sk_buff *skb); |
72 | void (*old_release_cb)(struct atm_vcc *vcc); |
73 | struct module *old_owner; |
74 | enum br2684_encaps encaps; |
75 | struct list_head brvccs; |
76 | #ifdef CONFIG_ATM_BR2684_IPFILTER |
77 | struct br2684_filter filter; |
78 | #endif /* CONFIG_ATM_BR2684_IPFILTER */ |
79 | unsigned int copies_needed, copies_failed; |
80 | atomic_t qspace; |
81 | }; |
82 | |
83 | struct br2684_dev { |
84 | struct net_device *net_dev; |
85 | struct list_head br2684_devs; |
86 | int number; |
87 | struct list_head brvccs; /* one device <=> one vcc (before xmas) */ |
88 | int mac_was_set; |
89 | enum br2684_payload payload; |
90 | }; |
91 | |
92 | /* |
93 | * This lock should be held for writing any time the list of devices or |
94 | * their attached vcc's could be altered. It should be held for reading |
95 | * any time these are being queried. Note that we sometimes need to |
96 | * do read-locking under interrupting context, so write locking must block |
97 | * the current CPU's interrupts. |
98 | */ |
99 | static DEFINE_RWLOCK(devs_lock); |
100 | |
101 | static LIST_HEAD(br2684_devs); |
102 | |
103 | static inline struct br2684_dev *BRPRIV(const struct net_device *net_dev) |
104 | { |
105 | return netdev_priv(dev: net_dev); |
106 | } |
107 | |
108 | static inline struct net_device *list_entry_brdev(const struct list_head *le) |
109 | { |
110 | return list_entry(le, struct br2684_dev, br2684_devs)->net_dev; |
111 | } |
112 | |
113 | static inline struct br2684_vcc *BR2684_VCC(const struct atm_vcc *atmvcc) |
114 | { |
115 | return (struct br2684_vcc *)(atmvcc->user_back); |
116 | } |
117 | |
118 | static inline struct br2684_vcc *list_entry_brvcc(const struct list_head *le) |
119 | { |
120 | return list_entry(le, struct br2684_vcc, brvccs); |
121 | } |
122 | |
123 | /* Caller should hold read_lock(&devs_lock) */ |
124 | static struct net_device *br2684_find_dev(const struct br2684_if_spec *s) |
125 | { |
126 | struct list_head *lh; |
127 | struct net_device *net_dev; |
128 | switch (s->method) { |
129 | case BR2684_FIND_BYNUM: |
130 | list_for_each(lh, &br2684_devs) { |
131 | net_dev = list_entry_brdev(le: lh); |
132 | if (BRPRIV(net_dev)->number == s->spec.devnum) |
133 | return net_dev; |
134 | } |
135 | break; |
136 | case BR2684_FIND_BYIFNAME: |
137 | list_for_each(lh, &br2684_devs) { |
138 | net_dev = list_entry_brdev(le: lh); |
139 | if (!strncmp(net_dev->name, s->spec.ifname, IFNAMSIZ)) |
140 | return net_dev; |
141 | } |
142 | break; |
143 | } |
144 | return NULL; |
145 | } |
146 | |
147 | static int atm_dev_event(struct notifier_block *this, unsigned long event, |
148 | void *arg) |
149 | { |
150 | struct atm_dev *atm_dev = arg; |
151 | struct list_head *lh; |
152 | struct net_device *net_dev; |
153 | struct br2684_vcc *brvcc; |
154 | struct atm_vcc *atm_vcc; |
155 | unsigned long flags; |
156 | |
157 | pr_debug("event=%ld dev=%p\n" , event, atm_dev); |
158 | |
159 | read_lock_irqsave(&devs_lock, flags); |
160 | list_for_each(lh, &br2684_devs) { |
161 | net_dev = list_entry_brdev(le: lh); |
162 | |
163 | list_for_each_entry(brvcc, &BRPRIV(net_dev)->brvccs, brvccs) { |
164 | atm_vcc = brvcc->atmvcc; |
165 | if (atm_vcc && brvcc->atmvcc->dev == atm_dev) { |
166 | |
167 | if (atm_vcc->dev->signal == ATM_PHY_SIG_LOST) |
168 | netif_carrier_off(dev: net_dev); |
169 | else |
170 | netif_carrier_on(dev: net_dev); |
171 | |
172 | } |
173 | } |
174 | } |
175 | read_unlock_irqrestore(&devs_lock, flags); |
176 | |
177 | return NOTIFY_DONE; |
178 | } |
179 | |
180 | static struct notifier_block atm_dev_notifier = { |
181 | .notifier_call = atm_dev_event, |
182 | }; |
183 | |
184 | /* chained vcc->pop function. Check if we should wake the netif_queue */ |
185 | static void br2684_pop(struct atm_vcc *vcc, struct sk_buff *skb) |
186 | { |
187 | struct br2684_vcc *brvcc = BR2684_VCC(atmvcc: vcc); |
188 | |
189 | pr_debug("(vcc %p ; net_dev %p )\n" , vcc, brvcc->device); |
190 | brvcc->old_pop(vcc, skb); |
191 | |
192 | /* If the queue space just went up from zero, wake */ |
193 | if (atomic_inc_return(v: &brvcc->qspace) == 1) |
194 | netif_wake_queue(dev: brvcc->device); |
195 | } |
196 | |
197 | /* |
198 | * Send a packet out a particular vcc. Not to useful right now, but paves |
199 | * the way for multiple vcc's per itf. Returns true if we can send, |
200 | * otherwise false |
201 | */ |
202 | static int br2684_xmit_vcc(struct sk_buff *skb, struct net_device *dev, |
203 | struct br2684_vcc *brvcc) |
204 | { |
205 | struct br2684_dev *brdev = BRPRIV(net_dev: dev); |
206 | struct atm_vcc *atmvcc; |
207 | int minheadroom = (brvcc->encaps == e_llc) ? |
208 | ((brdev->payload == p_bridged) ? |
209 | sizeof(llc_oui_pid_pad) : sizeof(llc_oui_ipv4)) : |
210 | ((brdev->payload == p_bridged) ? BR2684_PAD_LEN : 0); |
211 | |
212 | if (skb_headroom(skb) < minheadroom) { |
213 | struct sk_buff *skb2 = skb_realloc_headroom(skb, headroom: minheadroom); |
214 | brvcc->copies_needed++; |
215 | dev_kfree_skb(skb); |
216 | if (skb2 == NULL) { |
217 | brvcc->copies_failed++; |
218 | return 0; |
219 | } |
220 | skb = skb2; |
221 | } |
222 | |
223 | if (brvcc->encaps == e_llc) { |
224 | if (brdev->payload == p_bridged) { |
225 | skb_push(skb, len: sizeof(llc_oui_pid_pad)); |
226 | skb_copy_to_linear_data(skb, from: llc_oui_pid_pad, |
227 | len: sizeof(llc_oui_pid_pad)); |
228 | } else if (brdev->payload == p_routed) { |
229 | unsigned short prot = ntohs(skb->protocol); |
230 | |
231 | skb_push(skb, len: sizeof(llc_oui_ipv4)); |
232 | switch (prot) { |
233 | case ETH_P_IP: |
234 | skb_copy_to_linear_data(skb, from: llc_oui_ipv4, |
235 | len: sizeof(llc_oui_ipv4)); |
236 | break; |
237 | case ETH_P_IPV6: |
238 | skb_copy_to_linear_data(skb, from: llc_oui_ipv6, |
239 | len: sizeof(llc_oui_ipv6)); |
240 | break; |
241 | default: |
242 | dev_kfree_skb(skb); |
243 | return 0; |
244 | } |
245 | } |
246 | } else { /* e_vc */ |
247 | if (brdev->payload == p_bridged) { |
248 | skb_push(skb, len: 2); |
249 | memset(skb->data, 0, 2); |
250 | } |
251 | } |
252 | skb_debug(skb); |
253 | |
254 | ATM_SKB(skb)->vcc = atmvcc = brvcc->atmvcc; |
255 | pr_debug("atm_skb(%p)->vcc(%p)->dev(%p)\n" , skb, atmvcc, atmvcc->dev); |
256 | atm_account_tx(vcc: atmvcc, skb); |
257 | dev->stats.tx_packets++; |
258 | dev->stats.tx_bytes += skb->len; |
259 | |
260 | if (atomic_dec_return(v: &brvcc->qspace) < 1) { |
261 | /* No more please! */ |
262 | netif_stop_queue(dev: brvcc->device); |
263 | /* We might have raced with br2684_pop() */ |
264 | if (unlikely(atomic_read(&brvcc->qspace) > 0)) |
265 | netif_wake_queue(dev: brvcc->device); |
266 | } |
267 | |
268 | /* If this fails immediately, the skb will be freed and br2684_pop() |
269 | will wake the queue if appropriate. Just return an error so that |
270 | the stats are updated correctly */ |
271 | return !atmvcc->send(atmvcc, skb); |
272 | } |
273 | |
274 | static void br2684_release_cb(struct atm_vcc *atmvcc) |
275 | { |
276 | struct br2684_vcc *brvcc = BR2684_VCC(atmvcc); |
277 | |
278 | if (atomic_read(v: &brvcc->qspace) > 0) |
279 | netif_wake_queue(dev: brvcc->device); |
280 | |
281 | if (brvcc->old_release_cb) |
282 | brvcc->old_release_cb(atmvcc); |
283 | } |
284 | |
285 | static inline struct br2684_vcc *pick_outgoing_vcc(const struct sk_buff *skb, |
286 | const struct br2684_dev *brdev) |
287 | { |
288 | return list_empty(head: &brdev->brvccs) ? NULL : list_entry_brvcc(le: brdev->brvccs.next); /* 1 vcc/dev right now */ |
289 | } |
290 | |
291 | static netdev_tx_t br2684_start_xmit(struct sk_buff *skb, |
292 | struct net_device *dev) |
293 | { |
294 | struct br2684_dev *brdev = BRPRIV(net_dev: dev); |
295 | struct br2684_vcc *brvcc; |
296 | struct atm_vcc *atmvcc; |
297 | netdev_tx_t ret = NETDEV_TX_OK; |
298 | |
299 | pr_debug("skb_dst(skb)=%p\n" , skb_dst(skb)); |
300 | read_lock(&devs_lock); |
301 | brvcc = pick_outgoing_vcc(skb, brdev); |
302 | if (brvcc == NULL) { |
303 | pr_debug("no vcc attached to dev %s\n" , dev->name); |
304 | dev->stats.tx_errors++; |
305 | dev->stats.tx_carrier_errors++; |
306 | /* netif_stop_queue(dev); */ |
307 | dev_kfree_skb(skb); |
308 | goto out_devs; |
309 | } |
310 | atmvcc = brvcc->atmvcc; |
311 | |
312 | bh_lock_sock(sk_atm(atmvcc)); |
313 | |
314 | if (test_bit(ATM_VF_RELEASED, &atmvcc->flags) || |
315 | test_bit(ATM_VF_CLOSE, &atmvcc->flags) || |
316 | !test_bit(ATM_VF_READY, &atmvcc->flags)) { |
317 | dev->stats.tx_dropped++; |
318 | dev_kfree_skb(skb); |
319 | goto out; |
320 | } |
321 | |
322 | if (sock_owned_by_user(sk: sk_atm(vcc: atmvcc))) { |
323 | netif_stop_queue(dev: brvcc->device); |
324 | ret = NETDEV_TX_BUSY; |
325 | goto out; |
326 | } |
327 | |
328 | if (!br2684_xmit_vcc(skb, dev, brvcc)) { |
329 | /* |
330 | * We should probably use netif_*_queue() here, but that |
331 | * involves added complication. We need to walk before |
332 | * we can run. |
333 | * |
334 | * Don't free here! this pointer might be no longer valid! |
335 | */ |
336 | dev->stats.tx_errors++; |
337 | dev->stats.tx_fifo_errors++; |
338 | } |
339 | out: |
340 | bh_unlock_sock(sk_atm(atmvcc)); |
341 | out_devs: |
342 | read_unlock(&devs_lock); |
343 | return ret; |
344 | } |
345 | |
346 | /* |
347 | * We remember when the MAC gets set, so we don't override it later with |
348 | * the ESI of the ATM card of the first VC |
349 | */ |
350 | static int br2684_mac_addr(struct net_device *dev, void *p) |
351 | { |
352 | int err = eth_mac_addr(dev, p); |
353 | if (!err) |
354 | BRPRIV(net_dev: dev)->mac_was_set = 1; |
355 | return err; |
356 | } |
357 | |
358 | #ifdef CONFIG_ATM_BR2684_IPFILTER |
359 | /* this IOCTL is experimental. */ |
360 | static int br2684_setfilt(struct atm_vcc *atmvcc, void __user * arg) |
361 | { |
362 | struct br2684_vcc *brvcc; |
363 | struct br2684_filter_set fs; |
364 | |
365 | if (copy_from_user(to: &fs, from: arg, n: sizeof fs)) |
366 | return -EFAULT; |
367 | if (fs.ifspec.method != BR2684_FIND_BYNOTHING) { |
368 | /* |
369 | * This is really a per-vcc thing, but we can also search |
370 | * by device. |
371 | */ |
372 | struct br2684_dev *brdev; |
373 | read_lock(&devs_lock); |
374 | brdev = BRPRIV(net_dev: br2684_find_dev(s: &fs.ifspec)); |
375 | if (brdev == NULL || list_empty(head: &brdev->brvccs) || |
376 | brdev->brvccs.next != brdev->brvccs.prev) /* >1 VCC */ |
377 | brvcc = NULL; |
378 | else |
379 | brvcc = list_entry_brvcc(le: brdev->brvccs.next); |
380 | read_unlock(&devs_lock); |
381 | if (brvcc == NULL) |
382 | return -ESRCH; |
383 | } else |
384 | brvcc = BR2684_VCC(atmvcc); |
385 | memcpy(&brvcc->filter, &fs.filter, sizeof(brvcc->filter)); |
386 | return 0; |
387 | } |
388 | |
389 | /* Returns 1 if packet should be dropped */ |
390 | static inline int |
391 | packet_fails_filter(__be16 type, struct br2684_vcc *brvcc, struct sk_buff *skb) |
392 | { |
393 | if (brvcc->filter.netmask == 0) |
394 | return 0; /* no filter in place */ |
395 | if (type == htons(ETH_P_IP) && |
396 | (((struct iphdr *)(skb->data))->daddr & brvcc->filter. |
397 | netmask) == brvcc->filter.prefix) |
398 | return 0; |
399 | if (type == htons(ETH_P_ARP)) |
400 | return 0; |
401 | /* |
402 | * TODO: we should probably filter ARPs too.. don't want to have |
403 | * them returning values that don't make sense, or is that ok? |
404 | */ |
405 | return 1; /* drop */ |
406 | } |
407 | #endif /* CONFIG_ATM_BR2684_IPFILTER */ |
408 | |
409 | static void br2684_close_vcc(struct br2684_vcc *brvcc) |
410 | { |
411 | pr_debug("removing VCC %p from dev %p\n" , brvcc, brvcc->device); |
412 | write_lock_irq(&devs_lock); |
413 | list_del(entry: &brvcc->brvccs); |
414 | write_unlock_irq(&devs_lock); |
415 | brvcc->atmvcc->user_back = NULL; /* what about vcc->recvq ??? */ |
416 | brvcc->atmvcc->release_cb = brvcc->old_release_cb; |
417 | brvcc->old_push(brvcc->atmvcc, NULL); /* pass on the bad news */ |
418 | module_put(module: brvcc->old_owner); |
419 | kfree(objp: brvcc); |
420 | } |
421 | |
422 | /* when AAL5 PDU comes in: */ |
423 | static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb) |
424 | { |
425 | struct br2684_vcc *brvcc = BR2684_VCC(atmvcc); |
426 | struct net_device *net_dev = brvcc->device; |
427 | struct br2684_dev *brdev = BRPRIV(net_dev); |
428 | |
429 | pr_debug("\n" ); |
430 | |
431 | if (unlikely(skb == NULL)) { |
432 | /* skb==NULL means VCC is being destroyed */ |
433 | br2684_close_vcc(brvcc); |
434 | if (list_empty(head: &brdev->brvccs)) { |
435 | write_lock_irq(&devs_lock); |
436 | list_del(entry: &brdev->br2684_devs); |
437 | write_unlock_irq(&devs_lock); |
438 | unregister_netdev(dev: net_dev); |
439 | free_netdev(dev: net_dev); |
440 | } |
441 | return; |
442 | } |
443 | |
444 | skb_debug(skb); |
445 | atm_return(vcc: atmvcc, truesize: skb->truesize); |
446 | pr_debug("skb from brdev %p\n" , brdev); |
447 | if (brvcc->encaps == e_llc) { |
448 | |
449 | if (skb->len > 7 && skb->data[7] == 0x01) |
450 | __skb_trim(skb, len: skb->len - 4); |
451 | |
452 | /* accept packets that have "ipv[46]" in the snap header */ |
453 | if ((skb->len >= (sizeof(llc_oui_ipv4))) && |
454 | (memcmp(p: skb->data, q: llc_oui_ipv4, |
455 | size: sizeof(llc_oui_ipv4) - BR2684_ETHERTYPE_LEN) == 0)) { |
456 | if (memcmp(p: skb->data + 6, q: ethertype_ipv6, |
457 | size: sizeof(ethertype_ipv6)) == 0) |
458 | skb->protocol = htons(ETH_P_IPV6); |
459 | else if (memcmp(p: skb->data + 6, q: ethertype_ipv4, |
460 | size: sizeof(ethertype_ipv4)) == 0) |
461 | skb->protocol = htons(ETH_P_IP); |
462 | else |
463 | goto error; |
464 | skb_pull(skb, len: sizeof(llc_oui_ipv4)); |
465 | skb_reset_network_header(skb); |
466 | skb->pkt_type = PACKET_HOST; |
467 | /* |
468 | * Let us waste some time for checking the encapsulation. |
469 | * Note, that only 7 char is checked so frames with a valid FCS |
470 | * are also accepted (but FCS is not checked of course). |
471 | */ |
472 | } else if ((skb->len >= sizeof(llc_oui_pid_pad)) && |
473 | (memcmp(p: skb->data, q: llc_oui_pid_pad, size: 7) == 0)) { |
474 | skb_pull(skb, len: sizeof(llc_oui_pid_pad)); |
475 | skb->protocol = eth_type_trans(skb, dev: net_dev); |
476 | } else |
477 | goto error; |
478 | |
479 | } else { /* e_vc */ |
480 | if (brdev->payload == p_routed) { |
481 | struct iphdr *iph; |
482 | |
483 | skb_reset_network_header(skb); |
484 | iph = ip_hdr(skb); |
485 | if (iph->version == 4) |
486 | skb->protocol = htons(ETH_P_IP); |
487 | else if (iph->version == 6) |
488 | skb->protocol = htons(ETH_P_IPV6); |
489 | else |
490 | goto error; |
491 | skb->pkt_type = PACKET_HOST; |
492 | } else { /* p_bridged */ |
493 | /* first 2 chars should be 0 */ |
494 | if (memcmp(p: skb->data, q: pad, BR2684_PAD_LEN) != 0) |
495 | goto error; |
496 | skb_pull(skb, BR2684_PAD_LEN); |
497 | skb->protocol = eth_type_trans(skb, dev: net_dev); |
498 | } |
499 | } |
500 | |
501 | #ifdef CONFIG_ATM_BR2684_IPFILTER |
502 | if (unlikely(packet_fails_filter(skb->protocol, brvcc, skb))) |
503 | goto dropped; |
504 | #endif /* CONFIG_ATM_BR2684_IPFILTER */ |
505 | skb->dev = net_dev; |
506 | ATM_SKB(skb)->vcc = atmvcc; /* needed ? */ |
507 | pr_debug("received packet's protocol: %x\n" , ntohs(skb->protocol)); |
508 | skb_debug(skb); |
509 | /* sigh, interface is down? */ |
510 | if (unlikely(!(net_dev->flags & IFF_UP))) |
511 | goto dropped; |
512 | net_dev->stats.rx_packets++; |
513 | net_dev->stats.rx_bytes += skb->len; |
514 | memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data)); |
515 | netif_rx(skb); |
516 | return; |
517 | |
518 | dropped: |
519 | net_dev->stats.rx_dropped++; |
520 | goto free_skb; |
521 | error: |
522 | net_dev->stats.rx_errors++; |
523 | free_skb: |
524 | dev_kfree_skb(skb); |
525 | } |
526 | |
527 | /* |
528 | * Assign a vcc to a dev |
529 | * Note: we do not have explicit unassign, but look at _push() |
530 | */ |
531 | static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg) |
532 | { |
533 | struct br2684_vcc *brvcc; |
534 | struct br2684_dev *brdev; |
535 | struct net_device *net_dev; |
536 | struct atm_backend_br2684 be; |
537 | int err; |
538 | |
539 | if (copy_from_user(to: &be, from: arg, n: sizeof be)) |
540 | return -EFAULT; |
541 | brvcc = kzalloc(size: sizeof(struct br2684_vcc), GFP_KERNEL); |
542 | if (!brvcc) |
543 | return -ENOMEM; |
544 | /* |
545 | * Allow two packets in the ATM queue. One actually being sent, and one |
546 | * for the ATM 'TX done' handler to send. It shouldn't take long to get |
547 | * the next one from the netdev queue, when we need it. More than that |
548 | * would be bufferbloat. |
549 | */ |
550 | atomic_set(v: &brvcc->qspace, i: 2); |
551 | write_lock_irq(&devs_lock); |
552 | net_dev = br2684_find_dev(s: &be.ifspec); |
553 | if (net_dev == NULL) { |
554 | pr_err("tried to attach to non-existent device\n" ); |
555 | err = -ENXIO; |
556 | goto error; |
557 | } |
558 | brdev = BRPRIV(net_dev); |
559 | if (atmvcc->push == NULL) { |
560 | err = -EBADFD; |
561 | goto error; |
562 | } |
563 | if (!list_empty(head: &brdev->brvccs)) { |
564 | /* Only 1 VCC/dev right now */ |
565 | err = -EEXIST; |
566 | goto error; |
567 | } |
568 | if (be.fcs_in != BR2684_FCSIN_NO || |
569 | be.fcs_out != BR2684_FCSOUT_NO || |
570 | be.fcs_auto || be.has_vpiid || be.send_padding || |
571 | (be.encaps != BR2684_ENCAPS_VC && |
572 | be.encaps != BR2684_ENCAPS_LLC) || |
573 | be.min_size != 0) { |
574 | err = -EINVAL; |
575 | goto error; |
576 | } |
577 | pr_debug("vcc=%p, encaps=%d, brvcc=%p\n" , atmvcc, be.encaps, brvcc); |
578 | if (list_empty(head: &brdev->brvccs) && !brdev->mac_was_set) { |
579 | unsigned char *esi = atmvcc->dev->esi; |
580 | const u8 one = 1; |
581 | |
582 | if (esi[0] | esi[1] | esi[2] | esi[3] | esi[4] | esi[5]) |
583 | dev_addr_set(dev: net_dev, addr: esi); |
584 | else |
585 | dev_addr_mod(dev: net_dev, offset: 2, addr: &one, len: 1); |
586 | } |
587 | list_add(new: &brvcc->brvccs, head: &brdev->brvccs); |
588 | write_unlock_irq(&devs_lock); |
589 | brvcc->device = net_dev; |
590 | brvcc->atmvcc = atmvcc; |
591 | atmvcc->user_back = brvcc; |
592 | brvcc->encaps = (enum br2684_encaps)be.encaps; |
593 | brvcc->old_push = atmvcc->push; |
594 | brvcc->old_pop = atmvcc->pop; |
595 | brvcc->old_release_cb = atmvcc->release_cb; |
596 | brvcc->old_owner = atmvcc->owner; |
597 | barrier(); |
598 | atmvcc->push = br2684_push; |
599 | atmvcc->pop = br2684_pop; |
600 | atmvcc->release_cb = br2684_release_cb; |
601 | atmvcc->owner = THIS_MODULE; |
602 | |
603 | /* initialize netdev carrier state */ |
604 | if (atmvcc->dev->signal == ATM_PHY_SIG_LOST) |
605 | netif_carrier_off(dev: net_dev); |
606 | else |
607 | netif_carrier_on(dev: net_dev); |
608 | |
609 | __module_get(THIS_MODULE); |
610 | |
611 | /* re-process everything received between connection setup and |
612 | backend setup */ |
613 | vcc_process_recv_queue(vcc: atmvcc); |
614 | return 0; |
615 | |
616 | error: |
617 | write_unlock_irq(&devs_lock); |
618 | kfree(objp: brvcc); |
619 | return err; |
620 | } |
621 | |
622 | static const struct net_device_ops br2684_netdev_ops = { |
623 | .ndo_start_xmit = br2684_start_xmit, |
624 | .ndo_set_mac_address = br2684_mac_addr, |
625 | .ndo_validate_addr = eth_validate_addr, |
626 | }; |
627 | |
628 | static const struct net_device_ops br2684_netdev_ops_routed = { |
629 | .ndo_start_xmit = br2684_start_xmit, |
630 | .ndo_set_mac_address = br2684_mac_addr, |
631 | }; |
632 | |
633 | static void br2684_setup(struct net_device *netdev) |
634 | { |
635 | struct br2684_dev *brdev = BRPRIV(net_dev: netdev); |
636 | |
637 | ether_setup(dev: netdev); |
638 | netdev->hard_header_len += sizeof(llc_oui_pid_pad); /* worst case */ |
639 | brdev->net_dev = netdev; |
640 | |
641 | netdev->netdev_ops = &br2684_netdev_ops; |
642 | |
643 | INIT_LIST_HEAD(list: &brdev->brvccs); |
644 | } |
645 | |
646 | static void br2684_setup_routed(struct net_device *netdev) |
647 | { |
648 | struct br2684_dev *brdev = BRPRIV(net_dev: netdev); |
649 | |
650 | brdev->net_dev = netdev; |
651 | netdev->hard_header_len = sizeof(llc_oui_ipv4); /* worst case */ |
652 | netdev->netdev_ops = &br2684_netdev_ops_routed; |
653 | netdev->addr_len = 0; |
654 | netdev->mtu = ETH_DATA_LEN; |
655 | netdev->min_mtu = 0; |
656 | netdev->max_mtu = ETH_MAX_MTU; |
657 | netdev->type = ARPHRD_PPP; |
658 | netdev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; |
659 | netdev->tx_queue_len = 100; |
660 | INIT_LIST_HEAD(list: &brdev->brvccs); |
661 | } |
662 | |
663 | static int br2684_create(void __user *arg) |
664 | { |
665 | int err; |
666 | struct net_device *netdev; |
667 | struct br2684_dev *brdev; |
668 | struct atm_newif_br2684 ni; |
669 | enum br2684_payload payload; |
670 | |
671 | pr_debug("\n" ); |
672 | |
673 | if (copy_from_user(to: &ni, from: arg, n: sizeof ni)) |
674 | return -EFAULT; |
675 | |
676 | if (ni.media & BR2684_FLAG_ROUTED) |
677 | payload = p_routed; |
678 | else |
679 | payload = p_bridged; |
680 | ni.media &= 0xffff; /* strip flags */ |
681 | |
682 | if (ni.media != BR2684_MEDIA_ETHERNET || ni.mtu != 1500) |
683 | return -EINVAL; |
684 | |
685 | netdev = alloc_netdev(sizeof(struct br2684_dev), |
686 | ni.ifname[0] ? ni.ifname : "nas%d" , |
687 | NET_NAME_UNKNOWN, |
688 | (payload == p_routed) ? br2684_setup_routed : br2684_setup); |
689 | if (!netdev) |
690 | return -ENOMEM; |
691 | |
692 | brdev = BRPRIV(net_dev: netdev); |
693 | |
694 | pr_debug("registered netdev %s\n" , netdev->name); |
695 | /* open, stop, do_ioctl ? */ |
696 | err = register_netdev(dev: netdev); |
697 | if (err < 0) { |
698 | pr_err("register_netdev failed\n" ); |
699 | free_netdev(dev: netdev); |
700 | return err; |
701 | } |
702 | |
703 | write_lock_irq(&devs_lock); |
704 | |
705 | brdev->payload = payload; |
706 | |
707 | if (list_empty(head: &br2684_devs)) { |
708 | /* 1st br2684 device */ |
709 | brdev->number = 1; |
710 | } else |
711 | brdev->number = BRPRIV(net_dev: list_entry_brdev(le: br2684_devs.prev))->number + 1; |
712 | |
713 | list_add_tail(new: &brdev->br2684_devs, head: &br2684_devs); |
714 | write_unlock_irq(&devs_lock); |
715 | return 0; |
716 | } |
717 | |
718 | /* |
719 | * This handles ioctls actually performed on our vcc - we must return |
720 | * -ENOIOCTLCMD for any unrecognized ioctl |
721 | */ |
722 | static int br2684_ioctl(struct socket *sock, unsigned int cmd, |
723 | unsigned long arg) |
724 | { |
725 | struct atm_vcc *atmvcc = ATM_SD(sock); |
726 | void __user *argp = (void __user *)arg; |
727 | atm_backend_t b; |
728 | |
729 | int err; |
730 | switch (cmd) { |
731 | case ATM_SETBACKEND: |
732 | case ATM_NEWBACKENDIF: |
733 | err = get_user(b, (atm_backend_t __user *) argp); |
734 | if (err) |
735 | return -EFAULT; |
736 | if (b != ATM_BACKEND_BR2684) |
737 | return -ENOIOCTLCMD; |
738 | if (!capable(CAP_NET_ADMIN)) |
739 | return -EPERM; |
740 | if (cmd == ATM_SETBACKEND) { |
741 | if (sock->state != SS_CONNECTED) |
742 | return -EINVAL; |
743 | return br2684_regvcc(atmvcc, arg: argp); |
744 | } else { |
745 | return br2684_create(arg: argp); |
746 | } |
747 | #ifdef CONFIG_ATM_BR2684_IPFILTER |
748 | case BR2684_SETFILT: |
749 | if (atmvcc->push != br2684_push) |
750 | return -ENOIOCTLCMD; |
751 | if (!capable(CAP_NET_ADMIN)) |
752 | return -EPERM; |
753 | err = br2684_setfilt(atmvcc, arg: argp); |
754 | |
755 | return err; |
756 | #endif /* CONFIG_ATM_BR2684_IPFILTER */ |
757 | } |
758 | return -ENOIOCTLCMD; |
759 | } |
760 | |
761 | static struct atm_ioctl br2684_ioctl_ops = { |
762 | .owner = THIS_MODULE, |
763 | .ioctl = br2684_ioctl, |
764 | }; |
765 | |
766 | #ifdef CONFIG_PROC_FS |
767 | static void *br2684_seq_start(struct seq_file *seq, loff_t * pos) |
768 | __acquires(devs_lock) |
769 | { |
770 | read_lock(&devs_lock); |
771 | return seq_list_start(head: &br2684_devs, pos: *pos); |
772 | } |
773 | |
774 | static void *br2684_seq_next(struct seq_file *seq, void *v, loff_t * pos) |
775 | { |
776 | return seq_list_next(v, head: &br2684_devs, ppos: pos); |
777 | } |
778 | |
779 | static void br2684_seq_stop(struct seq_file *seq, void *v) |
780 | __releases(devs_lock) |
781 | { |
782 | read_unlock(&devs_lock); |
783 | } |
784 | |
785 | static int br2684_seq_show(struct seq_file *seq, void *v) |
786 | { |
787 | const struct br2684_dev *brdev = list_entry(v, struct br2684_dev, |
788 | br2684_devs); |
789 | const struct net_device *net_dev = brdev->net_dev; |
790 | const struct br2684_vcc *brvcc; |
791 | |
792 | seq_printf(m: seq, fmt: "dev %.16s: num=%d, mac=%pM (%s)\n" , |
793 | net_dev->name, |
794 | brdev->number, |
795 | net_dev->dev_addr, |
796 | brdev->mac_was_set ? "set" : "auto" ); |
797 | |
798 | list_for_each_entry(brvcc, &brdev->brvccs, brvccs) { |
799 | seq_printf(m: seq, fmt: " vcc %d.%d.%d: encaps=%s payload=%s" |
800 | ", failed copies %u/%u" |
801 | "\n" , brvcc->atmvcc->dev->number, |
802 | brvcc->atmvcc->vpi, brvcc->atmvcc->vci, |
803 | (brvcc->encaps == e_llc) ? "LLC" : "VC" , |
804 | (brdev->payload == p_bridged) ? "bridged" : "routed" , |
805 | brvcc->copies_failed, brvcc->copies_needed); |
806 | #ifdef CONFIG_ATM_BR2684_IPFILTER |
807 | if (brvcc->filter.netmask != 0) |
808 | seq_printf(m: seq, fmt: " filter=%pI4/%pI4\n" , |
809 | &brvcc->filter.prefix, |
810 | &brvcc->filter.netmask); |
811 | #endif /* CONFIG_ATM_BR2684_IPFILTER */ |
812 | } |
813 | return 0; |
814 | } |
815 | |
816 | static const struct seq_operations br2684_seq_ops = { |
817 | .start = br2684_seq_start, |
818 | .next = br2684_seq_next, |
819 | .stop = br2684_seq_stop, |
820 | .show = br2684_seq_show, |
821 | }; |
822 | |
823 | extern struct proc_dir_entry *atm_proc_root; /* from proc.c */ |
824 | #endif /* CONFIG_PROC_FS */ |
825 | |
826 | static int __init br2684_init(void) |
827 | { |
828 | #ifdef CONFIG_PROC_FS |
829 | struct proc_dir_entry *p; |
830 | p = proc_create_seq("br2684" , 0, atm_proc_root, &br2684_seq_ops); |
831 | if (p == NULL) |
832 | return -ENOMEM; |
833 | #endif |
834 | register_atm_ioctl(&br2684_ioctl_ops); |
835 | register_atmdevice_notifier(nb: &atm_dev_notifier); |
836 | return 0; |
837 | } |
838 | |
839 | static void __exit br2684_exit(void) |
840 | { |
841 | struct net_device *net_dev; |
842 | struct br2684_dev *brdev; |
843 | struct br2684_vcc *brvcc; |
844 | deregister_atm_ioctl(&br2684_ioctl_ops); |
845 | |
846 | #ifdef CONFIG_PROC_FS |
847 | remove_proc_entry("br2684" , atm_proc_root); |
848 | #endif |
849 | |
850 | |
851 | unregister_atmdevice_notifier(nb: &atm_dev_notifier); |
852 | |
853 | while (!list_empty(head: &br2684_devs)) { |
854 | net_dev = list_entry_brdev(le: br2684_devs.next); |
855 | brdev = BRPRIV(net_dev); |
856 | while (!list_empty(head: &brdev->brvccs)) { |
857 | brvcc = list_entry_brvcc(le: brdev->brvccs.next); |
858 | br2684_close_vcc(brvcc); |
859 | } |
860 | |
861 | list_del(entry: &brdev->br2684_devs); |
862 | unregister_netdev(dev: net_dev); |
863 | free_netdev(dev: net_dev); |
864 | } |
865 | } |
866 | |
867 | module_init(br2684_init); |
868 | module_exit(br2684_exit); |
869 | |
870 | MODULE_AUTHOR("Marcell GAL" ); |
871 | MODULE_DESCRIPTION("RFC2684 bridged protocols over ATM/AAL5" ); |
872 | MODULE_LICENSE("GPL" ); |
873 | |