blob: c5f662237448982a8b58701a18c6c5285728a738 [file] [log] [blame]
The Android Open Source Project2949f582009-03-03 19:30:46 -08001/*
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#ifndef lint
34static const char rcsid[] _U_ =
JP Abgrall53f17a92014-02-12 14:02:41 -080035 "@(#) $Header: /tcpdump/master/tcpdump/print-aodv.c,v 1.11 2004-03-24 00:30:19 guy Exp $ (LBL)";
The Android Open Source Project2949f582009-03-03 19:30:46 -080036#endif
37
38#ifdef HAVE_CONFIG_H
39#include "config.h"
40#endif
41
42#include <tcpdump-stdinc.h>
43
44#include <stddef.h>
45#include <stdio.h>
46#include <ctype.h>
47#include <string.h>
48
49#include "interface.h"
50#include "addrtoname.h"
51#include "extract.h" /* must come after interface.h */
52
53#include "aodv.h"
54
55static void
56aodv_extension(const struct aodv_ext *ep, u_int length)
57{
58 u_int i;
59 const struct aodv_hello *ah;
60
61 switch (ep->type) {
62 case AODV_EXT_HELLO:
63 if (snapend < (u_char *) ep) {
64 printf(" [|hello]");
65 return;
66 }
67 i = min(length, (u_int)(snapend - (u_char *)ep));
68 if (i < sizeof(struct aodv_hello)) {
69 printf(" [|hello]");
70 return;
71 }
72 i -= sizeof(struct aodv_hello);
73 ah = (void *)ep;
74 printf("\n\text HELLO %ld ms",
75 (unsigned long)EXTRACT_32BITS(&ah->interval));
76 break;
77
78 default:
79 printf("\n\text %u %u", ep->type, ep->length);
80 break;
81 }
82}
83
84static void
85aodv_rreq(const union aodv *ap, const u_char *dat, u_int length)
86{
87 u_int i;
88
89 if (snapend < dat) {
90 printf(" [|aodv]");
91 return;
92 }
93 i = min(length, (u_int)(snapend - dat));
94 if (i < sizeof(ap->rreq)) {
95 printf(" [|rreq]");
96 return;
97 }
98 i -= sizeof(ap->rreq);
99 printf(" rreq %u %s%s%s%s%shops %u id 0x%08lx\n"
100 "\tdst %s seq %lu src %s seq %lu", length,
101 ap->rreq.rreq_type & RREQ_JOIN ? "[J]" : "",
102 ap->rreq.rreq_type & RREQ_REPAIR ? "[R]" : "",
103 ap->rreq.rreq_type & RREQ_GRAT ? "[G]" : "",
104 ap->rreq.rreq_type & RREQ_DEST ? "[D]" : "",
105 ap->rreq.rreq_type & RREQ_UNKNOWN ? "[U] " : " ",
106 ap->rreq.rreq_hops,
107 (unsigned long)EXTRACT_32BITS(&ap->rreq.rreq_id),
108 ipaddr_string(&ap->rreq.rreq_da),
109 (unsigned long)EXTRACT_32BITS(&ap->rreq.rreq_ds),
110 ipaddr_string(&ap->rreq.rreq_oa),
111 (unsigned long)EXTRACT_32BITS(&ap->rreq.rreq_os));
112 if (i >= sizeof(struct aodv_ext))
113 aodv_extension((void *)(&ap->rreq + 1), i);
114}
115
116static void
117aodv_rrep(const union aodv *ap, const u_char *dat, u_int length)
118{
119 u_int i;
120
121 if (snapend < dat) {
122 printf(" [|aodv]");
123 return;
124 }
125 i = min(length, (u_int)(snapend - dat));
126 if (i < sizeof(ap->rrep)) {
127 printf(" [|rrep]");
128 return;
129 }
130 i -= sizeof(ap->rrep);
131 printf(" rrep %u %s%sprefix %u hops %u\n"
132 "\tdst %s dseq %lu src %s %lu ms", length,
133 ap->rrep.rrep_type & RREP_REPAIR ? "[R]" : "",
134 ap->rrep.rrep_type & RREP_ACK ? "[A] " : " ",
135 ap->rrep.rrep_ps & RREP_PREFIX_MASK,
136 ap->rrep.rrep_hops,
137 ipaddr_string(&ap->rrep.rrep_da),
138 (unsigned long)EXTRACT_32BITS(&ap->rrep.rrep_ds),
139 ipaddr_string(&ap->rrep.rrep_oa),
140 (unsigned long)EXTRACT_32BITS(&ap->rrep.rrep_life));
141 if (i >= sizeof(struct aodv_ext))
142 aodv_extension((void *)(&ap->rrep + 1), i);
143}
144
145static void
146aodv_rerr(const union aodv *ap, const u_char *dat, u_int length)
147{
148 u_int i;
149 const struct rerr_unreach *dp = NULL;
150 int n, trunc;
151
152 if (snapend < dat) {
153 printf(" [|aodv]");
154 return;
155 }
156 i = min(length, (u_int)(snapend - dat));
157 if (i < offsetof(struct aodv_rerr, r)) {
158 printf(" [|rerr]");
159 return;
160 }
161 i -= offsetof(struct aodv_rerr, r);
162 dp = &ap->rerr.r.dest[0];
163 n = ap->rerr.rerr_dc * sizeof(ap->rerr.r.dest[0]);
164 printf(" rerr %s [items %u] [%u]:",
165 ap->rerr.rerr_flags & RERR_NODELETE ? "[D]" : "",
166 ap->rerr.rerr_dc, length);
167 trunc = n - (i/sizeof(ap->rerr.r.dest[0]));
168 for (; i >= sizeof(ap->rerr.r.dest[0]);
169 ++dp, i -= sizeof(ap->rerr.r.dest[0])) {
170 printf(" {%s}(%ld)", ipaddr_string(&dp->u_da),
171 (unsigned long)EXTRACT_32BITS(&dp->u_ds));
172 }
173 if (trunc)
174 printf("[|rerr]");
175}
176
177static void
178#ifdef INET6
179aodv_v6_rreq(const union aodv *ap, const u_char *dat, u_int length)
180#else
181aodv_v6_rreq(const union aodv *ap _U_, const u_char *dat _U_, u_int length)
182#endif
183{
184#ifdef INET6
185 u_int i;
186
187 if (snapend < dat) {
188 printf(" [|aodv]");
189 return;
190 }
191 i = min(length, (u_int)(snapend - dat));
192 if (i < sizeof(ap->rreq6)) {
193 printf(" [|rreq6]");
194 return;
195 }
196 i -= sizeof(ap->rreq6);
197 printf(" v6 rreq %u %s%s%s%s%shops %u id 0x%08lx\n"
198 "\tdst %s seq %lu src %s seq %lu", length,
199 ap->rreq6.rreq_type & RREQ_JOIN ? "[J]" : "",
200 ap->rreq6.rreq_type & RREQ_REPAIR ? "[R]" : "",
201 ap->rreq6.rreq_type & RREQ_GRAT ? "[G]" : "",
202 ap->rreq6.rreq_type & RREQ_DEST ? "[D]" : "",
203 ap->rreq6.rreq_type & RREQ_UNKNOWN ? "[U] " : " ",
204 ap->rreq6.rreq_hops,
205 (unsigned long)EXTRACT_32BITS(&ap->rreq6.rreq_id),
206 ip6addr_string(&ap->rreq6.rreq_da),
207 (unsigned long)EXTRACT_32BITS(&ap->rreq6.rreq_ds),
208 ip6addr_string(&ap->rreq6.rreq_oa),
209 (unsigned long)EXTRACT_32BITS(&ap->rreq6.rreq_os));
210 if (i >= sizeof(struct aodv_ext))
211 aodv_extension((void *)(&ap->rreq6 + 1), i);
212#else
213 printf(" v6 rreq %u", length);
214#endif
215}
216
217static void
218#ifdef INET6
219aodv_v6_rrep(const union aodv *ap, const u_char *dat, u_int length)
220#else
221aodv_v6_rrep(const union aodv *ap _U_, const u_char *dat _U_, u_int length)
222#endif
223{
224#ifdef INET6
225 u_int i;
226
227 if (snapend < dat) {
228 printf(" [|aodv]");
229 return;
230 }
231 i = min(length, (u_int)(snapend - dat));
232 if (i < sizeof(ap->rrep6)) {
233 printf(" [|rrep6]");
234 return;
235 }
236 i -= sizeof(ap->rrep6);
237 printf(" rrep %u %s%sprefix %u hops %u\n"
238 "\tdst %s dseq %lu src %s %lu ms", length,
239 ap->rrep6.rrep_type & RREP_REPAIR ? "[R]" : "",
240 ap->rrep6.rrep_type & RREP_ACK ? "[A] " : " ",
241 ap->rrep6.rrep_ps & RREP_PREFIX_MASK,
242 ap->rrep6.rrep_hops,
243 ip6addr_string(&ap->rrep6.rrep_da),
244 (unsigned long)EXTRACT_32BITS(&ap->rrep6.rrep_ds),
245 ip6addr_string(&ap->rrep6.rrep_oa),
246 (unsigned long)EXTRACT_32BITS(&ap->rrep6.rrep_life));
247 if (i >= sizeof(struct aodv_ext))
248 aodv_extension((void *)(&ap->rrep6 + 1), i);
249#else
250 printf(" rrep %u", length);
251#endif
252}
253
254static void
255#ifdef INET6
256aodv_v6_rerr(const union aodv *ap, u_int length)
257#else
258aodv_v6_rerr(const union aodv *ap _U_, u_int length)
259#endif
260{
261#ifdef INET6
262 const struct rerr_unreach6 *dp6 = NULL;
263 int i, j, n, trunc;
264
265 i = length - offsetof(struct aodv_rerr, r);
266 j = sizeof(ap->rerr.r.dest6[0]);
267 dp6 = &ap->rerr.r.dest6[0];
268 n = ap->rerr.rerr_dc * j;
269 printf(" rerr %s [items %u] [%u]:",
270 ap->rerr.rerr_flags & RERR_NODELETE ? "[D]" : "",
271 ap->rerr.rerr_dc, length);
272 trunc = n - (i/j);
273 for (; i -= j >= 0; ++dp6) {
274 printf(" {%s}(%ld)", ip6addr_string(&dp6->u_da),
275 (unsigned long)EXTRACT_32BITS(&dp6->u_ds));
276 }
277 if (trunc)
278 printf("[|rerr]");
279#else
280 printf(" rerr %u", length);
281#endif
282}
283
284static void
285#ifdef INET6
286aodv_v6_draft_01_rreq(const union aodv *ap, const u_char *dat, u_int length)
287#else
288aodv_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}