home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / N / TCPIP / NETKIT-B.05 / NETKIT-B / NetKit-B-0.05 / arp / arp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-23  |  8.9 KB  |  399 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[] = "from: @(#)arp.c    5.11.1.1 (Berkeley) 7/22/91";*/
  45. static char rcsid[] = "$Id: arp.c,v 1.1 1994/05/23 08:58:37 rzsfl Exp rzsfl $";
  46. #endif /* not lint */
  47.  
  48. /*
  49.  * arp - display, set, and delete arp table entries
  50.  */
  51.  
  52. #include <sys/param.h>
  53. #include <sys/file.h>
  54. #include <sys/socket.h>
  55. #include <sys/ioctl.h>
  56.  
  57. #include <netdb.h>
  58. #include <netinet/in.h>
  59. #include <net/if.h>
  60. #include <linux/if_ether.h>
  61.  
  62. #include <errno.h>
  63. #include <stdio.h>
  64. #include <paths.h>
  65.  
  66. extern int errno;
  67.  
  68. main(argc, argv)
  69.     int argc;
  70.     char **argv;
  71. {
  72.     int ch;
  73.  
  74.     while ((ch = getopt(argc, argv, "adsf")) != EOF)
  75.         switch((char)ch) {
  76.         case 'a': {
  77.             char *mem = 0;
  78.  
  79.             if (argc > 2)
  80.                 usage();
  81.             dump();
  82.             exit(0);
  83.         }
  84.         case 'd':
  85.             if (argc != 3)
  86.                 usage();
  87.             delete(argv[2]);
  88.             exit(0);
  89.         case 's':
  90.             if (argc < 4 || argc > 7)
  91.                 usage();
  92.             exit(set(argc-2, &argv[2]) ? 1 : 0);
  93.         case 'f':
  94.             if (argc != 3)
  95.                 usage();
  96.             exit (file(argv[2]) ? 1 : 0);
  97.         case '?':
  98.         default:
  99.             usage();
  100.         }
  101.     if (argc != 2)
  102.         usage();
  103.     get(argv[1]);
  104.     exit(0);
  105. }
  106.  
  107. /*
  108.  * Process a file to set standard arp entries
  109.  */
  110. file(name)
  111.     char *name;
  112. {
  113.     FILE *fp;
  114.     int i, retval;
  115.     char line[100], arg[5][50], *args[5];
  116.  
  117.     if ((fp = fopen(name, "r")) == NULL) {
  118.         fprintf(stderr, "arp: cannot open %s\n", name);
  119.         exit(1);
  120.     }
  121.     args[0] = &arg[0][0];
  122.     args[1] = &arg[1][0];
  123.     args[2] = &arg[2][0];
  124.     args[3] = &arg[3][0];
  125.     args[4] = &arg[4][0];
  126.     retval = 0;
  127.     while(fgets(line, 100, fp) != NULL) {
  128.         i = sscanf(line, "%s %s %s %s %s", arg[0], arg[1], arg[2],
  129.             arg[3], arg[4]);
  130.         if (i < 2) {
  131.             fprintf(stderr, "arp: bad line: %s\n", line);
  132.             retval = 1;
  133.             continue;
  134.         }
  135.         if (set(i, args))
  136.             retval = 1;
  137.     }
  138.     fclose(fp);
  139.     return (retval);
  140. }
  141.  
  142. /*
  143.  * Set an individual arp entry 
  144.  */
  145. set(argc, argv)
  146.     int argc;
  147.     char **argv;
  148. {
  149.     struct arpreq ar;
  150.     struct hostent *hp;
  151.     struct sockaddr_in *sin;
  152.     u_char *ea;
  153.     int s;
  154.     char *host = argv[0], *eaddr = argv[1];
  155.  
  156.     argc -= 2;
  157.     argv += 2;
  158.     bzero((caddr_t)&ar, sizeof ar);
  159.     sin = (struct sockaddr_in *)&ar.arp_pa;
  160.     sin->sin_family = AF_INET;
  161.     sin->sin_addr.s_addr = inet_addr(host);
  162.     if (sin->sin_addr.s_addr == -1) {
  163.         if (!(hp = gethostbyname(host))) {
  164.             fprintf(stderr, "arp: %s: ", host);
  165.             herror((char *)NULL);
  166.             return (1);
  167.         }
  168.         bcopy((char *)hp->h_addr, (char *)&sin->sin_addr,
  169.             sizeof sin->sin_addr);
  170.     }
  171.     ea = (u_char *)ar.arp_ha.sa_data;
  172.     if (ether_aton(eaddr, ea))
  173.         return (1);
  174.     ar.arp_flags = ATF_PERM|ATF_COM;
  175.     while (argc-- > 0) {
  176.         if (strncmp(argv[0], "temp", 4) == 0)
  177.             ar.arp_flags &= ~ATF_PERM;
  178.         else if (strncmp(argv[0], "pub", 3) == 0)
  179.             ar.arp_flags |= ATF_PUBL;
  180.         else if (strncmp(argv[0], "trail", 5) == 0)
  181.             ar.arp_flags |= ATF_USETRAILERS;
  182.         argv++;
  183.     }
  184.     
  185.     s = socket(AF_INET, SOCK_DGRAM, 0);
  186.     if (s < 0) {
  187.         perror("arp: socket");
  188.         exit(1);
  189.     }
  190.     if (ioctl(s, SIOCSARP, (caddr_t)&ar) < 0) {
  191.         perror(host);
  192.         exit(1);
  193.     }
  194.     close(s);
  195.     return (0);
  196. }
  197.  
  198. /*
  199.  * Display an individual arp entry
  200.  */
  201. get(host)
  202.     char *host;
  203. {
  204.     struct arpreq ar;
  205.     struct hostent *hp;
  206.     struct sockaddr_in *sin;
  207.     unsigned char *ea;
  208.     int s;
  209.  
  210.     bzero((caddr_t)&ar, sizeof ar);
  211.     ar.arp_pa.sa_family = AF_INET;
  212.     sin = (struct sockaddr_in *)&ar.arp_pa;
  213.     sin->sin_family = AF_INET;
  214.     sin->sin_addr.s_addr = inet_addr(host);
  215.     if ((long)sin->sin_addr.s_addr == -1) {
  216.         if (!(hp = gethostbyname(host))) {
  217.             fprintf(stderr, "arp: %s: ", host);
  218.             herror((char *)NULL);
  219.             exit(1);
  220.         }
  221.         bcopy((char *)hp->h_addr, (char *)&sin->sin_addr,
  222.             sizeof sin->sin_addr);
  223.     }
  224.     s = socket(AF_INET, SOCK_DGRAM, 0);
  225.     if (s < 0) {
  226.         perror("arp: socket");
  227.         exit(1);
  228.     }
  229.     if (ioctl(s, SIOCGARP, (caddr_t)&ar) < 0) {
  230.         if (errno == ENXIO)
  231.             printf("%s (%s) -- no entry\n",
  232.                 host, inet_ntoa(sin->sin_addr));
  233.         else
  234.             perror("SIOCGARP");
  235.         exit(1);
  236.     }
  237.     close(s);
  238.     ea = (u_char *)ar.arp_ha.sa_data;
  239.     printf("%s (%s) at ", host, inet_ntoa(sin->sin_addr));
  240.     /* if (ar.arp_flags & ATF_COM)*/
  241.         ether_print(ea);
  242.     /* else
  243.         printf("(incomplete)"); */
  244.     if (ar.arp_flags & ATF_PERM)
  245.         printf(" permanent");
  246.     if (ar.arp_flags & ATF_PUBL)
  247.         printf(" published");
  248.     if (ar.arp_flags & ATF_USETRAILERS)
  249.         printf(" trailers");
  250.     printf("\n");
  251. }
  252.  
  253. /*
  254.  * Delete an arp entry 
  255.  */
  256. delete(host)
  257.     char *host;
  258. {
  259.     struct arpreq ar;
  260.     struct hostent *hp;
  261.     struct sockaddr_in *sin;
  262.     int s;
  263.  
  264.     bzero((caddr_t)&ar, sizeof ar);
  265.     ar.arp_pa.sa_family = AF_INET;
  266.     sin = (struct sockaddr_in *)&ar.arp_pa;
  267.     sin->sin_family = AF_INET;
  268.     sin->sin_addr.s_addr = inet_addr(host);
  269.     if ((long)sin->sin_addr.s_addr == -1) {
  270.         if (!(hp = gethostbyname(host))) {
  271.             fprintf(stderr, "arp: %s: ", host);
  272.             herror((char *)NULL);
  273.             exit(1);
  274.         }
  275.         bcopy((char *)hp->h_addr, (char *)&sin->sin_addr,
  276.             sizeof sin->sin_addr);
  277.     }
  278.     s = socket(AF_INET, SOCK_DGRAM, 0);
  279.     if (s < 0) {
  280.         perror("arp: socket");
  281.         exit(1);
  282.     }
  283.     if (ioctl(s, SIOCDARP, (caddr_t)&ar) < 0) {
  284.         if (errno == ENXIO)
  285.             printf("%s (%s) -- no entry\n",
  286.                 host, inet_ntoa(sin->sin_addr));
  287.         else
  288.             perror("SIOCDARP");
  289.         exit(1);
  290.     }
  291.     close(s);
  292.     printf("%s (%s) deleted\n", host, inet_ntoa(sin->sin_addr));
  293. }
  294.  
  295.  
  296. /*
  297.  * Dump the entire arp table
  298.  */
  299.  
  300. static unsigned long getipaddr(struct arpreq *at)
  301. {
  302.     return (* (long *)(at->arp_pa.sa_data));
  303. }
  304.  
  305. dump()
  306. {
  307.     extern int h_errno;
  308.     struct arpreq *at;
  309.     struct hostent *hp;
  310.     int bynumber, mf, arptab_size, sz;
  311.     int fd;
  312.     const char *host;
  313.  
  314.     sz = 65536;
  315.     at = (struct arpreq *)malloc((u_int)sz);
  316.     if (at == NULL) {
  317.         fputs("arp: can't get memory for arptab.\n", stderr);
  318.         exit(1);
  319.     }
  320.  
  321.     fd=open("/proc/net/arp",O_RDONLY,0);
  322.     if(fd==-1)
  323.     {
  324.         perror("arp: error opening arptab");
  325.         exit(1);
  326.     }
  327.     if((sz=read(fd,at,65536))<0)
  328.     {
  329.         perror("arp: error reading arptab");
  330.         exit(1);
  331.     }
  332.     arptab_size=sz/sizeof(struct arpreq);
  333.     close(fd);
  334.     for (bynumber = 0; arptab_size-- > 0; at++) {
  335.         unsigned long h_ip = getipaddr(at);
  336.         if (bynumber == 0)
  337.         {
  338.             struct in_addr ia;
  339.             ia.s_addr = h_ip;
  340.             hp = gethostbyaddr((const char *)&ia,
  341.                 sizeof(ia), AF_INET);
  342.         }
  343.         else
  344.             hp = 0;
  345.         if (hp)
  346.             host = hp->h_name;
  347.         else {
  348.             host = "?";
  349.             if (h_errno == TRY_AGAIN)
  350.                 bynumber = 1;
  351.         }
  352.         printf("%s (%s) at ", host, inet_ntoa(h_ip));
  353.         if (at->arp_flags & ATF_COM)
  354.             ether_print(at->arp_ha.sa_data);
  355.         else
  356.             printf("(incomplete)");
  357.         if (at->arp_flags & ATF_PERM)
  358.             printf(" permanent");
  359.         if (at->arp_flags & ATF_PUBL)
  360.             printf(" published");
  361.         if (at->arp_flags & ATF_USETRAILERS)
  362.             printf(" trailers");
  363.         printf("\n");
  364.     }
  365. }
  366.  
  367. ether_print(cp)
  368.     u_char *cp;
  369. {
  370.     printf("%02x:%02x:%02x:%02x:%02x:%02x", cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]);
  371. }
  372.  
  373. ether_aton(a, n)
  374.     char *a;
  375.     u_char *n;
  376. {
  377.     int i, o[6];
  378.  
  379.     i = sscanf(a, "%x:%x:%x:%x:%x:%x", &o[0], &o[1], &o[2],
  380.                        &o[3], &o[4], &o[5]);
  381.     if (i != 6) {
  382.         fprintf(stderr, "arp: invalid Ethernet address '%s'\n", a);
  383.         return (1);
  384.     }
  385.     for (i=0; i<6; i++)
  386.         n[i] = o[i];
  387.     return (0);
  388. }
  389.  
  390. usage()
  391. {
  392.     printf("usage: arp hostname\n");
  393.     printf("       arp -a\n");
  394.     printf("       arp -d hostname\n");
  395.     printf("       arp -s hostname ether_addr [temp] [pub] [trail]\n");
  396.     printf("       arp -f filename\n");
  397.     exit(1);
  398. }
  399.