PageRenderTime 51ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/contrib/tcpdump/print-llc.c

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