print-vtp.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. /*
  2. * Copyright (c) 1998-2007 The TCPDUMP project
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that: (1) source code
  6. * distributions retain the above copyright notice and this paragraph
  7. * in its entirety, and (2) distributions including binary code include
  8. * the above copyright notice and this paragraph in its entirety in
  9. * the documentation or other materials provided with the distribution.
  10. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
  11. * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
  12. * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  13. * FOR A PARTICULAR PURPOSE.
  14. *
  15. * Reference documentation:
  16. * http://www.cisco.com/c/en/us/support/docs/lan-switching/vtp/10558-21.html
  17. * http://docstore.mik.ua/univercd/cc/td/doc/product/lan/trsrb/frames.htm
  18. *
  19. * Original code ode by Carles Kishimoto <carles.kishimoto@gmail.com>
  20. */
  21. /* \summary: Cisco VLAN Trunking Protocol (VTP) printer */
  22. #ifdef HAVE_CONFIG_H
  23. #include "config.h"
  24. #endif
  25. #include <netdissect-stdinc.h>
  26. #include "netdissect.h"
  27. #include "addrtoname.h"
  28. #include "extract.h"
  29. #define VTP_HEADER_LEN 36
  30. #define VTP_DOMAIN_NAME_LEN 32
  31. #define VTP_MD5_DIGEST_LEN 16
  32. #define VTP_UPDATE_TIMESTAMP_LEN 12
  33. #define VTP_VLAN_INFO_FIXED_PART_LEN 12 /* length of VLAN info before VLAN name */
  34. #define VTP_SUMMARY_ADV 0x01
  35. #define VTP_SUBSET_ADV 0x02
  36. #define VTP_ADV_REQUEST 0x03
  37. #define VTP_JOIN_MESSAGE 0x04
  38. struct vtp_vlan_ {
  39. uint8_t len;
  40. uint8_t status;
  41. uint8_t type;
  42. uint8_t name_len;
  43. uint16_t vlanid;
  44. uint16_t mtu;
  45. uint32_t index;
  46. };
  47. static const struct tok vtp_message_type_values[] = {
  48. { VTP_SUMMARY_ADV, "Summary advertisement"},
  49. { VTP_SUBSET_ADV, "Subset advertisement"},
  50. { VTP_ADV_REQUEST, "Advertisement request"},
  51. { VTP_JOIN_MESSAGE, "Join message"},
  52. { 0, NULL }
  53. };
  54. static const struct tok vtp_header_values[] = {
  55. { 0x01, "Followers"}, /* On Summary advertisement, 3rd byte is Followers */
  56. { 0x02, "Seq number"}, /* On Subset advertisement, 3rd byte is Sequence number */
  57. { 0x03, "Rsvd"}, /* On Adver. requests 3rd byte is Rsvd */
  58. { 0x04, "Rsvd"}, /* On Adver. requests 3rd byte is Rsvd */
  59. { 0, NULL }
  60. };
  61. static const struct tok vtp_vlan_type_values[] = {
  62. { 0x01, "Ethernet"},
  63. { 0x02, "FDDI"},
  64. { 0x03, "TrCRF"},
  65. { 0x04, "FDDI-net"},
  66. { 0x05, "TrBRF"},
  67. { 0, NULL }
  68. };
  69. static const struct tok vtp_vlan_status[] = {
  70. { 0x00, "Operational"},
  71. { 0x01, "Suspended"},
  72. { 0, NULL }
  73. };
  74. #define VTP_VLAN_SOURCE_ROUTING_RING_NUMBER 0x01
  75. #define VTP_VLAN_SOURCE_ROUTING_BRIDGE_NUMBER 0x02
  76. #define VTP_VLAN_STP_TYPE 0x03
  77. #define VTP_VLAN_PARENT_VLAN 0x04
  78. #define VTP_VLAN_TRANS_BRIDGED_VLAN 0x05
  79. #define VTP_VLAN_PRUNING 0x06
  80. #define VTP_VLAN_BRIDGE_TYPE 0x07
  81. #define VTP_VLAN_ARP_HOP_COUNT 0x08
  82. #define VTP_VLAN_STE_HOP_COUNT 0x09
  83. #define VTP_VLAN_BACKUP_CRF_MODE 0x0A
  84. static const struct tok vtp_vlan_tlv_values[] = {
  85. { VTP_VLAN_SOURCE_ROUTING_RING_NUMBER, "Source-Routing Ring Number TLV"},
  86. { VTP_VLAN_SOURCE_ROUTING_BRIDGE_NUMBER, "Source-Routing Bridge Number TLV"},
  87. { VTP_VLAN_STP_TYPE, "STP type TLV"},
  88. { VTP_VLAN_PARENT_VLAN, "Parent VLAN TLV"},
  89. { VTP_VLAN_TRANS_BRIDGED_VLAN, "Translationally bridged VLANs TLV"},
  90. { VTP_VLAN_PRUNING, "Pruning TLV"},
  91. { VTP_VLAN_BRIDGE_TYPE, "Bridge Type TLV"},
  92. { VTP_VLAN_ARP_HOP_COUNT, "Max ARP Hop Count TLV"},
  93. { VTP_VLAN_STE_HOP_COUNT, "Max STE Hop Count TLV"},
  94. { VTP_VLAN_BACKUP_CRF_MODE, "Backup CRF Mode TLV"},
  95. { 0, NULL }
  96. };
  97. static const struct tok vtp_stp_type_values[] = {
  98. { 1, "SRT"},
  99. { 2, "SRB"},
  100. { 3, "Auto"},
  101. { 0, NULL }
  102. };
  103. void
  104. vtp_print (netdissect_options *ndo,
  105. const u_char *pptr, u_int length)
  106. {
  107. int type, len, tlv_len, tlv_value, mgmtd_len;
  108. const u_char *tptr;
  109. const struct vtp_vlan_ *vtp_vlan;
  110. if (length < VTP_HEADER_LEN)
  111. goto trunc;
  112. tptr = pptr;
  113. ND_TCHECK2(*tptr, VTP_HEADER_LEN);
  114. type = *(tptr+1);
  115. ND_PRINT((ndo, "VTPv%u, Message %s (0x%02x), length %u",
  116. *tptr,
  117. tok2str(vtp_message_type_values,"Unknown message type", type),
  118. type,
  119. length));
  120. /* In non-verbose mode, just print version and message type */
  121. if (ndo->ndo_vflag < 1) {
  122. return;
  123. }
  124. /* verbose mode print all fields */
  125. ND_PRINT((ndo, "\n\tDomain name: "));
  126. mgmtd_len = *(tptr + 3);
  127. if (mgmtd_len < 1 || mgmtd_len > 32) {
  128. ND_PRINT((ndo, " [invalid MgmtD Len %d]", mgmtd_len));
  129. return;
  130. }
  131. fn_printzp(ndo, tptr + 4, mgmtd_len, NULL);
  132. ND_PRINT((ndo, ", %s: %u",
  133. tok2str(vtp_header_values, "Unknown", type),
  134. *(tptr+2)));
  135. tptr += VTP_HEADER_LEN;
  136. switch (type) {
  137. case VTP_SUMMARY_ADV:
  138. /*
  139. * SUMMARY ADVERTISEMENT
  140. *
  141. * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  142. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  143. * | Version | Code | Followers | MgmtD Len |
  144. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  145. * | Management Domain Name (zero-padded to 32 bytes) |
  146. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  147. * | Configuration revision number |
  148. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  149. * | Updater Identity IP address |
  150. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  151. * | Update Timestamp (12 bytes) |
  152. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  153. * | MD5 digest (16 bytes) |
  154. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  155. *
  156. */
  157. ND_TCHECK2(*tptr, 8);
  158. ND_PRINT((ndo, "\n\t Config Rev %x, Updater %s",
  159. EXTRACT_32BITS(tptr),
  160. ipaddr_string(ndo, tptr+4)));
  161. tptr += 8;
  162. ND_TCHECK2(*tptr, VTP_UPDATE_TIMESTAMP_LEN);
  163. ND_PRINT((ndo, ", Timestamp 0x%08x 0x%08x 0x%08x",
  164. EXTRACT_32BITS(tptr),
  165. EXTRACT_32BITS(tptr + 4),
  166. EXTRACT_32BITS(tptr + 8)));
  167. tptr += VTP_UPDATE_TIMESTAMP_LEN;
  168. ND_TCHECK2(*tptr, VTP_MD5_DIGEST_LEN);
  169. ND_PRINT((ndo, ", MD5 digest: %08x%08x%08x%08x",
  170. EXTRACT_32BITS(tptr),
  171. EXTRACT_32BITS(tptr + 4),
  172. EXTRACT_32BITS(tptr + 8),
  173. EXTRACT_32BITS(tptr + 12)));
  174. tptr += VTP_MD5_DIGEST_LEN;
  175. break;
  176. case VTP_SUBSET_ADV:
  177. /*
  178. * SUBSET ADVERTISEMENT
  179. *
  180. * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  181. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  182. * | Version | Code | Seq number | MgmtD Len |
  183. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  184. * | Management Domain Name (zero-padded to 32 bytes) |
  185. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  186. * | Configuration revision number |
  187. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  188. * | VLAN info field 1 |
  189. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  190. * | ................ |
  191. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  192. * | VLAN info field N |
  193. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  194. *
  195. */
  196. ND_TCHECK_32BITS(tptr);
  197. ND_PRINT((ndo, ", Config Rev %x", EXTRACT_32BITS(tptr)));
  198. /*
  199. * VLAN INFORMATION
  200. * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  201. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  202. * | V info len | Status | VLAN type | VLAN name len |
  203. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  204. * | ISL vlan id | MTU size |
  205. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  206. * | 802.10 index (SAID) |
  207. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  208. * | VLAN name |
  209. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  210. *
  211. */
  212. tptr += 4;
  213. while (tptr < (pptr+length)) {
  214. ND_TCHECK_8BITS(tptr);
  215. len = *tptr;
  216. if (len == 0)
  217. break;
  218. ND_TCHECK2(*tptr, len);
  219. vtp_vlan = (const struct vtp_vlan_*)tptr;
  220. if (len < VTP_VLAN_INFO_FIXED_PART_LEN)
  221. goto trunc;
  222. ND_TCHECK(*vtp_vlan);
  223. ND_PRINT((ndo, "\n\tVLAN info status %s, type %s, VLAN-id %u, MTU %u, SAID 0x%08x, Name ",
  224. tok2str(vtp_vlan_status,"Unknown",vtp_vlan->status),
  225. tok2str(vtp_vlan_type_values,"Unknown",vtp_vlan->type),
  226. EXTRACT_16BITS(&vtp_vlan->vlanid),
  227. EXTRACT_16BITS(&vtp_vlan->mtu),
  228. EXTRACT_32BITS(&vtp_vlan->index)));
  229. len -= VTP_VLAN_INFO_FIXED_PART_LEN;
  230. tptr += VTP_VLAN_INFO_FIXED_PART_LEN;
  231. if (len < 4*((vtp_vlan->name_len + 3)/4))
  232. goto trunc;
  233. ND_TCHECK2(*tptr, vtp_vlan->name_len);
  234. fn_printzp(ndo, tptr, vtp_vlan->name_len, NULL);
  235. /*
  236. * Vlan names are aligned to 32-bit boundaries.
  237. */
  238. len -= 4*((vtp_vlan->name_len + 3)/4);
  239. tptr += 4*((vtp_vlan->name_len + 3)/4);
  240. /* TLV information follows */
  241. while (len > 0) {
  242. /*
  243. * Cisco specs say 2 bytes for type + 2 bytes for length;
  244. * see http://docstore.mik.ua/univercd/cc/td/doc/product/lan/trsrb/frames.htm
  245. * However, actual packets on the wire appear to use 1
  246. * byte for the type and 1 byte for the length, so that's
  247. * what we do.
  248. */
  249. if (len < 2)
  250. goto trunc;
  251. ND_TCHECK2(*tptr, 2);
  252. type = *tptr;
  253. tlv_len = *(tptr+1);
  254. ND_PRINT((ndo, "\n\t\t%s (0x%04x) TLV",
  255. tok2str(vtp_vlan_tlv_values, "Unknown", type),
  256. type));
  257. if (len < tlv_len * 2 + 2) {
  258. ND_PRINT((ndo, " (TLV goes past the end of the packet)"));
  259. return;
  260. }
  261. ND_TCHECK2(*tptr, tlv_len * 2 +2);
  262. /*
  263. * We assume the value is a 2-byte integer; the length is
  264. * in units of 16-bit words.
  265. */
  266. if (tlv_len != 1) {
  267. ND_PRINT((ndo, " (invalid TLV length %u != 1)", tlv_len));
  268. return;
  269. } else {
  270. tlv_value = EXTRACT_16BITS(tptr+2);
  271. switch (type) {
  272. case VTP_VLAN_STE_HOP_COUNT:
  273. ND_PRINT((ndo, ", %u", tlv_value));
  274. break;
  275. case VTP_VLAN_PRUNING:
  276. ND_PRINT((ndo, ", %s (%u)",
  277. tlv_value == 1 ? "Enabled" : "Disabled",
  278. tlv_value));
  279. break;
  280. case VTP_VLAN_STP_TYPE:
  281. ND_PRINT((ndo, ", %s (%u)",
  282. tok2str(vtp_stp_type_values, "Unknown", tlv_value),
  283. tlv_value));
  284. break;
  285. case VTP_VLAN_BRIDGE_TYPE:
  286. ND_PRINT((ndo, ", %s (%u)",
  287. tlv_value == 1 ? "SRB" : "SRT",
  288. tlv_value));
  289. break;
  290. case VTP_VLAN_BACKUP_CRF_MODE:
  291. ND_PRINT((ndo, ", %s (%u)",
  292. tlv_value == 1 ? "Backup" : "Not backup",
  293. tlv_value));
  294. break;
  295. /*
  296. * FIXME those are the defined TLVs that lack a decoder
  297. * you are welcome to contribute code ;-)
  298. */
  299. case VTP_VLAN_SOURCE_ROUTING_RING_NUMBER:
  300. case VTP_VLAN_SOURCE_ROUTING_BRIDGE_NUMBER:
  301. case VTP_VLAN_PARENT_VLAN:
  302. case VTP_VLAN_TRANS_BRIDGED_VLAN:
  303. case VTP_VLAN_ARP_HOP_COUNT:
  304. default:
  305. print_unknown_data(ndo, tptr, "\n\t\t ", 2 + tlv_len*2);
  306. break;
  307. }
  308. }
  309. len -= 2 + tlv_len*2;
  310. tptr += 2 + tlv_len*2;
  311. }
  312. }
  313. break;
  314. case VTP_ADV_REQUEST:
  315. /*
  316. * ADVERTISEMENT REQUEST
  317. *
  318. * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  319. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  320. * | Version | Code | Reserved | MgmtD Len |
  321. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  322. * | Management Domain Name (zero-padded to 32 bytes) |
  323. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  324. * | Start value |
  325. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  326. *
  327. */
  328. ND_TCHECK2(*tptr, 4);
  329. ND_PRINT((ndo, "\n\tStart value: %u", EXTRACT_32BITS(tptr)));
  330. break;
  331. case VTP_JOIN_MESSAGE:
  332. /* FIXME - Could not find message format */
  333. break;
  334. default:
  335. break;
  336. }
  337. return;
  338. trunc:
  339. ND_PRINT((ndo, "[|vtp]"));
  340. }
  341. /*
  342. * Local Variables:
  343. * c-style: whitesmith
  344. * c-basic-offset: 4
  345. * End:
  346. */