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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [uclinux/] [uClinux-2.0.x/] [net/] [ipv4/] [rarp.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 199 simons
/* linux/net/inet/rarp.c
2
 *
3
 * Copyright (C) 1994 by Ross Martin
4
 * Based on linux/net/inet/arp.c, Copyright (C) 1994 by Florian La Roche
5
 *
6
 * This module implements the Reverse Address Resolution Protocol
7
 * (RARP, RFC 903), which is used to convert low level addresses such
8
 * as ethernet addresses into high level addresses such as IP addresses.
9
 * The most common use of RARP is as a means for a diskless workstation
10
 * to discover its IP address during a network boot.
11
 *
12
 **
13
 ***    WARNING:::::::::::::::::::::::::::::::::WARNING
14
 ****
15
 *****  SUN machines seem determined to boot solely from the person who
16
 ****   answered their RARP query. NEVER add a SUN to your RARP table
17
 ***    unless you have all the rest to boot the box from it.
18
 **
19
 *
20
 * Currently, only ethernet address -> IP address is likely to work.
21
 * (Is RARP ever used for anything else?)
22
 *
23
 * This code is free software; you can redistribute it and/or
24
 * modify it under the terms of the GNU General Public License
25
 * as published by the Free Software Foundation; either version
26
 * 2 of the License, or (at your option) any later version.
27
 *
28
 * Fixes
29
 *      Alan Cox        :       Rarp delete on device down needed as
30
 *                              reported by Walter Wolfgang.
31
 *  Lawrence V. Stefani :       Added FDDI support.
32
 *      San Mehat       :       Fixed bug where rarp would fail to build
33
 *                              if procfs was not compiled into the kernel
34
 */
35
 
36
#include <linux/module.h>
37
 
38
#include <linux/types.h>
39
#include <linux/string.h>
40
#include <linux/kernel.h>
41
#include <linux/sched.h>
42
#include <linux/mm.h>
43
#include <linux/socket.h>
44
#include <linux/sockios.h>
45
#include <linux/errno.h>
46
#include <linux/netdevice.h>
47
#include <linux/if_arp.h>
48
#include <linux/in.h>
49
#include <linux/config.h>
50
 
51
#include <asm/system.h>
52
#include <asm/segment.h>
53
#include <stdarg.h>
54
#include <linux/inet.h>
55
#include <linux/etherdevice.h>
56
#include <net/ip.h>
57
#include <net/route.h>
58
#include <net/protocol.h>
59
#include <net/tcp.h>
60
#include <linux/skbuff.h>
61
#include <net/sock.h>
62
#include <net/arp.h>
63
#include <net/rarp.h>
64
#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
65
#include <net/ax25.h>
66
#endif
67
#include <linux/proc_fs.h>
68
#include <linux/stat.h>
69
 
70
extern int (*rarp_ioctl_hook)(unsigned int,void*);
71
 
72
/*
73
 *      This structure defines the RARP mapping cache. As long as we make
74
 *      changes in this structure, we keep interrupts off.
75
 */
76
 
77
struct rarp_table
78
{
79
        struct rarp_table  *next;             /* Linked entry list           */
80
        unsigned long      ip;                /* ip address of entry         */
81
        unsigned char      ha[MAX_ADDR_LEN];  /* Hardware address            */
82
        unsigned char      hlen;              /* Length of hardware address  */
83
        unsigned char      htype;             /* Type of hardware in use     */
84
        struct device      *dev;              /* Device the entry is tied to */
85
};
86
 
87
struct rarp_table *rarp_tables = NULL;
88
 
89
static int rarp_rcv(struct sk_buff *, struct device *, struct packet_type *);
90
 
91
static struct packet_type rarp_packet_type =
92
{
93
        0,  /* Should be: __constant_htons(ETH_P_RARP) - but this _doesn't_ come out constant! */
94
        0,                /* copy */
95
        rarp_rcv,
96
        NULL,
97
        NULL
98
};
99
 
100
static int initflag = 1;
101
 
102
 
103
/*
104
 *      Release the memory for this entry.
105
 */
106
 
107
static inline void rarp_release_entry(struct rarp_table *entry)
108
{
109
        kfree_s(entry, sizeof(struct rarp_table));
110
        MOD_DEC_USE_COUNT;
111
        return;
112
}
113
 
114
/*
115
 *      Delete a RARP mapping entry in the cache.
116
 */
117
 
118
static void rarp_destroy(unsigned long ip_addr)
119
{
120
        struct rarp_table *entry;
121
        struct rarp_table **pentry;
122
 
123
        cli();
124
        pentry = &rarp_tables;
125
        while ((entry = *pentry) != NULL)
126
        {
127
                if (entry->ip == ip_addr)
128
                {
129
                        *pentry = entry->next;
130
                        sti();
131
                        rarp_release_entry(entry);
132
                        return;
133
                }
134
                pentry = &entry->next;
135
        }
136
        sti();
137
}
138
 
139
/*
140
 *      Flush a device.
141
 */
142
 
143
static void rarp_destroy_dev(struct device *dev)
144
{
145
        struct rarp_table *entry;
146
        struct rarp_table **pentry;
147
 
148
        cli();
149
        pentry = &rarp_tables;
150
        while ((entry = *pentry) != NULL)
151
        {
152
                if (entry->dev == dev)
153
                {
154
                        *pentry = entry->next;
155
                        rarp_release_entry(entry);
156
                }
157
                else
158
                        pentry = &entry->next;
159
        }
160
        sti();
161
}
162
 
163
static int rarp_device_event(struct notifier_block *this, unsigned long event, void *ptr)
164
{
165
        if(event!=NETDEV_DOWN)
166
                return NOTIFY_DONE;
167
        rarp_destroy_dev((struct device *)ptr);
168
        return NOTIFY_DONE;
169
}
170
 
171
/*
172
 *      Called once when data first added to rarp cache with ioctl.
173
 */
174
 
175
static struct notifier_block rarp_dev_notifier={
176
        rarp_device_event,
177
        NULL,
178
 
179
};
180
 
181
static int rarp_pkt_inited=0;
182
 
183
static void rarp_init_pkt (void)
184
{
185
        /* Register the packet type */
186
        rarp_packet_type.type=htons(ETH_P_RARP);
187
        dev_add_pack(&rarp_packet_type);
188
        register_netdevice_notifier(&rarp_dev_notifier);
189
        rarp_pkt_inited=1;
190
}
191
 
192
#ifdef MODULE
193
 
194
static void rarp_end_pkt(void)
195
{
196
        if(!rarp_pkt_inited)
197
                return;
198
        dev_remove_pack(&rarp_packet_type);
199
        unregister_netdevice_notifier(&rarp_dev_notifier);
200
        rarp_pkt_inited=0;
201
}
202
 
203
#endif
204
 
205
 
206
/*
207
 *      Receive an arp request by the device layer.  Maybe it should be
208
 *      rewritten to use the incoming packet for the reply. The current
209
 *      "overhead" time isn't that high...
210
 */
211
 
212
static int rarp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
213
{
214
/*
215
 *      We shouldn't use this type conversion. Check later.
216
 */
217
        struct arphdr *rarp = (struct arphdr *) skb->data;
218
        unsigned char *rarp_ptr = skb_pull(skb,sizeof(struct arphdr));
219
        struct rarp_table *entry;
220
        long sip,tip;
221
        unsigned char *sha,*tha;            /* s for "source", t for "target" */
222
 
223
/*
224
 *      If this test doesn't pass, it's not IP, or we should ignore it anyway
225
 */
226
#ifdef CONFIG_FDDI
227
        if (dev->type == ARPHRD_FDDI)
228
        {
229
                /*
230
                 * Since the dev->type for FDDI is "made up", compare the rarp->ar_hrd
231
                 * field against ARPHRD_ETHER and ARPHRD_IEEE802.
232
                 *
233
                 * Ought to move to a device specifc 'arp_type_ok()'
234
                 */
235
                if (rarp->ar_hln != dev->addr_len
236
                        || ((ntohs(rarp->ar_hrd) != ARPHRD_ETHER) && (ntohs(rarp->ar_hrd) != ARPHRD_IEEE802))
237
                        || dev->flags&IFF_NOARP)
238
                {
239
                        kfree_skb(skb, FREE_READ);
240
                        return 0;
241
                }
242
        }
243
        else
244
        {
245
                if (rarp->ar_hln != dev->addr_len || dev->type != ntohs(rarp->ar_hrd)
246
                        || dev->flags&IFF_NOARP)
247
                        {
248
                        kfree_skb(skb, FREE_READ);
249
                        return 0;
250
                }
251
        }
252
#else
253
        if (rarp->ar_hln != dev->addr_len || dev->type != ntohs(rarp->ar_hrd)
254
                || dev->flags&IFF_NOARP)
255
        {
256
                kfree_skb(skb, FREE_READ);
257
                return 0;
258
        }
259
#endif
260
 
261
/*
262
 *      If it's not a RARP request, delete it.
263
 */
264
        if (rarp->ar_op != htons(ARPOP_RREQUEST))
265
        {
266
                kfree_skb(skb, FREE_READ);
267
                return 0;
268
        }
269
 
270
/*
271
 *      For now we will only deal with IP addresses.
272
 */
273
 
274
        if (
275
#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
276
                (rarp->ar_pro != htons(AX25_P_IP) && dev->type == ARPHRD_AX25) ||
277
#endif
278
                (rarp->ar_pro != htons(ETH_P_IP) && dev->type != ARPHRD_AX25)
279
                || rarp->ar_pln != 4)
280
        {
281
                /*
282
                 *      This packet is not for us. Remove it.
283
                 */
284
                kfree_skb(skb, FREE_READ);
285
                return 0;
286
        }
287
 
288
/*
289
 *      Extract variable width fields
290
 */
291
 
292
        sha=rarp_ptr;
293
        rarp_ptr+=dev->addr_len;
294
        memcpy(&sip,rarp_ptr,4);
295
        rarp_ptr+=4;
296
        tha=rarp_ptr;
297
        rarp_ptr+=dev->addr_len;
298
        memcpy(&tip,rarp_ptr,4);
299
 
300
/*
301
 *      Process entry. Use tha for table lookup according to RFC903.
302
 */
303
 
304
        cli();
305
        for (entry = rarp_tables; entry != NULL; entry = entry->next)
306
                if (!memcmp(entry->ha, tha, rarp->ar_hln))
307
                        break;
308
 
309
        if (entry != NULL)
310
        {
311
                sip=entry->ip;
312
                sti();
313
 
314
                arp_send(ARPOP_RREPLY, ETH_P_RARP, sip, dev, dev->pa_addr, sha,
315
                        dev->dev_addr, sha);
316
        }
317
        else
318
                sti();
319
 
320
        kfree_skb(skb, FREE_READ);
321
        return 0;
322
}
323
 
324
 
325
/*
326
 *      Set (create) a RARP cache entry.
327
 */
328
 
329
static int rarp_req_set(struct arpreq *req)
330
{
331
        struct arpreq r;
332
        struct rarp_table *entry;
333
        struct sockaddr_in *si;
334
        int htype, hlen;
335
        unsigned long ip;
336
        struct rtable *rt;
337
        struct device * dev;
338
 
339
        memcpy_fromfs(&r, req, sizeof(r));
340
 
341
        /*
342
         *      We only understand about IP addresses...
343
         */
344
 
345
        if (r.arp_pa.sa_family != AF_INET)
346
                return -EPFNOSUPPORT;
347
 
348
        switch (r.arp_ha.sa_family)
349
        {
350
                case ARPHRD_ETHER:
351
                        htype = ARPHRD_ETHER;
352
                        hlen = ETH_ALEN;
353
                        break;
354
#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
355
                case ARPHRD_AX25:
356
                        htype = ARPHRD_AX25;
357
                        hlen = 7;
358
                break;
359
#endif
360
                default:
361
                        return -EPFNOSUPPORT;
362
        }
363
 
364
        si = (struct sockaddr_in *) &r.arp_pa;
365
        ip = si->sin_addr.s_addr;
366
        if (ip == 0)
367
        {
368
                printk(KERN_DEBUG "RARP: SETRARP: requested PA is 0.0.0.0 !\n");
369
                return -EINVAL;
370
        }
371
 
372
/*
373
 *      Is it reachable directly ?
374
 */
375
 
376
        rt = ip_rt_route(ip, 0, NULL);
377
        if (rt == NULL)
378
                return -ENETUNREACH;
379
        dev = rt->rt_dev;
380
        ip_rt_put(rt);
381
 
382
/*
383
 *      Is there an existing entry for this address?  Find out...
384
 */
385
 
386
        cli();
387
        for (entry = rarp_tables; entry != NULL; entry = entry->next)
388
                if (entry->ip == ip)
389
                        break;
390
 
391
/*
392
 *      If no entry was found, create a new one.
393
 */
394
 
395
        if (entry == NULL)
396
        {
397
                entry = (struct rarp_table *) kmalloc(sizeof(struct rarp_table),
398
                                    GFP_ATOMIC);
399
                if (entry == NULL)
400
                {
401
                        sti();
402
                        return -ENOMEM;
403
                }
404
                if (initflag)
405
                {
406
                        rarp_init_pkt();
407
                        initflag=0;
408
                }
409
 
410
                entry->next = rarp_tables;
411
                rarp_tables = entry;
412
        }
413
 
414
        entry->ip = ip;
415
        entry->hlen = hlen;
416
        entry->htype = htype;
417
        memcpy(&entry->ha, &r.arp_ha.sa_data, hlen);
418
        entry->dev = dev;
419
 
420
        /* Don't unlink if we have entries to serve. */
421
        MOD_INC_USE_COUNT;
422
 
423
        sti();
424
 
425
        return 0;
426
}
427
 
428
 
429
/*
430
 *        Get a RARP cache entry.
431
 */
432
 
433
static int rarp_req_get(struct arpreq *req)
434
{
435
        struct arpreq r;
436
        struct rarp_table *entry;
437
        struct sockaddr_in *si;
438
        unsigned long ip;
439
 
440
/*
441
 *      We only understand about IP addresses...
442
 */
443
 
444
        memcpy_fromfs(&r, req, sizeof(r));
445
 
446
        if (r.arp_pa.sa_family != AF_INET)
447
                return -EPFNOSUPPORT;
448
 
449
/*
450
 *        Is there an existing entry for this address?
451
 */
452
 
453
        si = (struct sockaddr_in *) &r.arp_pa;
454
        ip = si->sin_addr.s_addr;
455
 
456
        cli();
457
        for (entry = rarp_tables; entry != NULL; entry = entry->next)
458
                if (entry->ip == ip)
459
                        break;
460
 
461
        if (entry == NULL)
462
        {
463
                sti();
464
                return -ENXIO;
465
        }
466
 
467
/*
468
 *        We found it; copy into structure.
469
 */
470
 
471
        memcpy(r.arp_ha.sa_data, &entry->ha, entry->hlen);
472
        r.arp_ha.sa_family = entry->htype;
473
        sti();
474
 
475
/*
476
 *        Copy the information back
477
 */
478
 
479
        memcpy_tofs(req, &r, sizeof(r));
480
        return 0;
481
}
482
 
483
 
484
/*
485
 *      Handle a RARP layer I/O control request.
486
 */
487
 
488
int rarp_ioctl(unsigned int cmd, void *arg)
489
{
490
        struct arpreq r;
491
        struct sockaddr_in *si;
492
        int err;
493
 
494
        switch(cmd)
495
        {
496
                case SIOCDRARP:
497
                        if (!suser())
498
                                return -EPERM;
499
                        err = verify_area(VERIFY_READ, arg, sizeof(struct arpreq));
500
                        if(err)
501
                                return err;
502
                        memcpy_fromfs(&r, arg, sizeof(r));
503
                        if (r.arp_pa.sa_family != AF_INET)
504
                                return -EPFNOSUPPORT;
505
                        si = (struct sockaddr_in *) &r.arp_pa;
506
                        rarp_destroy(si->sin_addr.s_addr);
507
                        return 0;
508
 
509
                case SIOCGRARP:
510
                        err = verify_area(VERIFY_WRITE, arg, sizeof(struct arpreq));
511
                        if(err)
512
                                return err;
513
                        return rarp_req_get((struct arpreq *)arg);
514
                case SIOCSRARP:
515
                        if (!suser())
516
                                return -EPERM;
517
                        err = verify_area(VERIFY_READ, arg, sizeof(struct arpreq));
518
                        if(err)
519
                                return err;
520
                        return rarp_req_set((struct arpreq *)arg);
521
                default:
522
                        return -EINVAL;
523
        }
524
 
525
        /*NOTREACHED*/
526
        return 0;
527
}
528
 
529
int rarp_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
530
{
531
        int len=0;
532
        off_t begin=0;
533
        off_t pos=0;
534
        int size;
535
        struct rarp_table *entry;
536
        char ipbuffer[20];
537
        unsigned long netip;
538
        if (initflag)
539
        {
540
                size = sprintf(buffer,"RARP disabled until entries added to cache.\n");
541
                pos+=size;
542
                len+=size;
543
        }
544
        else
545
        {
546
                size = sprintf(buffer,
547
                        "IP address       HW type             HW address\n");
548
                pos+=size;
549
                len+=size;
550
 
551
                cli();
552
                for(entry=rarp_tables; entry!=NULL; entry=entry->next)
553
                {
554
                        netip=htonl(entry->ip);          /* switch to network order */
555
                        sprintf(ipbuffer,"%d.%d.%d.%d",
556
                                (unsigned int)(netip>>24)&255,
557
                                (unsigned int)(netip>>16)&255,
558
                                (unsigned int)(netip>>8)&255,
559
                                (unsigned int)(netip)&255);
560
 
561
                        size = sprintf(buffer+len,
562
                                "%-17s%-20s%02x:%02x:%02x:%02x:%02x:%02x\n",
563
                                ipbuffer,
564
                                "10Mbps Ethernet",
565
                                (unsigned int)entry->ha[0],
566
                                (unsigned int)entry->ha[1],
567
                                (unsigned int)entry->ha[2],
568
                                (unsigned int)entry->ha[3],
569
                                (unsigned int)entry->ha[4],
570
                                (unsigned int)entry->ha[5]);
571
 
572
                        len+=size;
573
                        pos=begin+len;
574
 
575
                        if(pos<offset)
576
                        {
577
                                len=0;
578
                                begin=pos;
579
                        }
580
                        if(pos>offset+length)
581
                                break;
582
                }
583
                sti();
584
        }
585
 
586
        *start = buffer+(offset-begin); /* Start of wanted data */
587
        len   -= (offset-begin);        /* Start slop */
588
        if (len>length)
589
                len = length;           /* Ending slop */
590
        return len;
591
}
592
 
593
#ifdef CONFIG_PROC_FS
594
static struct proc_dir_entry pde1 = {
595
                PROC_NET_RARP, 4, "rarp",
596
                S_IFREG | S_IRUGO, 1, 0, 0,
597
                0, &proc_net_inode_operations,
598
                rarp_get_info
599
        };
600
#endif
601
 
602
void
603
rarp_init(void)
604
{
605
#ifdef CONFIG_PROC_FS
606
        proc_net_register(&pde1);
607
#endif
608
        rarp_ioctl_hook = rarp_ioctl;
609
}
610
 
611
#ifdef MODULE
612
 
613
int init_module(void)
614
{
615
        rarp_init();
616
        return 0;
617
}
618
 
619
void cleanup_module(void)
620
{
621
        struct rarp_table *rt, *rt_next;
622
#ifdef CONFIG_PROC_FS
623
        proc_net_unregister(PROC_NET_RARP);
624
#endif
625
        rarp_ioctl_hook = NULL;
626
        cli();
627
        /* Destroy the RARP-table */
628
        rt = rarp_tables;
629
        rarp_tables = NULL;
630
        sti();
631
        /* ... and free it. */
632
        for ( ; rt != NULL; rt = rt_next) {
633
                rt_next = rt->next;
634
                rarp_release_entry(rt);
635
        }
636
        rarp_end_pkt();
637
}
638
#endif

powered by: WebSVN 2.1.0

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