]> The Tcpdump Group git mirrors - tcpdump/blob - print-aodv.c
Add support for Apple's IP-over-IEEE 1394 encapsulation.
[tcpdump] / print-aodv.c
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 #ifndef lint
34 static const char rcsid[] _U_ =
35 "@(#) $Header: /tcpdump/master/tcpdump/print-aodv.c,v 1.8.2.2 2003-11-16 08:51:09 guy Exp $ (LBL)";
36 #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
55 static void
56 aodv_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
84 static void
85 aodv_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
116 static void
117 aodv_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
145 static void
146 aodv_rerr(const union aodv *ap, u_int length)
147 {
148 const struct rerr_unreach *dp = NULL;
149 int i, j, n, trunc;
150
151 i = length - offsetof(struct aodv_rerr, r);
152 j = sizeof(ap->rerr.r.dest[0]);
153 dp = &ap->rerr.r.dest[0];
154 n = ap->rerr.rerr_dc * j;
155 printf(" rerr %s [items %u] [%u]:",
156 ap->rerr.rerr_flags & RERR_NODELETE ? "[D]" : "",
157 ap->rerr.rerr_dc, length);
158 trunc = n - (i/j);
159 for (; i -= j >= 0; ++dp) {
160 printf(" {%s}(%ld)", ipaddr_string(&dp->u_da),
161 (unsigned long)EXTRACT_32BITS(&dp->u_ds));
162 }
163 if (trunc)
164 printf("[|rerr]");
165 }
166
167 static void
168 #ifdef INET6
169 aodv_v6_rreq(const union aodv *ap, const u_char *dat, u_int length)
170 #else
171 aodv_v6_rreq(const union aodv *ap _U_, const u_char *dat _U_, u_int length)
172 #endif
173 {
174 #ifdef INET6
175 u_int i;
176
177 if (snapend < dat) {
178 printf(" [|aodv]");
179 return;
180 }
181 i = min(length, (u_int)(snapend - dat));
182 if (i < sizeof(ap->rreq6)) {
183 printf(" [|rreq6]");
184 return;
185 }
186 i -= sizeof(ap->rreq6);
187 printf(" v6 rreq %u %s%s%s%s%shops %u id 0x%08lx\n"
188 "\tdst %s seq %lu src %s seq %lu", length,
189 ap->rreq6.rreq_type & RREQ_JOIN ? "[J]" : "",
190 ap->rreq6.rreq_type & RREQ_REPAIR ? "[R]" : "",
191 ap->rreq6.rreq_type & RREQ_GRAT ? "[G]" : "",
192 ap->rreq6.rreq_type & RREQ_DEST ? "[D]" : "",
193 ap->rreq6.rreq_type & RREQ_UNKNOWN ? "[U] " : " ",
194 ap->rreq6.rreq_hops,
195 (unsigned long)EXTRACT_32BITS(&ap->rreq6.rreq_id),
196 ip6addr_string(&ap->rreq6.rreq_da),
197 (unsigned long)EXTRACT_32BITS(&ap->rreq6.rreq_ds),
198 ip6addr_string(&ap->rreq6.rreq_oa),
199 (unsigned long)EXTRACT_32BITS(&ap->rreq6.rreq_os));
200 if (i >= sizeof(struct aodv_ext))
201 aodv_extension((void *)(&ap->rreq6 + 1), i);
202 #else
203 printf(" v6 rreq %u", length);
204 #endif
205 }
206
207 static void
208 #ifdef INET6
209 aodv_v6_rrep(const union aodv *ap, const u_char *dat, u_int length)
210 #else
211 aodv_v6_rrep(const union aodv *ap _U_, const u_char *dat _U_, u_int length)
212 #endif
213 {
214 #ifdef INET6
215 u_int i;
216
217 if (snapend < dat) {
218 printf(" [|aodv]");
219 return;
220 }
221 i = min(length, (u_int)(snapend - dat));
222 if (i < sizeof(ap->rrep6)) {
223 printf(" [|rrep6]");
224 return;
225 }
226 i -= sizeof(ap->rrep6);
227 printf(" rrep %u %s%sprefix %u hops %u\n"
228 "\tdst %s dseq %lu src %s %lu ms", length,
229 ap->rrep6.rrep_type & RREP_REPAIR ? "[R]" : "",
230 ap->rrep6.rrep_type & RREP_ACK ? "[A] " : " ",
231 ap->rrep6.rrep_ps & RREP_PREFIX_MASK,
232 ap->rrep6.rrep_hops,
233 ip6addr_string(&ap->rrep6.rrep_da),
234 (unsigned long)EXTRACT_32BITS(&ap->rrep6.rrep_ds),
235 ip6addr_string(&ap->rrep6.rrep_oa),
236 (unsigned long)EXTRACT_32BITS(&ap->rrep6.rrep_life));
237 if (i >= sizeof(struct aodv_ext))
238 aodv_extension((void *)(&ap->rrep6 + 1), i);
239 #else
240 printf(" rrep %u", length);
241 #endif
242 }
243
244 static void
245 #ifdef INET6
246 aodv_v6_rerr(const union aodv *ap, u_int length)
247 #else
248 aodv_v6_rerr(const union aodv *ap _U_, u_int length)
249 #endif
250 {
251 #ifdef INET6
252 const struct rerr_unreach6 *dp6 = NULL;
253 int i, j, n, trunc;
254
255 i = length - offsetof(struct aodv_rerr, r);
256 j = sizeof(ap->rerr.r.dest6[0]);
257 dp6 = &ap->rerr.r.dest6[0];
258 n = ap->rerr.rerr_dc * j;
259 printf(" rerr %s [items %u] [%u]:",
260 ap->rerr.rerr_flags & RERR_NODELETE ? "[D]" : "",
261 ap->rerr.rerr_dc, length);
262 trunc = n - (i/j);
263 for (; i -= j >= 0; ++dp6) {
264 printf(" {%s}(%ld)", ip6addr_string(&dp6->u_da),
265 (unsigned long)EXTRACT_32BITS(&dp6->u_ds));
266 }
267 if (trunc)
268 printf("[|rerr]");
269 #else
270 printf(" rerr %u", length);
271 #endif
272 }
273
274 static void
275 #ifdef INET6
276 aodv_v6_draft_01_rreq(const union aodv *ap, const u_char *dat, u_int length)
277 #else
278 aodv_v6_draft_01_rreq(const union aodv *ap _U_, const u_char *dat _U_,
279 u_int length)
280 #endif
281 {
282 #ifdef INET6
283 u_int i;
284
285 if (snapend < dat) {
286 printf(" [|aodv]");
287 return;
288 }
289 i = min(length, (u_int)(snapend - dat));
290 if (i < sizeof(ap->rreq6_draft_01)) {
291 printf(" [|rreq6]");
292 return;
293 }
294 i -= sizeof(ap->rreq6_draft_01);
295 printf(" rreq %u %s%s%s%s%shops %u id 0x%08lx\n"
296 "\tdst %s seq %lu src %s seq %lu", length,
297 ap->rreq6_draft_01.rreq_type & RREQ_JOIN ? "[J]" : "",
298 ap->rreq6_draft_01.rreq_type & RREQ_REPAIR ? "[R]" : "",
299 ap->rreq6_draft_01.rreq_type & RREQ_GRAT ? "[G]" : "",
300 ap->rreq6_draft_01.rreq_type & RREQ_DEST ? "[D]" : "",
301 ap->rreq6_draft_01.rreq_type & RREQ_UNKNOWN ? "[U] " : " ",
302 ap->rreq6_draft_01.rreq_hops,
303 (unsigned long)EXTRACT_32BITS(&ap->rreq6_draft_01.rreq_id),
304 ip6addr_string(&ap->rreq6_draft_01.rreq_da),
305 (unsigned long)EXTRACT_32BITS(&ap->rreq6_draft_01.rreq_ds),
306 ip6addr_string(&ap->rreq6_draft_01.rreq_oa),
307 (unsigned long)EXTRACT_32BITS(&ap->rreq6_draft_01.rreq_os));
308 if (i >= sizeof(struct aodv_ext))
309 aodv_extension((void *)(&ap->rreq6_draft_01 + 1), i);
310 #else
311 printf(" rreq %u", length);
312 #endif
313 }
314
315 static void
316 #ifdef INET6
317 aodv_v6_draft_01_rrep(const union aodv *ap, const u_char *dat, u_int length)
318 #else
319 aodv_v6_draft_01_rrep(const union aodv *ap _U_, const u_char *dat _U_,
320 u_int length)
321 #endif
322 {
323 #ifdef INET6
324 u_int i;
325
326 if (snapend < dat) {
327 printf(" [|aodv]");
328 return;
329 }
330 i = min(length, (u_int)(snapend - dat));
331 if (i < sizeof(ap->rrep6_draft_01)) {
332 printf(" [|rrep6]");
333 return;
334 }
335 i -= sizeof(ap->rrep6_draft_01);
336 printf(" rrep %u %s%sprefix %u hops %u\n"
337 "\tdst %s dseq %lu src %s %lu ms", length,
338 ap->rrep6_draft_01.rrep_type & RREP_REPAIR ? "[R]" : "",
339 ap->rrep6_draft_01.rrep_type & RREP_ACK ? "[A] " : " ",
340 ap->rrep6_draft_01.rrep_ps & RREP_PREFIX_MASK,
341 ap->rrep6_draft_01.rrep_hops,
342 ip6addr_string(&ap->rrep6_draft_01.rrep_da),
343 (unsigned long)EXTRACT_32BITS(&ap->rrep6_draft_01.rrep_ds),
344 ip6addr_string(&ap->rrep6_draft_01.rrep_oa),
345 (unsigned long)EXTRACT_32BITS(&ap->rrep6_draft_01.rrep_life));
346 if (i >= sizeof(struct aodv_ext))
347 aodv_extension((void *)(&ap->rrep6_draft_01 + 1), i);
348 #else
349 printf(" rrep %u", length);
350 #endif
351 }
352
353 static void
354 #ifdef INET6
355 aodv_v6_draft_01_rerr(const union aodv *ap, u_int length)
356 #else
357 aodv_v6_draft_01_rerr(const union aodv *ap _U_, u_int length)
358 #endif
359 {
360 #ifdef INET6
361 const struct rerr_unreach6_draft_01 *dp6 = NULL;
362 int i, j, n, trunc;
363
364 i = length - offsetof(struct aodv_rerr, r);
365 j = sizeof(ap->rerr.r.dest6_draft_01[0]);
366 dp6 = &ap->rerr.r.dest6_draft_01[0];
367 n = ap->rerr.rerr_dc * j;
368 printf(" rerr %s [items %u] [%u]:",
369 ap->rerr.rerr_flags & RERR_NODELETE ? "[D]" : "",
370 ap->rerr.rerr_dc, length);
371 trunc = n - (i/j);
372 for (; i -= j >= 0; ++dp6) {
373 printf(" {%s}(%ld)", ip6addr_string(&dp6->u_da),
374 (unsigned long)EXTRACT_32BITS(&dp6->u_ds));
375 }
376 if (trunc)
377 printf("[|rerr]");
378 #else
379 printf(" rerr %u", length);
380 #endif
381 }
382
383 void
384 aodv_print(const u_char *dat, u_int length, int is_ip6)
385 {
386 const union aodv *ap;
387
388 ap = (union aodv *)dat;
389 if (snapend < dat) {
390 printf(" [|aodv]");
391 return;
392 }
393 if (min(length, (u_int)(snapend - dat)) < sizeof(ap->rrep_ack)) {
394 printf(" [|aodv]");
395 return;
396 }
397 printf(" aodv");
398
399 switch (ap->rerr.rerr_type) {
400
401 case AODV_RREQ:
402 if (is_ip6)
403 aodv_v6_rreq(ap, dat, length);
404 else
405 aodv_rreq(ap, dat, length);
406 break;
407
408 case AODV_RREP:
409 if (is_ip6)
410 aodv_v6_rrep(ap, dat, length);
411 else
412 aodv_rrep(ap, dat, length);
413 break;
414
415 case AODV_RERR:
416 if (is_ip6)
417 aodv_v6_rerr(ap, length);
418 else
419 aodv_rerr(ap, length);
420 break;
421
422 case AODV_RREP_ACK:
423 printf(" rrep-ack %u", length);
424 break;
425
426 case AODV_V6_DRAFT_01_RREQ:
427 aodv_v6_draft_01_rreq(ap, dat, length);
428 break;
429
430 case AODV_V6_DRAFT_01_RREP:
431 aodv_v6_draft_01_rrep(ap, dat, length);
432 break;
433
434 case AODV_V6_DRAFT_01_RERR:
435 aodv_v6_draft_01_rerr(ap, length);
436 break;
437
438 case AODV_V6_DRAFT_01_RREP_ACK:
439 printf(" rrep-ack %u", length);
440 break;
441
442 default:
443 printf(" %u %u", ap->rreq.rreq_type, length);
444 }
445 }