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