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