Damien Zammit, le mar. 20 sept. 2022 08:15:35 +0000, a ecrit: > Did you fix <net/route.h> in glibc as well, > with something like what was in my commit message?
That's now done, yes. Samuel > I wasn't sure if the whole file should just be replaced, > as it currently has a lot of unused stuff so I couldn't > write an actual patch. > > Damien > > On 30/8/22 7:15 am, Samuel Thibault wrote: > > Applied, thanks! > > > > Damien Zammit, le lun. 29 août 2022 10:30:04 +0000, a ecrit: > >> Using a new client side <net/route.h> > >> I was able to clean up the existing options.c in pfinet > >> and add two new ioctls for adding/deleting network routes. > >> > >> #ifndef NET_ROUTE_H_ > >> #define NET_ROUTE_H_ > >> > >> #include <sys/socket.h> > >> #include <netinet/in.h> > >> #include <arpa/inet.h> > >> > >> #define _IOT_ifrtreq _IOT (_IOTS(char), IFNAMSIZ, _IOTS(int), 10, 0, 0) > >> > >> /* move to bits/ioctl.h */ > >> #define SIOCADDRT _IOW('i', 10, struct ifrtreq) > >> #define SIOCDELRT _IOW('i', 11, struct ifrtreq) > >> > >> 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; > >> }; > >> > >> #endif > >> > >> --- > >> hurd/iioctl.defs | 17 ++- > >> hurd/ioctl_types.h | 15 +++ > >> pfinet/iioctl-ops.c | 280 ++++++++++++++++++++++++++++++++++++++++++++ > >> pfinet/options.c | 122 ++++--------------- > >> 4 files changed, 332 insertions(+), 102 deletions(-) > >> > >> diff --git a/hurd/iioctl.defs b/hurd/iioctl.defs > >> index dfa89033f..6701d8ec7 100644 > >> --- a/hurd/iioctl.defs > >> +++ b/hurd/iioctl.defs > >> @@ -40,9 +40,24 @@ type ifname_t = array[16] of char; /* IFNAMSIZ is > >> 16. */ > >> definition of _IOT_ifreq in <net/if.h>. */ > >> type sockaddr_t = struct[16] of char; /* sizeof(struct sockaddr) is > >> 16. */ > >> > >> +/* This is the struct srtentry from <net/route.h>. */ > >> +type srtentry_t = struct[40] of char; /* sizeof(struct srtentry) is > >> 40. */ > >> + > >> skip; skip; skip; skip; /* 0 1 2 3 unused */ > >> skip; skip; skip; skip; /* 4 5 6 7 unused */ > >> -skip; skip; skip; skip; /* 8 9 10 11 unused */ > >> +skip; skip; /* 8 9 unused */ > >> + > >> +/* 10 SIOCADDRT */ > >> +routine iioctl_siocaddrt ( > >> + reqport: io_t; > >> + ifnam: ifname_t; > >> + route: srtentry_t); > >> + > >> +/* 11 SIOCDELRT */ > >> +routine iioctl_siocdelrt ( > >> + reqport: io_t; > >> + ifnam: ifname_t; > >> + route: srtentry_t); > >> > >> /* 12 SIOCSIFADDR */ > >> routine iioctl_siocsifaddr ( > >> diff --git a/hurd/ioctl_types.h b/hurd/ioctl_types.h > >> index 8baa36040..1e22fe597 100644 > >> --- a/hurd/ioctl_types.h > >> +++ b/hurd/ioctl_types.h > >> @@ -30,4 +30,19 @@ typedef struct winsize winsize_t; > >> typedef struct sockaddr sockaddr_t; > >> typedef char ifname_t[16]; > >> > >> +#include <stdint.h> > >> +struct srtentry { > >> + uint32_t rt_dest; > >> + uint32_t rt_mask; > >> + uint32_t rt_gateway; > >> + int rt_flags; > >> + int rt_metric; > >> + int rt_mtu; > >> + int rt_window; > >> + int rt_irtt; > >> + int rt_tos; > >> + int rt_class; > >> +}; > >> + > >> +typedef struct srtentry srtentry_t; > >> #endif /* hurd/ioctl_types.h */ > >> diff --git a/pfinet/iioctl-ops.c b/pfinet/iioctl-ops.c > >> index 191c65913..3185c8141 100644 > >> --- a/pfinet/iioctl-ops.c > >> +++ b/pfinet/iioctl-ops.c > >> @@ -22,9 +22,14 @@ > >> > >> #include <linux/netdevice.h> > >> #include <linux/notifier.h> > >> +#include <linux/inetdevice.h> > >> +#include <linux/ip.h> > >> +#include <linux/route.h> > >> +#include <linux/rtnetlink.h> > >> > >> #include "iioctl_S.h" > >> #include <netinet/in.h> > >> +#include <arpa/inet.h> > >> #include <fcntl.h> > >> #include <string.h> > >> #include <unistd.h> > >> @@ -32,9 +37,14 @@ > >> #include <sys/mman.h> > >> #include <hurd/fshelp.h> > >> > >> +#include <sys/socket.h> > >> #include <sys/ioctl.h> > >> #include <net/if.h> > >> #include <net/sock.h> > >> +#include <hurd/ioctl_types.h> > >> +#include <net/route.h> > >> +#include <net/ip_fib.h> > >> +#include <net/addrconf.h> > >> > >> extern struct notifier_block *netdev_chain; > >> > >> @@ -64,6 +74,226 @@ struct device *get_dev (const char *name) > >> return dev; > >> } > >> > >> +static uint32_t > >> +get_gateway(struct device *dev) > >> +{ > >> + uint32_t gateway = 0; > >> + struct rt_key key = { 0 }; > >> + struct fib_result res; > >> + > >> + /* Get gateway */ > >> + gateway = INADDR_NONE; > >> + key.oif = dev->ifindex; > >> + if (! main_table->tb_lookup (main_table, &key, &res) > >> + && FIB_RES_GW(res) != INADDR_ANY) > >> + gateway = FIB_RES_GW (res); > >> + return gateway; > >> +} > >> + > >> +/* This code is cobbled together from what > >> + * the SIOCADDRT ioctl code does, and from the apparent functionality > >> + * of the "netlink" layer from perusing a little. > >> + */ > >> +static error_t > >> +delete_gateway(struct device *dev, in_addr_t dst, in_addr_t mask, > >> in_addr_t gw) > >> +{ > >> + error_t err; > >> + struct kern_rta rta; > >> + struct > >> + { > >> + struct nlmsghdr nlh; > >> + struct rtmsg rtm; > >> + } req; > >> + struct fib_table *tb; > >> + > >> + if (bad_mask (mask, dst)) > >> + return EINVAL; > >> + > >> + req.nlh.nlmsg_pid = 0; > >> + req.nlh.nlmsg_seq = 0; > >> + req.nlh.nlmsg_len = NLMSG_LENGTH (sizeof req.rtm); > >> + > >> + memset (&req.rtm, 0, sizeof req.rtm); > >> + memset (&rta, 0, sizeof rta); > >> + req.rtm.rtm_scope = RT_SCOPE_UNIVERSE; > >> + req.rtm.rtm_type = RTN_UNICAST; > >> + req.rtm.rtm_protocol = RTPROT_BOOT; > >> + req.rtm.rtm_dst_len = inet_mask_len(mask); > >> + > >> + /* Delete any existing default route on configured device */ > >> + req.nlh.nlmsg_type = RTM_DELROUTE; > >> + req.nlh.nlmsg_flags = 0; > >> + rta.rta_oif = &dev->ifindex; > >> + rta.rta_dst = &dst; > >> + rta.rta_gw = &gw; > >> + tb = fib_get_table (req.rtm.rtm_table); > >> + if (tb) > >> + { > >> + err = - (*tb->tb_delete) > >> + (tb, &req.rtm, &rta, &req.nlh, 0); > >> + if (err && err != ESRCH) > >> + return err; > >> + err = 0; > >> + } > >> + return err; > >> +} > >> + > >> +static error_t > >> +add_gateway(struct device *dev, in_addr_t dst, in_addr_t mask, in_addr_t > >> gw) > >> +{ > >> + error_t err; > >> + struct kern_rta rta; > >> + struct > >> + { > >> + struct nlmsghdr nlh; > >> + struct rtmsg rtm; > >> + } req = {0}; > >> + struct fib_table *tb; > >> + > >> + if (bad_mask (mask, dst)) > >> + return EINVAL; > >> + > >> + req.nlh.nlmsg_pid = 0; > >> + req.nlh.nlmsg_seq = 0; > >> + req.nlh.nlmsg_len = NLMSG_LENGTH (sizeof req.rtm); > >> + > >> + memset (&req.rtm, 0, sizeof req.rtm); > >> + memset (&rta, 0, sizeof rta); > >> + req.rtm.rtm_scope = RT_SCOPE_UNIVERSE; > >> + req.rtm.rtm_type = RTN_UNICAST; > >> + req.rtm.rtm_protocol = RTPROT_BOOT; > >> + req.rtm.rtm_dst_len = inet_mask_len(mask); > >> + > >> + /* Add a gateway */ > >> + rta.rta_oif = &dev->ifindex; > >> + rta.rta_dst = &dst; > >> + rta.rta_gw = &gw; > >> + req.nlh.nlmsg_type = RTM_NEWROUTE; > >> + req.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE; > >> + tb = fib_new_table (req.rtm.rtm_table); > >> + err = (!tb ? ENOBUFS > >> + : - (*tb->tb_insert) (tb, &req.rtm, &rta, &req.nlh, 0)); > >> + return err; > >> +} > >> + > >> +/* Setup a static route (required for e.g. DHCP) */ > >> +static error_t > >> +add_static_route(struct device *dev, in_addr_t dst, in_addr_t mask) > >> +{ > >> + error_t err; > >> + struct kern_rta rta; > >> + struct > >> + { > >> + struct nlmsghdr nlh; > >> + struct rtmsg rtm; > >> + } req; > >> + struct fib_table *tb; > >> + > >> + if (bad_mask (mask, dst)) > >> + return EINVAL; > >> + > >> + if (!dev->name) > >> + return ENODEV; > >> + > >> + /* Simulate the SIOCADDRT behavior. */ > >> + memset (&req.rtm, 0, sizeof req.rtm); > >> + memset (&rta, 0, sizeof rta); > >> + > >> + /* Append this routing for addr. By this way we can always send > >> + dhcp messages (e.g dhcp renew). */ > >> + req.nlh.nlmsg_type = RTM_NEWROUTE; > >> + req.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_APPEND; > >> + req.rtm.rtm_protocol = RTPROT_BOOT; > >> + req.rtm.rtm_scope = RT_SCOPE_LINK; > >> + req.rtm.rtm_type = RTN_UNICAST; > >> + req.rtm.rtm_dst_len = inet_mask_len(mask); > >> + rta.rta_dst = &dst; > >> + rta.rta_oif = &dev->ifindex; > >> + > >> + tb = fib_new_table (req.rtm.rtm_table); > >> + if (tb) > >> + err = tb->tb_insert (tb, &req.rtm, &rta, &req.nlh, NULL); > >> + else > >> + err = ENOBUFS; > >> + return err; > >> +} > >> + > >> +static error_t > >> +delete_static_route(struct device *dev, in_addr_t dst, in_addr_t mask) > >> +{ > >> + error_t err; > >> + struct kern_rta rta; > >> + struct > >> + { > >> + struct nlmsghdr nlh; > >> + struct rtmsg rtm; > >> + } req; > >> + struct fib_table *tb; > >> + > >> + if (bad_mask (mask, dst)) > >> + return EINVAL; > >> + > >> + req.nlh.nlmsg_pid = 0; > >> + req.nlh.nlmsg_seq = 0; > >> + req.nlh.nlmsg_len = NLMSG_LENGTH (sizeof req.rtm); > >> + > >> + memset (&req.rtm, 0, sizeof req.rtm); > >> + memset (&rta, 0, sizeof rta); > >> + > >> + /* Delete existing static route on configured device matching src/dst */ > >> + req.nlh.nlmsg_type = RTM_DELROUTE; > >> + req.nlh.nlmsg_flags = 0; > >> + > >> + req.rtm.rtm_protocol = RTPROT_BOOT; > >> + req.rtm.rtm_scope = RT_SCOPE_LINK; > >> + req.rtm.rtm_type = RTN_UNICAST; > >> + req.rtm.rtm_dst_len = inet_mask_len(mask); > >> + rta.rta_dst = &dst; > >> + rta.rta_oif = &dev->ifindex; > >> + tb = fib_get_table (req.rtm.rtm_table); > >> + if (tb) > >> + { > >> + err = - (*tb->tb_delete) > >> + (tb, &req.rtm, &rta, &req.nlh, 0); > >> + if (err && err != ESRCH) > >> + return err; > >> + err = 0; > >> + } > >> + return err; > >> +} > >> + > >> +error_t > >> +add_route (struct device *dev, const struct srtentry *r) > >> +{ > >> + error_t err; > >> + > >> + if (!r) > >> + return EINVAL; > >> + > >> + if (r->rt_flags & RTF_GATEWAY) > >> + err = add_gateway(dev, r->rt_dest, r->rt_mask, r->rt_gateway); > >> + else > >> + err = add_static_route(dev, r->rt_dest, r->rt_mask); > >> + > >> + return err; > >> +} > >> + > >> +error_t > >> +delete_route (struct device *dev, const struct srtentry *r) > >> +{ > >> + error_t err; > >> + > >> + if (!r) > >> + return EINVAL; > >> + > >> + if (r->rt_flags & RTF_GATEWAY) > >> + err = delete_gateway(dev, r->rt_dest, r->rt_mask, r->rt_gateway); > >> + else > >> + err = delete_static_route(dev, r->rt_dest, r->rt_mask); > >> + > >> + return err; > >> +} > >> + > >> enum siocgif_type > >> { > >> ADDR, > >> @@ -158,6 +388,56 @@ siocsifXaddr (struct sock_user *user, > >> return err; > >> } > >> > >> +/* 10 SIOCADDRT -- Add a network route */ > >> +kern_return_t > >> +S_iioctl_siocaddrt (struct sock_user *user, > >> + const ifname_t ifnam, > >> + const struct srtentry route) > >> +{ > >> + error_t err = 0; > >> + struct device *dev; > >> + > >> + if (!user) > >> + return EOPNOTSUPP; > >> + > >> + dev = get_dev (ifnam); > >> + > >> + if (!dev) > >> + err = ENODEV; > >> + else if (user->sock->sk->family != AF_INET) > >> + err = EINVAL; > >> + else > >> + err = add_route (dev, &route); > >> + > >> + pthread_mutex_unlock (&global_lock); > >> + return err; > >> +} > >> + > >> +/* 11 SIOCDELRT -- Delete a network route */ > >> +kern_return_t > >> +S_iioctl_siocdelrt (struct sock_user *user, > >> + const ifname_t ifnam, > >> + const struct srtentry route) > >> +{ > >> + error_t err = 0; > >> + struct device *dev; > >> + > >> + if (!user) > >> + return EOPNOTSUPP; > >> + > >> + dev = get_dev (ifnam); > >> + > >> + if (!dev) > >> + err = ENODEV; > >> + else if (user->sock->sk->family != AF_INET) > >> + err = EINVAL; > >> + else > >> + err = delete_route (dev, &route); > >> + > >> + pthread_mutex_unlock (&global_lock); > >> + return err; > >> +} > >> + > >> /* 12 SIOCSIFADDR -- Set address of a network interface. */ > >> SIOCSIF (addr, ADDR); > >> > >> diff --git a/pfinet/options.c b/pfinet/options.c > >> index ae44759dc..b945257be 100644 > >> --- a/pfinet/options.c > >> +++ b/pfinet/options.c > >> @@ -28,6 +28,7 @@ > >> #include <error.h> > >> #include <netinet/in.h> > >> #include <arpa/inet.h> > >> +#include <hurd/ioctl_types.h> > >> > >> #include "pfinet.h" > >> > >> @@ -60,6 +61,10 @@ extern struct inet6_dev *ipv6_find_idev (struct device > >> *dev); > >> extern int inet6_addr_add (int ifindex, struct in6_addr *pfx, int plen); > >> extern int inet6_addr_del (int ifindex, struct in6_addr *pfx, int plen); > >> > >> +/* iioctl.c */ > >> +extern error_t add_route (struct device *dev, struct srtentry *r); > >> +extern error_t delete_route (struct device *dev, struct srtentry *r); > >> + > >> #ifdef CONFIG_IPV6 > >> static struct rt6_info * ipv6_get_dflt_router (void); > >> #endif > >> @@ -504,65 +509,22 @@ parse_opt (int opt, char *arg, struct argp_state > >> *state) > >> #endif /* CONFIG_IPV6 */ > >> } > >> > >> - /* Set the default gateway. This code is cobbled together from what > >> - the SIOCADDRT ioctl code does, and from the apparent functionality > >> - of the "netlink" layer from perusing a little. */ > >> + /* Set the default gateway. */ > >> + > >> { > >> - struct kern_rta rta; > >> - struct > >> - { > >> - struct nlmsghdr nlh; > >> - struct rtmsg rtm; > >> - } req; > >> - struct fib_table *tb; > >> - > >> - req.nlh.nlmsg_pid = 0; > >> - req.nlh.nlmsg_seq = 0; > >> - req.nlh.nlmsg_len = NLMSG_LENGTH (sizeof req.rtm); > >> - > >> - memset (&req.rtm, 0, sizeof req.rtm); > >> - memset (&rta, 0, sizeof rta); > >> - req.rtm.rtm_scope = RT_SCOPE_UNIVERSE; > >> - req.rtm.rtm_type = RTN_UNICAST; > >> - req.rtm.rtm_protocol = RTPROT_STATIC; > >> - > >> - if (!gw4_in) > >> - { > >> - /* Delete any existing default route on configured devices */ > >> - for (in = h->interfaces; in < h->interfaces + h->num_interfaces; > >> - in++) > >> - { > >> - req.nlh.nlmsg_type = RTM_DELROUTE; > >> - req.nlh.nlmsg_flags = 0; > >> - rta.rta_oif = &in->device->ifindex; > >> - tb = fib_get_table (req.rtm.rtm_table); > >> - if (tb) > >> - { > >> - err = - (*tb->tb_delete) > >> - (tb, &req.rtm, &rta, &req.nlh, 0); > >> - if (err && err != ESRCH) > >> - { > >> - pthread_mutex_unlock (&global_lock); > >> - FAIL (err, 17, 0, > >> - "cannot remove old default gateway"); > >> - } > >> - err = 0; > >> - } > >> - } > >> - } > >> - else > >> + struct srtentry route = {0}; > >> + route.rt_flags = RTF_GATEWAY; > >> + route.rt_mask = INADDR_ANY; > >> + route.rt_dest = INADDR_ANY; > >> + route.rt_gateway = h->curint->gateway; > >> + > >> + if (gw4_in) > >> { > >> - /* Add a default route, replacing any existing one. */ > >> - rta.rta_oif = &gw4_in->device->ifindex; > >> - rta.rta_gw = &gw4_in->gateway; > >> - req.nlh.nlmsg_type = RTM_NEWROUTE; > >> - req.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE; > >> - tb = fib_new_table (req.rtm.rtm_table); > >> - err = (!tb ? ENOBUFS > >> - : - (*tb->tb_insert) (tb, &req.rtm, &rta, &req.nlh, 0)); > >> + /* Add a default route */ > >> + err = add_route (gw4_in->device, &route); > >> if (err) > >> { > >> - pthread_mutex_unlock (&global_lock); > >> + pthread_mutex_unlock (&global_lock); > >> FAIL (err, 17, 0, "cannot set default gateway"); > >> } > >> } > >> @@ -592,55 +554,13 @@ parse_opt (int opt, char *arg, struct argp_state > >> *state) > >> /* Setup the routing required for DHCP. */ > >> for (in = h->interfaces; in < h->interfaces + h->num_interfaces; > >> in++) > >> { > >> - struct kern_rta rta; > >> - struct > >> - { > >> - struct nlmsghdr nlh; > >> - struct rtmsg rtm; > >> - } req; > >> - struct fib_table *tb; > >> - struct rtentry route; > >> - struct sockaddr_in *dst; > >> - struct device *dev; > >> - > >> if (!in->device) > >> continue; > >> + struct srtentry route = {0}; > >> + route.rt_flags = 0; > >> + route.rt_dest = INADDR_ANY; > >> > >> - dst = (struct sockaddr_in *) &route.rt_dst; > >> - if (!in->device->name) > >> - { > >> - pthread_mutex_unlock (&global_lock); > >> - FAIL (ENODEV, 17, 0, "unknown device"); > >> - } > >> - dev = dev_get (in->device->name); > >> - if (!dev) > >> - { > >> - pthread_mutex_unlock (&global_lock); > >> - FAIL (ENODEV, 17, 0, "unknown device"); > >> - } > >> - > >> - /* Simulate the SIOCADDRT behavior. */ > >> - memset (&route, 0, sizeof (struct rtentry)); > >> - memset (&req.rtm, 0, sizeof req.rtm); > >> - memset (&rta, 0, sizeof rta); > >> - req.nlh.nlmsg_type = RTM_NEWROUTE; > >> - > >> - /* Append this routing for 0.0.0.0. By this way we can send always > >> - dhcp messages (e.g dhcp renew). */ > >> - req.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE > >> - | NLM_F_APPEND; > >> - req.rtm.rtm_protocol = RTPROT_BOOT; > >> - req.rtm.rtm_scope = RT_SCOPE_LINK; > >> - req.rtm.rtm_type = RTN_UNICAST; > >> - rta.rta_dst = &dst->sin_addr.s_addr; > >> - rta.rta_oif = &dev->ifindex; > >> - > >> - tb = fib_new_table (req.rtm.rtm_table); > >> - if (tb) > >> - err = tb->tb_insert (tb, &req.rtm, &rta, &req.nlh, NULL); > >> - else > >> - err = ENOBUFS; > >> - > >> + err = add_route (in->device, &route); > >> if (err) > >> { > >> pthread_mutex_unlock (&global_lock); > >> -- > >> 2.34.1 > >> > >> > >> > > > > -- > > Samuel > > --- > > Pour une évaluation indépendante, transparente et rigoureuse ! > > Je soutiens la Commission d'Évaluation de l'Inria. > > > > -- Samuel --- Pour une évaluation indépendante, transparente et rigoureuse ! Je soutiens la Commission d'Évaluation de l'Inria.