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