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