Beispiel #1
0
int net_rt_list(net_rt_h *rth, void *arg)
{
	/* net.route.0.inet.flags.gateway */
	int mib[] = {CTL_NET, PF_ROUTE, 0, AF_UNSPEC,
	             NET_RT_FLAGS, RTF_GATEWAY};
	char ifname[IFNAMSIZ], *buf, *p;
	struct rt_msghdr *rt;
	struct sockaddr *sa, *sa_tab[RTAX_MAX];
	struct sa dst, gw;
	size_t l;
	int i, err = 0;

	if (sysctl(mib, sizeof(mib)/sizeof(int), 0, &l, 0, 0) < 0)
		return errno;
	if (!l)
		return ENOENT;

	buf = mem_alloc(l, NULL);
	if (!buf)
		return ENOMEM;

	if (sysctl(mib, sizeof(mib)/sizeof(int), buf, &l, 0, 0) < 0) {
		err = errno;
		goto out;
	}

	for (p = buf; p<buf+l; p += rt->rtm_msglen) {
		rt = (void *)p;  /* buffer is aligned */
		sa = (struct sockaddr *)(rt + 1);

		if (rt->rtm_type != RTM_GET)
			continue;

		if (!(rt->rtm_flags & RTF_UP))
			continue;

		for (i=0; i<RTAX_MAX; i++) {

			if (rt->rtm_addrs & (1 << i)) {
				sa_tab[i] = sa;
				sa = (struct sockaddr *)
					((char *)sa + ROUNDUP(sa->sa_len));
			}
			else {
				sa_tab[i] = NULL;
			}
		}

		if ((rt->rtm_addrs & RTA_DST) == RTA_DST) {
			err = sa_set_sa(&dst, sa_tab[RTAX_DST]);
			if (err)
				continue;
		}
		if ((rt->rtm_addrs & RTA_GATEWAY) == RTA_GATEWAY) {
			err = sa_set_sa(&gw, sa_tab[RTAX_GATEWAY]);
			if (err)
				continue;
		}

		if_indextoname(rt->rtm_index, ifname);

		if (rth(ifname, &dst, 0, &gw, arg))
			break;
	}

 out:
	mem_deref(buf);

	return err;
}
Beispiel #2
0
/**
 * List all entries in the routing table
 *
 * @param rth Route entry handler
 * @param arg Handler argument
 *
 * @return 0 if success, otherwise errorcode
 */
int net_rt_list(net_rt_h *rth, void *arg)
{
	union {
		uint8_t buf[BUFSIZE];
		struct nlmsghdr msg[1];
	} u;
	struct nlmsghdr *nlmsg;
	int sock, len, seq = 0, err = 0;

	if (!rth)
		return EINVAL;

	/* Create Socket */
	if ((sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) < 0) {
		DEBUG_WARNING("list: socket(): (%s)\n", strerror(errno));
		return errno;
	}

	/* Initialize the buffer */
	memset(u.buf, 0, sizeof(u.buf));

	/* point the header and the msg structure pointers into the buffer */
	nlmsg = u.msg;

	/* Fill in the nlmsg header*/
	nlmsg->nlmsg_len   = NLMSG_LENGTH(sizeof(struct rtmsg));
	nlmsg->nlmsg_type  = RTM_GETROUTE;
	nlmsg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST;
	nlmsg->nlmsg_seq   = seq++;
	nlmsg->nlmsg_pid   = getpid();

	/* Send the request */
	if (send(sock, nlmsg, nlmsg->nlmsg_len, 0) < 0) {
		err = errno;
		DEBUG_WARNING("list: write to socket failed (%s)\n",
			      strerror(err));
		goto out;
	}

	/* Read the response */
	if ((len = read_sock(sock, u.buf, sizeof(u.buf), seq, getpid())) < 0) {
		err = errno;
		DEBUG_WARNING("list: read from socket failed (%s)\n",
			      strerror(err));
		goto out;
	}

	/* Parse and print the response */
	for (;NLMSG_OK(nlmsg,(uint32_t)len);nlmsg = NLMSG_NEXT(nlmsg,len)) {
		struct net_rt rt;

		memset(&rt, 0, sizeof(struct net_rt));
		if (0 != rt_parse(nlmsg, &rt))
			continue;

#ifdef HAVE_INET6
		if (AF_INET6 == sa_af(&rt.dst)
		    && IN6_IS_ADDR_UNSPECIFIED(&rt.dst.u.in6.sin6_addr))
			continue;
#endif

		if (rth(rt.ifname, &rt.dst, rt.dstlen, &rt.gw, arg))
			break;
	}

 out:
	(void)close(sock);

	return err;
}