Blame view

net/atm/br2684.c 22.8 KB
09c434b8a   Thomas Gleixner   treewide: Add SPD...
1
  // SPDX-License-Identifier: GPL-2.0-only
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
  /*
fb64c735a   Chas Williams   [ATM]: [br2864] w...
3
4
5
6
7
8
   * Ethernet netdevice using ATM AAL5 as underlying carrier
   * (RFC1483 obsoleted by RFC2684) for Linux
   *
   * Authors: Marcell GAL, 2000, XDSL Ltd, Hungary
   *          Eric Kinzie, 2006-2007, US Naval Research Laboratory
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
9

99824461e   Joe Perches   net/atm: Convert ...
10
  #define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
11
  #include <linux/module.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
12
13
14
15
16
17
18
19
  #include <linux/init.h>
  #include <linux/kernel.h>
  #include <linux/list.h>
  #include <linux/netdevice.h>
  #include <linux/skbuff.h>
  #include <linux/etherdevice.h>
  #include <linux/rtnetlink.h>
  #include <linux/ip.h>
641d729eb   Joe Perches   net/atm/br2684.c:...
20
  #include <linux/uaccess.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
21
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
23
24
  #include <net/arp.h>
  #include <linux/atm.h>
  #include <linux/atmdev.h>
4fc268d24   Randy Dunlap   [PATCH] capable/c...
25
  #include <linux/capability.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26
27
28
29
30
  #include <linux/seq_file.h>
  
  #include <linux/atmbr2684.h>
  
  #include "common.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
31

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32
33
  static void skb_debug(const struct sk_buff *skb)
  {
641d729eb   Joe Perches   net/atm/br2684.c:...
34
  #ifdef SKB_DEBUG
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35
  #define NUM2PRINT 50
641d729eb   Joe Perches   net/atm/br2684.c:...
36
37
  	print_hex_dump(KERN_DEBUG, "br2684: skb: ", DUMP_OFFSET,
  		       16, 1, skb->data, min(NUM2PRINT, skb->len), true);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38
  #endif
641d729eb   Joe Perches   net/atm/br2684.c:...
39
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40

097b19a99   Eric Kinzie   [ATM]: [br2864] r...
41
42
43
44
45
46
47
48
49
50
  #define BR2684_ETHERTYPE_LEN	2
  #define BR2684_PAD_LEN		2
  
  #define LLC		0xaa, 0xaa, 0x03
  #define SNAP_BRIDGED	0x00, 0x80, 0xc2
  #define SNAP_ROUTED	0x00, 0x00, 0x00
  #define PID_ETHERNET	0x00, 0x07
  #define ETHERTYPE_IPV4	0x08, 0x00
  #define ETHERTYPE_IPV6	0x86, 0xdd
  #define PAD_BRIDGED	0x00, 0x00
61c33e012   Mitchell Blank Jr   atm: use const wh...
51
52
53
  static const unsigned char ethertype_ipv4[] = { ETHERTYPE_IPV4 };
  static const unsigned char ethertype_ipv6[] = { ETHERTYPE_IPV6 };
  static const unsigned char llc_oui_pid_pad[] =
fb64c735a   Chas Williams   [ATM]: [br2864] w...
54
  			{ LLC, SNAP_BRIDGED, PID_ETHERNET, PAD_BRIDGED };
befc93fe7   Pascal Hambourg   atm: br2684: Avoi...
55
  static const unsigned char pad[] = { PAD_BRIDGED };
61c33e012   Mitchell Blank Jr   atm: use const wh...
56
57
  static const unsigned char llc_oui_ipv4[] = { LLC, SNAP_ROUTED, ETHERTYPE_IPV4 };
  static const unsigned char llc_oui_ipv6[] = { LLC, SNAP_ROUTED, ETHERTYPE_IPV6 };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
58
59
  
  enum br2684_encaps {
fb64c735a   Chas Williams   [ATM]: [br2864] w...
60
  	e_vc = BR2684_ENCAPS_VC,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
61
62
63
64
  	e_llc = BR2684_ENCAPS_LLC,
  };
  
  struct br2684_vcc {
fb64c735a   Chas Williams   [ATM]: [br2864] w...
65
  	struct atm_vcc *atmvcc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
66
  	struct net_device *device;
fb64c735a   Chas Williams   [ATM]: [br2864] w...
67
  	/* keep old push, pop functions for chaining */
641d729eb   Joe Perches   net/atm/br2684.c:...
68
  	void (*old_push)(struct atm_vcc *vcc, struct sk_buff *skb);
137742cf9   Karl Hiramoto   atm/br2684: netif...
69
  	void (*old_pop)(struct atm_vcc *vcc, struct sk_buff *skb);
b89588531   David Woodhouse   br2684: don't sen...
70
  	void (*old_release_cb)(struct atm_vcc *vcc);
d71ffeb12   David Woodhouse   br2684: fix modul...
71
  	struct module *old_owner;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72
73
74
75
76
  	enum br2684_encaps encaps;
  	struct list_head brvccs;
  #ifdef CONFIG_ATM_BR2684_IPFILTER
  	struct br2684_filter filter;
  #endif /* CONFIG_ATM_BR2684_IPFILTER */
95c961747   Eric Dumazet   net: cleanup unsi...
77
  	unsigned int copies_needed, copies_failed;
ae088d663   David Woodhouse   atm: br2684: Fix ...
78
  	atomic_t qspace;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
79
80
81
82
83
84
  };
  
  struct br2684_dev {
  	struct net_device *net_dev;
  	struct list_head br2684_devs;
  	int number;
fb64c735a   Chas Williams   [ATM]: [br2864] w...
85
  	struct list_head brvccs;	/* one device <=> one vcc (before xmas) */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
86
  	int mac_was_set;
097b19a99   Eric Kinzie   [ATM]: [br2864] r...
87
  	enum br2684_payload payload;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
  };
  
  /*
   * This lock should be held for writing any time the list of devices or
   * their attached vcc's could be altered.  It should be held for reading
   * any time these are being queried.  Note that we sometimes need to
   * do read-locking under interrupt context, so write locking must block
   * the current CPU's interrupts
   */
  static DEFINE_RWLOCK(devs_lock);
  
  static LIST_HEAD(br2684_devs);
  
  static inline struct br2684_dev *BRPRIV(const struct net_device *net_dev)
  {
37d668004   Joe Perches   net/atm: Remove u...
103
  	return netdev_priv(net_dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
104
105
106
107
108
109
110
111
112
  }
  
  static inline struct net_device *list_entry_brdev(const struct list_head *le)
  {
  	return list_entry(le, struct br2684_dev, br2684_devs)->net_dev;
  }
  
  static inline struct br2684_vcc *BR2684_VCC(const struct atm_vcc *atmvcc)
  {
fb64c735a   Chas Williams   [ATM]: [br2864] w...
113
  	return (struct br2684_vcc *)(atmvcc->user_back);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
  }
  
  static inline struct br2684_vcc *list_entry_brvcc(const struct list_head *le)
  {
  	return list_entry(le, struct br2684_vcc, brvccs);
  }
  
  /* Caller should hold read_lock(&devs_lock) */
  static struct net_device *br2684_find_dev(const struct br2684_if_spec *s)
  {
  	struct list_head *lh;
  	struct net_device *net_dev;
  	switch (s->method) {
  	case BR2684_FIND_BYNUM:
  		list_for_each(lh, &br2684_devs) {
  			net_dev = list_entry_brdev(lh);
  			if (BRPRIV(net_dev)->number == s->spec.devnum)
  				return net_dev;
  		}
  		break;
  	case BR2684_FIND_BYIFNAME:
  		list_for_each(lh, &br2684_devs) {
  			net_dev = list_entry_brdev(lh);
  			if (!strncmp(net_dev->name, s->spec.ifname, IFNAMSIZ))
  				return net_dev;
  		}
  		break;
  	}
  	return NULL;
  }
005066122   Karl Hiramoto   atm/br2684: regis...
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
  static int atm_dev_event(struct notifier_block *this, unsigned long event,
  		 void *arg)
  {
  	struct atm_dev *atm_dev = arg;
  	struct list_head *lh;
  	struct net_device *net_dev;
  	struct br2684_vcc *brvcc;
  	struct atm_vcc *atm_vcc;
  	unsigned long flags;
  
  	pr_debug("event=%ld dev=%p
  ", event, atm_dev);
  
  	read_lock_irqsave(&devs_lock, flags);
  	list_for_each(lh, &br2684_devs) {
  		net_dev = list_entry_brdev(lh);
  
  		list_for_each_entry(brvcc, &BRPRIV(net_dev)->brvccs, brvccs) {
  			atm_vcc = brvcc->atmvcc;
  			if (atm_vcc && brvcc->atmvcc->dev == atm_dev) {
  
  				if (atm_vcc->dev->signal == ATM_PHY_SIG_LOST)
  					netif_carrier_off(net_dev);
  				else
  					netif_carrier_on(net_dev);
  
  			}
  		}
  	}
  	read_unlock_irqrestore(&devs_lock, flags);
  
  	return NOTIFY_DONE;
  }
  
  static struct notifier_block atm_dev_notifier = {
  	.notifier_call = atm_dev_event,
  };
137742cf9   Karl Hiramoto   atm/br2684: netif...
181
182
183
184
  /* chained vcc->pop function.  Check if we should wake the netif_queue */
  static void br2684_pop(struct atm_vcc *vcc, struct sk_buff *skb)
  {
  	struct br2684_vcc *brvcc = BR2684_VCC(vcc);
137742cf9   Karl Hiramoto   atm/br2684: netif...
185

ae088d663   David Woodhouse   atm: br2684: Fix ...
186
187
  	pr_debug("(vcc %p ; net_dev %p )
  ", vcc, brvcc->device);
137742cf9   Karl Hiramoto   atm/br2684: netif...
188
  	brvcc->old_pop(vcc, skb);
ae088d663   David Woodhouse   atm: br2684: Fix ...
189
190
191
  	/* If the queue space just went up from zero, wake */
  	if (atomic_inc_return(&brvcc->qspace) == 1)
  		netif_wake_queue(brvcc->device);
137742cf9   Karl Hiramoto   atm/br2684: netif...
192
  }
ae088d663   David Woodhouse   atm: br2684: Fix ...
193

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
194
195
196
197
198
  /*
   * Send a packet out a particular vcc.  Not to useful right now, but paves
   * the way for multiple vcc's per itf.  Returns true if we can send,
   * otherwise false
   */
410e9d8f9   Stephen Hemminger   atm: br2684 inter...
199
  static int br2684_xmit_vcc(struct sk_buff *skb, struct net_device *dev,
fb64c735a   Chas Williams   [ATM]: [br2864] w...
200
  			   struct br2684_vcc *brvcc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
201
  {
410e9d8f9   Stephen Hemminger   atm: br2684 inter...
202
  	struct br2684_dev *brdev = BRPRIV(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
203
  	struct atm_vcc *atmvcc;
9e667b298   Pascal Hambourg   atm: br2684: Make...
204
205
206
207
  	int minheadroom = (brvcc->encaps == e_llc) ?
  		((brdev->payload == p_bridged) ?
  			sizeof(llc_oui_pid_pad) : sizeof(llc_oui_ipv4)) :
  		((brdev->payload == p_bridged) ? BR2684_PAD_LEN : 0);
097b19a99   Eric Kinzie   [ATM]: [br2864] r...
208

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
209
210
211
212
213
214
215
216
217
218
  	if (skb_headroom(skb) < minheadroom) {
  		struct sk_buff *skb2 = skb_realloc_headroom(skb, minheadroom);
  		brvcc->copies_needed++;
  		dev_kfree_skb(skb);
  		if (skb2 == NULL) {
  			brvcc->copies_failed++;
  			return 0;
  		}
  		skb = skb2;
  	}
097b19a99   Eric Kinzie   [ATM]: [br2864] r...
219
220
221
222
  
  	if (brvcc->encaps == e_llc) {
  		if (brdev->payload == p_bridged) {
  			skb_push(skb, sizeof(llc_oui_pid_pad));
fb64c735a   Chas Williams   [ATM]: [br2864] w...
223
224
  			skb_copy_to_linear_data(skb, llc_oui_pid_pad,
  						sizeof(llc_oui_pid_pad));
097b19a99   Eric Kinzie   [ATM]: [br2864] r...
225
226
227
228
229
  		} else if (brdev->payload == p_routed) {
  			unsigned short prot = ntohs(skb->protocol);
  
  			skb_push(skb, sizeof(llc_oui_ipv4));
  			switch (prot) {
fb64c735a   Chas Williams   [ATM]: [br2864] w...
230
231
232
233
234
235
236
237
238
239
240
  			case ETH_P_IP:
  				skb_copy_to_linear_data(skb, llc_oui_ipv4,
  							sizeof(llc_oui_ipv4));
  				break;
  			case ETH_P_IPV6:
  				skb_copy_to_linear_data(skb, llc_oui_ipv6,
  							sizeof(llc_oui_ipv6));
  				break;
  			default:
  				dev_kfree_skb(skb);
  				return 0;
097b19a99   Eric Kinzie   [ATM]: [br2864] r...
241
242
  			}
  		}
7e903c2ae   Eric Kinzie   atm: [br2864] fix...
243
244
245
  	} else { /* e_vc */
  		if (brdev->payload == p_bridged) {
  			skb_push(skb, 2);
097b19a99   Eric Kinzie   [ATM]: [br2864] r...
246
  			memset(skb->data, 0, 2);
7e903c2ae   Eric Kinzie   atm: [br2864] fix...
247
  		}
097b19a99   Eric Kinzie   [ATM]: [br2864] r...
248
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
249
250
251
  	skb_debug(skb);
  
  	ATM_SKB(skb)->vcc = atmvcc = brvcc->atmvcc;
522400623   Stephen Hemminger   [ATM]: Replace DP...
252
253
  	pr_debug("atm_skb(%p)->vcc(%p)->dev(%p)
  ", skb, atmvcc, atmvcc->dev);
9bbe60a67   David Woodhouse   atm: Preserve val...
254
  	atm_account_tx(atmvcc, skb);
410e9d8f9   Stephen Hemminger   atm: br2684 inter...
255
256
  	dev->stats.tx_packets++;
  	dev->stats.tx_bytes += skb->len;
137742cf9   Karl Hiramoto   atm/br2684: netif...
257

ae088d663   David Woodhouse   atm: br2684: Fix ...
258
259
  	if (atomic_dec_return(&brvcc->qspace) < 1) {
  		/* No more please! */
137742cf9   Karl Hiramoto   atm/br2684: netif...
260
  		netif_stop_queue(brvcc->device);
ae088d663   David Woodhouse   atm: br2684: Fix ...
261
262
263
  		/* We might have raced with br2684_pop() */
  		if (unlikely(atomic_read(&brvcc->qspace) > 0))
  			netif_wake_queue(brvcc->device);
137742cf9   Karl Hiramoto   atm/br2684: netif...
264
  	}
ae088d663   David Woodhouse   atm: br2684: Fix ...
265
266
267
268
  	/* If this fails immediately, the skb will be freed and br2684_pop()
  	   will wake the queue if appropriate. Just return an error so that
  	   the stats are updated correctly */
  	return !atmvcc->send(atmvcc, skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
269
  }
b89588531   David Woodhouse   br2684: don't sen...
270
271
272
273
274
275
276
277
278
279
  static void br2684_release_cb(struct atm_vcc *atmvcc)
  {
  	struct br2684_vcc *brvcc = BR2684_VCC(atmvcc);
  
  	if (atomic_read(&brvcc->qspace) > 0)
  		netif_wake_queue(brvcc->device);
  
  	if (brvcc->old_release_cb)
  		brvcc->old_release_cb(atmvcc);
  }
61c33e012   Mitchell Blank Jr   atm: use const wh...
280
281
  static inline struct br2684_vcc *pick_outgoing_vcc(const struct sk_buff *skb,
  						   const struct br2684_dev *brdev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
282
  {
fb64c735a   Chas Williams   [ATM]: [br2864] w...
283
  	return list_empty(&brdev->brvccs) ? NULL : list_entry_brvcc(brdev->brvccs.next);	/* 1 vcc/dev right now */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
284
  }
3c805a22a   Stephen Hemminger   convert ATM drive...
285
286
  static netdev_tx_t br2684_start_xmit(struct sk_buff *skb,
  				     struct net_device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
287
288
289
  {
  	struct br2684_dev *brdev = BRPRIV(dev);
  	struct br2684_vcc *brvcc;
b89588531   David Woodhouse   br2684: don't sen...
290
291
  	struct atm_vcc *atmvcc;
  	netdev_tx_t ret = NETDEV_TX_OK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
292

99824461e   Joe Perches   net/atm: Convert ...
293
294
  	pr_debug("skb_dst(skb)=%p
  ", skb_dst(skb));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
295
296
297
  	read_lock(&devs_lock);
  	brvcc = pick_outgoing_vcc(skb, brdev);
  	if (brvcc == NULL) {
522400623   Stephen Hemminger   [ATM]: Replace DP...
298
299
  		pr_debug("no vcc attached to dev %s
  ", dev->name);
410e9d8f9   Stephen Hemminger   atm: br2684 inter...
300
301
  		dev->stats.tx_errors++;
  		dev->stats.tx_carrier_errors++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
302
303
  		/* netif_stop_queue(dev); */
  		dev_kfree_skb(skb);
b89588531   David Woodhouse   br2684: don't sen...
304
  		goto out_devs;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
305
  	}
b89588531   David Woodhouse   br2684: don't sen...
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
  	atmvcc = brvcc->atmvcc;
  
  	bh_lock_sock(sk_atm(atmvcc));
  
  	if (test_bit(ATM_VF_RELEASED, &atmvcc->flags) ||
  	    test_bit(ATM_VF_CLOSE, &atmvcc->flags) ||
  	    !test_bit(ATM_VF_READY, &atmvcc->flags)) {
  		dev->stats.tx_dropped++;
  		dev_kfree_skb(skb);
  		goto out;
  	}
  
  	if (sock_owned_by_user(sk_atm(atmvcc))) {
  		netif_stop_queue(brvcc->device);
  		ret = NETDEV_TX_BUSY;
  		goto out;
  	}
410e9d8f9   Stephen Hemminger   atm: br2684 inter...
323
  	if (!br2684_xmit_vcc(skb, dev, brvcc)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
324
325
326
  		/*
  		 * We should probably use netif_*_queue() here, but that
  		 * involves added complication.  We need to walk before
fb64c735a   Chas Williams   [ATM]: [br2864] w...
327
328
329
  		 * we can run.
  		 *
  		 * Don't free here! this pointer might be no longer valid!
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
330
  		 */
410e9d8f9   Stephen Hemminger   atm: br2684 inter...
331
332
  		dev->stats.tx_errors++;
  		dev->stats.tx_fifo_errors++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
333
  	}
b89588531   David Woodhouse   br2684: don't sen...
334
335
336
   out:
  	bh_unlock_sock(sk_atm(atmvcc));
   out_devs:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
337
  	read_unlock(&devs_lock);
b89588531   David Woodhouse   br2684: don't sen...
338
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
339
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
340
341
342
343
  /*
   * We remember when the MAC gets set, so we don't override it later with
   * the ESI of the ATM card of the first VC
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
344
345
  static int br2684_mac_addr(struct net_device *dev, void *p)
  {
0ba25ff4c   Stephen Hemminger   br2684: convert t...
346
  	int err = eth_mac_addr(dev, p);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
347
348
349
350
351
352
353
  	if (!err)
  		BRPRIV(dev)->mac_was_set = 1;
  	return err;
  }
  
  #ifdef CONFIG_ATM_BR2684_IPFILTER
  /* this IOCTL is experimental. */
fb64c735a   Chas Williams   [ATM]: [br2864] w...
354
  static int br2684_setfilt(struct atm_vcc *atmvcc, void __user * arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
355
356
357
358
359
360
361
362
363
  {
  	struct br2684_vcc *brvcc;
  	struct br2684_filter_set fs;
  
  	if (copy_from_user(&fs, arg, sizeof fs))
  		return -EFAULT;
  	if (fs.ifspec.method != BR2684_FIND_BYNOTHING) {
  		/*
  		 * This is really a per-vcc thing, but we can also search
fb64c735a   Chas Williams   [ATM]: [br2864] w...
364
  		 * by device.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
365
366
367
368
  		 */
  		struct br2684_dev *brdev;
  		read_lock(&devs_lock);
  		brdev = BRPRIV(br2684_find_dev(&fs.ifspec));
641d729eb   Joe Perches   net/atm/br2684.c:...
369
370
  		if (brdev == NULL || list_empty(&brdev->brvccs) ||
  		    brdev->brvccs.next != brdev->brvccs.prev)	/* >1 VCC */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
371
372
373
374
375
376
377
378
379
380
381
382
383
384
  			brvcc = NULL;
  		else
  			brvcc = list_entry_brvcc(brdev->brvccs.next);
  		read_unlock(&devs_lock);
  		if (brvcc == NULL)
  			return -ESRCH;
  	} else
  		brvcc = BR2684_VCC(atmvcc);
  	memcpy(&brvcc->filter, &fs.filter, sizeof(brvcc->filter));
  	return 0;
  }
  
  /* Returns 1 if packet should be dropped */
  static inline int
30d492da7   Al Viro   [ATM]: Annotations.
385
  packet_fails_filter(__be16 type, struct br2684_vcc *brvcc, struct sk_buff *skb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
386
387
  {
  	if (brvcc->filter.netmask == 0)
fb64c735a   Chas Williams   [ATM]: [br2864] w...
388
  		return 0;	/* no filter in place */
acde4855b   YOSHIFUJI Hideaki   [NET] ATM: Use ht...
389
  	if (type == htons(ETH_P_IP) &&
fb64c735a   Chas Williams   [ATM]: [br2864] w...
390
  	    (((struct iphdr *)(skb->data))->daddr & brvcc->filter.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
391
392
  	     netmask) == brvcc->filter.prefix)
  		return 0;
acde4855b   YOSHIFUJI Hideaki   [NET] ATM: Use ht...
393
  	if (type == htons(ETH_P_ARP))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
394
  		return 0;
fb64c735a   Chas Williams   [ATM]: [br2864] w...
395
396
397
  	/*
  	 * TODO: we should probably filter ARPs too.. don't want to have
  	 * them returning values that don't make sense, or is that ok?
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
398
399
400
401
402
403
404
  	 */
  	return 1;		/* drop */
  }
  #endif /* CONFIG_ATM_BR2684_IPFILTER */
  
  static void br2684_close_vcc(struct br2684_vcc *brvcc)
  {
522400623   Stephen Hemminger   [ATM]: Replace DP...
405
406
  	pr_debug("removing VCC %p from dev %p
  ", brvcc, brvcc->device);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
407
408
409
410
  	write_lock_irq(&devs_lock);
  	list_del(&brvcc->brvccs);
  	write_unlock_irq(&devs_lock);
  	brvcc->atmvcc->user_back = NULL;	/* what about vcc->recvq ??? */
b89588531   David Woodhouse   br2684: don't sen...
411
  	brvcc->atmvcc->release_cb = brvcc->old_release_cb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
412
  	brvcc->old_push(brvcc->atmvcc, NULL);	/* pass on the bad news */
d71ffeb12   David Woodhouse   br2684: fix modul...
413
  	module_put(brvcc->old_owner);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
414
  	kfree(brvcc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
415
416
417
418
419
420
421
422
  }
  
  /* when AAL5 PDU comes in: */
  static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb)
  {
  	struct br2684_vcc *brvcc = BR2684_VCC(atmvcc);
  	struct net_device *net_dev = brvcc->device;
  	struct br2684_dev *brdev = BRPRIV(net_dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
423

99824461e   Joe Perches   net/atm: Convert ...
424
425
  	pr_debug("
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
426
427
428
429
430
  
  	if (unlikely(skb == NULL)) {
  		/* skb==NULL means VCC is being destroyed */
  		br2684_close_vcc(brvcc);
  		if (list_empty(&brdev->brvccs)) {
1e0ba0060   Pavel Emelyanov   atm: Bad locking ...
431
  			write_lock_irq(&devs_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
432
  			list_del(&brdev->br2684_devs);
1e0ba0060   Pavel Emelyanov   atm: Bad locking ...
433
  			write_unlock_irq(&devs_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
434
  			unregister_netdev(net_dev);
5f6b1ea41   David S. Miller   Revert "atm: Do n...
435
  			free_netdev(net_dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
436
437
438
439
440
441
  		}
  		return;
  	}
  
  	skb_debug(skb);
  	atm_return(atmvcc, skb->truesize);
522400623   Stephen Hemminger   [ATM]: Replace DP...
442
443
  	pr_debug("skb from brdev %p
  ", brdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
444
  	if (brvcc->encaps == e_llc) {
097b19a99   Eric Kinzie   [ATM]: [br2864] r...
445
446
447
448
449
  
  		if (skb->len > 7 && skb->data[7] == 0x01)
  			__skb_trim(skb, skb->len - 4);
  
  		/* accept packets that have "ipv[46]" in the snap header */
641d729eb   Joe Perches   net/atm/br2684.c:...
450
451
452
453
454
  		if ((skb->len >= (sizeof(llc_oui_ipv4))) &&
  		    (memcmp(skb->data, llc_oui_ipv4,
  			    sizeof(llc_oui_ipv4) - BR2684_ETHERTYPE_LEN) == 0)) {
  			if (memcmp(skb->data + 6, ethertype_ipv6,
  				   sizeof(ethertype_ipv6)) == 0)
606780404   Arnaldo Carvalho de Melo   net: Use hton[sl]...
455
  				skb->protocol = htons(ETH_P_IPV6);
641d729eb   Joe Perches   net/atm/br2684.c:...
456
457
  			else if (memcmp(skb->data + 6, ethertype_ipv4,
  					sizeof(ethertype_ipv4)) == 0)
606780404   Arnaldo Carvalho de Melo   net: Use hton[sl]...
458
  				skb->protocol = htons(ETH_P_IP);
7e903c2ae   Eric Kinzie   atm: [br2864] fix...
459
460
  			else
  				goto error;
097b19a99   Eric Kinzie   [ATM]: [br2864] r...
461
462
463
  			skb_pull(skb, sizeof(llc_oui_ipv4));
  			skb_reset_network_header(skb);
  			skb->pkt_type = PACKET_HOST;
641d729eb   Joe Perches   net/atm/br2684.c:...
464
465
466
467
468
  		/*
  		 * Let us waste some time for checking the encapsulation.
  		 * Note, that only 7 char is checked so frames with a valid FCS
  		 * are also accepted (but FCS is not checked of course).
  		 */
097b19a99   Eric Kinzie   [ATM]: [br2864] r...
469
  		} else if ((skb->len >= sizeof(llc_oui_pid_pad)) &&
fb64c735a   Chas Williams   [ATM]: [br2864] w...
470
  			   (memcmp(skb->data, llc_oui_pid_pad, 7) == 0)) {
097b19a99   Eric Kinzie   [ATM]: [br2864] r...
471
472
  			skb_pull(skb, sizeof(llc_oui_pid_pad));
  			skb->protocol = eth_type_trans(skb, net_dev);
7e903c2ae   Eric Kinzie   atm: [br2864] fix...
473
474
  		} else
  			goto error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
475

7e903c2ae   Eric Kinzie   atm: [br2864] fix...
476
477
478
479
480
481
482
  	} else { /* e_vc */
  		if (brdev->payload == p_routed) {
  			struct iphdr *iph;
  
  			skb_reset_network_header(skb);
  			iph = ip_hdr(skb);
  			if (iph->version == 4)
606780404   Arnaldo Carvalho de Melo   net: Use hton[sl]...
483
  				skb->protocol = htons(ETH_P_IP);
7e903c2ae   Eric Kinzie   atm: [br2864] fix...
484
  			else if (iph->version == 6)
606780404   Arnaldo Carvalho de Melo   net: Use hton[sl]...
485
  				skb->protocol = htons(ETH_P_IPV6);
7e903c2ae   Eric Kinzie   atm: [br2864] fix...
486
487
488
489
490
  			else
  				goto error;
  			skb->pkt_type = PACKET_HOST;
  		} else { /* p_bridged */
  			/* first 2 chars should be 0 */
befc93fe7   Pascal Hambourg   atm: br2684: Avoi...
491
  			if (memcmp(skb->data, pad, BR2684_PAD_LEN) != 0)
7e903c2ae   Eric Kinzie   atm: [br2864] fix...
492
493
494
  				goto error;
  			skb_pull(skb, BR2684_PAD_LEN);
  			skb->protocol = eth_type_trans(skb, net_dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
495
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
496
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
497
  #ifdef CONFIG_ATM_BR2684_IPFILTER
7e903c2ae   Eric Kinzie   atm: [br2864] fix...
498
499
  	if (unlikely(packet_fails_filter(skb->protocol, brvcc, skb)))
  		goto dropped;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
500
501
502
  #endif /* CONFIG_ATM_BR2684_IPFILTER */
  	skb->dev = net_dev;
  	ATM_SKB(skb)->vcc = atmvcc;	/* needed ? */
522400623   Stephen Hemminger   [ATM]: Replace DP...
503
504
  	pr_debug("received packet's protocol: %x
  ", ntohs(skb->protocol));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
505
  	skb_debug(skb);
7e903c2ae   Eric Kinzie   atm: [br2864] fix...
506
507
508
  	/* sigh, interface is down? */
  	if (unlikely(!(net_dev->flags & IFF_UP)))
  		goto dropped;
410e9d8f9   Stephen Hemminger   atm: br2684 inter...
509
510
  	net_dev->stats.rx_packets++;
  	net_dev->stats.rx_bytes += skb->len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
511
512
  	memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data));
  	netif_rx(skb);
7e903c2ae   Eric Kinzie   atm: [br2864] fix...
513
514
515
  	return;
  
  dropped:
410e9d8f9   Stephen Hemminger   atm: br2684 inter...
516
  	net_dev->stats.rx_dropped++;
7e903c2ae   Eric Kinzie   atm: [br2864] fix...
517
518
  	goto free_skb;
  error:
410e9d8f9   Stephen Hemminger   atm: br2684 inter...
519
  	net_dev->stats.rx_errors++;
7e903c2ae   Eric Kinzie   atm: [br2864] fix...
520
521
  free_skb:
  	dev_kfree_skb(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
522
  }
fb64c735a   Chas Williams   [ATM]: [br2864] w...
523
524
525
526
527
  /*
   * Assign a vcc to a dev
   * Note: we do not have explicit unassign, but look at _push()
   */
  static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
528
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
529
  	struct br2684_vcc *brvcc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
530
531
532
  	struct br2684_dev *brdev;
  	struct net_device *net_dev;
  	struct atm_backend_br2684 be;
4e55f5785   Jorge Boncompte [DTI2]   atm: Introduce vc...
533
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
534
535
536
  
  	if (copy_from_user(&be, arg, sizeof be))
  		return -EFAULT;
0da974f4f   Panagiotis Issaris   [NET]: Conversion...
537
  	brvcc = kzalloc(sizeof(struct br2684_vcc), GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
538
539
  	if (!brvcc)
  		return -ENOMEM;
ae088d663   David Woodhouse   atm: br2684: Fix ...
540
541
542
543
544
545
546
  	/*
  	 * Allow two packets in the ATM queue. One actually being sent, and one
  	 * for the ATM 'TX done' handler to send. It shouldn't take long to get
  	 * the next one from the netdev queue, when we need it. More than that
  	 * would be bufferbloat.
  	 */
  	atomic_set(&brvcc->qspace, 2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
547
548
549
  	write_lock_irq(&devs_lock);
  	net_dev = br2684_find_dev(&be.ifspec);
  	if (net_dev == NULL) {
25985edce   Lucas De Marchi   Fix common misspe...
550
551
  		pr_err("tried to attach to non-existent device
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
552
553
554
555
556
557
558
559
560
561
562
563
564
  		err = -ENXIO;
  		goto error;
  	}
  	brdev = BRPRIV(net_dev);
  	if (atmvcc->push == NULL) {
  		err = -EBADFD;
  		goto error;
  	}
  	if (!list_empty(&brdev->brvccs)) {
  		/* Only 1 VCC/dev right now */
  		err = -EEXIST;
  		goto error;
  	}
641d729eb   Joe Perches   net/atm/br2684.c:...
565
566
567
568
569
570
  	if (be.fcs_in != BR2684_FCSIN_NO ||
  	    be.fcs_out != BR2684_FCSOUT_NO ||
  	    be.fcs_auto || be.has_vpiid || be.send_padding ||
  	    (be.encaps != BR2684_ENCAPS_VC &&
  	     be.encaps != BR2684_ENCAPS_LLC) ||
  	    be.min_size != 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
571
572
573
  		err = -EINVAL;
  		goto error;
  	}
99824461e   Joe Perches   net/atm: Convert ...
574
575
  	pr_debug("vcc=%p, encaps=%d, brvcc=%p
  ", atmvcc, be.encaps, brvcc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
576
577
578
579
580
581
582
583
584
585
586
587
  	if (list_empty(&brdev->brvccs) && !brdev->mac_was_set) {
  		unsigned char *esi = atmvcc->dev->esi;
  		if (esi[0] | esi[1] | esi[2] | esi[3] | esi[4] | esi[5])
  			memcpy(net_dev->dev_addr, esi, net_dev->addr_len);
  		else
  			net_dev->dev_addr[2] = 1;
  	}
  	list_add(&brvcc->brvccs, &brdev->brvccs);
  	write_unlock_irq(&devs_lock);
  	brvcc->device = net_dev;
  	brvcc->atmvcc = atmvcc;
  	atmvcc->user_back = brvcc;
fb64c735a   Chas Williams   [ATM]: [br2864] w...
588
  	brvcc->encaps = (enum br2684_encaps)be.encaps;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
589
  	brvcc->old_push = atmvcc->push;
137742cf9   Karl Hiramoto   atm/br2684: netif...
590
  	brvcc->old_pop = atmvcc->pop;
b89588531   David Woodhouse   br2684: don't sen...
591
  	brvcc->old_release_cb = atmvcc->release_cb;
d71ffeb12   David Woodhouse   br2684: fix modul...
592
  	brvcc->old_owner = atmvcc->owner;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
593
594
  	barrier();
  	atmvcc->push = br2684_push;
137742cf9   Karl Hiramoto   atm/br2684: netif...
595
  	atmvcc->pop = br2684_pop;
b89588531   David Woodhouse   br2684: don't sen...
596
  	atmvcc->release_cb = br2684_release_cb;
d71ffeb12   David Woodhouse   br2684: fix modul...
597
  	atmvcc->owner = THIS_MODULE;
c40a27f48   David S. Miller   [ATM]: Kill ipcom...
598

005066122   Karl Hiramoto   atm/br2684: regis...
599
600
601
602
603
  	/* initialize netdev carrier state */
  	if (atmvcc->dev->signal == ATM_PHY_SIG_LOST)
  		netif_carrier_off(net_dev);
  	else
  		netif_carrier_on(net_dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
604
  	__module_get(THIS_MODULE);
4e55f5785   Jorge Boncompte [DTI2]   atm: Introduce vc...
605
606
607
608
  
  	/* re-process everything received between connection setup and
  	   backend setup */
  	vcc_process_recv_queue(atmvcc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
609
  	return 0;
641d729eb   Joe Perches   net/atm/br2684.c:...
610
611
  
  error:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
612
613
614
615
  	write_unlock_irq(&devs_lock);
  	kfree(brvcc);
  	return err;
  }
0ba25ff4c   Stephen Hemminger   br2684: convert t...
616
617
618
  static const struct net_device_ops br2684_netdev_ops = {
  	.ndo_start_xmit 	= br2684_start_xmit,
  	.ndo_set_mac_address	= br2684_mac_addr,
0ba25ff4c   Stephen Hemminger   br2684: convert t...
619
620
  	.ndo_validate_addr	= eth_validate_addr,
  };
2e302ebfe   chas williams - CONTRACTOR   atm: [br2684] all...
621
622
623
  static const struct net_device_ops br2684_netdev_ops_routed = {
  	.ndo_start_xmit 	= br2684_start_xmit,
  	.ndo_set_mac_address	= br2684_mac_addr,
2e302ebfe   chas williams - CONTRACTOR   atm: [br2684] all...
624
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
625
626
627
628
629
  static void br2684_setup(struct net_device *netdev)
  {
  	struct br2684_dev *brdev = BRPRIV(netdev);
  
  	ether_setup(netdev);
9e667b298   Pascal Hambourg   atm: br2684: Make...
630
  	netdev->hard_header_len += sizeof(llc_oui_pid_pad); /* worst case */
902e5ea15   Rabin Vincent   Subject: [PATCH] ...
631
  	brdev->net_dev = netdev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
632

0ba25ff4c   Stephen Hemminger   br2684: convert t...
633
  	netdev->netdev_ops = &br2684_netdev_ops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
634
635
636
  
  	INIT_LIST_HEAD(&brdev->brvccs);
  }
097b19a99   Eric Kinzie   [ATM]: [br2864] r...
637
638
639
  static void br2684_setup_routed(struct net_device *netdev)
  {
  	struct br2684_dev *brdev = BRPRIV(netdev);
097b19a99   Eric Kinzie   [ATM]: [br2864] r...
640

2e302ebfe   chas williams - CONTRACTOR   atm: [br2684] all...
641
  	brdev->net_dev = netdev;
9e667b298   Pascal Hambourg   atm: br2684: Make...
642
  	netdev->hard_header_len = sizeof(llc_oui_ipv4); /* worst case */
2e302ebfe   chas williams - CONTRACTOR   atm: [br2684] all...
643
  	netdev->netdev_ops = &br2684_netdev_ops_routed;
097b19a99   Eric Kinzie   [ATM]: [br2864] r...
644
  	netdev->addr_len = 0;
8b1efc0f8   Jarod Wilson   net: remove MTU l...
645
646
647
  	netdev->mtu = ETH_DATA_LEN;
  	netdev->min_mtu = 0;
  	netdev->max_mtu = ETH_MAX_MTU;
097b19a99   Eric Kinzie   [ATM]: [br2864] r...
648
649
650
651
652
  	netdev->type = ARPHRD_PPP;
  	netdev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
  	netdev->tx_queue_len = 100;
  	INIT_LIST_HEAD(&brdev->brvccs);
  }
641d729eb   Joe Perches   net/atm/br2684.c:...
653
  static int br2684_create(void __user *arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
654
655
656
657
658
  {
  	int err;
  	struct net_device *netdev;
  	struct br2684_dev *brdev;
  	struct atm_newif_br2684 ni;
097b19a99   Eric Kinzie   [ATM]: [br2864] r...
659
  	enum br2684_payload payload;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
660

99824461e   Joe Perches   net/atm: Convert ...
661
662
  	pr_debug("
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
663

641d729eb   Joe Perches   net/atm/br2684.c:...
664
  	if (copy_from_user(&ni, arg, sizeof ni))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
665
  		return -EFAULT;
097b19a99   Eric Kinzie   [ATM]: [br2864] r...
666
667
668
669
670
  
  	if (ni.media & BR2684_FLAG_ROUTED)
  		payload = p_routed;
  	else
  		payload = p_bridged;
fb64c735a   Chas Williams   [ATM]: [br2864] w...
671
  	ni.media &= 0xffff;	/* strip flags */
097b19a99   Eric Kinzie   [ATM]: [br2864] r...
672

641d729eb   Joe Perches   net/atm/br2684.c:...
673
  	if (ni.media != BR2684_MEDIA_ETHERNET || ni.mtu != 1500)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
674
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
675
676
677
  
  	netdev = alloc_netdev(sizeof(struct br2684_dev),
  			      ni.ifname[0] ? ni.ifname : "nas%d",
c835a6773   Tom Gundersen   net: set name_ass...
678
679
  			      NET_NAME_UNKNOWN,
  			      (payload == p_routed) ? br2684_setup_routed : br2684_setup);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
680
681
682
683
  	if (!netdev)
  		return -ENOMEM;
  
  	brdev = BRPRIV(netdev);
522400623   Stephen Hemminger   [ATM]: Replace DP...
684
685
  	pr_debug("registered netdev %s
  ", netdev->name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
686
687
688
  	/* open, stop, do_ioctl ? */
  	err = register_netdev(netdev);
  	if (err < 0) {
99824461e   Joe Perches   net/atm: Convert ...
689
690
  		pr_err("register_netdev failed
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
691
692
693
694
695
  		free_netdev(netdev);
  		return err;
  	}
  
  	write_lock_irq(&devs_lock);
005066122   Karl Hiramoto   atm/br2684: regis...
696

097b19a99   Eric Kinzie   [ATM]: [br2864] r...
697
  	brdev->payload = payload;
005066122   Karl Hiramoto   atm/br2684: regis...
698
699
700
  
  	if (list_empty(&br2684_devs)) {
  		/* 1st br2684 device */
005066122   Karl Hiramoto   atm/br2684: regis...
701
702
703
  		brdev->number = 1;
  	} else
  		brdev->number = BRPRIV(list_entry_brdev(br2684_devs.prev))->number + 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
704
705
706
707
708
709
710
711
712
713
  	list_add_tail(&brdev->br2684_devs, &br2684_devs);
  	write_unlock_irq(&devs_lock);
  	return 0;
  }
  
  /*
   * This handles ioctls actually performed on our vcc - we must return
   * -ENOIOCTLCMD for any unrecognized ioctl
   */
  static int br2684_ioctl(struct socket *sock, unsigned int cmd,
fb64c735a   Chas Williams   [ATM]: [br2864] w...
714
  			unsigned long arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
715
716
717
  {
  	struct atm_vcc *atmvcc = ATM_SD(sock);
  	void __user *argp = (void __user *)arg;
fb64c735a   Chas Williams   [ATM]: [br2864] w...
718
  	atm_backend_t b;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
719
720
  
  	int err;
fb64c735a   Chas Williams   [ATM]: [br2864] w...
721
  	switch (cmd) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
722
  	case ATM_SETBACKEND:
fb64c735a   Chas Williams   [ATM]: [br2864] w...
723
  	case ATM_NEWBACKENDIF:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
724
725
726
727
728
729
730
  		err = get_user(b, (atm_backend_t __user *) argp);
  		if (err)
  			return -EFAULT;
  		if (b != ATM_BACKEND_BR2684)
  			return -ENOIOCTLCMD;
  		if (!capable(CAP_NET_ADMIN))
  			return -EPERM;
9eba25268   Krzysztof Mazur   br2684: allow ass...
731
732
733
  		if (cmd == ATM_SETBACKEND) {
  			if (sock->state != SS_CONNECTED)
  				return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
734
  			return br2684_regvcc(atmvcc, argp);
9eba25268   Krzysztof Mazur   br2684: allow ass...
735
  		} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
736
  			return br2684_create(argp);
9eba25268   Krzysztof Mazur   br2684: allow ass...
737
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
738
739
740
741
742
743
744
  #ifdef CONFIG_ATM_BR2684_IPFILTER
  	case BR2684_SETFILT:
  		if (atmvcc->push != br2684_push)
  			return -ENOIOCTLCMD;
  		if (!capable(CAP_NET_ADMIN))
  			return -EPERM;
  		err = br2684_setfilt(atmvcc, argp);
fb64c735a   Chas Williams   [ATM]: [br2864] w...
745

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
746
747
748
749
750
751
752
  		return err;
  #endif /* CONFIG_ATM_BR2684_IPFILTER */
  	}
  	return -ENOIOCTLCMD;
  }
  
  static struct atm_ioctl br2684_ioctl_ops = {
fb64c735a   Chas Williams   [ATM]: [br2864] w...
753
754
  	.owner = THIS_MODULE,
  	.ioctl = br2684_ioctl,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
755
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
756
  #ifdef CONFIG_PROC_FS
fb64c735a   Chas Williams   [ATM]: [br2864] w...
757
  static void *br2684_seq_start(struct seq_file *seq, loff_t * pos)
5c17d5f11   Eric Dumazet   [ATM]: Suppress s...
758
  	__acquires(devs_lock)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
759
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
760
  	read_lock(&devs_lock);
9af97186f   Pavel Emelianov   [ATM] br2684: Use...
761
  	return seq_list_start(&br2684_devs, *pos);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
762
  }
fb64c735a   Chas Williams   [ATM]: [br2864] w...
763
  static void *br2684_seq_next(struct seq_file *seq, void *v, loff_t * pos)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
764
  {
9af97186f   Pavel Emelianov   [ATM] br2684: Use...
765
  	return seq_list_next(v, &br2684_devs, pos);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
766
767
768
  }
  
  static void br2684_seq_stop(struct seq_file *seq, void *v)
5c17d5f11   Eric Dumazet   [ATM]: Suppress s...
769
  	__releases(devs_lock)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
770
771
772
773
774
775
  {
  	read_unlock(&devs_lock);
  }
  
  static int br2684_seq_show(struct seq_file *seq, void *v)
  {
9af97186f   Pavel Emelianov   [ATM] br2684: Use...
776
  	const struct br2684_dev *brdev = list_entry(v, struct br2684_dev,
fb64c735a   Chas Williams   [ATM]: [br2864] w...
777
  						    br2684_devs);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
778
779
  	const struct net_device *net_dev = brdev->net_dev;
  	const struct br2684_vcc *brvcc;
e174961ca   Johannes Berg   net: convert prin...
780
781
  	seq_printf(seq, "dev %.16s: num=%d, mac=%pM (%s)
  ",
0795af572   Joe Perches   [NET]: Introduce ...
782
783
  		   net_dev->name,
  		   brdev->number,
e174961ca   Johannes Berg   net: convert prin...
784
  		   net_dev->dev_addr,
0795af572   Joe Perches   [NET]: Introduce ...
785
  		   brdev->mac_was_set ? "set" : "auto");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
786
787
  
  	list_for_each_entry(brvcc, &brdev->brvccs, brvccs) {
097b19a99   Eric Kinzie   [ATM]: [br2864] r...
788
  		seq_printf(seq, "  vcc %d.%d.%d: encaps=%s payload=%s"
fb64c735a   Chas Williams   [ATM]: [br2864] w...
789
790
791
792
793
794
795
  			   ", failed copies %u/%u"
  			   "
  ", brvcc->atmvcc->dev->number,
  			   brvcc->atmvcc->vpi, brvcc->atmvcc->vci,
  			   (brvcc->encaps == e_llc) ? "LLC" : "VC",
  			   (brdev->payload == p_bridged) ? "bridged" : "routed",
  			   brvcc->copies_failed, brvcc->copies_needed);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
796
  #ifdef CONFIG_ATM_BR2684_IPFILTER
fb64c735a   Chas Williams   [ATM]: [br2864] w...
797
  		if (brvcc->filter.netmask != 0)
85b1d8bbf   Joe Perches   br2684: Remove un...
798
799
800
801
  			seq_printf(seq, "    filter=%pI4/%pI4
  ",
  				   &brvcc->filter.prefix,
  				   &brvcc->filter.netmask);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
802
803
804
805
  #endif /* CONFIG_ATM_BR2684_IPFILTER */
  	}
  	return 0;
  }
56b3d975b   Philippe De Muyter   [NET]: Make all i...
806
  static const struct seq_operations br2684_seq_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
807
  	.start = br2684_seq_start,
fb64c735a   Chas Williams   [ATM]: [br2864] w...
808
809
810
  	.next = br2684_seq_next,
  	.stop = br2684_seq_stop,
  	.show = br2684_seq_show,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
811
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
812
  extern struct proc_dir_entry *atm_proc_root;	/* from proc.c */
fb64c735a   Chas Williams   [ATM]: [br2864] w...
813
  #endif /* CONFIG_PROC_FS */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
814
815
816
817
818
  
  static int __init br2684_init(void)
  {
  #ifdef CONFIG_PROC_FS
  	struct proc_dir_entry *p;
fddda2b7b   Christoph Hellwig   proc: introduce p...
819
  	p = proc_create_seq("br2684", 0, atm_proc_root, &br2684_seq_ops);
16e297b35   Wang Chen   [ATM]: Use proc_c...
820
  	if (p == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
821
  		return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
822
823
  #endif
  	register_atm_ioctl(&br2684_ioctl_ops);
a3d6713fb   Karl Hiramoto   br2684: fix sched...
824
  	register_atmdevice_notifier(&atm_dev_notifier);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
825
826
827
828
829
830
831
832
833
834
835
836
837
  	return 0;
  }
  
  static void __exit br2684_exit(void)
  {
  	struct net_device *net_dev;
  	struct br2684_dev *brdev;
  	struct br2684_vcc *brvcc;
  	deregister_atm_ioctl(&br2684_ioctl_ops);
  
  #ifdef CONFIG_PROC_FS
  	remove_proc_entry("br2684", atm_proc_root);
  #endif
005066122   Karl Hiramoto   atm/br2684: regis...
838

a3d6713fb   Karl Hiramoto   br2684: fix sched...
839
  	unregister_atmdevice_notifier(&atm_dev_notifier);
005066122   Karl Hiramoto   atm/br2684: regis...
840

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
841
842
843
844
845
846
847
848
849
850
  	while (!list_empty(&br2684_devs)) {
  		net_dev = list_entry_brdev(br2684_devs.next);
  		brdev = BRPRIV(net_dev);
  		while (!list_empty(&brdev->brvccs)) {
  			brvcc = list_entry_brvcc(brdev->brvccs.next);
  			br2684_close_vcc(brvcc);
  		}
  
  		list_del(&brdev->br2684_devs);
  		unregister_netdev(net_dev);
5f6b1ea41   David S. Miller   Revert "atm: Do n...
851
  		free_netdev(net_dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
852
853
854
855
856
857
858
859
860
  	}
  }
  
  module_init(br2684_init);
  module_exit(br2684_exit);
  
  MODULE_AUTHOR("Marcell GAL");
  MODULE_DESCRIPTION("RFC2684 bridged protocols over ATM/AAL5");
  MODULE_LICENSE("GPL");