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