print-aodv.c revision 127668
1139749Simp/*
2137821Smarius * Copyright (c) 2003 Bruce M. Simpson <bms@spc.org>
3137821Smarius * All rights reserved.
4137821Smarius *
5137821Smarius * Redistribution and use in source and binary forms, with or without
6137821Smarius * modification, are permitted provided that the following conditions
7137821Smarius * are met:
8137821Smarius * 1. Redistributions of source code must retain the above copyright
9137821Smarius *    notice, this list of conditions and the following disclaimer.
10137821Smarius * 2. Redistributions in binary form must reproduce the above copyright
11137821Smarius *    notice, this list of conditions and the following disclaimer in the
12137821Smarius *    documentation and/or other materials provided with the distribution.
13137821Smarius * 3. All advertising materials mentioning features or use of this software
14137821Smarius *    must display the following acknowledgement:
15137821Smarius *        This product includes software developed by Bruce M. Simpson.
16137821Smarius * 4. Neither the name of Bruce M. Simpson nor the names of co-
17137821Smarius *    contributors may be used to endorse or promote products derived
18137821Smarius *    from this software without specific prior written permission.
19137821Smarius *
20137821Smarius * THIS SOFTWARE IS PROVIDED BY Bruce M. Simpson AND CONTRIBUTORS
21137821Smarius * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22137821Smarius * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23137821Smarius * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL Bruce M. Simpson OR CONTRIBUTORS
24201009Smarius * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25137821Smarius * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26137821Smarius * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27137821Smarius * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28137821Smarius * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29137821Smarius * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30137821Smarius * POSSIBILITY OF SUCH DAMAGE.
31137821Smarius */
32137821Smarius
33137821Smarius#ifndef lint
34137821Smariusstatic const char rcsid[] _U_ =
35137821Smarius    "@(#) $Header: /tcpdump/master/tcpdump/print-aodv.c,v 1.8.2.3 2004/03/24 00:30:41 guy Exp $ (LBL)";
36137821Smarius#endif
37137821Smarius
38146417Smarius#ifdef HAVE_CONFIG_H
39146417Smarius#include "config.h"
40137821Smarius#endif
41137821Smarius
42137821Smarius#include <tcpdump-stdinc.h>
43137821Smarius
44137821Smarius#include <stddef.h>
45137821Smarius#include <stdio.h>
46137821Smarius#include <ctype.h>
47137821Smarius#include <string.h>
48137821Smarius
49137821Smarius#include "interface.h"
50137821Smarius#include "addrtoname.h"
51137821Smarius#include "extract.h"			/* must come after interface.h */
52137821Smarius
53137821Smarius#include "aodv.h"
54137821Smarius
55137821Smariusstatic void
56137821Smariusaodv_extension(const struct aodv_ext *ep, u_int length)
57137821Smarius{
58146417Smarius	u_int i;
59146417Smarius	const struct aodv_hello *ah;
60146417Smarius
61146417Smarius	switch (ep->type) {
62146417Smarius	case AODV_EXT_HELLO:
63137821Smarius		if (snapend < (u_char *) ep) {
64137821Smarius			printf(" [|hello]");
65137821Smarius			return;
66137821Smarius		}
67137821Smarius		i = min(length, (u_int)(snapend - (u_char *)ep));
68137821Smarius		if (i < sizeof(struct aodv_hello)) {
69137821Smarius			printf(" [|hello]");
70137821Smarius			return;
71137821Smarius		}
72137821Smarius		i -= sizeof(struct aodv_hello);
73137821Smarius		ah = (void *)ep;
74137821Smarius		printf("\n\text HELLO %ld ms",
75137821Smarius		    (unsigned long)EXTRACT_32BITS(&ah->interval));
76137821Smarius		break;
77137821Smarius
78137821Smarius	default:
79146982Smarius		printf("\n\text %u %u", ep->type, ep->length);
80137821Smarius		break;
81146982Smarius	}
82146417Smarius}
83137821Smarius
84137821Smariusstatic void
85137821Smariusaodv_rreq(const union aodv *ap, const u_char *dat, u_int length)
86137821Smarius{
87137821Smarius	u_int i;
88137821Smarius
89137821Smarius	if (snapend < dat) {
90137821Smarius		printf(" [|aodv]");
91137821Smarius		return;
92137821Smarius	}
93146982Smarius	i = min(length, (u_int)(snapend - dat));
94137821Smarius	if (i < sizeof(ap->rreq)) {
95201008Smarius		printf(" [|rreq]");
96137821Smarius		return;
97137821Smarius	}
98137821Smarius	i -= sizeof(ap->rreq);
99137821Smarius	printf(" rreq %u %s%s%s%s%shops %u id 0x%08lx\n"
100137821Smarius	    "\tdst %s seq %lu src %s seq %lu", length,
101137821Smarius	    ap->rreq.rreq_type & RREQ_JOIN ? "[J]" : "",
102137821Smarius	    ap->rreq.rreq_type & RREQ_REPAIR ? "[R]" : "",
103137821Smarius	    ap->rreq.rreq_type & RREQ_GRAT ? "[G]" : "",
104137821Smarius	    ap->rreq.rreq_type & RREQ_DEST ? "[D]" : "",
105137821Smarius	    ap->rreq.rreq_type & RREQ_UNKNOWN ? "[U] " : " ",
106137821Smarius	    ap->rreq.rreq_hops,
107137821Smarius	    (unsigned long)EXTRACT_32BITS(&ap->rreq.rreq_id),
108137821Smarius	    ipaddr_string(&ap->rreq.rreq_da),
109137821Smarius	    (unsigned long)EXTRACT_32BITS(&ap->rreq.rreq_ds),
110137821Smarius	    ipaddr_string(&ap->rreq.rreq_oa),
111137821Smarius	    (unsigned long)EXTRACT_32BITS(&ap->rreq.rreq_os));
112137821Smarius	if (i >= sizeof(struct aodv_ext))
113137821Smarius		aodv_extension((void *)(&ap->rreq + 1), i);
114137821Smarius}
115137821Smarius
116137821Smariusstatic void
117201008Smariusaodv_rrep(const union aodv *ap, const u_char *dat, u_int length)
118137821Smarius{
119137821Smarius	u_int i;
120146982Smarius
121137821Smarius	if (snapend < dat) {
122137821Smarius		printf(" [|aodv]");
123146982Smarius		return;
124137821Smarius	}
125146417Smarius	i = min(length, (u_int)(snapend - dat));
126137821Smarius	if (i < sizeof(ap->rrep)) {
127137821Smarius		printf(" [|rrep]");
128137821Smarius		return;
129137821Smarius	}
130137821Smarius	i -= sizeof(ap->rrep);
131137821Smarius	printf(" rrep %u %s%sprefix %u hops %u\n"
132137821Smarius	    "\tdst %s dseq %lu src %s %lu ms", length,
133137821Smarius	    ap->rrep.rrep_type & RREP_REPAIR ? "[R]" : "",
134137821Smarius	    ap->rrep.rrep_type & RREP_ACK ? "[A] " : " ",
135137821Smarius	    ap->rrep.rrep_ps & RREP_PREFIX_MASK,
136146417Smarius	    ap->rrep.rrep_hops,
137137821Smarius	    ipaddr_string(&ap->rrep.rrep_da),
138137821Smarius	    (unsigned long)EXTRACT_32BITS(&ap->rrep.rrep_ds),
139137821Smarius	    ipaddr_string(&ap->rrep.rrep_oa),
140137821Smarius	    (unsigned long)EXTRACT_32BITS(&ap->rrep.rrep_life));
141146417Smarius	if (i >= sizeof(struct aodv_ext))
142146417Smarius		aodv_extension((void *)(&ap->rrep + 1), i);
143137821Smarius}
144137821Smarius
145146417Smariusstatic void
146146417Smariusaodv_rerr(const union aodv *ap, const u_char *dat, u_int length)
147146982Smarius{
148137821Smarius	u_int i;
149137821Smarius	const struct rerr_unreach *dp = NULL;
150137821Smarius	int n, trunc;
151137821Smarius
152137821Smarius	if (snapend < dat) {
153137821Smarius		printf(" [|aodv]");
154137821Smarius		return;
155137821Smarius	}
156137821Smarius	i = min(length, (u_int)(snapend - dat));
157137821Smarius	if (i < offsetof(struct aodv_rerr, r)) {
158137821Smarius		printf(" [|rerr]");
159137821Smarius		return;
160137821Smarius	}
161137821Smarius	i -= offsetof(struct aodv_rerr, r);
162137821Smarius	dp = &ap->rerr.r.dest[0];
163137821Smarius	n = ap->rerr.rerr_dc * sizeof(ap->rerr.r.dest[0]);
164137821Smarius	printf(" rerr %s [items %u] [%u]:",
165137821Smarius	    ap->rerr.rerr_flags & RERR_NODELETE ? "[D]" : "",
166146982Smarius	    ap->rerr.rerr_dc, length);
167137821Smarius	trunc = n - (i/sizeof(ap->rerr.r.dest[0]));
168137821Smarius	for (; i >= sizeof(ap->rerr.r.dest[0]);
169146982Smarius	    ++dp, i -= sizeof(ap->rerr.r.dest[0])) {
170137821Smarius		printf(" {%s}(%ld)", ipaddr_string(&dp->u_da),
171137821Smarius		    (unsigned long)EXTRACT_32BITS(&dp->u_ds));
172146982Smarius	}
173137821Smarius	if (trunc)
174146417Smarius		printf("[|rerr]");
175137821Smarius}
176137821Smarius
177137821Smariusstatic void
178137821Smarius#ifdef INET6
179137821Smariusaodv_v6_rreq(const union aodv *ap, const u_char *dat, u_int length)
180137821Smarius#else
181137821Smariusaodv_v6_rreq(const union aodv *ap _U_, const u_char *dat _U_, u_int length)
182137821Smarius#endif
183137821Smarius{
184137821Smarius#ifdef INET6
185137821Smarius	u_int i;
186137821Smarius
187137821Smarius	if (snapend < dat) {
188137821Smarius		printf(" [|aodv]");
189137821Smarius		return;
190137821Smarius	}
191137821Smarius	i = min(length, (u_int)(snapend - dat));
192137821Smarius	if (i < sizeof(ap->rreq6)) {
193137821Smarius		printf(" [|rreq6]");
194137821Smarius		return;
195137821Smarius	}
196137821Smarius	i -= sizeof(ap->rreq6);
197137821Smarius	printf(" v6 rreq %u %s%s%s%s%shops %u id 0x%08lx\n"
198137821Smarius	    "\tdst %s seq %lu src %s seq %lu", length,
199137821Smarius	    ap->rreq6.rreq_type & RREQ_JOIN ? "[J]" : "",
200137821Smarius	    ap->rreq6.rreq_type & RREQ_REPAIR ? "[R]" : "",
201137821Smarius	    ap->rreq6.rreq_type & RREQ_GRAT ? "[G]" : "",
202137821Smarius	    ap->rreq6.rreq_type & RREQ_DEST ? "[D]" : "",
203137821Smarius	    ap->rreq6.rreq_type & RREQ_UNKNOWN ? "[U] " : " ",
204137821Smarius	    ap->rreq6.rreq_hops,
205146982Smarius	    (unsigned long)EXTRACT_32BITS(&ap->rreq6.rreq_id),
206137821Smarius	    ip6addr_string(&ap->rreq6.rreq_da),
207137821Smarius	    (unsigned long)EXTRACT_32BITS(&ap->rreq6.rreq_ds),
208137821Smarius	    ip6addr_string(&ap->rreq6.rreq_oa),
209137821Smarius	    (unsigned long)EXTRACT_32BITS(&ap->rreq6.rreq_os));
210137821Smarius	if (i >= sizeof(struct aodv_ext))
211137821Smarius		aodv_extension((void *)(&ap->rreq6 + 1), i);
212137821Smarius#else
213137821Smarius	printf(" v6 rreq %u", length);
214137821Smarius#endif
215146417Smarius}
216137821Smarius
217137821Smariusstatic void
218137821Smarius#ifdef INET6
219137821Smariusaodv_v6_rrep(const union aodv *ap, const u_char *dat, u_int length)
220137821Smarius#else
221146417Smariusaodv_v6_rrep(const union aodv *ap _U_, const u_char *dat _U_, u_int length)
222137821Smarius#endif
223137821Smarius{
224137821Smarius#ifdef INET6
225146417Smarius	u_int i;
226137821Smarius
227137821Smarius	if (snapend < dat) {
228137821Smarius		printf(" [|aodv]");
229137821Smarius		return;
230137821Smarius	}
231146982Smarius	i = min(length, (u_int)(snapend - dat));
232137821Smarius	if (i < sizeof(ap->rrep6)) {
233137821Smarius		printf(" [|rrep6]");
234137821Smarius		return;
235137821Smarius	}
236137821Smarius	i -= sizeof(ap->rrep6);
237137821Smarius	printf(" rrep %u %s%sprefix %u hops %u\n"
238137821Smarius	   "\tdst %s dseq %lu src %s %lu ms", length,
239137821Smarius	    ap->rrep6.rrep_type & RREP_REPAIR ? "[R]" : "",
240137821Smarius	    ap->rrep6.rrep_type & RREP_ACK ? "[A] " : " ",
241170844Smarius	    ap->rrep6.rrep_ps & RREP_PREFIX_MASK,
242137821Smarius	    ap->rrep6.rrep_hops,
243137821Smarius	    ip6addr_string(&ap->rrep6.rrep_da),
244137821Smarius	    (unsigned long)EXTRACT_32BITS(&ap->rrep6.rrep_ds),
245137821Smarius	    ip6addr_string(&ap->rrep6.rrep_oa),
246137821Smarius	    (unsigned long)EXTRACT_32BITS(&ap->rrep6.rrep_life));
247137821Smarius	if (i >= sizeof(struct aodv_ext))
248137821Smarius		aodv_extension((void *)(&ap->rrep6 + 1), i);
249137821Smarius#else
250137821Smarius	printf(" rrep %u", length);
251170844Smarius#endif
252137821Smarius}
253137821Smarius
254137821Smariusstatic void
255137821Smarius#ifdef INET6
256137821Smariusaodv_v6_rerr(const union aodv *ap, u_int length)
257137821Smarius#else
258137821Smariusaodv_v6_rerr(const union aodv *ap _U_, u_int length)
259137821Smarius#endif
260137821Smarius{
261201008Smarius#ifdef INET6
262201008Smarius	const struct rerr_unreach6 *dp6 = NULL;
263201008Smarius	int i, j, n, trunc;
264137821Smarius
265137821Smarius	i = length - offsetof(struct aodv_rerr, r);
266137821Smarius	j = sizeof(ap->rerr.r.dest6[0]);
267137821Smarius	dp6 = &ap->rerr.r.dest6[0];
268137821Smarius	n = ap->rerr.rerr_dc * j;
269137821Smarius	printf(" rerr %s [items %u] [%u]:",
270137821Smarius	    ap->rerr.rerr_flags & RERR_NODELETE ? "[D]" : "",
271137821Smarius	    ap->rerr.rerr_dc, length);
272137821Smarius	trunc = n - (i/j);
273137821Smarius	for (; i -= j >= 0; ++dp6) {
274137821Smarius		printf(" {%s}(%ld)", ip6addr_string(&dp6->u_da),
275137821Smarius		    (unsigned long)EXTRACT_32BITS(&dp6->u_ds));
276137821Smarius	}
277137821Smarius	if (trunc)
278137821Smarius		printf("[|rerr]");
279137821Smarius#else
280137821Smarius	printf(" rerr %u", length);
281137821Smarius#endif
282137821Smarius}
283137821Smarius
284137821Smariusstatic void
285137821Smarius#ifdef INET6
286137821Smariusaodv_v6_draft_01_rreq(const union aodv *ap, const u_char *dat, u_int length)
287201008Smarius#else
288201008Smariusaodv_v6_draft_01_rreq(const union aodv *ap _U_, const u_char *dat _U_,
289    u_int length)
290#endif
291{
292#ifdef INET6
293	u_int i;
294
295	if (snapend < dat) {
296		printf(" [|aodv]");
297		return;
298	}
299	i = min(length, (u_int)(snapend - dat));
300	if (i < sizeof(ap->rreq6_draft_01)) {
301		printf(" [|rreq6]");
302		return;
303	}
304	i -= sizeof(ap->rreq6_draft_01);
305	printf(" rreq %u %s%s%s%s%shops %u id 0x%08lx\n"
306	    "\tdst %s seq %lu src %s seq %lu", length,
307	    ap->rreq6_draft_01.rreq_type & RREQ_JOIN ? "[J]" : "",
308	    ap->rreq6_draft_01.rreq_type & RREQ_REPAIR ? "[R]" : "",
309	    ap->rreq6_draft_01.rreq_type & RREQ_GRAT ? "[G]" : "",
310	    ap->rreq6_draft_01.rreq_type & RREQ_DEST ? "[D]" : "",
311	    ap->rreq6_draft_01.rreq_type & RREQ_UNKNOWN ? "[U] " : " ",
312	    ap->rreq6_draft_01.rreq_hops,
313	    (unsigned long)EXTRACT_32BITS(&ap->rreq6_draft_01.rreq_id),
314	    ip6addr_string(&ap->rreq6_draft_01.rreq_da),
315	    (unsigned long)EXTRACT_32BITS(&ap->rreq6_draft_01.rreq_ds),
316	    ip6addr_string(&ap->rreq6_draft_01.rreq_oa),
317	    (unsigned long)EXTRACT_32BITS(&ap->rreq6_draft_01.rreq_os));
318	if (i >= sizeof(struct aodv_ext))
319		aodv_extension((void *)(&ap->rreq6_draft_01 + 1), i);
320#else
321	printf(" rreq %u", length);
322#endif
323}
324
325static void
326#ifdef INET6
327aodv_v6_draft_01_rrep(const union aodv *ap, const u_char *dat, u_int length)
328#else
329aodv_v6_draft_01_rrep(const union aodv *ap _U_, const u_char *dat _U_,
330    u_int length)
331#endif
332{
333#ifdef INET6
334	u_int i;
335
336	if (snapend < dat) {
337		printf(" [|aodv]");
338		return;
339	}
340	i = min(length, (u_int)(snapend - dat));
341	if (i < sizeof(ap->rrep6_draft_01)) {
342		printf(" [|rrep6]");
343		return;
344	}
345	i -= sizeof(ap->rrep6_draft_01);
346	printf(" rrep %u %s%sprefix %u hops %u\n"
347	   "\tdst %s dseq %lu src %s %lu ms", length,
348	    ap->rrep6_draft_01.rrep_type & RREP_REPAIR ? "[R]" : "",
349	    ap->rrep6_draft_01.rrep_type & RREP_ACK ? "[A] " : " ",
350	    ap->rrep6_draft_01.rrep_ps & RREP_PREFIX_MASK,
351	    ap->rrep6_draft_01.rrep_hops,
352	    ip6addr_string(&ap->rrep6_draft_01.rrep_da),
353	    (unsigned long)EXTRACT_32BITS(&ap->rrep6_draft_01.rrep_ds),
354	    ip6addr_string(&ap->rrep6_draft_01.rrep_oa),
355	    (unsigned long)EXTRACT_32BITS(&ap->rrep6_draft_01.rrep_life));
356	if (i >= sizeof(struct aodv_ext))
357		aodv_extension((void *)(&ap->rrep6_draft_01 + 1), i);
358#else
359	printf(" rrep %u", length);
360#endif
361}
362
363static void
364#ifdef INET6
365aodv_v6_draft_01_rerr(const union aodv *ap, u_int length)
366#else
367aodv_v6_draft_01_rerr(const union aodv *ap _U_, u_int length)
368#endif
369{
370#ifdef INET6
371	const struct rerr_unreach6_draft_01 *dp6 = NULL;
372	int i, j, n, trunc;
373
374	i = length - offsetof(struct aodv_rerr, r);
375	j = sizeof(ap->rerr.r.dest6_draft_01[0]);
376	dp6 = &ap->rerr.r.dest6_draft_01[0];
377	n = ap->rerr.rerr_dc * j;
378	printf(" rerr %s [items %u] [%u]:",
379	    ap->rerr.rerr_flags & RERR_NODELETE ? "[D]" : "",
380	    ap->rerr.rerr_dc, length);
381	trunc = n - (i/j);
382	for (; i -= j >= 0; ++dp6) {
383		printf(" {%s}(%ld)", ip6addr_string(&dp6->u_da),
384		    (unsigned long)EXTRACT_32BITS(&dp6->u_ds));
385	}
386	if (trunc)
387		printf("[|rerr]");
388#else
389	printf(" rerr %u", length);
390#endif
391}
392
393void
394aodv_print(const u_char *dat, u_int length, int is_ip6)
395{
396	const union aodv *ap;
397
398	ap = (union aodv *)dat;
399	if (snapend < dat) {
400		printf(" [|aodv]");
401		return;
402	}
403	if (min(length, (u_int)(snapend - dat)) < sizeof(ap->rrep_ack)) {
404		printf(" [|aodv]");
405		return;
406	}
407	printf(" aodv");
408
409	switch (ap->rerr.rerr_type) {
410
411	case AODV_RREQ:
412		if (is_ip6)
413			aodv_v6_rreq(ap, dat, length);
414		else
415			aodv_rreq(ap, dat, length);
416		break;
417
418	case AODV_RREP:
419		if (is_ip6)
420			aodv_v6_rrep(ap, dat, length);
421		else
422			aodv_rrep(ap, dat, length);
423		break;
424
425	case AODV_RERR:
426		if (is_ip6)
427			aodv_v6_rerr(ap, length);
428		else
429			aodv_rerr(ap, dat, length);
430		break;
431
432	case AODV_RREP_ACK:
433		printf(" rrep-ack %u", length);
434		break;
435
436	case AODV_V6_DRAFT_01_RREQ:
437		aodv_v6_draft_01_rreq(ap, dat, length);
438		break;
439
440	case AODV_V6_DRAFT_01_RREP:
441		aodv_v6_draft_01_rrep(ap, dat, length);
442		break;
443
444	case AODV_V6_DRAFT_01_RERR:
445		aodv_v6_draft_01_rerr(ap, length);
446		break;
447
448	case AODV_V6_DRAFT_01_RREP_ACK:
449		printf(" rrep-ack %u", length);
450		break;
451
452	default:
453		printf(" %u %u", ap->rreq.rreq_type, length);
454	}
455}
456