1*38e37321Smikel /* $NetBSD: arp.c,v 1.16 1997/03/07 07:04:43 mikel Exp $ */ 27f624aaaSchopps 361f28255Scgd /* 417c454feSmycroft * Copyright (c) 1984, 1993 517c454feSmycroft * The Regents of the University of California. All rights reserved. 661f28255Scgd * 761f28255Scgd * This code is derived from software contributed to Berkeley by 861f28255Scgd * Sun Microsystems, Inc. 961f28255Scgd * 1061f28255Scgd * Redistribution and use in source and binary forms, with or without 1161f28255Scgd * modification, are permitted provided that the following conditions 1261f28255Scgd * are met: 1361f28255Scgd * 1. Redistributions of source code must retain the above copyright 1461f28255Scgd * notice, this list of conditions and the following disclaimer. 1561f28255Scgd * 2. Redistributions in binary form must reproduce the above copyright 1661f28255Scgd * notice, this list of conditions and the following disclaimer in the 1761f28255Scgd * documentation and/or other materials provided with the distribution. 1861f28255Scgd * 3. All advertising materials mentioning features or use of this software 1961f28255Scgd * must display the following acknowledgement: 2061f28255Scgd * This product includes software developed by the University of 2161f28255Scgd * California, Berkeley and its contributors. 2261f28255Scgd * 4. Neither the name of the University nor the names of its contributors 2361f28255Scgd * may be used to endorse or promote products derived from this software 2461f28255Scgd * without specific prior written permission. 2561f28255Scgd * 2661f28255Scgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2761f28255Scgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2861f28255Scgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2961f28255Scgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 3061f28255Scgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3161f28255Scgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3261f28255Scgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3361f28255Scgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3461f28255Scgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3561f28255Scgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3661f28255Scgd * SUCH DAMAGE. 3761f28255Scgd */ 3861f28255Scgd 3961f28255Scgd #ifndef lint 4017c454feSmycroft static char copyright[] = 4117c454feSmycroft "@(#) Copyright (c) 1984, 1993\n\ 4217c454feSmycroft The Regents of the University of California. All rights reserved.\n"; 4361f28255Scgd #endif /* not lint */ 4461f28255Scgd 4561f28255Scgd #ifndef lint 46*38e37321Smikel /* static char sccsid[] = "@(#)arp.c 8.3 (Berkeley) 4/28/95"; */ 47*38e37321Smikel static char *rcsid = "$NetBSD: arp.c,v 1.16 1997/03/07 07:04:43 mikel Exp $"; 4861f28255Scgd #endif /* not lint */ 4961f28255Scgd 5061f28255Scgd /* 5161f28255Scgd * arp - display, set, and delete arp table entries 5261f28255Scgd */ 5361f28255Scgd 5461f28255Scgd #include <sys/param.h> 5561f28255Scgd #include <sys/file.h> 5661f28255Scgd #include <sys/socket.h> 5717c454feSmycroft #include <sys/sysctl.h> 5861f28255Scgd 5961f28255Scgd #include <net/if.h> 6017c454feSmycroft #include <net/if_dl.h> 6117c454feSmycroft #include <net/if_types.h> 6217c454feSmycroft #include <net/route.h> 6317c454feSmycroft #include <netinet/in.h> 6461f28255Scgd #include <netinet/if_ether.h> 65804c4234Smycroft #include <arpa/inet.h> 6661f28255Scgd 67c4516a41Schopps #include <err.h> 68f3b151f5Smikel #include <errno.h> 69f3b151f5Smikel #include <netdb.h> 7061f28255Scgd #include <nlist.h> 71f3b151f5Smikel #include <paths.h> 7261f28255Scgd #include <stdio.h> 73c4516a41Schopps #include <stdlib.h> 74867b4b0fScgd #include <string.h> 75f3b151f5Smikel #include <unistd.h> 7661f28255Scgd 77*38e37321Smikel static int pid; 78*38e37321Smikel static int nflag; 79*38e37321Smikel static int s = -1; 80*38e37321Smikel 81c4516a41Schopps int delete __P((const char *, const char *)); 82c4516a41Schopps void dump __P((u_long)); 83c4516a41Schopps void ether_print __P((const u_char *)); 84c4516a41Schopps int file __P((char *)); 85c4516a41Schopps void get __P((const char *)); 86c4516a41Schopps int getinetaddr __P((const char *, struct in_addr *)); 87c4516a41Schopps void getsocket __P((void)); 88c4516a41Schopps int rtmsg __P((int)); 89c4516a41Schopps int set __P((int, char **)); 90c4516a41Schopps void usage __P((void)); 91c4516a41Schopps 92c4516a41Schopps int 9361f28255Scgd main(argc, argv) 9461f28255Scgd int argc; 9561f28255Scgd char **argv; 9661f28255Scgd { 9761f28255Scgd int ch; 98f3b151f5Smikel int op = 0; 9961f28255Scgd 10017c454feSmycroft pid = getpid(); 101f3b151f5Smikel 102f3b151f5Smikel while ((ch = getopt(argc, argv, "andsf")) != -1) 10361f28255Scgd switch((char)ch) { 10417c454feSmycroft case 'a': 10561f28255Scgd case 'd': 106f3b151f5Smikel case 's': 107f3b151f5Smikel case 'f': 108f3b151f5Smikel if (op) 10961f28255Scgd usage(); 110f3b151f5Smikel op = ch; 111f3b151f5Smikel break; 11217c454feSmycroft case 'n': 11317c454feSmycroft nflag = 1; 114c4516a41Schopps break; 11561f28255Scgd default: 11661f28255Scgd usage(); 11761f28255Scgd } 118f3b151f5Smikel argc -= optind; 119f3b151f5Smikel argv += optind; 120f3b151f5Smikel 121f3b151f5Smikel switch((char)op) { 122f3b151f5Smikel case 'a': 123f3b151f5Smikel dump(0); 124f3b151f5Smikel break; 125f3b151f5Smikel case 'd': 126f3b151f5Smikel if (argc < 1 || argc > 2) 12761f28255Scgd usage(); 128f3b151f5Smikel (void)delete(argv[0], argv[1]); 129f3b151f5Smikel break; 130f3b151f5Smikel case 's': 131f3b151f5Smikel if (argc < 2 || argc > 5) 132f3b151f5Smikel usage(); 133f3b151f5Smikel return (set(argc, argv) ? 1 : 0); 134f3b151f5Smikel case 'f': 135f3b151f5Smikel if (argc != 1) 136f3b151f5Smikel usage(); 137f3b151f5Smikel return (file(argv[0])); 138f3b151f5Smikel default: 139f3b151f5Smikel if (argc != 1) 140f3b151f5Smikel usage(); 141f3b151f5Smikel get(argv[0]); 142f3b151f5Smikel break; 143f3b151f5Smikel } 144c4516a41Schopps return (0); 14561f28255Scgd } 14661f28255Scgd 14761f28255Scgd /* 14861f28255Scgd * Process a file to set standard arp entries 14961f28255Scgd */ 150c4516a41Schopps int 15161f28255Scgd file(name) 15261f28255Scgd char *name; 15361f28255Scgd { 15461f28255Scgd char line[100], arg[5][50], *args[5]; 155c4516a41Schopps int i, retval; 156c4516a41Schopps FILE *fp; 15761f28255Scgd 158c4516a41Schopps if ((fp = fopen(name, "r")) == NULL) 159c4516a41Schopps err(1, "cannot open %s", name); 16061f28255Scgd args[0] = &arg[0][0]; 16161f28255Scgd args[1] = &arg[1][0]; 16261f28255Scgd args[2] = &arg[2][0]; 16361f28255Scgd args[3] = &arg[3][0]; 16461f28255Scgd args[4] = &arg[4][0]; 16561f28255Scgd retval = 0; 16661f28255Scgd while (fgets(line, 100, fp) != NULL) { 16761f28255Scgd i = sscanf(line, "%s %s %s %s %s", arg[0], arg[1], arg[2], 16861f28255Scgd arg[3], arg[4]); 16961f28255Scgd if (i < 2) { 170c4516a41Schopps warnx("bad line: %s", line); 17161f28255Scgd retval = 1; 17261f28255Scgd continue; 17361f28255Scgd } 17461f28255Scgd if (set(i, args)) 17561f28255Scgd retval = 1; 17661f28255Scgd } 17761f28255Scgd fclose(fp); 17861f28255Scgd return (retval); 17961f28255Scgd } 18061f28255Scgd 181c4516a41Schopps void 182c4516a41Schopps getsocket() 183c4516a41Schopps { 184c4516a41Schopps if (s >= 0) 185c4516a41Schopps return; 18617c454feSmycroft s = socket(PF_ROUTE, SOCK_RAW, 0); 187c4516a41Schopps if (s < 0) 188c4516a41Schopps err(1, "socket"); 18917c454feSmycroft } 19017c454feSmycroft 19117c454feSmycroft struct sockaddr_in so_mask = {8, 0, 0, { 0xffffffff}}; 19217c454feSmycroft struct sockaddr_inarp blank_sin = {sizeof(blank_sin), AF_INET }, sin_m; 19317c454feSmycroft struct sockaddr_dl blank_sdl = {sizeof(blank_sdl), AF_LINK }, sdl_m; 19417c454feSmycroft int expire_time, flags, export_only, doing_proxy, found_entry; 19517c454feSmycroft struct { 19617c454feSmycroft struct rt_msghdr m_rtm; 19717c454feSmycroft char m_space[512]; 19817c454feSmycroft } m_rtmsg; 19917c454feSmycroft 20061f28255Scgd /* 20161f28255Scgd * Set an individual arp entry 20261f28255Scgd */ 203c4516a41Schopps int 20461f28255Scgd set(argc, argv) 20561f28255Scgd int argc; 20661f28255Scgd char **argv; 20761f28255Scgd { 208c4516a41Schopps register struct sockaddr_inarp *sin; 20917c454feSmycroft register struct sockaddr_dl *sdl; 210c4516a41Schopps register struct rt_msghdr *rtm; 21138f1be35Smikel struct ether_addr *ea; 212c4516a41Schopps char *host = argv[0], *eaddr; 213c4516a41Schopps 214c4516a41Schopps sin = &sin_m; 215c4516a41Schopps rtm = &(m_rtmsg.m_rtm); 216c4516a41Schopps eaddr = argv[1]; 21761f28255Scgd 21817c454feSmycroft getsocket(); 21961f28255Scgd argc -= 2; 22061f28255Scgd argv += 2; 221c4516a41Schopps sdl_m = blank_sdl; /* struct copy */ 222c4516a41Schopps sin_m = blank_sin; /* struct copy */ 223c4516a41Schopps if (getinetaddr(host, &sin->sin_addr) == -1) 22461f28255Scgd return (1); 22538f1be35Smikel ea = ether_aton(eaddr); 22638f1be35Smikel if (ea != NULL) { 22738f1be35Smikel (void)memcpy(LLADDR(&sdl_m), ea, sizeof(struct ether_addr)); 22838f1be35Smikel sdl_m.sdl_alen = sizeof(struct ether_addr); 22938f1be35Smikel } 23038f1be35Smikel else 23138f1be35Smikel warnx("invalid Ethernet address '%s'", eaddr); 23217c454feSmycroft doing_proxy = flags = export_only = expire_time = 0; 23361f28255Scgd while (argc-- > 0) { 23417c454feSmycroft if (strncmp(argv[0], "temp", 4) == 0) { 23517c454feSmycroft struct timeval time; 236c4516a41Schopps (void)gettimeofday(&time, 0); 23717c454feSmycroft expire_time = time.tv_sec + 20 * 60; 23817c454feSmycroft } 23917c454feSmycroft else if (strncmp(argv[0], "pub", 3) == 0) { 24017c454feSmycroft flags |= RTF_ANNOUNCE; 24117c454feSmycroft doing_proxy = SIN_PROXY; 24217c454feSmycroft } else if (strncmp(argv[0], "trail", 5) == 0) { 243c4516a41Schopps (void)printf( 244c4516a41Schopps "%s: Sending trailers is no longer supported\n", 24517c454feSmycroft host); 24617c454feSmycroft } 24761f28255Scgd argv++; 24861f28255Scgd } 24917c454feSmycroft tryagain: 25017c454feSmycroft if (rtmsg(RTM_GET) < 0) { 251c4516a41Schopps warn("%s", host); 25217c454feSmycroft return (1); 25361f28255Scgd } 25417c454feSmycroft sin = (struct sockaddr_inarp *)(rtm + 1); 25517c454feSmycroft sdl = (struct sockaddr_dl *)(sin->sin_len + (char *)sin); 25617c454feSmycroft if (sin->sin_addr.s_addr == sin_m.sin_addr.s_addr) { 25717c454feSmycroft if (sdl->sdl_family == AF_LINK && 25817c454feSmycroft (rtm->rtm_flags & RTF_LLINFO) && 25917c454feSmycroft !(rtm->rtm_flags & RTF_GATEWAY)) switch (sdl->sdl_type) { 26017c454feSmycroft case IFT_ETHER: case IFT_FDDI: case IFT_ISO88023: 26117c454feSmycroft case IFT_ISO88024: case IFT_ISO88025: 26217c454feSmycroft goto overwrite; 26317c454feSmycroft } 26417c454feSmycroft if (doing_proxy == 0) { 265c4516a41Schopps (void)printf("set: can only proxy for %s\n", host); 26617c454feSmycroft return (1); 26717c454feSmycroft } 26817c454feSmycroft if (sin_m.sin_other & SIN_PROXY) { 269c4516a41Schopps (void)printf( 270c4516a41Schopps "set: proxy entry exists for non 802 device\n"); 27117c454feSmycroft return (1); 27217c454feSmycroft } 27317c454feSmycroft sin_m.sin_other = SIN_PROXY; 27417c454feSmycroft export_only = 1; 27517c454feSmycroft goto tryagain; 27617c454feSmycroft } 27717c454feSmycroft overwrite: 27817c454feSmycroft if (sdl->sdl_family != AF_LINK) { 279c4516a41Schopps (void)printf("cannot intuit interface index and type for %s\n", 280c4516a41Schopps host); 28117c454feSmycroft return (1); 28217c454feSmycroft } 28317c454feSmycroft sdl_m.sdl_type = sdl->sdl_type; 28417c454feSmycroft sdl_m.sdl_index = sdl->sdl_index; 28517c454feSmycroft return (rtmsg(RTM_ADD)); 28661f28255Scgd } 28761f28255Scgd 28861f28255Scgd /* 28961f28255Scgd * Display an individual arp entry 29061f28255Scgd */ 291c4516a41Schopps void 29261f28255Scgd get(host) 293c4516a41Schopps const char *host; 29461f28255Scgd { 295c4516a41Schopps struct sockaddr_inarp *sin; 29661f28255Scgd 297c4516a41Schopps sin = &sin_m; 298c4516a41Schopps sin_m = blank_sin; /* struct copy */ 299c4516a41Schopps if (getinetaddr(host, &sin->sin_addr) == -1) 30061f28255Scgd exit(1); 30117c454feSmycroft dump(sin->sin_addr.s_addr); 30217c454feSmycroft if (found_entry == 0) { 303c4516a41Schopps (void)printf("%s (%s) -- no entry\n", host, 304c4516a41Schopps inet_ntoa(sin->sin_addr)); 30561f28255Scgd exit(1); 30661f28255Scgd } 30761f28255Scgd } 30861f28255Scgd 30961f28255Scgd /* 31061f28255Scgd * Delete an arp entry 31161f28255Scgd */ 312c4516a41Schopps int 31317c454feSmycroft delete(host, info) 314c4516a41Schopps const char *host; 315c4516a41Schopps const char *info; 31661f28255Scgd { 317c4516a41Schopps register struct sockaddr_inarp *sin; 318c4516a41Schopps register struct rt_msghdr *rtm; 31917c454feSmycroft struct sockaddr_dl *sdl; 32061f28255Scgd 321c4516a41Schopps sin = &sin_m; 322c4516a41Schopps rtm = &m_rtmsg.m_rtm; 323c4516a41Schopps 32417c454feSmycroft if (info && strncmp(info, "pro", 3) ) 32517c454feSmycroft export_only = 1; 32617c454feSmycroft getsocket(); 327c4516a41Schopps sin_m = blank_sin; /* struct copy */ 328c4516a41Schopps if (getinetaddr(host, &sin->sin_addr) == -1) 32917c454feSmycroft return (1); 33017c454feSmycroft tryagain: 33117c454feSmycroft if (rtmsg(RTM_GET) < 0) { 332c4516a41Schopps warn("%s", host); 33317c454feSmycroft return (1); 33461f28255Scgd } 33517c454feSmycroft sin = (struct sockaddr_inarp *)(rtm + 1); 33617c454feSmycroft sdl = (struct sockaddr_dl *)(sin->sin_len + (char *)sin); 33717c454feSmycroft if (sin->sin_addr.s_addr == sin_m.sin_addr.s_addr) { 33817c454feSmycroft if (sdl->sdl_family == AF_LINK && 33917c454feSmycroft (rtm->rtm_flags & RTF_LLINFO) && 34017c454feSmycroft !(rtm->rtm_flags & RTF_GATEWAY)) switch (sdl->sdl_type) { 34117c454feSmycroft case IFT_ETHER: case IFT_FDDI: case IFT_ISO88023: 34217c454feSmycroft case IFT_ISO88024: case IFT_ISO88025: 34317c454feSmycroft goto delete; 34461f28255Scgd } 34517c454feSmycroft } 34617c454feSmycroft if (sin_m.sin_other & SIN_PROXY) { 347c4516a41Schopps warnx("delete: can't locate %s", host); 34817c454feSmycroft return (1); 34917c454feSmycroft } else { 35017c454feSmycroft sin_m.sin_other = SIN_PROXY; 35117c454feSmycroft goto tryagain; 35217c454feSmycroft } 35317c454feSmycroft delete: 35417c454feSmycroft if (sdl->sdl_family != AF_LINK) { 355c4516a41Schopps (void)printf("cannot locate %s\n", host); 35617c454feSmycroft return (1); 35717c454feSmycroft } 358c4516a41Schopps if (rtmsg(RTM_DELETE)) 359c4516a41Schopps return (1); 360c4516a41Schopps (void)printf("%s (%s) deleted\n", host, inet_ntoa(sin->sin_addr)); 361c4516a41Schopps return (0); 36261f28255Scgd } 36361f28255Scgd 36461f28255Scgd /* 36561f28255Scgd * Dump the entire arp table 36661f28255Scgd */ 367c4516a41Schopps void 36817c454feSmycroft dump(addr) 36917c454feSmycroft u_long addr; 37061f28255Scgd { 37117c454feSmycroft int mib[6]; 37217c454feSmycroft size_t needed; 373c4516a41Schopps char *host, *lim, *buf, *next; 37417c454feSmycroft struct rt_msghdr *rtm; 37517c454feSmycroft struct sockaddr_inarp *sin; 37617c454feSmycroft struct sockaddr_dl *sdl; 37761f28255Scgd extern int h_errno; 37861f28255Scgd struct hostent *hp; 37961f28255Scgd 38017c454feSmycroft mib[0] = CTL_NET; 38117c454feSmycroft mib[1] = PF_ROUTE; 38217c454feSmycroft mib[2] = 0; 38317c454feSmycroft mib[3] = AF_INET; 38417c454feSmycroft mib[4] = NET_RT_FLAGS; 38517c454feSmycroft mib[5] = RTF_LLINFO; 38617c454feSmycroft if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) 387c4516a41Schopps err(1, "route-sysctl-estimate"); 38817c454feSmycroft if ((buf = malloc(needed)) == NULL) 389c4516a41Schopps err(1, "malloc"); 39017c454feSmycroft if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) 391c4516a41Schopps err(1, "actual retrieval of routing table"); 39217c454feSmycroft lim = buf + needed; 39317c454feSmycroft for (next = buf; next < lim; next += rtm->rtm_msglen) { 39417c454feSmycroft rtm = (struct rt_msghdr *)next; 39517c454feSmycroft sin = (struct sockaddr_inarp *)(rtm + 1); 39617c454feSmycroft sdl = (struct sockaddr_dl *)(sin + 1); 39717c454feSmycroft if (addr) { 39817c454feSmycroft if (addr != sin->sin_addr.s_addr) 39961f28255Scgd continue; 40017c454feSmycroft found_entry = 1; 40117c454feSmycroft } 40217c454feSmycroft if (nflag == 0) 40317c454feSmycroft hp = gethostbyaddr((caddr_t)&(sin->sin_addr), 40417c454feSmycroft sizeof sin->sin_addr, AF_INET); 40561f28255Scgd else 40661f28255Scgd hp = 0; 40761f28255Scgd if (hp) 40861f28255Scgd host = hp->h_name; 40961f28255Scgd else { 41061f28255Scgd host = "?"; 41161f28255Scgd if (h_errno == TRY_AGAIN) 41217c454feSmycroft nflag = 1; 41361f28255Scgd } 414c4516a41Schopps (void)printf("%s (%s) at ", host, inet_ntoa(sin->sin_addr)); 41517c454feSmycroft if (sdl->sdl_alen) 416*38e37321Smikel ether_print((u_char *)LLADDR(sdl)); 41761f28255Scgd else 418c4516a41Schopps (void)printf("(incomplete)"); 41917c454feSmycroft if (rtm->rtm_rmx.rmx_expire == 0) 420c4516a41Schopps (void)printf(" permanent"); 42117c454feSmycroft if (sin->sin_other & SIN_PROXY) 422c4516a41Schopps (void)printf(" published (proxy only)"); 42317c454feSmycroft if (rtm->rtm_addrs & RTA_NETMASK) { 42417c454feSmycroft sin = (struct sockaddr_inarp *) 42517c454feSmycroft (sdl->sdl_len + (char *)sdl); 42617c454feSmycroft if (sin->sin_addr.s_addr == 0xffffffff) 427c4516a41Schopps (void)printf(" published"); 42817c454feSmycroft if (sin->sin_len != 8) 429c4516a41Schopps (void)printf("(wierd)"); 43017c454feSmycroft } 431c4516a41Schopps (void)printf("\n"); 43261f28255Scgd } 43361f28255Scgd } 43461f28255Scgd 435c4516a41Schopps void 43661f28255Scgd ether_print(cp) 437c4516a41Schopps const u_char *cp; 43861f28255Scgd { 439c4516a41Schopps (void)printf("%x:%x:%x:%x:%x:%x", cp[0], cp[1], cp[2], cp[3], cp[4], 440c4516a41Schopps cp[5]); 44161f28255Scgd } 44261f28255Scgd 443c4516a41Schopps void 44461f28255Scgd usage() 44561f28255Scgd { 446c4516a41Schopps (void)fprintf(stderr, "usage: arp [-n] hostname\n"); 447c4516a41Schopps (void)fprintf(stderr, "usage: arp [-n] -a\n"); 448c4516a41Schopps (void)fprintf(stderr, "usage: arp -d hostname\n"); 449c4516a41Schopps (void)fprintf(stderr, 450c4516a41Schopps "usage: arp -s hostname ether_addr [temp] [pub]\n"); 451c4516a41Schopps (void)fprintf(stderr, "usage: arp -f filename\n"); 45261f28255Scgd exit(1); 45361f28255Scgd } 45417c454feSmycroft 455c4516a41Schopps int 45617c454feSmycroft rtmsg(cmd) 457c4516a41Schopps int cmd; 45817c454feSmycroft { 45917c454feSmycroft static int seq; 46017c454feSmycroft int rlen; 461c4516a41Schopps register struct rt_msghdr *rtm; 462c4516a41Schopps register char *cp; 46317c454feSmycroft register int l; 46417c454feSmycroft 465c4516a41Schopps rtm = &m_rtmsg.m_rtm; 466c4516a41Schopps cp = m_rtmsg.m_space; 46717c454feSmycroft errno = 0; 468c4516a41Schopps 46917c454feSmycroft if (cmd == RTM_DELETE) 47017c454feSmycroft goto doit; 471c4516a41Schopps (void)memset(&m_rtmsg, 0, sizeof(m_rtmsg)); 47217c454feSmycroft rtm->rtm_flags = flags; 47317c454feSmycroft rtm->rtm_version = RTM_VERSION; 47417c454feSmycroft 47517c454feSmycroft switch (cmd) { 47617c454feSmycroft default: 477c4516a41Schopps errx(1, "internal wrong cmd"); 478c4516a41Schopps /*NOTREACHED*/ 47917c454feSmycroft case RTM_ADD: 48017c454feSmycroft rtm->rtm_addrs |= RTA_GATEWAY; 48117c454feSmycroft rtm->rtm_rmx.rmx_expire = expire_time; 48217c454feSmycroft rtm->rtm_inits = RTV_EXPIRE; 48317c454feSmycroft rtm->rtm_flags |= (RTF_HOST | RTF_STATIC); 48417c454feSmycroft sin_m.sin_other = 0; 48517c454feSmycroft if (doing_proxy) { 48617c454feSmycroft if (export_only) 48717c454feSmycroft sin_m.sin_other = SIN_PROXY; 48817c454feSmycroft else { 48917c454feSmycroft rtm->rtm_addrs |= RTA_NETMASK; 49017c454feSmycroft rtm->rtm_flags &= ~RTF_HOST; 49117c454feSmycroft } 49217c454feSmycroft } 49317c454feSmycroft /* FALLTHROUGH */ 49417c454feSmycroft case RTM_GET: 49517c454feSmycroft rtm->rtm_addrs |= RTA_DST; 49617c454feSmycroft } 49717c454feSmycroft #define NEXTADDR(w, s) \ 49817c454feSmycroft if (rtm->rtm_addrs & (w)) { \ 499c4516a41Schopps (void)memcpy(cp, &s, sizeof(s)); cp += sizeof(s);} 50017c454feSmycroft 50117c454feSmycroft NEXTADDR(RTA_DST, sin_m); 50217c454feSmycroft NEXTADDR(RTA_GATEWAY, sdl_m); 50317c454feSmycroft NEXTADDR(RTA_NETMASK, so_mask); 50417c454feSmycroft 50517c454feSmycroft rtm->rtm_msglen = cp - (char *)&m_rtmsg; 50617c454feSmycroft doit: 50717c454feSmycroft l = rtm->rtm_msglen; 50817c454feSmycroft rtm->rtm_seq = ++seq; 50917c454feSmycroft rtm->rtm_type = cmd; 51017c454feSmycroft if ((rlen = write(s, (char *)&m_rtmsg, l)) < 0) { 51117c454feSmycroft if (errno != ESRCH || cmd != RTM_DELETE) { 512c4516a41Schopps warn("writing to routing socket"); 51317c454feSmycroft return (-1); 51417c454feSmycroft } 51517c454feSmycroft } 51617c454feSmycroft do { 51717c454feSmycroft l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg)); 51817c454feSmycroft } while (l > 0 && (rtm->rtm_seq != seq || rtm->rtm_pid != pid)); 51917c454feSmycroft if (l < 0) 520c4516a41Schopps warn("read from routing socket"); 52117c454feSmycroft return (0); 52217c454feSmycroft } 52317c454feSmycroft 524c4516a41Schopps int 525c4516a41Schopps getinetaddr(host, inap) 526c4516a41Schopps const char *host; 527c4516a41Schopps struct in_addr *inap; 52817c454feSmycroft { 529c4516a41Schopps struct hostent *hp; 530c4516a41Schopps 5319a1b7b98Schopps if (inet_aton(host, inap) == 1) 532c4516a41Schopps return (0); 533c4516a41Schopps if ((hp = gethostbyname(host)) == NULL) { 5346020b180Smycroft warnx("%s: %s\n", host, hstrerror(h_errno)); 535c4516a41Schopps return (-1); 536c4516a41Schopps } 537c4516a41Schopps (void)memcpy(inap, hp->h_addr, sizeof(*inap)); 538c4516a41Schopps return (0); 53917c454feSmycroft } 540