#! /usr/bin/env python
# Ronald Heitmann
#
import argparse
from scapy.all import *
load_contrib("cdp")
from netaddr import IPNetwork, IPAddress
from netifaces import AF_INET, AF_INET6, AF_LINK
import netifaces
# returns a list of all IP-Adresses bound to the specified Interface "if_name"
def get_connected(if_name):
if_id = ""
networks = []
for i in ifaces.data.keys():
iface = ifaces.data[i]
wname = iface.data['name']
if wname == if_name:
if_id = i
addresses = netifaces.ifaddresses(i)
if AF_INET in addresses:
for addr in netifaces.ifaddresses(i)[AF_INET]:
#print(addr)
ipnetwork = IPNetwork(addr["addr"]+"/"+addr["netmask"]).cidr
networks.append(ipnetwork)
#print(networks)
return networks
# checks, if the IP-Address "ip" is within the subnet-range of any network contained in the list "networks"
def is_IP_connected(ip, networks):
found = False
ipnetwork = IPNetwork(ip).cidr
for n in networks:
if (ipnetwork in n):
found = True
return found
def main():
# Parse CLI-Arguments
parser = argparse.ArgumentParser(description='Wait for a CDP-Neighbor.')
parser.add_argument("-i", "--interface", help="monitored interface", default="VirtualBox Host-Only Ethernet Adapter")
parser.add_argument("-n", "--hostname", help="Neighbor to wait for", required=True)
parser.add_argument("-c", "--connected", help="wait, until CDP-Neighbor announces an directly-connected IP-Address", action='store_true')
args = parser.parse_args()
#looking for a specific hostname
#
hostname = ""
wait_for_hostname = args.hostname
#watching for CDP-Packets from this host on a specific interface
#the router-IP should use a directly-connected IP-Address
ip = "0.0.0.0"
wait_for_connected = args.connected
interface=args.interface
networks = get_connected(interface)
#print(networks)
#CDP
capturefilter="ether dst 01:00:0c:cc:cc:cc"
while not((hostname == wait_for_hostname) and (not(wait_for_connected) or is_IP_connected(ip,networks))):
p=sniff(iface=interface, count=1, filter=capturefilter)
pkt=p[0]
#print("Packet received",pkt.show())
#is this a CDP-Packet containing a hostname?
if (CDPMsgDeviceID in pkt):
#is this the CDP-Neighbor we're looking for?
device=pkt["CDPMsgDeviceID"].val.decode()
hostname=device.split(".")[0]
#print("Hostname:",hostname)
if (hostname == wait_for_hostname):
#is this a CDP-Packet containing a management-IP-Address?
if (CDPAddrRecordIPv4 in pkt):
ip=pkt["CDPAddrRecordIPv4"].addr
#print("IP-Address found:",ip)
#return the IP-Address to the calling application or the CLI
return ip
if __name__ == "__main__":
print(main())
You got the task to generate a list of IP-Networks connected to LAN „VirtualBox Host-Only Network“. There might be more than one IP-Network.
Use Scapy to crawl through all Interfaces and get the human-readable interface name [only required for windows users]. Use NetIfaces to get a list of IP-Addresses connected to this interface. Use IPAddress to calculate the IP-Network(s) directly connected.
! multiple IPs per Interface supporte
!
from netifaces import AF_INET, AF_INET6, AF_LINK
import netifaces
from scapy.all import *
import ipaddress
if_name = "VirtualBox Host-Only Network"
if_id = ""
if_inet = []
for i in ifaces.data.keys():
iface = ifaces.data[i]
wname = iface.data['netid']
if wname == if_name:
if_id = i
addresses = netifaces.ifaddresses(i)
if AF_INET in addresses:
for addr in netifaces.ifaddresses(i)[AF_INET]:
print(addr)
ipaddr = ipaddress.ip_interface(addr["addr"]+"/"+addr["netmask"])
ipnetwork = ipaddr.network
print(ipaddr,ipnetwork)
if_inet.append(ipnetwork)
print("NAME: {0}\nIP: {1}\nID: {2}".format(if_name,if_inet,if_id))
In my case, only one subnet is directly connected:
from netifaces import AF_INET, AF_INET6, AF_LINK
import netifaces
for i in netifaces.interfaces():
niif=netifaces.ifaddresses(i)
print("i",i)
for k,v in niif.items():
print("Key",k)
if k==AF_LINK:
print("LINK:",v)
if k==AF_INET:
print("IPv4",v)
if k==AF_INET6:
print("IPv6",v)
print()
Obviously far to much hard-coded stuff, just as an example 😉 waiting for a CDP-Neighbor to appear with the following properties:
hostname „CSR-A“
an IP-Address within the network „192.168.56.0 /24“
at the interface
VirtualBox Host-Only-Network
#! /usr/bin/env python
from scapy.all import *
load_contrib("cdp")
from netaddr import IPNetwork, IPAddress
# run it for max. 99 Packets
ip = "0.0.0.0"
wait_for_hostname = "CSR-A"
wait_for_host_in_network = "192.168.56.0/24"
interface="VirtualBox Host-Only Ethernet Adapter"
capturefilter="ether dst 01:00:0c:cc:cc:cc"
while not(IPAddress(ip) in IPNetwork(wait_for_host_in_network)):
p=sniff(iface=interface, count=1, filter=capturefilter)
pkt=p[0]
#print("Packet received",pkt.show())
#is this a CDP-Packet containing a hostname?
if (CDPMsgDeviceID in pkt):
#is this the CDP-Neighbor we're looking for?
device=pkt["CDPMsgDeviceID"].val.decode()
hostname=device.split(".")[0]
#print("Hostname:",hostname)
if (hostname == wait_for_hostname):
#is this a CDP-Packet containing a management-IP-Address?
if (CDPAddrRecordIPv4 in pkt):
ip=pkt["CDPAddrRecordIPv4"].addr
#print("IP-Address found:",ip)
#return the IP-Address to the calling application or the CLI
print(ip)
Provision a new CSR1000V Router named „CSR-A“
C:\RH>CSR1000v-Virtual-Box.cmd
Enter CSR1000v Hostname:CSR-A
Virtual machine 'CSR-A' is created and registered.
UUID: 8a9c969e-3895-4a7c-9cbc-5f5551bf1b7b
Settings file: 'c:\RH\LAB\VM\CSR-A\CSR-A.vbox'
Creating ISO image at c:\RH\LAB\VM\CSR-A\config.iso, 1 Files, Size: 8,00 KB
100%
0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
Medium created. UUID: 55ea8df5-7e3c-4485-8e08-9302cb61a09d
Waiting for VM "CSR-A" to power on...
VM "CSR-A" has been successfully started.