xref: /minix/external/bsd/tcpdump/dist/print-llc.c (revision b636d99d)
1*b636d99dSDavid van Moolenbroek /*
2*b636d99dSDavid van Moolenbroek  * Copyright (c) 1992, 1993, 1994, 1995, 1996, 1997
3*b636d99dSDavid van Moolenbroek  *	The Regents of the University of California.  All rights reserved.
4*b636d99dSDavid van Moolenbroek  *
5*b636d99dSDavid van Moolenbroek  * Redistribution and use in source and binary forms, with or without
6*b636d99dSDavid van Moolenbroek  * modification, are permitted provided that: (1) source code distributions
7*b636d99dSDavid van Moolenbroek  * retain the above copyright notice and this paragraph in its entirety, (2)
8*b636d99dSDavid van Moolenbroek  * distributions including binary code include the above copyright notice and
9*b636d99dSDavid van Moolenbroek  * this paragraph in its entirety in the documentation or other materials
10*b636d99dSDavid van Moolenbroek  * provided with the distribution, and (3) all advertising materials mentioning
11*b636d99dSDavid van Moolenbroek  * features or use of this software display the following acknowledgement:
12*b636d99dSDavid van Moolenbroek  * ``This product includes software developed by the University of California,
13*b636d99dSDavid van Moolenbroek  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14*b636d99dSDavid van Moolenbroek  * the University nor the names of its contributors may be used to endorse
15*b636d99dSDavid van Moolenbroek  * or promote products derived from this software without specific prior
16*b636d99dSDavid van Moolenbroek  * written permission.
17*b636d99dSDavid van Moolenbroek  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18*b636d99dSDavid van Moolenbroek  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19*b636d99dSDavid van Moolenbroek  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20*b636d99dSDavid van Moolenbroek  *
21*b636d99dSDavid van Moolenbroek  * Code by Matt Thomas, Digital Equipment Corporation
22*b636d99dSDavid van Moolenbroek  *	with an awful lot of hacking by Jeffrey Mogul, DECWRL
23*b636d99dSDavid van Moolenbroek  */
24*b636d99dSDavid van Moolenbroek 
25*b636d99dSDavid van Moolenbroek #include <sys/cdefs.h>
26*b636d99dSDavid van Moolenbroek #ifndef lint
27*b636d99dSDavid van Moolenbroek __RCSID("$NetBSD: print-llc.c,v 1.6 2015/03/31 21:59:35 christos Exp $");
28*b636d99dSDavid van Moolenbroek #endif
29*b636d99dSDavid van Moolenbroek 
30*b636d99dSDavid van Moolenbroek #define NETDISSECT_REWORKED
31*b636d99dSDavid van Moolenbroek #ifdef HAVE_CONFIG_H
32*b636d99dSDavid van Moolenbroek #include "config.h"
33*b636d99dSDavid van Moolenbroek #endif
34*b636d99dSDavid van Moolenbroek 
35*b636d99dSDavid van Moolenbroek #include <tcpdump-stdinc.h>
36*b636d99dSDavid van Moolenbroek 
37*b636d99dSDavid van Moolenbroek #include "interface.h"
38*b636d99dSDavid van Moolenbroek #include "addrtoname.h"
39*b636d99dSDavid van Moolenbroek #include "extract.h"			/* must come after interface.h */
40*b636d99dSDavid van Moolenbroek 
41*b636d99dSDavid van Moolenbroek #include "llc.h"
42*b636d99dSDavid van Moolenbroek #include "ethertype.h"
43*b636d99dSDavid van Moolenbroek #include "oui.h"
44*b636d99dSDavid van Moolenbroek 
45*b636d99dSDavid van Moolenbroek static const struct tok llc_values[] = {
46*b636d99dSDavid van Moolenbroek         { LLCSAP_NULL,     "Null" },
47*b636d99dSDavid van Moolenbroek         { LLCSAP_GLOBAL,   "Global" },
48*b636d99dSDavid van Moolenbroek         { LLCSAP_8021B_I,  "802.1B I" },
49*b636d99dSDavid van Moolenbroek         { LLCSAP_8021B_G,  "802.1B G" },
50*b636d99dSDavid van Moolenbroek         { LLCSAP_IP,       "IP" },
51*b636d99dSDavid van Moolenbroek         { LLCSAP_SNA,      "SNA" },
52*b636d99dSDavid van Moolenbroek         { LLCSAP_PROWAYNM, "ProWay NM" },
53*b636d99dSDavid van Moolenbroek         { LLCSAP_8021D,    "STP" },
54*b636d99dSDavid van Moolenbroek         { LLCSAP_RS511,    "RS511" },
55*b636d99dSDavid van Moolenbroek         { LLCSAP_ISO8208,  "ISO8208" },
56*b636d99dSDavid van Moolenbroek         { LLCSAP_PROWAY,   "ProWay" },
57*b636d99dSDavid van Moolenbroek         { LLCSAP_SNAP,     "SNAP" },
58*b636d99dSDavid van Moolenbroek         { LLCSAP_IPX,      "IPX" },
59*b636d99dSDavid van Moolenbroek         { LLCSAP_NETBEUI,  "NetBeui" },
60*b636d99dSDavid van Moolenbroek         { LLCSAP_ISONS,    "OSI" },
61*b636d99dSDavid van Moolenbroek         { 0,               NULL },
62*b636d99dSDavid van Moolenbroek };
63*b636d99dSDavid van Moolenbroek 
64*b636d99dSDavid van Moolenbroek static const struct tok llc_cmd_values[] = {
65*b636d99dSDavid van Moolenbroek 	{ LLC_UI,	"ui" },
66*b636d99dSDavid van Moolenbroek 	{ LLC_TEST,	"test" },
67*b636d99dSDavid van Moolenbroek 	{ LLC_XID,	"xid" },
68*b636d99dSDavid van Moolenbroek 	{ LLC_UA,	"ua" },
69*b636d99dSDavid van Moolenbroek 	{ LLC_DISC,	"disc" },
70*b636d99dSDavid van Moolenbroek 	{ LLC_DM,	"dm" },
71*b636d99dSDavid van Moolenbroek 	{ LLC_SABME,	"sabme" },
72*b636d99dSDavid van Moolenbroek 	{ LLC_FRMR,	"frmr" },
73*b636d99dSDavid van Moolenbroek 	{ 0,		NULL }
74*b636d99dSDavid van Moolenbroek };
75*b636d99dSDavid van Moolenbroek 
76*b636d99dSDavid van Moolenbroek static const struct tok llc_flag_values[] = {
77*b636d99dSDavid van Moolenbroek         { 0, "Command" },
78*b636d99dSDavid van Moolenbroek         { LLC_GSAP, "Response" },
79*b636d99dSDavid van Moolenbroek         { LLC_U_POLL, "Poll" },
80*b636d99dSDavid van Moolenbroek         { LLC_GSAP|LLC_U_POLL, "Final" },
81*b636d99dSDavid van Moolenbroek         { LLC_IS_POLL, "Poll" },
82*b636d99dSDavid van Moolenbroek         { LLC_GSAP|LLC_IS_POLL, "Final" },
83*b636d99dSDavid van Moolenbroek 	{ 0, NULL }
84*b636d99dSDavid van Moolenbroek };
85*b636d99dSDavid van Moolenbroek 
86*b636d99dSDavid van Moolenbroek 
87*b636d99dSDavid van Moolenbroek static const struct tok llc_ig_flag_values[] = {
88*b636d99dSDavid van Moolenbroek         { 0, "Individual" },
89*b636d99dSDavid van Moolenbroek         { LLC_IG, "Group" },
90*b636d99dSDavid van Moolenbroek 	{ 0, NULL }
91*b636d99dSDavid van Moolenbroek };
92*b636d99dSDavid van Moolenbroek 
93*b636d99dSDavid van Moolenbroek 
94*b636d99dSDavid van Moolenbroek static const struct tok llc_supervisory_values[] = {
95*b636d99dSDavid van Moolenbroek         { 0, "Receiver Ready" },
96*b636d99dSDavid van Moolenbroek         { 1, "Receiver not Ready" },
97*b636d99dSDavid van Moolenbroek         { 2, "Reject" },
98*b636d99dSDavid van Moolenbroek 	{ 0,             NULL }
99*b636d99dSDavid van Moolenbroek };
100*b636d99dSDavid van Moolenbroek 
101*b636d99dSDavid van Moolenbroek 
102*b636d99dSDavid van Moolenbroek static const struct tok cisco_values[] = {
103*b636d99dSDavid van Moolenbroek 	{ PID_CISCO_CDP, "CDP" },
104*b636d99dSDavid van Moolenbroek 	{ PID_CISCO_VTP, "VTP" },
105*b636d99dSDavid van Moolenbroek 	{ PID_CISCO_DTP, "DTP" },
106*b636d99dSDavid van Moolenbroek 	{ PID_CISCO_UDLD, "UDLD" },
107*b636d99dSDavid van Moolenbroek 	{ PID_CISCO_PVST, "PVST" },
108*b636d99dSDavid van Moolenbroek 	{ PID_CISCO_VLANBRIDGE, "VLAN Bridge" },
109*b636d99dSDavid van Moolenbroek 	{ 0,             NULL }
110*b636d99dSDavid van Moolenbroek };
111*b636d99dSDavid van Moolenbroek 
112*b636d99dSDavid van Moolenbroek static const struct tok bridged_values[] = {
113*b636d99dSDavid van Moolenbroek 	{ PID_RFC2684_ETH_FCS,     "Ethernet + FCS" },
114*b636d99dSDavid van Moolenbroek 	{ PID_RFC2684_ETH_NOFCS,   "Ethernet w/o FCS" },
115*b636d99dSDavid van Moolenbroek 	{ PID_RFC2684_802_4_FCS,   "802.4 + FCS" },
116*b636d99dSDavid van Moolenbroek 	{ PID_RFC2684_802_4_NOFCS, "802.4 w/o FCS" },
117*b636d99dSDavid van Moolenbroek 	{ PID_RFC2684_802_5_FCS,   "Token Ring + FCS" },
118*b636d99dSDavid van Moolenbroek 	{ PID_RFC2684_802_5_NOFCS, "Token Ring w/o FCS" },
119*b636d99dSDavid van Moolenbroek 	{ PID_RFC2684_FDDI_FCS,    "FDDI + FCS" },
120*b636d99dSDavid van Moolenbroek 	{ PID_RFC2684_FDDI_NOFCS,  "FDDI w/o FCS" },
121*b636d99dSDavid van Moolenbroek 	{ PID_RFC2684_802_6_FCS,   "802.6 + FCS" },
122*b636d99dSDavid van Moolenbroek 	{ PID_RFC2684_802_6_NOFCS, "802.6 w/o FCS" },
123*b636d99dSDavid van Moolenbroek 	{ PID_RFC2684_BPDU,        "BPDU" },
124*b636d99dSDavid van Moolenbroek 	{ 0,                       NULL },
125*b636d99dSDavid van Moolenbroek };
126*b636d99dSDavid van Moolenbroek 
127*b636d99dSDavid van Moolenbroek static const struct tok null_values[] = {
128*b636d99dSDavid van Moolenbroek 	{ 0,             NULL }
129*b636d99dSDavid van Moolenbroek };
130*b636d99dSDavid van Moolenbroek 
131*b636d99dSDavid van Moolenbroek struct oui_tok {
132*b636d99dSDavid van Moolenbroek 	uint32_t	oui;
133*b636d99dSDavid van Moolenbroek 	const struct tok *tok;
134*b636d99dSDavid van Moolenbroek };
135*b636d99dSDavid van Moolenbroek 
136*b636d99dSDavid van Moolenbroek static const struct oui_tok oui_to_tok[] = {
137*b636d99dSDavid van Moolenbroek 	{ OUI_ENCAP_ETHER, ethertype_values },
138*b636d99dSDavid van Moolenbroek 	{ OUI_CISCO_90, ethertype_values },	/* uses some Ethertype values */
139*b636d99dSDavid van Moolenbroek 	{ OUI_APPLETALK, ethertype_values },	/* uses some Ethertype values */
140*b636d99dSDavid van Moolenbroek 	{ OUI_CISCO, cisco_values },
141*b636d99dSDavid van Moolenbroek 	{ OUI_RFC2684, bridged_values },	/* bridged, RFC 2427 FR or RFC 2864 ATM */
142*b636d99dSDavid van Moolenbroek 	{ 0, NULL }
143*b636d99dSDavid van Moolenbroek };
144*b636d99dSDavid van Moolenbroek 
145*b636d99dSDavid van Moolenbroek /*
146*b636d99dSDavid van Moolenbroek  * Returns non-zero IFF it succeeds in printing the header
147*b636d99dSDavid van Moolenbroek  */
148*b636d99dSDavid van Moolenbroek int
llc_print(netdissect_options * ndo,const u_char * p,u_int length,u_int caplen,const u_char * esrc,const u_char * edst,u_short * extracted_ethertype)149*b636d99dSDavid van Moolenbroek llc_print(netdissect_options *ndo, const u_char *p, u_int length, u_int caplen,
150*b636d99dSDavid van Moolenbroek 	  const u_char *esrc, const u_char *edst, u_short *extracted_ethertype)
151*b636d99dSDavid van Moolenbroek {
152*b636d99dSDavid van Moolenbroek 	uint8_t dsap_field, dsap, ssap_field, ssap;
153*b636d99dSDavid van Moolenbroek 	uint16_t control;
154*b636d99dSDavid van Moolenbroek 	int is_u;
155*b636d99dSDavid van Moolenbroek 	register int ret;
156*b636d99dSDavid van Moolenbroek 
157*b636d99dSDavid van Moolenbroek 	*extracted_ethertype = 0;
158*b636d99dSDavid van Moolenbroek 
159*b636d99dSDavid van Moolenbroek 	if (caplen < 3 || length < 3) {
160*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "[|llc]"));
161*b636d99dSDavid van Moolenbroek 		ND_DEFAULTPRINT((u_char *)p, caplen);
162*b636d99dSDavid van Moolenbroek 		return (1);
163*b636d99dSDavid van Moolenbroek 	}
164*b636d99dSDavid van Moolenbroek 
165*b636d99dSDavid van Moolenbroek 	dsap_field = *p;
166*b636d99dSDavid van Moolenbroek 	ssap_field = *(p + 1);
167*b636d99dSDavid van Moolenbroek 
168*b636d99dSDavid van Moolenbroek 	/*
169*b636d99dSDavid van Moolenbroek 	 * OK, what type of LLC frame is this?  The length
170*b636d99dSDavid van Moolenbroek 	 * of the control field depends on that - I frames
171*b636d99dSDavid van Moolenbroek 	 * have a two-byte control field, and U frames have
172*b636d99dSDavid van Moolenbroek 	 * a one-byte control field.
173*b636d99dSDavid van Moolenbroek 	 */
174*b636d99dSDavid van Moolenbroek 	control = *(p + 2);
175*b636d99dSDavid van Moolenbroek 	if ((control & LLC_U_FMT) == LLC_U_FMT) {
176*b636d99dSDavid van Moolenbroek 		/*
177*b636d99dSDavid van Moolenbroek 		 * U frame.
178*b636d99dSDavid van Moolenbroek 		 */
179*b636d99dSDavid van Moolenbroek 		is_u = 1;
180*b636d99dSDavid van Moolenbroek 	} else {
181*b636d99dSDavid van Moolenbroek 		/*
182*b636d99dSDavid van Moolenbroek 		 * The control field in I and S frames is
183*b636d99dSDavid van Moolenbroek 		 * 2 bytes...
184*b636d99dSDavid van Moolenbroek 		 */
185*b636d99dSDavid van Moolenbroek 		if (caplen < 4 || length < 4) {
186*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, "[|llc]"));
187*b636d99dSDavid van Moolenbroek 			ND_DEFAULTPRINT((u_char *)p, caplen);
188*b636d99dSDavid van Moolenbroek 			return (1);
189*b636d99dSDavid van Moolenbroek 		}
190*b636d99dSDavid van Moolenbroek 
191*b636d99dSDavid van Moolenbroek 		/*
192*b636d99dSDavid van Moolenbroek 		 * ...and is little-endian.
193*b636d99dSDavid van Moolenbroek 		 */
194*b636d99dSDavid van Moolenbroek 		control = EXTRACT_LE_16BITS(p + 2);
195*b636d99dSDavid van Moolenbroek 		is_u = 0;
196*b636d99dSDavid van Moolenbroek 	}
197*b636d99dSDavid van Moolenbroek 
198*b636d99dSDavid van Moolenbroek 	if (ssap_field == LLCSAP_GLOBAL && dsap_field == LLCSAP_GLOBAL) {
199*b636d99dSDavid van Moolenbroek 		/*
200*b636d99dSDavid van Moolenbroek 		 * This is an Ethernet_802.3 IPX frame; it has an
201*b636d99dSDavid van Moolenbroek 		 * 802.3 header (i.e., an Ethernet header where the
202*b636d99dSDavid van Moolenbroek 		 * type/length field is <= ETHERMTU, i.e. it's a length
203*b636d99dSDavid van Moolenbroek 		 * field, not a type field), but has no 802.2 header -
204*b636d99dSDavid van Moolenbroek 		 * the IPX packet starts right after the Ethernet header,
205*b636d99dSDavid van Moolenbroek 		 * with a signature of two bytes of 0xFF (which is
206*b636d99dSDavid van Moolenbroek 		 * LLCSAP_GLOBAL).
207*b636d99dSDavid van Moolenbroek 		 *
208*b636d99dSDavid van Moolenbroek 		 * (It might also have been an Ethernet_802.3 IPX at
209*b636d99dSDavid van Moolenbroek 		 * one time, but got bridged onto another network,
210*b636d99dSDavid van Moolenbroek 		 * such as an 802.11 network; this has appeared in at
211*b636d99dSDavid van Moolenbroek 		 * least one capture file.)
212*b636d99dSDavid van Moolenbroek 		 */
213*b636d99dSDavid van Moolenbroek 
214*b636d99dSDavid van Moolenbroek             if (ndo->ndo_eflag)
215*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "IPX 802.3: "));
216*b636d99dSDavid van Moolenbroek 
217*b636d99dSDavid van Moolenbroek             ipx_print(ndo, p, length);
218*b636d99dSDavid van Moolenbroek             return (1);
219*b636d99dSDavid van Moolenbroek 	}
220*b636d99dSDavid van Moolenbroek 
221*b636d99dSDavid van Moolenbroek 	dsap = dsap_field & ~LLC_IG;
222*b636d99dSDavid van Moolenbroek 	ssap = ssap_field & ~LLC_GSAP;
223*b636d99dSDavid van Moolenbroek 
224*b636d99dSDavid van Moolenbroek 	if (ndo->ndo_eflag) {
225*b636d99dSDavid van Moolenbroek                 ND_PRINT((ndo, "LLC, dsap %s (0x%02x) %s, ssap %s (0x%02x) %s",
226*b636d99dSDavid van Moolenbroek                        tok2str(llc_values, "Unknown", dsap),
227*b636d99dSDavid van Moolenbroek                        dsap,
228*b636d99dSDavid van Moolenbroek                        tok2str(llc_ig_flag_values, "Unknown", dsap_field & LLC_IG),
229*b636d99dSDavid van Moolenbroek                        tok2str(llc_values, "Unknown", ssap),
230*b636d99dSDavid van Moolenbroek                        ssap,
231*b636d99dSDavid van Moolenbroek                        tok2str(llc_flag_values, "Unknown", ssap_field & LLC_GSAP)));
232*b636d99dSDavid van Moolenbroek 
233*b636d99dSDavid van Moolenbroek 		if (is_u) {
234*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, ", ctrl 0x%02x: ", control));
235*b636d99dSDavid van Moolenbroek 		} else {
236*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, ", ctrl 0x%04x: ", control));
237*b636d99dSDavid van Moolenbroek 		}
238*b636d99dSDavid van Moolenbroek 	}
239*b636d99dSDavid van Moolenbroek 
240*b636d99dSDavid van Moolenbroek 	if (ssap == LLCSAP_8021D && dsap == LLCSAP_8021D &&
241*b636d99dSDavid van Moolenbroek 	    control == LLC_UI) {
242*b636d99dSDavid van Moolenbroek 		stp_print(ndo, p+3, length-3);
243*b636d99dSDavid van Moolenbroek 		return (1);
244*b636d99dSDavid van Moolenbroek 	}
245*b636d99dSDavid van Moolenbroek 
246*b636d99dSDavid van Moolenbroek 	if (ssap == LLCSAP_IP && dsap == LLCSAP_IP &&
247*b636d99dSDavid van Moolenbroek 	    control == LLC_UI) {
248*b636d99dSDavid van Moolenbroek 		if (caplen < 4 || length < 4) {
249*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, "[|llc]"));
250*b636d99dSDavid van Moolenbroek 			ND_DEFAULTPRINT((u_char *)p, caplen);
251*b636d99dSDavid van Moolenbroek 			return (1);
252*b636d99dSDavid van Moolenbroek 		}
253*b636d99dSDavid van Moolenbroek 		ip_print(ndo, p+4, length-4);
254*b636d99dSDavid van Moolenbroek 		return (1);
255*b636d99dSDavid van Moolenbroek 	}
256*b636d99dSDavid van Moolenbroek 
257*b636d99dSDavid van Moolenbroek 	if (ssap == LLCSAP_IPX && dsap == LLCSAP_IPX &&
258*b636d99dSDavid van Moolenbroek 	    control == LLC_UI) {
259*b636d99dSDavid van Moolenbroek 		/*
260*b636d99dSDavid van Moolenbroek 		 * This is an Ethernet_802.2 IPX frame, with an 802.3
261*b636d99dSDavid van Moolenbroek 		 * header and an 802.2 LLC header with the source and
262*b636d99dSDavid van Moolenbroek 		 * destination SAPs being the IPX SAP.
263*b636d99dSDavid van Moolenbroek 		 *
264*b636d99dSDavid van Moolenbroek 		 * Skip DSAP, LSAP, and control field.
265*b636d99dSDavid van Moolenbroek 		 */
266*b636d99dSDavid van Moolenbroek                 if (ndo->ndo_eflag)
267*b636d99dSDavid van Moolenbroek                         ND_PRINT((ndo, "IPX 802.2: "));
268*b636d99dSDavid van Moolenbroek 
269*b636d99dSDavid van Moolenbroek 		ipx_print(ndo, p+3, length-3);
270*b636d99dSDavid van Moolenbroek 		return (1);
271*b636d99dSDavid van Moolenbroek 	}
272*b636d99dSDavid van Moolenbroek 
273*b636d99dSDavid van Moolenbroek #ifdef TCPDUMP_DO_SMB
274*b636d99dSDavid van Moolenbroek 	if (ssap == LLCSAP_NETBEUI && dsap == LLCSAP_NETBEUI
275*b636d99dSDavid van Moolenbroek 	    && (!(control & LLC_S_FMT) || control == LLC_U_FMT)) {
276*b636d99dSDavid van Moolenbroek 		/*
277*b636d99dSDavid van Moolenbroek 		 * we don't actually have a full netbeui parser yet, but the
278*b636d99dSDavid van Moolenbroek 		 * smb parser can handle many smb-in-netbeui packets, which
279*b636d99dSDavid van Moolenbroek 		 * is very useful, so we call that
280*b636d99dSDavid van Moolenbroek 		 *
281*b636d99dSDavid van Moolenbroek 		 * We don't call it for S frames, however, just I frames
282*b636d99dSDavid van Moolenbroek 		 * (which are frames that don't have the low-order bit,
283*b636d99dSDavid van Moolenbroek 		 * LLC_S_FMT, set in the first byte of the control field)
284*b636d99dSDavid van Moolenbroek 		 * and UI frames (whose control field is just 3, LLC_U_FMT).
285*b636d99dSDavid van Moolenbroek 		 */
286*b636d99dSDavid van Moolenbroek 
287*b636d99dSDavid van Moolenbroek 		/*
288*b636d99dSDavid van Moolenbroek 		 * Skip the LLC header.
289*b636d99dSDavid van Moolenbroek 		 */
290*b636d99dSDavid van Moolenbroek 		if (is_u) {
291*b636d99dSDavid van Moolenbroek 			p += 3;
292*b636d99dSDavid van Moolenbroek 			length -= 3;
293*b636d99dSDavid van Moolenbroek 		} else {
294*b636d99dSDavid van Moolenbroek 			p += 4;
295*b636d99dSDavid van Moolenbroek 			length -= 4;
296*b636d99dSDavid van Moolenbroek 		}
297*b636d99dSDavid van Moolenbroek 		netbeui_print(ndo, control, p, length);
298*b636d99dSDavid van Moolenbroek 		return (1);
299*b636d99dSDavid van Moolenbroek 	}
300*b636d99dSDavid van Moolenbroek #endif
301*b636d99dSDavid van Moolenbroek 	if (ssap == LLCSAP_ISONS && dsap == LLCSAP_ISONS
302*b636d99dSDavid van Moolenbroek 	    && control == LLC_UI) {
303*b636d99dSDavid van Moolenbroek 		isoclns_print(ndo, p + 3, length - 3, caplen - 3);
304*b636d99dSDavid van Moolenbroek 		return (1);
305*b636d99dSDavid van Moolenbroek 	}
306*b636d99dSDavid van Moolenbroek 
307*b636d99dSDavid van Moolenbroek 	if (ssap == LLCSAP_SNAP && dsap == LLCSAP_SNAP
308*b636d99dSDavid van Moolenbroek 	    && control == LLC_UI) {
309*b636d99dSDavid van Moolenbroek 		/*
310*b636d99dSDavid van Moolenbroek 		 * XXX - what *is* the right bridge pad value here?
311*b636d99dSDavid van Moolenbroek 		 * Does anybody ever bridge one form of LAN traffic
312*b636d99dSDavid van Moolenbroek 		 * over a networking type that uses 802.2 LLC?
313*b636d99dSDavid van Moolenbroek 		 */
314*b636d99dSDavid van Moolenbroek 		ret = snap_print(ndo, p+3, length-3, caplen-3, 2);
315*b636d99dSDavid van Moolenbroek 		if (ret)
316*b636d99dSDavid van Moolenbroek 			return (ret);
317*b636d99dSDavid van Moolenbroek 	}
318*b636d99dSDavid van Moolenbroek 
319*b636d99dSDavid van Moolenbroek 	if (!ndo->ndo_eflag) {
320*b636d99dSDavid van Moolenbroek 		if (ssap == dsap) {
321*b636d99dSDavid van Moolenbroek 			if (esrc == NULL || edst == NULL)
322*b636d99dSDavid van Moolenbroek 				ND_PRINT((ndo, "%s ", tok2str(llc_values, "Unknown DSAP 0x%02x", dsap)));
323*b636d99dSDavid van Moolenbroek 			else
324*b636d99dSDavid van Moolenbroek 				ND_PRINT((ndo, "%s > %s %s ",
325*b636d99dSDavid van Moolenbroek 						etheraddr_string(ndo, esrc),
326*b636d99dSDavid van Moolenbroek 						etheraddr_string(ndo, edst),
327*b636d99dSDavid van Moolenbroek 						tok2str(llc_values, "Unknown DSAP 0x%02x", dsap)));
328*b636d99dSDavid van Moolenbroek 		} else {
329*b636d99dSDavid van Moolenbroek 			if (esrc == NULL || edst == NULL)
330*b636d99dSDavid van Moolenbroek 				ND_PRINT((ndo, "%s > %s ",
331*b636d99dSDavid van Moolenbroek                                         tok2str(llc_values, "Unknown SSAP 0x%02x", ssap),
332*b636d99dSDavid van Moolenbroek 					tok2str(llc_values, "Unknown DSAP 0x%02x", dsap)));
333*b636d99dSDavid van Moolenbroek 			else
334*b636d99dSDavid van Moolenbroek 				ND_PRINT((ndo, "%s %s > %s %s ",
335*b636d99dSDavid van Moolenbroek 					etheraddr_string(ndo, esrc),
336*b636d99dSDavid van Moolenbroek                                         tok2str(llc_values, "Unknown SSAP 0x%02x", ssap),
337*b636d99dSDavid van Moolenbroek 					etheraddr_string(ndo, edst),
338*b636d99dSDavid van Moolenbroek 					tok2str(llc_values, "Unknown DSAP 0x%02x", dsap)));
339*b636d99dSDavid van Moolenbroek 		}
340*b636d99dSDavid van Moolenbroek 	}
341*b636d99dSDavid van Moolenbroek 
342*b636d99dSDavid van Moolenbroek 	if (is_u) {
343*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "Unnumbered, %s, Flags [%s], length %u",
344*b636d99dSDavid van Moolenbroek                        tok2str(llc_cmd_values, "%02x", LLC_U_CMD(control)),
345*b636d99dSDavid van Moolenbroek                        tok2str(llc_flag_values,"?",(ssap_field & LLC_GSAP) | (control & LLC_U_POLL)),
346*b636d99dSDavid van Moolenbroek                        length));
347*b636d99dSDavid van Moolenbroek 
348*b636d99dSDavid van Moolenbroek 		p += 3;
349*b636d99dSDavid van Moolenbroek 
350*b636d99dSDavid van Moolenbroek 		if ((control & ~LLC_U_POLL) == LLC_XID) {
351*b636d99dSDavid van Moolenbroek 			if (*p == LLC_XID_FI) {
352*b636d99dSDavid van Moolenbroek 				ND_PRINT((ndo, ": %02x %02x", p[1], p[2]));
353*b636d99dSDavid van Moolenbroek 			}
354*b636d99dSDavid van Moolenbroek 		}
355*b636d99dSDavid van Moolenbroek 	} else {
356*b636d99dSDavid van Moolenbroek 		if ((control & LLC_S_FMT) == LLC_S_FMT) {
357*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, "Supervisory, %s, rcv seq %u, Flags [%s], length %u",
358*b636d99dSDavid van Moolenbroek 				tok2str(llc_supervisory_values,"?",LLC_S_CMD(control)),
359*b636d99dSDavid van Moolenbroek 				LLC_IS_NR(control),
360*b636d99dSDavid van Moolenbroek 				tok2str(llc_flag_values,"?",(ssap_field & LLC_GSAP) | (control & LLC_IS_POLL)),
361*b636d99dSDavid van Moolenbroek                                 length));
362*b636d99dSDavid van Moolenbroek 		} else {
363*b636d99dSDavid van Moolenbroek 			ND_PRINT((ndo, "Information, send seq %u, rcv seq %u, Flags [%s], length %u",
364*b636d99dSDavid van Moolenbroek 				LLC_I_NS(control),
365*b636d99dSDavid van Moolenbroek 				LLC_IS_NR(control),
366*b636d99dSDavid van Moolenbroek 				tok2str(llc_flag_values,"?",(ssap_field & LLC_GSAP) | (control & LLC_IS_POLL)),
367*b636d99dSDavid van Moolenbroek                                 length));
368*b636d99dSDavid van Moolenbroek 		}
369*b636d99dSDavid van Moolenbroek 	}
370*b636d99dSDavid van Moolenbroek 	return(1);
371*b636d99dSDavid van Moolenbroek }
372*b636d99dSDavid van Moolenbroek 
373*b636d99dSDavid van Moolenbroek int
snap_print(netdissect_options * ndo,const u_char * p,u_int length,u_int caplen,u_int bridge_pad)374*b636d99dSDavid van Moolenbroek snap_print(netdissect_options *ndo, const u_char *p, u_int length, u_int caplen, u_int bridge_pad)
375*b636d99dSDavid van Moolenbroek {
376*b636d99dSDavid van Moolenbroek 	uint32_t orgcode;
377*b636d99dSDavid van Moolenbroek 	register u_short et;
378*b636d99dSDavid van Moolenbroek 	register int ret;
379*b636d99dSDavid van Moolenbroek 
380*b636d99dSDavid van Moolenbroek 	ND_TCHECK2(*p, 5);
381*b636d99dSDavid van Moolenbroek 	if (caplen < 5 || length < 5)
382*b636d99dSDavid van Moolenbroek 		goto trunc;
383*b636d99dSDavid van Moolenbroek 	orgcode = EXTRACT_24BITS(p);
384*b636d99dSDavid van Moolenbroek 	et = EXTRACT_16BITS(p + 3);
385*b636d99dSDavid van Moolenbroek 
386*b636d99dSDavid van Moolenbroek 	if (ndo->ndo_eflag) {
387*b636d99dSDavid van Moolenbroek 		const struct tok *tok = null_values;
388*b636d99dSDavid van Moolenbroek 		const struct oui_tok *otp;
389*b636d99dSDavid van Moolenbroek 
390*b636d99dSDavid van Moolenbroek 		for (otp = &oui_to_tok[0]; otp->tok != NULL; otp++) {
391*b636d99dSDavid van Moolenbroek 			if (otp->oui == orgcode) {
392*b636d99dSDavid van Moolenbroek 				tok = otp->tok;
393*b636d99dSDavid van Moolenbroek 				break;
394*b636d99dSDavid van Moolenbroek 			}
395*b636d99dSDavid van Moolenbroek 		}
396*b636d99dSDavid van Moolenbroek 		ND_PRINT((ndo, "oui %s (0x%06x), %s %s (0x%04x): ",
397*b636d99dSDavid van Moolenbroek 		     tok2str(oui_values, "Unknown", orgcode),
398*b636d99dSDavid van Moolenbroek 		     orgcode,
399*b636d99dSDavid van Moolenbroek 		     (orgcode == 0x000000 ? "ethertype" : "pid"),
400*b636d99dSDavid van Moolenbroek 		     tok2str(tok, "Unknown", et),
401*b636d99dSDavid van Moolenbroek 		     et));
402*b636d99dSDavid van Moolenbroek 	}
403*b636d99dSDavid van Moolenbroek 	p += 5;
404*b636d99dSDavid van Moolenbroek 	length -= 5;
405*b636d99dSDavid van Moolenbroek 	caplen -= 5;
406*b636d99dSDavid van Moolenbroek 
407*b636d99dSDavid van Moolenbroek 	switch (orgcode) {
408*b636d99dSDavid van Moolenbroek 	case OUI_ENCAP_ETHER:
409*b636d99dSDavid van Moolenbroek 	case OUI_CISCO_90:
410*b636d99dSDavid van Moolenbroek 		/*
411*b636d99dSDavid van Moolenbroek 		 * This is an encapsulated Ethernet packet,
412*b636d99dSDavid van Moolenbroek 		 * or a packet bridged by some piece of
413*b636d99dSDavid van Moolenbroek 		 * Cisco hardware; the protocol ID is
414*b636d99dSDavid van Moolenbroek 		 * an Ethernet protocol type.
415*b636d99dSDavid van Moolenbroek 		 */
416*b636d99dSDavid van Moolenbroek 		ret = ethertype_print(ndo, et, p, length, caplen);
417*b636d99dSDavid van Moolenbroek 		if (ret)
418*b636d99dSDavid van Moolenbroek 			return (ret);
419*b636d99dSDavid van Moolenbroek 		break;
420*b636d99dSDavid van Moolenbroek 
421*b636d99dSDavid van Moolenbroek 	case OUI_APPLETALK:
422*b636d99dSDavid van Moolenbroek 		if (et == ETHERTYPE_ATALK) {
423*b636d99dSDavid van Moolenbroek 			/*
424*b636d99dSDavid van Moolenbroek 			 * No, I have no idea why Apple used one
425*b636d99dSDavid van Moolenbroek 			 * of their own OUIs, rather than
426*b636d99dSDavid van Moolenbroek 			 * 0x000000, and an Ethernet packet
427*b636d99dSDavid van Moolenbroek 			 * type, for Appletalk data packets,
428*b636d99dSDavid van Moolenbroek 			 * but used 0x000000 and an Ethernet
429*b636d99dSDavid van Moolenbroek 			 * packet type for AARP packets.
430*b636d99dSDavid van Moolenbroek 			 */
431*b636d99dSDavid van Moolenbroek 			ret = ethertype_print(ndo, et, p, length, caplen);
432*b636d99dSDavid van Moolenbroek 			if (ret)
433*b636d99dSDavid van Moolenbroek 				return (ret);
434*b636d99dSDavid van Moolenbroek 		}
435*b636d99dSDavid van Moolenbroek 		break;
436*b636d99dSDavid van Moolenbroek 
437*b636d99dSDavid van Moolenbroek 	case OUI_CISCO:
438*b636d99dSDavid van Moolenbroek                 switch (et) {
439*b636d99dSDavid van Moolenbroek                 case PID_CISCO_CDP:
440*b636d99dSDavid van Moolenbroek                         cdp_print(ndo, p, length, caplen);
441*b636d99dSDavid van Moolenbroek                         return (1);
442*b636d99dSDavid van Moolenbroek                 case PID_CISCO_DTP:
443*b636d99dSDavid van Moolenbroek                         dtp_print(ndo, p, length);
444*b636d99dSDavid van Moolenbroek                         return (1);
445*b636d99dSDavid van Moolenbroek                 case PID_CISCO_UDLD:
446*b636d99dSDavid van Moolenbroek                         udld_print(ndo, p, length);
447*b636d99dSDavid van Moolenbroek                         return (1);
448*b636d99dSDavid van Moolenbroek                 case PID_CISCO_VTP:
449*b636d99dSDavid van Moolenbroek                         vtp_print(ndo, p, length);
450*b636d99dSDavid van Moolenbroek                         return (1);
451*b636d99dSDavid van Moolenbroek                 case PID_CISCO_PVST:
452*b636d99dSDavid van Moolenbroek                 case PID_CISCO_VLANBRIDGE:
453*b636d99dSDavid van Moolenbroek                         stp_print(ndo, p, length);
454*b636d99dSDavid van Moolenbroek                         return (1);
455*b636d99dSDavid van Moolenbroek                 default:
456*b636d99dSDavid van Moolenbroek                         break;
457*b636d99dSDavid van Moolenbroek                 }
458*b636d99dSDavid van Moolenbroek 		break;
459*b636d99dSDavid van Moolenbroek 
460*b636d99dSDavid van Moolenbroek 	case OUI_RFC2684:
461*b636d99dSDavid van Moolenbroek 		switch (et) {
462*b636d99dSDavid van Moolenbroek 
463*b636d99dSDavid van Moolenbroek 		case PID_RFC2684_ETH_FCS:
464*b636d99dSDavid van Moolenbroek 		case PID_RFC2684_ETH_NOFCS:
465*b636d99dSDavid van Moolenbroek 			/*
466*b636d99dSDavid van Moolenbroek 			 * XXX - remove the last two bytes for
467*b636d99dSDavid van Moolenbroek 			 * PID_RFC2684_ETH_FCS?
468*b636d99dSDavid van Moolenbroek 			 */
469*b636d99dSDavid van Moolenbroek 			/*
470*b636d99dSDavid van Moolenbroek 			 * Skip the padding.
471*b636d99dSDavid van Moolenbroek 			 */
472*b636d99dSDavid van Moolenbroek 			ND_TCHECK2(*p, bridge_pad);
473*b636d99dSDavid van Moolenbroek 			caplen -= bridge_pad;
474*b636d99dSDavid van Moolenbroek 			length -= bridge_pad;
475*b636d99dSDavid van Moolenbroek 			p += bridge_pad;
476*b636d99dSDavid van Moolenbroek 
477*b636d99dSDavid van Moolenbroek 			/*
478*b636d99dSDavid van Moolenbroek 			 * What remains is an Ethernet packet.
479*b636d99dSDavid van Moolenbroek 			 */
480*b636d99dSDavid van Moolenbroek 			ether_print(ndo, p, length, caplen, NULL, NULL);
481*b636d99dSDavid van Moolenbroek 			return (1);
482*b636d99dSDavid van Moolenbroek 
483*b636d99dSDavid van Moolenbroek 		case PID_RFC2684_802_5_FCS:
484*b636d99dSDavid van Moolenbroek 		case PID_RFC2684_802_5_NOFCS:
485*b636d99dSDavid van Moolenbroek 			/*
486*b636d99dSDavid van Moolenbroek 			 * XXX - remove the last two bytes for
487*b636d99dSDavid van Moolenbroek 			 * PID_RFC2684_ETH_FCS?
488*b636d99dSDavid van Moolenbroek 			 */
489*b636d99dSDavid van Moolenbroek 			/*
490*b636d99dSDavid van Moolenbroek 			 * Skip the padding, but not the Access
491*b636d99dSDavid van Moolenbroek 			 * Control field.
492*b636d99dSDavid van Moolenbroek 			 */
493*b636d99dSDavid van Moolenbroek 			ND_TCHECK2(*p, bridge_pad);
494*b636d99dSDavid van Moolenbroek 			caplen -= bridge_pad;
495*b636d99dSDavid van Moolenbroek 			length -= bridge_pad;
496*b636d99dSDavid van Moolenbroek 			p += bridge_pad;
497*b636d99dSDavid van Moolenbroek 
498*b636d99dSDavid van Moolenbroek 			/*
499*b636d99dSDavid van Moolenbroek 			 * What remains is an 802.5 Token Ring
500*b636d99dSDavid van Moolenbroek 			 * packet.
501*b636d99dSDavid van Moolenbroek 			 */
502*b636d99dSDavid van Moolenbroek 			token_print(ndo, p, length, caplen);
503*b636d99dSDavid van Moolenbroek 			return (1);
504*b636d99dSDavid van Moolenbroek 
505*b636d99dSDavid van Moolenbroek 		case PID_RFC2684_FDDI_FCS:
506*b636d99dSDavid van Moolenbroek 		case PID_RFC2684_FDDI_NOFCS:
507*b636d99dSDavid van Moolenbroek 			/*
508*b636d99dSDavid van Moolenbroek 			 * XXX - remove the last two bytes for
509*b636d99dSDavid van Moolenbroek 			 * PID_RFC2684_ETH_FCS?
510*b636d99dSDavid van Moolenbroek 			 */
511*b636d99dSDavid van Moolenbroek 			/*
512*b636d99dSDavid van Moolenbroek 			 * Skip the padding.
513*b636d99dSDavid van Moolenbroek 			 */
514*b636d99dSDavid van Moolenbroek 			ND_TCHECK2(*p, bridge_pad + 1);
515*b636d99dSDavid van Moolenbroek 			caplen -= bridge_pad + 1;
516*b636d99dSDavid van Moolenbroek 			length -= bridge_pad + 1;
517*b636d99dSDavid van Moolenbroek 			p += bridge_pad + 1;
518*b636d99dSDavid van Moolenbroek 
519*b636d99dSDavid van Moolenbroek 			/*
520*b636d99dSDavid van Moolenbroek 			 * What remains is an FDDI packet.
521*b636d99dSDavid van Moolenbroek 			 */
522*b636d99dSDavid van Moolenbroek 			fddi_print(ndo, p, length, caplen);
523*b636d99dSDavid van Moolenbroek 			return (1);
524*b636d99dSDavid van Moolenbroek 
525*b636d99dSDavid van Moolenbroek 		case PID_RFC2684_BPDU:
526*b636d99dSDavid van Moolenbroek 			stp_print(ndo, p, length);
527*b636d99dSDavid van Moolenbroek 			return (1);
528*b636d99dSDavid van Moolenbroek 		}
529*b636d99dSDavid van Moolenbroek 	}
530*b636d99dSDavid van Moolenbroek 	return (0);
531*b636d99dSDavid van Moolenbroek 
532*b636d99dSDavid van Moolenbroek trunc:
533*b636d99dSDavid van Moolenbroek 	ND_PRINT((ndo, "[|snap]"));
534*b636d99dSDavid van Moolenbroek 	return (1);
535*b636d99dSDavid van Moolenbroek }
536*b636d99dSDavid van Moolenbroek 
537*b636d99dSDavid van Moolenbroek 
538*b636d99dSDavid van Moolenbroek /*
539*b636d99dSDavid van Moolenbroek  * Local Variables:
540*b636d99dSDavid van Moolenbroek  * c-style: whitesmith
541*b636d99dSDavid van Moolenbroek  * c-basic-offset: 8
542*b636d99dSDavid van Moolenbroek  * End:
543*b636d99dSDavid van Moolenbroek  */
544