def convert_to_ipv4(source, stype='d'): """ 转换为常见的ip地址 :param source: 被转换的值 :param stype: 制定``source`` 参数的类型 * 二进制 -- 'b' * 八进制 -- 'o' * 十进制 -- 'd' * 十六进制 -- 'x' * 一个十进制整数 -- 'int' :return: 一个十进制点分ip """ base_map = { 'b': 2, 'o': 8, 'd': 10, 'x': 16, } if stype == 'int': source = format(int(source), 'b') stype = 'b' if '.' not in source: seg_len = len(format(255, stype)) max_len = seg_len * 4 if len(source) <= max_len: _source = ('0' * max_len + source)[-max_len:] _ipv4_segs = [ _source[ix:ix + seg_len] for ix in range(0, max_len, seg_len) ] source = '.'.join(_ipv4_segs) else: raise ValueError('len of source error') if stype in base_map: segs = [ str(int(seg, base=base_map[stype])) for seg in source.split('.') ] ipv4_str = '.'.join(segs) check = is_string_ipv4(ipv4_str) if check[0]: return check[1] else: raise ValueError('invalid ip for source: %s' % source) else: raise ValueError('invalid ftype arg: %s' % stype)
def is_ipv6_seg(seg): try: return all([ -1 < int(_si, base=16) < 65536 and _si.isalnum() and len(_si.strip()) < 5 for _si in seg if _si != '' ]) except ValueError: return False
def check(self): if isinstance(self._ip, (list, tuple)): self._ip = '.'.join([str(i) for i in self._ip]) check_res = is_string_ipv4(self._ip) if check_res[0]: self._ip = check_res[1] self._ip_list = [int(i) for i in self._ip.split('.')] else: raise ValueError('not a valid ip')
def check(ip_mask): sub_net_ip, mask = ip_mask.split('/') ip = IPV4(sub_net_ip) try: mask_code = int(mask) except ValueError: mask_code = subnet_mask_to_cidr_mask(mask) if 0 <= mask_code <= 32: return ip.ip_str, mask_code raise ValueError('%s is not a valid cidr.' % ip_mask)
def cidr_mask_to_ip_int(mask_num): """ 掩码位数转换为整数值 :param mask_num: 掩码位数, 如 16 :return: 一个整数值 """ cidr_num = int(mask_num) if 0 < cidr_num <= 32: return ((1 << cidr_num) - 1) << (32 - cidr_num) raise ValueError('% is not valid cidr code.' % cidr_num)
def subnet_mask_to_cidr_mask(subnet_mask): """ 点分掩码转换为掩码位数 :param subnet_mask: 十进制点分ipv4地址 :return: 掩码位数,一个整数,如16 """ subnet_bin = ipv4_format(subnet_mask, ftype='b', separator='') cidr_mask, _, check = subnet_bin.partition('0') if int(check or '0', base=2): raise ValueError('%s is not valid subnet mask.' % subnet_mask) return len(cidr_mask)
def ipv4_format(ipv4_str, ftype='b', **kwargs): """ ip格式化转换 :param ipv4_str: :param ftype: 格式化后值的类型 * int: 一个整数 * b: 二进制 * o: 八进制 * x: 十六进制 :param kwargs: * filling: 是否以0填充, 默认为True * separator: 分隔符,默认为 '.' :return: 格式化后的值 """ ipv4_check = is_string_ipv4(ipv4_str) if ipv4_check[0]: ipv4_str = ipv4_check[1] ip_segs = ipv4_str.split('.') if ftype == 'int': dec_value = 0 for i, ip_seg in enumerate(ip_segs): dec_value += int(ip_seg) << (24 - 8 * i) return dec_value elif ftype in ('b', 'o', 'x'): res = [] for ip_seg in ip_segs: seg_str = format(int(ip_seg), ftype) if kwargs.get('filling', True): seg_str = '0' * (len(format(255, ftype)) - len(seg_str)) + seg_str res.append(seg_str) separator = kwargs.get('separator', '.') return separator.join(res) else: raise ValueError('ftype: %s not support' % ftype) raise ValueError('%s not a normal IP.' % ipv4_str)
def is_ip_in_subnet(ipv4_str, subnet_str): """ 判断ip是否在子网中 :param ipv4_str: 一个十进制点分ipv4地址 :param subnet_str: 10.10.10.10/16 :return: """ cidr = CIDR(subnet_str) sub_net_ip, mask_code = cidr.ip, cidr.mask_code res = (ipv4_format(ipv4_str, ftype='int') & cidr_mask_to_ip_int(int(mask_code)) == ipv4_format(sub_net_ip, ftype='int')) return res
def is_string_ipv4(string): """ 判断一个字符串是否符合ipv4地址规则 :param string: 输入的字符串 :return: 一个元祖: (逻辑结果, ipv4 string 或 None) """ string = string.strip() seg = string.split('.') if len(seg) != 4: return False, None else: try: if not all([_si.isdigit() and -1 < int(_si) < 256 for _si in seg]): return False, None return True, string except ValueError: return False, None