1139749Simp/* 2197404Sjoel * Copyright (c) 1998-2007 The TCPDUMP project 3197404Sjoel * Copyright (c) 2009 Florian Forster 4197404Sjoel * 550724Scg * Redistribution and use in source and binary forms, with or without 6197404Sjoel * modification, are permitted provided that: (1) source code 7197404Sjoel * distributions retain the above copyright notice and this paragraph 8197404Sjoel * in its entirety, and (2) distributions including binary code include 9197404Sjoel * the above copyright notice and this paragraph in its entirety in 10197404Sjoel * the documentation or other materials provided with the distribution. 11197404Sjoel * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 12197404Sjoel * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT 13197404Sjoel * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 14197404Sjoel * FOR A PARTICULAR PURPOSE. 15197404Sjoel * 16197404Sjoel * Original code by Hannes Gredler <hannes@gredler.at> 17197404Sjoel * IPv6 additions by Florian Forster <octo at verplant.org> 18197404Sjoel */ 19197404Sjoel 20197404Sjoel/* \summary: Optimized Link State Routing Protocol (OLSR) printer */ 21197404Sjoel 22197404Sjoel/* specification: RFC 3626 */ 23197404Sjoel 24197404Sjoel#ifdef HAVE_CONFIG_H 25197404Sjoel#include <config.h> 26197404Sjoel#endif 27197404Sjoel 28197404Sjoel#include "netdissect-stdinc.h" 29119853Scg 30197404Sjoel#include "netdissect.h" 3150724Scg#include "addrtoname.h" 3250724Scg#include "extract.h" 3350724Scg 3450724Scg/* 3550724Scg * RFC 3626 common header 3650724Scg * 3750724Scg * 0 1 2 3 3850724Scg * 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 3950724Scg * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 4050724Scg * | Packet Length | Packet Sequence Number | 4150724Scg * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 4250724Scg * | Message Type | Vtime | Message Size | 4350724Scg * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 4450724Scg * | Originator Address | 4550724Scg * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 4650724Scg * | Time To Live | Hop Count | Message Sequence Number | 4750724Scg * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 4850724Scg * | | 4950724Scg * : MESSAGE : 5050724Scg * | | 5150724Scg * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 5250724Scg * | Message Type | Vtime | Message Size | 5350724Scg * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 5450724Scg * | Originator Address | 5550724Scg * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 5650724Scg * | Time To Live | Hop Count | Message Sequence Number | 5750724Scg * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 5850724Scg * | | 5950724Scg * : MESSAGE : 6050724Scg * | | 6150724Scg * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 6250724Scg * : : 6350724Scg */ 6450724Scg 6553413Srogerstruct olsr_common { 66197404Sjoel nd_uint16_t packet_len; 67197404Sjoel nd_uint16_t packet_seq; 68197404Sjoel}; 6953413Sroger 7053413Sroger#define OLSR_HELLO_MSG 1 /* rfc3626 */ 7154831Scg#define OLSR_TC_MSG 2 /* rfc3626 */ 7254831Scg#define OLSR_MID_MSG 3 /* rfc3626 */ 7353413Sroger#define OLSR_HNA_MSG 4 /* rfc3626 */ 7453413Sroger#define OLSR_POWERINFO_MSG 128 7553413Sroger#define OLSR_NAMESERVICE_MSG 130 76193640Sariff#define OLSR_HELLO_LQ_MSG 201 /* LQ extensions olsr.org */ 77193640Sariff#define OLSR_TC_LQ_MSG 202 /* LQ extensions olsr.org */ 78193640Sariff 79193640Sariffstatic const struct tok olsr_msg_values[] = { 8053465Scg { OLSR_HELLO_MSG, "Hello" }, 8153465Scg { OLSR_TC_MSG, "TC" }, 8253465Scg { OLSR_MID_MSG, "MID" }, 8350724Scg { OLSR_HNA_MSG, "HNA" }, 84119287Simp { OLSR_POWERINFO_MSG, "Powerinfo" }, 85119287Simp { OLSR_NAMESERVICE_MSG, "Nameservice" }, 8650724Scg { OLSR_HELLO_LQ_MSG, "Hello-LQ" }, 8753413Sroger { OLSR_TC_LQ_MSG, "TC-LQ" }, 8853413Sroger { 0, NULL} 8970134Scg}; 9070134Scg 9182180Scgstruct olsr_msg4 { 9282180Scg nd_uint8_t msg_type; 9350724Scg nd_uint8_t vtime; 9450724Scg nd_uint16_t msg_len; 9550724Scg nd_ipv4 originator; 9650724Scg nd_uint8_t ttl; 9753413Sroger nd_uint8_t hopcount; 9856154Speter nd_uint16_t msg_seq; 9976086Scg}; 100119548Sorion 10150724Scgstruct olsr_msg6 { 10278033Scg nd_uint8_t msg_type; 10376086Scg nd_uint8_t vtime; 10476086Scg nd_uint16_t msg_len; 10576086Scg nd_ipv6 originator; 10676086Scg nd_uint8_t ttl; 10776086Scg nd_uint8_t hopcount; 10876086Scg nd_uint16_t msg_seq; 10976086Scg}; 11076086Scg 11176086Scgstruct olsr_hello { 11276086Scg nd_byte res[2]; 11395678Scg nd_uint8_t htime; 11476086Scg nd_uint8_t will; 115119548Sorion}; 116119548Sorion 11784658Scgstruct olsr_hello_link { 11859019Scg nd_uint8_t link_code; 119152419Sariff nd_byte res; 120152419Sariff nd_uint16_t len; 121152419Sariff}; 122152419Sariff 123152419Sariffstruct olsr_tc { 124152419Sariff nd_uint16_t ans_seq; 125167648Sariff nd_byte res[2]; 126167648Sariff}; 127167648Sariff 128167648Sariffstruct olsr_hna4 { 129167648Sariff nd_ipv4 network; 130152419Sariff nd_ipv4 mask; 131152419Sariff}; 132152419Sariff 13350724Scgstruct olsr_hna6 { 13450724Scg nd_ipv6 network; 13550724Scg nd_ipv6 mask; 13655209Scg}; 13750724Scg 13874763Scg 13974763Scg/** gateway HNA flags */ 140152419Sariffenum gateway_hna_flags { 141152419Sariff GW_HNA_FLAG_LINKSPEED = 1 << 0, 142164614Sariff GW_HNA_FLAG_IPV4 = 1 << 1, 143164614Sariff GW_HNA_FLAG_IPV4_NAT = 1 << 2, 144164614Sariff GW_HNA_FLAG_IPV6 = 1 << 3, 14555209Scg GW_HNA_FLAG_IPV6PREFIX = 1 << 4 14650724Scg}; 147152419Sariff 148152419Sariff/** gateway HNA field byte offsets in the netmask field of the HNA */ 149152419Sariffenum gateway_hna_fields { 150152419Sariff GW_HNA_PAD = 0, 151152419Sariff GW_HNA_FLAGS = 1, 152152419Sariff GW_HNA_UPLINK = 2, 153152419Sariff GW_HNA_DOWNLINK = 3, 154152419Sariff GW_HNA_V6PREFIXLEN = 4, 155152419Sariff GW_HNA_V6PREFIX = 5 156152419Sariff}; 157152419Sariff 158152419Sariff 159152419Sariff#define OLSR_EXTRACT_LINK_TYPE(link_code) (link_code & 0x3) 160152419Sariff#define OLSR_EXTRACT_NEIGHBOR_TYPE(link_code) (link_code >> 2) 161152419Sariff 162152419Sariffstatic const struct tok olsr_link_type_values[] = { 163152419Sariff { 0, "Unspecified" }, 164152419Sariff { 1, "Asymmetric" }, 165152419Sariff { 2, "Symmetric" }, 166152419Sariff { 3, "Lost" }, 167152419Sariff { 0, NULL} 168152419Sariff}; 169152419Sariff 170152419Sariffstatic const struct tok olsr_neighbor_type_values[] = { 171152419Sariff { 0, "Not-Neighbor" }, 172152419Sariff { 1, "Symmetric" }, 173152419Sariff { 2, "Symmetric-MPR" }, 174152419Sariff { 0, NULL} 175152419Sariff}; 176152419Sariff 177152419Sariffstruct olsr_lq_neighbor4 { 178152419Sariff nd_ipv4 neighbor; 179152419Sariff nd_uint8_t link_quality; 180152419Sariff nd_uint8_t neighbor_link_quality; 181152419Sariff nd_byte res[2]; 182152419Sariff}; 183152419Sariff 184152419Sariffstruct olsr_lq_neighbor6 { 185152419Sariff nd_ipv6 neighbor; 186152419Sariff nd_uint8_t link_quality; 187152419Sariff nd_uint8_t neighbor_link_quality; 188152419Sariff nd_byte res[2]; 189152419Sariff}; 190152419Sariff 191152419Sariff#define MAX_SMARTGW_SPEED 320000000 192152419Sariff 193152419Sariff/** 194152419Sariff * Convert an encoded 1 byte transport value (5 bits mantissa, 3 bits exponent) 195152419Sariff * to an uplink/downlink speed value 196152419Sariff * 197152419Sariff * @param value the encoded 1 byte transport value 198152419Sariff * @return the uplink/downlink speed value (in kbit/s) 199152419Sariff */ 200152419Sariffstatic uint32_t deserialize_gw_speed(uint8_t value) { 201152419Sariff uint32_t speed; 202152419Sariff uint32_t exp; 203152419Sariff 204152419Sariff if (!value) { 205152419Sariff return 0; 206152419Sariff } 207152419Sariff 208152419Sariff if (value == UINT8_MAX) { 20955209Scg /* maximum value: also return maximum value */ 21050724Scg return MAX_SMARTGW_SPEED; 21150724Scg } 21250724Scg 21350724Scg speed = (value >> 3) + 1; 21465644Scg exp = value & 7; 21565644Scg 21665644Scg while (exp != 0) { 21765644Scg speed *= 10; 21859019Scg exp--; 21954831Scg } 220164614Sariff return speed; 22184658Scg} 22250724Scg 223150832Snetchild/* 224150832Snetchild * macro to convert the 8-bit mantissa/exponent to a double float 225152419Sariff * taken from olsr.org. 226152419Sariff */ 227148591Snetchild#define VTIME_SCALE_FACTOR 0.0625 228164614Sariff#define ME_TO_DOUBLE(me) \ 229164614Sariff (double)(VTIME_SCALE_FACTOR*(1+(double)(me>>4)/16)*(double)(1<<(me&0x0F))) 23055209Scg 23150724Scg/* 232150832Snetchild * print a neighbor list with LQ extensions. 233150832Snetchild */ 234150832Snetchildstatic int 23554831Scgolsr_print_lq_neighbor4(netdissect_options *ndo, 23653413Sroger const u_char *msg_data, u_int hello_len) 23754831Scg{ 238150832Snetchild const struct olsr_lq_neighbor4 *lq_neighbor; 239164614Sariff 240164614Sariff while (hello_len >= sizeof(struct olsr_lq_neighbor4)) { 241164614Sariff 242164614Sariff lq_neighbor = (const struct olsr_lq_neighbor4 *)msg_data; 243150832Snetchild ND_TCHECK_SIZE(lq_neighbor); 24454831Scg 245164614Sariff ND_PRINT("\n\t neighbor %s, link-quality %.2f%%" 24650724Scg ", neighbor-link-quality %.2f%%", 247164614Sariff GET_IPADDR_STRING(lq_neighbor->neighbor), 248193640Sariff ((double) GET_U_1(lq_neighbor->link_quality)/2.55), 249193640Sariff ((double) GET_U_1(lq_neighbor->neighbor_link_quality)/2.55)); 250193640Sariff 251193640Sariff msg_data += sizeof(struct olsr_lq_neighbor4); 25264881Scg hello_len -= sizeof(struct olsr_lq_neighbor4); 25350724Scg } 254150832Snetchild return (0); 25550724Scgtrunc: 25650724Scg return -1; 25750724Scg} 25850724Scg 25950724Scgstatic int 26050724Scgolsr_print_lq_neighbor6(netdissect_options *ndo, 26150724Scg const u_char *msg_data, u_int hello_len) 26250724Scg{ 26350724Scg const struct olsr_lq_neighbor6 *lq_neighbor; 264152419Sariff 26550724Scg while (hello_len >= sizeof(struct olsr_lq_neighbor6)) { 26650724Scg 26750724Scg lq_neighbor = (const struct olsr_lq_neighbor6 *)msg_data; 26850724Scg ND_TCHECK_SIZE(lq_neighbor); 26950724Scg 27050724Scg ND_PRINT("\n\t neighbor %s, link-quality %.2f%%" 27150724Scg ", neighbor-link-quality %.2f%%", 27250724Scg GET_IP6ADDR_STRING(lq_neighbor->neighbor), 27354831Scg ((double) GET_U_1(lq_neighbor->link_quality)/2.55), 27454831Scg ((double) GET_U_1(lq_neighbor->neighbor_link_quality)/2.55)); 27550724Scg 276164614Sariff msg_data += sizeof(struct olsr_lq_neighbor6); 277148591Snetchild hello_len -= sizeof(struct olsr_lq_neighbor6); 278148591Snetchild } 279148591Snetchild return (0); 280148591Snetchildtrunc: 281164614Sariff return -1; 282148591Snetchild} 283164614Sariff 284148591Snetchild/* 285164614Sariff * print a neighbor list. 286148591Snetchild */ 287164614Sariffstatic int 288148591Snetchildolsr_print_neighbor(netdissect_options *ndo, 289148591Snetchild const u_char *msg_data, u_int hello_len) 290148591Snetchild{ 291150832Snetchild int neighbor; 292164614Sariff 293148591Snetchild ND_PRINT("\n\t neighbor\n\t\t"); 294148591Snetchild neighbor = 1; 295148591Snetchild 296148591Snetchild while (hello_len >= sizeof(nd_ipv4)) { 297148591Snetchild /* print 4 neighbors per line */ 298148591Snetchild ND_PRINT("%s%s", GET_IPADDR_STRING(msg_data), 299148591Snetchild neighbor % 4 == 0 ? "\n\t\t" : " "); 300148591Snetchild 301148591Snetchild msg_data += sizeof(nd_ipv4); 302148591Snetchild hello_len -= sizeof(nd_ipv4); 303148591Snetchild } 304148591Snetchild return (0); 305148591Snetchild} 306148591Snetchild 307148591Snetchild 30870134Scgvoid 30970134Scgolsr_print(netdissect_options *ndo, 31070134Scg const u_char *pptr, u_int length, int is_ipv6) 31150724Scg{ 31274763Scg union { 31350724Scg const struct olsr_common *common; 314152419Sariff const struct olsr_msg4 *msg4; 31550724Scg const struct olsr_msg6 *msg6; 316164614Sariff const struct olsr_hello *hello; 31750724Scg const struct olsr_hello_link *hello_link; 318152419Sariff const struct olsr_tc *tc; 31950724Scg const struct olsr_hna4 *hna; 320164614Sariff } ptr; 321164614Sariff 322164614Sariff u_int msg_type, msg_len, msg_tlen, hello_len; 323164614Sariff uint16_t name_entry_type, name_entry_len; 324152419Sariff u_int name_entry_padding; 325152419Sariff uint8_t link_type, neighbor_type; 326152419Sariff const u_char *tptr, *msg_data; 327152419Sariff 328152419Sariff ndo->ndo_protocol = "olsr"; 329152419Sariff tptr = pptr; 330152419Sariff 331152419Sariff nd_print_protocol_caps(ndo); 332152419Sariff ND_PRINT("v%u", (is_ipv6) ? 6 : 4); 33350724Scg 33450724Scg if (length < sizeof(struct olsr_common)) { 335164614Sariff goto trunc; 336164614Sariff } 337164614Sariff 338164614Sariff ND_TCHECK_LEN(tptr, sizeof(struct olsr_common)); 339152419Sariff 340152419Sariff ptr.common = (const struct olsr_common *)tptr; 34150724Scg length = ND_MIN(length, GET_BE_U_2(ptr.common->packet_len)); 342164614Sariff 34350724Scg ND_PRINT(", seq 0x%04x, length %u", 34450724Scg GET_BE_U_2(ptr.common->packet_seq), 34550724Scg length); 34674763Scg 34750724Scg tptr += sizeof(struct olsr_common); 348150832Snetchild 349152419Sariff /* 35050724Scg * In non-verbose mode, just print version. 351164614Sariff */ 352164614Sariff if (ndo->ndo_vflag < 1) { 35350724Scg return; 354164614Sariff } 355164614Sariff 356164614Sariff while (tptr < (pptr+length)) { 357164614Sariff union 358206033Sjoel { 359150832Snetchild const struct olsr_msg4 *v4; 360150832Snetchild const struct olsr_msg6 *v6; 361152419Sariff } msgptr; 362164614Sariff int msg_len_valid = 0; 363152419Sariff 364164614Sariff if (is_ipv6) 365152419Sariff { 36650724Scg ND_TCHECK_LEN(tptr, sizeof(struct olsr_msg6)); 367206033Sjoel msgptr.v6 = (const struct olsr_msg6 *) tptr; 368150832Snetchild msg_type = GET_U_1(msgptr.v6->msg_type); 369152419Sariff msg_len = GET_BE_U_2(msgptr.v6->msg_len); 370164614Sariff if ((msg_len >= sizeof (struct olsr_msg6)) 371164614Sariff && (msg_len <= length)) 37250724Scg msg_len_valid = 1; 373150832Snetchild 374152419Sariff /* infinite loop check */ 375152419Sariff if (msg_type == 0 || msg_len == 0) { 376150832Snetchild return; 377150832Snetchild } 378164614Sariff 37950724Scg ND_PRINT("\n\t%s Message (%#04x), originator %s, ttl %u, hop %u" 38050724Scg "\n\t vtime %.3fs, msg-seq 0x%04x, length %u%s", 381193640Sariff tok2str(olsr_msg_values, "Unknown", msg_type), 382164614Sariff msg_type, GET_IP6ADDR_STRING(msgptr.v6->originator), 38350724Scg GET_U_1(msgptr.v6->ttl), 384150832Snetchild GET_U_1(msgptr.v6->hopcount), 38550724Scg ME_TO_DOUBLE(GET_U_1(msgptr.v6->vtime)), 38650724Scg GET_BE_U_2(msgptr.v6->msg_seq), 387150832Snetchild msg_len, (msg_len_valid == 0) ? " (invalid)" : ""); 38850724Scg if (!msg_len_valid) { 38950724Scg return; 39050724Scg } 39150724Scg 39250724Scg msg_tlen = msg_len - sizeof(struct olsr_msg6); 393150832Snetchild msg_data = tptr + sizeof(struct olsr_msg6); 394152419Sariff } 395164614Sariff else /* (!is_ipv6) */ 396152419Sariff { 397150832Snetchild ND_TCHECK_LEN(tptr, sizeof(struct olsr_msg4)); 398150832Snetchild msgptr.v4 = (const struct olsr_msg4 *) tptr; 399150832Snetchild msg_type = GET_U_1(msgptr.v4->msg_type); 400150832Snetchild msg_len = GET_BE_U_2(msgptr.v4->msg_len); 401150832Snetchild if ((msg_len >= sizeof (struct olsr_msg4)) 402150832Snetchild && (msg_len <= length)) 403150832Snetchild msg_len_valid = 1; 404150832Snetchild 405164614Sariff /* infinite loop check */ 40650724Scg if (msg_type == 0 || msg_len == 0) { 40750724Scg return; 40870134Scg } 409164614Sariff 410164614Sariff ND_PRINT("\n\t%s Message (%#04x), originator %s, ttl %u, hop %u" 411164614Sariff "\n\t vtime %.3fs, msg-seq 0x%04x, length %u%s", 412193640Sariff tok2str(olsr_msg_values, "Unknown", msg_type), 41370134Scg msg_type, GET_IPADDR_STRING(msgptr.v4->originator), 41470134Scg GET_U_1(msgptr.v4->ttl), 41570134Scg GET_U_1(msgptr.v4->hopcount), 41670134Scg ME_TO_DOUBLE(GET_U_1(msgptr.v4->vtime)), 41770134Scg GET_BE_U_2(msgptr.v4->msg_seq), 41850724Scg msg_len, (msg_len_valid == 0) ? " (invalid)" : ""); 419164614Sariff if (!msg_len_valid) { 42050724Scg return; 421164614Sariff } 42250724Scg 423150832Snetchild msg_tlen = msg_len - sizeof(struct olsr_msg4); 424150832Snetchild msg_data = tptr + sizeof(struct olsr_msg4); 425148591Snetchild } 426148591Snetchild 427164614Sariff switch (msg_type) { 428148591Snetchild case OLSR_HELLO_MSG: 429164614Sariff case OLSR_HELLO_LQ_MSG: 430164614Sariff if (msg_tlen < sizeof(struct olsr_hello)) 43150724Scg goto trunc; 432148591Snetchild ND_TCHECK_LEN(msg_data, sizeof(struct olsr_hello)); 433148591Snetchild 434150832Snetchild ptr.hello = (const struct olsr_hello *)msg_data; 435164614Sariff ND_PRINT("\n\t hello-time %.3fs, MPR willingness %u", 43650724Scg ME_TO_DOUBLE(GET_U_1(ptr.hello->htime)), 43750724Scg GET_U_1(ptr.hello->will)); 43850724Scg msg_data += sizeof(struct olsr_hello); 43950724Scg msg_tlen -= sizeof(struct olsr_hello); 44050724Scg 44150724Scg while (msg_tlen >= sizeof(struct olsr_hello_link)) { 442164614Sariff int hello_len_valid = 0; 443164614Sariff 44450724Scg /* 44550724Scg * link-type. 446152419Sariff */ 447152419Sariff ND_TCHECK_LEN(msg_data, sizeof(struct olsr_hello_link)); 44850724Scg 449152419Sariff ptr.hello_link = (const struct olsr_hello_link *)msg_data; 450152419Sariff 451152419Sariff hello_len = GET_BE_U_2(ptr.hello_link->len); 452152419Sariff link_type = OLSR_EXTRACT_LINK_TYPE(GET_U_1(ptr.hello_link->link_code)); 453152419Sariff neighbor_type = OLSR_EXTRACT_NEIGHBOR_TYPE(GET_U_1(ptr.hello_link->link_code)); 454164614Sariff 455152419Sariff if ((hello_len <= msg_tlen) 456164614Sariff && (hello_len >= sizeof(struct olsr_hello_link))) 457152419Sariff hello_len_valid = 1; 458164614Sariff 459164614Sariff ND_PRINT("\n\t link-type %s, neighbor-type %s, len %u%s", 460164614Sariff tok2str(olsr_link_type_values, "Unknown", link_type), 461152419Sariff tok2str(olsr_neighbor_type_values, "Unknown", neighbor_type), 462164614Sariff hello_len, 463152419Sariff (hello_len_valid == 0) ? " (invalid)" : ""); 464152419Sariff 465164614Sariff if (hello_len_valid == 0) 466152419Sariff break; 467164614Sariff 468152419Sariff msg_data += sizeof(struct olsr_hello_link); 469152419Sariff msg_tlen -= sizeof(struct olsr_hello_link); 470152419Sariff hello_len -= sizeof(struct olsr_hello_link); 471164614Sariff 472152419Sariff ND_TCHECK_LEN(msg_data, hello_len); 473164614Sariff if (msg_type == OLSR_HELLO_MSG) { 474152419Sariff if (olsr_print_neighbor(ndo, msg_data, hello_len) == -1) 475152419Sariff goto trunc; 476152419Sariff } else { 477152419Sariff if (is_ipv6) { 478152419Sariff if (olsr_print_lq_neighbor6(ndo, msg_data, hello_len) == -1) 479152419Sariff goto trunc; 480152419Sariff } else { 481152419Sariff if (olsr_print_lq_neighbor4(ndo, msg_data, hello_len) == -1) 482152419Sariff goto trunc; 483152419Sariff } 484152419Sariff } 485152419Sariff 486152419Sariff msg_data += hello_len; 487152419Sariff msg_tlen -= hello_len; 488152419Sariff } 489164614Sariff break; 490152419Sariff 491152419Sariff case OLSR_TC_MSG: 492152419Sariff case OLSR_TC_LQ_MSG: 493152419Sariff if (msg_tlen < sizeof(struct olsr_tc)) 494152419Sariff goto trunc; 49550724Scg ND_TCHECK_LEN(msg_data, sizeof(struct olsr_tc)); 49650724Scg 49750724Scg ptr.tc = (const struct olsr_tc *)msg_data; 49884658Scg ND_PRINT("\n\t advertised neighbor seq 0x%04x", 499164614Sariff GET_BE_U_2(ptr.tc->ans_seq)); 500164614Sariff msg_data += sizeof(struct olsr_tc); 501150832Snetchild msg_tlen -= sizeof(struct olsr_tc); 502152419Sariff 503168847Sariff if (msg_type == OLSR_TC_MSG) { 504164614Sariff if (olsr_print_neighbor(ndo, msg_data, msg_tlen) == -1) 505150832Snetchild goto trunc; 50650724Scg } else { 507152419Sariff if (is_ipv6) { 508164614Sariff if (olsr_print_lq_neighbor6(ndo, msg_data, msg_tlen) == -1) 509164614Sariff goto trunc; 510164614Sariff } else { 511164614Sariff if (olsr_print_lq_neighbor4(ndo, msg_data, msg_tlen) == -1) 512164614Sariff goto trunc; 513164614Sariff } 514152419Sariff } 515164614Sariff break; 516164614Sariff 517164614Sariff case OLSR_MID_MSG: 518164614Sariff { 519164614Sariff u_int addr_size = (u_int)sizeof(nd_ipv4); 520164614Sariff 521152419Sariff if (is_ipv6) 52250724Scg addr_size = (u_int)sizeof(nd_ipv6); 523148591Snetchild 524164614Sariff while (msg_tlen >= addr_size) { 525164614Sariff ND_TCHECK_LEN(msg_data, addr_size); 526164614Sariff ND_PRINT("\n\t interface address %s", 527164614Sariff is_ipv6 ? GET_IP6ADDR_STRING(msg_data) : 52850724Scg GET_IPADDR_STRING(msg_data)); 529150832Snetchild 530164614Sariff msg_data += addr_size; 53150724Scg msg_tlen -= addr_size; 53250724Scg } 53350724Scg break; 534164614Sariff } 53550724Scg 53650724Scg case OLSR_HNA_MSG: 53750724Scg if (is_ipv6) 53850724Scg { 539150832Snetchild int i = 0; 54050724Scg 541152419Sariff ND_PRINT("\n\t Advertised networks (total %u)", 542152419Sariff (unsigned int) (msg_tlen / sizeof(struct olsr_hna6))); 543164614Sariff 544164614Sariff while (msg_tlen >= sizeof(struct olsr_hna6)) { 545193640Sariff const struct olsr_hna6 *hna6; 546164614Sariff 547152419Sariff ND_TCHECK_LEN(msg_data, sizeof(struct olsr_hna6)); 548152419Sariff 549164614Sariff hna6 = (const struct olsr_hna6 *)msg_data; 550164614Sariff 551193640Sariff ND_PRINT("\n\t #%i: %s/%u", 552164614Sariff i, GET_IP6ADDR_STRING(hna6->network), 553152419Sariff mask62plen (hna6->mask)); 55450724Scg 55550724Scg msg_data += sizeof(struct olsr_hna6); 556164614Sariff msg_tlen -= sizeof(struct olsr_hna6); 557164614Sariff } 558193640Sariff } 559164614Sariff else 56050724Scg { 561148591Snetchild int col = 0; 562150832Snetchild 56350724Scg ND_PRINT("\n\t Advertised networks (total %u)", 564164614Sariff (unsigned int) (msg_tlen / sizeof(struct olsr_hna4))); 56550724Scg 56650724Scg while (msg_tlen >= sizeof(struct olsr_hna4)) { 567193640Sariff ND_TCHECK_LEN(msg_data, sizeof(struct olsr_hna4)); 568164614Sariff 56950724Scg ptr.hna = (const struct olsr_hna4 *)msg_data; 57050724Scg 57150724Scg /* print 4 prefixes per line */ 57250724Scg if (!ptr.hna->network[0] && !ptr.hna->network[1] && 573164614Sariff !ptr.hna->network[2] && !ptr.hna->network[3] && 574152419Sariff !ptr.hna->mask[GW_HNA_PAD] && 575171250Sariff ptr.hna->mask[GW_HNA_FLAGS]) { 576171250Sariff /* smart gateway */ 577164614Sariff ND_PRINT("%sSmart-Gateway:%s%s%s%s%s %u/%u", 578171250Sariff col == 0 ? "\n\t " : ", ", /* indent */ 579152419Sariff /* sgw */ 580152419Sariff /* LINKSPEED */ 581152419Sariff (ptr.hna->mask[GW_HNA_FLAGS] & 582152419Sariff GW_HNA_FLAG_LINKSPEED) ? " LINKSPEED" : "", 583152419Sariff /* IPV4 */ 584152419Sariff (ptr.hna->mask[GW_HNA_FLAGS] & 585152419Sariff GW_HNA_FLAG_IPV4) ? " IPV4" : "", 586152419Sariff /* IPV4-NAT */ 587218909Sbrucec (ptr.hna->mask[GW_HNA_FLAGS] & 588152419Sariff GW_HNA_FLAG_IPV4_NAT) ? " IPV4-NAT" : "", 589152419Sariff /* IPV6 */ 590152419Sariff (ptr.hna->mask[GW_HNA_FLAGS] & 591152419Sariff GW_HNA_FLAG_IPV6) ? " IPV6" : "", 592152419Sariff /* IPv6PREFIX */ 593152419Sariff (ptr.hna->mask[GW_HNA_FLAGS] & 594152419Sariff GW_HNA_FLAG_IPV6PREFIX) ? " IPv6-PREFIX" : "", 595152419Sariff /* uplink */ 596152419Sariff (ptr.hna->mask[GW_HNA_FLAGS] & 597152419Sariff GW_HNA_FLAG_LINKSPEED) ? 598152419Sariff deserialize_gw_speed(ptr.hna->mask[GW_HNA_UPLINK]) : 0, 599152419Sariff /* downlink */ 600152419Sariff (ptr.hna->mask[GW_HNA_FLAGS] & 601152419Sariff GW_HNA_FLAG_LINKSPEED) ? 602152419Sariff deserialize_gw_speed(ptr.hna->mask[GW_HNA_DOWNLINK]) : 0 603152419Sariff ); 604152419Sariff } else { 605152419Sariff /* normal route */ 606150832Snetchild ND_PRINT("%s%s/%u", 607148591Snetchild col == 0 ? "\n\t " : ", ", 608150832Snetchild GET_IPADDR_STRING(ptr.hna->network), 609164614Sariff mask2plen(GET_BE_U_4(ptr.hna->mask))); 61050724Scg } 61150724Scg 612193640Sariff msg_data += sizeof(struct olsr_hna4); 613164614Sariff msg_tlen -= sizeof(struct olsr_hna4); 61454831Scg 61554831Scg col = (col + 1) % 4; 61654831Scg } 617152419Sariff } 618152419Sariff break; 61954831Scg 620150832Snetchild case OLSR_NAMESERVICE_MSG: 621148591Snetchild { 622152419Sariff u_int name_entries; 623148591Snetchild u_int addr_size; 624152419Sariff int name_entries_valid; 625150832Snetchild u_int i; 626164614Sariff 627148591Snetchild if (msg_tlen < 4) 628164614Sariff goto trunc; 629164614Sariff 63054831Scg name_entries = GET_BE_U_2(msg_data + 2); 63154831Scg addr_size = 4; 63250724Scg if (is_ipv6) 633167648Sariff addr_size = 16; 63450724Scg 63570321Scg name_entries_valid = 0; 636164614Sariff if ((name_entries > 0) 63770321Scg && ((name_entries * (4 + addr_size)) <= msg_tlen)) 638167648Sariff name_entries_valid = 1; 639164614Sariff 640167648Sariff ND_PRINT("\n\t Version %u, Entries %u%s", 641167648Sariff GET_BE_U_2(msg_data), 642167648Sariff name_entries, (name_entries_valid == 0) ? " (invalid)" : ""); 643167648Sariff 644167648Sariff if (name_entries_valid == 0) 645167648Sariff break; 646167648Sariff 647167648Sariff msg_data += 4; 648164614Sariff msg_tlen -= 4; 649167648Sariff 650167648Sariff for (i = 0; i < name_entries; i++) { 651167648Sariff int name_entry_len_valid = 0; 652167648Sariff 653167648Sariff if (msg_tlen < 4) 654167648Sariff break; 655167648Sariff 656167648Sariff name_entry_type = GET_BE_U_2(msg_data); 657167648Sariff name_entry_len = GET_BE_U_2(msg_data + 2); 658164614Sariff 659167648Sariff msg_data += 4; 660167648Sariff msg_tlen -= 4; 661164614Sariff 662167648Sariff if ((name_entry_len > 0) && ((addr_size + name_entry_len) <= msg_tlen)) 663164614Sariff name_entry_len_valid = 1; 664164614Sariff 665164614Sariff ND_PRINT("\n\t #%u: type %#06x, length %u%s", 666167648Sariff (unsigned int) i, name_entry_type, 667164614Sariff name_entry_len, (name_entry_len_valid == 0) ? " (invalid)" : ""); 668193640Sariff 669167648Sariff if (name_entry_len_valid == 0) 670167648Sariff break; 671193640Sariff 672167648Sariff /* 32-bit alignment */ 673167648Sariff name_entry_padding = 0; 674167648Sariff if (name_entry_len%4 != 0) 675167648Sariff name_entry_padding = 4-(name_entry_len%4); 676167648Sariff 677167648Sariff if (msg_tlen < addr_size + name_entry_len + name_entry_padding) 678167648Sariff goto trunc; 679164614Sariff 680164614Sariff ND_TCHECK_LEN(msg_data, 681164614Sariff addr_size + name_entry_len + name_entry_padding); 682164614Sariff 683164614Sariff if (is_ipv6) 684164614Sariff ND_PRINT(", address %s, name \"", 685164614Sariff GET_IP6ADDR_STRING(msg_data)); 686164614Sariff else 687164614Sariff ND_PRINT(", address %s, name \"", 688164614Sariff GET_IPADDR_STRING(msg_data)); 689164614Sariff (void)nd_printn(ndo, msg_data + addr_size, name_entry_len, NULL); 690164614Sariff ND_PRINT("\""); 691164614Sariff 692164614Sariff msg_data += addr_size + name_entry_len + name_entry_padding; 693164614Sariff msg_tlen -= addr_size + name_entry_len + name_entry_padding; 694164614Sariff } /* for (i = 0; i < name_entries; i++) */ 695164614Sariff break; 696164614Sariff } /* case OLSR_NAMESERVICE_MSG */ 697164614Sariff 698164614Sariff /* 699164614Sariff * FIXME those are the defined messages that lack a decoder 700164614Sariff * you are welcome to contribute code ;-) 701164614Sariff */ 702164614Sariff case OLSR_POWERINFO_MSG: 703164614Sariff default: 704164614Sariff print_unknown_data(ndo, msg_data, "\n\t ", msg_tlen); 705164614Sariff break; 706164614Sariff } /* switch (msg_type) */ 707164614Sariff tptr += msg_len; 708164614Sariff } /* while (tptr < (pptr+length)) */ 709164614Sariff 710164614Sariff return; 711164614Sariff 712164614Sariff trunc: 713164614Sariff nd_print_trunc(ndo); 714164614Sariff} 715164614Sariff