xref: /onnv-gate/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_ether.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"	/* SunOS */
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate #include <stdio.h>
30*0Sstevel@tonic-gate #include <stdlib.h>
31*0Sstevel@tonic-gate #include <ctype.h>
32*0Sstevel@tonic-gate #include <string.h>
33*0Sstevel@tonic-gate #include <fcntl.h>
34*0Sstevel@tonic-gate #include <string.h>
35*0Sstevel@tonic-gate #include <sys/types.h>
36*0Sstevel@tonic-gate #include <sys/time.h>
37*0Sstevel@tonic-gate #include <sys/dlpi.h>
38*0Sstevel@tonic-gate #include <sys/sysmacros.h>
39*0Sstevel@tonic-gate #include <sys/socket.h>
40*0Sstevel@tonic-gate #include <sys/sockio.h>
41*0Sstevel@tonic-gate #include <net/if.h>
42*0Sstevel@tonic-gate #include <netinet/in_systm.h>
43*0Sstevel@tonic-gate #include <netinet/in.h>
44*0Sstevel@tonic-gate #include <netinet/ip.h>
45*0Sstevel@tonic-gate #include <netinet/if_ether.h>
46*0Sstevel@tonic-gate #include <sys/ib/clients/ibd/ibd.h>
47*0Sstevel@tonic-gate 
48*0Sstevel@tonic-gate #include "at.h"
49*0Sstevel@tonic-gate #include "snoop.h"
50*0Sstevel@tonic-gate 
51*0Sstevel@tonic-gate static 	uint_t ether_header_len(char *), fddi_header_len(char *),
52*0Sstevel@tonic-gate 		tr_header_len(char *), ib_header_len(char *);
53*0Sstevel@tonic-gate static uint_t interpret_ether(), interpret_fddi(), interpret_tr();
54*0Sstevel@tonic-gate static uint_t interpret_ib(int, char *, int, int);
55*0Sstevel@tonic-gate static void addr_copy_swap(struct ether_addr *, struct ether_addr *);
56*0Sstevel@tonic-gate 
57*0Sstevel@tonic-gate interface_t *interface;
58*0Sstevel@tonic-gate interface_t INTERFACES[] = {
59*0Sstevel@tonic-gate 
60*0Sstevel@tonic-gate 	/* IEEE 802.3 CSMA/CD network */
61*0Sstevel@tonic-gate 	{ DL_CSMACD, 1550, ether_header_len, interpret_ether, IF_HDR_FIXED },
62*0Sstevel@tonic-gate 
63*0Sstevel@tonic-gate 	/* Ethernet Bus */
64*0Sstevel@tonic-gate 	{ DL_ETHER, 1550, ether_header_len, interpret_ether, IF_HDR_FIXED },
65*0Sstevel@tonic-gate 
66*0Sstevel@tonic-gate 	/* Fiber Distributed data interface */
67*0Sstevel@tonic-gate 	{ DL_FDDI, 4500, fddi_header_len, interpret_fddi, IF_HDR_VAR },
68*0Sstevel@tonic-gate 
69*0Sstevel@tonic-gate 	/* Token Ring interface */
70*0Sstevel@tonic-gate 	{ DL_TPR, 17800, tr_header_len, interpret_tr, IF_HDR_VAR },
71*0Sstevel@tonic-gate 
72*0Sstevel@tonic-gate 	/* Infiniband */
73*0Sstevel@tonic-gate 	{ DL_IB, 4096, ib_header_len, interpret_ib, IF_HDR_FIXED },
74*0Sstevel@tonic-gate 
75*0Sstevel@tonic-gate 	{ (uint_t)-1, 0, 0, 0, 0 }
76*0Sstevel@tonic-gate 
77*0Sstevel@tonic-gate };
78*0Sstevel@tonic-gate 
79*0Sstevel@tonic-gate 
80*0Sstevel@tonic-gate /* externals */
81*0Sstevel@tonic-gate extern char *dlc_header;
82*0Sstevel@tonic-gate extern int pi_frame;
83*0Sstevel@tonic-gate extern int pi_time_hour;
84*0Sstevel@tonic-gate extern int pi_time_min;
85*0Sstevel@tonic-gate extern int pi_time_sec;
86*0Sstevel@tonic-gate extern int pi_time_usec;
87*0Sstevel@tonic-gate 
88*0Sstevel@tonic-gate char *printether();
89*0Sstevel@tonic-gate char *print_ethertype();
90*0Sstevel@tonic-gate static char *print_etherinfo();
91*0Sstevel@tonic-gate 
92*0Sstevel@tonic-gate char *print_fc();
93*0Sstevel@tonic-gate char *print_smttype();
94*0Sstevel@tonic-gate char *print_smtclass();
95*0Sstevel@tonic-gate 
96*0Sstevel@tonic-gate struct ether_addr ether_broadcast = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
97*0Sstevel@tonic-gate static char *data;			/* current data buffer */
98*0Sstevel@tonic-gate static int datalen;			/* current data buffer length */
99*0Sstevel@tonic-gate 
100*0Sstevel@tonic-gate uint_t
101*0Sstevel@tonic-gate interpret_ether(flags, e, elen, origlen)
102*0Sstevel@tonic-gate 	int flags;
103*0Sstevel@tonic-gate 	struct ether_header *e;
104*0Sstevel@tonic-gate 	int elen, origlen;
105*0Sstevel@tonic-gate {
106*0Sstevel@tonic-gate 	char *off;
107*0Sstevel@tonic-gate 	int len;
108*0Sstevel@tonic-gate 	int ieee8023 = 0;
109*0Sstevel@tonic-gate 	extern char *dst_name;
110*0Sstevel@tonic-gate 	int ethertype;
111*0Sstevel@tonic-gate 	boolean_t data_copied = B_FALSE;
112*0Sstevel@tonic-gate 	int blen = MAX(origlen, ETHERMTU);
113*0Sstevel@tonic-gate 
114*0Sstevel@tonic-gate 	if (data != NULL && datalen != 0 && datalen < blen) {
115*0Sstevel@tonic-gate 		free(data);
116*0Sstevel@tonic-gate 		data = NULL;
117*0Sstevel@tonic-gate 		datalen = 0;
118*0Sstevel@tonic-gate 	}
119*0Sstevel@tonic-gate 	if (!data) {
120*0Sstevel@tonic-gate 		data = (char *)malloc(blen);
121*0Sstevel@tonic-gate 		if (!data)
122*0Sstevel@tonic-gate 			pr_err("Warning: malloc failure");
123*0Sstevel@tonic-gate 		datalen = blen;
124*0Sstevel@tonic-gate 	}
125*0Sstevel@tonic-gate 	if (origlen < 14) {
126*0Sstevel@tonic-gate 		if (flags & F_SUM)
127*0Sstevel@tonic-gate 			(void) sprintf(get_sum_line(),
128*0Sstevel@tonic-gate 			"RUNT (short packet - %d bytes)",
129*0Sstevel@tonic-gate 			origlen);
130*0Sstevel@tonic-gate 		if (flags & F_DTAIL)
131*0Sstevel@tonic-gate 			show_header("RUNT:  ", "Short packet", origlen);
132*0Sstevel@tonic-gate 		return (elen);
133*0Sstevel@tonic-gate 	}
134*0Sstevel@tonic-gate 	if (elen < 14)
135*0Sstevel@tonic-gate 		return (elen);
136*0Sstevel@tonic-gate 
137*0Sstevel@tonic-gate 	if (memcmp(&e->ether_dhost, &ether_broadcast,
138*0Sstevel@tonic-gate 	    sizeof (struct ether_addr)) == 0)
139*0Sstevel@tonic-gate 		dst_name = "(broadcast)";
140*0Sstevel@tonic-gate 	else if (e->ether_dhost.ether_addr_octet[0] & 1)
141*0Sstevel@tonic-gate 		dst_name = "(multicast)";
142*0Sstevel@tonic-gate 
143*0Sstevel@tonic-gate 	ethertype = ntohs(e->ether_type);
144*0Sstevel@tonic-gate 
145*0Sstevel@tonic-gate 	/*
146*0Sstevel@tonic-gate 	 * The 14 byte ether header screws up alignment
147*0Sstevel@tonic-gate 	 * of the rest of the packet for 32 bit aligned
148*0Sstevel@tonic-gate 	 * architectures like SPARC. Alas, we have to copy
149*0Sstevel@tonic-gate 	 * the rest of the packet in order to align it.
150*0Sstevel@tonic-gate 	 */
151*0Sstevel@tonic-gate 	len = elen - sizeof (struct ether_header);
152*0Sstevel@tonic-gate 	off = (char *)(e + 1);
153*0Sstevel@tonic-gate 	if (ethertype <= 1514) {
154*0Sstevel@tonic-gate 		/*
155*0Sstevel@tonic-gate 		 * Fake out the IEEE 802.3 packets.
156*0Sstevel@tonic-gate 		 * Should be DSAP=170, SSAP=170, control=3
157*0Sstevel@tonic-gate 		 * then three padding bytes of zero,
158*0Sstevel@tonic-gate 		 * followed by a normal ethernet-type packet.
159*0Sstevel@tonic-gate 		 */
160*0Sstevel@tonic-gate 		ieee8023 = ntohs(e->ether_type);
161*0Sstevel@tonic-gate 		ethertype = ntohs(*(ushort_t *)(off + 6));
162*0Sstevel@tonic-gate 		off += 8;
163*0Sstevel@tonic-gate 		len -= 8;
164*0Sstevel@tonic-gate 	}
165*0Sstevel@tonic-gate 
166*0Sstevel@tonic-gate 	/*
167*0Sstevel@tonic-gate 	 * We cannot trust the length field in the header to be correct.
168*0Sstevel@tonic-gate 	 * But we should continue to process the packet.  Then user can
169*0Sstevel@tonic-gate 	 * notice something funny in the header.
170*0Sstevel@tonic-gate 	 */
171*0Sstevel@tonic-gate 	if (len > 0 && (off + len <= (char *)e + elen)) {
172*0Sstevel@tonic-gate 		(void) memcpy(data, off, len);
173*0Sstevel@tonic-gate 		data_copied = B_TRUE;
174*0Sstevel@tonic-gate 	}
175*0Sstevel@tonic-gate 
176*0Sstevel@tonic-gate 	if (flags & F_SUM) {
177*0Sstevel@tonic-gate 		(void) sprintf(get_sum_line(),
178*0Sstevel@tonic-gate 			"ETHER Type=%04X (%s), size = %d bytes",
179*0Sstevel@tonic-gate 			ethertype,
180*0Sstevel@tonic-gate 			print_ethertype(ethertype),
181*0Sstevel@tonic-gate 			origlen);
182*0Sstevel@tonic-gate 	}
183*0Sstevel@tonic-gate 
184*0Sstevel@tonic-gate 	if (flags & F_DTAIL) {
185*0Sstevel@tonic-gate 	show_header("ETHER:  ", "Ether Header", elen);
186*0Sstevel@tonic-gate 	show_space();
187*0Sstevel@tonic-gate 	(void) sprintf(get_line(0, 0),
188*0Sstevel@tonic-gate 		"Packet %d arrived at %d:%02d:%d.%05d",
189*0Sstevel@tonic-gate 		pi_frame,
190*0Sstevel@tonic-gate 		pi_time_hour, pi_time_min, pi_time_sec,
191*0Sstevel@tonic-gate 		pi_time_usec / 10);
192*0Sstevel@tonic-gate 	(void) sprintf(get_line(0, 0),
193*0Sstevel@tonic-gate 		"Packet size = %d bytes",
194*0Sstevel@tonic-gate 		elen, elen);
195*0Sstevel@tonic-gate 	(void) sprintf(get_line(0, 6),
196*0Sstevel@tonic-gate 		"Destination = %s, %s",
197*0Sstevel@tonic-gate 		printether(&e->ether_dhost),
198*0Sstevel@tonic-gate 		print_etherinfo(&e->ether_dhost));
199*0Sstevel@tonic-gate 	(void) sprintf(get_line(6, 6),
200*0Sstevel@tonic-gate 		"Source      = %s, %s",
201*0Sstevel@tonic-gate 		printether(&e->ether_shost),
202*0Sstevel@tonic-gate 		print_etherinfo(&e->ether_shost));
203*0Sstevel@tonic-gate 	if (ieee8023 > 0)
204*0Sstevel@tonic-gate 		(void) sprintf(get_line(12, 2),
205*0Sstevel@tonic-gate 			"IEEE 802.3 length = %d bytes",
206*0Sstevel@tonic-gate 			ieee8023);
207*0Sstevel@tonic-gate 	(void) sprintf(get_line(12, 2),
208*0Sstevel@tonic-gate 		"Ethertype = %04X (%s)",
209*0Sstevel@tonic-gate 		ethertype, print_ethertype(ethertype));
210*0Sstevel@tonic-gate 	show_space();
211*0Sstevel@tonic-gate 	}
212*0Sstevel@tonic-gate 
213*0Sstevel@tonic-gate 	/* Go to the next protocol layer only if data have been copied. */
214*0Sstevel@tonic-gate 	if (data_copied) {
215*0Sstevel@tonic-gate 		switch (ethertype) {
216*0Sstevel@tonic-gate 		case ETHERTYPE_IP:
217*0Sstevel@tonic-gate 			(void) interpret_ip(flags, (struct ip *)data, len);
218*0Sstevel@tonic-gate 			break;
219*0Sstevel@tonic-gate 		/* Just in case it is decided to add this type */
220*0Sstevel@tonic-gate 		case ETHERTYPE_IPV6:
221*0Sstevel@tonic-gate 			(void) interpret_ipv6(flags, (ip6_t *)data, len);
222*0Sstevel@tonic-gate 			break;
223*0Sstevel@tonic-gate 		case ETHERTYPE_ARP:
224*0Sstevel@tonic-gate 		case ETHERTYPE_REVARP:
225*0Sstevel@tonic-gate 			interpret_arp(flags, (struct arphdr *)data, len);
226*0Sstevel@tonic-gate 			break;
227*0Sstevel@tonic-gate 		case ETHERTYPE_PPPOED:
228*0Sstevel@tonic-gate 		case ETHERTYPE_PPPOES:
229*0Sstevel@tonic-gate 			(void) interpret_pppoe(flags, (poep_t *)data, len);
230*0Sstevel@tonic-gate 			break;
231*0Sstevel@tonic-gate 		case ETHERTYPE_AARP:    /* AppleTalk */
232*0Sstevel@tonic-gate 			interpret_aarp(flags, data, len);
233*0Sstevel@tonic-gate 			break;
234*0Sstevel@tonic-gate 		case ETHERTYPE_AT:
235*0Sstevel@tonic-gate 			interpret_at(flags, (struct ddp_hdr *)data, len);
236*0Sstevel@tonic-gate 			break;
237*0Sstevel@tonic-gate 		default:
238*0Sstevel@tonic-gate 			break;
239*0Sstevel@tonic-gate 		}
240*0Sstevel@tonic-gate 	}
241*0Sstevel@tonic-gate 
242*0Sstevel@tonic-gate 	return (elen);
243*0Sstevel@tonic-gate }
244*0Sstevel@tonic-gate 
245*0Sstevel@tonic-gate /* ARGSUSED */
246*0Sstevel@tonic-gate uint_t
247*0Sstevel@tonic-gate ether_header_len(e)
248*0Sstevel@tonic-gate char *e;
249*0Sstevel@tonic-gate {
250*0Sstevel@tonic-gate 	return (14);
251*0Sstevel@tonic-gate }
252*0Sstevel@tonic-gate 
253*0Sstevel@tonic-gate 
254*0Sstevel@tonic-gate /*
255*0Sstevel@tonic-gate  * Table of Ethertypes.
256*0Sstevel@tonic-gate  * Some of the more popular entries
257*0Sstevel@tonic-gate  * are at the beginning of the table
258*0Sstevel@tonic-gate  * to reduce search time.
259*0Sstevel@tonic-gate  */
260*0Sstevel@tonic-gate struct ether_type {
261*0Sstevel@tonic-gate 	int   e_type;
262*0Sstevel@tonic-gate 	char *e_name;
263*0Sstevel@tonic-gate } ether_type [] = {
264*0Sstevel@tonic-gate ETHERTYPE_IP, "IP",
265*0Sstevel@tonic-gate ETHERTYPE_ARP, "ARP",
266*0Sstevel@tonic-gate ETHERTYPE_REVARP, "RARP",
267*0Sstevel@tonic-gate ETHERTYPE_IPV6, "IPv6",
268*0Sstevel@tonic-gate ETHERTYPE_PPPOED, "PPPoE Discovery",
269*0Sstevel@tonic-gate ETHERTYPE_PPPOES, "PPPoE Session",
270*0Sstevel@tonic-gate /* end of popular entries */
271*0Sstevel@tonic-gate ETHERTYPE_PUP,	"Xerox PUP",
272*0Sstevel@tonic-gate 0x0201, "Xerox PUP",
273*0Sstevel@tonic-gate 0x0400, "Nixdorf",
274*0Sstevel@tonic-gate 0x0600, "Xerox NS IDP",
275*0Sstevel@tonic-gate 0x0601, "XNS Translation",
276*0Sstevel@tonic-gate 0x0801, "X.75 Internet",
277*0Sstevel@tonic-gate 0x0802, "NBS Internet",
278*0Sstevel@tonic-gate 0x0803, "ECMA Internet",
279*0Sstevel@tonic-gate 0x0804, "CHAOSnet",
280*0Sstevel@tonic-gate 0x0805, "X.25 Level 3",
281*0Sstevel@tonic-gate 0x0807, "XNS Compatibility",
282*0Sstevel@tonic-gate 0x081C, "Symbolics Private",
283*0Sstevel@tonic-gate 0x0888, "Xyplex",
284*0Sstevel@tonic-gate 0x0889, "Xyplex",
285*0Sstevel@tonic-gate 0x088A, "Xyplex",
286*0Sstevel@tonic-gate 0x0900, "Ungermann-Bass network debugger",
287*0Sstevel@tonic-gate 0x0A00, "Xerox IEEE802.3 PUP",
288*0Sstevel@tonic-gate 0x0A01, "Xerox IEEE802.3 PUP Address Translation",
289*0Sstevel@tonic-gate 0x0BAD, "Banyan Systems",
290*0Sstevel@tonic-gate 0x0BAF, "Banyon VINES Echo",
291*0Sstevel@tonic-gate 0x1000, "Berkeley Trailer negotiation",
292*0Sstevel@tonic-gate 0x1000,	"IP trailer (0)",
293*0Sstevel@tonic-gate 0x1001,	"IP trailer (1)",
294*0Sstevel@tonic-gate 0x1002,	"IP trailer (2)",
295*0Sstevel@tonic-gate 0x1003,	"IP trailer (3)",
296*0Sstevel@tonic-gate 0x1004,	"IP trailer (4)",
297*0Sstevel@tonic-gate 0x1005,	"IP trailer (5)",
298*0Sstevel@tonic-gate 0x1006,	"IP trailer (6)",
299*0Sstevel@tonic-gate 0x1007,	"IP trailer (7)",
300*0Sstevel@tonic-gate 0x1008,	"IP trailer (8)",
301*0Sstevel@tonic-gate 0x1009,	"IP trailer (9)",
302*0Sstevel@tonic-gate 0x100a,	"IP trailer (10)",
303*0Sstevel@tonic-gate 0x100b,	"IP trailer (11)",
304*0Sstevel@tonic-gate 0x100c,	"IP trailer (12)",
305*0Sstevel@tonic-gate 0x100d,	"IP trailer (13)",
306*0Sstevel@tonic-gate 0x100e,	"IP trailer (14)",
307*0Sstevel@tonic-gate 0x100f,	"IP trailer (15)",
308*0Sstevel@tonic-gate 0x1234, "DCA - Multicast",
309*0Sstevel@tonic-gate 0x1600, "VALID system protocol",
310*0Sstevel@tonic-gate 0x1989, "Aviator",
311*0Sstevel@tonic-gate 0x3C00, "3Com NBP virtual circuit datagram",
312*0Sstevel@tonic-gate 0x3C01, "3Com NBP System control datagram",
313*0Sstevel@tonic-gate 0x3C02, "3Com NBP Connect request (virtual cct)",
314*0Sstevel@tonic-gate 0x3C03, "3Com NBP Connect response",
315*0Sstevel@tonic-gate 0x3C04, "3Com NBP Connect complete",
316*0Sstevel@tonic-gate 0x3C05, "3Com NBP Close request (virtual cct)",
317*0Sstevel@tonic-gate 0x3C06, "3Com NBP Close response",
318*0Sstevel@tonic-gate 0x3C07, "3Com NBP Datagram (like XNS IDP)",
319*0Sstevel@tonic-gate 0x3C08, "3Com NBP Datagram broadcast",
320*0Sstevel@tonic-gate 0x3C09, "3Com NBP Claim NetBIOS name",
321*0Sstevel@tonic-gate 0x3C0A, "3Com NBP Delete Netbios name",
322*0Sstevel@tonic-gate 0x3C0B, "3Com NBP Remote adaptor status request",
323*0Sstevel@tonic-gate 0x3C0C, "3Com NBP Remote adaptor response",
324*0Sstevel@tonic-gate 0x3C0D, "3Com NBP Reset",
325*0Sstevel@tonic-gate 0x4242, "PCS Basic Block Protocol",
326*0Sstevel@tonic-gate 0x4321, "THD - Diddle",
327*0Sstevel@tonic-gate 0x5208, "BBN Simnet Private",
328*0Sstevel@tonic-gate 0x6000, "DEC unass, experimental",
329*0Sstevel@tonic-gate 0x6001, "DEC Dump/Load",
330*0Sstevel@tonic-gate 0x6002, "DEC Remote Console",
331*0Sstevel@tonic-gate 0x6003, "DECNET Phase IV, DNA Routing",
332*0Sstevel@tonic-gate 0x6004, "DEC LAT",
333*0Sstevel@tonic-gate 0x6005, "DEC Diagnostic",
334*0Sstevel@tonic-gate 0x6006, "DEC customer protocol",
335*0Sstevel@tonic-gate 0x6007, "DEC Local Area VAX Cluster (LAVC)",
336*0Sstevel@tonic-gate 0x6008, "DEC unass (AMBER?)",
337*0Sstevel@tonic-gate 0x6009, "DEC unass (MUMPS?)",
338*0Sstevel@tonic-gate 0x6010, "3Com",
339*0Sstevel@tonic-gate 0x6011, "3Com",
340*0Sstevel@tonic-gate 0x6012, "3Com",
341*0Sstevel@tonic-gate 0x6013, "3Com",
342*0Sstevel@tonic-gate 0x6014, "3Com",
343*0Sstevel@tonic-gate 0x7000, "Ungermann-Bass download",
344*0Sstevel@tonic-gate 0x7001, "Ungermann-Bass NIUs",
345*0Sstevel@tonic-gate 0x7002, "Ungermann-Bass diagnostic/loopback",
346*0Sstevel@tonic-gate 0x7003, "Ungermann-Bass ? (NMC to/from UB Bridge)",
347*0Sstevel@tonic-gate 0x7005, "Ungermann-Bass Bridge Spanning Tree",
348*0Sstevel@tonic-gate 0x7007, "OS/9 Microware",
349*0Sstevel@tonic-gate 0x7009, "OS/9 Net?",
350*0Sstevel@tonic-gate 0x7020, "Sintrom",
351*0Sstevel@tonic-gate 0x7021, "Sintrom",
352*0Sstevel@tonic-gate 0x7022, "Sintrom",
353*0Sstevel@tonic-gate 0x7023, "Sintrom",
354*0Sstevel@tonic-gate 0x7024, "Sintrom",
355*0Sstevel@tonic-gate 0x7025, "Sintrom",
356*0Sstevel@tonic-gate 0x7026, "Sintrom",
357*0Sstevel@tonic-gate 0x7027, "Sintrom",
358*0Sstevel@tonic-gate 0x7028, "Sintrom",
359*0Sstevel@tonic-gate 0x7029, "Sintrom",
360*0Sstevel@tonic-gate 0x8003, "Cronus VLN",
361*0Sstevel@tonic-gate 0x8004, "Cronus Direct",
362*0Sstevel@tonic-gate 0x8005, "HP Probe protocol",
363*0Sstevel@tonic-gate 0x8006, "Nestar",
364*0Sstevel@tonic-gate 0x8008, "AT&T/Stanford Univ",
365*0Sstevel@tonic-gate 0x8010, "Excelan",
366*0Sstevel@tonic-gate 0x8013, "SGI diagnostic",
367*0Sstevel@tonic-gate 0x8014, "SGI network games",
368*0Sstevel@tonic-gate 0x8015, "SGI reserved",
369*0Sstevel@tonic-gate 0x8016, "SGI XNS NameServer, bounce server",
370*0Sstevel@tonic-gate 0x8019, "Apollo DOMAIN",
371*0Sstevel@tonic-gate 0x802E, "Tymshare",
372*0Sstevel@tonic-gate 0x802F, "Tigan,",
373*0Sstevel@tonic-gate 0x8036, "Aeonic Systems",
374*0Sstevel@tonic-gate 0x8037, "IPX (Novell Netware)",
375*0Sstevel@tonic-gate 0x8038, "DEC LanBridge Management",
376*0Sstevel@tonic-gate 0x8039, "DEC unass (DSM/DTP?)",
377*0Sstevel@tonic-gate 0x803A, "DEC unass (Argonaut Console?)",
378*0Sstevel@tonic-gate 0x803B, "DEC unass (VAXELN?)",
379*0Sstevel@tonic-gate 0x803C, "DEC unass (NMSV? DNA Naming Service?)",
380*0Sstevel@tonic-gate 0x803D, "DEC Ethernet CSMA/CD Encryption Protocol",
381*0Sstevel@tonic-gate 0x803E, "DEC unass (DNA Time Service?)",
382*0Sstevel@tonic-gate 0x803F, "DEC LAN Traffic Monitor Protocol",
383*0Sstevel@tonic-gate 0x8040, "DEC unass (NetBios Emulator?)",
384*0Sstevel@tonic-gate 0x8041, "DEC unass (MS/DOS?, Local Area System Transport?)",
385*0Sstevel@tonic-gate 0x8042, "DEC unass",
386*0Sstevel@tonic-gate 0x8044, "Planning Research Corp.",
387*0Sstevel@tonic-gate 0x8046, "AT&T",
388*0Sstevel@tonic-gate 0x8047, "AT&T",
389*0Sstevel@tonic-gate 0x8049, "ExperData",
390*0Sstevel@tonic-gate 0x805B, "VMTP",
391*0Sstevel@tonic-gate 0x805C, "Stanford V Kernel, version 6.0",
392*0Sstevel@tonic-gate 0x805D, "Evans & Sutherland",
393*0Sstevel@tonic-gate 0x8060, "Little Machines",
394*0Sstevel@tonic-gate 0x8062, "Counterpoint",
395*0Sstevel@tonic-gate 0x8065, "University of Mass. at Amherst",
396*0Sstevel@tonic-gate 0x8066, "University of Mass. at Amherst",
397*0Sstevel@tonic-gate 0x8067, "Veeco Integrated Automation",
398*0Sstevel@tonic-gate 0x8068, "General Dynamics",
399*0Sstevel@tonic-gate 0x8069, "AT&T",
400*0Sstevel@tonic-gate 0x806A, "Autophon",
401*0Sstevel@tonic-gate 0x806C, "ComDesign",
402*0Sstevel@tonic-gate 0x806D, "Compugraphic Corp",
403*0Sstevel@tonic-gate 0x806E, "Landmark",
404*0Sstevel@tonic-gate 0x806F, "Landmark",
405*0Sstevel@tonic-gate 0x8070, "Landmark",
406*0Sstevel@tonic-gate 0x8071, "Landmark",
407*0Sstevel@tonic-gate 0x8072, "Landmark",
408*0Sstevel@tonic-gate 0x8073, "Landmark",
409*0Sstevel@tonic-gate 0x8074, "Landmark",
410*0Sstevel@tonic-gate 0x8075, "Landmark",
411*0Sstevel@tonic-gate 0x8076, "Landmark",
412*0Sstevel@tonic-gate 0x8077, "Landmark",
413*0Sstevel@tonic-gate 0x807A, "Matra",
414*0Sstevel@tonic-gate 0x807B, "Dansk Data Elektronik",
415*0Sstevel@tonic-gate 0x807C, "Merit Internodal",
416*0Sstevel@tonic-gate 0x807D, "Vitalink",
417*0Sstevel@tonic-gate 0x807E, "Vitalink",
418*0Sstevel@tonic-gate 0x807F, "Vitalink",
419*0Sstevel@tonic-gate 0x8080, "Vitalink TransLAN III Management",
420*0Sstevel@tonic-gate 0x8081, "Counterpoint",
421*0Sstevel@tonic-gate 0x8082, "Counterpoint",
422*0Sstevel@tonic-gate 0x8083, "Counterpoint",
423*0Sstevel@tonic-gate 0x8088, "Xyplex",
424*0Sstevel@tonic-gate 0x8089, "Xyplex",
425*0Sstevel@tonic-gate 0x808A, "Xyplex",
426*0Sstevel@tonic-gate 0x809B, "EtherTalk (AppleTalk over Ethernet)",
427*0Sstevel@tonic-gate 0x809C, "Datability",
428*0Sstevel@tonic-gate 0x809D, "Datability",
429*0Sstevel@tonic-gate 0x809E, "Datability",
430*0Sstevel@tonic-gate 0x809F, "Spider Systems",
431*0Sstevel@tonic-gate 0x80A3, "Nixdorf",
432*0Sstevel@tonic-gate 0x80A4, "Siemens Gammasonics",
433*0Sstevel@tonic-gate 0x80C0, "DCA Data Exchange Cluster",
434*0Sstevel@tonic-gate 0x80C6, "Pacer Software",
435*0Sstevel@tonic-gate 0x80C7, "Applitek Corp",
436*0Sstevel@tonic-gate 0x80C8, "Intergraph",
437*0Sstevel@tonic-gate 0x80C9, "Intergraph",
438*0Sstevel@tonic-gate 0x80CB, "Intergraph",
439*0Sstevel@tonic-gate 0x80CC, "Intergraph",
440*0Sstevel@tonic-gate 0x80CA, "Intergraph",
441*0Sstevel@tonic-gate 0x80CD, "Harris Corp",
442*0Sstevel@tonic-gate 0x80CE, "Harris Corp",
443*0Sstevel@tonic-gate 0x80CF, "Taylor Instrument",
444*0Sstevel@tonic-gate 0x80D0, "Taylor Instrument",
445*0Sstevel@tonic-gate 0x80D1, "Taylor Instrument",
446*0Sstevel@tonic-gate 0x80D2, "Taylor Instrument",
447*0Sstevel@tonic-gate 0x80D3, "Rosemount Corp",
448*0Sstevel@tonic-gate 0x80D4, "Rosemount Corp",
449*0Sstevel@tonic-gate 0x80D5, "IBM SNA Services over Ethernet",
450*0Sstevel@tonic-gate 0x80DD, "Varian Associates",
451*0Sstevel@tonic-gate 0x80DE, "TRFS",
452*0Sstevel@tonic-gate 0x80DF, "TRFS",
453*0Sstevel@tonic-gate 0x80E0, "Allen-Bradley",
454*0Sstevel@tonic-gate 0x80E1, "Allen-Bradley",
455*0Sstevel@tonic-gate 0x80E2, "Allen-Bradley",
456*0Sstevel@tonic-gate 0x80E3, "Allen-Bradley",
457*0Sstevel@tonic-gate 0x80E4, "Datability",
458*0Sstevel@tonic-gate 0x80F2, "Retix",
459*0Sstevel@tonic-gate 0x80F3, "AARP (Appletalk)",
460*0Sstevel@tonic-gate 0x80F4, "Kinetics",
461*0Sstevel@tonic-gate 0x80F5, "Kinetics",
462*0Sstevel@tonic-gate 0x80F7, "Apollo",
463*0Sstevel@tonic-gate 0x80FF, "Wellfleet Communications",
464*0Sstevel@tonic-gate 0x8102, "Wellfleet Communications",
465*0Sstevel@tonic-gate 0x8107, "Symbolics Private",
466*0Sstevel@tonic-gate 0x8108, "Symbolics Private",
467*0Sstevel@tonic-gate 0x8109, "Symbolics Private",
468*0Sstevel@tonic-gate 0x812B, "Talaris",
469*0Sstevel@tonic-gate 0x8130, "Waterloo",
470*0Sstevel@tonic-gate 0x8131, "VG Lab",
471*0Sstevel@tonic-gate 0x8137, "Novell (old) NetWare IPX",
472*0Sstevel@tonic-gate 0x8138, "Novell",
473*0Sstevel@tonic-gate 0x814C, "SNMP over Ethernet",
474*0Sstevel@tonic-gate 0x817D, "XTP",
475*0Sstevel@tonic-gate 0x81D6, "Lantastic",
476*0Sstevel@tonic-gate 0x8888, "HP LanProbe test?",
477*0Sstevel@tonic-gate 0x9000, "Loopback",
478*0Sstevel@tonic-gate 0x9001, "3Com, XNS Systems Management",
479*0Sstevel@tonic-gate 0x9002, "3Com, TCP/IP Systems Management",
480*0Sstevel@tonic-gate 0x9003, "3Com, loopback detection",
481*0Sstevel@tonic-gate 0xAAAA, "DECNET	(VAX 6220 DEBNI)",
482*0Sstevel@tonic-gate 0xFF00, "BBN VITAL-LanBridge cache wakeups",
483*0Sstevel@tonic-gate 0,	"",
484*0Sstevel@tonic-gate };
485*0Sstevel@tonic-gate 
486*0Sstevel@tonic-gate char *
487*0Sstevel@tonic-gate print_fc(type)
488*0Sstevel@tonic-gate uint_t type;
489*0Sstevel@tonic-gate {
490*0Sstevel@tonic-gate 
491*0Sstevel@tonic-gate 	switch (type) {
492*0Sstevel@tonic-gate 		case 0x50: return ("LLC");
493*0Sstevel@tonic-gate 		case 0x4f: return ("SMT NSA");
494*0Sstevel@tonic-gate 		case 0x41: return ("SMT Info");
495*0Sstevel@tonic-gate 		default: return ("Unknown");
496*0Sstevel@tonic-gate 	}
497*0Sstevel@tonic-gate }
498*0Sstevel@tonic-gate 
499*0Sstevel@tonic-gate char *
500*0Sstevel@tonic-gate print_smtclass(type)
501*0Sstevel@tonic-gate uint_t type;
502*0Sstevel@tonic-gate {
503*0Sstevel@tonic-gate 	switch (type) {
504*0Sstevel@tonic-gate 		case 0x01: return ("NIF");
505*0Sstevel@tonic-gate 		case 0x02: return ("SIF Conf");
506*0Sstevel@tonic-gate 		case 0x03: return ("SIF Oper");
507*0Sstevel@tonic-gate 		case 0x04: return ("ECF");
508*0Sstevel@tonic-gate 		case 0x05: return ("RAF");
509*0Sstevel@tonic-gate 		case 0x06: return ("RDF");
510*0Sstevel@tonic-gate 		case 0x07: return ("SRF");
511*0Sstevel@tonic-gate 		case 0x08: return ("PMF Get");
512*0Sstevel@tonic-gate 		case 0x09: return ("PMF Change");
513*0Sstevel@tonic-gate 		case 0x0a: return ("PMF Add");
514*0Sstevel@tonic-gate 		case 0x0b: return ("PMF Remove");
515*0Sstevel@tonic-gate 		case 0xff: return ("ESF");
516*0Sstevel@tonic-gate 		default: return ("Unknown");
517*0Sstevel@tonic-gate 	}
518*0Sstevel@tonic-gate 
519*0Sstevel@tonic-gate }
520*0Sstevel@tonic-gate char *
521*0Sstevel@tonic-gate print_smttype(type)
522*0Sstevel@tonic-gate uint_t type;
523*0Sstevel@tonic-gate {
524*0Sstevel@tonic-gate 	switch (type) {
525*0Sstevel@tonic-gate 		case 0x01: return ("Announce");
526*0Sstevel@tonic-gate 		case 0x02: return ("Request");
527*0Sstevel@tonic-gate 		case 0x03: return ("Response");
528*0Sstevel@tonic-gate 		default: return ("Unknown");
529*0Sstevel@tonic-gate 	}
530*0Sstevel@tonic-gate 
531*0Sstevel@tonic-gate }
532*0Sstevel@tonic-gate char *
533*0Sstevel@tonic-gate print_ethertype(type)
534*0Sstevel@tonic-gate 	int type;
535*0Sstevel@tonic-gate {
536*0Sstevel@tonic-gate 	int i;
537*0Sstevel@tonic-gate 
538*0Sstevel@tonic-gate 	for (i = 0; ether_type[i].e_type; i++)
539*0Sstevel@tonic-gate 		if (type == ether_type[i].e_type)
540*0Sstevel@tonic-gate 			return (ether_type[i].e_name);
541*0Sstevel@tonic-gate 	if (type < 1500)
542*0Sstevel@tonic-gate 		return ("LLC/802.3");
543*0Sstevel@tonic-gate 
544*0Sstevel@tonic-gate 	return ("Unknown");
545*0Sstevel@tonic-gate }
546*0Sstevel@tonic-gate 
547*0Sstevel@tonic-gate #define	MAX_RDFLDS	14		/* changed to 14 from 8 as per IEEE */
548*0Sstevel@tonic-gate #define	TR_FN_ADDR	0x80		/* dest addr is functional */
549*0Sstevel@tonic-gate #define	TR_SR_ADDR	0x80		/* MAC utilizes source route */
550*0Sstevel@tonic-gate #define	ACFCDASA_LEN	14		/* length of AC|FC|DA|SA */
551*0Sstevel@tonic-gate #define	TR_MAC_MASK	0xc0
552*0Sstevel@tonic-gate #define	TR_AC		0x00		/* Token Ring access control */
553*0Sstevel@tonic-gate #define	TR_LLC_FC	0x40		/* Token Ring llc frame control */
554*0Sstevel@tonic-gate #define	LSAP_SNAP	0xaa
555*0Sstevel@tonic-gate #define	LLC_SNAP_HDR_LEN	8
556*0Sstevel@tonic-gate #define	LLC_HDR1_LEN	3		/* DON'T use sizeof(struct llc_hdr1) */
557*0Sstevel@tonic-gate #define	CNTL_LLC_UI	0x03		/* un-numbered information packet */
558*0Sstevel@tonic-gate 
559*0Sstevel@tonic-gate /*
560*0Sstevel@tonic-gate  * Source Routing Route Information field.
561*0Sstevel@tonic-gate  */
562*0Sstevel@tonic-gate struct tr_ri {
563*0Sstevel@tonic-gate #if defined(_BIT_FIELDS_HTOL)
564*0Sstevel@tonic-gate 	uchar_t rt:3;			/* routing type */
565*0Sstevel@tonic-gate 	uchar_t len:5;			/* length */
566*0Sstevel@tonic-gate 	uchar_t dir:1;			/* direction bit */
567*0Sstevel@tonic-gate 	uchar_t mtu:3;			/* largest frame */
568*0Sstevel@tonic-gate 	uchar_t res:4;			/* reserved */
569*0Sstevel@tonic-gate #elif defined(_BIT_FIELDS_LTOH)
570*0Sstevel@tonic-gate 	uchar_t len:5;			/* length */
571*0Sstevel@tonic-gate 	uchar_t rt:3;			/* routing type */
572*0Sstevel@tonic-gate 	uchar_t res:4;			/* reserved */
573*0Sstevel@tonic-gate 	uchar_t mtu:3;			/* largest frame */
574*0Sstevel@tonic-gate 	uchar_t dir:1;			/* direction bit */
575*0Sstevel@tonic-gate #endif
576*0Sstevel@tonic-gate /*
577*0Sstevel@tonic-gate  * In little endian machine, the ring field has to be stored in a
578*0Sstevel@tonic-gate  * ushort_t type.  This implies that it is not possible to have a
579*0Sstevel@tonic-gate  * layout of bit field to represent bridge and ring.
580*0Sstevel@tonic-gate  *
581*0Sstevel@tonic-gate  * If the compiler uses _BIT_FIELDS_HTOL and it is a big endian
582*0Sstevel@tonic-gate  * machine, the following bit field definition will work.
583*0Sstevel@tonic-gate  *
584*0Sstevel@tonic-gate  *	struct tr_rd {
585*0Sstevel@tonic-gate  *		ushort_t bridge:4;
586*0Sstevel@tonic-gate  *		ushort_t ring:12;
587*0Sstevel@tonic-gate  *	} rd[MAX_RDFLDS];
588*0Sstevel@tonic-gate  *
589*0Sstevel@tonic-gate  * If the compiler uses _BIT_FIELDS_LTOH and it is a big endian
590*0Sstevel@tonic-gate  * machine, the definition can be changed to
591*0Sstevel@tonic-gate  *
592*0Sstevel@tonic-gate  *	struct tr_rd {
593*0Sstevel@tonic-gate  *		ushort_t bridge:4;
594*0Sstevel@tonic-gate  *		ushort_t ring:12;
595*0Sstevel@tonic-gate  *	} rd[MAX_RDFLDS];
596*0Sstevel@tonic-gate  *
597*0Sstevel@tonic-gate  * With little endian machine, we need to use 2 macroes.  For
598*0Sstevel@tonic-gate  * simplicity, since the macroes work for both big and little
599*0Sstevel@tonic-gate  * endian machines, we will not use bit fields for the
600*0Sstevel@tonic-gate  * definition.
601*0Sstevel@tonic-gate  */
602*0Sstevel@tonic-gate #define	bridge(route)	(ntohs((ushort_t)(route)) & 0x0F)
603*0Sstevel@tonic-gate #define	ring(route)	(ntohs((ushort_t)(route)) >> 4)
604*0Sstevel@tonic-gate 
605*0Sstevel@tonic-gate 	ushort_t rd[MAX_RDFLDS];	/* route designator fields */
606*0Sstevel@tonic-gate };
607*0Sstevel@tonic-gate 
608*0Sstevel@tonic-gate struct tr_header {
609*0Sstevel@tonic-gate 	uchar_t		ac;
610*0Sstevel@tonic-gate 	uchar_t		fc;
611*0Sstevel@tonic-gate 	struct ether_addr dhost;
612*0Sstevel@tonic-gate 	struct ether_addr shost;
613*0Sstevel@tonic-gate 	struct tr_ri	ri;
614*0Sstevel@tonic-gate };
615*0Sstevel@tonic-gate 
616*0Sstevel@tonic-gate struct llc_snap_hdr {
617*0Sstevel@tonic-gate 	uchar_t  d_lsap;		/* destination service access point */
618*0Sstevel@tonic-gate 	uchar_t  s_lsap;		/* source link service access point */
619*0Sstevel@tonic-gate 	uchar_t  control;		/* short control field */
620*0Sstevel@tonic-gate 	uchar_t  org[3];		/* Ethernet style organization field */
621*0Sstevel@tonic-gate 	ushort_t type;			/* Ethernet style type field */
622*0Sstevel@tonic-gate };
623*0Sstevel@tonic-gate 
624*0Sstevel@tonic-gate struct ether_addr tokenbroadcastaddr2 = {
625*0Sstevel@tonic-gate 	0xc0, 0x00, 0xff, 0xff, 0xff, 0xff
626*0Sstevel@tonic-gate };
627*0Sstevel@tonic-gate 
628*0Sstevel@tonic-gate int Mtutab[] = {516, 1470, 2052, 4472, 8144, 11407, 17800};
629*0Sstevel@tonic-gate 
630*0Sstevel@tonic-gate char *
631*0Sstevel@tonic-gate print_sr(struct tr_ri *rh)
632*0Sstevel@tonic-gate {
633*0Sstevel@tonic-gate 	int hops, ii;
634*0Sstevel@tonic-gate 	static char line[512];
635*0Sstevel@tonic-gate 
636*0Sstevel@tonic-gate 	sprintf(line, "TR Source Route dir=%d, mtu=%d",
637*0Sstevel@tonic-gate 			rh->dir, Mtutab[rh->mtu]);
638*0Sstevel@tonic-gate 
639*0Sstevel@tonic-gate 	hops = (int)(rh->len - 2) / (int)2;
640*0Sstevel@tonic-gate 
641*0Sstevel@tonic-gate 	if (hops) {
642*0Sstevel@tonic-gate 		sprintf(line+strlen(line), ", Route: ");
643*0Sstevel@tonic-gate 		for (ii = 0; ii < hops; ii++) {
644*0Sstevel@tonic-gate 			if (! bridge(rh->rd[ii])) {
645*0Sstevel@tonic-gate 				sprintf(line+strlen(line), "(%d)",
646*0Sstevel@tonic-gate 				    ring(rh->rd[ii]));
647*0Sstevel@tonic-gate 			} else {
648*0Sstevel@tonic-gate 				sprintf(line+strlen(line), "(%d)%d",
649*0Sstevel@tonic-gate 				    ring(rh->rd[ii]), bridge(rh->rd[ii]));
650*0Sstevel@tonic-gate 			}
651*0Sstevel@tonic-gate 		}
652*0Sstevel@tonic-gate 	}
653*0Sstevel@tonic-gate 	return (&line[0]);
654*0Sstevel@tonic-gate }
655*0Sstevel@tonic-gate 
656*0Sstevel@tonic-gate uint_t
657*0Sstevel@tonic-gate interpret_tr(flags, e, elen, origlen)
658*0Sstevel@tonic-gate 	int flags;
659*0Sstevel@tonic-gate 	caddr_t	e;
660*0Sstevel@tonic-gate 	int elen, origlen;
661*0Sstevel@tonic-gate {
662*0Sstevel@tonic-gate 	struct tr_header *mh;
663*0Sstevel@tonic-gate 	struct tr_ri *rh;
664*0Sstevel@tonic-gate 	uchar_t fc;
665*0Sstevel@tonic-gate 	struct llc_snap_hdr *snaphdr;
666*0Sstevel@tonic-gate 	char *off;
667*0Sstevel@tonic-gate 	int maclen, len;
668*0Sstevel@tonic-gate 	boolean_t data_copied = B_FALSE;
669*0Sstevel@tonic-gate 	extern char *dst_name, *src_name;
670*0Sstevel@tonic-gate 	int ethertype;
671*0Sstevel@tonic-gate 	int is_llc = 0, is_snap = 0, source_routing = 0;
672*0Sstevel@tonic-gate 	int tr_machdr_len(char *, int *, int *);
673*0Sstevel@tonic-gate 	int blen = MAX(origlen, 17800);
674*0Sstevel@tonic-gate 
675*0Sstevel@tonic-gate 	if (data != NULL && datalen != 0 && datalen < blen) {
676*0Sstevel@tonic-gate 		free(data);
677*0Sstevel@tonic-gate 		data = NULL;
678*0Sstevel@tonic-gate 		datalen = 0;
679*0Sstevel@tonic-gate 	}
680*0Sstevel@tonic-gate 	if (!data) {
681*0Sstevel@tonic-gate 		data = (char *)malloc(blen);
682*0Sstevel@tonic-gate 		if (!data)
683*0Sstevel@tonic-gate 			pr_err("Warning: malloc failure");
684*0Sstevel@tonic-gate 		datalen = blen;
685*0Sstevel@tonic-gate 	}
686*0Sstevel@tonic-gate 
687*0Sstevel@tonic-gate 	if (origlen < ACFCDASA_LEN) {
688*0Sstevel@tonic-gate 		if (flags & F_SUM)
689*0Sstevel@tonic-gate 			(void) sprintf(get_sum_line(),
690*0Sstevel@tonic-gate 			"RUNT (short packet - %d bytes)",
691*0Sstevel@tonic-gate 			origlen);
692*0Sstevel@tonic-gate 		if (flags & F_DTAIL)
693*0Sstevel@tonic-gate 			show_header("RUNT:  ", "Short packet", origlen);
694*0Sstevel@tonic-gate 		return (elen);
695*0Sstevel@tonic-gate 	}
696*0Sstevel@tonic-gate 	if (elen < ACFCDASA_LEN)
697*0Sstevel@tonic-gate 		return (elen);
698*0Sstevel@tonic-gate 
699*0Sstevel@tonic-gate 	mh = (struct tr_header *)e;
700*0Sstevel@tonic-gate 	rh = (struct tr_ri *)&mh->ri;
701*0Sstevel@tonic-gate 	fc = mh->fc;
702*0Sstevel@tonic-gate 
703*0Sstevel@tonic-gate 	if (is_llc = tr_machdr_len(e, &maclen, &source_routing)) {
704*0Sstevel@tonic-gate 		snaphdr = (struct llc_snap_hdr *)(e + maclen);
705*0Sstevel@tonic-gate 		if (snaphdr->d_lsap == LSAP_SNAP &&
706*0Sstevel@tonic-gate 			snaphdr->s_lsap == LSAP_SNAP &&
707*0Sstevel@tonic-gate 			snaphdr->control == CNTL_LLC_UI) {
708*0Sstevel@tonic-gate 			is_snap = 1;
709*0Sstevel@tonic-gate 		}
710*0Sstevel@tonic-gate 	}
711*0Sstevel@tonic-gate 
712*0Sstevel@tonic-gate 	if (memcmp(&mh->dhost, &ether_broadcast,
713*0Sstevel@tonic-gate 	    sizeof (struct ether_addr)) == 0)
714*0Sstevel@tonic-gate 		dst_name = "(broadcast)";
715*0Sstevel@tonic-gate 	else if (memcmp(&mh->dhost, &tokenbroadcastaddr2,
716*0Sstevel@tonic-gate 		sizeof (struct ether_addr)) == 0)
717*0Sstevel@tonic-gate 		dst_name = "(mac broadcast)";
718*0Sstevel@tonic-gate 	else if (mh->dhost.ether_addr_octet[0] & TR_FN_ADDR)
719*0Sstevel@tonic-gate 		dst_name = "(functional)";
720*0Sstevel@tonic-gate 
721*0Sstevel@tonic-gate 	if (is_snap)
722*0Sstevel@tonic-gate 		ethertype = ntohs(snaphdr->type);
723*0Sstevel@tonic-gate 	else {
724*0Sstevel@tonic-gate 		src_name =  print_etherinfo(&mh->shost);
725*0Sstevel@tonic-gate 		dst_name =  print_etherinfo(&mh->dhost);
726*0Sstevel@tonic-gate 	}
727*0Sstevel@tonic-gate 
728*0Sstevel@tonic-gate 	/*
729*0Sstevel@tonic-gate 	 * The 14 byte ether header screws up alignment
730*0Sstevel@tonic-gate 	 * of the rest of the packet for 32 bit aligned
731*0Sstevel@tonic-gate 	 * architectures like SPARC. Alas, we have to copy
732*0Sstevel@tonic-gate 	 * the rest of the packet in order to align it.
733*0Sstevel@tonic-gate 	 */
734*0Sstevel@tonic-gate 	if (is_llc) {
735*0Sstevel@tonic-gate 		if (is_snap) {
736*0Sstevel@tonic-gate 			len = elen - (maclen + LLC_SNAP_HDR_LEN);
737*0Sstevel@tonic-gate 			off = (char *)(e + maclen + LLC_SNAP_HDR_LEN);
738*0Sstevel@tonic-gate 		} else {
739*0Sstevel@tonic-gate 			len = elen - (maclen + LLC_HDR1_LEN);
740*0Sstevel@tonic-gate 			off = (char *)(e + maclen + LLC_HDR1_LEN);
741*0Sstevel@tonic-gate 		}
742*0Sstevel@tonic-gate 	} else {
743*0Sstevel@tonic-gate 		len = elen - maclen;
744*0Sstevel@tonic-gate 		off = (char *)(e + maclen);
745*0Sstevel@tonic-gate 	}
746*0Sstevel@tonic-gate 
747*0Sstevel@tonic-gate 	if (len > 0 && (off + len <= (char *)e + elen)) {
748*0Sstevel@tonic-gate 		(void) memcpy(data, off, len);
749*0Sstevel@tonic-gate 		data_copied = B_TRUE;
750*0Sstevel@tonic-gate 	}
751*0Sstevel@tonic-gate 
752*0Sstevel@tonic-gate 	if (flags & F_SUM) {
753*0Sstevel@tonic-gate 		if (source_routing)
754*0Sstevel@tonic-gate 			sprintf(get_sum_line(), print_sr(rh));
755*0Sstevel@tonic-gate 
756*0Sstevel@tonic-gate 		if (is_llc) {
757*0Sstevel@tonic-gate 			if (is_snap) {
758*0Sstevel@tonic-gate 				(void) sprintf(get_sum_line(),
759*0Sstevel@tonic-gate 				"TR LLC w/SNAP Type=%04X (%s), size=%d bytes",
760*0Sstevel@tonic-gate 				ethertype,
761*0Sstevel@tonic-gate 				print_ethertype(ethertype),
762*0Sstevel@tonic-gate 				origlen);
763*0Sstevel@tonic-gate 			} else {
764*0Sstevel@tonic-gate 				(void) sprintf(get_sum_line(),
765*0Sstevel@tonic-gate 				"TR LLC, but no SNAP encoding, size = %d bytes",
766*0Sstevel@tonic-gate 				origlen);
767*0Sstevel@tonic-gate 			}
768*0Sstevel@tonic-gate 		} else {
769*0Sstevel@tonic-gate 			(void) sprintf(get_sum_line(),
770*0Sstevel@tonic-gate 				"TR MAC FC=%02X (%s), size = %d bytes",
771*0Sstevel@tonic-gate 				fc, print_fc(fc), origlen);
772*0Sstevel@tonic-gate 		}
773*0Sstevel@tonic-gate 	}
774*0Sstevel@tonic-gate 
775*0Sstevel@tonic-gate 	if (flags & F_DTAIL) {
776*0Sstevel@tonic-gate 	show_header("TR:  ", "TR Header", elen);
777*0Sstevel@tonic-gate 	show_space();
778*0Sstevel@tonic-gate 	(void) sprintf(get_line(0, 0),
779*0Sstevel@tonic-gate 		"Packet %d arrived at %d:%02d:%d.%05d",
780*0Sstevel@tonic-gate 		pi_frame,
781*0Sstevel@tonic-gate 		pi_time_hour, pi_time_min, pi_time_sec,
782*0Sstevel@tonic-gate 		pi_time_usec / 10);
783*0Sstevel@tonic-gate 	(void) sprintf(get_line(0, 0),
784*0Sstevel@tonic-gate 		"Packet size = %d bytes",
785*0Sstevel@tonic-gate 		elen);
786*0Sstevel@tonic-gate 	(void) sprintf(get_line(0, 1),
787*0Sstevel@tonic-gate 		"Frame Control = %02x (%s)",
788*0Sstevel@tonic-gate 		fc, print_fc(fc));
789*0Sstevel@tonic-gate 	(void) sprintf(get_line(2, 6),
790*0Sstevel@tonic-gate 		"Destination = %s, %s",
791*0Sstevel@tonic-gate 		printether(&mh->dhost),
792*0Sstevel@tonic-gate 		print_etherinfo(&mh->dhost));
793*0Sstevel@tonic-gate 	(void) sprintf(get_line(8, 6),
794*0Sstevel@tonic-gate 		"Source      = %s, %s",
795*0Sstevel@tonic-gate 		printether(&mh->shost),
796*0Sstevel@tonic-gate 		print_etherinfo(&mh->shost));
797*0Sstevel@tonic-gate 
798*0Sstevel@tonic-gate 	if (source_routing)
799*0Sstevel@tonic-gate 		sprintf(get_line(ACFCDASA_LEN, rh->len), print_sr(rh));
800*0Sstevel@tonic-gate 
801*0Sstevel@tonic-gate 	if (is_llc) {
802*0Sstevel@tonic-gate 		(void) sprintf(get_line(maclen, 1),
803*0Sstevel@tonic-gate 			"Dest   Service Access Point = %02x",
804*0Sstevel@tonic-gate 			snaphdr->d_lsap);
805*0Sstevel@tonic-gate 		(void) sprintf(get_line(maclen+1, 1),
806*0Sstevel@tonic-gate 			"Source Service Access Point = %02x",
807*0Sstevel@tonic-gate 			snaphdr->s_lsap);
808*0Sstevel@tonic-gate 		(void) sprintf(get_line(maclen+2, 1),
809*0Sstevel@tonic-gate 			"Control = %02x",
810*0Sstevel@tonic-gate 			snaphdr->control);
811*0Sstevel@tonic-gate 		if (is_snap)
812*0Sstevel@tonic-gate 			(void) sprintf(get_line(maclen+3, 3),
813*0Sstevel@tonic-gate 				"SNAP Protocol Id = %02x%02x%02x",
814*0Sstevel@tonic-gate 				snaphdr->org[0], snaphdr->org[1],
815*0Sstevel@tonic-gate 				snaphdr->org[2]);
816*0Sstevel@tonic-gate 	}
817*0Sstevel@tonic-gate 
818*0Sstevel@tonic-gate 	if (is_snap)
819*0Sstevel@tonic-gate 		(void) sprintf(get_line(maclen+6, 2),
820*0Sstevel@tonic-gate 		"SNAP Type = %04X (%s)",
821*0Sstevel@tonic-gate 		ethertype, print_ethertype(ethertype));
822*0Sstevel@tonic-gate 
823*0Sstevel@tonic-gate 	show_space();
824*0Sstevel@tonic-gate 	}
825*0Sstevel@tonic-gate 
826*0Sstevel@tonic-gate 	/* go to the next protocol layer */
827*0Sstevel@tonic-gate 	if (is_snap && data_copied) {
828*0Sstevel@tonic-gate 		switch (ethertype) {
829*0Sstevel@tonic-gate 		case ETHERTYPE_IP:
830*0Sstevel@tonic-gate 			(void) interpret_ip(flags, (struct ip *)data, len);
831*0Sstevel@tonic-gate 			break;
832*0Sstevel@tonic-gate 		/* Just in case it is decided to add this type */
833*0Sstevel@tonic-gate 		case ETHERTYPE_IPV6:
834*0Sstevel@tonic-gate 			(void) interpret_ipv6(flags, (ip6_t *)data, len);
835*0Sstevel@tonic-gate 			break;
836*0Sstevel@tonic-gate 		case ETHERTYPE_ARP:
837*0Sstevel@tonic-gate 		case ETHERTYPE_REVARP:
838*0Sstevel@tonic-gate 			interpret_arp(flags, (struct arphdr *)data, len);
839*0Sstevel@tonic-gate 			break;
840*0Sstevel@tonic-gate 		case ETHERTYPE_AARP:	/* AppleTalk */
841*0Sstevel@tonic-gate 			interpret_aarp(flags, data, len);
842*0Sstevel@tonic-gate 			break;
843*0Sstevel@tonic-gate 		case ETHERTYPE_AT:
844*0Sstevel@tonic-gate 			interpret_at(flags, (struct ddp_hdr *)data, len);
845*0Sstevel@tonic-gate 			break;
846*0Sstevel@tonic-gate 		default:
847*0Sstevel@tonic-gate 			break;
848*0Sstevel@tonic-gate 		}
849*0Sstevel@tonic-gate 	}
850*0Sstevel@tonic-gate 
851*0Sstevel@tonic-gate 	return (elen);
852*0Sstevel@tonic-gate }
853*0Sstevel@tonic-gate 
854*0Sstevel@tonic-gate 
855*0Sstevel@tonic-gate /*
856*0Sstevel@tonic-gate  *	stuffs length of mac and ri fields into *lenp
857*0Sstevel@tonic-gate  *	returns:
858*0Sstevel@tonic-gate  *		0: mac frame
859*0Sstevel@tonic-gate  *		1: llc frame
860*0Sstevel@tonic-gate  */
861*0Sstevel@tonic-gate int
862*0Sstevel@tonic-gate tr_machdr_len(char *e, int *lenp, int *source_routing)
863*0Sstevel@tonic-gate {
864*0Sstevel@tonic-gate 	struct tr_header *mh;
865*0Sstevel@tonic-gate 	struct tr_ri *rh;
866*0Sstevel@tonic-gate 	uchar_t fc;
867*0Sstevel@tonic-gate 
868*0Sstevel@tonic-gate 	mh = (struct tr_header *)e;
869*0Sstevel@tonic-gate 	rh = (struct tr_ri *)&mh->ri;
870*0Sstevel@tonic-gate 	fc = mh->fc;
871*0Sstevel@tonic-gate 
872*0Sstevel@tonic-gate 	if (mh->shost.ether_addr_octet[0] & TR_SR_ADDR) {
873*0Sstevel@tonic-gate 		*lenp = ACFCDASA_LEN + rh->len;
874*0Sstevel@tonic-gate 		*source_routing = 1;
875*0Sstevel@tonic-gate 	} else {
876*0Sstevel@tonic-gate 		*lenp = ACFCDASA_LEN;
877*0Sstevel@tonic-gate 		*source_routing = 0;
878*0Sstevel@tonic-gate 	}
879*0Sstevel@tonic-gate 
880*0Sstevel@tonic-gate 	if ((fc & TR_MAC_MASK) == 0)
881*0Sstevel@tonic-gate 		return (0);		/* it's a MAC frame */
882*0Sstevel@tonic-gate 	else
883*0Sstevel@tonic-gate 		return (1);		/* it's an LLC frame */
884*0Sstevel@tonic-gate }
885*0Sstevel@tonic-gate 
886*0Sstevel@tonic-gate uint_t
887*0Sstevel@tonic-gate tr_header_len(e)
888*0Sstevel@tonic-gate char	*e;
889*0Sstevel@tonic-gate {
890*0Sstevel@tonic-gate 	struct llc_snap_hdr *snaphdr;
891*0Sstevel@tonic-gate 	int len = 0, source_routing;
892*0Sstevel@tonic-gate 
893*0Sstevel@tonic-gate 	if (tr_machdr_len(e, &len, &source_routing) == 0)
894*0Sstevel@tonic-gate 		return (len);		/* it's a MAC frame */
895*0Sstevel@tonic-gate 
896*0Sstevel@tonic-gate 	snaphdr = (struct llc_snap_hdr *)(e + len);
897*0Sstevel@tonic-gate 	if (snaphdr->d_lsap == LSAP_SNAP &&
898*0Sstevel@tonic-gate 			snaphdr->s_lsap == LSAP_SNAP &&
899*0Sstevel@tonic-gate 			snaphdr->control == CNTL_LLC_UI)
900*0Sstevel@tonic-gate 		len += LLC_SNAP_HDR_LEN;	/* it's a SNAP frame */
901*0Sstevel@tonic-gate 	else
902*0Sstevel@tonic-gate 		len += LLC_HDR1_LEN;
903*0Sstevel@tonic-gate 
904*0Sstevel@tonic-gate 	return (len);
905*0Sstevel@tonic-gate }
906*0Sstevel@tonic-gate 
907*0Sstevel@tonic-gate struct fddi_header {
908*0Sstevel@tonic-gate 	uchar_t fc;
909*0Sstevel@tonic-gate 	struct ether_addr dhost, shost;
910*0Sstevel@tonic-gate 	uchar_t dsap, ssap, ctl, proto_id[3];
911*0Sstevel@tonic-gate 	ushort_t	type;
912*0Sstevel@tonic-gate };
913*0Sstevel@tonic-gate 
914*0Sstevel@tonic-gate uint_t
915*0Sstevel@tonic-gate interpret_fddi(flags, e, elen, origlen)
916*0Sstevel@tonic-gate 	int flags;
917*0Sstevel@tonic-gate 	caddr_t	e;
918*0Sstevel@tonic-gate 	int elen, origlen;
919*0Sstevel@tonic-gate {
920*0Sstevel@tonic-gate 	struct fddi_header fhdr, *f = &fhdr;
921*0Sstevel@tonic-gate 	char *off;
922*0Sstevel@tonic-gate 	int len;
923*0Sstevel@tonic-gate 	boolean_t data_copied = B_FALSE;
924*0Sstevel@tonic-gate 	extern char *dst_name, *src_name;
925*0Sstevel@tonic-gate 	int ethertype;
926*0Sstevel@tonic-gate 	int is_llc = 0, is_smt = 0, is_snap = 0;
927*0Sstevel@tonic-gate 	int blen = MAX(origlen, 4500);
928*0Sstevel@tonic-gate 
929*0Sstevel@tonic-gate 	if (data != NULL && datalen != 0 && datalen < blen) {
930*0Sstevel@tonic-gate 		free(data);
931*0Sstevel@tonic-gate 		data = NULL;
932*0Sstevel@tonic-gate 		datalen = 0;
933*0Sstevel@tonic-gate 	}
934*0Sstevel@tonic-gate 	if (!data) {
935*0Sstevel@tonic-gate 		data = (char *)malloc(blen);
936*0Sstevel@tonic-gate 		if (!data)
937*0Sstevel@tonic-gate 			pr_err("Warning: malloc failure");
938*0Sstevel@tonic-gate 		datalen = blen;
939*0Sstevel@tonic-gate 	}
940*0Sstevel@tonic-gate 
941*0Sstevel@tonic-gate 	if (origlen < 13) {
942*0Sstevel@tonic-gate 		if (flags & F_SUM)
943*0Sstevel@tonic-gate 			(void) sprintf(get_sum_line(),
944*0Sstevel@tonic-gate 			"RUNT (short packet - %d bytes)",
945*0Sstevel@tonic-gate 			origlen);
946*0Sstevel@tonic-gate 		if (flags & F_DTAIL)
947*0Sstevel@tonic-gate 			show_header("RUNT:  ", "Short packet", origlen);
948*0Sstevel@tonic-gate 		return (elen);
949*0Sstevel@tonic-gate 	}
950*0Sstevel@tonic-gate 	if (elen < 13)
951*0Sstevel@tonic-gate 		return (elen);
952*0Sstevel@tonic-gate 
953*0Sstevel@tonic-gate 	(void) memcpy(&f->fc, e, sizeof (f->fc));
954*0Sstevel@tonic-gate 	addr_copy_swap(&f->dhost, (struct ether_addr *)(e+1));
955*0Sstevel@tonic-gate 	addr_copy_swap(&f->shost, (struct ether_addr *)(e+7));
956*0Sstevel@tonic-gate 
957*0Sstevel@tonic-gate 	if ((f->fc&0x50) == 0x50) {
958*0Sstevel@tonic-gate 		is_llc = 1;
959*0Sstevel@tonic-gate 		(void) memcpy(&f->dsap, e+13, sizeof (f->dsap));
960*0Sstevel@tonic-gate 		(void) memcpy(&f->ssap, e+14, sizeof (f->ssap));
961*0Sstevel@tonic-gate 		(void) memcpy(&f->ctl, e+15, sizeof (f->ctl));
962*0Sstevel@tonic-gate 		if (f->dsap == 0xaa && f->ssap == 0xaa) {
963*0Sstevel@tonic-gate 			is_snap = 1;
964*0Sstevel@tonic-gate 			(void) memcpy(&f->proto_id, e+16, sizeof (f->proto_id));
965*0Sstevel@tonic-gate 			(void) memcpy(&f->type, e+19, sizeof (f->type));
966*0Sstevel@tonic-gate 		}
967*0Sstevel@tonic-gate 	} else {
968*0Sstevel@tonic-gate 		if ((f->fc&0x41) == 0x41 || (f->fc&0x4f) == 0x4f) {
969*0Sstevel@tonic-gate 			is_smt = 1;
970*0Sstevel@tonic-gate 		}
971*0Sstevel@tonic-gate 	}
972*0Sstevel@tonic-gate 
973*0Sstevel@tonic-gate 
974*0Sstevel@tonic-gate 	if (memcmp(&f->dhost, &ether_broadcast,
975*0Sstevel@tonic-gate 	    sizeof (struct ether_addr)) == 0)
976*0Sstevel@tonic-gate 		dst_name = "(broadcast)";
977*0Sstevel@tonic-gate 	else if (f->dhost.ether_addr_octet[0] & 0x01)
978*0Sstevel@tonic-gate 		dst_name = "(multicast)";
979*0Sstevel@tonic-gate 
980*0Sstevel@tonic-gate 	if (is_snap)
981*0Sstevel@tonic-gate 		ethertype = ntohs(f->type);
982*0Sstevel@tonic-gate 	else {
983*0Sstevel@tonic-gate 		src_name = 	print_etherinfo(&f->shost);
984*0Sstevel@tonic-gate 		dst_name =  print_etherinfo(&f->dhost);
985*0Sstevel@tonic-gate 	}
986*0Sstevel@tonic-gate 
987*0Sstevel@tonic-gate 	/*
988*0Sstevel@tonic-gate 	 * The 14 byte ether header screws up alignment
989*0Sstevel@tonic-gate 	 * of the rest of the packet for 32 bit aligned
990*0Sstevel@tonic-gate 	 * architectures like SPARC. Alas, we have to copy
991*0Sstevel@tonic-gate 	 * the rest of the packet in order to align it.
992*0Sstevel@tonic-gate 	 */
993*0Sstevel@tonic-gate 	if (is_llc) {
994*0Sstevel@tonic-gate 		if (is_snap) {
995*0Sstevel@tonic-gate 			len = elen - 21;
996*0Sstevel@tonic-gate 			off = (char *)(e + 21);
997*0Sstevel@tonic-gate 		} else {
998*0Sstevel@tonic-gate 			len = elen - 16;
999*0Sstevel@tonic-gate 			off = (char *)(e + 16);
1000*0Sstevel@tonic-gate 		}
1001*0Sstevel@tonic-gate 	} else {
1002*0Sstevel@tonic-gate 		len = elen - 13;
1003*0Sstevel@tonic-gate 		off = (char *)(e + 13);
1004*0Sstevel@tonic-gate 	}
1005*0Sstevel@tonic-gate 
1006*0Sstevel@tonic-gate 	if (len > 0 && (off + len <= (char *)e + elen)) {
1007*0Sstevel@tonic-gate 		(void) memcpy(data, off, len);
1008*0Sstevel@tonic-gate 		data_copied = B_TRUE;
1009*0Sstevel@tonic-gate 	}
1010*0Sstevel@tonic-gate 
1011*0Sstevel@tonic-gate 	if (flags & F_SUM) {
1012*0Sstevel@tonic-gate 		if (is_llc) {
1013*0Sstevel@tonic-gate 			if (is_snap) {
1014*0Sstevel@tonic-gate 				(void) sprintf(get_sum_line(),
1015*0Sstevel@tonic-gate 				"FDDI LLC Type=%04X (%s), size = %d bytes",
1016*0Sstevel@tonic-gate 				ethertype,
1017*0Sstevel@tonic-gate 				print_ethertype(ethertype),
1018*0Sstevel@tonic-gate 				origlen);
1019*0Sstevel@tonic-gate 			} else {
1020*0Sstevel@tonic-gate 				(void) sprintf(get_sum_line(),
1021*0Sstevel@tonic-gate 				"LLC, but no SNAP encoding, size = %d bytes",
1022*0Sstevel@tonic-gate 				origlen);
1023*0Sstevel@tonic-gate 			}
1024*0Sstevel@tonic-gate 		} else if (is_smt) {
1025*0Sstevel@tonic-gate 			(void) sprintf(get_sum_line(),
1026*0Sstevel@tonic-gate 		"SMT Type=%02X (%s), Class = %02X (%s), size = %d bytes",
1027*0Sstevel@tonic-gate 			*(uchar_t *)(data+1), print_smttype(*(data+1)), *data,
1028*0Sstevel@tonic-gate 			print_smtclass(*data), origlen);
1029*0Sstevel@tonic-gate 		} else {
1030*0Sstevel@tonic-gate 			(void) sprintf(get_sum_line(),
1031*0Sstevel@tonic-gate 				"FC=%02X (%s), size = %d bytes",
1032*0Sstevel@tonic-gate 				f->fc, print_fc(f->fc), origlen);
1033*0Sstevel@tonic-gate 		}
1034*0Sstevel@tonic-gate 	}
1035*0Sstevel@tonic-gate 
1036*0Sstevel@tonic-gate 	if (flags & F_DTAIL) {
1037*0Sstevel@tonic-gate 	show_header("FDDI:  ", "FDDI Header", elen);
1038*0Sstevel@tonic-gate 	show_space();
1039*0Sstevel@tonic-gate 	(void) sprintf(get_line(0, 0),
1040*0Sstevel@tonic-gate 		"Packet %d arrived at %d:%02d:%d.%05d",
1041*0Sstevel@tonic-gate 		pi_frame,
1042*0Sstevel@tonic-gate 		pi_time_hour, pi_time_min, pi_time_sec,
1043*0Sstevel@tonic-gate 		pi_time_usec / 10);
1044*0Sstevel@tonic-gate 	(void) sprintf(get_line(0, 0),
1045*0Sstevel@tonic-gate 		"Packet size = %d bytes",
1046*0Sstevel@tonic-gate 		elen, elen);
1047*0Sstevel@tonic-gate 	(void) sprintf(get_line(0, 6),
1048*0Sstevel@tonic-gate 		"Destination = %s, %s",
1049*0Sstevel@tonic-gate 		printether(&f->dhost),
1050*0Sstevel@tonic-gate 		print_etherinfo(&f->dhost));
1051*0Sstevel@tonic-gate 	(void) sprintf(get_line(6, 6),
1052*0Sstevel@tonic-gate 		"Source      = %s, %s",
1053*0Sstevel@tonic-gate 		printether(&f->shost),
1054*0Sstevel@tonic-gate 		print_etherinfo(&f->shost));
1055*0Sstevel@tonic-gate 
1056*0Sstevel@tonic-gate 	if (is_llc) {
1057*0Sstevel@tonic-gate 		(void) sprintf(get_line(12, 2),
1058*0Sstevel@tonic-gate 			"Frame Control = %02x (%s)",
1059*0Sstevel@tonic-gate 			f->fc, print_fc(f->fc));
1060*0Sstevel@tonic-gate 		(void) sprintf(get_line(12, 2),
1061*0Sstevel@tonic-gate 			"Dest   Service Access Point = %02x",
1062*0Sstevel@tonic-gate 			f->dsap);
1063*0Sstevel@tonic-gate 		(void) sprintf(get_line(12, 2),
1064*0Sstevel@tonic-gate 			"Source Service Access Point = %02x",
1065*0Sstevel@tonic-gate 			f->ssap);
1066*0Sstevel@tonic-gate 		(void) sprintf(get_line(12, 2),
1067*0Sstevel@tonic-gate 			"Control = %02x",
1068*0Sstevel@tonic-gate 			f->ctl);
1069*0Sstevel@tonic-gate 		if (is_snap)
1070*0Sstevel@tonic-gate 			(void) sprintf(get_line(12, 2),
1071*0Sstevel@tonic-gate 				"Protocol Id = %02x%02x%02x",
1072*0Sstevel@tonic-gate 				f->proto_id[0], f->proto_id[1], f->proto_id[2]);
1073*0Sstevel@tonic-gate 	} else if (is_smt) {
1074*0Sstevel@tonic-gate 		(void) sprintf(get_line(12, 2),
1075*0Sstevel@tonic-gate 			"Frame Control = %02x (%s)",
1076*0Sstevel@tonic-gate 			f->fc, print_fc(f->fc));
1077*0Sstevel@tonic-gate 		(void) sprintf(get_line(12, 2),
1078*0Sstevel@tonic-gate 			"Class = %02x (%s)",
1079*0Sstevel@tonic-gate 			(uchar_t)*data, print_smtclass(*data));
1080*0Sstevel@tonic-gate 		(void) sprintf(get_line(12, 2),
1081*0Sstevel@tonic-gate 			"Type = %02x (%s)",
1082*0Sstevel@tonic-gate 			*(uchar_t *)(data+1), print_smttype(*(data+1)));
1083*0Sstevel@tonic-gate 	} else {
1084*0Sstevel@tonic-gate 		(void) sprintf(get_line(12, 2),
1085*0Sstevel@tonic-gate 			"FC=%02X (%s), size = %d bytes",
1086*0Sstevel@tonic-gate 			f->fc, print_fc(f->fc), origlen);
1087*0Sstevel@tonic-gate 	}
1088*0Sstevel@tonic-gate 
1089*0Sstevel@tonic-gate 	if (is_snap)
1090*0Sstevel@tonic-gate 		(void) sprintf(get_line(12, 2),
1091*0Sstevel@tonic-gate 		"LLC Type = %04X (%s)",
1092*0Sstevel@tonic-gate 		ethertype, print_ethertype(ethertype));
1093*0Sstevel@tonic-gate 
1094*0Sstevel@tonic-gate 	show_space();
1095*0Sstevel@tonic-gate 	}
1096*0Sstevel@tonic-gate 
1097*0Sstevel@tonic-gate 	/* go to the next protocol layer */
1098*0Sstevel@tonic-gate 	if (is_llc && is_snap && f->ctl == 0x03 && data_copied) {
1099*0Sstevel@tonic-gate 		switch (ethertype) {
1100*0Sstevel@tonic-gate 		case ETHERTYPE_IP:
1101*0Sstevel@tonic-gate 			(void) interpret_ip(flags, (struct ip *)data, len);
1102*0Sstevel@tonic-gate 			break;
1103*0Sstevel@tonic-gate 		/* Just in case it is decided to add this type */
1104*0Sstevel@tonic-gate 		case ETHERTYPE_IPV6:
1105*0Sstevel@tonic-gate 			(void) interpret_ipv6(flags, (ip6_t *)data, len);
1106*0Sstevel@tonic-gate 			break;
1107*0Sstevel@tonic-gate 		case ETHERTYPE_ARP:
1108*0Sstevel@tonic-gate 		case ETHERTYPE_REVARP:
1109*0Sstevel@tonic-gate 			interpret_arp(flags, (struct arphdr *)data, len);
1110*0Sstevel@tonic-gate 			break;
1111*0Sstevel@tonic-gate 		default:
1112*0Sstevel@tonic-gate 			break;
1113*0Sstevel@tonic-gate 		}
1114*0Sstevel@tonic-gate 
1115*0Sstevel@tonic-gate 	}
1116*0Sstevel@tonic-gate 
1117*0Sstevel@tonic-gate 	return (elen);
1118*0Sstevel@tonic-gate }
1119*0Sstevel@tonic-gate 
1120*0Sstevel@tonic-gate uint_t
1121*0Sstevel@tonic-gate fddi_header_len(e)
1122*0Sstevel@tonic-gate char	*e;
1123*0Sstevel@tonic-gate {
1124*0Sstevel@tonic-gate 	struct fddi_header fhdr, *f = &fhdr;
1125*0Sstevel@tonic-gate 
1126*0Sstevel@tonic-gate 	(void) memcpy(&f->fc, e, sizeof (f->fc));
1127*0Sstevel@tonic-gate 	(void) memcpy(&f->dhost, e+1, sizeof (struct ether_addr));
1128*0Sstevel@tonic-gate 	(void) memcpy(&f->shost, e+7, sizeof (struct ether_addr));
1129*0Sstevel@tonic-gate 
1130*0Sstevel@tonic-gate 	if ((f->fc&0x50) == 0x50) {
1131*0Sstevel@tonic-gate 		(void) memcpy(&f->dsap, e+13, sizeof (f->dsap));
1132*0Sstevel@tonic-gate 		(void) memcpy(&f->ssap, e+14, sizeof (f->ssap));
1133*0Sstevel@tonic-gate 		(void) memcpy(&f->ctl, e+15, sizeof (f->ctl));
1134*0Sstevel@tonic-gate 		if (f->dsap == 0xaa && f->ssap == 0xaa) {
1135*0Sstevel@tonic-gate 			return (21);
1136*0Sstevel@tonic-gate 		}
1137*0Sstevel@tonic-gate 		return (16);
1138*0Sstevel@tonic-gate 	} else {
1139*0Sstevel@tonic-gate 		if ((f->fc&0x41) == 0x41 || (f->fc&0x4f) == 0x4f) {
1140*0Sstevel@tonic-gate 			return (13);
1141*0Sstevel@tonic-gate 		}
1142*0Sstevel@tonic-gate 	}
1143*0Sstevel@tonic-gate }
1144*0Sstevel@tonic-gate 
1145*0Sstevel@tonic-gate /*
1146*0Sstevel@tonic-gate  * Print the given Ethernet address
1147*0Sstevel@tonic-gate  */
1148*0Sstevel@tonic-gate char *
1149*0Sstevel@tonic-gate printether(p)
1150*0Sstevel@tonic-gate 	struct ether_addr *p;
1151*0Sstevel@tonic-gate {
1152*0Sstevel@tonic-gate 	static char buf[256];
1153*0Sstevel@tonic-gate 
1154*0Sstevel@tonic-gate 	sprintf(buf, "%x:%x:%x:%x:%x:%x",
1155*0Sstevel@tonic-gate 		p->ether_addr_octet[0],
1156*0Sstevel@tonic-gate 		p->ether_addr_octet[1],
1157*0Sstevel@tonic-gate 		p->ether_addr_octet[2],
1158*0Sstevel@tonic-gate 		p->ether_addr_octet[3],
1159*0Sstevel@tonic-gate 		p->ether_addr_octet[4],
1160*0Sstevel@tonic-gate 		p->ether_addr_octet[5]);
1161*0Sstevel@tonic-gate 
1162*0Sstevel@tonic-gate 	return (buf);
1163*0Sstevel@tonic-gate }
1164*0Sstevel@tonic-gate 
1165*0Sstevel@tonic-gate /*
1166*0Sstevel@tonic-gate  * Table of Ethernet Address Assignments
1167*0Sstevel@tonic-gate  * Some of the more popular entries
1168*0Sstevel@tonic-gate  * are at the beginning of the table
1169*0Sstevel@tonic-gate  * to reduce search time.  Note that the
1170*0Sstevel@tonic-gate  * e-block's are stored in host byte-order.
1171*0Sstevel@tonic-gate  */
1172*0Sstevel@tonic-gate struct block_type {
1173*0Sstevel@tonic-gate 	int	e_block;
1174*0Sstevel@tonic-gate 	char	*e_name;
1175*0Sstevel@tonic-gate } ether_block [] = {
1176*0Sstevel@tonic-gate 0x080020,	"Sun",
1177*0Sstevel@tonic-gate 0x0000C6,	"HP",
1178*0Sstevel@tonic-gate 0x08002B,	"DEC",
1179*0Sstevel@tonic-gate 0x00000F,	"NeXT",
1180*0Sstevel@tonic-gate 0x00000C,	"Cisco",
1181*0Sstevel@tonic-gate 0x080069,	"Silicon Graphics",
1182*0Sstevel@tonic-gate 0x000069,	"Silicon Graphics",
1183*0Sstevel@tonic-gate 0x0000A7,	"Network Computing Devices (NCD	X-terminal)",
1184*0Sstevel@tonic-gate 0x08005A,	"IBM",
1185*0Sstevel@tonic-gate 0x0000AC,	"Apollo",
1186*0Sstevel@tonic-gate /* end of popular entries */
1187*0Sstevel@tonic-gate 0x000002,	"BBN",
1188*0Sstevel@tonic-gate 0x000010,	"Sytek",
1189*0Sstevel@tonic-gate 0x000011,	"Tektronix",
1190*0Sstevel@tonic-gate 0x000018,	"Webster (?)",
1191*0Sstevel@tonic-gate 0x00001B,	"Novell",
1192*0Sstevel@tonic-gate 0x00001D,	"Cabletron",
1193*0Sstevel@tonic-gate 0x000020,	"DIAB (Data Industrier AB)",
1194*0Sstevel@tonic-gate 0x000021,	"SC&C",
1195*0Sstevel@tonic-gate 0x000022,	"Visual Technology",
1196*0Sstevel@tonic-gate 0x000029,	"IMC",
1197*0Sstevel@tonic-gate 0x00002A,	"TRW",
1198*0Sstevel@tonic-gate 0x00003D,	"AT&T",
1199*0Sstevel@tonic-gate 0x000049,	"Apricot Ltd.",
1200*0Sstevel@tonic-gate 0x000055,	"AT&T",
1201*0Sstevel@tonic-gate 0x00005A,	"S & Koch",
1202*0Sstevel@tonic-gate 0x00005A,	"Xerox 806 (unregistered)",
1203*0Sstevel@tonic-gate 0x00005E,	"U.S. Department of Defense (IANA)",
1204*0Sstevel@tonic-gate 0x000065,	"Network General",
1205*0Sstevel@tonic-gate 0x00006B,	"MIPS",
1206*0Sstevel@tonic-gate 0x000077,	"MIPS",
1207*0Sstevel@tonic-gate 0x000079,	"NetWare (?)",
1208*0Sstevel@tonic-gate 0x00007A,	"Ardent",
1209*0Sstevel@tonic-gate 0x00007B,	"Research Machines",
1210*0Sstevel@tonic-gate 0x00007D,	"Harris (3M) (old)",
1211*0Sstevel@tonic-gate 0x000080,	"Imagen(?)",
1212*0Sstevel@tonic-gate 0x000081,	"Synoptics",
1213*0Sstevel@tonic-gate 0x000084,	"Aquila (?)",
1214*0Sstevel@tonic-gate 0x000086,	"Gateway (?)",
1215*0Sstevel@tonic-gate 0x000089,	"Cayman Systems	Gatorbox",
1216*0Sstevel@tonic-gate 0x000093,	"Proteon",
1217*0Sstevel@tonic-gate 0x000094,	"Asante",
1218*0Sstevel@tonic-gate 0x000098,	"Cross Com",
1219*0Sstevel@tonic-gate 0x00009F,	"Ameristar Technology",
1220*0Sstevel@tonic-gate 0x0000A2,	"Wellfleet",
1221*0Sstevel@tonic-gate 0x0000A3,	"Network Application Technology",
1222*0Sstevel@tonic-gate 0x0000A4,	"Acorn",
1223*0Sstevel@tonic-gate 0x0000A6,	"Network General",
1224*0Sstevel@tonic-gate 0x0000A7,	"Network Computing Devices (NCD	X-terminal)",
1225*0Sstevel@tonic-gate 0x0000A9,	"Network Systems",
1226*0Sstevel@tonic-gate 0x0000AA,	"Xerox",
1227*0Sstevel@tonic-gate 0x0000B3,	"CIMLinc",
1228*0Sstevel@tonic-gate 0x0000B5,	"Datability Terminal Server",
1229*0Sstevel@tonic-gate 0x0000B7,	"Dove Fastnet",
1230*0Sstevel@tonic-gate 0x0000BC,	"Allen-Bradley",
1231*0Sstevel@tonic-gate 0x0000C0,	"Western Digital",
1232*0Sstevel@tonic-gate 0x0000C8,	"Altos",
1233*0Sstevel@tonic-gate 0x0000C9,	"Emulex Terminal Server",
1234*0Sstevel@tonic-gate 0x0000D0,	"Develcon Electronics, Ltd.",
1235*0Sstevel@tonic-gate 0x0000D1,	"Adaptec Inc. Nodem product",
1236*0Sstevel@tonic-gate 0x0000D7,	"Dartmouth College (NED Router)",
1237*0Sstevel@tonic-gate 0x0000DD,	"Gould",
1238*0Sstevel@tonic-gate 0x0000DE,	"Unigraph",
1239*0Sstevel@tonic-gate 0x0000E2,	"Acer Counterpoint",
1240*0Sstevel@tonic-gate 0x0000E8,	"Accton Technology Corporation",
1241*0Sstevel@tonic-gate 0x0000EE,	"Network Designers Limited(?)",
1242*0Sstevel@tonic-gate 0x0000EF,	"Alantec",
1243*0Sstevel@tonic-gate 0x0000F3,	"Gandalf",
1244*0Sstevel@tonic-gate 0x0000FD,	"High Level Hardware (Orion, UK)",
1245*0Sstevel@tonic-gate 0x000143,	"IEEE 802",
1246*0Sstevel@tonic-gate 0x001700,	"Kabel",
1247*0Sstevel@tonic-gate 0x004010,	"Sonic",
1248*0Sstevel@tonic-gate 0x00608C,	"3Com",
1249*0Sstevel@tonic-gate 0x00800F,	"SMC",
1250*0Sstevel@tonic-gate 0x008019,	"Dayna Communications Etherprint product",
1251*0Sstevel@tonic-gate 0x00802D,	"Xylogics, Inc.	Annex terminal servers",
1252*0Sstevel@tonic-gate 0x008035,	"Technology Works",
1253*0Sstevel@tonic-gate 0x008087,	"Okidata",
1254*0Sstevel@tonic-gate 0x00808C,	"Frontier Software Development",
1255*0Sstevel@tonic-gate 0x0080C7,	"Xircom Inc.",
1256*0Sstevel@tonic-gate 0x0080D0,	"Computer Products International",
1257*0Sstevel@tonic-gate 0x0080D3,	"Shiva Appletalk-Ethernet interface",
1258*0Sstevel@tonic-gate 0x0080D4,	"Chase Limited",
1259*0Sstevel@tonic-gate 0x0080F1,	"Opus",
1260*0Sstevel@tonic-gate 0x00AA00,	"Intel",
1261*0Sstevel@tonic-gate 0x00B0D0,	"Computer Products International",
1262*0Sstevel@tonic-gate 0x00DD00,	"Ungermann-Bass",
1263*0Sstevel@tonic-gate 0x00DD01,	"Ungermann-Bass",
1264*0Sstevel@tonic-gate 0x00EFE5,	"IBM (3Com card)",
1265*0Sstevel@tonic-gate 0x020406,	"BBN",
1266*0Sstevel@tonic-gate 0x026060,	"3Com",
1267*0Sstevel@tonic-gate 0x026086,	"Satelcom MegaPac (UK)",
1268*0Sstevel@tonic-gate 0x02E6D3,	"Bus-Tech, Inc. (BTI)",
1269*0Sstevel@tonic-gate 0x080001,	"Computer Vision",
1270*0Sstevel@tonic-gate 0x080002,	"3Com (Formerly Bridge)",
1271*0Sstevel@tonic-gate 0x080003,	"ACC (Advanced Computer Communications)",
1272*0Sstevel@tonic-gate 0x080005,	"Symbolics",
1273*0Sstevel@tonic-gate 0x080007,	"Apple",
1274*0Sstevel@tonic-gate 0x080008,	"BBN",
1275*0Sstevel@tonic-gate 0x080009,	"Hewlett-Packard",
1276*0Sstevel@tonic-gate 0x08000A,	"Nestar Systems",
1277*0Sstevel@tonic-gate 0x08000B,	"Unisys",
1278*0Sstevel@tonic-gate 0x08000D,	"ICL",
1279*0Sstevel@tonic-gate 0x08000E,	"NCR",
1280*0Sstevel@tonic-gate 0x080010,	"AT&T",
1281*0Sstevel@tonic-gate 0x080011,	"Tektronix, Inc.",
1282*0Sstevel@tonic-gate 0x080017,	"NSC",
1283*0Sstevel@tonic-gate 0x08001A,	"Data General",
1284*0Sstevel@tonic-gate 0x08001B,	"Data General",
1285*0Sstevel@tonic-gate 0x08001E,	"Apollo",
1286*0Sstevel@tonic-gate 0x080022,	"NBI",
1287*0Sstevel@tonic-gate 0x080025,	"CDC",
1288*0Sstevel@tonic-gate 0x080026,	"Norsk Data (Nord)",
1289*0Sstevel@tonic-gate 0x080027,	"PCS Computer Systems GmbH",
1290*0Sstevel@tonic-gate 0x080028,	"TI Explorer",
1291*0Sstevel@tonic-gate 0x08002E,	"Metaphor",
1292*0Sstevel@tonic-gate 0x08002F,	"Prime Computer",
1293*0Sstevel@tonic-gate 0x080036,	"Intergraph CAE stations",
1294*0Sstevel@tonic-gate 0x080037,	"Fujitsu-Xerox",
1295*0Sstevel@tonic-gate 0x080038,	"Bull",
1296*0Sstevel@tonic-gate 0x080039,	"Spider Systems",
1297*0Sstevel@tonic-gate 0x08003B,	"Torus Systems",
1298*0Sstevel@tonic-gate 0x08003E,	"Motorola VME bus processor module",
1299*0Sstevel@tonic-gate 0x080041,	"DCA Digital Comm. Assoc.",
1300*0Sstevel@tonic-gate 0x080046,	"Sony",
1301*0Sstevel@tonic-gate 0x080047,	"Sequent",
1302*0Sstevel@tonic-gate 0x080049,	"Univation",
1303*0Sstevel@tonic-gate 0x08004C,	"Encore",
1304*0Sstevel@tonic-gate 0x08004E,	"BICC",
1305*0Sstevel@tonic-gate 0x080056,	"Stanford University",
1306*0Sstevel@tonic-gate 0x080057,	"Evans & Sutherland (?)",
1307*0Sstevel@tonic-gate 0x080067,	"Comdesign",
1308*0Sstevel@tonic-gate 0x080068,	"Ridge",
1309*0Sstevel@tonic-gate 0x08006A,	"ATTst (?)",
1310*0Sstevel@tonic-gate 0x08006E,	"Excelan",
1311*0Sstevel@tonic-gate 0x080075,	"DDE (Danish Data Elektronik A/S)",
1312*0Sstevel@tonic-gate 0x080077,	"TSL (now Retix)",
1313*0Sstevel@tonic-gate 0x08007C,	"Vitalink TransLAN III",
1314*0Sstevel@tonic-gate 0x080080,	"XIOS",
1315*0Sstevel@tonic-gate 0x080081,	"Crosfield Electronics",
1316*0Sstevel@tonic-gate 0x080086,	"Imagen/QMS",
1317*0Sstevel@tonic-gate 0x080087,	"Xyplex	terminal server",
1318*0Sstevel@tonic-gate 0x080089,	"Kinetics AppleTalk-Ethernet interface",
1319*0Sstevel@tonic-gate 0x08008B,	"Pyramid",
1320*0Sstevel@tonic-gate 0x08008D,	"XyVision",
1321*0Sstevel@tonic-gate 0x080090,	"Retix Inc Bridge",
1322*0Sstevel@tonic-gate 0x10005A,	"IBM",
1323*0Sstevel@tonic-gate 0x1000D4,	"DEC",
1324*0Sstevel@tonic-gate 0x400003,	"NetWare",
1325*0Sstevel@tonic-gate 0x800010,	"AT&T",
1326*0Sstevel@tonic-gate 0xAA0004,	"DEC (DECNET)",
1327*0Sstevel@tonic-gate 0xC00000,	"SMC",
1328*0Sstevel@tonic-gate 0,		"",
1329*0Sstevel@tonic-gate };
1330*0Sstevel@tonic-gate 
1331*0Sstevel@tonic-gate /*
1332*0Sstevel@tonic-gate  * The oui argument should be in host byte-order to conform with
1333*0Sstevel@tonic-gate  * the above array's values.
1334*0Sstevel@tonic-gate  */
1335*0Sstevel@tonic-gate char *
1336*0Sstevel@tonic-gate ether_ouiname(uint32_t oui)
1337*0Sstevel@tonic-gate {
1338*0Sstevel@tonic-gate 	uint_t i;
1339*0Sstevel@tonic-gate 
1340*0Sstevel@tonic-gate 	for (i = 0; ether_block[i].e_block != 0; i++)
1341*0Sstevel@tonic-gate 		if (oui == ether_block[i].e_block)
1342*0Sstevel@tonic-gate 			return (ether_block[i].e_name);
1343*0Sstevel@tonic-gate 
1344*0Sstevel@tonic-gate 	return (NULL);
1345*0Sstevel@tonic-gate }
1346*0Sstevel@tonic-gate 
1347*0Sstevel@tonic-gate /*
1348*0Sstevel@tonic-gate  * Print the additional Ethernet address info
1349*0Sstevel@tonic-gate  */
1350*0Sstevel@tonic-gate static char *
1351*0Sstevel@tonic-gate print_etherinfo(eaddr)
1352*0Sstevel@tonic-gate 	struct ether_addr *eaddr;
1353*0Sstevel@tonic-gate {
1354*0Sstevel@tonic-gate 	uint_t addr = 0;
1355*0Sstevel@tonic-gate 	char *p = (char *)&addr + 1;
1356*0Sstevel@tonic-gate 	char *ename;
1357*0Sstevel@tonic-gate 
1358*0Sstevel@tonic-gate 	(void) memcpy(p, eaddr, 3);
1359*0Sstevel@tonic-gate 
1360*0Sstevel@tonic-gate 	if (memcmp(eaddr, &ether_broadcast, sizeof (struct ether_addr)) == 0)
1361*0Sstevel@tonic-gate 		return ("(broadcast)");
1362*0Sstevel@tonic-gate 
1363*0Sstevel@tonic-gate 	if (eaddr->ether_addr_octet[0] & 1)
1364*0Sstevel@tonic-gate 		return ("(multicast)");
1365*0Sstevel@tonic-gate 
1366*0Sstevel@tonic-gate 	addr = ntohl(addr);	/* make it right for little-endians */
1367*0Sstevel@tonic-gate 	ename = ether_ouiname(addr);
1368*0Sstevel@tonic-gate 
1369*0Sstevel@tonic-gate 	if (ename != NULL)
1370*0Sstevel@tonic-gate 		return (ename);
1371*0Sstevel@tonic-gate 	else
1372*0Sstevel@tonic-gate 		return ("");
1373*0Sstevel@tonic-gate }
1374*0Sstevel@tonic-gate 
1375*0Sstevel@tonic-gate static uchar_t	endianswap[] = {
1376*0Sstevel@tonic-gate 	0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
1377*0Sstevel@tonic-gate 	0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
1378*0Sstevel@tonic-gate 	0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
1379*0Sstevel@tonic-gate 	0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
1380*0Sstevel@tonic-gate 	0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
1381*0Sstevel@tonic-gate 	0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
1382*0Sstevel@tonic-gate 	0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
1383*0Sstevel@tonic-gate 	0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
1384*0Sstevel@tonic-gate 	0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
1385*0Sstevel@tonic-gate 	0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
1386*0Sstevel@tonic-gate 	0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
1387*0Sstevel@tonic-gate 	0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
1388*0Sstevel@tonic-gate 	0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
1389*0Sstevel@tonic-gate 	0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
1390*0Sstevel@tonic-gate 	0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
1391*0Sstevel@tonic-gate 	0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
1392*0Sstevel@tonic-gate 	0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
1393*0Sstevel@tonic-gate 	0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
1394*0Sstevel@tonic-gate 	0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
1395*0Sstevel@tonic-gate 	0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
1396*0Sstevel@tonic-gate 	0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
1397*0Sstevel@tonic-gate 	0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
1398*0Sstevel@tonic-gate 	0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
1399*0Sstevel@tonic-gate 	0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
1400*0Sstevel@tonic-gate 	0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
1401*0Sstevel@tonic-gate 	0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
1402*0Sstevel@tonic-gate 	0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
1403*0Sstevel@tonic-gate 	0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
1404*0Sstevel@tonic-gate 	0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
1405*0Sstevel@tonic-gate 	0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
1406*0Sstevel@tonic-gate 	0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
1407*0Sstevel@tonic-gate 	0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
1408*0Sstevel@tonic-gate };
1409*0Sstevel@tonic-gate 
1410*0Sstevel@tonic-gate static void
1411*0Sstevel@tonic-gate addr_copy_swap(pd, ps)
1412*0Sstevel@tonic-gate 	struct ether_addr	*pd;
1413*0Sstevel@tonic-gate 	struct ether_addr	*ps;
1414*0Sstevel@tonic-gate {
1415*0Sstevel@tonic-gate 	pd->ether_addr_octet[0] = endianswap[ps->ether_addr_octet[0]];
1416*0Sstevel@tonic-gate 	pd->ether_addr_octet[1] = endianswap[ps->ether_addr_octet[1]];
1417*0Sstevel@tonic-gate 	pd->ether_addr_octet[2] = endianswap[ps->ether_addr_octet[2]];
1418*0Sstevel@tonic-gate 	pd->ether_addr_octet[3] = endianswap[ps->ether_addr_octet[3]];
1419*0Sstevel@tonic-gate 	pd->ether_addr_octet[4] = endianswap[ps->ether_addr_octet[4]];
1420*0Sstevel@tonic-gate 	pd->ether_addr_octet[5] = endianswap[ps->ether_addr_octet[5]];
1421*0Sstevel@tonic-gate }
1422*0Sstevel@tonic-gate 
1423*0Sstevel@tonic-gate /* ARGSUSED */
1424*0Sstevel@tonic-gate uint_t
1425*0Sstevel@tonic-gate ib_header_len(char *hdr)
1426*0Sstevel@tonic-gate {
1427*0Sstevel@tonic-gate 	return (IPOIB_HDRSIZE);
1428*0Sstevel@tonic-gate }
1429*0Sstevel@tonic-gate 
1430*0Sstevel@tonic-gate static uint_t
1431*0Sstevel@tonic-gate interpret_ib(int flags, char *header, int elen, int origlen)
1432*0Sstevel@tonic-gate {
1433*0Sstevel@tonic-gate 	struct ipoib_header *hdr = (struct ipoib_header *)header;
1434*0Sstevel@tonic-gate 	char *off;
1435*0Sstevel@tonic-gate 	int len;
1436*0Sstevel@tonic-gate 	extern char *dst_name;
1437*0Sstevel@tonic-gate 	unsigned short ethertype;
1438*0Sstevel@tonic-gate 	int blen = MAX(origlen, 4096);
1439*0Sstevel@tonic-gate 
1440*0Sstevel@tonic-gate 	if (data != NULL && datalen != 0 && datalen < blen) {
1441*0Sstevel@tonic-gate 		free(data);
1442*0Sstevel@tonic-gate 		data = NULL;
1443*0Sstevel@tonic-gate 		datalen = 0;
1444*0Sstevel@tonic-gate 	}
1445*0Sstevel@tonic-gate 	if (data == NULL) {
1446*0Sstevel@tonic-gate 		data = malloc(blen);
1447*0Sstevel@tonic-gate 		if (data == NULL)
1448*0Sstevel@tonic-gate 			pr_err("Warning: malloc failure");
1449*0Sstevel@tonic-gate 		datalen = blen;
1450*0Sstevel@tonic-gate 	}
1451*0Sstevel@tonic-gate 	if (origlen < IPOIB_HDRSIZE) {
1452*0Sstevel@tonic-gate 		if (flags & F_SUM)
1453*0Sstevel@tonic-gate 			(void) snprintf(get_sum_line(), MAXLINE,
1454*0Sstevel@tonic-gate 				"RUNT (short packet - %d bytes)", origlen);
1455*0Sstevel@tonic-gate 		if (flags & F_DTAIL)
1456*0Sstevel@tonic-gate 			show_header("RUNT:  ", "Short packet", origlen);
1457*0Sstevel@tonic-gate 		return (elen);
1458*0Sstevel@tonic-gate 	}
1459*0Sstevel@tonic-gate 	if (elen < IPOIB_HDRSIZE)
1460*0Sstevel@tonic-gate 		return (elen);
1461*0Sstevel@tonic-gate 
1462*0Sstevel@tonic-gate 	/*
1463*0Sstevel@tonic-gate 	 * It is not possible to understand just by looking
1464*0Sstevel@tonic-gate 	 * at the header whether this was a broad/multi cast
1465*0Sstevel@tonic-gate 	 * packet; thus dst_name is not updated.
1466*0Sstevel@tonic-gate 	 */
1467*0Sstevel@tonic-gate 	ethertype = ntohs(hdr->ipoib_type);
1468*0Sstevel@tonic-gate 	len = elen - IPOIB_HDRSIZE;
1469*0Sstevel@tonic-gate 	off = (char *)(hdr + 1);
1470*0Sstevel@tonic-gate 	(void) memcpy(data, off, len);
1471*0Sstevel@tonic-gate 
1472*0Sstevel@tonic-gate 	if (flags & F_SUM) {
1473*0Sstevel@tonic-gate 		(void) snprintf(get_sum_line(), MAXLINE,
1474*0Sstevel@tonic-gate 			"IPIB Type=%04X (%s), size = %d bytes",
1475*0Sstevel@tonic-gate 			ethertype,
1476*0Sstevel@tonic-gate 			print_ethertype(ethertype),
1477*0Sstevel@tonic-gate 			origlen);
1478*0Sstevel@tonic-gate 	}
1479*0Sstevel@tonic-gate 
1480*0Sstevel@tonic-gate 	if (flags & F_DTAIL) {
1481*0Sstevel@tonic-gate 		show_header("IPIB:  ", "IPIB Header", elen);
1482*0Sstevel@tonic-gate 		show_space();
1483*0Sstevel@tonic-gate 		(void) snprintf(get_line(0, 0), get_line_remain(),
1484*0Sstevel@tonic-gate 			"Packet %d arrived at %d:%02d:%d.%02d",
1485*0Sstevel@tonic-gate 			pi_frame, pi_time_hour, pi_time_min,
1486*0Sstevel@tonic-gate 			pi_time_sec, pi_time_usec / 10000);
1487*0Sstevel@tonic-gate 		(void) snprintf(get_line(0, 0), get_line_remain(),
1488*0Sstevel@tonic-gate 			"Packet size = %d bytes", elen, elen);
1489*0Sstevel@tonic-gate 		(void) snprintf(get_line(0, 2), get_line_remain(),
1490*0Sstevel@tonic-gate 			"Ethertype = %04X (%s)", ethertype,
1491*0Sstevel@tonic-gate 			print_ethertype(ethertype));
1492*0Sstevel@tonic-gate 		show_space();
1493*0Sstevel@tonic-gate 	}
1494*0Sstevel@tonic-gate 
1495*0Sstevel@tonic-gate 	/* Go to the next protocol layer */
1496*0Sstevel@tonic-gate 	switch (ethertype) {
1497*0Sstevel@tonic-gate 		case ETHERTYPE_IP:
1498*0Sstevel@tonic-gate 			(void) interpret_ip(flags, (struct ip *)data, len);
1499*0Sstevel@tonic-gate 			break;
1500*0Sstevel@tonic-gate 		case ETHERTYPE_IPV6:
1501*0Sstevel@tonic-gate 			(void) interpret_ipv6(flags, (ip6_t *)data, len);
1502*0Sstevel@tonic-gate 			break;
1503*0Sstevel@tonic-gate 		case ETHERTYPE_ARP:
1504*0Sstevel@tonic-gate 		case ETHERTYPE_REVARP:
1505*0Sstevel@tonic-gate 			interpret_arp(flags, (struct arphdr *)data, len);
1506*0Sstevel@tonic-gate 			break;
1507*0Sstevel@tonic-gate 	}
1508*0Sstevel@tonic-gate 
1509*0Sstevel@tonic-gate 	return (elen);
1510*0Sstevel@tonic-gate }
1511