Hi Samuel, Did you fix <net/route.h> in glibc as well, with something like what was in my commit message?
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. >