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