Applied, thanks! Joan Lledó, le sam. 11 oct. 2025 12:51:00 +0200, a ecrit: > From: Joan Lledó <[email protected]> > > The new methods try to map common network routing to limited lwip support for > routes. > > Only two scenarios ar supported: > * Add/delete subnet route > * Add/delete default route > --- > lwip/iioctl-ops.c | 188 ++++++++++++++++++++++++++++++++++++++++++++-- > 1 file changed, 182 insertions(+), 6 deletions(-) > > diff --git a/lwip/iioctl-ops.c b/lwip/iioctl-ops.c > index c7b6c332..a9e382ee 100644 > --- a/lwip/iioctl-ops.c > +++ b/lwip/iioctl-ops.c > @@ -30,7 +30,10 @@ > > #include <lwip-hurd.h> > #include <lwip-util.h> > +#include <lwip/tcpip.h> > #include <netif/ifcommon.h> > +#include <netinet/in.h> > +#include <hurd/ioctl_types.h> > > /* Get the interface from its name */ > static struct netif * > @@ -167,22 +170,195 @@ siocsifXaddr (struct sock_user *user, > return err; > } > > +static void > +set_default_if (void *arg) > +{ > + struct netif *netif; > + > + netif = (struct netif *) arg; > + > + netif_set_default (netif); > +} > + > /* 10 SIOCADDRT -- Add a network route */ > +/* > + * Lwip routing is very limited. Each netif has one gateway and all packets > from/to that netif go through there. > + * Considering this, we need to behave as clients expect. > + * > + * These are the supported scenarios: > + * - A client sending an interface plus a netmask but gateway=any: intends > to add a subnet route. > + * e.g. `192.168.1.0/24 dev eth0` > + * - A client sending an interface plus a gateway but netmask=any: intends > to set a default gateway. > + * e.g. `0.0.0.0/0 via 192.168.1.1` > + */ > kern_return_t > lwip_S_rioctl_siocaddrt (struct sock_user *user, > - const ifname_t ifnam, > - const struct srtentry route) > + const ifname_t ifnam, const struct srtentry route) > { > - return EOPNOTSUPP; > + kern_return_t err = 0; > + struct netif *netif; > + struct sockaddr sa; > + size_t buflen = sizeof (struct sockaddr); > + uint32_t ipv4_addrs[5]; > + > + if (!user) > + return EOPNOTSUPP; > + > + if (!user->isroot) > + return EPERM; > + > + /* All ones netmask means host route, not supported by lwip */ > + if (route.rt_mask == INADDR_NONE) > + return EOPNOTSUPP; > + > + netif = get_if (ifnam); > + if (!netif) > + return ENODEV; > + > + err = lwip_getsockname (user->sock->sockno, &sa, (socklen_t *)&buflen); > + if (err) > + return err; > + > + if (sa.sa_family != AF_INET) > + return EINVAL; > + > + inquire_device (netif, &ipv4_addrs[ADDR], &ipv4_addrs[NETMASK], > + &ipv4_addrs[DSTADDR], &ipv4_addrs[BRDADDR], > + &ipv4_addrs[GWADDR], 0, 0); > + > + if (route.rt_mask != INADDR_ANY && route.rt_gateway == INADDR_ANY) > + { > + /* > + * Subnet route. > + * Only one network can go through the interface so we set the netmask > to the interface. > + */ > + > + /* masking current IP must match given dest to be valid */ > + if (ipv4_addrs[ADDR] != INADDR_ANY && ipv4_addrs[ADDR] != INADDR_NONE > + && (ipv4_addrs[ADDR] & route.rt_mask) != route.rt_dest) > + return ENETUNREACH; > + > + ipv4_addrs[NETMASK] = route.rt_mask; > + } > + else if (route.rt_gateway != INADDR_ANY) > + { > + /* > + * Netmask is any, and we got a gateway so client is trying to add a > default route. > + * We set the given gateway to the given interface and set the > interface as default. > + */ > + > + /* First we verify the gateway is reachable from this netif */ > + if (ipv4_addrs[ADDR] != INADDR_ANY && ipv4_addrs[ADDR] != INADDR_NONE > + && ipv4_addrs[NETMASK] != INADDR_ANY > + && ipv4_addrs[NETMASK] != INADDR_NONE > + && (route.rt_gateway & ipv4_addrs[NETMASK]) != > + (ipv4_addrs[ADDR] & ipv4_addrs[NETMASK])) > + return EHOSTUNREACH; > + > + ipv4_addrs[GWADDR] = route.rt_gateway; > + tcpip_callback (set_default_if, netif); > + } > + else > + { > + /* Any other scenario not supported */ > + return EOPNOTSUPP; > + } > + > + err = configure_device (netif, ipv4_addrs[ADDR], ipv4_addrs[NETMASK], > + ipv4_addrs[DSTADDR], ipv4_addrs[BRDADDR], > + ipv4_addrs[GWADDR], 0, 0); > + > + return err; > } > > /* 11 SIOCDELRT -- Delete a network route */ > +/* > + * The only routing lwip supports is the default gateway for each netif. > + * We interpret "deleting a route" as removing the current gateway and > netmask, > + * but only if the given route matches. > + * > + * Supported scenarios: > + * - A client sending an interface plus a netmask but gateway=any: intends > to remove a subnet route. > + * e.g. `192.168.1.0/24 dev eth0` > + * - A client sending an interface plus a gateway but netmask=any: intends > to remove a default gateway. > + * e.g. `0.0.0.0/0 via 192.168.1.1` > + */ > kern_return_t > lwip_S_rioctl_siocdelrt (struct sock_user *user, > - const ifname_t ifnam, > - const struct srtentry route) > + const ifname_t ifnam, const struct srtentry route) > { > - return EOPNOTSUPP; > + kern_return_t err = 0; > + struct netif *netif; > + struct sockaddr sa; > + size_t buflen = sizeof (struct sockaddr); > + uint32_t ipv4_addrs[5]; > + > + if (!user) > + return EOPNOTSUPP; > + > + if (!user->isroot) > + return EPERM; > + > + netif = get_if (ifnam); > + if (!netif) > + return ENODEV; > + > + err = lwip_getsockname (user->sock->sockno, &sa, (socklen_t *)&buflen); > + if (err) > + return err; > + > + if (sa.sa_family != AF_INET) > + return EINVAL; > + > + inquire_device (netif, &ipv4_addrs[ADDR], &ipv4_addrs[NETMASK], > + &ipv4_addrs[DSTADDR], &ipv4_addrs[BRDADDR], > + &ipv4_addrs[GWADDR], 0, 0); > + > + if (route.rt_mask != INADDR_ANY && route.rt_gateway == INADDR_ANY) > + { > + /* > + * Subnet route. > + * Only one network can go through the interface so we remove the > netmask from the interface. > + */ > + > + /* We remove the netmask only if it matches the given one */ > + if (ipv4_addrs[NETMASK] != INADDR_ANY > + && ipv4_addrs[NETMASK] != INADDR_NONE > + && ipv4_addrs[NETMASK] != route.rt_mask) > + return EINVAL; > + > + ipv4_addrs[NETMASK] = INADDR_NONE; > + } > + else if (route.rt_gateway != INADDR_ANY) > + { > + /* > + * Netmask is any, and we got a gateway so client is trying to remove > a default route. > + * We remove the gateway from the given interface. > + */ > + > + /* We remove the gateway only if it matches the given one */ > + if (ipv4_addrs[GWADDR] != INADDR_ANY > + && ipv4_addrs[GWADDR] != INADDR_NONE > + && ipv4_addrs[GWADDR] != route.rt_gateway) > + return EINVAL; > + > + /* And only if it was the default one */ > + if (netif != netif_default) > + return EINVAL; > + > + ipv4_addrs[GWADDR] = INADDR_NONE; > + } > + else > + { > + /* Any other scenario not supported */ > + return EOPNOTSUPP; > + } > + > + err = configure_device (netif, ipv4_addrs[ADDR], ipv4_addrs[NETMASK], > + ipv4_addrs[DSTADDR], ipv4_addrs[BRDADDR], > + ipv4_addrs[GWADDR], 0, 0); > + > + return err; > } > > /* 12 SIOCSIFADDR -- Set address of a network interface. */ > -- > 2.50.1 > >
-- Samuel We are Pentium of Borg. Division is futile. You will be approximated. (seen in someone's .signature)
