Squashed 'third_party/rawrtc/re/' content from commit f3163ce8b

Change-Id: I6a235e6ac0f03269d951026f9d195da05c40fdab
git-subtree-dir: third_party/rawrtc/re
git-subtree-split: f3163ce8b526a13b35ef71ce4dd6f43585064d8a
diff --git a/src/net/bsd/brt.c b/src/net/bsd/brt.c
new file mode 100644
index 0000000..d30aab4
--- /dev/null
+++ b/src/net/bsd/brt.c
@@ -0,0 +1,101 @@
+/**
+ * @file bsd/brt.c  BSD routing table code
+ *
+ * Copyright (C) 2010 Creytiv.com
+ */
+#include <re_types.h>
+#include <re_fmt.h>
+#include <re_mem.h>
+#include <re_sa.h>
+#include <re_net.h>
+#include <sys/sysctl.h>
+#include <net/route.h>
+#include <net/if.h>
+
+
+/*
+ * See https://github.com/boundary/libdnet/blob/master/src/route-bsd.c
+ */
+
+#ifdef __APPLE__
+#define RT_MSGHDR_ALIGNMENT sizeof(uint32_t)
+#else
+#define RT_MSGHDR_ALIGNMENT sizeof(unsigned long)
+#endif
+
+#define ROUNDUP(a) \
+	((a) > 0						\
+	 ? (1 + (((size_t)(a) - 1) | (RT_MSGHDR_ALIGNMENT - 1))) \
+	 : RT_MSGHDR_ALIGNMENT)
+
+
+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;
+}