[prev in list] [next in list] [prev in thread] [next in thread] 

List:       gentoo-portage-dev
Subject:    [gentoo-portage-dev] Re: [PATCH] process: add _has_ipv6() function
From:       Mike Gilbert <floppym () gentoo ! org>
Date:       2019-08-04 13:46:23
Message-ID: CAJ0EP419N857i+o2k9cnGW0j5Bg_F=BKoShV3i6opPtU-7saeQ () mail ! gmail ! com
[Download RAW message or body]

On Sun, Aug 4, 2019 at 9:40 AM Mike Gilbert <floppym@gentoo.org> wrote:
> 
> On Sun, Aug 4, 2019 at 9:34 AM Mike Gilbert <floppym@gentoo.org> wrote:
> > 
> > On Sat, Aug 3, 2019 at 7:37 PM Mike Gilbert <floppym@gentoo.org> wrote:
> > > 
> > > On Sat, Aug 3, 2019 at 3:30 PM Zac Medico <zmedico@gentoo.org> wrote:
> > > > 
> > > > Add _has_ipv6() function and use it in _configure_loopback_interface()
> > > > to decide whether to add an IPv6 address.
> > > > 
> > > > Bug: https://bugs.gentoo.org/691290
> > > > ---
> > > > lib/portage/process.py | 40 +++++++++++++++++++++++++++++++++++++---
> > > > 1 file changed, 37 insertions(+), 3 deletions(-)
> > > > 
> > > > diff --git a/lib/portage/process.py b/lib/portage/process.py
> > > > index 690421815..ca8b0c172 100644
> > > > --- a/lib/portage/process.py
> > > > +++ b/lib/portage/process.py
> > > > @@ -339,6 +339,9 @@ def spawn(mycommand, env=None, opt_name=None, \
> > > > fd_pipes=None, returnpid=False, fd_pipes[1] = pw
> > > > fd_pipes[2] = pw
> > > > 
> > > > +       # Cache _has_ipv6() result for use in child processes.
> > > > +       _has_ipv6()
> > > > +
> > > > # This caches the libc library lookup and _unshare_validator results
> > > > # in the current process, so that results are cached for use in
> > > > # child processes.
> > > > @@ -446,6 +449,38 @@ def spawn(mycommand, env=None, opt_name=None, \
> > > > fd_pipes=None, returnpid=False, # Everything succeeded
> > > > return 0
> > > > 
> > > > +__has_ipv6 = None
> > > > +
> > > > +def _has_ipv6():
> > > > +       """
> > > > +       Test that both userland and kernel support IPv6, by attempting
> > > > +       to create a socket and listen on any unused port of the IPv6
> > > > +       ::1 loopback address.
> > > > +
> > > > +       @rtype: bool
> > > > +       @return: True if IPv6 is supported, False otherwise.
> > > > +       """
> > > > +       global __has_ipv6
> > > > +
> > > > +       if __has_ipv6 is None:
> > > > +               if socket.has_ipv6:
> > > > +                       sock = None
> > > > +                       try:
> > > > +                               # python2.7 sockets do not support context \
> > > > management protocol +                               sock = \
> > > > socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) +                           \
> > > > sock.bind(('::1', 0)) +                       except EnvironmentError:
> > > > +                               __has_ipv6 = False
> > > > +                       else:
> > > > +                               __has_ipv6 = True
> > > > +                       finally:
> > > > +                               if sock is not None:
> > > > +                                       sock.close()
> > > > +               else:
> > > > +                       __has_ipv6 = False
> > > > +
> > > > +       return __has_ipv6
> > > > +
> > > > def _configure_loopback_interface():
> > > > """
> > > > Configure the loopback interface.
> > > > @@ -478,9 +513,8 @@ def _configure_loopback_interface():
> > > > 
> > > > try:
> > > > subprocess.call(['ip', 'address', 'add', '10.0.0.1/8', 'dev', 'lo'])
> > > > -               with open(os.devnull, 'wb', 0) as devnull:
> > > > -                       subprocess.call(['ip', 'address', 'add', 'fd00::1/8', \
> > > >                 'dev', 'lo'],
> > > > -                               stdout=devnull, stderr=devnull)
> > > > +               if _has_ipv6():
> > > > +                       subprocess.call(['ip', 'address', 'add', 'fd00::1/8', \
> > > > 'dev', 'lo']) except EnvironmentError as e:
> > > > writemsg("Error calling 'ip': %s\n" % e.strerror, noiselevel=-1)
> > > > 
> > > > --
> > > > 2.21.0
> > > > 
> > > 
> > > This seems reasonable, though I don't have an IPv6-less system to test it on.
> > 
> > While chatting in #gentoo-desktop, we found that it is possible to
> > have IPv6 enabled, but prohibit IPv6 addresses from being added to
> > interfaces. This produces the following error from ip:
> > 
> > RTNETLINK answers: Permission denied
> > 
> > https://www.kernel.org/doc/Documentation/networking/ipv6.txt
> > 
> > ipv6.disabled = 0
> > ipv6.disable_ipv6 = 1
> > 
> > I don't think your __has_ipv6 function will catch this.
> 
> Possibly the bind('::1', 0) call will fail if the loopback interface
> doesn't have that address configured. This appears to be the case when
> disable_ipv6 = 1.

We confirmed that the bind() call will raise this error, which is good.

OSError: [Errno 99] Cannot assign requested address


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic