]> The Tcpdump Group git mirrors - tcpdump/blob - print-aodv.c
253c2e0b591ab72ef28ef6ddecd73d38a139ead0
[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[] =
35 "@(#) $Header: /tcpdump/master/tcpdump/print-aodv.c,v 1.7 2003-09-12 22:16:53 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(" v6 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(" v6 rerr %u", length);
271 #endif
272 }
273
274 void
275 aodv_print(const u_char *dat, u_int length, int is_ip6)
276 {
277 const union aodv *ap;
278
279 ap = (union aodv *)dat;
280 if (snapend < dat) {
281 printf(" [|aodv]");
282 return;
283 }
284 if (min(length, (u_int)(snapend - dat)) < sizeof(ap->rrep_ack)) {
285 printf(" [|aodv]");
286 return;
287 }
288 printf(" aodv");
289
290 switch (ap->rerr.rerr_type) {
291
292 case AODV_RREQ:
293 if (is_ip6)
294 aodv_v6_rreq(ap, dat, length);
295 else
296 aodv_rreq(ap, dat, length);
297 break;
298
299 case AODV_RREP:
300 if (is_ip6)
301 aodv_v6_rrep(ap, dat, length);
302 else
303 aodv_rrep(ap, dat, length);
304 break;
305
306 case AODV_RERR:
307 if (is_ip6)
308 aodv_v6_rerr(ap, length);
309 else
310 aodv_rerr(ap, length);
311 break;
312
313 case AODV_RREP_ACK:
314 printf(" rrep-ack %u", length);
315 break;
316
317 case AODV_V6_RREQ:
318 aodv_v6_rreq(ap, dat, length);
319 break;
320
321 case AODV_V6_RREP:
322 aodv_v6_rrep(ap, dat, length);
323 break;
324
325 case AODV_V6_RERR:
326 aodv_v6_rerr(ap, length);
327 break;
328
329 case AODV_V6_RREP_ACK:
330 printf(" v6 rrep-ack %u", length);
331 break;
332
333 default:
334 printf(" %u %u", ap->rreq.rreq_type, length);
335 }
336 }