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: Damien Zammit
Subject: Re: [PATCH v3] pfinet: Add SIOCADDRT and SIOCDELRT equivalent iioctls
Date: Tue, 20 Sep 2022 08:15:35 +0000

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.
>




reply via email to

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