home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / N / TCPIP / NET-TOOL.1 / NET-TOOL / net-tools / rarp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-07-18  |  5.2 KB  |  264 lines

  1. /*
  2.  * rarp        This file contains an implementation of the command
  3.  *        that maintains the kernel's RARP cache.  It is derived
  4.  *              from Fred N. van Kempen's arp command.
  5.  *
  6.  * Usage:       rarp -d hostname                      Delete entry
  7.  *        rarp -s hostname ethernet_address     Add entry
  8.  *              rarp -a                               Print entries
  9.  *
  10.  *  Ross D. Martin  <martin@trcsun3.eas.asu.edu>
  11.  */
  12. #include <sys/types.h>
  13. #include <sys/socket.h>
  14. #include <sys/ioctl.h>
  15. #include <arpa/inet.h>
  16. #include <netinet/in.h>
  17. #include <net/if.h>
  18. #include <stdlib.h>
  19. #include <stdio.h>
  20. #include <errno.h>
  21. #include <fcntl.h>
  22. #include <netdb.h>
  23. #include <string.h>
  24. #include <unistd.h>
  25.  
  26. int sockfd;                /* active socket descriptor    */
  27.  
  28. /* Input an Ethernet address and convert to binary. */
  29. unsigned char *in_ether(char *ptr)
  30. {
  31.   static unsigned char buff[6];
  32.   unsigned int temp[6];
  33.   int num;
  34.  
  35.   num=sscanf(ptr,"%x:%x:%x:%x:%x:%x",
  36.          &temp[0],&temp[1],&temp[2],&temp[3],&temp[4],&temp[5]);
  37.   if(num!=6)
  38.     {
  39.       fprintf(stderr,"Invalid Ethernet address: %s\n",ptr);
  40.     }
  41.   
  42.   for(num=0;num<6;num++)
  43.     buff[num]=temp[num];
  44.  
  45.   return(buff);
  46. }
  47.  
  48.  
  49. /* This structure defines hardware protocols and their handlers. */
  50. struct hwtype {
  51.   char        *name;
  52.   int        type;
  53.   int        hlen;
  54.   unsigned char    *(*input)(char *);
  55. };
  56.  
  57. struct hwtype hwtypes[] = {
  58.   { "ether",  ARPHRD_ETHER,  6, in_ether  },
  59. #ifdef HAVE_ARPHRD_PRONET
  60.   { "pronet", ARPHRD_PRONET, 2, in_pronet },
  61. #endif
  62. #ifdef HAVE_ARPHRD_AX25
  63.   { "ax25",   ARPHRD_AX25,  12, in_ax25   },
  64. #endif
  65.   { NULL,     -1,            0, NULL      }
  66. };
  67.  
  68. struct hwtype *hardware;
  69.  
  70. /* Check our hardware type table for this type. */
  71. struct hwtype *get_type(char *name)
  72. {
  73.   register struct hwtype *hwp;
  74.  
  75.   hwp = hwtypes;
  76.   while (hwp->name != NULL) {
  77.     if (!strcmp(hwp->name, name)) return(hwp);
  78.     hwp++;
  79.   }
  80.   return(NULL);
  81. }
  82.  
  83.  
  84. /* Check our hardware type table for this type. */
  85. struct hwtype *get_ntype(int type)
  86. {
  87.   register struct hwtype *hwp;
  88.  
  89.   hwp = hwtypes;
  90.   while (hwp->name != NULL) {
  91.     if (hwp->type == type) return(hwp);
  92.     hwp++;
  93.   }
  94.   return(NULL);
  95. }
  96.  
  97.  
  98. /* Delete an entry from the ARP cache. */
  99. int arp_del(char *host)
  100. {
  101.   struct hostent *hp;
  102.   struct arpreq req;
  103.   struct sockaddr_in *si;
  104.   register int i;
  105.   int found;
  106.  
  107.   /* Resolve the host name. */
  108.   if ((hp = gethostbyname(host)) == NULL) {
  109.     fprintf(stderr, "rarp: %s: unknown host\n", host);
  110.     return(-1);
  111.   }
  112.  
  113.   /* The host can have more than one address, so we loop on them. */
  114.   i = -1;
  115.   found = 0;
  116.   while (hp->h_addr_list[++i] != NULL) {
  117.     memset((char *) &req, 0, sizeof(req));
  118.     si = (struct sockaddr_in *) &req.arp_pa;
  119.     si->sin_family = hp->h_addrtype;
  120.     memcpy((char *) &si->sin_addr, hp->h_addr_list[i], hp->h_length);
  121.  
  122.     /* Call the kernel. */
  123.     if (ioctl(sockfd, SIOCDRARP, &req) < 0) {
  124.         if (errno != ENXIO) {
  125.             perror("SIOCDRARP");
  126.             return(-1);
  127.         } else continue;
  128.     }
  129.     found++;
  130.   }
  131.  
  132.   if (found == 0) printf("No ARP entry for %s\n", hp->h_name);
  133.   return(0);
  134. }
  135.  
  136.  
  137. /* Set an entry in the ARP cache. */
  138. int arp_set(char *host, char *hw_addr)
  139. {
  140.   struct hostent *hp;
  141.   struct arpreq req;
  142.   struct sockaddr_in *si;
  143.   unsigned char *ha;
  144.  
  145.   /* Resolve the host name. */
  146.   if ((hp = gethostbyname(host)) == NULL) {
  147.     fprintf(stderr, "rarp: %s: unknown host\n", host);
  148.     return(-1);
  149.   }
  150.  
  151.   if ((ha = hardware->input(hw_addr)) == NULL) return(-1);
  152.  
  153.   /* Clear and fill in the request block. */
  154.   memset((char *) &req, 0, sizeof(req));
  155.   si = (struct sockaddr_in *) &req.arp_pa;
  156.   si->sin_family = hp->h_addrtype;
  157.   memcpy((char *) &si->sin_addr, hp->h_addr_list[0], hp->h_length);
  158.   req.arp_ha.sa_family = hardware->type;
  159.   memcpy(req.arp_ha.sa_data, ha, hardware->hlen);
  160.  
  161.   /* Call the kernel. */
  162.   if (ioctl(sockfd, SIOCSRARP, &req) < 0) {
  163.     perror("SIOCSRARP");
  164.     return(-1);
  165.   }
  166.   return(0);
  167. }
  168.  
  169.  
  170. static void usage(void)
  171. {
  172.   fprintf(stderr, 
  173.       "Usage: rarp -a                   List Entries in cache.     \n");
  174.   fprintf(stderr, 
  175.       "       rarp -d hostname          Delete hostname from cache.\n");
  176.   fprintf(stderr, 
  177.       "       rarp -s hostname hw_addr  Add hostname to cache.\n");
  178.   exit(-1);
  179. }
  180.  
  181.  
  182. void main(argc, argv)
  183. int argc;
  184. char **argv;
  185. {
  186.   int result=0;
  187.  
  188.   /* Initialize variables... */
  189.   hardware = get_type("ether");
  190.  
  191.   argv++;
  192.   argc--;
  193.   if(argc==0)
  194.     usage();
  195.  
  196.  /* Fetch the command-line arguments. */
  197.  
  198.   if(argv[0][0]!='-')
  199.     usage();
  200.  
  201.   if(argv[0][1]=='t')
  202.     {
  203.       if(argc<3)  /* Need -t, type, and then at least one further arg */
  204.     usage();
  205.       
  206.       hardware = get_type(argv[1]);
  207.       if (hardware->type == -1) 
  208.     {
  209.       fprintf(stderr,
  210.           "rarp: %s: unknown hardware type.\n", optarg);
  211.       exit(-1);
  212.     }
  213.       argv+=2;
  214.       argc-=2;
  215.  
  216.       if(argv[0][0]!='-')
  217.     usage();
  218.     }
  219.  
  220.   switch(argv[0][1]) 
  221.     {
  222.     case 'a':
  223.       if(argc!=1)
  224.     usage();
  225.       result=system("cat /proc/net/rarp");  /* This is lazy, but who cares? */
  226.       break;
  227.  
  228.     case 'd':
  229.       if(argc!=2)
  230.     usage();
  231.  
  232.       if ((sockfd = socket(AF_INET,SOCK_DGRAM,0)) <0)
  233.     {
  234.       perror("socket");
  235.       exit(-1);
  236.     }
  237.  
  238.       result = arp_del(argv[1]);
  239.  
  240.       (void) close(sockfd);
  241.       break;
  242.  
  243.     case 's':
  244.       if(argc!=3)
  245.     usage();
  246.  
  247.       if ((sockfd = socket(AF_INET,SOCK_DGRAM,0)) <0)
  248.     {
  249.       perror("socket");
  250.       exit(-1);
  251.     }
  252.       result = arp_set(argv[1],argv[2]);
  253.  
  254.       (void) close(sockfd);
  255.       break;
  256.  
  257.     default:
  258.       usage();
  259.   }
  260.  
  261.   exit(result);
  262. }
  263.  
  264.