1b0453382SBill Fenner /* 2b0453382SBill Fenner * Copyright (c) 1988, 1989, 1990, 1991, 1993, 1994 3b0453382SBill Fenner * The Regents of the University of California. All rights reserved. 4b0453382SBill Fenner * 5b0453382SBill Fenner * Redistribution and use in source and binary forms, with or without 6b0453382SBill Fenner * modification, are permitted provided that: (1) source code distributions 7b0453382SBill Fenner * retain the above copyright notice and this paragraph in its entirety, (2) 8b0453382SBill Fenner * distributions including binary code include the above copyright notice and 9b0453382SBill Fenner * this paragraph in its entirety in the documentation or other materials 10b0453382SBill Fenner * provided with the distribution, and (3) all advertising materials mentioning 11b0453382SBill Fenner * features or use of this software display the following acknowledgement: 12b0453382SBill Fenner * ``This product includes software developed by the University of California, 13b0453382SBill Fenner * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 14b0453382SBill Fenner * the University nor the names of its contributors may be used to endorse 15b0453382SBill Fenner * or promote products derived from this software without specific prior 16b0453382SBill Fenner * written permission. 17b0453382SBill Fenner * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 18b0453382SBill Fenner * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 19b0453382SBill Fenner * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 20b0453382SBill Fenner */ 21b0453382SBill Fenner 22b0453382SBill Fenner #ifndef lint 235b0fe478SBruce M Simpson static const char rcsid[] _U_ = 242ebc47dbSSam Leffler "@(#) $Header: /tcpdump/master/tcpdump/print-icmp6.c,v 1.79.2.6 2005/09/05 09:29:28 guy Exp $"; 25b0453382SBill Fenner #endif 26b0453382SBill Fenner 27b0453382SBill Fenner #ifdef HAVE_CONFIG_H 28b0453382SBill Fenner #include "config.h" 29b0453382SBill Fenner #endif 30b0453382SBill Fenner 31b0453382SBill Fenner #ifdef INET6 32b0453382SBill Fenner 335b0fe478SBruce M Simpson #include <tcpdump-stdinc.h> 34b0453382SBill Fenner 35b0453382SBill Fenner #include <stdio.h> 36a90e161bSBill Fenner #include <string.h> 37b0453382SBill Fenner 38b0453382SBill Fenner #include "interface.h" 39b0453382SBill Fenner #include "addrtoname.h" 405b0fe478SBruce M Simpson #include "extract.h" 41b0453382SBill Fenner 42f4d0c64aSSam Leffler #include "ip6.h" 43f4d0c64aSSam Leffler #include "icmp6.h" 44f4d0c64aSSam Leffler #include "ipproto.h" 45f4d0c64aSSam Leffler 46685295f4SBill Fenner #include "udp.h" 47685295f4SBill Fenner #include "ah.h" 48685295f4SBill Fenner 49a90e161bSBill Fenner static const char *get_rtpref(u_int); 50a90e161bSBill Fenner static const char *get_lifetime(u_int32_t); 51a90e161bSBill Fenner static void print_lladdr(const u_char *, size_t); 525b0fe478SBruce M Simpson static void icmp6_opt_print(const u_char *, int); 535b0fe478SBruce M Simpson static void mld6_print(const u_char *); 541de50e9fSSam Leffler static void mldv2_report_print(const u_char *, u_int); 551de50e9fSSam Leffler static void mldv2_query_print(const u_char *, u_int); 565b0fe478SBruce M Simpson static struct udphdr *get_upperlayer(u_char *, u_int *); 57685295f4SBill Fenner static void dnsname_print(const u_char *, const u_char *); 585b0fe478SBruce M Simpson static void icmp6_nodeinfo_print(u_int, const u_char *, const u_char *); 595b0fe478SBruce M Simpson static void icmp6_rrenum_print(const u_char *, const u_char *); 60685295f4SBill Fenner 61685295f4SBill Fenner #ifndef abs 62685295f4SBill Fenner #define abs(a) ((0 < (a)) ? (a) : -(a)) 63685295f4SBill Fenner #endif 64b0453382SBill Fenner 651de50e9fSSam Leffler static struct tok icmp6_type_values[] = { 661de50e9fSSam Leffler { ICMP6_DST_UNREACH, "destination unreachable"}, 671de50e9fSSam Leffler { ICMP6_PACKET_TOO_BIG, "packet too big"}, 681de50e9fSSam Leffler { ICMP6_TIME_EXCEEDED, "time exceeded in-transit"}, 691de50e9fSSam Leffler { ICMP6_PARAM_PROB, "parameter problem"}, 701de50e9fSSam Leffler { ICMP6_ECHO_REQUEST, "echo request"}, 711de50e9fSSam Leffler { ICMP6_ECHO_REPLY, "echo reply"}, 721de50e9fSSam Leffler { MLD6_LISTENER_QUERY, "multicast listener query"}, 731de50e9fSSam Leffler { MLD6_LISTENER_REPORT, "multicast listener report"}, 741de50e9fSSam Leffler { MLD6_LISTENER_DONE, "multicast listener done"}, 751de50e9fSSam Leffler { ND_ROUTER_SOLICIT, "router solicitation"}, 761de50e9fSSam Leffler { ND_ROUTER_ADVERT, "router advertisement"}, 771de50e9fSSam Leffler { ND_NEIGHBOR_SOLICIT, "neighbor solicitation"}, 782ebc47dbSSam Leffler { ND_NEIGHBOR_ADVERT, "neighbor advertisement"}, 791de50e9fSSam Leffler { ND_REDIRECT, "redirect"}, 801de50e9fSSam Leffler { ICMP6_ROUTER_RENUMBERING, "router renumbering"}, 811de50e9fSSam Leffler { IND_SOLICIT, "inverse neighbor solicitation"}, 821de50e9fSSam Leffler { IND_ADVERT, "inverse neighbor advertisement"}, 831de50e9fSSam Leffler { MLDV2_LISTENER_REPORT, "multicast listener report v2"}, 841de50e9fSSam Leffler { ICMP6_HADISCOV_REQUEST, "ha discovery request"}, 851de50e9fSSam Leffler { ICMP6_HADISCOV_REPLY, "ha discovery reply"}, 861de50e9fSSam Leffler { ICMP6_MOBILEPREFIX_SOLICIT, "mobile router solicitation"}, 871de50e9fSSam Leffler { ICMP6_MOBILEPREFIX_ADVERT, "mobile router advertisement"}, 881de50e9fSSam Leffler { ICMP6_WRUREQUEST, "who-are-you request"}, 891de50e9fSSam Leffler { ICMP6_WRUREPLY, "who-are-you reply"}, 901de50e9fSSam Leffler { ICMP6_NI_QUERY, "node information query"}, 911de50e9fSSam Leffler { ICMP6_NI_REPLY, "node information reply"}, 921de50e9fSSam Leffler { MLD6_MTRACE, "mtrace message"}, 931de50e9fSSam Leffler { MLD6_MTRACE_RESP, "mtrace response"}, 941de50e9fSSam Leffler { 0, NULL } 951de50e9fSSam Leffler }; 961de50e9fSSam Leffler 971de50e9fSSam Leffler static struct tok icmp6_dst_unreach_code_values[] = { 981de50e9fSSam Leffler { ICMP6_DST_UNREACH_NOROUTE, "unreachable route" }, 991de50e9fSSam Leffler { ICMP6_DST_UNREACH_ADMIN, " unreachable prohibited"}, 1001de50e9fSSam Leffler { ICMP6_DST_UNREACH_BEYONDSCOPE, "beyond scope"}, 1011de50e9fSSam Leffler { ICMP6_DST_UNREACH_ADDR, "unreachable address"}, 1021de50e9fSSam Leffler { ICMP6_DST_UNREACH_NOPORT, "unreachable port"}, 1031de50e9fSSam Leffler { 0, NULL } 1041de50e9fSSam Leffler }; 1051de50e9fSSam Leffler 1061de50e9fSSam Leffler static struct tok icmp6_opt_pi_flag_values[] = { 1071de50e9fSSam Leffler { ND_OPT_PI_FLAG_ONLINK, "onlink" }, 1081de50e9fSSam Leffler { ND_OPT_PI_FLAG_AUTO, "auto" }, 1091de50e9fSSam Leffler { ND_OPT_PI_FLAG_ROUTER, "router" }, 1101de50e9fSSam Leffler { 0, NULL } 1111de50e9fSSam Leffler }; 1121de50e9fSSam Leffler 1131de50e9fSSam Leffler static struct tok icmp6_opt_ra_flag_values[] = { 1141de50e9fSSam Leffler { ND_RA_FLAG_MANAGED, "managed" }, 1151de50e9fSSam Leffler { ND_RA_FLAG_OTHER, "other stateful"}, 1161de50e9fSSam Leffler { ND_RA_FLAG_HOME_AGENT, "home agent"}, 1171de50e9fSSam Leffler { 0, NULL } 1181de50e9fSSam Leffler }; 1191de50e9fSSam Leffler 1201de50e9fSSam Leffler static struct tok icmp6_nd_na_flag_values[] = { 1211de50e9fSSam Leffler { ND_NA_FLAG_ROUTER, "router" }, 1221de50e9fSSam Leffler { ND_NA_FLAG_SOLICITED, "solicited" }, 1231de50e9fSSam Leffler { ND_NA_FLAG_OVERRIDE, "override" }, 1241de50e9fSSam Leffler { 0, NULL } 1251de50e9fSSam Leffler }; 1261de50e9fSSam Leffler 1271de50e9fSSam Leffler 1281de50e9fSSam Leffler static struct tok icmp6_opt_values[] = { 1291de50e9fSSam Leffler { ND_OPT_SOURCE_LINKADDR, "source link-address"}, 1301de50e9fSSam Leffler { ND_OPT_TARGET_LINKADDR, "destination link-address"}, 1311de50e9fSSam Leffler { ND_OPT_PREFIX_INFORMATION, "prefix info"}, 1321de50e9fSSam Leffler { ND_OPT_REDIRECTED_HEADER, "redirected header"}, 1331de50e9fSSam Leffler { ND_OPT_MTU, "mtu"}, 1342ebc47dbSSam Leffler { ND_OPT_ADVINTERVAL, "advertisement interval"}, 1351de50e9fSSam Leffler { ND_OPT_HOMEAGENT_INFO, "homeagent information"}, 1361de50e9fSSam Leffler { ND_OPT_ROUTE_INFO, "route info"}, 1371de50e9fSSam Leffler { 0, NULL } 1381de50e9fSSam Leffler }; 1391de50e9fSSam Leffler 1401de50e9fSSam Leffler /* mldv2 report types */ 1411de50e9fSSam Leffler static struct tok mldv2report2str[] = { 1421de50e9fSSam Leffler { 1, "is_in" }, 1431de50e9fSSam Leffler { 2, "is_ex" }, 1441de50e9fSSam Leffler { 3, "to_in" }, 1451de50e9fSSam Leffler { 4, "to_ex" }, 1461de50e9fSSam Leffler { 5, "allow" }, 1471de50e9fSSam Leffler { 6, "block" }, 1481de50e9fSSam Leffler { 0, NULL } 1491de50e9fSSam Leffler }; 1501de50e9fSSam Leffler 151a90e161bSBill Fenner static const char * 152a90e161bSBill Fenner get_rtpref(u_int v) 153a90e161bSBill Fenner { 154a90e161bSBill Fenner static const char *rtpref_str[] = { 155a90e161bSBill Fenner "medium", /* 00 */ 156a90e161bSBill Fenner "high", /* 01 */ 157a90e161bSBill Fenner "rsv", /* 10 */ 158a90e161bSBill Fenner "low" /* 11 */ 159a90e161bSBill Fenner }; 160a90e161bSBill Fenner 161a90e161bSBill Fenner return rtpref_str[((v & ND_RA_FLAG_RTPREF_MASK) >> 3) & 0xff]; 162a90e161bSBill Fenner } 163a90e161bSBill Fenner 164a90e161bSBill Fenner static const char * 165a90e161bSBill Fenner get_lifetime(u_int32_t v) 166a90e161bSBill Fenner { 167a90e161bSBill Fenner static char buf[20]; 168a90e161bSBill Fenner 169a90e161bSBill Fenner if (v == (u_int32_t)~0UL) 170a90e161bSBill Fenner return "infinity"; 171a90e161bSBill Fenner else { 172a90e161bSBill Fenner snprintf(buf, sizeof(buf), "%u", v); 173a90e161bSBill Fenner return buf; 174a90e161bSBill Fenner } 175a90e161bSBill Fenner } 176a90e161bSBill Fenner 177a90e161bSBill Fenner static void 178a90e161bSBill Fenner print_lladdr(const u_int8_t *p, size_t l) 179a90e161bSBill Fenner { 180a90e161bSBill Fenner const u_int8_t *ep, *q; 181a90e161bSBill Fenner 182a90e161bSBill Fenner q = p; 183a90e161bSBill Fenner ep = p + l; 184a90e161bSBill Fenner while (l > 0 && q < ep) { 185a90e161bSBill Fenner if (q > p) 186a90e161bSBill Fenner printf(":"); 187a90e161bSBill Fenner printf("%02x", *q++); 188a90e161bSBill Fenner l--; 189a90e161bSBill Fenner } 190a90e161bSBill Fenner } 191a90e161bSBill Fenner 1925b0fe478SBruce M Simpson static int icmp6_cksum(const struct ip6_hdr *ip6, const struct icmp6_hdr *icp, 1935b0fe478SBruce M Simpson u_int len) 1945b0fe478SBruce M Simpson { 1955b0fe478SBruce M Simpson size_t i; 1965b0fe478SBruce M Simpson register const u_int16_t *sp; 1975b0fe478SBruce M Simpson u_int32_t sum; 1985b0fe478SBruce M Simpson union { 1995b0fe478SBruce M Simpson struct { 2005b0fe478SBruce M Simpson struct in6_addr ph_src; 2015b0fe478SBruce M Simpson struct in6_addr ph_dst; 2025b0fe478SBruce M Simpson u_int32_t ph_len; 2035b0fe478SBruce M Simpson u_int8_t ph_zero[3]; 2045b0fe478SBruce M Simpson u_int8_t ph_nxt; 2055b0fe478SBruce M Simpson } ph; 2065b0fe478SBruce M Simpson u_int16_t pa[20]; 2075b0fe478SBruce M Simpson } phu; 2085b0fe478SBruce M Simpson 2095b0fe478SBruce M Simpson /* pseudo-header */ 2105b0fe478SBruce M Simpson memset(&phu, 0, sizeof(phu)); 2115b0fe478SBruce M Simpson phu.ph.ph_src = ip6->ip6_src; 2125b0fe478SBruce M Simpson phu.ph.ph_dst = ip6->ip6_dst; 2135b0fe478SBruce M Simpson phu.ph.ph_len = htonl(len); 2145b0fe478SBruce M Simpson phu.ph.ph_nxt = IPPROTO_ICMPV6; 2155b0fe478SBruce M Simpson 2165b0fe478SBruce M Simpson sum = 0; 2175b0fe478SBruce M Simpson for (i = 0; i < sizeof(phu.pa) / sizeof(phu.pa[0]); i++) 2185b0fe478SBruce M Simpson sum += phu.pa[i]; 2195b0fe478SBruce M Simpson 2205b0fe478SBruce M Simpson sp = (const u_int16_t *)icp; 2215b0fe478SBruce M Simpson 2225b0fe478SBruce M Simpson for (i = 0; i < (len & ~1); i += 2) 2235b0fe478SBruce M Simpson sum += *sp++; 2245b0fe478SBruce M Simpson 2255b0fe478SBruce M Simpson if (len & 1) 2265b0fe478SBruce M Simpson sum += htons((*(const u_int8_t *)sp) << 8); 2275b0fe478SBruce M Simpson 2285b0fe478SBruce M Simpson while (sum > 0xffff) 2295b0fe478SBruce M Simpson sum = (sum & 0xffff) + (sum >> 16); 2305b0fe478SBruce M Simpson sum = ~sum & 0xffff; 2315b0fe478SBruce M Simpson 2325b0fe478SBruce M Simpson return (sum); 2335b0fe478SBruce M Simpson } 2345b0fe478SBruce M Simpson 235b0453382SBill Fenner void 2365b0fe478SBruce M Simpson icmp6_print(const u_char *bp, u_int length, const u_char *bp2, int fragmented) 237b0453382SBill Fenner { 238685295f4SBill Fenner const struct icmp6_hdr *dp; 239a90e161bSBill Fenner const struct ip6_hdr *ip; 240a90e161bSBill Fenner const struct ip6_hdr *oip; 241a90e161bSBill Fenner const struct udphdr *ouh; 242a90e161bSBill Fenner int dport; 243a90e161bSBill Fenner const u_char *ep; 2445b0fe478SBruce M Simpson u_int prot; 245b0453382SBill Fenner 246b0453382SBill Fenner dp = (struct icmp6_hdr *)bp; 247b0453382SBill Fenner ip = (struct ip6_hdr *)bp2; 248b0453382SBill Fenner oip = (struct ip6_hdr *)(dp + 1); 249685295f4SBill Fenner /* 'ep' points to the end of available data. */ 250b0453382SBill Fenner ep = snapend; 251b0453382SBill Fenner 2525b0fe478SBruce M Simpson TCHECK(dp->icmp6_cksum); 2535b0fe478SBruce M Simpson 2545b0fe478SBruce M Simpson if (vflag && !fragmented) { 2555b0fe478SBruce M Simpson int sum = dp->icmp6_cksum; 2565b0fe478SBruce M Simpson 2575b0fe478SBruce M Simpson if (TTEST2(bp[0], length)) { 2585b0fe478SBruce M Simpson sum = icmp6_cksum(ip, dp, length); 2595b0fe478SBruce M Simpson if (sum != 0) 2605b0fe478SBruce M Simpson (void)printf("[bad icmp6 cksum %x!] ", sum); 2615b0fe478SBruce M Simpson else 2625b0fe478SBruce M Simpson (void)printf("[icmp6 sum ok] "); 2635b0fe478SBruce M Simpson } 2645b0fe478SBruce M Simpson } 2655b0fe478SBruce M Simpson 2661de50e9fSSam Leffler printf("ICMP6, %s", tok2str(icmp6_type_values,"unknown icmp6 type (%u)",dp->icmp6_type)); 2671de50e9fSSam Leffler 2681de50e9fSSam Leffler /* display cosmetics: print the packet length for printer that use the vflag now */ 2691de50e9fSSam Leffler if (vflag && (dp->icmp6_type == 2701de50e9fSSam Leffler ND_ROUTER_SOLICIT || 2711de50e9fSSam Leffler ND_ROUTER_ADVERT || 2721de50e9fSSam Leffler ND_NEIGHBOR_ADVERT || 2731de50e9fSSam Leffler ND_NEIGHBOR_SOLICIT || 2741de50e9fSSam Leffler ND_REDIRECT || 2751de50e9fSSam Leffler ICMP6_HADISCOV_REPLY || 2761de50e9fSSam Leffler ICMP6_MOBILEPREFIX_ADVERT )) 2771de50e9fSSam Leffler printf(", length %u", length); 2781de50e9fSSam Leffler 279b0453382SBill Fenner switch (dp->icmp6_type) { 280b0453382SBill Fenner case ICMP6_DST_UNREACH: 281b0453382SBill Fenner TCHECK(oip->ip6_dst); 2821de50e9fSSam Leffler printf(", %s", tok2str(icmp6_dst_unreach_code_values,"unknown unreach code (%u)",dp->icmp6_code)); 283b0453382SBill Fenner switch (dp->icmp6_code) { 2841de50e9fSSam Leffler 2851de50e9fSSam Leffler case ICMP6_DST_UNREACH_NOROUTE: /* fall through */ 286b0453382SBill Fenner case ICMP6_DST_UNREACH_ADMIN: 2871de50e9fSSam Leffler case ICMP6_DST_UNREACH_ADDR: 2881de50e9fSSam Leffler printf(" %s",ip6addr_string(&oip->ip6_dst)); 289b0453382SBill Fenner break; 290b0453382SBill Fenner case ICMP6_DST_UNREACH_BEYONDSCOPE: 2911de50e9fSSam Leffler printf(" %s, source address %s", 292b0453382SBill Fenner ip6addr_string(&oip->ip6_dst), 293b0453382SBill Fenner ip6addr_string(&oip->ip6_src)); 294b0453382SBill Fenner break; 295b0453382SBill Fenner case ICMP6_DST_UNREACH_NOPORT: 296685295f4SBill Fenner if ((ouh = get_upperlayer((u_char *)oip, &prot)) 297685295f4SBill Fenner == NULL) 298685295f4SBill Fenner goto trunc; 299685295f4SBill Fenner 3005b0fe478SBruce M Simpson dport = EXTRACT_16BITS(&ouh->uh_dport); 301685295f4SBill Fenner switch (prot) { 302b0453382SBill Fenner case IPPROTO_TCP: 3031de50e9fSSam Leffler printf(", %s tcp port %s", 304b0453382SBill Fenner ip6addr_string(&oip->ip6_dst), 305b0453382SBill Fenner tcpport_string(dport)); 306b0453382SBill Fenner break; 307b0453382SBill Fenner case IPPROTO_UDP: 3081de50e9fSSam Leffler printf(", %s udp port %s", 309b0453382SBill Fenner ip6addr_string(&oip->ip6_dst), 310b0453382SBill Fenner udpport_string(dport)); 311b0453382SBill Fenner break; 312b0453382SBill Fenner default: 3131de50e9fSSam Leffler printf(", %s protocol %d port %d unreachable", 314b0453382SBill Fenner ip6addr_string(&oip->ip6_dst), 315b0453382SBill Fenner oip->ip6_nxt, dport); 316b0453382SBill Fenner break; 317b0453382SBill Fenner } 318b0453382SBill Fenner break; 319b0453382SBill Fenner default: 3201de50e9fSSam Leffler if (vflag <= 1) { 3211de50e9fSSam Leffler print_unknown_data(bp,"\n\t",length); 3221de50e9fSSam Leffler return; 3231de50e9fSSam Leffler } 324b0453382SBill Fenner break; 325b0453382SBill Fenner } 326b0453382SBill Fenner break; 327b0453382SBill Fenner case ICMP6_PACKET_TOO_BIG: 328b0453382SBill Fenner TCHECK(dp->icmp6_mtu); 3291de50e9fSSam Leffler printf(", mtu %u", EXTRACT_32BITS(&dp->icmp6_mtu)); 330b0453382SBill Fenner break; 331b0453382SBill Fenner case ICMP6_TIME_EXCEEDED: 332b0453382SBill Fenner TCHECK(oip->ip6_dst); 333b0453382SBill Fenner switch (dp->icmp6_code) { 334b0453382SBill Fenner case ICMP6_TIME_EXCEED_TRANSIT: 3351de50e9fSSam Leffler printf(" for %s", 336b0453382SBill Fenner ip6addr_string(&oip->ip6_dst)); 337b0453382SBill Fenner break; 338b0453382SBill Fenner case ICMP6_TIME_EXCEED_REASSEMBLY: 3391de50e9fSSam Leffler printf(" (reassembly)"); 340b0453382SBill Fenner break; 341b0453382SBill Fenner default: 3421de50e9fSSam Leffler printf(", unknown code (%u)", dp->icmp6_code); 343b0453382SBill Fenner break; 344b0453382SBill Fenner } 345b0453382SBill Fenner break; 346b0453382SBill Fenner case ICMP6_PARAM_PROB: 347b0453382SBill Fenner TCHECK(oip->ip6_dst); 348b0453382SBill Fenner switch (dp->icmp6_code) { 349b0453382SBill Fenner case ICMP6_PARAMPROB_HEADER: 3501de50e9fSSam Leffler printf(", errorneous - octet %u", EXTRACT_32BITS(&dp->icmp6_pptr)); 351b0453382SBill Fenner break; 352b0453382SBill Fenner case ICMP6_PARAMPROB_NEXTHEADER: 3531de50e9fSSam Leffler printf(", next header - octet %u", EXTRACT_32BITS(&dp->icmp6_pptr)); 354b0453382SBill Fenner break; 355b0453382SBill Fenner case ICMP6_PARAMPROB_OPTION: 3561de50e9fSSam Leffler printf(", option - octet %u", EXTRACT_32BITS(&dp->icmp6_pptr)); 357b0453382SBill Fenner break; 358b0453382SBill Fenner default: 3591de50e9fSSam Leffler printf(", code-#%d", 360b0453382SBill Fenner dp->icmp6_code); 361b0453382SBill Fenner break; 362b0453382SBill Fenner } 363b0453382SBill Fenner break; 364b0453382SBill Fenner case ICMP6_ECHO_REQUEST: 365b0453382SBill Fenner case ICMP6_ECHO_REPLY: 3665b0fe478SBruce M Simpson TCHECK(dp->icmp6_seq); 3671de50e9fSSam Leffler printf(", seq %u", EXTRACT_16BITS(&dp->icmp6_seq)); 368b0453382SBill Fenner break; 369b0453382SBill Fenner case ICMP6_MEMBERSHIP_QUERY: 3701de50e9fSSam Leffler if (length == MLD_MINLEN) { 371b0453382SBill Fenner mld6_print((const u_char *)dp); 3721de50e9fSSam Leffler } else if (length >= MLDV2_MINLEN) { 3731de50e9fSSam Leffler printf("v2 "); 3741de50e9fSSam Leffler mldv2_query_print((const u_char *)dp, length); 3751de50e9fSSam Leffler } else { 3761de50e9fSSam Leffler printf(" unknown-version (len %u) ", length); 3771de50e9fSSam Leffler } 378b0453382SBill Fenner break; 379b0453382SBill Fenner case ICMP6_MEMBERSHIP_REPORT: 380b0453382SBill Fenner mld6_print((const u_char *)dp); 381b0453382SBill Fenner break; 382b0453382SBill Fenner case ICMP6_MEMBERSHIP_REDUCTION: 383b0453382SBill Fenner mld6_print((const u_char *)dp); 384b0453382SBill Fenner break; 385b0453382SBill Fenner case ND_ROUTER_SOLICIT: 386b0453382SBill Fenner #define RTSOLLEN 8 3871de50e9fSSam Leffler if (vflag) { 388b0453382SBill Fenner icmp6_opt_print((const u_char *)dp + RTSOLLEN, 3895b0fe478SBruce M Simpson length - RTSOLLEN); 390b0453382SBill Fenner } 391b0453382SBill Fenner break; 392b0453382SBill Fenner case ND_ROUTER_ADVERT: 3931de50e9fSSam Leffler #define RTADVLEN 16 394b0453382SBill Fenner if (vflag) { 395b0453382SBill Fenner struct nd_router_advert *p; 396b0453382SBill Fenner 397b0453382SBill Fenner p = (struct nd_router_advert *)dp; 398b0453382SBill Fenner TCHECK(p->nd_ra_retransmit); 3991de50e9fSSam Leffler printf("\n\thop limit %u, Flags [%s]" \ 4001de50e9fSSam Leffler ", pref %s, router lifetime %us, reachable time %us, retrans time %us", 4011de50e9fSSam Leffler (u_int)p->nd_ra_curhoplimit, 4021de50e9fSSam Leffler bittok2str(icmp6_opt_ra_flag_values,"none",(p->nd_ra_flags_reserved)), 4031de50e9fSSam Leffler get_rtpref(p->nd_ra_flags_reserved), 4041de50e9fSSam Leffler EXTRACT_16BITS(&p->nd_ra_router_lifetime), 4051de50e9fSSam Leffler EXTRACT_32BITS(&p->nd_ra_reachable), 4065b0fe478SBruce M Simpson EXTRACT_32BITS(&p->nd_ra_retransmit)); 4071de50e9fSSam Leffler 408b0453382SBill Fenner icmp6_opt_print((const u_char *)dp + RTADVLEN, 4095b0fe478SBruce M Simpson length - RTADVLEN); 410b0453382SBill Fenner } 411b0453382SBill Fenner break; 412b0453382SBill Fenner case ND_NEIGHBOR_SOLICIT: 413b0453382SBill Fenner { 414b0453382SBill Fenner struct nd_neighbor_solicit *p; 415b0453382SBill Fenner p = (struct nd_neighbor_solicit *)dp; 416b0453382SBill Fenner TCHECK(p->nd_ns_target); 4171de50e9fSSam Leffler printf(", who has %s", ip6addr_string(&p->nd_ns_target)); 418b0453382SBill Fenner if (vflag) { 419b0453382SBill Fenner #define NDSOLLEN 24 420b0453382SBill Fenner icmp6_opt_print((const u_char *)dp + NDSOLLEN, 4215b0fe478SBruce M Simpson length - NDSOLLEN); 422b0453382SBill Fenner } 423b0453382SBill Fenner } 424b0453382SBill Fenner break; 425b0453382SBill Fenner case ND_NEIGHBOR_ADVERT: 426b0453382SBill Fenner { 427b0453382SBill Fenner struct nd_neighbor_advert *p; 428b0453382SBill Fenner 429b0453382SBill Fenner p = (struct nd_neighbor_advert *)dp; 430b0453382SBill Fenner TCHECK(p->nd_na_target); 4311de50e9fSSam Leffler printf(", tgt is %s", 432b0453382SBill Fenner ip6addr_string(&p->nd_na_target)); 433b0453382SBill Fenner if (vflag) { 4341de50e9fSSam Leffler printf(", Flags [%s]", 4351de50e9fSSam Leffler bittok2str(icmp6_nd_na_flag_values, 4361de50e9fSSam Leffler "none", 4371de50e9fSSam Leffler EXTRACT_32BITS(&p->nd_na_flags_reserved))); 438b0453382SBill Fenner #define NDADVLEN 24 439b0453382SBill Fenner icmp6_opt_print((const u_char *)dp + NDADVLEN, 4405b0fe478SBruce M Simpson length - NDADVLEN); 441685295f4SBill Fenner #undef NDADVLEN 442b0453382SBill Fenner } 443b0453382SBill Fenner } 444b0453382SBill Fenner break; 445b0453382SBill Fenner case ND_REDIRECT: 446b0453382SBill Fenner #define RDR(i) ((struct nd_redirect *)(i)) 447b0453382SBill Fenner TCHECK(RDR(dp)->nd_rd_dst); 4481de50e9fSSam Leffler printf(", %s", getname6((const u_char *)&RDR(dp)->nd_rd_dst)); 4495b0fe478SBruce M Simpson TCHECK(RDR(dp)->nd_rd_target); 450685295f4SBill Fenner printf(" to %s", 451685295f4SBill Fenner getname6((const u_char*)&RDR(dp)->nd_rd_target)); 452b0453382SBill Fenner #define REDIRECTLEN 40 453b0453382SBill Fenner if (vflag) { 454b0453382SBill Fenner icmp6_opt_print((const u_char *)dp + REDIRECTLEN, 4555b0fe478SBruce M Simpson length - REDIRECTLEN); 456b0453382SBill Fenner } 457b0453382SBill Fenner break; 458685295f4SBill Fenner #undef REDIRECTLEN 459685295f4SBill Fenner #undef RDR 460b0453382SBill Fenner case ICMP6_ROUTER_RENUMBERING: 4615b0fe478SBruce M Simpson icmp6_rrenum_print(bp, ep); 462b0453382SBill Fenner break; 463685295f4SBill Fenner case ICMP6_NI_QUERY: 464685295f4SBill Fenner case ICMP6_NI_REPLY: 4655b0fe478SBruce M Simpson icmp6_nodeinfo_print(length, bp, ep); 4665b0fe478SBruce M Simpson break; 4671de50e9fSSam Leffler case IND_SOLICIT: 4681de50e9fSSam Leffler case IND_ADVERT: 4691de50e9fSSam Leffler break; 4701de50e9fSSam Leffler case ICMP6_V2_MEMBERSHIP_REPORT: 4711de50e9fSSam Leffler mldv2_report_print((const u_char *) dp, length); 4721de50e9fSSam Leffler break; 4731de50e9fSSam Leffler case ICMP6_MOBILEPREFIX_SOLICIT: /* fall through */ 4745b0fe478SBruce M Simpson case ICMP6_HADISCOV_REQUEST: 4755b0fe478SBruce M Simpson TCHECK(dp->icmp6_data16[0]); 4761de50e9fSSam Leffler printf(", id 0x%04x", EXTRACT_16BITS(&dp->icmp6_data16[0])); 4775b0fe478SBruce M Simpson break; 4785b0fe478SBruce M Simpson case ICMP6_HADISCOV_REPLY: 4795b0fe478SBruce M Simpson if (vflag) { 4805b0fe478SBruce M Simpson struct in6_addr *in6; 4815b0fe478SBruce M Simpson u_char *cp; 4825b0fe478SBruce M Simpson 4835b0fe478SBruce M Simpson TCHECK(dp->icmp6_data16[0]); 4841de50e9fSSam Leffler printf(", id 0x%04x", EXTRACT_16BITS(&dp->icmp6_data16[0])); 4855b0fe478SBruce M Simpson cp = (u_char *)dp + length; 4865b0fe478SBruce M Simpson in6 = (struct in6_addr *)(dp + 1); 4875b0fe478SBruce M Simpson for (; (u_char *)in6 < cp; in6++) { 4885b0fe478SBruce M Simpson TCHECK(*in6); 4895b0fe478SBruce M Simpson printf(", %s", ip6addr_string(in6)); 4905b0fe478SBruce M Simpson } 4915b0fe478SBruce M Simpson } 4925b0fe478SBruce M Simpson break; 4935b0fe478SBruce M Simpson case ICMP6_MOBILEPREFIX_ADVERT: 4945b0fe478SBruce M Simpson if (vflag) { 4955b0fe478SBruce M Simpson TCHECK(dp->icmp6_data16[0]); 4961de50e9fSSam Leffler printf(", id 0x%04x", EXTRACT_16BITS(&dp->icmp6_data16[0])); 4975b0fe478SBruce M Simpson if (dp->icmp6_data16[1] & 0xc0) 4985b0fe478SBruce M Simpson printf(" "); 4995b0fe478SBruce M Simpson if (dp->icmp6_data16[1] & 0x80) 5005b0fe478SBruce M Simpson printf("M"); 5015b0fe478SBruce M Simpson if (dp->icmp6_data16[1] & 0x40) 5025b0fe478SBruce M Simpson printf("O"); 5035b0fe478SBruce M Simpson #define MPADVLEN 8 5045b0fe478SBruce M Simpson icmp6_opt_print((const u_char *)dp + MPADVLEN, 5055b0fe478SBruce M Simpson length - MPADVLEN); 5065b0fe478SBruce M Simpson } 507b0453382SBill Fenner break; 508b0453382SBill Fenner default: 5091de50e9fSSam Leffler printf(", length %u", length); 5101de50e9fSSam Leffler if (vflag <= 1) 5111de50e9fSSam Leffler print_unknown_data(bp,"\n\t", length); 5121de50e9fSSam Leffler return; 513b0453382SBill Fenner } 5141de50e9fSSam Leffler if (!vflag) 5151de50e9fSSam Leffler printf(", length %u", length); 516b0453382SBill Fenner return; 517b0453382SBill Fenner trunc: 518b0453382SBill Fenner fputs("[|icmp6]", stdout); 519b0453382SBill Fenner } 520b0453382SBill Fenner 521685295f4SBill Fenner static struct udphdr * 5225b0fe478SBruce M Simpson get_upperlayer(u_char *bp, u_int *prot) 523685295f4SBill Fenner { 524a90e161bSBill Fenner const u_char *ep; 525685295f4SBill Fenner struct ip6_hdr *ip6 = (struct ip6_hdr *)bp; 526685295f4SBill Fenner struct udphdr *uh; 527685295f4SBill Fenner struct ip6_hbh *hbh; 528685295f4SBill Fenner struct ip6_frag *fragh; 529685295f4SBill Fenner struct ah *ah; 5305b0fe478SBruce M Simpson u_int nh; 5315b0fe478SBruce M Simpson int hlen; 532685295f4SBill Fenner 533685295f4SBill Fenner /* 'ep' points to the end of available data. */ 534685295f4SBill Fenner ep = snapend; 535685295f4SBill Fenner 5365b0fe478SBruce M Simpson if (!TTEST(ip6->ip6_nxt)) 537685295f4SBill Fenner return NULL; 538685295f4SBill Fenner 539685295f4SBill Fenner nh = ip6->ip6_nxt; 540685295f4SBill Fenner hlen = sizeof(struct ip6_hdr); 541685295f4SBill Fenner 542f4d0c64aSSam Leffler while (bp < ep) { 543685295f4SBill Fenner bp += hlen; 544685295f4SBill Fenner 545685295f4SBill Fenner switch(nh) { 546685295f4SBill Fenner case IPPROTO_UDP: 547685295f4SBill Fenner case IPPROTO_TCP: 548685295f4SBill Fenner uh = (struct udphdr *)bp; 549685295f4SBill Fenner if (TTEST(uh->uh_dport)) { 550685295f4SBill Fenner *prot = nh; 551685295f4SBill Fenner return(uh); 552685295f4SBill Fenner } 553685295f4SBill Fenner else 554685295f4SBill Fenner return(NULL); 555685295f4SBill Fenner /* NOTREACHED */ 556685295f4SBill Fenner 557685295f4SBill Fenner case IPPROTO_HOPOPTS: 558685295f4SBill Fenner case IPPROTO_DSTOPTS: 559685295f4SBill Fenner case IPPROTO_ROUTING: 560685295f4SBill Fenner hbh = (struct ip6_hbh *)bp; 5615b0fe478SBruce M Simpson if (!TTEST(hbh->ip6h_len)) 562685295f4SBill Fenner return(NULL); 563685295f4SBill Fenner nh = hbh->ip6h_nxt; 564685295f4SBill Fenner hlen = (hbh->ip6h_len + 1) << 3; 565685295f4SBill Fenner break; 566685295f4SBill Fenner 567685295f4SBill Fenner case IPPROTO_FRAGMENT: /* this should be odd, but try anyway */ 568685295f4SBill Fenner fragh = (struct ip6_frag *)bp; 5695b0fe478SBruce M Simpson if (!TTEST(fragh->ip6f_offlg)) 570685295f4SBill Fenner return(NULL); 571685295f4SBill Fenner /* fragments with non-zero offset are meaningless */ 5725b0fe478SBruce M Simpson if ((EXTRACT_16BITS(&fragh->ip6f_offlg) & IP6F_OFF_MASK) != 0) 573685295f4SBill Fenner return(NULL); 574685295f4SBill Fenner nh = fragh->ip6f_nxt; 575685295f4SBill Fenner hlen = sizeof(struct ip6_frag); 576685295f4SBill Fenner break; 577685295f4SBill Fenner 578685295f4SBill Fenner case IPPROTO_AH: 579685295f4SBill Fenner ah = (struct ah *)bp; 5805b0fe478SBruce M Simpson if (!TTEST(ah->ah_len)) 581685295f4SBill Fenner return(NULL); 582685295f4SBill Fenner nh = ah->ah_nxt; 583685295f4SBill Fenner hlen = (ah->ah_len + 2) << 2; 584685295f4SBill Fenner break; 585685295f4SBill Fenner 586685295f4SBill Fenner default: /* unknown or undecodable header */ 587685295f4SBill Fenner *prot = nh; /* meaningless, but set here anyway */ 588685295f4SBill Fenner return(NULL); 589685295f4SBill Fenner } 590685295f4SBill Fenner } 591685295f4SBill Fenner 592685295f4SBill Fenner return(NULL); /* should be notreached, though */ 593685295f4SBill Fenner } 594685295f4SBill Fenner 5955b0fe478SBruce M Simpson static void 596a90e161bSBill Fenner icmp6_opt_print(const u_char *bp, int resid) 597b0453382SBill Fenner { 598a90e161bSBill Fenner const struct nd_opt_hdr *op; 599a90e161bSBill Fenner const struct nd_opt_hdr *opl; /* why there's no struct? */ 600a90e161bSBill Fenner const struct nd_opt_prefix_info *opp; 601a90e161bSBill Fenner const struct icmp6_opts_redirect *opr; 602a90e161bSBill Fenner const struct nd_opt_mtu *opm; 603a90e161bSBill Fenner const struct nd_opt_advinterval *opa; 6045b0fe478SBruce M Simpson const struct nd_opt_homeagent_info *oph; 605a90e161bSBill Fenner const struct nd_opt_route_info *opri; 606a90e161bSBill Fenner const u_char *cp, *ep; 607a90e161bSBill Fenner struct in6_addr in6, *in6p; 608a90e161bSBill Fenner size_t l; 609b0453382SBill Fenner 610b0453382SBill Fenner #define ECHECK(var) if ((u_char *)&(var) > ep - sizeof(var)) return 611b0453382SBill Fenner 612a90e161bSBill Fenner cp = bp; 613685295f4SBill Fenner /* 'ep' points to the end of available data. */ 614b0453382SBill Fenner ep = snapend; 615b0453382SBill Fenner 616a90e161bSBill Fenner while (cp < ep) { 617a90e161bSBill Fenner op = (struct nd_opt_hdr *)cp; 618a90e161bSBill Fenner 619b0453382SBill Fenner ECHECK(op->nd_opt_len); 620b0453382SBill Fenner if (resid <= 0) 621b0453382SBill Fenner return; 622a90e161bSBill Fenner if (op->nd_opt_len == 0) 623a90e161bSBill Fenner goto trunc; 624a90e161bSBill Fenner if (cp + (op->nd_opt_len << 3) > ep) 625a90e161bSBill Fenner goto trunc; 626a90e161bSBill Fenner 6271de50e9fSSam Leffler printf("\n\t %s option (%u), length %u (%u): ", 6281de50e9fSSam Leffler tok2str(icmp6_opt_values, "unknown", op->nd_opt_type), 6291de50e9fSSam Leffler op->nd_opt_type, 6301de50e9fSSam Leffler op->nd_opt_len << 3, 6311de50e9fSSam Leffler op->nd_opt_len); 6321de50e9fSSam Leffler 633b0453382SBill Fenner switch (op->nd_opt_type) { 634b0453382SBill Fenner case ND_OPT_SOURCE_LINKADDR: 635b0453382SBill Fenner opl = (struct nd_opt_hdr *)op; 636a90e161bSBill Fenner l = (op->nd_opt_len << 3) - 2; 637a90e161bSBill Fenner print_lladdr(cp + 2, l); 638b0453382SBill Fenner break; 639b0453382SBill Fenner case ND_OPT_TARGET_LINKADDR: 640b0453382SBill Fenner opl = (struct nd_opt_hdr *)op; 641a90e161bSBill Fenner l = (op->nd_opt_len << 3) - 2; 642a90e161bSBill Fenner print_lladdr(cp + 2, l); 643b0453382SBill Fenner break; 644b0453382SBill Fenner case ND_OPT_PREFIX_INFORMATION: 645b0453382SBill Fenner opp = (struct nd_opt_prefix_info *)op; 646b0453382SBill Fenner TCHECK(opp->nd_opt_pi_prefix); 6471de50e9fSSam Leffler printf("%s/%u%s, Flags [%s], valid time %ss", 648a90e161bSBill Fenner ip6addr_string(&opp->nd_opt_pi_prefix), 6491de50e9fSSam Leffler opp->nd_opt_pi_prefix_len, 6501de50e9fSSam Leffler (op->nd_opt_len != 4) ? "badlen" : "", 6511de50e9fSSam Leffler bittok2str(icmp6_opt_pi_flag_values, "none", opp->nd_opt_pi_flags_reserved), 6521de50e9fSSam Leffler get_lifetime(EXTRACT_32BITS(&opp->nd_opt_pi_valid_time))); 6531de50e9fSSam Leffler printf(", pref. time %ss", get_lifetime(EXTRACT_32BITS(&opp->nd_opt_pi_preferred_time))); 654b0453382SBill Fenner break; 655b0453382SBill Fenner case ND_OPT_REDIRECTED_HEADER: 656b0453382SBill Fenner opr = (struct icmp6_opts_redirect *)op; 6571de50e9fSSam Leffler print_unknown_data(bp,"\n\t ",op->nd_opt_len<<3); 658b0453382SBill Fenner /* xxx */ 659b0453382SBill Fenner break; 660b0453382SBill Fenner case ND_OPT_MTU: 661b0453382SBill Fenner opm = (struct nd_opt_mtu *)op; 662b0453382SBill Fenner TCHECK(opm->nd_opt_mtu_mtu); 6631de50e9fSSam Leffler printf(" %u%s", 6641de50e9fSSam Leffler EXTRACT_32BITS(&opm->nd_opt_mtu_mtu), 6651de50e9fSSam Leffler (op->nd_opt_len != 1) ? "bad option length" : "" ); 666b0453382SBill Fenner break; 667a90e161bSBill Fenner case ND_OPT_ADVINTERVAL: 668a90e161bSBill Fenner opa = (struct nd_opt_advinterval *)op; 669a90e161bSBill Fenner TCHECK(opa->nd_opt_adv_interval); 6701de50e9fSSam Leffler printf(" %us", EXTRACT_32BITS(&opa->nd_opt_adv_interval)); 671a90e161bSBill Fenner break; 6725b0fe478SBruce M Simpson case ND_OPT_HOMEAGENT_INFO: 6735b0fe478SBruce M Simpson oph = (struct nd_opt_homeagent_info *)op; 6745b0fe478SBruce M Simpson TCHECK(oph->nd_opt_hai_lifetime); 6751de50e9fSSam Leffler printf(" preference %u, lifetime %u", 6761de50e9fSSam Leffler EXTRACT_16BITS(&oph->nd_opt_hai_preference), 6771de50e9fSSam Leffler EXTRACT_16BITS(&oph->nd_opt_hai_lifetime)); 6785b0fe478SBruce M Simpson break; 679a90e161bSBill Fenner case ND_OPT_ROUTE_INFO: 680a90e161bSBill Fenner opri = (struct nd_opt_route_info *)op; 681a90e161bSBill Fenner TCHECK(opri->nd_opt_rti_lifetime); 682a90e161bSBill Fenner memset(&in6, 0, sizeof(in6)); 683a90e161bSBill Fenner in6p = (struct in6_addr *)(opri + 1); 684a90e161bSBill Fenner switch (op->nd_opt_len) { 685a90e161bSBill Fenner case 1: 686a90e161bSBill Fenner break; 687a90e161bSBill Fenner case 2: 688a90e161bSBill Fenner TCHECK2(*in6p, 8); 689a90e161bSBill Fenner memcpy(&in6, opri + 1, 8); 690a90e161bSBill Fenner break; 691a90e161bSBill Fenner case 3: 692a90e161bSBill Fenner TCHECK(*in6p); 693a90e161bSBill Fenner memcpy(&in6, opri + 1, sizeof(in6)); 694685295f4SBill Fenner break; 695b0453382SBill Fenner default: 696a90e161bSBill Fenner goto trunc; 697a90e161bSBill Fenner } 698a90e161bSBill Fenner printf(" %s/%u", ip6addr_string(&in6), 699a90e161bSBill Fenner opri->nd_opt_rti_prefixlen); 700a90e161bSBill Fenner printf(", pref=%s", get_rtpref(opri->nd_opt_rti_flags)); 701a90e161bSBill Fenner printf(", lifetime=%s", 7025b0fe478SBruce M Simpson get_lifetime(EXTRACT_32BITS(&opri->nd_opt_rti_lifetime))); 703a90e161bSBill Fenner break; 704a90e161bSBill Fenner default: 7051de50e9fSSam Leffler if (vflag <= 1) { 7061de50e9fSSam Leffler print_unknown_data(cp+2,"\n\t ", (op->nd_opt_len << 3) - 2); /* skip option header */ 7071de50e9fSSam Leffler return; 7081de50e9fSSam Leffler } 709b0453382SBill Fenner break; 710b0453382SBill Fenner } 7111de50e9fSSam Leffler /* do we want to see an additional hexdump ? */ 7121de50e9fSSam Leffler if (vflag> 1) 7131de50e9fSSam Leffler print_unknown_data(cp+2,"\n\t ", (op->nd_opt_len << 3) - 2); /* skip option header */ 714a90e161bSBill Fenner 715a90e161bSBill Fenner cp += op->nd_opt_len << 3; 716a90e161bSBill Fenner resid -= op->nd_opt_len << 3; 717a90e161bSBill Fenner } 718b0453382SBill Fenner return; 719a90e161bSBill Fenner 720b0453382SBill Fenner trunc: 721b0453382SBill Fenner fputs("[ndp opt]", stdout); 722b0453382SBill Fenner return; 723b0453382SBill Fenner #undef ECHECK 724b0453382SBill Fenner } 725b0453382SBill Fenner 7265b0fe478SBruce M Simpson static void 727a90e161bSBill Fenner mld6_print(const u_char *bp) 728b0453382SBill Fenner { 729a90e161bSBill Fenner struct mld6_hdr *mp = (struct mld6_hdr *)bp; 730a90e161bSBill Fenner const u_char *ep; 731b0453382SBill Fenner 732685295f4SBill Fenner /* 'ep' points to the end of available data. */ 733b0453382SBill Fenner ep = snapend; 734b0453382SBill Fenner 735b0453382SBill Fenner if ((u_char *)mp + sizeof(*mp) > ep) 736b0453382SBill Fenner return; 737b0453382SBill Fenner 7385b0fe478SBruce M Simpson printf("max resp delay: %d ", EXTRACT_16BITS(&mp->mld6_maxdelay)); 739b0453382SBill Fenner printf("addr: %s", ip6addr_string(&mp->mld6_addr)); 740685295f4SBill Fenner } 741685295f4SBill Fenner 742685295f4SBill Fenner static void 7431de50e9fSSam Leffler mldv2_report_print(const u_char *bp, u_int len) 7441de50e9fSSam Leffler { 7451de50e9fSSam Leffler struct icmp6_hdr *icp = (struct icmp6_hdr *) bp; 7461de50e9fSSam Leffler u_int group, nsrcs, ngroups; 7471de50e9fSSam Leffler u_int i, j; 7481de50e9fSSam Leffler 7491de50e9fSSam Leffler /* Minimum len is 8 */ 7501de50e9fSSam Leffler if (len < 8) { 7511de50e9fSSam Leffler printf(" [invalid len %d]", len); 7521de50e9fSSam Leffler return; 7531de50e9fSSam Leffler } 7541de50e9fSSam Leffler 7551de50e9fSSam Leffler TCHECK(icp->icmp6_data16[1]); 7561de50e9fSSam Leffler ngroups = ntohs(icp->icmp6_data16[1]); 7571de50e9fSSam Leffler printf(", %d group record(s)", ngroups); 7581de50e9fSSam Leffler if (vflag > 0) { 7591de50e9fSSam Leffler /* Print the group records */ 7601de50e9fSSam Leffler group = 8; 7611de50e9fSSam Leffler for (i = 0; i < ngroups; i++) { 7621de50e9fSSam Leffler /* type(1) + auxlen(1) + numsrc(2) + grp(16) */ 7631de50e9fSSam Leffler if (len < group + 20) { 7641de50e9fSSam Leffler printf(" [invalid number of groups]"); 7651de50e9fSSam Leffler return; 7661de50e9fSSam Leffler } 7672ebc47dbSSam Leffler TCHECK2(bp[group + 4], sizeof(struct in6_addr)); 7681de50e9fSSam Leffler printf(" [gaddr %s", ip6addr_string(&bp[group + 4])); 7691de50e9fSSam Leffler printf(" %s", tok2str(mldv2report2str, " [v2-report-#%d]", 7701de50e9fSSam Leffler bp[group])); 7711de50e9fSSam Leffler nsrcs = (bp[group + 2] << 8) + bp[group + 3]; 7721de50e9fSSam Leffler /* Check the number of sources and print them */ 7732ebc47dbSSam Leffler if (len < group + 20 + (nsrcs * sizeof(struct in6_addr))) { 7741de50e9fSSam Leffler printf(" [invalid number of sources %d]", nsrcs); 7751de50e9fSSam Leffler return; 7761de50e9fSSam Leffler } 7771de50e9fSSam Leffler if (vflag == 1) 7781de50e9fSSam Leffler printf(", %d source(s)", nsrcs); 7791de50e9fSSam Leffler else { 7801de50e9fSSam Leffler /* Print the sources */ 7811de50e9fSSam Leffler (void)printf(" {"); 7821de50e9fSSam Leffler for (j = 0; j < nsrcs; j++) { 7832ebc47dbSSam Leffler TCHECK2(bp[group + 20 + j * sizeof(struct in6_addr)], 7842ebc47dbSSam Leffler sizeof(struct in6_addr)); 7852ebc47dbSSam Leffler printf(" %s", ip6addr_string(&bp[group + 20 + j * sizeof(struct in6_addr)])); 7861de50e9fSSam Leffler } 7871de50e9fSSam Leffler (void)printf(" }"); 7881de50e9fSSam Leffler } 7891de50e9fSSam Leffler /* Next group record */ 7902ebc47dbSSam Leffler group += 20 + nsrcs * sizeof(struct in6_addr); 7911de50e9fSSam Leffler printf("]"); 7921de50e9fSSam Leffler } 7931de50e9fSSam Leffler } 7941de50e9fSSam Leffler return; 7951de50e9fSSam Leffler trunc: 7961de50e9fSSam Leffler (void)printf("[|icmp6]"); 7971de50e9fSSam Leffler return; 7981de50e9fSSam Leffler } 7991de50e9fSSam Leffler 8001de50e9fSSam Leffler static void 8011de50e9fSSam Leffler mldv2_query_print(const u_char *bp, u_int len) 8021de50e9fSSam Leffler { 8031de50e9fSSam Leffler struct icmp6_hdr *icp = (struct icmp6_hdr *) bp; 8041de50e9fSSam Leffler u_int mrc; 8051de50e9fSSam Leffler int mrt, qqi; 8061de50e9fSSam Leffler u_int nsrcs; 8071de50e9fSSam Leffler register u_int i; 8081de50e9fSSam Leffler 8091de50e9fSSam Leffler /* Minimum len is 28 */ 8101de50e9fSSam Leffler if (len < 28) { 8111de50e9fSSam Leffler printf(" [invalid len %d]", len); 8121de50e9fSSam Leffler return; 8131de50e9fSSam Leffler } 8141de50e9fSSam Leffler TCHECK(icp->icmp6_data16[0]); 8151de50e9fSSam Leffler mrc = ntohs(icp->icmp6_data16[0]); 8161de50e9fSSam Leffler if (mrc < 32768) { 8171de50e9fSSam Leffler mrt = mrc; 8181de50e9fSSam Leffler } else { 8191de50e9fSSam Leffler mrt = ((mrc & 0x0fff) | 0x1000) << (((mrc & 0x7000) >> 12) + 3); 8201de50e9fSSam Leffler } 8211de50e9fSSam Leffler if (vflag) { 8221de50e9fSSam Leffler (void)printf(" [max resp delay=%d]", mrt); 8231de50e9fSSam Leffler } 8242ebc47dbSSam Leffler TCHECK2(bp[8], sizeof(struct in6_addr)); 8251de50e9fSSam Leffler printf(" [gaddr %s", ip6addr_string(&bp[8])); 8261de50e9fSSam Leffler 8271de50e9fSSam Leffler if (vflag) { 8281de50e9fSSam Leffler TCHECK(bp[25]); 8291de50e9fSSam Leffler if (bp[24] & 0x08) { 8301de50e9fSSam Leffler printf(" sflag"); 8311de50e9fSSam Leffler } 8321de50e9fSSam Leffler if (bp[24] & 0x07) { 8331de50e9fSSam Leffler printf(" robustness=%d", bp[24] & 0x07); 8341de50e9fSSam Leffler } 8351de50e9fSSam Leffler if (bp[25] < 128) { 8361de50e9fSSam Leffler qqi = bp[25]; 8371de50e9fSSam Leffler } else { 8381de50e9fSSam Leffler qqi = ((bp[25] & 0x0f) | 0x10) << (((bp[25] & 0x70) >> 4) + 3); 8391de50e9fSSam Leffler } 8401de50e9fSSam Leffler printf(" qqi=%d", qqi); 8411de50e9fSSam Leffler } 8421de50e9fSSam Leffler 8431de50e9fSSam Leffler TCHECK2(bp[26], 2); 8441de50e9fSSam Leffler nsrcs = ntohs(*(u_short *)&bp[26]); 8451de50e9fSSam Leffler if (nsrcs > 0) { 8462ebc47dbSSam Leffler if (len < 28 + nsrcs * sizeof(struct in6_addr)) 8471de50e9fSSam Leffler printf(" [invalid number of sources]"); 8481de50e9fSSam Leffler else if (vflag > 1) { 8491de50e9fSSam Leffler printf(" {"); 8501de50e9fSSam Leffler for (i = 0; i < nsrcs; i++) { 8512ebc47dbSSam Leffler TCHECK2(bp[28 + i * sizeof(struct in6_addr)], 8522ebc47dbSSam Leffler sizeof(struct in6_addr)); 8532ebc47dbSSam Leffler printf(" %s", ip6addr_string(&bp[28 + i * sizeof(struct in6_addr)])); 8541de50e9fSSam Leffler } 8551de50e9fSSam Leffler printf(" }"); 8561de50e9fSSam Leffler } else 8571de50e9fSSam Leffler printf(", %d source(s)", nsrcs); 8581de50e9fSSam Leffler } 8591de50e9fSSam Leffler printf("]"); 8601de50e9fSSam Leffler return; 8611de50e9fSSam Leffler trunc: 8621de50e9fSSam Leffler (void)printf("[|icmp6]"); 8631de50e9fSSam Leffler return; 8641de50e9fSSam Leffler } 8651de50e9fSSam Leffler 8661de50e9fSSam Leffler void 867685295f4SBill Fenner dnsname_print(const u_char *cp, const u_char *ep) 868685295f4SBill Fenner { 869685295f4SBill Fenner int i; 870685295f4SBill Fenner 871685295f4SBill Fenner /* DNS name decoding - no decompression */ 872685295f4SBill Fenner printf(", \""); 873685295f4SBill Fenner while (cp < ep) { 874685295f4SBill Fenner i = *cp++; 875685295f4SBill Fenner if (i) { 876685295f4SBill Fenner if (i > ep - cp) { 877685295f4SBill Fenner printf("???"); 878685295f4SBill Fenner break; 879685295f4SBill Fenner } 880685295f4SBill Fenner while (i-- && cp < ep) { 881685295f4SBill Fenner safeputchar(*cp); 882685295f4SBill Fenner cp++; 883685295f4SBill Fenner } 884685295f4SBill Fenner if (cp + 1 < ep && *cp) 885685295f4SBill Fenner printf("."); 886685295f4SBill Fenner } else { 887685295f4SBill Fenner if (cp == ep) { 888685295f4SBill Fenner /* FQDN */ 889685295f4SBill Fenner printf("."); 890685295f4SBill Fenner } else if (cp + 1 == ep && *cp == '\0') { 891685295f4SBill Fenner /* truncated */ 892685295f4SBill Fenner } else { 893685295f4SBill Fenner /* invalid */ 894685295f4SBill Fenner printf("???"); 895685295f4SBill Fenner } 896685295f4SBill Fenner break; 897685295f4SBill Fenner } 898685295f4SBill Fenner } 899685295f4SBill Fenner printf("\""); 900685295f4SBill Fenner } 901685295f4SBill Fenner 9025b0fe478SBruce M Simpson static void 9035b0fe478SBruce M Simpson icmp6_nodeinfo_print(u_int icmp6len, const u_char *bp, const u_char *ep) 904685295f4SBill Fenner { 905685295f4SBill Fenner struct icmp6_nodeinfo *ni6; 906685295f4SBill Fenner struct icmp6_hdr *dp; 907685295f4SBill Fenner const u_char *cp; 9085b0fe478SBruce M Simpson size_t siz, i; 909685295f4SBill Fenner int needcomma; 910685295f4SBill Fenner 9115b0fe478SBruce M Simpson if (ep < bp) 9125b0fe478SBruce M Simpson return; 913685295f4SBill Fenner dp = (struct icmp6_hdr *)bp; 914685295f4SBill Fenner ni6 = (struct icmp6_nodeinfo *)bp; 915685295f4SBill Fenner siz = ep - bp; 916685295f4SBill Fenner 917685295f4SBill Fenner switch (ni6->ni_type) { 918685295f4SBill Fenner case ICMP6_NI_QUERY: 919685295f4SBill Fenner if (siz == sizeof(*dp) + 4) { 920685295f4SBill Fenner /* KAME who-are-you */ 9211de50e9fSSam Leffler printf(" who-are-you request"); 922685295f4SBill Fenner break; 923685295f4SBill Fenner } 9241de50e9fSSam Leffler printf(" node information query"); 925685295f4SBill Fenner 926685295f4SBill Fenner TCHECK2(*dp, sizeof(*ni6)); 927685295f4SBill Fenner ni6 = (struct icmp6_nodeinfo *)dp; 928685295f4SBill Fenner printf(" ("); /*)*/ 9295b0fe478SBruce M Simpson switch (EXTRACT_16BITS(&ni6->ni_qtype)) { 930685295f4SBill Fenner case NI_QTYPE_NOOP: 931685295f4SBill Fenner printf("noop"); 932685295f4SBill Fenner break; 933685295f4SBill Fenner case NI_QTYPE_SUPTYPES: 934685295f4SBill Fenner printf("supported qtypes"); 9355b0fe478SBruce M Simpson i = EXTRACT_16BITS(&ni6->ni_flags); 936685295f4SBill Fenner if (i) 937685295f4SBill Fenner printf(" [%s]", (i & 0x01) ? "C" : ""); 938685295f4SBill Fenner break; 939685295f4SBill Fenner break; 940685295f4SBill Fenner case NI_QTYPE_FQDN: 941685295f4SBill Fenner printf("DNS name"); 942685295f4SBill Fenner break; 943685295f4SBill Fenner case NI_QTYPE_NODEADDR: 944685295f4SBill Fenner printf("node addresses"); 945685295f4SBill Fenner i = ni6->ni_flags; 946685295f4SBill Fenner if (!i) 947685295f4SBill Fenner break; 948685295f4SBill Fenner /* NI_NODEADDR_FLAG_TRUNCATE undefined for query */ 949685295f4SBill Fenner printf(" [%s%s%s%s%s%s]", 950685295f4SBill Fenner (i & NI_NODEADDR_FLAG_ANYCAST) ? "a" : "", 951685295f4SBill Fenner (i & NI_NODEADDR_FLAG_GLOBAL) ? "G" : "", 952685295f4SBill Fenner (i & NI_NODEADDR_FLAG_SITELOCAL) ? "S" : "", 953685295f4SBill Fenner (i & NI_NODEADDR_FLAG_LINKLOCAL) ? "L" : "", 954685295f4SBill Fenner (i & NI_NODEADDR_FLAG_COMPAT) ? "C" : "", 955685295f4SBill Fenner (i & NI_NODEADDR_FLAG_ALL) ? "A" : ""); 956685295f4SBill Fenner break; 957685295f4SBill Fenner default: 958685295f4SBill Fenner printf("unknown"); 959685295f4SBill Fenner break; 960685295f4SBill Fenner } 961685295f4SBill Fenner 962685295f4SBill Fenner if (ni6->ni_qtype == NI_QTYPE_NOOP || 963685295f4SBill Fenner ni6->ni_qtype == NI_QTYPE_SUPTYPES) { 964685295f4SBill Fenner if (siz != sizeof(*ni6)) 965685295f4SBill Fenner if (vflag) 966685295f4SBill Fenner printf(", invalid len"); 967685295f4SBill Fenner /*(*/ 968685295f4SBill Fenner printf(")"); 969685295f4SBill Fenner break; 970685295f4SBill Fenner } 971685295f4SBill Fenner 972685295f4SBill Fenner 973685295f4SBill Fenner /* XXX backward compat, icmp-name-lookup-03 */ 974685295f4SBill Fenner if (siz == sizeof(*ni6)) { 975685295f4SBill Fenner printf(", 03 draft"); 976685295f4SBill Fenner /*(*/ 977685295f4SBill Fenner printf(")"); 978685295f4SBill Fenner break; 979685295f4SBill Fenner } 980685295f4SBill Fenner 981685295f4SBill Fenner switch (ni6->ni_code) { 982685295f4SBill Fenner case ICMP6_NI_SUBJ_IPV6: 983685295f4SBill Fenner if (!TTEST2(*dp, 984685295f4SBill Fenner sizeof(*ni6) + sizeof(struct in6_addr))) 985685295f4SBill Fenner break; 986685295f4SBill Fenner if (siz != sizeof(*ni6) + sizeof(struct in6_addr)) { 987685295f4SBill Fenner if (vflag) 988685295f4SBill Fenner printf(", invalid subject len"); 989685295f4SBill Fenner break; 990685295f4SBill Fenner } 991685295f4SBill Fenner printf(", subject=%s", 992685295f4SBill Fenner getname6((const u_char *)(ni6 + 1))); 993685295f4SBill Fenner break; 994685295f4SBill Fenner case ICMP6_NI_SUBJ_FQDN: 995685295f4SBill Fenner printf(", subject=DNS name"); 996685295f4SBill Fenner cp = (const u_char *)(ni6 + 1); 997685295f4SBill Fenner if (cp[0] == ep - cp - 1) { 998685295f4SBill Fenner /* icmp-name-lookup-03, pascal string */ 999685295f4SBill Fenner if (vflag) 1000685295f4SBill Fenner printf(", 03 draft"); 1001685295f4SBill Fenner cp++; 1002685295f4SBill Fenner printf(", \""); 1003685295f4SBill Fenner while (cp < ep) { 1004685295f4SBill Fenner safeputchar(*cp); 1005685295f4SBill Fenner cp++; 1006685295f4SBill Fenner } 1007685295f4SBill Fenner printf("\""); 1008685295f4SBill Fenner } else 1009685295f4SBill Fenner dnsname_print(cp, ep); 1010685295f4SBill Fenner break; 1011685295f4SBill Fenner case ICMP6_NI_SUBJ_IPV4: 1012685295f4SBill Fenner if (!TTEST2(*dp, sizeof(*ni6) + sizeof(struct in_addr))) 1013685295f4SBill Fenner break; 1014685295f4SBill Fenner if (siz != sizeof(*ni6) + sizeof(struct in_addr)) { 1015685295f4SBill Fenner if (vflag) 1016685295f4SBill Fenner printf(", invalid subject len"); 1017685295f4SBill Fenner break; 1018685295f4SBill Fenner } 1019685295f4SBill Fenner printf(", subject=%s", 1020685295f4SBill Fenner getname((const u_char *)(ni6 + 1))); 1021685295f4SBill Fenner break; 1022685295f4SBill Fenner default: 1023685295f4SBill Fenner printf(", unknown subject"); 1024685295f4SBill Fenner break; 1025685295f4SBill Fenner } 1026685295f4SBill Fenner 1027685295f4SBill Fenner /*(*/ 1028685295f4SBill Fenner printf(")"); 1029685295f4SBill Fenner break; 1030685295f4SBill Fenner 1031685295f4SBill Fenner case ICMP6_NI_REPLY: 1032685295f4SBill Fenner if (icmp6len > siz) { 1033685295f4SBill Fenner printf("[|icmp6: node information reply]"); 1034685295f4SBill Fenner break; 1035685295f4SBill Fenner } 1036685295f4SBill Fenner 1037685295f4SBill Fenner needcomma = 0; 1038685295f4SBill Fenner 1039685295f4SBill Fenner ni6 = (struct icmp6_nodeinfo *)dp; 10401de50e9fSSam Leffler printf(" node information reply"); 1041685295f4SBill Fenner printf(" ("); /*)*/ 1042685295f4SBill Fenner switch (ni6->ni_code) { 1043685295f4SBill Fenner case ICMP6_NI_SUCCESS: 1044685295f4SBill Fenner if (vflag) { 1045685295f4SBill Fenner printf("success"); 1046685295f4SBill Fenner needcomma++; 1047685295f4SBill Fenner } 1048685295f4SBill Fenner break; 1049685295f4SBill Fenner case ICMP6_NI_REFUSED: 1050685295f4SBill Fenner printf("refused"); 1051685295f4SBill Fenner needcomma++; 1052685295f4SBill Fenner if (siz != sizeof(*ni6)) 1053685295f4SBill Fenner if (vflag) 1054685295f4SBill Fenner printf(", invalid length"); 1055685295f4SBill Fenner break; 1056685295f4SBill Fenner case ICMP6_NI_UNKNOWN: 1057685295f4SBill Fenner printf("unknown"); 1058685295f4SBill Fenner needcomma++; 1059685295f4SBill Fenner if (siz != sizeof(*ni6)) 1060685295f4SBill Fenner if (vflag) 1061685295f4SBill Fenner printf(", invalid length"); 1062685295f4SBill Fenner break; 1063685295f4SBill Fenner } 1064685295f4SBill Fenner 1065685295f4SBill Fenner if (ni6->ni_code != ICMP6_NI_SUCCESS) { 1066685295f4SBill Fenner /*(*/ 1067685295f4SBill Fenner printf(")"); 1068685295f4SBill Fenner break; 1069685295f4SBill Fenner } 1070685295f4SBill Fenner 10715b0fe478SBruce M Simpson switch (EXTRACT_16BITS(&ni6->ni_qtype)) { 1072685295f4SBill Fenner case NI_QTYPE_NOOP: 1073685295f4SBill Fenner if (needcomma) 1074685295f4SBill Fenner printf(", "); 1075685295f4SBill Fenner printf("noop"); 1076685295f4SBill Fenner if (siz != sizeof(*ni6)) 1077685295f4SBill Fenner if (vflag) 1078685295f4SBill Fenner printf(", invalid length"); 1079685295f4SBill Fenner break; 1080685295f4SBill Fenner case NI_QTYPE_SUPTYPES: 1081685295f4SBill Fenner if (needcomma) 1082685295f4SBill Fenner printf(", "); 1083685295f4SBill Fenner printf("supported qtypes"); 10845b0fe478SBruce M Simpson i = EXTRACT_16BITS(&ni6->ni_flags); 1085685295f4SBill Fenner if (i) 1086685295f4SBill Fenner printf(" [%s]", (i & 0x01) ? "C" : ""); 1087685295f4SBill Fenner break; 1088685295f4SBill Fenner case NI_QTYPE_FQDN: 1089685295f4SBill Fenner if (needcomma) 1090685295f4SBill Fenner printf(", "); 1091685295f4SBill Fenner printf("DNS name"); 1092685295f4SBill Fenner cp = (const u_char *)(ni6 + 1) + 4; 1093685295f4SBill Fenner if (cp[0] == ep - cp - 1) { 1094685295f4SBill Fenner /* icmp-name-lookup-03, pascal string */ 1095685295f4SBill Fenner if (vflag) 1096685295f4SBill Fenner printf(", 03 draft"); 1097685295f4SBill Fenner cp++; 1098685295f4SBill Fenner printf(", \""); 1099685295f4SBill Fenner while (cp < ep) { 1100685295f4SBill Fenner safeputchar(*cp); 1101685295f4SBill Fenner cp++; 1102685295f4SBill Fenner } 1103685295f4SBill Fenner printf("\""); 1104685295f4SBill Fenner } else 1105685295f4SBill Fenner dnsname_print(cp, ep); 11065b0fe478SBruce M Simpson if ((EXTRACT_16BITS(&ni6->ni_flags) & 0x01) != 0) 1107685295f4SBill Fenner printf(" [TTL=%u]", *(u_int32_t *)(ni6 + 1)); 1108685295f4SBill Fenner break; 1109685295f4SBill Fenner case NI_QTYPE_NODEADDR: 1110685295f4SBill Fenner if (needcomma) 1111685295f4SBill Fenner printf(", "); 1112685295f4SBill Fenner printf("node addresses"); 1113685295f4SBill Fenner i = sizeof(*ni6); 1114685295f4SBill Fenner while (i < siz) { 1115685295f4SBill Fenner if (i + sizeof(struct in6_addr) + sizeof(int32_t) > siz) 1116685295f4SBill Fenner break; 1117685295f4SBill Fenner printf(" %s", getname6(bp + i)); 1118685295f4SBill Fenner i += sizeof(struct in6_addr); 11195b0fe478SBruce M Simpson printf("(%d)", (int32_t)EXTRACT_32BITS(bp + i)); 1120685295f4SBill Fenner i += sizeof(int32_t); 1121685295f4SBill Fenner } 1122685295f4SBill Fenner i = ni6->ni_flags; 1123685295f4SBill Fenner if (!i) 1124685295f4SBill Fenner break; 1125685295f4SBill Fenner printf(" [%s%s%s%s%s%s%s]", 1126685295f4SBill Fenner (i & NI_NODEADDR_FLAG_ANYCAST) ? "a" : "", 1127685295f4SBill Fenner (i & NI_NODEADDR_FLAG_GLOBAL) ? "G" : "", 1128685295f4SBill Fenner (i & NI_NODEADDR_FLAG_SITELOCAL) ? "S" : "", 1129685295f4SBill Fenner (i & NI_NODEADDR_FLAG_LINKLOCAL) ? "L" : "", 1130685295f4SBill Fenner (i & NI_NODEADDR_FLAG_COMPAT) ? "C" : "", 1131685295f4SBill Fenner (i & NI_NODEADDR_FLAG_ALL) ? "A" : "", 1132685295f4SBill Fenner (i & NI_NODEADDR_FLAG_TRUNCATE) ? "T" : ""); 1133685295f4SBill Fenner break; 1134685295f4SBill Fenner default: 1135685295f4SBill Fenner if (needcomma) 1136685295f4SBill Fenner printf(", "); 1137685295f4SBill Fenner printf("unknown"); 1138685295f4SBill Fenner break; 1139685295f4SBill Fenner } 1140685295f4SBill Fenner 1141685295f4SBill Fenner /*(*/ 1142685295f4SBill Fenner printf(")"); 1143685295f4SBill Fenner break; 1144685295f4SBill Fenner } 1145685295f4SBill Fenner return; 1146685295f4SBill Fenner 1147685295f4SBill Fenner trunc: 1148685295f4SBill Fenner fputs("[|icmp6]", stdout); 1149685295f4SBill Fenner } 1150685295f4SBill Fenner 11515b0fe478SBruce M Simpson static void 11525b0fe478SBruce M Simpson icmp6_rrenum_print(const u_char *bp, const u_char *ep) 1153685295f4SBill Fenner { 1154685295f4SBill Fenner struct icmp6_router_renum *rr6; 1155685295f4SBill Fenner const char *cp; 1156685295f4SBill Fenner struct rr_pco_match *match; 1157685295f4SBill Fenner struct rr_pco_use *use; 1158685295f4SBill Fenner char hbuf[NI_MAXHOST]; 1159685295f4SBill Fenner int n; 1160685295f4SBill Fenner 11615b0fe478SBruce M Simpson if (ep < bp) 11625b0fe478SBruce M Simpson return; 1163685295f4SBill Fenner rr6 = (struct icmp6_router_renum *)bp; 1164685295f4SBill Fenner cp = (const char *)(rr6 + 1); 1165685295f4SBill Fenner 1166685295f4SBill Fenner TCHECK(rr6->rr_reserved); 1167685295f4SBill Fenner switch (rr6->rr_code) { 1168685295f4SBill Fenner case ICMP6_ROUTER_RENUMBERING_COMMAND: 1169685295f4SBill Fenner printf("router renum: command"); 1170685295f4SBill Fenner break; 1171685295f4SBill Fenner case ICMP6_ROUTER_RENUMBERING_RESULT: 1172685295f4SBill Fenner printf("router renum: result"); 1173685295f4SBill Fenner break; 1174685295f4SBill Fenner case ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET: 1175685295f4SBill Fenner printf("router renum: sequence number reset"); 1176685295f4SBill Fenner break; 1177685295f4SBill Fenner default: 1178685295f4SBill Fenner printf("router renum: code-#%d", rr6->rr_code); 1179685295f4SBill Fenner break; 1180685295f4SBill Fenner } 1181685295f4SBill Fenner 11825b0fe478SBruce M Simpson printf(", seq=%u", EXTRACT_32BITS(&rr6->rr_seqnum)); 1183685295f4SBill Fenner 1184685295f4SBill Fenner if (vflag) { 1185685295f4SBill Fenner #define F(x, y) ((rr6->rr_flags) & (x) ? (y) : "") 1186685295f4SBill Fenner printf("["); /*]*/ 1187685295f4SBill Fenner if (rr6->rr_flags) { 1188685295f4SBill Fenner printf("%s%s%s%s%s,", F(ICMP6_RR_FLAGS_TEST, "T"), 1189685295f4SBill Fenner F(ICMP6_RR_FLAGS_REQRESULT, "R"), 1190a90e161bSBill Fenner F(ICMP6_RR_FLAGS_FORCEAPPLY, "A"), 1191685295f4SBill Fenner F(ICMP6_RR_FLAGS_SPECSITE, "S"), 1192685295f4SBill Fenner F(ICMP6_RR_FLAGS_PREVDONE, "P")); 1193685295f4SBill Fenner } 1194685295f4SBill Fenner printf("seg=%u,", rr6->rr_segnum); 1195685295f4SBill Fenner printf("maxdelay=%u", rr6->rr_maxdelay); 1196685295f4SBill Fenner if (rr6->rr_reserved) 11975b0fe478SBruce M Simpson printf("rsvd=0x%x", EXTRACT_16BITS(&rr6->rr_reserved)); 1198685295f4SBill Fenner /*[*/ 1199685295f4SBill Fenner printf("]"); 1200685295f4SBill Fenner #undef F 1201685295f4SBill Fenner } 1202685295f4SBill Fenner 1203685295f4SBill Fenner if (rr6->rr_code == ICMP6_ROUTER_RENUMBERING_COMMAND) { 1204685295f4SBill Fenner match = (struct rr_pco_match *)cp; 1205685295f4SBill Fenner cp = (const char *)(match + 1); 1206685295f4SBill Fenner 1207685295f4SBill Fenner TCHECK(match->rpm_prefix); 1208685295f4SBill Fenner 1209a90e161bSBill Fenner if (vflag > 1) 1210685295f4SBill Fenner printf("\n\t"); 1211685295f4SBill Fenner else 1212685295f4SBill Fenner printf(" "); 1213685295f4SBill Fenner printf("match("); /*)*/ 1214685295f4SBill Fenner switch (match->rpm_code) { 1215685295f4SBill Fenner case RPM_PCO_ADD: printf("add"); break; 1216685295f4SBill Fenner case RPM_PCO_CHANGE: printf("change"); break; 1217685295f4SBill Fenner case RPM_PCO_SETGLOBAL: printf("setglobal"); break; 1218685295f4SBill Fenner default: printf("#%u", match->rpm_code); break; 1219685295f4SBill Fenner } 1220685295f4SBill Fenner 1221685295f4SBill Fenner if (vflag) { 1222685295f4SBill Fenner printf(",ord=%u", match->rpm_ordinal); 1223685295f4SBill Fenner printf(",min=%u", match->rpm_minlen); 1224685295f4SBill Fenner printf(",max=%u", match->rpm_maxlen); 1225685295f4SBill Fenner } 1226685295f4SBill Fenner if (inet_ntop(AF_INET6, &match->rpm_prefix, hbuf, sizeof(hbuf))) 1227685295f4SBill Fenner printf(",%s/%u", hbuf, match->rpm_matchlen); 1228685295f4SBill Fenner else 1229685295f4SBill Fenner printf(",?/%u", match->rpm_matchlen); 1230685295f4SBill Fenner /*(*/ 1231685295f4SBill Fenner printf(")"); 1232685295f4SBill Fenner 1233685295f4SBill Fenner n = match->rpm_len - 3; 1234685295f4SBill Fenner if (n % 4) 1235685295f4SBill Fenner goto trunc; 1236685295f4SBill Fenner n /= 4; 1237685295f4SBill Fenner while (n-- > 0) { 1238685295f4SBill Fenner use = (struct rr_pco_use *)cp; 1239685295f4SBill Fenner cp = (const char *)(use + 1); 1240685295f4SBill Fenner 1241685295f4SBill Fenner TCHECK(use->rpu_prefix); 1242685295f4SBill Fenner 1243a90e161bSBill Fenner if (vflag > 1) 1244685295f4SBill Fenner printf("\n\t"); 1245685295f4SBill Fenner else 1246685295f4SBill Fenner printf(" "); 1247685295f4SBill Fenner printf("use("); /*)*/ 1248685295f4SBill Fenner if (use->rpu_flags) { 1249685295f4SBill Fenner #define F(x, y) ((use->rpu_flags) & (x) ? (y) : "") 1250685295f4SBill Fenner printf("%s%s,", 1251685295f4SBill Fenner F(ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME, "V"), 1252685295f4SBill Fenner F(ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME, "P")); 1253685295f4SBill Fenner #undef F 1254685295f4SBill Fenner } 1255685295f4SBill Fenner if (vflag) { 1256685295f4SBill Fenner printf("mask=0x%x,", use->rpu_ramask); 1257685295f4SBill Fenner printf("raflags=0x%x,", use->rpu_raflags); 1258685295f4SBill Fenner if (~use->rpu_vltime == 0) 1259685295f4SBill Fenner printf("vltime=infty,"); 1260685295f4SBill Fenner else 1261685295f4SBill Fenner printf("vltime=%u,", 12625b0fe478SBruce M Simpson EXTRACT_32BITS(&use->rpu_vltime)); 1263685295f4SBill Fenner if (~use->rpu_pltime == 0) 1264685295f4SBill Fenner printf("pltime=infty,"); 1265685295f4SBill Fenner else 1266685295f4SBill Fenner printf("pltime=%u,", 12675b0fe478SBruce M Simpson EXTRACT_32BITS(&use->rpu_pltime)); 1268685295f4SBill Fenner } 1269685295f4SBill Fenner if (inet_ntop(AF_INET6, &use->rpu_prefix, hbuf, 1270685295f4SBill Fenner sizeof(hbuf))) 1271685295f4SBill Fenner printf("%s/%u/%u", hbuf, use->rpu_uselen, 1272685295f4SBill Fenner use->rpu_keeplen); 1273685295f4SBill Fenner else 1274685295f4SBill Fenner printf("?/%u/%u", use->rpu_uselen, 1275685295f4SBill Fenner use->rpu_keeplen); 1276685295f4SBill Fenner /*(*/ 1277685295f4SBill Fenner printf(")"); 1278685295f4SBill Fenner } 1279685295f4SBill Fenner } 1280b0453382SBill Fenner 1281b0453382SBill Fenner return; 1282685295f4SBill Fenner 1283685295f4SBill Fenner trunc: 1284685295f4SBill Fenner fputs("[|icmp6]", stdout); 1285b0453382SBill Fenner } 1286685295f4SBill Fenner 1287b0453382SBill Fenner #endif /* INET6 */ 1288