]> The Tcpdump Group git mirrors - tcpdump/blob - print-ip6opts.c
Get rid of unneeded includes of <netinet/in_systm.h> and <netinet/ip.h>.
[tcpdump] / print-ip6opts.c
1 /*
2 * Copyright (C) 1998 WIDE Project.
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. Neither the name of the project nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
33
34 #ifndef lint
35 static const char rcsid[] =
36 "@(#) $Header: /tcpdump/master/tcpdump/print-ip6opts.c,v 1.10 2002-03-28 10:02:35 guy Exp $";
37 #endif
38
39 #ifdef INET6
40 #include <sys/param.h>
41 #include <sys/time.h>
42 #include <sys/types.h>
43 #include <sys/socket.h>
44
45 #include <netinet/in.h>
46 #include <stdio.h>
47
48 #include "ip6.h"
49
50 #include "interface.h"
51 #include "addrtoname.h"
52
53 /* items outside of rfc2292bis */
54 #ifndef IP6OPT_MINLEN
55 #define IP6OPT_MINLEN 2
56 #endif
57 #ifndef IP6OPT_RTALERT_LEN
58 #define IP6OPT_RTALERT_LEN 4
59 #endif
60 #ifndef IP6OPT_JUMBO_LEN
61 #define IP6OPT_JUMBO_LEN 6
62 #endif
63 #define IP6OPT_HOMEADDR_MINLEN 18
64 #define IP6OPT_BU_MINLEN 10
65 #define IP6OPT_BA_MINLEN 13
66 #define IP6OPT_BR_MINLEN 2
67 #define IP6SOPT_UI 0x2
68 #define IP6SOPT_UI_MINLEN 4
69 #define IP6SOPT_ALTCOA 0x3
70 #define IP6SOPT_ALTCOA_MINLEN 18
71 #define IP6SOPT_AUTH 0x4
72 #define IP6SOPT_AUTH_MINLEN 6
73
74 static void ip6_sopt_print(const u_char *, int);
75
76 static void
77 ip6_sopt_print(const u_char *bp, int len)
78 {
79 int i;
80 int optlen;
81
82 for (i = 0; i < len; i += optlen) {
83 if (bp[i] == IP6OPT_PAD1)
84 optlen = 1;
85 else {
86 if (i + 1 < len)
87 optlen = bp[i + 1] + 2;
88 else
89 goto trunc;
90 }
91 if (i + optlen > len)
92 goto trunc;
93
94 switch (bp[i]) {
95 case IP6OPT_PAD1:
96 printf(", pad1");
97 break;
98 case IP6OPT_PADN:
99 if (len - i < IP6OPT_MINLEN) {
100 printf(", padn: trunc");
101 goto trunc;
102 }
103 printf(", padn");
104 break;
105 case IP6SOPT_UI:
106 if (len - i < IP6SOPT_UI_MINLEN) {
107 printf(", ui: trunc");
108 goto trunc;
109 }
110 printf(", ui: 0x%04x ", ntohs(*(u_int16_t *)&bp[i + 2]));
111 break;
112 case IP6SOPT_ALTCOA:
113 if (len - i < IP6SOPT_ALTCOA_MINLEN) {
114 printf(", altcoa: trunc");
115 goto trunc;
116 }
117 printf(", alt-CoA: %s", ip6addr_string(&bp[i+2]));
118 break;
119 case IP6SOPT_AUTH:
120 if (len - i < IP6SOPT_AUTH_MINLEN) {
121 printf(", auth: trunc");
122 goto trunc;
123 }
124 printf(", auth spi: 0x%08x",
125 (u_int32_t)ntohl(*(u_int32_t *)&bp[i + 2]));
126 break;
127 default:
128 if (len - i < IP6OPT_MINLEN) {
129 printf(", sopt_type %d: trunc)", bp[i]);
130 goto trunc;
131 }
132 printf(", sopt_type 0x%02x: len=%d", bp[i], bp[i + 1]);
133 break;
134 }
135 }
136 return;
137
138 trunc:
139 printf("[trunc] ");
140 }
141
142 void
143 ip6_opt_print(const u_char *bp, int len)
144 {
145 int i;
146 int optlen;
147
148 for (i = 0; i < len; i += optlen) {
149 if (bp[i] == IP6OPT_PAD1)
150 optlen = 1;
151 else {
152 if (i + 1 < len)
153 optlen = bp[i + 1] + 2;
154 else
155 goto trunc;
156 }
157 if (i + optlen > len)
158 goto trunc;
159
160 switch (bp[i]) {
161 case IP6OPT_PAD1:
162 printf("(pad1)");
163 break;
164 case IP6OPT_PADN:
165 if (len - i < IP6OPT_MINLEN) {
166 printf("(padn: trunc)");
167 goto trunc;
168 }
169 printf("(padn)");
170 break;
171 case IP6OPT_ROUTER_ALERT:
172 if (len - i < IP6OPT_RTALERT_LEN) {
173 printf("(rtalert: trunc)");
174 goto trunc;
175 }
176 if (bp[i + 1] != IP6OPT_RTALERT_LEN - 2) {
177 printf("(rtalert: invalid len %d)", bp[i + 1]);
178 goto trunc;
179 }
180 printf("(rtalert: 0x%04x) ", ntohs(*(u_int16_t *)&bp[i + 2]));
181 break;
182 case IP6OPT_JUMBO:
183 if (len - i < IP6OPT_JUMBO_LEN) {
184 printf("(jumbo: trunc)");
185 goto trunc;
186 }
187 if (bp[i + 1] != IP6OPT_JUMBO_LEN - 2) {
188 printf("(jumbo: invalid len %d)", bp[i + 1]);
189 goto trunc;
190 }
191 printf("(jumbo: %u) ", (u_int32_t)ntohl(*(u_int32_t *)&bp[i + 2]));
192 break;
193 case IP6OPT_HOME_ADDRESS:
194 if (len - i < IP6OPT_HOMEADDR_MINLEN) {
195 printf("(homeaddr: trunc)");
196 goto trunc;
197 }
198 if (bp[i + 1] < IP6OPT_HOMEADDR_MINLEN - 2) {
199 printf("(homeaddr: invalid len %d)", bp[i + 1]);
200 goto trunc;
201 }
202 printf("(homeaddr: %s", ip6addr_string(&bp[i + 2]));
203 if (bp[i + 1] > IP6OPT_HOMEADDR_MINLEN - 2) {
204 ip6_sopt_print(&bp[i + IP6OPT_HOMEADDR_MINLEN],
205 (optlen - IP6OPT_HOMEADDR_MINLEN));
206 }
207 printf(")");
208 break;
209 case IP6OPT_BINDING_UPDATE:
210 if (len - i < IP6OPT_BU_MINLEN) {
211 printf("(bu: trunc)");
212 goto trunc;
213 }
214 if (bp[i + 1] < IP6OPT_BU_MINLEN - 2) {
215 printf("(bu: invalid len %d)", bp[i + 1]);
216 goto trunc;
217 }
218 printf("(bu: ");
219 if (bp[i + 2] & 0x80)
220 printf("A");
221 if (bp[i + 2] & 0x40)
222 printf("H");
223 if (bp[i + 2] & 0x20)
224 printf("S");
225 if (bp[i + 2] & 0x10)
226 printf("D");
227 if ((bp[i + 2] & 0x0f) || bp[i + 3] || bp[i + 4])
228 printf("res");
229 printf(", sequence: %u", bp[i + 5]);
230 printf(", lifetime: %u",
231 (u_int32_t)ntohl(*(u_int32_t *)&bp[i + 6]));
232
233 if (bp[i + 1] > IP6OPT_BU_MINLEN - 2) {
234 ip6_sopt_print(&bp[i + IP6OPT_BU_MINLEN],
235 (optlen - IP6OPT_BU_MINLEN));
236 }
237 printf(")");
238 break;
239 case IP6OPT_BINDING_ACK:
240 if (len - i < IP6OPT_BA_MINLEN) {
241 printf("(ba: trunc)");
242 goto trunc;
243 }
244 if (bp[i + 1] < IP6OPT_BA_MINLEN - 2) {
245 printf("(ba: invalid len %d)", bp[i + 1]);
246 goto trunc;
247 }
248 printf("(ba: ");
249 printf("status: %u", bp[i + 2]);
250 if (bp[i + 3])
251 printf("res");
252 printf(", sequence: %u", bp[i + 4]);
253 printf(", lifetime: %u",
254 (u_int32_t)ntohl(*(u_int32_t *)&bp[i + 5]));
255 printf(", refresh: %u",
256 (u_int32_t)ntohl(*(u_int32_t *)&bp[i + 9]));
257
258 if (bp[i + 1] > IP6OPT_BA_MINLEN - 2) {
259 ip6_sopt_print(&bp[i + IP6OPT_BA_MINLEN],
260 (optlen - IP6OPT_BA_MINLEN));
261 }
262 printf(")");
263 break;
264 case IP6OPT_BINDING_REQ:
265 if (len - i < IP6OPT_BR_MINLEN) {
266 printf("(br: trunc)");
267 goto trunc;
268 }
269 printf("(br");
270 if (bp[i + 1] > IP6OPT_BR_MINLEN - 2) {
271 ip6_sopt_print(&bp[i + IP6OPT_BR_MINLEN],
272 (optlen - IP6OPT_BR_MINLEN));
273 }
274 printf(")");
275 break;
276 default:
277 if (len - i < IP6OPT_MINLEN) {
278 printf("(type %d: trunc)", bp[i]);
279 goto trunc;
280 }
281 printf("(opt_type 0x%02x: len=%d) ", bp[i], bp[i + 1]);
282 break;
283 }
284 }
285
286 #if 0
287 end:
288 #endif
289 return;
290
291 trunc:
292 printf("[trunc] ");
293 }
294
295 int
296 hbhopt_print(register const u_char *bp)
297 {
298 const struct ip6_hbh *dp = (struct ip6_hbh *)bp;
299 register const u_char *ep;
300 int hbhlen = 0;
301
302 /* 'ep' points to the end of available data. */
303 ep = snapend;
304 TCHECK(dp->ip6h_len);
305 hbhlen = (int)((dp->ip6h_len + 1) << 3);
306 TCHECK2(*dp, hbhlen);
307 printf("HBH ");
308 if (vflag)
309 ip6_opt_print((const u_char *)dp + sizeof(*dp), hbhlen - sizeof(*dp));
310
311 return(hbhlen);
312
313 trunc:
314 fputs("[|HBH]", stdout);
315 return(hbhlen);
316 }
317
318 int
319 dstopt_print(register const u_char *bp)
320 {
321 const struct ip6_dest *dp = (struct ip6_dest *)bp;
322 register const u_char *ep;
323 int dstoptlen = 0;
324
325 /* 'ep' points to the end of available data. */
326 ep = snapend;
327 TCHECK(dp->ip6d_len);
328 dstoptlen = (int)((dp->ip6d_len + 1) << 3);
329 TCHECK2(*dp, dstoptlen);
330 printf("DSTOPT ");
331 if (vflag) {
332 ip6_opt_print((const u_char *)dp + sizeof(*dp),
333 dstoptlen - sizeof(*dp));
334 }
335
336 return(dstoptlen);
337
338 trunc:
339 fputs("[|DSTOPT]", stdout);
340 return(dstoptlen);
341 }
342 #endif /* INET6 */