print-icmp6.c revision 127668
156893Sfenner/* 256893Sfenner * Copyright (c) 1988, 1989, 1990, 1991, 1993, 1994 356893Sfenner * The Regents of the University of California. All rights reserved. 456893Sfenner * 556893Sfenner * Redistribution and use in source and binary forms, with or without 656893Sfenner * modification, are permitted provided that: (1) source code distributions 756893Sfenner * retain the above copyright notice and this paragraph in its entirety, (2) 856893Sfenner * distributions including binary code include the above copyright notice and 956893Sfenner * this paragraph in its entirety in the documentation or other materials 1056893Sfenner * provided with the distribution, and (3) all advertising materials mentioning 1156893Sfenner * features or use of this software display the following acknowledgement: 1256893Sfenner * ``This product includes software developed by the University of California, 1356893Sfenner * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 1456893Sfenner * the University nor the names of its contributors may be used to endorse 1556893Sfenner * or promote products derived from this software without specific prior 1656893Sfenner * written permission. 1756893Sfenner * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 1856893Sfenner * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 1956893Sfenner * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 2056893Sfenner */ 2156893Sfenner 2256893Sfenner#ifndef lint 23127668Sbmsstatic const char rcsid[] _U_ = 24127668Sbms "@(#) $Header: /tcpdump/master/tcpdump/print-icmp6.c,v 1.72.2.4 2004/03/24 00:14:09 guy Exp $"; 2556893Sfenner#endif 2656893Sfenner 2756893Sfenner#ifdef HAVE_CONFIG_H 2856893Sfenner#include "config.h" 2956893Sfenner#endif 3056893Sfenner 3156893Sfenner#ifdef INET6 3256893Sfenner 33127668Sbms#include <tcpdump-stdinc.h> 3456893Sfenner 3556893Sfenner#include <stdio.h> 3698524Sfenner#include <string.h> 3756893Sfenner 3875115Sfenner#include "ip6.h" 3975115Sfenner#include "icmp6.h" 40127668Sbms#include "ipproto.h" 4156893Sfenner 4256893Sfenner#include "interface.h" 4356893Sfenner#include "addrtoname.h" 44127668Sbms#include "extract.h" 4556893Sfenner 4675115Sfenner#include "udp.h" 4775115Sfenner#include "ah.h" 4875115Sfenner 4998524Sfennerstatic const char *get_rtpref(u_int); 5098524Sfennerstatic const char *get_lifetime(u_int32_t); 5198524Sfennerstatic void print_lladdr(const u_char *, size_t); 52127668Sbmsstatic void icmp6_opt_print(const u_char *, int); 53127668Sbmsstatic void mld6_print(const u_char *); 54127668Sbmsstatic struct udphdr *get_upperlayer(u_char *, u_int *); 5575115Sfennerstatic void dnsname_print(const u_char *, const u_char *); 56127668Sbmsstatic void icmp6_nodeinfo_print(u_int, const u_char *, const u_char *); 57127668Sbmsstatic void icmp6_rrenum_print(const u_char *, const u_char *); 5856893Sfenner 5975115Sfenner#ifndef abs 6075115Sfenner#define abs(a) ((0 < (a)) ? (a) : -(a)) 6175115Sfenner#endif 6275115Sfenner 6398524Sfennerstatic const char * 6498524Sfennerget_rtpref(u_int v) 6598524Sfenner{ 6698524Sfenner static const char *rtpref_str[] = { 6798524Sfenner "medium", /* 00 */ 6898524Sfenner "high", /* 01 */ 6998524Sfenner "rsv", /* 10 */ 7098524Sfenner "low" /* 11 */ 7198524Sfenner }; 7298524Sfenner 7398524Sfenner return rtpref_str[((v & ND_RA_FLAG_RTPREF_MASK) >> 3) & 0xff]; 7498524Sfenner} 7598524Sfenner 7698524Sfennerstatic const char * 7798524Sfennerget_lifetime(u_int32_t v) 7898524Sfenner{ 7998524Sfenner static char buf[20]; 8098524Sfenner 8198524Sfenner if (v == (u_int32_t)~0UL) 8298524Sfenner return "infinity"; 8398524Sfenner else { 8498524Sfenner snprintf(buf, sizeof(buf), "%u", v); 8598524Sfenner return buf; 8698524Sfenner } 8798524Sfenner} 8898524Sfenner 8998524Sfennerstatic void 9098524Sfennerprint_lladdr(const u_int8_t *p, size_t l) 9198524Sfenner{ 9298524Sfenner const u_int8_t *ep, *q; 9398524Sfenner 9498524Sfenner q = p; 9598524Sfenner ep = p + l; 9698524Sfenner while (l > 0 && q < ep) { 9798524Sfenner if (q > p) 9898524Sfenner printf(":"); 9998524Sfenner printf("%02x", *q++); 10098524Sfenner l--; 10198524Sfenner } 10298524Sfenner} 10398524Sfenner 104127668Sbmsstatic int icmp6_cksum(const struct ip6_hdr *ip6, const struct icmp6_hdr *icp, 105127668Sbms u_int len) 106127668Sbms{ 107127668Sbms size_t i; 108127668Sbms register const u_int16_t *sp; 109127668Sbms u_int32_t sum; 110127668Sbms union { 111127668Sbms struct { 112127668Sbms struct in6_addr ph_src; 113127668Sbms struct in6_addr ph_dst; 114127668Sbms u_int32_t ph_len; 115127668Sbms u_int8_t ph_zero[3]; 116127668Sbms u_int8_t ph_nxt; 117127668Sbms } ph; 118127668Sbms u_int16_t pa[20]; 119127668Sbms } phu; 120127668Sbms 121127668Sbms /* pseudo-header */ 122127668Sbms memset(&phu, 0, sizeof(phu)); 123127668Sbms phu.ph.ph_src = ip6->ip6_src; 124127668Sbms phu.ph.ph_dst = ip6->ip6_dst; 125127668Sbms phu.ph.ph_len = htonl(len); 126127668Sbms phu.ph.ph_nxt = IPPROTO_ICMPV6; 127127668Sbms 128127668Sbms sum = 0; 129127668Sbms for (i = 0; i < sizeof(phu.pa) / sizeof(phu.pa[0]); i++) 130127668Sbms sum += phu.pa[i]; 131127668Sbms 132127668Sbms sp = (const u_int16_t *)icp; 133127668Sbms 134127668Sbms for (i = 0; i < (len & ~1); i += 2) 135127668Sbms sum += *sp++; 136127668Sbms 137127668Sbms if (len & 1) 138127668Sbms sum += htons((*(const u_int8_t *)sp) << 8); 139127668Sbms 140127668Sbms while (sum > 0xffff) 141127668Sbms sum = (sum & 0xffff) + (sum >> 16); 142127668Sbms sum = ~sum & 0xffff; 143127668Sbms 144127668Sbms return (sum); 145127668Sbms} 146127668Sbms 14756893Sfennervoid 148127668Sbmsicmp6_print(const u_char *bp, u_int length, const u_char *bp2, int fragmented) 14956893Sfenner{ 15075115Sfenner const struct icmp6_hdr *dp; 15198524Sfenner const struct ip6_hdr *ip; 15298524Sfenner const char *str; 15398524Sfenner const struct ip6_hdr *oip; 15498524Sfenner const struct udphdr *ouh; 15598524Sfenner int dport; 15698524Sfenner const u_char *ep; 15756893Sfenner char buf[256]; 158127668Sbms u_int prot; 15956893Sfenner 16056893Sfenner dp = (struct icmp6_hdr *)bp; 16156893Sfenner ip = (struct ip6_hdr *)bp2; 16256893Sfenner oip = (struct ip6_hdr *)(dp + 1); 16356893Sfenner str = buf; 16475115Sfenner /* 'ep' points to the end of available data. */ 16556893Sfenner ep = snapend; 16656893Sfenner 167127668Sbms TCHECK(dp->icmp6_cksum); 168127668Sbms 169127668Sbms if (vflag && !fragmented) { 170127668Sbms int sum = dp->icmp6_cksum; 171127668Sbms 172127668Sbms if (TTEST2(bp[0], length)) { 173127668Sbms sum = icmp6_cksum(ip, dp, length); 174127668Sbms if (sum != 0) 175127668Sbms (void)printf("[bad icmp6 cksum %x!] ", sum); 176127668Sbms else 177127668Sbms (void)printf("[icmp6 sum ok] "); 178127668Sbms } 179127668Sbms } 180127668Sbms 18175115Sfenner switch (dp->icmp6_type) { 18256893Sfenner case ICMP6_DST_UNREACH: 18356893Sfenner TCHECK(oip->ip6_dst); 18456893Sfenner switch (dp->icmp6_code) { 18556893Sfenner case ICMP6_DST_UNREACH_NOROUTE: 18656893Sfenner printf("icmp6: %s unreachable route", 18756893Sfenner ip6addr_string(&oip->ip6_dst)); 18856893Sfenner break; 18956893Sfenner case ICMP6_DST_UNREACH_ADMIN: 19056893Sfenner printf("icmp6: %s unreachable prohibited", 19156893Sfenner ip6addr_string(&oip->ip6_dst)); 19256893Sfenner break; 19356893Sfenner case ICMP6_DST_UNREACH_BEYONDSCOPE: 19456893Sfenner printf("icmp6: %s beyond scope of source address %s", 19556893Sfenner ip6addr_string(&oip->ip6_dst), 19656893Sfenner ip6addr_string(&oip->ip6_src)); 19756893Sfenner break; 19856893Sfenner case ICMP6_DST_UNREACH_ADDR: 19956893Sfenner printf("icmp6: %s unreachable address", 20056893Sfenner ip6addr_string(&oip->ip6_dst)); 20156893Sfenner break; 20256893Sfenner case ICMP6_DST_UNREACH_NOPORT: 20375115Sfenner if ((ouh = get_upperlayer((u_char *)oip, &prot)) 20475115Sfenner == NULL) 20575115Sfenner goto trunc; 20675115Sfenner 207127668Sbms dport = EXTRACT_16BITS(&ouh->uh_dport); 20875115Sfenner switch (prot) { 20956893Sfenner case IPPROTO_TCP: 21056893Sfenner printf("icmp6: %s tcp port %s unreachable", 21156893Sfenner ip6addr_string(&oip->ip6_dst), 21256893Sfenner tcpport_string(dport)); 21356893Sfenner break; 21456893Sfenner case IPPROTO_UDP: 21556893Sfenner printf("icmp6: %s udp port %s unreachable", 21656893Sfenner ip6addr_string(&oip->ip6_dst), 21756893Sfenner udpport_string(dport)); 21856893Sfenner break; 21956893Sfenner default: 22056893Sfenner printf("icmp6: %s protocol %d port %d unreachable", 22156893Sfenner ip6addr_string(&oip->ip6_dst), 22256893Sfenner oip->ip6_nxt, dport); 22356893Sfenner break; 22456893Sfenner } 22556893Sfenner break; 22656893Sfenner default: 22756893Sfenner printf("icmp6: %s unreachable code-#%d", 22856893Sfenner ip6addr_string(&oip->ip6_dst), 22956893Sfenner dp->icmp6_code); 23056893Sfenner break; 23156893Sfenner } 23256893Sfenner break; 23356893Sfenner case ICMP6_PACKET_TOO_BIG: 23456893Sfenner TCHECK(dp->icmp6_mtu); 235127668Sbms printf("icmp6: too big %u", EXTRACT_32BITS(&dp->icmp6_mtu)); 23656893Sfenner break; 23756893Sfenner case ICMP6_TIME_EXCEEDED: 23856893Sfenner TCHECK(oip->ip6_dst); 23956893Sfenner switch (dp->icmp6_code) { 24056893Sfenner case ICMP6_TIME_EXCEED_TRANSIT: 24156893Sfenner printf("icmp6: time exceeded in-transit for %s", 24256893Sfenner ip6addr_string(&oip->ip6_dst)); 24356893Sfenner break; 24456893Sfenner case ICMP6_TIME_EXCEED_REASSEMBLY: 24556893Sfenner printf("icmp6: ip6 reassembly time exceeded"); 24656893Sfenner break; 24756893Sfenner default: 24856893Sfenner printf("icmp6: time exceeded code-#%d", 24956893Sfenner dp->icmp6_code); 25056893Sfenner break; 25156893Sfenner } 25256893Sfenner break; 25356893Sfenner case ICMP6_PARAM_PROB: 25456893Sfenner TCHECK(oip->ip6_dst); 25556893Sfenner switch (dp->icmp6_code) { 25656893Sfenner case ICMP6_PARAMPROB_HEADER: 25798524Sfenner printf("icmp6: parameter problem errorneous - octet %u", 258127668Sbms EXTRACT_32BITS(&dp->icmp6_pptr)); 25956893Sfenner break; 26056893Sfenner case ICMP6_PARAMPROB_NEXTHEADER: 26198524Sfenner printf("icmp6: parameter problem next header - octet %u", 262127668Sbms EXTRACT_32BITS(&dp->icmp6_pptr)); 26356893Sfenner break; 26456893Sfenner case ICMP6_PARAMPROB_OPTION: 26598524Sfenner printf("icmp6: parameter problem option - octet %u", 266127668Sbms EXTRACT_32BITS(&dp->icmp6_pptr)); 26756893Sfenner break; 26856893Sfenner default: 26956893Sfenner printf("icmp6: parameter problem code-#%d", 27056893Sfenner dp->icmp6_code); 27156893Sfenner break; 27256893Sfenner } 27356893Sfenner break; 27456893Sfenner case ICMP6_ECHO_REQUEST: 27556893Sfenner case ICMP6_ECHO_REPLY: 276127668Sbms TCHECK(dp->icmp6_seq); 277127668Sbms printf("icmp6: echo %s seq %u", 278127668Sbms dp->icmp6_type == ICMP6_ECHO_REQUEST ? 279127668Sbms "request" : "reply", 280127668Sbms EXTRACT_16BITS(&dp->icmp6_seq)); 28156893Sfenner break; 28256893Sfenner case ICMP6_MEMBERSHIP_QUERY: 28356893Sfenner printf("icmp6: multicast listener query "); 28456893Sfenner mld6_print((const u_char *)dp); 28556893Sfenner break; 28656893Sfenner case ICMP6_MEMBERSHIP_REPORT: 28756893Sfenner printf("icmp6: multicast listener report "); 28856893Sfenner mld6_print((const u_char *)dp); 28956893Sfenner break; 29056893Sfenner case ICMP6_MEMBERSHIP_REDUCTION: 29156893Sfenner printf("icmp6: multicast listener done "); 29256893Sfenner mld6_print((const u_char *)dp); 29356893Sfenner break; 29456893Sfenner case ND_ROUTER_SOLICIT: 29556893Sfenner printf("icmp6: router solicitation "); 29656893Sfenner if (vflag) { 29756893Sfenner#define RTSOLLEN 8 29875115Sfenner icmp6_opt_print((const u_char *)dp + RTSOLLEN, 299127668Sbms length - RTSOLLEN); 30056893Sfenner } 30156893Sfenner break; 30256893Sfenner case ND_ROUTER_ADVERT: 30356893Sfenner printf("icmp6: router advertisement"); 30456893Sfenner if (vflag) { 30556893Sfenner struct nd_router_advert *p; 30656893Sfenner 30756893Sfenner p = (struct nd_router_advert *)dp; 30856893Sfenner TCHECK(p->nd_ra_retransmit); 30956893Sfenner printf("(chlim=%d, ", (int)p->nd_ra_curhoplimit); 31056893Sfenner if (p->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED) 31156893Sfenner printf("M"); 31256893Sfenner if (p->nd_ra_flags_reserved & ND_RA_FLAG_OTHER) 31356893Sfenner printf("O"); 31498524Sfenner if (p->nd_ra_flags_reserved & ND_RA_FLAG_HOME_AGENT) 31575115Sfenner printf("H"); 31698524Sfenner 31798524Sfenner if ((p->nd_ra_flags_reserved & ~ND_RA_FLAG_RTPREF_MASK) 31898524Sfenner != 0) 31956893Sfenner printf(" "); 32098524Sfenner 32198524Sfenner printf("pref=%s, ", 32298524Sfenner get_rtpref(p->nd_ra_flags_reserved)); 32398524Sfenner 324127668Sbms printf("router_ltime=%d, ", EXTRACT_16BITS(&p->nd_ra_router_lifetime)); 32556893Sfenner printf("reachable_time=%u, ", 326127668Sbms EXTRACT_32BITS(&p->nd_ra_reachable)); 32756893Sfenner printf("retrans_time=%u)", 328127668Sbms EXTRACT_32BITS(&p->nd_ra_retransmit)); 32956893Sfenner#define RTADVLEN 16 33075115Sfenner icmp6_opt_print((const u_char *)dp + RTADVLEN, 331127668Sbms length - RTADVLEN); 33256893Sfenner } 33356893Sfenner break; 33456893Sfenner case ND_NEIGHBOR_SOLICIT: 33556893Sfenner { 33656893Sfenner struct nd_neighbor_solicit *p; 33756893Sfenner p = (struct nd_neighbor_solicit *)dp; 33856893Sfenner TCHECK(p->nd_ns_target); 33956893Sfenner printf("icmp6: neighbor sol: who has %s", 34056893Sfenner ip6addr_string(&p->nd_ns_target)); 34156893Sfenner if (vflag) { 34256893Sfenner#define NDSOLLEN 24 34375115Sfenner icmp6_opt_print((const u_char *)dp + NDSOLLEN, 344127668Sbms length - NDSOLLEN); 34556893Sfenner } 34656893Sfenner } 34756893Sfenner break; 34856893Sfenner case ND_NEIGHBOR_ADVERT: 34956893Sfenner { 35056893Sfenner struct nd_neighbor_advert *p; 35156893Sfenner 35256893Sfenner p = (struct nd_neighbor_advert *)dp; 35356893Sfenner TCHECK(p->nd_na_target); 35456893Sfenner printf("icmp6: neighbor adv: tgt is %s", 35556893Sfenner ip6addr_string(&p->nd_na_target)); 35675115Sfenner if (vflag) { 35756893Sfenner#define ND_NA_FLAG_ALL \ 35856893Sfenner (ND_NA_FLAG_ROUTER|ND_NA_FLAG_SOLICITED|ND_NA_FLAG_OVERRIDE) 35956893Sfenner /* we don't need ntohl() here. see advanced-api-04. */ 36056893Sfenner if (p->nd_na_flags_reserved & ND_NA_FLAG_ALL) { 36156893Sfenner#undef ND_NA_FLAG_ALL 36256893Sfenner u_int32_t flags; 36356893Sfenner 36456893Sfenner flags = p->nd_na_flags_reserved; 36556893Sfenner printf("("); 36656893Sfenner if (flags & ND_NA_FLAG_ROUTER) 36756893Sfenner printf("R"); 36856893Sfenner if (flags & ND_NA_FLAG_SOLICITED) 36956893Sfenner printf("S"); 37056893Sfenner if (flags & ND_NA_FLAG_OVERRIDE) 37156893Sfenner printf("O"); 37256893Sfenner printf(")"); 37356893Sfenner } 37456893Sfenner#define NDADVLEN 24 37575115Sfenner icmp6_opt_print((const u_char *)dp + NDADVLEN, 376127668Sbms length - NDADVLEN); 37775115Sfenner#undef NDADVLEN 37856893Sfenner } 37956893Sfenner } 38056893Sfenner break; 38156893Sfenner case ND_REDIRECT: 38256893Sfenner#define RDR(i) ((struct nd_redirect *)(i)) 38356893Sfenner TCHECK(RDR(dp)->nd_rd_dst); 38475115Sfenner printf("icmp6: redirect %s", 38575115Sfenner getname6((const u_char *)&RDR(dp)->nd_rd_dst)); 386127668Sbms TCHECK(RDR(dp)->nd_rd_target); 38775115Sfenner printf(" to %s", 38875115Sfenner getname6((const u_char*)&RDR(dp)->nd_rd_target)); 38956893Sfenner#define REDIRECTLEN 40 39056893Sfenner if (vflag) { 39156893Sfenner icmp6_opt_print((const u_char *)dp + REDIRECTLEN, 392127668Sbms length - REDIRECTLEN); 39356893Sfenner } 39456893Sfenner break; 39575115Sfenner#undef REDIRECTLEN 39675115Sfenner#undef RDR 39756893Sfenner case ICMP6_ROUTER_RENUMBERING: 398127668Sbms icmp6_rrenum_print(bp, ep); 39956893Sfenner break; 40075115Sfenner case ICMP6_NI_QUERY: 40175115Sfenner case ICMP6_NI_REPLY: 402127668Sbms icmp6_nodeinfo_print(length, bp, ep); 40356893Sfenner break; 404127668Sbms case ICMP6_HADISCOV_REQUEST: 405127668Sbms printf("icmp6: ha discovery request"); 406127668Sbms if (vflag) { 407127668Sbms TCHECK(dp->icmp6_data16[0]); 408127668Sbms printf("(id=%d)", EXTRACT_16BITS(&dp->icmp6_data16[0])); 409127668Sbms } 410127668Sbms break; 411127668Sbms case ICMP6_HADISCOV_REPLY: 412127668Sbms printf("icmp6: ha discovery reply"); 413127668Sbms if (vflag) { 414127668Sbms struct in6_addr *in6; 415127668Sbms u_char *cp; 416127668Sbms 417127668Sbms TCHECK(dp->icmp6_data16[0]); 418127668Sbms printf("(id=%d", EXTRACT_16BITS(&dp->icmp6_data16[0])); 419127668Sbms cp = (u_char *)dp + length; 420127668Sbms in6 = (struct in6_addr *)(dp + 1); 421127668Sbms for (; (u_char *)in6 < cp; in6++) { 422127668Sbms TCHECK(*in6); 423127668Sbms printf(", %s", ip6addr_string(in6)); 424127668Sbms } 425127668Sbms printf(")"); 426127668Sbms } 427127668Sbms break; 428127668Sbms case ICMP6_MOBILEPREFIX_SOLICIT: 429127668Sbms printf("icmp6: mobile router solicitation"); 430127668Sbms if (vflag) { 431127668Sbms TCHECK(dp->icmp6_data16[0]); 432127668Sbms printf("(id=%d)", EXTRACT_16BITS(&dp->icmp6_data16[0])); 433127668Sbms } 434127668Sbms break; 435127668Sbms case ICMP6_MOBILEPREFIX_ADVERT: 436127668Sbms printf("icmp6: mobile router advertisement"); 437127668Sbms if (vflag) { 438127668Sbms TCHECK(dp->icmp6_data16[0]); 439127668Sbms printf("(id=%d", EXTRACT_16BITS(&dp->icmp6_data16[0])); 440127668Sbms if (dp->icmp6_data16[1] & 0xc0) 441127668Sbms printf(" "); 442127668Sbms if (dp->icmp6_data16[1] & 0x80) 443127668Sbms printf("M"); 444127668Sbms if (dp->icmp6_data16[1] & 0x40) 445127668Sbms printf("O"); 446127668Sbms printf(")"); 447127668Sbms#define MPADVLEN 8 448127668Sbms icmp6_opt_print((const u_char *)dp + MPADVLEN, 449127668Sbms length - MPADVLEN); 450127668Sbms } 451127668Sbms break; 45256893Sfenner default: 45356893Sfenner printf("icmp6: type-#%d", dp->icmp6_type); 45456893Sfenner break; 45556893Sfenner } 45656893Sfenner return; 45756893Sfennertrunc: 45856893Sfenner fputs("[|icmp6]", stdout); 45956893Sfenner} 46056893Sfenner 46175115Sfennerstatic struct udphdr * 462127668Sbmsget_upperlayer(u_char *bp, u_int *prot) 46375115Sfenner{ 46498524Sfenner const u_char *ep; 46575115Sfenner struct ip6_hdr *ip6 = (struct ip6_hdr *)bp; 46675115Sfenner struct udphdr *uh; 46775115Sfenner struct ip6_hbh *hbh; 46875115Sfenner struct ip6_frag *fragh; 46975115Sfenner struct ah *ah; 470127668Sbms u_int nh; 471127668Sbms int hlen; 47275115Sfenner 47375115Sfenner /* 'ep' points to the end of available data. */ 47475115Sfenner ep = snapend; 47575115Sfenner 476127668Sbms if (!TTEST(ip6->ip6_nxt)) 47775115Sfenner return NULL; 47875115Sfenner 47975115Sfenner nh = ip6->ip6_nxt; 48075115Sfenner hlen = sizeof(struct ip6_hdr); 48175115Sfenner 48275115Sfenner while (bp < snapend) { 48375115Sfenner bp += hlen; 48475115Sfenner 48575115Sfenner switch(nh) { 48675115Sfenner case IPPROTO_UDP: 48775115Sfenner case IPPROTO_TCP: 48875115Sfenner uh = (struct udphdr *)bp; 48975115Sfenner if (TTEST(uh->uh_dport)) { 49075115Sfenner *prot = nh; 49175115Sfenner return(uh); 49275115Sfenner } 49375115Sfenner else 49475115Sfenner return(NULL); 49575115Sfenner /* NOTREACHED */ 49675115Sfenner 49775115Sfenner case IPPROTO_HOPOPTS: 49875115Sfenner case IPPROTO_DSTOPTS: 49975115Sfenner case IPPROTO_ROUTING: 50075115Sfenner hbh = (struct ip6_hbh *)bp; 501127668Sbms if (!TTEST(hbh->ip6h_len)) 50275115Sfenner return(NULL); 50375115Sfenner nh = hbh->ip6h_nxt; 50475115Sfenner hlen = (hbh->ip6h_len + 1) << 3; 50575115Sfenner break; 50675115Sfenner 50775115Sfenner case IPPROTO_FRAGMENT: /* this should be odd, but try anyway */ 50875115Sfenner fragh = (struct ip6_frag *)bp; 509127668Sbms if (!TTEST(fragh->ip6f_offlg)) 51075115Sfenner return(NULL); 51175115Sfenner /* fragments with non-zero offset are meaningless */ 512127668Sbms if ((EXTRACT_16BITS(&fragh->ip6f_offlg) & IP6F_OFF_MASK) != 0) 51375115Sfenner return(NULL); 51475115Sfenner nh = fragh->ip6f_nxt; 51575115Sfenner hlen = sizeof(struct ip6_frag); 51675115Sfenner break; 51775115Sfenner 51875115Sfenner case IPPROTO_AH: 51975115Sfenner ah = (struct ah *)bp; 520127668Sbms if (!TTEST(ah->ah_len)) 52175115Sfenner return(NULL); 52275115Sfenner nh = ah->ah_nxt; 52375115Sfenner hlen = (ah->ah_len + 2) << 2; 52475115Sfenner break; 52575115Sfenner 52675115Sfenner default: /* unknown or undecodable header */ 52775115Sfenner *prot = nh; /* meaningless, but set here anyway */ 52875115Sfenner return(NULL); 52975115Sfenner } 53075115Sfenner } 53175115Sfenner 53275115Sfenner return(NULL); /* should be notreached, though */ 53375115Sfenner} 53475115Sfenner 535127668Sbmsstatic void 53698524Sfennericmp6_opt_print(const u_char *bp, int resid) 53756893Sfenner{ 53898524Sfenner const struct nd_opt_hdr *op; 53998524Sfenner const struct nd_opt_hdr *opl; /* why there's no struct? */ 54098524Sfenner const struct nd_opt_prefix_info *opp; 54198524Sfenner const struct icmp6_opts_redirect *opr; 54298524Sfenner const struct nd_opt_mtu *opm; 54398524Sfenner const struct nd_opt_advinterval *opa; 544127668Sbms const struct nd_opt_homeagent_info *oph; 54598524Sfenner const struct nd_opt_route_info *opri; 54698524Sfenner const u_char *cp, *ep; 54798524Sfenner struct in6_addr in6, *in6p; 54898524Sfenner size_t l; 54956893Sfenner 55056893Sfenner#define ECHECK(var) if ((u_char *)&(var) > ep - sizeof(var)) return 55156893Sfenner 55298524Sfenner cp = bp; 55375115Sfenner /* 'ep' points to the end of available data. */ 55456893Sfenner ep = snapend; 55556893Sfenner 55698524Sfenner while (cp < ep) { 55798524Sfenner op = (struct nd_opt_hdr *)cp; 55898524Sfenner 55998524Sfenner ECHECK(op->nd_opt_len); 56098524Sfenner if (resid <= 0) 56198524Sfenner return; 56298524Sfenner if (op->nd_opt_len == 0) 56356893Sfenner goto trunc; 56498524Sfenner if (cp + (op->nd_opt_len << 3) > ep) 56556893Sfenner goto trunc; 56698524Sfenner 56798524Sfenner switch (op->nd_opt_type) { 56898524Sfenner case ND_OPT_SOURCE_LINKADDR: 56998524Sfenner opl = (struct nd_opt_hdr *)op; 57098524Sfenner printf("(src lladdr: "); 57198524Sfenner l = (op->nd_opt_len << 3) - 2; 57298524Sfenner print_lladdr(cp + 2, l); 57398524Sfenner /*(*/ 57498524Sfenner printf(")"); 57598524Sfenner break; 57698524Sfenner case ND_OPT_TARGET_LINKADDR: 57798524Sfenner opl = (struct nd_opt_hdr *)op; 57898524Sfenner printf("(tgt lladdr: "); 57998524Sfenner l = (op->nd_opt_len << 3) - 2; 58098524Sfenner print_lladdr(cp + 2, l); 58198524Sfenner /*(*/ 58298524Sfenner printf(")"); 58398524Sfenner break; 58498524Sfenner case ND_OPT_PREFIX_INFORMATION: 58598524Sfenner opp = (struct nd_opt_prefix_info *)op; 58698524Sfenner TCHECK(opp->nd_opt_pi_prefix); 58798524Sfenner printf("(prefix info: "); /*)*/ 58898524Sfenner if (op->nd_opt_len != 4) { 58998524Sfenner printf("badlen"); 59098524Sfenner /*(*/ 59198524Sfenner printf(")"); 59298524Sfenner break; 59398524Sfenner } 59498524Sfenner if (opp->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_ONLINK) 59598524Sfenner printf("L"); 59698524Sfenner if (opp->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_AUTO) 59798524Sfenner printf("A"); 59898524Sfenner if (opp->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_ROUTER) 59998524Sfenner printf("R"); 60098524Sfenner if (opp->nd_opt_pi_flags_reserved) 60198524Sfenner printf(" "); 60298524Sfenner printf("valid_ltime=%s,", 603127668Sbms get_lifetime(EXTRACT_32BITS(&opp->nd_opt_pi_valid_time))); 60498524Sfenner printf("preferred_ltime=%s,", 605127668Sbms get_lifetime(EXTRACT_32BITS(&opp->nd_opt_pi_preferred_time))); 60698524Sfenner printf("prefix=%s/%d", 60798524Sfenner ip6addr_string(&opp->nd_opt_pi_prefix), 60898524Sfenner opp->nd_opt_pi_prefix_len); 60998524Sfenner if (opp->nd_opt_pi_len != 4) 61098524Sfenner printf("!"); 61198524Sfenner /*(*/ 61298524Sfenner printf(")"); 61398524Sfenner break; 61498524Sfenner case ND_OPT_REDIRECTED_HEADER: 61598524Sfenner opr = (struct icmp6_opts_redirect *)op; 61698524Sfenner printf("(redirect)"); 61798524Sfenner /* xxx */ 61898524Sfenner break; 61998524Sfenner case ND_OPT_MTU: 62098524Sfenner opm = (struct nd_opt_mtu *)op; 62198524Sfenner TCHECK(opm->nd_opt_mtu_mtu); 62298524Sfenner printf("(mtu:"); /*)*/ 62398524Sfenner if (op->nd_opt_len != 1) { 62498524Sfenner printf("badlen"); 62598524Sfenner /*(*/ 62698524Sfenner printf(")"); 62798524Sfenner break; 62898524Sfenner } 629127668Sbms printf(" mtu=%u", EXTRACT_32BITS(&opm->nd_opt_mtu_mtu)); 63098524Sfenner if (opm->nd_opt_mtu_len != 1) 63198524Sfenner printf("!"); 63298524Sfenner printf(")"); 63398524Sfenner break; 63498524Sfenner case ND_OPT_ADVINTERVAL: 63598524Sfenner opa = (struct nd_opt_advinterval *)op; 63698524Sfenner TCHECK(opa->nd_opt_adv_interval); 63798524Sfenner printf("(advint:"); /*)*/ 63898524Sfenner printf(" advint=%u", 639127668Sbms EXTRACT_32BITS(&opa->nd_opt_adv_interval)); 64098524Sfenner /*(*/ 64198524Sfenner printf(")"); 642127668Sbms break; 643127668Sbms case ND_OPT_HOMEAGENT_INFO: 644127668Sbms oph = (struct nd_opt_homeagent_info *)op; 645127668Sbms TCHECK(oph->nd_opt_hai_lifetime); 646127668Sbms printf("(ha info:"); /*)*/ 647127668Sbms printf(" pref=%d", EXTRACT_16BITS(&oph->nd_opt_hai_preference)); 648127668Sbms printf(", lifetime=%u", EXTRACT_16BITS(&oph->nd_opt_hai_lifetime)); 649127668Sbms printf(")"); 650127668Sbms break; 65198524Sfenner case ND_OPT_ROUTE_INFO: 65298524Sfenner opri = (struct nd_opt_route_info *)op; 65398524Sfenner TCHECK(opri->nd_opt_rti_lifetime); 65498524Sfenner memset(&in6, 0, sizeof(in6)); 65598524Sfenner in6p = (struct in6_addr *)(opri + 1); 65698524Sfenner switch (op->nd_opt_len) { 65798524Sfenner case 1: 65898524Sfenner break; 65998524Sfenner case 2: 66098524Sfenner TCHECK2(*in6p, 8); 66198524Sfenner memcpy(&in6, opri + 1, 8); 66298524Sfenner break; 66398524Sfenner case 3: 66498524Sfenner TCHECK(*in6p); 66598524Sfenner memcpy(&in6, opri + 1, sizeof(in6)); 66698524Sfenner break; 66798524Sfenner default: 66898524Sfenner goto trunc; 66998524Sfenner } 67098524Sfenner printf("(rtinfo:"); /*)*/ 67198524Sfenner printf(" %s/%u", ip6addr_string(&in6), 67298524Sfenner opri->nd_opt_rti_prefixlen); 67398524Sfenner printf(", pref=%s", get_rtpref(opri->nd_opt_rti_flags)); 67498524Sfenner printf(", lifetime=%s", 675127668Sbms get_lifetime(EXTRACT_32BITS(&opri->nd_opt_rti_lifetime))); 67698524Sfenner /*(*/ 67798524Sfenner printf(")"); 67898524Sfenner break; 67998524Sfenner default: 680111726Sfenner printf("(unknown opt_type=%d, opt_len=%d)", 68198524Sfenner op->nd_opt_type, op->nd_opt_len); 68298524Sfenner break; 68356893Sfenner } 68498524Sfenner 68598524Sfenner cp += op->nd_opt_len << 3; 68698524Sfenner resid -= op->nd_opt_len << 3; 68756893Sfenner } 68856893Sfenner return; 68998524Sfenner 69056893Sfenner trunc: 69156893Sfenner fputs("[ndp opt]", stdout); 69256893Sfenner return; 69356893Sfenner#undef ECHECK 69456893Sfenner} 69556893Sfenner 696127668Sbmsstatic void 69798524Sfennermld6_print(const u_char *bp) 69856893Sfenner{ 69998524Sfenner struct mld6_hdr *mp = (struct mld6_hdr *)bp; 70098524Sfenner const u_char *ep; 70156893Sfenner 70275115Sfenner /* 'ep' points to the end of available data. */ 70356893Sfenner ep = snapend; 70456893Sfenner 70556893Sfenner if ((u_char *)mp + sizeof(*mp) > ep) 70656893Sfenner return; 70756893Sfenner 708127668Sbms printf("max resp delay: %d ", EXTRACT_16BITS(&mp->mld6_maxdelay)); 70956893Sfenner printf("addr: %s", ip6addr_string(&mp->mld6_addr)); 71075115Sfenner} 71156893Sfenner 71275115Sfennerstatic void 71375115Sfennerdnsname_print(const u_char *cp, const u_char *ep) 71475115Sfenner{ 71575115Sfenner int i; 71675115Sfenner 71775115Sfenner /* DNS name decoding - no decompression */ 71875115Sfenner printf(", \""); 71975115Sfenner while (cp < ep) { 72075115Sfenner i = *cp++; 72175115Sfenner if (i) { 72275115Sfenner if (i > ep - cp) { 72375115Sfenner printf("???"); 72475115Sfenner break; 72575115Sfenner } 72675115Sfenner while (i-- && cp < ep) { 72775115Sfenner safeputchar(*cp); 72875115Sfenner cp++; 72975115Sfenner } 73075115Sfenner if (cp + 1 < ep && *cp) 73175115Sfenner printf("."); 73275115Sfenner } else { 73375115Sfenner if (cp == ep) { 73475115Sfenner /* FQDN */ 73575115Sfenner printf("."); 73675115Sfenner } else if (cp + 1 == ep && *cp == '\0') { 73775115Sfenner /* truncated */ 73875115Sfenner } else { 73975115Sfenner /* invalid */ 74075115Sfenner printf("???"); 74175115Sfenner } 74275115Sfenner break; 74375115Sfenner } 74475115Sfenner } 74575115Sfenner printf("\""); 74675115Sfenner} 74775115Sfenner 748127668Sbmsstatic void 749127668Sbmsicmp6_nodeinfo_print(u_int icmp6len, const u_char *bp, const u_char *ep) 75075115Sfenner{ 75175115Sfenner struct icmp6_nodeinfo *ni6; 75275115Sfenner struct icmp6_hdr *dp; 75375115Sfenner const u_char *cp; 754127668Sbms size_t siz, i; 75575115Sfenner int needcomma; 75675115Sfenner 757127668Sbms if (ep < bp) 758127668Sbms return; 75975115Sfenner dp = (struct icmp6_hdr *)bp; 76075115Sfenner ni6 = (struct icmp6_nodeinfo *)bp; 76175115Sfenner siz = ep - bp; 76275115Sfenner 76375115Sfenner switch (ni6->ni_type) { 76475115Sfenner case ICMP6_NI_QUERY: 76575115Sfenner if (siz == sizeof(*dp) + 4) { 76675115Sfenner /* KAME who-are-you */ 76775115Sfenner printf("icmp6: who-are-you request"); 76875115Sfenner break; 76975115Sfenner } 77075115Sfenner printf("icmp6: node information query"); 77175115Sfenner 77275115Sfenner TCHECK2(*dp, sizeof(*ni6)); 77375115Sfenner ni6 = (struct icmp6_nodeinfo *)dp; 77475115Sfenner printf(" ("); /*)*/ 775127668Sbms switch (EXTRACT_16BITS(&ni6->ni_qtype)) { 77675115Sfenner case NI_QTYPE_NOOP: 77775115Sfenner printf("noop"); 77875115Sfenner break; 77975115Sfenner case NI_QTYPE_SUPTYPES: 78075115Sfenner printf("supported qtypes"); 781127668Sbms i = EXTRACT_16BITS(&ni6->ni_flags); 78275115Sfenner if (i) 78375115Sfenner printf(" [%s]", (i & 0x01) ? "C" : ""); 78475115Sfenner break; 78575115Sfenner break; 78675115Sfenner case NI_QTYPE_FQDN: 78775115Sfenner printf("DNS name"); 78875115Sfenner break; 78975115Sfenner case NI_QTYPE_NODEADDR: 79075115Sfenner printf("node addresses"); 79175115Sfenner i = ni6->ni_flags; 79275115Sfenner if (!i) 79375115Sfenner break; 79475115Sfenner /* NI_NODEADDR_FLAG_TRUNCATE undefined for query */ 79575115Sfenner printf(" [%s%s%s%s%s%s]", 79675115Sfenner (i & NI_NODEADDR_FLAG_ANYCAST) ? "a" : "", 79775115Sfenner (i & NI_NODEADDR_FLAG_GLOBAL) ? "G" : "", 79875115Sfenner (i & NI_NODEADDR_FLAG_SITELOCAL) ? "S" : "", 79975115Sfenner (i & NI_NODEADDR_FLAG_LINKLOCAL) ? "L" : "", 80075115Sfenner (i & NI_NODEADDR_FLAG_COMPAT) ? "C" : "", 80175115Sfenner (i & NI_NODEADDR_FLAG_ALL) ? "A" : ""); 80275115Sfenner break; 80375115Sfenner default: 80475115Sfenner printf("unknown"); 80575115Sfenner break; 80675115Sfenner } 80775115Sfenner 80875115Sfenner if (ni6->ni_qtype == NI_QTYPE_NOOP || 80975115Sfenner ni6->ni_qtype == NI_QTYPE_SUPTYPES) { 81075115Sfenner if (siz != sizeof(*ni6)) 81175115Sfenner if (vflag) 81275115Sfenner printf(", invalid len"); 81375115Sfenner /*(*/ 81475115Sfenner printf(")"); 81575115Sfenner break; 81675115Sfenner } 81775115Sfenner 81875115Sfenner 81975115Sfenner /* XXX backward compat, icmp-name-lookup-03 */ 82075115Sfenner if (siz == sizeof(*ni6)) { 82175115Sfenner printf(", 03 draft"); 82275115Sfenner /*(*/ 82375115Sfenner printf(")"); 82475115Sfenner break; 82575115Sfenner } 82675115Sfenner 82775115Sfenner switch (ni6->ni_code) { 82875115Sfenner case ICMP6_NI_SUBJ_IPV6: 82975115Sfenner if (!TTEST2(*dp, 83075115Sfenner sizeof(*ni6) + sizeof(struct in6_addr))) 83175115Sfenner break; 83275115Sfenner if (siz != sizeof(*ni6) + sizeof(struct in6_addr)) { 83375115Sfenner if (vflag) 83475115Sfenner printf(", invalid subject len"); 83575115Sfenner break; 83675115Sfenner } 83775115Sfenner printf(", subject=%s", 83875115Sfenner getname6((const u_char *)(ni6 + 1))); 83975115Sfenner break; 84075115Sfenner case ICMP6_NI_SUBJ_FQDN: 84175115Sfenner printf(", subject=DNS name"); 84275115Sfenner cp = (const u_char *)(ni6 + 1); 84375115Sfenner if (cp[0] == ep - cp - 1) { 84475115Sfenner /* icmp-name-lookup-03, pascal string */ 84575115Sfenner if (vflag) 84675115Sfenner printf(", 03 draft"); 84775115Sfenner cp++; 84875115Sfenner printf(", \""); 84975115Sfenner while (cp < ep) { 85075115Sfenner safeputchar(*cp); 85175115Sfenner cp++; 85275115Sfenner } 85375115Sfenner printf("\""); 85475115Sfenner } else 85575115Sfenner dnsname_print(cp, ep); 85675115Sfenner break; 85775115Sfenner case ICMP6_NI_SUBJ_IPV4: 85875115Sfenner if (!TTEST2(*dp, sizeof(*ni6) + sizeof(struct in_addr))) 85975115Sfenner break; 86075115Sfenner if (siz != sizeof(*ni6) + sizeof(struct in_addr)) { 86175115Sfenner if (vflag) 86275115Sfenner printf(", invalid subject len"); 86375115Sfenner break; 86475115Sfenner } 86575115Sfenner printf(", subject=%s", 86675115Sfenner getname((const u_char *)(ni6 + 1))); 86775115Sfenner break; 86875115Sfenner default: 86975115Sfenner printf(", unknown subject"); 87075115Sfenner break; 87175115Sfenner } 87275115Sfenner 87375115Sfenner /*(*/ 87475115Sfenner printf(")"); 87575115Sfenner break; 87675115Sfenner 87775115Sfenner case ICMP6_NI_REPLY: 87875115Sfenner if (icmp6len > siz) { 87975115Sfenner printf("[|icmp6: node information reply]"); 88075115Sfenner break; 88175115Sfenner } 88275115Sfenner 88375115Sfenner needcomma = 0; 88475115Sfenner 88575115Sfenner ni6 = (struct icmp6_nodeinfo *)dp; 88675115Sfenner printf("icmp6: node information reply"); 88775115Sfenner printf(" ("); /*)*/ 88875115Sfenner switch (ni6->ni_code) { 88975115Sfenner case ICMP6_NI_SUCCESS: 89075115Sfenner if (vflag) { 89175115Sfenner printf("success"); 89275115Sfenner needcomma++; 89375115Sfenner } 89475115Sfenner break; 89575115Sfenner case ICMP6_NI_REFUSED: 89675115Sfenner printf("refused"); 89775115Sfenner needcomma++; 89875115Sfenner if (siz != sizeof(*ni6)) 89975115Sfenner if (vflag) 90075115Sfenner printf(", invalid length"); 90175115Sfenner break; 90275115Sfenner case ICMP6_NI_UNKNOWN: 90375115Sfenner printf("unknown"); 90475115Sfenner needcomma++; 90575115Sfenner if (siz != sizeof(*ni6)) 90675115Sfenner if (vflag) 90775115Sfenner printf(", invalid length"); 90875115Sfenner break; 90975115Sfenner } 91075115Sfenner 91175115Sfenner if (ni6->ni_code != ICMP6_NI_SUCCESS) { 91275115Sfenner /*(*/ 91375115Sfenner printf(")"); 91475115Sfenner break; 91575115Sfenner } 91675115Sfenner 917127668Sbms switch (EXTRACT_16BITS(&ni6->ni_qtype)) { 91875115Sfenner case NI_QTYPE_NOOP: 91975115Sfenner if (needcomma) 92075115Sfenner printf(", "); 92175115Sfenner printf("noop"); 92275115Sfenner if (siz != sizeof(*ni6)) 92375115Sfenner if (vflag) 92475115Sfenner printf(", invalid length"); 92575115Sfenner break; 92675115Sfenner case NI_QTYPE_SUPTYPES: 92775115Sfenner if (needcomma) 92875115Sfenner printf(", "); 92975115Sfenner printf("supported qtypes"); 930127668Sbms i = EXTRACT_16BITS(&ni6->ni_flags); 93175115Sfenner if (i) 93275115Sfenner printf(" [%s]", (i & 0x01) ? "C" : ""); 93375115Sfenner break; 93475115Sfenner case NI_QTYPE_FQDN: 93575115Sfenner if (needcomma) 93675115Sfenner printf(", "); 93775115Sfenner printf("DNS name"); 93875115Sfenner cp = (const u_char *)(ni6 + 1) + 4; 93975115Sfenner if (cp[0] == ep - cp - 1) { 94075115Sfenner /* icmp-name-lookup-03, pascal string */ 94175115Sfenner if (vflag) 94275115Sfenner printf(", 03 draft"); 94375115Sfenner cp++; 94475115Sfenner printf(", \""); 94575115Sfenner while (cp < ep) { 94675115Sfenner safeputchar(*cp); 94775115Sfenner cp++; 94875115Sfenner } 94975115Sfenner printf("\""); 95075115Sfenner } else 95175115Sfenner dnsname_print(cp, ep); 952127668Sbms if ((EXTRACT_16BITS(&ni6->ni_flags) & 0x01) != 0) 95375115Sfenner printf(" [TTL=%u]", *(u_int32_t *)(ni6 + 1)); 95475115Sfenner break; 95575115Sfenner case NI_QTYPE_NODEADDR: 95675115Sfenner if (needcomma) 95775115Sfenner printf(", "); 95875115Sfenner printf("node addresses"); 95975115Sfenner i = sizeof(*ni6); 96075115Sfenner while (i < siz) { 96175115Sfenner if (i + sizeof(struct in6_addr) + sizeof(int32_t) > siz) 96275115Sfenner break; 96375115Sfenner printf(" %s", getname6(bp + i)); 96475115Sfenner i += sizeof(struct in6_addr); 965127668Sbms printf("(%d)", (int32_t)EXTRACT_32BITS(bp + i)); 96675115Sfenner i += sizeof(int32_t); 96775115Sfenner } 96875115Sfenner i = ni6->ni_flags; 96975115Sfenner if (!i) 97075115Sfenner break; 97175115Sfenner printf(" [%s%s%s%s%s%s%s]", 97275115Sfenner (i & NI_NODEADDR_FLAG_ANYCAST) ? "a" : "", 97375115Sfenner (i & NI_NODEADDR_FLAG_GLOBAL) ? "G" : "", 97475115Sfenner (i & NI_NODEADDR_FLAG_SITELOCAL) ? "S" : "", 97575115Sfenner (i & NI_NODEADDR_FLAG_LINKLOCAL) ? "L" : "", 97675115Sfenner (i & NI_NODEADDR_FLAG_COMPAT) ? "C" : "", 97775115Sfenner (i & NI_NODEADDR_FLAG_ALL) ? "A" : "", 97875115Sfenner (i & NI_NODEADDR_FLAG_TRUNCATE) ? "T" : ""); 97975115Sfenner break; 98075115Sfenner default: 98175115Sfenner if (needcomma) 98275115Sfenner printf(", "); 98375115Sfenner printf("unknown"); 98475115Sfenner break; 98575115Sfenner } 98675115Sfenner 98775115Sfenner /*(*/ 98875115Sfenner printf(")"); 98975115Sfenner break; 99075115Sfenner } 99156893Sfenner return; 99275115Sfenner 99375115Sfennertrunc: 99475115Sfenner fputs("[|icmp6]", stdout); 99556893Sfenner} 99675115Sfenner 997127668Sbmsstatic void 998127668Sbmsicmp6_rrenum_print(const u_char *bp, const u_char *ep) 99975115Sfenner{ 100075115Sfenner struct icmp6_router_renum *rr6; 100175115Sfenner struct icmp6_hdr *dp; 100275115Sfenner size_t siz; 100375115Sfenner const char *cp; 100475115Sfenner struct rr_pco_match *match; 100575115Sfenner struct rr_pco_use *use; 100675115Sfenner char hbuf[NI_MAXHOST]; 100775115Sfenner int n; 100875115Sfenner 1009127668Sbms if (ep < bp) 1010127668Sbms return; 101175115Sfenner dp = (struct icmp6_hdr *)bp; 101275115Sfenner rr6 = (struct icmp6_router_renum *)bp; 101375115Sfenner siz = ep - bp; 101475115Sfenner cp = (const char *)(rr6 + 1); 101575115Sfenner 101675115Sfenner TCHECK(rr6->rr_reserved); 101775115Sfenner switch (rr6->rr_code) { 101875115Sfenner case ICMP6_ROUTER_RENUMBERING_COMMAND: 101975115Sfenner printf("router renum: command"); 102075115Sfenner break; 102175115Sfenner case ICMP6_ROUTER_RENUMBERING_RESULT: 102275115Sfenner printf("router renum: result"); 102375115Sfenner break; 102475115Sfenner case ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET: 102575115Sfenner printf("router renum: sequence number reset"); 102675115Sfenner break; 102775115Sfenner default: 102875115Sfenner printf("router renum: code-#%d", rr6->rr_code); 102975115Sfenner break; 103075115Sfenner } 103175115Sfenner 1032127668Sbms printf(", seq=%u", EXTRACT_32BITS(&rr6->rr_seqnum)); 103375115Sfenner 103475115Sfenner if (vflag) { 103575115Sfenner#define F(x, y) ((rr6->rr_flags) & (x) ? (y) : "") 103675115Sfenner printf("["); /*]*/ 103775115Sfenner if (rr6->rr_flags) { 103875115Sfenner printf("%s%s%s%s%s,", F(ICMP6_RR_FLAGS_TEST, "T"), 103975115Sfenner F(ICMP6_RR_FLAGS_REQRESULT, "R"), 104098524Sfenner F(ICMP6_RR_FLAGS_FORCEAPPLY, "A"), 104175115Sfenner F(ICMP6_RR_FLAGS_SPECSITE, "S"), 104275115Sfenner F(ICMP6_RR_FLAGS_PREVDONE, "P")); 104375115Sfenner } 104475115Sfenner printf("seg=%u,", rr6->rr_segnum); 104575115Sfenner printf("maxdelay=%u", rr6->rr_maxdelay); 104675115Sfenner if (rr6->rr_reserved) 1047127668Sbms printf("rsvd=0x%x", EXTRACT_16BITS(&rr6->rr_reserved)); 104875115Sfenner /*[*/ 104975115Sfenner printf("]"); 105075115Sfenner#undef F 105175115Sfenner } 105275115Sfenner 105375115Sfenner if (rr6->rr_code == ICMP6_ROUTER_RENUMBERING_COMMAND) { 105475115Sfenner match = (struct rr_pco_match *)cp; 105575115Sfenner cp = (const char *)(match + 1); 105675115Sfenner 105775115Sfenner TCHECK(match->rpm_prefix); 105875115Sfenner 105998524Sfenner if (vflag > 1) 106075115Sfenner printf("\n\t"); 106175115Sfenner else 106275115Sfenner printf(" "); 106375115Sfenner printf("match("); /*)*/ 106475115Sfenner switch (match->rpm_code) { 106575115Sfenner case RPM_PCO_ADD: printf("add"); break; 106675115Sfenner case RPM_PCO_CHANGE: printf("change"); break; 106775115Sfenner case RPM_PCO_SETGLOBAL: printf("setglobal"); break; 106875115Sfenner default: printf("#%u", match->rpm_code); break; 106975115Sfenner } 107075115Sfenner 107175115Sfenner if (vflag) { 107275115Sfenner printf(",ord=%u", match->rpm_ordinal); 107375115Sfenner printf(",min=%u", match->rpm_minlen); 107475115Sfenner printf(",max=%u", match->rpm_maxlen); 107575115Sfenner } 107675115Sfenner if (inet_ntop(AF_INET6, &match->rpm_prefix, hbuf, sizeof(hbuf))) 107775115Sfenner printf(",%s/%u", hbuf, match->rpm_matchlen); 107875115Sfenner else 107975115Sfenner printf(",?/%u", match->rpm_matchlen); 108075115Sfenner /*(*/ 108175115Sfenner printf(")"); 108275115Sfenner 108375115Sfenner n = match->rpm_len - 3; 108475115Sfenner if (n % 4) 108575115Sfenner goto trunc; 108675115Sfenner n /= 4; 108775115Sfenner while (n-- > 0) { 108875115Sfenner use = (struct rr_pco_use *)cp; 108975115Sfenner cp = (const char *)(use + 1); 109075115Sfenner 109175115Sfenner TCHECK(use->rpu_prefix); 109275115Sfenner 109398524Sfenner if (vflag > 1) 109475115Sfenner printf("\n\t"); 109575115Sfenner else 109675115Sfenner printf(" "); 109775115Sfenner printf("use("); /*)*/ 109875115Sfenner if (use->rpu_flags) { 109975115Sfenner#define F(x, y) ((use->rpu_flags) & (x) ? (y) : "") 110075115Sfenner printf("%s%s,", 110175115Sfenner F(ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME, "V"), 110275115Sfenner F(ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME, "P")); 110375115Sfenner#undef F 110475115Sfenner } 110575115Sfenner if (vflag) { 110675115Sfenner printf("mask=0x%x,", use->rpu_ramask); 110775115Sfenner printf("raflags=0x%x,", use->rpu_raflags); 110875115Sfenner if (~use->rpu_vltime == 0) 110975115Sfenner printf("vltime=infty,"); 111075115Sfenner else 111175115Sfenner printf("vltime=%u,", 1112127668Sbms EXTRACT_32BITS(&use->rpu_vltime)); 111375115Sfenner if (~use->rpu_pltime == 0) 111475115Sfenner printf("pltime=infty,"); 111575115Sfenner else 111675115Sfenner printf("pltime=%u,", 1117127668Sbms EXTRACT_32BITS(&use->rpu_pltime)); 111875115Sfenner } 111975115Sfenner if (inet_ntop(AF_INET6, &use->rpu_prefix, hbuf, 112075115Sfenner sizeof(hbuf))) 112175115Sfenner printf("%s/%u/%u", hbuf, use->rpu_uselen, 112275115Sfenner use->rpu_keeplen); 112375115Sfenner else 112475115Sfenner printf("?/%u/%u", use->rpu_uselen, 112575115Sfenner use->rpu_keeplen); 112675115Sfenner /*(*/ 112775115Sfenner printf(")"); 112875115Sfenner } 112975115Sfenner } 113075115Sfenner 113175115Sfenner return; 113275115Sfenner 113375115Sfennertrunc: 113475115Sfenner fputs("[|icmp6]", stdout); 113575115Sfenner} 113675115Sfenner 113756893Sfenner#endif /* INET6 */ 1138