Digging a bit more into this, it appears that in case of link local ipv6 address. also sin6_scope_id of sockaddr_in6 needs to be set:
struct sockaddr_in6 { __SOCKADDR_COMMON (sin6_); in_port_t sin6_port; /* Transport layer port # */ uint32_t sin6_flowinfo; /* IPv6 flow information */ struct in6_addr sin6_addr; /* IPv6 address */ uint32_t sin6_scope_id; /* IPv6 scope-id */ };
and there is function if_nametoindex() in <net/if.h> that can be used to convert interface name (in my case wlp1s0) into the scope id.
-- Juha