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.47.2.2 2005/07/03 20:36: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 "interface.h" 42 #include "addrtoname.h" 43 #include "extract.h" 44 45 #include "ip6.h" 46 #include "ipproto.h" 47 48 /* 49 * print an IP6 datagram. 50 */ 51 void 52 ip6_print(register const u_char *bp, register u_int length) 53 { 54 register const struct ip6_hdr *ip6; 55 register int advance; 56 u_int len; 57 const u_char *ipend; 58 register const u_char *cp; 59 register u_int payload_len; 60 int nh; 61 int fragmented = 0; 62 u_int flow; 63 64 ip6 = (const struct ip6_hdr *)bp; 65 66 TCHECK(*ip6); 67 if (length < sizeof (struct ip6_hdr)) { 68 (void)printf("truncated-ip6 %u", length); 69 return; 70 } 71 72 if (!eflag) 73 printf("IP6 "); 74 75 payload_len = EXTRACT_16BITS(&ip6->ip6_plen); 76 len = payload_len + sizeof(struct ip6_hdr); 77 if (length < len) 78 (void)printf("truncated-ip6 - %u bytes missing!", 79 len - length); 80 81 if (vflag) { 82 flow = EXTRACT_32BITS(&ip6->ip6_flow); 83 printf("("); 84 #if 0 85 /* rfc1883 */ 86 if (flow & 0x0f000000) 87 (void)printf("pri 0x%02x, ", (flow & 0x0f000000) >> 24); 88 if (flow & 0x00ffffff) 89 (void)printf("flowlabel 0x%06x, ", flow & 0x00ffffff); 90 #else 91 /* RFC 2460 */ 92 if (flow & 0x0ff00000) 93 (void)printf("class 0x%02x, ", (flow & 0x0ff00000) >> 20); 94 if (flow & 0x000fffff) 95 (void)printf("flowlabel 0x%05x, ", flow & 0x000fffff); 96 #endif 97 98 (void)printf("hlim %u, next-header: %s (%u), length: %u) ", 99 ip6->ip6_hlim, 100 tok2str(ipproto_values,"unknown",ip6->ip6_nxt), 101 ip6->ip6_nxt, 102 payload_len); 103 } 104 105 /* 106 * Cut off the snapshot length to the end of the IP payload. 107 */ 108 ipend = bp + len; 109 if (ipend < snapend) 110 snapend = ipend; 111 112 cp = (const u_char *)ip6; 113 advance = sizeof(struct ip6_hdr); 114 nh = ip6->ip6_nxt; 115 while (cp < snapend && advance > 0) { 116 cp += advance; 117 len -= advance; 118 119 if (cp == (const u_char *)(ip6 + 1) && 120 nh != IPPROTO_TCP && nh != IPPROTO_UDP && 121 nh != IPPROTO_SCTP) { 122 (void)printf("%s > %s: ", ip6addr_string(&ip6->ip6_src), 123 ip6addr_string(&ip6->ip6_dst)); 124 } 125 126 switch (nh) { 127 case IPPROTO_HOPOPTS: 128 advance = hbhopt_print(cp); 129 nh = *cp; 130 break; 131 case IPPROTO_DSTOPTS: 132 advance = dstopt_print(cp); 133 nh = *cp; 134 break; 135 case IPPROTO_FRAGMENT: 136 advance = frag6_print(cp, (const u_char *)ip6); 137 if (snapend <= cp + advance) 138 return; 139 nh = *cp; 140 fragmented = 1; 141 break; 142 143 case IPPROTO_MOBILITY_OLD: 144 case IPPROTO_MOBILITY: 145 /* 146 * XXX - we don't use "advance"; the current 147 * "Mobility Support in IPv6" draft 148 * (draft-ietf-mobileip-ipv6-24) says that 149 * the next header field in a mobility header 150 * should be IPPROTO_NONE, but speaks of 151 * the possiblity of a future extension in 152 * which payload can be piggybacked atop a 153 * mobility header. 154 */ 155 advance = mobility_print(cp, (const u_char *)ip6); 156 nh = *cp; 157 return; 158 case IPPROTO_ROUTING: 159 advance = rt6_print(cp, (const u_char *)ip6); 160 nh = *cp; 161 break; 162 case IPPROTO_SCTP: 163 sctp_print(cp, (const u_char *)ip6, len); 164 return; 165 case IPPROTO_TCP: 166 tcp_print(cp, len, (const u_char *)ip6, fragmented); 167 return; 168 case IPPROTO_UDP: 169 udp_print(cp, len, (const u_char *)ip6, fragmented); 170 return; 171 case IPPROTO_ICMPV6: 172 icmp6_print(cp, len, (const u_char *)ip6, fragmented); 173 return; 174 case IPPROTO_AH: 175 advance = ah_print(cp); 176 nh = *cp; 177 break; 178 case IPPROTO_ESP: 179 { 180 int enh, padlen; 181 advance = esp_print(gndo, cp, len, (const u_char *)ip6, &enh, &padlen); 182 nh = enh & 0xff; 183 len -= padlen; 184 break; 185 } 186 case IPPROTO_IPCOMP: 187 { 188 int enh; 189 advance = ipcomp_print(cp, &enh); 190 nh = enh & 0xff; 191 break; 192 } 193 194 case IPPROTO_PIM: 195 pim_print(cp, len); 196 return; 197 198 case IPPROTO_OSPF: 199 ospf6_print(cp, len); 200 return; 201 202 case IPPROTO_IPV6: 203 ip6_print(cp, len); 204 return; 205 206 case IPPROTO_IPV4: 207 ip_print(gndo, cp, len); 208 return; 209 210 case IPPROTO_PGM: 211 pgm_print(cp, len, (const u_char *)ip6); 212 return; 213 214 case IPPROTO_GRE: 215 gre_print(cp, len); 216 return; 217 218 case IPPROTO_RSVP: 219 rsvp_print(cp, len); 220 return; 221 222 case IPPROTO_NONE: 223 (void)printf("no next header"); 224 return; 225 226 default: 227 (void)printf("ip-proto-%d %d", ip6->ip6_nxt, len); 228 return; 229 } 230 } 231 232 return; 233 trunc: 234 (void)printf("[|ip6]"); 235 } 236 237 #endif /* INET6 */ 238