]> The Tcpdump Group git mirrors - tcpdump/blob - print-ip6opts.c
remove tcpdump's own CVS keywords
[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 #ifdef INET6
35 #include <tcpdump-stdinc.h>
36
37 #include <stdio.h>
38
39 #include "ip6.h"
40
41 #include "interface.h"
42 #include "addrtoname.h"
43 #include "extract.h"
44
45 /* items outside of rfc2292bis */
46 #ifndef IP6OPT_MINLEN
47 #define IP6OPT_MINLEN 2
48 #endif
49 #ifndef IP6OPT_RTALERT_LEN
50 #define IP6OPT_RTALERT_LEN 4
51 #endif
52 #ifndef IP6OPT_JUMBO_LEN
53 #define IP6OPT_JUMBO_LEN 6
54 #endif
55 #define IP6OPT_HOMEADDR_MINLEN 18
56 #define IP6OPT_BU_MINLEN 10
57 #define IP6OPT_BA_MINLEN 13
58 #define IP6OPT_BR_MINLEN 2
59 #define IP6SOPT_UI 0x2
60 #define IP6SOPT_UI_MINLEN 4
61 #define IP6SOPT_ALTCOA 0x3
62 #define IP6SOPT_ALTCOA_MINLEN 18
63 #define IP6SOPT_AUTH 0x4
64 #define IP6SOPT_AUTH_MINLEN 6
65
66 static void ip6_sopt_print(const u_char *, int);
67
68 static void
69 ip6_sopt_print(const u_char *bp, int len)
70 {
71 int i;
72 int optlen;
73
74 for (i = 0; i < len; i += optlen) {
75 if (bp[i] == IP6OPT_PAD1)
76 optlen = 1;
77 else {
78 if (i + 1 < len)
79 optlen = bp[i + 1] + 2;
80 else
81 goto trunc;
82 }
83 if (i + optlen > len)
84 goto trunc;
85
86 switch (bp[i]) {
87 case IP6OPT_PAD1:
88 printf(", pad1");
89 break;
90 case IP6OPT_PADN:
91 if (len - i < IP6OPT_MINLEN) {
92 printf(", padn: trunc");
93 goto trunc;
94 }
95 printf(", padn");
96 break;
97 case IP6SOPT_UI:
98 if (len - i < IP6SOPT_UI_MINLEN) {
99 printf(", ui: trunc");
100 goto trunc;
101 }
102 printf(", ui: 0x%04x ", EXTRACT_16BITS(&bp[i + 2]));
103 break;
104 case IP6SOPT_ALTCOA:
105 if (len - i < IP6SOPT_ALTCOA_MINLEN) {
106 printf(", altcoa: trunc");
107 goto trunc;
108 }
109 printf(", alt-CoA: %s", ip6addr_string(&bp[i+2]));
110 break;
111 case IP6SOPT_AUTH:
112 if (len - i < IP6SOPT_AUTH_MINLEN) {
113 printf(", auth: trunc");
114 goto trunc;
115 }
116 printf(", auth spi: 0x%08x", EXTRACT_32BITS(&bp[i + 2]));
117 break;
118 default:
119 if (len - i < IP6OPT_MINLEN) {
120 printf(", sopt_type %d: trunc)", bp[i]);
121 goto trunc;
122 }
123 printf(", sopt_type 0x%02x: len=%d", bp[i], bp[i + 1]);
124 break;
125 }
126 }
127 return;
128
129 trunc:
130 printf("[trunc] ");
131 }
132
133 void
134 ip6_opt_print(const u_char *bp, int len)
135 {
136 int i;
137 int optlen = 0;
138
139 if (len == 0)
140 return;
141 for (i = 0; i < len; i += optlen) {
142 if (bp[i] == IP6OPT_PAD1)
143 optlen = 1;
144 else {
145 if (i + 1 < len)
146 optlen = bp[i + 1] + 2;
147 else
148 goto trunc;
149 }
150 if (i + optlen > len)
151 goto trunc;
152
153 switch (bp[i]) {
154 case IP6OPT_PAD1:
155 printf("(pad1)");
156 break;
157 case IP6OPT_PADN:
158 if (len - i < IP6OPT_MINLEN) {
159 printf("(padn: trunc)");
160 goto trunc;
161 }
162 printf("(padn)");
163 break;
164 case IP6OPT_ROUTER_ALERT:
165 if (len - i < IP6OPT_RTALERT_LEN) {
166 printf("(rtalert: trunc)");
167 goto trunc;
168 }
169 if (bp[i + 1] != IP6OPT_RTALERT_LEN - 2) {
170 printf("(rtalert: invalid len %d)", bp[i + 1]);
171 goto trunc;
172 }
173 printf("(rtalert: 0x%04x) ", EXTRACT_16BITS(&bp[i + 2]));
174 break;
175 case IP6OPT_JUMBO:
176 if (len - i < IP6OPT_JUMBO_LEN) {
177 printf("(jumbo: trunc)");
178 goto trunc;
179 }
180 if (bp[i + 1] != IP6OPT_JUMBO_LEN - 2) {
181 printf("(jumbo: invalid len %d)", bp[i + 1]);
182 goto trunc;
183 }
184 printf("(jumbo: %u) ", EXTRACT_32BITS(&bp[i + 2]));
185 break;
186 case IP6OPT_HOME_ADDRESS:
187 if (len - i < IP6OPT_HOMEADDR_MINLEN) {
188 printf("(homeaddr: trunc)");
189 goto trunc;
190 }
191 if (bp[i + 1] < IP6OPT_HOMEADDR_MINLEN - 2) {
192 printf("(homeaddr: invalid len %d)", bp[i + 1]);
193 goto trunc;
194 }
195 printf("(homeaddr: %s", ip6addr_string(&bp[i + 2]));
196 if (bp[i + 1] > IP6OPT_HOMEADDR_MINLEN - 2) {
197 ip6_sopt_print(&bp[i + IP6OPT_HOMEADDR_MINLEN],
198 (optlen - IP6OPT_HOMEADDR_MINLEN));
199 }
200 printf(")");
201 break;
202 case IP6OPT_BINDING_UPDATE:
203 if (len - i < IP6OPT_BU_MINLEN) {
204 printf("(bu: trunc)");
205 goto trunc;
206 }
207 if (bp[i + 1] < IP6OPT_BU_MINLEN - 2) {
208 printf("(bu: invalid len %d)", bp[i + 1]);
209 goto trunc;
210 }
211 printf("(bu: ");
212 if (bp[i + 2] & 0x80)
213 printf("A");
214 if (bp[i + 2] & 0x40)
215 printf("H");
216 if (bp[i + 2] & 0x20)
217 printf("S");
218 if (bp[i + 2] & 0x10)
219 printf("D");
220 if ((bp[i + 2] & 0x0f) || bp[i + 3] || bp[i + 4])
221 printf("res");
222 printf(", sequence: %u", bp[i + 5]);
223 printf(", lifetime: %u", EXTRACT_32BITS(&bp[i + 6]));
224
225 if (bp[i + 1] > IP6OPT_BU_MINLEN - 2) {
226 ip6_sopt_print(&bp[i + IP6OPT_BU_MINLEN],
227 (optlen - IP6OPT_BU_MINLEN));
228 }
229 printf(")");
230 break;
231 case IP6OPT_BINDING_ACK:
232 if (len - i < IP6OPT_BA_MINLEN) {
233 printf("(ba: trunc)");
234 goto trunc;
235 }
236 if (bp[i + 1] < IP6OPT_BA_MINLEN - 2) {
237 printf("(ba: invalid len %d)", bp[i + 1]);
238 goto trunc;
239 }
240 printf("(ba: ");
241 printf("status: %u", bp[i + 2]);
242 if (bp[i + 3])
243 printf("res");
244 printf(", sequence: %u", bp[i + 4]);
245 printf(", lifetime: %u", EXTRACT_32BITS(&bp[i + 5]));
246 printf(", refresh: %u", EXTRACT_32BITS(&bp[i + 9]));
247
248 if (bp[i + 1] > IP6OPT_BA_MINLEN - 2) {
249 ip6_sopt_print(&bp[i + IP6OPT_BA_MINLEN],
250 (optlen - IP6OPT_BA_MINLEN));
251 }
252 printf(")");
253 break;
254 case IP6OPT_BINDING_REQ:
255 if (len - i < IP6OPT_BR_MINLEN) {
256 printf("(br: trunc)");
257 goto trunc;
258 }
259 printf("(br");
260 if (bp[i + 1] > IP6OPT_BR_MINLEN - 2) {
261 ip6_sopt_print(&bp[i + IP6OPT_BR_MINLEN],
262 (optlen - IP6OPT_BR_MINLEN));
263 }
264 printf(")");
265 break;
266 default:
267 if (len - i < IP6OPT_MINLEN) {
268 printf("(type %d: trunc)", bp[i]);
269 goto trunc;
270 }
271 printf("(opt_type 0x%02x: len=%d)", bp[i], bp[i + 1]);
272 break;
273 }
274 }
275 printf(" ");
276
277 #if 0
278 end:
279 #endif
280 return;
281
282 trunc:
283 printf("[trunc] ");
284 }
285
286 int
287 hbhopt_print(register const u_char *bp)
288 {
289 const struct ip6_hbh *dp = (struct ip6_hbh *)bp;
290 int hbhlen = 0;
291
292 TCHECK(dp->ip6h_len);
293 hbhlen = (int)((dp->ip6h_len + 1) << 3);
294 TCHECK2(*dp, hbhlen);
295 printf("HBH ");
296 if (vflag)
297 ip6_opt_print((const u_char *)dp + sizeof(*dp), hbhlen - sizeof(*dp));
298
299 return(hbhlen);
300
301 trunc:
302 fputs("[|HBH]", stdout);
303 return(-1);
304 }
305
306 int
307 dstopt_print(register const u_char *bp)
308 {
309 const struct ip6_dest *dp = (struct ip6_dest *)bp;
310 int dstoptlen = 0;
311
312 TCHECK(dp->ip6d_len);
313 dstoptlen = (int)((dp->ip6d_len + 1) << 3);
314 TCHECK2(*dp, dstoptlen);
315 printf("DSTOPT ");
316 if (vflag) {
317 ip6_opt_print((const u_char *)dp + sizeof(*dp),
318 dstoptlen - sizeof(*dp));
319 }
320
321 return(dstoptlen);
322
323 trunc:
324 fputs("[|DSTOPT]", stdout);
325 return(-1);
326 }
327 #endif /* INET6 */