]> The Tcpdump Group git mirrors - tcpdump/blob - print-aodv.c
use strlcpy/cat
[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.3 2003-08-13 02:23:07 itojun 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(struct aodv_ext *ep, u_int length)
57 {
58 u_int i;
59 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",
75 EXTRACT_32BITS(ah->interval));
76 break;
77
78 default:
79 printf("\n\text %d %d", ep->type, ep->length);
80 break;
81 }
82 }
83
84 static void
85 aodv_rreq(union aodv *ap, const u_char *dat, u_int length, void *ip6
86 #ifndef INET6
87 _U_
88 #endif
89 )
90 {
91 u_int i;
92
93 if (snapend < dat) {
94 printf(" [|aodv]");
95 return;
96 }
97 i = min(length, (u_int)(snapend - dat));
98 if (i < sizeof(ap->rreq)) {
99 printf(" [|rreq]");
100 return;
101 }
102 i -= sizeof(ap->rreq);
103 #ifdef INET6
104 if (ip6 != NULL) {
105 printf(" rreq %d %s%s%s%s%shops %d id 0x%08lx\n"
106 "\tdst %s seq %ld src %s seq %ld", length,
107 ap->rreq6.rreq_type & RREQ_JOIN ? "[J]" : "",
108 ap->rreq6.rreq_type & RREQ_REPAIR ? "[R]" : "",
109 ap->rreq6.rreq_type & RREQ_GRAT ? "[G]" : "",
110 ap->rreq6.rreq_type & RREQ_DEST ? "[D]" : "",
111 ap->rreq6.rreq_type & RREQ_UNKNOWN ? "[U] " : " ",
112 ap->rreq6.rreq_hops,
113 (unsigned long)EXTRACT_32BITS(ap->rreq6.rreq_id),
114 ip6addr_string(&ap->rreq6.rreq_da),
115 (unsigned long)EXTRACT_32BITS(ap->rreq6.rreq_ds),
116 ip6addr_string(&ap->rreq6.rreq_oa),
117 (unsigned long)EXTRACT_32BITS(ap->rreq6.rreq_os));
118 if (i >= sizeof(ap->rreq6) + sizeof(struct aodv_ext)) {
119 aodv_extension((void *) (&ap->rreq6 + 1),
120 length - sizeof(ap->rreq6));
121 }
122 } else
123 #endif
124 {
125 printf(" rreq %d %s%s%s%s%shops %d id 0x%08x\n"
126 "\tdst %s seq %d src %s seq %d", length,
127 ap->rreq.rreq_type & RREQ_JOIN ? "[J]" : "",
128 ap->rreq.rreq_type & RREQ_REPAIR ? "[R]" : "",
129 ap->rreq.rreq_type & RREQ_GRAT ? "[G]" : "",
130 ap->rreq.rreq_type & RREQ_DEST ? "[D]" : "",
131 ap->rreq.rreq_type & RREQ_UNKNOWN ? "[U] " : " ",
132 ap->rreq.rreq_hops,
133 EXTRACT_32BITS(ap->rreq.rreq_id),
134 ipaddr_string(ap->rreq.rreq_da),
135 EXTRACT_32BITS(ap->rreq.rreq_ds),
136 ipaddr_string(ap->rreq.rreq_oa),
137 EXTRACT_32BITS(ap->rreq.rreq_os));
138 if (i >= sizeof(ap->rreq) + sizeof(struct aodv_ext)) {
139 aodv_extension((void *) (&ap->rreq + 1),
140 length - sizeof(ap->rreq));
141 }
142 }
143 }
144
145 static void
146 aodv_rrep(union aodv *ap, const u_char *dat, u_int length, void *ip6
147 #ifndef INET6
148 _U_
149 #endif
150 )
151 {
152 u_int i;
153
154 if (snapend < dat) {
155 printf(" [|aodv]");
156 return;
157 }
158 i = min(length, (u_int)(snapend - dat));
159 if (i < sizeof(ap->rrep)) {
160 printf(" [|rrep]");
161 return;
162 }
163 i -= sizeof(ap->rrep);
164 #ifdef INET6
165 if (ip6 != NULL) {
166 printf(" rrep %d %s%sprefix %d hops %d\n"
167 "\tdst %s dseq %d src %s %d ms", length,
168 ap->rrep6.rrep_type & RREP_REPAIR ? "[R]" : "",
169 ap->rrep6.rrep_type & RREP_ACK ? "[A] " : " ",
170 ap->rrep6.rrep_ps & RREP_PREFIX_MASK,
171 ap->rrep6.rrep_hops,
172 ip6addr_string(&ap->rrep6.rrep_da),
173 EXTRACT_32BITS(ap->rrep6.rrep_ds),
174 ip6addr_string(&ap->rrep6.rrep_oa),
175 EXTRACT_32BITS(ap->rrep6.rrep_life));
176 if (i >= sizeof(ap->rrep6) + sizeof(struct aodv_ext)) {
177 aodv_extension((void *) (&ap->rrep6 + 1),
178 length - sizeof(ap->rrep6));
179 }
180 } else
181 #endif
182 {
183 printf(" rrep %d %s%sprefix %d hops %d\n"
184 "\tdst %s dseq %d src %s %d ms", length,
185 ap->rrep.rrep_type & RREP_REPAIR ? "[R]" : "",
186 ap->rrep.rrep_type & RREP_ACK ? "[A] " : " ",
187 ap->rrep.rrep_ps & RREP_PREFIX_MASK,
188 ap->rrep.rrep_hops,
189 ipaddr_string(ap->rrep.rrep_da),
190 EXTRACT_32BITS(ap->rrep.rrep_ds),
191 ipaddr_string(ap->rrep.rrep_oa),
192 EXTRACT_32BITS(ap->rrep.rrep_life));
193 if (i >= sizeof(ap->rrep) + sizeof(struct aodv_ext)) {
194 aodv_extension((void *) (&ap->rrep + 1),
195 length - sizeof(ap->rrep));
196 }
197 }
198 }
199
200 static void
201 aodv_rerr(union aodv *ap, u_int length, void *ip6
202 #ifndef INET6
203 _U_
204 #endif
205 )
206 {
207 int i, j, n, trunc;
208 struct rerr_unreach *dp;
209 #ifdef INET6
210 struct rerr_unreach6 *dp6;
211 #endif
212
213 i = length - offsetof(struct aodv_rerr, r);
214 #ifdef INET6
215 if (ip6 != NULL) {
216 j = sizeof(ap->rerr.r.dest6[0]);
217 dp6 = &ap->rerr.r.dest6[0];
218 } else
219 #endif
220 {
221 j = sizeof(ap->rerr.r.dest[0]);
222 dp = &ap->rerr.r.dest[0];
223 }
224 n = ap->rerr.rerr_dc * j;
225 printf(" rerr %s [items %d] [%d]:",
226 ap->rerr.rerr_flags & RERR_NODELETE ? "[D]" : "",
227 ap->rerr.rerr_dc, length);
228 trunc = n - (i/j);
229 #ifdef INET6
230 if (ip6 != NULL) {
231 for (; i -= j >= 0; ++dp6) {
232 printf(" {%s}(%d)", ip6addr_string(&dp6->u_da),
233 EXTRACT_32BITS(dp6->u_ds));
234 }
235 } else
236 #endif
237 {
238 for (; i -= j >= 0; ++dp) {
239 printf(" {%s}(%d)", ipaddr_string(dp->u_da),
240 EXTRACT_32BITS(dp->u_ds));
241 }
242 }
243 if (trunc)
244 printf("[|rerr]");
245 }
246
247 void
248 aodv_print(const u_char *dat, u_int length, void *ip6)
249 {
250 union aodv *ap;
251
252 ap = (union aodv *)dat;
253 if (snapend < dat) {
254 printf(" [|aodv]");
255 return;
256 }
257 if (min(length, (u_int)(snapend - dat)) < sizeof(ap->rrep_ack)) {
258 printf(" [|aodv]");
259 return;
260 }
261 printf(" aodv");
262
263 switch (ap->rerr.rerr_type) {
264 case AODV_RREQ:
265 aodv_rreq(ap, dat, length, ip6);
266 break;
267 case AODV_RREP:
268 aodv_rrep(ap, dat, length, ip6);
269 break;
270 case AODV_RERR:
271 aodv_rerr(ap, length, ip6);
272 break;
273 case AODV_RREP_ACK:
274 printf(" rrep-ack %d", ap->rrep_ack.ra_type);
275 break;
276
277 default:
278 printf(" %d %d", ap->rreq.rreq_type, length);
279 }
280 }