static int reaper_rtcp_format(const struct ip *ip, int sport, int dport, const char* data, int len) { char hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; char *buffer = reaper_packet_buffer_rtcp; #ifdef INET6 if (IP_V(ip) == 6) { const struct ip6_hdr *ip6; ip6 = (const struct ip6_hdr *)ip; buffer += sprintf(reaper_packet_buffer_rtcp, FORMAT, reaper_source_mac, ip6addr_string(&ip6->ip6_src), udpport_string(sport), reaper_destination_mac, ip6addr_string(&ip6->ip6_dst), udpport_string(dport)); } else { #endif /*INET6*/ buffer += sprintf(reaper_packet_buffer_rtcp, FORMAT, reaper_source_mac, ipaddr_string(&ip->ip_src), udpport_string(sport), reaper_destination_mac, ipaddr_string(&ip->ip_dst), udpport_string(dport)); #ifdef INET6 } #endif /*INET6*/ fprintf(stderr, "Sending RTCP packet <%s>\n", reaper_packet_buffer_rtcp); char *end_buffer = reaper_packet_buffer_rtcp + sizeof(reaper_packet_buffer_rtcp) - 3; const char *end_data = data + len; while (data < end_data) { *(buffer++) = hex[((*data >> 4) & 0xF)]; *(buffer++) = hex[(*data & 0xF)]; if (buffer >= end_buffer) break; ++data; } *(buffer++) = '\n'; *(buffer) = '\0'; return (buffer - reaper_packet_buffer_rtcp); }
static int reaper_rtp_format(const struct ip *ip, int sport, int dport, const char* data, int len) { if (reaper_packet_pointer == NULL) reaper_packet_pointer = reaper_packet_buffer; char *buffer = reaper_packet_pointer; #ifdef INET6 if (IP_V(ip) == 6) { const struct ip6_hdr *ip6; ip6 = (const struct ip6_hdr *)ip; buffer += sprintf(buffer, FORMAT, reaper_source_mac, ip6addr_string(&ip6->ip6_src), udpport_string(sport), reaper_destination_mac, ip6addr_string(&ip6->ip6_dst), udpport_string(dport)); } else { #endif /*INET6*/ buffer += sprintf(buffer, FORMAT, reaper_source_mac, ipaddr_string(&ip->ip_src), udpport_string(sport), reaper_destination_mac, ipaddr_string(&ip->ip_dst), udpport_string(dport)); #ifdef INET6 } #endif /*INET6*/ short sequenceNumber = ((data[2] & 0xFF) << 8) | (data[3] & 0xFF); int timeStamp = ((data[4] & 0xFF) << 24) | ((data[5] & 0xFF) << 16) | ((data[6] & 0xFF) << 8) | (data[7] & 0xFF); buffer += sprintf(buffer, "%d;%d;%d", sequenceNumber, timeStamp, reaper_time_stamp()); *(buffer++) = '\n'; *(buffer) = '\0'; reaper_packet_pointer = buffer; return (buffer - reaper_packet_buffer); }
void icmp_print(const u_char *bp, u_int plen, const u_char *bp2, int fragmented) { char *cp; const struct icmp *dp; const struct icmp_ext_t *ext_dp; const struct ip *ip; const char *str, *fmt; const struct ip *oip; const struct udphdr *ouh; const u_int8_t *obj_tptr; u_int32_t raw_label; const u_char *snapend_save; const struct icmp_mpls_ext_object_header_t *icmp_mpls_ext_object_header; u_int hlen, dport, mtu, obj_tlen, obj_class_num, obj_ctype; char buf[MAXHOSTNAMELEN + 100]; dp = (struct icmp *)bp; ext_dp = (struct icmp_ext_t *)bp; ip = (struct ip *)bp2; str = buf; TCHECK(dp->icmp_code); switch (dp->icmp_type) { case ICMP_ECHO: case ICMP_ECHOREPLY: TCHECK(dp->icmp_seq); (void)snprintf(buf, sizeof(buf), "echo %s, id %u, seq %u", dp->icmp_type == ICMP_ECHO ? "request" : "reply", EXTRACT_16BITS(&dp->icmp_id), EXTRACT_16BITS(&dp->icmp_seq)); break; case ICMP_UNREACH: TCHECK(dp->icmp_ip.ip_dst); switch (dp->icmp_code) { case ICMP_UNREACH_PROTOCOL: TCHECK(dp->icmp_ip.ip_p); (void)snprintf(buf, sizeof(buf), "%s protocol %d unreachable", ipaddr_string(&dp->icmp_ip.ip_dst), dp->icmp_ip.ip_p); break; case ICMP_UNREACH_PORT: TCHECK(dp->icmp_ip.ip_p); oip = &dp->icmp_ip; hlen = IP_HL(oip) * 4; ouh = (struct udphdr *)(((u_char *)oip) + hlen); TCHECK(ouh->uh_dport); dport = EXTRACT_16BITS(&ouh->uh_dport); switch (oip->ip_p) { case IPPROTO_TCP: (void)snprintf(buf, sizeof(buf), "%s tcp port %s unreachable", ipaddr_string(&oip->ip_dst), tcpport_string(dport)); break; case IPPROTO_UDP: (void)snprintf(buf, sizeof(buf), "%s udp port %s unreachable", ipaddr_string(&oip->ip_dst), udpport_string(dport)); break; default: (void)snprintf(buf, sizeof(buf), "%s protocol %d port %d unreachable", ipaddr_string(&oip->ip_dst), oip->ip_p, dport); break; } break; case ICMP_UNREACH_NEEDFRAG: { register const struct mtu_discovery *mp; mp = (struct mtu_discovery *)(u_char *)&dp->icmp_void; mtu = EXTRACT_16BITS(&mp->nexthopmtu); if (mtu) { (void)snprintf(buf, sizeof(buf), "%s unreachable - need to frag (mtu %d)", ipaddr_string(&dp->icmp_ip.ip_dst), mtu); } else { (void)snprintf(buf, sizeof(buf), "%s unreachable - need to frag", ipaddr_string(&dp->icmp_ip.ip_dst)); } } break; default: fmt = tok2str(unreach2str, "#%d %%s unreachable", dp->icmp_code); (void)snprintf(buf, sizeof(buf), fmt, ipaddr_string(&dp->icmp_ip.ip_dst)); break; } break; case ICMP_REDIRECT: TCHECK(dp->icmp_ip.ip_dst); fmt = tok2str(type2str, "redirect-#%d %%s to net %%s", dp->icmp_code); (void)snprintf(buf, sizeof(buf), fmt, ipaddr_string(&dp->icmp_ip.ip_dst), ipaddr_string(&dp->icmp_gwaddr)); break; case ICMP_ROUTERADVERT: { register const struct ih_rdiscovery *ihp; register const struct id_rdiscovery *idp; u_int lifetime, num, size; (void)snprintf(buf, sizeof(buf), "router advertisement"); cp = buf + strlen(buf); ihp = (struct ih_rdiscovery *)&dp->icmp_void; TCHECK(*ihp); (void)strncpy(cp, " lifetime ", sizeof(buf) - (cp - buf)); cp = buf + strlen(buf); lifetime = EXTRACT_16BITS(&ihp->ird_lifetime); if (lifetime < 60) { (void)snprintf(cp, sizeof(buf) - (cp - buf), "%u", lifetime); } else if (lifetime < 60 * 60) { (void)snprintf(cp, sizeof(buf) - (cp - buf), "%u:%02u", lifetime / 60, lifetime % 60); } else { (void)snprintf(cp, sizeof(buf) - (cp - buf), "%u:%02u:%02u", lifetime / 3600, (lifetime % 3600) / 60, lifetime % 60); } cp = buf + strlen(buf); num = ihp->ird_addrnum; (void)snprintf(cp, sizeof(buf) - (cp - buf), " %d:", num); cp = buf + strlen(buf); size = ihp->ird_addrsiz; if (size != 2) { (void)snprintf(cp, sizeof(buf) - (cp - buf), " [size %d]", size); break; } idp = (struct id_rdiscovery *)&dp->icmp_data; while (num-- > 0) { TCHECK(*idp); (void)snprintf(cp, sizeof(buf) - (cp - buf), " {%s %u}", ipaddr_string(&idp->ird_addr), EXTRACT_32BITS(&idp->ird_pref)); cp = buf + strlen(buf); ++idp; } } break; case ICMP_TIMXCEED: TCHECK(dp->icmp_ip.ip_dst); switch (dp->icmp_code) { case ICMP_TIMXCEED_INTRANS: str = "time exceeded in-transit"; break; case ICMP_TIMXCEED_REASS: str = "ip reassembly time exceeded"; break; default: (void)snprintf(buf, sizeof(buf), "time exceeded-#%d", dp->icmp_code); break; } break; case ICMP_PARAMPROB: if (dp->icmp_code) (void)snprintf(buf, sizeof(buf), "parameter problem - code %d", dp->icmp_code); else { TCHECK(dp->icmp_pptr); (void)snprintf(buf, sizeof(buf), "parameter problem - octet %d", dp->icmp_pptr); } break; case ICMP_MASKREPLY: TCHECK(dp->icmp_mask); (void)snprintf(buf, sizeof(buf), "address mask is 0x%08x", EXTRACT_32BITS(&dp->icmp_mask)); break; case ICMP_TSTAMP: TCHECK(dp->icmp_seq); (void)snprintf(buf, sizeof(buf), "time stamp query id %u seq %u", EXTRACT_16BITS(&dp->icmp_id), EXTRACT_16BITS(&dp->icmp_seq)); break; case ICMP_TSTAMPREPLY: TCHECK(dp->icmp_ttime); (void)snprintf(buf, sizeof(buf), "time stamp reply id %u seq %u: org %s", EXTRACT_16BITS(&dp->icmp_id), EXTRACT_16BITS(&dp->icmp_seq), icmp_tstamp_print(EXTRACT_32BITS(&dp->icmp_otime))); (void)snprintf(buf+strlen(buf),sizeof(buf)-strlen(buf),", recv %s", icmp_tstamp_print(EXTRACT_32BITS(&dp->icmp_rtime))); (void)snprintf(buf+strlen(buf),sizeof(buf)-strlen(buf),", xmit %s", icmp_tstamp_print(EXTRACT_32BITS(&dp->icmp_ttime))); break; default: str = tok2str(icmp2str, "type-#%d", dp->icmp_type); break; } (void)printf("ICMP %s, length %u", str, plen); if (vflag && !fragmented) { /* don't attempt checksumming if this is a frag */ u_int16_t sum, icmp_sum; if (TTEST2(*bp, plen)) { sum = in_cksum((u_short*)dp, plen, 0); if (sum != 0) { icmp_sum = EXTRACT_16BITS(&dp->icmp_cksum); (void)printf(" (wrong icmp cksum %x (->%x)!)", icmp_sum, in_cksum_shouldbe(icmp_sum, sum)); } } } /* * print the remnants of the IP packet. * save the snaplength as this may get overidden in the IP printer. */ if (vflag >= 1 && !ICMP_INFOTYPE(dp->icmp_type)) { bp += 8; (void)printf("\n\t"); ip = (struct ip *)bp; snaplen = snapend - bp; snapend_save = snapend; ip_print(gndo, bp, EXTRACT_16BITS(&ip->ip_len)); snapend = snapend_save; } /* * Attempt to decode the MPLS extensions only for some ICMP types. */ if (vflag >= 1 && plen > ICMP_EXTD_MINLEN && ICMP_MPLS_EXT_TYPE(dp->icmp_type)) { TCHECK(*ext_dp); /* * Check first if the mpls extension header shows a non-zero length. * If the length field is not set then silently verify the checksum * to check if an extension header is present. This is expedient, * however not all implementations set the length field proper. */ if (!ext_dp->icmp_length && in_cksum((const u_short *)&ext_dp->icmp_ext_version_res, plen - ICMP_EXTD_MINLEN, 0)) { return; } printf("\n\tMPLS extension v%u", ICMP_MPLS_EXT_EXTRACT_VERSION(*(ext_dp->icmp_ext_version_res))); /* * Sanity checking of the header. */ if (ICMP_MPLS_EXT_EXTRACT_VERSION(*(ext_dp->icmp_ext_version_res)) != ICMP_MPLS_EXT_VERSION) { printf(" packet not supported"); return; } hlen = plen - ICMP_EXTD_MINLEN; printf(", checksum 0x%04x (%scorrect), length %u", EXTRACT_16BITS(ext_dp->icmp_ext_checksum), in_cksum((const u_short *)&ext_dp->icmp_ext_version_res, plen - ICMP_EXTD_MINLEN, 0) ? "in" : "", hlen); hlen -= 4; /* subtract common header size */ obj_tptr = (u_int8_t *)ext_dp->icmp_ext_data; while (hlen > sizeof(struct icmp_mpls_ext_object_header_t)) { icmp_mpls_ext_object_header = (struct icmp_mpls_ext_object_header_t *)obj_tptr; TCHECK(*icmp_mpls_ext_object_header); obj_tlen = EXTRACT_16BITS(icmp_mpls_ext_object_header->length); obj_class_num = icmp_mpls_ext_object_header->class_num; obj_ctype = icmp_mpls_ext_object_header->ctype; obj_tptr += sizeof(struct icmp_mpls_ext_object_header_t); printf("\n\t %s Object (%u), Class-Type: %u, length %u", tok2str(icmp_mpls_ext_obj_values,"unknown",obj_class_num), obj_class_num, obj_ctype, obj_tlen); hlen-=sizeof(struct icmp_mpls_ext_object_header_t); /* length field includes tlv header */ /* infinite loop protection */ if ((obj_class_num == 0) || (obj_tlen < sizeof(struct icmp_mpls_ext_object_header_t))) { return; } obj_tlen-=sizeof(struct icmp_mpls_ext_object_header_t); switch (obj_class_num) { case 1: switch(obj_ctype) { case 1: TCHECK2(*obj_tptr, 4); raw_label = EXTRACT_32BITS(obj_tptr); printf("\n\t label %u, exp %u", MPLS_LABEL(raw_label), MPLS_EXP(raw_label)); if (MPLS_STACK(raw_label)) printf(", [S]"); printf(", ttl %u", MPLS_TTL(raw_label)); break; default: print_unknown_data(obj_tptr, "\n\t ", obj_tlen); } break; /* * FIXME those are the defined objects that lack a decoder * you are welcome to contribute code ;-) */ case 2: default: print_unknown_data(obj_tptr, "\n\t ", obj_tlen); break; } if (hlen < obj_tlen) break; hlen -= obj_tlen; obj_tptr += obj_tlen; } } return; trunc: fputs("[|icmp]", stdout); }
void icmp6_print(const u_char *bp, u_int length, const u_char *bp2) { register const struct icmp6_hdr *dp; register const struct ip6_hdr *ip; register const char *str; register const struct ip6_hdr *oip; register const struct udphdr *ouh; register int hlen, dport; register const u_char *ep; char buf[256]; int icmp6len; #if 0 #define TCHECK(var) if ((u_char *)&(var) > ep - sizeof(var)) goto trunc #endif dp = (struct icmp6_hdr *)bp; ip = (struct ip6_hdr *)bp2; oip = (struct ip6_hdr *)(dp + 1); str = buf; /* 'ep' points to the end of avaible data. */ ep = snapend; if (ip->ip6_plen) icmp6len = (ntohs(ip->ip6_plen) + sizeof(struct ip6_hdr) - (bp - bp2)); else /* XXX: jumbo payload case... */ icmp6len = snapend - bp; #if 0 (void)printf("%s > %s: ", ip6addr_string(&ip->ip6_src), ip6addr_string(&ip->ip6_dst)); #endif TCHECK(dp->icmp6_code); switch (dp->icmp6_type) { case ICMP6_DST_UNREACH: TCHECK(oip->ip6_dst); switch (dp->icmp6_code) { case ICMP6_DST_UNREACH_NOROUTE: printf("icmp6: %s unreachable route", ip6addr_string(&oip->ip6_dst)); break; case ICMP6_DST_UNREACH_ADMIN: printf("icmp6: %s unreachable prohibited", ip6addr_string(&oip->ip6_dst)); break; #ifdef ICMP6_DST_UNREACH_BEYONDSCOPE case ICMP6_DST_UNREACH_BEYONDSCOPE: #else case ICMP6_DST_UNREACH_NOTNEIGHBOR: #endif printf("icmp6: %s beyond scope of source address %s", ip6addr_string(&oip->ip6_dst), ip6addr_string(&oip->ip6_src)); break; case ICMP6_DST_UNREACH_ADDR: printf("icmp6: %s unreachable address", ip6addr_string(&oip->ip6_dst)); break; case ICMP6_DST_UNREACH_NOPORT: TCHECK(oip->ip6_nxt); hlen = sizeof(struct ip6_hdr); ouh = (struct udphdr *)(((u_char *)oip) + hlen); TCHECK(ouh->uh_dport); dport = ntohs(ouh->uh_dport); switch (oip->ip6_nxt) { case IPPROTO_TCP: printf("icmp6: %s tcp port %s unreachable", ip6addr_string(&oip->ip6_dst), tcpport_string(dport)); break; case IPPROTO_UDP: printf("icmp6: %s udp port %s unreachable", ip6addr_string(&oip->ip6_dst), udpport_string(dport)); break; default: printf("icmp6: %s protocol %d port %d unreachable", ip6addr_string(&oip->ip6_dst), oip->ip6_nxt, dport); break; } break; default: printf("icmp6: %s unreachable code-#%d", ip6addr_string(&oip->ip6_dst), dp->icmp6_code); break; } break; case ICMP6_PACKET_TOO_BIG: TCHECK(dp->icmp6_mtu); printf("icmp6: too big %u", (u_int32_t)ntohl(dp->icmp6_mtu)); break; case ICMP6_TIME_EXCEEDED: TCHECK(oip->ip6_dst); switch (dp->icmp6_code) { case ICMP6_TIME_EXCEED_TRANSIT: printf("icmp6: time exceeded in-transit for %s", ip6addr_string(&oip->ip6_dst)); break; case ICMP6_TIME_EXCEED_REASSEMBLY: printf("icmp6: ip6 reassembly time exceeded"); break; default: printf("icmp6: time exceeded code-#%d", dp->icmp6_code); break; } break; case ICMP6_PARAM_PROB: TCHECK(oip->ip6_dst); switch (dp->icmp6_code) { case ICMP6_PARAMPROB_HEADER: printf("icmp6: parameter problem errorneous - octet %u", (u_int32_t)ntohl(dp->icmp6_pptr)); break; case ICMP6_PARAMPROB_NEXTHEADER: printf("icmp6: parameter problem next header - octet %u", (u_int32_t)ntohl(dp->icmp6_pptr)); break; case ICMP6_PARAMPROB_OPTION: printf("icmp6: parameter problem option - octet %u", (u_int32_t)ntohl(dp->icmp6_pptr)); break; default: printf("icmp6: parameter problem code-#%d", dp->icmp6_code); break; } break; case ICMP6_ECHO_REQUEST: case ICMP6_ECHO_REPLY: printf("icmp6: echo %s", dp->icmp6_type == ICMP6_ECHO_REQUEST ? "request" : "reply"); if (vflag) { TCHECK(dp->icmp6_seq); printf(" (id:%04x seq:%u)", ntohs(dp->icmp6_id), ntohs(dp->icmp6_seq)); } break; case ICMP6_MEMBERSHIP_QUERY: printf("icmp6: multicast listener query "); if (length == MLD_V1_QUERY_MINLEN) { mld6_print((const u_char *)dp); } else if (length >= MLD_V2_QUERY_MINLEN) { printf("v2 "); mldv2_query_print((const u_char *)dp, length); } else { printf("unknown-version (len %u) ", length); } break; case ICMP6_MEMBERSHIP_REPORT: printf("icmp6: multicast listener report "); mld6_print((const u_char *)dp); break; case ICMP6_MEMBERSHIP_REDUCTION: printf("icmp6: multicast listener done "); mld6_print((const u_char *)dp); break; case ND_ROUTER_SOLICIT: printf("icmp6: router solicitation "); if (vflag) { #define RTSOLLEN 8 icmp6_opt_print((const u_char *)dp + RTSOLLEN, icmp6len - RTSOLLEN); } break; case ND_ROUTER_ADVERT: printf("icmp6: router advertisement"); if (vflag) { struct nd_router_advert *p; p = (struct nd_router_advert *)dp; TCHECK(p->nd_ra_retransmit); printf("(chlim=%d, ", (int)p->nd_ra_curhoplimit); if (p->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED) printf("M"); if (p->nd_ra_flags_reserved & ND_RA_FLAG_OTHER) printf("O"); if (p->nd_ra_flags_reserved != 0) printf(" "); printf("router_ltime=%d, ", ntohs(p->nd_ra_router_lifetime)); printf("reachable_time=%u, ", (u_int32_t)ntohl(p->nd_ra_reachable)); printf("retrans_time=%u)", (u_int32_t)ntohl(p->nd_ra_retransmit)); #define RTADVLEN 16 icmp6_opt_print((const u_char *)dp + RTADVLEN, icmp6len - RTADVLEN); } break; case ND_NEIGHBOR_SOLICIT: { struct nd_neighbor_solicit *p; p = (struct nd_neighbor_solicit *)dp; TCHECK(p->nd_ns_target); printf("icmp6: neighbor sol: who has %s", ip6addr_string(&p->nd_ns_target)); if (vflag) { #define NDSOLLEN 24 icmp6_opt_print((const u_char *)dp + NDSOLLEN, icmp6len - NDSOLLEN); } } break; case ND_NEIGHBOR_ADVERT: { struct nd_neighbor_advert *p; p = (struct nd_neighbor_advert *)dp; TCHECK(p->nd_na_target); printf("icmp6: neighbor adv: tgt is %s", ip6addr_string(&p->nd_na_target)); if (vflag) { #define ND_NA_FLAG_ALL \ (ND_NA_FLAG_ROUTER|ND_NA_FLAG_SOLICITED|ND_NA_FLAG_OVERRIDE) /* we don't need ntohl() here. see advanced-api-04. */ if (p->nd_na_flags_reserved & ND_NA_FLAG_ALL) { #undef ND_NA_FLAG_ALL u_int32_t flags; flags = p->nd_na_flags_reserved; printf("("); if (flags & ND_NA_FLAG_ROUTER) printf("R"); if (flags & ND_NA_FLAG_SOLICITED) printf("S"); if (flags & ND_NA_FLAG_OVERRIDE) printf("O"); printf(")"); } #define NDADVLEN 24 icmp6_opt_print((const u_char *)dp + NDADVLEN, icmp6len - NDADVLEN); } } break; case ND_REDIRECT: { #define RDR(i) ((struct nd_redirect *)(i)) char tgtbuf[INET6_ADDRSTRLEN], dstbuf[INET6_ADDRSTRLEN]; TCHECK(RDR(dp)->nd_rd_dst); inet_ntop(AF_INET6, &RDR(dp)->nd_rd_target, tgtbuf, INET6_ADDRSTRLEN); inet_ntop(AF_INET6, &RDR(dp)->nd_rd_dst, dstbuf, INET6_ADDRSTRLEN); printf("icmp6: redirect %s to %s", dstbuf, tgtbuf); #define REDIRECTLEN 40 if (vflag) { icmp6_opt_print((const u_char *)dp + REDIRECTLEN, icmp6len - REDIRECTLEN); } break; } case ICMP6_ROUTER_RENUMBERING: switch (dp->icmp6_code) { case ICMP6_ROUTER_RENUMBERING_COMMAND: printf("icmp6: router renum command"); break; case ICMP6_ROUTER_RENUMBERING_RESULT: printf("icmp6: router renum result"); break; default: printf("icmp6: router renum code-#%d", dp->icmp6_code); break; } break; #ifdef ICMP6_WRUREQUEST case ICMP6_WRUREQUEST: /*ICMP6_FQDN_QUERY*/ { int siz; siz = ep - (u_char *)(dp + 1); if (siz == 4) printf("icmp6: who-are-you request"); else { printf("icmp6: FQDN request"); if (vflag) { if (siz < 8) printf("?(icmp6_data %d bytes)", siz); else if (8 < siz) printf("?(extra %d bytes)", siz - 8); } } break; } #endif /*ICMP6_WRUREQUEST*/ #ifdef ICMP6_WRUREPLY case ICMP6_WRUREPLY: /*ICMP6_FQDN_REPLY*/ { enum { UNKNOWN, WRU, FQDN } mode = UNKNOWN; u_char const *buf; u_char const *cp = NULL; buf = (u_char *)(dp + 1); /* fair guess */ if (buf[12] == ep - buf - 13) mode = FQDN; else if (dp->icmp6_code == 1) mode = FQDN; /* wild guess */ if (mode == UNKNOWN) { cp = buf + 4; while (cp < ep) { if (!isprint(*cp++)) mode = FQDN; } } #ifndef abs #define abs(a) ((0 < (a)) ? (a) : -(a)) #endif if (mode == UNKNOWN && 2 < abs(buf[12] - (ep - buf - 13))) mode = WRU; if (mode == UNKNOWN) mode = FQDN; if (mode == WRU) { cp = buf + 4; printf("icmp6: who-are-you reply(\""); } else if (mode == FQDN) { cp = buf + 13; printf("icmp6: FQDN reply(\""); } for (; cp < ep; cp++) printf((isprint(*cp) ? "%c" : "\\%03o"), *cp); printf("\""); if (vflag) { printf(",%s", mode == FQDN ? "FQDN" : "WRU"); if (mode == FQDN) { int ttl; ttl = (int)ntohl(*(u_int32_t *)&buf[8]); if (dp->icmp6_code == 1) printf(",TTL=unknown"); else if (ttl < 0) printf(",TTL=%d:invalid", ttl); else printf(",TTL=%d", ttl); if (buf[12] != ep - buf - 13) { (void)printf(",invalid namelen:%d/%u", buf[12], (unsigned int)(ep - buf - 13)); } } } printf(")"); break; } #endif /*ICMP6_WRUREPLY*/ case MLDV2_LISTENER_REPORT: printf("multicast listener report v2"); mldv2_report_print((const u_char *) dp, length); break; default: printf("icmp6: type-#%d", dp->icmp6_type); break; } if (vflag) { u_int16_t sum; if (TTEST2(dp->icmp6_type, length)) { sum = icmp6_cksum(ip, dp, length); if (sum != 0) printf(" [bad icmp6 cksum %x!]", sum); else printf(" [icmp6 cksum ok]"); } } return; trunc: fputs("[|icmp6]", stdout); #if 0 #undef TCHECK #endif }
void icmp_print(const u_char *bp, u_int length, const u_char *bp2) { const struct icmp *dp; const struct ip *ip; const char *str, *fmt; const struct ip *oip; const struct udphdr *ouh; u_int hlen, dport, mtu; char buf[MAXHOSTNAMELEN+256]; char buf2[MAXHOSTNAMELEN+256]; dp = (struct icmp *)bp; ip = (struct ip *)bp2; str = buf; (void)printf("%s > %s: ", ipaddr_string(&ip->ip_src), ipaddr_string(&ip->ip_dst)); TCHECK(dp->icmp_code); if (qflag) (void) snprintf(buf, sizeof buf, "%u %u", dp->icmp_type, dp->icmp_code); else switch (dp->icmp_type) { case ICMP_ECHOREPLY: case ICMP_ECHO: if (vflag) { TCHECK(dp->icmp_seq); (void)snprintf(buf, sizeof buf, "echo %s (id:%04x seq:%u)", (dp->icmp_type == ICMP_ECHO)? "request": "reply", ntohs(dp->icmp_id), ntohs(dp->icmp_seq)); } else str = tok2str(icmp2str, "type-#%u", dp->icmp_type); break; case ICMP_UNREACH: TCHECK(dp->icmp_ip.ip_dst); switch (dp->icmp_code) { case ICMP_UNREACH_PROTOCOL: TCHECK(dp->icmp_ip.ip_p); (void)snprintf(buf, sizeof buf, "%s protocol %u unreachable", ipaddr_string(&dp->icmp_ip.ip_dst), dp->icmp_ip.ip_p); break; case ICMP_UNREACH_PORT: TCHECK(dp->icmp_ip.ip_p); oip = &dp->icmp_ip; hlen = oip->ip_hl * 4; ouh = (struct udphdr *)(((u_char *)oip) + hlen); TCHECK(ouh->uh_dport); dport = ntohs(ouh->uh_dport); switch (oip->ip_p) { case IPPROTO_TCP: (void)snprintf(buf, sizeof buf, "%s tcp port %s unreachable", ipaddr_string(&oip->ip_dst), tcpport_string(dport)); break; case IPPROTO_UDP: (void)snprintf(buf, sizeof buf, "%s udp port %s unreachable", ipaddr_string(&oip->ip_dst), udpport_string(dport)); break; default: (void)snprintf(buf, sizeof buf, "%s protocol %u port %u unreachable", ipaddr_string(&oip->ip_dst), oip->ip_p, dport); break; } break; case ICMP_UNREACH_NEEDFRAG: { const struct mtu_discovery *mp; mp = (struct mtu_discovery *)&dp->icmp_void; mtu = EXTRACT_16BITS(&mp->nexthopmtu); if (mtu) (void)snprintf(buf, sizeof buf, "%s unreachable - need to frag (mtu %u)", ipaddr_string(&dp->icmp_ip.ip_dst), mtu); else (void)snprintf(buf, sizeof buf, "%s unreachable - need to frag", ipaddr_string(&dp->icmp_ip.ip_dst)); } break; default: fmt = tok2str(unreach2str, "#%u %%s unreachable", dp->icmp_code); (void)snprintf(buf, sizeof buf, fmt, ipaddr_string(&dp->icmp_ip.ip_dst)); break; } break; case ICMP_REDIRECT: TCHECK(dp->icmp_ip.ip_dst); fmt = tok2str(type2str, "redirect-#%u %%s to net %%s", dp->icmp_code); (void)snprintf(buf, sizeof buf, fmt, ipaddr_string(&dp->icmp_ip.ip_dst), ipaddr_string(&dp->icmp_gwaddr)); break; case ICMP_ROUTERADVERT: { const struct ih_rdiscovery *ihp; const struct id_rdiscovery *idp; u_int lifetime, num, size; (void)strlcpy(buf, "router advertisement", sizeof(buf)); ihp = (struct ih_rdiscovery *)&dp->icmp_void; TCHECK(*ihp); (void)strlcat(buf, " lifetime ", sizeof(buf)); lifetime = EXTRACT_16BITS(&ihp->ird_lifetime); if (lifetime < 60) (void)snprintf(buf2, sizeof(buf2), "%u", lifetime); else if (lifetime < 60 * 60) (void)snprintf(buf2, sizeof(buf2), "%u:%02u", lifetime / 60, lifetime % 60); else (void)snprintf(buf2, sizeof(buf2), "%u:%02u:%02u", lifetime / 3600, (lifetime % 3600) / 60, lifetime % 60); strlcat(buf, buf2, sizeof(buf)); num = ihp->ird_addrnum; (void)snprintf(buf2, sizeof(buf2), " %u:", num); strlcat(buf, buf2, sizeof(buf)); size = ihp->ird_addrsiz; if (size != 2) { (void)snprintf(buf2, sizeof(buf2), " [size %u]", size); strlcat(buf, buf2, sizeof(buf)); break; } idp = (struct id_rdiscovery *)&dp->icmp_data; while (num-- > 0) { TCHECK(*idp); (void)snprintf(buf2, sizeof(buf2), " {%s %u}", ipaddr_string(&idp->ird_addr), EXTRACT_32BITS(&idp->ird_pref)); strlcat(buf, buf2, sizeof(buf)); } } break; case ICMP_TIMXCEED: TCHECK(dp->icmp_ip.ip_dst); switch (dp->icmp_code) { case ICMP_TIMXCEED_INTRANS: str = "time exceeded in-transit"; break; case ICMP_TIMXCEED_REASS: str = "ip reassembly time exceeded"; break; default: (void)snprintf(buf, sizeof buf, "time exceeded-#%u", dp->icmp_code); break; } break; case ICMP_PARAMPROB: switch (dp->icmp_code) { case ICMP_PARAMPROB_OPTABSENT: str = "requested option absent"; break; case ICMP_PARAMPROB_LENGTH: snprintf(buf, sizeof buf, "bad length %u", dp->icmp_pptr); break; default: TCHECK(dp->icmp_pptr); (void)snprintf(buf, sizeof buf, "parameter problem - octet %u", dp->icmp_pptr); break; } break; case ICMP_MASKREPLY: TCHECK(dp->icmp_mask); (void)snprintf(buf, sizeof buf, "address mask is 0x%08x", (u_int32_t)ntohl(dp->icmp_mask)); break; default: str = tok2str(icmp2str, "type-#%u", dp->icmp_type); break; } (void)printf("icmp: %s", str); if (vflag) { u_int16_t sum; if (TTEST2(dp->icmp_type, length)) { sum = in_cksum((const u_short *)dp, length, 0); if (sum != 0) (void)printf(" [bad icmp cksum %x!]", sum); else (void)printf(" [icmp cksum ok]"); } } if (vflag > 1 && !ICMP_INFOTYPE(dp->icmp_type) && TTEST(dp->icmp_ip)) { (void)printf(" for "); oip = &dp->icmp_ip; ip_print((u_char *)oip, ntohs(oip->ip_len)); } return; trunc: fputs("[|icmp]", stdout); }