diff options
Diffstat (limited to 'contrib/tcpdump/print-llc.c')
-rw-r--r-- | contrib/tcpdump/print-llc.c | 90 |
1 files changed, 73 insertions, 17 deletions
diff --git a/contrib/tcpdump/print-llc.c b/contrib/tcpdump/print-llc.c index 19f9f86..988fdfe 100644 --- a/contrib/tcpdump/print-llc.c +++ b/contrib/tcpdump/print-llc.c @@ -24,7 +24,7 @@ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/tcpdump/print-llc.c,v 1.27 1999/12/22 06:27:21 itojun Exp $"; + "@(#) $Header: /tcpdump/master/tcpdump/print-llc.c,v 1.32 2000/12/18 07:55:36 guy Exp $"; #endif #ifdef HAVE_CONFIG_H @@ -64,10 +64,11 @@ static struct tok cmd2str[] = { */ int llc_print(const u_char *p, u_int length, u_int caplen, - const u_char *esrc, const u_char *edst) + const u_char *esrc, const u_char *edst, u_short *extracted_ethertype) { struct llc llc; register u_short et; + u_int16_t control; register int ret; if (caplen < 3) { @@ -83,13 +84,61 @@ llc_print(const u_char *p, u_int length, u_int caplen, ipx_print(p, length); return (1); } - if (llc.ssap == 0xf0 && llc.dsap == 0xf0) { + + /* Cisco Discovery Protocol - SNAP & ether type 0x2000 */ + if(llc.ssap == LLCSAP_SNAP && llc.dsap == LLCSAP_SNAP && + llc.llcui == LLC_UI && + llc.ethertype[0] == 0x20 && llc.ethertype[1] == 0x00 ) { + cdp_print( p, length, caplen, esrc, edst); + return (1); + } + + if (llc.ssap == LLCSAP_8021D && llc.dsap == LLCSAP_8021D) { + stp_print(p, length); + return (1); + } + if (llc.ssap == 0xf0 && llc.dsap == 0xf0 + && (!(llc.llcu & LLC_S_FMT) || llc.llcu == LLC_U_FMT)) { /* * we don't actually have a full netbeui parser yet, but the * smb parser can handle many smb-in-netbeui packets, which * is very useful, so we call that + * + * We don't call it for S frames, however, just I frames + * (which are frames that don't have the low-order bit, + * LLC_S_FMT, set in the first byte of the control field) + * and UI frames (whose control field is just 3, LLC_U_FMT). + */ + + /* + * Skip the DSAP and LSAP. + */ + p += 2; + length -= 2; + caplen -= 2; + + /* + * OK, what type of LLC frame is this? The length + * of the control field depends on that - I frames + * have a two-byte control field, and U frames have + * a one-byte control field. */ - netbeui_print(p + 2, p + min(caplen, length)); + if (llc.llcu == LLC_U_FMT) { + control = llc.llcu; + p += 1; + length -= 1; + caplen -= 1; + } else { + /* + * The control field in I and S frames is + * little-endian. + */ + control = EXTRACT_LE_16BITS(&llc.llcu); + p += 2; + length -= 2; + caplen -= 2; + } + netbeui_print(control, p, p + min(caplen, length)); return (1); } if (llc.ssap == LLCSAP_ISONS && llc.dsap == LLCSAP_ISONS @@ -114,7 +163,8 @@ llc_print(const u_char *p, u_int length, u_int caplen, /* This is an encapsulated Ethernet packet */ et = EXTRACT_16BITS(&llc.ethertype[0]); - ret = ether_encap_print(et, p, length, caplen); + ret = ether_encap_print(et, p, length, caplen, + extracted_ethertype); if (ret) return (ret); } @@ -141,9 +191,12 @@ llc_print(const u_char *p, u_int length, u_int caplen, } if ((llc.llcu & LLC_U_FMT) == LLC_U_FMT) { + u_int16_t cmd; const char *m; char f; - m = tok2str(cmd2str, "%02x", LLC_U_CMD(llc.llcu)); + + cmd = LLC_U_CMD(llc.llcu); + m = tok2str(cmd2str, "%02x", cmd); switch ((llc.ssap & LLC_GSAP) | (llc.llcu & LLC_U_POLL)) { case 0: f = 'C'; break; case LLC_GSAP: f = 'R'; break; @@ -167,35 +220,38 @@ llc_print(const u_char *p, u_int length, u_int caplen, } } - if (!strcmp(m,"ui") && f=='C') { + if (cmd == LLC_UI && f == 'C') { /* * we don't have a proper ipx decoder yet, but there * is a partial one in the smb code */ ipx_netbios_print(p,p+min(caplen,length)); } - } else { char f; - llc.llcis = ntohs(llc.llcis); - switch ((llc.ssap & LLC_GSAP) | (llc.llcu & LLC_U_POLL)) { + + /* + * The control field in I and S frames is little-endian. + */ + control = EXTRACT_LE_16BITS(&llc.llcu); + switch ((llc.ssap & LLC_GSAP) | (control & LLC_IS_POLL)) { case 0: f = 'C'; break; case LLC_GSAP: f = 'R'; break; - case LLC_U_POLL: f = 'P'; break; - case LLC_GSAP|LLC_U_POLL: f = 'F'; break; + case LLC_IS_POLL: f = 'P'; break; + case LLC_GSAP|LLC_IS_POLL: f = 'F'; break; default: f = '?'; break; } - if ((llc.llcu & LLC_S_FMT) == LLC_S_FMT) { + if ((control & LLC_S_FMT) == LLC_S_FMT) { static char *llc_s[] = { "rr", "rej", "rnr", "03" }; (void)printf("%s (r=%d,%c)", - llc_s[LLC_S_CMD(llc.llcis)], - LLC_IS_NR(llc.llcis), + llc_s[LLC_S_CMD(control)], + LLC_IS_NR(control), f); } else { (void)printf("I (s=%d,r=%d,%c)", - LLC_I_NS(llc.llcis), - LLC_IS_NR(llc.llcis), + LLC_I_NS(control), + LLC_IS_NR(control), f); } p += 4; |