--- hurd/pfinet.defs | 10 ++++++++ pfinet/pfinet-ops.c | 56 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+)
diff --git a/hurd/pfinet.defs b/hurd/pfinet.defs index ec0b03e34..a6000142e 100644 --- a/hurd/pfinet.defs +++ b/hurd/pfinet.defs @@ -37,3 +37,13 @@ routine pfinet_siocgifconf ( amount: vm_size_t; out buf: data_t, dealloc ); + +/* Return the routing table as a char buffer. + The maximum number of bytes returned can be given in AMOUNT, + which will be truncated to the nearest row of the table. + But if AMOUNT is -1, all routes will be returned up to MAX_ROUTES. */ +routine pfinet_getroutes ( + port: io_t; + amount: vm_size_t; + out buf: data_t, dealloc +); diff --git a/pfinet/pfinet-ops.c b/pfinet/pfinet-ops.c index 5db669783..cf4050cf7 100644 --- a/pfinet/pfinet-ops.c +++ b/pfinet/pfinet-ops.c @@ -20,6 +20,7 @@ #include "pfinet.h" +#define _HACK_ERRNO_H #include <linux/netdevice.h> #include <linux/notifier.h> @@ -28,12 +29,15 @@ #include <fcntl.h> #include <string.h> #include <unistd.h> +#include <errno.h> #include <mach/notify.h> #include <sys/mman.h> #include <sys/ioctl.h> #include <net/if.h> +#define MAX_ROUTES 255 + extern int dev_ifconf(char *arg); /* Return the list of devices in the format provided by SIOCGIFCONF @@ -91,3 +95,55 @@ S_pfinet_siocgifconf (io_t port, pthread_mutex_unlock (&global_lock); return err; } + +/* Return the routing table as a char buffer + in routes, but don't return more then AMOUNT bytes. + If AMOUNT is -1, we get the needed length. */ +error_t +S_pfinet_getroutes (io_t port, + vm_size_t amount, + data_t *routes, + mach_msg_type_number_t *len) +{ + error_t err = 0; + char rs[(MAX_ROUTES + 1) * 128]; + int n; + char *buf; + + pthread_mutex_lock (&global_lock); + if (amount == (vm_size_t) -1) + { + /* Get the needed buffer length. */ + n = get_routing_table (rs, 0, MAX_ROUTES); + amount = (n + 1) * 128; + } + else + n = amount / 128; + + if (amount > 0) + { + /* Possibly allocate a new buffer. */ + if (*len < amount) + buf = (char *) mmap (0, amount, PROT_READ|PROT_WRITE, + MAP_ANON, 0, 0); + else + buf = *routes; + n = get_routing_table (buf, 0, n); + } + + if (buf == MAP_FAILED) + { + err = errno; + *len = 0; + if (buf != *routes) + munmap (buf, amount); + } + else + { + *len = (n + 1) * 128; + *routes = buf; + } + + pthread_mutex_unlock (&global_lock); + return err; +} -- 2.34.1