xref: /dragonfly/contrib/tcpdump/print-ip6opts.c (revision 279dd846)
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     if (len == 0)
145         return;
146     for (i = 0; i < len; i += optlen) {
147 	if (bp[i] == IP6OPT_PAD1)
148 	    optlen = 1;
149 	else {
150 	    if (i + 1 < len)
151 		optlen = bp[i + 1] + 2;
152 	    else
153 		goto trunc;
154 	}
155 	if (i + optlen > len)
156 	    goto trunc;
157 
158 	switch (bp[i]) {
159 	case IP6OPT_PAD1:
160             printf("(pad1)");
161 	    break;
162 	case IP6OPT_PADN:
163 	    if (len - i < IP6OPT_MINLEN) {
164 		printf("(padn: trunc)");
165 		goto trunc;
166 	    }
167             printf("(padn)");
168 	    break;
169 	case IP6OPT_ROUTER_ALERT:
170 	    if (len - i < IP6OPT_RTALERT_LEN) {
171 		printf("(rtalert: trunc)");
172 		goto trunc;
173 	    }
174 	    if (bp[i + 1] != IP6OPT_RTALERT_LEN - 2) {
175 		printf("(rtalert: invalid len %d)", bp[i + 1]);
176 		goto trunc;
177 	    }
178 	    printf("(rtalert: 0x%04x) ", EXTRACT_16BITS(&bp[i + 2]));
179 	    break;
180 	case IP6OPT_JUMBO:
181 	    if (len - i < IP6OPT_JUMBO_LEN) {
182 		printf("(jumbo: trunc)");
183 		goto trunc;
184 	    }
185 	    if (bp[i + 1] != IP6OPT_JUMBO_LEN - 2) {
186 		printf("(jumbo: invalid len %d)", bp[i + 1]);
187 		goto trunc;
188 	    }
189 	    printf("(jumbo: %u) ", EXTRACT_32BITS(&bp[i + 2]));
190 	    break;
191         case IP6OPT_HOME_ADDRESS:
192 	    if (len - i < IP6OPT_HOMEADDR_MINLEN) {
193 		printf("(homeaddr: trunc)");
194 		goto trunc;
195 	    }
196 	    if (bp[i + 1] < IP6OPT_HOMEADDR_MINLEN - 2) {
197 		printf("(homeaddr: invalid len %d)", bp[i + 1]);
198 		goto trunc;
199 	    }
200 	    printf("(homeaddr: %s", ip6addr_string(&bp[i + 2]));
201             if (bp[i + 1] > IP6OPT_HOMEADDR_MINLEN - 2) {
202 		ip6_sopt_print(&bp[i + IP6OPT_HOMEADDR_MINLEN],
203 		    (optlen - IP6OPT_HOMEADDR_MINLEN));
204 	    }
205             printf(")");
206 	    break;
207         case IP6OPT_BINDING_UPDATE:
208 	    if (len - i < IP6OPT_BU_MINLEN) {
209 		printf("(bu: trunc)");
210 		goto trunc;
211 	    }
212 	    if (bp[i + 1] < IP6OPT_BU_MINLEN - 2) {
213 		printf("(bu: invalid len %d)", bp[i + 1]);
214 		goto trunc;
215 	    }
216 	    printf("(bu: ");
217 	    if (bp[i + 2] & 0x80)
218 		    printf("A");
219 	    if (bp[i + 2] & 0x40)
220 		    printf("H");
221 	    if (bp[i + 2] & 0x20)
222 		    printf("S");
223 	    if (bp[i + 2] & 0x10)
224 		    printf("D");
225 	    if ((bp[i + 2] & 0x0f) || bp[i + 3] || bp[i + 4])
226 		    printf("res");
227 	    printf(", sequence: %u", bp[i + 5]);
228 	    printf(", lifetime: %u", EXTRACT_32BITS(&bp[i + 6]));
229 
230 	    if (bp[i + 1] > IP6OPT_BU_MINLEN - 2) {
231 		ip6_sopt_print(&bp[i + IP6OPT_BU_MINLEN],
232 		    (optlen - IP6OPT_BU_MINLEN));
233 	    }
234 	    printf(")");
235 	    break;
236 	case IP6OPT_BINDING_ACK:
237 	    if (len - i < IP6OPT_BA_MINLEN) {
238 		printf("(ba: trunc)");
239 		goto trunc;
240 	    }
241 	    if (bp[i + 1] < IP6OPT_BA_MINLEN - 2) {
242 		printf("(ba: invalid len %d)", bp[i + 1]);
243 		goto trunc;
244 	    }
245 	    printf("(ba: ");
246 	    printf("status: %u", bp[i + 2]);
247 	    if (bp[i + 3])
248 		    printf("res");
249 	    printf(", sequence: %u", bp[i + 4]);
250 	    printf(", lifetime: %u", EXTRACT_32BITS(&bp[i + 5]));
251 	    printf(", refresh: %u", EXTRACT_32BITS(&bp[i + 9]));
252 
253 	    if (bp[i + 1] > IP6OPT_BA_MINLEN - 2) {
254 		ip6_sopt_print(&bp[i + IP6OPT_BA_MINLEN],
255 		    (optlen - IP6OPT_BA_MINLEN));
256 	    }
257             printf(")");
258 	    break;
259         case IP6OPT_BINDING_REQ:
260 	    if (len - i < IP6OPT_BR_MINLEN) {
261 		printf("(br: trunc)");
262 		goto trunc;
263 	    }
264             printf("(br");
265             if (bp[i + 1] > IP6OPT_BR_MINLEN - 2) {
266 		ip6_sopt_print(&bp[i + IP6OPT_BR_MINLEN],
267 		    (optlen - IP6OPT_BR_MINLEN));
268 	    }
269             printf(")");
270 	    break;
271 	default:
272 	    if (len - i < IP6OPT_MINLEN) {
273 		printf("(type %d: trunc)", bp[i]);
274 		goto trunc;
275 	    }
276 	    printf("(opt_type 0x%02x: len=%d)", bp[i], bp[i + 1]);
277 	    break;
278 	}
279     }
280     printf(" ");
281 
282 #if 0
283 end:
284 #endif
285     return;
286 
287 trunc:
288     printf("[trunc] ");
289 }
290 
291 int
292 hbhopt_print(register const u_char *bp)
293 {
294     const struct ip6_hbh *dp = (struct ip6_hbh *)bp;
295     int hbhlen = 0;
296 
297     TCHECK(dp->ip6h_len);
298     hbhlen = (int)((dp->ip6h_len + 1) << 3);
299     TCHECK2(*dp, hbhlen);
300     printf("HBH ");
301     if (vflag)
302 	ip6_opt_print((const u_char *)dp + sizeof(*dp), hbhlen - sizeof(*dp));
303 
304     return(hbhlen);
305 
306   trunc:
307     fputs("[|HBH]", stdout);
308     return(-1);
309 }
310 
311 int
312 dstopt_print(register const u_char *bp)
313 {
314     const struct ip6_dest *dp = (struct ip6_dest *)bp;
315     int dstoptlen = 0;
316 
317     TCHECK(dp->ip6d_len);
318     dstoptlen = (int)((dp->ip6d_len + 1) << 3);
319     TCHECK2(*dp, dstoptlen);
320     printf("DSTOPT ");
321     if (vflag) {
322 	ip6_opt_print((const u_char *)dp + sizeof(*dp),
323 	    dstoptlen - sizeof(*dp));
324     }
325 
326     return(dstoptlen);
327 
328   trunc:
329     fputs("[|DSTOPT]", stdout);
330     return(-1);
331 }
332 #endif /* INET6 */
333