xref: /titanic_52/usr/src/cmd/cmd-inet/usr.sbin/arp.c (revision 2545d10d08f1bf15162c2c0998fcae535d08c0d9)
17c478bd9Sstevel@tonic-gate /*
269bb4bb4Scarlsonj  * 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  * arp - display, set, and delete arp table entries
447c478bd9Sstevel@tonic-gate  */
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate #include <stdio.h>
477c478bd9Sstevel@tonic-gate #include <sys/types.h>
487c478bd9Sstevel@tonic-gate #include <sys/socket.h>
497c478bd9Sstevel@tonic-gate #include <netinet/in.h>
507c478bd9Sstevel@tonic-gate #include <sys/ioctl.h>
517c478bd9Sstevel@tonic-gate #include <errno.h>
527c478bd9Sstevel@tonic-gate #include <netdb.h>
537c478bd9Sstevel@tonic-gate #include <net/if.h>
547c478bd9Sstevel@tonic-gate #include <net/if_arp.h>
557c478bd9Sstevel@tonic-gate #include <stdlib.h>
567c478bd9Sstevel@tonic-gate #include <unistd.h>
577c478bd9Sstevel@tonic-gate #include <string.h>
587c478bd9Sstevel@tonic-gate #include <arpa/inet.h>
597c478bd9Sstevel@tonic-gate #include <net/if_types.h>
607c478bd9Sstevel@tonic-gate #include <net/if_dl.h>
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate static int file(char *);
637c478bd9Sstevel@tonic-gate static int set(int, char *[]);
647c478bd9Sstevel@tonic-gate static void get(char *);
657c478bd9Sstevel@tonic-gate static void delete(char *);
667c478bd9Sstevel@tonic-gate static void usage(void);
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate int
697c478bd9Sstevel@tonic-gate main(int argc, char *argv[])
707c478bd9Sstevel@tonic-gate {
717c478bd9Sstevel@tonic-gate 	int c, nflags = 0, argsleft;
727c478bd9Sstevel@tonic-gate 	int n_flag, a_flag, d_flag, f_flag, s_flag;
737c478bd9Sstevel@tonic-gate 
747c478bd9Sstevel@tonic-gate 	n_flag = a_flag = d_flag = f_flag = s_flag = 0;
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate #define	CASE(x, y)				\
777c478bd9Sstevel@tonic-gate 		case x:				\
787c478bd9Sstevel@tonic-gate 			if (nflags > 0) {	\
797c478bd9Sstevel@tonic-gate 				usage();	\
807c478bd9Sstevel@tonic-gate 				exit(1);	\
817c478bd9Sstevel@tonic-gate 			} else			\
827c478bd9Sstevel@tonic-gate 				y##_flag = 1;	\
837c478bd9Sstevel@tonic-gate 				nflags++;	\
847c478bd9Sstevel@tonic-gate 			break
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "nadfs")) != EOF) {
877c478bd9Sstevel@tonic-gate 		switch (c) {
887c478bd9Sstevel@tonic-gate 		case '?':
897c478bd9Sstevel@tonic-gate 			usage();
907c478bd9Sstevel@tonic-gate 			exit(1);
917c478bd9Sstevel@tonic-gate 			/* NOTREACHED */
927c478bd9Sstevel@tonic-gate 			break;
937c478bd9Sstevel@tonic-gate 		case 'n':
947c478bd9Sstevel@tonic-gate 			n_flag = 1;
957c478bd9Sstevel@tonic-gate 			break;
967c478bd9Sstevel@tonic-gate 		CASE('a', a);
977c478bd9Sstevel@tonic-gate 		CASE('d', d);
987c478bd9Sstevel@tonic-gate 		CASE('f', f);
997c478bd9Sstevel@tonic-gate 		CASE('s', s);
1007c478bd9Sstevel@tonic-gate 		}
1017c478bd9Sstevel@tonic-gate 	}
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate #undef CASE
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate 	/*
1067c478bd9Sstevel@tonic-gate 	 * -n only allowed with -a
1077c478bd9Sstevel@tonic-gate 	 */
1087c478bd9Sstevel@tonic-gate 	if (n_flag && !a_flag) {
1097c478bd9Sstevel@tonic-gate 		usage();
1107c478bd9Sstevel@tonic-gate 		exit(1);
1117c478bd9Sstevel@tonic-gate 	}
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate 	argsleft = argc - optind;
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate 	if (a_flag && (argsleft == 0)) {
1167c478bd9Sstevel@tonic-gate 		/*
1177c478bd9Sstevel@tonic-gate 		 * the easiest way to get the complete arp table
1187c478bd9Sstevel@tonic-gate 		 * is to let netstat, which prints it as part of
1197c478bd9Sstevel@tonic-gate 		 * the MIB statistics, do it.
1207c478bd9Sstevel@tonic-gate 		 */
1217c478bd9Sstevel@tonic-gate 		(void) execl("/usr/bin/netstat", "netstat",
1227c478bd9Sstevel@tonic-gate 		    (n_flag ? "-np" : "-p"),
1237c478bd9Sstevel@tonic-gate 		    "-f", "inet", (char *)0);
124*2545d10dSRobert Mustacchi 		(void) fprintf(stderr, "failed to exec netstat: %s\n",
125*2545d10dSRobert Mustacchi 		    strerror(errno));
1267c478bd9Sstevel@tonic-gate 		exit(1);
1277c478bd9Sstevel@tonic-gate 
1287c478bd9Sstevel@tonic-gate 	} else if (s_flag && (argsleft >= 2)) {
1297c478bd9Sstevel@tonic-gate 		if (set(argsleft, &argv[optind]) != 0)
1307c478bd9Sstevel@tonic-gate 			exit(1);
1317c478bd9Sstevel@tonic-gate 
1327c478bd9Sstevel@tonic-gate 	} else if (d_flag && (argsleft == 1)) {
1337c478bd9Sstevel@tonic-gate 		delete(argv[optind]);
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate 	} else if (f_flag && (argsleft == 1)) {
1367c478bd9Sstevel@tonic-gate 		if (file(argv[optind]) != 0)
1377c478bd9Sstevel@tonic-gate 			exit(1);
1387c478bd9Sstevel@tonic-gate 
1397c478bd9Sstevel@tonic-gate 	} else if ((nflags == 0) && (argsleft == 1)) {
1407c478bd9Sstevel@tonic-gate 		get(argv[optind]);
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate 	} else {
1437c478bd9Sstevel@tonic-gate 		usage();
1447c478bd9Sstevel@tonic-gate 		exit(1);
1457c478bd9Sstevel@tonic-gate 	}
1467c478bd9Sstevel@tonic-gate 	return (0);
1477c478bd9Sstevel@tonic-gate }
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate /*
1507c478bd9Sstevel@tonic-gate  * Process a file to set standard arp entries
1517c478bd9Sstevel@tonic-gate  */
15269bb4bb4Scarlsonj static int
15369bb4bb4Scarlsonj file(char *name)
1547c478bd9Sstevel@tonic-gate {
1557c478bd9Sstevel@tonic-gate 	/*
1567c478bd9Sstevel@tonic-gate 	 * A line of input can be:
15769bb4bb4Scarlsonj 	 * <hostname> <macaddr> ["temp"] ["pub"] ["trail"] ["permanent"]
1587c478bd9Sstevel@tonic-gate 	 */
1597c478bd9Sstevel@tonic-gate #define	MAX_LINE_LEN	(MAXHOSTNAMELEN + \
16069bb4bb4Scarlsonj 	sizeof (" xx:xx:xx:xx:xx:xx temp pub trail permanent\n"))
1617c478bd9Sstevel@tonic-gate #define	MIN_ARGS	2
1627c478bd9Sstevel@tonic-gate #define	MAX_ARGS	5
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate 	FILE *fp;
1657c478bd9Sstevel@tonic-gate 	char line[MAX_LINE_LEN];
1667c478bd9Sstevel@tonic-gate 	int retval;
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate 	if ((fp = fopen(name, "r")) == NULL) {
1697c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "arp: cannot open %s\n", name);
1707c478bd9Sstevel@tonic-gate 		exit(1);
1717c478bd9Sstevel@tonic-gate 	}
1727c478bd9Sstevel@tonic-gate 
1737c478bd9Sstevel@tonic-gate 	retval = 0;
1747c478bd9Sstevel@tonic-gate 	while (fgets(line, MAX_LINE_LEN, fp) != NULL) {
1757c478bd9Sstevel@tonic-gate 		char line_copy[MAX_LINE_LEN];
1767c478bd9Sstevel@tonic-gate 		char *args[MAX_ARGS];
1777c478bd9Sstevel@tonic-gate 		char *start;
1787c478bd9Sstevel@tonic-gate 		int i;
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate 		/*
1817c478bd9Sstevel@tonic-gate 		 * Keep a copy of the un-altered line for error
1827c478bd9Sstevel@tonic-gate 		 * reporting.
1837c478bd9Sstevel@tonic-gate 		 */
1847c478bd9Sstevel@tonic-gate 		(void) strlcpy(line_copy, line, MAX_LINE_LEN);
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate 		start = line_copy;
1877c478bd9Sstevel@tonic-gate 		for (i = 0; i < MAX_ARGS; i++) {
1887c478bd9Sstevel@tonic-gate 			if ((args[i] = strtok(start, " \t\n")) == NULL)
1897c478bd9Sstevel@tonic-gate 				break;
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate 			start = NULL;
1927c478bd9Sstevel@tonic-gate 		}
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate 		if (i < MIN_ARGS) {
1957c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "arp: bad line: %s\n",
1967c478bd9Sstevel@tonic-gate 			    line);
1977c478bd9Sstevel@tonic-gate 			retval = 1;
1987c478bd9Sstevel@tonic-gate 			continue;
1997c478bd9Sstevel@tonic-gate 		}
2007c478bd9Sstevel@tonic-gate 
2017c478bd9Sstevel@tonic-gate 		if (set(i, args) != 0)
2027c478bd9Sstevel@tonic-gate 			retval = 1;
2037c478bd9Sstevel@tonic-gate 	}
2047c478bd9Sstevel@tonic-gate 
2057c478bd9Sstevel@tonic-gate #undef	MAX_LINE_LEN
2067c478bd9Sstevel@tonic-gate #undef	MIN_ARGS
2077c478bd9Sstevel@tonic-gate #undef	MAX_ARGS
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate 	(void) fclose(fp);
2107c478bd9Sstevel@tonic-gate 	return (retval);
2117c478bd9Sstevel@tonic-gate }
2127c478bd9Sstevel@tonic-gate 
2137c478bd9Sstevel@tonic-gate /*
2147c478bd9Sstevel@tonic-gate  * Set an individual arp entry
2157c478bd9Sstevel@tonic-gate  */
21669bb4bb4Scarlsonj static int
21769bb4bb4Scarlsonj set(int argc, char *argv[])
2187c478bd9Sstevel@tonic-gate {
2197c478bd9Sstevel@tonic-gate 	struct xarpreq ar;
2207c478bd9Sstevel@tonic-gate 	struct hostent *hp;
2217c478bd9Sstevel@tonic-gate 	struct sockaddr_in *sin;
2227c478bd9Sstevel@tonic-gate 	uchar_t *ea;
2237c478bd9Sstevel@tonic-gate 	int s;
2247c478bd9Sstevel@tonic-gate 	char *host = argv[0], *eaddr = argv[1];
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate 	argc -= 2;
2277c478bd9Sstevel@tonic-gate 	argv += 2;
2287c478bd9Sstevel@tonic-gate 	(void) memset(&ar, 0, sizeof (ar));
2297c478bd9Sstevel@tonic-gate 	sin = (struct sockaddr_in *)&ar.xarp_pa;
2307c478bd9Sstevel@tonic-gate 	sin->sin_family = AF_INET;
2317c478bd9Sstevel@tonic-gate 	sin->sin_addr.s_addr = inet_addr(host);
2327c478bd9Sstevel@tonic-gate 	if (sin->sin_addr.s_addr == (in_addr_t)-1) {
2337c478bd9Sstevel@tonic-gate 		hp = gethostbyname(host);
2347c478bd9Sstevel@tonic-gate 		if (hp == NULL) {
2357c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "arp: %s: unknown host\n",
2367c478bd9Sstevel@tonic-gate 			    host);
2377c478bd9Sstevel@tonic-gate 			return (1);
2387c478bd9Sstevel@tonic-gate 		}
2397c478bd9Sstevel@tonic-gate 		(void) memcpy(&sin->sin_addr, hp->h_addr,
2407c478bd9Sstevel@tonic-gate 		    sizeof (sin->sin_addr));
2417c478bd9Sstevel@tonic-gate 	}
2427c478bd9Sstevel@tonic-gate 	ea = _link_aton(eaddr, &s);
2437c478bd9Sstevel@tonic-gate 	if (ea == NULL) {
2447c478bd9Sstevel@tonic-gate 		if (s == -1) {
2457c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
2467c478bd9Sstevel@tonic-gate 			    "arp: invalid link layer address '%s'\n", eaddr);
2477c478bd9Sstevel@tonic-gate 			return (1);
2487c478bd9Sstevel@tonic-gate 		}
2497c478bd9Sstevel@tonic-gate 		perror("arp: nomem");
2507c478bd9Sstevel@tonic-gate 		exit(1);
2517c478bd9Sstevel@tonic-gate 	}
2527c478bd9Sstevel@tonic-gate 	ar.xarp_ha.sdl_alen = s;
2537c478bd9Sstevel@tonic-gate 	(void) memcpy(LLADDR(&ar.xarp_ha), ea, ar.xarp_ha.sdl_alen);
2547c478bd9Sstevel@tonic-gate 	free(ea);
2557c478bd9Sstevel@tonic-gate 	ar.xarp_ha.sdl_family = AF_LINK;
2567c478bd9Sstevel@tonic-gate 	ar.xarp_flags = ATF_PERM;
2577c478bd9Sstevel@tonic-gate 	while (argc-- > 0) {
25869bb4bb4Scarlsonj 		if (strncmp(argv[0], "temp", 4) == 0) {
2597c478bd9Sstevel@tonic-gate 			ar.xarp_flags &= ~ATF_PERM;
26069bb4bb4Scarlsonj 		} else if (strncmp(argv[0], "pub", 3) == 0) {
2617c478bd9Sstevel@tonic-gate 			ar.xarp_flags |= ATF_PUBL;
26269bb4bb4Scarlsonj 		} else if (strncmp(argv[0], "trail", 5) == 0) {
2637c478bd9Sstevel@tonic-gate 			ar.xarp_flags |= ATF_USETRAILERS;
26469bb4bb4Scarlsonj 		} else if (strcmp(argv[0], "permanent") == 0) {
26569bb4bb4Scarlsonj 			ar.xarp_flags |= ATF_AUTHORITY;
26669bb4bb4Scarlsonj 		} else {
26769bb4bb4Scarlsonj 			(void) fprintf(stderr,
26869bb4bb4Scarlsonj 			    "arp: unknown keyword '%s'\n", argv[0]);
26969bb4bb4Scarlsonj 			return (1);
27069bb4bb4Scarlsonj 		}
2717c478bd9Sstevel@tonic-gate 		argv++;
2727c478bd9Sstevel@tonic-gate 	}
2737c478bd9Sstevel@tonic-gate 
27469bb4bb4Scarlsonj 	if ((ar.xarp_flags & (ATF_PERM|ATF_AUTHORITY)) == ATF_AUTHORITY) {
27569bb4bb4Scarlsonj 		(void) fprintf(stderr, "arp: 'temp' and 'permanent' flags are "
27669bb4bb4Scarlsonj 		    "not usable together.\n");
27769bb4bb4Scarlsonj 		return (1);
27869bb4bb4Scarlsonj 	}
27969bb4bb4Scarlsonj 
2807c478bd9Sstevel@tonic-gate 	s = socket(AF_INET, SOCK_DGRAM, 0);
2817c478bd9Sstevel@tonic-gate 	if (s < 0) {
2827c478bd9Sstevel@tonic-gate 		perror("arp: socket");
2837c478bd9Sstevel@tonic-gate 		exit(1);
2847c478bd9Sstevel@tonic-gate 	}
2857c478bd9Sstevel@tonic-gate 	if (ioctl(s, SIOCSXARP, (caddr_t)&ar) < 0) {
2867c478bd9Sstevel@tonic-gate 		perror(host);
2877c478bd9Sstevel@tonic-gate 		exit(1);
2887c478bd9Sstevel@tonic-gate 	}
2897c478bd9Sstevel@tonic-gate 	(void) close(s);
2907c478bd9Sstevel@tonic-gate 	return (0);
2917c478bd9Sstevel@tonic-gate }
2927c478bd9Sstevel@tonic-gate 
2937c478bd9Sstevel@tonic-gate /*
2947c478bd9Sstevel@tonic-gate  * Display an individual arp entry
2957c478bd9Sstevel@tonic-gate  */
29669bb4bb4Scarlsonj static void
29769bb4bb4Scarlsonj get(char *host)
2987c478bd9Sstevel@tonic-gate {
2997c478bd9Sstevel@tonic-gate 	struct xarpreq ar;
3007c478bd9Sstevel@tonic-gate 	struct hostent *hp;
3017c478bd9Sstevel@tonic-gate 	struct sockaddr_in *sin;
3027c478bd9Sstevel@tonic-gate 	uchar_t *ea;
3037c478bd9Sstevel@tonic-gate 	int s;
3047c478bd9Sstevel@tonic-gate 	char *str = NULL;
3057c478bd9Sstevel@tonic-gate 
3067c478bd9Sstevel@tonic-gate 	(void) memset(&ar, 0, sizeof (ar));
3077c478bd9Sstevel@tonic-gate 	sin = (struct sockaddr_in *)&ar.xarp_pa;
3087c478bd9Sstevel@tonic-gate 	sin->sin_family = AF_INET;
3097c478bd9Sstevel@tonic-gate 	sin->sin_addr.s_addr = inet_addr(host);
3107c478bd9Sstevel@tonic-gate 	if (sin->sin_addr.s_addr == (in_addr_t)-1) {
3117c478bd9Sstevel@tonic-gate 		hp = gethostbyname(host);
3127c478bd9Sstevel@tonic-gate 		if (hp == NULL) {
3137c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "arp: %s: unknown host\n",
3147c478bd9Sstevel@tonic-gate 			    host);
3157c478bd9Sstevel@tonic-gate 			exit(1);
3167c478bd9Sstevel@tonic-gate 		}
3177c478bd9Sstevel@tonic-gate 		(void) memcpy(&sin->sin_addr, hp->h_addr,
3187c478bd9Sstevel@tonic-gate 		    sizeof (sin->sin_addr));
3197c478bd9Sstevel@tonic-gate 	}
3207c478bd9Sstevel@tonic-gate 	s = socket(AF_INET, SOCK_DGRAM, 0);
3217c478bd9Sstevel@tonic-gate 	if (s < 0) {
3227c478bd9Sstevel@tonic-gate 		perror("arp: socket");
3237c478bd9Sstevel@tonic-gate 		exit(1);
3247c478bd9Sstevel@tonic-gate 	}
3257c478bd9Sstevel@tonic-gate 	ar.xarp_ha.sdl_family = AF_LINK;
3267c478bd9Sstevel@tonic-gate 	if (ioctl(s, SIOCGXARP, (caddr_t)&ar) < 0) {
3277c478bd9Sstevel@tonic-gate 		if (errno == ENXIO)
3287c478bd9Sstevel@tonic-gate 			(void) printf("%s (%s) -- no entry\n",
3297c478bd9Sstevel@tonic-gate 			    host, inet_ntoa(sin->sin_addr));
3307c478bd9Sstevel@tonic-gate 		else
3317c478bd9Sstevel@tonic-gate 			perror("SIOCGXARP");
3327c478bd9Sstevel@tonic-gate 		exit(1);
3337c478bd9Sstevel@tonic-gate 	}
3347c478bd9Sstevel@tonic-gate 	(void) close(s);
3357c478bd9Sstevel@tonic-gate 	ea = (uchar_t *)LLADDR(&ar.xarp_ha);
3367c478bd9Sstevel@tonic-gate 	if (ar.xarp_flags & ATF_COM) {
3377c478bd9Sstevel@tonic-gate 		str = _link_ntoa(ea, str, ar.xarp_ha.sdl_alen, IFT_OTHER);
3387c478bd9Sstevel@tonic-gate 		if (str != NULL) {
3397c478bd9Sstevel@tonic-gate 			(void) printf("%s (%s) at %s", host,
3407c478bd9Sstevel@tonic-gate 			    inet_ntoa(sin->sin_addr), str);
3417c478bd9Sstevel@tonic-gate 			free(str);
3427c478bd9Sstevel@tonic-gate 		} else {
3437c478bd9Sstevel@tonic-gate 			perror("arp: nomem");
3447c478bd9Sstevel@tonic-gate 			exit(1);
3457c478bd9Sstevel@tonic-gate 		}
3467c478bd9Sstevel@tonic-gate 	} else {
3477c478bd9Sstevel@tonic-gate 		(void) printf("%s (%s) at (incomplete)", host,
3487c478bd9Sstevel@tonic-gate 		    inet_ntoa(sin->sin_addr));
3497c478bd9Sstevel@tonic-gate 	}
35069bb4bb4Scarlsonj 	if (!(ar.xarp_flags & ATF_PERM))
35169bb4bb4Scarlsonj 		(void) printf(" temp");
3527c478bd9Sstevel@tonic-gate 	if (ar.xarp_flags & ATF_PUBL)
35369bb4bb4Scarlsonj 		(void) printf(" pub");
3547c478bd9Sstevel@tonic-gate 	if (ar.xarp_flags & ATF_USETRAILERS)
35569bb4bb4Scarlsonj 		(void) printf(" trail");
35669bb4bb4Scarlsonj 	if (ar.xarp_flags & ATF_AUTHORITY)
35769bb4bb4Scarlsonj 		(void) printf(" permanent");
3587c478bd9Sstevel@tonic-gate 	(void) printf("\n");
3597c478bd9Sstevel@tonic-gate }
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate /*
3627c478bd9Sstevel@tonic-gate  * Delete an arp entry
3637c478bd9Sstevel@tonic-gate  */
36469bb4bb4Scarlsonj static void
36569bb4bb4Scarlsonj delete(char *host)
3667c478bd9Sstevel@tonic-gate {
3677c478bd9Sstevel@tonic-gate 	struct xarpreq ar;
3687c478bd9Sstevel@tonic-gate 	struct hostent *hp;
3697c478bd9Sstevel@tonic-gate 	struct sockaddr_in *sin;
3707c478bd9Sstevel@tonic-gate 	int s;
3717c478bd9Sstevel@tonic-gate 
3727c478bd9Sstevel@tonic-gate 	(void) memset(&ar, 0, sizeof (ar));
3737c478bd9Sstevel@tonic-gate 	sin = (struct sockaddr_in *)&ar.xarp_pa;
3747c478bd9Sstevel@tonic-gate 	sin->sin_family = AF_INET;
3757c478bd9Sstevel@tonic-gate 	sin->sin_addr.s_addr = inet_addr(host);
3767c478bd9Sstevel@tonic-gate 	if (sin->sin_addr.s_addr == (in_addr_t)-1) {
3777c478bd9Sstevel@tonic-gate 		hp = gethostbyname(host);
3787c478bd9Sstevel@tonic-gate 		if (hp == NULL) {
3797c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "arp: %s: unknown host\n",
3807c478bd9Sstevel@tonic-gate 			    host);
3817c478bd9Sstevel@tonic-gate 			exit(1);
3827c478bd9Sstevel@tonic-gate 		}
3837c478bd9Sstevel@tonic-gate 		(void) memcpy(&sin->sin_addr, hp->h_addr,
3847c478bd9Sstevel@tonic-gate 		    sizeof (sin->sin_addr));
3857c478bd9Sstevel@tonic-gate 	}
3867c478bd9Sstevel@tonic-gate 	s = socket(AF_INET, SOCK_DGRAM, 0);
3877c478bd9Sstevel@tonic-gate 	if (s < 0) {
3887c478bd9Sstevel@tonic-gate 		perror("arp: socket");
3897c478bd9Sstevel@tonic-gate 		exit(1);
3907c478bd9Sstevel@tonic-gate 	}
3917c478bd9Sstevel@tonic-gate 	ar.xarp_ha.sdl_family = AF_LINK;
3927c478bd9Sstevel@tonic-gate 	if (ioctl(s, SIOCDXARP, (caddr_t)&ar) < 0) {
3937c478bd9Sstevel@tonic-gate 		if (errno == ENXIO)
3947c478bd9Sstevel@tonic-gate 			(void) printf("%s (%s) -- no entry\n",
3957c478bd9Sstevel@tonic-gate 			    host, inet_ntoa(sin->sin_addr));
3967c478bd9Sstevel@tonic-gate 		else
3977c478bd9Sstevel@tonic-gate 			perror("SIOCDXARP");
3987c478bd9Sstevel@tonic-gate 		exit(1);
3997c478bd9Sstevel@tonic-gate 	}
4007c478bd9Sstevel@tonic-gate 	(void) close(s);
4017c478bd9Sstevel@tonic-gate 	(void) printf("%s (%s) deleted\n", host, inet_ntoa(sin->sin_addr));
4027c478bd9Sstevel@tonic-gate }
4037c478bd9Sstevel@tonic-gate 
40469bb4bb4Scarlsonj static void
40569bb4bb4Scarlsonj usage(void)
4067c478bd9Sstevel@tonic-gate {
4077c478bd9Sstevel@tonic-gate 	(void) printf("Usage: arp hostname\n");
4087c478bd9Sstevel@tonic-gate 	(void) printf("       arp -a [-n]\n");
4097c478bd9Sstevel@tonic-gate 	(void) printf("       arp -d hostname\n");
4107c478bd9Sstevel@tonic-gate 	(void) printf("       arp -s hostname ether_addr "
41169bb4bb4Scarlsonj 	    "[temp] [pub] [trail] [permanent]\n");
4127c478bd9Sstevel@tonic-gate 	(void) printf("       arp -f filename\n");
4137c478bd9Sstevel@tonic-gate }
414