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