1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include <stddef.h>
30#include <fcntl.h>
31#include <string.h>
32#include <sys/types.h>
33#include <sys/time.h>
34#include <sys/sysmacros.h>
35#include <sys/socket.h>
36#include <net/if.h>
37#include <netinet/in_systm.h>
38#include <netinet/in.h>
39#include <netinet/ip.h>
40#include <netinet/if_ether.h>
41#include <sys/ib/clients/ibd/ibd.h>
42#include <sys/ethernet.h>
43#include <sys/vlan.h>
44#include <sys/zone.h>
45#include <inet/iptun.h>
46#include <sys/byteorder.h>
47#include <limits.h>
48#include <inet/ip.h>
49#include <inet/ip6.h>
50#include <net/trill.h>
51
52#include "at.h"
53#include "snoop.h"
54
55static headerlen_fn_t ether_header_len, fddi_header_len, tr_header_len,
56    ib_header_len, ipnet_header_len, ipv4_header_len, ipv6_header_len;
57static interpreter_fn_t interpret_ether, interpret_fddi, interpret_tr,
58    interpret_ib, interpret_ipnet, interpret_iptun;
59static void addr_copy_swap(struct ether_addr *, struct ether_addr *);
60static int tr_machdr_len(char *, int *, int *);
61
62interface_t *interface;
63interface_t INTERFACES[] = {
64
65	/* IEEE 802.3 CSMA/CD network */
66	{ DL_CSMACD, 1550, 12, 2, ETHERTYPE_IP, ETHERTYPE_IPV6,
67	    ether_header_len, interpret_ether, B_TRUE },
68
69	/* Ethernet Bus */
70	{ DL_ETHER, 1550, 12, 2, ETHERTYPE_IP, ETHERTYPE_IPV6,
71	    ether_header_len, interpret_ether, B_TRUE },
72
73	/* Fiber Distributed data interface */
74	{ DL_FDDI, 4500, 19, 2, ETHERTYPE_IP, ETHERTYPE_IPV6,
75	    fddi_header_len, interpret_fddi, B_FALSE },
76
77	/* Token Ring interface */
78	{ DL_TPR, 17800, 0, 2, ETHERTYPE_IP, ETHERTYPE_IPV6,
79	    tr_header_len, interpret_tr, B_FALSE },
80
81	/* Infiniband */
82	{ DL_IB, 4096, 0, 2, ETHERTYPE_IP, ETHERTYPE_IPV6,
83	    ib_header_len, interpret_ib, B_TRUE },
84
85	/* ipnet */
86	{ DL_IPNET, INT_MAX, 1, 1, IPV4_VERSION, IPV6_VERSION,
87	    ipnet_header_len, interpret_ipnet, B_TRUE },
88
89	/* IPv4 tunnel */
90	{ DL_IPV4, 0, 9, 1, IPPROTO_ENCAP, IPPROTO_IPV6,
91	    ipv4_header_len, interpret_iptun, B_FALSE },
92
93	/* IPv6 tunnel */
94	{ DL_IPV6, 0, 40, 1, IPPROTO_ENCAP, IPPROTO_IPV6,
95	    ipv6_header_len, interpret_iptun, B_FALSE },
96
97	/* 6to4 tunnel */
98	{ DL_6TO4, 0, 9, 1, IPPROTO_ENCAP, IPPROTO_IPV6,
99	    ipv4_header_len, interpret_iptun, B_FALSE },
100
101	{ (uint_t)-1, 0, 0, 0, 0, 0, NULL, B_FALSE }
102};
103
104/* externals */
105extern char *dlc_header;
106extern int pi_frame;
107extern int pi_time_hour;
108extern int pi_time_min;
109extern int pi_time_sec;
110extern int pi_time_usec;
111
112char *printether();
113char *print_ethertype();
114static char *print_etherinfo();
115
116char *print_fc();
117char *print_smttype();
118char *print_smtclass();
119
120struct ether_addr ether_broadcast = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
121static char *data;			/* current data buffer */
122static int datalen;			/* current data buffer length */
123static const struct ether_addr all_isis_rbridges = ALL_ISIS_RBRIDGES;
124
125uint_t
126interpret_ether(int flags, char *header, int elen, int origlen)
127{
128	struct ether_header *e = (struct ether_header *)header;
129	uchar_t *off, *ieeestart;
130	int len;
131	int ieee8023 = 0;
132	extern char *dst_name;
133	int ethertype;
134	struct ether_vlan_extinfo *evx = NULL;
135	int blen = MAX(origlen, ETHERMTU);
136	boolean_t trillpkt = B_FALSE;
137	uint16_t tci = 0;
138
139	if (data != NULL && datalen != 0 && datalen < blen) {
140		free(data);
141		data = NULL;
142		datalen = 0;
143	}
144	if (!data) {
145		data = (char *)malloc(blen);
146		if (!data)
147			pr_err("Warning: malloc failure");
148		datalen = blen;
149	}
150inner_pkt:
151	if (origlen < 14) {
152		if (flags & F_SUM) {
153			(void) sprintf(get_sum_line(),
154			    "RUNT (short packet - %d bytes)",
155			    origlen);
156		}
157		if (flags & F_DTAIL)
158			show_header("RUNT:  ", "Short packet", origlen);
159		return (elen);
160	}
161	if (elen < 14)
162		return (elen);
163
164	if (memcmp(&e->ether_dhost, &ether_broadcast,
165	    sizeof (struct ether_addr)) == 0)
166		dst_name = "(broadcast)";
167	else if (e->ether_dhost.ether_addr_octet[0] & 1)
168		dst_name = "(multicast)";
169
170	ethertype = ntohs(e->ether_type);
171
172	/*
173	 * The 14 byte ether header screws up alignment
174	 * of the rest of the packet for 32 bit aligned
175	 * architectures like SPARC. Alas, we have to copy
176	 * the rest of the packet in order to align it.
177	 */
178	len = elen - sizeof (struct ether_header);
179	off = (uchar_t *)(e + 1);
180
181	if (ethertype == ETHERTYPE_VLAN) {
182		if (origlen < sizeof (struct ether_vlan_header)) {
183			if (flags & F_SUM) {
184				(void) sprintf(get_sum_line(),
185				    "RUNT (short VLAN packet - %d bytes)",
186				    origlen);
187			}
188			if (flags & F_DTAIL) {
189				show_header("RUNT:  ", "Short VLAN packet",
190				    origlen);
191			}
192			return (elen);
193		}
194		if (len < sizeof (struct ether_vlan_extinfo))
195			return (elen);
196
197		evx = (struct ether_vlan_extinfo *)off;
198		off += sizeof (struct ether_vlan_extinfo);
199		len -= sizeof (struct ether_vlan_extinfo);
200
201		ethertype = ntohs(evx->ether_type);
202		tci = ntohs(evx->ether_tci);
203	}
204
205	if (ethertype <= 1514) {
206		/*
207		 * Fake out the IEEE 802.3 packets.
208		 * Should be DSAP=0xAA, SSAP=0xAA, control=0x03
209		 * then three padding bytes of zero (OUI),
210		 * followed by a normal ethernet-type packet.
211		 */
212		ieee8023 = ethertype;
213		ieeestart = off;
214		if (off[0] == 0xAA && off[1] == 0xAA) {
215			ethertype = ntohs(*(ushort_t *)(off + 6));
216			off += 8;
217			len -= 8;
218		} else {
219			ethertype = 0;
220			off += 3;
221			len -= 3;
222		}
223	}
224
225	if (flags & F_SUM) {
226		/*
227		 * Set the flag that says don't display VLAN information.
228		 * If it needs to change, that will be done later if the
229		 * packet is VLAN tagged and if snoop is in its default
230		 * summary mode.
231		 */
232		set_vlan_id(0);
233		if (evx == NULL) {
234			if (ethertype == 0 && ieee8023 > 0) {
235				(void) sprintf(get_sum_line(),
236				    "ETHER 802.3 SSAP %02X DSAP %02X, "
237				    "size=%d bytes", ieeestart[0], ieeestart[1],
238				    origlen);
239			} else {
240				(void) sprintf(get_sum_line(),
241				    "ETHER Type=%04X (%s), size=%d bytes",
242				    ethertype, print_ethertype(ethertype),
243				    origlen);
244			}
245		} else {
246			if (ethertype == 0 && ieee8023 > 0) {
247				(void) sprintf(get_sum_line(),
248				    "ETHER 802.3 SSAP %02X DSAP %02X, "
249				    "VLAN ID=%hu, size=%d bytes", ieeestart[0],
250				    ieeestart[1], VLAN_ID(tci), origlen);
251			} else {
252				(void) sprintf(get_sum_line(),
253				    "ETHER Type=%04X (%s), VLAN ID=%hu, "
254				    "size=%d bytes", ethertype,
255				    print_ethertype(ethertype), VLAN_ID(tci),
256				    origlen);
257			}
258
259			if (!(flags & F_ALLSUM))
260				set_vlan_id(VLAN_ID(tci));
261		}
262	}
263
264	if (flags & F_DTAIL) {
265		show_header("ETHER:  ", "Ether Header", elen);
266		show_space();
267		if (!trillpkt) {
268			(void) sprintf(get_line(0, 0),
269			    "Packet %d arrived at %d:%02d:%d.%05d",
270			    pi_frame,
271			    pi_time_hour, pi_time_min, pi_time_sec,
272			    pi_time_usec / 10);
273			(void) sprintf(get_line(0, 0),
274			    "Packet size = %d bytes",
275			    elen, elen);
276		}
277		(void) sprintf(get_line(0, 6),
278		    "Destination = %s, %s",
279		    printether(&e->ether_dhost),
280		    print_etherinfo(&e->ether_dhost));
281		(void) sprintf(get_line(6, 6),
282		    "Source      = %s, %s",
283		    printether(&e->ether_shost),
284		    print_etherinfo(&e->ether_shost));
285		if (evx != NULL) {
286			(void) sprintf(get_line(0, 0),
287			    "VLAN ID     = %hu", VLAN_ID(tci));
288			(void) sprintf(get_line(0, 0),
289			    "VLAN Priority = %hu", VLAN_PRI(tci));
290		}
291		if (ieee8023 > 0) {
292			(void) sprintf(get_line(12, 2),
293			    "IEEE 802.3 length = %d bytes", ieee8023);
294			/* Print LLC only for non-TCP/IP packets */
295			if (ethertype == 0) {
296				(void) snprintf(get_line(0, 0),
297				    get_line_remain(),
298				    "SSAP = %02X, DSAP = %02X, CTRL = %02X",
299				    ieeestart[0], ieeestart[1], ieeestart[2]);
300			}
301		}
302		if (ethertype != 0 || ieee8023 == 0)
303			(void) sprintf(get_line(12, 2),
304			    "Ethertype = %04X (%s)",
305			    ethertype, print_ethertype(ethertype));
306		show_space();
307	}
308
309	/*
310	 * We cannot trust the length field in the header to be correct.
311	 * But we should continue to process the packet.  Then user can
312	 * notice something funny in the header.
313	 * Go to the next protocol layer only if data have been
314	 * copied.
315	 */
316	if (len > 0 && (off + len <= (uchar_t *)e + elen)) {
317		(void) memmove(data, off, len);
318
319		if (!trillpkt && ethertype == ETHERTYPE_TRILL) {
320			ethertype = interpret_trill(flags, &e, data, &len);
321			/* Decode inner Ethernet frame */
322			if (ethertype != 0) {
323				evx = NULL;
324				trillpkt = B_TRUE;
325				(void) memmove(data, e, len);
326				e = (struct ether_header *)data;
327				origlen = len;
328				elen = len;
329				goto inner_pkt;
330			}
331		}
332
333		switch (ethertype) {
334		case ETHERTYPE_IP:
335			(void) interpret_ip(flags, (struct ip *)data, len);
336			break;
337		/* Just in case it is decided to add this type */
338		case ETHERTYPE_IPV6:
339			(void) interpret_ipv6(flags, (ip6_t *)data, len);
340			break;
341		case ETHERTYPE_ARP:
342		case ETHERTYPE_REVARP:
343			interpret_arp(flags, (struct arphdr *)data, len);
344			break;
345		case ETHERTYPE_PPPOED:
346		case ETHERTYPE_PPPOES:
347			(void) interpret_pppoe(flags, (poep_t *)data, len);
348			break;
349		case ETHERTYPE_AARP:    /* AppleTalk */
350			interpret_aarp(flags, data, len);
351			break;
352		case ETHERTYPE_AT:
353			interpret_at(flags, (struct ddp_hdr *)data, len);
354			break;
355		case 0:
356			if (ieee8023 == 0)
357				break;
358			switch (ieeestart[0]) {
359			case 0xFE:
360				interpret_isis(flags, data, len,
361				    memcmp(&e->ether_dhost, &all_isis_rbridges,
362				    sizeof (struct ether_addr)) == 0);
363				break;
364			case 0x42:
365				interpret_bpdu(flags, data, len);
366				break;
367			}
368			break;
369		}
370	}
371
372	return (elen);
373}
374
375/*
376 * Return the length of the ethernet header.  In the case
377 * where we have a VLAN tagged packet, return the length of
378 * the ethernet header plus the length of the VLAN tag.
379 *
380 * INPUTS:  e  -  A buffer pointer.  Passing a NULL pointer
381 *                is not allowed, e must be non-NULL.
382 * OUTPUTS:  Return the size of an untagged ethernet header
383 *           if the packet is not VLAN tagged, and the size
384 *           of an untagged ethernet header plus the size of
385 *           a VLAN header otherwise.
386 */
387uint_t
388ether_header_len(char *e, size_t msgsize)
389{
390	uint16_t ether_type = 0;
391
392	if (msgsize < sizeof (struct ether_header))
393		return (0);
394
395	e += (offsetof(struct ether_header, ether_type));
396
397	GETINT16(ether_type, e);
398
399	if (ether_type == (uint16_t)ETHERTYPE_VLAN) {
400		return (sizeof (struct ether_vlan_header));
401	} else {
402		return (sizeof (struct ether_header));
403	}
404}
405
406
407/*
408 * Table of Ethertypes.
409 * Some of the more popular entries
410 * are at the beginning of the table
411 * to reduce search time.
412 */
413struct ether_type {
414	int   e_type;
415	char *e_name;
416} ether_type [] = {
417ETHERTYPE_IP, "IP",
418ETHERTYPE_ARP, "ARP",
419ETHERTYPE_REVARP, "RARP",
420ETHERTYPE_IPV6, "IPv6",
421ETHERTYPE_PPPOED, "PPPoE Discovery",
422ETHERTYPE_PPPOES, "PPPoE Session",
423ETHERTYPE_TRILL, "TRILL",
424/* end of popular entries */
425ETHERTYPE_PUP,	"Xerox PUP",
4260x0201, "Xerox PUP",
4270x0400, "Nixdorf",
4280x0600, "Xerox NS IDP",
4290x0601, "XNS Translation",
4300x0801, "X.75 Internet",
4310x0802, "NBS Internet",
4320x0803, "ECMA Internet",
4330x0804, "CHAOSnet",
4340x0805, "X.25 Level 3",
4350x0807, "XNS Compatibility",
4360x081C, "Symbolics Private",
4370x0888, "Xyplex",
4380x0889, "Xyplex",
4390x088A, "Xyplex",
4400x0900, "Ungermann-Bass network debugger",
4410x0A00, "Xerox IEEE802.3 PUP",
4420x0A01, "Xerox IEEE802.3 PUP Address Translation",
4430x0BAD, "Banyan Systems",
4440x0BAF, "Banyon VINES Echo",
4450x1000, "Berkeley Trailer negotiation",
4460x1000,	"IP trailer (0)",
4470x1001,	"IP trailer (1)",
4480x1002,	"IP trailer (2)",
4490x1003,	"IP trailer (3)",
4500x1004,	"IP trailer (4)",
4510x1005,	"IP trailer (5)",
4520x1006,	"IP trailer (6)",
4530x1007,	"IP trailer (7)",
4540x1008,	"IP trailer (8)",
4550x1009,	"IP trailer (9)",
4560x100a,	"IP trailer (10)",
4570x100b,	"IP trailer (11)",
4580x100c,	"IP trailer (12)",
4590x100d,	"IP trailer (13)",
4600x100e,	"IP trailer (14)",
4610x100f,	"IP trailer (15)",
4620x1234, "DCA - Multicast",
4630x1600, "VALID system protocol",
4640x1989, "Aviator",
4650x3C00, "3Com NBP virtual circuit datagram",
4660x3C01, "3Com NBP System control datagram",
4670x3C02, "3Com NBP Connect request (virtual cct)",
4680x3C03, "3Com NBP Connect response",
4690x3C04, "3Com NBP Connect complete",
4700x3C05, "3Com NBP Close request (virtual cct)",
4710x3C06, "3Com NBP Close response",
4720x3C07, "3Com NBP Datagram (like XNS IDP)",
4730x3C08, "3Com NBP Datagram broadcast",
4740x3C09, "3Com NBP Claim NetBIOS name",
4750x3C0A, "3Com NBP Delete Netbios name",
4760x3C0B, "3Com NBP Remote adaptor status request",
4770x3C0C, "3Com NBP Remote adaptor response",
4780x3C0D, "3Com NBP Reset",
4790x4242, "PCS Basic Block Protocol",
4800x4321, "THD - Diddle",
4810x5208, "BBN Simnet Private",
4820x6000, "DEC unass, experimental",
4830x6001, "DEC Dump/Load",
4840x6002, "DEC Remote Console",
4850x6003, "DECNET Phase IV, DNA Routing",
4860x6004, "DEC LAT",
4870x6005, "DEC Diagnostic",
4880x6006, "DEC customer protocol",
4890x6007, "DEC Local Area VAX Cluster (LAVC)",
4900x6008, "DEC unass (AMBER?)",
4910x6009, "DEC unass (MUMPS?)",
4920x6010, "3Com",
4930x6011, "3Com",
4940x6012, "3Com",
4950x6013, "3Com",
4960x6014, "3Com",
4970x7000, "Ungermann-Bass download",
4980x7001, "Ungermann-Bass NIUs",
4990x7002, "Ungermann-Bass diagnostic/loopback",
5000x7003, "Ungermann-Bass ? (NMC to/from UB Bridge)",
5010x7005, "Ungermann-Bass Bridge Spanning Tree",
5020x7007, "OS/9 Microware",
5030x7009, "OS/9 Net?",
5040x7020, "Sintrom",
5050x7021, "Sintrom",
5060x7022, "Sintrom",
5070x7023, "Sintrom",
5080x7024, "Sintrom",
5090x7025, "Sintrom",
5100x7026, "Sintrom",
5110x7027, "Sintrom",
5120x7028, "Sintrom",
5130x7029, "Sintrom",
5140x8003, "Cronus VLN",
5150x8004, "Cronus Direct",
5160x8005, "HP Probe protocol",
5170x8006, "Nestar",
5180x8008, "AT&T/Stanford Univ",
5190x8010, "Excelan",
5200x8013, "SGI diagnostic",
5210x8014, "SGI network games",
5220x8015, "SGI reserved",
5230x8016, "SGI XNS NameServer, bounce server",
5240x8019, "Apollo DOMAIN",
5250x802E, "Tymshare",
5260x802F, "Tigan,",
5270x8036, "Aeonic Systems",
5280x8037, "IPX (Novell Netware)",
5290x8038, "DEC LanBridge Management",
5300x8039, "DEC unass (DSM/DTP?)",
5310x803A, "DEC unass (Argonaut Console?)",
5320x803B, "DEC unass (VAXELN?)",
5330x803C, "DEC unass (NMSV? DNA Naming Service?)",
5340x803D, "DEC Ethernet CSMA/CD Encryption Protocol",
5350x803E, "DEC unass (DNA Time Service?)",
5360x803F, "DEC LAN Traffic Monitor Protocol",
5370x8040, "DEC unass (NetBios Emulator?)",
5380x8041, "DEC unass (MS/DOS?, Local Area System Transport?)",
5390x8042, "DEC unass",
5400x8044, "Planning Research Corp.",
5410x8046, "AT&T",
5420x8047, "AT&T",
5430x8049, "ExperData",
5440x805B, "VMTP",
5450x805C, "Stanford V Kernel, version 6.0",
5460x805D, "Evans & Sutherland",
5470x8060, "Little Machines",
5480x8062, "Counterpoint",
5490x8065, "University of Mass. at Amherst",
5500x8066, "University of Mass. at Amherst",
5510x8067, "Veeco Integrated Automation",
5520x8068, "General Dynamics",
5530x8069, "AT&T",
5540x806A, "Autophon",
5550x806C, "ComDesign",
5560x806D, "Compugraphic Corp",
5570x806E, "Landmark",
5580x806F, "Landmark",
5590x8070, "Landmark",
5600x8071, "Landmark",
5610x8072, "Landmark",
5620x8073, "Landmark",
5630x8074, "Landmark",
5640x8075, "Landmark",
5650x8076, "Landmark",
5660x8077, "Landmark",
5670x807A, "Matra",
5680x807B, "Dansk Data Elektronik",
5690x807C, "Merit Internodal",
5700x807D, "Vitalink",
5710x807E, "Vitalink",
5720x807F, "Vitalink",
5730x8080, "Vitalink TransLAN III Management",
5740x8081, "Counterpoint",
5750x8082, "Counterpoint",
5760x8083, "Counterpoint",
5770x8088, "Xyplex",
5780x8089, "Xyplex",
5790x808A, "Xyplex",
5800x809B, "EtherTalk (AppleTalk over Ethernet)",
5810x809C, "Datability",
5820x809D, "Datability",
5830x809E, "Datability",
5840x809F, "Spider Systems",
5850x80A3, "Nixdorf",
5860x80A4, "Siemens Gammasonics",
5870x80C0, "DCA Data Exchange Cluster",
5880x80C6, "Pacer Software",
5890x80C7, "Applitek Corp",
5900x80C8, "Intergraph",
5910x80C9, "Intergraph",
5920x80CB, "Intergraph",
5930x80CC, "Intergraph",
5940x80CA, "Intergraph",
5950x80CD, "Harris Corp",
5960x80CE, "Harris Corp",
5970x80CF, "Taylor Instrument",
5980x80D0, "Taylor Instrument",
5990x80D1, "Taylor Instrument",
6000x80D2, "Taylor Instrument",
6010x80D3, "Rosemount Corp",
6020x80D4, "Rosemount Corp",
6030x80D5, "IBM SNA Services over Ethernet",
6040x80DD, "Varian Associates",
6050x80DE, "TRFS",
6060x80DF, "TRFS",
6070x80E0, "Allen-Bradley",
6080x80E1, "Allen-Bradley",
6090x80E2, "Allen-Bradley",
6100x80E3, "Allen-Bradley",
6110x80E4, "Datability",
6120x80F2, "Retix",
6130x80F3, "AARP (Appletalk)",
6140x80F4, "Kinetics",
6150x80F5, "Kinetics",
6160x80F7, "Apollo",
6170x80FF, "Wellfleet Communications",
6180x8102, "Wellfleet Communications",
6190x8107, "Symbolics Private",
6200x8108, "Symbolics Private",
6210x8109, "Symbolics Private",
6220x812B, "Talaris",
6230x8130, "Waterloo",
6240x8131, "VG Lab",
6250x8137, "Novell (old) NetWare IPX",
6260x8138, "Novell",
6270x814C, "SNMP over Ethernet",
6280x817D, "XTP",
6290x81D6, "Lantastic",
6300x8888, "HP LanProbe test?",
6310x9000, "Loopback",
6320x9001, "3Com, XNS Systems Management",
6330x9002, "3Com, TCP/IP Systems Management",
6340x9003, "3Com, loopback detection",
6350xAAAA, "DECNET	(VAX 6220 DEBNI)",
6360xFF00, "BBN VITAL-LanBridge cache wakeups",
6370,	"",
638};
639
640char *
641print_fc(uint_t type)
642{
643
644	switch (type) {
645		case 0x50: return ("LLC");
646		case 0x4f: return ("SMT NSA");
647		case 0x41: return ("SMT Info");
648		default: return ("Unknown");
649	}
650}
651
652char *
653print_smtclass(uint_t type)
654{
655	switch (type) {
656		case 0x01: return ("NIF");
657		case 0x02: return ("SIF Conf");
658		case 0x03: return ("SIF Oper");
659		case 0x04: return ("ECF");
660		case 0x05: return ("RAF");
661		case 0x06: return ("RDF");
662		case 0x07: return ("SRF");
663		case 0x08: return ("PMF Get");
664		case 0x09: return ("PMF Change");
665		case 0x0a: return ("PMF Add");
666		case 0x0b: return ("PMF Remove");
667		case 0xff: return ("ESF");
668		default: return ("Unknown");
669	}
670
671}
672char *
673print_smttype(uint_t type)
674{
675	switch (type) {
676		case 0x01: return ("Announce");
677		case 0x02: return ("Request");
678		case 0x03: return ("Response");
679		default: return ("Unknown");
680	}
681
682}
683char *
684print_ethertype(int type)
685{
686	int i;
687
688	for (i = 0; ether_type[i].e_type; i++)
689		if (type == ether_type[i].e_type)
690			return (ether_type[i].e_name);
691	if (type < 1500)
692		return ("LLC/802.3");
693
694	return ("Unknown");
695}
696
697#define	MAX_RDFLDS	14		/* changed to 14 from 8 as per IEEE */
698#define	TR_FN_ADDR	0x80		/* dest addr is functional */
699#define	TR_SR_ADDR	0x80		/* MAC utilizes source route */
700#define	ACFCDASA_LEN	14		/* length of AC|FC|DA|SA */
701#define	TR_MAC_MASK	0xc0
702#define	TR_AC		0x00		/* Token Ring access control */
703#define	TR_LLC_FC	0x40		/* Token Ring llc frame control */
704#define	LSAP_SNAP	0xaa
705#define	LLC_SNAP_HDR_LEN	8
706#define	LLC_HDR1_LEN	3		/* DON'T use sizeof(struct llc_hdr1) */
707#define	CNTL_LLC_UI	0x03		/* un-numbered information packet */
708
709/*
710 * Source Routing Route Information field.
711 */
712struct tr_ri {
713#if defined(_BIT_FIELDS_HTOL)
714	uchar_t rt:3;			/* routing type */
715	uchar_t len:5;			/* length */
716	uchar_t dir:1;			/* direction bit */
717	uchar_t mtu:3;			/* largest frame */
718	uchar_t res:4;			/* reserved */
719#elif defined(_BIT_FIELDS_LTOH)
720	uchar_t len:5;			/* length */
721	uchar_t rt:3;			/* routing type */
722	uchar_t res:4;			/* reserved */
723	uchar_t mtu:3;			/* largest frame */
724	uchar_t dir:1;			/* direction bit */
725#endif
726/*
727 * In little endian machine, the ring field has to be stored in a
728 * ushort_t type.  This implies that it is not possible to have a
729 * layout of bit field to represent bridge and ring.
730 *
731 * If the compiler uses _BIT_FIELDS_HTOL and it is a big endian
732 * machine, the following bit field definition will work.
733 *
734 *	struct tr_rd {
735 *		ushort_t bridge:4;
736 *		ushort_t ring:12;
737 *	} rd[MAX_RDFLDS];
738 *
739 * If the compiler uses _BIT_FIELDS_LTOH and it is a big endian
740 * machine, the definition can be changed to
741 *
742 *	struct tr_rd {
743 *		ushort_t bridge:4;
744 *		ushort_t ring:12;
745 *	} rd[MAX_RDFLDS];
746 *
747 * With little endian machine, we need to use 2 macroes.  For
748 * simplicity, since the macroes work for both big and little
749 * endian machines, we will not use bit fields for the
750 * definition.
751 */
752#define	bridge(route)	(ntohs((ushort_t)(route)) & 0x0F)
753#define	ring(route)	(ntohs((ushort_t)(route)) >> 4)
754
755	ushort_t rd[MAX_RDFLDS];	/* route designator fields */
756};
757
758struct tr_header {
759	uchar_t		ac;
760	uchar_t		fc;
761	struct ether_addr dhost;
762	struct ether_addr shost;
763	struct tr_ri	ri;
764};
765
766struct llc_snap_hdr {
767	uchar_t  d_lsap;		/* destination service access point */
768	uchar_t  s_lsap;		/* source link service access point */
769	uchar_t  control;		/* short control field */
770	uchar_t  org[3];		/* Ethernet style organization field */
771	ushort_t type;			/* Ethernet style type field */
772};
773
774struct ether_addr tokenbroadcastaddr2 = {
775	0xc0, 0x00, 0xff, 0xff, 0xff, 0xff
776};
777
778int Mtutab[] = {516, 1470, 2052, 4472, 8144, 11407, 17800};
779
780char *
781print_sr(struct tr_ri *rh)
782{
783	int hops, ii;
784	static char line[512];
785
786	sprintf(line, "TR Source Route dir=%d, mtu=%d",
787	    rh->dir, Mtutab[rh->mtu]);
788
789	hops = (int)(rh->len - 2) / (int)2;
790
791	if (hops) {
792		sprintf(line+strlen(line), ", Route: ");
793		for (ii = 0; ii < hops; ii++) {
794			if (! bridge(rh->rd[ii])) {
795				sprintf(line+strlen(line), "(%d)",
796				    ring(rh->rd[ii]));
797			} else {
798				sprintf(line+strlen(line), "(%d)%d",
799				    ring(rh->rd[ii]), bridge(rh->rd[ii]));
800			}
801		}
802	}
803	return (&line[0]);
804}
805
806uint_t
807interpret_tr(int flags, caddr_t e, int elen, int origlen)
808{
809	struct tr_header *mh;
810	struct tr_ri *rh;
811	uchar_t fc;
812	struct llc_snap_hdr *snaphdr;
813	char *off;
814	int maclen, len;
815	boolean_t data_copied = B_FALSE;
816	extern char *dst_name, *src_name;
817	int ethertype;
818	int is_llc = 0, is_snap = 0, source_routing = 0;
819	int blen = MAX(origlen, 17800);
820
821	if (data != NULL && datalen != 0 && datalen < blen) {
822		free(data);
823		data = NULL;
824		datalen = 0;
825	}
826	if (!data) {
827		data = (char *)malloc(blen);
828		if (!data)
829			pr_err("Warning: malloc failure");
830		datalen = blen;
831	}
832
833	if (origlen < ACFCDASA_LEN) {
834		if (flags & F_SUM) {
835			(void) sprintf(get_sum_line(),
836			    "RUNT (short packet - %d bytes)",
837			    origlen);
838		}
839		if (flags & F_DTAIL)
840			show_header("RUNT:  ", "Short packet", origlen);
841		return (elen);
842	}
843	if (elen < ACFCDASA_LEN)
844		return (elen);
845
846	mh = (struct tr_header *)e;
847	rh = (struct tr_ri *)&mh->ri;
848	fc = mh->fc;
849
850	if (is_llc = tr_machdr_len(e, &maclen, &source_routing)) {
851		snaphdr = (struct llc_snap_hdr *)(e + maclen);
852		if (snaphdr->d_lsap == LSAP_SNAP &&
853		    snaphdr->s_lsap == LSAP_SNAP &&
854		    snaphdr->control == CNTL_LLC_UI) {
855			is_snap = 1;
856		}
857	}
858
859	if (memcmp(&mh->dhost, &ether_broadcast,
860	    sizeof (struct ether_addr)) == 0)
861		dst_name = "(broadcast)";
862	else if (memcmp(&mh->dhost, &tokenbroadcastaddr2,
863	    sizeof (struct ether_addr)) == 0)
864		dst_name = "(mac broadcast)";
865	else if (mh->dhost.ether_addr_octet[0] & TR_FN_ADDR)
866		dst_name = "(functional)";
867
868	if (is_snap)
869		ethertype = ntohs(snaphdr->type);
870	else {
871		src_name =  print_etherinfo(&mh->shost);
872		dst_name =  print_etherinfo(&mh->dhost);
873	}
874
875	/*
876	 * The 14 byte ether header screws up alignment
877	 * of the rest of the packet for 32 bit aligned
878	 * architectures like SPARC. Alas, we have to copy
879	 * the rest of the packet in order to align it.
880	 */
881	if (is_llc) {
882		if (is_snap) {
883			len = elen - (maclen + LLC_SNAP_HDR_LEN);
884			off = (char *)(e + maclen + LLC_SNAP_HDR_LEN);
885		} else {
886			len = elen - (maclen + LLC_HDR1_LEN);
887			off = (char *)(e + maclen + LLC_HDR1_LEN);
888		}
889	} else {
890		len = elen - maclen;
891		off = (char *)(e + maclen);
892	}
893
894	if (len > 0 && (off + len <= (char *)e + elen)) {
895		(void) memcpy(data, off, len);
896		data_copied = B_TRUE;
897	}
898
899	if (flags & F_SUM) {
900		if (source_routing)
901			sprintf(get_sum_line(), print_sr(rh));
902
903		if (is_llc) {
904			if (is_snap) {
905				(void) sprintf(get_sum_line(), "TR LLC w/SNAP "
906				    "Type=%04X (%s), size=%d bytes",
907				    ethertype,
908				    print_ethertype(ethertype),
909				    origlen);
910			} else {
911				(void) sprintf(get_sum_line(), "TR LLC, but no "
912				    "SNAP encoding, size = %d bytes",
913				    origlen);
914			}
915		} else {
916			(void) sprintf(get_sum_line(),
917			    "TR MAC FC=%02X (%s), size = %d bytes",
918			    fc, print_fc(fc), origlen);
919		}
920	}
921
922	if (flags & F_DTAIL) {
923		show_header("TR:  ", "TR Header", elen);
924		show_space();
925		(void) sprintf(get_line(0, 0),
926		    "Packet %d arrived at %d:%02d:%d.%05d",
927		    pi_frame,
928		    pi_time_hour, pi_time_min, pi_time_sec,
929		    pi_time_usec / 10);
930		(void) sprintf(get_line(0, 0),
931		    "Packet size = %d bytes",
932		    elen);
933		(void) sprintf(get_line(0, 1),
934		    "Frame Control = %02x (%s)",
935		    fc, print_fc(fc));
936		(void) sprintf(get_line(2, 6),
937		    "Destination = %s, %s",
938		    printether(&mh->dhost),
939		    print_etherinfo(&mh->dhost));
940		(void) sprintf(get_line(8, 6),
941		    "Source      = %s, %s",
942		    printether(&mh->shost),
943		    print_etherinfo(&mh->shost));
944
945		if (source_routing)
946			sprintf(get_line(ACFCDASA_LEN, rh->len), print_sr(rh));
947
948		if (is_llc) {
949			(void) sprintf(get_line(maclen, 1),
950			    "Dest   Service Access Point = %02x",
951			    snaphdr->d_lsap);
952			(void) sprintf(get_line(maclen+1, 1),
953			    "Source Service Access Point = %02x",
954			    snaphdr->s_lsap);
955			(void) sprintf(get_line(maclen+2, 1),
956			    "Control = %02x",
957			    snaphdr->control);
958			if (is_snap) {
959				(void) sprintf(get_line(maclen+3, 3),
960				    "SNAP Protocol Id = %02x%02x%02x",
961				    snaphdr->org[0], snaphdr->org[1],
962				    snaphdr->org[2]);
963			}
964		}
965
966		if (is_snap) {
967			(void) sprintf(get_line(maclen+6, 2),
968			    "SNAP Type = %04X (%s)",
969			    ethertype, print_ethertype(ethertype));
970		}
971
972		show_space();
973	}
974
975	/* go to the next protocol layer */
976	if (is_snap && data_copied) {
977		switch (ethertype) {
978		case ETHERTYPE_IP:
979			(void) interpret_ip(flags, (struct ip *)data, len);
980			break;
981		/* Just in case it is decided to add this type */
982		case ETHERTYPE_IPV6:
983			(void) interpret_ipv6(flags, (ip6_t *)data, len);
984			break;
985		case ETHERTYPE_ARP:
986		case ETHERTYPE_REVARP:
987			interpret_arp(flags, (struct arphdr *)data, len);
988			break;
989		case ETHERTYPE_AARP:	/* AppleTalk */
990			interpret_aarp(flags, data, len);
991			break;
992		case ETHERTYPE_AT:
993			interpret_at(flags, (struct ddp_hdr *)data, len);
994			break;
995		default:
996			break;
997		}
998	}
999
1000	return (elen);
1001}
1002
1003
1004/*
1005 *	stuffs length of mac and ri fields into *lenp
1006 *	returns:
1007 *		0: mac frame
1008 *		1: llc frame
1009 */
1010static int
1011tr_machdr_len(char *e, int *lenp, int *source_routing)
1012{
1013	struct tr_header *mh;
1014	struct tr_ri *rh;
1015	uchar_t fc;
1016
1017	mh = (struct tr_header *)e;
1018	rh = (struct tr_ri *)&mh->ri;
1019	fc = mh->fc;
1020
1021	if (mh->shost.ether_addr_octet[0] & TR_SR_ADDR) {
1022		*lenp = ACFCDASA_LEN + rh->len;
1023		*source_routing = 1;
1024	} else {
1025		*lenp = ACFCDASA_LEN;
1026		*source_routing = 0;
1027	}
1028
1029	if ((fc & TR_MAC_MASK) == 0)
1030		return (0);		/* it's a MAC frame */
1031	else
1032		return (1);		/* it's an LLC frame */
1033}
1034
1035uint_t
1036tr_header_len(char *e, size_t msgsize)
1037{
1038	struct llc_snap_hdr *snaphdr;
1039	int len = 0, source_routing;
1040
1041	if (tr_machdr_len(e, &len, &source_routing) == 0)
1042		return (len);		/* it's a MAC frame */
1043
1044	if (msgsize < sizeof (struct llc_snap_hdr))
1045		return (0);
1046
1047	snaphdr = (struct llc_snap_hdr *)(e + len);
1048	if (snaphdr->d_lsap == LSAP_SNAP &&
1049	    snaphdr->s_lsap == LSAP_SNAP &&
1050	    snaphdr->control == CNTL_LLC_UI)
1051		len += LLC_SNAP_HDR_LEN;	/* it's a SNAP frame */
1052	else
1053		len += LLC_HDR1_LEN;
1054
1055	return (len);
1056}
1057
1058struct fddi_header {
1059	uchar_t fc;
1060	struct ether_addr dhost, shost;
1061	uchar_t dsap, ssap, ctl, proto_id[3];
1062	ushort_t	type;
1063};
1064
1065uint_t
1066interpret_fddi(int flags, caddr_t e, int elen, int origlen)
1067{
1068	struct fddi_header fhdr, *f = &fhdr;
1069	char *off;
1070	int len;
1071	boolean_t data_copied = B_FALSE;
1072	extern char *dst_name, *src_name;
1073	int ethertype;
1074	int is_llc = 0, is_smt = 0, is_snap = 0;
1075	int blen = MAX(origlen, 4500);
1076
1077	if (data != NULL && datalen != 0 && datalen < blen) {
1078		free(data);
1079		data = NULL;
1080		datalen = 0;
1081	}
1082	if (!data) {
1083		data = (char *)malloc(blen);
1084		if (!data)
1085			pr_err("Warning: malloc failure");
1086		datalen = blen;
1087	}
1088
1089	if (origlen < 13) {
1090		if (flags & F_SUM) {
1091			(void) sprintf(get_sum_line(),
1092			    "RUNT (short packet - %d bytes)",
1093			    origlen);
1094		}
1095		if (flags & F_DTAIL)
1096			show_header("RUNT:  ", "Short packet", origlen);
1097		return (elen);
1098	}
1099	if (elen < 13)
1100		return (elen);
1101
1102	(void) memcpy(&f->fc, e, sizeof (f->fc));
1103	addr_copy_swap(&f->dhost, (struct ether_addr *)(e+1));
1104	addr_copy_swap(&f->shost, (struct ether_addr *)(e+7));
1105
1106	if ((f->fc&0x50) == 0x50) {
1107		is_llc = 1;
1108		(void) memcpy(&f->dsap, e+13, sizeof (f->dsap));
1109		(void) memcpy(&f->ssap, e+14, sizeof (f->ssap));
1110		(void) memcpy(&f->ctl, e+15, sizeof (f->ctl));
1111		if (f->dsap == 0xaa && f->ssap == 0xaa) {
1112			is_snap = 1;
1113			(void) memcpy(&f->proto_id, e+16, sizeof (f->proto_id));
1114			(void) memcpy(&f->type, e+19, sizeof (f->type));
1115		}
1116	} else {
1117		if ((f->fc&0x41) == 0x41 || (f->fc&0x4f) == 0x4f) {
1118			is_smt = 1;
1119		}
1120	}
1121
1122
1123	if (memcmp(&f->dhost, &ether_broadcast,
1124	    sizeof (struct ether_addr)) == 0)
1125		dst_name = "(broadcast)";
1126	else if (f->dhost.ether_addr_octet[0] & 0x01)
1127		dst_name = "(multicast)";
1128
1129	if (is_snap)
1130		ethertype = ntohs(f->type);
1131	else {
1132		src_name = 	print_etherinfo(&f->shost);
1133		dst_name =  print_etherinfo(&f->dhost);
1134	}
1135
1136	/*
1137	 * The 14 byte ether header screws up alignment
1138	 * of the rest of the packet for 32 bit aligned
1139	 * architectures like SPARC. Alas, we have to copy
1140	 * the rest of the packet in order to align it.
1141	 */
1142	if (is_llc) {
1143		if (is_snap) {
1144			len = elen - 21;
1145			off = (char *)(e + 21);
1146		} else {
1147			len = elen - 16;
1148			off = (char *)(e + 16);
1149		}
1150	} else {
1151		len = elen - 13;
1152		off = (char *)(e + 13);
1153	}
1154
1155	if (len > 0 && (off + len <= (char *)e + elen)) {
1156		(void) memcpy(data, off, len);
1157		data_copied = B_TRUE;
1158	}
1159
1160	if (flags & F_SUM) {
1161		if (is_llc) {
1162			if (is_snap) {
1163				(void) sprintf(get_sum_line(),
1164				    "FDDI LLC Type=%04X (%s), size = %d bytes",
1165				    ethertype,
1166				    print_ethertype(ethertype),
1167				    origlen);
1168			} else {
1169				(void) sprintf(get_sum_line(), "LLC, but no "
1170				    "SNAP encoding, size = %d bytes",
1171				    origlen);
1172			}
1173		} else if (is_smt) {
1174			(void) sprintf(get_sum_line(), "SMT Type=%02X (%s), "
1175			    "Class = %02X (%s), size = %d bytes",
1176			    *(uchar_t *)(data+1), print_smttype(*(data+1)),
1177			    *data, print_smtclass(*data), origlen);
1178		} else {
1179			(void) sprintf(get_sum_line(),
1180			    "FC=%02X (%s), size = %d bytes",
1181			    f->fc, print_fc(f->fc), origlen);
1182		}
1183	}
1184
1185	if (flags & F_DTAIL) {
1186		show_header("FDDI:  ", "FDDI Header", elen);
1187		show_space();
1188		(void) sprintf(get_line(0, 0),
1189		    "Packet %d arrived at %d:%02d:%d.%05d",
1190		    pi_frame,
1191		    pi_time_hour, pi_time_min, pi_time_sec,
1192		    pi_time_usec / 10);
1193		(void) sprintf(get_line(0, 0),
1194		    "Packet size = %d bytes",
1195		    elen, elen);
1196		(void) sprintf(get_line(0, 6),
1197		    "Destination = %s, %s",
1198		    printether(&f->dhost),
1199		    print_etherinfo(&f->dhost));
1200		(void) sprintf(get_line(6, 6),
1201		    "Source      = %s, %s",
1202		    printether(&f->shost),
1203		    print_etherinfo(&f->shost));
1204
1205		if (is_llc) {
1206			(void) sprintf(get_line(12, 2),
1207			    "Frame Control = %02x (%s)",
1208			    f->fc, print_fc(f->fc));
1209			(void) sprintf(get_line(12, 2),
1210			    "Dest   Service Access Point = %02x",
1211			    f->dsap);
1212			(void) sprintf(get_line(12, 2),
1213			    "Source Service Access Point = %02x",
1214			    f->ssap);
1215			(void) sprintf(get_line(12, 2),
1216			    "Control = %02x",
1217			    f->ctl);
1218			if (is_snap) {
1219				(void) sprintf(get_line(12, 2),
1220				    "Protocol Id = %02x%02x%02x",
1221				    f->proto_id[0], f->proto_id[1],
1222				    f->proto_id[2]);
1223			}
1224		} else if (is_smt) {
1225			(void) sprintf(get_line(12, 2),
1226			    "Frame Control = %02x (%s)",
1227			    f->fc, print_fc(f->fc));
1228			(void) sprintf(get_line(12, 2),
1229			    "Class = %02x (%s)",
1230			    (uchar_t)*data, print_smtclass(*data));
1231			(void) sprintf(get_line(12, 2),
1232			    "Type = %02x (%s)",
1233			    *(uchar_t *)(data+1), print_smttype(*(data+1)));
1234		} else {
1235			(void) sprintf(get_line(12, 2),
1236			    "FC=%02X (%s), size = %d bytes",
1237			    f->fc, print_fc(f->fc), origlen);
1238		}
1239
1240		if (is_snap) {
1241			(void) sprintf(get_line(12, 2),
1242			    "LLC Type = %04X (%s)",
1243			    ethertype, print_ethertype(ethertype));
1244		}
1245
1246		show_space();
1247	}
1248
1249	/* go to the next protocol layer */
1250	if (is_llc && is_snap && f->ctl == 0x03 && data_copied) {
1251		switch (ethertype) {
1252		case ETHERTYPE_IP:
1253			(void) interpret_ip(flags, (struct ip *)data, len);
1254			break;
1255		/* Just in case it is decided to add this type */
1256		case ETHERTYPE_IPV6:
1257			(void) interpret_ipv6(flags, (ip6_t *)data, len);
1258			break;
1259		case ETHERTYPE_ARP:
1260		case ETHERTYPE_REVARP:
1261			interpret_arp(flags, (struct arphdr *)data, len);
1262			break;
1263		default:
1264			break;
1265		}
1266
1267	}
1268
1269	return (elen);
1270}
1271
1272uint_t
1273fddi_header_len(char *e, size_t msgsize)
1274{
1275	struct fddi_header fhdr, *f = &fhdr;
1276
1277	if (msgsize < sizeof (struct fddi_header))
1278		return (0);
1279
1280	(void) memcpy(&f->fc, e, sizeof (f->fc));
1281	(void) memcpy(&f->dhost, e+1, sizeof (struct ether_addr));
1282	(void) memcpy(&f->shost, e+7, sizeof (struct ether_addr));
1283
1284	if ((f->fc&0x50) == 0x50) {
1285		(void) memcpy(&f->dsap, e+13, sizeof (f->dsap));
1286		(void) memcpy(&f->ssap, e+14, sizeof (f->ssap));
1287		(void) memcpy(&f->ctl, e+15, sizeof (f->ctl));
1288		if (f->dsap == 0xaa && f->ssap == 0xaa) {
1289			return (21);
1290		}
1291		return (16);
1292	} else {
1293		if ((f->fc&0x41) == 0x41 || (f->fc&0x4f) == 0x4f) {
1294			return (13);
1295		}
1296	}
1297	/* Return the default FDDI header length. */
1298	return (13);
1299}
1300
1301/*
1302 * Print the given Ethernet address
1303 */
1304char *
1305printether(struct ether_addr *p)
1306{
1307	static char buf[256];
1308
1309	sprintf(buf, "%x:%x:%x:%x:%x:%x",
1310	    p->ether_addr_octet[0],
1311	    p->ether_addr_octet[1],
1312	    p->ether_addr_octet[2],
1313	    p->ether_addr_octet[3],
1314	    p->ether_addr_octet[4],
1315	    p->ether_addr_octet[5]);
1316
1317	return (buf);
1318}
1319
1320/*
1321 * Table of Ethernet Address Assignments
1322 * Some of the more popular entries
1323 * are at the beginning of the table
1324 * to reduce search time.  Note that the
1325 * e-block's are stored in host byte-order.
1326 */
1327struct block_type {
1328	int	e_block;
1329	char	*e_name;
1330} ether_block [] = {
13310x080020,	"Sun",
13320x0000C6,	"HP",
13330x08002B,	"DEC",
13340x00000F,	"NeXT",
13350x00000C,	"Cisco",
13360x080069,	"Silicon Graphics",
13370x000069,	"Silicon Graphics",
13380x0000A7,	"Network Computing Devices (NCD	X-terminal)",
13390x08005A,	"IBM",
13400x0000AC,	"Apollo",
13410x0180C2,	"Standard MAC Group Address",
1342/* end of popular entries */
13430x000002,	"BBN",
13440x000010,	"Sytek",
13450x000011,	"Tektronix",
13460x000018,	"Webster (?)",
13470x00001B,	"Novell",
13480x00001D,	"Cabletron",
13490x000020,	"DIAB (Data Industrier AB)",
13500x000021,	"SC&C",
13510x000022,	"Visual Technology",
13520x000029,	"IMC",
13530x00002A,	"TRW",
13540x00003D,	"AT&T",
13550x000049,	"Apricot Ltd.",
13560x000055,	"AT&T",
13570x00005A,	"S & Koch",
13580x00005A,	"Xerox 806 (unregistered)",
13590x00005E,	"U.S. Department of Defense (IANA)",
13600x000065,	"Network General",
13610x00006B,	"MIPS",
13620x000077,	"MIPS",
13630x000079,	"NetWare (?)",
13640x00007A,	"Ardent",
13650x00007B,	"Research Machines",
13660x00007D,	"Harris (3M) (old)",
13670x000080,	"Imagen(?)",
13680x000081,	"Synoptics",
13690x000084,	"Aquila (?)",
13700x000086,	"Gateway (?)",
13710x000089,	"Cayman Systems	Gatorbox",
13720x000093,	"Proteon",
13730x000094,	"Asante",
13740x000098,	"Cross Com",
13750x00009F,	"Ameristar Technology",
13760x0000A2,	"Wellfleet",
13770x0000A3,	"Network Application Technology",
13780x0000A4,	"Acorn",
13790x0000A6,	"Network General",
13800x0000A7,	"Network Computing Devices (NCD	X-terminal)",
13810x0000A9,	"Network Systems",
13820x0000AA,	"Xerox",
13830x0000B3,	"CIMLinc",
13840x0000B5,	"Datability Terminal Server",
13850x0000B7,	"Dove Fastnet",
13860x0000BC,	"Allen-Bradley",
13870x0000C0,	"Western Digital",
13880x0000C8,	"Altos",
13890x0000C9,	"Emulex Terminal Server",
13900x0000D0,	"Develcon Electronics, Ltd.",
13910x0000D1,	"Adaptec Inc. Nodem product",
13920x0000D7,	"Dartmouth College (NED Router)",
13930x0000DD,	"Gould",
13940x0000DE,	"Unigraph",
13950x0000E2,	"Acer Counterpoint",
13960x0000E8,	"Accton Technology Corporation",
13970x0000EE,	"Network Designers Limited(?)",
13980x0000EF,	"Alantec",
13990x0000F3,	"Gandalf",
14000x0000FD,	"High Level Hardware (Orion, UK)",
14010x000143,	"IEEE 802",
14020x001700,	"Kabel",
14030x004010,	"Sonic",
14040x00608C,	"3Com",
14050x00800F,	"SMC",
14060x008019,	"Dayna Communications Etherprint product",
14070x00802D,	"Xylogics, Inc.	Annex terminal servers",
14080x008035,	"Technology Works",
14090x008087,	"Okidata",
14100x00808C,	"Frontier Software Development",
14110x0080C7,	"Xircom Inc.",
14120x0080D0,	"Computer Products International",
14130x0080D3,	"Shiva Appletalk-Ethernet interface",
14140x0080D4,	"Chase Limited",
14150x0080F1,	"Opus",
14160x00AA00,	"Intel",
14170x00B0D0,	"Computer Products International",
14180x00DD00,	"Ungermann-Bass",
14190x00DD01,	"Ungermann-Bass",
14200x00EFE5,	"IBM (3Com card)",
14210x020406,	"BBN",
14220x026060,	"3Com",
14230x026086,	"Satelcom MegaPac (UK)",
14240x02E6D3,	"Bus-Tech, Inc. (BTI)",
14250x080001,	"Computer Vision",
14260x080002,	"3Com (Formerly Bridge)",
14270x080003,	"ACC (Advanced Computer Communications)",
14280x080005,	"Symbolics",
14290x080007,	"Apple",
14300x080008,	"BBN",
14310x080009,	"Hewlett-Packard",
14320x08000A,	"Nestar Systems",
14330x08000B,	"Unisys",
14340x08000D,	"ICL",
14350x08000E,	"NCR",
14360x080010,	"AT&T",
14370x080011,	"Tektronix, Inc.",
14380x080017,	"NSC",
14390x08001A,	"Data General",
14400x08001B,	"Data General",
14410x08001E,	"Apollo",
14420x080022,	"NBI",
14430x080025,	"CDC",
14440x080026,	"Norsk Data (Nord)",
14450x080027,	"PCS Computer Systems GmbH",
14460x080028,	"TI Explorer",
14470x08002E,	"Metaphor",
14480x08002F,	"Prime Computer",
14490x080036,	"Intergraph CAE stations",
14500x080037,	"Fujitsu-Xerox",
14510x080038,	"Bull",
14520x080039,	"Spider Systems",
14530x08003B,	"Torus Systems",
14540x08003E,	"Motorola VME bus processor module",
14550x080041,	"DCA Digital Comm. Assoc.",
14560x080046,	"Sony",
14570x080047,	"Sequent",
14580x080049,	"Univation",
14590x08004C,	"Encore",
14600x08004E,	"BICC",
14610x080056,	"Stanford University",
14620x080057,	"Evans & Sutherland (?)",
14630x080067,	"Comdesign",
14640x080068,	"Ridge",
14650x08006A,	"ATTst (?)",
14660x08006E,	"Excelan",
14670x080075,	"DDE (Danish Data Elektronik A/S)",
14680x080077,	"TSL (now Retix)",
14690x08007C,	"Vitalink TransLAN III",
14700x080080,	"XIOS",
14710x080081,	"Crosfield Electronics",
14720x080086,	"Imagen/QMS",
14730x080087,	"Xyplex	terminal server",
14740x080089,	"Kinetics AppleTalk-Ethernet interface",
14750x08008B,	"Pyramid",
14760x08008D,	"XyVision",
14770x080090,	"Retix Inc Bridge",
14780x10005A,	"IBM",
14790x1000D4,	"DEC",
14800x400003,	"NetWare",
14810x800010,	"AT&T",
14820xAA0004,	"DEC (DECNET)",
14830xC00000,	"SMC",
14840,		"",
1485};
1486
1487/*
1488 * The oui argument should be in host byte-order to conform with
1489 * the above array's values.
1490 */
1491char *
1492ether_ouiname(uint32_t oui)
1493{
1494	uint_t i;
1495
1496	for (i = 0; ether_block[i].e_block != 0; i++)
1497		if (oui == ether_block[i].e_block)
1498			return (ether_block[i].e_name);
1499
1500	return (NULL);
1501}
1502
1503/*
1504 * Print the additional Ethernet address info
1505 */
1506static char *
1507print_etherinfo(struct ether_addr *eaddr)
1508{
1509	uint_t addr = 0;
1510	char *p = (char *)&addr + 1;
1511	char *ename;
1512
1513	(void) memcpy(p, eaddr, 3);
1514
1515	if (memcmp(eaddr, &ether_broadcast, sizeof (struct ether_addr)) == 0)
1516		return ("(broadcast)");
1517
1518	addr = ntohl(addr);	/* make it right for little-endians */
1519	ename = ether_ouiname(addr);
1520
1521	if (ename != NULL)
1522		return (ename);
1523	else
1524		return ((eaddr->ether_addr_octet[0] & 1) ? "(multicast)" : "");
1525}
1526
1527static uchar_t	endianswap[] = {
1528	0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
1529	0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
1530	0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
1531	0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
1532	0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
1533	0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
1534	0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
1535	0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
1536	0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
1537	0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
1538	0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
1539	0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
1540	0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
1541	0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
1542	0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
1543	0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
1544	0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
1545	0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
1546	0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
1547	0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
1548	0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
1549	0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
1550	0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
1551	0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
1552	0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
1553	0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
1554	0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
1555	0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
1556	0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
1557	0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
1558	0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
1559	0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
1560};
1561
1562static void
1563addr_copy_swap(struct ether_addr *pd, struct ether_addr *ps)
1564{
1565	pd->ether_addr_octet[0] = endianswap[ps->ether_addr_octet[0]];
1566	pd->ether_addr_octet[1] = endianswap[ps->ether_addr_octet[1]];
1567	pd->ether_addr_octet[2] = endianswap[ps->ether_addr_octet[2]];
1568	pd->ether_addr_octet[3] = endianswap[ps->ether_addr_octet[3]];
1569	pd->ether_addr_octet[4] = endianswap[ps->ether_addr_octet[4]];
1570	pd->ether_addr_octet[5] = endianswap[ps->ether_addr_octet[5]];
1571}
1572
1573/* ARGSUSED */
1574uint_t
1575ib_header_len(char *hdr, size_t msgsize)
1576{
1577	return (IPOIB_HDRSIZE);
1578}
1579
1580static uint_t
1581interpret_ib(int flags, char *header, int elen, int origlen)
1582{
1583	struct ipoib_header *hdr = (struct ipoib_header *)header;
1584	char *off;
1585	int len;
1586	unsigned short ethertype;
1587	int blen = MAX(origlen, 4096);
1588
1589	if (data != NULL && datalen != 0 && datalen < blen) {
1590		free(data);
1591		data = NULL;
1592		datalen = 0;
1593	}
1594	if (data == NULL) {
1595		data = malloc(blen);
1596		if (data == NULL)
1597			pr_err("Warning: malloc failure");
1598		datalen = blen;
1599	}
1600	if (origlen < IPOIB_HDRSIZE) {
1601		if (flags & F_SUM)
1602			(void) snprintf(get_sum_line(), MAXLINE,
1603			    "RUNT (short packet - %d bytes)", origlen);
1604		if (flags & F_DTAIL)
1605			show_header("RUNT:  ", "Short packet", origlen);
1606		return (elen);
1607	}
1608	if (elen < IPOIB_HDRSIZE)
1609		return (elen);
1610
1611	/*
1612	 * It is not possible to understand just by looking
1613	 * at the header whether this was a broad/multi cast
1614	 * packet; thus dst_name is not updated.
1615	 */
1616	ethertype = ntohs(hdr->ipoib_type);
1617	len = elen - IPOIB_HDRSIZE;
1618	off = (char *)(hdr + 1);
1619	(void) memcpy(data, off, len);
1620
1621	if (flags & F_SUM) {
1622		(void) snprintf(get_sum_line(), MAXLINE,
1623		    "IPIB Type=%04X (%s), size = %d bytes",
1624		    ethertype,
1625		    print_ethertype(ethertype),
1626		    origlen);
1627	}
1628
1629	if (flags & F_DTAIL) {
1630		show_header("IPIB:  ", "IPIB Header", elen);
1631		show_space();
1632		(void) snprintf(get_line(0, 0), get_line_remain(),
1633		    "Packet %d arrived at %d:%02d:%d.%02d",
1634		    pi_frame, pi_time_hour, pi_time_min,
1635		    pi_time_sec, pi_time_usec / 10000);
1636		(void) snprintf(get_line(0, 0), get_line_remain(),
1637		    "Packet size = %d bytes", elen, elen);
1638		(void) snprintf(get_line(0, 2), get_line_remain(),
1639		    "Ethertype = %04X (%s)", ethertype,
1640		    print_ethertype(ethertype));
1641		show_space();
1642	}
1643
1644	/* Go to the next protocol layer */
1645	switch (ethertype) {
1646		case ETHERTYPE_IP:
1647			(void) interpret_ip(flags, (struct ip *)data, len);
1648			break;
1649		case ETHERTYPE_IPV6:
1650			(void) interpret_ipv6(flags, (ip6_t *)data, len);
1651			break;
1652		case ETHERTYPE_ARP:
1653		case ETHERTYPE_REVARP:
1654			interpret_arp(flags, (struct arphdr *)data, len);
1655			break;
1656	}
1657
1658	return (elen);
1659}
1660
1661/* ARGSUSED */
1662uint_t
1663ipnet_header_len(char *hdr, size_t msgsize)
1664{
1665	return (sizeof (dl_ipnetinfo_t));
1666}
1667
1668#define	MAX_UINT64_STR	22
1669static uint_t
1670interpret_ipnet(int flags, char *header, int elen, int origlen)
1671{
1672	dl_ipnetinfo_t dl;
1673	size_t len = elen - sizeof (dl_ipnetinfo_t);
1674	char *off = (char *)header + sizeof (dl_ipnetinfo_t);
1675	int blen = MAX(origlen, 8252);
1676	char szone[MAX_UINT64_STR];
1677	char dzone[MAX_UINT64_STR];
1678
1679	(void) memcpy(&dl, header, sizeof (dl));
1680	if (data != NULL && datalen != 0 && datalen < blen) {
1681		free(data);
1682		data = NULL;
1683		datalen = 0;
1684	}
1685	if (data == NULL) {
1686		data = (char *)malloc(blen);
1687		if (!data)
1688			pr_err("Warning: malloc failure");
1689		datalen = blen;
1690	}
1691
1692	if (dl.dli_zsrc == ALL_ZONES)
1693		sprintf(szone, "Unknown");
1694	else
1695		sprintf(szone, "%lu", BE_32(dl.dli_zsrc));
1696
1697	if (dl.dli_zdst == ALL_ZONES)
1698		sprintf(dzone, "Unknown");
1699	else
1700		sprintf(dzone, "%lu", BE_32(dl.dli_zdst));
1701
1702	if (flags & F_SUM) {
1703		(void) snprintf(get_sum_line(), MAXLINE,
1704		    "IPNET src zone %s dst zone %s", szone, dzone);
1705	}
1706
1707	if (flags & F_DTAIL) {
1708		show_header("IPNET:  ", "IPNET Header", elen);
1709		show_space();
1710		(void) sprintf(get_line(0, 0),
1711		    "Packet %d arrived at %d:%02d:%d.%05d",
1712		    pi_frame,
1713		    pi_time_hour, pi_time_min, pi_time_sec,
1714		    pi_time_usec / 10);
1715		(void) sprintf(get_line(0, 0),
1716		    "Packet size = %d bytes",
1717		    elen);
1718		(void) snprintf(get_line(0, 0), get_line_remain(),
1719		    "dli_version = %d", dl.dli_version);
1720		(void) snprintf(get_line(0, 0), get_line_remain(),
1721		    "dli_family = %d", dl.dli_family);
1722		(void) snprintf(get_line(0, 2), get_line_remain(),
1723		    "dli_zsrc = %s", szone);
1724		(void) snprintf(get_line(0, 2), get_line_remain(),
1725		    "dli_zdst = %s", dzone);
1726		show_space();
1727	}
1728	memcpy(data, off, len);
1729
1730	switch (dl.dli_family) {
1731	case AF_INET:
1732		(void) interpret_ip(flags, (struct ip *)data, len);
1733		break;
1734	case AF_INET6:
1735		(void) interpret_ipv6(flags, (ip6_t *)data, len);
1736		break;
1737	default:
1738		break;
1739	}
1740
1741	return (0);
1742}
1743
1744uint_t
1745ipv4_header_len(char *hdr, size_t msgsize)
1746{
1747	return (msgsize < sizeof (ipha_t) ? 0 : IPH_HDR_LENGTH((ipha_t *)hdr));
1748}
1749
1750/*
1751 * The header length needs to include all potential extension headers, as the
1752 * caller expects to use this length as an offset to the inner network layer
1753 * header to be used as a filter offset.  IPsec headers aren't passed up here,
1754 * and neither are fragmentation headers.
1755 */
1756uint_t
1757ipv6_header_len(char *hdr, size_t msgsize)
1758{
1759	ip6_t		*ip6hdr = (ip6_t *)hdr;
1760	ip6_hbh_t	*exthdr;
1761	uint_t		hdrlen = sizeof (ip6_t), exthdrlen;
1762	char		*pptr;
1763	uint8_t		nxt;
1764
1765	if (msgsize < sizeof (ip6_t))
1766		return (0);
1767
1768	nxt = ip6hdr->ip6_nxt;
1769	pptr = (char *)(ip6hdr + 1);
1770
1771	while (nxt != IPPROTO_ENCAP && nxt != IPPROTO_IPV6) {
1772		switch (nxt) {
1773		case IPPROTO_HOPOPTS:
1774		case IPPROTO_DSTOPTS:
1775		case IPPROTO_ROUTING:
1776			if (msgsize < hdrlen + sizeof (ip6_hbh_t))
1777				return (0);
1778			exthdr = (ip6_hbh_t *)pptr;
1779			exthdrlen = 8 + exthdr->ip6h_len * 8;
1780			hdrlen += exthdrlen;
1781			pptr += exthdrlen;
1782			nxt = exthdr->ip6h_nxt;
1783			break;
1784		default:
1785			/*
1786			 * This is garbage, there's no way to know where the
1787			 * inner IP header is.
1788			 */
1789			return (0);
1790		}
1791	}
1792
1793	return (hdrlen);
1794}
1795
1796/* ARGSUSED */
1797uint_t
1798interpret_iptun(int flags, char *header, int elen, int origlen)
1799{
1800	(void) interpret_ip(flags, (struct ip *)header, elen);
1801	return (elen);
1802}
1803