print-eigrp.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522
  1. /*
  2. * Copyright (c) 1998-2004 Hannes Gredler <hannes@gredler.at>
  3. * The TCPDUMP project
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that: (1) source code
  7. * distributions retain the above copyright notice and this paragraph
  8. * in its entirety, and (2) distributions including binary code include
  9. * the above copyright notice and this paragraph in its entirety in
  10. * the documentation or other materials provided with the distribution.
  11. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
  12. * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
  13. * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  14. * FOR A PARTICULAR PURPOSE.
  15. */
  16. /* \summary: Enhanced Interior Gateway Routing Protocol (EIGRP) printer */
  17. #ifdef HAVE_CONFIG_H
  18. #include "config.h"
  19. #endif
  20. #include <netdissect-stdinc.h>
  21. #include <string.h>
  22. #include "netdissect.h"
  23. #include "extract.h"
  24. #include "addrtoname.h"
  25. /*
  26. * packet format documented at
  27. * http://www.rhyshaden.com/eigrp.htm
  28. * RFC 7868
  29. */
  30. struct eigrp_common_header {
  31. uint8_t version;
  32. uint8_t opcode;
  33. uint8_t checksum[2];
  34. uint8_t flags[4];
  35. uint8_t seq[4];
  36. uint8_t ack[4];
  37. uint8_t asn[4];
  38. };
  39. #define EIGRP_VERSION 2
  40. #define EIGRP_OPCODE_UPDATE 1
  41. #define EIGRP_OPCODE_QUERY 3
  42. #define EIGRP_OPCODE_REPLY 4
  43. #define EIGRP_OPCODE_HELLO 5
  44. #define EIGRP_OPCODE_IPXSAP 6
  45. #define EIGRP_OPCODE_PROBE 7
  46. static const struct tok eigrp_opcode_values[] = {
  47. { EIGRP_OPCODE_UPDATE, "Update" },
  48. { EIGRP_OPCODE_QUERY, "Query" },
  49. { EIGRP_OPCODE_REPLY, "Reply" },
  50. { EIGRP_OPCODE_HELLO, "Hello" },
  51. { EIGRP_OPCODE_IPXSAP, "IPX SAP" },
  52. { EIGRP_OPCODE_PROBE, "Probe" },
  53. { 0, NULL}
  54. };
  55. static const struct tok eigrp_common_header_flag_values[] = {
  56. { 0x01, "Init" },
  57. { 0x02, "Conditionally Received" },
  58. { 0, NULL}
  59. };
  60. struct eigrp_tlv_header {
  61. uint8_t type[2];
  62. uint8_t length[2];
  63. };
  64. #define EIGRP_TLV_GENERAL_PARM 0x0001
  65. #define EIGRP_TLV_AUTH 0x0002
  66. #define EIGRP_TLV_SEQ 0x0003
  67. #define EIGRP_TLV_SW_VERSION 0x0004
  68. #define EIGRP_TLV_MCAST_SEQ 0x0005
  69. #define EIGRP_TLV_IP_INT 0x0102
  70. #define EIGRP_TLV_IP_EXT 0x0103
  71. #define EIGRP_TLV_AT_INT 0x0202
  72. #define EIGRP_TLV_AT_EXT 0x0203
  73. #define EIGRP_TLV_AT_CABLE_SETUP 0x0204
  74. #define EIGRP_TLV_IPX_INT 0x0302
  75. #define EIGRP_TLV_IPX_EXT 0x0303
  76. static const struct tok eigrp_tlv_values[] = {
  77. { EIGRP_TLV_GENERAL_PARM, "General Parameters"},
  78. { EIGRP_TLV_AUTH, "Authentication"},
  79. { EIGRP_TLV_SEQ, "Sequence"},
  80. { EIGRP_TLV_SW_VERSION, "Software Version"},
  81. { EIGRP_TLV_MCAST_SEQ, "Next Multicast Sequence"},
  82. { EIGRP_TLV_IP_INT, "IP Internal routes"},
  83. { EIGRP_TLV_IP_EXT, "IP External routes"},
  84. { EIGRP_TLV_AT_INT, "AppleTalk Internal routes"},
  85. { EIGRP_TLV_AT_EXT, "AppleTalk External routes"},
  86. { EIGRP_TLV_AT_CABLE_SETUP, "AppleTalk Cable setup"},
  87. { EIGRP_TLV_IPX_INT, "IPX Internal routes"},
  88. { EIGRP_TLV_IPX_EXT, "IPX External routes"},
  89. { 0, NULL}
  90. };
  91. struct eigrp_tlv_general_parm_t {
  92. uint8_t k1;
  93. uint8_t k2;
  94. uint8_t k3;
  95. uint8_t k4;
  96. uint8_t k5;
  97. uint8_t res;
  98. uint8_t holdtime[2];
  99. };
  100. struct eigrp_tlv_sw_version_t {
  101. uint8_t ios_major;
  102. uint8_t ios_minor;
  103. uint8_t eigrp_major;
  104. uint8_t eigrp_minor;
  105. };
  106. struct eigrp_tlv_ip_int_t {
  107. uint8_t nexthop[4];
  108. uint8_t delay[4];
  109. uint8_t bandwidth[4];
  110. uint8_t mtu[3];
  111. uint8_t hopcount;
  112. uint8_t reliability;
  113. uint8_t load;
  114. uint8_t reserved[2];
  115. uint8_t plen;
  116. uint8_t destination; /* variable length [1-4] bytes encoding */
  117. };
  118. struct eigrp_tlv_ip_ext_t {
  119. uint8_t nexthop[4];
  120. uint8_t origin_router[4];
  121. uint8_t origin_as[4];
  122. uint8_t tag[4];
  123. uint8_t metric[4];
  124. uint8_t reserved[2];
  125. uint8_t proto_id;
  126. uint8_t flags;
  127. uint8_t delay[4];
  128. uint8_t bandwidth[4];
  129. uint8_t mtu[3];
  130. uint8_t hopcount;
  131. uint8_t reliability;
  132. uint8_t load;
  133. uint8_t reserved2[2];
  134. uint8_t plen;
  135. uint8_t destination; /* variable length [1-4] bytes encoding */
  136. };
  137. struct eigrp_tlv_at_cable_setup_t {
  138. uint8_t cable_start[2];
  139. uint8_t cable_end[2];
  140. uint8_t router_id[4];
  141. };
  142. struct eigrp_tlv_at_int_t {
  143. uint8_t nexthop[4];
  144. uint8_t delay[4];
  145. uint8_t bandwidth[4];
  146. uint8_t mtu[3];
  147. uint8_t hopcount;
  148. uint8_t reliability;
  149. uint8_t load;
  150. uint8_t reserved[2];
  151. uint8_t cable_start[2];
  152. uint8_t cable_end[2];
  153. };
  154. struct eigrp_tlv_at_ext_t {
  155. uint8_t nexthop[4];
  156. uint8_t origin_router[4];
  157. uint8_t origin_as[4];
  158. uint8_t tag[4];
  159. uint8_t proto_id;
  160. uint8_t flags;
  161. uint8_t metric[2];
  162. uint8_t delay[4];
  163. uint8_t bandwidth[4];
  164. uint8_t mtu[3];
  165. uint8_t hopcount;
  166. uint8_t reliability;
  167. uint8_t load;
  168. uint8_t reserved2[2];
  169. uint8_t cable_start[2];
  170. uint8_t cable_end[2];
  171. };
  172. static const struct tok eigrp_ext_proto_id_values[] = {
  173. { 0x01, "IGRP" },
  174. { 0x02, "EIGRP" },
  175. { 0x03, "Static" },
  176. { 0x04, "RIP" },
  177. { 0x05, "Hello" },
  178. { 0x06, "OSPF" },
  179. { 0x07, "IS-IS" },
  180. { 0x08, "EGP" },
  181. { 0x09, "BGP" },
  182. { 0x0a, "IDRP" },
  183. { 0x0b, "Connected" },
  184. { 0, NULL}
  185. };
  186. void
  187. eigrp_print(netdissect_options *ndo, register const u_char *pptr, register u_int len)
  188. {
  189. const struct eigrp_common_header *eigrp_com_header;
  190. const struct eigrp_tlv_header *eigrp_tlv_header;
  191. const u_char *tptr,*tlv_tptr;
  192. u_int tlen,eigrp_tlv_len,eigrp_tlv_type,tlv_tlen, byte_length, bit_length;
  193. uint8_t prefix[4];
  194. union {
  195. const struct eigrp_tlv_general_parm_t *eigrp_tlv_general_parm;
  196. const struct eigrp_tlv_sw_version_t *eigrp_tlv_sw_version;
  197. const struct eigrp_tlv_ip_int_t *eigrp_tlv_ip_int;
  198. const struct eigrp_tlv_ip_ext_t *eigrp_tlv_ip_ext;
  199. const struct eigrp_tlv_at_cable_setup_t *eigrp_tlv_at_cable_setup;
  200. const struct eigrp_tlv_at_int_t *eigrp_tlv_at_int;
  201. const struct eigrp_tlv_at_ext_t *eigrp_tlv_at_ext;
  202. } tlv_ptr;
  203. tptr=pptr;
  204. eigrp_com_header = (const struct eigrp_common_header *)pptr;
  205. ND_TCHECK(*eigrp_com_header);
  206. /*
  207. * Sanity checking of the header.
  208. */
  209. if (eigrp_com_header->version != EIGRP_VERSION) {
  210. ND_PRINT((ndo, "EIGRP version %u packet not supported",eigrp_com_header->version));
  211. return;
  212. }
  213. /* in non-verbose mode just lets print the basic Message Type*/
  214. if (ndo->ndo_vflag < 1) {
  215. ND_PRINT((ndo, "EIGRP %s, length: %u",
  216. tok2str(eigrp_opcode_values, "unknown (%u)",eigrp_com_header->opcode),
  217. len));
  218. return;
  219. }
  220. /* ok they seem to want to know everything - lets fully decode it */
  221. if (len < sizeof(struct eigrp_common_header)) {
  222. ND_PRINT((ndo, "EIGRP %s, length: %u (too short, < %u)",
  223. tok2str(eigrp_opcode_values, "unknown (%u)",eigrp_com_header->opcode),
  224. len, (u_int) sizeof(struct eigrp_common_header)));
  225. return;
  226. }
  227. tlen=len-sizeof(struct eigrp_common_header);
  228. /* FIXME print other header info */
  229. ND_PRINT((ndo, "\n\tEIGRP v%u, opcode: %s (%u), chksum: 0x%04x, Flags: [%s]\n\tseq: 0x%08x, ack: 0x%08x, AS: %u, length: %u",
  230. eigrp_com_header->version,
  231. tok2str(eigrp_opcode_values, "unknown, type: %u",eigrp_com_header->opcode),
  232. eigrp_com_header->opcode,
  233. EXTRACT_16BITS(&eigrp_com_header->checksum),
  234. tok2str(eigrp_common_header_flag_values,
  235. "none",
  236. EXTRACT_32BITS(&eigrp_com_header->flags)),
  237. EXTRACT_32BITS(&eigrp_com_header->seq),
  238. EXTRACT_32BITS(&eigrp_com_header->ack),
  239. EXTRACT_32BITS(&eigrp_com_header->asn),
  240. tlen));
  241. tptr+=sizeof(const struct eigrp_common_header);
  242. while(tlen>0) {
  243. /* did we capture enough for fully decoding the object header ? */
  244. ND_TCHECK2(*tptr, sizeof(struct eigrp_tlv_header));
  245. eigrp_tlv_header = (const struct eigrp_tlv_header *)tptr;
  246. eigrp_tlv_len=EXTRACT_16BITS(&eigrp_tlv_header->length);
  247. eigrp_tlv_type=EXTRACT_16BITS(&eigrp_tlv_header->type);
  248. if (eigrp_tlv_len < sizeof(struct eigrp_tlv_header) ||
  249. eigrp_tlv_len > tlen) {
  250. print_unknown_data(ndo,tptr+sizeof(struct eigrp_tlv_header),"\n\t ",tlen);
  251. return;
  252. }
  253. ND_PRINT((ndo, "\n\t %s TLV (0x%04x), length: %u",
  254. tok2str(eigrp_tlv_values,
  255. "Unknown",
  256. eigrp_tlv_type),
  257. eigrp_tlv_type,
  258. eigrp_tlv_len));
  259. if (eigrp_tlv_len < sizeof(struct eigrp_tlv_header)) {
  260. ND_PRINT((ndo, " (too short, < %u)",
  261. (u_int) sizeof(struct eigrp_tlv_header)));
  262. break;
  263. }
  264. tlv_tptr=tptr+sizeof(struct eigrp_tlv_header);
  265. tlv_tlen=eigrp_tlv_len-sizeof(struct eigrp_tlv_header);
  266. /* did we capture enough for fully decoding the object ? */
  267. ND_TCHECK2(*tptr, eigrp_tlv_len);
  268. switch(eigrp_tlv_type) {
  269. case EIGRP_TLV_GENERAL_PARM:
  270. tlv_ptr.eigrp_tlv_general_parm = (const struct eigrp_tlv_general_parm_t *)tlv_tptr;
  271. if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_general_parm)) {
  272. ND_PRINT((ndo, " (too short, < %u)",
  273. (u_int) (sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_general_parm))));
  274. break;
  275. }
  276. ND_PRINT((ndo, "\n\t holdtime: %us, k1 %u, k2 %u, k3 %u, k4 %u, k5 %u",
  277. EXTRACT_16BITS(tlv_ptr.eigrp_tlv_general_parm->holdtime),
  278. tlv_ptr.eigrp_tlv_general_parm->k1,
  279. tlv_ptr.eigrp_tlv_general_parm->k2,
  280. tlv_ptr.eigrp_tlv_general_parm->k3,
  281. tlv_ptr.eigrp_tlv_general_parm->k4,
  282. tlv_ptr.eigrp_tlv_general_parm->k5));
  283. break;
  284. case EIGRP_TLV_SW_VERSION:
  285. tlv_ptr.eigrp_tlv_sw_version = (const struct eigrp_tlv_sw_version_t *)tlv_tptr;
  286. if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_sw_version)) {
  287. ND_PRINT((ndo, " (too short, < %u)",
  288. (u_int) (sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_sw_version))));
  289. break;
  290. }
  291. ND_PRINT((ndo, "\n\t IOS version: %u.%u, EIGRP version %u.%u",
  292. tlv_ptr.eigrp_tlv_sw_version->ios_major,
  293. tlv_ptr.eigrp_tlv_sw_version->ios_minor,
  294. tlv_ptr.eigrp_tlv_sw_version->eigrp_major,
  295. tlv_ptr.eigrp_tlv_sw_version->eigrp_minor));
  296. break;
  297. case EIGRP_TLV_IP_INT:
  298. tlv_ptr.eigrp_tlv_ip_int = (const struct eigrp_tlv_ip_int_t *)tlv_tptr;
  299. if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_ip_int)) {
  300. ND_PRINT((ndo, " (too short, < %u)",
  301. (u_int) (sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_ip_int))));
  302. break;
  303. }
  304. bit_length = tlv_ptr.eigrp_tlv_ip_int->plen;
  305. if (bit_length > 32) {
  306. ND_PRINT((ndo, "\n\t illegal prefix length %u",bit_length));
  307. break;
  308. }
  309. byte_length = (bit_length + 7) / 8; /* variable length encoding */
  310. memset(prefix, 0, 4);
  311. memcpy(prefix,&tlv_ptr.eigrp_tlv_ip_int->destination,byte_length);
  312. ND_PRINT((ndo, "\n\t IPv4 prefix: %15s/%u, nexthop: ",
  313. ipaddr_string(ndo, prefix),
  314. bit_length));
  315. if (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_int->nexthop) == 0)
  316. ND_PRINT((ndo, "self"));
  317. else
  318. ND_PRINT((ndo, "%s",ipaddr_string(ndo, &tlv_ptr.eigrp_tlv_ip_int->nexthop)));
  319. ND_PRINT((ndo, "\n\t delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u",
  320. (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_int->delay)/100),
  321. EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_int->bandwidth),
  322. EXTRACT_24BITS(&tlv_ptr.eigrp_tlv_ip_int->mtu),
  323. tlv_ptr.eigrp_tlv_ip_int->hopcount,
  324. tlv_ptr.eigrp_tlv_ip_int->reliability,
  325. tlv_ptr.eigrp_tlv_ip_int->load));
  326. break;
  327. case EIGRP_TLV_IP_EXT:
  328. tlv_ptr.eigrp_tlv_ip_ext = (const struct eigrp_tlv_ip_ext_t *)tlv_tptr;
  329. if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_ip_ext)) {
  330. ND_PRINT((ndo, " (too short, < %u)",
  331. (u_int) (sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_ip_ext))));
  332. break;
  333. }
  334. bit_length = tlv_ptr.eigrp_tlv_ip_ext->plen;
  335. if (bit_length > 32) {
  336. ND_PRINT((ndo, "\n\t illegal prefix length %u",bit_length));
  337. break;
  338. }
  339. byte_length = (bit_length + 7) / 8; /* variable length encoding */
  340. memset(prefix, 0, 4);
  341. memcpy(prefix,&tlv_ptr.eigrp_tlv_ip_ext->destination,byte_length);
  342. ND_PRINT((ndo, "\n\t IPv4 prefix: %15s/%u, nexthop: ",
  343. ipaddr_string(ndo, prefix),
  344. bit_length));
  345. if (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_ext->nexthop) == 0)
  346. ND_PRINT((ndo, "self"));
  347. else
  348. ND_PRINT((ndo, "%s",ipaddr_string(ndo, &tlv_ptr.eigrp_tlv_ip_ext->nexthop)));
  349. ND_PRINT((ndo, "\n\t origin-router %s, origin-as %u, origin-proto %s, flags [0x%02x], tag 0x%08x, metric %u",
  350. ipaddr_string(ndo, tlv_ptr.eigrp_tlv_ip_ext->origin_router),
  351. EXTRACT_32BITS(tlv_ptr.eigrp_tlv_ip_ext->origin_as),
  352. tok2str(eigrp_ext_proto_id_values,"unknown",tlv_ptr.eigrp_tlv_ip_ext->proto_id),
  353. tlv_ptr.eigrp_tlv_ip_ext->flags,
  354. EXTRACT_32BITS(tlv_ptr.eigrp_tlv_ip_ext->tag),
  355. EXTRACT_32BITS(tlv_ptr.eigrp_tlv_ip_ext->metric)));
  356. ND_PRINT((ndo, "\n\t delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u",
  357. (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_ext->delay)/100),
  358. EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_ext->bandwidth),
  359. EXTRACT_24BITS(&tlv_ptr.eigrp_tlv_ip_ext->mtu),
  360. tlv_ptr.eigrp_tlv_ip_ext->hopcount,
  361. tlv_ptr.eigrp_tlv_ip_ext->reliability,
  362. tlv_ptr.eigrp_tlv_ip_ext->load));
  363. break;
  364. case EIGRP_TLV_AT_CABLE_SETUP:
  365. tlv_ptr.eigrp_tlv_at_cable_setup = (const struct eigrp_tlv_at_cable_setup_t *)tlv_tptr;
  366. if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_at_cable_setup)) {
  367. ND_PRINT((ndo, " (too short, < %u)",
  368. (u_int) (sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_at_cable_setup))));
  369. break;
  370. }
  371. ND_PRINT((ndo, "\n\t Cable-range: %u-%u, Router-ID %u",
  372. EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_cable_setup->cable_start),
  373. EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_cable_setup->cable_end),
  374. EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_cable_setup->router_id)));
  375. break;
  376. case EIGRP_TLV_AT_INT:
  377. tlv_ptr.eigrp_tlv_at_int = (const struct eigrp_tlv_at_int_t *)tlv_tptr;
  378. if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_at_int)) {
  379. ND_PRINT((ndo, " (too short, < %u)",
  380. (u_int) (sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_at_int))));
  381. break;
  382. }
  383. ND_PRINT((ndo, "\n\t Cable-Range: %u-%u, nexthop: ",
  384. EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_int->cable_start),
  385. EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_int->cable_end)));
  386. if (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_int->nexthop) == 0)
  387. ND_PRINT((ndo, "self"));
  388. else
  389. ND_PRINT((ndo, "%u.%u",
  390. EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_int->nexthop),
  391. EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_int->nexthop[2])));
  392. ND_PRINT((ndo, "\n\t delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u",
  393. (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_int->delay)/100),
  394. EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_int->bandwidth),
  395. EXTRACT_24BITS(&tlv_ptr.eigrp_tlv_at_int->mtu),
  396. tlv_ptr.eigrp_tlv_at_int->hopcount,
  397. tlv_ptr.eigrp_tlv_at_int->reliability,
  398. tlv_ptr.eigrp_tlv_at_int->load));
  399. break;
  400. case EIGRP_TLV_AT_EXT:
  401. tlv_ptr.eigrp_tlv_at_ext = (const struct eigrp_tlv_at_ext_t *)tlv_tptr;
  402. if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_at_ext)) {
  403. ND_PRINT((ndo, " (too short, < %u)",
  404. (u_int) (sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_at_ext))));
  405. break;
  406. }
  407. ND_PRINT((ndo, "\n\t Cable-Range: %u-%u, nexthop: ",
  408. EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_ext->cable_start),
  409. EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_ext->cable_end)));
  410. if (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_ext->nexthop) == 0)
  411. ND_PRINT((ndo, "self"));
  412. else
  413. ND_PRINT((ndo, "%u.%u",
  414. EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_ext->nexthop),
  415. EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_ext->nexthop[2])));
  416. ND_PRINT((ndo, "\n\t origin-router %u, origin-as %u, origin-proto %s, flags [0x%02x], tag 0x%08x, metric %u",
  417. EXTRACT_32BITS(tlv_ptr.eigrp_tlv_at_ext->origin_router),
  418. EXTRACT_32BITS(tlv_ptr.eigrp_tlv_at_ext->origin_as),
  419. tok2str(eigrp_ext_proto_id_values,"unknown",tlv_ptr.eigrp_tlv_at_ext->proto_id),
  420. tlv_ptr.eigrp_tlv_at_ext->flags,
  421. EXTRACT_32BITS(tlv_ptr.eigrp_tlv_at_ext->tag),
  422. EXTRACT_16BITS(tlv_ptr.eigrp_tlv_at_ext->metric)));
  423. ND_PRINT((ndo, "\n\t delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u",
  424. (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_ext->delay)/100),
  425. EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_ext->bandwidth),
  426. EXTRACT_24BITS(&tlv_ptr.eigrp_tlv_at_ext->mtu),
  427. tlv_ptr.eigrp_tlv_at_ext->hopcount,
  428. tlv_ptr.eigrp_tlv_at_ext->reliability,
  429. tlv_ptr.eigrp_tlv_at_ext->load));
  430. break;
  431. /*
  432. * FIXME those are the defined TLVs that lack a decoder
  433. * you are welcome to contribute code ;-)
  434. */
  435. case EIGRP_TLV_AUTH:
  436. case EIGRP_TLV_SEQ:
  437. case EIGRP_TLV_MCAST_SEQ:
  438. case EIGRP_TLV_IPX_INT:
  439. case EIGRP_TLV_IPX_EXT:
  440. default:
  441. if (ndo->ndo_vflag <= 1)
  442. print_unknown_data(ndo,tlv_tptr,"\n\t ",tlv_tlen);
  443. break;
  444. }
  445. /* do we want to see an additionally hexdump ? */
  446. if (ndo->ndo_vflag > 1)
  447. print_unknown_data(ndo,tptr+sizeof(struct eigrp_tlv_header),"\n\t ",
  448. eigrp_tlv_len-sizeof(struct eigrp_tlv_header));
  449. tptr+=eigrp_tlv_len;
  450. tlen-=eigrp_tlv_len;
  451. }
  452. return;
  453. trunc:
  454. ND_PRINT((ndo, "\n\t\t packet exceeded snapshot"));
  455. }