Gentoo Archives: gentoo-portage-dev

From: Mike Gilbert <floppym@g.o>
To: Zac Medico <zmedico@g.o>
Cc: gentoo-portage-dev@l.g.o
Subject: [gentoo-portage-dev] Re: [PATCH] process: add _has_ipv6() function
Date: Sun, 04 Aug 2019 13:46:38
Message-Id: CAJ0EP419N857i+o2k9cnGW0j5Bg_F=BKoShV3i6opPtU-7saeQ@mail.gmail.com
In Reply to: [gentoo-portage-dev] Re: [PATCH] process: add _has_ipv6() function by Mike Gilbert
1 On Sun, Aug 4, 2019 at 9:40 AM Mike Gilbert <floppym@g.o> wrote:
2 >
3 > On Sun, Aug 4, 2019 at 9:34 AM Mike Gilbert <floppym@g.o> wrote:
4 > >
5 > > On Sat, Aug 3, 2019 at 7:37 PM Mike Gilbert <floppym@g.o> wrote:
6 > > >
7 > > > On Sat, Aug 3, 2019 at 3:30 PM Zac Medico <zmedico@g.o> wrote:
8 > > > >
9 > > > > Add _has_ipv6() function and use it in _configure_loopback_interface()
10 > > > > to decide whether to add an IPv6 address.
11 > > > >
12 > > > > Bug: https://bugs.gentoo.org/691290
13 > > > > ---
14 > > > > lib/portage/process.py | 40 +++++++++++++++++++++++++++++++++++++---
15 > > > > 1 file changed, 37 insertions(+), 3 deletions(-)
16 > > > >
17 > > > > diff --git a/lib/portage/process.py b/lib/portage/process.py
18 > > > > index 690421815..ca8b0c172 100644
19 > > > > --- a/lib/portage/process.py
20 > > > > +++ b/lib/portage/process.py
21 > > > > @@ -339,6 +339,9 @@ def spawn(mycommand, env=None, opt_name=None, fd_pipes=None, returnpid=False,
22 > > > > fd_pipes[1] = pw
23 > > > > fd_pipes[2] = pw
24 > > > >
25 > > > > + # Cache _has_ipv6() result for use in child processes.
26 > > > > + _has_ipv6()
27 > > > > +
28 > > > > # This caches the libc library lookup and _unshare_validator results
29 > > > > # in the current process, so that results are cached for use in
30 > > > > # child processes.
31 > > > > @@ -446,6 +449,38 @@ def spawn(mycommand, env=None, opt_name=None, fd_pipes=None, returnpid=False,
32 > > > > # Everything succeeded
33 > > > > return 0
34 > > > >
35 > > > > +__has_ipv6 = None
36 > > > > +
37 > > > > +def _has_ipv6():
38 > > > > + """
39 > > > > + Test that both userland and kernel support IPv6, by attempting
40 > > > > + to create a socket and listen on any unused port of the IPv6
41 > > > > + ::1 loopback address.
42 > > > > +
43 > > > > + @rtype: bool
44 > > > > + @return: True if IPv6 is supported, False otherwise.
45 > > > > + """
46 > > > > + global __has_ipv6
47 > > > > +
48 > > > > + if __has_ipv6 is None:
49 > > > > + if socket.has_ipv6:
50 > > > > + sock = None
51 > > > > + try:
52 > > > > + # python2.7 sockets do not support context management protocol
53 > > > > + sock = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
54 > > > > + sock.bind(('::1', 0))
55 > > > > + except EnvironmentError:
56 > > > > + __has_ipv6 = False
57 > > > > + else:
58 > > > > + __has_ipv6 = True
59 > > > > + finally:
60 > > > > + if sock is not None:
61 > > > > + sock.close()
62 > > > > + else:
63 > > > > + __has_ipv6 = False
64 > > > > +
65 > > > > + return __has_ipv6
66 > > > > +
67 > > > > def _configure_loopback_interface():
68 > > > > """
69 > > > > Configure the loopback interface.
70 > > > > @@ -478,9 +513,8 @@ def _configure_loopback_interface():
71 > > > >
72 > > > > try:
73 > > > > subprocess.call(['ip', 'address', 'add', '10.0.0.1/8', 'dev', 'lo'])
74 > > > > - with open(os.devnull, 'wb', 0) as devnull:
75 > > > > - subprocess.call(['ip', 'address', 'add', 'fd00::1/8', 'dev', 'lo'],
76 > > > > - stdout=devnull, stderr=devnull)
77 > > > > + if _has_ipv6():
78 > > > > + subprocess.call(['ip', 'address', 'add', 'fd00::1/8', 'dev', 'lo'])
79 > > > > except EnvironmentError as e:
80 > > > > writemsg("Error calling 'ip': %s\n" % e.strerror, noiselevel=-1)
81 > > > >
82 > > > > --
83 > > > > 2.21.0
84 > > > >
85 > > >
86 > > > This seems reasonable, though I don't have an IPv6-less system to test it on.
87 > >
88 > > While chatting in #gentoo-desktop, we found that it is possible to
89 > > have IPv6 enabled, but prohibit IPv6 addresses from being added to
90 > > interfaces. This produces the following error from ip:
91 > >
92 > > RTNETLINK answers: Permission denied
93 > >
94 > > https://www.kernel.org/doc/Documentation/networking/ipv6.txt
95 > >
96 > > ipv6.disabled = 0
97 > > ipv6.disable_ipv6 = 1
98 > >
99 > > I don't think your __has_ipv6 function will catch this.
100 >
101 > Possibly the bind('::1', 0) call will fail if the loopback interface
102 > doesn't have that address configured. This appears to be the case when
103 > disable_ipv6 = 1.
104
105 We confirmed that the bind() call will raise this error, which is good.
106
107 OSError: [Errno 99] Cannot assign requested address