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

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