summaryrefslogtreecommitdiff
path: root/pfinet/pfinet-ops.c
diff options
context:
space:
mode:
authorDamien Zammit <damien@zamaudio.com>2022-09-09 09:42:48 +0000
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2022-09-11 19:10:14 +0200
commitb43d6d6f4617cf045ef1a5443568360df6cef328 (patch)
tree5a83d5debdcc9e665eab196675108cc3db3d183f /pfinet/pfinet-ops.c
parentda8d2ba4b61a7d6b25f5b2215447795f2b9badf9 (diff)
Add new RPC for pfinet network routes
Message-Id: <20220909094234.517165-1-damien@zamaudio.com>
Diffstat (limited to 'pfinet/pfinet-ops.c')
-rw-r--r--pfinet/pfinet-ops.c88
1 files changed, 87 insertions, 1 deletions
diff --git a/pfinet/pfinet-ops.c b/pfinet/pfinet-ops.c
index 5db66978..9722e0e3 100644
--- a/pfinet/pfinet-ops.c
+++ b/pfinet/pfinet-ops.c
@@ -22,6 +22,13 @@
#include <linux/netdevice.h>
#include <linux/notifier.h>
+#include <linux/inetdevice.h>
+#include <linux/rtnetlink.h>
+#include <linux/ip.h>
+#include <net/route.h>
+#include <net/sock.h>
+#include <net/ip_fib.h>
+#include <net/addrconf.h>
#include "pfinet_S.h"
#include <netinet/in.h>
@@ -32,7 +39,8 @@
#include <sys/mman.h>
#include <sys/ioctl.h>
-#include <net/if.h>
+
+#define MAX_ROUTES 255
extern int dev_ifconf(char *arg);
@@ -91,3 +99,81 @@ S_pfinet_siocgifconf (io_t port,
pthread_mutex_unlock (&global_lock);
return err;
}
+
+int
+get_routing_table(int start, int count, ifrtreq_t *routes)
+{
+ struct fib_table *tb;
+
+ if (!routes)
+ return 0;
+
+ if ((tb = fib_get_table(RT_TABLE_MAIN)) == NULL)
+ return 0;
+
+ return fn_hash_get_routes(tb, routes, start, count);
+}
+
+
+/* Return the routing table as a series of ifrtreq_t structs
+ in routes, but don't return more then AMOUNT number of them.
+ If AMOUNT is -1, we get the full table. */
+error_t
+S_pfinet_getroutes (io_t port,
+ vm_size_t amount,
+ data_t *routes,
+ mach_msg_type_number_t *len,
+ boolean_t *dealloc_data)
+{
+ error_t err = 0;
+ ifrtreq_t rs[MAX_ROUTES];
+ int n;
+ ifrtreq_t *rtable;
+
+ pthread_mutex_lock (&global_lock);
+
+ if (dealloc_data)
+ *dealloc_data = FALSE;
+
+ if (amount == (vm_size_t) -1)
+ {
+ /* Get all of them, and return the number we got. */
+ n = get_routing_table (0, MAX_ROUTES, rs);
+ amount = n;
+ }
+ else
+ n = amount;
+
+ if (amount > 0)
+ {
+ /* Possibly allocate a new buffer. */
+ if (*len < amount * sizeof(ifrtreq_t))
+ {
+ rtable = (ifrtreq_t *) mmap (0, amount * sizeof(ifrtreq_t), PROT_READ|PROT_WRITE,
+ MAP_ANON, 0, 0);
+ if (dealloc_data)
+ *dealloc_data = TRUE;
+ }
+ else
+ rtable = (ifrtreq_t *)*routes;
+
+ n = get_routing_table (0, n, rtable);
+ if (amount > n)
+ memset(&rtable[n], 0, (amount - n) * sizeof(ifrtreq_t));
+ }
+
+ if (rtable == MAP_FAILED)
+ {
+ /* Should use errno here, but glue headers #undef errno */
+ err = ENOMEM;
+ *len = 0;
+ }
+ else
+ {
+ *len = n * sizeof(ifrtreq_t);
+ *routes = (char *)rtable;
+ }
+
+ pthread_mutex_unlock (&global_lock);
+ return err;
+}