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

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