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