root/net/ipv4/rarp.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rarp_release_entry
  2. rarp_destroy
  3. rarp_destroy_dev
  4. rarp_device_event
  5. rarp_init_pkt
  6. rarp_rcv
  7. rarp_req_set
  8. rarp_req_get
  9. rarp_ioctl
  10. rarp_get_info
  11. rarp_init
  12. init_module
  13. cleanup_module

   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  * 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  *
  32  */
  33 
  34 #include <linux/config.h>
  35 
  36 #ifdef MODULE
  37 #include <linux/module.h>
  38 #include <linux/version.h>
  39 #endif
  40 
  41 #include <linux/types.h>
  42 #include <linux/string.h>
  43 #include <linux/kernel.h>
  44 #include <linux/sched.h>
  45 #include <linux/mm.h>
  46 #include <linux/socket.h>
  47 #include <linux/sockios.h>
  48 #include <linux/errno.h>
  49 #include <linux/if_arp.h>
  50 #include <linux/in.h>
  51 #include <asm/system.h>
  52 #include <asm/segment.h>
  53 #include <stdarg.h>
  54 #include <linux/inet.h>
  55 #include <linux/netdevice.h>
  56 #include <linux/etherdevice.h>
  57 #include <net/ip.h>
  58 #include <net/route.h>
  59 #include <net/protocol.h>
  60 #include <net/tcp.h>
  61 #include <linux/skbuff.h>
  62 #include <net/sock.h>
  63 #include <net/arp.h>
  64 #include <net/rarp.h>
  65 #ifdef CONFIG_AX25
  66 #include <net/ax25.h>
  67 #endif
  68 #include <linux/proc_fs.h>
  69 
  70 #if     defined(CONFIG_INET_RARP) || defined(MODULE)
  71 
  72 extern 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 
  79 struct 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 
  89 struct rarp_table *rarp_tables = NULL;
  90 
  91 static int rarp_rcv(struct sk_buff *, struct device *, struct packet_type *);
  92 
  93 static 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 
 102 static initflag = 1;
 103 
 104 
 105 /*
 106  *      Release the memory for this entry.
 107  */
 108 
 109 static inline void rarp_release_entry(struct rarp_table *entry)
     /* [previous][next][first][last][top][bottom][index][help] */
 110 {
 111         kfree_s(entry, sizeof(struct rarp_table));
 112         return;
 113 }
 114 
 115 /*
 116  *      Delete a RARP mapping entry in the cache.
 117  */
 118 
 119 static void rarp_destroy(unsigned long ip_addr)
     /* [previous][next][first][last][top][bottom][index][help] */
 120 {
 121         struct rarp_table *entry;
 122         struct rarp_table **pentry;
 123   
 124         cli();
 125         pentry = &rarp_tables;
 126         while ((entry = *pentry) != NULL)
 127         {
 128                 if (entry->ip == ip_addr)
 129                 {
 130                         *pentry = entry->next;
 131                         sti();
 132                         rarp_release_entry(entry);
 133                         return;
 134                 }
 135                 pentry = &entry->next;
 136         }
 137         sti();
 138 }
 139 
 140 /*
 141  *      Flush a device.
 142  */
 143 
 144 static void rarp_destroy_dev(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 145 {
 146         struct rarp_table *entry;
 147         struct rarp_table **pentry;
 148   
 149         cli();
 150         pentry = &rarp_tables;
 151         while ((entry = *pentry) != NULL)
 152         {
 153                 if (entry->dev == dev)
 154                 {
 155                         *pentry = entry->next;
 156                         sti();
 157                         rarp_release_entry(entry);
 158                 }
 159                 else
 160                         pentry = &entry->next;
 161         }
 162         sti();
 163 }
 164 
 165 static int rarp_device_event(unsigned long event, void *ptr)
     /* [previous][next][first][last][top][bottom][index][help] */
 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  
 177 static struct notifier_block rarp_dev_notifier={
 178         rarp_device_event,
 179         NULL,
 180         0
 181 };
 182  
 183 static void rarp_init_pkt (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 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 }
 190 
 191 /*
 192  *      Receive an arp request by the device layer.  Maybe it should be 
 193  *      rewritten to use the incoming packet for the reply. The current 
 194  *      "overhead" time isn't that high...
 195  */
 196 
 197 static int rarp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
     /* [previous][next][first][last][top][bottom][index][help] */
 198 {
 199 /*
 200  *      We shouldn't use this type conversion. Check later.
 201  */
 202         struct arphdr *rarp = (struct arphdr *)skb_pull(skb,sizeof(struct arphdr));
 203         unsigned char *rarp_ptr = skb->data;
 204         struct rarp_table *entry;
 205         long sip,tip;
 206         unsigned char *sha,*tha;            /* s for "source", t for "target" */
 207         
 208 /*
 209  *      If this test doesn't pass, it's not IP, or we should ignore it anyway
 210  */
 211 
 212         if (rarp->ar_hln != dev->addr_len || dev->type != ntohs(rarp->ar_hrd) 
 213                 || dev->flags&IFF_NOARP)
 214         {
 215                 kfree_skb(skb, FREE_READ);
 216                 return 0;
 217         }
 218 
 219 /*
 220  *      If it's not a RARP request, delete it.
 221  */
 222         if (rarp->ar_op != htons(ARPOP_RREQUEST))
 223         {
 224                 kfree_skb(skb, FREE_READ);
 225                 return 0;
 226         }
 227 
 228 /*
 229  *      For now we will only deal with IP addresses.
 230  */
 231 
 232         if (
 233 #ifdef CONFIG_AX25
 234                 (rarp->ar_pro != htons(AX25_P_IP) && dev->type == ARPHRD_AX25) ||
 235 #endif
 236                 (rarp->ar_pro != htons(ETH_P_IP) && dev->type != ARPHRD_AX25)
 237                 || rarp->ar_pln != 4)
 238         {
 239                 /*
 240                  *      This packet is not for us. Remove it. 
 241                  */
 242                 kfree_skb(skb, FREE_READ);
 243                 return 0;
 244         }
 245   
 246 /*
 247  *      Extract variable width fields
 248  */
 249 
 250         sha=rarp_ptr;
 251         rarp_ptr+=dev->addr_len;
 252         memcpy(&sip,rarp_ptr,4);
 253         rarp_ptr+=4;
 254         tha=rarp_ptr;
 255         rarp_ptr+=dev->addr_len;
 256         memcpy(&tip,rarp_ptr,4);
 257 
 258 /*
 259  *      Process entry. Use tha for table lookup according to RFC903.
 260  */
 261   
 262         cli();
 263         for (entry = rarp_tables; entry != NULL; entry = entry->next)
 264                 if (!memcmp(entry->ha, tha, rarp->ar_hln))
 265                         break;
 266   
 267         if (entry != NULL)
 268         {
 269                 sip=entry->ip;
 270                 sti();
 271 
 272                 arp_send(ARPOP_RREPLY, ETH_P_RARP, sip, dev, dev->pa_addr, sha, 
 273                         dev->dev_addr);
 274         }
 275         else
 276                 sti();
 277 
 278         kfree_skb(skb, FREE_READ);
 279         return 0;
 280 }
 281 
 282 
 283 /*
 284  *      Set (create) a RARP cache entry.
 285  */
 286 
 287 static int rarp_req_set(struct arpreq *req)
     /* [previous][next][first][last][top][bottom][index][help] */
 288 {
 289         struct arpreq r;
 290         struct rarp_table *entry;
 291         struct sockaddr_in *si;
 292         int htype, hlen;
 293         unsigned long ip;
 294         struct rtable *rt;
 295   
 296         memcpy_fromfs(&r, req, sizeof(r));
 297   
 298         /*
 299          *      We only understand about IP addresses... 
 300          */
 301 
 302         if (r.arp_pa.sa_family != AF_INET)
 303                 return -EPFNOSUPPORT;
 304   
 305         switch (r.arp_ha.sa_family) 
 306         {
 307                 case ARPHRD_ETHER:
 308                         htype = ARPHRD_ETHER;
 309                         hlen = ETH_ALEN;
 310                         break;
 311 #ifdef CONFIG_AX25
 312                 case ARPHRD_AX25:
 313                         htype = ARPHRD_AX25;
 314                         hlen = 7;
 315                 break;
 316 #endif
 317                 default:
 318                         return -EPFNOSUPPORT;
 319         }
 320 
 321         si = (struct sockaddr_in *) &r.arp_pa;
 322         ip = si->sin_addr.s_addr;
 323         if (ip == 0)
 324         {
 325                 printk("RARP: SETRARP: requested PA is 0.0.0.0 !\n");
 326                 return -EINVAL;
 327         }
 328   
 329 /*
 330  *      Is it reachable directly ?
 331  */
 332   
 333         rt = ip_rt_route(ip, NULL, NULL);
 334         if (rt == NULL)
 335                 return -ENETUNREACH;
 336 
 337 /*
 338  *      Is there an existing entry for this address?  Find out...
 339  */
 340   
 341         cli();
 342         for (entry = rarp_tables; entry != NULL; entry = entry->next)
 343                 if (entry->ip == ip)
 344                         break;
 345   
 346 /*
 347  *      If no entry was found, create a new one.
 348  */
 349 
 350         if (entry == NULL)
 351         {
 352                 entry = (struct rarp_table *) kmalloc(sizeof(struct rarp_table),
 353                                     GFP_ATOMIC);
 354                 if (entry == NULL)
 355                 {
 356                         sti();
 357                         return -ENOMEM;
 358                 }
 359                 if (initflag)
 360                 {
 361                         rarp_init_pkt();
 362                         initflag=0;
 363                 }
 364 
 365                 entry->next = rarp_tables;
 366                 rarp_tables = entry;
 367         }
 368 
 369         entry->ip = ip;
 370         entry->hlen = hlen;
 371         entry->htype = htype;
 372         memcpy(&entry->ha, &r.arp_ha.sa_data, hlen);
 373         entry->dev = rt->rt_dev;
 374 
 375         sti();  
 376 
 377         return 0;
 378 }
 379 
 380 
 381 /*
 382  *        Get a RARP cache entry.
 383  */
 384 
 385 static int rarp_req_get(struct arpreq *req)
     /* [previous][next][first][last][top][bottom][index][help] */
 386 {
 387         struct arpreq r;
 388         struct rarp_table *entry;
 389         struct sockaddr_in *si;
 390         unsigned long ip;
 391 
 392 /*
 393  *      We only understand about IP addresses...
 394  */
 395         
 396         memcpy_fromfs(&r, req, sizeof(r));
 397   
 398         if (r.arp_pa.sa_family != AF_INET)
 399                 return -EPFNOSUPPORT;
 400   
 401 /*
 402  *        Is there an existing entry for this address?
 403  */
 404 
 405         si = (struct sockaddr_in *) &r.arp_pa;
 406         ip = si->sin_addr.s_addr;
 407 
 408         cli();
 409         for (entry = rarp_tables; entry != NULL; entry = entry->next)
 410                 if (entry->ip == ip)
 411                         break;
 412 
 413         if (entry == NULL)
 414         {
 415                 sti();
 416                 return -ENXIO;
 417         }
 418 
 419 /*
 420  *        We found it; copy into structure.
 421  */
 422         
 423         memcpy(r.arp_ha.sa_data, &entry->ha, entry->hlen);
 424         r.arp_ha.sa_family = entry->htype;
 425         sti();
 426   
 427 /*
 428  *        Copy the information back
 429  */
 430   
 431         memcpy_tofs(req, &r, sizeof(r));
 432         return 0;
 433 }
 434 
 435 
 436 /*
 437  *      Handle a RARP layer I/O control request.
 438  */
 439 
 440 int rarp_ioctl(unsigned int cmd, void *arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 441 {
 442         struct arpreq r;
 443         struct sockaddr_in *si;
 444         int err;
 445 
 446         switch(cmd)
 447         {
 448                 case SIOCDRARP:
 449                         if (!suser())
 450                                 return -EPERM;
 451                         err = verify_area(VERIFY_READ, arg, sizeof(struct arpreq));
 452                         if(err)
 453                                 return err;
 454                         memcpy_fromfs(&r, arg, sizeof(r));
 455                         if (r.arp_pa.sa_family != AF_INET)
 456                                 return -EPFNOSUPPORT;
 457                         si = (struct sockaddr_in *) &r.arp_pa;
 458                         rarp_destroy(si->sin_addr.s_addr);
 459                         return 0;
 460 
 461                 case SIOCGRARP:
 462                         err = verify_area(VERIFY_WRITE, arg, sizeof(struct arpreq));
 463                         if(err)
 464                                 return err;
 465                         return rarp_req_get((struct arpreq *)arg);
 466                 case SIOCSRARP:
 467                         if (!suser())
 468                                 return -EPERM;
 469                         err = verify_area(VERIFY_READ, arg, sizeof(struct arpreq));
 470                         if(err)
 471                                 return err;
 472                         return rarp_req_set((struct arpreq *)arg);
 473                 default:
 474                         return -EINVAL;
 475         }
 476 
 477         /*NOTREACHED*/
 478         return 0;
 479 }
 480 
 481 int rarp_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
     /* [previous][next][first][last][top][bottom][index][help] */
 482 {
 483         int len=0;
 484         off_t begin=0;
 485         off_t pos=0;
 486         int size;
 487         struct rarp_table *entry;
 488         char ipbuffer[20];
 489         unsigned long netip;
 490         if (initflag)
 491         {
 492                 size = sprintf(buffer,"RARP disabled until entries added to cache.\n");
 493                 pos+=size;
 494                 len+=size;
 495         }   
 496         else
 497         {
 498                 size = sprintf(buffer,
 499                         "IP address       HW type             HW address\n");
 500                 pos+=size;
 501                 len+=size;
 502       
 503                 cli();
 504                 for(entry=rarp_tables; entry!=NULL; entry=entry->next)
 505                 {
 506                         netip=htonl(entry->ip);          /* switch to network order */
 507                         sprintf(ipbuffer,"%d.%d.%d.%d",
 508                                 (unsigned int)(netip>>24)&255,
 509                                 (unsigned int)(netip>>16)&255,
 510                                 (unsigned int)(netip>>8)&255,
 511                                 (unsigned int)(netip)&255);
 512 
 513                         size = sprintf(buffer+len,
 514                                 "%-17s%-20s%02x:%02x:%02x:%02x:%02x:%02x\n",
 515                                 ipbuffer,
 516                                 "10Mbps Ethernet",
 517                                 (unsigned int)entry->ha[0],
 518                                 (unsigned int)entry->ha[1],
 519                                 (unsigned int)entry->ha[2],
 520                                 (unsigned int)entry->ha[3],
 521                                 (unsigned int)entry->ha[4],
 522                                 (unsigned int)entry->ha[5]);
 523           
 524                         len+=size;
 525                         pos=begin+len;
 526           
 527                         if(pos<offset)
 528                         {
 529                                 len=0;
 530                                 begin=pos;
 531                         }
 532                         if(pos>offset+length)
 533                                 break;
 534                 }
 535                 sti();
 536         }      
 537 
 538         *start = buffer+(offset-begin); /* Start of wanted data */
 539         len   -= (offset-begin);        /* Start slop */
 540         if (len>length)
 541                 len = length;           /* Ending slop */
 542         return len;
 543 }
 544 
 545 void
 546 rarp_init(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 547 {
 548         proc_net_register(&(struct proc_dir_entry)
 549                           { PROC_NET_RARP, rarp_get_info, 4, "rarp"});
 550         rarp_ioctl_hook = rarp_ioctl;
 551 }
 552 
 553 
 554 #endif
 555 #ifdef MODULE
 556 char kernel_version[] = UTS_RELEASE;
 557 
 558 int init_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 559 {
 560         rarp_init();
 561         return 0;
 562 }
 563 
 564 void cleanup_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 565 {
 566         if (MOD_IN_USE)
 567           ;
 568         else {
 569                 struct rarp_table *rt, *rt_next;
 570                 proc_net_unregister(PROC_NET_RARP);
 571                 rarp_ioctl_hook = NULL;
 572                 cli();
 573                 /* Destroy the RARP-table */
 574                 rt = rarp_tables;
 575                 rarp_tables = NULL;
 576                 sti();
 577                 /* ... and free it. */
 578                 for ( ; rt != NULL; rt = rt_next) {
 579                         rt_next = rt->next;
 580                         rarp_release_entry(rt);
 581                 }
 582         }
 583 }
 584 
 585 #endif

/* [previous][next][first][last][top][bottom][index][help] */