Esempio n. 1
0
/*
 * Set an individual neighbor cache entry
 */
int
set(int argc, char **argv)
{
	struct sockaddr_in6 *sin = &sin_m;
	struct sockaddr_dl *sdl;
	struct rt_msghdr *rtm = &(m_rtmsg.m_rtm);
	struct addrinfo hints, *res;
	int gai_error;
	u_char *ea;
	char *host = argv[0], *eaddr = argv[1];

	getsocket();
	argc -= 2;
	argv += 2;
	sdl_m = blank_sdl;
	sin_m = blank_sin;

	bzero(&hints, sizeof(hints));
	hints.ai_family = AF_INET6;
	gai_error = getaddrinfo(host, NULL, &hints, &res);
	if (gai_error) {
		fprintf(stderr, "ndp: %s: %s\n", host,
			gai_strerror(gai_error));
		return 1;
	}
	sin->sin6_addr = ((struct sockaddr_in6 *)res->ai_addr)->sin6_addr;
#ifdef __KAME__
	if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr)) {
		*(u_int16_t *)&sin->sin6_addr.s6_addr[2] =
			htons(((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id);
	}
#endif
	ea = (u_char *)LLADDR(&sdl_m);
	if (ndp_ether_aton(eaddr, ea) == 0)
		sdl_m.sdl_alen = 6;
	flags = 0;
	expire_time = 0;
	while (argc-- > 0) {
		if (strncmp(argv[0], "temp", 4) == 0) {
			struct timespec sp;

			clock_gettime(CLOCK_MONOTONIC, &sp);
			expire_time = sp.tv_sec + 20 * 60;
		} else if (strncmp(argv[0], "proxy", 5) == 0)
			flags |= RTF_ANNOUNCE;
		argv++;
	}
	if (rtmsg(RTM_GET) < 0) {
		perror(host);
		return (1);
	}
	sin = (struct sockaddr_in6 *)(rtm + 1);
	sdl = (struct sockaddr_dl *)(RT_ROUNDUP(sin->sin6_len) + (char *)sin);
	if (IN6_ARE_ADDR_EQUAL(&sin->sin6_addr, &sin_m.sin6_addr)) {
		if (sdl->sdl_family == AF_LINK &&
		    (rtm->rtm_flags & RTF_LLINFO) &&
		    !(rtm->rtm_flags & RTF_GATEWAY)) switch (sdl->sdl_type) {
		case IFT_ETHER: case IFT_FDDI: case IFT_ISO88023:
		case IFT_ISO88024: case IFT_ISO88025:
			goto overwrite;
		}
		/*
		 * IPv4 arp command retries with sin_other = SIN_PROXY here.
		 */
		fprintf(stderr, "set: cannot configure a new entry\n");
		return 1;
	}

overwrite:
	if (sdl->sdl_family != AF_LINK) {
		printf("cannot intuit interface index and type for %s\n", host);
		return (1);
	}
	sdl_m.sdl_type = sdl->sdl_type;
	sdl_m.sdl_index = sdl->sdl_index;
	return (rtmsg(RTM_ADD));
}
Esempio n. 2
0
/*
 * Set an individual arp entry
 */
int
arptab_set(u_char *eaddr, u_int32_t host)
{
	struct sockaddr_inarp *sin = &sin_m;
	struct rt_msghdr *rtm = &(m_rtmsg.m_rtm);
	struct sockaddr_dl *sdl;
	struct timeval now;
	int rt;

	getsocket();
	pid = getpid();

	sdl_m = blank_sdl;
	sin_m = blank_sin;
	sin->sin_addr.s_addr = host;
	memcpy((u_char *)LLADDR(&sdl_m), (char *)eaddr, 6);
	sdl_m.sdl_alen = 6;
	expire_time = 0;
	doing_proxy = flags = export_only = 0;
	gettimeofday(&now, 0);
	expire_time = now.tv_sec + 20 * 60;

tryagain:
	if (rtmsg(RTM_GET) < 0) {
		syslog(LOG_ERR,"%s: %m", inet_ntoa(sin->sin_addr));
		close(s);
		s = -1;
		return (1);
	}
	sin = (struct sockaddr_inarp *)((char *)rtm + rtm->rtm_hdrlen);
	sdl = (struct sockaddr_dl *)(sin->sin_len + (char *)sin);
	if (sin->sin_addr.s_addr == sin_m.sin_addr.s_addr) {
		if (sdl->sdl_family == AF_LINK &&
		    (rtm->rtm_flags & RTF_LLINFO) &&
		    !(rtm->rtm_flags & RTF_GATEWAY))
			switch (sdl->sdl_type) {
			case IFT_ETHER:
			case IFT_FDDI:
			case IFT_ISO88023:
			case IFT_ISO88024:
			case IFT_ISO88025:
				goto overwrite;
			default:
				break;
		}
		if (doing_proxy == 0) {
			syslog(LOG_ERR, "arptab_set: can only proxy for %s",
			    inet_ntoa(sin->sin_addr));
			close(s);
			s = -1;
			return (1);
		}
		if (sin_m.sin_other & SIN_PROXY) {
			syslog(LOG_ERR,
			    "arptab_set: proxy entry exists for non 802 device");
			close(s);
			s = -1;
			return(1);
		}
		sin_m.sin_other = SIN_PROXY;
		export_only = 1;
		goto tryagain;
	}
overwrite:
	if (sdl->sdl_family != AF_LINK) {
		syslog(LOG_ERR,
		    "arptab_set: cannot intuit interface index and type for %s",
		    inet_ntoa(sin->sin_addr));
		close(s);
		s = -1;
		return (1);
	}
	sdl_m.sdl_type = sdl->sdl_type;
	sdl_m.sdl_index = sdl->sdl_index;
	rt = rtmsg(RTM_ADD);
	close(s);
	s = -1;
	return (rt);
}
Esempio n. 3
0
/*
 * Set an individual arp entry
 */
int
set(int argc, char *argv[])
{
	struct sockaddr_inarp *sin;
	struct sockaddr_dl *sdl;
	struct rt_msghdr *rtm;
	char *eaddr = argv[1], *host = argv[0];
	struct ether_addr *ea;

	sin = &sin_m;
	rtm = &(m_rtmsg.m_rtm);

	getsocket();
	argc -= 2;
	argv += 2;
	sdl_m = blank_sdl;		/* struct copy */
	sin_m = blank_sin;		/* struct copy */
	if (getinetaddr(host, &sin->sin_addr) == -1)
		return (1);
	ea = ether_aton(eaddr);
	if (ea == NULL)
		errx(1, "invalid ethernet address: %s", eaddr);
	memcpy(LLADDR(&sdl_m), ea, sizeof(*ea));
	sdl_m.sdl_alen = 6;
	expire_time = 0;
	doing_proxy = flags = export_only = 0;
	while (argc-- > 0) {
		if (strncmp(argv[0], "temp", 4) == 0) {
			struct timeval now;

			gettimeofday(&now, 0);
			expire_time = now.tv_sec + 20 * 60;
			if (flags & RTF_PERMANENT_ARP) {
				/* temp or permanent, not both */
				usage();
				return (0);
			}
		} else if (strncmp(argv[0], "pub", 3) == 0) {
			flags |= RTF_ANNOUNCE;
			doing_proxy = SIN_PROXY;
		} else if (strncmp(argv[0], "permanent", 9) == 0) {
			flags |= RTF_PERMANENT_ARP;
			if (expire_time != 0) {
				/* temp or permanent, not both */
				usage();
				return (0);
			}
		}

		argv++;
	}

tryagain:
	if (rtget(&sin, &sdl)) {
		warn("%s", host);
		return (1);
	}

	if (sin->sin_addr.s_addr == sin_m.sin_addr.s_addr) {
		if (sdl->sdl_family == AF_LINK &&
		    (rtm->rtm_flags & RTF_LLINFO) &&
		    !(rtm->rtm_flags & RTF_GATEWAY))
			switch (sdl->sdl_type) {
			case IFT_ETHER:
			case IFT_FDDI:
			case IFT_ISO88023:
			case IFT_ISO88024:
			case IFT_ISO88025:
			case IFT_CARP:
				goto overwrite;
			}

		if (doing_proxy == 0) {
			printf("set: can only proxy for %s\n", host);
			return (1);
		}
		if (sin_m.sin_other & SIN_PROXY) {
			printf("set: proxy entry exists for non 802 device\n");
			return (1);
		}
		sin_m.sin_other = SIN_PROXY;
		export_only = 1;
		goto tryagain;
	}

overwrite:
	if (sdl->sdl_family != AF_LINK) {
		printf("cannot intuit interface index and type for %s\n", host);
		return (1);
	}
	sdl_m.sdl_type = sdl->sdl_type;
	sdl_m.sdl_index = sdl->sdl_index;
	return (rtmsg(RTM_ADD));
}
Esempio n. 4
0
/*
 * Set an individual neighbor cache entry
 */
static int
set(int argc, char **argv)
{
	register struct sockaddr_in6 *sin = &sin_m;
	register struct sockaddr_dl *sdl;
	register struct rt_msghdr *rtm = &(m_rtmsg.m_rtm);
	struct addrinfo hints, *res;
	int gai_error;
	u_char *ea;
	char *host = argv[0], *eaddr = argv[1];

	getsocket();
	argc -= 2;
	argv += 2;
	sdl_m = blank_sdl;
	sin_m = blank_sin;

	bzero(&hints, sizeof(hints));
	hints.ai_family = AF_INET6;
	gai_error = getaddrinfo(host, NULL, &hints, &res);
	if (gai_error) {
		fprintf(stderr, "ndp: %s: %s\n", host,
			gai_strerror(gai_error));
		return 1;
	}
	sin->sin6_addr = ((struct sockaddr_in6 *)res->ai_addr)->sin6_addr;
	sin->sin6_scope_id =
	    ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id;
	ea = (u_char *)LLADDR(&sdl_m);
	if (ndp_ether_aton(eaddr, ea) == 0)
		sdl_m.sdl_alen = 6;
	flags = expire_time = 0;
	while (argc-- > 0) {
		if (strncmp(argv[0], "temp", 4) == 0) {
			struct timeval now;

			gettimeofday(&now, 0);
			expire_time = now.tv_sec + 20 * 60;
		} else if (strncmp(argv[0], "proxy", 5) == 0)
			flags |= RTF_ANNOUNCE;
		argv++;
	}
	if (rtmsg(RTM_GET) < 0) {
		errx(1, "RTM_GET(%s) failed", host);
		/* NOTREACHED */
	}
	sin = (struct sockaddr_in6 *)(rtm + 1);
	sdl = (struct sockaddr_dl *)(ALIGN(sin->sin6_len) + (char *)sin);
	if (IN6_ARE_ADDR_EQUAL(&sin->sin6_addr, &sin_m.sin6_addr)) {
		if (sdl->sdl_family == AF_LINK &&
		    !(rtm->rtm_flags & RTF_GATEWAY)) {
			switch (sdl->sdl_type) {
			case IFT_ETHER: case IFT_FDDI: case IFT_ISO88023:
			case IFT_ISO88024: case IFT_ISO88025:
			case IFT_L2VLAN: case IFT_BRIDGE:
				goto overwrite;
			}
		}
		fprintf(stderr, "set: cannot configure a new entry\n");
		return 1;
	}

overwrite:
	if (sdl->sdl_family != AF_LINK) {
		printf("cannot intuit interface index and type for %s\n", host);
		return (1);
	}
	sdl_m.sdl_type = sdl->sdl_type;
	sdl_m.sdl_index = sdl->sdl_index;
	return (rtmsg(RTM_ADD));
}
Esempio n. 5
0
/*
 * Set an individual arp entry
 */
static int
set(int argc, char **argv)
{
	struct sockaddr_in *addr;
	struct sockaddr_in *dst;	/* what are we looking for */
	struct sockaddr_dl *sdl;
	struct rt_msghdr *rtm;
	struct ether_addr *ea;
	char *host = argv[0], *eaddr = argv[1];
	struct sockaddr_dl sdl_m;

	argc -= 2;
	argv += 2;

	bzero(&sdl_m, sizeof(sdl_m));
	sdl_m.sdl_len = sizeof(sdl_m);
	sdl_m.sdl_family = AF_LINK;

	dst = getaddr(host);
	if (dst == NULL)
		return (1);
	doing_proxy = flags = expire_time = 0;
	while (argc-- > 0) {
		if (strncmp(argv[0], "temp", 4) == 0) {
			struct timespec tp;
			int max_age;
			size_t len = sizeof(max_age);

			clock_gettime(CLOCK_MONOTONIC, &tp);
			if (sysctlbyname("net.link.ether.inet.max_age",
			    &max_age, &len, NULL, 0) != 0)
				err(1, "sysctlbyname");
			expire_time = tp.tv_sec + max_age;
		} else if (strncmp(argv[0], "pub", 3) == 0) {
			flags |= RTF_ANNOUNCE;
			doing_proxy = 1;
			if (argc && strncmp(argv[1], "only", 3) == 0) {
				/*
				 * Compatibility: in pre FreeBSD 8 times
				 * the "only" keyword used to mean that
				 * an ARP entry should be announced, but
				 * not installed into routing table.
				 */
				argc--; argv++;
			}
		} else if (strncmp(argv[0], "blackhole", 9) == 0) {
			if (flags & RTF_REJECT) {
				printf("Choose one of blackhole or reject, not both.\n");
			}
			flags |= RTF_BLACKHOLE;
		} else if (strncmp(argv[0], "reject", 6) == 0) {
			if (flags & RTF_BLACKHOLE) {
				printf("Choose one of blackhole or reject, not both.\n");
			}
			flags |= RTF_REJECT;
		} else if (strncmp(argv[0], "trail", 5) == 0) {
			/* XXX deprecated and undocumented feature */
			printf("%s: Sending trailers is no longer supported\n",
				host);
		}
		argv++;
	}
	ea = (struct ether_addr *)LLADDR(&sdl_m);
	if (doing_proxy && !strcmp(eaddr, "auto")) {
		if (!get_ether_addr(dst->sin_addr.s_addr, ea)) {
			printf("no interface found for %s\n",
			       inet_ntoa(dst->sin_addr));
			return (1);
		}
		sdl_m.sdl_alen = ETHER_ADDR_LEN;
	} else {
		struct ether_addr *ea1 = ether_aton(eaddr);

		if (ea1 == NULL) {
			warnx("invalid Ethernet address '%s'", eaddr);
			return (1);
		} else {
			*ea = *ea1;
			sdl_m.sdl_alen = ETHER_ADDR_LEN;
		}
	}

	/*
	 * In the case a proxy-arp entry is being added for
	 * a remote end point, the RTF_ANNOUNCE flag in the 
	 * RTM_GET command is an indication to the kernel
	 * routing code that the interface associated with
	 * the prefix route covering the local end of the
	 * PPP link should be returned, on which ARP applies.
	 */
	rtm = rtmsg(RTM_GET, dst, &sdl_m);
	if (rtm == NULL) {
		warn("%s", host);
		return (1);
	}
	addr = (struct sockaddr_in *)(rtm + 1);
	sdl = (struct sockaddr_dl *)(SA_SIZE(addr) + (char *)addr);

	if ((sdl->sdl_family != AF_LINK) ||
	    (rtm->rtm_flags & RTF_GATEWAY) ||
	    !valid_type(sdl->sdl_type)) {
		printf("cannot intuit interface index and type for %s\n", host);
		return (1);
	}
	sdl_m.sdl_type = sdl->sdl_type;
	sdl_m.sdl_index = sdl->sdl_index;
	return (rtmsg(RTM_ADD, dst, &sdl_m) == NULL);
}
Esempio n. 6
0
/*
 * Set an individual arp entry
 */
int
bsd_arp_set(struct in_addr *ia, char *eaddr, int len)
{
	struct sockaddr_inarp *sin = &sin_m;
	struct sockaddr_dl *sdl;
	struct rt_msghdr *rtm = &(m_rtmsg.m_rtm);
	u_char *ea;
	struct timeval time;
	int op = RTM_ADD;

	getsocket();
	sdl_m = blank_sdl;
	sin_m = blank_sin;
	sin->sin_addr = *ia;

	ea = (u_char *)LLADDR(&sdl_m);
	bcopy(eaddr, ea, len);
	sdl_m.sdl_alen = len;
	doing_proxy = flags = export_only = expire_time = 0;

	/* make arp entry temporary */
	gettimeofday(&time, 0);
	expire_time = time.tv_sec + 20 * 60;

tryagain:
	if (rtmsg(RTM_GET) < 0) {
		report(LOG_WARNING, "rtmget: %s", strerror(errno));
		return (1);
	}
	sin = (struct sockaddr_inarp *)(rtm + 1);
	sdl = (struct sockaddr_dl *)(sin->sin_len + (char *)sin);
	if (sin->sin_addr.s_addr == sin_m.sin_addr.s_addr) {
		if (sdl->sdl_family == AF_LINK &&
		    (rtm->rtm_flags & RTF_LLINFO) &&
		    !(rtm->rtm_flags & RTF_GATEWAY)) switch (sdl->sdl_type) {
		case IFT_ETHER: case IFT_FDDI: case IFT_ISO88023:
		case IFT_ISO88024: case IFT_ISO88025:
			op = RTM_CHANGE;
			goto overwrite;
		}
		if (doing_proxy == 0) {
			report(LOG_WARNING, "set: can only proxy for %s\n",
				inet_ntoa(sin->sin_addr));
			return (1);
		}
		if (sin_m.sin_other & SIN_PROXY) {
			report(LOG_WARNING,
				"set: proxy entry exists for non 802 device\n");
			return(1);
		}
		sin_m.sin_other = SIN_PROXY;
		export_only = 1;
		goto tryagain;
	}
overwrite:
	if (sdl->sdl_family != AF_LINK) {
		report(LOG_WARNING,
			"cannot intuit interface index and type for %s\n",
			inet_ntoa(sin->sin_addr));
		return (1);
	}
	sdl_m.sdl_type = sdl->sdl_type;
	sdl_m.sdl_index = sdl->sdl_index;
	return (rtmsg(op));
}
Esempio n. 7
0
/*
 * Set an individual neighbor cache entry
 */
static int
set(int argc, char **argv)
{
	register struct sockaddr_in6 *mysin = &sin_m;
	register struct sockaddr_dl *sdl;
	register struct rt_msghdr *rtm = &(m_rtmsg.m_rtm);
	struct addrinfo hints, *res;
	int gai_error;
	u_char *ea;
	char *host = argv[0], *eaddr = argv[1];

	getsocket();
	argc -= 2;
	argv += 2;
	sdl_m = blank_sdl;
	sin_m = blank_sin;

	(void)memset(&hints, 0, sizeof(hints));
	hints.ai_family = AF_INET6;
	gai_error = getaddrinfo(host, NULL, &hints, &res);
	if (gai_error) {
		warnx("%s: %s\n", host, gai_strerror(gai_error));
		return 1;
	}
	mysin->sin6_addr = ((struct sockaddr_in6 *)(void *)res->ai_addr)->sin6_addr;
	inet6_putscopeid(mysin, INET6_IS_ADDR_LINKLOCAL);
	ea = (u_char *)LLADDR(&sdl_m);
	if (ndp_ether_aton(eaddr, ea) == 0)
		sdl_m.sdl_alen = 6;
	flags = expire_time = 0;
	while (argc-- > 0) {
		if (strncmp(argv[0], "temp", 4) == 0) {
			struct timeval tim;

			(void)gettimeofday(&tim, 0);
			expire_time = tim.tv_sec + 20 * 60;
		} else if (strncmp(argv[0], "proxy", 5) == 0)
			flags |= RTF_ANNOUNCE;
		argv++;
	}
	if (rtmsg(RTM_GET) < 0) {
		errx(1, "RTM_GET(%s) failed", host);
		/* NOTREACHED */
	}
	mysin = (struct sockaddr_in6 *)(void *)(rtm + 1);
	sdl = (struct sockaddr_dl *)(void *)(RT_ROUNDUP(mysin->sin6_len) + (char *)(void *)mysin);
	if (IN6_ARE_ADDR_EQUAL(&mysin->sin6_addr, &sin_m.sin6_addr)) {
		if (sdl->sdl_family == AF_LINK &&
		    (rtm->rtm_flags & RTF_LLINFO) &&
		    !(rtm->rtm_flags & RTF_GATEWAY)) {
			switch (sdl->sdl_type) {
			case IFT_ETHER: case IFT_FDDI: case IFT_ISO88023:
			case IFT_ISO88024: case IFT_ISO88025:
				goto overwrite;
			}
		}
		/*
		 * IPv4 arp command retries with sin_other = SIN_PROXY here.
		 */
		(void)fprintf(stderr, "set: cannot configure a new entry\n");
		return 1;
	}

overwrite:
	if (sdl->sdl_family != AF_LINK) {
		warnx("cannot intuit interface index and type for %s", host);
		return (1);
	}
	sdl_m.sdl_type = sdl->sdl_type;
	sdl_m.sdl_index = sdl->sdl_index;
	return (rtmsg(RTM_ADD));
}
Esempio n. 8
0
/*
 * Set an individual arp entry 
 */
static int
set(int argc, char **argv)
{
	struct sockaddr_inarp *sina;
	struct sockaddr_dl *sdl;
	struct rt_msghdr *rtm;
	char *host = argv[0], *eaddr;
	struct sockaddr_inarp sin_m = blank_sin; /* struct copy */
	struct sockaddr_dl sdl_m = blank_sdl; /* struct copy */
	int s;

	eaddr = argv[1];

	s = getsocket();
	argc -= 2;
	argv += 2;

	if (getinetaddr(host, &sin_m.sin_addr) == -1)
		return (1);
	if (atosdl(eaddr, &sdl_m))
		warnx("invalid link-level address '%s'", eaddr);
	doing_proxy = flags = export_only = expire_time = 0;
	for (; argc-- > 0; argv++) {
		if (strncmp(argv[0], "temp", 4) == 0) {
			struct timeval timev;
			(void)gettimeofday(&timev, 0);
			expire_time = timev.tv_sec + 20 * 60;
		}
		else if (strncmp(argv[0], "pub", 3) == 0) {
			flags |= RTF_ANNOUNCE;
			doing_proxy = SIN_PROXY;
			if (argc && strncmp(argv[1], "pro", 3) == 0) {
			        export_only = 1;
			        argc--; argv++;
			}
		} else if (strncmp(argv[0], "trail", 5) == 0) {
			warnx("%s: Sending trailers is no longer supported",
			    host);
		} else if (strcmp(argv[0], "ifscope") == 0) {
			if (argc == 0) {
				warnx("missing interface for ifscope");
				continue;
			}
			argc--;
			argv++;
			if (!getlink(argv[0], &sdl_m))
				warnx("cannot get link address for %s", argv[0]);
		}

	}
	if (memcmp(&sdl_m, &blank_sdl, sizeof(blank_sdl)))
		goto out;
tryagain:
	rtm = rtmsg(s, RTM_GET, &sin_m, &sdl_m);
	if (rtm == NULL) {
		warn("%s", host);
		return (1);
	}
	sina = (struct sockaddr_inarp *)(void *)(rtm + 1);
	sdl = (struct sockaddr_dl *)(void *)(RT_ROUNDUP(sina->sin_len) +
	    (char *)(void *)sina);
	if (sina->sin_addr.s_addr == sin_m.sin_addr.s_addr) {
		if (is_llinfo(sdl, rtm->rtm_flags))
			goto overwrite;
		if (doing_proxy == 0) {
			warnx("set: can only proxy for %s", host);
			return (1);
		}
		if (sin_m.sin_other & SIN_PROXY) {
			warnx("set: proxy entry exists for non 802 device");
			return (1);
		}
		sin_m.sin_other = SIN_PROXY;
		export_only = 1;
		goto tryagain;
	}
overwrite:
	if (sdl->sdl_family != AF_LINK) {
		warnx("cannot intuit interface index and type for %s",
		    host);
		return (1);
	}
	sdl_m.sdl_type = sdl->sdl_type;
	sdl_m.sdl_index = sdl->sdl_index;
out:
	sin_m.sin_other = 0;
	if (doing_proxy && export_only)
		sin_m.sin_other = SIN_PROXY;
	rtm = rtmsg(s, RTM_ADD, &sin_m, &sdl_m);
	if (vflag)
		(void)printf("%s (%s) added\n", host, eaddr);
	return (rtm == NULL) ? 1 : 0;
}
Esempio n. 9
0
/*
 * Set an individual arp entry
 */
int
set(int argc, char **argv)
{
	struct hostent *hp;
	struct sockaddr_inarp *addr = &sin_m;
	struct sockaddr_dl *sdl;
	struct rt_msghdr *rtm = &(m_rtmsg.m_rtm);
	struct ether_addr *ea;
	char *host = argv[0], *eaddr = argv[1];

	getsocket();
	argc -= 2;
	argv += 2;
	sdl_m = blank_sdl;
	sin_m = blank_sin;
	addr->sin_addr.s_addr = inet_addr(host);
	if (addr->sin_addr.s_addr == INADDR_NONE) {
		if (!(hp = gethostbyname(host))) {
			warnx("%s: %s", host, hstrerror(h_errno));
			return(1);
		}
		bcopy((char *)hp->h_addr, (char *)&addr->sin_addr,
		    sizeof(addr->sin_addr));
	}
	doing_proxy = flags = proxy_only = expire_time = 0;
	while (argc-- > 0) {
		if (strncmp(argv[0], "temp", 4) == 0) {
			struct timeval tv;
			gettimeofday(&tv, 0);
			expire_time = tv.tv_sec + 20 * 60;
		}
		else if (strncmp(argv[0], "pub", 3) == 0) {
			flags |= RTF_ANNOUNCE;
			doing_proxy = 1;
			if (argc && strncmp(argv[1], "only", 3) == 0) {
				proxy_only = 1;
				sin_m.sin_other = SIN_PROXY;
				argc--; argv++;
			}
		} else if (strncmp(argv[0], "trail", 5) == 0) {
			printf("%s: Sending trailers is no longer supported\n",
				host);
		}
		argv++;
	}
	ea = (struct ether_addr *)LLADDR(&sdl_m);
	if (doing_proxy && !strcmp(eaddr, "auto")) {
		if (!get_ether_addr(addr->sin_addr.s_addr, ea)) {
			printf("no interface found for %s\n",
			       inet_ntoa(addr->sin_addr));
			return(1);
		}
		sdl_m.sdl_alen = ETHER_ADDR_LEN;
	} else {
		if (my_ether_aton(eaddr, ea) == 0)
			sdl_m.sdl_alen = ETHER_ADDR_LEN;
	}
tryagain:
	if (rtmsg(RTM_GET) < 0) {
		warn("%s", host);
		return(1);
	}
	addr = (struct sockaddr_inarp *)(rtm + 1);
	sdl = (struct sockaddr_dl *)(ROUNDUP(addr->sin_len) + (char *)addr);
	if (addr->sin_addr.s_addr == sin_m.sin_addr.s_addr) {
		if (sdl->sdl_family == AF_LINK &&
		    (rtm->rtm_flags & RTF_LLINFO) &&
		    !(rtm->rtm_flags & RTF_GATEWAY)) switch (sdl->sdl_type) {
		case IFT_ETHER: case IFT_FDDI: case IFT_ISO88023:
		case IFT_ISO88024: case IFT_ISO88025: case IFT_L2VLAN:
		case IFT_CARP:
			goto overwrite;
		}
		if (doing_proxy == 0) {
			printf("set: can only proxy for %s\n", host);
			return(1);
		}
		if (sin_m.sin_other & SIN_PROXY) {
			printf("set: proxy entry exists for non 802 device\n");
			return(1);
		}
		sin_m.sin_other = SIN_PROXY;
		proxy_only = 1;
		goto tryagain;
	}
overwrite:
	if (sdl->sdl_family != AF_LINK) {
		printf("cannot intuit interface index and type for %s\n", host);
		return(1);
	}
	sdl_m.sdl_type = sdl->sdl_type;
	sdl_m.sdl_index = sdl->sdl_index;
	return(rtmsg(RTM_ADD));
}