root/net/inet/rarp.c

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

DEFINITIONS

This source file includes following definitions.
  1. rarp_init
  2. rarp_release_entry
  3. rarp_destroy
  4. rarp_rcv
  5. rarp_req_set
  6. rarp_req_get
  7. rarp_ioctl
  8. rarp_get_info

   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  */
  29 
  30 #include <linux/types.h>
  31 #include <linux/string.h>
  32 #include <linux/kernel.h>
  33 #include <linux/sched.h>
  34 #include <linux/mm.h>
  35 #include <linux/config.h>
  36 #include <linux/socket.h>
  37 #include <linux/sockios.h>
  38 #include <linux/errno.h>
  39 #include <linux/if_arp.h>
  40 #include <linux/in.h>
  41 #include <asm/system.h>
  42 #include <asm/segment.h>
  43 #include <stdarg.h>
  44 #include <linux/inet.h>
  45 #include <linux/netdevice.h>
  46 #include <linux/etherdevice.h>
  47 #include "ip.h"
  48 #include "route.h"
  49 #include "protocol.h"
  50 #include "tcp.h"
  51 #include <linux/skbuff.h>
  52 #include "sock.h"
  53 #include "arp.h"
  54 #include "rarp.h"
  55 #ifdef CONFIG_AX25
  56 #include "ax25.h"
  57 #endif
  58 
  59 #ifdef CONFIG_INET_RARP
  60 
  61 /*
  62  *      This structure defines the RARP mapping cache. As long as we make 
  63  *      changes in this structure, we keep interrupts off.
  64  */
  65 
  66 struct rarp_table
  67 {
  68         struct rarp_table  *next;             /* Linked entry list           */
  69         unsigned long      ip;                /* ip address of entry         */
  70         unsigned char      ha[MAX_ADDR_LEN];  /* Hardware address            */
  71         unsigned char      hlen;              /* Length of hardware address  */
  72         unsigned char      htype;             /* Type of hardware in use     */
  73         struct device      *dev;              /* Device the entry is tied to */
  74 };
  75 
  76 struct rarp_table *rarp_tables = NULL;
  77 
  78 
  79 static struct packet_type rarp_packet_type =
  80 {
  81         0,  /* Should be: __constant_htons(ETH_P_RARP) - but this _doesn't_ come out constant! */
  82         0,                /* copy */
  83         rarp_rcv,
  84         NULL,
  85         NULL
  86 };
  87 
  88 static initflag = 1;
  89 
  90 /*
  91  *      Called once when data first added to rarp cache with ioctl.
  92  */
  93 
  94 static void rarp_init (void)
     /* [previous][next][first][last][top][bottom][index][help] */
  95 {
  96         /* Register the packet type */
  97         rarp_packet_type.type=htons(ETH_P_RARP);
  98         dev_add_pack(&rarp_packet_type);
  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         return;
 109 }
 110 
 111 /*
 112  *      Delete a RARP mapping entry in the cache.
 113  */
 114 
 115 static void rarp_destroy(unsigned long ip_addr)
     /* [previous][next][first][last][top][bottom][index][help] */
 116 {
 117         struct rarp_table *entry;
 118         struct rarp_table **pentry;
 119   
 120         cli();
 121         pentry = &rarp_tables;
 122         while ((entry = *pentry) != NULL)
 123         {
 124                 if (entry->ip == ip_addr)
 125                 {
 126                         *pentry = entry->next;
 127                         sti();
 128                         rarp_release_entry(entry);
 129                         return;
 130                 }
 131                 pentry = &entry->next;
 132         }
 133         sti();
 134 }
 135 
 136 
 137 /*
 138  *      Receive an arp request by the device layer.  Maybe it should be 
 139  *      rewritten to use the incoming packet for the reply. The current 
 140  *      "overhead" time isn't that high...
 141  */
 142 
 143 int rarp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
     /* [previous][next][first][last][top][bottom][index][help] */
 144 {
 145 /*
 146  *      We shouldn't use this type conversion. Check later.
 147  */
 148         struct arphdr *rarp = (struct arphdr *)skb->h.raw;
 149         unsigned char *rarp_ptr = (unsigned char *)(rarp+1);
 150         struct rarp_table *entry;
 151         long sip,tip;
 152         unsigned char *sha,*tha;            /* s for "source", t for "target" */
 153   
 154 /*
 155  *      If this test doesn't pass, its not IP, or we should ignore it anyway
 156  */
 157 
 158         if (rarp->ar_hln != dev->addr_len || dev->type != ntohs(rarp->ar_hrd) 
 159                 || dev->flags&IFF_NOARP)
 160         {
 161                 kfree_skb(skb, FREE_READ);
 162                 return 0;
 163         }
 164 
 165 /*
 166  *      If it's not a RARP request, delete it.
 167  */
 168         if (rarp->ar_op != htons(ARPOP_RREQUEST))
 169         {
 170                 kfree_skb(skb, FREE_READ);
 171                 return 0;
 172         }
 173 
 174 /*
 175  *      For now we will only deal with IP addresses.
 176  */
 177 
 178         if (
 179 #ifdef CONFIG_AX25
 180                 (rarp->ar_pro != htons(AX25_P_IP) && dev->type == ARPHRD_AX25) ||
 181 #endif
 182                 (rarp->ar_pro != htons(ETH_P_IP) && dev->type != ARPHRD_AX25)
 183                 || rarp->ar_pln != 4)
 184         {
 185         /*
 186          *      This packet is not for us. Remove it. 
 187          */
 188         kfree_skb(skb, FREE_READ);
 189         return 0;
 190 }
 191   
 192 /*
 193  *      Extract variable width fields
 194  */
 195 
 196         sha=rarp_ptr;
 197         rarp_ptr+=dev->addr_len;
 198         memcpy(&sip,rarp_ptr,4);
 199         rarp_ptr+=4;
 200         tha=rarp_ptr;
 201         rarp_ptr+=dev->addr_len;
 202         memcpy(&tip,rarp_ptr,4);
 203 
 204 /*
 205  *      Process entry. Use tha for table lookup according to RFC903.
 206  */
 207   
 208         cli();
 209         for (entry = rarp_tables; entry != NULL; entry = entry->next)
 210                 if (!memcmp(entry->ha, tha, rarp->ar_hln))
 211                         break;
 212   
 213         if (entry != NULL)
 214         {
 215                 sip=entry->ip;
 216                 sti();
 217 
 218                 arp_send(ARPOP_RREPLY, ETH_P_RARP, sip, dev, dev->pa_addr, sha, 
 219                         dev->dev_addr);
 220         }
 221         else
 222                 sti();
 223 
 224         kfree_skb(skb, FREE_READ);
 225         return 0;
 226 }
 227 
 228 
 229 /*
 230  *      Set (create) a RARP cache entry.
 231  */
 232 
 233 static int rarp_req_set(struct arpreq *req)
     /* [previous][next][first][last][top][bottom][index][help] */
 234 {
 235         struct arpreq r;
 236         struct rarp_table *entry;
 237         struct sockaddr_in *si;
 238         int htype, hlen;
 239         unsigned long ip;
 240         struct rtable *rt;
 241   
 242         memcpy_fromfs(&r, req, sizeof(r));
 243   
 244         /*
 245          *      We only understand about IP addresses... 
 246          */
 247 
 248         if (r.arp_pa.sa_family != AF_INET)
 249                 return -EPFNOSUPPORT;
 250   
 251         switch (r.arp_ha.sa_family) 
 252         {
 253                 case ARPHRD_ETHER:
 254                         htype = ARPHRD_ETHER;
 255                         hlen = ETH_ALEN;
 256                         break;
 257 #ifdef CONFIG_AX25
 258                 case ARPHRD_AX25:
 259                         htype = ARPHRD_AX25;
 260                         hlen = 7;
 261                 break;
 262 #endif
 263                 default:
 264                         return -EPFNOSUPPORT;
 265         }
 266 
 267         si = (struct sockaddr_in *) &r.arp_pa;
 268         ip = si->sin_addr.s_addr;
 269         if (ip == 0)
 270         {
 271                 printk("RARP: SETRARP: requested PA is 0.0.0.0 !\n");
 272                 return -EINVAL;
 273         }
 274   
 275 /*
 276  *      Is it reachable directly ?
 277  */
 278   
 279         rt = ip_rt_route(ip, NULL, NULL);
 280         if (rt == NULL)
 281                 return -ENETUNREACH;
 282 
 283 /*
 284  *      Is there an existing entry for this address?  Find out...
 285  */
 286   
 287         cli();
 288         for (entry = rarp_tables; entry != NULL; entry = entry->next)
 289                 if (entry->ip == ip)
 290                         break;
 291   
 292 /*
 293  *      If no entry was found, create a new one.
 294  */
 295 
 296         if (entry == NULL)
 297         {
 298                 entry = (struct rarp_table *) kmalloc(sizeof(struct rarp_table),
 299                                     GFP_ATOMIC);
 300                 if (entry == NULL)
 301                 {
 302                         sti();
 303                         return -ENOMEM;
 304                 }
 305                 if(initflag)
 306                 {
 307                         rarp_init();
 308                         initflag=0;
 309                 }
 310 
 311                 entry->next = rarp_tables;
 312                 rarp_tables = entry;
 313         }
 314 
 315         entry->ip = ip;
 316         entry->hlen = hlen;
 317         entry->htype = htype;
 318         memcpy(&entry->ha, &r.arp_ha.sa_data, hlen);
 319         entry->dev = rt->rt_dev;
 320 
 321         sti();  
 322 
 323         return 0;
 324 }
 325 
 326 
 327 /*
 328  *        Get a RARP cache entry.
 329  */
 330 
 331 static int rarp_req_get(struct arpreq *req)
     /* [previous][next][first][last][top][bottom][index][help] */
 332 {
 333         struct arpreq r;
 334         struct rarp_table *entry;
 335         struct sockaddr_in *si;
 336         unsigned long ip;
 337 
 338 /*
 339  *      We only understand about IP addresses...
 340  */
 341         
 342         memcpy_fromfs(&r, req, sizeof(r));
 343   
 344         if (r.arp_pa.sa_family != AF_INET)
 345                 return -EPFNOSUPPORT;
 346   
 347 /*
 348  *        Is there an existing entry for this address?
 349  */
 350 
 351         si = (struct sockaddr_in *) &r.arp_pa;
 352         ip = si->sin_addr.s_addr;
 353 
 354         cli();
 355         for (entry = rarp_tables; entry != NULL; entry = entry->next)
 356                 if (entry->ip == ip)
 357                         break;
 358 
 359         if (entry == NULL)
 360         {
 361                 sti();
 362                 return -ENXIO;
 363         }
 364 
 365 /*
 366  *        We found it; copy into structure.
 367  */
 368         
 369         memcpy(r.arp_ha.sa_data, &entry->ha, entry->hlen);
 370         r.arp_ha.sa_family = entry->htype;
 371         sti();
 372   
 373 /*
 374  *        Copy the information back
 375  */
 376   
 377         memcpy_tofs(req, &r, sizeof(r));
 378         return 0;
 379 }
 380 
 381 
 382 /*
 383  *      Handle a RARP layer I/O control request.
 384  */
 385 
 386 int rarp_ioctl(unsigned int cmd, void *arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 387 {
 388         struct arpreq r;
 389         struct sockaddr_in *si;
 390         int err;
 391 
 392         switch(cmd)
 393         {
 394                 case SIOCDRARP:
 395                         if (!suser())
 396                                 return -EPERM;
 397                         err = verify_area(VERIFY_READ, arg, sizeof(struct arpreq));
 398                         if(err)
 399                                 return err;
 400                         memcpy_fromfs(&r, arg, sizeof(r));
 401                         if (r.arp_pa.sa_family != AF_INET)
 402                                 return -EPFNOSUPPORT;
 403                         si = (struct sockaddr_in *) &r.arp_pa;
 404                         rarp_destroy(si->sin_addr.s_addr);
 405                         return 0;
 406 
 407                 case SIOCGRARP:
 408                         err = verify_area(VERIFY_WRITE, arg, sizeof(struct arpreq));
 409                         if(err)
 410                                 return err;
 411                         return rarp_req_get((struct arpreq *)arg);
 412                 case SIOCSRARP:
 413                         if (!suser())
 414                                 return -EPERM;
 415                         err = verify_area(VERIFY_READ, arg, sizeof(struct arpreq));
 416                         if(err)
 417                                 return err;
 418                         return rarp_req_set((struct arpreq *)arg);
 419                 default:
 420                         return -EINVAL;
 421         }
 422 
 423         /*NOTREACHED*/
 424         return 0;
 425 }
 426 
 427 int rarp_get_info(char *buffer, char **start, off_t offset, int length)
     /* [previous][next][first][last][top][bottom][index][help] */
 428 {
 429         int len=0;
 430         off_t begin=0;
 431         off_t pos=0;
 432         int size;
 433         struct rarp_table *entry;
 434         char ipbuffer[20];
 435         unsigned long netip;
 436         if(initflag)
 437         {
 438                 size = sprintf(buffer,"RARP disabled until entries added to cache.\n");
 439                 pos+=size;
 440                 len+=size;
 441         }   
 442         else
 443         {
 444                 size = sprintf(buffer,
 445                         "IP address       HW type             HW address\n");
 446                 pos+=size;
 447                 len+=size;
 448       
 449                 cli();
 450                 for(entry=rarp_tables; entry!=NULL; entry=entry->next)
 451                 {
 452                         netip=htonl(entry->ip);          /* switch to network order */
 453                         sprintf(ipbuffer,"%d.%d.%d.%d",
 454                                 (unsigned int)(netip>>24)&255,
 455                                 (unsigned int)(netip>>16)&255,
 456                                 (unsigned int)(netip>>8)&255,
 457                                 (unsigned int)(netip)&255);
 458 
 459                         size = sprintf(buffer+len,
 460                                 "%-17s%-20s%02x:%02x:%02x:%02x:%02x:%02x\n",
 461                                 ipbuffer,
 462                                 "10Mbps Ethernet",
 463                                 (unsigned int)entry->ha[0],
 464                                 (unsigned int)entry->ha[1],
 465                                 (unsigned int)entry->ha[2],
 466                                 (unsigned int)entry->ha[3],
 467                                 (unsigned int)entry->ha[4],
 468                                 (unsigned int)entry->ha[5]);
 469           
 470                         len+=size;
 471                         pos=begin+len;
 472           
 473                         if(pos<offset)
 474                         {
 475                                 len=0;
 476                                 begin=pos;
 477                         }
 478                         if(pos>offset+length)
 479                                 break;
 480                 }
 481                 sti();
 482         }      
 483 
 484         *start=buffer+(offset-begin);   /* Start of wanted data */
 485         len-=(offset-begin);            /* Start slop */
 486         if(len>length)
 487                 len=length;                     /* Ending slop */
 488         return len;
 489 }
 490 
 491 #endif

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