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