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