def testIpMaskToInts(self): """Test IpMaskToInts().""" mask_str = '1.2.3.4/8' ip_mask_ints_expected = ( self._socket_ip2int('1.2.3.4'), self._socket_ip2int('255.0.0.0'), ) self.assertEqual(ip_mask_ints_expected, ipcalc.IpMaskToInts(mask_str))
def IpInList(cls, key_name, ip): """Check whether IP is in serialized IP/mask list in key_name. The KeyValueCache entity at key_name is expected to have a text_value which is in util.Serialize() form. The deserialized structure looks like [ "200.0.0.0/24", "10.0.0.0/8", etc ... ] Note that this function is not IPv6 safe and will always return False if the input ip is IPv6 format. Args: key_name: str, like 'auth_bad_ip_blocks' ip: str, like '127.0.0.1' Returns: True if the ip is inside a mask in the list, False if not """ if not ip: return False # lenient response # TODO(user): Once the underlying util.Ip* methods support ipv6 # this method can go away. Until then, this stops all of the churn # and exits early. if ip.find(':') > -1: # ipv6 return False try: ip_blocks_str = cls.MemcacheWrappedGet(key_name, 'text_value') if not ip_blocks_str: return False ip_blocks = util.Deserialize(ip_blocks_str) except (util.DeserializeError, db.Error): logging.exception('IpInList(%s)', ip) return False # lenient response # Note: The method below, parsing a serialized list of networks # expressed as strings, might seem silly. But the total time to # deserialize and translate the strings back into IP network/mask # integers is actually faster than storing them already split, e.g. a # list of 2 item lists (network,mask). Apparently JSON isn't as # efficient at parsing ints or nested lists. # # (pickle is 2X+ faster but not secure & deprecated inside util module) ip_int = ipcalc.IpToInt(ip) for ip_mask_str in ip_blocks: ip_mask = ipcalc.IpMaskToInts(ip_mask_str) if (ip_int & ip_mask[1]) == ip_mask[0]: return True return False