On Sun, Nov 27, 2016 at 10:37:36PM +0100, Uwe Kleine-König wrote:
> 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;

Using

+       serverAddr6->sin6_scope_id = gIF_INDEX;

is a bit better (and works here, too). Either needs some #ifdeffery, or
(probably more robust) some restructuring to save the sockaddr_in6 used
to lookup the local address instead of only gIF_IPV6.

Best regards
Uwe

Attachment: signature.asc
Description: PGP signature

Reply via email to