├── Makefile ├── .project ├── includes ├── crc16 │ ├── crc.h │ └── crc.c └── oui.h ├── CHANGELOG ├── README ├── cdpsnarf.h ├── LICENSE └── cdpsnarf.c /Makefile: -------------------------------------------------------------------------------- 1 | 2 | all: 3 | gcc -O3 -Wall -lm -lpcap cdpsnarf.c -o cdpsnarf 4 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | CDPSnarf 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /includes/crc16/crc.h: -------------------------------------------------------------------------------- 1 | // taken from atmels datasheet avr067 2 | 3 | unsigned short crc16_checksum( u_char *buf, unsigned long length); 4 | void crc16_append(char * buf, unsigned long length); 5 | 6 | #define CRC_INIT 0xFFFF 7 | #define CRC(crcval,newchar) crcval = (crcval >> 8) ^ crc_table[(crcval ^ newchar) & 0x00ff] 8 | 9 | -------------------------------------------------------------------------------- /CHANGELOG: -------------------------------------------------------------------------------- 1 | 2 | Version 0.1.6 3 | * Added support for the "IP Prefixes/Gateway" CDP field 4 | 5 | Version 0.1.5 6 | * Added support for dump files (using the "-w " argument) 7 | * Added help output 8 | * Added IPv6 support 9 | * Added debugging support (using the "-d" flag) 10 | * Added source MAC address to the output 11 | * Added support for extra TLV types 12 | (The majority of TLV types is now supported) 13 | * Added support for reading PCAP dumps instead of listening on an interface 14 | (using the "-r " argument) 15 | 16 | Version 0.1.4 17 | * Improved PCAP filter expression as there were reports of false positives 18 | (Props go to the usual suspect...) 19 | 20 | Version 0.1.3 21 | * free'd memory allocations and fixed memory leaks 22 | * fixed segfault when printing/parsing IP addresses 23 | (Thanks to paul@expsys.com for pointing that out.) 24 | 25 | Version 0.1.1 26 | * invalid IP address returned when CDP packet contained IP address of 0.0.0.0, 27 | accompanied by possible segfault. 28 | (Thanks to paul@expsys.com for pointing that out.) -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | 2 | CDPSnarf v0.1.6 Cisco Discovery Protocol Sniffer 3 | by Tasos "Zapotek" Laskos 4 | 5 | 6 | 7 | Licensed under the GNU General Public License v2 8 | 9 | 10 | 11 | General 12 | ---------- 13 | CDPSnarf is a network sniffer exclusively written to extract 14 | information from CDP packets. 15 | It provides all the information a "show cdp neighbors detail" 16 | command would return on a Cisco router and even more. 17 | 18 | Features 19 | ----------- 20 | A feature list follows: 21 | o Time intervals between CDP advertisements 22 | o Source MAC address 23 | o CDP Version 24 | o TTL 25 | o Checksum 26 | o Device ID 27 | o Software version 28 | o Platform 29 | o Addresses 30 | o Port ID 31 | o Capabilities 32 | o Duplex 33 | o Save packets in PCAP dump file format 34 | o Read packets from PCAP dump files 35 | o Debugging information (using the "-d" flag) 36 | o Tested with IPv4 and IPv6 [1] 37 | 38 | [1] Other protocols will be detected and addresses will be printed in an 39 | IPv6 hexadecimal format 40 | 41 | Usage 42 | ------ 43 | Issue the "make" command to built CDPsnarf from source. 44 | Then issue: 45 | sudo cdpsnarf -i 46 | 47 | More options with: 48 | cdpsnarf -h 49 | 50 | Requirements 51 | ------------- 52 | * PCAP library [http://www.tcpdump.org] 53 | * GCC 54 | 55 | Bug reports/Feature requests 56 | ------------------------------- 57 | Please send your feedback using GitHub's issue system (http://github.com/Zapotek/cdpsnarf/issues). 58 | I will do my best to apply bugfixes and add new features as fast as possible. 59 | 60 | License 61 | --------- 62 | CDPSnarf is licensed under the GNU General Public License v2. 63 | See the file "LICENSE" in the same folder for more informaton. 64 | 65 | Disclaimer 66 | ----------- 67 | CDPSnarf is free software and you are allowed to use it as you see fit. 68 | However, I can't be held responsible for your actions or for any damage 69 | caused by the use of this software. 70 | -------------------------------------------------------------------------------- /includes/crc16/crc.c: -------------------------------------------------------------------------------- 1 | //#include "crc.h" 2 | // 3 | //const unsigned short crc_table[256] = 4 | //{ 5 | // 0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF, 6 | // 0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7, 7 | // 0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E, 8 | // 0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876, 9 | // 0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD, 10 | // 0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5, 11 | // 0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C, 12 | // 0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974, 13 | // 0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB, 14 | // 0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3, 15 | // 0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A, 16 | // 0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72, 17 | // 0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9, 18 | // 0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1, 19 | // 0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738, 20 | // 0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70, 21 | // 0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7, 22 | // 0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF, 23 | // 0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036, 24 | // 0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E, 25 | // 0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5, 26 | // 0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD, 27 | // 0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134, 28 | // 0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C, 29 | // 0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3, 30 | // 0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB, 31 | // 0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232, 32 | // 0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A, 33 | // 0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1, 34 | // 0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9, 35 | // 0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330, 36 | // 0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78 37 | //}; 38 | // 39 | // 40 | //unsigned short crc16_checksum(char * buf,unsigned long length) 41 | //{ 42 | // unsigned long i; 43 | // unsigned short crc=0xffff; 44 | // 45 | // for(i=0;i>8) & 0xff); 58 | //} 59 | 60 | /* 61 | ************************************************************************** 62 | Function: ip_sum_calc 63 | Description: Calculate the 16 bit IP sum. 64 | *************************************************************************** 65 | */ 66 | typedef unsigned short u16; 67 | typedef unsigned long u32; 68 | 69 | u16 crc16_checksum(u_char buff[], u16 len_ip_header) 70 | { 71 | u16 word16; 72 | u32 sum=0; 73 | u16 i; 74 | 75 | // make 16 bit words out of every two adjacent 8 bit words in the packet 76 | // and add them up 77 | for (i=0;i>16) 84 | sum = (sum & 0xFFFF)+(sum >> 16); 85 | 86 | // one's complement the result 87 | sum = ~sum; 88 | 89 | return ((u16) sum); 90 | } 91 | -------------------------------------------------------------------------------- /includes/oui.h: -------------------------------------------------------------------------------- 1 | /* 2 | * CDPSnarf CDP packet sniffer 3 | * Copyright (C) 2006-2010 Tasos "Zapotek" Laskos 4 | * 5 | * 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License along 18 | * with this program; if not, write to the Free Software Foundation, Inc., 19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 20 | */ 21 | 22 | #ifndef OUI_H_ 23 | #define OUI_H_ 24 | 25 | /* 26 | * Registered OUIs: http://standards.ieee.org/regauth/oui/oui.txt 27 | * 28 | */ 29 | 30 | #define OUI_ENCAP_ETHER 0x000000 /* encapsulated Ethernet */ 31 | #define OUI_XEROX 0x000006 /* Xerox */ 32 | #define OUI_CISCO 0x00000C /* Cisco (future use) */ 33 | #define OUI_NORTEL 0x000081 /* Nortel SONMP */ 34 | #define OUI_CISCO_90 0x0000F8 /* Cisco (IOS 9.0 and above?) */ 35 | #define OUI_ERICSSON 0x0001EC /* Ericsson Group */ 36 | #define OUI_CATENA 0x00025A /* Catena Networks */ 37 | #define OUI_SONY_ERICSSON 0x000AD9 /* Sony Ericsson Mobile Communications AB */ 38 | #define OUI_SONY_ERICSSON_2 0x000E07 /* Sony Ericsson Mobile Communications AB */ 39 | #define OUI_PROFINET 0x000ECF /* PROFIBUS Nutzerorganisation e.V. */ 40 | #define OUI_SONY_ERICSSON_3 0x000FDE /* Sony Ericsson Mobile Communications AB */ 41 | #define OUI_IEEE_802_3 0x00120F /* IEEE 802.3 */ 42 | #define OUI_MEDIA_ENDPOINT 0x0012BB /* Media (TIA TR-41 Committee) */ 43 | #define OUI_SONY_ERICSSON_4 0x0012EE /* Sony Ericsson Mobile Communications AB */ 44 | #define OUI_ERICSSON_MOBILE 0x0015E0 /* Ericsson Mobile Platforms */ 45 | #define OUI_SONY_ERICSSON_5 0x001620 /* Sony Ericsson Mobile Communications AB */ 46 | #define OUI_SONY_ERICSSON_6 0x0016B8 /* Sony Ericsson Mobile Communications AB */ 47 | #define OUI_SONY_ERICSSON_7 0x001813 /* Sony Ericsson Mobile Communications AB */ 48 | #define OUI_SONY_ERICSSON_8 0x001963 /* Sony Ericsson Mobile Communications AB */ 49 | #define OUI_CISCOWL 0x004096 /* Cisco Wireless (Aironet) */ 50 | #define OUI_ERICSSON_2 0x008037 /* Ericsson Group */ 51 | #define OUI_BRIDGED 0x0080C2 /* Bridged Frame-Relay, RFC 2427 */ 52 | /* and Bridged ATM, RFC 2684 */ 53 | #define OUI_IEEE_802_1 0x0080C2 /* IEEE 802.1 Committee */ 54 | #define OUI_ATM_FORUM 0x00A03E /* ATM Forum */ 55 | #define OUI_EXTREME 0x00E02B /* Extreme EDP/ESRP */ 56 | #define OUI_CABLE_BPDU 0x00E02F /* DOCSIS spanning tree BPDU */ 57 | #define OUI_SIEMENS 0x080006 /* Siemens AG */ 58 | #define OUI_APPLE_ATALK 0x080007 /* Appletalk */ 59 | #define OUI_HP 0x080009 /* Hewlett-Packard */ 60 | 61 | // the names of the above OUI codes 62 | static assoc_array OUI_NAMES[] = { 63 | { OUI_ENCAP_ETHER, "Encapsulated Ethernet" }, 64 | { OUI_XEROX, "Xerox" }, 65 | { OUI_CISCO, "Cisco" }, 66 | { OUI_NORTEL, "Nortel SONMP" }, 67 | { OUI_CISCO_90, "Cisco" }, 68 | { OUI_ERICSSON, "Ericsson Group" }, 69 | { OUI_CATENA, "Catena Networks" }, 70 | { OUI_SONY_ERICSSON, "Sony Ericsson Mobile Communications AB" }, 71 | { OUI_SONY_ERICSSON_2, "Sony Ericsson Mobile Communications AB" }, 72 | { OUI_PROFINET, "PROFIBUS Nutzerorganisation e.V." }, 73 | { OUI_SONY_ERICSSON_3, "Sony Ericsson Mobile Communications AB" }, 74 | { OUI_IEEE_802_3, "IEEE 802.3" }, 75 | { OUI_MEDIA_ENDPOINT, "Media (TIA TR-41 Committee)" }, 76 | { OUI_SONY_ERICSSON_4, "Sony Ericsson Mobile Communications AB" }, 77 | { OUI_ERICSSON_MOBILE, "Sony Ericsson Mobile Communications AB" }, 78 | { OUI_SONY_ERICSSON_5, "Sony Ericsson Mobile Communications AB" }, 79 | { OUI_SONY_ERICSSON_6, "Sony Ericsson Mobile Communications AB" }, 80 | { OUI_SONY_ERICSSON_7, "Sony Ericsson Mobile Communications AB" }, 81 | { OUI_SONY_ERICSSON_8, "Sony Ericsson Mobile Communications AB" }, 82 | { OUI_CISCOWL, "Cisco Wireless (Aironet)" }, 83 | { OUI_ERICSSON_2, "Ericsson Group" }, 84 | { OUI_BRIDGED, " Bridged Frame-Relay/ATM" }, 85 | { OUI_IEEE_802_1, "IEEE 802.1 Committee" }, 86 | { OUI_ATM_FORUM, "ATM Forum" }, 87 | { OUI_EXTREME, "Extreme EDP/ESRP" }, 88 | { OUI_CABLE_BPDU, "DOCSIS spanning tree BPDU" }, 89 | { OUI_SIEMENS, "Siemens AG" }, 90 | { OUI_APPLE_ATALK, "Appletalk" }, 91 | { OUI_HP, "Hewlett-Packard" } 92 | }; 93 | 94 | #endif /*OUI_H_*/ 95 | -------------------------------------------------------------------------------- /cdpsnarf.h: -------------------------------------------------------------------------------- 1 | /* 2 | * CDPSnarf CDP packet sniffer 3 | * Copyright (C) 2006-2010 Tasos "Zapotek" Laskos 4 | * 5 | * 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License along 18 | * with this program; if not, write to the Free Software Foundation, Inc., 19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 20 | */ 21 | 22 | #ifndef SNARF_H_ 23 | #define SNARF_H_ 24 | 25 | typedef struct _assoc_array { 26 | int value; 27 | const char *string; 28 | } assoc_array; 29 | 30 | typedef unsigned short uint16_t; 31 | typedef unsigned int uint32_t; 32 | 33 | #include "includes/oui.h" 34 | //#include "includes/crc16/crc.c" 35 | 36 | struct address { 37 | int proto_type; 38 | int proto_len; 39 | int proto; 40 | int address_len; 41 | int address; 42 | } *addresses; 43 | 44 | // Type codes of the CDP TLV 45 | #define TYPE_DEVICE_ID 0x0001 // supported 46 | #define TYPE_ADDRESS 0x0002 // supported 47 | #define TYPE_PORT_ID 0x0003 // supported 48 | #define TYPE_CAPABILITIES 0x0004 // supported 49 | #define TYPE_IOS_VERSION 0x0005 // supported 50 | #define TYPE_PLATFORM 0x0006 // supported 51 | #define TYPE_IP_PREFIX 0x0007 // supported but needs further testing 52 | #define TYPE_PROTOCOL_HELLO 0x0008 // supported 53 | #define TYPE_VTP_MGMT_DOMAIN 0x0009 // supported 54 | #define TYPE_NATIVE_VLAN 0x000a // supported 55 | #define TYPE_DUPLEX 0x000b // supported 56 | /* 0x000c */ 57 | /* 0x000d */ 58 | #define TYPE_VOIP_VLAN_REPLY 0x000e 59 | #define TYPE_VOIP_VLAN_QUERY 0x000f 60 | #define TYPE_POWER 0x0010 61 | #define TYPE_MTU 0x0011 // supported 62 | #define TYPE_TRUST_BITMAP 0x0012 // supported 63 | #define TYPE_UNTRUSTED_COS 0x0013 // supported 64 | #define TYPE_SYSTEM_NAME 0x0014 // supported 65 | #define TYPE_SYSTEM_OID 0x0015 // supported 66 | #define TYPE_MANAGEMENT_ADDR 0x0016 // supported 67 | #define TYPE_LOCATION 0x0017 68 | #define TYPE_EXT_PORT_ID 0x0018 69 | #define TYPE_POWER_REQUESTED 0x0019 70 | #define TYPE_POWER_AVAILABLE 0x001a // not fully supported 71 | #define TYPE_PORT_UNIDIR 0x001b 72 | 73 | // the names of the above type codes in the same order 74 | static const char* TYPE_NAMES[] = { 75 | NULL, 76 | "Device ID", 77 | "Addresses" , 78 | "Port ID" , 79 | "Capabilities" , 80 | "Software version" , 81 | "Platform" , 82 | "IP Prefix/Gateway (used for ODR)" , 83 | "Protocol Hello" , 84 | "VTP Management Domain" , 85 | "Native VLAN" , 86 | "Duplex" , 87 | NULL, 88 | NULL, 89 | "VoIP VLAN Reply" , 90 | "VoIP VLAN Query" , 91 | "Power consumption" , 92 | "MTU", 93 | "Trust Bitmap" , 94 | "Untrusted Port CoS" , 95 | "System Name" , 96 | "System Object ID" , 97 | "Management Address" , 98 | "Location" , 99 | "External Port-ID" , 100 | "Power Requested" , 101 | "Power Available" , 102 | "Port Unidirectional" , 103 | }; 104 | 105 | #define TYPE_HELLO_CLUSTER_MGMT 0x0112 106 | 107 | static assoc_array type_hello_vals[] = { 108 | { TYPE_HELLO_CLUSTER_MGMT, "Cluster Management" }, 109 | { 0, NULL } 110 | }; 111 | 112 | #define MAC_OFFSET 6 113 | 114 | // bytes the from the beginning of the packet used for Ethernet and LLC 115 | #define ENCAP_OFFSET 22 116 | 117 | // sizes of the type and length fields in the TLV structure 118 | #define TLV_TYPE_SIZE 2 119 | #define TLV_LENGTH_SIZE 2 120 | 121 | 122 | // layer 2 protocol type available 123 | char *PROTO_TYPES[] = { 124 | "Uknown", 125 | "NLPID", 126 | "802.2" 127 | }; 128 | 129 | // IDs of Layer 3 protocols 130 | // NOTE: Keep these in order 131 | double long PROTO[] = { 132 | 0x81, 133 | 0xCC, 134 | 0x86DD, // Cisco says 0x0800 for IPv6 although it is 86DD 135 | 0x6003, 136 | 0x809B, 137 | 0x8137, 138 | 0x80c4, 139 | 0x0600, 140 | 0x8019 141 | }; 142 | 143 | // Layer 3 protocols used 144 | // NOTE: Keep these in order 145 | char PROTO_NAMES[][15] = { 146 | "ISO CLNS", 147 | "IP", 148 | "IPv6", 149 | "DECNET Phase IV", 150 | "AppleTalk", 151 | "Novell IPX", 152 | "Banyan VINES", 153 | "XNS", 154 | "Apollo Domain" 155 | }; 156 | 157 | // bit masks for each available capability 158 | int CAPABILITIES[] = { 159 | 0x01, 160 | 0x02, 161 | 0x04, 162 | 0x08, 163 | 0x10, 164 | 0x20, 165 | 0x40 166 | }; 167 | 168 | // capability names 169 | char CAPABILITIES_NAMES[7][19] = { 170 | "Router", 171 | "Transparent bridge", 172 | "Source Route Bridge", 173 | "Switch", 174 | "Host", 175 | "IGMP", 176 | "Repeater" 177 | }; 178 | 179 | #endif /*SNARF_H_*/ 180 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /cdpsnarf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * CDPSnarf CDP packet sniffer 3 | * Copyright (C) 2006-2010 Tasos "Zapotek" Laskos 4 | * 5 | * 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 2 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License along 18 | * with this program; if not, write to the Free Software Foundation, Inc., 19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 20 | */ 21 | 22 | /** 23 | * @author: Tasos "Zapotek" Laskos 24 | * 25 | * 26 | * @description: 27 | * CDPSnarf is a network sniffer exclusively written to extract 28 | * information from CDP packets. 29 | * It provides all the information a "show cdp neighbors detail" 30 | * command would return on a Cisco router and even more. 31 | * 32 | * Example output: 33 | * ----------------------------------------------------------- 34 | * CDPSnarf v0.1.5 initiated. 35 | * Author: Zapotek 36 | * Website: http://www.segfault.gr 37 | 38 | * Waiting for a CDP packet... 39 | * 40 | * [#1] Sniffed CDP advertisement with a size of 406 bytes. 41 | * 0 seconds since last advertisement. 42 | * ------------------------------------------------------- 43 | * Source MAC address: 0x00:0x0D:0xED:0x42:0xCD:0x02 44 | * 45 | * CDP Version: 2 46 | * TTL: 180 ms 47 | * Checksum: 0x2033 48 | * 49 | * Device ID: cisco-router-1.lab 50 | * 51 | * Addresses: 52 | * Address #: 1 53 | * Protocol type: [1] NLPID format 54 | * Protocol: IP 55 | * Address: 192.168.0.20 56 | * 57 | * 58 | * Address #: 2 59 | * Protocol type: [2] 802.2 format 60 | * Protocol: IPv6 61 | * Address: FE80:0000:0000:0000:0250:56FF:FEC0:000700 62 | * 63 | * 64 | * Port ID: FastEthernet1/2 65 | * 66 | * Capabilities: 67 | * [0x08] Switch 68 | * [0x20] IGMP 69 | * 70 | * Software version: Cisco Internetwork Operating System Software 71 | * IOS (tm) C2950 Software (C2950-I6Q4L2-M), Version 12.1(19)EA1a, RELEASE SOFTWARE (fc1) 72 | * Copyright (c) 1986-2003 by cisco Systems, Inc. 73 | * Compiled Tue 09-Dec-03 00:12 by yenanh 74 | * 75 | * Platform: cisco WS-C2950-12 76 | * 77 | * Protocol Hello: 78 | * OUI: Cisco 79 | * Protocol ID: Cluster Management 80 | * Cluster Master IP address: 0.0.0.0 81 | * Unknown (IP address?): 255.255.255.255 82 | * Version: 1 83 | * Sub Version: 2 84 | * Status: 0x21 85 | * Unknown: 0xFF 86 | * Cluster Commander MAC address: 0x00:0x00:0x00:0x00:0x00:0x00 87 | * Switch's MAC address: 0x00:0x0D:0xDF:0x67:0x00:0xCD 88 | * Unknown: 0xFF 89 | * Management VLAN: 0 90 | * 91 | * 92 | * VTP Management Domain: 93 | * 94 | * Native VLAN: 279 95 | * 96 | * Duplex: [0x01] Full 97 | * 98 | * Trust Bitmap: 0 99 | * 100 | * Untrusted Port CoS: 0 101 | * 102 | * Management Address: 103 | * Address #: 1 104 | * Protocol type: [0] NLPID format 105 | * Protocol: IP 106 | * Address: 192.168.0.20 107 | * ----------------------------------------------------------- 108 | * 109 | * In the absence of a Makefile compile with: 110 | * gcc -lm -lpcap cdpsnarf.c -o cdpsnarf 111 | */ 112 | 113 | /* 114 | * CDP packet format from Cisco: 115 | * http://www.cisco.com/univercd/cc/td/doc/product/lan/trsrb/frames.htm#xtocid12 116 | * 117 | * Additional info from Cisco: 118 | * http://www.cisco.com/en/US/products/hw/switches/ps663/products_tech_note09186a0080094713.shtml#cdp 119 | * 120 | * Wireshark ouput: 121 | * http://wiki.wireshark.org/CDP 122 | * 123 | */ 124 | 125 | #include 126 | #include 127 | #include 128 | #include 129 | #include 130 | #include 131 | #include 132 | #include 133 | #include 134 | #include 135 | #include "cdpsnarf.h" 136 | 137 | #define VERSION "v0.1.6" 138 | #define SVN_REV "$Rev: 797 $" 139 | 140 | void tlv_parse( const u_char* , int ); 141 | int tlv_get_number( const u_char*, int ); 142 | u_char* tlv_get_text( const u_char* , int ); 143 | 144 | void print_cdp_addresses( const u_char *, int, int ); 145 | void print_ipv6_address( const u_char *, int ); 146 | void print_ipv4_address( int ); 147 | void print_ip_prefixes( const u_char *, int ); 148 | void print_capabilities( int ); 149 | void print_protoname( int ); 150 | void print_help( char ** ); 151 | void print_bin( int ); 152 | void payload2hex( const u_char *, int, char * ); 153 | 154 | int* hex2ipv4( int ); 155 | char* get_assoc_value( int, assoc_array * ); 156 | //int compute_checksum( const u_char *, int ); 157 | 158 | int debug = 0; 159 | 160 | int main( int argc, char *argv[] ) { 161 | 162 | // PCAP session handler 163 | pcap_t *handle = 0; 164 | // PCAP dumper pointer 165 | pcap_dumper_t *dumper = 0; 166 | 167 | // the compiled pcap filter 168 | struct bpf_program fp; 169 | // header structure returned by PCAP 170 | struct pcap_pkthdr *header; 171 | 172 | // expression filter for CDP packets 173 | char filter_exp[] = "ether[12:2] <= 1500 && ether[14:2] == 0xAAAA" 174 | " && ether[16:1] == 0x03 && ether[17:2] == 0x0000" 175 | " && ether[19:1] == 0x0C && ether[20:2] == 0x2000" 176 | " && ether host 01:00:0C:CC:CC:CC"; 177 | // device to sniff on 178 | char *dev = NULL; 179 | // error buffer 180 | char errbuf[ PCAP_ERRBUF_SIZE ]; 181 | 182 | // our netmask 183 | bpf_u_int32 mask = 0; 184 | // our IP address 185 | bpf_u_int32 net = 0; 186 | 187 | // pcap_next_ex()'s return value 188 | int pcap_packet = 1; 189 | // captured packet's payload 190 | u_char *data; 191 | 192 | time_t timer = 0; 193 | 194 | char *dumpfile = NULL; 195 | int c; 196 | int i = 0; 197 | 198 | printf( "CDPSnarf %s [%s] initiated.\n", VERSION, SVN_REV ); 199 | printf( " Author: Tasos \"Zapotek\" Laskos\n" ); 200 | printf( " \n" ); 201 | printf( " \n" ); 202 | printf( " Website: http://github.com/Zapotek/cdpsnarf\n\n" ); 203 | 204 | // get command line arguments 205 | while( ( c = getopt( argc, argv, "i:dhw:r:" ) ) != -1 ) { 206 | switch( c ) { 207 | case 'i': 208 | dev = optarg; 209 | handle = pcap_open_live( dev, BUFSIZ, 1, 269000, errbuf ); 210 | 211 | if( handle == NULL ) { 212 | fprintf( stderr, "Couldn't open device %s: %s\n", dev, errbuf ); 213 | return( 2 ); 214 | } 215 | 216 | // get device properties 217 | if( pcap_lookupnet( dev, &net, &mask, errbuf ) == -1 ) { 218 | fprintf( stderr, "Couldn't get netmask for device %s: %s\n", 219 | dev, errbuf ); 220 | net = 0; 221 | mask = 0; 222 | } 223 | break; 224 | 225 | case 'd': 226 | debug = 1; 227 | break; 228 | 229 | case 'r': 230 | dumpfile = optarg; 231 | handle = pcap_open_offline( dumpfile, errbuf ); 232 | if( !handle ){ 233 | fprintf( stderr, "Couldn't open file %s: %s\n", 234 | dumpfile, errbuf ); 235 | return( 2 ); 236 | } 237 | 238 | net = 0; 239 | mask = 0; 240 | break; 241 | 242 | case 'w': 243 | dumper = pcap_dump_open( handle, optarg ); 244 | if( !dumper ){ 245 | fprintf( stderr, "Couldn't write to file %s: %s\n", 246 | optarg, errbuf ); 247 | } 248 | break; 249 | 250 | case '?': 251 | if( optopt == 'd' || optopt == 'w' ) { 252 | fprintf( stderr, "Option -%c requires an argument.\n", 253 | optopt ); 254 | } else if( isprint ( optopt ) ) { 255 | fprintf( stderr, "Unknown option `-%c'.\n", optopt ); 256 | } else { 257 | fprintf( stderr, "Unknown option character `\\x%x'.\n", 258 | optopt ); 259 | } 260 | return 1; 261 | 262 | case 'h': 263 | default: 264 | print_help( argv ); 265 | return( 0 ); 266 | 267 | } 268 | } 269 | 270 | if( !dev && !dumpfile ) { 271 | print_help( argv ); 272 | return( 0 ); 273 | } 274 | 275 | // compile filter 276 | if( pcap_compile( handle, &fp, filter_exp, 0, mask ) < 0 ) { 277 | fprintf( stderr, "Couldn't parse filter %s: %s\n", filter_exp, 278 | pcap_geterr( handle ) ); 279 | return( 2 ); 280 | } 281 | 282 | // apply compiled filter 283 | if( pcap_setfilter( handle, &fp ) < 0 ) { 284 | fprintf( stderr, "Couldn't install filter %s: %s\n", filter_exp, 285 | pcap_geterr( handle ) ); 286 | return( 2 ); 287 | } 288 | 289 | printf( "Reading packets from %s.\n", ( dev ) ? dev : dumpfile ); 290 | printf( "Waiting for a CDP packet...\n\n" ); 291 | 292 | // loop forever 293 | while( pcap_packet == 1 ) { 294 | 295 | // grab a packet 296 | pcap_packet = 297 | pcap_next_ex( handle, &header, (const u_char **) &data ); 298 | 299 | // write each packet to the dumpfile as soon as it arrives 300 | if( dumper ){ 301 | pcap_dump( (u_char *)dumper, header, data ); 302 | pcap_dump_flush( dumper ); 303 | } 304 | 305 | // handle error cases 306 | switch( pcap_packet ){ 307 | // EOF 308 | case -2: 309 | printf( "End of file reached.\nNo more packets to analyze.\n" ); 310 | return( 0 ); 311 | 312 | // unexpected error 313 | case -1: 314 | fprintf( stderr, "An error occurred while capturing packet.\n" ); 315 | return( 2 ); 316 | 317 | // timeout 318 | case 0: 319 | fprintf( stderr, "Timeout waiting for CDP packet.\n" ); 320 | // who cares, just keep waiting... 321 | pcap_packet = 1; 322 | continue; 323 | } 324 | 325 | 326 | // tell user we grabed a packet and it's length 327 | printf( "[#%d] Sniffed CDP advertisement with a size of %d bytes.\n", 328 | i++, header->len ); 329 | 330 | // if this is not our first packet display time delta 331 | if( i > 1 ) { 332 | printf( " %.0f seconds since last advertisement.\n", 333 | difftime( time( 0 ), timer ) ); 334 | } 335 | 336 | printf( "-------------------------------------------------------" ); 337 | 338 | // start timer 339 | timer = time( 0 ); 340 | 341 | // parse TLV tree 342 | tlv_parse( data, header->len ); 343 | 344 | printf( "\n" ); 345 | } 346 | 347 | // close session 348 | pcap_close( handle ); 349 | 350 | return( 0 ); 351 | } 352 | 353 | /** 354 | * Function for Type/Length/Value structure parsing (like CDP frames) 355 | * It traverses the TLV structure and prints out CDP data. 356 | * 357 | * @param const u_char* payload the packet data 358 | * @param int length the packet length 359 | * 360 | */ 361 | void tlv_parse( const u_char* payload, int length ) { 362 | 363 | // the next "Type" field 364 | int tlv_type; 365 | // the next "Length" field 366 | int tlv_length; 367 | int addresses_num, duplex; 368 | int offset = 0; 369 | int tmp = 0; 370 | u_char* value; 371 | // unsigned short our_checksum; 372 | 373 | printf( "\nSource MAC address: " ); 374 | payload2hex( payload + MAC_OFFSET, 6, ":" ); 375 | 376 | // compute_checksum( payload, length ); 377 | 378 | // set payload pointer right after Ethernet and LLC data 379 | payload += ENCAP_OFFSET; 380 | 381 | // get CDP version 382 | printf( "\nCDP Version: %d\n", *(payload++) ); 383 | 384 | // get CDP time-to-live 385 | printf( "TTL: %d ms\n", *(payload++) ); 386 | 387 | // get checksum 388 | tmp = tlv_get_number( payload, 2 ); 389 | printf( "Checksum: 0x%02X ", tmp ); 390 | payload += 2; 391 | 392 | // our_checksum = crc16_checksum( payload, length - ENCAP_OFFSET - 4 ); 393 | 394 | // printf( "\n---------------\n" ); 395 | // payload2hex( payload, length - ENCAP_OFFSET - 4, " 0x" ); 396 | // printf( "\n---------------\n" ); 397 | 398 | // if( our_checksum == tmp ) { 399 | // printf( "[Correct, 0x%02X]", our_checksum ); 400 | // } else { 401 | // printf( "[Invalid, should be 0x%02X]", our_checksum ); 402 | // } 403 | 404 | printf( "\n\n" ); 405 | 406 | // subtract Ethernet & LLC encapsulation 407 | length -= ENCAP_OFFSET + 4; 408 | // parse TLV until we reach the end of packet data 409 | while( length ) { 410 | 411 | // get next Type 412 | tlv_type = tlv_get_number( payload, TLV_TYPE_SIZE ); 413 | if( debug ) printf( "[TLV type: 0x%02X]\n", tlv_type ); 414 | // appropriately forward the pointer 415 | payload += TLV_TYPE_SIZE; 416 | 417 | // get next Length 418 | tlv_length = tlv_get_number( payload, TLV_LENGTH_SIZE ); 419 | if( debug ) printf( "[TLV length: %d bytes]\n", tlv_length ); 420 | /* 421 | * subtract the length of the Type field and the Length field to 422 | * accurately get the length of the Value field 423 | */ 424 | tlv_length -= TLV_TYPE_SIZE + TLV_LENGTH_SIZE; 425 | // appropriately forward the pointer 426 | payload += TLV_LENGTH_SIZE; 427 | 428 | // print current type name 429 | printf( "%s: ", TYPE_NAMES[tlv_type] ); 430 | 431 | switch( tlv_type ) { 432 | 433 | // addresses are special because the require further parsing 434 | case TYPE_ADDRESS: 435 | case TYPE_MANAGEMENT_ADDR: 436 | // get the number of addresses included in the packet 437 | addresses_num = tlv_get_number( payload, 4 ); 438 | // parse addresses into the addresses struct 439 | print_cdp_addresses( payload, addresses_num, tlv_length ); 440 | break; 441 | 442 | // capabilities require bitmask matching 443 | case TYPE_CAPABILITIES: 444 | printf( "\n" ); 445 | print_capabilities( tlv_get_number( payload, tlv_length ) ); 446 | break; 447 | 448 | // nothing special about duplex, just requires a bit more logic 449 | case TYPE_DUPLEX: 450 | duplex = tlv_get_number( payload, tlv_length ); 451 | 452 | printf( "[0x%02x] %s\n", duplex, 453 | ( duplex ) ? "Full" : "Half" ); 454 | break; 455 | 456 | case TYPE_PROTOCOL_HELLO: 457 | printf( "\n" ); 458 | 459 | tmp = tlv_get_number( payload, 3 ); 460 | 461 | printf( " OUI: %s\n", get_assoc_value( tmp, OUI_NAMES ) ); 462 | offset += 3; 463 | 464 | tmp = tlv_get_number( payload + offset, 2 ); 465 | 466 | printf( " Protocol ID: %s\n", 467 | get_assoc_value( tmp, type_hello_vals ) ); 468 | 469 | if( tmp == TYPE_HELLO_CLUSTER_MGMT ){ 470 | offset += 2; 471 | 472 | printf( " Cluster Master IP address: " ); 473 | tmp = tlv_get_number( payload + offset, 4 ); 474 | print_ipv4_address( tmp ); 475 | offset += 4; 476 | 477 | printf( "\n Unknown (IP address?): " ); 478 | tmp = tlv_get_number( payload + offset, 4 ); 479 | print_ipv4_address( tmp ); 480 | offset += 4; 481 | 482 | printf( "\n Version: %d\n", 483 | tlv_get_number( payload + offset, 1 ) ); 484 | offset += 1; 485 | 486 | printf( " Sub Version: %d\n", 487 | tlv_get_number( payload + offset, 1 ) ); 488 | offset += 1; 489 | 490 | printf( " Status: 0x%02X\n", 491 | tlv_get_number( payload + offset, 1 ) ); 492 | offset += 1; 493 | 494 | printf( " Unknown: 0x%02X\n", 495 | tlv_get_number( payload + offset, 1 ) ); 496 | offset += 1; 497 | 498 | printf( " Cluster Commander MAC address: " ); 499 | payload2hex( payload + offset, 6, ":" ); 500 | offset += 6; 501 | 502 | printf( " Switch's MAC address: " ); 503 | payload2hex( payload + offset, 6, ":" ); 504 | offset += 6; 505 | 506 | printf( " Unknown: 0x%02X\n", 507 | tlv_get_number( payload + offset, 1 ) ); 508 | offset += 1; 509 | 510 | printf( " Management VLAN: %d\n", 511 | tlv_get_number( payload + offset, 1 ) ); 512 | offset += 1; 513 | } 514 | 515 | printf( "\n" ); 516 | break; 517 | 518 | case TYPE_POWER_AVAILABLE: 519 | printf( "\n" ); 520 | printf( " Request ID: %u(?)\n", 521 | tlv_get_number( payload, 4 ) ); 522 | offset += 4; 523 | 524 | printf( " Management ID: %u(?)\n", 525 | tlv_get_number( payload + offset, 4 ) ); 526 | offset += 4; 527 | 528 | tmp = tlv_get_number( payload + offset, TLV_LENGTH_SIZE ); 529 | printf( " Power Available: %u mW(?)\n", 530 | tlv_get_number( payload + offset, 2 ) ); 531 | 532 | break; 533 | 534 | case TYPE_TRUST_BITMAP: 535 | tmp = tlv_get_number( payload, 2 ); 536 | printf( "0x%02X", tmp ); 537 | if( tmp ) { 538 | printf( "[" ); 539 | print_bin( tmp ); 540 | printf( "]" ); 541 | } 542 | printf( "\n" ); 543 | break; 544 | 545 | case TYPE_IP_PREFIX: 546 | printf( "\n" ); 547 | print_ip_prefixes( payload, tlv_length ); 548 | break; 549 | 550 | case TYPE_MTU: 551 | case TYPE_NATIVE_VLAN: 552 | case TYPE_UNTRUSTED_COS: 553 | printf( "%u\n", tlv_get_number( payload, 2 ) ); 554 | break; 555 | 556 | // the rest type values are just text, so print the text 557 | default: 558 | value = tlv_get_text( payload, tlv_length ); 559 | printf( "%s\n", value ); 560 | free( value ); 561 | break; 562 | } 563 | 564 | tmp = 0; 565 | offset = 0; 566 | // forward pointer to the next TLV 567 | payload += tlv_length; 568 | // lessen the length variable 569 | length -= tlv_length + TLV_TYPE_SIZE + TLV_LENGTH_SIZE; 570 | 571 | printf( "\n" ); 572 | 573 | } 574 | 575 | } 576 | 577 | /** 578 | * Function for getting a number residing in the next "length" bytes 579 | * of the payload 580 | * 581 | * @param const u_char* payload the payload 582 | * @param int length the aforementioned length 583 | * 584 | * @return int the aforementioned number 585 | */ 586 | int tlv_get_number( const u_char* payload, int length ) { 587 | int z, tl; 588 | long div; 589 | 590 | tl = 0x0; 591 | for( div = pow( 0x100, length - 1 ), z = 0; 592 | z < length; 593 | div /= 0x100, z++ ) 594 | { 595 | tl += ( div ) ? *payload++ * div : *payload++ ; 596 | } 597 | 598 | return tl; 599 | } 600 | 601 | /** 602 | * Function for getting a string residing in the next "length" bytes 603 | * of the payload 604 | * 605 | * @param const u_char* payload the payload 606 | * @param int length the aforementioned length 607 | * 608 | * @return const u_char* the aforementioned string 609 | */ 610 | u_char* tlv_get_text( const u_char* payload, int length ) { 611 | u_char* value; 612 | 613 | value = malloc( length + 1); 614 | memcpy( value, payload, length ); 615 | value[length] = '\0'; 616 | 617 | return value; 618 | } 619 | 620 | /** 621 | * Function for parsing the Addresses field of the CDP packet into 622 | * addresses struct 623 | * 624 | * @param const u_char *payload payload pointer located right 625 | * before the addresses field 626 | * 627 | * @param int address_num the number of included addresses 628 | * @param int address_len the length of the field 629 | * 630 | */ 631 | void print_cdp_addresses( const u_char *payload, int address_num, 632 | int address_len ) 633 | { 634 | int i; 635 | 636 | payload += 4; 637 | 638 | // save enough space for all included addresses 639 | addresses = calloc( address_num, address_len ); 640 | /* 641 | * loop thought all the addresses harvesting data and storing them 642 | * into the appropriate members of addresses 643 | */ 644 | for( i = 0; i < address_num; addresses++, i++ ) { 645 | printf( "\n Address #: %d\n", i + 1 ); 646 | addresses->proto_type = *payload++; 647 | 648 | if( debug ) 649 | printf( "[Protocol type: 0x%04X]\n", addresses->proto_type ); 650 | 651 | printf( " Protocol type: [%d] %s format\n", 652 | addresses->proto_type, 653 | PROTO_TYPES[addresses->proto_type] ); 654 | 655 | addresses->proto_len = *payload++; 656 | if( debug ) 657 | printf( "[Protocol length: %d bytes]\n", addresses->proto_len ); 658 | 659 | /* 660 | * The cool thing with protocols other than IP and ISO CLNS 661 | * (whose protocol length is 1 byte) 662 | * is that they all have a suffix of 0xaaaa03000000 so we can 663 | * ignore it and store only the 2 last hex values (ex. 86dd for IPv6) 664 | * 665 | */ 666 | if( addresses->proto_len == 8 ) { 667 | addresses->proto = 668 | tlv_get_number( payload + (addresses->proto_len - 2), 2 ); 669 | } else { 670 | addresses->proto = 671 | tlv_get_number( payload, addresses->proto_len ); 672 | } 673 | 674 | if( debug ) 675 | printf( "[Address protocol: 0x%04X]\n", addresses->proto ); 676 | 677 | printf( " Protocol: " ); 678 | print_protoname( addresses->proto ); 679 | printf( " \n" ); 680 | 681 | payload += addresses->proto_len; 682 | 683 | addresses->address_len = 684 | tlv_get_number( payload, TLV_LENGTH_SIZE ); 685 | 686 | if( debug ) 687 | printf( "[Address length: %d bytes]\n", addresses->address_len ); 688 | 689 | payload += TLV_LENGTH_SIZE; 690 | 691 | printf( " Address: " ); 692 | if( addresses->address_len <= 4 ) { 693 | print_ipv4_address( tlv_get_number( payload, addresses->address_len ) ); 694 | } else { 695 | print_ipv6_address( tlv_get_text( payload, addresses->address_len ), 696 | addresses->address_len ); 697 | } 698 | printf( "\n\n" ); 699 | 700 | payload += addresses->address_len; 701 | } 702 | 703 | addresses -= i; 704 | 705 | free( addresses ); 706 | } 707 | 708 | /** 709 | * Function for convertng hexadecimal IP addresses to decimal parts 710 | * ( ex. 0xC0A80014 to 192.168.0.20 ) 711 | * 712 | * @param int hex hexadecimal format of IP address 713 | * 714 | * @return array with 4 entries holding each IP address decimal value 715 | */ 716 | int* hex2ipv4( int hex ) { 717 | int *ip_address; 718 | 719 | ip_address = calloc( 4, sizeof(int) ); 720 | 721 | ip_address[3] = hex & 0xff; 722 | ip_address[2] = (hex & 0xff00) / 0x100; 723 | ip_address[1] = (hex & 0xff0000) / 0x10000; 724 | ip_address[0] = (hex & 0xff000000) / 0x1000000; 725 | 726 | return ip_address; 727 | } 728 | 729 | /** 730 | * Print IPv4 address based on a hexadecimal value 731 | * 732 | * @param int hex hex version of the IP address 733 | * 734 | */ 735 | void print_ipv4_address( int hex ) { 736 | int *ip_address; 737 | 738 | ip_address = hex2ipv4( hex ); 739 | printf( "%u.%u.%u.%u", 740 | ip_address[0], 741 | ip_address[1], 742 | ip_address[2], 743 | ip_address[3] ); 744 | 745 | free( ip_address ); 746 | } 747 | 748 | /** 749 | * Print IPv6 address based on a hexadecimal string 750 | * 751 | * @param const u_char *payload hex string of the IP address 752 | * @param int length length of the IP address 753 | * 754 | */ 755 | void print_ipv6_address( const u_char *payload, int length ) { 756 | do { 757 | printf( "%02X", *payload++ ); 758 | if( length != 1 && length % 2 ) printf( ":" ); 759 | } while( length-- ); 760 | } 761 | 762 | /** 763 | * Prints IPv4 prefixes 764 | * 765 | * @param const u_char *payload payload right before the IP prefixes 766 | * @param int length length of the IP prefixes 767 | * 768 | */ 769 | void print_ip_prefixes( const u_char *payload, int length ) { 770 | int iterations, offset = 0, i = 1; 771 | 772 | for( iterations = length / 5; iterations; iterations--, offset += 5 ) { 773 | printf( " [%d] ", i++ ); 774 | print_ipv4_address( tlv_get_number( payload + offset, 4 ) ); 775 | printf( "/%d\n", tlv_get_number( payload + 4 + offset, 1 ) ); 776 | } 777 | 778 | } 779 | 780 | /** 781 | * Print help message 782 | * 783 | * @param char *argv[] program command line arguments 784 | * 785 | */ 786 | void print_help( char *argv[] ) { 787 | printf( "%s -i [-h] [-w savefile] [-r dumpfile] [-d]\n\n", argv[0] ); 788 | printf( " -i define the interface to sniff on\n" ); 789 | printf( " -w write packets to PCAP dump file\n" ); 790 | printf( " -r read packets from PCAP dump file\n" ); 791 | printf( " -d show debugging information\n" ); 792 | printf( " -h show help message and exit\n\n" ); 793 | } 794 | 795 | /** 796 | * Function for printing device's capabilities 797 | * 798 | * @param int bitmask hexadecimal capabilities' bitmask 799 | * 800 | */ 801 | void print_capabilities( int bitmask ) { 802 | int i; 803 | 804 | // loop through all capability bitmasks searching for matches 805 | for( i = 0; i < sizeof CAPABILITIES / sizeof (int); i++ ) { 806 | // print match 807 | if( CAPABILITIES[i] & bitmask ) 808 | printf( " [0x%02X]\t%s\n", CAPABILITIES[i], 809 | CAPABILITIES_NAMES[i] ); 810 | } 811 | } 812 | 813 | /** 814 | * Function for printing protocol in use 815 | * 816 | * @param int hex hexadecimal protocol ID 817 | * 818 | */ 819 | void print_protoname( int hex ) { 820 | int i; 821 | 822 | for( i = 0; i < sizeof PROTO_NAMES / sizeof (char); i++ ) { 823 | if( PROTO[i] == hex ) { 824 | printf( "%s", PROTO_NAMES[i] ); 825 | return; 826 | } 827 | 828 | } 829 | printf( "Uknown" ); 830 | } 831 | 832 | /** 833 | * Simple debugging function for printing a given payload as a 834 | * sequence of hexadecimal values 835 | * 836 | * @param const u_char *payload the payload 837 | * @param int length how much of the payload to print 838 | * @param char *delim delimiter between hex values 839 | * 840 | */ 841 | void payload2hex( const u_char *payload, int length, char *delim ) { 842 | 843 | while( length-- ) { 844 | printf( "%02X", *payload++ ); 845 | if( length != 0 ) printf( "%s", delim ); 846 | } 847 | printf( "\n" ); 848 | 849 | } 850 | 851 | /** 852 | * Function used with the "_assoc_array" struct in order to get 853 | * stored strings based on the stored values 854 | * 855 | * @param int value the value to look for 856 | * @param assoc_array *aray the struct 857 | * 858 | * @return char * 859 | */ 860 | char* get_assoc_value( int value, assoc_array *array ){ 861 | int i = 0; 862 | while( array[i].string ){ 863 | if( array[i].value == value ) return (char *) array[i].string; 864 | i++; 865 | } 866 | return 0; 867 | } 868 | 869 | /** 870 | * Print binary representation of a number 871 | * 872 | * @param int num number to convert to binary 873 | */ 874 | void print_bin( int number ) { 875 | int remainder; 876 | 877 | if( number <= 1 ) { 878 | printf( "%d", number ); 879 | return; 880 | } 881 | 882 | remainder = number % 2; 883 | print_bin( number >> 1 ); 884 | printf( "%d", remainder ); 885 | } 886 | 887 | //int compute_checksum( const u_char *payload, int length ) { 888 | // u_char *data; 889 | // 890 | // data = malloc( length + 20 ); 891 | // 892 | // memcpy( data, payload, ENCAP_OFFSET + 2 ); 893 | // data += ENCAP_OFFSET + 2; 894 | // memcpy( data, payload + ENCAP_OFFSET + 4, length - 2 ); 895 | // data -= ENCAP_OFFSET + 2; 896 | // 897 | // payload2hex( payload, length, " 0x" ); 898 | // printf( "\n-----------------\n" ); 899 | // payload2hex( data, length - 2, " 0x" ); 900 | // 901 | // printf( "\n:::: 0x%04X ::::\n", crc16_checksum( data, length - 2 ) ); 902 | // printf( ":::: 0x%04X ::::\n", crc16_checksum( payload, length ) ); 903 | // 904 | // free( data ); 905 | // 906 | // return( 1 ); 907 | //} 908 | --------------------------------------------------------------------------------