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