]> git.pld-linux.org Git - packages/kernel.git/blob - br2684-against2.4.17.diff
9cdd694a797623b3d0f76ee69304dd85 linux-loop-hvr-2.4.16.0.patch
[packages/kernel.git] / br2684-against2.4.17.diff
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
4 @@ -6391,6 +6391,19 @@
5    briefly removed during revalidation. If you say Y here, packets to
6    such neighbours are silently discarded instead.
7  
8 +RFC1483/2684 Bridged protocols
9 +CONFIG_ATM_BR2684
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.
14 +
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.
20 +
21  LAN Emulation (LANE) support
22  CONFIG_ATM_LANE
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/>.
27  
28 +PPP over ATM (EXPERIMENTAL)
29 +CONFIG_PPPOATM
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.
34 +  
35  Wireless LAN (non-hamradio)
36  CONFIG_NET_RADIO
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
43  S:     Maintained
44  
45 +PPP OVER ATM (RFC 2364)
46 +P:      Mitchell Blank Jr
47 +M:      mitch@sfgoth.com
48 +S:      Maintained
49 +
50  PPP OVER ETHERNET
51  P:     Michal Ostrowski
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
56 @@ -215,6 +215,12 @@
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
64 +         fi
65 +       fi
66        fi
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
72 @@ -245,6 +245,9 @@
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
78 +      fi
79     fi
80  fi
81
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
85 @@ -0,0 +1,101 @@
86 +#ifndef _LINUX_ATMBR2684_H
87 +#define _LINUX_ATMBR2684_H
88 +
89 +#include <linux/atm.h>
90 +#include <linux/if.h>          /* For IFNAMSIZ */
91 +
92 +/*
93 + * Type of media we're bridging (ethernet, token ring, etc)  Currently only
94 + * ethernet is supported
95 + */
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 */
101 +
102 +/*
103 + * Is there FCS inbound on this VC?  This currently isn't supported.
104 + */
105 +#define BR2684_FCSIN_NO                (0)
106 +#define BR2684_FCSIN_IGNORE    (1)
107 +#define BR2684_FCSIN_VERIFY    (2)
108 +
109 +/*
110 + * Is there FCS outbound on this VC?  This currently isn't supported.
111 + */
112 +#define BR2684_FCSOUT_NO       (0)
113 +#define BR2684_FCSOUT_SENDZERO (1)
114 +#define BR2684_FCSOUT_GENERATE (2)
115 +
116 +/*
117 + * Does this VC include LLC encapsulation?
118 + */
119 +#define BR2684_ENCAPS_VC       (0)     /* VC-mux */
120 +#define BR2684_ENCAPS_LLC      (1)
121 +#define BR2684_ENCAPS_AUTODETECT (2)   /* Unsuported */
122 +
123 +/*
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
127 + */
128 +struct atm_newif_br2684 {
129 +       atm_backend_t   backend_num;    /* ATM_BACKEND_BR2684 */
130 +       int             media;          /* BR2684_MEDIA_* */
131 +       char            ifname[IFNAMSIZ];
132 +       int             mtu;
133 +};
134 +
135 +/*
136 + * This structure is used to specify a br2684 interface - either by a
137 + * positive integer (returned by ATM_NEWBACKENDIF) or the interfaces name
138 + */
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_* */
144 +       union {
145 +               char            ifname[IFNAMSIZ];
146 +               int             devnum;
147 +       } spec;
148 +};
149 +
150 +/*
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
154 + */
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 */
163 +       __u8    vpn_id[7];
164 +       int     send_padding;   /* unsupported */
165 +       int     min_size;       /* we will pad smaller packets than this */
166 +};
167 +
168 +/*
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
172 + */
173 +struct br2684_filter {
174 +       __u32   prefix;         /* network byte order */
175 +       __u32   netmask;        /* 0 = disable filter */
176 +};
177 +
178 +struct br2684_filter_set {
179 +       struct br2684_if_spec ifspec;
180 +       struct br2684_filter filter;
181 +};
182 +
183 +#define BR2684_SETFILT _IOW( 'a', ATMIOC_BACKEND + 0, \
184 +                               struct br2684_filter_set)
185 +
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
190 @@ -95,6 +95,8 @@
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 */
196  
197  /*
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
202 @@ -45,6 +45,10 @@
203        if [ "$CONFIG_INET" = "y" -a "$CONFIG_ATM_LANE" != "n" ]; then
204          tristate '    Multi-Protocol Over ATM (MPOA) support' CONFIG_ATM_MPOA
205        fi
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
209 +      fi
210     fi
211  fi
212  
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
216 @@ -21,6 +21,15 @@
217  NEED_IPCOM = ipcommon.o
218  endif
219  
220 +ifeq ($(CONFIG_ATM_BR2684),y)
221 +  NEED_IPCOM = ipcommon.o
222 +else
223 +  ifeq ($(CONFIG_ATM_BR2684),m)
224 +       NEED_IPCOM = ipcommon.o
225 +  endif
226 +endif
227 +obj-$(CONFIG_ATM_BR2684) += br2684.o
228 +
229  ifeq ($(CONFIG_NET_SCH_ATM),y)
230  NEED_IPCOM = ipcommon.o
231  endif
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
235 @@ -0,0 +1,794 @@
236 +/*
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
240 +*/
241 +
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>
254 +
255 +#include "ipcommon.h"
256 +
257 +/*
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
264 + */
265 +/* #define FASTER_VERSION */
266 +
267 +#ifdef DEBUG
268 +#define DPRINTK(format, args...) printk(KERN_DEBUG "br2684: " format, ##args)
269 +#else
270 +#define DPRINTK(format, args...)
271 +#endif
272 +
273 +#ifdef SKB_DEBUG
274 +static void skb_debug(const struct sk_buff *skb)
275 +{
276 +#define NUM2PRINT 50
277 +       char buf[NUM2PRINT * 3 + 1];    /* 3 chars per byte */
278 +       int i = 0;
279 +       for (i = 0; i < skb->len && i < NUM2PRINT; i++) {
280 +               sprintf(buf + i * 3, "%2.2x ", 0xff & skb->data[i]);
281 +       }
282 +       printk(KERN_DEBUG "br2684: skb: %s\n", buf);
283 +}
284 +#else
285 +#define skb_debug(skb) do {} while (0)
286 +#endif
287 +
288 +static unsigned char llc_oui_pid_pad[] =
289 +    { 0xAA, 0xAA, 0x03, 0x00, 0x80, 0xC2, 0x00, 0x07, 0x00, 0x00 };
290 +#define PADLEN (2)
291 +
292 +enum br2684_encaps {
293 +       e_vc  = BR2684_ENCAPS_VC,
294 +       e_llc = BR2684_ENCAPS_LLC,
295 +};
296 +
297 +struct br2684_vcc {
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 */
311 +};
312 +
313 +struct br2684_dev {
314 +       struct net_device net_dev;
315 +       struct list_head br2684_devs;
316 +       int number;
317 +       struct list_head brvccs; /* one device <=> one vcc (before xmas) */
318 +       struct net_device_stats stats;
319 +       int mac_was_set;
320 +};
321 +
322 +/*
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
328 + */
329 +static rwlock_t devs_lock = RW_LOCK_UNLOCKED;
330 +
331 +static LIST_HEAD(br2684_devs);
332 +
333 +static inline struct br2684_dev *BRPRIV(const struct net_device *net_dev)
334 +{
335 +       return (struct br2684_dev *) ((char *) (net_dev) -
336 +           (unsigned long) (&((struct br2684_dev *) 0)->net_dev));
337 +}
338 +
339 +static inline struct br2684_dev *list_entry_brdev(const struct list_head *le)
340 +{
341 +       return list_entry(le, struct br2684_dev, br2684_devs);
342 +}
343 +
344 +static inline struct br2684_vcc *BR2684_VCC(const struct atm_vcc *atmvcc)
345 +{
346 +       return (struct br2684_vcc *) (atmvcc->user_back);
347 +}
348 +
349 +static inline struct br2684_vcc *list_entry_brvcc(const struct list_head *le)
350 +{
351 +       return list_entry(le, struct br2684_vcc, brvccs);
352 +}
353 +
354 +/* Caller should hold read_lock(&devs_lock) */
355 +static struct br2684_dev *br2684_find_dev(const struct br2684_if_spec *s)
356 +{
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)
364 +                               return brdev;
365 +               }
366 +               break;
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))
372 +                               return brdev;
373 +               }
374 +               break;
375 +       }
376 +       return NULL;
377 +}
378 +
379 +/*
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,
382 + * otherwise false
383 + */
384 +static int br2684_xmit_vcc(struct sk_buff *skb, struct br2684_dev *brdev,
385 +       struct br2684_vcc *brvcc)
386 +{
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)
393 +        */
394 +#else
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++;
402 +                       return 0;
403 +               }
404 +               skb = skb2;
405 +       }
406 +       skb_push(skb, minheadroom);
407 +       if (brvcc->encaps == e_llc)
408 +               memcpy(skb->data, llc_oui_pid_pad, 10);
409 +       else
410 +               memset(skb->data, 0, 2);
411 +#endif /* FASTER_VERSION */
412 +       skb_debug(skb);
413 +
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.
419 +                       now, it always is.
420 +               */
421 +               dev_kfree_skb(skb);
422 +               return 0;
423 +               }
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);
430 +       return 1;
431 +}
432 +
433 +static inline struct br2684_vcc *pick_outgoing_vcc(struct sk_buff *skb,
434 +       struct br2684_dev *brdev)
435 +{
436 +       return list_empty(&brdev->brvccs) ? NULL :
437 +           list_entry_brvcc(brdev->brvccs.next); /* 1 vcc/dev right now */
438 +}
439 +
440 +static int br2684_start_xmit(struct sk_buff *skb, struct net_device *dev)
441 +{
442 +       struct br2684_dev *brdev = BRPRIV(dev);
443 +       struct br2684_vcc *brvcc;
444 +
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);
455 +               return -EUNATCH;
456 +       }
457 +       if (!br2684_xmit_vcc(skb, brdev, brvcc)) {
458 +               /*
459 +                * We should probably use netif_*_queue() here, but that
460 +                * involves added complication.  We need to walk before
461 +                * we can run
462 +                */
463 +               /* don't free here! this pointer might be no longer valid!
464 +               dev_kfree_skb(skb);
465 +               */
466 +               brdev->stats.tx_errors++;
467 +               brdev->stats.tx_fifo_errors++;
468 +       }
469 +       read_unlock(&devs_lock);
470 +       return 0;
471 +}
472 +
473 +static struct net_device_stats *br2684_get_stats(struct net_device *dev)
474 +{
475 +       DPRINTK("br2684_get_stats\n");
476 +       return &BRPRIV(dev)->stats;
477 +}
478 +
479 +#ifdef FASTER_VERSION
480 +/*
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.
484 + */
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 *);
488 +
489 +static int
490 +br2684_header(struct sk_buff *skb, struct net_device *dev,
491 +             unsigned short type, void *daddr, void *saddr, unsigned len)
492 +{
493 +       u16 *pad_before_eth;
494 +       int t = my_eth_header(skb, dev, type, daddr, saddr, len);
495 +       if (t > 0) {
496 +               pad_before_eth = (u16 *) skb_push(skb, 2);
497 +               *pad_before_eth = 0;
498 +               return dev->hard_header_len;    /* or return 16; ? */
499 +       } else
500 +               return t;
501 +}
502 +
503 +static int
504 +br2684_header_cache(struct neighbour *neigh, struct hh_cache *hh)
505 +{
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);
511 +       if (t < 0)
512 +               return t;
513 +       else {
514 +               *pad_before_eth = 0;
515 +               hh->hh_len = PADLEN + ETH_HLEN;
516 +       }
517 +       return 0;
518 +}
519 +
520 +/*
521 + * This is similar to eth_type_trans, which cannot be used because of
522 + * our dev->hard_header_len
523 + */
524 +static inline unsigned short br_type_trans(struct sk_buff *skb,
525 +                                              struct net_device *dev)
526 +{
527 +       struct ethhdr *eth;
528 +       unsigned char *rawp;
529 +       eth = skb->mac.ethernet;
530 +
531 +       if (*eth->h_dest & 1) {
532 +               if (memcmp(eth->h_dest, dev->broadcast, ETH_ALEN) == 0)
533 +                       skb->pkt_type = PACKET_BROADCAST;
534 +               else
535 +                       skb->pkt_type = PACKET_MULTICAST;
536 +       }
537 +
538 +       else if (memcmp(eth->h_dest, dev->dev_addr, ETH_ALEN))
539 +               skb->pkt_type = PACKET_OTHERHOST;
540 +
541 +       if (ntohs(eth->h_proto) >= 1536)
542 +               return eth->h_proto;
543 +
544 +       rawp = skb->data;
545 +
546 +       /*
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.
551 +        */
552 +       if (*(unsigned short *) rawp == 0xFFFF)
553 +               return htons(ETH_P_802_3);
554 +
555 +       /*
556 +        * Real 802.2 LLC
557 +        */
558 +       return htons(ETH_P_802_2);
559 +}
560 +#endif /* FASTER_VERSION */
561 +
562 +/*
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
565 + */
566 +static int (*my_eth_mac_addr)(struct net_device *, void *);
567 +static int br2684_mac_addr(struct net_device *dev, void *p)
568 +{
569 +       int err = my_eth_mac_addr(dev, p);
570 +       if (!err)
571 +               BRPRIV(dev)->mac_was_set = 1;
572 +       return err;
573 +}
574 +
575 +#ifdef CONFIG_ATM_BR2684_IPFILTER
576 +/* this IOCTL is experimental. */
577 +static int br2684_setfilt(struct atm_vcc *atmvcc, unsigned long arg)
578 +{
579 +       struct br2684_vcc *brvcc;
580 +       struct br2684_filter_set fs;
581 +
582 +       if (copy_from_user(&fs, (void *) arg, sizeof fs))
583 +               return -EFAULT;
584 +       if (fs.ifspec.method != BR2684_FIND_BYNOTHING) {
585 +               /*
586 +                * This is really a per-vcc thing, but we can also search
587 +                * by device
588 +                */
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 */
594 +                       brvcc = NULL;
595 +               else
596 +                       brvcc = list_entry_brvcc(brdev->brvccs.next);
597 +               read_unlock(&devs_lock);
598 +               if (brvcc == NULL)
599 +                       return -ESRCH;
600 +       } else
601 +               brvcc = BR2684_VCC(atmvcc);
602 +       memcpy(&brvcc->filter, &fs.filter, sizeof(brvcc->filter));
603 +       return 0;
604 +}
605 +
606 +/* Returns 1 if packet should be dropped */
607 +static inline int
608 +packet_fails_filter(u16 type, struct br2684_vcc *brvcc, struct sk_buff *skb)
609 +{
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)
615 +               return 0;
616 +       if (type == __constant_htons(ETH_P_ARP))
617 +               return 0;
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?
620 +        */
621 +       return 1;               /* drop */
622 +}
623 +#endif /* CONFIG_ATM_BR2684_IPFILTER */
624 +
625 +static void br2684_close_vcc(struct br2684_vcc *brvcc)
626 +{
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 */
633 +       kfree(brvcc);
634 +       MOD_DEC_USE_COUNT;
635 +}
636 +
637 +/* when AAL5 PDU comes in: */
638 +static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb)
639 +{
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;
643 +
644 +       DPRINTK("br2684_push\n");
645 +
646 +       if (skb == NULL) {      /* skb==NULL means VCC is being destroyed */
647 +               br2684_close_vcc(brvcc);
648 +               return;
649 +       }
650 +
651 +       skb_debug(skb);
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);
661 +                       return;
662 +               }
663 +       } else {
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);
669 +                       return;
670 +               }
671 +       }
672 +       if (skb->len < plen) {
673 +               brdev->stats.rx_errors++;
674 +               dev_kfree_skb(skb);     /* dev_ not needed? */
675 +               return;
676 +       }
677 +
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 */
689 +#else
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);
697 +               return;
698 +       }
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));
703 +       skb_debug(skb);
704 +       if (!(brdev->net_dev.flags & IFF_UP)) { /* sigh, interface is down */
705 +               brdev->stats.rx_dropped++;
706 +               dev_kfree_skb(skb);
707 +               return;
708 +       }
709 +       brdev->stats.rx_packets++;
710 +       brdev->stats.rx_bytes += skb->len;
711 +       netif_rx(skb);
712 +}
713 +
714 +static int br2684_regvcc(struct atm_vcc *atmvcc, unsigned long arg)
715 +{
716 +/* assign a vcc to a dev
717 +Note: we do not have explicit unassign, but look at _push()
718 +*/
719 +       int err;
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;
725 +
726 +       MOD_INC_USE_COUNT;
727 +       if (copy_from_user(&be, (void *) arg, sizeof be)) {
728 +               MOD_DEC_USE_COUNT;
729 +               return -EFAULT;
730 +       }
731 +       write_lock_irq(&devs_lock);
732 +       brdev = br2684_find_dev(&be.ifspec);
733 +       if (brdev == NULL) {
734 +               printk(KERN_ERR
735 +                   "br2684: tried to attach to non-existant device\n");
736 +               err = -ENXIO;
737 +               goto error;
738 +       }
739 +       if (atmvcc->push == NULL) {
740 +               err = -EBADFD;
741 +               goto error;
742 +       }
743 +       if (!list_empty(&brdev->brvccs)) {      /* Only 1 VCC/dev right now */
744 +               err = -EEXIST;
745 +               goto error;
746 +       }
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) {
751 +               err = -EINVAL;
752 +               goto error;
753 +       }
754 +       brvcc = kmalloc(sizeof(struct br2684_vcc), GFP_KERNEL);
755 +       if (!brvcc) {
756 +               err = -ENOMEM;
757 +               goto error;
758 +       }
759 +       memset(brvcc, 0, sizeof(struct br2684_vcc));
760 +       DPRINTK("br2684_regvcc vcc=%p, encaps=%d, brvcc=%p\n", atmvcc, be.encaps,
761 +               brvcc);
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);
767 +               else
768 +                       brdev->net_dev.dev_addr[2] = 1;
769 +       }
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;
777 +       barrier();
778 +       atmvcc->push = br2684_push;
779 +       skb_queue_head_init(&copy);
780 +       skb_migrate(&atmvcc->recvq, &copy);
781 +       while ((skb = skb_dequeue(&copy))) {
782 +               BRPRIV(skb->dev)->stats.rx_bytes -= skb->len;
783 +               BRPRIV(skb->dev)->stats.rx_packets--;
784 +               br2684_push(atmvcc, skb);
785 +       }
786 +       return 0;
787 +    error:
788 +       write_unlock_irq(&devs_lock);
789 +       MOD_DEC_USE_COUNT;
790 +       return err;
791 +}
792 +
793 +static int br2684_create(unsigned long arg)
794 +{
795 +       int err;
796 +       struct br2684_dev *brdev;
797 +       struct atm_newif_br2684 ni;
798 +
799 +       DPRINTK("br2684_create\n");
800 +       /*
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.
805 +        */
806 +       MOD_INC_USE_COUNT;
807 +       if (copy_from_user(&ni, (void *) arg, sizeof ni)) {
808 +               MOD_DEC_USE_COUNT;
809 +               return -EFAULT;
810 +       }
811 +       if (ni.media != BR2684_MEDIA_ETHERNET || ni.mtu != 1500) {
812 +               MOD_DEC_USE_COUNT;
813 +               return -EINVAL;
814 +       }
815 +       if ((brdev = kmalloc(sizeof(struct br2684_dev), GFP_KERNEL)) == NULL) {
816 +               MOD_DEC_USE_COUNT;
817 +               return -ENOMEM;
818 +       }
819 +       memset(brdev, 0, sizeof(struct br2684_dev));
820 +       INIT_LIST_HEAD(&brdev->brvccs);
821 +
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);
827 +
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';
832 +       } else
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 */
843 +#endif
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;
848 +
849 +       /* open, stop, do_ioctl ? */
850 +       err = register_netdev(&brdev->net_dev);
851 +       MOD_DEC_USE_COUNT;
852 +       if (err < 0) {
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);
857 +               kfree(brdev);
858 +               return err;
859 +       }
860 +       return 0;
861 +}
862 +
863 +/*
864 + * This handles ioctls actually performed on our vcc - we must return
865 + * -ENOIOCTLCMD for any unrecognized ioctl
866 + */
867 +static int br2684_ioctl(struct atm_vcc *atmvcc, unsigned int cmd,
868 +       unsigned long arg)
869 +{
870 +       int err;
871 +       switch(cmd) {
872 +       case ATM_SETBACKEND:
873 +       case ATM_NEWBACKENDIF: {
874 +               atm_backend_t b;
875 +               MOD_INC_USE_COUNT;
876 +               err = get_user(b, (atm_backend_t *) arg);
877 +               MOD_DEC_USE_COUNT;
878 +               if (err)
879 +                       return -EFAULT;
880 +               if (b != ATM_BACKEND_BR_2684)
881 +                       return -ENOIOCTLCMD;
882 +               if (!capable(CAP_NET_ADMIN))
883 +                       return -EPERM;
884 +               if (cmd == ATM_SETBACKEND)
885 +                       return br2684_regvcc(atmvcc, arg);
886 +               else
887 +                       return br2684_create(arg);
888 +               }
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))
894 +                       return -EPERM;
895 +               MOD_INC_USE_COUNT;
896 +               err = br2684_setfilt(atmvcc, arg);
897 +               MOD_DEC_USE_COUNT;
898 +               return err;
899 +#endif /* CONFIG_ATM_BR2684_IPFILTER */
900 +       }
901 +       return -ENOIOCTLCMD;
902 +}
903 +
904 +/* Never put more than 256 bytes in at once */
905 +static int br2684_proc_engine(loff_t pos, char *buf)
906 +{
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);
912 +               if (pos-- == 0)
913 +                       return sprintf(buf, "dev %.16s: num=%d, mac=%02X:%02X:"
914 +                           "%02X:%02X:%02X:%02X (%s)\n", brdev->net_dev.name,
915 +                           brdev->number,
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);
925 +                       if (pos-- == 0)
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 */
937 +                                   );
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));
944 +#undef bs
945 +#undef b1
946 +#endif /* CONFIG_ATM_BR2684_IPFILTER */
947 +               }
948 +       }
949 +       return 0;
950 +}
951 +
952 +static ssize_t br2684_proc_read(struct file *file, char *buf, size_t count,
953 +       loff_t *pos)
954 +{
955 +       unsigned long page;
956 +       int len = 0, x, left;
957 +       page = get_free_page(GFP_KERNEL);
958 +       if (!page)
959 +               return -ENOMEM;
960 +       left = PAGE_SIZE - 256;
961 +       if (count < left)
962 +               left = count;
963 +       read_lock(&devs_lock);
964 +       for (;;) {
965 +               x = br2684_proc_engine(*pos, &((char *) page)[len]);
966 +               if (x == 0)
967 +                       break;
968 +               if (x > left)
969 +                       /*
970 +                        * This should only happen if the user passed in
971 +                        * a "count" too small for even one line
972 +                        */
973 +                       x = -EINVAL;
974 +               if (x < 0) {
975 +                       len = x;
976 +                       break;
977 +               }
978 +               len += x;
979 +               left -= x;
980 +               (*pos)++;
981 +               if (left < 256)
982 +                       break;
983 +       }
984 +       read_unlock(&devs_lock);
985 +       if (len > 0 && copy_to_user(buf, (char *) page, len))
986 +               len = -EFAULT;
987 +       free_page(page);
988 +       return len;
989 +}
990 +
991 +static struct file_operations br2684_proc_operations = {
992 +       read: br2684_proc_read,
993 +};
994 +
995 +extern struct proc_dir_entry *atm_proc_root;   /* from proc.c */
996 +
997 +extern int (*br2684_ioctl_hook)(struct atm_vcc *, unsigned int, unsigned long);
998 +
999 +/* the following avoids some spurious warnings from the compiler */
1000 +#define UNUSED __attribute__((unused))
1001 +
1002 +static int __init UNUSED br2684_init(void)
1003 +{
1004 +       struct proc_dir_entry *p;
1005 +       if ((p = create_proc_entry("br2684", 0, atm_proc_root)) == NULL)
1006 +               return -ENOMEM;
1007 +       p->proc_fops = &br2684_proc_operations;
1008 +       br2684_ioctl_hook = br2684_ioctl;
1009 +       return 0;
1010 +}
1011 +
1012 +static void __exit UNUSED br2684_exit(void)
1013 +{
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);
1021 +               kfree(brdev);
1022 +       }
1023 +}
1024 +
1025 +module_init(br2684_init);
1026 +module_exit(br2684_exit);
1027 +
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
1033 @@ -63,6 +63,13 @@
1034  EXPORT_SYMBOL(pppoatm_ioctl_hook);
1035  #endif
1036  
1037 +#if defined(CONFIG_ATM_BR2684) || defined(CONFIG_ATM_BR2684_MODULE)
1038 +int (*br2684_ioctl_hook)(struct atm_vcc *, unsigned int, unsigned long);
1039 +#endif
1040 +#ifdef CONFIG_ATM_BR2684_MODULE
1041 +EXPORT_SYMBOL(br2684_ioctl_hook);
1042 +#endif
1043 +
1044  #include "resources.h"         /* atm_find_dev */
1045  #include "common.h"            /* prototypes */
1046  #include "protocols.h"         /* atm_init_<transport> */
1047 @@ -774,6 +786,13 @@
1048                         goto done;
1049         }
1050  #endif
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)
1055 +                       goto done;
1056 +       }
1057 +#endif
1058         if (get_user(buf,&((struct atmif_sioc *) arg)->arg)) {
1059                 ret_val = -EFAULT;
1060                 goto done;
This page took 0.326072 seconds and 3 git commands to generate.