print-babel.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717
  1. /*
  2. * Copyright (c) 2007-2011 Grégoire Henry, Juliusz Chroboczek
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. * 1. Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * 2. Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. * 3. Neither the name of the project nor the names of its contributors
  13. * may be used to endorse or promote products derived from this software
  14. * without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
  17. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  18. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  19. * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
  20. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  21. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  22. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  23. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  24. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  25. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  26. * SUCH DAMAGE.
  27. */
  28. /* \summary: Babel Routing Protocol printer */
  29. #ifdef HAVE_CONFIG_H
  30. #include "config.h"
  31. #endif
  32. #include <netdissect-stdinc.h>
  33. #include <stdio.h>
  34. #include <string.h>
  35. #include "netdissect.h"
  36. #include "addrtoname.h"
  37. #include "extract.h"
  38. static const char tstr[] = "[|babel]";
  39. static void babel_print_v2(netdissect_options *, const u_char *cp, u_int length);
  40. void
  41. babel_print(netdissect_options *ndo,
  42. const u_char *cp, u_int length)
  43. {
  44. ND_PRINT((ndo, "babel"));
  45. ND_TCHECK2(*cp, 4);
  46. if(cp[0] != 42) {
  47. ND_PRINT((ndo, " invalid header"));
  48. return;
  49. } else {
  50. ND_PRINT((ndo, " %d", cp[1]));
  51. }
  52. switch(cp[1]) {
  53. case 2:
  54. babel_print_v2(ndo, cp, length);
  55. break;
  56. default:
  57. ND_PRINT((ndo, " unknown version"));
  58. break;
  59. }
  60. return;
  61. trunc:
  62. ND_PRINT((ndo, " %s", tstr));
  63. return;
  64. }
  65. /* TLVs */
  66. #define MESSAGE_PAD1 0
  67. #define MESSAGE_PADN 1
  68. #define MESSAGE_ACK_REQ 2
  69. #define MESSAGE_ACK 3
  70. #define MESSAGE_HELLO 4
  71. #define MESSAGE_IHU 5
  72. #define MESSAGE_ROUTER_ID 6
  73. #define MESSAGE_NH 7
  74. #define MESSAGE_UPDATE 8
  75. #define MESSAGE_REQUEST 9
  76. #define MESSAGE_MH_REQUEST 10
  77. #define MESSAGE_TSPC 11
  78. #define MESSAGE_HMAC 12
  79. #define MESSAGE_UPDATE_SRC_SPECIFIC 13
  80. #define MESSAGE_REQUEST_SRC_SPECIFIC 14
  81. #define MESSAGE_MH_REQUEST_SRC_SPECIFIC 15
  82. /* sub-TLVs */
  83. #define MESSAGE_SUB_PAD1 0
  84. #define MESSAGE_SUB_PADN 1
  85. #define MESSAGE_SUB_DIVERSITY 2
  86. #define MESSAGE_SUB_TIMESTAMP 3
  87. /* Diversity sub-TLV channel codes */
  88. static const struct tok diversity_str[] = {
  89. { 0, "reserved" },
  90. { 255, "all" },
  91. { 0, NULL }
  92. };
  93. static const char *
  94. format_id(const u_char *id)
  95. {
  96. static char buf[25];
  97. snprintf(buf, 25, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
  98. id[0], id[1], id[2], id[3], id[4], id[5], id[6], id[7]);
  99. buf[24] = '\0';
  100. return buf;
  101. }
  102. static const unsigned char v4prefix[16] =
  103. {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 };
  104. static const char *
  105. format_prefix(netdissect_options *ndo, const u_char *prefix, unsigned char plen)
  106. {
  107. static char buf[50];
  108. if(plen >= 96 && memcmp(prefix, v4prefix, 12) == 0)
  109. snprintf(buf, 50, "%s/%u", ipaddr_string(ndo, prefix + 12), plen - 96);
  110. else
  111. snprintf(buf, 50, "%s/%u", ip6addr_string(ndo, prefix), plen);
  112. buf[49] = '\0';
  113. return buf;
  114. }
  115. static const char *
  116. format_address(netdissect_options *ndo, const u_char *prefix)
  117. {
  118. if(memcmp(prefix, v4prefix, 12) == 0)
  119. return ipaddr_string(ndo, prefix + 12);
  120. else
  121. return ip6addr_string(ndo, prefix);
  122. }
  123. static const char *
  124. format_interval(const uint16_t i)
  125. {
  126. static char buf[sizeof("000.00s")];
  127. if (i == 0)
  128. return "0.0s (bogus)";
  129. snprintf(buf, sizeof(buf), "%u.%02us", i / 100, i % 100);
  130. return buf;
  131. }
  132. static const char *
  133. format_interval_update(const uint16_t i)
  134. {
  135. return i == 0xFFFF ? "infinity" : format_interval(i);
  136. }
  137. static const char *
  138. format_timestamp(const uint32_t i)
  139. {
  140. static char buf[sizeof("0000.000000s")];
  141. snprintf(buf, sizeof(buf), "%u.%06us", i / 1000000, i % 1000000);
  142. return buf;
  143. }
  144. /* Return number of octets consumed from the input buffer (not the prefix length
  145. * in bytes), or -1 for encoding error. */
  146. static int
  147. network_prefix(int ae, int plen, unsigned int omitted,
  148. const unsigned char *p, const unsigned char *dp,
  149. unsigned int len, unsigned char *p_r)
  150. {
  151. unsigned pb;
  152. unsigned char prefix[16];
  153. int consumed = 0;
  154. if(plen >= 0)
  155. pb = (plen + 7) / 8;
  156. else if(ae == 1)
  157. pb = 4;
  158. else
  159. pb = 16;
  160. if(pb > 16)
  161. return -1;
  162. memset(prefix, 0, 16);
  163. switch(ae) {
  164. case 0: break;
  165. case 1:
  166. if(omitted > 4 || pb > 4 || (pb > omitted && len < pb - omitted))
  167. return -1;
  168. memcpy(prefix, v4prefix, 12);
  169. if(omitted) {
  170. if (dp == NULL) return -1;
  171. memcpy(prefix, dp, 12 + omitted);
  172. }
  173. if(pb > omitted) {
  174. memcpy(prefix + 12 + omitted, p, pb - omitted);
  175. consumed = pb - omitted;
  176. }
  177. break;
  178. case 2:
  179. if(omitted > 16 || (pb > omitted && len < pb - omitted))
  180. return -1;
  181. if(omitted) {
  182. if (dp == NULL) return -1;
  183. memcpy(prefix, dp, omitted);
  184. }
  185. if(pb > omitted) {
  186. memcpy(prefix + omitted, p, pb - omitted);
  187. consumed = pb - omitted;
  188. }
  189. break;
  190. case 3:
  191. if(pb > 8 && len < pb - 8) return -1;
  192. prefix[0] = 0xfe;
  193. prefix[1] = 0x80;
  194. if(pb > 8) {
  195. memcpy(prefix + 8, p, pb - 8);
  196. consumed = pb - 8;
  197. }
  198. break;
  199. default:
  200. return -1;
  201. }
  202. memcpy(p_r, prefix, 16);
  203. return consumed;
  204. }
  205. static int
  206. network_address(int ae, const unsigned char *a, unsigned int len,
  207. unsigned char *a_r)
  208. {
  209. return network_prefix(ae, -1, 0, a, NULL, len, a_r);
  210. }
  211. /*
  212. * Sub-TLVs consume the "extra data" of Babel TLVs (see Section 4.3 of RFC6126),
  213. * their encoding is similar to the encoding of TLVs, but the type namespace is
  214. * different:
  215. *
  216. * o Type 0 stands for Pad1 sub-TLV with the same encoding as the Pad1 TLV.
  217. * o Type 1 stands for PadN sub-TLV with the same encoding as the PadN TLV.
  218. * o Type 2 stands for Diversity sub-TLV, which propagates diversity routing
  219. * data. Its body is a variable-length sequence of 8-bit unsigned integers,
  220. * each representing per-hop number of interferring radio channel for the
  221. * prefix. Channel 0 is invalid and must not be used in the sub-TLV, channel
  222. * 255 interferes with any other channel.
  223. * o Type 3 stands for Timestamp sub-TLV, used to compute RTT between
  224. * neighbours. In the case of a Hello TLV, the body stores a 32-bits
  225. * timestamp, while in the case of a IHU TLV, two 32-bits timestamps are
  226. * stored.
  227. *
  228. * Sub-TLV types 0 and 1 are valid for any TLV type, whether sub-TLV type 2 is
  229. * only valid for TLV type 8 (Update). Note that within an Update TLV a missing
  230. * Diversity sub-TLV is not the same as a Diversity sub-TLV with an empty body.
  231. * The former would mean a lack of any claims about the interference, and the
  232. * latter would state that interference is definitely absent.
  233. * A type 3 sub-TLV is valid both for Hello and IHU TLVs, though the exact
  234. * semantic of the sub-TLV is different in each case.
  235. */
  236. static void
  237. subtlvs_print(netdissect_options *ndo,
  238. const u_char *cp, const u_char *ep, const uint8_t tlv_type)
  239. {
  240. uint8_t subtype, sublen;
  241. const char *sep;
  242. uint32_t t1, t2;
  243. while (cp < ep) {
  244. subtype = *cp++;
  245. if(subtype == MESSAGE_SUB_PAD1) {
  246. ND_PRINT((ndo, " sub-pad1"));
  247. continue;
  248. }
  249. if(cp == ep)
  250. goto invalid;
  251. sublen = *cp++;
  252. if(cp + sublen > ep)
  253. goto invalid;
  254. switch(subtype) {
  255. case MESSAGE_SUB_PADN:
  256. ND_PRINT((ndo, " sub-padn"));
  257. cp += sublen;
  258. break;
  259. case MESSAGE_SUB_DIVERSITY:
  260. ND_PRINT((ndo, " sub-diversity"));
  261. if (sublen == 0) {
  262. ND_PRINT((ndo, " empty"));
  263. break;
  264. }
  265. sep = " ";
  266. while(sublen--) {
  267. ND_PRINT((ndo, "%s%s", sep, tok2str(diversity_str, "%u", *cp++)));
  268. sep = "-";
  269. }
  270. if(tlv_type != MESSAGE_UPDATE &&
  271. tlv_type != MESSAGE_UPDATE_SRC_SPECIFIC)
  272. ND_PRINT((ndo, " (bogus)"));
  273. break;
  274. case MESSAGE_SUB_TIMESTAMP:
  275. ND_PRINT((ndo, " sub-timestamp"));
  276. if(tlv_type == MESSAGE_HELLO) {
  277. if(sublen < 4)
  278. goto invalid;
  279. t1 = EXTRACT_32BITS(cp);
  280. ND_PRINT((ndo, " %s", format_timestamp(t1)));
  281. } else if(tlv_type == MESSAGE_IHU) {
  282. if(sublen < 8)
  283. goto invalid;
  284. t1 = EXTRACT_32BITS(cp);
  285. ND_PRINT((ndo, " %s", format_timestamp(t1)));
  286. t2 = EXTRACT_32BITS(cp + 4);
  287. ND_PRINT((ndo, "|%s", format_timestamp(t2)));
  288. } else
  289. ND_PRINT((ndo, " (bogus)"));
  290. cp += sublen;
  291. break;
  292. default:
  293. ND_PRINT((ndo, " sub-unknown-0x%02x", subtype));
  294. cp += sublen;
  295. } /* switch */
  296. } /* while */
  297. return;
  298. invalid:
  299. ND_PRINT((ndo, "%s", istr));
  300. }
  301. #define ICHECK(i, l) \
  302. if ((i) + (l) > bodylen || (i) + (l) > length) goto invalid;
  303. static void
  304. babel_print_v2(netdissect_options *ndo,
  305. const u_char *cp, u_int length)
  306. {
  307. u_int i;
  308. u_short bodylen;
  309. u_char v4_prefix[16] =
  310. {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 };
  311. u_char v6_prefix[16] = {0};
  312. ND_TCHECK2(*cp, 4);
  313. if (length < 4)
  314. goto invalid;
  315. bodylen = EXTRACT_16BITS(cp + 2);
  316. ND_PRINT((ndo, " (%u)", bodylen));
  317. /* Process the TLVs in the body */
  318. i = 0;
  319. while(i < bodylen) {
  320. const u_char *message;
  321. u_int type, len;
  322. message = cp + 4 + i;
  323. ND_TCHECK2(*message, 1);
  324. if((type = message[0]) == MESSAGE_PAD1) {
  325. ND_PRINT((ndo, ndo->ndo_vflag ? "\n\tPad 1" : " pad1"));
  326. i += 1;
  327. continue;
  328. }
  329. ND_TCHECK2(*message, 2);
  330. ICHECK(i, 2);
  331. len = message[1];
  332. ND_TCHECK2(*message, 2 + len);
  333. ICHECK(i, 2 + len);
  334. switch(type) {
  335. case MESSAGE_PADN: {
  336. if (!ndo->ndo_vflag)
  337. ND_PRINT((ndo, " padN"));
  338. else
  339. ND_PRINT((ndo, "\n\tPad %d", len + 2));
  340. }
  341. break;
  342. case MESSAGE_ACK_REQ: {
  343. u_short nonce, interval;
  344. if (!ndo->ndo_vflag)
  345. ND_PRINT((ndo, " ack-req"));
  346. else {
  347. ND_PRINT((ndo, "\n\tAcknowledgment Request "));
  348. if(len < 6) goto invalid;
  349. nonce = EXTRACT_16BITS(message + 4);
  350. interval = EXTRACT_16BITS(message + 6);
  351. ND_PRINT((ndo, "%04x %s", nonce, format_interval(interval)));
  352. }
  353. }
  354. break;
  355. case MESSAGE_ACK: {
  356. u_short nonce;
  357. if (!ndo->ndo_vflag)
  358. ND_PRINT((ndo, " ack"));
  359. else {
  360. ND_PRINT((ndo, "\n\tAcknowledgment "));
  361. if(len < 2) goto invalid;
  362. nonce = EXTRACT_16BITS(message + 2);
  363. ND_PRINT((ndo, "%04x", nonce));
  364. }
  365. }
  366. break;
  367. case MESSAGE_HELLO: {
  368. u_short seqno, interval;
  369. if (!ndo->ndo_vflag)
  370. ND_PRINT((ndo, " hello"));
  371. else {
  372. ND_PRINT((ndo, "\n\tHello "));
  373. if(len < 6) goto invalid;
  374. seqno = EXTRACT_16BITS(message + 4);
  375. interval = EXTRACT_16BITS(message + 6);
  376. ND_PRINT((ndo, "seqno %u interval %s", seqno, format_interval(interval)));
  377. /* Extra data. */
  378. if(len > 6)
  379. subtlvs_print(ndo, message + 8, message + 2 + len, type);
  380. }
  381. }
  382. break;
  383. case MESSAGE_IHU: {
  384. unsigned short txcost, interval;
  385. if (!ndo->ndo_vflag)
  386. ND_PRINT((ndo, " ihu"));
  387. else {
  388. u_char address[16];
  389. int rc;
  390. ND_PRINT((ndo, "\n\tIHU "));
  391. if(len < 6) goto invalid;
  392. txcost = EXTRACT_16BITS(message + 4);
  393. interval = EXTRACT_16BITS(message + 6);
  394. rc = network_address(message[2], message + 8, len - 6, address);
  395. if(rc < 0) { ND_PRINT((ndo, "%s", tstr)); break; }
  396. ND_PRINT((ndo, "%s txcost %u interval %s",
  397. format_address(ndo, address), txcost, format_interval(interval)));
  398. /* Extra data. */
  399. if((u_int)rc < len - 6)
  400. subtlvs_print(ndo, message + 8 + rc, message + 2 + len,
  401. type);
  402. }
  403. }
  404. break;
  405. case MESSAGE_ROUTER_ID: {
  406. if (!ndo->ndo_vflag)
  407. ND_PRINT((ndo, " router-id"));
  408. else {
  409. ND_PRINT((ndo, "\n\tRouter Id"));
  410. if(len < 10) goto invalid;
  411. ND_PRINT((ndo, " %s", format_id(message + 4)));
  412. }
  413. }
  414. break;
  415. case MESSAGE_NH: {
  416. if (!ndo->ndo_vflag)
  417. ND_PRINT((ndo, " nh"));
  418. else {
  419. int rc;
  420. u_char nh[16];
  421. ND_PRINT((ndo, "\n\tNext Hop"));
  422. if(len < 2) goto invalid;
  423. rc = network_address(message[2], message + 4, len - 2, nh);
  424. if(rc < 0) goto invalid;
  425. ND_PRINT((ndo, " %s", format_address(ndo, nh)));
  426. }
  427. }
  428. break;
  429. case MESSAGE_UPDATE: {
  430. if (!ndo->ndo_vflag) {
  431. ND_PRINT((ndo, " update"));
  432. if(len < 1)
  433. ND_PRINT((ndo, "/truncated"));
  434. else
  435. ND_PRINT((ndo, "%s%s%s",
  436. (message[3] & 0x80) ? "/prefix": "",
  437. (message[3] & 0x40) ? "/id" : "",
  438. (message[3] & 0x3f) ? "/unknown" : ""));
  439. } else {
  440. u_short interval, seqno, metric;
  441. u_char plen;
  442. int rc;
  443. u_char prefix[16];
  444. ND_PRINT((ndo, "\n\tUpdate"));
  445. if(len < 10) goto invalid;
  446. plen = message[4] + (message[2] == 1 ? 96 : 0);
  447. rc = network_prefix(message[2], message[4], message[5],
  448. message + 12,
  449. message[2] == 1 ? v4_prefix : v6_prefix,
  450. len - 10, prefix);
  451. if(rc < 0) goto invalid;
  452. interval = EXTRACT_16BITS(message + 6);
  453. seqno = EXTRACT_16BITS(message + 8);
  454. metric = EXTRACT_16BITS(message + 10);
  455. ND_PRINT((ndo, "%s%s%s %s metric %u seqno %u interval %s",
  456. (message[3] & 0x80) ? "/prefix": "",
  457. (message[3] & 0x40) ? "/id" : "",
  458. (message[3] & 0x3f) ? "/unknown" : "",
  459. format_prefix(ndo, prefix, plen),
  460. metric, seqno, format_interval_update(interval)));
  461. if(message[3] & 0x80) {
  462. if(message[2] == 1)
  463. memcpy(v4_prefix, prefix, 16);
  464. else
  465. memcpy(v6_prefix, prefix, 16);
  466. }
  467. /* extra data? */
  468. if((u_int)rc < len - 10)
  469. subtlvs_print(ndo, message + 12 + rc, message + 2 + len, type);
  470. }
  471. }
  472. break;
  473. case MESSAGE_REQUEST: {
  474. if (!ndo->ndo_vflag)
  475. ND_PRINT((ndo, " request"));
  476. else {
  477. int rc;
  478. u_char prefix[16], plen;
  479. ND_PRINT((ndo, "\n\tRequest "));
  480. if(len < 2) goto invalid;
  481. plen = message[3] + (message[2] == 1 ? 96 : 0);
  482. rc = network_prefix(message[2], message[3], 0,
  483. message + 4, NULL, len - 2, prefix);
  484. if(rc < 0) goto invalid;
  485. ND_PRINT((ndo, "for %s",
  486. message[2] == 0 ? "any" : format_prefix(ndo, prefix, plen)));
  487. }
  488. }
  489. break;
  490. case MESSAGE_MH_REQUEST : {
  491. if (!ndo->ndo_vflag)
  492. ND_PRINT((ndo, " mh-request"));
  493. else {
  494. int rc;
  495. u_short seqno;
  496. u_char prefix[16], plen;
  497. ND_PRINT((ndo, "\n\tMH-Request "));
  498. if(len < 14) goto invalid;
  499. seqno = EXTRACT_16BITS(message + 4);
  500. rc = network_prefix(message[2], message[3], 0,
  501. message + 16, NULL, len - 14, prefix);
  502. if(rc < 0) goto invalid;
  503. plen = message[3] + (message[2] == 1 ? 96 : 0);
  504. ND_PRINT((ndo, "(%u hops) for %s seqno %u id %s",
  505. message[6], format_prefix(ndo, prefix, plen),
  506. seqno, format_id(message + 8)));
  507. }
  508. }
  509. break;
  510. case MESSAGE_TSPC :
  511. if (!ndo->ndo_vflag)
  512. ND_PRINT((ndo, " tspc"));
  513. else {
  514. ND_PRINT((ndo, "\n\tTS/PC "));
  515. if(len < 6) goto invalid;
  516. ND_PRINT((ndo, "timestamp %u packetcounter %u", EXTRACT_32BITS (message + 4),
  517. EXTRACT_16BITS(message + 2)));
  518. }
  519. break;
  520. case MESSAGE_HMAC : {
  521. if (!ndo->ndo_vflag)
  522. ND_PRINT((ndo, " hmac"));
  523. else {
  524. unsigned j;
  525. ND_PRINT((ndo, "\n\tHMAC "));
  526. if(len < 18) goto invalid;
  527. ND_PRINT((ndo, "key-id %u digest-%u ", EXTRACT_16BITS(message + 2), len - 2));
  528. for (j = 0; j < len - 2; j++)
  529. ND_PRINT((ndo, "%02X", message[4 + j]));
  530. }
  531. }
  532. break;
  533. case MESSAGE_UPDATE_SRC_SPECIFIC : {
  534. if(!ndo->ndo_vflag) {
  535. ND_PRINT((ndo, " ss-update"));
  536. } else {
  537. u_char prefix[16], src_prefix[16];
  538. u_short interval, seqno, metric;
  539. u_char ae, plen, src_plen, omitted;
  540. int rc;
  541. int parsed_len = 10;
  542. ND_PRINT((ndo, "\n\tSS-Update"));
  543. if(len < 10) goto invalid;
  544. ae = message[2];
  545. src_plen = message[3];
  546. plen = message[4];
  547. omitted = message[5];
  548. interval = EXTRACT_16BITS(message + 6);
  549. seqno = EXTRACT_16BITS(message + 8);
  550. metric = EXTRACT_16BITS(message + 10);
  551. rc = network_prefix(ae, plen, omitted, message + 2 + parsed_len,
  552. ae == 1 ? v4_prefix : v6_prefix,
  553. len - parsed_len, prefix);
  554. if(rc < 0) goto invalid;
  555. if(ae == 1)
  556. plen += 96;
  557. parsed_len += rc;
  558. rc = network_prefix(ae, src_plen, 0, message + 2 + parsed_len,
  559. NULL, len - parsed_len, src_prefix);
  560. if(rc < 0) goto invalid;
  561. if(ae == 1)
  562. src_plen += 96;
  563. parsed_len += rc;
  564. ND_PRINT((ndo, " %s from", format_prefix(ndo, prefix, plen)));
  565. ND_PRINT((ndo, " %s metric %u seqno %u interval %s",
  566. format_prefix(ndo, src_prefix, src_plen),
  567. metric, seqno, format_interval_update(interval)));
  568. /* extra data? */
  569. if((u_int)parsed_len < len)
  570. subtlvs_print(ndo, message + 2 + parsed_len,
  571. message + 2 + len, type);
  572. }
  573. }
  574. break;
  575. case MESSAGE_REQUEST_SRC_SPECIFIC : {
  576. if(!ndo->ndo_vflag)
  577. ND_PRINT((ndo, " ss-request"));
  578. else {
  579. int rc, parsed_len = 3;
  580. u_char ae, plen, src_plen, prefix[16], src_prefix[16];
  581. ND_PRINT((ndo, "\n\tSS-Request "));
  582. if(len < 3) goto invalid;
  583. ae = message[2];
  584. plen = message[3];
  585. src_plen = message[4];
  586. rc = network_prefix(ae, plen, 0, message + 2 + parsed_len,
  587. NULL, len - parsed_len, prefix);
  588. if(rc < 0) goto invalid;
  589. if(ae == 1)
  590. plen += 96;
  591. parsed_len += rc;
  592. rc = network_prefix(ae, src_plen, 0, message + 2 + parsed_len,
  593. NULL, len - parsed_len, src_prefix);
  594. if(rc < 0) goto invalid;
  595. if(ae == 1)
  596. src_plen += 96;
  597. parsed_len += rc;
  598. if(ae == 0) {
  599. ND_PRINT((ndo, "for any"));
  600. } else {
  601. ND_PRINT((ndo, "for (%s, ", format_prefix(ndo, prefix, plen)));
  602. ND_PRINT((ndo, "%s)", format_prefix(ndo, src_prefix, src_plen)));
  603. }
  604. }
  605. }
  606. break;
  607. case MESSAGE_MH_REQUEST_SRC_SPECIFIC : {
  608. if(!ndo->ndo_vflag)
  609. ND_PRINT((ndo, " ss-mh-request"));
  610. else {
  611. int rc, parsed_len = 14;
  612. u_short seqno;
  613. u_char ae, plen, src_plen, prefix[16], src_prefix[16], hopc;
  614. const u_char *router_id = NULL;
  615. ND_PRINT((ndo, "\n\tSS-MH-Request "));
  616. if(len < 14) goto invalid;
  617. ae = message[2];
  618. plen = message[3];
  619. seqno = EXTRACT_16BITS(message + 4);
  620. hopc = message[6];
  621. src_plen = message[7];
  622. router_id = message + 8;
  623. rc = network_prefix(ae, plen, 0, message + 2 + parsed_len,
  624. NULL, len - parsed_len, prefix);
  625. if(rc < 0) goto invalid;
  626. if(ae == 1)
  627. plen += 96;
  628. parsed_len += rc;
  629. rc = network_prefix(ae, src_plen, 0, message + 2 + parsed_len,
  630. NULL, len - parsed_len, src_prefix);
  631. if(rc < 0) goto invalid;
  632. if(ae == 1)
  633. src_plen += 96;
  634. ND_PRINT((ndo, "(%u hops) for (%s, ",
  635. hopc, format_prefix(ndo, prefix, plen)));
  636. ND_PRINT((ndo, "%s) seqno %u id %s",
  637. format_prefix(ndo, src_prefix, src_plen),
  638. seqno, format_id(router_id)));
  639. }
  640. }
  641. break;
  642. default:
  643. if (!ndo->ndo_vflag)
  644. ND_PRINT((ndo, " unknown"));
  645. else
  646. ND_PRINT((ndo, "\n\tUnknown message type %d", type));
  647. }
  648. i += len + 2;
  649. }
  650. return;
  651. trunc:
  652. ND_PRINT((ndo, " %s", tstr));
  653. return;
  654. invalid:
  655. ND_PRINT((ndo, "%s", istr));
  656. return;
  657. }