xref: /titanic_41/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_ether.c (revision 0a0e9771ca0211c15f3ac4466b661c145feeb9e4)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5605445d5Sdg199075  * Common Development and Distribution License (the "License").
6605445d5Sdg199075  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
224eaa4710SRishi Srivatsavai  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include <stdio.h>
277c478bd9Sstevel@tonic-gate #include <stdlib.h>
287c478bd9Sstevel@tonic-gate #include <string.h>
29605445d5Sdg199075 #include <stddef.h>
307c478bd9Sstevel@tonic-gate #include <fcntl.h>
317c478bd9Sstevel@tonic-gate #include <string.h>
327c478bd9Sstevel@tonic-gate #include <sys/types.h>
337c478bd9Sstevel@tonic-gate #include <sys/time.h>
347c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
357c478bd9Sstevel@tonic-gate #include <sys/socket.h>
367c478bd9Sstevel@tonic-gate #include <net/if.h>
377c478bd9Sstevel@tonic-gate #include <netinet/in_systm.h>
387c478bd9Sstevel@tonic-gate #include <netinet/in.h>
397c478bd9Sstevel@tonic-gate #include <netinet/ip.h>
407c478bd9Sstevel@tonic-gate #include <netinet/if_ether.h>
417c478bd9Sstevel@tonic-gate #include <sys/ib/clients/ibd/ibd.h>
42605445d5Sdg199075 #include <sys/ethernet.h>
43605445d5Sdg199075 #include <sys/vlan.h>
44b127ac41SPhilip Kirk #include <sys/zone.h>
452b24ab6bSSebastien Roy #include <inet/iptun.h>
46b127ac41SPhilip Kirk #include <sys/byteorder.h>
47b127ac41SPhilip Kirk #include <limits.h>
48b127ac41SPhilip Kirk #include <inet/ip.h>
49b127ac41SPhilip Kirk #include <inet/ip6.h>
504eaa4710SRishi Srivatsavai #include <net/trill.h>
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate #include "at.h"
537c478bd9Sstevel@tonic-gate #include "snoop.h"
547c478bd9Sstevel@tonic-gate 
552b24ab6bSSebastien Roy static headerlen_fn_t ether_header_len, fddi_header_len, tr_header_len,
562b24ab6bSSebastien Roy     ib_header_len, ipnet_header_len, ipv4_header_len, ipv6_header_len;
572b24ab6bSSebastien Roy static interpreter_fn_t interpret_ether, interpret_fddi, interpret_tr,
582b24ab6bSSebastien Roy     interpret_ib, interpret_ipnet, interpret_iptun;
597c478bd9Sstevel@tonic-gate static void addr_copy_swap(struct ether_addr *, struct ether_addr *);
602b24ab6bSSebastien Roy static int tr_machdr_len(char *, int *, int *);
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate interface_t *interface;
637c478bd9Sstevel@tonic-gate interface_t INTERFACES[] = {
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate 	/* IEEE 802.3 CSMA/CD network */
66b127ac41SPhilip Kirk 	{ DL_CSMACD, 1550, 12, 2, ETHERTYPE_IP, ETHERTYPE_IPV6,
67b127ac41SPhilip Kirk 	    ether_header_len, interpret_ether, B_TRUE },
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate 	/* Ethernet Bus */
70b127ac41SPhilip Kirk 	{ DL_ETHER, 1550, 12, 2, ETHERTYPE_IP, ETHERTYPE_IPV6,
71b127ac41SPhilip Kirk 	    ether_header_len, interpret_ether, B_TRUE },
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate 	/* Fiber Distributed data interface */
74b127ac41SPhilip Kirk 	{ DL_FDDI, 4500, 19, 2, ETHERTYPE_IP, ETHERTYPE_IPV6,
75b127ac41SPhilip Kirk 	    fddi_header_len, interpret_fddi, B_FALSE },
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate 	/* Token Ring interface */
78b127ac41SPhilip Kirk 	{ DL_TPR, 17800, 0, 2, ETHERTYPE_IP, ETHERTYPE_IPV6,
79b127ac41SPhilip Kirk 	    tr_header_len, interpret_tr, B_FALSE },
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate 	/* Infiniband */
82b127ac41SPhilip Kirk 	{ DL_IB, 4096, 0, 2, ETHERTYPE_IP, ETHERTYPE_IPV6,
83b127ac41SPhilip Kirk 	    ib_header_len, interpret_ib, B_TRUE },
847c478bd9Sstevel@tonic-gate 
85b127ac41SPhilip Kirk 	/* ipnet */
86041bde0aSSebastien Roy 	{ DL_IPNET, INT_MAX, 1, 1, IPV4_VERSION, IPV6_VERSION,
87b127ac41SPhilip Kirk 	    ipnet_header_len, interpret_ipnet, B_TRUE },
887c478bd9Sstevel@tonic-gate 
892b24ab6bSSebastien Roy 	/* IPv4 tunnel */
902b24ab6bSSebastien Roy 	{ DL_IPV4, 0, 9, 1, IPPROTO_ENCAP, IPPROTO_IPV6,
912b24ab6bSSebastien Roy 	    ipv4_header_len, interpret_iptun, B_FALSE },
922b24ab6bSSebastien Roy 
932b24ab6bSSebastien Roy 	/* IPv6 tunnel */
942b24ab6bSSebastien Roy 	{ DL_IPV6, 0, 40, 1, IPPROTO_ENCAP, IPPROTO_IPV6,
952b24ab6bSSebastien Roy 	    ipv6_header_len, interpret_iptun, B_FALSE },
962b24ab6bSSebastien Roy 
972b24ab6bSSebastien Roy 	/* 6to4 tunnel */
982b24ab6bSSebastien Roy 	{ DL_6TO4, 0, 9, 1, IPPROTO_ENCAP, IPPROTO_IPV6,
992b24ab6bSSebastien Roy 	    ipv4_header_len, interpret_iptun, B_FALSE },
1002b24ab6bSSebastien Roy 
101b127ac41SPhilip Kirk 	{ (uint_t)-1, 0, 0, 0, 0, NULL, NULL, B_FALSE }
1027c478bd9Sstevel@tonic-gate };
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate /* externals */
1057c478bd9Sstevel@tonic-gate extern char *dlc_header;
1067c478bd9Sstevel@tonic-gate extern int pi_frame;
1077c478bd9Sstevel@tonic-gate extern int pi_time_hour;
1087c478bd9Sstevel@tonic-gate extern int pi_time_min;
1097c478bd9Sstevel@tonic-gate extern int pi_time_sec;
1107c478bd9Sstevel@tonic-gate extern int pi_time_usec;
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate char *printether();
1137c478bd9Sstevel@tonic-gate char *print_ethertype();
1147c478bd9Sstevel@tonic-gate static char *print_etherinfo();
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate char *print_fc();
1177c478bd9Sstevel@tonic-gate char *print_smttype();
1187c478bd9Sstevel@tonic-gate char *print_smtclass();
1197c478bd9Sstevel@tonic-gate 
1207c478bd9Sstevel@tonic-gate struct ether_addr ether_broadcast = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
1217c478bd9Sstevel@tonic-gate static char *data;			/* current data buffer */
1227c478bd9Sstevel@tonic-gate static int datalen;			/* current data buffer length */
1234eaa4710SRishi Srivatsavai static const struct ether_addr all_isis_rbridges = ALL_ISIS_RBRIDGES;
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate uint_t
interpret_ether(int flags,char * header,int elen,int origlen)1262b24ab6bSSebastien Roy interpret_ether(int flags, char *header, int elen, int origlen)
1277c478bd9Sstevel@tonic-gate {
1282b24ab6bSSebastien Roy 	struct ether_header *e = (struct ether_header *)header;
1294eaa4710SRishi Srivatsavai 	uchar_t *off, *ieeestart;
1307c478bd9Sstevel@tonic-gate 	int len;
1317c478bd9Sstevel@tonic-gate 	int ieee8023 = 0;
1327c478bd9Sstevel@tonic-gate 	extern char *dst_name;
1337c478bd9Sstevel@tonic-gate 	int ethertype;
134605445d5Sdg199075 	struct ether_vlan_extinfo *evx = NULL;
1357c478bd9Sstevel@tonic-gate 	int blen = MAX(origlen, ETHERMTU);
1364eaa4710SRishi Srivatsavai 	boolean_t trillpkt = B_FALSE;
1374eaa4710SRishi Srivatsavai 	uint16_t tci = 0;
1387c478bd9Sstevel@tonic-gate 
1397c478bd9Sstevel@tonic-gate 	if (data != NULL && datalen != 0 && datalen < blen) {
1407c478bd9Sstevel@tonic-gate 		free(data);
1417c478bd9Sstevel@tonic-gate 		data = NULL;
1427c478bd9Sstevel@tonic-gate 		datalen = 0;
1437c478bd9Sstevel@tonic-gate 	}
1447c478bd9Sstevel@tonic-gate 	if (!data) {
1457c478bd9Sstevel@tonic-gate 		data = (char *)malloc(blen);
1467c478bd9Sstevel@tonic-gate 		if (!data)
1477c478bd9Sstevel@tonic-gate 			pr_err("Warning: malloc failure");
1487c478bd9Sstevel@tonic-gate 		datalen = blen;
1497c478bd9Sstevel@tonic-gate 	}
1504eaa4710SRishi Srivatsavai inner_pkt:
1517c478bd9Sstevel@tonic-gate 	if (origlen < 14) {
1522b24ab6bSSebastien Roy 		if (flags & F_SUM) {
1537c478bd9Sstevel@tonic-gate 			(void) sprintf(get_sum_line(),
1547c478bd9Sstevel@tonic-gate 			    "RUNT (short packet - %d bytes)",
1557c478bd9Sstevel@tonic-gate 			    origlen);
1562b24ab6bSSebastien Roy 		}
1577c478bd9Sstevel@tonic-gate 		if (flags & F_DTAIL)
1587c478bd9Sstevel@tonic-gate 			show_header("RUNT:  ", "Short packet", origlen);
1597c478bd9Sstevel@tonic-gate 		return (elen);
1607c478bd9Sstevel@tonic-gate 	}
1617c478bd9Sstevel@tonic-gate 	if (elen < 14)
1627c478bd9Sstevel@tonic-gate 		return (elen);
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate 	if (memcmp(&e->ether_dhost, &ether_broadcast,
1657c478bd9Sstevel@tonic-gate 	    sizeof (struct ether_addr)) == 0)
1667c478bd9Sstevel@tonic-gate 		dst_name = "(broadcast)";
1677c478bd9Sstevel@tonic-gate 	else if (e->ether_dhost.ether_addr_octet[0] & 1)
1687c478bd9Sstevel@tonic-gate 		dst_name = "(multicast)";
1697c478bd9Sstevel@tonic-gate 
1707c478bd9Sstevel@tonic-gate 	ethertype = ntohs(e->ether_type);
1717c478bd9Sstevel@tonic-gate 
1727c478bd9Sstevel@tonic-gate 	/*
1737c478bd9Sstevel@tonic-gate 	 * The 14 byte ether header screws up alignment
1747c478bd9Sstevel@tonic-gate 	 * of the rest of the packet for 32 bit aligned
1757c478bd9Sstevel@tonic-gate 	 * architectures like SPARC. Alas, we have to copy
1767c478bd9Sstevel@tonic-gate 	 * the rest of the packet in order to align it.
1777c478bd9Sstevel@tonic-gate 	 */
1787c478bd9Sstevel@tonic-gate 	len = elen - sizeof (struct ether_header);
1794eaa4710SRishi Srivatsavai 	off = (uchar_t *)(e + 1);
1807c478bd9Sstevel@tonic-gate 
181605445d5Sdg199075 	if (ethertype == ETHERTYPE_VLAN) {
182605445d5Sdg199075 		if (origlen < sizeof (struct ether_vlan_header)) {
183605445d5Sdg199075 			if (flags & F_SUM) {
184605445d5Sdg199075 				(void) sprintf(get_sum_line(),
185605445d5Sdg199075 				    "RUNT (short VLAN packet - %d bytes)",
186605445d5Sdg199075 				    origlen);
187605445d5Sdg199075 			}
188605445d5Sdg199075 			if (flags & F_DTAIL) {
189605445d5Sdg199075 				show_header("RUNT:  ", "Short VLAN packet",
190605445d5Sdg199075 				    origlen);
191605445d5Sdg199075 			}
192605445d5Sdg199075 			return (elen);
193605445d5Sdg199075 		}
194605445d5Sdg199075 		if (len < sizeof (struct ether_vlan_extinfo))
195605445d5Sdg199075 			return (elen);
196605445d5Sdg199075 
197605445d5Sdg199075 		evx = (struct ether_vlan_extinfo *)off;
198605445d5Sdg199075 		off += sizeof (struct ether_vlan_extinfo);
199605445d5Sdg199075 		len -= sizeof (struct ether_vlan_extinfo);
200605445d5Sdg199075 
201605445d5Sdg199075 		ethertype = ntohs(evx->ether_type);
2024eaa4710SRishi Srivatsavai 		tci = ntohs(evx->ether_tci);
203605445d5Sdg199075 	}
204605445d5Sdg199075 
2054eaa4710SRishi Srivatsavai 	if (ethertype <= 1514) {
2067c478bd9Sstevel@tonic-gate 		/*
2074eaa4710SRishi Srivatsavai 		 * Fake out the IEEE 802.3 packets.
2084eaa4710SRishi Srivatsavai 		 * Should be DSAP=0xAA, SSAP=0xAA, control=0x03
2094eaa4710SRishi Srivatsavai 		 * then three padding bytes of zero (OUI),
2104eaa4710SRishi Srivatsavai 		 * followed by a normal ethernet-type packet.
2117c478bd9Sstevel@tonic-gate 		 */
2124eaa4710SRishi Srivatsavai 		ieee8023 = ethertype;
2134eaa4710SRishi Srivatsavai 		ieeestart = off;
2144eaa4710SRishi Srivatsavai 		if (off[0] == 0xAA && off[1] == 0xAA) {
2154eaa4710SRishi Srivatsavai 			ethertype = ntohs(*(ushort_t *)(off + 6));
2164eaa4710SRishi Srivatsavai 			off += 8;
2174eaa4710SRishi Srivatsavai 			len -= 8;
2184eaa4710SRishi Srivatsavai 		} else {
2194eaa4710SRishi Srivatsavai 			ethertype = 0;
2204eaa4710SRishi Srivatsavai 			off += 3;
2214eaa4710SRishi Srivatsavai 			len -= 3;
2224eaa4710SRishi Srivatsavai 		}
2237c478bd9Sstevel@tonic-gate 	}
2247c478bd9Sstevel@tonic-gate 
2257c478bd9Sstevel@tonic-gate 	if (flags & F_SUM) {
226605445d5Sdg199075 		/*
227605445d5Sdg199075 		 * Set the flag that says don't display VLAN information.
228605445d5Sdg199075 		 * If it needs to change, that will be done later if the
229605445d5Sdg199075 		 * packet is VLAN tagged and if snoop is in its default
230605445d5Sdg199075 		 * summary mode.
231605445d5Sdg199075 		 */
232605445d5Sdg199075 		set_vlan_id(0);
233605445d5Sdg199075 		if (evx == NULL) {
2344eaa4710SRishi Srivatsavai 			if (ethertype == 0 && ieee8023 > 0) {
2354eaa4710SRishi Srivatsavai 				(void) sprintf(get_sum_line(),
2364eaa4710SRishi Srivatsavai 				    "ETHER 802.3 SSAP %02X DSAP %02X, "
2374eaa4710SRishi Srivatsavai 				    "size=%d bytes", ieeestart[0], ieeestart[1],
2384eaa4710SRishi Srivatsavai 				    origlen);
2394eaa4710SRishi Srivatsavai 			} else {
2407c478bd9Sstevel@tonic-gate 				(void) sprintf(get_sum_line(),
2417c478bd9Sstevel@tonic-gate 				    "ETHER Type=%04X (%s), size=%d bytes",
242605445d5Sdg199075 				    ethertype, print_ethertype(ethertype),
2437c478bd9Sstevel@tonic-gate 				    origlen);
2444eaa4710SRishi Srivatsavai 			}
2454eaa4710SRishi Srivatsavai 		} else {
2464eaa4710SRishi Srivatsavai 			if (ethertype == 0 && ieee8023 > 0) {
2474eaa4710SRishi Srivatsavai 				(void) sprintf(get_sum_line(),
2484eaa4710SRishi Srivatsavai 				    "ETHER 802.3 SSAP %02X DSAP %02X, "
2494eaa4710SRishi Srivatsavai 				    "VLAN ID=%hu, size=%d bytes", ieeestart[0],
2504eaa4710SRishi Srivatsavai 				    ieeestart[1], VLAN_ID(tci), origlen);
251605445d5Sdg199075 			} else {
252605445d5Sdg199075 				(void) sprintf(get_sum_line(),
2534eaa4710SRishi Srivatsavai 				    "ETHER Type=%04X (%s), VLAN ID=%hu, "
2544eaa4710SRishi Srivatsavai 				    "size=%d bytes", ethertype,
2554eaa4710SRishi Srivatsavai 				    print_ethertype(ethertype), VLAN_ID(tci),
2564eaa4710SRishi Srivatsavai 				    origlen);
2574eaa4710SRishi Srivatsavai 			}
258605445d5Sdg199075 
259605445d5Sdg199075 			if (!(flags & F_ALLSUM))
2604eaa4710SRishi Srivatsavai 				set_vlan_id(VLAN_ID(tci));
261605445d5Sdg199075 		}
2627c478bd9Sstevel@tonic-gate 	}
2637c478bd9Sstevel@tonic-gate 
2647c478bd9Sstevel@tonic-gate 	if (flags & F_DTAIL) {
2657c478bd9Sstevel@tonic-gate 		show_header("ETHER:  ", "Ether Header", elen);
2667c478bd9Sstevel@tonic-gate 		show_space();
2674eaa4710SRishi Srivatsavai 		if (!trillpkt) {
2687c478bd9Sstevel@tonic-gate 			(void) sprintf(get_line(0, 0),
2697c478bd9Sstevel@tonic-gate 			    "Packet %d arrived at %d:%02d:%d.%05d",
2707c478bd9Sstevel@tonic-gate 			    pi_frame,
2717c478bd9Sstevel@tonic-gate 			    pi_time_hour, pi_time_min, pi_time_sec,
2727c478bd9Sstevel@tonic-gate 			    pi_time_usec / 10);
2737c478bd9Sstevel@tonic-gate 			(void) sprintf(get_line(0, 0),
2747c478bd9Sstevel@tonic-gate 			    "Packet size = %d bytes",
2757c478bd9Sstevel@tonic-gate 			    elen, elen);
2764eaa4710SRishi Srivatsavai 		}
2777c478bd9Sstevel@tonic-gate 		(void) sprintf(get_line(0, 6),
2787c478bd9Sstevel@tonic-gate 		    "Destination = %s, %s",
2797c478bd9Sstevel@tonic-gate 		    printether(&e->ether_dhost),
2807c478bd9Sstevel@tonic-gate 		    print_etherinfo(&e->ether_dhost));
2817c478bd9Sstevel@tonic-gate 		(void) sprintf(get_line(6, 6),
2827c478bd9Sstevel@tonic-gate 		    "Source      = %s, %s",
2837c478bd9Sstevel@tonic-gate 		    printether(&e->ether_shost),
2847c478bd9Sstevel@tonic-gate 		    print_etherinfo(&e->ether_shost));
2854eaa4710SRishi Srivatsavai 		if (evx != NULL) {
2864eaa4710SRishi Srivatsavai 			(void) sprintf(get_line(0, 0),
2874eaa4710SRishi Srivatsavai 			    "VLAN ID     = %hu", VLAN_ID(tci));
2884eaa4710SRishi Srivatsavai 			(void) sprintf(get_line(0, 0),
2894eaa4710SRishi Srivatsavai 			    "VLAN Priority = %hu", VLAN_PRI(tci));
2904eaa4710SRishi Srivatsavai 		}
291605445d5Sdg199075 		if (ieee8023 > 0) {
2927c478bd9Sstevel@tonic-gate 			(void) sprintf(get_line(12, 2),
293605445d5Sdg199075 			    "IEEE 802.3 length = %d bytes", ieee8023);
2944eaa4710SRishi Srivatsavai 			/* Print LLC only for non-TCP/IP packets */
2954eaa4710SRishi Srivatsavai 			if (ethertype == 0) {
2964eaa4710SRishi Srivatsavai 				(void) snprintf(get_line(0, 0),
2974eaa4710SRishi Srivatsavai 				    get_line_remain(),
2984eaa4710SRishi Srivatsavai 				    "SSAP = %02X, DSAP = %02X, CTRL = %02X",
2994eaa4710SRishi Srivatsavai 				    ieeestart[0], ieeestart[1], ieeestart[2]);
300605445d5Sdg199075 			}
301605445d5Sdg199075 		}
3024eaa4710SRishi Srivatsavai 		if (ethertype != 0 || ieee8023 == 0)
3037c478bd9Sstevel@tonic-gate 			(void) sprintf(get_line(12, 2),
3047c478bd9Sstevel@tonic-gate 			    "Ethertype = %04X (%s)",
3057c478bd9Sstevel@tonic-gate 			    ethertype, print_ethertype(ethertype));
3067c478bd9Sstevel@tonic-gate 		show_space();
3077c478bd9Sstevel@tonic-gate 	}
3087c478bd9Sstevel@tonic-gate 
3094eaa4710SRishi Srivatsavai 	/*
3104eaa4710SRishi Srivatsavai 	 * We cannot trust the length field in the header to be correct.
3114eaa4710SRishi Srivatsavai 	 * But we should continue to process the packet.  Then user can
3124eaa4710SRishi Srivatsavai 	 * notice something funny in the header.
3134eaa4710SRishi Srivatsavai 	 * Go to the next protocol layer only if data have been
3144eaa4710SRishi Srivatsavai 	 * copied.
3154eaa4710SRishi Srivatsavai 	 */
3164eaa4710SRishi Srivatsavai 	if (len > 0 && (off + len <= (uchar_t *)e + elen)) {
3174eaa4710SRishi Srivatsavai 		(void) memmove(data, off, len);
3184eaa4710SRishi Srivatsavai 
3194eaa4710SRishi Srivatsavai 		if (!trillpkt && ethertype == ETHERTYPE_TRILL) {
3204eaa4710SRishi Srivatsavai 			ethertype = interpret_trill(flags, &e, data, &len);
3214eaa4710SRishi Srivatsavai 			/* Decode inner Ethernet frame */
3224eaa4710SRishi Srivatsavai 			if (ethertype != 0) {
3234eaa4710SRishi Srivatsavai 				evx = NULL;
3244eaa4710SRishi Srivatsavai 				trillpkt = B_TRUE;
3254eaa4710SRishi Srivatsavai 				(void) memmove(data, e, len);
3264eaa4710SRishi Srivatsavai 				e = (struct ether_header *)data;
3274eaa4710SRishi Srivatsavai 				origlen = len;
3284eaa4710SRishi Srivatsavai 				elen = len;
3294eaa4710SRishi Srivatsavai 				goto inner_pkt;
3304eaa4710SRishi Srivatsavai 			}
3314eaa4710SRishi Srivatsavai 		}
3324eaa4710SRishi Srivatsavai 
3337c478bd9Sstevel@tonic-gate 		switch (ethertype) {
3347c478bd9Sstevel@tonic-gate 		case ETHERTYPE_IP:
3357c478bd9Sstevel@tonic-gate 			(void) interpret_ip(flags, (struct ip *)data, len);
3367c478bd9Sstevel@tonic-gate 			break;
3377c478bd9Sstevel@tonic-gate 		/* Just in case it is decided to add this type */
3387c478bd9Sstevel@tonic-gate 		case ETHERTYPE_IPV6:
3397c478bd9Sstevel@tonic-gate 			(void) interpret_ipv6(flags, (ip6_t *)data, len);
3407c478bd9Sstevel@tonic-gate 			break;
3417c478bd9Sstevel@tonic-gate 		case ETHERTYPE_ARP:
3427c478bd9Sstevel@tonic-gate 		case ETHERTYPE_REVARP:
3437c478bd9Sstevel@tonic-gate 			interpret_arp(flags, (struct arphdr *)data, len);
3447c478bd9Sstevel@tonic-gate 			break;
3457c478bd9Sstevel@tonic-gate 		case ETHERTYPE_PPPOED:
3467c478bd9Sstevel@tonic-gate 		case ETHERTYPE_PPPOES:
3477c478bd9Sstevel@tonic-gate 			(void) interpret_pppoe(flags, (poep_t *)data, len);
3487c478bd9Sstevel@tonic-gate 			break;
3497c478bd9Sstevel@tonic-gate 		case ETHERTYPE_AARP:    /* AppleTalk */
3507c478bd9Sstevel@tonic-gate 			interpret_aarp(flags, data, len);
3517c478bd9Sstevel@tonic-gate 			break;
3527c478bd9Sstevel@tonic-gate 		case ETHERTYPE_AT:
3537c478bd9Sstevel@tonic-gate 			interpret_at(flags, (struct ddp_hdr *)data, len);
3547c478bd9Sstevel@tonic-gate 			break;
3554eaa4710SRishi Srivatsavai 		case 0:
3564eaa4710SRishi Srivatsavai 			if (ieee8023 == 0)
3574eaa4710SRishi Srivatsavai 				break;
3584eaa4710SRishi Srivatsavai 			switch (ieeestart[0]) {
3594eaa4710SRishi Srivatsavai 			case 0xFE:
3604eaa4710SRishi Srivatsavai 				interpret_isis(flags, data, len,
3614eaa4710SRishi Srivatsavai 				    memcmp(&e->ether_dhost, &all_isis_rbridges,
3624eaa4710SRishi Srivatsavai 				    sizeof (struct ether_addr)) == 0);
3634eaa4710SRishi Srivatsavai 				break;
3644eaa4710SRishi Srivatsavai 			case 0x42:
3654eaa4710SRishi Srivatsavai 				interpret_bpdu(flags, data, len);
3664eaa4710SRishi Srivatsavai 				break;
3674eaa4710SRishi Srivatsavai 			}
3687c478bd9Sstevel@tonic-gate 			break;
3697c478bd9Sstevel@tonic-gate 		}
3707c478bd9Sstevel@tonic-gate 	}
3717c478bd9Sstevel@tonic-gate 
3727c478bd9Sstevel@tonic-gate 	return (elen);
3737c478bd9Sstevel@tonic-gate }
3747c478bd9Sstevel@tonic-gate 
375605445d5Sdg199075 /*
376605445d5Sdg199075  * Return the length of the ethernet header.  In the case
377605445d5Sdg199075  * where we have a VLAN tagged packet, return the length of
378605445d5Sdg199075  * the ethernet header plus the length of the VLAN tag.
379605445d5Sdg199075  *
380605445d5Sdg199075  * INPUTS:  e  -  A buffer pointer.  Passing a NULL pointer
381605445d5Sdg199075  *                is not allowed, e must be non-NULL.
382605445d5Sdg199075  * OUTPUTS:  Return the size of an untagged ethernet header
383605445d5Sdg199075  *           if the packet is not VLAN tagged, and the size
384605445d5Sdg199075  *           of an untagged ethernet header plus the size of
385605445d5Sdg199075  *           a VLAN header otherwise.
386605445d5Sdg199075  */
3877c478bd9Sstevel@tonic-gate uint_t
ether_header_len(char * e,size_t msgsize)3882b24ab6bSSebastien Roy ether_header_len(char *e, size_t msgsize)
3897c478bd9Sstevel@tonic-gate {
390605445d5Sdg199075 	uint16_t ether_type = 0;
3912b24ab6bSSebastien Roy 
3922b24ab6bSSebastien Roy 	if (msgsize < sizeof (struct ether_header))
3932b24ab6bSSebastien Roy 		return (0);
3942b24ab6bSSebastien Roy 
395605445d5Sdg199075 	e += (offsetof(struct ether_header, ether_type));
396605445d5Sdg199075 
397605445d5Sdg199075 	GETINT16(ether_type, e);
398605445d5Sdg199075 
399605445d5Sdg199075 	if (ether_type == (uint16_t)ETHERTYPE_VLAN) {
400605445d5Sdg199075 		return (sizeof (struct ether_vlan_header));
401605445d5Sdg199075 	} else {
402605445d5Sdg199075 		return (sizeof (struct ether_header));
403605445d5Sdg199075 	}
4047c478bd9Sstevel@tonic-gate }
4057c478bd9Sstevel@tonic-gate 
4067c478bd9Sstevel@tonic-gate 
4077c478bd9Sstevel@tonic-gate /*
4087c478bd9Sstevel@tonic-gate  * Table of Ethertypes.
4097c478bd9Sstevel@tonic-gate  * Some of the more popular entries
4107c478bd9Sstevel@tonic-gate  * are at the beginning of the table
4117c478bd9Sstevel@tonic-gate  * to reduce search time.
4127c478bd9Sstevel@tonic-gate  */
4137c478bd9Sstevel@tonic-gate struct ether_type {
4147c478bd9Sstevel@tonic-gate 	int   e_type;
4157c478bd9Sstevel@tonic-gate 	char *e_name;
4167c478bd9Sstevel@tonic-gate } ether_type [] = {
4177c478bd9Sstevel@tonic-gate ETHERTYPE_IP, "IP",
4187c478bd9Sstevel@tonic-gate ETHERTYPE_ARP, "ARP",
4197c478bd9Sstevel@tonic-gate ETHERTYPE_REVARP, "RARP",
4207c478bd9Sstevel@tonic-gate ETHERTYPE_IPV6, "IPv6",
4217c478bd9Sstevel@tonic-gate ETHERTYPE_PPPOED, "PPPoE Discovery",
4227c478bd9Sstevel@tonic-gate ETHERTYPE_PPPOES, "PPPoE Session",
4234eaa4710SRishi Srivatsavai ETHERTYPE_TRILL, "TRILL",
4247c478bd9Sstevel@tonic-gate /* end of popular entries */
4257c478bd9Sstevel@tonic-gate ETHERTYPE_PUP,	"Xerox PUP",
4267c478bd9Sstevel@tonic-gate 0x0201, "Xerox PUP",
4277c478bd9Sstevel@tonic-gate 0x0400, "Nixdorf",
4287c478bd9Sstevel@tonic-gate 0x0600, "Xerox NS IDP",
4297c478bd9Sstevel@tonic-gate 0x0601, "XNS Translation",
4307c478bd9Sstevel@tonic-gate 0x0801, "X.75 Internet",
4317c478bd9Sstevel@tonic-gate 0x0802, "NBS Internet",
4327c478bd9Sstevel@tonic-gate 0x0803, "ECMA Internet",
4337c478bd9Sstevel@tonic-gate 0x0804, "CHAOSnet",
4347c478bd9Sstevel@tonic-gate 0x0805, "X.25 Level 3",
4357c478bd9Sstevel@tonic-gate 0x0807, "XNS Compatibility",
4367c478bd9Sstevel@tonic-gate 0x081C, "Symbolics Private",
4377c478bd9Sstevel@tonic-gate 0x0888, "Xyplex",
4387c478bd9Sstevel@tonic-gate 0x0889, "Xyplex",
4397c478bd9Sstevel@tonic-gate 0x088A, "Xyplex",
4407c478bd9Sstevel@tonic-gate 0x0900, "Ungermann-Bass network debugger",
4417c478bd9Sstevel@tonic-gate 0x0A00, "Xerox IEEE802.3 PUP",
4427c478bd9Sstevel@tonic-gate 0x0A01, "Xerox IEEE802.3 PUP Address Translation",
4437c478bd9Sstevel@tonic-gate 0x0BAD, "Banyan Systems",
4447c478bd9Sstevel@tonic-gate 0x0BAF, "Banyon VINES Echo",
4457c478bd9Sstevel@tonic-gate 0x1000, "Berkeley Trailer negotiation",
4467c478bd9Sstevel@tonic-gate 0x1000,	"IP trailer (0)",
4477c478bd9Sstevel@tonic-gate 0x1001,	"IP trailer (1)",
4487c478bd9Sstevel@tonic-gate 0x1002,	"IP trailer (2)",
4497c478bd9Sstevel@tonic-gate 0x1003,	"IP trailer (3)",
4507c478bd9Sstevel@tonic-gate 0x1004,	"IP trailer (4)",
4517c478bd9Sstevel@tonic-gate 0x1005,	"IP trailer (5)",
4527c478bd9Sstevel@tonic-gate 0x1006,	"IP trailer (6)",
4537c478bd9Sstevel@tonic-gate 0x1007,	"IP trailer (7)",
4547c478bd9Sstevel@tonic-gate 0x1008,	"IP trailer (8)",
4557c478bd9Sstevel@tonic-gate 0x1009,	"IP trailer (9)",
4567c478bd9Sstevel@tonic-gate 0x100a,	"IP trailer (10)",
4577c478bd9Sstevel@tonic-gate 0x100b,	"IP trailer (11)",
4587c478bd9Sstevel@tonic-gate 0x100c,	"IP trailer (12)",
4597c478bd9Sstevel@tonic-gate 0x100d,	"IP trailer (13)",
4607c478bd9Sstevel@tonic-gate 0x100e,	"IP trailer (14)",
4617c478bd9Sstevel@tonic-gate 0x100f,	"IP trailer (15)",
4627c478bd9Sstevel@tonic-gate 0x1234, "DCA - Multicast",
4637c478bd9Sstevel@tonic-gate 0x1600, "VALID system protocol",
4647c478bd9Sstevel@tonic-gate 0x1989, "Aviator",
4657c478bd9Sstevel@tonic-gate 0x3C00, "3Com NBP virtual circuit datagram",
4667c478bd9Sstevel@tonic-gate 0x3C01, "3Com NBP System control datagram",
4677c478bd9Sstevel@tonic-gate 0x3C02, "3Com NBP Connect request (virtual cct)",
4687c478bd9Sstevel@tonic-gate 0x3C03, "3Com NBP Connect response",
4697c478bd9Sstevel@tonic-gate 0x3C04, "3Com NBP Connect complete",
4707c478bd9Sstevel@tonic-gate 0x3C05, "3Com NBP Close request (virtual cct)",
4717c478bd9Sstevel@tonic-gate 0x3C06, "3Com NBP Close response",
4727c478bd9Sstevel@tonic-gate 0x3C07, "3Com NBP Datagram (like XNS IDP)",
4737c478bd9Sstevel@tonic-gate 0x3C08, "3Com NBP Datagram broadcast",
4747c478bd9Sstevel@tonic-gate 0x3C09, "3Com NBP Claim NetBIOS name",
4757c478bd9Sstevel@tonic-gate 0x3C0A, "3Com NBP Delete Netbios name",
4767c478bd9Sstevel@tonic-gate 0x3C0B, "3Com NBP Remote adaptor status request",
4777c478bd9Sstevel@tonic-gate 0x3C0C, "3Com NBP Remote adaptor response",
4787c478bd9Sstevel@tonic-gate 0x3C0D, "3Com NBP Reset",
4797c478bd9Sstevel@tonic-gate 0x4242, "PCS Basic Block Protocol",
4807c478bd9Sstevel@tonic-gate 0x4321, "THD - Diddle",
4817c478bd9Sstevel@tonic-gate 0x5208, "BBN Simnet Private",
4827c478bd9Sstevel@tonic-gate 0x6000, "DEC unass, experimental",
4837c478bd9Sstevel@tonic-gate 0x6001, "DEC Dump/Load",
4847c478bd9Sstevel@tonic-gate 0x6002, "DEC Remote Console",
4857c478bd9Sstevel@tonic-gate 0x6003, "DECNET Phase IV, DNA Routing",
4867c478bd9Sstevel@tonic-gate 0x6004, "DEC LAT",
4877c478bd9Sstevel@tonic-gate 0x6005, "DEC Diagnostic",
4887c478bd9Sstevel@tonic-gate 0x6006, "DEC customer protocol",
4897c478bd9Sstevel@tonic-gate 0x6007, "DEC Local Area VAX Cluster (LAVC)",
4907c478bd9Sstevel@tonic-gate 0x6008, "DEC unass (AMBER?)",
4917c478bd9Sstevel@tonic-gate 0x6009, "DEC unass (MUMPS?)",
4927c478bd9Sstevel@tonic-gate 0x6010, "3Com",
4937c478bd9Sstevel@tonic-gate 0x6011, "3Com",
4947c478bd9Sstevel@tonic-gate 0x6012, "3Com",
4957c478bd9Sstevel@tonic-gate 0x6013, "3Com",
4967c478bd9Sstevel@tonic-gate 0x6014, "3Com",
4977c478bd9Sstevel@tonic-gate 0x7000, "Ungermann-Bass download",
4987c478bd9Sstevel@tonic-gate 0x7001, "Ungermann-Bass NIUs",
4997c478bd9Sstevel@tonic-gate 0x7002, "Ungermann-Bass diagnostic/loopback",
5007c478bd9Sstevel@tonic-gate 0x7003, "Ungermann-Bass ? (NMC to/from UB Bridge)",
5017c478bd9Sstevel@tonic-gate 0x7005, "Ungermann-Bass Bridge Spanning Tree",
5027c478bd9Sstevel@tonic-gate 0x7007, "OS/9 Microware",
5037c478bd9Sstevel@tonic-gate 0x7009, "OS/9 Net?",
5047c478bd9Sstevel@tonic-gate 0x7020, "Sintrom",
5057c478bd9Sstevel@tonic-gate 0x7021, "Sintrom",
5067c478bd9Sstevel@tonic-gate 0x7022, "Sintrom",
5077c478bd9Sstevel@tonic-gate 0x7023, "Sintrom",
5087c478bd9Sstevel@tonic-gate 0x7024, "Sintrom",
5097c478bd9Sstevel@tonic-gate 0x7025, "Sintrom",
5107c478bd9Sstevel@tonic-gate 0x7026, "Sintrom",
5117c478bd9Sstevel@tonic-gate 0x7027, "Sintrom",
5127c478bd9Sstevel@tonic-gate 0x7028, "Sintrom",
5137c478bd9Sstevel@tonic-gate 0x7029, "Sintrom",
5147c478bd9Sstevel@tonic-gate 0x8003, "Cronus VLN",
5157c478bd9Sstevel@tonic-gate 0x8004, "Cronus Direct",
5167c478bd9Sstevel@tonic-gate 0x8005, "HP Probe protocol",
5177c478bd9Sstevel@tonic-gate 0x8006, "Nestar",
5187c478bd9Sstevel@tonic-gate 0x8008, "AT&T/Stanford Univ",
5197c478bd9Sstevel@tonic-gate 0x8010, "Excelan",
5207c478bd9Sstevel@tonic-gate 0x8013, "SGI diagnostic",
5217c478bd9Sstevel@tonic-gate 0x8014, "SGI network games",
5227c478bd9Sstevel@tonic-gate 0x8015, "SGI reserved",
5237c478bd9Sstevel@tonic-gate 0x8016, "SGI XNS NameServer, bounce server",
5247c478bd9Sstevel@tonic-gate 0x8019, "Apollo DOMAIN",
5257c478bd9Sstevel@tonic-gate 0x802E, "Tymshare",
5267c478bd9Sstevel@tonic-gate 0x802F, "Tigan,",
5277c478bd9Sstevel@tonic-gate 0x8036, "Aeonic Systems",
5287c478bd9Sstevel@tonic-gate 0x8037, "IPX (Novell Netware)",
5297c478bd9Sstevel@tonic-gate 0x8038, "DEC LanBridge Management",
5307c478bd9Sstevel@tonic-gate 0x8039, "DEC unass (DSM/DTP?)",
5317c478bd9Sstevel@tonic-gate 0x803A, "DEC unass (Argonaut Console?)",
5327c478bd9Sstevel@tonic-gate 0x803B, "DEC unass (VAXELN?)",
5337c478bd9Sstevel@tonic-gate 0x803C, "DEC unass (NMSV? DNA Naming Service?)",
5347c478bd9Sstevel@tonic-gate 0x803D, "DEC Ethernet CSMA/CD Encryption Protocol",
5357c478bd9Sstevel@tonic-gate 0x803E, "DEC unass (DNA Time Service?)",
5367c478bd9Sstevel@tonic-gate 0x803F, "DEC LAN Traffic Monitor Protocol",
5377c478bd9Sstevel@tonic-gate 0x8040, "DEC unass (NetBios Emulator?)",
5387c478bd9Sstevel@tonic-gate 0x8041, "DEC unass (MS/DOS?, Local Area System Transport?)",
5397c478bd9Sstevel@tonic-gate 0x8042, "DEC unass",
5407c478bd9Sstevel@tonic-gate 0x8044, "Planning Research Corp.",
5417c478bd9Sstevel@tonic-gate 0x8046, "AT&T",
5427c478bd9Sstevel@tonic-gate 0x8047, "AT&T",
5437c478bd9Sstevel@tonic-gate 0x8049, "ExperData",
5447c478bd9Sstevel@tonic-gate 0x805B, "VMTP",
5457c478bd9Sstevel@tonic-gate 0x805C, "Stanford V Kernel, version 6.0",
5467c478bd9Sstevel@tonic-gate 0x805D, "Evans & Sutherland",
5477c478bd9Sstevel@tonic-gate 0x8060, "Little Machines",
5487c478bd9Sstevel@tonic-gate 0x8062, "Counterpoint",
5497c478bd9Sstevel@tonic-gate 0x8065, "University of Mass. at Amherst",
5507c478bd9Sstevel@tonic-gate 0x8066, "University of Mass. at Amherst",
5517c478bd9Sstevel@tonic-gate 0x8067, "Veeco Integrated Automation",
5527c478bd9Sstevel@tonic-gate 0x8068, "General Dynamics",
5537c478bd9Sstevel@tonic-gate 0x8069, "AT&T",
5547c478bd9Sstevel@tonic-gate 0x806A, "Autophon",
5557c478bd9Sstevel@tonic-gate 0x806C, "ComDesign",
5567c478bd9Sstevel@tonic-gate 0x806D, "Compugraphic Corp",
5577c478bd9Sstevel@tonic-gate 0x806E, "Landmark",
5587c478bd9Sstevel@tonic-gate 0x806F, "Landmark",
5597c478bd9Sstevel@tonic-gate 0x8070, "Landmark",
5607c478bd9Sstevel@tonic-gate 0x8071, "Landmark",
5617c478bd9Sstevel@tonic-gate 0x8072, "Landmark",
5627c478bd9Sstevel@tonic-gate 0x8073, "Landmark",
5637c478bd9Sstevel@tonic-gate 0x8074, "Landmark",
5647c478bd9Sstevel@tonic-gate 0x8075, "Landmark",
5657c478bd9Sstevel@tonic-gate 0x8076, "Landmark",
5667c478bd9Sstevel@tonic-gate 0x8077, "Landmark",
5677c478bd9Sstevel@tonic-gate 0x807A, "Matra",
5687c478bd9Sstevel@tonic-gate 0x807B, "Dansk Data Elektronik",
5697c478bd9Sstevel@tonic-gate 0x807C, "Merit Internodal",
5707c478bd9Sstevel@tonic-gate 0x807D, "Vitalink",
5717c478bd9Sstevel@tonic-gate 0x807E, "Vitalink",
5727c478bd9Sstevel@tonic-gate 0x807F, "Vitalink",
5737c478bd9Sstevel@tonic-gate 0x8080, "Vitalink TransLAN III Management",
5747c478bd9Sstevel@tonic-gate 0x8081, "Counterpoint",
5757c478bd9Sstevel@tonic-gate 0x8082, "Counterpoint",
5767c478bd9Sstevel@tonic-gate 0x8083, "Counterpoint",
5777c478bd9Sstevel@tonic-gate 0x8088, "Xyplex",
5787c478bd9Sstevel@tonic-gate 0x8089, "Xyplex",
5797c478bd9Sstevel@tonic-gate 0x808A, "Xyplex",
5807c478bd9Sstevel@tonic-gate 0x809B, "EtherTalk (AppleTalk over Ethernet)",
5817c478bd9Sstevel@tonic-gate 0x809C, "Datability",
5827c478bd9Sstevel@tonic-gate 0x809D, "Datability",
5837c478bd9Sstevel@tonic-gate 0x809E, "Datability",
5847c478bd9Sstevel@tonic-gate 0x809F, "Spider Systems",
5857c478bd9Sstevel@tonic-gate 0x80A3, "Nixdorf",
5867c478bd9Sstevel@tonic-gate 0x80A4, "Siemens Gammasonics",
5877c478bd9Sstevel@tonic-gate 0x80C0, "DCA Data Exchange Cluster",
5887c478bd9Sstevel@tonic-gate 0x80C6, "Pacer Software",
5897c478bd9Sstevel@tonic-gate 0x80C7, "Applitek Corp",
5907c478bd9Sstevel@tonic-gate 0x80C8, "Intergraph",
5917c478bd9Sstevel@tonic-gate 0x80C9, "Intergraph",
5927c478bd9Sstevel@tonic-gate 0x80CB, "Intergraph",
5937c478bd9Sstevel@tonic-gate 0x80CC, "Intergraph",
5947c478bd9Sstevel@tonic-gate 0x80CA, "Intergraph",
5957c478bd9Sstevel@tonic-gate 0x80CD, "Harris Corp",
5967c478bd9Sstevel@tonic-gate 0x80CE, "Harris Corp",
5977c478bd9Sstevel@tonic-gate 0x80CF, "Taylor Instrument",
5987c478bd9Sstevel@tonic-gate 0x80D0, "Taylor Instrument",
5997c478bd9Sstevel@tonic-gate 0x80D1, "Taylor Instrument",
6007c478bd9Sstevel@tonic-gate 0x80D2, "Taylor Instrument",
6017c478bd9Sstevel@tonic-gate 0x80D3, "Rosemount Corp",
6027c478bd9Sstevel@tonic-gate 0x80D4, "Rosemount Corp",
6037c478bd9Sstevel@tonic-gate 0x80D5, "IBM SNA Services over Ethernet",
6047c478bd9Sstevel@tonic-gate 0x80DD, "Varian Associates",
6057c478bd9Sstevel@tonic-gate 0x80DE, "TRFS",
6067c478bd9Sstevel@tonic-gate 0x80DF, "TRFS",
6077c478bd9Sstevel@tonic-gate 0x80E0, "Allen-Bradley",
6087c478bd9Sstevel@tonic-gate 0x80E1, "Allen-Bradley",
6097c478bd9Sstevel@tonic-gate 0x80E2, "Allen-Bradley",
6107c478bd9Sstevel@tonic-gate 0x80E3, "Allen-Bradley",
6117c478bd9Sstevel@tonic-gate 0x80E4, "Datability",
6127c478bd9Sstevel@tonic-gate 0x80F2, "Retix",
6137c478bd9Sstevel@tonic-gate 0x80F3, "AARP (Appletalk)",
6147c478bd9Sstevel@tonic-gate 0x80F4, "Kinetics",
6157c478bd9Sstevel@tonic-gate 0x80F5, "Kinetics",
6167c478bd9Sstevel@tonic-gate 0x80F7, "Apollo",
6177c478bd9Sstevel@tonic-gate 0x80FF, "Wellfleet Communications",
6187c478bd9Sstevel@tonic-gate 0x8102, "Wellfleet Communications",
6197c478bd9Sstevel@tonic-gate 0x8107, "Symbolics Private",
6207c478bd9Sstevel@tonic-gate 0x8108, "Symbolics Private",
6217c478bd9Sstevel@tonic-gate 0x8109, "Symbolics Private",
6227c478bd9Sstevel@tonic-gate 0x812B, "Talaris",
6237c478bd9Sstevel@tonic-gate 0x8130, "Waterloo",
6247c478bd9Sstevel@tonic-gate 0x8131, "VG Lab",
6257c478bd9Sstevel@tonic-gate 0x8137, "Novell (old) NetWare IPX",
6267c478bd9Sstevel@tonic-gate 0x8138, "Novell",
6277c478bd9Sstevel@tonic-gate 0x814C, "SNMP over Ethernet",
6287c478bd9Sstevel@tonic-gate 0x817D, "XTP",
6297c478bd9Sstevel@tonic-gate 0x81D6, "Lantastic",
6307c478bd9Sstevel@tonic-gate 0x8888, "HP LanProbe test?",
6317c478bd9Sstevel@tonic-gate 0x9000, "Loopback",
6327c478bd9Sstevel@tonic-gate 0x9001, "3Com, XNS Systems Management",
6337c478bd9Sstevel@tonic-gate 0x9002, "3Com, TCP/IP Systems Management",
6347c478bd9Sstevel@tonic-gate 0x9003, "3Com, loopback detection",
6357c478bd9Sstevel@tonic-gate 0xAAAA, "DECNET	(VAX 6220 DEBNI)",
6367c478bd9Sstevel@tonic-gate 0xFF00, "BBN VITAL-LanBridge cache wakeups",
6377c478bd9Sstevel@tonic-gate 0,	"",
6387c478bd9Sstevel@tonic-gate };
6397c478bd9Sstevel@tonic-gate 
6407c478bd9Sstevel@tonic-gate char *
print_fc(uint_t type)6412b24ab6bSSebastien Roy print_fc(uint_t type)
6427c478bd9Sstevel@tonic-gate {
6437c478bd9Sstevel@tonic-gate 
6447c478bd9Sstevel@tonic-gate 	switch (type) {
6457c478bd9Sstevel@tonic-gate 		case 0x50: return ("LLC");
6467c478bd9Sstevel@tonic-gate 		case 0x4f: return ("SMT NSA");
6477c478bd9Sstevel@tonic-gate 		case 0x41: return ("SMT Info");
6487c478bd9Sstevel@tonic-gate 		default: return ("Unknown");
6497c478bd9Sstevel@tonic-gate 	}
6507c478bd9Sstevel@tonic-gate }
6517c478bd9Sstevel@tonic-gate 
6527c478bd9Sstevel@tonic-gate char *
print_smtclass(uint_t type)6532b24ab6bSSebastien Roy print_smtclass(uint_t type)
6547c478bd9Sstevel@tonic-gate {
6557c478bd9Sstevel@tonic-gate 	switch (type) {
6567c478bd9Sstevel@tonic-gate 		case 0x01: return ("NIF");
6577c478bd9Sstevel@tonic-gate 		case 0x02: return ("SIF Conf");
6587c478bd9Sstevel@tonic-gate 		case 0x03: return ("SIF Oper");
6597c478bd9Sstevel@tonic-gate 		case 0x04: return ("ECF");
6607c478bd9Sstevel@tonic-gate 		case 0x05: return ("RAF");
6617c478bd9Sstevel@tonic-gate 		case 0x06: return ("RDF");
6627c478bd9Sstevel@tonic-gate 		case 0x07: return ("SRF");
6637c478bd9Sstevel@tonic-gate 		case 0x08: return ("PMF Get");
6647c478bd9Sstevel@tonic-gate 		case 0x09: return ("PMF Change");
6657c478bd9Sstevel@tonic-gate 		case 0x0a: return ("PMF Add");
6667c478bd9Sstevel@tonic-gate 		case 0x0b: return ("PMF Remove");
6677c478bd9Sstevel@tonic-gate 		case 0xff: return ("ESF");
6687c478bd9Sstevel@tonic-gate 		default: return ("Unknown");
6697c478bd9Sstevel@tonic-gate 	}
6707c478bd9Sstevel@tonic-gate 
6717c478bd9Sstevel@tonic-gate }
6727c478bd9Sstevel@tonic-gate char *
print_smttype(uint_t type)6732b24ab6bSSebastien Roy print_smttype(uint_t type)
6747c478bd9Sstevel@tonic-gate {
6757c478bd9Sstevel@tonic-gate 	switch (type) {
6767c478bd9Sstevel@tonic-gate 		case 0x01: return ("Announce");
6777c478bd9Sstevel@tonic-gate 		case 0x02: return ("Request");
6787c478bd9Sstevel@tonic-gate 		case 0x03: return ("Response");
6797c478bd9Sstevel@tonic-gate 		default: return ("Unknown");
6807c478bd9Sstevel@tonic-gate 	}
6817c478bd9Sstevel@tonic-gate 
6827c478bd9Sstevel@tonic-gate }
6837c478bd9Sstevel@tonic-gate char *
print_ethertype(int type)6842b24ab6bSSebastien Roy print_ethertype(int type)
6857c478bd9Sstevel@tonic-gate {
6867c478bd9Sstevel@tonic-gate 	int i;
6877c478bd9Sstevel@tonic-gate 
6887c478bd9Sstevel@tonic-gate 	for (i = 0; ether_type[i].e_type; i++)
6897c478bd9Sstevel@tonic-gate 		if (type == ether_type[i].e_type)
6907c478bd9Sstevel@tonic-gate 			return (ether_type[i].e_name);
6917c478bd9Sstevel@tonic-gate 	if (type < 1500)
6927c478bd9Sstevel@tonic-gate 		return ("LLC/802.3");
6937c478bd9Sstevel@tonic-gate 
6947c478bd9Sstevel@tonic-gate 	return ("Unknown");
6957c478bd9Sstevel@tonic-gate }
6967c478bd9Sstevel@tonic-gate 
6977c478bd9Sstevel@tonic-gate #define	MAX_RDFLDS	14		/* changed to 14 from 8 as per IEEE */
6987c478bd9Sstevel@tonic-gate #define	TR_FN_ADDR	0x80		/* dest addr is functional */
6997c478bd9Sstevel@tonic-gate #define	TR_SR_ADDR	0x80		/* MAC utilizes source route */
7007c478bd9Sstevel@tonic-gate #define	ACFCDASA_LEN	14		/* length of AC|FC|DA|SA */
7017c478bd9Sstevel@tonic-gate #define	TR_MAC_MASK	0xc0
7027c478bd9Sstevel@tonic-gate #define	TR_AC		0x00		/* Token Ring access control */
7037c478bd9Sstevel@tonic-gate #define	TR_LLC_FC	0x40		/* Token Ring llc frame control */
7047c478bd9Sstevel@tonic-gate #define	LSAP_SNAP	0xaa
7057c478bd9Sstevel@tonic-gate #define	LLC_SNAP_HDR_LEN	8
7067c478bd9Sstevel@tonic-gate #define	LLC_HDR1_LEN	3		/* DON'T use sizeof(struct llc_hdr1) */
7077c478bd9Sstevel@tonic-gate #define	CNTL_LLC_UI	0x03		/* un-numbered information packet */
7087c478bd9Sstevel@tonic-gate 
7097c478bd9Sstevel@tonic-gate /*
7107c478bd9Sstevel@tonic-gate  * Source Routing Route Information field.
7117c478bd9Sstevel@tonic-gate  */
7127c478bd9Sstevel@tonic-gate struct tr_ri {
7137c478bd9Sstevel@tonic-gate #if defined(_BIT_FIELDS_HTOL)
7147c478bd9Sstevel@tonic-gate 	uchar_t rt:3;			/* routing type */
7157c478bd9Sstevel@tonic-gate 	uchar_t len:5;			/* length */
7167c478bd9Sstevel@tonic-gate 	uchar_t dir:1;			/* direction bit */
7177c478bd9Sstevel@tonic-gate 	uchar_t mtu:3;			/* largest frame */
7187c478bd9Sstevel@tonic-gate 	uchar_t res:4;			/* reserved */
7197c478bd9Sstevel@tonic-gate #elif defined(_BIT_FIELDS_LTOH)
7207c478bd9Sstevel@tonic-gate 	uchar_t len:5;			/* length */
7217c478bd9Sstevel@tonic-gate 	uchar_t rt:3;			/* routing type */
7227c478bd9Sstevel@tonic-gate 	uchar_t res:4;			/* reserved */
7237c478bd9Sstevel@tonic-gate 	uchar_t mtu:3;			/* largest frame */
7247c478bd9Sstevel@tonic-gate 	uchar_t dir:1;			/* direction bit */
7257c478bd9Sstevel@tonic-gate #endif
7267c478bd9Sstevel@tonic-gate /*
7277c478bd9Sstevel@tonic-gate  * In little endian machine, the ring field has to be stored in a
7287c478bd9Sstevel@tonic-gate  * ushort_t type.  This implies that it is not possible to have a
7297c478bd9Sstevel@tonic-gate  * layout of bit field to represent bridge and ring.
7307c478bd9Sstevel@tonic-gate  *
7317c478bd9Sstevel@tonic-gate  * If the compiler uses _BIT_FIELDS_HTOL and it is a big endian
7327c478bd9Sstevel@tonic-gate  * machine, the following bit field definition will work.
7337c478bd9Sstevel@tonic-gate  *
7347c478bd9Sstevel@tonic-gate  *	struct tr_rd {
7357c478bd9Sstevel@tonic-gate  *		ushort_t bridge:4;
7367c478bd9Sstevel@tonic-gate  *		ushort_t ring:12;
7377c478bd9Sstevel@tonic-gate  *	} rd[MAX_RDFLDS];
7387c478bd9Sstevel@tonic-gate  *
7397c478bd9Sstevel@tonic-gate  * If the compiler uses _BIT_FIELDS_LTOH and it is a big endian
7407c478bd9Sstevel@tonic-gate  * machine, the definition can be changed to
7417c478bd9Sstevel@tonic-gate  *
7427c478bd9Sstevel@tonic-gate  *	struct tr_rd {
7437c478bd9Sstevel@tonic-gate  *		ushort_t bridge:4;
7447c478bd9Sstevel@tonic-gate  *		ushort_t ring:12;
7457c478bd9Sstevel@tonic-gate  *	} rd[MAX_RDFLDS];
7467c478bd9Sstevel@tonic-gate  *
7477c478bd9Sstevel@tonic-gate  * With little endian machine, we need to use 2 macroes.  For
7487c478bd9Sstevel@tonic-gate  * simplicity, since the macroes work for both big and little
7497c478bd9Sstevel@tonic-gate  * endian machines, we will not use bit fields for the
7507c478bd9Sstevel@tonic-gate  * definition.
7517c478bd9Sstevel@tonic-gate  */
7527c478bd9Sstevel@tonic-gate #define	bridge(route)	(ntohs((ushort_t)(route)) & 0x0F)
7537c478bd9Sstevel@tonic-gate #define	ring(route)	(ntohs((ushort_t)(route)) >> 4)
7547c478bd9Sstevel@tonic-gate 
7557c478bd9Sstevel@tonic-gate 	ushort_t rd[MAX_RDFLDS];	/* route designator fields */
7567c478bd9Sstevel@tonic-gate };
7577c478bd9Sstevel@tonic-gate 
7587c478bd9Sstevel@tonic-gate struct tr_header {
7597c478bd9Sstevel@tonic-gate 	uchar_t		ac;
7607c478bd9Sstevel@tonic-gate 	uchar_t		fc;
7617c478bd9Sstevel@tonic-gate 	struct ether_addr dhost;
7627c478bd9Sstevel@tonic-gate 	struct ether_addr shost;
7637c478bd9Sstevel@tonic-gate 	struct tr_ri	ri;
7647c478bd9Sstevel@tonic-gate };
7657c478bd9Sstevel@tonic-gate 
7667c478bd9Sstevel@tonic-gate struct llc_snap_hdr {
7677c478bd9Sstevel@tonic-gate 	uchar_t  d_lsap;		/* destination service access point */
7687c478bd9Sstevel@tonic-gate 	uchar_t  s_lsap;		/* source link service access point */
7697c478bd9Sstevel@tonic-gate 	uchar_t  control;		/* short control field */
7707c478bd9Sstevel@tonic-gate 	uchar_t  org[3];		/* Ethernet style organization field */
7717c478bd9Sstevel@tonic-gate 	ushort_t type;			/* Ethernet style type field */
7727c478bd9Sstevel@tonic-gate };
7737c478bd9Sstevel@tonic-gate 
7747c478bd9Sstevel@tonic-gate struct ether_addr tokenbroadcastaddr2 = {
7757c478bd9Sstevel@tonic-gate 	0xc0, 0x00, 0xff, 0xff, 0xff, 0xff
7767c478bd9Sstevel@tonic-gate };
7777c478bd9Sstevel@tonic-gate 
7787c478bd9Sstevel@tonic-gate int Mtutab[] = {516, 1470, 2052, 4472, 8144, 11407, 17800};
7797c478bd9Sstevel@tonic-gate 
7807c478bd9Sstevel@tonic-gate char *
print_sr(struct tr_ri * rh)7817c478bd9Sstevel@tonic-gate print_sr(struct tr_ri *rh)
7827c478bd9Sstevel@tonic-gate {
7837c478bd9Sstevel@tonic-gate 	int hops, ii;
7847c478bd9Sstevel@tonic-gate 	static char line[512];
7857c478bd9Sstevel@tonic-gate 
7867c478bd9Sstevel@tonic-gate 	sprintf(line, "TR Source Route dir=%d, mtu=%d",
7877c478bd9Sstevel@tonic-gate 	    rh->dir, Mtutab[rh->mtu]);
7887c478bd9Sstevel@tonic-gate 
7897c478bd9Sstevel@tonic-gate 	hops = (int)(rh->len - 2) / (int)2;
7907c478bd9Sstevel@tonic-gate 
7917c478bd9Sstevel@tonic-gate 	if (hops) {
7927c478bd9Sstevel@tonic-gate 		sprintf(line+strlen(line), ", Route: ");
7937c478bd9Sstevel@tonic-gate 		for (ii = 0; ii < hops; ii++) {
7947c478bd9Sstevel@tonic-gate 			if (! bridge(rh->rd[ii])) {
7957c478bd9Sstevel@tonic-gate 				sprintf(line+strlen(line), "(%d)",
7967c478bd9Sstevel@tonic-gate 				    ring(rh->rd[ii]));
7977c478bd9Sstevel@tonic-gate 			} else {
7987c478bd9Sstevel@tonic-gate 				sprintf(line+strlen(line), "(%d)%d",
7997c478bd9Sstevel@tonic-gate 				    ring(rh->rd[ii]), bridge(rh->rd[ii]));
8007c478bd9Sstevel@tonic-gate 			}
8017c478bd9Sstevel@tonic-gate 		}
8027c478bd9Sstevel@tonic-gate 	}
8037c478bd9Sstevel@tonic-gate 	return (&line[0]);
8047c478bd9Sstevel@tonic-gate }
8057c478bd9Sstevel@tonic-gate 
8067c478bd9Sstevel@tonic-gate uint_t
interpret_tr(int flags,caddr_t e,int elen,int origlen)8072b24ab6bSSebastien Roy interpret_tr(int flags, caddr_t e, int elen, int origlen)
8087c478bd9Sstevel@tonic-gate {
8097c478bd9Sstevel@tonic-gate 	struct tr_header *mh;
8107c478bd9Sstevel@tonic-gate 	struct tr_ri *rh;
8117c478bd9Sstevel@tonic-gate 	uchar_t fc;
8127c478bd9Sstevel@tonic-gate 	struct llc_snap_hdr *snaphdr;
8137c478bd9Sstevel@tonic-gate 	char *off;
8147c478bd9Sstevel@tonic-gate 	int maclen, len;
8157c478bd9Sstevel@tonic-gate 	boolean_t data_copied = B_FALSE;
8167c478bd9Sstevel@tonic-gate 	extern char *dst_name, *src_name;
8177c478bd9Sstevel@tonic-gate 	int ethertype;
8187c478bd9Sstevel@tonic-gate 	int is_llc = 0, is_snap = 0, source_routing = 0;
8197c478bd9Sstevel@tonic-gate 	int blen = MAX(origlen, 17800);
8207c478bd9Sstevel@tonic-gate 
8217c478bd9Sstevel@tonic-gate 	if (data != NULL && datalen != 0 && datalen < blen) {
8227c478bd9Sstevel@tonic-gate 		free(data);
8237c478bd9Sstevel@tonic-gate 		data = NULL;
8247c478bd9Sstevel@tonic-gate 		datalen = 0;
8257c478bd9Sstevel@tonic-gate 	}
8267c478bd9Sstevel@tonic-gate 	if (!data) {
8277c478bd9Sstevel@tonic-gate 		data = (char *)malloc(blen);
8287c478bd9Sstevel@tonic-gate 		if (!data)
8297c478bd9Sstevel@tonic-gate 			pr_err("Warning: malloc failure");
8307c478bd9Sstevel@tonic-gate 		datalen = blen;
8317c478bd9Sstevel@tonic-gate 	}
8327c478bd9Sstevel@tonic-gate 
8337c478bd9Sstevel@tonic-gate 	if (origlen < ACFCDASA_LEN) {
8342b24ab6bSSebastien Roy 		if (flags & F_SUM) {
8357c478bd9Sstevel@tonic-gate 			(void) sprintf(get_sum_line(),
8367c478bd9Sstevel@tonic-gate 			    "RUNT (short packet - %d bytes)",
8377c478bd9Sstevel@tonic-gate 			    origlen);
8382b24ab6bSSebastien Roy 		}
8397c478bd9Sstevel@tonic-gate 		if (flags & F_DTAIL)
8407c478bd9Sstevel@tonic-gate 			show_header("RUNT:  ", "Short packet", origlen);
8417c478bd9Sstevel@tonic-gate 		return (elen);
8427c478bd9Sstevel@tonic-gate 	}
8437c478bd9Sstevel@tonic-gate 	if (elen < ACFCDASA_LEN)
8447c478bd9Sstevel@tonic-gate 		return (elen);
8457c478bd9Sstevel@tonic-gate 
8467c478bd9Sstevel@tonic-gate 	mh = (struct tr_header *)e;
8477c478bd9Sstevel@tonic-gate 	rh = (struct tr_ri *)&mh->ri;
8487c478bd9Sstevel@tonic-gate 	fc = mh->fc;
8497c478bd9Sstevel@tonic-gate 
8507c478bd9Sstevel@tonic-gate 	if (is_llc = tr_machdr_len(e, &maclen, &source_routing)) {
8517c478bd9Sstevel@tonic-gate 		snaphdr = (struct llc_snap_hdr *)(e + maclen);
8527c478bd9Sstevel@tonic-gate 		if (snaphdr->d_lsap == LSAP_SNAP &&
8537c478bd9Sstevel@tonic-gate 		    snaphdr->s_lsap == LSAP_SNAP &&
8547c478bd9Sstevel@tonic-gate 		    snaphdr->control == CNTL_LLC_UI) {
8557c478bd9Sstevel@tonic-gate 			is_snap = 1;
8567c478bd9Sstevel@tonic-gate 		}
8577c478bd9Sstevel@tonic-gate 	}
8587c478bd9Sstevel@tonic-gate 
8597c478bd9Sstevel@tonic-gate 	if (memcmp(&mh->dhost, &ether_broadcast,
8607c478bd9Sstevel@tonic-gate 	    sizeof (struct ether_addr)) == 0)
8617c478bd9Sstevel@tonic-gate 		dst_name = "(broadcast)";
8627c478bd9Sstevel@tonic-gate 	else if (memcmp(&mh->dhost, &tokenbroadcastaddr2,
8637c478bd9Sstevel@tonic-gate 	    sizeof (struct ether_addr)) == 0)
8647c478bd9Sstevel@tonic-gate 		dst_name = "(mac broadcast)";
8657c478bd9Sstevel@tonic-gate 	else if (mh->dhost.ether_addr_octet[0] & TR_FN_ADDR)
8667c478bd9Sstevel@tonic-gate 		dst_name = "(functional)";
8677c478bd9Sstevel@tonic-gate 
8687c478bd9Sstevel@tonic-gate 	if (is_snap)
8697c478bd9Sstevel@tonic-gate 		ethertype = ntohs(snaphdr->type);
8707c478bd9Sstevel@tonic-gate 	else {
8717c478bd9Sstevel@tonic-gate 		src_name =  print_etherinfo(&mh->shost);
8727c478bd9Sstevel@tonic-gate 		dst_name =  print_etherinfo(&mh->dhost);
8737c478bd9Sstevel@tonic-gate 	}
8747c478bd9Sstevel@tonic-gate 
8757c478bd9Sstevel@tonic-gate 	/*
8767c478bd9Sstevel@tonic-gate 	 * The 14 byte ether header screws up alignment
8777c478bd9Sstevel@tonic-gate 	 * of the rest of the packet for 32 bit aligned
8787c478bd9Sstevel@tonic-gate 	 * architectures like SPARC. Alas, we have to copy
8797c478bd9Sstevel@tonic-gate 	 * the rest of the packet in order to align it.
8807c478bd9Sstevel@tonic-gate 	 */
8817c478bd9Sstevel@tonic-gate 	if (is_llc) {
8827c478bd9Sstevel@tonic-gate 		if (is_snap) {
8837c478bd9Sstevel@tonic-gate 			len = elen - (maclen + LLC_SNAP_HDR_LEN);
8847c478bd9Sstevel@tonic-gate 			off = (char *)(e + maclen + LLC_SNAP_HDR_LEN);
8857c478bd9Sstevel@tonic-gate 		} else {
8867c478bd9Sstevel@tonic-gate 			len = elen - (maclen + LLC_HDR1_LEN);
8877c478bd9Sstevel@tonic-gate 			off = (char *)(e + maclen + LLC_HDR1_LEN);
8887c478bd9Sstevel@tonic-gate 		}
8897c478bd9Sstevel@tonic-gate 	} else {
8907c478bd9Sstevel@tonic-gate 		len = elen - maclen;
8917c478bd9Sstevel@tonic-gate 		off = (char *)(e + maclen);
8927c478bd9Sstevel@tonic-gate 	}
8937c478bd9Sstevel@tonic-gate 
8947c478bd9Sstevel@tonic-gate 	if (len > 0 && (off + len <= (char *)e + elen)) {
8957c478bd9Sstevel@tonic-gate 		(void) memcpy(data, off, len);
8967c478bd9Sstevel@tonic-gate 		data_copied = B_TRUE;
8977c478bd9Sstevel@tonic-gate 	}
8987c478bd9Sstevel@tonic-gate 
8997c478bd9Sstevel@tonic-gate 	if (flags & F_SUM) {
9007c478bd9Sstevel@tonic-gate 		if (source_routing)
9017c478bd9Sstevel@tonic-gate 			sprintf(get_sum_line(), print_sr(rh));
9027c478bd9Sstevel@tonic-gate 
9037c478bd9Sstevel@tonic-gate 		if (is_llc) {
9047c478bd9Sstevel@tonic-gate 			if (is_snap) {
9052b24ab6bSSebastien Roy 				(void) sprintf(get_sum_line(), "TR LLC w/SNAP "
9062b24ab6bSSebastien Roy 				    "Type=%04X (%s), size=%d bytes",
9077c478bd9Sstevel@tonic-gate 				    ethertype,
9087c478bd9Sstevel@tonic-gate 				    print_ethertype(ethertype),
9097c478bd9Sstevel@tonic-gate 				    origlen);
9107c478bd9Sstevel@tonic-gate 			} else {
9112b24ab6bSSebastien Roy 				(void) sprintf(get_sum_line(), "TR LLC, but no "
9122b24ab6bSSebastien Roy 				    "SNAP encoding, size = %d bytes",
9137c478bd9Sstevel@tonic-gate 				    origlen);
9147c478bd9Sstevel@tonic-gate 			}
9157c478bd9Sstevel@tonic-gate 		} else {
9167c478bd9Sstevel@tonic-gate 			(void) sprintf(get_sum_line(),
9177c478bd9Sstevel@tonic-gate 			    "TR MAC FC=%02X (%s), size = %d bytes",
9187c478bd9Sstevel@tonic-gate 			    fc, print_fc(fc), origlen);
9197c478bd9Sstevel@tonic-gate 		}
9207c478bd9Sstevel@tonic-gate 	}
9217c478bd9Sstevel@tonic-gate 
9227c478bd9Sstevel@tonic-gate 	if (flags & F_DTAIL) {
9237c478bd9Sstevel@tonic-gate 		show_header("TR:  ", "TR Header", elen);
9247c478bd9Sstevel@tonic-gate 		show_space();
9257c478bd9Sstevel@tonic-gate 		(void) sprintf(get_line(0, 0),
9267c478bd9Sstevel@tonic-gate 		    "Packet %d arrived at %d:%02d:%d.%05d",
9277c478bd9Sstevel@tonic-gate 		    pi_frame,
9287c478bd9Sstevel@tonic-gate 		    pi_time_hour, pi_time_min, pi_time_sec,
9297c478bd9Sstevel@tonic-gate 		    pi_time_usec / 10);
9307c478bd9Sstevel@tonic-gate 		(void) sprintf(get_line(0, 0),
9317c478bd9Sstevel@tonic-gate 		    "Packet size = %d bytes",
9327c478bd9Sstevel@tonic-gate 		    elen);
9337c478bd9Sstevel@tonic-gate 		(void) sprintf(get_line(0, 1),
9347c478bd9Sstevel@tonic-gate 		    "Frame Control = %02x (%s)",
9357c478bd9Sstevel@tonic-gate 		    fc, print_fc(fc));
9367c478bd9Sstevel@tonic-gate 		(void) sprintf(get_line(2, 6),
9377c478bd9Sstevel@tonic-gate 		    "Destination = %s, %s",
9387c478bd9Sstevel@tonic-gate 		    printether(&mh->dhost),
9397c478bd9Sstevel@tonic-gate 		    print_etherinfo(&mh->dhost));
9407c478bd9Sstevel@tonic-gate 		(void) sprintf(get_line(8, 6),
9417c478bd9Sstevel@tonic-gate 		    "Source      = %s, %s",
9427c478bd9Sstevel@tonic-gate 		    printether(&mh->shost),
9437c478bd9Sstevel@tonic-gate 		    print_etherinfo(&mh->shost));
9447c478bd9Sstevel@tonic-gate 
9457c478bd9Sstevel@tonic-gate 		if (source_routing)
9467c478bd9Sstevel@tonic-gate 			sprintf(get_line(ACFCDASA_LEN, rh->len), print_sr(rh));
9477c478bd9Sstevel@tonic-gate 
9487c478bd9Sstevel@tonic-gate 		if (is_llc) {
9497c478bd9Sstevel@tonic-gate 			(void) sprintf(get_line(maclen, 1),
9507c478bd9Sstevel@tonic-gate 			    "Dest   Service Access Point = %02x",
9517c478bd9Sstevel@tonic-gate 			    snaphdr->d_lsap);
9527c478bd9Sstevel@tonic-gate 			(void) sprintf(get_line(maclen+1, 1),
9537c478bd9Sstevel@tonic-gate 			    "Source Service Access Point = %02x",
9547c478bd9Sstevel@tonic-gate 			    snaphdr->s_lsap);
9557c478bd9Sstevel@tonic-gate 			(void) sprintf(get_line(maclen+2, 1),
9567c478bd9Sstevel@tonic-gate 			    "Control = %02x",
9577c478bd9Sstevel@tonic-gate 			    snaphdr->control);
9582b24ab6bSSebastien Roy 			if (is_snap) {
9597c478bd9Sstevel@tonic-gate 				(void) sprintf(get_line(maclen+3, 3),
9607c478bd9Sstevel@tonic-gate 				    "SNAP Protocol Id = %02x%02x%02x",
9617c478bd9Sstevel@tonic-gate 				    snaphdr->org[0], snaphdr->org[1],
9627c478bd9Sstevel@tonic-gate 				    snaphdr->org[2]);
9637c478bd9Sstevel@tonic-gate 			}
9642b24ab6bSSebastien Roy 		}
9657c478bd9Sstevel@tonic-gate 
9662b24ab6bSSebastien Roy 		if (is_snap) {
9677c478bd9Sstevel@tonic-gate 			(void) sprintf(get_line(maclen+6, 2),
9687c478bd9Sstevel@tonic-gate 			    "SNAP Type = %04X (%s)",
9697c478bd9Sstevel@tonic-gate 			    ethertype, print_ethertype(ethertype));
9702b24ab6bSSebastien Roy 		}
9717c478bd9Sstevel@tonic-gate 
9727c478bd9Sstevel@tonic-gate 		show_space();
9737c478bd9Sstevel@tonic-gate 	}
9747c478bd9Sstevel@tonic-gate 
9757c478bd9Sstevel@tonic-gate 	/* go to the next protocol layer */
9767c478bd9Sstevel@tonic-gate 	if (is_snap && data_copied) {
9777c478bd9Sstevel@tonic-gate 		switch (ethertype) {
9787c478bd9Sstevel@tonic-gate 		case ETHERTYPE_IP:
9797c478bd9Sstevel@tonic-gate 			(void) interpret_ip(flags, (struct ip *)data, len);
9807c478bd9Sstevel@tonic-gate 			break;
9817c478bd9Sstevel@tonic-gate 		/* Just in case it is decided to add this type */
9827c478bd9Sstevel@tonic-gate 		case ETHERTYPE_IPV6:
9837c478bd9Sstevel@tonic-gate 			(void) interpret_ipv6(flags, (ip6_t *)data, len);
9847c478bd9Sstevel@tonic-gate 			break;
9857c478bd9Sstevel@tonic-gate 		case ETHERTYPE_ARP:
9867c478bd9Sstevel@tonic-gate 		case ETHERTYPE_REVARP:
9877c478bd9Sstevel@tonic-gate 			interpret_arp(flags, (struct arphdr *)data, len);
9887c478bd9Sstevel@tonic-gate 			break;
9897c478bd9Sstevel@tonic-gate 		case ETHERTYPE_AARP:	/* AppleTalk */
9907c478bd9Sstevel@tonic-gate 			interpret_aarp(flags, data, len);
9917c478bd9Sstevel@tonic-gate 			break;
9927c478bd9Sstevel@tonic-gate 		case ETHERTYPE_AT:
9937c478bd9Sstevel@tonic-gate 			interpret_at(flags, (struct ddp_hdr *)data, len);
9947c478bd9Sstevel@tonic-gate 			break;
9957c478bd9Sstevel@tonic-gate 		default:
9967c478bd9Sstevel@tonic-gate 			break;
9977c478bd9Sstevel@tonic-gate 		}
9987c478bd9Sstevel@tonic-gate 	}
9997c478bd9Sstevel@tonic-gate 
10007c478bd9Sstevel@tonic-gate 	return (elen);
10017c478bd9Sstevel@tonic-gate }
10027c478bd9Sstevel@tonic-gate 
10037c478bd9Sstevel@tonic-gate 
10047c478bd9Sstevel@tonic-gate /*
10057c478bd9Sstevel@tonic-gate  *	stuffs length of mac and ri fields into *lenp
10067c478bd9Sstevel@tonic-gate  *	returns:
10077c478bd9Sstevel@tonic-gate  *		0: mac frame
10087c478bd9Sstevel@tonic-gate  *		1: llc frame
10097c478bd9Sstevel@tonic-gate  */
10102b24ab6bSSebastien Roy static int
tr_machdr_len(char * e,int * lenp,int * source_routing)10117c478bd9Sstevel@tonic-gate tr_machdr_len(char *e, int *lenp, int *source_routing)
10127c478bd9Sstevel@tonic-gate {
10137c478bd9Sstevel@tonic-gate 	struct tr_header *mh;
10147c478bd9Sstevel@tonic-gate 	struct tr_ri *rh;
10157c478bd9Sstevel@tonic-gate 	uchar_t fc;
10167c478bd9Sstevel@tonic-gate 
10177c478bd9Sstevel@tonic-gate 	mh = (struct tr_header *)e;
10187c478bd9Sstevel@tonic-gate 	rh = (struct tr_ri *)&mh->ri;
10197c478bd9Sstevel@tonic-gate 	fc = mh->fc;
10207c478bd9Sstevel@tonic-gate 
10217c478bd9Sstevel@tonic-gate 	if (mh->shost.ether_addr_octet[0] & TR_SR_ADDR) {
10227c478bd9Sstevel@tonic-gate 		*lenp = ACFCDASA_LEN + rh->len;
10237c478bd9Sstevel@tonic-gate 		*source_routing = 1;
10247c478bd9Sstevel@tonic-gate 	} else {
10257c478bd9Sstevel@tonic-gate 		*lenp = ACFCDASA_LEN;
10267c478bd9Sstevel@tonic-gate 		*source_routing = 0;
10277c478bd9Sstevel@tonic-gate 	}
10287c478bd9Sstevel@tonic-gate 
10297c478bd9Sstevel@tonic-gate 	if ((fc & TR_MAC_MASK) == 0)
10307c478bd9Sstevel@tonic-gate 		return (0);		/* it's a MAC frame */
10317c478bd9Sstevel@tonic-gate 	else
10327c478bd9Sstevel@tonic-gate 		return (1);		/* it's an LLC frame */
10337c478bd9Sstevel@tonic-gate }
10347c478bd9Sstevel@tonic-gate 
10357c478bd9Sstevel@tonic-gate uint_t
tr_header_len(char * e,size_t msgsize)10362b24ab6bSSebastien Roy tr_header_len(char *e, size_t msgsize)
10377c478bd9Sstevel@tonic-gate {
10387c478bd9Sstevel@tonic-gate 	struct llc_snap_hdr *snaphdr;
10397c478bd9Sstevel@tonic-gate 	int len = 0, source_routing;
10407c478bd9Sstevel@tonic-gate 
10417c478bd9Sstevel@tonic-gate 	if (tr_machdr_len(e, &len, &source_routing) == 0)
10427c478bd9Sstevel@tonic-gate 		return (len);		/* it's a MAC frame */
10437c478bd9Sstevel@tonic-gate 
10442b24ab6bSSebastien Roy 	if (msgsize < sizeof (struct llc_snap_hdr))
10452b24ab6bSSebastien Roy 		return (0);
10462b24ab6bSSebastien Roy 
10477c478bd9Sstevel@tonic-gate 	snaphdr = (struct llc_snap_hdr *)(e + len);
10487c478bd9Sstevel@tonic-gate 	if (snaphdr->d_lsap == LSAP_SNAP &&
10497c478bd9Sstevel@tonic-gate 	    snaphdr->s_lsap == LSAP_SNAP &&
10507c478bd9Sstevel@tonic-gate 	    snaphdr->control == CNTL_LLC_UI)
10517c478bd9Sstevel@tonic-gate 		len += LLC_SNAP_HDR_LEN;	/* it's a SNAP frame */
10527c478bd9Sstevel@tonic-gate 	else
10537c478bd9Sstevel@tonic-gate 		len += LLC_HDR1_LEN;
10547c478bd9Sstevel@tonic-gate 
10557c478bd9Sstevel@tonic-gate 	return (len);
10567c478bd9Sstevel@tonic-gate }
10577c478bd9Sstevel@tonic-gate 
10587c478bd9Sstevel@tonic-gate struct fddi_header {
10597c478bd9Sstevel@tonic-gate 	uchar_t fc;
10607c478bd9Sstevel@tonic-gate 	struct ether_addr dhost, shost;
10617c478bd9Sstevel@tonic-gate 	uchar_t dsap, ssap, ctl, proto_id[3];
10627c478bd9Sstevel@tonic-gate 	ushort_t	type;
10637c478bd9Sstevel@tonic-gate };
10647c478bd9Sstevel@tonic-gate 
10657c478bd9Sstevel@tonic-gate uint_t
interpret_fddi(int flags,caddr_t e,int elen,int origlen)10662b24ab6bSSebastien Roy interpret_fddi(int flags, caddr_t e, int elen, int origlen)
10677c478bd9Sstevel@tonic-gate {
10687c478bd9Sstevel@tonic-gate 	struct fddi_header fhdr, *f = &fhdr;
10697c478bd9Sstevel@tonic-gate 	char *off;
10707c478bd9Sstevel@tonic-gate 	int len;
10717c478bd9Sstevel@tonic-gate 	boolean_t data_copied = B_FALSE;
10727c478bd9Sstevel@tonic-gate 	extern char *dst_name, *src_name;
10737c478bd9Sstevel@tonic-gate 	int ethertype;
10747c478bd9Sstevel@tonic-gate 	int is_llc = 0, is_smt = 0, is_snap = 0;
10757c478bd9Sstevel@tonic-gate 	int blen = MAX(origlen, 4500);
10767c478bd9Sstevel@tonic-gate 
10777c478bd9Sstevel@tonic-gate 	if (data != NULL && datalen != 0 && datalen < blen) {
10787c478bd9Sstevel@tonic-gate 		free(data);
10797c478bd9Sstevel@tonic-gate 		data = NULL;
10807c478bd9Sstevel@tonic-gate 		datalen = 0;
10817c478bd9Sstevel@tonic-gate 	}
10827c478bd9Sstevel@tonic-gate 	if (!data) {
10837c478bd9Sstevel@tonic-gate 		data = (char *)malloc(blen);
10847c478bd9Sstevel@tonic-gate 		if (!data)
10857c478bd9Sstevel@tonic-gate 			pr_err("Warning: malloc failure");
10867c478bd9Sstevel@tonic-gate 		datalen = blen;
10877c478bd9Sstevel@tonic-gate 	}
10887c478bd9Sstevel@tonic-gate 
10897c478bd9Sstevel@tonic-gate 	if (origlen < 13) {
10902b24ab6bSSebastien Roy 		if (flags & F_SUM) {
10917c478bd9Sstevel@tonic-gate 			(void) sprintf(get_sum_line(),
10927c478bd9Sstevel@tonic-gate 			    "RUNT (short packet - %d bytes)",
10937c478bd9Sstevel@tonic-gate 			    origlen);
10942b24ab6bSSebastien Roy 		}
10957c478bd9Sstevel@tonic-gate 		if (flags & F_DTAIL)
10967c478bd9Sstevel@tonic-gate 			show_header("RUNT:  ", "Short packet", origlen);
10977c478bd9Sstevel@tonic-gate 		return (elen);
10987c478bd9Sstevel@tonic-gate 	}
10997c478bd9Sstevel@tonic-gate 	if (elen < 13)
11007c478bd9Sstevel@tonic-gate 		return (elen);
11017c478bd9Sstevel@tonic-gate 
11027c478bd9Sstevel@tonic-gate 	(void) memcpy(&f->fc, e, sizeof (f->fc));
11037c478bd9Sstevel@tonic-gate 	addr_copy_swap(&f->dhost, (struct ether_addr *)(e+1));
11047c478bd9Sstevel@tonic-gate 	addr_copy_swap(&f->shost, (struct ether_addr *)(e+7));
11057c478bd9Sstevel@tonic-gate 
11067c478bd9Sstevel@tonic-gate 	if ((f->fc&0x50) == 0x50) {
11077c478bd9Sstevel@tonic-gate 		is_llc = 1;
11087c478bd9Sstevel@tonic-gate 		(void) memcpy(&f->dsap, e+13, sizeof (f->dsap));
11097c478bd9Sstevel@tonic-gate 		(void) memcpy(&f->ssap, e+14, sizeof (f->ssap));
11107c478bd9Sstevel@tonic-gate 		(void) memcpy(&f->ctl, e+15, sizeof (f->ctl));
11117c478bd9Sstevel@tonic-gate 		if (f->dsap == 0xaa && f->ssap == 0xaa) {
11127c478bd9Sstevel@tonic-gate 			is_snap = 1;
11137c478bd9Sstevel@tonic-gate 			(void) memcpy(&f->proto_id, e+16, sizeof (f->proto_id));
11147c478bd9Sstevel@tonic-gate 			(void) memcpy(&f->type, e+19, sizeof (f->type));
11157c478bd9Sstevel@tonic-gate 		}
11167c478bd9Sstevel@tonic-gate 	} else {
11177c478bd9Sstevel@tonic-gate 		if ((f->fc&0x41) == 0x41 || (f->fc&0x4f) == 0x4f) {
11187c478bd9Sstevel@tonic-gate 			is_smt = 1;
11197c478bd9Sstevel@tonic-gate 		}
11207c478bd9Sstevel@tonic-gate 	}
11217c478bd9Sstevel@tonic-gate 
11227c478bd9Sstevel@tonic-gate 
11237c478bd9Sstevel@tonic-gate 	if (memcmp(&f->dhost, &ether_broadcast,
11247c478bd9Sstevel@tonic-gate 	    sizeof (struct ether_addr)) == 0)
11257c478bd9Sstevel@tonic-gate 		dst_name = "(broadcast)";
11267c478bd9Sstevel@tonic-gate 	else if (f->dhost.ether_addr_octet[0] & 0x01)
11277c478bd9Sstevel@tonic-gate 		dst_name = "(multicast)";
11287c478bd9Sstevel@tonic-gate 
11297c478bd9Sstevel@tonic-gate 	if (is_snap)
11307c478bd9Sstevel@tonic-gate 		ethertype = ntohs(f->type);
11317c478bd9Sstevel@tonic-gate 	else {
11327c478bd9Sstevel@tonic-gate 		src_name = 	print_etherinfo(&f->shost);
11337c478bd9Sstevel@tonic-gate 		dst_name =  print_etherinfo(&f->dhost);
11347c478bd9Sstevel@tonic-gate 	}
11357c478bd9Sstevel@tonic-gate 
11367c478bd9Sstevel@tonic-gate 	/*
11377c478bd9Sstevel@tonic-gate 	 * The 14 byte ether header screws up alignment
11387c478bd9Sstevel@tonic-gate 	 * of the rest of the packet for 32 bit aligned
11397c478bd9Sstevel@tonic-gate 	 * architectures like SPARC. Alas, we have to copy
11407c478bd9Sstevel@tonic-gate 	 * the rest of the packet in order to align it.
11417c478bd9Sstevel@tonic-gate 	 */
11427c478bd9Sstevel@tonic-gate 	if (is_llc) {
11437c478bd9Sstevel@tonic-gate 		if (is_snap) {
11447c478bd9Sstevel@tonic-gate 			len = elen - 21;
11457c478bd9Sstevel@tonic-gate 			off = (char *)(e + 21);
11467c478bd9Sstevel@tonic-gate 		} else {
11477c478bd9Sstevel@tonic-gate 			len = elen - 16;
11487c478bd9Sstevel@tonic-gate 			off = (char *)(e + 16);
11497c478bd9Sstevel@tonic-gate 		}
11507c478bd9Sstevel@tonic-gate 	} else {
11517c478bd9Sstevel@tonic-gate 		len = elen - 13;
11527c478bd9Sstevel@tonic-gate 		off = (char *)(e + 13);
11537c478bd9Sstevel@tonic-gate 	}
11547c478bd9Sstevel@tonic-gate 
11557c478bd9Sstevel@tonic-gate 	if (len > 0 && (off + len <= (char *)e + elen)) {
11567c478bd9Sstevel@tonic-gate 		(void) memcpy(data, off, len);
11577c478bd9Sstevel@tonic-gate 		data_copied = B_TRUE;
11587c478bd9Sstevel@tonic-gate 	}
11597c478bd9Sstevel@tonic-gate 
11607c478bd9Sstevel@tonic-gate 	if (flags & F_SUM) {
11617c478bd9Sstevel@tonic-gate 		if (is_llc) {
11627c478bd9Sstevel@tonic-gate 			if (is_snap) {
11637c478bd9Sstevel@tonic-gate 				(void) sprintf(get_sum_line(),
11647c478bd9Sstevel@tonic-gate 				    "FDDI LLC Type=%04X (%s), size = %d bytes",
11657c478bd9Sstevel@tonic-gate 				    ethertype,
11667c478bd9Sstevel@tonic-gate 				    print_ethertype(ethertype),
11677c478bd9Sstevel@tonic-gate 				    origlen);
11687c478bd9Sstevel@tonic-gate 			} else {
11692b24ab6bSSebastien Roy 				(void) sprintf(get_sum_line(), "LLC, but no "
11702b24ab6bSSebastien Roy 				    "SNAP encoding, size = %d bytes",
11717c478bd9Sstevel@tonic-gate 				    origlen);
11727c478bd9Sstevel@tonic-gate 			}
11737c478bd9Sstevel@tonic-gate 		} else if (is_smt) {
11742b24ab6bSSebastien Roy 			(void) sprintf(get_sum_line(), "SMT Type=%02X (%s), "
11752b24ab6bSSebastien Roy 			    "Class = %02X (%s), size = %d bytes",
11762b24ab6bSSebastien Roy 			    *(uchar_t *)(data+1), print_smttype(*(data+1)),
11772b24ab6bSSebastien Roy 			    *data, print_smtclass(*data), origlen);
11787c478bd9Sstevel@tonic-gate 		} else {
11797c478bd9Sstevel@tonic-gate 			(void) sprintf(get_sum_line(),
11807c478bd9Sstevel@tonic-gate 			    "FC=%02X (%s), size = %d bytes",
11817c478bd9Sstevel@tonic-gate 			    f->fc, print_fc(f->fc), origlen);
11827c478bd9Sstevel@tonic-gate 		}
11837c478bd9Sstevel@tonic-gate 	}
11847c478bd9Sstevel@tonic-gate 
11857c478bd9Sstevel@tonic-gate 	if (flags & F_DTAIL) {
11867c478bd9Sstevel@tonic-gate 		show_header("FDDI:  ", "FDDI Header", elen);
11877c478bd9Sstevel@tonic-gate 		show_space();
11887c478bd9Sstevel@tonic-gate 		(void) sprintf(get_line(0, 0),
11897c478bd9Sstevel@tonic-gate 		    "Packet %d arrived at %d:%02d:%d.%05d",
11907c478bd9Sstevel@tonic-gate 		    pi_frame,
11917c478bd9Sstevel@tonic-gate 		    pi_time_hour, pi_time_min, pi_time_sec,
11927c478bd9Sstevel@tonic-gate 		    pi_time_usec / 10);
11937c478bd9Sstevel@tonic-gate 		(void) sprintf(get_line(0, 0),
11947c478bd9Sstevel@tonic-gate 		    "Packet size = %d bytes",
11957c478bd9Sstevel@tonic-gate 		    elen, elen);
11967c478bd9Sstevel@tonic-gate 		(void) sprintf(get_line(0, 6),
11977c478bd9Sstevel@tonic-gate 		    "Destination = %s, %s",
11987c478bd9Sstevel@tonic-gate 		    printether(&f->dhost),
11997c478bd9Sstevel@tonic-gate 		    print_etherinfo(&f->dhost));
12007c478bd9Sstevel@tonic-gate 		(void) sprintf(get_line(6, 6),
12017c478bd9Sstevel@tonic-gate 		    "Source      = %s, %s",
12027c478bd9Sstevel@tonic-gate 		    printether(&f->shost),
12037c478bd9Sstevel@tonic-gate 		    print_etherinfo(&f->shost));
12047c478bd9Sstevel@tonic-gate 
12057c478bd9Sstevel@tonic-gate 		if (is_llc) {
12067c478bd9Sstevel@tonic-gate 			(void) sprintf(get_line(12, 2),
12077c478bd9Sstevel@tonic-gate 			    "Frame Control = %02x (%s)",
12087c478bd9Sstevel@tonic-gate 			    f->fc, print_fc(f->fc));
12097c478bd9Sstevel@tonic-gate 			(void) sprintf(get_line(12, 2),
12107c478bd9Sstevel@tonic-gate 			    "Dest   Service Access Point = %02x",
12117c478bd9Sstevel@tonic-gate 			    f->dsap);
12127c478bd9Sstevel@tonic-gate 			(void) sprintf(get_line(12, 2),
12137c478bd9Sstevel@tonic-gate 			    "Source Service Access Point = %02x",
12147c478bd9Sstevel@tonic-gate 			    f->ssap);
12157c478bd9Sstevel@tonic-gate 			(void) sprintf(get_line(12, 2),
12167c478bd9Sstevel@tonic-gate 			    "Control = %02x",
12177c478bd9Sstevel@tonic-gate 			    f->ctl);
12182b24ab6bSSebastien Roy 			if (is_snap) {
12197c478bd9Sstevel@tonic-gate 				(void) sprintf(get_line(12, 2),
12207c478bd9Sstevel@tonic-gate 				    "Protocol Id = %02x%02x%02x",
12212b24ab6bSSebastien Roy 				    f->proto_id[0], f->proto_id[1],
12222b24ab6bSSebastien Roy 				    f->proto_id[2]);
12232b24ab6bSSebastien Roy 			}
12247c478bd9Sstevel@tonic-gate 		} else if (is_smt) {
12257c478bd9Sstevel@tonic-gate 			(void) sprintf(get_line(12, 2),
12267c478bd9Sstevel@tonic-gate 			    "Frame Control = %02x (%s)",
12277c478bd9Sstevel@tonic-gate 			    f->fc, print_fc(f->fc));
12287c478bd9Sstevel@tonic-gate 			(void) sprintf(get_line(12, 2),
12297c478bd9Sstevel@tonic-gate 			    "Class = %02x (%s)",
12307c478bd9Sstevel@tonic-gate 			    (uchar_t)*data, print_smtclass(*data));
12317c478bd9Sstevel@tonic-gate 			(void) sprintf(get_line(12, 2),
12327c478bd9Sstevel@tonic-gate 			    "Type = %02x (%s)",
12337c478bd9Sstevel@tonic-gate 			    *(uchar_t *)(data+1), print_smttype(*(data+1)));
12347c478bd9Sstevel@tonic-gate 		} else {
12357c478bd9Sstevel@tonic-gate 			(void) sprintf(get_line(12, 2),
12367c478bd9Sstevel@tonic-gate 			    "FC=%02X (%s), size = %d bytes",
12377c478bd9Sstevel@tonic-gate 			    f->fc, print_fc(f->fc), origlen);
12387c478bd9Sstevel@tonic-gate 		}
12397c478bd9Sstevel@tonic-gate 
12402b24ab6bSSebastien Roy 		if (is_snap) {
12417c478bd9Sstevel@tonic-gate 			(void) sprintf(get_line(12, 2),
12427c478bd9Sstevel@tonic-gate 			    "LLC Type = %04X (%s)",
12437c478bd9Sstevel@tonic-gate 			    ethertype, print_ethertype(ethertype));
12442b24ab6bSSebastien Roy 		}
12457c478bd9Sstevel@tonic-gate 
12467c478bd9Sstevel@tonic-gate 		show_space();
12477c478bd9Sstevel@tonic-gate 	}
12487c478bd9Sstevel@tonic-gate 
12497c478bd9Sstevel@tonic-gate 	/* go to the next protocol layer */
12507c478bd9Sstevel@tonic-gate 	if (is_llc && is_snap && f->ctl == 0x03 && data_copied) {
12517c478bd9Sstevel@tonic-gate 		switch (ethertype) {
12527c478bd9Sstevel@tonic-gate 		case ETHERTYPE_IP:
12537c478bd9Sstevel@tonic-gate 			(void) interpret_ip(flags, (struct ip *)data, len);
12547c478bd9Sstevel@tonic-gate 			break;
12557c478bd9Sstevel@tonic-gate 		/* Just in case it is decided to add this type */
12567c478bd9Sstevel@tonic-gate 		case ETHERTYPE_IPV6:
12577c478bd9Sstevel@tonic-gate 			(void) interpret_ipv6(flags, (ip6_t *)data, len);
12587c478bd9Sstevel@tonic-gate 			break;
12597c478bd9Sstevel@tonic-gate 		case ETHERTYPE_ARP:
12607c478bd9Sstevel@tonic-gate 		case ETHERTYPE_REVARP:
12617c478bd9Sstevel@tonic-gate 			interpret_arp(flags, (struct arphdr *)data, len);
12627c478bd9Sstevel@tonic-gate 			break;
12637c478bd9Sstevel@tonic-gate 		default:
12647c478bd9Sstevel@tonic-gate 			break;
12657c478bd9Sstevel@tonic-gate 		}
12667c478bd9Sstevel@tonic-gate 
12677c478bd9Sstevel@tonic-gate 	}
12687c478bd9Sstevel@tonic-gate 
12697c478bd9Sstevel@tonic-gate 	return (elen);
12707c478bd9Sstevel@tonic-gate }
12717c478bd9Sstevel@tonic-gate 
12727c478bd9Sstevel@tonic-gate uint_t
fddi_header_len(char * e,size_t msgsize)12732b24ab6bSSebastien Roy fddi_header_len(char *e, size_t msgsize)
12747c478bd9Sstevel@tonic-gate {
12757c478bd9Sstevel@tonic-gate 	struct fddi_header fhdr, *f = &fhdr;
12767c478bd9Sstevel@tonic-gate 
12772b24ab6bSSebastien Roy 	if (msgsize < sizeof (struct fddi_header))
12782b24ab6bSSebastien Roy 		return (0);
12792b24ab6bSSebastien Roy 
12807c478bd9Sstevel@tonic-gate 	(void) memcpy(&f->fc, e, sizeof (f->fc));
12817c478bd9Sstevel@tonic-gate 	(void) memcpy(&f->dhost, e+1, sizeof (struct ether_addr));
12827c478bd9Sstevel@tonic-gate 	(void) memcpy(&f->shost, e+7, sizeof (struct ether_addr));
12837c478bd9Sstevel@tonic-gate 
12847c478bd9Sstevel@tonic-gate 	if ((f->fc&0x50) == 0x50) {
12857c478bd9Sstevel@tonic-gate 		(void) memcpy(&f->dsap, e+13, sizeof (f->dsap));
12867c478bd9Sstevel@tonic-gate 		(void) memcpy(&f->ssap, e+14, sizeof (f->ssap));
12877c478bd9Sstevel@tonic-gate 		(void) memcpy(&f->ctl, e+15, sizeof (f->ctl));
12887c478bd9Sstevel@tonic-gate 		if (f->dsap == 0xaa && f->ssap == 0xaa) {
12897c478bd9Sstevel@tonic-gate 			return (21);
12907c478bd9Sstevel@tonic-gate 		}
12917c478bd9Sstevel@tonic-gate 		return (16);
12927c478bd9Sstevel@tonic-gate 	} else {
12937c478bd9Sstevel@tonic-gate 		if ((f->fc&0x41) == 0x41 || (f->fc&0x4f) == 0x4f) {
12947c478bd9Sstevel@tonic-gate 			return (13);
12957c478bd9Sstevel@tonic-gate 		}
12967c478bd9Sstevel@tonic-gate 	}
12972e3b6467Skcpoon 	/* Return the default FDDI header length. */
12982e3b6467Skcpoon 	return (13);
12997c478bd9Sstevel@tonic-gate }
13007c478bd9Sstevel@tonic-gate 
13017c478bd9Sstevel@tonic-gate /*
13027c478bd9Sstevel@tonic-gate  * Print the given Ethernet address
13037c478bd9Sstevel@tonic-gate  */
13047c478bd9Sstevel@tonic-gate char *
printether(struct ether_addr * p)13052b24ab6bSSebastien Roy printether(struct ether_addr *p)
13067c478bd9Sstevel@tonic-gate {
13077c478bd9Sstevel@tonic-gate 	static char buf[256];
13087c478bd9Sstevel@tonic-gate 
13097c478bd9Sstevel@tonic-gate 	sprintf(buf, "%x:%x:%x:%x:%x:%x",
13107c478bd9Sstevel@tonic-gate 	    p->ether_addr_octet[0],
13117c478bd9Sstevel@tonic-gate 	    p->ether_addr_octet[1],
13127c478bd9Sstevel@tonic-gate 	    p->ether_addr_octet[2],
13137c478bd9Sstevel@tonic-gate 	    p->ether_addr_octet[3],
13147c478bd9Sstevel@tonic-gate 	    p->ether_addr_octet[4],
13157c478bd9Sstevel@tonic-gate 	    p->ether_addr_octet[5]);
13167c478bd9Sstevel@tonic-gate 
13177c478bd9Sstevel@tonic-gate 	return (buf);
13187c478bd9Sstevel@tonic-gate }
13197c478bd9Sstevel@tonic-gate 
13207c478bd9Sstevel@tonic-gate /*
13217c478bd9Sstevel@tonic-gate  * Table of Ethernet Address Assignments
13227c478bd9Sstevel@tonic-gate  * Some of the more popular entries
13237c478bd9Sstevel@tonic-gate  * are at the beginning of the table
13247c478bd9Sstevel@tonic-gate  * to reduce search time.  Note that the
13257c478bd9Sstevel@tonic-gate  * e-block's are stored in host byte-order.
13267c478bd9Sstevel@tonic-gate  */
13277c478bd9Sstevel@tonic-gate struct block_type {
13287c478bd9Sstevel@tonic-gate 	int	e_block;
13297c478bd9Sstevel@tonic-gate 	char	*e_name;
13307c478bd9Sstevel@tonic-gate } ether_block [] = {
13317c478bd9Sstevel@tonic-gate 0x080020,	"Sun",
13327c478bd9Sstevel@tonic-gate 0x0000C6,	"HP",
13337c478bd9Sstevel@tonic-gate 0x08002B,	"DEC",
13347c478bd9Sstevel@tonic-gate 0x00000F,	"NeXT",
13357c478bd9Sstevel@tonic-gate 0x00000C,	"Cisco",
13367c478bd9Sstevel@tonic-gate 0x080069,	"Silicon Graphics",
13377c478bd9Sstevel@tonic-gate 0x000069,	"Silicon Graphics",
13387c478bd9Sstevel@tonic-gate 0x0000A7,	"Network Computing Devices (NCD	X-terminal)",
13397c478bd9Sstevel@tonic-gate 0x08005A,	"IBM",
13407c478bd9Sstevel@tonic-gate 0x0000AC,	"Apollo",
13414eaa4710SRishi Srivatsavai 0x0180C2,	"Standard MAC Group Address",
13427c478bd9Sstevel@tonic-gate /* end of popular entries */
13437c478bd9Sstevel@tonic-gate 0x000002,	"BBN",
13447c478bd9Sstevel@tonic-gate 0x000010,	"Sytek",
13457c478bd9Sstevel@tonic-gate 0x000011,	"Tektronix",
13467c478bd9Sstevel@tonic-gate 0x000018,	"Webster (?)",
13477c478bd9Sstevel@tonic-gate 0x00001B,	"Novell",
13487c478bd9Sstevel@tonic-gate 0x00001D,	"Cabletron",
13497c478bd9Sstevel@tonic-gate 0x000020,	"DIAB (Data Industrier AB)",
13507c478bd9Sstevel@tonic-gate 0x000021,	"SC&C",
13517c478bd9Sstevel@tonic-gate 0x000022,	"Visual Technology",
13527c478bd9Sstevel@tonic-gate 0x000029,	"IMC",
13537c478bd9Sstevel@tonic-gate 0x00002A,	"TRW",
13547c478bd9Sstevel@tonic-gate 0x00003D,	"AT&T",
13557c478bd9Sstevel@tonic-gate 0x000049,	"Apricot Ltd.",
13567c478bd9Sstevel@tonic-gate 0x000055,	"AT&T",
13577c478bd9Sstevel@tonic-gate 0x00005A,	"S & Koch",
13587c478bd9Sstevel@tonic-gate 0x00005A,	"Xerox 806 (unregistered)",
13597c478bd9Sstevel@tonic-gate 0x00005E,	"U.S. Department of Defense (IANA)",
13607c478bd9Sstevel@tonic-gate 0x000065,	"Network General",
13617c478bd9Sstevel@tonic-gate 0x00006B,	"MIPS",
13627c478bd9Sstevel@tonic-gate 0x000077,	"MIPS",
13637c478bd9Sstevel@tonic-gate 0x000079,	"NetWare (?)",
13647c478bd9Sstevel@tonic-gate 0x00007A,	"Ardent",
13657c478bd9Sstevel@tonic-gate 0x00007B,	"Research Machines",
13667c478bd9Sstevel@tonic-gate 0x00007D,	"Harris (3M) (old)",
13677c478bd9Sstevel@tonic-gate 0x000080,	"Imagen(?)",
13687c478bd9Sstevel@tonic-gate 0x000081,	"Synoptics",
13697c478bd9Sstevel@tonic-gate 0x000084,	"Aquila (?)",
13707c478bd9Sstevel@tonic-gate 0x000086,	"Gateway (?)",
13717c478bd9Sstevel@tonic-gate 0x000089,	"Cayman Systems	Gatorbox",
13727c478bd9Sstevel@tonic-gate 0x000093,	"Proteon",
13737c478bd9Sstevel@tonic-gate 0x000094,	"Asante",
13747c478bd9Sstevel@tonic-gate 0x000098,	"Cross Com",
13757c478bd9Sstevel@tonic-gate 0x00009F,	"Ameristar Technology",
13767c478bd9Sstevel@tonic-gate 0x0000A2,	"Wellfleet",
13777c478bd9Sstevel@tonic-gate 0x0000A3,	"Network Application Technology",
13787c478bd9Sstevel@tonic-gate 0x0000A4,	"Acorn",
13797c478bd9Sstevel@tonic-gate 0x0000A6,	"Network General",
13807c478bd9Sstevel@tonic-gate 0x0000A7,	"Network Computing Devices (NCD	X-terminal)",
13817c478bd9Sstevel@tonic-gate 0x0000A9,	"Network Systems",
13827c478bd9Sstevel@tonic-gate 0x0000AA,	"Xerox",
13837c478bd9Sstevel@tonic-gate 0x0000B3,	"CIMLinc",
13847c478bd9Sstevel@tonic-gate 0x0000B5,	"Datability Terminal Server",
13857c478bd9Sstevel@tonic-gate 0x0000B7,	"Dove Fastnet",
13867c478bd9Sstevel@tonic-gate 0x0000BC,	"Allen-Bradley",
13877c478bd9Sstevel@tonic-gate 0x0000C0,	"Western Digital",
13887c478bd9Sstevel@tonic-gate 0x0000C8,	"Altos",
13897c478bd9Sstevel@tonic-gate 0x0000C9,	"Emulex Terminal Server",
13907c478bd9Sstevel@tonic-gate 0x0000D0,	"Develcon Electronics, Ltd.",
13917c478bd9Sstevel@tonic-gate 0x0000D1,	"Adaptec Inc. Nodem product",
13927c478bd9Sstevel@tonic-gate 0x0000D7,	"Dartmouth College (NED Router)",
13937c478bd9Sstevel@tonic-gate 0x0000DD,	"Gould",
13947c478bd9Sstevel@tonic-gate 0x0000DE,	"Unigraph",
13957c478bd9Sstevel@tonic-gate 0x0000E2,	"Acer Counterpoint",
13967c478bd9Sstevel@tonic-gate 0x0000E8,	"Accton Technology Corporation",
13977c478bd9Sstevel@tonic-gate 0x0000EE,	"Network Designers Limited(?)",
13987c478bd9Sstevel@tonic-gate 0x0000EF,	"Alantec",
13997c478bd9Sstevel@tonic-gate 0x0000F3,	"Gandalf",
14007c478bd9Sstevel@tonic-gate 0x0000FD,	"High Level Hardware (Orion, UK)",
14017c478bd9Sstevel@tonic-gate 0x000143,	"IEEE 802",
14027c478bd9Sstevel@tonic-gate 0x001700,	"Kabel",
14037c478bd9Sstevel@tonic-gate 0x004010,	"Sonic",
14047c478bd9Sstevel@tonic-gate 0x00608C,	"3Com",
14057c478bd9Sstevel@tonic-gate 0x00800F,	"SMC",
14067c478bd9Sstevel@tonic-gate 0x008019,	"Dayna Communications Etherprint product",
14077c478bd9Sstevel@tonic-gate 0x00802D,	"Xylogics, Inc.	Annex terminal servers",
14087c478bd9Sstevel@tonic-gate 0x008035,	"Technology Works",
14097c478bd9Sstevel@tonic-gate 0x008087,	"Okidata",
14107c478bd9Sstevel@tonic-gate 0x00808C,	"Frontier Software Development",
14117c478bd9Sstevel@tonic-gate 0x0080C7,	"Xircom Inc.",
14127c478bd9Sstevel@tonic-gate 0x0080D0,	"Computer Products International",
14137c478bd9Sstevel@tonic-gate 0x0080D3,	"Shiva Appletalk-Ethernet interface",
14147c478bd9Sstevel@tonic-gate 0x0080D4,	"Chase Limited",
14157c478bd9Sstevel@tonic-gate 0x0080F1,	"Opus",
14167c478bd9Sstevel@tonic-gate 0x00AA00,	"Intel",
14177c478bd9Sstevel@tonic-gate 0x00B0D0,	"Computer Products International",
14187c478bd9Sstevel@tonic-gate 0x00DD00,	"Ungermann-Bass",
14197c478bd9Sstevel@tonic-gate 0x00DD01,	"Ungermann-Bass",
14207c478bd9Sstevel@tonic-gate 0x00EFE5,	"IBM (3Com card)",
14217c478bd9Sstevel@tonic-gate 0x020406,	"BBN",
14227c478bd9Sstevel@tonic-gate 0x026060,	"3Com",
14237c478bd9Sstevel@tonic-gate 0x026086,	"Satelcom MegaPac (UK)",
14247c478bd9Sstevel@tonic-gate 0x02E6D3,	"Bus-Tech, Inc. (BTI)",
14257c478bd9Sstevel@tonic-gate 0x080001,	"Computer Vision",
14267c478bd9Sstevel@tonic-gate 0x080002,	"3Com (Formerly Bridge)",
14277c478bd9Sstevel@tonic-gate 0x080003,	"ACC (Advanced Computer Communications)",
14287c478bd9Sstevel@tonic-gate 0x080005,	"Symbolics",
14297c478bd9Sstevel@tonic-gate 0x080007,	"Apple",
14307c478bd9Sstevel@tonic-gate 0x080008,	"BBN",
14317c478bd9Sstevel@tonic-gate 0x080009,	"Hewlett-Packard",
14327c478bd9Sstevel@tonic-gate 0x08000A,	"Nestar Systems",
14337c478bd9Sstevel@tonic-gate 0x08000B,	"Unisys",
14347c478bd9Sstevel@tonic-gate 0x08000D,	"ICL",
14357c478bd9Sstevel@tonic-gate 0x08000E,	"NCR",
14367c478bd9Sstevel@tonic-gate 0x080010,	"AT&T",
14377c478bd9Sstevel@tonic-gate 0x080011,	"Tektronix, Inc.",
14387c478bd9Sstevel@tonic-gate 0x080017,	"NSC",
14397c478bd9Sstevel@tonic-gate 0x08001A,	"Data General",
14407c478bd9Sstevel@tonic-gate 0x08001B,	"Data General",
14417c478bd9Sstevel@tonic-gate 0x08001E,	"Apollo",
14427c478bd9Sstevel@tonic-gate 0x080022,	"NBI",
14437c478bd9Sstevel@tonic-gate 0x080025,	"CDC",
14447c478bd9Sstevel@tonic-gate 0x080026,	"Norsk Data (Nord)",
14457c478bd9Sstevel@tonic-gate 0x080027,	"PCS Computer Systems GmbH",
14467c478bd9Sstevel@tonic-gate 0x080028,	"TI Explorer",
14477c478bd9Sstevel@tonic-gate 0x08002E,	"Metaphor",
14487c478bd9Sstevel@tonic-gate 0x08002F,	"Prime Computer",
14497c478bd9Sstevel@tonic-gate 0x080036,	"Intergraph CAE stations",
14507c478bd9Sstevel@tonic-gate 0x080037,	"Fujitsu-Xerox",
14517c478bd9Sstevel@tonic-gate 0x080038,	"Bull",
14527c478bd9Sstevel@tonic-gate 0x080039,	"Spider Systems",
14537c478bd9Sstevel@tonic-gate 0x08003B,	"Torus Systems",
14547c478bd9Sstevel@tonic-gate 0x08003E,	"Motorola VME bus processor module",
14557c478bd9Sstevel@tonic-gate 0x080041,	"DCA Digital Comm. Assoc.",
14567c478bd9Sstevel@tonic-gate 0x080046,	"Sony",
14577c478bd9Sstevel@tonic-gate 0x080047,	"Sequent",
14587c478bd9Sstevel@tonic-gate 0x080049,	"Univation",
14597c478bd9Sstevel@tonic-gate 0x08004C,	"Encore",
14607c478bd9Sstevel@tonic-gate 0x08004E,	"BICC",
14617c478bd9Sstevel@tonic-gate 0x080056,	"Stanford University",
14627c478bd9Sstevel@tonic-gate 0x080057,	"Evans & Sutherland (?)",
14637c478bd9Sstevel@tonic-gate 0x080067,	"Comdesign",
14647c478bd9Sstevel@tonic-gate 0x080068,	"Ridge",
14657c478bd9Sstevel@tonic-gate 0x08006A,	"ATTst (?)",
14667c478bd9Sstevel@tonic-gate 0x08006E,	"Excelan",
14677c478bd9Sstevel@tonic-gate 0x080075,	"DDE (Danish Data Elektronik A/S)",
14687c478bd9Sstevel@tonic-gate 0x080077,	"TSL (now Retix)",
14697c478bd9Sstevel@tonic-gate 0x08007C,	"Vitalink TransLAN III",
14707c478bd9Sstevel@tonic-gate 0x080080,	"XIOS",
14717c478bd9Sstevel@tonic-gate 0x080081,	"Crosfield Electronics",
14727c478bd9Sstevel@tonic-gate 0x080086,	"Imagen/QMS",
14737c478bd9Sstevel@tonic-gate 0x080087,	"Xyplex	terminal server",
14747c478bd9Sstevel@tonic-gate 0x080089,	"Kinetics AppleTalk-Ethernet interface",
14757c478bd9Sstevel@tonic-gate 0x08008B,	"Pyramid",
14767c478bd9Sstevel@tonic-gate 0x08008D,	"XyVision",
14777c478bd9Sstevel@tonic-gate 0x080090,	"Retix Inc Bridge",
14787c478bd9Sstevel@tonic-gate 0x10005A,	"IBM",
14797c478bd9Sstevel@tonic-gate 0x1000D4,	"DEC",
14807c478bd9Sstevel@tonic-gate 0x400003,	"NetWare",
14817c478bd9Sstevel@tonic-gate 0x800010,	"AT&T",
14827c478bd9Sstevel@tonic-gate 0xAA0004,	"DEC (DECNET)",
14837c478bd9Sstevel@tonic-gate 0xC00000,	"SMC",
14847c478bd9Sstevel@tonic-gate 0,		"",
14857c478bd9Sstevel@tonic-gate };
14867c478bd9Sstevel@tonic-gate 
14877c478bd9Sstevel@tonic-gate /*
14887c478bd9Sstevel@tonic-gate  * The oui argument should be in host byte-order to conform with
14897c478bd9Sstevel@tonic-gate  * the above array's values.
14907c478bd9Sstevel@tonic-gate  */
14917c478bd9Sstevel@tonic-gate char *
ether_ouiname(uint32_t oui)14927c478bd9Sstevel@tonic-gate ether_ouiname(uint32_t oui)
14937c478bd9Sstevel@tonic-gate {
14947c478bd9Sstevel@tonic-gate 	uint_t i;
14957c478bd9Sstevel@tonic-gate 
14967c478bd9Sstevel@tonic-gate 	for (i = 0; ether_block[i].e_block != 0; i++)
14977c478bd9Sstevel@tonic-gate 		if (oui == ether_block[i].e_block)
14987c478bd9Sstevel@tonic-gate 			return (ether_block[i].e_name);
14997c478bd9Sstevel@tonic-gate 
15007c478bd9Sstevel@tonic-gate 	return (NULL);
15017c478bd9Sstevel@tonic-gate }
15027c478bd9Sstevel@tonic-gate 
15037c478bd9Sstevel@tonic-gate /*
15047c478bd9Sstevel@tonic-gate  * Print the additional Ethernet address info
15057c478bd9Sstevel@tonic-gate  */
15067c478bd9Sstevel@tonic-gate static char *
print_etherinfo(struct ether_addr * eaddr)15072b24ab6bSSebastien Roy print_etherinfo(struct ether_addr *eaddr)
15087c478bd9Sstevel@tonic-gate {
15097c478bd9Sstevel@tonic-gate 	uint_t addr = 0;
15107c478bd9Sstevel@tonic-gate 	char *p = (char *)&addr + 1;
15117c478bd9Sstevel@tonic-gate 	char *ename;
15127c478bd9Sstevel@tonic-gate 
15137c478bd9Sstevel@tonic-gate 	(void) memcpy(p, eaddr, 3);
15147c478bd9Sstevel@tonic-gate 
15157c478bd9Sstevel@tonic-gate 	if (memcmp(eaddr, &ether_broadcast, sizeof (struct ether_addr)) == 0)
15167c478bd9Sstevel@tonic-gate 		return ("(broadcast)");
15177c478bd9Sstevel@tonic-gate 
15187c478bd9Sstevel@tonic-gate 	addr = ntohl(addr);	/* make it right for little-endians */
15197c478bd9Sstevel@tonic-gate 	ename = ether_ouiname(addr);
15207c478bd9Sstevel@tonic-gate 
15217c478bd9Sstevel@tonic-gate 	if (ename != NULL)
15227c478bd9Sstevel@tonic-gate 		return (ename);
15237c478bd9Sstevel@tonic-gate 	else
15244eaa4710SRishi Srivatsavai 		return ((eaddr->ether_addr_octet[0] & 1) ? "(multicast)" : "");
15257c478bd9Sstevel@tonic-gate }
15267c478bd9Sstevel@tonic-gate 
15277c478bd9Sstevel@tonic-gate static uchar_t	endianswap[] = {
15287c478bd9Sstevel@tonic-gate 	0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
15297c478bd9Sstevel@tonic-gate 	0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
15307c478bd9Sstevel@tonic-gate 	0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
15317c478bd9Sstevel@tonic-gate 	0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
15327c478bd9Sstevel@tonic-gate 	0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
15337c478bd9Sstevel@tonic-gate 	0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
15347c478bd9Sstevel@tonic-gate 	0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
15357c478bd9Sstevel@tonic-gate 	0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
15367c478bd9Sstevel@tonic-gate 	0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
15377c478bd9Sstevel@tonic-gate 	0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
15387c478bd9Sstevel@tonic-gate 	0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
15397c478bd9Sstevel@tonic-gate 	0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
15407c478bd9Sstevel@tonic-gate 	0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
15417c478bd9Sstevel@tonic-gate 	0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
15427c478bd9Sstevel@tonic-gate 	0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
15437c478bd9Sstevel@tonic-gate 	0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
15447c478bd9Sstevel@tonic-gate 	0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
15457c478bd9Sstevel@tonic-gate 	0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
15467c478bd9Sstevel@tonic-gate 	0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
15477c478bd9Sstevel@tonic-gate 	0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
15487c478bd9Sstevel@tonic-gate 	0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
15497c478bd9Sstevel@tonic-gate 	0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
15507c478bd9Sstevel@tonic-gate 	0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
15517c478bd9Sstevel@tonic-gate 	0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
15527c478bd9Sstevel@tonic-gate 	0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
15537c478bd9Sstevel@tonic-gate 	0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
15547c478bd9Sstevel@tonic-gate 	0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
15557c478bd9Sstevel@tonic-gate 	0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
15567c478bd9Sstevel@tonic-gate 	0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
15577c478bd9Sstevel@tonic-gate 	0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
15587c478bd9Sstevel@tonic-gate 	0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
15597c478bd9Sstevel@tonic-gate 	0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
15607c478bd9Sstevel@tonic-gate };
15617c478bd9Sstevel@tonic-gate 
15627c478bd9Sstevel@tonic-gate static void
addr_copy_swap(struct ether_addr * pd,struct ether_addr * ps)15632b24ab6bSSebastien Roy addr_copy_swap(struct ether_addr *pd, struct ether_addr *ps)
15647c478bd9Sstevel@tonic-gate {
15657c478bd9Sstevel@tonic-gate 	pd->ether_addr_octet[0] = endianswap[ps->ether_addr_octet[0]];
15667c478bd9Sstevel@tonic-gate 	pd->ether_addr_octet[1] = endianswap[ps->ether_addr_octet[1]];
15677c478bd9Sstevel@tonic-gate 	pd->ether_addr_octet[2] = endianswap[ps->ether_addr_octet[2]];
15687c478bd9Sstevel@tonic-gate 	pd->ether_addr_octet[3] = endianswap[ps->ether_addr_octet[3]];
15697c478bd9Sstevel@tonic-gate 	pd->ether_addr_octet[4] = endianswap[ps->ether_addr_octet[4]];
15707c478bd9Sstevel@tonic-gate 	pd->ether_addr_octet[5] = endianswap[ps->ether_addr_octet[5]];
15717c478bd9Sstevel@tonic-gate }
15727c478bd9Sstevel@tonic-gate 
15737c478bd9Sstevel@tonic-gate /* ARGSUSED */
15747c478bd9Sstevel@tonic-gate uint_t
ib_header_len(char * hdr,size_t msgsize)15752b24ab6bSSebastien Roy ib_header_len(char *hdr, size_t msgsize)
15767c478bd9Sstevel@tonic-gate {
15777c478bd9Sstevel@tonic-gate 	return (IPOIB_HDRSIZE);
15787c478bd9Sstevel@tonic-gate }
15797c478bd9Sstevel@tonic-gate 
15807c478bd9Sstevel@tonic-gate static uint_t
interpret_ib(int flags,char * header,int elen,int origlen)15817c478bd9Sstevel@tonic-gate interpret_ib(int flags, char *header, int elen, int origlen)
15827c478bd9Sstevel@tonic-gate {
15837c478bd9Sstevel@tonic-gate 	struct ipoib_header *hdr = (struct ipoib_header *)header;
15847c478bd9Sstevel@tonic-gate 	char *off;
15857c478bd9Sstevel@tonic-gate 	int len;
15867c478bd9Sstevel@tonic-gate 	unsigned short ethertype;
15877c478bd9Sstevel@tonic-gate 	int blen = MAX(origlen, 4096);
15887c478bd9Sstevel@tonic-gate 
15897c478bd9Sstevel@tonic-gate 	if (data != NULL && datalen != 0 && datalen < blen) {
15907c478bd9Sstevel@tonic-gate 		free(data);
15917c478bd9Sstevel@tonic-gate 		data = NULL;
15927c478bd9Sstevel@tonic-gate 		datalen = 0;
15937c478bd9Sstevel@tonic-gate 	}
15947c478bd9Sstevel@tonic-gate 	if (data == NULL) {
15957c478bd9Sstevel@tonic-gate 		data = malloc(blen);
15967c478bd9Sstevel@tonic-gate 		if (data == NULL)
15977c478bd9Sstevel@tonic-gate 			pr_err("Warning: malloc failure");
15987c478bd9Sstevel@tonic-gate 		datalen = blen;
15997c478bd9Sstevel@tonic-gate 	}
16007c478bd9Sstevel@tonic-gate 	if (origlen < IPOIB_HDRSIZE) {
16017c478bd9Sstevel@tonic-gate 		if (flags & F_SUM)
16027c478bd9Sstevel@tonic-gate 			(void) snprintf(get_sum_line(), MAXLINE,
16037c478bd9Sstevel@tonic-gate 			    "RUNT (short packet - %d bytes)", origlen);
16047c478bd9Sstevel@tonic-gate 		if (flags & F_DTAIL)
16057c478bd9Sstevel@tonic-gate 			show_header("RUNT:  ", "Short packet", origlen);
16067c478bd9Sstevel@tonic-gate 		return (elen);
16077c478bd9Sstevel@tonic-gate 	}
16087c478bd9Sstevel@tonic-gate 	if (elen < IPOIB_HDRSIZE)
16097c478bd9Sstevel@tonic-gate 		return (elen);
16107c478bd9Sstevel@tonic-gate 
16117c478bd9Sstevel@tonic-gate 	/*
16127c478bd9Sstevel@tonic-gate 	 * It is not possible to understand just by looking
16137c478bd9Sstevel@tonic-gate 	 * at the header whether this was a broad/multi cast
16147c478bd9Sstevel@tonic-gate 	 * packet; thus dst_name is not updated.
16157c478bd9Sstevel@tonic-gate 	 */
16167c478bd9Sstevel@tonic-gate 	ethertype = ntohs(hdr->ipoib_type);
16177c478bd9Sstevel@tonic-gate 	len = elen - IPOIB_HDRSIZE;
16187c478bd9Sstevel@tonic-gate 	off = (char *)(hdr + 1);
16197c478bd9Sstevel@tonic-gate 	(void) memcpy(data, off, len);
16207c478bd9Sstevel@tonic-gate 
16217c478bd9Sstevel@tonic-gate 	if (flags & F_SUM) {
16227c478bd9Sstevel@tonic-gate 		(void) snprintf(get_sum_line(), MAXLINE,
16237c478bd9Sstevel@tonic-gate 		    "IPIB Type=%04X (%s), size = %d bytes",
16247c478bd9Sstevel@tonic-gate 		    ethertype,
16257c478bd9Sstevel@tonic-gate 		    print_ethertype(ethertype),
16267c478bd9Sstevel@tonic-gate 		    origlen);
16277c478bd9Sstevel@tonic-gate 	}
16287c478bd9Sstevel@tonic-gate 
16297c478bd9Sstevel@tonic-gate 	if (flags & F_DTAIL) {
16307c478bd9Sstevel@tonic-gate 		show_header("IPIB:  ", "IPIB Header", elen);
16317c478bd9Sstevel@tonic-gate 		show_space();
16327c478bd9Sstevel@tonic-gate 		(void) snprintf(get_line(0, 0), get_line_remain(),
16337c478bd9Sstevel@tonic-gate 		    "Packet %d arrived at %d:%02d:%d.%02d",
16347c478bd9Sstevel@tonic-gate 		    pi_frame, pi_time_hour, pi_time_min,
16357c478bd9Sstevel@tonic-gate 		    pi_time_sec, pi_time_usec / 10000);
16367c478bd9Sstevel@tonic-gate 		(void) snprintf(get_line(0, 0), get_line_remain(),
16377c478bd9Sstevel@tonic-gate 		    "Packet size = %d bytes", elen, elen);
16387c478bd9Sstevel@tonic-gate 		(void) snprintf(get_line(0, 2), get_line_remain(),
16397c478bd9Sstevel@tonic-gate 		    "Ethertype = %04X (%s)", ethertype,
16407c478bd9Sstevel@tonic-gate 		    print_ethertype(ethertype));
16417c478bd9Sstevel@tonic-gate 		show_space();
16427c478bd9Sstevel@tonic-gate 	}
16437c478bd9Sstevel@tonic-gate 
16447c478bd9Sstevel@tonic-gate 	/* Go to the next protocol layer */
16457c478bd9Sstevel@tonic-gate 	switch (ethertype) {
16467c478bd9Sstevel@tonic-gate 		case ETHERTYPE_IP:
16477c478bd9Sstevel@tonic-gate 			(void) interpret_ip(flags, (struct ip *)data, len);
16487c478bd9Sstevel@tonic-gate 			break;
16497c478bd9Sstevel@tonic-gate 		case ETHERTYPE_IPV6:
16507c478bd9Sstevel@tonic-gate 			(void) interpret_ipv6(flags, (ip6_t *)data, len);
16517c478bd9Sstevel@tonic-gate 			break;
16527c478bd9Sstevel@tonic-gate 		case ETHERTYPE_ARP:
16537c478bd9Sstevel@tonic-gate 		case ETHERTYPE_REVARP:
16547c478bd9Sstevel@tonic-gate 			interpret_arp(flags, (struct arphdr *)data, len);
16557c478bd9Sstevel@tonic-gate 			break;
16567c478bd9Sstevel@tonic-gate 	}
16577c478bd9Sstevel@tonic-gate 
16587c478bd9Sstevel@tonic-gate 	return (elen);
16597c478bd9Sstevel@tonic-gate }
1660b127ac41SPhilip Kirk 
16612b24ab6bSSebastien Roy /* ARGSUSED */
1662b127ac41SPhilip Kirk uint_t
ipnet_header_len(char * hdr,size_t msgsize)16632b24ab6bSSebastien Roy ipnet_header_len(char *hdr, size_t msgsize)
1664b127ac41SPhilip Kirk {
1665b127ac41SPhilip Kirk 	return (sizeof (dl_ipnetinfo_t));
1666b127ac41SPhilip Kirk }
1667b127ac41SPhilip Kirk 
1668b127ac41SPhilip Kirk #define	MAX_UINT64_STR	22
1669b127ac41SPhilip Kirk static uint_t
interpret_ipnet(int flags,char * header,int elen,int origlen)1670b127ac41SPhilip Kirk interpret_ipnet(int flags, char *header, int elen, int origlen)
1671b127ac41SPhilip Kirk {
1672b127ac41SPhilip Kirk 	dl_ipnetinfo_t dl;
1673b127ac41SPhilip Kirk 	size_t len = elen - sizeof (dl_ipnetinfo_t);
1674b127ac41SPhilip Kirk 	char *off = (char *)header + sizeof (dl_ipnetinfo_t);
1675b127ac41SPhilip Kirk 	int blen = MAX(origlen, 8252);
1676b127ac41SPhilip Kirk 	char szone[MAX_UINT64_STR];
1677b127ac41SPhilip Kirk 	char dzone[MAX_UINT64_STR];
1678b127ac41SPhilip Kirk 
1679b127ac41SPhilip Kirk 	(void) memcpy(&dl, header, sizeof (dl));
1680b127ac41SPhilip Kirk 	if (data != NULL && datalen != 0 && datalen < blen) {
1681b127ac41SPhilip Kirk 		free(data);
1682b127ac41SPhilip Kirk 		data = NULL;
1683b127ac41SPhilip Kirk 		datalen = 0;
1684b127ac41SPhilip Kirk 	}
1685b127ac41SPhilip Kirk 	if (data == NULL) {
1686b127ac41SPhilip Kirk 		data = (char *)malloc(blen);
1687b127ac41SPhilip Kirk 		if (!data)
1688b127ac41SPhilip Kirk 			pr_err("Warning: malloc failure");
1689b127ac41SPhilip Kirk 		datalen = blen;
1690b127ac41SPhilip Kirk 	}
1691b127ac41SPhilip Kirk 
1692*0a0e9771SDarren Reed 	if (dl.dli_zsrc == ALL_ZONES)
1693b127ac41SPhilip Kirk 		sprintf(szone, "Unknown");
1694b127ac41SPhilip Kirk 	else
1695*0a0e9771SDarren Reed 		sprintf(szone, "%lu", BE_32(dl.dli_zsrc));
1696b127ac41SPhilip Kirk 
1697*0a0e9771SDarren Reed 	if (dl.dli_zdst == ALL_ZONES)
1698b127ac41SPhilip Kirk 		sprintf(dzone, "Unknown");
1699b127ac41SPhilip Kirk 	else
1700*0a0e9771SDarren Reed 		sprintf(dzone, "%lu", BE_32(dl.dli_zdst));
1701b127ac41SPhilip Kirk 
1702b127ac41SPhilip Kirk 	if (flags & F_SUM) {
1703b127ac41SPhilip Kirk 		(void) snprintf(get_sum_line(), MAXLINE,
1704b127ac41SPhilip Kirk 		    "IPNET src zone %s dst zone %s", szone, dzone);
1705b127ac41SPhilip Kirk 	}
1706b127ac41SPhilip Kirk 
1707b127ac41SPhilip Kirk 	if (flags & F_DTAIL) {
1708b127ac41SPhilip Kirk 		show_header("IPNET:  ", "IPNET Header", elen);
1709b127ac41SPhilip Kirk 		show_space();
1710b127ac41SPhilip Kirk 		(void) sprintf(get_line(0, 0),
1711b127ac41SPhilip Kirk 		    "Packet %d arrived at %d:%02d:%d.%05d",
1712b127ac41SPhilip Kirk 		    pi_frame,
1713b127ac41SPhilip Kirk 		    pi_time_hour, pi_time_min, pi_time_sec,
1714b127ac41SPhilip Kirk 		    pi_time_usec / 10);
1715b127ac41SPhilip Kirk 		(void) sprintf(get_line(0, 0),
1716b127ac41SPhilip Kirk 		    "Packet size = %d bytes",
1717b127ac41SPhilip Kirk 		    elen);
1718b127ac41SPhilip Kirk 		(void) snprintf(get_line(0, 0), get_line_remain(),
1719b127ac41SPhilip Kirk 		    "dli_version = %d", dl.dli_version);
1720b127ac41SPhilip Kirk 		(void) snprintf(get_line(0, 0), get_line_remain(),
1721*0a0e9771SDarren Reed 		    "dli_family = %d", dl.dli_family);
1722b127ac41SPhilip Kirk 		(void) snprintf(get_line(0, 2), get_line_remain(),
1723*0a0e9771SDarren Reed 		    "dli_zsrc = %s", szone);
1724b127ac41SPhilip Kirk 		(void) snprintf(get_line(0, 2), get_line_remain(),
1725*0a0e9771SDarren Reed 		    "dli_zdst = %s", dzone);
1726b127ac41SPhilip Kirk 		show_space();
1727b127ac41SPhilip Kirk 	}
1728b127ac41SPhilip Kirk 	memcpy(data, off, len);
1729b127ac41SPhilip Kirk 
1730*0a0e9771SDarren Reed 	switch (dl.dli_family) {
1731*0a0e9771SDarren Reed 	case AF_INET:
1732b127ac41SPhilip Kirk 		(void) interpret_ip(flags, (struct ip *)data, len);
1733b127ac41SPhilip Kirk 		break;
1734*0a0e9771SDarren Reed 	case AF_INET6:
1735b127ac41SPhilip Kirk 		(void) interpret_ipv6(flags, (ip6_t *)data, len);
1736b127ac41SPhilip Kirk 		break;
1737b127ac41SPhilip Kirk 	default:
1738b127ac41SPhilip Kirk 		break;
1739b127ac41SPhilip Kirk 	}
1740b127ac41SPhilip Kirk 
1741b127ac41SPhilip Kirk 	return (0);
1742b127ac41SPhilip Kirk }
17432b24ab6bSSebastien Roy 
17442b24ab6bSSebastien Roy uint_t
ipv4_header_len(char * hdr,size_t msgsize)17452b24ab6bSSebastien Roy ipv4_header_len(char *hdr, size_t msgsize)
17462b24ab6bSSebastien Roy {
17472b24ab6bSSebastien Roy 	return (msgsize < sizeof (ipha_t) ? 0 : IPH_HDR_LENGTH((ipha_t *)hdr));
17482b24ab6bSSebastien Roy }
17492b24ab6bSSebastien Roy 
17502b24ab6bSSebastien Roy /*
17512b24ab6bSSebastien Roy  * The header length needs to include all potential extension headers, as the
17522b24ab6bSSebastien Roy  * caller expects to use this length as an offset to the inner network layer
17532b24ab6bSSebastien Roy  * header to be used as a filter offset.  IPsec headers aren't passed up here,
17542b24ab6bSSebastien Roy  * and neither are fragmentation headers.
17552b24ab6bSSebastien Roy  */
17562b24ab6bSSebastien Roy uint_t
ipv6_header_len(char * hdr,size_t msgsize)17572b24ab6bSSebastien Roy ipv6_header_len(char *hdr, size_t msgsize)
17582b24ab6bSSebastien Roy {
17592b24ab6bSSebastien Roy 	ip6_t		*ip6hdr = (ip6_t *)hdr;
17602b24ab6bSSebastien Roy 	ip6_hbh_t	*exthdr;
17612b24ab6bSSebastien Roy 	uint_t		hdrlen = sizeof (ip6_t), exthdrlen;
17622b24ab6bSSebastien Roy 	char		*pptr;
17632b24ab6bSSebastien Roy 	uint8_t		nxt;
17642b24ab6bSSebastien Roy 
17652b24ab6bSSebastien Roy 	if (msgsize < sizeof (ip6_t))
17662b24ab6bSSebastien Roy 		return (0);
17672b24ab6bSSebastien Roy 
17682b24ab6bSSebastien Roy 	nxt = ip6hdr->ip6_nxt;
17692b24ab6bSSebastien Roy 	pptr = (char *)(ip6hdr + 1);
17702b24ab6bSSebastien Roy 
17712b24ab6bSSebastien Roy 	while (nxt != IPPROTO_ENCAP && nxt != IPPROTO_IPV6) {
17722b24ab6bSSebastien Roy 		switch (nxt) {
17732b24ab6bSSebastien Roy 		case IPPROTO_HOPOPTS:
17742b24ab6bSSebastien Roy 		case IPPROTO_DSTOPTS:
17752b24ab6bSSebastien Roy 		case IPPROTO_ROUTING:
17762b24ab6bSSebastien Roy 			if (msgsize < hdrlen + sizeof (ip6_hbh_t))
17772b24ab6bSSebastien Roy 				return (0);
17782b24ab6bSSebastien Roy 			exthdr = (ip6_hbh_t *)pptr;
17792b24ab6bSSebastien Roy 			exthdrlen = 8 + exthdr->ip6h_len * 8;
17802b24ab6bSSebastien Roy 			hdrlen += exthdrlen;
17812b24ab6bSSebastien Roy 			pptr += exthdrlen;
17822b24ab6bSSebastien Roy 			nxt = exthdr->ip6h_nxt;
17832b24ab6bSSebastien Roy 			break;
17842b24ab6bSSebastien Roy 		default:
17852b24ab6bSSebastien Roy 			/*
17862b24ab6bSSebastien Roy 			 * This is garbage, there's no way to know where the
17872b24ab6bSSebastien Roy 			 * inner IP header is.
17882b24ab6bSSebastien Roy 			 */
17892b24ab6bSSebastien Roy 			return (0);
17902b24ab6bSSebastien Roy 		}
17912b24ab6bSSebastien Roy 	}
17922b24ab6bSSebastien Roy 
17932b24ab6bSSebastien Roy 	return (hdrlen);
17942b24ab6bSSebastien Roy }
17952b24ab6bSSebastien Roy 
17962b24ab6bSSebastien Roy /* ARGSUSED */
17972b24ab6bSSebastien Roy uint_t
interpret_iptun(int flags,char * header,int elen,int origlen)17982b24ab6bSSebastien Roy interpret_iptun(int flags, char *header, int elen, int origlen)
17992b24ab6bSSebastien Roy {
18002b24ab6bSSebastien Roy 	(void) interpret_ip(flags, (struct ip *)header, elen);
18012b24ab6bSSebastien Roy 	return (elen);
18022b24ab6bSSebastien Roy }
1803