1 /* 2 * Copyright (c) 1988, 1989, 1990, 1991, 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-icmp6.c,v 1.16 2024/09/02 16:15:31 christos Exp $"); 25 #endif 26 27 /* \summary: IPv6 Internet Control Message Protocol (ICMPv6) printer */ 28 29 #include <config.h> 30 31 #include "netdissect-stdinc.h" 32 33 #include <stdio.h> 34 #include <string.h> 35 36 #include "netdissect.h" 37 #include "addrtoname.h" 38 #include "addrtostr.h" 39 #include "extract.h" 40 41 #include "ip6.h" 42 #include "ipproto.h" 43 44 #include "udp.h" 45 #include "ah.h" 46 47 /* NetBSD: icmp6.h,v 1.13 2000/08/03 16:30:37 itojun Exp */ 48 /* $KAME: icmp6.h,v 1.22 2000/08/03 15:25:16 jinmei Exp $ */ 49 50 /* 51 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 52 * All rights reserved. 53 * 54 * Redistribution and use in source and binary forms, with or without 55 * modification, are permitted provided that the following conditions 56 * are met: 57 * 1. Redistributions of source code must retain the above copyright 58 * notice, this list of conditions and the following disclaimer. 59 * 2. Redistributions in binary form must reproduce the above copyright 60 * notice, this list of conditions and the following disclaimer in the 61 * documentation and/or other materials provided with the distribution. 62 * 3. Neither the name of the project nor the names of its contributors 63 * may be used to endorse or promote products derived from this software 64 * without specific prior written permission. 65 * 66 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 67 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 68 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 69 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 70 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 71 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 72 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 73 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 74 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 75 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 76 * SUCH DAMAGE. 77 */ 78 79 struct icmp6_hdr { 80 nd_uint8_t icmp6_type; /* type field */ 81 nd_uint8_t icmp6_code; /* code field */ 82 nd_uint16_t icmp6_cksum; /* checksum field */ 83 union { 84 nd_uint32_t icmp6_un_data32[1]; /* type-specific field */ 85 nd_uint16_t icmp6_un_data16[2]; /* type-specific field */ 86 nd_uint8_t icmp6_un_data8[4]; /* type-specific field */ 87 nd_byte icmp6_un_data[1]; /* type-specific field */ 88 } icmp6_dataun; 89 }; 90 91 #define icmp6_data32 icmp6_dataun.icmp6_un_data32 92 #define icmp6_data16 icmp6_dataun.icmp6_un_data16 93 #define icmp6_data8 icmp6_dataun.icmp6_un_data8 94 #define icmp6_data icmp6_dataun.icmp6_un_data 95 #define icmp6_pptr icmp6_data32[0] /* parameter prob */ 96 #define icmp6_mtu icmp6_data32[0] /* packet too big */ 97 #define icmp6_id icmp6_data16[0] /* echo request/reply */ 98 #define icmp6_seq icmp6_data16[1] /* echo request/reply */ 99 #define icmp6_maxdelay icmp6_data16[0] /* mcast group membership */ 100 101 #define ICMP6_DST_UNREACH 1 /* dest unreachable, codes: */ 102 #define ICMP6_PACKET_TOO_BIG 2 /* packet too big */ 103 #define ICMP6_TIME_EXCEEDED 3 /* time exceeded, code: */ 104 #define ICMP6_PARAM_PROB 4 /* ip6 header bad */ 105 106 #define ICMP6_ECHO_REQUEST 128 /* echo service */ 107 #define ICMP6_ECHO_REPLY 129 /* echo reply */ 108 #define ICMP6_MEMBERSHIP_QUERY 130 /* group membership query */ 109 #define MLD6_LISTENER_QUERY 130 /* multicast listener query */ 110 #define ICMP6_MEMBERSHIP_REPORT 131 /* group membership report */ 111 #define MLD6_LISTENER_REPORT 131 /* multicast listener report */ 112 #define ICMP6_MEMBERSHIP_REDUCTION 132 /* group membership termination */ 113 #define MLD6_LISTENER_DONE 132 /* multicast listener done */ 114 115 #define ND_ROUTER_SOLICIT 133 /* router solicitation */ 116 #define ND_ROUTER_ADVERT 134 /* router advertisement */ 117 #define ND_NEIGHBOR_SOLICIT 135 /* neighbor solicitation */ 118 #define ND_NEIGHBOR_ADVERT 136 /* neighbor advertisement */ 119 #define ND_REDIRECT 137 /* redirect */ 120 121 #define ICMP6_ROUTER_RENUMBERING 138 /* router renumbering */ 122 123 #define ICMP6_WRUREQUEST 139 /* who are you request */ 124 #define ICMP6_WRUREPLY 140 /* who are you reply */ 125 #define ICMP6_FQDN_QUERY 139 /* FQDN query */ 126 #define ICMP6_FQDN_REPLY 140 /* FQDN reply */ 127 #define ICMP6_NI_QUERY 139 /* node information request - RFC 4620 */ 128 #define ICMP6_NI_REPLY 140 /* node information reply - RFC 4620 */ 129 #define IND_SOLICIT 141 /* inverse neighbor solicitation */ 130 #define IND_ADVERT 142 /* inverse neighbor advertisement */ 131 132 #define ICMP6_V2_MEMBERSHIP_REPORT 143 /* v2 membership report */ 133 #define MLDV2_LISTENER_REPORT 143 /* v2 multicast listener report */ 134 #define ICMP6_HADISCOV_REQUEST 144 135 #define ICMP6_HADISCOV_REPLY 145 136 #define ICMP6_MOBILEPREFIX_SOLICIT 146 137 #define ICMP6_MOBILEPREFIX_ADVERT 147 138 139 #define MLD6_MTRACE_RESP 200 /* mtrace response(to sender) */ 140 #define MLD6_MTRACE 201 /* mtrace messages */ 141 142 #define ICMP6_MAXTYPE 201 143 144 #define ICMP6_DST_UNREACH_NOROUTE 0 /* no route to destination */ 145 #define ICMP6_DST_UNREACH_ADMIN 1 /* administratively prohibited */ 146 #define ICMP6_DST_UNREACH_NOTNEIGHBOR 2 /* not a neighbor(obsolete) */ 147 #define ICMP6_DST_UNREACH_BEYONDSCOPE 2 /* beyond scope of source address */ 148 #define ICMP6_DST_UNREACH_ADDR 3 /* address unreachable */ 149 #define ICMP6_DST_UNREACH_NOPORT 4 /* port unreachable */ 150 151 #define ICMP6_TIME_EXCEED_TRANSIT 0 /* ttl==0 in transit */ 152 #define ICMP6_TIME_EXCEED_REASSEMBLY 1 /* ttl==0 in reass */ 153 154 #define ICMP6_PARAMPROB_HEADER 0 /* erroneous header field */ 155 #define ICMP6_PARAMPROB_NEXTHEADER 1 /* unrecognized next header */ 156 #define ICMP6_PARAMPROB_OPTION 2 /* unrecognized option */ 157 #define ICMP6_PARAMPROB_FRAGHDRCHAIN 3 /* incomplete header chain */ 158 159 #define ICMP6_INFOMSG_MASK 0x80 /* all informational messages */ 160 161 #define ICMP6_NI_SUBJ_IPV6 0 /* Query Subject is an IPv6 address */ 162 #define ICMP6_NI_SUBJ_FQDN 1 /* Query Subject is a Domain name */ 163 #define ICMP6_NI_SUBJ_IPV4 2 /* Query Subject is an IPv4 address */ 164 165 #define ICMP6_NI_SUCCESS 0 /* node information successful reply */ 166 #define ICMP6_NI_REFUSED 1 /* node information request is refused */ 167 #define ICMP6_NI_UNKNOWN 2 /* unknown Qtype */ 168 169 #define ICMP6_ROUTER_RENUMBERING_COMMAND 0 /* rr command */ 170 #define ICMP6_ROUTER_RENUMBERING_RESULT 1 /* rr result */ 171 #define ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET 255 /* rr seq num reset */ 172 173 /* Used in kernel only */ 174 #define ND_REDIRECT_ONLINK 0 /* redirect to an on-link node */ 175 #define ND_REDIRECT_ROUTER 1 /* redirect to a better router */ 176 177 /* 178 * Multicast Listener Discovery 179 */ 180 struct mld6_hdr { 181 struct icmp6_hdr mld6_hdr; 182 nd_ipv6 mld6_addr; /* multicast address */ 183 }; 184 185 #define mld6_type mld6_hdr.icmp6_type 186 #define mld6_code mld6_hdr.icmp6_code 187 #define mld6_cksum mld6_hdr.icmp6_cksum 188 #define mld6_maxdelay mld6_hdr.icmp6_data16[0] 189 #define mld6_reserved mld6_hdr.icmp6_data16[1] 190 191 #define MLD_MINLEN 24 192 #define MLDV2_MINLEN 28 193 194 /* 195 * Neighbor Discovery 196 */ 197 198 struct nd_router_solicit { /* router solicitation */ 199 struct icmp6_hdr nd_rs_hdr; 200 /* could be followed by options */ 201 }; 202 203 #define nd_rs_type nd_rs_hdr.icmp6_type 204 #define nd_rs_code nd_rs_hdr.icmp6_code 205 #define nd_rs_cksum nd_rs_hdr.icmp6_cksum 206 #define nd_rs_reserved nd_rs_hdr.icmp6_data32[0] 207 208 struct nd_router_advert { /* router advertisement */ 209 struct icmp6_hdr nd_ra_hdr; 210 nd_uint32_t nd_ra_reachable; /* reachable time */ 211 nd_uint32_t nd_ra_retransmit; /* retransmit timer */ 212 /* could be followed by options */ 213 }; 214 215 #define nd_ra_type nd_ra_hdr.icmp6_type 216 #define nd_ra_code nd_ra_hdr.icmp6_code 217 #define nd_ra_cksum nd_ra_hdr.icmp6_cksum 218 #define nd_ra_curhoplimit nd_ra_hdr.icmp6_data8[0] 219 #define nd_ra_flags_reserved nd_ra_hdr.icmp6_data8[1] 220 #define ND_RA_FLAG_MANAGED 0x80 221 #define ND_RA_FLAG_OTHER 0x40 222 #define ND_RA_FLAG_HOME_AGENT 0x20 223 #define ND_RA_FLAG_IPV6ONLY 0x02 224 225 /* 226 * Router preference values based on draft-draves-ipngwg-router-selection-01. 227 * These are non-standard definitions. 228 */ 229 #define ND_RA_FLAG_RTPREF_MASK 0x18 /* 00011000 */ 230 231 #define ND_RA_FLAG_RTPREF_HIGH 0x08 /* 00001000 */ 232 #define ND_RA_FLAG_RTPREF_MEDIUM 0x00 /* 00000000 */ 233 #define ND_RA_FLAG_RTPREF_LOW 0x18 /* 00011000 */ 234 #define ND_RA_FLAG_RTPREF_RSV 0x10 /* 00010000 */ 235 236 #define nd_ra_router_lifetime nd_ra_hdr.icmp6_data16[1] 237 238 struct nd_neighbor_solicit { /* neighbor solicitation */ 239 struct icmp6_hdr nd_ns_hdr; 240 nd_ipv6 nd_ns_target; /*target address */ 241 /* could be followed by options */ 242 }; 243 244 #define nd_ns_type nd_ns_hdr.icmp6_type 245 #define nd_ns_code nd_ns_hdr.icmp6_code 246 #define nd_ns_cksum nd_ns_hdr.icmp6_cksum 247 #define nd_ns_reserved nd_ns_hdr.icmp6_data32[0] 248 249 struct nd_neighbor_advert { /* neighbor advertisement */ 250 struct icmp6_hdr nd_na_hdr; 251 nd_ipv6 nd_na_target; /* target address */ 252 /* could be followed by options */ 253 }; 254 255 #define nd_na_type nd_na_hdr.icmp6_type 256 #define nd_na_code nd_na_hdr.icmp6_code 257 #define nd_na_cksum nd_na_hdr.icmp6_cksum 258 #define nd_na_flags_reserved nd_na_hdr.icmp6_data32[0] 259 260 #define ND_NA_FLAG_ROUTER 0x80000000 261 #define ND_NA_FLAG_SOLICITED 0x40000000 262 #define ND_NA_FLAG_OVERRIDE 0x20000000 263 264 struct nd_redirect { /* redirect */ 265 struct icmp6_hdr nd_rd_hdr; 266 nd_ipv6 nd_rd_target; /* target address */ 267 nd_ipv6 nd_rd_dst; /* destination address */ 268 /* could be followed by options */ 269 }; 270 271 #define nd_rd_type nd_rd_hdr.icmp6_type 272 #define nd_rd_code nd_rd_hdr.icmp6_code 273 #define nd_rd_cksum nd_rd_hdr.icmp6_cksum 274 #define nd_rd_reserved nd_rd_hdr.icmp6_data32[0] 275 276 struct nd_opt_hdr { /* Neighbor discovery option header */ 277 nd_uint8_t nd_opt_type; 278 nd_uint8_t nd_opt_len; 279 /* followed by option specific data*/ 280 }; 281 282 #define ND_OPT_SOURCE_LINKADDR 1 283 #define ND_OPT_TARGET_LINKADDR 2 284 #define ND_OPT_PREFIX_INFORMATION 3 285 #define ND_OPT_REDIRECTED_HEADER 4 286 #define ND_OPT_MTU 5 287 #define ND_OPT_ADVINTERVAL 7 288 #define ND_OPT_HOMEAGENT_INFO 8 289 #define ND_OPT_ROUTE_INFO 24 /* RFC4191 */ 290 #define ND_OPT_RDNSS 25 291 #define ND_OPT_DNSSL 31 292 293 struct nd_opt_prefix_info { /* prefix information */ 294 nd_uint8_t nd_opt_pi_type; 295 nd_uint8_t nd_opt_pi_len; 296 nd_uint8_t nd_opt_pi_prefix_len; 297 nd_uint8_t nd_opt_pi_flags_reserved; 298 nd_uint32_t nd_opt_pi_valid_time; 299 nd_uint32_t nd_opt_pi_preferred_time; 300 nd_uint32_t nd_opt_pi_reserved2; 301 nd_ipv6 nd_opt_pi_prefix; 302 }; 303 304 #define ND_OPT_PI_FLAG_ONLINK 0x80 305 #define ND_OPT_PI_FLAG_AUTO 0x40 306 #define ND_OPT_PI_FLAG_ROUTER 0x20 /*2292bis*/ 307 308 struct nd_opt_rd_hdr { /* redirected header */ 309 nd_uint8_t nd_opt_rh_type; 310 nd_uint8_t nd_opt_rh_len; 311 nd_uint16_t nd_opt_rh_reserved1; 312 nd_uint32_t nd_opt_rh_reserved2; 313 /* followed by IP header and data */ 314 }; 315 316 struct nd_opt_mtu { /* MTU option */ 317 nd_uint8_t nd_opt_mtu_type; 318 nd_uint8_t nd_opt_mtu_len; 319 nd_uint16_t nd_opt_mtu_reserved; 320 nd_uint32_t nd_opt_mtu_mtu; 321 }; 322 323 struct nd_opt_rdnss { /* RDNSS RFC 6106 5.1 */ 324 nd_uint8_t nd_opt_rdnss_type; 325 nd_uint8_t nd_opt_rdnss_len; 326 nd_uint16_t nd_opt_rdnss_reserved; 327 nd_uint32_t nd_opt_rdnss_lifetime; 328 nd_ipv6 nd_opt_rdnss_addr[1]; /* variable-length */ 329 }; 330 331 struct nd_opt_dnssl { /* DNSSL RFC 6106 5.2 */ 332 nd_uint8_t nd_opt_dnssl_type; 333 nd_uint8_t nd_opt_dnssl_len; 334 nd_uint16_t nd_opt_dnssl_reserved; 335 nd_uint32_t nd_opt_dnssl_lifetime; 336 /* followed by list of DNS search domains, variable-length */ 337 }; 338 339 struct nd_opt_advinterval { /* Advertisement interval option */ 340 nd_uint8_t nd_opt_adv_type; 341 nd_uint8_t nd_opt_adv_len; 342 nd_uint16_t nd_opt_adv_reserved; 343 nd_uint32_t nd_opt_adv_interval; 344 }; 345 346 struct nd_opt_homeagent_info { /* Home Agent info */ 347 nd_uint8_t nd_opt_hai_type; 348 nd_uint8_t nd_opt_hai_len; 349 nd_uint16_t nd_opt_hai_reserved; 350 nd_uint16_t nd_opt_hai_preference; 351 nd_uint16_t nd_opt_hai_lifetime; 352 }; 353 354 struct nd_opt_route_info { /* route info */ 355 nd_uint8_t nd_opt_rti_type; 356 nd_uint8_t nd_opt_rti_len; 357 nd_uint8_t nd_opt_rti_prefixlen; 358 nd_uint8_t nd_opt_rti_flags; 359 nd_uint32_t nd_opt_rti_lifetime; 360 /* prefix follows */ 361 }; 362 363 /* 364 * icmp6 namelookup 365 */ 366 367 struct icmp6_namelookup { 368 struct icmp6_hdr icmp6_nl_hdr; 369 nd_byte icmp6_nl_nonce[8]; 370 nd_int32_t icmp6_nl_ttl; 371 #if 0 372 nd_uint8_t icmp6_nl_len; 373 nd_byte icmp6_nl_name[3]; 374 #endif 375 /* could be followed by options */ 376 }; 377 378 /* 379 * icmp6 node information 380 */ 381 struct icmp6_nodeinfo { 382 struct icmp6_hdr icmp6_ni_hdr; 383 nd_byte icmp6_ni_nonce[8]; 384 /* could be followed by reply data */ 385 }; 386 387 #define ni_type icmp6_ni_hdr.icmp6_type 388 #define ni_code icmp6_ni_hdr.icmp6_code 389 #define ni_cksum icmp6_ni_hdr.icmp6_cksum 390 #define ni_qtype icmp6_ni_hdr.icmp6_data16[0] 391 #define ni_flags icmp6_ni_hdr.icmp6_data16[1] 392 393 #define NI_QTYPE_NOOP 0 /* NOOP */ 394 #define NI_QTYPE_SUPTYPES 1 /* Supported Qtypes (drafts up to 09) */ 395 #define NI_QTYPE_FQDN 2 /* FQDN (draft 04) */ 396 #define NI_QTYPE_DNSNAME 2 /* DNS Name */ 397 #define NI_QTYPE_NODEADDR 3 /* Node Addresses */ 398 #define NI_QTYPE_IPV4ADDR 4 /* IPv4 Addresses */ 399 400 #define NI_NODEADDR_FLAG_TRUNCATE 0x0001 401 #define NI_NODEADDR_FLAG_ALL 0x0002 402 #define NI_NODEADDR_FLAG_COMPAT 0x0004 403 #define NI_NODEADDR_FLAG_LINKLOCAL 0x0008 404 #define NI_NODEADDR_FLAG_SITELOCAL 0x0010 405 #define NI_NODEADDR_FLAG_GLOBAL 0x0020 406 #define NI_NODEADDR_FLAG_ANYCAST 0x0040 /* just experimental. not in spec */ 407 408 struct ni_reply_fqdn { 409 nd_uint32_t ni_fqdn_ttl; /* TTL */ 410 nd_uint8_t ni_fqdn_namelen; /* length in octets of the FQDN */ 411 nd_byte ni_fqdn_name[3]; /* XXX: alignment */ 412 }; 413 414 /* 415 * Router Renumbering. as router-renum-08.txt 416 */ 417 struct icmp6_router_renum { /* router renumbering header */ 418 struct icmp6_hdr rr_hdr; 419 nd_uint8_t rr_segnum; 420 nd_uint8_t rr_flags; 421 nd_uint16_t rr_maxdelay; 422 nd_uint32_t rr_reserved; 423 }; 424 #define ICMP6_RR_FLAGS_TEST 0x80 425 #define ICMP6_RR_FLAGS_REQRESULT 0x40 426 #define ICMP6_RR_FLAGS_FORCEAPPLY 0x20 427 #define ICMP6_RR_FLAGS_SPECSITE 0x10 428 #define ICMP6_RR_FLAGS_PREVDONE 0x08 429 430 #define rr_type rr_hdr.icmp6_type 431 #define rr_code rr_hdr.icmp6_code 432 #define rr_cksum rr_hdr.icmp6_cksum 433 #define rr_seqnum rr_hdr.icmp6_data32[0] 434 435 struct rr_pco_match { /* match prefix part */ 436 nd_uint8_t rpm_code; 437 nd_uint8_t rpm_len; 438 nd_uint8_t rpm_ordinal; 439 nd_uint8_t rpm_matchlen; 440 nd_uint8_t rpm_minlen; 441 nd_uint8_t rpm_maxlen; 442 nd_uint16_t rpm_reserved; 443 nd_ipv6 rpm_prefix; 444 }; 445 446 #define RPM_PCO_ADD 1 447 #define RPM_PCO_CHANGE 2 448 #define RPM_PCO_SETGLOBAL 3 449 #define RPM_PCO_MAX 4 450 451 struct rr_pco_use { /* use prefix part */ 452 nd_uint8_t rpu_uselen; 453 nd_uint8_t rpu_keeplen; 454 nd_uint8_t rpu_ramask; 455 nd_uint8_t rpu_raflags; 456 nd_uint32_t rpu_vltime; 457 nd_uint32_t rpu_pltime; 458 nd_uint32_t rpu_flags; 459 nd_ipv6 rpu_prefix; 460 }; 461 #define ICMP6_RR_PCOUSE_RAFLAGS_ONLINK 0x80 462 #define ICMP6_RR_PCOUSE_RAFLAGS_AUTO 0x40 463 464 /* network endian */ 465 #define ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME ((uint32_t)htonl(0x80000000)) 466 #define ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME ((uint32_t)htonl(0x40000000)) 467 468 struct rr_result { /* router renumbering result message */ 469 nd_uint16_t rrr_flags; 470 nd_uint8_t rrr_ordinal; 471 nd_uint8_t rrr_matchedlen; 472 nd_uint32_t rrr_ifid; 473 nd_ipv6 rrr_prefix; 474 }; 475 /* network endian */ 476 #define ICMP6_RR_RESULT_FLAGS_OOB ((uint16_t)htons(0x0002)) 477 #define ICMP6_RR_RESULT_FLAGS_FORBIDDEN ((uint16_t)htons(0x0001)) 478 479 static const char *get_rtpref(u_int); 480 static const char *get_lifetime(uint32_t); 481 static void print_lladdr(netdissect_options *ndo, const u_char *, size_t); 482 static int icmp6_opt_print(netdissect_options *ndo, const u_char *, int); 483 static void mld6_print(netdissect_options *ndo, const u_char *); 484 static void mldv2_report_print(netdissect_options *ndo, const u_char *, u_int); 485 static void mldv2_query_print(netdissect_options *ndo, const u_char *, u_int); 486 static const struct udphdr *get_upperlayer(netdissect_options *ndo, const u_char *, u_int *); 487 static void dnsname_print(netdissect_options *ndo, const u_char *, const u_char *); 488 static void icmp6_nodeinfo_print(netdissect_options *ndo, u_int, const u_char *, const u_char *); 489 static void icmp6_rrenum_print(netdissect_options *ndo, const u_char *, const u_char *); 490 491 /* 492 * DIO: Updated to RFC6550, as published in 2012: section 6. (page 30) 493 */ 494 495 #define ND_RPL_MESSAGE 155 /* 0x9B */ 496 497 enum ND_RPL_CODE { 498 ND_RPL_DAG_IS=0x00, 499 ND_RPL_DAG_IO=0x01, 500 ND_RPL_DAO =0x02, 501 ND_RPL_DAO_ACK=0x03, 502 ND_RPL_SEC_DAG_IS = 0x80, 503 ND_RPL_SEC_DAG_IO = 0x81, 504 ND_RPL_SEC_DAG = 0x82, 505 ND_RPL_SEC_DAG_ACK= 0x83, 506 ND_RPL_SEC_CONSIST= 0x8A 507 }; 508 509 enum ND_RPL_DIO_FLAGS { 510 ND_RPL_DIO_GROUNDED = 0x80, 511 ND_RPL_DIO_DATRIG = 0x40, 512 ND_RPL_DIO_DASUPPORT= 0x20, 513 ND_RPL_DIO_RES4 = 0x10, 514 ND_RPL_DIO_RES3 = 0x08, 515 ND_RPL_DIO_PRF_MASK = 0x07 /* 3-bit preference */ 516 }; 517 518 #define DAGID_LEN 16 519 520 /* section 6 of draft-ietf-roll-rpl-19 */ 521 struct nd_rpl_security { 522 nd_uint8_t rpl_sec_t_reserved; /* bit 7 is T-bit */ 523 nd_uint8_t rpl_sec_algo; 524 nd_uint16_t rpl_sec_kim_lvl_flags; /* bit 15/14, KIM */ 525 /* bit 10-8, LVL, bit 7-0 flags */ 526 nd_uint32_t rpl_sec_counter; 527 #if 0 528 nd_byte rpl_sec_ki[0]; /* depends upon kim */ 529 #endif 530 }; 531 532 /* section 6.2.1, DODAG Information Solicitation (DIS_IS) */ 533 struct nd_rpl_dis_is { 534 nd_uint8_t rpl_dis_flags; 535 nd_uint8_t rpl_dis_reserved; 536 #if 0 537 nd_byte rpl_dis_options[0]; 538 #endif 539 }; 540 541 /* section 6.3.1, DODAG Information Object (DIO) */ 542 struct nd_rpl_dio { 543 nd_uint8_t rpl_instanceid; 544 nd_uint8_t rpl_version; 545 nd_uint16_t rpl_dagrank; 546 nd_uint8_t rpl_mopprf; /* bit 7=G, 5-3=MOP, 2-0=PRF */ 547 nd_uint8_t rpl_dtsn; /* Dest. Advertisement Trigger Sequence Number */ 548 nd_uint8_t rpl_flags; /* no flags defined yet */ 549 nd_uint8_t rpl_resv1; 550 nd_byte rpl_dagid[DAGID_LEN]; 551 }; 552 #define RPL_DIO_GROUND_FLAG 0x80 553 #define RPL_DIO_MOP_SHIFT 3 554 #define RPL_DIO_MOP_MASK (7 << RPL_DIO_MOP_SHIFT) 555 #define RPL_DIO_PRF_SHIFT 0 556 #define RPL_DIO_PRF_MASK (7 << RPL_DIO_PRF_SHIFT) 557 #define RPL_DIO_GROUNDED(X) ((X)&RPL_DIO_GROUND_FLAG) 558 #define RPL_DIO_MOP(X) (enum RPL_DIO_MOP)(((X)&RPL_DIO_MOP_MASK) >> RPL_DIO_MOP_SHIFT) 559 #define RPL_DIO_PRF(X) (((X)&RPL_DIO_PRF_MASK) >> RPL_DIO_PRF_SHIFT) 560 561 enum RPL_DIO_MOP { 562 RPL_DIO_NONSTORING= 0x0, 563 RPL_DIO_STORING = 0x1, 564 RPL_DIO_NONSTORING_MULTICAST = 0x2, 565 RPL_DIO_STORING_MULTICAST = 0x3 566 }; 567 568 enum RPL_SUBOPT { 569 RPL_OPT_PAD1 = 0, 570 RPL_OPT_PADN = 1, 571 RPL_DIO_METRICS = 2, 572 RPL_DIO_ROUTINGINFO = 3, 573 RPL_DIO_CONFIG = 4, 574 RPL_DAO_RPLTARGET = 5, 575 RPL_DAO_TRANSITINFO = 6, 576 RPL_DIO_DESTPREFIX = 8, 577 RPL_DAO_RPLTARGET_DESC=9 578 }; 579 580 struct rpl_genoption { 581 nd_uint8_t rpl_dio_type; 582 nd_uint8_t rpl_dio_len; /* suboption length, not including type/len */ 583 }; 584 #define RPL_GENOPTION_LEN 2 585 586 #define RPL_DIO_LIFETIME_INFINITE 0xffffffff 587 #define RPL_DIO_LIFETIME_DISCONNECT 0 588 589 struct rpl_dio_destprefix { 590 nd_uint8_t rpl_dio_type; 591 nd_uint8_t rpl_dio_len; 592 nd_uint8_t rpl_dio_prefixlen; /* in bits */ 593 nd_uint8_t rpl_dio_prf; /* flags, including Route Preference */ 594 nd_uint32_t rpl_dio_prefixlifetime; /* in seconds */ 595 #if 0 596 nd_byte rpl_dio_prefix[0]; /* variable number of bytes */ 597 #endif 598 }; 599 600 /* section 6.4.1, DODAG Information Object (DIO) */ 601 struct nd_rpl_dao { 602 nd_uint8_t rpl_instanceid; 603 nd_uint8_t rpl_flags; /* bit 7=K, 6=D */ 604 nd_uint8_t rpl_resv; 605 nd_uint8_t rpl_daoseq; 606 nd_byte rpl_dagid[DAGID_LEN]; /* present when D set. */ 607 }; 608 #define ND_RPL_DAO_MIN_LEN 4 /* length without DAGID */ 609 610 /* indicates if this DAO is to be acK'ed */ 611 #define RPL_DAO_K_SHIFT 7 612 #define RPL_DAO_K_MASK (1 << RPL_DAO_K_SHIFT) 613 #define RPL_DAO_K(X) (((X)&RPL_DAO_K_MASK) >> RPL_DAO_K_SHIFT) 614 615 /* indicates if the DAGID is present */ 616 #define RPL_DAO_D_SHIFT 6 617 #define RPL_DAO_D_MASK (1 << RPL_DAO_D_SHIFT) 618 #define RPL_DAO_D(X) (((X)&RPL_DAO_D_MASK) >> RPL_DAO_D_SHIFT) 619 620 struct rpl_dao_target { 621 nd_uint8_t rpl_dao_type; 622 nd_uint8_t rpl_dao_len; 623 nd_uint8_t rpl_dao_flags; /* unused */ 624 nd_uint8_t rpl_dao_prefixlen; /* in bits */ 625 #if 0 626 nd_byte rpl_dao_prefix[0]; /* variable number of bytes */ 627 #endif 628 }; 629 630 /* section 6.5.1, Destination Advertisement Object Acknowledgement (DAO-ACK) */ 631 struct nd_rpl_daoack { 632 nd_uint8_t rpl_instanceid; 633 nd_uint8_t rpl_flags; /* bit 7=D */ 634 nd_uint8_t rpl_daoseq; 635 nd_uint8_t rpl_status; 636 nd_byte rpl_dagid[DAGID_LEN]; /* present when D set. */ 637 }; 638 #define ND_RPL_DAOACK_MIN_LEN 4 /* length without DAGID */ 639 /* indicates if the DAGID is present */ 640 #define RPL_DAOACK_D_SHIFT 7 641 #define RPL_DAOACK_D_MASK (1 << RPL_DAOACK_D_SHIFT) 642 #define RPL_DAOACK_D(X) (((X)&RPL_DAOACK_D_MASK) >> RPL_DAOACK_D_SHIFT) 643 644 static const struct tok icmp6_type_values[] = { 645 { ICMP6_DST_UNREACH, "destination unreachable"}, 646 { ICMP6_PACKET_TOO_BIG, "packet too big"}, 647 { ICMP6_TIME_EXCEEDED, "time exceeded in-transit"}, 648 { ICMP6_PARAM_PROB, "parameter problem"}, 649 { ICMP6_ECHO_REQUEST, "echo request"}, 650 { ICMP6_ECHO_REPLY, "echo reply"}, 651 { MLD6_LISTENER_QUERY, "multicast listener query"}, 652 { MLD6_LISTENER_REPORT, "multicast listener report"}, 653 { MLD6_LISTENER_DONE, "multicast listener done"}, 654 { ND_ROUTER_SOLICIT, "router solicitation"}, 655 { ND_ROUTER_ADVERT, "router advertisement"}, 656 { ND_NEIGHBOR_SOLICIT, "neighbor solicitation"}, 657 { ND_NEIGHBOR_ADVERT, "neighbor advertisement"}, 658 { ND_REDIRECT, "redirect"}, 659 { ICMP6_ROUTER_RENUMBERING, "router renumbering"}, 660 { IND_SOLICIT, "inverse neighbor solicitation"}, 661 { IND_ADVERT, "inverse neighbor advertisement"}, 662 { MLDV2_LISTENER_REPORT, "multicast listener report v2"}, 663 { ICMP6_HADISCOV_REQUEST, "ha discovery request"}, 664 { ICMP6_HADISCOV_REPLY, "ha discovery reply"}, 665 { ICMP6_MOBILEPREFIX_SOLICIT, "mobile router solicitation"}, 666 { ICMP6_MOBILEPREFIX_ADVERT, "mobile router advertisement"}, 667 { ICMP6_WRUREQUEST, "who-are-you request"}, 668 { ICMP6_WRUREPLY, "who-are-you reply"}, 669 { ICMP6_NI_QUERY, "node information query"}, 670 { ICMP6_NI_REPLY, "node information reply"}, 671 { MLD6_MTRACE, "mtrace message"}, 672 { MLD6_MTRACE_RESP, "mtrace response"}, 673 { ND_RPL_MESSAGE, "RPL"}, 674 { 0, NULL } 675 }; 676 677 static const struct tok icmp6_dst_unreach_code_values[] = { 678 { ICMP6_DST_UNREACH_NOROUTE, "unreachable route" }, 679 { ICMP6_DST_UNREACH_ADMIN, " unreachable prohibited"}, 680 { ICMP6_DST_UNREACH_BEYONDSCOPE, "beyond scope"}, 681 { ICMP6_DST_UNREACH_ADDR, "unreachable address"}, 682 { ICMP6_DST_UNREACH_NOPORT, "unreachable port"}, 683 { 0, NULL } 684 }; 685 686 static const struct tok icmp6_opt_pi_flag_values[] = { 687 { ND_OPT_PI_FLAG_ONLINK, "onlink" }, 688 { ND_OPT_PI_FLAG_AUTO, "auto" }, 689 { ND_OPT_PI_FLAG_ROUTER, "router" }, 690 { 0, NULL } 691 }; 692 693 static const struct tok icmp6_opt_ra_flag_values[] = { 694 { ND_RA_FLAG_MANAGED, "managed" }, 695 { ND_RA_FLAG_OTHER, "other stateful"}, 696 { ND_RA_FLAG_HOME_AGENT, "home agent"}, 697 { ND_RA_FLAG_IPV6ONLY, "ipv6 only"}, 698 { 0, NULL } 699 }; 700 701 static const struct tok icmp6_nd_na_flag_values[] = { 702 { ND_NA_FLAG_ROUTER, "router" }, 703 { ND_NA_FLAG_SOLICITED, "solicited" }, 704 { ND_NA_FLAG_OVERRIDE, "override" }, 705 { 0, NULL } 706 }; 707 708 static const struct tok icmp6_opt_values[] = { 709 { ND_OPT_SOURCE_LINKADDR, "source link-address"}, 710 { ND_OPT_TARGET_LINKADDR, "destination link-address"}, 711 { ND_OPT_PREFIX_INFORMATION, "prefix info"}, 712 { ND_OPT_REDIRECTED_HEADER, "redirected header"}, 713 { ND_OPT_MTU, "mtu"}, 714 { ND_OPT_RDNSS, "rdnss"}, 715 { ND_OPT_DNSSL, "dnssl"}, 716 { ND_OPT_ADVINTERVAL, "advertisement interval"}, 717 { ND_OPT_HOMEAGENT_INFO, "homeagent information"}, 718 { ND_OPT_ROUTE_INFO, "route info"}, 719 { 0, NULL } 720 }; 721 722 /* mldv2 report types */ 723 static const struct tok mldv2report2str[] = { 724 { 1, "is_in" }, 725 { 2, "is_ex" }, 726 { 3, "to_in" }, 727 { 4, "to_ex" }, 728 { 5, "allow" }, 729 { 6, "block" }, 730 { 0, NULL } 731 }; 732 733 static const char * 734 get_rtpref(u_int v) 735 { 736 static const char *rtpref_str[] = { 737 "medium", /* 00 */ 738 "high", /* 01 */ 739 "rsv", /* 10 */ 740 "low" /* 11 */ 741 }; 742 743 return rtpref_str[((v & ND_RA_FLAG_RTPREF_MASK) >> 3) & 0xff]; 744 } 745 746 static const char * 747 get_lifetime(uint32_t v) 748 { 749 static char buf[20]; 750 751 if (v == (uint32_t)~0UL) 752 return "infinity"; 753 else { 754 snprintf(buf, sizeof(buf), "%us", v); 755 return buf; 756 } 757 } 758 759 static void 760 print_lladdr(netdissect_options *ndo, const uint8_t *p, size_t l) 761 { 762 const uint8_t *ep, *q; 763 764 q = p; 765 ep = p + l; 766 while (l > 0 && q < ep) { 767 if (q > p) 768 ND_PRINT(":"); 769 ND_PRINT("%02x", GET_U_1(q)); 770 q++; 771 l--; 772 } 773 } 774 775 static uint16_t icmp6_cksum(netdissect_options *ndo, const struct ip6_hdr *ip6, 776 const struct icmp6_hdr *icp, u_int len) 777 { 778 return nextproto6_cksum(ndo, ip6, (const uint8_t *)(const void *)icp, len, len, 779 IPPROTO_ICMPV6); 780 } 781 782 static const struct tok rpl_mop_values[] = { 783 { RPL_DIO_NONSTORING, "nonstoring"}, 784 { RPL_DIO_STORING, "storing"}, 785 { RPL_DIO_NONSTORING_MULTICAST, "nonstoring-multicast"}, 786 { RPL_DIO_STORING_MULTICAST, "storing-multicast"}, 787 { 0, NULL}, 788 }; 789 790 static const struct tok rpl_subopt_values[] = { 791 { RPL_OPT_PAD1, "pad1"}, 792 { RPL_OPT_PADN, "padN"}, 793 { RPL_DIO_METRICS, "metrics"}, 794 { RPL_DIO_ROUTINGINFO, "routinginfo"}, 795 { RPL_DIO_CONFIG, "config"}, 796 { RPL_DAO_RPLTARGET, "rpltarget"}, 797 { RPL_DAO_TRANSITINFO, "transitinfo"}, 798 { RPL_DIO_DESTPREFIX, "destprefix"}, 799 { RPL_DAO_RPLTARGET_DESC, "rpltargetdesc"}, 800 { 0, NULL}, 801 }; 802 803 static void 804 rpl_printopts(netdissect_options *ndo, const uint8_t *opts, u_int length) 805 { 806 const struct rpl_genoption *opt; 807 uint8_t dio_type; 808 u_int optlen; 809 810 while (length != 0) { 811 opt = (const struct rpl_genoption *)opts; 812 dio_type = GET_U_1(opt->rpl_dio_type); 813 if (dio_type == RPL_OPT_PAD1) { 814 optlen = 1; 815 ND_PRINT(" opt:pad1"); 816 } else { 817 if (length < RPL_GENOPTION_LEN) 818 goto trunc; 819 optlen = GET_U_1(opt->rpl_dio_len)+RPL_GENOPTION_LEN; 820 ND_PRINT(" opt:%s len:%u ", 821 tok2str(rpl_subopt_values, "subopt:%u", dio_type), 822 optlen); 823 ND_TCHECK_LEN(opt, optlen); 824 if (length < optlen) 825 goto trunc; 826 if (ndo->ndo_vflag > 2) { 827 hex_print(ndo, 828 " ", 829 opts + RPL_GENOPTION_LEN, /* content of DIO option */ 830 optlen - RPL_GENOPTION_LEN); 831 } 832 } 833 opts += optlen; 834 length -= optlen; 835 } 836 return; 837 trunc: 838 nd_print_trunc(ndo); 839 } 840 841 static void 842 rpl_dio_print(netdissect_options *ndo, 843 const u_char *bp, u_int length) 844 { 845 const struct nd_rpl_dio *dio = (const struct nd_rpl_dio *)bp; 846 847 ND_ICHECK_ZU(length, <, sizeof(struct nd_rpl_dio)); 848 ND_PRINT(" [dagid:%s,seq:%u,instance:%u,rank:%u,%smop:%s,prf:%u]", 849 GET_IP6ADDR_STRING(dio->rpl_dagid), 850 GET_U_1(dio->rpl_dtsn), 851 GET_U_1(dio->rpl_instanceid), 852 GET_BE_U_2(dio->rpl_dagrank), 853 RPL_DIO_GROUNDED(GET_U_1(dio->rpl_mopprf)) ? "grounded,":"", 854 tok2str(rpl_mop_values, "mop%u", 855 RPL_DIO_MOP(GET_U_1(dio->rpl_mopprf))), 856 RPL_DIO_PRF(GET_U_1(dio->rpl_mopprf))); 857 858 if(ndo->ndo_vflag > 1) { 859 rpl_printopts(ndo, bp + sizeof(struct nd_rpl_dio), 860 length - sizeof(struct nd_rpl_dio)); 861 } 862 return; 863 invalid: 864 nd_print_invalid(ndo); 865 } 866 867 static void 868 rpl_dao_print(netdissect_options *ndo, 869 const u_char *bp, u_int length) 870 { 871 const struct nd_rpl_dao *dao = (const struct nd_rpl_dao *)bp; 872 const char *dagid_str = "<elided>"; 873 uint8_t rpl_flags; 874 875 ND_TCHECK_SIZE(dao); 876 if (length < ND_RPL_DAO_MIN_LEN) 877 goto tooshort; 878 879 bp += ND_RPL_DAO_MIN_LEN; 880 length -= ND_RPL_DAO_MIN_LEN; 881 rpl_flags = GET_U_1(dao->rpl_flags); 882 if(RPL_DAO_D(rpl_flags)) { 883 ND_TCHECK_LEN(dao->rpl_dagid, DAGID_LEN); 884 if (length < DAGID_LEN) 885 goto tooshort; 886 dagid_str = ip6addr_string (ndo, dao->rpl_dagid); 887 bp += DAGID_LEN; 888 length -= DAGID_LEN; 889 } 890 891 ND_PRINT(" [dagid:%s,seq:%u,instance:%u%s%s,flags:%02x]", 892 dagid_str, 893 GET_U_1(dao->rpl_daoseq), 894 GET_U_1(dao->rpl_instanceid), 895 RPL_DAO_K(rpl_flags) ? ",acK":"", 896 RPL_DAO_D(rpl_flags) ? ",Dagid":"", 897 rpl_flags); 898 899 if(ndo->ndo_vflag > 1) { 900 rpl_printopts(ndo, bp, length); 901 } 902 return; 903 904 trunc: 905 nd_print_trunc(ndo); 906 return; 907 908 tooshort: 909 ND_PRINT(" [|length too short]"); 910 } 911 912 static void 913 rpl_daoack_print(netdissect_options *ndo, 914 const u_char *bp, u_int length) 915 { 916 const struct nd_rpl_daoack *daoack = (const struct nd_rpl_daoack *)bp; 917 const char *dagid_str = "<elided>"; 918 919 ND_TCHECK_LEN(daoack, ND_RPL_DAOACK_MIN_LEN); 920 if (length < ND_RPL_DAOACK_MIN_LEN) 921 goto tooshort; 922 923 bp += ND_RPL_DAOACK_MIN_LEN; 924 length -= ND_RPL_DAOACK_MIN_LEN; 925 if(RPL_DAOACK_D(GET_U_1(daoack->rpl_flags))) { 926 ND_TCHECK_LEN(daoack->rpl_dagid, DAGID_LEN); 927 if (length < DAGID_LEN) 928 goto tooshort; 929 dagid_str = ip6addr_string (ndo, daoack->rpl_dagid); 930 bp += DAGID_LEN; 931 length -= DAGID_LEN; 932 } 933 934 ND_PRINT(" [dagid:%s,seq:%u,instance:%u,status:%u]", 935 dagid_str, 936 GET_U_1(daoack->rpl_daoseq), 937 GET_U_1(daoack->rpl_instanceid), 938 GET_U_1(daoack->rpl_status)); 939 940 /* no officially defined options for DAOACK, but print any we find */ 941 if(ndo->ndo_vflag > 1) { 942 rpl_printopts(ndo, bp, length); 943 } 944 return; 945 946 trunc: 947 nd_print_trunc(ndo); 948 return; 949 950 tooshort: 951 ND_PRINT(" [|dao-length too short]"); 952 } 953 954 UNALIGNED_OK 955 static void 956 rpl_print(netdissect_options *ndo, 957 uint8_t icmp6_code, 958 const u_char *bp, u_int length) 959 { 960 int secured = icmp6_code & 0x80; 961 int basecode= icmp6_code & 0x7f; 962 963 if(secured) { 964 ND_PRINT(", (SEC) [worktodo]"); 965 /* XXX 966 * the next header pointer needs to move forward to 967 * skip the secure part. 968 */ 969 return; 970 } else { 971 ND_PRINT(", (CLR)"); 972 } 973 974 switch(basecode) { 975 case ND_RPL_DAG_IS: 976 ND_PRINT("DODAG Information Solicitation"); 977 if(ndo->ndo_vflag) { 978 } 979 break; 980 case ND_RPL_DAG_IO: 981 ND_PRINT("DODAG Information Object"); 982 if(ndo->ndo_vflag) { 983 rpl_dio_print(ndo, bp, length); 984 } 985 break; 986 case ND_RPL_DAO: 987 ND_PRINT("Destination Advertisement Object"); 988 if(ndo->ndo_vflag) { 989 rpl_dao_print(ndo, bp, length); 990 } 991 break; 992 case ND_RPL_DAO_ACK: 993 ND_PRINT("Destination Advertisement Object Ack"); 994 if(ndo->ndo_vflag) { 995 rpl_daoack_print(ndo, bp, length); 996 } 997 break; 998 default: 999 ND_PRINT("RPL message, unknown code %u",icmp6_code); 1000 break; 1001 } 1002 return; 1003 1004 #if 0 1005 trunc: 1006 nd_print_trunc(ndo); 1007 return; 1008 #endif 1009 1010 } 1011 1012 void 1013 icmp6_print(netdissect_options *ndo, 1014 const u_char *bp, u_int length, const u_char *bp2, int fragmented) 1015 { 1016 const struct icmp6_hdr *dp; 1017 uint8_t icmp6_type, icmp6_code; 1018 const struct ip6_hdr *ip; 1019 const struct ip6_hdr *oip; 1020 const struct udphdr *ouh; 1021 uint16_t dport; 1022 const u_char *ep; 1023 u_int prot; 1024 1025 ndo->ndo_protocol = "icmp6"; 1026 dp = (const struct icmp6_hdr *)bp; 1027 ip = (const struct ip6_hdr *)bp2; 1028 oip = (const struct ip6_hdr *)(dp + 1); 1029 /* 'ep' points to the end of available data. */ 1030 ep = ndo->ndo_snapend; 1031 if (length == 0) { 1032 ND_PRINT("ICMP6, length 0"); 1033 nd_print_invalid(ndo); 1034 return; 1035 } 1036 1037 if (ndo->ndo_vflag && !fragmented) { 1038 uint16_t sum, udp_sum; 1039 1040 if (ND_TTEST_LEN(bp, length)) { 1041 udp_sum = GET_BE_U_2(dp->icmp6_cksum); 1042 sum = icmp6_cksum(ndo, ip, dp, length); 1043 if (sum != 0) 1044 ND_PRINT("[bad icmp6 cksum 0x%04x -> 0x%04x!] ", 1045 udp_sum, 1046 in_cksum_shouldbe(udp_sum, sum)); 1047 else 1048 ND_PRINT("[icmp6 sum ok] "); 1049 } 1050 } 1051 1052 icmp6_type = GET_U_1(dp->icmp6_type); 1053 ND_PRINT("ICMP6, %s", tok2str(icmp6_type_values,"unknown icmp6 type (%u)",icmp6_type)); 1054 1055 /* display cosmetics: print the packet length for printer that use the vflag now */ 1056 if (ndo->ndo_vflag && (icmp6_type == ND_ROUTER_SOLICIT || 1057 icmp6_type == ND_ROUTER_ADVERT || 1058 icmp6_type == ND_NEIGHBOR_ADVERT || 1059 icmp6_type == ND_NEIGHBOR_SOLICIT || 1060 icmp6_type == ND_REDIRECT || 1061 icmp6_type == ICMP6_HADISCOV_REPLY || 1062 icmp6_type == ICMP6_MOBILEPREFIX_ADVERT )) 1063 ND_PRINT(", length %u", length); 1064 1065 icmp6_code = GET_U_1(dp->icmp6_code); 1066 1067 switch (icmp6_type) { 1068 case ICMP6_DST_UNREACH: 1069 ND_PRINT(", %s", tok2str(icmp6_dst_unreach_code_values,"unknown unreach code (%u)",icmp6_code)); 1070 switch (icmp6_code) { 1071 1072 case ICMP6_DST_UNREACH_NOROUTE: /* fall through */ 1073 case ICMP6_DST_UNREACH_ADMIN: 1074 case ICMP6_DST_UNREACH_ADDR: 1075 ND_PRINT(" %s",GET_IP6ADDR_STRING(oip->ip6_dst)); 1076 break; 1077 case ICMP6_DST_UNREACH_BEYONDSCOPE: 1078 ND_PRINT(" %s, source address %s", 1079 GET_IP6ADDR_STRING(oip->ip6_dst), 1080 GET_IP6ADDR_STRING(oip->ip6_src)); 1081 break; 1082 case ICMP6_DST_UNREACH_NOPORT: 1083 if ((ouh = get_upperlayer(ndo, (const u_char *)oip, &prot)) 1084 == NULL) 1085 goto trunc; 1086 1087 dport = GET_BE_U_2(ouh->uh_dport); 1088 switch (prot) { 1089 case IPPROTO_TCP: 1090 ND_PRINT(", %s tcp port %s", 1091 GET_IP6ADDR_STRING(oip->ip6_dst), 1092 tcpport_string(ndo, dport)); 1093 break; 1094 case IPPROTO_UDP: 1095 ND_PRINT(", %s udp port %s", 1096 GET_IP6ADDR_STRING(oip->ip6_dst), 1097 udpport_string(ndo, dport)); 1098 break; 1099 default: 1100 ND_PRINT(", %s protocol %u port %u unreachable", 1101 GET_IP6ADDR_STRING(oip->ip6_dst), 1102 prot, dport); 1103 break; 1104 } 1105 break; 1106 default: 1107 if (ndo->ndo_vflag <= 1) { 1108 print_unknown_data(ndo, bp,"\n\t",length); 1109 return; 1110 } 1111 break; 1112 } 1113 break; 1114 case ICMP6_PACKET_TOO_BIG: 1115 ND_PRINT(", mtu %u", GET_BE_U_4(dp->icmp6_mtu)); 1116 break; 1117 case ICMP6_TIME_EXCEEDED: 1118 switch (icmp6_code) { 1119 case ICMP6_TIME_EXCEED_TRANSIT: 1120 ND_PRINT(" for %s", 1121 GET_IP6ADDR_STRING(oip->ip6_dst)); 1122 break; 1123 case ICMP6_TIME_EXCEED_REASSEMBLY: 1124 ND_PRINT(" (reassembly)"); 1125 break; 1126 default: 1127 ND_PRINT(", unknown code (%u)", icmp6_code); 1128 break; 1129 } 1130 break; 1131 case ICMP6_PARAM_PROB: 1132 ND_TCHECK_16(oip->ip6_dst); 1133 switch (icmp6_code) { 1134 case ICMP6_PARAMPROB_HEADER: 1135 ND_PRINT(", erroneous - octet %u", 1136 GET_BE_U_4(dp->icmp6_pptr)); 1137 break; 1138 case ICMP6_PARAMPROB_NEXTHEADER: 1139 ND_PRINT(", next header - octet %u", 1140 GET_BE_U_4(dp->icmp6_pptr)); 1141 break; 1142 case ICMP6_PARAMPROB_OPTION: 1143 ND_PRINT(", option - octet %u", 1144 GET_BE_U_4(dp->icmp6_pptr)); 1145 break; 1146 case ICMP6_PARAMPROB_FRAGHDRCHAIN: 1147 ND_PRINT(", incomplete header chain - octet %u", 1148 GET_BE_U_4(dp->icmp6_pptr)); 1149 break; 1150 default: 1151 ND_PRINT(", code-#%u", 1152 icmp6_code); 1153 break; 1154 } 1155 break; 1156 case ICMP6_ECHO_REQUEST: 1157 case ICMP6_ECHO_REPLY: 1158 ND_PRINT(", id %u, seq %u", GET_BE_U_2(dp->icmp6_id), 1159 GET_BE_U_2(dp->icmp6_seq)); 1160 break; 1161 case ICMP6_MEMBERSHIP_QUERY: 1162 if (length == MLD_MINLEN) { 1163 mld6_print(ndo, (const u_char *)dp); 1164 } else if (length >= MLDV2_MINLEN) { 1165 ND_PRINT(" v2"); 1166 mldv2_query_print(ndo, (const u_char *)dp, length); 1167 } else { 1168 ND_PRINT(" unknown-version (len %u) ", length); 1169 } 1170 break; 1171 case ICMP6_MEMBERSHIP_REPORT: 1172 mld6_print(ndo, (const u_char *)dp); 1173 break; 1174 case ICMP6_MEMBERSHIP_REDUCTION: 1175 mld6_print(ndo, (const u_char *)dp); 1176 break; 1177 case ND_ROUTER_SOLICIT: 1178 #define RTSOLLEN 8 1179 if (ndo->ndo_vflag) { 1180 if (icmp6_opt_print(ndo, (const u_char *)dp + RTSOLLEN, 1181 length - RTSOLLEN) == -1) 1182 goto trunc; 1183 } 1184 break; 1185 case ND_ROUTER_ADVERT: 1186 #define RTADVLEN 16 1187 if (ndo->ndo_vflag) { 1188 const struct nd_router_advert *p; 1189 1190 p = (const struct nd_router_advert *)dp; 1191 ND_PRINT("\n\thop limit %u, Flags [%s]" 1192 ", pref %s, router lifetime %us, reachable time %ums, retrans timer %ums", 1193 GET_U_1(p->nd_ra_curhoplimit), 1194 bittok2str(icmp6_opt_ra_flag_values,"none",GET_U_1(p->nd_ra_flags_reserved)), 1195 get_rtpref(GET_U_1(p->nd_ra_flags_reserved)), 1196 GET_BE_U_2(p->nd_ra_router_lifetime), 1197 GET_BE_U_4(p->nd_ra_reachable), 1198 GET_BE_U_4(p->nd_ra_retransmit)); 1199 1200 if (icmp6_opt_print(ndo, (const u_char *)dp + RTADVLEN, 1201 length - RTADVLEN) == -1) 1202 goto trunc; 1203 } 1204 break; 1205 case ND_NEIGHBOR_SOLICIT: 1206 { 1207 const struct nd_neighbor_solicit *p; 1208 p = (const struct nd_neighbor_solicit *)dp; 1209 ND_PRINT(", who has %s", GET_IP6ADDR_STRING(p->nd_ns_target)); 1210 if (ndo->ndo_vflag) { 1211 #define NDSOLLEN 24 1212 if (icmp6_opt_print(ndo, (const u_char *)dp + NDSOLLEN, 1213 length - NDSOLLEN) == -1) 1214 goto trunc; 1215 } 1216 } 1217 break; 1218 case ND_NEIGHBOR_ADVERT: 1219 { 1220 const struct nd_neighbor_advert *p; 1221 1222 p = (const struct nd_neighbor_advert *)dp; 1223 ND_PRINT(", tgt is %s", 1224 GET_IP6ADDR_STRING(p->nd_na_target)); 1225 if (ndo->ndo_vflag) { 1226 ND_PRINT(", Flags [%s]", 1227 bittok2str(icmp6_nd_na_flag_values, 1228 "none", 1229 GET_BE_U_4(p->nd_na_flags_reserved))); 1230 #define NDADVLEN 24 1231 if (icmp6_opt_print(ndo, (const u_char *)dp + NDADVLEN, 1232 length - NDADVLEN) == -1) 1233 goto trunc; 1234 #undef NDADVLEN 1235 } 1236 } 1237 break; 1238 case ND_REDIRECT: 1239 { 1240 const struct nd_redirect *p; 1241 1242 p = (const struct nd_redirect *)dp; 1243 ND_PRINT(", %s", GET_IP6ADDR_STRING(p->nd_rd_dst)); 1244 ND_PRINT(" to %s", GET_IP6ADDR_STRING(p->nd_rd_target)); 1245 #define REDIRECTLEN 40 1246 if (ndo->ndo_vflag) { 1247 if (icmp6_opt_print(ndo, (const u_char *)dp + REDIRECTLEN, 1248 length - REDIRECTLEN) == -1) 1249 goto trunc; 1250 #undef REDIRECTLEN 1251 } 1252 } 1253 break; 1254 case ICMP6_ROUTER_RENUMBERING: 1255 icmp6_rrenum_print(ndo, bp, ep); 1256 break; 1257 case ICMP6_NI_QUERY: 1258 case ICMP6_NI_REPLY: 1259 icmp6_nodeinfo_print(ndo, length, bp, ep); 1260 break; 1261 case IND_SOLICIT: 1262 case IND_ADVERT: 1263 break; 1264 case ICMP6_V2_MEMBERSHIP_REPORT: 1265 mldv2_report_print(ndo, (const u_char *) dp, length); 1266 break; 1267 case ICMP6_MOBILEPREFIX_SOLICIT: /* fall through */ 1268 case ICMP6_HADISCOV_REQUEST: 1269 ND_PRINT(", id 0x%04x", GET_BE_U_2(dp->icmp6_data16[0])); 1270 break; 1271 case ICMP6_HADISCOV_REPLY: 1272 if (ndo->ndo_vflag) { 1273 const u_char *cp; 1274 const u_char *p; 1275 1276 ND_PRINT(", id 0x%04x", 1277 GET_BE_U_2(dp->icmp6_data16[0])); 1278 cp = (const u_char *)dp + 1279 ND_MIN(length, ND_BYTES_AVAILABLE_AFTER(dp)); 1280 p = (const u_char *)(dp + 1); 1281 while (p < cp) { 1282 ND_PRINT(", %s", GET_IP6ADDR_STRING(p)); 1283 p += 16; 1284 } 1285 } 1286 break; 1287 case ICMP6_MOBILEPREFIX_ADVERT: 1288 if (ndo->ndo_vflag) { 1289 uint16_t flags; 1290 1291 ND_PRINT(", id 0x%04x", 1292 GET_BE_U_2(dp->icmp6_data16[0])); 1293 flags = GET_BE_U_2(dp->icmp6_data16[1]); 1294 if (flags & 0xc000) 1295 ND_PRINT(" "); 1296 if (flags & 0x8000) 1297 ND_PRINT("M"); 1298 if (flags & 0x4000) 1299 ND_PRINT("O"); 1300 #define MPADVLEN 8 1301 if (icmp6_opt_print(ndo, (const u_char *)dp + MPADVLEN, 1302 length - MPADVLEN) == -1) 1303 goto trunc; 1304 } 1305 break; 1306 case ND_RPL_MESSAGE: 1307 /* plus 4, because struct icmp6_hdr contains 4 bytes of icmp payload */ 1308 rpl_print(ndo, icmp6_code, dp->icmp6_data, length-sizeof(struct icmp6_hdr)+4); 1309 break; 1310 default: 1311 ND_PRINT(", length %u", length); 1312 if (ndo->ndo_vflag <= 1) 1313 print_unknown_data(ndo, bp,"\n\t", length); 1314 return; 1315 } 1316 if (!ndo->ndo_vflag) 1317 ND_PRINT(", length %u", length); 1318 return; 1319 trunc: 1320 nd_print_trunc(ndo); 1321 } 1322 1323 static const struct udphdr * 1324 get_upperlayer(netdissect_options *ndo, const u_char *bp, u_int *prot) 1325 { 1326 const u_char *ep; 1327 const struct ip6_hdr *ip6 = (const struct ip6_hdr *)bp; 1328 const struct udphdr *uh; 1329 const struct ip6_hbh *hbh; 1330 const struct ip6_frag *fragh; 1331 const struct ah *ah; 1332 u_int nh; 1333 int hlen; 1334 1335 /* 'ep' points to the end of available data. */ 1336 ep = ndo->ndo_snapend; 1337 1338 if (!ND_TTEST_1(ip6->ip6_nxt)) 1339 return NULL; 1340 1341 nh = GET_U_1(ip6->ip6_nxt); 1342 hlen = sizeof(struct ip6_hdr); 1343 1344 while (bp < ep) { 1345 bp += hlen; 1346 1347 switch(nh) { 1348 case IPPROTO_UDP: 1349 case IPPROTO_TCP: 1350 uh = (const struct udphdr *)bp; 1351 if (ND_TTEST_2(uh->uh_dport)) { 1352 *prot = nh; 1353 return(uh); 1354 } else 1355 return(NULL); 1356 /* NOTREACHED */ 1357 1358 case IPPROTO_HOPOPTS: 1359 case IPPROTO_DSTOPTS: 1360 case IPPROTO_ROUTING: 1361 hbh = (const struct ip6_hbh *)bp; 1362 if (!ND_TTEST_1(hbh->ip6h_len)) 1363 return(NULL); 1364 nh = GET_U_1(hbh->ip6h_nxt); 1365 hlen = (GET_U_1(hbh->ip6h_len) + 1) << 3; 1366 break; 1367 1368 case IPPROTO_FRAGMENT: /* this should be odd, but try anyway */ 1369 fragh = (const struct ip6_frag *)bp; 1370 if (!ND_TTEST_2(fragh->ip6f_offlg)) 1371 return(NULL); 1372 /* fragments with non-zero offset are meaningless */ 1373 if ((GET_BE_U_2(fragh->ip6f_offlg) & IP6F_OFF_MASK) != 0) 1374 return(NULL); 1375 nh = GET_U_1(fragh->ip6f_nxt); 1376 hlen = sizeof(struct ip6_frag); 1377 break; 1378 1379 case IPPROTO_AH: 1380 ah = (const struct ah *)bp; 1381 if (!ND_TTEST_1(ah->ah_len)) 1382 return(NULL); 1383 nh = GET_U_1(ah->ah_nxt); 1384 hlen = (GET_U_1(ah->ah_len) + 2) << 2; 1385 break; 1386 1387 default: /* unknown or undecodable header */ 1388 *prot = nh; /* meaningless, but set here anyway */ 1389 return(NULL); 1390 } 1391 } 1392 1393 return(NULL); /* should be notreached, though */ 1394 } 1395 1396 static int 1397 icmp6_opt_print(netdissect_options *ndo, const u_char *bp, int resid) 1398 { 1399 const struct nd_opt_hdr *op; 1400 uint8_t opt_type; 1401 u_int opt_len; 1402 const struct nd_opt_prefix_info *opp; 1403 const struct nd_opt_mtu *opm; 1404 const struct nd_opt_rdnss *oprd; 1405 const struct nd_opt_dnssl *opds; 1406 const struct nd_opt_advinterval *opa; 1407 const struct nd_opt_homeagent_info *oph; 1408 const struct nd_opt_route_info *opri; 1409 const u_char *cp, *ep, *domp; 1410 nd_ipv6 in6; 1411 size_t l; 1412 u_int i; 1413 1414 cp = bp; 1415 /* 'ep' points to the end of available data. */ 1416 ep = ndo->ndo_snapend; 1417 1418 while (cp < ep) { 1419 op = (const struct nd_opt_hdr *)cp; 1420 1421 ND_TCHECK_1(op->nd_opt_len); 1422 if (resid <= 0) 1423 return 0; 1424 opt_type = GET_U_1(op->nd_opt_type); 1425 opt_len = GET_U_1(op->nd_opt_len); 1426 if (opt_len == 0) 1427 goto trunc; 1428 if (cp + (opt_len << 3) > ep) 1429 goto trunc; 1430 1431 ND_PRINT("\n\t %s option (%u), length %u (%u): ", 1432 tok2str(icmp6_opt_values, "unknown", opt_type), 1433 opt_type, 1434 opt_len << 3, 1435 opt_len); 1436 1437 switch (opt_type) { 1438 case ND_OPT_SOURCE_LINKADDR: 1439 l = (opt_len << 3) - 2; 1440 print_lladdr(ndo, cp + 2, l); 1441 break; 1442 case ND_OPT_TARGET_LINKADDR: 1443 l = (opt_len << 3) - 2; 1444 print_lladdr(ndo, cp + 2, l); 1445 break; 1446 case ND_OPT_PREFIX_INFORMATION: 1447 opp = (const struct nd_opt_prefix_info *)op; 1448 ND_PRINT("%s/%u%s, Flags [%s], valid time %s", 1449 GET_IP6ADDR_STRING(opp->nd_opt_pi_prefix), 1450 GET_U_1(opp->nd_opt_pi_prefix_len), 1451 (opt_len != 4) ? "badlen" : "", 1452 bittok2str(icmp6_opt_pi_flag_values, "none", GET_U_1(opp->nd_opt_pi_flags_reserved)), 1453 get_lifetime(GET_BE_U_4(opp->nd_opt_pi_valid_time))); 1454 ND_PRINT(", pref. time %s", 1455 get_lifetime(GET_BE_U_4(opp->nd_opt_pi_preferred_time))); 1456 break; 1457 case ND_OPT_REDIRECTED_HEADER: 1458 print_unknown_data(ndo, bp,"\n\t ",opt_len<<3); 1459 /* xxx */ 1460 break; 1461 case ND_OPT_MTU: 1462 opm = (const struct nd_opt_mtu *)op; 1463 ND_PRINT(" %u%s", 1464 GET_BE_U_4(opm->nd_opt_mtu_mtu), 1465 (opt_len != 1) ? "bad option length" : "" ); 1466 break; 1467 case ND_OPT_RDNSS: 1468 oprd = (const struct nd_opt_rdnss *)op; 1469 l = (opt_len - 1) / 2; 1470 ND_PRINT(" lifetime %us,", 1471 GET_BE_U_4(oprd->nd_opt_rdnss_lifetime)); 1472 for (i = 0; i < l; i++) { 1473 ND_PRINT(" addr: %s", 1474 GET_IP6ADDR_STRING(oprd->nd_opt_rdnss_addr[i])); 1475 } 1476 break; 1477 case ND_OPT_DNSSL: 1478 opds = (const struct nd_opt_dnssl *)op; 1479 ND_PRINT(" lifetime %us, domain(s):", 1480 GET_BE_U_4(opds->nd_opt_dnssl_lifetime)); 1481 domp = cp + 8; /* domain names, variable-sized, RFC1035-encoded */ 1482 while (domp < cp + (opt_len << 3) && GET_U_1(domp) != '\0') { 1483 ND_PRINT(" "); 1484 if ((domp = fqdn_print(ndo, domp, bp)) == NULL) 1485 goto trunc; 1486 } 1487 break; 1488 case ND_OPT_ADVINTERVAL: 1489 opa = (const struct nd_opt_advinterval *)op; 1490 ND_PRINT(" %ums", 1491 GET_BE_U_4(opa->nd_opt_adv_interval)); 1492 break; 1493 case ND_OPT_HOMEAGENT_INFO: 1494 oph = (const struct nd_opt_homeagent_info *)op; 1495 ND_PRINT(" preference %u, lifetime %u", 1496 GET_BE_U_2(oph->nd_opt_hai_preference), 1497 GET_BE_U_2(oph->nd_opt_hai_lifetime)); 1498 break; 1499 case ND_OPT_ROUTE_INFO: 1500 opri = (const struct nd_opt_route_info *)op; 1501 ND_TCHECK_4(opri->nd_opt_rti_lifetime); 1502 memset(&in6, 0, sizeof(in6)); 1503 switch (opt_len) { 1504 case 1: 1505 break; 1506 case 2: 1507 GET_CPY_BYTES(&in6, opri + 1, 8); 1508 break; 1509 case 3: 1510 GET_CPY_BYTES(&in6, opri + 1, 16); 1511 break; 1512 default: 1513 goto trunc; 1514 } 1515 ND_PRINT(" %s/%u", ip6addr_string(ndo, (const u_char *)&in6), /* local buffer, not packet data; don't use GET_IP6ADDR_STRING() */ 1516 GET_U_1(opri->nd_opt_rti_prefixlen)); 1517 ND_PRINT(", pref=%s", 1518 get_rtpref(GET_U_1(opri->nd_opt_rti_flags))); 1519 ND_PRINT(", lifetime=%s", 1520 get_lifetime(GET_BE_U_4(opri->nd_opt_rti_lifetime))); 1521 break; 1522 default: 1523 if (ndo->ndo_vflag <= 1) { 1524 print_unknown_data(ndo,cp+2,"\n\t ", (opt_len << 3) - 2); /* skip option header */ 1525 return 0; 1526 } 1527 break; 1528 } 1529 /* do we want to see an additional hexdump ? */ 1530 if (ndo->ndo_vflag> 1) 1531 print_unknown_data(ndo, cp+2,"\n\t ", (opt_len << 3) - 2); /* skip option header */ 1532 1533 cp += opt_len << 3; 1534 resid -= opt_len << 3; 1535 } 1536 return 0; 1537 1538 trunc: 1539 return -1; 1540 } 1541 1542 UNALIGNED_OK 1543 static void 1544 mld6_print(netdissect_options *ndo, const u_char *bp) 1545 { 1546 const struct mld6_hdr *mp = (const struct mld6_hdr *)bp; 1547 const u_char *ep; 1548 1549 /* 'ep' points to the end of available data. */ 1550 ep = ndo->ndo_snapend; 1551 1552 if ((const u_char *)mp + sizeof(*mp) > ep) 1553 return; 1554 1555 ND_PRINT("max resp delay: %u ", GET_BE_U_2(mp->mld6_maxdelay)); 1556 ND_PRINT("addr: %s", GET_IP6ADDR_STRING(mp->mld6_addr)); 1557 } 1558 1559 UNALIGNED_OK 1560 static void 1561 mldv2_report_print(netdissect_options *ndo, const u_char *bp, u_int len) 1562 { 1563 const struct icmp6_hdr *icp = (const struct icmp6_hdr *) bp; 1564 u_int group, nsrcs, ngroups; 1565 u_int i, j; 1566 1567 /* Minimum len is 8 */ 1568 if (len < 8) { 1569 ND_PRINT(" [invalid len %u]", len); 1570 return; 1571 } 1572 1573 ngroups = GET_BE_U_2(icp->icmp6_data16[1]); 1574 ND_PRINT(", %u group record(s)", ngroups); 1575 if (ndo->ndo_vflag > 0) { 1576 /* Print the group records */ 1577 group = 8; 1578 for (i = 0; i < ngroups; i++) { 1579 /* type(1) + auxlen(1) + numsrc(2) + grp(16) */ 1580 if (len < group + 20) { 1581 ND_PRINT(" [invalid number of groups]"); 1582 return; 1583 } 1584 ND_PRINT(" [gaddr %s", GET_IP6ADDR_STRING(bp + group + 4)); 1585 ND_PRINT(" %s", tok2str(mldv2report2str, " [v2-report-#%u]", 1586 GET_U_1(bp + group))); 1587 nsrcs = GET_BE_U_2(bp + group + 2); 1588 /* Check the number of sources and print them */ 1589 if (len < group + 20 + (nsrcs * sizeof(nd_ipv6))) { 1590 ND_PRINT(" [invalid number of sources %u]", nsrcs); 1591 return; 1592 } 1593 if (ndo->ndo_vflag == 1) 1594 ND_PRINT(", %u source(s)", nsrcs); 1595 else { 1596 /* Print the sources */ 1597 ND_PRINT(" {"); 1598 for (j = 0; j < nsrcs; j++) { 1599 ND_PRINT(" %s", GET_IP6ADDR_STRING(bp + group + 20 + (j * sizeof(nd_ipv6)))); 1600 } 1601 ND_PRINT(" }"); 1602 } 1603 /* Next group record */ 1604 group += 20 + nsrcs * sizeof(nd_ipv6); 1605 ND_PRINT("]"); 1606 } 1607 } 1608 } 1609 1610 UNALIGNED_OK 1611 static void 1612 mldv2_query_print(netdissect_options *ndo, const u_char *bp, u_int len) 1613 { 1614 const struct icmp6_hdr *icp = (const struct icmp6_hdr *) bp; 1615 u_int mrc; 1616 u_int mrt, qqi; 1617 u_int nsrcs; 1618 u_int i; 1619 1620 /* Minimum len is 28 */ 1621 if (len < 28) { 1622 ND_PRINT(" [invalid len %u]", len); 1623 return; 1624 } 1625 mrc = GET_BE_U_2(icp->icmp6_data16[0]); 1626 if (mrc < 32768) { 1627 mrt = mrc; 1628 } else { 1629 mrt = ((mrc & 0x0fff) | 0x1000) << (((mrc & 0x7000) >> 12) + 3); 1630 } 1631 if (ndo->ndo_vflag) { 1632 ND_PRINT(" [max resp delay=%u]", mrt); 1633 } 1634 ND_PRINT(" [gaddr %s", GET_IP6ADDR_STRING(bp + 8)); 1635 1636 if (ndo->ndo_vflag) { 1637 if (GET_U_1(bp + 24) & 0x08) { 1638 ND_PRINT(" sflag"); 1639 } 1640 if (GET_U_1(bp + 24) & 0x07) { 1641 ND_PRINT(" robustness=%u", GET_U_1(bp + 24) & 0x07); 1642 } 1643 if (GET_U_1(bp + 25) < 128) { 1644 qqi = GET_U_1(bp + 25); 1645 } else { 1646 qqi = ((GET_U_1(bp + 25) & 0x0f) | 0x10) << 1647 (((GET_U_1(bp + 25) & 0x70) >> 4) + 3); 1648 } 1649 ND_PRINT(" qqi=%u", qqi); 1650 } 1651 1652 nsrcs = GET_BE_U_2(bp + 26); 1653 if (nsrcs > 0) { 1654 if (len < 28 + nsrcs * sizeof(nd_ipv6)) 1655 ND_PRINT(" [invalid number of sources]"); 1656 else if (ndo->ndo_vflag > 1) { 1657 ND_PRINT(" {"); 1658 for (i = 0; i < nsrcs; i++) { 1659 ND_PRINT(" %s", GET_IP6ADDR_STRING(bp + 28 + (i * sizeof(nd_ipv6)))); 1660 } 1661 ND_PRINT(" }"); 1662 } else 1663 ND_PRINT(", %u source(s)", nsrcs); 1664 } 1665 ND_PRINT("]"); 1666 } 1667 1668 static void 1669 dnsname_print(netdissect_options *ndo, const u_char *cp, const u_char *ep) 1670 { 1671 int i; 1672 1673 /* DNS name decoding - no decompression */ 1674 ND_PRINT(", \""); 1675 while (cp < ep) { 1676 i = GET_U_1(cp); 1677 cp++; 1678 if (i) { 1679 if (i > ep - cp) { 1680 ND_PRINT("???"); 1681 break; 1682 } 1683 while (i-- && cp < ep) { 1684 fn_print_char(ndo, GET_U_1(cp)); 1685 cp++; 1686 } 1687 if (cp + 1 < ep && GET_U_1(cp)) 1688 ND_PRINT("."); 1689 } else { 1690 if (cp == ep) { 1691 /* FQDN */ 1692 ND_PRINT("."); 1693 } else if (cp + 1 == ep && GET_U_1(cp) == '\0') { 1694 /* truncated */ 1695 } else { 1696 /* invalid */ 1697 ND_PRINT("???"); 1698 } 1699 break; 1700 } 1701 } 1702 ND_PRINT("\""); 1703 } 1704 1705 static void 1706 icmp6_nodeinfo_print(netdissect_options *ndo, u_int icmp6len, const u_char *bp, const u_char *ep) 1707 { 1708 const struct icmp6_nodeinfo *ni6; 1709 const struct icmp6_hdr *dp; 1710 const u_char *cp; 1711 size_t siz, i; 1712 int needcomma; 1713 1714 if (ep < bp) 1715 return; 1716 dp = (const struct icmp6_hdr *)bp; 1717 ni6 = (const struct icmp6_nodeinfo *)bp; 1718 siz = ep - bp; 1719 1720 switch (GET_U_1(ni6->ni_type)) { 1721 case ICMP6_NI_QUERY: 1722 if (siz == sizeof(*dp) + 4) { 1723 /* KAME who-are-you */ 1724 ND_PRINT(" who-are-you request"); 1725 break; 1726 } 1727 ND_PRINT(" node information query"); 1728 1729 ND_TCHECK_LEN(dp, sizeof(*ni6)); 1730 ni6 = (const struct icmp6_nodeinfo *)dp; 1731 ND_PRINT(" ("); /*)*/ 1732 switch (GET_BE_U_2(ni6->ni_qtype)) { 1733 case NI_QTYPE_NOOP: 1734 ND_PRINT("noop"); 1735 break; 1736 case NI_QTYPE_SUPTYPES: 1737 ND_PRINT("supported qtypes"); 1738 i = GET_BE_U_2(ni6->ni_flags); 1739 if (i) 1740 ND_PRINT(" [%s]", (i & 0x01) ? "C" : ""); 1741 break; 1742 case NI_QTYPE_FQDN: 1743 ND_PRINT("DNS name"); 1744 break; 1745 case NI_QTYPE_NODEADDR: 1746 ND_PRINT("node addresses"); 1747 i = GET_BE_U_2(ni6->ni_flags); 1748 if (!i) 1749 break; 1750 /* NI_NODEADDR_FLAG_TRUNCATE undefined for query */ 1751 ND_PRINT(" [%s%s%s%s%s%s]", 1752 (i & NI_NODEADDR_FLAG_ANYCAST) ? "a" : "", 1753 (i & NI_NODEADDR_FLAG_GLOBAL) ? "G" : "", 1754 (i & NI_NODEADDR_FLAG_SITELOCAL) ? "S" : "", 1755 (i & NI_NODEADDR_FLAG_LINKLOCAL) ? "L" : "", 1756 (i & NI_NODEADDR_FLAG_COMPAT) ? "C" : "", 1757 (i & NI_NODEADDR_FLAG_ALL) ? "A" : ""); 1758 break; 1759 default: 1760 ND_PRINT("unknown"); 1761 break; 1762 } 1763 1764 if (GET_BE_U_2(ni6->ni_qtype) == NI_QTYPE_NOOP || 1765 GET_BE_U_2(ni6->ni_qtype) == NI_QTYPE_SUPTYPES) { 1766 if (siz != sizeof(*ni6)) 1767 if (ndo->ndo_vflag) 1768 ND_PRINT(", invalid len"); 1769 /*(*/ 1770 ND_PRINT(")"); 1771 break; 1772 } 1773 1774 /* XXX backward compat, icmp-name-lookup-03 */ 1775 if (siz == sizeof(*ni6)) { 1776 ND_PRINT(", 03 draft"); 1777 /*(*/ 1778 ND_PRINT(")"); 1779 break; 1780 } 1781 1782 cp = (const u_char *)(ni6 + 1); 1783 switch (GET_U_1(ni6->ni_code)) { 1784 case ICMP6_NI_SUBJ_IPV6: 1785 if (!ND_TTEST_LEN(dp, sizeof(*ni6) + sizeof(nd_ipv6))) 1786 break; 1787 if (siz != sizeof(*ni6) + sizeof(nd_ipv6)) { 1788 if (ndo->ndo_vflag) 1789 ND_PRINT(", invalid subject len"); 1790 break; 1791 } 1792 ND_PRINT(", subject=%s", 1793 GET_IP6ADDR_STRING(cp)); 1794 break; 1795 case ICMP6_NI_SUBJ_FQDN: 1796 ND_PRINT(", subject=DNS name"); 1797 if (GET_U_1(cp) == ep - cp - 1) { 1798 /* icmp-name-lookup-03, pascal string */ 1799 if (ndo->ndo_vflag) 1800 ND_PRINT(", 03 draft"); 1801 cp++; 1802 ND_PRINT(", \""); 1803 while (cp < ep) { 1804 fn_print_char(ndo, GET_U_1(cp)); 1805 cp++; 1806 } 1807 ND_PRINT("\""); 1808 } else 1809 dnsname_print(ndo, cp, ep); 1810 break; 1811 case ICMP6_NI_SUBJ_IPV4: 1812 if (!ND_TTEST_LEN(dp, sizeof(*ni6) + sizeof(nd_ipv4))) 1813 break; 1814 if (siz != sizeof(*ni6) + sizeof(nd_ipv4)) { 1815 if (ndo->ndo_vflag) 1816 ND_PRINT(", invalid subject len"); 1817 break; 1818 } 1819 ND_PRINT(", subject=%s", 1820 GET_IPADDR_STRING(cp)); 1821 break; 1822 default: 1823 ND_PRINT(", unknown subject"); 1824 break; 1825 } 1826 1827 /*(*/ 1828 ND_PRINT(")"); 1829 break; 1830 1831 case ICMP6_NI_REPLY: 1832 if (icmp6len > siz) 1833 goto trunc; 1834 1835 needcomma = 0; 1836 1837 ND_TCHECK_LEN(dp, sizeof(*ni6)); 1838 ni6 = (const struct icmp6_nodeinfo *)dp; 1839 ND_PRINT(" node information reply"); 1840 ND_PRINT(" ("); /*)*/ 1841 switch (GET_U_1(ni6->ni_code)) { 1842 case ICMP6_NI_SUCCESS: 1843 if (ndo->ndo_vflag) { 1844 ND_PRINT("success"); 1845 needcomma++; 1846 } 1847 break; 1848 case ICMP6_NI_REFUSED: 1849 ND_PRINT("refused"); 1850 needcomma++; 1851 if (siz != sizeof(*ni6)) 1852 if (ndo->ndo_vflag) 1853 ND_PRINT(", invalid length"); 1854 break; 1855 case ICMP6_NI_UNKNOWN: 1856 ND_PRINT("unknown"); 1857 needcomma++; 1858 if (siz != sizeof(*ni6)) 1859 if (ndo->ndo_vflag) 1860 ND_PRINT(", invalid length"); 1861 break; 1862 } 1863 1864 if (GET_U_1(ni6->ni_code) != ICMP6_NI_SUCCESS) { 1865 /*(*/ 1866 ND_PRINT(")"); 1867 break; 1868 } 1869 1870 switch (GET_BE_U_2(ni6->ni_qtype)) { 1871 case NI_QTYPE_NOOP: 1872 if (needcomma) 1873 ND_PRINT(", "); 1874 ND_PRINT("noop"); 1875 if (siz != sizeof(*ni6)) 1876 if (ndo->ndo_vflag) 1877 ND_PRINT(", invalid length"); 1878 break; 1879 case NI_QTYPE_SUPTYPES: 1880 if (needcomma) 1881 ND_PRINT(", "); 1882 ND_PRINT("supported qtypes"); 1883 i = GET_BE_U_2(ni6->ni_flags); 1884 if (i) 1885 ND_PRINT(" [%s]", (i & 0x01) ? "C" : ""); 1886 break; 1887 case NI_QTYPE_FQDN: 1888 if (needcomma) 1889 ND_PRINT(", "); 1890 ND_PRINT("DNS name"); 1891 cp = (const u_char *)(ni6 + 1) + 4; 1892 if (GET_U_1(cp) == ep - cp - 1) { 1893 /* icmp-name-lookup-03, pascal string */ 1894 if (ndo->ndo_vflag) 1895 ND_PRINT(", 03 draft"); 1896 cp++; 1897 ND_PRINT(", \""); 1898 while (cp < ep) { 1899 fn_print_char(ndo, GET_U_1(cp)); 1900 cp++; 1901 } 1902 ND_PRINT("\""); 1903 } else 1904 dnsname_print(ndo, cp, ep); 1905 if ((GET_BE_U_2(ni6->ni_flags) & 0x01) != 0) 1906 ND_PRINT(" [TTL=%u]", GET_BE_U_4(ni6 + 1)); 1907 break; 1908 case NI_QTYPE_NODEADDR: 1909 if (needcomma) 1910 ND_PRINT(", "); 1911 ND_PRINT("node addresses"); 1912 i = sizeof(*ni6); 1913 while (i < siz) { 1914 if (i + sizeof(uint32_t) + sizeof(nd_ipv6) > siz) 1915 break; 1916 ND_PRINT(" %s(%u)", 1917 GET_IP6ADDR_STRING(bp + i + sizeof(uint32_t)), 1918 GET_BE_U_4(bp + i)); 1919 i += sizeof(uint32_t) + sizeof(nd_ipv6); 1920 } 1921 i = GET_BE_U_2(ni6->ni_flags); 1922 if (!i) 1923 break; 1924 ND_PRINT(" [%s%s%s%s%s%s%s]", 1925 (i & NI_NODEADDR_FLAG_ANYCAST) ? "a" : "", 1926 (i & NI_NODEADDR_FLAG_GLOBAL) ? "G" : "", 1927 (i & NI_NODEADDR_FLAG_SITELOCAL) ? "S" : "", 1928 (i & NI_NODEADDR_FLAG_LINKLOCAL) ? "L" : "", 1929 (i & NI_NODEADDR_FLAG_COMPAT) ? "C" : "", 1930 (i & NI_NODEADDR_FLAG_ALL) ? "A" : "", 1931 (i & NI_NODEADDR_FLAG_TRUNCATE) ? "T" : ""); 1932 break; 1933 default: 1934 if (needcomma) 1935 ND_PRINT(", "); 1936 ND_PRINT("unknown"); 1937 break; 1938 } 1939 1940 /*(*/ 1941 ND_PRINT(")"); 1942 break; 1943 } 1944 return; 1945 1946 trunc: 1947 nd_print_trunc(ndo); 1948 } 1949 1950 static void 1951 icmp6_rrenum_print(netdissect_options *ndo, const u_char *bp, const u_char *ep) 1952 { 1953 const struct icmp6_router_renum *rr6; 1954 const char *cp; 1955 const struct rr_pco_match *match; 1956 const struct rr_pco_use *use; 1957 char hbuf[NI_MAXHOST]; 1958 int n; 1959 1960 if (ep < bp) 1961 return; 1962 rr6 = (const struct icmp6_router_renum *)bp; 1963 cp = (const char *)(rr6 + 1); 1964 1965 ND_TCHECK_4(rr6->rr_reserved); 1966 switch (GET_U_1(rr6->rr_code)) { 1967 case ICMP6_ROUTER_RENUMBERING_COMMAND: 1968 ND_PRINT(", command"); 1969 break; 1970 case ICMP6_ROUTER_RENUMBERING_RESULT: 1971 ND_PRINT(", result"); 1972 break; 1973 case ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET: 1974 ND_PRINT(", sequence number reset"); 1975 break; 1976 default: 1977 ND_PRINT(", code-#%u", GET_U_1(rr6->rr_code)); 1978 break; 1979 } 1980 1981 ND_PRINT(", seq=%u", GET_BE_U_4(rr6->rr_seqnum)); 1982 1983 if (ndo->ndo_vflag) { 1984 uint8_t rr_flags = GET_U_1(rr6->rr_flags); 1985 #define F(x, y) (rr_flags & (x) ? (y) : "") 1986 ND_PRINT("["); /*]*/ 1987 if (rr_flags) { 1988 ND_PRINT("%s%s%s%s%s,", F(ICMP6_RR_FLAGS_TEST, "T"), 1989 F(ICMP6_RR_FLAGS_REQRESULT, "R"), 1990 F(ICMP6_RR_FLAGS_FORCEAPPLY, "A"), 1991 F(ICMP6_RR_FLAGS_SPECSITE, "S"), 1992 F(ICMP6_RR_FLAGS_PREVDONE, "P")); 1993 } 1994 ND_PRINT("seg=%u,", GET_U_1(rr6->rr_segnum)); 1995 ND_PRINT("maxdelay=%u", GET_BE_U_2(rr6->rr_maxdelay)); 1996 if (GET_BE_U_4(rr6->rr_reserved)) 1997 ND_PRINT("rsvd=0x%x", GET_BE_U_4(rr6->rr_reserved)); 1998 /*[*/ 1999 ND_PRINT("]"); 2000 #undef F 2001 } 2002 2003 if (GET_U_1(rr6->rr_code) == ICMP6_ROUTER_RENUMBERING_COMMAND) { 2004 match = (const struct rr_pco_match *)cp; 2005 cp = (const char *)(match + 1); 2006 2007 ND_TCHECK_16(match->rpm_prefix); 2008 2009 if (ndo->ndo_vflag > 1) 2010 ND_PRINT("\n\t"); 2011 else 2012 ND_PRINT(" "); 2013 ND_PRINT("match("); /*)*/ 2014 switch (GET_U_1(match->rpm_code)) { 2015 case RPM_PCO_ADD: ND_PRINT("add"); break; 2016 case RPM_PCO_CHANGE: ND_PRINT("change"); break; 2017 case RPM_PCO_SETGLOBAL: ND_PRINT("setglobal"); break; 2018 default: ND_PRINT("#%u", 2019 GET_U_1(match->rpm_code)); break; 2020 } 2021 2022 if (ndo->ndo_vflag) { 2023 ND_PRINT(",ord=%u", GET_U_1(match->rpm_ordinal)); 2024 ND_PRINT(",min=%u", GET_U_1(match->rpm_minlen)); 2025 ND_PRINT(",max=%u", GET_U_1(match->rpm_maxlen)); 2026 } 2027 if (addrtostr6(match->rpm_prefix, hbuf, sizeof(hbuf))) 2028 ND_PRINT(",%s/%u", hbuf, GET_U_1(match->rpm_matchlen)); 2029 else 2030 ND_PRINT(",?/%u", GET_U_1(match->rpm_matchlen)); 2031 /*(*/ 2032 ND_PRINT(")"); 2033 2034 n = GET_U_1(match->rpm_len) - 3; 2035 if (n % 4) 2036 goto trunc; 2037 n /= 4; 2038 while (n-- > 0) { 2039 use = (const struct rr_pco_use *)cp; 2040 cp = (const char *)(use + 1); 2041 2042 ND_TCHECK_16(use->rpu_prefix); 2043 2044 if (ndo->ndo_vflag > 1) 2045 ND_PRINT("\n\t"); 2046 else 2047 ND_PRINT(" "); 2048 ND_PRINT("use("); /*)*/ 2049 if (GET_U_1(use->rpu_flags)) { 2050 #define F(x, y) (GET_U_1(use->rpu_flags) & (x) ? (y) : "") 2051 ND_PRINT("%s%s,", 2052 F(ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME, "V"), 2053 F(ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME, "P")); 2054 #undef F 2055 } 2056 if (ndo->ndo_vflag) { 2057 ND_PRINT("mask=0x%x,", 2058 GET_U_1(use->rpu_ramask)); 2059 ND_PRINT("raflags=0x%x,", 2060 GET_U_1(use->rpu_raflags)); 2061 if (GET_BE_U_4(use->rpu_vltime) == 0xffffffff) 2062 ND_PRINT("vltime=infty,"); 2063 else 2064 ND_PRINT("vltime=%u,", 2065 GET_BE_U_4(use->rpu_vltime)); 2066 if (GET_BE_U_4(use->rpu_pltime) == 0xffffffff) 2067 ND_PRINT("pltime=infty,"); 2068 else 2069 ND_PRINT("pltime=%u,", 2070 GET_BE_U_4(use->rpu_pltime)); 2071 } 2072 if (addrtostr6(use->rpu_prefix, hbuf, sizeof(hbuf))) 2073 ND_PRINT("%s/%u/%u", hbuf, 2074 GET_U_1(use->rpu_uselen), 2075 GET_U_1(use->rpu_keeplen)); 2076 else 2077 ND_PRINT("?/%u/%u", GET_U_1(use->rpu_uselen), 2078 GET_U_1(use->rpu_keeplen)); 2079 /*(*/ 2080 ND_PRINT(")"); 2081 } 2082 } 2083 2084 return; 2085 2086 trunc: 2087 nd_print_trunc(ndo); 2088 } 2089