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