Hi Lukas,

On Thu, Jun 20, 2013 at 08:26:47PM +0200, Lukas Tribus wrote:
> Hi Willy,
> 
> 
> > One is a fix (to->from) and can as well include the doc fix.
> 
> Attaching the patch. I stole your explanation for the commit message, hope
> you don't mind :)

No of course, you're welcome.

> I'm thinking about this logic (pseudo code):
> #if defined(IP_TOS) && defined(IPV6_TCLASS)
> /* IP_TOS needs to be set for both families, because a AF_INET6
>    socket may carries IPv4 traffic (when IPV6_V6ONLY is 0) */
> if (address-family == AF_INET || address-family == AF_INET6)
>     setsockopt(fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
> if (address-family == AF_INET6)
>     setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS, &tos, sizeof(tos));
> #endif

I don't like much mixing IPv4 and IPv6 together in the #ifdef,
because I don't know if IPV6_TCLASS is defined on all libcs,
especially old ones or embedded ones, where it could result in
disabling the IPv4 setting. I'd rather split that approximately
like this :

#if defined(IP_TOS)
        if (address-family == AF_INET)
                setsockopt(fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
        if (address-family == AF_INET6) {
                if (setsockopt(fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) == 
-1) {
#if defined(IPV6_TCLASS)
                        setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS, &tos, 
sizeof(tos));
#endif
                }
        }
#endif

It would also avoid doing systematically two syscalls when the
first one succeeds.

> Is the address-family check needed anyway or is this a result of your
> intention to do this in v4 only?

I prefer to keep it because I don't know what these setsockopt can do on
unix sockets for example. And since we don't use exactly the same ones
depending on the family, it's better as well.

> Its hard to upset setsockopt, it will just return -1 when things don't make
> sense, nothing breaks:
> 
> when family is AF_INET (a true ipv4 socket):
> setsockopt->IPV6_TCLASS returns -1
> setsockopt->IP_TOS returns 0
> 
> when family is AF_INET6 (either a true ipv6 or a v4 mapped socket)
> setsockopt->IPV6_TCLASS returns 0
> setsockopt->IP_TOS returns 0
> 
> when family is a unix-socket obviously:
> setsockopt->IPV6_TCLASS returns -1
> setsockopt->IP_TOS returns -1

I must say I don't much like making syscalls return errors when we can
avoid them, because not only this means they're called for no reason,
but more specifically they make debugging more difficult (eg: strace -c).

> With the pseudo code example above, setsockopt would always be successful,
> so this should be most portable and the corner case of a v4-in-a-v6-mapped
> socket would be addressed.

I already forgot about this one :-)

Then maybe why not :

#if defined(IP_TOS)
        if (address-family == AF_INET || address-family == AF_INET6) {
                if (setsockopt(fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) == 
-1) {
#if defined(IPV6_TCLASS)
                        setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS, &tos, 
sizeof(tos));
#endif
                }
        }
#endif

This would only call the second one if the first fails, which according
to your tests should not happen.

Or you can even put that more elegantly in an inline function :

static inline void inet_set_tos(int fd, sa_family_t family, int tos)
{
        if (family != AF_INET && family != AF_INET6)
                return;
#if defined(IP_TOS)
        if (setsockopt(fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) == 0)
                return;
#endif
#if defined(IPV6_TCLASS)
        if (setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS, &tos, sizeof(tos) == 0)
                return;
#endif
}

What do you think ?

Best regards,
Willy


Reply via email to