]> The Tcpdump Group git mirrors - tcpdump/blob - print-ip6opts.c
Use more nd_print_invalid()
[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 /* \summary: IPv6 header option printer */
31
32 #ifdef HAVE_CONFIG_H
33 #include <config.h>
34 #endif
35
36 #include "netdissect-stdinc.h"
37
38 #include "netdissect.h"
39 #include "addrtoname.h"
40 #include "extract.h"
41
42 #include "ip6.h"
43
44 static int
45 ip6_sopt_print(netdissect_options *ndo, const u_char *bp, int len)
46 {
47 int i;
48 int optlen;
49
50 for (i = 0; i < len; i += optlen) {
51 if (EXTRACT_U_1(bp + i) == IP6OPT_PAD1)
52 optlen = 1;
53 else {
54 if (i + 1 < len)
55 optlen = EXTRACT_U_1(bp + i + 1) + 2;
56 else
57 goto trunc;
58 }
59 if (i + optlen > len)
60 goto trunc;
61
62 switch (EXTRACT_U_1(bp + i)) {
63 case IP6OPT_PAD1:
64 ND_PRINT(", pad1");
65 break;
66 case IP6OPT_PADN:
67 if (len - i < IP6OPT_MINLEN) {
68 ND_PRINT(", padn: trunc");
69 goto trunc;
70 }
71 ND_PRINT(", padn");
72 break;
73 default:
74 if (len - i < IP6OPT_MINLEN) {
75 ND_PRINT(", sopt_type %u: trunc)", EXTRACT_U_1(bp + i));
76 goto trunc;
77 }
78 ND_PRINT(", sopt_type 0x%02x: len=%u", EXTRACT_U_1(bp + i), EXTRACT_U_1(bp + i + 1));
79 break;
80 }
81 }
82 return 0;
83
84 trunc:
85 return -1;
86 }
87
88 static int
89 ip6_opt_print(netdissect_options *ndo, const u_char *bp, int len)
90 {
91 int i;
92 int optlen = 0;
93
94 if (len == 0)
95 return 0;
96 for (i = 0; i < len; i += optlen) {
97 if (EXTRACT_U_1(bp + i) == IP6OPT_PAD1)
98 optlen = 1;
99 else {
100 if (i + 1 < len)
101 optlen = EXTRACT_U_1(bp + i + 1) + 2;
102 else
103 goto trunc;
104 }
105 if (i + optlen > len)
106 goto trunc;
107
108 switch (EXTRACT_U_1(bp + i)) {
109 case IP6OPT_PAD1:
110 ND_PRINT("(pad1)");
111 break;
112 case IP6OPT_PADN:
113 if (len - i < IP6OPT_MINLEN) {
114 ND_PRINT("(padn: trunc)");
115 goto trunc;
116 }
117 ND_PRINT("(padn)");
118 break;
119 case IP6OPT_ROUTER_ALERT:
120 if (len - i < IP6OPT_RTALERT_LEN) {
121 ND_PRINT("(rtalert: trunc)");
122 goto trunc;
123 }
124 if (EXTRACT_U_1(bp + i + 1) != IP6OPT_RTALERT_LEN - 2) {
125 ND_PRINT("(rtalert: invalid len %u)", EXTRACT_U_1(bp + i + 1));
126 goto trunc;
127 }
128 ND_PRINT("(rtalert: 0x%04x) ", EXTRACT_BE_U_2(bp + i + 2));
129 break;
130 case IP6OPT_JUMBO:
131 if (len - i < IP6OPT_JUMBO_LEN) {
132 ND_PRINT("(jumbo: trunc)");
133 goto trunc;
134 }
135 if (EXTRACT_U_1(bp + i + 1) != IP6OPT_JUMBO_LEN - 2) {
136 ND_PRINT("(jumbo: invalid len %u)", EXTRACT_U_1(bp + i + 1));
137 goto trunc;
138 }
139 ND_PRINT("(jumbo: %u) ", EXTRACT_BE_U_4(bp + i + 2));
140 break;
141 case IP6OPT_HOME_ADDRESS:
142 if (len - i < IP6OPT_HOMEADDR_MINLEN) {
143 ND_PRINT("(homeaddr: trunc)");
144 goto trunc;
145 }
146 if (EXTRACT_U_1(bp + i + 1) < IP6OPT_HOMEADDR_MINLEN - 2) {
147 ND_PRINT("(homeaddr: invalid len %u)", EXTRACT_U_1(bp + i + 1));
148 goto trunc;
149 }
150 ND_PRINT("(homeaddr: %s", ip6addr_string(ndo, bp + i + 2));
151 if (EXTRACT_U_1(bp + i + 1) > IP6OPT_HOMEADDR_MINLEN - 2) {
152 if (ip6_sopt_print(ndo, bp + i + IP6OPT_HOMEADDR_MINLEN,
153 (optlen - IP6OPT_HOMEADDR_MINLEN)) == -1)
154 goto trunc;
155 }
156 ND_PRINT(")");
157 break;
158 default:
159 if (len - i < IP6OPT_MINLEN) {
160 ND_PRINT("(type %u: trunc)", EXTRACT_U_1(bp + i));
161 goto trunc;
162 }
163 ND_PRINT("(opt_type 0x%02x: len=%u)", EXTRACT_U_1(bp + i), EXTRACT_U_1(bp + i + 1));
164 break;
165 }
166 }
167 ND_PRINT(" ");
168 return 0;
169
170 trunc:
171 return -1;
172 }
173
174 int
175 hbhopt_print(netdissect_options *ndo, const u_char *bp)
176 {
177 const struct ip6_hbh *dp = (const struct ip6_hbh *)bp;
178 u_int hbhlen = 0;
179
180 ndo->ndo_protocol = "hbhopt";
181 ND_TCHECK_1(dp->ip6h_len);
182 hbhlen = (EXTRACT_U_1(dp->ip6h_len) + 1) << 3;
183 ND_TCHECK_LEN(dp, hbhlen);
184 ND_PRINT("HBH ");
185 if (ndo->ndo_vflag)
186 if (ip6_opt_print(ndo, (const u_char *)dp + sizeof(*dp),
187 hbhlen - sizeof(*dp)) == -1)
188 goto trunc;
189 return hbhlen;
190
191 trunc:
192 nd_print_trunc(ndo);
193 return -1;
194 }
195
196 int
197 dstopt_print(netdissect_options *ndo, const u_char *bp)
198 {
199 const struct ip6_dest *dp = (const struct ip6_dest *)bp;
200 u_int dstoptlen = 0;
201
202 ndo->ndo_protocol = "dstopt";
203 ND_TCHECK_1(dp->ip6d_len);
204 dstoptlen = (EXTRACT_U_1(dp->ip6d_len) + 1) << 3;
205 ND_TCHECK_LEN(dp, dstoptlen);
206 ND_PRINT("DSTOPT ");
207 if (ndo->ndo_vflag) {
208 if (ip6_opt_print(ndo, (const u_char *)dp + sizeof(*dp),
209 dstoptlen - sizeof(*dp)) == -1)
210 goto trunc;
211 }
212
213 return dstoptlen;
214
215 trunc:
216 nd_print_trunc(ndo);
217 return -1;
218 }