Пример #1
0
void interpret_icmp_mip_ext(uchar_t *p, int len) {
	show_space();
	show_header("ICMP:  ", " MIP Advertisement Extensions ", len);
	show_space();

	interpret_extensions(p, len, ADV);
}
Пример #2
0
int
interpret_pppoe(int flags, poep_t *poep, int len)
{
	uint8_t code = poep->poep_code;
	uint8_t *payload;

	if (len < sizeof (poep_t))
		return (len);

	payload = (uint8_t *)poep + sizeof (poep_t);

	if (flags & F_SUM) {
		(void) sprintf(get_sum_line(), "PPPoE %s",
		    pppoe_codetoname(code, B_FALSE));
	} else { /* flags & F_DTAIL */
		show_header("PPPoE:  ", "PPP Over Ethernet", len);
		show_space();

		(void) sprintf(get_line(0, 0),
		    "Version = %d", POE_VERS(poep->poep_version_type));

		(void) sprintf(get_line(0, 0),
		    "Type = %d", POE_TYPE(poep->poep_version_type));

		(void) sprintf(get_line(0, 0),
		    "Code = %d (%s)", code, pppoe_codetoname(code, B_TRUE));

		(void) sprintf(get_line(0, 0),
		    "Session Id = %d", ntohs(poep->poep_session_id));

		(void) sprintf(get_line(0, 0),
		    "Length = %d bytes", ntohs(poep->poep_length));

		show_space();

		len -= sizeof (poep_t);
		len = MIN(len, ntohs(poep->poep_length));

		if (poep->poep_code != 0 && poep->poep_length > 0) {
			interpret_tags(payload, len);
		}
	}

	if (poep->poep_code == 0) {
		return (interpret_ppp(flags, payload, len));
	}
	return (len);
}
Пример #3
0
void MainWindow::show_tree(){           //expose all tree

    delete ui->treeWidget->takeTopLevelItem(0);
    show_space();
    if(getRoot() == NULL)   //if tree doesn`t exist
    {
        return;
    }
    QTreeWidgetItem * root_item = new QTreeWidgetItem(ui->treeWidget); //create item for expose tree

    space * wp = (space*)getRoot();
    root_item->setText(0,wp->name);
    star** star_array = (star**)wp->sublvl;

    int star_count = wp->sublvl_count;

    if(star_count == 0 || star_array == NULL)
    {
        return;
    }

    for(int i_star = 0;i_star < star_count;i_star++)
    {
        star * p_star = star_array[i_star];
        //expose star
        QTreeWidgetItem *s_item = new QTreeWidgetItem(root_item);
        s_item->setText(0,p_star->name);

        planet ** planet_array = (planet**)p_star->sublvl;
        int planet_count =  p_star->sublvl_count;

        if(planet_array == NULL || planet_count == 0)
        {
            continue;
        }

        for(int i_planet = 0;i_planet < planet_count;i_planet++)
        {
            planet * p_planet = planet_array[i_planet];
            //expose planet
            QTreeWidgetItem * p_item = new QTreeWidgetItem(s_item);
            p_item->setText(0,p_planet->name);

            satellite ** satellite_array = (satellite**)p_planet->sublvl;
            int satellite_count = p_planet->sublvl_count;

            if(satellite_array == NULL || satellite_count == 0)
            {
                continue;
            }
            for(int i_sat = 0; i_sat < satellite_count;i_sat++)
            {
                satellite * p_sat = satellite_array[i_sat];
                //expose satellite
                QTreeWidgetItem *sat_item = new QTreeWidgetItem(p_item);
                sat_item->setText(0,p_sat->name);
            }
        }
    }ui->treeWidget->expandAll();
}
Пример #4
0
void MainWindow::on_treeWidget_clicked(const QModelIndex &index)
{

    setButtonState(false,false);
    int lvl = selected_lvl();
    space * wp = (space*)getRoot();
    if(lvl == 0){
        show_space();

    }else if(lvl == 1){
        int index_s = selected_index(0);
        star * p_star = (star*)wp->sublvl[index_s];
        show_star(p_star);

    }else if(lvl == 2){
        int index_s = selected_index(1);
        star * p_star = (star*)wp->sublvl[index_s];

        int index_p = selected_index(0);
        planet * p_planet = (planet*)p_star->sublvl[index_p];
        show_planet(p_planet);

    }else if(lvl == 3){
        int index_s = selected_index(2);
        star * p_star = (star*)wp->sublvl[index_s];

        int index_p = selected_index(1);
        planet * p_planet = (planet*)p_star->sublvl[index_p];

        int index_sat = selected_index(0);
        satellite * p_sat = (satellite*)p_planet->sublvl[index_sat];
        show_satellite(p_sat);
    }
}
Пример #5
0
/*
 * interpret_tags() prints PPPoE Discovery Stage TAGs in detail.
 */
static void
interpret_tags(uint8_t *payload, uint16_t length)
{
	uint8_t *tagptr = payload;
	uint16_t tag_length;
	uint16_t tag_type;
	uint8_t *tag_value;
	taginfo_t *tinfo;

	while (length >= POET_HDRLEN) {
		tag_type = POET_GET_TYPE(tagptr);
		tag_length = POET_GET_LENG(tagptr);

		tinfo = pppoe_gettaginfo(tag_type);

		show_header("PPPoE:  ", tinfo->tag_name,
		    tag_length + POET_HDRLEN);

		(void) sprintf(get_line(0, 0),
		    "Tag Type = %d", tag_type);

		(void) sprintf(get_line(0, 0),
		    "Tag Length = %d bytes", tag_length);

		length -= POET_HDRLEN;
		if (tag_length > length) {
			(void) sprintf(get_line(0, 0),
			    "Warning: Truncated Packet");
			show_space();
			break;
		}

		/*
		 * unknown tags or tags which should always have 0 length
		 * are not interpreted any further.
		 */
		tag_value = POET_DATA(tagptr);
		if (tag_length != 0 && tinfo->interpret_tagvalue != NULL)
			tinfo->interpret_tagvalue(tag_value, tag_length);

		show_space();
		length -= tag_length;
		tagptr = POET_NEXT(tagptr);
	}
}
Пример #6
0
/* ARGSUSED */
int
interpret_esp(int flags, uint8_t *hdr, int iplen, int fraglen)
{
	/* LINTED: alignment */
	esph_t *esph = (esph_t *)hdr;
	esph_t *aligned_esph;
	esph_t storage;	/* In case hdr isn't aligned. */
	char *line;

	if (fraglen < sizeof (esph_t))
		return (fraglen);	/* incomplete header */

	if (!IS_P2ALIGNED(hdr, 4)) {
		aligned_esph = &storage;
		bcopy(hdr, aligned_esph, sizeof (esph_t));
	} else {
		aligned_esph = esph;
	}

	if (flags & F_SUM) {
		line = (char *)get_sum_line();
		/*
		 * sprintf() is safe because line guarantees us 80 columns,
		 * and SPI and replay certainly won't exceed that.
		 */
		(void) sprintf(line, "ESP SPI=0x%x Replay=%u",
		    ntohl(aligned_esph->esph_spi),
		    ntohl(aligned_esph->esph_replay));
		line += strlen(line);
	}

	if (flags & F_DTAIL) {
		show_header("ESP:  ", "Encapsulating Security Payload",
		    sizeof (esph_t));
		show_space();
		/*
		 * sprintf() is safe because get_line guarantees us 80 columns,
		 * and SPI and replay certainly won't exceed that.
		 */
		(void) sprintf(get_line((char *)&esph->esph_spi - dlc_header,
		    4), "SPI = 0x%x", ntohl(aligned_esph->esph_spi));
		(void) sprintf(get_line((char *)&esph->esph_replay -
		    dlc_header, 4), "Replay = %u",
		    ntohl(aligned_esph->esph_replay));
		(void) sprintf(get_line((char *)(esph + 1) - dlc_header,
		    4), "   ....ENCRYPTED DATA....");
	}

	return (sizeof (esph_t));
}
Пример #7
0
void
interpret_nbp(int flags, struct nbp_hdr *nbp, int len)
{
    uint8_t *data;
    int nbp_cnt = nbp->nbp_fun_cnt & 0xf; /* lower four bits */
    int nbp_op = (nbp->nbp_fun_cnt >> 4) & 0xf; /* upper four bits */

    data = (uint8_t *)(nbp + 1);

    if (flags & F_SUM) {
        if (len < sizeof (struct nbp_hdr)) {
            (void) snprintf(get_sum_line(), MAXLINE,
                            "NBP (short packet)");
            return;
        }
        (void) snprintf(get_sum_line(), MAXLINE,
                        "NBP F=%s CNT=%d ID=%d", nbp_short[nbp_op],
                        nbp_cnt, nbp->nbp_id);
    }

    if (flags & F_DTAIL) {
        show_header("NBP:  ", "NBP Header", len);
        show_space();

        if (len < sizeof (struct nbp_hdr)) {
            (void) snprintf(get_line(0, 0), get_line_remain(),
                            "NBP (short packet)");
            return;
        }
        (void) snprintf(get_line(0, 0), get_line_remain(),
                        "Length = %d", len);

        (void) snprintf(get_line(0, 0), get_line_remain(),
                        "Func = %d (%s)", nbp_op, nbp_short[nbp_op]);

        (void) snprintf(get_line(0, 0), get_line_remain(),
                        "Tuple count = %d", nbp_cnt);
        (void) snprintf(get_line(0, 0), get_line_remain(),
                        "Id = %d", nbp->nbp_id);
        show_nbp_tuples(data, nbp_cnt, ((uint8_t *)nbp) + len);
    }
}
Пример #8
0
void
interpret_aecho(int flags, struct ddp_hdr *ddp, int len)
{
	char *data;

	data = (char *)ddp + DDPHDR_SIZE;

	if (flags & F_SUM) {
		if (len < DDPHDR_SIZE + 1) {
			(void) snprintf(get_sum_line(), MAXLINE,
			    "AECHO (short packet)");
			return;
		}

		(void) snprintf(get_sum_line(), MAXLINE,
		    "AECHO F=%s LEN=%d",
		    *data == AEP_REQ ? "Request" : "Reply",
		    len);
	}

	if (flags & F_DTAIL) {
		if (len < DDPHDR_SIZE + 1) {
			(void) snprintf(get_line(0, 0), get_line_remain(),
			    "AECHO (short packet)");
			return;
		}

		show_header("AECHO:  ", "AECHO Header", len);
		show_space();

		(void) snprintf(get_line(0, 0), get_line_remain(),
		    "Func = %d (%s)",
		    data[0],
		    data[0] == AEP_REQ ? "Request" : "Reply");
		(void) snprintf(get_line(0, 0), get_line_remain(),
		    "Length = %d", len);
	}
}
Пример #9
0
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, &ether_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);
}
Пример #10
0
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, &ether_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);
}
Пример #11
0
int
interpret_rip6(int flags, struct rip6 *rip6, int fraglen)
{
	char *p;
	struct netinfo6 *n;
	int len, count;
	struct in6_addr *dst;
	int notdefault = 0;
	char dststr[INET6_ADDRSTRLEN];

	if (flags & F_SUM) {
		switch (rip6->rip6_cmd) {
		case RIPCMD6_REQUEST:	p = "C";		break;
		case RIPCMD6_RESPONSE:	p = "R";		break;
		default: p = "?"; break;
		}

		switch (rip6->rip6_cmd) {
		case RIPCMD6_REQUEST:
		case RIPCMD6_RESPONSE:
			len = fraglen - 4;
			count = 0;
			for (n = rip6->rip6_nets;
			    len >= sizeof (struct netinfo6); n++) {
				count++;
				len -= sizeof (struct netinfo6);
			}
			(void) sprintf(get_sum_line(),
			    "RIPng %s (%d destinations)", p, count);
			break;
		default:
			(void) sprintf(get_sum_line(), "RIPng %s", p);
			break;
		}
	}

	if (flags & F_DTAIL) {

		show_header("RIPng:  ", "Routing Information Protocol for IPv6",
		    fraglen);
		show_space();
		(void) sprintf(get_line((char *)(uintptr_t)rip6->rip6_cmd -
		    dlc_header, 1), "Opcode = %d (%s)", rip6->rip6_cmd,
		    show_cmd6(rip6->rip6_cmd));
		(void) sprintf(get_line((char *)(uintptr_t)rip6->rip6_vers -
		    dlc_header, 1), "Version = %d", rip6->rip6_vers);

		switch (rip6->rip6_cmd) {
		case RIPCMD6_REQUEST:
		case RIPCMD6_RESPONSE:
			show_space();
			(void) sprintf(get_line(0, 0), "Address"
			    "                       Prefix        Metric");
			len = fraglen - 4;
			for (n = rip6->rip6_nets;
			    len >= sizeof (struct netinfo6); n++) {
				if (rip6->rip6_vers > 0) {
					n->rip6_metric = n->rip6_metric;
				}
				dst = &n->rip6_prefix;
				notdefault = bcmp((caddr_t *)dst,
				    (caddr_t *)&all_zeroes_addr, sizeof (*dst));
				(void) inet_ntop(AF_INET6, (char *)dst, dststr,
				    INET6_ADDRSTRLEN);
				(void) sprintf(get_line((char *)n - dlc_header,
				    sizeof (struct netinfo6)),
				    "%-30s %-10d     %-5d %s",
				    notdefault ? dststr :
				    " (default)", n->rip6_prefix_length,
				    n->rip6_metric, n->rip6_metric == 16 ?
				    " (not reachable)":"");
				len -= sizeof (struct netinfo);
			}
			break;
		}
	}
	return (fraglen);
}
Пример #12
0
/*ARGSUSED*/
void
interpret_igmp(int flags, char *data, int iplen, int ilen)
{
	const char *pt;
	char *line;
	struct igmp *igmp = (struct igmp *)data;
	char addrstr[INET_ADDRSTRLEN];

	if (ilen < IGMP_MINLEN) {
		/* incomplete header */
		line = get_sum_line();
		(void) snprintf(line, MAXLINE, "Malformed IGMP packet");
		return;
	}

	switch (igmp->igmp_type) {
	case IGMP_MEMBERSHIP_QUERY:
		if (ilen == IGMP_MINLEN) {
			if (igmp->igmp_code == 0)
				pt = "v1 membership query";
			else
				pt = "v2 membership query";
		} else if (ilen >= IGMP_V3_QUERY_MINLEN) {
			pt = "v3 membership query";
		} else {
			pt = "Unknown membership query";
		}
		break;
	case IGMP_V1_MEMBERSHIP_REPORT:
		pt = "v1 membership report";
		break;
	case IGMP_V2_MEMBERSHIP_REPORT:
		pt = "v2 membership report";
		break;
	case IGMP_V3_MEMBERSHIP_REPORT:
		pt = "v3 membership report";
		break;
	case IGMP_V2_LEAVE_GROUP:
		pt = "v2 leave group";
		break;

	default:
		pt = "Unknown";
		break;
	}

	if (flags & F_SUM) {
		line = get_sum_line();
		(void) snprintf(line, MAXLINE, "IGMP %s", pt);
	}

	if (flags & F_DTAIL) {
		show_header("IGMP:  ", "IGMP Header", ilen);
		show_space();
		(void) snprintf(get_line(0, 0), get_line_remain(),
		    "Type = %d (%s)", igmp->igmp_type, pt);
		(void) snprintf(get_line(0, 0), get_line_remain(),
		    "Max Response Time = %d", igmp->igmp_code);
		(void) snprintf(get_line(0, 0), get_line_remain(),
		    "Checksum = %x", ntohs(igmp->igmp_cksum));

		if (igmp->igmp_type == IGMP_MEMBERSHIP_QUERY &&
		    ilen >= IGMP_V3_QUERY_MINLEN) {
			interpret_igmpv3qry(igmp, ilen);
		} else if (igmp->igmp_type == IGMP_V3_MEMBERSHIP_REPORT) {
			interpret_igmpv3rpt(igmp, ilen);
		} else {
			(void) snprintf(get_line(0, 0), get_line_remain(),
			    "Group = %s",
			    inet_ntop(AF_INET, &igmp->igmp_group.s_addr,
			    addrstr, INET_ADDRSTRLEN));
		}

		show_space();
	}
}
Пример #13
0
void
interpret_mip_cntrlmsg(int flags, uchar_t *msg, int fraglen) {
	char		*pt, *pc = NULL;
	char		*line;
	regreq_t	rreq[1];
	regrep_t	rrep[1];
	int		regext_size;
	uchar_t		*regext_data;
	struct in_addr	addr_temp;


	/* First byte of the message should be the type */
	switch (*msg) {
	case REG_TYPE_REQ:
		if (fraglen < sizeof (regreq_t))
			return;
		pt = (flags & F_DTAIL ? "registration request ":"reg rqst ");

		(void) memcpy(rreq, msg, sizeof (*rreq));
		regext_size = fraglen - sizeof (regreq_t);
		regext_data = msg + sizeof (*rreq);
		break;
	case REG_TYPE_REP:
		if (fraglen < sizeof (regrep_t))
			return;
		pt = (flags & F_DTAIL ? "registration reply ":"reg reply ");

		(void) memcpy(rrep, msg, sizeof (*rrep));
		regext_size = fraglen - sizeof (regrep_t);
		regext_data = msg + sizeof (*rrep);

		switch (rrep->code) {
		case  REPLY_CODE_ACK:
			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL)) ?
			    "OK" : "OK code 0";
			break;
		case  REPLY_CODE_ACK_NO_SIMULTANEOUS:
			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
			    "OK simultaneous bindings" : "OK code 1";
			break;
		case  REPLY_CODE_FA_NACK_UNSPECIFIED:
			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
			    "FA denial: unspecified":"FA denial: code 64";
			break;
		case  REPLY_CODE_FA_NACK_PROHIBITED:
			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
			    "FA denial: prohibited":"FA denial: code 65";
			break;
		case  REPLY_CODE_FA_NACK_RESOURCES:
			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
			    "FA denial: no resources":"FA denial: code 66";
			break;
		case  REPLY_CODE_FA_NACK_MN_AUTH:
			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
			    "FA denial: MN auth failed":"FA denial: code 67";
			break;
		case  REPLY_CODE_FA_NACK_HA_AUTH:
			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
			    "FA denial: HA auth failed":
			    "FA denial: code 68";
			break;
		case  REPLY_CODE_FA_NACK_LIFETIME:
			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
			    "FA denial: lifetime":"FA denial: code 69";
			break;
		case  REPLY_CODE_FA_NACK_BAD_REQUEST:
			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
			    "FA denial: bad request": "FA: code 70";
			break;
		case  REPLY_CODE_FA_NACK_BAD_REPLY:
			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
			    "FA denial: bad Reply":"FA denial: code 71";
			break;
		case  REPLY_CODE_FA_NACK_ENCAP_UNAVAILABLE:
			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
			    "FA denial: encapsulation":"FA denial: code 72";
			break;
		case  REPLY_CODE_FA_NACK_VJ_UNAVAILABLE:
			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
			    "FA denial: VJ compression":"FA denial: code 73";
			break;
		case  REPLY_CODE_FA_NACK_BIDIR_TUNNEL_UNAVAILABLE:
			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
			    "FA denial: reverse tunnel unavailable":
				"FA denial: code 74";
			break;
		case  REPLY_CODE_FA_NACK_BIDIR_TUNNEL_NO_TBIT:
			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
			    "FA denial: reverse tunnel: missing T-bit":
				"FA denial: code 75";
			break;
		case  REPLY_CODE_FA_NACK_BIDIR_TUNNEL_TOO_DISTANT:
			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
			    "FA denial: reverse tunnel: too distant":
				"FA denial: code 76";
			break;
		case  REPLY_CODE_FA_NACK_ICMP_HA_NET_UNREACHABLE:
			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
			    "FA denial: home network unreachable":
			    "FA denial: code 80";
			break;
		case  REPLY_CODE_FA_NACK_ICMP_HA_HOST_UNREACHABLE:
			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
			    "FA denial: HA host unreachable":
			    "FA denial: code 81";
			break;
		case  REPLY_CODE_FA_NACK_ICMP_HA_PORT_UNREACHABLE:
			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
			    "FA denial: HA port unreachable":
			    "FA denial: code 82";
			break;
		case  REPLY_CODE_FA_NACK_ICMP_HA_UNREACHABLE:
			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
			    "FA denial: HA unreachable":"FA denial: code 88";
			break;
		case REPLY_CODE_FA_NACK_UNIQUE_HOMEADDR_REQD:
			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
			    "FA denial: Unique Home Addr Required":
				"FA denial: code 96";
			break;
		case REPLY_CODE_FA_NACK_MISSING_NAI:
			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
			    "FA denial: Missing NAI":
				"FA denial: code 97";
			break;
		case REPLY_CODE_FA_NACK_MISSING_HOME_AGENT:
			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
			    "FA denial: Missing Home Agent":
				"FA denial: code 98";
			break;
		case REPLY_CODE_FA_NACK_UNKNOWN_CHALLENGE:
			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
			    "FA denial: Unknown Challenge":
				"FA denial: code 104";
			break;
		case REPLY_CODE_FA_NACK_MISSING_CHALLENGE:
			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
			    "FA denial: Missing Challenge":
				"FA denial: code 105";
			break;
		case REPLY_CODE_FA_NACK_MISSING_MN_FA:
			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
			    "FA denial: Missing Mobile-Foreign Key Extension":
				"FA denial: code 106";
			break;
		case  REPLY_CODE_HA_NACK_UNSPECIFIED:
			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
			    "HA denial: unspecified":"HA denial: code 128";
			break;
		case  REPLY_CODE_HA_NACK_PROHIBITED:
			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
			    "HA denial: prohibited":"HA denial: code 129";
			break;
		case  REPLY_CODE_HA_NACK_RESOURCES:
			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
			    "HA denial: no resources":"HA denial: code 130";
			break;
		case  REPLY_CODE_HA_NACK_MN_AUTH:
			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
			    "HA denial: MN auth failed":"HA denial: code 131";
			break;
		case  REPLY_CODE_HA_NACK_FA_AUTH:
			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
			    "HA denial: FA auth failed":"HA denial: code 132";
			break;
		case  REPLY_CODE_HA_NACK_ID_MISMATCH:
			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
			    "HA denial: ID mismatch":"HA denial: code 133";
			break;
		case  REPLY_CODE_HA_NACK_BAD_REQUEST:
			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
			    "HA denial: bad request":"HA denial: code 134";
			break;
		case  REPLY_CODE_HA_NACK_TOO_MANY_BINDINGS:
			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
			    "HA denial: too many bindings":
			    "HA denial: code 135";
			break;
		case  REPLY_CODE_HA_NACK_BAD_HA_ADDRESS:
			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
			    "HA denial: bad HA address":"HA denial: code 136";
			break;
		case  REPLY_CODE_HA_NACK_BIDIR_TUNNEL_UNAVAILABLE:
			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
			    "HA denial: no reverse tunnel":
			    "HA denial: code 137";
			break;
		case  REPLY_CODE_HA_NACK_BIDIR_TUNNEL_NO_TBIT:
			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
			    "HA denial: reverse tunnel: no T-bit":
			    "HA denial: code 138";
			break;
		case  REPLY_CODE_HA_NACK_BIDIR_ENCAP_UNAVAILABLE:
			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
			    "HA denial: encapsulation unavailable":
			    "HA denial: code 139";
			break;
		default:
			pc = "?";
			break;
		}
		break;

	default :
		break;
	}
	if (flags & F_SUM) {
		line = get_sum_line();

		if (pc != NULL)
			(void) sprintf(line, "Mobile IP %s(%s)", pt, pc);
		else
			(void) sprintf(line, "Mobile IP %s", pt);
	}

	if (flags & F_DTAIL) {
		show_header("MIP:  ", "Mobile IP Header", fraglen);
		show_space();

		if (*msg == REG_TYPE_REQ) {
			(void) sprintf(get_line((char *)&rreq -
			    dlc_header, 1), "Registration header type = %s",
			    pt);
			(void) sprintf(get_line(
			    (char *)(((uchar_t *)&rreq) + 1) - dlc_header, 1),
			    "%d... .... = %s simultaneous bindings  ",
			    (rreq->Simultaneous_registration == 1)? 1 : 0,
			    (rreq->Simultaneous_registration == 1)? "":"no");
			(void) sprintf(get_line(
			    (char *)(((uchar_t *)&rreq) + 1) - dlc_header, 1),
			    ".%d.. .... = %s broadcast datagrams ",
			    (rreq->Broadcasts_desired == 1) ?  1 : 0,
			    (rreq->Broadcasts_desired == 1) ? "":"no");
			(void) sprintf(get_line(
			    (char *)(((uchar_t *)&rreq) + 1) - dlc_header, 1),
			    "..%d. .... = %s decapsulation by MN",
			    (rreq->Decapsulation_done_locally == 1) ? 1 : 0,
			    (rreq->Decapsulation_done_locally == 1) ?
				"" : "no");
			(void) sprintf(get_line(
			    (char *)(((uchar_t *)&rreq) + 1) - dlc_header, 1),
			    "...%d .... = %s minimum encapsulation ",
			    (rreq->Minimal_encap_desired == 1) ? 1 : 0,
			    (rreq->Minimal_encap_desired == 1) ? "" : "no");
			(void) sprintf(get_line(
			    (char *)(((uchar_t *)&rreq) + 1) - dlc_header, 1),
			    ".... %d... = %s GRE encapsulation ",
			    (rreq->GRE_encap_desired == 1) ? 1 : 0,
			    (rreq->GRE_encap_desired == 1) ? "" : "no");
			(void) sprintf(get_line(
			    (char *)(((uchar_t *)&rreq) + 1) - dlc_header, 1),
			    ".... .%d.. = %s VJ hdr Compression ",
			    (rreq->VJ_compression_desired == 1) ? 1 : 0,
			    (rreq->VJ_compression_desired == 1) ? "" : "no");
			(void) sprintf(get_line(
			    (char *)(((uchar_t *)&rreq) + 1) - dlc_header, 1),
			    ".... ..%d. = %s reverse tunnel",
			    (rreq->BiDirectional_Tunnel_desired == 1) ? 1 : 0,
			    (rreq->BiDirectional_Tunnel_desired == 1) ?
				"" : "no");
			if (ntohs(rreq->lifetime) == 0xffff) {
				(void) sprintf(get_line(
				    (char *)&rreq->lifetime - dlc_header, 1),
				    "Life Time = 0xFFFF (infinity)");
			} else if (ntohs(rreq->lifetime) == 0) {
				(void) sprintf(get_line(
				    (char *)&rreq->lifetime - dlc_header, 1),
				    "Life Time = 0 "
				    "(request for de-registration)");
			} else {
				(void) sprintf(get_line(
				    (char *)&rreq->lifetime - dlc_header, 1),
				    "Life time = %d seconds",
				    ntohs(rreq->lifetime));
			}
			addr_temp.s_addr = rreq->home_addr;
			(void) sprintf(get_line(
			    (char *)&rreq->home_addr - dlc_header, 1),
			    "Home address = %s, %s",
			    inet_ntoa(addr_temp),
			    addrtoname(AF_INET, &addr_temp));
			addr_temp.s_addr = rreq->home_agent_addr;
			(void) sprintf(get_line(
			    (char *)&rreq->home_agent_addr - dlc_header, 1),
			    "Home Agent address = %s, %s",
			    inet_ntoa(addr_temp),
			    addrtoname(AF_INET, &addr_temp));
			addr_temp.s_addr = rreq->care_of_addr;
			(void) sprintf(get_line(
			    (char *)&rreq->care_of_addr - dlc_header, 1),
			    "Care of address = %s, %s",
			    inet_ntoa(addr_temp),
			    addrtoname(AF_INET, &addr_temp));
			(void) sprintf(get_line(
			    (char *)&rreq->identification - dlc_header, 1),
			    "Identification = 0x%x-%x",
			    ntohl(rreq->identification.high_bits),
			    ntohl(rreq->identification.low_bits));
		} else if (*msg == REG_TYPE_REP) {
			(void) sprintf(
			    get_line((char *)&rrep->type - dlc_header, 1),
			    "Registration header type = %d (%s)",
			    (int)rrep->type, pt);
			(void) sprintf(get_line((char *)&rrep - dlc_header, 1),
			    "Code = %d %s", (int)rrep->code, pc);
			if (ntohs(rrep->lifetime) == 0xffff) {
				(void) sprintf(get_line(
				    (char *)&rrep->lifetime - dlc_header, 1),
				    "Life time = 0xFFFF (infinity)");
			} else if (ntohs(rrep->lifetime) == 0) {
				(void) sprintf(get_line(
				    (char *)&rrep->lifetime - dlc_header, 1),
				    ((rrep->code == REPLY_CODE_ACK) ||
				    (rrep->code ==
					REPLY_CODE_ACK_NO_SIMULTANEOUS))?
				    "Life time = 0 (de-registeration success)" :
				    "Life time = 0 (de-registration failed)");
			} else {
				(void) sprintf(get_line(
				    (char *)&rrep->lifetime - dlc_header, 1),
				    "Life time = %d seconds",
				    ntohs(rrep->lifetime));
			}
			addr_temp.s_addr = rrep->home_addr;
			(void) sprintf(
			    get_line((char *)&rrep->home_addr - dlc_header, 1),
			    "Home address = %s, %s",
			    inet_ntoa(addr_temp),
			    addrtoname(AF_INET, &addr_temp));
			addr_temp.s_addr = rrep->home_agent_addr;
			(void) sprintf(get_line(
			    (char *)&rrep->home_agent_addr - dlc_header, 1),
			    "Home Agent address = %s, %s",
			    inet_ntoa(addr_temp),
			    addrtoname(AF_INET, &addr_temp));
			(void) sprintf(get_line(
			    (char *)&rrep->identification - dlc_header, 1),
			    "Identification = 0x%x-%x",
			    ntohl(rrep->identification.high_bits),
			    ntohl(rrep->identification.low_bits));
		}
		fraglen = interpret_extensions(regext_data, regext_size, REG);
	}
}
Пример #14
0
/*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();
	}
}
Пример #15
0
static int v1_header(int flags,
			struct slpv1_hdr *slp,
			int fraglen) {
	extern int src_port, dst_port, curr_proto;
	char *prototag = (curr_proto == IPPROTO_TCP? "/tcp" : "");

	if (flags & F_SUM) {
	    char portflag = ' ';

	    if (msglength < sizeof (*slp)) {
		sprintf(msgbuf, "SLP V1 [incomplete header]");
		return (0);
	    }

	    if (slp->vers != 1) {
		if (curr_proto == IPPROTO_TCP)
		    sprintf(msgbuf, "SLP [TCP Continuation]");
		else
		    sprintf(msgbuf, "SLP [unknown version %d]", slp->vers);
		return (0);
	    }

	    if (src_port != 427 && dst_port != 427)
		portflag = '-';

	    sprintf(msgbuf, "SLP V1%c%s [%d%s] ", portflag,
		    slpv1_func(slp->function, B_TRUE),
		    ntohs(slp->xid), prototag);
	    msgend = msgbuf + strlen(msgbuf);
	    msglength -= sizeof (*slp);
	    p += sizeof (*slp);
	} else if (flags & F_DTAIL) {
	    show_header("SLP:  ", "Service Location Protocol (v1)", fraglen);
	    show_space();

	    if (msglength < sizeof (*slp)) {
		sprintf(get_line(0, 0), "==> Incomplete SLP header");
		return (0);
	    }

	    sprintf(get_line(0, 0), "Version = %d", slp->vers);
	    if (slp->vers != 1) {
		if (curr_proto == IPPROTO_TCP)
		    sprintf(get_line(0, 0), "==> TCP continuation");
		else
		    sprintf(get_line(0, 0), "==> Unexpected version number");
		return (0);
	    }
	    sprintf(get_line(0, 0), "Function = %d, %s",
		slp->function, slpv1_func(slp->function, B_FALSE));
	    sprintf(get_line(0, 0), "Message length = %u", ntohs(slp->length));

	    /* flags */
	    sprintf(get_line(0, 0), "Flags = 0x%02x", slp->flags);
	    sprintf(get_line(0, 0), "      %s",
		    getflag(slp->flags, V1_OVERFLOW,
			    "overflow", "no overflow"));
	    sprintf(get_line(0, 0), "      %s",
		    getflag(slp->flags, V1_MONOLINGUAL,
			    "monolingual", "not monolingual"));
	    sprintf(get_line(0, 0), "      %s",
		    getflag(slp->flags, V1_URL_AUTH,
			    "url authentication", "no url authentication"));
	    sprintf(get_line(0, 0), "      %s",
		    getflag(slp->flags, V1_ATTR_AUTH,
		"attribute authentication", "no attribute authentication"));
	    sprintf(get_line(0, 0), "      %s",
		    getflag(slp->flags, V1_FRESH_REG,
			    "fresh registration", "no fresh registration"));
	    /* check reserved flags that must be zero */
	    if ((slp->flags & 7) != 0) {
		sprintf(get_line(0, 0),
			"      .... .xxx = %d (reserved flags nonzero)",
			slp->flags & 7);
	    }
	    /* end of flags */

	    sprintf(get_line(0, 0), "Dialect = %u", slp->dialect);
	    sprintf(get_line(0, 0), "Language = 0x%02x%02x, %c%c",
		    slp->language[0], slp->language[1],
		    slp->language[0], slp->language[1]);
	    v1_charset = ntohs(slp->charset);
	    sprintf(get_line(0, 0), "Character encoding = %u, %s",
		    v1_charset,
		    slpv1_charset(v1_charset));
	    sprintf(get_line(0, 0), "XID = %u", ntohs(slp->xid));

	    /* set msglength to remaining length of SLP message */
	    msglength -= sizeof (*slp);
	    p += sizeof (*slp);
	}

	return (1);
}
Пример #16
0
int
interpret_rpc(int flags, char *rpc, int fraglen, int type)
{
	ulong_t xid;
	int direction;
	struct cache_struct *x;
	int rpcvers, prog, vers, proc;
	int status, astat, rstat, why;
	char *lp;
	unsigned recmark;
	int markpos;
	extern int pi_frame;
	int lo, hi;

	xdr_init(rpc, fraglen);

	if (setjmp(xdr_err)) {
		if (flags & F_DTAIL)
			(void) sprintf(get_line(0, 0),
				"----  short frame ---");
		return (fraglen);
	}

	if (type == IPPROTO_TCP) {	/* record mark */
		markpos = getxdr_pos();
		recmark = getxdr_long();
	}

	xid	  = getxdr_u_long();
	direction = getxdr_long();

	if (direction == CALL) {
		rpcvers = getxdr_long();
		pos = getxdr_pos();
		prog = getxdr_long();
		vers = getxdr_long();
		proc = getxdr_long();
		stash_xid(xid, pi_frame, prog, vers, proc);
		if (!(flags & (F_SUM | F_DTAIL)))
			protoprint(flags, CALL, xid, prog, vers, proc,
				rpc, fraglen);
	} else {
		x = find_xid(xid);
	}

	if (flags & F_SUM) {
		switch (direction) {
		case CALL:
			(void) sprintf(get_sum_line(),
				"RPC C XID=%lu PROG=%d (%s) VERS=%d PROC=%d",
				xid,
				prog, nameof_prog(prog),
				vers, proc);
			if (getxdr_long() == RPCSEC_GSS) { /* Cred auth type */
				extract_rpcsec_gss_cred_info(xid);
				/* RPCSEC_GSS cred auth data */
			} else {
				xdr_skip(getxdr_long());
				/* non RPCSEC_GSS cred auth data */
			}
			xdr_skip(4);			/* Verf auth type */
			xdr_skip(RNDUP(getxdr_long()));	/* Verf auth data */

			protoprint(flags, CALL, xid, prog, vers, proc,
				rpc, fraglen);
			break;

		case REPLY:
			lp = get_sum_line();
			if (x == NULL)
				(void) sprintf(lp, "RPC R XID=%lu", xid);
			else
				(void) sprintf(lp, "RPC R (#%d) XID=%lu",
					x->xid_frame, xid);

			lp += strlen(lp);
			status = getxdr_long();
			switch (status) {
			case MSG_ACCEPTED:
				/* eat flavor and verifier */
				(void) getxdr_long();
				xdr_skip(RNDUP(getxdr_long()));
				astat = getxdr_long();
				(void) sprintf(lp, " %s",
					nameof_astat(astat));
				lp += strlen(lp);

				switch (astat) {
				case SUCCESS:
					if (x) {
						protoprint(flags, REPLY,
							xid,
							x->xid_prog,
							x->xid_vers,
							x->xid_proc,
							rpc, fraglen);
					}
					break;

				case PROG_UNAVAIL :
				case PROG_MISMATCH:
				case PROC_UNAVAIL :
					lo = getxdr_long();
					hi = getxdr_long();
					(void) sprintf(lp,
						" (low=%d, high=%d)",
						lo, hi);
					break;

				case GARBAGE_ARGS:
				case SYSTEM_ERR:
				default:
					;
				}
				break;

			case MSG_DENIED:
				rstat = getxdr_long();

				switch (rstat) {
				case RPC_MISMATCH:
					lo = getxdr_long();
					hi = getxdr_long();
					(void) sprintf(lp,
					" Vers mismatch (low=%d, high=%d)",
						lo, hi);
					break;

				case AUTH_ERROR:
					why = getxdr_u_long();
					(void) sprintf(lp,
						" Can't authenticate (%s)",
						nameof_why(why));
					break;
				}
			}
			break;
		}
	}

	if (flags & F_DTAIL) {
		show_header("RPC:  ", "SUN RPC Header", fraglen);
		show_space();
		if (type == IPPROTO_TCP) {	/* record mark */
			(void) sprintf(get_line(markpos, markpos+4),
				"Record Mark: %s fragment, length = %d",
				recmark & LAST_FRAG ? "last" : "",
				recmark & ~LAST_FRAG);
		}

		(void) sprintf(get_line(0, 0),
			"Transaction id = %lu",
			xid);
		(void) sprintf(get_line(0, 0),
			"Type = %d (%s)",
			direction,
			direction == CALL ? "Call":"Reply");

		switch (direction) {
		case CALL:
			rpc_detail_call(flags, xid, rpcvers,
				prog, vers, proc, rpc, fraglen);
			break;
		case REPLY:
			rpc_detail_reply(flags, xid, x, rpc, fraglen);
			break;
		}
	}

	return (fraglen);
}
Пример #17
0
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, &ether_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);
}
Пример #18
0
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);
}
Пример #19
0
int
interpret_udp(int flags, struct udphdr *udp, int iplen, int fraglen)
{
	char *data;
	int udplen;
	int sunrpc;
	char *pname;
	char buff [32];

	if (fraglen < sizeof (struct udphdr))
		return (fraglen);	/* incomplete header */

	data = (char *)udp + sizeof (struct udphdr);
	udplen = ntohs((ushort_t)udp->uh_ulen) - sizeof (struct udphdr);
	fraglen -= sizeof (struct udphdr);
	if (fraglen > udplen)
		fraglen = udplen;

	if (flags & F_SUM) {
		(void) sprintf(get_sum_line(),
			"UDP D=%d S=%d LEN=%d",
			ntohs(udp->uh_dport),
			ntohs(udp->uh_sport),
			ntohs((ushort_t)udp->uh_ulen));
	}

	sunrpc = !reservedport(IPPROTO_UDP, ntohs(udp->uh_dport)) &&
		!reservedport(IPPROTO_UDP, ntohs(udp->uh_sport)) &&
		valid_rpc(data, udplen);

	if (flags & F_DTAIL) {
		show_header("UDP:  ", "UDP Header", udplen);
		show_space();
		(void) sprintf(get_line((char *)(uintptr_t)udp->uh_sport -
		    dlc_header, 1), "Source port = %d", ntohs(udp->uh_sport));

		if (sunrpc) {
			pname = "(Sun RPC)";
		} else {
			pname = getportname(IPPROTO_UDP, ntohs(udp->uh_dport));
			if (pname == NULL) {
				pname = "";
			} else {
				(void) sprintf(buff, "(%s)", pname);
				pname = buff;
			}
		}
		(void) sprintf(get_line((char *)(uintptr_t)udp->uh_dport -
		    dlc_header, 1), "Destination port = %d %s",
		    ntohs(udp->uh_dport), pname);
		(void) sprintf(get_line((char *)(uintptr_t)udp->uh_ulen -
		    dlc_header, 1), "Length = %d %s",
		    ntohs((ushort_t)udp->uh_ulen),
		    udplen > fraglen ?
			"(Not all data contained in this fragment)"
			: "");
		    (void) sprintf(get_line((char *)(uintptr_t)udp->uh_sum -
			dlc_header, 1),	"Checksum = %04X %s",
			ntohs(udp->uh_sum),
			udp->uh_sum == 0 ? "(no checksum)" : "");
		show_space();
	}


	/* go to the next protocol layer */

	if (!interpret_reserved(flags, IPPROTO_UDP,
		ntohs(udp->uh_sport),
		ntohs(udp->uh_dport),
		data, fraglen)) {
		if (fraglen > 0 && sunrpc)
			interpret_rpc(flags, data, fraglen, IPPROTO_UDP);
	}

	return (fraglen);
}
Пример #20
0
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);
}
Пример #21
0
static int
interpret_extensions(uchar_t *ext,
			int regext_size,
			enum EXT_TYPE etype) {

	int curr_size  =  regext_size; /* remaining total for all exts */
	exthdr_t *exthdr;
	gen_exthdr_t *gen_exthdr;
	const char *st;
	uchar_t	*p;
	interpreter_f *f;
	uint8_t	ext_type;
	uint16_t ext_len;
	uint_t ext_hdrlen;

	show_space();
	exthdr = (exthdr_t *)ALIGN(ext);


	do {
	    ext_type = exthdr->type;
	    if (ext_type == GEN_AUTH) {
		gen_exthdr = (gen_exthdr_t *)exthdr;
		ext_hdrlen = sizeof (gen_exthdr_t);
		ext_len = ntohs(gen_exthdr->length);
	    } else {
		ext_hdrlen = sizeof (exthdr_t);
		ext_len = exthdr->length;
	    }

	    if (!((etype == ADV && ext_type == ICMP_ADV_MSG_PADDING_EXT &&
		curr_size >= 1) ||
		curr_size >= ext_hdrlen + ext_len))
		    break;

	    /* Print description for this extension */
	    if (etype == ADV) {
		st = get_desc(adv_desc, ext_type, ADV_TBL_LEN);
	    } else /* REG */ {
		st = get_desc(reg_desc, ext_type, REG_TBL_LEN);
	    }

	    (void) sprintf(get_line((char *)exthdr-dlc_header, 1),
			"Extension header type = %d  %s", ext_type, st);

	    if (ext_type == GEN_AUTH) {
		st = get_desc(genauth_desc, gen_exthdr->subtype,
		    GENAUTH_TBL_LEN);
		(void) sprintf(get_line((char *)exthdr-dlc_header, 1),
		    "Subtype = %d %s", gen_exthdr->subtype, st);
	    }

	    /* Special case for 1-byte padding */
	    if (etype == ADV && ext_type == ICMP_ADV_MSG_PADDING_EXT) {
		exthdr = (exthdr_t *)((uchar_t *)exthdr + 1);
		curr_size--;
		continue;
	    }

	    (void) sprintf(get_line((char *)&exthdr->length-dlc_header, 1),
			"Length = %d", ext_len);

	    /* Parse out the extension's payload */
	    p = (uchar_t *)exthdr + ext_hdrlen;
	    curr_size -= (ext_hdrlen + ext_len);

	    if (etype == ADV) {
		f = get_interpreter(adv_dispatch, ext_type, ADV_TBL_LEN);
	    } else /* REG */ {
		f = get_interpreter(reg_dispatch, ext_type, REG_TBL_LEN);
	    }

	    f(ext_type, ext_len, p);

	    show_space();
	    exthdr = (exthdr_t *)(p + ext_len);
	} while (B_TRUE);

	return (0);
}
Пример #22
0
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);
}
Пример #23
0
static int v2_header(int flags,
			struct slpv2_hdr *slp,
			int *totallen,
			int fraglen) {
	extern int curr_proto, dst_port;
	char *prototag = (curr_proto == IPPROTO_TCP ? "/tcp" : "");

	if ((slp->flags & V2_OVERFLOW) == V2_OVERFLOW)
	    overflow = B_TRUE;

	/* summary mode header parsing */
	if (flags & F_SUM) {

	    /* make sure we have at least a header */
	    if (msglength < sizeof (*slp)) {
		sprintf(get_sum_line(), "SLP V2 [Incomplete Header]");
		return (0);
	    }

	    sprintf(msgbuf, "SLP V2 %s [%d%s] ",
		    slpv2_func(slp->function, B_TRUE),
		    ntohs(slp->xid), prototag);

	    /* skip to end of header */
	    msgend = msgbuf + strlen(msgbuf);
	    msglength -= sizeof (*slp);
	    p += sizeof (*slp);

	    /* skip language tag */
	    SKIPFIELD(FIELD_DEFAULT);
	} else if (flags & F_DTAIL) {
	    char *lang;
	    int len;

	    /* detailed mode header parsing */
	    show_header("SLP:  ", "Service Location Protocol (v2)", fraglen);
	    show_space();

	    if (msglength < sizeof (*slp)) {
		sprintf(get_line(0, 0), "==> Incomplete SLP header");
		return (0);
	    }

	    sprintf(get_line(0, 0), "Version = %d", slp->vers);
	    sprintf(get_line(0, 0), "Function = %d, %s",
		    slp->function, slpv2_func(slp->function, B_FALSE));
	    get_int24(&(slp->l1));
	    *totallen = netval;
	    sprintf(get_line(0, 0), "Message length = %u", *totallen);
	    /* check for TCP continuation */
	    if (curr_proto == IPPROTO_TCP &&
		*totallen > msglength &&
		!tcp_continuation) {
		tcp_continuation = B_TRUE;
		reg_tcp_cont((char *)slp, *totallen, msglength, dst_port);
	    }

	    if (!tcp_continuation && *totallen != msglength) {
		sprintf(get_line(0, 0),
			"  (Stated and on-the-wire lengths differ)");
	    }
	    /* flags */
	    sprintf(get_line(0, 0), "Flags = 0x%02x", slp->flags);
	    sprintf(get_line(0, 0), "      %s",
		    getflag(slp->flags, V2_OVERFLOW,
			    "overflow", "no overflow"));
	    sprintf(get_line(0, 0), "      %s",
		    getflag(slp->flags, V2_FRESH,
			    "fresh registration", "no fresh registration"));
	    sprintf(get_line(0, 0), "      %s",
		    getflag(slp->flags, V2_MCAST,
			    "request multicast / broadcast", "unicast"));
	    /* check reserved flags that must be zero */
	    if ((slp->flags & 7) != 0) {
		sprintf(get_line(0, 0),
			"      .... .xxx = %d (reserved flags nonzero)",
			slp->flags & 7);
	    }
	    /* end of flags */

	    /* language tag */
	    p = (char *)slp + sizeof (*slp);
	    msglength -= sizeof (*slp);
	    GETSHORT(len);
	    if (len > msglength) {
		sprintf(get_line(0, 0),
			"Language Tag Length = %u [CORRUPT MESSAGE]",
			len);
		return (0);
	    }

	    lang = get_line(0, 0);
	    strcpy(lang, "Language Tag = ");
	    strncat(lang,  p, len);
	    sprintf(get_line(0, 0), "XID = %u", ntohs(slp->xid));

	    /* set msglength to remaining length of SLP message */
	    p += len;
	    msglength -= len;
	}

	return (1);
}
Пример #24
0
/*
 * This is called by snoop_netbios.c.
 * This is the external entry point.
 */
void
interpret_smb(int flags, uchar_t *data, int len)
{
	struct smb *smb;
	struct decode *decoder;
	char xtra[MAXLINE];
	ushort_t smb_flags2;
	void (*func)(int, uchar_t *, int, char *, int);

	if (len < sizeof (struct smb))
		return;

	smb = (struct smb *)data;
	decoder = &SMBtable[smb->com & 255];
	smb_flags2 = get2(smb->flags2);
	xtra[0] = '\0';

	/*
	 * SMB Header description
	 * [X/Open-SMB, Sec. 5.1]
	 */
	if (flags & F_DTAIL) {
		show_header("SMB:  ", "SMB Header", len);
		show_space();

		if (smb->flags & SERVER_RESPONSE)
			show_line("SERVER RESPONSE");
		else
			show_line("CLIENT REQUEST");

		if (decoder->name)
			show_printf("Command code = 0x%x (SMB%s)",
			    smb->com, decoder->name);
		else
			show_printf("Command code = 0x%x", smb->com);

		/*
		 * NT status or error class/code
		 * [X/Open-SMB, Sec. 5.6]
		 */
		if (smb_flags2 & FLAGS2_NT_STATUS) {
			show_printf("NT Status = %x", get4(smb->err));
		} else {
			/* Error classes [X/Open-SMB, Sec. 5.6] */
			show_printf("Error class/code = %d/%d",
			    smb->err[0], get2(&smb->err[2]));
		}

		show_printf("Flags summary = 0x%.2x", smb->flags);
		show_printf("Flags2 summary = 0x%.4x", smb_flags2);
		show_printf("Tree ID  (TID) = 0x%.4x", get2(smb->tid));
		show_printf("Proc. ID (PID) = 0x%.4x", get2(smb->pid));
		show_printf("User ID  (UID) = 0x%.4x", get2(smb->uid));
		show_printf("Mux. ID  (MID) = 0x%.4x", get2(smb->mid));
		show_space();
	}

	if ((func = decoder->func) == NULL)
		func = interpret_default;
	(*func)(flags, (uchar_t *)data, len, xtra, sizeof (xtra));

	if (flags & F_SUM) {
		char *p;
		int sz, tl;

		/* Will advance p and decr. sz */
		p = get_sum_line();
		sz = MAXLINE;

		/* Call or Reply */
		if (smb->flags & SERVER_RESPONSE)
			tl = snprintf(p, sz, "SMB R");
		else
			tl = snprintf(p, sz, "SMB C");
		p += tl;
		sz -= tl;

		/* The name, if known, else the cmd code */
		if (decoder->name) {
			tl = snprintf(p, sz, " Cmd=SMB%s", decoder->name);
		} else {
			tl = snprintf(p, sz, " Cmd=0x%02X", smb->com);
		}
		p += tl;
		sz -= tl;

		/*
		 * The "extra" (cmd-specific summary).
		 * If non-null, has leading blank.
		 */
		if (xtra[0] != '\0') {
			tl = snprintf(p, sz, "%s", xtra);
			p += tl;
			sz -= tl;
		}

		/*
		 * NT status or error class/code
		 * [X/Open-SMB, Sec. 5.6]
		 *
		 * Only show for response, not call.
		 */
		if (smb->flags & SERVER_RESPONSE) {
			if (smb_flags2 & FLAGS2_NT_STATUS) {
				uint_t status = get4(smb->err);
				snprintf(p, sz, " Status=0x%x", status);
			} else {
				uchar_t errcl = smb->err[0];
				ushort_t code = get2(&smb->err[2]);
				snprintf(p, sz, " Error=%d/%d", errcl, code);
			}
		}
	}

	if (flags & F_DTAIL)
		show_trailer();
}
Пример #25
0
int
interpret_dhcpv6(int flags, const uint8_t *data, int len)
{
	int olen = len;
	char *line, *lstart;
	dhcpv6_relay_t d6r;
	dhcpv6_message_t d6m;
	uint_t optlen;
	uint16_t statuscode;

	if (len <= 0) {
		(void) strlcpy(get_sum_line(), "DHCPv6?", MAXLINE);
		return (0);
	}
	if (flags & F_SUM) {
		uint_t ias;
		dhcpv6_option_t *d6o;
		in6_addr_t link, peer;
		char linkstr[INET6_ADDRSTRLEN];
		char peerstr[INET6_ADDRSTRLEN];

		line = lstart = get_sum_line();
		line += snprintf(line, MAXLINE, "DHCPv6 %s",
		    mtype_to_str(data[0]));
		if (data[0] == DHCPV6_MSG_RELAY_FORW ||
		    data[0] == DHCPV6_MSG_RELAY_REPL) {
			if (len < sizeof (d6r)) {
				(void) strlcpy(line, "?",
				    MAXLINE - (line - lstart));
				return (olen);
			}
			/* Not much in DHCPv6 is aligned. */
			(void) memcpy(&d6r, data, sizeof (d6r));
			(void) memcpy(&link, d6r.d6r_linkaddr, sizeof (link));
			(void) memcpy(&peer, d6r.d6r_peeraddr, sizeof (peer));
			line += snprintf(line, MAXLINE - (line - lstart),
			    " HC=%d link=%s peer=%s", d6r.d6r_hop_count,
			    inet_ntop(AF_INET6, &link, linkstr,
			    sizeof (linkstr)),
			    inet_ntop(AF_INET6, &peer, peerstr,
			    sizeof (peerstr)));
			data += sizeof (d6r);
			len -= sizeof (d6r);
		} else {
			if (len < sizeof (d6m)) {
				(void) strlcpy(line, "?",
				    MAXLINE - (line - lstart));
				return (olen);
			}
			(void) memcpy(&d6m, data, sizeof (d6m));
			line += snprintf(line, MAXLINE - (line - lstart),
			    " xid=%x", DHCPV6_GET_TRANSID(&d6m));
			data += sizeof (d6m);
			len -= sizeof (d6m);
		}
		ias = 0;
		d6o = NULL;
		while ((d6o = dhcpv6_find_option(data, len, d6o,
		    DHCPV6_OPT_IA_NA, NULL)) != NULL)
			ias++;
		if (ias > 0)
			line += snprintf(line, MAXLINE - (line - lstart),
			    " IAs=%u", ias);
		d6o = dhcpv6_find_option(data, len, NULL,
		    DHCPV6_OPT_STATUS_CODE, &optlen);
		optlen -= sizeof (*d6o);
		if (d6o != NULL && optlen >= sizeof (statuscode)) {
			(void) memcpy(&statuscode, d6o + 1,
			    sizeof (statuscode));
			line += snprintf(line, MAXLINE - (line - lstart),
			    " status=%u", ntohs(statuscode));
			optlen -= sizeof (statuscode);
			if (optlen > 0) {
				line += snprintf(line,
				    MAXLINE - (line - lstart), " \"%.*s\"",
				    optlen, (char *)(d6o + 1) + 2);
			}
		}
		d6o = dhcpv6_find_option(data, len, NULL,
		    DHCPV6_OPT_RELAY_MSG, &optlen);
		optlen -= sizeof (*d6o);
		if (d6o != NULL && optlen >= 1) {
			line += snprintf(line, MAXLINE - (line - lstart),
			    " relay=%s", mtype_to_str(*(uint8_t *)(d6o + 1)));
		}
	} else if (flags & F_DTAIL) {
		show_header("DHCPv6: ",
		    "Dynamic Host Configuration Protocol Version 6", len);
		show_space();
		(void) snprintf(get_line(0, 0), get_line_remain(),
		    "Message type (msg-type) = %u (%s)", data[0],
		    mtype_to_str(data[0]));
		if (data[0] == DHCPV6_MSG_RELAY_FORW ||
		    data[0] == DHCPV6_MSG_RELAY_REPL) {
			if (len < sizeof (d6r)) {
				(void) strlcpy(get_line(0, 0), "Truncated",
				    get_line_remain());
				return (olen);
			}
			(void) memcpy(&d6r, data, sizeof (d6r));
			(void) snprintf(get_line(0, 0), get_line_remain(),
			    "Hop count = %u", d6r.d6r_hop_count);
			show_address("Link address", d6r.d6r_linkaddr);
			show_address("Peer address", d6r.d6r_peeraddr);
			data += sizeof (d6r);
			len -= sizeof (d6r);
		} else {
			if (len < sizeof (d6m)) {
				(void) strlcpy(get_line(0, 0), "Truncated",
				    get_line_remain());
				return (olen);
			}
			(void) memcpy(&d6m, data, sizeof (d6m));
			(void) snprintf(get_line(0, 0), get_line_remain(),
			    "Transaction ID = %x", DHCPV6_GET_TRANSID(&d6m));
			data += sizeof (d6m);
			len -= sizeof (d6m);
		}
		show_space();
		show_options(data, len);
		show_space();
	}
	return (olen);
}