xref: /netbsd-src/external/bsd/tcpdump/dist/print-aodv.c (revision 3117ece4fc4a4ca4489ba793710b60b0d26bab6c)
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.10 2024/09/02 16:15:30 christos Exp $");
36 #endif
37 
38 /* \summary: Ad hoc On-Demand Distance Vector (AODV) Routing printer */
39 
40 #include <config.h>
41 
42 #include "netdissect-stdinc.h"
43 
44 #include "netdissect.h"
45 #include "addrtoname.h"
46 #include "extract.h"
47 
48 /*
49  * RFC 3561
50  */
51 struct aodv_rreq {
52 	nd_uint8_t	rreq_type;	/* AODV message type (1) */
53 	nd_uint8_t	rreq_flags;	/* various flags */
54 	nd_uint8_t	rreq_zero0;	/* reserved, set to zero */
55 	nd_uint8_t	rreq_hops;	/* number of hops from originator */
56 	nd_uint32_t	rreq_id;	/* request ID */
57 	nd_ipv4		rreq_da;	/* destination IPv4 address */
58 	nd_uint32_t	rreq_ds;	/* destination sequence number */
59 	nd_ipv4		rreq_oa;	/* originator IPv4 address */
60 	nd_uint32_t	rreq_os;	/* originator sequence number */
61 };
62 struct aodv_rreq6 {
63 	nd_uint8_t	rreq_type;	/* AODV message type (1) */
64 	nd_uint8_t	rreq_flags;	/* various flags */
65 	nd_uint8_t	rreq_zero0;	/* reserved, set to zero */
66 	nd_uint8_t	rreq_hops;	/* number of hops from originator */
67 	nd_uint32_t	rreq_id;	/* request ID */
68 	nd_ipv6		rreq_da;	/* destination IPv6 address */
69 	nd_uint32_t	rreq_ds;	/* destination sequence number */
70 	nd_ipv6		rreq_oa;	/* originator IPv6 address */
71 	nd_uint32_t	rreq_os;	/* originator sequence number */
72 };
73 struct aodv_rreq6_draft_01 {
74 	nd_uint8_t	rreq_type;	/* AODV message type (16) */
75 	nd_uint8_t	rreq_flags;	/* various flags */
76 	nd_uint8_t	rreq_zero0;	/* reserved, set to zero */
77 	nd_uint8_t	rreq_hops;	/* number of hops from originator */
78 	nd_uint32_t	rreq_id;	/* request ID */
79 	nd_uint32_t	rreq_ds;	/* destination sequence number */
80 	nd_uint32_t	rreq_os;	/* originator sequence number */
81 	nd_ipv6		rreq_da;	/* destination IPv6 address */
82 	nd_ipv6		rreq_oa;	/* originator IPv6 address */
83 };
84 
85 #define	RREQ_JOIN	0x80		/* join (reserved for multicast */
86 #define	RREQ_REPAIR	0x40		/* repair (reserved for multicast */
87 #define	RREQ_GRAT	0x20		/* gratuitous RREP */
88 #define	RREQ_DEST	0x10		/* destination only */
89 #define	RREQ_UNKNOWN	0x08		/* unknown destination sequence num */
90 #define	RREQ_FLAGS_MASK	0xF8		/* mask for rreq_flags */
91 
92 struct aodv_rrep {
93 	nd_uint8_t	rrep_type;	/* AODV message type (2) */
94 	nd_uint8_t	rrep_flags;	/* various flags */
95 	nd_uint8_t	rrep_ps;	/* prefix size */
96 	nd_uint8_t	rrep_hops;	/* number of hops from o to d */
97 	nd_ipv4		rrep_da;	/* destination IPv4 address */
98 	nd_uint32_t	rrep_ds;	/* destination sequence number */
99 	nd_ipv4		rrep_oa;	/* originator IPv4 address */
100 	nd_uint32_t	rrep_life;	/* lifetime of this route */
101 };
102 struct aodv_rrep6 {
103 	nd_uint8_t	rrep_type;	/* AODV message type (2) */
104 	nd_uint8_t	rrep_flags;	/* various flags */
105 	nd_uint8_t	rrep_ps;	/* prefix size */
106 	nd_uint8_t	rrep_hops;	/* number of hops from o to d */
107 	nd_ipv6		rrep_da;	/* destination IPv6 address */
108 	nd_uint32_t	rrep_ds;	/* destination sequence number */
109 	nd_ipv6		rrep_oa;	/* originator IPv6 address */
110 	nd_uint32_t	rrep_life;	/* lifetime of this route */
111 };
112 struct aodv_rrep6_draft_01 {
113 	nd_uint8_t	rrep_type;	/* AODV message type (17) */
114 	nd_uint8_t	rrep_flags;	/* various flags */
115 	nd_uint8_t	rrep_ps;	/* prefix size */
116 	nd_uint8_t	rrep_hops;	/* number of hops from o to d */
117 	nd_uint32_t	rrep_ds;	/* destination sequence number */
118 	nd_ipv6		rrep_da;	/* destination IPv6 address */
119 	nd_ipv6		rrep_oa;	/* originator IPv6 address */
120 	nd_uint32_t	rrep_life;	/* lifetime of this route */
121 };
122 
123 #define	RREP_REPAIR		0x80	/* repair (reserved for multicast */
124 #define	RREP_ACK		0x40	/* acknowledgement required */
125 #define	RREP_FLAGS_MASK		0xC0	/* mask for rrep_flags */
126 #define	RREP_PREFIX_MASK	0x1F	/* mask for prefix size */
127 
128 struct rerr_unreach {
129 	nd_ipv4		u_da;	/* IPv4 address */
130 	nd_uint32_t	u_ds;	/* sequence number */
131 };
132 struct rerr_unreach6 {
133 	nd_ipv6		u_da;	/* IPv6 address */
134 	nd_uint32_t	u_ds;	/* sequence number */
135 };
136 struct rerr_unreach6_draft_01 {
137 	nd_ipv6		u_da;	/* IPv6 address */
138 	nd_uint32_t	u_ds;	/* sequence number */
139 };
140 
141 struct aodv_rerr {
142 	nd_uint8_t	rerr_type;	/* AODV message type (3 or 18) */
143 	nd_uint8_t	rerr_flags;	/* various flags */
144 	nd_uint8_t	rerr_zero0;	/* reserved, set to zero */
145 	nd_uint8_t	rerr_dc;	/* destination count */
146 };
147 
148 #define RERR_NODELETE		0x80	/* don't delete the link */
149 #define RERR_FLAGS_MASK		0x80	/* mask for rerr_flags */
150 
151 struct aodv_rrep_ack {
152 	nd_uint8_t	ra_type;
153 	nd_uint8_t	ra_zero0;
154 };
155 
156 #define	AODV_RREQ		1	/* route request */
157 #define	AODV_RREP		2	/* route response */
158 #define	AODV_RERR		3	/* error report */
159 #define	AODV_RREP_ACK		4	/* route response acknowledgement */
160 
161 #define AODV_V6_DRAFT_01_RREQ		16	/* IPv6 route request */
162 #define AODV_V6_DRAFT_01_RREP		17	/* IPv6 route response */
163 #define AODV_V6_DRAFT_01_RERR		18	/* IPv6 error report */
164 #define AODV_V6_DRAFT_01_RREP_ACK	19	/* IPV6 route response acknowledgment */
165 
166 struct aodv_ext {
167 	nd_uint8_t	type;		/* extension type */
168 	nd_uint8_t	length;		/* extension length */
169 };
170 
171 struct aodv_hello {
172 	struct	aodv_ext	eh;		/* extension header */
173 	nd_uint32_t		interval;	/* expect my next hello in
174 						 * (n) ms
175 						 * NOTE: this is not aligned */
176 };
177 
178 #define	AODV_EXT_HELLO	1
179 
180 static void
181 aodv_extension(netdissect_options *ndo,
182                const struct aodv_ext *ep, u_int length)
183 {
184 	const struct aodv_hello *ah;
185 
186 	ND_TCHECK_SIZE(ep);
187 	switch (GET_U_1(ep->type)) {
188 	case AODV_EXT_HELLO:
189 		ah = (const struct aodv_hello *)(const void *)ep;
190 		ND_TCHECK_SIZE(ah);
191 		if (length < sizeof(struct aodv_hello))
192 			goto trunc;
193 		if (GET_U_1(ep->length) < 4) {
194 			ND_PRINT("\n\text HELLO - bad length %u",
195 				 GET_U_1(ep->length));
196 			break;
197 		}
198 		ND_PRINT("\n\text HELLO %u ms",
199 		    GET_BE_U_4(ah->interval));
200 		break;
201 
202 	default:
203 		ND_PRINT("\n\text %u %u", GET_U_1(ep->type),
204 			 GET_U_1(ep->length));
205 		break;
206 	}
207 	return;
208 
209 trunc:
210 	nd_print_trunc(ndo);
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_SIZE(ap);
220 	if (length < sizeof(*ap))
221 		goto trunc;
222 	ND_PRINT(" rreq %u %s%s%s%s%shops %u id 0x%08x\n"
223 	    "\tdst %s seq %u src %s seq %u", length,
224 	    GET_U_1(ap->rreq_type) & RREQ_JOIN ? "[J]" : "",
225 	    GET_U_1(ap->rreq_type) & RREQ_REPAIR ? "[R]" : "",
226 	    GET_U_1(ap->rreq_type) & RREQ_GRAT ? "[G]" : "",
227 	    GET_U_1(ap->rreq_type) & RREQ_DEST ? "[D]" : "",
228 	    GET_U_1(ap->rreq_type) & RREQ_UNKNOWN ? "[U] " : " ",
229 	    GET_U_1(ap->rreq_hops),
230 	    GET_BE_U_4(ap->rreq_id),
231 	    GET_IPADDR_STRING(ap->rreq_da),
232 	    GET_BE_U_4(ap->rreq_ds),
233 	    GET_IPADDR_STRING(ap->rreq_oa),
234 	    GET_BE_U_4(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_trunc(ndo);
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_SIZE(ap);
251 	if (length < sizeof(*ap))
252 		goto trunc;
253 	ND_PRINT(" rrep %u %s%sprefix %u hops %u\n"
254 	    "\tdst %s dseq %u src %s %u ms", length,
255 	    GET_U_1(ap->rrep_type) & RREP_REPAIR ? "[R]" : "",
256 	    GET_U_1(ap->rrep_type) & RREP_ACK ? "[A] " : " ",
257 	    GET_U_1(ap->rrep_ps) & RREP_PREFIX_MASK,
258 	    GET_U_1(ap->rrep_hops),
259 	    GET_IPADDR_STRING(ap->rrep_da),
260 	    GET_BE_U_4(ap->rrep_ds),
261 	    GET_IPADDR_STRING(ap->rrep_oa),
262 	    GET_BE_U_4(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_trunc(ndo);
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_SIZE(ap);
280 	if (length < sizeof(*ap))
281 		goto trunc;
282 	ND_PRINT(" rerr %s [items %u] [%u]:",
283 	    GET_U_1(ap->rerr_flags) & RERR_NODELETE ? "[D]" : "",
284 	    GET_U_1(ap->rerr_dc), length);
285 	dp = (const struct rerr_unreach *)(dat + sizeof(*ap));
286 	i = length - sizeof(*ap);
287 	for (dc = GET_U_1(ap->rerr_dc); dc != 0; dc--) {
288 		ND_TCHECK_SIZE(dp);
289 		if (i < sizeof(*dp))
290 			goto trunc;
291 		ND_PRINT(" {%s}(%u)", GET_IPADDR_STRING(dp->u_da),
292 		    GET_BE_U_4(dp->u_ds));
293 		dp++;
294 		i -= sizeof(*dp);
295 	}
296 	return;
297 
298 trunc:
299 	nd_print_trunc(ndo);
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_SIZE(ap);
309 	if (length < sizeof(*ap))
310 		goto trunc;
311 	ND_PRINT(" v6 rreq %u %s%s%s%s%shops %u id 0x%08x\n"
312 	    "\tdst %s seq %u src %s seq %u", length,
313 	    GET_U_1(ap->rreq_type) & RREQ_JOIN ? "[J]" : "",
314 	    GET_U_1(ap->rreq_type) & RREQ_REPAIR ? "[R]" : "",
315 	    GET_U_1(ap->rreq_type) & RREQ_GRAT ? "[G]" : "",
316 	    GET_U_1(ap->rreq_type) & RREQ_DEST ? "[D]" : "",
317 	    GET_U_1(ap->rreq_type) & RREQ_UNKNOWN ? "[U] " : " ",
318 	    GET_U_1(ap->rreq_hops),
319 	    GET_BE_U_4(ap->rreq_id),
320 	    GET_IP6ADDR_STRING(ap->rreq_da),
321 	    GET_BE_U_4(ap->rreq_ds),
322 	    GET_IP6ADDR_STRING(ap->rreq_oa),
323 	    GET_BE_U_4(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_trunc(ndo);
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_SIZE(ap);
340 	if (length < sizeof(*ap))
341 		goto trunc;
342 	ND_PRINT(" rrep %u %s%sprefix %u hops %u\n"
343 	   "\tdst %s dseq %u src %s %u ms", length,
344 	    GET_U_1(ap->rrep_type) & RREP_REPAIR ? "[R]" : "",
345 	    GET_U_1(ap->rrep_type) & RREP_ACK ? "[A] " : " ",
346 	    GET_U_1(ap->rrep_ps) & RREP_PREFIX_MASK,
347 	    GET_U_1(ap->rrep_hops),
348 	    GET_IP6ADDR_STRING(ap->rrep_da),
349 	    GET_BE_U_4(ap->rrep_ds),
350 	    GET_IP6ADDR_STRING(ap->rrep_oa),
351 	    GET_BE_U_4(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_trunc(ndo);
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_SIZE(ap);
369 	if (length < sizeof(*ap))
370 		goto trunc;
371 	ND_PRINT(" rerr %s [items %u] [%u]:",
372 	    GET_U_1(ap->rerr_flags) & RERR_NODELETE ? "[D]" : "",
373 	    GET_U_1(ap->rerr_dc), length);
374 	dp6 = (const struct rerr_unreach6 *)(const void *)(ap + 1);
375 	i = length - sizeof(*ap);
376 	for (dc = GET_U_1(ap->rerr_dc); dc != 0; dc--) {
377 		ND_TCHECK_SIZE(dp6);
378 		if (i < sizeof(*dp6))
379 			goto trunc;
380 		ND_PRINT(" {%s}(%u)", GET_IP6ADDR_STRING(dp6->u_da),
381 			 GET_BE_U_4(dp6->u_ds));
382 		dp6++;
383 		i -= sizeof(*dp6);
384 	}
385 	return;
386 
387 trunc:
388 	nd_print_trunc(ndo);
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_SIZE(ap);
398 	if (length < sizeof(*ap))
399 		goto trunc;
400 	ND_PRINT(" rreq %u %s%s%s%s%shops %u id 0x%08x\n"
401 	    "\tdst %s seq %u src %s seq %u", length,
402 	    GET_U_1(ap->rreq_type) & RREQ_JOIN ? "[J]" : "",
403 	    GET_U_1(ap->rreq_type) & RREQ_REPAIR ? "[R]" : "",
404 	    GET_U_1(ap->rreq_type) & RREQ_GRAT ? "[G]" : "",
405 	    GET_U_1(ap->rreq_type) & RREQ_DEST ? "[D]" : "",
406 	    GET_U_1(ap->rreq_type) & RREQ_UNKNOWN ? "[U] " : " ",
407 	    GET_U_1(ap->rreq_hops),
408 	    GET_BE_U_4(ap->rreq_id),
409 	    GET_IP6ADDR_STRING(ap->rreq_da),
410 	    GET_BE_U_4(ap->rreq_ds),
411 	    GET_IP6ADDR_STRING(ap->rreq_oa),
412 	    GET_BE_U_4(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_trunc(ndo);
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_SIZE(ap);
429 	if (length < sizeof(*ap))
430 		goto trunc;
431 	ND_PRINT(" rrep %u %s%sprefix %u hops %u\n"
432 	   "\tdst %s dseq %u src %s %u ms", length,
433 	    GET_U_1(ap->rrep_type) & RREP_REPAIR ? "[R]" : "",
434 	    GET_U_1(ap->rrep_type) & RREP_ACK ? "[A] " : " ",
435 	    GET_U_1(ap->rrep_ps) & RREP_PREFIX_MASK,
436 	    GET_U_1(ap->rrep_hops),
437 	    GET_IP6ADDR_STRING(ap->rrep_da),
438 	    GET_BE_U_4(ap->rrep_ds),
439 	    GET_IP6ADDR_STRING(ap->rrep_oa),
440 	    GET_BE_U_4(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_trunc(ndo);
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_SIZE(ap);
458 	if (length < sizeof(*ap))
459 		goto trunc;
460 	ND_PRINT(" rerr %s [items %u] [%u]:",
461 	    GET_U_1(ap->rerr_flags) & RERR_NODELETE ? "[D]" : "",
462 	    GET_U_1(ap->rerr_dc), length);
463 	dp6 = (const struct rerr_unreach6_draft_01 *)(const void *)(ap + 1);
464 	i = length - sizeof(*ap);
465 	for (dc = GET_U_1(ap->rerr_dc); dc != 0; dc--) {
466 		ND_TCHECK_SIZE(dp6);
467 		if (i < sizeof(*dp6))
468 			goto trunc;
469 		ND_PRINT(" {%s}(%u)", GET_IP6ADDR_STRING(dp6->u_da),
470 			 GET_BE_U_4(dp6->u_ds));
471 		dp6++;
472 		i -= sizeof(*dp6);
473 	}
474 	return;
475 
476 trunc:
477 	nd_print_trunc(ndo);
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 	ndo->ndo_protocol = "aodv";
487 	/*
488 	 * The message type is the first byte; make sure we have it
489 	 * and then fetch it.
490 	 */
491 	msg_type = GET_U_1(dat);
492 	ND_PRINT(" 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(" 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(" rrep-ack %u", length);
535 		break;
536 
537 	default:
538 		ND_PRINT(" type %u %u", msg_type, length);
539 	}
540 }
541