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