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 #include <sys/cdefs.h> 23 #ifndef lint 24 __RCSID("$NetBSD: print-ip6.c,v 1.8 2017/09/08 14:01:13 christos Exp $"); 25 #endif 26 27 /* \summary: IPv6 printer */ 28 29 #ifdef HAVE_CONFIG_H 30 #include "config.h" 31 #endif 32 33 #include <netdissect-stdinc.h> 34 35 #include <string.h> 36 37 #include "netdissect.h" 38 #include "addrtoname.h" 39 #include "extract.h" 40 41 #include "ip6.h" 42 #include "ipproto.h" 43 44 /* 45 * If routing headers are presend and valid, set dst to the final destination. 46 * Otherwise, set it to the IPv6 destination. 47 * 48 * This is used for UDP and TCP pseudo-header in the checksum 49 * calculation. 50 */ 51 static void 52 ip6_finddst(netdissect_options *ndo, struct in6_addr *dst, 53 const struct ip6_hdr *ip6) 54 { 55 const u_char *cp; 56 int advance; 57 u_int nh; 58 const struct in6_addr *dst_addr; 59 const struct ip6_rthdr *dp; 60 const struct ip6_rthdr0 *dp0; 61 const struct in6_addr *addr; 62 int i, len; 63 64 cp = (const u_char *)ip6; 65 advance = sizeof(struct ip6_hdr); 66 nh = ip6->ip6_nxt; 67 dst_addr = &ip6->ip6_dst; 68 69 while (cp < ndo->ndo_snapend) { 70 cp += advance; 71 72 switch (nh) { 73 74 case IPPROTO_HOPOPTS: 75 case IPPROTO_DSTOPTS: 76 case IPPROTO_MOBILITY_OLD: 77 case IPPROTO_MOBILITY: 78 /* 79 * These have a header length byte, following 80 * the next header byte, giving the length of 81 * the header, in units of 8 octets, excluding 82 * the first 8 octets. 83 */ 84 ND_TCHECK2(*cp, 2); 85 advance = (int)((*(cp + 1) + 1) << 3); 86 nh = *cp; 87 break; 88 89 case IPPROTO_FRAGMENT: 90 /* 91 * The byte following the next header byte is 92 * marked as reserved, and the header is always 93 * the same size. 94 */ 95 ND_TCHECK2(*cp, 1); 96 advance = sizeof(struct ip6_frag); 97 nh = *cp; 98 break; 99 100 case IPPROTO_ROUTING: 101 /* 102 * OK, we found it. 103 */ 104 dp = (const struct ip6_rthdr *)cp; 105 ND_TCHECK(*dp); 106 len = dp->ip6r_len; 107 switch (dp->ip6r_type) { 108 109 case IPV6_RTHDR_TYPE_0: 110 case IPV6_RTHDR_TYPE_2: /* Mobile IPv6 ID-20 */ 111 dp0 = (const struct ip6_rthdr0 *)dp; 112 if (len % 2 == 1) 113 goto trunc; 114 len >>= 1; 115 addr = &dp0->ip6r0_addr[0]; 116 for (i = 0; i < len; i++) { 117 if ((const u_char *)(addr + 1) > ndo->ndo_snapend) 118 goto trunc; 119 120 dst_addr = addr; 121 addr++; 122 } 123 break; 124 125 default: 126 break; 127 } 128 129 /* 130 * Only one routing header to a customer. 131 */ 132 goto done; 133 134 case IPPROTO_AH: 135 case IPPROTO_ESP: 136 case IPPROTO_IPCOMP: 137 default: 138 /* 139 * AH and ESP are, in the RFCs that describe them, 140 * described as being "viewed as an end-to-end 141 * payload" "in the IPv6 context, so that they 142 * "should appear after hop-by-hop, routing, and 143 * fragmentation extension headers". We assume 144 * that's the case, and stop as soon as we see 145 * one. (We can't handle an ESP header in 146 * the general case anyway, as its length depends 147 * on the encryption algorithm.) 148 * 149 * IPComp is also "viewed as an end-to-end 150 * payload" "in the IPv6 context". 151 * 152 * All other protocols are assumed to be the final 153 * protocol. 154 */ 155 goto done; 156 } 157 } 158 159 done: 160 trunc: 161 UNALIGNED_MEMCPY(dst, dst_addr, sizeof(struct in6_addr)); 162 } 163 164 /* 165 * Compute a V6-style checksum by building a pseudoheader. 166 */ 167 int 168 nextproto6_cksum(netdissect_options *ndo, 169 const struct ip6_hdr *ip6, const uint8_t *data, 170 u_int len, u_int covlen, u_int next_proto) 171 { 172 struct { 173 struct in6_addr ph_src; 174 struct in6_addr ph_dst; 175 uint32_t ph_len; 176 uint8_t ph_zero[3]; 177 uint8_t ph_nxt; 178 } ph; 179 struct cksum_vec vec[2]; 180 181 /* pseudo-header */ 182 memset(&ph, 0, sizeof(ph)); 183 UNALIGNED_MEMCPY(&ph.ph_src, &ip6->ip6_src, sizeof (struct in6_addr)); 184 switch (ip6->ip6_nxt) { 185 186 case IPPROTO_HOPOPTS: 187 case IPPROTO_DSTOPTS: 188 case IPPROTO_MOBILITY_OLD: 189 case IPPROTO_MOBILITY: 190 case IPPROTO_FRAGMENT: 191 case IPPROTO_ROUTING: 192 /* 193 * The next header is either a routing header or a header 194 * after which there might be a routing header, so scan 195 * for a routing header. 196 */ 197 ip6_finddst(ndo, &ph.ph_dst, ip6); 198 break; 199 200 default: 201 UNALIGNED_MEMCPY(&ph.ph_dst, &ip6->ip6_dst, sizeof (struct in6_addr)); 202 break; 203 } 204 ph.ph_len = htonl(len); 205 ph.ph_nxt = next_proto; 206 207 vec[0].ptr = (const uint8_t *)(void *)&ph; 208 vec[0].len = sizeof(ph); 209 vec[1].ptr = data; 210 vec[1].len = covlen; 211 212 return in_cksum(vec, 2); 213 } 214 215 /* 216 * print an IP6 datagram. 217 */ 218 void 219 ip6_print(netdissect_options *ndo, const u_char *bp, u_int length) 220 { 221 register const struct ip6_hdr *ip6; 222 register int advance; 223 u_int len; 224 const u_char *ipend; 225 register const u_char *cp; 226 register u_int payload_len; 227 int nh; 228 int fragmented = 0; 229 u_int flow; 230 231 ip6 = (const struct ip6_hdr *)bp; 232 233 ND_TCHECK(*ip6); 234 if (length < sizeof (struct ip6_hdr)) { 235 ND_PRINT((ndo, "truncated-ip6 %u", length)); 236 return; 237 } 238 239 if (!ndo->ndo_eflag) 240 ND_PRINT((ndo, "IP6 ")); 241 242 if (IP6_VERSION(ip6) != 6) { 243 ND_PRINT((ndo,"version error: %u != 6", IP6_VERSION(ip6))); 244 return; 245 } 246 247 payload_len = EXTRACT_16BITS(&ip6->ip6_plen); 248 len = payload_len + sizeof(struct ip6_hdr); 249 if (length < len) 250 ND_PRINT((ndo, "truncated-ip6 - %u bytes missing!", 251 len - length)); 252 253 if (ndo->ndo_vflag) { 254 flow = EXTRACT_32BITS(&ip6->ip6_flow); 255 ND_PRINT((ndo, "(")); 256 #if 0 257 /* rfc1883 */ 258 if (flow & 0x0f000000) 259 ND_PRINT((ndo, "pri 0x%02x, ", (flow & 0x0f000000) >> 24)); 260 if (flow & 0x00ffffff) 261 ND_PRINT((ndo, "flowlabel 0x%06x, ", flow & 0x00ffffff)); 262 #else 263 /* RFC 2460 */ 264 if (flow & 0x0ff00000) 265 ND_PRINT((ndo, "class 0x%02x, ", (flow & 0x0ff00000) >> 20)); 266 if (flow & 0x000fffff) 267 ND_PRINT((ndo, "flowlabel 0x%05x, ", flow & 0x000fffff)); 268 #endif 269 270 ND_PRINT((ndo, "hlim %u, next-header %s (%u) payload length: %u) ", 271 ip6->ip6_hlim, 272 tok2str(ipproto_values,"unknown",ip6->ip6_nxt), 273 ip6->ip6_nxt, 274 payload_len)); 275 } 276 277 /* 278 * Cut off the snapshot length to the end of the IP payload. 279 */ 280 ipend = bp + len; 281 if (ipend < ndo->ndo_snapend) 282 ndo->ndo_snapend = ipend; 283 284 cp = (const u_char *)ip6; 285 advance = sizeof(struct ip6_hdr); 286 nh = ip6->ip6_nxt; 287 while (cp < ndo->ndo_snapend && advance > 0) { 288 if (len < (u_int)advance) 289 goto trunc; 290 cp += advance; 291 len -= advance; 292 293 if (cp == (const u_char *)(ip6 + 1) && 294 nh != IPPROTO_TCP && nh != IPPROTO_UDP && 295 nh != IPPROTO_DCCP && nh != IPPROTO_SCTP) { 296 ND_PRINT((ndo, "%s > %s: ", ip6addr_string(ndo, &ip6->ip6_src), 297 ip6addr_string(ndo, &ip6->ip6_dst))); 298 } 299 300 switch (nh) { 301 case IPPROTO_HOPOPTS: 302 advance = hbhopt_print(ndo, cp); 303 if (advance < 0) 304 return; 305 nh = *cp; 306 break; 307 case IPPROTO_DSTOPTS: 308 advance = dstopt_print(ndo, cp); 309 if (advance < 0) 310 return; 311 nh = *cp; 312 break; 313 case IPPROTO_FRAGMENT: 314 advance = frag6_print(ndo, cp, (const u_char *)ip6); 315 if (advance < 0 || ndo->ndo_snapend <= cp + advance) 316 return; 317 nh = *cp; 318 fragmented = 1; 319 break; 320 321 case IPPROTO_MOBILITY_OLD: 322 case IPPROTO_MOBILITY: 323 /* 324 * XXX - we don't use "advance"; RFC 3775 says that 325 * the next header field in a mobility header 326 * should be IPPROTO_NONE, but speaks of 327 * the possiblity of a future extension in 328 * which payload can be piggybacked atop a 329 * mobility header. 330 */ 331 advance = mobility_print(ndo, cp, (const u_char *)ip6); 332 if (advance < 0) 333 return; 334 nh = *cp; 335 return; 336 case IPPROTO_ROUTING: 337 ND_TCHECK(*cp); 338 advance = rt6_print(ndo, cp, (const u_char *)ip6); 339 if (advance < 0) 340 return; 341 nh = *cp; 342 break; 343 case IPPROTO_SCTP: 344 sctp_print(ndo, cp, (const u_char *)ip6, len); 345 return; 346 case IPPROTO_DCCP: 347 dccp_print(ndo, cp, (const u_char *)ip6, len); 348 return; 349 case IPPROTO_TCP: 350 tcp_print(ndo, cp, len, (const u_char *)ip6, fragmented); 351 return; 352 case IPPROTO_UDP: 353 udp_print(ndo, cp, len, (const u_char *)ip6, fragmented); 354 return; 355 case IPPROTO_ICMPV6: 356 icmp6_print(ndo, cp, len, (const u_char *)ip6, fragmented); 357 return; 358 case IPPROTO_AH: 359 advance = ah_print(ndo, cp); 360 if (advance < 0) 361 return; 362 nh = *cp; 363 break; 364 case IPPROTO_ESP: 365 { 366 int enh, padlen; 367 advance = esp_print(ndo, cp, len, (const u_char *)ip6, &enh, &padlen); 368 if (advance < 0) 369 return; 370 nh = enh & 0xff; 371 len -= padlen; 372 break; 373 } 374 case IPPROTO_IPCOMP: 375 { 376 ipcomp_print(ndo, cp); 377 /* 378 * Either this has decompressed the payload and 379 * printed it, in which case there's nothing more 380 * to do, or it hasn't, in which case there's 381 * nothing more to do. 382 */ 383 advance = -1; 384 break; 385 } 386 387 case IPPROTO_PIM: 388 pim_print(ndo, cp, len, (const u_char *)ip6); 389 return; 390 391 case IPPROTO_OSPF: 392 ospf6_print(ndo, cp, len); 393 return; 394 395 case IPPROTO_IPV6: 396 ip6_print(ndo, cp, len); 397 return; 398 399 case IPPROTO_IPV4: 400 ip_print(ndo, cp, len); 401 return; 402 403 case IPPROTO_PGM: 404 pgm_print(ndo, cp, len, (const u_char *)ip6); 405 return; 406 407 case IPPROTO_GRE: 408 gre_print(ndo, cp, len); 409 return; 410 411 case IPPROTO_RSVP: 412 rsvp_print(ndo, cp, len); 413 return; 414 415 case IPPROTO_NONE: 416 ND_PRINT((ndo, "no next header")); 417 return; 418 419 default: 420 ND_PRINT((ndo, "ip-proto-%d %d", nh, len)); 421 return; 422 } 423 } 424 425 return; 426 trunc: 427 ND_PRINT((ndo, "[|ip6]")); 428 } 429