[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: |
Wed, 21 Sep 2022 23:21:48 +0200 |
User-agent: |
NeoMutt/20170609 (1.8.3) |
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.