OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [net/] [atm/] [clip.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/* net/atm/clip.c - RFC1577 Classical IP over ATM */
2
 
3
/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
4
 
5
#include <linux/string.h>
6
#include <linux/errno.h>
7
#include <linux/kernel.h> /* for UINT_MAX */
8
#include <linux/module.h>
9
#include <linux/init.h>
10
#include <linux/netdevice.h>
11
#include <linux/skbuff.h>
12
#include <linux/wait.h>
13
#include <linux/timer.h>
14
#include <linux/if_arp.h> /* for some manifest constants */
15
#include <linux/notifier.h>
16
#include <linux/atm.h>
17
#include <linux/atmdev.h>
18
#include <linux/atmclip.h>
19
#include <linux/atmarp.h>
20
#include <linux/capability.h>
21
#include <linux/ip.h> /* for net/route.h */
22
#include <linux/in.h> /* for struct sockaddr_in */
23
#include <linux/if.h> /* for IFF_UP */
24
#include <linux/inetdevice.h>
25
#include <linux/bitops.h>
26
#include <linux/poison.h>
27
#include <linux/proc_fs.h>
28
#include <linux/seq_file.h>
29
#include <linux/rcupdate.h>
30
#include <linux/jhash.h>
31
#include <net/route.h> /* for struct rtable and routing */
32
#include <net/icmp.h> /* icmp_send */
33
#include <asm/param.h> /* for HZ */
34
#include <asm/byteorder.h> /* for htons etc. */
35
#include <asm/system.h> /* save/restore_flags */
36
#include <asm/uaccess.h>
37
#include <asm/atomic.h>
38
 
39
#include "common.h"
40
#include "resources.h"
41
#include <net/atmclip.h>
42
 
43
static struct net_device *clip_devs;
44
static struct atm_vcc *atmarpd;
45
static struct neigh_table clip_tbl;
46
static struct timer_list idle_timer;
47
 
48
static int to_atmarpd(enum atmarp_ctrl_type type, int itf, __be32 ip)
49
{
50
        struct sock *sk;
51
        struct atmarp_ctrl *ctrl;
52
        struct sk_buff *skb;
53
 
54
        pr_debug("to_atmarpd(%d)\n", type);
55
        if (!atmarpd)
56
                return -EUNATCH;
57
        skb = alloc_skb(sizeof(struct atmarp_ctrl),GFP_ATOMIC);
58
        if (!skb)
59
                return -ENOMEM;
60
        ctrl = (struct atmarp_ctrl *) skb_put(skb,sizeof(struct atmarp_ctrl));
61
        ctrl->type = type;
62
        ctrl->itf_num = itf;
63
        ctrl->ip = ip;
64
        atm_force_charge(atmarpd, skb->truesize);
65
 
66
        sk = sk_atm(atmarpd);
67
        skb_queue_tail(&sk->sk_receive_queue, skb);
68
        sk->sk_data_ready(sk, skb->len);
69
        return 0;
70
}
71
 
72
static void link_vcc(struct clip_vcc *clip_vcc, struct atmarp_entry *entry)
73
{
74
        pr_debug("link_vcc %p to entry %p (neigh %p)\n", clip_vcc, entry,
75
                entry->neigh);
76
        clip_vcc->entry = entry;
77
        clip_vcc->xoff = 0;      /* @@@ may overrun buffer by one packet */
78
        clip_vcc->next = entry->vccs;
79
        entry->vccs = clip_vcc;
80
        entry->neigh->used = jiffies;
81
}
82
 
83
static void unlink_clip_vcc(struct clip_vcc *clip_vcc)
84
{
85
        struct atmarp_entry *entry = clip_vcc->entry;
86
        struct clip_vcc **walk;
87
 
88
        if (!entry) {
89
                printk(KERN_CRIT "!clip_vcc->entry (clip_vcc %p)\n", clip_vcc);
90
                return;
91
        }
92
        netif_tx_lock_bh(entry->neigh->dev);    /* block clip_start_xmit() */
93
        entry->neigh->used = jiffies;
94
        for (walk = &entry->vccs; *walk; walk = &(*walk)->next)
95
                if (*walk == clip_vcc) {
96
                        int error;
97
 
98
                        *walk = clip_vcc->next; /* atomic */
99
                        clip_vcc->entry = NULL;
100
                        if (clip_vcc->xoff)
101
                                netif_wake_queue(entry->neigh->dev);
102
                        if (entry->vccs)
103
                                goto out;
104
                        entry->expires = jiffies - 1;
105
                        /* force resolution or expiration */
106
                        error = neigh_update(entry->neigh, NULL, NUD_NONE,
107
                                             NEIGH_UPDATE_F_ADMIN);
108
                        if (error)
109
                                printk(KERN_CRIT "unlink_clip_vcc: "
110
                                       "neigh_update failed with %d\n", error);
111
                        goto out;
112
                }
113
        printk(KERN_CRIT "ATMARP: unlink_clip_vcc failed (entry %p, vcc "
114
               "0x%p)\n", entry, clip_vcc);
115
      out:
116
        netif_tx_unlock_bh(entry->neigh->dev);
117
}
118
 
119
/* The neighbour entry n->lock is held. */
120
static int neigh_check_cb(struct neighbour *n)
121
{
122
        struct atmarp_entry *entry = NEIGH2ENTRY(n);
123
        struct clip_vcc *cv;
124
 
125
        for (cv = entry->vccs; cv; cv = cv->next) {
126
                unsigned long exp = cv->last_use + cv->idle_timeout;
127
 
128
                if (cv->idle_timeout && time_after(jiffies, exp)) {
129
                        pr_debug("releasing vcc %p->%p of entry %p\n",
130
                                cv, cv->vcc, entry);
131
                        vcc_release_async(cv->vcc, -ETIMEDOUT);
132
                }
133
        }
134
 
135
        if (entry->vccs || time_before(jiffies, entry->expires))
136
                return 0;
137
 
138
        if (atomic_read(&n->refcnt) > 1) {
139
                struct sk_buff *skb;
140
 
141
                pr_debug("destruction postponed with ref %d\n",
142
                        atomic_read(&n->refcnt));
143
 
144
                while ((skb = skb_dequeue(&n->arp_queue)) != NULL)
145
                        dev_kfree_skb(skb);
146
 
147
                return 0;
148
        }
149
 
150
        pr_debug("expired neigh %p\n", n);
151
        return 1;
152
}
153
 
154
static void idle_timer_check(unsigned long dummy)
155
{
156
        write_lock(&clip_tbl.lock);
157
        __neigh_for_each_release(&clip_tbl, neigh_check_cb);
158
        mod_timer(&idle_timer, jiffies + CLIP_CHECK_INTERVAL * HZ);
159
        write_unlock(&clip_tbl.lock);
160
}
161
 
162
static int clip_arp_rcv(struct sk_buff *skb)
163
{
164
        struct atm_vcc *vcc;
165
 
166
        pr_debug("clip_arp_rcv\n");
167
        vcc = ATM_SKB(skb)->vcc;
168
        if (!vcc || !atm_charge(vcc, skb->truesize)) {
169
                dev_kfree_skb_any(skb);
170
                return 0;
171
        }
172
        pr_debug("pushing to %p\n", vcc);
173
        pr_debug("using %p\n", CLIP_VCC(vcc)->old_push);
174
        CLIP_VCC(vcc)->old_push(vcc, skb);
175
        return 0;
176
}
177
 
178
static const unsigned char llc_oui[] = {
179
        0xaa,   /* DSAP: non-ISO */
180
        0xaa,   /* SSAP: non-ISO */
181
        0x03,   /* Ctrl: Unnumbered Information Command PDU */
182
        0x00,   /* OUI: EtherType */
183
        0x00,
184
        0x00
185
};
186
 
187
static void clip_push(struct atm_vcc *vcc, struct sk_buff *skb)
188
{
189
        struct clip_vcc *clip_vcc = CLIP_VCC(vcc);
190
 
191
        pr_debug("clip push\n");
192
        if (!skb) {
193
                pr_debug("removing VCC %p\n", clip_vcc);
194
                if (clip_vcc->entry)
195
                        unlink_clip_vcc(clip_vcc);
196
                clip_vcc->old_push(vcc, NULL);  /* pass on the bad news */
197
                kfree(clip_vcc);
198
                return;
199
        }
200
        atm_return(vcc, skb->truesize);
201
        skb->dev = clip_vcc->entry ? clip_vcc->entry->neigh->dev : clip_devs;
202
        /* clip_vcc->entry == NULL if we don't have an IP address yet */
203
        if (!skb->dev) {
204
                dev_kfree_skb_any(skb);
205
                return;
206
        }
207
        ATM_SKB(skb)->vcc = vcc;
208
        skb_reset_mac_header(skb);
209
        if (!clip_vcc->encap
210
            || skb->len < RFC1483LLC_LEN
211
            || memcmp(skb->data, llc_oui, sizeof (llc_oui)))
212
                skb->protocol = htons(ETH_P_IP);
213
        else {
214
                skb->protocol = ((__be16 *) skb->data)[3];
215
                skb_pull(skb, RFC1483LLC_LEN);
216
                if (skb->protocol == htons(ETH_P_ARP)) {
217
                        PRIV(skb->dev)->stats.rx_packets++;
218
                        PRIV(skb->dev)->stats.rx_bytes += skb->len;
219
                        clip_arp_rcv(skb);
220
                        return;
221
                }
222
        }
223
        clip_vcc->last_use = jiffies;
224
        PRIV(skb->dev)->stats.rx_packets++;
225
        PRIV(skb->dev)->stats.rx_bytes += skb->len;
226
        memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data));
227
        netif_rx(skb);
228
}
229
 
230
/*
231
 * Note: these spinlocks _must_not_ block on non-SMP. The only goal is that
232
 * clip_pop is atomic with respect to the critical section in clip_start_xmit.
233
 */
234
 
235
static void clip_pop(struct atm_vcc *vcc, struct sk_buff *skb)
236
{
237
        struct clip_vcc *clip_vcc = CLIP_VCC(vcc);
238
        struct net_device *dev = skb->dev;
239
        int old;
240
        unsigned long flags;
241
 
242
        pr_debug("clip_pop(vcc %p)\n", vcc);
243
        clip_vcc->old_pop(vcc, skb);
244
        /* skb->dev == NULL in outbound ARP packets */
245
        if (!dev)
246
                return;
247
        spin_lock_irqsave(&PRIV(dev)->xoff_lock, flags);
248
        if (atm_may_send(vcc, 0)) {
249
                old = xchg(&clip_vcc->xoff, 0);
250
                if (old)
251
                        netif_wake_queue(dev);
252
        }
253
        spin_unlock_irqrestore(&PRIV(dev)->xoff_lock, flags);
254
}
255
 
256
static void clip_neigh_solicit(struct neighbour *neigh, struct sk_buff *skb)
257
{
258
        pr_debug("clip_neigh_solicit (neigh %p, skb %p)\n", neigh, skb);
259
        to_atmarpd(act_need, PRIV(neigh->dev)->number, NEIGH2ENTRY(neigh)->ip);
260
}
261
 
262
static void clip_neigh_error(struct neighbour *neigh, struct sk_buff *skb)
263
{
264
#ifndef CONFIG_ATM_CLIP_NO_ICMP
265
        icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0);
266
#endif
267
        kfree_skb(skb);
268
}
269
 
270
static struct neigh_ops clip_neigh_ops = {
271
        .family =               AF_INET,
272
        .solicit =              clip_neigh_solicit,
273
        .error_report =         clip_neigh_error,
274
        .output =               dev_queue_xmit,
275
        .connected_output =     dev_queue_xmit,
276
        .hh_output =            dev_queue_xmit,
277
        .queue_xmit =           dev_queue_xmit,
278
};
279
 
280
static int clip_constructor(struct neighbour *neigh)
281
{
282
        struct atmarp_entry *entry = NEIGH2ENTRY(neigh);
283
        struct net_device *dev = neigh->dev;
284
        struct in_device *in_dev;
285
        struct neigh_parms *parms;
286
 
287
        pr_debug("clip_constructor (neigh %p, entry %p)\n", neigh, entry);
288
        neigh->type = inet_addr_type(entry->ip);
289
        if (neigh->type != RTN_UNICAST)
290
                return -EINVAL;
291
 
292
        rcu_read_lock();
293
        in_dev = __in_dev_get_rcu(dev);
294
        if (!in_dev) {
295
                rcu_read_unlock();
296
                return -EINVAL;
297
        }
298
 
299
        parms = in_dev->arp_parms;
300
        __neigh_parms_put(neigh->parms);
301
        neigh->parms = neigh_parms_clone(parms);
302
        rcu_read_unlock();
303
 
304
        neigh->ops = &clip_neigh_ops;
305
        neigh->output = neigh->nud_state & NUD_VALID ?
306
            neigh->ops->connected_output : neigh->ops->output;
307
        entry->neigh = neigh;
308
        entry->vccs = NULL;
309
        entry->expires = jiffies - 1;
310
        return 0;
311
}
312
 
313
static u32 clip_hash(const void *pkey, const struct net_device *dev)
314
{
315
        return jhash_2words(*(u32 *) pkey, dev->ifindex, clip_tbl.hash_rnd);
316
}
317
 
318
static struct neigh_table clip_tbl = {
319
        .family         = AF_INET,
320
        .entry_size     = sizeof(struct neighbour)+sizeof(struct atmarp_entry),
321
        .key_len        = 4,
322
        .hash           = clip_hash,
323
        .constructor    = clip_constructor,
324
        .id             = "clip_arp_cache",
325
 
326
        /* parameters are copied from ARP ... */
327
        .parms = {
328
                .tbl                    = &clip_tbl,
329
                .base_reachable_time    = 30 * HZ,
330
                .retrans_time           = 1 * HZ,
331
                .gc_staletime           = 60 * HZ,
332
                .reachable_time         = 30 * HZ,
333
                .delay_probe_time       = 5 * HZ,
334
                .queue_len              = 3,
335
                .ucast_probes           = 3,
336
                .mcast_probes           = 3,
337
                .anycast_delay          = 1 * HZ,
338
                .proxy_delay            = (8 * HZ) / 10,
339
                .proxy_qlen             = 64,
340
                .locktime               = 1 * HZ,
341
        },
342
        .gc_interval    = 30 * HZ,
343
        .gc_thresh1     = 128,
344
        .gc_thresh2     = 512,
345
        .gc_thresh3     = 1024,
346
};
347
 
348
/* @@@ copy bh locking from arp.c -- need to bh-enable atm code before */
349
 
350
/*
351
 * We play with the resolve flag: 0 and 1 have the usual meaning, but -1 means
352
 * to allocate the neighbour entry but not to ask atmarpd for resolution. Also,
353
 * don't increment the usage count. This is used to create entries in
354
 * clip_setentry.
355
 */
356
 
357
static int clip_encap(struct atm_vcc *vcc, int mode)
358
{
359
        CLIP_VCC(vcc)->encap = mode;
360
        return 0;
361
}
362
 
363
static int clip_start_xmit(struct sk_buff *skb, struct net_device *dev)
364
{
365
        struct clip_priv *clip_priv = PRIV(dev);
366
        struct atmarp_entry *entry;
367
        struct atm_vcc *vcc;
368
        int old;
369
        unsigned long flags;
370
 
371
        pr_debug("clip_start_xmit (skb %p)\n", skb);
372
        if (!skb->dst) {
373
                printk(KERN_ERR "clip_start_xmit: skb->dst == NULL\n");
374
                dev_kfree_skb(skb);
375
                clip_priv->stats.tx_dropped++;
376
                return 0;
377
        }
378
        if (!skb->dst->neighbour) {
379
#if 0
380
                skb->dst->neighbour = clip_find_neighbour(skb->dst, 1);
381
                if (!skb->dst->neighbour) {
382
                        dev_kfree_skb(skb);     /* lost that one */
383
                        clip_priv->stats.tx_dropped++;
384
                        return 0;
385
                }
386
#endif
387
                printk(KERN_ERR "clip_start_xmit: NO NEIGHBOUR !\n");
388
                dev_kfree_skb(skb);
389
                clip_priv->stats.tx_dropped++;
390
                return 0;
391
        }
392
        entry = NEIGH2ENTRY(skb->dst->neighbour);
393
        if (!entry->vccs) {
394
                if (time_after(jiffies, entry->expires)) {
395
                        /* should be resolved */
396
                        entry->expires = jiffies + ATMARP_RETRY_DELAY * HZ;
397
                        to_atmarpd(act_need, PRIV(dev)->number, entry->ip);
398
                }
399
                if (entry->neigh->arp_queue.qlen < ATMARP_MAX_UNRES_PACKETS)
400
                        skb_queue_tail(&entry->neigh->arp_queue, skb);
401
                else {
402
                        dev_kfree_skb(skb);
403
                        clip_priv->stats.tx_dropped++;
404
                }
405
                return 0;
406
        }
407
        pr_debug("neigh %p, vccs %p\n", entry, entry->vccs);
408
        ATM_SKB(skb)->vcc = vcc = entry->vccs->vcc;
409
        pr_debug("using neighbour %p, vcc %p\n", skb->dst->neighbour, vcc);
410
        if (entry->vccs->encap) {
411
                void *here;
412
 
413
                here = skb_push(skb, RFC1483LLC_LEN);
414
                memcpy(here, llc_oui, sizeof(llc_oui));
415
                ((__be16 *) here)[3] = skb->protocol;
416
        }
417
        atomic_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
418
        ATM_SKB(skb)->atm_options = vcc->atm_options;
419
        entry->vccs->last_use = jiffies;
420
        pr_debug("atm_skb(%p)->vcc(%p)->dev(%p)\n", skb, vcc, vcc->dev);
421
        old = xchg(&entry->vccs->xoff, 1);      /* assume XOFF ... */
422
        if (old) {
423
                printk(KERN_WARNING "clip_start_xmit: XOFF->XOFF transition\n");
424
                return 0;
425
        }
426
        clip_priv->stats.tx_packets++;
427
        clip_priv->stats.tx_bytes += skb->len;
428
        vcc->send(vcc, skb);
429
        if (atm_may_send(vcc, 0)) {
430
                entry->vccs->xoff = 0;
431
                return 0;
432
        }
433
        spin_lock_irqsave(&clip_priv->xoff_lock, flags);
434
        netif_stop_queue(dev);  /* XOFF -> throttle immediately */
435
        barrier();
436
        if (!entry->vccs->xoff)
437
                netif_start_queue(dev);
438
        /* Oh, we just raced with clip_pop. netif_start_queue should be
439
           good enough, because nothing should really be asleep because
440
           of the brief netif_stop_queue. If this isn't true or if it
441
           changes, use netif_wake_queue instead. */
442
        spin_unlock_irqrestore(&clip_priv->xoff_lock, flags);
443
        return 0;
444
}
445
 
446
static struct net_device_stats *clip_get_stats(struct net_device *dev)
447
{
448
        return &PRIV(dev)->stats;
449
}
450
 
451
static int clip_mkip(struct atm_vcc *vcc, int timeout)
452
{
453
        struct clip_vcc *clip_vcc;
454
        struct sk_buff *skb;
455
        struct sk_buff_head *rq;
456
        unsigned long flags;
457
 
458
        if (!vcc->push)
459
                return -EBADFD;
460
        clip_vcc = kmalloc(sizeof(struct clip_vcc), GFP_KERNEL);
461
        if (!clip_vcc)
462
                return -ENOMEM;
463
        pr_debug("mkip clip_vcc %p vcc %p\n", clip_vcc, vcc);
464
        clip_vcc->vcc = vcc;
465
        vcc->user_back = clip_vcc;
466
        set_bit(ATM_VF_IS_CLIP, &vcc->flags);
467
        clip_vcc->entry = NULL;
468
        clip_vcc->xoff = 0;
469
        clip_vcc->encap = 1;
470
        clip_vcc->last_use = jiffies;
471
        clip_vcc->idle_timeout = timeout * HZ;
472
        clip_vcc->old_push = vcc->push;
473
        clip_vcc->old_pop = vcc->pop;
474
        vcc->push = clip_push;
475
        vcc->pop = clip_pop;
476
 
477
        rq = &sk_atm(vcc)->sk_receive_queue;
478
 
479
        spin_lock_irqsave(&rq->lock, flags);
480
        if (skb_queue_empty(rq)) {
481
                skb = NULL;
482
        } else {
483
                /* NULL terminate the list.  */
484
                rq->prev->next = NULL;
485
                skb = rq->next;
486
        }
487
        rq->prev = rq->next = (struct sk_buff *)rq;
488
        rq->qlen = 0;
489
        spin_unlock_irqrestore(&rq->lock, flags);
490
 
491
        /* re-process everything received between connection setup and MKIP */
492
        while (skb) {
493
                struct sk_buff *next = skb->next;
494
 
495
                skb->next = skb->prev = NULL;
496
                if (!clip_devs) {
497
                        atm_return(vcc, skb->truesize);
498
                        kfree_skb(skb);
499
                } else {
500
                        unsigned int len = skb->len;
501
 
502
                        skb_get(skb);
503
                        clip_push(vcc, skb);
504
                        PRIV(skb->dev)->stats.rx_packets--;
505
                        PRIV(skb->dev)->stats.rx_bytes -= len;
506
                        kfree_skb(skb);
507
                }
508
 
509
                skb = next;
510
        }
511
        return 0;
512
}
513
 
514
static int clip_setentry(struct atm_vcc *vcc, __be32 ip)
515
{
516
        struct neighbour *neigh;
517
        struct atmarp_entry *entry;
518
        int error;
519
        struct clip_vcc *clip_vcc;
520
        struct flowi fl = { .nl_u = { .ip4_u = { .daddr = ip, .tos = 1}} };
521
        struct rtable *rt;
522
 
523
        if (vcc->push != clip_push) {
524
                printk(KERN_WARNING "clip_setentry: non-CLIP VCC\n");
525
                return -EBADF;
526
        }
527
        clip_vcc = CLIP_VCC(vcc);
528
        if (!ip) {
529
                if (!clip_vcc->entry) {
530
                        printk(KERN_ERR "hiding hidden ATMARP entry\n");
531
                        return 0;
532
                }
533
                pr_debug("setentry: remove\n");
534
                unlink_clip_vcc(clip_vcc);
535
                return 0;
536
        }
537
        error = ip_route_output_key(&rt, &fl);
538
        if (error)
539
                return error;
540
        neigh = __neigh_lookup(&clip_tbl, &ip, rt->u.dst.dev, 1);
541
        ip_rt_put(rt);
542
        if (!neigh)
543
                return -ENOMEM;
544
        entry = NEIGH2ENTRY(neigh);
545
        if (entry != clip_vcc->entry) {
546
                if (!clip_vcc->entry)
547
                        pr_debug("setentry: add\n");
548
                else {
549
                        pr_debug("setentry: update\n");
550
                        unlink_clip_vcc(clip_vcc);
551
                }
552
                link_vcc(clip_vcc, entry);
553
        }
554
        error = neigh_update(neigh, llc_oui, NUD_PERMANENT,
555
                             NEIGH_UPDATE_F_OVERRIDE | NEIGH_UPDATE_F_ADMIN);
556
        neigh_release(neigh);
557
        return error;
558
}
559
 
560
static void clip_setup(struct net_device *dev)
561
{
562
        dev->hard_start_xmit = clip_start_xmit;
563
        /* sg_xmit ... */
564
        dev->get_stats = clip_get_stats;
565
        dev->type = ARPHRD_ATM;
566
        dev->hard_header_len = RFC1483LLC_LEN;
567
        dev->mtu = RFC1626_MTU;
568
        dev->tx_queue_len = 100;        /* "normal" queue (packets) */
569
        /* When using a "real" qdisc, the qdisc determines the queue */
570
        /* length. tx_queue_len is only used for the default case, */
571
        /* without any more elaborate queuing. 100 is a reasonable */
572
        /* compromise between decent burst-tolerance and protection */
573
        /* against memory hogs. */
574
}
575
 
576
static int clip_create(int number)
577
{
578
        struct net_device *dev;
579
        struct clip_priv *clip_priv;
580
        int error;
581
 
582
        if (number != -1) {
583
                for (dev = clip_devs; dev; dev = PRIV(dev)->next)
584
                        if (PRIV(dev)->number == number)
585
                                return -EEXIST;
586
        } else {
587
                number = 0;
588
                for (dev = clip_devs; dev; dev = PRIV(dev)->next)
589
                        if (PRIV(dev)->number >= number)
590
                                number = PRIV(dev)->number + 1;
591
        }
592
        dev = alloc_netdev(sizeof(struct clip_priv), "", clip_setup);
593
        if (!dev)
594
                return -ENOMEM;
595
        clip_priv = PRIV(dev);
596
        sprintf(dev->name, "atm%d", number);
597
        spin_lock_init(&clip_priv->xoff_lock);
598
        clip_priv->number = number;
599
        error = register_netdev(dev);
600
        if (error) {
601
                free_netdev(dev);
602
                return error;
603
        }
604
        clip_priv->next = clip_devs;
605
        clip_devs = dev;
606
        pr_debug("registered (net:%s)\n", dev->name);
607
        return number;
608
}
609
 
610
static int clip_device_event(struct notifier_block *this, unsigned long event,
611
                             void *arg)
612
{
613
        struct net_device *dev = arg;
614
 
615
        if (dev->nd_net != &init_net)
616
                return NOTIFY_DONE;
617
 
618
        if (event == NETDEV_UNREGISTER) {
619
                neigh_ifdown(&clip_tbl, dev);
620
                return NOTIFY_DONE;
621
        }
622
 
623
        /* ignore non-CLIP devices */
624
        if (dev->type != ARPHRD_ATM || dev->hard_start_xmit != clip_start_xmit)
625
                return NOTIFY_DONE;
626
 
627
        switch (event) {
628
        case NETDEV_UP:
629
                pr_debug("clip_device_event NETDEV_UP\n");
630
                to_atmarpd(act_up, PRIV(dev)->number, 0);
631
                break;
632
        case NETDEV_GOING_DOWN:
633
                pr_debug("clip_device_event NETDEV_DOWN\n");
634
                to_atmarpd(act_down, PRIV(dev)->number, 0);
635
                break;
636
        case NETDEV_CHANGE:
637
        case NETDEV_CHANGEMTU:
638
                pr_debug("clip_device_event NETDEV_CHANGE*\n");
639
                to_atmarpd(act_change, PRIV(dev)->number, 0);
640
                break;
641
        }
642
        return NOTIFY_DONE;
643
}
644
 
645
static int clip_inet_event(struct notifier_block *this, unsigned long event,
646
                           void *ifa)
647
{
648
        struct in_device *in_dev;
649
 
650
        in_dev = ((struct in_ifaddr *)ifa)->ifa_dev;
651
        if (!in_dev || !in_dev->dev) {
652
                printk(KERN_WARNING "clip_inet_event: no device\n");
653
                return NOTIFY_DONE;
654
        }
655
        /*
656
         * Transitions are of the down-change-up type, so it's sufficient to
657
         * handle the change on up.
658
         */
659
        if (event != NETDEV_UP)
660
                return NOTIFY_DONE;
661
        return clip_device_event(this, NETDEV_CHANGE, in_dev->dev);
662
}
663
 
664
 
665
static struct notifier_block clip_dev_notifier = {
666
        .notifier_call = clip_device_event,
667
};
668
 
669
 
670
 
671
static struct notifier_block clip_inet_notifier = {
672
        .notifier_call = clip_inet_event,
673
};
674
 
675
 
676
 
677
static void atmarpd_close(struct atm_vcc *vcc)
678
{
679
        pr_debug("atmarpd_close\n");
680
 
681
        rtnl_lock();
682
        atmarpd = NULL;
683
        skb_queue_purge(&sk_atm(vcc)->sk_receive_queue);
684
        rtnl_unlock();
685
 
686
        pr_debug("(done)\n");
687
        module_put(THIS_MODULE);
688
}
689
 
690
 
691
static struct atmdev_ops atmarpd_dev_ops = {
692
        .close = atmarpd_close
693
};
694
 
695
 
696
static struct atm_dev atmarpd_dev = {
697
        .ops =                  &atmarpd_dev_ops,
698
        .type =                 "arpd",
699
        .number =               999,
700
        .lock =                 __SPIN_LOCK_UNLOCKED(atmarpd_dev.lock)
701
};
702
 
703
 
704
static int atm_init_atmarp(struct atm_vcc *vcc)
705
{
706
        rtnl_lock();
707
        if (atmarpd) {
708
                rtnl_unlock();
709
                return -EADDRINUSE;
710
        }
711
 
712
        mod_timer(&idle_timer, jiffies+CLIP_CHECK_INTERVAL*HZ);
713
 
714
        atmarpd = vcc;
715
        set_bit(ATM_VF_META,&vcc->flags);
716
        set_bit(ATM_VF_READY,&vcc->flags);
717
            /* allow replies and avoid getting closed if signaling dies */
718
        vcc->dev = &atmarpd_dev;
719
        vcc_insert_socket(sk_atm(vcc));
720
        vcc->push = NULL;
721
        vcc->pop = NULL; /* crash */
722
        vcc->push_oam = NULL; /* crash */
723
        rtnl_unlock();
724
        return 0;
725
}
726
 
727
static int clip_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
728
{
729
        struct atm_vcc *vcc = ATM_SD(sock);
730
        int err = 0;
731
 
732
        switch (cmd) {
733
        case SIOCMKCLIP:
734
        case ATMARPD_CTRL:
735
        case ATMARP_MKIP:
736
        case ATMARP_SETENTRY:
737
        case ATMARP_ENCAP:
738
                if (!capable(CAP_NET_ADMIN))
739
                        return -EPERM;
740
                break;
741
        default:
742
                return -ENOIOCTLCMD;
743
        }
744
 
745
        switch (cmd) {
746
        case SIOCMKCLIP:
747
                err = clip_create(arg);
748
                break;
749
        case ATMARPD_CTRL:
750
                err = atm_init_atmarp(vcc);
751
                if (!err) {
752
                        sock->state = SS_CONNECTED;
753
                        __module_get(THIS_MODULE);
754
                }
755
                break;
756
        case ATMARP_MKIP:
757
                err = clip_mkip(vcc, arg);
758
                break;
759
        case ATMARP_SETENTRY:
760
                err = clip_setentry(vcc, (__force __be32)arg);
761
                break;
762
        case ATMARP_ENCAP:
763
                err = clip_encap(vcc, arg);
764
                break;
765
        }
766
        return err;
767
}
768
 
769
static struct atm_ioctl clip_ioctl_ops = {
770
        .owner = THIS_MODULE,
771
        .ioctl = clip_ioctl,
772
};
773
 
774
#ifdef CONFIG_PROC_FS
775
 
776
static void svc_addr(struct seq_file *seq, struct sockaddr_atmsvc *addr)
777
{
778
        static int code[] = { 1, 2, 10, 6, 1, 0 };
779
        static int e164[] = { 1, 8, 4, 6, 1, 0 };
780
 
781
        if (*addr->sas_addr.pub) {
782
                seq_printf(seq, "%s", addr->sas_addr.pub);
783
                if (*addr->sas_addr.prv)
784
                        seq_putc(seq, '+');
785
        } else if (!*addr->sas_addr.prv) {
786
                seq_printf(seq, "%s", "(none)");
787
                return;
788
        }
789
        if (*addr->sas_addr.prv) {
790
                unsigned char *prv = addr->sas_addr.prv;
791
                int *fields;
792
                int i, j;
793
 
794
                fields = *prv == ATM_AFI_E164 ? e164 : code;
795
                for (i = 0; fields[i]; i++) {
796
                        for (j = fields[i]; j; j--)
797
                                seq_printf(seq, "%02X", *prv++);
798
                        if (fields[i + 1])
799
                                seq_putc(seq, '.');
800
                }
801
        }
802
}
803
 
804
/* This means the neighbour entry has no attached VCC objects. */
805
#define SEQ_NO_VCC_TOKEN        ((void *) 2)
806
 
807
static void atmarp_info(struct seq_file *seq, struct net_device *dev,
808
                        struct atmarp_entry *entry, struct clip_vcc *clip_vcc)
809
{
810
        unsigned long exp;
811
        char buf[17];
812
        int svc, llc, off;
813
 
814
        svc = ((clip_vcc == SEQ_NO_VCC_TOKEN) ||
815
               (sk_atm(clip_vcc->vcc)->sk_family == AF_ATMSVC));
816
 
817
        llc = ((clip_vcc == SEQ_NO_VCC_TOKEN) || clip_vcc->encap);
818
 
819
        if (clip_vcc == SEQ_NO_VCC_TOKEN)
820
                exp = entry->neigh->used;
821
        else
822
                exp = clip_vcc->last_use;
823
 
824
        exp = (jiffies - exp) / HZ;
825
 
826
        seq_printf(seq, "%-6s%-4s%-4s%5ld ",
827
                   dev->name, svc ? "SVC" : "PVC", llc ? "LLC" : "NULL", exp);
828
 
829
        off = scnprintf(buf, sizeof(buf) - 1, "%d.%d.%d.%d",
830
                        NIPQUAD(entry->ip));
831
        while (off < 16)
832
                buf[off++] = ' ';
833
        buf[off] = '\0';
834
        seq_printf(seq, "%s", buf);
835
 
836
        if (clip_vcc == SEQ_NO_VCC_TOKEN) {
837
                if (time_before(jiffies, entry->expires))
838
                        seq_printf(seq, "(resolving)\n");
839
                else
840
                        seq_printf(seq, "(expired, ref %d)\n",
841
                                   atomic_read(&entry->neigh->refcnt));
842
        } else if (!svc) {
843
                seq_printf(seq, "%d.%d.%d\n",
844
                           clip_vcc->vcc->dev->number,
845
                           clip_vcc->vcc->vpi, clip_vcc->vcc->vci);
846
        } else {
847
                svc_addr(seq, &clip_vcc->vcc->remote);
848
                seq_putc(seq, '\n');
849
        }
850
}
851
 
852
struct clip_seq_state {
853
        /* This member must be first. */
854
        struct neigh_seq_state ns;
855
 
856
        /* Local to clip specific iteration. */
857
        struct clip_vcc *vcc;
858
};
859
 
860
static struct clip_vcc *clip_seq_next_vcc(struct atmarp_entry *e,
861
                                          struct clip_vcc *curr)
862
{
863
        if (!curr) {
864
                curr = e->vccs;
865
                if (!curr)
866
                        return SEQ_NO_VCC_TOKEN;
867
                return curr;
868
        }
869
        if (curr == SEQ_NO_VCC_TOKEN)
870
                return NULL;
871
 
872
        curr = curr->next;
873
 
874
        return curr;
875
}
876
 
877
static void *clip_seq_vcc_walk(struct clip_seq_state *state,
878
                               struct atmarp_entry *e, loff_t * pos)
879
{
880
        struct clip_vcc *vcc = state->vcc;
881
 
882
        vcc = clip_seq_next_vcc(e, vcc);
883
        if (vcc && pos != NULL) {
884
                while (*pos) {
885
                        vcc = clip_seq_next_vcc(e, vcc);
886
                        if (!vcc)
887
                                break;
888
                        --(*pos);
889
                }
890
        }
891
        state->vcc = vcc;
892
 
893
        return vcc;
894
}
895
 
896
static void *clip_seq_sub_iter(struct neigh_seq_state *_state,
897
                               struct neighbour *n, loff_t * pos)
898
{
899
        struct clip_seq_state *state = (struct clip_seq_state *)_state;
900
 
901
        return clip_seq_vcc_walk(state, NEIGH2ENTRY(n), pos);
902
}
903
 
904
static void *clip_seq_start(struct seq_file *seq, loff_t * pos)
905
{
906
        return neigh_seq_start(seq, pos, &clip_tbl, NEIGH_SEQ_NEIGH_ONLY);
907
}
908
 
909
static int clip_seq_show(struct seq_file *seq, void *v)
910
{
911
        static char atm_arp_banner[] =
912
            "IPitf TypeEncp Idle IP address      ATM address\n";
913
 
914
        if (v == SEQ_START_TOKEN) {
915
                seq_puts(seq, atm_arp_banner);
916
        } else {
917
                struct clip_seq_state *state = seq->private;
918
                struct neighbour *n = v;
919
                struct clip_vcc *vcc = state->vcc;
920
 
921
                atmarp_info(seq, n->dev, NEIGH2ENTRY(n), vcc);
922
        }
923
        return 0;
924
}
925
 
926
static const struct seq_operations arp_seq_ops = {
927
        .start  = clip_seq_start,
928
        .next   = neigh_seq_next,
929
        .stop   = neigh_seq_stop,
930
        .show   = clip_seq_show,
931
};
932
 
933
static int arp_seq_open(struct inode *inode, struct file *file)
934
{
935
        struct clip_seq_state *state;
936
        struct seq_file *seq;
937
        int rc = -EAGAIN;
938
 
939
        state = kzalloc(sizeof(*state), GFP_KERNEL);
940
        if (!state) {
941
                rc = -ENOMEM;
942
                goto out_kfree;
943
        }
944
        state->ns.neigh_sub_iter = clip_seq_sub_iter;
945
 
946
        rc = seq_open(file, &arp_seq_ops);
947
        if (rc)
948
                goto out_kfree;
949
 
950
        seq = file->private_data;
951
        seq->private = state;
952
out:
953
        return rc;
954
 
955
out_kfree:
956
        kfree(state);
957
        goto out;
958
}
959
 
960
static const struct file_operations arp_seq_fops = {
961
        .open           = arp_seq_open,
962
        .read           = seq_read,
963
        .llseek         = seq_lseek,
964
        .release        = seq_release_private,
965
        .owner          = THIS_MODULE
966
};
967
#endif
968
 
969
static int __init atm_clip_init(void)
970
{
971
        neigh_table_init_no_netlink(&clip_tbl);
972
 
973
        clip_tbl_hook = &clip_tbl;
974
        register_atm_ioctl(&clip_ioctl_ops);
975
        register_netdevice_notifier(&clip_dev_notifier);
976
        register_inetaddr_notifier(&clip_inet_notifier);
977
 
978
        setup_timer(&idle_timer, idle_timer_check, 0);
979
 
980
#ifdef CONFIG_PROC_FS
981
        {
982
                struct proc_dir_entry *p;
983
 
984
                p = create_proc_entry("arp", S_IRUGO, atm_proc_root);
985
                if (p)
986
                        p->proc_fops = &arp_seq_fops;
987
        }
988
#endif
989
 
990
        return 0;
991
}
992
 
993
static void __exit atm_clip_exit(void)
994
{
995
        struct net_device *dev, *next;
996
 
997
        remove_proc_entry("arp", atm_proc_root);
998
 
999
        unregister_inetaddr_notifier(&clip_inet_notifier);
1000
        unregister_netdevice_notifier(&clip_dev_notifier);
1001
 
1002
        deregister_atm_ioctl(&clip_ioctl_ops);
1003
 
1004
        /* First, stop the idle timer, so it stops banging
1005
         * on the table.
1006
         */
1007
        del_timer_sync(&idle_timer);
1008
 
1009
        /* Next, purge the table, so that the device
1010
         * unregister loop below does not hang due to
1011
         * device references remaining in the table.
1012
         */
1013
        neigh_ifdown(&clip_tbl, NULL);
1014
 
1015
        dev = clip_devs;
1016
        while (dev) {
1017
                next = PRIV(dev)->next;
1018
                unregister_netdev(dev);
1019
                free_netdev(dev);
1020
                dev = next;
1021
        }
1022
 
1023
        /* Now it is safe to fully shutdown whole table. */
1024
        neigh_table_clear(&clip_tbl);
1025
 
1026
        clip_tbl_hook = NULL;
1027
}
1028
 
1029
module_init(atm_clip_init);
1030
module_exit(atm_clip_exit);
1031
MODULE_AUTHOR("Werner Almesberger");
1032
MODULE_DESCRIPTION("Classical/IP over ATM interface");
1033
MODULE_LICENSE("GPL");

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.