bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v3] pfinet: Add SIOCADDRT and SIOCDELRT equivalent iioctls


From: Samuel Thibault
Subject: Re: [PATCH v3] pfinet: Add SIOCADDRT and SIOCDELRT equivalent iioctls
Date: Mon, 29 Aug 2022 23:15:59 +0200
User-agent: NeoMutt/20170609 (1.8.3)

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.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]