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