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;
+}