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