print-pgm.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838
  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 Andy Heffernan (ahh@juniper.net)
  14. */
  15. /* \summary: Pragmatic General Multicast (PGM) printer */
  16. #ifdef HAVE_CONFIG_H
  17. #include "config.h"
  18. #endif
  19. #include <netdissect-stdinc.h>
  20. #include "netdissect.h"
  21. #include "extract.h"
  22. #include "addrtoname.h"
  23. #include "addrtostr.h"
  24. #include "ip.h"
  25. #include "ip6.h"
  26. #include "ipproto.h"
  27. #include "af.h"
  28. /*
  29. * PGM header (RFC 3208)
  30. */
  31. struct pgm_header {
  32. uint16_t pgm_sport;
  33. uint16_t pgm_dport;
  34. uint8_t pgm_type;
  35. uint8_t pgm_options;
  36. uint16_t pgm_sum;
  37. uint8_t pgm_gsid[6];
  38. uint16_t pgm_length;
  39. };
  40. struct pgm_spm {
  41. uint32_t pgms_seq;
  42. uint32_t pgms_trailseq;
  43. uint32_t pgms_leadseq;
  44. uint16_t pgms_nla_afi;
  45. uint16_t pgms_reserved;
  46. /* ... uint8_t pgms_nla[0]; */
  47. /* ... options */
  48. };
  49. struct pgm_nak {
  50. uint32_t pgmn_seq;
  51. uint16_t pgmn_source_afi;
  52. uint16_t pgmn_reserved;
  53. /* ... uint8_t pgmn_source[0]; */
  54. /* ... uint16_t pgmn_group_afi */
  55. /* ... uint16_t pgmn_reserved2; */
  56. /* ... uint8_t pgmn_group[0]; */
  57. /* ... options */
  58. };
  59. struct pgm_ack {
  60. uint32_t pgma_rx_max_seq;
  61. uint32_t pgma_bitmap;
  62. /* ... options */
  63. };
  64. struct pgm_poll {
  65. uint32_t pgmp_seq;
  66. uint16_t pgmp_round;
  67. uint16_t pgmp_reserved;
  68. /* ... options */
  69. };
  70. struct pgm_polr {
  71. uint32_t pgmp_seq;
  72. uint16_t pgmp_round;
  73. uint16_t pgmp_subtype;
  74. uint16_t pgmp_nla_afi;
  75. uint16_t pgmp_reserved;
  76. /* ... uint8_t pgmp_nla[0]; */
  77. /* ... options */
  78. };
  79. struct pgm_data {
  80. uint32_t pgmd_seq;
  81. uint32_t pgmd_trailseq;
  82. /* ... options */
  83. };
  84. typedef enum _pgm_type {
  85. PGM_SPM = 0, /* source path message */
  86. PGM_POLL = 1, /* POLL Request */
  87. PGM_POLR = 2, /* POLL Response */
  88. PGM_ODATA = 4, /* original data */
  89. PGM_RDATA = 5, /* repair data */
  90. PGM_NAK = 8, /* NAK */
  91. PGM_NULLNAK = 9, /* Null NAK */
  92. PGM_NCF = 10, /* NAK Confirmation */
  93. PGM_ACK = 11, /* ACK for congestion control */
  94. PGM_SPMR = 12, /* SPM request */
  95. PGM_MAX = 255
  96. } pgm_type;
  97. #define PGM_OPT_BIT_PRESENT 0x01
  98. #define PGM_OPT_BIT_NETWORK 0x02
  99. #define PGM_OPT_BIT_VAR_PKTLEN 0x40
  100. #define PGM_OPT_BIT_PARITY 0x80
  101. #define PGM_OPT_LENGTH 0x00
  102. #define PGM_OPT_FRAGMENT 0x01
  103. #define PGM_OPT_NAK_LIST 0x02
  104. #define PGM_OPT_JOIN 0x03
  105. #define PGM_OPT_NAK_BO_IVL 0x04
  106. #define PGM_OPT_NAK_BO_RNG 0x05
  107. #define PGM_OPT_REDIRECT 0x07
  108. #define PGM_OPT_PARITY_PRM 0x08
  109. #define PGM_OPT_PARITY_GRP 0x09
  110. #define PGM_OPT_CURR_TGSIZE 0x0A
  111. #define PGM_OPT_NBR_UNREACH 0x0B
  112. #define PGM_OPT_PATH_NLA 0x0C
  113. #define PGM_OPT_SYN 0x0D
  114. #define PGM_OPT_FIN 0x0E
  115. #define PGM_OPT_RST 0x0F
  116. #define PGM_OPT_CR 0x10
  117. #define PGM_OPT_CRQST 0x11
  118. #define PGM_OPT_PGMCC_DATA 0x12
  119. #define PGM_OPT_PGMCC_FEEDBACK 0x13
  120. #define PGM_OPT_MASK 0x7f
  121. #define PGM_OPT_END 0x80 /* end of options marker */
  122. #define PGM_MIN_OPT_LEN 4
  123. void
  124. pgm_print(netdissect_options *ndo,
  125. register const u_char *bp, register u_int length,
  126. register const u_char *bp2)
  127. {
  128. register const struct pgm_header *pgm;
  129. register const struct ip *ip;
  130. register char ch;
  131. uint16_t sport, dport;
  132. u_int nla_afnum;
  133. char nla_buf[INET6_ADDRSTRLEN];
  134. register const struct ip6_hdr *ip6;
  135. uint8_t opt_type, opt_len;
  136. uint32_t seq, opts_len, len, offset;
  137. pgm = (const struct pgm_header *)bp;
  138. ip = (const struct ip *)bp2;
  139. if (IP_V(ip) == 6)
  140. ip6 = (const struct ip6_hdr *)bp2;
  141. else
  142. ip6 = NULL;
  143. ch = '\0';
  144. if (!ND_TTEST(pgm->pgm_dport)) {
  145. if (ip6) {
  146. ND_PRINT((ndo, "%s > %s: [|pgm]",
  147. ip6addr_string(ndo, &ip6->ip6_src),
  148. ip6addr_string(ndo, &ip6->ip6_dst)));
  149. } else {
  150. ND_PRINT((ndo, "%s > %s: [|pgm]",
  151. ipaddr_string(ndo, &ip->ip_src),
  152. ipaddr_string(ndo, &ip->ip_dst)));
  153. }
  154. return;
  155. }
  156. sport = EXTRACT_16BITS(&pgm->pgm_sport);
  157. dport = EXTRACT_16BITS(&pgm->pgm_dport);
  158. if (ip6) {
  159. if (ip6->ip6_nxt == IPPROTO_PGM) {
  160. ND_PRINT((ndo, "%s.%s > %s.%s: ",
  161. ip6addr_string(ndo, &ip6->ip6_src),
  162. tcpport_string(ndo, sport),
  163. ip6addr_string(ndo, &ip6->ip6_dst),
  164. tcpport_string(ndo, dport)));
  165. } else {
  166. ND_PRINT((ndo, "%s > %s: ",
  167. tcpport_string(ndo, sport), tcpport_string(ndo, dport)));
  168. }
  169. } else {
  170. if (ip->ip_p == IPPROTO_PGM) {
  171. ND_PRINT((ndo, "%s.%s > %s.%s: ",
  172. ipaddr_string(ndo, &ip->ip_src),
  173. tcpport_string(ndo, sport),
  174. ipaddr_string(ndo, &ip->ip_dst),
  175. tcpport_string(ndo, dport)));
  176. } else {
  177. ND_PRINT((ndo, "%s > %s: ",
  178. tcpport_string(ndo, sport), tcpport_string(ndo, dport)));
  179. }
  180. }
  181. ND_TCHECK(*pgm);
  182. ND_PRINT((ndo, "PGM, length %u", EXTRACT_16BITS(&pgm->pgm_length)));
  183. if (!ndo->ndo_vflag)
  184. return;
  185. ND_PRINT((ndo, " 0x%02x%02x%02x%02x%02x%02x ",
  186. pgm->pgm_gsid[0],
  187. pgm->pgm_gsid[1],
  188. pgm->pgm_gsid[2],
  189. pgm->pgm_gsid[3],
  190. pgm->pgm_gsid[4],
  191. pgm->pgm_gsid[5]));
  192. switch (pgm->pgm_type) {
  193. case PGM_SPM: {
  194. const struct pgm_spm *spm;
  195. spm = (const struct pgm_spm *)(pgm + 1);
  196. ND_TCHECK(*spm);
  197. bp = (const u_char *) (spm + 1);
  198. switch (EXTRACT_16BITS(&spm->pgms_nla_afi)) {
  199. case AFNUM_INET:
  200. ND_TCHECK2(*bp, sizeof(struct in_addr));
  201. addrtostr(bp, nla_buf, sizeof(nla_buf));
  202. bp += sizeof(struct in_addr);
  203. break;
  204. case AFNUM_INET6:
  205. ND_TCHECK2(*bp, sizeof(struct in6_addr));
  206. addrtostr6(bp, nla_buf, sizeof(nla_buf));
  207. bp += sizeof(struct in6_addr);
  208. break;
  209. default:
  210. goto trunc;
  211. break;
  212. }
  213. ND_PRINT((ndo, "SPM seq %u trail %u lead %u nla %s",
  214. EXTRACT_32BITS(&spm->pgms_seq),
  215. EXTRACT_32BITS(&spm->pgms_trailseq),
  216. EXTRACT_32BITS(&spm->pgms_leadseq),
  217. nla_buf));
  218. break;
  219. }
  220. case PGM_POLL: {
  221. const struct pgm_poll *poll_msg;
  222. poll_msg = (const struct pgm_poll *)(pgm + 1);
  223. ND_TCHECK(*poll_msg);
  224. ND_PRINT((ndo, "POLL seq %u round %u",
  225. EXTRACT_32BITS(&poll_msg->pgmp_seq),
  226. EXTRACT_16BITS(&poll_msg->pgmp_round)));
  227. bp = (const u_char *) (poll_msg + 1);
  228. break;
  229. }
  230. case PGM_POLR: {
  231. const struct pgm_polr *polr;
  232. uint32_t ivl, rnd, mask;
  233. polr = (const struct pgm_polr *)(pgm + 1);
  234. ND_TCHECK(*polr);
  235. bp = (const u_char *) (polr + 1);
  236. switch (EXTRACT_16BITS(&polr->pgmp_nla_afi)) {
  237. case AFNUM_INET:
  238. ND_TCHECK2(*bp, sizeof(struct in_addr));
  239. addrtostr(bp, nla_buf, sizeof(nla_buf));
  240. bp += sizeof(struct in_addr);
  241. break;
  242. case AFNUM_INET6:
  243. ND_TCHECK2(*bp, sizeof(struct in6_addr));
  244. addrtostr6(bp, nla_buf, sizeof(nla_buf));
  245. bp += sizeof(struct in6_addr);
  246. break;
  247. default:
  248. goto trunc;
  249. break;
  250. }
  251. ND_TCHECK2(*bp, sizeof(uint32_t));
  252. ivl = EXTRACT_32BITS(bp);
  253. bp += sizeof(uint32_t);
  254. ND_TCHECK2(*bp, sizeof(uint32_t));
  255. rnd = EXTRACT_32BITS(bp);
  256. bp += sizeof(uint32_t);
  257. ND_TCHECK2(*bp, sizeof(uint32_t));
  258. mask = EXTRACT_32BITS(bp);
  259. bp += sizeof(uint32_t);
  260. ND_PRINT((ndo, "POLR seq %u round %u nla %s ivl %u rnd 0x%08x "
  261. "mask 0x%08x", EXTRACT_32BITS(&polr->pgmp_seq),
  262. EXTRACT_16BITS(&polr->pgmp_round), nla_buf, ivl, rnd, mask));
  263. break;
  264. }
  265. case PGM_ODATA: {
  266. const struct pgm_data *odata;
  267. odata = (const struct pgm_data *)(pgm + 1);
  268. ND_TCHECK(*odata);
  269. ND_PRINT((ndo, "ODATA trail %u seq %u",
  270. EXTRACT_32BITS(&odata->pgmd_trailseq),
  271. EXTRACT_32BITS(&odata->pgmd_seq)));
  272. bp = (const u_char *) (odata + 1);
  273. break;
  274. }
  275. case PGM_RDATA: {
  276. const struct pgm_data *rdata;
  277. rdata = (const struct pgm_data *)(pgm + 1);
  278. ND_TCHECK(*rdata);
  279. ND_PRINT((ndo, "RDATA trail %u seq %u",
  280. EXTRACT_32BITS(&rdata->pgmd_trailseq),
  281. EXTRACT_32BITS(&rdata->pgmd_seq)));
  282. bp = (const u_char *) (rdata + 1);
  283. break;
  284. }
  285. case PGM_NAK:
  286. case PGM_NULLNAK:
  287. case PGM_NCF: {
  288. const struct pgm_nak *nak;
  289. char source_buf[INET6_ADDRSTRLEN], group_buf[INET6_ADDRSTRLEN];
  290. nak = (const struct pgm_nak *)(pgm + 1);
  291. ND_TCHECK(*nak);
  292. bp = (const u_char *) (nak + 1);
  293. /*
  294. * Skip past the source, saving info along the way
  295. * and stopping if we don't have enough.
  296. */
  297. switch (EXTRACT_16BITS(&nak->pgmn_source_afi)) {
  298. case AFNUM_INET:
  299. ND_TCHECK2(*bp, sizeof(struct in_addr));
  300. addrtostr(bp, source_buf, sizeof(source_buf));
  301. bp += sizeof(struct in_addr);
  302. break;
  303. case AFNUM_INET6:
  304. ND_TCHECK2(*bp, sizeof(struct in6_addr));
  305. addrtostr6(bp, source_buf, sizeof(source_buf));
  306. bp += sizeof(struct in6_addr);
  307. break;
  308. default:
  309. goto trunc;
  310. break;
  311. }
  312. /*
  313. * Skip past the group, saving info along the way
  314. * and stopping if we don't have enough.
  315. */
  316. bp += (2 * sizeof(uint16_t));
  317. ND_TCHECK_16BITS(bp);
  318. switch (EXTRACT_16BITS(bp)) {
  319. case AFNUM_INET:
  320. ND_TCHECK2(*bp, sizeof(struct in_addr));
  321. addrtostr(bp, group_buf, sizeof(group_buf));
  322. bp += sizeof(struct in_addr);
  323. break;
  324. case AFNUM_INET6:
  325. ND_TCHECK2(*bp, sizeof(struct in6_addr));
  326. addrtostr6(bp, group_buf, sizeof(group_buf));
  327. bp += sizeof(struct in6_addr);
  328. break;
  329. default:
  330. goto trunc;
  331. break;
  332. }
  333. /*
  334. * Options decoding can go here.
  335. */
  336. switch (pgm->pgm_type) {
  337. case PGM_NAK:
  338. ND_PRINT((ndo, "NAK "));
  339. break;
  340. case PGM_NULLNAK:
  341. ND_PRINT((ndo, "NNAK "));
  342. break;
  343. case PGM_NCF:
  344. ND_PRINT((ndo, "NCF "));
  345. break;
  346. default:
  347. break;
  348. }
  349. ND_PRINT((ndo, "(%s -> %s), seq %u",
  350. source_buf, group_buf, EXTRACT_32BITS(&nak->pgmn_seq)));
  351. break;
  352. }
  353. case PGM_ACK: {
  354. const struct pgm_ack *ack;
  355. ack = (const struct pgm_ack *)(pgm + 1);
  356. ND_TCHECK(*ack);
  357. ND_PRINT((ndo, "ACK seq %u",
  358. EXTRACT_32BITS(&ack->pgma_rx_max_seq)));
  359. bp = (const u_char *) (ack + 1);
  360. break;
  361. }
  362. case PGM_SPMR:
  363. ND_PRINT((ndo, "SPMR"));
  364. break;
  365. default:
  366. ND_PRINT((ndo, "UNKNOWN type 0x%02x", pgm->pgm_type));
  367. break;
  368. }
  369. if (pgm->pgm_options & PGM_OPT_BIT_PRESENT) {
  370. /*
  371. * make sure there's enough for the first option header
  372. */
  373. if (!ND_TTEST2(*bp, PGM_MIN_OPT_LEN)) {
  374. ND_PRINT((ndo, "[|OPT]"));
  375. return;
  376. }
  377. /*
  378. * That option header MUST be an OPT_LENGTH option
  379. * (see the first paragraph of section 9.1 in RFC 3208).
  380. */
  381. opt_type = *bp++;
  382. if ((opt_type & PGM_OPT_MASK) != PGM_OPT_LENGTH) {
  383. ND_PRINT((ndo, "[First option bad, should be PGM_OPT_LENGTH, is %u]", opt_type & PGM_OPT_MASK));
  384. return;
  385. }
  386. opt_len = *bp++;
  387. if (opt_len != 4) {
  388. ND_PRINT((ndo, "[Bad OPT_LENGTH option, length %u != 4]", opt_len));
  389. return;
  390. }
  391. opts_len = EXTRACT_16BITS(bp);
  392. if (opts_len < 4) {
  393. ND_PRINT((ndo, "[Bad total option length %u < 4]", opts_len));
  394. return;
  395. }
  396. bp += sizeof(uint16_t);
  397. ND_PRINT((ndo, " OPTS LEN %d", opts_len));
  398. opts_len -= 4;
  399. while (opts_len) {
  400. if (opts_len < PGM_MIN_OPT_LEN) {
  401. ND_PRINT((ndo, "[Total option length leaves no room for final option]"));
  402. return;
  403. }
  404. if (!ND_TTEST2(*bp, 2)) {
  405. ND_PRINT((ndo, " [|OPT]"));
  406. return;
  407. }
  408. opt_type = *bp++;
  409. opt_len = *bp++;
  410. if (opt_len < PGM_MIN_OPT_LEN) {
  411. ND_PRINT((ndo, "[Bad option, length %u < %u]", opt_len,
  412. PGM_MIN_OPT_LEN));
  413. break;
  414. }
  415. if (opts_len < opt_len) {
  416. ND_PRINT((ndo, "[Total option length leaves no room for final option]"));
  417. return;
  418. }
  419. if (!ND_TTEST2(*bp, opt_len - 2)) {
  420. ND_PRINT((ndo, " [|OPT]"));
  421. return;
  422. }
  423. switch (opt_type & PGM_OPT_MASK) {
  424. case PGM_OPT_LENGTH:
  425. #define PGM_OPT_LENGTH_LEN (2+2)
  426. if (opt_len != PGM_OPT_LENGTH_LEN) {
  427. ND_PRINT((ndo, "[Bad OPT_LENGTH option, length %u != %u]",
  428. opt_len, PGM_OPT_LENGTH_LEN));
  429. return;
  430. }
  431. ND_PRINT((ndo, " OPTS LEN (extra?) %d", EXTRACT_16BITS(bp)));
  432. bp += 2;
  433. opts_len -= PGM_OPT_LENGTH_LEN;
  434. break;
  435. case PGM_OPT_FRAGMENT:
  436. #define PGM_OPT_FRAGMENT_LEN (2+2+4+4+4)
  437. if (opt_len != PGM_OPT_FRAGMENT_LEN) {
  438. ND_PRINT((ndo, "[Bad OPT_FRAGMENT option, length %u != %u]",
  439. opt_len, PGM_OPT_FRAGMENT_LEN));
  440. return;
  441. }
  442. bp += 2;
  443. seq = EXTRACT_32BITS(bp);
  444. bp += 4;
  445. offset = EXTRACT_32BITS(bp);
  446. bp += 4;
  447. len = EXTRACT_32BITS(bp);
  448. bp += 4;
  449. ND_PRINT((ndo, " FRAG seq %u off %u len %u", seq, offset, len));
  450. opts_len -= PGM_OPT_FRAGMENT_LEN;
  451. break;
  452. case PGM_OPT_NAK_LIST:
  453. bp += 2;
  454. opt_len -= 4; /* option header */
  455. ND_PRINT((ndo, " NAK LIST"));
  456. while (opt_len) {
  457. if (opt_len < 4) {
  458. ND_PRINT((ndo, "[Option length not a multiple of 4]"));
  459. return;
  460. }
  461. ND_TCHECK2(*bp, 4);
  462. ND_PRINT((ndo, " %u", EXTRACT_32BITS(bp)));
  463. bp += 4;
  464. opt_len -= 4;
  465. opts_len -= 4;
  466. }
  467. break;
  468. case PGM_OPT_JOIN:
  469. #define PGM_OPT_JOIN_LEN (2+2+4)
  470. if (opt_len != PGM_OPT_JOIN_LEN) {
  471. ND_PRINT((ndo, "[Bad OPT_JOIN option, length %u != %u]",
  472. opt_len, PGM_OPT_JOIN_LEN));
  473. return;
  474. }
  475. bp += 2;
  476. seq = EXTRACT_32BITS(bp);
  477. bp += 4;
  478. ND_PRINT((ndo, " JOIN %u", seq));
  479. opts_len -= PGM_OPT_JOIN_LEN;
  480. break;
  481. case PGM_OPT_NAK_BO_IVL:
  482. #define PGM_OPT_NAK_BO_IVL_LEN (2+2+4+4)
  483. if (opt_len != PGM_OPT_NAK_BO_IVL_LEN) {
  484. ND_PRINT((ndo, "[Bad OPT_NAK_BO_IVL option, length %u != %u]",
  485. opt_len, PGM_OPT_NAK_BO_IVL_LEN));
  486. return;
  487. }
  488. bp += 2;
  489. offset = EXTRACT_32BITS(bp);
  490. bp += 4;
  491. seq = EXTRACT_32BITS(bp);
  492. bp += 4;
  493. ND_PRINT((ndo, " BACKOFF ivl %u ivlseq %u", offset, seq));
  494. opts_len -= PGM_OPT_NAK_BO_IVL_LEN;
  495. break;
  496. case PGM_OPT_NAK_BO_RNG:
  497. #define PGM_OPT_NAK_BO_RNG_LEN (2+2+4+4)
  498. if (opt_len != PGM_OPT_NAK_BO_RNG_LEN) {
  499. ND_PRINT((ndo, "[Bad OPT_NAK_BO_RNG option, length %u != %u]",
  500. opt_len, PGM_OPT_NAK_BO_RNG_LEN));
  501. return;
  502. }
  503. bp += 2;
  504. offset = EXTRACT_32BITS(bp);
  505. bp += 4;
  506. seq = EXTRACT_32BITS(bp);
  507. bp += 4;
  508. ND_PRINT((ndo, " BACKOFF max %u min %u", offset, seq));
  509. opts_len -= PGM_OPT_NAK_BO_RNG_LEN;
  510. break;
  511. case PGM_OPT_REDIRECT:
  512. #define PGM_OPT_REDIRECT_FIXED_LEN (2+2+2+2)
  513. if (opt_len < PGM_OPT_REDIRECT_FIXED_LEN) {
  514. ND_PRINT((ndo, "[Bad OPT_REDIRECT option, length %u < %u]",
  515. opt_len, PGM_OPT_REDIRECT_FIXED_LEN));
  516. return;
  517. }
  518. bp += 2;
  519. nla_afnum = EXTRACT_16BITS(bp);
  520. bp += 2+2;
  521. switch (nla_afnum) {
  522. case AFNUM_INET:
  523. if (opt_len != PGM_OPT_REDIRECT_FIXED_LEN + sizeof(struct in_addr)) {
  524. ND_PRINT((ndo, "[Bad OPT_REDIRECT option, length %u != %u + address size]",
  525. opt_len, PGM_OPT_REDIRECT_FIXED_LEN));
  526. return;
  527. }
  528. ND_TCHECK2(*bp, sizeof(struct in_addr));
  529. addrtostr(bp, nla_buf, sizeof(nla_buf));
  530. bp += sizeof(struct in_addr);
  531. opts_len -= PGM_OPT_REDIRECT_FIXED_LEN + sizeof(struct in_addr);
  532. break;
  533. case AFNUM_INET6:
  534. if (opt_len != PGM_OPT_REDIRECT_FIXED_LEN + sizeof(struct in6_addr)) {
  535. ND_PRINT((ndo, "[Bad OPT_REDIRECT option, length %u != %u + address size]",
  536. PGM_OPT_REDIRECT_FIXED_LEN, opt_len));
  537. return;
  538. }
  539. ND_TCHECK2(*bp, sizeof(struct in6_addr));
  540. addrtostr6(bp, nla_buf, sizeof(nla_buf));
  541. bp += sizeof(struct in6_addr);
  542. opts_len -= PGM_OPT_REDIRECT_FIXED_LEN + sizeof(struct in6_addr);
  543. break;
  544. default:
  545. goto trunc;
  546. break;
  547. }
  548. ND_PRINT((ndo, " REDIRECT %s", nla_buf));
  549. break;
  550. case PGM_OPT_PARITY_PRM:
  551. #define PGM_OPT_PARITY_PRM_LEN (2+2+4)
  552. if (opt_len != PGM_OPT_PARITY_PRM_LEN) {
  553. ND_PRINT((ndo, "[Bad OPT_PARITY_PRM option, length %u != %u]",
  554. opt_len, PGM_OPT_PARITY_PRM_LEN));
  555. return;
  556. }
  557. bp += 2;
  558. len = EXTRACT_32BITS(bp);
  559. bp += 4;
  560. ND_PRINT((ndo, " PARITY MAXTGS %u", len));
  561. opts_len -= PGM_OPT_PARITY_PRM_LEN;
  562. break;
  563. case PGM_OPT_PARITY_GRP:
  564. #define PGM_OPT_PARITY_GRP_LEN (2+2+4)
  565. if (opt_len != PGM_OPT_PARITY_GRP_LEN) {
  566. ND_PRINT((ndo, "[Bad OPT_PARITY_GRP option, length %u != %u]",
  567. opt_len, PGM_OPT_PARITY_GRP_LEN));
  568. return;
  569. }
  570. bp += 2;
  571. seq = EXTRACT_32BITS(bp);
  572. bp += 4;
  573. ND_PRINT((ndo, " PARITY GROUP %u", seq));
  574. opts_len -= PGM_OPT_PARITY_GRP_LEN;
  575. break;
  576. case PGM_OPT_CURR_TGSIZE:
  577. #define PGM_OPT_CURR_TGSIZE_LEN (2+2+4)
  578. if (opt_len != PGM_OPT_CURR_TGSIZE_LEN) {
  579. ND_PRINT((ndo, "[Bad OPT_CURR_TGSIZE option, length %u != %u]",
  580. opt_len, PGM_OPT_CURR_TGSIZE_LEN));
  581. return;
  582. }
  583. bp += 2;
  584. len = EXTRACT_32BITS(bp);
  585. bp += 4;
  586. ND_PRINT((ndo, " PARITY ATGS %u", len));
  587. opts_len -= PGM_OPT_CURR_TGSIZE_LEN;
  588. break;
  589. case PGM_OPT_NBR_UNREACH:
  590. #define PGM_OPT_NBR_UNREACH_LEN (2+2)
  591. if (opt_len != PGM_OPT_NBR_UNREACH_LEN) {
  592. ND_PRINT((ndo, "[Bad OPT_NBR_UNREACH option, length %u != %u]",
  593. opt_len, PGM_OPT_NBR_UNREACH_LEN));
  594. return;
  595. }
  596. bp += 2;
  597. ND_PRINT((ndo, " NBR_UNREACH"));
  598. opts_len -= PGM_OPT_NBR_UNREACH_LEN;
  599. break;
  600. case PGM_OPT_PATH_NLA:
  601. ND_PRINT((ndo, " PATH_NLA [%d]", opt_len));
  602. bp += opt_len;
  603. opts_len -= opt_len;
  604. break;
  605. case PGM_OPT_SYN:
  606. #define PGM_OPT_SYN_LEN (2+2)
  607. if (opt_len != PGM_OPT_SYN_LEN) {
  608. ND_PRINT((ndo, "[Bad OPT_SYN option, length %u != %u]",
  609. opt_len, PGM_OPT_SYN_LEN));
  610. return;
  611. }
  612. bp += 2;
  613. ND_PRINT((ndo, " SYN"));
  614. opts_len -= PGM_OPT_SYN_LEN;
  615. break;
  616. case PGM_OPT_FIN:
  617. #define PGM_OPT_FIN_LEN (2+2)
  618. if (opt_len != PGM_OPT_FIN_LEN) {
  619. ND_PRINT((ndo, "[Bad OPT_FIN option, length %u != %u]",
  620. opt_len, PGM_OPT_FIN_LEN));
  621. return;
  622. }
  623. bp += 2;
  624. ND_PRINT((ndo, " FIN"));
  625. opts_len -= PGM_OPT_FIN_LEN;
  626. break;
  627. case PGM_OPT_RST:
  628. #define PGM_OPT_RST_LEN (2+2)
  629. if (opt_len != PGM_OPT_RST_LEN) {
  630. ND_PRINT((ndo, "[Bad OPT_RST option, length %u != %u]",
  631. opt_len, PGM_OPT_RST_LEN));
  632. return;
  633. }
  634. bp += 2;
  635. ND_PRINT((ndo, " RST"));
  636. opts_len -= PGM_OPT_RST_LEN;
  637. break;
  638. case PGM_OPT_CR:
  639. ND_PRINT((ndo, " CR"));
  640. bp += opt_len;
  641. opts_len -= opt_len;
  642. break;
  643. case PGM_OPT_CRQST:
  644. #define PGM_OPT_CRQST_LEN (2+2)
  645. if (opt_len != PGM_OPT_CRQST_LEN) {
  646. ND_PRINT((ndo, "[Bad OPT_CRQST option, length %u != %u]",
  647. opt_len, PGM_OPT_CRQST_LEN));
  648. return;
  649. }
  650. bp += 2;
  651. ND_PRINT((ndo, " CRQST"));
  652. opts_len -= PGM_OPT_CRQST_LEN;
  653. break;
  654. case PGM_OPT_PGMCC_DATA:
  655. #define PGM_OPT_PGMCC_DATA_FIXED_LEN (2+2+4+2+2)
  656. if (opt_len < PGM_OPT_PGMCC_DATA_FIXED_LEN) {
  657. ND_PRINT((ndo, "[Bad OPT_PGMCC_DATA option, length %u < %u]",
  658. opt_len, PGM_OPT_PGMCC_DATA_FIXED_LEN));
  659. return;
  660. }
  661. bp += 2;
  662. offset = EXTRACT_32BITS(bp);
  663. bp += 4;
  664. nla_afnum = EXTRACT_16BITS(bp);
  665. bp += 2+2;
  666. switch (nla_afnum) {
  667. case AFNUM_INET:
  668. if (opt_len != PGM_OPT_PGMCC_DATA_FIXED_LEN + sizeof(struct in_addr)) {
  669. ND_PRINT((ndo, "[Bad OPT_PGMCC_DATA option, length %u != %u + address size]",
  670. opt_len, PGM_OPT_PGMCC_DATA_FIXED_LEN));
  671. return;
  672. }
  673. ND_TCHECK2(*bp, sizeof(struct in_addr));
  674. addrtostr(bp, nla_buf, sizeof(nla_buf));
  675. bp += sizeof(struct in_addr);
  676. opts_len -= PGM_OPT_PGMCC_DATA_FIXED_LEN + sizeof(struct in_addr);
  677. break;
  678. case AFNUM_INET6:
  679. if (opt_len != PGM_OPT_PGMCC_DATA_FIXED_LEN + sizeof(struct in6_addr)) {
  680. ND_PRINT((ndo, "[Bad OPT_PGMCC_DATA option, length %u != %u + address size]",
  681. opt_len, PGM_OPT_PGMCC_DATA_FIXED_LEN));
  682. return;
  683. }
  684. ND_TCHECK2(*bp, sizeof(struct in6_addr));
  685. addrtostr6(bp, nla_buf, sizeof(nla_buf));
  686. bp += sizeof(struct in6_addr);
  687. opts_len -= PGM_OPT_PGMCC_DATA_FIXED_LEN + sizeof(struct in6_addr);
  688. break;
  689. default:
  690. goto trunc;
  691. break;
  692. }
  693. ND_PRINT((ndo, " PGMCC DATA %u %s", offset, nla_buf));
  694. break;
  695. case PGM_OPT_PGMCC_FEEDBACK:
  696. #define PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN (2+2+4+2+2)
  697. if (opt_len < PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN) {
  698. ND_PRINT((ndo, "[Bad PGM_OPT_PGMCC_FEEDBACK option, length %u < %u]",
  699. opt_len, PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN));
  700. return;
  701. }
  702. bp += 2;
  703. offset = EXTRACT_32BITS(bp);
  704. bp += 4;
  705. nla_afnum = EXTRACT_16BITS(bp);
  706. bp += 2+2;
  707. switch (nla_afnum) {
  708. case AFNUM_INET:
  709. if (opt_len != PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN + sizeof(struct in_addr)) {
  710. ND_PRINT((ndo, "[Bad OPT_PGMCC_FEEDBACK option, length %u != %u + address size]",
  711. opt_len, PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN));
  712. return;
  713. }
  714. ND_TCHECK2(*bp, sizeof(struct in_addr));
  715. addrtostr(bp, nla_buf, sizeof(nla_buf));
  716. bp += sizeof(struct in_addr);
  717. opts_len -= PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN + sizeof(struct in_addr);
  718. break;
  719. case AFNUM_INET6:
  720. if (opt_len != PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN + sizeof(struct in6_addr)) {
  721. ND_PRINT((ndo, "[Bad OPT_PGMCC_FEEDBACK option, length %u != %u + address size]",
  722. opt_len, PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN));
  723. return;
  724. }
  725. ND_TCHECK2(*bp, sizeof(struct in6_addr));
  726. addrtostr6(bp, nla_buf, sizeof(nla_buf));
  727. bp += sizeof(struct in6_addr);
  728. opts_len -= PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN + sizeof(struct in6_addr);
  729. break;
  730. default:
  731. goto trunc;
  732. break;
  733. }
  734. ND_PRINT((ndo, " PGMCC FEEDBACK %u %s", offset, nla_buf));
  735. break;
  736. default:
  737. ND_PRINT((ndo, " OPT_%02X [%d] ", opt_type, opt_len));
  738. bp += opt_len;
  739. opts_len -= opt_len;
  740. break;
  741. }
  742. if (opt_type & PGM_OPT_END)
  743. break;
  744. }
  745. }
  746. ND_PRINT((ndo, " [%u]", length));
  747. if (ndo->ndo_packettype == PT_PGM_ZMTP1 &&
  748. (pgm->pgm_type == PGM_ODATA || pgm->pgm_type == PGM_RDATA))
  749. zmtp1_print_datagram(ndo, bp, EXTRACT_16BITS(&pgm->pgm_length));
  750. return;
  751. trunc:
  752. ND_PRINT((ndo, "[|pgm]"));
  753. if (ch != '\0')
  754. ND_PRINT((ndo, ">"));
  755. }