The following version adds a „-c“ option: „Connected IP-Address“-Check.
- the script exits, when the Router-VM is up and running and has an usable IP-Address
The Script still checks all CDP-Packets received at the specified Interface:
- If the Sender has the correct „Hostname“ it reads the CDP-Management-IP-Address announced.
- This IP-Address has to be within the IP-Range of any connected IP-Network at the specified Interface.
So it’ll be possible to establish a SSH-Session to the router-VM.
C:\> echo %VM% CSX C:\> python WaitForCDPNeighbor.py -n %VM% -c -i "VirtualBox Host-Only Ethernet Adapter" 192.168.56.101
#! /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())