Applied, thanks! Damien Zammit, le ven. 09 sept. 2022 09:42:48 +0000, a ecrit: > --- > hurd/pfinet.defs | 9 +++ > pfinet/iioctl-ops.c | 1 + > pfinet/linux-src/include/net/ip_fib.h | 2 + > pfinet/linux-src/net/ipv4/fib_hash.c | 80 ++++++++++++++++++++++++ > pfinet/pfinet-ops.c | 88 ++++++++++++++++++++++++++- > pfinet/pfinet.h | 5 +- > pfinet/route.h | 42 +++++++++++++ > 7 files changed, 223 insertions(+), 4 deletions(-) > create mode 100644 pfinet/route.h > > diff --git a/hurd/pfinet.defs b/hurd/pfinet.defs > index ec0b03e3..81f7c194 100644 > --- a/hurd/pfinet.defs > +++ b/hurd/pfinet.defs > @@ -37,3 +37,12 @@ routine pfinet_siocgifconf ( > amount: vm_size_t; > out buf: data_t, dealloc > ); > + > +/* Return the routing table as a sequence of ifrtreq_t structs. > + The maximum number of routes returned can be given in AMOUNT. > + 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 routes: data_t, dealloc[] > +); > diff --git a/pfinet/iioctl-ops.c b/pfinet/iioctl-ops.c > index b128242b..adf7bd82 100644 > --- a/pfinet/iioctl-ops.c > +++ b/pfinet/iioctl-ops.c > @@ -104,6 +104,7 @@ prepare_rt_req(struct rt_req *req, struct device *dev, > in_addr_t dst, in_addr_t > req->rtm.rtm_type = RTN_UNICAST; > req->rtm.rtm_protocol = RTPROT_BOOT; > req->rtm.rtm_dst_len = inet_mask_len(mask); > + req->rtm.rtm_table = RT_TABLE_MAIN; > > return 0; > } > diff --git a/pfinet/linux-src/include/net/ip_fib.h > b/pfinet/linux-src/include/net/ip_fib.h > index 60338945..faf13c64 100644 > --- a/pfinet/linux-src/include/net/ip_fib.h > +++ b/pfinet/linux-src/include/net/ip_fib.h > @@ -17,6 +17,7 @@ > #define _NET_IP_FIB_H > > #include <linux/config.h> > +#include "route.h" > > struct kern_rta > { > @@ -223,6 +224,7 @@ extern u32 __fib_res_prefsrc(struct fib_result *res); > > /* Exported by fib_hash.c */ > extern struct fib_table *fib_hash_init(int id); > +int fn_hash_get_routes(struct fib_table *tb, ifrtreq_t *routes, int first, > int count); > > #ifdef CONFIG_IP_MULTIPLE_TABLES > /* Exported by fib_rules.c */ > diff --git a/pfinet/linux-src/net/ipv4/fib_hash.c > b/pfinet/linux-src/net/ipv4/fib_hash.c > index 074a3687..495f1682 100644 > --- a/pfinet/linux-src/net/ipv4/fib_hash.c > +++ b/pfinet/linux-src/net/ipv4/fib_hash.c > @@ -883,3 +883,83 @@ __initfunc(struct fib_table * fib_hash_init(int id)) > memset(tb->tb_data, 0, sizeof(struct fn_hash)); > return tb; > } > + > +static void > +fib_node_get_route(int type, int dead, struct fib_info *fi, u32 prefix, u32 > mask, ifrtreq_t *r) > +{ > + int len; > + static unsigned type2flags[RTN_MAX+1] = { > + [RTN_UNREACHABLE] = RTF_REJECT, > + [RTN_PROHIBIT] = RTF_REJECT > + }; > + unsigned flags; > + > + flags = type2flags[type]; > + > + if (fi && fi->fib_nh->nh_gw) > + flags |= RTF_GATEWAY; > + if (mask == 0xFFFFFFFF) > + flags |= RTF_HOST; > + if (!dead) > + flags |= RTF_UP; > + > + > + if (fi && fi->fib_dev) { > + snprintf (r->ifname, IFNAMSIZ, "%s", fi->fib_dev->name); > + } else { > + r->ifname[0] = '*'; > + r->ifname[1] = '\0'; > + } > + > + r->rt_dest = prefix; > + r->rt_flags = flags; > + r->rt_mask = mask; > + > + if (fi) { > + r->rt_gateway = fi->fib_nh->nh_gw; > + r->rt_metric = fi->fib_priority; > + r->rt_mtu = fi->fib_mtu; > + r->rt_window = fi->fib_window; > + r->rt_irtt = fi->fib_rtt; > + } > +} > + > +int > +fn_hash_get_routes(struct fib_table *tb, ifrtreq_t *routes, int first, int > count) > +{ > + struct fn_hash *table = (struct fn_hash*)tb->tb_data; > + struct fn_zone *fz; > + int pos = 0; > + int n = 0; > + > + for (fz=table->fn_zone_list; fz; fz = fz->fz_next) { > + int i; > + struct fib_node *f; > + int maxslot = fz->fz_divisor; > + struct fib_node **fp = fz->fz_hash; > + > + if (fz->fz_nent == 0) > + continue; > + > + if (pos + fz->fz_nent <= first) { > + pos += fz->fz_nent; > + continue; > + } > + > + for (i=0; i < maxslot; i++, fp++) { > + for (f = *fp; f; f = f->fn_next) { > + if (++pos <= first) > + continue; > + fib_node_get_route(f->fn_type, > + f->fn_state & FN_S_ZOMBIE, > + FIB_INFO(f), > + fz_prefix(f->fn_key, fz), > + FZ_MASK(fz), routes); > + routes++; > + if (++n >= count) > + return n; > + } > + } > + } > + return n; > +} > 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; > +} > diff --git a/pfinet/pfinet.h b/pfinet/pfinet.h > index d08779bf..f8a1dd8d 100644 > --- a/pfinet/pfinet.h > +++ b/pfinet/pfinet.h > @@ -29,6 +29,7 @@ > #include <sys/mman.h> > #include <sys/socket.h> > #include <pthread.h> > +#include "route.h" > > extern pthread_mutex_t global_lock; > extern pthread_mutex_t net_bh_lock; > @@ -77,9 +78,7 @@ error_t make_sockaddr_port (struct socket *, int, > void init_devices (void); > void *net_bh_worker (void *); > void init_time (void); > -void ip_rt_add (short, u_long, u_long, u_long, struct device *, > - u_short, u_long); > -void ip_rt_del (u_long, struct device *); > +int get_routing_table(int start, int count, ifrtreq_t *routes); > struct sock; > error_t tcp_tiocinq (struct sock *sk, mach_msg_type_number_t *amount); > > diff --git a/pfinet/route.h b/pfinet/route.h > new file mode 100644 > index 00000000..00beb6c1 > --- /dev/null > +++ b/pfinet/route.h > @@ -0,0 +1,42 @@ > +/* > + Copyright (C) 2022 Free Software Foundation, Inc. > + > + This file is part of the GNU Hurd. > + > + The GNU Hurd is free software; you can redistribute it and/or > + modify it under the terms of the GNU General Public License as > + published by the Free Software Foundation; either version 2, or (at > + your option) any later version. > + > + The GNU Hurd is distributed in the hope that it will be useful, but > + WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + General Public License for more details. > + > + You should have received a copy of the GNU General Public License > + along with this program; if not, write to the Free Software > + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ > + > +#ifndef ROUTE_H_ > +#define ROUTE_H_ > + > +#include <sys/socket.h> > +#include <netinet/in.h> > +#include <arpa/inet.h> > +#include <net/if.h> > + > +typedef struct ifrtreq { > + char ifname[IFNAMSIZ]; > + in_addr_t rt_dest; > + in_addr_t rt_mask; > + in_addr_t rt_gateway; > + int rt_flags; > + int rt_metric; > + int rt_mtu; > + int rt_window; > + int rt_irtt; > + int rt_tos; > + int rt_class; > +} ifrtreq_t; > + > +#endif > -- > 2.34.1 > > >
-- Samuel --- Pour une évaluation indépendante, transparente et rigoureuse ! Je soutiens la Commission d'Évaluation de l'Inria.