home *** CD-ROM | disk | FTP | other *** search
/ PC-Online 1996 May / PCOnline_05_1996.bin / linux / source / n / tcpip / netkit-a.06 / netkit-a / NetKit-A-0.06 / net-tools-1.1.38 / arp.c next >
Encoding:
C/C++ Source or Header  |  1994-08-17  |  9.4 KB  |  442 lines

  1.  
  2. /*
  3.  * arp        This file contains an implementation of the command
  4.  *        that maintains the kernel's ARP cache.  It is derived
  5.  *        from Berkeley UNIX arp(8), but cleaner and with sup-
  6.  *        port for devices other than Ethernet.
  7.  *
  8.  * Usage:    arp [-vn] [-p proto] [-t type] -a [hostname]
  9.  *        arp [-v] [-p proto] -d hostname ...
  10.  *        arp [-v] [-p proto] [-t type] -s hostname hw_addr
  11.  *                        [temp|pub|rarp|trail]
  12.  *        arp [-vn] -f filename
  13.  *
  14.  * Version:    @(#)arp.c    1.50    01/20/94
  15.  *
  16.  * Author:     Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
  17.  *
  18.  * Modified for NET3 by Alan Cox.
  19.  */
  20. #include <sys/types.h>
  21. #include <sys/socket.h>
  22. #include <sys/ioctl.h>
  23. #include <net/if.h>
  24. #include <stdlib.h>
  25. #include <stdio.h>
  26. #include <errno.h>
  27. #include <ctype.h>
  28. #include <fcntl.h>
  29. #include <string.h>
  30. #include <unistd.h>
  31. #include "support.h"
  32. #include "pathnames.h"
  33. #include "version.h"
  34.  
  35.  
  36. #define DFLT_AF    "inet"
  37. #define DFLT_HW    "ether"
  38.  
  39.  
  40. char *Release = RELEASE,
  41.      *Version = "@(#) arp 1.50 (01/20/94)";
  42.  
  43.  
  44. int opt_n = 0;                /* do not resolve addresses    */
  45. int opt_v = 0;                /* debugging output flag    */
  46. struct aftype *ap;            /* current address family    */
  47. struct hwtype *hw;            /* current hardware type    */
  48. int skfd;                /* active /proc  descriptor    */
  49. int sockfd;                /* active socket descriptor     */
  50.  
  51.  
  52. /* Delete an entry from the ARP cache. */
  53. static int
  54. arp_del(char **args)
  55. {
  56.   char host[128];
  57.   struct arpreq req;
  58.   struct sockaddr sa;
  59.  
  60.   /* Resolve the host name. */
  61.   if (*args == NULL) {
  62.     fprintf(stderr, "arp: need host name\n");
  63.     return(-1);
  64.   }
  65.   strcpy(host, *args);
  66.   if (ap->input(host, &sa) < 0) {
  67.     ap->herror(host);
  68.     return(-1);
  69.   }
  70.  
  71.   /* If a host has more than one address, use the correct one! */
  72.   memcpy((char *) &req.arp_pa, (char *) &sa, sizeof(struct sockaddr));
  73.  
  74.   /* Call the kernel. */
  75.   if (ioctl(sockfd, SIOCDARP, &req) < 0) {
  76.     if (errno != ENXIO) {
  77.         perror("SIOCDARP");
  78.         return(-1);
  79.     } else printf("No ARP entry for %s\n", host);
  80.   }
  81.  
  82.   return(0);
  83. }
  84.  
  85.  
  86. /* Set an entry in the ARP cache. */
  87. static int
  88. arp_set(char **args)
  89. {
  90.   char host[128];
  91.   struct arpreq req;
  92.   struct sockaddr sa;
  93.   int flags;
  94.  
  95.   /* Resolve the host name. */
  96.   if (*args == NULL) {
  97.     fprintf(stderr, "arp: need host name\n");
  98.     return(-1);
  99.   }
  100.   strcpy(host, *args++);
  101.   if (ap->input(host, &sa) < 0) {
  102.     ap->herror(host);
  103.     return(-1);
  104.   }
  105.  
  106.   /* If a host has more than one address, use the correct one! */
  107.   memcpy((char *) &req.arp_pa, (char *) &sa, sizeof(struct sockaddr));
  108.  
  109.   /* Fetch the hardware address. */
  110.   if (*args == NULL) {
  111.     fprintf(stderr, "arp: need hardware address\n");
  112.     return(-1);
  113.   }
  114.   if (hw->input(*args++, &req.arp_ha) < 0) {
  115.     fprintf(stderr, "arp: invalid hardware address\n");
  116.     return(-1);
  117.   }
  118.  
  119.   /* Check out any modifiers. */
  120.   flags = ATF_PERM;
  121.   while (*args != NULL) {
  122.     if (! strcmp(*args, "temp")) flags &= ~ATF_PERM;
  123.     if (! strcmp(*args, "pub")) flags |= ATF_PUBL;
  124. /*    if (! strcmp(*args, "rarp")) flags |= ATF_RARP;*/
  125.     if (! strcmp(*args, "trail")) flags |= ATF_USETRAILERS;
  126.     args++;
  127.   }
  128.  
  129.   /* Fill in the remainder of the request. */
  130.   req.arp_flags = flags;
  131.  
  132.   /* Call the kernel. */
  133.   if (ioctl(sockfd, SIOCSARP, &req) < 0) {
  134.     perror("SIOCSARP");
  135.     return(-1);
  136.   }
  137.   return(0);
  138. }
  139.  
  140.  
  141. /* Process an EtherFile */
  142. static int
  143. arp_file(char *name)
  144. {
  145.   char buff[1024];
  146.   char *sp, *args[32];
  147.   int linenr, argc;
  148.   FILE *fp;
  149.  
  150.   if ((fp = fopen(name, "r")) == NULL) {
  151.     fprintf(stderr, "arp: cannot open etherfile %s !\n", name);
  152.     return(-1);
  153.   }
  154.  
  155.   /* Read the lines in the file. */
  156.   linenr = 0;
  157.   while (fgets(buff, sizeof(buff), fp) != (char *)NULL) {
  158.     linenr++;
  159.     if (opt_v == 1) fprintf(stderr, ">> %s", buff);
  160.     if ((sp = strchr(buff, '\n')) != (char *)NULL) *sp = '\0';
  161.     if (buff[0] == '#' || buff[0] == '\0') continue;
  162.  
  163.     argc = getargs(buff, args);
  164.     if (argc < 2) {
  165.         fprintf(stderr,
  166.             "arp: format error on line %u of etherfile %s !\n",
  167.                             linenr, name);
  168.         continue;
  169.     }
  170.  
  171.     if (arp_set(args) != 0) {
  172.         fprintf(stderr,
  173.             "arp: cannot set entry on line %u of etherfile %s !\n",
  174.                             linenr, name);
  175.     }
  176.   }
  177.  
  178.   (void) fclose(fp);
  179.   return(0);
  180. }
  181.  
  182.  
  183. /* Print the contents of an ARP request block. */
  184. static void
  185. arp_disp(struct arpreq *req)
  186. {
  187.   static int title = 0;
  188.   struct hwtype *xhw;
  189.   struct aftype *xap;
  190.   char *sp, flags[6];
  191.  
  192.   /* Fetch the hardware type, which was given by the kernel. */
  193.   if(req->arp_ha.sa_family==0)
  194.       req->arp_ha.sa_family=ARPHRD_ETHER;
  195.   xhw = get_hwntype(req->arp_ha.sa_family);
  196.   if (xhw == NULL) xhw = get_hwtype("ether");
  197.   xap = get_afntype(req->arp_pa.sa_family);
  198.   if (xap == NULL) xap = get_aftype("inet");
  199.   
  200.   if (title++ == 0) printf("Address\t\t\tHW type\t\tHW address\t\tFlags\n");
  201.  
  202.   /* Setup the flags. */
  203.   flags[0] = '\0';
  204.   if (req->arp_flags & ATF_COM) strcat(flags, "C");
  205.   if (req->arp_flags & ATF_PERM) strcat(flags, "M");
  206.   if (req->arp_flags & ATF_PUBL) strcat(flags, "P");
  207. /*  if (req->arp_flags & ATF_RARP) strcat(flags, "R");*/
  208.   if (req->arp_flags & ATF_USETRAILERS) strcat(flags, "T");
  209.  
  210.   sp = xap->print(req->arp_pa.sa_data/*, opt_n*/);
  211.   printf("%-23.23s\t%-16.16s", sp, xhw->title);
  212.   printf("%-21.21s\t%-6s\n", xhw->sprint(&req->arp_ha), flags);
  213. }
  214.  
  215.  
  216. /* Print the contents of an ARP request block. */
  217. static void
  218. arp_disp_2(char *ip,int type,int arp_flags,char *hw)
  219. {
  220.   static int title = 0;
  221.   struct hwtype *xhw;
  222.   struct aftype *xap;
  223. /*  char *sp; */ 
  224.   char flags[6];
  225.  
  226.   xhw = get_hwntype(type);
  227.   if (xhw == NULL) 
  228.     xhw = get_hwtype("ether");
  229. /*
  230.  * xap = get_afntype(req->arp_pa.sa_family);
  231.  * if (xap == NULL) 
  232.  */
  233.   xap = get_aftype("inet");
  234.   
  235.   if (title++ == 0) 
  236.     printf("Address\t\t\tHW type\t\tHW address\t\tFlags\n");
  237.  
  238.   /* Setup the flags. */
  239.   flags[0] = '\0';
  240.   if (arp_flags & ATF_COM) strcat(flags, "C");
  241.   if (arp_flags & ATF_PERM) strcat(flags, "M");
  242.   if (arp_flags & ATF_PUBL) strcat(flags, "P");
  243. /*  if (arp_flags & ATF_RARP) strcat(flags, "R");*/
  244.   if (arp_flags & ATF_USETRAILERS) strcat(flags, "T");
  245.  
  246. #ifdef NOTDEF
  247.   sp = xap->print(req->arp_pa.sa_data/*, opt_n*/);
  248. #endif
  249.   printf("%-23.23s\t%-16.16s", ip /* sp */, xhw->title);
  250.   printf("%-21.21s\t%-6s\n", hw /* xhw->sprint(&req->arp_ha) */, flags);
  251. }
  252.  
  253.  
  254. /* Display the contents of the ARP cache in the kernel. */
  255. static int
  256. pr_arps(void)
  257. {
  258.   char ip[100];
  259.   char hw[100];
  260.   int type,flags;
  261.   FILE *fp;
  262.   int num;
  263.  
  264.   /* Open the PROCps kernel table. */
  265.   if ((fp = fopen(_PATH_PROCNET_ARP, "r")) == NULL) {
  266.     perror(_PATH_PROCNET_ARP);
  267.     return(-1);
  268.   }
  269.  
  270. /* Bypass header -- read until newline */
  271.   fscanf(fp,"%*[^\n]");
  272.  
  273.  
  274.   /* Read the ARP cache entries. */
  275.   for(;;)
  276.     {
  277.       num=fscanf(fp,"%s 0x%x 0x%x %s",ip,&type,&flags,hw);
  278.       if(num!=4)
  279.     break;
  280.  
  281.       arp_disp_2(ip,type,flags,hw);
  282.     }
  283.  
  284.   (void) fclose(fp);
  285.   return(0);
  286. }
  287.  
  288.  
  289. /* Show one or more entries from the ARP cache. */
  290. static int
  291. arp_show(char *name)
  292. {
  293.   char host[128];
  294.   struct sockaddr sa;
  295.   struct arpreq req;
  296.  
  297.   /* Do we have to show the whole table? */
  298.   if (name == NULL) return(pr_arps());
  299.  
  300.   /* Nope.  Resolve the host name. */
  301.   strcpy(host, name);
  302.   if (ap->input(host, &sa) < 0) {
  303.     fprintf(stderr, "arp: %s: %s\n", host, strerror(errno));
  304.     return(-1);
  305.   }
  306.  
  307.   /* If a host has more than one address, use the correct one! */
  308.   memcpy((char *) &req.arp_pa, &sa, sizeof(struct sockaddr));
  309.   req.arp_ha.sa_family = AF_INET;    /* any type */
  310.  
  311.   /* Call the kernel. */
  312.   if (ioctl(sockfd, SIOCGARP, &req) < 0) {
  313.     if (errno != ENXIO) perror("SIOCGARP");
  314.       else printf("No ARP entry for %s\n", host);
  315.     return -1;
  316.   }
  317.  
  318.   /* We found it.  Display the results. */
  319.   arp_disp(&req);
  320.  
  321.   return(0);
  322. }
  323.  
  324.  
  325. static void
  326. usage(void)
  327. {
  328.   fprintf(stderr,
  329.     "Usage: arp [-vn] [-p proto] [-t type] -a [hostname]\n");
  330.   fprintf(stderr,
  331.     "       arp [-v] [-p proto] -d hostname ...\n");
  332.   fprintf(stderr,
  333.     "       arp [-v] [-p proto] [-t type] -s hostname hw_addr [temp|pub|trail]\n");
  334.   fprintf(stderr,
  335.     "       arp [-vn] -f filename\n");
  336.   exit(-1);
  337. }
  338.  
  339.  
  340. int
  341. main(int argc, char **argv)
  342. {
  343.   int c, what;
  344.  
  345.   /* Initialize variables... */
  346.   if ((hw = get_hwtype(DFLT_HW)) == NULL) {
  347.     fprintf(stderr, "%s: hardware type not supported!\n", DFLT_HW);
  348.     return(-1);
  349.   }
  350.   if ((ap = get_aftype(DFLT_AF)) == NULL) {
  351.     fprintf(stderr, "%s: address family not supported!\n", DFLT_AF);
  352.     return(-1);
  353.   }
  354.   what = -1;
  355.  
  356.   /* Fetch the command-line arguments. */
  357.   opterr = 0;
  358.   while ((c = getopt(argc, argv, "adfp:nst:v")) != EOF) switch(c) {
  359.     case 'a':
  360.         what = 1;
  361.         break;
  362.  
  363.     case 'd':
  364.         what = 3;
  365.         break;
  366.  
  367.     case 'f':
  368.         what = 2;
  369.         break;
  370.  
  371.     case 'n':
  372.         opt_n = 1;
  373.         break;
  374.  
  375.     case 'p':
  376.         ap = get_aftype(optarg);
  377.         if (ap == NULL) {
  378.             fprintf(stderr, "arp: %s: unknown address family.\n",
  379.                                 optarg);
  380.             exit(-1);
  381.         }
  382.         break;
  383.  
  384.     case 's':
  385.         what = 4;
  386.         break;
  387.  
  388.     case 't':
  389.         hw = get_hwtype(optarg);
  390.         if (hw == NULL) {
  391.             fprintf(stderr, "arp: %s: unknown hardware type.\n",
  392.                                 optarg);
  393.             exit(-1);
  394.         }
  395.         break;
  396.  
  397.     case 'v':
  398.         opt_v = 1;
  399.         break;
  400.  
  401.     default:
  402.         usage();
  403.   }
  404.  
  405.   /* Create an entry point into the ARP protocol. */
  406.   if ((skfd = open(_PATH_PROCNET_ARP, O_RDONLY)) < 0) {
  407.     perror(_PATH_PROCNET_ARP);
  408.     exit(-1);
  409.   }
  410.   if ((sockfd = socket(AF_INET,SOCK_DGRAM,0)) <0)
  411.   {
  412.       perror("socket");
  413.       exit(-1);
  414.   }
  415.  
  416.   /* Now see what we have to do here... */
  417.   switch(what) {
  418.     case 1:        /* show an ARP entry in the cache */
  419.         what = arp_show(argv[optind]);
  420.         break;
  421.  
  422.     case 2:        /* process an EtherFile */
  423.         what = arp_file(argv[optind]);
  424.         break;
  425.  
  426.     case 3:        /* delete an ARP entry from the cache */
  427.         what = arp_del(&argv[optind]);
  428.         break;
  429.  
  430.     case 4:        /* set an ARP entry in the cache */
  431.         what = arp_set(&argv[optind]);
  432.         break;
  433.  
  434.     default:
  435.         usage();
  436.   }
  437.  
  438.   (void) close(skfd);
  439.   exit(what);
  440. }
  441.  
  442.