uint_t interpret_tr(int flags, caddr_t e, int elen, int origlen) { struct tr_header *mh; struct tr_ri *rh; uchar_t fc; struct llc_snap_hdr *snaphdr; char *off; int maclen, len; boolean_t data_copied = B_FALSE; extern char *dst_name, *src_name; int ethertype; int is_llc = 0, is_snap = 0, source_routing = 0; int blen = MAX(origlen, 17800); if (data != NULL && datalen != 0 && datalen < blen) { free(data); data = NULL; datalen = 0; } if (!data) { data = (char *)malloc(blen); if (!data) pr_err("Warning: malloc failure"); datalen = blen; } if (origlen < ACFCDASA_LEN) { if (flags & F_SUM) { (void) sprintf(get_sum_line(), "RUNT (short packet - %d bytes)", origlen); } if (flags & F_DTAIL) show_header("RUNT: ", "Short packet", origlen); return (elen); } if (elen < ACFCDASA_LEN) return (elen); mh = (struct tr_header *)e; rh = (struct tr_ri *)&mh->ri; fc = mh->fc; if (is_llc = tr_machdr_len(e, &maclen, &source_routing)) { snaphdr = (struct llc_snap_hdr *)(e + maclen); if (snaphdr->d_lsap == LSAP_SNAP && snaphdr->s_lsap == LSAP_SNAP && snaphdr->control == CNTL_LLC_UI) { is_snap = 1; } } if (memcmp(&mh->dhost, ðer_broadcast, sizeof (struct ether_addr)) == 0) dst_name = "(broadcast)"; else if (memcmp(&mh->dhost, &tokenbroadcastaddr2, sizeof (struct ether_addr)) == 0) dst_name = "(mac broadcast)"; else if (mh->dhost.ether_addr_octet[0] & TR_FN_ADDR) dst_name = "(functional)"; if (is_snap) ethertype = ntohs(snaphdr->type); else { src_name = print_etherinfo(&mh->shost); dst_name = print_etherinfo(&mh->dhost); } /* * The 14 byte ether header screws up alignment * of the rest of the packet for 32 bit aligned * architectures like SPARC. Alas, we have to copy * the rest of the packet in order to align it. */ if (is_llc) { if (is_snap) { len = elen - (maclen + LLC_SNAP_HDR_LEN); off = (char *)(e + maclen + LLC_SNAP_HDR_LEN); } else { len = elen - (maclen + LLC_HDR1_LEN); off = (char *)(e + maclen + LLC_HDR1_LEN); } } else { len = elen - maclen; off = (char *)(e + maclen); } if (len > 0 && (off + len <= (char *)e + elen)) { (void) memcpy(data, off, len); data_copied = B_TRUE; } if (flags & F_SUM) { if (source_routing) sprintf(get_sum_line(), print_sr(rh)); if (is_llc) { if (is_snap) { (void) sprintf(get_sum_line(), "TR LLC w/SNAP " "Type=%04X (%s), size=%d bytes", ethertype, print_ethertype(ethertype), origlen); } else { (void) sprintf(get_sum_line(), "TR LLC, but no " "SNAP encoding, size = %d bytes", origlen); } } else { (void) sprintf(get_sum_line(), "TR MAC FC=%02X (%s), size = %d bytes", fc, print_fc(fc), origlen); } } if (flags & F_DTAIL) { show_header("TR: ", "TR Header", elen); show_space(); (void) sprintf(get_line(0, 0), "Packet %d arrived at %d:%02d:%d.%05d", pi_frame, pi_time_hour, pi_time_min, pi_time_sec, pi_time_usec / 10); (void) sprintf(get_line(0, 0), "Packet size = %d bytes", elen); (void) sprintf(get_line(0, 1), "Frame Control = %02x (%s)", fc, print_fc(fc)); (void) sprintf(get_line(2, 6), "Destination = %s, %s", printether(&mh->dhost), print_etherinfo(&mh->dhost)); (void) sprintf(get_line(8, 6), "Source = %s, %s", printether(&mh->shost), print_etherinfo(&mh->shost)); if (source_routing) sprintf(get_line(ACFCDASA_LEN, rh->len), print_sr(rh)); if (is_llc) { (void) sprintf(get_line(maclen, 1), "Dest Service Access Point = %02x", snaphdr->d_lsap); (void) sprintf(get_line(maclen+1, 1), "Source Service Access Point = %02x", snaphdr->s_lsap); (void) sprintf(get_line(maclen+2, 1), "Control = %02x", snaphdr->control); if (is_snap) { (void) sprintf(get_line(maclen+3, 3), "SNAP Protocol Id = %02x%02x%02x", snaphdr->org[0], snaphdr->org[1], snaphdr->org[2]); } } if (is_snap) { (void) sprintf(get_line(maclen+6, 2), "SNAP Type = %04X (%s)", ethertype, print_ethertype(ethertype)); } show_space(); } /* go to the next protocol layer */ if (is_snap && data_copied) { switch (ethertype) { case ETHERTYPE_IP: (void) interpret_ip(flags, (struct ip *)data, len); break; /* Just in case it is decided to add this type */ case ETHERTYPE_IPV6: (void) interpret_ipv6(flags, (ip6_t *)data, len); break; case ETHERTYPE_ARP: case ETHERTYPE_REVARP: interpret_arp(flags, (struct arphdr *)data, len); break; case ETHERTYPE_AARP: /* AppleTalk */ interpret_aarp(flags, data, len); break; case ETHERTYPE_AT: interpret_at(flags, (struct ddp_hdr *)data, len); break; default: break; } } return (elen); }
static uint_t interpret_ipnet(int flags, char *header, int elen, int origlen) { dl_ipnetinfo_t dl; size_t len = elen - sizeof (dl_ipnetinfo_t); char *off = (char *)header + sizeof (dl_ipnetinfo_t); int blen = MAX(origlen, 8252); char szone[MAX_UINT64_STR]; char dzone[MAX_UINT64_STR]; (void) memcpy(&dl, header, sizeof (dl)); if (data != NULL && datalen != 0 && datalen < blen) { free(data); data = NULL; datalen = 0; } if (data == NULL) { data = (char *)malloc(blen); if (!data) pr_err("Warning: malloc failure"); datalen = blen; } if (dl.dli_zsrc == ALL_ZONES) sprintf(szone, "Unknown"); else sprintf(szone, "%lu", BE_32(dl.dli_zsrc)); if (dl.dli_zdst == ALL_ZONES) sprintf(dzone, "Unknown"); else sprintf(dzone, "%lu", BE_32(dl.dli_zdst)); if (flags & F_SUM) { (void) snprintf(get_sum_line(), MAXLINE, "IPNET src zone %s dst zone %s", szone, dzone); } if (flags & F_DTAIL) { show_header("IPNET: ", "IPNET Header", elen); show_space(); (void) sprintf(get_line(0, 0), "Packet %d arrived at %d:%02d:%d.%05d", pi_frame, pi_time_hour, pi_time_min, pi_time_sec, pi_time_usec / 10); (void) sprintf(get_line(0, 0), "Packet size = %d bytes", elen); (void) snprintf(get_line(0, 0), get_line_remain(), "dli_version = %d", dl.dli_version); (void) snprintf(get_line(0, 0), get_line_remain(), "dli_family = %d", dl.dli_family); (void) snprintf(get_line(0, 2), get_line_remain(), "dli_zsrc = %s", szone); (void) snprintf(get_line(0, 2), get_line_remain(), "dli_zdst = %s", dzone); show_space(); } memcpy(data, off, len); switch (dl.dli_family) { case AF_INET: (void) interpret_ip(flags, (struct ip *)data, len); break; case AF_INET6: (void) interpret_ipv6(flags, (ip6_t *)data, len); break; default: break; } return (0); }
/* ARGSUSED */ uint_t interpret_iptun(int flags, char *header, int elen, int origlen) { (void) interpret_ip(flags, (struct ip *)header, elen); return (elen); }
static uint_t interpret_ib(int flags, char *header, int elen, int origlen) { struct ipoib_header *hdr = (struct ipoib_header *)header; char *off; int len; unsigned short ethertype; int blen = MAX(origlen, 4096); if (data != NULL && datalen != 0 && datalen < blen) { free(data); data = NULL; datalen = 0; } if (data == NULL) { data = malloc(blen); if (data == NULL) pr_err("Warning: malloc failure"); datalen = blen; } if (origlen < IPOIB_HDRSIZE) { if (flags & F_SUM) (void) snprintf(get_sum_line(), MAXLINE, "RUNT (short packet - %d bytes)", origlen); if (flags & F_DTAIL) show_header("RUNT: ", "Short packet", origlen); return (elen); } if (elen < IPOIB_HDRSIZE) return (elen); /* * It is not possible to understand just by looking * at the header whether this was a broad/multi cast * packet; thus dst_name is not updated. */ ethertype = ntohs(hdr->ipoib_type); len = elen - IPOIB_HDRSIZE; off = (char *)(hdr + 1); (void) memcpy(data, off, len); if (flags & F_SUM) { (void) snprintf(get_sum_line(), MAXLINE, "IPIB Type=%04X (%s), size = %d bytes", ethertype, print_ethertype(ethertype), origlen); } if (flags & F_DTAIL) { show_header("IPIB: ", "IPIB Header", elen); show_space(); (void) snprintf(get_line(0, 0), get_line_remain(), "Packet %d arrived at %d:%02d:%d.%02d", pi_frame, pi_time_hour, pi_time_min, pi_time_sec, pi_time_usec / 10000); (void) snprintf(get_line(0, 0), get_line_remain(), "Packet size = %d bytes", elen, elen); (void) snprintf(get_line(0, 2), get_line_remain(), "Ethertype = %04X (%s)", ethertype, print_ethertype(ethertype)); show_space(); } /* Go to the next protocol layer */ switch (ethertype) { case ETHERTYPE_IP: (void) interpret_ip(flags, (struct ip *)data, len); break; case ETHERTYPE_IPV6: (void) interpret_ipv6(flags, (ip6_t *)data, len); break; case ETHERTYPE_ARP: case ETHERTYPE_REVARP: interpret_arp(flags, (struct arphdr *)data, len); break; } return (elen); }
uint_t interpret_ether(int flags, char *header, int elen, int origlen) { struct ether_header *e = (struct ether_header *)header; uchar_t *off, *ieeestart; int len; int ieee8023 = 0; extern char *dst_name; int ethertype; struct ether_vlan_extinfo *evx = NULL; int blen = MAX(origlen, ETHERMTU); boolean_t trillpkt = B_FALSE; uint16_t tci = 0; if (data != NULL && datalen != 0 && datalen < blen) { free(data); data = NULL; datalen = 0; } if (!data) { data = (char *)malloc(blen); if (!data) pr_err("Warning: malloc failure"); datalen = blen; } inner_pkt: if (origlen < 14) { if (flags & F_SUM) { (void) sprintf(get_sum_line(), "RUNT (short packet - %d bytes)", origlen); } if (flags & F_DTAIL) show_header("RUNT: ", "Short packet", origlen); return (elen); } if (elen < 14) return (elen); if (memcmp(&e->ether_dhost, ðer_broadcast, sizeof (struct ether_addr)) == 0) dst_name = "(broadcast)"; else if (e->ether_dhost.ether_addr_octet[0] & 1) dst_name = "(multicast)"; ethertype = ntohs(e->ether_type); /* * The 14 byte ether header screws up alignment * of the rest of the packet for 32 bit aligned * architectures like SPARC. Alas, we have to copy * the rest of the packet in order to align it. */ len = elen - sizeof (struct ether_header); off = (uchar_t *)(e + 1); if (ethertype == ETHERTYPE_VLAN) { if (origlen < sizeof (struct ether_vlan_header)) { if (flags & F_SUM) { (void) sprintf(get_sum_line(), "RUNT (short VLAN packet - %d bytes)", origlen); } if (flags & F_DTAIL) { show_header("RUNT: ", "Short VLAN packet", origlen); } return (elen); } if (len < sizeof (struct ether_vlan_extinfo)) return (elen); evx = (struct ether_vlan_extinfo *)off; off += sizeof (struct ether_vlan_extinfo); len -= sizeof (struct ether_vlan_extinfo); ethertype = ntohs(evx->ether_type); tci = ntohs(evx->ether_tci); } if (ethertype <= 1514) { /* * Fake out the IEEE 802.3 packets. * Should be DSAP=0xAA, SSAP=0xAA, control=0x03 * then three padding bytes of zero (OUI), * followed by a normal ethernet-type packet. */ ieee8023 = ethertype; ieeestart = off; if (off[0] == 0xAA && off[1] == 0xAA) { ethertype = ntohs(*(ushort_t *)(off + 6)); off += 8; len -= 8; } else { ethertype = 0; off += 3; len -= 3; } } if (flags & F_SUM) { /* * Set the flag that says don't display VLAN information. * If it needs to change, that will be done later if the * packet is VLAN tagged and if snoop is in its default * summary mode. */ set_vlan_id(0); if (evx == NULL) { if (ethertype == 0 && ieee8023 > 0) { (void) sprintf(get_sum_line(), "ETHER 802.3 SSAP %02X DSAP %02X, " "size=%d bytes", ieeestart[0], ieeestart[1], origlen); } else { (void) sprintf(get_sum_line(), "ETHER Type=%04X (%s), size=%d bytes", ethertype, print_ethertype(ethertype), origlen); } } else { if (ethertype == 0 && ieee8023 > 0) { (void) sprintf(get_sum_line(), "ETHER 802.3 SSAP %02X DSAP %02X, " "VLAN ID=%hu, size=%d bytes", ieeestart[0], ieeestart[1], VLAN_ID(tci), origlen); } else { (void) sprintf(get_sum_line(), "ETHER Type=%04X (%s), VLAN ID=%hu, " "size=%d bytes", ethertype, print_ethertype(ethertype), VLAN_ID(tci), origlen); } if (!(flags & F_ALLSUM)) set_vlan_id(VLAN_ID(tci)); } } if (flags & F_DTAIL) { show_header("ETHER: ", "Ether Header", elen); show_space(); if (!trillpkt) { (void) sprintf(get_line(0, 0), "Packet %d arrived at %d:%02d:%d.%05d", pi_frame, pi_time_hour, pi_time_min, pi_time_sec, pi_time_usec / 10); (void) sprintf(get_line(0, 0), "Packet size = %d bytes", elen, elen); } (void) sprintf(get_line(0, 6), "Destination = %s, %s", printether(&e->ether_dhost), print_etherinfo(&e->ether_dhost)); (void) sprintf(get_line(6, 6), "Source = %s, %s", printether(&e->ether_shost), print_etherinfo(&e->ether_shost)); if (evx != NULL) { (void) sprintf(get_line(0, 0), "VLAN ID = %hu", VLAN_ID(tci)); (void) sprintf(get_line(0, 0), "VLAN Priority = %hu", VLAN_PRI(tci)); } if (ieee8023 > 0) { (void) sprintf(get_line(12, 2), "IEEE 802.3 length = %d bytes", ieee8023); /* Print LLC only for non-TCP/IP packets */ if (ethertype == 0) { (void) snprintf(get_line(0, 0), get_line_remain(), "SSAP = %02X, DSAP = %02X, CTRL = %02X", ieeestart[0], ieeestart[1], ieeestart[2]); } } if (ethertype != 0 || ieee8023 == 0) (void) sprintf(get_line(12, 2), "Ethertype = %04X (%s)", ethertype, print_ethertype(ethertype)); show_space(); } /* * We cannot trust the length field in the header to be correct. * But we should continue to process the packet. Then user can * notice something funny in the header. * Go to the next protocol layer only if data have been * copied. */ if (len > 0 && (off + len <= (uchar_t *)e + elen)) { (void) memmove(data, off, len); if (!trillpkt && ethertype == ETHERTYPE_TRILL) { ethertype = interpret_trill(flags, &e, data, &len); /* Decode inner Ethernet frame */ if (ethertype != 0) { evx = NULL; trillpkt = B_TRUE; (void) memmove(data, e, len); e = (struct ether_header *)data; origlen = len; elen = len; goto inner_pkt; } } switch (ethertype) { case ETHERTYPE_IP: (void) interpret_ip(flags, (struct ip *)data, len); break; /* Just in case it is decided to add this type */ case ETHERTYPE_IPV6: (void) interpret_ipv6(flags, (ip6_t *)data, len); break; case ETHERTYPE_ARP: case ETHERTYPE_REVARP: interpret_arp(flags, (struct arphdr *)data, len); break; case ETHERTYPE_PPPOED: case ETHERTYPE_PPPOES: (void) interpret_pppoe(flags, (poep_t *)data, len); break; case ETHERTYPE_AARP: /* AppleTalk */ interpret_aarp(flags, data, len); break; case ETHERTYPE_AT: interpret_at(flags, (struct ddp_hdr *)data, len); break; case 0: if (ieee8023 == 0) break; switch (ieeestart[0]) { case 0xFE: interpret_isis(flags, data, len, memcmp(&e->ether_dhost, &all_isis_rbridges, sizeof (struct ether_addr)) == 0); break; case 0x42: interpret_bpdu(flags, data, len); break; } break; } } return (elen); }
uint_t interpret_fddi(int flags, caddr_t e, int elen, int origlen) { struct fddi_header fhdr, *f = &fhdr; char *off; int len; boolean_t data_copied = B_FALSE; extern char *dst_name, *src_name; int ethertype; int is_llc = 0, is_smt = 0, is_snap = 0; int blen = MAX(origlen, 4500); if (data != NULL && datalen != 0 && datalen < blen) { free(data); data = NULL; datalen = 0; } if (!data) { data = (char *)malloc(blen); if (!data) pr_err("Warning: malloc failure"); datalen = blen; } if (origlen < 13) { if (flags & F_SUM) { (void) sprintf(get_sum_line(), "RUNT (short packet - %d bytes)", origlen); } if (flags & F_DTAIL) show_header("RUNT: ", "Short packet", origlen); return (elen); } if (elen < 13) return (elen); (void) memcpy(&f->fc, e, sizeof (f->fc)); addr_copy_swap(&f->dhost, (struct ether_addr *)(e+1)); addr_copy_swap(&f->shost, (struct ether_addr *)(e+7)); if ((f->fc&0x50) == 0x50) { is_llc = 1; (void) memcpy(&f->dsap, e+13, sizeof (f->dsap)); (void) memcpy(&f->ssap, e+14, sizeof (f->ssap)); (void) memcpy(&f->ctl, e+15, sizeof (f->ctl)); if (f->dsap == 0xaa && f->ssap == 0xaa) { is_snap = 1; (void) memcpy(&f->proto_id, e+16, sizeof (f->proto_id)); (void) memcpy(&f->type, e+19, sizeof (f->type)); } } else { if ((f->fc&0x41) == 0x41 || (f->fc&0x4f) == 0x4f) { is_smt = 1; } } if (memcmp(&f->dhost, ðer_broadcast, sizeof (struct ether_addr)) == 0) dst_name = "(broadcast)"; else if (f->dhost.ether_addr_octet[0] & 0x01) dst_name = "(multicast)"; if (is_snap) ethertype = ntohs(f->type); else { src_name = print_etherinfo(&f->shost); dst_name = print_etherinfo(&f->dhost); } /* * The 14 byte ether header screws up alignment * of the rest of the packet for 32 bit aligned * architectures like SPARC. Alas, we have to copy * the rest of the packet in order to align it. */ if (is_llc) { if (is_snap) { len = elen - 21; off = (char *)(e + 21); } else { len = elen - 16; off = (char *)(e + 16); } } else { len = elen - 13; off = (char *)(e + 13); } if (len > 0 && (off + len <= (char *)e + elen)) { (void) memcpy(data, off, len); data_copied = B_TRUE; } if (flags & F_SUM) { if (is_llc) { if (is_snap) { (void) sprintf(get_sum_line(), "FDDI LLC Type=%04X (%s), size = %d bytes", ethertype, print_ethertype(ethertype), origlen); } else { (void) sprintf(get_sum_line(), "LLC, but no " "SNAP encoding, size = %d bytes", origlen); } } else if (is_smt) { (void) sprintf(get_sum_line(), "SMT Type=%02X (%s), " "Class = %02X (%s), size = %d bytes", *(uchar_t *)(data+1), print_smttype(*(data+1)), *data, print_smtclass(*data), origlen); } else { (void) sprintf(get_sum_line(), "FC=%02X (%s), size = %d bytes", f->fc, print_fc(f->fc), origlen); } } if (flags & F_DTAIL) { show_header("FDDI: ", "FDDI Header", elen); show_space(); (void) sprintf(get_line(0, 0), "Packet %d arrived at %d:%02d:%d.%05d", pi_frame, pi_time_hour, pi_time_min, pi_time_sec, pi_time_usec / 10); (void) sprintf(get_line(0, 0), "Packet size = %d bytes", elen, elen); (void) sprintf(get_line(0, 6), "Destination = %s, %s", printether(&f->dhost), print_etherinfo(&f->dhost)); (void) sprintf(get_line(6, 6), "Source = %s, %s", printether(&f->shost), print_etherinfo(&f->shost)); if (is_llc) { (void) sprintf(get_line(12, 2), "Frame Control = %02x (%s)", f->fc, print_fc(f->fc)); (void) sprintf(get_line(12, 2), "Dest Service Access Point = %02x", f->dsap); (void) sprintf(get_line(12, 2), "Source Service Access Point = %02x", f->ssap); (void) sprintf(get_line(12, 2), "Control = %02x", f->ctl); if (is_snap) { (void) sprintf(get_line(12, 2), "Protocol Id = %02x%02x%02x", f->proto_id[0], f->proto_id[1], f->proto_id[2]); } } else if (is_smt) { (void) sprintf(get_line(12, 2), "Frame Control = %02x (%s)", f->fc, print_fc(f->fc)); (void) sprintf(get_line(12, 2), "Class = %02x (%s)", (uchar_t)*data, print_smtclass(*data)); (void) sprintf(get_line(12, 2), "Type = %02x (%s)", *(uchar_t *)(data+1), print_smttype(*(data+1))); } else { (void) sprintf(get_line(12, 2), "FC=%02X (%s), size = %d bytes", f->fc, print_fc(f->fc), origlen); } if (is_snap) { (void) sprintf(get_line(12, 2), "LLC Type = %04X (%s)", ethertype, print_ethertype(ethertype)); } show_space(); } /* go to the next protocol layer */ if (is_llc && is_snap && f->ctl == 0x03 && data_copied) { switch (ethertype) { case ETHERTYPE_IP: (void) interpret_ip(flags, (struct ip *)data, len); break; /* Just in case it is decided to add this type */ case ETHERTYPE_IPV6: (void) interpret_ipv6(flags, (ip6_t *)data, len); break; case ETHERTYPE_ARP: case ETHERTYPE_REVARP: interpret_arp(flags, (struct arphdr *)data, len); break; default: break; } } return (elen); }
int interpret_ah(int flags, uint8_t *hdr, int iplen, int fraglen) { /* LINTED: alignment */ ah_t *ah = (ah_t *)hdr; ah_t *aligned_ah; ah_t storage; /* In case hdr isn't aligned. */ char *line, *buff; uint_t ahlen, auth_data_len; uint8_t *auth_data, *data; int new_iplen; uint8_t proto; if (fraglen < sizeof (ah_t)) return (fraglen); /* incomplete header */ if (!IS_P2ALIGNED(hdr, 4)) { aligned_ah = (ah_t *)&storage; bcopy(hdr, &storage, sizeof (ah_t)); } else { aligned_ah = ah; } /* * "+ 8" is for the "constant" part that's not included in the AH * length. * * The AH RFC specifies the length field in "length in 4-byte units, * not counting the first 8 bytes". So if an AH is 24 bytes long, * the length field will contain "4". (4 * 4 + 8 == 24). */ ahlen = (aligned_ah->ah_length << 2) + 8; fraglen -= ahlen; if (fraglen < 0) return (fraglen + ahlen); /* incomplete header */ auth_data_len = ahlen - sizeof (ah_t); auth_data = (uint8_t *)(ah + 1); data = auth_data + auth_data_len; if (flags & F_SUM) { line = (char *)get_sum_line(); (void) sprintf(line, "AH SPI=0x%x Replay=%u", ntohl(aligned_ah->ah_spi), ntohl(aligned_ah->ah_replay)); line += strlen(line); } if (flags & F_DTAIL) { show_header("AH: ", "Authentication Header", ahlen); show_space(); (void) sprintf(get_line((char *)&ah->ah_nexthdr - dlc_header, 1), "Next header = %d (%s)", aligned_ah->ah_nexthdr, getproto(aligned_ah->ah_nexthdr)); (void) sprintf(get_line((char *)&ah->ah_length - dlc_header, 1), "AH length = %d (%d bytes)", aligned_ah->ah_length, ahlen); (void) sprintf(get_line((char *)&ah->ah_reserved - dlc_header, 2), "<Reserved field = 0x%x>", ntohs(aligned_ah->ah_reserved)); (void) sprintf(get_line((char *)&ah->ah_spi - dlc_header, 4), "SPI = 0x%x", ntohl(aligned_ah->ah_spi)); (void) sprintf(get_line((char *)&ah->ah_replay - dlc_header, 4), "Replay = %u", ntohl(aligned_ah->ah_replay)); /* * 2 for two hex digits per auth_data byte. */ buff = malloc(auth_data_len * 2); if (buff != NULL) { int i; for (i = 0; i < auth_data_len; i++) sprintf(buff + i * 2, "%02x", auth_data[i]); } (void) sprintf(get_line((char *)auth_data - dlc_header, auth_data_len), "ICV = %s", (buff == NULL) ? "<out of memory>" : buff); /* malloc(3c) says I can call free even if buff == NULL */ free(buff); show_space(); } new_iplen = iplen - ahlen; proto = aligned_ah->ah_nexthdr; /* * Print IPv6 Extension Headers, or skip them in the summary case. */ if (proto == IPPROTO_HOPOPTS || proto == IPPROTO_DSTOPTS || proto == IPPROTO_ROUTING || proto == IPPROTO_FRAGMENT) { (void) print_ipv6_extensions(flags, &data, &proto, &iplen, &fraglen); } if (fraglen > 0) switch (proto) { case IPPROTO_ENCAP: /* LINTED: alignment */ (void) interpret_ip(flags, (struct ip *)data, new_iplen); break; case IPPROTO_IPV6: (void) interpret_ipv6(flags, (ip6_t *)data, new_iplen); break; case IPPROTO_ICMP: (void) interpret_icmp(flags, /* LINTED: alignment */ (struct icmp *)data, new_iplen, fraglen); break; case IPPROTO_ICMPV6: /* LINTED: alignment */ (void) interpret_icmpv6(flags, (icmp6_t *)data, new_iplen, fraglen); break; case IPPROTO_TCP: (void) interpret_tcp(flags, (struct tcphdr *)data, new_iplen, fraglen); break; case IPPROTO_ESP: (void) interpret_esp(flags, data, new_iplen, fraglen); break; case IPPROTO_AH: (void) interpret_ah(flags, data, new_iplen, fraglen); break; case IPPROTO_UDP: (void) interpret_udp(flags, (struct udphdr *)data, new_iplen, fraglen); break; /* default case is to not print anything else */ } return (ahlen); }
/*ARGSUSED*/ void interpret_icmp(int flags, struct icmp *icmp, int iplen, int ilen) { char *pt, *pc, *px; char *line; char buff[67627]; /* Router adv. can have 256 routers .... */ /* Each router has a name 256 char long .. */ char extbuff[MAXHOSTNAMELEN + 1]; struct udphdr *orig_uhdr; int num_rtr_addrs = 0; extern char *prot_nest_prefix; if (ilen < ICMP_MINLEN) return; /* incomplete header */ pt = "Unknown"; pc = ""; px = ""; switch (icmp->icmp_type) { case ICMP_ECHOREPLY: pt = "Echo reply"; (void) sprintf(buff, "ID: %d Sequence number: %d", ntohs(icmp->icmp_id), ntohs(icmp->icmp_seq)); pc = buff; break; case ICMP_UNREACH: pt = "Destination unreachable"; switch (icmp->icmp_code) { case ICMP_UNREACH_NET: if (ilen >= ICMP_ADVLENMIN) { (void) sprintf(buff, "Net %s unreachable", addrtoname(AF_INET, &icmp->icmp_ip.ip_dst)); pc = buff; } else { pc = "Bad net"; } break; case ICMP_UNREACH_HOST: if (ilen >= ICMP_ADVLENMIN) { (void) sprintf(buff, "Host %s unreachable", addrtoname(AF_INET, &icmp->icmp_ip.ip_dst)); pc = buff; } else { pc = "Bad host"; } break; case ICMP_UNREACH_PROTOCOL: if (ilen >= ICMP_ADVLENMIN) { (void) sprintf(buff, "Bad protocol %d", icmp->icmp_ip.ip_p); pc = buff; } else { pc = "Bad protocol"; } break; case ICMP_UNREACH_PORT: if (ilen >= ICMP_ADVLENMIN) { orig_uhdr = (struct udphdr *)((uchar_t *)icmp + ICMP_MINLEN + icmp->icmp_ip.ip_hl * 4); switch (icmp->icmp_ip.ip_p) { case IPPROTO_TCP: (void) sprintf(buff, "TCP port %d" " unreachable", ntohs(orig_uhdr->uh_dport)); pc = buff; break; case IPPROTO_UDP: (void) sprintf(buff, "UDP port %d" " unreachable", ntohs(orig_uhdr->uh_dport)); pc = buff; break; default: pc = "Port unreachable"; break; } } else { pc = "Bad port"; } break; case ICMP_UNREACH_NEEDFRAG: if (ntohs(icmp->icmp_nextmtu) != 0) { (void) sprintf(buff, "Needed to fragment:" " next hop MTU = %d", ntohs(icmp->icmp_nextmtu)); pc = buff; } else { pc = "Needed to fragment"; } break; case ICMP_UNREACH_SRCFAIL: pc = "Source route failed"; break; case ICMP_UNREACH_NET_UNKNOWN: pc = "Unknown network"; break; case ICMP_UNREACH_HOST_UNKNOWN: pc = "Unknown host"; break; case ICMP_UNREACH_ISOLATED: pc = "Source host isolated"; break; case ICMP_UNREACH_NET_PROHIB: pc = "Net administratively prohibited"; break; case ICMP_UNREACH_HOST_PROHIB: pc = "Host administratively prohibited"; break; case ICMP_UNREACH_TOSNET: pc = "Net unreachable for this TOS"; break; case ICMP_UNREACH_TOSHOST: pc = "Host unreachable for this TOS"; break; case ICMP_UNREACH_FILTER_PROHIB: pc = "Communication administratively prohibited"; break; case ICMP_UNREACH_HOST_PRECEDENCE: pc = "Host precedence violation"; break; case ICMP_UNREACH_PRECEDENCE_CUTOFF: pc = "Precedence cutoff in effect"; break; default: break; } break; case ICMP_SOURCEQUENCH: pt = "Packet lost, slow down"; break; case ICMP_REDIRECT: pt = "Redirect"; switch (icmp->icmp_code) { case ICMP_REDIRECT_NET: pc = "for network"; break; case ICMP_REDIRECT_HOST: pc = "for host"; break; case ICMP_REDIRECT_TOSNET: pc = "for tos and net"; break; case ICMP_REDIRECT_TOSHOST: pc = "for tos and host"; break; default: break; } (void) sprintf(buff, "%s %s to %s", pc, addrtoname(AF_INET, &icmp->icmp_ip.ip_dst), addrtoname(AF_INET, &icmp->icmp_gwaddr)); pc = buff; break; case ICMP_ECHO: pt = "Echo request"; (void) sprintf(buff, "ID: %d Sequence number: %d", ntohs(icmp->icmp_id), ntohs(icmp->icmp_seq)); pc = buff; break; case ICMP_ROUTERADVERT: #define icmp_num_addrs icmp_hun.ih_rtradv.irt_num_addrs #define icmp_wpa icmp_hun.ih_rtradv.irt_wpa #define icmp_lifetime icmp_hun.ih_rtradv.irt_lifetime pt = "Router advertisement"; (void) sprintf(buff, "Lifetime %ds [%d]:", ntohs(icmp->icmp_lifetime), icmp->icmp_num_addrs); if (icmp->icmp_wpa == 2) { struct icmp_ra_addr *ra; char ra_buf[MAXHOSTNAMELEN + 32]; char ra_ext_buf[50]; struct in_addr sin; int icmp_ra_len; int i; /* Cannot trust anything from the network... */ num_rtr_addrs = MIN((ilen - ICMP_MINLEN) / 8, icmp->icmp_num_addrs); ra = (struct icmp_ra_addr *)icmp->icmp_data; for (i = 0; i < num_rtr_addrs; i++) { sin.s_addr = ra->addr; (void) snprintf(ra_buf, sizeof (ra_buf), " {%s %u}", addrtoname(AF_INET, &sin), ntohl(ra->preference)); if (strlcat(buff, ra_buf, sizeof (buff)) >= sizeof (buff)) { buff[sizeof (buff) - strlen("<Too Long>)")] = '\0'; (void) strlcat(buff, "<Too Long>", sizeof (buff)); break; } ra++; } icmp_ra_len = ICMP_MINLEN + num_rtr_addrs * sizeof (struct icmp_ra_addr); if (ilen > icmp_ra_len) { int curr_len = ilen - icmp_ra_len; int ocurr_len; exthdr_t *exthdr = (exthdr_t *)ra; extbuff[0] = '\0'; while (curr_len > 0) { /* Append Mobile-IP description */ (void) snprintf(ra_ext_buf, sizeof (ra_ext_buf), ", %s", get_mip_adv_desc(exthdr->type)); (void) strlcat(extbuff, ra_ext_buf, sizeof (extbuff)); /* Special case for padding */ if (exthdr->type == ICMP_ADV_MSG_PADDING_EXT) { curr_len--; exthdr = (exthdr_t *) ((char *)exthdr + 1); continue; } /* else normal extension */ ocurr_len = curr_len; curr_len -= sizeof (*exthdr) + exthdr->length; /* detect bad length */ if (ocurr_len < curr_len) break; exthdr = (exthdr_t *) ((char *)exthdr + sizeof (*exthdr) + exthdr->length); } px = extbuff; } pc = buff; } break; case ICMP_ROUTERSOLICIT: pt = "Router solicitation"; break; case ICMP_TIMXCEED: pt = "Time exceeded"; switch (icmp->icmp_code) { case ICMP_TIMXCEED_INTRANS: pc = "in transit"; break; case ICMP_TIMXCEED_REASS: pc = "in reassembly"; break; default: break; } break; case ICMP_PARAMPROB: pt = "IP parameter problem"; switch (icmp->icmp_code) { case ICMP_PARAMPROB_OPTABSENT: pc = "Required option missing"; break; case ICMP_PARAMPROB_BADLENGTH: pc = "Bad length"; break; case 0: /* Should this be the default? */ (void) sprintf(buff, "Problem at octet %d\n", icmp->icmp_pptr); pc = buff; default: break; } break; case ICMP_TSTAMP: pt = "Timestamp request"; break; case ICMP_TSTAMPREPLY: pt = "Timestamp reply"; break; case ICMP_IREQ: pt = "Information request"; break; case ICMP_IREQREPLY: pt = "Information reply"; break; case ICMP_MASKREQ: pt = "Address mask request"; break; case ICMP_MASKREPLY: pt = "Address mask reply"; (void) sprintf(buff, "Mask = 0x%x", ntohl(icmp->icmp_mask)); pc = buff; break; default: break; } if (flags & F_SUM) { line = get_sum_line(); if (*pc) { if (*px) { (void) sprintf(line, "ICMP %s (%s)%s", pt, pc, px); } else { (void) sprintf(line, "ICMP %s (%s)", pt, pc); } } else { (void) sprintf(line, "ICMP %s", pt); } } if (flags & F_DTAIL) { show_header("ICMP: ", "ICMP Header", ilen); show_space(); (void) sprintf(get_line(0, 0), "Type = %d (%s)", icmp->icmp_type, pt); if (*pc) { (void) sprintf(get_line(0, 0), "Code = %d (%s)", icmp->icmp_code, pc); } else { (void) sprintf(get_line(0, 0), "Code = %d", icmp->icmp_code); } (void) sprintf(get_line(0, 0), "Checksum = %x", ntohs(icmp->icmp_cksum)); if (icmp->icmp_type == ICMP_UNREACH || icmp->icmp_type == ICMP_REDIRECT) { if (ilen > 28) { show_space(); (void) sprintf(get_line(0, 0), "[ subject header follows ]"); show_space(); prot_nest_prefix = "ICMP:"; (void) interpret_ip(flags, (struct ip *)icmp->icmp_data, 28); prot_nest_prefix = ""; } } else if (icmp->icmp_type == ICMP_PARAMPROB) { if (ilen > 28) { show_space(); (void) sprintf(get_line(0, 0), "[ subject header follows ]"); show_space(); prot_nest_prefix = "ICMP:"; (void) interpret_ip(flags, (struct ip *)icmp->icmp_data, 28); prot_nest_prefix = ""; } } else if (icmp->icmp_type == ICMP_ROUTERADVERT) { if (icmp->icmp_wpa == 2) { int icmp_ra_len; show_space(); icmp_ra_len = ICMP_MINLEN + num_rtr_addrs * sizeof (struct icmp_ra_addr); prot_nest_prefix = ""; if (ilen > icmp_ra_len) { interpret_icmp_mip_ext( (uchar_t *)icmp + icmp_ra_len, ilen - icmp_ra_len); } } } show_space(); } }