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_ = 2427df3f5dSRui Paulo "@(#) $Header: /tcpdump/master/tcpdump/print-icmp6.c,v 1.86 2008-02-05 19:36:13 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 6527df3f5dSRui Paulo /* inline the various RPL definitions */ 6627df3f5dSRui Paulo #define ND_RPL_MESSAGE 0x9B 6727df3f5dSRui Paulo 681de50e9fSSam Leffler static struct tok icmp6_type_values[] = { 691de50e9fSSam Leffler { ICMP6_DST_UNREACH, "destination unreachable"}, 701de50e9fSSam Leffler { ICMP6_PACKET_TOO_BIG, "packet too big"}, 711de50e9fSSam Leffler { ICMP6_TIME_EXCEEDED, "time exceeded in-transit"}, 721de50e9fSSam Leffler { ICMP6_PARAM_PROB, "parameter problem"}, 731de50e9fSSam Leffler { ICMP6_ECHO_REQUEST, "echo request"}, 741de50e9fSSam Leffler { ICMP6_ECHO_REPLY, "echo reply"}, 751de50e9fSSam Leffler { MLD6_LISTENER_QUERY, "multicast listener query"}, 761de50e9fSSam Leffler { MLD6_LISTENER_REPORT, "multicast listener report"}, 771de50e9fSSam Leffler { MLD6_LISTENER_DONE, "multicast listener done"}, 781de50e9fSSam Leffler { ND_ROUTER_SOLICIT, "router solicitation"}, 791de50e9fSSam Leffler { ND_ROUTER_ADVERT, "router advertisement"}, 801de50e9fSSam Leffler { ND_NEIGHBOR_SOLICIT, "neighbor solicitation"}, 812ebc47dbSSam Leffler { ND_NEIGHBOR_ADVERT, "neighbor advertisement"}, 821de50e9fSSam Leffler { ND_REDIRECT, "redirect"}, 831de50e9fSSam Leffler { ICMP6_ROUTER_RENUMBERING, "router renumbering"}, 841de50e9fSSam Leffler { IND_SOLICIT, "inverse neighbor solicitation"}, 851de50e9fSSam Leffler { IND_ADVERT, "inverse neighbor advertisement"}, 861de50e9fSSam Leffler { MLDV2_LISTENER_REPORT, "multicast listener report v2"}, 871de50e9fSSam Leffler { ICMP6_HADISCOV_REQUEST, "ha discovery request"}, 881de50e9fSSam Leffler { ICMP6_HADISCOV_REPLY, "ha discovery reply"}, 891de50e9fSSam Leffler { ICMP6_MOBILEPREFIX_SOLICIT, "mobile router solicitation"}, 901de50e9fSSam Leffler { ICMP6_MOBILEPREFIX_ADVERT, "mobile router advertisement"}, 911de50e9fSSam Leffler { ICMP6_WRUREQUEST, "who-are-you request"}, 921de50e9fSSam Leffler { ICMP6_WRUREPLY, "who-are-you reply"}, 931de50e9fSSam Leffler { ICMP6_NI_QUERY, "node information query"}, 941de50e9fSSam Leffler { ICMP6_NI_REPLY, "node information reply"}, 951de50e9fSSam Leffler { MLD6_MTRACE, "mtrace message"}, 961de50e9fSSam Leffler { MLD6_MTRACE_RESP, "mtrace response"}, 9727df3f5dSRui Paulo { ND_RPL_MESSAGE, "RPL"}, 981de50e9fSSam Leffler { 0, NULL } 991de50e9fSSam Leffler }; 1001de50e9fSSam Leffler 1011de50e9fSSam Leffler static struct tok icmp6_dst_unreach_code_values[] = { 1021de50e9fSSam Leffler { ICMP6_DST_UNREACH_NOROUTE, "unreachable route" }, 1031de50e9fSSam Leffler { ICMP6_DST_UNREACH_ADMIN, " unreachable prohibited"}, 1041de50e9fSSam Leffler { ICMP6_DST_UNREACH_BEYONDSCOPE, "beyond scope"}, 1051de50e9fSSam Leffler { ICMP6_DST_UNREACH_ADDR, "unreachable address"}, 1061de50e9fSSam Leffler { ICMP6_DST_UNREACH_NOPORT, "unreachable port"}, 1071de50e9fSSam Leffler { 0, NULL } 1081de50e9fSSam Leffler }; 1091de50e9fSSam Leffler 1101de50e9fSSam Leffler static struct tok icmp6_opt_pi_flag_values[] = { 1111de50e9fSSam Leffler { ND_OPT_PI_FLAG_ONLINK, "onlink" }, 1121de50e9fSSam Leffler { ND_OPT_PI_FLAG_AUTO, "auto" }, 1131de50e9fSSam Leffler { ND_OPT_PI_FLAG_ROUTER, "router" }, 1141de50e9fSSam Leffler { 0, NULL } 1151de50e9fSSam Leffler }; 1161de50e9fSSam Leffler 1171de50e9fSSam Leffler static struct tok icmp6_opt_ra_flag_values[] = { 1181de50e9fSSam Leffler { ND_RA_FLAG_MANAGED, "managed" }, 1191de50e9fSSam Leffler { ND_RA_FLAG_OTHER, "other stateful"}, 1201de50e9fSSam Leffler { ND_RA_FLAG_HOME_AGENT, "home agent"}, 1211de50e9fSSam Leffler { 0, NULL } 1221de50e9fSSam Leffler }; 1231de50e9fSSam Leffler 1241de50e9fSSam Leffler static struct tok icmp6_nd_na_flag_values[] = { 1251de50e9fSSam Leffler { ND_NA_FLAG_ROUTER, "router" }, 1261de50e9fSSam Leffler { ND_NA_FLAG_SOLICITED, "solicited" }, 1271de50e9fSSam Leffler { ND_NA_FLAG_OVERRIDE, "override" }, 1281de50e9fSSam Leffler { 0, NULL } 1291de50e9fSSam Leffler }; 1301de50e9fSSam Leffler 1311de50e9fSSam Leffler 1321de50e9fSSam Leffler static struct tok icmp6_opt_values[] = { 1331de50e9fSSam Leffler { ND_OPT_SOURCE_LINKADDR, "source link-address"}, 1341de50e9fSSam Leffler { ND_OPT_TARGET_LINKADDR, "destination link-address"}, 1351de50e9fSSam Leffler { ND_OPT_PREFIX_INFORMATION, "prefix info"}, 1361de50e9fSSam Leffler { ND_OPT_REDIRECTED_HEADER, "redirected header"}, 1371de50e9fSSam Leffler { ND_OPT_MTU, "mtu"}, 13827df3f5dSRui Paulo { ND_OPT_RDNSS, "rdnss"}, 139*d03c0883SXin LI { ND_OPT_DNSSL, "dnssl"}, 1402ebc47dbSSam Leffler { ND_OPT_ADVINTERVAL, "advertisement interval"}, 1411de50e9fSSam Leffler { ND_OPT_HOMEAGENT_INFO, "homeagent information"}, 1421de50e9fSSam Leffler { ND_OPT_ROUTE_INFO, "route info"}, 1431de50e9fSSam Leffler { 0, NULL } 1441de50e9fSSam Leffler }; 1451de50e9fSSam Leffler 1461de50e9fSSam Leffler /* mldv2 report types */ 1471de50e9fSSam Leffler static struct tok mldv2report2str[] = { 1481de50e9fSSam Leffler { 1, "is_in" }, 1491de50e9fSSam Leffler { 2, "is_ex" }, 1501de50e9fSSam Leffler { 3, "to_in" }, 1511de50e9fSSam Leffler { 4, "to_ex" }, 1521de50e9fSSam Leffler { 5, "allow" }, 1531de50e9fSSam Leffler { 6, "block" }, 1541de50e9fSSam Leffler { 0, NULL } 1551de50e9fSSam Leffler }; 1561de50e9fSSam Leffler 157a90e161bSBill Fenner static const char * 158a90e161bSBill Fenner get_rtpref(u_int v) 159a90e161bSBill Fenner { 160a90e161bSBill Fenner static const char *rtpref_str[] = { 161a90e161bSBill Fenner "medium", /* 00 */ 162a90e161bSBill Fenner "high", /* 01 */ 163a90e161bSBill Fenner "rsv", /* 10 */ 164a90e161bSBill Fenner "low" /* 11 */ 165a90e161bSBill Fenner }; 166a90e161bSBill Fenner 167a90e161bSBill Fenner return rtpref_str[((v & ND_RA_FLAG_RTPREF_MASK) >> 3) & 0xff]; 168a90e161bSBill Fenner } 169a90e161bSBill Fenner 170a90e161bSBill Fenner static const char * 171a90e161bSBill Fenner get_lifetime(u_int32_t v) 172a90e161bSBill Fenner { 173a90e161bSBill Fenner static char buf[20]; 174a90e161bSBill Fenner 175a90e161bSBill Fenner if (v == (u_int32_t)~0UL) 176a90e161bSBill Fenner return "infinity"; 177a90e161bSBill Fenner else { 178*d03c0883SXin LI snprintf(buf, sizeof(buf), "%us", v); 179a90e161bSBill Fenner return buf; 180a90e161bSBill Fenner } 181a90e161bSBill Fenner } 182a90e161bSBill Fenner 183a90e161bSBill Fenner static void 184a90e161bSBill Fenner print_lladdr(const u_int8_t *p, size_t l) 185a90e161bSBill Fenner { 186a90e161bSBill Fenner const u_int8_t *ep, *q; 187a90e161bSBill Fenner 188a90e161bSBill Fenner q = p; 189a90e161bSBill Fenner ep = p + l; 190a90e161bSBill Fenner while (l > 0 && q < ep) { 191a90e161bSBill Fenner if (q > p) 192a90e161bSBill Fenner printf(":"); 193a90e161bSBill Fenner printf("%02x", *q++); 194a90e161bSBill Fenner l--; 195a90e161bSBill Fenner } 196a90e161bSBill Fenner } 197a90e161bSBill Fenner 1985b0fe478SBruce M Simpson static int icmp6_cksum(const struct ip6_hdr *ip6, const struct icmp6_hdr *icp, 1995b0fe478SBruce M Simpson u_int len) 2005b0fe478SBruce M Simpson { 201cac3dcd5SXin LI return (nextproto6_cksum(ip6, (const u_int8_t *)(void *)icp, len, 202cac3dcd5SXin LI IPPROTO_ICMPV6)); 2035b0fe478SBruce M Simpson } 2045b0fe478SBruce M Simpson 20527df3f5dSRui Paulo enum ND_RPL_CODE { 206cac3dcd5SXin LI ND_RPL_DIS =0x00, 207cac3dcd5SXin LI ND_RPL_DIO =0x01, 208cac3dcd5SXin LI ND_RPL_DAO =0x02, 209cac3dcd5SXin LI ND_RPL_DAO_ACK=0x03, 210cac3dcd5SXin LI ND_RPL_SDIS =0x80, 211cac3dcd5SXin LI ND_RPL_SDIO =0x81, 212cac3dcd5SXin LI ND_RPL_SDAO =0x82, 213cac3dcd5SXin LI ND_RPL_SDAO_ACK=0x83, 214cac3dcd5SXin LI ND_RPL_SCC =0x8A, 21527df3f5dSRui Paulo }; 21627df3f5dSRui Paulo 21727df3f5dSRui Paulo enum ND_RPL_DIO_FLAGS { 21827df3f5dSRui Paulo ND_RPL_DIO_GROUNDED = 0x80, 21927df3f5dSRui Paulo ND_RPL_DIO_DATRIG = 0x40, 22027df3f5dSRui Paulo ND_RPL_DIO_DASUPPORT= 0x20, 22127df3f5dSRui Paulo ND_RPL_DIO_RES4 = 0x10, 22227df3f5dSRui Paulo ND_RPL_DIO_RES3 = 0x08, 22327df3f5dSRui Paulo ND_RPL_DIO_PRF_MASK = 0x07, /* 3-bit preference */ 22427df3f5dSRui Paulo }; 22527df3f5dSRui Paulo 22627df3f5dSRui Paulo struct nd_rpl_dio { 22727df3f5dSRui Paulo u_int8_t rpl_flags; 22827df3f5dSRui Paulo u_int8_t rpl_seq; 22927df3f5dSRui Paulo u_int8_t rpl_instanceid; 23027df3f5dSRui Paulo u_int8_t rpl_dagrank; 23127df3f5dSRui Paulo u_int8_t rpl_dagid[16]; 23227df3f5dSRui Paulo }; 23327df3f5dSRui Paulo 23427df3f5dSRui Paulo static void 23527df3f5dSRui Paulo rpl_print(netdissect_options *ndo, 23627df3f5dSRui Paulo const struct icmp6_hdr *hdr, 23727df3f5dSRui Paulo const u_char *bp, u_int length _U_) 23827df3f5dSRui Paulo { 23927df3f5dSRui Paulo struct nd_rpl_dio *dio = (struct nd_rpl_dio *)bp; 240cac3dcd5SXin LI int secured = hdr->icmp6_code & 0x80; 241cac3dcd5SXin LI int basecode= hdr->icmp6_code & 0x7f; 24227df3f5dSRui Paulo 24327df3f5dSRui Paulo ND_TCHECK(dio->rpl_dagid); 24427df3f5dSRui Paulo 245cac3dcd5SXin LI if(secured) { 246cac3dcd5SXin LI ND_PRINT((ndo, ", (SEC)")); 247cac3dcd5SXin LI } else { 248cac3dcd5SXin LI ND_PRINT((ndo, ", (CLR)")); 249cac3dcd5SXin LI } 250cac3dcd5SXin LI 251cac3dcd5SXin LI switch(basecode) { 252cac3dcd5SXin LI case ND_RPL_DIS: 253cac3dcd5SXin LI ND_PRINT((ndo, "DODAG Information Solicitation")); 25427df3f5dSRui Paulo if(ndo->ndo_vflag) { 25527df3f5dSRui Paulo } 25627df3f5dSRui Paulo break; 257cac3dcd5SXin LI case ND_RPL_DIO: 258cac3dcd5SXin LI ND_PRINT((ndo, "DODAG Information Object")); 25927df3f5dSRui Paulo if(ndo->ndo_vflag) { 26027df3f5dSRui Paulo char dagid[65]; 26127df3f5dSRui Paulo char *d = dagid; 26227df3f5dSRui Paulo int i; 26327df3f5dSRui Paulo for(i=0;i<16;i++) { 26427df3f5dSRui Paulo if(isprint(dio->rpl_dagid[i])) { 26527df3f5dSRui Paulo *d++ = dio->rpl_dagid[i]; 26627df3f5dSRui Paulo } else { 26727df3f5dSRui Paulo int cnt=snprintf(d,4,"0x%02x", 26827df3f5dSRui Paulo dio->rpl_dagid[i]); 26927df3f5dSRui Paulo d += cnt; 27027df3f5dSRui Paulo } 27127df3f5dSRui Paulo } 27227df3f5dSRui Paulo *d++ = '\0'; 27327df3f5dSRui Paulo ND_PRINT((ndo, " [seq:%u,instance:%u,rank:%u,dagid:%s]", 27427df3f5dSRui Paulo dio->rpl_seq, 27527df3f5dSRui Paulo dio->rpl_instanceid, 27627df3f5dSRui Paulo dio->rpl_dagrank, 27727df3f5dSRui Paulo dagid)); 27827df3f5dSRui Paulo } 27927df3f5dSRui Paulo break; 28027df3f5dSRui Paulo case ND_RPL_DAO: 281cac3dcd5SXin LI ND_PRINT((ndo, "Destination Advertisement Object")); 282cac3dcd5SXin LI if(ndo->ndo_vflag) { 283cac3dcd5SXin LI } 284cac3dcd5SXin LI break; 285cac3dcd5SXin LI case ND_RPL_DAO_ACK: 286cac3dcd5SXin LI ND_PRINT((ndo, "Destination Advertisement Object Ack")); 28727df3f5dSRui Paulo if(ndo->ndo_vflag) { 28827df3f5dSRui Paulo } 28927df3f5dSRui Paulo break; 29027df3f5dSRui Paulo default: 291cac3dcd5SXin LI ND_PRINT((ndo, "RPL message, unknown code %u",hdr->icmp6_code)); 29227df3f5dSRui Paulo break; 29327df3f5dSRui Paulo } 29427df3f5dSRui Paulo return; 29527df3f5dSRui Paulo trunc: 29627df3f5dSRui Paulo ND_PRINT((ndo," [|truncated]")); 29727df3f5dSRui Paulo return; 29827df3f5dSRui Paulo 29927df3f5dSRui Paulo } 30027df3f5dSRui Paulo 30127df3f5dSRui Paulo 302b0453382SBill Fenner void 30327df3f5dSRui Paulo icmp6_print(netdissect_options *ndo, 30427df3f5dSRui Paulo const u_char *bp, u_int length, const u_char *bp2, int fragmented) 305b0453382SBill Fenner { 306685295f4SBill Fenner const struct icmp6_hdr *dp; 307a90e161bSBill Fenner const struct ip6_hdr *ip; 308a90e161bSBill Fenner const struct ip6_hdr *oip; 309a90e161bSBill Fenner const struct udphdr *ouh; 310a90e161bSBill Fenner int dport; 311a90e161bSBill Fenner const u_char *ep; 3125b0fe478SBruce M Simpson u_int prot; 313b0453382SBill Fenner 314b0453382SBill Fenner dp = (struct icmp6_hdr *)bp; 315b0453382SBill Fenner ip = (struct ip6_hdr *)bp2; 316b0453382SBill Fenner oip = (struct ip6_hdr *)(dp + 1); 317685295f4SBill Fenner /* 'ep' points to the end of available data. */ 318b0453382SBill Fenner ep = snapend; 319b0453382SBill Fenner 3205b0fe478SBruce M Simpson TCHECK(dp->icmp6_cksum); 3215b0fe478SBruce M Simpson 3225b0fe478SBruce M Simpson if (vflag && !fragmented) { 323cac3dcd5SXin LI u_int16_t sum, udp_sum; 3245b0fe478SBruce M Simpson 3255b0fe478SBruce M Simpson if (TTEST2(bp[0], length)) { 326cac3dcd5SXin LI udp_sum = EXTRACT_16BITS(&dp->icmp6_cksum); 3275b0fe478SBruce M Simpson sum = icmp6_cksum(ip, dp, length); 3285b0fe478SBruce M Simpson if (sum != 0) 329cac3dcd5SXin LI (void)printf("[bad icmp6 cksum 0x%04x -> 0x%04x!] ", 330cac3dcd5SXin LI udp_sum, 331cac3dcd5SXin LI in_cksum_shouldbe(udp_sum, sum)); 3325b0fe478SBruce M Simpson else 3335b0fe478SBruce M Simpson (void)printf("[icmp6 sum ok] "); 3345b0fe478SBruce M Simpson } 3355b0fe478SBruce M Simpson } 3365b0fe478SBruce M Simpson 3371de50e9fSSam Leffler printf("ICMP6, %s", tok2str(icmp6_type_values,"unknown icmp6 type (%u)",dp->icmp6_type)); 3381de50e9fSSam Leffler 3391de50e9fSSam Leffler /* display cosmetics: print the packet length for printer that use the vflag now */ 34038034737SDimitry Andric if (vflag && (dp->icmp6_type == ND_ROUTER_SOLICIT || 34138034737SDimitry Andric dp->icmp6_type == ND_ROUTER_ADVERT || 34238034737SDimitry Andric dp->icmp6_type == ND_NEIGHBOR_ADVERT || 34338034737SDimitry Andric dp->icmp6_type == ND_NEIGHBOR_SOLICIT || 34438034737SDimitry Andric dp->icmp6_type == ND_REDIRECT || 34538034737SDimitry Andric dp->icmp6_type == ICMP6_HADISCOV_REPLY || 34638034737SDimitry Andric dp->icmp6_type == ICMP6_MOBILEPREFIX_ADVERT )) 3471de50e9fSSam Leffler printf(", length %u", length); 3481de50e9fSSam Leffler 349b0453382SBill Fenner switch (dp->icmp6_type) { 350b0453382SBill Fenner case ICMP6_DST_UNREACH: 351b0453382SBill Fenner TCHECK(oip->ip6_dst); 3521de50e9fSSam Leffler printf(", %s", tok2str(icmp6_dst_unreach_code_values,"unknown unreach code (%u)",dp->icmp6_code)); 353b0453382SBill Fenner switch (dp->icmp6_code) { 3541de50e9fSSam Leffler 3551de50e9fSSam Leffler case ICMP6_DST_UNREACH_NOROUTE: /* fall through */ 356b0453382SBill Fenner case ICMP6_DST_UNREACH_ADMIN: 3571de50e9fSSam Leffler case ICMP6_DST_UNREACH_ADDR: 3581de50e9fSSam Leffler printf(" %s",ip6addr_string(&oip->ip6_dst)); 359b0453382SBill Fenner break; 360b0453382SBill Fenner case ICMP6_DST_UNREACH_BEYONDSCOPE: 3611de50e9fSSam Leffler printf(" %s, source address %s", 362b0453382SBill Fenner ip6addr_string(&oip->ip6_dst), 363b0453382SBill Fenner ip6addr_string(&oip->ip6_src)); 364b0453382SBill Fenner break; 365b0453382SBill Fenner case ICMP6_DST_UNREACH_NOPORT: 366685295f4SBill Fenner if ((ouh = get_upperlayer((u_char *)oip, &prot)) 367685295f4SBill Fenner == NULL) 368685295f4SBill Fenner goto trunc; 369685295f4SBill Fenner 3705b0fe478SBruce M Simpson dport = EXTRACT_16BITS(&ouh->uh_dport); 371685295f4SBill Fenner switch (prot) { 372b0453382SBill Fenner case IPPROTO_TCP: 3731de50e9fSSam Leffler printf(", %s tcp port %s", 374b0453382SBill Fenner ip6addr_string(&oip->ip6_dst), 375b0453382SBill Fenner tcpport_string(dport)); 376b0453382SBill Fenner break; 377b0453382SBill Fenner case IPPROTO_UDP: 3781de50e9fSSam Leffler printf(", %s udp port %s", 379b0453382SBill Fenner ip6addr_string(&oip->ip6_dst), 380b0453382SBill Fenner udpport_string(dport)); 381b0453382SBill Fenner break; 382b0453382SBill Fenner default: 3831de50e9fSSam Leffler printf(", %s protocol %d port %d unreachable", 384b0453382SBill Fenner ip6addr_string(&oip->ip6_dst), 385b0453382SBill Fenner oip->ip6_nxt, dport); 386b0453382SBill Fenner break; 387b0453382SBill Fenner } 388b0453382SBill Fenner break; 389b0453382SBill Fenner default: 3901de50e9fSSam Leffler if (vflag <= 1) { 3911de50e9fSSam Leffler print_unknown_data(bp,"\n\t",length); 3921de50e9fSSam Leffler return; 3931de50e9fSSam Leffler } 394b0453382SBill Fenner break; 395b0453382SBill Fenner } 396b0453382SBill Fenner break; 397b0453382SBill Fenner case ICMP6_PACKET_TOO_BIG: 398b0453382SBill Fenner TCHECK(dp->icmp6_mtu); 3991de50e9fSSam Leffler printf(", mtu %u", EXTRACT_32BITS(&dp->icmp6_mtu)); 400b0453382SBill Fenner break; 401b0453382SBill Fenner case ICMP6_TIME_EXCEEDED: 402b0453382SBill Fenner TCHECK(oip->ip6_dst); 403b0453382SBill Fenner switch (dp->icmp6_code) { 404b0453382SBill Fenner case ICMP6_TIME_EXCEED_TRANSIT: 4051de50e9fSSam Leffler printf(" for %s", 406b0453382SBill Fenner ip6addr_string(&oip->ip6_dst)); 407b0453382SBill Fenner break; 408b0453382SBill Fenner case ICMP6_TIME_EXCEED_REASSEMBLY: 4091de50e9fSSam Leffler printf(" (reassembly)"); 410b0453382SBill Fenner break; 411b0453382SBill Fenner default: 4121de50e9fSSam Leffler printf(", unknown code (%u)", dp->icmp6_code); 413b0453382SBill Fenner break; 414b0453382SBill Fenner } 415b0453382SBill Fenner break; 416b0453382SBill Fenner case ICMP6_PARAM_PROB: 417b0453382SBill Fenner TCHECK(oip->ip6_dst); 418b0453382SBill Fenner switch (dp->icmp6_code) { 419b0453382SBill Fenner case ICMP6_PARAMPROB_HEADER: 4201de50e9fSSam Leffler printf(", errorneous - octet %u", EXTRACT_32BITS(&dp->icmp6_pptr)); 421b0453382SBill Fenner break; 422b0453382SBill Fenner case ICMP6_PARAMPROB_NEXTHEADER: 4231de50e9fSSam Leffler printf(", next header - octet %u", EXTRACT_32BITS(&dp->icmp6_pptr)); 424b0453382SBill Fenner break; 425b0453382SBill Fenner case ICMP6_PARAMPROB_OPTION: 4261de50e9fSSam Leffler printf(", option - octet %u", EXTRACT_32BITS(&dp->icmp6_pptr)); 427b0453382SBill Fenner break; 428b0453382SBill Fenner default: 4291de50e9fSSam Leffler printf(", code-#%d", 430b0453382SBill Fenner dp->icmp6_code); 431b0453382SBill Fenner break; 432b0453382SBill Fenner } 433b0453382SBill Fenner break; 434b0453382SBill Fenner case ICMP6_ECHO_REQUEST: 435b0453382SBill Fenner case ICMP6_ECHO_REPLY: 4365b0fe478SBruce M Simpson TCHECK(dp->icmp6_seq); 4371de50e9fSSam Leffler printf(", seq %u", EXTRACT_16BITS(&dp->icmp6_seq)); 438b0453382SBill Fenner break; 439b0453382SBill Fenner case ICMP6_MEMBERSHIP_QUERY: 4401de50e9fSSam Leffler if (length == MLD_MINLEN) { 441b0453382SBill Fenner mld6_print((const u_char *)dp); 4421de50e9fSSam Leffler } else if (length >= MLDV2_MINLEN) { 4431de50e9fSSam Leffler printf(" v2"); 4441de50e9fSSam Leffler mldv2_query_print((const u_char *)dp, length); 4451de50e9fSSam Leffler } else { 4461de50e9fSSam Leffler printf(" unknown-version (len %u) ", length); 4471de50e9fSSam Leffler } 448b0453382SBill Fenner break; 449b0453382SBill Fenner case ICMP6_MEMBERSHIP_REPORT: 450b0453382SBill Fenner mld6_print((const u_char *)dp); 451b0453382SBill Fenner break; 452b0453382SBill Fenner case ICMP6_MEMBERSHIP_REDUCTION: 453b0453382SBill Fenner mld6_print((const u_char *)dp); 454b0453382SBill Fenner break; 455b0453382SBill Fenner case ND_ROUTER_SOLICIT: 456b0453382SBill Fenner #define RTSOLLEN 8 4571de50e9fSSam Leffler if (vflag) { 458b0453382SBill Fenner icmp6_opt_print((const u_char *)dp + RTSOLLEN, 4595b0fe478SBruce M Simpson length - RTSOLLEN); 460b0453382SBill Fenner } 461b0453382SBill Fenner break; 462b0453382SBill Fenner case ND_ROUTER_ADVERT: 4631de50e9fSSam Leffler #define RTADVLEN 16 464b0453382SBill Fenner if (vflag) { 465b0453382SBill Fenner struct nd_router_advert *p; 466b0453382SBill Fenner 467b0453382SBill Fenner p = (struct nd_router_advert *)dp; 468b0453382SBill Fenner TCHECK(p->nd_ra_retransmit); 4691de50e9fSSam Leffler printf("\n\thop limit %u, Flags [%s]" \ 4701de50e9fSSam Leffler ", pref %s, router lifetime %us, reachable time %us, retrans time %us", 4711de50e9fSSam Leffler (u_int)p->nd_ra_curhoplimit, 4721de50e9fSSam Leffler bittok2str(icmp6_opt_ra_flag_values,"none",(p->nd_ra_flags_reserved)), 4731de50e9fSSam Leffler get_rtpref(p->nd_ra_flags_reserved), 4741de50e9fSSam Leffler EXTRACT_16BITS(&p->nd_ra_router_lifetime), 4751de50e9fSSam Leffler EXTRACT_32BITS(&p->nd_ra_reachable), 4765b0fe478SBruce M Simpson EXTRACT_32BITS(&p->nd_ra_retransmit)); 4771de50e9fSSam Leffler 478b0453382SBill Fenner icmp6_opt_print((const u_char *)dp + RTADVLEN, 4795b0fe478SBruce M Simpson length - RTADVLEN); 480b0453382SBill Fenner } 481b0453382SBill Fenner break; 482b0453382SBill Fenner case ND_NEIGHBOR_SOLICIT: 483b0453382SBill Fenner { 484b0453382SBill Fenner struct nd_neighbor_solicit *p; 485b0453382SBill Fenner p = (struct nd_neighbor_solicit *)dp; 486b0453382SBill Fenner TCHECK(p->nd_ns_target); 4871de50e9fSSam Leffler printf(", who has %s", ip6addr_string(&p->nd_ns_target)); 488b0453382SBill Fenner if (vflag) { 489b0453382SBill Fenner #define NDSOLLEN 24 490b0453382SBill Fenner icmp6_opt_print((const u_char *)dp + NDSOLLEN, 4915b0fe478SBruce M Simpson length - NDSOLLEN); 492b0453382SBill Fenner } 493b0453382SBill Fenner } 494b0453382SBill Fenner break; 495b0453382SBill Fenner case ND_NEIGHBOR_ADVERT: 496b0453382SBill Fenner { 497b0453382SBill Fenner struct nd_neighbor_advert *p; 498b0453382SBill Fenner 499b0453382SBill Fenner p = (struct nd_neighbor_advert *)dp; 500b0453382SBill Fenner TCHECK(p->nd_na_target); 5011de50e9fSSam Leffler printf(", tgt is %s", 502b0453382SBill Fenner ip6addr_string(&p->nd_na_target)); 503b0453382SBill Fenner if (vflag) { 5041de50e9fSSam Leffler printf(", Flags [%s]", 5051de50e9fSSam Leffler bittok2str(icmp6_nd_na_flag_values, 5061de50e9fSSam Leffler "none", 5071de50e9fSSam Leffler EXTRACT_32BITS(&p->nd_na_flags_reserved))); 508b0453382SBill Fenner #define NDADVLEN 24 509b0453382SBill Fenner icmp6_opt_print((const u_char *)dp + NDADVLEN, 5105b0fe478SBruce M Simpson length - NDADVLEN); 511685295f4SBill Fenner #undef NDADVLEN 512b0453382SBill Fenner } 513b0453382SBill Fenner } 514b0453382SBill Fenner break; 515b0453382SBill Fenner case ND_REDIRECT: 516b0453382SBill Fenner #define RDR(i) ((struct nd_redirect *)(i)) 517b0453382SBill Fenner TCHECK(RDR(dp)->nd_rd_dst); 5181de50e9fSSam Leffler printf(", %s", getname6((const u_char *)&RDR(dp)->nd_rd_dst)); 5195b0fe478SBruce M Simpson TCHECK(RDR(dp)->nd_rd_target); 520685295f4SBill Fenner printf(" to %s", 521685295f4SBill Fenner getname6((const u_char*)&RDR(dp)->nd_rd_target)); 522b0453382SBill Fenner #define REDIRECTLEN 40 523b0453382SBill Fenner if (vflag) { 524b0453382SBill Fenner icmp6_opt_print((const u_char *)dp + REDIRECTLEN, 5255b0fe478SBruce M Simpson length - REDIRECTLEN); 526b0453382SBill Fenner } 527b0453382SBill Fenner break; 528685295f4SBill Fenner #undef REDIRECTLEN 529685295f4SBill Fenner #undef RDR 530b0453382SBill Fenner case ICMP6_ROUTER_RENUMBERING: 5315b0fe478SBruce M Simpson icmp6_rrenum_print(bp, ep); 532b0453382SBill Fenner break; 533685295f4SBill Fenner case ICMP6_NI_QUERY: 534685295f4SBill Fenner case ICMP6_NI_REPLY: 5355b0fe478SBruce M Simpson icmp6_nodeinfo_print(length, bp, ep); 5365b0fe478SBruce M Simpson break; 5371de50e9fSSam Leffler case IND_SOLICIT: 5381de50e9fSSam Leffler case IND_ADVERT: 5391de50e9fSSam Leffler break; 5401de50e9fSSam Leffler case ICMP6_V2_MEMBERSHIP_REPORT: 5411de50e9fSSam Leffler mldv2_report_print((const u_char *) dp, length); 5421de50e9fSSam Leffler break; 5431de50e9fSSam Leffler case ICMP6_MOBILEPREFIX_SOLICIT: /* fall through */ 5445b0fe478SBruce M Simpson case ICMP6_HADISCOV_REQUEST: 5455b0fe478SBruce M Simpson TCHECK(dp->icmp6_data16[0]); 5461de50e9fSSam Leffler printf(", id 0x%04x", EXTRACT_16BITS(&dp->icmp6_data16[0])); 5475b0fe478SBruce M Simpson break; 5485b0fe478SBruce M Simpson case ICMP6_HADISCOV_REPLY: 5495b0fe478SBruce M Simpson if (vflag) { 5505b0fe478SBruce M Simpson struct in6_addr *in6; 5515b0fe478SBruce M Simpson u_char *cp; 5525b0fe478SBruce M Simpson 5535b0fe478SBruce M Simpson TCHECK(dp->icmp6_data16[0]); 5541de50e9fSSam Leffler printf(", id 0x%04x", EXTRACT_16BITS(&dp->icmp6_data16[0])); 5555b0fe478SBruce M Simpson cp = (u_char *)dp + length; 5565b0fe478SBruce M Simpson in6 = (struct in6_addr *)(dp + 1); 5575b0fe478SBruce M Simpson for (; (u_char *)in6 < cp; in6++) { 5585b0fe478SBruce M Simpson TCHECK(*in6); 5595b0fe478SBruce M Simpson printf(", %s", ip6addr_string(in6)); 5605b0fe478SBruce M Simpson } 5615b0fe478SBruce M Simpson } 5625b0fe478SBruce M Simpson break; 5635b0fe478SBruce M Simpson case ICMP6_MOBILEPREFIX_ADVERT: 5645b0fe478SBruce M Simpson if (vflag) { 5655b0fe478SBruce M Simpson TCHECK(dp->icmp6_data16[0]); 5661de50e9fSSam Leffler printf(", id 0x%04x", EXTRACT_16BITS(&dp->icmp6_data16[0])); 5675b0fe478SBruce M Simpson if (dp->icmp6_data16[1] & 0xc0) 5685b0fe478SBruce M Simpson printf(" "); 5695b0fe478SBruce M Simpson if (dp->icmp6_data16[1] & 0x80) 5705b0fe478SBruce M Simpson printf("M"); 5715b0fe478SBruce M Simpson if (dp->icmp6_data16[1] & 0x40) 5725b0fe478SBruce M Simpson printf("O"); 5735b0fe478SBruce M Simpson #define MPADVLEN 8 5745b0fe478SBruce M Simpson icmp6_opt_print((const u_char *)dp + MPADVLEN, 5755b0fe478SBruce M Simpson length - MPADVLEN); 5765b0fe478SBruce M Simpson } 577b0453382SBill Fenner break; 57827df3f5dSRui Paulo case ND_RPL_MESSAGE: 57927df3f5dSRui Paulo rpl_print(ndo, dp, &dp->icmp6_data8[0], length); 58027df3f5dSRui Paulo break; 581b0453382SBill Fenner default: 5821de50e9fSSam Leffler printf(", length %u", length); 5831de50e9fSSam Leffler if (vflag <= 1) 5841de50e9fSSam Leffler print_unknown_data(bp,"\n\t", length); 5851de50e9fSSam Leffler return; 586b0453382SBill Fenner } 5871de50e9fSSam Leffler if (!vflag) 5881de50e9fSSam Leffler printf(", length %u", length); 589b0453382SBill Fenner return; 590b0453382SBill Fenner trunc: 591b0453382SBill Fenner fputs("[|icmp6]", stdout); 592b0453382SBill Fenner } 593b0453382SBill Fenner 594685295f4SBill Fenner static struct udphdr * 5955b0fe478SBruce M Simpson get_upperlayer(u_char *bp, u_int *prot) 596685295f4SBill Fenner { 597a90e161bSBill Fenner const u_char *ep; 598685295f4SBill Fenner struct ip6_hdr *ip6 = (struct ip6_hdr *)bp; 599685295f4SBill Fenner struct udphdr *uh; 600685295f4SBill Fenner struct ip6_hbh *hbh; 601685295f4SBill Fenner struct ip6_frag *fragh; 602685295f4SBill Fenner struct ah *ah; 6035b0fe478SBruce M Simpson u_int nh; 6045b0fe478SBruce M Simpson int hlen; 605685295f4SBill Fenner 606685295f4SBill Fenner /* 'ep' points to the end of available data. */ 607685295f4SBill Fenner ep = snapend; 608685295f4SBill Fenner 6095b0fe478SBruce M Simpson if (!TTEST(ip6->ip6_nxt)) 610685295f4SBill Fenner return NULL; 611685295f4SBill Fenner 612685295f4SBill Fenner nh = ip6->ip6_nxt; 613685295f4SBill Fenner hlen = sizeof(struct ip6_hdr); 614685295f4SBill Fenner 615f4d0c64aSSam Leffler while (bp < ep) { 616685295f4SBill Fenner bp += hlen; 617685295f4SBill Fenner 618685295f4SBill Fenner switch(nh) { 619685295f4SBill Fenner case IPPROTO_UDP: 620685295f4SBill Fenner case IPPROTO_TCP: 621685295f4SBill Fenner uh = (struct udphdr *)bp; 622685295f4SBill Fenner if (TTEST(uh->uh_dport)) { 623685295f4SBill Fenner *prot = nh; 624685295f4SBill Fenner return(uh); 625685295f4SBill Fenner } 626685295f4SBill Fenner else 627685295f4SBill Fenner return(NULL); 628685295f4SBill Fenner /* NOTREACHED */ 629685295f4SBill Fenner 630685295f4SBill Fenner case IPPROTO_HOPOPTS: 631685295f4SBill Fenner case IPPROTO_DSTOPTS: 632685295f4SBill Fenner case IPPROTO_ROUTING: 633685295f4SBill Fenner hbh = (struct ip6_hbh *)bp; 6345b0fe478SBruce M Simpson if (!TTEST(hbh->ip6h_len)) 635685295f4SBill Fenner return(NULL); 636685295f4SBill Fenner nh = hbh->ip6h_nxt; 637685295f4SBill Fenner hlen = (hbh->ip6h_len + 1) << 3; 638685295f4SBill Fenner break; 639685295f4SBill Fenner 640685295f4SBill Fenner case IPPROTO_FRAGMENT: /* this should be odd, but try anyway */ 641685295f4SBill Fenner fragh = (struct ip6_frag *)bp; 6425b0fe478SBruce M Simpson if (!TTEST(fragh->ip6f_offlg)) 643685295f4SBill Fenner return(NULL); 644685295f4SBill Fenner /* fragments with non-zero offset are meaningless */ 6455b0fe478SBruce M Simpson if ((EXTRACT_16BITS(&fragh->ip6f_offlg) & IP6F_OFF_MASK) != 0) 646685295f4SBill Fenner return(NULL); 647685295f4SBill Fenner nh = fragh->ip6f_nxt; 648685295f4SBill Fenner hlen = sizeof(struct ip6_frag); 649685295f4SBill Fenner break; 650685295f4SBill Fenner 651685295f4SBill Fenner case IPPROTO_AH: 652685295f4SBill Fenner ah = (struct ah *)bp; 6535b0fe478SBruce M Simpson if (!TTEST(ah->ah_len)) 654685295f4SBill Fenner return(NULL); 655685295f4SBill Fenner nh = ah->ah_nxt; 656685295f4SBill Fenner hlen = (ah->ah_len + 2) << 2; 657685295f4SBill Fenner break; 658685295f4SBill Fenner 659685295f4SBill Fenner default: /* unknown or undecodable header */ 660685295f4SBill Fenner *prot = nh; /* meaningless, but set here anyway */ 661685295f4SBill Fenner return(NULL); 662685295f4SBill Fenner } 663685295f4SBill Fenner } 664685295f4SBill Fenner 665685295f4SBill Fenner return(NULL); /* should be notreached, though */ 666685295f4SBill Fenner } 667685295f4SBill Fenner 6685b0fe478SBruce M Simpson static void 669a90e161bSBill Fenner icmp6_opt_print(const u_char *bp, int resid) 670b0453382SBill Fenner { 671a90e161bSBill Fenner const struct nd_opt_hdr *op; 672a90e161bSBill Fenner const struct nd_opt_hdr *opl; /* why there's no struct? */ 673a90e161bSBill Fenner const struct nd_opt_prefix_info *opp; 674a90e161bSBill Fenner const struct icmp6_opts_redirect *opr; 675a90e161bSBill Fenner const struct nd_opt_mtu *opm; 67627df3f5dSRui Paulo const struct nd_opt_rdnss *oprd; 677*d03c0883SXin LI const struct nd_opt_dnssl *opds; 678a90e161bSBill Fenner const struct nd_opt_advinterval *opa; 6795b0fe478SBruce M Simpson const struct nd_opt_homeagent_info *oph; 680a90e161bSBill Fenner const struct nd_opt_route_info *opri; 681*d03c0883SXin LI const u_char *cp, *ep, *domp; 682a90e161bSBill Fenner struct in6_addr in6, *in6p; 683a90e161bSBill Fenner size_t l; 68427df3f5dSRui Paulo u_int i; 685b0453382SBill Fenner 686b0453382SBill Fenner #define ECHECK(var) if ((u_char *)&(var) > ep - sizeof(var)) return 687b0453382SBill Fenner 688a90e161bSBill Fenner cp = bp; 689685295f4SBill Fenner /* 'ep' points to the end of available data. */ 690b0453382SBill Fenner ep = snapend; 691b0453382SBill Fenner 692a90e161bSBill Fenner while (cp < ep) { 693a90e161bSBill Fenner op = (struct nd_opt_hdr *)cp; 694a90e161bSBill Fenner 695b0453382SBill Fenner ECHECK(op->nd_opt_len); 696b0453382SBill Fenner if (resid <= 0) 697b0453382SBill Fenner return; 698a90e161bSBill Fenner if (op->nd_opt_len == 0) 699a90e161bSBill Fenner goto trunc; 700a90e161bSBill Fenner if (cp + (op->nd_opt_len << 3) > ep) 701a90e161bSBill Fenner goto trunc; 702a90e161bSBill Fenner 7031de50e9fSSam Leffler printf("\n\t %s option (%u), length %u (%u): ", 7041de50e9fSSam Leffler tok2str(icmp6_opt_values, "unknown", op->nd_opt_type), 7051de50e9fSSam Leffler op->nd_opt_type, 7061de50e9fSSam Leffler op->nd_opt_len << 3, 7071de50e9fSSam Leffler op->nd_opt_len); 7081de50e9fSSam Leffler 709b0453382SBill Fenner switch (op->nd_opt_type) { 710b0453382SBill Fenner case ND_OPT_SOURCE_LINKADDR: 711b0453382SBill Fenner opl = (struct nd_opt_hdr *)op; 712a90e161bSBill Fenner l = (op->nd_opt_len << 3) - 2; 713a90e161bSBill Fenner print_lladdr(cp + 2, l); 714b0453382SBill Fenner break; 715b0453382SBill Fenner case ND_OPT_TARGET_LINKADDR: 716b0453382SBill Fenner opl = (struct nd_opt_hdr *)op; 717a90e161bSBill Fenner l = (op->nd_opt_len << 3) - 2; 718a90e161bSBill Fenner print_lladdr(cp + 2, l); 719b0453382SBill Fenner break; 720b0453382SBill Fenner case ND_OPT_PREFIX_INFORMATION: 721b0453382SBill Fenner opp = (struct nd_opt_prefix_info *)op; 722b0453382SBill Fenner TCHECK(opp->nd_opt_pi_prefix); 723*d03c0883SXin LI printf("%s/%u%s, Flags [%s], valid time %s", 724a90e161bSBill Fenner ip6addr_string(&opp->nd_opt_pi_prefix), 7251de50e9fSSam Leffler opp->nd_opt_pi_prefix_len, 7261de50e9fSSam Leffler (op->nd_opt_len != 4) ? "badlen" : "", 7271de50e9fSSam Leffler bittok2str(icmp6_opt_pi_flag_values, "none", opp->nd_opt_pi_flags_reserved), 7281de50e9fSSam Leffler get_lifetime(EXTRACT_32BITS(&opp->nd_opt_pi_valid_time))); 729*d03c0883SXin LI printf(", pref. time %s", get_lifetime(EXTRACT_32BITS(&opp->nd_opt_pi_preferred_time))); 730b0453382SBill Fenner break; 731b0453382SBill Fenner case ND_OPT_REDIRECTED_HEADER: 732b0453382SBill Fenner opr = (struct icmp6_opts_redirect *)op; 7331de50e9fSSam Leffler print_unknown_data(bp,"\n\t ",op->nd_opt_len<<3); 734b0453382SBill Fenner /* xxx */ 735b0453382SBill Fenner break; 736b0453382SBill Fenner case ND_OPT_MTU: 737b0453382SBill Fenner opm = (struct nd_opt_mtu *)op; 738b0453382SBill Fenner TCHECK(opm->nd_opt_mtu_mtu); 7391de50e9fSSam Leffler printf(" %u%s", 7401de50e9fSSam Leffler EXTRACT_32BITS(&opm->nd_opt_mtu_mtu), 7411de50e9fSSam Leffler (op->nd_opt_len != 1) ? "bad option length" : "" ); 742b0453382SBill Fenner break; 74327df3f5dSRui Paulo case ND_OPT_RDNSS: 74427df3f5dSRui Paulo oprd = (struct nd_opt_rdnss *)op; 74527df3f5dSRui Paulo l = (op->nd_opt_len - 1) / 2; 74627df3f5dSRui Paulo printf(" lifetime %us,", 74727df3f5dSRui Paulo EXTRACT_32BITS(&oprd->nd_opt_rdnss_lifetime)); 74827df3f5dSRui Paulo for (i = 0; i < l; i++) { 74927df3f5dSRui Paulo TCHECK(oprd->nd_opt_rdnss_addr[i]); 75027df3f5dSRui Paulo printf(" addr: %s", 75127df3f5dSRui Paulo ip6addr_string(&oprd->nd_opt_rdnss_addr[i])); 75227df3f5dSRui Paulo } 75327df3f5dSRui Paulo break; 754*d03c0883SXin LI case ND_OPT_DNSSL: 755*d03c0883SXin LI opds = (struct nd_opt_dnssl *)op; 756*d03c0883SXin LI printf(" lifetime %us, domain(s):", 757*d03c0883SXin LI EXTRACT_32BITS(&opds->nd_opt_dnssl_lifetime)); 758*d03c0883SXin LI domp = cp + 8; /* domain names, variable-sized, RFC1035-encoded */ 759*d03c0883SXin LI while (domp < cp + (op->nd_opt_len << 3) && *domp != '\0') 760*d03c0883SXin LI { 761*d03c0883SXin LI printf (" "); 762*d03c0883SXin LI if ((domp = ns_nprint (domp, bp)) == NULL) 763*d03c0883SXin LI goto trunc; 764*d03c0883SXin LI } 765*d03c0883SXin LI break; 766a90e161bSBill Fenner case ND_OPT_ADVINTERVAL: 767a90e161bSBill Fenner opa = (struct nd_opt_advinterval *)op; 768a90e161bSBill Fenner TCHECK(opa->nd_opt_adv_interval); 769d09a7e67SXin LI printf(" %ums", EXTRACT_32BITS(&opa->nd_opt_adv_interval)); 770a90e161bSBill Fenner break; 7715b0fe478SBruce M Simpson case ND_OPT_HOMEAGENT_INFO: 7725b0fe478SBruce M Simpson oph = (struct nd_opt_homeagent_info *)op; 7735b0fe478SBruce M Simpson TCHECK(oph->nd_opt_hai_lifetime); 7741de50e9fSSam Leffler printf(" preference %u, lifetime %u", 7751de50e9fSSam Leffler EXTRACT_16BITS(&oph->nd_opt_hai_preference), 7761de50e9fSSam Leffler EXTRACT_16BITS(&oph->nd_opt_hai_lifetime)); 7775b0fe478SBruce M Simpson break; 778a90e161bSBill Fenner case ND_OPT_ROUTE_INFO: 779a90e161bSBill Fenner opri = (struct nd_opt_route_info *)op; 780a90e161bSBill Fenner TCHECK(opri->nd_opt_rti_lifetime); 781a90e161bSBill Fenner memset(&in6, 0, sizeof(in6)); 782a90e161bSBill Fenner in6p = (struct in6_addr *)(opri + 1); 783a90e161bSBill Fenner switch (op->nd_opt_len) { 784a90e161bSBill Fenner case 1: 785a90e161bSBill Fenner break; 786a90e161bSBill Fenner case 2: 787a90e161bSBill Fenner TCHECK2(*in6p, 8); 788a90e161bSBill Fenner memcpy(&in6, opri + 1, 8); 789a90e161bSBill Fenner break; 790a90e161bSBill Fenner case 3: 791a90e161bSBill Fenner TCHECK(*in6p); 792a90e161bSBill Fenner memcpy(&in6, opri + 1, sizeof(in6)); 793685295f4SBill Fenner break; 794b0453382SBill Fenner default: 795a90e161bSBill Fenner goto trunc; 796a90e161bSBill Fenner } 797a90e161bSBill Fenner printf(" %s/%u", ip6addr_string(&in6), 798a90e161bSBill Fenner opri->nd_opt_rti_prefixlen); 799a90e161bSBill Fenner printf(", pref=%s", get_rtpref(opri->nd_opt_rti_flags)); 800a90e161bSBill Fenner printf(", lifetime=%s", 8015b0fe478SBruce M Simpson get_lifetime(EXTRACT_32BITS(&opri->nd_opt_rti_lifetime))); 802a90e161bSBill Fenner break; 803a90e161bSBill Fenner default: 8041de50e9fSSam Leffler if (vflag <= 1) { 8051de50e9fSSam Leffler print_unknown_data(cp+2,"\n\t ", (op->nd_opt_len << 3) - 2); /* skip option header */ 8061de50e9fSSam Leffler return; 8071de50e9fSSam Leffler } 808b0453382SBill Fenner break; 809b0453382SBill Fenner } 8101de50e9fSSam Leffler /* do we want to see an additional hexdump ? */ 8111de50e9fSSam Leffler if (vflag> 1) 8121de50e9fSSam Leffler print_unknown_data(cp+2,"\n\t ", (op->nd_opt_len << 3) - 2); /* skip option header */ 813a90e161bSBill Fenner 814a90e161bSBill Fenner cp += op->nd_opt_len << 3; 815a90e161bSBill Fenner resid -= op->nd_opt_len << 3; 816a90e161bSBill Fenner } 817b0453382SBill Fenner return; 818a90e161bSBill Fenner 819b0453382SBill Fenner trunc: 820b0453382SBill Fenner fputs("[ndp opt]", stdout); 821b0453382SBill Fenner return; 822b0453382SBill Fenner #undef ECHECK 823b0453382SBill Fenner } 824b0453382SBill Fenner 8255b0fe478SBruce M Simpson static void 826a90e161bSBill Fenner mld6_print(const u_char *bp) 827b0453382SBill Fenner { 828a90e161bSBill Fenner struct mld6_hdr *mp = (struct mld6_hdr *)bp; 829a90e161bSBill Fenner const u_char *ep; 830b0453382SBill Fenner 831685295f4SBill Fenner /* 'ep' points to the end of available data. */ 832b0453382SBill Fenner ep = snapend; 833b0453382SBill Fenner 834b0453382SBill Fenner if ((u_char *)mp + sizeof(*mp) > ep) 835b0453382SBill Fenner return; 836b0453382SBill Fenner 8375b0fe478SBruce M Simpson printf("max resp delay: %d ", EXTRACT_16BITS(&mp->mld6_maxdelay)); 838b0453382SBill Fenner printf("addr: %s", ip6addr_string(&mp->mld6_addr)); 839685295f4SBill Fenner } 840685295f4SBill Fenner 841685295f4SBill Fenner static void 8421de50e9fSSam Leffler mldv2_report_print(const u_char *bp, u_int len) 8431de50e9fSSam Leffler { 8441de50e9fSSam Leffler struct icmp6_hdr *icp = (struct icmp6_hdr *) bp; 8451de50e9fSSam Leffler u_int group, nsrcs, ngroups; 8461de50e9fSSam Leffler u_int i, j; 8471de50e9fSSam Leffler 8481de50e9fSSam Leffler /* Minimum len is 8 */ 8491de50e9fSSam Leffler if (len < 8) { 8501de50e9fSSam Leffler printf(" [invalid len %d]", len); 8511de50e9fSSam Leffler return; 8521de50e9fSSam Leffler } 8531de50e9fSSam Leffler 8541de50e9fSSam Leffler TCHECK(icp->icmp6_data16[1]); 85527df3f5dSRui Paulo ngroups = EXTRACT_16BITS(&icp->icmp6_data16[1]); 8561de50e9fSSam Leffler printf(", %d group record(s)", ngroups); 8571de50e9fSSam Leffler if (vflag > 0) { 8581de50e9fSSam Leffler /* Print the group records */ 8591de50e9fSSam Leffler group = 8; 8601de50e9fSSam Leffler for (i = 0; i < ngroups; i++) { 8611de50e9fSSam Leffler /* type(1) + auxlen(1) + numsrc(2) + grp(16) */ 8621de50e9fSSam Leffler if (len < group + 20) { 8631de50e9fSSam Leffler printf(" [invalid number of groups]"); 8641de50e9fSSam Leffler return; 8651de50e9fSSam Leffler } 8662ebc47dbSSam Leffler TCHECK2(bp[group + 4], sizeof(struct in6_addr)); 8671de50e9fSSam Leffler printf(" [gaddr %s", ip6addr_string(&bp[group + 4])); 8681de50e9fSSam Leffler printf(" %s", tok2str(mldv2report2str, " [v2-report-#%d]", 8691de50e9fSSam Leffler bp[group])); 8701de50e9fSSam Leffler nsrcs = (bp[group + 2] << 8) + bp[group + 3]; 8711de50e9fSSam Leffler /* Check the number of sources and print them */ 8722ebc47dbSSam Leffler if (len < group + 20 + (nsrcs * sizeof(struct in6_addr))) { 8731de50e9fSSam Leffler printf(" [invalid number of sources %d]", nsrcs); 8741de50e9fSSam Leffler return; 8751de50e9fSSam Leffler } 8761de50e9fSSam Leffler if (vflag == 1) 8771de50e9fSSam Leffler printf(", %d source(s)", nsrcs); 8781de50e9fSSam Leffler else { 8791de50e9fSSam Leffler /* Print the sources */ 8801de50e9fSSam Leffler (void)printf(" {"); 8811de50e9fSSam Leffler for (j = 0; j < nsrcs; j++) { 8822ebc47dbSSam Leffler TCHECK2(bp[group + 20 + j * sizeof(struct in6_addr)], 8832ebc47dbSSam Leffler sizeof(struct in6_addr)); 8842ebc47dbSSam Leffler printf(" %s", ip6addr_string(&bp[group + 20 + j * sizeof(struct in6_addr)])); 8851de50e9fSSam Leffler } 8861de50e9fSSam Leffler (void)printf(" }"); 8871de50e9fSSam Leffler } 8881de50e9fSSam Leffler /* Next group record */ 8892ebc47dbSSam Leffler group += 20 + nsrcs * sizeof(struct in6_addr); 8901de50e9fSSam Leffler printf("]"); 8911de50e9fSSam Leffler } 8921de50e9fSSam Leffler } 8931de50e9fSSam Leffler return; 8941de50e9fSSam Leffler trunc: 8951de50e9fSSam Leffler (void)printf("[|icmp6]"); 8961de50e9fSSam Leffler return; 8971de50e9fSSam Leffler } 8981de50e9fSSam Leffler 8991de50e9fSSam Leffler static void 9001de50e9fSSam Leffler mldv2_query_print(const u_char *bp, u_int len) 9011de50e9fSSam Leffler { 9021de50e9fSSam Leffler struct icmp6_hdr *icp = (struct icmp6_hdr *) bp; 9031de50e9fSSam Leffler u_int mrc; 9041de50e9fSSam Leffler int mrt, qqi; 9051de50e9fSSam Leffler u_int nsrcs; 9061de50e9fSSam Leffler register u_int i; 9071de50e9fSSam Leffler 9081de50e9fSSam Leffler /* Minimum len is 28 */ 9091de50e9fSSam Leffler if (len < 28) { 9101de50e9fSSam Leffler printf(" [invalid len %d]", len); 9111de50e9fSSam Leffler return; 9121de50e9fSSam Leffler } 9131de50e9fSSam Leffler TCHECK(icp->icmp6_data16[0]); 91427df3f5dSRui Paulo mrc = EXTRACT_16BITS(&icp->icmp6_data16[0]); 9151de50e9fSSam Leffler if (mrc < 32768) { 9161de50e9fSSam Leffler mrt = mrc; 9171de50e9fSSam Leffler } else { 9181de50e9fSSam Leffler mrt = ((mrc & 0x0fff) | 0x1000) << (((mrc & 0x7000) >> 12) + 3); 9191de50e9fSSam Leffler } 9201de50e9fSSam Leffler if (vflag) { 9211de50e9fSSam Leffler (void)printf(" [max resp delay=%d]", mrt); 9221de50e9fSSam Leffler } 9232ebc47dbSSam Leffler TCHECK2(bp[8], sizeof(struct in6_addr)); 9241de50e9fSSam Leffler printf(" [gaddr %s", ip6addr_string(&bp[8])); 9251de50e9fSSam Leffler 9261de50e9fSSam Leffler if (vflag) { 9271de50e9fSSam Leffler TCHECK(bp[25]); 9281de50e9fSSam Leffler if (bp[24] & 0x08) { 9291de50e9fSSam Leffler printf(" sflag"); 9301de50e9fSSam Leffler } 9311de50e9fSSam Leffler if (bp[24] & 0x07) { 9321de50e9fSSam Leffler printf(" robustness=%d", bp[24] & 0x07); 9331de50e9fSSam Leffler } 9341de50e9fSSam Leffler if (bp[25] < 128) { 9351de50e9fSSam Leffler qqi = bp[25]; 9361de50e9fSSam Leffler } else { 9371de50e9fSSam Leffler qqi = ((bp[25] & 0x0f) | 0x10) << (((bp[25] & 0x70) >> 4) + 3); 9381de50e9fSSam Leffler } 9391de50e9fSSam Leffler printf(" qqi=%d", qqi); 9401de50e9fSSam Leffler } 9411de50e9fSSam Leffler 9421de50e9fSSam Leffler TCHECK2(bp[26], 2); 94327df3f5dSRui Paulo nsrcs = EXTRACT_16BITS(&bp[26]); 9441de50e9fSSam Leffler if (nsrcs > 0) { 9452ebc47dbSSam Leffler if (len < 28 + nsrcs * sizeof(struct in6_addr)) 9461de50e9fSSam Leffler printf(" [invalid number of sources]"); 9471de50e9fSSam Leffler else if (vflag > 1) { 9481de50e9fSSam Leffler printf(" {"); 9491de50e9fSSam Leffler for (i = 0; i < nsrcs; i++) { 9502ebc47dbSSam Leffler TCHECK2(bp[28 + i * sizeof(struct in6_addr)], 9512ebc47dbSSam Leffler sizeof(struct in6_addr)); 9522ebc47dbSSam Leffler printf(" %s", ip6addr_string(&bp[28 + i * sizeof(struct in6_addr)])); 9531de50e9fSSam Leffler } 9541de50e9fSSam Leffler printf(" }"); 9551de50e9fSSam Leffler } else 9561de50e9fSSam Leffler printf(", %d source(s)", nsrcs); 9571de50e9fSSam Leffler } 9581de50e9fSSam Leffler printf("]"); 9591de50e9fSSam Leffler return; 9601de50e9fSSam Leffler trunc: 9611de50e9fSSam Leffler (void)printf("[|icmp6]"); 9621de50e9fSSam Leffler return; 9631de50e9fSSam Leffler } 9641de50e9fSSam Leffler 96527df3f5dSRui Paulo static void 966685295f4SBill Fenner dnsname_print(const u_char *cp, const u_char *ep) 967685295f4SBill Fenner { 968685295f4SBill Fenner int i; 969685295f4SBill Fenner 970685295f4SBill Fenner /* DNS name decoding - no decompression */ 971685295f4SBill Fenner printf(", \""); 972685295f4SBill Fenner while (cp < ep) { 973685295f4SBill Fenner i = *cp++; 974685295f4SBill Fenner if (i) { 975685295f4SBill Fenner if (i > ep - cp) { 976685295f4SBill Fenner printf("???"); 977685295f4SBill Fenner break; 978685295f4SBill Fenner } 979685295f4SBill Fenner while (i-- && cp < ep) { 980685295f4SBill Fenner safeputchar(*cp); 981685295f4SBill Fenner cp++; 982685295f4SBill Fenner } 983685295f4SBill Fenner if (cp + 1 < ep && *cp) 984685295f4SBill Fenner printf("."); 985685295f4SBill Fenner } else { 986685295f4SBill Fenner if (cp == ep) { 987685295f4SBill Fenner /* FQDN */ 988685295f4SBill Fenner printf("."); 989685295f4SBill Fenner } else if (cp + 1 == ep && *cp == '\0') { 990685295f4SBill Fenner /* truncated */ 991685295f4SBill Fenner } else { 992685295f4SBill Fenner /* invalid */ 993685295f4SBill Fenner printf("???"); 994685295f4SBill Fenner } 995685295f4SBill Fenner break; 996685295f4SBill Fenner } 997685295f4SBill Fenner } 998685295f4SBill Fenner printf("\""); 999685295f4SBill Fenner } 1000685295f4SBill Fenner 10015b0fe478SBruce M Simpson static void 10025b0fe478SBruce M Simpson icmp6_nodeinfo_print(u_int icmp6len, const u_char *bp, const u_char *ep) 1003685295f4SBill Fenner { 1004685295f4SBill Fenner struct icmp6_nodeinfo *ni6; 1005685295f4SBill Fenner struct icmp6_hdr *dp; 1006685295f4SBill Fenner const u_char *cp; 10075b0fe478SBruce M Simpson size_t siz, i; 1008685295f4SBill Fenner int needcomma; 1009685295f4SBill Fenner 10105b0fe478SBruce M Simpson if (ep < bp) 10115b0fe478SBruce M Simpson return; 1012685295f4SBill Fenner dp = (struct icmp6_hdr *)bp; 1013685295f4SBill Fenner ni6 = (struct icmp6_nodeinfo *)bp; 1014685295f4SBill Fenner siz = ep - bp; 1015685295f4SBill Fenner 1016685295f4SBill Fenner switch (ni6->ni_type) { 1017685295f4SBill Fenner case ICMP6_NI_QUERY: 1018685295f4SBill Fenner if (siz == sizeof(*dp) + 4) { 1019685295f4SBill Fenner /* KAME who-are-you */ 10201de50e9fSSam Leffler printf(" who-are-you request"); 1021685295f4SBill Fenner break; 1022685295f4SBill Fenner } 10231de50e9fSSam Leffler printf(" node information query"); 1024685295f4SBill Fenner 1025685295f4SBill Fenner TCHECK2(*dp, sizeof(*ni6)); 1026685295f4SBill Fenner ni6 = (struct icmp6_nodeinfo *)dp; 1027685295f4SBill Fenner printf(" ("); /*)*/ 10285b0fe478SBruce M Simpson switch (EXTRACT_16BITS(&ni6->ni_qtype)) { 1029685295f4SBill Fenner case NI_QTYPE_NOOP: 1030685295f4SBill Fenner printf("noop"); 1031685295f4SBill Fenner break; 1032685295f4SBill Fenner case NI_QTYPE_SUPTYPES: 1033685295f4SBill Fenner printf("supported qtypes"); 10345b0fe478SBruce M Simpson i = EXTRACT_16BITS(&ni6->ni_flags); 1035685295f4SBill Fenner if (i) 1036685295f4SBill Fenner printf(" [%s]", (i & 0x01) ? "C" : ""); 1037685295f4SBill Fenner break; 1038685295f4SBill Fenner break; 1039685295f4SBill Fenner case NI_QTYPE_FQDN: 1040685295f4SBill Fenner printf("DNS name"); 1041685295f4SBill Fenner break; 1042685295f4SBill Fenner case NI_QTYPE_NODEADDR: 1043685295f4SBill Fenner printf("node addresses"); 1044685295f4SBill Fenner i = ni6->ni_flags; 1045685295f4SBill Fenner if (!i) 1046685295f4SBill Fenner break; 1047685295f4SBill Fenner /* NI_NODEADDR_FLAG_TRUNCATE undefined for query */ 1048685295f4SBill Fenner printf(" [%s%s%s%s%s%s]", 1049685295f4SBill Fenner (i & NI_NODEADDR_FLAG_ANYCAST) ? "a" : "", 1050685295f4SBill Fenner (i & NI_NODEADDR_FLAG_GLOBAL) ? "G" : "", 1051685295f4SBill Fenner (i & NI_NODEADDR_FLAG_SITELOCAL) ? "S" : "", 1052685295f4SBill Fenner (i & NI_NODEADDR_FLAG_LINKLOCAL) ? "L" : "", 1053685295f4SBill Fenner (i & NI_NODEADDR_FLAG_COMPAT) ? "C" : "", 1054685295f4SBill Fenner (i & NI_NODEADDR_FLAG_ALL) ? "A" : ""); 1055685295f4SBill Fenner break; 1056685295f4SBill Fenner default: 1057685295f4SBill Fenner printf("unknown"); 1058685295f4SBill Fenner break; 1059685295f4SBill Fenner } 1060685295f4SBill Fenner 1061685295f4SBill Fenner if (ni6->ni_qtype == NI_QTYPE_NOOP || 1062685295f4SBill Fenner ni6->ni_qtype == NI_QTYPE_SUPTYPES) { 1063685295f4SBill Fenner if (siz != sizeof(*ni6)) 1064685295f4SBill Fenner if (vflag) 1065685295f4SBill Fenner printf(", invalid len"); 1066685295f4SBill Fenner /*(*/ 1067685295f4SBill Fenner printf(")"); 1068685295f4SBill Fenner break; 1069685295f4SBill Fenner } 1070685295f4SBill Fenner 1071685295f4SBill Fenner 1072685295f4SBill Fenner /* XXX backward compat, icmp-name-lookup-03 */ 1073685295f4SBill Fenner if (siz == sizeof(*ni6)) { 1074685295f4SBill Fenner printf(", 03 draft"); 1075685295f4SBill Fenner /*(*/ 1076685295f4SBill Fenner printf(")"); 1077685295f4SBill Fenner break; 1078685295f4SBill Fenner } 1079685295f4SBill Fenner 1080685295f4SBill Fenner switch (ni6->ni_code) { 1081685295f4SBill Fenner case ICMP6_NI_SUBJ_IPV6: 1082685295f4SBill Fenner if (!TTEST2(*dp, 1083685295f4SBill Fenner sizeof(*ni6) + sizeof(struct in6_addr))) 1084685295f4SBill Fenner break; 1085685295f4SBill Fenner if (siz != sizeof(*ni6) + sizeof(struct in6_addr)) { 1086685295f4SBill Fenner if (vflag) 1087685295f4SBill Fenner printf(", invalid subject len"); 1088685295f4SBill Fenner break; 1089685295f4SBill Fenner } 1090685295f4SBill Fenner printf(", subject=%s", 1091685295f4SBill Fenner getname6((const u_char *)(ni6 + 1))); 1092685295f4SBill Fenner break; 1093685295f4SBill Fenner case ICMP6_NI_SUBJ_FQDN: 1094685295f4SBill Fenner printf(", subject=DNS name"); 1095685295f4SBill Fenner cp = (const u_char *)(ni6 + 1); 1096685295f4SBill Fenner if (cp[0] == ep - cp - 1) { 1097685295f4SBill Fenner /* icmp-name-lookup-03, pascal string */ 1098685295f4SBill Fenner if (vflag) 1099685295f4SBill Fenner printf(", 03 draft"); 1100685295f4SBill Fenner cp++; 1101685295f4SBill Fenner printf(", \""); 1102685295f4SBill Fenner while (cp < ep) { 1103685295f4SBill Fenner safeputchar(*cp); 1104685295f4SBill Fenner cp++; 1105685295f4SBill Fenner } 1106685295f4SBill Fenner printf("\""); 1107685295f4SBill Fenner } else 1108685295f4SBill Fenner dnsname_print(cp, ep); 1109685295f4SBill Fenner break; 1110685295f4SBill Fenner case ICMP6_NI_SUBJ_IPV4: 1111685295f4SBill Fenner if (!TTEST2(*dp, sizeof(*ni6) + sizeof(struct in_addr))) 1112685295f4SBill Fenner break; 1113685295f4SBill Fenner if (siz != sizeof(*ni6) + sizeof(struct in_addr)) { 1114685295f4SBill Fenner if (vflag) 1115685295f4SBill Fenner printf(", invalid subject len"); 1116685295f4SBill Fenner break; 1117685295f4SBill Fenner } 1118685295f4SBill Fenner printf(", subject=%s", 1119685295f4SBill Fenner getname((const u_char *)(ni6 + 1))); 1120685295f4SBill Fenner break; 1121685295f4SBill Fenner default: 1122685295f4SBill Fenner printf(", unknown subject"); 1123685295f4SBill Fenner break; 1124685295f4SBill Fenner } 1125685295f4SBill Fenner 1126685295f4SBill Fenner /*(*/ 1127685295f4SBill Fenner printf(")"); 1128685295f4SBill Fenner break; 1129685295f4SBill Fenner 1130685295f4SBill Fenner case ICMP6_NI_REPLY: 1131685295f4SBill Fenner if (icmp6len > siz) { 1132685295f4SBill Fenner printf("[|icmp6: node information reply]"); 1133685295f4SBill Fenner break; 1134685295f4SBill Fenner } 1135685295f4SBill Fenner 1136685295f4SBill Fenner needcomma = 0; 1137685295f4SBill Fenner 1138685295f4SBill Fenner ni6 = (struct icmp6_nodeinfo *)dp; 11391de50e9fSSam Leffler printf(" node information reply"); 1140685295f4SBill Fenner printf(" ("); /*)*/ 1141685295f4SBill Fenner switch (ni6->ni_code) { 1142685295f4SBill Fenner case ICMP6_NI_SUCCESS: 1143685295f4SBill Fenner if (vflag) { 1144685295f4SBill Fenner printf("success"); 1145685295f4SBill Fenner needcomma++; 1146685295f4SBill Fenner } 1147685295f4SBill Fenner break; 1148685295f4SBill Fenner case ICMP6_NI_REFUSED: 1149685295f4SBill Fenner printf("refused"); 1150685295f4SBill Fenner needcomma++; 1151685295f4SBill Fenner if (siz != sizeof(*ni6)) 1152685295f4SBill Fenner if (vflag) 1153685295f4SBill Fenner printf(", invalid length"); 1154685295f4SBill Fenner break; 1155685295f4SBill Fenner case ICMP6_NI_UNKNOWN: 1156685295f4SBill Fenner printf("unknown"); 1157685295f4SBill Fenner needcomma++; 1158685295f4SBill Fenner if (siz != sizeof(*ni6)) 1159685295f4SBill Fenner if (vflag) 1160685295f4SBill Fenner printf(", invalid length"); 1161685295f4SBill Fenner break; 1162685295f4SBill Fenner } 1163685295f4SBill Fenner 1164685295f4SBill Fenner if (ni6->ni_code != ICMP6_NI_SUCCESS) { 1165685295f4SBill Fenner /*(*/ 1166685295f4SBill Fenner printf(")"); 1167685295f4SBill Fenner break; 1168685295f4SBill Fenner } 1169685295f4SBill Fenner 11705b0fe478SBruce M Simpson switch (EXTRACT_16BITS(&ni6->ni_qtype)) { 1171685295f4SBill Fenner case NI_QTYPE_NOOP: 1172685295f4SBill Fenner if (needcomma) 1173685295f4SBill Fenner printf(", "); 1174685295f4SBill Fenner printf("noop"); 1175685295f4SBill Fenner if (siz != sizeof(*ni6)) 1176685295f4SBill Fenner if (vflag) 1177685295f4SBill Fenner printf(", invalid length"); 1178685295f4SBill Fenner break; 1179685295f4SBill Fenner case NI_QTYPE_SUPTYPES: 1180685295f4SBill Fenner if (needcomma) 1181685295f4SBill Fenner printf(", "); 1182685295f4SBill Fenner printf("supported qtypes"); 11835b0fe478SBruce M Simpson i = EXTRACT_16BITS(&ni6->ni_flags); 1184685295f4SBill Fenner if (i) 1185685295f4SBill Fenner printf(" [%s]", (i & 0x01) ? "C" : ""); 1186685295f4SBill Fenner break; 1187685295f4SBill Fenner case NI_QTYPE_FQDN: 1188685295f4SBill Fenner if (needcomma) 1189685295f4SBill Fenner printf(", "); 1190685295f4SBill Fenner printf("DNS name"); 1191685295f4SBill Fenner cp = (const u_char *)(ni6 + 1) + 4; 1192685295f4SBill Fenner if (cp[0] == ep - cp - 1) { 1193685295f4SBill Fenner /* icmp-name-lookup-03, pascal string */ 1194685295f4SBill Fenner if (vflag) 1195685295f4SBill Fenner printf(", 03 draft"); 1196685295f4SBill Fenner cp++; 1197685295f4SBill Fenner printf(", \""); 1198685295f4SBill Fenner while (cp < ep) { 1199685295f4SBill Fenner safeputchar(*cp); 1200685295f4SBill Fenner cp++; 1201685295f4SBill Fenner } 1202685295f4SBill Fenner printf("\""); 1203685295f4SBill Fenner } else 1204685295f4SBill Fenner dnsname_print(cp, ep); 12055b0fe478SBruce M Simpson if ((EXTRACT_16BITS(&ni6->ni_flags) & 0x01) != 0) 1206685295f4SBill Fenner printf(" [TTL=%u]", *(u_int32_t *)(ni6 + 1)); 1207685295f4SBill Fenner break; 1208685295f4SBill Fenner case NI_QTYPE_NODEADDR: 1209685295f4SBill Fenner if (needcomma) 1210685295f4SBill Fenner printf(", "); 1211685295f4SBill Fenner printf("node addresses"); 1212685295f4SBill Fenner i = sizeof(*ni6); 1213685295f4SBill Fenner while (i < siz) { 1214685295f4SBill Fenner if (i + sizeof(struct in6_addr) + sizeof(int32_t) > siz) 1215685295f4SBill Fenner break; 1216685295f4SBill Fenner printf(" %s", getname6(bp + i)); 1217685295f4SBill Fenner i += sizeof(struct in6_addr); 12185b0fe478SBruce M Simpson printf("(%d)", (int32_t)EXTRACT_32BITS(bp + i)); 1219685295f4SBill Fenner i += sizeof(int32_t); 1220685295f4SBill Fenner } 1221685295f4SBill Fenner i = ni6->ni_flags; 1222685295f4SBill Fenner if (!i) 1223685295f4SBill Fenner break; 1224685295f4SBill Fenner printf(" [%s%s%s%s%s%s%s]", 1225685295f4SBill Fenner (i & NI_NODEADDR_FLAG_ANYCAST) ? "a" : "", 1226685295f4SBill Fenner (i & NI_NODEADDR_FLAG_GLOBAL) ? "G" : "", 1227685295f4SBill Fenner (i & NI_NODEADDR_FLAG_SITELOCAL) ? "S" : "", 1228685295f4SBill Fenner (i & NI_NODEADDR_FLAG_LINKLOCAL) ? "L" : "", 1229685295f4SBill Fenner (i & NI_NODEADDR_FLAG_COMPAT) ? "C" : "", 1230685295f4SBill Fenner (i & NI_NODEADDR_FLAG_ALL) ? "A" : "", 1231685295f4SBill Fenner (i & NI_NODEADDR_FLAG_TRUNCATE) ? "T" : ""); 1232685295f4SBill Fenner break; 1233685295f4SBill Fenner default: 1234685295f4SBill Fenner if (needcomma) 1235685295f4SBill Fenner printf(", "); 1236685295f4SBill Fenner printf("unknown"); 1237685295f4SBill Fenner break; 1238685295f4SBill Fenner } 1239685295f4SBill Fenner 1240685295f4SBill Fenner /*(*/ 1241685295f4SBill Fenner printf(")"); 1242685295f4SBill Fenner break; 1243685295f4SBill Fenner } 1244685295f4SBill Fenner return; 1245685295f4SBill Fenner 1246685295f4SBill Fenner trunc: 1247685295f4SBill Fenner fputs("[|icmp6]", stdout); 1248685295f4SBill Fenner } 1249685295f4SBill Fenner 12505b0fe478SBruce M Simpson static void 12515b0fe478SBruce M Simpson icmp6_rrenum_print(const u_char *bp, const u_char *ep) 1252685295f4SBill Fenner { 1253685295f4SBill Fenner struct icmp6_router_renum *rr6; 1254685295f4SBill Fenner const char *cp; 1255685295f4SBill Fenner struct rr_pco_match *match; 1256685295f4SBill Fenner struct rr_pco_use *use; 1257685295f4SBill Fenner char hbuf[NI_MAXHOST]; 1258685295f4SBill Fenner int n; 1259685295f4SBill Fenner 12605b0fe478SBruce M Simpson if (ep < bp) 12615b0fe478SBruce M Simpson return; 1262685295f4SBill Fenner rr6 = (struct icmp6_router_renum *)bp; 1263685295f4SBill Fenner cp = (const char *)(rr6 + 1); 1264685295f4SBill Fenner 1265685295f4SBill Fenner TCHECK(rr6->rr_reserved); 1266685295f4SBill Fenner switch (rr6->rr_code) { 1267685295f4SBill Fenner case ICMP6_ROUTER_RENUMBERING_COMMAND: 1268685295f4SBill Fenner printf("router renum: command"); 1269685295f4SBill Fenner break; 1270685295f4SBill Fenner case ICMP6_ROUTER_RENUMBERING_RESULT: 1271685295f4SBill Fenner printf("router renum: result"); 1272685295f4SBill Fenner break; 1273685295f4SBill Fenner case ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET: 1274685295f4SBill Fenner printf("router renum: sequence number reset"); 1275685295f4SBill Fenner break; 1276685295f4SBill Fenner default: 1277685295f4SBill Fenner printf("router renum: code-#%d", rr6->rr_code); 1278685295f4SBill Fenner break; 1279685295f4SBill Fenner } 1280685295f4SBill Fenner 12815b0fe478SBruce M Simpson printf(", seq=%u", EXTRACT_32BITS(&rr6->rr_seqnum)); 1282685295f4SBill Fenner 1283685295f4SBill Fenner if (vflag) { 1284685295f4SBill Fenner #define F(x, y) ((rr6->rr_flags) & (x) ? (y) : "") 1285685295f4SBill Fenner printf("["); /*]*/ 1286685295f4SBill Fenner if (rr6->rr_flags) { 1287685295f4SBill Fenner printf("%s%s%s%s%s,", F(ICMP6_RR_FLAGS_TEST, "T"), 1288685295f4SBill Fenner F(ICMP6_RR_FLAGS_REQRESULT, "R"), 1289a90e161bSBill Fenner F(ICMP6_RR_FLAGS_FORCEAPPLY, "A"), 1290685295f4SBill Fenner F(ICMP6_RR_FLAGS_SPECSITE, "S"), 1291685295f4SBill Fenner F(ICMP6_RR_FLAGS_PREVDONE, "P")); 1292685295f4SBill Fenner } 1293685295f4SBill Fenner printf("seg=%u,", rr6->rr_segnum); 1294a5779b6eSRui Paulo printf("maxdelay=%u", EXTRACT_16BITS(&rr6->rr_maxdelay)); 1295685295f4SBill Fenner if (rr6->rr_reserved) 1296a5779b6eSRui Paulo printf("rsvd=0x%x", EXTRACT_32BITS(&rr6->rr_reserved)); 1297685295f4SBill Fenner /*[*/ 1298685295f4SBill Fenner printf("]"); 1299685295f4SBill Fenner #undef F 1300685295f4SBill Fenner } 1301685295f4SBill Fenner 1302685295f4SBill Fenner if (rr6->rr_code == ICMP6_ROUTER_RENUMBERING_COMMAND) { 1303685295f4SBill Fenner match = (struct rr_pco_match *)cp; 1304685295f4SBill Fenner cp = (const char *)(match + 1); 1305685295f4SBill Fenner 1306685295f4SBill Fenner TCHECK(match->rpm_prefix); 1307685295f4SBill Fenner 1308a90e161bSBill Fenner if (vflag > 1) 1309685295f4SBill Fenner printf("\n\t"); 1310685295f4SBill Fenner else 1311685295f4SBill Fenner printf(" "); 1312685295f4SBill Fenner printf("match("); /*)*/ 1313685295f4SBill Fenner switch (match->rpm_code) { 1314685295f4SBill Fenner case RPM_PCO_ADD: printf("add"); break; 1315685295f4SBill Fenner case RPM_PCO_CHANGE: printf("change"); break; 1316685295f4SBill Fenner case RPM_PCO_SETGLOBAL: printf("setglobal"); break; 1317685295f4SBill Fenner default: printf("#%u", match->rpm_code); break; 1318685295f4SBill Fenner } 1319685295f4SBill Fenner 1320685295f4SBill Fenner if (vflag) { 1321685295f4SBill Fenner printf(",ord=%u", match->rpm_ordinal); 1322685295f4SBill Fenner printf(",min=%u", match->rpm_minlen); 1323685295f4SBill Fenner printf(",max=%u", match->rpm_maxlen); 1324685295f4SBill Fenner } 1325685295f4SBill Fenner if (inet_ntop(AF_INET6, &match->rpm_prefix, hbuf, sizeof(hbuf))) 1326685295f4SBill Fenner printf(",%s/%u", hbuf, match->rpm_matchlen); 1327685295f4SBill Fenner else 1328685295f4SBill Fenner printf(",?/%u", match->rpm_matchlen); 1329685295f4SBill Fenner /*(*/ 1330685295f4SBill Fenner printf(")"); 1331685295f4SBill Fenner 1332685295f4SBill Fenner n = match->rpm_len - 3; 1333685295f4SBill Fenner if (n % 4) 1334685295f4SBill Fenner goto trunc; 1335685295f4SBill Fenner n /= 4; 1336685295f4SBill Fenner while (n-- > 0) { 1337685295f4SBill Fenner use = (struct rr_pco_use *)cp; 1338685295f4SBill Fenner cp = (const char *)(use + 1); 1339685295f4SBill Fenner 1340685295f4SBill Fenner TCHECK(use->rpu_prefix); 1341685295f4SBill Fenner 1342a90e161bSBill Fenner if (vflag > 1) 1343685295f4SBill Fenner printf("\n\t"); 1344685295f4SBill Fenner else 1345685295f4SBill Fenner printf(" "); 1346685295f4SBill Fenner printf("use("); /*)*/ 1347685295f4SBill Fenner if (use->rpu_flags) { 1348685295f4SBill Fenner #define F(x, y) ((use->rpu_flags) & (x) ? (y) : "") 1349685295f4SBill Fenner printf("%s%s,", 1350685295f4SBill Fenner F(ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME, "V"), 1351685295f4SBill Fenner F(ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME, "P")); 1352685295f4SBill Fenner #undef F 1353685295f4SBill Fenner } 1354685295f4SBill Fenner if (vflag) { 1355685295f4SBill Fenner printf("mask=0x%x,", use->rpu_ramask); 1356685295f4SBill Fenner printf("raflags=0x%x,", use->rpu_raflags); 1357685295f4SBill Fenner if (~use->rpu_vltime == 0) 1358685295f4SBill Fenner printf("vltime=infty,"); 1359685295f4SBill Fenner else 1360685295f4SBill Fenner printf("vltime=%u,", 13615b0fe478SBruce M Simpson EXTRACT_32BITS(&use->rpu_vltime)); 1362685295f4SBill Fenner if (~use->rpu_pltime == 0) 1363685295f4SBill Fenner printf("pltime=infty,"); 1364685295f4SBill Fenner else 1365685295f4SBill Fenner printf("pltime=%u,", 13665b0fe478SBruce M Simpson EXTRACT_32BITS(&use->rpu_pltime)); 1367685295f4SBill Fenner } 1368685295f4SBill Fenner if (inet_ntop(AF_INET6, &use->rpu_prefix, hbuf, 1369685295f4SBill Fenner sizeof(hbuf))) 1370685295f4SBill Fenner printf("%s/%u/%u", hbuf, use->rpu_uselen, 1371685295f4SBill Fenner use->rpu_keeplen); 1372685295f4SBill Fenner else 1373685295f4SBill Fenner printf("?/%u/%u", use->rpu_uselen, 1374685295f4SBill Fenner use->rpu_keeplen); 1375685295f4SBill Fenner /*(*/ 1376685295f4SBill Fenner printf(")"); 1377685295f4SBill Fenner } 1378685295f4SBill Fenner } 1379b0453382SBill Fenner 1380b0453382SBill Fenner return; 1381685295f4SBill Fenner 1382685295f4SBill Fenner trunc: 1383685295f4SBill Fenner fputs("[|icmp6]", stdout); 1384b0453382SBill Fenner } 1385685295f4SBill Fenner 1386b0453382SBill Fenner #endif /* INET6 */ 1387