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