]> The Tcpdump Group git mirrors - tcpdump/blob - print-aodv.c
Fix the pointer tests in the non-ndoified TTEST2() macro as well.
[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 <stdio.h>
45 #include <ctype.h>
46 #include <string.h>
47
48 #include "interface.h"
49 #include "addrtoname.h"
50 #include "extract.h" /* must come after interface.h */
51
52 #include "aodv.h"
53
54 static void
55 aodv_extension(const struct aodv_ext *ep, u_int length)
56 {
57 const struct aodv_hello *ah;
58
59 switch (ep->type) {
60 case AODV_EXT_HELLO:
61 ah = (const struct aodv_hello *)(const void *)ep;
62 TCHECK(*ah);
63 if (length < sizeof(struct aodv_hello))
64 goto trunc;
65 printf("\n\text HELLO %ld ms",
66 (unsigned long)EXTRACT_32BITS(&ah->interval));
67 break;
68
69 default:
70 printf("\n\text %u %u", ep->type, ep->length);
71 break;
72 }
73 return;
74
75 trunc:
76 printf(" [|hello]");
77 }
78
79 static void
80 aodv_rreq(const u_char *dat, u_int length)
81 {
82 u_int i;
83 const struct aodv_rreq *ap = (const struct aodv_rreq *)dat;
84
85 TCHECK(*ap);
86 if (length < sizeof(*ap))
87 goto trunc;
88 printf(" rreq %u %s%s%s%s%shops %u id 0x%08lx\n"
89 "\tdst %s seq %lu src %s seq %lu", length,
90 ap->rreq_type & RREQ_JOIN ? "[J]" : "",
91 ap->rreq_type & RREQ_REPAIR ? "[R]" : "",
92 ap->rreq_type & RREQ_GRAT ? "[G]" : "",
93 ap->rreq_type & RREQ_DEST ? "[D]" : "",
94 ap->rreq_type & RREQ_UNKNOWN ? "[U] " : " ",
95 ap->rreq_hops,
96 (unsigned long)EXTRACT_32BITS(&ap->rreq_id),
97 ipaddr_string(&ap->rreq_da),
98 (unsigned long)EXTRACT_32BITS(&ap->rreq_ds),
99 ipaddr_string(&ap->rreq_oa),
100 (unsigned long)EXTRACT_32BITS(&ap->rreq_os));
101 i = length - sizeof(*ap);
102 if (i >= sizeof(struct aodv_ext))
103 aodv_extension((const struct aodv_ext *)(dat + sizeof(*ap)), i);
104 return;
105
106 trunc:
107 printf(" [|rreq");
108 }
109
110 static void
111 aodv_rrep(const u_char *dat, u_int length)
112 {
113 u_int i;
114 const struct aodv_rrep *ap = (const struct aodv_rrep *)dat;
115
116 TCHECK(*ap);
117 if (length < sizeof(*ap))
118 goto trunc;
119 printf(" rrep %u %s%sprefix %u hops %u\n"
120 "\tdst %s dseq %lu src %s %lu ms", length,
121 ap->rrep_type & RREP_REPAIR ? "[R]" : "",
122 ap->rrep_type & RREP_ACK ? "[A] " : " ",
123 ap->rrep_ps & RREP_PREFIX_MASK,
124 ap->rrep_hops,
125 ipaddr_string(&ap->rrep_da),
126 (unsigned long)EXTRACT_32BITS(&ap->rrep_ds),
127 ipaddr_string(&ap->rrep_oa),
128 (unsigned long)EXTRACT_32BITS(&ap->rrep_life));
129 i = length - sizeof(*ap);
130 if (i >= sizeof(struct aodv_ext))
131 aodv_extension((const struct aodv_ext *)(dat + sizeof(*ap)), i);
132 return;
133
134 trunc:
135 printf(" [|rreq");
136 }
137
138 static void
139 aodv_rerr(const u_char *dat, u_int length)
140 {
141 u_int i, dc;
142 const struct aodv_rerr *ap = (const struct aodv_rerr *)dat;
143 const struct rerr_unreach *dp;
144
145 TCHECK(*ap);
146 if (length < sizeof(*ap))
147 goto trunc;
148 printf(" rerr %s [items %u] [%u]:",
149 ap->rerr_flags & RERR_NODELETE ? "[D]" : "",
150 ap->rerr_dc, length);
151 dp = (struct rerr_unreach *)(dat + sizeof(*ap));
152 i = length - sizeof(*ap);
153 for (dc = ap->rerr_dc; dc != 0; dc--) {
154 TCHECK(*dp);
155 if (i < sizeof(*dp))
156 goto trunc;
157 printf(" {%s}(%ld)", ipaddr_string(&dp->u_da),
158 (unsigned long)EXTRACT_32BITS(&dp->u_ds));
159 dp++;
160 i -= sizeof(*dp);
161 }
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; dc--) {
264 TCHECK(*dp6);
265 if (i < sizeof(*dp6))
266 goto trunc;
267 printf(" {%s}(%ld)", ip6addr_string(&dp6->u_da),
268 (unsigned long)EXTRACT_32BITS(&dp6->u_ds));
269 dp6++;
270 i -= sizeof(*dp6);
271 }
272 return;
273
274 trunc:
275 printf("[|rerr]");
276 #else
277 printf(" rerr %u", length);
278 #endif
279 }
280
281 static void
282 #ifdef INET6
283 aodv_v6_draft_01_rreq(const u_char *dat, u_int length)
284 #else
285 aodv_v6_draft_01_rreq(const u_char *dat _U_, u_int length)
286 #endif
287 {
288 #ifdef INET6
289 u_int i;
290 const struct aodv_rreq6_draft_01 *ap = (const struct aodv_rreq6_draft_01 *)dat;
291
292 TCHECK(*ap);
293 if (length < sizeof(*ap))
294 goto trunc;
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->rreq_type & RREQ_JOIN ? "[J]" : "",
298 ap->rreq_type & RREQ_REPAIR ? "[R]" : "",
299 ap->rreq_type & RREQ_GRAT ? "[G]" : "",
300 ap->rreq_type & RREQ_DEST ? "[D]" : "",
301 ap->rreq_type & RREQ_UNKNOWN ? "[U] " : " ",
302 ap->rreq_hops,
303 (unsigned long)EXTRACT_32BITS(&ap->rreq_id),
304 ip6addr_string(&ap->rreq_da),
305 (unsigned long)EXTRACT_32BITS(&ap->rreq_ds),
306 ip6addr_string(&ap->rreq_oa),
307 (unsigned long)EXTRACT_32BITS(&ap->rreq_os));
308 i = length - sizeof(*ap);
309 if (i >= sizeof(struct aodv_ext))
310 aodv_extension((const struct aodv_ext *)(dat + sizeof(*ap)), i);
311 return;
312
313 trunc:
314 printf(" [|rreq");
315 #else
316 printf(" rreq %u", length);
317 #endif
318 }
319
320 static void
321 #ifdef INET6
322 aodv_v6_draft_01_rrep(const u_char *dat, u_int length)
323 #else
324 aodv_v6_draft_01_rrep(const u_char *dat _U_, u_int length)
325 #endif
326 {
327 #ifdef INET6
328 u_int i;
329 const struct aodv_rrep6_draft_01 *ap = (const struct aodv_rrep6_draft_01 *)dat;
330
331 TCHECK(*ap);
332 if (length < sizeof(*ap))
333 goto trunc;
334 printf(" rrep %u %s%sprefix %u hops %u\n"
335 "\tdst %s dseq %lu src %s %lu ms", length,
336 ap->rrep_type & RREP_REPAIR ? "[R]" : "",
337 ap->rrep_type & RREP_ACK ? "[A] " : " ",
338 ap->rrep_ps & RREP_PREFIX_MASK,
339 ap->rrep_hops,
340 ip6addr_string(&ap->rrep_da),
341 (unsigned long)EXTRACT_32BITS(&ap->rrep_ds),
342 ip6addr_string(&ap->rrep_oa),
343 (unsigned long)EXTRACT_32BITS(&ap->rrep_life));
344 i = length - sizeof(*ap);
345 if (i >= sizeof(struct aodv_ext))
346 aodv_extension((const struct aodv_ext *)(dat + sizeof(*ap)), i);
347 return;
348
349 trunc:
350 printf(" [|rreq");
351 #else
352 printf(" rrep %u", length);
353 #endif
354 }
355
356 static void
357 #ifdef INET6
358 aodv_v6_draft_01_rerr(const u_char *dat, u_int length)
359 #else
360 aodv_v6_draft_01_rerr(const u_char *dat _U_, u_int length)
361 #endif
362 {
363 #ifdef INET6
364 u_int i, dc;
365 const struct aodv_rerr *ap = (const struct aodv_rerr *)dat;
366 const struct rerr_unreach6_draft_01 *dp6;
367
368 TCHECK(*ap);
369 if (length < sizeof(*ap))
370 goto trunc;
371 printf(" rerr %s [items %u] [%u]:",
372 ap->rerr_flags & RERR_NODELETE ? "[D]" : "",
373 ap->rerr_dc, length);
374 dp6 = (struct rerr_unreach6_draft_01 *)(void *)(ap + 1);
375 i = length - sizeof(*ap);
376 for (dc = ap->rerr_dc; dc != 0; dc--) {
377 TCHECK(*dp6);
378 if (i < sizeof(*dp6))
379 goto trunc;
380 printf(" {%s}(%ld)", ip6addr_string(&dp6->u_da),
381 (unsigned long)EXTRACT_32BITS(&dp6->u_ds));
382 dp6++;
383 i -= sizeof(*dp6);
384 }
385 return;
386
387 trunc:
388 printf("[|rerr]");
389 #else
390 printf(" rerr %u", length);
391 #endif
392 }
393
394 void
395 aodv_print(const u_char *dat, u_int length, int is_ip6)
396 {
397 u_int8_t msg_type;
398
399 /*
400 * The message type is the first byte; make sure we have it
401 * and then fetch it.
402 */
403 TCHECK(*dat);
404 msg_type = *dat;
405 printf(" aodv");
406
407 switch (msg_type) {
408
409 case AODV_RREQ:
410 if (is_ip6)
411 aodv_v6_rreq(dat, length);
412 else
413 aodv_rreq(dat, length);
414 break;
415
416 case AODV_RREP:
417 if (is_ip6)
418 aodv_v6_rrep(dat, length);
419 else
420 aodv_rrep(dat, length);
421 break;
422
423 case AODV_RERR:
424 if (is_ip6)
425 aodv_v6_rerr(dat, length);
426 else
427 aodv_rerr(dat, length);
428 break;
429
430 case AODV_RREP_ACK:
431 printf(" rrep-ack %u", length);
432 break;
433
434 case AODV_V6_DRAFT_01_RREQ:
435 aodv_v6_draft_01_rreq(dat, length);
436 break;
437
438 case AODV_V6_DRAFT_01_RREP:
439 aodv_v6_draft_01_rrep(dat, length);
440 break;
441
442 case AODV_V6_DRAFT_01_RERR:
443 aodv_v6_draft_01_rerr(dat, length);
444 break;
445
446 case AODV_V6_DRAFT_01_RREP_ACK:
447 printf(" rrep-ack %u", length);
448 break;
449
450 default:
451 printf(" type %u %u", msg_type, length);
452 }
453 return;
454
455 trunc:
456 printf(" [|aodv]");
457 }