blob: d30aab4f13f509c361136bf01f95c59b5762d5e2 [file] [log] [blame]
James Kuszmaul82f6c042021-01-17 11:30:16 -08001/**
2 * @file bsd/brt.c BSD routing table code
3 *
4 * Copyright (C) 2010 Creytiv.com
5 */
6#include <re_types.h>
7#include <re_fmt.h>
8#include <re_mem.h>
9#include <re_sa.h>
10#include <re_net.h>
11#include <sys/sysctl.h>
12#include <net/route.h>
13#include <net/if.h>
14
15
16/*
17 * See https://github.com/boundary/libdnet/blob/master/src/route-bsd.c
18 */
19
20#ifdef __APPLE__
21#define RT_MSGHDR_ALIGNMENT sizeof(uint32_t)
22#else
23#define RT_MSGHDR_ALIGNMENT sizeof(unsigned long)
24#endif
25
26#define ROUNDUP(a) \
27 ((a) > 0 \
28 ? (1 + (((size_t)(a) - 1) | (RT_MSGHDR_ALIGNMENT - 1))) \
29 : RT_MSGHDR_ALIGNMENT)
30
31
32int net_rt_list(net_rt_h *rth, void *arg)
33{
34 /* net.route.0.inet.flags.gateway */
35 int mib[] = {CTL_NET, PF_ROUTE, 0, AF_UNSPEC,
36 NET_RT_FLAGS, RTF_GATEWAY};
37 char ifname[IFNAMSIZ], *buf, *p;
38 struct rt_msghdr *rt;
39 struct sockaddr *sa, *sa_tab[RTAX_MAX];
40 struct sa dst, gw;
41 size_t l;
42 int i, err = 0;
43
44 if (sysctl(mib, sizeof(mib)/sizeof(int), 0, &l, 0, 0) < 0)
45 return errno;
46 if (!l)
47 return ENOENT;
48
49 buf = mem_alloc(l, NULL);
50 if (!buf)
51 return ENOMEM;
52
53 if (sysctl(mib, sizeof(mib)/sizeof(int), buf, &l, 0, 0) < 0) {
54 err = errno;
55 goto out;
56 }
57
58 for (p = buf; p<buf+l; p += rt->rtm_msglen) {
59 rt = (void *)p; /* buffer is aligned */
60 sa = (struct sockaddr *)(rt + 1);
61
62 if (rt->rtm_type != RTM_GET)
63 continue;
64
65 if (!(rt->rtm_flags & RTF_UP))
66 continue;
67
68 for (i=0; i<RTAX_MAX; i++) {
69
70 if (rt->rtm_addrs & (1 << i)) {
71 sa_tab[i] = sa;
72 sa = (struct sockaddr *)
73 ((char *)sa + ROUNDUP(sa->sa_len));
74 }
75 else {
76 sa_tab[i] = NULL;
77 }
78 }
79
80 if ((rt->rtm_addrs & RTA_DST) == RTA_DST) {
81 err = sa_set_sa(&dst, sa_tab[RTAX_DST]);
82 if (err)
83 continue;
84 }
85 if ((rt->rtm_addrs & RTA_GATEWAY) == RTA_GATEWAY) {
86 err = sa_set_sa(&gw, sa_tab[RTAX_GATEWAY]);
87 if (err)
88 continue;
89 }
90
91 if_indextoname(rt->rtm_index, ifname);
92
93 if (rth(ifname, &dst, 0, &gw, arg))
94 break;
95 }
96
97 out:
98 mem_deref(buf);
99
100 return err;
101}