示例#1
0
ssize_t
if_sendrawpacket(const struct interface *ifp, int protocol,
    const void *data, size_t len)
{
	struct iovec iov[2];
	struct ether_header hw;
	int fd;
	const struct dhcp_state *state;

	memset(&hw, 0, ETHER_HDR_LEN);
	memset(&hw.ether_dhost, 0xff, ETHER_ADDR_LEN);
	hw.ether_type = htons(protocol);
	iov[0].iov_base = &hw;
	iov[0].iov_len = ETHER_HDR_LEN;
	iov[1].iov_base = UNCONST(data);
	iov[1].iov_len = len;
	state = D_CSTATE(ifp);
	if (protocol == ETHERTYPE_ARP)
		fd = state->arp_fd;
	else
		fd = state->raw_fd;
	return writev(fd, iov, 2);
}
示例#2
0
int
if_route(const struct rt *rt, int action)
{
	const struct dhcp_state *state;
	union sockunion {
		struct sockaddr sa;
		struct sockaddr_in sin;
		struct sockaddr_dl sdl;
		struct sockaddr_storage ss;
	} su;
	struct rtm
	{
		struct rt_msghdr hdr;
		char buffer[sizeof(su) * 4];
	} rtm;
	char *bp = rtm.buffer;
	size_t l;
	int retval = 0;

#define ADDSU {								      \
		l = RT_ROUNDUP(su.sa.sa_len);				      \
		memcpy(bp, &su, l);					      \
		bp += l;						      \
	}
#define ADDADDR(addr) {							      \
		memset(&su, 0, sizeof(su));				      \
		su.sin.sin_family = AF_INET;				      \
		su.sin.sin_len = sizeof(su.sin);			      \
		(&su.sin)->sin_addr = *addr;				      \
		ADDSU;							      \
	}

	state = D_CSTATE(rt->iface);
	memset(&rtm, 0, sizeof(rtm));
	rtm.hdr.rtm_version = RTM_VERSION;
	rtm.hdr.rtm_seq = 1;
	if (action == 0)
		rtm.hdr.rtm_type = RTM_CHANGE;
	else if (action > 0)
		rtm.hdr.rtm_type = RTM_ADD;
	else
		rtm.hdr.rtm_type = RTM_DELETE;
	rtm.hdr.rtm_flags = RTF_UP;
	/* None interface subnet routes are static. */
	if (rt->gate.s_addr != INADDR_ANY ||
	    rt->net.s_addr != state->net.s_addr ||
	    rt->dest.s_addr != (state->addr.s_addr & state->net.s_addr))
		rtm.hdr.rtm_flags |= RTF_STATIC;
	rtm.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY;
	if (rt->dest.s_addr == rt->gate.s_addr &&
	    rt->net.s_addr == INADDR_BROADCAST)
		rtm.hdr.rtm_flags |= RTF_HOST;
	else if (rt->gate.s_addr == htonl(INADDR_LOOPBACK) &&
	    rt->net.s_addr == INADDR_BROADCAST)
		rtm.hdr.rtm_flags |= RTF_HOST | RTF_GATEWAY;
	else {
		rtm.hdr.rtm_addrs |= RTA_NETMASK;
		if (rtm.hdr.rtm_flags & RTF_STATIC)
			rtm.hdr.rtm_flags |= RTF_GATEWAY;
		if (action >= 0)
			rtm.hdr.rtm_addrs |= RTA_IFA;
	}

	ADDADDR(&rt->dest);
	if ((rtm.hdr.rtm_flags & RTF_HOST &&
	    rt->gate.s_addr != htonl(INADDR_LOOPBACK)) ||
	    !(rtm.hdr.rtm_flags & RTF_STATIC))
	{
		/* Make us a link layer socket for the host gateway */
		memset(&su, 0, sizeof(su));
		su.sdl.sdl_len = sizeof(struct sockaddr_dl);
		link_addr(rt->iface->name, &su.sdl);
		ADDSU;
	} else
		ADDADDR(&rt->gate);

	if (rtm.hdr.rtm_addrs & RTA_NETMASK)
		ADDADDR(&rt->net);

	if (rtm.hdr.rtm_addrs & RTA_IFP) {
		/* Make us a link layer socket for the host gateway */
		memset(&su, 0, sizeof(su));
		su.sdl.sdl_len = sizeof(struct sockaddr_dl);
		link_addr(rt->iface->name, &su.sdl);
		ADDSU;
	}

	if (rtm.hdr.rtm_addrs & RTA_IFA)
		ADDADDR(&state->addr);

#undef ADDADDR
#undef ADDSU

	rtm.hdr.rtm_msglen = l = bp - (char *)&rtm;
	if (write(r_fd, &rtm, l) == -1)
		retval = -1;
	return retval;
}
示例#3
0
int
if_route(const struct rt *rt, int action)
{
	const struct dhcp_state *state;
	union sockunion {
		struct sockaddr sa;
		struct sockaddr_in sin;
		struct sockaddr_dl sdl;
		struct sockaddr_storage ss;
	} su;
	struct rtm
	{
		struct rt_msghdr hdr;
		char buffer[sizeof(su) * 5];
	} rtm;
	char *bp = rtm.buffer;
	size_t l;
	int s, retval;

	if ((s = socket(PF_ROUTE, SOCK_RAW, 0)) == -1)
		return -1;

#define ADDSU {								      \
		l = RT_ROUNDUP(su.sa.sa_len);				      \
		memcpy(bp, &su, l);					      \
		bp += l;						      \
	}
#define ADDADDR(addr) {							      \
		memset(&su, 0, sizeof(su));				      \
		su.sin.sin_family = AF_INET;				      \
		su.sin.sin_len = sizeof(su.sin);			      \
		(&su.sin)->sin_addr = *addr;				      \
		ADDSU;							      \
	}

	state = D_CSTATE(rt->iface);
	memset(&rtm, 0, sizeof(rtm));
	rtm.hdr.rtm_version = RTM_VERSION;
	rtm.hdr.rtm_seq = 1;
	rtm.hdr.rtm_addrs = RTA_DST;
	if (action == 0)
		rtm.hdr.rtm_type = RTM_CHANGE;
	else if (action > 0) {
		rtm.hdr.rtm_type = RTM_ADD;
		rtm.hdr.rtm_addrs |= RTA_GATEWAY;
	} else
		rtm.hdr.rtm_type = RTM_DELETE;
	rtm.hdr.rtm_flags = RTF_UP;
#ifdef RTF_PINNED
	if (rtm.hdr.rtm_type != RTM_ADD)
		rtm.hdr.rtm_flags |= RTF_PINNED;
#endif
#ifdef SIOCGIFPRIORITY
	rtm.hdr.rtm_priority = rt->metric;
#endif

	/* None interface subnet routes are static. */
	if (rt->gate.s_addr != INADDR_ANY ||
	    rt->net.s_addr != state->net.s_addr ||
	    rt->dest.s_addr != (state->addr.s_addr & state->net.s_addr))
		rtm.hdr.rtm_flags |= RTF_STATIC;
	if (rt->dest.s_addr == rt->gate.s_addr &&
	    rt->net.s_addr == INADDR_BROADCAST)
		rtm.hdr.rtm_flags |= RTF_HOST;
	else if (rt->gate.s_addr == htonl(INADDR_LOOPBACK) &&
	    rt->net.s_addr == INADDR_BROADCAST)
		rtm.hdr.rtm_flags |= RTF_HOST | RTF_GATEWAY;
	else {
		rtm.hdr.rtm_addrs |= RTA_NETMASK;
		if (rtm.hdr.rtm_flags & RTF_STATIC)
			rtm.hdr.rtm_flags |= RTF_GATEWAY;
		if (action >= 0)
			rtm.hdr.rtm_addrs |= RTA_IFA;
	}

	ADDADDR(&rt->dest);
	if (rtm.hdr.rtm_addrs & RTA_GATEWAY) {
		if ((rtm.hdr.rtm_flags & RTF_HOST &&
		    rt->gate.s_addr != htonl(INADDR_LOOPBACK)) ||
		    !(rtm.hdr.rtm_flags & RTF_STATIC))
		{
			if_linkaddr(&su.sdl, rt->iface);
			ADDSU;
		} else
			ADDADDR(&rt->gate);
	}

	if (rtm.hdr.rtm_addrs & RTA_NETMASK)
		ADDADDR(&rt->net);

	if (rtm.hdr.rtm_addrs & RTA_IFP) {
		if_linkaddr(&su.sdl, rt->iface);
		ADDSU;
	}

	if (rtm.hdr.rtm_addrs & RTA_IFA)
		ADDADDR(&state->addr);

#undef ADDADDR
#undef ADDSU

	rtm.hdr.rtm_msglen = (unsigned short)(bp - (char *)&rtm);

	retval = write(s, &rtm, rtm.hdr.rtm_msglen) == -1 ? -1 : 0;
	close(s);
	return retval;
}