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