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