1 /* $OpenBSD: print-ip6.c,v 1.16 2014/08/14 12:44:44 mpi Exp $ */ 2 3 /* 4 * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that: (1) source code distributions 9 * retain the above copyright notice and this paragraph in its entirety, (2) 10 * distributions including binary code include the above copyright notice and 11 * this paragraph in its entirety in the documentation or other materials 12 * provided with the distribution, and (3) all advertising materials mentioning 13 * features or use of this software display the following acknowledgement: 14 * ``This product includes software developed by the University of California, 15 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 16 * the University nor the names of its contributors may be used to endorse 17 * or promote products derived from this software without specific prior 18 * written permission. 19 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 20 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 22 */ 23 24 #ifdef INET6 25 26 #include <sys/param.h> 27 #include <sys/time.h> 28 #include <sys/types.h> 29 #include <sys/socket.h> 30 31 #include <netinet/in.h> 32 #include <netinet/ip.h> 33 #include <netinet/ip_var.h> 34 #include <netinet/udp.h> 35 #include <netinet/udp_var.h> 36 #include <netinet/tcp.h> 37 38 #include <inttypes.h> 39 #include <stdio.h> 40 #include <stdlib.h> 41 #include <string.h> 42 #include <unistd.h> 43 44 #include "interface.h" 45 #include "addrtoname.h" 46 47 #include <netinet/ip6.h> 48 49 /* 50 * print an IP6 datagram. 51 */ 52 void 53 ip6_print(register const u_char *bp, register int length) 54 { 55 register const struct ip6_hdr *ip6; 56 register int hlen; 57 register int len; 58 register const u_char *cp; 59 int nh; 60 u_int flow; 61 62 ip6 = (const struct ip6_hdr *)bp; 63 64 /* 65 * The IP header is not word aligned, so copy into abuf. 66 * This will never happen with BPF. It does happen with 67 * raw packet dumps from -r. 68 */ 69 if ((intptr_t)ip6 & (sizeof(long)-1)) { 70 static u_char *abuf = NULL; 71 static int didwarn = 0; 72 int clen = snapend - bp; 73 if (clen > snaplen) 74 clen = snaplen; 75 76 if (abuf == NULL) { 77 abuf = (u_char *)malloc(snaplen); 78 if (abuf == NULL) 79 error("ip6_print: malloc"); 80 } 81 memmove((char *)abuf, (char *)ip6, min(length, clen)); 82 snapend = abuf + clen; 83 packetp = bp = abuf; 84 ip6 = (struct ip6_hdr *)abuf; 85 /* We really want libpcap to give us aligned packets */ 86 if (!didwarn) { 87 warning("compensating for unaligned libpcap packets"); 88 ++didwarn; 89 } 90 } 91 92 if ((u_char *)(ip6 + 1) > snapend) { 93 printf("[|ip6]"); 94 return; 95 } 96 if (length < sizeof (struct ip6_hdr)) { 97 (void)printf("truncated-ip6 %d", length); 98 return; 99 } 100 if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) { 101 (void)printf("bad-ip6-version %u", ip6->ip6_vfc >> 4); 102 return; 103 } 104 hlen = sizeof(struct ip6_hdr); 105 106 len = ntohs(ip6->ip6_plen); 107 if (length < len + hlen) 108 (void)printf("truncated-ip6 - %d bytes missing!", 109 len + hlen - length); 110 111 cp = (const u_char *)ip6; 112 nh = ip6->ip6_nxt; 113 while (cp + hlen <= snapend) { 114 cp += hlen; 115 116 #ifndef IPPROTO_IPV4 117 #define IPPROTO_IPV4 4 118 #endif 119 if (cp == (u_char *)(ip6 + 1) && 120 nh != IPPROTO_TCP && nh != IPPROTO_UDP && 121 nh != IPPROTO_ESP && nh != IPPROTO_AH && 122 (vflag || (nh != IPPROTO_IPV4 && nh != IPPROTO_IPV6))) { 123 (void)printf("%s > %s: ", ip6addr_string(&ip6->ip6_src), 124 ip6addr_string(&ip6->ip6_dst)); 125 } 126 127 switch (nh) { 128 case IPPROTO_HOPOPTS: 129 hlen = hbhopt_print(cp); 130 nh = *cp; 131 break; 132 case IPPROTO_DSTOPTS: 133 hlen = dstopt_print(cp); 134 nh = *cp; 135 break; 136 case IPPROTO_FRAGMENT: 137 hlen = frag6_print(cp, (const u_char *)ip6); 138 if (snapend < cp + hlen) 139 goto end; 140 nh = *cp; 141 break; 142 case IPPROTO_ROUTING: 143 hlen = rt6_print(cp, (const u_char *)ip6); 144 nh = *cp; 145 break; 146 case IPPROTO_TCP: 147 tcp_print(cp, len + sizeof(struct ip6_hdr) - (cp - bp), 148 (const u_char *)ip6); 149 goto end; 150 case IPPROTO_UDP: 151 udp_print(cp, len + sizeof(struct ip6_hdr) - (cp - bp), 152 (const u_char *)ip6); 153 goto end; 154 case IPPROTO_ESP: 155 esp_print(cp, len + sizeof(struct ip6_hdr) - (cp - bp), 156 (const u_char *)ip6); 157 goto end; 158 case IPPROTO_AH: 159 ah_print(cp, len + sizeof(struct ip6_hdr) - (cp - bp), 160 (const u_char *)ip6); 161 goto end; 162 case IPPROTO_ICMPV6: 163 icmp6_print(cp, len + sizeof(struct ip6_hdr) - (cp - bp), 164 (const u_char *)ip6); 165 goto end; 166 case IPPROTO_PIM: 167 (void)printf("PIM"); 168 pim_print(cp, len); 169 goto end; 170 #ifndef IPPROTO_OSPF 171 #define IPPROTO_OSPF 89 172 #endif 173 case IPPROTO_OSPF: 174 ospf6_print(cp, len); 175 goto end; 176 case IPPROTO_IPV6: 177 ip6_print(cp, len); 178 if (! vflag) 179 printf(" (encap)"); 180 goto end; 181 case IPPROTO_IPV4: 182 ip_print(cp, len); 183 if (! vflag) 184 printf(" (encap)"); 185 goto end; 186 case IPPROTO_NONE: 187 (void)printf("no next header"); 188 goto end; 189 190 #ifndef IPPROTO_CARP 191 #define IPPROTO_CARP 112 192 #endif 193 case IPPROTO_CARP: 194 if (packettype == PT_VRRP) 195 vrrp_print(cp, len, ip6->ip6_hlim); 196 else 197 carp_print(cp, len, ip6->ip6_hlim); 198 break; 199 200 default: 201 (void)printf("ip-proto-%d %d", ip6->ip6_nxt, len); 202 goto end; 203 } 204 if (hlen == 0) 205 break; 206 } 207 208 end: 209 210 flow = ntohl(ip6->ip6_flow); 211 #if 0 212 /* rfc1883 */ 213 if (flow & 0x0f000000) 214 (void)printf(" [pri 0x%x]", (flow & 0x0f000000) >> 24); 215 if (flow & 0x00ffffff) 216 (void)printf(" [flowlabel 0x%x]", flow & 0x00ffffff); 217 #else 218 /* RFC 2460 */ 219 if (flow & 0x0ff00000) 220 (void)printf(" [class 0x%x]", (flow & 0x0ff00000) >> 20); 221 if (flow & 0x000fffff) 222 (void)printf(" [flowlabel 0x%x]", flow & 0x000fffff); 223 #endif 224 225 if (ip6->ip6_hlim <= 1) 226 (void)printf(" [hlim %d]", (int)ip6->ip6_hlim); 227 228 if (vflag) { 229 printf(" ("); 230 (void)printf("len %d", len); 231 if (ip6->ip6_hlim > 1) 232 (void)printf(", hlim %d", (int)ip6->ip6_hlim); 233 printf(")"); 234 } 235 } 236 237 #endif /* INET6 */ 238