Control: tag 813249 + ipv6

Hello,

On Sun, Jan 31, 2016 at 02:44:51AM +0100, Uwe Kleine-König wrote:
> On 01/30/2016 11:05 PM, Uwe Kleine-König wrote:
> > Package: libupnp6
> > Version: 1:1.6.19+git20160116-1
> > Severity: normal
> > 
> > Hello,
> > 
> > vlc stopped showing my dlna provider, when downgrading libupnp6 to
> > 1:1.6.19+git20141001-1 it works fine again.
> > 
> > With libupnp6 1:1.6.19+git20141001-1 the (I think) relevant part obtained 
> > from strace is:
> > 
> >     10317 socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 18
> >     10317 socket(PF_INET6, SOCK_STREAM, IPPROTO_IP) = 19
> >     10317 setsockopt(19, SOL_IPV6, IPV6_V6ONLY, [1], 4) = 0
> >     10317 bind(18, {sa_family=AF_INET, sin_port=htons(49152), 
> > sin_addr=inet_addr("0.0.0.0")}, 16) = 0
> >     10317 bind(19, {sa_family=AF_INET6, sin6_port=htons(49152), 
> > inet_pton(AF_INET6, "::", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, 
> > 28) = 0
> >     10317 listen(18, 128)                   = 0
> >     10317 getsockname(18, {sa_family=AF_INET, sin_port=htons(49152), 
> > sin_addr=inet_addr("0.0.0.0")}, [16]) = 0
> >     10317 listen(19, 128)                   = 0
> >     10317 getsockname(19, {sa_family=AF_INET6, sin6_port=htons(49152), 
> > inet_pton(AF_INET6, "::", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, 
> > [28]) = 0
> > 
> > while with 1:1.6.19+git20160116-1 I get:
> > 
> >     10997 socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 18
> >     10997 socket(PF_INET6, SOCK_STREAM, IPPROTO_IP) = 19
> >     10997 setsockopt(19, SOL_IPV6, IPV6_V6ONLY, [1], 4) = 0
> >     10997 bind(18, {sa_family=AF_INET, sin_port=htons(49152), 
> > sin_addr=inet_addr("192.168.77.157")}, 16) = 0
> >     10997 bind(19, {sa_family=AF_INET6, sin6_port=htons(49152), 
> > inet_pton(AF_INET6, "fe80::f2de:f1ff:fe44:529d", &sin6_addr), 
> > sin6_flowinfo=0, sin6_scope_id=0}, 28) = -1 EINVAL (Invalid argument)
> >     10997 bind(19, {sa_family=AF_INET6, sin6_port=htons(49153), 
> > inet_pton(AF_INET6, "fe80::f2de:f1ff:fe44:529d", &sin6_addr), 
> > sin6_flowinfo=0, sin6_scope_id=0}, 28) = -1 EINVAL (Invalid argument)
> >     10997 bind(19, {sa_family=AF_INET6, sin6_port=htons(49154), 
> > inet_pton(AF_INET6, "fe80::f2de:f1ff:fe44:529d", &sin6_addr), 
> > sin6_flowinfo=0, sin6_scope_id=0}, 28) = -1 EINVAL (Invalid argument)
> >     10997 bind(19, {sa_family=AF_INET6, sin6_port=htons(49155), 
> > inet_pton(AF_INET6, "fe80::f2de:f1ff:fe44:529d", &sin6_addr), 
> > sin6_flowinfo=0, sin6_scope_id=0}, 28) = -1 EINVAL (Invalid argument)
> >     10997 bind(19, {sa_family=AF_INET6, sin6_port=htons(49156), 
> > inet_pton(AF_INET6, "fe80::f2de:f1ff:fe44:529d", &sin6_addr), 
> > sin6_flowinfo=0, sin6_scope_id=0}, 28) = -1 EINVAL (Invalid argument)
> >     ...
> >     10997 bind(19, {sa_family=AF_INET6, sin6_port=htons(65531), 
> > inet_pton(AF_INET6, "fe80::f2de:f1ff:fe44:529d", &sin6_addr), 
> > sin6_flowinfo=0, sin6_scope_id=0}, 28) = -1 EINVAL (Invalid argument)
> >     10997 bind(19, {sa_family=AF_INET6, sin6_port=htons(65532), 
> > inet_pton(AF_INET6, "fe80::f2de:f1ff:fe44:529d", &sin6_addr), 
> > sin6_flowinfo=0, sin6_scope_id=0}, 28) = -1 EINVAL (Invalid argument)
> >     10997 bind(19, {sa_family=AF_INET6, sin6_port=htons(65533), 
> > inet_pton(AF_INET6, "fe80::f2de:f1ff:fe44:529d", &sin6_addr), 
> > sin6_flowinfo=0, sin6_scope_id=0}, 28) = -1 EINVAL (Invalid argument)
> >     10997 bind(19, {sa_family=AF_INET6, sin6_port=htons(65534), 
> > inet_pton(AF_INET6, "fe80::f2de:f1ff:fe44:529d", &sin6_addr), 
> > sin6_flowinfo=0, sin6_scope_id=0}, 28) = -1 EINVAL (Invalid argument)
> >     10997 bind(19, {sa_family=AF_INET6, sin6_port=htons(65535), 
> > inet_pton(AF_INET6, "fe80::f2de:f1ff:fe44:529d", &sin6_addr), 
> > sin6_flowinfo=0, sin6_scope_id=0}, 28) = -1 EINVAL (Invalid argument)
> >     10997 close(18)                         = 0
> >     10997 close(19)                         = 0
> > 
> > The obvious difference is that the newer libupnp uses an explicit
> > address for binding the port, but I don't see this as an excuse for bind
> > to fail. And in fact the same difference exists for ipv4 where there
> > doesn't seem to be a problem.
> > 
> > btw, netcat-openbsd has the same problem:
> > 
> >     nc fe80::2ac6:8eff:fe36:df57 22
> > 
> > fails with:
> > 
> >     connect(3, {sa_family=AF_INET6, sin6_port=htons(22), 
> > inet_pton(AF_INET6, "fe80::2ac6:8eff:fe36:df57", &sin6_addr), 
> > sin6_flowinfo=0, sin6_scope_id=0}, 28) = -1 EINVAL (Invalid argument)
> > 
> > while it works fine when using the ipv4 or a global ipv6 of the same
> > machine.

btw, this works:

        nc fe80::2ac6:8eff:fe36:df57%eth0 22

to specify the device. strace output changes to:

        ... sin6_scope_id=if_nametoindex("eth0")

> > So it seems to be a bad idea to use the link local ipv6. Without
> > checking the source code, for machines with >1 network device using the
> > wildcard address seems to be easier. Also it would be nice if libupnp
> > fell back to ipv4 only if it fails to connect via ipv6.
> > 
> > Maybe this bug is a regression from addressing #781876?
> 
> No, it's not, it's a regression from
> 
> * Bind miniserver sockets to our given IP address not INADDR_ANY (patch 24).
> 
> that is upstream bug 127[1]. When reverting that one, vlc works as
> expected (and before).
> 
> While searching for the problem I stumbled about the following paragraph
> in ipv6(7):
> 
> ERRORS
>        ENODEV The user tried to bind(2) to a link-local IPv6 address,
>               but the sin6_scope_id in the supplied sockaddr_in6
>               structure is not a valid interface index.
> 
> This doesn't match EINVAL that I'm seeing, but still is the problem I
> think. libupnp (and also netcat) pass 0, which isn't a valid scope_id.
> (The valid scope_ids can be determined from either $(ip link) or with
> the SIOCGIFINDEX ioctl on a socket (see netdevice(7)). Not sure how
> portable to non-Linux architectures that is though.

I just tested this patch:
diff --git a/upnp/src/genlib/miniserver/miniserver.c 
b/upnp/src/genlib/miniserver/miniserver.c
index 683c4b3d36cc..7e94a03de4d8 100644
--- a/upnp/src/genlib/miniserver/miniserver.c
+++ b/upnp/src/genlib/miniserver/miniserver.c
@@ -583,6 +583,7 @@ static int get_miniserver_sockets(
        memset(&__ss_v6, 0, sizeof (__ss_v6));
        serverAddr6->sin6_family = (sa_family_t)AF_INET6;
        inet_pton(AF_INET6, gIF_IPV6, &serverAddr6->sin6_addr);
+       serverAddr6->sin6_scope_id = 3;
 #endif
        /* Getting away with implementation of re-using address:port and
         * instead choosing to increment port numbers.

which of course is not correct in general, but on my host it makes vlc
see my upnp share again.

Maybe the easiest way forward would be so somehow save the struct
sockaddr_in6 used to make the lookup for the link local address?

Best regards
Uwe

Attachment: signature.asc
Description: PGP signature

Reply via email to