]> The Tcpdump Group git mirrors - tcpdump/blob - print-aodv.c
e0a1952fd7f5cae7ff9c28c33eb5fae63f1f680c
[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.11 2004-03-24 00:30:19 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 const struct aodv_hello *ah;
59
60 switch (ep->type) {
61 case AODV_EXT_HELLO:
62 ah = (const struct aodv_hello *)(const void *)ep;
63 TCHECK(*ah);
64 if (length < sizeof(struct aodv_hello))
65 goto trunc;
66 printf("\n\text HELLO %ld ms",
67 (unsigned long)EXTRACT_32BITS(&ah->interval));
68 break;
69
70 default:
71 printf("\n\text %u %u", ep->type, ep->length);
72 break;
73 }
74 return;
75
76 trunc:
77 printf(" [|hello]");
78 }
79
80 static void
81 aodv_rreq(const u_char *dat, u_int length)
82 {
83 u_int i;
84 const struct aodv_rreq *ap = (const struct aodv_rreq *)dat;
85
86 TCHECK(*ap);
87 if (length < sizeof(*ap))
88 goto trunc;
89 printf(" rreq %u %s%s%s%s%shops %u id 0x%08lx\n"
90 "\tdst %s seq %lu src %s seq %lu", length,
91 ap->rreq_type & RREQ_JOIN ? "[J]" : "",
92 ap->rreq_type & RREQ_REPAIR ? "[R]" : "",
93 ap->rreq_type & RREQ_GRAT ? "[G]" : "",
94 ap->rreq_type & RREQ_DEST ? "[D]" : "",
95 ap->rreq_type & RREQ_UNKNOWN ? "[U] " : " ",
96 ap->rreq_hops,
97 (unsigned long)EXTRACT_32BITS(&ap->rreq_id),
98 ipaddr_string(&ap->rreq_da),
99 (unsigned long)EXTRACT_32BITS(&ap->rreq_ds),
100 ipaddr_string(&ap->rreq_oa),
101 (unsigned long)EXTRACT_32BITS(&ap->rreq_os));
102 i = length - sizeof(*ap);
103 if (i >= sizeof(struct aodv_ext))
104 aodv_extension((const struct aodv_ext *)(dat + sizeof(*ap)), i);
105 return;
106
107 trunc:
108 printf(" [|rreq");
109 }
110
111 static void
112 aodv_rrep(const u_char *dat, u_int length)
113 {
114 u_int i;
115 const struct aodv_rrep *ap = (const struct aodv_rrep *)dat;
116
117 TCHECK(*ap);
118 if (length < sizeof(*ap))
119 goto trunc;
120 printf(" rrep %u %s%sprefix %u hops %u\n"
121 "\tdst %s dseq %lu src %s %lu ms", length,
122 ap->rrep_type & RREP_REPAIR ? "[R]" : "",
123 ap->rrep_type & RREP_ACK ? "[A] " : " ",
124 ap->rrep_ps & RREP_PREFIX_MASK,
125 ap->rrep_hops,
126 ipaddr_string(&ap->rrep_da),
127 (unsigned long)EXTRACT_32BITS(&ap->rrep_ds),
128 ipaddr_string(&ap->rrep_oa),
129 (unsigned long)EXTRACT_32BITS(&ap->rrep_life));
130 i = length - sizeof(*ap);
131 if (i >= sizeof(struct aodv_ext))
132 aodv_extension((const struct aodv_ext *)(dat + sizeof(*ap)), i);
133 return;
134
135 trunc:
136 printf(" [|rreq");
137 }
138
139 static void
140 aodv_rerr(const u_char *dat, u_int length)
141 {
142 u_int i, dc;
143 const struct aodv_rerr *ap = (const struct aodv_rerr *)dat;
144 const struct rerr_unreach *dp;
145
146 TCHECK(*ap);
147 if (length < sizeof(*ap))
148 goto trunc;
149 printf(" rerr %s [items %u] [%u]:",
150 ap->rerr_flags & RERR_NODELETE ? "[D]" : "",
151 ap->rerr_dc, length);
152 dp = (struct rerr_unreach *)(dat + sizeof(*ap));
153 i = length - sizeof(*ap);
154 for (dc = ap->rerr_dc; dc != 0 && i >= sizeof(*dp);
155 ++dp, --dc, i -= sizeof(*dp)) {
156 TCHECK(*dp);
157 printf(" {%s}(%ld)", ipaddr_string(&dp->u_da),
158 (unsigned long)EXTRACT_32BITS(&dp->u_ds));
159 }
160 if ((i % sizeof(*dp)) != 0)
161 goto trunc;
162 return;
163
164 trunc:
165 printf("[|rerr]");
166 }
167
168 static void
169 #ifdef INET6
170 aodv_v6_rreq(const u_char *dat, u_int length)
171 #else
172 aodv_v6_rreq(const u_char *dat _U_, u_int length)
173 #endif
174 {
175 #ifdef INET6
176 u_int i;
177 const struct aodv_rreq6 *ap = (const struct aodv_rreq6 *)dat;
178
179 TCHECK(*ap);
180 if (length < sizeof(*ap))
181 goto trunc;
182 printf(" v6 rreq %u %s%s%s%s%shops %u id 0x%08lx\n"
183 "\tdst %s seq %lu src %s seq %lu", length,
184 ap->rreq_type & RREQ_JOIN ? "[J]" : "",
185 ap->rreq_type & RREQ_REPAIR ? "[R]" : "",
186 ap->rreq_type & RREQ_GRAT ? "[G]" : "",
187 ap->rreq_type & RREQ_DEST ? "[D]" : "",
188 ap->rreq_type & RREQ_UNKNOWN ? "[U] " : " ",
189 ap->rreq_hops,
190 (unsigned long)EXTRACT_32BITS(&ap->rreq_id),
191 ip6addr_string(&ap->rreq_da),
192 (unsigned long)EXTRACT_32BITS(&ap->rreq_ds),
193 ip6addr_string(&ap->rreq_oa),
194 (unsigned long)EXTRACT_32BITS(&ap->rreq_os));
195 i = length - sizeof(*ap);
196 if (i >= sizeof(struct aodv_ext))
197 aodv_extension((const struct aodv_ext *)(dat + sizeof(*ap)), i);
198 return;
199
200 trunc:
201 printf(" [|rreq");
202 #else
203 printf(" v6 rreq %u", length);
204 #endif
205 }
206
207 static void
208 #ifdef INET6
209 aodv_v6_rrep(const u_char *dat, u_int length)
210 #else
211 aodv_v6_rrep(const u_char *dat _U_, u_int length)
212 #endif
213 {
214 #ifdef INET6
215 u_int i;
216 const struct aodv_rrep6 *ap = (const struct aodv_rrep6 *)dat;
217
218 TCHECK(*ap);
219 if (length < sizeof(*ap))
220 goto trunc;
221 printf(" rrep %u %s%sprefix %u hops %u\n"
222 "\tdst %s dseq %lu src %s %lu ms", length,
223 ap->rrep_type & RREP_REPAIR ? "[R]" : "",
224 ap->rrep_type & RREP_ACK ? "[A] " : " ",
225 ap->rrep_ps & RREP_PREFIX_MASK,
226 ap->rrep_hops,
227 ip6addr_string(&ap->rrep_da),
228 (unsigned long)EXTRACT_32BITS(&ap->rrep_ds),
229 ip6addr_string(&ap->rrep_oa),
230 (unsigned long)EXTRACT_32BITS(&ap->rrep_life));
231 i = length - sizeof(*ap);
232 if (i >= sizeof(struct aodv_ext))
233 aodv_extension((const struct aodv_ext *)(dat + sizeof(*ap)), i);
234 return;
235
236 trunc:
237 printf(" [|rreq");
238 #else
239 printf(" rrep %u", length);
240 #endif
241 }
242
243 static void
244 #ifdef INET6
245 aodv_v6_rerr(const u_char *dat, u_int length)
246 #else
247 aodv_v6_rerr(const u_char *dat _U_, u_int length)
248 #endif
249 {
250 #ifdef INET6
251 u_int i, dc;
252 const struct aodv_rerr *ap = (const struct aodv_rerr *)dat;
253 const struct rerr_unreach6 *dp6;
254
255 TCHECK(*ap);
256 if (length < sizeof(*ap))
257 goto trunc;
258 printf(" rerr %s [items %u] [%u]:",
259 ap->rerr_flags & RERR_NODELETE ? "[D]" : "",
260 ap->rerr_dc, length);
261 dp6 = (struct rerr_unreach6 *)(void *)(ap + 1);
262 i = length - sizeof(*ap);
263 for (dc = ap->rerr_dc; dc != 0 && i >= sizeof(*dp6);
264 ++dp6, --dc, i -= sizeof(*dp6)) {
265 TCHECK(*dp6);
266 printf(" {%s}(%ld)", ip6addr_string(&dp6->u_da),
267 (unsigned long)EXTRACT_32BITS(&dp6->u_ds));
268 }
269 if ((i % sizeof(*dp6)) != 0)
270 goto trunc;
271 return;
272
273 trunc:
274 printf("[|rerr]");
275 #else
276 printf(" rerr %u", length);
277 #endif
278 }
279
280 static void
281 #ifdef INET6
282 aodv_v6_draft_01_rreq(const u_char *dat, u_int length)
283 #else
284 aodv_v6_draft_01_rreq(const u_char *dat _U_, u_int length)
285 #endif
286 {
287 #ifdef INET6
288 u_int i;
289 const struct aodv_rreq6_draft_01 *ap = (const struct aodv_rreq6_draft_01 *)dat;
290
291 TCHECK(*ap);
292 if (length < sizeof(*ap))
293 goto trunc;
294 printf(" rreq %u %s%s%s%s%shops %u id 0x%08lx\n"
295 "\tdst %s seq %lu src %s seq %lu", length,
296 ap->rreq_type & RREQ_JOIN ? "[J]" : "",
297 ap->rreq_type & RREQ_REPAIR ? "[R]" : "",
298 ap->rreq_type & RREQ_GRAT ? "[G]" : "",
299 ap->rreq_type & RREQ_DEST ? "[D]" : "",
300 ap->rreq_type & RREQ_UNKNOWN ? "[U] " : " ",
301 ap->rreq_hops,
302 (unsigned long)EXTRACT_32BITS(&ap->rreq_id),
303 ip6addr_string(&ap->rreq_da),
304 (unsigned long)EXTRACT_32BITS(&ap->rreq_ds),
305 ip6addr_string(&ap->rreq_oa),
306 (unsigned long)EXTRACT_32BITS(&ap->rreq_os));
307 i = length - sizeof(*ap);
308 if (i >= sizeof(struct aodv_ext))
309 aodv_extension((const struct aodv_ext *)(dat + sizeof(*ap)), i);
310 return;
311
312 trunc:
313 printf(" [|rreq");
314 #else
315 printf(" rreq %u", length);
316 #endif
317 }
318
319 static void
320 #ifdef INET6
321 aodv_v6_draft_01_rrep(const u_char *dat, u_int length)
322 #else
323 aodv_v6_draft_01_rrep(const u_char *dat _U_, u_int length)
324 #endif
325 {
326 #ifdef INET6
327 u_int i;
328 const struct aodv_rrep6_draft_01 *ap = (const struct aodv_rrep6_draft_01 *)dat;
329
330 TCHECK(*ap);
331 if (length < sizeof(*ap))
332 goto trunc;
333 printf(" rrep %u %s%sprefix %u hops %u\n"
334 "\tdst %s dseq %lu src %s %lu ms", length,
335 ap->rrep_type & RREP_REPAIR ? "[R]" : "",
336 ap->rrep_type & RREP_ACK ? "[A] " : " ",
337 ap->rrep_ps & RREP_PREFIX_MASK,
338 ap->rrep_hops,
339 ip6addr_string(&ap->rrep_da),
340 (unsigned long)EXTRACT_32BITS(&ap->rrep_ds),
341 ip6addr_string(&ap->rrep_oa),
342 (unsigned long)EXTRACT_32BITS(&ap->rrep_life));
343 i = length - sizeof(*ap);
344 if (i >= sizeof(struct aodv_ext))
345 aodv_extension((const struct aodv_ext *)(dat + sizeof(*ap)), i);
346 return;
347
348 trunc:
349 printf(" [|rreq");
350 #else
351 printf(" rrep %u", length);
352 #endif
353 }
354
355 static void
356 #ifdef INET6
357 aodv_v6_draft_01_rerr(const u_char *dat, u_int length)
358 #else
359 aodv_v6_draft_01_rerr(const u_char *dat _U_, u_int length)
360 #endif
361 {
362 #ifdef INET6
363 u_int i, dc;
364 const struct aodv_rerr *ap = (const struct aodv_rerr *)dat;
365 const struct rerr_unreach6_draft_01 *dp6;
366
367 TCHECK(*ap);
368 if (length < sizeof(*ap))
369 goto trunc;
370 printf(" rerr %s [items %u] [%u]:",
371 ap->rerr_flags & RERR_NODELETE ? "[D]" : "",
372 ap->rerr_dc, length);
373 dp6 = (struct rerr_unreach6_draft_01 *)(void *)(ap + 1);
374 i = length - sizeof(*ap);
375 for (dc = ap->rerr_dc; dc != 0 && i >= sizeof(*dp6);
376 ++dp6, --dc, i -= sizeof(*dp6)) {
377 TCHECK(*dp6);
378 printf(" {%s}(%ld)", ip6addr_string(&dp6->u_da),
379 (unsigned long)EXTRACT_32BITS(&dp6->u_ds));
380 }
381 if ((i % sizeof(*dp6)) != 0)
382 goto trunc;
383 return;
384
385 trunc:
386 printf("[|rerr]");
387 #else
388 printf(" rerr %u", length);
389 #endif
390 }
391
392 void
393 aodv_print(const u_char *dat, u_int length, int is_ip6)
394 {
395 u_int8_t msg_type;
396
397 /*
398 * The message type is the first byte; make sure we have it
399 * and then fetch it.
400 */
401 TCHECK(*dat);
402 msg_type = *dat;
403 printf(" aodv");
404
405 switch (msg_type) {
406
407 case AODV_RREQ:
408 if (is_ip6)
409 aodv_v6_rreq(dat, length);
410 else
411 aodv_rreq(dat, length);
412 break;
413
414 case AODV_RREP:
415 if (is_ip6)
416 aodv_v6_rrep(dat, length);
417 else
418 aodv_rrep(dat, length);
419 break;
420
421 case AODV_RERR:
422 if (is_ip6)
423 aodv_v6_rerr(dat, length);
424 else
425 aodv_rerr(dat, length);
426 break;
427
428 case AODV_RREP_ACK:
429 printf(" rrep-ack %u", length);
430 break;
431
432 case AODV_V6_DRAFT_01_RREQ:
433 aodv_v6_draft_01_rreq(dat, length);
434 break;
435
436 case AODV_V6_DRAFT_01_RREP:
437 aodv_v6_draft_01_rrep(dat, length);
438 break;
439
440 case AODV_V6_DRAFT_01_RERR:
441 aodv_v6_draft_01_rerr(dat, length);
442 break;
443
444 case AODV_V6_DRAFT_01_RREP_ACK:
445 printf(" rrep-ack %u", length);
446 break;
447
448 default:
449 printf(" type %u %u", msg_type, length);
450 }
451 return;
452
453 trunc:
454 printf(" [|aodv]");
455 }