print-ldp.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698
  1. /*
  2. * Redistribution and use in source and binary forms, with or without
  3. * modification, are permitted provided that: (1) source code
  4. * distributions retain the above copyright notice and this paragraph
  5. * in its entirety, and (2) distributions including binary code include
  6. * the above copyright notice and this paragraph in its entirety in
  7. * the documentation or other materials provided with the distribution.
  8. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
  9. * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
  10. * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  11. * FOR A PARTICULAR PURPOSE.
  12. *
  13. * Original code by Hannes Gredler (hannes@gredler.at)
  14. * and Steinar Haug (sthaug@nethelp.no)
  15. */
  16. /* \summary: Label Distribution Protocol (LDP) printer */
  17. #ifdef HAVE_CONFIG_H
  18. #include "config.h"
  19. #endif
  20. #include <netdissect-stdinc.h>
  21. #include "netdissect.h"
  22. #include "extract.h"
  23. #include "addrtoname.h"
  24. #include "l2vpn.h"
  25. #include "af.h"
  26. /*
  27. * ldp common header
  28. *
  29. * 0 1 2 3
  30. * 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
  31. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  32. * | Version | PDU Length |
  33. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  34. * | LDP Identifier |
  35. * + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  36. * | |
  37. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  38. *
  39. */
  40. struct ldp_common_header {
  41. uint8_t version[2];
  42. uint8_t pdu_length[2];
  43. uint8_t lsr_id[4];
  44. uint8_t label_space[2];
  45. };
  46. #define LDP_VERSION 1
  47. /*
  48. * ldp message header
  49. *
  50. * 0 1 2 3
  51. * 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
  52. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  53. * |U| Message Type | Message Length |
  54. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  55. * | Message ID |
  56. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  57. * | |
  58. * + +
  59. * | Mandatory Parameters |
  60. * + +
  61. * | |
  62. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  63. * | |
  64. * + +
  65. * | Optional Parameters |
  66. * + +
  67. * | |
  68. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  69. */
  70. struct ldp_msg_header {
  71. uint8_t type[2];
  72. uint8_t length[2];
  73. uint8_t id[4];
  74. };
  75. #define LDP_MASK_MSG_TYPE(x) ((x)&0x7fff)
  76. #define LDP_MASK_U_BIT(x) ((x)&0x8000)
  77. #define LDP_MSG_NOTIF 0x0001
  78. #define LDP_MSG_HELLO 0x0100
  79. #define LDP_MSG_INIT 0x0200
  80. #define LDP_MSG_KEEPALIVE 0x0201
  81. #define LDP_MSG_ADDRESS 0x0300
  82. #define LDP_MSG_ADDRESS_WITHDRAW 0x0301
  83. #define LDP_MSG_LABEL_MAPPING 0x0400
  84. #define LDP_MSG_LABEL_REQUEST 0x0401
  85. #define LDP_MSG_LABEL_WITHDRAW 0x0402
  86. #define LDP_MSG_LABEL_RELEASE 0x0403
  87. #define LDP_MSG_LABEL_ABORT_REQUEST 0x0404
  88. #define LDP_VENDOR_PRIVATE_MIN 0x3e00
  89. #define LDP_VENDOR_PRIVATE_MAX 0x3eff
  90. #define LDP_EXPERIMENTAL_MIN 0x3f00
  91. #define LDP_EXPERIMENTAL_MAX 0x3fff
  92. static const struct tok ldp_msg_values[] = {
  93. { LDP_MSG_NOTIF, "Notification" },
  94. { LDP_MSG_HELLO, "Hello" },
  95. { LDP_MSG_INIT, "Initialization" },
  96. { LDP_MSG_KEEPALIVE, "Keepalive" },
  97. { LDP_MSG_ADDRESS, "Address" },
  98. { LDP_MSG_ADDRESS_WITHDRAW, "Address Withdraw" },
  99. { LDP_MSG_LABEL_MAPPING, "Label Mapping" },
  100. { LDP_MSG_LABEL_REQUEST, "Label Request" },
  101. { LDP_MSG_LABEL_WITHDRAW, "Label Withdraw" },
  102. { LDP_MSG_LABEL_RELEASE, "Label Release" },
  103. { LDP_MSG_LABEL_ABORT_REQUEST, "Label Abort Request" },
  104. { 0, NULL}
  105. };
  106. #define LDP_MASK_TLV_TYPE(x) ((x)&0x3fff)
  107. #define LDP_MASK_F_BIT(x) ((x)&0x4000)
  108. #define LDP_TLV_FEC 0x0100
  109. #define LDP_TLV_ADDRESS_LIST 0x0101
  110. #define LDP_TLV_ADDRESS_LIST_AFNUM_LEN 2
  111. #define LDP_TLV_HOP_COUNT 0x0103
  112. #define LDP_TLV_PATH_VECTOR 0x0104
  113. #define LDP_TLV_GENERIC_LABEL 0x0200
  114. #define LDP_TLV_ATM_LABEL 0x0201
  115. #define LDP_TLV_FR_LABEL 0x0202
  116. #define LDP_TLV_STATUS 0x0300
  117. #define LDP_TLV_EXTD_STATUS 0x0301
  118. #define LDP_TLV_RETURNED_PDU 0x0302
  119. #define LDP_TLV_RETURNED_MSG 0x0303
  120. #define LDP_TLV_COMMON_HELLO 0x0400
  121. #define LDP_TLV_IPV4_TRANSPORT_ADDR 0x0401
  122. #define LDP_TLV_CONFIG_SEQ_NUMBER 0x0402
  123. #define LDP_TLV_IPV6_TRANSPORT_ADDR 0x0403
  124. #define LDP_TLV_COMMON_SESSION 0x0500
  125. #define LDP_TLV_ATM_SESSION_PARM 0x0501
  126. #define LDP_TLV_FR_SESSION_PARM 0x0502
  127. #define LDP_TLV_FT_SESSION 0x0503
  128. #define LDP_TLV_LABEL_REQUEST_MSG_ID 0x0600
  129. #define LDP_TLV_MTU 0x0601 /* rfc 3988 */
  130. static const struct tok ldp_tlv_values[] = {
  131. { LDP_TLV_FEC, "FEC" },
  132. { LDP_TLV_ADDRESS_LIST, "Address List" },
  133. { LDP_TLV_HOP_COUNT, "Hop Count" },
  134. { LDP_TLV_PATH_VECTOR, "Path Vector" },
  135. { LDP_TLV_GENERIC_LABEL, "Generic Label" },
  136. { LDP_TLV_ATM_LABEL, "ATM Label" },
  137. { LDP_TLV_FR_LABEL, "Frame-Relay Label" },
  138. { LDP_TLV_STATUS, "Status" },
  139. { LDP_TLV_EXTD_STATUS, "Extended Status" },
  140. { LDP_TLV_RETURNED_PDU, "Returned PDU" },
  141. { LDP_TLV_RETURNED_MSG, "Returned Message" },
  142. { LDP_TLV_COMMON_HELLO, "Common Hello Parameters" },
  143. { LDP_TLV_IPV4_TRANSPORT_ADDR, "IPv4 Transport Address" },
  144. { LDP_TLV_CONFIG_SEQ_NUMBER, "Configuration Sequence Number" },
  145. { LDP_TLV_IPV6_TRANSPORT_ADDR, "IPv6 Transport Address" },
  146. { LDP_TLV_COMMON_SESSION, "Common Session Parameters" },
  147. { LDP_TLV_ATM_SESSION_PARM, "ATM Session Parameters" },
  148. { LDP_TLV_FR_SESSION_PARM, "Frame-Relay Session Parameters" },
  149. { LDP_TLV_FT_SESSION, "Fault-Tolerant Session Parameters" },
  150. { LDP_TLV_LABEL_REQUEST_MSG_ID, "Label Request Message ID" },
  151. { LDP_TLV_MTU, "MTU" },
  152. { 0, NULL}
  153. };
  154. #define LDP_FEC_WILDCARD 0x01
  155. #define LDP_FEC_PREFIX 0x02
  156. #define LDP_FEC_HOSTADDRESS 0x03
  157. /* From RFC 4906; should probably be updated to RFC 4447 (e.g., VC -> PW) */
  158. #define LDP_FEC_MARTINI_VC 0x80
  159. static const struct tok ldp_fec_values[] = {
  160. { LDP_FEC_WILDCARD, "Wildcard" },
  161. { LDP_FEC_PREFIX, "Prefix" },
  162. { LDP_FEC_HOSTADDRESS, "Host address" },
  163. { LDP_FEC_MARTINI_VC, "Martini VC" },
  164. { 0, NULL}
  165. };
  166. #define LDP_FEC_MARTINI_IFPARM_MTU 0x01
  167. #define LDP_FEC_MARTINI_IFPARM_DESC 0x03
  168. #define LDP_FEC_MARTINI_IFPARM_VCCV 0x0c
  169. static const struct tok ldp_fec_martini_ifparm_values[] = {
  170. { LDP_FEC_MARTINI_IFPARM_MTU, "MTU" },
  171. { LDP_FEC_MARTINI_IFPARM_DESC, "Description" },
  172. { LDP_FEC_MARTINI_IFPARM_VCCV, "VCCV" },
  173. { 0, NULL}
  174. };
  175. /* draft-ietf-pwe3-vccv-04.txt */
  176. static const struct tok ldp_fec_martini_ifparm_vccv_cc_values[] = {
  177. { 0x01, "PWE3 control word" },
  178. { 0x02, "MPLS Router Alert Label" },
  179. { 0x04, "MPLS inner label TTL = 1" },
  180. { 0, NULL}
  181. };
  182. /* draft-ietf-pwe3-vccv-04.txt */
  183. static const struct tok ldp_fec_martini_ifparm_vccv_cv_values[] = {
  184. { 0x01, "ICMP Ping" },
  185. { 0x02, "LSP Ping" },
  186. { 0x04, "BFD" },
  187. { 0, NULL}
  188. };
  189. static int ldp_pdu_print(netdissect_options *, register const u_char *);
  190. /*
  191. * ldp tlv header
  192. *
  193. * 0 1 2 3
  194. * 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
  195. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  196. * |U|F| Type | Length |
  197. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  198. * | |
  199. * | Value |
  200. * ~ ~
  201. * | |
  202. * | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  203. * | |
  204. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  205. */
  206. #define TLV_TCHECK(minlen) \
  207. ND_TCHECK2(*tptr, minlen); if (tlv_tlen < minlen) goto badtlv;
  208. static int
  209. ldp_tlv_print(netdissect_options *ndo,
  210. register const u_char *tptr,
  211. u_short msg_tlen)
  212. {
  213. struct ldp_tlv_header {
  214. uint8_t type[2];
  215. uint8_t length[2];
  216. };
  217. const struct ldp_tlv_header *ldp_tlv_header;
  218. u_short tlv_type,tlv_len,tlv_tlen,af,ft_flags;
  219. u_char fec_type;
  220. u_int ui,vc_info_len, vc_info_tlv_type, vc_info_tlv_len,idx;
  221. char buf[100];
  222. int i;
  223. ldp_tlv_header = (const struct ldp_tlv_header *)tptr;
  224. ND_TCHECK(*ldp_tlv_header);
  225. tlv_len=EXTRACT_16BITS(ldp_tlv_header->length);
  226. if (tlv_len + 4 > msg_tlen) {
  227. ND_PRINT((ndo, "\n\t\t TLV contents go past end of message"));
  228. return 0;
  229. }
  230. tlv_tlen=tlv_len;
  231. tlv_type=LDP_MASK_TLV_TYPE(EXTRACT_16BITS(ldp_tlv_header->type));
  232. /* FIXME vendor private / experimental check */
  233. ND_PRINT((ndo, "\n\t %s TLV (0x%04x), length: %u, Flags: [%s and %s forward if unknown]",
  234. tok2str(ldp_tlv_values,
  235. "Unknown",
  236. tlv_type),
  237. tlv_type,
  238. tlv_len,
  239. LDP_MASK_U_BIT(EXTRACT_16BITS(&ldp_tlv_header->type)) ? "continue processing" : "ignore",
  240. LDP_MASK_F_BIT(EXTRACT_16BITS(&ldp_tlv_header->type)) ? "do" : "don't"));
  241. tptr+=sizeof(struct ldp_tlv_header);
  242. switch(tlv_type) {
  243. case LDP_TLV_COMMON_HELLO:
  244. TLV_TCHECK(4);
  245. ND_PRINT((ndo, "\n\t Hold Time: %us, Flags: [%s Hello%s]",
  246. EXTRACT_16BITS(tptr),
  247. (EXTRACT_16BITS(tptr+2)&0x8000) ? "Targeted" : "Link",
  248. (EXTRACT_16BITS(tptr+2)&0x4000) ? ", Request for targeted Hellos" : ""));
  249. break;
  250. case LDP_TLV_IPV4_TRANSPORT_ADDR:
  251. TLV_TCHECK(4);
  252. ND_PRINT((ndo, "\n\t IPv4 Transport Address: %s", ipaddr_string(ndo, tptr)));
  253. break;
  254. case LDP_TLV_IPV6_TRANSPORT_ADDR:
  255. TLV_TCHECK(16);
  256. ND_PRINT((ndo, "\n\t IPv6 Transport Address: %s", ip6addr_string(ndo, tptr)));
  257. break;
  258. case LDP_TLV_CONFIG_SEQ_NUMBER:
  259. TLV_TCHECK(4);
  260. ND_PRINT((ndo, "\n\t Sequence Number: %u", EXTRACT_32BITS(tptr)));
  261. break;
  262. case LDP_TLV_ADDRESS_LIST:
  263. TLV_TCHECK(LDP_TLV_ADDRESS_LIST_AFNUM_LEN);
  264. af = EXTRACT_16BITS(tptr);
  265. tptr+=LDP_TLV_ADDRESS_LIST_AFNUM_LEN;
  266. tlv_tlen -= LDP_TLV_ADDRESS_LIST_AFNUM_LEN;
  267. ND_PRINT((ndo, "\n\t Address Family: %s, addresses",
  268. tok2str(af_values, "Unknown (%u)", af)));
  269. switch (af) {
  270. case AFNUM_INET:
  271. while(tlv_tlen >= sizeof(struct in_addr)) {
  272. ND_TCHECK2(*tptr, sizeof(struct in_addr));
  273. ND_PRINT((ndo, " %s", ipaddr_string(ndo, tptr)));
  274. tlv_tlen-=sizeof(struct in_addr);
  275. tptr+=sizeof(struct in_addr);
  276. }
  277. break;
  278. case AFNUM_INET6:
  279. while(tlv_tlen >= sizeof(struct in6_addr)) {
  280. ND_TCHECK2(*tptr, sizeof(struct in6_addr));
  281. ND_PRINT((ndo, " %s", ip6addr_string(ndo, tptr)));
  282. tlv_tlen-=sizeof(struct in6_addr);
  283. tptr+=sizeof(struct in6_addr);
  284. }
  285. break;
  286. default:
  287. /* unknown AF */
  288. break;
  289. }
  290. break;
  291. case LDP_TLV_COMMON_SESSION:
  292. TLV_TCHECK(8);
  293. ND_PRINT((ndo, "\n\t Version: %u, Keepalive: %us, Flags: [Downstream %s, Loop Detection %s]",
  294. EXTRACT_16BITS(tptr), EXTRACT_16BITS(tptr+2),
  295. (EXTRACT_16BITS(tptr+6)&0x8000) ? "On Demand" : "Unsolicited",
  296. (EXTRACT_16BITS(tptr+6)&0x4000) ? "Enabled" : "Disabled"
  297. ));
  298. break;
  299. case LDP_TLV_FEC:
  300. TLV_TCHECK(1);
  301. fec_type = *tptr;
  302. ND_PRINT((ndo, "\n\t %s FEC (0x%02x)",
  303. tok2str(ldp_fec_values, "Unknown", fec_type),
  304. fec_type));
  305. tptr+=1;
  306. tlv_tlen-=1;
  307. switch(fec_type) {
  308. case LDP_FEC_WILDCARD:
  309. break;
  310. case LDP_FEC_PREFIX:
  311. TLV_TCHECK(2);
  312. af = EXTRACT_16BITS(tptr);
  313. tptr+=LDP_TLV_ADDRESS_LIST_AFNUM_LEN;
  314. tlv_tlen-=LDP_TLV_ADDRESS_LIST_AFNUM_LEN;
  315. if (af == AFNUM_INET) {
  316. i=decode_prefix4(ndo, tptr, tlv_tlen, buf, sizeof(buf));
  317. if (i == -2)
  318. goto trunc;
  319. if (i == -3)
  320. ND_PRINT((ndo, ": IPv4 prefix (goes past end of TLV)"));
  321. else if (i == -1)
  322. ND_PRINT((ndo, ": IPv4 prefix (invalid length)"));
  323. else
  324. ND_PRINT((ndo, ": IPv4 prefix %s", buf));
  325. }
  326. else if (af == AFNUM_INET6) {
  327. i=decode_prefix6(ndo, tptr, tlv_tlen, buf, sizeof(buf));
  328. if (i == -2)
  329. goto trunc;
  330. if (i == -3)
  331. ND_PRINT((ndo, ": IPv4 prefix (goes past end of TLV)"));
  332. else if (i == -1)
  333. ND_PRINT((ndo, ": IPv6 prefix (invalid length)"));
  334. else
  335. ND_PRINT((ndo, ": IPv6 prefix %s", buf));
  336. }
  337. else
  338. ND_PRINT((ndo, ": Address family %u prefix", af));
  339. break;
  340. case LDP_FEC_HOSTADDRESS:
  341. break;
  342. case LDP_FEC_MARTINI_VC:
  343. /*
  344. * We assume the type was supposed to be one of the MPLS
  345. * Pseudowire Types.
  346. */
  347. TLV_TCHECK(7);
  348. vc_info_len = *(tptr+2);
  349. /*
  350. * According to RFC 4908, the VC info Length field can be zero,
  351. * in which case not only are there no interface parameters,
  352. * there's no VC ID.
  353. */
  354. if (vc_info_len == 0) {
  355. ND_PRINT((ndo, ": %s, %scontrol word, group-ID %u, VC-info-length: %u",
  356. tok2str(mpls_pw_types_values, "Unknown", EXTRACT_16BITS(tptr)&0x7fff),
  357. EXTRACT_16BITS(tptr)&0x8000 ? "" : "no ",
  358. EXTRACT_32BITS(tptr+3),
  359. vc_info_len));
  360. break;
  361. }
  362. /* Make sure we have the VC ID as well */
  363. TLV_TCHECK(11);
  364. ND_PRINT((ndo, ": %s, %scontrol word, group-ID %u, VC-ID %u, VC-info-length: %u",
  365. tok2str(mpls_pw_types_values, "Unknown", EXTRACT_16BITS(tptr)&0x7fff),
  366. EXTRACT_16BITS(tptr)&0x8000 ? "" : "no ",
  367. EXTRACT_32BITS(tptr+3),
  368. EXTRACT_32BITS(tptr+7),
  369. vc_info_len));
  370. if (vc_info_len < 4) {
  371. /* minimum 4, for the VC ID */
  372. ND_PRINT((ndo, " (invalid, < 4"));
  373. return(tlv_len+4); /* Type & Length fields not included */
  374. }
  375. vc_info_len -= 4; /* subtract out the VC ID, giving the length of the interface parameters */
  376. /* Skip past the fixed information and the VC ID */
  377. tptr+=11;
  378. tlv_tlen-=11;
  379. TLV_TCHECK(vc_info_len);
  380. while (vc_info_len > 2) {
  381. vc_info_tlv_type = *tptr;
  382. vc_info_tlv_len = *(tptr+1);
  383. if (vc_info_tlv_len < 2)
  384. break;
  385. if (vc_info_len < vc_info_tlv_len)
  386. break;
  387. ND_PRINT((ndo, "\n\t\tInterface Parameter: %s (0x%02x), len %u",
  388. tok2str(ldp_fec_martini_ifparm_values,"Unknown",vc_info_tlv_type),
  389. vc_info_tlv_type,
  390. vc_info_tlv_len));
  391. switch(vc_info_tlv_type) {
  392. case LDP_FEC_MARTINI_IFPARM_MTU:
  393. ND_PRINT((ndo, ": %u", EXTRACT_16BITS(tptr+2)));
  394. break;
  395. case LDP_FEC_MARTINI_IFPARM_DESC:
  396. ND_PRINT((ndo, ": "));
  397. for (idx = 2; idx < vc_info_tlv_len; idx++)
  398. safeputchar(ndo, *(tptr + idx));
  399. break;
  400. case LDP_FEC_MARTINI_IFPARM_VCCV:
  401. ND_PRINT((ndo, "\n\t\t Control Channels (0x%02x) = [%s]",
  402. *(tptr+2),
  403. bittok2str(ldp_fec_martini_ifparm_vccv_cc_values, "none", *(tptr+2))));
  404. ND_PRINT((ndo, "\n\t\t CV Types (0x%02x) = [%s]",
  405. *(tptr+3),
  406. bittok2str(ldp_fec_martini_ifparm_vccv_cv_values, "none", *(tptr+3))));
  407. break;
  408. default:
  409. print_unknown_data(ndo, tptr+2, "\n\t\t ", vc_info_tlv_len-2);
  410. break;
  411. }
  412. vc_info_len -= vc_info_tlv_len;
  413. tptr += vc_info_tlv_len;
  414. }
  415. break;
  416. }
  417. break;
  418. case LDP_TLV_GENERIC_LABEL:
  419. TLV_TCHECK(4);
  420. ND_PRINT((ndo, "\n\t Label: %u", EXTRACT_32BITS(tptr) & 0xfffff));
  421. break;
  422. case LDP_TLV_STATUS:
  423. TLV_TCHECK(8);
  424. ui = EXTRACT_32BITS(tptr);
  425. tptr+=4;
  426. ND_PRINT((ndo, "\n\t Status: 0x%02x, Flags: [%s and %s forward]",
  427. ui&0x3fffffff,
  428. ui&0x80000000 ? "Fatal error" : "Advisory Notification",
  429. ui&0x40000000 ? "do" : "don't"));
  430. ui = EXTRACT_32BITS(tptr);
  431. tptr+=4;
  432. if (ui)
  433. ND_PRINT((ndo, ", causing Message ID: 0x%08x", ui));
  434. break;
  435. case LDP_TLV_FT_SESSION:
  436. TLV_TCHECK(8);
  437. ft_flags = EXTRACT_16BITS(tptr);
  438. ND_PRINT((ndo, "\n\t Flags: [%sReconnect, %sSave State, %sAll-Label Protection, %s Checkpoint, %sRe-Learn State]",
  439. ft_flags&0x8000 ? "" : "No ",
  440. ft_flags&0x8 ? "" : "Don't ",
  441. ft_flags&0x4 ? "" : "No ",
  442. ft_flags&0x2 ? "Sequence Numbered Label" : "All Labels",
  443. ft_flags&0x1 ? "" : "Don't "));
  444. tptr+=4;
  445. ui = EXTRACT_32BITS(tptr);
  446. if (ui)
  447. ND_PRINT((ndo, ", Reconnect Timeout: %ums", ui));
  448. tptr+=4;
  449. ui = EXTRACT_32BITS(tptr);
  450. if (ui)
  451. ND_PRINT((ndo, ", Recovery Time: %ums", ui));
  452. break;
  453. case LDP_TLV_MTU:
  454. TLV_TCHECK(2);
  455. ND_PRINT((ndo, "\n\t MTU: %u", EXTRACT_16BITS(tptr)));
  456. break;
  457. /*
  458. * FIXME those are the defined TLVs that lack a decoder
  459. * you are welcome to contribute code ;-)
  460. */
  461. case LDP_TLV_HOP_COUNT:
  462. case LDP_TLV_PATH_VECTOR:
  463. case LDP_TLV_ATM_LABEL:
  464. case LDP_TLV_FR_LABEL:
  465. case LDP_TLV_EXTD_STATUS:
  466. case LDP_TLV_RETURNED_PDU:
  467. case LDP_TLV_RETURNED_MSG:
  468. case LDP_TLV_ATM_SESSION_PARM:
  469. case LDP_TLV_FR_SESSION_PARM:
  470. case LDP_TLV_LABEL_REQUEST_MSG_ID:
  471. default:
  472. if (ndo->ndo_vflag <= 1)
  473. print_unknown_data(ndo, tptr, "\n\t ", tlv_tlen);
  474. break;
  475. }
  476. return(tlv_len+4); /* Type & Length fields not included */
  477. trunc:
  478. ND_PRINT((ndo, "\n\t\t packet exceeded snapshot"));
  479. return 0;
  480. badtlv:
  481. ND_PRINT((ndo, "\n\t\t TLV contents go past end of TLV"));
  482. return(tlv_len+4); /* Type & Length fields not included */
  483. }
  484. void
  485. ldp_print(netdissect_options *ndo,
  486. register const u_char *pptr, register u_int len)
  487. {
  488. int processed;
  489. while (len > (sizeof(struct ldp_common_header) + sizeof(struct ldp_msg_header))) {
  490. processed = ldp_pdu_print(ndo, pptr);
  491. if (processed == 0)
  492. return;
  493. len -= processed;
  494. pptr += processed;
  495. }
  496. }
  497. static int
  498. ldp_pdu_print(netdissect_options *ndo,
  499. register const u_char *pptr)
  500. {
  501. const struct ldp_common_header *ldp_com_header;
  502. const struct ldp_msg_header *ldp_msg_header;
  503. const u_char *tptr,*msg_tptr;
  504. u_short tlen;
  505. u_short pdu_len,msg_len,msg_type,msg_tlen;
  506. int hexdump,processed;
  507. ldp_com_header = (const struct ldp_common_header *)pptr;
  508. ND_TCHECK(*ldp_com_header);
  509. /*
  510. * Sanity checking of the header.
  511. */
  512. if (EXTRACT_16BITS(&ldp_com_header->version) != LDP_VERSION) {
  513. ND_PRINT((ndo, "%sLDP version %u packet not supported",
  514. (ndo->ndo_vflag < 1) ? "" : "\n\t",
  515. EXTRACT_16BITS(&ldp_com_header->version)));
  516. return 0;
  517. }
  518. pdu_len = EXTRACT_16BITS(&ldp_com_header->pdu_length);
  519. if (pdu_len < sizeof(const struct ldp_common_header)-4) {
  520. /* length too short */
  521. ND_PRINT((ndo, "%sLDP, pdu-length: %u (too short, < %u)",
  522. (ndo->ndo_vflag < 1) ? "" : "\n\t",
  523. pdu_len,
  524. (u_int)(sizeof(const struct ldp_common_header)-4)));
  525. return 0;
  526. }
  527. /* print the LSR-ID, label-space & length */
  528. ND_PRINT((ndo, "%sLDP, Label-Space-ID: %s:%u, pdu-length: %u",
  529. (ndo->ndo_vflag < 1) ? "" : "\n\t",
  530. ipaddr_string(ndo, &ldp_com_header->lsr_id),
  531. EXTRACT_16BITS(&ldp_com_header->label_space),
  532. pdu_len));
  533. /* bail out if non-verbose */
  534. if (ndo->ndo_vflag < 1)
  535. return 0;
  536. /* ok they seem to want to know everything - lets fully decode it */
  537. tptr = pptr + sizeof(const struct ldp_common_header);
  538. tlen = pdu_len - (sizeof(const struct ldp_common_header)-4); /* Type & Length fields not included */
  539. while(tlen>0) {
  540. /* did we capture enough for fully decoding the msg header ? */
  541. ND_TCHECK2(*tptr, sizeof(struct ldp_msg_header));
  542. ldp_msg_header = (const struct ldp_msg_header *)tptr;
  543. msg_len=EXTRACT_16BITS(ldp_msg_header->length);
  544. msg_type=LDP_MASK_MSG_TYPE(EXTRACT_16BITS(ldp_msg_header->type));
  545. if (msg_len < sizeof(struct ldp_msg_header)-4) {
  546. /* length too short */
  547. /* FIXME vendor private / experimental check */
  548. ND_PRINT((ndo, "\n\t %s Message (0x%04x), length: %u (too short, < %u)",
  549. tok2str(ldp_msg_values,
  550. "Unknown",
  551. msg_type),
  552. msg_type,
  553. msg_len,
  554. (u_int)(sizeof(struct ldp_msg_header)-4)));
  555. return 0;
  556. }
  557. /* FIXME vendor private / experimental check */
  558. ND_PRINT((ndo, "\n\t %s Message (0x%04x), length: %u, Message ID: 0x%08x, Flags: [%s if unknown]",
  559. tok2str(ldp_msg_values,
  560. "Unknown",
  561. msg_type),
  562. msg_type,
  563. msg_len,
  564. EXTRACT_32BITS(&ldp_msg_header->id),
  565. LDP_MASK_U_BIT(EXTRACT_16BITS(&ldp_msg_header->type)) ? "continue processing" : "ignore"));
  566. msg_tptr=tptr+sizeof(struct ldp_msg_header);
  567. msg_tlen=msg_len-(sizeof(struct ldp_msg_header)-4); /* Type & Length fields not included */
  568. /* did we capture enough for fully decoding the message ? */
  569. ND_TCHECK2(*tptr, msg_len);
  570. hexdump=FALSE;
  571. switch(msg_type) {
  572. case LDP_MSG_NOTIF:
  573. case LDP_MSG_HELLO:
  574. case LDP_MSG_INIT:
  575. case LDP_MSG_KEEPALIVE:
  576. case LDP_MSG_ADDRESS:
  577. case LDP_MSG_LABEL_MAPPING:
  578. case LDP_MSG_ADDRESS_WITHDRAW:
  579. case LDP_MSG_LABEL_WITHDRAW:
  580. while(msg_tlen >= 4) {
  581. processed = ldp_tlv_print(ndo, msg_tptr, msg_tlen);
  582. if (processed == 0)
  583. break;
  584. msg_tlen-=processed;
  585. msg_tptr+=processed;
  586. }
  587. break;
  588. /*
  589. * FIXME those are the defined messages that lack a decoder
  590. * you are welcome to contribute code ;-)
  591. */
  592. case LDP_MSG_LABEL_REQUEST:
  593. case LDP_MSG_LABEL_RELEASE:
  594. case LDP_MSG_LABEL_ABORT_REQUEST:
  595. default:
  596. if (ndo->ndo_vflag <= 1)
  597. print_unknown_data(ndo, msg_tptr, "\n\t ", msg_tlen);
  598. break;
  599. }
  600. /* do we want to see an additionally hexdump ? */
  601. if (ndo->ndo_vflag > 1 || hexdump==TRUE)
  602. print_unknown_data(ndo, tptr+sizeof(struct ldp_msg_header), "\n\t ",
  603. msg_len);
  604. tptr += msg_len+4;
  605. tlen -= msg_len+4;
  606. }
  607. return pdu_len+4;
  608. trunc:
  609. ND_PRINT((ndo, "\n\t\t packet exceeded snapshot"));
  610. return 0;
  611. }
  612. /*
  613. * Local Variables:
  614. * c-style: whitesmith
  615. * c-basic-offset: 8
  616. * End:
  617. */