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