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