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