home *** CD-ROM | disk | FTP | other *** search
/ Network CD 2 / Network CD - Volume 2.iso / programs / internet / tcp / amitcp / amitcp-src-22.lha / AmiTCP-2.2 / src / util / arp / arp.c next >
Encoding:
C/C++ Source or Header  |  1993-11-06  |  15.0 KB  |  591 lines

  1. static char rcsid[] = 
  2.   "$Id: arp.c,v 1.10 1993/11/07 00:19:45 ppessi Exp $";
  3. /*
  4.  * arp.c --- arp utility for AmiTCP/IP
  5.  *
  6.  * Copyright © 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>,
  7.  *                  Helsinki University of Technology, Finland.
  8.  *                  All rights reserved.
  9.  *
  10.  * Created      : Sun Apr 18 05:08:20 1993 ppessi
  11.  * Last modified: Sun Nov  7 02:19:02 1993 ppessi
  12.  *
  13.  * $Log: arp.c,v $
  14.  * Revision 1.10  1993/11/07  00:19:45  ppessi
  15.  * Reverted back to scanf()
  16.  *
  17.  * Revision 1.9  1993/10/29  01:26:40  ppessi
  18.  * Implemented dumping of arp tables.
  19.  * Cleaned up code, fixed close() bug.
  20.  *
  21.  * Revision 1.8  1993/08/10  20:46:23  jraja
  22.  * Added version string.
  23.  *
  24.  * Revision 1.7  1993/08/02  10:56:49  jraja
  25.  * Changed ioctl() calls to IoctlSocket() for the second release.
  26.  *
  27.  * Revision 1.6  1993/08/02  10:55:18  jraja
  28.  * Changes for the first release (ppessi).
  29.  *
  30.  * Revision 1.5  1993/05/15  12:57:25  ppessi
  31.  * Fixed silly quotation bug.
  32.  *
  33.  * Revision 1.4  1993/05/15  01:25:21  ppessi
  34.  * added autodoc page
  35.  *
  36.  * Revision 1.3  1993/05/14  23:41:47  ppessi
  37.  * Fixed includes for Demo version.
  38.  *
  39.  * Revision 1.2  93/04/20  22:53:21  ppessi
  40.  * Fixed to work with if_arpsana.
  41.  * 
  42.  * Revision 1.1  93/04/18  05:16:18  ppessi
  43.  * Initial revision
  44.  */
  45.  
  46. static const char version[] = "$VER: arp 2.2 (29.10.93)";
  47.  
  48. char copyright[] =
  49. "@(#) Copyright © 1984 The Regents of the University of California.\n"
  50.                       "All rights reserved.\n"
  51.      "Copyright © 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>\n"
  52.                       "Helsinki University of Technology, Finland.\n"
  53.                       "All rights reserved.\n";
  54.  
  55.  
  56. /*
  57.  * Copyright © 1984 Regents of the University of California.
  58.  * All rights reserved.
  59.  *
  60.  * This code is derived from software contributed to Berkeley by
  61.  * Sun Microsystems, Inc.
  62.  *
  63.  * Redistribution and use in source and binary forms, with or without
  64.  * modification, are permitted provided that the following conditions
  65.  * are met:
  66.  * 1. Redistributions of source code must retain the above copyright
  67.  *    notice, this list of conditions and the following disclaimer.
  68.  * 2. Redistributions in binary form must reproduce the above copyright
  69.  *    notice, this list of conditions and the following disclaimer in the
  70.  *    documentation and/or other materials provided with the distribution.
  71.  * 3. All advertising materials mentioning features or use of this software
  72.  *    must display the following acknowledgement:
  73.  *    This product includes software developed by the University of
  74.  *    California, Berkeley and its contributors.
  75.  * 4. Neither the name of the University nor the names of its contributors
  76.  *    may be used to endorse or promote products derived from this software
  77.  *    without specific prior written permission.
  78.  *
  79.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  80.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  81.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  82.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  83.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  84.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  85.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  86.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  87.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  88.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  89.  * SUCH DAMAGE.
  90.  */
  91.  
  92. /****** netutil.doc/arp *****************************************************
  93. *
  94. *  NAME
  95. *       Arp - address resolution display and control
  96. *
  97. *  SYNOPSIS
  98. *       arp hostname
  99. *       arp -a [netname | hostname]
  100. *       arp -d hostname
  101. *       arp -s hostname address [temp] [pub] 
  102. *       arp -f filename
  103. *
  104. *  DESCRIPTION
  105. *       Arp displays and modifies the Internet to hardware address
  106. *       translation tables used by the Address Resolution Protocol. The
  107. *       hardware address is a hexadecimal string with each octet separated
  108. *       by a colon, for instance 0:12:ff:a. The length of the address must
  109. *       be correct for the specified interface.
  110. *
  111. *  OPTIONS
  112. *        none If no options are specified (first form above), arp displays
  113. *             the current ARP entry for hostname.  The hostname must either
  114. *             appear in the hostname database (SEE hosts), or be a DARPA
  115. *             Internet address expressed in Internet standard "dot
  116. *             notation". Hostname can also be resolved by nameserver.
  117. *
  118. *       -a    Display all current ARP entries by reading the address mapping
  119. *             table of the specified (sub)network. `Hostname' is used to as
  120. *             default network specifier.
  121. *
  122. *       -d    If an ARP entry exists for the host called hostname, delete
  123. *             it. [This requires super-user privileges.]
  124. *
  125. *       -s    Create an ARP entry for the host called hostname with the
  126. *             hardware station address address. The hardware station address
  127. *             is given as hexadecimal bytes separated by colons. If an ARP
  128. *             entry already exists for hostname, the existing entry is
  129. *             updated with the new information. The entry is permanent
  130. *             unless the word temp is given in the command. If the word pub
  131. *             is specified, the entry is published, which means that this
  132. *             system will act as an ARP server responding to requests for
  133. *             hostname even though the host address is not its own.
  134. *
  135. *       -f    Read file filename and set multiple entries in the ARP tables.
  136. *             Entries in the file should be of the form:
  137. *
  138. *                  hostname address [temp] [pub]
  139. *
  140. *             Argument meanings are the same as for the -s option.
  141. *
  142. *  AUTHOR
  143. *       Arp was developed by the University of California, Berkeley, for the
  144. *       BSD Unix system.
  145. *
  146. *  SEE ALSO
  147. *       ifconfig, netif.protocols/arp, "net/if_arp.h"
  148. *
  149. *****************************************************************************
  150. *
  151. */
  152.  
  153. /*
  154.  * arp - display, set, and delete arp table entries
  155.  */
  156.  
  157. #ifdef AMIGA
  158. #if __SASC
  159. #include <proto/socket.h>
  160. #elif __GNUC__
  161. #include <inline/socket.h>
  162. #else
  163. #include <clib/socket_protos.h>
  164. #endif
  165. #define herror(x) (fputs("not found\n", stderr))
  166. int h_errno = 0;
  167. #endif /* AMIGA */
  168.  
  169. #include <sys/param.h>
  170. #include <sys/socket.h>
  171. #include <sys/ioctl.h>
  172.  
  173. #include <arpa/inet.h>
  174. #include <netdb.h>
  175. #include <netinet/in.h>
  176. #include <net/if.h>
  177.  
  178. #include <errno.h>
  179. #include <stdlib.h>
  180. #include <stdio.h>
  181.  
  182. extern int errno;
  183.  
  184. static int file(char *name);
  185. static int set(int argc, char **argv);
  186. static void get(char *host);
  187. static void delete(char *host);
  188. static int arpreq_print(struct arpreq *ar, int bynumber);
  189. static void sana_print(const u_char *cp, int len);
  190. static int sana_aton(const char *a, u_char *n, u_char *lenp);
  191. static void usage(void);
  192. static void dump(char *name);
  193. char * strsep(register char **stringp, register const char *delim);
  194.  
  195. char usage_str[] = 
  196.   "usage: arp hostname\n"
  197.   "       arp -a [netname | hostname]\n"
  198.   "       arp -d hostname\n"
  199.   "       arp -s hostname address [temp] [pub]\n"
  200.   "       arp -f filename\n";
  201.  
  202. main(argc, argv)
  203.     int argc;
  204.     char **argv;
  205. {
  206.   int ch;
  207.  
  208.   while ((ch = getopt(argc, argv, "adsf")) != EOF)
  209.     switch((char)ch) {
  210.     case 'a': {
  211.       char *net;
  212.       char myname[MAXHOSTNAMELEN];
  213.  
  214.       if (argc > 3)
  215.     usage();
  216.       if (argc == 3) {
  217.     net = argv[2];
  218.       } else {
  219.     net = myname;
  220.     gethostname(myname, sizeof(myname));
  221.       }
  222.       dump(net);
  223.       exit(0);
  224.     }
  225.     case 'd':
  226.       if (argc != 3)
  227.     usage();
  228.       delete(argv[2]);
  229.       exit(0);
  230.     case 's':
  231.       if (argc < 4 || argc > 7)
  232.     usage();
  233.       exit(set(argc-2, &argv[2]) ? 1 : 0);
  234.     case 'f':
  235.       if (argc != 3)
  236.     usage();
  237.       exit (file(argv[2]) ? 1 : 0);
  238.     case '?':
  239.     default:
  240.       usage();
  241.     }
  242.   if (argc != 2)
  243.     usage();
  244.   get(argv[1]);
  245.   exit(0);
  246. }
  247.  
  248. /*
  249.  * Process a file to set standard arp entries
  250.  */
  251. static int
  252. file(char *name)
  253. {
  254.   FILE *fp;
  255.   int i, retval;
  256.   char line[100], arg[5][50], *args[5];
  257.  
  258.   if ((fp = fopen(name, "r")) == NULL) {
  259.     fprintf(stderr, "arp: cannot open %s\n", name);
  260.     exit(1);
  261.   }
  262.  
  263.   args[0] = &arg[0][0];
  264.   args[1] = &arg[1][0];
  265.   args[2] = &arg[2][0];
  266.   args[3] = &arg[3][0];
  267.   args[4] = &arg[4][0];
  268.  
  269.   retval = 0;
  270.   while(fgets(line, 100, fp) != NULL) {
  271.     i = sscanf(line, "%s %s %s %s %s", arg[0], arg[1], arg[2], arg[3], arg[4]);
  272.     if (i < 2) {
  273.       fprintf(stderr, "arp: bad line: %s\n", line);
  274.       retval = 1;
  275.       continue;
  276.     }
  277.     if (set(i, args))
  278.       retval = 1;
  279.   }
  280.   fclose(fp);
  281.   return (retval);
  282. }
  283.  
  284. /*
  285.  * Set an individual arp entry 
  286.  */
  287. static int
  288. set(int argc, char **argv)
  289. {
  290.   struct arpreq ar;
  291.   struct hostent *hp;
  292.   struct sockaddr_in *sin;
  293.   u_char *ea;
  294.   int s;
  295.   char *host = argv[0], *eaddr = argv[1];
  296.  
  297.   argc -= 2;
  298.   argv += 2;
  299.   bzero((caddr_t)&ar, sizeof ar);
  300.   sin = (struct sockaddr_in *)&ar.arp_pa;
  301.   sin->sin_len = sizeof(*sin);
  302.   sin->sin_family = AF_INET;
  303.   sin->sin_addr.s_addr = inet_addr(host);
  304.   if (sin->sin_addr.s_addr == -1) {
  305.     if (!(hp = gethostbyname(host))) {
  306.       fprintf(stderr, "arp: %s: ", host);
  307.       herror((char *)NULL);
  308.       return (1);
  309.     }
  310.     bcopy((char *)hp->h_addr, (char *)&sin->sin_addr,
  311.       sizeof sin->sin_addr);
  312.   }
  313.   ea = (u_char *)ar.arp_ha.sa_data;
  314.   if (sana_aton(eaddr, ea, &ar.arp_ha.sa_len))
  315.     return (1);
  316.   ar.arp_ha.sa_len += 2;
  317.   ar.arp_flags = ATF_PERM;
  318.   while (argc-- > 0) {
  319.     if (strncmp(argv[0], "temp", 4) == 0)
  320.       ar.arp_flags &= ~ATF_PERM;
  321.     else if (strncmp(argv[0], "pub", 3) == 0)
  322.       ar.arp_flags |= ATF_PUBL;
  323.     else if (strncmp(argv[0], "trail", 5) == 0)
  324.       ar.arp_flags |= ATF_USETRAILERS;
  325.     argv++;
  326.   }
  327.     
  328.   s = socket(AF_INET, SOCK_DGRAM, 0);
  329.   if (s < 0) {
  330.     perror("arp: socket");
  331.     exit(1);
  332.   }
  333.   if (IoctlSocket(s, SIOCSARP, (caddr_t)&ar) < 0) {
  334.     perror(host);
  335.     exit(1);
  336.   }
  337.   CloseSocket(s);
  338.  
  339.   return (0);
  340. }
  341.  
  342. /*
  343.  * Display an individual arp entry
  344.  */
  345. static void
  346. get(char *host)
  347. {
  348.   struct arpreq ar;
  349.   struct hostent *hp;
  350.   struct sockaddr_in *sin;
  351.   int s;
  352.  
  353.   bzero((caddr_t)&ar, sizeof ar);
  354.   sin = (struct sockaddr_in *)&ar.arp_pa;
  355.   sin->sin_len = sizeof(*sin);
  356.   sin->sin_family = AF_INET;
  357.   sin->sin_addr.s_addr = inet_addr(host);
  358.   if (sin->sin_addr.s_addr == -1) {
  359.     if (!(hp = gethostbyname(host))) {
  360.       fprintf(stderr, "arp: %s: ", host);
  361.       herror((char *)NULL);
  362.       exit(1);
  363.     }
  364.     bcopy((char *)hp->h_addr, (char *)&sin->sin_addr, sizeof sin->sin_addr);
  365.   }
  366.   s = socket(AF_INET, SOCK_DGRAM, 0);
  367.   if (s < 0) {
  368.     perror("arp: socket");
  369.     exit(1);
  370.   }
  371.   if (IoctlSocket(s, SIOCGARP, (caddr_t)&ar) < 0) {
  372.     if (errno == ENXIO)
  373.       printf("%s (%s) -- no entry\n", host, inet_ntoa(sin->sin_addr));
  374.     else
  375.       perror("SIOCGARP");
  376.     exit(1);
  377.   }
  378.   CloseSocket(s);
  379.  
  380.   (void)arpreq_print(&ar, 0);
  381. }
  382.  
  383. /*
  384.  * Delete an arp entry 
  385.  */
  386. static void
  387. delete(char *host)
  388. {
  389.   struct arpreq ar;
  390.   struct hostent *hp;
  391.   struct sockaddr_in *sin;
  392.   int s;
  393.  
  394.   bzero((caddr_t)&ar, sizeof ar);
  395.   sin = (struct sockaddr_in *)&ar.arp_pa;
  396.   sin->sin_len = sizeof(*sin);
  397.   sin->sin_family = AF_INET;
  398.   sin->sin_addr.s_addr = inet_addr(host);
  399.   if (sin->sin_addr.s_addr == -1) {
  400.     if (!(hp = gethostbyname(host))) {
  401.       fprintf(stderr, "arp: %s: ", host);
  402.       herror((char *)NULL);
  403.       exit(1);
  404.     }
  405.     bcopy((char *)hp->h_addr, (char *)&sin->sin_addr,
  406.       sizeof sin->sin_addr);
  407.   }
  408.   s = socket(AF_INET, SOCK_DGRAM, 0);
  409.   if (s < 0) {
  410.     perror("arp: socket");
  411.     exit(1);
  412.   }
  413.   if (IoctlSocket(s, SIOCDARP, (caddr_t)&ar) < 0) {
  414.     if (errno == ENXIO)
  415.       printf("%s (%s) -- no entry\n",
  416.          host, inet_ntoa(sin->sin_addr));
  417.     else
  418.       perror("SIOCDARP");
  419.     exit(1);
  420.   }
  421.   CloseSocket(s);
  422.   printf("%s (%s) deleted\n", host, inet_ntoa(sin->sin_addr));
  423. }
  424.  
  425. /*
  426.  * Dump the entire arp table
  427.  */
  428. static void 
  429. dump(char *host)
  430. {
  431.   struct arptabreq atr; 
  432.   struct arpreq *ar;
  433.   struct sockaddr_in *sin;
  434.   int s, bynumber;
  435.   long n;
  436.   
  437.   bzero((caddr_t)&atr, sizeof atr);
  438.  
  439.   /* Identify the used interface according the host/net name */
  440.   sin = (struct sockaddr_in *)&atr.atr_arpreq.arp_pa;
  441.   sin->sin_len = sizeof(*sin);
  442.   sin->sin_family = AF_INET;
  443.   sin->sin_addr.s_addr = inet_addr(host);
  444.   if (sin->sin_addr.s_addr == -1) {
  445.     struct hostent *hp;
  446.     struct netent *np = NULL;
  447.     if (!(hp = gethostbyname(host)) &&
  448.     !(np = getnetbyname(host))) {
  449.       fprintf(stderr, "arp: %s: ", host);
  450.       herror((char *)NULL);
  451.       exit(1);
  452.     }
  453.     if (hp) 
  454.       bcopy((char *)hp->h_addr, (char *)&sin->sin_addr, sizeof sin->sin_addr);
  455.     else
  456.       bcopy((char *)&np->n_net, (char *)&sin->sin_addr, sizeof np->n_net);
  457.   }
  458.  
  459.   s = socket(AF_INET, SOCK_DGRAM, 0);
  460.   if (s < 0) {
  461.     perror("arp: socket");
  462.     exit(1);
  463.   }
  464.  
  465.   if (IoctlSocket(s, SIOCGARPT, (caddr_t)&atr) < 0) {
  466.     perror("SIOCGARPT");
  467.     exit(1);
  468.   }
  469.  
  470.   n = atr.atr_size = atr.atr_inuse;
  471.   if (n) {
  472.     ar = atr.atr_table = malloc(sizeof(*ar) * n);
  473.     if (!ar) {
  474.       perror("arp: malloc");
  475.       exit(1);
  476.     }
  477.     if (IoctlSocket(s, SIOCGARPT, (caddr_t)&atr) < 0) {
  478.       perror("SIOCGARPT");
  479.       exit(1);
  480.     }
  481.     /* Entries may be deleted */
  482.     n = max(n, atr.atr_inuse);
  483.   }
  484.   CloseSocket(s);
  485.  
  486.   bynumber = 0;
  487.   while (n-- > 0) {
  488.     bynumber = arpreq_print(ar++, bynumber);
  489.   }
  490. }
  491.  
  492. static int
  493. arpreq_print(struct arpreq *ar, int bynumber)
  494. {
  495.   struct sockaddr_in *sin;
  496.   struct hostent *hp;
  497.   char *host;
  498.  
  499.   sin = (struct sockaddr_in *)&ar->arp_pa;
  500.  
  501.   if (bynumber == 0)
  502.     hp = gethostbyaddr((caddr_t)&sin->sin_addr, 
  503.                sizeof(struct in_addr), AF_INET);
  504.   else
  505.     hp = 0;
  506.  
  507.   if (hp)
  508.     host = hp->h_name;
  509.   else {
  510.     host = "?";
  511.     if (h_errno == TRY_AGAIN)
  512.       bynumber = 1;
  513.   }
  514.  
  515.   printf("%s (%s) at ", host, inet_ntoa(sin->sin_addr));
  516.   if (ar->arp_flags & ATF_COM)
  517.     sana_print(ar->arp_ha.sa_data, ar->arp_ha.sa_len - 2);
  518.   else
  519.     printf("(incomplete)");
  520.   if (ar->arp_flags & ATF_PERM)
  521.     printf(" permanent");
  522.   if (ar->arp_flags & ATF_PUBL)
  523.     printf(" published");
  524.   if (ar->arp_flags & ATF_USETRAILERS)
  525.     printf(" trailers");
  526.   printf("\n");
  527.  
  528.   return bynumber;
  529. }
  530.  
  531. static void
  532. sana_print(const u_char *cp, int len)
  533. {
  534.   char format[] = 
  535.     "%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx";
  536.   int i; long o[16];
  537.  
  538.   if (len) {
  539.     format[4*len - 1] = '\0';
  540.     for (i = 0; i < len; i++)
  541.       o[i] = cp[i];
  542.     vprintf(format, (va_list)o);
  543.   }
  544. }
  545.  
  546. static int
  547. sana_aton(const char *str, u_char *n, u_char *lenp)
  548. {
  549.   int i, chars, o[16];
  550.   u_char c;
  551.   const char *a = str;
  552.  
  553.   for (i = 0; i < 16; a++) {
  554.     o[i] = chars = 0;
  555.     while ((c = *a - '0') <= 9 
  556.       || (c = c - 'A' + '0' + 10) >= 9 && c < 16  /*ABCDEF*/
  557.       || (c = c - 'a' + 'A') >= 9 && c < 16) /*abcdef*/ {
  558.       a++; chars++;
  559.       o[i] = (o[i] << 4) + c;
  560.       if (o[i] >= 0x100)
  561.     return 1;
  562.     }
  563.     if (!chars)
  564.       return 1;
  565.     i++;
  566.     if (*a == '\0')
  567.       break;
  568.     else if (*a == ':')
  569.       continue;
  570.     return 1;
  571.   }
  572.  
  573.   if (i >= 16) {
  574.     fprintf(stderr, "arp: invalid SANA-II address '%s'\n", str);
  575.     return (1);
  576.   }
  577.  
  578.   *lenp = i;
  579.   while (i-- > 0)
  580.     n[i] = o[i];
  581.   return 0;
  582. }
  583.  
  584. static void
  585. usage(void)
  586. {
  587.   printf(usage_str);
  588.  
  589.   exit(1);
  590. }
  591.