Esempio n. 1
0
def inet_pton(address_family, ip_string):
    # Verify IP Address
    # This will catch IP Addresses such as 10.1.2
    if address_family == socket.AF_INET:
        try:
            ipaddress.ip_address(str(ip_string))
        except ValueError:
            raise socket.error('illegal IP address string passed to inet_pton')
        return socket.inet_aton(ip_string)

    # Verify IP Address
    # The `WSAStringToAddressA` function handles notations used by Berkeley
    # software which includes 3 part IP Addresses such as `10.1.2`. That's why
    # the above check is needed to enforce more strict IP Address validation as
    # used by the `inet_pton` function in Unix.
    # See the following:
    # https://stackoverflow.com/a/29286098
    # Docs for the `inet_addr` function on MSDN
    # https://msdn.microsoft.com/en-us/library/windows/desktop/ms738563.aspx
    addr = sockaddr()
    addr.sa_family = address_family
    addr_size = ctypes.c_int(ctypes.sizeof(addr))

    if WSAStringToAddressA(ip_string.encode('ascii'), address_family, None,
                           ctypes.byref(addr), ctypes.byref(addr_size)) != 0:
        raise socket.error(ctypes.FormatError())

    if address_family == socket.AF_INET:
        return ctypes.string_at(addr.ipv4_addr, 4)
    if address_family == socket.AF_INET6:
        return ctypes.string_at(addr.ipv6_addr, 16)

    raise socket.error('unknown address family')
Esempio n. 2
0
def _ip_addrs(interface=None,
              include_loopback=False,
              interface_data=None,
              proto='inet'):
    """
    Return the full list of IP adresses matching the criteria

    proto = inet|inet6
    """
    ret = set()

    ifaces = interface_data \
        if isinstance(interface_data, dict) \
        else interfaces()
    if interface is None:
        target_ifaces = ifaces
    else:
        target_ifaces = dict([(k, v) for k, v in iter(ifaces.items())
                              if k == interface])
        if not target_ifaces:
            log.error('Interface %s not found.', interface)
    for ip_info in target_ifaces.values():
        addrs = ip_info.get(proto, [])
        addrs.extend([
            addr for addr in ip_info.get('secondary', [])
            if addr.get('type') == proto
        ])

        for addr in addrs:
            addr = ipaddress.ip_address(addr.get('address'))
            if not addr.is_loopback or include_loopback:
                ret.add(addr)
    return [str(addr) for addr in sorted(ret)]
Esempio n. 3
0
def is_ipv4(ip):
    """
    Returns a bool telling if the value passed to it was a valid IPv4 address
    """
    try:
        return ipaddress.ip_address(ip).version == 4
    except ValueError:
        return False
Esempio n. 4
0
def in_subnet(cidr, addr=None):
    """
    Returns True if host or (any of) addrs is within specified subnet, otherwise False
    """
    try:
        cidr = ipaddress.ip_network(cidr)
    except ValueError:
        log.error("Invalid CIDR '%s'", cidr)
        return False

    if addr is None:
        addr = ip_addrs()
        addr.extend(ip_addrs6())
    elif not isinstance(addr, (list, tuple)):
        addr = (addr, )

    return any(ipaddress.ip_address(item) in cidr for item in addr)
Esempio n. 5
0
def _generate_minion_id():
    '''
    Get list of possible host names and convention names.

    :return:
    '''

    # There are three types of hostnames:
    # 1. Network names. How host is accessed from the network.
    # 2. Host aliases. They might be not available in all the network or only locally (/etc/hosts)
    # 3. Convention names, an internal nodename.

    class DistinctList(list):
        '''
        List, which allows one to append only distinct objects.
        Needs to work on Python 2.6, because of collections.OrderedDict only since 2.7 version.
        Override 'filter()' for custom filtering.
        '''
        localhost_matchers = [
            r'localhost.*', r'ip6-.*', r'127[.]\d', r'0\.0\.0\.0', r'::1.*',
            r'ipv6-.*', r'fe00::.*', r'fe02::.*', r'1.0.0.*.ip6.arpa'
        ]

        def append(self, p_object):
            if p_object and p_object not in self and not self.filter(p_object):
                super(self.__class__, self).append(p_object)
            return self

        def extend(self, iterable):
            for obj in iterable:
                self.append(obj)
            return self

        def filter(self, element):
            'Returns True if element needs to be filtered'
            for rgx in self.localhost_matchers:
                if re.match(rgx, element):
                    return True

        def first(self):
            return self and self[0] or None

    hostname = socket.gethostname()

    hosts = DistinctList().append(
        hubblestack.utils.stringutils.to_unicode(
            socket.getfqdn(
                hubblestack.utils.stringutils.to_bytes(hostname)))).append(
                    platform.node()).append(hostname)
    if not hosts:
        try:
            for a_nfo in socket.getaddrinfo(hosts.first() or 'localhost', None,
                                            socket.AF_INET, socket.SOCK_RAW,
                                            socket.IPPROTO_IP,
                                            socket.AI_CANONNAME):
                if len(a_nfo) > 3:
                    hosts.append(a_nfo[3])
        except socket.gaierror:
            log.warning(
                'Cannot resolve address {addr} info via socket: {message}'.
                format(addr=hosts.first() or 'localhost (N/A)',
                       message=socket.gaierror))
    # Universal method for everywhere (Linux, Slowlaris, Windows etc)
    for f_name in ('/etc/hostname', '/etc/nodename', '/etc/hosts',
                   r'{win}\system32\drivers\etc\hosts'.format(
                       win=os.getenv('WINDIR'))):
        try:
            with hubblestack.utils.files.fopen(f_name) as f_hdl:
                for line in f_hdl:
                    line = hubblestack.utils.stringutils.to_unicode(line)
                    hst = line.strip().split('#')[0].strip().split()
                    if hst:
                        if hst[0][:4] in ('127.', '::1') or len(hst) == 1:
                            hosts.extend(hst)
        except IOError:
            pass

    # include public and private ipaddresses
    return hosts.extend([
        addr for addr in ip_addrs()
        if not ipaddress.ip_address(addr).is_loopback
    ])
Esempio n. 6
0
def parse_resolv(src='/etc/resolv.conf'):
    '''
    Parse a resolver configuration file (traditionally /etc/resolv.conf)
    '''

    nameservers = []
    ip4_nameservers = []
    ip6_nameservers = []
    search = []
    sortlist = []
    domain = ''
    options = []

    try:
        with hubblestack.utils.files.fopen(src) as src_file:
            # pylint: disable=too-many-nested-blocks
            for line in src_file:
                line = hubblestack.utils.stringutils.to_unicode(
                    line).strip().split()

                try:
                    (directive, arg) = (line[0].lower(), line[1:])
                    # Drop everything after # or ; (comments)
                    arg = list(
                        itertools.takewhile(lambda x: x[0] not in ('#', ';'),
                                            arg))
                    if directive == 'nameserver':
                        addr = arg[0]
                        try:
                            ip_addr = ipaddress.ip_address(addr)
                            version = ip_addr.version
                            ip_addr = str(ip_addr)
                            if ip_addr not in nameservers:
                                nameservers.append(ip_addr)
                            if version == 4 and ip_addr not in ip4_nameservers:
                                ip4_nameservers.append(ip_addr)
                            elif version == 6 and ip_addr not in ip6_nameservers:
                                ip6_nameservers.append(ip_addr)
                        except ValueError as exc:
                            log.error('%s: %s', src, exc)
                    elif directive == 'domain':
                        domain = arg[0]
                    elif directive == 'search':
                        search = arg
                    elif directive == 'sortlist':
                        # A sortlist is specified by IP address netmask pairs.
                        # The netmask is optional and defaults to the natural
                        # netmask of the net. The IP address and optional
                        # network pairs are separated by slashes.
                        for ip_raw in arg:
                            try:
                                ip_net = ipaddress.ip_network(ip_raw)
                            except ValueError as exc:
                                log.error('%s: %s', src, exc)
                            else:
                                if '/' not in ip_raw:
                                    # No netmask has been provided, guess
                                    # the "natural" one
                                    if ip_net.version == 4:
                                        ip_addr = str(ip_net.network_address)
                                        # pylint: disable=protected-access
                                        mask = hubblestack.utils.network.natural_ipv4_netmask(
                                            ip_addr)
                                        ip_net = ipaddress.ip_network(
                                            '{0}{1}'.format(ip_addr, mask),
                                            strict=False)
                                    if ip_net.version == 6:
                                        # TODO
                                        pass

                                if ip_net not in sortlist:
                                    sortlist.append(ip_net)
                    elif directive == 'options':
                        # Options allows certain internal resolver variables to
                        # be modified.
                        if arg[0] not in options:
                            options.append(arg[0])
                except IndexError:
                    continue

        if domain and search:
            # The domain and search keywords are mutually exclusive.  If more
            # than one instance of these keywords is present, the last instance
            # will override.
            log.debug(
                '%s: The domain and search keywords are mutually exclusive.',
                src)

        return {
            'nameservers': nameservers,
            'ip4_nameservers': ip4_nameservers,
            'ip6_nameservers': ip6_nameservers,
            'sortlist': [ip.with_netmask for ip in sortlist],
            'domain': domain,
            'search': search,
            'options': options
        }
    except IOError:
        return {}