clip.c 22.0 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4
/* net/atm/clip.c - RFC1577 Classical IP over ATM */

/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */

5 6
#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__

L
Linus Torvalds 已提交
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/kernel.h> /* for UINT_MAX */
#include <linux/module.h>
#include <linux/init.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/wait.h>
#include <linux/timer.h>
#include <linux/if_arp.h> /* for some manifest constants */
#include <linux/notifier.h>
#include <linux/atm.h>
#include <linux/atmdev.h>
#include <linux/atmclip.h>
#include <linux/atmarp.h>
22
#include <linux/capability.h>
L
Linus Torvalds 已提交
23 24 25 26 27
#include <linux/ip.h> /* for net/route.h */
#include <linux/in.h> /* for struct sockaddr_in */
#include <linux/if.h> /* for IFF_UP */
#include <linux/inetdevice.h>
#include <linux/bitops.h>
R
Randy Dunlap 已提交
28
#include <linux/poison.h>
L
Linus Torvalds 已提交
29 30 31 32
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/rcupdate.h>
#include <linux/jhash.h>
33
#include <linux/slab.h>
L
Linus Torvalds 已提交
34 35
#include <net/route.h> /* for struct rtable and routing */
#include <net/icmp.h> /* icmp_send */
36
#include <net/arp.h>
37 38
#include <linux/param.h> /* for HZ */
#include <linux/uaccess.h>
L
Linus Torvalds 已提交
39 40
#include <asm/byteorder.h> /* for htons etc. */
#include <asm/system.h> /* save/restore_flags */
A
Arun Sharma 已提交
41
#include <linux/atomic.h>
L
Linus Torvalds 已提交
42 43 44 45 46 47 48 49 50 51

#include "common.h"
#include "resources.h"
#include <net/atmclip.h>

static struct net_device *clip_devs;
static struct atm_vcc *atmarpd;
static struct neigh_table clip_tbl;
static struct timer_list idle_timer;

A
Al Viro 已提交
52
static int to_atmarpd(enum atmarp_ctrl_type type, int itf, __be32 ip)
L
Linus Torvalds 已提交
53 54 55 56 57
{
	struct sock *sk;
	struct atmarp_ctrl *ctrl;
	struct sk_buff *skb;

58
	pr_debug("(%d)\n", type);
59 60
	if (!atmarpd)
		return -EUNATCH;
61
	skb = alloc_skb(sizeof(struct atmarp_ctrl), GFP_ATOMIC);
62 63
	if (!skb)
		return -ENOMEM;
64
	ctrl = (struct atmarp_ctrl *)skb_put(skb, sizeof(struct atmarp_ctrl));
L
Linus Torvalds 已提交
65 66 67
	ctrl->type = type;
	ctrl->itf_num = itf;
	ctrl->ip = ip;
68
	atm_force_charge(atmarpd, skb->truesize);
L
Linus Torvalds 已提交
69 70 71 72 73 74 75

	sk = sk_atm(atmarpd);
	skb_queue_tail(&sk->sk_receive_queue, skb);
	sk->sk_data_ready(sk, skb->len);
	return 0;
}

76
static void link_vcc(struct clip_vcc *clip_vcc, struct atmarp_entry *entry)
L
Linus Torvalds 已提交
77
{
78
	pr_debug("%p to entry %p (neigh %p)\n", clip_vcc, entry, entry->neigh);
L
Linus Torvalds 已提交
79
	clip_vcc->entry = entry;
80
	clip_vcc->xoff = 0;	/* @@@ may overrun buffer by one packet */
L
Linus Torvalds 已提交
81 82 83 84 85 86 87 88 89 90 91
	clip_vcc->next = entry->vccs;
	entry->vccs = clip_vcc;
	entry->neigh->used = jiffies;
}

static void unlink_clip_vcc(struct clip_vcc *clip_vcc)
{
	struct atmarp_entry *entry = clip_vcc->entry;
	struct clip_vcc **walk;

	if (!entry) {
92
		pr_crit("!clip_vcc->entry (clip_vcc %p)\n", clip_vcc);
L
Linus Torvalds 已提交
93 94
		return;
	}
H
Herbert Xu 已提交
95
	netif_tx_lock_bh(entry->neigh->dev);	/* block clip_start_xmit() */
L
Linus Torvalds 已提交
96 97 98 99 100
	entry->neigh->used = jiffies;
	for (walk = &entry->vccs; *walk; walk = &(*walk)->next)
		if (*walk == clip_vcc) {
			int error;

101
			*walk = clip_vcc->next;	/* atomic */
L
Linus Torvalds 已提交
102 103 104 105 106
			clip_vcc->entry = NULL;
			if (clip_vcc->xoff)
				netif_wake_queue(entry->neigh->dev);
			if (entry->vccs)
				goto out;
107 108
			entry->expires = jiffies - 1;
			/* force resolution or expiration */
L
Linus Torvalds 已提交
109 110 111
			error = neigh_update(entry->neigh, NULL, NUD_NONE,
					     NEIGH_UPDATE_F_ADMIN);
			if (error)
112
				pr_crit("neigh_update failed with %d\n", error);
L
Linus Torvalds 已提交
113 114
			goto out;
		}
115
	pr_crit("ATMARP: failed (entry %p, vcc 0x%p)\n", entry, clip_vcc);
116
out:
H
Herbert Xu 已提交
117
	netif_tx_unlock_bh(entry->neigh->dev);
L
Linus Torvalds 已提交
118 119 120 121 122
}

/* The neighbour entry n->lock is held. */
static int neigh_check_cb(struct neighbour *n)
{
123
	struct atmarp_entry *entry = neighbour_priv(n);
L
Linus Torvalds 已提交
124 125 126 127 128 129
	struct clip_vcc *cv;

	for (cv = entry->vccs; cv; cv = cv->next) {
		unsigned long exp = cv->last_use + cv->idle_timeout;

		if (cv->idle_timeout && time_after(jiffies, exp)) {
130
			pr_debug("releasing vcc %p->%p of entry %p\n",
131
				 cv, cv->vcc, entry);
L
Linus Torvalds 已提交
132 133 134 135 136 137 138 139 140 141
			vcc_release_async(cv->vcc, -ETIMEDOUT);
		}
	}

	if (entry->vccs || time_before(jiffies, entry->expires))
		return 0;

	if (atomic_read(&n->refcnt) > 1) {
		struct sk_buff *skb;

142
		pr_debug("destruction postponed with ref %d\n",
143
			 atomic_read(&n->refcnt));
L
Linus Torvalds 已提交
144

145
		while ((skb = skb_dequeue(&n->arp_queue)) != NULL)
L
Linus Torvalds 已提交
146 147 148 149 150
			dev_kfree_skb(skb);

		return 0;
	}

151
	pr_debug("expired neigh %p\n", n);
L
Linus Torvalds 已提交
152 153 154 155 156 157 158
	return 1;
}

static void idle_timer_check(unsigned long dummy)
{
	write_lock(&clip_tbl.lock);
	__neigh_for_each_release(&clip_tbl, neigh_check_cb);
159
	mod_timer(&idle_timer, jiffies + CLIP_CHECK_INTERVAL * HZ);
L
Linus Torvalds 已提交
160 161 162 163 164 165 166
	write_unlock(&clip_tbl.lock);
}

static int clip_arp_rcv(struct sk_buff *skb)
{
	struct atm_vcc *vcc;

167
	pr_debug("\n");
L
Linus Torvalds 已提交
168
	vcc = ATM_SKB(skb)->vcc;
169
	if (!vcc || !atm_charge(vcc, skb->truesize)) {
L
Linus Torvalds 已提交
170 171 172
		dev_kfree_skb_any(skb);
		return 0;
	}
173 174
	pr_debug("pushing to %p\n", vcc);
	pr_debug("using %p\n", CLIP_VCC(vcc)->old_push);
175
	CLIP_VCC(vcc)->old_push(vcc, skb);
L
Linus Torvalds 已提交
176 177 178 179 180 181 182 183 184
	return 0;
}

static const unsigned char llc_oui[] = {
	0xaa,	/* DSAP: non-ISO */
	0xaa,	/* SSAP: non-ISO */
	0x03,	/* Ctrl: Unnumbered Information Command PDU */
	0x00,	/* OUI: EtherType */
	0x00,
185 186
	0x00
};
L
Linus Torvalds 已提交
187

188
static void clip_push(struct atm_vcc *vcc, struct sk_buff *skb)
L
Linus Torvalds 已提交
189 190 191
{
	struct clip_vcc *clip_vcc = CLIP_VCC(vcc);

192
	pr_debug("\n");
193 194 195 196 197 198 199

	if (!clip_devs) {
		atm_return(vcc, skb->truesize);
		kfree_skb(skb);
		return;
	}

L
Linus Torvalds 已提交
200
	if (!skb) {
201
		pr_debug("removing VCC %p\n", clip_vcc);
202 203 204
		if (clip_vcc->entry)
			unlink_clip_vcc(clip_vcc);
		clip_vcc->old_push(vcc, NULL);	/* pass on the bad news */
L
Linus Torvalds 已提交
205 206 207
		kfree(clip_vcc);
		return;
	}
208
	atm_return(vcc, skb->truesize);
L
Linus Torvalds 已提交
209
	skb->dev = clip_vcc->entry ? clip_vcc->entry->neigh->dev : clip_devs;
210
	/* clip_vcc->entry == NULL if we don't have an IP address yet */
L
Linus Torvalds 已提交
211 212 213 214 215
	if (!skb->dev) {
		dev_kfree_skb_any(skb);
		return;
	}
	ATM_SKB(skb)->vcc = vcc;
216
	skb_reset_mac_header(skb);
217 218 219
	if (!clip_vcc->encap ||
	    skb->len < RFC1483LLC_LEN ||
	    memcmp(skb->data, llc_oui, sizeof(llc_oui)))
220
		skb->protocol = htons(ETH_P_IP);
L
Linus Torvalds 已提交
221
	else {
222
		skb->protocol = ((__be16 *)skb->data)[3];
223
		skb_pull(skb, RFC1483LLC_LEN);
L
Linus Torvalds 已提交
224
		if (skb->protocol == htons(ETH_P_ARP)) {
225 226
			skb->dev->stats.rx_packets++;
			skb->dev->stats.rx_bytes += skb->len;
L
Linus Torvalds 已提交
227 228 229 230 231
			clip_arp_rcv(skb);
			return;
		}
	}
	clip_vcc->last_use = jiffies;
232 233
	skb->dev->stats.rx_packets++;
	skb->dev->stats.rx_bytes += skb->len;
L
Linus Torvalds 已提交
234 235 236 237 238 239 240 241 242
	memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data));
	netif_rx(skb);
}

/*
 * Note: these spinlocks _must_not_ block on non-SMP. The only goal is that
 * clip_pop is atomic with respect to the critical section in clip_start_xmit.
 */

243
static void clip_pop(struct atm_vcc *vcc, struct sk_buff *skb)
L
Linus Torvalds 已提交
244 245 246 247 248 249
{
	struct clip_vcc *clip_vcc = CLIP_VCC(vcc);
	struct net_device *dev = skb->dev;
	int old;
	unsigned long flags;

250
	pr_debug("(vcc %p)\n", vcc);
251
	clip_vcc->old_pop(vcc, skb);
L
Linus Torvalds 已提交
252
	/* skb->dev == NULL in outbound ARP packets */
253 254 255 256 257 258 259
	if (!dev)
		return;
	spin_lock_irqsave(&PRIV(dev)->xoff_lock, flags);
	if (atm_may_send(vcc, 0)) {
		old = xchg(&clip_vcc->xoff, 0);
		if (old)
			netif_wake_queue(dev);
L
Linus Torvalds 已提交
260
	}
261
	spin_unlock_irqrestore(&PRIV(dev)->xoff_lock, flags);
L
Linus Torvalds 已提交
262 263
}

264
static void clip_neigh_solicit(struct neighbour *neigh, struct sk_buff *skb)
L
Linus Torvalds 已提交
265
{
266 267
	__be32 *ip = (__be32 *) neigh->primary_key;

268
	pr_debug("(neigh %p, skb %p)\n", neigh, skb);
269
	to_atmarpd(act_need, PRIV(neigh->dev)->number, *ip);
L
Linus Torvalds 已提交
270 271
}

272
static void clip_neigh_error(struct neighbour *neigh, struct sk_buff *skb)
L
Linus Torvalds 已提交
273 274
{
#ifndef CONFIG_ATM_CLIP_NO_ICMP
275
	icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0);
L
Linus Torvalds 已提交
276 277 278 279
#endif
	kfree_skb(skb);
}

S
Stephen Hemminger 已提交
280
static const struct neigh_ops clip_neigh_ops = {
L
Linus Torvalds 已提交
281 282 283
	.family =		AF_INET,
	.solicit =		clip_neigh_solicit,
	.error_report =		clip_neigh_error,
284 285
	.output =		neigh_direct_output,
	.connected_output =	neigh_direct_output,
L
Linus Torvalds 已提交
286 287 288 289
};

static int clip_constructor(struct neighbour *neigh)
{
290
	struct atmarp_entry *entry = neighbour_priv(neigh);
L
Linus Torvalds 已提交
291

292
	if (neigh->tbl->family != AF_INET)
293
		return -EINVAL;
L
Linus Torvalds 已提交
294

295
	if (neigh->type != RTN_UNICAST)
L
Linus Torvalds 已提交
296 297
		return -EINVAL;

298
	neigh->nud_state = NUD_NONE;
L
Linus Torvalds 已提交
299
	neigh->ops = &clip_neigh_ops;
300
	neigh->output = neigh->ops->output;
L
Linus Torvalds 已提交
301 302
	entry->neigh = neigh;
	entry->vccs = NULL;
303
	entry->expires = jiffies - 1;
304

L
Linus Torvalds 已提交
305 306 307 308 309 310 311 312 313 314 315 316
	return 0;
}

/* @@@ copy bh locking from arp.c -- need to bh-enable atm code before */

/*
 * We play with the resolve flag: 0 and 1 have the usual meaning, but -1 means
 * to allocate the neighbour entry but not to ask atmarpd for resolution. Also,
 * don't increment the usage count. This is used to create entries in
 * clip_setentry.
 */

317
static int clip_encap(struct atm_vcc *vcc, int mode)
L
Linus Torvalds 已提交
318 319 320 321 322
{
	CLIP_VCC(vcc)->encap = mode;
	return 0;
}

323 324
static netdev_tx_t clip_start_xmit(struct sk_buff *skb,
				   struct net_device *dev)
L
Linus Torvalds 已提交
325 326
{
	struct clip_priv *clip_priv = PRIV(dev);
327
	struct dst_entry *dst = skb_dst(skb);
L
Linus Torvalds 已提交
328
	struct atmarp_entry *entry;
329
	struct neighbour *n;
L
Linus Torvalds 已提交
330 331 332 333
	struct atm_vcc *vcc;
	int old;
	unsigned long flags;

334
	pr_debug("(skb %p)\n", skb);
335
	if (!dst) {
336
		pr_err("skb_dst(skb) == NULL\n");
L
Linus Torvalds 已提交
337
		dev_kfree_skb(skb);
338
		dev->stats.tx_dropped++;
339
		return NETDEV_TX_OK;
L
Linus Torvalds 已提交
340
	}
341
	n = dst_get_neighbour_noref(dst);
342
	if (!n) {
343
		pr_err("NO NEIGHBOUR !\n");
L
Linus Torvalds 已提交
344
		dev_kfree_skb(skb);
345
		dev->stats.tx_dropped++;
346
		return NETDEV_TX_OK;
L
Linus Torvalds 已提交
347
	}
348
	entry = neighbour_priv(n);
L
Linus Torvalds 已提交
349 350 351
	if (!entry->vccs) {
		if (time_after(jiffies, entry->expires)) {
			/* should be resolved */
352
			entry->expires = jiffies + ATMARP_RETRY_DELAY * HZ;
353
			to_atmarpd(act_need, PRIV(dev)->number, *((__be32 *)n->primary_key));
L
Linus Torvalds 已提交
354 355
		}
		if (entry->neigh->arp_queue.qlen < ATMARP_MAX_UNRES_PACKETS)
356
			skb_queue_tail(&entry->neigh->arp_queue, skb);
L
Linus Torvalds 已提交
357 358
		else {
			dev_kfree_skb(skb);
359
			dev->stats.tx_dropped++;
L
Linus Torvalds 已提交
360
		}
361
		return NETDEV_TX_OK;
L
Linus Torvalds 已提交
362
	}
363
	pr_debug("neigh %p, vccs %p\n", entry, entry->vccs);
L
Linus Torvalds 已提交
364
	ATM_SKB(skb)->vcc = vcc = entry->vccs->vcc;
365
	pr_debug("using neighbour %p, vcc %p\n", n, vcc);
L
Linus Torvalds 已提交
366 367 368
	if (entry->vccs->encap) {
		void *here;

369 370
		here = skb_push(skb, RFC1483LLC_LEN);
		memcpy(here, llc_oui, sizeof(llc_oui));
A
Al Viro 已提交
371
		((__be16 *) here)[3] = skb->protocol;
L
Linus Torvalds 已提交
372 373 374 375
	}
	atomic_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
	ATM_SKB(skb)->atm_options = vcc->atm_options;
	entry->vccs->last_use = jiffies;
376
	pr_debug("atm_skb(%p)->vcc(%p)->dev(%p)\n", skb, vcc, vcc->dev);
377
	old = xchg(&entry->vccs->xoff, 1);	/* assume XOFF ... */
L
Linus Torvalds 已提交
378
	if (old) {
379
		pr_warning("XOFF->XOFF transition\n");
380
		return NETDEV_TX_OK;
L
Linus Torvalds 已提交
381
	}
382 383
	dev->stats.tx_packets++;
	dev->stats.tx_bytes += skb->len;
384
	vcc->send(vcc, skb);
385
	if (atm_may_send(vcc, 0)) {
L
Linus Torvalds 已提交
386
		entry->vccs->xoff = 0;
387
		return NETDEV_TX_OK;
L
Linus Torvalds 已提交
388
	}
389 390
	spin_lock_irqsave(&clip_priv->xoff_lock, flags);
	netif_stop_queue(dev);	/* XOFF -> throttle immediately */
L
Linus Torvalds 已提交
391 392 393
	barrier();
	if (!entry->vccs->xoff)
		netif_start_queue(dev);
394 395 396 397 398
	/* Oh, we just raced with clip_pop. netif_start_queue should be
	   good enough, because nothing should really be asleep because
	   of the brief netif_stop_queue. If this isn't true or if it
	   changes, use netif_wake_queue instead. */
	spin_unlock_irqrestore(&clip_priv->xoff_lock, flags);
399
	return NETDEV_TX_OK;
L
Linus Torvalds 已提交
400 401
}

402
static int clip_mkip(struct atm_vcc *vcc, int timeout)
L
Linus Torvalds 已提交
403 404 405
{
	struct clip_vcc *clip_vcc;

406 407 408 409 410
	if (!vcc->push)
		return -EBADFD;
	clip_vcc = kmalloc(sizeof(struct clip_vcc), GFP_KERNEL);
	if (!clip_vcc)
		return -ENOMEM;
411
	pr_debug("%p vcc %p\n", clip_vcc, vcc);
L
Linus Torvalds 已提交
412 413 414 415 416 417 418
	clip_vcc->vcc = vcc;
	vcc->user_back = clip_vcc;
	set_bit(ATM_VF_IS_CLIP, &vcc->flags);
	clip_vcc->entry = NULL;
	clip_vcc->xoff = 0;
	clip_vcc->encap = 1;
	clip_vcc->last_use = jiffies;
419
	clip_vcc->idle_timeout = timeout * HZ;
L
Linus Torvalds 已提交
420 421 422 423
	clip_vcc->old_push = vcc->push;
	clip_vcc->old_pop = vcc->pop;
	vcc->push = clip_push;
	vcc->pop = clip_pop;
D
David S. Miller 已提交
424

L
Linus Torvalds 已提交
425
	/* re-process everything received between connection setup and MKIP */
426
	vcc_process_recv_queue(vcc);
427

L
Linus Torvalds 已提交
428 429 430
	return 0;
}

A
Al Viro 已提交
431
static int clip_setentry(struct atm_vcc *vcc, __be32 ip)
L
Linus Torvalds 已提交
432 433 434 435 436 437 438 439
{
	struct neighbour *neigh;
	struct atmarp_entry *entry;
	int error;
	struct clip_vcc *clip_vcc;
	struct rtable *rt;

	if (vcc->push != clip_push) {
440
		pr_warning("non-CLIP VCC\n");
L
Linus Torvalds 已提交
441 442 443 444 445
		return -EBADF;
	}
	clip_vcc = CLIP_VCC(vcc);
	if (!ip) {
		if (!clip_vcc->entry) {
446
			pr_err("hiding hidden ATMARP entry\n");
L
Linus Torvalds 已提交
447 448
			return 0;
		}
449
		pr_debug("remove\n");
L
Linus Torvalds 已提交
450 451 452
		unlink_clip_vcc(clip_vcc);
		return 0;
	}
453
	rt = ip_route_output(&init_net, ip, 0, 1, 0);
454 455
	if (IS_ERR(rt))
		return PTR_ERR(rt);
456
	neigh = __neigh_lookup(&arp_tbl, &ip, rt->dst.dev, 1);
L
Linus Torvalds 已提交
457 458 459
	ip_rt_put(rt);
	if (!neigh)
		return -ENOMEM;
460
	entry = neighbour_priv(neigh);
L
Linus Torvalds 已提交
461
	if (entry != clip_vcc->entry) {
462
		if (!clip_vcc->entry)
463
			pr_debug("add\n");
L
Linus Torvalds 已提交
464
		else {
465
			pr_debug("update\n");
L
Linus Torvalds 已提交
466 467
			unlink_clip_vcc(clip_vcc);
		}
468
		link_vcc(clip_vcc, entry);
L
Linus Torvalds 已提交
469
	}
470 471
	error = neigh_update(neigh, llc_oui, NUD_PERMANENT,
			     NEIGH_UPDATE_F_OVERRIDE | NEIGH_UPDATE_F_ADMIN);
L
Linus Torvalds 已提交
472 473 474 475
	neigh_release(neigh);
	return error;
}

476
static const struct net_device_ops clip_netdev_ops = {
477 478
	.ndo_start_xmit		= clip_start_xmit,
	.ndo_neigh_construct	= clip_constructor,
479 480
};

L
Linus Torvalds 已提交
481 482
static void clip_setup(struct net_device *dev)
{
483
	dev->netdev_ops = &clip_netdev_ops;
L
Linus Torvalds 已提交
484
	dev->type = ARPHRD_ATM;
485
	dev->neigh_priv_len = sizeof(struct atmarp_entry);
L
Linus Torvalds 已提交
486 487
	dev->hard_header_len = RFC1483LLC_LEN;
	dev->mtu = RFC1626_MTU;
488 489 490 491 492 493
	dev->tx_queue_len = 100;	/* "normal" queue (packets) */
	/* When using a "real" qdisc, the qdisc determines the queue */
	/* length. tx_queue_len is only used for the default case, */
	/* without any more elaborate queuing. 100 is a reasonable */
	/* compromise between decent burst-tolerance and protection */
	/* against memory hogs. */
494
	dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
L
Linus Torvalds 已提交
495 496 497 498 499 500 501 502 503 504
}

static int clip_create(int number)
{
	struct net_device *dev;
	struct clip_priv *clip_priv;
	int error;

	if (number != -1) {
		for (dev = clip_devs; dev; dev = PRIV(dev)->next)
505 506 507
			if (PRIV(dev)->number == number)
				return -EEXIST;
	} else {
L
Linus Torvalds 已提交
508 509 510
		number = 0;
		for (dev = clip_devs; dev; dev = PRIV(dev)->next)
			if (PRIV(dev)->number >= number)
511
				number = PRIV(dev)->number + 1;
L
Linus Torvalds 已提交
512 513 514 515 516
	}
	dev = alloc_netdev(sizeof(struct clip_priv), "", clip_setup);
	if (!dev)
		return -ENOMEM;
	clip_priv = PRIV(dev);
517
	sprintf(dev->name, "atm%d", number);
L
Linus Torvalds 已提交
518 519 520 521 522 523 524 525 526
	spin_lock_init(&clip_priv->xoff_lock);
	clip_priv->number = number;
	error = register_netdev(dev);
	if (error) {
		free_netdev(dev);
		return error;
	}
	clip_priv->next = clip_devs;
	clip_devs = dev;
527
	pr_debug("registered (net:%s)\n", dev->name);
L
Linus Torvalds 已提交
528 529 530
	return number;
}

531
static int clip_device_event(struct notifier_block *this, unsigned long event,
532
			     void *arg)
L
Linus Torvalds 已提交
533
{
534 535
	struct net_device *dev = arg;

536
	if (!net_eq(dev_net(dev), &init_net))
537 538
		return NOTIFY_DONE;

539
	if (event == NETDEV_UNREGISTER)
540 541
		return NOTIFY_DONE;

L
Linus Torvalds 已提交
542
	/* ignore non-CLIP devices */
543
	if (dev->type != ARPHRD_ATM || dev->netdev_ops != &clip_netdev_ops)
L
Linus Torvalds 已提交
544
		return NOTIFY_DONE;
545

L
Linus Torvalds 已提交
546
	switch (event) {
547
	case NETDEV_UP:
548
		pr_debug("NETDEV_UP\n");
549
		to_atmarpd(act_up, PRIV(dev)->number, 0);
550 551
		break;
	case NETDEV_GOING_DOWN:
552
		pr_debug("NETDEV_DOWN\n");
553
		to_atmarpd(act_down, PRIV(dev)->number, 0);
554 555 556
		break;
	case NETDEV_CHANGE:
	case NETDEV_CHANGEMTU:
557
		pr_debug("NETDEV_CHANGE*\n");
558
		to_atmarpd(act_change, PRIV(dev)->number, 0);
559
		break;
L
Linus Torvalds 已提交
560 561 562 563
	}
	return NOTIFY_DONE;
}

564 565
static int clip_inet_event(struct notifier_block *this, unsigned long event,
			   void *ifa)
L
Linus Torvalds 已提交
566 567 568
{
	struct in_device *in_dev;

569
	in_dev = ((struct in_ifaddr *)ifa)->ifa_dev;
L
Linus Torvalds 已提交
570 571 572 573
	/*
	 * Transitions are of the down-change-up type, so it's sufficient to
	 * handle the change on up.
	 */
574 575 576
	if (event != NETDEV_UP)
		return NOTIFY_DONE;
	return clip_device_event(this, NETDEV_CHANGE, in_dev->dev);
L
Linus Torvalds 已提交
577 578 579
}

static struct notifier_block clip_dev_notifier = {
580
	.notifier_call = clip_device_event,
L
Linus Torvalds 已提交
581 582 583 584 585
};



static struct notifier_block clip_inet_notifier = {
586
	.notifier_call = clip_inet_event,
L
Linus Torvalds 已提交
587 588 589 590 591 592
};



static void atmarpd_close(struct atm_vcc *vcc)
{
593
	pr_debug("\n");
594 595 596

	rtnl_lock();
	atmarpd = NULL;
L
Linus Torvalds 已提交
597
	skb_queue_purge(&sk_atm(vcc)->sk_receive_queue);
598 599
	rtnl_unlock();

600
	pr_debug("(done)\n");
L
Linus Torvalds 已提交
601 602 603 604 605 606 607 608 609 610 611 612
	module_put(THIS_MODULE);
}

static struct atmdev_ops atmarpd_dev_ops = {
	.close = atmarpd_close
};


static struct atm_dev atmarpd_dev = {
	.ops =			&atmarpd_dev_ops,
	.type =			"arpd",
	.number = 		999,
613
	.lock =			__SPIN_LOCK_UNLOCKED(atmarpd_dev.lock)
L
Linus Torvalds 已提交
614 615 616 617 618
};


static int atm_init_atmarp(struct atm_vcc *vcc)
{
619 620 621 622 623 624
	rtnl_lock();
	if (atmarpd) {
		rtnl_unlock();
		return -EADDRINUSE;
	}

625
	mod_timer(&idle_timer, jiffies + CLIP_CHECK_INTERVAL * HZ);
S
Stephen Hemminger 已提交
626

L
Linus Torvalds 已提交
627
	atmarpd = vcc;
628 629
	set_bit(ATM_VF_META, &vcc->flags);
	set_bit(ATM_VF_READY, &vcc->flags);
L
Linus Torvalds 已提交
630 631 632 633 634 635
	    /* allow replies and avoid getting closed if signaling dies */
	vcc->dev = &atmarpd_dev;
	vcc_insert_socket(sk_atm(vcc));
	vcc->push = NULL;
	vcc->pop = NULL; /* crash */
	vcc->push_oam = NULL; /* crash */
636
	rtnl_unlock();
L
Linus Torvalds 已提交
637 638 639 640 641 642 643 644 645
	return 0;
}

static int clip_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{
	struct atm_vcc *vcc = ATM_SD(sock);
	int err = 0;

	switch (cmd) {
646 647 648 649 650 651 652 653 654 655
	case SIOCMKCLIP:
	case ATMARPD_CTRL:
	case ATMARP_MKIP:
	case ATMARP_SETENTRY:
	case ATMARP_ENCAP:
		if (!capable(CAP_NET_ADMIN))
			return -EPERM;
		break;
	default:
		return -ENOIOCTLCMD;
L
Linus Torvalds 已提交
656 657 658
	}

	switch (cmd) {
659 660 661 662 663 664 665 666 667 668 669 670 671 672
	case SIOCMKCLIP:
		err = clip_create(arg);
		break;
	case ATMARPD_CTRL:
		err = atm_init_atmarp(vcc);
		if (!err) {
			sock->state = SS_CONNECTED;
			__module_get(THIS_MODULE);
		}
		break;
	case ATMARP_MKIP:
		err = clip_mkip(vcc, arg);
		break;
	case ATMARP_SETENTRY:
A
Al Viro 已提交
673
		err = clip_setentry(vcc, (__force __be32)arg);
674 675 676 677
		break;
	case ATMARP_ENCAP:
		err = clip_encap(vcc, arg);
		break;
L
Linus Torvalds 已提交
678 679 680 681 682
	}
	return err;
}

static struct atm_ioctl clip_ioctl_ops = {
683 684
	.owner = THIS_MODULE,
	.ioctl = clip_ioctl,
L
Linus Torvalds 已提交
685 686 687 688 689 690
};

#ifdef CONFIG_PROC_FS

static void svc_addr(struct seq_file *seq, struct sockaddr_atmsvc *addr)
{
691 692
	static int code[] = { 1, 2, 10, 6, 1, 0 };
	static int e164[] = { 1, 8, 4, 6, 1, 0 };
L
Linus Torvalds 已提交
693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710

	if (*addr->sas_addr.pub) {
		seq_printf(seq, "%s", addr->sas_addr.pub);
		if (*addr->sas_addr.prv)
			seq_putc(seq, '+');
	} else if (!*addr->sas_addr.prv) {
		seq_printf(seq, "%s", "(none)");
		return;
	}
	if (*addr->sas_addr.prv) {
		unsigned char *prv = addr->sas_addr.prv;
		int *fields;
		int i, j;

		fields = *prv == ATM_AFI_E164 ? e164 : code;
		for (i = 0; fields[i]; i++) {
			for (j = fields[i]; j; j--)
				seq_printf(seq, "%02X", *prv++);
711
			if (fields[i + 1])
L
Linus Torvalds 已提交
712 713 714 715 716 717 718 719
				seq_putc(seq, '.');
		}
	}
}

/* This means the neighbour entry has no attached VCC objects. */
#define SEQ_NO_VCC_TOKEN	((void *) 2)

720
static void atmarp_info(struct seq_file *seq, struct neighbour *n,
L
Linus Torvalds 已提交
721 722
			struct atmarp_entry *entry, struct clip_vcc *clip_vcc)
{
723
	struct net_device *dev = n->dev;
L
Linus Torvalds 已提交
724 725 726 727 728 729 730
	unsigned long exp;
	char buf[17];
	int svc, llc, off;

	svc = ((clip_vcc == SEQ_NO_VCC_TOKEN) ||
	       (sk_atm(clip_vcc->vcc)->sk_family == AF_ATMSVC));

731
	llc = ((clip_vcc == SEQ_NO_VCC_TOKEN) || clip_vcc->encap);
L
Linus Torvalds 已提交
732 733 734 735 736 737 738 739 740

	if (clip_vcc == SEQ_NO_VCC_TOKEN)
		exp = entry->neigh->used;
	else
		exp = clip_vcc->last_use;

	exp = (jiffies - exp) / HZ;

	seq_printf(seq, "%-6s%-4s%-4s%5ld ",
741
		   dev->name, svc ? "SVC" : "PVC", llc ? "LLC" : "NULL", exp);
L
Linus Torvalds 已提交
742

743
	off = scnprintf(buf, sizeof(buf) - 1, "%pI4", n->primary_key);
L
Linus Torvalds 已提交
744 745 746 747 748 749 750 751 752 753 754 755 756 757
	while (off < 16)
		buf[off++] = ' ';
	buf[off] = '\0';
	seq_printf(seq, "%s", buf);

	if (clip_vcc == SEQ_NO_VCC_TOKEN) {
		if (time_before(jiffies, entry->expires))
			seq_printf(seq, "(resolving)\n");
		else
			seq_printf(seq, "(expired, ref %d)\n",
				   atomic_read(&entry->neigh->refcnt));
	} else if (!svc) {
		seq_printf(seq, "%d.%d.%d\n",
			   clip_vcc->vcc->dev->number,
758
			   clip_vcc->vcc->vpi, clip_vcc->vcc->vci);
L
Linus Torvalds 已提交
759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790
	} else {
		svc_addr(seq, &clip_vcc->vcc->remote);
		seq_putc(seq, '\n');
	}
}

struct clip_seq_state {
	/* This member must be first. */
	struct neigh_seq_state ns;

	/* Local to clip specific iteration. */
	struct clip_vcc *vcc;
};

static struct clip_vcc *clip_seq_next_vcc(struct atmarp_entry *e,
					  struct clip_vcc *curr)
{
	if (!curr) {
		curr = e->vccs;
		if (!curr)
			return SEQ_NO_VCC_TOKEN;
		return curr;
	}
	if (curr == SEQ_NO_VCC_TOKEN)
		return NULL;

	curr = curr->next;

	return curr;
}

static void *clip_seq_vcc_walk(struct clip_seq_state *state,
791
			       struct atmarp_entry *e, loff_t * pos)
L
Linus Torvalds 已提交
792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807
{
	struct clip_vcc *vcc = state->vcc;

	vcc = clip_seq_next_vcc(e, vcc);
	if (vcc && pos != NULL) {
		while (*pos) {
			vcc = clip_seq_next_vcc(e, vcc);
			if (!vcc)
				break;
			--(*pos);
		}
	}
	state->vcc = vcc;

	return vcc;
}
808

L
Linus Torvalds 已提交
809
static void *clip_seq_sub_iter(struct neigh_seq_state *_state,
810
			       struct neighbour *n, loff_t * pos)
L
Linus Torvalds 已提交
811
{
812
	struct clip_seq_state *state = (struct clip_seq_state *)_state;
L
Linus Torvalds 已提交
813

814 815 816
	if (n->dev->type != ARPHRD_ATM)
		return NULL;

817
	return clip_seq_vcc_walk(state, neighbour_priv(n), pos);
L
Linus Torvalds 已提交
818 819
}

820
static void *clip_seq_start(struct seq_file *seq, loff_t * pos)
L
Linus Torvalds 已提交
821
{
822 823
	struct clip_seq_state *state = seq->private;
	state->ns.neigh_sub_iter = clip_seq_sub_iter;
824
	return neigh_seq_start(seq, pos, &arp_tbl, NEIGH_SEQ_NEIGH_ONLY);
L
Linus Torvalds 已提交
825 826 827 828
}

static int clip_seq_show(struct seq_file *seq, void *v)
{
829 830
	static char atm_arp_banner[] =
	    "IPitf TypeEncp Idle IP address      ATM address\n";
L
Linus Torvalds 已提交
831 832 833 834 835 836

	if (v == SEQ_START_TOKEN) {
		seq_puts(seq, atm_arp_banner);
	} else {
		struct clip_seq_state *state = seq->private;
		struct clip_vcc *vcc = state->vcc;
837
		struct neighbour *n = v;
L
Linus Torvalds 已提交
838

839
		atmarp_info(seq, n, neighbour_priv(n), vcc);
L
Linus Torvalds 已提交
840
	}
841
	return 0;
L
Linus Torvalds 已提交
842 843
}

844
static const struct seq_operations arp_seq_ops = {
L
Linus Torvalds 已提交
845 846 847 848 849 850 851 852
	.start	= clip_seq_start,
	.next	= neigh_seq_next,
	.stop	= neigh_seq_stop,
	.show	= clip_seq_show,
};

static int arp_seq_open(struct inode *inode, struct file *file)
{
853 854
	return seq_open_net(inode, file, &arp_seq_ops,
			    sizeof(struct clip_seq_state));
855 856
}

857
static const struct file_operations arp_seq_fops = {
L
Linus Torvalds 已提交
858 859 860
	.open		= arp_seq_open,
	.read		= seq_read,
	.llseek		= seq_lseek,
861
	.release	= seq_release_net,
L
Linus Torvalds 已提交
862 863 864 865
	.owner		= THIS_MODULE
};
#endif

866 867
static void atm_clip_exit_noproc(void);

L
Linus Torvalds 已提交
868 869 870
static int __init atm_clip_init(void)
{
	register_atm_ioctl(&clip_ioctl_ops);
871 872
	register_netdevice_notifier(&clip_dev_notifier);
	register_inetaddr_notifier(&clip_inet_notifier);
L
Linus Torvalds 已提交
873

S
Stephen Hemminger 已提交
874 875
	setup_timer(&idle_timer, idle_timer_check, 0);

876 877 878 879
#ifdef CONFIG_PROC_FS
	{
		struct proc_dir_entry *p;

880
		p = proc_create("arp", S_IRUGO, atm_proc_root, &arp_seq_fops);
881
		if (!p) {
882
			pr_err("Unable to initialize /proc/net/atm/arp\n");
883 884 885
			atm_clip_exit_noproc();
			return -ENOMEM;
		}
886 887
	}
#endif
L
Linus Torvalds 已提交
888 889 890 891

	return 0;
}

892
static void atm_clip_exit_noproc(void)
L
Linus Torvalds 已提交
893 894 895
{
	struct net_device *dev, *next;

896 897 898
	unregister_inetaddr_notifier(&clip_inet_notifier);
	unregister_netdevice_notifier(&clip_dev_notifier);

L
Linus Torvalds 已提交
899 900 901 902 903
	deregister_atm_ioctl(&clip_ioctl_ops);

	/* First, stop the idle timer, so it stops banging
	 * on the table.
	 */
S
Stephen Hemminger 已提交
904
	del_timer_sync(&idle_timer);
L
Linus Torvalds 已提交
905 906 907 908 909 910 911 912 913 914

	dev = clip_devs;
	while (dev) {
		next = PRIV(dev)->next;
		unregister_netdev(dev);
		free_netdev(dev);
		dev = next;
	}
}

915 916 917 918 919 920 921
static void __exit atm_clip_exit(void)
{
	remove_proc_entry("arp", atm_proc_root);

	atm_clip_exit_noproc();
}

L
Linus Torvalds 已提交
922 923
module_init(atm_clip_init);
module_exit(atm_clip_exit);
S
Stephen Hemminger 已提交
924 925
MODULE_AUTHOR("Werner Almesberger");
MODULE_DESCRIPTION("Classical/IP over ATM interface");
L
Linus Torvalds 已提交
926
MODULE_LICENSE("GPL");