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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [net/] [appletalk/] [aarp.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 *      AARP:           An implementation of the AppleTalk AARP protocol for
3
 *                      Ethernet 'ELAP'.
4
 *
5
 *              Alan Cox  <Alan.Cox@linux.org>
6
 *
7
 *      This doesn't fit cleanly with the IP arp. Potentially we can use
8
 *      the generic neighbour discovery code to clean this up.
9
 *
10
 *      FIXME:
11
 *              We ought to handle the retransmits with a single list and a
12
 *      separate fast timer for when it is needed.
13
 *              Use neighbour discovery code.
14
 *              Token Ring Support.
15
 *
16
 *              This program is free software; you can redistribute it and/or
17
 *              modify it under the terms of the GNU General Public License
18
 *              as published by the Free Software Foundation; either version
19
 *              2 of the License, or (at your option) any later version.
20
 *
21
 *
22
 *      References:
23
 *              Inside AppleTalk (2nd Ed).
24
 *      Fixes:
25
 *              Jaume Grau      -       flush caches on AARP_PROBE
26
 *              Rob Newberry    -       Added proxy AARP and AARP proc fs,
27
 *                                      moved probing from DDP module.
28
 *              Arnaldo C. Melo -       don't mangle rx packets
29
 *
30
 */
31
 
32
#include <linux/config.h>
33
#if defined(CONFIG_ATALK) || defined(CONFIG_ATALK_MODULE) 
34
#include <asm/uaccess.h>
35
#include <asm/system.h>
36
#include <asm/bitops.h>
37
#include <linux/types.h>
38
#include <linux/kernel.h>
39
#include <linux/sched.h>
40
#include <linux/string.h>
41
#include <linux/mm.h>
42
#include <linux/socket.h>
43
#include <linux/sockios.h>
44
#include <linux/in.h>
45
#include <linux/errno.h>
46
#include <linux/interrupt.h>
47
#include <linux/if_ether.h>
48
#include <linux/inet.h>
49
#include <linux/notifier.h>
50
#include <linux/netdevice.h>
51
#include <linux/etherdevice.h>
52
#include <linux/if_arp.h>
53
#include <linux/skbuff.h>
54
#include <linux/spinlock.h>
55
#include <net/sock.h>
56
#include <net/datalink.h>
57
#include <net/psnap.h>
58
#include <linux/atalk.h>
59
#include <linux/init.h>
60
#include <linux/proc_fs.h>
61
#include <linux/module.h>
62
 
63
int sysctl_aarp_expiry_time = AARP_EXPIRY_TIME;
64
int sysctl_aarp_tick_time = AARP_TICK_TIME;
65
int sysctl_aarp_retransmit_limit = AARP_RETRANSMIT_LIMIT;
66
int sysctl_aarp_resolve_time = AARP_RESOLVE_TIME;
67
 
68
/* Lists of aarp entries */
69
struct aarp_entry {
70
        /* These first two are only used for unresolved entries */
71
        unsigned long last_sent;                /* Last time we xmitted the aarp request */
72
        struct sk_buff_head packet_queue;       /* Queue of frames wait for resolution */
73
        int status;                             /* Used for proxy AARP */
74
        unsigned long expires_at;               /* Entry expiry time */
75
        struct at_addr target_addr;             /* DDP Address */
76
        struct net_device *dev;                 /* Device to use */
77
        char hwaddr[6];                         /* Physical i/f address of target/router */
78
        unsigned short xmit_count;              /* When this hits 10 we give up */
79
        struct aarp_entry *next;                /* Next entry in chain */
80
};
81
 
82
/* Hashed list of resolved, unresolved and proxy entries */
83
static struct aarp_entry *resolved[AARP_HASH_SIZE];
84
static struct aarp_entry *unresolved[AARP_HASH_SIZE];
85
static struct aarp_entry *proxies[AARP_HASH_SIZE];
86
static int unresolved_count;
87
 
88
/* One lock protects it all. */
89
static spinlock_t aarp_lock = SPIN_LOCK_UNLOCKED;
90
 
91
/* Used to walk the list and purge/kick entries.  */
92
static struct timer_list aarp_timer;
93
 
94
/*
95
 *      Delete an aarp queue
96
 *
97
 *      Must run under aarp_lock.
98
 */
99
static void __aarp_expire(struct aarp_entry *a)
100
{
101
        skb_queue_purge(&a->packet_queue);
102
        kfree(a);
103
}
104
 
105
/*
106
 *      Send an aarp queue entry request
107
 *
108
 *      Must run under aarp_lock.
109
 */
110
 
111
static void __aarp_send_query(struct aarp_entry *a)
112
{
113
        static char aarp_eth_multicast[ETH_ALEN] =
114
                { 0x09, 0x00, 0x07, 0xFF, 0xFF, 0xFF };
115
        struct net_device *dev = a->dev;
116
        int len = dev->hard_header_len + sizeof(struct elapaarp) +
117
                aarp_dl->header_length;
118
        struct sk_buff *skb = alloc_skb(len, GFP_ATOMIC);
119
        struct at_addr *sat = atalk_find_dev_addr(dev);
120
        struct elapaarp *eah;
121
 
122
        if (!skb)
123
                return;
124
 
125
        if (!sat) {
126
                kfree_skb(skb);
127
                return;
128
        }
129
 
130
        /* Set up the buffer */
131
        skb_reserve(skb, dev->hard_header_len + aarp_dl->header_length);
132
        eah             =       (struct elapaarp *)skb_put(skb,
133
                                                sizeof(struct elapaarp));
134
        skb->protocol   =       htons(ETH_P_ATALK);
135
        skb->nh.raw     =       skb->h.raw = (void *) eah;
136
        skb->dev        =       dev;
137
 
138
        /* Set up the ARP */
139
        eah->hw_type    =       htons(AARP_HW_TYPE_ETHERNET);
140
        eah->pa_type    =       htons(ETH_P_ATALK);
141
        eah->hw_len     =       ETH_ALEN;
142
        eah->pa_len     =       AARP_PA_ALEN;
143
        eah->function   =       htons(AARP_REQUEST);
144
 
145
        memcpy(eah->hw_src, dev->dev_addr, ETH_ALEN);
146
 
147
        eah->pa_src_zero=       0;
148
        eah->pa_src_net =       sat->s_net;
149
        eah->pa_src_node=       sat->s_node;
150
 
151
        memset(eah->hw_dst, '\0', ETH_ALEN);
152
 
153
        eah->pa_dst_zero=       0;
154
        eah->pa_dst_net =       a->target_addr.s_net;
155
        eah->pa_dst_node=       a->target_addr.s_node;
156
 
157
        /* Add ELAP headers and set target to the AARP multicast */
158
        aarp_dl->datalink_header(aarp_dl, skb, aarp_eth_multicast);
159
 
160
        /* Send it */
161
        dev_queue_xmit(skb);
162
        /* Update the sending count */
163
        a->xmit_count++;
164
}
165
 
166
/* This runs under aarp_lock and in softint context, so only atomic memory
167
 * allocations can be used. */
168
static void aarp_send_reply(struct net_device *dev, struct at_addr *us,
169
                            struct at_addr *them, unsigned char *sha)
170
{
171
        int len = dev->hard_header_len + sizeof(struct elapaarp) +
172
                        aarp_dl->header_length;
173
        struct sk_buff *skb = alloc_skb(len, GFP_ATOMIC);
174
        struct elapaarp *eah;
175
 
176
        if (!skb)
177
                return;
178
 
179
        /* Set up the buffer */
180
        skb_reserve(skb, dev->hard_header_len + aarp_dl->header_length);
181
        eah             =       (struct elapaarp *)skb_put(skb,
182
                                        sizeof(struct elapaarp));
183
        skb->protocol   =       htons(ETH_P_ATALK);
184
        skb->nh.raw     =       skb->h.raw = (void *) eah;
185
        skb->dev        =       dev;
186
 
187
        /* Set up the ARP */
188
        eah->hw_type    =       htons(AARP_HW_TYPE_ETHERNET);
189
        eah->pa_type    =       htons(ETH_P_ATALK);
190
        eah->hw_len     =       ETH_ALEN;
191
        eah->pa_len     =       AARP_PA_ALEN;
192
        eah->function   =       htons(AARP_REPLY);
193
 
194
        memcpy(eah->hw_src, dev->dev_addr, ETH_ALEN);
195
 
196
        eah->pa_src_zero=       0;
197
        eah->pa_src_net =       us->s_net;
198
        eah->pa_src_node=       us->s_node;
199
 
200
        if (!sha)
201
                memset(eah->hw_dst, '\0', ETH_ALEN);
202
        else
203
                memcpy(eah->hw_dst, sha, ETH_ALEN);
204
 
205
        eah->pa_dst_zero=       0;
206
        eah->pa_dst_net =       them->s_net;
207
        eah->pa_dst_node=       them->s_node;
208
 
209
        /* Add ELAP headers and set target to the AARP multicast */
210
        aarp_dl->datalink_header(aarp_dl, skb, sha);
211
        /* Send it */
212
        dev_queue_xmit(skb);
213
}
214
 
215
/*
216
 *      Send probe frames. Called from aarp_probe_network and
217
 *      aarp_proxy_probe_network.
218
 */
219
 
220
void aarp_send_probe(struct net_device *dev, struct at_addr *us)
221
{
222
        int len = dev->hard_header_len + sizeof(struct elapaarp) +
223
                        aarp_dl->header_length;
224
        struct sk_buff *skb = alloc_skb(len, GFP_ATOMIC);
225
        static char aarp_eth_multicast[ETH_ALEN] =
226
                { 0x09, 0x00, 0x07, 0xFF, 0xFF, 0xFF };
227
        struct elapaarp *eah;
228
 
229
        if (!skb)
230
                return;
231
 
232
        /* Set up the buffer */
233
        skb_reserve(skb, dev->hard_header_len + aarp_dl->header_length);
234
        eah             =       (struct elapaarp *)skb_put(skb,
235
                                        sizeof(struct elapaarp));
236
        skb->protocol   =       htons(ETH_P_ATALK);
237
        skb->nh.raw     =       skb->h.raw = (void *) eah;
238
        skb->dev        =       dev;
239
 
240
        /* Set up the ARP */
241
        eah->hw_type    =       htons(AARP_HW_TYPE_ETHERNET);
242
        eah->pa_type    =       htons(ETH_P_ATALK);
243
        eah->hw_len     =       ETH_ALEN;
244
        eah->pa_len     =       AARP_PA_ALEN;
245
        eah->function   =       htons(AARP_PROBE);
246
 
247
        memcpy(eah->hw_src, dev->dev_addr, ETH_ALEN);
248
 
249
        eah->pa_src_zero=       0;
250
        eah->pa_src_net =       us->s_net;
251
        eah->pa_src_node=       us->s_node;
252
 
253
        memset(eah->hw_dst, '\0', ETH_ALEN);
254
 
255
        eah->pa_dst_zero=       0;
256
        eah->pa_dst_net =       us->s_net;
257
        eah->pa_dst_node=       us->s_node;
258
 
259
        /* Add ELAP headers and set target to the AARP multicast */
260
        aarp_dl->datalink_header(aarp_dl, skb, aarp_eth_multicast);
261
        /* Send it */
262
        dev_queue_xmit(skb);
263
}
264
 
265
/*
266
 *      Handle an aarp timer expire
267
 *
268
 *      Must run under the aarp_lock.
269
 */
270
 
271
static void __aarp_expire_timer(struct aarp_entry **n)
272
{
273
        struct aarp_entry *t;
274
 
275
        while (*n)
276
                /* Expired ? */
277
                if (time_after(jiffies, (*n)->expires_at)) {
278
                        t = *n;
279
                        *n = (*n)->next;
280
                        __aarp_expire(t);
281
                } else
282
                        n = &((*n)->next);
283
}
284
 
285
/*
286
 *      Kick all pending requests 5 times a second.
287
 *
288
 *      Must run under the aarp_lock.
289
 */
290
 
291
static void __aarp_kick(struct aarp_entry **n)
292
{
293
        struct aarp_entry *t;
294
 
295
        while (*n)
296
                /* Expired: if this will be the 11th tx, we delete instead. */
297
                if ((*n)->xmit_count >= sysctl_aarp_retransmit_limit) {
298
                        t = *n;
299
                        *n = (*n)->next;
300
                        __aarp_expire(t);
301
                } else {
302
                        __aarp_send_query(*n);
303
                        n = &((*n)->next);
304
                }
305
}
306
 
307
/*
308
 *      A device has gone down. Take all entries referring to the device
309
 *      and remove them.
310
 *
311
 *      Must run under the aarp_lock.
312
 */
313
 
314
static void __aarp_expire_device(struct aarp_entry **n, struct net_device *dev)
315
{
316
        struct aarp_entry *t;
317
 
318
        while (*n)
319
                if ((*n)->dev == dev) {
320
                        t = *n;
321
                        *n = (*n)->next;
322
                        __aarp_expire(t);
323
                } else
324
                        n = &((*n)->next);
325
}
326
 
327
/* Handle the timer event */
328
static void aarp_expire_timeout(unsigned long unused)
329
{
330
        int ct;
331
 
332
        spin_lock_bh(&aarp_lock);
333
 
334
        for (ct = 0; ct < AARP_HASH_SIZE; ct++) {
335
                __aarp_expire_timer(&resolved[ct]);
336
                __aarp_kick(&unresolved[ct]);
337
                __aarp_expire_timer(&unresolved[ct]);
338
                __aarp_expire_timer(&proxies[ct]);
339
        }
340
 
341
        spin_unlock_bh(&aarp_lock);
342
        mod_timer(&aarp_timer, jiffies +
343
                  (unresolved_count ? sysctl_aarp_tick_time :
344
                   sysctl_aarp_expiry_time));
345
}
346
 
347
/* Network device notifier chain handler. */
348
static int aarp_device_event(struct notifier_block *this, unsigned long event,
349
                                void *ptr)
350
{
351
        int ct;
352
 
353
        if (event == NETDEV_DOWN) {
354
                spin_lock_bh(&aarp_lock);
355
 
356
                for (ct = 0; ct < AARP_HASH_SIZE; ct++) {
357
                        __aarp_expire_device(&resolved[ct], ptr);
358
                        __aarp_expire_device(&unresolved[ct], ptr);
359
                        __aarp_expire_device(&proxies[ct], ptr);
360
                }
361
 
362
                spin_unlock_bh(&aarp_lock);
363
        }
364
        return NOTIFY_DONE;
365
}
366
 
367
/*
368
 *      Create a new aarp entry.  This must use GFP_ATOMIC because it
369
 *      runs while holding spinlocks.
370
 */
371
 
372
static struct aarp_entry *aarp_alloc(void)
373
{
374
        struct aarp_entry *a = kmalloc(sizeof(struct aarp_entry), GFP_ATOMIC);
375
 
376
        if (a)
377
                skb_queue_head_init(&a->packet_queue);
378
        return a;
379
}
380
 
381
/*
382
 * Find an entry. We might return an expired but not yet purged entry. We
383
 * don't care as it will do no harm.
384
 *
385
 * This must run under the aarp_lock.
386
 */
387
static struct aarp_entry *__aarp_find_entry(struct aarp_entry *list,
388
                                            struct net_device *dev,
389
                                            struct at_addr *sat)
390
{
391
        while (list) {
392
                if (list->target_addr.s_net == sat->s_net &&
393
                    list->target_addr.s_node == sat->s_node &&
394
                    list->dev == dev)
395
                        break;
396
                list = list->next;
397
        }
398
 
399
        return list;
400
}
401
 
402
/* Called from the DDP code, and thus must be exported. */
403
void aarp_proxy_remove(struct net_device *dev, struct at_addr *sa)
404
{
405
        int hash = sa->s_node % (AARP_HASH_SIZE - 1);
406
        struct aarp_entry *a;
407
 
408
        spin_lock_bh(&aarp_lock);
409
 
410
        a = __aarp_find_entry(proxies[hash], dev, sa);
411
        if (a)
412
                a->expires_at = jiffies - 1;
413
 
414
        spin_unlock_bh(&aarp_lock);
415
}
416
 
417
/* This must run under aarp_lock. */
418
static struct at_addr *__aarp_proxy_find(struct net_device *dev,
419
                                         struct at_addr *sa)
420
{
421
        int hash = sa->s_node % (AARP_HASH_SIZE - 1);
422
        struct aarp_entry *a = __aarp_find_entry(proxies[hash], dev, sa);
423
 
424
        return a ? sa : NULL;
425
}
426
 
427
/*
428
 * Probe a Phase 1 device or a device that requires its Net:Node to
429
 * be set via an ioctl.
430
 */
431
void aarp_send_probe_phase1(struct atalk_iface *iface)
432
{
433
    struct ifreq atreq;
434
    struct sockaddr_at *sa = (struct sockaddr_at *)&atreq.ifr_addr;
435
 
436
    sa->sat_addr.s_node = iface->address.s_node;
437
    sa->sat_addr.s_net = ntohs(iface->address.s_net);
438
 
439
    /* We pass the Net:Node to the drivers/cards by a Device ioctl. */
440
    if (!(iface->dev->do_ioctl(iface->dev, &atreq, SIOCSIFADDR))) {
441
            (void)iface->dev->do_ioctl(iface->dev, &atreq, SIOCGIFADDR);
442
            if (iface->address.s_net != htons(sa->sat_addr.s_net) ||
443
                iface->address.s_node != sa->sat_addr.s_node)
444
                    iface->status |= ATIF_PROBE_FAIL;
445
 
446
            iface->address.s_net  = htons(sa->sat_addr.s_net);
447
            iface->address.s_node = sa->sat_addr.s_node;
448
    }
449
}
450
 
451
 
452
void aarp_probe_network(struct atalk_iface *atif)
453
{
454
        if (atif->dev->type == ARPHRD_LOCALTLK ||
455
            atif->dev->type == ARPHRD_PPP)
456
                aarp_send_probe_phase1(atif);
457
        else {
458
                unsigned int count;
459
 
460
                for (count = 0; count < AARP_RETRANSMIT_LIMIT; count++) {
461
                        aarp_send_probe(atif->dev, &atif->address);
462
 
463
                        /* Defer 1/10th */
464
                        current->state = TASK_INTERRUPTIBLE;
465
                        schedule_timeout(HZ/10);
466
 
467
                        if (atif->status & ATIF_PROBE_FAIL)
468
                                break;
469
                }
470
        }
471
}
472
 
473
int aarp_proxy_probe_network(struct atalk_iface *atif, struct at_addr *sa)
474
{
475
        int hash, retval = 1;
476
        struct aarp_entry *entry;
477
        unsigned int count;
478
 
479
        /*
480
         * we don't currently support LocalTalk or PPP for proxy AARP;
481
         * if someone wants to try and add it, have fun
482
         */
483
        if (atif->dev->type == ARPHRD_LOCALTLK)
484
                return -EPROTONOSUPPORT;
485
 
486
        if (atif->dev->type == ARPHRD_PPP)
487
                return -EPROTONOSUPPORT;
488
 
489
        /*
490
         * create a new AARP entry with the flags set to be published --
491
         * we need this one to hang around even if it's in use
492
         */
493
        entry = aarp_alloc();
494
        if (!entry)
495
                return -ENOMEM;
496
 
497
        entry->expires_at = -1;
498
        entry->status = ATIF_PROBE;
499
        entry->target_addr.s_node = sa->s_node;
500
        entry->target_addr.s_net = sa->s_net;
501
        entry->dev = atif->dev;
502
 
503
        spin_lock_bh(&aarp_lock);
504
 
505
        hash = sa->s_node % (AARP_HASH_SIZE - 1);
506
        entry->next = proxies[hash];
507
        proxies[hash] = entry;
508
 
509
        for (count = 0; count < AARP_RETRANSMIT_LIMIT; count++) {
510
                aarp_send_probe(atif->dev, sa);
511
 
512
                /* Defer 1/10th */
513
                current->state = TASK_INTERRUPTIBLE;
514
                spin_unlock_bh(&aarp_lock);
515
                schedule_timeout(HZ/10);
516
                spin_lock_bh(&aarp_lock);
517
 
518
                if (entry->status & ATIF_PROBE_FAIL)
519
                        break;
520
        }
521
 
522
        if (entry->status & ATIF_PROBE_FAIL) {
523
                entry->expires_at = jiffies - 1; /* free the entry */
524
                retval = -EADDRINUSE; /* return network full */
525
        } else /* clear the probing flag */
526
                entry->status &= ~ATIF_PROBE;
527
 
528
        spin_unlock_bh(&aarp_lock);
529
        return retval;
530
}
531
 
532
/* Send a DDP frame */
533
int aarp_send_ddp(struct net_device *dev,struct sk_buff *skb,
534
                        struct at_addr *sa, void *hwaddr)
535
{
536
        static char ddp_eth_multicast[ETH_ALEN] =
537
                { 0x09, 0x00, 0x07, 0xFF, 0xFF, 0xFF };
538
        int hash;
539
        struct aarp_entry *a;
540
 
541
        skb->nh.raw = skb->data;
542
 
543
        /* Check for LocalTalk first */
544
        if (dev->type == ARPHRD_LOCALTLK) {
545
                struct at_addr *at = atalk_find_dev_addr(dev);
546
                struct ddpehdr *ddp = (struct ddpehdr *)skb->data;
547
                int ft = 2;
548
 
549
                /*
550
                 *      Compressible ?
551
                 *
552
                 *      IFF: src_net==dest_net==device_net
553
                 *      (zero matches anything)
554
                 */
555
 
556
                if ((!ddp->deh_snet || at->s_net == ddp->deh_snet) &&
557
                    (!ddp->deh_dnet || at->s_net == ddp->deh_dnet)) {
558
                        skb_pull(skb, sizeof(struct ddpehdr) - 4);
559
 
560
                        /*
561
                         *      The upper two remaining bytes are the port
562
                         *      numbers we just happen to need. Now put the
563
                         *      length in the lower two.
564
                         */
565
                        *((__u16 *)skb->data) = htons(skb->len);
566
                        ft = 1;
567
                }
568
                /*
569
                 *      Nice and easy. No AARP type protocols occur here
570
                 *      so we can just shovel it out with a 3 byte LLAP header
571
                 */
572
 
573
                skb_push(skb, 3);
574
                skb->data[0] = sa->s_node;
575
                skb->data[1] = at->s_node;
576
                skb->data[2] = ft;
577
                skb->dev = dev;
578
                goto sendit;
579
        }
580
 
581
        /* On a PPP link we neither compress nor aarp.  */
582
        if (dev->type == ARPHRD_PPP) {
583
                skb->protocol = htons(ETH_P_PPPTALK);
584
                skb->dev = dev;
585
                goto sendit;
586
        }
587
 
588
        /* Non ELAP we cannot do. */
589
        if (dev->type != ARPHRD_ETHER)
590
                return -1;
591
 
592
        skb->dev = dev;
593
        skb->protocol = htons(ETH_P_ATALK);
594
        hash = sa->s_node % (AARP_HASH_SIZE - 1);
595
 
596
        /* Do we have a resolved entry? */
597
        if (sa->s_node == ATADDR_BCAST) {
598
                ddp_dl->datalink_header(ddp_dl, skb, ddp_eth_multicast);
599
                goto sendit;
600
        }
601
 
602
        spin_lock_bh(&aarp_lock);
603
        a = __aarp_find_entry(resolved[hash], dev, sa);
604
 
605
        if (a) { /* Return 1 and fill in the address */
606
                a->expires_at = jiffies + (sysctl_aarp_expiry_time * 10);
607
                ddp_dl->datalink_header(ddp_dl, skb, a->hwaddr);
608
                spin_unlock_bh(&aarp_lock);
609
                goto sendit;
610
        }
611
 
612
        /* Do we have an unresolved entry: This is the less common path */
613
        a = __aarp_find_entry(unresolved[hash], dev, sa);
614
        if (a) { /* Queue onto the unresolved queue */
615
                skb_queue_tail(&a->packet_queue, skb);
616
                spin_unlock_bh(&aarp_lock);
617
                return 0;
618
        }
619
 
620
        /* Allocate a new entry */
621
        a = aarp_alloc();
622
        if (!a) {
623
                /* Whoops slipped... good job it's an unreliable protocol 8) */
624
                spin_unlock_bh(&aarp_lock);
625
                return -1;
626
        }
627
 
628
        /* Set up the queue */
629
        skb_queue_tail(&a->packet_queue, skb);
630
        a->expires_at = jiffies + sysctl_aarp_resolve_time;
631
        a->dev = dev;
632
        a->next = unresolved[hash];
633
        a->target_addr = *sa;
634
        a->xmit_count = 0;
635
        unresolved[hash] = a;
636
        unresolved_count++;
637
 
638
        /* Send an initial request for the address */
639
        __aarp_send_query(a);
640
 
641
        /*
642
         *      Switch to fast timer if needed (That is if this is the
643
         *      first unresolved entry to get added)
644
         */
645
 
646
        if (unresolved_count == 1)
647
                mod_timer(&aarp_timer, jiffies + sysctl_aarp_tick_time);
648
 
649
        /* Now finally, it is safe to drop the lock. */
650
        spin_unlock_bh(&aarp_lock);
651
 
652
        /* Tell the ddp layer we have taken over for this frame. */
653
        return 0;
654
 
655
sendit: if (skb->sk)
656
                skb->priority = skb->sk->priority;
657
        dev_queue_xmit(skb);
658
        return 1;
659
}
660
 
661
/*
662
 *      An entry in the aarp unresolved queue has become resolved. Send
663
 *      all the frames queued under it.
664
 *
665
 *      Must run under aarp_lock.
666
 */
667
static void __aarp_resolved(struct aarp_entry **list, struct aarp_entry *a,
668
                                int hash)
669
{
670
        struct sk_buff *skb;
671
 
672
        while (*list)
673
                if (*list == a) {
674
                        unresolved_count--;
675
                        *list = a->next;
676
 
677
                        /* Move into the resolved list */
678
                        a->next = resolved[hash];
679
                        resolved[hash] = a;
680
 
681
                        /* Kick frames off */
682
                        while ((skb = skb_dequeue(&a->packet_queue)) != NULL) {
683
                                a->expires_at = jiffies +
684
                                                sysctl_aarp_expiry_time * 10;
685
                                ddp_dl->datalink_header(ddp_dl, skb, a->hwaddr);
686
                                if (skb->sk)
687
                                        skb->priority = skb->sk->priority;
688
                                dev_queue_xmit(skb);
689
                        }
690
                } else
691
                        list = &((*list)->next);
692
}
693
 
694
/*
695
 *      This is called by the SNAP driver whenever we see an AARP SNAP
696
 *      frame. We currently only support Ethernet.
697
 */
698
static int aarp_rcv(struct sk_buff *skb, struct net_device *dev,
699
                        struct packet_type *pt)
700
{
701
        struct elapaarp *ea = (struct elapaarp *)skb->h.raw;
702
        int hash, ret = 0;
703
        __u16 function;
704
        struct aarp_entry *a;
705
        struct at_addr sa, *ma, da;
706
        struct atalk_iface *ifa;
707
 
708
        /* We only do Ethernet SNAP AARP. */
709
        if (dev->type != ARPHRD_ETHER)
710
                goto out0;
711
 
712
        /* Frame size ok? */
713
        if (!skb_pull(skb, sizeof(*ea)))
714
                goto out0;
715
 
716
        function = ntohs(ea->function);
717
 
718
        /* Sanity check fields. */
719
        if (function < AARP_REQUEST || function > AARP_PROBE ||
720
            ea->hw_len != ETH_ALEN || ea->pa_len != AARP_PA_ALEN ||
721
            ea->pa_src_zero || ea->pa_dst_zero)
722
                goto out0;
723
 
724
        /* Looks good. */
725
        hash = ea->pa_src_node % (AARP_HASH_SIZE - 1);
726
 
727
        /* Build an address. */
728
        sa.s_node = ea->pa_src_node;
729
        sa.s_net = ea->pa_src_net;
730
 
731
        /* Process the packet. Check for replies of me. */
732
        ifa = atalk_find_dev(dev);
733
        if (!ifa)
734
                goto out1;
735
 
736
        if (ifa->status & ATIF_PROBE &&
737
            ifa->address.s_node == ea->pa_dst_node &&
738
            ifa->address.s_net == ea->pa_dst_net) {
739
                ifa->status |= ATIF_PROBE_FAIL; /* Fail the probe (in use) */
740
                goto out1;
741
        }
742
 
743
        /* Check for replies of proxy AARP entries */
744
        da.s_node = ea->pa_dst_node;
745
        da.s_net = ea->pa_dst_net;
746
 
747
        spin_lock_bh(&aarp_lock);
748
        a = __aarp_find_entry(proxies[hash], dev, &da);
749
 
750
        if (a && a->status & ATIF_PROBE) {
751
                a->status |= ATIF_PROBE_FAIL;
752
                /*
753
                 * we do not respond to probe or request packets for
754
                 * this address while we are probing this address
755
                 */
756
                goto unlock;
757
        }
758
 
759
        switch (function) {
760
                case AARP_REPLY:
761
                        if (!unresolved_count)  /* Speed up */
762
                                break;
763
 
764
                        /* Find the entry.  */
765
                        a = __aarp_find_entry(unresolved[hash],dev,&sa);
766
                        if (!a || dev != a->dev)
767
                                break;
768
 
769
                        /* We can fill one in - this is good. */
770
                        memcpy(a->hwaddr,ea->hw_src,ETH_ALEN);
771
                        __aarp_resolved(&unresolved[hash],a,hash);
772
                        if (!unresolved_count)
773
                                mod_timer(&aarp_timer,
774
                                          jiffies + sysctl_aarp_expiry_time);
775
                        break;
776
 
777
                case AARP_REQUEST:
778
                case AARP_PROBE:
779
                        /*
780
                         *      If it is my address set ma to my address and
781
                         *      reply. We can treat probe and request the
782
                         *      same. Probe simply means we shouldn't cache
783
                         *      the querying host, as in a probe they are
784
                         *      proposing an address not using one.
785
                         *
786
                         *      Support for proxy-AARP added. We check if the
787
                         *      address is one of our proxies before we toss
788
                         *      the packet out.
789
                         */
790
 
791
                        sa.s_node = ea->pa_dst_node;
792
                        sa.s_net = ea->pa_dst_net;
793
 
794
                        /* See if we have a matching proxy. */
795
                        ma = __aarp_proxy_find(dev, &sa);
796
                        if (!ma)
797
                                ma = &ifa->address;
798
                        else { /* We need to make a copy of the entry. */
799
                                da.s_node = sa.s_node;
800
                                da.s_net = da.s_net;
801
                                ma = &da;
802
                        }
803
 
804
                        if (function == AARP_PROBE) {
805
                                /* A probe implies someone trying to get an
806
                                 * address. So as a precaution flush any
807
                                 * entries we have for this address. */
808
                                struct aarp_entry *a = __aarp_find_entry(
809
                                        resolved[sa.s_node%(AARP_HASH_SIZE-1)],
810
                                        skb->dev, &sa);
811
                                /* Make it expire next tick - that avoids us
812
                                 * getting into a probe/flush/learn/probe/
813
                                 * flush/learn cycle during probing of a slow
814
                                 * to respond host addr. */
815
                                if (a) {
816
                                        a->expires_at = jiffies - 1;
817
                                        mod_timer(&aarp_timer, jiffies +
818
                                                        sysctl_aarp_tick_time);
819
                                }
820
                        }
821
 
822
                        if (sa.s_node != ma->s_node)
823
                                break;
824
 
825
                        if (sa.s_net && ma->s_net && sa.s_net != ma->s_net)
826
                                break;
827
 
828
                        sa.s_node = ea->pa_src_node;
829
                        sa.s_net = ea->pa_src_net;
830
 
831
                        /* aarp_my_address has found the address to use for us.
832
                        */
833
                        aarp_send_reply(dev, ma, &sa, ea->hw_src);
834
                        break;
835
        }
836
 
837
unlock: spin_unlock_bh(&aarp_lock);
838
out1:   ret = 1;
839
out0:   kfree_skb(skb);
840
        return ret;
841
}
842
 
843
static struct notifier_block aarp_notifier = {
844
        notifier_call:  aarp_device_event,
845
};
846
 
847
static char aarp_snap_id[] = { 0x00, 0x00, 0x00, 0x80, 0xF3 };
848
 
849
void __init aarp_proto_init(void)
850
{
851
        aarp_dl = register_snap_client(aarp_snap_id, aarp_rcv);
852
        if (!aarp_dl)
853
                printk(KERN_CRIT "Unable to register AARP with SNAP.\n");
854
        init_timer(&aarp_timer);
855
        aarp_timer.function = aarp_expire_timeout;
856
        aarp_timer.data = 0;
857
        aarp_timer.expires = jiffies + sysctl_aarp_expiry_time;
858
        add_timer(&aarp_timer);
859
        register_netdevice_notifier(&aarp_notifier);
860
}
861
 
862
/* Remove the AARP entries associated with a device. */
863
void aarp_device_down(struct net_device *dev)
864
{
865
        int ct;
866
 
867
        spin_lock_bh(&aarp_lock);
868
 
869
        for (ct = 0; ct < AARP_HASH_SIZE; ct++) {
870
                __aarp_expire_device(&resolved[ct], dev);
871
                __aarp_expire_device(&unresolved[ct], dev);
872
                __aarp_expire_device(&proxies[ct], dev);
873
        }
874
 
875
        spin_unlock_bh(&aarp_lock);
876
}
877
 
878
/* Called from proc fs */
879
static int aarp_get_info(char *buffer, char **start, off_t offset, int length)
880
{
881
        /* we should dump all our AARP entries */
882
        struct aarp_entry *entry;
883
        int len, ct;
884
 
885
        len = sprintf(buffer,
886
                "%-10.10s  %-10.10s%-18.18s%12.12s%12.12s xmit_count  status\n",
887
                "address", "device", "hw addr", "last_sent", "expires");
888
 
889
        spin_lock_bh(&aarp_lock);
890
 
891
        for (ct = 0; ct < AARP_HASH_SIZE; ct++) {
892
                for (entry = resolved[ct]; entry; entry = entry->next) {
893
                        len+= sprintf(buffer+len,"%6u:%-3u  ",
894
                                (unsigned int)ntohs(entry->target_addr.s_net),
895
                                (unsigned int)(entry->target_addr.s_node));
896
                        len+= sprintf(buffer+len,"%-10.10s",
897
                                entry->dev->name);
898
                        len+= sprintf(buffer+len,"%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
899
                                (int)(entry->hwaddr[0] & 0x000000FF),
900
                                (int)(entry->hwaddr[1] & 0x000000FF),
901
                                (int)(entry->hwaddr[2] & 0x000000FF),
902
                                (int)(entry->hwaddr[3] & 0x000000FF),
903
                                (int)(entry->hwaddr[4] & 0x000000FF),
904
                                (int)(entry->hwaddr[5] & 0x000000FF));
905
                        len+= sprintf(buffer+len,"%12lu ""%12lu ",
906
                                (unsigned long)entry->last_sent,
907
                                (unsigned long)entry->expires_at);
908
                        len+=sprintf(buffer+len,"%10u",
909
                                (unsigned int)entry->xmit_count);
910
 
911
                        len+=sprintf(buffer+len,"   resolved\n");
912
                }
913
        }
914
 
915
        for (ct = 0; ct < AARP_HASH_SIZE; ct++) {
916
                for (entry = unresolved[ct]; entry; entry = entry->next) {
917
                        len+= sprintf(buffer+len,"%6u:%-3u  ",
918
                                (unsigned int)ntohs(entry->target_addr.s_net),
919
                                (unsigned int)(entry->target_addr.s_node));
920
                        len+= sprintf(buffer+len,"%-10.10s",
921
                                entry->dev->name);
922
                        len+= sprintf(buffer+len,"%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
923
                                (int)(entry->hwaddr[0] & 0x000000FF),
924
                                (int)(entry->hwaddr[1] & 0x000000FF),
925
                                (int)(entry->hwaddr[2] & 0x000000FF),
926
                                (int)(entry->hwaddr[3] & 0x000000FF),
927
                                (int)(entry->hwaddr[4] & 0x000000FF),
928
                                (int)(entry->hwaddr[5] & 0x000000FF));
929
                        len+= sprintf(buffer+len,"%12lu ""%12lu ",
930
                                (unsigned long)entry->last_sent,
931
                                (unsigned long)entry->expires_at);
932
                        len+=sprintf(buffer+len,"%10u",
933
                                (unsigned int)entry->xmit_count);
934
                        len+=sprintf(buffer+len," unresolved\n");
935
                }
936
        }
937
 
938
        for (ct = 0; ct < AARP_HASH_SIZE; ct++) {
939
                for (entry = proxies[ct]; entry; entry = entry->next) {
940
                        len+= sprintf(buffer+len,"%6u:%-3u  ",
941
                                (unsigned int)ntohs(entry->target_addr.s_net),
942
                                (unsigned int)(entry->target_addr.s_node));
943
                        len+= sprintf(buffer+len,"%-10.10s",
944
                                entry->dev->name);
945
                        len+= sprintf(buffer+len,"%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
946
                                (int)(entry->hwaddr[0] & 0x000000FF),
947
                                (int)(entry->hwaddr[1] & 0x000000FF),
948
                                (int)(entry->hwaddr[2] & 0x000000FF),
949
                                (int)(entry->hwaddr[3] & 0x000000FF),
950
                                (int)(entry->hwaddr[4] & 0x000000FF),
951
                                (int)(entry->hwaddr[5] & 0x000000FF));
952
                        len+= sprintf(buffer+len,"%12lu ""%12lu ",
953
                                (unsigned long)entry->last_sent,
954
                                (unsigned long)entry->expires_at);
955
                        len+=sprintf(buffer+len,"%10u",
956
                                (unsigned int)entry->xmit_count);
957
                        len+=sprintf(buffer+len,"      proxy\n");
958
                }
959
        }
960
 
961
        spin_unlock_bh(&aarp_lock);
962
        return len;
963
}
964
 
965
#ifdef MODULE
966
/* General module cleanup. Called from cleanup_module() in ddp.c. */
967
void aarp_cleanup_module(void)
968
{
969
        del_timer(&aarp_timer);
970
        unregister_netdevice_notifier(&aarp_notifier);
971
        unregister_snap_client(aarp_snap_id);
972
}
973
#endif  /* MODULE */
974
#ifdef CONFIG_PROC_FS
975
void aarp_register_proc_fs(void)
976
{
977
        proc_net_create("aarp", 0, aarp_get_info);
978
}
979
 
980
void aarp_unregister_proc_fs(void)
981
{
982
        proc_net_remove("aarp");
983
}
984
#endif
985
#endif  /* CONFIG_ATALK || CONFIG_ATALK_MODULE */
986
MODULE_LICENSE("GPL");

powered by: WebSVN 2.1.0

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