xref: /illumos-gate/usr/src/cmd/cmd-inet/usr.sbin/arp.c (revision 19f828df)
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
main(int argc,char * argv[])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);	\
81*19f828dfSToomas Soome 			} else {		\
827c478bd9Sstevel@tonic-gate 				y##_flag = 1;	\
83*19f828dfSToomas Soome 			}			\
84*19f828dfSToomas Soome 			nflags++;		\
857c478bd9Sstevel@tonic-gate 			break
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "nadfs")) != EOF) {
887c478bd9Sstevel@tonic-gate 		switch (c) {
897c478bd9Sstevel@tonic-gate 		case '?':
907c478bd9Sstevel@tonic-gate 			usage();
917c478bd9Sstevel@tonic-gate 			exit(1);
927c478bd9Sstevel@tonic-gate 			/* NOTREACHED */
937c478bd9Sstevel@tonic-gate 			break;
947c478bd9Sstevel@tonic-gate 		case 'n':
957c478bd9Sstevel@tonic-gate 			n_flag = 1;
967c478bd9Sstevel@tonic-gate 			break;
977c478bd9Sstevel@tonic-gate 		CASE('a', a);
987c478bd9Sstevel@tonic-gate 		CASE('d', d);
997c478bd9Sstevel@tonic-gate 		CASE('f', f);
1007c478bd9Sstevel@tonic-gate 		CASE('s', s);
1017c478bd9Sstevel@tonic-gate 		}
1027c478bd9Sstevel@tonic-gate 	}
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate #undef CASE
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate 	/*
1077c478bd9Sstevel@tonic-gate 	 * -n only allowed with -a
1087c478bd9Sstevel@tonic-gate 	 */
1097c478bd9Sstevel@tonic-gate 	if (n_flag && !a_flag) {
1107c478bd9Sstevel@tonic-gate 		usage();
1117c478bd9Sstevel@tonic-gate 		exit(1);
1127c478bd9Sstevel@tonic-gate 	}
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate 	argsleft = argc - optind;
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate 	if (a_flag && (argsleft == 0)) {
1177c478bd9Sstevel@tonic-gate 		/*
1187c478bd9Sstevel@tonic-gate 		 * the easiest way to get the complete arp table
1197c478bd9Sstevel@tonic-gate 		 * is to let netstat, which prints it as part of
1207c478bd9Sstevel@tonic-gate 		 * the MIB statistics, do it.
1217c478bd9Sstevel@tonic-gate 		 */
1227c478bd9Sstevel@tonic-gate 		(void) execl("/usr/bin/netstat", "netstat",
1237c478bd9Sstevel@tonic-gate 		    (n_flag ? "-np" : "-p"),
1247c478bd9Sstevel@tonic-gate 		    "-f", "inet", (char *)0);
1252545d10dSRobert Mustacchi 		(void) fprintf(stderr, "failed to exec netstat: %s\n",
1262545d10dSRobert Mustacchi 		    strerror(errno));
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  */
15369bb4bb4Scarlsonj static int
file(char * name)15469bb4bb4Scarlsonj file(char *name)
1557c478bd9Sstevel@tonic-gate {
1567c478bd9Sstevel@tonic-gate 	/*
1577c478bd9Sstevel@tonic-gate 	 * A line of input can be:
15869bb4bb4Scarlsonj 	 * <hostname> <macaddr> ["temp"] ["pub"] ["trail"] ["permanent"]
1597c478bd9Sstevel@tonic-gate 	 */
1607c478bd9Sstevel@tonic-gate #define	MAX_LINE_LEN	(MAXHOSTNAMELEN + \
16169bb4bb4Scarlsonj 	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  */
21769bb4bb4Scarlsonj static int
set(int argc,char * argv[])21869bb4bb4Scarlsonj 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) {
25969bb4bb4Scarlsonj 		if (strncmp(argv[0], "temp", 4) == 0) {
2607c478bd9Sstevel@tonic-gate 			ar.xarp_flags &= ~ATF_PERM;
26169bb4bb4Scarlsonj 		} else if (strncmp(argv[0], "pub", 3) == 0) {
2627c478bd9Sstevel@tonic-gate 			ar.xarp_flags |= ATF_PUBL;
26369bb4bb4Scarlsonj 		} else if (strncmp(argv[0], "trail", 5) == 0) {
2647c478bd9Sstevel@tonic-gate 			ar.xarp_flags |= ATF_USETRAILERS;
26569bb4bb4Scarlsonj 		} else if (strcmp(argv[0], "permanent") == 0) {
26669bb4bb4Scarlsonj 			ar.xarp_flags |= ATF_AUTHORITY;
26769bb4bb4Scarlsonj 		} else {
26869bb4bb4Scarlsonj 			(void) fprintf(stderr,
26969bb4bb4Scarlsonj 			    "arp: unknown keyword '%s'\n", argv[0]);
27069bb4bb4Scarlsonj 			return (1);
27169bb4bb4Scarlsonj 		}
2727c478bd9Sstevel@tonic-gate 		argv++;
2737c478bd9Sstevel@tonic-gate 	}
2747c478bd9Sstevel@tonic-gate 
27569bb4bb4Scarlsonj 	if ((ar.xarp_flags & (ATF_PERM|ATF_AUTHORITY)) == ATF_AUTHORITY) {
27669bb4bb4Scarlsonj 		(void) fprintf(stderr, "arp: 'temp' and 'permanent' flags are "
27769bb4bb4Scarlsonj 		    "not usable together.\n");
27869bb4bb4Scarlsonj 		return (1);
27969bb4bb4Scarlsonj 	}
28069bb4bb4Scarlsonj 
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  */
29769bb4bb4Scarlsonj static void
get(char * host)29869bb4bb4Scarlsonj 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 	}
35169bb4bb4Scarlsonj 	if (!(ar.xarp_flags & ATF_PERM))
35269bb4bb4Scarlsonj 		(void) printf(" temp");
3537c478bd9Sstevel@tonic-gate 	if (ar.xarp_flags & ATF_PUBL)
35469bb4bb4Scarlsonj 		(void) printf(" pub");
3557c478bd9Sstevel@tonic-gate 	if (ar.xarp_flags & ATF_USETRAILERS)
35669bb4bb4Scarlsonj 		(void) printf(" trail");
35769bb4bb4Scarlsonj 	if (ar.xarp_flags & ATF_AUTHORITY)
35869bb4bb4Scarlsonj 		(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  */
36569bb4bb4Scarlsonj static void
delete(char * host)36669bb4bb4Scarlsonj 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 
40569bb4bb4Scarlsonj static void
usage(void)40669bb4bb4Scarlsonj 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 "
41269bb4bb4Scarlsonj 	    "[temp] [pub] [trail] [permanent]\n");
4137c478bd9Sstevel@tonic-gate 	(void) printf("       arp -f filename\n");
4147c478bd9Sstevel@tonic-gate }
415