Se fier au module "struct" peut causer des problèmes avec les tailles d'endian-ness et de type, et n'est tout simplement pas nécessaire. Socket.inet_aton () non plus. Python fonctionne très bien avec les adresses IP à quatre points:
def ip_to_u32(ip):
return int(''.join('%02x' % int(d) for d in ip.split('.')), 16)
Je dois faire une correspondance IP sur chaque appel de socket accept (), contre un ensemble complet de réseaux source autorisés, donc je précalcule les masques et les réseaux, sous forme d'entiers:
SNS_SOURCES = [
# US-EAST-1
'207.171.167.101',
'207.171.167.25',
'207.171.167.26',
'207.171.172.6',
'54.239.98.0/24',
'54.240.217.16/29',
'54.240.217.8/29',
'54.240.217.64/28',
'54.240.217.80/29',
'72.21.196.64/29',
'72.21.198.64/29',
'72.21.198.72',
'72.21.217.0/24',
]
def build_masks():
masks = [ ]
for cidr in SNS_SOURCES:
if '/' in cidr:
netstr, bits = cidr.split('/')
mask = (0xffffffff << (32 - int(bits))) & 0xffffffff
net = ip_to_u32(netstr) & mask
else:
mask = 0xffffffff
net = ip_to_u32(cidr)
masks.append((mask, net))
return masks
Ensuite, je peux voir rapidement si une adresse IP donnée se trouve dans l'un de ces réseaux:
ip = ip_to_u32(ipstr)
for mask, net in cached_masks:
if ip & mask == net:
# matched!
break
else:
raise BadClientIP(ipstr)
Aucune importation de module n'est nécessaire et le code est très rapide à faire correspondre.