home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.sbin / arp / arp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-08-05  |  9.3 KB  |  407 lines

  1. /*
  2.  * Copyright (c) 1984 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * This code is derived from software contributed to Berkeley by
  6.  * Sun Microsystems, Inc.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. All advertising materials mentioning features or use of this software
  17.  *    must display the following acknowledgement:
  18.  *    This product includes software developed by the University of
  19.  *    California, Berkeley and its contributors.
  20.  * 4. Neither the name of the University nor the names of its contributors
  21.  *    may be used to endorse or promote products derived from this software
  22.  *    without specific prior written permission.
  23.  *
  24.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  */
  36.  
  37. #ifndef lint
  38. char copyright[] =
  39. "@(#) Copyright (c) 1984 Regents of the University of California.\n\
  40.  All rights reserved.\n";
  41. #endif /* not lint */
  42.  
  43. #ifndef lint
  44. static char sccsid[] = "@(#)arp.c    5.11.1.1 (Berkeley) 7/22/91";
  45. #endif /* not lint */
  46.  
  47. /*
  48.  * arp - display, set, and delete arp table entries
  49.  */
  50.  
  51. #include <sys/param.h>
  52. #include <sys/file.h>
  53. #include <sys/socket.h>
  54. #include <sys/ioctl.h>
  55.  
  56. #include <netdb.h>
  57. #include <netinet/in.h>
  58. #include <net/if.h>
  59. #include <netinet/if_ether.h>
  60.  
  61. #include <errno.h>
  62. #include <nlist.h>
  63. #include <kvm.h>
  64. #include <stdio.h>
  65. #include <paths.h>
  66.  
  67. extern int errno;
  68.  
  69. main(argc, argv)
  70.     int argc;
  71.     char **argv;
  72. {
  73.     int ch;
  74.  
  75.     while ((ch = getopt(argc, argv, "adsf")) != EOF)
  76.         switch((char)ch) {
  77.         case 'a': {
  78.             char *mem = 0;
  79.  
  80.             if (argc > 4)
  81.                 usage();
  82.             if (argc == 4) {
  83.                 mem = argv[3];
  84.             }
  85.             dump((argc >= 3) ? argv[2] : _PATH_UNIX, mem);
  86.             exit(0);
  87.         }
  88.         case 'd':
  89.             if (argc != 3)
  90.                 usage();
  91.             delete(argv[2]);
  92.             exit(0);
  93.         case 's':
  94.             if (argc < 4 || argc > 7)
  95.                 usage();
  96.             exit(set(argc-2, &argv[2]) ? 1 : 0);
  97.         case 'f':
  98.             if (argc != 3)
  99.                 usage();
  100.             exit (file(argv[2]) ? 1 : 0);
  101.         case '?':
  102.         default:
  103.             usage();
  104.         }
  105.     if (argc != 2)
  106.         usage();
  107.     get(argv[1]);
  108.     exit(0);
  109. }
  110.  
  111. /*
  112.  * Process a file to set standard arp entries
  113.  */
  114. file(name)
  115.     char *name;
  116. {
  117.     FILE *fp;
  118.     int i, retval;
  119.     char line[100], arg[5][50], *args[5];
  120.  
  121.     if ((fp = fopen(name, "r")) == NULL) {
  122.         fprintf(stderr, "arp: cannot open %s\n", name);
  123.         exit(1);
  124.     }
  125.     args[0] = &arg[0][0];
  126.     args[1] = &arg[1][0];
  127.     args[2] = &arg[2][0];
  128.     args[3] = &arg[3][0];
  129.     args[4] = &arg[4][0];
  130.     retval = 0;
  131.     while(fgets(line, 100, fp) != NULL) {
  132.         i = sscanf(line, "%s %s %s %s %s", arg[0], arg[1], arg[2],
  133.             arg[3], arg[4]);
  134.         if (i < 2) {
  135.             fprintf(stderr, "arp: bad line: %s\n", line);
  136.             retval = 1;
  137.             continue;
  138.         }
  139.         if (set(i, args))
  140.             retval = 1;
  141.     }
  142.     fclose(fp);
  143.     return (retval);
  144. }
  145.  
  146. /*
  147.  * Set an individual arp entry 
  148.  */
  149. set(argc, argv)
  150.     int argc;
  151.     char **argv;
  152. {
  153.     struct arpreq ar;
  154.     struct hostent *hp;
  155.     struct sockaddr_in *sin;
  156.     u_char *ea;
  157.     int s;
  158.     char *host = argv[0], *eaddr = argv[1];
  159.  
  160.     argc -= 2;
  161.     argv += 2;
  162.     bzero((caddr_t)&ar, sizeof ar);
  163.     sin = (struct sockaddr_in *)&ar.arp_pa;
  164.     sin->sin_family = AF_INET;
  165.     sin->sin_addr.s_addr = inet_addr(host);
  166.     if (sin->sin_addr.s_addr == -1) {
  167.         if (!(hp = gethostbyname(host))) {
  168.             fprintf(stderr, "arp: %s: ", host);
  169.             herror((char *)NULL);
  170.             return (1);
  171.         }
  172.         bcopy((char *)hp->h_addr, (char *)&sin->sin_addr,
  173.             sizeof sin->sin_addr);
  174.     }
  175.     ea = (u_char *)ar.arp_ha.sa_data;
  176.     if (ether_aton(eaddr, ea))
  177.         return (1);
  178.     ar.arp_flags = ATF_PERM;
  179.     while (argc-- > 0) {
  180.         if (strncmp(argv[0], "temp", 4) == 0)
  181.             ar.arp_flags &= ~ATF_PERM;
  182.         else if (strncmp(argv[0], "pub", 3) == 0)
  183.             ar.arp_flags |= ATF_PUBL;
  184.         else if (strncmp(argv[0], "trail", 5) == 0)
  185.             ar.arp_flags |= ATF_USETRAILERS;
  186.         argv++;
  187.     }
  188.     
  189.     s = socket(AF_INET, SOCK_DGRAM, 0);
  190.     if (s < 0) {
  191.         perror("arp: socket");
  192.         exit(1);
  193.     }
  194.     if (ioctl(s, SIOCSARP, (caddr_t)&ar) < 0) {
  195.         perror(host);
  196.         exit(1);
  197.     }
  198.     close(s);
  199.     return (0);
  200. }
  201.  
  202. /*
  203.  * Display an individual arp entry
  204.  */
  205. get(host)
  206.     char *host;
  207. {
  208.     struct arpreq ar;
  209.     struct hostent *hp;
  210.     struct sockaddr_in *sin;
  211.     u_char *ea;
  212.     int s;
  213.     char *inet_ntoa();
  214.  
  215.     bzero((caddr_t)&ar, sizeof ar);
  216.     ar.arp_pa.sa_family = AF_INET;
  217.     sin = (struct sockaddr_in *)&ar.arp_pa;
  218.     sin->sin_family = AF_INET;
  219.     sin->sin_addr.s_addr = inet_addr(host);
  220.     if (sin->sin_addr.s_addr == -1) {
  221.         if (!(hp = gethostbyname(host))) {
  222.             fprintf(stderr, "arp: %s: ", host);
  223.             herror((char *)NULL);
  224.             exit(1);
  225.         }
  226.         bcopy((char *)hp->h_addr, (char *)&sin->sin_addr,
  227.             sizeof sin->sin_addr);
  228.     }
  229.     s = socket(AF_INET, SOCK_DGRAM, 0);
  230.     if (s < 0) {
  231.         perror("arp: socket");
  232.         exit(1);
  233.     }
  234.     if (ioctl(s, SIOCGARP, (caddr_t)&ar) < 0) {
  235.         if (errno == ENXIO)
  236.             printf("%s (%s) -- no entry\n",
  237.                 host, inet_ntoa(sin->sin_addr));
  238.         else
  239.             perror("SIOCGARP");
  240.         exit(1);
  241.     }
  242.     close(s);
  243.     ea = (u_char *)ar.arp_ha.sa_data;
  244.     printf("%s (%s) at ", host, inet_ntoa(sin->sin_addr));
  245.     if (ar.arp_flags & ATF_COM)
  246.         ether_print(ea);
  247.     else
  248.         printf("(incomplete)");
  249.     if (ar.arp_flags & ATF_PERM)
  250.         printf(" permanent");
  251.     if (ar.arp_flags & ATF_PUBL)
  252.         printf(" published");
  253.     if (ar.arp_flags & ATF_USETRAILERS)
  254.         printf(" trailers");
  255.     printf("\n");
  256. }
  257.  
  258. /*
  259.  * Delete an arp entry 
  260.  */
  261. delete(host)
  262.     char *host;
  263. {
  264.     struct arpreq ar;
  265.     struct hostent *hp;
  266.     struct sockaddr_in *sin;
  267.     int s;
  268.  
  269.     bzero((caddr_t)&ar, sizeof ar);
  270.     ar.arp_pa.sa_family = AF_INET;
  271.     sin = (struct sockaddr_in *)&ar.arp_pa;
  272.     sin->sin_family = AF_INET;
  273.     sin->sin_addr.s_addr = inet_addr(host);
  274.     if (sin->sin_addr.s_addr == -1) {
  275.         if (!(hp = gethostbyname(host))) {
  276.             fprintf(stderr, "arp: %s: ", host);
  277.             herror((char *)NULL);
  278.             exit(1);
  279.         }
  280.         bcopy((char *)hp->h_addr, (char *)&sin->sin_addr,
  281.             sizeof sin->sin_addr);
  282.     }
  283.     s = socket(AF_INET, SOCK_DGRAM, 0);
  284.     if (s < 0) {
  285.         perror("arp: socket");
  286.         exit(1);
  287.     }
  288.     if (ioctl(s, SIOCDARP, (caddr_t)&ar) < 0) {
  289.         if (errno == ENXIO)
  290.             printf("%s (%s) -- no entry\n",
  291.                 host, inet_ntoa(sin->sin_addr));
  292.         else
  293.             perror("SIOCDARP");
  294.         exit(1);
  295.     }
  296.     close(s);
  297.     printf("%s (%s) deleted\n", host, inet_ntoa(sin->sin_addr));
  298. }
  299.  
  300. struct nlist nl[] = {
  301. #define    X_ARPTAB    0
  302.     { "_arptab" },
  303. #define    X_ARPTAB_SIZE    1
  304.     { "_arptab_size" },
  305.     { "" },
  306. };
  307.  
  308. /*
  309.  * Dump the entire arp table
  310.  */
  311. dump(kernel, mem)
  312.     char *kernel, *mem;
  313. {
  314.     extern int h_errno;
  315.     struct arptab *at;
  316.     struct hostent *hp;
  317.     int bynumber, mf, arptab_size, sz;
  318.     char *host, *malloc();
  319.     off_t lseek();
  320.  
  321.     if (kvm_openfiles(kernel, mem, NULL) == -1) {
  322.         fprintf(stderr, "arp: kvm_openfiles: %s\n", kvm_geterr());
  323.         exit(1);
  324.     }
  325.     if (kvm_nlist(nl) < 0 || nl[X_ARPTAB_SIZE].n_type == 0) {
  326.         fprintf(stderr, "arp: %s: bad namelist\n", kernel);
  327.         exit(1);
  328.     }
  329.     if (kvm_read((void *)(nl[X_ARPTAB_SIZE].n_value),
  330.              &arptab_size, sizeof arptab_size) == -1 ||
  331.         arptab_size <= 0 || arptab_size > 1000) {
  332.         fprintf(stderr, "arp: %s: namelist wrong\n", kernel);
  333.         exit(1);
  334.     }
  335.     sz = arptab_size * sizeof (struct arptab);
  336.     at = (struct arptab *)malloc((u_int)sz);
  337.     if (at == NULL) {
  338.         fputs("arp: can't get memory for arptab.\n", stderr);
  339.         exit(1);
  340.     }
  341.     if (kvm_read((void *)(nl[X_ARPTAB].n_value), (char *)at, sz) == -1) {
  342.         perror("arp: error reading arptab");
  343.         exit(1);
  344.     }
  345.     for (bynumber = 0; arptab_size-- > 0; at++) {
  346.         if (at->at_iaddr.s_addr == 0 || at->at_flags == 0)
  347.             continue;
  348.         if (bynumber == 0)
  349.             hp = gethostbyaddr((caddr_t)&at->at_iaddr,
  350.                 sizeof at->at_iaddr, AF_INET);
  351.         else
  352.             hp = 0;
  353.         if (hp)
  354.             host = hp->h_name;
  355.         else {
  356.             host = "?";
  357.             if (h_errno == TRY_AGAIN)
  358.                 bynumber = 1;
  359.         }
  360.         printf("%s (%s) at ", host, inet_ntoa(at->at_iaddr));
  361.         if (at->at_flags & ATF_COM)
  362.             ether_print(at->at_enaddr);
  363.         else
  364.             printf("(incomplete)");
  365.         if (at->at_flags & ATF_PERM)
  366.             printf(" permanent");
  367.         if (at->at_flags & ATF_PUBL)
  368.             printf(" published");
  369.         if (at->at_flags & ATF_USETRAILERS)
  370.             printf(" trailers");
  371.         printf("\n");
  372.     }
  373. }
  374.  
  375. ether_print(cp)
  376.     u_char *cp;
  377. {
  378.     printf("%x:%x:%x:%x:%x:%x", cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]);
  379. }
  380.  
  381. ether_aton(a, n)
  382.     char *a;
  383.     u_char *n;
  384. {
  385.     int i, o[6];
  386.  
  387.     i = sscanf(a, "%x:%x:%x:%x:%x:%x", &o[0], &o[1], &o[2],
  388.                        &o[3], &o[4], &o[5]);
  389.     if (i != 6) {
  390.         fprintf(stderr, "arp: invalid Ethernet address '%s'\n", a);
  391.         return (1);
  392.     }
  393.     for (i=0; i<6; i++)
  394.         n[i] = o[i];
  395.     return (0);
  396. }
  397.  
  398. usage()
  399. {
  400.     printf("usage: arp hostname\n");
  401.     printf("       arp -a [kernel] [kernel_memory]\n");
  402.     printf("       arp -d hostname\n");
  403.     printf("       arp -s hostname ether_addr [temp] [pub] [trail]\n");
  404.     printf("       arp -f filename\n");
  405.     exit(1);
  406. }
  407.