diff options
Diffstat (limited to 'pfinet/pfinet-ops.c')
-rw-r--r-- | pfinet/pfinet-ops.c | 88 |
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; +} |