156893Sfenner/* 256893Sfenner * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994 356893Sfenner * The Regents of the University of California. All rights reserved. 456893Sfenner * 556893Sfenner * Redistribution and use in source and binary forms, with or without 656893Sfenner * modification, are permitted provided that: (1) source code distributions 756893Sfenner * retain the above copyright notice and this paragraph in its entirety, (2) 856893Sfenner * distributions including binary code include the above copyright notice and 956893Sfenner * this paragraph in its entirety in the documentation or other materials 1056893Sfenner * provided with the distribution, and (3) all advertising materials mentioning 1156893Sfenner * features or use of this software display the following acknowledgement: 1256893Sfenner * ``This product includes software developed by the University of California, 1356893Sfenner * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 1456893Sfenner * the University nor the names of its contributors may be used to endorse 1556893Sfenner * or promote products derived from this software without specific prior 1656893Sfenner * written permission. 1756893Sfenner * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 1856893Sfenner * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 1956893Sfenner * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 2057278Sfenner * 2157278Sfenner * $FreeBSD$ 2256893Sfenner */ 2356893Sfenner 2456893Sfenner#ifndef lint 25127675Sbmsstatic const char rcsid[] _U_ = 26190207Srpaulo "@(#) $Header: /tcpdump/master/tcpdump/print-ip6.c,v 1.52 2007-09-21 07:05:33 hannes Exp $"; 2756893Sfenner#endif 2856893Sfenner 2956893Sfenner#ifdef HAVE_CONFIG_H 3056893Sfenner#include "config.h" 3156893Sfenner#endif 3256893Sfenner 3356893Sfenner#ifdef INET6 3456893Sfenner 35127675Sbms#include <tcpdump-stdinc.h> 3656893Sfenner 3756893Sfenner#include <stdio.h> 3856893Sfenner#include <stdlib.h> 3975118Sfenner#include <string.h> 4056893Sfenner 41214478Srpaulo#include "netdissect.h" 4256893Sfenner#include "interface.h" 4356893Sfenner#include "addrtoname.h" 44127675Sbms#include "extract.h" 4556893Sfenner 4675118Sfenner#include "ip6.h" 47127675Sbms#include "ipproto.h" 4856893Sfenner 4956893Sfenner/* 50214478Srpaulo * Compute a V6-style checksum by building a pseudoheader. 51214478Srpaulo */ 52214478Srpauloint 53235530Sdelphijnextproto6_cksum(const struct ip6_hdr *ip6, const u_int8_t *data, 54214478Srpaulo u_int len, u_int next_proto) 55214478Srpaulo{ 56235530Sdelphij struct { 57235530Sdelphij struct in6_addr ph_src; 58235530Sdelphij struct in6_addr ph_dst; 59235530Sdelphij u_int32_t ph_len; 60235530Sdelphij u_int8_t ph_zero[3]; 61235530Sdelphij u_int8_t ph_nxt; 62235530Sdelphij } ph; 63235530Sdelphij struct cksum_vec vec[2]; 64214478Srpaulo 65214478Srpaulo /* pseudo-header */ 66235530Sdelphij memset(&ph, 0, sizeof(ph)); 67235530Sdelphij ph.ph_src = ip6->ip6_src; 68235530Sdelphij ph.ph_dst = ip6->ip6_dst; 69235530Sdelphij ph.ph_len = htonl(len); 70235530Sdelphij ph.ph_nxt = next_proto; 71214478Srpaulo 72235530Sdelphij vec[0].ptr = (const u_int8_t *)(void *)&ph; 73235530Sdelphij vec[0].len = sizeof(ph); 74235530Sdelphij vec[1].ptr = data; 75235530Sdelphij vec[1].len = len; 76214478Srpaulo 77235530Sdelphij return in_cksum(vec, 2); 78214478Srpaulo} 79214478Srpaulo 80214478Srpaulo/* 8156893Sfenner * print an IP6 datagram. 8256893Sfenner */ 8356893Sfennervoid 84235530Sdelphijip6_print(netdissect_options *ndo, const u_char *bp, u_int length) 8556893Sfenner{ 8656893Sfenner register const struct ip6_hdr *ip6; 8775118Sfenner register int advance; 88127675Sbms u_int len; 89127675Sbms const u_char *ipend; 9056893Sfenner register const u_char *cp; 91127675Sbms register u_int payload_len; 9256893Sfenner int nh; 9375118Sfenner int fragmented = 0; 9456893Sfenner u_int flow; 95127675Sbms 9656893Sfenner ip6 = (const struct ip6_hdr *)bp; 9756893Sfenner 9898527Sfenner TCHECK(*ip6); 9956893Sfenner if (length < sizeof (struct ip6_hdr)) { 100235530Sdelphij (void)ND_PRINT((ndo, "truncated-ip6 %u", length)); 10156893Sfenner return; 10256893Sfenner } 10356893Sfenner 104235530Sdelphij if (!ndo->ndo_eflag) 105235530Sdelphij ND_PRINT((ndo, "IP6 ")); 106146778Ssam 107127675Sbms payload_len = EXTRACT_16BITS(&ip6->ip6_plen); 108127675Sbms len = payload_len + sizeof(struct ip6_hdr); 109127675Sbms if (length < len) 110235530Sdelphij (void)ND_PRINT((ndo, "truncated-ip6 - %u bytes missing!", 111235530Sdelphij len - length)); 11256893Sfenner 113235530Sdelphij if (ndo->ndo_vflag) { 114146778Ssam flow = EXTRACT_32BITS(&ip6->ip6_flow); 115235530Sdelphij ND_PRINT((ndo, "(")); 116146778Ssam#if 0 117146778Ssam /* rfc1883 */ 118146778Ssam if (flow & 0x0f000000) 119235530Sdelphij (void)ND_PRINT((ndo, "pri 0x%02x, ", (flow & 0x0f000000) >> 24)); 120146778Ssam if (flow & 0x00ffffff) 121235530Sdelphij (void)ND_PRINT((ndo, "flowlabel 0x%06x, ", flow & 0x00ffffff)); 122146778Ssam#else 123146778Ssam /* RFC 2460 */ 124146778Ssam if (flow & 0x0ff00000) 125235530Sdelphij (void)ND_PRINT((ndo, "class 0x%02x, ", (flow & 0x0ff00000) >> 20)); 126146778Ssam if (flow & 0x000fffff) 127235530Sdelphij (void)ND_PRINT((ndo, "flowlabel 0x%05x, ", flow & 0x000fffff)); 128146778Ssam#endif 129146778Ssam 130235530Sdelphij (void)ND_PRINT((ndo, "hlim %u, next-header %s (%u) payload length: %u) ", 131146778Ssam ip6->ip6_hlim, 132146778Ssam tok2str(ipproto_values,"unknown",ip6->ip6_nxt), 133146778Ssam ip6->ip6_nxt, 134235530Sdelphij payload_len)); 135146778Ssam } 136146778Ssam 137127675Sbms /* 138127675Sbms * Cut off the snapshot length to the end of the IP payload. 139127675Sbms */ 140127675Sbms ipend = bp + len; 141235530Sdelphij if (ipend < ndo->ndo_snapend) 142235530Sdelphij ndo->ndo_snapend = ipend; 143127675Sbms 14456893Sfenner cp = (const u_char *)ip6; 145127675Sbms advance = sizeof(struct ip6_hdr); 14656893Sfenner nh = ip6->ip6_nxt; 147235530Sdelphij while (cp < ndo->ndo_snapend && advance > 0) { 14875118Sfenner cp += advance; 149127675Sbms len -= advance; 15056893Sfenner 151127675Sbms if (cp == (const u_char *)(ip6 + 1) && 152127675Sbms nh != IPPROTO_TCP && nh != IPPROTO_UDP && 153162021Ssam nh != IPPROTO_DCCP && nh != IPPROTO_SCTP) { 154235530Sdelphij (void)ND_PRINT((ndo, "%s > %s: ", ip6addr_string(&ip6->ip6_src), 155235530Sdelphij ip6addr_string(&ip6->ip6_dst))); 15656893Sfenner } 15756893Sfenner 15856893Sfenner switch (nh) { 15956893Sfenner case IPPROTO_HOPOPTS: 16075118Sfenner advance = hbhopt_print(cp); 16156893Sfenner nh = *cp; 16256893Sfenner break; 16356893Sfenner case IPPROTO_DSTOPTS: 16475118Sfenner advance = dstopt_print(cp); 16556893Sfenner nh = *cp; 16656893Sfenner break; 16756893Sfenner case IPPROTO_FRAGMENT: 16875118Sfenner advance = frag6_print(cp, (const u_char *)ip6); 169235530Sdelphij if (ndo->ndo_snapend <= cp + advance) 170146778Ssam return; 17156893Sfenner nh = *cp; 17275118Sfenner fragmented = 1; 17356893Sfenner break; 174127675Sbms 175127675Sbms case IPPROTO_MOBILITY_OLD: 176127675Sbms case IPPROTO_MOBILITY: 177127675Sbms /* 178127675Sbms * XXX - we don't use "advance"; the current 179127675Sbms * "Mobility Support in IPv6" draft 180127675Sbms * (draft-ietf-mobileip-ipv6-24) says that 181127675Sbms * the next header field in a mobility header 182127675Sbms * should be IPPROTO_NONE, but speaks of 183127675Sbms * the possiblity of a future extension in 184127675Sbms * which payload can be piggybacked atop a 185127675Sbms * mobility header. 186127675Sbms */ 187127675Sbms advance = mobility_print(cp, (const u_char *)ip6); 188127675Sbms nh = *cp; 189146778Ssam return; 19056893Sfenner case IPPROTO_ROUTING: 19175118Sfenner advance = rt6_print(cp, (const u_char *)ip6); 19256893Sfenner nh = *cp; 19356893Sfenner break; 194127675Sbms case IPPROTO_SCTP: 195127675Sbms sctp_print(cp, (const u_char *)ip6, len); 196146778Ssam return; 197162021Ssam case IPPROTO_DCCP: 198162021Ssam dccp_print(cp, (const u_char *)ip6, len); 199162021Ssam return; 20056893Sfenner case IPPROTO_TCP: 201127675Sbms tcp_print(cp, len, (const u_char *)ip6, fragmented); 202146778Ssam return; 20356893Sfenner case IPPROTO_UDP: 204127675Sbms udp_print(cp, len, (const u_char *)ip6, fragmented); 205146778Ssam return; 20656893Sfenner case IPPROTO_ICMPV6: 207235530Sdelphij icmp6_print(ndo, cp, len, (const u_char *)ip6, fragmented); 208146778Ssam return; 20956893Sfenner case IPPROTO_AH: 210127675Sbms advance = ah_print(cp); 21156893Sfenner nh = *cp; 21256893Sfenner break; 21356893Sfenner case IPPROTO_ESP: 21456893Sfenner { 21598527Sfenner int enh, padlen; 216235530Sdelphij advance = esp_print(ndo, cp, len, (const u_char *)ip6, &enh, &padlen); 21756893Sfenner nh = enh & 0xff; 21898527Sfenner len -= padlen; 21956893Sfenner break; 22056893Sfenner } 22156893Sfenner case IPPROTO_IPCOMP: 22256893Sfenner { 22356893Sfenner int enh; 224127675Sbms advance = ipcomp_print(cp, &enh); 22556893Sfenner nh = enh & 0xff; 22656893Sfenner break; 22756893Sfenner } 22875118Sfenner 22956893Sfenner case IPPROTO_PIM: 230235530Sdelphij pim_print(cp, len, nextproto6_cksum(ip6, cp, len, 231214478Srpaulo IPPROTO_PIM)); 232146778Ssam return; 233147904Ssam 23456893Sfenner case IPPROTO_OSPF: 23556893Sfenner ospf6_print(cp, len); 236146778Ssam return; 237127675Sbms 23856893Sfenner case IPPROTO_IPV6: 239235530Sdelphij ip6_print(ndo, cp, len); 240146778Ssam return; 241127675Sbms 24256893Sfenner case IPPROTO_IPV4: 243235530Sdelphij ip_print(ndo, cp, len); 244146778Ssam return; 245127675Sbms 246147904Ssam case IPPROTO_PGM: 247147904Ssam pgm_print(cp, len, (const u_char *)ip6); 248147904Ssam return; 249147904Ssam 250147904Ssam case IPPROTO_GRE: 251147904Ssam gre_print(cp, len); 252147904Ssam return; 253147904Ssam 254147904Ssam case IPPROTO_RSVP: 255147904Ssam rsvp_print(cp, len); 256147904Ssam return; 257147904Ssam 25856893Sfenner case IPPROTO_NONE: 259235530Sdelphij (void)ND_PRINT((ndo, "no next header")); 260146778Ssam return; 26156893Sfenner 26256893Sfenner default: 263235530Sdelphij (void)ND_PRINT((ndo, "ip-proto-%d %d", nh, len)); 264146778Ssam return; 26556893Sfenner } 26656893Sfenner } 26756893Sfenner 26898527Sfenner return; 26998527Sfennertrunc: 270235530Sdelphij (void)ND_PRINT((ndo, "[|ip6]")); 27156893Sfenner} 27256893Sfenner 27356893Sfenner#endif /* INET6 */ 274