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