From: Joan Lledó <[email protected]>
---
lwip/pfinet-ops.c | 83 +++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 81 insertions(+), 2 deletions(-)
diff --git a/lwip/pfinet-ops.c b/lwip/pfinet-ops.c
index c30efccc..271f2ac5 100644
--- a/lwip/pfinet-ops.c
+++ b/lwip/pfinet-ops.c
@@ -29,6 +29,7 @@
#include <lwip/sockets.h>
#include <lwip/inet.h>
#include <sys/mman.h>
+#include <net/route.h>
#include <lwip-util.h>
#include <netif/hurdethif.h>
@@ -114,12 +115,90 @@ lwip_S_pfinet_siocgifconf (io_t port,
return 0;
}
+/* pfinet_getroutes must return up to 255 routes */
+#define MAX_ROUTES 255
+
kern_return_t
lwip_S_pfinet_getroutes (io_t port,
- vm_size_t amount,
+ vm_size_t requested_amount,
data_t *routes,
mach_msg_type_number_t *len,
boolean_t *dealloc_data)
{
- return EOPNOTSUPP;
+ struct netif *netif;
+ uint32_t addr, netmask, gw, available_count, count_to_return;
+ uint8_t i;
+ ifrtreq_t *rtable;
+ char *devname;
+
+ if (dealloc_data)
+ *dealloc_data = FALSE;
+
+ available_count = 0;
+ NETIF_FOREACH (netif)
+ {
+ available_count++;
+ }
+
+ if (requested_amount == (vm_size_t) - 1)
+ {
+ /* All available */
+ count_to_return = available_count;
+ }
+ else
+ /* Minimum of requested and available */
+ count_to_return =
+ requested_amount > available_count ? available_count : requested_amount;
+
+ if (count_to_return > MAX_ROUTES)
+ count_to_return = MAX_ROUTES;
+
+ /* If the user requested 0 or there are 0 available, do nothing */
+ if (count_to_return > 0)
+ {
+ /* Possibly allocate a new buffer. */
+ if (*len < count_to_return * sizeof (ifrtreq_t))
+ {
+ rtable =
+ (ifrtreq_t *) mmap (0, count_to_return * sizeof (ifrtreq_t),
+ PROT_READ | PROT_WRITE, MAP_ANON, 0, 0);
+ if (dealloc_data)
+ *dealloc_data = TRUE;
+ }
+ else
+ rtable = (ifrtreq_t *) * routes;
+
+ if (rtable == MAP_FAILED)
+ {
+ *len = 0;
+ return ENOMEM;
+ }
+
+ /* Clear the output buffer */
+ memset (rtable, 0, count_to_return * sizeof (ifrtreq_t));
+
+ /* Get the routes */
+ i = 0;
+ NETIF_FOREACH (netif)
+ {
+ if (i == count_to_return)
+ break;
+
+ devname = netif_get_state (netif)->devname;
+ inquire_device (netif, &addr, &netmask, 0, 0, &gw, 0, 0);
+ strncpy (rtable[i].ifname, devname, IF_NAMESIZE);
+ rtable[i].ifname[IF_NAMESIZE-1] = '\0';
+ rtable[i].rt_dest = addr & netmask;
+ rtable[i].rt_mask = netmask;
+ rtable[i].rt_gateway = gw;
+
+ i++;
+ }
+
+ *routes = (char *) rtable;
+ }
+
+ *len = count_to_return * sizeof (ifrtreq_t);
+
+ return 0;
}
--
2.50.1