Hi Willy,
> 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 > } Since setsockopt always returns 0, the function will return too early to set IPV6_TCLASS. However we can - as per RFC2553 section 3.7 - use the libc macro IN6_IS_ADDR_V4MAPPED(), to test whether the IPv6 address is actually a V4-mapped-in-V6 adress (so we set IP_TOS) or a proper IPv6 address (so we set IPV6_TCLASS). Instead of the sa_family_t I'm passing the whole sockaddr_storage struct to the function, so I can access the actual IPv6 address. Let me know if there are any implications of doing so: static inline void inet_set_tos(int fd, struct sockaddr_storage from, int tos) { #ifdef IP_TOS if (from.ss_family == AF_INET) setsockopt(fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)); #endif #ifdef IPV6_TCLASS if (from.ss_family != AF_INET6) return; if (IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&from)->sin6_addr)) setsockopt(fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)); else setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS, &tos, sizeof(tos)); #endif } Thats means we make a single (the correct one) syscall only, and all 3 scenarios (native IPv4, native IPv6 and v4-in-v6-mapped) are covered. To maintain compatibility we put everything v6 related in #ifdef's of IPV6_TCLASS. In case the libc doesn't have that macro, but defines other IPv6 related things like IPV6_TCLASS, we add a compatibility define in compat.h: #if defined(IPV6_TCLASS) && !defined(IN6_IS_ADDR_V4MAPPED) #define IN6_IS_ADDR_V4MAPPED(a) \ ((((const uint32_t *) (a))[0] == 0) \ && (((const uint32_t *) (a))[1] == 0) \ && (((const uint32_t *) (a))[2] == htonl (0xffff))) #endif > We could emit a warning if IPV6_TCLASS is not defined when the set-tos > is used, but quite frankly, it could upset users who are only using IPV4. I agree, I didn't think of that. The user may not be able to change the underlying kernel/libc and a warning can be annoying. Also this is only interesting for one situation: when IPv6 is used, but IPV6_TCLASS is not defined, and that particular case will probably never happen in real life. Let me know if you are ok with the approach above. Best regards, Lukas