#2695 we should not influence ip address family selection (traceback when IPv6 disabled)
Closed: Fixed None Opened 8 years ago by jdennis.

In nsslib (and possibly other places) we try to influence ip family selection. This is wrong. We should always use getaddrinfo (or one of it's wrappers) and iterate over the address list returned trying to connect the socket. The returned address list is sorted according to what the system networking configuration believes are the preferred selections. We should respect the system network configuration.


This is a part of the python-nss work.

no, I don't believe this is part of the python-nss work, not if you mean the updates to python-nss. Rather this is improper use of the python-nss API strictly within IPA

Replying to [comment:4 jdennis]:

no, I don't believe this is part of the python-nss work, not if you mean the updates to python-nss. Rather this is improper use of the python-nss API strictly within IPA

Ok thanks for correction, sorry for confusion.

The doc, which can be found here shows correct usage:

http://jdennis.fedorapeople.org/doc/python-nss/api/html/nss.io.AddrInfo-class.html

FWIW, whoever did the first implementation copied code from one of the examples that had a command line arg to force an address family, that's not normal and it shouldn't have been followed.

The idea behind getaddrinfo is that it returns an ordered list of addresses to try. It's ordered by the system according to rules established in the network stack. You're supposed to iterate through the address list in order and attempt to connect to see if the address is valid. If you can connect then use that address, else continue. BTW, this all explained in Steven's UNIX networking book.

Right, when I was looking in Python socket doc and accompanied examples, this was their recommended use.

Patch freeipa-mkosek-283-improve-address-family-handling-in-sockets.patch sent for review

Huh?

        try:
            addr_info = io.AddrInfo(host, family=self.family)
        except Exception:
             raise NSPRError(error.PR_ADDRESS_NOT_SUPPORTED_ERROR,
                             "Cannot resolve %s using family %s" % (host,
                                 io.addr_family_name(self.family)))

Why are we forcing the family? The whole point of using addr_info is to let it return an ordered list of addresses to attempt.

This is because NSSConnection allows forcing a family:

class NSSConnection(httplib.HTTPConnection, NSSAddressFamilyFallback):
    default_port = httplib.HTTPSConnection.default_port

    def __init__(self, host, port=None, strict=None,
                 dbdir=None, family=socket.AF_UNSPEC, no_init=False):
        """
        :param host: the server to connect to
        :param port: the port to use (default is set in HTTPConnection)
        :param dbdir: the NSS database directory
        :param family: network family to use (default AF_UNSPEC)
        :param no_init: do not initialize the NSS database. This requires
                        that the database has already been initialized or
                        the request will fail.
        """
        httplib.HTTPConnection.__init__(self, host, port, strict)
        NSSAddressFamilyFallback.__init__(self, family)

This selection is saved in NSSConnection class and used later in NSSAddressFamilyFallback (your example). However, the family is set by default to socket.AF_UNSPEC, i.e. io.PR_AF_UNSPEC when translated to NSS language.

Thus, by default, no forcing should happen. Or am I wrong with this one?

NSSConnection should not offer a family.

The nss.io.AddrInfo class is a wrapper around the familiar getaddrinfo() call. The idea behind getaddrinfo is uses information from the host system configuration to build an ordered list of addresses to try. You're supposed to iterate through the list in order attempting to connect with the supplied address until you successfully connect (usually that will happen on the first try). See Stevens book "UNIX Network Programming" for a more thorough discussion.

The reason we don't want to influence the family selection is we are ignorant of how the host networking is configured. If they prefer IPv6 over IPv4 we should not be subverting their choice. getaddrinfo() also utilizes information it has about routing, available interfaces etc. It attempts to pick the optimal address on the optimal interface for the supplied target address. But it doesn't have perfect information therefore it returns an ordered list of "suggestions" to try. Does this make more sense now?

You may point out that getaddrinfo does provide a mechanism to select only a subset of possible addresses (including the family), but in general that's only for when you have very specific a prori knowledge about your connection requirements. We don't have that knowledge and in general most apps don't, so they should allow getaddrinfo() to do it's job.

closing again, opened new ticket #3443 to cover the issue.

Moving back to appropriate Milestone.

Metadata Update from @jdennis:
- Issue assigned to mkosek
- Issue set to the milestone: FreeIPA 3.0 Beta 2

3 years ago

Login to comment on this ticket.

Metadata