print-olsr.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719
  1. /*
  2. * Copyright (c) 1998-2007 The TCPDUMP project
  3. * Copyright (c) 2009 Florian Forster
  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. * Original code by Hannes Gredler <hannes@gredler.at>
  17. * IPv6 additions by Florian Forster <octo at verplant.org>
  18. */
  19. /* \summary: Optimized Link State Routing Protocol (OLSR) printer */
  20. /* specification: RFC 3626 */
  21. #ifdef HAVE_CONFIG_H
  22. #include "config.h"
  23. #endif
  24. #include <netdissect-stdinc.h>
  25. #include "netdissect.h"
  26. #include "addrtoname.h"
  27. #include "extract.h"
  28. /*
  29. * RFC 3626 common header
  30. *
  31. * 0 1 2 3
  32. * 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
  33. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  34. * | Packet Length | Packet Sequence Number |
  35. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  36. * | Message Type | Vtime | Message Size |
  37. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  38. * | Originator Address |
  39. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  40. * | Time To Live | Hop Count | Message Sequence Number |
  41. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  42. * | |
  43. * : MESSAGE :
  44. * | |
  45. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  46. * | Message Type | Vtime | Message Size |
  47. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  48. * | Originator Address |
  49. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  50. * | Time To Live | Hop Count | Message Sequence Number |
  51. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  52. * | |
  53. * : MESSAGE :
  54. * | |
  55. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  56. * : :
  57. */
  58. struct olsr_common {
  59. uint8_t packet_len[2];
  60. uint8_t packet_seq[2];
  61. };
  62. #define OLSR_HELLO_MSG 1 /* rfc3626 */
  63. #define OLSR_TC_MSG 2 /* rfc3626 */
  64. #define OLSR_MID_MSG 3 /* rfc3626 */
  65. #define OLSR_HNA_MSG 4 /* rfc3626 */
  66. #define OLSR_POWERINFO_MSG 128
  67. #define OLSR_NAMESERVICE_MSG 130
  68. #define OLSR_HELLO_LQ_MSG 201 /* LQ extensions olsr.org */
  69. #define OLSR_TC_LQ_MSG 202 /* LQ extensions olsr.org */
  70. static const struct tok olsr_msg_values[] = {
  71. { OLSR_HELLO_MSG, "Hello" },
  72. { OLSR_TC_MSG, "TC" },
  73. { OLSR_MID_MSG, "MID" },
  74. { OLSR_HNA_MSG, "HNA" },
  75. { OLSR_POWERINFO_MSG, "Powerinfo" },
  76. { OLSR_NAMESERVICE_MSG, "Nameservice" },
  77. { OLSR_HELLO_LQ_MSG, "Hello-LQ" },
  78. { OLSR_TC_LQ_MSG, "TC-LQ" },
  79. { 0, NULL}
  80. };
  81. struct olsr_msg4 {
  82. uint8_t msg_type;
  83. uint8_t vtime;
  84. uint8_t msg_len[2];
  85. uint8_t originator[4];
  86. uint8_t ttl;
  87. uint8_t hopcount;
  88. uint8_t msg_seq[2];
  89. };
  90. struct olsr_msg6 {
  91. uint8_t msg_type;
  92. uint8_t vtime;
  93. uint8_t msg_len[2];
  94. uint8_t originator[16];
  95. uint8_t ttl;
  96. uint8_t hopcount;
  97. uint8_t msg_seq[2];
  98. };
  99. struct olsr_hello {
  100. uint8_t res[2];
  101. uint8_t htime;
  102. uint8_t will;
  103. };
  104. struct olsr_hello_link {
  105. uint8_t link_code;
  106. uint8_t res;
  107. uint8_t len[2];
  108. };
  109. struct olsr_tc {
  110. uint8_t ans_seq[2];
  111. uint8_t res[2];
  112. };
  113. struct olsr_hna4 {
  114. uint8_t network[4];
  115. uint8_t mask[4];
  116. };
  117. struct olsr_hna6 {
  118. uint8_t network[16];
  119. uint8_t mask[16];
  120. };
  121. /** gateway HNA flags */
  122. enum gateway_hna_flags {
  123. GW_HNA_FLAG_LINKSPEED = 1 << 0,
  124. GW_HNA_FLAG_IPV4 = 1 << 1,
  125. GW_HNA_FLAG_IPV4_NAT = 1 << 2,
  126. GW_HNA_FLAG_IPV6 = 1 << 3,
  127. GW_HNA_FLAG_IPV6PREFIX = 1 << 4
  128. };
  129. /** gateway HNA field byte offsets in the netmask field of the HNA */
  130. enum gateway_hna_fields {
  131. GW_HNA_PAD = 0,
  132. GW_HNA_FLAGS = 1,
  133. GW_HNA_UPLINK = 2,
  134. GW_HNA_DOWNLINK = 3,
  135. GW_HNA_V6PREFIXLEN = 4,
  136. GW_HNA_V6PREFIX = 5
  137. };
  138. #define OLSR_EXTRACT_LINK_TYPE(link_code) (link_code & 0x3)
  139. #define OLSR_EXTRACT_NEIGHBOR_TYPE(link_code) (link_code >> 2)
  140. static const struct tok olsr_link_type_values[] = {
  141. { 0, "Unspecified" },
  142. { 1, "Asymmetric" },
  143. { 2, "Symmetric" },
  144. { 3, "Lost" },
  145. { 0, NULL}
  146. };
  147. static const struct tok olsr_neighbor_type_values[] = {
  148. { 0, "Not-Neighbor" },
  149. { 1, "Symmetric" },
  150. { 2, "Symmetric-MPR" },
  151. { 0, NULL}
  152. };
  153. struct olsr_lq_neighbor4 {
  154. uint8_t neighbor[4];
  155. uint8_t link_quality;
  156. uint8_t neighbor_link_quality;
  157. uint8_t res[2];
  158. };
  159. struct olsr_lq_neighbor6 {
  160. uint8_t neighbor[16];
  161. uint8_t link_quality;
  162. uint8_t neighbor_link_quality;
  163. uint8_t res[2];
  164. };
  165. #define MAX_SMARTGW_SPEED 320000000
  166. /**
  167. * Convert an encoded 1 byte transport value (5 bits mantissa, 3 bits exponent)
  168. * to an uplink/downlink speed value
  169. *
  170. * @param value the encoded 1 byte transport value
  171. * @return the uplink/downlink speed value (in kbit/s)
  172. */
  173. static uint32_t deserialize_gw_speed(uint8_t value) {
  174. uint32_t speed;
  175. uint32_t exp;
  176. if (!value) {
  177. return 0;
  178. }
  179. if (value == UINT8_MAX) {
  180. /* maximum value: also return maximum value */
  181. return MAX_SMARTGW_SPEED;
  182. }
  183. speed = (value >> 3) + 1;
  184. exp = value & 7;
  185. while (exp-- > 0) {
  186. speed *= 10;
  187. }
  188. return speed;
  189. }
  190. /*
  191. * macro to convert the 8-bit mantissa/exponent to a double float
  192. * taken from olsr.org.
  193. */
  194. #define VTIME_SCALE_FACTOR 0.0625
  195. #define ME_TO_DOUBLE(me) \
  196. (double)(VTIME_SCALE_FACTOR*(1+(double)(me>>4)/16)*(double)(1<<(me&0x0F)))
  197. /*
  198. * print a neighbor list with LQ extensions.
  199. */
  200. static int
  201. olsr_print_lq_neighbor4(netdissect_options *ndo,
  202. const u_char *msg_data, u_int hello_len)
  203. {
  204. const struct olsr_lq_neighbor4 *lq_neighbor;
  205. while (hello_len >= sizeof(struct olsr_lq_neighbor4)) {
  206. lq_neighbor = (const struct olsr_lq_neighbor4 *)msg_data;
  207. if (!ND_TTEST(*lq_neighbor))
  208. return (-1);
  209. ND_PRINT((ndo, "\n\t neighbor %s, link-quality %.2f%%"
  210. ", neighbor-link-quality %.2f%%",
  211. ipaddr_string(ndo, lq_neighbor->neighbor),
  212. ((double)lq_neighbor->link_quality/2.55),
  213. ((double)lq_neighbor->neighbor_link_quality/2.55)));
  214. msg_data += sizeof(struct olsr_lq_neighbor4);
  215. hello_len -= sizeof(struct olsr_lq_neighbor4);
  216. }
  217. return (0);
  218. }
  219. static int
  220. olsr_print_lq_neighbor6(netdissect_options *ndo,
  221. const u_char *msg_data, u_int hello_len)
  222. {
  223. const struct olsr_lq_neighbor6 *lq_neighbor;
  224. while (hello_len >= sizeof(struct olsr_lq_neighbor6)) {
  225. lq_neighbor = (const struct olsr_lq_neighbor6 *)msg_data;
  226. if (!ND_TTEST(*lq_neighbor))
  227. return (-1);
  228. ND_PRINT((ndo, "\n\t neighbor %s, link-quality %.2f%%"
  229. ", neighbor-link-quality %.2f%%",
  230. ip6addr_string(ndo, lq_neighbor->neighbor),
  231. ((double)lq_neighbor->link_quality/2.55),
  232. ((double)lq_neighbor->neighbor_link_quality/2.55)));
  233. msg_data += sizeof(struct olsr_lq_neighbor6);
  234. hello_len -= sizeof(struct olsr_lq_neighbor6);
  235. }
  236. return (0);
  237. }
  238. /*
  239. * print a neighbor list.
  240. */
  241. static int
  242. olsr_print_neighbor(netdissect_options *ndo,
  243. const u_char *msg_data, u_int hello_len)
  244. {
  245. int neighbor;
  246. ND_PRINT((ndo, "\n\t neighbor\n\t\t"));
  247. neighbor = 1;
  248. while (hello_len >= sizeof(struct in_addr)) {
  249. if (!ND_TTEST2(*msg_data, sizeof(struct in_addr)))
  250. return (-1);
  251. /* print 4 neighbors per line */
  252. ND_PRINT((ndo, "%s%s", ipaddr_string(ndo, msg_data),
  253. neighbor % 4 == 0 ? "\n\t\t" : " "));
  254. msg_data += sizeof(struct in_addr);
  255. hello_len -= sizeof(struct in_addr);
  256. }
  257. return (0);
  258. }
  259. void
  260. olsr_print(netdissect_options *ndo,
  261. const u_char *pptr, u_int length, int is_ipv6)
  262. {
  263. union {
  264. const struct olsr_common *common;
  265. const struct olsr_msg4 *msg4;
  266. const struct olsr_msg6 *msg6;
  267. const struct olsr_hello *hello;
  268. const struct olsr_hello_link *hello_link;
  269. const struct olsr_tc *tc;
  270. const struct olsr_hna4 *hna;
  271. } ptr;
  272. u_int msg_type, msg_len, msg_tlen, hello_len;
  273. uint16_t name_entry_type, name_entry_len;
  274. u_int name_entry_padding;
  275. uint8_t link_type, neighbor_type;
  276. const u_char *tptr, *msg_data;
  277. tptr = pptr;
  278. if (length < sizeof(struct olsr_common)) {
  279. goto trunc;
  280. }
  281. ND_TCHECK2(*tptr, sizeof(struct olsr_common));
  282. ptr.common = (const struct olsr_common *)tptr;
  283. length = min(length, EXTRACT_16BITS(ptr.common->packet_len));
  284. ND_PRINT((ndo, "OLSRv%i, seq 0x%04x, length %u",
  285. (is_ipv6 == 0) ? 4 : 6,
  286. EXTRACT_16BITS(ptr.common->packet_seq),
  287. length));
  288. tptr += sizeof(struct olsr_common);
  289. /*
  290. * In non-verbose mode, just print version.
  291. */
  292. if (ndo->ndo_vflag < 1) {
  293. return;
  294. }
  295. while (tptr < (pptr+length)) {
  296. union
  297. {
  298. const struct olsr_msg4 *v4;
  299. const struct olsr_msg6 *v6;
  300. } msgptr;
  301. int msg_len_valid = 0;
  302. if (is_ipv6)
  303. {
  304. ND_TCHECK2(*tptr, sizeof(struct olsr_msg6));
  305. msgptr.v6 = (const struct olsr_msg6 *) tptr;
  306. msg_type = msgptr.v6->msg_type;
  307. msg_len = EXTRACT_16BITS(msgptr.v6->msg_len);
  308. if ((msg_len >= sizeof (struct olsr_msg6))
  309. && (msg_len <= length))
  310. msg_len_valid = 1;
  311. /* infinite loop check */
  312. if (msg_type == 0 || msg_len == 0) {
  313. return;
  314. }
  315. ND_PRINT((ndo, "\n\t%s Message (%#04x), originator %s, ttl %u, hop %u"
  316. "\n\t vtime %.3fs, msg-seq 0x%04x, length %u%s",
  317. tok2str(olsr_msg_values, "Unknown", msg_type),
  318. msg_type, ip6addr_string(ndo, msgptr.v6->originator),
  319. msgptr.v6->ttl,
  320. msgptr.v6->hopcount,
  321. ME_TO_DOUBLE(msgptr.v6->vtime),
  322. EXTRACT_16BITS(msgptr.v6->msg_seq),
  323. msg_len, (msg_len_valid == 0) ? " (invalid)" : ""));
  324. if (!msg_len_valid) {
  325. return;
  326. }
  327. msg_tlen = msg_len - sizeof(struct olsr_msg6);
  328. msg_data = tptr + sizeof(struct olsr_msg6);
  329. }
  330. else /* (!is_ipv6) */
  331. {
  332. ND_TCHECK2(*tptr, sizeof(struct olsr_msg4));
  333. msgptr.v4 = (const struct olsr_msg4 *) tptr;
  334. msg_type = msgptr.v4->msg_type;
  335. msg_len = EXTRACT_16BITS(msgptr.v4->msg_len);
  336. if ((msg_len >= sizeof (struct olsr_msg4))
  337. && (msg_len <= length))
  338. msg_len_valid = 1;
  339. /* infinite loop check */
  340. if (msg_type == 0 || msg_len == 0) {
  341. return;
  342. }
  343. ND_PRINT((ndo, "\n\t%s Message (%#04x), originator %s, ttl %u, hop %u"
  344. "\n\t vtime %.3fs, msg-seq 0x%04x, length %u%s",
  345. tok2str(olsr_msg_values, "Unknown", msg_type),
  346. msg_type, ipaddr_string(ndo, msgptr.v4->originator),
  347. msgptr.v4->ttl,
  348. msgptr.v4->hopcount,
  349. ME_TO_DOUBLE(msgptr.v4->vtime),
  350. EXTRACT_16BITS(msgptr.v4->msg_seq),
  351. msg_len, (msg_len_valid == 0) ? " (invalid)" : ""));
  352. if (!msg_len_valid) {
  353. return;
  354. }
  355. msg_tlen = msg_len - sizeof(struct olsr_msg4);
  356. msg_data = tptr + sizeof(struct olsr_msg4);
  357. }
  358. switch (msg_type) {
  359. case OLSR_HELLO_MSG:
  360. case OLSR_HELLO_LQ_MSG:
  361. if (msg_tlen < sizeof(struct olsr_hello))
  362. goto trunc;
  363. ND_TCHECK2(*msg_data, sizeof(struct olsr_hello));
  364. ptr.hello = (const struct olsr_hello *)msg_data;
  365. ND_PRINT((ndo, "\n\t hello-time %.3fs, MPR willingness %u",
  366. ME_TO_DOUBLE(ptr.hello->htime), ptr.hello->will));
  367. msg_data += sizeof(struct olsr_hello);
  368. msg_tlen -= sizeof(struct olsr_hello);
  369. while (msg_tlen >= sizeof(struct olsr_hello_link)) {
  370. int hello_len_valid = 0;
  371. /*
  372. * link-type.
  373. */
  374. ND_TCHECK2(*msg_data, sizeof(struct olsr_hello_link));
  375. ptr.hello_link = (const struct olsr_hello_link *)msg_data;
  376. hello_len = EXTRACT_16BITS(ptr.hello_link->len);
  377. link_type = OLSR_EXTRACT_LINK_TYPE(ptr.hello_link->link_code);
  378. neighbor_type = OLSR_EXTRACT_NEIGHBOR_TYPE(ptr.hello_link->link_code);
  379. if ((hello_len <= msg_tlen)
  380. && (hello_len >= sizeof(struct olsr_hello_link)))
  381. hello_len_valid = 1;
  382. ND_PRINT((ndo, "\n\t link-type %s, neighbor-type %s, len %u%s",
  383. tok2str(olsr_link_type_values, "Unknown", link_type),
  384. tok2str(olsr_neighbor_type_values, "Unknown", neighbor_type),
  385. hello_len,
  386. (hello_len_valid == 0) ? " (invalid)" : ""));
  387. if (hello_len_valid == 0)
  388. break;
  389. msg_data += sizeof(struct olsr_hello_link);
  390. msg_tlen -= sizeof(struct olsr_hello_link);
  391. hello_len -= sizeof(struct olsr_hello_link);
  392. ND_TCHECK2(*msg_data, hello_len);
  393. if (msg_type == OLSR_HELLO_MSG) {
  394. if (olsr_print_neighbor(ndo, msg_data, hello_len) == -1)
  395. goto trunc;
  396. } else {
  397. if (is_ipv6) {
  398. if (olsr_print_lq_neighbor6(ndo, msg_data, hello_len) == -1)
  399. goto trunc;
  400. } else {
  401. if (olsr_print_lq_neighbor4(ndo, msg_data, hello_len) == -1)
  402. goto trunc;
  403. }
  404. }
  405. msg_data += hello_len;
  406. msg_tlen -= hello_len;
  407. }
  408. break;
  409. case OLSR_TC_MSG:
  410. case OLSR_TC_LQ_MSG:
  411. if (msg_tlen < sizeof(struct olsr_tc))
  412. goto trunc;
  413. ND_TCHECK2(*msg_data, sizeof(struct olsr_tc));
  414. ptr.tc = (const struct olsr_tc *)msg_data;
  415. ND_PRINT((ndo, "\n\t advertised neighbor seq 0x%04x",
  416. EXTRACT_16BITS(ptr.tc->ans_seq)));
  417. msg_data += sizeof(struct olsr_tc);
  418. msg_tlen -= sizeof(struct olsr_tc);
  419. if (msg_type == OLSR_TC_MSG) {
  420. if (olsr_print_neighbor(ndo, msg_data, msg_tlen) == -1)
  421. goto trunc;
  422. } else {
  423. if (is_ipv6) {
  424. if (olsr_print_lq_neighbor6(ndo, msg_data, msg_tlen) == -1)
  425. goto trunc;
  426. } else {
  427. if (olsr_print_lq_neighbor4(ndo, msg_data, msg_tlen) == -1)
  428. goto trunc;
  429. }
  430. }
  431. break;
  432. case OLSR_MID_MSG:
  433. {
  434. size_t addr_size = sizeof(struct in_addr);
  435. if (is_ipv6)
  436. addr_size = sizeof(struct in6_addr);
  437. while (msg_tlen >= addr_size) {
  438. ND_TCHECK2(*msg_data, addr_size);
  439. ND_PRINT((ndo, "\n\t interface address %s",
  440. is_ipv6 ? ip6addr_string(ndo, msg_data) :
  441. ipaddr_string(ndo, msg_data)));
  442. msg_data += addr_size;
  443. msg_tlen -= addr_size;
  444. }
  445. break;
  446. }
  447. case OLSR_HNA_MSG:
  448. if (is_ipv6)
  449. {
  450. int i = 0;
  451. ND_PRINT((ndo, "\n\t Advertised networks (total %u)",
  452. (unsigned int) (msg_tlen / sizeof(struct olsr_hna6))));
  453. while (msg_tlen >= sizeof(struct olsr_hna6)) {
  454. const struct olsr_hna6 *hna6;
  455. ND_TCHECK2(*msg_data, sizeof(struct olsr_hna6));
  456. hna6 = (const struct olsr_hna6 *)msg_data;
  457. ND_PRINT((ndo, "\n\t #%i: %s/%u",
  458. i, ip6addr_string(ndo, hna6->network),
  459. mask62plen (hna6->mask)));
  460. msg_data += sizeof(struct olsr_hna6);
  461. msg_tlen -= sizeof(struct olsr_hna6);
  462. }
  463. }
  464. else
  465. {
  466. int col = 0;
  467. ND_PRINT((ndo, "\n\t Advertised networks (total %u)",
  468. (unsigned int) (msg_tlen / sizeof(struct olsr_hna4))));
  469. while (msg_tlen >= sizeof(struct olsr_hna4)) {
  470. ND_TCHECK2(*msg_data, sizeof(struct olsr_hna4));
  471. ptr.hna = (const struct olsr_hna4 *)msg_data;
  472. /* print 4 prefixes per line */
  473. if (!ptr.hna->network[0] && !ptr.hna->network[1] &&
  474. !ptr.hna->network[2] && !ptr.hna->network[3] &&
  475. !ptr.hna->mask[GW_HNA_PAD] &&
  476. ptr.hna->mask[GW_HNA_FLAGS]) {
  477. /* smart gateway */
  478. ND_PRINT((ndo, "%sSmart-Gateway:%s%s%s%s%s %u/%u",
  479. col == 0 ? "\n\t " : ", ", /* indent */
  480. /* sgw */
  481. /* LINKSPEED */
  482. (ptr.hna->mask[GW_HNA_FLAGS] &
  483. GW_HNA_FLAG_LINKSPEED) ? " LINKSPEED" : "",
  484. /* IPV4 */
  485. (ptr.hna->mask[GW_HNA_FLAGS] &
  486. GW_HNA_FLAG_IPV4) ? " IPV4" : "",
  487. /* IPV4-NAT */
  488. (ptr.hna->mask[GW_HNA_FLAGS] &
  489. GW_HNA_FLAG_IPV4_NAT) ? " IPV4-NAT" : "",
  490. /* IPV6 */
  491. (ptr.hna->mask[GW_HNA_FLAGS] &
  492. GW_HNA_FLAG_IPV6) ? " IPV6" : "",
  493. /* IPv6PREFIX */
  494. (ptr.hna->mask[GW_HNA_FLAGS] &
  495. GW_HNA_FLAG_IPV6PREFIX) ? " IPv6-PREFIX" : "",
  496. /* uplink */
  497. (ptr.hna->mask[GW_HNA_FLAGS] &
  498. GW_HNA_FLAG_LINKSPEED) ?
  499. deserialize_gw_speed(ptr.hna->mask[GW_HNA_UPLINK]) : 0,
  500. /* downlink */
  501. (ptr.hna->mask[GW_HNA_FLAGS] &
  502. GW_HNA_FLAG_LINKSPEED) ?
  503. deserialize_gw_speed(ptr.hna->mask[GW_HNA_DOWNLINK]) : 0
  504. ));
  505. } else {
  506. /* normal route */
  507. ND_PRINT((ndo, "%s%s/%u",
  508. col == 0 ? "\n\t " : ", ",
  509. ipaddr_string(ndo, ptr.hna->network),
  510. mask2plen(EXTRACT_32BITS(ptr.hna->mask))));
  511. }
  512. msg_data += sizeof(struct olsr_hna4);
  513. msg_tlen -= sizeof(struct olsr_hna4);
  514. col = (col + 1) % 4;
  515. }
  516. }
  517. break;
  518. case OLSR_NAMESERVICE_MSG:
  519. {
  520. u_int name_entries;
  521. u_int addr_size;
  522. int name_entries_valid;
  523. u_int i;
  524. if (msg_tlen < 4)
  525. goto trunc;
  526. ND_TCHECK2(*msg_data, 4);
  527. name_entries = EXTRACT_16BITS(msg_data+2);
  528. addr_size = 4;
  529. if (is_ipv6)
  530. addr_size = 16;
  531. name_entries_valid = 0;
  532. if ((name_entries > 0)
  533. && ((name_entries * (4 + addr_size)) <= msg_tlen))
  534. name_entries_valid = 1;
  535. ND_PRINT((ndo, "\n\t Version %u, Entries %u%s",
  536. EXTRACT_16BITS(msg_data),
  537. name_entries, (name_entries_valid == 0) ? " (invalid)" : ""));
  538. if (name_entries_valid == 0)
  539. break;
  540. msg_data += 4;
  541. msg_tlen -= 4;
  542. for (i = 0; i < name_entries; i++) {
  543. int name_entry_len_valid = 0;
  544. if (msg_tlen < 4)
  545. break;
  546. ND_TCHECK2(*msg_data, 4);
  547. name_entry_type = EXTRACT_16BITS(msg_data);
  548. name_entry_len = EXTRACT_16BITS(msg_data+2);
  549. msg_data += 4;
  550. msg_tlen -= 4;
  551. if ((name_entry_len > 0) && ((addr_size + name_entry_len) <= msg_tlen))
  552. name_entry_len_valid = 1;
  553. ND_PRINT((ndo, "\n\t #%u: type %#06x, length %u%s",
  554. (unsigned int) i, name_entry_type,
  555. name_entry_len, (name_entry_len_valid == 0) ? " (invalid)" : ""));
  556. if (name_entry_len_valid == 0)
  557. break;
  558. /* 32-bit alignment */
  559. name_entry_padding = 0;
  560. if (name_entry_len%4 != 0)
  561. name_entry_padding = 4-(name_entry_len%4);
  562. if (msg_tlen < addr_size + name_entry_len + name_entry_padding)
  563. goto trunc;
  564. ND_TCHECK2(*msg_data, addr_size + name_entry_len + name_entry_padding);
  565. if (is_ipv6)
  566. ND_PRINT((ndo, ", address %s, name \"",
  567. ip6addr_string(ndo, msg_data)));
  568. else
  569. ND_PRINT((ndo, ", address %s, name \"",
  570. ipaddr_string(ndo, msg_data)));
  571. (void)fn_printn(ndo, msg_data + addr_size, name_entry_len, NULL);
  572. ND_PRINT((ndo, "\""));
  573. msg_data += addr_size + name_entry_len + name_entry_padding;
  574. msg_tlen -= addr_size + name_entry_len + name_entry_padding;
  575. } /* for (i = 0; i < name_entries; i++) */
  576. break;
  577. } /* case OLSR_NAMESERVICE_MSG */
  578. /*
  579. * FIXME those are the defined messages that lack a decoder
  580. * you are welcome to contribute code ;-)
  581. */
  582. case OLSR_POWERINFO_MSG:
  583. default:
  584. print_unknown_data(ndo, msg_data, "\n\t ", msg_tlen);
  585. break;
  586. } /* switch (msg_type) */
  587. tptr += msg_len;
  588. } /* while (tptr < (pptr+length)) */
  589. return;
  590. trunc:
  591. ND_PRINT((ndo, "[|olsr]"));
  592. }
  593. /*
  594. * Local Variables:
  595. * c-style: whitesmith
  596. * c-basic-offset: 4
  597. * End:
  598. */