Greetings,

1. The manual of route(4) explains the structure of its messages thus:

    `Messages are formed by a header followed by a small number of
    sockaddr structures (which are variable length), interpreted by
    position, and delimited by the length entry in the sockaddr.'

(That phrase is quite unfortunate in itself: `sa_len' is supposed to
/determine/ the length of a structure.  To me, the word `delimited'
implies the presence of a memory object between two adjacent
structures, which certainly was not the intent of the author.)

Armed with that knowledge, I wrote a parser the other day.  I very
much enjoyed OpenBSD until my program fatally stumbled on a peculiar
structure that does not fit the above description:

    05 00 00 00 ff 00 00 00

(The value of `sa_len' of that `sockaddr' is nothing that I am
familiar with, the address family is `AF_UNSPEC', and the most
disturbing: `sa_len' does not match the physical size of this
structure. These eight bytes were immediately followed by a perfectly
valid `sockaddr_in'.)

It took me some time to figure out that, apparently, I am looking at
the combined effect of in_socktrim() (see src/sys/netinet/in.c) and
ROUNDUP() (see src/sys/net/rtsock.c) applied to the netmask of
0xff000000 that was stored as sockaddr_in'.

I believe that manuals should be more merciful.  In the absence of
proper documentation, the part of my program that handles this case looks like a mysterious ritual; it should not be that way.


2. The definition of ROUNDUP() somewhat surprised me: it silently handles zero. The macro is local to the compilation unit; it is used
this way:

        if (rtinfo == NULL || (sa = rtinfo->rti_info[i]) == NULL)
                continue;
        rtinfo->rti_addrs |= (1 << i);
        dlen = ROUNDUP(sa->sa_len);

and this way:

        if ((sa = rtinfo->rti_info[i]) == NULL)
                continue;
        rtinfo->rti_addrs |= (1 << i);
        dlen = ROUNDUP(sa->sa_len);

(In the second case, the programmer does not check `rtinfo' for being
NULL.  I only hope that there exists a good explanation to that.)

Since `sa_len' describes the size of a `sockaddr' (or one of its
derivatives) /including/ `sa_len' (maybe I am wrong, but this is my
interpretation of the comment `total length' that appears near the
definition of `struct sockaddr' in <sys/socket.h>), `sa_len' just
cannot be zero.

The current definition of ROUNDUP() might hide a bug.  In addition, on
some machines, it disturbs the pipeline of the CPU by introducing a
branch (for no real reason, as it seems, while I might be
nitpicking). At very least, it looks confusing.


Thank you for your time,
-- Vadim

Reply via email to