CDP Sniffing with an Arduino

Firstly full credit to Chris van Marle for his work on his CDPSniffino code, of which I have butchered (to be honest) to get it to work with ENC28J60 ethernet controllers. The packet info that is captured is slightly different, so it took a while debugging. This is also my first Arduino project (not including 3D printers). It has  been a while since I have written C code… Enough excuses…

Anyway, I use a lot of Cisco equipment and I have found on many occasion that network wall ports are either not labeled or the labels have worn off. When that port needs to be reconfigured it can take time to work out which network cabinet it goes back too, then which switch, and then which switch port. Most of the information can be obtained from CDP (Cisco Discovery Protocol):

  • The switch name gives a good indication of which cabinet and switch.
  • Model: Helps when the hostname has no indications of what the device is.
  • IP address: You can try to remotely access the switch (SSH/Telnet/Web interface).
  • The switch port is given (E.g; FastEthernet0/1).
  • VLAN: Good to know because it often determines what DHCP range is offered – I’m still working out if it’s the VLAN of the port or the “switch”.

The original code for CDPSniffino compiled fine on an Uno with a W5100 network shield (kudos again to Chris). I had always planned to make a few network enabled devices, and cost cuts are in effect. The ENC28J60 is significantly cheaper than the W5100, and the Arduino Mini Pro compatible boards have enough capacity to be a good substitute. Arduino Uno R3 + Wiznet W5100 shield >$20. Arduino Mini Pro + ENC28J60 = can be < $5 (shop around).

The ENC28J60 works with the Ethercard library. It took a while to find now to get the NIC to switch to promiscuous mode. When enabled the controller will process all packets it sees, and not filter multicast and broadcast packets.

To make it faster and easier to obtain the info, it needs a screen. The alternative is plugging it in and dragging out a laptop to read the info through a serial port. I tried a few no name LCD’s, but found (as many others have), that without correct information (datasheets or a driver name) it’s a huge time waster. Also most had 3.3v VCC and data lines (not 5v). Luckily I found a cheap supplier that did (after 3 failures). These have been pretty good, they can output text with basic commands using the Adafruit_ST7735 library. I mistakenly had 5V running to the LED line for a while (should be 3.3V) , after the LEDs cooled down, the blue tinge disappeared and all was fine.

The two test rigs shown below are both using ENC28J60 controllers, the larger on has a character LCD and Arduino Uno R3 board. The smaller one has an Arduino Mini Pro (compatible), and an ST7735 based color graphical LCD. During testing the larger one drained a 9V battery after about an hour of use. A goal was to make it small enough to  join to this and use the phone charger battery for power.

What I found when testing:

  • CDP is enabled by default on most Cisco devices.
  • The default schedule for sending CDP packets is every 60 seconds – Although this can be changed or disabled.
  • Wireless Access Points also have CDP enabled by default, which is good when tracing which WAP connects to which power injector (what out for POE!).
  • Un-managed consumer grade switches will pass CDP packets, so the switch you see may not be the one that is connected directly to the port. Also the heavier the traffic on an un-managed switch, the longer it takes to detect the packets. I believe this is because the ENC28J60 doesn’t not have a lot of processing power, and the Arduino Mini can’t keep up, so it drops packets when under heavy load.

All code and STL’s for the case will be published when I’m happy with the smaller test unit.

UPDATE: Reprinted case in green and crudely added it too the wireless serial device. Time for a field test.

UPDATE [24-06-14]: I’ve reduced the overall size of the case by about 10% by using a smaller ENC28J60 PCB, and started working on extra features. One of the features I’m working on is getting it to check for open ports (80, 22, and 23) on the detected equipment (if it’s IP can be obtained). If the switch accepts a connection on any of those ports you can gain access to the remote switch using network rather than using a serial cable.

UPDATE [9-1-2015]

As requested below: Source Code (needs clean up)

Edited Ethercard Library  ethercard_edited

UPDATE [9-6-2018]

The sketchup 8 file of the final designs BLUETOOTH_SERIAL_Final. You can still download Sketchup8 and use it for free.

UPDATE [15-06-2018]

Made another one of these and had a few issues with details missing, so I created a wiring diagram in Fritzing:

  • The only version of Arduino IDE that it compiled in was Arduino 1.6.4.
  • There was a typo that can be commented out in the source code:
int iplength;
// ip=ip.substring(ip.length()-1)='\0';


37 thoughts on “CDP Sniffing with an Arduino

  1. Greetings! I would love to do this. You mentioned you would publish the final code. Do you have that available somewhere? Thanks!

  2. I get compile errors with your code attached. Can you please fix it?
    most probably here:


    This report would have more information with
    “Show verbose output during compilation”
    enabled in File > Preferences.
    Arduino: 1.0.6 (Mac OS X), Board: “Arduino Pro or Pro Mini (5V, 16 MHz) w/ ATmega328″
    LCD_Listener_Nano.ino: In function ‘String print_ip(const byte*, unsigned int, unsigned int)’:
    LCD_Listener_Nano:320: error: ambiguous overload for ‘operator=’ in ‘String::substring(unsigned int) const((ip.String::length() + 65535u)) = ’00”
    /Applications/ note: candidates are: String& String::operator=(const String&)
    /Applications/ note: String& String::operator=(const char*)
    /Applications/ note: String& String::operator=(const __FlashStringHelper*)

  3. Got the code fixed and all good but one minor issue.
    Sometimes DHCP gives as the DHCP IP address.
    Have you seen this? Any fix?


    • Hi, unless you’ve changed it, the code waits 20 seconds for a DHCP reply. I have also gotten on the odd occasion, when I’ve turned it on and not plugged the network cable in fast enough, I originally wanted to have a loop that keeps going until it detects line sync on the NIC, but I wasn’t able to get it to work. You’ll also get “” when plugged into a trunked port where you shouldn’t receive DHCP requests, but you’ll still see CDP packets.


      • Access port not a trunk port.

        Sometimes if I turn it off and turned it back on with the same cable connected, occasionally gets but it gives switch information correctly.
        I get;
        1) DHCP Failed message
        2) Then I unplug the network cable and plug it back on.
        3) DHCP IP: but Correct device information displayed except DHCP

  4. Hi there! I am a C++ developer with a side hobby in hardware hacking and arduinos. I had this unoriginal idea the other day LOL that I should be able to create an in-line packet sniffer using an arduino and Ethernet shield, but it seems you’ve already done this. What I would like to do however is be able to modify the packet data based on some custom filter before the packet goes out the door. I wanted to ask you, do you think your device could be easily modified in that respect? I want to situate this between my router and a PlayStation 3. It will need to work transparently to the PS3 during online play. Any ideas? I really want to learn how to do this and don’t mind paying for the tutoring. Everyone is telling me the device would be SLOW, but gameplay packets generally have a tiny footprint. I won’t be streaming movies or downloading files over this thing. Email me please, Thanks!

  5. I’m intending to use this as a little Network tester fot work. I’m always having to borrow my boss’s fluke just to pull port info. So I’m going to throw my own version of this together and I’ll publish my work as well.

    However, a question I had, I’m trying to determine whether the NIC will survive POE. All the jacks usually have it enabled. Its type B terminations and all thr jacks are gigabit. So it’s a super imposed signal on some of the lines. As far as I understand, I shouldn’t have to worry about it. I don’t intend to utilize the power or measure it. Just don’t want to burn it up. Have you ever plugged this into a POE jack?

    • Hi Gary, Ive used it with many current Cisco switches that have POE capabilites and it was ok. I have also had it plugged into the seperate power injectors and its been fine. What I cant confirm is if it will survive a passive power injector – one that has the voltage running all the time.

      Please let me know how you go with your project.


  6. Hello,

    Thanks a lot for your description and code!!

    Could you also upload the wiring diagram? That would help me a lot!

    Kind regards.

  7. Hi,

    I want to add pining and to get the publick IP. For the best result Promiscuous should be disabled for this.
    Do you know how to disable Promiscuous? I have found the code below. But I don’t know what to use for writeRegByte(ERXFCON, 0); to disable it.

    void ENC28J60::enablePromiscuous () {
    writeRegByte(ERXFCON, 0);

    • Hi Colin,
      If you read through the documentation (I forget where) you’ll see references for: ERXFCON and what the static variables mean: ERXFCON_CRCEN, ERXFCON_PMEN, ERXFCON_BCEN. Thats how it’s turned on/off. You’ll also see in my code the line: ENC28J60::enablePromiscuous () – That goes to the function and turns on promiscuous mode, so with that in mind you’d have to either write your own function or use one that already exists. I don’t remember if there was one.

      From memory the static variables defined what it it would listen for; eg: traffic addressed to the devices MAC, broadcast traffic, both itself and broadcast or all traffic.


  8. Hi Kristian,

    I have some problem with the pins used for ENC28J60. On your description you use pin 10 to 13 on the Arduino. But on the code the following pins are defined:

    //Use these pins for the shield!
    #define sclk 13
    #define mosi 11
    #define cs 4
    #define dc 8
    #define rst -1 // you can also connect this to the Arduino reset
    #define ETH_RS_PIN 9

    That does not match. Can you explain me how this works?. Because I want to use an arduino mega. But don’t get the ENC28J60 working on this if I use the same pins 10-13 or the 50 to 54 pins on the mega.

    Regards Colin.

    • Hi Colin,
      I’ve had a quick look and it appears to be achievable. Not sure if the two codes are compatible enough and the processor fast enough to scan both types of incoming packets at the same time. I’ll check it out but my time is limited at the moment, so it might take a while.


    • Hi Colin,
      After spending hours using Wireshark and spotting a non NULL terminated char array, I’ve got a work in progress that works well. it’s not ready for release yet but should be in the next week or so. Thank you for your patience. I’ve also spotted a few other improvements in the source code.


  9. Hi Kristian!
    I build your project and working well!
    Thank You!
    I have a problem. I would like to use your project with STM32103f Blue pill board and STM32duino programming language. I modify your program but the CDP data reading is not working. I think the cause the EtherCard library. The Arduino and STM32duino Ethercard library is not same, so I can’t to enable the (promiscuous mode). Please help me! I would like a working STM32duino EtherCard library, if it is possible.
    Sorry my english is poor.
    Regards: József

Leave a Reply to Kristian Cancel reply

Your email address will not be published. Required fields are marked *