]> The Tcpdump Group git mirrors - tcpdump/blob - print-ip6.c
Fix compilation warnings:
[tcpdump] / print-ip6.c
1 /*
2 * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that: (1) source code distributions
7 * retain the above copyright notice and this paragraph in its entirety, (2)
8 * distributions including binary code include the above copyright notice and
9 * this paragraph in its entirety in the documentation or other materials
10 * provided with the distribution, and (3) all advertising materials mentioning
11 * features or use of this software display the following acknowledgement:
12 * ``This product includes software developed by the University of California,
13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14 * the University nor the names of its contributors may be used to endorse
15 * or promote products derived from this software without specific prior
16 * written permission.
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 */
21
22 #ifndef lint
23 static const char rcsid[] _U_ =
24 "@(#) $Header: /tcpdump/master/tcpdump/print-ip6.c,v 1.52 2007-09-21 07:05:33 hannes Exp $";
25 #endif
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #ifdef INET6
32
33 #include <tcpdump-stdinc.h>
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38
39 #include "netdissect.h"
40 #include "interface.h"
41 #include "addrtoname.h"
42 #include "extract.h"
43
44 #include "ip6.h"
45 #include "ipproto.h"
46
47 /*
48 * Compute a V6-style checksum by building a pseudoheader.
49 */
50 int
51 nextproto6_cksum(const struct ip6_hdr *ip6, const u_int8_t *data,
52 u_int len, u_int next_proto)
53 {
54 struct {
55 struct in6_addr ph_src;
56 struct in6_addr ph_dst;
57 u_int32_t ph_len;
58 u_int8_t ph_zero[3];
59 u_int8_t ph_nxt;
60 } ph;
61 struct cksum_vec vec[2];
62
63 /* pseudo-header */
64 memset(&ph, 0, sizeof(ph));
65 ph.ph_src = ip6->ip6_src;
66 ph.ph_dst = ip6->ip6_dst;
67 ph.ph_len = htonl(len);
68 ph.ph_nxt = next_proto;
69
70 vec[0].ptr = (const u_int8_t *)(void *)&ph;
71 vec[0].len = sizeof(ph);
72 vec[1].ptr = data;
73 vec[1].len = len;
74
75 return in_cksum(vec, 2);
76 }
77
78 /*
79 * print an IP6 datagram.
80 */
81 void
82 ip6_print(netdissect_options *ndo, const u_char *bp, u_int length)
83 {
84 register const struct ip6_hdr *ip6;
85 register int advance;
86 u_int len;
87 const u_char *ipend;
88 register const u_char *cp;
89 register u_int payload_len;
90 int nh;
91 int fragmented = 0;
92 u_int flow;
93
94 ip6 = (const struct ip6_hdr *)bp;
95
96 TCHECK(*ip6);
97 if (length < sizeof (struct ip6_hdr)) {
98 (void)ND_PRINT((ndo, "truncated-ip6 %u", length));
99 return;
100 }
101
102 if (!ndo->ndo_eflag)
103 ND_PRINT((ndo, "IP6 "));
104
105 if (IP6_VERSION(ip6) != 6) {
106 printf("version error: %u != 6", IP6_VERSION(ip6));
107 return;
108 }
109
110 payload_len = EXTRACT_16BITS(&ip6->ip6_plen);
111 len = payload_len + sizeof(struct ip6_hdr);
112 if (length < len)
113 (void)ND_PRINT((ndo, "truncated-ip6 - %u bytes missing!",
114 len - length));
115
116 if (ndo->ndo_vflag) {
117 flow = EXTRACT_32BITS(&ip6->ip6_flow);
118 ND_PRINT((ndo, "("));
119 #if 0
120 /* rfc1883 */
121 if (flow & 0x0f000000)
122 (void)ND_PRINT((ndo, "pri 0x%02x, ", (flow & 0x0f000000) >> 24));
123 if (flow & 0x00ffffff)
124 (void)ND_PRINT((ndo, "flowlabel 0x%06x, ", flow & 0x00ffffff));
125 #else
126 /* RFC 2460 */
127 if (flow & 0x0ff00000)
128 (void)ND_PRINT((ndo, "class 0x%02x, ", (flow & 0x0ff00000) >> 20));
129 if (flow & 0x000fffff)
130 (void)ND_PRINT((ndo, "flowlabel 0x%05x, ", flow & 0x000fffff));
131 #endif
132
133 (void)ND_PRINT((ndo, "hlim %u, next-header %s (%u) payload length: %u) ",
134 ip6->ip6_hlim,
135 tok2str(ipproto_values,"unknown",ip6->ip6_nxt),
136 ip6->ip6_nxt,
137 payload_len));
138 }
139
140 /*
141 * Cut off the snapshot length to the end of the IP payload.
142 */
143 ipend = bp + len;
144 if (ipend < ndo->ndo_snapend)
145 ndo->ndo_snapend = ipend;
146
147 cp = (const u_char *)ip6;
148 advance = sizeof(struct ip6_hdr);
149 nh = ip6->ip6_nxt;
150 while (cp < ndo->ndo_snapend && advance > 0) {
151 cp += advance;
152 len -= advance;
153
154 if (cp == (const u_char *)(ip6 + 1) &&
155 nh != IPPROTO_TCP && nh != IPPROTO_UDP &&
156 nh != IPPROTO_DCCP && nh != IPPROTO_SCTP) {
157 (void)ND_PRINT((ndo, "%s > %s: ", ip6addr_string(&ip6->ip6_src),
158 ip6addr_string(&ip6->ip6_dst)));
159 }
160
161 switch (nh) {
162 case IPPROTO_HOPOPTS:
163 advance = hbhopt_print(cp);
164 nh = *cp;
165 break;
166 case IPPROTO_DSTOPTS:
167 advance = dstopt_print(cp);
168 nh = *cp;
169 break;
170 case IPPROTO_FRAGMENT:
171 advance = frag6_print(cp, (const u_char *)ip6);
172 if (ndo->ndo_snapend <= cp + advance)
173 return;
174 nh = *cp;
175 fragmented = 1;
176 break;
177
178 case IPPROTO_MOBILITY_OLD:
179 case IPPROTO_MOBILITY:
180 /*
181 * XXX - we don't use "advance"; the current
182 * "Mobility Support in IPv6" draft
183 * (draft-ietf-mobileip-ipv6-24) says that
184 * the next header field in a mobility header
185 * should be IPPROTO_NONE, but speaks of
186 * the possiblity of a future extension in
187 * which payload can be piggybacked atop a
188 * mobility header.
189 */
190 advance = mobility_print(cp, (const u_char *)ip6);
191 nh = *cp;
192 return;
193 case IPPROTO_ROUTING:
194 advance = rt6_print(cp, (const u_char *)ip6);
195 nh = *cp;
196 break;
197 case IPPROTO_SCTP:
198 sctp_print(cp, (const u_char *)ip6, len);
199 return;
200 case IPPROTO_DCCP:
201 dccp_print(cp, (const u_char *)ip6, len);
202 return;
203 case IPPROTO_TCP:
204 tcp_print(cp, len, (const u_char *)ip6, fragmented);
205 return;
206 case IPPROTO_UDP:
207 udp_print(cp, len, (const u_char *)ip6, fragmented);
208 return;
209 case IPPROTO_ICMPV6:
210 icmp6_print(ndo, cp, len, (const u_char *)ip6, fragmented);
211 return;
212 case IPPROTO_AH:
213 advance = ah_print(cp);
214 nh = *cp;
215 break;
216 case IPPROTO_ESP:
217 {
218 int enh, padlen;
219 advance = esp_print(ndo, cp, len, (const u_char *)ip6, &enh, &padlen);
220 nh = enh & 0xff;
221 len -= padlen;
222 break;
223 }
224 case IPPROTO_IPCOMP:
225 {
226 int enh;
227 advance = ipcomp_print(cp, &enh);
228 nh = enh & 0xff;
229 break;
230 }
231
232 case IPPROTO_PIM:
233 pim_print(cp, len, nextproto6_cksum(ip6, cp, len,
234 IPPROTO_PIM));
235 return;
236
237 case IPPROTO_OSPF:
238 ospf6_print(cp, len);
239 return;
240
241 case IPPROTO_IPV6:
242 ip6_print(ndo, cp, len);
243 return;
244
245 case IPPROTO_IPV4:
246 ip_print(ndo, cp, len);
247 return;
248
249 case IPPROTO_PGM:
250 pgm_print(cp, len, (const u_char *)ip6);
251 return;
252
253 case IPPROTO_GRE:
254 gre_print(cp, len);
255 return;
256
257 case IPPROTO_RSVP:
258 rsvp_print(cp, len);
259 return;
260
261 case IPPROTO_NONE:
262 (void)ND_PRINT((ndo, "no next header"));
263 return;
264
265 default:
266 (void)ND_PRINT((ndo, "ip-proto-%d %d", nh, len));
267 return;
268 }
269 }
270
271 return;
272 trunc:
273 (void)ND_PRINT((ndo, "[|ip6]"));
274 }
275
276 #endif /* INET6 */