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