xref: /freebsd/contrib/tcpdump/print-olsr.c (revision b5bfcb5d8ae026769a67b6230c15014efc32f7fe)
1b5bfcb5dSMax Laier /*
2b5bfcb5dSMax Laier  * Copyright (c) 1998-2007 The TCPDUMP project
3b5bfcb5dSMax Laier  *
4b5bfcb5dSMax Laier  * Redistribution and use in source and binary forms, with or without
5b5bfcb5dSMax Laier  * modification, are permitted provided that: (1) source code
6b5bfcb5dSMax Laier  * distributions retain the above copyright notice and this paragraph
7b5bfcb5dSMax Laier  * in its entirety, and (2) distributions including binary code include
8b5bfcb5dSMax Laier  * the above copyright notice and this paragraph in its entirety in
9b5bfcb5dSMax Laier  * the documentation or other materials provided with the distribution.
10b5bfcb5dSMax Laier  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
11b5bfcb5dSMax Laier  * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
12b5bfcb5dSMax Laier  * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
13b5bfcb5dSMax Laier  * FOR A PARTICULAR PURPOSE.
14b5bfcb5dSMax Laier  *
15b5bfcb5dSMax Laier  * Optimized Link State Protocl (OLSR) as per rfc3626
16b5bfcb5dSMax Laier  *
17b5bfcb5dSMax Laier  * Original code by Hannes Gredler <hannes@juniper.net>
18b5bfcb5dSMax Laier  */
19b5bfcb5dSMax Laier 
20b5bfcb5dSMax Laier #ifdef HAVE_CONFIG_H
21b5bfcb5dSMax Laier #include "config.h"
22b5bfcb5dSMax Laier #endif
23b5bfcb5dSMax Laier 
24b5bfcb5dSMax Laier #include <tcpdump-stdinc.h>
25b5bfcb5dSMax Laier 
26b5bfcb5dSMax Laier #include <stdio.h>
27b5bfcb5dSMax Laier #include <string.h>
28b5bfcb5dSMax Laier 
29b5bfcb5dSMax Laier #include "interface.h"
30b5bfcb5dSMax Laier #include "addrtoname.h"
31b5bfcb5dSMax Laier #include "extract.h"
32b5bfcb5dSMax Laier #include "ip.h"
33b5bfcb5dSMax Laier 
34b5bfcb5dSMax Laier /*
35b5bfcb5dSMax Laier  * RFC 3626 common header
36b5bfcb5dSMax Laier  *
37b5bfcb5dSMax Laier  *  0                   1                   2                   3
38b5bfcb5dSMax 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
39b5bfcb5dSMax Laier  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
40b5bfcb5dSMax Laier  * |         Packet Length         |    Packet Sequence Number     |
41b5bfcb5dSMax Laier  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
42b5bfcb5dSMax Laier  * |  Message Type |     Vtime     |         Message Size          |
43b5bfcb5dSMax Laier  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
44b5bfcb5dSMax Laier  * |                      Originator Address                       |
45b5bfcb5dSMax Laier  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
46b5bfcb5dSMax Laier  * |  Time To Live |   Hop Count   |    Message Sequence Number    |
47b5bfcb5dSMax Laier  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
48b5bfcb5dSMax Laier  * |                                                               |
49b5bfcb5dSMax Laier  * :                            MESSAGE                            :
50b5bfcb5dSMax Laier  * |                                                               |
51b5bfcb5dSMax Laier  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
52b5bfcb5dSMax Laier  * |  Message Type |     Vtime     |         Message Size          |
53b5bfcb5dSMax Laier  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
54b5bfcb5dSMax Laier  * |                      Originator Address                       |
55b5bfcb5dSMax Laier  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
56b5bfcb5dSMax Laier  * |  Time To Live |   Hop Count   |    Message Sequence Number    |
57b5bfcb5dSMax Laier  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
58b5bfcb5dSMax Laier  * |                                                               |
59b5bfcb5dSMax Laier  * :                            MESSAGE                            :
60b5bfcb5dSMax Laier  * |                                                               |
61b5bfcb5dSMax Laier  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
62b5bfcb5dSMax Laier  * :                                                               :
63b5bfcb5dSMax Laier  */
64b5bfcb5dSMax Laier 
65b5bfcb5dSMax Laier struct olsr_common {
66b5bfcb5dSMax Laier     u_int8_t packet_len[2];
67b5bfcb5dSMax Laier     u_int8_t packet_seq[2];
68b5bfcb5dSMax Laier };
69b5bfcb5dSMax Laier 
70b5bfcb5dSMax Laier #define OLSR_HELLO_MSG         1 /* rfc3626 */
71b5bfcb5dSMax Laier #define OLSR_TC_MSG            2 /* rfc3626 */
72b5bfcb5dSMax Laier #define OLSR_MID_MSG           3 /* rfc3626 */
73b5bfcb5dSMax Laier #define OLSR_HNA_MSG           4 /* rfc3626 */
74b5bfcb5dSMax Laier #define OLSR_POWERINFO_MSG   128
75b5bfcb5dSMax Laier #define OLSR_NAMESERVICE_MSG 130
76b5bfcb5dSMax Laier #define OLSR_HELLO_LQ_MSG    201 /* LQ extensions olsr.org */
77b5bfcb5dSMax Laier #define OLSR_TC_LQ_MSG       202 /* LQ extensions olsr.org */
78b5bfcb5dSMax Laier 
79b5bfcb5dSMax Laier static struct tok olsr_msg_values[] = {
80b5bfcb5dSMax Laier     { OLSR_HELLO_MSG, "Hello" },
81b5bfcb5dSMax Laier     { OLSR_TC_MSG, "TC" },
82b5bfcb5dSMax Laier     { OLSR_MID_MSG, "MID" },
83b5bfcb5dSMax Laier     { OLSR_HNA_MSG, "HNA" },
84b5bfcb5dSMax Laier     { OLSR_POWERINFO_MSG, "Powerinfo" },
85b5bfcb5dSMax Laier     { OLSR_NAMESERVICE_MSG, "Nameservice" },
86b5bfcb5dSMax Laier     { OLSR_HELLO_LQ_MSG, "Hello-LQ" },
87b5bfcb5dSMax Laier     { OLSR_TC_LQ_MSG, "TC-LQ" },
88b5bfcb5dSMax Laier     { 0, NULL}
89b5bfcb5dSMax Laier };
90b5bfcb5dSMax Laier 
91b5bfcb5dSMax Laier struct olsr_msg {
92b5bfcb5dSMax Laier     u_int8_t msg_type;
93b5bfcb5dSMax Laier     u_int8_t vtime;
94b5bfcb5dSMax Laier     u_int8_t msg_len[2];
95b5bfcb5dSMax Laier     u_int8_t originator[4];
96b5bfcb5dSMax Laier     u_int8_t ttl;
97b5bfcb5dSMax Laier     u_int8_t hopcount;
98b5bfcb5dSMax Laier     u_int8_t msg_seq[2];
99b5bfcb5dSMax Laier };
100b5bfcb5dSMax Laier 
101b5bfcb5dSMax Laier struct olsr_hello {
102b5bfcb5dSMax Laier     u_int8_t res[2];
103b5bfcb5dSMax Laier     u_int8_t htime;
104b5bfcb5dSMax Laier     u_int8_t will;
105b5bfcb5dSMax Laier };
106b5bfcb5dSMax Laier 
107b5bfcb5dSMax Laier struct olsr_hello_link {
108b5bfcb5dSMax Laier     u_int8_t link_code;
109b5bfcb5dSMax Laier     u_int8_t res;
110b5bfcb5dSMax Laier     u_int8_t len[2];
111b5bfcb5dSMax Laier };
112b5bfcb5dSMax Laier 
113b5bfcb5dSMax Laier struct olsr_tc {
114b5bfcb5dSMax Laier     u_int8_t ans_seq[2];
115b5bfcb5dSMax Laier     u_int8_t res[2];
116b5bfcb5dSMax Laier };
117b5bfcb5dSMax Laier 
118b5bfcb5dSMax Laier struct olsr_hna {
119b5bfcb5dSMax Laier     u_int8_t network[4];
120b5bfcb5dSMax Laier     u_int8_t mask[4];
121b5bfcb5dSMax Laier };
122b5bfcb5dSMax Laier 
123b5bfcb5dSMax Laier 
124b5bfcb5dSMax Laier #define OLSR_EXTRACT_LINK_TYPE(link_code) (link_code & 0x3)
125b5bfcb5dSMax Laier #define OLSR_EXTRACT_NEIGHBOR_TYPE(link_code) (link_code >> 2)
126b5bfcb5dSMax Laier 
127b5bfcb5dSMax Laier static struct tok olsr_link_type_values[] = {
128b5bfcb5dSMax Laier     { 0, "Unspecified" },
129b5bfcb5dSMax Laier     { 1, "Asymmetric" },
130b5bfcb5dSMax Laier     { 2, "Symmetric" },
131b5bfcb5dSMax Laier     { 3, "Lost" },
132b5bfcb5dSMax Laier     { 0, NULL}
133b5bfcb5dSMax Laier };
134b5bfcb5dSMax Laier 
135b5bfcb5dSMax Laier static struct tok olsr_neighbor_type_values[] = {
136b5bfcb5dSMax Laier     { 0, "Not-Neighbor" },
137b5bfcb5dSMax Laier     { 1, "Symmetric" },
138b5bfcb5dSMax Laier     { 2, "Symmetric-MPR" },
139b5bfcb5dSMax Laier     { 0, NULL}
140b5bfcb5dSMax Laier };
141b5bfcb5dSMax Laier 
142b5bfcb5dSMax Laier struct olsr_lq_neighbor {
143b5bfcb5dSMax Laier     u_int8_t neighbor[4];
144b5bfcb5dSMax Laier     u_int8_t link_quality;
145b5bfcb5dSMax Laier     u_int8_t neighbor_link_quality;
146b5bfcb5dSMax Laier     u_int8_t res[2];
147b5bfcb5dSMax Laier };
148b5bfcb5dSMax Laier 
149b5bfcb5dSMax Laier /*
150b5bfcb5dSMax Laier  * macro to convert the 8-bit mantissa/exponent to a double float
151b5bfcb5dSMax Laier  * taken from olsr.org.
152b5bfcb5dSMax Laier  */
153b5bfcb5dSMax Laier #define VTIME_SCALE_FACTOR    0.0625
154b5bfcb5dSMax Laier #define ME_TO_DOUBLE(me) \
155b5bfcb5dSMax Laier   (double)(VTIME_SCALE_FACTOR*(1+(double)(me>>4)/16)*(double)(1<<(me&0x0F)))
156b5bfcb5dSMax Laier 
157b5bfcb5dSMax Laier /*
158b5bfcb5dSMax Laier  * print a neighbor list with LQ extensions.
159b5bfcb5dSMax Laier  */
160b5bfcb5dSMax Laier static void
161b5bfcb5dSMax Laier olsr_print_lq_neighbor (const u_char *msg_data, u_int hello_len)
162b5bfcb5dSMax Laier {
163b5bfcb5dSMax Laier     struct olsr_lq_neighbor *lq_neighbor;
164b5bfcb5dSMax Laier 
165b5bfcb5dSMax Laier     while (hello_len >= sizeof(struct olsr_lq_neighbor)) {
166b5bfcb5dSMax Laier 
167b5bfcb5dSMax Laier         lq_neighbor = (struct olsr_lq_neighbor *)msg_data;
168b5bfcb5dSMax Laier 
169b5bfcb5dSMax Laier         printf("\n\t      neighbor %s, link-quality %.2lf%%"
170b5bfcb5dSMax Laier                ", neighbor-link-quality %.2lf%%",
171b5bfcb5dSMax Laier                ipaddr_string(lq_neighbor->neighbor),
172b5bfcb5dSMax Laier                ((double)lq_neighbor->link_quality/2.55),
173b5bfcb5dSMax Laier                ((double)lq_neighbor->neighbor_link_quality/2.55));
174b5bfcb5dSMax Laier 
175b5bfcb5dSMax Laier         msg_data += sizeof(struct olsr_lq_neighbor);
176b5bfcb5dSMax Laier         hello_len -= sizeof(struct olsr_lq_neighbor);
177b5bfcb5dSMax Laier     }
178b5bfcb5dSMax Laier }
179b5bfcb5dSMax Laier 
180b5bfcb5dSMax Laier /*
181b5bfcb5dSMax Laier  * print a neighbor list.
182b5bfcb5dSMax Laier  */
183b5bfcb5dSMax Laier static void
184b5bfcb5dSMax Laier olsr_print_neighbor (const u_char *msg_data, u_int hello_len)
185b5bfcb5dSMax Laier {
186b5bfcb5dSMax Laier     int neighbor;
187b5bfcb5dSMax Laier 
188b5bfcb5dSMax Laier     printf("\n\t      neighbor\n\t\t");
189b5bfcb5dSMax Laier     neighbor = 1;
190b5bfcb5dSMax Laier 
191b5bfcb5dSMax Laier     while (hello_len >= sizeof(struct in_addr)) {
192b5bfcb5dSMax Laier 
193b5bfcb5dSMax Laier         /* print 4 neighbors per line */
194b5bfcb5dSMax Laier 
195b5bfcb5dSMax Laier         printf("%s%s", ipaddr_string(msg_data),
196b5bfcb5dSMax Laier                neighbor % 4 == 0 ? "\n\t\t" : " ");
197b5bfcb5dSMax Laier 
198b5bfcb5dSMax Laier         msg_data += sizeof(struct in_addr);
199b5bfcb5dSMax Laier         hello_len -= sizeof(struct in_addr);
200b5bfcb5dSMax Laier     }
201b5bfcb5dSMax Laier }
202b5bfcb5dSMax Laier 
203b5bfcb5dSMax Laier 
204b5bfcb5dSMax Laier void
205b5bfcb5dSMax Laier olsr_print (const u_char *pptr, u_int length)
206b5bfcb5dSMax Laier {
207b5bfcb5dSMax Laier     union {
208b5bfcb5dSMax Laier         const struct olsr_common *common;
209b5bfcb5dSMax Laier         const struct olsr_msg *msg;
210b5bfcb5dSMax Laier         const struct olsr_hello *hello;
211b5bfcb5dSMax Laier         const struct olsr_hello_link *hello_link;
212b5bfcb5dSMax Laier         const struct olsr_lq_neighbor *lq_neighbor;
213b5bfcb5dSMax Laier         const struct olsr_tc *tc;
214b5bfcb5dSMax Laier         const struct olsr_hna *hna;
215b5bfcb5dSMax Laier     } ptr;
216b5bfcb5dSMax Laier 
217b5bfcb5dSMax Laier     u_int msg_type, msg_len, msg_tlen, hello_len, prefix;
218b5bfcb5dSMax Laier     u_int8_t link_type, neighbor_type;
219b5bfcb5dSMax Laier     const u_char *tptr, *msg_data;
220b5bfcb5dSMax Laier 
221b5bfcb5dSMax Laier     tptr = pptr;
222b5bfcb5dSMax Laier 
223b5bfcb5dSMax Laier     if (length < sizeof(struct olsr_common)) {
224b5bfcb5dSMax Laier         goto trunc;
225b5bfcb5dSMax Laier     }
226b5bfcb5dSMax Laier 
227b5bfcb5dSMax Laier     if (!TTEST2(*tptr, sizeof(struct olsr_common))) {
228b5bfcb5dSMax Laier 	goto trunc;
229b5bfcb5dSMax Laier     }
230b5bfcb5dSMax Laier 
231b5bfcb5dSMax Laier     ptr.common = (struct olsr_common *)tptr;
232b5bfcb5dSMax Laier     length = MIN(length, EXTRACT_16BITS(ptr.common->packet_len));
233b5bfcb5dSMax Laier 
234b5bfcb5dSMax Laier     printf("OLSR, seq 0x%04x, length %u",
235b5bfcb5dSMax Laier            EXTRACT_16BITS(ptr.common->packet_seq),
236b5bfcb5dSMax Laier            length);
237b5bfcb5dSMax Laier 
238b5bfcb5dSMax Laier     tptr += sizeof(struct olsr_common);
239b5bfcb5dSMax Laier 
240b5bfcb5dSMax Laier     /*
241b5bfcb5dSMax Laier      * In non-verbose mode, just print version.
242b5bfcb5dSMax Laier      */
243b5bfcb5dSMax Laier     if (vflag < 1) {
244b5bfcb5dSMax Laier 	return;
245b5bfcb5dSMax Laier     }
246b5bfcb5dSMax Laier 
247b5bfcb5dSMax Laier     while (tptr < (pptr+length)) {
248b5bfcb5dSMax Laier 
249b5bfcb5dSMax Laier         if (!TTEST2(*tptr, sizeof(struct olsr_msg)))
250b5bfcb5dSMax Laier             goto trunc;
251b5bfcb5dSMax Laier 
252b5bfcb5dSMax Laier         ptr.msg = (struct olsr_msg *)tptr;
253b5bfcb5dSMax Laier 
254b5bfcb5dSMax Laier         msg_type = ptr.msg->msg_type;
255b5bfcb5dSMax Laier         msg_len = EXTRACT_16BITS(ptr.msg->msg_len);
256b5bfcb5dSMax Laier 
257b5bfcb5dSMax Laier         /* infinite loop check */
258b5bfcb5dSMax Laier         if (msg_type == 0 || msg_len == 0) {
259b5bfcb5dSMax Laier             return;
260b5bfcb5dSMax Laier         }
261b5bfcb5dSMax Laier 
262b5bfcb5dSMax Laier         printf("\n\t%s Message (%u), originator %s, ttl %u, hop %u"
263b5bfcb5dSMax Laier                "\n\t  vtime %.3lfs, msg-seq 0x%04x, length %u",
264b5bfcb5dSMax Laier                tok2str(olsr_msg_values, "Unknown", msg_type),
265b5bfcb5dSMax Laier                msg_type, ipaddr_string(ptr.msg->originator),
266b5bfcb5dSMax Laier                ptr.msg->ttl,
267b5bfcb5dSMax Laier                ptr.msg->hopcount,
268b5bfcb5dSMax Laier                ME_TO_DOUBLE(ptr.msg->vtime),
269b5bfcb5dSMax Laier                EXTRACT_16BITS(ptr.msg->msg_seq),
270b5bfcb5dSMax Laier                msg_len);
271b5bfcb5dSMax Laier 
272b5bfcb5dSMax Laier         msg_tlen = msg_len - sizeof(struct olsr_msg);
273b5bfcb5dSMax Laier         msg_data = tptr + sizeof(struct olsr_msg);
274b5bfcb5dSMax Laier 
275b5bfcb5dSMax Laier         switch (msg_type) {
276b5bfcb5dSMax Laier         case OLSR_HELLO_MSG:
277b5bfcb5dSMax Laier         case OLSR_HELLO_LQ_MSG:
278b5bfcb5dSMax Laier             if (!TTEST2(*msg_data, sizeof(struct olsr_hello)))
279b5bfcb5dSMax Laier                 goto trunc;
280b5bfcb5dSMax Laier 
281b5bfcb5dSMax Laier             ptr.hello = (struct olsr_hello *)msg_data;
282b5bfcb5dSMax Laier             printf("\n\t  hello-time %.3lfs, MPR willingness %u",
283b5bfcb5dSMax Laier                    ME_TO_DOUBLE(ptr.hello->htime), ptr.hello->will);
284b5bfcb5dSMax Laier             msg_data += sizeof(struct olsr_hello);
285b5bfcb5dSMax Laier             msg_tlen -= sizeof(struct olsr_hello);
286b5bfcb5dSMax Laier 
287b5bfcb5dSMax Laier             while (msg_tlen >= sizeof(struct olsr_hello_link)) {
288b5bfcb5dSMax Laier 
289b5bfcb5dSMax Laier                 /*
290b5bfcb5dSMax Laier                  * link-type.
291b5bfcb5dSMax Laier                  */
292b5bfcb5dSMax Laier                 if (!TTEST2(*msg_data, sizeof(struct olsr_hello_link)))
293b5bfcb5dSMax Laier                     goto trunc;
294b5bfcb5dSMax Laier 
295b5bfcb5dSMax Laier                 ptr.hello_link = (struct olsr_hello_link *)msg_data;
296b5bfcb5dSMax Laier 
297b5bfcb5dSMax Laier                 hello_len = EXTRACT_16BITS(ptr.hello_link->len);
298b5bfcb5dSMax Laier                 link_type = OLSR_EXTRACT_LINK_TYPE(ptr.hello_link->link_code);
299b5bfcb5dSMax Laier                 neighbor_type = OLSR_EXTRACT_NEIGHBOR_TYPE(ptr.hello_link->link_code);
300b5bfcb5dSMax Laier 
301b5bfcb5dSMax Laier                 printf("\n\t    link-type %s, neighbor-type %s, len %u",
302b5bfcb5dSMax Laier                        tok2str(olsr_link_type_values, "Unknown", link_type),
303b5bfcb5dSMax Laier                        tok2str(olsr_neighbor_type_values, "Unknown", neighbor_type),
304b5bfcb5dSMax Laier                        hello_len);
305b5bfcb5dSMax Laier 
306b5bfcb5dSMax Laier                 msg_data += sizeof(struct olsr_hello_link);
307b5bfcb5dSMax Laier                 msg_tlen -= sizeof(struct olsr_hello_link);
308b5bfcb5dSMax Laier                 hello_len -= sizeof(struct olsr_hello_link);
309b5bfcb5dSMax Laier 
310b5bfcb5dSMax Laier                 if (msg_type == OLSR_HELLO_MSG) {
311b5bfcb5dSMax Laier                     olsr_print_neighbor(msg_data, hello_len);
312b5bfcb5dSMax Laier                 } else {
313b5bfcb5dSMax Laier                     olsr_print_lq_neighbor(msg_data, hello_len);
314b5bfcb5dSMax Laier                 }
315b5bfcb5dSMax Laier 
316b5bfcb5dSMax Laier                 msg_data += hello_len;
317b5bfcb5dSMax Laier                 msg_tlen -= hello_len;
318b5bfcb5dSMax Laier             }
319b5bfcb5dSMax Laier             break;
320b5bfcb5dSMax Laier 
321b5bfcb5dSMax Laier         case OLSR_TC_MSG:
322b5bfcb5dSMax Laier         case OLSR_TC_LQ_MSG:
323b5bfcb5dSMax Laier             if (!TTEST2(*msg_data, sizeof(struct olsr_tc)))
324b5bfcb5dSMax Laier                 goto trunc;
325b5bfcb5dSMax Laier 
326b5bfcb5dSMax Laier             ptr.tc = (struct olsr_tc *)msg_data;
327b5bfcb5dSMax Laier             printf("\n\t    advertised neighbor seq 0x%04x",
328b5bfcb5dSMax Laier                    EXTRACT_16BITS(ptr.tc->ans_seq));
329b5bfcb5dSMax Laier             msg_data += sizeof(struct olsr_tc);
330b5bfcb5dSMax Laier             msg_tlen -= sizeof(struct olsr_tc);
331b5bfcb5dSMax Laier 
332b5bfcb5dSMax Laier             if (msg_type == OLSR_TC_MSG) {
333b5bfcb5dSMax Laier                 olsr_print_neighbor(msg_data, msg_tlen);
334b5bfcb5dSMax Laier             } else {
335b5bfcb5dSMax Laier                 olsr_print_lq_neighbor(msg_data, msg_tlen);
336b5bfcb5dSMax Laier             }
337b5bfcb5dSMax Laier             break;
338b5bfcb5dSMax Laier 
339b5bfcb5dSMax Laier         case OLSR_MID_MSG:
340b5bfcb5dSMax Laier             if (!TTEST2(*msg_data, sizeof(struct in_addr)))
341b5bfcb5dSMax Laier                 goto trunc;
342b5bfcb5dSMax Laier 
343b5bfcb5dSMax Laier             while (msg_tlen >= sizeof(struct in_addr)) {
344b5bfcb5dSMax Laier                 printf("\n\t  interface address %s", ipaddr_string(msg_data));
345b5bfcb5dSMax Laier                 msg_data += sizeof(struct in_addr);
346b5bfcb5dSMax Laier                 msg_tlen -= sizeof(struct in_addr);
347b5bfcb5dSMax Laier             }
348b5bfcb5dSMax Laier             break;
349b5bfcb5dSMax Laier 
350b5bfcb5dSMax Laier         case OLSR_HNA_MSG:
351b5bfcb5dSMax Laier             prefix = 1;
352b5bfcb5dSMax Laier             printf("\n\t  advertised networks\n\t    ");
353b5bfcb5dSMax Laier             while (msg_tlen >= sizeof(struct olsr_hna)) {
354b5bfcb5dSMax Laier                 if (!TTEST2(*msg_data, sizeof(struct olsr_hna)))
355b5bfcb5dSMax Laier                     goto trunc;
356b5bfcb5dSMax Laier 
357b5bfcb5dSMax Laier                 ptr.hna = (struct olsr_hna *)msg_data;
358b5bfcb5dSMax Laier 
359b5bfcb5dSMax Laier                 /* print 4 prefixes per line */
360b5bfcb5dSMax Laier 
361b5bfcb5dSMax Laier                 printf("%s/%u%s",
362b5bfcb5dSMax Laier                        ipaddr_string(ptr.hna->network),
363b5bfcb5dSMax Laier                        mask2plen(EXTRACT_32BITS(ptr.hna->mask)),
364b5bfcb5dSMax Laier                        prefix % 4 == 0 ? "\n\t    " : " ");
365b5bfcb5dSMax Laier 
366b5bfcb5dSMax Laier                 msg_data += sizeof(struct olsr_hna);
367b5bfcb5dSMax Laier                 msg_tlen -= sizeof(struct olsr_hna);
368b5bfcb5dSMax Laier                 prefix ++;
369b5bfcb5dSMax Laier             }
370b5bfcb5dSMax Laier             break;
371b5bfcb5dSMax Laier 
372b5bfcb5dSMax Laier             /*
373b5bfcb5dSMax Laier              * FIXME those are the defined messages that lack a decoder
374b5bfcb5dSMax Laier              * you are welcome to contribute code ;-)
375b5bfcb5dSMax Laier              */
376b5bfcb5dSMax Laier 
377b5bfcb5dSMax Laier         case OLSR_POWERINFO_MSG:
378b5bfcb5dSMax Laier         case OLSR_NAMESERVICE_MSG:
379b5bfcb5dSMax Laier         default:
380b5bfcb5dSMax Laier 	    print_unknown_data(msg_data, "\n\t    ", msg_tlen);
381b5bfcb5dSMax Laier             break;
382b5bfcb5dSMax Laier         }
383b5bfcb5dSMax Laier         tptr += msg_len;
384b5bfcb5dSMax Laier     }
385b5bfcb5dSMax Laier 
386b5bfcb5dSMax Laier     return;
387b5bfcb5dSMax Laier 
388b5bfcb5dSMax Laier  trunc:
389b5bfcb5dSMax Laier     printf("[|olsr]");
390b5bfcb5dSMax Laier }
391b5bfcb5dSMax Laier 
392b5bfcb5dSMax Laier /*
393b5bfcb5dSMax Laier  * Local Variables:
394b5bfcb5dSMax Laier  * c-style: whitesmith
395b5bfcb5dSMax Laier  * c-basic-offset: 4
396b5bfcb5dSMax Laier  * End:
397b5bfcb5dSMax Laier  */
398