मैं यह कैसे देख सकता हूं कि पायथन में एक नेटवर्क में एक आईपी है?


100

एक आईपी पते (192.168.0.1 कहते हैं) को देखते हुए, पायथन में नेटवर्क (यदि 192.168.0.0/24) कहूं तो मैं कैसे जांच करूं?

क्या आईपी पता हेरफेर के लिए पायथन में सामान्य उपकरण हैं? होस्ट लुकअप, आईपी ऐडड्रेस टू इंट, नेटवर्क एड्रेस के साथ नेटमास्क के साथ इंट वगैरह जैसी सामग्री? 2.5 के लिए मानक पायथन पुस्तकालय में उम्मीद है।


यह प्रश्न बहुत पुराने 2.x उत्तरों के लिए एक विहित कैनोनिकल जैसा प्रतीत होता है, लेकिन 3.x के लिए अप्रचलित है। देखें कि "पायथन / पंडों की आईपी पते / सीआईडीआर की तुलना" के लिए कैनोनिकल कैसे व्यवस्थित करें और असाइन करें?
smci

@smci मैं क्यों नहीं देख रहा हूँ; stackoverflow.com/a/1004527/1709587 पर फ़िहाग का जवाब पायथन 3 के लिए एक अच्छा जवाब है और 2014 से यहाँ है। मैंने आपका उत्तर वापस ले लिया है जिसने उस उत्तर को अमान्य कर दिया है।
मार्क एमी

@Staale - आपको अपने उत्तर को यहां अपडेट करना चाहिए जिसमें महत्वपूर्ण बग नहीं है । अन्य उत्तर बिलियन लाइब्रेरीज़ का उपयोग करते हैं, जो कि 1/10 में एक ही चीज़ को पूरा करने के लिए है, बिना किसी बग के।
एडिसन

जवाबों:


30

यह लेख दिखाता है कि आप इसे बहुत अधिक अतिरिक्त प्रयास के बिना socketऔर structमॉड्यूल के साथ कर सकते हैं । मैंने लेख को इस तरह से थोड़ा जोड़ा:

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

8
इसके अतिरिक्त, struct.unpack ('L', socket.inet_aton (ip)) [0] आर्किटेक्चर पर विफल हो जाएगा जहां 'L' 4 बाइट्स से कुछ अलग करने के लिए अनपैक्स करता है, चाहे एंडियननेस की परवाह किए बिना।
राफेल डाउगर्ड

5
रफाल की टिप्पणी पर जारी, 64-बिट पायथन दुभाषिया पर काम करने के लिए, इस प्रश्न के साथ पंक्ति को प्रतिस्थापित करें:return struct.unpack('<L',socket.inet_aton(ip))[0]
नाइटविट

11
मुझे लगता है कि आपके समाधान में एक गंभीर बग है: addressInNetwork('172.7.1.1', '172.3.0.0/16') -> True(मैंने अपनी 64 बिट ओएस में 'एल' को '<L' में बदल दिया)
ताहा जहांगीर

20
चेतावनी: इस समाधान में एक गंभीर बग है:addressInNetwork('172.7.1.1', '172.3.0.0/16') -> True
ताहा जहाँगीर

6
इस उत्तर में एक बग है । उत्तर देखें: stackoverflow.com/questions/819355/…
देबांशु कुंडू

156

मुझे उस के लिए netaddr का उपयोग करना पसंद है:

from netaddr import CIDR, IP

if IP("192.168.0.1") in CIDR("192.168.0.0/24"):
    print "Yay!"

जैसा कि arno_v ने टिप्पणियों में बताया है, netaddr का नया संस्करण इस तरह से है:

from netaddr import IPNetwork, IPAddress
if IPAddress("192.168.0.1") in IPNetwork("192.168.0.0/24"):
    print "Yay!"

>>> netaddr.all_matching_cidrs ("192.168.0.1", ["192.168.0.0/24","212.11.64.0/19"]] [IPNetwork ('192.168.0.0/24')]

22
या नए संस्करण में: netaddr इंपोर्ट से IPNetwork, IPAddress IPAddress ("192.168.0.1") IPNetwork ("192.168.0.0/24") में
arno_v

140

IPaddress का उपयोग करना ( stdlib में 3.3 के बाद से , PyPi पर 2.6 / 2.7 के लिए ):

>>> import ipaddress
>>> ipaddress.ip_address('192.168.0.1') in ipaddress.ip_network('192.168.0.0/24')
True

यदि आप इस तरह से बहुत सारे आईपी पते का मूल्यांकन करना चाहते हैं , तो आप शायद नेटमास्क अपफ्रंट की गणना करना चाहेंगे

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

अंत में, आप बस जाँच कर सकते हैं:

in_network = (a & mask) == netw

2
खबरदार, अजगर-आइपैड ने हमारे लिए काफी धीमी गति से व्यवहार किया, इसलिए यह कुछ मामलों के लिए अनुपयुक्त हो सकता है , जहां अक्सर बहुत सारे कंपार्टमेंट की आवश्यकता होती है। YMMV, इसलिए खुद को बेंचमार्क करें।
शराबी जुआन

कुछ संस्करणों में, आपको एक अजगर स्ट्रिंग प्रकार के बजाय एक यूनिकोड स्ट्रिंग की आपूर्ति करने की आवश्यकता हो सकती है ipaddress.ip_address(u'192.168.0.1') in ipaddress.ip_network(u'192.168.0.0/24')
मूंडोगी

1
मैं चिंतित था कि यह विधि नेटवर्क में पतों की सूची से अधिक परेशान थी, लेकिन ipaddress मॉड्यूल __contains__नेटवर्क और प्रसारण पतों के पूर्णांक निरूपण की तुलना करके इसे कुशल तरीके से करने की विधि को ओवरराइड करता है, इसलिए यदि आपकी चिंता है तो आराम करें। ।
avatarofhope2

24

पायथन 3 के लिए

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')

आउटपुट:

False
True

1
मानक लिबास चतुर बिटवाइज़ जाँच का उपयोग करता है इसलिए यह यहाँ सबसे इष्टतम समाधान है। github.com/python/cpython/blob/3.8/Lib/ipaddress.py#L690
रॉकेट्स स्पेसर

10

यह कोड मेरे लिए लिनक्स x86 पर काम कर रहा है। मैंने वास्तव में धीरज वाले मुद्दों पर कोई विचार नहीं दिया है, लेकिन मैंने इसे "ipaddr" मॉड्यूल के खिलाफ 200K IP पते का उपयोग करके 8 अलग-अलग नेटवर्क स्ट्रिंग्स के खिलाफ परीक्षण किया है, और ipaddr के परिणाम इस कोड के समान हैं।

def addressInNetwork(ip, net):
   import socket,struct
   ipaddr = int(''.join([ '%02x' % int(x) for x in ip.split('.') ]), 16)
   netstr, bits = net.split('/')
   netaddr = int(''.join([ '%02x' % int(x) for x in netstr.split('.') ]), 16)
   mask = (0xffffffff << (32 - int(bits))) & 0xffffffff
   return (ipaddr & mask) == (netaddr & mask)

उदाहरण:

>>> print addressInNetwork('10.9.8.7', '10.9.1.0/16')
True
>>> print addressInNetwork('10.9.8.7', '10.9.1.0/24')
False

अच्छा और तेज। कुछ सरल तर्क संचालन के लिए पुस्तकालय की आवश्यकता नहीं है।
क्रिस कोस्टोन

7

Python3 ipaddress का उपयोग करना :

import ipaddress

address = ipaddress.ip_address("192.168.0.1")
network = ipaddress.ip_network("192.168.0.0/16")

print(network.supernet_of(ipaddress.ip_network(f"{address}/{address.max_prefixlen}")))

व्याख्या

आप आईपी ​​एड्रेस को नेटवर्क के रूप में सबसे बड़े संभावित नेटमास्क ( /32आईपीवी 4 के लिए, /128आईपीवी 6 के लिए) के रूप में सोच सकते हैं

जांच की जा रही है कि क्या 192.168.0.1में है 192.168.0.0/16अनिवार्य रूप से जाँच के रूप में ही है, चाहे 192.168.0.1/32की एक सबनेट है192.168.0.0/16


... यकीन नहीं है कि यह जवाब शीर्ष (अभी तक) पर क्यों नहीं है।
फिलिप्पो विटाले

6

मैंने डेव वेब के समाधान की कोशिश की, लेकिन कुछ समस्याओं का सामना किया:

सबसे मौलिक रूप से - एक मैच को मास्क के साथ आईपी पते को एंड्रॉइड द्वारा जांचना चाहिए, फिर परिणाम की जांच करके नेटवर्क पते से बिल्कुल मिलान किया जाना चाहिए। नेटवर्क पते के साथ आईपी पते की तरह नहीं किया गया था।

मैंने यह भी देखा कि सिर्फ एंडियन व्यवहार को नजरअंदाज करते हुए यह मान लेना कि निरंतरता आपको बचाएगी केवल ऑक्टेट सीमाओं (/ 24, / 16) पर मास्क के लिए काम करेगी। अन्य मास्क (/ 23, / 21) को सही ढंग से काम करने के लिए मैंने "कमांड कमांड" से अधिक जोड़ा और बाइनरी मास्क बनाने के लिए कोड को बदलकर सभी "1" के साथ शुरू किया और (32-मास्क) छोड़ दिया )।

अंत में, मैंने एक साधारण जाँच जोड़ी कि नेटवर्क पता मास्क के लिए मान्य है और यदि ऐसा नहीं है तो बस एक चेतावनी प्रिंट करें।

यहाँ परिणाम है:

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

यह 64-बिट पर मज़बूती से काम करने के लिए प्रतीत होता है ('L' विफल रहता है क्योंकि मान 32-बिट है) और समझदार क्रम में मान लौटाता है (ipaddr 192.168.0.1 के लिए 0xC0A80001 होगा)। यह "192.168.0.1/24" के साथ "192.168.0.1" (मानक नहीं, लेकिन संभव और आसानी से
सुधारा

Python 2.4
xlash

6

जब वे आवश्यक नहीं हैं, तो मैं मॉड्यूल का उपयोग करने का प्रशंसक नहीं हूं। इस नौकरी के लिए केवल सरल गणित की आवश्यकता होती है, इसलिए यहां कार्य करने का मेरा सरल कार्य है:

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

फिर इसका उपयोग करने के लिए:

>>> print isIpInSubnet('66.151.97.0', '66.151.97.192',24) 
True
>>> print isIpInSubnet('66.151.97.193', '66.151.97.192',29) 
True
>>> print isIpInSubnet('66.151.96.0', '66.151.97.192',24) 
False
>>> print isIpInSubnet('66.151.97.0', '66.151.97.192',29) 

यही है, यह शामिल मॉड्यूल के साथ ऊपर दिए गए समाधानों की तुलना में बहुत तेज है।


{TypeError}'map' object is not subscriptable। आप एक की जरूरत o = list(o)के बादo = map(int, ip.split('.'))
gies0r

5

2.5 के लिए मानक पुस्तकालय में नहीं है, लेकिन ipaddr यह बहुत आसान बनाता है। मेरा मानना ​​है कि यह ipaddress नाम से 3.3 में है।

import ipaddr

a = ipaddr.IPAddress('192.168.0.1')
n = ipaddr.IPNetwork('192.168.0.0/24')

#This will return True
n.Contains(a)

यह अब तक के सभी असंख्य विकल्पों में से मेरा पसंदीदा है (टिप्पणी के समय, 2017)। धन्यवाद!
rsaw

5

स्वीकृत उत्तर काम नहीं करता ... जो मुझे गुस्सा दिला रहा है। मास्क पीछे की ओर है और किसी भी बिट के साथ काम नहीं करता है जो एक साधारण 8 बिट ब्लॉक नहीं है (जैसे / 24)। मैंने उत्तर को अनुकूलित किया, और यह अच्छी तरह से काम करता है।

    import socket,struct

    def addressInNetwork(ip, net_n_bits):  
      ipaddr = struct.unpack('!L', socket.inet_aton(ip))[0]
      net, bits = net_n_bits.split('/')
      netaddr = struct.unpack('!L', socket.inet_aton(net))[0]
      netmask = (0xFFFFFFFF >> int(bits)) ^ 0xFFFFFFFF
      return ipaddr & netmask == netaddr

यहाँ एक फ़ंक्शन है जो मास्किंग की कल्पना करने में मदद करने के लिए एक डॉटेड बाइनरी स्ट्रिंग देता है .. जैसे ipcalcआउटपुट।

    def bb(i):
     def s = '{:032b}'.format(i)
     def return s[0:8]+"."+s[8:16]+"."+s[16:24]+"."+s[24:32]

उदाहरण के लिए:

अजगर का स्क्रीन शॉट


4

मार्क का कोड लगभग सही है। कोड का एक पूर्ण संस्करण है -

def addressInNetwork3(ip,net):
    '''This function allows you to check if on IP belogs to a Network'''
    ipaddr = struct.unpack('=L',socket.inet_aton(ip))[0]
    netaddr,bits = net.split('/')
    netmask = struct.unpack('=L',socket.inet_aton(calcDottedNetmask(int(bits))))[0]
    network = struct.unpack('=L',socket.inet_aton(netaddr))[0] & netmask
    return (ipaddr & netmask) == (network & netmask)

def calcDottedNetmask(mask):
    bits = 0
    for i in xrange(32-mask,32):
        bits |= (1 << i)
    return "%d.%d.%d.%d" % ((bits & 0xff000000) >> 24, (bits & 0xff0000) >> 16, (bits & 0xff00) >> 8 , (bits & 0xff))

स्पष्ट रूप से ऊपर के समान स्रोतों से ...

एक बहुत ही महत्वपूर्ण नोट यह है कि पहले कोड में एक छोटी सी गड़बड़ है - आईपी पता 255.255.255.255 भी किसी भी सबनेट के लिए वैध आईपी के रूप में दिखाई देता है। मेरे पास काम करने के लिए इस कोड को रखने का एक सही समय था और सही उत्तर के लिए मार्क के लिए धन्यवाद।


आजमाया और परखा गया। इस पृष्ठ पर सभी सॉकेट / संरचना के उदाहरणों से यह एकमात्र सही है
ज़बज़मैन

4

"संरचना" मॉड्यूल पर भरोसा करने से एंडियन-नेस और प्रकार के आकार के साथ समस्याएं हो सकती हैं, और बस जरूरत नहीं है। और न ही socket.inet_aton () है। पायथन डॉटेड-क्वाड आईपी पते के साथ बहुत अच्छी तरह से काम करता है:

def ip_to_u32(ip):
  return int(''.join('%02x' % int(d) for d in ip.split('.')), 16)

मुझे स्वीकार्य सॉर्ट नेटवर्क के एक पूरे सेट के खिलाफ प्रत्येक सॉकेट स्वीकार () कॉल पर आईपी मिलान करने की आवश्यकता है, इसलिए मैं पूर्णांक के रूप में मास्क और नेटवर्क को प्राथमिकता देता हूं:

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

फिर मैं जल्दी से देख सकता हूं कि क्या एक दिया गया आईपी उन नेटवर्क में से एक है:

ip = ip_to_u32(ipstr)
for mask, net in cached_masks:
  if ip & mask == net:
    # matched!
    break
else:
  raise BadClientIP(ipstr)

कोई मॉड्यूल आयात की आवश्यकता नहीं है, और कोड मिलान में बहुत तेज है।


इस कैश्ड_मास्क को क्या कहा जाता है ??
अजीन

2

netaddr से all_matching_cidrs आयात करते हैं

>>> 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.

मूल रूप से आप पहले तर्क के रूप में एक आईपी पता और दूसरे तर्क के रूप में सिडर्स की एक सूची प्रदान करते हैं। हिट की एक सूची वापस कर दी जाती है।


2
# यह बाइट हैंडलिंग द्वारा अजीब बाइट के बिना ठीक से काम करता है
पता एड्रेस नेटवर्क (आईपी, नेट):
    '' 'नेटवर्क में एक पता है' ''
    # पतों को होस्ट ऑर्डर में कनवर्ट करें, ताकि शिफ्ट वास्तव में समझ में आए
    ip = struct.unpack ('> L', socket.inet_aton (ip)) [0]
    netaddr, बिट्स = net.split ('/')
    netaddr = struct.unpack ('> L', socket.inet_aton (netaddr)] [0]
    # शिफ्ट को सभी लोगों के लिए छोड़ दिया जाना चाहिए, 32 / शून्य शिफ्ट, / 0 = 32 शिफ्ट छोड़ दिया
    netmask = (0xffffff << (32-int (बिट्स))) और 0xffffffff
    # नेटवर्क एड्रेस को मास्क करने की आवश्यकता नहीं है, जब तक कि यह एक उचित नेटवर्क एड्रेस हो
    वापसी (आईपी और netmask) == netaddr 

गलत netmaskमान के कारण 64-बिट OS पर कोड सही तरीके से काम नहीं करता था । मैंने इसे ठीक करने के लिए एक स्वतंत्रता ली है।
ड्रगमैन

2

पिछले समाधान में आईपी और नेट == नेट में एक बग है। सही IP लुकअप IP & netmask = net है

बगिचित कोड:

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");

2

चुना जवाब में एक बग है।

निम्नलिखित सही कोड है:

def addressInNetwork(ip, net_n_bits):
   ipaddr = struct.unpack('<L', socket.inet_aton(ip))[0]
   net, bits = net_n_bits.split('/')
   netaddr = struct.unpack('<L', socket.inet_aton(net))[0]
   netmask = ((1L << int(bits)) - 1)
   return ipaddr & netmask == netaddr & netmask

नोट: के ipaddr & netmask == netaddr & netmaskबजाय ipaddr & netmask == netmask

मैं भी बदलने के ((2L<<int(bits)-1) - 1)साथ ((1L << int(bits)) - 1), बाद अधिक समझ में आता है लगता है के रूप में।


मुझे लगता है कि मुखौटा रूपांतरण ((2L<<int(bits)-1) - 1)सही है। उदाहरण के लिए यदि मुखौटा 16 वर्ष का है, तो इसे "255.255.0.0" या 65535L होना चाहिए, लेकिन ((1L << int(bits)) - 1)32767L मिलेगा, जो सही नहीं है।
क्रिस .Q

@ Chris.Q, ((1L << int(bits)) - 1)मेरे सिस्टम पर 65535L देता है, bits16 के सेट के साथ !!
देबांशु कुंडू

इसके अलावा, के लिए bitsसेट 0, ((2L<<int(bits)-1) - 1)त्रुटि उठा रहा है।
देबांशु कुंडू

हां, वास्तव में / 0, / 8, / 16, / 32 के अलावा कोई मूल्य ठीक से काम नहीं कर रहा है।
देबांशु कुंडू

2

यहाँ एक वर्ग है जो मैंने सबसे लंबे समय तक उपसर्ग मिलान के लिए लिखा है:

#!/usr/bin/env python

class Node:
def __init__(self):
    self.left_child = None
    self.right_child = None
    self.data = "-"

def setData(self, data): self.data = data
def setLeft(self, pointer): self.left_child = pointer
def setRight(self, pointer): self.right_child = pointer
def getData(self): return self.data
def getLeft(self): return self.left_child
def getRight(self): return self.right_child

def __str__(self):
        return "LC: %s RC: %s data: %s" % (self.left_child, self.right_child, self.data)


class LPMTrie:      

def __init__(self):
    self.nodes = [Node()]
    self.curr_node_ind = 0

def addPrefix(self, prefix):
    self.curr_node_ind = 0
    prefix_bits = ''.join([bin(int(x)+256)[3:] for x in prefix.split('/')[0].split('.')])
    prefix_length = int(prefix.split('/')[1])
    for i in xrange(0, prefix_length):
        if (prefix_bits[i] == '1'):
            if (self.nodes[self.curr_node_ind].getRight()):
                self.curr_node_ind = self.nodes[self.curr_node_ind].getRight()
            else:
                tmp = Node()
                self.nodes[self.curr_node_ind].setRight(len(self.nodes))
                tmp.setData(self.nodes[self.curr_node_ind].getData());
                self.curr_node_ind = len(self.nodes)
                self.nodes.append(tmp)
        else:
            if (self.nodes[self.curr_node_ind].getLeft()):
                self.curr_node_ind = self.nodes[self.curr_node_ind].getLeft()
            else:
                tmp = Node()
                self.nodes[self.curr_node_ind].setLeft(len(self.nodes))
                tmp.setData(self.nodes[self.curr_node_ind].getData());
                self.curr_node_ind = len(self.nodes)
                self.nodes.append(tmp)

        if i == prefix_length - 1 :
            self.nodes[self.curr_node_ind].setData(prefix)

def searchPrefix(self, ip):
    self.curr_node_ind = 0
    ip_bits = ''.join([bin(int(x)+256)[3:] for x in ip.split('.')])
    for i in xrange(0, 32):
        if (ip_bits[i] == '1'):
            if (self.nodes[self.curr_node_ind].getRight()):
                self.curr_node_ind = self.nodes[self.curr_node_ind].getRight()
            else:
                return self.nodes[self.curr_node_ind].getData()
        else:
            if (self.nodes[self.curr_node_ind].getLeft()):
                self.curr_node_ind = self.nodes[self.curr_node_ind].getLeft()
            else:
                return self.nodes[self.curr_node_ind].getData()

    return None

def triePrint(self):
    n = 1
    for i in self.nodes:
        print n, ':'
        print i
        n += 1

और यहाँ एक परीक्षण कार्यक्रम है:

n=LPMTrie()
n.addPrefix('10.25.63.0/24')
n.addPrefix('10.25.63.0/16')
n.addPrefix('100.25.63.2/8')
n.addPrefix('100.25.0.3/16')
print n.searchPrefix('10.25.63.152')
print n.searchPrefix('100.25.63.200')
#10.25.63.0/24
#100.25.0.3/16

1

आपकी स्क्रिप्ट के लिए धन्यवाद!
मेरे पास सब कुछ काम करने के लिए इस पर काफी लंबा काम है ... इसलिए मैं इसे यहां साझा कर रहा हूं

  • बाइनरी रूपांतरण का उपयोग करने की तुलना में netaddr वर्ग का उपयोग 10 गुना धीमा है, इसलिए यदि आप इसे IP की एक बड़ी सूची पर उपयोग करना चाहते हैं, तो आपको netaddr वर्ग का उपयोग नहीं करने पर विचार करना चाहिए
  • मेकमास्क फ़ंक्शन काम नहीं कर रहा है! केवल / 8, / 16, / 24
    पूर्व के लिए काम करना:

    बिट्स = "21"; socket.inet_ntoa (struct.pack ('= L', (2L << int (बिट्स) -1) - 1))
    '255.255.31.0' जबकि यह 255.255.248.0 होना चाहिए

    इसलिए मैंने http://code.activestate.com/recipes/576483-convert-subnetmask-from-cidr-notation-to-dotdima/
    Ex: से एक और फंक्शन कैलक्लोनेटनेटमास्क (मास्क) का इस्तेमाल किया है।


#!/usr/bin/python
>>> calcDottedNetmask(21)
>>> '255.255.248.0'
  • यदि आईपी एक नेटवर्क से संबंधित है तो एक और समस्या मिलान की प्रक्रिया है! बेसिक ऑपरेशन की तुलना (ipaddr & netmask) और (नेटवर्क और नेटमास्क) से की जानी चाहिए।
    Ex: समय के लिए, फ़ंक्शन गलत है

#!/usr/bin/python
>>> addressInNetwork('188.104.8.64','172.16.0.0/12')
>>>True which is completely WRONG!!

तो मेरा नया पता InNetwork फ़ंक्शन दिखता है:


#!/usr/bin/python
import socket,struct
def addressInNetwork(ip,net):
    '''This function allows you to check if on IP belogs to a Network'''
    ipaddr = struct.unpack('=L',socket.inet_aton(ip))[0]
    netaddr,bits = net.split('/')
    netmask = struct.unpack('=L',socket.inet_aton(calcDottedNetmask(bits)))[0]
    network = struct.unpack('=L',socket.inet_aton(netaddr))[0] & netmask
    return (ipaddr & netmask) == (network & netmask)

def calcDottedNetmask(mask):
    bits = 0
    for i in xrange(32-int(mask),32):
        bits |= (1 > 24, (bits & 0xff0000) >> 16, (bits & 0xff00) >> 8 , (bits & 0xff))

और अब, जवाब सही है !!


#!/usr/bin/python
>>> addressInNetwork('188.104.8.64','172.16.0.0/12')
False

मुझे उम्मीद है कि यह अन्य लोगों की मदद करेगा, उनके लिए समय की बचत करेगा!


1
उपरोक्त कोड का वर्तमान संस्करण अंतिम पंक्ति में एक ट्रेसबैक देता है, जिसे आप एक इंट और टुपल "=" कर सकते हैं।
सीन रिफ़्शिनडर


1
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('/')
    netaddr = struct.unpack('!L',socket.inet_aton(netaddr))[0]
    netmask = ((1<<(32-int(bits))) - 1)^0xffffffff
    return ipaddr & netmask == netaddr & netmask
print addressInNetwork('10.10.10.110','10.10.10.128/25')
print addressInNetwork('10.10.10.110','10.10.10.0/25')
print addressInNetwork('10.10.10.110','10.20.10.128/25')

$ python check-subnet.py
गलत
सही
गलत


क्या आप बता सकते हैं कि आप पहले से दिए गए उत्तरों में क्या जोड़ रहे हैं?
डेविड गयोन

दिए गए उत्तरों में कुछ समस्या है, जो CIDR को संभाल नहीं सका। मैंने अभी IP पते का बाइट क्रम बदला है। बस इस तरह से:>>> struct.unpack('!L',socket.inet_aton('10.10.10.110'))[0] 168430190 >>> socket.inet_ntoa(struct.pack('!L', 168430190)) '10.10.10.110'
जॉनसन

1
जवाब के लिए धन्यवाद। मुझे लगता है कि यह कुछ ऐसा है जिसे आपको स्पष्ट करने के लिए अपने उत्तर में जोड़ना चाहिए। यह StackOverflow की भावना में है कि "क्या" "क्यों" और अंत में "कैसे" की व्याख्या करें। आपके उत्तर में केवल "कैसे" है :(। मैंने आपको अपना उत्तर संपादित करके पूरा करने दिया;)।
डेविड गुयोन

1

मैं मानक पुस्तकालय में कुछ भी नहीं जानता, लेकिन PySubnetTree एक पायथन पुस्तकालय है जो सबनेट मिलान करेगा।


लिंक को बदल दिया गया है। PySubnetTree को GitHub
मयंक अग्रवाल

0

उपरोक्त विभिन्न स्रोतों से, और मेरे अपने शोध से, यह है कि मुझे सबनेट और एड्रेस गणना कैसे काम कर रही है। प्रश्न और अन्य संबंधित प्रश्नों को हल करने के लिए ये टुकड़े पर्याप्त हैं।

class iptools:
    @staticmethod
    def dottedQuadToNum(ip):
        "convert decimal dotted quad string to long integer"
        return struct.unpack('>L', socket.inet_aton(ip))[0]

    @staticmethod
    def numToDottedQuad(n):
        "convert long int to dotted quad string"
        return socket.inet_ntoa(struct.pack('>L', n))

    @staticmethod
    def makeNetmask(mask):
        bits = 0
        for i in xrange(32-int(mask), 32):
            bits |= (1 << i)
        return bits

    @staticmethod
    def ipToNetAndHost(ip, maskbits):
        "returns tuple (network, host) dotted-quad addresses given"
        " IP and mask size"
        # (by Greg Jorgensen)
        n = iptools.dottedQuadToNum(ip)
        m = iptools.makeMask(maskbits)
        net = n & m
        host = n - mask
        return iptools.numToDottedQuad(net), iptools.numToDottedQuad(host)

0

एक एपीआई है जिसे अजगर में सबनेटट्री कहा जाता है जो इस काम को बहुत अच्छी तरह से करता है। यह एक सरल उदाहरण है:

import SubnetTree
t = SubnetTree.SubnetTree()
t.insert("10.0.1.3/32")
print("10.0.1.3" in t)

यहीं वह लिंक है


0

यहाँ मेरा कोड है

# -*- coding: utf-8 -*-
import socket


class SubnetTest(object):
    def __init__(self, network):
        self.network, self.netmask = network.split('/')
        self._network_int = int(socket.inet_aton(self.network).encode('hex'), 16)
        self._mask = ((1L << int(self.netmask)) - 1) << (32 - int(self.netmask))
        self._net_prefix = self._network_int & self._mask

    def match(self, ip):
        '''
        判断传入的 IP 是不是本 Network 内的 IP
        '''
        ip_int = int(socket.inet_aton(ip).encode('hex'), 16)
        return (ip_int & self._mask) == self._net_prefix

st = SubnetTest('100.98.21.0/24')
print st.match('100.98.23.32')

0

यदि आप अन्य मॉड्यूल को आयात नहीं करना चाहते हैं, तो आप इनके साथ जा सकते हैं:

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]

0

मैंने इन उत्तरों में प्रस्तावित समाधानों में से एक सबसेट की कोशिश की .. किसी भी सफलता के साथ, मैंने अंत में प्रस्तावित कोड को अनुकूलित और निर्धारित किया और अपना निश्चित कार्य लिखा।

मैंने इसका परीक्षण किया और कम से कम एंडियन आर्किटेक्चर पर काम करता है - egx86-- अगर किसी को एक बड़े एंडियन आर्किटेक्चर पर कोशिश करना पसंद है, तो कृपया मुझे प्रतिक्रिया दें।

IP2Intइस पोस्ट से कोड आता है , दूसरी विधि पूरी तरह से (मेरे परीक्षण के मामलों के लिए) इस प्रश्न में पिछले प्रस्तावों का काम कर रही है।

कोड:

def IP2Int(ip):
    o = map(int, ip.split('.'))
    res = (16777216 * o[0]) + (65536 * o[1]) + (256 * o[2]) + o[3]
    return res


def addressInNetwork(ip, net_n_bits):
    ipaddr = IP2Int(ip)
    net, bits = net_n_bits.split('/')
    netaddr = IP2Int(net)
    bits_num = int(bits)
    netmask = ((1L << bits_num) - 1) << (32 - bits_num)
    return ipaddr & netmask == netaddr & netmask

आशा है कि उपयोगी,


0

यहाँ netaddr पैकेज का उपयोग कर समाधान है

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)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.