]> git.pld-linux.org Git - packages/kernel.git/blame - br2684-against2.4.10.diff
- removed all Group fields translations (oure rpm now can handle translating
[packages/kernel.git] / br2684-against2.4.10.diff
CommitLineData
1a032709
JR
1diff -urN linux.orig/Documentation/Configure.help linux/Documentation/Configure.help
2--- linux.orig/Documentation/Configure.help Sat Apr 21 18:05:00 2001
3+++ linux/Documentation/Configure.help Sat Apr 21 18:06:09 2001
4@@ -5328,6 +5328,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@@ -7558,6 +7571,13 @@
25 This driver requires a specially patched pppd daemon. The patch to
26 pppd, along with binaries of a patched pppd package can be found at:
27 http://www.shoshin.uwaterloo.ca/~mostrows
28+
29+PPP over ATM (EXPERIMENTAL)
30+CONFIG_PPPOATM
31+ PPP over ATM is one of several protocols used over DSL lines.
32+ If you are connecting to a DSL line using an internal ATM or
33+ DSL adaptor (as opposed to an ethernet card) then there is
34+ a good possibility you will need this protocol.
35
36 Wireless LAN (non-hamradio)
37 CONFIG_NET_RADIO
38diff -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
53diff -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
69diff -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
82diff -urN linux.orig/include/linux/atm.h linux/include/linux/atm.h
83--- linux.orig/include/linux/atm.h Tue Mar 27 01:49:24 2001
84+++ linux/include/linux/atm.h Sat Apr 21 18:06:09 2001
85@@ -235,6 +235,7 @@
86 void *arg;
87 };
88
89+typedef unsigned short atm_backend_t;
90
91 #ifdef __KERNEL__
92
93diff -urN linux.orig/include/linux/atmbr2684.h linux/include/linux/atmbr2684.h
94--- linux.orig/include/linux/atmbr2684.h Thu Jan 1 01:00:00 1970
95+++ linux/include/linux/atmbr2684.h Sat Apr 21 18:06:09 2001
96@@ -0,0 +1,101 @@
97+#ifndef _LINUX_ATMBR2684_H
98+#define _LINUX_ATMBR2684_H
99+
100+#include <linux/atm.h>
101+#include <linux/if.h> /* For IFNAMSIZ */
102+
103+/*
104+ * Type of media we're bridging (ethernet, token ring, etc) Currently only
105+ * ethernet is supported
106+ */
107+#define BR2684_MEDIA_ETHERNET (0) /* 802.3 */
108+#define BR2684_MEDIA_802_4 (1) /* 802.4 */
109+#define BR2684_MEDIA_TR (2) /* 802.5 - token ring */
110+#define BR2684_MEDIA_FDDI (3)
111+#define BR2684_MEDIA_802_6 (4) /* 802.6 */
112+
113+/*
114+ * Is there FCS inbound on this VC? This currently isn't supported.
115+ */
116+#define BR2684_FCSIN_NO (0)
117+#define BR2684_FCSIN_IGNORE (1)
118+#define BR2684_FCSIN_VERIFY (2)
119+
120+/*
121+ * Is there FCS outbound on this VC? This currently isn't supported.
122+ */
123+#define BR2684_FCSOUT_NO (0)
124+#define BR2684_FCSOUT_SENDZERO (1)
125+#define BR2684_FCSOUT_GENERATE (2)
126+
127+/*
128+ * Does this VC include LLC encapsulation?
129+ */
130+#define BR2684_ENCAPS_VC (0) /* VC-mux */
131+#define BR2684_ENCAPS_LLC (1)
132+#define BR2684_ENCAPS_AUTODETECT (2) /* Unsuported */
133+
134+/*
135+ * This is for the ATM_NEWBACKENDIF call - these are like socket families:
136+ * the first element of the structure is the backend number and the rest
137+ * is per-backend specific
138+ */
139+struct atm_newif_br2684 {
140+ atm_backend_t backend_num; /* ATM_BACKEND_BR2684 */
141+ int media; /* BR2684_MEDIA_* */
142+ char ifname[IFNAMSIZ];
143+ int mtu;
144+};
145+
146+/*
147+ * This structure is used to specify a br2684 interface - either by a
148+ * positive integer (returned by ATM_NEWBACKENDIF) or the interfaces name
149+ */
150+#define BR2684_FIND_BYNOTHING (0)
151+#define BR2684_FIND_BYNUM (1)
152+#define BR2684_FIND_BYIFNAME (2)
153+struct br2684_if_spec {
154+ int method; /* BR2684_FIND_* */
155+ union {
156+ char ifname[IFNAMSIZ];
157+ int devnum;
158+ } spec;
159+};
160+
161+/*
162+ * This is for the ATM_SETBACKEND call - these are like socket families:
163+ * the first element of the structure is the backend number and the rest
164+ * is per-backend specific
165+ */
166+struct atm_backend_br2684 {
167+ atm_backend_t backend_num; /* ATM_BACKEND_BR2684 */
168+ struct br2684_if_spec ifspec;
169+ int fcs_in; /* BR2684_FCSIN_* */
170+ int fcs_out; /* BR2684_FCSOUT_* */
171+ int fcs_auto; /* 1: fcs_{in,out} disabled if no FCS rx'ed */
172+ int encaps; /* BR2684_ENCAPS_* */
173+ int has_vpiid; /* 1: use vpn_id - Unsupported */
174+ __u8 vpn_id[7];
175+ int send_padding; /* unsupported */
176+ int min_size; /* we will pad smaller packets than this */
177+};
178+
179+/*
180+ * The BR2684_SETFILT ioctl is an experimental mechanism for folks
181+ * terminating a large number of IP-only vcc's. When netfilter allows
182+ * efficient per-if in/out filters, this support will be removed
183+ */
184+struct br2684_filter {
185+ __u32 prefix; /* network byte order */
186+ __u32 netmask; /* 0 = disable filter */
187+};
188+
189+struct br2684_filter_set {
190+ struct br2684_if_spec ifspec;
191+ struct br2684_filter filter;
192+};
193+
194+#define BR2684_SETFILT _IOW( 'a', ATMIOC_BACKEND + 0, \
195+ struct br2684_filter_set)
196+
197+#endif /* _LINUX_ATMBR2684_H */
198diff -urN linux.orig/include/linux/atmdev.h linux/include/linux/atmdev.h
199--- linux.orig/include/linux/atmdev.h Tue Mar 27 01:50:03 2001
200+++ linux/include/linux/atmdev.h Sat Apr 21 18:06:09 2001
201@@ -87,6 +87,20 @@
202 #define ATM_SETSC _IOW('a',ATMIOC_SPECIAL+1,int)
203 /* enable or disable single-copy */
204
205+#define ATM_SETBACKEND _IOW('a',ATMIOC_SPECIAL+2,atm_backend_t)
206+ /* set backend handler */
207+#define ATM_NEWBACKENDIF _IOW('a',ATMIOC_SPECIAL+3,atm_backend_t)
208+ /* use backend to make new if */
209+
210+/*
211+ * These are backend handkers that can be set via the ATM_SETBACKEND call
212+ * above. In the future we may support dynamic loading of these - for now,
213+ * they're just being used to share the ATMIOC_BACKEND ioctls
214+ */
215+#define ATM_BACKEND_RAW 0
216+#define ATM_BACKEND_PPP 1 /* PPPoATM - RFC2364 */
217+#define ATM_BACKEND_BR2684 2 /* Bridged RFC1483/2684 */
218+
219 /* for ATM_GETTYPE */
220 #define ATM_ITFTYP_LEN 8 /* maximum length of interface type name */
221
222diff -urN linux.orig/include/linux/atmioc.h linux/include/linux/atmioc.h
223--- linux.orig/include/linux/atmioc.h Wed Feb 9 03:23:13 2000
224+++ linux/include/linux/atmioc.h Sat Apr 21 18:06:09 2001
225@@ -27,7 +27,9 @@
226 #define ATMIOC_SARPRV_END 0x7f
227 #define ATMIOC_ITF 0x80 /* Interface ioctls, globally unique */
228 #define ATMIOC_ITF_END 0x8f
229-/* 0x90-0xbf: Reserved for future use */
230+#define ATMIOC_BACKEND 0x90 /* ATM generic backend ioctls, u. per backend */
231+#define ATMIOC_BACKEND_END 0xaf
232+/* 0xb0-0xbf: Reserved for future use */
233 #define ATMIOC_AREQUIPA 0xc0 /* Application requested IP over ATM, glob. u. */
234 #define ATMIOC_LANE 0xd0 /* LAN Emulation, globally unique */
235 #define ATMIOC_MPOA 0xd8 /* MPOA, globally unique */
236diff -urN linux.orig/include/linux/atmppp.h linux/include/linux/atmppp.h
237--- linux.orig/include/linux/atmppp.h Thu Jan 1 01:00:00 1970
238+++ linux/include/linux/atmppp.h Sat Apr 21 18:06:09 2001
239@@ -0,0 +1,24 @@
240+/* atmppp.h - RFC2364 PPPoATM */
241+
242+/* Written 2000 by Mitchell Blank Jr */
243+
244+#ifndef _LINUX_ATMPPP_H
245+#define _LINUX_ATMPPP_H
246+
247+#include <linux/atm.h>
248+
249+#define PPPOATM_ENCAPS_AUTODETECT (0)
250+#define PPPOATM_ENCAPS_VC (1)
251+#define PPPOATM_ENCAPS_LLC (2)
252+
253+/*
254+ * This is for the ATM_SETBACKEND call - these are like socket families:
255+ * the first element of the structure is the backend number and the rest
256+ * is per-backend specific
257+ */
258+struct atm_backend_ppp {
259+ atm_backend_t backend_num; /* ATM_BACKEND_PPP */
260+ int encaps; /* PPPOATM_ENCAPS_* */
261+};
262+
263+#endif /* _LINUX_ATMPPP_H */
264diff -urN linux.orig/net/Config.in linux/net/Config.in
265--- linux.orig/net/Config.in Sat Apr 21 18:05:00 2001
266+++ linux/net/Config.in Sat Apr 21 18:06:09 2001
267@@ -45,6 +45,10 @@
268 if [ "$CONFIG_INET" = "y" -a "$CONFIG_ATM_LANE" != "n" ]; then
269 tristate ' Multi-Protocol Over ATM (MPOA) support' CONFIG_ATM_MPOA
270 fi
271+ tristate ' RFC1483/2684 Bridged protocols' CONFIG_ATM_BR2684
272+ if [ "$CONFIG_ATM_BR2684" != "n" ]; then
273+ bool ' Per-VC IP filter kludge' CONFIG_ATM_BR2684_IPFILTER
274+ fi
275 fi
276 fi
277
278diff -urN linux.orig/net/atm/Makefile linux/net/atm/Makefile
279--- linux.orig/net/atm/Makefile Tue Mar 27 01:36:30 2001
280+++ linux/net/atm/Makefile Sat Apr 21 18:06:09 2001
281@@ -21,6 +21,15 @@
282 NEED_IPCOM = ipcommon.o
283 endif
284
285+ifeq ($(CONFIG_ATM_BR2684),y)
286+ NEED_IPCOM = ipcommon.o
287+else
288+ ifeq ($(CONFIG_ATM_BR2684),m)
289+ NEED_IPCOM = ipcommon.o
290+ endif
291+endif
292+obj-$(CONFIG_ATM_BR2684) += br2684.o
293+
294 ifeq ($(CONFIG_NET_SCH_ATM),y)
295 NEED_IPCOM = ipcommon.o
296 endif
297@@ -33,6 +42,7 @@
298
299 obj-$(CONFIG_ATM_LANE) += lec.o
300 obj-$(CONFIG_ATM_MPOA) += mpoa.o
301+obj-$(CONFIG_PPPOATM) += pppoatm.o
302
303 include $(TOPDIR)/Rules.make
304
305diff -urN linux.orig/net/atm/br2684.c linux/net/atm/br2684.c
306--- linux.orig/net/atm/br2684.c Thu Jan 1 01:00:00 1970
307+++ linux/net/atm/br2684.c Sat Apr 21 18:06:09 2001
308@@ -0,0 +1,794 @@
309+/*
310+Experimental ethernet netdevice using ATM AAL5 as underlying carrier
311+(RFC1483 obsoleted by RFC2684) for Linux 2.4
312+Author: Marcell GAL, 2000, XDSL Ltd, Hungary
313+*/
314+
315+#include <linux/module.h>
316+#include <linux/config.h>
317+#include <linux/init.h>
318+#include <linux/kernel.h>
319+#include <linux/list.h>
320+#include <asm/uaccess.h>
321+#include <linux/netdevice.h>
322+#include <linux/skbuff.h>
323+#include <linux/etherdevice.h>
324+#include <net/arp.h>
325+#include <linux/rtnetlink.h>
326+#include <linux/atmbr2684.h>
327+
328+#include "ipcommon.h"
329+
330+/*
331+ * Define this to use a version of the code which interacts with the higher
332+ * layers in a more intellegent way, by always reserving enough space for
333+ * our header at the begining of the packet. However, there may still be
334+ * some problems with programs like tcpdump. In 2.5 we'll sort out what
335+ * we need to do to get this perfect. For now we just will copy the packet
336+ * if we need space for the header
337+ */
338+/* #define FASTER_VERSION */
339+
340+#ifdef DEBUG
341+#define DPRINTK(format, args...) printk(KERN_DEBUG "br2684: " format, ##args)
342+#else
343+#define DPRINTK(format, args...)
344+#endif
345+
346+#ifdef SKB_DEBUG
347+static void skb_debug(const struct sk_buff *skb)
348+{
349+#define NUM2PRINT 50
350+ char buf[NUM2PRINT * 3 + 1]; /* 3 chars per byte */
351+ int i = 0;
352+ for (i = 0; i < skb->len && i < NUM2PRINT; i++) {
353+ sprintf(buf + i * 3, "%2.2x ", 0xff & skb->data[i]);
354+ }
355+ printk(KERN_DEBUG "br2684: skb: %s\n", buf);
356+}
357+#else
358+#define skb_debug(skb) do {} while (0)
359+#endif
360+
361+static unsigned char llc_oui_pid_pad[] =
362+ { 0xAA, 0xAA, 0x03, 0x00, 0x80, 0xC2, 0x00, 0x07, 0x00, 0x00 };
363+#define PADLEN (2)
364+
365+enum br2684_encaps {
366+ e_vc = BR2684_ENCAPS_VC,
367+ e_llc = BR2684_ENCAPS_LLC,
368+};
369+
370+struct br2684_vcc {
371+ struct atm_vcc *atmvcc;
372+ struct br2684_dev *brdev;
373+ /* keep old push,pop functions for chaining */
374+ void (*old_push)(struct atm_vcc *vcc,struct sk_buff *skb);
375+ /* void (*old_pop)(struct atm_vcc *vcc,struct sk_buff *skb); */
376+ enum br2684_encaps encaps;
377+ struct list_head brvccs;
378+#ifdef CONFIG_ATM_BR2684_IPFILTER
379+ struct br2684_filter filter;
380+#endif /* CONFIG_ATM_BR2684_IPFILTER */
381+#ifndef FASTER_VERSION
382+ unsigned copies_needed, copies_failed;
383+#endif /* FASTER_VERSION */
384+};
385+
386+struct br2684_dev {
387+ struct net_device net_dev;
388+ struct list_head br2684_devs;
389+ int number;
390+ struct list_head brvccs; /* one device <=> one vcc (before xmas) */
391+ struct net_device_stats stats;
392+ int mac_was_set;
393+};
394+
395+/*
396+ * This lock should be held for writing any time the list of devices or
397+ * their attached vcc's could be altered. It should be held for reading
398+ * any time these are being queried. Note that we sometimes need to
399+ * do read-locking under interrupt context, so write locking must block
400+ * the current CPU's interrupts
401+ */
402+static rwlock_t devs_lock = RW_LOCK_UNLOCKED;
403+
404+static LIST_HEAD(br2684_devs);
405+
406+static inline struct br2684_dev *BRPRIV(const struct net_device *net_dev)
407+{
408+ return (struct br2684_dev *) ((char *) (net_dev) -
409+ (unsigned long) (&((struct br2684_dev *) 0)->net_dev));
410+}
411+
412+static inline struct br2684_dev *list_entry_brdev(const struct list_head *le)
413+{
414+ return list_entry(le, struct br2684_dev, br2684_devs);
415+}
416+
417+static inline struct br2684_vcc *BR2684_VCC(const struct atm_vcc *atmvcc)
418+{
419+ return (struct br2684_vcc *) (atmvcc->user_back);
420+}
421+
422+static inline struct br2684_vcc *list_entry_brvcc(const struct list_head *le)
423+{
424+ return list_entry(le, struct br2684_vcc, brvccs);
425+}
426+
427+/* Caller should hold read_lock(&devs_lock) */
428+static struct br2684_dev *br2684_find_dev(const struct br2684_if_spec *s)
429+{
430+ struct list_head *lh;
431+ struct br2684_dev *brdev;
432+ switch (s->method) {
433+ case BR2684_FIND_BYNUM:
434+ list_for_each(lh, &br2684_devs) {
435+ brdev = list_entry_brdev(lh);
436+ if (brdev->number == s->spec.devnum)
437+ return brdev;
438+ }
439+ break;
440+ case BR2684_FIND_BYIFNAME:
441+ list_for_each(lh, &br2684_devs) {
442+ brdev = list_entry_brdev(lh);
443+ if (!strncmp(brdev->net_dev.name, s->spec.ifname,
444+ sizeof brdev->net_dev.name))
445+ return brdev;
446+ }
447+ break;
448+ }
449+ return NULL;
450+}
451+
452+/*
453+ * Send a packet out a particular vcc. Not to useful right now, but paves
454+ * the way for multiple vcc's per itf. Returns true if we can send,
455+ * otherwise false
456+ */
457+static int br2684_xmit_vcc(struct sk_buff *skb, struct br2684_dev *brdev,
458+ struct br2684_vcc *brvcc)
459+{
460+ struct atm_vcc *atmvcc;
461+#ifdef FASTER_VERSION
462+ if (brvcc->encaps == e_llc)
463+ memcpy(skb_push(skb, 8), llc_oui_pid_pad, 8);
464+ /* last 2 bytes of llc_oui_pid_pad are managed by header routines;
465+ yes, you got it: 8 + 2 = sizeof(llc_oui_pid_pad)
466+ */
467+#else
468+ int minheadroom = (brvcc->encaps == e_llc) ? 10 : 2;
469+ if (skb_headroom(skb) < minheadroom) {
470+ struct sk_buff *skb2 = skb_realloc_headroom(skb, minheadroom);
471+ brvcc->copies_needed++;
472+ dev_kfree_skb(skb);
473+ if (skb2 == NULL) {
474+ brvcc->copies_failed++;
475+ return 0;
476+ }
477+ skb = skb2;
478+ }
479+ skb_push(skb, minheadroom);
480+ if (brvcc->encaps == e_llc)
481+ memcpy(skb->data, llc_oui_pid_pad, 10);
482+ else
483+ memset(skb->data, 0, 2);
484+#endif /* FASTER_VERSION */
485+ skb_debug(skb);
486+
487+ ATM_SKB(skb)->vcc = atmvcc = brvcc->atmvcc;
488+ DPRINTK("atm_skb(%p)->vcc(%p)->dev(%p)\n", skb, atmvcc, atmvcc->dev);
489+ if (!atm_may_send(atmvcc, skb->truesize)) {
490+ /* we free this here for now, because we cannot know in a higher
491+ layer whether the skb point it supplied wasn't freed yet.
492+ now, it always is.
493+ */
494+ dev_kfree_skb(skb);
495+ return 0;
496+ }
497+ atomic_add(skb->truesize, &atmvcc->tx_inuse);
498+ ATM_SKB(skb)->iovcnt = 0;
499+ ATM_SKB(skb)->atm_options = atmvcc->atm_options;
500+ brdev->stats.tx_packets++;
501+ brdev->stats.tx_bytes += skb->len;
502+ atmvcc->send(atmvcc, skb);
503+ return 1;
504+}
505+
506+static inline struct br2684_vcc *pick_outgoing_vcc(struct sk_buff *skb,
507+ struct br2684_dev *brdev)
508+{
509+ return list_empty(&brdev->brvccs) ? NULL :
510+ list_entry_brvcc(brdev->brvccs.next); /* 1 vcc/dev right now */
511+}
512+
513+static int br2684_start_xmit(struct sk_buff *skb, struct net_device *dev)
514+{
515+ struct br2684_dev *brdev = BRPRIV(dev);
516+ struct br2684_vcc *brvcc;
517+
518+ DPRINTK("br2684_start_xmit, skb->dst=%p\n", skb->dst);
519+ read_lock(&devs_lock);
520+ brvcc = pick_outgoing_vcc(skb, brdev);
521+ if (brvcc == NULL) {
522+ DPRINTK("no vcc attached to dev %s\n", dev->name);
523+ brdev->stats.tx_errors++;
524+ brdev->stats.tx_carrier_errors++;
525+ /* netif_stop_queue(dev); */
526+ dev_kfree_skb(skb);
527+ read_unlock(&devs_lock);
528+ return -EUNATCH;
529+ }
530+ if (!br2684_xmit_vcc(skb, brdev, brvcc)) {
531+ /*
532+ * We should probably use netif_*_queue() here, but that
533+ * involves added complication. We need to walk before
534+ * we can run
535+ */
536+ /* don't free here! this pointer might be no longer valid!
537+ dev_kfree_skb(skb);
538+ */
539+ brdev->stats.tx_errors++;
540+ brdev->stats.tx_fifo_errors++;
541+ }
542+ read_unlock(&devs_lock);
543+ return 0;
544+}
545+
546+static struct net_device_stats *br2684_get_stats(struct net_device *dev)
547+{
548+ DPRINTK("br2684_get_stats\n");
549+ return &BRPRIV(dev)->stats;
550+}
551+
552+#ifdef FASTER_VERSION
553+/*
554+ * These mirror eth_header and eth_header_cache. They are not usually
555+ * exported for use in modules, so we grab them from net_device
556+ * after ether_setup() is done with it. Bit of a hack.
557+ */
558+static int (*my_eth_header)(struct sk_buff *, struct net_device *,
559+ unsigned short, void *, void *, unsigned);
560+static int (*my_eth_header_cache)(struct neighbour *, struct hh_cache *);
561+
562+static int
563+br2684_header(struct sk_buff *skb, struct net_device *dev,
564+ unsigned short type, void *daddr, void *saddr, unsigned len)
565+{
566+ u16 *pad_before_eth;
567+ int t = my_eth_header(skb, dev, type, daddr, saddr, len);
568+ if (t > 0) {
569+ pad_before_eth = (u16 *) skb_push(skb, 2);
570+ *pad_before_eth = 0;
571+ return dev->hard_header_len; /* or return 16; ? */
572+ } else
573+ return t;
574+}
575+
576+static int
577+br2684_header_cache(struct neighbour *neigh, struct hh_cache *hh)
578+{
579+/* hh_data is 16 bytes long. if encaps is ether-llc we need 24, so
580+xmit will add the additional header part in that case */
581+ u16 *pad_before_eth = (u16 *)(hh->hh_data);
582+ int t = my_eth_header_cache(neigh, hh);
583+ DPRINTK("br2684_header_cache, neigh=%p, hh_cache=%p\n", neigh, hh);
584+ if (t < 0)
585+ return t;
586+ else {
587+ *pad_before_eth = 0;
588+ hh->hh_len = PADLEN + ETH_HLEN;
589+ }
590+ return 0;
591+}
592+
593+/*
594+ * This is similar to eth_type_trans, which cannot be used because of
595+ * our dev->hard_header_len
596+ */
597+static inline unsigned short br_type_trans(struct sk_buff *skb,
598+ struct net_device *dev)
599+{
600+ struct ethhdr *eth;
601+ unsigned char *rawp;
602+ eth = skb->mac.ethernet;
603+
604+ if (*eth->h_dest & 1) {
605+ if (memcmp(eth->h_dest, dev->broadcast, ETH_ALEN) == 0)
606+ skb->pkt_type = PACKET_BROADCAST;
607+ else
608+ skb->pkt_type = PACKET_MULTICAST;
609+ }
610+
611+ else if (memcmp(eth->h_dest, dev->dev_addr, ETH_ALEN))
612+ skb->pkt_type = PACKET_OTHERHOST;
613+
614+ if (ntohs(eth->h_proto) >= 1536)
615+ return eth->h_proto;
616+
617+ rawp = skb->data;
618+
619+ /*
620+ * This is a magic hack to spot IPX packets. Older Novell breaks
621+ * the protocol design and runs IPX over 802.3 without an 802.2 LLC
622+ * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This
623+ * won't work for fault tolerant netware but does for the rest.
624+ */
625+ if (*(unsigned short *) rawp == 0xFFFF)
626+ return htons(ETH_P_802_3);
627+
628+ /*
629+ * Real 802.2 LLC
630+ */
631+ return htons(ETH_P_802_2);
632+}
633+#endif /* FASTER_VERSION */
634+
635+/*
636+ * We remember when the MAC gets set, so we don't override it later with
637+ * the ESI of the ATM card of the first VC
638+ */
639+static int (*my_eth_mac_addr)(struct net_device *, void *);
640+static int br2684_mac_addr(struct net_device *dev, void *p)
641+{
642+ int err = my_eth_mac_addr(dev, p);
643+ if (!err)
644+ BRPRIV(dev)->mac_was_set = 1;
645+ return err;
646+}
647+
648+#ifdef CONFIG_ATM_BR2684_IPFILTER
649+/* this IOCTL is experimental. */
650+static int br2684_setfilt(struct atm_vcc *atmvcc, unsigned long arg)
651+{
652+ struct br2684_vcc *brvcc;
653+ struct br2684_filter_set fs;
654+
655+ if (copy_from_user(&fs, (void *) arg, sizeof fs))
656+ return -EFAULT;
657+ if (fs.ifspec.method != BR2684_FIND_BYNOTHING) {
658+ /*
659+ * This is really a per-vcc thing, but we can also search
660+ * by device
661+ */
662+ struct br2684_dev *brdev;
663+ read_lock(&devs_lock);
664+ brdev = br2684_find_dev(&fs.ifspec);
665+ if (brdev == NULL || list_empty(&brdev->brvccs) ||
666+ brdev->brvccs.next != brdev->brvccs.prev) /* >1 VCC */
667+ brvcc = NULL;
668+ else
669+ brvcc = list_entry_brvcc(brdev->brvccs.next);
670+ read_unlock(&devs_lock);
671+ if (brvcc == NULL)
672+ return -ESRCH;
673+ } else
674+ brvcc = BR2684_VCC(atmvcc);
675+ memcpy(&brvcc->filter, &fs.filter, sizeof(brvcc->filter));
676+ return 0;
677+}
678+
679+/* Returns 1 if packet should be dropped */
680+static inline int
681+packet_fails_filter(u16 type, struct br2684_vcc *brvcc, struct sk_buff *skb)
682+{
683+ if (brvcc->filter.netmask == 0)
684+ return 0; /* no filter in place */
685+ if (type == __constant_htons(ETH_P_IP) &&
686+ (((struct iphdr *) (skb->data))->daddr & brvcc->filter.
687+ netmask) == brvcc->filter.prefix)
688+ return 0;
689+ if (type == __constant_htons(ETH_P_ARP))
690+ return 0;
691+ /* TODO: we should probably filter ARPs too.. don't want to have
692+ * them returning values that don't make sense, or is that ok?
693+ */
694+ return 1; /* drop */
695+}
696+#endif /* CONFIG_ATM_BR2684_IPFILTER */
697+
698+static void br2684_close_vcc(struct br2684_vcc *brvcc)
699+{
700+ DPRINTK("removing VCC %p from dev %p\n", brvcc, brvcc->brdev);
701+ write_lock_irq(&devs_lock);
702+ list_del(&brvcc->brvccs);
703+ write_unlock_irq(&devs_lock);
704+ brvcc->atmvcc->user_back = NULL; /* what about vcc->recvq ??? */
705+ brvcc->old_push(brvcc->atmvcc, NULL); /* pass on the bad news */
706+ kfree(brvcc);
707+ MOD_DEC_USE_COUNT;
708+}
709+
710+/* when AAL5 PDU comes in: */
711+static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb)
712+{
713+ struct br2684_vcc *brvcc = BR2684_VCC(atmvcc);
714+ struct br2684_dev *brdev = brvcc->brdev;
715+ int plen = sizeof(llc_oui_pid_pad) + ETH_HLEN;
716+
717+ DPRINTK("br2684_push\n");
718+
719+ if (skb == NULL) { /* skb==NULL means VCC is being destroyed */
720+ br2684_close_vcc(brvcc);
721+ return;
722+ }
723+
724+ skb_debug(skb);
725+ atm_return(atmvcc, skb->truesize);
726+ DPRINTK("skb from brdev %p\n", brdev);
727+ if (brvcc->encaps == e_llc) {
728+ /* let us waste some time for checking the encapsulation.
729+ Note, that only 7 char is checked so frames with a valid FCS
730+ are also accepted (but FCS is not checked of course) */
731+ if (memcmp(skb->data, llc_oui_pid_pad, 7)) {
732+ brdev->stats.rx_errors++;
733+ dev_kfree_skb(skb);
734+ return;
735+ }
736+ } else {
737+ plen = PADLEN + ETH_HLEN; /* pad, dstmac,srcmac, ethtype */
738+ /* first 2 chars should be 0 */
739+ if (*((u16 *) (skb->data)) != 0) {
740+ brdev->stats.rx_errors++;
741+ dev_kfree_skb(skb);
742+ return;
743+ }
744+ }
745+ if (skb->len < plen) {
746+ brdev->stats.rx_errors++;
747+ dev_kfree_skb(skb); /* dev_ not needed? */
748+ return;
749+ }
750+
751+#ifdef FASTER_VERSION
752+ /* FIXME: tcpdump shows that pointer to mac header is 2 bytes earlier,
753+ than should be. What else should I set? */
754+ skb_pull(skb, plen);
755+ skb->mac.raw = ((char *) (skb->data)) - ETH_HLEN;
756+ skb->pkt_type = PACKET_HOST;
757+#ifdef CONFIG_BR2684_FAST_TRANS
758+ skb->protocol = ((u16 *) skb->data)[-1];
759+#else /* some protocols might require this: */
760+ skb->protocol = br_type_trans(skb, &brdev->net_dev);
761+#endif /* CONFIG_BR2684_FAST_TRANS */
762+#else
763+ skb_pull(skb, plen - ETH_HLEN);
764+ skb->protocol = eth_type_trans(skb, &brdev->net_dev);
765+#endif /* FASTER_VERSION */
766+#ifdef CONFIG_ATM_BR2684_IPFILTER
767+ if (packet_fails_filter(skb->protocol, brvcc, skb)) {
768+ brdev->stats.rx_dropped++;
769+ dev_kfree_skb(skb);
770+ return;
771+ }
772+#endif /* CONFIG_ATM_BR2684_IPFILTER */
773+ skb->dev = &brdev->net_dev;
774+ ATM_SKB(skb)->vcc = atmvcc; /* needed ? */
775+ DPRINTK("received packet's protocol: %x\n", ntohs(skb->protocol));
776+ skb_debug(skb);
777+ if (!(brdev->net_dev.flags & IFF_UP)) { /* sigh, interface is down */
778+ brdev->stats.rx_dropped++;
779+ dev_kfree_skb(skb);
780+ return;
781+ }
782+ brdev->stats.rx_packets++;
783+ brdev->stats.rx_bytes += skb->len;
784+ netif_rx(skb);
785+}
786+
787+static int br2684_regvcc(struct atm_vcc *atmvcc, unsigned long arg)
788+{
789+/* assign a vcc to a dev
790+Note: we do not have explicit unassign, but look at _push()
791+*/
792+ int err;
793+ struct br2684_vcc *brvcc;
794+ struct sk_buff_head copy;
795+ struct sk_buff *skb;
796+ struct br2684_dev *brdev;
797+ struct atm_backend_br2684 be;
798+
799+ MOD_INC_USE_COUNT;
800+ if (copy_from_user(&be, (void *) arg, sizeof be)) {
801+ MOD_DEC_USE_COUNT;
802+ return -EFAULT;
803+ }
804+ write_lock_irq(&devs_lock);
805+ brdev = br2684_find_dev(&be.ifspec);
806+ if (brdev == NULL) {
807+ printk(KERN_ERR
808+ "br2684: tried to attach to non-existant device\n");
809+ err = -ENXIO;
810+ goto error;
811+ }
812+ if (atmvcc->push == NULL) {
813+ err = -EBADFD;
814+ goto error;
815+ }
816+ if (!list_empty(&brdev->brvccs)) { /* Only 1 VCC/dev right now */
817+ err = -EEXIST;
818+ goto error;
819+ }
820+ if (be.fcs_in != BR2684_FCSIN_NO || be.fcs_out != BR2684_FCSOUT_NO ||
821+ be.fcs_auto || be.has_vpiid || be.send_padding || (be.encaps !=
822+ BR2684_ENCAPS_VC && be.encaps != BR2684_ENCAPS_LLC) ||
823+ be.min_size != 0) {
824+ err = -EINVAL;
825+ goto error;
826+ }
827+ brvcc = kmalloc(sizeof(struct br2684_vcc), GFP_KERNEL);
828+ if (!brvcc) {
829+ err = -ENOMEM;
830+ goto error;
831+ }
832+ memset(brvcc, 0, sizeof(struct br2684_vcc));
833+ DPRINTK("br2684_regvcc vcc=%p, encaps=%d, brvcc=%p\n", atmvcc, be.encaps,
834+ brvcc);
835+ if (list_empty(&brdev->brvccs) && !brdev->mac_was_set) {
836+ unsigned char *esi = atmvcc->dev->esi;
837+ if (esi[0] | esi[1] | esi[2] | esi[3] | esi[4] | esi[5])
838+ memcpy(brdev->net_dev.dev_addr, esi,
839+ brdev->net_dev.addr_len);
840+ else
841+ brdev->net_dev.dev_addr[2] = 1;
842+ }
843+ list_add(&brvcc->brvccs, &brdev->brvccs);
844+ write_unlock_irq(&devs_lock);
845+ brvcc->brdev = brdev;
846+ brvcc->atmvcc = atmvcc;
847+ atmvcc->user_back = brvcc;
848+ brvcc->encaps = (enum br2684_encaps) be.encaps;
849+ brvcc->old_push = atmvcc->push;
850+ barrier();
851+ atmvcc->push = br2684_push;
852+ skb_queue_head_init(&copy);
853+ skb_migrate(&atmvcc->recvq, &copy);
854+ while ((skb = skb_dequeue(&copy))) {
855+ BRPRIV(skb->dev)->stats.rx_bytes -= skb->len;
856+ BRPRIV(skb->dev)->stats.rx_packets--;
857+ br2684_push(atmvcc, skb);
858+ }
859+ return 0;
860+ error:
861+ write_unlock_irq(&devs_lock);
862+ MOD_DEC_USE_COUNT;
863+ return err;
864+}
865+
866+static int br2684_create(unsigned long arg)
867+{
868+ int err;
869+ struct br2684_dev *brdev;
870+ struct atm_newif_br2684 ni;
871+
872+ DPRINTK("br2684_create\n");
873+ /*
874+ * We track module use by vcc's NOT the devices they're on. We're
875+ * protected here against module death by the kernel_lock, but if
876+ * we need to sleep we should make sure that the module doesn't
877+ * disappear under us.
878+ */
879+ MOD_INC_USE_COUNT;
880+ if (copy_from_user(&ni, (void *) arg, sizeof ni)) {
881+ MOD_DEC_USE_COUNT;
882+ return -EFAULT;
883+ }
884+ if (ni.media != BR2684_MEDIA_ETHERNET || ni.mtu != 1500) {
885+ MOD_DEC_USE_COUNT;
886+ return -EINVAL;
887+ }
888+ if ((brdev = kmalloc(sizeof(struct br2684_dev), GFP_KERNEL)) == NULL) {
889+ MOD_DEC_USE_COUNT;
890+ return -ENOMEM;
891+ }
892+ memset(brdev, 0, sizeof(struct br2684_dev));
893+ INIT_LIST_HEAD(&brdev->brvccs);
894+
895+ write_lock_irq(&devs_lock);
896+ brdev->number = list_empty(&br2684_devs) ? 1 :
897+ list_entry_brdev(br2684_devs.prev)->number + 1;
898+ list_add_tail(&brdev->br2684_devs, &br2684_devs);
899+ write_unlock_irq(&devs_lock);
900+
901+ if (ni.ifname[0] != '\0') {
902+ memcpy(brdev->net_dev.name, ni.ifname,
903+ sizeof(brdev->net_dev.name));
904+ brdev->net_dev.name[sizeof(brdev->net_dev.name) - 1] = '\0';
905+ } else
906+ sprintf(brdev->net_dev.name, "nas%d", brdev->number);
907+ DPRINTK("registered netdev %s\n", brdev->net_dev.name);
908+ ether_setup(&brdev->net_dev);
909+ brdev->mac_was_set = 0;
910+#ifdef FASTER_VERSION
911+ my_eth_header = brdev->net_dev.hard_header;
912+ brdev->net_dev.hard_header = br2684_header;
913+ my_eth_header_cache = brdev->net_dev.hard_header_cache;
914+ brdev->net_dev.hard_header_cache = br2684_header_cache;
915+ brdev->net_dev.hard_header_len = sizeof(llc_oui_pid_pad) + ETH_HLEN; /* 10 + 14 */
916+#endif
917+ my_eth_mac_addr = brdev->net_dev.set_mac_address;
918+ brdev->net_dev.set_mac_address = br2684_mac_addr;
919+ brdev->net_dev.hard_start_xmit = br2684_start_xmit;
920+ brdev->net_dev.get_stats = br2684_get_stats;
921+
922+ /* open, stop, do_ioctl ? */
923+ err = register_netdev(&brdev->net_dev);
924+ MOD_DEC_USE_COUNT;
925+ if (err < 0) {
926+ printk(KERN_ERR "br2684_create: register_netdev failed\n");
927+ write_lock_irq(&devs_lock);
928+ list_del(&brdev->br2684_devs);
929+ write_unlock_irq(&devs_lock);
930+ kfree(brdev);
931+ return err;
932+ }
933+ return 0;
934+}
935+
936+/*
937+ * This handles ioctls actually performed on our vcc - we must return
938+ * -ENOIOCTLCMD for any unrecognized ioctl
939+ */
940+static int br2684_ioctl(struct atm_vcc *atmvcc, unsigned int cmd,
941+ unsigned long arg)
942+{
943+ int err;
944+ switch(cmd) {
945+ case ATM_SETBACKEND:
946+ case ATM_NEWBACKENDIF: {
947+ atm_backend_t b;
948+ MOD_INC_USE_COUNT;
949+ err = get_user(b, (atm_backend_t *) arg);
950+ MOD_DEC_USE_COUNT;
951+ if (err)
952+ return -EFAULT;
953+ if (b != ATM_BACKEND_BR2684)
954+ return -ENOIOCTLCMD;
955+ if (!capable(CAP_NET_ADMIN))
956+ return -EPERM;
957+ if (cmd == ATM_SETBACKEND)
958+ return br2684_regvcc(atmvcc, arg);
959+ else
960+ return br2684_create(arg);
961+ }
962+#ifdef CONFIG_ATM_BR2684_IPFILTER
963+ case BR2684_SETFILT:
964+ if (atmvcc->push != br2684_push)
965+ return -ENOIOCTLCMD;
966+ if (!capable(CAP_NET_ADMIN))
967+ return -EPERM;
968+ MOD_INC_USE_COUNT;
969+ err = br2684_setfilt(atmvcc, arg);
970+ MOD_DEC_USE_COUNT;
971+ return err;
972+#endif /* CONFIG_ATM_BR2684_IPFILTER */
973+ }
974+ return -ENOIOCTLCMD;
975+}
976+
977+/* Never put more than 256 bytes in at once */
978+static int br2684_proc_engine(loff_t pos, char *buf)
979+{
980+ struct list_head *lhd, *lhc;
981+ struct br2684_dev *brdev;
982+ struct br2684_vcc *brvcc;
983+ list_for_each(lhd, &br2684_devs) {
984+ brdev = list_entry_brdev(lhd);
985+ if (pos-- == 0)
986+ return sprintf(buf, "dev %.16s: num=%d, mac=%02X:%02X:"
987+ "%02X:%02X:%02X:%02X (%s)\n", brdev->net_dev.name,
988+ brdev->number,
989+ brdev->net_dev.dev_addr[0],
990+ brdev->net_dev.dev_addr[1],
991+ brdev->net_dev.dev_addr[2],
992+ brdev->net_dev.dev_addr[3],
993+ brdev->net_dev.dev_addr[4],
994+ brdev->net_dev.dev_addr[5],
995+ brdev->mac_was_set ? "set" : "auto");
996+ list_for_each(lhc, &brdev->brvccs) {
997+ brvcc = list_entry_brvcc(lhc);
998+ if (pos-- == 0)
999+ return sprintf(buf, " vcc %d.%d.%d: encaps=%s"
1000+#ifndef FASTER_VERSION
1001+ ", failed copies %u/%u"
1002+#endif /* FASTER_VERSION */
1003+ "\n", brvcc->atmvcc->dev->number,
1004+ brvcc->atmvcc->vpi, brvcc->atmvcc->vci,
1005+ (brvcc->encaps == e_llc) ? "LLC" : "VC"
1006+#ifndef FASTER_VERSION
1007+ , brvcc->copies_failed
1008+ , brvcc->copies_needed
1009+#endif /* FASTER_VERSION */
1010+ );
1011+#ifdef CONFIG_ATM_BR2684_IPFILTER
1012+#define b1(var, byte) ((u8 *) &brvcc->filter.var)[byte]
1013+#define bs(var) b1(var, 0), b1(var, 1), b1(var, 2), b1(var, 3)
1014+ if (brvcc->filter.netmask != 0 && pos-- == 0)
1015+ return sprintf(buf, " filter=%d.%d.%d.%d/"
1016+ "%d.%d.%d.%d\n", bs(prefix), bs(netmask));
1017+#undef bs
1018+#undef b1
1019+#endif /* CONFIG_ATM_BR2684_IPFILTER */
1020+ }
1021+ }
1022+ return 0;
1023+}
1024+
1025+static ssize_t br2684_proc_read(struct file *file, char *buf, size_t count,
1026+ loff_t *pos)
1027+{
1028+ unsigned long page;
1029+ int len = 0, x, left;
1030+ page = get_free_page(GFP_KERNEL);
1031+ if (!page)
1032+ return -ENOMEM;
1033+ left = PAGE_SIZE - 256;
1034+ if (count < left)
1035+ left = count;
1036+ read_lock(&devs_lock);
1037+ for (;;) {
1038+ x = br2684_proc_engine(*pos, &((char *) page)[len]);
1039+ if (x == 0)
1040+ break;
1041+ if (x > left)
1042+ /*
1043+ * This should only happen if the user passed in
1044+ * a "count" too small for even one line
1045+ */
1046+ x = -EINVAL;
1047+ if (x < 0) {
1048+ len = x;
1049+ break;
1050+ }
1051+ len += x;
1052+ left -= x;
1053+ (*pos)++;
1054+ if (left < 256)
1055+ break;
1056+ }
1057+ read_unlock(&devs_lock);
1058+ if (len > 0 && copy_to_user(buf, (char *) page, len))
1059+ len = -EFAULT;
1060+ free_page(page);
1061+ return len;
1062+}
1063+
1064+static struct file_operations br2684_proc_operations = {
1065+ read: br2684_proc_read,
1066+};
1067+
1068+extern struct proc_dir_entry *atm_proc_root; /* from proc.c */
1069+
1070+extern int (*br2684_ioctl_hook)(struct atm_vcc *, unsigned int, unsigned long);
1071+
1072+/* the following avoids some spurious warnings from the compiler */
1073+#define UNUSED __attribute__((unused))
1074+
1075+static int __init UNUSED br2684_init(void)
1076+{
1077+ struct proc_dir_entry *p;
1078+ if ((p = create_proc_entry("br2684", 0, atm_proc_root)) == NULL)
1079+ return -ENOMEM;
1080+ p->proc_fops = &br2684_proc_operations;
1081+ br2684_ioctl_hook = br2684_ioctl;
1082+ return 0;
1083+}
1084+
1085+static void __exit UNUSED br2684_exit(void)
1086+{
1087+ struct br2684_dev *brdev;
1088+ br2684_ioctl_hook = NULL;
1089+ remove_proc_entry("br2684", atm_proc_root);
1090+ while (!list_empty(&br2684_devs)) {
1091+ brdev = list_entry_brdev(br2684_devs.next);
1092+ unregister_netdev(&brdev->net_dev);
1093+ list_del(&brdev->br2684_devs);
1094+ kfree(brdev);
1095+ }
1096+}
1097+
1098+module_init(br2684_init);
1099+module_exit(br2684_exit);
1100+
1101+MODULE_AUTHOR("Marcell GAL");
1102+MODULE_DESCRIPTION("RFC2684 bridged protocols over ATM/AAL5");
1103diff -urN linux.orig/net/atm/common.c linux/net/atm/common.c
1104--- linux.orig/net/atm/common.c Sat Apr 21 18:04:58 2001
1105+++ linux/net/atm/common.c Sat Apr 21 18:06:09 2001
1106@@ -58,6 +58,18 @@
1107 #endif
1108 #endif
1109
1110+#if defined(CONFIG_PPPOATM) || defined(CONFIG_PPPOATM_MODULE)
1111+int (*pppoatm_ioctl_hook)(struct atm_vcc *, unsigned int, unsigned long);
1112+EXPORT_SYMBOL(pppoatm_ioctl_hook);
1113+#endif
1114+
1115+#if defined(CONFIG_ATM_BR2684) || defined(CONFIG_ATM_BR2684_MODULE)
1116+int (*br2684_ioctl_hook)(struct atm_vcc *, unsigned int, unsigned long);
1117+#endif
1118+#ifdef CONFIG_ATM_BR2684_MODULE
1119+EXPORT_SYMBOL(br2684_ioctl_hook);
1120+#endif
1121+
1122 #include "resources.h" /* atm_find_dev */
1123 #include "common.h" /* prototypes */
1124 #include "protocols.h" /* atm_init_<transport> */
1125@@ -774,6 +786,20 @@
1126 default:
1127 break;
1128 }
1129+#if defined(CONFIG_PPPOATM) || defined(CONFIG_PPPOATM_MODULE)
1130+ if (pppoatm_ioctl_hook &&
1131+ (error = pppoatm_ioctl_hook(vcc, cmd, arg)) != -ENOIOCTLCMD) {
1132+ spin_unlock (&atm_dev_lock);
1133+ return error;
1134+ }
1135+#endif
1136+#if defined(CONFIG_ATM_BR2684) || defined(CONFIG_ATM_BR2684_MODULE)
1137+ if (br2684_ioctl_hook &&
1138+ (error = br2684_ioctl_hook(vcc, cmd, arg)) != -ENOIOCTLCMD) {
1139+ spin_unlock (&atm_dev_lock);
1140+ return error;
1141+ }
1142+#endif
1143 if (get_user(buf,&((struct atmif_sioc *) arg)->arg)) {
1144 ret_val = -EFAULT;
1145 goto done;
1146diff -urN linux.orig/net/atm/pppoatm.c linux/net/atm/pppoatm.c
1147--- linux.orig/net/atm/pppoatm.c Thu Jan 1 01:00:00 1970
1148+++ linux/net/atm/pppoatm.c Sat Apr 21 18:06:09 2001
1149@@ -0,0 +1,373 @@
1150+/* net/atm/pppoatm.c - RFC2364 PPP over ATM/AAL5 */
1151+
1152+/* Copyright 1999-2000 by Mitchell Blank Jr */
1153+/* Based on clip.c; 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
1154+/* And on ppp_async.c; Copyright 1999 Paul Mackerras */
1155+/* And help from Jens Axboe */
1156+
1157+/*
1158+ * This program is free software; you can redistribute it and/or
1159+ * modify it under the terms of the GNU General Public License
1160+ * as published by the Free Software Foundation; either version
1161+ * 2 of the License, or (at your option) any later version.
1162+ *
1163+ * This driver provides the encapsulation and framing for sending
1164+ * and receiving PPP frames in ATM AAL5 PDUs.
1165+ */
1166+
1167+/*
1168+ * One shortcoming of this driver is that it does not comply with
1169+ * section 8 of RFC2364 - we are supposed to detect a change
1170+ * in encapsulation and immediately abort the connection (in order
1171+ * to avoid a black-hole being created if our peer loses state
1172+ * and changes encapsulation unilaterally. However, since the
1173+ * ppp_generic layer actually does the decapsulation, we need
1174+ * a way of notifying it when we _think_ there might be a problem)
1175+ * There's two cases:
1176+ * 1. LLC-encapsulation was missing when it was enabled. In
1177+ * this case, we should tell the upper layer "tear down
1178+ * this session if this skb looks ok to you"
1179+ * 2. LLC-encapsulation was present when it was disabled. Then
1180+ * we need to tell the upper layer "this packet may be
1181+ * ok, but if its in error tear down the session"
1182+ * These hooks are not yet available in ppp_generic
1183+ */
1184+
1185+#include <linux/module.h>
1186+#include <linux/config.h>
1187+#include <linux/init.h>
1188+#include <linux/skbuff.h>
1189+#include <linux/atm.h>
1190+#include <linux/atmdev.h>
1191+#include <linux/ppp_defs.h>
1192+#include <linux/if_ppp.h>
1193+#include <linux/ppp_channel.h>
1194+#include <linux/atmppp.h>
1195+
1196+#if 0
1197+#define DPRINTK(format, args...) \
1198+ printk(KERN_DEBUG "pppoatm: " format, ##args)
1199+#else
1200+#define DPRINTK(format, args...)
1201+#endif
1202+
1203+enum pppoatm_encaps {
1204+ e_autodetect = PPPOATM_ENCAPS_AUTODETECT,
1205+ e_vc = PPPOATM_ENCAPS_VC,
1206+ e_llc = PPPOATM_ENCAPS_LLC,
1207+};
1208+
1209+struct pppoatm_vcc {
1210+ struct atm_vcc *atmvcc; /* VCC descriptor */
1211+ void (*old_push)(struct atm_vcc *, struct sk_buff *);
1212+ void (*old_pop)(struct atm_vcc *, struct sk_buff *);
1213+ /* keep old push/pop for detaching */
1214+ enum pppoatm_encaps encaps;
1215+ int flags; /* SC_COMP_PROT - compress protocol */
1216+ struct ppp_channel chan; /* interface to generic ppp layer */
1217+ struct tasklet_struct wakeup_tasklet;
1218+};
1219+
1220+/*
1221+ * Header used for LLC Encapsulated PPP (4 bytes) followed by the LCP protocol
1222+ * ID (0xC021) used in autodetection
1223+ */
1224+static const unsigned char pppllc[6] = { 0xFE, 0xFE, 0x03, 0xCF, 0xC0, 0x21 };
1225+#define LLC_LEN (4)
1226+
1227+static inline struct pppoatm_vcc *atmvcc_to_pvcc(const struct atm_vcc *atmvcc)
1228+{
1229+ return (struct pppoatm_vcc *) (atmvcc->user_back);
1230+}
1231+
1232+static inline struct pppoatm_vcc *chan_to_pvcc(const struct ppp_channel *chan)
1233+{
1234+ return (struct pppoatm_vcc *) (chan->private);
1235+}
1236+
1237+/*
1238+ * We can't do this directly from our _pop handler, since the ppp code
1239+ * doesn't want to be called in interrupt context, so we do it from
1240+ * a tasklet
1241+ */
1242+static void pppoatm_wakeup_sender(unsigned long arg)
1243+{
1244+ ppp_output_wakeup((struct ppp_channel *) arg);
1245+}
1246+
1247+/*
1248+ * This gets called every time the ATM card has finished sending our
1249+ * skb. The ->old_pop will take care up normal atm flow control,
1250+ * but we also need to wake up the device if we blocked it
1251+ */
1252+static void pppoatm_pop(struct atm_vcc *atmvcc, struct sk_buff *skb)
1253+{
1254+ struct pppoatm_vcc *pvcc = atmvcc_to_pvcc(atmvcc);
1255+ pvcc->old_pop(atmvcc, skb);
1256+ /*
1257+ * We don't really always want to do this since it's
1258+ * really inefficient - it would be much better if we could
1259+ * test if we had actually throttled the generic layer.
1260+ * Unfortunately then there would be a nasty SMP race where
1261+ * we could clear that flag just as we refuse another packet.
1262+ * For now we do the safe thing.
1263+ */
1264+ tasklet_schedule(&pvcc->wakeup_tasklet);
1265+}
1266+
1267+/*
1268+ * Unbind from PPP - currently we only do this when closing the socket,
1269+ * but we could put this into an ioctl if need be
1270+ */
1271+static void pppoatm_unassign_vcc(struct atm_vcc *atmvcc)
1272+{
1273+ struct pppoatm_vcc *pvcc;
1274+ pvcc = atmvcc_to_pvcc(atmvcc);
1275+ atmvcc->push = pvcc->old_push;
1276+ atmvcc->pop = pvcc->old_pop;
1277+ tasklet_disable(&pvcc->wakeup_tasklet);
1278+ ppp_unregister_channel(&pvcc->chan);
1279+ atmvcc->user_back = NULL;
1280+ kfree(pvcc);
1281+ /* Gee, I hope we have the big kernel lock here... */
1282+ MOD_DEC_USE_COUNT;
1283+}
1284+
1285+/* Called when an AAL5 PDU comes in */
1286+static void pppoatm_push(struct atm_vcc *atmvcc, struct sk_buff *skb)
1287+{
1288+ struct pppoatm_vcc *pvcc = atmvcc_to_pvcc(atmvcc);
1289+ DPRINTK("pppoatm push\n");
1290+ if (skb == NULL) { /* VCC was closed */
1291+ DPRINTK("removing ATMPPP VCC %p\n", pvcc);
1292+ pppoatm_unassign_vcc(atmvcc);
1293+ atmvcc->push(atmvcc, NULL); /* Pass along bad news */
1294+ return;
1295+ }
1296+ atm_return(atmvcc, skb->truesize);
1297+ switch (pvcc->encaps) {
1298+ case e_llc:
1299+ if (skb->len < LLC_LEN ||
1300+ memcmp(skb->data, pppllc, LLC_LEN))
1301+ goto error;
1302+ skb_pull(skb, LLC_LEN);
1303+ break;
1304+ case e_autodetect:
1305+ if (pvcc->chan.ppp == NULL) { /* Not bound yet! */
1306+ kfree_skb(skb);
1307+ return;
1308+ }
1309+ if (skb->len >= sizeof(pppllc) &&
1310+ !memcmp(skb->data, pppllc, sizeof(pppllc))) {
1311+ pvcc->encaps = e_llc;
1312+ skb_pull(skb, LLC_LEN);
1313+ break;
1314+ }
1315+ if (skb->len >= (sizeof(pppllc) - LLC_LEN) &&
1316+ !memcmp(skb->data, &pppllc[LLC_LEN],
1317+ sizeof(pppllc) - LLC_LEN)) {
1318+ pvcc->encaps = e_vc;
1319+ pvcc->chan.mtu += LLC_LEN;
1320+ break;
1321+ }
1322+ DPRINTK("(unit %d): Couldn't autodetect yet "
1323+ "(skb: %02X %02X %02X %02X %02X %02X)\n",
1324+ pvcc->chan.unit,
1325+ skb->data[0], skb->data[1], skb->data[2],
1326+ skb->data[3], skb->data[4], skb->data[5]);
1327+ goto error;
1328+ case e_vc:
1329+ break;
1330+ }
1331+ ppp_input(&pvcc->chan, skb);
1332+ return;
1333+ error:
1334+ kfree_skb(skb);
1335+ ppp_input_error(&pvcc->chan, 0);
1336+}
1337+
1338+/*
1339+ * Called by the ppp_generic.c to send a packet - returns true if packet
1340+ * was accepted. If we return false, then it's our job to call
1341+ * ppp_output_wakeup(chan) when we're feeling more up to it.
1342+ * Note that in the ENOMEM case (as opposed to the !atm_may_send case)
1343+ * we should really drop the packet, but the generic layer doesn't
1344+ * support this yet. We just return 'DROP_PACKET' which we actually define
1345+ * as success, just to be clear what we're really doing.
1346+ */
1347+#define DROP_PACKET 1
1348+static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb)
1349+{
1350+ struct pppoatm_vcc *pvcc = chan_to_pvcc(chan);
1351+ ATM_SKB(skb)->vcc = pvcc->atmvcc;
1352+ DPRINTK("(unit %d): pppoatm_send (skb=0x%p, vcc=0x%p)\n",
1353+ pvcc->chan.unit, skb, pvcc->atmvcc);
1354+ if (skb->data[0] == '\0' && (pvcc->flags & SC_COMP_PROT))
1355+ (void) skb_pull(skb, 1);
1356+ switch (pvcc->encaps) { /* LLC encapsulation needed */
1357+ case e_llc:
1358+ if (skb_headroom(skb) < LLC_LEN) {
1359+ struct sk_buff *n;
1360+ n = skb_realloc_headroom(skb, LLC_LEN);
1361+ if (n != NULL &&
1362+ !atm_may_send(pvcc->atmvcc, n->truesize)) {
1363+ kfree_skb(n);
1364+ goto nospace;
1365+ }
1366+ kfree_skb(skb);
1367+ if ((skb = n) == NULL)
1368+ return DROP_PACKET;
1369+ } else if (!atm_may_send(pvcc->atmvcc, skb->truesize))
1370+ goto nospace;
1371+ memcpy(skb_push(skb, LLC_LEN), pppllc, LLC_LEN);
1372+ break;
1373+ case e_vc:
1374+ if (!atm_may_send(pvcc->atmvcc, skb->truesize))
1375+ goto nospace;
1376+ break;
1377+ case e_autodetect:
1378+ DPRINTK("(unit %d): Trying to send without setting encaps!\n",
1379+ pvcc->chan.unit);
1380+ kfree_skb(skb);
1381+ return 1;
1382+ }
1383+ atomic_add(skb->truesize, &ATM_SKB(skb)->vcc->tx_inuse);
1384+ ATM_SKB(skb)->iovcnt = 0;
1385+ ATM_SKB(skb)->atm_options = ATM_SKB(skb)->vcc->atm_options;
1386+ DPRINTK("(unit %d): atm_skb(%p)->vcc(%p)->dev(%p)\n",
1387+ pvcc->chan.unit, skb, ATM_SKB(skb)->vcc,
1388+ ATM_SKB(skb)->vcc->dev);
1389+ return ATM_SKB(skb)->vcc->send(ATM_SKB(skb)->vcc, skb)
1390+ ? DROP_PACKET : 1;
1391+ nospace:
1392+ /*
1393+ * We don't have space to send this SKB now, but we might have
1394+ * already applied SC_COMP_PROT compression, so may need to undo
1395+ */
1396+ if ((pvcc->flags & SC_COMP_PROT) && skb_headroom(skb) > 0 &&
1397+ skb->data[-1] == '\0')
1398+ (void) skb_push(skb, 1);
1399+ return 0;
1400+}
1401+
1402+/* This handles ioctls sent to the /dev/ppp interface */
1403+static int pppoatm_devppp_ioctl(struct ppp_channel *chan, unsigned int cmd,
1404+ unsigned long arg)
1405+{
1406+ switch (cmd) {
1407+ case PPPIOCGFLAGS:
1408+ return put_user(chan_to_pvcc(chan)->flags, (int *) arg)
1409+ ? -EFAULT : 0;
1410+ case PPPIOCSFLAGS:
1411+ return get_user(chan_to_pvcc(chan)->flags, (int *) arg)
1412+ ? -EFAULT : 0;
1413+ }
1414+ return -ENOTTY;
1415+}
1416+
1417+static /*const*/ struct ppp_channel_ops pppoatm_ops = {
1418+ start_xmit: pppoatm_send,
1419+ ioctl: pppoatm_devppp_ioctl,
1420+};
1421+
1422+static int pppoatm_assign_vcc(struct atm_vcc *atmvcc, unsigned long arg)
1423+{
1424+ struct atm_backend_ppp be;
1425+ struct pppoatm_vcc *pvcc;
1426+ int err;
1427+ /*
1428+ * Each PPPoATM instance has its own tasklet - this is just a
1429+ * prototypical one used to initialize them
1430+ */
1431+ static const DECLARE_TASKLET(tasklet_proto, pppoatm_wakeup_sender, 0);
1432+ if (copy_from_user(&be, (void *) arg, sizeof be))
1433+ return -EFAULT;
1434+ if (be.encaps != PPPOATM_ENCAPS_AUTODETECT &&
1435+ be.encaps != PPPOATM_ENCAPS_VC && be.encaps != PPPOATM_ENCAPS_LLC)
1436+ return -EINVAL;
1437+ MOD_INC_USE_COUNT;
1438+ pvcc = kmalloc(sizeof(*pvcc), GFP_KERNEL);
1439+ if (pvcc == NULL) {
1440+ MOD_DEC_USE_COUNT;
1441+ return -ENOMEM;
1442+ }
1443+ memset(pvcc, 0, sizeof(*pvcc));
1444+ pvcc->atmvcc = atmvcc;
1445+ pvcc->old_push = atmvcc->push;
1446+ pvcc->old_pop = atmvcc->pop;
1447+ pvcc->encaps = (enum pppoatm_encaps) be.encaps;
1448+ pvcc->chan.private = pvcc;
1449+ pvcc->chan.ops = &pppoatm_ops;
1450+ pvcc->chan.mtu = atmvcc->qos.txtp.max_sdu - PPP_HDRLEN -
1451+ (be.encaps == e_vc ? 0 : LLC_LEN);
1452+ pvcc->wakeup_tasklet = tasklet_proto;
1453+ pvcc->wakeup_tasklet.data = (unsigned long) &pvcc->chan;
1454+ if ((err = ppp_register_channel(&pvcc->chan)) != 0) {
1455+ kfree(pvcc);
1456+ return err;
1457+ }
1458+ atmvcc->user_back = pvcc;
1459+ atmvcc->push = pppoatm_push;
1460+ atmvcc->pop = pppoatm_pop;
1461+ return 0;
1462+}
1463+
1464+/*
1465+ * This handles ioctls actually performed on our vcc - we must return
1466+ * -ENOIOCTLCMD for any unrecognized ioctl
1467+ */
1468+static int pppoatm_ioctl(struct atm_vcc *atmvcc, unsigned int cmd,
1469+ unsigned long arg)
1470+{
1471+ int err;
1472+ if (cmd != ATM_SETBACKEND && atmvcc->push != pppoatm_push)
1473+ return -ENOIOCTLCMD;
1474+ switch (cmd) {
1475+ case ATM_SETBACKEND: {
1476+ atm_backend_t b;
1477+ MOD_INC_USE_COUNT;
1478+ err = get_user(b, (atm_backend_t *) arg);
1479+ MOD_DEC_USE_COUNT;
1480+ if (err)
1481+ return -EFAULT;
1482+ if (b != ATM_BACKEND_PPP)
1483+ return -ENOIOCTLCMD;
1484+ if (!capable(CAP_NET_ADMIN))
1485+ return -EPERM;
1486+ return pppoatm_assign_vcc(atmvcc, arg);
1487+ }
1488+ case PPPIOCGCHAN:
1489+ case PPPIOCGUNIT:
1490+ MOD_INC_USE_COUNT;
1491+ err = put_user((cmd == PPPIOCGCHAN) ?
1492+ ppp_channel_index(&atmvcc_to_pvcc(atmvcc)->chan) :
1493+ ppp_unit_number(&atmvcc_to_pvcc(atmvcc)->chan),
1494+ (int *) arg);
1495+ MOD_DEC_USE_COUNT;
1496+ return err ? -EFAULT : 0;
1497+ }
1498+ return -ENOIOCTLCMD;
1499+}
1500+
1501+/* the following avoids some spurious warnings from the compiler */
1502+#define UNUSED __attribute__((unused))
1503+
1504+extern int (*pppoatm_ioctl_hook)(struct atm_vcc *,
1505+ unsigned int, unsigned long);
1506+
1507+static int __init UNUSED pppoatm_init(void)
1508+{
1509+ pppoatm_ioctl_hook = pppoatm_ioctl;
1510+ return 0;
1511+}
1512+
1513+static void __exit UNUSED pppoatm_exit(void)
1514+{
1515+ pppoatm_ioctl_hook = NULL;
1516+}
1517+
1518+module_init(pppoatm_init);
1519+module_exit(pppoatm_exit);
1520+
1521+MODULE_AUTHOR("Mitchell Blank Jr <mitch@sfgoth.com>");
1522+MODULE_DESCRIPTION("RFC2364 PPP over ATM/AAL5");
This page took 0.277618 seconds and 4 git commands to generate.