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 * $FreeBSD$ 22 */ 23 24 #ifndef lint 25 static const char rcsid[] _U_ = 26 "@(#) $Header: /tcpdump/master/tcpdump/print-ip6.c,v 1.52 2007-09-21 07:05:33 hannes Exp $"; 27 #endif 28 29 #ifdef HAVE_CONFIG_H 30 #include "config.h" 31 #endif 32 33 #ifdef INET6 34 35 #include <tcpdump-stdinc.h> 36 37 #include <stdio.h> 38 #include <stdlib.h> 39 #include <string.h> 40 41 #include "netdissect.h" 42 #include "interface.h" 43 #include "addrtoname.h" 44 #include "extract.h" 45 46 #include "ip6.h" 47 #include "ipproto.h" 48 49 /* 50 * Compute a V6-style checksum by building a pseudoheader. 51 */ 52 int 53 nextproto6_cksum(const struct ip6_hdr *ip6, const u_short *data, 54 u_int len, u_int next_proto) 55 { 56 size_t i; 57 u_int32_t sum = 0; 58 union ip6_pseudo_hdr phu; 59 60 /* pseudo-header */ 61 memset(&phu, 0, sizeof(phu)); 62 phu.ph.ph_src = ip6->ip6_src; 63 phu.ph.ph_dst = ip6->ip6_dst; 64 phu.ph.ph_len = htonl(len); 65 phu.ph.ph_nxt = next_proto; 66 67 for (i = 0; i < sizeof(phu.pa) / sizeof(phu.pa[0]); i++) { 68 sum += phu.pa[i]; 69 } 70 71 return in_cksum(data, len, sum); 72 } 73 74 /* 75 * print an IP6 datagram. 76 */ 77 void 78 ip6_print(register const u_char *bp, register u_int length) 79 { 80 register const struct ip6_hdr *ip6; 81 register int advance; 82 u_int len; 83 const u_char *ipend; 84 register const u_char *cp; 85 register u_int payload_len; 86 int nh; 87 int fragmented = 0; 88 u_int flow; 89 90 ip6 = (const struct ip6_hdr *)bp; 91 92 TCHECK(*ip6); 93 if (length < sizeof (struct ip6_hdr)) { 94 (void)printf("truncated-ip6 %u", length); 95 return; 96 } 97 98 if (!eflag) 99 printf("IP6 "); 100 101 payload_len = EXTRACT_16BITS(&ip6->ip6_plen); 102 len = payload_len + sizeof(struct ip6_hdr); 103 if (length < len) 104 (void)printf("truncated-ip6 - %u bytes missing!", 105 len - length); 106 107 if (vflag) { 108 flow = EXTRACT_32BITS(&ip6->ip6_flow); 109 printf("("); 110 #if 0 111 /* rfc1883 */ 112 if (flow & 0x0f000000) 113 (void)printf("pri 0x%02x, ", (flow & 0x0f000000) >> 24); 114 if (flow & 0x00ffffff) 115 (void)printf("flowlabel 0x%06x, ", flow & 0x00ffffff); 116 #else 117 /* RFC 2460 */ 118 if (flow & 0x0ff00000) 119 (void)printf("class 0x%02x, ", (flow & 0x0ff00000) >> 20); 120 if (flow & 0x000fffff) 121 (void)printf("flowlabel 0x%05x, ", flow & 0x000fffff); 122 #endif 123 124 (void)printf("hlim %u, next-header %s (%u) payload length: %u) ", 125 ip6->ip6_hlim, 126 tok2str(ipproto_values,"unknown",ip6->ip6_nxt), 127 ip6->ip6_nxt, 128 payload_len); 129 } 130 131 /* 132 * Cut off the snapshot length to the end of the IP payload. 133 */ 134 ipend = bp + len; 135 if (ipend < snapend) 136 snapend = ipend; 137 138 cp = (const u_char *)ip6; 139 advance = sizeof(struct ip6_hdr); 140 nh = ip6->ip6_nxt; 141 while (cp < snapend && advance > 0) { 142 cp += advance; 143 len -= advance; 144 145 if (cp == (const u_char *)(ip6 + 1) && 146 nh != IPPROTO_TCP && nh != IPPROTO_UDP && 147 nh != IPPROTO_DCCP && nh != IPPROTO_SCTP) { 148 (void)printf("%s > %s: ", ip6addr_string(&ip6->ip6_src), 149 ip6addr_string(&ip6->ip6_dst)); 150 } 151 152 switch (nh) { 153 case IPPROTO_HOPOPTS: 154 advance = hbhopt_print(cp); 155 nh = *cp; 156 break; 157 case IPPROTO_DSTOPTS: 158 advance = dstopt_print(cp); 159 nh = *cp; 160 break; 161 case IPPROTO_FRAGMENT: 162 advance = frag6_print(cp, (const u_char *)ip6); 163 if (snapend <= cp + advance) 164 return; 165 nh = *cp; 166 fragmented = 1; 167 break; 168 169 case IPPROTO_MOBILITY_OLD: 170 case IPPROTO_MOBILITY: 171 /* 172 * XXX - we don't use "advance"; the current 173 * "Mobility Support in IPv6" draft 174 * (draft-ietf-mobileip-ipv6-24) says that 175 * the next header field in a mobility header 176 * should be IPPROTO_NONE, but speaks of 177 * the possiblity of a future extension in 178 * which payload can be piggybacked atop a 179 * mobility header. 180 */ 181 advance = mobility_print(cp, (const u_char *)ip6); 182 nh = *cp; 183 return; 184 case IPPROTO_ROUTING: 185 advance = rt6_print(cp, (const u_char *)ip6); 186 nh = *cp; 187 break; 188 case IPPROTO_SCTP: 189 sctp_print(cp, (const u_char *)ip6, len); 190 return; 191 case IPPROTO_DCCP: 192 dccp_print(cp, (const u_char *)ip6, len); 193 return; 194 case IPPROTO_TCP: 195 tcp_print(cp, len, (const u_char *)ip6, fragmented); 196 return; 197 case IPPROTO_UDP: 198 udp_print(cp, len, (const u_char *)ip6, fragmented); 199 return; 200 case IPPROTO_ICMPV6: 201 icmp6_print(gndo, cp, len, (const u_char *)ip6, fragmented); 202 return; 203 case IPPROTO_AH: 204 advance = ah_print(cp); 205 nh = *cp; 206 break; 207 case IPPROTO_ESP: 208 { 209 int enh, padlen; 210 advance = esp_print(gndo, cp, len, (const u_char *)ip6, &enh, &padlen); 211 nh = enh & 0xff; 212 len -= padlen; 213 break; 214 } 215 case IPPROTO_IPCOMP: 216 { 217 int enh; 218 advance = ipcomp_print(cp, &enh); 219 nh = enh & 0xff; 220 break; 221 } 222 223 case IPPROTO_PIM: 224 pim_print(cp, len, nextproto6_cksum(ip6, (u_short *)cp, len, 225 IPPROTO_PIM)); 226 return; 227 228 case IPPROTO_OSPF: 229 ospf6_print(cp, len); 230 return; 231 232 case IPPROTO_IPV6: 233 ip6_print(cp, len); 234 return; 235 236 case IPPROTO_IPV4: 237 ip_print(gndo, cp, len); 238 return; 239 240 case IPPROTO_PGM: 241 pgm_print(cp, len, (const u_char *)ip6); 242 return; 243 244 case IPPROTO_GRE: 245 gre_print(cp, len); 246 return; 247 248 case IPPROTO_RSVP: 249 rsvp_print(cp, len); 250 return; 251 252 case IPPROTO_NONE: 253 (void)printf("no next header"); 254 return; 255 256 default: 257 (void)printf("ip-proto-%d %d", nh, len); 258 return; 259 } 260 } 261 262 return; 263 trunc: 264 (void)printf("[|ip6]"); 265 } 266 267 #endif /* INET6 */ 268