xref: /netbsd-src/external/bsd/tcpdump/dist/print-aodv.c (revision 82d56013d7b633d116a93943de88e08335357a7c)
1 /*
2  * Copyright (c) 2003 Bruce M. Simpson <bms@spc.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *        This product includes software developed by Bruce M. Simpson.
16  * 4. Neither the name of Bruce M. Simpson nor the names of co-
17  *    contributors may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY Bruce M. Simpson AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL Bruce M. Simpson OR CONTRIBUTORS
24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #include <sys/cdefs.h>
34 #ifndef lint
35 __RCSID("$NetBSD: print-aodv.c,v 1.8 2017/09/08 14:01:12 christos Exp $");
36 #endif
37 
38 /* \summary: Ad hoc On-Demand Distance Vector (AODV) Routing printer */
39 
40 #ifdef HAVE_CONFIG_H
41 #include "config.h"
42 #endif
43 
44 #include <netdissect-stdinc.h>
45 
46 #include "netdissect.h"
47 #include "addrtoname.h"
48 #include "extract.h"
49 
50 /*
51  * RFC 3561
52  */
53 struct aodv_rreq {
54 	uint8_t		rreq_type;	/* AODV message type (1) */
55 	uint8_t		rreq_flags;	/* various flags */
56 	uint8_t		rreq_zero0;	/* reserved, set to zero */
57 	uint8_t		rreq_hops;	/* number of hops from originator */
58 	uint32_t	rreq_id;	/* request ID */
59 	uint32_t	rreq_da;	/* destination IPv4 address */
60 	uint32_t	rreq_ds;	/* destination sequence number */
61 	uint32_t	rreq_oa;	/* originator IPv4 address */
62 	uint32_t	rreq_os;	/* originator sequence number */
63 };
64 struct aodv_rreq6 {
65 	uint8_t		rreq_type;	/* AODV message type (1) */
66 	uint8_t		rreq_flags;	/* various flags */
67 	uint8_t		rreq_zero0;	/* reserved, set to zero */
68 	uint8_t		rreq_hops;	/* number of hops from originator */
69 	uint32_t	rreq_id;	/* request ID */
70 	struct in6_addr	rreq_da;	/* destination IPv6 address */
71 	uint32_t	rreq_ds;	/* destination sequence number */
72 	struct in6_addr	rreq_oa;	/* originator IPv6 address */
73 	uint32_t	rreq_os;	/* originator sequence number */
74 };
75 struct aodv_rreq6_draft_01 {
76 	uint8_t		rreq_type;	/* AODV message type (16) */
77 	uint8_t		rreq_flags;	/* various flags */
78 	uint8_t		rreq_zero0;	/* reserved, set to zero */
79 	uint8_t		rreq_hops;	/* number of hops from originator */
80 	uint32_t	rreq_id;	/* request ID */
81 	uint32_t	rreq_ds;	/* destination sequence number */
82 	uint32_t	rreq_os;	/* originator sequence number */
83 	struct in6_addr	rreq_da;	/* destination IPv6 address */
84 	struct in6_addr	rreq_oa;	/* originator IPv6 address */
85 };
86 
87 #define	RREQ_JOIN	0x80		/* join (reserved for multicast */
88 #define	RREQ_REPAIR	0x40		/* repair (reserved for multicast */
89 #define	RREQ_GRAT	0x20		/* gratuitous RREP */
90 #define	RREQ_DEST	0x10		/* destination only */
91 #define	RREQ_UNKNOWN	0x08		/* unknown destination sequence num */
92 #define	RREQ_FLAGS_MASK	0xF8		/* mask for rreq_flags */
93 
94 struct aodv_rrep {
95 	uint8_t		rrep_type;	/* AODV message type (2) */
96 	uint8_t		rrep_flags;	/* various flags */
97 	uint8_t		rrep_ps;	/* prefix size */
98 	uint8_t		rrep_hops;	/* number of hops from o to d */
99 	uint32_t	rrep_da;	/* destination IPv4 address */
100 	uint32_t	rrep_ds;	/* destination sequence number */
101 	uint32_t	rrep_oa;	/* originator IPv4 address */
102 	uint32_t	rrep_life;	/* lifetime of this route */
103 };
104 struct aodv_rrep6 {
105 	uint8_t		rrep_type;	/* AODV message type (2) */
106 	uint8_t		rrep_flags;	/* various flags */
107 	uint8_t		rrep_ps;	/* prefix size */
108 	uint8_t		rrep_hops;	/* number of hops from o to d */
109 	struct in6_addr	rrep_da;	/* destination IPv6 address */
110 	uint32_t	rrep_ds;	/* destination sequence number */
111 	struct in6_addr	rrep_oa;	/* originator IPv6 address */
112 	uint32_t	rrep_life;	/* lifetime of this route */
113 };
114 struct aodv_rrep6_draft_01 {
115 	uint8_t		rrep_type;	/* AODV message type (17) */
116 	uint8_t		rrep_flags;	/* various flags */
117 	uint8_t		rrep_ps;	/* prefix size */
118 	uint8_t		rrep_hops;	/* number of hops from o to d */
119 	uint32_t	rrep_ds;	/* destination sequence number */
120 	struct in6_addr	rrep_da;	/* destination IPv6 address */
121 	struct in6_addr	rrep_oa;	/* originator IPv6 address */
122 	uint32_t	rrep_life;	/* lifetime of this route */
123 };
124 
125 #define	RREP_REPAIR		0x80	/* repair (reserved for multicast */
126 #define	RREP_ACK		0x40	/* acknowledgement required */
127 #define	RREP_FLAGS_MASK		0xC0	/* mask for rrep_flags */
128 #define	RREP_PREFIX_MASK	0x1F	/* mask for prefix size */
129 
130 struct rerr_unreach {
131 	uint32_t	u_da;	/* IPv4 address */
132 	uint32_t	u_ds;	/* sequence number */
133 };
134 struct rerr_unreach6 {
135 	struct in6_addr	u_da;	/* IPv6 address */
136 	uint32_t	u_ds;	/* sequence number */
137 };
138 struct rerr_unreach6_draft_01 {
139 	struct in6_addr	u_da;	/* IPv6 address */
140 	uint32_t	u_ds;	/* sequence number */
141 };
142 
143 struct aodv_rerr {
144 	uint8_t		rerr_type;	/* AODV message type (3 or 18) */
145 	uint8_t		rerr_flags;	/* various flags */
146 	uint8_t		rerr_zero0;	/* reserved, set to zero */
147 	uint8_t		rerr_dc;	/* destination count */
148 };
149 
150 #define RERR_NODELETE		0x80	/* don't delete the link */
151 #define RERR_FLAGS_MASK		0x80	/* mask for rerr_flags */
152 
153 struct aodv_rrep_ack {
154 	uint8_t		ra_type;
155 	uint8_t		ra_zero0;
156 };
157 
158 #define	AODV_RREQ		1	/* route request */
159 #define	AODV_RREP		2	/* route response */
160 #define	AODV_RERR		3	/* error report */
161 #define	AODV_RREP_ACK		4	/* route response acknowledgement */
162 
163 #define AODV_V6_DRAFT_01_RREQ		16	/* IPv6 route request */
164 #define AODV_V6_DRAFT_01_RREP		17	/* IPv6 route response */
165 #define AODV_V6_DRAFT_01_RERR		18	/* IPv6 error report */
166 #define AODV_V6_DRAFT_01_RREP_ACK	19	/* IPV6 route response acknowledgment */
167 
168 struct aodv_ext {
169 	uint8_t		type;		/* extension type */
170 	uint8_t		length;		/* extension length */
171 };
172 
173 struct aodv_hello {
174 	struct	aodv_ext	eh;		/* extension header */
175 	uint8_t			interval[4];	/* expect my next hello in
176 						 * (n) ms
177 						 * NOTE: this is not aligned */
178 };
179 
180 #define	AODV_EXT_HELLO	1
181 
182 static void
183 aodv_extension(netdissect_options *ndo,
184                const struct aodv_ext *ep, u_int length)
185 {
186 	const struct aodv_hello *ah;
187 
188 	ND_TCHECK(*ep);
189 	switch (ep->type) {
190 	case AODV_EXT_HELLO:
191 		ah = (const struct aodv_hello *)(const void *)ep;
192 		ND_TCHECK(*ah);
193 		if (length < sizeof(struct aodv_hello))
194 			goto trunc;
195 		if (ep->length < 4) {
196 			ND_PRINT((ndo, "\n\text HELLO - bad length %u", ep->length));
197 			break;
198 		}
199 		ND_PRINT((ndo, "\n\text HELLO %ld ms",
200 		    (unsigned long)EXTRACT_32BITS(&ah->interval)));
201 		break;
202 
203 	default:
204 		ND_PRINT((ndo, "\n\text %u %u", ep->type, ep->length));
205 		break;
206 	}
207 	return;
208 
209 trunc:
210 	ND_PRINT((ndo, " [|hello]"));
211 }
212 
213 static void
214 aodv_rreq(netdissect_options *ndo, const u_char *dat, u_int length)
215 {
216 	u_int i;
217 	const struct aodv_rreq *ap = (const struct aodv_rreq *)dat;
218 
219 	ND_TCHECK(*ap);
220 	if (length < sizeof(*ap))
221 		goto trunc;
222 	ND_PRINT((ndo, " rreq %u %s%s%s%s%shops %u id 0x%08lx\n"
223 	    "\tdst %s seq %lu src %s seq %lu", length,
224 	    ap->rreq_type & RREQ_JOIN ? "[J]" : "",
225 	    ap->rreq_type & RREQ_REPAIR ? "[R]" : "",
226 	    ap->rreq_type & RREQ_GRAT ? "[G]" : "",
227 	    ap->rreq_type & RREQ_DEST ? "[D]" : "",
228 	    ap->rreq_type & RREQ_UNKNOWN ? "[U] " : " ",
229 	    ap->rreq_hops,
230 	    (unsigned long)EXTRACT_32BITS(&ap->rreq_id),
231 	    ipaddr_string(ndo, &ap->rreq_da),
232 	    (unsigned long)EXTRACT_32BITS(&ap->rreq_ds),
233 	    ipaddr_string(ndo, &ap->rreq_oa),
234 	    (unsigned long)EXTRACT_32BITS(&ap->rreq_os)));
235 	i = length - sizeof(*ap);
236 	if (i >= sizeof(struct aodv_ext))
237 		aodv_extension(ndo, (const struct aodv_ext *)(dat + sizeof(*ap)), i);
238 	return;
239 
240 trunc:
241 	ND_PRINT((ndo, " [|rreq"));
242 }
243 
244 static void
245 aodv_rrep(netdissect_options *ndo, const u_char *dat, u_int length)
246 {
247 	u_int i;
248 	const struct aodv_rrep *ap = (const struct aodv_rrep *)dat;
249 
250 	ND_TCHECK(*ap);
251 	if (length < sizeof(*ap))
252 		goto trunc;
253 	ND_PRINT((ndo, " rrep %u %s%sprefix %u hops %u\n"
254 	    "\tdst %s dseq %lu src %s %lu ms", length,
255 	    ap->rrep_type & RREP_REPAIR ? "[R]" : "",
256 	    ap->rrep_type & RREP_ACK ? "[A] " : " ",
257 	    ap->rrep_ps & RREP_PREFIX_MASK,
258 	    ap->rrep_hops,
259 	    ipaddr_string(ndo, &ap->rrep_da),
260 	    (unsigned long)EXTRACT_32BITS(&ap->rrep_ds),
261 	    ipaddr_string(ndo, &ap->rrep_oa),
262 	    (unsigned long)EXTRACT_32BITS(&ap->rrep_life)));
263 	i = length - sizeof(*ap);
264 	if (i >= sizeof(struct aodv_ext))
265 		aodv_extension(ndo, (const struct aodv_ext *)(dat + sizeof(*ap)), i);
266 	return;
267 
268 trunc:
269 	ND_PRINT((ndo, " [|rreq"));
270 }
271 
272 static void
273 aodv_rerr(netdissect_options *ndo, const u_char *dat, u_int length)
274 {
275 	u_int i, dc;
276 	const struct aodv_rerr *ap = (const struct aodv_rerr *)dat;
277 	const struct rerr_unreach *dp;
278 
279 	ND_TCHECK(*ap);
280 	if (length < sizeof(*ap))
281 		goto trunc;
282 	ND_PRINT((ndo, " rerr %s [items %u] [%u]:",
283 	    ap->rerr_flags & RERR_NODELETE ? "[D]" : "",
284 	    ap->rerr_dc, length));
285 	dp = (const struct rerr_unreach *)(dat + sizeof(*ap));
286 	i = length - sizeof(*ap);
287 	for (dc = ap->rerr_dc; dc != 0; dc--) {
288 		ND_TCHECK(*dp);
289 		if (i < sizeof(*dp))
290 			goto trunc;
291 		ND_PRINT((ndo, " {%s}(%ld)", ipaddr_string(ndo, &dp->u_da),
292 		    (unsigned long)EXTRACT_32BITS(&dp->u_ds)));
293 		dp++;
294 		i -= sizeof(*dp);
295 	}
296 	return;
297 
298 trunc:
299 	ND_PRINT((ndo, "[|rerr]"));
300 }
301 
302 static void
303 aodv_v6_rreq(netdissect_options *ndo, const u_char *dat, u_int length)
304 {
305 	u_int i;
306 	const struct aodv_rreq6 *ap = (const struct aodv_rreq6 *)dat;
307 
308 	ND_TCHECK(*ap);
309 	if (length < sizeof(*ap))
310 		goto trunc;
311 	ND_PRINT((ndo, " v6 rreq %u %s%s%s%s%shops %u id 0x%08lx\n"
312 	    "\tdst %s seq %lu src %s seq %lu", length,
313 	    ap->rreq_type & RREQ_JOIN ? "[J]" : "",
314 	    ap->rreq_type & RREQ_REPAIR ? "[R]" : "",
315 	    ap->rreq_type & RREQ_GRAT ? "[G]" : "",
316 	    ap->rreq_type & RREQ_DEST ? "[D]" : "",
317 	    ap->rreq_type & RREQ_UNKNOWN ? "[U] " : " ",
318 	    ap->rreq_hops,
319 	    (unsigned long)EXTRACT_32BITS(&ap->rreq_id),
320 	    ip6addr_string(ndo, &ap->rreq_da),
321 	    (unsigned long)EXTRACT_32BITS(&ap->rreq_ds),
322 	    ip6addr_string(ndo, &ap->rreq_oa),
323 	    (unsigned long)EXTRACT_32BITS(&ap->rreq_os)));
324 	i = length - sizeof(*ap);
325 	if (i >= sizeof(struct aodv_ext))
326 		aodv_extension(ndo, (const struct aodv_ext *)(dat + sizeof(*ap)), i);
327 	return;
328 
329 trunc:
330 	ND_PRINT((ndo, " [|rreq"));
331 }
332 
333 static void
334 aodv_v6_rrep(netdissect_options *ndo, const u_char *dat, u_int length)
335 {
336 	u_int i;
337 	const struct aodv_rrep6 *ap = (const struct aodv_rrep6 *)dat;
338 
339 	ND_TCHECK(*ap);
340 	if (length < sizeof(*ap))
341 		goto trunc;
342 	ND_PRINT((ndo, " rrep %u %s%sprefix %u hops %u\n"
343 	   "\tdst %s dseq %lu src %s %lu ms", length,
344 	    ap->rrep_type & RREP_REPAIR ? "[R]" : "",
345 	    ap->rrep_type & RREP_ACK ? "[A] " : " ",
346 	    ap->rrep_ps & RREP_PREFIX_MASK,
347 	    ap->rrep_hops,
348 	    ip6addr_string(ndo, &ap->rrep_da),
349 	    (unsigned long)EXTRACT_32BITS(&ap->rrep_ds),
350 	    ip6addr_string(ndo, &ap->rrep_oa),
351 	    (unsigned long)EXTRACT_32BITS(&ap->rrep_life)));
352 	i = length - sizeof(*ap);
353 	if (i >= sizeof(struct aodv_ext))
354 		aodv_extension(ndo, (const struct aodv_ext *)(dat + sizeof(*ap)), i);
355 	return;
356 
357 trunc:
358 	ND_PRINT((ndo, " [|rreq"));
359 }
360 
361 static void
362 aodv_v6_rerr(netdissect_options *ndo, const u_char *dat, u_int length)
363 {
364 	u_int i, dc;
365 	const struct aodv_rerr *ap = (const struct aodv_rerr *)dat;
366 	const struct rerr_unreach6 *dp6;
367 
368 	ND_TCHECK(*ap);
369 	if (length < sizeof(*ap))
370 		goto trunc;
371 	ND_PRINT((ndo, " rerr %s [items %u] [%u]:",
372 	    ap->rerr_flags & RERR_NODELETE ? "[D]" : "",
373 	    ap->rerr_dc, length));
374 	dp6 = (const struct rerr_unreach6 *)(const void *)(ap + 1);
375 	i = length - sizeof(*ap);
376 	for (dc = ap->rerr_dc; dc != 0; dc--) {
377 		ND_TCHECK(*dp6);
378 		if (i < sizeof(*dp6))
379 			goto trunc;
380 		ND_PRINT((ndo, " {%s}(%ld)", ip6addr_string(ndo, &dp6->u_da),
381 		    (unsigned long)EXTRACT_32BITS(&dp6->u_ds)));
382 		dp6++;
383 		i -= sizeof(*dp6);
384 	}
385 	return;
386 
387 trunc:
388 	ND_PRINT((ndo, "[|rerr]"));
389 }
390 
391 static void
392 aodv_v6_draft_01_rreq(netdissect_options *ndo, const u_char *dat, u_int length)
393 {
394 	u_int i;
395 	const struct aodv_rreq6_draft_01 *ap = (const struct aodv_rreq6_draft_01 *)dat;
396 
397 	ND_TCHECK(*ap);
398 	if (length < sizeof(*ap))
399 		goto trunc;
400 	ND_PRINT((ndo, " rreq %u %s%s%s%s%shops %u id 0x%08lx\n"
401 	    "\tdst %s seq %lu src %s seq %lu", length,
402 	    ap->rreq_type & RREQ_JOIN ? "[J]" : "",
403 	    ap->rreq_type & RREQ_REPAIR ? "[R]" : "",
404 	    ap->rreq_type & RREQ_GRAT ? "[G]" : "",
405 	    ap->rreq_type & RREQ_DEST ? "[D]" : "",
406 	    ap->rreq_type & RREQ_UNKNOWN ? "[U] " : " ",
407 	    ap->rreq_hops,
408 	    (unsigned long)EXTRACT_32BITS(&ap->rreq_id),
409 	    ip6addr_string(ndo, &ap->rreq_da),
410 	    (unsigned long)EXTRACT_32BITS(&ap->rreq_ds),
411 	    ip6addr_string(ndo, &ap->rreq_oa),
412 	    (unsigned long)EXTRACT_32BITS(&ap->rreq_os)));
413 	i = length - sizeof(*ap);
414 	if (i >= sizeof(struct aodv_ext))
415 		aodv_extension(ndo, (const struct aodv_ext *)(dat + sizeof(*ap)), i);
416 	return;
417 
418 trunc:
419 	ND_PRINT((ndo, " [|rreq"));
420 }
421 
422 static void
423 aodv_v6_draft_01_rrep(netdissect_options *ndo, const u_char *dat, u_int length)
424 {
425 	u_int i;
426 	const struct aodv_rrep6_draft_01 *ap = (const struct aodv_rrep6_draft_01 *)dat;
427 
428 	ND_TCHECK(*ap);
429 	if (length < sizeof(*ap))
430 		goto trunc;
431 	ND_PRINT((ndo, " rrep %u %s%sprefix %u hops %u\n"
432 	   "\tdst %s dseq %lu src %s %lu ms", length,
433 	    ap->rrep_type & RREP_REPAIR ? "[R]" : "",
434 	    ap->rrep_type & RREP_ACK ? "[A] " : " ",
435 	    ap->rrep_ps & RREP_PREFIX_MASK,
436 	    ap->rrep_hops,
437 	    ip6addr_string(ndo, &ap->rrep_da),
438 	    (unsigned long)EXTRACT_32BITS(&ap->rrep_ds),
439 	    ip6addr_string(ndo, &ap->rrep_oa),
440 	    (unsigned long)EXTRACT_32BITS(&ap->rrep_life)));
441 	i = length - sizeof(*ap);
442 	if (i >= sizeof(struct aodv_ext))
443 		aodv_extension(ndo, (const struct aodv_ext *)(dat + sizeof(*ap)), i);
444 	return;
445 
446 trunc:
447 	ND_PRINT((ndo, " [|rreq"));
448 }
449 
450 static void
451 aodv_v6_draft_01_rerr(netdissect_options *ndo, const u_char *dat, u_int length)
452 {
453 	u_int i, dc;
454 	const struct aodv_rerr *ap = (const struct aodv_rerr *)dat;
455 	const struct rerr_unreach6_draft_01 *dp6;
456 
457 	ND_TCHECK(*ap);
458 	if (length < sizeof(*ap))
459 		goto trunc;
460 	ND_PRINT((ndo, " rerr %s [items %u] [%u]:",
461 	    ap->rerr_flags & RERR_NODELETE ? "[D]" : "",
462 	    ap->rerr_dc, length));
463 	dp6 = (const struct rerr_unreach6_draft_01 *)(const void *)(ap + 1);
464 	i = length - sizeof(*ap);
465 	for (dc = ap->rerr_dc; dc != 0; dc--) {
466 		ND_TCHECK(*dp6);
467 		if (i < sizeof(*dp6))
468 			goto trunc;
469 		ND_PRINT((ndo, " {%s}(%ld)", ip6addr_string(ndo, &dp6->u_da),
470 		    (unsigned long)EXTRACT_32BITS(&dp6->u_ds)));
471 		dp6++;
472 		i -= sizeof(*dp6);
473 	}
474 	return;
475 
476 trunc:
477 	ND_PRINT((ndo, "[|rerr]"));
478 }
479 
480 void
481 aodv_print(netdissect_options *ndo,
482            const u_char *dat, u_int length, int is_ip6)
483 {
484 	uint8_t msg_type;
485 
486 	/*
487 	 * The message type is the first byte; make sure we have it
488 	 * and then fetch it.
489 	 */
490 	ND_TCHECK(*dat);
491 	msg_type = *dat;
492 	ND_PRINT((ndo, " aodv"));
493 
494 	switch (msg_type) {
495 
496 	case AODV_RREQ:
497 		if (is_ip6)
498 			aodv_v6_rreq(ndo, dat, length);
499 		else
500 			aodv_rreq(ndo, dat, length);
501 		break;
502 
503 	case AODV_RREP:
504 		if (is_ip6)
505 			aodv_v6_rrep(ndo, dat, length);
506 		else
507 			aodv_rrep(ndo, dat, length);
508 		break;
509 
510 	case AODV_RERR:
511 		if (is_ip6)
512 			aodv_v6_rerr(ndo, dat, length);
513 		else
514 			aodv_rerr(ndo, dat, length);
515 		break;
516 
517 	case AODV_RREP_ACK:
518 		ND_PRINT((ndo, " rrep-ack %u", length));
519 		break;
520 
521 	case AODV_V6_DRAFT_01_RREQ:
522 		aodv_v6_draft_01_rreq(ndo, dat, length);
523 		break;
524 
525 	case AODV_V6_DRAFT_01_RREP:
526 		aodv_v6_draft_01_rrep(ndo, dat, length);
527 		break;
528 
529 	case AODV_V6_DRAFT_01_RERR:
530 		aodv_v6_draft_01_rerr(ndo, dat, length);
531 		break;
532 
533 	case AODV_V6_DRAFT_01_RREP_ACK:
534 		ND_PRINT((ndo, " rrep-ack %u", length));
535 		break;
536 
537 	default:
538 		ND_PRINT((ndo, " type %u %u", msg_type, length));
539 	}
540 	return;
541 
542 trunc:
543 	ND_PRINT((ndo, " [|aodv]"));
544 }
545