bug-hurd
[Top][All Lists]
Advanced

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

Re: [PATCH] LwIP translator


From: Samuel Thibault
Subject: Re: [PATCH] LwIP translator
Date: Wed, 27 Sep 2017 00:44:15 +0200
User-agent: NeoMutt/20170113 (1.7.2)

Hello,

Joan Lledó, on mer. 06 sept. 2017 10:09:36 +0200, wrote:
> --- /dev/null
> +++ b/lwip/iioctl-ops.c

> +/* Get the interface from its name */
> +static struct netif *
> +get_if (char *name)
...
> +
> +  netif = netif_list;
> +  while (netif != 0)
> +    {
> +      if (strcmp (netif_get_state (netif)->devname, ifname) == 0)
> +     break;
> +
> +      netif = netif->next;
> +    }

Rather use a for loop:

  for (netif = netif_list; netif != 0; netif = netif->next)

that's much more trustable :)

> +/* Get some sockaddr type of info.  */
> +static kern_return_t
> +siocgifXaddr (struct sock_user *user,
> +           ifname_t ifnam, sockaddr_t * addr, enum siocgif_type type)
> +{
> +  error_t err = 0;
> +  struct sockaddr_in *sin = (struct sockaddr_in *) addr;
> +  struct netif *netif;

> +  size_t buflen = sizeof (struct sockaddr);
> +  uint32_t addrs[4];

> +  err = lwip_getsockname (user->sock->sockno, addr, (socklen_t *) & buflen);

Here, perhaps comment that we are only interested in checking the
address family, thus only sizeof (struct sockaddr)

> +/* 100 SIOCGIFINDEX -- Get index number of a network interface.  */
> +error_t
> +lwip_S_iioctl_siocgifindex (struct sock_user * user,
> +                         ifname_t ifnam,
> +                         int *index)
> +{
> +  error_t err = 0;
> +  struct netif *netif;
> +  int i;
> +
> +  if (!user)
> +    return EOPNOTSUPP;
> +
> +  i = 1;                     /* The first index must be 1 */
> +  netif = netif_list;
> +  while (netif != 0)
> +    {
> +      if (strcmp (netif_get_state (netif)->devname, ifnam) == 0)
> +     {
> +       *index = i;
> +       break;
> +     }
> +
> +      netif = netif->next;
> +      i++;

Similarly, it makes the reader more confident to read a for loop here.

> +/* 101 SIOCGIFNAME -- Get name of a network interface from index number.  */
> +error_t
> +lwip_S_iioctl_siocgifname (struct sock_user * user,
> +                        ifname_t ifnam,
> +                        int *index)
> +{

And there again :)

> diff --git a/lwip/io-ops.c b/lwip/io-ops.c
> new file mode 100644
> index 00000000..2553ca33
> --- /dev/null
> +++ b/lwip/io-ops.c

> +error_t
> +lwip_S_io_write (struct sock_user * user,
> +              char *data,
> +              size_t datalen,
> +              off_t offset, mach_msg_type_number_t * amount)
> +{
...
> +  if (sockflags & O_NONBLOCK)
> +    m.msg_flags |= MSG_DONTWAIT;
> +  sent = lwip_sendmsg (user->sock->sockno, &m, 0);

I'm wondering about thread-safety: I guess you enabled the unix arch to
get pthread mutex locks?

Also, why using lwip_sendmsg instead of just lwip_send? That'd avoid the
construction of m etc.
In the linuxish pfinet case, it's just because there is no recv method
:)

> +static error_t
> +lwip_io_select_common (struct sock_user *user,
> +                    mach_port_t reply,
> +                    mach_msg_type_name_t reply_type,
> +                    struct timeval *tv, int *select_type)
> +{
...
> +  timeout = tv ? tv->tv_sec * 1000 + tv->tv_usec / 1000 : -1;
> +  ret = lwip_poll (&fdp, nfds, timeout);

Better use lwip_ppoll to have better timeout resolution, and use struct
timespec instead of struct timeval.

> diff --git a/lwip/lwip-util.c b/lwip/lwip-util.c
> new file mode 100644
> index 00000000..2996632e
> --- /dev/null
> +++ b/lwip/lwip-util.c

> +  /* Freed in the module terminate callback */
> +  ifc->devname = malloc (strlen (name) + 1);
> +  if (ifc->devname)
> +    {
> +      memset (ifc->devname, 0, strlen (name) + 1);
> +      strncpy (ifc->devname, name, strlen (name));
> +    }

Err, rather just use strdup (name)? :)


> +      if (addr6_prefix_len)
> +     for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++)
> +       *(addr6_prefix_len + i) = 64;

Does lwip support only /64 IPv6 networks?

> --- /dev/null
> +++ b/lwip/main.c

> +#ifndef _GNU_SOURCE
> +#define _GNU_SOURCE
> +#endif

_GNU_SOURCE has to be defined *before* including headers. And we always
define _GNU_SOURCE while building hurd translators, this it *is* the GNU
system, so we use the GNU standard :)

> +error_t
> +trivfs_goaway (struct trivfs_control *fsys, int flags)
> +{
> +  exit (0);
> +}

The linuxish pfinet returns EBUSY if there are still sockets, it is a
useful thing to check.

> +  if (pi)
> +    {
> +      ports_port_deref (pi);
> +
> +      mig_routine_t routine;
> +      if ((routine = lwip_io_server_routine (inp)) ||
> +       (routine = lwip_socket_server_routine (inp)) ||
> +       (routine = lwip_pfinet_server_routine (inp)) ||
> +       (routine = lwip_iioctl_server_routine (inp)) ||
> +       (routine = NULL, trivfs_demuxer (inp, outp)))

In the linuxish pfinet, the startup protocol is also used, to nicely
close net channels before exiting, that's a useful thing to do.

> diff --git a/lwip/options.c b/lwip/options.c
> new file mode 100644
> index 00000000..b7b34fd8
> --- /dev/null
> +++ b/lwip/options.c
> @@ -0,0 +1,346 @@

> +    case 'A':
> +      /* IPv6 address */
> +      if (arg)
> +     {

> +
> +       for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++)
> +         {
> +           address6 = (ip6_addr_t *) & h->curint->addr6[i];
> +
> +           /* Is the slot free? */
> +           if (!ip6_addr_isany (address6))
> +             continue;
> +
> +           /* Use the slot */
> +           if (ip6addr_aton (arg, address6) <= 0)
> +             PERR (EINVAL, "Malformed address");
> +
> +           break;
> +         }

There should be some error thrown if we couldn't find a free slot.

> +  netif = netif_list;
> +  while (netif != 0)
> +    {

Again, for loop :)

> --- /dev/null
> +++ b/lwip/pfinet-ops.c

> +static void
> +dev_ifconf (struct ifconf *ifc)
> +{
> +  struct netif *netif;
> +  struct ifreq ifr;
> +  struct sockaddr_in *saddr;
> +  char *buf;
> +  int len;
> +
> +  buf = (char *) ifc->ifc_req;
> +  len = ifc->ifc_len;
> +  saddr = (struct sockaddr_in *) &ifr.ifr_addr;
> +  netif = netif_list;
> +  while (netif != 0)
> +    {

Ditto.

> +      if (ifc->ifc_req != 0)
> +     {
> +       /* Get the data */
> +       if (len < (int) sizeof (struct ifreq))
> +         break;
> +
> +       memset (&ifr, 0, sizeof (struct ifreq));
> +
> +       memcpy (ifr.ifr_name, netif_get_state (netif)->devname,
> +               strlen (netif_get_state (netif)->devname));
> +       saddr->sin_len = sizeof (struct sockaddr_in);
> +       saddr->sin_family = AF_INET;
> +       saddr->sin_addr.s_addr = netif_ip4_addr (netif)->addr;
> +
> +       memcpy (buf, &ifr, sizeof (struct ifreq));

Why filling ifr before copying to the buffer? You could use a

struct ifreq *ifr = buf;
struct sockaddr_in *saddr = (struct sockaddr_in *) &ifr->ifr_addr;

> diff --git a/lwip/port-objs.c b/lwip/port-objs.c
> new file mode 100644
> index 00000000..e60c6808
> --- /dev/null
> +++ b/lwip/port-objs.c

> +struct sock_user *
> +make_sock_user (struct socket *sock, int isroot, int noinstall, int consume)
> +{
> +  error_t err;
> +  struct sock_user *user;
> +
> +  assert (sock->refcnt != 0);

Btw, use assert_backtrace everywhere you can, it's much more useful than
just assert :)

> +  if (noinstall)
> +    err = ports_create_port_noinstall (socketport_class, lwip_bucket,
> +                                    sizeof (struct sock_user), &user);
> +  else
> +    err = ports_create_port (socketport_class, lwip_bucket,
> +                          sizeof (struct sock_user), &user);
> +  if (err)
> +    return 0;
> +
> +  if (!consume)
> +    ++sock->refcnt;

This kind of reference counting needs locking. You can probably use
refcount.h to avoid having to add locking.

> diff --git a/lwip/port/netif/hurdethif.c b/lwip/port/netif/hurdethif.c
> new file mode 100644
> index 00000000..b17aa84a
> --- /dev/null
> +++ b/lwip/port/netif/hurdethif.c

> +error_t
> +hurdethif_device_init (struct netif * netif)
> +{
> +  ethif = malloc (sizeof (hurdethif));
> +  if (!ethif)
> +    {
> +      LWIP_DEBUGF (NETIF_DEBUG, ("hurdethif_init: out of memory\n"));
> +      return ERR_MEM;
> +    }
> +  memset (ethif, 0, sizeof (hurdethif));

Better use calloc in such cases, to let glibc automatically optimize
whenever possible.

> +  /* Maximum transfer unit: MSS + IP header size + TCP header size */
> +  netif->mtu = TCP_MSS + 0x28;

Better use 20 + 20 in such case instead of 0x28.

> --- /dev/null
> +++ b/lwip/socket-ops.c

> +  struct sock_user *newuser;
> +  union
> +  {
> +    struct sockaddr_storage storage;
> +    struct sockaddr sa;
> +  } addr =

You don't need to do this, just use sockaddr_storage, and cast the
address of addr to (struct sockaddr *), it is defined in a way that
makes the cast valid.


Last but not least, did you try to run the glibc testsuite while running
this TCP/IP stack?  It would probably find potential bugs.  Also, the
perl testsuite is probably a nice thing to run.

Apart from that, it looks good to me :)

Samuel



reply via email to

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