1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 3*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 4*7c478bd9Sstevel@tonic-gate */ 5*7c478bd9Sstevel@tonic-gate /* 6*7c478bd9Sstevel@tonic-gate * Copyright (c) 1984 Regents of the University of California. 7*7c478bd9Sstevel@tonic-gate * All rights reserved. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * This code is derived from software contributed to Berkeley by 10*7c478bd9Sstevel@tonic-gate * Sun Microsystems, Inc. 11*7c478bd9Sstevel@tonic-gate * 12*7c478bd9Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 13*7c478bd9Sstevel@tonic-gate * modification, are permitted provided that the following conditions 14*7c478bd9Sstevel@tonic-gate * are met: 15*7c478bd9Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright 16*7c478bd9Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 17*7c478bd9Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 18*7c478bd9Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the 19*7c478bd9Sstevel@tonic-gate * documentation and/or other materials provided with the distribution. 20*7c478bd9Sstevel@tonic-gate * 3. All advertising materials mentioning features or use of this software 21*7c478bd9Sstevel@tonic-gate * must display the following acknowledgement: 22*7c478bd9Sstevel@tonic-gate * This product includes software developed by the University of 23*7c478bd9Sstevel@tonic-gate * California, Berkeley and its contributors. 24*7c478bd9Sstevel@tonic-gate * 4. Neither the name of the University nor the names of its contributors 25*7c478bd9Sstevel@tonic-gate * may be used to endorse or promote products derived from this software 26*7c478bd9Sstevel@tonic-gate * without specific prior written permission. 27*7c478bd9Sstevel@tonic-gate * 28*7c478bd9Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29*7c478bd9Sstevel@tonic-gate * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30*7c478bd9Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31*7c478bd9Sstevel@tonic-gate * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32*7c478bd9Sstevel@tonic-gate * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33*7c478bd9Sstevel@tonic-gate * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34*7c478bd9Sstevel@tonic-gate * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35*7c478bd9Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36*7c478bd9Sstevel@tonic-gate * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37*7c478bd9Sstevel@tonic-gate * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38*7c478bd9Sstevel@tonic-gate * SUCH DAMAGE. 39*7c478bd9Sstevel@tonic-gate */ 40*7c478bd9Sstevel@tonic-gate 41*7c478bd9Sstevel@tonic-gate 42*7c478bd9Sstevel@tonic-gate 43*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 44*7c478bd9Sstevel@tonic-gate 45*7c478bd9Sstevel@tonic-gate /* 46*7c478bd9Sstevel@tonic-gate * arp - display, set, and delete arp table entries 47*7c478bd9Sstevel@tonic-gate */ 48*7c478bd9Sstevel@tonic-gate 49*7c478bd9Sstevel@tonic-gate #include <stdio.h> 50*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 51*7c478bd9Sstevel@tonic-gate #include <sys/socket.h> 52*7c478bd9Sstevel@tonic-gate #include <netinet/in.h> 53*7c478bd9Sstevel@tonic-gate #include <sys/ioctl.h> 54*7c478bd9Sstevel@tonic-gate #include <errno.h> 55*7c478bd9Sstevel@tonic-gate #include <netdb.h> 56*7c478bd9Sstevel@tonic-gate #include <net/if.h> 57*7c478bd9Sstevel@tonic-gate #include <net/if_arp.h> 58*7c478bd9Sstevel@tonic-gate #include <netinet/if_ether.h> 59*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 60*7c478bd9Sstevel@tonic-gate #include <unistd.h> 61*7c478bd9Sstevel@tonic-gate #include <string.h> 62*7c478bd9Sstevel@tonic-gate #include <arpa/inet.h> 63*7c478bd9Sstevel@tonic-gate #include <net/if_types.h> 64*7c478bd9Sstevel@tonic-gate #include <net/if_dl.h> 65*7c478bd9Sstevel@tonic-gate 66*7c478bd9Sstevel@tonic-gate static int file(char *); 67*7c478bd9Sstevel@tonic-gate static int set(int, char *[]); 68*7c478bd9Sstevel@tonic-gate static void get(char *); 69*7c478bd9Sstevel@tonic-gate static void delete(char *); 70*7c478bd9Sstevel@tonic-gate static void usage(void); 71*7c478bd9Sstevel@tonic-gate 72*7c478bd9Sstevel@tonic-gate int 73*7c478bd9Sstevel@tonic-gate main(int argc, char *argv[]) 74*7c478bd9Sstevel@tonic-gate { 75*7c478bd9Sstevel@tonic-gate int c, nflags = 0, argsleft; 76*7c478bd9Sstevel@tonic-gate int n_flag, a_flag, d_flag, f_flag, s_flag; 77*7c478bd9Sstevel@tonic-gate 78*7c478bd9Sstevel@tonic-gate n_flag = a_flag = d_flag = f_flag = s_flag = 0; 79*7c478bd9Sstevel@tonic-gate 80*7c478bd9Sstevel@tonic-gate #define CASE(x, y) \ 81*7c478bd9Sstevel@tonic-gate case x: \ 82*7c478bd9Sstevel@tonic-gate if (nflags > 0) { \ 83*7c478bd9Sstevel@tonic-gate usage(); \ 84*7c478bd9Sstevel@tonic-gate exit(1); \ 85*7c478bd9Sstevel@tonic-gate } else \ 86*7c478bd9Sstevel@tonic-gate y##_flag = 1; \ 87*7c478bd9Sstevel@tonic-gate nflags++; \ 88*7c478bd9Sstevel@tonic-gate break 89*7c478bd9Sstevel@tonic-gate 90*7c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, "nadfs")) != EOF) { 91*7c478bd9Sstevel@tonic-gate switch (c) { 92*7c478bd9Sstevel@tonic-gate case '?': 93*7c478bd9Sstevel@tonic-gate usage(); 94*7c478bd9Sstevel@tonic-gate exit(1); 95*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 96*7c478bd9Sstevel@tonic-gate break; 97*7c478bd9Sstevel@tonic-gate case 'n': 98*7c478bd9Sstevel@tonic-gate n_flag = 1; 99*7c478bd9Sstevel@tonic-gate break; 100*7c478bd9Sstevel@tonic-gate CASE('a', a); 101*7c478bd9Sstevel@tonic-gate CASE('d', d); 102*7c478bd9Sstevel@tonic-gate CASE('f', f); 103*7c478bd9Sstevel@tonic-gate CASE('s', s); 104*7c478bd9Sstevel@tonic-gate } 105*7c478bd9Sstevel@tonic-gate } 106*7c478bd9Sstevel@tonic-gate 107*7c478bd9Sstevel@tonic-gate #undef CASE 108*7c478bd9Sstevel@tonic-gate 109*7c478bd9Sstevel@tonic-gate /* 110*7c478bd9Sstevel@tonic-gate * -n only allowed with -a 111*7c478bd9Sstevel@tonic-gate */ 112*7c478bd9Sstevel@tonic-gate if (n_flag && !a_flag) { 113*7c478bd9Sstevel@tonic-gate usage(); 114*7c478bd9Sstevel@tonic-gate exit(1); 115*7c478bd9Sstevel@tonic-gate } 116*7c478bd9Sstevel@tonic-gate 117*7c478bd9Sstevel@tonic-gate argsleft = argc - optind; 118*7c478bd9Sstevel@tonic-gate 119*7c478bd9Sstevel@tonic-gate if (a_flag && (argsleft == 0)) { 120*7c478bd9Sstevel@tonic-gate /* 121*7c478bd9Sstevel@tonic-gate * the easiest way to get the complete arp table 122*7c478bd9Sstevel@tonic-gate * is to let netstat, which prints it as part of 123*7c478bd9Sstevel@tonic-gate * the MIB statistics, do it. 124*7c478bd9Sstevel@tonic-gate */ 125*7c478bd9Sstevel@tonic-gate (void) execl("/usr/bin/netstat", "netstat", 126*7c478bd9Sstevel@tonic-gate (n_flag ? "-np" : "-p"), 127*7c478bd9Sstevel@tonic-gate "-f", "inet", (char *)0); 128*7c478bd9Sstevel@tonic-gate exit(1); 129*7c478bd9Sstevel@tonic-gate 130*7c478bd9Sstevel@tonic-gate } else if (s_flag && (argsleft >= 2)) { 131*7c478bd9Sstevel@tonic-gate if (set(argsleft, &argv[optind]) != 0) 132*7c478bd9Sstevel@tonic-gate exit(1); 133*7c478bd9Sstevel@tonic-gate 134*7c478bd9Sstevel@tonic-gate } else if (d_flag && (argsleft == 1)) { 135*7c478bd9Sstevel@tonic-gate delete(argv[optind]); 136*7c478bd9Sstevel@tonic-gate 137*7c478bd9Sstevel@tonic-gate } else if (f_flag && (argsleft == 1)) { 138*7c478bd9Sstevel@tonic-gate if (file(argv[optind]) != 0) 139*7c478bd9Sstevel@tonic-gate exit(1); 140*7c478bd9Sstevel@tonic-gate 141*7c478bd9Sstevel@tonic-gate } else if ((nflags == 0) && (argsleft == 1)) { 142*7c478bd9Sstevel@tonic-gate get(argv[optind]); 143*7c478bd9Sstevel@tonic-gate 144*7c478bd9Sstevel@tonic-gate } else { 145*7c478bd9Sstevel@tonic-gate usage(); 146*7c478bd9Sstevel@tonic-gate exit(1); 147*7c478bd9Sstevel@tonic-gate } 148*7c478bd9Sstevel@tonic-gate return (0); 149*7c478bd9Sstevel@tonic-gate } 150*7c478bd9Sstevel@tonic-gate 151*7c478bd9Sstevel@tonic-gate /* 152*7c478bd9Sstevel@tonic-gate * Process a file to set standard arp entries 153*7c478bd9Sstevel@tonic-gate */ 154*7c478bd9Sstevel@tonic-gate static int file(char *name) 155*7c478bd9Sstevel@tonic-gate { 156*7c478bd9Sstevel@tonic-gate /* 157*7c478bd9Sstevel@tonic-gate * A line of input can be: 158*7c478bd9Sstevel@tonic-gate * <hostname> <macaddr> ["temp"] ["pub"] ["trail"] 159*7c478bd9Sstevel@tonic-gate */ 160*7c478bd9Sstevel@tonic-gate #define MAX_LINE_LEN (MAXHOSTNAMELEN + \ 161*7c478bd9Sstevel@tonic-gate sizeof (" xx:xx:xx:xx:xx:xx temp pub trail\n")) 162*7c478bd9Sstevel@tonic-gate #define MIN_ARGS 2 163*7c478bd9Sstevel@tonic-gate #define MAX_ARGS 5 164*7c478bd9Sstevel@tonic-gate 165*7c478bd9Sstevel@tonic-gate FILE *fp; 166*7c478bd9Sstevel@tonic-gate char line[MAX_LINE_LEN]; 167*7c478bd9Sstevel@tonic-gate int retval; 168*7c478bd9Sstevel@tonic-gate 169*7c478bd9Sstevel@tonic-gate if ((fp = fopen(name, "r")) == NULL) { 170*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "arp: cannot open %s\n", name); 171*7c478bd9Sstevel@tonic-gate exit(1); 172*7c478bd9Sstevel@tonic-gate } 173*7c478bd9Sstevel@tonic-gate 174*7c478bd9Sstevel@tonic-gate retval = 0; 175*7c478bd9Sstevel@tonic-gate while (fgets(line, MAX_LINE_LEN, fp) != NULL) { 176*7c478bd9Sstevel@tonic-gate char line_copy[MAX_LINE_LEN]; 177*7c478bd9Sstevel@tonic-gate char *args[MAX_ARGS]; 178*7c478bd9Sstevel@tonic-gate char *start; 179*7c478bd9Sstevel@tonic-gate int i; 180*7c478bd9Sstevel@tonic-gate 181*7c478bd9Sstevel@tonic-gate /* 182*7c478bd9Sstevel@tonic-gate * Keep a copy of the un-altered line for error 183*7c478bd9Sstevel@tonic-gate * reporting. 184*7c478bd9Sstevel@tonic-gate */ 185*7c478bd9Sstevel@tonic-gate (void) strlcpy(line_copy, line, MAX_LINE_LEN); 186*7c478bd9Sstevel@tonic-gate 187*7c478bd9Sstevel@tonic-gate start = line_copy; 188*7c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_ARGS; i++) { 189*7c478bd9Sstevel@tonic-gate if ((args[i] = strtok(start, " \t\n")) == NULL) 190*7c478bd9Sstevel@tonic-gate break; 191*7c478bd9Sstevel@tonic-gate 192*7c478bd9Sstevel@tonic-gate start = NULL; 193*7c478bd9Sstevel@tonic-gate } 194*7c478bd9Sstevel@tonic-gate 195*7c478bd9Sstevel@tonic-gate if (i < MIN_ARGS) { 196*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "arp: bad line: %s\n", 197*7c478bd9Sstevel@tonic-gate line); 198*7c478bd9Sstevel@tonic-gate retval = 1; 199*7c478bd9Sstevel@tonic-gate continue; 200*7c478bd9Sstevel@tonic-gate } 201*7c478bd9Sstevel@tonic-gate 202*7c478bd9Sstevel@tonic-gate if (set(i, args) != 0) 203*7c478bd9Sstevel@tonic-gate retval = 1; 204*7c478bd9Sstevel@tonic-gate } 205*7c478bd9Sstevel@tonic-gate 206*7c478bd9Sstevel@tonic-gate #undef MAX_LINE_LEN 207*7c478bd9Sstevel@tonic-gate #undef MIN_ARGS 208*7c478bd9Sstevel@tonic-gate #undef MAX_ARGS 209*7c478bd9Sstevel@tonic-gate 210*7c478bd9Sstevel@tonic-gate (void) fclose(fp); 211*7c478bd9Sstevel@tonic-gate return (retval); 212*7c478bd9Sstevel@tonic-gate } 213*7c478bd9Sstevel@tonic-gate 214*7c478bd9Sstevel@tonic-gate /* 215*7c478bd9Sstevel@tonic-gate * Set an individual arp entry 216*7c478bd9Sstevel@tonic-gate */ 217*7c478bd9Sstevel@tonic-gate static int set(int argc, char *argv[]) 218*7c478bd9Sstevel@tonic-gate { 219*7c478bd9Sstevel@tonic-gate struct xarpreq ar; 220*7c478bd9Sstevel@tonic-gate struct hostent *hp; 221*7c478bd9Sstevel@tonic-gate struct sockaddr_in *sin; 222*7c478bd9Sstevel@tonic-gate uchar_t *ea; 223*7c478bd9Sstevel@tonic-gate int s; 224*7c478bd9Sstevel@tonic-gate char *host = argv[0], *eaddr = argv[1]; 225*7c478bd9Sstevel@tonic-gate 226*7c478bd9Sstevel@tonic-gate argc -= 2; 227*7c478bd9Sstevel@tonic-gate argv += 2; 228*7c478bd9Sstevel@tonic-gate (void) memset(&ar, 0, sizeof (ar)); 229*7c478bd9Sstevel@tonic-gate sin = (struct sockaddr_in *)&ar.xarp_pa; 230*7c478bd9Sstevel@tonic-gate sin->sin_family = AF_INET; 231*7c478bd9Sstevel@tonic-gate sin->sin_addr.s_addr = inet_addr(host); 232*7c478bd9Sstevel@tonic-gate if (sin->sin_addr.s_addr == (in_addr_t)-1) { 233*7c478bd9Sstevel@tonic-gate hp = gethostbyname(host); 234*7c478bd9Sstevel@tonic-gate if (hp == NULL) { 235*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "arp: %s: unknown host\n", 236*7c478bd9Sstevel@tonic-gate host); 237*7c478bd9Sstevel@tonic-gate return (1); 238*7c478bd9Sstevel@tonic-gate } 239*7c478bd9Sstevel@tonic-gate (void) memcpy(&sin->sin_addr, hp->h_addr, 240*7c478bd9Sstevel@tonic-gate sizeof (sin->sin_addr)); 241*7c478bd9Sstevel@tonic-gate } 242*7c478bd9Sstevel@tonic-gate ea = _link_aton(eaddr, &s); 243*7c478bd9Sstevel@tonic-gate if (ea == NULL) { 244*7c478bd9Sstevel@tonic-gate if (s == -1) { 245*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 246*7c478bd9Sstevel@tonic-gate "arp: invalid link layer address '%s'\n", eaddr); 247*7c478bd9Sstevel@tonic-gate return (1); 248*7c478bd9Sstevel@tonic-gate } 249*7c478bd9Sstevel@tonic-gate perror("arp: nomem"); 250*7c478bd9Sstevel@tonic-gate exit(1); 251*7c478bd9Sstevel@tonic-gate } 252*7c478bd9Sstevel@tonic-gate ar.xarp_ha.sdl_alen = s; 253*7c478bd9Sstevel@tonic-gate (void) memcpy(LLADDR(&ar.xarp_ha), ea, ar.xarp_ha.sdl_alen); 254*7c478bd9Sstevel@tonic-gate free(ea); 255*7c478bd9Sstevel@tonic-gate ar.xarp_ha.sdl_family = AF_LINK; 256*7c478bd9Sstevel@tonic-gate ar.xarp_flags = ATF_PERM; 257*7c478bd9Sstevel@tonic-gate while (argc-- > 0) { 258*7c478bd9Sstevel@tonic-gate if (strncmp(argv[0], "temp", 4) == 0) 259*7c478bd9Sstevel@tonic-gate ar.xarp_flags &= ~ATF_PERM; 260*7c478bd9Sstevel@tonic-gate if (strncmp(argv[0], "pub", 3) == 0) 261*7c478bd9Sstevel@tonic-gate ar.xarp_flags |= ATF_PUBL; 262*7c478bd9Sstevel@tonic-gate if (strncmp(argv[0], "trail", 5) == 0) 263*7c478bd9Sstevel@tonic-gate ar.xarp_flags |= ATF_USETRAILERS; 264*7c478bd9Sstevel@tonic-gate argv++; 265*7c478bd9Sstevel@tonic-gate } 266*7c478bd9Sstevel@tonic-gate 267*7c478bd9Sstevel@tonic-gate s = socket(AF_INET, SOCK_DGRAM, 0); 268*7c478bd9Sstevel@tonic-gate if (s < 0) { 269*7c478bd9Sstevel@tonic-gate perror("arp: socket"); 270*7c478bd9Sstevel@tonic-gate exit(1); 271*7c478bd9Sstevel@tonic-gate } 272*7c478bd9Sstevel@tonic-gate if (ioctl(s, SIOCSXARP, (caddr_t)&ar) < 0) { 273*7c478bd9Sstevel@tonic-gate perror(host); 274*7c478bd9Sstevel@tonic-gate exit(1); 275*7c478bd9Sstevel@tonic-gate } 276*7c478bd9Sstevel@tonic-gate (void) close(s); 277*7c478bd9Sstevel@tonic-gate return (0); 278*7c478bd9Sstevel@tonic-gate } 279*7c478bd9Sstevel@tonic-gate 280*7c478bd9Sstevel@tonic-gate 281*7c478bd9Sstevel@tonic-gate /* 282*7c478bd9Sstevel@tonic-gate * Display an individual arp entry 283*7c478bd9Sstevel@tonic-gate */ 284*7c478bd9Sstevel@tonic-gate static void get(char *host) 285*7c478bd9Sstevel@tonic-gate { 286*7c478bd9Sstevel@tonic-gate struct xarpreq ar; 287*7c478bd9Sstevel@tonic-gate struct hostent *hp; 288*7c478bd9Sstevel@tonic-gate struct sockaddr_in *sin; 289*7c478bd9Sstevel@tonic-gate uchar_t *ea; 290*7c478bd9Sstevel@tonic-gate int s; 291*7c478bd9Sstevel@tonic-gate char *str = NULL; 292*7c478bd9Sstevel@tonic-gate 293*7c478bd9Sstevel@tonic-gate (void) memset(&ar, 0, sizeof (ar)); 294*7c478bd9Sstevel@tonic-gate sin = (struct sockaddr_in *)&ar.xarp_pa; 295*7c478bd9Sstevel@tonic-gate sin->sin_family = AF_INET; 296*7c478bd9Sstevel@tonic-gate sin->sin_addr.s_addr = inet_addr(host); 297*7c478bd9Sstevel@tonic-gate if (sin->sin_addr.s_addr == (in_addr_t)-1) { 298*7c478bd9Sstevel@tonic-gate hp = gethostbyname(host); 299*7c478bd9Sstevel@tonic-gate if (hp == NULL) { 300*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "arp: %s: unknown host\n", 301*7c478bd9Sstevel@tonic-gate host); 302*7c478bd9Sstevel@tonic-gate exit(1); 303*7c478bd9Sstevel@tonic-gate } 304*7c478bd9Sstevel@tonic-gate (void) memcpy(&sin->sin_addr, hp->h_addr, 305*7c478bd9Sstevel@tonic-gate sizeof (sin->sin_addr)); 306*7c478bd9Sstevel@tonic-gate } 307*7c478bd9Sstevel@tonic-gate s = socket(AF_INET, SOCK_DGRAM, 0); 308*7c478bd9Sstevel@tonic-gate if (s < 0) { 309*7c478bd9Sstevel@tonic-gate perror("arp: socket"); 310*7c478bd9Sstevel@tonic-gate exit(1); 311*7c478bd9Sstevel@tonic-gate } 312*7c478bd9Sstevel@tonic-gate ar.xarp_ha.sdl_family = AF_LINK; 313*7c478bd9Sstevel@tonic-gate if (ioctl(s, SIOCGXARP, (caddr_t)&ar) < 0) { 314*7c478bd9Sstevel@tonic-gate if (errno == ENXIO) 315*7c478bd9Sstevel@tonic-gate (void) printf("%s (%s) -- no entry\n", 316*7c478bd9Sstevel@tonic-gate host, inet_ntoa(sin->sin_addr)); 317*7c478bd9Sstevel@tonic-gate else 318*7c478bd9Sstevel@tonic-gate perror("SIOCGXARP"); 319*7c478bd9Sstevel@tonic-gate exit(1); 320*7c478bd9Sstevel@tonic-gate } 321*7c478bd9Sstevel@tonic-gate (void) close(s); 322*7c478bd9Sstevel@tonic-gate ea = (uchar_t *)LLADDR(&ar.xarp_ha); 323*7c478bd9Sstevel@tonic-gate if (ar.xarp_flags & ATF_COM) { 324*7c478bd9Sstevel@tonic-gate str = _link_ntoa(ea, str, ar.xarp_ha.sdl_alen, IFT_OTHER); 325*7c478bd9Sstevel@tonic-gate if (str != NULL) { 326*7c478bd9Sstevel@tonic-gate (void) printf("%s (%s) at %s", host, 327*7c478bd9Sstevel@tonic-gate inet_ntoa(sin->sin_addr), str); 328*7c478bd9Sstevel@tonic-gate free(str); 329*7c478bd9Sstevel@tonic-gate } else { 330*7c478bd9Sstevel@tonic-gate perror("arp: nomem"); 331*7c478bd9Sstevel@tonic-gate exit(1); 332*7c478bd9Sstevel@tonic-gate } 333*7c478bd9Sstevel@tonic-gate } else { 334*7c478bd9Sstevel@tonic-gate (void) printf("%s (%s) at (incomplete)", host, 335*7c478bd9Sstevel@tonic-gate inet_ntoa(sin->sin_addr)); 336*7c478bd9Sstevel@tonic-gate } 337*7c478bd9Sstevel@tonic-gate if (ar.xarp_flags & ATF_PERM) 338*7c478bd9Sstevel@tonic-gate (void) printf(" permanent"); 339*7c478bd9Sstevel@tonic-gate if (ar.xarp_flags & ATF_PUBL) 340*7c478bd9Sstevel@tonic-gate (void) printf(" published"); 341*7c478bd9Sstevel@tonic-gate if (ar.xarp_flags & ATF_USETRAILERS) 342*7c478bd9Sstevel@tonic-gate (void) printf(" trailers"); 343*7c478bd9Sstevel@tonic-gate (void) printf("\n"); 344*7c478bd9Sstevel@tonic-gate } 345*7c478bd9Sstevel@tonic-gate 346*7c478bd9Sstevel@tonic-gate /* 347*7c478bd9Sstevel@tonic-gate * Delete an arp entry 348*7c478bd9Sstevel@tonic-gate */ 349*7c478bd9Sstevel@tonic-gate static void delete(char *host) 350*7c478bd9Sstevel@tonic-gate { 351*7c478bd9Sstevel@tonic-gate struct xarpreq ar; 352*7c478bd9Sstevel@tonic-gate struct hostent *hp; 353*7c478bd9Sstevel@tonic-gate struct sockaddr_in *sin; 354*7c478bd9Sstevel@tonic-gate int s; 355*7c478bd9Sstevel@tonic-gate 356*7c478bd9Sstevel@tonic-gate (void) memset(&ar, 0, sizeof (ar)); 357*7c478bd9Sstevel@tonic-gate sin = (struct sockaddr_in *)&ar.xarp_pa; 358*7c478bd9Sstevel@tonic-gate sin->sin_family = AF_INET; 359*7c478bd9Sstevel@tonic-gate sin->sin_addr.s_addr = inet_addr(host); 360*7c478bd9Sstevel@tonic-gate if (sin->sin_addr.s_addr == (in_addr_t)-1) { 361*7c478bd9Sstevel@tonic-gate hp = gethostbyname(host); 362*7c478bd9Sstevel@tonic-gate if (hp == NULL) { 363*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "arp: %s: unknown host\n", 364*7c478bd9Sstevel@tonic-gate host); 365*7c478bd9Sstevel@tonic-gate exit(1); 366*7c478bd9Sstevel@tonic-gate } 367*7c478bd9Sstevel@tonic-gate (void) memcpy(&sin->sin_addr, hp->h_addr, 368*7c478bd9Sstevel@tonic-gate sizeof (sin->sin_addr)); 369*7c478bd9Sstevel@tonic-gate } 370*7c478bd9Sstevel@tonic-gate s = socket(AF_INET, SOCK_DGRAM, 0); 371*7c478bd9Sstevel@tonic-gate if (s < 0) { 372*7c478bd9Sstevel@tonic-gate perror("arp: socket"); 373*7c478bd9Sstevel@tonic-gate exit(1); 374*7c478bd9Sstevel@tonic-gate } 375*7c478bd9Sstevel@tonic-gate ar.xarp_ha.sdl_family = AF_LINK; 376*7c478bd9Sstevel@tonic-gate if (ioctl(s, SIOCDXARP, (caddr_t)&ar) < 0) { 377*7c478bd9Sstevel@tonic-gate if (errno == ENXIO) 378*7c478bd9Sstevel@tonic-gate (void) printf("%s (%s) -- no entry\n", 379*7c478bd9Sstevel@tonic-gate host, inet_ntoa(sin->sin_addr)); 380*7c478bd9Sstevel@tonic-gate else 381*7c478bd9Sstevel@tonic-gate perror("SIOCDXARP"); 382*7c478bd9Sstevel@tonic-gate exit(1); 383*7c478bd9Sstevel@tonic-gate } 384*7c478bd9Sstevel@tonic-gate (void) close(s); 385*7c478bd9Sstevel@tonic-gate (void) printf("%s (%s) deleted\n", host, inet_ntoa(sin->sin_addr)); 386*7c478bd9Sstevel@tonic-gate } 387*7c478bd9Sstevel@tonic-gate 388*7c478bd9Sstevel@tonic-gate static void usage(void) 389*7c478bd9Sstevel@tonic-gate { 390*7c478bd9Sstevel@tonic-gate (void) printf("Usage: arp hostname\n"); 391*7c478bd9Sstevel@tonic-gate (void) printf(" arp -a [-n]\n"); 392*7c478bd9Sstevel@tonic-gate (void) printf(" arp -d hostname\n"); 393*7c478bd9Sstevel@tonic-gate (void) printf(" arp -s hostname ether_addr " 394*7c478bd9Sstevel@tonic-gate "[temp] [pub] [trail]\n"); 395*7c478bd9Sstevel@tonic-gate (void) printf(" arp -f filename\n"); 396*7c478bd9Sstevel@tonic-gate } 397