2015-11-05 202 views
0

ip a outputscreenshot我想創建一個腳本,掃描局域網,並獲得所有使用Python的機器的IP地址和MAC地址。下面的腳本執行此操作,但是它會將列表打印兩次?這怎麼可能實現,或者如何改變下面的腳本來打印一次列表(作爲一個字典,其中ip地址是鍵,mac是值)?Python掃描網絡IP地址和mac

from __future__ import absolute_import, division, print_function 
import logging 
import scapy.config 
import scapy.layers.l2 
import scapy.route 
import socket 
import math 
import errno 

logging.basicConfig(format='%(asctime)s %(levelname)-5s %(message)s', datefmt='%Y-%m-%d %H:%M:%S', level=logging.DEBUG) 
logger = logging.getLogger(__name__) 


def long2net(arg): 
    if (arg <= 0 or arg >= 0xFFFFFFFF): 
     raise ValueError("illegal netmask value", hex(arg)) 
    return 32 - int(round(math.log(0xFFFFFFFF - arg, 2))) 


def to_CIDR_notation(bytes_network, bytes_netmask): 
    network = scapy.utils.ltoa(bytes_network) 
    netmask = long2net(bytes_netmask) 
    net = "%s/%s" % (network, netmask) 
    if netmask < 16: 
     logger.warn("%s is too big. skipping" % net) 
     return None 

    return net 


def scan_and_print_neighbors(net, interface, timeout=1): 
    logger.info("arping %s on %s" % (net, interface)) 
    try: 
     ans, unans = scapy.layers.l2.arping(net, iface=interface, timeout=timeout, verbose=True) 
     for s, r in ans.res: 
      line = r.sprintf("%Ether.src% %ARP.psrc%") 
      try: 
       hostname = socket.gethostbyaddr(r.psrc) 
       line += " " + hostname[0] 
      except socket.herror: 
       # failed to resolve 
       pass 
      logger.info(line) 
    except socket.error as e: 
     if e.errno == errno.EPERM:  # Operation not permitted 
      logger.error("%s. Did you run as root?", e.strerror) 
     else: 
      raise 


if __name__ == "__main__": 
    for network, netmask, _, interface, address in scapy.config.conf.route.routes: 

     # skip loopback network and default gw 
     if network == 0 or interface == 'lo' or address == '127.0.0.1' or address == '0.0.0.0': 
      continue 

     if netmask <= 0 or netmask == 0xFFFFFFFF: 
      continue 

     net = to_CIDR_notation(network, netmask) 

     if interface != scapy.config.conf.iface: 
      # see http://trac.secdev.org/scapy/ticket/537 
      logger.warn("skipping %s because scapy currently doesn't support arping on non-primary network interfaces", net) 
      continue 

     if net: 
      scan_and_print_neighbors(net, interface) 

回答

1

您是否試過將verbose設置爲False

ans, unans = scapy.layers.l2.arping(net, iface=interface, timeout=timeout, verbose=False) 

除了你scapy.layers.l2.arping(設置verbose=False, 導入conf模塊:

from scapy.all import conf 

僅低於你的if __name__ == "__main__":行添加conf.verb=0

if __name__ == "__main__": 
    conf.verb=0 
    for network, netmask, _, interface, address in scapy.config.conf.route.routes: 

     # skip loopback network and default gw 
     if network == 0 or interface == 'lo' or address == '127.0.0.1' or address == '0.0.0.0': 
      continue 

編輯:我認爲你的腳本正在循環對於您的/proc/net/route中定義的每個「路線」,尚未明確過濾(即, )我的猜測是,如果你在哪裏執行route -n,你可能會發現有2條路徑在那裏有某種方式具有相同的網絡和接口值,但其他的東西與網絡掩碼或網關不同。

不管怎麼說,通過這種方法得到通過的方法是在您致電scan_and_print_neighbors(net, interface)後添加break以退出for-loop。

例如:

if __name__ == "__main__": 
    for network, netmask, _, interface, address in scapy.config.conf.route.routes: 

     # skip loopback network and default gw 
     if network == 0 or interface == 'lo' or address == '127.0.0.1' or address == '0.0.0.0': 
      continue 

     if netmask <= 0 or netmask == 0xFFFFFFFF: 
      continue 

     net = to_CIDR_notation(network, netmask) 

     if interface != scapy.config.conf.iface: 
      # see http://trac.secdev.org/scapy/ticket/537 
      logger.warn("skipping %s because scapy currently doesn't support arping on non-primary network interfaces", net) 
      continue 

     if net: 
      scan_and_print_neighbors(net, interface) 
      break 
+0

有,我有,它仍然打印列表兩次? – bshah

+0

更新了我的答案並在我的系統上進行了測試。現在它只打印你使用記錄器聲明的信息,而不是來自scapy模塊本身的詳細信息。 –

+0

它仍然打印出兩個列表。通過在scapy.layers.l2.arping中導入conf模塊是什麼意思? – bshah