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[] = 24b0453382SBill Fenner "@(#) $Header: /tcpdump/master/tcpdump/print-icmp6.c,v 1.2.2.1 2000/01/11 06:58:24 fenner 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 #include <net/if.h> 41b0453382SBill Fenner 42b0453382SBill Fenner #include <netinet/in.h> 43b0453382SBill Fenner #include <netinet/if_ether.h> 44b0453382SBill Fenner #include <netinet/in_systm.h> 45b0453382SBill Fenner #include <netinet/ip.h> 46b0453382SBill Fenner #include <netinet/ip_icmp.h> 47b0453382SBill Fenner #include <netinet/ip_var.h> 48b0453382SBill Fenner #include <netinet/udp.h> 49b0453382SBill Fenner #include <netinet/udp_var.h> 50b0453382SBill Fenner #include <netinet/tcp.h> 51b0453382SBill Fenner 52b0453382SBill Fenner #include <arpa/inet.h> 53b0453382SBill Fenner 54b0453382SBill Fenner #include <stdio.h> 55b0453382SBill Fenner 56b0453382SBill Fenner #include <netinet/ip6.h> 57b0453382SBill Fenner #include <netinet/icmp6.h> 58b0453382SBill Fenner 59b0453382SBill Fenner #include "interface.h" 60b0453382SBill Fenner #include "addrtoname.h" 61b0453382SBill Fenner 62b0453382SBill Fenner void icmp6_opt_print(const u_char *, int); 63b0453382SBill Fenner void mld6_print(const u_char *); 64b0453382SBill Fenner 65b0453382SBill Fenner void 66b0453382SBill Fenner icmp6_print(register const u_char *bp, register const u_char *bp2) 67b0453382SBill Fenner { 68b0453382SBill Fenner register const struct icmp6_hdr *dp; 69b0453382SBill Fenner register const struct ip6_hdr *ip; 70b0453382SBill Fenner register const char *str; 71b0453382SBill Fenner register const struct ip6_hdr *oip; 72b0453382SBill Fenner register const struct udphdr *ouh; 73b0453382SBill Fenner register int hlen, dport; 74b0453382SBill Fenner register const u_char *ep; 75b0453382SBill Fenner char buf[256]; 76b0453382SBill Fenner int icmp6len; 77b0453382SBill Fenner 78b0453382SBill Fenner #if 0 79b0453382SBill Fenner #define TCHECK(var) if ((u_char *)&(var) > ep - sizeof(var)) goto trunc 80b0453382SBill Fenner #endif 81b0453382SBill Fenner 82b0453382SBill Fenner dp = (struct icmp6_hdr *)bp; 83b0453382SBill Fenner ip = (struct ip6_hdr *)bp2; 84b0453382SBill Fenner oip = (struct ip6_hdr *)(dp + 1); 85b0453382SBill Fenner str = buf; 86b0453382SBill Fenner /* 'ep' points to the end of avaible data. */ 87b0453382SBill Fenner ep = snapend; 88b0453382SBill Fenner if (ip->ip6_plen) 89b0453382SBill Fenner icmp6len = (ntohs(ip->ip6_plen) + sizeof(struct ip6_hdr) - 90b0453382SBill Fenner (bp - bp2)); 91b0453382SBill Fenner else /* XXX: jumbo payload case... */ 92b0453382SBill Fenner icmp6len = snapend - bp; 93b0453382SBill Fenner 94b0453382SBill Fenner #if 0 95b0453382SBill Fenner (void)printf("%s > %s: ", 96b0453382SBill Fenner ip6addr_string(&ip->ip6_src), 97b0453382SBill Fenner ip6addr_string(&ip->ip6_dst)); 98b0453382SBill Fenner #endif 99b0453382SBill Fenner 100b0453382SBill Fenner TCHECK(dp->icmp6_code); 101b0453382SBill Fenner switch(dp->icmp6_type) { 102b0453382SBill Fenner case ICMP6_DST_UNREACH: 103b0453382SBill Fenner TCHECK(oip->ip6_dst); 104b0453382SBill Fenner switch (dp->icmp6_code) { 105b0453382SBill Fenner case ICMP6_DST_UNREACH_NOROUTE: 106b0453382SBill Fenner printf("icmp6: %s unreachable route", 107b0453382SBill Fenner ip6addr_string(&oip->ip6_dst)); 108b0453382SBill Fenner break; 109b0453382SBill Fenner case ICMP6_DST_UNREACH_ADMIN: 110b0453382SBill Fenner printf("icmp6: %s unreachable prohibited", 111b0453382SBill Fenner ip6addr_string(&oip->ip6_dst)); 112b0453382SBill Fenner break; 113b0453382SBill Fenner #ifdef ICMP6_DST_UNREACH_BEYONDSCOPE 114b0453382SBill Fenner case ICMP6_DST_UNREACH_BEYONDSCOPE: 115b0453382SBill Fenner #else 116b0453382SBill Fenner case ICMP6_DST_UNREACH_NOTNEIGHBOR: 117b0453382SBill Fenner #endif 118b0453382SBill Fenner printf("icmp6: %s beyond scope of source address %s", 119b0453382SBill Fenner ip6addr_string(&oip->ip6_dst), 120b0453382SBill Fenner ip6addr_string(&oip->ip6_src)); 121b0453382SBill Fenner break; 122b0453382SBill Fenner case ICMP6_DST_UNREACH_ADDR: 123b0453382SBill Fenner printf("icmp6: %s unreachable address", 124b0453382SBill Fenner ip6addr_string(&oip->ip6_dst)); 125b0453382SBill Fenner break; 126b0453382SBill Fenner case ICMP6_DST_UNREACH_NOPORT: 127b0453382SBill Fenner TCHECK(oip->ip6_nxt); 128b0453382SBill Fenner hlen = sizeof(struct ip6_hdr); 129b0453382SBill Fenner ouh = (struct udphdr *)(((u_char *)oip) + hlen); 130b0453382SBill Fenner dport = ntohs(ouh->uh_dport); 131b0453382SBill Fenner switch (oip->ip6_nxt) { 132b0453382SBill Fenner case IPPROTO_TCP: 133b0453382SBill Fenner printf("icmp6: %s tcp port %s unreachable", 134b0453382SBill Fenner ip6addr_string(&oip->ip6_dst), 135b0453382SBill Fenner tcpport_string(dport)); 136b0453382SBill Fenner break; 137b0453382SBill Fenner case IPPROTO_UDP: 138b0453382SBill Fenner printf("icmp6: %s udp port %s unreachable", 139b0453382SBill Fenner ip6addr_string(&oip->ip6_dst), 140b0453382SBill Fenner udpport_string(dport)); 141b0453382SBill Fenner break; 142b0453382SBill Fenner default: 143b0453382SBill Fenner printf("icmp6: %s protocol %d port %d unreachable", 144b0453382SBill Fenner ip6addr_string(&oip->ip6_dst), 145b0453382SBill Fenner oip->ip6_nxt, dport); 146b0453382SBill Fenner break; 147b0453382SBill Fenner } 148b0453382SBill Fenner break; 149b0453382SBill Fenner default: 150b0453382SBill Fenner printf("icmp6: %s unreachable code-#%d", 151b0453382SBill Fenner ip6addr_string(&oip->ip6_dst), 152b0453382SBill Fenner dp->icmp6_code); 153b0453382SBill Fenner break; 154b0453382SBill Fenner } 155b0453382SBill Fenner break; 156b0453382SBill Fenner case ICMP6_PACKET_TOO_BIG: 157b0453382SBill Fenner TCHECK(dp->icmp6_mtu); 158b0453382SBill Fenner printf("icmp6: too big %u\n", (u_int32_t)ntohl(dp->icmp6_mtu)); 159b0453382SBill Fenner break; 160b0453382SBill Fenner case ICMP6_TIME_EXCEEDED: 161b0453382SBill Fenner TCHECK(oip->ip6_dst); 162b0453382SBill Fenner switch (dp->icmp6_code) { 163b0453382SBill Fenner case ICMP6_TIME_EXCEED_TRANSIT: 164b0453382SBill Fenner printf("icmp6: time exceeded in-transit for %s", 165b0453382SBill Fenner ip6addr_string(&oip->ip6_dst)); 166b0453382SBill Fenner break; 167b0453382SBill Fenner case ICMP6_TIME_EXCEED_REASSEMBLY: 168b0453382SBill Fenner printf("icmp6: ip6 reassembly time exceeded"); 169b0453382SBill Fenner break; 170b0453382SBill Fenner default: 171b0453382SBill Fenner printf("icmp6: time exceeded code-#%d", 172b0453382SBill Fenner dp->icmp6_code); 173b0453382SBill Fenner break; 174b0453382SBill Fenner } 175b0453382SBill Fenner break; 176b0453382SBill Fenner case ICMP6_PARAM_PROB: 177b0453382SBill Fenner TCHECK(oip->ip6_dst); 178b0453382SBill Fenner switch (dp->icmp6_code) { 179b0453382SBill Fenner case ICMP6_PARAMPROB_HEADER: 180b0453382SBill Fenner printf("icmp6: parameter problem errorneous - octet %u\n", 181b0453382SBill Fenner (u_int32_t)ntohl(dp->icmp6_pptr)); 182b0453382SBill Fenner break; 183b0453382SBill Fenner case ICMP6_PARAMPROB_NEXTHEADER: 184b0453382SBill Fenner printf("icmp6: parameter problem next header - octet %u\n", 185b0453382SBill Fenner (u_int32_t)ntohl(dp->icmp6_pptr)); 186b0453382SBill Fenner break; 187b0453382SBill Fenner case ICMP6_PARAMPROB_OPTION: 188b0453382SBill Fenner printf("icmp6: parameter problem option - octet %u\n", 189b0453382SBill Fenner (u_int32_t)ntohl(dp->icmp6_pptr)); 190b0453382SBill Fenner break; 191b0453382SBill Fenner default: 192b0453382SBill Fenner printf("icmp6: parameter problem code-#%d", 193b0453382SBill Fenner dp->icmp6_code); 194b0453382SBill Fenner break; 195b0453382SBill Fenner } 196b0453382SBill Fenner break; 197b0453382SBill Fenner case ICMP6_ECHO_REQUEST: 198b0453382SBill Fenner printf("icmp6: echo request"); 199b0453382SBill Fenner break; 200b0453382SBill Fenner case ICMP6_ECHO_REPLY: 201b0453382SBill Fenner printf("icmp6: echo reply"); 202b0453382SBill Fenner break; 203b0453382SBill Fenner case ICMP6_MEMBERSHIP_QUERY: 204b0453382SBill Fenner printf("icmp6: multicast listener query "); 205b0453382SBill Fenner mld6_print((const u_char *)dp); 206b0453382SBill Fenner break; 207b0453382SBill Fenner case ICMP6_MEMBERSHIP_REPORT: 208b0453382SBill Fenner printf("icmp6: multicast listener report "); 209b0453382SBill Fenner mld6_print((const u_char *)dp); 210b0453382SBill Fenner break; 211b0453382SBill Fenner case ICMP6_MEMBERSHIP_REDUCTION: 212b0453382SBill Fenner printf("icmp6: multicast listener done "); 213b0453382SBill Fenner mld6_print((const u_char *)dp); 214b0453382SBill Fenner break; 215b0453382SBill Fenner case ND_ROUTER_SOLICIT: 216b0453382SBill Fenner printf("icmp6: router solicitation "); 217b0453382SBill Fenner if (vflag) { 218b0453382SBill Fenner #define RTSOLLEN 8 219b0453382SBill Fenner icmp6_opt_print((const u_char *)dp + RTSOLLEN, 220b0453382SBill Fenner icmp6len - RTSOLLEN); 221b0453382SBill Fenner } 222b0453382SBill Fenner break; 223b0453382SBill Fenner case ND_ROUTER_ADVERT: 224b0453382SBill Fenner printf("icmp6: router advertisement"); 225b0453382SBill Fenner if (vflag) { 226b0453382SBill Fenner struct nd_router_advert *p; 227b0453382SBill Fenner 228b0453382SBill Fenner p = (struct nd_router_advert *)dp; 229b0453382SBill Fenner TCHECK(p->nd_ra_retransmit); 230b0453382SBill Fenner printf("(chlim=%d, ", (int)p->nd_ra_curhoplimit); 231b0453382SBill Fenner if (p->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED) 232b0453382SBill Fenner printf("M"); 233b0453382SBill Fenner if (p->nd_ra_flags_reserved & ND_RA_FLAG_OTHER) 234b0453382SBill Fenner printf("O"); 235b0453382SBill Fenner if (p->nd_ra_flags_reserved != 0) 236b0453382SBill Fenner printf(" "); 237b0453382SBill Fenner printf("router_ltime=%d, ", ntohs(p->nd_ra_router_lifetime)); 238b0453382SBill Fenner printf("reachable_time=%u, ", 239b0453382SBill Fenner (u_int32_t)ntohl(p->nd_ra_reachable)); 240b0453382SBill Fenner printf("retrans_time=%u)", 241b0453382SBill Fenner (u_int32_t)ntohl(p->nd_ra_retransmit)); 242b0453382SBill Fenner #define RTADVLEN 16 243b0453382SBill Fenner icmp6_opt_print((const u_char *)dp + RTADVLEN, 244b0453382SBill Fenner icmp6len - RTADVLEN); 245b0453382SBill Fenner } 246b0453382SBill Fenner break; 247b0453382SBill Fenner case ND_NEIGHBOR_SOLICIT: 248b0453382SBill Fenner { 249b0453382SBill Fenner struct nd_neighbor_solicit *p; 250b0453382SBill Fenner p = (struct nd_neighbor_solicit *)dp; 251b0453382SBill Fenner TCHECK(p->nd_ns_target); 252b0453382SBill Fenner printf("icmp6: neighbor sol: who has %s", 253b0453382SBill Fenner ip6addr_string(&p->nd_ns_target)); 254b0453382SBill Fenner if (vflag) { 255b0453382SBill Fenner #define NDSOLLEN 24 256b0453382SBill Fenner icmp6_opt_print((const u_char *)dp + NDSOLLEN, 257b0453382SBill Fenner icmp6len - NDSOLLEN); 258b0453382SBill Fenner } 259b0453382SBill Fenner } 260b0453382SBill Fenner break; 261b0453382SBill Fenner case ND_NEIGHBOR_ADVERT: 262b0453382SBill Fenner { 263b0453382SBill Fenner struct nd_neighbor_advert *p; 264b0453382SBill Fenner 265b0453382SBill Fenner p = (struct nd_neighbor_advert *)dp; 266b0453382SBill Fenner TCHECK(p->nd_na_target); 267b0453382SBill Fenner printf("icmp6: neighbor adv: tgt is %s", 268b0453382SBill Fenner ip6addr_string(&p->nd_na_target)); 269b0453382SBill Fenner if (vflag) { 270b0453382SBill Fenner #define ND_NA_FLAG_ALL \ 271b0453382SBill Fenner (ND_NA_FLAG_ROUTER|ND_NA_FLAG_SOLICITED|ND_NA_FLAG_OVERRIDE) 272b0453382SBill Fenner /* we don't need ntohl() here. see advanced-api-04. */ 273b0453382SBill Fenner if (p->nd_na_flags_reserved & ND_NA_FLAG_ALL) { 274b0453382SBill Fenner #undef ND_NA_FLAG_ALL 275b0453382SBill Fenner u_int32_t flags; 276b0453382SBill Fenner 277b0453382SBill Fenner flags = p->nd_na_flags_reserved; 278b0453382SBill Fenner printf("("); 279b0453382SBill Fenner if (flags & ND_NA_FLAG_ROUTER) 280b0453382SBill Fenner printf("R"); 281b0453382SBill Fenner if (flags & ND_NA_FLAG_SOLICITED) 282b0453382SBill Fenner printf("S"); 283b0453382SBill Fenner if (flags & ND_NA_FLAG_OVERRIDE) 284b0453382SBill Fenner printf("O"); 285b0453382SBill Fenner printf(")"); 286b0453382SBill Fenner } 287b0453382SBill Fenner #define NDADVLEN 24 288b0453382SBill Fenner icmp6_opt_print((const u_char *)dp + NDADVLEN, 289b0453382SBill Fenner icmp6len - NDADVLEN); 290b0453382SBill Fenner } 291b0453382SBill Fenner } 292b0453382SBill Fenner break; 293b0453382SBill Fenner case ND_REDIRECT: 294b0453382SBill Fenner { 295b0453382SBill Fenner #define RDR(i) ((struct nd_redirect *)(i)) 296b0453382SBill Fenner char tgtbuf[INET6_ADDRSTRLEN], dstbuf[INET6_ADDRSTRLEN]; 297b0453382SBill Fenner 298b0453382SBill Fenner TCHECK(RDR(dp)->nd_rd_dst); 299b0453382SBill Fenner inet_ntop(AF_INET6, &RDR(dp)->nd_rd_target, 300b0453382SBill Fenner tgtbuf, INET6_ADDRSTRLEN); 301b0453382SBill Fenner inet_ntop(AF_INET6, &RDR(dp)->nd_rd_dst, 302b0453382SBill Fenner dstbuf, INET6_ADDRSTRLEN); 303b0453382SBill Fenner printf("icmp6: redirect %s to %s", dstbuf, tgtbuf); 304b0453382SBill Fenner #define REDIRECTLEN 40 305b0453382SBill Fenner if (vflag) { 306b0453382SBill Fenner icmp6_opt_print((const u_char *)dp + REDIRECTLEN, 307b0453382SBill Fenner icmp6len - REDIRECTLEN); 308b0453382SBill Fenner } 309b0453382SBill Fenner break; 310b0453382SBill Fenner } 311b0453382SBill Fenner case ICMP6_ROUTER_RENUMBERING: 312b0453382SBill Fenner switch (dp->icmp6_code) { 313b0453382SBill Fenner case ICMP6_ROUTER_RENUMBERING_COMMAND: 314b0453382SBill Fenner printf("icmp6: router renum command"); 315b0453382SBill Fenner break; 316b0453382SBill Fenner case ICMP6_ROUTER_RENUMBERING_RESULT: 317b0453382SBill Fenner printf("icmp6: router renum result"); 318b0453382SBill Fenner break; 319b0453382SBill Fenner default: 320b0453382SBill Fenner printf("icmp6: router renum code-#%d", dp->icmp6_code); 321b0453382SBill Fenner break; 322b0453382SBill Fenner } 323b0453382SBill Fenner break; 324b0453382SBill Fenner #ifdef ICMP6_WRUREQUEST 325b0453382SBill Fenner case ICMP6_WRUREQUEST: /*ICMP6_FQDN_QUERY*/ 326b0453382SBill Fenner { 327b0453382SBill Fenner int siz; 328b0453382SBill Fenner siz = ep - (u_char *)(dp + 1); 329b0453382SBill Fenner if (siz == 4) 330b0453382SBill Fenner printf("icmp6: who-are-you request"); 331b0453382SBill Fenner else { 332b0453382SBill Fenner printf("icmp6: FQDN request"); 333b0453382SBill Fenner if (vflag) { 334b0453382SBill Fenner if (siz < 8) 335b0453382SBill Fenner printf("?(icmp6_data %d bytes)", siz); 336b0453382SBill Fenner else if (8 < siz) 337b0453382SBill Fenner printf("?(extra %d bytes)", siz - 8); 338b0453382SBill Fenner } 339b0453382SBill Fenner } 340b0453382SBill Fenner break; 341b0453382SBill Fenner } 342b0453382SBill Fenner #endif /*ICMP6_WRUREQUEST*/ 343b0453382SBill Fenner #ifdef ICMP6_WRUREPLY 344b0453382SBill Fenner case ICMP6_WRUREPLY: /*ICMP6_FQDN_REPLY*/ 345b0453382SBill Fenner { 346b0453382SBill Fenner enum { UNKNOWN, WRU, FQDN } mode = UNKNOWN; 347b0453382SBill Fenner u_char const *buf; 348b0453382SBill Fenner u_char const *cp = NULL; 349b0453382SBill Fenner 350b0453382SBill Fenner buf = (u_char *)(dp + 1); 351b0453382SBill Fenner 352b0453382SBill Fenner /* fair guess */ 353b0453382SBill Fenner if (buf[12] == ep - buf - 13) 354b0453382SBill Fenner mode = FQDN; 355b0453382SBill Fenner else if (dp->icmp6_code == 1) 356b0453382SBill Fenner mode = FQDN; 357b0453382SBill Fenner 358b0453382SBill Fenner /* wild guess */ 359b0453382SBill Fenner if (mode == UNKNOWN) { 360b0453382SBill Fenner cp = buf + 4; 361b0453382SBill Fenner while (cp < ep) { 362b0453382SBill Fenner if (!isprint(*cp++)) 363b0453382SBill Fenner mode = FQDN; 364b0453382SBill Fenner } 365b0453382SBill Fenner } 366b0453382SBill Fenner #ifndef abs 367b0453382SBill Fenner #define abs(a) ((0 < (a)) ? (a) : -(a)) 368b0453382SBill Fenner #endif 369b0453382SBill Fenner if (mode == UNKNOWN && 2 < abs(buf[12] - (ep - buf - 13))) 370b0453382SBill Fenner mode = WRU; 371b0453382SBill Fenner if (mode == UNKNOWN) 372b0453382SBill Fenner mode = FQDN; 373b0453382SBill Fenner 374b0453382SBill Fenner if (mode == WRU) { 375b0453382SBill Fenner cp = buf + 4; 376b0453382SBill Fenner printf("icmp6: who-are-you reply(\""); 377b0453382SBill Fenner } else if (mode == FQDN) { 378b0453382SBill Fenner cp = buf + 13; 379b0453382SBill Fenner printf("icmp6: FQDN reply(\""); 380b0453382SBill Fenner } 381b0453382SBill Fenner for (; cp < ep; cp++) 382b0453382SBill Fenner printf((isprint(*cp) ? "%c" : "\\%03o"), *cp); 383b0453382SBill Fenner printf("\""); 384b0453382SBill Fenner if (vflag) { 385b0453382SBill Fenner printf(",%s", mode == FQDN ? "FQDN" : "WRU"); 386b0453382SBill Fenner if (mode == FQDN) { 387b0453382SBill Fenner long ttl; 388b0453382SBill Fenner ttl = (long)ntohl(*(u_long *)&buf[8]); 389b0453382SBill Fenner if (dp->icmp6_code == 1) 390b0453382SBill Fenner printf(",TTL=unknown"); 391b0453382SBill Fenner else if (ttl < 0) 392b0453382SBill Fenner printf(",TTL=%ld:invalid", ttl); 393b0453382SBill Fenner else 394b0453382SBill Fenner printf(",TTL=%ld", ttl); 395b0453382SBill Fenner if (buf[12] != ep - buf - 13) { 396b0453382SBill Fenner (void)printf(",invalid namelen:%d/%u", 397b0453382SBill Fenner buf[12], 398b0453382SBill Fenner (unsigned int)(ep - buf - 13)); 399b0453382SBill Fenner } 400b0453382SBill Fenner } 401b0453382SBill Fenner } 402b0453382SBill Fenner printf(")"); 403b0453382SBill Fenner break; 404b0453382SBill Fenner } 405b0453382SBill Fenner #endif /*ICMP6_WRUREPLY*/ 406b0453382SBill Fenner default: 407b0453382SBill Fenner printf("icmp6: type-#%d", dp->icmp6_type); 408b0453382SBill Fenner break; 409b0453382SBill Fenner } 410b0453382SBill Fenner return; 411b0453382SBill Fenner trunc: 412b0453382SBill Fenner fputs("[|icmp6]", stdout); 413b0453382SBill Fenner #if 0 414b0453382SBill Fenner #undef TCHECK 415b0453382SBill Fenner #endif 416b0453382SBill Fenner } 417b0453382SBill Fenner 418b0453382SBill Fenner void 419b0453382SBill Fenner icmp6_opt_print(register const u_char *bp, int resid) 420b0453382SBill Fenner { 421b0453382SBill Fenner register const struct nd_opt_hdr *op; 422b0453382SBill Fenner register const struct nd_opt_hdr *opl; /* why there's no struct? */ 423b0453382SBill Fenner register const struct nd_opt_prefix_info *opp; 424b0453382SBill Fenner register const struct icmp6_opts_redirect *opr; 425b0453382SBill Fenner register const struct nd_opt_mtu *opm; 426b0453382SBill Fenner register const u_char *ep; 427b0453382SBill Fenner int opts_len; 428b0453382SBill Fenner #if 0 429b0453382SBill Fenner register const struct ip6_hdr *ip; 430b0453382SBill Fenner register const char *str; 431b0453382SBill Fenner register const struct ip6_hdr *oip; 432b0453382SBill Fenner register const struct udphdr *ouh; 433b0453382SBill Fenner register int hlen, dport; 434b0453382SBill Fenner char buf[256]; 435b0453382SBill Fenner #endif 436b0453382SBill Fenner 437b0453382SBill Fenner #if 0 438b0453382SBill Fenner #define TCHECK(var) if ((u_char *)&(var) > ep - sizeof(var)) goto trunc 439b0453382SBill Fenner #endif 440b0453382SBill Fenner #define ECHECK(var) if ((u_char *)&(var) > ep - sizeof(var)) return 441b0453382SBill Fenner 442b0453382SBill Fenner op = (struct nd_opt_hdr *)bp; 443b0453382SBill Fenner #if 0 444b0453382SBill Fenner ip = (struct ip6_hdr *)bp2; 445b0453382SBill Fenner oip = &dp->icmp6_ip6; 446b0453382SBill Fenner str = buf; 447b0453382SBill Fenner #endif 448b0453382SBill Fenner /* 'ep' points to the end of avaible data. */ 449b0453382SBill Fenner ep = snapend; 450b0453382SBill Fenner 451b0453382SBill Fenner ECHECK(op->nd_opt_len); 452b0453382SBill Fenner if (resid <= 0) 453b0453382SBill Fenner return; 454b0453382SBill Fenner switch(op->nd_opt_type) { 455b0453382SBill Fenner case ND_OPT_SOURCE_LINKADDR: 456b0453382SBill Fenner opl = (struct nd_opt_hdr *)op; 457b0453382SBill Fenner #if 1 458b0453382SBill Fenner if ((u_char *)opl + (opl->nd_opt_len << 3) > ep) 459b0453382SBill Fenner goto trunc; 460b0453382SBill Fenner #else 461b0453382SBill Fenner TCHECK((u_char *)opl + (opl->nd_opt_len << 3) - 1); 462b0453382SBill Fenner #endif 463b0453382SBill Fenner printf("(src lladdr: %s", 464b0453382SBill Fenner etheraddr_string((u_char *)(opl + 1))); 465b0453382SBill Fenner if (opl->nd_opt_len != 1) 466b0453382SBill Fenner printf("!"); 467b0453382SBill Fenner printf(")"); 468b0453382SBill Fenner icmp6_opt_print((const u_char *)op + (op->nd_opt_len << 3), 469b0453382SBill Fenner resid - (op->nd_opt_len << 3)); 470b0453382SBill Fenner break; 471b0453382SBill Fenner case ND_OPT_TARGET_LINKADDR: 472b0453382SBill Fenner opl = (struct nd_opt_hdr *)op; 473b0453382SBill Fenner #if 1 474b0453382SBill Fenner if ((u_char *)opl + (opl->nd_opt_len << 3) > ep) 475b0453382SBill Fenner goto trunc; 476b0453382SBill Fenner #else 477b0453382SBill Fenner TCHECK((u_char *)opl + (opl->nd_opt_len << 3) - 1); 478b0453382SBill Fenner #endif 479b0453382SBill Fenner printf("(tgt lladdr: %s", 480b0453382SBill Fenner etheraddr_string((u_char *)(opl + 1))); 481b0453382SBill Fenner if (opl->nd_opt_len != 1) 482b0453382SBill Fenner printf("!"); 483b0453382SBill Fenner printf(")"); 484b0453382SBill Fenner icmp6_opt_print((const u_char *)op + (op->nd_opt_len << 3), 485b0453382SBill Fenner resid - (op->nd_opt_len << 3)); 486b0453382SBill Fenner break; 487b0453382SBill Fenner case ND_OPT_PREFIX_INFORMATION: 488b0453382SBill Fenner opp = (struct nd_opt_prefix_info *)op; 489b0453382SBill Fenner TCHECK(opp->nd_opt_pi_prefix); 490b0453382SBill Fenner printf("(prefix info: "); 491b0453382SBill Fenner if (opp->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_ONLINK) 492b0453382SBill Fenner printf("L"); 493b0453382SBill Fenner if (opp->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_AUTO) 494b0453382SBill Fenner printf("A"); 495b0453382SBill Fenner if (opp->nd_opt_pi_flags_reserved) 496b0453382SBill Fenner printf(" "); 497b0453382SBill Fenner printf("valid_ltime="); 498b0453382SBill Fenner if ((u_int32_t)ntohl(opp->nd_opt_pi_valid_time) == ~0U) 499b0453382SBill Fenner printf("infinity"); 500b0453382SBill Fenner else { 501b0453382SBill Fenner printf("%u", (u_int32_t)ntohl(opp->nd_opt_pi_valid_time)); 502b0453382SBill Fenner } 503b0453382SBill Fenner printf(", "); 504b0453382SBill Fenner printf("preffered_ltime="); 505b0453382SBill Fenner if ((u_int32_t)ntohl(opp->nd_opt_pi_preferred_time) == ~0U) 506b0453382SBill Fenner printf("infinity"); 507b0453382SBill Fenner else { 508b0453382SBill Fenner printf("%u", (u_int32_t)ntohl(opp->nd_opt_pi_preferred_time)); 509b0453382SBill Fenner } 510b0453382SBill Fenner printf(", "); 511b0453382SBill Fenner printf("prefix=%s/%d", ip6addr_string(&opp->nd_opt_pi_prefix), 512b0453382SBill Fenner opp->nd_opt_pi_prefix_len); 513b0453382SBill Fenner if (opp->nd_opt_pi_len != 4) 514b0453382SBill Fenner printf("!"); 515b0453382SBill Fenner printf(")"); 516b0453382SBill Fenner icmp6_opt_print((const u_char *)op + (op->nd_opt_len << 3), 517b0453382SBill Fenner resid - (op->nd_opt_len << 3)); 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 icmp6_opt_print((const u_char *)op + (op->nd_opt_len << 3), 524b0453382SBill Fenner resid - (op->nd_opt_len << 3)); 525b0453382SBill Fenner break; 526b0453382SBill Fenner case ND_OPT_MTU: 527b0453382SBill Fenner opm = (struct nd_opt_mtu *)op; 528b0453382SBill Fenner TCHECK(opm->nd_opt_mtu_mtu); 529b0453382SBill Fenner printf("(mtu: "); 530b0453382SBill Fenner printf("mtu=%u", (u_int32_t)ntohl(opm->nd_opt_mtu_mtu)); 531b0453382SBill Fenner if (opm->nd_opt_mtu_len != 1) 532b0453382SBill Fenner printf("!"); 533b0453382SBill Fenner printf(")"); 534b0453382SBill Fenner icmp6_opt_print((const u_char *)op + (op->nd_opt_len << 3), 535b0453382SBill Fenner resid - (op->nd_opt_len << 3)); 536b0453382SBill Fenner break; 537b0453382SBill Fenner default: 538b0453382SBill Fenner opts_len = op->nd_opt_len; 539b0453382SBill Fenner printf("(unknwon opt_type=%d, opt_len=%d)", 540b0453382SBill Fenner op->nd_opt_type, opts_len); 541b0453382SBill Fenner if (opts_len == 0) 542b0453382SBill Fenner opts_len = 1; /* XXX */ 543b0453382SBill Fenner icmp6_opt_print((const u_char *)op + (opts_len << 3), 544b0453382SBill Fenner resid - (opts_len << 3)); 545b0453382SBill Fenner break; 546b0453382SBill Fenner } 547b0453382SBill Fenner return; 548b0453382SBill Fenner trunc: 549b0453382SBill Fenner fputs("[ndp opt]", stdout); 550b0453382SBill Fenner return; 551b0453382SBill Fenner #if 0 552b0453382SBill Fenner #undef TCHECK 553b0453382SBill Fenner #endif 554b0453382SBill Fenner #undef ECHECK 555b0453382SBill Fenner } 556b0453382SBill Fenner 557b0453382SBill Fenner void 558b0453382SBill Fenner mld6_print(register const u_char *bp) 559b0453382SBill Fenner { 560b0453382SBill Fenner register struct mld6_hdr *mp = (struct mld6_hdr *)bp; 561b0453382SBill Fenner register const u_char *ep; 562b0453382SBill Fenner 563b0453382SBill Fenner /* 'ep' points to the end of avaible data. */ 564b0453382SBill Fenner ep = snapend; 565b0453382SBill Fenner 566b0453382SBill Fenner if ((u_char *)mp + sizeof(*mp) > ep) 567b0453382SBill Fenner return; 568b0453382SBill Fenner 569b0453382SBill Fenner printf("max resp delay: %d ", ntohs(mp->mld6_maxdelay)); 570b0453382SBill Fenner printf("addr: %s", ip6addr_string(&mp->mld6_addr)); 571b0453382SBill Fenner 572b0453382SBill Fenner return; 573b0453382SBill Fenner } 574b0453382SBill Fenner #endif /* INET6 */ 575