home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.2 / LINUX-1.2 / LINUX-1 / linux / net / inet / rarp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-06  |  9.8 KB  |  492 lines

  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)
  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)
  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)
  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)
  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, it's 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)
  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)
  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)
  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)
  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
  492.