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