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