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