1dea673e9SRodney W. Grimes /* 2dea673e9SRodney W. Grimes * Copyright (c) 1984, 1993 3dea673e9SRodney W. Grimes * The Regents of the University of California. All rights reserved. 4dea673e9SRodney W. Grimes * 5dea673e9SRodney W. Grimes * This code is derived from software contributed to Berkeley by 6dea673e9SRodney W. Grimes * Sun Microsystems, Inc. 7dea673e9SRodney W. Grimes * 8dea673e9SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 9dea673e9SRodney W. Grimes * modification, are permitted provided that the following conditions 10dea673e9SRodney W. Grimes * are met: 11dea673e9SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 12dea673e9SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 13dea673e9SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 14dea673e9SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 15dea673e9SRodney W. Grimes * documentation and/or other materials provided with the distribution. 16dea673e9SRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 17dea673e9SRodney W. Grimes * must display the following acknowledgement: 18dea673e9SRodney W. Grimes * This product includes software developed by the University of 19dea673e9SRodney W. Grimes * California, Berkeley and its contributors. 20dea673e9SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 21dea673e9SRodney W. Grimes * may be used to endorse or promote products derived from this software 22dea673e9SRodney W. Grimes * without specific prior written permission. 23dea673e9SRodney W. Grimes * 24dea673e9SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25dea673e9SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26dea673e9SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27dea673e9SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28dea673e9SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29dea673e9SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30dea673e9SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31dea673e9SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32dea673e9SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33dea673e9SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34dea673e9SRodney W. Grimes * SUCH DAMAGE. 35dea673e9SRodney W. Grimes */ 36dea673e9SRodney W. Grimes 37dea673e9SRodney W. Grimes #ifndef lint 38a42a667dSPoul-Henning Kamp static char const copyright[] = 39dea673e9SRodney W. Grimes "@(#) Copyright (c) 1984, 1993\n\ 40dea673e9SRodney W. Grimes The Regents of the University of California. All rights reserved.\n"; 41dea673e9SRodney W. Grimes #endif /* not lint */ 42dea673e9SRodney W. Grimes 43dea673e9SRodney W. Grimes #ifndef lint 44c72049e4SPhilippe Charnier #if 0 45a42a667dSPoul-Henning Kamp static char const sccsid[] = "@(#)from: arp.c 8.2 (Berkeley) 1/2/94"; 46c72049e4SPhilippe Charnier #endif 47c72049e4SPhilippe Charnier static const char rcsid[] = 4897d92980SPeter Wemm "$FreeBSD$"; 49dea673e9SRodney W. Grimes #endif /* not lint */ 50dea673e9SRodney W. Grimes 51dea673e9SRodney W. Grimes /* 52dea673e9SRodney W. Grimes * arp - display, set, and delete arp table entries 53dea673e9SRodney W. Grimes */ 54dea673e9SRodney W. Grimes 55dea673e9SRodney W. Grimes 56dea673e9SRodney W. Grimes #include <sys/param.h> 57dea673e9SRodney W. Grimes #include <sys/file.h> 58dea673e9SRodney W. Grimes #include <sys/socket.h> 59a42a667dSPoul-Henning Kamp #include <sys/sockio.h> 60dea673e9SRodney W. Grimes #include <sys/sysctl.h> 61a42a667dSPoul-Henning Kamp #include <sys/ioctl.h> 62628d2ac1SGarrett Wollman #include <sys/time.h> 63dea673e9SRodney W. Grimes 64dea673e9SRodney W. Grimes #include <net/if.h> 65dea673e9SRodney W. Grimes #include <net/if_dl.h> 66dea673e9SRodney W. Grimes #include <net/if_types.h> 67dea673e9SRodney W. Grimes #include <net/route.h> 68dea673e9SRodney W. Grimes 69dea673e9SRodney W. Grimes #include <netinet/in.h> 70dea673e9SRodney W. Grimes #include <netinet/if_ether.h> 71dea673e9SRodney W. Grimes 72dea673e9SRodney W. Grimes #include <arpa/inet.h> 73dea673e9SRodney W. Grimes 74c72049e4SPhilippe Charnier #include <err.h> 75dea673e9SRodney W. Grimes #include <errno.h> 76c72049e4SPhilippe Charnier #include <netdb.h> 77dea673e9SRodney W. Grimes #include <nlist.h> 78c72049e4SPhilippe Charnier #include <paths.h> 79dea673e9SRodney W. Grimes #include <stdio.h> 80a42a667dSPoul-Henning Kamp #include <stdlib.h> 81a42a667dSPoul-Henning Kamp #include <strings.h> 82c72049e4SPhilippe Charnier #include <unistd.h> 83dea673e9SRodney W. Grimes 848dc4b495SJulian Elischer void search(u_long addr, void (*action)(struct sockaddr_dl *sdl, 858dc4b495SJulian Elischer struct sockaddr_inarp *sin, struct rt_msghdr *rtm)); 868dc4b495SJulian Elischer void print_entry(struct sockaddr_dl *sdl, 878dc4b495SJulian Elischer struct sockaddr_inarp *sin, struct rt_msghdr *rtm); 888dc4b495SJulian Elischer void nuke_entry(struct sockaddr_dl *sdl, 898dc4b495SJulian Elischer struct sockaddr_inarp *sin, struct rt_msghdr *rtm); 90a42a667dSPoul-Henning Kamp int delete(char *host, char *info); 91a42a667dSPoul-Henning Kamp void ether_print(u_char *cp); 92a42a667dSPoul-Henning Kamp void usage(void); 93a42a667dSPoul-Henning Kamp int set(int argc, char **argv); 948dc4b495SJulian Elischer int get(char *host); 95a42a667dSPoul-Henning Kamp int file(char *name); 96a42a667dSPoul-Henning Kamp void getsocket(void); 9763c64400SNate Williams int my_ether_aton(char *a, u_char *n); 98a42a667dSPoul-Henning Kamp int rtmsg(int cmd); 991fece1a6SYoshinobu Inoue int get_ether_addr(u_int32_t ipaddr, u_char *hwaddr); 100a42a667dSPoul-Henning Kamp 101dea673e9SRodney W. Grimes static int pid; 1028dc4b495SJulian Elischer static int nflag; /* no reverse dns lookups */ 1038dc4b495SJulian Elischer static int aflag; /* do it for all entries */ 104dea673e9SRodney W. Grimes static int s = -1; 105dea673e9SRodney W. Grimes 1068dc4b495SJulian Elischer /* which function we're supposed to do */ 1078dc4b495SJulian Elischer #define F_GET 1 1088dc4b495SJulian Elischer #define F_SET 2 1098dc4b495SJulian Elischer #define F_FILESET 3 1108dc4b495SJulian Elischer #define F_REPLACE 4 1118dc4b495SJulian Elischer #define F_DELETE 5 1128dc4b495SJulian Elischer 1133a6a5ebeSRuslan Ermilov #define ROUNDUP(a) \ 1143a6a5ebeSRuslan Ermilov ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 1158dc4b495SJulian Elischer #define SETFUNC(f) { if (func) usage(); func = (f); } 1168dc4b495SJulian Elischer 117a42a667dSPoul-Henning Kamp int 1183f844a22SRuslan Ermilov main(int argc, char *argv[]) 119dea673e9SRodney W. Grimes { 1208dc4b495SJulian Elischer int ch, func = 0; 1218dc4b495SJulian Elischer int rtn = 0; 122dea673e9SRodney W. Grimes 123dea673e9SRodney W. Grimes pid = getpid(); 1246c3f552aSWarner Losh while ((ch = getopt(argc, argv, "andfsS")) != -1) 125dea673e9SRodney W. Grimes switch((char)ch) { 126dea673e9SRodney W. Grimes case 'a': 1278dc4b495SJulian Elischer aflag = 1; 1288dc4b495SJulian Elischer break; 129dea673e9SRodney W. Grimes case 'd': 1308dc4b495SJulian Elischer SETFUNC(F_DELETE); 1318dc4b495SJulian Elischer break; 132dea673e9SRodney W. Grimes case 'n': 133dea673e9SRodney W. Grimes nflag = 1; 1348dc4b495SJulian Elischer break; 135a42a667dSPoul-Henning Kamp case 'S': 1368dc4b495SJulian Elischer SETFUNC(F_REPLACE); 1378dc4b495SJulian Elischer break; 138dea673e9SRodney W. Grimes case 's': 1398dc4b495SJulian Elischer SETFUNC(F_SET); 1408dc4b495SJulian Elischer break; 14195319e17SJordan K. Hubbard case 'f' : 1428dc4b495SJulian Elischer SETFUNC(F_FILESET); 1438dc4b495SJulian Elischer break; 144dea673e9SRodney W. Grimes case '?': 145dea673e9SRodney W. Grimes default: 146dea673e9SRodney W. Grimes usage(); 147dea673e9SRodney W. Grimes } 1488dc4b495SJulian Elischer argc -= optind; 1498dc4b495SJulian Elischer argv += optind; 1508dc4b495SJulian Elischer 1518dc4b495SJulian Elischer if (!func) 1528dc4b495SJulian Elischer func = F_GET; 1538dc4b495SJulian Elischer switch (func) { 1548dc4b495SJulian Elischer case F_GET: 1558dc4b495SJulian Elischer if (aflag) { 1568dc4b495SJulian Elischer if (argc != 0) 157dea673e9SRodney W. Grimes usage(); 1588dc4b495SJulian Elischer search(0, print_entry); 1598dc4b495SJulian Elischer } else { 1608dc4b495SJulian Elischer if (argc != 1) 1618dc4b495SJulian Elischer usage(); 1628dc4b495SJulian Elischer get(argv[0]); 1638dc4b495SJulian Elischer } 1648dc4b495SJulian Elischer break; 1658dc4b495SJulian Elischer case F_SET: 1668dc4b495SJulian Elischer case F_REPLACE: 1673f844a22SRuslan Ermilov if (argc < 2 || argc > 6) 1688dc4b495SJulian Elischer usage(); 1698dc4b495SJulian Elischer if (func == F_REPLACE) 1708dc4b495SJulian Elischer (void) delete(argv[0], NULL); 1718dc4b495SJulian Elischer rtn = set(argc, argv) ? 1 : 0; 1728dc4b495SJulian Elischer break; 1738dc4b495SJulian Elischer case F_DELETE: 1748dc4b495SJulian Elischer if (aflag) { 1758dc4b495SJulian Elischer if (argc != 0) 1768dc4b495SJulian Elischer usage(); 1778dc4b495SJulian Elischer search(0, nuke_entry); 1788dc4b495SJulian Elischer } else { 1798dc4b495SJulian Elischer if (argc < 1 || argc > 2) 1808dc4b495SJulian Elischer usage(); 1818dc4b495SJulian Elischer rtn = delete(argv[0], argv[1]); 1828dc4b495SJulian Elischer } 1838dc4b495SJulian Elischer break; 1848dc4b495SJulian Elischer case F_FILESET: 1858dc4b495SJulian Elischer if (argc != 1) 1868dc4b495SJulian Elischer usage(); 1878dc4b495SJulian Elischer rtn = file(argv[0]); 1888dc4b495SJulian Elischer break; 1898dc4b495SJulian Elischer } 1908dc4b495SJulian Elischer 1918dc4b495SJulian Elischer return(rtn); 192dea673e9SRodney W. Grimes } 193dea673e9SRodney W. Grimes 194dea673e9SRodney W. Grimes /* 195dea673e9SRodney W. Grimes * Process a file to set standard arp entries 196dea673e9SRodney W. Grimes */ 197a42a667dSPoul-Henning Kamp int 198a42a667dSPoul-Henning Kamp file(char *name) 199dea673e9SRodney W. Grimes { 200dea673e9SRodney W. Grimes FILE *fp; 201dea673e9SRodney W. Grimes int i, retval; 202dea673e9SRodney W. Grimes char line[100], arg[5][50], *args[5]; 203dea673e9SRodney W. Grimes 204c72049e4SPhilippe Charnier if ((fp = fopen(name, "r")) == NULL) 205c72049e4SPhilippe Charnier errx(1, "cannot open %s", name); 206dea673e9SRodney W. Grimes args[0] = &arg[0][0]; 207dea673e9SRodney W. Grimes args[1] = &arg[1][0]; 208dea673e9SRodney W. Grimes args[2] = &arg[2][0]; 209dea673e9SRodney W. Grimes args[3] = &arg[3][0]; 210dea673e9SRodney W. Grimes args[4] = &arg[4][0]; 211dea673e9SRodney W. Grimes retval = 0; 212dea673e9SRodney W. Grimes while(fgets(line, 100, fp) != NULL) { 2130cecd500SKris Kennaway i = sscanf(line, "%49s %49s %49s %49s %49s", arg[0], arg[1], 214135adb1eSJordan K. Hubbard arg[2], arg[3], arg[4]); 215dea673e9SRodney W. Grimes if (i < 2) { 216c72049e4SPhilippe Charnier warnx("bad line: %s", line); 217dea673e9SRodney W. Grimes retval = 1; 218dea673e9SRodney W. Grimes continue; 219dea673e9SRodney W. Grimes } 220dea673e9SRodney W. Grimes if (set(i, args)) 221dea673e9SRodney W. Grimes retval = 1; 222dea673e9SRodney W. Grimes } 223dea673e9SRodney W. Grimes fclose(fp); 224dea673e9SRodney W. Grimes return (retval); 225dea673e9SRodney W. Grimes } 226dea673e9SRodney W. Grimes 227a42a667dSPoul-Henning Kamp void 228a42a667dSPoul-Henning Kamp getsocket(void) 229a42a667dSPoul-Henning Kamp { 230dea673e9SRodney W. Grimes if (s < 0) { 231dea673e9SRodney W. Grimes s = socket(PF_ROUTE, SOCK_RAW, 0); 232c72049e4SPhilippe Charnier if (s < 0) 233c72049e4SPhilippe Charnier err(1, "socket"); 234dea673e9SRodney W. Grimes } 235dea673e9SRodney W. Grimes } 236dea673e9SRodney W. Grimes 237dea673e9SRodney W. Grimes struct sockaddr_in so_mask = {8, 0, 0, { 0xffffffff}}; 238dea673e9SRodney W. Grimes struct sockaddr_inarp blank_sin = {sizeof(blank_sin), AF_INET }, sin_m; 239dea673e9SRodney W. Grimes struct sockaddr_dl blank_sdl = {sizeof(blank_sdl), AF_LINK }, sdl_m; 2403f844a22SRuslan Ermilov int expire_time, flags, doing_proxy, proxy_only, found_entry; 241dea673e9SRodney W. Grimes struct { 242dea673e9SRodney W. Grimes struct rt_msghdr m_rtm; 243dea673e9SRodney W. Grimes char m_space[512]; 244dea673e9SRodney W. Grimes } m_rtmsg; 245dea673e9SRodney W. Grimes 246dea673e9SRodney W. Grimes /* 247dea673e9SRodney W. Grimes * Set an individual arp entry 248dea673e9SRodney W. Grimes */ 249a42a667dSPoul-Henning Kamp int 250a42a667dSPoul-Henning Kamp set(int argc, char **argv) 251dea673e9SRodney W. Grimes { 252dea673e9SRodney W. Grimes struct hostent *hp; 253dea673e9SRodney W. Grimes register struct sockaddr_inarp *sin = &sin_m; 254dea673e9SRodney W. Grimes register struct sockaddr_dl *sdl; 255dea673e9SRodney W. Grimes register struct rt_msghdr *rtm = &(m_rtmsg.m_rtm); 256dea673e9SRodney W. Grimes u_char *ea; 257dea673e9SRodney W. Grimes char *host = argv[0], *eaddr = argv[1]; 258dea673e9SRodney W. Grimes 259dea673e9SRodney W. Grimes getsocket(); 260dea673e9SRodney W. Grimes argc -= 2; 261dea673e9SRodney W. Grimes argv += 2; 262dea673e9SRodney W. Grimes sdl_m = blank_sdl; 263dea673e9SRodney W. Grimes sin_m = blank_sin; 264dea673e9SRodney W. Grimes sin->sin_addr.s_addr = inet_addr(host); 2653f844a22SRuslan Ermilov if (sin->sin_addr.s_addr == INADDR_NONE) { 266dea673e9SRodney W. Grimes if (!(hp = gethostbyname(host))) { 267c72049e4SPhilippe Charnier warnx("%s: %s", host, hstrerror(h_errno)); 268dea673e9SRodney W. Grimes return (1); 269dea673e9SRodney W. Grimes } 270dea673e9SRodney W. Grimes bcopy((char *)hp->h_addr, (char *)&sin->sin_addr, 271dea673e9SRodney W. Grimes sizeof sin->sin_addr); 272dea673e9SRodney W. Grimes } 2733f844a22SRuslan Ermilov doing_proxy = flags = proxy_only = expire_time = 0; 274dea673e9SRodney W. Grimes while (argc-- > 0) { 275dea673e9SRodney W. Grimes if (strncmp(argv[0], "temp", 4) == 0) { 2763f844a22SRuslan Ermilov struct timeval tv; 2773f844a22SRuslan Ermilov gettimeofday(&tv, 0); 2783f844a22SRuslan Ermilov expire_time = tv.tv_sec + 20 * 60; 279dea673e9SRodney W. Grimes } 280dea673e9SRodney W. Grimes else if (strncmp(argv[0], "pub", 3) == 0) { 281dea673e9SRodney W. Grimes flags |= RTF_ANNOUNCE; 2823f844a22SRuslan Ermilov doing_proxy = 1; 2833f844a22SRuslan Ermilov if (argc && strncmp(argv[1], "only", 3) == 0) { 2843f844a22SRuslan Ermilov proxy_only = 1; 2853f844a22SRuslan Ermilov sin_m.sin_other = SIN_PROXY; 2863f844a22SRuslan Ermilov argc--; argv++; 2873f844a22SRuslan Ermilov } 288dea673e9SRodney W. Grimes } else if (strncmp(argv[0], "trail", 5) == 0) { 289dea673e9SRodney W. Grimes printf("%s: Sending trailers is no longer supported\n", 290dea673e9SRodney W. Grimes host); 291dea673e9SRodney W. Grimes } 292dea673e9SRodney W. Grimes argv++; 293dea673e9SRodney W. Grimes } 294a42a667dSPoul-Henning Kamp ea = (u_char *)LLADDR(&sdl_m); 295a42a667dSPoul-Henning Kamp if (doing_proxy && !strcmp(eaddr, "auto")) { 296a42a667dSPoul-Henning Kamp if (!get_ether_addr(sin->sin_addr.s_addr, ea)) { 297eec827b0SRuslan Ermilov printf("no interface found for %s\n", 298eec827b0SRuslan Ermilov inet_ntoa(sin->sin_addr)); 299a42a667dSPoul-Henning Kamp return (1); 300a42a667dSPoul-Henning Kamp } 301a42a667dSPoul-Henning Kamp sdl_m.sdl_alen = 6; 302a42a667dSPoul-Henning Kamp } else { 30363c64400SNate Williams if (my_ether_aton(eaddr, ea) == 0) 304a42a667dSPoul-Henning Kamp sdl_m.sdl_alen = 6; 305a42a667dSPoul-Henning Kamp } 306dea673e9SRodney W. Grimes tryagain: 307dea673e9SRodney W. Grimes if (rtmsg(RTM_GET) < 0) { 308c72049e4SPhilippe Charnier warn("%s", host); 309dea673e9SRodney W. Grimes return (1); 310dea673e9SRodney W. Grimes } 311dea673e9SRodney W. Grimes sin = (struct sockaddr_inarp *)(rtm + 1); 3123a6a5ebeSRuslan Ermilov sdl = (struct sockaddr_dl *)(ROUNDUP(sin->sin_len) + (char *)sin); 313dea673e9SRodney W. Grimes if (sin->sin_addr.s_addr == sin_m.sin_addr.s_addr) { 314dea673e9SRodney W. Grimes if (sdl->sdl_family == AF_LINK && 315dea673e9SRodney W. Grimes (rtm->rtm_flags & RTF_LLINFO) && 316dea673e9SRodney W. Grimes !(rtm->rtm_flags & RTF_GATEWAY)) switch (sdl->sdl_type) { 317dea673e9SRodney W. Grimes case IFT_ETHER: case IFT_FDDI: case IFT_ISO88023: 31888d5b613SYaroslav Tykhiy case IFT_ISO88024: case IFT_ISO88025: case IFT_L2VLAN: 319dea673e9SRodney W. Grimes goto overwrite; 320dea673e9SRodney W. Grimes } 321dea673e9SRodney W. Grimes if (doing_proxy == 0) { 322dea673e9SRodney W. Grimes printf("set: can only proxy for %s\n", host); 323dea673e9SRodney W. Grimes return (1); 324dea673e9SRodney W. Grimes } 325dea673e9SRodney W. Grimes if (sin_m.sin_other & SIN_PROXY) { 326dea673e9SRodney W. Grimes printf("set: proxy entry exists for non 802 device\n"); 327dea673e9SRodney W. Grimes return(1); 328dea673e9SRodney W. Grimes } 329dea673e9SRodney W. Grimes sin_m.sin_other = SIN_PROXY; 3303f844a22SRuslan Ermilov proxy_only = 1; 331dea673e9SRodney W. Grimes goto tryagain; 332dea673e9SRodney W. Grimes } 333dea673e9SRodney W. Grimes overwrite: 334dea673e9SRodney W. Grimes if (sdl->sdl_family != AF_LINK) { 335dea673e9SRodney W. Grimes printf("cannot intuit interface index and type for %s\n", host); 336dea673e9SRodney W. Grimes return (1); 337dea673e9SRodney W. Grimes } 338dea673e9SRodney W. Grimes sdl_m.sdl_type = sdl->sdl_type; 339dea673e9SRodney W. Grimes sdl_m.sdl_index = sdl->sdl_index; 340dea673e9SRodney W. Grimes return (rtmsg(RTM_ADD)); 341dea673e9SRodney W. Grimes } 342dea673e9SRodney W. Grimes 343dea673e9SRodney W. Grimes /* 344dea673e9SRodney W. Grimes * Display an individual arp entry 345dea673e9SRodney W. Grimes */ 3468dc4b495SJulian Elischer int 347a42a667dSPoul-Henning Kamp get(char *host) 348dea673e9SRodney W. Grimes { 349dea673e9SRodney W. Grimes struct hostent *hp; 350dea673e9SRodney W. Grimes struct sockaddr_inarp *sin = &sin_m; 351dea673e9SRodney W. Grimes 352dea673e9SRodney W. Grimes sin_m = blank_sin; 353dea673e9SRodney W. Grimes sin->sin_addr.s_addr = inet_addr(host); 3543f844a22SRuslan Ermilov if (sin->sin_addr.s_addr == INADDR_NONE) { 355c72049e4SPhilippe Charnier if (!(hp = gethostbyname(host))) 356c72049e4SPhilippe Charnier errx(1, "%s: %s", host, hstrerror(h_errno)); 357dea673e9SRodney W. Grimes bcopy((char *)hp->h_addr, (char *)&sin->sin_addr, 358dea673e9SRodney W. Grimes sizeof sin->sin_addr); 359dea673e9SRodney W. Grimes } 3608dc4b495SJulian Elischer search(sin->sin_addr.s_addr, print_entry); 361dea673e9SRodney W. Grimes if (found_entry == 0) { 362dea673e9SRodney W. Grimes printf("%s (%s) -- no entry\n", 363dea673e9SRodney W. Grimes host, inet_ntoa(sin->sin_addr)); 3648dc4b495SJulian Elischer return(1); 365dea673e9SRodney W. Grimes } 3668dc4b495SJulian Elischer return(0); 367dea673e9SRodney W. Grimes } 368dea673e9SRodney W. Grimes 369dea673e9SRodney W. Grimes /* 370dea673e9SRodney W. Grimes * Delete an arp entry 371dea673e9SRodney W. Grimes */ 372a42a667dSPoul-Henning Kamp int 373a42a667dSPoul-Henning Kamp delete(char *host, char *info) 374dea673e9SRodney W. Grimes { 375dea673e9SRodney W. Grimes struct hostent *hp; 376dea673e9SRodney W. Grimes register struct sockaddr_inarp *sin = &sin_m; 377dea673e9SRodney W. Grimes register struct rt_msghdr *rtm = &m_rtmsg.m_rtm; 378dea673e9SRodney W. Grimes struct sockaddr_dl *sdl; 379dea673e9SRodney W. Grimes 380dea673e9SRodney W. Grimes getsocket(); 381dea673e9SRodney W. Grimes sin_m = blank_sin; 3823f844a22SRuslan Ermilov if (info) { 3833f844a22SRuslan Ermilov if (strncmp(info, "pub", 3) == 0) 3849ea1ba64SRuslan Ermilov sin_m.sin_other = SIN_PROXY; 3853f844a22SRuslan Ermilov else 3863f844a22SRuslan Ermilov usage(); 3873f844a22SRuslan Ermilov } 388dea673e9SRodney W. Grimes sin->sin_addr.s_addr = inet_addr(host); 3893f844a22SRuslan Ermilov if (sin->sin_addr.s_addr == INADDR_NONE) { 390dea673e9SRodney W. Grimes if (!(hp = gethostbyname(host))) { 391c72049e4SPhilippe Charnier warnx("%s: %s", host, hstrerror(h_errno)); 392dea673e9SRodney W. Grimes return (1); 393dea673e9SRodney W. Grimes } 394dea673e9SRodney W. Grimes bcopy((char *)hp->h_addr, (char *)&sin->sin_addr, 395dea673e9SRodney W. Grimes sizeof sin->sin_addr); 396dea673e9SRodney W. Grimes } 397dea673e9SRodney W. Grimes tryagain: 398dea673e9SRodney W. Grimes if (rtmsg(RTM_GET) < 0) { 399c72049e4SPhilippe Charnier warn("%s", host); 400dea673e9SRodney W. Grimes return (1); 401dea673e9SRodney W. Grimes } 402dea673e9SRodney W. Grimes sin = (struct sockaddr_inarp *)(rtm + 1); 4033a6a5ebeSRuslan Ermilov sdl = (struct sockaddr_dl *)(ROUNDUP(sin->sin_len) + (char *)sin); 404dea673e9SRodney W. Grimes if (sin->sin_addr.s_addr == sin_m.sin_addr.s_addr) { 405dea673e9SRodney W. Grimes if (sdl->sdl_family == AF_LINK && 406dea673e9SRodney W. Grimes (rtm->rtm_flags & RTF_LLINFO) && 407dea673e9SRodney W. Grimes !(rtm->rtm_flags & RTF_GATEWAY)) switch (sdl->sdl_type) { 408dea673e9SRodney W. Grimes case IFT_ETHER: case IFT_FDDI: case IFT_ISO88023: 40988d5b613SYaroslav Tykhiy case IFT_ISO88024: case IFT_ISO88025: case IFT_L2VLAN: 410dea673e9SRodney W. Grimes goto delete; 411dea673e9SRodney W. Grimes } 412dea673e9SRodney W. Grimes } 413dea673e9SRodney W. Grimes if (sin_m.sin_other & SIN_PROXY) { 414dea673e9SRodney W. Grimes fprintf(stderr, "delete: can't locate %s\n",host); 415dea673e9SRodney W. Grimes return (1); 416dea673e9SRodney W. Grimes } else { 417dea673e9SRodney W. Grimes sin_m.sin_other = SIN_PROXY; 418dea673e9SRodney W. Grimes goto tryagain; 419dea673e9SRodney W. Grimes } 420dea673e9SRodney W. Grimes delete: 421dea673e9SRodney W. Grimes if (sdl->sdl_family != AF_LINK) { 422dea673e9SRodney W. Grimes printf("cannot locate %s\n", host); 423dea673e9SRodney W. Grimes return (1); 424dea673e9SRodney W. Grimes } 425a42a667dSPoul-Henning Kamp if (rtmsg(RTM_DELETE) == 0) { 426dea673e9SRodney W. Grimes printf("%s (%s) deleted\n", host, inet_ntoa(sin->sin_addr)); 427a42a667dSPoul-Henning Kamp return (0); 428a42a667dSPoul-Henning Kamp } 429a42a667dSPoul-Henning Kamp return (1); 430dea673e9SRodney W. Grimes } 431dea673e9SRodney W. Grimes 432dea673e9SRodney W. Grimes /* 4338dc4b495SJulian Elischer * Search the arp table and do some action on matching entries 434dea673e9SRodney W. Grimes */ 435a42a667dSPoul-Henning Kamp void 4368dc4b495SJulian Elischer search(u_long addr, void (*action)(struct sockaddr_dl *sdl, 4378dc4b495SJulian Elischer struct sockaddr_inarp *sin, struct rt_msghdr *rtm)) 438dea673e9SRodney W. Grimes { 439dea673e9SRodney W. Grimes int mib[6]; 440dea673e9SRodney W. Grimes size_t needed; 4418dc4b495SJulian Elischer char *lim, *buf, *next; 442dea673e9SRodney W. Grimes struct rt_msghdr *rtm; 443dea673e9SRodney W. Grimes struct sockaddr_inarp *sin; 444dea673e9SRodney W. Grimes struct sockaddr_dl *sdl; 445dea673e9SRodney W. Grimes 446dea673e9SRodney W. Grimes mib[0] = CTL_NET; 447dea673e9SRodney W. Grimes mib[1] = PF_ROUTE; 448dea673e9SRodney W. Grimes mib[2] = 0; 449dea673e9SRodney W. Grimes mib[3] = AF_INET; 450dea673e9SRodney W. Grimes mib[4] = NET_RT_FLAGS; 451dea673e9SRodney W. Grimes mib[5] = RTF_LLINFO; 452dea673e9SRodney W. Grimes if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) 453c72049e4SPhilippe Charnier errx(1, "route-sysctl-estimate"); 454dea673e9SRodney W. Grimes if ((buf = malloc(needed)) == NULL) 455c72049e4SPhilippe Charnier errx(1, "malloc"); 456dea673e9SRodney W. Grimes if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) 457c72049e4SPhilippe Charnier errx(1, "actual retrieval of routing table"); 458dea673e9SRodney W. Grimes lim = buf + needed; 459dea673e9SRodney W. Grimes for (next = buf; next < lim; next += rtm->rtm_msglen) { 460dea673e9SRodney W. Grimes rtm = (struct rt_msghdr *)next; 461dea673e9SRodney W. Grimes sin = (struct sockaddr_inarp *)(rtm + 1); 46208e13cdfSRuslan Ermilov (char *)sdl = (char *)sin + ROUNDUP(sin->sin_len); 463dea673e9SRodney W. Grimes if (addr) { 464dea673e9SRodney W. Grimes if (addr != sin->sin_addr.s_addr) 465dea673e9SRodney W. Grimes continue; 466dea673e9SRodney W. Grimes found_entry = 1; 467dea673e9SRodney W. Grimes } 4688dc4b495SJulian Elischer (*action)(sdl, sin, rtm); 4698dc4b495SJulian Elischer } 470ae14be20SYaroslav Tykhiy free(buf); 4718dc4b495SJulian Elischer } 4728dc4b495SJulian Elischer 4738dc4b495SJulian Elischer /* 4748dc4b495SJulian Elischer * Display an arp entry 4758dc4b495SJulian Elischer */ 4768dc4b495SJulian Elischer void 4778dc4b495SJulian Elischer print_entry(struct sockaddr_dl *sdl, 4788dc4b495SJulian Elischer struct sockaddr_inarp *sin, struct rt_msghdr *rtm) 4798dc4b495SJulian Elischer { 4803f844a22SRuslan Ermilov const char *host; 4818dc4b495SJulian Elischer struct hostent *hp; 482e87a372bSRuslan Ermilov char ifname[IF_NAMESIZE]; 483fda82fc2SJulian Elischer int seg; 4848dc4b495SJulian Elischer 485dea673e9SRodney W. Grimes if (nflag == 0) 486dea673e9SRodney W. Grimes hp = gethostbyaddr((caddr_t)&(sin->sin_addr), 487dea673e9SRodney W. Grimes sizeof sin->sin_addr, AF_INET); 488dea673e9SRodney W. Grimes else 489dea673e9SRodney W. Grimes hp = 0; 490dea673e9SRodney W. Grimes if (hp) 491dea673e9SRodney W. Grimes host = hp->h_name; 492dea673e9SRodney W. Grimes else { 493dea673e9SRodney W. Grimes host = "?"; 494dea673e9SRodney W. Grimes if (h_errno == TRY_AGAIN) 495dea673e9SRodney W. Grimes nflag = 1; 496dea673e9SRodney W. Grimes } 497dea673e9SRodney W. Grimes printf("%s (%s) at ", host, inet_ntoa(sin->sin_addr)); 498dea673e9SRodney W. Grimes if (sdl->sdl_alen) 499dea673e9SRodney W. Grimes ether_print(LLADDR(sdl)); 500dea673e9SRodney W. Grimes else 501dea673e9SRodney W. Grimes printf("(incomplete)"); 502e87a372bSRuslan Ermilov if (if_indextoname(sdl->sdl_index, ifname) != NULL) 503e87a372bSRuslan Ermilov printf(" on %s", ifname); 504dea673e9SRodney W. Grimes if (rtm->rtm_rmx.rmx_expire == 0) 505dea673e9SRodney W. Grimes printf(" permanent"); 506dea673e9SRodney W. Grimes if (sin->sin_other & SIN_PROXY) 507dea673e9SRodney W. Grimes printf(" published (proxy only)"); 508dea673e9SRodney W. Grimes if (rtm->rtm_addrs & RTA_NETMASK) { 509dea673e9SRodney W. Grimes sin = (struct sockaddr_inarp *) 5103a6a5ebeSRuslan Ermilov (ROUNDUP(sdl->sdl_len) + (char *)sdl); 511dea673e9SRodney W. Grimes if (sin->sin_addr.s_addr == 0xffffffff) 512dea673e9SRodney W. Grimes printf(" published"); 513dea673e9SRodney W. Grimes if (sin->sin_len != 8) 5143a6a5ebeSRuslan Ermilov printf("(weird)"); 515dea673e9SRodney W. Grimes } 516fda82fc2SJulian Elischer switch(sdl->sdl_type) { 517fda82fc2SJulian Elischer case IFT_ETHER: 518fda82fc2SJulian Elischer printf(" [ethernet]"); 519fda82fc2SJulian Elischer break; 520fda82fc2SJulian Elischer case IFT_ISO88025: 521fda82fc2SJulian Elischer printf(" [token-ring]"); 522fda82fc2SJulian Elischer break; 52304427472SMatthew N. Dodd case IFT_FDDI: 52404427472SMatthew N. Dodd printf(" [fddi]"); 52504427472SMatthew N. Dodd break; 52604427472SMatthew N. Dodd case IFT_ATM: 52704427472SMatthew N. Dodd printf(" [atm]"); 52804427472SMatthew N. Dodd break; 52988d5b613SYaroslav Tykhiy case IFT_L2VLAN: 53088d5b613SYaroslav Tykhiy printf(" [vlan]"); 53188d5b613SYaroslav Tykhiy break; 532fda82fc2SJulian Elischer default: 533fda82fc2SJulian Elischer } 534fda82fc2SJulian Elischer if (sdl->sdl_rcf != NULL) { 535fda82fc2SJulian Elischer printf(" rt=%x", ntohs(sdl->sdl_rcf)); 536fda82fc2SJulian Elischer for (seg = 0; seg < ((((ntohs(sdl->sdl_rcf) & 0x1f00) >> 8) - 2 ) / 2); seg++) 537fda82fc2SJulian Elischer printf(":%x", ntohs(sdl->sdl_route[seg])); 538fda82fc2SJulian Elischer } 539fda82fc2SJulian Elischer 540dea673e9SRodney W. Grimes printf("\n"); 541fda82fc2SJulian Elischer 542dea673e9SRodney W. Grimes } 5438dc4b495SJulian Elischer 5448dc4b495SJulian Elischer /* 5458dc4b495SJulian Elischer * Nuke an arp entry 5468dc4b495SJulian Elischer */ 5478dc4b495SJulian Elischer void 5488dc4b495SJulian Elischer nuke_entry(struct sockaddr_dl *sdl, 5498dc4b495SJulian Elischer struct sockaddr_inarp *sin, struct rt_msghdr *rtm) 5508dc4b495SJulian Elischer { 5518dc4b495SJulian Elischer char ip[20]; 5528dc4b495SJulian Elischer 5538dc4b495SJulian Elischer snprintf(ip, sizeof(ip), "%s", inet_ntoa(sin->sin_addr)); 5548dc4b495SJulian Elischer delete(ip, NULL); 555dea673e9SRodney W. Grimes } 556dea673e9SRodney W. Grimes 557a42a667dSPoul-Henning Kamp void 558a42a667dSPoul-Henning Kamp ether_print(u_char *cp) 559dea673e9SRodney W. Grimes { 5605651a036SBill Fumerola printf("%02x:%02x:%02x:%02x:%02x:%02x", cp[0], cp[1], cp[2], cp[3], 5615651a036SBill Fumerola cp[4], cp[5]); 562dea673e9SRodney W. Grimes } 563dea673e9SRodney W. Grimes 564a42a667dSPoul-Henning Kamp int 56563c64400SNate Williams my_ether_aton(char *a, u_char *n) 566dea673e9SRodney W. Grimes { 567dea673e9SRodney W. Grimes int i, o[6]; 568dea673e9SRodney W. Grimes 569dea673e9SRodney W. Grimes i = sscanf(a, "%x:%x:%x:%x:%x:%x", &o[0], &o[1], &o[2], 570dea673e9SRodney W. Grimes &o[3], &o[4], &o[5]); 571dea673e9SRodney W. Grimes if (i != 6) { 572c72049e4SPhilippe Charnier warnx("invalid Ethernet address '%s'", a); 573dea673e9SRodney W. Grimes return (1); 574dea673e9SRodney W. Grimes } 575dea673e9SRodney W. Grimes for (i=0; i<6; i++) 576dea673e9SRodney W. Grimes n[i] = o[i]; 577dea673e9SRodney W. Grimes return (0); 578dea673e9SRodney W. Grimes } 579dea673e9SRodney W. Grimes 580a42a667dSPoul-Henning Kamp void 581a42a667dSPoul-Henning Kamp usage(void) 582dea673e9SRodney W. Grimes { 5838dc4b495SJulian Elischer fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n", 584c72049e4SPhilippe Charnier "usage: arp [-n] hostname", 5858dc4b495SJulian Elischer " arp [-n] -a", 5863f844a22SRuslan Ermilov " arp -d hostname [pub]", 5878dc4b495SJulian Elischer " arp -d -a", 588c72049e4SPhilippe Charnier " arp -s hostname ether_addr [temp] [pub]", 589c72049e4SPhilippe Charnier " arp -S hostname ether_addr [temp] [pub]", 590c72049e4SPhilippe Charnier " arp -f filename"); 591dea673e9SRodney W. Grimes exit(1); 592dea673e9SRodney W. Grimes } 593dea673e9SRodney W. Grimes 594a42a667dSPoul-Henning Kamp int 595a42a667dSPoul-Henning Kamp rtmsg(int cmd) 596dea673e9SRodney W. Grimes { 597dea673e9SRodney W. Grimes static int seq; 598dea673e9SRodney W. Grimes int rlen; 599dea673e9SRodney W. Grimes register struct rt_msghdr *rtm = &m_rtmsg.m_rtm; 600dea673e9SRodney W. Grimes register char *cp = m_rtmsg.m_space; 601dea673e9SRodney W. Grimes register int l; 602dea673e9SRodney W. Grimes 603dea673e9SRodney W. Grimes errno = 0; 604dea673e9SRodney W. Grimes if (cmd == RTM_DELETE) 605dea673e9SRodney W. Grimes goto doit; 606dea673e9SRodney W. Grimes bzero((char *)&m_rtmsg, sizeof(m_rtmsg)); 607dea673e9SRodney W. Grimes rtm->rtm_flags = flags; 608dea673e9SRodney W. Grimes rtm->rtm_version = RTM_VERSION; 609dea673e9SRodney W. Grimes 610dea673e9SRodney W. Grimes switch (cmd) { 611dea673e9SRodney W. Grimes default: 612c72049e4SPhilippe Charnier errx(1, "internal wrong cmd"); 613dea673e9SRodney W. Grimes case RTM_ADD: 614dea673e9SRodney W. Grimes rtm->rtm_addrs |= RTA_GATEWAY; 615dea673e9SRodney W. Grimes rtm->rtm_rmx.rmx_expire = expire_time; 616dea673e9SRodney W. Grimes rtm->rtm_inits = RTV_EXPIRE; 617dea673e9SRodney W. Grimes rtm->rtm_flags |= (RTF_HOST | RTF_STATIC); 618dea673e9SRodney W. Grimes sin_m.sin_other = 0; 619dea673e9SRodney W. Grimes if (doing_proxy) { 6203f844a22SRuslan Ermilov if (proxy_only) 621dea673e9SRodney W. Grimes sin_m.sin_other = SIN_PROXY; 622dea673e9SRodney W. Grimes else { 623dea673e9SRodney W. Grimes rtm->rtm_addrs |= RTA_NETMASK; 624dea673e9SRodney W. Grimes rtm->rtm_flags &= ~RTF_HOST; 625dea673e9SRodney W. Grimes } 626dea673e9SRodney W. Grimes } 627dea673e9SRodney W. Grimes /* FALLTHROUGH */ 628dea673e9SRodney W. Grimes case RTM_GET: 629dea673e9SRodney W. Grimes rtm->rtm_addrs |= RTA_DST; 630dea673e9SRodney W. Grimes } 631dea673e9SRodney W. Grimes #define NEXTADDR(w, s) \ 632dea673e9SRodney W. Grimes if (rtm->rtm_addrs & (w)) { \ 6333a6a5ebeSRuslan Ermilov bcopy((char *)&s, cp, sizeof(s)); cp += ROUNDUP(sizeof(s));} 634dea673e9SRodney W. Grimes 635dea673e9SRodney W. Grimes NEXTADDR(RTA_DST, sin_m); 636dea673e9SRodney W. Grimes NEXTADDR(RTA_GATEWAY, sdl_m); 637dea673e9SRodney W. Grimes NEXTADDR(RTA_NETMASK, so_mask); 638dea673e9SRodney W. Grimes 639dea673e9SRodney W. Grimes rtm->rtm_msglen = cp - (char *)&m_rtmsg; 640dea673e9SRodney W. Grimes doit: 641dea673e9SRodney W. Grimes l = rtm->rtm_msglen; 642dea673e9SRodney W. Grimes rtm->rtm_seq = ++seq; 643dea673e9SRodney W. Grimes rtm->rtm_type = cmd; 644dea673e9SRodney W. Grimes if ((rlen = write(s, (char *)&m_rtmsg, l)) < 0) { 645dea673e9SRodney W. Grimes if (errno != ESRCH || cmd != RTM_DELETE) { 646c72049e4SPhilippe Charnier warn("writing to routing socket"); 647dea673e9SRodney W. Grimes return (-1); 648dea673e9SRodney W. Grimes } 649dea673e9SRodney W. Grimes } 650dea673e9SRodney W. Grimes do { 651dea673e9SRodney W. Grimes l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg)); 652dea673e9SRodney W. Grimes } while (l > 0 && (rtm->rtm_seq != seq || rtm->rtm_pid != pid)); 653dea673e9SRodney W. Grimes if (l < 0) 654c72049e4SPhilippe Charnier warn("read from routing socket"); 655dea673e9SRodney W. Grimes return (0); 656dea673e9SRodney W. Grimes } 657dea673e9SRodney W. Grimes 658a42a667dSPoul-Henning Kamp /* 659a42a667dSPoul-Henning Kamp * get_ether_addr - get the hardware address of an interface on the 660a42a667dSPoul-Henning Kamp * the same subnet as ipaddr. 661a42a667dSPoul-Henning Kamp */ 662a42a667dSPoul-Henning Kamp #define MAX_IFS 32 663a42a667dSPoul-Henning Kamp 664a42a667dSPoul-Henning Kamp int 6651fece1a6SYoshinobu Inoue get_ether_addr(u_int32_t ipaddr, u_char *hwaddr) 666a42a667dSPoul-Henning Kamp { 667a42a667dSPoul-Henning Kamp struct ifreq *ifr, *ifend, *ifp; 6681fece1a6SYoshinobu Inoue u_int32_t ina, mask; 669a42a667dSPoul-Henning Kamp struct sockaddr_dl *dla; 670a42a667dSPoul-Henning Kamp struct ifreq ifreq; 671a42a667dSPoul-Henning Kamp struct ifconf ifc; 672a42a667dSPoul-Henning Kamp struct ifreq ifs[MAX_IFS]; 673a42a667dSPoul-Henning Kamp int s; 674a42a667dSPoul-Henning Kamp 675a42a667dSPoul-Henning Kamp s = socket(AF_INET, SOCK_DGRAM, 0); 676c72049e4SPhilippe Charnier if (s < 0) 677c72049e4SPhilippe Charnier err(1, "socket"); 678a42a667dSPoul-Henning Kamp 679a42a667dSPoul-Henning Kamp ifc.ifc_len = sizeof(ifs); 680a42a667dSPoul-Henning Kamp ifc.ifc_req = ifs; 681a42a667dSPoul-Henning Kamp if (ioctl(s, SIOCGIFCONF, &ifc) < 0) { 682c72049e4SPhilippe Charnier warnx("ioctl(SIOCGIFCONF)"); 683a42a667dSPoul-Henning Kamp close(s); 684a42a667dSPoul-Henning Kamp return 0; 685a42a667dSPoul-Henning Kamp } 686a42a667dSPoul-Henning Kamp 687a42a667dSPoul-Henning Kamp /* 688a42a667dSPoul-Henning Kamp * Scan through looking for an interface with an Internet 689a42a667dSPoul-Henning Kamp * address on the same subnet as `ipaddr'. 690a42a667dSPoul-Henning Kamp */ 691a42a667dSPoul-Henning Kamp ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len); 692a42a667dSPoul-Henning Kamp for (ifr = ifc.ifc_req; ifr < ifend; ) { 693a42a667dSPoul-Henning Kamp if (ifr->ifr_addr.sa_family == AF_INET) { 694a42a667dSPoul-Henning Kamp ina = ((struct sockaddr_in *) 695a42a667dSPoul-Henning Kamp &ifr->ifr_addr)->sin_addr.s_addr; 696a42a667dSPoul-Henning Kamp strncpy(ifreq.ifr_name, ifr->ifr_name, 697a42a667dSPoul-Henning Kamp sizeof(ifreq.ifr_name)); 698a42a667dSPoul-Henning Kamp /* 699a42a667dSPoul-Henning Kamp * Check that the interface is up, 700a42a667dSPoul-Henning Kamp * and not point-to-point or loopback. 701a42a667dSPoul-Henning Kamp */ 702a42a667dSPoul-Henning Kamp if (ioctl(s, SIOCGIFFLAGS, &ifreq) < 0) 703a42a667dSPoul-Henning Kamp continue; 704a42a667dSPoul-Henning Kamp if ((ifreq.ifr_flags & 705a42a667dSPoul-Henning Kamp (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT| 706a42a667dSPoul-Henning Kamp IFF_LOOPBACK|IFF_NOARP)) 707a42a667dSPoul-Henning Kamp != (IFF_UP|IFF_BROADCAST)) 708a42a667dSPoul-Henning Kamp goto nextif; 709a42a667dSPoul-Henning Kamp /* 710a42a667dSPoul-Henning Kamp * Get its netmask and check that it's on 711a42a667dSPoul-Henning Kamp * the right subnet. 712a42a667dSPoul-Henning Kamp */ 713a42a667dSPoul-Henning Kamp if (ioctl(s, SIOCGIFNETMASK, &ifreq) < 0) 714a42a667dSPoul-Henning Kamp continue; 715a42a667dSPoul-Henning Kamp mask = ((struct sockaddr_in *) 716a42a667dSPoul-Henning Kamp &ifreq.ifr_addr)->sin_addr.s_addr; 717a42a667dSPoul-Henning Kamp if ((ipaddr & mask) != (ina & mask)) 718a42a667dSPoul-Henning Kamp goto nextif; 719a42a667dSPoul-Henning Kamp break; 720a42a667dSPoul-Henning Kamp } 721a42a667dSPoul-Henning Kamp nextif: 7223816c56cSArchie Cobbs ifr = (struct ifreq *) ((char *)&ifr->ifr_addr 7233816c56cSArchie Cobbs + MAX(ifr->ifr_addr.sa_len, sizeof(ifr->ifr_addr))); 724a42a667dSPoul-Henning Kamp } 725a42a667dSPoul-Henning Kamp 726a42a667dSPoul-Henning Kamp if (ifr >= ifend) { 727a42a667dSPoul-Henning Kamp close(s); 728a42a667dSPoul-Henning Kamp return 0; 729a42a667dSPoul-Henning Kamp } 730a42a667dSPoul-Henning Kamp 731a42a667dSPoul-Henning Kamp /* 732a42a667dSPoul-Henning Kamp * Now scan through again looking for a link-level address 733a42a667dSPoul-Henning Kamp * for this interface. 734a42a667dSPoul-Henning Kamp */ 735a42a667dSPoul-Henning Kamp ifp = ifr; 736a42a667dSPoul-Henning Kamp for (ifr = ifc.ifc_req; ifr < ifend; ) { 737a42a667dSPoul-Henning Kamp if (strcmp(ifp->ifr_name, ifr->ifr_name) == 0 738a42a667dSPoul-Henning Kamp && ifr->ifr_addr.sa_family == AF_LINK) { 739a42a667dSPoul-Henning Kamp /* 740a42a667dSPoul-Henning Kamp * Found the link-level address - copy it out 741a42a667dSPoul-Henning Kamp */ 742a42a667dSPoul-Henning Kamp dla = (struct sockaddr_dl *) &ifr->ifr_addr; 743a42a667dSPoul-Henning Kamp memcpy(hwaddr, LLADDR(dla), dla->sdl_alen); 744a42a667dSPoul-Henning Kamp close (s); 745a42a667dSPoul-Henning Kamp printf("using interface %s for proxy with address ", 746a42a667dSPoul-Henning Kamp ifp->ifr_name); 747a42a667dSPoul-Henning Kamp ether_print(hwaddr); 748a42a667dSPoul-Henning Kamp printf("\n"); 749a42a667dSPoul-Henning Kamp return dla->sdl_alen; 750a42a667dSPoul-Henning Kamp } 7513816c56cSArchie Cobbs ifr = (struct ifreq *) ((char *)&ifr->ifr_addr 7523816c56cSArchie Cobbs + MAX(ifr->ifr_addr.sa_len, sizeof(ifr->ifr_addr))); 753a42a667dSPoul-Henning Kamp } 754a42a667dSPoul-Henning Kamp return 0; 755a42a667dSPoul-Henning Kamp } 756