xref: /titanic_44/usr/src/cmd/cmd-inet/usr.sbin/arp.c (revision 69bb4bb45c98da60d21839c4dc3c01ea1be60585)
17c478bd9Sstevel@tonic-gate /*
2*69bb4bb4Scarlsonj  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
37c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate  */
57c478bd9Sstevel@tonic-gate /*
67c478bd9Sstevel@tonic-gate  * Copyright (c) 1984 Regents of the University of California.
77c478bd9Sstevel@tonic-gate  * All rights reserved.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * This code is derived from software contributed to Berkeley by
107c478bd9Sstevel@tonic-gate  * Sun Microsystems, Inc.
117c478bd9Sstevel@tonic-gate  *
127c478bd9Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
137c478bd9Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
147c478bd9Sstevel@tonic-gate  * are met:
157c478bd9Sstevel@tonic-gate  * 1. Redistributions of source code must retain the above copyright
167c478bd9Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
177c478bd9Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
187c478bd9Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in the
197c478bd9Sstevel@tonic-gate  *    documentation and/or other materials provided with the distribution.
207c478bd9Sstevel@tonic-gate  * 3. All advertising materials mentioning features or use of this software
217c478bd9Sstevel@tonic-gate  *    must display the following acknowledgement:
227c478bd9Sstevel@tonic-gate  *      This product includes software developed by the University of
237c478bd9Sstevel@tonic-gate  *      California, Berkeley and its contributors.
247c478bd9Sstevel@tonic-gate  * 4. Neither the name of the University nor the names of its contributors
257c478bd9Sstevel@tonic-gate  *    may be used to endorse or promote products derived from this software
267c478bd9Sstevel@tonic-gate  *    without specific prior written permission.
277c478bd9Sstevel@tonic-gate  *
287c478bd9Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
297c478bd9Sstevel@tonic-gate  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
307c478bd9Sstevel@tonic-gate  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
317c478bd9Sstevel@tonic-gate  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
327c478bd9Sstevel@tonic-gate  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
337c478bd9Sstevel@tonic-gate  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
347c478bd9Sstevel@tonic-gate  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
357c478bd9Sstevel@tonic-gate  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
367c478bd9Sstevel@tonic-gate  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
377c478bd9Sstevel@tonic-gate  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
387c478bd9Sstevel@tonic-gate  * SUCH DAMAGE.
397c478bd9Sstevel@tonic-gate  */
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
447c478bd9Sstevel@tonic-gate 
457c478bd9Sstevel@tonic-gate /*
467c478bd9Sstevel@tonic-gate  * arp - display, set, and delete arp table entries
477c478bd9Sstevel@tonic-gate  */
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate #include <stdio.h>
507c478bd9Sstevel@tonic-gate #include <sys/types.h>
517c478bd9Sstevel@tonic-gate #include <sys/socket.h>
527c478bd9Sstevel@tonic-gate #include <netinet/in.h>
537c478bd9Sstevel@tonic-gate #include <sys/ioctl.h>
547c478bd9Sstevel@tonic-gate #include <errno.h>
557c478bd9Sstevel@tonic-gate #include <netdb.h>
567c478bd9Sstevel@tonic-gate #include <net/if.h>
577c478bd9Sstevel@tonic-gate #include <net/if_arp.h>
587c478bd9Sstevel@tonic-gate #include <stdlib.h>
597c478bd9Sstevel@tonic-gate #include <unistd.h>
607c478bd9Sstevel@tonic-gate #include <string.h>
617c478bd9Sstevel@tonic-gate #include <arpa/inet.h>
627c478bd9Sstevel@tonic-gate #include <net/if_types.h>
637c478bd9Sstevel@tonic-gate #include <net/if_dl.h>
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate static int file(char *);
667c478bd9Sstevel@tonic-gate static int set(int, char *[]);
677c478bd9Sstevel@tonic-gate static void get(char *);
687c478bd9Sstevel@tonic-gate static void delete(char *);
697c478bd9Sstevel@tonic-gate static void usage(void);
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate int
main(int argc,char * argv[])727c478bd9Sstevel@tonic-gate main(int argc, char *argv[])
737c478bd9Sstevel@tonic-gate {
747c478bd9Sstevel@tonic-gate 	int c, nflags = 0, argsleft;
757c478bd9Sstevel@tonic-gate 	int n_flag, a_flag, d_flag, f_flag, s_flag;
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate 	n_flag = a_flag = d_flag = f_flag = s_flag = 0;
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate #define	CASE(x, y)				\
807c478bd9Sstevel@tonic-gate 		case x:				\
817c478bd9Sstevel@tonic-gate 			if (nflags > 0) {	\
827c478bd9Sstevel@tonic-gate 				usage();	\
837c478bd9Sstevel@tonic-gate 				exit(1);	\
847c478bd9Sstevel@tonic-gate 			} else			\
857c478bd9Sstevel@tonic-gate 				y##_flag = 1;	\
867c478bd9Sstevel@tonic-gate 				nflags++;	\
877c478bd9Sstevel@tonic-gate 			break
887c478bd9Sstevel@tonic-gate 
897c478bd9Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "nadfs")) != EOF) {
907c478bd9Sstevel@tonic-gate 		switch (c) {
917c478bd9Sstevel@tonic-gate 		case '?':
927c478bd9Sstevel@tonic-gate 			usage();
937c478bd9Sstevel@tonic-gate 			exit(1);
947c478bd9Sstevel@tonic-gate 			/* NOTREACHED */
957c478bd9Sstevel@tonic-gate 			break;
967c478bd9Sstevel@tonic-gate 		case 'n':
977c478bd9Sstevel@tonic-gate 			n_flag = 1;
987c478bd9Sstevel@tonic-gate 			break;
997c478bd9Sstevel@tonic-gate 		CASE('a', a);
1007c478bd9Sstevel@tonic-gate 		CASE('d', d);
1017c478bd9Sstevel@tonic-gate 		CASE('f', f);
1027c478bd9Sstevel@tonic-gate 		CASE('s', s);
1037c478bd9Sstevel@tonic-gate 		}
1047c478bd9Sstevel@tonic-gate 	}
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate #undef CASE
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate 	/*
1097c478bd9Sstevel@tonic-gate 	 * -n only allowed with -a
1107c478bd9Sstevel@tonic-gate 	 */
1117c478bd9Sstevel@tonic-gate 	if (n_flag && !a_flag) {
1127c478bd9Sstevel@tonic-gate 		usage();
1137c478bd9Sstevel@tonic-gate 		exit(1);
1147c478bd9Sstevel@tonic-gate 	}
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate 	argsleft = argc - optind;
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate 	if (a_flag && (argsleft == 0)) {
1197c478bd9Sstevel@tonic-gate 		/*
1207c478bd9Sstevel@tonic-gate 		 * the easiest way to get the complete arp table
1217c478bd9Sstevel@tonic-gate 		 * is to let netstat, which prints it as part of
1227c478bd9Sstevel@tonic-gate 		 * the MIB statistics, do it.
1237c478bd9Sstevel@tonic-gate 		 */
1247c478bd9Sstevel@tonic-gate 		(void) execl("/usr/bin/netstat", "netstat",
1257c478bd9Sstevel@tonic-gate 		    (n_flag ? "-np" : "-p"),
1267c478bd9Sstevel@tonic-gate 		    "-f", "inet", (char *)0);
1277c478bd9Sstevel@tonic-gate 		exit(1);
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate 	} else if (s_flag && (argsleft >= 2)) {
1307c478bd9Sstevel@tonic-gate 		if (set(argsleft, &argv[optind]) != 0)
1317c478bd9Sstevel@tonic-gate 			exit(1);
1327c478bd9Sstevel@tonic-gate 
1337c478bd9Sstevel@tonic-gate 	} else if (d_flag && (argsleft == 1)) {
1347c478bd9Sstevel@tonic-gate 		delete(argv[optind]);
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate 	} else if (f_flag && (argsleft == 1)) {
1377c478bd9Sstevel@tonic-gate 		if (file(argv[optind]) != 0)
1387c478bd9Sstevel@tonic-gate 			exit(1);
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate 	} else if ((nflags == 0) && (argsleft == 1)) {
1417c478bd9Sstevel@tonic-gate 		get(argv[optind]);
1427c478bd9Sstevel@tonic-gate 
1437c478bd9Sstevel@tonic-gate 	} else {
1447c478bd9Sstevel@tonic-gate 		usage();
1457c478bd9Sstevel@tonic-gate 		exit(1);
1467c478bd9Sstevel@tonic-gate 	}
1477c478bd9Sstevel@tonic-gate 	return (0);
1487c478bd9Sstevel@tonic-gate }
1497c478bd9Sstevel@tonic-gate 
1507c478bd9Sstevel@tonic-gate /*
1517c478bd9Sstevel@tonic-gate  * Process a file to set standard arp entries
1527c478bd9Sstevel@tonic-gate  */
153*69bb4bb4Scarlsonj static int
file(char * name)154*69bb4bb4Scarlsonj file(char *name)
1557c478bd9Sstevel@tonic-gate {
1567c478bd9Sstevel@tonic-gate 	/*
1577c478bd9Sstevel@tonic-gate 	 * A line of input can be:
158*69bb4bb4Scarlsonj 	 * <hostname> <macaddr> ["temp"] ["pub"] ["trail"] ["permanent"]
1597c478bd9Sstevel@tonic-gate 	 */
1607c478bd9Sstevel@tonic-gate #define	MAX_LINE_LEN	(MAXHOSTNAMELEN + \
161*69bb4bb4Scarlsonj 	sizeof (" xx:xx:xx:xx:xx:xx temp pub trail permanent\n"))
1627c478bd9Sstevel@tonic-gate #define	MIN_ARGS	2
1637c478bd9Sstevel@tonic-gate #define	MAX_ARGS	5
1647c478bd9Sstevel@tonic-gate 
1657c478bd9Sstevel@tonic-gate 	FILE *fp;
1667c478bd9Sstevel@tonic-gate 	char line[MAX_LINE_LEN];
1677c478bd9Sstevel@tonic-gate 	int retval;
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate 	if ((fp = fopen(name, "r")) == NULL) {
1707c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "arp: cannot open %s\n", name);
1717c478bd9Sstevel@tonic-gate 		exit(1);
1727c478bd9Sstevel@tonic-gate 	}
1737c478bd9Sstevel@tonic-gate 
1747c478bd9Sstevel@tonic-gate 	retval = 0;
1757c478bd9Sstevel@tonic-gate 	while (fgets(line, MAX_LINE_LEN, fp) != NULL) {
1767c478bd9Sstevel@tonic-gate 		char line_copy[MAX_LINE_LEN];
1777c478bd9Sstevel@tonic-gate 		char *args[MAX_ARGS];
1787c478bd9Sstevel@tonic-gate 		char *start;
1797c478bd9Sstevel@tonic-gate 		int i;
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate 		/*
1827c478bd9Sstevel@tonic-gate 		 * Keep a copy of the un-altered line for error
1837c478bd9Sstevel@tonic-gate 		 * reporting.
1847c478bd9Sstevel@tonic-gate 		 */
1857c478bd9Sstevel@tonic-gate 		(void) strlcpy(line_copy, line, MAX_LINE_LEN);
1867c478bd9Sstevel@tonic-gate 
1877c478bd9Sstevel@tonic-gate 		start = line_copy;
1887c478bd9Sstevel@tonic-gate 		for (i = 0; i < MAX_ARGS; i++) {
1897c478bd9Sstevel@tonic-gate 			if ((args[i] = strtok(start, " \t\n")) == NULL)
1907c478bd9Sstevel@tonic-gate 				break;
1917c478bd9Sstevel@tonic-gate 
1927c478bd9Sstevel@tonic-gate 			start = NULL;
1937c478bd9Sstevel@tonic-gate 		}
1947c478bd9Sstevel@tonic-gate 
1957c478bd9Sstevel@tonic-gate 		if (i < MIN_ARGS) {
1967c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "arp: bad line: %s\n",
1977c478bd9Sstevel@tonic-gate 			    line);
1987c478bd9Sstevel@tonic-gate 			retval = 1;
1997c478bd9Sstevel@tonic-gate 			continue;
2007c478bd9Sstevel@tonic-gate 		}
2017c478bd9Sstevel@tonic-gate 
2027c478bd9Sstevel@tonic-gate 		if (set(i, args) != 0)
2037c478bd9Sstevel@tonic-gate 			retval = 1;
2047c478bd9Sstevel@tonic-gate 	}
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate #undef	MAX_LINE_LEN
2077c478bd9Sstevel@tonic-gate #undef	MIN_ARGS
2087c478bd9Sstevel@tonic-gate #undef	MAX_ARGS
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate 	(void) fclose(fp);
2117c478bd9Sstevel@tonic-gate 	return (retval);
2127c478bd9Sstevel@tonic-gate }
2137c478bd9Sstevel@tonic-gate 
2147c478bd9Sstevel@tonic-gate /*
2157c478bd9Sstevel@tonic-gate  * Set an individual arp entry
2167c478bd9Sstevel@tonic-gate  */
217*69bb4bb4Scarlsonj static int
set(int argc,char * argv[])218*69bb4bb4Scarlsonj set(int argc, char *argv[])
2197c478bd9Sstevel@tonic-gate {
2207c478bd9Sstevel@tonic-gate 	struct xarpreq ar;
2217c478bd9Sstevel@tonic-gate 	struct hostent *hp;
2227c478bd9Sstevel@tonic-gate 	struct sockaddr_in *sin;
2237c478bd9Sstevel@tonic-gate 	uchar_t *ea;
2247c478bd9Sstevel@tonic-gate 	int s;
2257c478bd9Sstevel@tonic-gate 	char *host = argv[0], *eaddr = argv[1];
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate 	argc -= 2;
2287c478bd9Sstevel@tonic-gate 	argv += 2;
2297c478bd9Sstevel@tonic-gate 	(void) memset(&ar, 0, sizeof (ar));
2307c478bd9Sstevel@tonic-gate 	sin = (struct sockaddr_in *)&ar.xarp_pa;
2317c478bd9Sstevel@tonic-gate 	sin->sin_family = AF_INET;
2327c478bd9Sstevel@tonic-gate 	sin->sin_addr.s_addr = inet_addr(host);
2337c478bd9Sstevel@tonic-gate 	if (sin->sin_addr.s_addr == (in_addr_t)-1) {
2347c478bd9Sstevel@tonic-gate 		hp = gethostbyname(host);
2357c478bd9Sstevel@tonic-gate 		if (hp == NULL) {
2367c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "arp: %s: unknown host\n",
2377c478bd9Sstevel@tonic-gate 			    host);
2387c478bd9Sstevel@tonic-gate 			return (1);
2397c478bd9Sstevel@tonic-gate 		}
2407c478bd9Sstevel@tonic-gate 		(void) memcpy(&sin->sin_addr, hp->h_addr,
2417c478bd9Sstevel@tonic-gate 		    sizeof (sin->sin_addr));
2427c478bd9Sstevel@tonic-gate 	}
2437c478bd9Sstevel@tonic-gate 	ea = _link_aton(eaddr, &s);
2447c478bd9Sstevel@tonic-gate 	if (ea == NULL) {
2457c478bd9Sstevel@tonic-gate 		if (s == -1) {
2467c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
2477c478bd9Sstevel@tonic-gate 			    "arp: invalid link layer address '%s'\n", eaddr);
2487c478bd9Sstevel@tonic-gate 			return (1);
2497c478bd9Sstevel@tonic-gate 		}
2507c478bd9Sstevel@tonic-gate 		perror("arp: nomem");
2517c478bd9Sstevel@tonic-gate 		exit(1);
2527c478bd9Sstevel@tonic-gate 	}
2537c478bd9Sstevel@tonic-gate 	ar.xarp_ha.sdl_alen = s;
2547c478bd9Sstevel@tonic-gate 	(void) memcpy(LLADDR(&ar.xarp_ha), ea, ar.xarp_ha.sdl_alen);
2557c478bd9Sstevel@tonic-gate 	free(ea);
2567c478bd9Sstevel@tonic-gate 	ar.xarp_ha.sdl_family = AF_LINK;
2577c478bd9Sstevel@tonic-gate 	ar.xarp_flags = ATF_PERM;
2587c478bd9Sstevel@tonic-gate 	while (argc-- > 0) {
259*69bb4bb4Scarlsonj 		if (strncmp(argv[0], "temp", 4) == 0) {
2607c478bd9Sstevel@tonic-gate 			ar.xarp_flags &= ~ATF_PERM;
261*69bb4bb4Scarlsonj 		} else if (strncmp(argv[0], "pub", 3) == 0) {
2627c478bd9Sstevel@tonic-gate 			ar.xarp_flags |= ATF_PUBL;
263*69bb4bb4Scarlsonj 		} else if (strncmp(argv[0], "trail", 5) == 0) {
2647c478bd9Sstevel@tonic-gate 			ar.xarp_flags |= ATF_USETRAILERS;
265*69bb4bb4Scarlsonj 		} else if (strcmp(argv[0], "permanent") == 0) {
266*69bb4bb4Scarlsonj 			ar.xarp_flags |= ATF_AUTHORITY;
267*69bb4bb4Scarlsonj 		} else {
268*69bb4bb4Scarlsonj 			(void) fprintf(stderr,
269*69bb4bb4Scarlsonj 			    "arp: unknown keyword '%s'\n", argv[0]);
270*69bb4bb4Scarlsonj 			return (1);
271*69bb4bb4Scarlsonj 		}
2727c478bd9Sstevel@tonic-gate 		argv++;
2737c478bd9Sstevel@tonic-gate 	}
2747c478bd9Sstevel@tonic-gate 
275*69bb4bb4Scarlsonj 	if ((ar.xarp_flags & (ATF_PERM|ATF_AUTHORITY)) == ATF_AUTHORITY) {
276*69bb4bb4Scarlsonj 		(void) fprintf(stderr, "arp: 'temp' and 'permanent' flags are "
277*69bb4bb4Scarlsonj 		    "not usable together.\n");
278*69bb4bb4Scarlsonj 		return (1);
279*69bb4bb4Scarlsonj 	}
280*69bb4bb4Scarlsonj 
2817c478bd9Sstevel@tonic-gate 	s = socket(AF_INET, SOCK_DGRAM, 0);
2827c478bd9Sstevel@tonic-gate 	if (s < 0) {
2837c478bd9Sstevel@tonic-gate 		perror("arp: socket");
2847c478bd9Sstevel@tonic-gate 		exit(1);
2857c478bd9Sstevel@tonic-gate 	}
2867c478bd9Sstevel@tonic-gate 	if (ioctl(s, SIOCSXARP, (caddr_t)&ar) < 0) {
2877c478bd9Sstevel@tonic-gate 		perror(host);
2887c478bd9Sstevel@tonic-gate 		exit(1);
2897c478bd9Sstevel@tonic-gate 	}
2907c478bd9Sstevel@tonic-gate 	(void) close(s);
2917c478bd9Sstevel@tonic-gate 	return (0);
2927c478bd9Sstevel@tonic-gate }
2937c478bd9Sstevel@tonic-gate 
2947c478bd9Sstevel@tonic-gate /*
2957c478bd9Sstevel@tonic-gate  * Display an individual arp entry
2967c478bd9Sstevel@tonic-gate  */
297*69bb4bb4Scarlsonj static void
get(char * host)298*69bb4bb4Scarlsonj get(char *host)
2997c478bd9Sstevel@tonic-gate {
3007c478bd9Sstevel@tonic-gate 	struct xarpreq ar;
3017c478bd9Sstevel@tonic-gate 	struct hostent *hp;
3027c478bd9Sstevel@tonic-gate 	struct sockaddr_in *sin;
3037c478bd9Sstevel@tonic-gate 	uchar_t *ea;
3047c478bd9Sstevel@tonic-gate 	int s;
3057c478bd9Sstevel@tonic-gate 	char *str = NULL;
3067c478bd9Sstevel@tonic-gate 
3077c478bd9Sstevel@tonic-gate 	(void) memset(&ar, 0, sizeof (ar));
3087c478bd9Sstevel@tonic-gate 	sin = (struct sockaddr_in *)&ar.xarp_pa;
3097c478bd9Sstevel@tonic-gate 	sin->sin_family = AF_INET;
3107c478bd9Sstevel@tonic-gate 	sin->sin_addr.s_addr = inet_addr(host);
3117c478bd9Sstevel@tonic-gate 	if (sin->sin_addr.s_addr == (in_addr_t)-1) {
3127c478bd9Sstevel@tonic-gate 		hp = gethostbyname(host);
3137c478bd9Sstevel@tonic-gate 		if (hp == NULL) {
3147c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "arp: %s: unknown host\n",
3157c478bd9Sstevel@tonic-gate 			    host);
3167c478bd9Sstevel@tonic-gate 			exit(1);
3177c478bd9Sstevel@tonic-gate 		}
3187c478bd9Sstevel@tonic-gate 		(void) memcpy(&sin->sin_addr, hp->h_addr,
3197c478bd9Sstevel@tonic-gate 		    sizeof (sin->sin_addr));
3207c478bd9Sstevel@tonic-gate 	}
3217c478bd9Sstevel@tonic-gate 	s = socket(AF_INET, SOCK_DGRAM, 0);
3227c478bd9Sstevel@tonic-gate 	if (s < 0) {
3237c478bd9Sstevel@tonic-gate 		perror("arp: socket");
3247c478bd9Sstevel@tonic-gate 		exit(1);
3257c478bd9Sstevel@tonic-gate 	}
3267c478bd9Sstevel@tonic-gate 	ar.xarp_ha.sdl_family = AF_LINK;
3277c478bd9Sstevel@tonic-gate 	if (ioctl(s, SIOCGXARP, (caddr_t)&ar) < 0) {
3287c478bd9Sstevel@tonic-gate 		if (errno == ENXIO)
3297c478bd9Sstevel@tonic-gate 			(void) printf("%s (%s) -- no entry\n",
3307c478bd9Sstevel@tonic-gate 			    host, inet_ntoa(sin->sin_addr));
3317c478bd9Sstevel@tonic-gate 		else
3327c478bd9Sstevel@tonic-gate 			perror("SIOCGXARP");
3337c478bd9Sstevel@tonic-gate 		exit(1);
3347c478bd9Sstevel@tonic-gate 	}
3357c478bd9Sstevel@tonic-gate 	(void) close(s);
3367c478bd9Sstevel@tonic-gate 	ea = (uchar_t *)LLADDR(&ar.xarp_ha);
3377c478bd9Sstevel@tonic-gate 	if (ar.xarp_flags & ATF_COM) {
3387c478bd9Sstevel@tonic-gate 		str = _link_ntoa(ea, str, ar.xarp_ha.sdl_alen, IFT_OTHER);
3397c478bd9Sstevel@tonic-gate 		if (str != NULL) {
3407c478bd9Sstevel@tonic-gate 			(void) printf("%s (%s) at %s", host,
3417c478bd9Sstevel@tonic-gate 			    inet_ntoa(sin->sin_addr), str);
3427c478bd9Sstevel@tonic-gate 			free(str);
3437c478bd9Sstevel@tonic-gate 		} else {
3447c478bd9Sstevel@tonic-gate 			perror("arp: nomem");
3457c478bd9Sstevel@tonic-gate 			exit(1);
3467c478bd9Sstevel@tonic-gate 		}
3477c478bd9Sstevel@tonic-gate 	} else {
3487c478bd9Sstevel@tonic-gate 		(void) printf("%s (%s) at (incomplete)", host,
3497c478bd9Sstevel@tonic-gate 		    inet_ntoa(sin->sin_addr));
3507c478bd9Sstevel@tonic-gate 	}
351*69bb4bb4Scarlsonj 	if (!(ar.xarp_flags & ATF_PERM))
352*69bb4bb4Scarlsonj 		(void) printf(" temp");
3537c478bd9Sstevel@tonic-gate 	if (ar.xarp_flags & ATF_PUBL)
354*69bb4bb4Scarlsonj 		(void) printf(" pub");
3557c478bd9Sstevel@tonic-gate 	if (ar.xarp_flags & ATF_USETRAILERS)
356*69bb4bb4Scarlsonj 		(void) printf(" trail");
357*69bb4bb4Scarlsonj 	if (ar.xarp_flags & ATF_AUTHORITY)
358*69bb4bb4Scarlsonj 		(void) printf(" permanent");
3597c478bd9Sstevel@tonic-gate 	(void) printf("\n");
3607c478bd9Sstevel@tonic-gate }
3617c478bd9Sstevel@tonic-gate 
3627c478bd9Sstevel@tonic-gate /*
3637c478bd9Sstevel@tonic-gate  * Delete an arp entry
3647c478bd9Sstevel@tonic-gate  */
365*69bb4bb4Scarlsonj static void
delete(char * host)366*69bb4bb4Scarlsonj delete(char *host)
3677c478bd9Sstevel@tonic-gate {
3687c478bd9Sstevel@tonic-gate 	struct xarpreq ar;
3697c478bd9Sstevel@tonic-gate 	struct hostent *hp;
3707c478bd9Sstevel@tonic-gate 	struct sockaddr_in *sin;
3717c478bd9Sstevel@tonic-gate 	int s;
3727c478bd9Sstevel@tonic-gate 
3737c478bd9Sstevel@tonic-gate 	(void) memset(&ar, 0, sizeof (ar));
3747c478bd9Sstevel@tonic-gate 	sin = (struct sockaddr_in *)&ar.xarp_pa;
3757c478bd9Sstevel@tonic-gate 	sin->sin_family = AF_INET;
3767c478bd9Sstevel@tonic-gate 	sin->sin_addr.s_addr = inet_addr(host);
3777c478bd9Sstevel@tonic-gate 	if (sin->sin_addr.s_addr == (in_addr_t)-1) {
3787c478bd9Sstevel@tonic-gate 		hp = gethostbyname(host);
3797c478bd9Sstevel@tonic-gate 		if (hp == NULL) {
3807c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "arp: %s: unknown host\n",
3817c478bd9Sstevel@tonic-gate 			    host);
3827c478bd9Sstevel@tonic-gate 			exit(1);
3837c478bd9Sstevel@tonic-gate 		}
3847c478bd9Sstevel@tonic-gate 		(void) memcpy(&sin->sin_addr, hp->h_addr,
3857c478bd9Sstevel@tonic-gate 		    sizeof (sin->sin_addr));
3867c478bd9Sstevel@tonic-gate 	}
3877c478bd9Sstevel@tonic-gate 	s = socket(AF_INET, SOCK_DGRAM, 0);
3887c478bd9Sstevel@tonic-gate 	if (s < 0) {
3897c478bd9Sstevel@tonic-gate 		perror("arp: socket");
3907c478bd9Sstevel@tonic-gate 		exit(1);
3917c478bd9Sstevel@tonic-gate 	}
3927c478bd9Sstevel@tonic-gate 	ar.xarp_ha.sdl_family = AF_LINK;
3937c478bd9Sstevel@tonic-gate 	if (ioctl(s, SIOCDXARP, (caddr_t)&ar) < 0) {
3947c478bd9Sstevel@tonic-gate 		if (errno == ENXIO)
3957c478bd9Sstevel@tonic-gate 			(void) printf("%s (%s) -- no entry\n",
3967c478bd9Sstevel@tonic-gate 			    host, inet_ntoa(sin->sin_addr));
3977c478bd9Sstevel@tonic-gate 		else
3987c478bd9Sstevel@tonic-gate 			perror("SIOCDXARP");
3997c478bd9Sstevel@tonic-gate 		exit(1);
4007c478bd9Sstevel@tonic-gate 	}
4017c478bd9Sstevel@tonic-gate 	(void) close(s);
4027c478bd9Sstevel@tonic-gate 	(void) printf("%s (%s) deleted\n", host, inet_ntoa(sin->sin_addr));
4037c478bd9Sstevel@tonic-gate }
4047c478bd9Sstevel@tonic-gate 
405*69bb4bb4Scarlsonj static void
usage(void)406*69bb4bb4Scarlsonj usage(void)
4077c478bd9Sstevel@tonic-gate {
4087c478bd9Sstevel@tonic-gate 	(void) printf("Usage: arp hostname\n");
4097c478bd9Sstevel@tonic-gate 	(void) printf("       arp -a [-n]\n");
4107c478bd9Sstevel@tonic-gate 	(void) printf("       arp -d hostname\n");
4117c478bd9Sstevel@tonic-gate 	(void) printf("       arp -s hostname ether_addr "
412*69bb4bb4Scarlsonj 	    "[temp] [pub] [trail] [permanent]\n");
4137c478bd9Sstevel@tonic-gate 	(void) printf("       arp -f filename\n");
4147c478bd9Sstevel@tonic-gate }
415