├── 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 |
--------------------------------------------------------------------------------