import socket,struct
def makeMask(n):
"return a mask of n bits as a long integer"
return (2L<<n-1) - 1
def dottedQuadToNum(ip):
"convert decimal dotted quad string to long integer"
return struct.unpack('L',socket.inet_aton(ip))[0]
def networkMask(ip,bits):
"Convert a network address to a long integer"
return dottedQuadToNum(ip) & makeMask(bits)
def addressInNetwork(ip,net):
"Is an address in a network"
return ip & net == net
address = dottedQuadToNum("192.168.1.1")
networka = networkMask("10.0.0.0",24)
networkb = networkMask("192.168.0.0",24)
print (address,networka,networkb)
print addressInNetwork(address,networka)
print addressInNetwork(address,networkb)
产出:
False
True
如果你只想要一个接受字符串的函数,它应该是这样的:
import socket,struct
def addressInNetwork(ip,net):
"Is an address in a network"
ipaddr = struct.unpack('L',socket.inet_aton(ip))[0]
netaddr,bits = net.split('/')
netmask = struct.unpack('L',socket.inet_aton(netaddr))[0] & ((2L<<int(bits)-1) - 1)
return ipaddr & netmask == netmask
>>> import ipaddress
>>> ipaddress.ip_address('192.168.0.1') in ipaddress.ip_network('192.168.0.0/24')
True
如果希望以这种方式计算 IP 地址的 很多,可能需要预先计算网络掩码,如
n = ipaddress.ip_network('192.0.0.0/16')
netw = int(n.network_address)
mask = int(n.netmask)
然后,对于每个地址,使用
a = int(ipaddress.ip_address('192.0.43.10'))
a = struct.unpack('!I', socket.inet_pton(socket.AF_INET, '192.0.43.10'))[0]
a = struct.unpack('!I', socket.inet_aton('192.0.43.10'))[0] # IPv4 only
>>> from netaddr import all_matching_cidrs
>>> all_matching_cidrs("212.11.70.34", ["192.168.0.0/24","212.11.64.0/19"] )
[IPNetwork('212.11.64.0/19')]
这个方法的用法如下:
>>> help(all_matching_cidrs)
Help on function all_matching_cidrs in module netaddr.ip:
all_matching_cidrs(ip, cidrs)
Matches an IP address or subnet against a given sequence of IP addresses and subnets.
@param ip: a single IP address or subnet.
@param cidrs: a sequence of IP addresses and/or subnets.
@return: all matching IPAddress and/or IPNetwork objects from the provided
sequence, an empty list if there was no match.
#This works properly without the weird byte by byte handling
def addressInNetwork(ip,net):
'''Is an address in a network'''
# Convert addresses to host order, so shifts actually make sense
ip = struct.unpack('>L',socket.inet_aton(ip))[0]
netaddr,bits = net.split('/')
netaddr = struct.unpack('>L',socket.inet_aton(netaddr))[0]
# Must shift left an all ones value, /32 = zero shift, /0 = 32 shift left
netmask = (0xffffffff << (32-int(bits))) & 0xffffffff
# There's no need to mask the network address, as long as its a proper network address
return (ip & netmask) == netaddr
def addressInNetwork(ip,net):
"Is an address in a network"
ipaddr = struct.unpack('>L',socket.inet_aton(ip))[0]
netaddr,bits = net.split('/')
netmask = struct.unpack('>L',socket.inet_aton(netaddr))[0]
ipaddr_masked = ipaddr & (4294967295<<(32-int(bits))) # Logical AND of IP address and mask will equal the network address if it matches
if netmask == netmask & (4294967295<<(32-int(bits))): # Validate network address is valid for mask
return ipaddr_masked == netmask
else:
print "***WARNING*** Network",netaddr,"not valid with mask /"+bits
return ipaddr_masked == netmask
import socket
import struct
def makeMask(n):
"return a mask of n bits as a long integer"
return (2L<<n-1) - 1
def dottedQuadToNum(ip):
"convert decimal dotted quad string to long integer"
return struct.unpack('L',socket.inet_aton(ip))[0]
def addressInNetwork(ip,net,netmask):
"Is an address in a network"
print "IP "+str(ip) + " NET "+str(net) + " MASK "+str(netmask)+" AND "+str(ip & netmask)
return ip & netmask == net
def humannetcheck(ip,net):
address=dottedQuadToNum(ip)
netaddr=dottedQuadToNum(net.split("/")[0])
netmask=makeMask(long(net.split("/")[1]))
return addressInNetwork(address,netaddr,netmask)
print humannetcheck("192.168.0.1","192.168.0.0/24");
print humannetcheck("192.169.0.1","192.168.0.0/24");
def ipToInt(ip):
o = map(int, ip.split('.'))
res = (16777216 * o[0]) + (65536 * o[1]) + (256 * o[2]) + o[3]
return res
def isIpInSubnet(ip, ipNetwork, maskLength):
ipInt = ipToInt(ip)#my test ip, in int form
maskLengthFromRight = 32 - maskLength
ipNetworkInt = ipToInt(ipNetwork) #convert the ip network into integer form
binString = "{0:b}".format(ipNetworkInt) #convert that into into binary (string format)
chopAmount = 0 #find out how much of that int I need to cut off
for i in range(maskLengthFromRight):
if i < len(binString):
chopAmount += int(binString[len(binString)-1-i]) * 2**i
minVal = ipNetworkInt-chopAmount
maxVal = minVal+2**maskLengthFromRight -1
return minVal <= ipInt and ipInt <= maxVal
def ip_matches_network(self, network, ip):
"""
'{:08b}'.format(254): Converts 254 in a string of its binary representation
ip_bits[:net_mask] == net_ip_bits[:net_mask]: compare the ip bit streams
:param network: string like '192.168.33.0/24'
:param ip: string like '192.168.33.1'
:return: if ip matches network
"""
net_ip, net_mask = network.split('/')
net_mask = int(net_mask)
ip_bits = ''.join('{:08b}'.format(int(x)) for x in ip.split('.'))
net_ip_bits = ''.join('{:08b}'.format(int(x)) for x in net_ip.split('.'))
# example: net_mask=24 -> compare strings at position 0 to 23
return ip_bits[:net_mask] == net_ip_bits[:net_mask]
import ipaddress
ipaddress.IPv4Address('192.168.1.1') in ipaddress.IPv4Network('192.168.0.0/24')
ipaddress.IPv4Address('192.168.1.1') in ipaddress.IPv4Network('192.168.0.0/16')
from netaddr import IPNetwork, IPAddress
def network_has_ip(network, ip):
if not isinstance(network, IPNetwork):
raise Exception("network parameter must be {0} instance".format(IPNetwork.__name__))
if not isinstance(ip, IPAddress):
raise Exception("ip parameter must be {0} instance".format(IPAddress.__name__))
return (network.cidr.ip.value & network.netmask.value) == (ip.value & network.netmask.value)
为了只测试一个 IP,你可以使用子网掩码 /32,意思是“只有这个 IP 地址”作为子网,或者你可以将 IP 地址传递给 IPv4Nework或 IPv6Nework构造函数,他们会为你返回一个子网值。
举个例子:
from ipaddress import IPv4Network, IPv4Address
# Store IP Address as variable
>>> myip = IPv4Address('192.168.0.1')
>>> myip
IPv4Address('192.168.0.1')
# This treats the IP as a subnet
>>> myip_subnet = IPv4Network(myip)
>>> myip_subnet
IPv4Network('192.168.0.1/32')
# The other subnet to test membership against
>>> other_subnet = IPv4Network('192.168.0.0/24')
>>> other_subnet
IPv4Network('192.168.0.0/24')
# Now we can test
>>> myip_subnet.subnet_of(other_subnet)
True
Python 中是否有用于 IP 地址操作的通用工具
如主机查找,IP 地址到整型,网络地址与网络掩码到
希望在2.5版本的标准 Python 库中。
def subnet_lookup(subnet: str, netmask: str, ip_address: str):
"""
:param subnet: subnet to test against (as string)
:param netmask: mask of subnet
:param ip_address: ip to test against subnet and mask
:return True if a match; False if not a match
Steps:
1) convert entire subnet into one binary word
2) convert entire mask into one binary word
3) determine bcast from comparing subnet and mask
4) convert entire ip_address into one binary word
5) convert entire subnet into decimal
6) convert entire bcast into decimal
7) convert entire ip_address into decimal
8) determine if ip_address falls between subnet and bcast using range(); returns True if yes, False if no
"""
def convert_whole_to_bin(whole):
ip_dec_list = whole.split(".")
ip_bin_str = ""
for ip in ip_dec_list:
binary = dec_to_bin(int(ip))
ip_bin_str += binary
return ip_bin_str
def dec_to_bin(decimal_octet: int):
binary = bin(decimal_octet).replace("0b", "")
return binary.rjust(8, '0')
def split_binary_into_list(binary_octet: str):
bin_list = []
for s in binary_octet:
bin_list.append(s)
return bin_list
def determine_bcast(subnet, netmask):
subnet_split = split_binary_into_list(subnet)
netmask_split = split_binary_into_list(netmask)
bcast_list = []
for subnet, mask in zip(subnet_split, netmask_split):
if mask != '0':
bcast_list.append(subnet)
else:
bcast_list.append('1')
bcast_bin = "".join(bcast_list)
return bcast_bin
def bin_to_dec(binary_single_word: str):
decimal = int(binary_single_word, 2)
return decimal
def subnet_lookup(ip_address, subnet, bcast):
return ip_address in range(subnet, bcast + 1)
# 1) convert entire subnet into one binary word
subnet_single_bin = convert_whole_to_bin(whole=subnet)
# 2) convert entire mask into one binary word
mask_single_bin = convert_whole_to_bin(whole=netmask)
# 3) determine bcast from comparing subnet and mask
bcast_single_bin = determine_bcast(subnet=subnet_single_bin, netmask=mask_single_bin)
# 4) convert entire ip_address into one binary word
ip_address_single_bin = convert_whole_to_bin(whole=ip_address)
# 5) convert entire subnet into decimal
subnet_single_dec = bin_to_dec(binary_single_word=subnet_single_bin)
# 6) convert entire bcast into decimal
bcast_single_dec = bin_to_dec(binary_single_word=bcast_single_bin)
# 7) convert entire ip_address into decimal
ip_address_single_dec = bin_to_dec(binary_single_word=ip_address_single_bin)
# 8) determine if ip_address falls between subnet and bcast; returns True if yes, False if no
lookup_result = subnet_lookup(ip_address=ip_address_single_dec, subnet=subnet_single_dec, bcast=bcast_single_dec)
return lookup_result
# Testing:
subnet = "172.16.0.0"
netmask = "255.255.0.0"
ip_address = "172.16.255.255"
result = subnet_lookup(subnet=subnet, netmask=netmask, ip_address=ip_address)
print(result)