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


Reply via email to