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