]> The Tcpdump Group git mirrors - tcpdump/blob - print-aodv.c
Updates from Bruce Simpson:
[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.5 2003-09-12 22:05:57 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 %d ms", EXTRACT_32BITS(&ah->interval));
75 break;
76
77 default:
78 printf("\n\text %d %d", ep->type, ep->length);
79 break;
80 }
81 }
82
83 static void
84 aodv_rreq(const union aodv *ap, const u_char *dat, u_int length)
85 {
86 u_int i;
87
88 if (snapend < dat) {
89 printf(" [|aodv]");
90 return;
91 }
92 i = min(length, (u_int)(snapend - dat));
93 if (i < sizeof(ap->rreq)) {
94 printf(" [|rreq]");
95 return;
96 }
97 i -= sizeof(ap->rreq);
98 printf(" rreq %d %s%s%s%s%shops %d id 0x%08x\n"
99 "\tdst %s seq %d src %s seq %d", length,
100 ap->rreq.rreq_type & RREQ_JOIN ? "[J]" : "",
101 ap->rreq.rreq_type & RREQ_REPAIR ? "[R]" : "",
102 ap->rreq.rreq_type & RREQ_GRAT ? "[G]" : "",
103 ap->rreq.rreq_type & RREQ_DEST ? "[D]" : "",
104 ap->rreq.rreq_type & RREQ_UNKNOWN ? "[U] " : " ",
105 ap->rreq.rreq_hops,
106 EXTRACT_32BITS(&ap->rreq.rreq_id),
107 ipaddr_string(&ap->rreq.rreq_da),
108 EXTRACT_32BITS(&ap->rreq.rreq_ds),
109 ipaddr_string(&ap->rreq.rreq_oa),
110 EXTRACT_32BITS(&ap->rreq.rreq_os));
111 if (i >= sizeof(struct aodv_ext))
112 aodv_extension((void *)(&ap->rreq + 1), i);
113 }
114
115 static void
116 aodv_rrep(const union aodv *ap, const u_char *dat, u_int length)
117 {
118 u_int i;
119
120 if (snapend < dat) {
121 printf(" [|aodv]");
122 return;
123 }
124 i = min(length, (u_int)(snapend - dat));
125 if (i < sizeof(ap->rrep)) {
126 printf(" [|rrep]");
127 return;
128 }
129 i -= sizeof(ap->rrep);
130 printf(" rrep %d %s%sprefix %d hops %d\n"
131 "\tdst %s dseq %d src %s %d ms", length,
132 ap->rrep.rrep_type & RREP_REPAIR ? "[R]" : "",
133 ap->rrep.rrep_type & RREP_ACK ? "[A] " : " ",
134 ap->rrep.rrep_ps & RREP_PREFIX_MASK,
135 ap->rrep.rrep_hops,
136 ipaddr_string(&ap->rrep.rrep_da),
137 EXTRACT_32BITS(&ap->rrep.rrep_ds),
138 ipaddr_string(&ap->rrep.rrep_oa),
139 EXTRACT_32BITS(&ap->rrep.rrep_life));
140 if (i >= sizeof(struct aodv_ext))
141 aodv_extension((void *)(&ap->rrep + 1), i);
142 }
143
144 static void
145 aodv_rerr(const union aodv *ap, u_int length)
146 {
147 const struct rerr_unreach *dp = NULL;
148 int i, j, n, trunc;
149
150 i = length - offsetof(struct aodv_rerr, r);
151 j = sizeof(ap->rerr.r.dest[0]);
152 dp = &ap->rerr.r.dest[0];
153 n = ap->rerr.rerr_dc * j;
154 printf(" rerr %s [items %d] [%d]:",
155 ap->rerr.rerr_flags & RERR_NODELETE ? "[D]" : "",
156 ap->rerr.rerr_dc, length);
157 trunc = n - (i/j);
158 for (; i -= j >= 0; ++dp) {
159 printf(" {%s}(%d)", ipaddr_string(&dp->u_da),
160 EXTRACT_32BITS(&dp->u_ds));
161 }
162 if (trunc)
163 printf("[|rerr]");
164 }
165
166 static void
167 #ifdef INET6
168 aodv_v6_rreq(const union aodv *ap, const u_char *dat, u_int length)
169 #else
170 aodv_v6_rreq(const union aodv *ap _U_, const u_char *dat _U_, u_int length)
171 #endif
172 {
173 #ifdef INET6
174 u_int i;
175
176 if (snapend < dat) {
177 printf(" [|aodv]");
178 return;
179 }
180 i = min(length, (u_int)(snapend - dat));
181 if (i < sizeof(ap->rreq6)) {
182 printf(" [|rreq6]");
183 return;
184 }
185 i -= sizeof(ap->rreq6);
186 printf(" v6 rreq %d %s%s%s%s%shops %d id 0x%08x\n"
187 "\tdst %s seq %d src %s seq %d", length,
188 ap->rreq6.rreq_type & RREQ_JOIN ? "[J]" : "",
189 ap->rreq6.rreq_type & RREQ_REPAIR ? "[R]" : "",
190 ap->rreq6.rreq_type & RREQ_GRAT ? "[G]" : "",
191 ap->rreq6.rreq_type & RREQ_DEST ? "[D]" : "",
192 ap->rreq6.rreq_type & RREQ_UNKNOWN ? "[U] " : " ",
193 ap->rreq6.rreq_hops,
194 EXTRACT_32BITS(&ap->rreq6.rreq_id),
195 ip6addr_string(&ap->rreq6.rreq_da),
196 EXTRACT_32BITS(&ap->rreq6.rreq_ds),
197 ip6addr_string(&ap->rreq6.rreq_oa),
198 EXTRACT_32BITS(&ap->rreq6.rreq_os));
199 if (i >= sizeof(struct aodv_ext))
200 aodv_extension((void *)(&ap->rreq6 + 1), i);
201 #else
202 printf(" v6 rreq %d", length);
203 #endif
204 }
205
206 static void
207 #ifdef INET6
208 aodv_v6_rrep(const union aodv *ap, const u_char *dat, u_int length)
209 #else
210 aodv_v6_rrep(const union aodv *ap _U_, const u_char *dat _U_, u_int length)
211 #endif
212 {
213 #ifdef INET6
214 u_int i;
215
216 if (snapend < dat) {
217 printf(" [|aodv]");
218 return;
219 }
220 i = min(length, (u_int)(snapend - dat));
221 if (i < sizeof(ap->rrep6)) {
222 printf(" [|rrep6]");
223 return;
224 }
225 i -= sizeof(ap->rrep6);
226 printf(" rrep %d %s%sprefix %d hops %d\n"
227 "\tdst %s dseq %d src %s %d ms", length,
228 ap->rrep6.rrep_type & RREP_REPAIR ? "[R]" : "",
229 ap->rrep6.rrep_type & RREP_ACK ? "[A] " : " ",
230 ap->rrep6.rrep_ps & RREP_PREFIX_MASK,
231 ap->rrep6.rrep_hops,
232 ip6addr_string(&ap->rrep6.rrep_da),
233 EXTRACT_32BITS(&ap->rrep6.rrep_ds),
234 ip6addr_string(&ap->rrep6.rrep_oa),
235 EXTRACT_32BITS(&ap->rrep6.rrep_life));
236 if (i >= sizeof(struct aodv_ext))
237 aodv_extension((void *)(&ap->rrep6 + 1), i);
238 #else
239 printf(" v6 rrep %d", length);
240 #endif
241 }
242
243 static void
244 #ifdef INET6
245 aodv_v6_rerr(const union aodv *ap, u_int length)
246 #else
247 aodv_v6_rerr(const union aodv *ap _U_, u_int length)
248 #endif
249 {
250 #ifdef INET6
251 const struct rerr_unreach6 *dp6 = NULL;
252 int i, j, n, trunc;
253
254 i = length - offsetof(struct aodv_rerr, r);
255 j = sizeof(ap->rerr.r.dest6[0]);
256 dp6 = &ap->rerr.r.dest6[0];
257 n = ap->rerr.rerr_dc * j;
258 printf(" rerr %s [items %d] [%d]:",
259 ap->rerr.rerr_flags & RERR_NODELETE ? "[D]" : "",
260 ap->rerr.rerr_dc, length);
261 trunc = n - (i/j);
262 for (; i -= j >= 0; ++dp6) {
263 printf(" {%s}(%d)", ip6addr_string(&dp6->u_da),
264 EXTRACT_32BITS(&dp6->u_ds));
265 }
266 if (trunc)
267 printf("[|rerr]");
268 #else
269 printf(" v6 rerr %d", length);
270 #endif
271 }
272
273 void
274 aodv_print(const u_char *dat, u_int length, int is_ip6)
275 {
276 const union aodv *ap;
277
278 ap = (union aodv *)dat;
279 if (snapend < dat) {
280 printf(" [|aodv]");
281 return;
282 }
283 if (min(length, (u_int)(snapend - dat)) < sizeof(ap->rrep_ack)) {
284 printf(" [|aodv]");
285 return;
286 }
287 printf(" aodv");
288
289 switch (ap->rerr.rerr_type) {
290
291 case AODV_RREQ:
292 if (is_ip6)
293 aodv_v6_rreq(ap, dat, length);
294 else
295 aodv_rreq(ap, dat, length);
296 break;
297
298 case AODV_RREP:
299 if (is_ip6)
300 aodv_v6_rrep(ap, dat, length);
301 else
302 aodv_rrep(ap, dat, length);
303 break;
304
305 case AODV_RERR:
306 if (is_ip6)
307 aodv_v6_rerr(ap, length);
308 else
309 aodv_rerr(ap, length);
310 break;
311
312 case AODV_RREP_ACK:
313 printf(" rrep-ack %d", length);
314 break;
315
316 case AODV_V6_RREQ:
317 aodv_v6_rreq(ap, dat, length);
318 break;
319
320 case AODV_V6_RREP:
321 aodv_v6_rrep(ap, dat, length);
322 break;
323
324 case AODV_V6_RERR:
325 aodv_v6_rerr(ap, length);
326 break;
327
328 case AODV_V6_RREP_ACK:
329 printf(" v6 rrep-ack %d", length);
330 break;
331
332 default:
333 printf(" %d %d", ap->rreq.rreq_type, length);
334 }
335 }