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.8 2015/03/31 21:59:35 christos Exp $"); 25 #endif 26 27 #define NETDISSECT_REWORKED 28 #ifdef HAVE_CONFIG_H 29 #include "config.h" 30 #endif 31 32 #ifdef INET6 33 34 #include <tcpdump-stdinc.h> 35 36 #include <stdio.h> 37 #include <string.h> 38 39 #include "interface.h" 40 #include "addrtoname.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 uint8_t nd_opt_pi_type; 293 uint8_t nd_opt_pi_len; 294 uint8_t nd_opt_pi_prefix_len; 295 uint8_t nd_opt_pi_flags_reserved; 296 uint8_t nd_opt_pi_valid_time[4]; 297 uint8_t nd_opt_pi_preferred_time[4]; 298 uint8_t nd_opt_pi_reserved2[4]; 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(const struct ip6_hdr *ip6, const struct icmp6_hdr *icp, 631 u_int len) 632 { 633 return nextproto6_cksum(ip6, (const uint8_t *)(void *)icp, len, len, 634 IPPROTO_ICMPV6); 635 } 636 637 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 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_format_dagid(char dagid_str[65], const u_char *dagid) 660 { 661 char *d = dagid_str; 662 int i; 663 664 for(i=0;i<16;i++) { 665 if(isprint(dagid[i])) { 666 *d++ = dagid[i]; 667 } else { 668 snprintf(d,5,"0x%02x", dagid[i]); /* 4 + null char */ 669 d += 4; 670 } 671 } 672 *d++ = '\0'; 673 } 674 675 static void 676 rpl_dio_printopt(netdissect_options *ndo, 677 const struct rpl_dio_genoption *opt, 678 u_int length) 679 { 680 if(length < RPL_DIO_GENOPTION_LEN) return; 681 length -= RPL_DIO_GENOPTION_LEN; 682 683 ND_TCHECK(opt->rpl_dio_len); 684 685 while((opt->rpl_dio_type == RPL_OPT_PAD0 && 686 (u_char *)opt < ndo->ndo_snapend) || 687 ND_TTEST2(*opt,(opt->rpl_dio_len+2))) { 688 689 unsigned int optlen = opt->rpl_dio_len+2; 690 if(opt->rpl_dio_type == RPL_OPT_PAD0) { 691 optlen = 1; 692 ND_PRINT((ndo, " opt:pad0")); 693 } else { 694 ND_PRINT((ndo, " opt:%s len:%u ", 695 tok2str(rpl_subopt_values, "%subopt:%u", opt->rpl_dio_type), 696 optlen)); 697 if(ndo->ndo_vflag > 2) { 698 unsigned int paylen = opt->rpl_dio_len; 699 if(paylen > length) paylen = length; 700 hex_print(ndo, 701 " ", 702 ((uint8_t *)opt) + RPL_DIO_GENOPTION_LEN, /* content of DIO option */ 703 paylen); 704 } 705 } 706 opt = (struct rpl_dio_genoption *)(((char *)opt) + optlen); 707 length -= optlen; 708 } 709 return; 710 trunc: 711 ND_PRINT((ndo," [|truncated]")); 712 return; 713 } 714 715 static void 716 rpl_dio_print(netdissect_options *ndo, 717 const u_char *bp, u_int length) 718 { 719 const struct nd_rpl_dio *dio = (struct nd_rpl_dio *)bp; 720 char dagid_str[65]; 721 722 ND_TCHECK(*dio); 723 rpl_format_dagid(dagid_str, dio->rpl_dagid); 724 725 ND_PRINT((ndo, " [dagid:%s,seq:%u,instance:%u,rank:%u,%smop:%s,prf:%u]", 726 dagid_str, 727 dio->rpl_dtsn, 728 dio->rpl_instanceid, 729 EXTRACT_16BITS(&dio->rpl_dagrank), 730 RPL_DIO_GROUNDED(dio->rpl_mopprf) ? "grounded,":"", 731 tok2str(rpl_mop_values, "mop%u", RPL_DIO_MOP(dio->rpl_mopprf)), 732 RPL_DIO_PRF(dio->rpl_mopprf))); 733 734 if(ndo->ndo_vflag > 1) { 735 struct rpl_dio_genoption *opt = (struct rpl_dio_genoption *)&dio[1]; 736 rpl_dio_printopt(ndo, opt, length); 737 } 738 return; 739 trunc: 740 ND_PRINT((ndo," [|truncated]")); 741 return; 742 } 743 744 static void 745 rpl_dao_print(netdissect_options *ndo, 746 const u_char *bp, u_int length) 747 { 748 const struct nd_rpl_dao *dao = (struct nd_rpl_dao *)bp; 749 char dagid_str[65]; 750 751 ND_TCHECK(*dao); 752 if (length < ND_RPL_DAO_MIN_LEN) 753 goto tooshort; 754 755 strcpy(dagid_str,"<elided>"); 756 bp += ND_RPL_DAO_MIN_LEN; 757 length -= ND_RPL_DAO_MIN_LEN; 758 if(RPL_DAO_D(dao->rpl_flags)) { 759 ND_TCHECK2(dao->rpl_dagid, DAGID_LEN); 760 if (length < DAGID_LEN) 761 goto tooshort; 762 rpl_format_dagid(dagid_str, dao->rpl_dagid); 763 bp += DAGID_LEN; 764 length -= DAGID_LEN; 765 } 766 767 ND_PRINT((ndo, " [dagid:%s,seq:%u,instance:%u%s%s,%02x]", 768 dagid_str, 769 dao->rpl_daoseq, 770 dao->rpl_instanceid, 771 RPL_DAO_K(dao->rpl_flags) ? ",acK":"", 772 RPL_DAO_D(dao->rpl_flags) ? ",Dagid":"", 773 dao->rpl_flags)); 774 775 if(ndo->ndo_vflag > 1) { 776 const struct rpl_dio_genoption *opt = (struct rpl_dio_genoption *)bp; 777 rpl_dio_printopt(ndo, opt, length); 778 } 779 return; 780 781 trunc: 782 ND_PRINT((ndo," [|truncated]")); 783 return; 784 785 tooshort: 786 ND_PRINT((ndo," [|length too short]")); 787 return; 788 } 789 790 static void 791 rpl_daoack_print(netdissect_options *ndo, 792 const u_char *bp, u_int length) 793 { 794 const struct nd_rpl_daoack *daoack = (struct nd_rpl_daoack *)bp; 795 char dagid_str[65]; 796 797 ND_TCHECK2(*daoack, ND_RPL_DAOACK_MIN_LEN); 798 if (length < ND_RPL_DAOACK_MIN_LEN) 799 goto tooshort; 800 801 strcpy(dagid_str,"<elided>"); 802 bp += ND_RPL_DAOACK_MIN_LEN; 803 length -= ND_RPL_DAOACK_MIN_LEN; 804 if(RPL_DAOACK_D(daoack->rpl_flags)) { 805 ND_TCHECK2(daoack->rpl_dagid, 16); 806 if (length < DAGID_LEN) 807 goto tooshort; 808 rpl_format_dagid(dagid_str, daoack->rpl_dagid); 809 bp += DAGID_LEN; 810 length -= DAGID_LEN; 811 } 812 813 ND_PRINT((ndo, " [dagid:%s,seq:%u,instance:%u,status:%u]", 814 dagid_str, 815 daoack->rpl_daoseq, 816 daoack->rpl_instanceid, 817 daoack->rpl_status)); 818 819 /* no officially defined options for DAOACK, but print any we find */ 820 if(ndo->ndo_vflag > 1) { 821 const struct rpl_dio_genoption *opt = (struct rpl_dio_genoption *)bp; 822 rpl_dio_printopt(ndo, opt, length); 823 } 824 return; 825 826 trunc: 827 ND_PRINT((ndo," [|dao-truncated]")); 828 return; 829 830 tooshort: 831 ND_PRINT((ndo," [|dao-length too short]")); 832 return; 833 } 834 835 static void 836 rpl_print(netdissect_options *ndo, 837 const struct icmp6_hdr *hdr, 838 const u_char *bp, u_int length) 839 { 840 int secured = hdr->icmp6_code & 0x80; 841 int basecode= hdr->icmp6_code & 0x7f; 842 843 if(secured) { 844 ND_PRINT((ndo, ", (SEC) [worktodo]")); 845 /* XXX 846 * the next header pointer needs to move forward to 847 * skip the secure part. 848 */ 849 return; 850 } else { 851 ND_PRINT((ndo, ", (CLR)")); 852 } 853 854 switch(basecode) { 855 case ND_RPL_DAG_IS: 856 ND_PRINT((ndo, "DODAG Information Solicitation")); 857 if(ndo->ndo_vflag) { 858 } 859 break; 860 case ND_RPL_DAG_IO: 861 ND_PRINT((ndo, "DODAG Information Object")); 862 if(ndo->ndo_vflag) { 863 rpl_dio_print(ndo, bp, length); 864 } 865 break; 866 case ND_RPL_DAO: 867 ND_PRINT((ndo, "Destination Advertisement Object")); 868 if(ndo->ndo_vflag) { 869 rpl_dao_print(ndo, bp, length); 870 } 871 break; 872 case ND_RPL_DAO_ACK: 873 ND_PRINT((ndo, "Destination Advertisement Object Ack")); 874 if(ndo->ndo_vflag) { 875 rpl_daoack_print(ndo, bp, length); 876 } 877 break; 878 default: 879 ND_PRINT((ndo, "RPL message, unknown code %u",hdr->icmp6_code)); 880 break; 881 } 882 return; 883 884 #if 0 885 trunc: 886 ND_PRINT((ndo," [|truncated]")); 887 return; 888 #endif 889 890 } 891 892 893 void 894 icmp6_print(netdissect_options *ndo, 895 const u_char *bp, u_int length, const u_char *bp2, int fragmented) 896 { 897 const struct icmp6_hdr *dp; 898 const struct ip6_hdr *ip; 899 const struct ip6_hdr *oip; 900 const struct udphdr *ouh; 901 int dport; 902 const u_char *ep; 903 u_int prot; 904 905 dp = (struct icmp6_hdr *)bp; 906 ip = (struct ip6_hdr *)bp2; 907 oip = (struct ip6_hdr *)(dp + 1); 908 /* 'ep' points to the end of available data. */ 909 ep = ndo->ndo_snapend; 910 911 ND_TCHECK(dp->icmp6_cksum); 912 913 if (ndo->ndo_vflag && !fragmented) { 914 uint16_t sum, udp_sum; 915 916 if (ND_TTEST2(bp[0], length)) { 917 udp_sum = EXTRACT_16BITS(&dp->icmp6_cksum); 918 sum = icmp6_cksum(ip, dp, length); 919 if (sum != 0) 920 ND_PRINT((ndo,"[bad icmp6 cksum 0x%04x -> 0x%04x!] ", 921 udp_sum, 922 in_cksum_shouldbe(udp_sum, sum))); 923 else 924 ND_PRINT((ndo,"[icmp6 sum ok] ")); 925 } 926 } 927 928 ND_PRINT((ndo,"ICMP6, %s", tok2str(icmp6_type_values,"unknown icmp6 type (%u)",dp->icmp6_type))); 929 930 /* display cosmetics: print the packet length for printer that use the vflag now */ 931 if (ndo->ndo_vflag) 932 switch (dp->icmp6_type) { 933 case ND_ROUTER_SOLICIT: 934 case ND_ROUTER_ADVERT: 935 case ND_NEIGHBOR_ADVERT: 936 case ND_NEIGHBOR_SOLICIT: 937 case ND_REDIRECT: 938 case ICMP6_HADISCOV_REPLY: 939 case ICMP6_MOBILEPREFIX_ADVERT: 940 ND_PRINT((ndo, ", length %u", length)); 941 break; 942 default: 943 break; 944 } 945 946 switch (dp->icmp6_type) { 947 case ICMP6_DST_UNREACH: 948 ND_TCHECK(oip->ip6_dst); 949 ND_PRINT((ndo,", %s", tok2str(icmp6_dst_unreach_code_values,"unknown unreach code (%u)",dp->icmp6_code))); 950 switch (dp->icmp6_code) { 951 952 case ICMP6_DST_UNREACH_NOROUTE: /* fall through */ 953 case ICMP6_DST_UNREACH_ADMIN: 954 case ICMP6_DST_UNREACH_ADDR: 955 ND_PRINT((ndo," %s",ip6addr_string(ndo, &oip->ip6_dst))); 956 break; 957 case ICMP6_DST_UNREACH_BEYONDSCOPE: 958 ND_PRINT((ndo," %s, source address %s", 959 ip6addr_string(ndo, &oip->ip6_dst), 960 ip6addr_string(ndo, &oip->ip6_src))); 961 break; 962 case ICMP6_DST_UNREACH_NOPORT: 963 if ((ouh = get_upperlayer(ndo, (u_char *)oip, &prot)) 964 == NULL) 965 goto trunc; 966 967 dport = EXTRACT_16BITS(&ouh->uh_dport); 968 switch (prot) { 969 case IPPROTO_TCP: 970 ND_PRINT((ndo,", %s tcp port %s", 971 ip6addr_string(ndo, &oip->ip6_dst), 972 tcpport_string(dport))); 973 break; 974 case IPPROTO_UDP: 975 ND_PRINT((ndo,", %s udp port %s", 976 ip6addr_string(ndo, &oip->ip6_dst), 977 udpport_string(dport))); 978 break; 979 default: 980 ND_PRINT((ndo,", %s protocol %d port %d unreachable", 981 ip6addr_string(ndo, &oip->ip6_dst), 982 oip->ip6_nxt, dport)); 983 break; 984 } 985 break; 986 default: 987 if (ndo->ndo_vflag <= 1) { 988 print_unknown_data(ndo, bp,"\n\t",length); 989 return; 990 } 991 break; 992 } 993 break; 994 case ICMP6_PACKET_TOO_BIG: 995 ND_TCHECK(dp->icmp6_mtu); 996 ND_PRINT((ndo,", mtu %u", EXTRACT_32BITS(&dp->icmp6_mtu))); 997 break; 998 case ICMP6_TIME_EXCEEDED: 999 ND_TCHECK(oip->ip6_dst); 1000 switch (dp->icmp6_code) { 1001 case ICMP6_TIME_EXCEED_TRANSIT: 1002 ND_PRINT((ndo," for %s", 1003 ip6addr_string(ndo, &oip->ip6_dst))); 1004 break; 1005 case ICMP6_TIME_EXCEED_REASSEMBLY: 1006 ND_PRINT((ndo," (reassembly)")); 1007 break; 1008 default: 1009 ND_PRINT((ndo,", unknown code (%u)", dp->icmp6_code)); 1010 break; 1011 } 1012 break; 1013 case ICMP6_PARAM_PROB: 1014 ND_TCHECK(oip->ip6_dst); 1015 switch (dp->icmp6_code) { 1016 case ICMP6_PARAMPROB_HEADER: 1017 ND_PRINT((ndo,", erroneous - octet %u", EXTRACT_32BITS(&dp->icmp6_pptr))); 1018 break; 1019 case ICMP6_PARAMPROB_NEXTHEADER: 1020 ND_PRINT((ndo,", next header - octet %u", EXTRACT_32BITS(&dp->icmp6_pptr))); 1021 break; 1022 case ICMP6_PARAMPROB_OPTION: 1023 ND_PRINT((ndo,", option - octet %u", EXTRACT_32BITS(&dp->icmp6_pptr))); 1024 break; 1025 default: 1026 ND_PRINT((ndo,", code-#%d", 1027 dp->icmp6_code)); 1028 break; 1029 } 1030 break; 1031 case ICMP6_ECHO_REQUEST: 1032 case ICMP6_ECHO_REPLY: 1033 ND_TCHECK(dp->icmp6_seq); 1034 ND_PRINT((ndo,", seq %u", EXTRACT_16BITS(&dp->icmp6_seq))); 1035 break; 1036 case ICMP6_MEMBERSHIP_QUERY: 1037 if (length == MLD_MINLEN) { 1038 mld6_print(ndo, (const u_char *)dp); 1039 } else if (length >= MLDV2_MINLEN) { 1040 ND_PRINT((ndo," v2")); 1041 mldv2_query_print(ndo, (const u_char *)dp, length); 1042 } else { 1043 ND_PRINT((ndo," unknown-version (len %u) ", length)); 1044 } 1045 break; 1046 case ICMP6_MEMBERSHIP_REPORT: 1047 mld6_print(ndo, (const u_char *)dp); 1048 break; 1049 case ICMP6_MEMBERSHIP_REDUCTION: 1050 mld6_print(ndo, (const u_char *)dp); 1051 break; 1052 case ND_ROUTER_SOLICIT: 1053 #define RTSOLLEN 8 1054 if (ndo->ndo_vflag) { 1055 icmp6_opt_print(ndo, (const u_char *)dp + RTSOLLEN, 1056 length - RTSOLLEN); 1057 } 1058 break; 1059 case ND_ROUTER_ADVERT: 1060 #define RTADVLEN 16 1061 if (ndo->ndo_vflag) { 1062 struct nd_router_advert *p; 1063 1064 p = (struct nd_router_advert *)dp; 1065 ND_TCHECK(p->nd_ra_retransmit); 1066 ND_PRINT((ndo,"\n\thop limit %u, Flags [%s]" \ 1067 ", pref %s, router lifetime %us, reachable time %us, retrans time %us", 1068 (u_int)p->nd_ra_curhoplimit, 1069 bittok2str(icmp6_opt_ra_flag_values,"none",(p->nd_ra_flags_reserved)), 1070 get_rtpref(p->nd_ra_flags_reserved), 1071 EXTRACT_16BITS(&p->nd_ra_router_lifetime), 1072 EXTRACT_32BITS(&p->nd_ra_reachable), 1073 EXTRACT_32BITS(&p->nd_ra_retransmit))); 1074 1075 icmp6_opt_print(ndo, (const u_char *)dp + RTADVLEN, 1076 length - RTADVLEN); 1077 } 1078 break; 1079 case ND_NEIGHBOR_SOLICIT: 1080 { 1081 struct nd_neighbor_solicit *p; 1082 p = (struct nd_neighbor_solicit *)dp; 1083 ND_TCHECK(p->nd_ns_target); 1084 ND_PRINT((ndo,", who has %s", ip6addr_string(ndo, &p->nd_ns_target))); 1085 if (ndo->ndo_vflag) { 1086 #define NDSOLLEN 24 1087 icmp6_opt_print(ndo, (const u_char *)dp + NDSOLLEN, 1088 length - NDSOLLEN); 1089 } 1090 } 1091 break; 1092 case ND_NEIGHBOR_ADVERT: 1093 { 1094 struct nd_neighbor_advert *p; 1095 1096 p = (struct nd_neighbor_advert *)dp; 1097 ND_TCHECK(p->nd_na_target); 1098 ND_PRINT((ndo,", tgt is %s", 1099 ip6addr_string(ndo, &p->nd_na_target))); 1100 if (ndo->ndo_vflag) { 1101 ND_PRINT((ndo,", Flags [%s]", 1102 bittok2str(icmp6_nd_na_flag_values, 1103 "none", 1104 EXTRACT_32BITS(&p->nd_na_flags_reserved)))); 1105 #define NDADVLEN 24 1106 icmp6_opt_print(ndo, (const u_char *)dp + NDADVLEN, 1107 length - NDADVLEN); 1108 #undef NDADVLEN 1109 } 1110 } 1111 break; 1112 case ND_REDIRECT: 1113 #define RDR(i) ((struct nd_redirect *)(i)) 1114 ND_TCHECK(RDR(dp)->nd_rd_dst); 1115 ND_PRINT((ndo,", %s", getname6(ndo, (const u_char *)&RDR(dp)->nd_rd_dst))); 1116 ND_TCHECK(RDR(dp)->nd_rd_target); 1117 ND_PRINT((ndo," to %s", 1118 getname6(ndo, (const u_char*)&RDR(dp)->nd_rd_target))); 1119 #define REDIRECTLEN 40 1120 if (ndo->ndo_vflag) { 1121 icmp6_opt_print(ndo, (const u_char *)dp + REDIRECTLEN, 1122 length - REDIRECTLEN); 1123 } 1124 break; 1125 #undef REDIRECTLEN 1126 #undef RDR 1127 case ICMP6_ROUTER_RENUMBERING: 1128 icmp6_rrenum_print(ndo, bp, ep); 1129 break; 1130 case ICMP6_NI_QUERY: 1131 case ICMP6_NI_REPLY: 1132 icmp6_nodeinfo_print(ndo, length, bp, ep); 1133 break; 1134 case IND_SOLICIT: 1135 case IND_ADVERT: 1136 break; 1137 case ICMP6_V2_MEMBERSHIP_REPORT: 1138 mldv2_report_print(ndo, (const u_char *) dp, length); 1139 break; 1140 case ICMP6_MOBILEPREFIX_SOLICIT: /* fall through */ 1141 case ICMP6_HADISCOV_REQUEST: 1142 ND_TCHECK(dp->icmp6_data16[0]); 1143 ND_PRINT((ndo,", id 0x%04x", EXTRACT_16BITS(&dp->icmp6_data16[0]))); 1144 break; 1145 case ICMP6_HADISCOV_REPLY: 1146 if (ndo->ndo_vflag) { 1147 struct in6_addr *in6; 1148 u_char *cp; 1149 1150 ND_TCHECK(dp->icmp6_data16[0]); 1151 ND_PRINT((ndo,", id 0x%04x", EXTRACT_16BITS(&dp->icmp6_data16[0]))); 1152 cp = (u_char *)dp + length; 1153 in6 = (struct in6_addr *)(dp + 1); 1154 for (; (u_char *)in6 < cp; in6++) { 1155 ND_TCHECK(*in6); 1156 ND_PRINT((ndo,", %s", ip6addr_string(ndo, in6))); 1157 } 1158 } 1159 break; 1160 case ICMP6_MOBILEPREFIX_ADVERT: 1161 if (ndo->ndo_vflag) { 1162 ND_TCHECK(dp->icmp6_data16[0]); 1163 ND_PRINT((ndo,", id 0x%04x", EXTRACT_16BITS(&dp->icmp6_data16[0]))); 1164 if (dp->icmp6_data16[1] & 0xc0) 1165 ND_PRINT((ndo," ")); 1166 if (dp->icmp6_data16[1] & 0x80) 1167 ND_PRINT((ndo,"M")); 1168 if (dp->icmp6_data16[1] & 0x40) 1169 ND_PRINT((ndo,"O")); 1170 #define MPADVLEN 8 1171 icmp6_opt_print(ndo, (const u_char *)dp + MPADVLEN, 1172 length - MPADVLEN); 1173 } 1174 break; 1175 case ND_RPL_MESSAGE: 1176 /* plus 4, because struct icmp6_hdr contains 4 bytes of icmp payload */ 1177 rpl_print(ndo, dp, &dp->icmp6_data8[0], length-sizeof(struct icmp6_hdr)+4); 1178 break; 1179 default: 1180 ND_PRINT((ndo,", length %u", length)); 1181 if (ndo->ndo_vflag <= 1) 1182 print_unknown_data(ndo, bp,"\n\t", length); 1183 return; 1184 } 1185 if (!ndo->ndo_vflag) 1186 ND_PRINT((ndo,", length %u", length)); 1187 return; 1188 trunc: 1189 ND_PRINT((ndo, "[|icmp6]")); 1190 } 1191 1192 static const struct udphdr * 1193 get_upperlayer(netdissect_options *ndo, const u_char *bp, u_int *prot) 1194 { 1195 const u_char *ep; 1196 const struct ip6_hdr *ip6 = (struct ip6_hdr *)bp; 1197 const struct udphdr *uh; 1198 const struct ip6_hbh *hbh; 1199 const struct ip6_frag *fragh; 1200 const struct ah *ah; 1201 u_int nh; 1202 int hlen; 1203 1204 /* 'ep' points to the end of available data. */ 1205 ep = ndo->ndo_snapend; 1206 1207 if (!ND_TTEST(ip6->ip6_nxt)) 1208 return NULL; 1209 1210 nh = ip6->ip6_nxt; 1211 hlen = sizeof(struct ip6_hdr); 1212 1213 while (bp < ep) { 1214 bp += hlen; 1215 1216 switch(nh) { 1217 case IPPROTO_UDP: 1218 case IPPROTO_TCP: 1219 uh = (struct udphdr *)bp; 1220 if (ND_TTEST(uh->uh_dport)) { 1221 *prot = nh; 1222 return(uh); 1223 } 1224 else 1225 return(NULL); 1226 /* NOTREACHED */ 1227 1228 case IPPROTO_HOPOPTS: 1229 case IPPROTO_DSTOPTS: 1230 case IPPROTO_ROUTING: 1231 hbh = (struct ip6_hbh *)bp; 1232 if (!ND_TTEST(hbh->ip6h_len)) 1233 return(NULL); 1234 nh = hbh->ip6h_nxt; 1235 hlen = (hbh->ip6h_len + 1) << 3; 1236 break; 1237 1238 case IPPROTO_FRAGMENT: /* this should be odd, but try anyway */ 1239 fragh = (struct ip6_frag *)bp; 1240 if (!ND_TTEST(fragh->ip6f_offlg)) 1241 return(NULL); 1242 /* fragments with non-zero offset are meaningless */ 1243 if ((EXTRACT_16BITS(&fragh->ip6f_offlg) & IP6F_OFF_MASK) != 0) 1244 return(NULL); 1245 nh = fragh->ip6f_nxt; 1246 hlen = sizeof(struct ip6_frag); 1247 break; 1248 1249 case IPPROTO_AH: 1250 ah = (struct ah *)bp; 1251 if (!ND_TTEST(ah->ah_len)) 1252 return(NULL); 1253 nh = ah->ah_nxt; 1254 hlen = (ah->ah_len + 2) << 2; 1255 break; 1256 1257 default: /* unknown or undecodable header */ 1258 *prot = nh; /* meaningless, but set here anyway */ 1259 return(NULL); 1260 } 1261 } 1262 1263 return(NULL); /* should be notreached, though */ 1264 } 1265 1266 static void 1267 icmp6_opt_print(netdissect_options *ndo, const u_char *bp, int resid) 1268 { 1269 const struct nd_opt_hdr *op; 1270 const struct nd_opt_prefix_info *opp; 1271 const struct nd_opt_mtu *opm; 1272 const struct nd_opt_rdnss *oprd; 1273 const struct nd_opt_dnssl *opds; 1274 const struct nd_opt_advinterval *opa; 1275 const struct nd_opt_homeagent_info *oph; 1276 const struct nd_opt_route_info *opri; 1277 const u_char *cp, *ep, *domp; 1278 struct in6_addr in6, *in6p; 1279 size_t l; 1280 u_int i; 1281 1282 #define ECHECK(var) if ((u_char *)&(var) > ep - sizeof(var)) return 1283 1284 cp = bp; 1285 /* 'ep' points to the end of available data. */ 1286 ep = ndo->ndo_snapend; 1287 1288 while (cp < ep) { 1289 op = (struct nd_opt_hdr *)cp; 1290 1291 ECHECK(op->nd_opt_len); 1292 if (resid <= 0) 1293 return; 1294 if (op->nd_opt_len == 0) 1295 goto trunc; 1296 if (cp + (op->nd_opt_len << 3) > ep) 1297 goto trunc; 1298 1299 ND_PRINT((ndo,"\n\t %s option (%u), length %u (%u): ", 1300 tok2str(icmp6_opt_values, "unknown", op->nd_opt_type), 1301 op->nd_opt_type, 1302 op->nd_opt_len << 3, 1303 op->nd_opt_len)); 1304 1305 switch (op->nd_opt_type) { 1306 case ND_OPT_SOURCE_LINKADDR: 1307 l = (op->nd_opt_len << 3) - 2; 1308 print_lladdr(ndo, cp + 2, l); 1309 break; 1310 case ND_OPT_TARGET_LINKADDR: 1311 l = (op->nd_opt_len << 3) - 2; 1312 print_lladdr(ndo, cp + 2, l); 1313 break; 1314 case ND_OPT_PREFIX_INFORMATION: 1315 opp = (struct nd_opt_prefix_info *)op; 1316 ND_TCHECK(opp->nd_opt_pi_prefix); 1317 ND_PRINT((ndo,"%s/%u%s, Flags [%s], valid time %s", 1318 ip6addr_string(ndo, &opp->nd_opt_pi_prefix), 1319 opp->nd_opt_pi_prefix_len, 1320 (op->nd_opt_len != 4) ? "badlen" : "", 1321 bittok2str(icmp6_opt_pi_flag_values, "none", opp->nd_opt_pi_flags_reserved), 1322 get_lifetime(EXTRACT_32BITS(&opp->nd_opt_pi_valid_time)))); 1323 ND_PRINT((ndo,", pref. time %s", get_lifetime(EXTRACT_32BITS(&opp->nd_opt_pi_preferred_time)))); 1324 break; 1325 case ND_OPT_REDIRECTED_HEADER: 1326 print_unknown_data(ndo, bp,"\n\t ",op->nd_opt_len<<3); 1327 /* xxx */ 1328 break; 1329 case ND_OPT_MTU: 1330 opm = (struct nd_opt_mtu *)op; 1331 ND_TCHECK(opm->nd_opt_mtu_mtu); 1332 ND_PRINT((ndo," %u%s", 1333 EXTRACT_32BITS(&opm->nd_opt_mtu_mtu), 1334 (op->nd_opt_len != 1) ? "bad option length" : "" )); 1335 break; 1336 case ND_OPT_RDNSS: 1337 oprd = (struct nd_opt_rdnss *)op; 1338 l = (op->nd_opt_len - 1) / 2; 1339 ND_PRINT((ndo," lifetime %us,", 1340 EXTRACT_32BITS(&oprd->nd_opt_rdnss_lifetime))); 1341 for (i = 0; i < l; i++) { 1342 ND_TCHECK(oprd->nd_opt_rdnss_addr[i]); 1343 ND_PRINT((ndo," addr: %s", 1344 ip6addr_string(ndo, &oprd->nd_opt_rdnss_addr[i]))); 1345 } 1346 break; 1347 case ND_OPT_DNSSL: 1348 opds = (struct nd_opt_dnssl *)op; 1349 ND_PRINT((ndo," lifetime %us, domain(s):", 1350 EXTRACT_32BITS(&opds->nd_opt_dnssl_lifetime))); 1351 domp = cp + 8; /* domain names, variable-sized, RFC1035-encoded */ 1352 while (domp < cp + (op->nd_opt_len << 3) && *domp != '\0') 1353 { 1354 ND_PRINT((ndo, " ")); 1355 if ((domp = ns_nprint (ndo, domp, bp)) == NULL) 1356 goto trunc; 1357 } 1358 break; 1359 case ND_OPT_ADVINTERVAL: 1360 opa = (struct nd_opt_advinterval *)op; 1361 ND_TCHECK(opa->nd_opt_adv_interval); 1362 ND_PRINT((ndo," %ums", EXTRACT_32BITS(&opa->nd_opt_adv_interval))); 1363 break; 1364 case ND_OPT_HOMEAGENT_INFO: 1365 oph = (struct nd_opt_homeagent_info *)op; 1366 ND_TCHECK(oph->nd_opt_hai_lifetime); 1367 ND_PRINT((ndo," preference %u, lifetime %u", 1368 EXTRACT_16BITS(&oph->nd_opt_hai_preference), 1369 EXTRACT_16BITS(&oph->nd_opt_hai_lifetime))); 1370 break; 1371 case ND_OPT_ROUTE_INFO: 1372 opri = (struct nd_opt_route_info *)op; 1373 ND_TCHECK(opri->nd_opt_rti_lifetime); 1374 memset(&in6, 0, sizeof(in6)); 1375 in6p = (struct in6_addr *)(opri + 1); 1376 switch (op->nd_opt_len) { 1377 case 1: 1378 break; 1379 case 2: 1380 ND_TCHECK2(*in6p, 8); 1381 memcpy(&in6, opri + 1, 8); 1382 break; 1383 case 3: 1384 ND_TCHECK(*in6p); 1385 memcpy(&in6, opri + 1, sizeof(in6)); 1386 break; 1387 default: 1388 goto trunc; 1389 } 1390 ND_PRINT((ndo," %s/%u", ip6addr_string(ndo, &in6), 1391 opri->nd_opt_rti_prefixlen)); 1392 ND_PRINT((ndo,", pref=%s", get_rtpref(opri->nd_opt_rti_flags))); 1393 ND_PRINT((ndo,", lifetime=%s", 1394 get_lifetime(EXTRACT_32BITS(&opri->nd_opt_rti_lifetime)))); 1395 break; 1396 default: 1397 if (ndo->ndo_vflag <= 1) { 1398 print_unknown_data(ndo,cp+2,"\n\t ", (op->nd_opt_len << 3) - 2); /* skip option header */ 1399 return; 1400 } 1401 break; 1402 } 1403 /* do we want to see an additional hexdump ? */ 1404 if (ndo->ndo_vflag> 1) 1405 print_unknown_data(ndo, cp+2,"\n\t ", (op->nd_opt_len << 3) - 2); /* skip option header */ 1406 1407 cp += op->nd_opt_len << 3; 1408 resid -= op->nd_opt_len << 3; 1409 } 1410 return; 1411 1412 trunc: 1413 ND_PRINT((ndo, "[ndp opt]")); 1414 return; 1415 #undef ECHECK 1416 } 1417 1418 static void 1419 mld6_print(netdissect_options *ndo, const u_char *bp) 1420 { 1421 const struct mld6_hdr *mp = (struct mld6_hdr *)bp; 1422 const u_char *ep; 1423 1424 /* 'ep' points to the end of available data. */ 1425 ep = ndo->ndo_snapend; 1426 1427 if ((u_char *)mp + sizeof(*mp) > ep) 1428 return; 1429 1430 ND_PRINT((ndo,"max resp delay: %d ", EXTRACT_16BITS(&mp->mld6_maxdelay))); 1431 ND_PRINT((ndo,"addr: %s", ip6addr_string(ndo, &mp->mld6_addr))); 1432 } 1433 1434 static void 1435 mldv2_report_print(netdissect_options *ndo, const u_char *bp, u_int len) 1436 { 1437 struct icmp6_hdr *icp = (struct icmp6_hdr *) bp; 1438 u_int group, nsrcs, ngroups; 1439 u_int i, j; 1440 1441 /* Minimum len is 8 */ 1442 if (len < 8) { 1443 ND_PRINT((ndo," [invalid len %d]", len)); 1444 return; 1445 } 1446 1447 ND_TCHECK(icp->icmp6_data16[1]); 1448 ngroups = EXTRACT_16BITS(&icp->icmp6_data16[1]); 1449 ND_PRINT((ndo,", %d group record(s)", ngroups)); 1450 if (ndo->ndo_vflag > 0) { 1451 /* Print the group records */ 1452 group = 8; 1453 for (i = 0; i < ngroups; i++) { 1454 /* type(1) + auxlen(1) + numsrc(2) + grp(16) */ 1455 if (len < group + 20) { 1456 ND_PRINT((ndo," [invalid number of groups]")); 1457 return; 1458 } 1459 ND_TCHECK2(bp[group + 4], sizeof(struct in6_addr)); 1460 ND_PRINT((ndo," [gaddr %s", ip6addr_string(ndo, &bp[group + 4]))); 1461 ND_PRINT((ndo," %s", tok2str(mldv2report2str, " [v2-report-#%d]", 1462 bp[group]))); 1463 nsrcs = (bp[group + 2] << 8) + bp[group + 3]; 1464 /* Check the number of sources and print them */ 1465 if (len < group + 20 + (nsrcs * sizeof(struct in6_addr))) { 1466 ND_PRINT((ndo," [invalid number of sources %d]", nsrcs)); 1467 return; 1468 } 1469 if (ndo->ndo_vflag == 1) 1470 ND_PRINT((ndo,", %d source(s)", nsrcs)); 1471 else { 1472 /* Print the sources */ 1473 ND_PRINT((ndo," {")); 1474 for (j = 0; j < nsrcs; j++) { 1475 ND_TCHECK2(bp[group + 20 + j * sizeof(struct in6_addr)], 1476 sizeof(struct in6_addr)); 1477 ND_PRINT((ndo," %s", ip6addr_string(ndo, &bp[group + 20 + j * sizeof(struct in6_addr)]))); 1478 } 1479 ND_PRINT((ndo," }")); 1480 } 1481 /* Next group record */ 1482 group += 20 + nsrcs * sizeof(struct in6_addr); 1483 ND_PRINT((ndo,"]")); 1484 } 1485 } 1486 return; 1487 trunc: 1488 ND_PRINT((ndo,"[|icmp6]")); 1489 return; 1490 } 1491 1492 static void 1493 mldv2_query_print(netdissect_options *ndo, const u_char *bp, u_int len) 1494 { 1495 struct icmp6_hdr *icp = (struct icmp6_hdr *) bp; 1496 u_int mrc; 1497 int mrt, qqi; 1498 u_int nsrcs; 1499 register u_int i; 1500 1501 /* Minimum len is 28 */ 1502 if (len < 28) { 1503 ND_PRINT((ndo," [invalid len %d]", len)); 1504 return; 1505 } 1506 ND_TCHECK(icp->icmp6_data16[0]); 1507 mrc = EXTRACT_16BITS(&icp->icmp6_data16[0]); 1508 if (mrc < 32768) { 1509 mrt = mrc; 1510 } else { 1511 mrt = ((mrc & 0x0fff) | 0x1000) << (((mrc & 0x7000) >> 12) + 3); 1512 } 1513 if (ndo->ndo_vflag) { 1514 ND_PRINT((ndo," [max resp delay=%d]", mrt)); 1515 } 1516 ND_TCHECK2(bp[8], sizeof(struct in6_addr)); 1517 ND_PRINT((ndo," [gaddr %s", ip6addr_string(ndo, &bp[8]))); 1518 1519 if (ndo->ndo_vflag) { 1520 ND_TCHECK(bp[25]); 1521 if (bp[24] & 0x08) { 1522 ND_PRINT((ndo," sflag")); 1523 } 1524 if (bp[24] & 0x07) { 1525 ND_PRINT((ndo," robustness=%d", bp[24] & 0x07)); 1526 } 1527 if (bp[25] < 128) { 1528 qqi = bp[25]; 1529 } else { 1530 qqi = ((bp[25] & 0x0f) | 0x10) << (((bp[25] & 0x70) >> 4) + 3); 1531 } 1532 ND_PRINT((ndo," qqi=%d", qqi)); 1533 } 1534 1535 ND_TCHECK2(bp[26], 2); 1536 nsrcs = EXTRACT_16BITS(&bp[26]); 1537 if (nsrcs > 0) { 1538 if (len < 28 + nsrcs * sizeof(struct in6_addr)) 1539 ND_PRINT((ndo," [invalid number of sources]")); 1540 else if (ndo->ndo_vflag > 1) { 1541 ND_PRINT((ndo," {")); 1542 for (i = 0; i < nsrcs; i++) { 1543 ND_TCHECK2(bp[28 + i * sizeof(struct in6_addr)], 1544 sizeof(struct in6_addr)); 1545 ND_PRINT((ndo," %s", ip6addr_string(ndo, &bp[28 + i * sizeof(struct in6_addr)]))); 1546 } 1547 ND_PRINT((ndo," }")); 1548 } else 1549 ND_PRINT((ndo,", %d source(s)", nsrcs)); 1550 } 1551 ND_PRINT((ndo,"]")); 1552 return; 1553 trunc: 1554 ND_PRINT((ndo,"[|icmp6]")); 1555 return; 1556 } 1557 1558 static void 1559 dnsname_print(netdissect_options *ndo, const u_char *cp, const u_char *ep) 1560 { 1561 int i; 1562 1563 /* DNS name decoding - no decompression */ 1564 ND_PRINT((ndo,", \"")); 1565 while (cp < ep) { 1566 i = *cp++; 1567 if (i) { 1568 if (i > ep - cp) { 1569 ND_PRINT((ndo,"???")); 1570 break; 1571 } 1572 while (i-- && cp < ep) { 1573 safeputchar(ndo, *cp); 1574 cp++; 1575 } 1576 if (cp + 1 < ep && *cp) 1577 ND_PRINT((ndo,".")); 1578 } else { 1579 if (cp == ep) { 1580 /* FQDN */ 1581 ND_PRINT((ndo,".")); 1582 } else if (cp + 1 == ep && *cp == '\0') { 1583 /* truncated */ 1584 } else { 1585 /* invalid */ 1586 ND_PRINT((ndo,"???")); 1587 } 1588 break; 1589 } 1590 } 1591 ND_PRINT((ndo,"\"")); 1592 } 1593 1594 static void 1595 icmp6_nodeinfo_print(netdissect_options *ndo, u_int icmp6len, const u_char *bp, const u_char *ep) 1596 { 1597 const struct icmp6_nodeinfo *ni6; 1598 const struct icmp6_hdr *dp; 1599 const u_char *cp; 1600 size_t siz, i; 1601 int needcomma; 1602 1603 if (ep < bp) 1604 return; 1605 dp = (struct icmp6_hdr *)bp; 1606 ni6 = (struct icmp6_nodeinfo *)bp; 1607 siz = ep - bp; 1608 1609 switch (ni6->ni_type) { 1610 case ICMP6_NI_QUERY: 1611 if (siz == sizeof(*dp) + 4) { 1612 /* KAME who-are-you */ 1613 ND_PRINT((ndo," who-are-you request")); 1614 break; 1615 } 1616 ND_PRINT((ndo," node information query")); 1617 1618 ND_TCHECK2(*dp, sizeof(*ni6)); 1619 ni6 = (struct icmp6_nodeinfo *)dp; 1620 ND_PRINT((ndo," (")); /*)*/ 1621 switch (EXTRACT_16BITS(&ni6->ni_qtype)) { 1622 case NI_QTYPE_NOOP: 1623 ND_PRINT((ndo,"noop")); 1624 break; 1625 case NI_QTYPE_SUPTYPES: 1626 ND_PRINT((ndo,"supported qtypes")); 1627 i = EXTRACT_16BITS(&ni6->ni_flags); 1628 if (i) 1629 ND_PRINT((ndo," [%s]", (i & 0x01) ? "C" : "")); 1630 break; 1631 case NI_QTYPE_FQDN: 1632 ND_PRINT((ndo,"DNS name")); 1633 break; 1634 case NI_QTYPE_NODEADDR: 1635 ND_PRINT((ndo,"node addresses")); 1636 i = ni6->ni_flags; 1637 if (!i) 1638 break; 1639 /* NI_NODEADDR_FLAG_TRUNCATE undefined for query */ 1640 ND_PRINT((ndo," [%s%s%s%s%s%s]", 1641 (i & NI_NODEADDR_FLAG_ANYCAST) ? "a" : "", 1642 (i & NI_NODEADDR_FLAG_GLOBAL) ? "G" : "", 1643 (i & NI_NODEADDR_FLAG_SITELOCAL) ? "S" : "", 1644 (i & NI_NODEADDR_FLAG_LINKLOCAL) ? "L" : "", 1645 (i & NI_NODEADDR_FLAG_COMPAT) ? "C" : "", 1646 (i & NI_NODEADDR_FLAG_ALL) ? "A" : "")); 1647 break; 1648 default: 1649 ND_PRINT((ndo,"unknown")); 1650 break; 1651 } 1652 1653 if (ni6->ni_qtype == NI_QTYPE_NOOP || 1654 ni6->ni_qtype == NI_QTYPE_SUPTYPES) { 1655 if (siz != sizeof(*ni6)) 1656 if (ndo->ndo_vflag) 1657 ND_PRINT((ndo,", invalid len")); 1658 /*(*/ 1659 ND_PRINT((ndo,")")); 1660 break; 1661 } 1662 1663 1664 /* XXX backward compat, icmp-name-lookup-03 */ 1665 if (siz == sizeof(*ni6)) { 1666 ND_PRINT((ndo,", 03 draft")); 1667 /*(*/ 1668 ND_PRINT((ndo,")")); 1669 break; 1670 } 1671 1672 switch (ni6->ni_code) { 1673 case ICMP6_NI_SUBJ_IPV6: 1674 if (!ND_TTEST2(*dp, 1675 sizeof(*ni6) + sizeof(struct in6_addr))) 1676 break; 1677 if (siz != sizeof(*ni6) + sizeof(struct in6_addr)) { 1678 if (ndo->ndo_vflag) 1679 ND_PRINT((ndo,", invalid subject len")); 1680 break; 1681 } 1682 ND_PRINT((ndo,", subject=%s", 1683 getname6(ndo, (const u_char *)(ni6 + 1)))); 1684 break; 1685 case ICMP6_NI_SUBJ_FQDN: 1686 ND_PRINT((ndo,", subject=DNS name")); 1687 cp = (const u_char *)(ni6 + 1); 1688 if (cp[0] == ep - cp - 1) { 1689 /* icmp-name-lookup-03, pascal string */ 1690 if (ndo->ndo_vflag) 1691 ND_PRINT((ndo,", 03 draft")); 1692 cp++; 1693 ND_PRINT((ndo,", \"")); 1694 while (cp < ep) { 1695 safeputchar(ndo, *cp); 1696 cp++; 1697 } 1698 ND_PRINT((ndo,"\"")); 1699 } else 1700 dnsname_print(ndo, cp, ep); 1701 break; 1702 case ICMP6_NI_SUBJ_IPV4: 1703 if (!ND_TTEST2(*dp, sizeof(*ni6) + sizeof(struct in_addr))) 1704 break; 1705 if (siz != sizeof(*ni6) + sizeof(struct in_addr)) { 1706 if (ndo->ndo_vflag) 1707 ND_PRINT((ndo,", invalid subject len")); 1708 break; 1709 } 1710 ND_PRINT((ndo,", subject=%s", 1711 getname(ndo, (const u_char *)(ni6 + 1)))); 1712 break; 1713 default: 1714 ND_PRINT((ndo,", unknown subject")); 1715 break; 1716 } 1717 1718 /*(*/ 1719 ND_PRINT((ndo,")")); 1720 break; 1721 1722 case ICMP6_NI_REPLY: 1723 if (icmp6len > siz) { 1724 ND_PRINT((ndo,"[|icmp6: node information reply]")); 1725 break; 1726 } 1727 1728 needcomma = 0; 1729 1730 ni6 = (struct icmp6_nodeinfo *)dp; 1731 ND_PRINT((ndo," node information reply")); 1732 ND_PRINT((ndo," (")); /*)*/ 1733 switch (ni6->ni_code) { 1734 case ICMP6_NI_SUCCESS: 1735 if (ndo->ndo_vflag) { 1736 ND_PRINT((ndo,"success")); 1737 needcomma++; 1738 } 1739 break; 1740 case ICMP6_NI_REFUSED: 1741 ND_PRINT((ndo,"refused")); 1742 needcomma++; 1743 if (siz != sizeof(*ni6)) 1744 if (ndo->ndo_vflag) 1745 ND_PRINT((ndo,", invalid length")); 1746 break; 1747 case ICMP6_NI_UNKNOWN: 1748 ND_PRINT((ndo,"unknown")); 1749 needcomma++; 1750 if (siz != sizeof(*ni6)) 1751 if (ndo->ndo_vflag) 1752 ND_PRINT((ndo,", invalid length")); 1753 break; 1754 } 1755 1756 if (ni6->ni_code != ICMP6_NI_SUCCESS) { 1757 /*(*/ 1758 ND_PRINT((ndo,")")); 1759 break; 1760 } 1761 1762 switch (EXTRACT_16BITS(&ni6->ni_qtype)) { 1763 case NI_QTYPE_NOOP: 1764 if (needcomma) 1765 ND_PRINT((ndo,", ")); 1766 ND_PRINT((ndo,"noop")); 1767 if (siz != sizeof(*ni6)) 1768 if (ndo->ndo_vflag) 1769 ND_PRINT((ndo,", invalid length")); 1770 break; 1771 case NI_QTYPE_SUPTYPES: 1772 if (needcomma) 1773 ND_PRINT((ndo,", ")); 1774 ND_PRINT((ndo,"supported qtypes")); 1775 i = EXTRACT_16BITS(&ni6->ni_flags); 1776 if (i) 1777 ND_PRINT((ndo," [%s]", (i & 0x01) ? "C" : "")); 1778 break; 1779 case NI_QTYPE_FQDN: 1780 if (needcomma) 1781 ND_PRINT((ndo,", ")); 1782 ND_PRINT((ndo,"DNS name")); 1783 cp = (const u_char *)(ni6 + 1) + 4; 1784 if (cp[0] == ep - cp - 1) { 1785 /* icmp-name-lookup-03, pascal string */ 1786 if (ndo->ndo_vflag) 1787 ND_PRINT((ndo,", 03 draft")); 1788 cp++; 1789 ND_PRINT((ndo,", \"")); 1790 while (cp < ep) { 1791 safeputchar(ndo, *cp); 1792 cp++; 1793 } 1794 ND_PRINT((ndo,"\"")); 1795 } else 1796 dnsname_print(ndo, cp, ep); 1797 if ((EXTRACT_16BITS(&ni6->ni_flags) & 0x01) != 0) 1798 ND_PRINT((ndo," [TTL=%u]", *(uint32_t *)(ni6 + 1))); 1799 break; 1800 case NI_QTYPE_NODEADDR: 1801 if (needcomma) 1802 ND_PRINT((ndo,", ")); 1803 ND_PRINT((ndo,"node addresses")); 1804 i = sizeof(*ni6); 1805 while (i < siz) { 1806 if (i + sizeof(struct in6_addr) + sizeof(int32_t) > siz) 1807 break; 1808 ND_PRINT((ndo," %s", getname6(ndo, bp + i))); 1809 i += sizeof(struct in6_addr); 1810 ND_PRINT((ndo,"(%d)", (int32_t)EXTRACT_32BITS(bp + i))); 1811 i += sizeof(int32_t); 1812 } 1813 i = ni6->ni_flags; 1814 if (!i) 1815 break; 1816 ND_PRINT((ndo," [%s%s%s%s%s%s%s]", 1817 (i & NI_NODEADDR_FLAG_ANYCAST) ? "a" : "", 1818 (i & NI_NODEADDR_FLAG_GLOBAL) ? "G" : "", 1819 (i & NI_NODEADDR_FLAG_SITELOCAL) ? "S" : "", 1820 (i & NI_NODEADDR_FLAG_LINKLOCAL) ? "L" : "", 1821 (i & NI_NODEADDR_FLAG_COMPAT) ? "C" : "", 1822 (i & NI_NODEADDR_FLAG_ALL) ? "A" : "", 1823 (i & NI_NODEADDR_FLAG_TRUNCATE) ? "T" : "")); 1824 break; 1825 default: 1826 if (needcomma) 1827 ND_PRINT((ndo,", ")); 1828 ND_PRINT((ndo,"unknown")); 1829 break; 1830 } 1831 1832 /*(*/ 1833 ND_PRINT((ndo,")")); 1834 break; 1835 } 1836 return; 1837 1838 trunc: 1839 ND_PRINT((ndo, "[|icmp6]")); 1840 } 1841 1842 static void 1843 icmp6_rrenum_print(netdissect_options *ndo, const u_char *bp, const u_char *ep) 1844 { 1845 const struct icmp6_router_renum *rr6; 1846 const char *cp; 1847 struct rr_pco_match *match; 1848 struct rr_pco_use *use; 1849 char hbuf[NI_MAXHOST]; 1850 int n; 1851 1852 if (ep < bp) 1853 return; 1854 rr6 = (struct icmp6_router_renum *)bp; 1855 cp = (const char *)(rr6 + 1); 1856 1857 ND_TCHECK(rr6->rr_reserved); 1858 switch (rr6->rr_code) { 1859 case ICMP6_ROUTER_RENUMBERING_COMMAND: 1860 ND_PRINT((ndo,"router renum: command")); 1861 break; 1862 case ICMP6_ROUTER_RENUMBERING_RESULT: 1863 ND_PRINT((ndo,"router renum: result")); 1864 break; 1865 case ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET: 1866 ND_PRINT((ndo,"router renum: sequence number reset")); 1867 break; 1868 default: 1869 ND_PRINT((ndo,"router renum: code-#%d", rr6->rr_code)); 1870 break; 1871 } 1872 1873 ND_PRINT((ndo,", seq=%u", EXTRACT_32BITS(&rr6->rr_seqnum))); 1874 1875 if (ndo->ndo_vflag) { 1876 #define F(x, y) ((rr6->rr_flags) & (x) ? (y) : "") 1877 ND_PRINT((ndo,"[")); /*]*/ 1878 if (rr6->rr_flags) { 1879 ND_PRINT((ndo,"%s%s%s%s%s,", F(ICMP6_RR_FLAGS_TEST, "T"), 1880 F(ICMP6_RR_FLAGS_REQRESULT, "R"), 1881 F(ICMP6_RR_FLAGS_FORCEAPPLY, "A"), 1882 F(ICMP6_RR_FLAGS_SPECSITE, "S"), 1883 F(ICMP6_RR_FLAGS_PREVDONE, "P"))); 1884 } 1885 ND_PRINT((ndo,"seg=%u,", rr6->rr_segnum)); 1886 ND_PRINT((ndo,"maxdelay=%u", EXTRACT_16BITS(&rr6->rr_maxdelay))); 1887 if (rr6->rr_reserved) 1888 ND_PRINT((ndo,"rsvd=0x%x", EXTRACT_32BITS(&rr6->rr_reserved))); 1889 /*[*/ 1890 ND_PRINT((ndo,"]")); 1891 #undef F 1892 } 1893 1894 if (rr6->rr_code == ICMP6_ROUTER_RENUMBERING_COMMAND) { 1895 match = (struct rr_pco_match *)cp; 1896 cp = (const char *)(match + 1); 1897 1898 ND_TCHECK(match->rpm_prefix); 1899 1900 if (ndo->ndo_vflag > 1) 1901 ND_PRINT((ndo,"\n\t")); 1902 else 1903 ND_PRINT((ndo," ")); 1904 ND_PRINT((ndo,"match(")); /*)*/ 1905 switch (match->rpm_code) { 1906 case RPM_PCO_ADD: ND_PRINT((ndo,"add")); break; 1907 case RPM_PCO_CHANGE: ND_PRINT((ndo,"change")); break; 1908 case RPM_PCO_SETGLOBAL: ND_PRINT((ndo,"setglobal")); break; 1909 default: ND_PRINT((ndo,"#%u", match->rpm_code)); break; 1910 } 1911 1912 if (ndo->ndo_vflag) { 1913 ND_PRINT((ndo,",ord=%u", match->rpm_ordinal)); 1914 ND_PRINT((ndo,",min=%u", match->rpm_minlen)); 1915 ND_PRINT((ndo,",max=%u", match->rpm_maxlen)); 1916 } 1917 if (inet_ntop(AF_INET6, &match->rpm_prefix, hbuf, sizeof(hbuf))) 1918 ND_PRINT((ndo,",%s/%u", hbuf, match->rpm_matchlen)); 1919 else 1920 ND_PRINT((ndo,",?/%u", match->rpm_matchlen)); 1921 /*(*/ 1922 ND_PRINT((ndo,")")); 1923 1924 n = match->rpm_len - 3; 1925 if (n % 4) 1926 goto trunc; 1927 n /= 4; 1928 while (n-- > 0) { 1929 use = (struct rr_pco_use *)cp; 1930 cp = (const char *)(use + 1); 1931 1932 ND_TCHECK(use->rpu_prefix); 1933 1934 if (ndo->ndo_vflag > 1) 1935 ND_PRINT((ndo,"\n\t")); 1936 else 1937 ND_PRINT((ndo," ")); 1938 ND_PRINT((ndo,"use(")); /*)*/ 1939 if (use->rpu_flags) { 1940 #define F(x, y) ((use->rpu_flags) & (x) ? (y) : "") 1941 ND_PRINT((ndo,"%s%s,", 1942 F(ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME, "V"), 1943 F(ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME, "P"))); 1944 #undef F 1945 } 1946 if (ndo->ndo_vflag) { 1947 ND_PRINT((ndo,"mask=0x%x,", use->rpu_ramask)); 1948 ND_PRINT((ndo,"raflags=0x%x,", use->rpu_raflags)); 1949 if (~use->rpu_vltime == 0) 1950 ND_PRINT((ndo,"vltime=infty,")); 1951 else 1952 ND_PRINT((ndo,"vltime=%u,", 1953 EXTRACT_32BITS(&use->rpu_vltime))); 1954 if (~use->rpu_pltime == 0) 1955 ND_PRINT((ndo,"pltime=infty,")); 1956 else 1957 ND_PRINT((ndo,"pltime=%u,", 1958 EXTRACT_32BITS(&use->rpu_pltime))); 1959 } 1960 if (inet_ntop(AF_INET6, &use->rpu_prefix, hbuf, 1961 sizeof(hbuf))) 1962 ND_PRINT((ndo,"%s/%u/%u", hbuf, use->rpu_uselen, 1963 use->rpu_keeplen)); 1964 else 1965 ND_PRINT((ndo,"?/%u/%u", use->rpu_uselen, 1966 use->rpu_keeplen)); 1967 /*(*/ 1968 ND_PRINT((ndo,")")); 1969 } 1970 } 1971 1972 return; 1973 1974 trunc: 1975 ND_PRINT((ndo,"[|icmp6]")); 1976 } 1977 1978 #endif /* INET6 */ 1979 1980 /* 1981 * Local Variables: 1982 * c-style: whitesmith 1983 * c-basic-offset: 8 1984 * End: 1985 */ 1986