1 /* $OpenBSD: print-ip6.c,v 1.27 2018/09/29 15:53:07 kn 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/time.h> 27 #include <sys/types.h> 28 #include <sys/socket.h> 29 30 #include <netinet/in.h> 31 #include <netinet/ip.h> 32 #include <netinet/ip_var.h> 33 #include <netinet/udp.h> 34 #include <netinet/udp_var.h> 35 #include <netinet/tcp.h> 36 37 #include <inttypes.h> 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <string.h> 41 #include <unistd.h> 42 43 #include "interface.h" 44 #include "addrtoname.h" 45 46 #include <netinet/ip6.h> 47 48 /* 49 * print an IP6 datagram. 50 */ 51 void 52 ip6_print(const u_char *bp, u_int length) 53 { 54 const struct ip6_hdr *ip6; 55 int hlen; 56 int len; 57 const u_char *cp; 58 const u_char *pktp = packetp; 59 const u_char *send = snapend; 60 int nh; 61 u_int flow; 62 63 ip6 = (const struct ip6_hdr *)bp; 64 if ((u_char *)(ip6 + 1) > snapend) { 65 printf("[|ip6]"); 66 return; 67 } 68 69 /* 70 * The IP header is not word aligned, so copy into abuf. 71 * This will never happen with BPF. It does happen with 72 * raw packet dumps from -r. 73 */ 74 if ((intptr_t)ip6 & (sizeof(u_int32_t)-1)) { 75 static u_char *abuf = NULL; 76 static int didwarn = 0; 77 int clen = snapend - bp; 78 if (clen > snaplen) 79 clen = snaplen; 80 81 if (abuf == NULL) { 82 abuf = malloc(snaplen); 83 if (abuf == NULL) 84 error("ip6_print: malloc"); 85 } 86 memmove((char *)abuf, (char *)ip6, min(length, clen)); 87 snapend = abuf + clen; 88 packetp = bp = abuf; 89 ip6 = (struct ip6_hdr *)abuf; 90 /* We really want libpcap to give us aligned packets */ 91 if (!didwarn) { 92 warning("compensating for unaligned libpcap packets"); 93 ++didwarn; 94 } 95 } 96 97 if (length < sizeof (struct ip6_hdr)) { 98 (void)printf("truncated-ip6 %d", length); 99 goto out; 100 } 101 if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) { 102 (void)printf("bad-ip6-version %u", ip6->ip6_vfc >> 4); 103 goto out; 104 } 105 hlen = sizeof(struct ip6_hdr); 106 107 len = ntohs(ip6->ip6_plen); 108 if (length < len + hlen) 109 (void)printf("truncated-ip6 - %d bytes missing!", 110 len + hlen - length); 111 112 cp = (const u_char *)ip6; 113 nh = ip6->ip6_nxt; 114 while (cp + hlen <= snapend) { 115 cp += hlen; 116 117 #ifndef IPPROTO_IPV4 118 #define IPPROTO_IPV4 4 119 #endif 120 if (cp == (u_char *)(ip6 + 1) && 121 nh != IPPROTO_TCP && nh != IPPROTO_UDP && 122 nh != IPPROTO_ESP && nh != IPPROTO_AH && 123 (vflag || (nh != IPPROTO_IPV4 && nh != IPPROTO_IPV6))) { 124 (void)printf("%s > %s: ", ip6addr_string(&ip6->ip6_src), 125 ip6addr_string(&ip6->ip6_dst)); 126 } 127 128 switch (nh) { 129 case IPPROTO_HOPOPTS: 130 hlen = hbhopt_print(cp); 131 nh = *cp; 132 break; 133 case IPPROTO_DSTOPTS: 134 hlen = dstopt_print(cp); 135 nh = *cp; 136 break; 137 case IPPROTO_FRAGMENT: 138 hlen = frag6_print(cp, (const u_char *)ip6); 139 if (snapend < cp + hlen) 140 goto end; 141 nh = *cp; 142 break; 143 case IPPROTO_ROUTING: 144 hlen = rt6_print(cp, (const u_char *)ip6); 145 nh = *cp; 146 break; 147 case IPPROTO_TCP: 148 tcp_print(cp, len + sizeof(struct ip6_hdr) - (cp - bp), 149 (const u_char *)ip6); 150 goto end; 151 case IPPROTO_UDP: 152 udp_print(cp, len + sizeof(struct ip6_hdr) - (cp - bp), 153 (const u_char *)ip6); 154 goto end; 155 case IPPROTO_ESP: 156 esp_print(cp, len + sizeof(struct ip6_hdr) - (cp - bp), 157 (const u_char *)ip6); 158 goto end; 159 case IPPROTO_AH: 160 ah_print(cp, len + sizeof(struct ip6_hdr) - (cp - bp), 161 (const u_char *)ip6); 162 goto end; 163 case IPPROTO_ICMPV6: 164 icmp6_print(cp, len + sizeof(struct ip6_hdr) - (cp - bp), 165 (const u_char *)ip6); 166 goto end; 167 case IPPROTO_PIM: 168 (void)printf("PIM"); 169 pim_print(cp, len); 170 goto end; 171 #ifndef IPPROTO_OSPF 172 #define IPPROTO_OSPF 89 173 #endif 174 case IPPROTO_OSPF: 175 ospf6_print(cp, len); 176 goto end; 177 case IPPROTO_IPV6: 178 ip6_print(cp, len); 179 if (! vflag) 180 printf(" (encap)"); 181 goto end; 182 case IPPROTO_IPV4: 183 ip_print(cp, len); 184 if (! vflag) 185 printf(" (encap)"); 186 goto end; 187 188 #ifndef IPPROTO_GRE 189 #define IPPROTO_GRE 47 190 #endif 191 case IPPROTO_GRE: 192 gre_print(cp, len); 193 goto end; 194 195 case IPPROTO_NONE: 196 (void)printf("no next header"); 197 goto end; 198 199 #ifndef IPPROTO_ETHERIP 200 #define IPPROTO_ETHERIP 97 201 #endif 202 case IPPROTO_ETHERIP: 203 etherip_print(cp, snapend - cp, len); 204 goto end; 205 206 #ifndef IPPROTO_CARP 207 #define IPPROTO_CARP 112 208 #endif 209 case IPPROTO_CARP: 210 if (packettype == PT_VRRP) 211 vrrp_print(cp, len, ip6->ip6_hlim); 212 else 213 carp_print(cp, len, ip6->ip6_hlim); 214 break; 215 216 default: 217 (void)printf("ip-proto-%d %d", ip6->ip6_nxt, len); 218 goto end; 219 } 220 if (hlen == 0) 221 break; 222 } 223 224 end: 225 226 flow = ntohl(ip6->ip6_flow); 227 if (flow & 0x0ff00000) 228 (void)printf(" [class 0x%x]", (flow & 0x0ff00000) >> 20); 229 if (flow & 0x000fffff) 230 (void)printf(" [flowlabel 0x%x]", flow & 0x000fffff); 231 232 if (ip6->ip6_hlim <= 1) 233 (void)printf(" [hlim %d]", (int)ip6->ip6_hlim); 234 235 if (vflag) { 236 printf(" ("); 237 (void)printf("len %d", len); 238 if (ip6->ip6_hlim > 1) 239 (void)printf(", hlim %d", (int)ip6->ip6_hlim); 240 printf(")"); 241 } 242 243 out: 244 packetp = pktp; 245 snapend = send; 246 } 247 248 #endif /* INET6 */ 249