117680Spst/*
239300Sfenner * Copyright (c) 1992, 1993, 1994, 1995, 1996, 1997
317680Spst *	The Regents of the University of California.  All rights reserved.
417680Spst *
517680Spst * Redistribution and use in source and binary forms, with or without
617680Spst * modification, are permitted provided that: (1) source code distributions
717680Spst * retain the above copyright notice and this paragraph in its entirety, (2)
817680Spst * distributions including binary code include the above copyright notice and
917680Spst * this paragraph in its entirety in the documentation or other materials
1017680Spst * provided with the distribution, and (3) all advertising materials mentioning
1117680Spst * features or use of this software display the following acknowledgement:
1217680Spst * ``This product includes software developed by the University of California,
1317680Spst * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
1417680Spst * the University nor the names of its contributors may be used to endorse
1517680Spst * or promote products derived from this software without specific prior
1617680Spst * written permission.
1717680Spst * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
1817680Spst * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
1917680Spst * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2026183Sfenner *
2117680Spst * Code by Matt Thomas, Digital Equipment Corporation
2217680Spst *	with an awful lot of hacking by Jeffrey Mogul, DECWRL
2356896Sfenner *
2456896Sfenner * $FreeBSD$
2517680Spst */
2617680Spst
2717680Spst#ifndef lint
28127675Sbmsstatic const char rcsid[] _U_ =
29190207Srpaulo    "@(#) $Header: /tcpdump/master/tcpdump/print-llc.c,v 1.75 2007-04-13 09:43:11 hannes Exp $";
3017680Spst#endif
3117680Spst
3256896Sfenner#ifdef HAVE_CONFIG_H
3356896Sfenner#include "config.h"
3456896Sfenner#endif
3556896Sfenner
36127675Sbms#include <tcpdump-stdinc.h>
3717680Spst
3817680Spst#include <stdio.h>
3917680Spst#include <string.h>
4017680Spst
4117680Spst#include "interface.h"
4217680Spst#include "addrtoname.h"
4317680Spst#include "extract.h"			/* must come after interface.h */
4417680Spst
4517680Spst#include "llc.h"
4698527Sfenner#include "ethertype.h"
47146778Ssam#include "oui.h"
4817680Spst
49127675Sbmsstatic struct tok llc_values[] = {
50127675Sbms        { LLCSAP_NULL,     "Null" },
51127675Sbms        { LLCSAP_GLOBAL,   "Global" },
52127675Sbms        { LLCSAP_8021B_I,  "802.1B I" },
53127675Sbms        { LLCSAP_8021B_G,  "802.1B G" },
54127675Sbms        { LLCSAP_IP,       "IP" },
55162021Ssam        { LLCSAP_SNA,      "SNA" },
56127675Sbms        { LLCSAP_PROWAYNM, "ProWay NM" },
57127675Sbms        { LLCSAP_8021D,    "STP" },
58127675Sbms        { LLCSAP_RS511,    "RS511" },
59127675Sbms        { LLCSAP_ISO8208,  "ISO8208" },
60127675Sbms        { LLCSAP_PROWAY,   "ProWay" },
61127675Sbms        { LLCSAP_SNAP,     "SNAP" },
62127675Sbms        { LLCSAP_IPX,      "IPX" },
63127675Sbms        { LLCSAP_NETBEUI,  "NetBeui" },
64127675Sbms        { LLCSAP_ISONS,    "OSI" },
65147904Ssam        { 0,               NULL },
66127675Sbms};
67127675Sbms
68162021Ssamstatic struct tok llc_cmd_values[] = {
6917680Spst	{ LLC_UI,	"ui" },
7017680Spst	{ LLC_TEST,	"test" },
7117680Spst	{ LLC_XID,	"xid" },
7217680Spst	{ LLC_UA,	"ua" },
7317680Spst	{ LLC_DISC,	"disc" },
7417680Spst	{ LLC_DM,	"dm" },
7517680Spst	{ LLC_SABME,	"sabme" },
7617680Spst	{ LLC_FRMR,	"frmr" },
7717680Spst	{ 0,		NULL }
7817680Spst};
7917680Spst
80162021Ssamstatic const struct tok llc_flag_values[] = {
81162021Ssam        { 0, "Command" },
82162021Ssam        { LLC_GSAP, "Response" },
83162021Ssam        { LLC_U_POLL, "Poll" },
84162021Ssam        { LLC_GSAP|LLC_U_POLL, "Final" },
85172686Smlaier        { LLC_IS_POLL, "Poll" },
86162021Ssam        { LLC_GSAP|LLC_IS_POLL, "Final" },
87162021Ssam	{ 0, NULL }
88162021Ssam};
89162021Ssam
90172686Smlaier
91172686Smlaierstatic const struct tok llc_ig_flag_values[] = {
92172686Smlaier        { 0, "Individual" },
93172686Smlaier        { LLC_IG, "Group" },
94172686Smlaier	{ 0, NULL }
95172686Smlaier};
96172686Smlaier
97172686Smlaier
98162021Ssamstatic const struct tok llc_supervisory_values[] = {
99162021Ssam        { 0, "Receiver Ready" },
100172686Smlaier        { 1, "Receiver not Ready" },
101172686Smlaier        { 2, "Reject" },
102162021Ssam	{ 0,             NULL }
103162021Ssam};
104162021Ssam
105162021Ssam
106147904Ssamstatic const struct tok cisco_values[] = {
107147904Ssam	{ PID_CISCO_CDP, "CDP" },
108172686Smlaier	{ PID_CISCO_VTP, "VTP" },
109172686Smlaier	{ PID_CISCO_DTP, "DTP" },
110190207Srpaulo	{ PID_CISCO_UDLD, "UDLD" },
111190207Srpaulo	{ PID_CISCO_PVST, "PVST" },
112147904Ssam	{ 0,             NULL }
113147904Ssam};
114147904Ssam
115147904Ssamstatic const struct tok bridged_values[] = {
116147904Ssam	{ PID_RFC2684_ETH_FCS,     "Ethernet + FCS" },
117147904Ssam	{ PID_RFC2684_ETH_NOFCS,   "Ethernet w/o FCS" },
118147904Ssam	{ PID_RFC2684_802_4_FCS,   "802.4 + FCS" },
119147904Ssam	{ PID_RFC2684_802_4_NOFCS, "802.4 w/o FCS" },
120147904Ssam	{ PID_RFC2684_802_5_FCS,   "Token Ring + FCS" },
121147904Ssam	{ PID_RFC2684_802_5_NOFCS, "Token Ring w/o FCS" },
122147904Ssam	{ PID_RFC2684_FDDI_FCS,    "FDDI + FCS" },
123147904Ssam	{ PID_RFC2684_FDDI_NOFCS,  "FDDI w/o FCS" },
124147904Ssam	{ PID_RFC2684_802_6_FCS,   "802.6 + FCS" },
125147904Ssam	{ PID_RFC2684_802_6_NOFCS, "802.6 w/o FCS" },
126147904Ssam	{ PID_RFC2684_BPDU,        "BPDU" },
127147904Ssam	{ 0,                       NULL },
128147904Ssam};
129147904Ssam
130172686Smlaierstatic const struct tok null_values[] = {
131172686Smlaier	{ 0,             NULL }
132172686Smlaier};
133172686Smlaier
134147904Ssamstruct oui_tok {
135147904Ssam	u_int32_t	oui;
136147904Ssam	const struct tok *tok;
137147904Ssam};
138147904Ssam
139147904Ssamstatic const struct oui_tok oui_to_tok[] = {
140147904Ssam	{ OUI_ENCAP_ETHER, ethertype_values },
141147904Ssam	{ OUI_CISCO_90, ethertype_values },	/* uses some Ethertype values */
142147904Ssam	{ OUI_APPLETALK, ethertype_values },	/* uses some Ethertype values */
143147904Ssam	{ OUI_CISCO, cisco_values },
144147904Ssam	{ OUI_RFC2684, bridged_values },	/* bridged, RFC 2427 FR or RFC 2864 ATM */
145147904Ssam	{ 0, NULL }
146147904Ssam};
147147904Ssam
14817680Spst/*
14917680Spst * Returns non-zero IFF it succeeds in printing the header
15017680Spst */
15117680Spstint
15217680Spstllc_print(const u_char *p, u_int length, u_int caplen,
15375118Sfenner	  const u_char *esrc, const u_char *edst, u_short *extracted_ethertype)
15417680Spst{
155162021Ssam	u_int8_t dsap_field, dsap, ssap_field, ssap;
15675118Sfenner	u_int16_t control;
157147904Ssam	int is_u;
15817680Spst	register int ret;
15917680Spst
160172686Smlaier	*extracted_ethertype = 0;
161172686Smlaier
16217680Spst	if (caplen < 3) {
16317680Spst		(void)printf("[|llc]");
16417680Spst		default_print((u_char *)p, caplen);
16517680Spst		return(0);
16617680Spst	}
16717680Spst
168162021Ssam	dsap_field = *p;
169162021Ssam	ssap_field = *(p + 1);
17017680Spst
171147904Ssam	/*
172147904Ssam	 * OK, what type of LLC frame is this?  The length
173147904Ssam	 * of the control field depends on that - I frames
174147904Ssam	 * have a two-byte control field, and U frames have
175147904Ssam	 * a one-byte control field.
176147904Ssam	 */
177147904Ssam	control = *(p + 2);
178147904Ssam	if ((control & LLC_U_FMT) == LLC_U_FMT) {
179147904Ssam		/*
180147904Ssam		 * U frame.
181147904Ssam		 */
182147904Ssam		is_u = 1;
183147904Ssam	} else {
184147904Ssam		/*
185147904Ssam		 * The control field in I and S frames is
186147904Ssam		 * 2 bytes...
187147904Ssam		 */
188147904Ssam		if (caplen < 4) {
189147904Ssam			(void)printf("[|llc]");
190147904Ssam			default_print((u_char *)p, caplen);
191147904Ssam			return(0);
192147904Ssam		}
193127675Sbms
19498527Sfenner		/*
195147904Ssam		 * ...and is little-endian.
196147904Ssam		 */
197147904Ssam		control = EXTRACT_LE_16BITS(p + 2);
198147904Ssam		is_u = 0;
199147904Ssam	}
200147904Ssam
201172686Smlaier	if (ssap_field == LLCSAP_GLOBAL && dsap_field == LLCSAP_GLOBAL) {
202147904Ssam		/*
20398527Sfenner		 * This is an Ethernet_802.3 IPX frame; it has an
20498527Sfenner		 * 802.3 header (i.e., an Ethernet header where the
20598527Sfenner		 * type/length field is <= ETHERMTU, i.e. it's a length
20698527Sfenner		 * field, not a type field), but has no 802.2 header -
20798527Sfenner		 * the IPX packet starts right after the Ethernet header,
20898527Sfenner		 * with a signature of two bytes of 0xFF (which is
20998527Sfenner		 * LLCSAP_GLOBAL).
21098527Sfenner		 *
21198527Sfenner		 * (It might also have been an Ethernet_802.3 IPX at
21298527Sfenner		 * one time, but got bridged onto another network,
21398527Sfenner		 * such as an 802.11 network; this has appeared in at
21498527Sfenner		 * least one capture file.)
21598527Sfenner		 */
216146778Ssam
217146778Ssam            if (eflag)
218162021Ssam		printf("IPX 802.3: ");
219146778Ssam
220146778Ssam            ipx_print(p, length);
221146778Ssam            return (1);
22217680Spst	}
22375118Sfenner
224172686Smlaier	dsap = dsap_field & ~LLC_IG;
225172686Smlaier	ssap = ssap_field & ~LLC_GSAP;
226172686Smlaier
227147904Ssam	if (eflag) {
228172686Smlaier                printf("LLC, dsap %s (0x%02x) %s, ssap %s (0x%02x) %s",
229162021Ssam                       tok2str(llc_values, "Unknown", dsap),
230162021Ssam                       dsap,
231172686Smlaier                       tok2str(llc_ig_flag_values, "Unknown", dsap_field & LLC_IG),
232162021Ssam                       tok2str(llc_values, "Unknown", ssap),
233172686Smlaier                       ssap,
234172686Smlaier                       tok2str(llc_flag_values, "Unknown", ssap_field & LLC_GSAP));
235162021Ssam
236147904Ssam		if (is_u) {
237172686Smlaier			printf(", ctrl 0x%02x: ", control);
238147904Ssam		} else {
239172686Smlaier			printf(", ctrl 0x%04x: ", control);
240147904Ssam		}
241147904Ssam	}
242147904Ssam
243147904Ssam	if (ssap == LLCSAP_8021D && dsap == LLCSAP_8021D &&
244147904Ssam	    control == LLC_UI) {
245147904Ssam		stp_print(p+3, length-3);
24675118Sfenner		return (1);
24775118Sfenner	}
24898527Sfenner
249147904Ssam	if (ssap == LLCSAP_IP && dsap == LLCSAP_IP &&
250147904Ssam	    control == LLC_UI) {
251146778Ssam		ip_print(gndo, p+4, length-4);
252127675Sbms		return (1);
253127675Sbms	}
254127675Sbms
255147904Ssam	if (ssap == LLCSAP_IPX && dsap == LLCSAP_IPX &&
256147904Ssam	    control == LLC_UI) {
25798527Sfenner		/*
25898527Sfenner		 * This is an Ethernet_802.2 IPX frame, with an 802.3
25998527Sfenner		 * header and an 802.2 LLC header with the source and
26098527Sfenner		 * destination SAPs being the IPX SAP.
26198527Sfenner		 *
26298527Sfenner		 * Skip DSAP, LSAP, and control field.
26398527Sfenner		 */
264162021Ssam                if (eflag)
265162021Ssam                        printf("IPX 802.2: ");
266162021Ssam
267147904Ssam		ipx_print(p+3, length-3);
26898527Sfenner		return (1);
26998527Sfenner	}
27098527Sfenner
27198527Sfenner#ifdef TCPDUMP_DO_SMB
272147904Ssam	if (ssap == LLCSAP_NETBEUI && dsap == LLCSAP_NETBEUI
273147904Ssam	    && (!(control & LLC_S_FMT) || control == LLC_U_FMT)) {
27456896Sfenner		/*
27556896Sfenner		 * we don't actually have a full netbeui parser yet, but the
27656896Sfenner		 * smb parser can handle many smb-in-netbeui packets, which
27756896Sfenner		 * is very useful, so we call that
27875118Sfenner		 *
27975118Sfenner		 * We don't call it for S frames, however, just I frames
28075118Sfenner		 * (which are frames that don't have the low-order bit,
28175118Sfenner		 * LLC_S_FMT, set in the first byte of the control field)
28275118Sfenner		 * and UI frames (whose control field is just 3, LLC_U_FMT).
28356896Sfenner		 */
28475118Sfenner
28575118Sfenner		/*
286147904Ssam		 * Skip the LLC header.
28775118Sfenner		 */
288147904Ssam		if (is_u) {
289147904Ssam			p += 3;
290147904Ssam			length -= 3;
291147904Ssam			caplen -= 3;
29275118Sfenner		} else {
293147904Ssam			p += 4;
294147904Ssam			length -= 4;
295147904Ssam			caplen -= 4;
29675118Sfenner		}
29798527Sfenner		netbeui_print(control, p, length);
29856896Sfenner		return (1);
29956896Sfenner	}
30098527Sfenner#endif
301147904Ssam	if (ssap == LLCSAP_ISONS && dsap == LLCSAP_ISONS
302147904Ssam	    && control == LLC_UI) {
303127675Sbms		isoclns_print(p + 3, length - 3, caplen - 3);
30417680Spst		return (1);
30517680Spst	}
30617680Spst
307147904Ssam	if (ssap == LLCSAP_SNAP && dsap == LLCSAP_SNAP
308147904Ssam	    && control == LLC_UI) {
309127675Sbms		/*
310127675Sbms		 * XXX - what *is* the right bridge pad value here?
311127675Sbms		 * Does anybody ever bridge one form of LAN traffic
312127675Sbms		 * over a networking type that uses 802.2 LLC?
313127675Sbms		 */
314214478Srpaulo		ret = snap_print(p+3, length-3, caplen-3, 2);
315127675Sbms		if (ret)
316127675Sbms			return (ret);
31717680Spst	}
31817680Spst
319147904Ssam	if (!eflag) {
320162021Ssam		if (ssap == dsap) {
321147904Ssam			if (esrc == NULL || edst == NULL)
322162021Ssam				(void)printf("%s ", tok2str(llc_values, "Unknown DSAP 0x%02x", dsap));
323147904Ssam			else
324147904Ssam				(void)printf("%s > %s %s ",
325147904Ssam						etheraddr_string(esrc),
326147904Ssam						etheraddr_string(edst),
327162021Ssam						tok2str(llc_values, "Unknown DSAP 0x%02x", dsap));
328147904Ssam		} else {
329147904Ssam			if (esrc == NULL || edst == NULL)
330147904Ssam				(void)printf("%s > %s ",
331162021Ssam                                        tok2str(llc_values, "Unknown SSAP 0x%02x", ssap),
332162021Ssam					tok2str(llc_values, "Unknown DSAP 0x%02x", dsap));
333147904Ssam			else
334147904Ssam				(void)printf("%s %s > %s %s ",
33517680Spst					etheraddr_string(esrc),
336162021Ssam                                        tok2str(llc_values, "Unknown SSAP 0x%02x", ssap),
33717680Spst					etheraddr_string(edst),
338162021Ssam					tok2str(llc_values, "Unknown DSAP 0x%02x", dsap));
339147904Ssam		}
34017680Spst	}
34117680Spst
342147904Ssam	if (is_u) {
343162021Ssam		printf("Unnumbered, %s, Flags [%s], length %u",
344162021Ssam                       tok2str(llc_cmd_values, "%02x", LLC_U_CMD(control)),
345172686Smlaier                       tok2str(llc_flag_values,"?",(ssap_field & LLC_GSAP) | (control & LLC_U_POLL)),
346162021Ssam                       length);
34775118Sfenner
34817680Spst		p += 3;
34917680Spst		length -= 3;
35017680Spst		caplen -= 3;
35117680Spst
352147904Ssam		if ((control & ~LLC_U_POLL) == LLC_XID) {
35356896Sfenner			if (*p == LLC_XID_FI) {
35456896Sfenner				printf(": %02x %02x", p[1], p[2]);
35556896Sfenner				p += 3;
35656896Sfenner				length -= 3;
35756896Sfenner				caplen -= 3;
35856896Sfenner			}
35917680Spst		}
36017680Spst	} else {
36175118Sfenner		if ((control & LLC_S_FMT) == LLC_S_FMT) {
362162021Ssam			(void)printf("Supervisory, %s, rcv seq %u, Flags [%s], length %u",
363162021Ssam				tok2str(llc_supervisory_values,"?",LLC_S_CMD(control)),
36475118Sfenner				LLC_IS_NR(control),
365172686Smlaier				tok2str(llc_flag_values,"?",(ssap_field & LLC_GSAP) | (control & LLC_IS_POLL)),
366162021Ssam                                length);
36717680Spst		} else {
368162021Ssam			(void)printf("Information, send seq %u, rcv seq %u, Flags [%s], length %u",
36975118Sfenner				LLC_I_NS(control),
37075118Sfenner				LLC_IS_NR(control),
371172686Smlaier				tok2str(llc_flag_values,"?",(ssap_field & LLC_GSAP) | (control & LLC_IS_POLL)),
372162021Ssam                                length);
37317680Spst		}
37417680Spst		p += 4;
37517680Spst		length -= 4;
37617680Spst		caplen -= 4;
37717680Spst	}
37817680Spst	return(1);
37917680Spst}
380127675Sbms
381127675Sbmsint
382214478Srpaulosnap_print(const u_char *p, u_int length, u_int caplen, u_int bridge_pad)
383127675Sbms{
384147904Ssam	u_int32_t orgcode;
385147904Ssam	register u_short et;
386127675Sbms	register int ret;
387127675Sbms
388147904Ssam	TCHECK2(*p, 5);
389147904Ssam	orgcode = EXTRACT_24BITS(p);
390147904Ssam	et = EXTRACT_16BITS(p + 3);
391147904Ssam
392147904Ssam	if (eflag) {
393172686Smlaier		const struct tok *tok = null_values;
394147904Ssam		const struct oui_tok *otp;
395147904Ssam
396147904Ssam		for (otp = &oui_to_tok[0]; otp->tok != NULL; otp++) {
397147904Ssam			if (otp->oui == orgcode) {
398147904Ssam				tok = otp->tok;
399147904Ssam				break;
400147904Ssam			}
401147904Ssam		}
402147904Ssam		(void)printf("oui %s (0x%06x), %s %s (0x%04x): ",
403147904Ssam		     tok2str(oui_values, "Unknown", orgcode),
404147904Ssam		     orgcode,
405147904Ssam		     (orgcode == 0x000000 ? "ethertype" : "pid"),
406147904Ssam		     tok2str(tok, "Unknown", et),
407147904Ssam		     et);
408147904Ssam	}
409147904Ssam	p += 5;
410147904Ssam	length -= 5;
411147904Ssam	caplen -= 5;
412147904Ssam
413127675Sbms	switch (orgcode) {
414127675Sbms	case OUI_ENCAP_ETHER:
415127675Sbms	case OUI_CISCO_90:
416127675Sbms		/*
417127675Sbms		 * This is an encapsulated Ethernet packet,
418127675Sbms		 * or a packet bridged by some piece of
419127675Sbms		 * Cisco hardware; the protocol ID is
420127675Sbms		 * an Ethernet protocol type.
421127675Sbms		 */
422235530Sdelphij		ret = ethertype_print(gndo, et, p, length, caplen);
423127675Sbms		if (ret)
424127675Sbms			return (ret);
425127675Sbms		break;
426127675Sbms
427127675Sbms	case OUI_APPLETALK:
428127675Sbms		if (et == ETHERTYPE_ATALK) {
429127675Sbms			/*
430127675Sbms			 * No, I have no idea why Apple used one
431127675Sbms			 * of their own OUIs, rather than
432127675Sbms			 * 0x000000, and an Ethernet packet
433127675Sbms			 * type, for Appletalk data packets,
434127675Sbms			 * but used 0x000000 and an Ethernet
435127675Sbms			 * packet type for AARP packets.
436127675Sbms			 */
437235530Sdelphij			ret = ethertype_print(gndo, et, p, length, caplen);
438127675Sbms			if (ret)
439127675Sbms				return (ret);
440127675Sbms		}
441127675Sbms		break;
442127675Sbms
443127675Sbms	case OUI_CISCO:
444190207Srpaulo                switch (et) {
445190207Srpaulo                case PID_CISCO_CDP:
446190207Srpaulo                        cdp_print(p, length, caplen);
447190207Srpaulo                        return (1);
448190207Srpaulo                case PID_CISCO_DTP:
449190207Srpaulo                        dtp_print(p, length);
450190207Srpaulo                        return (1);
451190207Srpaulo                case PID_CISCO_UDLD:
452190207Srpaulo                        udld_print(p, length);
453190207Srpaulo                        return (1);
454190207Srpaulo                case PID_CISCO_VTP:
455190207Srpaulo                        vtp_print(p, length);
456190207Srpaulo                        return (1);
457190207Srpaulo                case PID_CISCO_PVST:
458190207Srpaulo                        stp_print(p, length);
459190207Srpaulo                        return (1);
460190207Srpaulo                default:
461190207Srpaulo                        break;
462190207Srpaulo                }
463127675Sbms
464127675Sbms	case OUI_RFC2684:
465127675Sbms		switch (et) {
466127675Sbms
467127675Sbms		case PID_RFC2684_ETH_FCS:
468127675Sbms		case PID_RFC2684_ETH_NOFCS:
469127675Sbms			/*
470127675Sbms			 * XXX - remove the last two bytes for
471127675Sbms			 * PID_RFC2684_ETH_FCS?
472127675Sbms			 */
473127675Sbms			/*
474127675Sbms			 * Skip the padding.
475127675Sbms			 */
476147904Ssam			TCHECK2(*p, bridge_pad);
477127675Sbms			caplen -= bridge_pad;
478127675Sbms			length -= bridge_pad;
479127675Sbms			p += bridge_pad;
480127675Sbms
481127675Sbms			/*
482127675Sbms			 * What remains is an Ethernet packet.
483127675Sbms			 */
484235530Sdelphij			ether_print(gndo, p, length, caplen, NULL, NULL);
485127675Sbms			return (1);
486127675Sbms
487127675Sbms		case PID_RFC2684_802_5_FCS:
488127675Sbms		case PID_RFC2684_802_5_NOFCS:
489127675Sbms			/*
490127675Sbms			 * XXX - remove the last two bytes for
491127675Sbms			 * PID_RFC2684_ETH_FCS?
492127675Sbms			 */
493127675Sbms			/*
494127675Sbms			 * Skip the padding, but not the Access
495127675Sbms			 * Control field.
496127675Sbms			 */
497147904Ssam			TCHECK2(*p, bridge_pad);
498127675Sbms			caplen -= bridge_pad;
499127675Sbms			length -= bridge_pad;
500127675Sbms			p += bridge_pad;
501127675Sbms
502127675Sbms			/*
503127675Sbms			 * What remains is an 802.5 Token Ring
504127675Sbms			 * packet.
505127675Sbms			 */
506127675Sbms			token_print(p, length, caplen);
507127675Sbms			return (1);
508127675Sbms
509127675Sbms		case PID_RFC2684_FDDI_FCS:
510127675Sbms		case PID_RFC2684_FDDI_NOFCS:
511127675Sbms			/*
512127675Sbms			 * XXX - remove the last two bytes for
513127675Sbms			 * PID_RFC2684_ETH_FCS?
514127675Sbms			 */
515127675Sbms			/*
516127675Sbms			 * Skip the padding.
517127675Sbms			 */
518147904Ssam			TCHECK2(*p, bridge_pad + 1);
519127675Sbms			caplen -= bridge_pad + 1;
520127675Sbms			length -= bridge_pad + 1;
521127675Sbms			p += bridge_pad + 1;
522127675Sbms
523127675Sbms			/*
524127675Sbms			 * What remains is an FDDI packet.
525127675Sbms			 */
526127675Sbms			fddi_print(p, length, caplen);
527127675Sbms			return (1);
528127675Sbms
529127675Sbms		case PID_RFC2684_BPDU:
530127675Sbms			stp_print(p, length);
531127675Sbms			return (1);
532127675Sbms		}
533127675Sbms	}
534127675Sbms	return (0);
535147904Ssam
536147904Ssamtrunc:
537147904Ssam	(void)printf("[|snap]");
538147904Ssam	return (1);
539127675Sbms}
540146778Ssam
541146778Ssam
542146778Ssam/*
543146778Ssam * Local Variables:
544146778Ssam * c-style: whitesmith
545146778Ssam * c-basic-offset: 8
546146778Ssam * End:
547146778Ssam */
548