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 23b0453382SBill Fenner static const char rcsid[] = 24a90e161bSBill Fenner "@(#) $Header: /tcpdump/master/tcpdump/print-icmp6.c,v 1.56 2001/06/27 02:48:43 itojun 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 33b0453382SBill Fenner #include <ctype.h> 34b0453382SBill Fenner 35b0453382SBill Fenner #include <sys/param.h> 36b0453382SBill Fenner #include <sys/time.h> 37b0453382SBill Fenner #include <sys/types.h> 38b0453382SBill Fenner #include <sys/socket.h> 39b0453382SBill Fenner 40b0453382SBill Fenner 41b0453382SBill Fenner #include <netinet/in.h> 42b0453382SBill Fenner 43b0453382SBill Fenner #include <arpa/inet.h> 44b0453382SBill Fenner 45b0453382SBill Fenner #include <stdio.h> 46a90e161bSBill Fenner #include <string.h> 47685295f4SBill Fenner #include <netdb.h> 48b0453382SBill Fenner 49685295f4SBill Fenner #include "ip6.h" 50685295f4SBill Fenner #include "icmp6.h" 51b0453382SBill Fenner 52b0453382SBill Fenner #include "interface.h" 53b0453382SBill Fenner #include "addrtoname.h" 54b0453382SBill Fenner 55685295f4SBill Fenner #include "udp.h" 56685295f4SBill Fenner #include "ah.h" 57685295f4SBill Fenner 58a90e161bSBill Fenner static const char *get_rtpref(u_int); 59a90e161bSBill Fenner static const char *get_lifetime(u_int32_t); 60a90e161bSBill Fenner static void print_lladdr(const u_char *, size_t); 61b0453382SBill Fenner void icmp6_opt_print(const u_char *, int); 62b0453382SBill Fenner void mld6_print(const u_char *); 63685295f4SBill Fenner static struct udphdr *get_upperlayer(u_char *, int *); 64685295f4SBill Fenner static void dnsname_print(const u_char *, const u_char *); 65685295f4SBill Fenner void icmp6_nodeinfo_print(int, const u_char *, const u_char *); 66685295f4SBill Fenner void icmp6_rrenum_print(int, const u_char *, const u_char *); 67685295f4SBill Fenner 68685295f4SBill Fenner #ifndef abs 69685295f4SBill Fenner #define abs(a) ((0 < (a)) ? (a) : -(a)) 70685295f4SBill Fenner #endif 71b0453382SBill Fenner 72a90e161bSBill Fenner static const char * 73a90e161bSBill Fenner get_rtpref(u_int v) 74a90e161bSBill Fenner { 75a90e161bSBill Fenner static const char *rtpref_str[] = { 76a90e161bSBill Fenner "medium", /* 00 */ 77a90e161bSBill Fenner "high", /* 01 */ 78a90e161bSBill Fenner "rsv", /* 10 */ 79a90e161bSBill Fenner "low" /* 11 */ 80a90e161bSBill Fenner }; 81a90e161bSBill Fenner 82a90e161bSBill Fenner return rtpref_str[((v & ND_RA_FLAG_RTPREF_MASK) >> 3) & 0xff]; 83a90e161bSBill Fenner } 84a90e161bSBill Fenner 85a90e161bSBill Fenner static const char * 86a90e161bSBill Fenner get_lifetime(u_int32_t v) 87a90e161bSBill Fenner { 88a90e161bSBill Fenner static char buf[20]; 89a90e161bSBill Fenner 90a90e161bSBill Fenner if (v == (u_int32_t)~0UL) 91a90e161bSBill Fenner return "infinity"; 92a90e161bSBill Fenner else { 93a90e161bSBill Fenner snprintf(buf, sizeof(buf), "%u", v); 94a90e161bSBill Fenner return buf; 95a90e161bSBill Fenner } 96a90e161bSBill Fenner } 97a90e161bSBill Fenner 98a90e161bSBill Fenner static void 99a90e161bSBill Fenner print_lladdr(const u_int8_t *p, size_t l) 100a90e161bSBill Fenner { 101a90e161bSBill Fenner const u_int8_t *ep, *q; 102a90e161bSBill Fenner 103a90e161bSBill Fenner q = p; 104a90e161bSBill Fenner ep = p + l; 105a90e161bSBill Fenner while (l > 0 && q < ep) { 106a90e161bSBill Fenner if (q > p) 107a90e161bSBill Fenner printf(":"); 108a90e161bSBill Fenner printf("%02x", *q++); 109a90e161bSBill Fenner l--; 110a90e161bSBill Fenner } 111a90e161bSBill Fenner } 112a90e161bSBill Fenner 113b0453382SBill Fenner void 114a90e161bSBill Fenner icmp6_print(const u_char *bp, const u_char *bp2) 115b0453382SBill Fenner { 116685295f4SBill Fenner const struct icmp6_hdr *dp; 117a90e161bSBill Fenner const struct ip6_hdr *ip; 118a90e161bSBill Fenner const char *str; 119a90e161bSBill Fenner const struct ip6_hdr *oip; 120a90e161bSBill Fenner const struct udphdr *ouh; 121a90e161bSBill Fenner int dport; 122a90e161bSBill Fenner const u_char *ep; 123b0453382SBill Fenner char buf[256]; 124685295f4SBill Fenner int icmp6len, prot; 125b0453382SBill Fenner 126b0453382SBill Fenner dp = (struct icmp6_hdr *)bp; 127b0453382SBill Fenner ip = (struct ip6_hdr *)bp2; 128b0453382SBill Fenner oip = (struct ip6_hdr *)(dp + 1); 129b0453382SBill Fenner str = buf; 130685295f4SBill Fenner /* 'ep' points to the end of available data. */ 131b0453382SBill Fenner ep = snapend; 132b0453382SBill Fenner if (ip->ip6_plen) 133b0453382SBill Fenner icmp6len = (ntohs(ip->ip6_plen) + sizeof(struct ip6_hdr) - 134b0453382SBill Fenner (bp - bp2)); 135b0453382SBill Fenner else /* XXX: jumbo payload case... */ 136b0453382SBill Fenner icmp6len = snapend - bp; 137b0453382SBill Fenner 138b0453382SBill Fenner TCHECK(dp->icmp6_code); 139b0453382SBill Fenner switch (dp->icmp6_type) { 140b0453382SBill Fenner case ICMP6_DST_UNREACH: 141b0453382SBill Fenner TCHECK(oip->ip6_dst); 142b0453382SBill Fenner switch (dp->icmp6_code) { 143b0453382SBill Fenner case ICMP6_DST_UNREACH_NOROUTE: 144b0453382SBill Fenner printf("icmp6: %s unreachable route", 145b0453382SBill Fenner ip6addr_string(&oip->ip6_dst)); 146b0453382SBill Fenner break; 147b0453382SBill Fenner case ICMP6_DST_UNREACH_ADMIN: 148b0453382SBill Fenner printf("icmp6: %s unreachable prohibited", 149b0453382SBill Fenner ip6addr_string(&oip->ip6_dst)); 150b0453382SBill Fenner break; 151b0453382SBill Fenner case ICMP6_DST_UNREACH_BEYONDSCOPE: 152b0453382SBill Fenner printf("icmp6: %s beyond scope of source address %s", 153b0453382SBill Fenner ip6addr_string(&oip->ip6_dst), 154b0453382SBill Fenner ip6addr_string(&oip->ip6_src)); 155b0453382SBill Fenner break; 156b0453382SBill Fenner case ICMP6_DST_UNREACH_ADDR: 157b0453382SBill Fenner printf("icmp6: %s unreachable address", 158b0453382SBill Fenner ip6addr_string(&oip->ip6_dst)); 159b0453382SBill Fenner break; 160b0453382SBill Fenner case ICMP6_DST_UNREACH_NOPORT: 161685295f4SBill Fenner if ((ouh = get_upperlayer((u_char *)oip, &prot)) 162685295f4SBill Fenner == NULL) 163685295f4SBill Fenner goto trunc; 164685295f4SBill Fenner 165b0453382SBill Fenner dport = ntohs(ouh->uh_dport); 166685295f4SBill Fenner switch (prot) { 167b0453382SBill Fenner case IPPROTO_TCP: 168b0453382SBill Fenner printf("icmp6: %s tcp port %s unreachable", 169b0453382SBill Fenner ip6addr_string(&oip->ip6_dst), 170b0453382SBill Fenner tcpport_string(dport)); 171b0453382SBill Fenner break; 172b0453382SBill Fenner case IPPROTO_UDP: 173b0453382SBill Fenner printf("icmp6: %s udp port %s unreachable", 174b0453382SBill Fenner ip6addr_string(&oip->ip6_dst), 175b0453382SBill Fenner udpport_string(dport)); 176b0453382SBill Fenner break; 177b0453382SBill Fenner default: 178b0453382SBill Fenner printf("icmp6: %s protocol %d port %d unreachable", 179b0453382SBill Fenner ip6addr_string(&oip->ip6_dst), 180b0453382SBill Fenner oip->ip6_nxt, dport); 181b0453382SBill Fenner break; 182b0453382SBill Fenner } 183b0453382SBill Fenner break; 184b0453382SBill Fenner default: 185b0453382SBill Fenner printf("icmp6: %s unreachable code-#%d", 186b0453382SBill Fenner ip6addr_string(&oip->ip6_dst), 187b0453382SBill Fenner dp->icmp6_code); 188b0453382SBill Fenner break; 189b0453382SBill Fenner } 190b0453382SBill Fenner break; 191b0453382SBill Fenner case ICMP6_PACKET_TOO_BIG: 192b0453382SBill Fenner TCHECK(dp->icmp6_mtu); 193a90e161bSBill Fenner printf("icmp6: too big %u", (u_int32_t)ntohl(dp->icmp6_mtu)); 194b0453382SBill Fenner break; 195b0453382SBill Fenner case ICMP6_TIME_EXCEEDED: 196b0453382SBill Fenner TCHECK(oip->ip6_dst); 197b0453382SBill Fenner switch (dp->icmp6_code) { 198b0453382SBill Fenner case ICMP6_TIME_EXCEED_TRANSIT: 199b0453382SBill Fenner printf("icmp6: time exceeded in-transit for %s", 200b0453382SBill Fenner ip6addr_string(&oip->ip6_dst)); 201b0453382SBill Fenner break; 202b0453382SBill Fenner case ICMP6_TIME_EXCEED_REASSEMBLY: 203b0453382SBill Fenner printf("icmp6: ip6 reassembly time exceeded"); 204b0453382SBill Fenner break; 205b0453382SBill Fenner default: 206b0453382SBill Fenner printf("icmp6: time exceeded code-#%d", 207b0453382SBill Fenner dp->icmp6_code); 208b0453382SBill Fenner break; 209b0453382SBill Fenner } 210b0453382SBill Fenner break; 211b0453382SBill Fenner case ICMP6_PARAM_PROB: 212b0453382SBill Fenner TCHECK(oip->ip6_dst); 213b0453382SBill Fenner switch (dp->icmp6_code) { 214b0453382SBill Fenner case ICMP6_PARAMPROB_HEADER: 215a90e161bSBill Fenner printf("icmp6: parameter problem errorneous - octet %u", 216b0453382SBill Fenner (u_int32_t)ntohl(dp->icmp6_pptr)); 217b0453382SBill Fenner break; 218b0453382SBill Fenner case ICMP6_PARAMPROB_NEXTHEADER: 219a90e161bSBill Fenner printf("icmp6: parameter problem next header - octet %u", 220b0453382SBill Fenner (u_int32_t)ntohl(dp->icmp6_pptr)); 221b0453382SBill Fenner break; 222b0453382SBill Fenner case ICMP6_PARAMPROB_OPTION: 223a90e161bSBill Fenner printf("icmp6: parameter problem option - octet %u", 224b0453382SBill Fenner (u_int32_t)ntohl(dp->icmp6_pptr)); 225b0453382SBill Fenner break; 226b0453382SBill Fenner default: 227b0453382SBill Fenner printf("icmp6: parameter problem code-#%d", 228b0453382SBill Fenner dp->icmp6_code); 229b0453382SBill Fenner break; 230b0453382SBill Fenner } 231b0453382SBill Fenner break; 232b0453382SBill Fenner case ICMP6_ECHO_REQUEST: 233b0453382SBill Fenner printf("icmp6: echo request"); 234b0453382SBill Fenner break; 235b0453382SBill Fenner case ICMP6_ECHO_REPLY: 236b0453382SBill Fenner printf("icmp6: echo reply"); 237b0453382SBill Fenner break; 238b0453382SBill Fenner case ICMP6_MEMBERSHIP_QUERY: 239b0453382SBill Fenner printf("icmp6: multicast listener query "); 240b0453382SBill Fenner mld6_print((const u_char *)dp); 241b0453382SBill Fenner break; 242b0453382SBill Fenner case ICMP6_MEMBERSHIP_REPORT: 243b0453382SBill Fenner printf("icmp6: multicast listener report "); 244b0453382SBill Fenner mld6_print((const u_char *)dp); 245b0453382SBill Fenner break; 246b0453382SBill Fenner case ICMP6_MEMBERSHIP_REDUCTION: 247b0453382SBill Fenner printf("icmp6: multicast listener done "); 248b0453382SBill Fenner mld6_print((const u_char *)dp); 249b0453382SBill Fenner break; 250b0453382SBill Fenner case ND_ROUTER_SOLICIT: 251b0453382SBill Fenner printf("icmp6: router solicitation "); 252b0453382SBill Fenner if (vflag) { 253b0453382SBill Fenner #define RTSOLLEN 8 254b0453382SBill Fenner icmp6_opt_print((const u_char *)dp + RTSOLLEN, 255b0453382SBill Fenner icmp6len - RTSOLLEN); 256b0453382SBill Fenner } 257b0453382SBill Fenner break; 258b0453382SBill Fenner case ND_ROUTER_ADVERT: 259b0453382SBill Fenner printf("icmp6: router advertisement"); 260b0453382SBill Fenner if (vflag) { 261b0453382SBill Fenner struct nd_router_advert *p; 262b0453382SBill Fenner 263b0453382SBill Fenner p = (struct nd_router_advert *)dp; 264b0453382SBill Fenner TCHECK(p->nd_ra_retransmit); 265b0453382SBill Fenner printf("(chlim=%d, ", (int)p->nd_ra_curhoplimit); 266b0453382SBill Fenner if (p->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED) 267b0453382SBill Fenner printf("M"); 268b0453382SBill Fenner if (p->nd_ra_flags_reserved & ND_RA_FLAG_OTHER) 269b0453382SBill Fenner printf("O"); 270a90e161bSBill Fenner if (p->nd_ra_flags_reserved & ND_RA_FLAG_HOME_AGENT) 271685295f4SBill Fenner printf("H"); 272a90e161bSBill Fenner 273a90e161bSBill Fenner if ((p->nd_ra_flags_reserved & ~ND_RA_FLAG_RTPREF_MASK) 274a90e161bSBill Fenner != 0) 275b0453382SBill Fenner printf(" "); 276a90e161bSBill Fenner 277a90e161bSBill Fenner printf("pref=%s, ", 278a90e161bSBill Fenner get_rtpref(p->nd_ra_flags_reserved)); 279a90e161bSBill Fenner 280b0453382SBill Fenner printf("router_ltime=%d, ", ntohs(p->nd_ra_router_lifetime)); 281b0453382SBill Fenner printf("reachable_time=%u, ", 282b0453382SBill Fenner (u_int32_t)ntohl(p->nd_ra_reachable)); 283b0453382SBill Fenner printf("retrans_time=%u)", 284b0453382SBill Fenner (u_int32_t)ntohl(p->nd_ra_retransmit)); 285b0453382SBill Fenner #define RTADVLEN 16 286b0453382SBill Fenner icmp6_opt_print((const u_char *)dp + RTADVLEN, 287b0453382SBill Fenner icmp6len - RTADVLEN); 288b0453382SBill Fenner } 289b0453382SBill Fenner break; 290b0453382SBill Fenner case ND_NEIGHBOR_SOLICIT: 291b0453382SBill Fenner { 292b0453382SBill Fenner struct nd_neighbor_solicit *p; 293b0453382SBill Fenner p = (struct nd_neighbor_solicit *)dp; 294b0453382SBill Fenner TCHECK(p->nd_ns_target); 295b0453382SBill Fenner printf("icmp6: neighbor sol: who has %s", 296b0453382SBill Fenner ip6addr_string(&p->nd_ns_target)); 297b0453382SBill Fenner if (vflag) { 298b0453382SBill Fenner #define NDSOLLEN 24 299b0453382SBill Fenner icmp6_opt_print((const u_char *)dp + NDSOLLEN, 300b0453382SBill Fenner icmp6len - NDSOLLEN); 301b0453382SBill Fenner } 302b0453382SBill Fenner } 303b0453382SBill Fenner break; 304b0453382SBill Fenner case ND_NEIGHBOR_ADVERT: 305b0453382SBill Fenner { 306b0453382SBill Fenner struct nd_neighbor_advert *p; 307b0453382SBill Fenner 308b0453382SBill Fenner p = (struct nd_neighbor_advert *)dp; 309b0453382SBill Fenner TCHECK(p->nd_na_target); 310b0453382SBill Fenner printf("icmp6: neighbor adv: tgt is %s", 311b0453382SBill Fenner ip6addr_string(&p->nd_na_target)); 312b0453382SBill Fenner if (vflag) { 313b0453382SBill Fenner #define ND_NA_FLAG_ALL \ 314b0453382SBill Fenner (ND_NA_FLAG_ROUTER|ND_NA_FLAG_SOLICITED|ND_NA_FLAG_OVERRIDE) 315b0453382SBill Fenner /* we don't need ntohl() here. see advanced-api-04. */ 316b0453382SBill Fenner if (p->nd_na_flags_reserved & ND_NA_FLAG_ALL) { 317b0453382SBill Fenner #undef ND_NA_FLAG_ALL 318b0453382SBill Fenner u_int32_t flags; 319b0453382SBill Fenner 320b0453382SBill Fenner flags = p->nd_na_flags_reserved; 321b0453382SBill Fenner printf("("); 322b0453382SBill Fenner if (flags & ND_NA_FLAG_ROUTER) 323b0453382SBill Fenner printf("R"); 324b0453382SBill Fenner if (flags & ND_NA_FLAG_SOLICITED) 325b0453382SBill Fenner printf("S"); 326b0453382SBill Fenner if (flags & ND_NA_FLAG_OVERRIDE) 327b0453382SBill Fenner printf("O"); 328b0453382SBill Fenner printf(")"); 329b0453382SBill Fenner } 330b0453382SBill Fenner #define NDADVLEN 24 331b0453382SBill Fenner icmp6_opt_print((const u_char *)dp + NDADVLEN, 332b0453382SBill Fenner icmp6len - NDADVLEN); 333685295f4SBill Fenner #undef NDADVLEN 334b0453382SBill Fenner } 335b0453382SBill Fenner } 336b0453382SBill Fenner break; 337b0453382SBill Fenner case ND_REDIRECT: 338b0453382SBill Fenner #define RDR(i) ((struct nd_redirect *)(i)) 339b0453382SBill Fenner TCHECK(RDR(dp)->nd_rd_dst); 340685295f4SBill Fenner printf("icmp6: redirect %s", 341685295f4SBill Fenner getname6((const u_char *)&RDR(dp)->nd_rd_dst)); 342685295f4SBill Fenner printf(" to %s", 343685295f4SBill Fenner getname6((const u_char*)&RDR(dp)->nd_rd_target)); 344b0453382SBill Fenner #define REDIRECTLEN 40 345b0453382SBill Fenner if (vflag) { 346b0453382SBill Fenner icmp6_opt_print((const u_char *)dp + REDIRECTLEN, 347b0453382SBill Fenner icmp6len - REDIRECTLEN); 348b0453382SBill Fenner } 349b0453382SBill Fenner break; 350685295f4SBill Fenner #undef REDIRECTLEN 351685295f4SBill Fenner #undef RDR 352b0453382SBill Fenner case ICMP6_ROUTER_RENUMBERING: 353685295f4SBill Fenner icmp6_rrenum_print(icmp6len, bp, ep); 354b0453382SBill Fenner break; 355685295f4SBill Fenner case ICMP6_NI_QUERY: 356685295f4SBill Fenner case ICMP6_NI_REPLY: 357685295f4SBill Fenner icmp6_nodeinfo_print(icmp6len, bp, ep); 358b0453382SBill Fenner break; 359b0453382SBill Fenner default: 360b0453382SBill Fenner printf("icmp6: type-#%d", dp->icmp6_type); 361b0453382SBill Fenner break; 362b0453382SBill Fenner } 363b0453382SBill Fenner return; 364b0453382SBill Fenner trunc: 365b0453382SBill Fenner fputs("[|icmp6]", stdout); 366b0453382SBill Fenner } 367b0453382SBill Fenner 368685295f4SBill Fenner static struct udphdr * 369a90e161bSBill Fenner get_upperlayer(u_char *bp, int *prot) 370685295f4SBill Fenner { 371a90e161bSBill Fenner const u_char *ep; 372685295f4SBill Fenner struct ip6_hdr *ip6 = (struct ip6_hdr *)bp; 373685295f4SBill Fenner struct udphdr *uh; 374685295f4SBill Fenner struct ip6_hbh *hbh; 375685295f4SBill Fenner struct ip6_frag *fragh; 376685295f4SBill Fenner struct ah *ah; 377685295f4SBill Fenner int nh, hlen; 378685295f4SBill Fenner 379685295f4SBill Fenner /* 'ep' points to the end of available data. */ 380685295f4SBill Fenner ep = snapend; 381685295f4SBill Fenner 382685295f4SBill Fenner if (TTEST(ip6->ip6_nxt) == 0) 383685295f4SBill Fenner return NULL; 384685295f4SBill Fenner 385685295f4SBill Fenner nh = ip6->ip6_nxt; 386685295f4SBill Fenner hlen = sizeof(struct ip6_hdr); 387685295f4SBill Fenner 388685295f4SBill Fenner while (bp < snapend) { 389685295f4SBill Fenner bp += hlen; 390685295f4SBill Fenner 391685295f4SBill Fenner switch(nh) { 392685295f4SBill Fenner case IPPROTO_UDP: 393685295f4SBill Fenner case IPPROTO_TCP: 394685295f4SBill Fenner uh = (struct udphdr *)bp; 395685295f4SBill Fenner if (TTEST(uh->uh_dport)) { 396685295f4SBill Fenner *prot = nh; 397685295f4SBill Fenner return(uh); 398685295f4SBill Fenner } 399685295f4SBill Fenner else 400685295f4SBill Fenner return(NULL); 401685295f4SBill Fenner /* NOTREACHED */ 402685295f4SBill Fenner 403685295f4SBill Fenner case IPPROTO_HOPOPTS: 404685295f4SBill Fenner case IPPROTO_DSTOPTS: 405685295f4SBill Fenner case IPPROTO_ROUTING: 406685295f4SBill Fenner hbh = (struct ip6_hbh *)bp; 407685295f4SBill Fenner if (TTEST(hbh->ip6h_len) == 0) 408685295f4SBill Fenner return(NULL); 409685295f4SBill Fenner nh = hbh->ip6h_nxt; 410685295f4SBill Fenner hlen = (hbh->ip6h_len + 1) << 3; 411685295f4SBill Fenner break; 412685295f4SBill Fenner 413685295f4SBill Fenner case IPPROTO_FRAGMENT: /* this should be odd, but try anyway */ 414685295f4SBill Fenner fragh = (struct ip6_frag *)bp; 415685295f4SBill Fenner if (TTEST(fragh->ip6f_offlg) == 0) 416685295f4SBill Fenner return(NULL); 417685295f4SBill Fenner /* fragments with non-zero offset are meaningless */ 418685295f4SBill Fenner if ((fragh->ip6f_offlg & IP6F_OFF_MASK) != 0) 419685295f4SBill Fenner return(NULL); 420685295f4SBill Fenner nh = fragh->ip6f_nxt; 421685295f4SBill Fenner hlen = sizeof(struct ip6_frag); 422685295f4SBill Fenner break; 423685295f4SBill Fenner 424685295f4SBill Fenner case IPPROTO_AH: 425685295f4SBill Fenner ah = (struct ah *)bp; 426685295f4SBill Fenner if (TTEST(ah->ah_len) == 0) 427685295f4SBill Fenner return(NULL); 428685295f4SBill Fenner nh = ah->ah_nxt; 429685295f4SBill Fenner hlen = (ah->ah_len + 2) << 2; 430685295f4SBill Fenner break; 431685295f4SBill Fenner 432685295f4SBill Fenner default: /* unknown or undecodable header */ 433685295f4SBill Fenner *prot = nh; /* meaningless, but set here anyway */ 434685295f4SBill Fenner return(NULL); 435685295f4SBill Fenner } 436685295f4SBill Fenner } 437685295f4SBill Fenner 438685295f4SBill Fenner return(NULL); /* should be notreached, though */ 439685295f4SBill Fenner } 440685295f4SBill Fenner 441b0453382SBill Fenner void 442a90e161bSBill Fenner icmp6_opt_print(const u_char *bp, int resid) 443b0453382SBill Fenner { 444a90e161bSBill Fenner const struct nd_opt_hdr *op; 445a90e161bSBill Fenner const struct nd_opt_hdr *opl; /* why there's no struct? */ 446a90e161bSBill Fenner const struct nd_opt_prefix_info *opp; 447a90e161bSBill Fenner const struct icmp6_opts_redirect *opr; 448a90e161bSBill Fenner const struct nd_opt_mtu *opm; 449a90e161bSBill Fenner const struct nd_opt_advinterval *opa; 450a90e161bSBill Fenner const struct nd_opt_route_info *opri; 451a90e161bSBill Fenner const u_char *cp, *ep; 452a90e161bSBill Fenner struct in6_addr in6, *in6p; 453a90e161bSBill Fenner size_t l; 454b0453382SBill Fenner 455b0453382SBill Fenner #define ECHECK(var) if ((u_char *)&(var) > ep - sizeof(var)) return 456b0453382SBill Fenner 457a90e161bSBill Fenner cp = bp; 458685295f4SBill Fenner /* 'ep' points to the end of available data. */ 459b0453382SBill Fenner ep = snapend; 460b0453382SBill Fenner 461a90e161bSBill Fenner while (cp < ep) { 462a90e161bSBill Fenner op = (struct nd_opt_hdr *)cp; 463a90e161bSBill Fenner 464b0453382SBill Fenner ECHECK(op->nd_opt_len); 465b0453382SBill Fenner if (resid <= 0) 466b0453382SBill Fenner return; 467a90e161bSBill Fenner if (op->nd_opt_len == 0) 468a90e161bSBill Fenner goto trunc; 469a90e161bSBill Fenner if (cp + (op->nd_opt_len << 3) > ep) 470a90e161bSBill Fenner goto trunc; 471a90e161bSBill Fenner 472b0453382SBill Fenner switch (op->nd_opt_type) { 473b0453382SBill Fenner case ND_OPT_SOURCE_LINKADDR: 474b0453382SBill Fenner opl = (struct nd_opt_hdr *)op; 475a90e161bSBill Fenner printf("(src lladdr: "); 476a90e161bSBill Fenner l = (op->nd_opt_len << 3) - 2; 477a90e161bSBill Fenner print_lladdr(cp + 2, l); 478685295f4SBill Fenner /*(*/ 479b0453382SBill Fenner printf(")"); 480b0453382SBill Fenner break; 481b0453382SBill Fenner case ND_OPT_TARGET_LINKADDR: 482b0453382SBill Fenner opl = (struct nd_opt_hdr *)op; 483a90e161bSBill Fenner printf("(tgt lladdr: "); 484a90e161bSBill Fenner l = (op->nd_opt_len << 3) - 2; 485a90e161bSBill Fenner print_lladdr(cp + 2, l); 486685295f4SBill Fenner /*(*/ 487b0453382SBill Fenner printf(")"); 488b0453382SBill Fenner break; 489b0453382SBill Fenner case ND_OPT_PREFIX_INFORMATION: 490b0453382SBill Fenner opp = (struct nd_opt_prefix_info *)op; 491b0453382SBill Fenner TCHECK(opp->nd_opt_pi_prefix); 492685295f4SBill Fenner printf("(prefix info: "); /*)*/ 493a90e161bSBill Fenner if (op->nd_opt_len != 4) { 494a90e161bSBill Fenner printf("badlen"); 495a90e161bSBill Fenner /*(*/ 496a90e161bSBill Fenner printf(")"); 497a90e161bSBill Fenner break; 498a90e161bSBill Fenner } 499b0453382SBill Fenner if (opp->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_ONLINK) 500b0453382SBill Fenner printf("L"); 501b0453382SBill Fenner if (opp->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_AUTO) 502b0453382SBill Fenner printf("A"); 503685295f4SBill Fenner if (opp->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_ROUTER) 504685295f4SBill Fenner printf("R"); 505b0453382SBill Fenner if (opp->nd_opt_pi_flags_reserved) 506b0453382SBill Fenner printf(" "); 507a90e161bSBill Fenner printf("valid_ltime=%s,", 508a90e161bSBill Fenner get_lifetime((u_int32_t)ntohl(opp->nd_opt_pi_valid_time))); 509a90e161bSBill Fenner printf("preferred_ltime=%s,", 510a90e161bSBill Fenner get_lifetime((u_int32_t)ntohl(opp->nd_opt_pi_preferred_time))); 511a90e161bSBill Fenner printf("prefix=%s/%d", 512a90e161bSBill Fenner ip6addr_string(&opp->nd_opt_pi_prefix), 513b0453382SBill Fenner opp->nd_opt_pi_prefix_len); 514b0453382SBill Fenner if (opp->nd_opt_pi_len != 4) 515b0453382SBill Fenner printf("!"); 516685295f4SBill Fenner /*(*/ 517b0453382SBill Fenner printf(")"); 518b0453382SBill Fenner break; 519b0453382SBill Fenner case ND_OPT_REDIRECTED_HEADER: 520b0453382SBill Fenner opr = (struct icmp6_opts_redirect *)op; 521b0453382SBill Fenner printf("(redirect)"); 522b0453382SBill Fenner /* xxx */ 523b0453382SBill Fenner break; 524b0453382SBill Fenner case ND_OPT_MTU: 525b0453382SBill Fenner opm = (struct nd_opt_mtu *)op; 526b0453382SBill Fenner TCHECK(opm->nd_opt_mtu_mtu); 527685295f4SBill Fenner printf("(mtu:"); /*)*/ 528a90e161bSBill Fenner if (op->nd_opt_len != 1) { 529a90e161bSBill Fenner printf("badlen"); 530a90e161bSBill Fenner /*(*/ 531a90e161bSBill Fenner printf(")"); 532a90e161bSBill Fenner break; 533a90e161bSBill Fenner } 534b0453382SBill Fenner printf(" mtu=%u", (u_int32_t)ntohl(opm->nd_opt_mtu_mtu)); 535b0453382SBill Fenner if (opm->nd_opt_mtu_len != 1) 536b0453382SBill Fenner printf("!"); 537b0453382SBill Fenner printf(")"); 538b0453382SBill Fenner break; 539a90e161bSBill Fenner case ND_OPT_ADVINTERVAL: 540a90e161bSBill Fenner opa = (struct nd_opt_advinterval *)op; 541a90e161bSBill Fenner TCHECK(opa->nd_opt_adv_interval); 542685295f4SBill Fenner printf("(advint:"); /*)*/ 543685295f4SBill Fenner printf(" advint=%u", 544a90e161bSBill Fenner (u_int32_t)ntohl(opa->nd_opt_adv_interval)); 545685295f4SBill Fenner /*(*/ 546685295f4SBill Fenner printf(")"); 547a90e161bSBill Fenner break; 548a90e161bSBill Fenner case ND_OPT_ROUTE_INFO: 549a90e161bSBill Fenner opri = (struct nd_opt_route_info *)op; 550a90e161bSBill Fenner TCHECK(opri->nd_opt_rti_lifetime); 551a90e161bSBill Fenner memset(&in6, 0, sizeof(in6)); 552a90e161bSBill Fenner in6p = (struct in6_addr *)(opri + 1); 553a90e161bSBill Fenner switch (op->nd_opt_len) { 554a90e161bSBill Fenner case 1: 555a90e161bSBill Fenner break; 556a90e161bSBill Fenner case 2: 557a90e161bSBill Fenner TCHECK2(*in6p, 8); 558a90e161bSBill Fenner memcpy(&in6, opri + 1, 8); 559a90e161bSBill Fenner break; 560a90e161bSBill Fenner case 3: 561a90e161bSBill Fenner TCHECK(*in6p); 562a90e161bSBill Fenner memcpy(&in6, opri + 1, sizeof(in6)); 563685295f4SBill Fenner break; 564b0453382SBill Fenner default: 565a90e161bSBill Fenner goto trunc; 566a90e161bSBill Fenner } 567a90e161bSBill Fenner printf("(rtinfo:"); /*)*/ 568a90e161bSBill Fenner printf(" %s/%u", ip6addr_string(&in6), 569a90e161bSBill Fenner opri->nd_opt_rti_prefixlen); 570a90e161bSBill Fenner printf(", pref=%s", get_rtpref(opri->nd_opt_rti_flags)); 571a90e161bSBill Fenner printf(", lifetime=%s", 572a90e161bSBill Fenner get_lifetime((u_int32_t)ntohl(opri->nd_opt_rti_lifetime))); 573a90e161bSBill Fenner /*(*/ 574a90e161bSBill Fenner printf(")"); 575a90e161bSBill Fenner break; 576a90e161bSBill Fenner default: 577b0453382SBill Fenner printf("(unknwon opt_type=%d, opt_len=%d)", 578a90e161bSBill Fenner op->nd_opt_type, op->nd_opt_len); 579b0453382SBill Fenner break; 580b0453382SBill Fenner } 581a90e161bSBill Fenner 582a90e161bSBill Fenner cp += op->nd_opt_len << 3; 583a90e161bSBill Fenner resid -= op->nd_opt_len << 3; 584a90e161bSBill Fenner } 585b0453382SBill Fenner return; 586a90e161bSBill Fenner 587b0453382SBill Fenner trunc: 588b0453382SBill Fenner fputs("[ndp opt]", stdout); 589b0453382SBill Fenner return; 590b0453382SBill Fenner #undef ECHECK 591b0453382SBill Fenner } 592b0453382SBill Fenner 593b0453382SBill Fenner void 594a90e161bSBill Fenner mld6_print(const u_char *bp) 595b0453382SBill Fenner { 596a90e161bSBill Fenner struct mld6_hdr *mp = (struct mld6_hdr *)bp; 597a90e161bSBill Fenner const u_char *ep; 598b0453382SBill Fenner 599685295f4SBill Fenner /* 'ep' points to the end of available data. */ 600b0453382SBill Fenner ep = snapend; 601b0453382SBill Fenner 602b0453382SBill Fenner if ((u_char *)mp + sizeof(*mp) > ep) 603b0453382SBill Fenner return; 604b0453382SBill Fenner 605b0453382SBill Fenner printf("max resp delay: %d ", ntohs(mp->mld6_maxdelay)); 606b0453382SBill Fenner printf("addr: %s", ip6addr_string(&mp->mld6_addr)); 607685295f4SBill Fenner } 608685295f4SBill Fenner 609685295f4SBill Fenner static void 610685295f4SBill Fenner dnsname_print(const u_char *cp, const u_char *ep) 611685295f4SBill Fenner { 612685295f4SBill Fenner int i; 613685295f4SBill Fenner 614685295f4SBill Fenner /* DNS name decoding - no decompression */ 615685295f4SBill Fenner printf(", \""); 616685295f4SBill Fenner while (cp < ep) { 617685295f4SBill Fenner i = *cp++; 618685295f4SBill Fenner if (i) { 619685295f4SBill Fenner if (i > ep - cp) { 620685295f4SBill Fenner printf("???"); 621685295f4SBill Fenner break; 622685295f4SBill Fenner } 623685295f4SBill Fenner while (i-- && cp < ep) { 624685295f4SBill Fenner safeputchar(*cp); 625685295f4SBill Fenner cp++; 626685295f4SBill Fenner } 627685295f4SBill Fenner if (cp + 1 < ep && *cp) 628685295f4SBill Fenner printf("."); 629685295f4SBill Fenner } else { 630685295f4SBill Fenner if (cp == ep) { 631685295f4SBill Fenner /* FQDN */ 632685295f4SBill Fenner printf("."); 633685295f4SBill Fenner } else if (cp + 1 == ep && *cp == '\0') { 634685295f4SBill Fenner /* truncated */ 635685295f4SBill Fenner } else { 636685295f4SBill Fenner /* invalid */ 637685295f4SBill Fenner printf("???"); 638685295f4SBill Fenner } 639685295f4SBill Fenner break; 640685295f4SBill Fenner } 641685295f4SBill Fenner } 642685295f4SBill Fenner printf("\""); 643685295f4SBill Fenner } 644685295f4SBill Fenner 645685295f4SBill Fenner void 646685295f4SBill Fenner icmp6_nodeinfo_print(int icmp6len, const u_char *bp, const u_char *ep) 647685295f4SBill Fenner { 648685295f4SBill Fenner struct icmp6_nodeinfo *ni6; 649685295f4SBill Fenner struct icmp6_hdr *dp; 650685295f4SBill Fenner const u_char *cp; 651685295f4SBill Fenner int siz, i; 652685295f4SBill Fenner int needcomma; 653685295f4SBill Fenner 654685295f4SBill Fenner dp = (struct icmp6_hdr *)bp; 655685295f4SBill Fenner ni6 = (struct icmp6_nodeinfo *)bp; 656685295f4SBill Fenner siz = ep - bp; 657685295f4SBill Fenner 658685295f4SBill Fenner switch (ni6->ni_type) { 659685295f4SBill Fenner case ICMP6_NI_QUERY: 660685295f4SBill Fenner if (siz == sizeof(*dp) + 4) { 661685295f4SBill Fenner /* KAME who-are-you */ 662685295f4SBill Fenner printf("icmp6: who-are-you request"); 663685295f4SBill Fenner break; 664685295f4SBill Fenner } 665685295f4SBill Fenner printf("icmp6: node information query"); 666685295f4SBill Fenner 667685295f4SBill Fenner TCHECK2(*dp, sizeof(*ni6)); 668685295f4SBill Fenner ni6 = (struct icmp6_nodeinfo *)dp; 669685295f4SBill Fenner printf(" ("); /*)*/ 670685295f4SBill Fenner switch (ntohs(ni6->ni_qtype)) { 671685295f4SBill Fenner case NI_QTYPE_NOOP: 672685295f4SBill Fenner printf("noop"); 673685295f4SBill Fenner break; 674685295f4SBill Fenner case NI_QTYPE_SUPTYPES: 675685295f4SBill Fenner printf("supported qtypes"); 676685295f4SBill Fenner i = ntohs(ni6->ni_flags); 677685295f4SBill Fenner if (i) 678685295f4SBill Fenner printf(" [%s]", (i & 0x01) ? "C" : ""); 679685295f4SBill Fenner break; 680685295f4SBill Fenner break; 681685295f4SBill Fenner case NI_QTYPE_FQDN: 682685295f4SBill Fenner printf("DNS name"); 683685295f4SBill Fenner break; 684685295f4SBill Fenner case NI_QTYPE_NODEADDR: 685685295f4SBill Fenner printf("node addresses"); 686685295f4SBill Fenner i = ni6->ni_flags; 687685295f4SBill Fenner if (!i) 688685295f4SBill Fenner break; 689685295f4SBill Fenner /* NI_NODEADDR_FLAG_TRUNCATE undefined for query */ 690685295f4SBill Fenner printf(" [%s%s%s%s%s%s]", 691685295f4SBill Fenner (i & NI_NODEADDR_FLAG_ANYCAST) ? "a" : "", 692685295f4SBill Fenner (i & NI_NODEADDR_FLAG_GLOBAL) ? "G" : "", 693685295f4SBill Fenner (i & NI_NODEADDR_FLAG_SITELOCAL) ? "S" : "", 694685295f4SBill Fenner (i & NI_NODEADDR_FLAG_LINKLOCAL) ? "L" : "", 695685295f4SBill Fenner (i & NI_NODEADDR_FLAG_COMPAT) ? "C" : "", 696685295f4SBill Fenner (i & NI_NODEADDR_FLAG_ALL) ? "A" : ""); 697685295f4SBill Fenner break; 698685295f4SBill Fenner default: 699685295f4SBill Fenner printf("unknown"); 700685295f4SBill Fenner break; 701685295f4SBill Fenner } 702685295f4SBill Fenner 703685295f4SBill Fenner if (ni6->ni_qtype == NI_QTYPE_NOOP || 704685295f4SBill Fenner ni6->ni_qtype == NI_QTYPE_SUPTYPES) { 705685295f4SBill Fenner if (siz != sizeof(*ni6)) 706685295f4SBill Fenner if (vflag) 707685295f4SBill Fenner printf(", invalid len"); 708685295f4SBill Fenner /*(*/ 709685295f4SBill Fenner printf(")"); 710685295f4SBill Fenner break; 711685295f4SBill Fenner } 712685295f4SBill Fenner 713685295f4SBill Fenner 714685295f4SBill Fenner /* XXX backward compat, icmp-name-lookup-03 */ 715685295f4SBill Fenner if (siz == sizeof(*ni6)) { 716685295f4SBill Fenner printf(", 03 draft"); 717685295f4SBill Fenner /*(*/ 718685295f4SBill Fenner printf(")"); 719685295f4SBill Fenner break; 720685295f4SBill Fenner } 721685295f4SBill Fenner 722685295f4SBill Fenner switch (ni6->ni_code) { 723685295f4SBill Fenner case ICMP6_NI_SUBJ_IPV6: 724685295f4SBill Fenner if (!TTEST2(*dp, 725685295f4SBill Fenner sizeof(*ni6) + sizeof(struct in6_addr))) 726685295f4SBill Fenner break; 727685295f4SBill Fenner if (siz != sizeof(*ni6) + sizeof(struct in6_addr)) { 728685295f4SBill Fenner if (vflag) 729685295f4SBill Fenner printf(", invalid subject len"); 730685295f4SBill Fenner break; 731685295f4SBill Fenner } 732685295f4SBill Fenner printf(", subject=%s", 733685295f4SBill Fenner getname6((const u_char *)(ni6 + 1))); 734685295f4SBill Fenner break; 735685295f4SBill Fenner case ICMP6_NI_SUBJ_FQDN: 736685295f4SBill Fenner printf(", subject=DNS name"); 737685295f4SBill Fenner cp = (const u_char *)(ni6 + 1); 738685295f4SBill Fenner if (cp[0] == ep - cp - 1) { 739685295f4SBill Fenner /* icmp-name-lookup-03, pascal string */ 740685295f4SBill Fenner if (vflag) 741685295f4SBill Fenner printf(", 03 draft"); 742685295f4SBill Fenner cp++; 743685295f4SBill Fenner printf(", \""); 744685295f4SBill Fenner while (cp < ep) { 745685295f4SBill Fenner safeputchar(*cp); 746685295f4SBill Fenner cp++; 747685295f4SBill Fenner } 748685295f4SBill Fenner printf("\""); 749685295f4SBill Fenner } else 750685295f4SBill Fenner dnsname_print(cp, ep); 751685295f4SBill Fenner break; 752685295f4SBill Fenner case ICMP6_NI_SUBJ_IPV4: 753685295f4SBill Fenner if (!TTEST2(*dp, sizeof(*ni6) + sizeof(struct in_addr))) 754685295f4SBill Fenner break; 755685295f4SBill Fenner if (siz != sizeof(*ni6) + sizeof(struct in_addr)) { 756685295f4SBill Fenner if (vflag) 757685295f4SBill Fenner printf(", invalid subject len"); 758685295f4SBill Fenner break; 759685295f4SBill Fenner } 760685295f4SBill Fenner printf(", subject=%s", 761685295f4SBill Fenner getname((const u_char *)(ni6 + 1))); 762685295f4SBill Fenner break; 763685295f4SBill Fenner default: 764685295f4SBill Fenner printf(", unknown subject"); 765685295f4SBill Fenner break; 766685295f4SBill Fenner } 767685295f4SBill Fenner 768685295f4SBill Fenner /*(*/ 769685295f4SBill Fenner printf(")"); 770685295f4SBill Fenner break; 771685295f4SBill Fenner 772685295f4SBill Fenner case ICMP6_NI_REPLY: 773685295f4SBill Fenner if (icmp6len > siz) { 774685295f4SBill Fenner printf("[|icmp6: node information reply]"); 775685295f4SBill Fenner break; 776685295f4SBill Fenner } 777685295f4SBill Fenner 778685295f4SBill Fenner needcomma = 0; 779685295f4SBill Fenner 780685295f4SBill Fenner ni6 = (struct icmp6_nodeinfo *)dp; 781685295f4SBill Fenner printf("icmp6: node information reply"); 782685295f4SBill Fenner printf(" ("); /*)*/ 783685295f4SBill Fenner switch (ni6->ni_code) { 784685295f4SBill Fenner case ICMP6_NI_SUCCESS: 785685295f4SBill Fenner if (vflag) { 786685295f4SBill Fenner printf("success"); 787685295f4SBill Fenner needcomma++; 788685295f4SBill Fenner } 789685295f4SBill Fenner break; 790685295f4SBill Fenner case ICMP6_NI_REFUSED: 791685295f4SBill Fenner printf("refused"); 792685295f4SBill Fenner needcomma++; 793685295f4SBill Fenner if (siz != sizeof(*ni6)) 794685295f4SBill Fenner if (vflag) 795685295f4SBill Fenner printf(", invalid length"); 796685295f4SBill Fenner break; 797685295f4SBill Fenner case ICMP6_NI_UNKNOWN: 798685295f4SBill Fenner printf("unknown"); 799685295f4SBill Fenner needcomma++; 800685295f4SBill Fenner if (siz != sizeof(*ni6)) 801685295f4SBill Fenner if (vflag) 802685295f4SBill Fenner printf(", invalid length"); 803685295f4SBill Fenner break; 804685295f4SBill Fenner } 805685295f4SBill Fenner 806685295f4SBill Fenner if (ni6->ni_code != ICMP6_NI_SUCCESS) { 807685295f4SBill Fenner /*(*/ 808685295f4SBill Fenner printf(")"); 809685295f4SBill Fenner break; 810685295f4SBill Fenner } 811685295f4SBill Fenner 812685295f4SBill Fenner switch (ntohs(ni6->ni_qtype)) { 813685295f4SBill Fenner case NI_QTYPE_NOOP: 814685295f4SBill Fenner if (needcomma) 815685295f4SBill Fenner printf(", "); 816685295f4SBill Fenner printf("noop"); 817685295f4SBill Fenner if (siz != sizeof(*ni6)) 818685295f4SBill Fenner if (vflag) 819685295f4SBill Fenner printf(", invalid length"); 820685295f4SBill Fenner break; 821685295f4SBill Fenner case NI_QTYPE_SUPTYPES: 822685295f4SBill Fenner if (needcomma) 823685295f4SBill Fenner printf(", "); 824685295f4SBill Fenner printf("supported qtypes"); 825685295f4SBill Fenner i = ntohs(ni6->ni_flags); 826685295f4SBill Fenner if (i) 827685295f4SBill Fenner printf(" [%s]", (i & 0x01) ? "C" : ""); 828685295f4SBill Fenner break; 829685295f4SBill Fenner case NI_QTYPE_FQDN: 830685295f4SBill Fenner if (needcomma) 831685295f4SBill Fenner printf(", "); 832685295f4SBill Fenner printf("DNS name"); 833685295f4SBill Fenner cp = (const u_char *)(ni6 + 1) + 4; 834685295f4SBill Fenner if (cp[0] == ep - cp - 1) { 835685295f4SBill Fenner /* icmp-name-lookup-03, pascal string */ 836685295f4SBill Fenner if (vflag) 837685295f4SBill Fenner printf(", 03 draft"); 838685295f4SBill Fenner cp++; 839685295f4SBill Fenner printf(", \""); 840685295f4SBill Fenner while (cp < ep) { 841685295f4SBill Fenner safeputchar(*cp); 842685295f4SBill Fenner cp++; 843685295f4SBill Fenner } 844685295f4SBill Fenner printf("\""); 845685295f4SBill Fenner } else 846685295f4SBill Fenner dnsname_print(cp, ep); 847685295f4SBill Fenner if ((ntohs(ni6->ni_flags) & 0x01) != 0) 848685295f4SBill Fenner printf(" [TTL=%u]", *(u_int32_t *)(ni6 + 1)); 849685295f4SBill Fenner break; 850685295f4SBill Fenner case NI_QTYPE_NODEADDR: 851685295f4SBill Fenner if (needcomma) 852685295f4SBill Fenner printf(", "); 853685295f4SBill Fenner printf("node addresses"); 854685295f4SBill Fenner i = sizeof(*ni6); 855685295f4SBill Fenner while (i < siz) { 856685295f4SBill Fenner if (i + sizeof(struct in6_addr) + sizeof(int32_t) > siz) 857685295f4SBill Fenner break; 858685295f4SBill Fenner printf(" %s", getname6(bp + i)); 859685295f4SBill Fenner i += sizeof(struct in6_addr); 860a90e161bSBill Fenner printf("(%d)", (int32_t)ntohl(*(int32_t *)(bp + i))); 861685295f4SBill Fenner i += sizeof(int32_t); 862685295f4SBill Fenner } 863685295f4SBill Fenner i = ni6->ni_flags; 864685295f4SBill Fenner if (!i) 865685295f4SBill Fenner break; 866685295f4SBill Fenner printf(" [%s%s%s%s%s%s%s]", 867685295f4SBill Fenner (i & NI_NODEADDR_FLAG_ANYCAST) ? "a" : "", 868685295f4SBill Fenner (i & NI_NODEADDR_FLAG_GLOBAL) ? "G" : "", 869685295f4SBill Fenner (i & NI_NODEADDR_FLAG_SITELOCAL) ? "S" : "", 870685295f4SBill Fenner (i & NI_NODEADDR_FLAG_LINKLOCAL) ? "L" : "", 871685295f4SBill Fenner (i & NI_NODEADDR_FLAG_COMPAT) ? "C" : "", 872685295f4SBill Fenner (i & NI_NODEADDR_FLAG_ALL) ? "A" : "", 873685295f4SBill Fenner (i & NI_NODEADDR_FLAG_TRUNCATE) ? "T" : ""); 874685295f4SBill Fenner break; 875685295f4SBill Fenner default: 876685295f4SBill Fenner if (needcomma) 877685295f4SBill Fenner printf(", "); 878685295f4SBill Fenner printf("unknown"); 879685295f4SBill Fenner break; 880685295f4SBill Fenner } 881685295f4SBill Fenner 882685295f4SBill Fenner /*(*/ 883685295f4SBill Fenner printf(")"); 884685295f4SBill Fenner break; 885685295f4SBill Fenner } 886685295f4SBill Fenner return; 887685295f4SBill Fenner 888685295f4SBill Fenner trunc: 889685295f4SBill Fenner fputs("[|icmp6]", stdout); 890685295f4SBill Fenner } 891685295f4SBill Fenner 892685295f4SBill Fenner void 893685295f4SBill Fenner icmp6_rrenum_print(int icmp6len, const u_char *bp, const u_char *ep) 894685295f4SBill Fenner { 895685295f4SBill Fenner struct icmp6_router_renum *rr6; 896685295f4SBill Fenner struct icmp6_hdr *dp; 897685295f4SBill Fenner size_t siz; 898685295f4SBill Fenner const char *cp; 899685295f4SBill Fenner struct rr_pco_match *match; 900685295f4SBill Fenner struct rr_pco_use *use; 901685295f4SBill Fenner char hbuf[NI_MAXHOST]; 902685295f4SBill Fenner int n; 903685295f4SBill Fenner 904685295f4SBill Fenner dp = (struct icmp6_hdr *)bp; 905685295f4SBill Fenner rr6 = (struct icmp6_router_renum *)bp; 906685295f4SBill Fenner siz = ep - bp; 907685295f4SBill Fenner cp = (const char *)(rr6 + 1); 908685295f4SBill Fenner 909685295f4SBill Fenner TCHECK(rr6->rr_reserved); 910685295f4SBill Fenner switch (rr6->rr_code) { 911685295f4SBill Fenner case ICMP6_ROUTER_RENUMBERING_COMMAND: 912685295f4SBill Fenner printf("router renum: command"); 913685295f4SBill Fenner break; 914685295f4SBill Fenner case ICMP6_ROUTER_RENUMBERING_RESULT: 915685295f4SBill Fenner printf("router renum: result"); 916685295f4SBill Fenner break; 917685295f4SBill Fenner case ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET: 918685295f4SBill Fenner printf("router renum: sequence number reset"); 919685295f4SBill Fenner break; 920685295f4SBill Fenner default: 921685295f4SBill Fenner printf("router renum: code-#%d", rr6->rr_code); 922685295f4SBill Fenner break; 923685295f4SBill Fenner } 924685295f4SBill Fenner 925685295f4SBill Fenner printf(", seq=%u", (u_int32_t)ntohl(rr6->rr_seqnum)); 926685295f4SBill Fenner 927685295f4SBill Fenner if (vflag) { 928685295f4SBill Fenner #define F(x, y) ((rr6->rr_flags) & (x) ? (y) : "") 929685295f4SBill Fenner printf("["); /*]*/ 930685295f4SBill Fenner if (rr6->rr_flags) { 931685295f4SBill Fenner printf("%s%s%s%s%s,", F(ICMP6_RR_FLAGS_TEST, "T"), 932685295f4SBill Fenner F(ICMP6_RR_FLAGS_REQRESULT, "R"), 933a90e161bSBill Fenner F(ICMP6_RR_FLAGS_FORCEAPPLY, "A"), 934685295f4SBill Fenner F(ICMP6_RR_FLAGS_SPECSITE, "S"), 935685295f4SBill Fenner F(ICMP6_RR_FLAGS_PREVDONE, "P")); 936685295f4SBill Fenner } 937685295f4SBill Fenner printf("seg=%u,", rr6->rr_segnum); 938685295f4SBill Fenner printf("maxdelay=%u", rr6->rr_maxdelay); 939685295f4SBill Fenner if (rr6->rr_reserved) 940685295f4SBill Fenner printf("rsvd=0x%x", (u_int16_t)ntohs(rr6->rr_reserved)); 941685295f4SBill Fenner /*[*/ 942685295f4SBill Fenner printf("]"); 943685295f4SBill Fenner #undef F 944685295f4SBill Fenner } 945685295f4SBill Fenner 946685295f4SBill Fenner if (rr6->rr_code == ICMP6_ROUTER_RENUMBERING_COMMAND) { 947685295f4SBill Fenner match = (struct rr_pco_match *)cp; 948685295f4SBill Fenner cp = (const char *)(match + 1); 949685295f4SBill Fenner 950685295f4SBill Fenner TCHECK(match->rpm_prefix); 951685295f4SBill Fenner 952a90e161bSBill Fenner if (vflag > 1) 953685295f4SBill Fenner printf("\n\t"); 954685295f4SBill Fenner else 955685295f4SBill Fenner printf(" "); 956685295f4SBill Fenner printf("match("); /*)*/ 957685295f4SBill Fenner switch (match->rpm_code) { 958685295f4SBill Fenner case RPM_PCO_ADD: printf("add"); break; 959685295f4SBill Fenner case RPM_PCO_CHANGE: printf("change"); break; 960685295f4SBill Fenner case RPM_PCO_SETGLOBAL: printf("setglobal"); break; 961685295f4SBill Fenner default: printf("#%u", match->rpm_code); break; 962685295f4SBill Fenner } 963685295f4SBill Fenner 964685295f4SBill Fenner if (vflag) { 965685295f4SBill Fenner printf(",ord=%u", match->rpm_ordinal); 966685295f4SBill Fenner printf(",min=%u", match->rpm_minlen); 967685295f4SBill Fenner printf(",max=%u", match->rpm_maxlen); 968685295f4SBill Fenner } 969685295f4SBill Fenner if (inet_ntop(AF_INET6, &match->rpm_prefix, hbuf, sizeof(hbuf))) 970685295f4SBill Fenner printf(",%s/%u", hbuf, match->rpm_matchlen); 971685295f4SBill Fenner else 972685295f4SBill Fenner printf(",?/%u", match->rpm_matchlen); 973685295f4SBill Fenner /*(*/ 974685295f4SBill Fenner printf(")"); 975685295f4SBill Fenner 976685295f4SBill Fenner n = match->rpm_len - 3; 977685295f4SBill Fenner if (n % 4) 978685295f4SBill Fenner goto trunc; 979685295f4SBill Fenner n /= 4; 980685295f4SBill Fenner while (n-- > 0) { 981685295f4SBill Fenner use = (struct rr_pco_use *)cp; 982685295f4SBill Fenner cp = (const char *)(use + 1); 983685295f4SBill Fenner 984685295f4SBill Fenner TCHECK(use->rpu_prefix); 985685295f4SBill Fenner 986a90e161bSBill Fenner if (vflag > 1) 987685295f4SBill Fenner printf("\n\t"); 988685295f4SBill Fenner else 989685295f4SBill Fenner printf(" "); 990685295f4SBill Fenner printf("use("); /*)*/ 991685295f4SBill Fenner if (use->rpu_flags) { 992685295f4SBill Fenner #define F(x, y) ((use->rpu_flags) & (x) ? (y) : "") 993685295f4SBill Fenner printf("%s%s,", 994685295f4SBill Fenner F(ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME, "V"), 995685295f4SBill Fenner F(ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME, "P")); 996685295f4SBill Fenner #undef F 997685295f4SBill Fenner } 998685295f4SBill Fenner if (vflag) { 999685295f4SBill Fenner printf("mask=0x%x,", use->rpu_ramask); 1000685295f4SBill Fenner printf("raflags=0x%x,", use->rpu_raflags); 1001685295f4SBill Fenner if (~use->rpu_vltime == 0) 1002685295f4SBill Fenner printf("vltime=infty,"); 1003685295f4SBill Fenner else 1004685295f4SBill Fenner printf("vltime=%u,", 1005685295f4SBill Fenner (u_int32_t)ntohl(use->rpu_vltime)); 1006685295f4SBill Fenner if (~use->rpu_pltime == 0) 1007685295f4SBill Fenner printf("pltime=infty,"); 1008685295f4SBill Fenner else 1009685295f4SBill Fenner printf("pltime=%u,", 1010685295f4SBill Fenner (u_int32_t)ntohl(use->rpu_pltime)); 1011685295f4SBill Fenner } 1012685295f4SBill Fenner if (inet_ntop(AF_INET6, &use->rpu_prefix, hbuf, 1013685295f4SBill Fenner sizeof(hbuf))) 1014685295f4SBill Fenner printf("%s/%u/%u", hbuf, use->rpu_uselen, 1015685295f4SBill Fenner use->rpu_keeplen); 1016685295f4SBill Fenner else 1017685295f4SBill Fenner printf("?/%u/%u", use->rpu_uselen, 1018685295f4SBill Fenner use->rpu_keeplen); 1019685295f4SBill Fenner /*(*/ 1020685295f4SBill Fenner printf(")"); 1021685295f4SBill Fenner } 1022685295f4SBill Fenner } 1023b0453382SBill Fenner 1024b0453382SBill Fenner return; 1025685295f4SBill Fenner 1026685295f4SBill Fenner trunc: 1027685295f4SBill Fenner fputs("[|icmp6]", stdout); 1028b0453382SBill Fenner } 1029685295f4SBill Fenner 1030b0453382SBill Fenner #endif /* INET6 */ 1031