1b5bfcb5dSMax Laier /* 2b5bfcb5dSMax Laier * Copyright (c) 1998-2007 The TCPDUMP project 327df3f5dSRui Paulo * Copyright (c) 2009 Florian Forster 4b5bfcb5dSMax Laier * 5b5bfcb5dSMax Laier * Redistribution and use in source and binary forms, with or without 6b5bfcb5dSMax Laier * modification, are permitted provided that: (1) source code 7b5bfcb5dSMax Laier * distributions retain the above copyright notice and this paragraph 8b5bfcb5dSMax Laier * in its entirety, and (2) distributions including binary code include 9b5bfcb5dSMax Laier * the above copyright notice and this paragraph in its entirety in 10b5bfcb5dSMax Laier * the documentation or other materials provided with the distribution. 11b5bfcb5dSMax Laier * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 12b5bfcb5dSMax Laier * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT 13b5bfcb5dSMax Laier * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 14b5bfcb5dSMax Laier * FOR A PARTICULAR PURPOSE. 15b5bfcb5dSMax Laier * 16b5bfcb5dSMax Laier * Optimized Link State Protocl (OLSR) as per rfc3626 17b5bfcb5dSMax Laier * 18b5bfcb5dSMax Laier * Original code by Hannes Gredler <hannes@juniper.net> 1927df3f5dSRui Paulo * IPv6 additions by Florian Forster <octo at verplant.org> 20b5bfcb5dSMax Laier */ 21b5bfcb5dSMax Laier 223c602fabSXin LI #define NETDISSECT_REWORKED 23b5bfcb5dSMax Laier #ifdef HAVE_CONFIG_H 24b5bfcb5dSMax Laier #include "config.h" 25b5bfcb5dSMax Laier #endif 26b5bfcb5dSMax Laier 27b5bfcb5dSMax Laier #include <tcpdump-stdinc.h> 28b5bfcb5dSMax Laier 29b5bfcb5dSMax Laier #include "interface.h" 30b5bfcb5dSMax Laier #include "addrtoname.h" 31b5bfcb5dSMax Laier #include "extract.h" 32b5bfcb5dSMax Laier 33b5bfcb5dSMax Laier /* 34b5bfcb5dSMax Laier * RFC 3626 common header 35b5bfcb5dSMax Laier * 36b5bfcb5dSMax Laier * 0 1 2 3 37b5bfcb5dSMax Laier * 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 38b5bfcb5dSMax Laier * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 39b5bfcb5dSMax Laier * | Packet Length | Packet Sequence Number | 40b5bfcb5dSMax Laier * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 41b5bfcb5dSMax Laier * | Message Type | Vtime | Message Size | 42b5bfcb5dSMax Laier * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 43b5bfcb5dSMax Laier * | Originator Address | 44b5bfcb5dSMax Laier * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 45b5bfcb5dSMax Laier * | Time To Live | Hop Count | Message Sequence Number | 46b5bfcb5dSMax Laier * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 47b5bfcb5dSMax Laier * | | 48b5bfcb5dSMax Laier * : MESSAGE : 49b5bfcb5dSMax Laier * | | 50b5bfcb5dSMax Laier * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 51b5bfcb5dSMax Laier * | Message Type | Vtime | Message Size | 52b5bfcb5dSMax Laier * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 53b5bfcb5dSMax Laier * | Originator Address | 54b5bfcb5dSMax Laier * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 55b5bfcb5dSMax Laier * | Time To Live | Hop Count | Message Sequence Number | 56b5bfcb5dSMax Laier * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 57b5bfcb5dSMax Laier * | | 58b5bfcb5dSMax Laier * : MESSAGE : 59b5bfcb5dSMax Laier * | | 60b5bfcb5dSMax Laier * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 61b5bfcb5dSMax Laier * : : 62b5bfcb5dSMax Laier */ 63b5bfcb5dSMax Laier 64b5bfcb5dSMax Laier struct olsr_common { 653c602fabSXin LI uint8_t packet_len[2]; 663c602fabSXin LI uint8_t packet_seq[2]; 67b5bfcb5dSMax Laier }; 68b5bfcb5dSMax Laier 69b5bfcb5dSMax Laier #define OLSR_HELLO_MSG 1 /* rfc3626 */ 70b5bfcb5dSMax Laier #define OLSR_TC_MSG 2 /* rfc3626 */ 71b5bfcb5dSMax Laier #define OLSR_MID_MSG 3 /* rfc3626 */ 72b5bfcb5dSMax Laier #define OLSR_HNA_MSG 4 /* rfc3626 */ 73b5bfcb5dSMax Laier #define OLSR_POWERINFO_MSG 128 74b5bfcb5dSMax Laier #define OLSR_NAMESERVICE_MSG 130 75b5bfcb5dSMax Laier #define OLSR_HELLO_LQ_MSG 201 /* LQ extensions olsr.org */ 76b5bfcb5dSMax Laier #define OLSR_TC_LQ_MSG 202 /* LQ extensions olsr.org */ 77b5bfcb5dSMax Laier 783c602fabSXin LI static const struct tok olsr_msg_values[] = { 79b5bfcb5dSMax Laier { OLSR_HELLO_MSG, "Hello" }, 80b5bfcb5dSMax Laier { OLSR_TC_MSG, "TC" }, 81b5bfcb5dSMax Laier { OLSR_MID_MSG, "MID" }, 82b5bfcb5dSMax Laier { OLSR_HNA_MSG, "HNA" }, 83b5bfcb5dSMax Laier { OLSR_POWERINFO_MSG, "Powerinfo" }, 84b5bfcb5dSMax Laier { OLSR_NAMESERVICE_MSG, "Nameservice" }, 85b5bfcb5dSMax Laier { OLSR_HELLO_LQ_MSG, "Hello-LQ" }, 86b5bfcb5dSMax Laier { OLSR_TC_LQ_MSG, "TC-LQ" }, 87b5bfcb5dSMax Laier { 0, NULL} 88b5bfcb5dSMax Laier }; 89b5bfcb5dSMax Laier 9027df3f5dSRui Paulo struct olsr_msg4 { 913c602fabSXin LI uint8_t msg_type; 923c602fabSXin LI uint8_t vtime; 933c602fabSXin LI uint8_t msg_len[2]; 943c602fabSXin LI uint8_t originator[4]; 953c602fabSXin LI uint8_t ttl; 963c602fabSXin LI uint8_t hopcount; 973c602fabSXin LI uint8_t msg_seq[2]; 98b5bfcb5dSMax Laier }; 99b5bfcb5dSMax Laier 10027df3f5dSRui Paulo struct olsr_msg6 { 1013c602fabSXin LI uint8_t msg_type; 1023c602fabSXin LI uint8_t vtime; 1033c602fabSXin LI uint8_t msg_len[2]; 1043c602fabSXin LI uint8_t originator[16]; 1053c602fabSXin LI uint8_t ttl; 1063c602fabSXin LI uint8_t hopcount; 1073c602fabSXin LI uint8_t msg_seq[2]; 10827df3f5dSRui Paulo }; 10927df3f5dSRui Paulo 110b5bfcb5dSMax Laier struct olsr_hello { 1113c602fabSXin LI uint8_t res[2]; 1123c602fabSXin LI uint8_t htime; 1133c602fabSXin LI uint8_t will; 114b5bfcb5dSMax Laier }; 115b5bfcb5dSMax Laier 116b5bfcb5dSMax Laier struct olsr_hello_link { 1173c602fabSXin LI uint8_t link_code; 1183c602fabSXin LI uint8_t res; 1193c602fabSXin LI uint8_t len[2]; 120b5bfcb5dSMax Laier }; 121b5bfcb5dSMax Laier 122b5bfcb5dSMax Laier struct olsr_tc { 1233c602fabSXin LI uint8_t ans_seq[2]; 1243c602fabSXin LI uint8_t res[2]; 125b5bfcb5dSMax Laier }; 126b5bfcb5dSMax Laier 12727df3f5dSRui Paulo struct olsr_hna4 { 1283c602fabSXin LI uint8_t network[4]; 1293c602fabSXin LI uint8_t mask[4]; 130b5bfcb5dSMax Laier }; 131b5bfcb5dSMax Laier 13227df3f5dSRui Paulo struct olsr_hna6 { 1333c602fabSXin LI uint8_t network[16]; 1343c602fabSXin LI uint8_t mask[16]; 13527df3f5dSRui Paulo }; 13627df3f5dSRui Paulo 137b5bfcb5dSMax Laier 138b5bfcb5dSMax Laier #define OLSR_EXTRACT_LINK_TYPE(link_code) (link_code & 0x3) 139b5bfcb5dSMax Laier #define OLSR_EXTRACT_NEIGHBOR_TYPE(link_code) (link_code >> 2) 140b5bfcb5dSMax Laier 1413c602fabSXin LI static const struct tok olsr_link_type_values[] = { 142b5bfcb5dSMax Laier { 0, "Unspecified" }, 143b5bfcb5dSMax Laier { 1, "Asymmetric" }, 144b5bfcb5dSMax Laier { 2, "Symmetric" }, 145b5bfcb5dSMax Laier { 3, "Lost" }, 146b5bfcb5dSMax Laier { 0, NULL} 147b5bfcb5dSMax Laier }; 148b5bfcb5dSMax Laier 1493c602fabSXin LI static const struct tok olsr_neighbor_type_values[] = { 150b5bfcb5dSMax Laier { 0, "Not-Neighbor" }, 151b5bfcb5dSMax Laier { 1, "Symmetric" }, 152b5bfcb5dSMax Laier { 2, "Symmetric-MPR" }, 153b5bfcb5dSMax Laier { 0, NULL} 154b5bfcb5dSMax Laier }; 155b5bfcb5dSMax Laier 15627df3f5dSRui Paulo struct olsr_lq_neighbor4 { 1573c602fabSXin LI uint8_t neighbor[4]; 1583c602fabSXin LI uint8_t link_quality; 1593c602fabSXin LI uint8_t neighbor_link_quality; 1603c602fabSXin LI uint8_t res[2]; 161b5bfcb5dSMax Laier }; 162b5bfcb5dSMax Laier 16327df3f5dSRui Paulo struct olsr_lq_neighbor6 { 1643c602fabSXin LI uint8_t neighbor[16]; 1653c602fabSXin LI uint8_t link_quality; 1663c602fabSXin LI uint8_t neighbor_link_quality; 1673c602fabSXin LI uint8_t res[2]; 16827df3f5dSRui Paulo }; 16927df3f5dSRui Paulo 170b5bfcb5dSMax Laier /* 171b5bfcb5dSMax Laier * macro to convert the 8-bit mantissa/exponent to a double float 172b5bfcb5dSMax Laier * taken from olsr.org. 173b5bfcb5dSMax Laier */ 174b5bfcb5dSMax Laier #define VTIME_SCALE_FACTOR 0.0625 175b5bfcb5dSMax Laier #define ME_TO_DOUBLE(me) \ 176b5bfcb5dSMax Laier (double)(VTIME_SCALE_FACTOR*(1+(double)(me>>4)/16)*(double)(1<<(me&0x0F))) 177b5bfcb5dSMax Laier 178b5bfcb5dSMax Laier /* 179b5bfcb5dSMax Laier * print a neighbor list with LQ extensions. 180b5bfcb5dSMax Laier */ 181*8bdc5a62SPatrick Kelsey static int 1823c602fabSXin LI olsr_print_lq_neighbor4(netdissect_options *ndo, 1833c602fabSXin LI const u_char *msg_data, u_int hello_len) 184b5bfcb5dSMax Laier { 18527df3f5dSRui Paulo struct olsr_lq_neighbor4 *lq_neighbor; 186b5bfcb5dSMax Laier 18727df3f5dSRui Paulo while (hello_len >= sizeof(struct olsr_lq_neighbor4)) { 188b5bfcb5dSMax Laier 18927df3f5dSRui Paulo lq_neighbor = (struct olsr_lq_neighbor4 *)msg_data; 190*8bdc5a62SPatrick Kelsey if (!ND_TTEST(*lq_neighbor)) 191*8bdc5a62SPatrick Kelsey return (-1); 192b5bfcb5dSMax Laier 1933c602fabSXin LI ND_PRINT((ndo, "\n\t neighbor %s, link-quality %.2lf%%" 194b5bfcb5dSMax Laier ", neighbor-link-quality %.2lf%%", 1953c602fabSXin LI ipaddr_string(ndo, lq_neighbor->neighbor), 196b5bfcb5dSMax Laier ((double)lq_neighbor->link_quality/2.55), 1973c602fabSXin LI ((double)lq_neighbor->neighbor_link_quality/2.55))); 198b5bfcb5dSMax Laier 19927df3f5dSRui Paulo msg_data += sizeof(struct olsr_lq_neighbor4); 20027df3f5dSRui Paulo hello_len -= sizeof(struct olsr_lq_neighbor4); 201b5bfcb5dSMax Laier } 202*8bdc5a62SPatrick Kelsey return (0); 203b5bfcb5dSMax Laier } 204b5bfcb5dSMax Laier 20527df3f5dSRui Paulo #if INET6 206*8bdc5a62SPatrick Kelsey static int 2073c602fabSXin LI olsr_print_lq_neighbor6(netdissect_options *ndo, 2083c602fabSXin LI const u_char *msg_data, u_int hello_len) 20927df3f5dSRui Paulo { 21027df3f5dSRui Paulo struct olsr_lq_neighbor6 *lq_neighbor; 21127df3f5dSRui Paulo 21227df3f5dSRui Paulo while (hello_len >= sizeof(struct olsr_lq_neighbor6)) { 21327df3f5dSRui Paulo 21427df3f5dSRui Paulo lq_neighbor = (struct olsr_lq_neighbor6 *)msg_data; 215*8bdc5a62SPatrick Kelsey if (!ND_TTEST(*lq_neighbor)) 216*8bdc5a62SPatrick Kelsey return (-1); 21727df3f5dSRui Paulo 2183c602fabSXin LI ND_PRINT((ndo, "\n\t neighbor %s, link-quality %.2lf%%" 21927df3f5dSRui Paulo ", neighbor-link-quality %.2lf%%", 2203c602fabSXin LI ip6addr_string(ndo, lq_neighbor->neighbor), 22127df3f5dSRui Paulo ((double)lq_neighbor->link_quality/2.55), 2223c602fabSXin LI ((double)lq_neighbor->neighbor_link_quality/2.55))); 22327df3f5dSRui Paulo 22427df3f5dSRui Paulo msg_data += sizeof(struct olsr_lq_neighbor6); 22527df3f5dSRui Paulo hello_len -= sizeof(struct olsr_lq_neighbor6); 22627df3f5dSRui Paulo } 227*8bdc5a62SPatrick Kelsey return (0); 22827df3f5dSRui Paulo } 22927df3f5dSRui Paulo #endif /* INET6 */ 23027df3f5dSRui Paulo 231b5bfcb5dSMax Laier /* 232b5bfcb5dSMax Laier * print a neighbor list. 233b5bfcb5dSMax Laier */ 234*8bdc5a62SPatrick Kelsey static int 2353c602fabSXin LI olsr_print_neighbor(netdissect_options *ndo, 2363c602fabSXin LI const u_char *msg_data, u_int hello_len) 237b5bfcb5dSMax Laier { 238b5bfcb5dSMax Laier int neighbor; 239b5bfcb5dSMax Laier 2403c602fabSXin LI ND_PRINT((ndo, "\n\t neighbor\n\t\t")); 241b5bfcb5dSMax Laier neighbor = 1; 242b5bfcb5dSMax Laier 243b5bfcb5dSMax Laier while (hello_len >= sizeof(struct in_addr)) { 244b5bfcb5dSMax Laier 245*8bdc5a62SPatrick Kelsey if (!ND_TTEST2(*msg_data, sizeof(struct in_addr))) 246*8bdc5a62SPatrick Kelsey return (-1); 247b5bfcb5dSMax Laier /* print 4 neighbors per line */ 248b5bfcb5dSMax Laier 2493c602fabSXin LI ND_PRINT((ndo, "%s%s", ipaddr_string(ndo, msg_data), 2503c602fabSXin LI neighbor % 4 == 0 ? "\n\t\t" : " ")); 251b5bfcb5dSMax Laier 252b5bfcb5dSMax Laier msg_data += sizeof(struct in_addr); 253b5bfcb5dSMax Laier hello_len -= sizeof(struct in_addr); 254b5bfcb5dSMax Laier } 255*8bdc5a62SPatrick Kelsey return (0); 256b5bfcb5dSMax Laier } 257b5bfcb5dSMax Laier 258b5bfcb5dSMax Laier 259b5bfcb5dSMax Laier void 2603c602fabSXin LI olsr_print(netdissect_options *ndo, 2613c602fabSXin LI const u_char *pptr, u_int length, int is_ipv6) 262b5bfcb5dSMax Laier { 263b5bfcb5dSMax Laier union { 264b5bfcb5dSMax Laier const struct olsr_common *common; 26527df3f5dSRui Paulo const struct olsr_msg4 *msg4; 26627df3f5dSRui Paulo const struct olsr_msg6 *msg6; 267b5bfcb5dSMax Laier const struct olsr_hello *hello; 268b5bfcb5dSMax Laier const struct olsr_hello_link *hello_link; 269b5bfcb5dSMax Laier const struct olsr_tc *tc; 27027df3f5dSRui Paulo const struct olsr_hna4 *hna; 271b5bfcb5dSMax Laier } ptr; 272b5bfcb5dSMax Laier 27327df3f5dSRui Paulo u_int msg_type, msg_len, msg_tlen, hello_len; 2743c602fabSXin LI uint16_t name_entry_type, name_entry_len; 27527df3f5dSRui Paulo u_int name_entry_padding; 2763c602fabSXin LI uint8_t link_type, neighbor_type; 277b5bfcb5dSMax Laier const u_char *tptr, *msg_data; 278b5bfcb5dSMax Laier 279b5bfcb5dSMax Laier tptr = pptr; 280b5bfcb5dSMax Laier 281b5bfcb5dSMax Laier if (length < sizeof(struct olsr_common)) { 282b5bfcb5dSMax Laier goto trunc; 283b5bfcb5dSMax Laier } 284b5bfcb5dSMax Laier 2853c602fabSXin LI ND_TCHECK2(*tptr, sizeof(struct olsr_common)); 286b5bfcb5dSMax Laier 287b5bfcb5dSMax Laier ptr.common = (struct olsr_common *)tptr; 2883c602fabSXin LI length = min(length, EXTRACT_16BITS(ptr.common->packet_len)); 289b5bfcb5dSMax Laier 2903c602fabSXin LI ND_PRINT((ndo, "OLSRv%i, seq 0x%04x, length %u", 29127df3f5dSRui Paulo (is_ipv6 == 0) ? 4 : 6, 292b5bfcb5dSMax Laier EXTRACT_16BITS(ptr.common->packet_seq), 2933c602fabSXin LI length)); 294b5bfcb5dSMax Laier 295b5bfcb5dSMax Laier tptr += sizeof(struct olsr_common); 296b5bfcb5dSMax Laier 297b5bfcb5dSMax Laier /* 298b5bfcb5dSMax Laier * In non-verbose mode, just print version. 299b5bfcb5dSMax Laier */ 3003c602fabSXin LI if (ndo->ndo_vflag < 1) { 301b5bfcb5dSMax Laier return; 302b5bfcb5dSMax Laier } 303b5bfcb5dSMax Laier 304b5bfcb5dSMax Laier while (tptr < (pptr+length)) { 30527df3f5dSRui Paulo union 30627df3f5dSRui Paulo { 30727df3f5dSRui Paulo struct olsr_msg4 *v4; 30827df3f5dSRui Paulo struct olsr_msg6 *v6; 30927df3f5dSRui Paulo } msgptr; 31027df3f5dSRui Paulo int msg_len_valid = 0; 311b5bfcb5dSMax Laier 3123c602fabSXin LI ND_TCHECK2(*tptr, sizeof(struct olsr_msg4)); 313b5bfcb5dSMax Laier 31427df3f5dSRui Paulo #if INET6 31527df3f5dSRui Paulo if (is_ipv6) 31627df3f5dSRui Paulo { 31727df3f5dSRui Paulo msgptr.v6 = (struct olsr_msg6 *) tptr; 31827df3f5dSRui Paulo msg_type = msgptr.v6->msg_type; 31927df3f5dSRui Paulo msg_len = EXTRACT_16BITS(msgptr.v6->msg_len); 32027df3f5dSRui Paulo if ((msg_len >= sizeof (struct olsr_msg6)) 32127df3f5dSRui Paulo && (msg_len <= length)) 32227df3f5dSRui Paulo msg_len_valid = 1; 323b5bfcb5dSMax Laier 324b5bfcb5dSMax Laier /* infinite loop check */ 325b5bfcb5dSMax Laier if (msg_type == 0 || msg_len == 0) { 326b5bfcb5dSMax Laier return; 327b5bfcb5dSMax Laier } 328b5bfcb5dSMax Laier 3293c602fabSXin LI ND_PRINT((ndo, "\n\t%s Message (%#04x), originator %s, ttl %u, hop %u" 33027df3f5dSRui Paulo "\n\t vtime %.3lfs, msg-seq 0x%04x, length %u%s", 331b5bfcb5dSMax Laier tok2str(olsr_msg_values, "Unknown", msg_type), 3323c602fabSXin LI msg_type, ip6addr_string(ndo, msgptr.v6->originator), 33327df3f5dSRui Paulo msgptr.v6->ttl, 33427df3f5dSRui Paulo msgptr.v6->hopcount, 33527df3f5dSRui Paulo ME_TO_DOUBLE(msgptr.v6->vtime), 33627df3f5dSRui Paulo EXTRACT_16BITS(msgptr.v6->msg_seq), 3373c602fabSXin LI msg_len, (msg_len_valid == 0) ? " (invalid)" : "")); 338*8bdc5a62SPatrick Kelsey if (!msg_len_valid) { 339*8bdc5a62SPatrick Kelsey return; 340*8bdc5a62SPatrick Kelsey } 341b5bfcb5dSMax Laier 34227df3f5dSRui Paulo msg_tlen = msg_len - sizeof(struct olsr_msg6); 34327df3f5dSRui Paulo msg_data = tptr + sizeof(struct olsr_msg6); 34427df3f5dSRui Paulo } 34527df3f5dSRui Paulo else /* (!is_ipv6) */ 34627df3f5dSRui Paulo #endif /* INET6 */ 34727df3f5dSRui Paulo { 34827df3f5dSRui Paulo msgptr.v4 = (struct olsr_msg4 *) tptr; 34927df3f5dSRui Paulo msg_type = msgptr.v4->msg_type; 35027df3f5dSRui Paulo msg_len = EXTRACT_16BITS(msgptr.v4->msg_len); 35127df3f5dSRui Paulo if ((msg_len >= sizeof (struct olsr_msg4)) 35227df3f5dSRui Paulo && (msg_len <= length)) 35327df3f5dSRui Paulo msg_len_valid = 1; 35427df3f5dSRui Paulo 35527df3f5dSRui Paulo /* infinite loop check */ 35627df3f5dSRui Paulo if (msg_type == 0 || msg_len == 0) { 35727df3f5dSRui Paulo return; 35827df3f5dSRui Paulo } 35927df3f5dSRui Paulo 3603c602fabSXin LI ND_PRINT((ndo, "\n\t%s Message (%#04x), originator %s, ttl %u, hop %u" 36127df3f5dSRui Paulo "\n\t vtime %.3lfs, msg-seq 0x%04x, length %u%s", 36227df3f5dSRui Paulo tok2str(olsr_msg_values, "Unknown", msg_type), 3633c602fabSXin LI msg_type, ipaddr_string(ndo, msgptr.v4->originator), 36427df3f5dSRui Paulo msgptr.v4->ttl, 36527df3f5dSRui Paulo msgptr.v4->hopcount, 36627df3f5dSRui Paulo ME_TO_DOUBLE(msgptr.v4->vtime), 36727df3f5dSRui Paulo EXTRACT_16BITS(msgptr.v4->msg_seq), 3683c602fabSXin LI msg_len, (msg_len_valid == 0) ? " (invalid)" : "")); 369*8bdc5a62SPatrick Kelsey if (!msg_len_valid) { 370*8bdc5a62SPatrick Kelsey return; 371*8bdc5a62SPatrick Kelsey } 37227df3f5dSRui Paulo 37327df3f5dSRui Paulo msg_tlen = msg_len - sizeof(struct olsr_msg4); 37427df3f5dSRui Paulo msg_data = tptr + sizeof(struct olsr_msg4); 37527df3f5dSRui Paulo } 376b5bfcb5dSMax Laier 377b5bfcb5dSMax Laier switch (msg_type) { 378b5bfcb5dSMax Laier case OLSR_HELLO_MSG: 379b5bfcb5dSMax Laier case OLSR_HELLO_LQ_MSG: 380*8bdc5a62SPatrick Kelsey if (msg_tlen < sizeof(struct olsr_hello)) 381*8bdc5a62SPatrick Kelsey goto trunc; 3823c602fabSXin LI ND_TCHECK2(*msg_data, sizeof(struct olsr_hello)); 383b5bfcb5dSMax Laier 384b5bfcb5dSMax Laier ptr.hello = (struct olsr_hello *)msg_data; 3853c602fabSXin LI ND_PRINT((ndo, "\n\t hello-time %.3lfs, MPR willingness %u", 3863c602fabSXin LI ME_TO_DOUBLE(ptr.hello->htime), ptr.hello->will)); 387b5bfcb5dSMax Laier msg_data += sizeof(struct olsr_hello); 388b5bfcb5dSMax Laier msg_tlen -= sizeof(struct olsr_hello); 389b5bfcb5dSMax Laier 390b5bfcb5dSMax Laier while (msg_tlen >= sizeof(struct olsr_hello_link)) { 39127df3f5dSRui Paulo int hello_len_valid = 0; 392b5bfcb5dSMax Laier 393b5bfcb5dSMax Laier /* 394b5bfcb5dSMax Laier * link-type. 395b5bfcb5dSMax Laier */ 3963c602fabSXin LI ND_TCHECK2(*msg_data, sizeof(struct olsr_hello_link)); 397b5bfcb5dSMax Laier 398b5bfcb5dSMax Laier ptr.hello_link = (struct olsr_hello_link *)msg_data; 399b5bfcb5dSMax Laier 400b5bfcb5dSMax Laier hello_len = EXTRACT_16BITS(ptr.hello_link->len); 401b5bfcb5dSMax Laier link_type = OLSR_EXTRACT_LINK_TYPE(ptr.hello_link->link_code); 402b5bfcb5dSMax Laier neighbor_type = OLSR_EXTRACT_NEIGHBOR_TYPE(ptr.hello_link->link_code); 403b5bfcb5dSMax Laier 40427df3f5dSRui Paulo if ((hello_len <= msg_tlen) 40527df3f5dSRui Paulo && (hello_len >= sizeof(struct olsr_hello_link))) 40627df3f5dSRui Paulo hello_len_valid = 1; 40727df3f5dSRui Paulo 4083c602fabSXin LI ND_PRINT((ndo, "\n\t link-type %s, neighbor-type %s, len %u%s", 409b5bfcb5dSMax Laier tok2str(olsr_link_type_values, "Unknown", link_type), 410b5bfcb5dSMax Laier tok2str(olsr_neighbor_type_values, "Unknown", neighbor_type), 41127df3f5dSRui Paulo hello_len, 4123c602fabSXin LI (hello_len_valid == 0) ? " (invalid)" : "")); 41327df3f5dSRui Paulo 41427df3f5dSRui Paulo if (hello_len_valid == 0) 41527df3f5dSRui Paulo break; 416b5bfcb5dSMax Laier 417b5bfcb5dSMax Laier msg_data += sizeof(struct olsr_hello_link); 418b5bfcb5dSMax Laier msg_tlen -= sizeof(struct olsr_hello_link); 419b5bfcb5dSMax Laier hello_len -= sizeof(struct olsr_hello_link); 420b5bfcb5dSMax Laier 421*8bdc5a62SPatrick Kelsey ND_TCHECK2(*msg_data, hello_len); 422b5bfcb5dSMax Laier if (msg_type == OLSR_HELLO_MSG) { 423*8bdc5a62SPatrick Kelsey if (olsr_print_neighbor(ndo, msg_data, hello_len) == -1) 424*8bdc5a62SPatrick Kelsey goto trunc; 425b5bfcb5dSMax Laier } else { 42627df3f5dSRui Paulo #if INET6 427*8bdc5a62SPatrick Kelsey if (is_ipv6) { 428*8bdc5a62SPatrick Kelsey if (olsr_print_lq_neighbor6(ndo, msg_data, hello_len) == -1) 429*8bdc5a62SPatrick Kelsey goto trunc; 430*8bdc5a62SPatrick Kelsey } else 43127df3f5dSRui Paulo #endif 432*8bdc5a62SPatrick Kelsey { 433*8bdc5a62SPatrick Kelsey if (olsr_print_lq_neighbor4(ndo, msg_data, hello_len) == -1) 434*8bdc5a62SPatrick Kelsey goto trunc; 435*8bdc5a62SPatrick Kelsey } 436b5bfcb5dSMax Laier } 437b5bfcb5dSMax Laier 438b5bfcb5dSMax Laier msg_data += hello_len; 439b5bfcb5dSMax Laier msg_tlen -= hello_len; 440b5bfcb5dSMax Laier } 441b5bfcb5dSMax Laier break; 442b5bfcb5dSMax Laier 443b5bfcb5dSMax Laier case OLSR_TC_MSG: 444b5bfcb5dSMax Laier case OLSR_TC_LQ_MSG: 445*8bdc5a62SPatrick Kelsey if (msg_tlen < sizeof(struct olsr_tc)) 446*8bdc5a62SPatrick Kelsey goto trunc; 4473c602fabSXin LI ND_TCHECK2(*msg_data, sizeof(struct olsr_tc)); 448b5bfcb5dSMax Laier 449b5bfcb5dSMax Laier ptr.tc = (struct olsr_tc *)msg_data; 4503c602fabSXin LI ND_PRINT((ndo, "\n\t advertised neighbor seq 0x%04x", 4513c602fabSXin LI EXTRACT_16BITS(ptr.tc->ans_seq))); 452b5bfcb5dSMax Laier msg_data += sizeof(struct olsr_tc); 453b5bfcb5dSMax Laier msg_tlen -= sizeof(struct olsr_tc); 454b5bfcb5dSMax Laier 455b5bfcb5dSMax Laier if (msg_type == OLSR_TC_MSG) { 456*8bdc5a62SPatrick Kelsey if (olsr_print_neighbor(ndo, msg_data, msg_tlen) == -1) 457*8bdc5a62SPatrick Kelsey goto trunc; 458b5bfcb5dSMax Laier } else { 45927df3f5dSRui Paulo #if INET6 460*8bdc5a62SPatrick Kelsey if (is_ipv6) { 461*8bdc5a62SPatrick Kelsey if (olsr_print_lq_neighbor6(ndo, msg_data, msg_tlen) == -1) 462*8bdc5a62SPatrick Kelsey goto trunc; 463*8bdc5a62SPatrick Kelsey } else 46427df3f5dSRui Paulo #endif 465*8bdc5a62SPatrick Kelsey { 466*8bdc5a62SPatrick Kelsey if (olsr_print_lq_neighbor4(ndo, msg_data, msg_tlen) == -1) 467*8bdc5a62SPatrick Kelsey goto trunc; 468*8bdc5a62SPatrick Kelsey } 469b5bfcb5dSMax Laier } 470b5bfcb5dSMax Laier break; 471b5bfcb5dSMax Laier 472b5bfcb5dSMax Laier case OLSR_MID_MSG: 47327df3f5dSRui Paulo { 47427df3f5dSRui Paulo size_t addr_size = sizeof(struct in_addr); 47527df3f5dSRui Paulo 47627df3f5dSRui Paulo #if INET6 47727df3f5dSRui Paulo if (is_ipv6) 47827df3f5dSRui Paulo addr_size = sizeof(struct in6_addr); 47927df3f5dSRui Paulo #endif 48027df3f5dSRui Paulo 48127df3f5dSRui Paulo while (msg_tlen >= addr_size) { 4823c602fabSXin LI ND_TCHECK2(*msg_data, addr_size); 48327df3f5dSRui Paulo #if INET6 4843c602fabSXin LI ND_PRINT((ndo, "\n\t interface address %s", 4853c602fabSXin LI is_ipv6 ? ip6addr_string(ndo, msg_data) : 4863c602fabSXin LI ipaddr_string(ndo, msg_data))); 4873c602fabSXin LI #else 4883c602fabSXin LI ND_PRINT((ndo, "\n\t interface address %s", 4893c602fabSXin LI ipaddr_string(ndo, msg_data))); 49027df3f5dSRui Paulo #endif 4913c602fabSXin LI 49227df3f5dSRui Paulo msg_data += addr_size; 49327df3f5dSRui Paulo msg_tlen -= addr_size; 494b5bfcb5dSMax Laier } 495b5bfcb5dSMax Laier break; 49627df3f5dSRui Paulo } 497b5bfcb5dSMax Laier 498b5bfcb5dSMax Laier case OLSR_HNA_MSG: 4993c602fabSXin LI ND_PRINT((ndo, "\n\t Advertised networks (total %u)", 5003c602fabSXin LI (unsigned int) (msg_tlen / sizeof(struct olsr_hna6)))); 50127df3f5dSRui Paulo #if INET6 50227df3f5dSRui Paulo if (is_ipv6) 50327df3f5dSRui Paulo { 50427df3f5dSRui Paulo int i = 0; 50527df3f5dSRui Paulo while (msg_tlen >= sizeof(struct olsr_hna6)) { 50627df3f5dSRui Paulo struct olsr_hna6 *hna6; 50727df3f5dSRui Paulo 5083c602fabSXin LI ND_TCHECK2(*msg_data, sizeof(struct olsr_hna6)); 509b5bfcb5dSMax Laier 51027df3f5dSRui Paulo hna6 = (struct olsr_hna6 *)msg_data; 51127df3f5dSRui Paulo 5123c602fabSXin LI ND_PRINT((ndo, "\n\t #%i: %s/%u", 5133c602fabSXin LI i, ip6addr_string(ndo, hna6->network), 5143c602fabSXin LI mask62plen (hna6->mask))); 51527df3f5dSRui Paulo 51627df3f5dSRui Paulo msg_data += sizeof(struct olsr_hna6); 51727df3f5dSRui Paulo msg_tlen -= sizeof(struct olsr_hna6); 51827df3f5dSRui Paulo } 51927df3f5dSRui Paulo } 52027df3f5dSRui Paulo else 52127df3f5dSRui Paulo #endif 52227df3f5dSRui Paulo { 52327df3f5dSRui Paulo int col = 0; 52427df3f5dSRui Paulo while (msg_tlen >= sizeof(struct olsr_hna4)) { 5253c602fabSXin LI ND_TCHECK2(*msg_data, sizeof(struct olsr_hna4)); 52627df3f5dSRui Paulo 52727df3f5dSRui Paulo ptr.hna = (struct olsr_hna4 *)msg_data; 528b5bfcb5dSMax Laier 529b5bfcb5dSMax Laier /* print 4 prefixes per line */ 5303c602fabSXin LI ND_PRINT((ndo, "%s%s/%u", 5313c602fabSXin LI col == 0 ? "\n\t " : ", ", 5323c602fabSXin LI ipaddr_string(ndo, ptr.hna->network), 5333c602fabSXin LI mask2plen(EXTRACT_32BITS(ptr.hna->mask)))); 534b5bfcb5dSMax Laier 53527df3f5dSRui Paulo msg_data += sizeof(struct olsr_hna4); 53627df3f5dSRui Paulo msg_tlen -= sizeof(struct olsr_hna4); 53727df3f5dSRui Paulo 53827df3f5dSRui Paulo col = (col + 1) % 4; 53927df3f5dSRui Paulo } 540b5bfcb5dSMax Laier } 541b5bfcb5dSMax Laier break; 542b5bfcb5dSMax Laier 54327df3f5dSRui Paulo case OLSR_NAMESERVICE_MSG: 54427df3f5dSRui Paulo { 54527df3f5dSRui Paulo u_int name_entries = EXTRACT_16BITS(msg_data+2); 54627df3f5dSRui Paulo u_int addr_size = 4; 54727df3f5dSRui Paulo int name_entries_valid = 0; 54827df3f5dSRui Paulo u_int i; 54927df3f5dSRui Paulo 55027df3f5dSRui Paulo if (is_ipv6) 55127df3f5dSRui Paulo addr_size = 16; 55227df3f5dSRui Paulo 55327df3f5dSRui Paulo if ((name_entries > 0) 55427df3f5dSRui Paulo && ((name_entries * (4 + addr_size)) <= msg_tlen)) 55527df3f5dSRui Paulo name_entries_valid = 1; 55627df3f5dSRui Paulo 55727df3f5dSRui Paulo if (msg_tlen < 4) 55827df3f5dSRui Paulo goto trunc; 5593c602fabSXin LI ND_TCHECK2(*msg_data, 4); 56027df3f5dSRui Paulo 5613c602fabSXin LI ND_PRINT((ndo, "\n\t Version %u, Entries %u%s", 56227df3f5dSRui Paulo EXTRACT_16BITS(msg_data), 5633c602fabSXin LI name_entries, (name_entries_valid == 0) ? " (invalid)" : "")); 56427df3f5dSRui Paulo 56527df3f5dSRui Paulo if (name_entries_valid == 0) 56627df3f5dSRui Paulo break; 56727df3f5dSRui Paulo 56827df3f5dSRui Paulo msg_data += 4; 56927df3f5dSRui Paulo msg_tlen -= 4; 57027df3f5dSRui Paulo 57127df3f5dSRui Paulo for (i = 0; i < name_entries; i++) { 57227df3f5dSRui Paulo int name_entry_len_valid = 0; 57327df3f5dSRui Paulo 57427df3f5dSRui Paulo if (msg_tlen < 4) 57527df3f5dSRui Paulo break; 5763c602fabSXin LI ND_TCHECK2(*msg_data, 4); 57727df3f5dSRui Paulo 57827df3f5dSRui Paulo name_entry_type = EXTRACT_16BITS(msg_data); 57927df3f5dSRui Paulo name_entry_len = EXTRACT_16BITS(msg_data+2); 58027df3f5dSRui Paulo 58127df3f5dSRui Paulo msg_data += 4; 58227df3f5dSRui Paulo msg_tlen -= 4; 58327df3f5dSRui Paulo 58427df3f5dSRui Paulo if ((name_entry_len > 0) && ((addr_size + name_entry_len) <= msg_tlen)) 58527df3f5dSRui Paulo name_entry_len_valid = 1; 58627df3f5dSRui Paulo 5873c602fabSXin LI ND_PRINT((ndo, "\n\t #%u: type %#06x, length %u%s", 58827df3f5dSRui Paulo (unsigned int) i, name_entry_type, 5893c602fabSXin LI name_entry_len, (name_entry_len_valid == 0) ? " (invalid)" : "")); 59027df3f5dSRui Paulo 59127df3f5dSRui Paulo if (name_entry_len_valid == 0) 59227df3f5dSRui Paulo break; 59327df3f5dSRui Paulo 59427df3f5dSRui Paulo /* 32-bit alignment */ 59527df3f5dSRui Paulo name_entry_padding = 0; 59627df3f5dSRui Paulo if (name_entry_len%4 != 0) 59727df3f5dSRui Paulo name_entry_padding = 4-(name_entry_len%4); 59827df3f5dSRui Paulo 59927df3f5dSRui Paulo if (msg_tlen < addr_size + name_entry_len + name_entry_padding) 60027df3f5dSRui Paulo goto trunc; 60127df3f5dSRui Paulo 6023c602fabSXin LI ND_TCHECK2(*msg_data, addr_size + name_entry_len + name_entry_padding); 60327df3f5dSRui Paulo 60427df3f5dSRui Paulo #if INET6 60527df3f5dSRui Paulo if (is_ipv6) 6063c602fabSXin LI ND_PRINT((ndo, ", address %s, name \"", 6073c602fabSXin LI ip6addr_string(ndo, msg_data))); 60827df3f5dSRui Paulo else 60927df3f5dSRui Paulo #endif 6103c602fabSXin LI ND_PRINT((ndo, ", address %s, name \"", 6113c602fabSXin LI ipaddr_string(ndo, msg_data))); 612*8bdc5a62SPatrick Kelsey (void)fn_printn(ndo, msg_data + addr_size, name_entry_len, NULL); 6133c602fabSXin LI ND_PRINT((ndo, "\"")); 61427df3f5dSRui Paulo 61527df3f5dSRui Paulo msg_data += addr_size + name_entry_len + name_entry_padding; 61627df3f5dSRui Paulo msg_tlen -= addr_size + name_entry_len + name_entry_padding; 61727df3f5dSRui Paulo } /* for (i = 0; i < name_entries; i++) */ 61827df3f5dSRui Paulo break; 61927df3f5dSRui Paulo } /* case OLSR_NAMESERVICE_MSG */ 62027df3f5dSRui Paulo 621b5bfcb5dSMax Laier /* 622b5bfcb5dSMax Laier * FIXME those are the defined messages that lack a decoder 623b5bfcb5dSMax Laier * you are welcome to contribute code ;-) 624b5bfcb5dSMax Laier */ 625b5bfcb5dSMax Laier case OLSR_POWERINFO_MSG: 626b5bfcb5dSMax Laier default: 6273c602fabSXin LI print_unknown_data(ndo, msg_data, "\n\t ", msg_tlen); 628b5bfcb5dSMax Laier break; 62927df3f5dSRui Paulo } /* switch (msg_type) */ 630b5bfcb5dSMax Laier tptr += msg_len; 63127df3f5dSRui Paulo } /* while (tptr < (pptr+length)) */ 632b5bfcb5dSMax Laier 633b5bfcb5dSMax Laier return; 634b5bfcb5dSMax Laier 635b5bfcb5dSMax Laier trunc: 6363c602fabSXin LI ND_PRINT((ndo, "[|olsr]")); 637b5bfcb5dSMax Laier } 638b5bfcb5dSMax Laier 639b5bfcb5dSMax Laier /* 640b5bfcb5dSMax Laier * Local Variables: 641b5bfcb5dSMax Laier * c-style: whitesmith 642b5bfcb5dSMax Laier * c-basic-offset: 4 643b5bfcb5dSMax Laier * End: 644b5bfcb5dSMax Laier */ 645