]> The Tcpdump Group git mirrors - tcpdump/blob - print-ip6opts.c
Use the new GET_ macros instead of the EXTRACT_ ones
[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 (GET_U_1(bp + i) == IP6OPT_PAD1)
52 optlen = 1;
53 else {
54 if (i + 1 < len)
55 optlen = GET_U_1(bp + i + 1) + 2;
56 else
57 goto trunc;
58 }
59 if (i + optlen > len)
60 goto trunc;
61
62 switch (GET_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)", GET_U_1(bp + i));
76 goto trunc;
77 }
78 ND_PRINT(", sopt_type 0x%02x: len=%u", GET_U_1(bp + i),
79 GET_U_1(bp + i + 1));
80 break;
81 }
82 }
83 return 0;
84
85 trunc:
86 return -1;
87 }
88
89 static int
90 ip6_opt_print(netdissect_options *ndo, const u_char *bp, int len)
91 {
92 int i;
93 int optlen = 0;
94
95 if (len == 0)
96 return 0;
97 for (i = 0; i < len; i += optlen) {
98 if (GET_U_1(bp + i) == IP6OPT_PAD1)
99 optlen = 1;
100 else {
101 if (i + 1 < len)
102 optlen = GET_U_1(bp + i + 1) + 2;
103 else
104 goto trunc;
105 }
106 if (i + optlen > len)
107 goto trunc;
108
109 switch (GET_U_1(bp + i)) {
110 case IP6OPT_PAD1:
111 ND_PRINT("(pad1)");
112 break;
113 case IP6OPT_PADN:
114 if (len - i < IP6OPT_MINLEN) {
115 ND_PRINT("(padn: trunc)");
116 goto trunc;
117 }
118 ND_PRINT("(padn)");
119 break;
120 case IP6OPT_ROUTER_ALERT:
121 if (len - i < IP6OPT_RTALERT_LEN) {
122 ND_PRINT("(rtalert: trunc)");
123 goto trunc;
124 }
125 if (GET_U_1(bp + i + 1) != IP6OPT_RTALERT_LEN - 2) {
126 ND_PRINT("(rtalert: invalid len %u)", GET_U_1(bp + i + 1));
127 goto trunc;
128 }
129 ND_PRINT("(rtalert: 0x%04x) ", GET_BE_U_2(bp + i + 2));
130 break;
131 case IP6OPT_JUMBO:
132 if (len - i < IP6OPT_JUMBO_LEN) {
133 ND_PRINT("(jumbo: trunc)");
134 goto trunc;
135 }
136 if (GET_U_1(bp + i + 1) != IP6OPT_JUMBO_LEN - 2) {
137 ND_PRINT("(jumbo: invalid len %u)", GET_U_1(bp + i + 1));
138 goto trunc;
139 }
140 ND_PRINT("(jumbo: %u) ", GET_BE_U_4(bp + i + 2));
141 break;
142 case IP6OPT_HOME_ADDRESS:
143 if (len - i < IP6OPT_HOMEADDR_MINLEN) {
144 ND_PRINT("(homeaddr: trunc)");
145 goto trunc;
146 }
147 if (GET_U_1(bp + i + 1) < IP6OPT_HOMEADDR_MINLEN - 2) {
148 ND_PRINT("(homeaddr: invalid len %u)", GET_U_1(bp + i + 1));
149 goto trunc;
150 }
151 ND_PRINT("(homeaddr: %s", ip6addr_string(ndo, bp + i + 2));
152 if (GET_U_1(bp + i + 1) > IP6OPT_HOMEADDR_MINLEN - 2) {
153 if (ip6_sopt_print(ndo, bp + i + IP6OPT_HOMEADDR_MINLEN,
154 (optlen - IP6OPT_HOMEADDR_MINLEN)) == -1)
155 goto trunc;
156 }
157 ND_PRINT(")");
158 break;
159 default:
160 if (len - i < IP6OPT_MINLEN) {
161 ND_PRINT("(type %u: trunc)", GET_U_1(bp + i));
162 goto trunc;
163 }
164 ND_PRINT("(opt_type 0x%02x: len=%u)", GET_U_1(bp + i),
165 GET_U_1(bp + i + 1));
166 break;
167 }
168 }
169 ND_PRINT(" ");
170 return 0;
171
172 trunc:
173 return -1;
174 }
175
176 int
177 hbhopt_print(netdissect_options *ndo, const u_char *bp)
178 {
179 const struct ip6_hbh *dp = (const struct ip6_hbh *)bp;
180 u_int hbhlen = 0;
181
182 ndo->ndo_protocol = "hbhopt";
183 ND_TCHECK_1(dp->ip6h_len);
184 hbhlen = (GET_U_1(dp->ip6h_len) + 1) << 3;
185 ND_TCHECK_LEN(dp, hbhlen);
186 ND_PRINT("HBH ");
187 if (ndo->ndo_vflag)
188 if (ip6_opt_print(ndo, (const u_char *)dp + sizeof(*dp),
189 hbhlen - sizeof(*dp)) == -1)
190 goto trunc;
191 return hbhlen;
192
193 trunc:
194 nd_print_trunc(ndo);
195 return -1;
196 }
197
198 int
199 dstopt_print(netdissect_options *ndo, const u_char *bp)
200 {
201 const struct ip6_dest *dp = (const struct ip6_dest *)bp;
202 u_int dstoptlen = 0;
203
204 ndo->ndo_protocol = "dstopt";
205 ND_TCHECK_1(dp->ip6d_len);
206 dstoptlen = (GET_U_1(dp->ip6d_len) + 1) << 3;
207 ND_TCHECK_LEN(dp, dstoptlen);
208 ND_PRINT("DSTOPT ");
209 if (ndo->ndo_vflag) {
210 if (ip6_opt_print(ndo, (const u_char *)dp + sizeof(*dp),
211 dstoptlen - sizeof(*dp)) == -1)
212 goto trunc;
213 }
214
215 return dstoptlen;
216
217 trunc:
218 nd_print_trunc(ndo);
219 return -1;
220 }