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