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