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 /* \summary: IPv6 printer */ 23 24 #include <config.h> 25 26 #include "netdissect-stdinc.h" 27 28 #include <string.h> 29 30 #include "netdissect.h" 31 #include "addrtoname.h" 32 #include "extract.h" 33 34 #include "ip6.h" 35 #include "ipproto.h" 36 37 /* 38 * If routing headers are presend and valid, set dst to the final destination. 39 * Otherwise, set it to the IPv6 destination. 40 * 41 * This is used for UDP and TCP pseudo-header in the checksum 42 * calculation. 43 */ 44 static void 45 ip6_finddst(netdissect_options *ndo, nd_ipv6 *dst, 46 const struct ip6_hdr *ip6) 47 { 48 const u_char *cp; 49 u_int advance; 50 u_int nh; 51 const void *dst_addr; 52 const struct ip6_rthdr *dp; 53 const struct ip6_rthdr0 *dp0; 54 const struct ip6_srh *srh; 55 const u_char *p; 56 int i, len; 57 58 cp = (const u_char *)ip6; 59 advance = sizeof(struct ip6_hdr); 60 nh = GET_U_1(ip6->ip6_nxt); 61 dst_addr = (const void *)ip6->ip6_dst; 62 63 while (cp < ndo->ndo_snapend) { 64 cp += advance; 65 66 switch (nh) { 67 68 case IPPROTO_HOPOPTS: 69 case IPPROTO_DSTOPTS: 70 case IPPROTO_MOBILITY_OLD: 71 case IPPROTO_MOBILITY: 72 /* 73 * These have a header length byte, following 74 * the next header byte, giving the length of 75 * the header, in units of 8 octets, excluding 76 * the first 8 octets. 77 */ 78 advance = (GET_U_1(cp + 1) + 1) << 3; 79 nh = GET_U_1(cp); 80 break; 81 82 case IPPROTO_FRAGMENT: 83 /* 84 * The byte following the next header byte is 85 * marked as reserved, and the header is always 86 * the same size. 87 */ 88 advance = sizeof(struct ip6_frag); 89 nh = GET_U_1(cp); 90 break; 91 92 case IPPROTO_ROUTING: 93 /* 94 * OK, we found it. 95 */ 96 dp = (const struct ip6_rthdr *)cp; 97 ND_TCHECK_SIZE(dp); 98 len = GET_U_1(dp->ip6r_len); 99 switch (GET_U_1(dp->ip6r_type)) { 100 101 case IPV6_RTHDR_TYPE_0: 102 case IPV6_RTHDR_TYPE_2: /* Mobile IPv6 ID-20 */ 103 dp0 = (const struct ip6_rthdr0 *)dp; 104 if (len % 2 == 1) 105 goto trunc; 106 len >>= 1; 107 p = (const u_char *) dp0->ip6r0_addr; 108 for (i = 0; i < len; i++) { 109 ND_TCHECK_16(p); 110 dst_addr = (const void *)p; 111 p += 16; 112 } 113 break; 114 case IPV6_RTHDR_TYPE_4: 115 /* IPv6 Segment Routing Header (SRH) */ 116 srh = (const struct ip6_srh *)dp; 117 if (len % 2 == 1) 118 goto trunc; 119 p = (const u_char *) srh->srh_segments; 120 /* 121 * The list of segments are encoded in the reverse order. 122 * Accordingly, the final DA is encoded in srh_segments[0] 123 */ 124 ND_TCHECK_16(p); 125 dst_addr = (const void *)p; 126 break; 127 128 default: 129 break; 130 } 131 132 /* 133 * Only one routing header to a customer. 134 */ 135 goto done; 136 137 case IPPROTO_AH: 138 case IPPROTO_ESP: 139 case IPPROTO_IPCOMP: 140 default: 141 /* 142 * AH and ESP are, in the RFCs that describe them, 143 * described as being "viewed as an end-to-end 144 * payload" "in the IPv6 context, so that they 145 * "should appear after hop-by-hop, routing, and 146 * fragmentation extension headers". We assume 147 * that's the case, and stop as soon as we see 148 * one. (We can't handle an ESP header in 149 * the general case anyway, as its length depends 150 * on the encryption algorithm.) 151 * 152 * IPComp is also "viewed as an end-to-end 153 * payload" "in the IPv6 context". 154 * 155 * All other protocols are assumed to be the final 156 * protocol. 157 */ 158 goto done; 159 } 160 } 161 162 done: 163 trunc: 164 GET_CPY_BYTES(dst, dst_addr, sizeof(nd_ipv6)); 165 } 166 167 /* 168 * Compute a V6-style checksum by building a pseudoheader. 169 */ 170 uint16_t 171 nextproto6_cksum(netdissect_options *ndo, 172 const struct ip6_hdr *ip6, const uint8_t *data, 173 u_int len, u_int covlen, uint8_t next_proto) 174 { 175 struct { 176 nd_ipv6 ph_src; 177 nd_ipv6 ph_dst; 178 uint32_t ph_len; 179 uint8_t ph_zero[3]; 180 uint8_t ph_nxt; 181 } ph; 182 struct cksum_vec vec[2]; 183 u_int nh; 184 185 /* pseudo-header */ 186 memset(&ph, 0, sizeof(ph)); 187 GET_CPY_BYTES(&ph.ph_src, ip6->ip6_src, sizeof(nd_ipv6)); 188 nh = GET_U_1(ip6->ip6_nxt); 189 switch (nh) { 190 191 case IPPROTO_HOPOPTS: 192 case IPPROTO_DSTOPTS: 193 case IPPROTO_MOBILITY_OLD: 194 case IPPROTO_MOBILITY: 195 case IPPROTO_FRAGMENT: 196 case IPPROTO_ROUTING: 197 /* 198 * The next header is either a routing header or a header 199 * after which there might be a routing header, so scan 200 * for a routing header. 201 */ 202 ip6_finddst(ndo, &ph.ph_dst, ip6); 203 break; 204 205 default: 206 GET_CPY_BYTES(&ph.ph_dst, ip6->ip6_dst, sizeof(nd_ipv6)); 207 break; 208 } 209 ph.ph_len = htonl(len); 210 ph.ph_nxt = next_proto; 211 212 vec[0].ptr = (const uint8_t *)(void *)&ph; 213 vec[0].len = sizeof(ph); 214 vec[1].ptr = data; 215 vec[1].len = covlen; 216 217 return in_cksum(vec, 2); 218 } 219 220 /* 221 * print an IP6 datagram. 222 */ 223 void 224 ip6_print(netdissect_options *ndo, const u_char *bp, u_int length) 225 { 226 const struct ip6_hdr *ip6; 227 int advance; 228 u_int len; 229 u_int total_advance; 230 const u_char *cp; 231 uint32_t payload_len; 232 uint8_t ph, nh; 233 int fragmented = 0; 234 u_int flow; 235 int found_extension_header; 236 int found_jumbo; 237 int found_hbh; 238 239 ndo->ndo_protocol = "ip6"; 240 ip6 = (const struct ip6_hdr *)bp; 241 242 if (!ndo->ndo_eflag) { 243 nd_print_protocol_caps(ndo); 244 ND_PRINT(" "); 245 } 246 247 ND_ICHECK_ZU(length, <, sizeof (struct ip6_hdr)); 248 ND_ICHECKMSG_U("version", IP6_VERSION(ip6), !=, 6); 249 250 payload_len = GET_BE_U_2(ip6->ip6_plen); 251 /* 252 * RFC 1883 says: 253 * 254 * The Payload Length field in the IPv6 header must be set to zero 255 * in every packet that carries the Jumbo Payload option. If a 256 * packet is received with a valid Jumbo Payload option present and 257 * a non-zero IPv6 Payload Length field, an ICMP Parameter Problem 258 * message, Code 0, should be sent to the packet's source, pointing 259 * to the Option Type field of the Jumbo Payload option. 260 * 261 * Later versions of the IPv6 spec don't discuss the Jumbo Payload 262 * option. 263 * 264 * If the payload length is 0, we temporarily just set the total 265 * length to the remaining data in the packet (which, for Ethernet, 266 * could include frame padding, but if it's a Jumbo Payload frame, 267 * it shouldn't even be sendable over Ethernet, so we don't worry 268 * about that), so we can process the extension headers in order 269 * to *find* a Jumbo Payload hop-by-hop option and, when we've 270 * processed all the extension headers, check whether we found 271 * a Jumbo Payload option, and fail if we haven't. 272 */ 273 if (payload_len != 0) { 274 len = payload_len + sizeof(struct ip6_hdr); 275 if (len > length) { 276 ND_PRINT("[header+payload length %u > length %u]", 277 len, length); 278 nd_print_invalid(ndo); 279 ND_PRINT(" "); 280 } 281 } else 282 len = length + sizeof(struct ip6_hdr); 283 284 ph = 255; 285 nh = GET_U_1(ip6->ip6_nxt); 286 if (ndo->ndo_vflag) { 287 flow = GET_BE_U_4(ip6->ip6_flow); 288 ND_PRINT("("); 289 /* RFC 2460 */ 290 if (flow & 0x0ff00000) 291 ND_PRINT("class 0x%02x, ", (flow & 0x0ff00000) >> 20); 292 if (flow & 0x000fffff) 293 ND_PRINT("flowlabel 0x%05x, ", flow & 0x000fffff); 294 295 ND_PRINT("hlim %u, next-header %s (%u) payload length: %u) ", 296 GET_U_1(ip6->ip6_hlim), 297 tok2str(ipproto_values,"unknown",nh), 298 nh, 299 payload_len); 300 } 301 ND_TCHECK_SIZE(ip6); 302 303 /* 304 * Cut off the snapshot length to the end of the IP payload. 305 */ 306 if (!nd_push_snaplen(ndo, bp, len)) { 307 (*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC, 308 "%s: can't push snaplen on buffer stack", __func__); 309 } 310 311 cp = (const u_char *)ip6; 312 advance = sizeof(struct ip6_hdr); 313 total_advance = 0; 314 /* Process extension headers */ 315 found_extension_header = 0; 316 found_jumbo = 0; 317 found_hbh = 0; 318 while (cp < ndo->ndo_snapend && advance > 0) { 319 if (len < (u_int)advance) 320 goto trunc; 321 cp += advance; 322 len -= advance; 323 total_advance += advance; 324 325 if (cp == (const u_char *)(ip6 + 1) && 326 nh != IPPROTO_TCP && nh != IPPROTO_UDP && 327 nh != IPPROTO_DCCP && nh != IPPROTO_SCTP) { 328 ND_PRINT("%s > %s: ", GET_IP6ADDR_STRING(ip6->ip6_src), 329 GET_IP6ADDR_STRING(ip6->ip6_dst)); 330 } 331 332 switch (nh) { 333 334 case IPPROTO_HOPOPTS: 335 /* 336 * The Hop-by-Hop Options header, when present, 337 * must immediately follow the IPv6 header (RFC 8200) 338 */ 339 if (found_hbh == 1) { 340 ND_PRINT("[The Hop-by-Hop Options header was already found]"); 341 nd_print_invalid(ndo); 342 return; 343 } 344 if (ph != 255) { 345 ND_PRINT("[The Hop-by-Hop Options header don't follow the IPv6 header]"); 346 nd_print_invalid(ndo); 347 return; 348 } 349 advance = hbhopt_process(ndo, cp, &found_jumbo, &payload_len); 350 if (payload_len == 0 && found_jumbo == 0) { 351 ND_PRINT("[No valid Jumbo Payload Hop-by-Hop option found]"); 352 nd_print_invalid(ndo); 353 return; 354 } 355 if (advance < 0) { 356 nd_pop_packet_info(ndo); 357 return; 358 } 359 found_extension_header = 1; 360 found_hbh = 1; 361 nh = GET_U_1(cp); 362 break; 363 364 case IPPROTO_DSTOPTS: 365 advance = dstopt_process(ndo, cp); 366 if (advance < 0) { 367 nd_pop_packet_info(ndo); 368 return; 369 } 370 found_extension_header = 1; 371 nh = GET_U_1(cp); 372 break; 373 374 case IPPROTO_FRAGMENT: 375 advance = frag6_print(ndo, cp, (const u_char *)ip6); 376 if (advance < 0 || ndo->ndo_snapend <= cp + advance) { 377 nd_pop_packet_info(ndo); 378 return; 379 } 380 found_extension_header = 1; 381 nh = GET_U_1(cp); 382 fragmented = 1; 383 break; 384 385 case IPPROTO_MOBILITY_OLD: 386 case IPPROTO_MOBILITY: 387 /* 388 * RFC 3775 says that 389 * the next header field in a mobility header 390 * should be IPPROTO_NONE, but speaks of 391 * the possibility of a future extension in 392 * which payload can be piggybacked atop a 393 * mobility header. 394 */ 395 advance = mobility_print(ndo, cp, (const u_char *)ip6); 396 if (advance < 0) { 397 nd_pop_packet_info(ndo); 398 return; 399 } 400 found_extension_header = 1; 401 nh = GET_U_1(cp); 402 nd_pop_packet_info(ndo); 403 return; 404 405 case IPPROTO_ROUTING: 406 ND_TCHECK_1(cp); 407 advance = rt6_print(ndo, cp, (const u_char *)ip6); 408 if (advance < 0) { 409 nd_pop_packet_info(ndo); 410 return; 411 } 412 found_extension_header = 1; 413 nh = GET_U_1(cp); 414 break; 415 416 default: 417 /* 418 * Not an extension header; hand off to the 419 * IP protocol demuxer. 420 */ 421 if (found_jumbo) { 422 /* 423 * We saw a Jumbo Payload option. 424 * Set the length to the payload length 425 * plus the IPv6 header length, and 426 * change the snapshot length accordingly. 427 * 428 * But make sure it's not shorter than 429 * the total number of bytes we've 430 * processed so far. 431 */ 432 len = payload_len + sizeof(struct ip6_hdr); 433 if (len < total_advance) 434 goto trunc; 435 if (len > length) { 436 ND_PRINT("[header+payload length %u > length %u]", 437 len, length); 438 nd_print_invalid(ndo); 439 ND_PRINT(" "); 440 } 441 nd_change_snaplen(ndo, bp, len); 442 443 /* 444 * Now subtract the length of the IPv6 445 * header plus extension headers to get 446 * the payload length. 447 */ 448 len -= total_advance; 449 } else { 450 /* 451 * We didn't see a Jumbo Payload option; 452 * was the payload length zero? 453 */ 454 if (payload_len == 0) { 455 /* 456 * Yes. If we found an extension 457 * header, treat that as a truncated 458 * packet header, as there was 459 * no payload to contain an 460 * extension header. 461 */ 462 if (found_extension_header) 463 goto trunc; 464 465 /* 466 * OK, we didn't see any extension 467 * header, but that means we have 468 * no payload, so set the length 469 * to the IPv6 header length, 470 * and change the snapshot length 471 * accordingly. 472 */ 473 len = sizeof(struct ip6_hdr); 474 nd_change_snaplen(ndo, bp, len); 475 476 /* 477 * Now subtract the length of 478 * the IPv6 header plus extension 479 * headers (there weren't any, so 480 * that's just the IPv6 header 481 * length) to get the payload length. 482 */ 483 len -= total_advance; 484 } 485 } 486 ip_demux_print(ndo, cp, len, 6, fragmented, 487 GET_U_1(ip6->ip6_hlim), nh, bp); 488 nd_pop_packet_info(ndo); 489 return; 490 } 491 ph = nh; 492 493 /* ndo_protocol reassignment after xxx_print() calls */ 494 ndo->ndo_protocol = "ip6"; 495 } 496 497 nd_pop_packet_info(ndo); 498 return; 499 trunc: 500 nd_print_trunc(ndo); 501 return; 502 503 invalid: 504 nd_print_invalid(ndo); 505 } 506