print-llc.c revision 127675
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: head/contrib/tcpdump/print-llc.c 127675 2004-03-31 14:57:24Z bms $
2517680Spst */
2617680Spst
2717680Spst#ifndef lint
28127675Sbmsstatic const char rcsid[] _U_ =
29127675Sbms    "@(#) $Header: /tcpdump/master/tcpdump/print-llc.c,v 1.53.2.3 2003/12/29 22:33:18 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"
4717680Spst
48127675Sbmsstatic struct tok llc_values[] = {
49127675Sbms        { LLCSAP_NULL,     "Null" },
50127675Sbms        { LLCSAP_GLOBAL,   "Global" },
51127675Sbms        { LLCSAP_8021B_I,  "802.1B I" },
52127675Sbms        { LLCSAP_8021B_G,  "802.1B G" },
53127675Sbms        { LLCSAP_IP,       "IP" },
54127675Sbms        { LLCSAP_PROWAYNM, "ProWay NM" },
55127675Sbms        { LLCSAP_8021D,    "STP" },
56127675Sbms        { LLCSAP_RS511,    "RS511" },
57127675Sbms        { LLCSAP_ISO8208,  "ISO8208" },
58127675Sbms        { LLCSAP_PROWAY,   "ProWay" },
59127675Sbms        { LLCSAP_SNAP,     "SNAP" },
60127675Sbms        { LLCSAP_IPX,      "IPX" },
61127675Sbms        { LLCSAP_NETBEUI,  "NetBeui" },
62127675Sbms        { LLCSAP_ISONS,    "OSI" },
63127675Sbms};
64127675Sbms
6517680Spststatic struct tok cmd2str[] = {
6617680Spst	{ LLC_UI,	"ui" },
6717680Spst	{ LLC_TEST,	"test" },
6817680Spst	{ LLC_XID,	"xid" },
6917680Spst	{ LLC_UA,	"ua" },
7017680Spst	{ LLC_DISC,	"disc" },
7117680Spst	{ LLC_DM,	"dm" },
7217680Spst	{ LLC_SABME,	"sabme" },
7317680Spst	{ LLC_FRMR,	"frmr" },
7417680Spst	{ 0,		NULL }
7517680Spst};
7617680Spst
7717680Spst/*
7817680Spst * Returns non-zero IFF it succeeds in printing the header
7917680Spst */
8017680Spstint
8117680Spstllc_print(const u_char *p, u_int length, u_int caplen,
8275118Sfenner	  const u_char *esrc, const u_char *edst, u_short *extracted_ethertype)
8317680Spst{
8417680Spst	struct llc llc;
8517680Spst	register u_short et;
8675118Sfenner	u_int16_t control;
8717680Spst	register int ret;
8817680Spst
8917680Spst	if (caplen < 3) {
9017680Spst		(void)printf("[|llc]");
9117680Spst		default_print((u_char *)p, caplen);
9217680Spst		return(0);
9317680Spst	}
9417680Spst
9517680Spst	/* Watch out for possible alignment problems */
9617680Spst	memcpy((char *)&llc, (char *)p, min(caplen, sizeof(llc)));
9717680Spst
98127675Sbms	if (eflag)
99127675Sbms	  printf("LLC, dsap %s (0x%02x), ssap %s (0x%02x), cmd 0x%02x, ",
100127675Sbms                 tok2str(llc_values,"Unknown",llc.dsap),
101127675Sbms		 llc.dsap,
102127675Sbms                 tok2str(llc_values,"Unknown",llc.ssap),
103127675Sbms		 llc.ssap,
104127675Sbms		 llc.llcu);
105127675Sbms
10617680Spst	if (llc.ssap == LLCSAP_GLOBAL && llc.dsap == LLCSAP_GLOBAL) {
10798527Sfenner		/*
10898527Sfenner		 * This is an Ethernet_802.3 IPX frame; it has an
10998527Sfenner		 * 802.3 header (i.e., an Ethernet header where the
11098527Sfenner		 * type/length field is <= ETHERMTU, i.e. it's a length
11198527Sfenner		 * field, not a type field), but has no 802.2 header -
11298527Sfenner		 * the IPX packet starts right after the Ethernet header,
11398527Sfenner		 * with a signature of two bytes of 0xFF (which is
11498527Sfenner		 * LLCSAP_GLOBAL).
11598527Sfenner		 *
11698527Sfenner		 * (It might also have been an Ethernet_802.3 IPX at
11798527Sfenner		 * one time, but got bridged onto another network,
11898527Sfenner		 * such as an 802.11 network; this has appeared in at
11998527Sfenner		 * least one capture file.)
12098527Sfenner		 */
121127675Sbms		printf("(NOV-802.3) ");
12217680Spst		ipx_print(p, length);
12317680Spst		return (1);
12417680Spst	}
12575118Sfenner
12675118Sfenner	if (llc.ssap == LLCSAP_8021D && llc.dsap == LLCSAP_8021D) {
12775118Sfenner		stp_print(p, length);
12875118Sfenner		return (1);
12975118Sfenner	}
13098527Sfenner
131127675Sbms	if (llc.ssap == LLCSAP_IP && llc.dsap == LLCSAP_IP) {
132127675Sbms		ip_print(p+4, length-4);
133127675Sbms		return (1);
134127675Sbms	}
135127675Sbms
13698527Sfenner	if (llc.ssap == LLCSAP_IPX && llc.dsap == LLCSAP_IPX &&
13798527Sfenner	    llc.llcui == LLC_UI) {
13898527Sfenner		/*
13998527Sfenner		 * This is an Ethernet_802.2 IPX frame, with an 802.3
14098527Sfenner		 * header and an 802.2 LLC header with the source and
14198527Sfenner		 * destination SAPs being the IPX SAP.
14298527Sfenner		 *
14398527Sfenner		 * Skip DSAP, LSAP, and control field.
14498527Sfenner		 */
145127675Sbms		printf("(NOV-802.2) ");
14698527Sfenner		p += 3;
14798527Sfenner		length -= 3;
14898527Sfenner		caplen -= 3;
14998527Sfenner		ipx_print(p, length);
15098527Sfenner		return (1);
15198527Sfenner	}
15298527Sfenner
15398527Sfenner#ifdef TCPDUMP_DO_SMB
15498527Sfenner	if (llc.ssap == LLCSAP_NETBEUI && llc.dsap == LLCSAP_NETBEUI
15575118Sfenner	    && (!(llc.llcu & LLC_S_FMT) || llc.llcu == LLC_U_FMT)) {
15656896Sfenner		/*
15756896Sfenner		 * we don't actually have a full netbeui parser yet, but the
15856896Sfenner		 * smb parser can handle many smb-in-netbeui packets, which
15956896Sfenner		 * is very useful, so we call that
16075118Sfenner		 *
16175118Sfenner		 * We don't call it for S frames, however, just I frames
16275118Sfenner		 * (which are frames that don't have the low-order bit,
16375118Sfenner		 * LLC_S_FMT, set in the first byte of the control field)
16475118Sfenner		 * and UI frames (whose control field is just 3, LLC_U_FMT).
16556896Sfenner		 */
16675118Sfenner
16775118Sfenner		/*
16875118Sfenner		 * Skip the DSAP and LSAP.
16975118Sfenner		 */
17075118Sfenner		p += 2;
17175118Sfenner		length -= 2;
17275118Sfenner		caplen -= 2;
17375118Sfenner
17475118Sfenner		/*
17575118Sfenner		 * OK, what type of LLC frame is this?  The length
17675118Sfenner		 * of the control field depends on that - I frames
17775118Sfenner		 * have a two-byte control field, and U frames have
17875118Sfenner		 * a one-byte control field.
17975118Sfenner		 */
18075118Sfenner		if (llc.llcu == LLC_U_FMT) {
18175118Sfenner			control = llc.llcu;
18275118Sfenner			p += 1;
18375118Sfenner			length -= 1;
18475118Sfenner			caplen -= 1;
18575118Sfenner		} else {
18675118Sfenner			/*
18775118Sfenner			 * The control field in I and S frames is
18875118Sfenner			 * little-endian.
18975118Sfenner			 */
19075118Sfenner			control = EXTRACT_LE_16BITS(&llc.llcu);
19175118Sfenner			p += 2;
19275118Sfenner			length -= 2;
19375118Sfenner			caplen -= 2;
19475118Sfenner		}
19598527Sfenner		netbeui_print(control, p, length);
19656896Sfenner		return (1);
19756896Sfenner	}
19898527Sfenner#endif
19917680Spst	if (llc.ssap == LLCSAP_ISONS && llc.dsap == LLCSAP_ISONS
20017680Spst	    && llc.llcui == LLC_UI) {
201127675Sbms		isoclns_print(p + 3, length - 3, caplen - 3);
20217680Spst		return (1);
20317680Spst	}
20417680Spst
20517680Spst	if (llc.ssap == LLCSAP_SNAP && llc.dsap == LLCSAP_SNAP
20617680Spst	    && llc.llcui == LLC_UI) {
20798527Sfenner		u_int32_t orgcode;
20898527Sfenner
20917680Spst		if (caplen < sizeof(llc)) {
21056896Sfenner			(void)printf("[|llc-snap]");
21156896Sfenner			default_print((u_char *)p, caplen);
21256896Sfenner			return (0);
21317680Spst		}
21417680Spst
21517680Spst		caplen -= sizeof(llc);
21617680Spst		length -= sizeof(llc);
21717680Spst		p += sizeof(llc);
21817680Spst
21998527Sfenner		orgcode = EXTRACT_24BITS(&llc.llc_orgcode[0]);
22098527Sfenner		et = EXTRACT_16BITS(&llc.llc_ethertype[0]);
221127675Sbms		/*
222127675Sbms		 * XXX - what *is* the right bridge pad value here?
223127675Sbms		 * Does anybody ever bridge one form of LAN traffic
224127675Sbms		 * over a networking type that uses 802.2 LLC?
225127675Sbms		 */
226127675Sbms		ret = snap_print(p, length, caplen, extracted_ethertype,
227127675Sbms		    orgcode, et, 2);
228127675Sbms		if (ret)
229127675Sbms			return (ret);
23017680Spst	}
23117680Spst
23217680Spst	if ((llc.ssap & ~LLC_GSAP) == llc.dsap) {
23398527Sfenner		if (eflag || esrc == NULL || edst == NULL)
23417680Spst			(void)printf("%s ", llcsap_string(llc.dsap));
23517680Spst		else
23617680Spst			(void)printf("%s > %s %s ",
23717680Spst					etheraddr_string(esrc),
23817680Spst					etheraddr_string(edst),
23917680Spst					llcsap_string(llc.dsap));
24017680Spst	} else {
24198527Sfenner		if (eflag || esrc == NULL || edst == NULL)
24217680Spst			(void)printf("%s > %s ",
24317680Spst				llcsap_string(llc.ssap & ~LLC_GSAP),
24417680Spst				llcsap_string(llc.dsap));
24517680Spst		else
24617680Spst			(void)printf("%s %s > %s %s ",
24717680Spst				etheraddr_string(esrc),
24817680Spst				llcsap_string(llc.ssap & ~LLC_GSAP),
24917680Spst				etheraddr_string(edst),
25017680Spst				llcsap_string(llc.dsap));
25117680Spst	}
25217680Spst
25317680Spst	if ((llc.llcu & LLC_U_FMT) == LLC_U_FMT) {
25475118Sfenner		u_int16_t cmd;
25517680Spst		const char *m;
25617680Spst		char f;
25775118Sfenner
25875118Sfenner		cmd = LLC_U_CMD(llc.llcu);
25975118Sfenner		m = tok2str(cmd2str, "%02x", cmd);
26017680Spst		switch ((llc.ssap & LLC_GSAP) | (llc.llcu & LLC_U_POLL)) {
26156896Sfenner			case 0:			f = 'C'; break;
26256896Sfenner			case LLC_GSAP:		f = 'R'; break;
26356896Sfenner			case LLC_U_POLL:	f = 'P'; break;
26456896Sfenner			case LLC_GSAP|LLC_U_POLL: f = 'F'; break;
26556896Sfenner			default:		f = '?'; break;
26617680Spst		}
26717680Spst
26817680Spst		printf("%s/%c", m, f);
26917680Spst
27017680Spst		p += 3;
27117680Spst		length -= 3;
27217680Spst		caplen -= 3;
27317680Spst
27417680Spst		if ((llc.llcu & ~LLC_U_POLL) == LLC_XID) {
27556896Sfenner			if (*p == LLC_XID_FI) {
27656896Sfenner				printf(": %02x %02x", p[1], p[2]);
27756896Sfenner				p += 3;
27856896Sfenner				length -= 3;
27956896Sfenner				caplen -= 3;
28056896Sfenner			}
28117680Spst		}
28217680Spst	} else {
28317680Spst		char f;
28475118Sfenner
28575118Sfenner		/*
28675118Sfenner		 * The control field in I and S frames is little-endian.
28775118Sfenner		 */
28875118Sfenner		control = EXTRACT_LE_16BITS(&llc.llcu);
28975118Sfenner		switch ((llc.ssap & LLC_GSAP) | (control & LLC_IS_POLL)) {
29056896Sfenner			case 0:			f = 'C'; break;
29156896Sfenner			case LLC_GSAP:		f = 'R'; break;
29275118Sfenner			case LLC_IS_POLL:	f = 'P'; break;
29375118Sfenner			case LLC_GSAP|LLC_IS_POLL: f = 'F'; break;
29456896Sfenner			default:		f = '?'; break;
29517680Spst		}
29617680Spst
29775118Sfenner		if ((control & LLC_S_FMT) == LLC_S_FMT) {
298127675Sbms			static const char *llc_s[] = { "rr", "rej", "rnr", "03" };
29917680Spst			(void)printf("%s (r=%d,%c)",
30075118Sfenner				llc_s[LLC_S_CMD(control)],
30175118Sfenner				LLC_IS_NR(control),
30217680Spst				f);
30317680Spst		} else {
30417680Spst			(void)printf("I (s=%d,r=%d,%c)",
30575118Sfenner				LLC_I_NS(control),
30675118Sfenner				LLC_IS_NR(control),
30717680Spst				f);
30817680Spst		}
30917680Spst		p += 4;
31017680Spst		length -= 4;
31117680Spst		caplen -= 4;
31217680Spst	}
31317680Spst	(void)printf(" len=%d", length);
31417680Spst	return(1);
31517680Spst}
316127675Sbms
317127675Sbmsint
318127675Sbmssnap_print(const u_char *p, u_int length, u_int caplen,
319127675Sbms    u_short *extracted_ethertype, u_int32_t orgcode, u_short et,
320127675Sbms    u_int bridge_pad)
321127675Sbms{
322127675Sbms	register int ret;
323127675Sbms
324127675Sbms	switch (orgcode) {
325127675Sbms	case OUI_ENCAP_ETHER:
326127675Sbms	case OUI_CISCO_90:
327127675Sbms		/*
328127675Sbms		 * This is an encapsulated Ethernet packet,
329127675Sbms		 * or a packet bridged by some piece of
330127675Sbms		 * Cisco hardware; the protocol ID is
331127675Sbms		 * an Ethernet protocol type.
332127675Sbms		 */
333127675Sbms		ret = ether_encap_print(et, p, length, caplen,
334127675Sbms		    extracted_ethertype);
335127675Sbms		if (ret)
336127675Sbms			return (ret);
337127675Sbms		break;
338127675Sbms
339127675Sbms	case OUI_APPLETALK:
340127675Sbms		if (et == ETHERTYPE_ATALK) {
341127675Sbms			/*
342127675Sbms			 * No, I have no idea why Apple used one
343127675Sbms			 * of their own OUIs, rather than
344127675Sbms			 * 0x000000, and an Ethernet packet
345127675Sbms			 * type, for Appletalk data packets,
346127675Sbms			 * but used 0x000000 and an Ethernet
347127675Sbms			 * packet type for AARP packets.
348127675Sbms			 */
349127675Sbms			ret = ether_encap_print(et, p, length, caplen,
350127675Sbms			    extracted_ethertype);
351127675Sbms			if (ret)
352127675Sbms				return (ret);
353127675Sbms		}
354127675Sbms		break;
355127675Sbms
356127675Sbms	case OUI_CISCO:
357127675Sbms		if (et == PID_CISCO_CDP) {
358127675Sbms			cdp_print(p, length, caplen);
359127675Sbms			return (1);
360127675Sbms		}
361127675Sbms		break;
362127675Sbms
363127675Sbms	case OUI_RFC2684:
364127675Sbms		switch (et) {
365127675Sbms
366127675Sbms		case PID_RFC2684_ETH_FCS:
367127675Sbms		case PID_RFC2684_ETH_NOFCS:
368127675Sbms			/*
369127675Sbms			 * XXX - remove the last two bytes for
370127675Sbms			 * PID_RFC2684_ETH_FCS?
371127675Sbms			 */
372127675Sbms			/*
373127675Sbms			 * Skip the padding.
374127675Sbms			 */
375127675Sbms			caplen -= bridge_pad;
376127675Sbms			length -= bridge_pad;
377127675Sbms			p += bridge_pad;
378127675Sbms
379127675Sbms			/*
380127675Sbms			 * What remains is an Ethernet packet.
381127675Sbms			 */
382127675Sbms			ether_print(p, length, caplen);
383127675Sbms			return (1);
384127675Sbms
385127675Sbms		case PID_RFC2684_802_5_FCS:
386127675Sbms		case PID_RFC2684_802_5_NOFCS:
387127675Sbms			/*
388127675Sbms			 * XXX - remove the last two bytes for
389127675Sbms			 * PID_RFC2684_ETH_FCS?
390127675Sbms			 */
391127675Sbms			/*
392127675Sbms			 * Skip the padding, but not the Access
393127675Sbms			 * Control field.
394127675Sbms			 */
395127675Sbms			caplen -= bridge_pad;
396127675Sbms			length -= bridge_pad;
397127675Sbms			p += bridge_pad;
398127675Sbms
399127675Sbms			/*
400127675Sbms			 * What remains is an 802.5 Token Ring
401127675Sbms			 * packet.
402127675Sbms			 */
403127675Sbms			token_print(p, length, caplen);
404127675Sbms			return (1);
405127675Sbms
406127675Sbms		case PID_RFC2684_FDDI_FCS:
407127675Sbms		case PID_RFC2684_FDDI_NOFCS:
408127675Sbms			/*
409127675Sbms			 * XXX - remove the last two bytes for
410127675Sbms			 * PID_RFC2684_ETH_FCS?
411127675Sbms			 */
412127675Sbms			/*
413127675Sbms			 * Skip the padding.
414127675Sbms			 */
415127675Sbms			caplen -= bridge_pad + 1;
416127675Sbms			length -= bridge_pad + 1;
417127675Sbms			p += bridge_pad + 1;
418127675Sbms
419127675Sbms			/*
420127675Sbms			 * What remains is an FDDI packet.
421127675Sbms			 */
422127675Sbms			fddi_print(p, length, caplen);
423127675Sbms			return (1);
424127675Sbms
425127675Sbms		case PID_RFC2684_BPDU:
426127675Sbms			stp_print(p, length);
427127675Sbms			return (1);
428127675Sbms		}
429127675Sbms	}
430127675Sbms	return (0);
431127675Sbms}
432