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