1 diff -urN linux.orig/Documentation/Configure.help linux/Documentation/Configure.help
2 --- linux.orig/Documentation/Configure.help.orig Fri Jan 4 12:58:32 2002
3 +++ linux/Documentation/Configure.help Fri Jan 4 13:00:14 2002
5 briefly removed during revalidation. If you say Y here, packets to
6 such neighbours are silently discarded instead.
8 +RFC1483/2684 Bridged protocols
10 + ATM PVCs can carry ethernet PDUs according to rfc2684 (formerly 1483)
11 + This device will act like an ethernet from the kernels point of view,
12 + with the traffic being carried by ATM PVCs (currently 1 PVC/device).
13 + This is sometimes used over DSL lines. If in doubt, say N.
15 +Per-VC IP filter kludge
16 +CONFIG_ATM_BR2684_IPFILTER
17 + This is an experimental mechanism for users who need to terminating a
18 + large number of IP-only vcc's. Do not enable this unless you are sure
19 + you know what you are doing.
21 LAN Emulation (LANE) support
23 LAN Emulation emulates services of existing LANs across an ATM
24 @@ -8826,6 +8839,13 @@
25 pppd, along with binaries of a patched pppd package can be found at:
26 <http://www.shoshin.uwaterloo.ca/~mostrows/>.
28 +PPP over ATM (EXPERIMENTAL)
30 + PPP over ATM is one of several protocols used over DSL lines.
31 + If you are connecting to a DSL line using an internal ATM or
32 + DSL adaptor (as opposed to an ethernet card) then there is
33 + a good possibility you will need this protocol.
35 Wireless LAN (non-hamradio)
37 Support for wireless LANs and everything having to do with radio,
38 diff -urN linux.orig/MAINTAINERS linux/MAINTAINERS
39 --- linux.orig/MAINTAINERS Sat Apr 21 18:05:00 2001
40 +++ linux/MAINTAINERS Sat Apr 21 18:07:12 2001
41 @@ -1060,6 +1060,11 @@
42 L: linux-ppp@vger.kernel.org
45 +PPP OVER ATM (RFC 2364)
52 M: mostrows@styx.uwaterloo.ca
53 diff -urN linux.orig/arch/sparc/config.in linux/arch/sparc/config.in
54 --- linux.orig/arch/sparc/config.in Sat Apr 21 18:04:59 2001
55 +++ linux/arch/sparc/config.in Sat Apr 21 18:06:09 2001
57 dep_tristate ' PPP support for sync tty ports' CONFIG_PPP_SYNC_TTY $CONFIG_PPP
58 dep_tristate ' PPP Deflate compression' CONFIG_PPP_DEFLATE $CONFIG_PPP
59 dep_tristate ' PPP BSD-Compress compression' CONFIG_PPP_BSDCOMP m
60 + if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
61 + dep_tristate ' PPP over Ethernet (EXPERIMENTAL)' CONFIG_PPPOE $CONFIG_PPP
62 + if [ "$CONFIG_ATM" = "y" ]; then
63 + dep_tristate ' PPP over ATM (EXPERIMENTAL)' CONFIG_PPPOATM $CONFIG_PPP
67 tristate ' SLIP (serial line) support' CONFIG_SLIP
68 if [ "$CONFIG_SLIP" != "n" ]; then
69 diff -urN linux.orig/drivers/net/Config.in linux/drivers/net/Config.in
70 --- linux.orig/drivers/net/Config.in Sat Apr 21 18:04:55 2001
71 +++ linux/drivers/net/Config.in Sat Apr 21 18:06:09 2001
73 dep_tristate ' PPP BSD-Compress compression' CONFIG_PPP_BSDCOMP $CONFIG_PPP
74 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
75 dep_tristate ' PPP over Ethernet (EXPERIMENTAL)' CONFIG_PPPOE $CONFIG_PPP
76 + if [ "$CONFIG_ATM" = "y" ]; then
77 + dep_tristate ' PPP over ATM (EXPERIMENTAL)' CONFIG_PPPOATM $CONFIG_PPP $CONFIG_EXPERIMENTAL
82 diff -urN linux.orig/include/linux/atmbr2684.h linux/include/linux/atmbr2684.h
83 --- linux.orig/include/linux/atmbr2684.h Thu Jan 1 01:00:00 1970
84 +++ linux/include/linux/atmbr2684.h Sat Apr 21 18:06:09 2001
86 +#ifndef _LINUX_ATMBR2684_H
87 +#define _LINUX_ATMBR2684_H
89 +#include <linux/atm.h>
90 +#include <linux/if.h> /* For IFNAMSIZ */
93 + * Type of media we're bridging (ethernet, token ring, etc) Currently only
94 + * ethernet is supported
96 +#define BR2684_MEDIA_ETHERNET (0) /* 802.3 */
97 +#define BR2684_MEDIA_802_4 (1) /* 802.4 */
98 +#define BR2684_MEDIA_TR (2) /* 802.5 - token ring */
99 +#define BR2684_MEDIA_FDDI (3)
100 +#define BR2684_MEDIA_802_6 (4) /* 802.6 */
103 + * Is there FCS inbound on this VC? This currently isn't supported.
105 +#define BR2684_FCSIN_NO (0)
106 +#define BR2684_FCSIN_IGNORE (1)
107 +#define BR2684_FCSIN_VERIFY (2)
110 + * Is there FCS outbound on this VC? This currently isn't supported.
112 +#define BR2684_FCSOUT_NO (0)
113 +#define BR2684_FCSOUT_SENDZERO (1)
114 +#define BR2684_FCSOUT_GENERATE (2)
117 + * Does this VC include LLC encapsulation?
119 +#define BR2684_ENCAPS_VC (0) /* VC-mux */
120 +#define BR2684_ENCAPS_LLC (1)
121 +#define BR2684_ENCAPS_AUTODETECT (2) /* Unsuported */
124 + * This is for the ATM_NEWBACKENDIF call - these are like socket families:
125 + * the first element of the structure is the backend number and the rest
126 + * is per-backend specific
128 +struct atm_newif_br2684 {
129 + atm_backend_t backend_num; /* ATM_BACKEND_BR2684 */
130 + int media; /* BR2684_MEDIA_* */
131 + char ifname[IFNAMSIZ];
136 + * This structure is used to specify a br2684 interface - either by a
137 + * positive integer (returned by ATM_NEWBACKENDIF) or the interfaces name
139 +#define BR2684_FIND_BYNOTHING (0)
140 +#define BR2684_FIND_BYNUM (1)
141 +#define BR2684_FIND_BYIFNAME (2)
142 +struct br2684_if_spec {
143 + int method; /* BR2684_FIND_* */
145 + char ifname[IFNAMSIZ];
151 + * This is for the ATM_SETBACKEND call - these are like socket families:
152 + * the first element of the structure is the backend number and the rest
153 + * is per-backend specific
155 +struct atm_backend_br2684 {
156 + atm_backend_t backend_num; /* ATM_BACKEND_BR2684 */
157 + struct br2684_if_spec ifspec;
158 + int fcs_in; /* BR2684_FCSIN_* */
159 + int fcs_out; /* BR2684_FCSOUT_* */
160 + int fcs_auto; /* 1: fcs_{in,out} disabled if no FCS rx'ed */
161 + int encaps; /* BR2684_ENCAPS_* */
162 + int has_vpiid; /* 1: use vpn_id - Unsupported */
164 + int send_padding; /* unsupported */
165 + int min_size; /* we will pad smaller packets than this */
169 + * The BR2684_SETFILT ioctl is an experimental mechanism for folks
170 + * terminating a large number of IP-only vcc's. When netfilter allows
171 + * efficient per-if in/out filters, this support will be removed
173 +struct br2684_filter {
174 + __u32 prefix; /* network byte order */
175 + __u32 netmask; /* 0 = disable filter */
178 +struct br2684_filter_set {
179 + struct br2684_if_spec ifspec;
180 + struct br2684_filter filter;
183 +#define BR2684_SETFILT _IOW( 'a', ATMIOC_BACKEND + 0, \
184 + struct br2684_filter_set)
186 +#endif /* _LINUX_ATMBR2684_H */
187 diff -urN linux.orig/include/linux/atmdev.h linux/include/linux/atmdev.h
188 --- linux.orig/include/linux/atmdev.h Tue Mar 27 01:50:03 2001
189 +++ linux/include/linux/atmdev.h Sat Apr 21 18:06:09 2001
191 /* enable or disable single-copy */
192 #define ATM_SETBACKEND _IOW('a',ATMIOC_SPECIAL+2,atm_backend_t)
193 /* set backend handler */
194 +#define ATM_NEWBACKENDIF _IOW('a',ATMIOC_SPECIAL+3,atm_backend_t)
195 + /* use backend to make new if */
198 * These are backend handkers that can be set via the ATM_SETBACKEND call
199 diff -urN linux.orig/net/Config.in linux/net/Config.in
200 --- linux.orig/net/Config.in Sat Apr 21 18:05:00 2001
201 +++ linux/net/Config.in Sat Apr 21 18:06:09 2001
203 if [ "$CONFIG_INET" = "y" -a "$CONFIG_ATM_LANE" != "n" ]; then
204 tristate ' Multi-Protocol Over ATM (MPOA) support' CONFIG_ATM_MPOA
206 + tristate ' RFC1483/2684 Bridged protocols' CONFIG_ATM_BR2684
207 + if [ "$CONFIG_ATM_BR2684" != "n" ]; then
208 + bool ' Per-VC IP filter kludge' CONFIG_ATM_BR2684_IPFILTER
213 diff -urN linux.orig/net/atm/Makefile linux/net/atm/Makefile
214 --- linux.orig/net/atm/Makefile Tue Mar 27 01:36:30 2001
215 +++ linux/net/atm/Makefile Sat Apr 21 18:06:09 2001
217 NEED_IPCOM = ipcommon.o
220 +ifeq ($(CONFIG_ATM_BR2684),y)
221 + NEED_IPCOM = ipcommon.o
223 + ifeq ($(CONFIG_ATM_BR2684),m)
224 + NEED_IPCOM = ipcommon.o
227 +obj-$(CONFIG_ATM_BR2684) += br2684.o
229 ifeq ($(CONFIG_NET_SCH_ATM),y)
230 NEED_IPCOM = ipcommon.o
232 diff -urN linux.orig/net/atm/br2684.c linux/net/atm/br2684.c
233 --- linux.orig/net/atm/br2684.c Thu Jan 1 01:00:00 1970
234 +++ linux/net/atm/br2684.c Sat Apr 21 18:06:09 2001
237 +Experimental ethernet netdevice using ATM AAL5 as underlying carrier
238 +(RFC1483 obsoleted by RFC2684) for Linux 2.4
239 +Author: Marcell GAL, 2000, XDSL Ltd, Hungary
242 +#include <linux/module.h>
243 +#include <linux/config.h>
244 +#include <linux/init.h>
245 +#include <linux/kernel.h>
246 +#include <linux/list.h>
247 +#include <asm/uaccess.h>
248 +#include <linux/netdevice.h>
249 +#include <linux/skbuff.h>
250 +#include <linux/etherdevice.h>
251 +#include <net/arp.h>
252 +#include <linux/rtnetlink.h>
253 +#include <linux/atmbr2684.h>
255 +#include "ipcommon.h"
258 + * Define this to use a version of the code which interacts with the higher
259 + * layers in a more intellegent way, by always reserving enough space for
260 + * our header at the begining of the packet. However, there may still be
261 + * some problems with programs like tcpdump. In 2.5 we'll sort out what
262 + * we need to do to get this perfect. For now we just will copy the packet
263 + * if we need space for the header
265 +/* #define FASTER_VERSION */
268 +#define DPRINTK(format, args...) printk(KERN_DEBUG "br2684: " format, ##args)
270 +#define DPRINTK(format, args...)
274 +static void skb_debug(const struct sk_buff *skb)
276 +#define NUM2PRINT 50
277 + char buf[NUM2PRINT * 3 + 1]; /* 3 chars per byte */
279 + for (i = 0; i < skb->len && i < NUM2PRINT; i++) {
280 + sprintf(buf + i * 3, "%2.2x ", 0xff & skb->data[i]);
282 + printk(KERN_DEBUG "br2684: skb: %s\n", buf);
285 +#define skb_debug(skb) do {} while (0)
288 +static unsigned char llc_oui_pid_pad[] =
289 + { 0xAA, 0xAA, 0x03, 0x00, 0x80, 0xC2, 0x00, 0x07, 0x00, 0x00 };
292 +enum br2684_encaps {
293 + e_vc = BR2684_ENCAPS_VC,
294 + e_llc = BR2684_ENCAPS_LLC,
298 + struct atm_vcc *atmvcc;
299 + struct br2684_dev *brdev;
300 + /* keep old push,pop functions for chaining */
301 + void (*old_push)(struct atm_vcc *vcc,struct sk_buff *skb);
302 + /* void (*old_pop)(struct atm_vcc *vcc,struct sk_buff *skb); */
303 + enum br2684_encaps encaps;
304 + struct list_head brvccs;
305 +#ifdef CONFIG_ATM_BR2684_IPFILTER
306 + struct br2684_filter filter;
307 +#endif /* CONFIG_ATM_BR2684_IPFILTER */
308 +#ifndef FASTER_VERSION
309 + unsigned copies_needed, copies_failed;
310 +#endif /* FASTER_VERSION */
314 + struct net_device net_dev;
315 + struct list_head br2684_devs;
317 + struct list_head brvccs; /* one device <=> one vcc (before xmas) */
318 + struct net_device_stats stats;
323 + * This lock should be held for writing any time the list of devices or
324 + * their attached vcc's could be altered. It should be held for reading
325 + * any time these are being queried. Note that we sometimes need to
326 + * do read-locking under interrupt context, so write locking must block
327 + * the current CPU's interrupts
329 +static rwlock_t devs_lock = RW_LOCK_UNLOCKED;
331 +static LIST_HEAD(br2684_devs);
333 +static inline struct br2684_dev *BRPRIV(const struct net_device *net_dev)
335 + return (struct br2684_dev *) ((char *) (net_dev) -
336 + (unsigned long) (&((struct br2684_dev *) 0)->net_dev));
339 +static inline struct br2684_dev *list_entry_brdev(const struct list_head *le)
341 + return list_entry(le, struct br2684_dev, br2684_devs);
344 +static inline struct br2684_vcc *BR2684_VCC(const struct atm_vcc *atmvcc)
346 + return (struct br2684_vcc *) (atmvcc->user_back);
349 +static inline struct br2684_vcc *list_entry_brvcc(const struct list_head *le)
351 + return list_entry(le, struct br2684_vcc, brvccs);
354 +/* Caller should hold read_lock(&devs_lock) */
355 +static struct br2684_dev *br2684_find_dev(const struct br2684_if_spec *s)
357 + struct list_head *lh;
358 + struct br2684_dev *brdev;
359 + switch (s->method) {
360 + case BR2684_FIND_BYNUM:
361 + list_for_each(lh, &br2684_devs) {
362 + brdev = list_entry_brdev(lh);
363 + if (brdev->number == s->spec.devnum)
367 + case BR2684_FIND_BYIFNAME:
368 + list_for_each(lh, &br2684_devs) {
369 + brdev = list_entry_brdev(lh);
370 + if (!strncmp(brdev->net_dev.name, s->spec.ifname,
371 + sizeof brdev->net_dev.name))
380 + * Send a packet out a particular vcc. Not to useful right now, but paves
381 + * the way for multiple vcc's per itf. Returns true if we can send,
384 +static int br2684_xmit_vcc(struct sk_buff *skb, struct br2684_dev *brdev,
385 + struct br2684_vcc *brvcc)
387 + struct atm_vcc *atmvcc;
388 +#ifdef FASTER_VERSION
389 + if (brvcc->encaps == e_llc)
390 + memcpy(skb_push(skb, 8), llc_oui_pid_pad, 8);
391 + /* last 2 bytes of llc_oui_pid_pad are managed by header routines;
392 + yes, you got it: 8 + 2 = sizeof(llc_oui_pid_pad)
395 + int minheadroom = (brvcc->encaps == e_llc) ? 10 : 2;
396 + if (skb_headroom(skb) < minheadroom) {
397 + struct sk_buff *skb2 = skb_realloc_headroom(skb, minheadroom);
398 + brvcc->copies_needed++;
399 + dev_kfree_skb(skb);
400 + if (skb2 == NULL) {
401 + brvcc->copies_failed++;
406 + skb_push(skb, minheadroom);
407 + if (brvcc->encaps == e_llc)
408 + memcpy(skb->data, llc_oui_pid_pad, 10);
410 + memset(skb->data, 0, 2);
411 +#endif /* FASTER_VERSION */
414 + ATM_SKB(skb)->vcc = atmvcc = brvcc->atmvcc;
415 + DPRINTK("atm_skb(%p)->vcc(%p)->dev(%p)\n", skb, atmvcc, atmvcc->dev);
416 + if (!atm_may_send(atmvcc, skb->truesize)) {
417 + /* we free this here for now, because we cannot know in a higher
418 + layer whether the skb point it supplied wasn't freed yet.
421 + dev_kfree_skb(skb);
424 + atomic_add(skb->truesize, &atmvcc->tx_inuse);
425 + ATM_SKB(skb)->iovcnt = 0;
426 + ATM_SKB(skb)->atm_options = atmvcc->atm_options;
427 + brdev->stats.tx_packets++;
428 + brdev->stats.tx_bytes += skb->len;
429 + atmvcc->send(atmvcc, skb);
433 +static inline struct br2684_vcc *pick_outgoing_vcc(struct sk_buff *skb,
434 + struct br2684_dev *brdev)
436 + return list_empty(&brdev->brvccs) ? NULL :
437 + list_entry_brvcc(brdev->brvccs.next); /* 1 vcc/dev right now */
440 +static int br2684_start_xmit(struct sk_buff *skb, struct net_device *dev)
442 + struct br2684_dev *brdev = BRPRIV(dev);
443 + struct br2684_vcc *brvcc;
445 + DPRINTK("br2684_start_xmit, skb->dst=%p\n", skb->dst);
446 + read_lock(&devs_lock);
447 + brvcc = pick_outgoing_vcc(skb, brdev);
448 + if (brvcc == NULL) {
449 + DPRINTK("no vcc attached to dev %s\n", dev->name);
450 + brdev->stats.tx_errors++;
451 + brdev->stats.tx_carrier_errors++;
452 + /* netif_stop_queue(dev); */
453 + dev_kfree_skb(skb);
454 + read_unlock(&devs_lock);
457 + if (!br2684_xmit_vcc(skb, brdev, brvcc)) {
459 + * We should probably use netif_*_queue() here, but that
460 + * involves added complication. We need to walk before
463 + /* don't free here! this pointer might be no longer valid!
464 + dev_kfree_skb(skb);
466 + brdev->stats.tx_errors++;
467 + brdev->stats.tx_fifo_errors++;
469 + read_unlock(&devs_lock);
473 +static struct net_device_stats *br2684_get_stats(struct net_device *dev)
475 + DPRINTK("br2684_get_stats\n");
476 + return &BRPRIV(dev)->stats;
479 +#ifdef FASTER_VERSION
481 + * These mirror eth_header and eth_header_cache. They are not usually
482 + * exported for use in modules, so we grab them from net_device
483 + * after ether_setup() is done with it. Bit of a hack.
485 +static int (*my_eth_header)(struct sk_buff *, struct net_device *,
486 + unsigned short, void *, void *, unsigned);
487 +static int (*my_eth_header_cache)(struct neighbour *, struct hh_cache *);
490 +br2684_header(struct sk_buff *skb, struct net_device *dev,
491 + unsigned short type, void *daddr, void *saddr, unsigned len)
493 + u16 *pad_before_eth;
494 + int t = my_eth_header(skb, dev, type, daddr, saddr, len);
496 + pad_before_eth = (u16 *) skb_push(skb, 2);
497 + *pad_before_eth = 0;
498 + return dev->hard_header_len; /* or return 16; ? */
504 +br2684_header_cache(struct neighbour *neigh, struct hh_cache *hh)
506 +/* hh_data is 16 bytes long. if encaps is ether-llc we need 24, so
507 +xmit will add the additional header part in that case */
508 + u16 *pad_before_eth = (u16 *)(hh->hh_data);
509 + int t = my_eth_header_cache(neigh, hh);
510 + DPRINTK("br2684_header_cache, neigh=%p, hh_cache=%p\n", neigh, hh);
514 + *pad_before_eth = 0;
515 + hh->hh_len = PADLEN + ETH_HLEN;
521 + * This is similar to eth_type_trans, which cannot be used because of
522 + * our dev->hard_header_len
524 +static inline unsigned short br_type_trans(struct sk_buff *skb,
525 + struct net_device *dev)
527 + struct ethhdr *eth;
528 + unsigned char *rawp;
529 + eth = skb->mac.ethernet;
531 + if (*eth->h_dest & 1) {
532 + if (memcmp(eth->h_dest, dev->broadcast, ETH_ALEN) == 0)
533 + skb->pkt_type = PACKET_BROADCAST;
535 + skb->pkt_type = PACKET_MULTICAST;
538 + else if (memcmp(eth->h_dest, dev->dev_addr, ETH_ALEN))
539 + skb->pkt_type = PACKET_OTHERHOST;
541 + if (ntohs(eth->h_proto) >= 1536)
542 + return eth->h_proto;
547 + * This is a magic hack to spot IPX packets. Older Novell breaks
548 + * the protocol design and runs IPX over 802.3 without an 802.2 LLC
549 + * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This
550 + * won't work for fault tolerant netware but does for the rest.
552 + if (*(unsigned short *) rawp == 0xFFFF)
553 + return htons(ETH_P_802_3);
558 + return htons(ETH_P_802_2);
560 +#endif /* FASTER_VERSION */
563 + * We remember when the MAC gets set, so we don't override it later with
564 + * the ESI of the ATM card of the first VC
566 +static int (*my_eth_mac_addr)(struct net_device *, void *);
567 +static int br2684_mac_addr(struct net_device *dev, void *p)
569 + int err = my_eth_mac_addr(dev, p);
571 + BRPRIV(dev)->mac_was_set = 1;
575 +#ifdef CONFIG_ATM_BR2684_IPFILTER
576 +/* this IOCTL is experimental. */
577 +static int br2684_setfilt(struct atm_vcc *atmvcc, unsigned long arg)
579 + struct br2684_vcc *brvcc;
580 + struct br2684_filter_set fs;
582 + if (copy_from_user(&fs, (void *) arg, sizeof fs))
584 + if (fs.ifspec.method != BR2684_FIND_BYNOTHING) {
586 + * This is really a per-vcc thing, but we can also search
589 + struct br2684_dev *brdev;
590 + read_lock(&devs_lock);
591 + brdev = br2684_find_dev(&fs.ifspec);
592 + if (brdev == NULL || list_empty(&brdev->brvccs) ||
593 + brdev->brvccs.next != brdev->brvccs.prev) /* >1 VCC */
596 + brvcc = list_entry_brvcc(brdev->brvccs.next);
597 + read_unlock(&devs_lock);
601 + brvcc = BR2684_VCC(atmvcc);
602 + memcpy(&brvcc->filter, &fs.filter, sizeof(brvcc->filter));
606 +/* Returns 1 if packet should be dropped */
608 +packet_fails_filter(u16 type, struct br2684_vcc *brvcc, struct sk_buff *skb)
610 + if (brvcc->filter.netmask == 0)
611 + return 0; /* no filter in place */
612 + if (type == __constant_htons(ETH_P_IP) &&
613 + (((struct iphdr *) (skb->data))->daddr & brvcc->filter.
614 + netmask) == brvcc->filter.prefix)
616 + if (type == __constant_htons(ETH_P_ARP))
618 + /* TODO: we should probably filter ARPs too.. don't want to have
619 + * them returning values that don't make sense, or is that ok?
621 + return 1; /* drop */
623 +#endif /* CONFIG_ATM_BR2684_IPFILTER */
625 +static void br2684_close_vcc(struct br2684_vcc *brvcc)
627 + DPRINTK("removing VCC %p from dev %p\n", brvcc, brvcc->brdev);
628 + write_lock_irq(&devs_lock);
629 + list_del(&brvcc->brvccs);
630 + write_unlock_irq(&devs_lock);
631 + brvcc->atmvcc->user_back = NULL; /* what about vcc->recvq ??? */
632 + brvcc->old_push(brvcc->atmvcc, NULL); /* pass on the bad news */
637 +/* when AAL5 PDU comes in: */
638 +static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb)
640 + struct br2684_vcc *brvcc = BR2684_VCC(atmvcc);
641 + struct br2684_dev *brdev = brvcc->brdev;
642 + int plen = sizeof(llc_oui_pid_pad) + ETH_HLEN;
644 + DPRINTK("br2684_push\n");
646 + if (skb == NULL) { /* skb==NULL means VCC is being destroyed */
647 + br2684_close_vcc(brvcc);
652 + atm_return(atmvcc, skb->truesize);
653 + DPRINTK("skb from brdev %p\n", brdev);
654 + if (brvcc->encaps == e_llc) {
655 + /* let us waste some time for checking the encapsulation.
656 + Note, that only 7 char is checked so frames with a valid FCS
657 + are also accepted (but FCS is not checked of course) */
658 + if (memcmp(skb->data, llc_oui_pid_pad, 7)) {
659 + brdev->stats.rx_errors++;
660 + dev_kfree_skb(skb);
664 + plen = PADLEN + ETH_HLEN; /* pad, dstmac,srcmac, ethtype */
665 + /* first 2 chars should be 0 */
666 + if (*((u16 *) (skb->data)) != 0) {
667 + brdev->stats.rx_errors++;
668 + dev_kfree_skb(skb);
672 + if (skb->len < plen) {
673 + brdev->stats.rx_errors++;
674 + dev_kfree_skb(skb); /* dev_ not needed? */
678 +#ifdef FASTER_VERSION
679 + /* FIXME: tcpdump shows that pointer to mac header is 2 bytes earlier,
680 + than should be. What else should I set? */
681 + skb_pull(skb, plen);
682 + skb->mac.raw = ((char *) (skb->data)) - ETH_HLEN;
683 + skb->pkt_type = PACKET_HOST;
684 +#ifdef CONFIG_BR2684_FAST_TRANS
685 + skb->protocol = ((u16 *) skb->data)[-1];
686 +#else /* some protocols might require this: */
687 + skb->protocol = br_type_trans(skb, &brdev->net_dev);
688 +#endif /* CONFIG_BR2684_FAST_TRANS */
690 + skb_pull(skb, plen - ETH_HLEN);
691 + skb->protocol = eth_type_trans(skb, &brdev->net_dev);
692 +#endif /* FASTER_VERSION */
693 +#ifdef CONFIG_ATM_BR2684_IPFILTER
694 + if (packet_fails_filter(skb->protocol, brvcc, skb)) {
695 + brdev->stats.rx_dropped++;
696 + dev_kfree_skb(skb);
699 +#endif /* CONFIG_ATM_BR2684_IPFILTER */
700 + skb->dev = &brdev->net_dev;
701 + ATM_SKB(skb)->vcc = atmvcc; /* needed ? */
702 + DPRINTK("received packet's protocol: %x\n", ntohs(skb->protocol));
704 + if (!(brdev->net_dev.flags & IFF_UP)) { /* sigh, interface is down */
705 + brdev->stats.rx_dropped++;
706 + dev_kfree_skb(skb);
709 + brdev->stats.rx_packets++;
710 + brdev->stats.rx_bytes += skb->len;
714 +static int br2684_regvcc(struct atm_vcc *atmvcc, unsigned long arg)
716 +/* assign a vcc to a dev
717 +Note: we do not have explicit unassign, but look at _push()
720 + struct br2684_vcc *brvcc;
721 + struct sk_buff_head copy;
722 + struct sk_buff *skb;
723 + struct br2684_dev *brdev;
724 + struct atm_backend_br2684 be;
727 + if (copy_from_user(&be, (void *) arg, sizeof be)) {
731 + write_lock_irq(&devs_lock);
732 + brdev = br2684_find_dev(&be.ifspec);
733 + if (brdev == NULL) {
735 + "br2684: tried to attach to non-existant device\n");
739 + if (atmvcc->push == NULL) {
743 + if (!list_empty(&brdev->brvccs)) { /* Only 1 VCC/dev right now */
747 + if (be.fcs_in != BR2684_FCSIN_NO || be.fcs_out != BR2684_FCSOUT_NO ||
748 + be.fcs_auto || be.has_vpiid || be.send_padding || (be.encaps !=
749 + BR2684_ENCAPS_VC && be.encaps != BR2684_ENCAPS_LLC) ||
750 + be.min_size != 0) {
754 + brvcc = kmalloc(sizeof(struct br2684_vcc), GFP_KERNEL);
759 + memset(brvcc, 0, sizeof(struct br2684_vcc));
760 + DPRINTK("br2684_regvcc vcc=%p, encaps=%d, brvcc=%p\n", atmvcc, be.encaps,
762 + if (list_empty(&brdev->brvccs) && !brdev->mac_was_set) {
763 + unsigned char *esi = atmvcc->dev->esi;
764 + if (esi[0] | esi[1] | esi[2] | esi[3] | esi[4] | esi[5])
765 + memcpy(brdev->net_dev.dev_addr, esi,
766 + brdev->net_dev.addr_len);
768 + brdev->net_dev.dev_addr[2] = 1;
770 + list_add(&brvcc->brvccs, &brdev->brvccs);
771 + write_unlock_irq(&devs_lock);
772 + brvcc->brdev = brdev;
773 + brvcc->atmvcc = atmvcc;
774 + atmvcc->user_back = brvcc;
775 + brvcc->encaps = (enum br2684_encaps) be.encaps;
776 + brvcc->old_push = atmvcc->push;
778 + atmvcc->push = br2684_push;
779 + skb_queue_head_init(©);
780 + skb_migrate(&atmvcc->recvq, ©);
781 + while ((skb = skb_dequeue(©))) {
782 + BRPRIV(skb->dev)->stats.rx_bytes -= skb->len;
783 + BRPRIV(skb->dev)->stats.rx_packets--;
784 + br2684_push(atmvcc, skb);
788 + write_unlock_irq(&devs_lock);
793 +static int br2684_create(unsigned long arg)
796 + struct br2684_dev *brdev;
797 + struct atm_newif_br2684 ni;
799 + DPRINTK("br2684_create\n");
801 + * We track module use by vcc's NOT the devices they're on. We're
802 + * protected here against module death by the kernel_lock, but if
803 + * we need to sleep we should make sure that the module doesn't
804 + * disappear under us.
807 + if (copy_from_user(&ni, (void *) arg, sizeof ni)) {
811 + if (ni.media != BR2684_MEDIA_ETHERNET || ni.mtu != 1500) {
815 + if ((brdev = kmalloc(sizeof(struct br2684_dev), GFP_KERNEL)) == NULL) {
819 + memset(brdev, 0, sizeof(struct br2684_dev));
820 + INIT_LIST_HEAD(&brdev->brvccs);
822 + write_lock_irq(&devs_lock);
823 + brdev->number = list_empty(&br2684_devs) ? 1 :
824 + list_entry_brdev(br2684_devs.prev)->number + 1;
825 + list_add_tail(&brdev->br2684_devs, &br2684_devs);
826 + write_unlock_irq(&devs_lock);
828 + if (ni.ifname[0] != '\0') {
829 + memcpy(brdev->net_dev.name, ni.ifname,
830 + sizeof(brdev->net_dev.name));
831 + brdev->net_dev.name[sizeof(brdev->net_dev.name) - 1] = '\0';
833 + sprintf(brdev->net_dev.name, "nas%d", brdev->number);
834 + DPRINTK("registered netdev %s\n", brdev->net_dev.name);
835 + ether_setup(&brdev->net_dev);
836 + brdev->mac_was_set = 0;
837 +#ifdef FASTER_VERSION
838 + my_eth_header = brdev->net_dev.hard_header;
839 + brdev->net_dev.hard_header = br2684_header;
840 + my_eth_header_cache = brdev->net_dev.hard_header_cache;
841 + brdev->net_dev.hard_header_cache = br2684_header_cache;
842 + brdev->net_dev.hard_header_len = sizeof(llc_oui_pid_pad) + ETH_HLEN; /* 10 + 14 */
844 + my_eth_mac_addr = brdev->net_dev.set_mac_address;
845 + brdev->net_dev.set_mac_address = br2684_mac_addr;
846 + brdev->net_dev.hard_start_xmit = br2684_start_xmit;
847 + brdev->net_dev.get_stats = br2684_get_stats;
849 + /* open, stop, do_ioctl ? */
850 + err = register_netdev(&brdev->net_dev);
853 + printk(KERN_ERR "br2684_create: register_netdev failed\n");
854 + write_lock_irq(&devs_lock);
855 + list_del(&brdev->br2684_devs);
856 + write_unlock_irq(&devs_lock);
864 + * This handles ioctls actually performed on our vcc - we must return
865 + * -ENOIOCTLCMD for any unrecognized ioctl
867 +static int br2684_ioctl(struct atm_vcc *atmvcc, unsigned int cmd,
872 + case ATM_SETBACKEND:
873 + case ATM_NEWBACKENDIF: {
876 + err = get_user(b, (atm_backend_t *) arg);
880 + if (b != ATM_BACKEND_BR_2684)
881 + return -ENOIOCTLCMD;
882 + if (!capable(CAP_NET_ADMIN))
884 + if (cmd == ATM_SETBACKEND)
885 + return br2684_regvcc(atmvcc, arg);
887 + return br2684_create(arg);
889 +#ifdef CONFIG_ATM_BR2684_IPFILTER
890 + case BR2684_SETFILT:
891 + if (atmvcc->push != br2684_push)
892 + return -ENOIOCTLCMD;
893 + if (!capable(CAP_NET_ADMIN))
896 + err = br2684_setfilt(atmvcc, arg);
899 +#endif /* CONFIG_ATM_BR2684_IPFILTER */
901 + return -ENOIOCTLCMD;
904 +/* Never put more than 256 bytes in at once */
905 +static int br2684_proc_engine(loff_t pos, char *buf)
907 + struct list_head *lhd, *lhc;
908 + struct br2684_dev *brdev;
909 + struct br2684_vcc *brvcc;
910 + list_for_each(lhd, &br2684_devs) {
911 + brdev = list_entry_brdev(lhd);
913 + return sprintf(buf, "dev %.16s: num=%d, mac=%02X:%02X:"
914 + "%02X:%02X:%02X:%02X (%s)\n", brdev->net_dev.name,
916 + brdev->net_dev.dev_addr[0],
917 + brdev->net_dev.dev_addr[1],
918 + brdev->net_dev.dev_addr[2],
919 + brdev->net_dev.dev_addr[3],
920 + brdev->net_dev.dev_addr[4],
921 + brdev->net_dev.dev_addr[5],
922 + brdev->mac_was_set ? "set" : "auto");
923 + list_for_each(lhc, &brdev->brvccs) {
924 + brvcc = list_entry_brvcc(lhc);
926 + return sprintf(buf, " vcc %d.%d.%d: encaps=%s"
927 +#ifndef FASTER_VERSION
928 + ", failed copies %u/%u"
929 +#endif /* FASTER_VERSION */
930 + "\n", brvcc->atmvcc->dev->number,
931 + brvcc->atmvcc->vpi, brvcc->atmvcc->vci,
932 + (brvcc->encaps == e_llc) ? "LLC" : "VC"
933 +#ifndef FASTER_VERSION
934 + , brvcc->copies_failed
935 + , brvcc->copies_needed
936 +#endif /* FASTER_VERSION */
938 +#ifdef CONFIG_ATM_BR2684_IPFILTER
939 +#define b1(var, byte) ((u8 *) &brvcc->filter.var)[byte]
940 +#define bs(var) b1(var, 0), b1(var, 1), b1(var, 2), b1(var, 3)
941 + if (brvcc->filter.netmask != 0 && pos-- == 0)
942 + return sprintf(buf, " filter=%d.%d.%d.%d/"
943 + "%d.%d.%d.%d\n", bs(prefix), bs(netmask));
946 +#endif /* CONFIG_ATM_BR2684_IPFILTER */
952 +static ssize_t br2684_proc_read(struct file *file, char *buf, size_t count,
955 + unsigned long page;
956 + int len = 0, x, left;
957 + page = get_free_page(GFP_KERNEL);
960 + left = PAGE_SIZE - 256;
963 + read_lock(&devs_lock);
965 + x = br2684_proc_engine(*pos, &((char *) page)[len]);
970 + * This should only happen if the user passed in
971 + * a "count" too small for even one line
984 + read_unlock(&devs_lock);
985 + if (len > 0 && copy_to_user(buf, (char *) page, len))
991 +static struct file_operations br2684_proc_operations = {
992 + read: br2684_proc_read,
995 +extern struct proc_dir_entry *atm_proc_root; /* from proc.c */
997 +extern int (*br2684_ioctl_hook)(struct atm_vcc *, unsigned int, unsigned long);
999 +/* the following avoids some spurious warnings from the compiler */
1000 +#define UNUSED __attribute__((unused))
1002 +static int __init UNUSED br2684_init(void)
1004 + struct proc_dir_entry *p;
1005 + if ((p = create_proc_entry("br2684", 0, atm_proc_root)) == NULL)
1007 + p->proc_fops = &br2684_proc_operations;
1008 + br2684_ioctl_hook = br2684_ioctl;
1012 +static void __exit UNUSED br2684_exit(void)
1014 + struct br2684_dev *brdev;
1015 + br2684_ioctl_hook = NULL;
1016 + remove_proc_entry("br2684", atm_proc_root);
1017 + while (!list_empty(&br2684_devs)) {
1018 + brdev = list_entry_brdev(br2684_devs.next);
1019 + unregister_netdev(&brdev->net_dev);
1020 + list_del(&brdev->br2684_devs);
1025 +module_init(br2684_init);
1026 +module_exit(br2684_exit);
1028 +MODULE_AUTHOR("Marcell GAL");
1029 +MODULE_DESCRIPTION("RFC2684 bridged protocols over ATM/AAL5");
1030 diff -urN linux.orig/net/atm/common.c linux/net/atm/common.c
1031 --- linux.orig/net/atm/common.c Sat Apr 21 18:04:58 2001
1032 +++ linux/net/atm/common.c Sat Apr 21 18:06:09 2001
1034 EXPORT_SYMBOL(pppoatm_ioctl_hook);
1037 +#if defined(CONFIG_ATM_BR2684) || defined(CONFIG_ATM_BR2684_MODULE)
1038 +int (*br2684_ioctl_hook)(struct atm_vcc *, unsigned int, unsigned long);
1040 +#ifdef CONFIG_ATM_BR2684_MODULE
1041 +EXPORT_SYMBOL(br2684_ioctl_hook);
1044 #include "resources.h" /* atm_find_dev */
1045 #include "common.h" /* prototypes */
1046 #include "protocols.h" /* atm_init_<transport> */
1047 @@ -774,6 +786,13 @@
1051 +#if defined(CONFIG_ATM_BR2684) || defined(CONFIG_ATM_BR2684_MODULE)
1052 + if (br2684_ioctl_hook) {
1053 + ret_val = br2684_ioctl_hook(vcc, cmd, arg);
1054 + if (ret_val != -ENOIOCTLCMD)
1058 if (get_user(buf,&((struct atmif_sioc *) arg)->arg)) {