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

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